diff options
author | Marcel Ziswiler <marcel.ziswiler@toradex.com> | 2012-11-12 15:28:39 +0100 |
---|---|---|
committer | Marcel Ziswiler <marcel.ziswiler@toradex.com> | 2012-11-12 15:28:39 +0100 |
commit | f987e832a9e79d2ce8009a5ea9c7b677624b3b30 (patch) | |
tree | 0dd09a5e6b4c60ee0a9916907dfc2cda83f3e496 /arch/arm/mach-tegra | |
parent | f737b7f46a72c099cf8ac88baff02fbf61b1a47c (diff) | |
parent | fc993d9bc48f772133d8cd156c67c296477db070 (diff) |
Merge branch 'l4t/l4t-r16-r2' into colibri
Conflicts:
arch/arm/mach-tegra/tegra3_usb_phy.c
arch/arm/mach-tegra/usb_phy.c
drivers/usb/gadget/tegra_udc.c
drivers/usb/otg/Makefile
drivers/video/tegra/fb.c
sound/soc/tegra/tegra_pcm.c
Diffstat (limited to 'arch/arm/mach-tegra')
111 files changed, 7461 insertions, 1873 deletions
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index 00e4c30783ef..243c33665641 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -1,3 +1,17 @@ +# 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/>. + if ARCH_TEGRA comment "NVIDIA Tegra options" @@ -53,6 +67,7 @@ config ARCH_TEGRA_3x_SOC select CPA select ARCH_HAS_SUSPEND_PAGETABLE select NVMAP_CACHE_MAINT_BY_SET_WAYS + select PL310_ERRATA_727915 help Support for NVIDIA Tegra 3 family of SoCs, based upon the ARM CortexA9MP CPU and the ARM PL310 L2 cache controller @@ -76,6 +91,14 @@ config TEGRA_PCI help Adds PCIe Host controller driver for tegra based systems +config TEGRA_IRDA + bool "IRDA on UARTB Port of Verbier" + select IRDA_CPLD + depends on ARCH_TEGRA_3x_SOC && MACH_CARDHU + help + Adds support for Vishay IrDA transceiver at UARTB port + of Verbier Boards(E1186 and E1198) with no ULPI rework done. + comment "Tegra board type" config MACH_COLIBRI_T20 @@ -177,6 +200,12 @@ config MACH_P1852 help Support for NVIDIA P1852 development platform +config MACH_E1853 + bool "E1853 board" + depends on ARCH_TEGRA_3x_SOC + help + Support for NVIDIA E1853 development platform + config MACH_TEGRA_ENTERPRISE bool "Enterprise board" depends on ARCH_TEGRA_3x_SOC @@ -186,6 +215,12 @@ config MACH_TEGRA_ENTERPRISE help Support for NVIDIA Enterprise development platform +config MACH_TAI + bool "Tai board" + depends on MACH_TEGRA_ENTERPRISE + help + Support for NVIDIA Tai development platform + config MACH_KAI bool "Kai board" depends on ARCH_TEGRA_3x_SOC @@ -276,6 +311,13 @@ config TEGRA_P1852_TDM Enables TDM mode driver for P1852 SKUs. If this is not defined then I2S mode is selected by default. +config TEGRA_TDM + bool "Enable TDM mode for Automotive SKUs" + depends on MACH_E1853 + help + Enables TDM mode driver for Automotive 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 @@ -422,6 +464,16 @@ config TEGRA_EMC_TO_DDR_CLOCK default "2" if ARCH_TEGRA_2x_SOC default "1" +config TEGRA_SE_ON_CBUS + bool "To Drive SE clock from cbus" + default y + help + This option enables SE clock to be derived from cbus + +config TEGRA_CBUS_CLOCK_DIVIDER + int "CBUS clock divider" + default "2" + config TEGRA_CONVSERVATIVE_GOV_ON_EARLYSUPSEND bool "Use conservative cpu frequency governor when device enters early suspend" depends on HAS_EARLYSUSPEND && CPU_FREQ @@ -543,4 +595,20 @@ config TEGRA_SKIN_THROTTLE help Enable throttling to control the temperature of the skin/case of the device. + +config TEGRA_LP1_950 + bool "LP1 low core voltage" + default n + depends on ARCH_TEGRA_3x_SOC + help + Enable support for LP1 Core voltage to set to lowest endif + +config TEGRA_DC_USE_HW_BPP + bool "Default Bits Per Pixel value from tegra DC hardware" + depends on TEGRA_DC + default n + help + Programs platform data to inform DC driver to use current + hardware value for bits per pixel setting. Useful for + preserving and displaying framebuffer content from bootloader. diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile index c1a76685c31d..9a476876374a 100644 --- a/arch/arm/mach-tegra/Makefile +++ b/arch/arm/mach-tegra/Makefile @@ -19,6 +19,7 @@ obj-y += tegra2_clocks.o obj-y += timer-t2.o else obj-y += tegra3_clocks.o +obj-$(CONFIG_DEBUG_FS) += clocks_stats.o obj-y += timer-t3.o endif obj-y += pinmux.o @@ -38,7 +39,7 @@ AFLAGS_sleep.o :=-Wa,-march=armv7-a$(plus_sec) obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += sleep-t2.o obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += sleep-t3.o -obj-y += fuse.o +obj-y += tegra_fuse.o obj-y += kfuse.o obj-y += csi.o obj-$(CONFIG_TEGRA_SILICON_PLATFORM) += tegra_odm_fuses.o @@ -171,6 +172,7 @@ obj-${CONFIG_MACH_WHISTLER} += board-whistler-memory.o obj-${CONFIG_MACH_CARDHU} += board-cardhu.o obj-${CONFIG_MACH_CARDHU} += board-cardhu-kbc.o +obj-${CONFIG_MACH_CARDHU} += board-cardhu-irda.o obj-${CONFIG_MACH_CARDHU} += board-cardhu-panel.o obj-${CONFIG_MACH_CARDHU} += board-cardhu-pinmux.o obj-${CONFIG_MACH_CARDHU} += board-cardhu-power.o @@ -195,6 +197,11 @@ obj-${CONFIG_MACH_P1852} += board-p1852-panel.o obj-${CONFIG_MACH_P1852} += board-p1852-pinmux.o obj-${CONFIG_MACH_P1852} += board-p1852-sdhci.o +obj-${CONFIG_MACH_E1853} += board-e1853.o +obj-${CONFIG_MACH_E1853} += board-e1853-panel.o +obj-${CONFIG_MACH_E1853} += board-e1853-pinmux.o +obj-${CONFIG_MACH_E1853} += board-e1853-sdhci.o + obj-${CONFIG_MACH_TEGRA_ENTERPRISE} += board-enterprise.o obj-${CONFIG_MACH_TEGRA_ENTERPRISE} += board-enterprise-panel.o obj-${CONFIG_MACH_TEGRA_ENTERPRISE} += board-enterprise-pinmux.o diff --git a/arch/arm/mach-tegra/Makefile.boot b/arch/arm/mach-tegra/Makefile.boot index d8cb9173cdf7..6ca6212c711a 100644 --- a/arch/arm/mach-tegra/Makefile.boot +++ b/arch/arm/mach-tegra/Makefile.boot @@ -6,5 +6,9 @@ zreladdr-$(CONFIG_ARCH_TEGRA_3x_SOC) := 0x80008000 params_phys-$(CONFIG_ARCH_TEGRA_3x_SOC) := 0x80000100 initrd_phys-$(CONFIG_ARCH_TEGRA_3x_SOC) := 0x80800000 -dtb-$(CONFIG_MACH_HARMONY) += tegra-harmony.dtb -dtb-$(CONFIG_MACH_SEABOARD) += tegra-seaboard.dtb +dtb-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20-harmony.dtb +dtb-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20-seaboard.dtb +dtb-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20-ventana.dtb +dtb-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20-whistler.dtb +dtb-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra30-cardhu.dtb +dtb-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra30-enterprise.dtb diff --git a/arch/arm/mach-tegra/baseband-xmm-power.c b/arch/arm/mach-tegra/baseband-xmm-power.c index 36f5fc6611f9..59e0779047b9 100644 --- a/arch/arm/mach-tegra/baseband-xmm-power.c +++ b/arch/arm/mach-tegra/baseband-xmm-power.c @@ -1,7 +1,7 @@ /* * arch/arm/mach-tegra/baseband-xmm-power.c * - * Copyright (C) 2011 NVIDIA Corporation + * Copyright (c) 2012, NVIDIA CORPORATION. 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 @@ -51,8 +51,6 @@ EXPORT_SYMBOL(modem_flash); unsigned long modem_pm = 1; EXPORT_SYMBOL(modem_pm); -unsigned long enum_delay_ms = 1000; /* ignored if !modem_flash */ - module_param(modem_ver, ulong, 0644); MODULE_PARM_DESC(modem_ver, "baseband xmm power - modem software version"); @@ -62,50 +60,39 @@ MODULE_PARM_DESC(modem_flash, module_param(modem_pm, ulong, 0644); MODULE_PARM_DESC(modem_pm, "baseband xmm power - modem power management (1 = pm, 0 = no pm)"); -module_param(enum_delay_ms, ulong, 0644); -MODULE_PARM_DESC(enum_delay_ms, - "baseband xmm power - delay in ms between modem on and enumeration"); static struct usb_device_id xmm_pm_ids[] = { { USB_DEVICE(VENDOR_ID, PRODUCT_ID), .driver_info = 0 }, {} }; - +MODULE_DEVICE_TABLE(usb, xmm_pm_ids); static struct gpio tegra_baseband_gpios[] = { { -1, GPIOF_OUT_INIT_LOW, "BB_RSTn" }, { -1, GPIOF_OUT_INIT_LOW, "BB_ON" }, { -1, GPIOF_OUT_INIT_LOW, "IPC_BB_WAKE" }, { -1, GPIOF_IN, "IPC_AP_WAKE" }, - { -1, GPIOF_OUT_INIT_HIGH, "IPC_HSIC_ACTIVE" }, + { -1, GPIOF_OUT_INIT_LOW, "IPC_HSIC_ACTIVE" }, { -1, GPIOF_IN, "IPC_HSIC_SUS_REQ" }, }; -static enum { - IPC_AP_WAKE_UNINIT, - IPC_AP_WAKE_IRQ_READY, - IPC_AP_WAKE_INIT1, - IPC_AP_WAKE_INIT2, - IPC_AP_WAKE_L, - IPC_AP_WAKE_H, -} ipc_ap_wake_state; - static enum baseband_xmm_powerstate_t baseband_xmm_powerstate; +static enum ipc_ap_wake_state_t ipc_ap_wake_state; static struct workqueue_struct *workqueue; -static struct work_struct init1_work; static struct work_struct init2_work; -static struct work_struct L2_resume_work; +static struct work_struct l2_resume_work; static struct work_struct autopm_resume_work; static bool register_hsic_device; static struct wake_lock wakelock; static struct usb_device *usbdev; -static bool CP_initiated_L2toL0; +static bool cp_initiated_l2tol0; static bool modem_power_on; static int power_onoff; static int reenable_autosuspend; static bool wakeup_pending; static bool modem_sleep_flag; +static bool modem_acked_resume; static spinlock_t xmm_lock; static DEFINE_MUTEX(xmm_onoff_mutex); static bool system_suspending; @@ -178,6 +165,17 @@ static int tegra_baseband_rail_off(void) return 0; } +static inline enum baseband_xmm_powerstate_t baseband_xmm_get_power_status(void) +{ + enum baseband_xmm_powerstate_t status; + unsigned long flags; + + spin_lock_irqsave(&xmm_lock, flags); + status = baseband_xmm_powerstate; + spin_unlock_irqrestore(&xmm_lock, flags); + return status; +} + static int baseband_modem_power_on(struct baseband_power_platform_data *data) { /* set IPC_HSIC_ACTIVE active */ @@ -227,11 +225,24 @@ static int baseband_modem_power_on_async( return 0; } +static void xmm_power_reset_on(struct baseband_power_platform_data *pdata) +{ + /* reset / power on sequence */ + gpio_set_value(pdata->modem.xmm.bb_rst, 0); + msleep(40); + gpio_set_value(pdata->modem.xmm.bb_rst, 1); + usleep_range(1000, 1100); + gpio_set_value(pdata->modem.xmm.bb_on, 1); + udelay(70); + gpio_set_value(pdata->modem.xmm.bb_on, 0); +} + static int xmm_power_on(struct platform_device *device) { struct baseband_power_platform_data *pdata = device->dev.platform_data; struct xmm_power_data *data = &xmm_power_drv_data; + unsigned long flags; int ret; pr_debug("%s {\n", __func__); @@ -241,15 +252,15 @@ static int xmm_power_on(struct platform_device *device) pr_err("%s: !pdata\n", __func__); return -EINVAL; } - if (baseband_xmm_powerstate != BBXMM_PS_UNINIT) + if (baseband_xmm_get_power_status() != BBXMM_PS_UNINIT) return -EINVAL; tegra_baseband_rail_on(); /* reset the state machine */ - baseband_xmm_powerstate = BBXMM_PS_INIT; + baseband_xmm_set_power_status(BBXMM_PS_INIT); modem_sleep_flag = false; - ipc_ap_wake_state = IPC_AP_WAKE_INIT2; + modem_acked_resume = true; pr_debug("%s wake_st(%d) modem version %lu\n", __func__, ipc_ap_wake_state, modem_ver); @@ -257,6 +268,11 @@ static int xmm_power_on(struct platform_device *device) /* register usb host controller */ if (!modem_flash) { pr_debug("%s - %d\n", __func__, __LINE__); + + spin_lock_irqsave(&xmm_lock, flags); + ipc_ap_wake_state = IPC_AP_WAKE_INIT2; + spin_unlock_irqrestore(&xmm_lock, flags); + /* register usb host controller only once */ if (register_hsic_device) { pr_debug("%s: register usb host controller\n", @@ -277,7 +293,22 @@ static int xmm_power_on(struct platform_device *device) __func__); baseband_modem_power_on_async(pdata); } + } else { + /* reset flashed modem then it will respond with + * ap-wake rising followed by falling gpio + */ + + pr_debug("%s: reset flash modem\n", __func__); + + modem_power_on = false; + spin_lock_irqsave(&xmm_lock, flags); + ipc_ap_wake_state = IPC_AP_WAKE_IRQ_READY; + spin_unlock_irqrestore(&xmm_lock, flags); + gpio_set_value(pdata->modem.xmm.ipc_hsic_active, 0); + + xmm_power_reset_on(pdata); } + ret = enable_irq_wake(gpio_to_irq(pdata->modem.xmm.ipc_ap_wake)); if (ret < 0) pr_err("%s: enable_irq_wake error\n", __func__); @@ -291,14 +322,14 @@ static int xmm_power_off(struct platform_device *device) struct baseband_power_platform_data *pdata = device->dev.platform_data; struct xmm_power_data *data = &xmm_power_drv_data; - int ret; unsigned long flags; pr_debug("%s {\n", __func__); - if (baseband_xmm_powerstate == BBXMM_PS_UNINIT) + if (baseband_xmm_get_power_status() == BBXMM_PS_UNINIT) return -EINVAL; + /* check for device / platform data */ if (!device) { pr_err("%s: !device\n", __func__); @@ -309,18 +340,20 @@ static int xmm_power_off(struct platform_device *device) return -EINVAL; } + spin_lock_irqsave(&xmm_lock, flags); ipc_ap_wake_state = IPC_AP_WAKE_UNINIT; + spin_unlock_irqrestore(&xmm_lock, flags); + ret = disable_irq_wake(gpio_to_irq(pdata->modem.xmm.ipc_ap_wake)); if (ret < 0) pr_err("%s: disable_irq_wake error\n", __func__); /* unregister usb host controller */ if (pdata->hsic_unregister) - pdata->hsic_unregister(data->hsic_device); + pdata->hsic_unregister(&data->hsic_device); else pr_err("%s: hsic_unregister is missing\n", __func__); - /* set IPC_HSIC_ACTIVE low */ gpio_set_value(pdata->modem.xmm.ipc_hsic_active, 0); @@ -332,13 +365,15 @@ static int xmm_power_off(struct platform_device *device) /* sleep 1ms */ usleep_range(1000, 2000); - baseband_xmm_powerstate = BBXMM_PS_UNINIT; - modem_sleep_flag = false; - CP_initiated_L2toL0 = false; + baseband_xmm_set_power_status(BBXMM_PS_UNINIT); + spin_lock_irqsave(&xmm_lock, flags); + modem_sleep_flag = false; + cp_initiated_l2tol0 = false; wakeup_pending = false; system_suspending = false; spin_unlock_irqrestore(&xmm_lock, flags); + /* start registration process once again on xmm on */ register_hsic_device = true; @@ -419,73 +454,77 @@ static void xmm_power_l2_resume(void) if (!pdata) return; + /* erroneous remote-wakeup might call this from irq */ + if (in_interrupt() || in_atomic()) { + pr_err("%s: not allowed in interrupt\n", __func__); + return; + } + /* claim the wakelock here to avoid any system suspend */ if (!wake_lock_active(&wakelock)) wake_lock_timeout(&wakelock, HZ*2); - modem_sleep_flag = false; + spin_lock_irqsave(&xmm_lock, flags); + modem_sleep_flag = false; wakeup_pending = false; - spin_unlock_irqrestore(&xmm_lock, flags); - if (CP_initiated_L2toL0) { - pr_info("CP L2->L0\n"); - CP_initiated_L2toL0 = false; - queue_work(workqueue, &L2_resume_work); - } else { - /* set the slave wakeup request */ - pr_info("AP/CP L2->L0\n"); - value = gpio_get_value(pdata->modem.xmm.ipc_ap_wake); - if (value) { - drv->hostwake = 0; - /* wake bb */ - gpio_set_value(pdata->modem.xmm.ipc_bb_wake, 1); + value = gpio_get_value(pdata->modem.xmm.ipc_ap_wake); + if (value) { + /* set the slave wakeup request - bb_wake high */ + drv->hostwake = 0; + gpio_set_value(pdata->modem.xmm.ipc_bb_wake, 1); + spin_unlock_irqrestore(&xmm_lock, flags); + pr_info("AP L2->L0\n"); retry: - /* wait for cp */ - pr_debug("waiting for host wakeup from CP...\n"); - ret = wait_event_interruptible_timeout(drv->bb_wait, + /* 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) { + if (ret == 0) { + pr_info("!!AP L2->L0 Failed\n"); + return; + } + if (ret == -ERESTARTSYS) { + if (rcount >= 5) { pr_info("!!AP L2->L0 Failed\n"); 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"); + pr_debug("%s: caught signal\n", __func__); + rcount++; + goto retry; + } + pr_debug("Get gpio host wakeup low <-\n"); + } else { + cp_initiated_l2tol0 = false; + queue_work(workqueue, &l2_resume_work); + spin_unlock_irqrestore(&xmm_lock, flags); + pr_info("CP L2->L0\n"); } } - +/* this function holds xmm_lock */ void baseband_xmm_set_power_status(unsigned int status) { struct baseband_power_platform_data *data = xmm_power_drv_data.pdata; int value = 0; unsigned long flags; - if (baseband_xmm_powerstate == status) + if (baseband_xmm_get_power_status() == status) return; - pr_debug("%s\n", __func__); + + /* avoid prints inside spinlock */ + if (status <= BBXMM_PS_L2) + pr_info("%s\n", status == BBXMM_PS_L0 ? "L0" : "L2"); + + spin_lock_irqsave(&xmm_lock, flags); switch (status) { case BBXMM_PS_L0: - if (modem_sleep_flag) { - /* We dont have L3 state now, should be handled from L2 - * xmm_power_driver_handle_resume(data); - */ - } - pr_info("L0\n"); baseband_xmm_powerstate = status; if (!wake_lock_active(&wakelock)) wake_lock_timeout(&wakelock, HZ*2); + + /* pull hsic_active high for enumeration */ value = gpio_get_value(data->modem.xmm.ipc_hsic_active); - pr_debug("before L0 ipc_hsic_active=%d\n", value); if (!value) { pr_debug("L0 gpio set ipc_hsic_active=1 ->\n"); gpio_set_value(data->modem.xmm.ipc_hsic_active, 1); @@ -494,33 +533,42 @@ void baseband_xmm_set_power_status(unsigned int status) modem_power_on = false; baseband_modem_power_on(data); } + + /* cp acknowledgment for ap L2->L0 wake */ + if (!modem_acked_resume) + pr_err("%s: CP didn't ack usb-resume\n", __func__); + value = gpio_get_value(data->modem.xmm.ipc_bb_wake); + if (value) { + /* clear the slave wakeup request */ + gpio_set_value(data->modem.xmm.ipc_bb_wake, 0); + pr_debug("gpio bb_wake done low\n"); + } break; case BBXMM_PS_L2: - pr_info("L2\n"); - baseband_xmm_powerstate = status; - spin_lock_irqsave(&xmm_lock, flags); + modem_acked_resume = false; if (wakeup_pending) { spin_unlock_irqrestore(&xmm_lock, flags); pr_debug("%s: wakeup pending\n", __func__); xmm_power_l2_resume(); + spin_lock_irqsave(&xmm_lock, flags); + break; } else { - spin_unlock_irqrestore(&xmm_lock, flags); if (wake_lock_active(&wakelock)) wake_unlock(&wakelock); modem_sleep_flag = true; } + baseband_xmm_powerstate = status; break; case BBXMM_PS_L2TOL0: pr_debug("L2TOL0\n"); - spin_lock_irqsave(&xmm_lock, flags); system_suspending = false; wakeup_pending = false; - spin_unlock_irqrestore(&xmm_lock, flags); /* do this only from L2 state */ if (baseband_xmm_powerstate == BBXMM_PS_L2) { baseband_xmm_powerstate = status; - pr_debug("BB XMM POWER STATE = %d\n", status); + spin_unlock_irqrestore(&xmm_lock, flags); xmm_power_l2_resume(); + spin_lock_irqsave(&xmm_lock, flags); } baseband_xmm_powerstate = status; break; @@ -529,141 +577,109 @@ void baseband_xmm_set_power_status(unsigned int status) baseband_xmm_powerstate = status; break; } + spin_unlock_irqrestore(&xmm_lock, flags); pr_debug("BB XMM POWER STATE = %d\n", status); } EXPORT_SYMBOL_GPL(baseband_xmm_set_power_status); -irqreturn_t xmm_power_ipc_ap_wake_irq(int irq, void *dev_id) + +irqreturn_t xmm_power_ipc_ap_wake_irq(int value) { 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); - pr_debug("%s g(%d), wake_st(%d)\n", __func__, value, ipc_ap_wake_state); - - /* modem initialization/bootup part*/ - if (unlikely(ipc_ap_wake_state < IPC_AP_WAKE_IRQ_READY)) { - pr_err("%s - spurious irq\n", __func__); - return IRQ_HANDLED; - } else if (ipc_ap_wake_state == IPC_AP_WAKE_IRQ_READY) { - if (!value) { - pr_debug("%s - IPC_AP_WAKE_INIT1" - " - got falling edge\n", __func__); - /* go to IPC_AP_WAKE_INIT1 state */ - ipc_ap_wake_state = IPC_AP_WAKE_INIT1; - queue_work(workqueue, &init1_work); - } else - pr_debug("%s - IPC_AP_WAKE_INIT1" - " - wait for falling edge\n", __func__); - return IRQ_HANDLED; - } else if (ipc_ap_wake_state == IPC_AP_WAKE_INIT1) { - if (!value) { - pr_debug("%s - IPC_AP_WAKE_INIT2" - " - wait for rising edge\n", __func__); - } else { - pr_debug("%s - IPC_AP_WAKE_INIT2" - " - got rising edge\n", __func__); - /* go to IPC_AP_WAKE_INIT2 state */ - ipc_ap_wake_state = IPC_AP_WAKE_INIT2; - queue_work(workqueue, &init2_work); - } - return IRQ_HANDLED; - } /* 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); - } + spin_lock(&xmm_lock); + + /* AP L2 to L0 wakeup */ + 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) { pr_debug("cp ack for bb_wake\n"); ipc_ap_wake_state = IPC_AP_WAKE_L; + spin_unlock(&xmm_lock); return IRQ_HANDLED; } - spin_lock(&xmm_lock); wakeup_pending = true; - if (system_suspending) { - spin_unlock(&xmm_lock); - pr_info("Set wakeup_pending = 1 in system_" - " suspending!!!\n"); - } else { - if (baseband_xmm_powerstate == BBXMM_PS_L2) { - CP_initiated_L2toL0 = true; + if (system_suspending) + pr_info("set wakeup_pending 1 in system_suspending\n"); + else { + if (baseband_xmm_powerstate == BBXMM_PS_L2 || + baseband_xmm_powerstate == BBXMM_PS_L2TOL0) { + cp_initiated_l2tol0 = true; spin_unlock(&xmm_lock); baseband_xmm_set_power_status(BBXMM_PS_L2TOL0); - } else { - CP_initiated_L2toL0 = true; - spin_unlock(&xmm_lock); - } + spin_lock(&xmm_lock); + } else + cp_initiated_l2tol0 = true; + } + /* save gpio state */ ipc_ap_wake_state = IPC_AP_WAKE_L; + spin_unlock(&xmm_lock); } else { pr_debug("%s - rising\n", __func__); + spin_lock(&xmm_lock); + modem_acked_resume = true; value = gpio_get_value(data->modem.xmm.ipc_hsic_active); if (!value) { pr_info("host active low: ignore request\n"); ipc_ap_wake_state = IPC_AP_WAKE_H; + spin_unlock(&xmm_lock); return IRQ_HANDLED; } - value = gpio_get_value(data->modem.xmm.ipc_bb_wake); - if (value) { - /* Clear the slave wakeup request */ - gpio_set_value(data->modem.xmm.ipc_bb_wake, 0); - pr_debug("gpio slave wakeup done ->\n"); - } + if (reenable_autosuspend && usbdev) { reenable_autosuspend = false; queue_work(workqueue, &autopm_resume_work); } modem_sleep_flag = false; - baseband_xmm_set_power_status(BBXMM_PS_L0); /* save gpio state */ ipc_ap_wake_state = IPC_AP_WAKE_H; + spin_unlock(&xmm_lock); } - return IRQ_HANDLED; } EXPORT_SYMBOL(xmm_power_ipc_ap_wake_irq); -static void xmm_power_init1_work(struct work_struct *work) +static irqreturn_t ipc_ap_wake_irq(int irq, void *dev_id) { - struct baseband_power_platform_data *pdata = xmm_power_drv_data.pdata; + struct baseband_power_platform_data *data = xmm_power_drv_data.pdata; int value; - pr_debug("%s {\n", __func__); - - /* check if IPC_HSIC_ACTIVE high */ - value = gpio_get_value(pdata->modem.xmm.ipc_hsic_active); - if (value != 1) { - pr_err("%s - expected IPC_HSIC_ACTIVE high!\n", __func__); - return; - } - - /* wait 100 ms */ - msleep(100); - - /* set IPC_HSIC_ACTIVE low */ - gpio_set_value(pdata->modem.xmm.ipc_hsic_active, 0); - - /* wait 10 ms */ - usleep_range(10000, 11000); - - /* set IPC_HSIC_ACTIVE high */ - gpio_set_value(pdata->modem.xmm.ipc_hsic_active, 1); + value = gpio_get_value(data->modem.xmm.ipc_ap_wake); + pr_debug("%s g(%d), wake_st(%d)\n", __func__, value, ipc_ap_wake_state); - /* wait 20 ms */ - msleep(20); + /* modem wakeup part */ + if (likely(ipc_ap_wake_state >= IPC_AP_WAKE_INIT2)) + return xmm_power_ipc_ap_wake_irq(value); - pr_debug("%s }\n", __func__); + /* modem initialization/bootup part*/ + if (unlikely(ipc_ap_wake_state < IPC_AP_WAKE_IRQ_READY)) { + pr_err("%s - spurious irq\n", __func__); + } else if (ipc_ap_wake_state == IPC_AP_WAKE_IRQ_READY) { + if (value) { + /* make state ready for falling edge */ + ipc_ap_wake_state = IPC_AP_WAKE_INIT1; + pr_debug("%s - got rising edge\n", __func__); + } + } else if (ipc_ap_wake_state == IPC_AP_WAKE_INIT1) { + if (!value) { + pr_debug("%s - got falling edge at INIT1\n", __func__); + /* go to IPC_AP_WAKE_INIT2 state */ + ipc_ap_wake_state = IPC_AP_WAKE_INIT2; + queue_work(workqueue, &init2_work); + } else + pr_debug("%s - unexpected rising edge\n", __func__); + } + return IRQ_HANDLED; } static void xmm_power_init2_work(struct work_struct *work) @@ -684,7 +700,6 @@ static void xmm_power_init2_work(struct work_struct *work) pr_err("%s: hsic_register is missing\n", __func__); register_hsic_device = false; } - } static void xmm_power_autopm_resume(struct work_struct *work) @@ -724,19 +739,6 @@ static void xmm_power_l2_resume_work(struct work_struct *work) pr_debug("} %s\n", __func__); } -static void xmm_power_reset_on(struct baseband_power_platform_data *pdata) -{ - /* reset / power on sequence */ - gpio_set_value(pdata->modem.xmm.bb_rst, 0); - msleep(40); - gpio_set_value(pdata->modem.xmm.bb_rst, 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); -} - - static void xmm_power_work_func(struct work_struct *work) { struct xmm_power_data *data = @@ -774,12 +776,12 @@ static void xmm_power_work_func(struct work_struct *work) case BBXMM_WORK_INIT_FLASH_PM_STEP1: pr_debug("BBXMM_WORK_INIT_FLASH_PM_STEP1\n"); pr_debug("%s: ipc_hsic_active -> 0\n", __func__); - gpio_set_value(pdata->modem.xmm.ipc_hsic_active, 1); + gpio_set_value(pdata->modem.xmm.ipc_hsic_active, 0); + modem_acked_resume = true; /* reset / power on sequence */ xmm_power_reset_on(pdata); /* set power status as on */ power_onoff = 1; - gpio_set_value(pdata->modem.xmm.ipc_hsic_active, 0); /* expecting init2 performs register hsic to enumerate modem * software directly. @@ -820,7 +822,7 @@ static void xmm_device_remove_handler(struct usb_device *udev) if (usbdev == udev) { pr_info("Remove device %d <%s %s>\n", udev->devnum, udev->manufacturer, udev->product); - usbdev = 0; + usbdev = NULL; } } @@ -882,9 +884,9 @@ static int xmm_power_pm_notifier_event(struct notifier_block *this, if (wakeup_pending && (baseband_xmm_powerstate == BBXMM_PS_L2)) { wakeup_pending = false; + cp_initiated_l2tol0 = true; spin_unlock_irqrestore(&xmm_lock, flags); pr_info("%s : Service Pending CP wakeup\n", __func__); - CP_initiated_L2toL0 = true; baseband_xmm_set_power_status(BBXMM_PS_L2TOL0); return NOTIFY_OK; } @@ -908,7 +910,6 @@ static int xmm_power_driver_probe(struct platform_device *device) int err; pr_debug("%s\n", __func__); - pr_debug("[XMM] enum_delay_ms=%ld\n", enum_delay_ms); /* check for platform data */ if (!pdata) @@ -959,7 +960,7 @@ static int xmm_power_driver_probe(struct platform_device *device) ipc_ap_wake_state = IPC_AP_WAKE_UNINIT; err = request_threaded_irq( gpio_to_irq(pdata->modem.xmm.ipc_ap_wake), - NULL, xmm_power_ipc_ap_wake_irq, + NULL, ipc_ap_wake_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "IPC_AP_WAKE_IRQ", NULL); if (err < 0) { @@ -972,9 +973,9 @@ static int xmm_power_driver_probe(struct platform_device *device) if (err < 0) pr_err("%s: enable_irq_wake error\n", __func__); - pr_debug("%s: AP_WAKE_INIT1\n", __func__); - /* ver 1130 or later starts in INIT1 state */ - ipc_ap_wake_state = IPC_AP_WAKE_INIT1; + pr_debug("%s: set state IPC_AP_WAKE_IRQ_READY\n", __func__); + /* ver 1130 or later start in IRQ_READY state */ + ipc_ap_wake_state = IPC_AP_WAKE_IRQ_READY; } /* init work queue */ @@ -989,15 +990,14 @@ static int xmm_power_driver_probe(struct platform_device *device) queue_work(workqueue, &xmm_power_drv_data.work); /* init work objects */ - INIT_WORK(&init1_work, xmm_power_init1_work); INIT_WORK(&init2_work, xmm_power_init2_work); - INIT_WORK(&L2_resume_work, xmm_power_l2_resume_work); + INIT_WORK(&l2_resume_work, xmm_power_l2_resume_work); INIT_WORK(&autopm_resume_work, xmm_power_autopm_resume); /* init state variables */ register_hsic_device = true; - CP_initiated_L2toL0 = false; - baseband_xmm_powerstate = BBXMM_PS_UNINIT; + cp_initiated_l2tol0 = false; + baseband_xmm_set_power_status(BBXMM_PS_UNINIT); spin_lock_irqsave(&xmm_lock, flags); wakeup_pending = false; system_suspending = false; @@ -1026,9 +1026,8 @@ static int xmm_power_driver_remove(struct platform_device *device) usb_unregister_notify(&usb_xmm_nb); /* free baseband irq(s) */ - if (modem_flash && modem_pm) { + if (modem_flash && modem_pm) free_irq(gpio_to_irq(pdata->modem.xmm.ipc_ap_wake), NULL); - } /* free baseband gpio(s) */ gpio_free_array(tegra_baseband_gpios, @@ -1042,7 +1041,7 @@ static int xmm_power_driver_remove(struct platform_device *device) /* unregister usb host controller */ if (pdata->hsic_unregister) - pdata->hsic_unregister(data->hsic_device); + pdata->hsic_unregister(&data->hsic_device); else pr_err("%s: hsic_unregister is missing\n", __func__); diff --git a/arch/arm/mach-tegra/baseband-xmm-power.h b/arch/arm/mach-tegra/baseband-xmm-power.h index 69140891319d..55c81833ba04 100644 --- a/arch/arm/mach-tegra/baseband-xmm-power.h +++ b/arch/arm/mach-tegra/baseband-xmm-power.h @@ -15,7 +15,7 @@ */ #ifndef BASEBAND_XMM_POWER_H -#define BASREBAND_XMM_POWER_H +#define BASEBAND_XMM_POWER_H #include <linux/pm.h> #include <linux/suspend.h> @@ -41,7 +41,7 @@ enum baseband_type { struct baseband_power_platform_data { enum baseband_type baseband_type; struct platform_device* (*hsic_register)(void); - void (*hsic_unregister)(struct platform_device *); + void (*hsic_unregister)(struct platform_device **); union { struct { int mdm_reset; @@ -90,21 +90,28 @@ struct xmm_power_data { }; enum baseband_xmm_powerstate_t { - BBXMM_PS_UNINIT = 0, - BBXMM_PS_INIT = 1, - BBXMM_PS_L0 = 2, - BBXMM_PS_L0TOL2 = 3, - BBXMM_PS_L2 = 4, - BBXMM_PS_L2TOL0 = 5, - BBXMM_PS_L2TOL3 = 6, - BBXMM_PS_L3 = 7, - BBXMM_PS_L3TOL0 = 8, + BBXMM_PS_L0 = 0, + BBXMM_PS_L2 = 1, + BBXMM_PS_L0TOL2 = 2, + BBXMM_PS_L2TOL0 = 3, + BBXMM_PS_UNINIT = 4, + BBXMM_PS_INIT = 5, + BBXMM_PS_L3 = 6, BBXMM_PS_LAST = -1, }; -irqreturn_t xmm_power_ipc_ap_wake_irq(int irq, void *dev_id); +enum ipc_ap_wake_state_t { + IPC_AP_WAKE_UNINIT, + IPC_AP_WAKE_IRQ_READY, + IPC_AP_WAKE_INIT1, + IPC_AP_WAKE_INIT2, + IPC_AP_WAKE_L, + IPC_AP_WAKE_H, +}; + +irqreturn_t xmm_power_ipc_ap_wake_irq(int value); void baseband_xmm_set_power_status(unsigned int status); extern struct xmm_power_data xmm_power_drv_data; -#endif /* BASREBAND_XMM_POWER_H */ +#endif /* BASEBAND_XMM_POWER_H */ diff --git a/arch/arm/mach-tegra/baseband-xmm-power2.c b/arch/arm/mach-tegra/baseband-xmm-power2.c index 3c6285c0a070..a79cd6fb499f 100644 --- a/arch/arm/mach-tegra/baseband-xmm-power2.c +++ b/arch/arm/mach-tegra/baseband-xmm-power2.c @@ -49,16 +49,7 @@ MODULE_PARM_DESC(XYZ, static struct workqueue_struct *workqueue; static bool free_ipc_ap_wake_irq; - -static enum { - IPC_AP_WAKE_UNINIT, - IPC_AP_WAKE_IRQ_READY, - IPC_AP_WAKE_INIT1, - IPC_AP_WAKE_INIT2, - IPC_AP_WAKE_L, - IPC_AP_WAKE_H, -} ipc_ap_wake_state; - +static enum ipc_ap_wake_state_t ipc_ap_wake_state; static irqreturn_t xmm_power2_ipc_ap_wake_irq(int irq, void *dev_id) { @@ -66,8 +57,6 @@ static irqreturn_t xmm_power2_ipc_ap_wake_irq(int irq, void *dev_id) struct xmm_power_data *data = dev_id; struct baseband_power_platform_data *pdata = data->pdata; - pr_debug("%s\n", __func__); - /* check for platform data */ if (!pdata) return IRQ_HANDLED; @@ -79,8 +68,8 @@ static irqreturn_t xmm_power2_ipc_ap_wake_irq(int irq, void *dev_id) pr_err("%s - spurious irq\n", __func__); else if (ipc_ap_wake_state == IPC_AP_WAKE_IRQ_READY) { if (!value) { - pr_debug("%s: IPC_AP_WAKE_INIT1 got falling edge\n", - __func__); + pr_debug("%s: IPC_AP_WAKE_IRQ_READY got falling edge\n", + __func__); /* go to IPC_AP_WAKE_INIT2 state */ ipc_ap_wake_state = IPC_AP_WAKE_INIT2; /* queue work */ @@ -88,7 +77,7 @@ static irqreturn_t xmm_power2_ipc_ap_wake_irq(int irq, void *dev_id) BBXMM_WORK_INIT_FLASHLESS_PM_STEP2; queue_work(workqueue, &data->work); } else - pr_debug("%s: IPC_AP_WAKE_INIT1" + pr_debug("%s: IPC_AP_WAKE_IRQ_READY" " wait for falling edge\n", __func__); } else { if (!value) { @@ -98,7 +87,7 @@ static irqreturn_t xmm_power2_ipc_ap_wake_irq(int irq, void *dev_id) pr_debug("%s - rising\n", __func__); ipc_ap_wake_state = IPC_AP_WAKE_H; } - return xmm_power_ipc_ap_wake_irq(irq, dev_id); + return xmm_power_ipc_ap_wake_irq(value); } return IRQ_HANDLED; @@ -119,7 +108,7 @@ static void xmm_power2_step1(struct work_struct *work) /* unregister usb host controller */ if (pdata->hsic_unregister) - pdata->hsic_unregister(data->hsic_device); + pdata->hsic_unregister(&data->hsic_device); else pr_err("%s: hsic_unregister is missing\n", __func__); diff --git a/arch/arm/mach-tegra/board-aruba-panel.c b/arch/arm/mach-tegra/board-aruba-panel.c index 01ade01a0eb6..488f212422e6 100644 --- a/arch/arm/mach-tegra/board-aruba-panel.c +++ b/arch/arm/mach-tegra/board-aruba-panel.c @@ -50,8 +50,6 @@ static int aruba_backlight_init(struct device *dev) { ret = gpio_direction_output(aruba_bl_enb, 1); if (ret < 0) gpio_free(aruba_bl_enb); - else - tegra_gpio_enable(aruba_bl_enb); return ret; }; @@ -59,7 +57,6 @@ static int aruba_backlight_init(struct device *dev) { static void aruba_backlight_exit(struct device *dev) { gpio_set_value(aruba_bl_enb, 0); gpio_free(aruba_bl_enb); - tegra_gpio_disable(aruba_bl_enb); } static int aruba_backlight_notify(struct device *unused, int brightness) diff --git a/arch/arm/mach-tegra/board-aruba-sdhci.c b/arch/arm/mach-tegra/board-aruba-sdhci.c index 26b04a9021e1..cf29137b773f 100644 --- a/arch/arm/mach-tegra/board-aruba-sdhci.c +++ b/arch/arm/mach-tegra/board-aruba-sdhci.c @@ -224,9 +224,6 @@ static int __init aruba_wifi_init(void) gpio_request(ARUBA_WLAN_PWR, "wlan_power"); gpio_request(ARUBA_WLAN_RST, "wlan_rst"); - tegra_gpio_enable(ARUBA_WLAN_PWR); - tegra_gpio_enable(ARUBA_WLAN_RST); - gpio_direction_output(ARUBA_WLAN_PWR, 0); gpio_direction_output(ARUBA_WLAN_RST, 0); diff --git a/arch/arm/mach-tegra/board-aruba-sensors.c b/arch/arm/mach-tegra/board-aruba-sensors.c index f5ba3d761634..34891ae6f6c2 100644 --- a/arch/arm/mach-tegra/board-aruba-sensors.c +++ b/arch/arm/mach-tegra/board-aruba-sensors.c @@ -43,14 +43,12 @@ static void aruba_isl29018_init(void) { - tegra_gpio_enable(ISL29018_IRQ_GPIO); gpio_request(ISL29018_IRQ_GPIO, "isl29018"); gpio_direction_input(ISL29018_IRQ_GPIO); } static void aruba_akm8975_init(void) { - tegra_gpio_enable(AKM8975_IRQ_GPIO); gpio_request(AKM8975_IRQ_GPIO, "akm8975"); gpio_direction_input(AKM8975_IRQ_GPIO); } diff --git a/arch/arm/mach-tegra/board-aruba.c b/arch/arm/mach-tegra/board-aruba.c index 2fc524ccef93..bb47beeffbdc 100644 --- a/arch/arm/mach-tegra/board-aruba.c +++ b/arch/arm/mach-tegra/board-aruba.c @@ -459,14 +459,6 @@ static struct platform_device *aruba_devices[] __initdata = { #endif }; -static void aruba_keys_init(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(aruba_keys); i++) - tegra_gpio_enable(aruba_keys[i].gpio); -} - static int __init aruba_touch_init(void) { return 0; @@ -518,7 +510,6 @@ static void __init tegra_aruba_init(void) aruba_i2c_init(); aruba_regulator_init(); aruba_touch_init(); - aruba_keys_init(); aruba_usb_init(); aruba_panel_init(); aruba_sensors_init(); diff --git a/arch/arm/mach-tegra/board-cardhu-irda.c b/arch/arm/mach-tegra/board-cardhu-irda.c new file mode 100644 index 000000000000..489d473fc08f --- /dev/null +++ b/arch/arm/mach-tegra/board-cardhu-irda.c @@ -0,0 +1,178 @@ +/* + * arch/arm/mach-tegra/board-cardhu-irda.c + * + * Copyright (c) 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 + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* This driver tested with tfdu6103 irda transceiver */ + +#include <linux/gpio.h> +#include <linux/delay.h> +#include <linux/serial_8250.h> +#include <linux/tegra_uart.h> + +#include "gpio-names.h" +#include "board-cardhu.h" +#include "board.h" +#include "devices.h" + +/* Uncomment the next line to get the function entry logs */ +/*#define DRV_FUNC 1*/ + +#undef FPRINT +#ifdef DRV_FUNC +#define FPRINT(fmt, args...) printk(KERN_INFO "IRDA: " fmt, ## args) +#else +#define FPRINT(fmt, args...) +#endif + +#define CARDHU_IRDA_SD TEGRA_GPIO_PJ6 +#define CARDHU_IRDA_TX TEGRA_GPIO_PC2 +#define CARDHU_IRDA_RX TEGRA_GPIO_PC3 + +#define IRDA_DELAY 1 + +#define SIR 1 +#define FIR 2 +#define VFIR 3 /* tfdu6108 doesn't support */ + + +static int irda_mode; + +/* If mode = SIR mode switch will be FIR -> SIR + If mode = FIR mode switch will be SIR ->FIR */ + +static int cardhu_irda_mode_switch(int mode) +{ + int ret = -1; + + FPRINT("Start of Func %s\n", __func__); + + if ((mode != SIR) && (mode != FIR)) { + pr_err("Unsupported irda mode\n"); + return ret; + } + + gpio_set_value(CARDHU_IRDA_SD, 1); + + udelay(IRDA_DELAY); + + ret = gpio_request(CARDHU_IRDA_TX, "irda_tx"); + if (ret < 0) { + pr_err("%s: cardhu_irda_tx gpio request failed %d\n", + __func__, ret); + gpio_set_value(CARDHU_IRDA_SD, 0); + return ret; + } + + if (mode == SIR) + ret = gpio_direction_output(CARDHU_IRDA_TX, 0); + else if (mode == FIR) + ret = gpio_direction_output(CARDHU_IRDA_TX, 1); + + if (ret) { + pr_err("%s: cardhu_irda_tx Direction configuration failed %d\n", + __func__, ret); + gpio_set_value(CARDHU_IRDA_SD, 0); + goto closure; + } + + udelay(IRDA_DELAY); + + gpio_set_value(CARDHU_IRDA_SD, 0); + + udelay(IRDA_DELAY); + + if (mode == FIR) { + gpio_set_value(CARDHU_IRDA_TX, 0); + irda_mode = FIR; + pr_info("IrDA Transceiver is switched to FIR mode\n"); + } else { + pr_info("IrDA Transceiver is switched to SIR mode\n"); + irda_mode = SIR; + } + + udelay(IRDA_DELAY); + +closure: + gpio_free(CARDHU_IRDA_TX); + return ret; +} + +static int SD_config(void) +{ + int ret = -1; + + FPRINT("Start of the Func %s\n", __func__); + /* Gpio enable for SD */ + ret = gpio_request(CARDHU_IRDA_SD, "irda_sd"); + if (ret < 0) { + pr_err("%s: cardhu_irda_sd gpio request failed %d\n", + __func__, ret); + return ret; + } + + ret = gpio_direction_output(CARDHU_IRDA_SD, 1); + if (ret) + pr_err("%s: cardhu_irda_sd Direction configuration failed %d\n", + __func__, ret); + return ret; +} + +static void cardhu_irda_start(void) +{ + FPRINT("Start of the Func %s\n", __func__); + pr_info("IrDA transceiver is enabled\n"); + gpio_set_value(CARDHU_IRDA_SD, 0); + irda_mode = SIR; +} + +static void cardhu_irda_shutdown(void) +{ + FPRINT("Start of the Func %s\n", __func__); + pr_info("IrDA transceiver is disabled\n"); + /* Setting the IrDA transceiver into shutdown mode*/ + gpio_set_value(CARDHU_IRDA_SD, 1); +} + +static int cardhu_irda_init(void) +{ + int ret = 0; + + FPRINT("Start of the Func %s\n", __func__); + if (SD_config() < 0) { + pr_err("%s: Error in IRDA_SD signal configuration\n", __func__); + ret = -1; + } + return ret; +} + +static void cardhu_irda_remove(void) +{ + FPRINT("Start of the Func %s\n", __func__); + gpio_free(CARDHU_IRDA_SD); +} + + +struct tegra_uart_platform_data cardhu_irda_pdata = { + .is_irda = true, + .irda_init = cardhu_irda_init, + .irda_start = cardhu_irda_start, + .irda_mode_switch = cardhu_irda_mode_switch, + .irda_shutdown = cardhu_irda_shutdown, + .irda_remove = cardhu_irda_remove, +}; diff --git a/arch/arm/mach-tegra/board-cardhu-kbc.c b/arch/arm/mach-tegra/board-cardhu-kbc.c index c3971403148f..ce9b22cc1170 100644 --- a/arch/arm/mach-tegra/board-cardhu-kbc.c +++ b/arch/arm/mach-tegra/board-cardhu-kbc.c @@ -122,6 +122,17 @@ int __init cardhu_scroll_init(void) .debounce_interval = 10, \ } +#define GPIO_SW_KEY(_id, _gpio, _iswake) \ + { \ + .code = _id, \ + .gpio = _gpio, \ + .active_low = 1, \ + .desc = #_id, \ + .type = EV_SW, \ + .wakeup = _iswake, \ + .debounce_interval = 1, \ + } + #define GPIO_IKEY(_id, _irq, _iswake, _deb) \ { \ .code = _id, \ @@ -165,6 +176,7 @@ static struct gpio_keys_button cardhu_keys_e1291[] = { [4] = GPIO_KEY(KEY_BACK, PQ0, 0), [5] = GPIO_KEY(KEY_MENU, PQ1, 0), [6] = GPIO_IKEY(KEY_POWER, TPS6591X_IRQ_BASE + TPS6591X_INT_PWRON, 1, 100), + [7] = GPIO_SW_KEY(SW_LID, TPS6591X_GPIO_5, 0), }; static struct gpio_keys_button cardhu_keys_e1291_a04[] = { @@ -176,6 +188,7 @@ static struct gpio_keys_button cardhu_keys_e1291_a04[] = { [5] = GPIO_KEY(KEY_MENU, PQ1, 0), [6] = GPIO_KEY(KEY_RESERVED, PV0, 1), [7] = GPIO_IKEY(KEY_POWER, TPS6591X_IRQ_BASE + TPS6591X_INT_PWRON, 1, 100), + [8] = GPIO_SW_KEY(SW_LID, TPS6591X_GPIO_5, 0), }; static struct gpio_keys_platform_data cardhu_keys_e1291_pdata = { diff --git a/arch/arm/mach-tegra/board-cardhu-memory.c b/arch/arm/mach-tegra/board-cardhu-memory.c index 1ed99a9fa1fa..4ec8839c44f6 100644 --- a/arch/arm/mach-tegra/board-cardhu-memory.c +++ b/arch/arm/mach-tegra/board-cardhu-memory.c @@ -705,7 +705,7 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000280, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00020001, /* MC_EMEM_ARB_CFG */ + 0x00030003, /* MC_EMEM_ARB_CFG */ 0xc0000010, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -825,7 +825,7 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x8000040b, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000001, /* MC_EMEM_ARB_CFG */ + 0x00010003, /* MC_EMEM_ARB_CFG */ 0xc0000010, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -945,7 +945,7 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000713, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000001, /* MC_EMEM_ARB_CFG */ + 0x00000003, /* MC_EMEM_ARB_CFG */ 0xc0000018, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -1065,7 +1065,7 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000d22, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000003, /* MC_EMEM_ARB_CFG */ + 0x00000006, /* MC_EMEM_ARB_CFG */ 0xc0000025, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -1185,8 +1185,8 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x8000174b, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000005, /* MC_EMEM_ARB_CFG */ - 0x80000044, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x0000000b, /* MC_EMEM_ARB_CFG */ + 0xc0000044, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000002, /* MC_EMEM_ARB_TIMING_RP */ 0x00000009, /* MC_EMEM_ARB_TIMING_RC */ @@ -1305,8 +1305,8 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80001941, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000006, /* MC_EMEM_ARB_CFG */ - 0x8000004a, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x0000000c, /* MC_EMEM_ARB_CFG */ + 0xc000004a, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000002, /* MC_EMEM_ARB_TIMING_RP */ 0x0000000a, /* MC_EMEM_ARB_TIMING_RC */ @@ -1425,8 +1425,8 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80001bc0, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000006, /* MC_EMEM_ARB_CFG */ - 0x80000051, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x0000000d, /* MC_EMEM_ARB_CFG */ + 0xc0000051, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000002, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000003, /* MC_EMEM_ARB_TIMING_RP */ 0x0000000b, /* MC_EMEM_ARB_TIMING_RC */ @@ -1545,8 +1545,8 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x800020ae, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000008, /* MC_EMEM_ARB_CFG */ - 0x80000060, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x0000000f, /* MC_EMEM_ARB_CFG */ + 0xc0000060, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000002, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000003, /* MC_EMEM_ARB_TIMING_RP */ 0x0000000d, /* MC_EMEM_ARB_TIMING_RC */ @@ -1665,8 +1665,8 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x800028a5, /* EMC_DYN_SELF_REF_CONTROL */ - 0x0000000a, /* MC_EMEM_ARB_CFG */ - 0x80000079, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x00000014, /* MC_EMEM_ARB_CFG */ + 0xc0000079, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000003, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000004, /* MC_EMEM_ARB_TIMING_RP */ 0x00000010, /* MC_EMEM_ARB_TIMING_RC */ @@ -1785,8 +1785,8 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x8000308c, /* EMC_DYN_SELF_REF_CONTROL */ - 0x0000000c, /* MC_EMEM_ARB_CFG */ - 0x80000090, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x00000016, /* MC_EMEM_ARB_CFG */ + 0xc0000090, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000004, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000005, /* MC_EMEM_ARB_TIMING_RP */ 0x00000013, /* MC_EMEM_ARB_TIMING_RC */ @@ -1905,8 +1905,8 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x8000308c, /* EMC_DYN_SELF_REF_CONTROL */ - 0x0000000c, /* MC_EMEM_ARB_CFG */ - 0x80000090, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x00000018, /* MC_EMEM_ARB_CFG */ + 0xc0000090, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000004, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000005, /* MC_EMEM_ARB_TIMING_RP */ 0x00000013, /* MC_EMEM_ARB_TIMING_RC */ @@ -2025,8 +2025,8 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x8000367d, /* EMC_DYN_SELF_REF_CONTROL */ - 0x0000000d, /* MC_EMEM_ARB_CFG */ - 0x800000a2, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x0000001b, /* MC_EMEM_ARB_CFG */ + 0xc00000a2, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000005, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000006, /* MC_EMEM_ARB_TIMING_RP */ 0x00000016, /* MC_EMEM_ARB_TIMING_RC */ @@ -2148,7 +2148,7 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2_2GB1R[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x8000040b, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00010001, /* MC_EMEM_ARB_CFG */ + 0x00010003, /* MC_EMEM_ARB_CFG */ 0xc0000010, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -2268,7 +2268,7 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2_2GB1R[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000713, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000001, /* MC_EMEM_ARB_CFG */ + 0x00000003, /* MC_EMEM_ARB_CFG */ 0xc0000018, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -2388,7 +2388,7 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2_2GB1R[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000d22, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000003, /* MC_EMEM_ARB_CFG */ + 0x00000006, /* MC_EMEM_ARB_CFG */ 0xc0000025, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -2508,8 +2508,8 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2_2GB1R[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x8000174b, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000005, /* MC_EMEM_ARB_CFG */ - 0x80000044, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x0000000b, /* MC_EMEM_ARB_CFG */ + 0xc0000044, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000002, /* MC_EMEM_ARB_TIMING_RP */ 0x00000009, /* MC_EMEM_ARB_TIMING_RC */ @@ -2628,8 +2628,8 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2_2GB1R[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x800018c8, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000006, /* MC_EMEM_ARB_CFG */ - 0x80000048, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x0000000c, /* MC_EMEM_ARB_CFG */ + 0xc0000048, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000002, /* MC_EMEM_ARB_TIMING_RP */ 0x00000009, /* MC_EMEM_ARB_TIMING_RC */ @@ -2748,8 +2748,8 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2_2GB1R[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80002d93, /* EMC_DYN_SELF_REF_CONTROL */ - 0x0000000b, /* MC_EMEM_ARB_CFG */ - 0x80000087, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x00000014, /* MC_EMEM_ARB_CFG */ + 0xc0000087, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000004, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000005, /* MC_EMEM_ARB_TIMING_RP */ 0x00000012, /* MC_EMEM_ARB_TIMING_RC */ @@ -2868,8 +2868,8 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2_2GB1R[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80002d93, /* EMC_DYN_SELF_REF_CONTROL */ - 0x0000000b, /* MC_EMEM_ARB_CFG */ - 0x80000087, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x00000016, /* MC_EMEM_ARB_CFG */ + 0xc0000087, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000004, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000005, /* MC_EMEM_ARB_TIMING_RP */ 0x00000012, /* MC_EMEM_ARB_TIMING_RC */ @@ -2988,8 +2988,8 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2_2GB1R[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x8000308c, /* EMC_DYN_SELF_REF_CONTROL */ - 0x0000000c, /* MC_EMEM_ARB_CFG */ - 0x80000090, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x00000018, /* MC_EMEM_ARB_CFG */ + 0xc0000090, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000004, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000005, /* MC_EMEM_ARB_TIMING_RP */ 0x00000013, /* MC_EMEM_ARB_TIMING_RC */ @@ -3111,7 +3111,7 @@ static const struct tegra_emc_table cardhu_emc_tables_k4b4g0846b_hyk0[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000287, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00020001, /* MC_EMEM_ARB_CFG */ + 0x00030003, /* MC_EMEM_ARB_CFG */ 0xc0000010, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -3186,14 +3186,14 @@ static const struct tegra_emc_table cardhu_emc_tables_k4b4g0846b_hyk0[] = { 0x00004288, /* EMC_FBIO_CFG5 */ 0x007800a4, /* EMC_CFG_DIG_DLL */ 0x00008000, /* EMC_CFG_DIG_DLL_PERIOD */ - 0x000fc000, /* EMC_DLL_XFORM_DQS0 */ - 0x000fc000, /* EMC_DLL_XFORM_DQS1 */ - 0x000fc000, /* EMC_DLL_XFORM_DQS2 */ - 0x000fc000, /* EMC_DLL_XFORM_DQS3 */ - 0x000fc000, /* EMC_DLL_XFORM_DQS4 */ - 0x000fc000, /* EMC_DLL_XFORM_DQS5 */ - 0x000fc000, /* EMC_DLL_XFORM_DQS6 */ - 0x000fc000, /* EMC_DLL_XFORM_DQS7 */ + 0x00080000, /* EMC_DLL_XFORM_DQS0 */ + 0x00080000, /* EMC_DLL_XFORM_DQS1 */ + 0x00080000, /* EMC_DLL_XFORM_DQS2 */ + 0x00080000, /* EMC_DLL_XFORM_DQS3 */ + 0x00080000, /* EMC_DLL_XFORM_DQS4 */ + 0x00080000, /* EMC_DLL_XFORM_DQS5 */ + 0x00080000, /* EMC_DLL_XFORM_DQS6 */ + 0x00080000, /* EMC_DLL_XFORM_DQS7 */ 0x00000000, /* EMC_DLL_XFORM_QUSE0 */ 0x00000000, /* EMC_DLL_XFORM_QUSE1 */ 0x00000000, /* EMC_DLL_XFORM_QUSE2 */ @@ -3210,10 +3210,10 @@ static const struct tegra_emc_table cardhu_emc_tables_k4b4g0846b_hyk0[] = { 0x00000000, /* EMC_DLI_TRIM_TXDQS5 */ 0x00000000, /* EMC_DLI_TRIM_TXDQS6 */ 0x00000000, /* EMC_DLI_TRIM_TXDQS7 */ - 0x000fc000, /* EMC_DLL_XFORM_DQ0 */ - 0x000fc000, /* EMC_DLL_XFORM_DQ1 */ - 0x000fc000, /* EMC_DLL_XFORM_DQ2 */ - 0x000fc000, /* EMC_DLL_XFORM_DQ3 */ + 0x00080000, /* EMC_DLL_XFORM_DQ0 */ + 0x00080000, /* EMC_DLL_XFORM_DQ1 */ + 0x00080000, /* EMC_DLL_XFORM_DQ2 */ + 0x00080000, /* EMC_DLL_XFORM_DQ3 */ 0x000002a0, /* EMC_XM2CMDPADCTRL */ 0x0800211c, /* EMC_XM2DQSPADCTRL2 */ 0x00000000, /* EMC_XM2DQPADCTRL2 */ @@ -3231,7 +3231,7 @@ static const struct tegra_emc_table cardhu_emc_tables_k4b4g0846b_hyk0[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x8000040b, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00010001, /* MC_EMEM_ARB_CFG */ + 0x00010003, /* MC_EMEM_ARB_CFG */ 0xc0000010, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -3306,14 +3306,14 @@ static const struct tegra_emc_table cardhu_emc_tables_k4b4g0846b_hyk0[] = { 0x00004288, /* EMC_FBIO_CFG5 */ 0x007800a4, /* EMC_CFG_DIG_DLL */ 0x00008000, /* EMC_CFG_DIG_DLL_PERIOD */ - 0x000fc000, /* EMC_DLL_XFORM_DQS0 */ - 0x000fc000, /* EMC_DLL_XFORM_DQS1 */ - 0x000fc000, /* EMC_DLL_XFORM_DQS2 */ - 0x000fc000, /* EMC_DLL_XFORM_DQS3 */ - 0x000fc000, /* EMC_DLL_XFORM_DQS4 */ - 0x000fc000, /* EMC_DLL_XFORM_DQS5 */ - 0x000fc000, /* EMC_DLL_XFORM_DQS6 */ - 0x000fc000, /* EMC_DLL_XFORM_DQS7 */ + 0x00080000, /* EMC_DLL_XFORM_DQS0 */ + 0x00080000, /* EMC_DLL_XFORM_DQS1 */ + 0x00080000, /* EMC_DLL_XFORM_DQS2 */ + 0x00080000, /* EMC_DLL_XFORM_DQS3 */ + 0x00080000, /* EMC_DLL_XFORM_DQS4 */ + 0x00080000, /* EMC_DLL_XFORM_DQS5 */ + 0x00080000, /* EMC_DLL_XFORM_DQS6 */ + 0x00080000, /* EMC_DLL_XFORM_DQS7 */ 0x00000000, /* EMC_DLL_XFORM_QUSE0 */ 0x00000000, /* EMC_DLL_XFORM_QUSE1 */ 0x00000000, /* EMC_DLL_XFORM_QUSE2 */ @@ -3330,10 +3330,10 @@ static const struct tegra_emc_table cardhu_emc_tables_k4b4g0846b_hyk0[] = { 0x00000000, /* EMC_DLI_TRIM_TXDQS5 */ 0x00000000, /* EMC_DLI_TRIM_TXDQS6 */ 0x00000000, /* EMC_DLI_TRIM_TXDQS7 */ - 0x000fc000, /* EMC_DLL_XFORM_DQ0 */ - 0x000fc000, /* EMC_DLL_XFORM_DQ1 */ - 0x000fc000, /* EMC_DLL_XFORM_DQ2 */ - 0x000fc000, /* EMC_DLL_XFORM_DQ3 */ + 0x00080000, /* EMC_DLL_XFORM_DQ0 */ + 0x00080000, /* EMC_DLL_XFORM_DQ1 */ + 0x00080000, /* EMC_DLL_XFORM_DQ2 */ + 0x00080000, /* EMC_DLL_XFORM_DQ3 */ 0x000002a0, /* EMC_XM2CMDPADCTRL */ 0x0800211c, /* EMC_XM2DQSPADCTRL2 */ 0x00000000, /* EMC_XM2DQPADCTRL2 */ @@ -3351,7 +3351,7 @@ static const struct tegra_emc_table cardhu_emc_tables_k4b4g0846b_hyk0[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000713, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000001, /* MC_EMEM_ARB_CFG */ + 0x00000003, /* MC_EMEM_ARB_CFG */ 0xc0000018, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -3471,7 +3471,7 @@ static const struct tegra_emc_table cardhu_emc_tables_k4b4g0846b_hyk0[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000d22, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000003, /* MC_EMEM_ARB_CFG */ + 0x00000006, /* MC_EMEM_ARB_CFG */ 0xc0000025, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -3591,8 +3591,8 @@ static const struct tegra_emc_table cardhu_emc_tables_k4b4g0846b_hyk0[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x8000174b, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000005, /* MC_EMEM_ARB_CFG */ - 0x80000044, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x0000000b, /* MC_EMEM_ARB_CFG */ + 0xc0000044, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000002, /* MC_EMEM_ARB_TIMING_RP */ 0x00000009, /* MC_EMEM_ARB_TIMING_RC */ @@ -3711,8 +3711,8 @@ static const struct tegra_emc_table cardhu_emc_tables_k4b4g0846b_hyk0[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x800018c8, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000006, /* MC_EMEM_ARB_CFG */ - 0x80000048, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x0000000c, /* MC_EMEM_ARB_CFG */ + 0xc0000048, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000002, /* MC_EMEM_ARB_TIMING_RP */ 0x00000009, /* MC_EMEM_ARB_TIMING_RC */ @@ -3831,8 +3831,8 @@ static const struct tegra_emc_table cardhu_emc_tables_k4b4g0846b_hyk0[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80002d93, /* EMC_DYN_SELF_REF_CONTROL */ - 0x0000000b, /* MC_EMEM_ARB_CFG */ - 0x80000087, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x00000016, /* MC_EMEM_ARB_CFG */ + 0xc0000087, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000004, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000005, /* MC_EMEM_ARB_TIMING_RP */ 0x00000012, /* MC_EMEM_ARB_TIMING_RC */ @@ -3951,8 +3951,8 @@ static const struct tegra_emc_table cardhu_emc_tables_k4b4g0846b_hyk0[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x8000308c, /* EMC_DYN_SELF_REF_CONTROL */ - 0x0000000c, /* MC_EMEM_ARB_CFG */ - 0x80000090, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x00000018, /* MC_EMEM_ARB_CFG */ + 0xc0000090, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000004, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000005, /* MC_EMEM_ARB_TIMING_RP */ 0x00000013, /* MC_EMEM_ARB_TIMING_RC */ @@ -4194,7 +4194,7 @@ static const struct tegra_emc_table cardhu_emc_tables_k4p8g304eb[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x800001c2, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00020001, /* MC_EMEM_ARB_CFG */ + 0x00030003, /* MC_EMEM_ARB_CFG */ 0xc0000008, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -4314,7 +4314,7 @@ static const struct tegra_emc_table cardhu_emc_tables_k4p8g304eb[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000287, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00010001, /* MC_EMEM_ARB_CFG */ + 0x00010003, /* MC_EMEM_ARB_CFG */ 0xc000000a, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -4434,7 +4434,7 @@ static const struct tegra_emc_table cardhu_emc_tables_k4p8g304eb[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x8000040b, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000001, /* MC_EMEM_ARB_CFG */ + 0x00000003, /* MC_EMEM_ARB_CFG */ 0xc0000013, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -4554,7 +4554,7 @@ static const struct tegra_emc_table cardhu_emc_tables_k4p8g304eb[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000713, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000003, /* MC_EMEM_ARB_CFG */ + 0x00000006, /* MC_EMEM_ARB_CFG */ 0xc0000025, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -4619,7 +4619,7 @@ static const struct tegra_emc_table cardhu_emc_tables_k4p8g304eb[] = { 0x00000004, /* EMC_TCKE */ 0x0000000e, /* EMC_TFAW */ 0x00000006, /* EMC_TRPAB */ - 0x00000001, /* EMC_TCLKSTABLE */ + 0x00000004, /* EMC_TCLKSTABLE */ 0x00000002, /* EMC_TCLKSTOP */ 0x00000455, /* EMC_TREFBW */ 0x00000000, /* EMC_QUSE_EXTRA */ @@ -4674,8 +4674,8 @@ static const struct tegra_emc_table cardhu_emc_tables_k4p8g304eb[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x800008ee, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000004, /* MC_EMEM_ARB_CFG */ - 0x80000030, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x00000008, /* MC_EMEM_ARB_CFG */ + 0xc0000030, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000002, /* MC_EMEM_ARB_TIMING_RP */ 0x00000008, /* MC_EMEM_ARB_TIMING_RC */ @@ -4794,7 +4794,7 @@ static const struct tegra_emc_table cardhu_emc_tables_k4p8g304eb[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000dff, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000006, /* MC_EMEM_ARB_CFG */ + 0x0000000d, /* MC_EMEM_ARB_CFG */ 0xc000004f, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000002, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000003, /* MC_EMEM_ARB_TIMING_RP */ @@ -4914,8 +4914,8 @@ static const struct tegra_emc_table cardhu_emc_tables_k4p8g304eb[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x800010d9, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000008, /* MC_EMEM_ARB_CFG */ - 0x80000060, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x0000000f, /* MC_EMEM_ARB_CFG */ + 0xc0000060, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000003, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000004, /* MC_EMEM_ARB_TIMING_RP */ 0x00000010, /* MC_EMEM_ARB_TIMING_RC */ @@ -5037,7 +5037,7 @@ static const struct tegra_emc_table cardhu_emc_tables_edb8132b2ma[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x800001c5, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00020001, /* MC_EMEM_ARB_CFG */ + 0x00030003, /* MC_EMEM_ARB_CFG */ 0xc0000008, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -5157,7 +5157,7 @@ static const struct tegra_emc_table cardhu_emc_tables_edb8132b2ma[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000287, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00010001, /* MC_EMEM_ARB_CFG */ + 0x00010003, /* MC_EMEM_ARB_CFG */ 0xc000000a, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -5277,7 +5277,7 @@ static const struct tegra_emc_table cardhu_emc_tables_edb8132b2ma[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x8000040b, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000001, /* MC_EMEM_ARB_CFG */ + 0x00000003, /* MC_EMEM_ARB_CFG */ 0xc0000013, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -5397,7 +5397,7 @@ static const struct tegra_emc_table cardhu_emc_tables_edb8132b2ma[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000713, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000003, /* MC_EMEM_ARB_CFG */ + 0x00000006, /* MC_EMEM_ARB_CFG */ 0xc0000025, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -5517,8 +5517,8 @@ static const struct tegra_emc_table cardhu_emc_tables_edb8132b2ma[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x800010d9, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000008, /* MC_EMEM_ARB_CFG */ - 0x80000060, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x0000000f, /* MC_EMEM_ARB_CFG */ + 0xc0000060, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000003, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000004, /* MC_EMEM_ARB_TIMING_RP */ 0x00000010, /* MC_EMEM_ARB_TIMING_RC */ @@ -5640,7 +5640,7 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_pm311[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x8000040b, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00010001, /* MC_EMEM_ARB_CFG */ + 0x00010003, /* MC_EMEM_ARB_CFG */ 0xc000000a, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -5760,7 +5760,7 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_pm311[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000713, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000001, /* MC_EMEM_ARB_CFG */ + 0x00000003, /* MC_EMEM_ARB_CFG */ 0xc0000013, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -5880,7 +5880,7 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_pm311[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000d22, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000003, /* MC_EMEM_ARB_CFG */ + 0x00000006, /* MC_EMEM_ARB_CFG */ 0xc0000025, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -6000,8 +6000,8 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_pm311[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x800014d4, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000005, /* MC_EMEM_ARB_CFG */ - 0x8000003d, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x0000000a, /* MC_EMEM_ARB_CFG */ + 0xc000003d, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000002, /* MC_EMEM_ARB_TIMING_RP */ 0x00000008, /* MC_EMEM_ARB_TIMING_RC */ @@ -6120,8 +6120,8 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_pm311[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x800028a5, /* EMC_DYN_SELF_REF_CONTROL */ - 0x0000000a, /* MC_EMEM_ARB_CFG */ - 0x80000079, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x00000014, /* MC_EMEM_ARB_CFG */ + 0xc0000079, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000003, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000004, /* MC_EMEM_ARB_TIMING_RP */ 0x00000010, /* MC_EMEM_ARB_TIMING_RC */ @@ -6151,6 +6151,609 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_pm311[] = { }, }; +static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2_2g2r[] = { + { + 0x32, /* Rev 3.2 */ + 25500, /* SDRAM frequency */ + { + 0x00000001, /* EMC_RC */ + 0x00000004, /* EMC_RFC */ + 0x00000000, /* EMC_RAS */ + 0x00000000, /* EMC_RP */ + 0x00000002, /* EMC_R2W */ + 0x0000000a, /* EMC_W2R */ + 0x00000003, /* EMC_R2P */ + 0x0000000b, /* EMC_W2P */ + 0x00000000, /* EMC_RD_RCD */ + 0x00000000, /* EMC_WR_RCD */ + 0x00000003, /* EMC_RRD */ + 0x00000001, /* EMC_REXT */ + 0x00000000, /* EMC_WEXT */ + 0x00000005, /* EMC_WDV */ + 0x00000005, /* EMC_QUSE */ + 0x00000004, /* EMC_QRST */ + 0x00000007, /* EMC_QSAFE */ + 0x0000000c, /* EMC_RDV */ + 0x000000c0, /* EMC_REFRESH */ + 0x00000000, /* EMC_BURST_REFRESH_NUM */ + 0x00000030, /* EMC_PRE_REFRESH_REQ_CNT */ + 0x00000002, /* EMC_PDEX2WR */ + 0x00000002, /* EMC_PDEX2RD */ + 0x00000001, /* EMC_PCHG2PDEN */ + 0x00000000, /* EMC_ACT2PDEN */ + 0x00000007, /* EMC_AR2PDEN */ + 0x0000000f, /* EMC_RW2PDEN */ + 0x00000005, /* EMC_TXSR */ + 0x00000005, /* EMC_TXSRDLL */ + 0x00000004, /* EMC_TCKE */ + 0x00000001, /* EMC_TFAW */ + 0x00000000, /* EMC_TRPAB */ + 0x00000004, /* EMC_TCLKSTABLE */ + 0x00000005, /* EMC_TCLKSTOP */ + 0x000000c7, /* EMC_TREFBW */ + 0x00000000, /* EMC_QUSE_EXTRA */ + 0x00000004, /* EMC_FBIO_CFG6 */ + 0x00000000, /* EMC_ODT_WRITE */ + 0x00000000, /* EMC_ODT_READ */ + 0x00006288, /* EMC_FBIO_CFG5 */ + 0x007800a4, /* EMC_CFG_DIG_DLL */ + 0x00008000, /* EMC_CFG_DIG_DLL_PERIOD */ + 0x000fc000, /* EMC_DLL_XFORM_DQS0 */ + 0x000fc000, /* EMC_DLL_XFORM_DQS1 */ + 0x000fc000, /* EMC_DLL_XFORM_DQS2 */ + 0x000fc000, /* EMC_DLL_XFORM_DQS3 */ + 0x000fc000, /* EMC_DLL_XFORM_DQS4 */ + 0x000fc000, /* EMC_DLL_XFORM_DQS5 */ + 0x000fc000, /* EMC_DLL_XFORM_DQS6 */ + 0x000fc000, /* EMC_DLL_XFORM_DQS7 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE0 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE1 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE2 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE3 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE4 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE5 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE6 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE7 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS0 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS1 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS2 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS3 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS4 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS5 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS6 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS7 */ + 0x000fc000, /* EMC_DLL_XFORM_DQ0 */ + 0x000fc000, /* EMC_DLL_XFORM_DQ1 */ + 0x000fc000, /* EMC_DLL_XFORM_DQ2 */ + 0x000fc000, /* EMC_DLL_XFORM_DQ3 */ + 0x000002a0, /* EMC_XM2CMDPADCTRL */ + 0x0800211c, /* EMC_XM2DQSPADCTRL2 */ + 0x00000000, /* EMC_XM2DQPADCTRL2 */ + 0x77fff884, /* EMC_XM2CLKPADCTRL */ + 0x01f1f108, /* EMC_XM2COMPPADCTRL */ + 0x05057404, /* EMC_XM2VTTGENPADCTRL */ + 0x54000007, /* EMC_XM2VTTGENPADCTRL2 */ + 0x08000168, /* EMC_XM2QUSEPADCTRL */ + 0x08000000, /* EMC_XM2DQSPADCTRL3 */ + 0x00000802, /* EMC_CTT_TERM_CTRL */ + 0x00000000, /* EMC_ZCAL_INTERVAL */ + 0x00000040, /* EMC_ZCAL_WAIT_CNT */ + 0x000c000c, /* EMC_MRS_WAIT_CNT */ + 0xa0f10000, /* EMC_AUTO_CAL_CONFIG */ + 0x00000000, /* EMC_CTT */ + 0x00000000, /* EMC_CTT_DURATION */ + 0x80000287, /* EMC_DYN_SELF_REF_CONTROL */ + 0x00030003, /* MC_EMEM_ARB_CFG */ + 0xc0000010, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ + 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ + 0x00000002, /* MC_EMEM_ARB_TIMING_RC */ + 0x00000000, /* MC_EMEM_ARB_TIMING_RAS */ + 0x00000001, /* MC_EMEM_ARB_TIMING_FAW */ + 0x00000001, /* MC_EMEM_ARB_TIMING_RRD */ + 0x00000002, /* MC_EMEM_ARB_TIMING_RAP2PRE */ + 0x00000008, /* MC_EMEM_ARB_TIMING_WAP2PRE */ + 0x00000002, /* MC_EMEM_ARB_TIMING_R2R */ + 0x00000001, /* MC_EMEM_ARB_TIMING_W2W */ + 0x00000002, /* MC_EMEM_ARB_TIMING_R2W */ + 0x00000006, /* MC_EMEM_ARB_TIMING_W2R */ + 0x06020102, /* MC_EMEM_ARB_DA_TURNS */ + 0x000a0402, /* MC_EMEM_ARB_DA_COVERS */ + 0x74830303, /* MC_EMEM_ARB_MISC0 */ + 0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */ + 0xd8000000, /* EMC_FBIO_SPARE */ + 0xff00ff00, /* EMC_CFG_RSV */ + }, + 0x00000040, /* EMC_ZCAL_WAIT_CNT after clock change */ + 0x001fffff, /* EMC_AUTO_CAL_INTERVAL */ + 0x00000000, /* EMC_CFG.PERIODIC_QRST */ + 0x00001221, /* Mode Register 0 */ + 0x00100003, /* Mode Register 1 */ + 0x00200008, /* Mode Register 2 */ + 0x00000001, /* EMC_CFG.DYN_SELF_REF */ + }, + { + 0x32, /* Rev 3.2 */ + 51000, /* SDRAM frequency */ + { + 0x00000002, /* EMC_RC */ + 0x00000008, /* EMC_RFC */ + 0x00000001, /* EMC_RAS */ + 0x00000000, /* EMC_RP */ + 0x00000002, /* EMC_R2W */ + 0x0000000a, /* EMC_W2R */ + 0x00000003, /* EMC_R2P */ + 0x0000000b, /* EMC_W2P */ + 0x00000000, /* EMC_RD_RCD */ + 0x00000000, /* EMC_WR_RCD */ + 0x00000003, /* EMC_RRD */ + 0x00000001, /* EMC_REXT */ + 0x00000000, /* EMC_WEXT */ + 0x00000005, /* EMC_WDV */ + 0x00000005, /* EMC_QUSE */ + 0x00000004, /* EMC_QRST */ + 0x00000007, /* EMC_QSAFE */ + 0x0000000c, /* EMC_RDV */ + 0x00000181, /* EMC_REFRESH */ + 0x00000000, /* EMC_BURST_REFRESH_NUM */ + 0x00000060, /* EMC_PRE_REFRESH_REQ_CNT */ + 0x00000002, /* EMC_PDEX2WR */ + 0x00000002, /* EMC_PDEX2RD */ + 0x00000001, /* EMC_PCHG2PDEN */ + 0x00000000, /* EMC_ACT2PDEN */ + 0x00000007, /* EMC_AR2PDEN */ + 0x0000000f, /* EMC_RW2PDEN */ + 0x00000009, /* EMC_TXSR */ + 0x00000009, /* EMC_TXSRDLL */ + 0x00000004, /* EMC_TCKE */ + 0x00000002, /* EMC_TFAW */ + 0x00000000, /* EMC_TRPAB */ + 0x00000004, /* EMC_TCLKSTABLE */ + 0x00000005, /* EMC_TCLKSTOP */ + 0x0000018e, /* EMC_TREFBW */ + 0x00000000, /* EMC_QUSE_EXTRA */ + 0x00000004, /* EMC_FBIO_CFG6 */ + 0x00000000, /* EMC_ODT_WRITE */ + 0x00000000, /* EMC_ODT_READ */ + 0x00006288, /* EMC_FBIO_CFG5 */ + 0x007800a4, /* EMC_CFG_DIG_DLL */ + 0x00008000, /* EMC_CFG_DIG_DLL_PERIOD */ + 0x000fc000, /* EMC_DLL_XFORM_DQS0 */ + 0x000fc000, /* EMC_DLL_XFORM_DQS1 */ + 0x000fc000, /* EMC_DLL_XFORM_DQS2 */ + 0x000fc000, /* EMC_DLL_XFORM_DQS3 */ + 0x000fc000, /* EMC_DLL_XFORM_DQS4 */ + 0x000fc000, /* EMC_DLL_XFORM_DQS5 */ + 0x000fc000, /* EMC_DLL_XFORM_DQS6 */ + 0x000fc000, /* EMC_DLL_XFORM_DQS7 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE0 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE1 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE2 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE3 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE4 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE5 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE6 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE7 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS0 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS1 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS2 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS3 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS4 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS5 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS6 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS7 */ + 0x000fc000, /* EMC_DLL_XFORM_DQ0 */ + 0x000fc000, /* EMC_DLL_XFORM_DQ1 */ + 0x000fc000, /* EMC_DLL_XFORM_DQ2 */ + 0x000fc000, /* EMC_DLL_XFORM_DQ3 */ + 0x000002a0, /* EMC_XM2CMDPADCTRL */ + 0x0800211c, /* EMC_XM2DQSPADCTRL2 */ + 0x00000000, /* EMC_XM2DQPADCTRL2 */ + 0x77fff884, /* EMC_XM2CLKPADCTRL */ + 0x01f1f108, /* EMC_XM2COMPPADCTRL */ + 0x05057404, /* EMC_XM2VTTGENPADCTRL */ + 0x54000007, /* EMC_XM2VTTGENPADCTRL2 */ + 0x08000168, /* EMC_XM2QUSEPADCTRL */ + 0x08000000, /* EMC_XM2DQSPADCTRL3 */ + 0x00000802, /* EMC_CTT_TERM_CTRL */ + 0x00000000, /* EMC_ZCAL_INTERVAL */ + 0x00000040, /* EMC_ZCAL_WAIT_CNT */ + 0x000c000c, /* EMC_MRS_WAIT_CNT */ + 0xa0f10000, /* EMC_AUTO_CAL_CONFIG */ + 0x00000000, /* EMC_CTT */ + 0x00000000, /* EMC_CTT_DURATION */ + 0x8000040b, /* EMC_DYN_SELF_REF_CONTROL */ + 0x00010003, /* MC_EMEM_ARB_CFG */ + 0xc0000010, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ + 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ + 0x00000002, /* MC_EMEM_ARB_TIMING_RC */ + 0x00000000, /* MC_EMEM_ARB_TIMING_RAS */ + 0x00000001, /* MC_EMEM_ARB_TIMING_FAW */ + 0x00000001, /* MC_EMEM_ARB_TIMING_RRD */ + 0x00000002, /* MC_EMEM_ARB_TIMING_RAP2PRE */ + 0x00000008, /* MC_EMEM_ARB_TIMING_WAP2PRE */ + 0x00000002, /* MC_EMEM_ARB_TIMING_R2R */ + 0x00000001, /* MC_EMEM_ARB_TIMING_W2W */ + 0x00000002, /* MC_EMEM_ARB_TIMING_R2W */ + 0x00000006, /* MC_EMEM_ARB_TIMING_W2R */ + 0x06020102, /* MC_EMEM_ARB_DA_TURNS */ + 0x000a0402, /* MC_EMEM_ARB_DA_COVERS */ + 0x73430303, /* MC_EMEM_ARB_MISC0 */ + 0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */ + 0xd8000000, /* EMC_FBIO_SPARE */ + 0xff00ff00, /* EMC_CFG_RSV */ + }, + 0x00000040, /* EMC_ZCAL_WAIT_CNT after clock change */ + 0x001fffff, /* EMC_AUTO_CAL_INTERVAL */ + 0x00000000, /* EMC_CFG.PERIODIC_QRST */ + 0x00001221, /* Mode Register 0 */ + 0x00100003, /* Mode Register 1 */ + 0x00200008, /* Mode Register 2 */ + 0x00000001, /* EMC_CFG.DYN_SELF_REF */ + }, + { + 0x32, /* Rev 3.2 */ + 102000, /* SDRAM frequency */ + { + 0x00000004, /* EMC_RC */ + 0x00000010, /* EMC_RFC */ + 0x00000003, /* EMC_RAS */ + 0x00000001, /* EMC_RP */ + 0x00000002, /* EMC_R2W */ + 0x0000000a, /* EMC_W2R */ + 0x00000003, /* EMC_R2P */ + 0x0000000b, /* EMC_W2P */ + 0x00000001, /* EMC_RD_RCD */ + 0x00000001, /* EMC_WR_RCD */ + 0x00000003, /* EMC_RRD */ + 0x00000001, /* EMC_REXT */ + 0x00000000, /* EMC_WEXT */ + 0x00000005, /* EMC_WDV */ + 0x00000005, /* EMC_QUSE */ + 0x00000004, /* EMC_QRST */ + 0x00000007, /* EMC_QSAFE */ + 0x0000000c, /* EMC_RDV */ + 0x00000303, /* EMC_REFRESH */ + 0x00000000, /* EMC_BURST_REFRESH_NUM */ + 0x000000c0, /* EMC_PRE_REFRESH_REQ_CNT */ + 0x00000002, /* EMC_PDEX2WR */ + 0x00000002, /* EMC_PDEX2RD */ + 0x00000001, /* EMC_PCHG2PDEN */ + 0x00000000, /* EMC_ACT2PDEN */ + 0x00000007, /* EMC_AR2PDEN */ + 0x0000000f, /* EMC_RW2PDEN */ + 0x00000012, /* EMC_TXSR */ + 0x00000012, /* EMC_TXSRDLL */ + 0x00000004, /* EMC_TCKE */ + 0x00000004, /* EMC_TFAW */ + 0x00000000, /* EMC_TRPAB */ + 0x00000004, /* EMC_TCLKSTABLE */ + 0x00000005, /* EMC_TCLKSTOP */ + 0x0000031c, /* EMC_TREFBW */ + 0x00000000, /* EMC_QUSE_EXTRA */ + 0x00000004, /* EMC_FBIO_CFG6 */ + 0x00000000, /* EMC_ODT_WRITE */ + 0x00000000, /* EMC_ODT_READ */ + 0x00006288, /* EMC_FBIO_CFG5 */ + 0x007800a4, /* EMC_CFG_DIG_DLL */ + 0x00008000, /* EMC_CFG_DIG_DLL_PERIOD */ + 0x000fc000, /* EMC_DLL_XFORM_DQS0 */ + 0x000fc000, /* EMC_DLL_XFORM_DQS1 */ + 0x000fc000, /* EMC_DLL_XFORM_DQS2 */ + 0x000fc000, /* EMC_DLL_XFORM_DQS3 */ + 0x000fc000, /* EMC_DLL_XFORM_DQS4 */ + 0x000fc000, /* EMC_DLL_XFORM_DQS5 */ + 0x000fc000, /* EMC_DLL_XFORM_DQS6 */ + 0x000fc000, /* EMC_DLL_XFORM_DQS7 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE0 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE1 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE2 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE3 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE4 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE5 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE6 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE7 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS0 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS1 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS2 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS3 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS4 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS5 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS6 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS7 */ + 0x000fc000, /* EMC_DLL_XFORM_DQ0 */ + 0x000fc000, /* EMC_DLL_XFORM_DQ1 */ + 0x000fc000, /* EMC_DLL_XFORM_DQ2 */ + 0x000fc000, /* EMC_DLL_XFORM_DQ3 */ + 0x000002a0, /* EMC_XM2CMDPADCTRL */ + 0x0800211c, /* EMC_XM2DQSPADCTRL2 */ + 0x00000000, /* EMC_XM2DQPADCTRL2 */ + 0x77fff884, /* EMC_XM2CLKPADCTRL */ + 0x01f1f108, /* EMC_XM2COMPPADCTRL */ + 0x05057404, /* EMC_XM2VTTGENPADCTRL */ + 0x54000007, /* EMC_XM2VTTGENPADCTRL2 */ + 0x08000168, /* EMC_XM2QUSEPADCTRL */ + 0x08000000, /* EMC_XM2DQSPADCTRL3 */ + 0x00000802, /* EMC_CTT_TERM_CTRL */ + 0x00000000, /* EMC_ZCAL_INTERVAL */ + 0x00000040, /* EMC_ZCAL_WAIT_CNT */ + 0x000c000c, /* EMC_MRS_WAIT_CNT */ + 0xa0f10000, /* EMC_AUTO_CAL_CONFIG */ + 0x00000000, /* EMC_CTT */ + 0x00000000, /* EMC_CTT_DURATION */ + 0x80000713, /* EMC_DYN_SELF_REF_CONTROL */ + 0x00000003, /* MC_EMEM_ARB_CFG */ + 0xc0000018, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ + 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ + 0x00000003, /* MC_EMEM_ARB_TIMING_RC */ + 0x00000000, /* MC_EMEM_ARB_TIMING_RAS */ + 0x00000001, /* MC_EMEM_ARB_TIMING_FAW */ + 0x00000001, /* MC_EMEM_ARB_TIMING_RRD */ + 0x00000002, /* MC_EMEM_ARB_TIMING_RAP2PRE */ + 0x00000008, /* MC_EMEM_ARB_TIMING_WAP2PRE */ + 0x00000002, /* MC_EMEM_ARB_TIMING_R2R */ + 0x00000001, /* MC_EMEM_ARB_TIMING_W2W */ + 0x00000002, /* MC_EMEM_ARB_TIMING_R2W */ + 0x00000006, /* MC_EMEM_ARB_TIMING_W2R */ + 0x06020102, /* MC_EMEM_ARB_DA_TURNS */ + 0x000a0403, /* MC_EMEM_ARB_DA_COVERS */ + 0x72830504, /* MC_EMEM_ARB_MISC0 */ + 0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */ + 0xd8000000, /* EMC_FBIO_SPARE */ + 0xff00ff00, /* EMC_CFG_RSV */ + }, + 0x00000040, /* EMC_ZCAL_WAIT_CNT after clock change */ + 0x001fffff, /* EMC_AUTO_CAL_INTERVAL */ + 0x00000000, /* EMC_CFG.PERIODIC_QRST */ + 0x00001221, /* Mode Register 0 */ + 0x00100003, /* Mode Register 1 */ + 0x00200008, /* Mode Register 2 */ + 0x00000001, /* EMC_CFG.DYN_SELF_REF */ + }, + { + 0x32, /* Rev 3.2 */ + 333500, /* SDRAM frequency */ + { + 0x0000000f, /* EMC_RC */ + 0x00000034, /* EMC_RFC */ + 0x0000000a, /* EMC_RAS */ + 0x00000003, /* EMC_RP */ + 0x00000003, /* EMC_R2W */ + 0x00000008, /* EMC_W2R */ + 0x00000002, /* EMC_R2P */ + 0x00000009, /* EMC_W2P */ + 0x00000003, /* EMC_RD_RCD */ + 0x00000003, /* EMC_WR_RCD */ + 0x00000002, /* EMC_RRD */ + 0x00000001, /* EMC_REXT */ + 0x00000000, /* EMC_WEXT */ + 0x00000004, /* EMC_WDV */ + 0x00000006, /* EMC_QUSE */ + 0x00000004, /* EMC_QRST */ + 0x0000000a, /* EMC_QSAFE */ + 0x0000000c, /* EMC_RDV */ + 0x000009e9, /* EMC_REFRESH */ + 0x00000000, /* EMC_BURST_REFRESH_NUM */ + 0x0000027a, /* EMC_PRE_REFRESH_REQ_CNT */ + 0x00000001, /* EMC_PDEX2WR */ + 0x00000008, /* EMC_PDEX2RD */ + 0x00000001, /* EMC_PCHG2PDEN */ + 0x00000000, /* EMC_ACT2PDEN */ + 0x00000007, /* EMC_AR2PDEN */ + 0x0000000e, /* EMC_RW2PDEN */ + 0x00000039, /* EMC_TXSR */ + 0x00000200, /* EMC_TXSRDLL */ + 0x00000004, /* EMC_TCKE */ + 0x0000000a, /* EMC_TFAW */ + 0x00000000, /* EMC_TRPAB */ + 0x00000004, /* EMC_TCLKSTABLE */ + 0x00000005, /* EMC_TCLKSTOP */ + 0x00000a2a, /* EMC_TREFBW */ + 0x00000000, /* EMC_QUSE_EXTRA */ + 0x00000006, /* EMC_FBIO_CFG6 */ + 0x00000000, /* EMC_ODT_WRITE */ + 0x00000000, /* EMC_ODT_READ */ + 0x00007088, /* EMC_FBIO_CFG5 */ + 0x00260084, /* EMC_CFG_DIG_DLL */ + 0x00008000, /* EMC_CFG_DIG_DLL_PERIOD */ + 0x00028000, /* EMC_DLL_XFORM_DQS0 */ + 0x00028000, /* EMC_DLL_XFORM_DQS1 */ + 0x00028000, /* EMC_DLL_XFORM_DQS2 */ + 0x00028000, /* EMC_DLL_XFORM_DQS3 */ + 0x00028000, /* EMC_DLL_XFORM_DQS4 */ + 0x00028000, /* EMC_DLL_XFORM_DQS5 */ + 0x00028000, /* EMC_DLL_XFORM_DQS6 */ + 0x00028000, /* EMC_DLL_XFORM_DQS7 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE0 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE1 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE2 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE3 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE4 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE5 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE6 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE7 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS0 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS1 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS2 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS3 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS4 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS5 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS6 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS7 */ + 0x0004c000, /* EMC_DLL_XFORM_DQ0 */ + 0x0004c000, /* EMC_DLL_XFORM_DQ1 */ + 0x0004c000, /* EMC_DLL_XFORM_DQ2 */ + 0x0004c000, /* EMC_DLL_XFORM_DQ3 */ + 0x000002a0, /* EMC_XM2CMDPADCTRL */ + 0x0800013d, /* EMC_XM2DQSPADCTRL2 */ + 0x00000000, /* EMC_XM2DQPADCTRL2 */ + 0x77fff884, /* EMC_XM2CLKPADCTRL */ + 0x01f1f508, /* EMC_XM2COMPPADCTRL */ + 0x05057404, /* EMC_XM2VTTGENPADCTRL */ + 0x54000007, /* EMC_XM2VTTGENPADCTRL2 */ + 0x080001e8, /* EMC_XM2QUSEPADCTRL */ + 0x08000021, /* EMC_XM2DQSPADCTRL3 */ + 0x00000802, /* EMC_CTT_TERM_CTRL */ + 0x00020000, /* EMC_ZCAL_INTERVAL */ + 0x00000100, /* EMC_ZCAL_WAIT_CNT */ + 0x014b000c, /* EMC_MRS_WAIT_CNT */ + 0xa0f10000, /* EMC_AUTO_CAL_CONFIG */ + 0x00000000, /* EMC_CTT */ + 0x00000000, /* EMC_CTT_DURATION */ + 0x800014d4, /* EMC_DYN_SELF_REF_CONTROL */ + 0x0000000a, /* MC_EMEM_ARB_CFG */ + 0xc000003d, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ + 0x00000002, /* MC_EMEM_ARB_TIMING_RP */ + 0x00000008, /* MC_EMEM_ARB_TIMING_RC */ + 0x00000004, /* MC_EMEM_ARB_TIMING_RAS */ + 0x00000004, /* MC_EMEM_ARB_TIMING_FAW */ + 0x00000001, /* MC_EMEM_ARB_TIMING_RRD */ + 0x00000002, /* MC_EMEM_ARB_TIMING_RAP2PRE */ + 0x00000007, /* MC_EMEM_ARB_TIMING_WAP2PRE */ + 0x00000002, /* MC_EMEM_ARB_TIMING_R2R */ + 0x00000002, /* MC_EMEM_ARB_TIMING_W2W */ + 0x00000003, /* MC_EMEM_ARB_TIMING_R2W */ + 0x00000006, /* MC_EMEM_ARB_TIMING_W2R */ + 0x06030202, /* MC_EMEM_ARB_DA_TURNS */ + 0x000b0608, /* MC_EMEM_ARB_DA_COVERS */ + 0x70850f09, /* MC_EMEM_ARB_MISC0 */ + 0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */ + 0xe8000000, /* EMC_FBIO_SPARE */ + 0xff00ff88, /* EMC_CFG_RSV */ + }, + 0x00000040, /* EMC_ZCAL_WAIT_CNT after clock change */ + 0x001fffff, /* EMC_AUTO_CAL_INTERVAL */ + 0x00000000, /* EMC_CFG.PERIODIC_QRST */ + 0x00000321, /* Mode Register 0 */ + 0x00100002, /* Mode Register 1 */ + 0x00200000, /* Mode Register 2 */ + 0x00000000, /* EMC_CFG.DYN_SELF_REF */ + }, + { + 0x32, /* Rev 3.2 */ + 667000, /* SDRAM frequency */ + { + 0x0000001f, /* EMC_RC */ + 0x00000069, /* EMC_RFC */ + 0x00000016, /* EMC_RAS */ + 0x00000008, /* EMC_RP */ + 0x00000005, /* EMC_R2W */ + 0x0000000c, /* EMC_W2R */ + 0x00000003, /* EMC_R2P */ + 0x00000011, /* EMC_W2P */ + 0x00000008, /* EMC_RD_RCD */ + 0x00000008, /* EMC_WR_RCD */ + 0x00000002, /* EMC_RRD */ + 0x00000001, /* EMC_REXT */ + 0x00000000, /* EMC_WEXT */ + 0x00000007, /* EMC_WDV */ + 0x0000000b, /* EMC_QUSE */ + 0x00000009, /* EMC_QRST */ + 0x0000000c, /* EMC_QSAFE */ + 0x00000011, /* EMC_RDV */ + 0x00001412, /* EMC_REFRESH */ + 0x00000000, /* EMC_BURST_REFRESH_NUM */ + 0x00000504, /* EMC_PRE_REFRESH_REQ_CNT */ + 0x00000002, /* EMC_PDEX2WR */ + 0x0000000e, /* EMC_PDEX2RD */ + 0x00000001, /* EMC_PCHG2PDEN */ + 0x00000000, /* EMC_ACT2PDEN */ + 0x0000000c, /* EMC_AR2PDEN */ + 0x00000016, /* EMC_RW2PDEN */ + 0x00000072, /* EMC_TXSR */ + 0x00000200, /* EMC_TXSRDLL */ + 0x00000005, /* EMC_TCKE */ + 0x00000015, /* EMC_TFAW */ + 0x00000000, /* EMC_TRPAB */ + 0x00000006, /* EMC_TCLKSTABLE */ + 0x00000007, /* EMC_TCLKSTOP */ + 0x00001453, /* EMC_TREFBW */ + 0x0000000c, /* EMC_QUSE_EXTRA */ + 0x00000004, /* EMC_FBIO_CFG6 */ + 0x00000000, /* EMC_ODT_WRITE */ + 0x00000000, /* EMC_ODT_READ */ + 0x00005088, /* EMC_FBIO_CFG5 */ + 0xf00b0191, /* EMC_CFG_DIG_DLL */ + 0x00008000, /* EMC_CFG_DIG_DLL_PERIOD */ + 0x00000008, /* EMC_DLL_XFORM_DQS0 */ + 0x00000008, /* EMC_DLL_XFORM_DQS1 */ + 0x00000008, /* EMC_DLL_XFORM_DQS2 */ + 0x00000008, /* EMC_DLL_XFORM_DQS3 */ + 0x00000008, /* EMC_DLL_XFORM_DQS4 */ + 0x00000008, /* EMC_DLL_XFORM_DQS5 */ + 0x00000008, /* EMC_DLL_XFORM_DQS6 */ + 0x00000008, /* EMC_DLL_XFORM_DQS7 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE0 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE1 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE2 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE3 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE4 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE5 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE6 */ + 0x00000000, /* EMC_DLL_XFORM_QUSE7 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS0 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS1 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS2 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS3 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS4 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS5 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS6 */ + 0x00000000, /* EMC_DLI_TRIM_TXDQS7 */ + 0x00000008, /* EMC_DLL_XFORM_DQ0 */ + 0x00000008, /* EMC_DLL_XFORM_DQ1 */ + 0x00000008, /* EMC_DLL_XFORM_DQ2 */ + 0x00000008, /* EMC_DLL_XFORM_DQ3 */ + 0x000002a0, /* EMC_XM2CMDPADCTRL */ + 0x0600013d, /* EMC_XM2DQSPADCTRL2 */ + 0x00000000, /* EMC_XM2DQPADCTRL2 */ + 0x77fff884, /* EMC_XM2CLKPADCTRL */ + 0x01f1f508, /* EMC_XM2COMPPADCTRL */ + 0x07077404, /* EMC_XM2VTTGENPADCTRL */ + 0x54000000, /* EMC_XM2VTTGENPADCTRL2 */ + 0x080001e8, /* EMC_XM2QUSEPADCTRL */ + 0x07000021, /* EMC_XM2DQSPADCTRL3 */ + 0x00000802, /* EMC_CTT_TERM_CTRL */ + 0x00020000, /* EMC_ZCAL_INTERVAL */ + 0x00000100, /* EMC_ZCAL_WAIT_CNT */ + 0x0116000c, /* EMC_MRS_WAIT_CNT */ + 0xa0f10000, /* EMC_AUTO_CAL_CONFIG */ + 0x00000000, /* EMC_CTT */ + 0x00000000, /* EMC_CTT_DURATION */ + 0x800028a5, /* EMC_DYN_SELF_REF_CONTROL */ + 0x00000014, /* MC_EMEM_ARB_CFG */ + 0xc0000079, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x00000003, /* MC_EMEM_ARB_TIMING_RCD */ + 0x00000004, /* MC_EMEM_ARB_TIMING_RP */ + 0x00000010, /* MC_EMEM_ARB_TIMING_RC */ + 0x0000000a, /* MC_EMEM_ARB_TIMING_RAS */ + 0x0000000a, /* MC_EMEM_ARB_TIMING_FAW */ + 0x00000001, /* MC_EMEM_ARB_TIMING_RRD */ + 0x00000003, /* MC_EMEM_ARB_TIMING_RAP2PRE */ + 0x0000000b, /* MC_EMEM_ARB_TIMING_WAP2PRE */ + 0x00000002, /* MC_EMEM_ARB_TIMING_R2R */ + 0x00000002, /* MC_EMEM_ARB_TIMING_W2W */ + 0x00000004, /* MC_EMEM_ARB_TIMING_R2W */ + 0x00000008, /* MC_EMEM_ARB_TIMING_W2R */ + 0x08040202, /* MC_EMEM_ARB_DA_TURNS */ + 0x00140c10, /* MC_EMEM_ARB_DA_COVERS */ + 0x70ea1f11, /* MC_EMEM_ARB_MISC0 */ + 0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */ + 0xf8000000, /* EMC_FBIO_SPARE */ + 0xff00ff01, /* EMC_CFG_RSV */ + }, + 0x00000040, /* EMC_ZCAL_WAIT_CNT after clock change */ + 0x001fffff, /* EMC_AUTO_CAL_INTERVAL */ + 0x00000001, /* EMC_CFG.PERIODIC_QRST */ + 0x00000b71, /* Mode Register 0 */ + 0x00100002, /* Mode Register 1 */ + 0x00200018, /* Mode Register 2 */ + 0x00000000, /* EMC_CFG.DYN_SELF_REF */ + }, +}; + static const u32 pm269_bit_swap_map[32] = { /* DDR bit # SoC bit # */ [0] = 0x1 << 1, @@ -6231,6 +6834,9 @@ int cardhu_emc_init(void) SKU_MEMORY_CARDHU_2GB_1R_HYNIX) tegra_init_emc(cardhu_emc_tables_h5tc2g_a2_2GB1R, ARRAY_SIZE(cardhu_emc_tables_h5tc2g_a2_2GB1R)); + else if (MEMORY_TYPE(board.sku) == SKU_MEMORY_CARDHU_2GB_2R) + tegra_init_emc(cardhu_emc_tables_h5tc2g_a2_2g2r, + ARRAY_SIZE(cardhu_emc_tables_h5tc2g_a2_2g2r)); break; } diff --git a/arch/arm/mach-tegra/board-cardhu-panel.c b/arch/arm/mach-tegra/board-cardhu-panel.c index 6fa33f919dad..d7101af55712 100644 --- a/arch/arm/mach-tegra/board-cardhu-panel.c +++ b/arch/arm/mach-tegra/board-cardhu-panel.c @@ -678,7 +678,11 @@ static struct tegra_fb_data cardhu_fb_data = { .win = 0, .xres = 1366, .yres = 768, +#ifdef CONFIG_TEGRA_DC_USE_HW_BPP + .bits_per_pixel = -1, +#else .bits_per_pixel = 32, +#endif .flags = TEGRA_FB_FLIP_ON_PROBE, }; @@ -686,7 +690,11 @@ static struct tegra_fb_data cardhu_hdmi_fb_data = { .win = 0, .xres = 640, .yres = 480, +#ifdef CONFIG_TEGRA_DC_USE_HW_BPP + .bits_per_pixel = -1, +#else .bits_per_pixel = 32, +#endif .flags = TEGRA_FB_FLIP_ON_PROBE, }; @@ -873,13 +881,9 @@ static int cardhu_dsi_panel_disable(void) } else if (is_panel_218) { gpio_free(cardhu_dsi_pnl_reset); } else if (is_panel_1506) { - tegra_gpio_disable(e1506_bl_enb); gpio_free(e1506_bl_enb); - tegra_gpio_disable(cardhu_dsi_pnl_reset); gpio_free(cardhu_dsi_pnl_reset); - tegra_gpio_disable(e1506_panel_enb); gpio_free(e1506_panel_enb); - tegra_gpio_disable(e1506_dsi_vddio); gpio_free(e1506_dsi_vddio); } return err; @@ -1213,11 +1217,19 @@ static void cardhu_panel_early_suspend(struct early_suspend *h) fb_blank(registered_fb[0], FB_BLANK_POWERDOWN); if (num_registered_fb > 1) fb_blank(registered_fb[1], FB_BLANK_NORMAL); + +#ifdef CONFIG_TEGRA_CONVSERVATIVE_GOV_ON_EARLYSUPSEND + cpufreq_store_default_gov(); + cpufreq_change_gov(cpufreq_conservative_gov); +#endif } static void cardhu_panel_late_resume(struct early_suspend *h) { unsigned i; +#ifdef CONFIG_TEGRA_CONVSERVATIVE_GOV_ON_EARLYSUPSEND + cpufreq_restore_default_gov(); +#endif for (i = 0; i < num_registered_fb; i++) fb_blank(registered_fb[i], FB_BLANK_UNBLANK); } @@ -1241,6 +1253,9 @@ static void cardhu_panel_preinit(void) cardhu_disp1_out.n_modes = ARRAY_SIZE(cardhu_panel_modes); cardhu_disp1_out.enable = cardhu_panel_enable; cardhu_disp1_out.disable = cardhu_panel_disable; + /* Set height and width in mm. */ + cardhu_disp1_out.height = 125; + cardhu_disp1_out.width = 223; cardhu_disp1_pdata.fb = &cardhu_fb_data; } else { @@ -1262,12 +1277,18 @@ static void cardhu_panel_preinit(void) ARRAY_SIZE(cardhu_dsi_modes_218); cardhu_dsi_fb_data.xres = 864; cardhu_dsi_fb_data.yres = 480; + /* Set height and width in mm. */ + cardhu_disp1_out.height = 47; + cardhu_disp1_out.width = 84; } else if (is_panel_219) { cardhu_disp1_out.modes = cardhu_dsi_modes_219; cardhu_disp1_out.n_modes = ARRAY_SIZE(cardhu_dsi_modes_219); cardhu_dsi_fb_data.xres = 540; cardhu_dsi_fb_data.yres = 960; + /* Set height and width in mm. */ + cardhu_disp1_out.height = 95; + cardhu_disp1_out.width = 53; } else if (is_panel_1506) { cardhu_disp1_out.modes = cardhu_dsi_modes_1506; cardhu_disp1_out.n_modes = @@ -1277,9 +1298,13 @@ static void cardhu_panel_preinit(void) cardhu_dsi.n_suspend_cmd = ARRAY_SIZE(dsi_suspend_cmd_1506); cardhu_dsi.dsi_suspend_cmd = dsi_suspend_cmd_1506; - cardhu_dsi.panel_send_dc_frames = true, + cardhu_dsi.panel_send_dc_frames = true; + cardhu_dsi.suspend_aggr = DSI_HOST_SUSPEND_LV0; cardhu_dsi_fb_data.xres = 720; cardhu_dsi_fb_data.yres = 1280; + /* Set height and width in mm. */ + cardhu_disp1_out.height = 95; + cardhu_disp1_out.width = 53; } cardhu_disp1_pdata.fb = &cardhu_dsi_fb_data; @@ -1328,6 +1353,9 @@ int __init cardhu_panel_init(void) #else cardhu_disp1_out.depth = 24; #endif + /* Set height and width in mm. */ + cardhu_disp1_out.height = 135; + cardhu_disp1_out.width = 217; cardhu_fb_data.xres = 1920; cardhu_fb_data.yres = 1200; @@ -1376,7 +1404,6 @@ skip_lvds: gpio_direction_input(cardhu_hdmi_hpd); #if !(DC_CTRL_MODE & TEGRA_DC_OUT_ONE_SHOT_MODE) - tegra_gpio_enable(e1506_lcd_te); gpio_request(e1506_lcd_te, "lcd_te"); gpio_direction_input(e1506_lcd_te); #endif diff --git a/arch/arm/mach-tegra/board-cardhu-pinmux.c b/arch/arm/mach-tegra/board-cardhu-pinmux.c index 7b98af0f167c..346dccfd715b 100644 --- a/arch/arm/mach-tegra/board-cardhu-pinmux.c +++ b/arch/arm/mach-tegra/board-cardhu-pinmux.c @@ -482,6 +482,9 @@ static __initdata struct tegra_pingroup_config cardhu_pinmux_cardhu_a03[] = { DEFAULT_PINMUX(PEX_L0_CLKREQ_N, PCIE, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(PEX_L1_CLKREQ_N, RSVD3, PULL_UP, NORMAL, INPUT), DEFAULT_PINMUX(PEX_L1_PRSNT_N, RSVD3, PULL_UP, NORMAL, INPUT), + + /*PCIE dock detect*/ + DEFAULT_PINMUX(GPIO_PU4, RSVD1, PULL_UP, NORMAL, INPUT), }; static __initdata struct tegra_pingroup_config cardhu_pinmux_e1291_a04[] = { @@ -489,6 +492,9 @@ static __initdata struct tegra_pingroup_config cardhu_pinmux_e1291_a04[] = { DEFAULT_PINMUX(ULPI_DATA6, UARTA, NORMAL, NORMAL, OUTPUT), DEFAULT_PINMUX(SPI2_MOSI, SPI6, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(DAP3_SCLK, RSVD1, NORMAL, NORMAL, OUTPUT), + + /*PCIE dock detect*/ + DEFAULT_PINMUX(GPIO_PU4, RSVD1, PULL_UP, NORMAL, INPUT), }; static __initdata struct tegra_pingroup_config cardhu_pinmux_e1198[] = { @@ -536,6 +542,48 @@ static __initdata struct tegra_pingroup_config unused_pins_lowpower[] = { DEFAULT_PINMUX(GMI_DQS, NAND, NORMAL, TRISTATE, OUTPUT), }; +static __initdata struct tegra_pingroup_config unused_pins_lowpower_e1506[] = { + DEFAULT_PINMUX(LCD_D0, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D1, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D2, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D3, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D4, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D5, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D6, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D7, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D8, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D9, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D10, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D11, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D12, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D13, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D14, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D15, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D16, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D17, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D18, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D19, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D20, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D21, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D22, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D23, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + + DEFAULT_PINMUX(LCD_DC0, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_PWR0, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_PWR1, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_PWR2, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_CS0_N, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_CS1_N, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + + DEFAULT_PINMUX(LCD_PCLK, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_WR_N, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_HSYNC, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_VSYNC, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_SCK, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_SDOUT, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_SDIN, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), +}; + static __initdata struct tegra_pingroup_config gmi_pins_269[] = { /* Continuation of table unused_pins_lowpower only for PM269 */ DEFAULT_PINMUX(GMI_CS0_N, NAND, PULL_UP, NORMAL, OUTPUT), @@ -686,6 +734,8 @@ int __init cardhu_pinmux_init(void) if (display_board_info.board_id == BOARD_DISPLAY_E1506) { tegra_pinmux_config_table(cardhu_pinmux_pm269_e1506, ARRAY_SIZE(cardhu_pinmux_pm269_e1506)); + tegra_pinmux_config_table(unused_pins_lowpower_e1506, + ARRAY_SIZE(unused_pins_lowpower_e1506)); } tegra_pinmux_config_table(unused_pins_lowpower, @@ -749,6 +799,47 @@ struct gpio_init_pin_info vddio_gmi_pins_pm269_e1506[] = { PIN_GPIO_LPM("GMI_CS2", TEGRA_GPIO_PK3, 1, 0), }; +static struct gpio_init_pin_info cardhu_unused_gpio_pins_e1506[] = { + PIN_GPIO_LPM("LCD_D0", TEGRA_GPIO_PE0, 0, 0), + PIN_GPIO_LPM("LCD_D1", TEGRA_GPIO_PE1, 0, 0), + PIN_GPIO_LPM("LCD_D2", TEGRA_GPIO_PE2, 0, 0), + PIN_GPIO_LPM("LCD_D3", TEGRA_GPIO_PE3, 0, 0), + PIN_GPIO_LPM("LCD_D4", TEGRA_GPIO_PE4, 0, 0), + PIN_GPIO_LPM("LCD_D5", TEGRA_GPIO_PE5, 0, 0), + PIN_GPIO_LPM("LCD_D6", TEGRA_GPIO_PE6, 0, 0), + PIN_GPIO_LPM("LCD_D7", TEGRA_GPIO_PE7, 0, 0), + PIN_GPIO_LPM("LCD_D8", TEGRA_GPIO_PF0, 0, 0), + PIN_GPIO_LPM("LCD_D9", TEGRA_GPIO_PF1, 0, 0), + PIN_GPIO_LPM("LCD_D10", TEGRA_GPIO_PF2, 0, 0), + PIN_GPIO_LPM("LCD_D11", TEGRA_GPIO_PF3, 0, 0), + PIN_GPIO_LPM("LCD_D12", TEGRA_GPIO_PF4, 0, 0), + PIN_GPIO_LPM("LCD_D13", TEGRA_GPIO_PF5, 0, 0), + PIN_GPIO_LPM("LCD_D14", TEGRA_GPIO_PF6, 0, 0), + PIN_GPIO_LPM("LCD_D15", TEGRA_GPIO_PF7, 0, 0), + PIN_GPIO_LPM("LCD_D16", TEGRA_GPIO_PM0, 0, 0), + PIN_GPIO_LPM("LCD_D17", TEGRA_GPIO_PM1, 0, 0), + PIN_GPIO_LPM("LCD_D18", TEGRA_GPIO_PM2, 0, 0), + PIN_GPIO_LPM("LCD_D19", TEGRA_GPIO_PM3, 0, 0), + PIN_GPIO_LPM("LCD_D20", TEGRA_GPIO_PM4, 0, 0), + PIN_GPIO_LPM("LCD_D21", TEGRA_GPIO_PM5, 0, 0), + PIN_GPIO_LPM("LCD_D22", TEGRA_GPIO_PM6, 0, 0), + PIN_GPIO_LPM("LCD_D23", TEGRA_GPIO_PM7, 0, 0), + + PIN_GPIO_LPM("LCD_DC0", TEGRA_GPIO_PN6, 0, 0), + PIN_GPIO_LPM("LCD_PWR0", TEGRA_GPIO_PB2, 0, 0), + PIN_GPIO_LPM("LCD_PWR1", TEGRA_GPIO_PC1, 0, 0), + PIN_GPIO_LPM("LCD_PWR2", TEGRA_GPIO_PC6, 0, 0), + PIN_GPIO_LPM("LCD_CS0_N", TEGRA_GPIO_PN4, 0, 0), + PIN_GPIO_LPM("LCD_CS1_N", TEGRA_GPIO_PW0, 0, 0), + PIN_GPIO_LPM("LCD_PCLK", TEGRA_GPIO_PB3, 0, 0), + PIN_GPIO_LPM("LCD_WR_N", TEGRA_GPIO_PZ3, 0, 0), + PIN_GPIO_LPM("LCD_HSYNC", TEGRA_GPIO_PJ3, 0, 0), + PIN_GPIO_LPM("LCD_VSYNC", TEGRA_GPIO_PJ4, 0, 0), + PIN_GPIO_LPM("LCD_SCK", TEGRA_GPIO_PZ4, 0, 0), + PIN_GPIO_LPM("LCD_SDOUT", TEGRA_GPIO_PN5, 0, 0), + PIN_GPIO_LPM("LCD_SDIN", TEGRA_GPIO_PZ2, 0, 0), +}; + static void set_unused_pin_gpio(struct gpio_init_pin_info *lpm_pin_info, int list_count) { @@ -811,6 +902,8 @@ int __init cardhu_pins_state_init(void) if (display_board_info.board_id == BOARD_DISPLAY_E1506) { set_unused_pin_gpio(&vddio_gmi_pins_pm269_e1506[0], ARRAY_SIZE(vddio_gmi_pins_pm269_e1506)); + set_unused_pin_gpio(cardhu_unused_gpio_pins_e1506, + ARRAY_SIZE(cardhu_unused_gpio_pins_e1506)); } else if (display_board_info.board_id != BOARD_DISPLAY_PM313) { set_unused_pin_gpio(&vddio_gmi_pins_pm269_wo_pm313[0], ARRAY_SIZE(vddio_gmi_pins_pm269_wo_pm313)); diff --git a/arch/arm/mach-tegra/board-cardhu-power.c b/arch/arm/mach-tegra/board-cardhu-power.c index ace103f5ba6b..677b38347514 100644 --- a/arch/arm/mach-tegra/board-cardhu-power.c +++ b/arch/arm/mach-tegra/board-cardhu-power.c @@ -538,7 +538,10 @@ static struct regulator_consumer_supply fixed_reg_en_3v3_sys_supply[] = { REGULATOR_SUPPLY("hvdd_pex_pmu", NULL), REGULATOR_SUPPLY("avdd_hdmi", NULL), REGULATOR_SUPPLY("vpp_fuse", NULL), - REGULATOR_SUPPLY("avdd_usb", NULL), + REGULATOR_SUPPLY("avdd_usb", "tegra-udc.0"), + REGULATOR_SUPPLY("avdd_usb", "tegra-ehci.0"), + REGULATOR_SUPPLY("avdd_usb", "tegra-ehci.1"), + REGULATOR_SUPPLY("avdd_usb", "tegra-ehci.2"), REGULATOR_SUPPLY("vdd_ddr_rx", NULL), REGULATOR_SUPPLY("vcore_nand", NULL), REGULATOR_SUPPLY("hvdd_sata", NULL), @@ -1131,15 +1134,25 @@ static struct tegra_suspend_platform_data cardhu_suspend_data = { .cpu_lp2_min_residency = 2000, .board_suspend = cardhu_board_suspend, .board_resume = cardhu_board_resume, +#ifdef CONFIG_TEGRA_LP1_950 + .lp1_lowvolt_support = false, + .i2c_base_addr = 0, + .pmuslave_addr = 0, + .core_reg_addr = 0, + .lp1_core_volt_low = 0, + .lp1_core_volt_high = 0, +#endif }; int __init cardhu_suspend_init(void) { struct board_info board_info; struct board_info pmu_board_info; + struct board_info display_board_info; tegra_get_board_info(&board_info); tegra_get_pmu_board_info(&pmu_board_info); + tegra_get_display_board_info(&display_board_info); /* For PMU Fab A03, A04 and A05 make core_pwr_req to high */ if ((pmu_board_info.fab == BOARD_FAB_A03) || @@ -1158,25 +1171,43 @@ int __init cardhu_suspend_init(void) if (board_info.fab == BOARD_FAB_A03) cardhu_suspend_data.corereq_high = true; if (board_info.fab < BOARD_FAB_A03) - /* post E1291-A02 revisions WAKE19/USB1-VBUS wake supported */ + /* post E1291-A02 revisions VBUS wake supported */ tegra_disable_wake_source(TEGRA_WAKE_USB1_VBUS); break; case BOARD_E1198: if (board_info.fab < BOARD_FAB_A02) - /* post E1198-A01 revisions WAKE19/USB1-VBUS wake supported */ + /* post E1198-A01 revisions VBUS wake supported */ tegra_disable_wake_source(TEGRA_WAKE_USB1_VBUS); break; case BOARD_PM269: +#ifdef CONFIG_TEGRA_LP1_950 + /* AP37 board supports the LP1_950mV feature */ + if (is_display_board_dsi(display_board_info.board_id)) { + cardhu_suspend_data.lp1_lowvolt_support = true; + cardhu_suspend_data.i2c_base_addr = TEGRA_I2C5_BASE; + cardhu_suspend_data.pmuslave_addr = 0xC0; + cardhu_suspend_data.core_reg_addr = 0x03; + cardhu_suspend_data.lp1_core_volt_low = 0x2D; + cardhu_suspend_data.lp1_core_volt_high = 0x50; + } +#endif + if (is_display_board_dsi(display_board_info.board_id)) + cardhu_suspend_data.cpu_wake_freq = CPU_WAKE_FREQ_LOW; case BOARD_PM305: case BOARD_PM311: break; - case BOARD_E1187: - case BOARD_E1186: case BOARD_E1256: case BOARD_E1257: cardhu_suspend_data.cpu_timer = 5000; cardhu_suspend_data.cpu_off_timer = 5000; break; + case BOARD_E1187: + case BOARD_E1186: + /* VBUS repeated wakeup seen on older E1186 boards */ + tegra_disable_wake_source(TEGRA_WAKE_USB1_VBUS); + cardhu_suspend_data.cpu_timer = 5000; + cardhu_suspend_data.cpu_off_timer = 5000; + break; default: break; } diff --git a/arch/arm/mach-tegra/board-cardhu-sdhci.c b/arch/arm/mach-tegra/board-cardhu-sdhci.c index d8be9fe6747f..df7177fb34a7 100644 --- a/arch/arm/mach-tegra/board-cardhu-sdhci.c +++ b/arch/arm/mach-tegra/board-cardhu-sdhci.c @@ -28,6 +28,7 @@ #include <mach/irqs.h> #include <mach/iomap.h> #include <mach/sdhci.h> +#include <mach/io_dpd.h> #include "gpio-names.h" #include "board.h" @@ -251,11 +252,31 @@ static int cardhu_wifi_set_carddetect(int val) static int cardhu_wifi_power(int on) { + struct tegra_io_dpd *sd_dpd; + pr_debug("%s: %d\n", __func__, on); + + /* + * FIXME : we need to revisit IO DPD code + * on how should multiple pins under DPD get controlled + * + * cardhu GPIO WLAN enable is part of SDMMC3 pin group + */ + sd_dpd = tegra_io_dpd_get(&tegra_sdhci_device2.dev); + if (sd_dpd) { + mutex_lock(&sd_dpd->delay_lock); + tegra_io_dpd_disable(sd_dpd); + mutex_unlock(&sd_dpd->delay_lock); + } gpio_set_value(CARDHU_WLAN_PWR, on); mdelay(100); gpio_set_value(CARDHU_WLAN_RST, on); mdelay(200); + if (sd_dpd) { + mutex_lock(&sd_dpd->delay_lock); + tegra_io_dpd_enable(sd_dpd); + mutex_unlock(&sd_dpd->delay_lock); + } return 0; } diff --git a/arch/arm/mach-tegra/board-cardhu-sensors.c b/arch/arm/mach-tegra/board-cardhu-sensors.c index bb6a2ae5774d..7e9774f290eb 100644 --- a/arch/arm/mach-tegra/board-cardhu-sensors.c +++ b/arch/arm/mach-tegra/board-cardhu-sensors.c @@ -340,7 +340,7 @@ static int cardhu_right_ov5650_power_off(void) gpio_direction_output(CAMERA_CSI_MUX_SEL_GPIO, 0); /* Boards E1198 and E1291 are of Cardhu personality - * and donot have TCA6416 exp for camera */ + * and do not have TCA6416 for camera */ if ((board_info.board_id == BOARD_E1198) || (board_info.board_id == BOARD_E1291)) { gpio_direction_output(CAM1_POWER_DWN_GPIO, 1); @@ -387,16 +387,21 @@ static int cardhu_ov2710_power_on(void) /* CSI-B and front sensor are muxed on cardhu */ gpio_direction_output(CAMERA_CSI_MUX_SEL_GPIO, 1); + /* Enable VDD_1V8_Cam3 */ + if (cardhu_1v8_cam3 == NULL) { + cardhu_1v8_cam3 = regulator_get(NULL, "vdd_1v8_cam3"); + if (WARN_ON(IS_ERR(cardhu_1v8_cam3))) { + pr_err("%s: couldn't get regulator vdd_1v8_cam3: %ld\n", + __func__, PTR_ERR(cardhu_1v8_cam3)); + goto reg_alloc_fail; + } + } + regulator_enable(cardhu_1v8_cam3); + /* Boards E1198 and E1291 are of Cardhu personality - * and donot have TCA6416 exp for camera */ + * and do not have TCA6416 for camera */ if ((board_info.board_id == BOARD_E1198) || (board_info.board_id == BOARD_E1291)) { - - gpio_direction_output(CAM1_POWER_DWN_GPIO, 0); - gpio_direction_output(CAM2_POWER_DWN_GPIO, 0); - gpio_direction_output(CAM3_POWER_DWN_GPIO, 0); - mdelay(10); - if (cardhu_vdd_cam3 == NULL) { cardhu_vdd_cam3 = regulator_get(NULL, "vdd_cam3"); if (WARN_ON(IS_ERR(cardhu_vdd_cam3))) { @@ -406,19 +411,17 @@ static int cardhu_ov2710_power_on(void) } } regulator_enable(cardhu_vdd_cam3); - } - /* Enable VDD_1V8_Cam3 */ - if (cardhu_1v8_cam3 == NULL) { - cardhu_1v8_cam3 = regulator_get(NULL, "vdd_1v8_cam3"); - if (WARN_ON(IS_ERR(cardhu_1v8_cam3))) { - pr_err("%s: couldn't get regulator vdd_1v8_cam3: %ld\n", - __func__, PTR_ERR(cardhu_1v8_cam3)); - goto reg_alloc_fail; - } + mdelay(5); + + gpio_direction_output(CAM1_POWER_DWN_GPIO, 0); + gpio_direction_output(CAM2_POWER_DWN_GPIO, 0); + gpio_direction_output(CAM3_POWER_DWN_GPIO, 0); + mdelay(10); + } - regulator_enable(cardhu_1v8_cam3); - mdelay(5); + + mdelay(20); return 0; @@ -447,12 +450,12 @@ static int cardhu_ov2710_power_off(void) gpio_direction_output(CAM1_POWER_DWN_GPIO, 1); gpio_direction_output(CAM2_POWER_DWN_GPIO, 1); gpio_direction_output(CAM3_POWER_DWN_GPIO, 1); + if (cardhu_vdd_cam3) + regulator_disable(cardhu_vdd_cam3); } if (cardhu_1v8_cam3) regulator_disable(cardhu_1v8_cam3); - if (cardhu_vdd_cam3) - regulator_disable(cardhu_vdd_cam3); return 0; } diff --git a/arch/arm/mach-tegra/board-cardhu.c b/arch/arm/mach-tegra/board-cardhu.c index b5fa3f316698..e14e6b25d644 100644 --- a/arch/arm/mach-tegra/board-cardhu.c +++ b/arch/arm/mach-tegra/board-cardhu.c @@ -2,6 +2,7 @@ * arch/arm/mach-tegra/board-cardhu.c * * Copyright (c) 2011-2012, NVIDIA Corporation. All rights reserved. + * 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 as published by @@ -44,12 +45,14 @@ #include <sound/wm8903.h> #include <sound/max98095.h> #include <media/tegra_dtv.h> +#include <media/tegra_camera.h> #include <mach/clk.h> #include <mach/iomap.h> #include <mach/irqs.h> #include <mach/pinmux.h> #include <mach/iomap.h> +#include <mach/io_dpd.h> #include <mach/io.h> #include <mach/i2s.h> #include <mach/tegra_asoc_pdata.h> @@ -491,6 +494,16 @@ static void __init uart_debug_init(void) debug_port_id = 1; } +#ifdef CONFIG_TEGRA_IRDA + if ((board_info.board_id == BOARD_E1186) || + (board_info.board_id == BOARD_E1198)) { + if (debug_port_id == 1) { + cardhu_irda_pdata.is_irda = false; + pr_err("UARTB is not available for IrDA\n"); + } + } +#endif + switch (debug_port_id) { case 0: /* UARTA is the debug port. */ @@ -552,6 +565,9 @@ static void __init cardhu_uart_init(void) { struct clk *c; int i; + struct board_info board_info; + + tegra_get_board_info(&board_info); for (i = 0; i < ARRAY_SIZE(uart_parent_clk); ++i) { c = tegra_get_clock_by_name(uart_parent_clk[i].name); @@ -597,15 +613,44 @@ static void __init cardhu_uart_init(void) } } +#ifdef CONFIG_TEGRA_IRDA + if (((board_info.board_id == BOARD_E1186) || + (board_info.board_id == BOARD_E1198)) && + cardhu_irda_pdata.is_irda) { + cardhu_irda_pdata.parent_clk_list = uart_parent_clk; + cardhu_irda_pdata.parent_clk_count = + ARRAY_SIZE(uart_parent_clk); + + tegra_uartb_device.dev.platform_data = &cardhu_irda_pdata; + } +#endif + platform_add_devices(cardhu_uart_devices, ARRAY_SIZE(cardhu_uart_devices)); } +static struct tegra_camera_platform_data tegra_camera_pdata = { + .limit_3d_emc_clk = false, +}; + static struct platform_device tegra_camera = { .name = "tegra_camera", + .dev = { + .platform_data = &tegra_camera_pdata, + }, .id = -1, }; +static void tegra_camera_init(void) +{ + /* For AP37 platform, limit 3d and emc freq when camera is ON */ + if (TEGRA_REVISION_A03 == tegra_get_revision() && + 0xA0 == tegra_sku_id()) + tegra_camera_pdata.limit_3d_emc_clk = true; + else + tegra_camera_pdata.limit_3d_emc_clk = false; +} + static struct platform_device *cardhu_spi_devices[] __initdata = { &tegra_spi_device4, }; @@ -698,12 +743,25 @@ static struct platform_device tegra_rtc_device = { .num_resources = ARRAY_SIZE(tegra_rtc_resources), }; -static struct tegra_wm8903_platform_data cardhu_audio_wm8903_pdata = { +static struct tegra_asoc_platform_data cardhu_audio_wm8903_pdata = { .gpio_spkr_en = TEGRA_GPIO_SPKR_EN, .gpio_hp_det = TEGRA_GPIO_HP_DET, .gpio_hp_mute = -1, .gpio_int_mic_en = -1, .gpio_ext_mic_en = -1, + .i2s_param[HIFI_CODEC] = { + .audio_port_id = 0, + .is_i2s_master = 1, + .i2s_mode = TEGRA_DAIFMT_I2S, + }, + .i2s_param[BASEBAND] = { + .audio_port_id = -1, + }, + .i2s_param[BT_SCO] = { + .audio_port_id = 3, + .is_i2s_master = 1, + .i2s_mode = TEGRA_DAIFMT_DSP_A, + }, }; static struct tegra_asoc_platform_data cardhu_audio_max98095_pdata = { @@ -712,6 +770,19 @@ static struct tegra_asoc_platform_data cardhu_audio_max98095_pdata = { .gpio_hp_mute = -1, .gpio_int_mic_en = -1, .gpio_ext_mic_en = -1, + .i2s_param[HIFI_CODEC] = { + .audio_port_id = 0, + .is_i2s_master = 1, + .i2s_mode = TEGRA_DAIFMT_I2S, + }, + .i2s_param[BASEBAND] = { + .audio_port_id = -1, + }, + .i2s_param[BT_SCO] = { + .audio_port_id = 3, + .is_i2s_master = 1, + .i2s_mode = TEGRA_DAIFMT_DSP_A, + }, }; static struct platform_device cardhu_audio_wm8903_device = { @@ -737,14 +808,17 @@ static struct tegra_asoc_platform_data cardhu_audio_aic326x_pdata = { .gpio_int_mic_en = -1, .gpio_ext_mic_en = -1, /*defaults for Verbier-Cardhu board with TI AIC326X codec*/ - .audio_port_id = { - [HIFI_CODEC] = 0, - [BASEBAND] = -1, - [BT_SCO] = 3, + .i2s_param[HIFI_CODEC] = { + .audio_port_id = 0, + .is_i2s_master = 1, + .i2s_mode = TEGRA_DAIFMT_I2S, + .sample_size = 16, }, - .baseband_param = { - .rate = -1, - .channels = -1, + .i2s_param[BT_SCO] = { + .sample_size = 16, + .audio_port_id = 3, + .is_i2s_master = 1, + .i2s_mode = TEGRA_DAIFMT_DSP_A, }, }; @@ -1008,13 +1082,6 @@ static struct tegra_usb_platform_data tegra_ehci2_hsic_xmm_pdata = { .remote_wakeup_supported = false, .power_off_on_suspend = false, }, - .u_cfg.hsic = { - .sync_start_delay = 9, - .idle_wait_delay = 17, - .term_range_adj = 0, - .elastic_underrun_limit = 16, - .elastic_overrun_limit = 16, - }, .ops = &hsic_xmm_plat_ops, }; #endif @@ -1035,10 +1102,6 @@ void hsic_platform_open(void) gpio_direction_output(hsic_enable_gpio, 0 /* deasserted */); if (!reset_gpio) gpio_direction_output(hsic_reset_gpio, 0 /* asserted */); - if (!enable_gpio) - tegra_gpio_enable(hsic_enable_gpio); - if (!reset_gpio) - tegra_gpio_enable(hsic_reset_gpio); /* keep hsic reset asserted for 1 ms */ udelay(1000); /* enable (power on) hsic */ @@ -1098,13 +1161,6 @@ static struct tegra_usb_platform_data tegra_ehci2_hsic_pdata = { .remote_wakeup_supported = false, .power_off_on_suspend = false, }, - .u_cfg.hsic = { - .sync_start_delay = 9, - .idle_wait_delay = 17, - .term_range_adj = 0, - .elastic_underrun_limit = 16, - .elastic_overrun_limit = 16, - }, .ops = &hsic_plat_ops, }; @@ -1384,8 +1440,10 @@ static void __init tegra_cardhu_init(void) cardhu_edp_init(); #endif cardhu_uart_init(); + tegra_camera_init(); platform_add_devices(cardhu_devices, ARRAY_SIZE(cardhu_devices)); tegra_ram_console_debug_init(); + tegra_io_dpd_init(); cardhu_sdhci_init(); cardhu_regulator_init(); cardhu_dtv_init(); @@ -1422,6 +1480,11 @@ static void __init tegra_cardhu_reserve(void) tegra_ram_console_debug_reserve(SZ_1M); } +static const char *cardhu_dt_board_compat[] = { + "nvidia,cardhu", + NULL +}; + MACHINE_START(CARDHU, "cardhu") .boot_params = 0x80000100, .map_io = tegra_map_common_io, @@ -1430,4 +1493,5 @@ MACHINE_START(CARDHU, "cardhu") .init_irq = tegra_init_irq, .timer = &tegra_timer, .init_machine = tegra_cardhu_init, + .dt_compat = cardhu_dt_board_compat, MACHINE_END diff --git a/arch/arm/mach-tegra/board-cardhu.h b/arch/arm/mach-tegra/board-cardhu.h index a8be32ec9cdd..3dd3d23d9414 100644 --- a/arch/arm/mach-tegra/board-cardhu.h +++ b/arch/arm/mach-tegra/board-cardhu.h @@ -221,6 +221,8 @@ int cardhu_pm298_regulator_init(void); int cardhu_pm299_gpio_switch_regulator_init(void); int cardhu_pm299_regulator_init(void); +extern struct tegra_uart_platform_data cardhu_irda_pdata; + #define MPU_TYPE_MPU3050 1 #define MPU_TYPE_MPU6050 2 #define MPU_GYRO_TYPE MPU_TYPE_MPU3050 @@ -229,7 +231,7 @@ int cardhu_pm299_regulator_init(void); #define MPU_GYRO_BUS_NUM 2 #define MPU_GYRO_ORIENTATION { 0, -1, 0, -1, 0, 0, 0, 0, -1 } #define MPU_ACCEL_NAME "kxtf9" -#define MPU_ACCEL_IRQ_GPIO TEGRA_GPIO_PL1 +#define MPU_ACCEL_IRQ_GPIO 0 /* DISABLE ACCELIRQ: TEGRA_GPIO_PL1 */ #define MPU_ACCEL_ADDR 0x0F #define MPU_ACCEL_BUS_NUM 2 #define MPU_ACCEL_ORIENTATION { 0, -1, 0, -1, 0, 0, 0, 0, -1 } diff --git a/arch/arm/mach-tegra/board-e1853-panel.c b/arch/arm/mach-tegra/board-e1853-panel.c new file mode 100644 index 000000000000..a4d6bc66f4e7 --- /dev/null +++ b/arch/arm/mach-tegra/board-e1853-panel.c @@ -0,0 +1,202 @@ +/* + * arch/arm/mach-tegra/board-e1853-panel.c + * + * 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/resource.h> +#include <asm/mach-types.h> +#include <linux/platform_device.h> +#include <linux/nvhost.h> +#include <linux/nvmap.h> +#include <mach/irqs.h> +#include <mach/iomap.h> +#include <mach/dc.h> +#include <mach/fb.h> + +#include "board.h" +#include "devices.h" +#include "tegra3_host1x_devices.h" +#include "gpio-names.h" + +#define E1853_HDMI_HPD TEGRA_GPIO_PB2 + +static int e1853_panel_enable(void) +{ + return 0; +} + +static int e1853_panel_disable(void) +{ + return 0; +} + +static struct tegra_dc_mode e1853_panel_modes[] = { + { + /* 800x480@60 */ + .pclk = 32460000, + .h_ref_to_sync = 1, + .v_ref_to_sync = 1, + .h_sync_width = 64, + .v_sync_width = 3, + .h_back_porch = 128, + .v_back_porch = 22, + .h_front_porch = 64, + .v_front_porch = 20, + .h_active = 800, + .v_active = 480, + }, +}; + +static struct tegra_fb_data e1853_fb_data = { + .win = 0, + .xres = 800, + .yres = 480, + .bits_per_pixel = 32, +}; + +static struct tegra_dc_out e1853_disp1_out = { + .align = TEGRA_DC_ALIGN_MSB, + .order = TEGRA_DC_ORDER_RED_BLUE, + .type = TEGRA_DC_OUT_RGB, + .modes = e1853_panel_modes, + .n_modes = ARRAY_SIZE(e1853_panel_modes), + .enable = e1853_panel_enable, + .disable = e1853_panel_disable, +}; + +static struct tegra_dc_platform_data e1853_disp1_pdata = { + .flags = TEGRA_DC_FLAG_ENABLED, + .default_out = &e1853_disp1_out, + .emc_clk_rate = 300000000, + .fb = &e1853_fb_data, +}; + +static int e1853_hdmi_enable(void) +{ + return 0; +} + +static int e1853_hdmi_disable(void) +{ + return 0; +} + +static struct tegra_fb_data e1853_hdmi_fb_data = { + .win = 0, + .xres = 800, + .yres = 480, + .bits_per_pixel = 32, + .flags = TEGRA_FB_FLIP_ON_PROBE, +}; + +static struct tegra_dc_out e1853_hdmi_out = { + .align = TEGRA_DC_ALIGN_MSB, + .order = TEGRA_DC_ORDER_RED_BLUE, + .parent_clk = "pll_d2_out0", + .type = TEGRA_DC_OUT_HDMI, + .flags = TEGRA_DC_OUT_HOTPLUG_LOW | + TEGRA_DC_OUT_NVHDCP_POLICY_ON_DEMAND, + .max_pixclock = KHZ2PICOS(148500), + /* XXX: Check the GPIO */ + .hotplug_gpio = E1853_HDMI_HPD, + .enable = e1853_hdmi_enable, + .disable = e1853_hdmi_disable, + /* XXX: Check the I2C instance */ + .dcc_bus = 3, +}; + +static struct tegra_dc_platform_data e1853_hdmi_pdata = { + .flags = 0, + .default_out = &e1853_hdmi_out, + .emc_clk_rate = 300000000, + .fb = &e1853_hdmi_fb_data, +}; + +static struct nvmap_platform_carveout e1853_carveouts[] = { + [0] = { + .name = "iram", + .usage_mask = NVMAP_HEAP_CARVEOUT_IRAM, + .base = TEGRA_IRAM_BASE + TEGRA_RESET_HANDLER_SIZE, + .size = TEGRA_IRAM_SIZE - TEGRA_RESET_HANDLER_SIZE, + .buddy_size = 0, /* no buddy allocation for IRAM */ + }, + [1] = { + .name = "generic-0", + .usage_mask = NVMAP_HEAP_CARVEOUT_GENERIC, + .base = 0, /* Filled in by e1853_panel_init() */ + .size = 0, /* Filled in by e1853_panel_init() */ + .buddy_size = SZ_32K, + }, +}; + +static struct nvmap_platform_data e1853_nvmap_data = { + .carveouts = e1853_carveouts, + .nr_carveouts = ARRAY_SIZE(e1853_carveouts), +}; + +static struct platform_device *e1853_gfx_devices[] __initdata = { + &tegra_nvmap_device, +}; + +int __init e1853_panel_init(void) +{ + int err; + struct resource *res; + + e1853_carveouts[1].base = tegra_carveout_start; + e1853_carveouts[1].size = tegra_carveout_size; + tegra_nvmap_device.dev.platform_data = &e1853_nvmap_data; + tegra_disp1_device.dev.platform_data = &e1853_disp1_pdata; + tegra_disp2_device.dev.platform_data = &e1853_hdmi_pdata; + +#ifdef CONFIG_TEGRA_GRHOST + err = tegra3_register_host1x_devices(); + if (err) + return err; +#endif + + err = platform_add_devices(e1853_gfx_devices, + ARRAY_SIZE(e1853_gfx_devices)); + +#if defined(CONFIG_TEGRA_GRHOST) && defined(CONFIG_TEGRA_DC) + res = nvhost_get_resource_byname(&tegra_disp1_device, + IORESOURCE_MEM, "fbmem"); + if (res) { + res->start = tegra_fb_start; + res->end = tegra_fb_start + tegra_fb_size - 1; + } + + if (!err) + err = nvhost_device_register(&tegra_disp1_device); + + res = nvhost_get_resource_byname(&tegra_disp2_device, + IORESOURCE_MEM, "fbmem"); + if (res) { + res->start = tegra_fb2_start; + res->end = tegra_fb2_start + tegra_fb2_size - 1; + } + + if (!err) + err = nvhost_device_register(&tegra_disp2_device); +#endif + +#if defined(CONFIG_TEGRA_GRHOST) && defined(CONFIG_TEGRA_NVAVP) + if (!err) + err = nvhost_device_register(&nvavp_device); +#endif + return err; +} diff --git a/arch/arm/mach-tegra/board-e1853-pinmux.c b/arch/arm/mach-tegra/board-e1853-pinmux.c new file mode 100644 index 000000000000..9e81b7035aba --- /dev/null +++ b/arch/arm/mach-tegra/board-e1853-pinmux.c @@ -0,0 +1,502 @@ +/* + * arch/arm/mach-tegra/board-e1853-pinmux.c + * + * 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/init.h> +#include <mach/pinmux.h> +#include <linux/gpio.h> +#include "board.h" +#include "board-e1853.h" +#include "gpio-names.h" + +#define DEFAULT_DRIVE(_name) \ + { \ + .pingroup = TEGRA_DRIVE_PINGROUP_##_name, \ + .hsm = TEGRA_HSM_DISABLE, \ + .schmitt = TEGRA_SCHMITT_ENABLE, \ + .drive = TEGRA_DRIVE_DIV_1, \ + .pull_down = TEGRA_PULL_31, \ + .pull_up = TEGRA_PULL_31, \ + .slew_rising = TEGRA_SLEW_SLOWEST, \ + .slew_falling = TEGRA_SLEW_SLOWEST, \ + } +/* Setting the drive strength of pins + * hsm: Enable High speed mode (ENABLE/DISABLE) + * Schimit: Enable/disable schimit (ENABLE/DISABLE) + * drive: low power mode (DIV_1, DIV_2, DIV_4, DIV_8) + * pulldn_drive - drive down (falling edge) - Driver Output Pull-Down drive + * strength code. Value from 0 to 31. + * pullup_drive - drive up (rising edge) - Driver Output Pull-Up drive + * strength code. Value from 0 to 31. + * pulldn_slew - Driver Output Pull-Up slew control code - 2bit code + * code 11 is least slewing of signal. code 00 is highest + * slewing of the signal. + * Value - FASTEST, FAST, SLOW, SLOWEST + * pullup_slew - Driver Output Pull-Down slew control code - + * code 11 is least slewing of signal. code 00 is highest + * slewing of the signal. + * Value - FASTEST, FAST, SLOW, SLOWEST + */ +#define SET_DRIVE(_name, _hsm, _schmitt, _drive, _pulldn_drive, _pullup_drive, _pulldn_slew, _pullup_slew) \ + { \ + .pingroup = TEGRA_DRIVE_PINGROUP_##_name, \ + .hsm = TEGRA_HSM_##_hsm, \ + .schmitt = TEGRA_SCHMITT_##_schmitt, \ + .drive = TEGRA_DRIVE_##_drive, \ + .pull_down = TEGRA_PULL_##_pulldn_drive, \ + .pull_up = TEGRA_PULL_##_pullup_drive, \ + .slew_rising = TEGRA_SLEW_##_pulldn_slew, \ + .slew_falling = TEGRA_SLEW_##_pullup_slew, \ + } + +/* !!!FIXME!!!! Update drive strength with characterized value */ +static __initdata struct tegra_drive_pingroup_config e1853_drive_pinmux[] = { + /* 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, 12, 30, FASTEST, FASTEST), + + /* DDC I2C */ + SET_DRIVE(DDC, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST), + + /* PWR_I2C */ + SET_DRIVE(AO1, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST), + + /* SDMMC4 */ + SET_DRIVE(GME, DISABLE, ENABLE, DIV_1, 22, 18, SLOWEST, SLOWEST), + 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), + + /* SDMMC 3 */ + SET_DRIVE(SDIO3, DISABLE, DISABLE, DIV_1, 46, 42, FAST, FAST), +}; + +#define DEFAULT_PINMUX(_pingroup, _mux, _pupd, _tri, _io) \ + { \ + .pingroup = TEGRA_PINGROUP_##_pingroup, \ + .func = TEGRA_MUX_##_mux, \ + .pupd = TEGRA_PUPD_##_pupd, \ + .tristate = TEGRA_TRI_##_tri, \ + .io = TEGRA_PIN_##_io, \ + .lock = TEGRA_PIN_LOCK_DEFAULT, \ + .od = TEGRA_PIN_OD_DEFAULT, \ + .ioreset = TEGRA_PIN_IO_RESET_DEFAULT, \ + } + +#define I2C_PINMUX(_pingroup, _mux, _pupd, _tri, _io, _lock, _od) \ + { \ + .pingroup = TEGRA_PINGROUP_##_pingroup, \ + .func = TEGRA_MUX_##_mux, \ + .pupd = TEGRA_PUPD_##_pupd, \ + .tristate = TEGRA_TRI_##_tri, \ + .io = TEGRA_PIN_##_io, \ + .lock = TEGRA_PIN_LOCK_##_lock, \ + .od = TEGRA_PIN_OD_##_od, \ + .ioreset = TEGRA_PIN_IO_RESET_DEFAULT, \ + } + +#define VI_PINMUX(_pingroup, _mux, _pupd, _tri, _io, _lock, _ioreset) \ + { \ + .pingroup = TEGRA_PINGROUP_##_pingroup, \ + .func = TEGRA_MUX_##_mux, \ + .pupd = TEGRA_PUPD_##_pupd, \ + .tristate = TEGRA_TRI_##_tri, \ + .io = TEGRA_PIN_##_io, \ + .lock = TEGRA_PIN_LOCK_##_lock, \ + .od = TEGRA_PIN_OD_DEFAULT, \ + .ioreset = TEGRA_PIN_IO_RESET_##_ioreset \ + } + +static __initdata struct tegra_pingroup_config e1853_pinmux_common[] = { + + /* CLK-EXTCLK1 */ + DEFAULT_PINMUX(CLK1_OUT, EXTPERIPH1, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(CLK3_OUT, EXTPERIPH3, NORMAL, NORMAL, OUTPUT), + + /* SDMMC1 pinmux */ + DEFAULT_PINMUX(SDMMC1_CLK, SDMMC1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC1_CMD, SDMMC1, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC1_DAT3, SDMMC1, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC1_DAT2, SDMMC1, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC1_DAT1, SDMMC1, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC1_DAT0, SDMMC1, PULL_UP, NORMAL, INPUT), + + /* SDMMC2 pinmux */ + DEFAULT_PINMUX(KB_ROW10, SDMMC2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW11, SDMMC2, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW12, SDMMC2, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW13, SDMMC2, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW14, SDMMC2, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW15, SDMMC2, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW6, SDMMC2, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW7, SDMMC2, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW8, SDMMC2, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW9, SDMMC2, PULL_UP, NORMAL, INPUT), + + /* SDMMC3 pinmux */ + DEFAULT_PINMUX(SDMMC3_CLK, SDMMC3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC3_CMD, SDMMC3, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC3_DAT0, SDMMC3, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC3_DAT1, SDMMC3, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC3_DAT2, SDMMC3, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC3_DAT3, SDMMC3, PULL_UP, NORMAL, INPUT), + + /* I2C1 pinmux */ + I2C_PINMUX(GEN1_I2C_SCL, I2C1, NORMAL, NORMAL, INPUT, DISABLE, ENABLE), + I2C_PINMUX(GEN1_I2C_SDA, I2C1, NORMAL, NORMAL, INPUT, DISABLE, ENABLE), + + /* I2C2 pinmux */ + I2C_PINMUX(GEN2_I2C_SCL, I2C2, NORMAL, NORMAL, INPUT, DISABLE, ENABLE), + I2C_PINMUX(GEN2_I2C_SDA, I2C2, NORMAL, NORMAL, INPUT, DISABLE, ENABLE), + + /* I2C3 pinmux */ + I2C_PINMUX(CAM_I2C_SCL, I2C3, PULL_UP, NORMAL, INPUT, DISABLE, ENABLE), + I2C_PINMUX(CAM_I2C_SDA, I2C3, PULL_UP, NORMAL, INPUT, DISABLE, ENABLE), + + /* I2C4 pinmux */ + I2C_PINMUX(DDC_SCL, I2C4, NORMAL, NORMAL, INPUT, DISABLE, ENABLE), + I2C_PINMUX(DDC_SDA, I2C4, NORMAL, NORMAL, INPUT, DISABLE, ENABLE), + + /* PowerI2C pinmux */ + I2C_PINMUX(PWR_I2C_SCL, I2CPWR, NORMAL, NORMAL, INPUT, DISABLE, ENABLE), + I2C_PINMUX(PWR_I2C_SDA, I2CPWR, NORMAL, NORMAL, INPUT, DISABLE, ENABLE), + + /* UART1 pinmux */ + DEFAULT_PINMUX(GPIO_PU0, UARTA, PULL_UP, NORMAL, OUTPUT), + DEFAULT_PINMUX(GPIO_PU1, UARTA, NORMAL, NORMAL, INPUT), + + /* UART2 pinmux */ + DEFAULT_PINMUX(UART2_CTS_N, UARTB, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(UART2_RTS_N, UARTB, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(UART2_RXD, IRDA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(UART2_TXD, IRDA, PULL_UP, NORMAL, OUTPUT), + + /* UART3 pinmux */ + DEFAULT_PINMUX(UART3_CTS_N, UARTC, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(UART3_RTS_N, UARTC, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(UART3_RXD, UARTC, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(UART3_TXD, UARTC, PULL_UP, NORMAL, OUTPUT), + + /* UART4 pinmux */ + DEFAULT_PINMUX(ULPI_CLK, UARTD, PULL_UP, NORMAL, OUTPUT), + DEFAULT_PINMUX(ULPI_DIR, UARTD, NORMAL, NORMAL, INPUT), + + /* SPI2 pinmux */ + DEFAULT_PINMUX(ULPI_DATA4, SPI2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(ULPI_DATA5, SPI2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(ULPI_DATA6, SPI2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(ULPI_DATA7, SPI2, NORMAL, NORMAL, INPUT), + + /* SPI3 pinmux */ + DEFAULT_PINMUX(ULPI_DATA0, SPI3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(ULPI_DATA1, SPI3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(ULPI_DATA2, SPI3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(ULPI_DATA3, SPI3, NORMAL, NORMAL, INPUT), + + /* SPI5 pinmux */ + DEFAULT_PINMUX(LCD_SCK, SPI5, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_CS0_N, SPI5, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_SDIN, SPI5, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_SDOUT, SPI5, NORMAL, NORMAL, INPUT), + + /* DAP1 */ + DEFAULT_PINMUX(DAP1_FS, I2S0, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP1_DIN, I2S0, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP1_DOUT, I2S0, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(DAP1_SCLK, I2S0, NORMAL, NORMAL, INPUT), + + /* DAP2 */ + DEFAULT_PINMUX(DAP3_FS, I2S2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP3_DIN, I2S2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP3_DOUT, I2S2, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(DAP3_SCLK, I2S2, NORMAL, NORMAL, INPUT), + + /* I2S1 */ + DEFAULT_PINMUX(DAP2_DIN, I2S1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP2_DOUT, I2S1, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(DAP2_FS, I2S1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP2_SCLK, I2S1, NORMAL, NORMAL, INPUT), + + /* I2S3 */ + DEFAULT_PINMUX(DAP4_DIN, I2S3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP4_DOUT, I2S3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP4_FS, I2S3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP4_SCLK, I2S3, NORMAL, NORMAL, INPUT), + + /* NOR pinmux */ + DEFAULT_PINMUX(SDMMC4_DAT0, GMI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC4_DAT1, GMI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC4_DAT2, GMI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC4_DAT3, GMI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC4_DAT4, GMI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC4_DAT5, GMI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC4_DAT6, GMI, NORMAL, NORMAL, INPUT), + + DEFAULT_PINMUX(GMI_A16, GMI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_A17, GMI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_A18, GMI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_A19, GMI, NORMAL, NORMAL, INPUT), + + DEFAULT_PINMUX(GMI_AD0, GMI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_AD1, GMI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_AD2, GMI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_AD3, GMI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_AD4, GMI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_AD5, GMI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_AD6, GMI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_AD7, GMI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_AD8, GMI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_AD9, GMI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_AD10, GMI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_AD11, GMI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_AD12, GMI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_AD13, GMI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_AD14, GMI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_AD15, GMI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_ADV_N, GMI, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GMI_CLK, GMI, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GMI_CS0_N, GMI, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GMI_OE_N, GMI, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GMI_RST_N, GMI, PULL_UP, NORMAL, OUTPUT), + DEFAULT_PINMUX(GMI_WAIT, GMI, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GMI_WP_N, GMI, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GMI_WR_N, GMI, NORMAL, NORMAL, OUTPUT), + + /* DISPLAY pinmux */ + DEFAULT_PINMUX(LCD_D0, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D1, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D2, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D3, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D4, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D5, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D6, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D7, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D8, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D9, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D10, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D11, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D12, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D13, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D14, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D15, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D16, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D17, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D18, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D19, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D20, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D21, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D22, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D23, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_DE, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_HSYNC, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_PCLK, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_VSYNC, DISPLAYA, NORMAL, NORMAL, OUTPUT), + + /* PCIE */ + DEFAULT_PINMUX(PEX_L0_CLKREQ_N, PCIE, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(PEX_L1_RST_N, PCIE, PULL_UP, NORMAL, OUTPUT), + DEFAULT_PINMUX(PEX_L1_CLKREQ_N, PCIE, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(PEX_L0_RST_N, PCIE, PULL_UP, NORMAL, OUTPUT), + + VI_PINMUX(VI_D2, VI, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), + VI_PINMUX(VI_D3, VI, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), + VI_PINMUX(VI_D4, VI, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), + VI_PINMUX(VI_D5, VI, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), + VI_PINMUX(VI_D6, VI, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), + VI_PINMUX(VI_D7, VI, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), + VI_PINMUX(VI_D8, VI, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), + VI_PINMUX(VI_D9, VI, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), + VI_PINMUX(VI_PCLK, VI, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), + VI_PINMUX(VI_HSYNC, VI, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), + VI_PINMUX(VI_VSYNC, VI, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), + + /* pin config for gpios */ + DEFAULT_PINMUX(PEX_L2_CLKREQ_N, RSVD2, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(PEX_L1_PRSNT_N, RSVD2, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_CS1_N, RSVD2, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_DC0, RSVD1, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_DC1, RSVD1, PULL_UP, NORMAL, OUTPUT), + DEFAULT_PINMUX(VI_D0, RSVD1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(ULPI_NXT, RSVD, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(ULPI_STP, RSVD, PULL_DOWN, NORMAL, INPUT), + DEFAULT_PINMUX(CRT_VSYNC, RSVD1, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(CRT_HSYNC, RSVD1, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_PWR1, RSVD1, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_PWR2, RSVD, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(PEX_L0_PRSNT_N, RSVD2, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PV2, RSVD1, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC3_DAT7, RSVD, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(CLK_32K_OUT, RSVD1, PULL_DOWN, NORMAL, OUTPUT), + DEFAULT_PINMUX(CLK3_REQ, RSVD1, PULL_DOWN, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PV0, RSVD, PULL_DOWN, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PV1, RSVD, PULL_DOWN, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_M1, RSVD1, PULL_DOWN, NORMAL, INPUT), + DEFAULT_PINMUX(VI_MCLK, VI, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_WR_N, RSVD, PULL_DOWN, NORMAL, INPUT), + DEFAULT_PINMUX(PEX_L2_PRSNT_N, RSVD2, PULL_DOWN, NORMAL, INPUT), + DEFAULT_PINMUX(PEX_L2_RST_N, RSVD2, PULL_DOWN, NORMAL, INPUT), + DEFAULT_PINMUX(PEX_WAKE_N, RSVD2, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(HDMI_INT, RSVD, PULL_DOWN, NORMAL, OUTPUT), + DEFAULT_PINMUX(KB_ROW1, RSVD2, PULL_DOWN, NORMAL, OUTPUT), + DEFAULT_PINMUX(KB_ROW2, RSVD2, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW3, RSVD2, PULL_UP, NORMAL, OUTPUT), + DEFAULT_PINMUX(KB_ROW4, RSVD3, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(VI_D10, RSVD1, PULL_DOWN, NORMAL, OUTPUT), + DEFAULT_PINMUX(VI_D11, RSVD1, PULL_UP, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_PWR0, DISPLAYA, PULL_DOWN, NORMAL, INPUT), + + /* + * unused pins: tristate them all. + */ + DEFAULT_PINMUX(SPI2_CS0_N, GMI, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(SPI2_SCK, GMI, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(SPI2_MOSI, GMI, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(SPI2_MISO, GMI, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GPIO_PU2, GMI, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GPIO_PU3, GMI, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GPIO_PU4, GMI, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GPIO_PU5, GMI, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GPIO_PU6, GMI, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(CLK1_REQ, RSVD2, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(SDMMC3_DAT4, SDMMC3, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(SDMMC3_DAT5, SDMMC3, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(SPI2_CS1_N, SPI2, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(SPDIF_IN, SPDIF, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(SPDIF_OUT, SAFE, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(SPI1_CS0_N, SPI1, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(SPI1_MISO, SPI1, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(SPI1_MOSI, SPI1, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(SPI1_SCK, SPI1, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(CAM_MCLK, POPSDMMC4, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GPIO_PCC1, POPSDMMC4, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GPIO_PCC2, POPSDMMC4, PULL_UP, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GPIO_PBB0, POPSDMMC4, PULL_UP, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GPIO_PBB3, POPSDMMC4, PULL_UP, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GPIO_PBB4, POPSDMMC4, PULL_UP, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GPIO_PBB5, POPSDMMC4, PULL_UP, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GPIO_PBB6, POPSDMMC4, PULL_UP, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GPIO_PBB7, POPSDMMC4, PULL_UP, TRISTATE, OUTPUT), + +}; + +int __init e1853_pinmux_init(void) +{ + tegra_pinmux_config_table(e1853_pinmux_common, + ARRAY_SIZE(e1853_pinmux_common)); + tegra_drive_pinmux_config_table(e1853_drive_pinmux, + ARRAY_SIZE(e1853_drive_pinmux)); + return 0; +} + +static struct gpio e1853_sku8_gpios[] = { + {TEGRA_GPIO_PV0, GPIOF_IN, "v0"}, + {TEGRA_GPIO_PV1, GPIOF_IN, "v1"}, + {TEGRA_GPIO_PY2, GPIOF_OUT_INIT_HIGH, "y2"}, + {TEGRA_GPIO_PY3, GPIOF_IN, "y3"}, + {TEGRA_GPIO_PV6, GPIOF_IN, "v6"}, + {TEGRA_GPIO_PV7, GPIOF_IN, "v7"}, + {TEGRA_GPIO_PW0, GPIOF_IN, "w0"}, + {TEGRA_GPIO_PD2, GPIOF_OUT_INIT_HIGH, "d2"}, + {TEGRA_GPIO_PW1, GPIOF_IN, "w1"}, + {TEGRA_GPIO_PB2, GPIOF_IN, "b2"}, + {TEGRA_GPIO_PC1, GPIOF_IN, "c1"}, + {TEGRA_GPIO_PC6, GPIOF_IN, "c6"}, + {TEGRA_GPIO_PZ3, GPIOF_IN, "z3"}, + {TEGRA_GPIO_PDD0, GPIOF_IN, "dd0"}, + {TEGRA_GPIO_PDD4, GPIOF_IN, "dd4"}, + {TEGRA_GPIO_PCC7, GPIOF_IN, "cc7"}, + {TEGRA_GPIO_PDD7, GPIOF_IN, "dd7"}, + {TEGRA_GPIO_PCC6, GPIOF_IN, "cc6"}, + {TEGRA_GPIO_PDD3, GPIOF_IN, "dd3"}, + {TEGRA_GPIO_PV2, GPIOF_IN, "v2"}, + {TEGRA_GPIO_PA0, GPIOF_OUT_INIT_LOW, "a0"}, + {TEGRA_GPIO_PR1, GPIOF_OUT_INIT_LOW, "r1"}, + {TEGRA_GPIO_PR2, GPIOF_IN, "r2"}, + {TEGRA_GPIO_PR3, GPIOF_IN, "r3"}, + {TEGRA_GPIO_PR4, GPIOF_IN, "r4"}, + {TEGRA_GPIO_PEE1, GPIOF_IN, "ee1"}, + {TEGRA_GPIO_PT2, GPIOF_OUT_INIT_LOW, "t2"}, + {TEGRA_GPIO_PT3, GPIOF_OUT_INIT_HIGH, "t3"}, + {TEGRA_GPIO_PT1, GPIOF_IN, "t1"}, +}; +int __init e1853_gpio_init(void) +{ + int i, pin_count = 0; + struct gpio *gpios_info = NULL; + gpios_info = e1853_sku8_gpios; + pin_count = ARRAY_SIZE(e1853_sku8_gpios); + + gpio_request_array(gpios_info, pin_count); + for (i = 0; i < pin_count; i++) { + gpio_export(gpios_info[i].gpio, true); + } + return 0; +} diff --git a/arch/arm/mach-tegra/board-e1853-sdhci.c b/arch/arm/mach-tegra/board-e1853-sdhci.c new file mode 100644 index 000000000000..5446bb46df15 --- /dev/null +++ b/arch/arm/mach-tegra/board-e1853-sdhci.c @@ -0,0 +1,83 @@ +/* + * arch/arm/mach-tegra/board-e1853-sdhci.c + * + * 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/resource.h> +#include <linux/platform_device.h> +#include <linux/wlan_plat.h> +#include <linux/delay.h> +#include <linux/gpio.h> +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/mmc/host.h> + +#include <asm/mach-types.h> +#include <mach/irqs.h> +#include <mach/iomap.h> +#include <mach/sdhci.h> + +#include "gpio-names.h" +#include "board.h" +#include "board-e1853.h" +#include "devices.h" + +static struct tegra_sdhci_platform_data tegra_sdhci_platform_data1 = { + .cd_gpio = -1, + .wp_gpio = -1, + .power_gpio = -1, + .is_8bit = false, +}; + +static struct tegra_sdhci_platform_data tegra_sdhci_platform_data2 = { + .cd_gpio = -1, + .wp_gpio = -1, + .power_gpio = -1, + .is_8bit = 1, + .mmc_data = { + .built_in = 1, + } +}; + +static struct tegra_sdhci_platform_data tegra_sdhci_platform_data3 = { + .cd_gpio = TEGRA_GPIO_PN6, + .wp_gpio = TEGRA_GPIO_PD4, + .power_gpio = TEGRA_GPIO_PN7, + .is_8bit = false, +}; + +static struct tegra_sdhci_platform_data tegra_sdhci_platform_data4 = { + .cd_gpio = -1, + .wp_gpio = -1, + .power_gpio = -1, + .is_8bit = true, +}; + +int __init e1853_sdhci_init(void) +{ + tegra_sdhci_device1.dev.platform_data = &tegra_sdhci_platform_data1; + tegra_sdhci_device2.dev.platform_data = &tegra_sdhci_platform_data2; + tegra_sdhci_device3.dev.platform_data = &tegra_sdhci_platform_data3; + tegra_sdhci_device4.dev.platform_data = &tegra_sdhci_platform_data4; + + platform_device_register(&tegra_sdhci_device1); + platform_device_register(&tegra_sdhci_device2); + platform_device_register(&tegra_sdhci_device3); + platform_device_register(&tegra_sdhci_device4); + + return 0; +} diff --git a/arch/arm/mach-tegra/board-e1853.c b/arch/arm/mach-tegra/board-e1853.c new file mode 100644 index 000000000000..3b6d2bfc3d4c --- /dev/null +++ b/arch/arm/mach-tegra/board-e1853.c @@ -0,0 +1,421 @@ +/* + * arch/arm/mach-tegra/board-e1853.c + * + * 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/init.h> +#include <linux/slab.h> +#include <linux/ctype.h> +#include <linux/platform_device.h> +#include <linux/clk.h> +#include <linux/serial_8250.h> +#include <linux/i2c.h> +#include <linux/i2c/panjit_ts.h> +#include <linux/dma-mapping.h> +#include <linux/delay.h> +#include <linux/i2c-tegra.h> +#include <linux/gpio.h> +#include <linux/input.h> +#include <linux/platform_data/tegra_usb.h> +#include <linux/platform_data/tegra_nor.h> +#include <linux/spi/spi.h> +#include <linux/mtd/partitions.h> +#include <mach/clk.h> +#include <mach/iomap.h> +#include <mach/irqs.h> +#include <mach/pinmux.h> +#include <mach/iomap.h> +#include <mach/io.h> +#include <mach/pci.h> +#include <mach/audio.h> +#include <mach/tegra_e1853_pdata.h> +#include <asm/mach/flash.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <mach/usb_phy.h> +#include <sound/wm8903.h> +#include <mach/tsensor.h> +#include "board.h" +#include "clock.h" +#include "board-e1853.h" +#include "devices.h" +#include "gpio-names.h" +#include "fuse.h" + +static __initdata struct tegra_clk_init_table e1853_clk_init_table[] = { + /* name parent rate enabled */ + { "pll_m", NULL, 0, true}, + { "hda", "pll_p", 108000000, false}, + { "hda2codec_2x", "pll_p", 48000000, false}, + { "pwm", "clk_32k", 32768, false}, + { "blink", "clk_32k", 32768, true}, + { "pll_a", NULL, 552960000, false}, + /* audio cif clock should be faster than i2s */ + { "pll_a_out0", NULL, 24576000, false}, + { "d_audio", "pll_a_out0", 24576000, false}, + { "nor", "pll_p", 86500000, true}, + { "uarta", "pll_p", 480000000, true}, + { "uartb", "pll_p", 480000000, true}, + { "uartc", "pll_p", 480000000, true}, + { "uartd", "pll_p", 480000000, true}, + { "sdmmc2", "pll_p", 52000000, true}, + { "sbc2", "pll_m", 100000000, true}, + { "sbc3", "pll_m", 100000000, true}, + { "sbc4", "pll_m", 100000000, true}, + { "sbc5", "pll_m", 100000000, true}, + { "sbc6", "pll_m", 100000000, true}, + { "cpu_g", "cclk_g", 900000000, true}, + { "i2s0", "pll_a_out0", 24576000, false}, + { "i2s1", "pll_a_out0", 24576000, false}, + { "i2s2", "pll_a_out0", 24576000, false}, + { "i2s3", "pll_a_out0", 24576000, false}, + { "i2s4", "pll_a_out0", 24576000, false}, + { "audio0", "i2s0_sync", 12288000, false}, + { "audio1", "i2s1_sync", 12288000, false}, + { "audio2", "i2s2_sync", 12288000, false}, + { "audio3", "i2s3_sync", 12288000, false}, + { "audio4", "i2s4_sync", 12288000, false}, + { "apbif", "clk_m", 12000000, false}, + { "dam0", "clk_m", 12000000, true}, + { "dam1", "clk_m", 12000000, true}, + { "dam2", "clk_m", 12000000, true}, + { "vi", "pll_p", 470000000, false}, + { "vi_sensor", "pll_p", 150000000, false}, + { "vde", "pll_c", 484000000, true}, + { "host1x", "pll_c", 242000000, true}, + { "mpe", "pll_c", 484000000, true}, + { "se", "pll_m", 625000000, true}, + { "i2c1", "pll_p", 3200000, true}, + { "i2c2", "pll_p", 3200000, true}, + { "i2c3", "pll_p", 3200000, true}, + { "i2c4", "pll_p", 3200000, true}, + { "i2c5", "pll_p", 3200000, true}, + { "sdmmc2", "pll_p", 104000000, false}, + {"wake.sclk", NULL, 334000000, true }, + { NULL, NULL, 0, 0}, +}; + +static struct tegra_i2c_platform_data e1853_i2c1_platform_data = { + .adapter_nr = 0, + .bus_count = 1, + .bus_clk_rate = { 100000, 0 }, +}; + +static struct tegra_i2c_platform_data e1853_i2c2_platform_data = { + .adapter_nr = 1, + .bus_count = 1, + .bus_clk_rate = { 100000, 0 }, + .is_clkon_always = true, +}; + +static struct tegra_i2c_platform_data e1853_i2c4_platform_data = { + .adapter_nr = 3, + .bus_count = 1, + .bus_clk_rate = { 100000, 0 }, +}; + +static struct tegra_i2c_platform_data e1853_i2c5_platform_data = { + .adapter_nr = 4, + .bus_count = 1, + .bus_clk_rate = { 100000, 0 }, +}; + +static struct tegra_pci_platform_data e1853_pci_platform_data = { + .port_status[0] = 1, + .port_status[1] = 1, + .port_status[2] = 1, + .use_dock_detect = 0, + .gpio = 0, +}; + +static void e1853_pcie_init(void) +{ + tegra_pci_device.dev.platform_data = &e1853_pci_platform_data; + platform_device_register(&tegra_pci_device); +} + +static void e1853_i2c_init(void) +{ + tegra_i2c_device1.dev.platform_data = &e1853_i2c1_platform_data; + tegra_i2c_device2.dev.platform_data = &e1853_i2c2_platform_data; + tegra_i2c_device4.dev.platform_data = &e1853_i2c4_platform_data; + tegra_i2c_device5.dev.platform_data = &e1853_i2c5_platform_data; + + platform_device_register(&tegra_i2c_device5); + platform_device_register(&tegra_i2c_device4); + platform_device_register(&tegra_i2c_device2); + platform_device_register(&tegra_i2c_device1); +} + +static struct platform_device *e1853_uart_devices[] __initdata = { + &tegra_uarta_device, + &tegra_uartb_device, + &tegra_uartc_device, + &tegra_uartd_device, +}; +static struct clk *debug_uart_clk; + +static void __init uart_debug_init(void) +{ + /* UARTA is the debug port. */ + pr_info("Selecting UARTA as the debug console\n"); + e1853_uart_devices[0] = &debug_uarta_device; + debug_uart_clk = clk_get_sys("serial8250.0", "uarta"); +} + +static void __init e1853_uart_init(void) +{ + /* Register low speed only if it is selected */ + if (!is_tegra_debug_uartport_hs()) { + uart_debug_init(); + /* Clock enable for the debug channel */ + if (!IS_ERR_OR_NULL(debug_uart_clk)) { + pr_info("The debug console clock name is %s\n", + debug_uart_clk->name); + clk_enable(debug_uart_clk); + clk_set_rate(debug_uart_clk, 408000000); + } else { + pr_err("Not getting the clock %s for debug console\n", + debug_uart_clk->name); + } + } + + platform_add_devices(e1853_uart_devices, + ARRAY_SIZE(e1853_uart_devices)); +} + +#if defined(CONFIG_SPI_TEGRA) && defined(CONFIG_SPI_SPIDEV) +static struct spi_board_info tegra_spi_devices[] __initdata = { + { + .modalias = "spidev", + .bus_num = 1, + .chip_select = 1, + .mode = SPI_MODE_0, + .max_speed_hz = 18000000, + .platform_data = NULL, + .irq = 0, + }, + { + .modalias = "spidev", + .bus_num = 2, + .chip_select = 1, + .mode = SPI_MODE_0, + .max_speed_hz = 18000000, + .platform_data = NULL, + .irq = 0, + }, + { + .modalias = "spidev", + .bus_num = 4, + .chip_select = 2, + .mode = SPI_MODE_0, + .max_speed_hz = 18000000, + .platform_data = NULL, + .irq = 0, + }, +}; + +static void __init e1853_register_spidev(void) +{ + spi_register_board_info(tegra_spi_devices, + ARRAY_SIZE(tegra_spi_devices)); +} +#else +#define e1853_register_spidev() do {} while (0) +#endif + + +static void e1853_spi_init(void) +{ + tegra_spi_device3.name = "spi_slave_tegra"; + platform_device_register(&tegra_spi_device2); + platform_device_register(&tegra_spi_device3); + platform_device_register(&tegra_spi_device5); + e1853_register_spidev(); +} + +static struct platform_device tegra_camera = { + .name = "tegra_camera", + .id = -1, +}; + +static struct platform_device *e1853_devices[] __initdata = { +#if defined(CONFIG_TEGRA_IOVMM_SMMU) + &tegra_smmu_device, +#endif +#if defined(CONFIG_TEGRA_AVP) + &tegra_avp_device, +#endif + &tegra_camera, + &tegra_wdt0_device +}; + +static struct tegra_usb_platform_data tegra_ehci1_utmi_pdata = { + .port_otg = false, + .has_hostpc = true, + .phy_intf = TEGRA_USB_PHY_INTF_UTMI, + .op_mode = TEGRA_USB_OPMODE_HOST, + .u_data.host = { + .vbus_gpio = -1, + .vbus_reg = NULL, + .hot_plug = false, + .remote_wakeup_supported = true, + .power_off_on_suspend = true, + }, + .u_cfg.utmi = { + .hssync_start_delay = 0, + .idle_wait_delay = 17, + .elastic_limit = 16, + .term_range_adj = 6, + .xcvr_setup = 63, + .xcvr_setup_offset = 6, + .xcvr_use_fuses = 1, + .xcvr_lsfslew = 2, + .xcvr_lsrslew = 2, + .xcvr_use_lsb = 1, + }, +}; + +static struct tegra_usb_platform_data tegra_ehci2_utmi_pdata = { + .port_otg = false, + .has_hostpc = true, + .phy_intf = TEGRA_USB_PHY_INTF_UTMI, + .op_mode = TEGRA_USB_OPMODE_HOST, + .u_data.host = { + .vbus_gpio = -1, + .vbus_reg = NULL, + .hot_plug = false, + .remote_wakeup_supported = true, + .power_off_on_suspend = true, + }, + .u_cfg.utmi = { + .hssync_start_delay = 0, + .idle_wait_delay = 17, + .elastic_limit = 16, + .term_range_adj = 6, + .xcvr_setup = 63, + .xcvr_setup_offset = 6, + .xcvr_use_fuses = 1, + .xcvr_lsfslew = 2, + .xcvr_lsrslew = 2, + .xcvr_use_lsb = 1, + }, +}; + +static struct tegra_usb_platform_data tegra_ehci3_utmi_pdata = { + .port_otg = false, + .has_hostpc = true, + .phy_intf = TEGRA_USB_PHY_INTF_UTMI, + .op_mode = TEGRA_USB_OPMODE_HOST, + .u_data.host = { + .vbus_gpio = -1, + .vbus_reg = NULL, + .hot_plug = false, + .remote_wakeup_supported = true, + .power_off_on_suspend = true, + }, + .u_cfg.utmi = { + .hssync_start_delay = 0, + .idle_wait_delay = 17, + .elastic_limit = 16, + .term_range_adj = 6, + .xcvr_setup = 63, + .xcvr_setup_offset = 6, + .xcvr_use_fuses = 1, + .xcvr_lsfslew = 2, + .xcvr_lsrslew = 2, + .xcvr_use_lsb = 1, + }, +}; + +static void e1853_usb_init(void) +{ + tegra_ehci1_device.dev.platform_data = &tegra_ehci1_utmi_pdata; + platform_device_register(&tegra_ehci1_device); + + tegra_ehci2_device.dev.platform_data = &tegra_ehci2_utmi_pdata; + platform_device_register(&tegra_ehci2_device); + + tegra_ehci3_device.dev.platform_data = &tegra_ehci3_utmi_pdata; + platform_device_register(&tegra_ehci3_device); +} + +static struct tegra_nor_platform_data e1853_nor_data = { + .flash = { + .map_name = "cfi_probe", + .width = 2, + }, + .chip_parms = { + .MuxMode = NorMuxMode_ADMux, + .BurstLength = NorBurstLength_CntBurst, + .ReadMode = NorReadMode_Async, + .ReadyActive = NorReadyActive_BeforeData, + /* FIXME: Need to use characterized value */ + .timing_default = { + .timing0 = 0xA0A05585, + .timing1 = 0x200A0406, + }, + .timing_read = { + .timing0 = 0xA0A05585, + .timing1 = 0x00050406, + }, + }, +}; + +static void e1853_nor_init(void) +{ + tegra_nor_device.resource[2].end = TEGRA_NOR_FLASH_BASE + SZ_64M - 1; + tegra_nor_device.dev.platform_data = &e1853_nor_data; + platform_device_register(&tegra_nor_device); +} + +static void __init tegra_e1853_init(void) +{ + tegra_init_board_info(); + tegra_clk_init_from_table(e1853_clk_init_table); + e1853_pinmux_init(); + e1853_i2c_init(); + e1853_gpio_init(); + e1853_uart_init(); + e1853_usb_init(); + e1853_sdhci_init(); + e1853_spi_init(); + platform_add_devices(e1853_devices, ARRAY_SIZE(e1853_devices)); + e1853_panel_init(); + e1853_nor_init(); + e1853_pcie_init(); +} + +static void __init tegra_e1853_reserve(void) +{ +#if defined(CONFIG_NVMAP_CONVERT_CARVEOUT_TO_IOVMM) + tegra_reserve(0, SZ_8M, SZ_8M); +#else + tegra_reserve(SZ_128M, SZ_8M, SZ_8M); +#endif +} + +MACHINE_START(E1853, "e1853") + .boot_params = 0x80000100, + .init_irq = tegra_init_irq, + .init_early = tegra_init_early, + .init_machine = tegra_e1853_init, + .map_io = tegra_map_common_io, + .reserve = tegra_e1853_reserve, + .timer = &tegra_timer, +MACHINE_END diff --git a/arch/arm/mach-tegra/board-e1853.h b/arch/arm/mach-tegra/board-e1853.h new file mode 100644 index 000000000000..58b8ab8725af --- /dev/null +++ b/arch/arm/mach-tegra/board-e1853.h @@ -0,0 +1,28 @@ +/* + * arch/arm/mach-tegra/e1853/board-e1853.h + * + * 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 _MACH_TEGRA_BOARD_E1853_H +#define _MACH_TEGRA_BOARD_E1853_H + +int e1853_sdhci_init(void); +int e1853_pinmux_init(void); +int e1853_panel_init(void); +int e1853_gpio_init(void); +int e1853_pins_state_init(void); + +#endif diff --git a/arch/arm/mach-tegra/board-enterprise-memory.c b/arch/arm/mach-tegra/board-enterprise-memory.c index 36a8264c2a21..1fc0d3c3fddd 100644 --- a/arch/arm/mach-tegra/board-enterprise-memory.c +++ b/arch/arm/mach-tegra/board-enterprise-memory.c @@ -116,7 +116,7 @@ static const struct tegra_emc_table enterprise_emc_tables_kmmll0_a02[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000164, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00050001, /* MC_EMEM_ARB_CFG */ + 0x00050002, /* MC_EMEM_ARB_CFG */ 0xc0000008, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -236,7 +236,7 @@ static const struct tegra_emc_table enterprise_emc_tables_kmmll0_a02[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x800001c2, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00020001, /* MC_EMEM_ARB_CFG */ + 0x00030003, /* MC_EMEM_ARB_CFG */ 0xc0000008, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -356,7 +356,7 @@ static const struct tegra_emc_table enterprise_emc_tables_kmmll0_a02[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000287, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00010001, /* MC_EMEM_ARB_CFG */ + 0x00010003, /* MC_EMEM_ARB_CFG */ 0xc000000a, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -476,7 +476,7 @@ static const struct tegra_emc_table enterprise_emc_tables_kmmll0_a02[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x8000040b, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000001, /* MC_EMEM_ARB_CFG */ + 0x00000003, /* MC_EMEM_ARB_CFG */ 0xc0000013, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -596,7 +596,7 @@ static const struct tegra_emc_table enterprise_emc_tables_kmmll0_a02[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000713, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000003, /* MC_EMEM_ARB_CFG */ + 0x00000006, /* MC_EMEM_ARB_CFG */ 0xc0000025, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -716,7 +716,7 @@ static const struct tegra_emc_table enterprise_emc_tables_kmmll0_a02[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000ce6, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000006, /* MC_EMEM_ARB_CFG */ + 0x0000000c, /* MC_EMEM_ARB_CFG */ 0xc0000048, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000002, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000003, /* MC_EMEM_ARB_TIMING_RP */ diff --git a/arch/arm/mach-tegra/board-enterprise-panel.c b/arch/arm/mach-tegra/board-enterprise-panel.c index 837635bf0731..c27201171e4b 100644 --- a/arch/arm/mach-tegra/board-enterprise-panel.c +++ b/arch/arm/mach-tegra/board-enterprise-panel.c @@ -1,7 +1,7 @@ /* * arch/arm/mach-tegra/board-enterprise-panel.c * - * Copyright (c) 2011-2012, NVIDIA Corporation. + * Copyright (c) 2011-2012, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -169,6 +169,16 @@ static int enterprise_backlight_notify(struct device *unused, int brightness) static int enterprise_disp1_check_fb(struct device *dev, struct fb_info *info); +static struct platform_pwm_backlight_data external_pwm_disp1_backlight_data = { + .pwm_id = 3, + .max_brightness = 255, + .dft_brightness = 224, + .pwm_period_ns = 1000000, + .notify = enterprise_backlight_notify, + /* Only toggle backlight on fb blank notifications for disp1 */ + .check_fb = enterprise_disp1_check_fb, +}; + #if IS_EXTERNAL_PWM static struct platform_pwm_backlight_data enterprise_disp1_backlight_data = { .pwm_id = 3, @@ -214,10 +224,21 @@ static struct platform_device enterprise_disp1_backlight_device = { }, }; +static struct platform_device external_pwm_disp1_backlight_device = { + .name = "pwm-backlight", + .id = -1, + .dev = { + .platform_data = &external_pwm_disp1_backlight_data, + }, +}; #ifdef CONFIG_TEGRA_DC static int enterprise_hdmi_vddio_enable(void) { int ret; + struct board_info board_info; + + tegra_get_board_info(&board_info); + if (!enterprise_hdmi_vddio) { enterprise_hdmi_vddio = regulator_get(NULL, "hdmi_5v0"); if (IS_ERR_OR_NULL(enterprise_hdmi_vddio)) { @@ -234,16 +255,40 @@ static int enterprise_hdmi_vddio_enable(void) enterprise_hdmi_vddio = NULL; return ret; } + if (board_info.board_id == BOARD_E1239) { + ret = gpio_request(TEGRA_GPIO_PM4, "en_hdmi_buffers"); + if (ret < 0) { + pr_err("%s: gpio_request failed %d\n", __func__, ret); + return ret; + } + + ret = gpio_direction_output(TEGRA_GPIO_PM4, 1); + if (ret < 0) { + pr_err("%s: gpio_direction_ouput failed %d\n", + __func__, ret); + gpio_free(TEGRA_GPIO_PM4); + return ret; + } + } + return ret; } static int enterprise_hdmi_vddio_disable(void) { + struct board_info board_info; + + tegra_get_board_info(&board_info); + if (enterprise_hdmi_vddio) { regulator_disable(enterprise_hdmi_vddio); regulator_put(enterprise_hdmi_vddio); enterprise_hdmi_vddio = NULL; } + if (board_info.board_id == BOARD_E1239) { + gpio_set_value(TEGRA_GPIO_PM4, 0); + gpio_free(TEGRA_GPIO_PM4); + } return 0; } @@ -530,12 +575,10 @@ static int enterprise_dsi_panel_enable(void) if (ret) return ret; -#if IS_EXTERNAL_PWM - tegra_gpio_disable(enterprise_bl_pwm); -#endif #if DSI_PANEL_RESET - if (board_info.fab >= BOARD_FAB_A03) { + if ((board_info.fab >= BOARD_FAB_A03) || + (board_info.board_id == BOARD_E1239)) { if (enterprise_lcd_reg == NULL) { enterprise_lcd_reg = regulator_get(NULL, "lcd_vddio_en"); if (IS_ERR_OR_NULL(enterprise_lcd_reg)) { @@ -554,16 +597,13 @@ static int enterprise_dsi_panel_enable(void) } } - if (kernel_1st_panel_init != true) { + if (kernel_1st_panel_init == true) { ret = gpio_request(enterprise_dsi_panel_reset, "panel reset"); if (ret < 0) return ret; - - ret = gpio_direction_output(enterprise_dsi_panel_reset, 0); - if (ret < 0) { - gpio_free(enterprise_dsi_panel_reset); - return ret; - } + kernel_1st_panel_init = false; + } else { + gpio_direction_output(enterprise_dsi_panel_reset, 0); gpio_set_value(enterprise_dsi_panel_reset, 0); udelay(2000); @@ -581,10 +621,7 @@ static int enterprise_dsi_panel_disable(void) regulator_disable(enterprise_lcd_reg); #if DSI_PANEL_RESET - if (kernel_1st_panel_init != true) { - gpio_free(enterprise_dsi_panel_reset); - } else - kernel_1st_panel_init = false; + gpio_direction_output(enterprise_dsi_panel_reset, 0); #endif return 0; } @@ -824,6 +861,13 @@ static struct platform_device *enterprise_gfx_devices[] __initdata = { #endif }; +static struct platform_device *external_pwm_gfx_devices[] __initdata = { +#if defined(CONFIG_TEGRA_NVMAP) + &enterprise_nvmap_device, +#endif + &tegra_pwfm3_device, +}; + static struct platform_device *enterprise_bl_devices[] = { &enterprise_disp1_backlight_device, }; @@ -871,14 +915,22 @@ int __init enterprise_panel_init(void) BUILD_BUG_ON(ARRAY_SIZE(enterprise_bl_output_measured_a03) != 256); BUILD_BUG_ON(ARRAY_SIZE(enterprise_bl_output_measured_a02) != 256); - if (board_info.fab >= BOARD_FAB_A03) { + if (board_info.board_id != BOARD_E1239) { + if (board_info.fab >= BOARD_FAB_A03) { #if !(IS_EXTERNAL_PWM) - enterprise_disp1_backlight_data.clk_div = 0x1D; + enterprise_disp1_backlight_data.clk_div = 0x1D; #endif - bl_output = enterprise_bl_output_measured_a03; - } else - bl_output = enterprise_bl_output_measured_a02; - + bl_output = enterprise_bl_output_measured_a03; + } else + bl_output = enterprise_bl_output_measured_a02; + } else { + enterprise_sd_settings.bl_device = + &external_pwm_disp1_backlight_device; + enterprise_bl_devices[0] = + &external_pwm_disp1_backlight_device; + bl_output = + enterprise_bl_output_measured_a03; + } enterprise_dsi.chip_id = tegra_get_chipid(); enterprise_dsi.chip_rev = tegra_get_revision(); @@ -890,13 +942,25 @@ int __init enterprise_panel_init(void) gpio_request(enterprise_hdmi_hpd, "hdmi_hpd"); gpio_direction_input(enterprise_hdmi_hpd); - gpio_request(enterprise_lcd_2d_3d, "lcd_2d_3d"); - gpio_direction_output(enterprise_lcd_2d_3d, 0); - enterprise_stereo_set_mode(enterprise_stereo.mode_2d_3d); + if (board_info.board_id != BOARD_E1239) { + gpio_request(enterprise_lcd_2d_3d, "lcd_2d_3d"); + gpio_direction_output(enterprise_lcd_2d_3d, 0); + enterprise_stereo_set_mode(enterprise_stereo.mode_2d_3d); - gpio_request(enterprise_lcd_swp_pl, "lcd_swp_pl"); - gpio_direction_output(enterprise_lcd_swp_pl, 0); - enterprise_stereo_set_orientation(enterprise_stereo.orientation); + gpio_request(enterprise_lcd_swp_pl, "lcd_swp_pl"); + gpio_direction_output(enterprise_lcd_swp_pl, 0); + enterprise_stereo_set_orientation( + enterprise_stereo.orientation); +#if IS_EXTERNAL_PWM + gpio_request(enterprise_bl_pwm, "bl_pwm"); + gpio_free(enterprise_bl_pwm); +#endif + } else { + /* External pwm is used but do not use IS_EXTERNAL_PWM + compiler switch for TAI */ + gpio_request(enterprise_bl_pwm, "bl_pwm"); + gpio_free(enterprise_bl_pwm); + } #if !(DC_CTRL_MODE & TEGRA_DC_OUT_ONE_SHOT_MODE) gpio_request(enterprise_lcd_swp_pl, "lcd_te"); @@ -916,9 +980,13 @@ int __init enterprise_panel_init(void) return err; #endif - err = platform_add_devices(enterprise_gfx_devices, - ARRAY_SIZE(enterprise_gfx_devices)); - + if (board_info.board_id != BOARD_E1239) { + err = platform_add_devices(enterprise_gfx_devices, + ARRAY_SIZE(enterprise_gfx_devices)); + } else { + err = platform_add_devices(external_pwm_gfx_devices, + ARRAY_SIZE(external_pwm_gfx_devices)); + } #if defined(CONFIG_TEGRA_GRHOST) && defined(CONFIG_TEGRA_DC) res = nvhost_get_resource_byname(&enterprise_disp1_device, IORESOURCE_MEM, "fbmem"); diff --git a/arch/arm/mach-tegra/board-enterprise-pinmux.c b/arch/arm/mach-tegra/board-enterprise-pinmux.c index 721eb0d27576..efbdeb337e15 100644 --- a/arch/arm/mach-tegra/board-enterprise-pinmux.c +++ b/arch/arm/mach-tegra/board-enterprise-pinmux.c @@ -1,7 +1,7 @@ /* * arch/arm/mach-tegra/board-enterprise-pinmux.c * - * Copyright (C) 2011 NVIDIA Corporation + * Copyright (C) 2011-2012, NVIDIA CORPORATION. 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 @@ -84,6 +84,9 @@ static __initdata struct tegra_drive_pingroup_config enterprise_drive_pinmux[] = /* UART3 */ SET_DRIVE(UART3, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST), + + /* SDMMC1 */ + SET_DRIVE(SDIO1, DISABLE, DISABLE, DIV_1, 46, 42, FAST, FAST), }; #define DEFAULT_PINMUX(_pingroup, _mux, _pupd, _tri, _io) \ @@ -153,7 +156,6 @@ static __initdata struct tegra_pingroup_config enterprise_pinmux_common[] = { /* SDMMC4 pinmux */ DEFAULT_PINMUX(SDMMC4_CLK, SDMMC4, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(SDMMC4_CMD, SDMMC4, PULL_UP, NORMAL, INPUT), DEFAULT_PINMUX(SDMMC4_DAT0, SDMMC4, PULL_UP, NORMAL, INPUT), DEFAULT_PINMUX(SDMMC4_DAT1, SDMMC4, PULL_UP, NORMAL, INPUT), DEFAULT_PINMUX(SDMMC4_DAT2, SDMMC4, PULL_UP, NORMAL, INPUT), @@ -192,47 +194,7 @@ static __initdata struct tegra_pingroup_config enterprise_pinmux_common[] = { DEFAULT_PINMUX(ULPI_DATA5, ULPI, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(ULPI_DATA6, ULPI, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(ULPI_DATA7, ULPI, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(ULPI_CLK, ULPI, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(ULPI_DIR, ULPI, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(ULPI_NXT, ULPI, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(ULPI_STP, ULPI, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP3_FS, I2S2, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP3_DIN, I2S2, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP3_DOUT, I2S2, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP3_SCLK, I2S2, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(GPIO_PV2, RSVD1, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(GPIO_PV3, RSVD1, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(LCD_PWR1, DISPLAYA, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(LCD_PWR2, DISPLAYA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_CS0_N, DISPLAYA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_DC0, DISPLAYA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_DE, DISPLAYA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_D0, DISPLAYA, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(LCD_D1, DISPLAYA, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(LCD_D2, DISPLAYA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_D3, DISPLAYA, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(LCD_D4, DISPLAYA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_D5, DISPLAYA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_D6, RSVD1, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_D7, RSVD1, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(LCD_D8, DISPLAYA, NORMAL, TRISTATE, INPUT), - DEFAULT_PINMUX(LCD_D9, DISPLAYA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_D11, DISPLAYA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_D12, DISPLAYA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_D13, DISPLAYA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_D14, DISPLAYA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_D15, DISPLAYA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_D16, DISPLAYA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_D17, DISPLAYA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_D18, DISPLAYA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_D19, DISPLAYA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_D20, DISPLAYA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_D21, DISPLAYA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_D22, RSVD1, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_D23, DISPLAYA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_CS1_N, DISPLAYA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(LCD_M1, DISPLAYA, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(LCD_DC1, DISPLAYA, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(VI_D0, RSVD1, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(VI_D1, SDMMC2, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(VI_D2, SDMMC2, NORMAL, NORMAL, INPUT), @@ -243,84 +205,27 @@ static __initdata struct tegra_pingroup_config enterprise_pinmux_common[] = { DEFAULT_PINMUX(VI_D10, RSVD1, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(VI_MCLK, VI, PULL_UP, NORMAL, INPUT), - DEFAULT_PINMUX(UART2_RXD, IRDA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(UART2_TXD, IRDA, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(UART2_RTS_N, UARTB, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(UART2_CTS_N, UARTB, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(UART3_TXD, UARTC, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(UART3_RXD, UARTC, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(UART3_CTS_N, UARTC, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(UART3_RTS_N, UARTC, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(GPIO_PU0, UARTA, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(GPIO_PU1, UARTA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(GPIO_PU2, UARTA, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(GPIO_PU3, UARTA, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(GPIO_PU4, PWM1, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(GPIO_PU5, PWM2, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(GPIO_PU6, PWM3, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP4_FS, I2S3, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP4_DIN, I2S3, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP4_DOUT, I2S3, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP4_SCLK, I2S3, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(GMI_AD8, PWM0, NORMAL, NORMAL, OUTPUT), DEFAULT_PINMUX(GMI_AD9, NAND, NORMAL, NORMAL, OUTPUT), DEFAULT_PINMUX(GMI_AD10, NAND, NORMAL, NORMAL, OUTPUT), #if IS_EXTERNAL_PWM DEFAULT_PINMUX(GMI_AD11, PWM3, NORMAL, NORMAL, OUTPUT), #endif - DEFAULT_PINMUX(GMI_A16, UARTD, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(GMI_A17, UARTD, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(GMI_A18, UARTD, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(GMI_A19, UARTD, NORMAL, NORMAL, OUTPUT), - DEFAULT_PINMUX(CAM_MCLK, VI_ALT2, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(GPIO_PCC1, RSVD1, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(GPIO_PBB0, RSVD1, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(GPIO_PBB3, VGP3, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(GPIO_PBB7, I2S4, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(GPIO_PCC2, I2S4, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(JTAG_RTCK, RTCK, NORMAL, NORMAL, OUTPUT), DEFAULT_PINMUX(KB_ROW0, KBC, PULL_UP, NORMAL, INPUT), DEFAULT_PINMUX(KB_ROW1, KBC, PULL_UP, NORMAL, INPUT), DEFAULT_PINMUX(KB_ROW2, KBC, PULL_UP, NORMAL, INPUT), DEFAULT_PINMUX(KB_ROW3, KBC, PULL_UP, NORMAL, INPUT), - DEFAULT_PINMUX(KB_ROW10, KBC, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(KB_ROW12, KBC, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(KB_COL0, KBC, PULL_UP, NORMAL, INPUT), DEFAULT_PINMUX(KB_COL1, KBC, PULL_UP, NORMAL, INPUT), DEFAULT_PINMUX(KB_COL2, KBC, PULL_UP, NORMAL, INPUT), - DEFAULT_PINMUX(KB_COL3, KBC, PULL_UP, NORMAL, INPUT), DEFAULT_PINMUX(KB_COL4, KBC, PULL_UP, NORMAL, INPUT), DEFAULT_PINMUX(KB_COL5, KBC, PULL_UP, NORMAL, INPUT), - DEFAULT_PINMUX(GPIO_PV0, RSVD, PULL_UP, NORMAL, INPUT), DEFAULT_PINMUX(CLK_32K_OUT, BLINK, PULL_DOWN, TRISTATE, OUTPUT), DEFAULT_PINMUX(SYS_CLK_REQ, SYSCLK, NORMAL, NORMAL, OUTPUT), DEFAULT_PINMUX(OWR, OWR, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP1_FS, I2S0, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP1_DIN, I2S0, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP1_DOUT, I2S0, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP1_SCLK, I2S0, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(CLK1_REQ, DAP, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(CLK1_OUT, EXTPERIPH1, NORMAL, NORMAL, INPUT), -#if 0 /* For HDA realtek Codec */ - DEFAULT_PINMUX(SPDIF_IN, DAP2, PULL_DOWN, NORMAL, INPUT), -#else - DEFAULT_PINMUX(SPDIF_IN, SPDIF, NORMAL, NORMAL, INPUT), -#endif -#if 0 /* For HDA realtek Codec */ - DEFAULT_PINMUX(DAP2_FS, HDA, PULL_DOWN, NORMAL, INPUT), - DEFAULT_PINMUX(DAP2_DIN, HDA, PULL_DOWN, NORMAL, INPUT), - DEFAULT_PINMUX(DAP2_DOUT, HDA, PULL_DOWN, NORMAL, INPUT), - DEFAULT_PINMUX(DAP2_SCLK, HDA, PULL_DOWN, NORMAL, INPUT), -#else - DEFAULT_PINMUX(DAP2_FS, I2S1, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP2_DIN, I2S1, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP2_DOUT, I2S1, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(DAP2_SCLK, I2S1, NORMAL, NORMAL, INPUT), -#endif DEFAULT_PINMUX(SPI2_CS1_N, SPI2, PULL_UP, NORMAL, INPUT), - DEFAULT_PINMUX(SPI1_MOSI, SPI1, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(SPI1_SCK, SPI1, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(SPI1_MISO, SPI1, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(PEX_L0_PRSNT_N, PCIE, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(PEX_L0_RST_N, PCIE, NORMAL, NORMAL, OUTPUT), DEFAULT_PINMUX(PEX_L0_CLKREQ_N, PCIE, NORMAL, NORMAL, INPUT), @@ -333,25 +238,8 @@ static __initdata struct tegra_pingroup_config enterprise_pinmux_common[] = { DEFAULT_PINMUX(PEX_L2_CLKREQ_N, PCIE, NORMAL, NORMAL, INPUT), CEC_PINMUX(HDMI_CEC, CEC, NORMAL, TRISTATE, OUTPUT, DEFAULT, DISABLE), DEFAULT_PINMUX(HDMI_INT, RSVD0, NORMAL, TRISTATE, INPUT), - - /* Gpios */ - /* SDMMC1 CD gpio */ - DEFAULT_PINMUX(GMI_IORDY, RSVD1, PULL_UP, NORMAL, INPUT), - /* SDMMC1 WP gpio */ DEFAULT_PINMUX(VI_D11, RSVD1, PULL_UP, NORMAL, INPUT), - - /* Touch panel GPIO */ - /* Touch IRQ */ - DEFAULT_PINMUX(GMI_AD12, NAND, NORMAL, NORMAL, INPUT), - - /* Touch RESET */ - DEFAULT_PINMUX(GMI_AD14, NAND, NORMAL, NORMAL, INPUT), - DEFAULT_PINMUX(GMI_AD15, NAND, PULL_UP, TRISTATE, INPUT), - - /* Power rails GPIO */ - DEFAULT_PINMUX(KB_ROW8, KBC, PULL_UP, NORMAL, INPUT), - VI_PINMUX(VI_D6, VI, NORMAL, NORMAL, OUTPUT, DISABLE, DISABLE), VI_PINMUX(VI_D8, SDMMC2, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), VI_PINMUX(VI_D9, SDMMC2, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), @@ -363,6 +251,97 @@ static __initdata struct tegra_pingroup_config enterprise_pinmux_common[] = { static __initdata struct tegra_pingroup_config enterprise_pinmux_a03[] = { DEFAULT_PINMUX(LCD_PWR0, DISPLAYA, NORMAL, NORMAL, OUTPUT), DEFAULT_PINMUX(LCD_D10, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(SDMMC4_CMD, SDMMC4, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(ULPI_CLK, ULPI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(ULPI_DIR, ULPI, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(ULPI_NXT, ULPI, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(ULPI_STP, ULPI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP3_FS, I2S2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP3_DIN, I2S2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP3_DOUT, I2S2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP3_SCLK, I2S2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PV3, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_PWR1, DISPLAYA, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_PWR2, DISPLAYA, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(LCD_CS0_N, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_DC0, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_DE, DISPLAYA, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(LCD_D0, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D1, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D2, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D3, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D4, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D5, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D6, RSVD1, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D7, RSVD1, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D8, DISPLAYA, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(LCD_D9, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D11, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D12, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D13, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D14, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D15, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D16, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D17, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D18, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D19, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D20, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_D21, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D22, RSVD1, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D23, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_CS1_N, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_M1, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_DC1, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(UART2_RXD, IRDA, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(UART2_TXD, IRDA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(UART2_RTS_N, UARTB, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(UART2_CTS_N, UARTB, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(UART3_TXD, UARTC, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(UART3_RXD, UARTC, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(UART3_CTS_N, UARTC, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(UART3_RTS_N, UARTC, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GPIO_PU0, UARTA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GPIO_PU1, UARTA, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(GPIO_PU2, UARTA, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(GPIO_PU3, UARTA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GPIO_PU4, PWM1, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GPIO_PU5, PWM2, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(GPIO_PU6, PWM3, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(DAP4_FS, I2S3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP4_DIN, I2S3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP4_DOUT, I2S3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP4_SCLK, I2S3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_A16, UARTD, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GMI_A17, UARTD, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(GMI_A18, UARTD, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(GMI_A19, UARTD, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(CAM_MCLK, VI_ALT2, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GPIO_PCC1, I2S4, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PBB0, I2S4, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PBB3, VGP3, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GPIO_PBB7, I2S4, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PCC2, I2S4, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW10, KBC, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(KB_ROW12, KBC, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(KB_COL3, KBC, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GPIO_PV0, RSVD, PULL_UP, TRISTATE, INPUT), + DEFAULT_PINMUX(DAP1_FS, I2S0, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP1_DIN, I2S0, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP1_DOUT, I2S0, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP1_SCLK, I2S0, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(CLK1_OUT, EXTPERIPH1, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(SPDIF_IN, SPDIF, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(DAP2_FS, I2S1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP2_DIN, I2S1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP2_DOUT, I2S1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP2_SCLK, I2S1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(SPI1_MOSI, SPI1, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(SPI1_SCK, SPI1, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(SPI1_MISO, SPI1, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GMI_IORDY, RSVD1, PULL_UP, TRISTATE, INPUT), + DEFAULT_PINMUX(GMI_AD12, NAND, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(GMI_AD14, NAND, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(KB_ROW8, KBC, PULL_UP, TRISTATE, INPUT), }; static __initdata struct tegra_pingroup_config enterprise_unused_pinmux_common[] = { @@ -423,15 +402,108 @@ static __initdata struct tegra_pingroup_config enterprise_unused_pinmux_common[] DEFAULT_PINMUX(SPI2_MISO, SPI2, PULL_DOWN, TRISTATE, OUTPUT), }; -static __initdata struct tegra_pingroup_config enterprise_unused_pinmux_a02[] = { - DEFAULT_PINMUX(LCD_D10, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), - DEFAULT_PINMUX(LCD_PWR0, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), +static __initdata struct tegra_pingroup_config enterprise_pinmux_a02[] = { + DEFAULT_PINMUX(LCD_D10, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_PWR0, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(SDMMC4_CMD, SDMMC4, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(ULPI_CLK, ULPI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(ULPI_DIR, ULPI, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(ULPI_NXT, ULPI, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(ULPI_STP, ULPI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP3_FS, I2S2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP3_DIN, I2S2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP3_DOUT, I2S2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP3_SCLK, I2S2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PV3, RSVD1, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_PWR1, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_PWR2, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_CS0_N, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_DC0, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_DE, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D0, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D1, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D2, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D3, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D4, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D5, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D6, RSVD1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D7, RSVD1, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D8, DISPLAYA, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(LCD_D9, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D11, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D12, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D13, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D14, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D15, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D16, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D17, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D18, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D19, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D20, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D21, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D22, RSVD1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D23, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_CS1_N, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_M1, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_DC1, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(UART2_RXD, IRDA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(UART2_TXD, IRDA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(UART2_RTS_N, UARTB, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(UART2_CTS_N, UARTB, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(UART3_TXD, UARTC, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(UART3_RXD, UARTC, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(UART3_CTS_N, UARTC, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(UART3_RTS_N, UARTC, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GPIO_PU0, UARTA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GPIO_PU1, UARTA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PU2, UARTA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PU3, UARTA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GPIO_PU4, PWM1, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GPIO_PU5, PWM2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PU6, PWM3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP4_FS, I2S3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP4_DIN, I2S3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP4_DOUT, I2S3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP4_SCLK, I2S3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_A16, UARTD, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GMI_A17, UARTD, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_A18, UARTD, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_A19, UARTD, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(CAM_MCLK, VI_ALT2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PCC1, RSVD1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PBB0, RSVD1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PBB3, VGP3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PBB7, I2S4, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PCC2, I2S4, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW10, KBC, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW12, KBC, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(KB_COL3, KBC, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PV0, RSVD, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(DAP1_FS, I2S0, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP1_DIN, I2S0, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP1_DOUT, I2S0, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP1_SCLK, I2S0, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(CLK1_OUT, EXTPERIPH1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(SPDIF_IN, SPDIF, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP2_FS, I2S1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP2_DIN, I2S1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP2_DOUT, I2S1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP2_SCLK, I2S1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(SPI1_MOSI, SPI1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(SPI1_SCK, SPI1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(SPI1_MISO, SPI1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_IORDY, RSVD1, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_AD12, NAND, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_AD14, NAND, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW8, KBC, PULL_UP, NORMAL, INPUT), }; static struct tegra_gpio_table gpio_table[] = { { .gpio = TEGRA_GPIO_HP_DET, .enable = true }, }; - +static struct tegra_gpio_table tai_gpio_table[] = { + { .gpio = TEGRA_GPIO_CODEC_RST, .enable = true }, +}; struct pin_info_low_power_mode { char name[16]; int gpio_nr; @@ -512,6 +584,367 @@ static __initdata struct pin_info_low_power_mode enterprise_unused_gpio_pins_a02 PIN_GPIO_LPM("LCD_PWR0", TEGRA_GPIO_PB2, 0, 0), }; +static __initdata struct pin_info_low_power_mode enterprise_gpio_pins_a03[] = { + PIN_GPIO_LPM("GPIO_PV3", TEGRA_GPIO_PV3, 0, 0), + PIN_GPIO_LPM("LCD_DC0", TEGRA_GPIO_PN6, 0, 0), + PIN_GPIO_LPM("LCD_D5", TEGRA_GPIO_PE5, 0, 0), + PIN_GPIO_LPM("LCD_D20", TEGRA_GPIO_PM4, 0, 0), + PIN_GPIO_LPM("LCD_DC1", TEGRA_GPIO_PD2, 0, 0), + PIN_GPIO_LPM("GPIO_PU4", TEGRA_GPIO_PU4, 0, 0), + PIN_GPIO_LPM("KB_COL3", TEGRA_GPIO_PQ3, 0, 0), + PIN_GPIO_LPM("SPI1_MOSI", TEGRA_GPIO_PX4, 0, 0), + PIN_GPIO_LPM("SPI1_MISO", TEGRA_GPIO_PX7, 0, 0), + PIN_GPIO_LPM("SPI1_SCK", TEGRA_GPIO_PX5, 0, 0), +}; +/*******************************TAI pinmux (E1239) ************************/ +static __initdata struct tegra_pingroup_config tai_pinmux_common[] = { + /* SDMMC1 pinmux */ + DEFAULT_PINMUX(SDMMC1_CLK, SDMMC1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC1_CMD, SDMMC1, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC1_DAT3, SDMMC1, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC1_DAT2, SDMMC1, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC1_DAT1, SDMMC1, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC1_DAT0, SDMMC1, PULL_UP, NORMAL, INPUT), + + /* SDMMC3 pinmux */ + DEFAULT_PINMUX(SDMMC3_CLK, SDMMC3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC3_CMD, SDMMC3, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC3_DAT0, SDMMC3, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC3_DAT1, SDMMC3, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC3_DAT2, SDMMC3, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC3_DAT3, SDMMC3, PULL_UP, NORMAL, INPUT), + + /* SDMMC4 pinmux */ + DEFAULT_PINMUX(SDMMC4_CLK, SDMMC4, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC4_CMD, SDMMC4, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC4_DAT0, SDMMC4, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC4_DAT1, SDMMC4, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC4_DAT2, SDMMC4, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC4_DAT3, SDMMC4, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC4_DAT4, SDMMC4, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC4_DAT5, SDMMC4, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC4_DAT6, SDMMC4, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC4_DAT7, SDMMC4, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC4_RST_N, RSVD1, PULL_DOWN, NORMAL, INPUT), + + /* I2C1 pinmux */ + I2C_PINMUX(GEN1_I2C_SCL, I2C1, NORMAL, NORMAL, INPUT, DISABLE, ENABLE), + I2C_PINMUX(GEN1_I2C_SDA, I2C1, NORMAL, NORMAL, INPUT, DISABLE, ENABLE), + + /* I2C2 pinmux */ + I2C_PINMUX(GEN2_I2C_SCL, I2C2, NORMAL, NORMAL, INPUT, DISABLE, ENABLE), + I2C_PINMUX(GEN2_I2C_SDA, I2C2, NORMAL, NORMAL, INPUT, DISABLE, ENABLE), + + /* I2C3 pinmux */ + I2C_PINMUX(CAM_I2C_SCL, I2C3, NORMAL, NORMAL, INPUT, DISABLE, ENABLE), + I2C_PINMUX(CAM_I2C_SDA, I2C3, NORMAL, NORMAL, INPUT, DISABLE, ENABLE), + + /* I2C4 pinmux */ + I2C_PINMUX(DDC_SCL, I2C4, PULL_UP, NORMAL, INPUT, DISABLE, DISABLE), + I2C_PINMUX(DDC_SDA, I2C4, PULL_UP, NORMAL, INPUT, DISABLE, DISABLE), + + /* Power I2C pinmux */ + I2C_PINMUX(PWR_I2C_SCL, I2CPWR, NORMAL, NORMAL, INPUT, DISABLE, ENABLE), + I2C_PINMUX(PWR_I2C_SDA, I2CPWR, NORMAL, NORMAL, INPUT, DISABLE, ENABLE), + + DEFAULT_PINMUX(ULPI_DATA0, ULPI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(ULPI_DATA1, ULPI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(ULPI_DATA2, ULPI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(ULPI_DATA3, ULPI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(ULPI_DATA4, ULPI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(ULPI_DATA5, ULPI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(ULPI_DATA6, ULPI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(ULPI_DATA7, ULPI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(ULPI_CLK, ULPI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(ULPI_DIR, ULPI, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(ULPI_NXT, ULPI, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(ULPI_STP, ULPI, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP3_FS, I2S2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP3_DIN, I2S2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP3_DOUT, I2S2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP3_SCLK, I2S2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PV2, RSVD1, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GPIO_PV3, RSVD1, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_CS0_N, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_DC0, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_DE, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D0, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D1, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D2, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D3, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D4, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D5, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D6, RSVD1, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D7, RSVD1, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D8, DISPLAYA, NORMAL, TRISTATE, INPUT), + DEFAULT_PINMUX(LCD_D9, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D11, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D12, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D13, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D14, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D15, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D16, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D17, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D18, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D20, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D21, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D22, RSVD1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_D23, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_CS1_N, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_DC1, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(VI_D0, RSVD1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(VI_D1, SDMMC2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(VI_D2, SDMMC2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(VI_D3, SDMMC2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(VI_D4, VI, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(VI_D5, SDMMC2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(VI_D7, SDMMC2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(VI_D10, RSVD1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(VI_MCLK, VI, PULL_UP, NORMAL, INPUT), + + DEFAULT_PINMUX(UART2_RXD, IRDA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(UART2_TXD, IRDA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(UART2_RTS_N, UARTB, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(UART2_CTS_N, UARTB, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(UART3_TXD, UARTC, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(UART3_RXD, UARTC, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(UART3_CTS_N, UARTC, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(UART3_RTS_N, UARTC, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GPIO_PU0, UARTA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GPIO_PU1, UARTA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PU2, UARTA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PU3, UARTA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GPIO_PU4, PWM1, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GPIO_PU5, PWM2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PU6, PWM3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP4_FS, I2S3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP4_DIN, I2S3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP4_DOUT, I2S3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP4_SCLK, I2S3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_AD11, PWM3, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GMI_A16, UARTD, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GMI_A17, UARTD, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_A18, UARTD, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GMI_A19, UARTD, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(CAM_MCLK, VI_ALT2, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PCC1, I2S4, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PBB0, I2S4, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PBB3, VGP3, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PBB7, I2S4, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PCC2, I2S4, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(JTAG_RTCK, RTCK, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(KB_ROW0, KBC, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW1, KBC, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW2, KBC, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW3, KBC, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW10, KBC, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(KB_ROW12, KBC, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(KB_COL0, KBC, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_COL1, KBC, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_COL2, KBC, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_COL3, KBC, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_COL4, KBC, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(KB_COL5, KBC, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(GPIO_PV0, RSVD, PULL_UP, NORMAL, INPUT), + DEFAULT_PINMUX(CLK_32K_OUT, BLINK, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(SYS_CLK_REQ, SYSCLK, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(OWR, OWR, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP1_FS, I2S0, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP1_DIN, I2S0, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP1_DOUT, I2S0, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP1_SCLK, I2S0, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(CLK1_REQ, DAP, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(CLK1_OUT, EXTPERIPH1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(SPDIF_IN, SPDIF, NORMAL, NORMAL, INPUT), + + + DEFAULT_PINMUX(SPI2_CS1_N, INVALID, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(PEX_L0_PRSNT_N, PCIE, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(PEX_L0_RST_N, PCIE, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(PEX_L0_CLKREQ_N, PCIE, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(PEX_WAKE_N, PCIE, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(PEX_L1_PRSNT_N, PCIE, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(PEX_L1_RST_N, PCIE, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(PEX_L1_CLKREQ_N, PCIE, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(PEX_L2_PRSNT_N, PCIE, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(PEX_L2_RST_N, PCIE, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(PEX_L2_CLKREQ_N, PCIE, NORMAL, NORMAL, INPUT), + CEC_PINMUX(HDMI_CEC, CEC, NORMAL, TRISTATE, OUTPUT, DEFAULT, DISABLE), + DEFAULT_PINMUX(HDMI_INT, RSVD0, NORMAL, TRISTATE, INPUT), + + /* Gpios */ + /* SDMMC1 CD gpio */ + DEFAULT_PINMUX(GMI_IORDY, RSVD1, PULL_UP, NORMAL, INPUT), + /* SDMMC1 WP gpio */ + DEFAULT_PINMUX(VI_D11, RSVD1, PULL_UP, NORMAL, INPUT), + + /* Touch RESET */ + DEFAULT_PINMUX(GMI_AD14, NAND, NORMAL, NORMAL, INPUT), + + DEFAULT_PINMUX(GMI_AD15, NAND, PULL_UP, TRISTATE, INPUT), + + /* Power rails GPIO */ + DEFAULT_PINMUX(KB_ROW8, KBC, PULL_UP, NORMAL, INPUT), + + VI_PINMUX(VI_D6, VI, NORMAL, NORMAL, OUTPUT, DISABLE, DISABLE), + VI_PINMUX(VI_D8, SDMMC2, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), + VI_PINMUX(VI_D9, SDMMC2, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), + VI_PINMUX(VI_PCLK, RSVD1, PULL_UP, TRISTATE, INPUT, DISABLE, ENABLE), + VI_PINMUX(VI_HSYNC, RSVD1, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), + VI_PINMUX(VI_VSYNC, RSVD1, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), + + DEFAULT_PINMUX(LCD_PWR0, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_D10, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(GMI_CS7_N, NAND_ALT, PULL_UP, TRISTATE, INPUT), + DEFAULT_PINMUX(SPI2_MOSI, SPI6, PULL_UP, NORMAL, OUTPUT), + DEFAULT_PINMUX(CLK3_OUT, EXTPERIPH3, NORMAL, NORMAL, OUTPUT), +}; + +static __initdata struct tegra_pingroup_config tai_pinmux_a02[] = { + DEFAULT_PINMUX(LCD_PWR2, DISPLAYA, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(LCD_PWR1, DISPLAYA, NORMAL, NORMAL, INPUT), +}; + +static __initdata struct tegra_pingroup_config tai_pinmux_a03[] = { + DEFAULT_PINMUX(LCD_PWR2, DISPLAYA, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(LCD_PWR1, DISPLAYA, NORMAL, NORMAL, OUTPUT), +}; + +static __initdata struct tegra_pingroup_config tai_unused_pinmux_common[] = { + DEFAULT_PINMUX(CLK2_OUT, EXTPERIPH2, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(CLK2_REQ, DAP, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(CLK3_REQ, DEV3, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(CLK_32K_OUT, BLINK, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GPIO_PBB4, VGP4, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GPIO_PBB5, VGP5, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GPIO_PBB6, VGP6, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GMI_AD0, GMI, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GMI_AD1, GMI, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GMI_AD2, GMI, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GMI_AD3, GMI, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GMI_AD4, GMI, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GMI_AD5, GMI, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GMI_AD6, GMI, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GMI_AD7, GMI, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GMI_CS0_N, GMI, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GMI_CS2_N, GMI, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GMI_CS3_N, GMI, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GMI_CS6_N, GMI, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GMI_CLK, GMI, NORMAL, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GMI_DQS, RSVD3, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GMI_RST_N, GMI, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GMI_WAIT, GMI, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GMI_WP_N, GMI, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(KB_ROW6, KBC, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(KB_ROW7, KBC, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(KB_ROW9, KBC, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(KB_ROW11, KBC, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(KB_ROW13, KBC, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(KB_ROW14, KBC, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(KB_ROW15, KBC, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_PCLK, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_WR_N, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_HSYNC, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_VSYNC, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_SCK, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_SDOUT, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_SDIN, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(CRT_HSYNC, CRT, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(CRT_VSYNC, CRT, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(SDMMC3_DAT4, SDMMC3, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(SDMMC3_DAT5, SDMMC3, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(SDMMC3_DAT6, SDMMC3, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(SDMMC3_DAT7, SDMMC3, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(SPDIF_OUT, SPDIF, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(SPI2_SCK, SPI2, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(SPI2_MISO, SPI2, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(SPI2_CS0_N, SPI2, PULL_DOWN, TRISTATE, OUTPUT), + + DEFAULT_PINMUX(LCD_D19, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(LCD_M1, DISPLAYA, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GMI_AD8, PWM0, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GMI_AD9, PWM1, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GMI_AD10, PWM2, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GMI_AD12, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(GMI_AD13, RSVD1, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(DAP2_FS, I2S1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP2_DIN, I2S1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(DAP2_DOUT, I2S1, NORMAL, NORMAL, OUTPUT), + DEFAULT_PINMUX(DAP2_SCLK, I2S1, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(SPI1_MOSI, SPI2, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(SPI1_SCK , SPI2, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(SPI1_MISO , INVALID, PULL_DOWN, TRISTATE, OUTPUT), + DEFAULT_PINMUX(SPI1_CS0_N, SPI1, PULL_DOWN, TRISTATE, OUTPUT), +}; + +static __initdata struct pin_info_low_power_mode +tai_unused_gpio_pins_common[] = { + PIN_GPIO_LPM("CLK2_OUT", TEGRA_GPIO_PW5, 0, 0), + PIN_GPIO_LPM("CLK2_REQ", TEGRA_GPIO_PCC5, 0, 0), + PIN_GPIO_LPM("CLK3_REQ", TEGRA_GPIO_PEE1, 0, 0), + PIN_GPIO_LPM("CLK_32K_OUT", TEGRA_GPIO_PA0, 0, 0), + PIN_GPIO_LPM("GPIO_PBB4", TEGRA_GPIO_PBB4, 0, 0), + PIN_GPIO_LPM("GPIO_PBB5", TEGRA_GPIO_PBB5, 0, 0), + PIN_GPIO_LPM("GPIO_PBB6", TEGRA_GPIO_PBB6, 0, 0), + PIN_GPIO_LPM("GMI_AD0", TEGRA_GPIO_PG0, 0, 0), + PIN_GPIO_LPM("GMI_AD1", TEGRA_GPIO_PG1, 0, 0), + PIN_GPIO_LPM("GMI_AD2", TEGRA_GPIO_PG2, 0, 0), + PIN_GPIO_LPM("GMI_AD3", TEGRA_GPIO_PG3, 0, 0), + PIN_GPIO_LPM("GMI_AD4", TEGRA_GPIO_PG4, 0, 0), + PIN_GPIO_LPM("GMI_AD5", TEGRA_GPIO_PG5, 0, 0), + PIN_GPIO_LPM("GMI_AD6", TEGRA_GPIO_PG6, 0, 0), + PIN_GPIO_LPM("GMI_AD7", TEGRA_GPIO_PG7, 0, 0), + PIN_GPIO_LPM("GMI_CS0_N", TEGRA_GPIO_PJ0, 0, 0), + PIN_GPIO_LPM("GMI_CS2_N", TEGRA_GPIO_PK3, 0, 0), + PIN_GPIO_LPM("GMI_CS3_N", TEGRA_GPIO_PK4, 0, 0), + PIN_GPIO_LPM("GMI_CS6_N", TEGRA_GPIO_PI3, 0, 0), + PIN_GPIO_LPM("GMI_CLK", TEGRA_GPIO_PK1, 0, 0), + PIN_GPIO_LPM("GMI_DQS", TEGRA_GPIO_PI2, 0, 0), + PIN_GPIO_LPM("GMI_RST_N", TEGRA_GPIO_PI4, 0, 0), + PIN_GPIO_LPM("GMI_WAIT", TEGRA_GPIO_PI7, 0, 0), + PIN_GPIO_LPM("GMI_WP_N", TEGRA_GPIO_PC7, 0, 0), + PIN_GPIO_LPM("KB_ROW6", TEGRA_GPIO_PR6, 0, 0), + PIN_GPIO_LPM("KB_ROW7", TEGRA_GPIO_PR7, 0, 0), + PIN_GPIO_LPM("KB_ROW9", TEGRA_GPIO_PS1, 0, 0), + PIN_GPIO_LPM("KB_ROW11", TEGRA_GPIO_PS3, 0, 0), + PIN_GPIO_LPM("KB_ROW13", TEGRA_GPIO_PS5, 0, 0), + PIN_GPIO_LPM("KB_ROW14", TEGRA_GPIO_PS6, 0, 0), + PIN_GPIO_LPM("KB_ROW15", TEGRA_GPIO_PS7, 0, 0), + PIN_GPIO_LPM("LCD_PCLK", TEGRA_GPIO_PB3, 0, 0), + PIN_GPIO_LPM("LCD_WR_N", TEGRA_GPIO_PZ3, 0, 0), + PIN_GPIO_LPM("LCD_HSYNC", TEGRA_GPIO_PJ3, 0, 0), + PIN_GPIO_LPM("LCD_VSYNC", TEGRA_GPIO_PJ4, 0, 0), + PIN_GPIO_LPM("LCD_SCK", TEGRA_GPIO_PZ4, 0, 0), + PIN_GPIO_LPM("LCD_SDOUT", TEGRA_GPIO_PN5, 0, 0), + PIN_GPIO_LPM("LCD_SDIN", TEGRA_GPIO_PZ2, 0, 0), + PIN_GPIO_LPM("CRT_HSYNC", TEGRA_GPIO_PV6, 0, 0), + PIN_GPIO_LPM("CRT_VSYNC", TEGRA_GPIO_PV7, 0, 0), + PIN_GPIO_LPM("SDMMC3_DAT4", TEGRA_GPIO_PD1, 0, 0), + PIN_GPIO_LPM("SDMMC3_DAT5", TEGRA_GPIO_PD0, 0, 0), + PIN_GPIO_LPM("SDMMC3_DAT6", TEGRA_GPIO_PD3, 0, 0), + PIN_GPIO_LPM("SDMMC3_DAT7", TEGRA_GPIO_PD4, 0, 0), + PIN_GPIO_LPM("SPDIF_OUT", TEGRA_GPIO_PK5, 0, 0), + PIN_GPIO_LPM("SPI1_CS0_N", TEGRA_GPIO_PX6, 0, 0), + PIN_GPIO_LPM("SPI2_SCK", TEGRA_GPIO_PX2, 0, 0), + PIN_GPIO_LPM("SPI2_MISO", TEGRA_GPIO_PX1, 0, 0), + PIN_GPIO_LPM("SPI2_CS0_N", TEGRA_GPIO_PX3, 0, 0), + PIN_GPIO_LPM("LCD_D19", TEGRA_GPIO_PM3, 0, 0), + PIN_GPIO_LPM("LCD_M1", TEGRA_GPIO_PW1, 0, 0), + PIN_GPIO_LPM("GMI_AD8", TEGRA_GPIO_PH0, 0, 0), + PIN_GPIO_LPM("GMI_AD9", TEGRA_GPIO_PH1, 0, 0), + PIN_GPIO_LPM("GMI_AD10", TEGRA_GPIO_PH2, 0, 0), + PIN_GPIO_LPM("GMI_AD12", TEGRA_GPIO_PH4, 0, 0), + PIN_GPIO_LPM("GMI_AD13", TEGRA_GPIO_PH5, 0, 0), + PIN_GPIO_LPM("DAP2_FS", TEGRA_GPIO_PA2, 0, 0), + PIN_GPIO_LPM("DAP2_DIN", TEGRA_GPIO_PA4, 0, 0), + PIN_GPIO_LPM("DAP2_DOUT", TEGRA_GPIO_PA5, 0, 0), + PIN_GPIO_LPM("DAP2_SCLK", TEGRA_GPIO_PA3, 0, 0), + PIN_GPIO_LPM("SPI1_MOSI", TEGRA_GPIO_PX4, 0, 0), + PIN_GPIO_LPM("SPI1_SCK", TEGRA_GPIO_PX5, 0, 0), + PIN_GPIO_LPM("SPI1_MISO", TEGRA_GPIO_PX7, 0, 0), + +}; + static void enterprise_set_unused_pin_gpio(struct pin_info_low_power_mode *lpm_pin_info, int list_count) { @@ -549,25 +982,51 @@ int __init enterprise_pinmux_init(void) struct board_info board_info; tegra_get_board_info(&board_info); - tegra_pinmux_config_table(enterprise_pinmux_common, + if (board_info.board_id != BOARD_E1239) { + tegra_pinmux_config_table(enterprise_pinmux_common, ARRAY_SIZE(enterprise_pinmux_common)); - tegra_drive_pinmux_config_table(enterprise_drive_pinmux, - ARRAY_SIZE(enterprise_drive_pinmux)); - tegra_pinmux_config_table(enterprise_unused_pinmux_common, + tegra_drive_pinmux_config_table(enterprise_drive_pinmux, + ARRAY_SIZE(enterprise_drive_pinmux)); + tegra_pinmux_config_table(enterprise_unused_pinmux_common, ARRAY_SIZE(enterprise_unused_pinmux_common)); - tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table)); - enterprise_set_unused_pin_gpio(enterprise_unused_gpio_pins_common, - ARRAY_SIZE(enterprise_unused_gpio_pins_common)); + tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table)); + enterprise_set_unused_pin_gpio( + enterprise_unused_gpio_pins_common, + ARRAY_SIZE(enterprise_unused_gpio_pins_common)); - if (board_info.fab < BOARD_FAB_A03) { - tegra_pinmux_config_table(enterprise_unused_pinmux_a02, - ARRAY_SIZE(enterprise_unused_pinmux_a02)); - enterprise_set_unused_pin_gpio(enterprise_unused_gpio_pins_a02, - ARRAY_SIZE(enterprise_unused_gpio_pins_a02)); - } else { - tegra_pinmux_config_table(enterprise_pinmux_a03, + if (board_info.fab < BOARD_FAB_A03) { + tegra_pinmux_config_table(enterprise_pinmux_a02, + ARRAY_SIZE(enterprise_pinmux_a02)); + enterprise_set_unused_pin_gpio( + enterprise_unused_gpio_pins_a02, + ARRAY_SIZE(enterprise_unused_gpio_pins_a02)); + } else { + tegra_pinmux_config_table(enterprise_pinmux_a03, ARRAY_SIZE(enterprise_pinmux_a03)); + enterprise_set_unused_pin_gpio(enterprise_gpio_pins_a03, + ARRAY_SIZE(enterprise_gpio_pins_a03)); + } + } else { + tegra_pinmux_config_table(tai_pinmux_common, + ARRAY_SIZE(tai_pinmux_common)); + if (board_info.fab <= BOARD_FAB_A02) { + tegra_pinmux_config_table(tai_pinmux_a02, + ARRAY_SIZE(tai_pinmux_a02)); + } else { + tegra_pinmux_config_table(tai_pinmux_a03, + ARRAY_SIZE(tai_pinmux_a03)); + } + tegra_drive_pinmux_config_table(enterprise_drive_pinmux, + ARRAY_SIZE(enterprise_drive_pinmux)); + tegra_pinmux_config_table(tai_unused_pinmux_common, + ARRAY_SIZE(tai_unused_pinmux_common)); + + tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table)); + tegra_gpio_config(tai_gpio_table, ARRAY_SIZE(tai_gpio_table)); + enterprise_set_unused_pin_gpio(tai_unused_gpio_pins_common, + ARRAY_SIZE(tai_unused_gpio_pins_common)); + } return 0; diff --git a/arch/arm/mach-tegra/board-enterprise-power.c b/arch/arm/mach-tegra/board-enterprise-power.c index bbe39ec4ad3e..3475452adc5a 100644 --- a/arch/arm/mach-tegra/board-enterprise-power.c +++ b/arch/arm/mach-tegra/board-enterprise-power.c @@ -140,6 +140,13 @@ static struct regulator_consumer_supply tps80031_smps4_supply_a03[] = { REGULATOR_SUPPLY("vddf_core_emmc", NULL), }; +static struct regulator_consumer_supply tps80031_smps4_supply_tai[] = { + REGULATOR_SUPPLY("vddio_sdmmc_2v85", NULL), + REGULATOR_SUPPLY("pwrdet_sdmmc3", NULL), + REGULATOR_SUPPLY("vdd_ddr_rx", NULL), + REGULATOR_SUPPLY("vddf_core_emmc", NULL), +}; + static struct regulator_consumer_supply tps80031_vana_supply_a02[] = { REGULATOR_SUPPLY("unused_vana", NULL), }; @@ -233,28 +240,30 @@ static struct regulator_consumer_supply tps80031_battery_charge_supply[] = { REGULATOR_SUPPLY("usb_bat_chg", NULL), }; -#define TPS_PDATA_INIT(_id, _sname, _minmv, _maxmv, _supply_reg, _always_on, \ +#define TPS_PDATA_INIT(_reg_id, _id, _sname, _minmv, _maxmv, _supply_reg, _always_on, \ _boot_on, _apply_uv, _init_uV, _init_enable, _init_apply, \ _flags, _ectrl, _delay) \ - static struct tps80031_regulator_platform_data pdata_##_id##_##_sname = { \ - .regulator = { \ - .constraints = { \ - .min_uV = (_minmv)*1000, \ - .max_uV = (_maxmv)*1000, \ - .valid_modes_mask = (REGULATOR_MODE_NORMAL | \ - REGULATOR_MODE_STANDBY), \ - .valid_ops_mask = (REGULATOR_CHANGE_MODE | \ - REGULATOR_CHANGE_STATUS | \ - REGULATOR_CHANGE_VOLTAGE), \ - .always_on = _always_on, \ - .boot_on = _boot_on, \ - .apply_uV = _apply_uv, \ - }, \ - .num_consumer_supplies = \ - ARRAY_SIZE(tps80031_##_id##_supply_##_sname), \ - .consumer_supplies = tps80031_##_id##_supply_##_sname, \ - .supply_regulator = _supply_reg, \ + static struct regulator_init_data reg_idata_##_id##_##_sname = { \ + .constraints = { \ + .name = tps80031_rails(_id), \ + .min_uV = (_minmv)*1000, \ + .max_uV = (_maxmv)*1000, \ + .valid_modes_mask = (REGULATOR_MODE_NORMAL | \ + REGULATOR_MODE_STANDBY), \ + .valid_ops_mask = (REGULATOR_CHANGE_MODE | \ + REGULATOR_CHANGE_STATUS | \ + REGULATOR_CHANGE_VOLTAGE), \ + .always_on = _always_on, \ + .boot_on = _boot_on, \ + .apply_uV = _apply_uv, \ }, \ + .num_consumer_supplies = \ + ARRAY_SIZE(tps80031_##_id##_supply_##_sname), \ + .consumer_supplies = tps80031_##_id##_supply_##_sname, \ + }; \ + static struct tps80031_regulator_platform_data pdata_##_id##_##_sname = { \ + .reg_init_data = ®_idata_##_id##_##_sname, \ + .regulator_id = TPS80031_REGULATOR_##_reg_id, \ .init_uV = _init_uV * 1000, \ .init_enable = _init_enable, \ .init_apply = _init_apply, \ @@ -263,31 +272,32 @@ static struct regulator_consumer_supply tps80031_battery_charge_supply[] = { .delay_us = _delay, \ } -TPS_PDATA_INIT(vio, a02, 600, 2100, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0); -TPS_PDATA_INIT(vio, a03, 600, 2100, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0); -TPS_PDATA_INIT(smps1, common, 600, 2100, 0, 0, 0, 0, -1, 0, 0, 0, PWR_REQ_INPUT_PREQ2 | PWR_OFF_ON_SLEEP, 0); -TPS_PDATA_INIT(smps2, common, 600, 2100, 0, 0, 0, 0, -1, 0, 0, 0, PWR_REQ_INPUT_PREQ1, 0); -TPS_PDATA_INIT(smps3, common, 600, 2100, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0); -TPS_PDATA_INIT(smps4, a02, 600, 2100, 0, 0, 0, 0, -1, 0, 0, 0, PWR_REQ_INPUT_PREQ1, 0); -TPS_PDATA_INIT(smps4, a03, 600, 2100, 0, 0, 0, 0, -1, 0, 0, 0, PWR_REQ_INPUT_PREQ1, 0); -TPS_PDATA_INIT(ldo1, a02, 1000, 3300, tps80031_rails(VIO), 0, 0, 0, -1, 0, 0, 0, 0, 0); -TPS_PDATA_INIT(ldo1, a03, 1000, 3300, tps80031_rails(VIO), 0, 0, 0, -1, 0, 0, 0, PWR_REQ_INPUT_PREQ1, 0); -TPS_PDATA_INIT(ldo2, common, 1000, 3300, 0, 1, 1, 1, 1000, 1, 1, 0, 0, 0); -TPS_PDATA_INIT(ldo3, common, 1000, 3300, tps80031_rails(VIO), 0, 0, 0, -1, 0, 0, 0, PWR_OFF_ON_SLEEP, 0); -TPS_PDATA_INIT(ldo4, a02, 1000, 3300, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0); -TPS_PDATA_INIT(ldo4, a03, 1000, 3300, tps80031_rails(VIO), 0, 0, 0, -1, 0, 0, 0, PWR_REQ_INPUT_PREQ1, 0); -TPS_PDATA_INIT(ldo5, common, 1000, 3300, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0); -TPS_PDATA_INIT(ldo6, a02, 1000, 3300, 0, 0, 0, 0, -1, 0, 0, 0, PWR_REQ_INPUT_PREQ1, 0); -TPS_PDATA_INIT(ldo6, a03, 1000, 3300, 0, 0, 0, 0, -1, 0, 0, 0, PWR_REQ_INPUT_PREQ1, 0); -TPS_PDATA_INIT(ldo7, a02, 1000, 3300, tps80031_rails(VIO), 0, 0, 0, -1, 0, 0, 0, PWR_REQ_INPUT_PREQ1, 0); -TPS_PDATA_INIT(ldo7, a03, 1000, 3300, 0, 0, 0, 0, -1, 0, 0, 0, PWR_REQ_INPUT_PREQ1, 0); -TPS_PDATA_INIT(ldoln, a02, 1000, 3300, tps80031_rails(SMPS3), 0, 0, 0, -1, 0, 0, 0, PWR_REQ_INPUT_PREQ1, 0); -TPS_PDATA_INIT(ldoln, a03, 1000, 3300, tps80031_rails(VIO), 0, 0, 0, -1, 0, 0, 0, PWR_REQ_INPUT_PREQ1, 0); -TPS_PDATA_INIT(ldousb, a02, 1000, 3300, 0, 0, 0, 0, -1, 0, 0, USBLDO_INPUT_VSYS, PWR_OFF_ON_SLEEP, 0); -TPS_PDATA_INIT(ldousb, a03, 1000, 3300, 0, 0, 0, 0, -1, 0, 0, USBLDO_INPUT_VSYS, PWR_REQ_INPUT_PREQ1, 0); -TPS_PDATA_INIT(vana, a02, 1000, 3300, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0); -TPS_PDATA_INIT(vana, a03, 1000, 3300, 0, 0, 0, 0, -1, 0, 1, 0, PWR_OFF_ON_SLEEP, 0); -TPS_PDATA_INIT(vbus, common, 0, 5000, 0, 0, 0, 0, -1, 0, 0, (VBUS_SW_ONLY | VBUS_DISCHRG_EN_PDN), 0, 100000); +TPS_PDATA_INIT(VIO, vio, a02, 600, 2100, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0); +TPS_PDATA_INIT(VIO, vio, a03, 600, 2100, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0); +TPS_PDATA_INIT(SMPS1, smps1, common, 600, 2100, 0, 0, 0, 0, -1, 0, 0, 0, PWR_REQ_INPUT_PREQ2 | PWR_OFF_ON_SLEEP, 0); +TPS_PDATA_INIT(SMPS2, smps2, common, 600, 2100, 0, 0, 0, 0, -1, 0, 0, 0, PWR_REQ_INPUT_PREQ1, 0); +TPS_PDATA_INIT(SMPS3, smps3, common, 600, 2100, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0); +TPS_PDATA_INIT(SMPS4, smps4, a02, 600, 2100, 0, 0, 0, 0, -1, 0, 0, 0, PWR_REQ_INPUT_PREQ1, 0); +TPS_PDATA_INIT(SMPS4, smps4, a03, 600, 2100, 0, 0, 0, 0, -1, 0, 0, 0, PWR_REQ_INPUT_PREQ1, 0); +TPS_PDATA_INIT(SMPS4, smps4, tai, 600, 2100, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0); +TPS_PDATA_INIT(LDO1, ldo1, a02, 1000, 3300, tps80031_rails(vio), 0, 0, 0, -1, 0, 0, 0, 0, 0); +TPS_PDATA_INIT(LDO1, ldo1, a03, 1000, 3300, tps80031_rails(vio), 0, 0, 0, -1, 0, 0, 0, PWR_REQ_INPUT_PREQ1, 0); +TPS_PDATA_INIT(LDO2, ldo2, common, 1000, 1000, 0, 1, 1, 1, -1, 0, 0, 0, 0, 0); +TPS_PDATA_INIT(LDO3, ldo3, common, 1000, 3300, tps80031_rails(vio), 0, 0, 0, -1, 0, 0, 0, PWR_OFF_ON_SLEEP, 0); +TPS_PDATA_INIT(LDO4, ldo4, a02, 1000, 3300, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0); +TPS_PDATA_INIT(LDO4, ldo4, a03, 1000, 3300, tps80031_rails(vio), 0, 0, 0, -1, 0, 0, 0, PWR_REQ_INPUT_PREQ1, 0); +TPS_PDATA_INIT(LDO5, ldo5, common, 1000, 3300, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0); +TPS_PDATA_INIT(LDO6, ldo6, a02, 1000, 3300, 0, 0, 0, 0, -1, 0, 0, 0, PWR_REQ_INPUT_PREQ1, 0); +TPS_PDATA_INIT(LDO6, ldo6, a03, 1000, 3300, 0, 0, 0, 0, -1, 0, 0, 0, PWR_REQ_INPUT_PREQ1, 0); +TPS_PDATA_INIT(LDO7, ldo7, a02, 1000, 3300, tps80031_rails(vio), 0, 0, 0, -1, 0, 0, 0, PWR_REQ_INPUT_PREQ1, 0); +TPS_PDATA_INIT(LDO7, ldo7, a03, 1000, 3300, 0, 0, 0, 0, -1, 0, 0, 0, PWR_REQ_INPUT_PREQ1, 0); +TPS_PDATA_INIT(LDOLN, ldoln, a02, 1000, 3300, tps80031_rails(smps3), 0, 0, 0, -1, 0, 0, 0, PWR_REQ_INPUT_PREQ1, 0); +TPS_PDATA_INIT(LDOLN, ldoln, a03, 1000, 3300, tps80031_rails(vio), 0, 0, 0, -1, 0, 0, 0, PWR_REQ_INPUT_PREQ1, 0); +TPS_PDATA_INIT(LDOUSB, ldousb, a02, 1000, 3300, 0, 0, 0, 0, -1, 0, 0, USBLDO_INPUT_VSYS, PWR_OFF_ON_SLEEP, 0); +TPS_PDATA_INIT(LDOUSB, ldousb, a03, 1000, 3300, 0, 0, 0, 0, -1, 0, 0, USBLDO_INPUT_VSYS, PWR_REQ_INPUT_PREQ1, 0); +TPS_PDATA_INIT(VANA, vana, a02, 1000, 3300, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0); +TPS_PDATA_INIT(VANA, vana, a03, 1000, 3300, 0, 0, 0, 0, -1, 0, 0, 0, PWR_OFF_ON_SLEEP, 0); +TPS_PDATA_INIT(VBUS, vbus, common, 0, 5000, 0, 0, 0, 0, -1, 0, 0, (VBUS_SW_ONLY | VBUS_DISCHRG_EN_PDN), 0, 100000); static struct tps80031_rtc_platform_data rtc_data = { .irq = ENT_TPS80031_IRQ_BASE + TPS80031_INT_RTC_ALARM, @@ -331,74 +341,62 @@ static struct tps80031_bg_platform_data battery_gauge_data = { .battery_present = 1, }; -#define TPS_RTC() \ - { \ - .id = 0, \ - .name = "rtc_tps80031", \ - .platform_data = &rtc_data, \ - } - -#define TPS_REG(_id, _data, _sname) \ - { \ - .id = TPS80031_ID_##_id, \ - .name = "tps80031-regulator", \ - .platform_data = &pdata_##_data##_##_sname, \ - } -#define TPS_BATTERY() \ - { \ - .name = "tps80031-charger", \ - .platform_data = &bcharger_pdata, \ - } -#define TPS_BATTERY_GAUGE() \ - { \ - .name = "tps80031-battery-gauge", \ - .platform_data = &battery_gauge_data, \ - } -#define TPS_GPADC() \ - { \ - .name = "tps80031-gpadc", \ - } - -#define TPS80031_DEVS_COMMON \ - TPS_REG(SMPS1, smps1, common), \ - TPS_REG(SMPS2, smps2, common), \ - TPS_REG(SMPS3, smps3, common), \ - TPS_REG(LDO2, ldo2, common), \ - TPS_REG(LDO3, ldo3, common), \ - TPS_REG(LDO5, ldo5, common), \ - TPS_REG(VBUS, vbus, common), \ - TPS_RTC(), \ - TPS_BATTERY(), \ - TPS_BATTERY_GAUGE(), \ - TPS_GPADC() - - -static struct tps80031_subdev_info tps80031_devs_a02[] = { - TPS_REG(VIO, vio, a02), - TPS80031_DEVS_COMMON, - TPS_REG(SMPS4, smps4, a02), - TPS_REG(LDO1, ldo1, a02), - TPS_REG(LDO4, ldo4, a02), - TPS_REG(LDO6, ldo6, a02), - TPS_REG(LDO7, ldo7, a02), - TPS_REG(LDOLN, ldoln, a02), - TPS_REG(LDOUSB, ldousb, a02), - TPS_REG(VANA, vana, a02), - -}; - -static struct tps80031_subdev_info tps80031_devs_a03[] = { - TPS_REG(VIO, vio, a03), - TPS80031_DEVS_COMMON, - TPS_REG(SMPS4, smps4, a03), - TPS_REG(LDO1, ldo1, a03), - TPS_REG(LDO4, ldo4, a03), - TPS_REG(LDO6, ldo6, a03), - TPS_REG(LDO7, ldo7, a03), - TPS_REG(LDOLN, ldoln, a03), - TPS_REG(LDOUSB, ldousb, a03), - TPS_REG(VANA, vana, a03), - +#define TPS_REG_PDATA(_id, _sname) &pdata_##_id##_##_sname +static struct tps80031_regulator_platform_data *tps80031_reg_pdata_a02[] = { + TPS_REG_PDATA(vio, a02), + TPS_REG_PDATA(smps1, common), + TPS_REG_PDATA(smps2, common), + TPS_REG_PDATA(smps3, common), + TPS_REG_PDATA(ldo2, common), + TPS_REG_PDATA(ldo3, common), + TPS_REG_PDATA(ldo5, common), + TPS_REG_PDATA(vbus, common), + TPS_REG_PDATA(smps4, a02), + TPS_REG_PDATA(ldo1, a02), + TPS_REG_PDATA(ldo4, a02), + TPS_REG_PDATA(ldo6, a02), + TPS_REG_PDATA(ldo7, a02), + TPS_REG_PDATA(ldoln, a02), + TPS_REG_PDATA(ldousb, a02), + TPS_REG_PDATA(vana, a02), +}; + +static struct tps80031_regulator_platform_data *tps80031_reg_pdata_a03[] = { + TPS_REG_PDATA(vio, a03), + TPS_REG_PDATA(smps1, common), + TPS_REG_PDATA(smps2, common), + TPS_REG_PDATA(smps3, common), + TPS_REG_PDATA(ldo2, common), + TPS_REG_PDATA(ldo3, common), + TPS_REG_PDATA(ldo5, common), + TPS_REG_PDATA(vbus, common), + TPS_REG_PDATA(smps4, a03), + TPS_REG_PDATA(ldo1, a03), + TPS_REG_PDATA(ldo4, a03), + TPS_REG_PDATA(ldo6, a03), + TPS_REG_PDATA(ldo7, a03), + TPS_REG_PDATA(ldoln, a03), + TPS_REG_PDATA(ldousb, a03), + TPS_REG_PDATA(vana, a03), +}; + +static struct tps80031_regulator_platform_data *tps80031_reg_pdata_tai[] = { + TPS_REG_PDATA(vio, a03), + TPS_REG_PDATA(smps1, common), + TPS_REG_PDATA(smps2, common), + TPS_REG_PDATA(smps3, common), + TPS_REG_PDATA(ldo2, common), + TPS_REG_PDATA(ldo3, common), + TPS_REG_PDATA(ldo5, common), + TPS_REG_PDATA(vbus, common), + TPS_REG_PDATA(smps4, tai), + TPS_REG_PDATA(ldo1, a03), + TPS_REG_PDATA(ldo4, a03), + TPS_REG_PDATA(ldo6, a03), + TPS_REG_PDATA(ldo7, a03), + TPS_REG_PDATA(ldoln, a03), + TPS_REG_PDATA(ldousb, a03), + TPS_REG_PDATA(vana, a03), }; static struct tps80031_clk32k_init_data clk32k_idata[] = { @@ -444,6 +442,9 @@ static struct tps80031_platform_data tps_platform = { .clk32k_init_data = clk32k_idata, .clk32k_init_data_size = ARRAY_SIZE(clk32k_idata), .use_power_off = true, + .rtc_pdata = &rtc_data, + .bg_pdata = &battery_gauge_data, + .battery_charger_pdata = &bcharger_pdata, }; static struct i2c_board_info __initdata enterprise_regulators[] = { @@ -472,6 +473,10 @@ static struct regulator_consumer_supply fixed_reg_pmu_3v3_en_supply[] = { static struct regulator_consumer_supply fixed_reg_pmu_hdmi_5v0_en_supply[] = { REGULATOR_SUPPLY("hdmi_5v0", NULL), }; +static struct regulator_consumer_supply +fixed_reg_pmu_hdmi_5v0_en_tai_supply[] = { + REGULATOR_SUPPLY("hdmi_5v0", NULL), +}; /* LCD-D16 (GPIO M0) from T30*/ static struct regulator_consumer_supply fixed_reg_vdd_fuse_en_supply[] = { @@ -594,7 +599,7 @@ static struct gpio gpio_reg_sdmmc3_vdd_sel_gpios[] = { }, \ } -GPIO_REG(4, sdmmc3_vdd_sel, tps80031_rails(SMPS4), +GPIO_REG(4, sdmmc3_vdd_sel, tps80031_rails(smps4), true, false, 0, 1000, 3300); /* Macro for defining fixed regulator sub device data */ @@ -653,26 +658,33 @@ FIXED_REG(7, vdd_sdmmc3_2v85_en, NULL, FIXED_REG(8, lcd_1v8_en, NULL, TEGRA_GPIO_PB2, true, 1800, 0, 0); -#define ADD_FIXED_REG(_name) (&fixed_reg_##_name##_dev) - -#define FIXED_REGS_COMMON \ - ADD_FIXED_REG(pmu_5v15_en), \ - ADD_FIXED_REG(pmu_hdmi_5v0_en), \ - ADD_FIXED_REG(vdd_fuse_en), \ - ADD_FIXED_REG(cam_ldo_2v8_en), \ - ADD_FIXED_REG(cam_ldo_1v8_en) +FIXED_REG(9, pmu_hdmi_5v0_en_tai, NULL, + ENT_TPS80031_GPIO_SYSEN, true, 5000, 0, 0); +#define ADD_FIXED_REG(_name) (&fixed_reg_##_name##_dev) static struct platform_device *fixed_regs_devices_a02[] = { - ADD_FIXED_REG(pmu_5v15_en), \ - ADD_FIXED_REG(pmu_3v3_en), \ - ADD_FIXED_REG(pmu_hdmi_5v0_en), \ - ADD_FIXED_REG(vdd_fuse_en), \ - ADD_FIXED_REG(cam_ldo_2v8_en), \ + ADD_FIXED_REG(pmu_5v15_en), + ADD_FIXED_REG(pmu_3v3_en), + ADD_FIXED_REG(pmu_hdmi_5v0_en), + ADD_FIXED_REG(vdd_fuse_en), + ADD_FIXED_REG(cam_ldo_2v8_en), ADD_FIXED_REG(cam_ldo_1v8_en) }; static struct platform_device *fixed_regs_devices_a03[] = { - FIXED_REGS_COMMON, + ADD_FIXED_REG(pmu_5v15_en), + ADD_FIXED_REG(pmu_hdmi_5v0_en), + ADD_FIXED_REG(vdd_fuse_en), + ADD_FIXED_REG(cam_ldo_2v8_en), + ADD_FIXED_REG(cam_ldo_1v8_en), + ADD_FIXED_REG(vdd_sdmmc3_2v85_en), + ADD_FIXED_REG(lcd_1v8_en), +}; + +static struct platform_device *fixed_regs_devices_tai[] = { + ADD_FIXED_REG(pmu_hdmi_5v0_en_tai), + ADD_FIXED_REG(cam_ldo_2v8_en), + ADD_FIXED_REG(cam_ldo_1v8_en), ADD_FIXED_REG(vdd_sdmmc3_2v85_en), ADD_FIXED_REG(lcd_1v8_en), }; @@ -690,14 +702,18 @@ static int __init enterprise_fixed_regulator_init(void) tegra_get_board_info(&board_info); - if (board_info.fab < BOARD_FAB_A03) { - fixed_regs_devices = fixed_regs_devices_a02; - nfixreg_devs = ARRAY_SIZE(fixed_regs_devices_a02); + if (board_info.board_id == BOARD_E1239) { + fixed_regs_devices = fixed_regs_devices_tai; + nfixreg_devs = ARRAY_SIZE(fixed_regs_devices_tai); } else { - fixed_regs_devices = fixed_regs_devices_a03; - nfixreg_devs = ARRAY_SIZE(fixed_regs_devices_a03); + if (board_info.fab < BOARD_FAB_A03) { + fixed_regs_devices = fixed_regs_devices_a02; + nfixreg_devs = ARRAY_SIZE(fixed_regs_devices_a02); + } else { + fixed_regs_devices = fixed_regs_devices_a03; + nfixreg_devs = ARRAY_SIZE(fixed_regs_devices_a03); + } } - return platform_add_devices(fixed_regs_devices, nfixreg_devs); } @@ -741,6 +757,9 @@ int __init enterprise_regulator_init(void) pmc_dpd_pads = readl(pmc + PMC_DPD_PADS_ORIDE); writel(pmc_dpd_pads & ~PMC_DPD_PADS_ORIDE_BLINK , pmc + PMC_DPD_PADS_ORIDE); + /* Setting CPU voltage tolerance in lower side for 3000uV */ + pdata_smps1_common.tolerance_uv = 3000; + /* Disable battery charging if power adapter is connected. */ if (get_power_supply_type() == POWER_SUPPLY_TYPE_MAINS) { bcharger_pdata.num_consumer_supplies = 0; @@ -748,14 +767,21 @@ 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; + if ((board_info.fab < BOARD_FAB_A03) && + (board_info.board_id != BOARD_E1239)) { + tps_platform.num_regulator_pdata = ARRAY_SIZE(tps80031_reg_pdata_a02); + tps_platform.regulator_pdata = tps80031_reg_pdata_a02; } else { - tps_platform.num_subdevs = ARRAY_SIZE(tps80031_devs_a03); - tps_platform.subdevs = tps80031_devs_a03; + if (machine_is_tai()) { + tps_platform.num_regulator_pdata = + ARRAY_SIZE(tps80031_reg_pdata_tai); + tps_platform.regulator_pdata = + tps80031_reg_pdata_tai; + } else { + tps_platform.num_regulator_pdata = + ARRAY_SIZE(tps80031_reg_pdata_a03); + tps_platform.regulator_pdata = tps80031_reg_pdata_a03; + } tps_platform.pupd_init_data = pupd_idata; tps_platform.pupd_init_data_size = ARRAY_SIZE(pupd_idata); tps_platform.gpio_init_data = gpio_idata_a03; @@ -788,6 +814,15 @@ static struct tegra_suspend_platform_data enterprise_suspend_data = { .sysclkreq_high = true, .board_suspend = enterprise_board_suspend, .board_resume = enterprise_board_resume, +#ifdef CONFIG_TEGRA_LP1_950 + .lp1_lowvolt_support = true, + .i2c_base_addr = TEGRA_I2C5_BASE, + .pmuslave_addr = 0x24, + .core_reg_addr = 0x5B, + .lp1_core_volt_low = 0x1D, + .lp1_core_volt_high = 0x33, +#endif + .cpu_wake_freq = CPU_WAKE_FREQ_LOW, }; static void enterprise_init_deep_sleep_mode(void) @@ -799,6 +834,7 @@ static void enterprise_init_deep_sleep_mode(void) enterprise_suspend_data.suspend_mode = TEGRA_SUSPEND_LP1; if ((bi.board_id == BOARD_E1205 && (bi.sku & BOARD_SKU_VF_BIT) == 0) || + (bi.board_id == BOARD_E1239 && (bi.sku & BOARD_SKU_VF_BIT) == 0) || (bi.board_id == BOARD_E1197 && (bi.sku & BOARD_SKU_VF_BIT))) enterprise_suspend_data.cpu_timer = 8000; } @@ -843,9 +879,9 @@ static struct platform_device enterprise_bpc_mgmt_device = { void __init enterprise_bpc_mgmt_init(void) { +#ifdef CONFIG_SMP int int_gpio = TEGRA_GPIO_TO_IRQ(TEGRA_BPC_TRIGGER); -#ifdef CONFIG_SMP cpumask_setall(&(bpc_mgmt_platform_data.affinity_mask)); irq_set_affinity_hint(int_gpio, &(bpc_mgmt_platform_data.affinity_mask)); diff --git a/arch/arm/mach-tegra/board-enterprise-sdhci.c b/arch/arm/mach-tegra/board-enterprise-sdhci.c index 7a5632601fe6..a003ae9cbd8e 100644 --- a/arch/arm/mach-tegra/board-enterprise-sdhci.c +++ b/arch/arm/mach-tegra/board-enterprise-sdhci.c @@ -22,11 +22,13 @@ #include <linux/clk.h> #include <linux/err.h> #include <linux/mmc/host.h> +#include <linux/wl12xx.h> #include <asm/mach-types.h> #include <mach/irqs.h> #include <mach/iomap.h> #include <mach/sdhci.h> +#include <mach/io_dpd.h> #include "gpio-names.h" #include "board.h" @@ -51,6 +53,14 @@ static struct wifi_platform_data enterprise_wifi_control = { .set_carddetect = enterprise_wifi_set_carddetect, }; +static struct wl12xx_platform_data enterprise_wl12xx_wlan_data __initdata = { + .irq = TEGRA_GPIO_TO_IRQ(ENTERPRISE_WLAN_WOW), + .board_ref_clock = WL12XX_REFCLOCK_26, + .board_tcxo_clock = 1, + .set_power = enterprise_wifi_power, + .set_carddetect = enterprise_wifi_set_carddetect, +}; + static struct resource wifi_resource[] = { [0] = { .name = "bcm4329_wlan_irq", @@ -60,7 +70,7 @@ static struct resource wifi_resource[] = { }, }; -static struct platform_device enterprise_wifi_device = { +static struct platform_device enterprise_brcm_wifi_device = { .name = "bcm4329_wlan", .id = 1, .num_resources = 1, @@ -221,11 +231,43 @@ static int enterprise_wifi_set_carddetect(int val) static int enterprise_wifi_power(int on) { + struct tegra_io_dpd *sd_dpd; + pr_debug("%s: %d\n", __func__, on); - gpio_set_value(ENTERPRISE_WLAN_PWR, on); - mdelay(100); - gpio_set_value(ENTERPRISE_WLAN_RST, on); - mdelay(200); + + /* + * FIXME : we need to revisit IO DPD code + * on how should multiple pins under DPD get controlled + * + * enterprise GPIO WLAN enable is part of SDMMC1 pin group + */ + sd_dpd = tegra_io_dpd_get(&tegra_sdhci_device0.dev); + if (sd_dpd) { + mutex_lock(&sd_dpd->delay_lock); + tegra_io_dpd_disable(sd_dpd); + mutex_unlock(&sd_dpd->delay_lock); + } + + if (on) { + gpio_set_value(ENTERPRISE_WLAN_RST, 1); + mdelay(100); + gpio_set_value(ENTERPRISE_WLAN_RST, 0); + mdelay(100); + gpio_set_value(ENTERPRISE_WLAN_RST, 1); + mdelay(100); + gpio_set_value(ENTERPRISE_WLAN_PWR, 1); + mdelay(200); + } else { + gpio_set_value(ENTERPRISE_WLAN_RST, 0); + mdelay(100); + gpio_set_value(ENTERPRISE_WLAN_PWR, 0); + } + + if (sd_dpd) { + mutex_lock(&sd_dpd->delay_lock); + tegra_io_dpd_enable(sd_dpd); + mutex_unlock(&sd_dpd->delay_lock); + } return 0; } @@ -274,7 +316,11 @@ static int __init enterprise_wifi_init(void) if (rc) pr_err("WLAN_WOW gpio direction configuration failed:%d\n", rc); - platform_device_register(&enterprise_wifi_device); + if (tegra_get_commchip_id() == COMMCHIP_TI_WL18XX) + wl12xx_set_platform_data(&enterprise_wl12xx_wlan_data); + else + platform_device_register(&enterprise_brcm_wifi_device); + return 0; } @@ -285,6 +331,13 @@ int __init enterprise_sdhci_init(void) tegra_sdhci_platform_data2.cd_gpio = ENTERPRISE_SD_CD; platform_device_register(&tegra_sdhci_device2); + /* TI wifi module does not use emdedded sdio */ + if (tegra_get_commchip_id() == COMMCHIP_TI_WL18XX) { +#ifdef CONFIG_MMC_EMBEDDED_SDIO + tegra_sdhci_platform_data0.mmc_data.embedded_sdio = NULL; +#endif + } + platform_device_register(&tegra_sdhci_device0); enterprise_wifi_init(); return 0; diff --git a/arch/arm/mach-tegra/board-enterprise-sensors.c b/arch/arm/mach-tegra/board-enterprise-sensors.c index aab409b89ea9..c66d3fbbd1e8 100644 --- a/arch/arm/mach-tegra/board-enterprise-sensors.c +++ b/arch/arm/mach-tegra/board-enterprise-sensors.c @@ -40,16 +40,21 @@ #include <linux/platform_data/ina230.h> #include <linux/regulator/consumer.h> #include <linux/slab.h> +#include <linux/clk.h> #include <mach/gpio.h> #include <media/ar0832_main.h> #include <media/tps61050.h> #include <media/ov9726.h> #include <mach/edp.h> #include <mach/thermal.h> +#include <mach/clk.h> #include "cpu-tegra.h" #include "gpio-names.h" #include "board-enterprise.h" #include "board.h" +#include "clock.h" + +static struct board_info board_info; static int nct_get_temp(void *_data, long *temp) { @@ -283,6 +288,14 @@ struct enterprise_power_rail { static struct enterprise_power_rail ent_vicsi_pwr[NUM_OF_CAM]; +static __initdata struct tegra_clk_init_table tai_front_cam_clk_init_table[] = { + /* name parent rate enabled */ + { "extern3", "pll_p", 24000000, false}, + { "clk_out_3", "extern3", 24000000, false}, + { NULL, NULL, 0, 0}, +}; + + static int enterprise_cam_pwr(enum CAMERA_INDEX cam, bool pwr_on) { struct enterprise_power_rail *reg_cam = &ent_vicsi_pwr[cam]; @@ -357,7 +370,8 @@ static int enterprise_ar0832_ri_power_on(int is_stereo) /* Release Reset */ if (is_stereo) { gpio_set_value(CAM1_RST_L_GPIO, 1); - gpio_set_value(CAM2_RST_L_GPIO, 1); + if (board_info.board_id != BOARD_E1239) + gpio_set_value(CAM2_RST_L_GPIO, 1); } else gpio_set_value(CAM1_RST_L_GPIO, 1); /* @@ -375,11 +389,12 @@ static int enterprise_ar0832_le_power_on(int is_stereo) int ret = 0; pr_info("%s: ++\n", __func__); - ret = enterprise_cam_pwr(CAM_REAR_LEFT, true); - - /* Release Reset */ - gpio_set_value(CAM2_RST_L_GPIO, 1); + if (board_info.board_id != BOARD_E1239) { + ret = enterprise_cam_pwr(CAM_REAR_LEFT, true); + /* Release Reset */ + gpio_set_value(CAM2_RST_L_GPIO, 1); + } /* It takes 2400 EXTCLK for ar0832 to be ready for I2c. EXTCLK is 10 ~ 24MHz. 1 ms should be enough to cover @@ -387,8 +402,10 @@ static int enterprise_ar0832_le_power_on(int is_stereo) */ enterprise_msleep(1); - /* CSI B is shared between Front camera and Rear Left camera */ - gpio_set_value(CAM_CSI_MUX_SEL_GPIO, 1); + if (board_info.board_id != BOARD_E1239) { + /* CSI B is shared between Front camera and Rear Left camera */ + gpio_set_value(CAM_CSI_MUX_SEL_GPIO, 1); + } return ret; } @@ -403,7 +420,8 @@ static int enterprise_ar0832_ri_power_off(int is_stereo) /* Assert Reset */ if (is_stereo) { gpio_set_value(CAM1_RST_L_GPIO, 0); - gpio_set_value(CAM2_RST_L_GPIO, 0); + if (board_info.board_id != BOARD_E1239) + gpio_set_value(CAM2_RST_L_GPIO, 0); } else gpio_set_value(CAM1_RST_L_GPIO, 0); @@ -412,14 +430,15 @@ static int enterprise_ar0832_ri_power_off(int is_stereo) static int enterprise_ar0832_le_power_off(int is_stereo) { - int ret; - - pr_info("%s: ++\n", __func__); - ret = enterprise_cam_pwr(CAM_REAR_LEFT, false); + int ret = 0; - /* Assert Reset */ - gpio_set_value(CAM2_RST_L_GPIO, 0); + if (board_info.board_id != BOARD_E1239) { + pr_info("%s: ++\n", __func__); + ret = enterprise_cam_pwr(CAM_REAR_LEFT, false); + /* Assert Reset */ + gpio_set_value(CAM2_RST_L_GPIO, 0); + } return ret; } @@ -427,10 +446,15 @@ static int enterprise_ov9726_power_on(void) { pr_info("ov9726 power on\n"); - /* switch mipi mux to front camera */ - gpio_set_value(CAM_CSI_MUX_SEL_GPIO, CAM_CSI_MUX_SEL_FRONT); + if (board_info.board_id != BOARD_E1239) { + /* switch mipi mux to front camera */ + gpio_set_value(CAM_CSI_MUX_SEL_GPIO, CAM_CSI_MUX_SEL_FRONT); + } enterprise_cam_pwr(CAM_FRONT, true); + if (board_info.board_id == BOARD_E1239) + clk_enable(tegra_get_clock_by_name("clk_out_3")); + return 0; } @@ -440,6 +464,9 @@ static int enterprise_ov9726_power_off(void) enterprise_cam_pwr(CAM_FRONT, false); + if (board_info.board_id == BOARD_E1239) + clk_disable(tegra_get_clock_by_name("clk_out_3")); + return 0; } @@ -485,7 +512,13 @@ static struct enterprise_cam_gpio enterprise_cam_gpio_data[] = { [5] = TEGRA_CAMERA_GPIO(CAM_FLASH_EN_GPIO, "flash_en", 1), [6] = TEGRA_CAMERA_GPIO(CAM_I2C_MUX_RST_EXP, "cam_i2c_mux_rst", 1), }; - +static struct enterprise_cam_gpio tai_cam_gpio_data[] = { + [0] = TEGRA_CAMERA_GPIO(CAM1_RST_L_GPIO, "cam1_rst_lo", 0), + [1] = TEGRA_CAMERA_GPIO(CAM3_RST_L_GPIO, "cam3_rst_lo", 0), + [2] = TEGRA_CAMERA_GPIO(CAM3_PWDN_GPIO, "cam3_pwdn", 1), + [3] = TEGRA_CAMERA_GPIO(CAM_FLASH_EN_GPIO, "flash_en", 1), + [4] = TEGRA_CAMERA_GPIO(CAM_I2C_MUX_RST_EXP, "cam_i2c_mux_rst", 1), +}; static struct pca954x_platform_mode enterprise_pca954x_modes[] = { { .adap_id = PCA954x_I2C_BUS0, .deselect_on_exit = true, }, { .adap_id = PCA954x_I2C_BUS1, .deselect_on_exit = true, }, @@ -565,49 +598,87 @@ static struct i2c_board_info enterprise_i2c7_boardinfo[] = { .platform_data = &enterprise_ar0832_ri_data, }, }; +static struct i2c_board_info ar0832_i2c2_boardinfo_tai[] = { + { + /* 0x36: alternative slave address */ + I2C_BOARD_INFO("ar0832", 0x36), + .platform_data = &enterprise_ar0832_ri_data, + }, + { + I2C_BOARD_INFO("tps61050", 0x33), + .platform_data = &enterprise_tps61050_pdata, + }, + { + I2C_BOARD_INFO("ov9726", OV9726_I2C_ADDR >> 1), + .platform_data = &enterprise_ov9726_data, + }, +}; static int enterprise_cam_init(void) { int ret; int i; - struct board_info bi; struct board_info cam_bi; bool i2c_mux = false; pr_info("%s:++\n", __func__); memset(ent_vicsi_pwr, 0, sizeof(ent_vicsi_pwr)); - for (i = 0; i < ARRAY_SIZE(enterprise_cam_gpio_data); i++) { - ret = gpio_request(enterprise_cam_gpio_data[i].gpio, - enterprise_cam_gpio_data[i].label); - if (ret < 0) { - pr_err("%s: gpio_request failed for gpio #%d\n", - __func__, i); - goto fail_free_gpio; - } - gpio_direction_output(enterprise_cam_gpio_data[i].gpio, - enterprise_cam_gpio_data[i].value); - gpio_export(enterprise_cam_gpio_data[i].gpio, false); - } - tegra_get_board_info(&bi); tegra_get_camera_board_info(&cam_bi); - if (bi.board_id == BOARD_E1205) { - if (bi.fab == BOARD_FAB_A00 || bi.fab == BOARD_FAB_A01) + if (board_info.board_id == BOARD_E1239) { + for (i = 0; i < ARRAY_SIZE(tai_cam_gpio_data); i++) { + ret = gpio_request(tai_cam_gpio_data[i].gpio, + tai_cam_gpio_data[i].label); + if (ret < 0) { + pr_err("%s: gpio_request failed for gpio #%d\n", + __func__, i); + goto fail_free_gpio; + } + gpio_direction_output(tai_cam_gpio_data[i].gpio, + tai_cam_gpio_data[i].value); + gpio_export(tai_cam_gpio_data[i].gpio, false); + } + + tegra_clk_init_from_table(tai_front_cam_clk_init_table); + + } else { + for (i = 0; i < ARRAY_SIZE(enterprise_cam_gpio_data); i++) { + ret = gpio_request(enterprise_cam_gpio_data[i].gpio, + enterprise_cam_gpio_data[i].label); + if (ret < 0) { + pr_err("%s: gpio_request failed for gpio #%d\n", + __func__, i); + goto fail_free_gpio; + } + gpio_direction_output(enterprise_cam_gpio_data[i].gpio, + enterprise_cam_gpio_data[i].value); + gpio_export(enterprise_cam_gpio_data[i].gpio, false); + } + } + + if (board_info.board_id == BOARD_E1205) { + if (board_info.fab == BOARD_FAB_A00 || + board_info.fab == BOARD_FAB_A01) i2c_mux = false; - else if (bi.fab == BOARD_FAB_A02) + else if (board_info.fab == BOARD_FAB_A02) i2c_mux = true; - } else if (bi.board_id == BOARD_E1197) { + } else if (board_info.board_id == BOARD_E1197) { if (cam_bi.fab == BOARD_FAB_A00) i2c_mux = false; else if (cam_bi.fab == BOARD_FAB_A01) i2c_mux = true; } - if (!i2c_mux) - i2c_register_board_info(2, ar0832_i2c2_boardinfo, - ARRAY_SIZE(ar0832_i2c2_boardinfo)); - else { + if (!i2c_mux) { + if (board_info.board_id == BOARD_E1239) { + i2c_register_board_info(2, ar0832_i2c2_boardinfo_tai, + ARRAY_SIZE(ar0832_i2c2_boardinfo)); + } else { + i2c_register_board_info(2, ar0832_i2c2_boardinfo, + ARRAY_SIZE(ar0832_i2c2_boardinfo)); + } + } else { i2c_register_board_info(2, enterprise_i2c2_boardinfo, ARRAY_SIZE(enterprise_i2c2_boardinfo)); /* @@ -623,8 +694,14 @@ static int enterprise_cam_init(void) fail_free_gpio: pr_err("%s enterprise_cam_init failed!\n", __func__); - while (i--) - gpio_free(enterprise_cam_gpio_data[i].gpio); + if (board_info.board_id == BOARD_E1239) { + while (i--) + gpio_free(tai_cam_gpio_data[i].gpio); + + } else { + while (i--) + gpio_free(enterprise_cam_gpio_data[i].gpio); + } return ret; } @@ -657,9 +734,12 @@ int __init enterprise_sensors_init(void) { int ret; + tegra_get_board_info(&board_info); + enterprise_isl_init(); enterprise_nct1008_init(); - mpuirq_init(); + if (board_info.board_id != BOARD_E1239) + mpuirq_init(); #if ENTERPRISE_INA230_ENABLED enterprise_ina230_init(); #endif diff --git a/arch/arm/mach-tegra/board-enterprise.c b/arch/arm/mach-tegra/board-enterprise.c index 9c8890ed96cf..a85c2dccd1a3 100644 --- a/arch/arm/mach-tegra/board-enterprise.c +++ b/arch/arm/mach-tegra/board-enterprise.c @@ -1,7 +1,7 @@ /* * arch/arm/mach-tegra/board-enterprise.c * - * Copyright (c) 2011-2012, NVIDIA Corporation. + * Copyright (c) 2011-2012, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -38,8 +38,12 @@ #include <linux/i2c/atmel_mxt_ts.h> #include <linux/memblock.h> #include <linux/rfkill-gpio.h> +#include <linux/mfd/tlv320aic3262-registers.h> +#include <linux/mfd/tlv320aic3262-core.h> #include <linux/nfc/pn544.h> +#include <linux/skbuff.h> +#include <linux/ti_wilink_st.h> #include <sound/max98088.h> #include <mach/clk.h> @@ -48,6 +52,7 @@ #include <mach/pinmux.h> #include <mach/iomap.h> #include <mach/io.h> +#include <mach/io_dpd.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> #include <mach/usb_phy.h> @@ -121,6 +126,32 @@ static struct tegra_thermal_data thermal_data = { #endif }; +/* wl128x BT, FM, GPS connectivity chip */ +struct ti_st_plat_data enterprise_wilink_pdata = { + .nshutdown_gpio = TEGRA_GPIO_PE6, + .dev_name = BLUETOOTH_UART_DEV_NAME, + .flow_cntrl = 1, + .baud_rate = 3000000, +}; + +static struct platform_device wl128x_device = { + .name = "kim", + .id = -1, + .dev.platform_data = &enterprise_wilink_pdata, +}; + +static struct platform_device btwilink_device = { + .name = "btwilink", + .id = -1, +}; + +static noinline void __init enterprise_bt_st(void) +{ + pr_info("enterprise_bt_st"); + + platform_device_register(&wl128x_device); + platform_device_register(&btwilink_device); +} static struct rfkill_gpio_platform_data enterprise_bt_rfkill_pdata[] = { { .name = "bt_rfkill", @@ -137,8 +168,21 @@ static struct platform_device enterprise_bt_rfkill_device = { .platform_data = &enterprise_bt_rfkill_pdata, }, }; - -static struct resource enterprise_bluesleep_resources[] = { +static struct resource enterprise_ti_bluesleep_resources[] = { + [0] = { + .name = "gpio_host_wake", + .start = TEGRA_GPIO_PS2, + .end = TEGRA_GPIO_PS2, + .flags = IORESOURCE_IO, + }, + [1] = { + .name = "host_wake", + .start = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PS2), + .end = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PS2), + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, + }, +}; +static struct resource enterprise_brcm_bluesleep_resources[] = { [0] = { .name = "gpio_host_wake", .start = TEGRA_GPIO_PS2, @@ -159,16 +203,30 @@ static struct resource enterprise_bluesleep_resources[] = { }, }; -static struct platform_device enterprise_bluesleep_device = { +static struct platform_device enterprise_ti_bluesleep_device = { .name = "bluesleep", .id = -1, - .num_resources = ARRAY_SIZE(enterprise_bluesleep_resources), - .resource = enterprise_bluesleep_resources, + .num_resources = ARRAY_SIZE(enterprise_ti_bluesleep_resources), + .resource = enterprise_ti_bluesleep_resources, }; +static struct platform_device enterprise_brcm_bluesleep_device = { + .name = "bluesleep", + .id = -1, + .num_resources = ARRAY_SIZE(enterprise_brcm_bluesleep_resources), + .resource = enterprise_brcm_bluesleep_resources, +}; +static void __init enterprise_bt_rfkill(void) +{ + platform_device_register(&enterprise_bt_rfkill_device); + return; +} static void __init enterprise_setup_bluesleep(void) { - platform_device_register(&enterprise_bluesleep_device); + if (tegra_get_commchip_id() == COMMCHIP_TI_WL18XX) + platform_device_register(&enterprise_ti_bluesleep_device); + else + platform_device_register(&enterprise_brcm_bluesleep_device); return; } @@ -181,7 +239,6 @@ static __initdata struct tegra_clk_init_table enterprise_clk_init_table[] = { { "blink", "clk_32k", 32768, true}, { "i2s0", "pll_a_out0", 0, false}, { "i2s1", "pll_a_out0", 0, false}, - { "i2s2", "pll_a_out0", 0, false}, { "i2s3", "pll_a_out0", 0, false}, { "spdif_out", "pll_a_out0", 0, false}, { "d_audio", "clk_m", 12000000, false}, @@ -194,9 +251,61 @@ static __initdata struct tegra_clk_init_table enterprise_clk_init_table[] = { { "audio3", "i2s3_sync", 0, false}, { "vi", "pll_p", 0, false}, { "vi_sensor", "pll_p", 0, false}, + { "i2c5", "pll_p", 3200000, false}, { NULL, NULL, 0, 0}, }; +static __initdata struct tegra_clk_init_table enterprise_clk_i2s2_table[] = { + /* name parent rate enabled */ + { "i2s2", "pll_a_out0", 0, false}, + { NULL, NULL, 0, 0}, +}; + +static __initdata struct tegra_clk_init_table enterprise_clk_i2s4_table[] = { + /* name parent rate enabled */ + { "i2s4", "pll_a_out0", 0, false}, + { NULL, NULL, 0, 0}, +}; + +static struct aic3262_gpio_setup aic3262_gpio[] = { + /* GPIO 1*/ + { + .used = 1, + .in = 0, + .value = AIC3262_GPIO1_FUNC_INT1_OUTPUT , + }, + /* GPIO 2*/ + { + .used = 1, + .in = 0, + .value = AIC3262_GPIO2_FUNC_ADC_MOD_CLK_OUTPUT, + }, + /* GPIO 1 */ + { + .used = 0, + }, + {// GPI2 + .used = 1, + .in = 1, + .in_reg = AIC3262_DMIC_INPUT_CNTL, + .in_reg_bitmask = AIC3262_DMIC_CONFIGURE_MASK, + .in_reg_shift = AIC3262_DMIC_CONFIGURE_SHIFT, + .value = AIC3262_DMIC_GPI2_LEFT_GPI2_RIGHT, + }, + {// GPO1 + .used = 0, + .value = AIC3262_GPO1_FUNC_DISABLED, + }, +}; + +static struct aic3262_pdata aic3262_codec_pdata = { + .gpio_irq = 1, + .gpio_reset = TEGRA_GPIO_CODEC_RST, + .gpio = aic3262_gpio, + .naudint_irq = TEGRA_GPIO_HP_DET, + .irq_base = AIC3262_CODEC_IRQ_BASE, +}; + static struct tegra_i2c_platform_data enterprise_i2c1_platform_data = { .adapter_nr = 0, .bus_count = 1, @@ -237,7 +346,7 @@ static struct tegra_i2c_platform_data enterprise_i2c4_platform_data = { static struct tegra_i2c_platform_data enterprise_i2c5_platform_data = { .adapter_nr = 4, .bus_count = 1, - .bus_clk_rate = { 400000, 0 }, + .bus_clk_rate = { 390000, 0 }, .scl_gpio = {TEGRA_GPIO_PZ6, 0}, .sda_gpio = {TEGRA_GPIO_PZ7, 0}, .arb_recovery = arb_lost_recovery, @@ -351,8 +460,9 @@ static struct i2c_board_info __initdata max98088_board_info = { }; static struct i2c_board_info __initdata enterprise_codec_aic326x_info = { - I2C_BOARD_INFO("aic3262-codec", 0x18), - .irq = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_HP_DET), + I2C_BOARD_INFO("tlv320aic3262", 0x18), + .platform_data = &aic3262_codec_pdata, + .irq = TEGRA_GPIO_HP_DET, }; static struct i2c_board_info __initdata nfc_board_info = { @@ -466,8 +576,6 @@ static void __init enterprise_uart_init(void) ARRAY_SIZE(enterprise_uart_devices)); } - - static struct resource tegra_rtc_resources[] = { [0] = { .start = TEGRA_RTC_BASE, @@ -499,16 +607,26 @@ static struct tegra_asoc_platform_data enterprise_audio_pdata = { .gpio_hp_mute = -1, .gpio_int_mic_en = -1, .gpio_ext_mic_en = -1, - .debounce_time_hp = -1, + .debounce_time_hp = -1, /*defaults for Enterprise board*/ - .audio_port_id = { - [HIFI_CODEC] = 0, - [BASEBAND] = 2, - [BT_SCO] = 3, + .i2s_param[HIFI_CODEC] = { + .audio_port_id = 0, + .is_i2s_master = 0, + .i2s_mode = TEGRA_DAIFMT_I2S, + .sample_size = 16, + }, + .i2s_param[BASEBAND] = { + .is_i2s_master = 1, + .i2s_mode = TEGRA_DAIFMT_DSP_A, + .sample_size = 16, + .rate = 8000, + .channels = 1, }, - .baseband_param = { - .rate = 8000, - .channels = 1, + .i2s_param[BT_SCO] = { + .audio_port_id = 3, + .is_i2s_master = 1, + .i2s_mode = TEGRA_DAIFMT_DSP_A, + .sample_size = 16, }, }; @@ -527,15 +645,25 @@ static struct tegra_asoc_platform_data enterprise_audio_aic326x_pdata = { .gpio_int_mic_en = -1, .gpio_ext_mic_en = -1, /*defaults for Verbier-Enterprise (E1197) board with TI AIC326X codec*/ - .audio_port_id = { - [HIFI_CODEC] = 0, - [BASEBAND] = 2, - [BT_SCO] = 3, + .i2s_param[HIFI_CODEC] = { + .audio_port_id = 0, + .is_i2s_master = 1, + .i2s_mode = TEGRA_DAIFMT_I2S, + .sample_size = 16, + }, + .i2s_param[BASEBAND] = { + .audio_port_id = 2, + .is_i2s_master = 1, + .i2s_mode = TEGRA_DAIFMT_DSP_A, + .sample_size = 16, + .rate = 8000, + .channels = 1, }, - .baseband_param = { - .rate = 8000, - .channels = 1, - .bit_format = TEGRA_DAIFMT_DSP_A, + .i2s_param[BT_SCO] = { + .sample_size = 16, + .audio_port_id = 3, + .is_i2s_master = 1, + .i2s_mode = TEGRA_DAIFMT_DSP_A, }, }; @@ -561,7 +689,6 @@ static struct platform_device *enterprise_devices[] __initdata = { &tegra_avp_device, #endif &tegra_camera, - &enterprise_bt_rfkill_device, &tegra_spi_device4, &tegra_hda_device, #if defined(CONFIG_CRYPTO_DEV_TEGRA_SE) @@ -672,6 +799,14 @@ static void enterprise_usb_hsic_preresume(void) #endif } +static void enterprise_usb_hsic_post_resume(void) +{ + pr_debug("%s\n", __func__); +#ifdef CONFIG_TEGRA_BB_XMM_POWER + baseband_xmm_set_power_status(BBXMM_PS_L0); +#endif +} + static void enterprise_usb_hsic_phy_power(void) { pr_debug("%s\n", __func__); @@ -692,6 +827,7 @@ static struct tegra_usb_phy_platform_ops hsic_xmm_plat_ops = { .post_suspend = enterprise_usb_hsic_postsupend, .pre_resume = enterprise_usb_hsic_preresume, .port_power = enterprise_usb_hsic_phy_power, + .post_resume = enterprise_usb_hsic_post_resume, .post_phy_off = enterprise_usb_hsic_post_phy_off, }; @@ -706,21 +842,13 @@ static struct tegra_usb_platform_data tegra_ehci2_hsic_xmm_pdata = { .remote_wakeup_supported = false, .power_off_on_suspend = false, }, - .u_cfg.hsic = { - .sync_start_delay = 9, - .idle_wait_delay = 17, - .term_range_adj = 0, - .elastic_underrun_limit = 16, - .elastic_overrun_limit = 16, - }, .ops = &hsic_xmm_plat_ops, }; - - static struct tegra_usb_platform_data tegra_udc_pdata = { .port_otg = true, .has_hostpc = true, + .builtin_host_disabled = true, .phy_intf = TEGRA_USB_PHY_INTF_UTMI, .op_mode = TEGRA_USB_OPMODE_DEVICE, .u_data.dev = { @@ -809,9 +937,15 @@ error: return NULL; } -void tegra_usb_hsic_host_unregister(struct platform_device *pdev) +void tegra_usb_hsic_host_unregister(struct platform_device **platdev) { - platform_device_unregister(pdev); + struct platform_device *pdev = *platdev; + + if (pdev && &pdev->dev) { + platform_device_unregister(pdev); + *platdev = NULL; + } else + pr_err("%s: no platform device\n", __func__); } static void enterprise_usb_init(void) @@ -829,7 +963,6 @@ static struct platform_device *enterprise_audio_devices[] __initdata = { &tegra_dam_device2, &tegra_i2s_device0, &tegra_i2s_device1, - &tegra_i2s_device2, &tegra_i2s_device3, &tegra_spdif_device, &spdif_dit_device, @@ -846,11 +979,31 @@ static void enterprise_audio_init(void) tegra_get_board_info(&board_info); - if (board_info.board_id == BOARD_E1197) - enterprise_audio_pdata.audio_port_id[HIFI_CODEC] = 1; + if (board_info.board_id == BOARD_E1239) { + enterprise_audio_aic326x_pdata.i2s_param[BASEBAND]. + audio_port_id = 4; + enterprise_audio_aic326x_pdata.i2s_param[BASEBAND]. + i2s_mode = TEGRA_DAIFMT_I2S; + enterprise_audio_aic326x_pdata.i2s_param[BASEBAND]. + channels = 2; + platform_device_register(&tegra_i2s_device4); + } else { + if (board_info.board_id == BOARD_E1197) + enterprise_audio_pdata.i2s_param[HIFI_CODEC]. + audio_port_id = 1; + else if (board_info.fab == BOARD_FAB_A04) { + enterprise_audio_pdata.i2s_param[BASEBAND]. + audio_port_id = 4; + platform_device_register(&tegra_i2s_device4); + } else { + enterprise_audio_pdata.i2s_param[BASEBAND]. + audio_port_id = 2; + platform_device_register(&tegra_i2s_device2); + } + } platform_add_devices(enterprise_audio_devices, - ARRAY_SIZE(enterprise_audio_devices)); + ARRAY_SIZE(enterprise_audio_devices)); } @@ -917,8 +1070,12 @@ static struct platform_device tegra_baseband_m7400_device = { static void enterprise_baseband_init(void) { + struct board_info board_info; + int modem_id = tegra_get_modem_id(); + tegra_get_board_info(&board_info); + switch (modem_id) { case TEGRA_BB_PH450: /* PH450 ULPI */ enterprise_modem_init(); @@ -931,7 +1088,13 @@ static void enterprise_baseband_init(void) &tegra_usb_hsic_host_register; tegra_baseband_power_data.hsic_unregister = &tegra_usb_hsic_host_unregister; - + if ((board_info.board_id == BOARD_E1239) && + (board_info.fab <= BOARD_FAB_A02)) { + tegra_baseband_power_data.modem. + xmm.ipc_hsic_active = BB_GPIO_LCD_PWR2; + tegra_baseband_power_data.modem. + xmm.ipc_hsic_sus_req = BB_GPIO_LCD_PWR1; + } platform_device_register(&tegra_baseband_power_device); platform_device_register(&tegra_baseband_power2_device); break; @@ -953,11 +1116,20 @@ static void enterprise_nfc_init(void) tegra_get_board_info(&bi); if (bi.board_id == BOARD_E1205 && bi.fab >= BOARD_FAB_A03) { nfc_pdata.firm_gpio = TEGRA_GPIO_PX7; + } else if (bi.board_id == BOARD_E1239) { + nfc_pdata.firm_gpio = TEGRA_GPIO_PD2; } } static void __init tegra_enterprise_init(void) { + struct board_info board_info; + tegra_get_board_info(&board_info); + if (board_info.fab == BOARD_FAB_A04) + tegra_clk_init_from_table(enterprise_clk_i2s4_table); + else + tegra_clk_init_from_table(enterprise_clk_i2s2_table); + tegra_thermal_init(&thermal_data, throttle_list, ARRAY_SIZE(throttle_list)); @@ -966,9 +1138,12 @@ static void __init tegra_enterprise_init(void) enterprise_i2c_init(); enterprise_uart_init(); enterprise_usb_init(); + if (board_info.board_id == BOARD_E1239) + enterprise_bt_rfkill_pdata[0].reset_gpio = TEGRA_GPIO_PF4; platform_add_devices(enterprise_devices, ARRAY_SIZE(enterprise_devices)); tegra_ram_console_debug_init(); enterprise_regulator_init(); + tegra_io_dpd_init(); enterprise_sdhci_init(); #ifdef CONFIG_TEGRA_EDP_LIMITS enterprise_edp_init(); @@ -979,6 +1154,10 @@ static void __init tegra_enterprise_init(void) enterprise_audio_init(); enterprise_baseband_init(); enterprise_panel_init(); + if (tegra_get_commchip_id() == COMMCHIP_TI_WL18XX) + enterprise_bt_st(); + else + enterprise_bt_rfkill(); enterprise_setup_bluesleep(); enterprise_emc_init(); enterprise_sensors_init(); @@ -998,6 +1177,11 @@ static void __init tegra_enterprise_reserve(void) tegra_ram_console_debug_reserve(SZ_1M); } +static const char *enterprise_dt_board_compat[] = { + "nvidia,enterprise", + NULL +}; + MACHINE_START(TEGRA_ENTERPRISE, "tegra_enterprise") .boot_params = 0x80000100, .map_io = tegra_map_common_io, @@ -1006,4 +1190,5 @@ MACHINE_START(TEGRA_ENTERPRISE, "tegra_enterprise") .init_irq = tegra_init_irq, .timer = &tegra_timer, .init_machine = tegra_enterprise_init, + .dt_compat = enterprise_dt_board_compat, MACHINE_END diff --git a/arch/arm/mach-tegra/board-enterprise.h b/arch/arm/mach-tegra/board-enterprise.h index 3c6d149abdff..ae488dfb4618 100644 --- a/arch/arm/mach-tegra/board-enterprise.h +++ b/arch/arm/mach-tegra/board-enterprise.h @@ -1,7 +1,7 @@ /* * arch/arm/mach-tegra/board-enterprise.h * - * Copyright (c) 2011, NVIDIA Corporation. + * Copyright (c) 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 @@ -28,6 +28,7 @@ /* Processor Board ID */ #define BOARD_E1205 0x0C05 #define BOARD_E1197 0x0B61 +#define BOARD_E1239 0x0C27 #define SKU_BATTERY_SUPPORT 0x1 /* Board Fab version */ @@ -93,6 +94,11 @@ void enterprise_bpc_mgmt_init(void); #define ENT_TPS80031_IRQ_BASE TEGRA_NR_IRQS #define ENT_TPS80031_IRQ_END (ENT_TPS80031_IRQ_BASE + TPS80031_INT_NR) +/* AIC326X IRQs */ +/* Assuming TPS is the PMIC on Ent */ +#define AIC3262_CODEC_IRQ_BASE ENT_TPS80031_IRQ_END +#define AIC3262_CODEC_IRQ_END (AIC3262_CODEC_IRQ_BASE + 6) + /*****************Camera GPIOs ******************/ #define CAM_CSI_MUX_SEL_GPIO TEGRA_GPIO_PM3 #define CAM_CSI_MUX_SEL_REAR 1 @@ -113,7 +119,10 @@ void enterprise_bpc_mgmt_init(void); /* Audio-related GPIOs */ #define TEGRA_GPIO_HP_DET TEGRA_GPIO_PW3 +#define TEGRA_GPIO_CODEC_RST TEGRA_GPIO_PX0 +/* UART port which is used by bluetooth*/ +#define BLUETOOTH_UART_DEV_NAME "/dev/ttyHS2" /* Baseband GPIO addresses */ #define GPIO_BB_RESET TEGRA_GPIO_PE1 @@ -159,6 +168,7 @@ enum tegra_bb_type { }; /* Indicate the pwm of backlight, DC pwm or external pwm3. */ +/* External pwm is used for TAI (E1239) but do not set this compiler switch */ #define IS_EXTERNAL_PWM 0 #endif /*_MACH_TEGRA_BOARD_ENTERPRISE_H */ diff --git a/arch/arm/mach-tegra/board-harmony-panel.c b/arch/arm/mach-tegra/board-harmony-panel.c index d4cd3f461b66..ff1c44ad0f3a 100644 --- a/arch/arm/mach-tegra/board-harmony-panel.c +++ b/arch/arm/mach-tegra/board-harmony-panel.c @@ -57,8 +57,6 @@ static int harmony_backlight_init(struct device *dev) ret = gpio_direction_output(harmony_bl_enb, 1); if (ret < 0) gpio_free(harmony_bl_enb); - else - tegra_gpio_enable(harmony_bl_enb); return ret; } @@ -67,7 +65,6 @@ static void harmony_backlight_exit(struct device *dev) { gpio_set_value(harmony_bl_enb, 0); gpio_free(harmony_bl_enb); - tegra_gpio_disable(harmony_bl_enb); } static int harmony_backlight_notify(struct device *unused, int brightness) @@ -337,19 +334,15 @@ int __init harmony_panel_init(void) gpio_request(harmony_en_vdd_pnl, "en_vdd_pnl"); gpio_direction_output(harmony_en_vdd_pnl, 1); - tegra_gpio_enable(harmony_en_vdd_pnl); gpio_request(harmony_bl_vdd, "bl_vdd"); gpio_direction_output(harmony_bl_vdd, 1); - tegra_gpio_enable(harmony_bl_vdd); gpio_request(harmony_lvds_shutdown, "lvds_shdn"); gpio_direction_output(harmony_lvds_shutdown, 1); - tegra_gpio_enable(harmony_lvds_shutdown); gpio_request(harmony_hdmi_hpd, "hdmi_hpd"); gpio_direction_input(harmony_hdmi_hpd); - tegra_gpio_enable(harmony_hdmi_hpd); #if defined(CONFIG_TEGRA_NVMAP) harmony_carveouts[1].base = tegra_carveout_start; diff --git a/arch/arm/mach-tegra/board-harmony.c b/arch/arm/mach-tegra/board-harmony.c index dd14435cc17c..0e8a9f18c6d9 100644 --- a/arch/arm/mach-tegra/board-harmony.c +++ b/arch/arm/mach-tegra/board-harmony.c @@ -3,6 +3,7 @@ * * Copyright (C) 2010 Google, Inc. * Copyright (C) 2011 NVIDIA, Inc. + * Copyright (c) 2012, NVIDIA CORPORATION. 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 @@ -43,7 +44,7 @@ #include <asm/mach/time.h> #include <asm/setup.h> -#include <mach/tegra_wm8903_pdata.h> +#include <mach/tegra_asoc_pdata.h> #include <mach/iomap.h> #include <mach/irqs.h> #include <mach/sdhci.h> @@ -222,20 +223,25 @@ static struct platform_device harmony_gpio_keys_device = { } }; -static void harmony_keys_init(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(harmony_gpio_keys_buttons); i++) - tegra_gpio_enable(harmony_gpio_keys_buttons[i].gpio); -} - -static struct tegra_wm8903_platform_data harmony_audio_pdata = { +static struct tegra_asoc_platform_data harmony_audio_pdata = { .gpio_spkr_en = TEGRA_GPIO_SPKR_EN, .gpio_hp_det = TEGRA_GPIO_HP_DET, .gpio_hp_mute = -1, .gpio_int_mic_en = TEGRA_GPIO_INT_MIC_EN, .gpio_ext_mic_en = TEGRA_GPIO_EXT_MIC_EN, + .i2s_param[HIFI_CODEC] = { + .audio_port_id = 0, + .is_i2s_master = 1, + .i2s_mode = TEGRA_DAIFMT_I2S, + }, + .i2s_param[BASEBAND] = { + .audio_port_id = -1, + }, + .i2s_param[BT_SCO] = { + .audio_port_id = 3, + .is_i2s_master = 1, + .i2s_mode = TEGRA_DAIFMT_DSP_A, + }, }; static struct platform_device harmony_audio_device = { @@ -486,8 +492,6 @@ static int __init harmony_wifi_prepower(void) pr_warning("Unable to get gpio for WLAN Power and Reset\n"); else { - tegra_gpio_enable(TEGRA_GPIO_WLAN_PWR_LOW); - tegra_gpio_enable(TEGRA_GPIO_WLAN_RST_LOW); /* toggle in this order as per spec */ gpio_direction_output(TEGRA_GPIO_WLAN_PWR_LOW, 0); gpio_direction_output(TEGRA_GPIO_WLAN_RST_LOW, 0); @@ -514,8 +518,6 @@ static void __init tegra_harmony_init(void) harmony_pinmux_init(); - harmony_keys_init(); - harmony_uart_init(); tegra_sdhci_device1.dev.platform_data = &sdhci_pdata1; diff --git a/arch/arm/mach-tegra/board-kai-memory.c b/arch/arm/mach-tegra/board-kai-memory.c index 1f812ece741b..07d6405c7016 100644 --- a/arch/arm/mach-tegra/board-kai-memory.c +++ b/arch/arm/mach-tegra/board-kai-memory.c @@ -117,8 +117,8 @@ static const struct tegra_emc_table kai_emc_tables_h5tc4g[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000287, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00020001, /* MC_EMEM_ARB_CFG */ - 0xc0000008, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x00030003, /* MC_EMEM_ARB_CFG */ + 0xc0000010, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ 0x00000002, /* MC_EMEM_ARB_TIMING_RC */ @@ -237,8 +237,8 @@ static const struct tegra_emc_table kai_emc_tables_h5tc4g[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x8000040b, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00010001, /* MC_EMEM_ARB_CFG */ - 0xc000000a, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x00010003, /* MC_EMEM_ARB_CFG */ + 0xc0000010, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ 0x00000002, /* MC_EMEM_ARB_TIMING_RC */ @@ -357,8 +357,8 @@ static const struct tegra_emc_table kai_emc_tables_h5tc4g[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000713, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000001, /* MC_EMEM_ARB_CFG */ - 0xc0000013, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x00000003, /* MC_EMEM_ARB_CFG */ + 0xc0000018, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ 0x00000003, /* MC_EMEM_ARB_TIMING_RC */ @@ -477,7 +477,7 @@ static const struct tegra_emc_table kai_emc_tables_h5tc4g[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x80000d22, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000003, /* MC_EMEM_ARB_CFG */ + 0x00000006, /* MC_EMEM_ARB_CFG */ 0xc0000025, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */ @@ -597,8 +597,8 @@ static const struct tegra_emc_table kai_emc_tables_h5tc4g[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x800014d4, /* EMC_DYN_SELF_REF_CONTROL */ - 0x00000005, /* MC_EMEM_ARB_CFG */ - 0x8000003d, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x0000000a, /* MC_EMEM_ARB_CFG */ + 0xc000003d, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000002, /* MC_EMEM_ARB_TIMING_RP */ 0x00000008, /* MC_EMEM_ARB_TIMING_RC */ @@ -717,8 +717,8 @@ static const struct tegra_emc_table kai_emc_tables_h5tc4g[] = { 0x00000000, /* EMC_CTT */ 0x00000000, /* EMC_CTT_DURATION */ 0x800028a5, /* EMC_DYN_SELF_REF_CONTROL */ - 0x0000000a, /* MC_EMEM_ARB_CFG */ - 0x80000079, /* MC_EMEM_ARB_OUTSTANDING_REQ */ + 0x00000014, /* MC_EMEM_ARB_CFG */ + 0xc0000079, /* MC_EMEM_ARB_OUTSTANDING_REQ */ 0x00000003, /* MC_EMEM_ARB_TIMING_RCD */ 0x00000004, /* MC_EMEM_ARB_TIMING_RP */ 0x00000010, /* MC_EMEM_ARB_TIMING_RC */ diff --git a/arch/arm/mach-tegra/board-kai-power.c b/arch/arm/mach-tegra/board-kai-power.c index 6c66f1d2bbe9..027d97458dd3 100644 --- a/arch/arm/mach-tegra/board-kai-power.c +++ b/arch/arm/mach-tegra/board-kai-power.c @@ -614,6 +614,14 @@ static struct tegra_suspend_platform_data kai_suspend_data = { .cpu_lp2_min_residency = 2000, .board_suspend = kai_board_suspend, .board_resume = kai_board_resume, +#ifdef CONFIG_TEGRA_LP1_950 + .lp1_lowvolt_support = true, + .i2c_base_addr = TEGRA_I2C5_BASE, + .pmuslave_addr = 0x78, + .core_reg_addr = 0x17, + .lp1_core_volt_low = 0x0C, + .lp1_core_volt_high = 0x20, +#endif }; int __init kai_suspend_init(void) diff --git a/arch/arm/mach-tegra/board-kai-sdhci.c b/arch/arm/mach-tegra/board-kai-sdhci.c index 0fa39ccf475d..70ba7bcdb202 100644 --- a/arch/arm/mach-tegra/board-kai-sdhci.c +++ b/arch/arm/mach-tegra/board-kai-sdhci.c @@ -28,6 +28,7 @@ #include <mach/irqs.h> #include <mach/iomap.h> #include <mach/sdhci.h> +#include <mach/io_dpd.h> #include "gpio-names.h" #include "board.h" @@ -202,8 +203,21 @@ static int kai_wifi_set_carddetect(int val) static int kai_wifi_power(int power_on) { + struct tegra_io_dpd *sd_dpd; pr_err("Powering %s wifi\n", (power_on ? "on" : "off")); + /* + * FIXME : we need to revisit IO DPD code + * on how should multiple pins under DPD get controlled + * + * kai GPIO WLAN enable is part of SDMMC3 pin group + */ + sd_dpd = tegra_io_dpd_get(&tegra_sdhci_device2.dev); + if (sd_dpd) { + mutex_lock(&sd_dpd->delay_lock); + tegra_io_dpd_disable(sd_dpd); + mutex_unlock(&sd_dpd->delay_lock); + } if (power_on) { gpio_set_value(KAI_WLAN_EN, 1); mdelay(15); @@ -214,6 +228,11 @@ static int kai_wifi_power(int power_on) } else { gpio_set_value(KAI_WLAN_EN, 0); } + if (sd_dpd) { + mutex_lock(&sd_dpd->delay_lock); + tegra_io_dpd_enable(sd_dpd); + mutex_unlock(&sd_dpd->delay_lock); + } return 0; } diff --git a/arch/arm/mach-tegra/board-kai-sensors.c b/arch/arm/mach-tegra/board-kai-sensors.c index 29d1bea2e8a7..048c39c9759f 100644 --- a/arch/arm/mach-tegra/board-kai-sensors.c +++ b/arch/arm/mach-tegra/board-kai-sensors.c @@ -179,8 +179,15 @@ static int kai_camera_init(void) static int kai_ov2710_power_on(void) { - gpio_direction_output(CAM2_POWER_DWN_GPIO, 0); - mdelay(10); + if (kai_1v8_cam3 == NULL) { + kai_1v8_cam3 = regulator_get(NULL, "vdd_1v8_cam3"); + if (WARN_ON(IS_ERR(kai_1v8_cam3))) { + pr_err("%s: couldn't get regulator vdd_1v8_cam3: %d\n", + __func__, (int)PTR_ERR(kai_1v8_cam3)); + goto reg_get_vdd_1v8_cam3_fail; + } + } + regulator_enable(kai_1v8_cam3); if (kai_vdd_cam3 == NULL) { kai_vdd_cam3 = regulator_get(NULL, "vdd_cam3"); @@ -191,43 +198,36 @@ static int kai_ov2710_power_on(void) } } regulator_enable(kai_vdd_cam3); - - if (kai_1v8_cam3 == NULL) { - kai_1v8_cam3 = regulator_get(NULL, "vdd_1v8_cam3"); - if (WARN_ON(IS_ERR(kai_1v8_cam3))) { - pr_err("%s: couldn't get regulator vdd_1v8_cam3: %d\n", - __func__, (int)PTR_ERR(kai_1v8_cam3)); - goto reg_get_vdd_1v8_cam3_fail; - } - } - regulator_enable(kai_1v8_cam3); mdelay(5); + gpio_direction_output(CAM2_POWER_DWN_GPIO, 0); + mdelay(10); + gpio_direction_output(CAM2_RST_GPIO, 1); mdelay(10); return 0; -reg_get_vdd_1v8_cam3_fail: - kai_1v8_cam3 = NULL; - regulator_put(kai_vdd_cam3); - reg_get_vdd_cam3_fail: kai_vdd_cam3 = NULL; + regulator_put(kai_1v8_cam3); + +reg_get_vdd_1v8_cam3_fail: + kai_1v8_cam3 = NULL; return -ENODEV; } static int kai_ov2710_power_off(void) { - gpio_direction_output(CAM2_POWER_DWN_GPIO, 1); - gpio_direction_output(CAM2_RST_GPIO, 0); - if (kai_1v8_cam3) - regulator_disable(kai_1v8_cam3); + gpio_direction_output(CAM2_POWER_DWN_GPIO, 1); + if (kai_vdd_cam3) regulator_disable(kai_vdd_cam3); + if (kai_1v8_cam3) + regulator_disable(kai_1v8_cam3); return 0; } diff --git a/arch/arm/mach-tegra/board-kai.c b/arch/arm/mach-tegra/board-kai.c index bf4ae415072d..83874f89d836 100644 --- a/arch/arm/mach-tegra/board-kai.c +++ b/arch/arm/mach-tegra/board-kai.c @@ -1,7 +1,7 @@ /* * arch/arm/mach-tegra/board-kai.c * - * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -50,8 +50,9 @@ #include <mach/pinmux.h> #include <mach/iomap.h> #include <mach/io.h> +#include <mach/io_dpd.h> #include <mach/i2s.h> -#include <mach/tegra_rt5640_pdata.h> +#include <mach/tegra_asoc_pdata.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> #include <mach/usb_phy.h> @@ -574,12 +575,25 @@ static struct platform_device tegra_rtc_device = { .num_resources = ARRAY_SIZE(tegra_rtc_resources), }; -static struct tegra_rt5640_platform_data kai_audio_pdata = { +static struct tegra_asoc_platform_data kai_audio_pdata = { .gpio_spkr_en = TEGRA_GPIO_SPKR_EN, .gpio_hp_det = TEGRA_GPIO_HP_DET, .gpio_hp_mute = -1, .gpio_int_mic_en = TEGRA_GPIO_INT_MIC_EN, .gpio_ext_mic_en = TEGRA_GPIO_EXT_MIC_EN, + .i2s_param[HIFI_CODEC] = { + .audio_port_id = 0, + .is_i2s_master = 1, + .i2s_mode = TEGRA_DAIFMT_I2S, + }, + .i2s_param[BASEBAND] = { + .audio_port_id = -1, + }, + .i2s_param[BT_SCO] = { + .audio_port_id = 3, + .is_i2s_master = 1, + .i2s_mode = TEGRA_DAIFMT_DSP_A, + }, }; static struct platform_device kai_audio_device = { @@ -870,6 +884,7 @@ static void __init tegra_kai_init(void) kai_audio_init(); platform_add_devices(kai_devices, ARRAY_SIZE(kai_devices)); tegra_ram_console_debug_init(); + tegra_io_dpd_init(); kai_sdhci_init(); kai_regulator_init(); kai_suspend_init(); diff --git a/arch/arm/mach-tegra/board-p1852-panel.c b/arch/arm/mach-tegra/board-p1852-panel.c index 4e86476cdd2c..8ca533175ea1 100644 --- a/arch/arm/mach-tegra/board-p1852-panel.c +++ b/arch/arm/mach-tegra/board-p1852-panel.c @@ -29,7 +29,27 @@ #include "board.h" #include "devices.h" #include "tegra3_host1x_devices.h" +#include "board-p1852.h" +#include "gpio-names.h" +#define P1852_LVDS_ENA1 TEGRA_GPIO_PV0 +#define P1852_LVDS_ENA2 TEGRA_GPIO_PV1 +#define P1852_HDMI_HPD TEGRA_GPIO_PN7 +#define P1852_HDMI_RGB TEGRA_GPIO_PW1 +#define P1852_LVDS_SER1_ADDR 0xd +#define P1852_LVDS_SER2_ADDR 0xc + +#define LVDS_SER_REG_CONFIG_1 0x4 +#define LVDS_SER_REG_CONFIG_1_BKWD_OVERRIDE 3 +#define LVDS_SER_REG_CONFIG_1_BKWD 2 + +#define LVDS_SER_REG_DATA_PATH_CTRL 0x12 +#define LVDS_SER_REG_DATA_PATH_CTRL_PASS_RGB 6 + +#define LVDS_SER_REG_CONFIG_0 0x3 +#define LVDS_SER_REG_CONFIG_0_TRFB 0 + +/* RGB panel requires no special enable/disable */ static int p1852_panel_enable(void) { return 0; @@ -40,6 +60,199 @@ static int p1852_panel_disable(void) return 0; } +static int ser_i2c_read(struct i2c_client *client, + u8 reg_addr, u8 *pval) +{ + struct i2c_msg msg[] = { + { + .addr = client->addr, + .flags = 0, + .len = 1, + .buf = ®_addr, + }, + { + .addr = client->addr, + .flags = I2C_M_RD, + .len = 1, + .buf = pval, + }, + }; + + return i2c_transfer(client->adapter, msg, 2); +} + +static int ser_i2c_write(struct i2c_client *client, + u8 reg_addr, u8 val) +{ + u8 buffer[] = {reg_addr, val}; + struct i2c_msg msg[] = { + { + .addr = client->addr, + .flags = 0, + .len = 2, + .buf = buffer, + }, + }; + + return i2c_transfer(client->adapter, msg, 1); +} + +static int lvds_ser_init(struct i2c_client *client, + bool is_fpdlinkII, + bool support_hdcp, + bool clk_rise_edge) +{ + u8 val; + int err = 0; + + /* intentional call make register & bus ready */ + ser_i2c_read(client, LVDS_SER_REG_CONFIG_1, &val); + + if (is_fpdlinkII) { + err = ser_i2c_read(client, LVDS_SER_REG_CONFIG_1, &val); + if (err < 0) + return err; + + val |= (1 << LVDS_SER_REG_CONFIG_1_BKWD_OVERRIDE); + val |= (1 << LVDS_SER_REG_CONFIG_1_BKWD); + + err = ser_i2c_write(client, LVDS_SER_REG_CONFIG_1, val); + if (err < 0) + return err; + } + else if (!support_hdcp) { + err = ser_i2c_read(client, LVDS_SER_REG_DATA_PATH_CTRL, &val); + if (err < 0) + return err; + + val |= (1 << LVDS_SER_REG_DATA_PATH_CTRL_PASS_RGB); + + err = ser_i2c_write(client, LVDS_SER_REG_DATA_PATH_CTRL, val); + if (err < 0) + return err; + } + + if (clk_rise_edge) { + err = ser_i2c_read(client, LVDS_SER_REG_CONFIG_0, &val); + if (err < 0) + return err; + + val |= (1 << LVDS_SER_REG_CONFIG_0_TRFB); + + err = ser_i2c_write(client, LVDS_SER_REG_CONFIG_0, val); + } + + return (err < 0 ? err : 0); +} + +/* enable primary LVDS */ +static int p1852_lvds_enable(void) +{ + struct i2c_adapter *adapter; + struct i2c_board_info info = {{0}}; + static struct i2c_client *client; + int err = -1; + + /* Turn on serializer chip */ + gpio_set_value(P1852_LVDS_ENA1, 1); + + /* Program the serializer */ + adapter = i2c_get_adapter(3); + if (!adapter) + pr_warning("%s: adapter is null\n", __func__); + else { + info.addr = P1852_LVDS_SER1_ADDR; + if (!client) + client = i2c_new_device(adapter, &info); + i2c_put_adapter(adapter); + if (!client) + pr_warning("%s: client is null\n", __func__); + else { + err = lvds_ser_init(client, + true, /* is_fpdlinkII*/ + false, /* support_hdcp */ + true); /* clk_rise_edge */ + } + } + return err; +} + +/* Disable primary LVDS */ +static int p1852_lvds_disable(void) +{ + /* Turn off serializer chip */ + gpio_set_value(P1852_LVDS_ENA1, 0); + + return 0; +} + +/* Enable secondary LVDS */ +static int p1852_lvds2_enable(void) +{ + struct i2c_adapter *adapter; + struct i2c_board_info info = {{0}}; + static struct i2c_client *client; + int err = -1; + + /* Enable HDMI HPD */ + /* need nothing here */ + + /* Turn on HDMI-RGB converter */ + gpio_set_value(P1852_HDMI_RGB, 1); + + /* Turn on serializer chip */ + gpio_set_value(P1852_LVDS_ENA2, 1); + + /* Program the serializer */ + adapter = i2c_get_adapter(3); + if (!adapter) + pr_warning("%s: adapter is null\n", __func__); + else { + info.addr = P1852_LVDS_SER2_ADDR; + if (!client) + client = i2c_new_device(adapter, &info); + i2c_put_adapter(adapter); + if (!client) + pr_warning("%s: client is null\n", __func__); + else { + err = lvds_ser_init(client, + true, /* is_fpdlinkII*/ + false, /* support_hdcp */ + true); /* clk_rise_edge */ + } + } + return err; +} + +/* Disable secondary LVDS */ +static int p1852_lvds2_disable(void) +{ + /* Turn off serializer chip */ + gpio_set_value(P1852_LVDS_ENA2, 0); + + /* Turn off HDMI-RGB converter */ + gpio_set_value(P1852_HDMI_RGB, 0); + + /* Turn off HDMI */ + /* need nothing here */ + + return 0; +} + +/* Enable secondary HDMI */ +static int p1852_hdmi_enable(void) +{ + /* need nothing here */ + return 0; +} + +/* Disable secondary HDMI */ +static int p1852_hdmi_disable(void) +{ + /* need nothing here */ + return 0; +} + #ifdef CONFIG_TOUCHSCREEN_ATMEL_MXT static struct tegra_dc_mode p1852_panel_modes[] = { @@ -123,9 +336,42 @@ static struct tegra_fb_data p1852_fb_data = { #endif +/* Mode data for secondary LVDS out */ +static struct tegra_dc_mode p1852_hdmi_lvds_modes[] = { + { + /* 800x480@60 */ + .pclk = 33260000, + .h_ref_to_sync = 1, + .v_ref_to_sync = 1, + .h_sync_width = 64, + .v_sync_width = 3, + .h_back_porch = 128, + .v_back_porch = 38, + .h_front_porch = 64, + .v_front_porch = 4, + .h_active = 800, + .v_active = 480, + }, +}; + +static struct tegra_fb_data p1852_hdmi_fb_data = { + .win = 0, + .xres = 800, + .yres = 480, + .bits_per_pixel = 32, + .flags = TEGRA_FB_FLIP_ON_PROBE, +}; + +/* Start of DC_OUT data + * disp1 = Primary RGB out + * ser1 = Primary LVDS out + * ser2 = Secondary LVDS out + * hdmi = Secondary HDMI out + */ static struct tegra_dc_out p1852_disp1_out = { .align = TEGRA_DC_ALIGN_MSB, .order = TEGRA_DC_ORDER_RED_BLUE, + .parent_clk = "pll_d_out0", .type = TEGRA_DC_OUT_RGB, .modes = p1852_panel_modes, .n_modes = ARRAY_SIZE(p1852_panel_modes), @@ -133,6 +379,51 @@ static struct tegra_dc_out p1852_disp1_out = { .disable = p1852_panel_disable, }; +static struct tegra_dc_out p1852_ser1_out = { + .align = TEGRA_DC_ALIGN_MSB, + .order = TEGRA_DC_ORDER_RED_BLUE, + .parent_clk = "pll_d_out0", + .type = TEGRA_DC_OUT_RGB, + .modes = p1852_panel_modes, + .n_modes = ARRAY_SIZE(p1852_panel_modes), + .enable = p1852_lvds_enable, + .disable = p1852_lvds_disable, +}; + +static struct tegra_dc_out p1852_ser2_out = { + .align = TEGRA_DC_ALIGN_MSB, + .order = TEGRA_DC_ORDER_RED_BLUE, + .parent_clk = "pll_d2_out0", + .type = TEGRA_DC_OUT_HDMI, + .flags = TEGRA_DC_OUT_HOTPLUG_LOW | + TEGRA_DC_OUT_NVHDCP_POLICY_ON_DEMAND, + .max_pixclock = KHZ2PICOS(148500), + .hotplug_gpio = P1852_HDMI_HPD, + .modes = p1852_hdmi_lvds_modes, + .n_modes = ARRAY_SIZE(p1852_hdmi_lvds_modes), + .enable = p1852_lvds2_enable, + .disable = p1852_lvds2_disable, + .dcc_bus = 3, +}; + +static struct tegra_dc_out p1852_hdmi_out = { + .align = TEGRA_DC_ALIGN_MSB, + .order = TEGRA_DC_ORDER_RED_BLUE, + .parent_clk = "pll_d2_out0", + .type = TEGRA_DC_OUT_HDMI, + .flags = TEGRA_DC_OUT_HOTPLUG_LOW | + TEGRA_DC_OUT_NVHDCP_POLICY_ON_DEMAND, + .max_pixclock = KHZ2PICOS(148500), + .hotplug_gpio = P1852_HDMI_HPD, + .enable = p1852_hdmi_enable, + .disable = p1852_hdmi_disable, + + .dcc_bus = 1, +}; + +/* End of DC_OUT data */ + +/* Start of platform data */ static struct tegra_dc_platform_data p1852_disp1_pdata = { .flags = TEGRA_DC_FLAG_ENABLED, .default_out = &p1852_disp1_out, @@ -140,6 +431,29 @@ static struct tegra_dc_platform_data p1852_disp1_pdata = { .fb = &p1852_fb_data, }; +static struct tegra_dc_platform_data p1852_ser1_pdata = { + .flags = TEGRA_DC_FLAG_ENABLED, + .default_out = &p1852_ser1_out, + .emc_clk_rate = 300000000, + .fb = &p1852_fb_data, +}; + +static struct tegra_dc_platform_data p1852_ser2_pdata = { + .flags = TEGRA_DC_FLAG_ENABLED, + .default_out = &p1852_ser2_out, + .emc_clk_rate = 300000000, + .fb = &p1852_hdmi_fb_data, +}; + +static struct tegra_dc_platform_data p1852_hdmi_pdata = { + .flags = TEGRA_DC_FLAG_ENABLED, + .default_out = &p1852_hdmi_out, + .emc_clk_rate = 300000000, + .fb = &p1852_hdmi_fb_data, +}; + +/* End of platform data */ + static struct nvmap_platform_carveout p1852_carveouts[] = { [0] = { .name = "iram", @@ -166,7 +480,7 @@ static struct platform_device *p1852_gfx_devices[] __initdata = { &tegra_nvmap_device, }; -int __init p1852_panel_init(void) +static int __init p1852_sku2_panel_init(void) { int err; struct resource *res; @@ -174,16 +488,62 @@ int __init p1852_panel_init(void) p1852_carveouts[1].base = tegra_carveout_start; p1852_carveouts[1].size = tegra_carveout_size; tegra_nvmap_device.dev.platform_data = &p1852_nvmap_data; - tegra_disp1_device.dev.platform_data = &p1852_disp1_pdata; + /* + * sku2 has primary LVDS out and secondary LVDS out + * (via HDMI->RGB->Serializer) + */ + tegra_disp1_device.dev.platform_data = &p1852_ser1_pdata; + tegra_disp2_device.dev.platform_data = &p1852_ser2_pdata; +#ifdef CONFIG_TEGRA_GRHOST + err = tegra3_register_host1x_devices(); + if (err) + return err; +#endif + + err = platform_add_devices(p1852_gfx_devices, + ARRAY_SIZE(p1852_gfx_devices)); + +#if defined(CONFIG_TEGRA_GRHOST) && defined(CONFIG_TEGRA_DC) res = nvhost_get_resource_byname(&tegra_disp1_device, IORESOURCE_MEM, "fbmem"); - if (!res) { - pr_err("No memory resources\n"); - return -ENODEV; + if (res) { + res->start = tegra_fb_start; + res->end = tegra_fb_start + tegra_fb_size - 1; + } + + if (!err) + err = nvhost_device_register(&tegra_disp1_device); + + res = nvhost_get_resource_byname(&tegra_disp2_device, + IORESOURCE_MEM, "fbmem"); + if (res) { + res->start = tegra_fb2_start; + res->end = tegra_fb2_start + tegra_fb2_size - 1; } - res->start = tegra_fb_start; - res->end = tegra_fb_start + tegra_fb_size - 1; + + if (!err) + err = nvhost_device_register(&tegra_disp2_device); +#endif + +#if defined(CONFIG_TEGRA_GRHOST) && defined(CONFIG_TEGRA_NVAVP) + if (!err) + err = nvhost_device_register(&nvavp_device); +#endif + return err; +} + +static int __init p1852_sku8_panel_init(void) +{ + int err; + struct resource *res; + + p1852_carveouts[1].base = tegra_carveout_start; + p1852_carveouts[1].size = tegra_carveout_size; + tegra_nvmap_device.dev.platform_data = &p1852_nvmap_data; + /* sku 8 has primary RGB out and secondary HDMI out */ + tegra_disp1_device.dev.platform_data = &p1852_disp1_pdata; + tegra_disp2_device.dev.platform_data = &p1852_hdmi_pdata; #ifdef CONFIG_TEGRA_GRHOST err = tegra3_register_host1x_devices(); @@ -193,12 +553,50 @@ int __init p1852_panel_init(void) err = platform_add_devices(p1852_gfx_devices, ARRAY_SIZE(p1852_gfx_devices)); + +#if defined(CONFIG_TEGRA_GRHOST) && defined(CONFIG_TEGRA_DC) + res = nvhost_get_resource_byname(&tegra_disp1_device, + IORESOURCE_MEM, "fbmem"); + if (res) { + res->start = tegra_fb_start; + res->end = tegra_fb_start + tegra_fb_size - 1; + } + if (!err) err = nvhost_device_register(&tegra_disp1_device); + res = nvhost_get_resource_byname(&tegra_disp2_device, + IORESOURCE_MEM, "fbmem"); + if (res) { + res->start = tegra_fb2_start; + res->end = tegra_fb2_start + tegra_fb2_size - 1; + } + + if (!err) + err = nvhost_device_register(&tegra_disp2_device); +#endif + #if defined(CONFIG_TEGRA_GRHOST) && defined(CONFIG_TEGRA_NVAVP) if (!err) err = nvhost_device_register(&nvavp_device); #endif return err; } + +int __init p1852_panel_init(void) +{ + int skuid; + + skuid = p1852_get_skuid(); + + switch (skuid) { + case 2: + return p1852_sku2_panel_init(); + case 5: /* Sku 5 display is same as 8 */ + case 8: + return p1852_sku8_panel_init(); + default: + pr_warning("%s: unknown skuid %d\n", __func__, skuid); + return 1; + } +} diff --git a/arch/arm/mach-tegra/board-p1852-pinmux.c b/arch/arm/mach-tegra/board-p1852-pinmux.c index 21f310b0ef16..bb28e278dc89 100644 --- a/arch/arm/mach-tegra/board-p1852-pinmux.c +++ b/arch/arm/mach-tegra/board-p1852-pinmux.c @@ -119,13 +119,8 @@ static __initdata struct tegra_drive_pingroup_config p1852_drive_pinmux[] = { 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), @@ -184,6 +179,9 @@ static __initdata struct tegra_drive_pingroup_config p1852_drive_pinmux[] = { } +static __initdata struct tegra_pingroup_config p1852_pinmux_i2s4_master[] = { + DEFAULT_PINMUX(SDMMC4_CLK, NAND, PULL_UP, NORMAL, INPUT), +}; static __initdata struct tegra_pingroup_config p1852_pinmux_common[] = { /* SDMMC1 pinmux */ @@ -291,10 +289,10 @@ static __initdata struct tegra_pingroup_config p1852_pinmux_common[] = { DEFAULT_PINMUX(DAP3_SCLK, I2S2, NORMAL, NORMAL, INPUT), /* DAP3 */ - LVPAD_PINMUX(SDMMC4_DAT4, I2S4, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), - LVPAD_PINMUX(SDMMC4_DAT5, I2S4, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), - LVPAD_PINMUX(SDMMC4_DAT6, I2S4, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), - LVPAD_PINMUX(SDMMC4_DAT7, I2S4, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), + DEFAULT_PINMUX(SDMMC4_DAT4, I2S4, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC4_DAT5, I2S4, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC4_DAT6, I2S4, NORMAL, NORMAL, INPUT), + DEFAULT_PINMUX(SDMMC4_DAT7, I2S4, NORMAL, NORMAL, INPUT), /* NOR pinmux */ DEFAULT_PINMUX(GMI_AD0, GMI, NORMAL, NORMAL, INPUT), @@ -427,7 +425,7 @@ static __initdata struct tegra_pingroup_config p1852_pinmux_common[] = { DEFAULT_PINMUX(GPIO_PV2, RSVD1, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(GPIO_PV3, RSVD1, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(SDMMC3_DAT7, SDMMC3, NORMAL, NORMAL, INPUT), - LVPAD_PINMUX(SDMMC4_CLK, NAND, NORMAL, NORMAL, INPUT, DISABLE, DISABLE), + DEFAULT_PINMUX(SDMMC4_CLK, NAND, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(SDMMC3_CMD, SDMMC3, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(SDMMC3_DAT3, RSVD0, NORMAL, NORMAL, INPUT), DEFAULT_PINMUX(VI_D1, RSVD1, NORMAL, NORMAL, INPUT), @@ -445,6 +443,12 @@ int __init p1852_pinmux_init(void) return 0; } +int p1852_pinmux_set_i2s4_master(void) +{ + tegra_pinmux_config_table(p1852_pinmux_i2s4_master, + ARRAY_SIZE(p1852_pinmux_i2s4_master)); + return 0; +} #define GPIO_INIT_PIN_MODE(_gpio, _is_input, _value) \ { \ .gpio_nr = _gpio, \ diff --git a/arch/arm/mach-tegra/board-p1852.c b/arch/arm/mach-tegra/board-p1852.c index ce7768e19594..4ff3eaf47899 100644 --- a/arch/arm/mach-tegra/board-p1852.c +++ b/arch/arm/mach-tegra/board-p1852.c @@ -1,6 +1,4 @@ /* - * arch/arm/mach-tegra/board-p1852.c - * * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it @@ -15,6 +13,8 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * + * arch/arm/mach-tegra/board-p1852.c + * */ #include <linux/kernel.h> @@ -43,6 +43,7 @@ #include <mach/irqs.h> #include <mach/pinmux.h> #include <mach/iomap.h> +#include <mach/io_dpd.h> #include <mach/io.h> #include <mach/pci.h> #include <mach/audio.h> @@ -96,7 +97,6 @@ static __initdata struct tegra_clk_init_table p1852_clk_init_table[] = { { "vi", "pll_p", 470000000, false}, { "vi_sensor", "pll_p", 150000000, false}, { "vde", "pll_c", 484000000, true}, - { "host1x", "pll_c", 242000000, true}, { "mpe", "pll_c", 484000000, true}, { "se", "pll_m", 625000000, true}, { "i2c1", "pll_p", 3200000, true}, @@ -198,7 +198,6 @@ static void __init p1852_uart_init(void) platform_add_devices(p1852_uart_devices, ARRAY_SIZE(p1852_uart_devices)); } - #if defined(CONFIG_TEGRA_P1852_TDM) static struct tegra_p1852_platform_data p1852_audio_tdm_pdata = { .codec_info[0] = { @@ -208,11 +207,15 @@ static struct tegra_p1852_platform_data p1852_audio_tdm_pdata = { .name = "tegra-i2s-1", .pcm_driver = "tegra-tdm-pcm-audio", .i2s_format = format_tdm, + /* Defines whether the Codec Chip is Master or Slave */ .master = 1, - .num_slots = 4, + /* Defines the number of TDM slots */ + .num_slots = 8, + /* Defines the width of each slot */ .slot_width = 32, - .tx_mask = 0x0f, - .rx_mask = 0x0f, + /* Defines which slots are enabled */ + .tx_mask = 0xff, + .rx_mask = 0xff, }, .codec_info[1] = { .codec_dai_name = "dit-hifi", @@ -237,6 +240,7 @@ static struct tegra_p1852_platform_data p1852_audio_i2s_pdata = { .name = "tegra-i2s-1", .pcm_driver = "tegra-pcm-audio", .i2s_format = format_i2s, + /* Defines whether the Audio codec chip is master or slave */ .master = 1, }, .codec_info[1] = { @@ -246,6 +250,7 @@ static struct tegra_p1852_platform_data p1852_audio_i2s_pdata = { .name = "tegra-i2s-2", .pcm_driver = "tegra-pcm-audio", .i2s_format = format_i2s, + /* Defines whether the Audio codec chip is master or slave */ .master = 0, }, }; @@ -273,6 +278,8 @@ static struct platform_device tegra_snd_p1852 = { static void p1852_i2s_audio_init(void) { + struct tegra_p1852_platform_data *pdata; + platform_device_register(&tegra_pcm_device); platform_device_register(&tegra_tdm_pcm_device); platform_device_register(&generic_codec_1); @@ -281,6 +288,11 @@ static void p1852_i2s_audio_init(void) platform_device_register(&tegra_i2s_device4); platform_device_register(&tegra_ahub_device); platform_device_register(&tegra_snd_p1852); + + /* Change pinmux of I2S4 for master mode */ + pdata = tegra_snd_p1852.dev.platform_data; + if (!pdata->codec_info[1].master) + p1852_pinmux_set_i2s4_master(); } @@ -445,9 +457,6 @@ static __initdata struct tegra_clk_init_table spi_clk_init_table[] = { static int __init p1852_touch_init(void) { - tegra_gpio_enable(TOUCH_GPIO_IRQ_ATMEL_T9); - tegra_gpio_enable(TOUCH_GPIO_RST_ATMEL_T9); - gpio_request(TOUCH_GPIO_IRQ_ATMEL_T9, "atmel-irq"); gpio_direction_input(TOUCH_GPIO_IRQ_ATMEL_T9); @@ -467,6 +476,32 @@ static int __init p1852_touch_init(void) #endif // CONFIG_TOUCHSCREEN_ATMEL_MXT +#if defined(CONFIG_USB_G_ANDROID) +static struct tegra_usb_platform_data tegra_udc_pdata = { + .port_otg = false, + .has_hostpc = true, + .phy_intf = TEGRA_USB_PHY_INTF_UTMI, + .op_mode = TEGRA_USB_OPMODE_DEVICE, + .u_data.dev = { + .vbus_pmu_irq = 0, + .vbus_gpio = -1, + .charging_supported = false, + .remote_wakeup_supported = false, + }, + .u_cfg.utmi = { + .hssync_start_delay = 0, + .idle_wait_delay = 17, + .elastic_limit = 16, + .term_range_adj = 6, + .xcvr_setup = 63, + .xcvr_setup_offset = 6, + .xcvr_use_fuses = 1, + .xcvr_lsfslew = 2, + .xcvr_lsrslew = 2, + .xcvr_use_lsb = 1, + }, +}; +#else static struct tegra_usb_platform_data tegra_ehci1_utmi_pdata = { .port_otg = false, .has_hostpc = true, @@ -492,6 +527,7 @@ static struct tegra_usb_platform_data tegra_ehci1_utmi_pdata = { .xcvr_use_lsb = 1, }, }; +#endif static struct tegra_usb_platform_data tegra_ehci2_utmi_pdata = { .port_otg = false, @@ -547,9 +583,16 @@ static struct tegra_usb_platform_data tegra_ehci3_utmi_pdata = { static void p1852_usb_init(void) { + /* Need to parse sku info to decide host/device mode */ + + /* G_ANDROID require device mode */ +#if defined(CONFIG_USB_G_ANDROID) + tegra_udc_device.dev.platform_data = &tegra_udc_pdata; + platform_device_register(&tegra_udc_device); +#else tegra_ehci1_device.dev.platform_data = &tegra_ehci1_utmi_pdata; platform_device_register(&tegra_ehci1_device); - +#endif tegra_ehci2_device.dev.platform_data = &tegra_ehci2_utmi_pdata; platform_device_register(&tegra_ehci2_device); @@ -563,6 +606,10 @@ static struct tegra_nor_platform_data p1852_nor_data = { .width = 2, }, .chip_parms = { + .MuxMode = NorMuxMode_ADNonMux, + .ReadMode = NorReadMode_Page, + .PageLength = NorPageLength_8Word, + .ReadyActive = NorReadyActive_WithData, /* FIXME: Need to use characterized value */ .timing_default = { .timing0 = 0x30300263, @@ -592,6 +639,7 @@ static void __init tegra_p1852_init(void) p1852_gpio_init(); p1852_uart_init(); p1852_usb_init(); + tegra_io_dpd_init(); p1852_sdhci_init(); p1852_spi_init(); platform_add_devices(p1852_devices, ARRAY_SIZE(p1852_devices)); @@ -607,12 +655,29 @@ static void __init tegra_p1852_init(void) static void __init tegra_p1852_reserve(void) { #if defined(CONFIG_NVMAP_CONVERT_CARVEOUT_TO_IOVMM) - tegra_reserve(0, SZ_8M, 0); + tegra_reserve(0, SZ_8M, SZ_8M); #else - tegra_reserve(SZ_128M, SZ_8M, 0); + tegra_reserve(SZ_128M, SZ_8M, SZ_8M); #endif } +int p1852_get_skuid() +{ + switch (system_rev) { + case TEGRA_P1852_SKU2_A00: + case TEGRA_P1852_SKU2_B00: + return 2; + case TEGRA_P1852_SKU5_A00: + case TEGRA_P1852_SKU5_B00: + return 5; + case TEGRA_P1852_SKU8_A00: + case TEGRA_P1852_SKU8_B00: + return 8; + default: + return -1; + } +} + MACHINE_START(P1852, "p1852") .boot_params = 0x80000100, .init_irq = tegra_init_irq, diff --git a/arch/arm/mach-tegra/board-p1852.h b/arch/arm/mach-tegra/board-p1852.h index 1ac0968f9518..7de6a6b358e6 100644 --- a/arch/arm/mach-tegra/board-p1852.h +++ b/arch/arm/mach-tegra/board-p1852.h @@ -90,16 +90,28 @@ #define AC_PRESENT_INT (TPS6591X_INT_GPIO4 + TPS6591X_IRQ_BASE) +/* List of P1852 skus - replicated from core/include/nvmachtypes.h */ +#define TEGRA_P1852_SKU2_A00 0x020000UL +#define TEGRA_P1852_SKU2_B00 0x020200UL +#define TEGRA_P1852_SKU5_A00 0x050000UL +#define TEGRA_P1852_SKU5_B00 0x050200UL +#define TEGRA_P1852_SKU8_A00 0x080000UL +#define TEGRA_P1852_SKU8_B00 0x080200UL + int p1852_sdhci_init(void); int p1852_pinmux_init(void); +int p1852_pinmux_set_i2s4_master(void); int p1852_panel_init(void); int p1852_gpio_init(void); int p1852_pins_state_init(void); +int p1852_get_skuid(void); + #ifdef CONFIG_TOUCHSCREEN_ATMEL_MXT #define TOUCH_GPIO_IRQ_ATMEL_T9 TEGRA_GPIO_PEE1 #define TOUCH_GPIO_RST_ATMEL_T9 TEGRA_GPIO_PW2 #define TOUCH_BUS_ATMEL_T9 0 #endif + #endif diff --git a/arch/arm/mach-tegra/board-touch-kai-synaptics-spi.c b/arch/arm/mach-tegra/board-touch-kai-synaptics-spi.c index 989cf3339be4..718047acf896 100644 --- a/arch/arm/mach-tegra/board-touch-kai-synaptics-spi.c +++ b/arch/arm/mach-tegra/board-touch-kai-synaptics-spi.c @@ -38,11 +38,9 @@ static struct rmi_f19_button_map synaptics_button_map = { static int synaptics_touchpad_gpio_setup(void *gpio_data, bool configure) { if (configure) { - tegra_gpio_enable(SYNAPTICS_ATTN_GPIO); gpio_request(SYNAPTICS_ATTN_GPIO, "synaptics-irq"); gpio_direction_input(SYNAPTICS_ATTN_GPIO); - tegra_gpio_enable(SYNAPTICS_RESET_GPIO); gpio_request(SYNAPTICS_RESET_GPIO, "synaptics-reset"); gpio_direction_output(SYNAPTICS_RESET_GPIO, 0); @@ -52,8 +50,6 @@ static int synaptics_touchpad_gpio_setup(void *gpio_data, bool configure) } else { gpio_free(SYNAPTICS_ATTN_GPIO); gpio_free(SYNAPTICS_RESET_GPIO); - tegra_gpio_disable(SYNAPTICS_ATTN_GPIO); - tegra_gpio_disable(SYNAPTICS_RESET_GPIO); } return 0; } diff --git a/arch/arm/mach-tegra/board-touch-raydium_spi.c b/arch/arm/mach-tegra/board-touch-raydium_spi.c index eb13fc4a44ab..b4ed0310054c 100644 --- a/arch/arm/mach-tegra/board-touch-raydium_spi.c +++ b/arch/arm/mach-tegra/board-touch-raydium_spi.c @@ -201,11 +201,9 @@ struct spi_board_info rm31080a_spi_board[1] = { int __init touch_init_raydium(int irq_gpio, int reset_gpio, int platform) { int err = 0; - tegra_gpio_enable(irq_gpio); gpio_request(irq_gpio, "raydium-irq"); gpio_direction_input(irq_gpio); - tegra_gpio_enable(reset_gpio); gpio_request(reset_gpio, "raydium-reset"); gpio_direction_output(reset_gpio, 0); diff --git a/arch/arm/mach-tegra/board-ventana-pinmux.c b/arch/arm/mach-tegra/board-ventana-pinmux.c index eb371384ed4c..43b4b75878a2 100644 --- a/arch/arm/mach-tegra/board-ventana-pinmux.c +++ b/arch/arm/mach-tegra/board-ventana-pinmux.c @@ -181,6 +181,7 @@ static struct tegra_gpio_table gpio_table[] = { { .gpio = TEGRA_GPIO_HP_DET, .enable = true }, { .gpio = TEGRA_GPIO_INT_MIC_EN, .enable = true }, { .gpio = TEGRA_GPIO_EXT_MIC_EN, .enable = true }, + { .gpio = TEGRA_GPIO_USB1_VBUS, .enable = false }, }; int __init ventana_pinmux_init(void) diff --git a/arch/arm/mach-tegra/board-ventana.c b/arch/arm/mach-tegra/board-ventana.c index c8c9ac49745f..500118114b39 100644 --- a/arch/arm/mach-tegra/board-ventana.c +++ b/arch/arm/mach-tegra/board-ventana.c @@ -2,6 +2,7 @@ * arch/arm/mach-tegra/board-ventana.c * * Copyright (c) 2010-2011 NVIDIA Corporation. + * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -49,7 +50,7 @@ #include <mach/iomap.h> #include <mach/io.h> #include <mach/i2s.h> -#include <mach/tegra_wm8903_pdata.h> +#include <mach/tegra_asoc_pdata.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -350,12 +351,25 @@ static struct platform_device tegra_camera = { .id = -1, }; -static struct tegra_wm8903_platform_data ventana_audio_pdata = { +static struct tegra_asoc_platform_data ventana_audio_pdata = { .gpio_spkr_en = TEGRA_GPIO_SPKR_EN, .gpio_hp_det = TEGRA_GPIO_HP_DET, .gpio_hp_mute = -1, .gpio_int_mic_en = TEGRA_GPIO_INT_MIC_EN, .gpio_ext_mic_en = TEGRA_GPIO_EXT_MIC_EN, + .i2s_param[HIFI_CODEC] = { + .audio_port_id = 0, + .is_i2s_master = 1, + .i2s_mode = TEGRA_DAIFMT_I2S, + }, + .i2s_param[BASEBAND] = { + .audio_port_id = -1, + }, + .i2s_param[BT_SCO] = { + .audio_port_id = 3, + .is_i2s_master = 1, + .i2s_mode = TEGRA_DAIFMT_DSP_A, + }, }; static struct platform_device ventana_audio_device = { @@ -410,9 +424,6 @@ static struct i2c_board_info __initdata i2c_info[] = { static int __init ventana_touch_init_atmel(void) { - tegra_gpio_enable(TEGRA_GPIO_PV6); - tegra_gpio_enable(TEGRA_GPIO_PQ7); - gpio_request(TEGRA_GPIO_PV6, "atmel-irq"); gpio_direction_input(TEGRA_GPIO_PV6); @@ -441,9 +452,6 @@ static struct i2c_board_info __initdata ventana_i2c_bus1_touch_info[] = { static int __init ventana_touch_init_panjit(void) { - tegra_gpio_enable(TEGRA_GPIO_PV6); - - tegra_gpio_enable(TEGRA_GPIO_PQ7); i2c_register_board_info(0, ventana_i2c_bus1_touch_info, 1); return 0; @@ -457,7 +465,6 @@ static int __init ventana_gps_init(void) clk_enable(clk32); } - tegra_gpio_enable(TEGRA_GPIO_PZ3); return 0; } @@ -495,7 +502,7 @@ static struct tegra_usb_platform_data tegra_ehci1_utmi_pdata = { .vbus_reg = NULL, .hot_plug = true, .remote_wakeup_supported = false, - .power_off_on_suspend = true, + .power_off_on_suspend = false, }, .u_cfg.utmi = { .hssync_start_delay = 9, @@ -514,9 +521,6 @@ static void ulpi_link_platform_open(void) gpio_request(reset_gpio, "ulpi_phy_reset"); gpio_direction_output(reset_gpio, 0); - tegra_gpio_enable(reset_gpio); - - gpio_direction_output(reset_gpio, 0); msleep(5); gpio_direction_output(reset_gpio, 1); } @@ -558,7 +562,7 @@ static struct tegra_usb_platform_data tegra_ehci3_utmi_pdata = { .vbus_reg = NULL, .hot_plug = true, .remote_wakeup_supported = false, - .power_off_on_suspend = true, + .power_off_on_suspend = false, }, .u_cfg.utmi = { .hssync_start_delay = 9, @@ -648,12 +652,18 @@ void __init tegra_ventana_reserve(void) tegra_ram_console_debug_reserve(SZ_1M); } +static const char *ventana_dt_board_compat[] = { + "nvidia,ventana", + NULL +}; + MACHINE_START(VENTANA, "ventana") .boot_params = 0x00000100, .map_io = tegra_map_common_io, - .reserve = tegra_ventana_reserve, .init_early = tegra_init_early, - .init_irq = tegra_init_irq, + .init_irq = tegra_init_irq, + .reserve = tegra_ventana_reserve, .timer = &tegra_timer, - .init_machine = tegra_ventana_init, + .init_machine = tegra_ventana_init, + .dt_compat = ventana_dt_board_compat, MACHINE_END diff --git a/arch/arm/mach-tegra/board-ventana.h b/arch/arm/mach-tegra/board-ventana.h index b8d8040d187b..8ebf4c9b3c4a 100644 --- a/arch/arm/mach-tegra/board-ventana.h +++ b/arch/arm/mach-tegra/board-ventana.h @@ -87,6 +87,9 @@ int ventana_cam_fixed_voltage_regulator_init(void); #define TEGRA_GPIO_INT_MIC_EN TEGRA_GPIO_PX0 #define TEGRA_GPIO_EXT_MIC_EN TEGRA_GPIO_PX1 +/* Usb1 vbus GPIO */ +#define TEGRA_GPIO_USB1_VBUS TEGRA_GPIO_PD0 + /* AC detect GPIO */ #define AC_PRESENT_GPIO TEGRA_GPIO_PV3 diff --git a/arch/arm/mach-tegra/board-whistler.c b/arch/arm/mach-tegra/board-whistler.c index 06e704e47870..492367076170 100644 --- a/arch/arm/mach-tegra/board-whistler.c +++ b/arch/arm/mach-tegra/board-whistler.c @@ -352,12 +352,32 @@ static struct platform_device tegra_camera = { }; static struct tegra_asoc_platform_data whistler_audio_pdata = { - .gpio_spkr_en = -1, - .gpio_hp_det = TEGRA_GPIO_HP_DET, - .gpio_hp_mute = -1, - .gpio_int_mic_en = -1, - .gpio_ext_mic_en = -1, - .debounce_time_hp = 200, + .gpio_spkr_en = -1, + .gpio_hp_det = TEGRA_GPIO_HP_DET, + .gpio_hp_mute = -1, + .gpio_int_mic_en = -1, + .gpio_ext_mic_en = -1, + .debounce_time_hp = 200, + .i2s_param[HIFI_CODEC] = { + .audio_port_id = 0, + .is_i2s_master = 1, + .i2s_mode = TEGRA_DAIFMT_I2S, + .sample_size = 16, + }, + .i2s_param[BASEBAND] = { + .audio_port_id = 2, + .is_i2s_master = 1, + .i2s_mode = TEGRA_DAIFMT_DSP_A, + .sample_size = 16, + .rate = 8000, + .channels = 1, + }, + .i2s_param[BT_SCO] = { + .sample_size = 16, + .audio_port_id = 3, + .is_i2s_master = 1, + .i2s_mode = TEGRA_DAIFMT_DSP_A, + }, }; static struct platform_device whistler_audio_aic326x_device = { @@ -421,6 +441,7 @@ static int __init whistler_touch_init(void) static struct tegra_usb_platform_data tegra_udc_pdata = { .port_otg = true, .has_hostpc = false, + .builtin_host_disabled = true, .phy_intf = TEGRA_USB_PHY_INTF_UTMI, .op_mode = TEGRA_USB_OPMODE_DEVICE, .u_data.dev = { @@ -445,6 +466,7 @@ static struct tegra_usb_platform_data tegra_udc_pdata = { static struct tegra_usb_platform_data tegra_ehci1_utmi_pdata = { .port_otg = true, .has_hostpc = false, + .builtin_host_disabled = true, .phy_intf = TEGRA_USB_PHY_INTF_UTMI, .op_mode = TEGRA_USB_OPMODE_HOST, .u_data.host = { @@ -517,12 +539,18 @@ void __init tegra_whistler_reserve(void) tegra_ram_console_debug_reserve(SZ_1M); } +static const char *whistler_dt_board_compat[] = { + "nvidia,whistler", + NULL +}; + MACHINE_START(WHISTLER, "whistler") .boot_params = 0x00000100, .map_io = tegra_map_common_io, - .reserve = tegra_whistler_reserve, .init_early = tegra_init_early, .init_irq = tegra_init_irq, + .reserve = tegra_whistler_reserve, .timer = &tegra_timer, .init_machine = tegra_whistler_init, + .dt_compat = whistler_dt_board_compat, MACHINE_END diff --git a/arch/arm/mach-tegra/board.h b/arch/arm/mach-tegra/board.h index 7c081fad642a..85d02d501b63 100644 --- a/arch/arm/mach-tegra/board.h +++ b/arch/arm/mach-tegra/board.h @@ -72,9 +72,9 @@ #define COMMCHIP_UNKNOWN 0 #define COMMCHIP_NOCHIP 1 #define COMMCHIP_BROADCOM_BCM4329 2 -#define COMMCHIP BROADCOM_BCM4330 3 +#define COMMCHIP_BROADCOM_BCM4330 3 #define COMMCHIP_MARVELL_SD8797 4 - +#define COMMCHIP_TI_WL18XX 5 struct memory_accessor; diff --git a/arch/arm/mach-tegra/clock.h b/arch/arm/mach-tegra/clock.h index d2e510818042..754a3fbaef20 100644 --- a/arch/arm/mach-tegra/clock.h +++ b/arch/arm/mach-tegra/clock.h @@ -69,6 +69,7 @@ #include <linux/list.h> #include <linux/mutex.h> #include <linux/spinlock.h> +#include <trace/events/power.h> #include <asm/cputime.h> #include <mach/clk.h> @@ -286,6 +287,7 @@ static inline bool clk_cansleep(struct clk *c) static inline void clk_lock_save(struct clk *c, unsigned long *flags) { + trace_clock_lock(c->name, c->rate, smp_processor_id()); if (clk_cansleep(c)) { *flags = 0; mutex_lock(&c->mutex); @@ -300,6 +302,7 @@ static inline void clk_unlock_restore(struct clk *c, unsigned long *flags) mutex_unlock(&c->mutex); else spin_unlock_irqrestore(&c->spinlock, *flags); + trace_clock_unlock(c->name, c->rate, smp_processor_id()); } static inline void clk_lock_init(struct clk *c) diff --git a/arch/arm/mach-tegra/clocks_stats.c b/arch/arm/mach-tegra/clocks_stats.c new file mode 100644 index 000000000000..1018a24ddbf9 --- /dev/null +++ b/arch/arm/mach-tegra/clocks_stats.c @@ -0,0 +1,259 @@ +/* + * arch/arm/mach-tegra/clocks_stats.c + * + * Copyright (C) 2012, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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/spinlock.h> +#include <linux/clk.h> +#include <linux/debugfs.h> +#include <linux/seq_file.h> +#include <linux/list.h> + +#include "clock.h" + +#define STATS_TABLE_MAX_SIZE 64 + +/* + * Generic stats tracking structures and functions + */ +struct stats_entry { + int rate; + cputime64_t time_at_rate; +}; + +struct stats_table { + struct stats_entry *entry; + int last_rate; + cputime64_t last_updated; + spinlock_t spinlock; + unsigned int num_entries; +}; + +struct clock_data { + struct dentry *dentry; + struct list_head node; + struct stats_table table; + struct notifier_block rate_change_nb; +}; + +static LIST_HEAD(clock_stats); +static struct dentry *clock_debugfs_root; + +/* + * Initialize a stats table to zeros + */ +static void init_stats_table(struct stats_table *table) +{ + table->last_rate = -1; + spin_lock_init(&(table->spinlock)); + table->num_entries = 0; + table->last_updated = get_jiffies_64(); +} + +/* + * Populate table with possible rates + */ +static int populate_rates(struct stats_table *table, struct clk *c) +{ + unsigned long rate = 0, rounded_rate = 0; + unsigned int num_rates = 0; + int i = 0; + + /* Calculate number of rates */ + while (rate <= c->max_rate) { + rounded_rate = c->ops->round_rate(c, rate); + if (IS_ERR_VALUE(rounded_rate) || (rounded_rate <= rate)) + break; + + num_rates++; + rate = rounded_rate + 2000; /* 2kHz resolution */ + } + + /* Allocate space for a table of that size */ + table->entry = kmalloc(num_rates * sizeof(struct stats_entry), + GFP_KERNEL); + if (!table->entry) + return -ENOMEM; + rate = 0; + i = 0; + + /* Populate table with possible rates */ + while (rate <= c->max_rate) { + rounded_rate = c->ops->round_rate(c, rate); + if (IS_ERR_VALUE(rounded_rate) || (rounded_rate <= rate)) + break; + + table->entry[i].rate = rounded_rate; + table->entry[i].time_at_rate = 0; + i++; + rate = rounded_rate + 2000; /* 2kHz resolution */ + } + + table->num_entries = num_rates; + + return 0; +} + +/* + * Function is called whenever a rate changes. The time spent + * in the 'old rate' is finalized and the new rate is tracked. + * Entries are tracked in increasing order of rate + */ +static void update_stats_table(struct stats_table *table, int new_rate) +{ + int i = 0; + unsigned long flags; + u64 cur_jiffies = get_jiffies_64(); + + spin_lock_irqsave(&table->spinlock, flags); + + if (new_rate == -1) + new_rate = table->last_rate; + + /* update time spent on old clock */ + for (i = 0; i < table->num_entries; i++) { + if (table->entry[i].rate == table->last_rate) { + table->entry[i].time_at_rate = cputime64_add( + table->entry[i].time_at_rate, + cputime64_sub(cur_jiffies, + table->last_updated)); + } + } + + table->last_updated = cur_jiffies; + table->last_rate = new_rate; + + spin_unlock_irqrestore(&table->spinlock, flags); + +} + +/* + * Print stats table to seq_file + */ +static void dump_stats_table(struct seq_file *s, struct stats_table *table) +{ + int i = 0; + update_stats_table(table, -1); + + seq_printf(s, "%-10s %-10s\n", "rate kHz", "time"); + for (i = 0; i < table->num_entries; i++) { + seq_printf(s, "%-10lu %-10llu\n", + (long unsigned int)(table->entry[i].rate/1000), + cputime64_to_clock_t(table->entry[i].time_at_rate)); + } +} + +static int stats_show(struct seq_file *s, void *data) +{ + struct clock_data *d = (struct clock_data *)(s->private); + dump_stats_table(s, &d->table); + return 0; +} + +static int stats_open(struct inode *inode, struct file *file) +{ + return single_open(file, stats_show, inode->i_private); +} + +static const struct file_operations clock_stats_fops = { + .open = stats_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +/* + * Clock rate change notification callback + */ +static int rate_notify_cb(struct notifier_block *nb, unsigned long rate, + void *v) +{ + struct clock_data *c = + container_of(nb, struct clock_data, rate_change_nb); + update_stats_table(&c->table, rate); + return NOTIFY_OK; +} + +/* + * Call once for each clock to track + */ +static int track_clock(char *clk_name) +{ + int ret = 0; + struct clock_data *d; + struct clk *c = clk_get(NULL, clk_name); + if (IS_ERR(c)) + return PTR_ERR(c); + + d = kmalloc(sizeof(struct clock_data), GFP_KERNEL); + if (d == NULL) + goto err_clk; + + d->rate_change_nb.notifier_call = rate_notify_cb; + + if (!clock_debugfs_root) + goto err_clk; + + d->dentry = debugfs_create_file( + clk_name, S_IRUGO, clock_debugfs_root, d, &clock_stats_fops); + if (!d->dentry) + goto err_clk; + + init_stats_table(&d->table); + ret = populate_rates(&d->table, c); + if (ret) + goto err_out; + + ret = tegra_register_clk_rate_notifier(c, &d->rate_change_nb); + if (ret) + goto err_out; + + list_add(&d->node, &clock_stats); + + clk_put(c); + return 0; + +err_out: + kfree(d->table.entry); + debugfs_remove(d->dentry); +err_clk: + kfree(d); + clk_put(c); + return -ENOMEM; +} + +static int __init tegra_clocks_debug_init(void) +{ + int ret = 0; + + clock_debugfs_root = debugfs_create_dir("clock_stats", NULL); + if (!clock_debugfs_root) + return -ENOMEM; + + /* Start tracking individual clocks */ + ret = track_clock("sbus"); + if (0 != ret) + goto err_out; + + ret = track_clock("cbus"); + if (0 != ret) + goto err_out; + + return 0; + +err_out: + return ret; + +} +late_initcall(tegra_clocks_debug_init); diff --git a/arch/arm/mach-tegra/common-t3.c b/arch/arm/mach-tegra/common-t3.c index 2da656f97c38..76188723b46f 100644 --- a/arch/arm/mach-tegra/common-t3.c +++ b/arch/arm/mach-tegra/common-t3.c @@ -3,7 +3,7 @@ * * Tegra 3 SoC-specific initialization (memory controller, etc.) * - * Copyright (c) 2010-2012, NVIDIA Corporation. + * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -44,6 +44,8 @@ ((MC_EMEM_ARB_TIMING_W2R - MC_EMEM_ARB_CFG) / 4 + 1) #define MC_TIMING_REG_NUM2 \ ((MC_EMEM_ARB_MISC1 - MC_EMEM_ARB_DA_TURNS) / 4 + 1) +#define MC_TIMING_REG_NUM3 \ + ((MC_LATENCY_ALLOWANCE_VI_2 - MC_LATENCY_ALLOWANCE_AFI) / 4 + 1) struct mc_client { const char *name; @@ -59,7 +61,8 @@ static void __iomem *mc = IO_ADDRESS(TEGRA_MC_BASE); #ifdef CONFIG_PM_SLEEP -static u32 mc_boot_timing[MC_TIMING_REG_NUM1 + MC_TIMING_REG_NUM2 + 4]; +static u32 mc_boot_timing[MC_TIMING_REG_NUM1 + MC_TIMING_REG_NUM2 + + MC_TIMING_REG_NUM3 + 4]; static void tegra_mc_timing_save(void) { @@ -76,6 +79,10 @@ static void tegra_mc_timing_save(void) *ctx++ = readl((u32)mc + MC_EMEM_ARB_OVERRIDE); *ctx++ = readl((u32)mc + MC_RESERVED_RSV); + for (off = MC_LATENCY_ALLOWANCE_AFI; off <= MC_LATENCY_ALLOWANCE_VI_2; + off += 4) + *ctx++ = readl((u32)mc + off); + *ctx++ = readl((u32)mc + MC_INT_MASK); } @@ -94,6 +101,10 @@ void tegra_mc_timing_restore(void) __raw_writel(*ctx++, (u32)mc + MC_EMEM_ARB_OVERRIDE); __raw_writel(*ctx++, (u32)mc + MC_RESERVED_RSV); + for (off = MC_LATENCY_ALLOWANCE_AFI; off <= MC_LATENCY_ALLOWANCE_VI_2; + off += 4) + __raw_writel(*ctx++, (u32)mc + off); + writel(*ctx++, (u32)mc + MC_INT_MASK); off = readl((u32)mc + MC_INT_MASK); diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c index 3a4f86079053..a34d37f2f250 100644 --- a/arch/arm/mach-tegra/common.c +++ b/arch/arm/mach-tegra/common.c @@ -2,7 +2,7 @@ * arch/arm/mach-tegra/common.c * * Copyright (C) 2010 Google, Inc. - * Copyright (C) 2010-2012 NVIDIA Corporation + * Copyright (C) 2010-2012, NVIDIA Corporation. All rights reserved. * * Author: * Colin Cross <ccross@android.com> @@ -29,6 +29,7 @@ #include <linux/bitops.h> #include <linux/sched.h> #include <linux/cpufreq.h> +#include <linux/of.h> #include <asm/hardware/cache-l2x0.h> #include <asm/system.h> @@ -220,6 +221,7 @@ static __initdata struct tegra_clk_init_table common_clk_init_table[] = { { "sbc5.sclk", NULL, 40000000, false}, { "sbc6.sclk", NULL, 40000000, false}, { "wake.sclk", NULL, 40000000, true }, + { "cpu_mode.sclk", NULL, 80000000, false }, { "cbus", "pll_c", 416000000, false }, { "pll_c_out1", "pll_c", 208000000, false }, { "mselect", "pll_p", 102000000, true }, @@ -227,61 +229,11 @@ static __initdata struct tegra_clk_init_table common_clk_init_table[] = { { NULL, NULL, 0, 0}, }; -#ifdef CONFIG_CACHE_L2X0 #ifdef CONFIG_TRUSTED_FOUNDATIONS -static void tegra_cache_smc(bool enable, u32 arg) +static inline void tegra_l2x0_disable_tz(void) { - void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000; - bool need_affinity_switch; - bool can_switch_affinity; - bool l2x0_enabled; - cpumask_t local_cpu_mask; - cpumask_t saved_cpu_mask; - unsigned long flags; - long ret; - - /* - * ISSUE : Some registers of PL310 controler must be written - * from Secure context (and from CPU0)! - * - * When called form Normal we obtain an abort or do nothing. - * Instructions that must be called in Secure: - * - Write to Control register (L2X0_CTRL==0x100) - * - Write in Auxiliary controler (L2X0_AUX_CTRL==0x104) - * - Invalidate all entries (L2X0_INV_WAY==0x77C), - * mandatory at boot time. - * - Tag and Data RAM Latency Control Registers - * (0x108 & 0x10C) must be written in Secure. - */ - need_affinity_switch = (smp_processor_id() != 0); - can_switch_affinity = !irqs_disabled(); - - WARN_ON(need_affinity_switch && !can_switch_affinity); - if (need_affinity_switch && can_switch_affinity) { - cpu_set(0, local_cpu_mask); - sched_getaffinity(0, &saved_cpu_mask); - ret = sched_setaffinity(0, &local_cpu_mask); - WARN_ON(ret != 0); - } - - local_irq_save(flags); - l2x0_enabled = readl_relaxed(p + L2X0_CTRL) & 1; - if (enable && !l2x0_enabled) - tegra_generic_smc(0xFFFFF100, 0x00000001, arg); - else if (!enable && l2x0_enabled) - tegra_generic_smc(0xFFFFF100, 0x00000002, arg); - local_irq_restore(flags); - - if (need_affinity_switch && can_switch_affinity) { - ret = sched_setaffinity(0, &saved_cpu_mask); - WARN_ON(ret != 0); - } -} - -static void tegra_l2x0_disable(void) -{ - unsigned long flags; static u32 l2x0_way_mask; + BUG_ON(smp_processor_id() != 0); if (!l2x0_way_mask) { void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000; @@ -292,30 +244,75 @@ static void tegra_l2x0_disable(void) ways = (aux_ctrl & (1 << 16)) ? 16 : 8; l2x0_way_mask = (1 << ways) - 1; } - - local_irq_save(flags); - tegra_cache_smc(false, l2x0_way_mask); - local_irq_restore(flags); +#ifdef CONFIG_ARCH_TEGRA_2x_SOC + /* flush all ways on any disable */ + tegra_generic_smc_uncached(0xFFFFF100, 0x00000002, l2x0_way_mask); +#elif defined(CONFIG_ARCH_TEGRA_3x_SOC) + if (tegra_is_cpu_in_lp2(0) == false) { + /* + * If entering LP0/LP1, ask secureos to fully flush and + * disable the L2. + * + * If entering LP2, L2 disable is handled by the secureos + * as part of the tegra_sleep_cpu() SMC. This SMC indicates + * no more secureos tasks will be scheduled, allowing it + * to optimize out L2 flushes on its side. + */ + tegra_generic_smc_uncached(0xFFFFF100, + 0x00000002, l2x0_way_mask); + } +#endif } -#endif /* CONFIG_TRUSTED_FOUNDATIONS */ -void tegra_init_cache(bool init) +static inline void tegra_init_cache_tz(bool init) { void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000; u32 aux_ctrl; -#ifdef CONFIG_TRUSTED_FOUNDATIONS - /* issue the SMC to enable the L2 */ - aux_ctrl = readl_relaxed(p + L2X0_AUX_CTRL); - tegra_cache_smc(true, aux_ctrl); + BUG_ON(smp_processor_id() != 0); + + if (init) { + /* init L2 from secureos */ + tegra_generic_smc(0xFFFFF100, 0x00000001, 0x0); + + /* common init called for outer call hookup */ + aux_ctrl = readl_relaxed(p + L2X0_AUX_CTRL); + l2x0_init(p, aux_ctrl, 0xFFFFFFFF); + + /* use our outer_disable() routine */ + outer_cache.disable = tegra_l2x0_disable_tz; + } else { + /* reenable L2 in secureos */ + aux_ctrl = readl_relaxed(p + L2X0_AUX_CTRL); + tegra_generic_smc_uncached(0xFFFFF100, 0x00000004, aux_ctrl); + } +} +#endif /* CONFIG_TRUSTED_FOUNDATIONS */ - /* after init, reread aux_ctrl and register handlers */ - aux_ctrl = readl_relaxed(p + L2X0_AUX_CTRL); - l2x0_init(p, aux_ctrl, 0xFFFFFFFF); +#ifdef CONFIG_CACHE_L2X0 +/* + * We define our own outer_disable() to avoid L2 flush upon LP2 entry. + * Since the Tegra kernel will always be in single core mode when + * L2 is being disabled, we can omit the locking. Since we are not + * accessing the spinlock we also avoid the problem of the spinlock + * storage getting out of sync. + */ +static inline void tegra_l2x0_disable(void) +{ + void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000; + writel_relaxed(0, p + L2X0_CTRL); + dsb(); +} - /* override outer_disable() with our disable */ - outer_cache.disable = tegra_l2x0_disable; +void tegra_init_cache(bool init) +{ +#ifdef CONFIG_TRUSTED_FOUNDATIONS + /* enable/re-enable of L2 handled by secureos */ + return tegra_init_cache_tz(init); #else + void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000; + u32 aux_ctrl; + #if defined(CONFIG_ARCH_TEGRA_2x_SOC) writel_relaxed(0x331, p + L2X0_TAG_LATENCY_CTRL); writel_relaxed(0x441, p + L2X0_DATA_LATENCY_CTRL); @@ -353,6 +350,8 @@ void tegra_init_cache(bool init) aux_ctrl |= 0x7C000001; if (init) { l2x0_init(p, aux_ctrl, 0x8200c3fe); + /* use our outer_disable() routine to avoid flush */ + outer_cache.disable = tegra_l2x0_disable; } else { u32 tmp; @@ -365,7 +364,7 @@ void tegra_init_cache(bool init) l2x0_enable(); #endif } -#endif +#endif /* CONFIG_CACHE_L2X0 */ static void __init tegra_init_power(void) { @@ -676,11 +675,54 @@ __setup("audio_codec=", tegra_audio_codec_type); void tegra_get_board_info(struct board_info *bi) { - bi->board_id = (system_serial_high >> 16) & 0xFFFF; - bi->sku = (system_serial_high) & 0xFFFF; - bi->fab = (system_serial_low >> 24) & 0xFF; - bi->major_revision = (system_serial_low >> 16) & 0xFF; - bi->minor_revision = (system_serial_low >> 8) & 0xFF; +#ifdef CONFIG_OF + struct device_node *board_info; + u32 prop_val; + int err; + + board_info = of_find_node_by_path("/chosen/board_info"); + if (!IS_ERR_OR_NULL(board_info)) { + memset(bi, 0, sizeof(*bi)); + + err = of_property_read_u32(board_info, "id", &prop_val); + if (err) + pr_err("failed to read /chosen/board_info/id\n"); + else + bi->board_id = prop_val; + + err = of_property_read_u32(board_info, "sku", &prop_val); + if (err) + pr_err("failed to read /chosen/board_info/sku\n"); + else + bi->sku = prop_val; + + err = of_property_read_u32(board_info, "fab", &prop_val); + if (err) + pr_err("failed to read /chosen/board_info/fab\n"); + else + bi->fab = prop_val; + + err = of_property_read_u32(board_info, "major_revision", &prop_val); + if (err) + pr_err("failed to read /chosen/board_info/major_revision\n"); + else + bi->major_revision = prop_val; + + err = of_property_read_u32(board_info, "minor_revision", &prop_val); + if (err) + pr_err("failed to read /chosen/board_info/minor_revision\n"); + else + bi->minor_revision = prop_val; + } else { +#endif + bi->board_id = (system_serial_high >> 16) & 0xFFFF; + bi->sku = (system_serial_high) & 0xFFFF; + bi->fab = (system_serial_low >> 24) & 0xFF; + bi->major_revision = (system_serial_low >> 16) & 0xFF; + bi->minor_revision = (system_serial_low >> 8) & 0xFF; +#ifdef CONFIG_OF + } +#endif } static int __init tegra_pmu_board_info(char *info) diff --git a/arch/arm/mach-tegra/cpu-tegra.c b/arch/arm/mach-tegra/cpu-tegra.c index 9bed9270b412..ea5bbcf237c0 100644 --- a/arch/arm/mach-tegra/cpu-tegra.c +++ b/arch/arm/mach-tegra/cpu-tegra.c @@ -7,7 +7,7 @@ * Colin Cross <ccross@google.com> * Based on arch/arm/plat-omap/cpu-omap.c, (C) 2005 Nokia Corporation * - * Copyright (C) 2010-2012 NVIDIA Corporation + * Copyright (C) 2010-2012 NVIDIA CORPORATION. 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 @@ -242,12 +242,12 @@ int tegra_edp_update_thermal_zone(int temperature) /* Update cpu rate if cpufreq (at least on cpu0) is already started; alter cpu dvfs table for this thermal zone if necessary */ - tegra_cpu_dvfs_alter(edp_thermal_index, &edp_cpumask, true); + tegra_cpu_dvfs_alter(edp_thermal_index, &edp_cpumask, true, 0); if (target_cpu_speed[0]) { edp_update_limit(); tegra_cpu_set_speed_cap(NULL); } - tegra_cpu_dvfs_alter(edp_thermal_index, &edp_cpumask, false); + tegra_cpu_dvfs_alter(edp_thermal_index, &edp_cpumask, false, 0); mutex_unlock(&tegra_cpu_lock); return ret; @@ -321,31 +321,31 @@ static int tegra_cpu_edp_notify( case CPU_UP_PREPARE: mutex_lock(&tegra_cpu_lock); cpu_set(cpu, edp_cpumask); - tegra_cpu_dvfs_alter(edp_thermal_index, &edp_cpumask, true); edp_update_limit(); cpu_speed = tegra_getspeed(0); new_speed = edp_governor_speed(cpu_speed); if (new_speed < cpu_speed) { ret = tegra_cpu_set_speed_cap(NULL); - if (ret) { - cpu_clear(cpu, edp_cpumask); - edp_update_limit(); - } - - printk(KERN_DEBUG "tegra CPU:%sforce EDP limit %u kHz" + printk(KERN_DEBUG "cpu-tegra:%sforce EDP limit %u kHz" "\n", ret ? " failed to " : " ", new_speed); } - tegra_cpu_dvfs_alter(edp_thermal_index, &edp_cpumask, false); + if (!ret) + ret = tegra_cpu_dvfs_alter( + edp_thermal_index, &edp_cpumask, false, event); + if (ret) { + cpu_clear(cpu, edp_cpumask); + edp_update_limit(); + } mutex_unlock(&tegra_cpu_lock); break; case CPU_DEAD: mutex_lock(&tegra_cpu_lock); cpu_clear(cpu, edp_cpumask); - tegra_cpu_dvfs_alter(edp_thermal_index, &edp_cpumask, true); + tegra_cpu_dvfs_alter( + edp_thermal_index, &edp_cpumask, true, event); edp_update_limit(); tegra_cpu_set_speed_cap(NULL); - tegra_cpu_dvfs_alter(edp_thermal_index, &edp_cpumask, false); mutex_unlock(&tegra_cpu_lock); break; } diff --git a/arch/arm/mach-tegra/cpu-tegra3.c b/arch/arm/mach-tegra/cpu-tegra3.c index 051381297f6f..c0d21bfa816a 100644 --- a/arch/arm/mach-tegra/cpu-tegra3.c +++ b/arch/arm/mach-tegra/cpu-tegra3.c @@ -3,7 +3,7 @@ * * CPU auto-hotplug for Tegra3 CPUs * - * Copyright (c) 2011-2012, NVIDIA Corporation. + * Copyright (c) 2011-2012, NVIDIA Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -41,7 +41,7 @@ #define INITIAL_STATE TEGRA_HP_DISABLED #define UP2G0_DELAY_MS 70 #define UP2Gn_DELAY_MS 100 -#define DOWN_DELAY_MS 500 +#define DOWN_DELAY_MS 2000 static struct mutex *tegra3_cpu_lock; @@ -189,10 +189,38 @@ enum { }; #define NR_FSHIFT 2 -static unsigned int nr_run_thresholds[] = { + +static unsigned int rt_profile_sel; + +/* avg run threads * 4 (e.g., 9 = 2.25 threads) */ + +static unsigned int rt_profile_default[] = { /* 1, 2, 3, 4 - on-line cpus target */ - 5, 9, 10, UINT_MAX /* avg run threads * 4 (e.g., 9 = 2.25 threads) */ + 5, 9, 10, UINT_MAX +}; + +static unsigned int rt_profile_1[] = { +/* 1, 2, 3, 4 - on-line cpus target */ + 8, 9, 10, UINT_MAX +}; + +static unsigned int rt_profile_2[] = { +/* 1, 2, 3, 4 - on-line cpus target */ + 5, 13, 14, UINT_MAX +}; + +static unsigned int rt_profile_off[] = { /* disables runable thread */ + 0, 0, 0, UINT_MAX +}; + +static unsigned int *rt_profiles[] = { + rt_profile_default, + rt_profile_1, + rt_profile_2, + rt_profile_off }; + + static unsigned int nr_run_hysteresis = 2; /* 0.5 thread */ static unsigned int nr_run_last; @@ -216,8 +244,10 @@ static noinline int tegra_cpu_speed_balance(void) * TEGRA_CPU_SPEED_BIASED to keep CPU core composition unchanged * TEGRA_CPU_SPEED_SKEWED to remove CPU core off-line */ - for (nr_run = 1; nr_run < ARRAY_SIZE(nr_run_thresholds); nr_run++) { - unsigned int nr_threshold = nr_run_thresholds[nr_run - 1]; + + unsigned int *current_profile = rt_profiles[rt_profile_sel]; + for (nr_run = 1; nr_run < ARRAY_SIZE(rt_profile_default); nr_run++) { + unsigned int nr_threshold = current_profile[nr_run - 1]; if (nr_run_last <= nr_run) nr_threshold += nr_run_hysteresis; if (avg_nr_run <= (nr_threshold << (FSHIFT - NR_FSHIFT))) @@ -330,7 +360,7 @@ static int min_cpus_notify(struct notifier_block *nb, unsigned long n, void *p) { mutex_lock(tegra3_cpu_lock); - if ((n >= 1) && is_lp_cluster()) { + if ((n >= 1) && is_lp_cluster() && !no_lp) { /* make sure cpu rate is within g-mode range before switching */ unsigned int speed = max((unsigned long)tegra_getspeed(0), clk_get_min_rate(cpu_g_clk) / 1000); @@ -527,6 +557,25 @@ static const struct file_operations hp_stats_fops = { .release = single_release, }; +static int rt_bias_get(void *data, u64 *val) +{ + *val = rt_profile_sel; + return 0; +} +static int rt_bias_set(void *data, u64 val) +{ + if (val < ARRAY_SIZE(rt_profiles)) + rt_profile_sel = (u32)val; + + pr_debug("rt_profile_sel set to %d\nthresholds are now [%d, %d, %d]\n", + rt_profile_sel, + rt_profiles[rt_profile_sel][0], + rt_profiles[rt_profile_sel][1], + rt_profiles[rt_profile_sel][2]); + return 0; +} +DEFINE_SIMPLE_ATTRIBUTE(rt_bias_fops, rt_bias_get, rt_bias_set, "%llu\n"); + static int min_cpus_get(void *data, u64 *val) { *val = pm_qos_request(PM_QOS_MIN_ONLINE_CPUS); @@ -577,6 +626,10 @@ static int __init tegra_auto_hotplug_debug_init(void) "stats", S_IRUGO, hp_debugfs_root, NULL, &hp_stats_fops)) goto err_out; + if (!debugfs_create_file( + "core_bias", S_IRUGO, hp_debugfs_root, NULL, &rt_bias_fops)) + goto err_out; + return 0; err_out: diff --git a/arch/arm/mach-tegra/cpuidle.c b/arch/arm/mach-tegra/cpuidle.c index 47d5996e5961..25f63f6c4b2a 100644 --- a/arch/arm/mach-tegra/cpuidle.c +++ b/arch/arm/mach-tegra/cpuidle.c @@ -45,6 +45,7 @@ #include "cpuidle.h" #include "pm.h" #include "sleep.h" +#include "timer.h" int tegra_lp2_exit_latency; static int tegra_lp2_power_off_time; @@ -117,20 +118,25 @@ static int tegra_idle_enter_lp2(struct cpuidle_device *dev, return tegra_idle_enter_lp3(dev, state); } + trace_printk("LP2 entry at %lu us\n", + (unsigned long)readl(IO_ADDRESS(TEGRA_TMR1_BASE) + + TIMERUS_CNTR_1US)); + local_irq_disable(); enter = ktime_get(); tegra_cpu_idle_stats_lp2_ready(dev->cpu); tegra_idle_lp2(dev, state); + trace_printk("LP2 exit at %lu us\n", + (unsigned long)readl(IO_ADDRESS(TEGRA_TMR1_BASE) + + TIMERUS_CNTR_1US)); + exit = ktime_sub(ktime_get(), enter); us = ktime_to_us(exit); local_irq_enable(); - /* cpu clockevents may have been reset by powerdown */ - hrtimer_peek_ahead_timers(); - smp_rmb(); /* Update LP2 latency provided no fall back to LP3 */ diff --git a/arch/arm/mach-tegra/cpuquiet.c b/arch/arm/mach-tegra/cpuquiet.c index 26adce230920..87aebfe7badb 100644 --- a/arch/arm/mach-tegra/cpuquiet.c +++ b/arch/arm/mach-tegra/cpuquiet.c @@ -134,7 +134,7 @@ static void apply_core_config(void) static void tegra_cpuquiet_work_func(struct work_struct *work) { - bool update_cr_config = false; + int device_busy = -1; mutex_lock(tegra3_cpu_lock); @@ -148,7 +148,7 @@ static void tegra_cpuquiet_work_func(struct work_struct *work) /*catch-up with governor target speed */ tegra_cpu_set_speed_cap(NULL); /* process pending core requests*/ - update_cr_config = true; + device_busy = 0; } } break; @@ -159,6 +159,7 @@ static void tegra_cpuquiet_work_func(struct work_struct *work) if (!clk_set_parent(cpu_clk, cpu_lp_clk)) { /*catch-up with governor target speed*/ tegra_cpu_set_speed_cap(NULL); + device_busy = 1; } } break; @@ -169,8 +170,12 @@ static void tegra_cpuquiet_work_func(struct work_struct *work) mutex_unlock(tegra3_cpu_lock); - if (update_cr_config) + if (device_busy == 1) { + cpuquiet_device_busy(); + } else if (!device_busy) { apply_core_config(); + cpuquiet_device_free(); + } } static void min_max_constraints_workfunc(struct work_struct *work) @@ -183,6 +188,9 @@ static void min_max_constraints_workfunc(struct work_struct *work) int max_cpus = pm_qos_request(PM_QOS_MAX_ONLINE_CPUS) ? : 4; int min_cpus = pm_qos_request(PM_QOS_MIN_ONLINE_CPUS); + if (cpq_state == TEGRA_CPQ_DISABLED) + return; + if (is_lp_cluster()) return; @@ -212,15 +220,22 @@ static void min_max_constraints_workfunc(struct work_struct *work) static int min_cpus_notify(struct notifier_block *nb, unsigned long n, void *p) { + bool g_cluster = false; + + if (cpq_state == TEGRA_CPQ_DISABLED) + return NOTIFY_OK; + mutex_lock(tegra3_cpu_lock); if ((n >= 1) && is_lp_cluster()) { - /* make sure cpu rate is within g-mode range before switching */ + /* make sure cpu rate is within g-mode + * range before switching */ unsigned long speed = max((unsigned long)tegra_getspeed(0), clk_get_min_rate(cpu_g_clk) / 1000); tegra_update_cpu_speed(speed); clk_set_parent(cpu_clk, cpu_g_clk); + g_cluster = true; } tegra_cpu_set_speed_cap(NULL); @@ -228,11 +243,17 @@ static int min_cpus_notify(struct notifier_block *nb, unsigned long n, void *p) schedule_work(&minmax_work); + if (g_cluster) + cpuquiet_device_free(); + return NOTIFY_OK; } static int max_cpus_notify(struct notifier_block *nb, unsigned long n, void *p) { + if (cpq_state == TEGRA_CPQ_DISABLED) + return NOTIFY_OK; + if (n < num_online_cpus()) schedule_work(&minmax_work); @@ -253,6 +274,7 @@ void tegra_auto_hotplug_governor(unsigned int cpu_freq, bool suspend) /* Switch to G-mode if suspend rate is high enough */ if (is_lp_cluster() && (cpu_freq >= idle_bottom_freq)) { clk_set_parent(cpu_clk, cpu_g_clk); + cpuquiet_device_free(); } return; } @@ -306,11 +328,13 @@ static void enable_callback(struct cpuquiet_attribute *attr) mutex_unlock(tegra3_cpu_lock); cancel_delayed_work_sync(&cpuquiet_work); pr_info("Tegra cpuquiet clusterswitch disabled\n"); + cpuquiet_device_busy(); mutex_lock(tegra3_cpu_lock); } else if (enable && cpq_state == TEGRA_CPQ_DISABLED) { cpq_state = TEGRA_CPQ_IDLE; pr_info("Tegra cpuquiet clusterswitch enabled\n"); tegra_cpu_set_speed_cap(NULL); + cpuquiet_device_free(); } mutex_unlock(tegra3_cpu_lock); diff --git a/arch/arm/mach-tegra/devices.c b/arch/arm/mach-tegra/devices.c index 79f3ccc57f92..c3bc1ded475a 100644 --- a/arch/arm/mach-tegra/devices.c +++ b/arch/arm/mach-tegra/devices.c @@ -1723,6 +1723,43 @@ struct nvhost_device tegra_disp1_device = { .num_resources = ARRAY_SIZE(tegra_disp1_resources), }; +static struct resource tegra_disp2_resources[] = { + { + .name = "irq", + .start = INT_DISPLAY_B_GENERAL, + .end = INT_DISPLAY_B_GENERAL, + .flags = IORESOURCE_IRQ, + }, + { + .name = "regs", + .start = TEGRA_DISPLAY2_BASE, + .end = TEGRA_DISPLAY2_BASE + TEGRA_DISPLAY2_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .name = "fbmem", + .flags = IORESOURCE_MEM, + .start = 0, + .end = 0, + }, + { + .name = "hdmi_regs", + .start = TEGRA_HDMI_BASE, + .end = TEGRA_HDMI_BASE + TEGRA_HDMI_SIZE - 1, + .flags = IORESOURCE_MEM, + }, +}; + +struct nvhost_device tegra_disp2_device = { + .name = "tegradc", + .id = 1, + .resource = tegra_disp2_resources, + .num_resources = ARRAY_SIZE(tegra_disp2_resources), + .dev = { + .platform_data = 0, + }, +}; + struct platform_device tegra_nvmap_device = { .name = "tegra-nvmap", .id = -1, diff --git a/arch/arm/mach-tegra/devices.h b/arch/arm/mach-tegra/devices.h index c5cf7b708ec4..02962b59031f 100644 --- a/arch/arm/mach-tegra/devices.h +++ b/arch/arm/mach-tegra/devices.h @@ -132,6 +132,7 @@ extern struct platform_device debug_uarte_device; #endif extern struct nvhost_device tegra_disp1_device; +extern struct nvhost_device tegra_disp2_device; extern struct platform_device tegra_nvmap_device; #ifndef CONFIG_ARCH_TEGRA_2x_SOC extern struct platform_device tegra_cec_device; diff --git a/arch/arm/mach-tegra/dvfs.c b/arch/arm/mach-tegra/dvfs.c index cb33e3db862f..c36b81d2c402 100644 --- a/arch/arm/mach-tegra/dvfs.c +++ b/arch/arm/mach-tegra/dvfs.c @@ -38,6 +38,7 @@ #include "board.h" #include "clock.h" #include "dvfs.h" +#include "timer.h" #define DVFS_RAIL_STATS_BIN 25 #define DVFS_RAIL_STATS_SCALE 2 @@ -308,6 +309,13 @@ static int dvfs_rail_connect_to_regulator(struct dvfs_rail *rail) rail->reg = reg; } + v = regulator_enable(rail->reg); + if (v < 0) { + pr_err("tegra_dvfs: failed on enabling regulator %s\n, err %d", + rail->reg_id, v); + return v; + } + v = regulator_get_voltage(rail->reg); if (v < 0) { pr_err("tegra_dvfs: failed initial get %s voltage\n", @@ -681,9 +689,13 @@ int __init tegra_dvfs_late_init(void) { bool connected = true; struct dvfs_rail *rail; + int cur_linear_age = tegra_get_linear_age(); mutex_lock(&dvfs_lock); + if (cur_linear_age >= 0) + tegra_dvfs_age_cpu(cur_linear_age); + list_for_each_entry(rail, &dvfs_rail_list, node) if (dvfs_rail_connect_to_regulator(rail)) connected = false; diff --git a/arch/arm/mach-tegra/dvfs.h b/arch/arm/mach-tegra/dvfs.h index 3bdb13690278..7cacd954b914 100644 --- a/arch/arm/mach-tegra/dvfs.h +++ b/arch/arm/mach-tegra/dvfs.h @@ -5,7 +5,7 @@ * Author: * Colin Cross <ccross@google.com> * - * Copyright (C) 2010-2011 NVIDIA Corporation. + * Copyright (C) 2010-2012 NVIDIA CORPORATION. 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 @@ -21,8 +21,8 @@ #ifndef _TEGRA_DVFS_H_ #define _TEGRA_DVFS_H_ -#define MAX_DVFS_FREQS 20 -#define DVFS_RAIL_STATS_TOP_BIN 40 +#define MAX_DVFS_FREQS 40 +#define DVFS_RAIL_STATS_TOP_BIN 42 struct clk; struct dvfs_rail; @@ -118,8 +118,8 @@ int tegra_dvfs_predict_millivolts(struct clk *c, unsigned long rate); void tegra_dvfs_core_cap_enable(bool enable); void tegra_dvfs_core_cap_level_set(int level); int tegra_dvfs_alt_freqs_set(struct dvfs *d, unsigned long *alt_freqs); -void tegra_cpu_dvfs_alter( - int edp_thermal_index, const cpumask_t *cpus, bool before_clk_update); +int tegra_cpu_dvfs_alter(int edp_thermal_index, const cpumask_t *cpus, + bool before_clk_update, int cpu_event); #else static inline void tegra_soc_init_dvfs(void) {} @@ -157,19 +157,22 @@ static inline void tegra_dvfs_core_cap_level_set(int level) static inline int tegra_dvfs_alt_freqs_set(struct dvfs *d, unsigned long *alt_freqs) { return 0; } -static inline void tegra_cpu_dvfs_alter( - int edp_thermal_index, const cpumask_t *cpus, bool before_clk_update) +static inline int tegra_cpu_dvfs_alter(int edp_thermal_index, + const cpumask_t *cpus, bool before_clk_update, int cpu_event) {} #endif #ifndef CONFIG_ARCH_TEGRA_2x_SOC int tegra_dvfs_rail_disable_prepare(struct dvfs_rail *rail); int tegra_dvfs_rail_post_enable(struct dvfs_rail *rail); +void tegra_dvfs_age_cpu(int cur_linear_age); #else static inline int tegra_dvfs_rail_disable_prepare(struct dvfs_rail *rail) { return 0; } static inline int tegra_dvfs_rail_post_enable(struct dvfs_rail *rail) { return 0; } +static inline void tegra_dvfs_age_cpu(int cur_linear_age) +{ return; } #endif #endif diff --git a/arch/arm/mach-tegra/fuse.h b/arch/arm/mach-tegra/fuse.h index 37f591af5695..0b04938988c7 100644 --- a/arch/arm/mach-tegra/fuse.h +++ b/arch/arm/mach-tegra/fuse.h @@ -36,6 +36,7 @@ int tegra_cpu_process_id(void); int tegra_core_process_id(void); int tegra_soc_speedo_id(void); void tegra_init_speedo_data(void); +int tegra_get_age(void); #ifndef CONFIG_ARCH_TEGRA_2x_SOC int tegra_package_id(void); diff --git a/arch/arm/mach-tegra/headsmp.S b/arch/arm/mach-tegra/headsmp.S index 4e28a558cc38..2fa96381f68f 100644 --- a/arch/arm/mach-tegra/headsmp.S +++ b/arch/arm/mach-tegra/headsmp.S @@ -3,7 +3,7 @@ * * CPU initialization routines for Tegra SoCs * - * Copyright (c) 2009-2011, NVIDIA Corporation. + * Copyright (c) 2009-2012, NVIDIA Corporation. All rights reserved. * Copyright (c) 2011 Google, Inc. * Author: Colin Cross <ccross@android.com> * Gary King <gking@nvidia.com> @@ -82,16 +82,12 @@ ENTRY(tegra_resume) mov32 r0, TEGRA_ARM_PERIF_BASE ldr r1, [r0] orr r1, r1, #1 -#if defined(CONFIG_HAVE_ARM_SCU) - orr r1, r1, #(1 << 3) @ Enable SCU speculative line fill. - orr r1, r1, #(1 << 5) @ Enable IC standby. - orr r1, r1, #(1 << 6) @ Enable SCU standby. -#endif str r1, [r0] #ifdef CONFIG_TRUSTED_FOUNDATIONS - /* wake up (should have specified args?) */ - bl tegra_generic_smc + /* wake up */ + mov r0, #0x00000003 + bl tegra_generic_smc_local #endif b tegra_cpu_resume_phys diff --git a/arch/arm/mach-tegra/i2c_error_recovery.c b/arch/arm/mach-tegra/i2c_error_recovery.c index a3ac4e122a8f..2993a6b3abc5 100644 --- a/arch/arm/mach-tegra/i2c_error_recovery.c +++ b/arch/arm/mach-tegra/i2c_error_recovery.c @@ -44,7 +44,6 @@ int arb_lost_recovery(int scl_gpio, int sda_gpio) scl_gpio, ret);
return -EINVAL;;
}
- tegra_gpio_enable(scl_gpio);
ret = gpio_request(sda_gpio, "sda_gpio");
if (ret < 0) {
@@ -52,7 +51,6 @@ int arb_lost_recovery(int scl_gpio, int sda_gpio) sda_gpio, ret);
goto err;
}
- tegra_gpio_enable(sda_gpio);
gpio_direction_input(sda_gpio);
while (retry--) {
@@ -82,9 +80,7 @@ int arb_lost_recovery(int scl_gpio, int sda_gpio) }
gpio_free(scl_gpio);
- tegra_gpio_disable(scl_gpio);
gpio_free(sda_gpio);
- tegra_gpio_disable(sda_gpio);
if (likely(recovered_successfully)) {
pr_err("arbitration lost recovered by re-try-count 0x%08x\n",
@@ -97,7 +93,6 @@ int arb_lost_recovery(int scl_gpio, int sda_gpio) err:
gpio_free(scl_gpio);
- tegra_gpio_disable(scl_gpio);
return ret;
}
diff --git a/arch/arm/mach-tegra/include/mach/dc.h b/arch/arm/mach-tegra/include/mach/dc.h index 97f02ce6e95d..d7aaed0bdcdc 100644 --- a/arch/arm/mach-tegra/include/mach/dc.h +++ b/arch/arm/mach-tegra/include/mach/dc.h @@ -24,6 +24,7 @@ #include <linux/pm.h> #include <linux/types.h> +#include <linux/fb.h> #include <drm/drm_fixed.h> #define TEGRA_MAX_DC 2 @@ -368,6 +369,8 @@ struct tegra_dc_out { u8 *out_sel_configs; unsigned n_out_sel_configs; + bool user_needs_vblank; + struct completion user_vblank_comp; int (*enable)(void); int (*postpoweron)(void); @@ -525,6 +528,8 @@ bool tegra_dc_get_connected(struct tegra_dc *); bool tegra_dc_hpd(struct tegra_dc *dc); +void tegra_dc_get_fbvblank(struct tegra_dc *dc, struct fb_vblank *vblank); +int tegra_dc_wait_for_vsync(struct tegra_dc *dc); void tegra_dc_blank(struct tegra_dc *dc); void tegra_dc_enable(struct tegra_dc *dc); @@ -539,6 +544,9 @@ void tegra_dc_incr_syncpt_min(struct tegra_dc *dc, int i, u32 val); */ int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n); int tegra_dc_sync_windows(struct tegra_dc_win *windows[], int n); +int tegra_dc_config_frame_end_intr(struct tegra_dc *dc, bool enable); +bool tegra_dc_is_within_n_vsync(struct tegra_dc *dc, s64 ts); +bool tegra_dc_does_vsync_separate(struct tegra_dc *dc, s64 new_ts, s64 old_ts); int tegra_dc_set_mode(struct tegra_dc *dc, const struct tegra_dc_mode *mode); struct fb_videomode; @@ -565,10 +573,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_suspend(struct tegra_dc *dc); -void tegra_dc_host_resume(struct tegra_dc *dc); -int tegra_dsi_host_suspend(struct tegra_dc *dc); -int tegra_dsi_host_resume(struct tegra_dc *dc); int tegra_dc_update_csc(struct tegra_dc *dc, int win_index); @@ -588,4 +592,8 @@ struct tegra_dc_edid { struct tegra_dc_edid *tegra_dc_get_edid(struct tegra_dc *dc); void tegra_dc_put_edid(struct tegra_dc_edid *edid); +int tegra_dc_set_flip_callback(void (*callback)(void)); +int tegra_dc_unset_flip_callback(void); +int tegra_dc_get_panel_sync_rate(void); + #endif diff --git a/arch/arm/mach-tegra/include/mach/io_dpd.h b/arch/arm/mach-tegra/include/mach/io_dpd.h index 8d153792b798..6eb05c3f1b93 100644 --- a/arch/arm/mach-tegra/include/mach/io_dpd.h +++ b/arch/arm/mach-tegra/include/mach/io_dpd.h @@ -1,7 +1,7 @@ /* * arch/arm/mach-tegra/include/mach/io_dpd.h * - * Copyright (C) 2012 NVIDIA Corporation. + * Copyright (c) 2012, NVIDIA CORPORATION. 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 @@ -16,25 +16,23 @@ #ifndef __MACH_TEGRA_IO_DPD_H #define __MACH_TEGRA_IO_DPD_H +#include <linux/delay.h> + +/* Tegra io dpd entry - for each supported driver */ +struct tegra_io_dpd { + const char *name; /* driver name */ + u8 io_dpd_reg_index; /* io dpd register index */ + u8 io_dpd_bit; /* bit position for driver in dpd register */ + u8 need_delay_dpd; /* work around to delay dpd after lp0*/ + struct delayed_work delay_dpd; + struct mutex delay_lock; +}; + /* Tegra io dpd APIs */ -#ifdef CONFIG_PM_SLEEP struct tegra_io_dpd *tegra_io_dpd_get(struct device *dev); /* get handle */ void tegra_io_dpd_enable(struct tegra_io_dpd *hnd); /* enable dpd */ void tegra_io_dpd_disable(struct tegra_io_dpd *hnd); /* disable dpd */ -#else -static inline struct tegra_io_dpd *tegra_io_dpd_get(struct device *dev) -{ - return NULL; -} -static inline void tegra_io_dpd_enable(struct tegra_io_dpd *hnd) -{ - /* Do nothing */ -} -static inline void tegra_io_dpd_disable(struct tegra_io_dpd *hnd) -{ - /* Do nothing */ -} -#endif +int tegra_io_dpd_init(void); #endif /* end __MACH_TEGRA_IO_DPD_H */ diff --git a/arch/arm/mach-tegra/include/mach/latency_allowance.h b/arch/arm/mach-tegra/include/mach/latency_allowance.h index 8644075a88b3..9861834ad9de 100644 --- a/arch/arm/mach-tegra/include/mach/latency_allowance.h +++ b/arch/arm/mach-tegra/include/mach/latency_allowance.h @@ -1,7 +1,7 @@ /* * arch/arm/mach-tegra/include/mach/latency_allowance.h * - * Copyright (C) 2011-2012 NVIDIA Corporation. + * Copyright (C) 2011-2012, NVIDIA CORPORATION. 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 @@ -18,19 +18,19 @@ #define _MACH_TEGRA_LATENCY_ALLOWANCE_H_ enum tegra_la_id { - TEGRA_LA_AFIR = 0, - TEGRA_LA_AFIW, + TEGRA_LA_AFIR = 0, /* T30 specific */ + TEGRA_LA_AFIW, /* T30 specific */ TEGRA_LA_AVPC_ARM7R, TEGRA_LA_AVPC_ARM7W, TEGRA_LA_DISPLAY_0A, TEGRA_LA_DISPLAY_0B, TEGRA_LA_DISPLAY_0C, - TEGRA_LA_DISPLAY_1B, + TEGRA_LA_DISPLAY_1B, /* T30 specific */ TEGRA_LA_DISPLAY_HC, TEGRA_LA_DISPLAY_0AB, TEGRA_LA_DISPLAY_0BB, TEGRA_LA_DISPLAY_0CB, - TEGRA_LA_DISPLAY_1BB, + TEGRA_LA_DISPLAY_1BB, /* T30 specific */ TEGRA_LA_DISPLAY_HCB, TEGRA_LA_EPPUP, TEGRA_LA_EPPU, @@ -50,27 +50,27 @@ enum tegra_la_id { TEGRA_LA_MPCOREW, TEGRA_LA_MPCORE_LPR, TEGRA_LA_MPCORE_LPW, - TEGRA_LA_MPE_UNIFBR, - TEGRA_LA_MPE_IPRED, - TEGRA_LA_MPE_AMEMRD, - TEGRA_LA_MPE_CSRD, - TEGRA_LA_MPE_UNIFBW, - TEGRA_LA_MPE_CSWR, + TEGRA_LA_MPE_UNIFBR, /* T30 specific */ + TEGRA_LA_MPE_IPRED, /* T30 specific */ + TEGRA_LA_MPE_AMEMRD, /* T30 specific */ + TEGRA_LA_MPE_CSRD, /* T30 specific */ + TEGRA_LA_MPE_UNIFBW, /* T30 specific */ + TEGRA_LA_MPE_CSWR, /* T30 specific */ TEGRA_LA_FDCDRD, TEGRA_LA_IDXSRD, TEGRA_LA_TEXSRD, TEGRA_LA_FDCDWR, TEGRA_LA_FDCDRD2, - TEGRA_LA_IDXSRD2, - TEGRA_LA_TEXSRD2, + TEGRA_LA_IDXSRD2, /* T30 specific */ + TEGRA_LA_TEXSRD2, /* T30 specific */ TEGRA_LA_FDCDWR2, TEGRA_LA_PPCS_AHBDMAR, TEGRA_LA_PPCS_AHBSLVR, TEGRA_LA_PPCS_AHBDMAW, TEGRA_LA_PPCS_AHBSLVW, TEGRA_LA_PTCR, - TEGRA_LA_SATAR, - TEGRA_LA_SATAW, + TEGRA_LA_SATAR, /* T30 specific */ + TEGRA_LA_SATAW, /* T30 specific */ TEGRA_LA_VDE_BSEVR, TEGRA_LA_VDE_MBER, TEGRA_LA_VDE_MCER, @@ -79,11 +79,12 @@ enum tegra_la_id { TEGRA_LA_VDE_DBGW, TEGRA_LA_VDE_MBEW, TEGRA_LA_VDE_TPMW, - TEGRA_LA_VI_RUV, + TEGRA_LA_VI_RUV, /* T30 specific */ TEGRA_LA_VI_WSB, TEGRA_LA_VI_WU, TEGRA_LA_VI_WV, TEGRA_LA_VI_WY, + TEGRA_LA_MAX_ID }; @@ -106,6 +107,12 @@ static inline void tegra_disable_latency_scaling(enum tegra_la_id id) { return; } + +static inline void tegra_latency_allowance_update_tick_length( + unsigned int new_ns_per_tick) +{ + return; +} #else int tegra_set_latency_allowance(enum tegra_la_id id, unsigned int bandwidth_in_mbps); @@ -116,6 +123,7 @@ int tegra_enable_latency_scaling(enum tegra_la_id id, unsigned int threshold_high); void tegra_disable_latency_scaling(enum tegra_la_id id); +void tegra_latency_allowance_update_tick_length(unsigned int new_ns_per_tick); #endif #endif /* _MACH_TEGRA_LATENCY_ALLOWANCE_H_ */ diff --git a/arch/arm/mach-tegra/include/mach/tegra-bb-power.h b/arch/arm/mach-tegra/include/mach/tegra-bb-power.h index e0b7e3de326f..96e36116f04f 100644 --- a/arch/arm/mach-tegra/include/mach/tegra-bb-power.h +++ b/arch/arm/mach-tegra/include/mach/tegra-bb-power.h @@ -50,7 +50,7 @@ union tegra_bb_gpio_id { }; typedef struct platform_device* (*ehci_register_cb)(void); -typedef void (*ehci_unregister_cb)(struct platform_device *); +typedef void (*ehci_unregister_cb)(struct platform_device **); struct tegra_bb_pdata { union tegra_bb_gpio_id *id; diff --git a/arch/arm/mach-tegra/include/mach/tegra_asoc_pdata.h b/arch/arm/mach-tegra/include/mach/tegra_asoc_pdata.h index fff2fcc68269..7aada6940b39 100644 --- a/arch/arm/mach-tegra/include/mach/tegra_asoc_pdata.h +++ b/arch/arm/mach-tegra/include/mach/tegra_asoc_pdata.h @@ -1,7 +1,7 @@ /* * arch/arm/mach-tegra/include/mach/tegra_asoc_pdata.h * - * Copyright 2012 NVIDIA, Inc. + * Copyright (c) 2012, NVIDIA CORPORATION. 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 @@ -25,20 +25,23 @@ #define TEGRA_DAIFMT_RIGHT_J 3 #define TEGRA_DAIFMT_LEFT_J 4 -struct baseband_config { +struct i2s_config { + int audio_port_id; + int is_i2s_master; + int i2s_mode; + int sample_size; int rate; int channels; - int bit_format; - int is_master; }; struct tegra_asoc_platform_data { + const char *codec_name; + const char *codec_dai_name; int gpio_spkr_en; int gpio_hp_det; int gpio_hp_mute; int gpio_int_mic_en; int gpio_ext_mic_en; unsigned int debounce_time_hp; - int audio_port_id[NUM_I2S_DEVICES]; - struct baseband_config baseband_param; + struct i2s_config i2s_param[NUM_I2S_DEVICES]; }; diff --git a/arch/arm/mach-tegra/include/mach/tegra_e1853_pdata.h b/arch/arm/mach-tegra/include/mach/tegra_e1853_pdata.h new file mode 100644 index 000000000000..633f04855e6e --- /dev/null +++ b/arch/arm/mach-tegra/include/mach/tegra_e1853_pdata.h @@ -0,0 +1,55 @@ +/* + * arch/arm/mach-tegra/include/mach/tegra_e1853_pdata.h + * + * 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 __MACH_TEGRA_E1853_PDATA_H +#define __MACH_TEGRA_E1853_PDATA_H + +#define NUM_AUDIO_CONTROLLERS 4 + +/* data format supported */ +enum i2s_data_format { + format_i2s = 0x1, + format_dsp = 0x2, + format_rjm = 0x4, + format_ljm = 0x8, + format_tdm = 0x10 +}; + +struct codec_info_s { + /* Name of the Codec Dai on the system */ + char *codec_dai_name; + /* Name of the I2S controller dai its connected to */ + 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 */ + int num_slots; /* Number of TDM slots */ + int slot_width; /* Width of each slot */ + int rx_mask; /* Number of Rx Enabled slots */ + int tx_mask; /* Number of Tx Enabled slots */ + +}; + +struct tegra_e1853_platform_data { + struct codec_info_s codec_info[NUM_AUDIO_CONTROLLERS]; +}; +#endif diff --git a/arch/arm/mach-tegra/iovmm.c b/arch/arm/mach-tegra/iovmm.c index 86a92aec2d28..488c6a6fc828 100644 --- a/arch/arm/mach-tegra/iovmm.c +++ b/arch/arm/mach-tegra/iovmm.c @@ -255,11 +255,13 @@ static struct tegra_iovmm_block *iovmm_split_free_block( struct tegra_iovmm_block *rem; struct tegra_iovmm_block *b; + spin_unlock(&domain->block_lock); rem = kmem_cache_zalloc(iovmm_cache, GFP_KERNEL); + spin_lock(&domain->block_lock); + if (!rem) return NULL; - spin_lock(&domain->block_lock); p = &domain->free_blocks.rb_node; rem->start = block->start + size; @@ -344,7 +346,6 @@ static struct tegra_iovmm_block *iovmm_alloc_block( simalign = SIMALIGN(best, align); if (DO_SPLIT(simalign)) { iovmm_block_splitting = 1; - spin_unlock(&domain->block_lock); /* Split off misalignment */ b = best; @@ -365,7 +366,6 @@ static struct tegra_iovmm_block *iovmm_alloc_block( if (DO_SPLIT((best->start + best->length) - iovmm_end(best))) { iovmm_block_splitting = 1; - spin_unlock(&domain->block_lock); /* Split off excess */ (void)iovmm_split_free_block(domain, best, size + simalign); @@ -415,7 +415,6 @@ static struct tegra_iovmm_block *iovmm_allocate_vm( /* split the mem before iovm_start. */ if (DO_SPLIT(iovm_start - best->start)) { iovmm_block_splitting = 1; - spin_unlock(&domain->block_lock); best = iovmm_split_free_block(domain, best, (iovm_start - best->start)); } @@ -435,7 +434,6 @@ static struct tegra_iovmm_block *iovmm_allocate_vm( /* split the mem after iovm_start+size. */ if (DO_SPLIT(best->start + best->length - iovmm_end(best))) { iovmm_block_splitting = 1; - spin_unlock(&domain->block_lock); (void)iovmm_split_free_block(domain, best, (iovmm_start(best) - best->start + size)); } diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c index 278912486f40..4f34b87d8f36 100644 --- a/arch/arm/mach-tegra/irq.c +++ b/arch/arm/mach-tegra/irq.c @@ -196,6 +196,12 @@ static int tegra_legacy_irq_suspend(void) /* disable COP interrupts */ writel(~0, ictlr + ICTLR_COP_IER_CLR); + + /* disable CPU interrupts */ + writel(~0, ictlr + ICTLR_CPU_IER_CLR); + + /* enable lp1 wake sources */ + writel(ictlr_wake_mask[i], ictlr + ICTLR_CPU_IER_SET); } local_irq_restore(flags); diff --git a/arch/arm/mach-tegra/la_priv_common.h b/arch/arm/mach-tegra/la_priv_common.h new file mode 100644 index 000000000000..5b487e5970c5 --- /dev/null +++ b/arch/arm/mach-tegra/la_priv_common.h @@ -0,0 +1,71 @@ +/* + * arch/arm/mach-tegra/la_priv_common.h + * + * Copyright (C) 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 + * 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_TEGRA_LA_PRIV_H_ +#define _MACH_TEGRA_LA_PRIV_H_ + +/* maximum valid value for latency allowance */ +#define MC_LA_MAX_VALUE 255 + +#define MC_RA(r) \ + ((u32)IO_ADDRESS(TEGRA_MC_BASE) + (MC_##r)) +#define RA(r) \ + ((u32)IO_ADDRESS(TEGRA_MC_BASE) + (MC_LA_##r)) + +#define MASK(x) \ + ((0xFFFFFFFFUL >> (31 - (1 ? x) + (0 ? x))) << (0 ? x)) +#define SHIFT(x) \ + (0 ? x) +#define ID(id) \ + TEGRA_LA_##id + +#define LA_INFO(f, e, a, r, id, ss) \ +{f, e, RA(a), MASK(r), SHIFT(r), ID(id), __stringify(id), ss} + +struct la_client_info { + unsigned int fifo_size_in_atoms; + unsigned int expiration_in_ns; /* worst case expiration value */ + unsigned long reg_addr; + unsigned long mask; + unsigned long shift; + enum tegra_la_id id; + char *name; + bool scaling_supported; +}; + +struct la_scaling_info { + unsigned int threshold_low; + unsigned int threshold_mid; + unsigned int threshold_high; + int scaling_ref_count; + int actual_la_to_set; + int la_set; +}; + +struct la_scaling_reg_info { + enum tegra_la_id id; + unsigned int tl_reg_addr; + unsigned int tl_mask; + unsigned int tl_shift; + unsigned int tm_reg_addr; + unsigned int tm_mask; + unsigned int tm_shift; + unsigned int th_reg_addr; + unsigned int th_mask; + unsigned int th_shift; +}; + +#endif /* _MACH_TEGRA_LA_PRIV_H_ */ diff --git a/arch/arm/mach-tegra/latency_allowance.c b/arch/arm/mach-tegra/latency_allowance.c index 7698ba39f4ca..86ab179e4646 100644 --- a/arch/arm/mach-tegra/latency_allowance.c +++ b/arch/arm/mach-tegra/latency_allowance.c @@ -1,7 +1,7 @@ /* * arch/arm/mach-tegra/latency_allowance.c * - * Copyright (C) 2011 NVIDIA Corporation + * Copyright (C) 2011-2012, NVIDIA CORPORATION. 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 @@ -29,68 +29,8 @@ #include <mach/iomap.h> #include <mach/io.h> #include <mach/latency_allowance.h> - -#define MC_ARB_OVERRIDE 0xe8 -#define GLOBAL_LATENCY_SCALING_ENABLE_BIT 7 - -#define MC_LA_AFI_0 0x2e0 -#define MC_LA_AVPC_ARM7_0 0x2e4 -#define MC_LA_DC_0 0x2e8 -#define MC_LA_DC_1 0x2ec -#define MC_LA_DC_2 0x2f0 -#define MC_LA_DCB_0 0x2f4 -#define MC_LA_DCB_1 0x2f8 -#define MC_LA_DCB_2 0x2fc -#define MC_LA_EPP_0 0x300 -#define MC_LA_EPP_1 0x304 -#define MC_LA_G2_0 0x308 -#define MC_LA_G2_1 0x30c -#define MC_LA_HC_0 0x310 -#define MC_LA_HC_1 0x314 -#define MC_LA_HDA_0 0x318 -#define MC_LA_ISP_0 0x31C -#define MC_LA_MPCORE_0 0x320 -#define MC_LA_MPCORELP_0 0x324 -#define MC_LA_MPE_0 0x328 -#define MC_LA_MPE_1 0x32c -#define MC_LA_MPE_2 0x330 -#define MC_LA_NV_0 0x334 -#define MC_LA_NV_1 0x338 -#define MC_LA_NV2_0 0x33c -#define MC_LA_NV2_1 0x340 -#define MC_LA_PPCS_0 0x344 -#define MC_LA_PPCS_1 0x348 -#define MC_LA_PTC_0 0x34c -#define MC_LA_SATA_0 0x350 -#define MC_LA_VDE_0 0x354 -#define MC_LA_VDE_1 0x358 -#define MC_LA_VDE_2 0x35c -#define MC_LA_VDE_3 0x360 -#define MC_LA_VI_0 0x364 -#define MC_LA_VI_1 0x368 -#define MC_LA_VI_2 0x36c - -#define DS_DISP_MCCIF_DISPLAY0A_HYST (0x481 * 4) -#define DS_DISP_MCCIF_DISPLAY0B_HYST (0x482 * 4) -#define DS_DISP_MCCIF_DISPLAY0C_HYST (0x483 * 4) -#define DS_DISP_MCCIF_DISPLAY1B_HYST (0x484 * 4) - -#define DS_DISP_MCCIF_DISPLAY0AB_HYST (0x481 * 4) -#define DS_DISP_MCCIF_DISPLAY0BB_HYST (0x482 * 4) -#define DS_DISP_MCCIF_DISPLAY0CB_HYST (0x483 * 4) -#define DS_DISP_MCCIF_DISPLAY1BB_HYST (0x484 * 4) - -#define VI_MCCIF_VIWSB_HYST (0x9a * 4) -#define VI_MCCIF_VIWU_HYST (0x9b * 4) -#define VI_MCCIF_VIWV_HYST (0x9c * 4) -#define VI_MCCIF_VIWY_HYST (0x9d * 4) - -#define VI_TIMEOUT_WOCAL_VI (0x70 * 4) -#define VI_RESERVE_3 (0x97 * 4) -#define VI_RESERVE_4 (0x98 * 4) - -/* maximum valid value for latency allowance */ -#define MC_LA_MAX_VALUE 255 +#include "la_priv_common.h" +#include "tegra3_la_priv.h" #define ENABLE_LA_DEBUG 0 #define TEST_LA_CODE 0 @@ -100,210 +40,22 @@ printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__); \ } -static struct dentry *latency_debug_dir; - -struct la_client_info { - unsigned int fifo_size_in_atoms; - unsigned int expiration_in_ns; /* worst case expiration value */ - unsigned long reg_addr; - unsigned long mask; - unsigned long shift; - enum tegra_la_id id; - char *name; - bool scaling_supported; -}; +/* Bug 995270 */ +#define HACK_LA_FIFO 1 +static struct dentry *latency_debug_dir; static DEFINE_SPINLOCK(safety_lock); - -static const int ns_per_tick = 30; -/* fifo atom size in bytes for non-fdc clients*/ -static const int normal_atom_size = 16; -/* fifo atom size in bytes for fdc clients*/ -static const int fdc_atom_size = 32; - -#define MC_RA(r) \ - ((u32)IO_ADDRESS(TEGRA_MC_BASE) + (MC_##r)) -#define RA(r) \ - ((u32)IO_ADDRESS(TEGRA_MC_BASE) + (MC_LA_##r)) - -#define MASK(x) \ - ((0xFFFFFFFFUL >> (31 - (1 ? x) + (0 ? x))) << (0 ? x)) -#define SHIFT(x) \ - (0 ? x) -#define ID(id) \ - TEGRA_LA_##id - -#define LA_INFO(f, e, a, r, id, ss) \ -{f, e, RA(a), MASK(r), SHIFT(r), ID(id), __stringify(id), ss} - -/* - * The rule for getting the fifo_size_in_atoms is: - * 1.If REORDER_DEPTH exists, use it(default is overridden). - * 2.Else if (write_client) use RFIFO_DEPTH. - * 3.Else (read client) use RDFIFO_DEPTH. - * Refer to project.h file. - */ -struct la_client_info la_info[] = { - LA_INFO(32, 150, AFI_0, 7 : 0, AFIR, false), - LA_INFO(32, 150, AFI_0, 23 : 16, AFIW, false), - LA_INFO(2, 150, AVPC_ARM7_0, 7 : 0, AVPC_ARM7R, false), - LA_INFO(2, 150, AVPC_ARM7_0, 23 : 16, AVPC_ARM7W, false), - LA_INFO(128, 1050, DC_0, 7 : 0, DISPLAY_0A, true), - LA_INFO(64, 1050, DC_0, 23 : 16, DISPLAY_0B, true), - LA_INFO(128, 1050, DC_1, 7 : 0, DISPLAY_0C, true), - LA_INFO(64, 1050, DC_1, 23 : 16, DISPLAY_1B, true), - LA_INFO(2, 1050, DC_2, 7 : 0, DISPLAY_HC, false), - LA_INFO(128, 1050, DCB_0, 7 : 0, DISPLAY_0AB, true), - LA_INFO(64, 1050, DCB_0, 23 : 16, DISPLAY_0BB, true), - LA_INFO(128, 1050, DCB_1, 7 : 0, DISPLAY_0CB, true), - LA_INFO(64, 1050, DCB_1, 23 : 16, DISPLAY_1BB, true), - LA_INFO(2, 1050, DCB_2, 7 : 0, DISPLAY_HCB, false), - LA_INFO(8, 150, EPP_0, 7 : 0, EPPUP, false), - LA_INFO(64, 150, EPP_0, 23 : 16, EPPU, false), - LA_INFO(64, 150, EPP_1, 7 : 0, EPPV, false), - LA_INFO(64, 150, EPP_1, 23 : 16, EPPY, false), - LA_INFO(64, 150, G2_0, 7 : 0, G2PR, false), - LA_INFO(64, 150, G2_0, 23 : 16, G2SR, false), - LA_INFO(48, 150, G2_1, 7 : 0, G2DR, false), - LA_INFO(128, 150, G2_1, 23 : 16, G2DW, false), - LA_INFO(16, 150, HC_0, 7 : 0, HOST1X_DMAR, false), - LA_INFO(8, 150, HC_0, 23 : 16, HOST1XR, false), - LA_INFO(32, 150, HC_1, 7 : 0, HOST1XW, false), - LA_INFO(16, 150, HDA_0, 7 : 0, HDAR, false), - LA_INFO(16, 150, HDA_0, 23 : 16, HDAW, false), - LA_INFO(64, 150, ISP_0, 7 : 0, ISPW, false), - LA_INFO(14, 150, MPCORE_0, 7 : 0, MPCORER, false), - LA_INFO(24, 150, MPCORE_0, 23 : 16, MPCOREW, false), - LA_INFO(14, 150, MPCORELP_0, 7 : 0, MPCORE_LPR, false), - LA_INFO(24, 150, MPCORELP_0, 23 : 16, MPCORE_LPW, false), - LA_INFO(8, 150, MPE_0, 7 : 0, MPE_UNIFBR, false), - LA_INFO(2, 150, MPE_0, 23 : 16, MPE_IPRED, false), - LA_INFO(64, 150, MPE_1, 7 : 0, MPE_AMEMRD, false), - LA_INFO(8, 150, MPE_1, 23 : 16, MPE_CSRD, false), - LA_INFO(8, 150, MPE_2, 7 : 0, MPE_UNIFBW, false), - LA_INFO(8, 150, MPE_2, 23 : 16, MPE_CSWR, false), - LA_INFO(48, 150, NV_0, 7 : 0, FDCDRD, false), - LA_INFO(64, 150, NV_0, 23 : 16, IDXSRD, false), - LA_INFO(64, 150, NV_1, 7 : 0, TEXSRD, false), - LA_INFO(48, 150, NV_1, 23 : 16, FDCDWR, false), - LA_INFO(48, 150, NV2_0, 7 : 0, FDCDRD2, false), - LA_INFO(64, 150, NV2_0, 23 : 16, IDXSRD2, false), - LA_INFO(64, 150, NV2_1, 7 : 0, TEXSRD2, false), - LA_INFO(48, 150, NV2_1, 23 : 16, FDCDWR2, false), - LA_INFO(2, 150, PPCS_0, 7 : 0, PPCS_AHBDMAR, false), - LA_INFO(8, 150, PPCS_0, 23 : 16, PPCS_AHBSLVR, false), - LA_INFO(2, 150, PPCS_1, 7 : 0, PPCS_AHBDMAW, false), - LA_INFO(4, 150, PPCS_1, 23 : 16, PPCS_AHBSLVW, false), - LA_INFO(2, 150, PTC_0, 7 : 0, PTCR, false), - LA_INFO(32, 150, SATA_0, 7 : 0, SATAR, false), - LA_INFO(32, 150, SATA_0, 23 : 16, SATAW, false), - LA_INFO(8, 150, VDE_0, 7 : 0, VDE_BSEVR, false), - LA_INFO(4, 150, VDE_0, 23 : 16, VDE_MBER, false), - LA_INFO(16, 150, VDE_1, 7 : 0, VDE_MCER, false), - LA_INFO(16, 150, VDE_1, 23 : 16, VDE_TPER, false), - LA_INFO(4, 150, VDE_2, 7 : 0, VDE_BSEVW, false), - LA_INFO(16, 150, VDE_2, 23 : 16, VDE_DBGW, false), - LA_INFO(2, 150, VDE_3, 7 : 0, VDE_MBEW, false), - LA_INFO(16, 150, VDE_3, 23 : 16, VDE_TPMW, false), - LA_INFO(8, 1050, VI_0, 7 : 0, VI_RUV, false), - LA_INFO(64, 1050, VI_0, 23 : 16, VI_WSB, true), - LA_INFO(64, 1050, VI_1, 7 : 0, VI_WU, true), - LA_INFO(64, 1050, VI_1, 23 : 16, VI_WV, true), - LA_INFO(64, 1050, VI_2, 7 : 0, VI_WY, true), - -/* end of list. */ - LA_INFO(0, 0, AFI_0, 0 : 0, MAX_ID, false) -}; - -struct la_scaling_info { - unsigned int threshold_low; - unsigned int threshold_mid; - unsigned int threshold_high; - int scaling_ref_count; - int actual_la_to_set; - int la_set; -}; - -struct la_scaling_reg_info { - enum tegra_la_id id; - unsigned int tl_reg_addr; - unsigned int tl_mask; - unsigned int tl_shift; - unsigned int tm_reg_addr; - unsigned int tm_mask; - unsigned int tm_shift; - unsigned int th_reg_addr; - unsigned int th_mask; - unsigned int th_shift; -}; - -#define DISP1_RA(r) \ - ((u32)IO_ADDRESS(TEGRA_DISPLAY_BASE) + DS_DISP_MCCIF_##r##_HYST) -#define DISP2_RA(r) \ - ((u32)IO_ADDRESS(TEGRA_DISPLAY2_BASE) + DS_DISP_MCCIF_##r##_HYST) - -#define DISP_SCALING_REG_INFO(id, r, ra) \ - { \ - ID(id), \ - ra(r), MASK(15 : 8), SHIFT(15 : 8), \ - ra(r), MASK(23 : 16), SHIFT(15 : 8), \ - ra(r), MASK(7 : 0), SHIFT(15 : 8) \ - } - -struct la_scaling_reg_info disp_info[] = { - DISP_SCALING_REG_INFO(DISPLAY_0A, DISPLAY0A, DISP1_RA), - DISP_SCALING_REG_INFO(DISPLAY_0B, DISPLAY0B, DISP1_RA), - DISP_SCALING_REG_INFO(DISPLAY_0C, DISPLAY0C, DISP1_RA), - DISP_SCALING_REG_INFO(DISPLAY_1B, DISPLAY1B, DISP1_RA), - DISP_SCALING_REG_INFO(MAX_ID, DISPLAY1B, DISP1_RA), /*dummy entry*/ - DISP_SCALING_REG_INFO(DISPLAY_0AB, DISPLAY0AB, DISP2_RA), - DISP_SCALING_REG_INFO(DISPLAY_0BB, DISPLAY0BB, DISP2_RA), - DISP_SCALING_REG_INFO(DISPLAY_0CB, DISPLAY0CB, DISP2_RA), - DISP_SCALING_REG_INFO(DISPLAY_1BB, DISPLAY1BB, DISP2_RA), -}; - -#define VI_TH_RA(r) \ - ((u32)IO_ADDRESS(TEGRA_VI_BASE) + VI_MCCIF_##r##_HYST) -#define VI_TM_RA(r) \ - ((u32)IO_ADDRESS(TEGRA_VI_BASE) + VI_TIMEOUT_WOCAL_VI) -#define VI_TL_RA(r) \ - ((u32)IO_ADDRESS(TEGRA_VI_BASE) + VI_RESERVE_##r) - -struct la_scaling_reg_info vi_info[] = { - { - ID(VI_WSB), - VI_TL_RA(4), MASK(7 : 0), SHIFT(7 : 0), - VI_TM_RA(0), MASK(7 : 0), SHIFT(7 : 0), - VI_TH_RA(VIWSB), MASK(7 : 0), SHIFT(7 : 0) - }, - { - ID(VI_WU), - VI_TL_RA(3), MASK(15 : 8), SHIFT(15 : 8), - VI_TM_RA(0), MASK(15 : 8), SHIFT(15 : 8), - VI_TH_RA(VIWU), MASK(7 : 0), SHIFT(7 : 0) - }, - { - ID(VI_WV), - VI_TL_RA(3), MASK(7 : 0), SHIFT(7 : 0), - VI_TM_RA(0), MASK(23 : 16), SHIFT(23 : 16), - VI_TH_RA(VIWV), MASK(7 : 0), SHIFT(7 : 0) - }, - { - ID(VI_WY), - VI_TL_RA(4), MASK(15 : 8), SHIFT(15 : 8), - VI_TM_RA(0), MASK(31 : 24), SHIFT(31 : 24), - VI_TH_RA(VIWY), MASK(7 : 0), SHIFT(7 : 0) - } -}; - +static unsigned short id_to_index[ID(MAX_ID) + 1]; static struct la_scaling_info scaling_info[TEGRA_LA_MAX_ID]; static int la_scaling_enable_count; #define VALIDATE_ID(id) \ do { \ - if (id >= TEGRA_LA_MAX_ID) \ + if (id >= TEGRA_LA_MAX_ID || id_to_index[id] == 0xFFFF) { \ + pr_err("%s: invalid Id=%d", __func__, id); \ return -EINVAL; \ - BUG_ON(la_info[id].id != id); \ + } \ + BUG_ON(la_info_array[id_to_index[id]].id != id); \ } while (0) #define VALIDATE_BW(bw_in_mbps) \ @@ -327,20 +79,22 @@ static void set_thresholds(struct la_scaling_reg_info *info, unsigned int thresh_mid; unsigned int thresh_high; int la_set; + int idx = id_to_index[id]; - reg_read = readl(la_info[id].reg_addr); - la_set = (reg_read & la_info[id].mask) >> la_info[id].shift; + reg_read = readl(la_info_array[idx].reg_addr); + la_set = (reg_read & la_info_array[idx].mask) >> + la_info_array[idx].shift; /* la should be set before enabling scaling. */ - BUG_ON(la_set != scaling_info[id].la_set); + BUG_ON(la_set != scaling_info[idx].la_set); - thresh_low = (scaling_info[id].threshold_low * la_set) / 100; - thresh_mid = (scaling_info[id].threshold_mid * la_set) / 100; - thresh_high = (scaling_info[id].threshold_high * la_set) / 100; + thresh_low = (scaling_info[idx].threshold_low * la_set) / 100; + thresh_mid = (scaling_info[idx].threshold_mid * la_set) / 100; + thresh_high = (scaling_info[idx].threshold_high * la_set) / 100; la_debug("%s: la_set=%d, thresh_low=%d(%d%%), thresh_mid=%d(%d%%)," " thresh_high=%d(%d%%) ", __func__, la_set, - thresh_low, scaling_info[id].threshold_low, - thresh_mid, scaling_info[id].threshold_mid, - thresh_high, scaling_info[id].threshold_high); + thresh_low, scaling_info[idx].threshold_low, + thresh_mid, scaling_info[idx].threshold_mid, + thresh_high, scaling_info[idx].threshold_high); reg_read = readl(info->tl_reg_addr); reg_write = (reg_read & ~info->tl_mask) | @@ -384,42 +138,45 @@ int tegra_set_latency_allowance(enum tegra_la_id id, int la_to_set; unsigned long reg_read; unsigned long reg_write; + unsigned int fifo_size_in_atoms; int bytes_per_atom = normal_atom_size; + const int fifo_scale = 4; /* 25% of the FIFO */ struct la_client_info *ci; + int idx = id_to_index[id]; VALIDATE_ID(id); VALIDATE_BW(bandwidth_in_mbps); - if (id == ID(FDCDRD) || id == ID(FDCDWR) || - id == ID(FDCDRD2) || id == ID(FDCDWR2)) - bytes_per_atom = fdc_atom_size; - ci = &la_info[id]; + ci = &la_info_array[idx]; + fifo_size_in_atoms = ci->fifo_size_in_atoms; + +#if HACK_LA_FIFO + /* pretend that our FIFO is only as deep as the lowest fullness + * we expect to see */ + if (id >= ID(DISPLAY_0A) && id <= ID(DISPLAY_HCB)) + fifo_size_in_atoms /= fifo_scale; +#endif if (bandwidth_in_mbps == 0) { la_to_set = MC_LA_MAX_VALUE; } else { - ideal_la = (ci->fifo_size_in_atoms * bytes_per_atom * 1000) / + ideal_la = (fifo_size_in_atoms * bytes_per_atom * 1000) / (bandwidth_in_mbps * ns_per_tick); la_to_set = ideal_la - (ci->expiration_in_ns/ns_per_tick) - 1; } - la_debug("\n%s:id=%d,bw=%dmbps, la_to_set=%d", - __func__, id, bandwidth_in_mbps, la_to_set); + la_debug("\n%s:id=%d,idx=%d, bw=%dmbps, la_to_set=%d", + __func__, id, idx, bandwidth_in_mbps, la_to_set); la_to_set = (la_to_set < 0) ? 0 : la_to_set; la_to_set = (la_to_set > MC_LA_MAX_VALUE) ? MC_LA_MAX_VALUE : la_to_set; - scaling_info[id].actual_la_to_set = la_to_set; - - /* until display can use latency allowance scaling, use a more - * aggressive LA setting. Bug 862709 */ - if (id >= ID(DISPLAY_0A) && id <= ID(DISPLAY_HCB)) - la_to_set /= 3; + scaling_info[idx].actual_la_to_set = la_to_set; spin_lock(&safety_lock); reg_read = readl(ci->reg_addr); reg_write = (reg_read & ~ci->mask) | (la_to_set << ci->shift); writel(reg_write, ci->reg_addr); - scaling_info[id].la_set = la_to_set; + scaling_info[idx].la_set = la_to_set; la_debug("reg_addr=0x%x, read=0x%x, write=0x%x", (u32)ci->reg_addr, (u32)reg_read, (u32)reg_write); spin_unlock(&safety_lock); @@ -442,21 +199,22 @@ int tegra_enable_latency_scaling(enum tegra_la_id id, { unsigned long reg; unsigned long scaling_enable_reg = MC_RA(ARB_OVERRIDE); + int idx = id_to_index[id]; VALIDATE_ID(id); VALIDATE_THRESHOLDS(threshold_low, threshold_mid, threshold_high); - if (la_info[id].scaling_supported == false) + if (la_info_array[idx].scaling_supported == false) goto exit; spin_lock(&safety_lock); la_debug("\n%s: id=%d, tl=%d, tm=%d, th=%d", __func__, id, threshold_low, threshold_mid, threshold_high); - scaling_info[id].threshold_low = threshold_low; - scaling_info[id].threshold_mid = threshold_mid; - scaling_info[id].threshold_high = threshold_high; - scaling_info[id].scaling_ref_count++; + scaling_info[idx].threshold_low = threshold_low; + scaling_info[idx].threshold_mid = threshold_mid; + scaling_info[idx].threshold_high = threshold_high; + scaling_info[idx].scaling_ref_count++; if (id >= ID(DISPLAY_0A) && id <= ID(DISPLAY_1BB)) set_disp_latency_thresholds(id); @@ -477,17 +235,18 @@ void tegra_disable_latency_scaling(enum tegra_la_id id) { unsigned long reg; unsigned long scaling_enable_reg = MC_RA(ARB_OVERRIDE); + int idx; - if (id >= TEGRA_LA_MAX_ID) - return; - BUG_ON(la_info[id].id != id); + BUG_ON(id >= TEGRA_LA_MAX_ID); + idx = id_to_index[id]; + BUG_ON(la_info_array[idx].id != id); - if (la_info[id].scaling_supported == false) + if (la_info_array[idx].scaling_supported == false) return; spin_lock(&safety_lock); la_debug("\n%s: id=%d", __func__, id); - scaling_info[id].scaling_ref_count--; - BUG_ON(scaling_info[id].scaling_ref_count < 0); + scaling_info[idx].scaling_ref_count--; + BUG_ON(scaling_info[idx].scaling_ref_count < 0); if (!--la_scaling_enable_count) { reg = readl(scaling_enable_reg); @@ -498,19 +257,50 @@ void tegra_disable_latency_scaling(enum tegra_la_id id) spin_unlock(&safety_lock); } +void tegra_latency_allowance_update_tick_length(unsigned int new_ns_per_tick) +{ + int i = 0; + int la; + unsigned long reg_read; + unsigned long reg_write; + unsigned long scale_factor = new_ns_per_tick / ns_per_tick; + + if (scale_factor > 1) { + spin_lock(&safety_lock); + ns_per_tick = new_ns_per_tick; + for (i = 0; i < ARRAY_SIZE(la_info_array) - 1; i++) { + reg_read = readl(la_info_array[i].reg_addr); + la = ((reg_read & la_info_array[i].mask) >> + la_info_array[i].shift) / scale_factor; + + reg_write = (reg_read & ~la_info_array[i].mask) | + (la << la_info_array[i].shift); + writel(reg_write, la_info_array[i].reg_addr); + scaling_info[i].la_set = la; + } + spin_unlock(&safety_lock); + + /* Re-scale G2PR, G2SR, G2DR, G2DW with updated ns_per_tick */ + tegra_set_latency_allowance(TEGRA_LA_G2PR, 20); + tegra_set_latency_allowance(TEGRA_LA_G2SR, 20); + tegra_set_latency_allowance(TEGRA_LA_G2DR, 20); + tegra_set_latency_allowance(TEGRA_LA_G2DW, 20); + } +} + static int la_regs_show(struct seq_file *s, void *unused) { unsigned i; unsigned long la; /* iterate the list, but don't print MAX_ID */ - for (i = 0; i < ARRAY_SIZE(la_info) - 1; i++) { - la = (readl(la_info[i].reg_addr) & la_info[i].mask) - >> la_info[i].shift; - seq_printf(s, "%-16s: %4lu\n", la_info[i].name, la); + for (i = 0; i < ARRAY_SIZE(la_info_array) - 1; i++) { + la = (readl(la_info_array[i].reg_addr) & la_info_array[i].mask) + >> la_info_array[i].shift; + seq_printf(s, "%-16s: %4lu\n", la_info_array[i].name, la); } - return 0; + return 0; } static int dbg_la_regs_open(struct inode *inode, struct file *file) @@ -542,7 +332,13 @@ late_initcall(tegra_latency_allowance_debugfs_init); static int __init tegra_latency_allowance_init(void) { + unsigned int i; + la_scaling_enable_count = 0; + memset(&id_to_index[0], 0xFF, sizeof(id_to_index)); + + for (i = 0; i < ARRAY_SIZE(la_info_array); i++) + id_to_index[la_info_array[i].id] = i; tegra_set_latency_allowance(TEGRA_LA_G2PR, 20); tegra_set_latency_allowance(TEGRA_LA_G2SR, 20); @@ -554,12 +350,19 @@ static int __init tegra_latency_allowance_init(void) core_initcall(tegra_latency_allowance_init); #if TEST_LA_CODE +#define PRINT_ID_IDX_MAPPING 0 static int __init test_la(void) { + int i; int err; enum tegra_la_id id = 0; int repeat_count = 5; +#if PRINT_ID_IDX_MAPPING + for (i = 0; i < ID(MAX_ID); i++) + pr_info("ID=0x%x, Idx=0x%x", i, id_to_index[i]); +#endif + do { for (id = 0; id < TEGRA_LA_MAX_ID; id++) { err = tegra_set_latency_allowance(id, 200); diff --git a/arch/arm/mach-tegra/p852/board-p852-gpio.c b/arch/arm/mach-tegra/p852/board-p852-gpio.c index 71f568087c5d..6272d36fb849 100644 --- a/arch/arm/mach-tegra/p852/board-p852-gpio.c +++ b/arch/arm/mach-tegra/p852/board-p852-gpio.c @@ -152,7 +152,6 @@ void __init p852_gpio_init(void) gpio_request_array(gpios_info, pin_count); for (i = 0; i < pin_count; i++) { - tegra_gpio_enable(gpios_info[i].gpio); gpio_export(gpios_info[i].gpio, true); } } diff --git a/arch/arm/mach-tegra/p852/board-p852-sdhci.c b/arch/arm/mach-tegra/p852/board-p852-sdhci.c index dc5b81fa3727..54fd42e38ab6 100644 --- a/arch/arm/mach-tegra/p852/board-p852-sdhci.c +++ b/arch/arm/mach-tegra/p852/board-p852-sdhci.c @@ -165,7 +165,7 @@ void __init p852_sdhci_init(void) gpio_request(p852_sdhci_platform_data [i].cd_gpio, gpio_name[cd]); - tegra_gpio_enable + gpio_direction_input (p852_sdhci_platform_data[i]. cd_gpio); } @@ -176,7 +176,7 @@ void __init p852_sdhci_init(void) gpio_request(p852_sdhci_platform_data [i].wp_gpio, gpio_name[wp]); - tegra_gpio_enable + gpio_direction_input (p852_sdhci_platform_data[i]. wp_gpio); } @@ -187,7 +187,7 @@ void __init p852_sdhci_init(void) gpio_request(p852_sdhci_platform_data [i].power_gpio, gpio_name[pw]); - tegra_gpio_enable + gpio_direction_input (p852_sdhci_platform_data[i]. power_gpio); } diff --git a/arch/arm/mach-tegra/p852/board-p852.c b/arch/arm/mach-tegra/p852/board-p852.c index 039d9db6a3a6..0382d7306f42 100644 --- a/arch/arm/mach-tegra/p852/board-p852.c +++ b/arch/arm/mach-tegra/p852/board-p852.c @@ -342,12 +342,10 @@ static void p852_usb_gpio_config(void) if (has_onboard_ethernet) { gpio_request_one(usbeth_mux_gpio, GPIOF_OUT_INIT_LOW, "eth_ena"); - tegra_gpio_enable(usbeth_mux_gpio); /* eth reset */ gpio_request_one(p852_eth_reset, GPIOF_OUT_INIT_LOW, "eth_reset"); - tegra_gpio_enable(p852_eth_reset); udelay(1); gpio_direction_output(p852_eth_reset, 1); @@ -432,7 +430,6 @@ void __init p852_spi_i2s_init(void) gpio_request_one(pdata->gpio_i2s.gpio_no, GPIOF_OUT_INIT_HIGH, "i2s_cpld_dir1"); } - tegra_gpio_enable(pdata->gpio_i2s.gpio_no); if (pdata->gpio_spi.active_state) { gpio_request_one(pdata->gpio_spi.gpio_no, GPIOF_OUT_INIT_LOW, "spi_cpld_dir2"); @@ -441,7 +438,6 @@ void __init p852_spi_i2s_init(void) "spi_cpld_dir2"); } - tegra_gpio_enable(pdata->gpio_spi.gpio_no); spi_register_board_info(&tegra_spi_i2s_device, 1); } #endif @@ -498,7 +494,6 @@ static void ulpi_link_platform_open(void) gpio_request(reset_gpio, "ulpi_phy_reset"); gpio_direction_output(reset_gpio, 0); - tegra_gpio_enable(reset_gpio); gpio_direction_output(reset_gpio, 0); msleep(5); diff --git a/arch/arm/mach-tegra/pcie.c b/arch/arm/mach-tegra/pcie.c index ec386a51721c..04d3a5db3f7e 100644 --- a/arch/arm/mach-tegra/pcie.c +++ b/arch/arm/mach-tegra/pcie.c @@ -105,6 +105,7 @@ #define AFI_CONFIGURATION 0xac #define AFI_CONFIGURATION_EN_FPCI (1 << 0) +#define AFI_CONFIGURATION_DFPCI_RSPPASSPW (1 << 2) #define AFI_FPCI_ERROR_MASKS 0xb0 @@ -155,6 +156,12 @@ #define RP_VEND_XP 0x00000F00 #define RP_VEND_XP_DL_UP (1 << 30) +#define RP_TXBA1 0x00000E1C +#define RP_TXBA1_CM_OVER_PW_BURST_MASK (0xF << 4) +#define RP_TXBA1_CM_OVER_PW_BURST_INIT_VAL (0x4 << 4) +#define RP_TXBA1_PW_OVER_CM_BURST_MASK (0xF) +#define RP_TXBA1_PW_OVER_CM_BURST_INIT_VAL (0x4) + #define RP_LINK_CONTROL_STATUS 0x00000090 #define RP_LINK_CONTROL_STATUS_LINKSTAT_MASK 0x3fff0000 @@ -300,7 +307,7 @@ struct tegra_pcie_info { void __iomem *reg_clk_base; void __iomem *regs; - struct resource res_mmio; + struct resource *res_mmio; int power_rails_enabled; int pcie_power_enabled; struct work_struct hotplug_detect; @@ -311,20 +318,13 @@ struct tegra_pcie_info { struct clk *pcie_xclk; struct clk *pll_e; struct tegra_pci_platform_data *plat_data; -}; +}tegra_pcie; -#define pmc_writel(value, reg) \ - __raw_writel(value, (u32)reg_pmc_base + (reg)) -#define pmc_readl(reg) \ - __raw_readl((u32)reg_pmc_base + (reg)) - -static struct tegra_pcie_info tegra_pcie = { - .res_mmio = { - .name = "PCI IO", - .start = MMIO_BASE, - .end = MMIO_BASE + MMIO_SIZE - 1, - .flags = IORESOURCE_MEM, - }, +struct resource tegra_pcie_res_mmio = { + .name = "PCI IO", + .start = MMIO_BASE, + .end = MMIO_BASE + MMIO_SIZE - 1, + .flags = IORESOURCE_MEM, }; static struct resource pcie_io_space; @@ -639,9 +639,6 @@ static void tegra_pcie_hotplug_init(void) static void tegra_pcie_attach(void) { - /* this hardcode is just to bypass the check in resume */ - if (!is_dock_conn_at_boot) - tegra_pcie.num_ports = 1; #ifdef CONFIG_PM tegra_pcie_resume(NULL); #endif @@ -880,8 +877,11 @@ static void tegra_pcie_enable_controller(void) /* Take the PCIe interface module out of reset */ tegra_periph_reset_deassert(tegra_pcie.pcie_xclk); + /* WAR avoid hang on CPU read/write while gpu transfers in progress */ + val = afi_readl(AFI_CONFIGURATION) | AFI_CONFIGURATION_DFPCI_RSPPASSPW; + /* Finally enable PCIe */ - val = afi_readl(AFI_CONFIGURATION) | AFI_CONFIGURATION_EN_FPCI; + val |= AFI_CONFIGURATION_EN_FPCI; afi_writel(val, AFI_CONFIGURATION); val = (AFI_INTR_EN_INI_SLVERR | AFI_INTR_EN_INI_DECERR | @@ -902,8 +902,12 @@ static void tegra_pcie_enable_controller(void) static int tegra_pcie_enable_regulators(void) { - if (tegra_pcie.power_rails_enabled) + if (tegra_pcie.power_rails_enabled) { + pr_debug("PCIE: Already power rails enabled"); return 0; + } + tegra_pcie.power_rails_enabled = 1; + if (tegra_pcie.regulator_hvdd == NULL) { printk(KERN_INFO "PCIE.C: %s : regulator hvdd_pex\n", __func__); @@ -948,16 +952,17 @@ static int tegra_pcie_enable_regulators(void) if (tegra_pcie.regulator_avdd_plle) regulator_enable(tegra_pcie.regulator_avdd_plle); - tegra_pcie.power_rails_enabled = 1; - return 0; } static int tegra_pcie_disable_regulators(void) { int err = 0; - if (tegra_pcie.power_rails_enabled == 0) + + if (tegra_pcie.power_rails_enabled == 0) { + pr_debug("PCIE: Already power rails disabled"); goto err_exit; + } if (tegra_pcie.regulator_hvdd) err = regulator_disable(tegra_pcie.regulator_hvdd); if (err) @@ -985,30 +990,92 @@ static int tegra_pcie_power_regate(void) return clk_enable(tegra_pcie.pll_e); } -#ifdef CONFIG_PM +static int tegra_pcie_map_resources(void) +{ + int err; + + /* Allocate config space virtual memory */ + tegra_pcie.regs = ioremap_nocache(TEGRA_PCIE_BASE, PCIE_IOMAP_SZ); + if (tegra_pcie.regs == NULL) { + pr_err("PCIE: Failed to map PCI/AFI registers\n"); + return -ENOMEM; + } + + err = request_resource(&iomem_resource, &tegra_pcie_res_mmio); + if (err) { + pr_err("PCIE: Failed to request resources: %d\n", err); + return err; + } + tegra_pcie.res_mmio = &tegra_pcie_res_mmio; + + /* Allocate downstream IO virtual memory */ + tegra_pcie_io_base = ioremap_nocache(tegra_pcie_res_mmio.start, + resource_size(&tegra_pcie_res_mmio)); + if (tegra_pcie_io_base == NULL) { + pr_err("PCIE: Failed to map IO\n"); + return -ENOMEM; + } + return err; +} + +void tegra_pcie_unmap_resources(void) +{ + if (tegra_pcie_io_base) { + iounmap(tegra_pcie_io_base); + tegra_pcie_io_base = 0; + } + if (tegra_pcie.res_mmio) { + release_resource(tegra_pcie.res_mmio); + tegra_pcie.res_mmio = 0; + } + if (tegra_pcie.regs) { + iounmap(tegra_pcie.regs); + tegra_pcie.regs = 0; + } +} +static int tegra_pcie_power_off(void); + static int tegra_pcie_power_on(void) { int err = 0; - if (tegra_pcie.pcie_power_enabled) - return 0; + + if (tegra_pcie.pcie_power_enabled) { + pr_debug("PCIE: Already powered on"); + goto err_exit; + } + tegra_pcie.pcie_power_enabled = 1; + err = tegra_pcie_enable_regulators(); - if (err) + if (err) { + pr_err("PCIE: Failed to enable regulators\n"); goto err_exit; + } err = tegra_pcie_power_regate(); - if (err) + if (err) { + pr_err("PCIE: Failed to power regate\n"); + goto err_exit; + } + err = tegra_pcie_map_resources(); + if (err) { + pr_err("PCIE: Failed to map resources\n"); goto err_exit; + } - tegra_pcie.pcie_power_enabled = 1; err_exit: + if (err) + tegra_pcie_power_off(); return err; } -#endif static int tegra_pcie_power_off(void) { int err = 0; - if (tegra_pcie.pcie_power_enabled == 0) - return 0; + + if (tegra_pcie.pcie_power_enabled == 0) { + pr_debug("PCIE: Already powered off"); + goto err_exit; + } + tegra_pcie_unmap_resources(); if (tegra_pcie.pll_e) clk_disable(tegra_pcie.pll_e); @@ -1047,81 +1114,42 @@ error_exit: static void tegra_pcie_clocks_put(void) { - clk_put(tegra_pcie.pll_e); - clk_put(tegra_pcie.pcie_xclk); + if (tegra_pcie.pll_e) + clk_put(tegra_pcie.pll_e); + if (tegra_pcie.pcie_xclk) + clk_put(tegra_pcie.pcie_xclk); } static int tegra_pcie_get_resources(void) { - struct resource *res_mmio = 0; int err; tegra_pcie.power_rails_enabled = 0; - err = tegra_pcie_enable_regulators(); - if (err) { - pr_err("PCIE: failed to enable power rails %d\n", err); - goto err_pwr_on_rail; - } - tegra_unpowergate_partition(TEGRA_POWERGATE_PCIE); + tegra_pcie.pcie_power_enabled = 0; err = tegra_pcie_clocks_get(); if (err) { pr_err("PCIE: failed to get clocks: %d\n", err); - return err; + goto err_clk_get; } - - err = tegra_pcie_power_regate(); + err = tegra_pcie_power_on(); if (err) { - pr_err("PCIE: failed to power up: %d\n", err); + pr_err("PCIE: Failed to power on: %d\n", err); goto err_pwr_on; } - - /* Allocate config space virtual memory */ - tegra_pcie.regs = ioremap_nocache(TEGRA_PCIE_BASE, PCIE_IOMAP_SZ); - if (tegra_pcie.regs == NULL) { - pr_err("PCIE: Failed to map PCI/AFI registers\n"); - err = -ENOMEM; - goto err_map_reg; - } - res_mmio = &tegra_pcie.res_mmio; - - err = request_resource(&iomem_resource, res_mmio); - if (err) { - pr_err("PCIE: Failed to request resources: %d\n", err); - goto err_req_io; - } - - /* Allocate downstream IO virtual memory */ - tegra_pcie_io_base = ioremap_nocache(res_mmio->start, - resource_size(res_mmio)); - if (tegra_pcie_io_base == NULL) { - pr_err("PCIE: Failed to map IO\n"); - err = -ENOMEM; - goto err_map_io; - } - err = request_irq(INT_PCIE_INTR, tegra_pcie_isr, - IRQF_SHARED, "PCIE", &tegra_pcie); + IRQF_SHARED, "PCIE", &tegra_pcie); if (err) { pr_err("PCIE: Failed to register IRQ: %d\n", err); - goto err_irq; + goto err_pwr_on; } set_irq_flags(INT_PCIE_INTR, IRQF_VALID); - return 0; -err_irq: - iounmap(tegra_pcie_io_base); -err_map_io: - release_resource(&tegra_pcie.res_mmio); -err_req_io: - iounmap(tegra_pcie.regs); -err_map_reg: - tegra_pcie_power_off(); err_pwr_on: + tegra_pcie_power_off(); +err_clk_get: tegra_pcie_clocks_put(); -err_pwr_on_rail: - tegra_pcie_disable_regulators(); return err; } @@ -1205,6 +1233,7 @@ static void tegra_pcie_enable_aspm_l1_support(int index) static void tegra_pcie_add_port(int index, u32 offset, u32 reset_reg) { struct tegra_pcie_port *pp; + unsigned int data; pp = tegra_pcie.port + tegra_pcie.num_ports; @@ -1219,6 +1248,18 @@ static void tegra_pcie_add_port(int index, u32 offset, u32 reset_reg) } tegra_pcie_enable_clock_clamp(index); tegra_pcie_enable_aspm_l1_support(index); + + /* + * Initialize TXBA1 register to fix the unfair arbitration + * between downstream reads and completions to upstream reads + */ + data = rp_readl(RP_TXBA1, index); + data &= ~(RP_TXBA1_PW_OVER_CM_BURST_MASK); + data |= RP_TXBA1_PW_OVER_CM_BURST_INIT_VAL; + data &= ~(RP_TXBA1_CM_OVER_PW_BURST_MASK); + data |= RP_TXBA1_CM_OVER_PW_BURST_INIT_VAL; + rp_writel(data, RP_TXBA1, index); + tegra_pcie.num_ports++; pp->index = index; memset(pp->res, 0, sizeof(pp->res)); @@ -1254,7 +1295,6 @@ static int tegra_pcie_init(void) tegra_pcie_add_port(port, rp_offset, ctrl_offset); } - tegra_pcie.pcie_power_enabled = 1; if (tegra_pcie.plat_data->use_dock_detect) { unsigned int irq; @@ -1294,7 +1334,6 @@ err_irq: static int tegra_pcie_probe(struct platform_device *pdev) { int ret; - struct pci_dev *dev = NULL; tegra_pcie.plat_data = pdev->dev.platform_data; dev_dbg(&pdev->dev, "PCIE.C: %s : _port_status[0] %d\n", @@ -1305,23 +1344,14 @@ static int tegra_pcie_probe(struct platform_device *pdev) __func__, tegra_pcie.plat_data->port_status[2]); ret = tegra_pcie_init(); - /* disable async PM of pci devices to ensure right order */ - /* suspend/resume calls of tegra and bus driver */ - for_each_pci_dev(dev) - device_disable_async_suspend(&dev->dev); - return ret; } #ifdef CONFIG_PM static int tegra_pcie_suspend(struct device *dev) { - int ret = 0; struct pci_dev *pdev = NULL; - if (!tegra_pcie.num_ports) - return ret; - for_each_pci_dev(pdev) { pci_remove_bus_device(pdev); break; @@ -1329,6 +1359,8 @@ static int tegra_pcie_suspend(struct device *dev) /* disable read/write registers before powering off */ is_pcie_noirq_op = true; + /* reset number of ports since fresh initialization occurs in resume */ + tegra_pcie.num_ports = 0; return tegra_pcie_power_off(); } @@ -1358,24 +1390,31 @@ static int tegra_pcie_resume(struct device *dev) int port, rp_offset = 0; int ctrl_offset = AFI_PEX0_CTRL; - if (!tegra_pcie.num_ports) - return ret; + /* return w/o resume if cardhu dock is not connected */ + if (gpio_get_value(tegra_pcie.plat_data->gpio)) + goto exit; ret = tegra_pcie_power_on(); + if (ret) { + pr_err("PCIE: Failed to power on: %d\n", ret); + return ret; + } /* enable read/write registers after powering on */ is_pcie_noirq_op = false; tegra_pcie_enable_controller(); tegra_pcie_setup_translations(); msi_enable = false; - /* reset number of ports before adding port */ - tegra_pcie.num_ports = 0; for (port = 0; port < MAX_PCIE_SUPPORTED_PORTS; port++) { ctrl_offset += (port * 8); rp_offset = (rp_offset + 0x1000) * port; if (tegra_pcie.plat_data->port_status[port]) tegra_pcie_add_port(port, rp_offset, ctrl_offset); } + if (!tegra_pcie.num_ports) { + tegra_pcie_power_off(); + goto exit; + } tegra_pcie_hotplug_init(); while ((bus = pci_find_next_bus(bus)) != NULL) { @@ -1395,8 +1434,8 @@ static int tegra_pcie_resume(struct device *dev) pci_enable_bridges(bus); pci_bus_add_devices(bus); } - - return ret; +exit: + return 0; } #endif diff --git a/arch/arm/mach-tegra/pinmux-t3-tables.c b/arch/arm/mach-tegra/pinmux-t3-tables.c index 09729a4cfbae..988e3bebb43f 100644 --- a/arch/arm/mach-tegra/pinmux-t3-tables.c +++ b/arch/arm/mach-tegra/pinmux-t3-tables.c @@ -178,10 +178,10 @@ const struct tegra_drive_pingroup_desc tegra_soc_drive_pingroups[TEGRA_MAX_DRIVE PINGROUP(CLK2_OUT, PW5, SDMMC1, EXTPERIPH2, RSVD1, RSVD2, RSVD3, EXTPERIPH2, INPUT, 0x3068),\ PINGROUP(CLK2_REQ, PCC5, SDMMC1, DAP, RSVD1, RSVD2, RSVD3, DAP, INPUT, 0x306c),\ PINGROUP(LCD_PWR1, PC1, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, DISPLAYA, OUTPUT, 0x3070),\ - PINGROUP(LCD_PWR2, PC6, LCD, DISPLAYA, DISPLAYB, SPI5, INVALID, DISPLAYA, OUTPUT, 0x3074),\ + PINGROUP(LCD_PWR2, PC6, LCD, DISPLAYA, DISPLAYB, SPI5, RSVD, DISPLAYA, OUTPUT, 0x3074),\ PINGROUP(LCD_SDIN, PZ2, LCD, DISPLAYA, DISPLAYB, SPI5, RSVD, DISPLAYA, OUTPUT, 0x3078),\ PINGROUP(LCD_SDOUT, PN5, LCD, DISPLAYA, DISPLAYB, SPI5, INVALID, DISPLAYA, OUTPUT, 0x307c),\ - PINGROUP(LCD_WR_N, PZ3, LCD, DISPLAYA, DISPLAYB, SPI5, INVALID, DISPLAYA, OUTPUT, 0x3080),\ + PINGROUP(LCD_WR_N, PZ3, LCD, DISPLAYA, DISPLAYB, SPI5, RSVD, DISPLAYA, OUTPUT, 0x3080),\ PINGROUP(LCD_CS0_N, PN4, LCD, DISPLAYA, DISPLAYB, SPI5, RSVD, DISPLAYA, OUTPUT, 0x3084),\ PINGROUP(LCD_DC0, PN6, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, DISPLAYA, OUTPUT, 0x3088),\ PINGROUP(LCD_SCK, PZ4, LCD, DISPLAYA, DISPLAYB, SPI5, INVALID, DISPLAYA, OUTPUT, 0x308c),\ @@ -320,7 +320,7 @@ const struct tegra_drive_pingroup_desc tegra_soc_drive_pingroups[TEGRA_MAX_DRIVE PINGROUP(GPIO_PBB5, PBB5, CAM, VGP5, DISPLAYA, DISPLAYB, POPSDMMC4, RSVD, INPUT, 0x32a0),\ PINGROUP(GPIO_PBB6, PBB6, CAM, VGP6, DISPLAYA, DISPLAYB, POPSDMMC4, RSVD, INPUT, 0x32a4),\ PINGROUP(GPIO_PBB7, PBB7, CAM, I2S4, RSVD1, RSVD2, POPSDMMC4, RSVD, INPUT, 0x32a8),\ - PINGROUP(GPIO_PCC2, PCC2, CAM, I2S4, RSVD1, RSVD2, POPSDMMC4, RSVD, INPUT, 0x32ac),\ + PINGROUP(GPIO_PCC2, PCC2, CAM, I2S4, RSVD1, RSVD2, POPSDMMC4, RSVD, INPUT, 0x32ac),\ PINGROUP(JTAG_RTCK, PU7, SYS, RTCK, RSVD1, RSVD2, RSVD3, RTCK, INPUT, 0x32b0),\ PINGROUP(PWR_I2C_SCL, PZ6, SYS, I2CPWR, RSVD1, RSVD2, RSVD3, I2CPWR, INPUT, 0x32b4),\ PINGROUP(PWR_I2C_SDA, PZ7, SYS, I2CPWR, RSVD1, RSVD2, RSVD3, I2CPWR, INPUT, 0x32b8),\ @@ -386,7 +386,7 @@ const struct tegra_drive_pingroup_desc tegra_soc_drive_pingroups[TEGRA_MAX_DRIVE PINGROUP(SDMMC3_DAT4, PD1, SDMMC3, PWM1, INVALID, SDMMC3, INVALID, SDMMC3, INPUT, 0x33a8),\ PINGROUP(SDMMC3_DAT5, PD0, SDMMC3, PWM0, INVALID, SDMMC3, INVALID, SDMMC3, INPUT, 0x33ac),\ PINGROUP(SDMMC3_DAT6, PD3, SDMMC3, SPDIF, INVALID, SDMMC3, INVALID, SDMMC3, INPUT, 0x33b0),\ - PINGROUP(SDMMC3_DAT7, PD4, SDMMC3, SPDIF, INVALID, SDMMC3, INVALID, SDMMC3, INPUT, 0x33b4),\ + PINGROUP(SDMMC3_DAT7, PD4, SDMMC3, SPDIF, RSVD, SDMMC3, INVALID, SDMMC3, INPUT, 0x33b4),\ PINGROUP(PEX_L0_PRSNT_N, PDD0, PEXCTL, PCIE, HDA, RSVD2, RSVD3, PCIE, INPUT, 0x33b8),\ PINGROUP(PEX_L0_RST_N, PDD1, PEXCTL, PCIE, HDA, RSVD2, RSVD3, PCIE, INPUT, 0x33bc),\ PINGROUP(PEX_L0_CLKREQ_N, PDD2, PEXCTL, PCIE, HDA, RSVD2, RSVD3, PCIE, INPUT, 0x33c0),\ diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c index d1178a820f39..dbd302414c67 100644 --- a/arch/arm/mach-tegra/platsmp.c +++ b/arch/arm/mach-tegra/platsmp.c @@ -32,6 +32,7 @@ #include "clock.h" #include "reset.h" #include "sleep.h" +#include "cpu-tegra.h" bool tegra_all_cpus_booted; @@ -209,8 +210,16 @@ int boot_secondary(unsigned int cpu, struct task_struct *idle) /* Early boot, clock infrastructure is not initialized - CPU mode switch is not allowed */ status = -EINVAL; - } else + } else { +#ifdef CONFIG_CPU_FREQ + /* set cpu rate is within g-mode range before switch */ + unsigned int speed = max( + (unsigned long)tegra_getspeed(0), + clk_get_min_rate(cpu_g_clk) / 1000); + tegra_update_cpu_speed(speed); +#endif status = clk_set_parent(cpu_clk, cpu_g_clk); + } if (status) goto done; @@ -287,16 +296,5 @@ void __init platform_smp_prepare_cpus(unsigned int max_cpus) smp_init_cpus() which also means that it did not initialize the reset handler. Do it now before the secondary CPUs are started. */ tegra_cpu_reset_handler_init(); - -#if defined(CONFIG_HAVE_ARM_SCU) - { - u32 scu_ctrl = __raw_readl(scu_base) | - 1 << 3 | /* Enable speculative line fill*/ - 1 << 5 | /* Enable IC standby */ - 1 << 6; /* Enable SCU standby */ - if (!(scu_ctrl & 1)) - __raw_writel(scu_ctrl, scu_base); - } -#endif scu_enable(scu_base); } diff --git a/arch/arm/mach-tegra/pm-irq.c b/arch/arm/mach-tegra/pm-irq.c index 4a3f3c31830c..4e3c06835b2f 100644 --- a/arch/arm/mach-tegra/pm-irq.c +++ b/arch/arm/mach-tegra/pm-irq.c @@ -284,10 +284,15 @@ static int tegra_pm_irq_syscore_suspend(void) wake_enb = 0xffffffff; } - /* Clear PMC Wake Status register while going to suspend */ + /* Clear PMC Wake Status registers while going to suspend */ temp = readl(pmc + PMC_WAKE_STATUS); if (temp) pmc_32kwritel(temp, PMC_WAKE_STATUS); +#ifndef CONFIG_ARCH_TEGRA_2x_SOC + temp = readl(pmc + PMC_WAKE2_STATUS); + if (temp) + pmc_32kwritel(temp, PMC_WAKE2_STATUS); +#endif write_pmc_wake_level(wake_level); diff --git a/arch/arm/mach-tegra/pm-t2.c b/arch/arm/mach-tegra/pm-t2.c index 7ddbb2125595..6b8515ab2e3e 100644 --- a/arch/arm/mach-tegra/pm-t2.c +++ b/arch/arm/mach-tegra/pm-t2.c @@ -3,7 +3,7 @@ * * Tegra 2 LP0 scratch register preservation * - * Copyright (c) 2009-2011, NVIDIA Corporation. + * Copyright (c) 2009-2012, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -357,6 +357,8 @@ void __init tegra2_lp0_suspend_init(void) wmb(); } +#ifdef CONFIG_PM_SLEEP + struct tegra_io_dpd *tegra_io_dpd_get(struct device *dev) { return NULL; @@ -374,3 +376,17 @@ void tegra_io_dpd_disable(struct tegra_io_dpd *hnd) return; } EXPORT_SYMBOL(tegra_io_dpd_disable); + +#endif + +int tegra_io_dpd_init(void) +{ + return 0; +} +EXPORT_SYMBOL(tegra_io_dpd_init); + +void tegra_bl_io_dpd_cleanup() +{ +} +EXPORT_SYMBOL(tegra_bl_io_dpd_cleanup); + diff --git a/arch/arm/mach-tegra/pm-t3.c b/arch/arm/mach-tegra/pm-t3.c index a83174224498..939a9b8ad404 100644 --- a/arch/arm/mach-tegra/pm-t3.c +++ b/arch/arm/mach-tegra/pm-t3.c @@ -3,7 +3,7 @@ * * Tegra3 SOC-specific power and cluster management * - * Copyright (c) 2009-2012, NVIDIA Corporation. + * Copyright (c) 2009-2012, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -31,6 +31,7 @@ #include <mach/gpio.h> #include <mach/iomap.h> #include <mach/irqs.h> +#include <mach/io_dpd.h> #include <asm/cpu_pm.h> #include <asm/hardware/gic.h> @@ -101,6 +102,12 @@ #define CPU_CLOCK(cpu) (0x1<<(8+cpu)) #define CPU_RESET(cpu) (0x1111ul<<(cpu)) +#define PLLX_FO_G (1<<28) +#define PLLX_FO_LP (1<<29) + +#define CLK_RST_CONTROLLER_PLLX_MISC_0 \ + (IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0xE4) + static int cluster_switch_prolog_clock(unsigned int flags) { u32 reg; @@ -188,6 +195,20 @@ static int cluster_switch_prolog_clock(unsigned int flags) return 0; } +static inline void enable_pllx_cluster_port(void) +{ + u32 val = readl(CLK_RST_CONTROLLER_PLLX_MISC_0); + val &= (is_lp_cluster()?(~PLLX_FO_G):(~PLLX_FO_LP)); + writel(val, CLK_RST_CONTROLLER_PLLX_MISC_0); +} + +static inline void disable_pllx_cluster_port(void) +{ + u32 val = readl(CLK_RST_CONTROLLER_PLLX_MISC_0); + val |= (is_lp_cluster()?PLLX_FO_G:PLLX_FO_LP); + writel(val, CLK_RST_CONTROLLER_PLLX_MISC_0); +} + void tegra_cluster_switch_prolog(unsigned int flags) { unsigned int target_cluster = flags & TEGRA_POWER_CLUSTER_MASK; @@ -222,6 +243,9 @@ void tegra_cluster_switch_prolog(unsigned int flags) /* Set up the flow controller to switch CPUs. */ reg |= FLOW_CTRL_CPU_CSR_SWITCH_CLUSTER; + + /* Enable target port of PLL_X */ + enable_pllx_cluster_port(); } } @@ -304,6 +328,9 @@ void tegra_cluster_switch_epilog(unsigned int flags) cluster_switch_epilog_gic(); } + /* Disable unused port of PLL_X */ + disable_pllx_cluster_port(); + #if DEBUG_CLUSTER_SWITCH { /* FIXME: clock functions below are taking mutex */ @@ -450,16 +477,22 @@ void tegra_lp0_cpu_mode(bool enter) #define PMC_DPD_SAMPLE 0x20 struct tegra_io_dpd tegra_list_io_dpd[] = { -/* Empty DPD list - sd dpd entries removed */ + /* sd dpd bits in dpd2 register */ + IO_DPD_INFO("sdhci-tegra.0", 1, 1), /* SDMMC1 */ + IO_DPD_INFO("sdhci-tegra.2", 1, 2), /* SDMMC3 */ + IO_DPD_INFO("sdhci-tegra.3", 1, 3), /* SDMMC4 */ }; +/* we want to cleanup bootloader io dpd setting in kernel */ +static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE); + +#ifdef CONFIG_PM_SLEEP struct tegra_io_dpd *tegra_io_dpd_get(struct device *dev) { int i; const char *name = dev ? dev_name(dev) : NULL; if (name) { - for (i = 0; i < (sizeof(tegra_list_io_dpd) / - sizeof(struct tegra_io_dpd)); i++) { + for (i = 0; i < ARRAY_SIZE(tegra_list_io_dpd); i++) { if (!(strncmp(tegra_list_io_dpd[i].name, name, strlen(name)))) { return &tegra_list_io_dpd[i]; @@ -470,9 +503,7 @@ struct tegra_io_dpd *tegra_io_dpd_get(struct device *dev) ((name) ? name : "NULL")); return NULL; } -EXPORT_SYMBOL(tegra_io_dpd_get); -static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE); static DEFINE_SPINLOCK(tegra_io_dpd_lock); void tegra_io_dpd_enable(struct tegra_io_dpd *hnd) @@ -481,8 +512,10 @@ void tegra_io_dpd_enable(struct tegra_io_dpd *hnd) unsigned int dpd_status; unsigned int dpd_enable_lsb; - if ((!hnd)) + if ((!hnd)) { + pr_warn("SD IO DPD handle NULL in %s\n", __func__); return; + } spin_lock(&tegra_io_dpd_lock); dpd_enable_lsb = (hnd->io_dpd_reg_index) ? APBDEV_DPD2_ENABLE_LSB : APBDEV_DPD_ENABLE_LSB; @@ -502,7 +535,6 @@ void tegra_io_dpd_enable(struct tegra_io_dpd *hnd) spin_unlock(&tegra_io_dpd_lock); return; } -EXPORT_SYMBOL(tegra_io_dpd_enable); void tegra_io_dpd_disable(struct tegra_io_dpd *hnd) { @@ -510,8 +542,10 @@ void tegra_io_dpd_disable(struct tegra_io_dpd *hnd) unsigned int dpd_status; unsigned int dpd_enable_lsb; - if ((!hnd)) + if ((!hnd)) { + pr_warn("SD IO DPD handle NULL in %s\n", __func__); return; + } spin_lock(&tegra_io_dpd_lock); dpd_enable_lsb = (hnd->io_dpd_reg_index) ? APBDEV_DPD2_ENABLE_LSB : APBDEV_DPD_ENABLE_LSB; @@ -526,4 +560,88 @@ void tegra_io_dpd_disable(struct tegra_io_dpd *hnd) spin_unlock(&tegra_io_dpd_lock); return; } + +static void tegra_io_dpd_delayed_disable(struct work_struct *work) +{ + struct tegra_io_dpd *hnd = container_of( + to_delayed_work(work), struct tegra_io_dpd, delay_dpd); + tegra_io_dpd_disable(hnd); + hnd->need_delay_dpd = 0; +} + +int tegra_io_dpd_init(void) +{ + int i; + for (i = 0; + i < (sizeof(tegra_list_io_dpd) / sizeof(struct tegra_io_dpd)); + i++) { + INIT_DELAYED_WORK(&(tegra_list_io_dpd[i].delay_dpd), + tegra_io_dpd_delayed_disable); + mutex_init(&(tegra_list_io_dpd[i].delay_lock)); + tegra_list_io_dpd[i].need_delay_dpd = 0; + } + return 0; +} + +#else + +int tegra_io_dpd_init(void) +{ + return 0; +} + +void tegra_io_dpd_enable(struct tegra_io_dpd *hnd) +{ +} + +void tegra_io_dpd_disable(struct tegra_io_dpd *hnd) +{ +} + +struct tegra_io_dpd *tegra_io_dpd_get(struct device *dev) +{ + return NULL; +} + +#endif + +EXPORT_SYMBOL(tegra_io_dpd_get); +EXPORT_SYMBOL(tegra_io_dpd_enable); EXPORT_SYMBOL(tegra_io_dpd_disable); +EXPORT_SYMBOL(tegra_io_dpd_init); + +struct io_dpd_reg_info { + u32 req_reg_off; + u8 dpd_code_lsb; +}; + +static struct io_dpd_reg_info t3_io_dpd_req_regs[] = { + {0x1b8, 30}, + {0x1c0, 5}, +}; + +/* io dpd off request code */ +#define IO_DPD_CODE_OFF 1 + +/* cleans io dpd settings from bootloader during kernel init */ +void tegra_bl_io_dpd_cleanup() +{ + int i; + unsigned int dpd_mask; + unsigned int dpd_status; + + pr_info("Clear bootloader IO dpd settings\n"); + /* clear all dpd requests from bootloader */ + for (i = 0; i < ARRAY_SIZE(t3_io_dpd_req_regs); i++) { + dpd_mask = ((1 << t3_io_dpd_req_regs[i].dpd_code_lsb) - 1); + dpd_mask |= (IO_DPD_CODE_OFF << + t3_io_dpd_req_regs[i].dpd_code_lsb); + writel(dpd_mask, pmc + t3_io_dpd_req_regs[i].req_reg_off); + /* dpd status register is next to req reg in tegra3 */ + dpd_status = readl(pmc + + (t3_io_dpd_req_regs[i].req_reg_off + 4)); + } + return; +} +EXPORT_SYMBOL(tegra_bl_io_dpd_cleanup); + diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c index 7a08bc1aef24..88dd501689af 100644 --- a/arch/arm/mach-tegra/pm.c +++ b/arch/arm/mach-tegra/pm.c @@ -3,7 +3,7 @@ * * CPU complex suspend & resume functions for Tegra SoCs * - * Copyright (c) 2009-2012, NVIDIA Corporation. + * Copyright (c) 2009-2012, NVIDIA Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -178,7 +178,6 @@ struct suspend_context tegra_sctx; #define MC_SECURITY_SIZE 0x70 #define MC_SECURITY_CFG2 0x7c -#define AWAKE_CPU_FREQ_MIN 100000 static struct pm_qos_request_list awake_cpu_freq_req; struct dvfs_rail *tegra_cpu_rail; @@ -546,17 +545,27 @@ bool tegra_set_cpu_in_lp2(int cpu) return last_cpu; } +bool tegra_is_cpu_in_lp2(int cpu) +{ + bool in_lp2; + + spin_lock(&tegra_lp2_lock); + in_lp2 = cpumask_test_cpu(cpu, &tegra_in_lp2); + spin_unlock(&tegra_lp2_lock); + return in_lp2; +} + static void tegra_sleep_core(enum tegra_suspend_mode mode, unsigned long v2p) { #ifdef CONFIG_TRUSTED_FOUNDATIONS if (mode == TEGRA_SUSPEND_LP0) { - tegra_generic_smc(0xFFFFFFFC, 0xFFFFFFE3, - virt_to_phys(tegra_resume)); + tegra_generic_smc_uncached(0xFFFFFFFC, 0xFFFFFFE3, + virt_to_phys(tegra_resume)); } else { - tegra_generic_smc(0xFFFFFFFC, 0xFFFFFFE6, - (TEGRA_RESET_HANDLER_BASE + - tegra_cpu_reset_handler_offset)); + tegra_generic_smc_uncached(0xFFFFFFFC, 0xFFFFFFE6, + (TEGRA_RESET_HANDLER_BASE + + tegra_cpu_reset_handler_offset)); } #endif #ifdef CONFIG_ARCH_TEGRA_2x_SOC @@ -569,9 +578,19 @@ static void tegra_sleep_core(enum tegra_suspend_mode mode, static inline void tegra_sleep_cpu(unsigned long v2p) { #ifdef CONFIG_TRUSTED_FOUNDATIONS - tegra_generic_smc(0xFFFFFFFC, 0xFFFFFFE4, - (TEGRA_RESET_HANDLER_BASE + - tegra_cpu_reset_handler_offset)); + if (tegra_is_cpu_in_lp2(0)) { + struct thread_info *thread; + + /* flush thread state (sleep SMC will also disable L2) */ + thread = current_thread_info(); + BUG_ON(!thread); + + __cpuc_flush_dcache_area(thread, THREAD_SIZE); + outer_flush_range(__pa(thread), __pa(thread) + THREAD_SIZE); + } + tegra_generic_smc_uncached(0xFFFFFFFC, 0xFFFFFFE4, + (TEGRA_RESET_HANDLER_BASE + + tegra_cpu_reset_handler_offset)); #endif tegra_sleep_cpu_save(v2p); } @@ -1085,13 +1104,17 @@ void __init tegra_init_suspend(struct tegra_suspend_platform_data *plat) u32 reg; u32 mode; + if (plat->cpu_wake_freq == 0) + plat->cpu_wake_freq = CPU_WAKE_FREQ_HIGH; + tegra_cpu_rail = tegra_dvfs_get_rail_by_name("vdd_cpu"); tegra_core_rail = tegra_dvfs_get_rail_by_name("vdd_core"); pm_qos_add_request(&awake_cpu_freq_req, PM_QOS_CPU_FREQ_MIN, - AWAKE_CPU_FREQ_MIN); + plat->cpu_wake_freq); tegra_pclk = clk_get_sys(NULL, "pclk"); BUG_ON(IS_ERR(tegra_pclk)); + pdata = plat; (void)reg; (void)mode; @@ -1176,6 +1199,21 @@ out: plat->suspend_mode = TEGRA_SUSPEND_LP2; } +#ifdef CONFIG_TEGRA_LP1_950 + if (pdata->lp1_lowvolt_support) { + u32 lp1_core_lowvolt, lp1_core_highvolt; + memcpy(tegra_lp1_register_pmuslave_addr(), &pdata->pmuslave_addr, 4); + memcpy(tegra_lp1_register_i2c_base_addr(), &pdata->i2c_base_addr, 4); + + lp1_core_lowvolt = 0; + lp1_core_lowvolt = (pdata->lp1_core_volt_low << 8) | pdata->core_reg_addr; + memcpy(tegra_lp1_register_core_lowvolt(), &lp1_core_lowvolt, 4); + + lp1_core_highvolt = 0; + lp1_core_highvolt = (pdata->lp1_core_volt_high << 8) | pdata->core_reg_addr; + memcpy(tegra_lp1_register_core_highvolt(), &lp1_core_highvolt, 4); + } +#endif /* !!!FIXME!!! THIS IS TEGRA2 ONLY */ /* Initialize scratch registers used for CPU LP2 synchronization */ writel(0, pmc + PMC_SCRATCH37); @@ -1231,6 +1269,10 @@ out: iram_cpu_lp2_mask = tegra_cpu_lp2_mask; iram_cpu_lp1_mask = tegra_cpu_lp1_mask; + + /* clear io dpd settings before kernel */ + tegra_bl_io_dpd_cleanup(); + fail: #endif if (plat->suspend_mode == TEGRA_SUSPEND_NONE) @@ -1344,7 +1386,7 @@ static void pm_late_resume(struct early_suspend *h) { if (clk_wake) clk_enable(clk_wake); - pm_qos_update_request(&awake_cpu_freq_req, (s32)AWAKE_CPU_FREQ_MIN); + pm_qos_update_request(&awake_cpu_freq_req, (s32)pdata->cpu_wake_freq); } static struct early_suspend pm_early_suspender = { diff --git a/arch/arm/mach-tegra/pm.h b/arch/arm/mach-tegra/pm.h index 421b21ac9342..401c0aaf061f 100644 --- a/arch/arm/mach-tegra/pm.h +++ b/arch/arm/mach-tegra/pm.h @@ -2,7 +2,7 @@ * arch/arm/mach-tegra/include/mach/pm.h * * Copyright (C) 2010 Google, Inc. - * Copyright (C) 2010-2012 NVIDIA Corporation + * Copyright (c) 2010-2012, NVIDIA CORPORATION. All rights reserved. * * Author: * Colin Cross <ccross@google.com> @@ -33,6 +33,16 @@ #define PMC_SCRATCH1 0x54 #define PMC_SCRATCH4 0x60 +/* The following two constants are for setting the CPU freq + * floor when display is on. 204000Khz is for tablet and + * 102000KHz is for phones. The reason for different values + * for tablet and phone is due to phones usually have smart + * displays that requires less CPU activity for refreshing + * the screen + */ + +#define CPU_WAKE_FREQ_HIGH 204000 +#define CPU_WAKE_FREQ_LOW 102000 enum tegra_suspend_mode { TEGRA_SUSPEND_NONE = 0, TEGRA_SUSPEND_LP2, /* CPU voltage off */ @@ -65,20 +75,26 @@ struct tegra_suspend_platform_data { /* lp_state = 0 for LP0 state, 1 for LP1 state, 2 for LP2 state */ void (*board_resume)(int lp_state, enum resume_stage stg); unsigned int cpu_resume_boost; /* CPU frequency resume boost in kHz */ +#ifdef CONFIG_TEGRA_LP1_950 + bool lp1_lowvolt_support; + unsigned int i2c_base_addr; + unsigned int pmuslave_addr; + unsigned int core_reg_addr; + unsigned int lp1_core_volt_low; + unsigned int lp1_core_volt_high; +#endif + int cpu_wake_freq; }; -/* Tegra io dpd entry - for each supported driver */ -struct tegra_io_dpd { - const char *name; /* driver name */ - u8 io_dpd_reg_index; /* io dpd register index */ - u8 io_dpd_bit; /* bit position for driver in dpd register */ -}; +/* clears io dpd settings before kernel code */ +void tegra_bl_io_dpd_cleanup(void); unsigned long tegra_cpu_power_good_time(void); unsigned long tegra_cpu_power_off_time(void); unsigned long tegra_cpu_lp2_min_residency(void); void tegra_clear_cpu_in_lp2(int cpu); bool tegra_set_cpu_in_lp2(int cpu); +bool tegra_is_cpu_in_lp2(int cpu); int tegra_suspend_dram(enum tegra_suspend_mode mode, unsigned int flags); @@ -226,6 +242,8 @@ extern bool tegra_all_cpus_booted __read_mostly; #ifdef CONFIG_TRUSTED_FOUNDATIONS void tegra_generic_smc(u32 type, u32 subtype, u32 arg); +void tegra_generic_smc_local(u32 type, u32 subtype, u32 arg); +void tegra_generic_smc_uncached(u32 type, u32 subtype, u32 arg); #endif /* The debug channel uart base physical address */ diff --git a/arch/arm/mach-tegra/pwm.c b/arch/arm/mach-tegra/pwm.c index a268c391cb27..d5533c7d3c05 100644 --- a/arch/arm/mach-tegra/pwm.c +++ b/arch/arm/mach-tegra/pwm.c @@ -87,9 +87,10 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) if (rate >> PWM_SCALE_WIDTH) return -EINVAL; - /* Due to the PWM divider is zero-based, we need to minus 1 to get desired frequency*/ - if (rate>0) - rate--; + /* Due to the PWM divider is zero-based, we need to minus 1 to get + *desired frequency*/ + if (rate > 0) + rate--; val |= (rate << PWM_SCALE_SHIFT); @@ -182,19 +183,16 @@ static int tegra_pwm_probe(struct platform_device *pdev) { struct pwm_device *pwm; struct resource *r; - int ret; - pwm = kzalloc(sizeof(*pwm), GFP_KERNEL); + pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL); if (!pwm) { dev_err(&pdev->dev, "failed to allocate memory\n"); return -ENOMEM; } - pwm->clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(pwm->clk)) { - ret = PTR_ERR(pwm->clk); - goto err_free; - } + pwm->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(pwm->clk)) + return PTR_ERR(pwm->clk); pwm->clk_enb = 0; pwm->in_use = 0; @@ -204,22 +202,13 @@ static int tegra_pwm_probe(struct platform_device *pdev) r = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!r) { dev_err(&pdev->dev, "no memory resources defined\n"); - ret = -ENODEV; - goto err_put_clk; - } - - r = request_mem_region(r->start, resource_size(r), pdev->name); - if (!r) { - dev_err(&pdev->dev, "failed to request memory\n"); - ret = -EBUSY; - goto err_put_clk; + return -ENODEV; } - pwm->mmio_base = ioremap(r->start, resource_size(r)); + pwm->mmio_base = devm_request_and_ioremap(&pdev->dev, r); if (!pwm->mmio_base) { - dev_err(&pdev->dev, "failed to ioremap() region\n"); - ret = -ENODEV; - goto err_free_mem; + dev_err(&pdev->dev, "failed to request/ioremap memory\n"); + return -EADDRNOTAVAIL; } platform_set_drvdata(pdev, pwm); @@ -230,13 +219,7 @@ static int tegra_pwm_probe(struct platform_device *pdev) return 0; -err_free_mem: - release_mem_region(r->start, resource_size(r)); -err_put_clk: - clk_put(pwm->clk); -err_free: - kfree(pwm); - return ret; + } static int __devexit tegra_pwm_remove(struct platform_device *pdev) @@ -259,16 +242,9 @@ static int __devexit tegra_pwm_remove(struct platform_device *pdev) mutex_unlock(&pwm_lock); rc = pwm_writel(pwm, 0); - - iounmap(pwm->mmio_base); - release_mem_region(r->start, resource_size(r)); - if (pwm->clk_enb) clk_disable(pwm->clk); - clk_put(pwm->clk); - - kfree(pwm); return rc; } diff --git a/arch/arm/mach-tegra/sleep-t3.S b/arch/arm/mach-tegra/sleep-t3.S index 23e96c605b96..4ee73d581a08 100644 --- a/arch/arm/mach-tegra/sleep-t3.S +++ b/arch/arm/mach-tegra/sleep-t3.S @@ -95,6 +95,16 @@ #define PMC_PLLM_WB0_OVERRIDE 0x1dc #define CLK_RESET_CLK_SOURCE_MSELECT 0x3b4 +#define CLK_RESET_CLK_ENB_H_SET 0x328 +#define CLK_RESET_CLK_ENB_H_CLR 0x32c +#define CLK_RESET_CLK_RST_DEV_H_SET 0x308 +#define CLK_RESET_CLK_RST_DEV_H_CLR 0x30c + +#define I2C_CNFG 0x0 +#define I2C_ADDR0 0x4 +#define I2C_DATA1 0xc +#define I2C_DATA2 0x10 +#define I2C_STATUS 0x1c #define MSELECT_CLKM (0x3 << 30) @@ -348,6 +358,66 @@ ENTRY(tegra3_lp1_reset) mov32 r4, ((1<<28) | (8)) @ burst policy is PLLX str r4, [r0, #CLK_RESET_CCLK_BURST] +#ifdef CONFIG_TEGRA_LP1_950 +lp1_voltset: + /* Restore the Core voltage to high on LP1 resume */ + /* Reset(Enable/Disable) the DVC-I2C Controller*/ + mov r1, #(1 << 15) + str r1, [r0, #CLK_RESET_CLK_RST_DEV_H_SET] + + /* Wait for 2us */ + mov32 r7, TEGRA_TMRUS_BASE + wait_for_us r1, r7, r9 + add r1, r1, #2 + wait_until r1, r7, r9 + + mov r1, #(1 << 15) + str r1, [r0, #CLK_RESET_CLK_RST_DEV_H_CLR] + + /* Enable the DVC-I2C Controller */ + mov r1, #(1 << 15) + str r1, [r0, #CLK_RESET_CLK_ENB_H_SET] + + + /* Same I2C transaction protocol as suspend */ + ldr r1, lp1_register_pmuslave_addr + cmp r1, #0 + beq lp1_voltskip_resume + + ldr r4, lp1_register_i2c_base_addr + str r1, [r4, #I2C_ADDR0] + + mov32 r1, 0x2 + str r1, [r4, #I2C_CNFG] + + ldr r1, lp1_register_core_highvolt + str r1, [r4, #I2C_DATA1] + + mov32 r1, 0 + str r1, [r4, #I2C_DATA2] + + mov32 r1, 0xA02 + str r1, [r4, #I2C_CNFG] + + wait_for_us r1, r7, r9 + mov32 r3, 0x7D0 /* Wait for 2ms and try transaction again */ + add r0, r1, r3 +loop_i2c_status_resume: + add r1, r1, #0xFA /* Check status every 250us */ + wait_until r1, r7, r9 + cmp r0, r1 + beq lp1_voltset + + ldr r3, [r4, #I2C_STATUS] + cmp r3, #0 + bne loop_i2c_status_resume + +lp1_voltskip_resume: + /* Disable the DVC-I2C Controller */ + mov r0, #(1 << 15) + str r0, [r5, #CLK_RESET_CLK_ENB_H_CLR] +#endif + #if defined (CONFIG_CACHE_L2X0) /* power up L2 */ ldr r0, [r2, #PMC_PWRGATE_STATUS] @@ -492,6 +562,21 @@ tegra3_sdram_pad_address: tegra3_sdram_pad_size: .word tegra3_sdram_pad_address - tegra3_sdram_pad_save +#ifdef CONFIG_TEGRA_LP1_950 + .globl lp1_register_pmuslave_addr + .globl lp1_register_i2c_base_addr + .globl lp1_register_core_lowvolt + .globl lp1_register_core_highvolt +lp1_register_pmuslave_addr: + .word 0 +lp1_register_i2c_base_addr: + .word 0 +lp1_register_core_lowvolt: + .word 0 +lp1_register_core_highvolt: + .word 0 +#endif + /* * tegra3_tear_down_core * @@ -526,9 +611,72 @@ tegra3_cpu_clk32k: str r0, [r4, #PMC_PLLM_WB0_OVERRIDE] mov pc, lr +lp1_clocks_prepare: + /* Prepare to set the Core to the lowest voltage if supported. + * Start by setting the I2C clocks to make the I2C transfer */ +#ifdef CONFIG_TEGRA_LP1_950 + /* Set up the PWR I2C GPIOs with the right masks*/ + + /* Reset(Set/Clr) the DVC-I2C Controller*/ + mov r0, #(1 << 15) + str r0, [r5, #CLK_RESET_CLK_RST_DEV_H_SET] + + /* Wait for 2us */ + wait_for_us r1, r7, r9 + mov32 r0, 0x7D0 + add r1, r1, r0 + wait_until r1, r7, r9 + + mov r0, #(1 << 15) + str r0, [r5, #CLK_RESET_CLK_RST_DEV_H_CLR] + + /* Enable the DVC-I2C Controller */ + mov r0, #(1 << 15) + str r0, [r5, #CLK_RESET_CLK_ENB_H_SET] + + /* I2C transfer protocol: + * 4 packets: Slaveaddr + WriteConfigure + Data1 + Data2 */ + ldr r0, lp1_register_pmuslave_addr + cmp r0, #0 + beq lp1_volt_skip + ldr r1, lp1_register_i2c_base_addr + str r0, [r1, #I2C_ADDR0] + + mov32 r0, 0x2 + str r0, [r1, #I2C_CNFG] + + ldr r0, lp1_register_core_lowvolt + str r0, [r1, #I2C_DATA1] + + mov32 r0, 0 + str r0, [r1, #I2C_DATA2] + + /* Send I2C transaction */ + mov32 r0, 0xA02 + str r0, [r1, #I2C_CNFG] + + /* Check the transaction status before proceeding */ + wait_for_us r2, r7, r9 + mov32 r3, 0x7D0 /* Wait for 2ms for I2C transaction */ + add r3, r2, r3 +loop_i2c_status_suspend: + add r2, r2, #0xFA /* Check status every 250us */ + cmp r3, r2 + beq lp1_volt_skip /* Waited for 2ms, I2C transaction didn't take place */ + wait_until r2, r7, r9 + + ldr r0, [r1, #I2C_STATUS] + cmp r0, #0 + bne loop_i2c_status_suspend +lp1_volt_skip: + + /* Disable the DVC-I2C Controller */ + mov r0, #(1 << 15) + str r0, [r5, #CLK_RESET_CLK_ENB_H_CLR] + +#endif /* start by jumping to clkm to safely disable PLLs, then jump * to clks */ -lp1_clocks_prepare: mov r0, #(1 << 28) str r0, [r5, #CLK_RESET_SCLK_BURST] str r0, [r5, #CLK_RESET_CCLK_BURST] diff --git a/arch/arm/mach-tegra/sleep.S b/arch/arm/mach-tegra/sleep.S index 973c8677bafe..e86795c5c46a 100644 --- a/arch/arm/mach-tegra/sleep.S +++ b/arch/arm/mach-tegra/sleep.S @@ -1,7 +1,7 @@ /* * arch/arm/mach-tegra/sleep.S * - * Copyright (c) 2010-2011, NVIDIA Corporation. + * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved. * Copyright (c) 2011, Google, Inc. * * Author: Colin Cross <ccross@android.com> @@ -440,28 +440,83 @@ ENDPROC(tegra_cpu_pllp) #endif #ifdef CONFIG_TRUSTED_FOUNDATIONS + /* - * tegra_generic_smc + * Confirm we're issuing this SMC from CPU0 (only one + * currently supported) and issue the instruction. * * r0 = smc type * r1 = smc subtype * r2 = argument passed to smc - * - * issues SMC (secure monitor call) instruction with - * the specified parameters. */ -ENTRY(tegra_generic_smc) - adr r3, __tegra_smc_stack - stmia r3, {r4-r12, lr} +.macro smc_issue_smc tmp + cpu_id \tmp + cmp \tmp, #0 + bne . mov r3, #0 mov r4, #0 dsb smc #0 - adr r3, __tegra_smc_stack - ldmia r3, {r4-r12, pc} +.endm + +/* + * Issue SMC with ctx kept on an uncached stack + */ +ENTRY(tegra_generic_smc_uncached) +#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_CACHE_L2X0) + mov32 r3, tegra_cpu_context @ borrow CPU0's non-cached + ldr r3, [r3] @ context grows up + stmia r3, {r4-r12, sp, lr} + + smc_issue_smc r5 + + mov32 r3, tegra_cpu_context @ borrow CPU0's non-cached + ldr r3, [r3] @ context grows up + ldmia r3, {r4-r12, sp, pc} +#else + mov pc, lr +#endif +ENDPROC(tegra_generic_smc_uncached) + +/* + * Issue SMC with ctx kept on a cacheable stack + * (args in R0, R1, R2 and R3 holds save/restore ptr) + */ +ENTRY(tegra_generic_smc_cached) + stmia r3, {r4-r12, sp, lr} + adr r4, __tegra_smc_current_ctx @ save current ptr + str r3, [r4] + + smc_issue_smc r5 + + adr r4, __tegra_smc_current_ctx @ restore from saved ptr + ldr r3, [r4] + ldmia r3, {r4-r12, sp, pc} +ENDPROC(tegra_generic_smc_cached) + .type __tegra_smc_current_ctx, %object +__tegra_smc_current_ctx: + .long 0 + .size __tegra_smc_current_ctx, . - __tegra_smc_current_ctx + +#define TEGRA_SMC_SAVED_WORDS 11 + +/* SMC issued using the current cacheable SP stack */ +ENTRY(tegra_generic_smc) + mov r3, sp @ use current stack + sub r3, #(TEGRA_SMC_SAVED_WORDS << 2) @ context grows up + b tegra_generic_smc_cached ENDPROC(tegra_generic_smc) - .type __tegra_smc_stack, %object + +/* SMC issued using a local cacheable stack */ +ENTRY(tegra_generic_smc_local) + adr r3, __tegra_smc_stack @ use local stack + b tegra_generic_smc_cached +ENDPROC(tegra_generic_smc_local) + .align L1_CACHE_SHIFT + .type __tegra_smc_stack, %object __tegra_smc_stack: - .long 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + .rept TEGRA_SMC_SAVED_WORDS + .long 0 + .endr .size __tegra_smc_stack, . - __tegra_smc_stack #endif diff --git a/arch/arm/mach-tegra/sleep.h b/arch/arm/mach-tegra/sleep.h index c57399985ecd..48b2bb8cfdb2 100644 --- a/arch/arm/mach-tegra/sleep.h +++ b/arch/arm/mach-tegra/sleep.h @@ -223,6 +223,10 @@ void tegra2_sleep_wfi(unsigned long v2p); #else extern unsigned int tegra3_iram_start; extern unsigned int tegra3_iram_end; +extern unsigned int lp1_register_pmuslave_addr; +extern unsigned int lp1_register_i2c_base_addr; +extern unsigned int lp1_register_core_lowvolt; +extern unsigned int lp1_register_core_highvolt; void tegra3_sleep_core(unsigned long v2p); void tegra3_sleep_cpu_secondary(unsigned long v2p); void tegra3_hotplug_shutdown(void); @@ -245,5 +249,41 @@ static inline void *tegra_iram_end(void) return &tegra3_iram_end; #endif } + +static inline void *tegra_lp1_register_pmuslave_addr(void) +{ +#ifdef CONFIG_ARCH_TEGRA_2x_SOC + return NULL; +#else + return &lp1_register_pmuslave_addr; +#endif +} + +static inline void *tegra_lp1_register_i2c_base_addr(void) +{ +#ifdef CONFIG_ARCH_TEGRA_2x_SOC + return NULL; +#else + return &lp1_register_i2c_base_addr; +#endif +} + +static inline void *tegra_lp1_register_core_lowvolt(void) +{ +#ifdef CONFIG_ARCH_TEGRA_2x_SOC + return NULL; +#else + return &lp1_register_core_lowvolt; +#endif +} + +static inline void *tegra_lp1_register_core_highvolt(void) +{ +#ifdef CONFIG_ARCH_TEGRA_2x_SOC + return NULL; +#else + return &lp1_register_core_highvolt; +#endif +} #endif #endif diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c index 65434963d7d7..58d2dcddbfaa 100644 --- a/arch/arm/mach-tegra/tegra2_clocks.c +++ b/arch/arm/mach-tegra/tegra2_clocks.c @@ -2462,14 +2462,14 @@ struct clk tegra_list_periph_clks[] = { PERIPH_CLK("owr", "tegra_w1", NULL, 71, 0x1cc, 0x31E, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | PERIPH_ON_APB), PERIPH_CLK("nor", "tegra-nor", NULL, 42, 0x1d0, 0x31E, 92000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* requires min voltage */ PERIPH_CLK("mipi", "mipi", NULL, 50, 0x174, 0x31E, 60000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | PERIPH_ON_APB), /* scales with voltage */ - PERIPH_CLK("i2c1", "tegra-i2c.0", "i2c-div", 12, 0x124, 0x31E, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U16 | PERIPH_ON_APB), - PERIPH_CLK("i2c2", "tegra-i2c.1", "i2c-div", 54, 0x198, 0x31E, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U16 | PERIPH_ON_APB), - PERIPH_CLK("i2c3", "tegra-i2c.2", "i2c-div", 67, 0x1b8, 0x31E, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U16 | PERIPH_ON_APB), - PERIPH_CLK("dvc", "tegra-i2c.3", "i2c-div", 47, 0x128, 0x31E, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U16 | PERIPH_ON_APB), - PERIPH_CLK("i2c1-fast", "tegra-i2c.0", "i2c-fast", 0, 0, 0x31E, 108000000, mux_pllp_out3, PERIPH_NO_ENB), - PERIPH_CLK("i2c2-fast", "tegra-i2c.1", "i2c-fast", 0, 0, 0x31E, 108000000, mux_pllp_out3, PERIPH_NO_ENB), - PERIPH_CLK("i2c3-fast", "tegra-i2c.2", "i2c-fast", 0, 0, 0x31E, 108000000, mux_pllp_out3, PERIPH_NO_ENB), - PERIPH_CLK("dvc-fast", "tegra-i2c.3", "i2c-fast", 0, 0, 0x31E, 108000000, mux_pllp_out3, PERIPH_NO_ENB), + PERIPH_CLK("i2c1", "tegra-i2c.0", "div-clk", 12, 0x124, 0x31E, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U16 | PERIPH_ON_APB), + PERIPH_CLK("i2c2", "tegra-i2c.1", "div-clk", 54, 0x198, 0x31E, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U16 | PERIPH_ON_APB), + PERIPH_CLK("i2c3", "tegra-i2c.2", "div-clk", 67, 0x1b8, 0x31E, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U16 | PERIPH_ON_APB), + PERIPH_CLK("dvc", "tegra-i2c.3", "div-clk", 47, 0x128, 0x31E, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U16 | PERIPH_ON_APB), + PERIPH_CLK("i2c1-fast", "tegra-i2c.0", "fast-clk", 0, 0, 0x31E, 108000000, mux_pllp_out3, PERIPH_NO_ENB), + PERIPH_CLK("i2c2-fast", "tegra-i2c.1", "fast-clk", 0, 0, 0x31E, 108000000, mux_pllp_out3, PERIPH_NO_ENB), + PERIPH_CLK("i2c3-fast", "tegra-i2c.2", "fast-clk", 0, 0, 0x31E, 108000000, mux_pllp_out3, PERIPH_NO_ENB), + PERIPH_CLK("dvc-fast", "tegra-i2c.3", "fast-clk", 0, 0, 0x31E, 108000000, mux_pllp_out3, PERIPH_NO_ENB), PERIPH_CLK("uarta", "tegra_uart.0", NULL, 6, 0x178, 0x31E, 600000000, mux_pllp_pllc_pllm_clkm, MUX | PERIPH_ON_APB), PERIPH_CLK("uartb", "tegra_uart.1", NULL, 7, 0x17c, 0x31E, 600000000, mux_pllp_pllc_pllm_clkm, MUX | PERIPH_ON_APB), PERIPH_CLK("uartc", "tegra_uart.2", NULL, 55, 0x1a0, 0x31E, 600000000, mux_pllp_pllc_pllm_clkm, MUX | PERIPH_ON_APB), diff --git a/arch/arm/mach-tegra/tegra2_usb_phy.c b/arch/arm/mach-tegra/tegra2_usb_phy.c index 6e0801625614..121a84b2bcb0 100644 --- a/arch/arm/mach-tegra/tegra2_usb_phy.c +++ b/arch/arm/mach-tegra/tegra2_usb_phy.c @@ -47,11 +47,13 @@ #define USB_USBSTS_SRI (1 << 7) #define USB_USBSTS_HCH (1 << 12) +#define USB_USBINTR 0x148 + #define USB_ASYNCLISTADDR 0x158 #define USB_TXFILLTUNING 0x164 #define USB_FIFO_TXFILL_THRES(x) (((x) & 0x1f) << 16) -#define USB_FIFO_TXFILL_MASK 0x1f0000 +#define USB_FIFO_TXFILL_MASK 0x3f0000 #define ULPI_VIEWPORT 0x170 #define ULPI_WAKEUP (1 << 31) @@ -69,6 +71,7 @@ #define USB_PORTSC_PP (1 << 12) #define USB_PORTSC_LS(x) (((x) & 0x3) << 10) #define USB_PORTSC_SUSP (1 << 7) +#define USB_PORTSC_RESUME (1 << 6) #define USB_PORTSC_OCC (1 << 5) #define USB_PORTSC_PEC (1 << 3) #define USB_PORTSC_PE (1 << 2) @@ -277,6 +280,11 @@ #define DBG(stuff...) do {} while (0) #endif +/* define HSIC phy params */ +#define HSIC_SYNC_START_DELAY 9 +#define HSIC_IDLE_WAIT_DELAY 17 +#define HSIC_ELASTIC_UNDERRUN_LIMIT 16 +#define HSIC_ELASTIC_OVERRUN_LIMIT 16 static DEFINE_SPINLOCK(utmip_pad_lock); static int utmip_pad_count; @@ -605,13 +613,21 @@ static int utmi_phy_irq(struct tegra_usb_phy *phy) val &= ~USB_PHY_CLK_VALID_INT_ENB | USB_PHY_CLK_VALID_INT_STS; writel(val , (base + USB_SUSP_CTRL)); - pr_info("%s: usb device plugged-in\n", __func__); + val = readl(base + USB_USBSTS); if (!(val & USB_USBSTS_PCI)) return IRQ_NONE; + val = readl(base + USB_PORTSC); - val &= ~(USB_PORTSC_WKCN | USB_PORTSC_RWC_BITS); + if (val & USB_PORTSC_CCS) + val &= ~USB_PORTSC_WKCN; + else + val &= ~USB_PORTSC_WKDS; + val &= ~USB_PORTSC_RWC_BITS; writel(val , (base + USB_PORTSC)); + + } else if (!phy->phy_clk_on) { + return IRQ_NONE; } } else if (!phy->phy_clk_on) { return IRQ_NONE; @@ -702,21 +718,27 @@ static int utmi_phy_power_off(struct tegra_usb_phy *phy) enable_hotplug = (val & USB_ID_STATUS) ? false : true; } if (enable_hotplug) { + /* Enable wakeup event of device plug-in/plug-out */ val = readl(base + USB_PORTSC); - val |= USB_PORTSC_WKCN; + if (val & USB_PORTSC_CCS) + val |= USB_PORTSC_WKDS; + else + val |= USB_PORTSC_WKCN; writel(val, base + USB_PORTSC); val = readl(base + USB_SUSP_CTRL); val |= USB_PHY_CLK_VALID_INT_ENB; writel(val, base + USB_SUSP_CTRL); } else { - /* Disable PHY clock valid interrupts while going into suspend*/ + /* Disable PHY clock valid interrupts + while going into suspend*/ val = readl(base + USB_SUSP_CTRL); val &= ~USB_PHY_CLK_VALID_INT_ENB; writel(val, base + USB_SUSP_CTRL); } } + /* Disable PHY clock */ if (phy->inst == 2) { val = readl(base + USB_PORTSC); val |= USB_PORTSC_PHCD; @@ -932,7 +954,8 @@ static int utmi_phy_resume(struct tegra_usb_phy *phy) if (usb_phy_reg_status_wait(base + USB_USBCMD, USB_USBCMD_RESET, 0, 2500) < 0) { - pr_err("%s: timeout waiting for reset\n", __func__); + pr_err("%s: timeout waiting for reset\n", + __func__); } val = readl(base + USB_USBMODE_REG_OFFSET); @@ -949,7 +972,8 @@ static int utmi_phy_resume(struct tegra_usb_phy *phy) if (usb_phy_reg_status_wait(base + USB_USBCMD, USB_USBCMD_RS, USB_USBCMD_RS, 2500) < 0) { - pr_err("%s: timeout waiting for run bit\n", __func__); + pr_err("%s: timeout waiting for run bit\n", + __func__); } /* Enable Port Power */ @@ -959,7 +983,8 @@ static int utmi_phy_resume(struct tegra_usb_phy *phy) udelay(10); DBG("USB_USBSTS[0x%x] USB_PORTSC[0x%x]\n", - readl(base + USB_USBSTS), readl(base + USB_PORTSC)); + readl(base + USB_USBSTS), + readl(base + USB_PORTSC)); } } else { /* Restoring the pad powers */ @@ -1051,7 +1076,6 @@ static int uhsic_phy_power_on(struct tegra_usb_phy *phy) { unsigned long val; void __iomem *base = phy->regs; - struct tegra_hsic_config *config = &phy->pdata->u_cfg.hsic; DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst); if (phy->phy_clk_on) { @@ -1077,13 +1101,13 @@ static int uhsic_phy_power_on(struct tegra_usb_phy *phy) writel(val, base + USB_SUSP_CTRL); val = readl(base + UTMIP_XCVR_UHSIC_HSRX_CFG0); - val |= UHSIC_IDLE_WAIT(config->idle_wait_delay); - val |= UHSIC_ELASTIC_UNDERRUN_LIMIT(config->elastic_underrun_limit); - val |= UHSIC_ELASTIC_OVERRUN_LIMIT(config->elastic_overrun_limit); + val |= UHSIC_IDLE_WAIT(HSIC_IDLE_WAIT_DELAY); + val |= UHSIC_ELASTIC_UNDERRUN_LIMIT(HSIC_ELASTIC_UNDERRUN_LIMIT); + val |= UHSIC_ELASTIC_OVERRUN_LIMIT(HSIC_ELASTIC_OVERRUN_LIMIT); writel(val, base + UTMIP_XCVR_UHSIC_HSRX_CFG0); val = readl(base + UHSIC_HSRX_CFG1); - val |= UHSIC_HS_SYNC_START_DLY(config->sync_start_delay); + val |= UHSIC_HS_SYNC_START_DLY(HSIC_SYNC_START_DELAY); writel(val, base + UHSIC_HSRX_CFG1); val = readl(base + UHSIC_MISC_CFG0); @@ -1354,7 +1378,7 @@ static int ulpi_link_phy_open(struct tegra_usb_phy *phy) phy->ulpi_vp = otg_ulpi_create(&ulpi_viewport_access_ops, 0); phy->ulpi_vp->io_priv = phy->regs + ULPI_VIEWPORT; - + phy->linkphy_init = true; return err; } @@ -1450,49 +1474,74 @@ static int ulpi_link_phy_power_on(struct tegra_usb_phy *phy) } 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); + /* Case for lp0 */ + if (!(val & UHSIC_RESET)) { + val |= UHSIC_RESET; + writel(val, base + USB_SUSP_CTRL); - val = readl(base + USB_SUSP_CTRL); - val |= ULPI_PHY_ENABLE; - writel(val, base + USB_SUSP_CTRL); + val = 0; + writel(val, base + ULPI_TIMING_CTRL_1); - val = readl(base + USB_SUSP_CTRL); - val |= USB_SUSP_CLR; - writel(val, base + USB_SUSP_CTRL); + ulpi_set_trimmer(phy); - 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__); + val = readl(base + ULPI_TIMING_CTRL_0); + val |= ULPI_OUTPUT_PINMUX_BYP | ULPI_CLKOUT_PINMUX_BYP; + writel(val, base + ULPI_TIMING_CTRL_0); +#ifdef CONFIG_ARCH_TEGRA_2x_SOC + tegra_pinmux_set_tristate(TEGRA_PINGROUP_UAA, TEGRA_TRI_NORMAL); + tegra_pinmux_set_tristate(TEGRA_PINGROUP_UAB, TEGRA_TRI_NORMAL); + tegra_pinmux_set_tristate(TEGRA_PINGROUP_UDA, TEGRA_TRI_NORMAL); +#endif + val = readl(base + USB_SUSP_CTRL); + val |= ULPI_PHY_ENABLE; + writel(val, base + USB_SUSP_CTRL); - if (usb_phy_reg_status_wait(base + USB_SUSP_CTRL, USB_CLKEN, - USB_CLKEN, 2500)) - pr_err("%s: timeout waiting for AHB clock\n", __func__); + if (usb_phy_reg_status_wait(base + USB_SUSP_CTRL, + USB_PHY_CLK_VALID, USB_PHY_CLK_VALID, 2500) < 0) + pr_err("%s: timeout waiting for phy" \ + "to stabilize\n", __func__); - val = readl(base + USB_SUSP_CTRL); - val &= ~USB_SUSP_CLR; - writel(val, base + USB_SUSP_CTRL); + val = readl(base + USB_TXFILLTUNING); + if ((val & USB_FIFO_TXFILL_MASK) != + USB_FIFO_TXFILL_THRES(0x10)) { + val = USB_FIFO_TXFILL_THRES(0x10); + writel(val, base + USB_TXFILLTUNING); + } + } else { + /* Case for auto resume*/ + val = readl(base + USB_SUSP_CTRL); + val |= USB_SUSP_CLR; + writel(val, base + USB_SUSP_CTRL); - val = 0; - writel(val, base + ULPI_TIMING_CTRL_1); + if (usb_phy_reg_status_wait(base + USB_SUSP_CTRL, + USB_PHY_CLK_VALID, USB_PHY_CLK_VALID, 2500) < 0) + pr_err("%s: timeout waiting for phy" \ + "to stabilize\n", __func__); - ulpi_set_trimmer(phy); + if (usb_phy_reg_status_wait(base + USB_SUSP_CTRL, + USB_CLKEN, USB_CLKEN, 2500) < 0) + pr_err("%s: timeout waiting for AHB clock\n", __func__); - /* Fix VbusInvalid due to floating VBUS */ - ret = otg_io_write(phy->ulpi_vp, 0x40, 0x08); - if (ret) { - pr_err("%s: ulpi write failed\n", __func__); - return ret; + val = readl(base + USB_SUSP_CTRL); + val &= ~USB_SUSP_CLR; + writel(val, base + USB_SUSP_CTRL); } + if (phy->linkphy_init) { + /* To be done only incase of coldboot*/ + /* Fix VbusInvalid due to floating VBUS */ + ret = otg_io_write(phy->ulpi_vp, 0x40, 0x08); + if (ret) { + pr_err("%s: ulpi write failed\n", __func__); + return ret; + } - ret = otg_io_write(phy->ulpi_vp, 0x80, 0x0B); - if (ret) { - pr_err("%s: ulpi write failed\n", __func__); - return ret; + ret = otg_io_write(phy->ulpi_vp, 0x80, 0x0B); + if (ret) { + pr_err("%s: ulpi write failed\n", __func__); + return ret; + } + phy->linkphy_init = false; } val = readl(base + USB_PORTSC); @@ -1510,6 +1559,7 @@ static inline void ulpi_link_phy_set_tristate(bool enable) #ifdef CONFIG_ARCH_TEGRA_2x_SOC int tristate = (enable) ? TEGRA_TRI_TRISTATE : TEGRA_TRI_NORMAL; + tegra_pinmux_set_tristate(TEGRA_PINGROUP_CDEV2, tristate); tegra_pinmux_set_tristate(TEGRA_PINGROUP_UAA, tristate); tegra_pinmux_set_tristate(TEGRA_PINGROUP_UAB, tristate); tegra_pinmux_set_tristate(TEGRA_PINGROUP_UDA, tristate); @@ -1535,6 +1585,7 @@ static void ulpi_link_phy_restore_end(struct tegra_usb_phy *phy) { unsigned long val; void __iomem *base = phy->regs; + int ret; DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst); @@ -1543,6 +1594,13 @@ static void ulpi_link_phy_restore_end(struct tegra_usb_phy *phy) writel(val, base + ULPI_TIMING_CTRL_0); ulpi_link_phy_set_tristate(false); + + udelay(10); + ret = otg_io_write(phy->ulpi_vp, 0x55, 0x04); + if (ret) { + pr_err("%s: ulpi write failed\n", __func__); + return; + } } static int ulpi_link_phy_resume(struct tegra_usb_phy *phy) @@ -1562,7 +1620,70 @@ static int ulpi_link_phy_resume(struct tegra_usb_phy *phy) return status; } -static inline void ulpi_pinmux_bypass(struct tegra_usb_phy *phy, bool enable) +static int ulpi_link_phy_pre_resume(struct tegra_usb_phy *phy, + bool remote_wakeup) +{ + int status = 0; + unsigned long val; + void __iomem *base = phy->regs; + DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst); + + val = readl(base + USB_PORTSC); + if (val & USB_PORTSC_RESUME) { + + val = readl(base + USB_USBCMD); + val &= ~USB_USBCMD_RS; + writel(val, base + USB_USBCMD); + + /* detect remote wakeup */ + msleep(20); + + val = readl(base + USB_PORTSC); + + /* Poll until the controller clears RESUME and SUSPEND */ + if (usb_phy_reg_status_wait(base + USB_SUSP_CTRL, + USB_PORTSC_RESUME, 0, 2500)) + pr_err("%s: timeout waiting for RESUME\n", __func__); + if (usb_phy_reg_status_wait(base + USB_SUSP_CTRL, + USB_PORTSC_SUSP, 0, 2500)) + pr_err("%s: timeout waiting for SUSPEND\n", __func__); + + /* Since we skip remote wakeup event, + put controller in suspend again and + resume port later */ + val = readl(base + USB_PORTSC); + val |= USB_PORTSC_SUSP; + writel(val, base + USB_PORTSC); + mdelay(4); + /* Wait until port suspend completes */ + if (usb_phy_reg_status_wait(base + USB_SUSP_CTRL, + USB_PORTSC_SUSP, USB_PORTSC_SUSP, 2500)) + pr_err("%s: timeout waiting for" \ + "PORT_SUSPEND\n", __func__); + + /* 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__); + } + usb_phy_wait_for_sof(phy); + + val = readl(base + USB_USBCMD); + val |= USB_USBCMD_RS; + writel(val, base + USB_USBCMD); + } + return status; +} + + +static inline void ulpi_pinmux_bypass(struct tegra_usb_phy *phy, + bool enable) { unsigned long val; void __iomem *base = phy->regs; @@ -1795,7 +1916,8 @@ static int ulpi_null_phy_power_on(struct tegra_usb_phy *phy) 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_SPARE((phy->pdata->op_mode == TEGRA_USB_OPMODE_HOST) + ? 3 : 1); val |= ULPIS2S_PLLU_MASTER_BLASTER60; writel(val, base + ULPIS2S_CTRL); @@ -1906,6 +2028,7 @@ static struct tegra_usb_phy_ops ulpi_link_phy_ops = { .power_on = ulpi_link_phy_power_on, .power_off = ulpi_link_phy_power_off, .resume = ulpi_link_phy_resume, + .pre_resume = ulpi_link_phy_pre_resume, }; static struct tegra_usb_phy_ops ulpi_null_phy_ops = { diff --git a/arch/arm/mach-tegra/tegra3_clocks.c b/arch/arm/mach-tegra/tegra3_clocks.c index eba959c9e2d3..468f50dee329 100644 --- a/arch/arm/mach-tegra/tegra3_clocks.c +++ b/arch/arm/mach-tegra/tegra3_clocks.c @@ -319,6 +319,7 @@ static int tegra3_emc_relock_set_rate(struct clk *emc, unsigned long old_rate, static unsigned long cpu_stay_on_backup_max; static struct clk *emc_bridge; +static struct clk *cpu_mode_sclk; static bool detach_shared_bus; module_param(detach_shared_bus, bool, 0644); @@ -1053,6 +1054,8 @@ static int tegra3_cpu_cmplx_clk_set_parent(struct clk *c, struct clk *p) flags |= (p->u.cpu.mode == MODE_LP) ? TEGRA_POWER_CLUSTER_LP : TEGRA_POWER_CLUSTER_G; + clk_enable(cpu_mode_sclk); /* set SCLK floor for cluster switch */ + /* Since in both LP and G mode CPU main and backup sources are the same, set rate on the new parent just synchronizes super-clock muxes before mode switch with no PLL re-locking */ @@ -1060,6 +1063,7 @@ static int tegra3_cpu_cmplx_clk_set_parent(struct clk *c, struct clk *p) if (ret) { pr_err("%s: Failed to set rate %lu for %s\n", __func__, rate, p->name); + clk_disable(cpu_mode_sclk); return ret; } @@ -1075,6 +1079,7 @@ static int tegra3_cpu_cmplx_clk_set_parent(struct clk *c, struct clk *p) clk_disable(p); pr_err("%s: Failed to switch %s mode to %s\n", __func__, c->name, p->name); + clk_disable(cpu_mode_sclk); return ret; } @@ -1083,6 +1088,7 @@ static int tegra3_cpu_cmplx_clk_set_parent(struct clk *c, struct clk *p) clk_disable(c->parent); clk_reparent(c, p); + clk_disable(cpu_mode_sclk); return 0; } @@ -1398,11 +1404,11 @@ static int tegra3_pll_clk_wait_for_lock(struct clk *c, u32 lock_reg, u32 lock_bi #if USE_PLL_LOCK_BITS int i; for (i = 0; i < c->u.pll.lock_delay; i++) { + udelay(2); /* timeout = 2 * lock time */ if (clk_readl(lock_reg) & lock_bit) { udelay(PLL_POST_LOCK_DELAY); return 0; } - udelay(2); /* timeout = 2 * lock time */ } pr_err("Timed out waiting for lock bit on pll %s", c->name); return -1; @@ -1559,6 +1565,7 @@ static int tegra3_pll_clk_enable(struct clk *c) val = pmc_readl(PMC_PLLP_WB0_OVERRIDE); val |= PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE; pmc_writel(val, PMC_PLLP_WB0_OVERRIDE); + pmc_readl(PMC_PLLP_WB0_OVERRIDE); } tegra3_pll_clk_wait_for_lock(c, c->reg + PLL_BASE, PLL_BASE_LOCK); @@ -3076,6 +3083,7 @@ static int tegra3_clk_shared_bus_update(struct clk *bus) unsigned long rate = bus->min_rate; unsigned long bw = 0; unsigned long ceiling = bus->max_rate; + u8 emc_bw_efficiency = tegra_emc_bw_efficiency_boost; if (detach_shared_bus) return 0; @@ -3089,6 +3097,9 @@ static int tegra3_clk_shared_bus_update(struct clk *bus) */ if (c->u.shared_bus_user.enabled || (c->u.shared_bus_user.mode == SHARED_CEILING)) { + if (!strcmp(c->name, "3d.emc")) + emc_bw_efficiency = tegra_emc_bw_efficiency; + switch (c->u.shared_bus_user.mode) { case SHARED_BW: if (bw < bus->max_rate) @@ -3108,8 +3119,8 @@ static int tegra3_clk_shared_bus_update(struct clk *bus) if (bw) { if (bus->flags & PERIPH_EMC_ENB) { - bw = tegra_emc_bw_efficiency ? - (bw / tegra_emc_bw_efficiency) : bus->max_rate; + bw = emc_bw_efficiency ? + (bw / emc_bw_efficiency) : bus->max_rate; bw = (bw < bus->max_rate / 100) ? (bw * 100) : bus->max_rate; } @@ -4224,18 +4235,21 @@ static struct clk tegra_clk_emc_bridge = { .parent = &tegra_clk_emc, }; +static RAW_NOTIFIER_HEAD(cbus_rate_change_nh); + static struct clk tegra_clk_cbus = { .name = "cbus", .parent = &tegra_pll_c, .ops = &tegra_clk_cbus_ops, .max_rate = 700000000, .mul = 1, - .div = 2, + .div = CONFIG_TEGRA_CBUS_CLOCK_DIVIDER, .flags = PERIPH_ON_CBUS, .shared_bus_backup = { .input = &tegra_pll_p, .value = 2, - } + }, + .rate_change_nh = &cbus_rate_change_nh, }; #define PERIPH_CLK(_name, _dev, _con, _clk_num, _reg, _max, _inputs, _flags) \ @@ -4293,7 +4307,7 @@ struct clk tegra_list_clks[] = { PERIPH_CLK("rtc", "rtc-tegra", NULL, 4, 0, 32768, mux_clk_32k, PERIPH_NO_RESET | PERIPH_ON_APB), PERIPH_CLK("kbc", "tegra-kbc", NULL, 36, 0, 32768, mux_clk_32k, PERIPH_NO_RESET | PERIPH_ON_APB), PERIPH_CLK("timer", "timer", NULL, 5, 0, 26000000, mux_clk_m, 0), - PERIPH_CLK("kfuse", "kfuse-tegra", NULL, 40, 0, 26000000, mux_clk_m, 0), + PERIPH_CLK("kfuse", "kfuse-tegra", NULL, 40, 0, 26000000, mux_clk_m, PERIPH_ON_APB), PERIPH_CLK("fuse", "fuse-tegra", "fuse", 39, 0, 26000000, mux_clk_m, PERIPH_ON_APB), PERIPH_CLK("fuse_burn", "fuse-tegra", "fuse_burn", 39, 0, 26000000, mux_clk_m, PERIPH_ON_APB), PERIPH_CLK("apbif", "tegra30-ahub", "apbif", 107, 0, 26000000, mux_clk_m, PERIPH_ON_APB), @@ -4306,9 +4320,9 @@ struct clk tegra_list_clks[] = { PERIPH_CLK("spdif_in", "tegra30-spdif", "spdif_in", 10, 0x10c, 100000000, mux_pllp_pllc_pllm, MUX | DIV_U71 | PERIPH_ON_APB), PERIPH_CLK("pwm", "pwm", NULL, 17, 0x110, 408000000, mux_pllp_pllc_clk32_clkm, MUX | MUX_PWM | DIV_U71 | PERIPH_ON_APB), PERIPH_CLK("d_audio", "tegra30-ahub", "d_audio", 106, 0x3d0, 48000000, mux_plla_pllc_pllp_clkm, MUX | DIV_U71 | PERIPH_ON_APB), - PERIPH_CLK("dam0", "tegra30-dam.0", NULL, 108, 0x3d8, 48000000, mux_plla_pllc_pllp_clkm, MUX | DIV_U71), - PERIPH_CLK("dam1", "tegra30-dam.1", NULL, 109, 0x3dc, 48000000, mux_plla_pllc_pllp_clkm, MUX | DIV_U71), - PERIPH_CLK("dam2", "tegra30-dam.2", NULL, 110, 0x3e0, 48000000, mux_plla_pllc_pllp_clkm, MUX | DIV_U71), + PERIPH_CLK("dam0", "tegra30-dam.0", NULL, 108, 0x3d8, 48000000, mux_plla_pllc_pllp_clkm, MUX | DIV_U71 | PERIPH_ON_APB), + PERIPH_CLK("dam1", "tegra30-dam.1", NULL, 109, 0x3dc, 48000000, mux_plla_pllc_pllp_clkm, MUX | DIV_U71 | PERIPH_ON_APB), + PERIPH_CLK("dam2", "tegra30-dam.2", NULL, 110, 0x3e0, 48000000, mux_plla_pllc_pllp_clkm, MUX | DIV_U71 | PERIPH_ON_APB), PERIPH_CLK("hda", "tegra30-hda", "hda", 125, 0x428, 108000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | PERIPH_ON_APB), PERIPH_CLK("hda2codec_2x", "tegra30-hda", "hda2codec", 111, 0x3e4, 48000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | PERIPH_ON_APB), PERIPH_CLK("hda2hdmi", "tegra30-hda", "hda2hdmi", 128, 0, 48000000, mux_clk_m, PERIPH_ON_APB), @@ -4318,36 +4332,36 @@ struct clk tegra_list_clks[] = { PERIPH_CLK("sbc4", "spi_tegra.3", "spi", 68, 0x1b4, 160000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | PERIPH_ON_APB), PERIPH_CLK("sbc5", "spi_tegra.4", "spi", 104, 0x3c8, 160000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | PERIPH_ON_APB), PERIPH_CLK("sbc6", "spi_tegra.5", "spi", 105, 0x3cc, 160000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | PERIPH_ON_APB), - PERIPH_CLK("sata_oob", "tegra_sata_oob", NULL, 123, 0x420, 216000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), - PERIPH_CLK("sata", "tegra_sata", NULL, 124, 0x424, 216000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), - PERIPH_CLK("sata_cold", "tegra_sata_cold", NULL, 129, 0, 48000000, mux_clk_m, 0), - PERIPH_CLK_EX("ndflash","tegra_nand", NULL, 13, 0x160, 240000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71, &tegra_nand_clk_ops), - PERIPH_CLK("ndspeed", "tegra_nand_speed", NULL, 80, 0x3f8, 240000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), + PERIPH_CLK("sata_oob", "tegra_sata_oob", NULL, 123, 0x420, 216000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | PERIPH_ON_APB), + PERIPH_CLK("sata", "tegra_sata", NULL, 124, 0x424, 216000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | PERIPH_ON_APB), + PERIPH_CLK("sata_cold", "tegra_sata_cold", NULL, 129, 0, 48000000, mux_clk_m, PERIPH_ON_APB), + PERIPH_CLK_EX("ndflash", "tegra_nand", NULL, 13, 0x160, 240000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | PERIPH_ON_APB, &tegra_nand_clk_ops), + PERIPH_CLK("ndspeed", "tegra_nand_speed", NULL, 80, 0x3f8, 240000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | PERIPH_ON_APB), PERIPH_CLK("vfir", "vfir", NULL, 7, 0x168, 72000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | PERIPH_ON_APB), PERIPH_CLK("sdmmc1", "sdhci-tegra.0", NULL, 14, 0x150, 208000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage */ - PERIPH_CLK("sdmmc2", "sdhci-tegra.1", NULL, 9, 0x154, 104000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage */ + PERIPH_CLK("sdmmc2", "sdhci-tegra.1", NULL, 9, 0x154, 50000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage */ PERIPH_CLK("sdmmc3", "sdhci-tegra.2", NULL, 69, 0x1bc, 208000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage */ - PERIPH_CLK("sdmmc4", "sdhci-tegra.3", NULL, 15, 0x164, 104000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage */ + PERIPH_CLK("sdmmc4", "sdhci-tegra.3", NULL, 15, 0x164, 102000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage */ PERIPH_CLK("vcp", "tegra-avp", "vcp", 29, 0, 250000000, mux_clk_m, 0), PERIPH_CLK("bsea", "tegra-avp", "bsea", 62, 0, 250000000, mux_clk_m, 0), PERIPH_CLK("bsev", "tegra-aes", "bsev", 63, 0, 250000000, mux_clk_m, 0), - PERIPH_CLK("cec", "tegra_cec", NULL, 136, 0, 26000000, mux_clk_m, PERIPH_ON_APB), + PERIPH_CLK("cec", "tegra_cec", NULL, 136, 0, 26000000, mux_clk_m, PERIPH_ON_APB), PERIPH_CLK("vde", "vde", NULL, 61, 0x1c8, 600000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | DIV_U71_INT), - PERIPH_CLK("csite", "csite", NULL, 73, 0x1d4, 144000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* max rate ??? */ - PERIPH_CLK("la", "la", NULL, 76, 0x1f8, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), + PERIPH_CLK("csite", "csite", NULL, 73, 0x1d4, 144000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | PERIPH_ON_APB), /* max rate ??? */ + PERIPH_CLK("la", "la", NULL, 76, 0x1f8, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | PERIPH_ON_APB), PERIPH_CLK("owr", "tegra_w1", NULL, 71, 0x1cc, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | PERIPH_ON_APB), PERIPH_CLK("nor", "tegra-nor", NULL, 42, 0x1d0, 127000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* requires min voltage */ PERIPH_CLK("mipi", "mipi", NULL, 50, 0x174, 60000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | PERIPH_ON_APB), /* scales with voltage */ - PERIPH_CLK("i2c1", "tegra-i2c.0", "i2c-div", 12, 0x124, 26000000, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB), - PERIPH_CLK("i2c2", "tegra-i2c.1", "i2c-div", 54, 0x198, 26000000, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB), - PERIPH_CLK("i2c3", "tegra-i2c.2", "i2c-div", 67, 0x1b8, 26000000, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB), - PERIPH_CLK("i2c4", "tegra-i2c.3", "i2c-div", 103, 0x3c4, 26000000, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB), - PERIPH_CLK("i2c5", "tegra-i2c.4", "i2c-div", 47, 0x128, 26000000, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB), - PERIPH_CLK("i2c1-fast", "tegra-i2c.0", "i2c-fast", 0, 0, 108000000, mux_pllp_out3, PERIPH_NO_ENB), - PERIPH_CLK("i2c2-fast", "tegra-i2c.1", "i2c-fast", 0, 0, 108000000, mux_pllp_out3, PERIPH_NO_ENB), - PERIPH_CLK("i2c3-fast", "tegra-i2c.2", "i2c-fast", 0, 0, 108000000, mux_pllp_out3, PERIPH_NO_ENB), - PERIPH_CLK("i2c4-fast", "tegra-i2c.3", "i2c-fast", 0, 0, 108000000, mux_pllp_out3, PERIPH_NO_ENB), - PERIPH_CLK("i2c5-fast", "tegra-i2c.4", "i2c-fast", 0, 0, 108000000, mux_pllp_out3, PERIPH_NO_ENB), + PERIPH_CLK("i2c1", "tegra-i2c.0", "div-clk", 12, 0x124, 26000000, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB), + PERIPH_CLK("i2c2", "tegra-i2c.1", "div-clk", 54, 0x198, 26000000, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB), + PERIPH_CLK("i2c3", "tegra-i2c.2", "div-clk", 67, 0x1b8, 26000000, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB), + PERIPH_CLK("i2c4", "tegra-i2c.3", "div-clk", 103, 0x3c4, 26000000, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB), + PERIPH_CLK("i2c5", "tegra-i2c.4", "div-clk", 47, 0x128, 26000000, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB), + PERIPH_CLK("i2c1-fast", "tegra-i2c.0", "fast-clk", 0, 0, 108000000, mux_pllp_out3, PERIPH_NO_ENB), + PERIPH_CLK("i2c2-fast", "tegra-i2c.1", "fast-clk", 0, 0, 108000000, mux_pllp_out3, PERIPH_NO_ENB), + PERIPH_CLK("i2c3-fast", "tegra-i2c.2", "fast-clk", 0, 0, 108000000, mux_pllp_out3, PERIPH_NO_ENB), + PERIPH_CLK("i2c4-fast", "tegra-i2c.3", "fast-clk", 0, 0, 108000000, mux_pllp_out3, PERIPH_NO_ENB), + PERIPH_CLK("i2c5-fast", "tegra-i2c.4", "fast-clk", 0, 0, 108000000, mux_pllp_out3, PERIPH_NO_ENB), PERIPH_CLK("uarta", "tegra_uart.0", NULL, 6, 0x178, 900000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U151 | DIV_U151_UART | PERIPH_ON_APB), PERIPH_CLK("uartb", "tegra_uart.1", NULL, 7, 0x17c, 900000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U151 | DIV_U151_UART | PERIPH_ON_APB), PERIPH_CLK("uartc", "tegra_uart.2", NULL, 55, 0x1a0, 900000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U151 | DIV_U151_UART | PERIPH_ON_APB), @@ -4368,7 +4382,7 @@ struct clk tegra_list_clks[] = { PERIPH_CLK("host1x", "host1x", NULL, 28, 0x180, 300000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | DIV_U71_INT), PERIPH_CLK("cve", "cve", NULL, 49, 0x140, 250000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), /* requires min voltage */ PERIPH_CLK("tvo", "tvo", NULL, 49, 0x188, 250000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), /* requires min voltage */ - PERIPH_CLK_EX("dtv", "dtv", NULL, 79, 0x1dc, 250000000, mux_clk_m, 0, &tegra_dtv_clk_ops), + PERIPH_CLK_EX("dtv", "dtv", NULL, 79, 0x1dc, 250000000, mux_clk_m, PERIPH_ON_APB, &tegra_dtv_clk_ops), PERIPH_CLK("hdmi", "hdmi", NULL, 51, 0x18c, 148500000, mux_pllp_pllm_plld_plla_pllc_plld2_clkm, MUX | MUX8 | DIV_U71), PERIPH_CLK("tvdac", "tvdac", NULL, 53, 0x194, 220000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), /* requires min voltage */ PERIPH_CLK("disp1", "tegradc.0", NULL, 27, 0x138, 600000000, mux_pllp_pllm_plld_plla_pllc_plld2_clkm, MUX | MUX8), @@ -4384,7 +4398,7 @@ struct clk tegra_list_clks[] = { PERIPH_CLK("isp", "tegra_camera", "isp", 23, 0, 150000000, mux_clk_m, 0), /* same frequency as VI */ PERIPH_CLK("csus", "tegra_camera", "csus", 92, 0, 150000000, mux_clk_m, PERIPH_NO_RESET), - PERIPH_CLK("tsensor", "tegra-tsensor", NULL, 100, 0x3b8, 216000000, mux_pllp_pllc_clkm_clk32, MUX | DIV_U71), + PERIPH_CLK("tsensor", "tegra-tsensor", NULL, 100, 0x3b8, 216000000, mux_pllp_pllc_clkm_clk32, MUX | DIV_U71 | PERIPH_ON_APB), PERIPH_CLK("actmon", "actmon", NULL, 119, 0x3e8, 216000000, mux_pllp_pllc_clk32_clkm, MUX | DIV_U71), PERIPH_CLK("extern1", "extern1", NULL, 120, 0x3ec, 216000000, mux_plla_clk32_pllp_clkm_plle, MUX | MUX8 | DIV_U71), PERIPH_CLK("extern2", "extern2", NULL, 121, 0x3f0, 216000000, mux_plla_clk32_pllp_clkm_plle, MUX | MUX8 | DIV_U71), @@ -4392,7 +4406,7 @@ struct clk tegra_list_clks[] = { PERIPH_CLK("i2cslow", "i2cslow", NULL, 81, 0x3fc, 26000000, mux_pllp_pllc_clk32_clkm, MUX | DIV_U71 | PERIPH_ON_APB), PERIPH_CLK("pcie", "tegra-pcie", "pcie", 70, 0, 250000000, mux_clk_m, 0), PERIPH_CLK("afi", "tegra-pcie", "afi", 72, 0, 250000000, mux_clk_m, 0), - PERIPH_CLK("se", "se", NULL, 127, 0x42c, 625000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | DIV_U71_INT), + PERIPH_CLK("se", "se", NULL, 127, 0x42c, 625000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | DIV_U71_INT | PERIPH_ON_APB), PERIPH_CLK("mselect", "mselect", NULL, 99, 0x3b4, 108000000, mux_pllp_clkm, MUX | DIV_U71), SHARED_CLK("avp.sclk", "tegra-avp", "sclk", &tegra_clk_sbus_cmplx, NULL, 0, 0), @@ -4401,7 +4415,8 @@ struct clk tegra_list_clks[] = { SHARED_CLK("usb1.sclk", "tegra-ehci.0", "sclk", &tegra_clk_sbus_cmplx, NULL, 0, 0), SHARED_CLK("usb2.sclk", "tegra-ehci.1", "sclk", &tegra_clk_sbus_cmplx, NULL, 0, 0), SHARED_CLK("usb3.sclk", "tegra-ehci.2", "sclk", &tegra_clk_sbus_cmplx, NULL, 0, 0), - SHARED_CLK("wake.sclk", "wake_sclk", "sclk", &tegra_clk_sbus_cmplx, NULL, 0, 0), + SHARED_CLK("wake.sclk", "wake_sclk", "sclk", &tegra_clk_sbus_cmplx, NULL, 0, 0), + SHARED_CLK("cpu_mode.sclk","cpu_mode", "sclk", &tegra_clk_sbus_cmplx, NULL, 0, 0), SHARED_CLK("mon.avp", "tegra_actmon", "avp", &tegra_clk_sbus_cmplx, NULL, 0, 0), SHARED_CLK("cap.sclk", "cap_sclk", NULL, &tegra_clk_sbus_cmplx, NULL, 0, SHARED_CEILING), SHARED_CLK("floor.sclk", "floor_sclk", NULL, &tegra_clk_sbus_cmplx, NULL, 0, 0), @@ -4437,8 +4452,11 @@ struct clk tegra_list_clks[] = { SHARED_CLK("epp.cbus", "tegra_gr2d", "epp", &tegra_clk_cbus, "epp", 0, 0), SHARED_CLK("mpe.cbus", "tegra_mpe", "mpe", &tegra_clk_cbus, "mpe", 0, 0), SHARED_CLK("vde.cbus", "tegra-avp", "vde", &tegra_clk_cbus, "vde", 0, 0), +#ifdef CONFIG_TEGRA_SE_ON_CBUS SHARED_CLK("se.cbus", "tegra-se", NULL, &tegra_clk_cbus, "se", 0, 0), +#endif SHARED_CLK("cap.cbus", "cap.cbus", NULL, &tegra_clk_cbus, NULL, 0, SHARED_CEILING), + SHARED_CLK("cap.profile.cbus", "profile.cbus", NULL, &tegra_clk_cbus, NULL, 0, SHARED_CEILING), SHARED_CLK("floor.cbus", "floor.cbus", NULL, &tegra_clk_cbus, NULL, 0, 0), }; @@ -5468,6 +5486,7 @@ void __init tegra_soc_init_clocks(void) tegra3_init_one_clock(&tegra_clk_out_list[i]); emc_bridge = &tegra_clk_emc_bridge; + cpu_mode_sclk = tegra_get_clock_by_name("cpu_mode.sclk"); /* Initialize to default */ tegra_init_cpu_edp_limits(0); diff --git a/arch/arm/mach-tegra/tegra3_dvfs.c b/arch/arm/mach-tegra/tegra3_dvfs.c index 5af1b44cd99c..feb69a4621ed 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-2012, NVIDIA Corporation. + * Copyright (C) 2010-2012, NVIDIA CORPORATION. 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 @@ -21,6 +21,7 @@ #include <linux/clk.h> #include <linux/kobject.h> #include <linux/err.h> +#include <linux/time.h> #include "clock.h" #include "dvfs.h" @@ -28,15 +29,19 @@ #include "board.h" #include "tegra3_emc.h" +#define CPU_MILLIVOLTS {\ + 750, 762, 775, 787, 800, 825, 837, 850, 862, 875, 887, 900, 912, 916, 925, 937, 950, 962, 975, 987, 1000, 1007, 1012, 1025, 1037, 1050, 1062, 1075, 1087, 1100, 1112, 1125, 1137, 1150, 1162, 1175, 1187, 1200, 1212, 1237}; + static bool tegra_dvfs_cpu_disabled; static bool tegra_dvfs_core_disabled; static struct dvfs *cpu_dvfs; -static const int cpu_millivolts[MAX_DVFS_FREQS] = { - 800, 825, 850, 875, 900, 916, 950, 975, 1000, 1007, 1025, 1050, 1075, 1100, 1125, 1150, 1175, 1200, 1212, 1237}; +static int cpu_millivolts[MAX_DVFS_FREQS] = CPU_MILLIVOLTS; + +static const int cpu_millivolts_aged[MAX_DVFS_FREQS] = CPU_MILLIVOLTS; static const unsigned int cpu_cold_offs_mhz[MAX_DVFS_FREQS] = { - 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50}; + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50}; static const int core_millivolts[MAX_DVFS_FREQS] = { 950, 1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350}; @@ -54,7 +59,7 @@ static int cpu_below_core = VDD_CPU_BELOW_VDD_CORE; static struct dvfs_rail tegra3_dvfs_rail_vdd_cpu = { .reg_id = "vdd_cpu", .max_millivolts = 1250, - .min_millivolts = 800, + .min_millivolts = 725, .step = VDD_SAFE_STEP, .jmp_to_zero = true, }; @@ -141,59 +146,59 @@ static struct dvfs_relationship tegra3_dvfs_relationships[] = { } static struct dvfs cpu_dvfs_table[] = { - /* Cpu voltages (mV): 800, 825, 850, 875, 900, 916, 950, 975, 1000, 1007, 1025, 1050, 1075, 1100, 1125, 1150, 1175, 1200, 1212, 1237 */ - CPU_DVFS("cpu_g", 0, 0, MHZ, 1, 1, 684, 684, 817, 817, 817, 1026, 1102, 1102, 1149, 1187, 1225, 1282, 1300), - CPU_DVFS("cpu_g", 0, 1, MHZ, 1, 1, 807, 807, 948, 948, 948, 1117, 1171, 1171, 1206, 1300), - CPU_DVFS("cpu_g", 0, 2, MHZ, 1, 1, 883, 883, 1039, 1039, 1039, 1178, 1206, 1206, 1300), - CPU_DVFS("cpu_g", 0, 3, MHZ, 1, 1, 931, 931, 1102, 1102, 1102, 1216, 1300, 1300), - - CPU_DVFS("cpu_g", 1, 0, MHZ, 460, 460, 550, 550, 680, 680, 680, 820, 970, 970, 1040, 1080, 1150, 1200, 1280, 1300), - CPU_DVFS("cpu_g", 1, 1, MHZ, 480, 480, 650, 650, 780, 780, 780, 990, 1040, 1040, 1100, 1200, 1300), - CPU_DVFS("cpu_g", 1, 2, MHZ, 520, 520, 700, 700, 860, 860, 860, 1050, 1150, 1150, 1200, 1300), - CPU_DVFS("cpu_g", 1, 3, MHZ, 550, 550, 770, 770, 910, 910, 910, 1150, 1230, 1230, 1300), - - CPU_DVFS("cpu_g", 2, 1, MHZ, 480, 480, 650, 650, 780, 780, 780, 990, 1040, 1040, 1100, 1200, 1250, 1300, 1330, 1400), - CPU_DVFS("cpu_g", 2, 2, MHZ, 520, 520, 700, 700, 860, 860, 860, 1050, 1150, 1150, 1200, 1280, 1300, 1350, 1400), - CPU_DVFS("cpu_g", 2, 3, MHZ, 550, 550, 770, 770, 910, 910, 910, 1150, 1230, 1230, 1280, 1300, 1350, 1400), - - CPU_DVFS("cpu_g", 3, 1, MHZ, 480, 480, 650, 650, 780, 780, 780, 990, 1040, 1040, 1100, 1200, 1250, 1300, 1330, 1400), - CPU_DVFS("cpu_g", 3, 2, MHZ, 520, 520, 700, 700, 860, 860, 860, 1050, 1150, 1150, 1200, 1280, 1300, 1350, 1400), - CPU_DVFS("cpu_g", 3, 3, MHZ, 550, 550, 770, 770, 910, 910, 910, 1150, 1230, 1230, 1280, 1300, 1350, 1400), - - CPU_DVFS("cpu_g", 4, 0, MHZ, 460, 460, 550, 550, 680, 680, 680, 820, 970, 970, 1040, 1080, 1150, 1200, 1240, 1280, 1320, 1360, 1360, 1500), - CPU_DVFS("cpu_g", 4, 1, MHZ, 480, 480, 650, 650, 780, 780, 780, 990, 1040, 1040, 1100, 1200, 1250, 1300, 1330, 1360, 1400, 1500), - CPU_DVFS("cpu_g", 4, 2, MHZ, 520, 520, 700, 700, 860, 860, 860, 1050, 1150, 1150, 1200, 1280, 1300, 1340, 1380, 1500), - CPU_DVFS("cpu_g", 4, 3, MHZ, 550, 550, 770, 770, 910, 910, 910, 1150, 1230, 1230, 1280, 1330, 1370, 1400, 1500), - - CPU_DVFS("cpu_g", 5, 3, MHZ, 550, 550, 770, 770, 910, 910, 910, 1150, 1230, 1230, 1280, 1330, 1370, 1400, 1470, 1500, 1500, 1540, 1540, 1700), - CPU_DVFS("cpu_g", 5, 4, MHZ, 550, 550, 770, 770, 940, 940, 940, 1160, 1240, 1240, 1280, 1360, 1390, 1470, 1500, 1520, 1520, 1590, 1700), - - CPU_DVFS("cpu_g", 6, 3, MHZ, 550, 550, 770, 770, 910, 910, 910, 1150, 1230, 1230, 1280, 1330, 1370, 1400, 1470, 1500, 1500, 1540, 1540, 1700), - CPU_DVFS("cpu_g", 6, 4, MHZ, 550, 550, 770, 770, 940, 940, 940, 1160, 1240, 1240, 1280, 1360, 1390, 1470, 1500, 1520, 1520, 1590, 1700), - - CPU_DVFS("cpu_g", 7, 0, MHZ, 460, 460, 550, 550, 680, 680, 680, 820, 970, 970, 1040, 1080, 1150, 1200, 1280, 1300), - CPU_DVFS("cpu_g", 7, 1, MHZ, 480, 480, 650, 650, 780, 780, 780, 990, 1040, 1040, 1100, 1200, 1300), - CPU_DVFS("cpu_g", 7, 2, MHZ, 520, 520, 700, 700, 860, 860, 860, 1050, 1150, 1150, 1200, 1300), - CPU_DVFS("cpu_g", 7, 3, MHZ, 550, 550, 770, 770, 910, 910, 910, 1150, 1230, 1230, 1300), - CPU_DVFS("cpu_g", 7, 4, MHZ, 550, 550, 770, 770, 940, 940, 940, 1160, 1300, 1300), - - CPU_DVFS("cpu_g", 8, 0, MHZ, 460, 460, 550, 550, 680, 680, 680, 820, 970, 970, 1040, 1080, 1150, 1200, 1280, 1300), - CPU_DVFS("cpu_g", 8, 1, MHZ, 480, 480, 650, 650, 780, 780, 780, 990, 1040, 1040, 1100, 1200, 1300), - CPU_DVFS("cpu_g", 8, 2, MHZ, 520, 520, 700, 700, 860, 860, 860, 1050, 1150, 1150, 1200, 1300), - CPU_DVFS("cpu_g", 8, 3, MHZ, 550, 550, 770, 770, 910, 910, 910, 1150, 1230, 1230, 1300), - CPU_DVFS("cpu_g", 8, 4, MHZ, 550, 550, 770, 770, 940, 940, 940, 1160, 1300, 1300), - - CPU_DVFS("cpu_g", 9, -1, MHZ, 1, 1, 1, 1, 1, 1, 1, 1, 1, 900, 900, 900, 900, 900, 900, 900), - CPU_DVFS("cpu_g", 10, -1, MHZ, 1, 1, 1, 1, 1, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900), - CPU_DVFS("cpu_g", 11, -1, MHZ, 1, 1, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600), - CPU_DVFS("cpu_g", 14, -1, MHZ, 1, 1, 1, 1, 1, 1, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900), - CPU_DVFS("cpu_g", 15, -1, MHZ, 1, 1, 1, 1, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900), - - CPU_DVFS("cpu_g", 12, 3, MHZ, 550, 550, 770, 770, 910, 910, 910, 1150, 1230, 1230, 1280, 1330, 1370, 1400, 1470, 1500, 1500, 1540, 1540, 1700), - CPU_DVFS("cpu_g", 12, 4, MHZ, 550, 550, 770, 770, 940, 940, 940, 1160, 1240, 1240, 1280, 1360, 1390, 1470, 1500, 1520, 1520, 1590, 1700), - - CPU_DVFS("cpu_g", 13, 3, MHZ, 550, 550, 770, 770, 910, 910, 910, 1150, 1230, 1230, 1280, 1330, 1370, 1400, 1470, 1500, 1500, 1540, 1540, 1700), - CPU_DVFS("cpu_g", 13, 4, MHZ, 550, 550, 770, 770, 940, 940, 940, 1160, 1240, 1240, 1280, 1360, 1390, 1470, 1500, 1520, 1520, 1590, 1700), + /* Cpu voltages (mV): 750, 762, 775, 787, 800, 825, 837, 850, 862, 875, 887, 900, 912, 916, 925, 937, 950, 962, 975, 987, 1000, 1007, 1012, 1025, 1037, 1050, 1062, 1075, 1087, 1100, 1112, 1125, 1137, 1150, 1162, 1175, 1187, 1200, 1212, 1237 */ + CPU_DVFS("cpu_g", 0, 0, MHZ, 1, 1, 1, 1, 1, 1, 1, 684, 684, 684, 684, 817, 817, 817, 817, 817, 817, 817, 1026, 1026, 1102, 1102, 1102, 1149, 1149, 1187, 1187, 1225, 1225, 1282, 1282, 1300), + CPU_DVFS("cpu_g", 0, 1, MHZ, 1, 1, 1, 1, 1, 1, 1, 807, 807, 807, 807, 948, 948, 948, 948, 948, 948, 948, 1117, 1117, 1171, 1171, 1171, 1206, 1206, 1300), + CPU_DVFS("cpu_g", 0, 2, MHZ, 1, 1, 1, 1, 1, 1, 1, 883, 883, 883, 883, 1039, 1039, 1039, 1039, 1039, 1039, 1039, 1178, 1178, 1206, 1206, 1206, 1300), + CPU_DVFS("cpu_g", 0, 3, MHZ, 1, 1, 1, 1, 1, 1, 1, 931, 931, 931, 931, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1216, 1216, 1300, 1300, 1300), + + CPU_DVFS("cpu_g", 1, 0, MHZ, 1, 1, 1, 1, 460, 460, 460, 550, 550, 550, 550, 680, 680, 680, 680, 680, 680, 680, 820, 820, 970, 970, 970, 1040, 1040, 1080, 1080, 1150, 1150, 1200, 1200, 1280, 1280, 1300), + CPU_DVFS("cpu_g", 1, 1, MHZ, 1, 1, 1, 1, 480, 480, 480, 650, 650, 650, 650, 780, 780, 780, 780, 780, 780, 780, 990, 990, 1040, 1040, 1040, 1100, 1100, 1200, 1200, 1300), + CPU_DVFS("cpu_g", 1, 2, MHZ, 1, 1, 1, 1, 520, 520, 520, 700, 700, 700, 700, 860, 860, 860, 860, 860, 860, 860, 1050, 1050, 1150, 1150, 1150, 1200, 1200, 1300), + CPU_DVFS("cpu_g", 1, 3, MHZ, 1, 1, 1, 1, 550, 550, 550, 770, 770, 770, 770, 910, 910, 910, 910, 910, 910, 910, 1150, 1150, 1230, 1230, 1230, 1300), + + CPU_DVFS("cpu_g", 2, 1, MHZ, 1, 1, 1, 1, 480, 480, 480, 650, 650, 650, 650, 780, 780, 780, 780, 780, 780, 780, 990, 990, 1040, 1040, 1040, 1100, 1100, 1200, 1200, 1250, 1250, 1300, 1300, 1330, 1330, 1400), + CPU_DVFS("cpu_g", 2, 2, MHZ, 1, 1, 1, 1, 520, 520, 520, 700, 700, 700, 700, 860, 860, 860, 860, 860, 860, 860, 1050, 1050, 1150, 1150, 1150, 1200, 1200, 1280, 1280, 1300, 1300, 1350, 1350, 1400), + CPU_DVFS("cpu_g", 2, 3, MHZ, 1, 1, 1, 1, 550, 550, 550, 770, 770, 770, 770, 910, 910, 910, 910, 910, 910, 910, 1150, 1150, 1230, 1230, 1230, 1280, 1280, 1300, 1300, 1350, 1350, 1400), + + CPU_DVFS("cpu_g", 3, 1, MHZ, 1, 1, 1, 1, 480, 480, 480, 650, 650, 650, 650, 780, 780, 780, 780, 780, 780, 780, 990, 990, 1040, 1040, 1040, 1100, 1100, 1200, 1200, 1250, 1250, 1300, 1300, 1330, 1330, 1400), + CPU_DVFS("cpu_g", 3, 2, MHZ, 1, 1, 1, 1, 520, 520, 520, 700, 700, 700, 700, 860, 860, 860, 860, 860, 860, 860, 1050, 1050, 1150, 1150, 1150, 1200, 1200, 1280, 1280, 1300, 1300, 1350, 1350, 1400), + CPU_DVFS("cpu_g", 3, 3, MHZ, 1, 1, 1, 1, 550, 550, 550, 770, 770, 770, 770, 910, 910, 910, 910, 910, 910, 910, 1150, 1150, 1230, 1230, 1230, 1280, 1280, 1300, 1300, 1350, 1350, 1400), + + CPU_DVFS("cpu_g", 4, 0, MHZ, 1, 1, 1, 1, 460, 460, 460, 550, 550, 550, 550, 680, 680, 680, 680, 680, 680, 680, 820, 820, 970, 970, 970, 1040, 1040, 1080, 1080, 1150, 1150, 1200, 1200, 1240, 1240, 1280, 1280, 1320, 1320, 1360, 1360, 1500), + CPU_DVFS("cpu_g", 4, 1, MHZ, 1, 1, 1, 1, 480, 480, 480, 650, 650, 650, 650, 780, 780, 780, 780, 780, 780, 780, 990, 990, 1040, 1040, 1040, 1100, 1100, 1200, 1200, 1250, 1250, 1300, 1300, 1330, 1330, 1360, 1360, 1400, 1400, 1500), + CPU_DVFS("cpu_g", 4, 2, MHZ, 1, 1, 1, 1, 520, 520, 520, 700, 700, 700, 700, 860, 860, 860, 860, 860, 860, 860, 1050, 1050, 1150, 1150, 1150, 1200, 1200, 1280, 1280, 1300, 1300, 1340, 1340, 1380, 1380, 1500), + CPU_DVFS("cpu_g", 4, 3, MHZ, 1, 1, 1, 1, 550, 550, 550, 770, 770, 770, 770, 910, 910, 910, 910, 910, 910, 910, 1150, 1150, 1230, 1230, 1230, 1280, 1280, 1330, 1330, 1370, 1370, 1400, 1400, 1500), + + CPU_DVFS("cpu_g", 5, 3, MHZ, 1, 1, 1, 1, 550, 550, 550, 770, 770, 770, 770, 910, 910, 910, 910, 910, 910, 910, 1150, 1150, 1230, 1230, 1230, 1280, 1280, 1330, 1330, 1370, 1370, 1400, 1400, 1470, 1470, 1500, 1500, 1500, 1500, 1540, 1540, 1700), + CPU_DVFS("cpu_g", 5, 4, MHZ, 1, 1, 1, 1, 550, 550, 550, 770, 770, 770, 770, 940, 940, 940, 940, 940, 940, 940, 1160, 1160, 1240, 1240, 1240, 1280, 1280, 1360, 1360, 1390, 1390, 1470, 1470, 1500, 1500, 1520, 1520, 1520, 1520, 1590, 1700), + + CPU_DVFS("cpu_g", 6, 3, MHZ, 1, 1, 1, 1, 550, 550, 550, 770, 770, 770, 770, 910, 910, 910, 910, 910, 910, 910, 1150, 1150, 1230, 1230, 1230, 1280, 1280, 1330, 1330, 1370, 1370, 1400, 1400, 1470, 1470, 1500, 1500, 1500, 1500, 1540, 1540, 1700), + CPU_DVFS("cpu_g", 6, 4, MHZ, 1, 1, 1, 1, 550, 550, 550, 770, 770, 770, 770, 940, 940, 940, 940, 940, 940, 940, 1160, 1160, 1240, 1240, 1240, 1280, 1280, 1360, 1360, 1390, 1390, 1470, 1470, 1500, 1500, 1520, 1520, 1520, 1520, 1590, 1700), + + CPU_DVFS("cpu_g", 7, 0, MHZ, 1, 1, 1, 1, 460, 460, 460, 550, 550, 550, 550, 680, 680, 680, 680, 680, 680, 680, 820, 820, 970, 970, 970, 1040, 1040, 1080, 1080, 1150, 1150, 1200, 1200, 1280, 1280, 1300), + CPU_DVFS("cpu_g", 7, 1, MHZ, 1, 1, 1, 1, 480, 480, 480, 650, 650, 650, 650, 780, 780, 780, 780, 780, 780, 780, 990, 990, 1040, 1040, 1040, 1100, 1100, 1200, 1200, 1300), + CPU_DVFS("cpu_g", 7, 2, MHZ, 1, 1, 1, 1, 520, 520, 520, 700, 700, 700, 700, 860, 860, 860, 860, 860, 860, 860, 1050, 1050, 1150, 1150, 1150, 1200, 1200, 1300), + CPU_DVFS("cpu_g", 7, 3, MHZ, 1, 1, 1, 1, 550, 550, 550, 770, 770, 770, 770, 910, 910, 910, 910, 910, 910, 910, 1150, 1150, 1230, 1230, 1230, 1300), + CPU_DVFS("cpu_g", 7, 4, MHZ, 1, 1, 1, 1, 550, 550, 550, 770, 770, 770, 770, 940, 940, 940, 940, 940, 940, 940, 1160, 1160, 1300, 1300, 1300), + + CPU_DVFS("cpu_g", 8, 0, MHZ, 1, 1, 1, 1, 460, 460, 460, 550, 550, 550, 550, 680, 680, 680, 680, 680, 680, 680, 820, 820, 970, 970, 970, 1040, 1040, 1080, 1080, 1150, 1150, 1200, 1200, 1280, 1280, 1300), + CPU_DVFS("cpu_g", 8, 1, MHZ, 1, 1, 1, 1, 480, 480, 480, 650, 650, 650, 650, 780, 780, 780, 780, 780, 780, 780, 990, 990, 1040, 1040, 1040, 1100, 1100, 1200, 1200, 1300), + CPU_DVFS("cpu_g", 8, 2, MHZ, 1, 1, 1, 1, 520, 520, 520, 700, 700, 700, 700, 860, 860, 860, 860, 860, 860, 860, 1050, 1050, 1150, 1150, 1150, 1200, 1200, 1300), + CPU_DVFS("cpu_g", 8, 3, MHZ, 1, 1, 1, 1, 550, 550, 550, 770, 770, 770, 770, 910, 910, 910, 910, 910, 910, 910, 1150, 1150, 1230, 1230, 1230, 1300), + CPU_DVFS("cpu_g", 8, 4, MHZ, 1, 1, 1, 1, 550, 550, 550, 770, 770, 770, 770, 940, 940, 940, 940, 940, 940, 940, 1160, 1160, 1300, 1300, 1300), + + CPU_DVFS("cpu_g", 9, -1, MHZ, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900), + CPU_DVFS("cpu_g", 10, -1, MHZ, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900), + CPU_DVFS("cpu_g", 11, -1, MHZ, 1, 1, 1, 1, 1, 1, 1, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600), + CPU_DVFS("cpu_g", 14, -1, MHZ, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900), + CPU_DVFS("cpu_g", 15, -1, MHZ, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900), + + CPU_DVFS("cpu_g", 12, 3, MHZ, 1, 475, 475, 475, 475, 620, 620, 620, 620, 760, 760, 760, 760, 760, 910, 910, 1000, 1000, 1000, 1000, 1150, 1150, 1150, 1150, 1150, 1300, 1300, 1300, 1300, 1400, 1400, 1400, 1400, 1500, 1500, 1500, 1500, 1500, 1500, 1700), + CPU_DVFS("cpu_g", 12, 4, MHZ, 475, 475, 475, 475, 475, 620, 620, 620, 760, 760, 760, 760, 910, 910, 910, 1000, 1000, 1000, 1000, 1150, 1150, 1150, 1150, 1300, 1300, 1300, 1300, 1400, 1400, 1400, 1400, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1700), + + CPU_DVFS("cpu_g", 13, 3, MHZ, 1, 1, 1, 1, 550, 550, 550, 770, 770, 770, 770, 910, 910, 910, 910, 910, 910, 910, 1150, 1150, 1230, 1230, 1230, 1280, 1280, 1330, 1330, 1370, 1370, 1400, 1400, 1470, 1470, 1500, 1500, 1500, 1500, 1540, 1540, 1700), + CPU_DVFS("cpu_g", 13, 4, MHZ, 1, 1, 1, 1, 550, 550, 550, 770, 770, 770, 770, 940, 940, 940, 940, 940, 940, 940, 1160, 1160, 1240, 1240, 1240, 1280, 1280, 1360, 1360, 1390, 1390, 1470, 1470, 1500, 1500, 1520, 1520, 1520, 1520, 1590, 1700), /* * "Safe entry" to be used when no match for chip speedo, process @@ -203,7 +208,20 @@ static struct dvfs cpu_dvfs_table[] = { }; static struct dvfs cpu_0_dvfs_table[] = { - /* Cpu voltages (mV): 800, 825, 850, 875, 900, 916, 950, 975, 1000, 1007, 1025, 1050, 1075, 1100, 1125, 1150, 1175, 1200, 1212, 1237 */ + /* Cpu voltages (mV): 750, 762, 775, 787, 800, 825, 837, 850, 862, 875, 887, 900, 912, 916, 925, 937, 950, 962, 975, 987, 1000, 1007, 1012, 1025, 1037, 1050, 1062, 1075, 1087, 1100, 1112, 1125, 1137, 1150, 1162, 1175, 1187, 1200, 1212, 1237*/ + CPU_DVFS("cpu_0", 4, 0, MHZ, 1, 1, 1, 475, 475, 475, 475, 640, 640, 640, 760, 760, 760, 760, 860, 860, 860, 860, 860, 1000, 1000, 1000, 1000, 1100, 1100, 1100, 1100, 1200, 1200, 1200, 1200, 1200, 1300, 1300, 1300, 1300, 1400, 1400, 1400, 1500), + CPU_DVFS("cpu_0", 4, 1, MHZ, 1, 475, 475, 475, 475, 640, 640, 640, 760, 760, 760, 860, 860, 860, 860, 860, 1000, 1000, 1000, 1100, 1100, 1100, 1100, 1100, 1200, 1200, 1200, 1300, 1300, 1300, 1300, 1400, 1400, 1400, 1400, 1400, 1400, 1500), + CPU_DVFS("cpu_0", 4, 2, MHZ, 475, 475, 475, 640, 640, 640, 760, 760, 760, 860, 860, 860, 1000, 1000, 1000, 1000, 1000, 1100, 1100, 1200, 1200, 1200, 1200, 1200, 1300, 1300, 1300, 1300, 1400, 1400, 1400, 1400, 1400, 1500), + CPU_DVFS("cpu_0", 4, 3, MHZ, 475, 475, 640, 640, 640, 760, 760, 860, 860, 860, 860, 1000, 1000, 1000, 1100, 1100, 1100, 1100, 1200, 1200, 1200, 1200, 1300, 1300, 1300, 1300, 1400, 1400, 1400, 1400, 1400, 1500), + + CPU_DVFS("cpu_0", 5, 3, MHZ, 475, 475, 620, 620, 620, 760, 760, 760, 910, 910, 910, 1000, 1000, 1000, 1000, 1000, 1000, 1150, 1150, 1150, 1150, 1150, 1300, 1300, 1300, 1300, 1400, 1400, 1400, 1400, 1500, 1500, 1500, 1500, 1500, 1600, 1600, 1600, 1600, 1700), + CPU_DVFS("cpu_0", 5, 4, MHZ, 475, 620, 620, 620, 760, 760, 760, 910, 910, 1000, 1000, 1000, 1000, 1000, 1150, 1150, 1150, 1150, 1150, 1300, 1300, 1300, 1300, 1400, 1400, 1400, 1500, 1500, 1500, 1500, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1700), + + CPU_DVFS("cpu_0", 6, 3, MHZ, 475, 475, 620, 620, 620, 760, 760, 760, 910, 910, 910, 1000, 1000, 1000, 1000, 1000, 1000, 1150, 1150, 1150, 1150, 1150, 1300, 1300, 1300, 1300, 1400, 1400, 1400, 1400, 1500, 1500, 1500, 1500, 1500, 1600, 1600, 1600, 1600, 1700), + CPU_DVFS("cpu_0", 6, 4, MHZ, 475, 620, 620, 620, 760, 760, 760, 910, 910, 1000, 1000, 1000, 1000, 1000, 1150, 1150, 1150, 1150, 1150, 1300, 1300, 1300, 1300, 1400, 1400, 1400, 1500, 1500, 1500, 1500, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1700), + + CPU_DVFS("cpu_0", 12, 3, MHZ, 475, 475, 620, 620, 620, 760, 760, 760, 910, 910, 910, 1000, 1000, 1000, 1000, 1000, 1000, 1150, 1150, 1150, 1150, 1150, 1300, 1300, 1300, 1300, 1400, 1400, 1400, 1400, 1500, 1500, 1500, 1500, 1500, 1600, 1600, 1600, 1600, 1700), + CPU_DVFS("cpu_0", 12, 4, MHZ, 475, 620, 620, 620, 760, 760, 760, 910, 910, 1000, 1000, 1000, 1000, 1000, 1000, 1150, 1150, 1150, 1150, 1300, 1300, 1300, 1300, 1400, 1400, 1400, 1500, 1500, 1500, 1500, 1500, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1700), }; #define CORE_DVFS(_clk_name, _speedo_id, _auto, _mult, _freqs...) \ @@ -305,6 +323,7 @@ static struct dvfs core_dvfs_table[] = { CORE_DVFS("fuse_burn", -1, 1, KHZ, 1, 1, 1, 1, 26000, 26000, 26000, 26000, 26000), CORE_DVFS("sdmmc1", -1, 1, KHZ, 104000, 104000, 104000, 104000, 104000, 208000, 208000, 208000, 208000), CORE_DVFS("sdmmc3", -1, 1, KHZ, 104000, 104000, 104000, 104000, 104000, 208000, 208000, 208000, 208000), + CORE_DVFS("sdmmc4", -1, 1, KHZ, 51000, 102000, 102000, 102000, 102000, 102000, 102000, 102000, 102000), CORE_DVFS("ndflash", -1, 1, KHZ, 120000, 120000, 120000, 120000, 200000, 200000, 200000, 200000, 200000), CORE_DVFS("nor", 0, 1, KHZ, 1, 115000, 130000, 130000, 133000, 133000, 133000, 133000, 133000), @@ -618,6 +637,41 @@ static int __init get_core_nominal_mv_index(int speedo_id) return (i - 1); } +static void tegra_adjust_cpu_mvs(int mvs) +{ + int i; + + BUG_ON(ARRAY_SIZE(cpu_millivolts) != ARRAY_SIZE(cpu_millivolts_aged)); + + for (i = 0; i < ARRAY_SIZE(cpu_millivolts); i++) + cpu_millivolts[i] = cpu_millivolts_aged[i] - mvs; +} + +/** + * Adjust VDD_CPU to offset aging. + * 25mV for 1st year + * 12mV for 2nd and 3rd year + * 0mV for 4th year onwards + */ +void tegra_dvfs_age_cpu(int cur_linear_age) +{ + int chip_linear_age; + int chip_life; + chip_linear_age = tegra_get_age(); + chip_life = cur_linear_age - chip_linear_age; + + /*For T37 and AP37*/ + if (tegra_cpu_speedo_id() == 12 || tegra_cpu_speedo_id() == 13) { + if (chip_linear_age <= 0) { + return; + } else if (chip_life <= 12) { + tegra_adjust_cpu_mvs(25); + } else if (chip_life <= 36) { + tegra_adjust_cpu_mvs(13); + } + } +} + void __init tegra_soc_init_dvfs(void) { int cpu_speedo_id = tegra_cpu_speedo_id(); @@ -692,19 +746,23 @@ void __init tegra_soc_init_dvfs(void) tegra_dvfs_core_disabled ? "disabled" : "enabled"); } -void tegra_cpu_dvfs_alter(int edp_thermal_index, const cpumask_t *cpus, - bool before_clk_update) +int tegra_cpu_dvfs_alter(int edp_thermal_index, const cpumask_t *cpus, + bool before_clk_update, int cpu_event) { bool cpu_warm = !!edp_thermal_index; unsigned int n = cpumask_weight(cpus); unsigned long *alt_freqs = cpu_warm ? (n > 1 ? NULL : cpu_0_freqs) : cpu_cold_freqs; - if (cpu_warm == before_clk_update) { + if (cpu_event || (cpu_warm == before_clk_update)) { int ret = tegra_dvfs_alt_freqs_set(cpu_dvfs, alt_freqs); - WARN_ONCE(ret, "tegra dvfs: failed to update CPU alternative" - " frequency limits\n"); + if (ret) { + pr_err("tegra dvfs: failed to set alternative dvfs on " + "%u %s CPUs\n", n, cpu_warm ? "warm" : "cold"); + return ret; + } } + return 0; } int tegra_dvfs_rail_disable_prepare(struct dvfs_rail *rail) @@ -762,6 +820,8 @@ static struct core_cap tegra3_core_cap; static struct core_cap kdvfs_core_cap; static struct core_cap user_core_cap; +static struct core_cap user_cbus_cap; + static struct kobject *cap_kobj; /* Arranged in order required for enabling/lowering the cap */ @@ -880,14 +940,91 @@ core_cap_level_store(struct kobject *kobj, struct kobj_attribute *attr, return count; } +static void cbus_cap_update(void) +{ + static struct clk *cbus_cap; + + if (!cbus_cap) { + cbus_cap = tegra_get_clock_by_name("cap.profile.cbus"); + if (!cbus_cap) { + WARN_ONCE(1, "tegra3_dvfs: cbus profiling is not supported"); + return; + } + } + + if (user_cbus_cap.refcnt) + clk_set_rate(cbus_cap, user_cbus_cap.level); + else + clk_set_rate(cbus_cap, clk_get_max_rate(cbus_cap)); +} + +static ssize_t +cbus_cap_state_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d\n", user_cbus_cap.refcnt ? 1 : 0); +} +static ssize_t +cbus_cap_state_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t count) +{ + int state; + + if (sscanf(buf, "%d", &state) != 1) + return -1; + + mutex_lock(&core_cap_lock); + + if (state) { + user_cbus_cap.refcnt++; + if (user_cbus_cap.refcnt == 1) + cbus_cap_update(); + } else if (user_cbus_cap.refcnt) { + user_cbus_cap.refcnt--; + if (user_cbus_cap.refcnt == 0) + cbus_cap_update(); + } + + mutex_unlock(&core_cap_lock); + return count; +} + +static ssize_t +cbus_cap_level_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d\n", user_cbus_cap.level); +} +static ssize_t +cbus_cap_level_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t count) +{ + int level; + + if (sscanf(buf, "%d", &level) != 1) + return -1; + + mutex_lock(&core_cap_lock); + user_cbus_cap.level = level; + cbus_cap_update(); + mutex_unlock(&core_cap_lock); + return count; +} + static struct kobj_attribute cap_state_attribute = __ATTR(core_cap_state, 0644, core_cap_state_show, core_cap_state_store); static struct kobj_attribute cap_level_attribute = __ATTR(core_cap_level, 0644, core_cap_level_show, core_cap_level_store); +static struct kobj_attribute cbus_state_attribute = + __ATTR(cbus_cap_state, 0644, cbus_cap_state_show, cbus_cap_state_store); +static struct kobj_attribute cbus_level_attribute = + __ATTR(cbus_cap_level, 0644, cbus_cap_level_show, cbus_cap_level_store); const struct attribute *cap_attributes[] = { &cap_state_attribute.attr, &cap_level_attribute.attr, + &cbus_state_attribute.attr, + &cbus_level_attribute.attr, NULL, }; diff --git a/arch/arm/mach-tegra/tegra3_emc.c b/arch/arm/mach-tegra/tegra3_emc.c index a138091d9197..4c06bf91ab1f 100644 --- a/arch/arm/mach-tegra/tegra3_emc.c +++ b/arch/arm/mach-tegra/tegra3_emc.c @@ -1,7 +1,7 @@ /* * arch/arm/mach-tegra/tegra3_emc.c * - * Copyright (C) 2012 NVIDIA Corporation + * Copyright (C) 2011-2012, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -33,6 +33,7 @@ #include <asm/cacheflush.h> #include <mach/iomap.h> +#include <mach/latency_allowance.h> #include "clock.h" #include "dvfs.h" @@ -46,6 +47,7 @@ static bool emc_enable; module_param(emc_enable, bool, 0644); u8 tegra_emc_bw_efficiency = 35; +u8 tegra_emc_bw_efficiency_boost = 45; #define EMC_MIN_RATE_DDR3 25500000 #define EMC_STATUS_UPDATE_TIMEOUT 100 @@ -1017,6 +1019,31 @@ static struct notifier_block tegra_emc_resume_nb = { .priority = -1, }; +static int tegra_emc_get_table_ns_per_tick(unsigned int emc_rate, + unsigned int table_tick_len) +{ + unsigned int ns_per_tick = 0; + unsigned int mc_period_10ns = 0; + unsigned int reg; + + reg = mc_readl(MC_EMEM_ARB_MISC0) & MC_EMEM_ARB_MISC0_EMC_SAME_FREQ; + + mc_period_10ns = ((reg ? (NSEC_PER_MSEC * 10) : (20 * NSEC_PER_MSEC)) / + (emc_rate)); + ns_per_tick = ((table_tick_len & MC_EMEM_ARB_CFG_CYCLE_MASK) + * mc_period_10ns) / (10 * + (1 + ((table_tick_len & MC_EMEM_ARB_CFG_EXTRA_TICK_MASK) + >> MC_EMEM_ARB_CFG_EXTRA_TICK_SHIFT))); + + /* round new_ns_per_tick to 30/60 */ + if (ns_per_tick < 45) + ns_per_tick = 30; + else + ns_per_tick = 60; + + return ns_per_tick; +} + void tegra_init_emc(const struct tegra_emc_table *table, int table_size) { int i, mv; @@ -1024,6 +1051,8 @@ void tegra_init_emc(const struct tegra_emc_table *table, int table_size) bool max_entry = false; unsigned long boot_rate, max_rate; struct clk *cbus = tegra_get_clock_by_name("cbus"); + unsigned int ns_per_tick = 0; + unsigned int cur_ns_per_tick = 0; emc_stats.clkchange_count = 0; spin_lock_init(&emc_stats.spinlock); @@ -1084,6 +1113,19 @@ void tegra_init_emc(const struct tegra_emc_table *table, int table_size) if (table_rate == max_rate) max_entry = true; + + cur_ns_per_tick = tegra_emc_get_table_ns_per_tick(table_rate, + table[i].burst_regs[MC_EMEM_ARB_CFG_INDEX]); + + if (ns_per_tick == 0) { + ns_per_tick = cur_ns_per_tick; + } else if (ns_per_tick != cur_ns_per_tick) { + pr_err("tegra: invalid EMC DFS table: " + "mismatched DFS tick lengths " + "within table!\n"); + ns_per_tick = 0; + return; + } } /* Validate EMC rate and voltage limits */ @@ -1093,6 +1135,8 @@ void tegra_init_emc(const struct tegra_emc_table *table, int table_size) return; } + tegra_latency_allowance_update_tick_length(ns_per_tick); + tegra_emc_table = table; adjust_emc_dvfs_table(tegra_emc_table, tegra_emc_table_size); @@ -1379,6 +1423,22 @@ static int efficiency_set(void *data, u64 val) DEFINE_SIMPLE_ATTRIBUTE(efficiency_fops, efficiency_get, efficiency_set, "%llu\n"); +static int efficiency_boost_get(void *data, u64 *val) +{ + *val = tegra_emc_bw_efficiency_boost; + return 0; +} +static int efficiency_boost_set(void *data, u64 val) +{ + tegra_emc_bw_efficiency_boost = (val > 100) ? 100 : val; + if (emc) + tegra_clk_shared_bus_update(emc); + + return 0; +} +DEFINE_SIMPLE_ATTRIBUTE(efficiency_boost_fops, efficiency_boost_get, + efficiency_boost_set, "%llu\n"); + static int __init tegra_emc_debug_init(void) { if (!tegra_emc_table) @@ -1408,6 +1468,10 @@ static int __init tegra_emc_debug_init(void) emc_debugfs_root, NULL, &efficiency_fops)) goto err_out; + if (!debugfs_create_file("efficiency_boost", S_IRUGO | S_IWUSR, + emc_debugfs_root, NULL, &efficiency_boost_fops)) + goto err_out; + return 0; err_out: diff --git a/arch/arm/mach-tegra/tegra3_emc.h b/arch/arm/mach-tegra/tegra3_emc.h index f59654295ba4..43ef636c613f 100644 --- a/arch/arm/mach-tegra/tegra3_emc.h +++ b/arch/arm/mach-tegra/tegra3_emc.h @@ -1,7 +1,7 @@ /* * arch/arm/mach-tegra/tegra3_emc.h * - * Copyright (C) 2012 NVIDIA Corporation + * Copyright (C) 2011-2012, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,6 +28,7 @@ #define TEGRA_EMC_BRIDGE_MVOLTS_MIN 1200 extern u8 tegra_emc_bw_efficiency; +extern u8 tegra_emc_bw_efficiency_boost; struct tegra_emc_table { u8 rev; @@ -266,6 +267,10 @@ enum { #define MC_EMEM_ADR_CFG 0x54 #define MC_EMEM_ARB_CFG 0x90 +#define MC_EMEM_ARB_CFG_CYCLE_MASK 0x1ff +#define MC_EMEM_ARB_CFG_EXTRA_TICK_SHIFT 16 +#define MC_EMEM_ARB_CFG_EXTRA_TICK_MASK \ + (0x1f << MC_EMEM_ARB_CFG_EXTRA_TICK_SHIFT) #define MC_EMEM_ARB_OUTSTANDING_REQ 0x94 #define MC_EMEM_ARB_OUTSTANDING_REQ_MAX_SHIFT 0 #define MC_EMEM_ARB_OUTSTANDING_REQ_MAX_MASK \ @@ -294,6 +299,43 @@ enum { #define MC_EMEM_ARB_OVERRIDE 0xe8 #define MC_EMEM_ARB_OVERRIDE_EACK_MASK (0x3 << 0) #define MC_TIMING_CONTROL 0xfc +#define MC_LATENCY_ALLOWANCE_AFI 0x2e0 +#define MC_LATENCY_ALLOWANCE_AVPC 0x2e4 +#define MC_LATENCY_ALLOWANCE_DC_0 0x2e8 +#define MC_LATENCY_ALLOWANCE_DC_1 0x2ec +#define MC_LATENCY_ALLOWANCE_DC_2 0x2f0 +#define MC_LATENCY_ALLOWANCE_DCB_0 0x2f4 +#define MC_LATENCY_ALLOWANCE_DCB_1 0x2f8 +#define MC_LATENCY_ALLOWANCE_DCB_2 0x2fc +#define MC_LATENCY_ALLOWANCE_EPP_0 0x300 +#define MC_LATENCY_ALLOWANCE_EPP_1 0x304 +#define MC_LATENCY_ALLOWANCE_G2_0 0x308 +#define MC_LATENCY_ALLOWANCE_G2_1 0x30c +#define MC_LATENCY_ALLOWANCE_HC_0 0x310 +#define MC_LATENCY_ALLOWANCE_HC_1 0x314 +#define MC_LATENCY_ALLOWANCE_HDA 0x318 +#define MC_LATENCY_ALLOWANCE_ISP 0x31c +#define MC_LATENCY_ALLOWANCE_MPCORE 0x320 +#define MC_LATENCY_ALLOWANCE_MPCORELP 0x324 +#define MC_LATENCY_ALLOWANCE_MPE_0 0x328 +#define MC_LATENCY_ALLOWANCE_MPE_1 0x32c +#define MC_LATENCY_ALLOWANCE_MPE_2 0x330 +#define MC_LATENCY_ALLOWANCE_NV_0 0x334 +#define MC_LATENCY_ALLOWANCE_NV_1 0x338 +#define MC_LATENCY_ALLOWANCE_NV2_0 0x33c +#define MC_LATENCY_ALLOWANCE_NV2_1 0x340 +#define MC_LATENCY_ALLOWANCE_PPCS_0 0x344 +#define MC_LATENCY_ALLOWANCE_PPCS_1 0x348 +#define MC_LATENCY_ALLOWANCE_PTC 0x34c +#define MC_LATENCY_ALLOWANCE_SATA 0x350 +#define MC_LATENCY_ALLOWANCE_VDE_0 0x354 +#define MC_LATENCY_ALLOWANCE_VDE_1 0x358 +#define MC_LATENCY_ALLOWANCE_VDE_2 0x35c +#define MC_LATENCY_ALLOWANCE_VDE_3 0x360 +#define MC_LATENCY_ALLOWANCE_VI_0 0x364 +#define MC_LATENCY_ALLOWANCE_VI_1 0x368 +#define MC_LATENCY_ALLOWANCE_VI_2 0x36c + #define MC_RESERVED_RSV 0x3fc #endif diff --git a/arch/arm/mach-tegra/tegra3_la_priv.h b/arch/arm/mach-tegra/tegra3_la_priv.h new file mode 100644 index 000000000000..2a39ea41b6f5 --- /dev/null +++ b/arch/arm/mach-tegra/tegra3_la_priv.h @@ -0,0 +1,226 @@ +/* + * arch/arm/mach-tegra/tegra3_la_priv.h + * + * Copyright (C) 2012, NVIDIA CORPORATION. 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. + * + */ + +#ifndef _MACH_TEGRA_TEGRA3_LA_PRIV_H_ +#define _MACH_TEGRA_TEGRA3_LA_PRIV_H_ + +#if defined(CONFIG_ARCH_TEGRA_3x_SOC) + +#define MC_LA_AFI_0 0x2e0 +#define MC_LA_AVPC_ARM7_0 0x2e4 +#define MC_LA_DC_0 0x2e8 +#define MC_LA_DC_1 0x2ec +#define MC_LA_DC_2 0x2f0 +#define MC_LA_DCB_0 0x2f4 +#define MC_LA_DCB_1 0x2f8 +#define MC_LA_DCB_2 0x2fc +#define MC_LA_EPP_0 0x300 +#define MC_LA_EPP_1 0x304 +#define MC_LA_G2_0 0x308 +#define MC_LA_G2_1 0x30c +#define MC_LA_HC_0 0x310 +#define MC_LA_HC_1 0x314 +#define MC_LA_HDA_0 0x318 +#define MC_LA_ISP_0 0x31C +#define MC_LA_MPCORE_0 0x320 +#define MC_LA_MPCORELP_0 0x324 +#define MC_LA_MPE_0 0x328 +#define MC_LA_MPE_1 0x32c +#define MC_LA_MPE_2 0x330 +#define MC_LA_NV_0 0x334 +#define MC_LA_NV_1 0x338 +#define MC_LA_NV2_0 0x33c +#define MC_LA_NV2_1 0x340 +#define MC_LA_PPCS_0 0x344 +#define MC_LA_PPCS_1 0x348 +#define MC_LA_PTC_0 0x34c +#define MC_LA_SATA_0 0x350 +#define MC_LA_VDE_0 0x354 +#define MC_LA_VDE_1 0x358 +#define MC_LA_VDE_2 0x35c +#define MC_LA_VDE_3 0x360 +#define MC_LA_VI_0 0x364 +#define MC_LA_VI_1 0x368 +#define MC_LA_VI_2 0x36c + +#define MC_ARB_OVERRIDE 0xe8 +#define GLOBAL_LATENCY_SCALING_ENABLE_BIT 7 + +#define DS_DISP_MCCIF_DISPLAY0A_HYST (0x481 * 4) +#define DS_DISP_MCCIF_DISPLAY0B_HYST (0x482 * 4) +#define DS_DISP_MCCIF_DISPLAY0C_HYST (0x483 * 4) +#define DS_DISP_MCCIF_DISPLAY1B_HYST (0x484 * 4) + +#define DS_DISP_MCCIF_DISPLAY0AB_HYST (0x481 * 4) +#define DS_DISP_MCCIF_DISPLAY0BB_HYST (0x482 * 4) +#define DS_DISP_MCCIF_DISPLAY0CB_HYST (0x483 * 4) +#define DS_DISP_MCCIF_DISPLAY1BB_HYST (0x484 * 4) + +#define VI_MCCIF_VIWSB_HYST (0x9a * 4) +#define VI_MCCIF_VIWU_HYST (0x9b * 4) +#define VI_MCCIF_VIWV_HYST (0x9c * 4) +#define VI_MCCIF_VIWY_HYST (0x9d * 4) + +#define VI_TIMEOUT_WOCAL_VI (0x70 * 4) +#define VI_RESERVE_3 (0x97 * 4) +#define VI_RESERVE_4 (0x98 * 4) + +/* + * The rule for getting the fifo_size_in_atoms is: + * 1.If REORDER_DEPTH exists, use it(default is overridden). + * 2.Else if (write_client) use RFIFO_DEPTH. + * 3.Else (read client) use RDFIFO_DEPTH. + * Multiply the value by 2 for wide clients. + * A client is wide, if CMW is larger than MW. + * Refer to project.h file. + */ +struct la_client_info la_info_array[] = { + LA_INFO(32, 150, AFI_0, 7 : 0, AFIR, false), + LA_INFO(32, 150, AFI_0, 23 : 16, AFIW, false), + LA_INFO(2, 150, AVPC_ARM7_0, 7 : 0, AVPC_ARM7R, false), + LA_INFO(2, 150, AVPC_ARM7_0, 23 : 16, AVPC_ARM7W, false), + LA_INFO(128, 1050, DC_0, 7 : 0, DISPLAY_0A, true), + LA_INFO(64, 1050, DC_0, 23 : 16, DISPLAY_0B, true), + LA_INFO(128, 1050, DC_1, 7 : 0, DISPLAY_0C, true), + LA_INFO(64, 1050, DC_1, 23 : 16, DISPLAY_1B, true), + LA_INFO(2, 1050, DC_2, 7 : 0, DISPLAY_HC, false), + LA_INFO(128, 1050, DCB_0, 7 : 0, DISPLAY_0AB, true), + LA_INFO(64, 1050, DCB_0, 23 : 16, DISPLAY_0BB, true), + LA_INFO(128, 1050, DCB_1, 7 : 0, DISPLAY_0CB, true), + LA_INFO(64, 1050, DCB_1, 23 : 16, DISPLAY_1BB, true), + LA_INFO(2, 1050, DCB_2, 7 : 0, DISPLAY_HCB, false), + LA_INFO(8, 150, EPP_0, 7 : 0, EPPUP, false), + LA_INFO(64, 150, EPP_0, 23 : 16, EPPU, false), + LA_INFO(64, 150, EPP_1, 7 : 0, EPPV, false), + LA_INFO(64, 150, EPP_1, 23 : 16, EPPY, false), + LA_INFO(64, 150, G2_0, 7 : 0, G2PR, false), + LA_INFO(64, 150, G2_0, 23 : 16, G2SR, false), + LA_INFO(48, 150, G2_1, 7 : 0, G2DR, false), + LA_INFO(128, 150, G2_1, 23 : 16, G2DW, false), + LA_INFO(16, 150, HC_0, 7 : 0, HOST1X_DMAR, false), + LA_INFO(8, 150, HC_0, 23 : 16, HOST1XR, false), + LA_INFO(32, 150, HC_1, 7 : 0, HOST1XW, false), + LA_INFO(16, 150, HDA_0, 7 : 0, HDAR, false), + LA_INFO(16, 150, HDA_0, 23 : 16, HDAW, false), + LA_INFO(64, 150, ISP_0, 7 : 0, ISPW, false), + LA_INFO(14, 150, MPCORE_0, 7 : 0, MPCORER, false), + LA_INFO(24, 150, MPCORE_0, 23 : 16, MPCOREW, false), + LA_INFO(14, 150, MPCORELP_0, 7 : 0, MPCORE_LPR, false), + LA_INFO(24, 150, MPCORELP_0, 23 : 16, MPCORE_LPW, false), + LA_INFO(8, 150, MPE_0, 7 : 0, MPE_UNIFBR, false), + LA_INFO(2, 150, MPE_0, 23 : 16, MPE_IPRED, false), + LA_INFO(64, 150, MPE_1, 7 : 0, MPE_AMEMRD, false), + LA_INFO(8, 150, MPE_1, 23 : 16, MPE_CSRD, false), + LA_INFO(8, 150, MPE_2, 7 : 0, MPE_UNIFBW, false), + LA_INFO(8, 150, MPE_2, 23 : 16, MPE_CSWR, false), + LA_INFO(96, 150, NV_0, 7 : 0, FDCDRD, false), + LA_INFO(64, 150, NV_0, 23 : 16, IDXSRD, false), + LA_INFO(64, 150, NV_1, 7 : 0, TEXSRD, false), + LA_INFO(96, 150, NV_1, 23 : 16, FDCDWR, false), + LA_INFO(96, 150, NV2_0, 7 : 0, FDCDRD2, false), + LA_INFO(64, 150, NV2_0, 23 : 16, IDXSRD2, false), + LA_INFO(64, 150, NV2_1, 7 : 0, TEXSRD2, false), + LA_INFO(96, 150, NV2_1, 23 : 16, FDCDWR2, false), + LA_INFO(2, 150, PPCS_0, 7 : 0, PPCS_AHBDMAR, false), + LA_INFO(8, 150, PPCS_0, 23 : 16, PPCS_AHBSLVR, false), + LA_INFO(2, 150, PPCS_1, 7 : 0, PPCS_AHBDMAW, false), + LA_INFO(4, 150, PPCS_1, 23 : 16, PPCS_AHBSLVW, false), + LA_INFO(2, 150, PTC_0, 7 : 0, PTCR, false), + LA_INFO(32, 150, SATA_0, 7 : 0, SATAR, false), + LA_INFO(32, 150, SATA_0, 23 : 16, SATAW, false), + LA_INFO(8, 150, VDE_0, 7 : 0, VDE_BSEVR, false), + LA_INFO(4, 150, VDE_0, 23 : 16, VDE_MBER, false), + LA_INFO(16, 150, VDE_1, 7 : 0, VDE_MCER, false), + LA_INFO(16, 150, VDE_1, 23 : 16, VDE_TPER, false), + LA_INFO(4, 150, VDE_2, 7 : 0, VDE_BSEVW, false), + LA_INFO(16, 150, VDE_2, 23 : 16, VDE_DBGW, false), + LA_INFO(2, 150, VDE_3, 7 : 0, VDE_MBEW, false), + LA_INFO(16, 150, VDE_3, 23 : 16, VDE_TPMW, false), + LA_INFO(8, 1050, VI_0, 7 : 0, VI_RUV, false), + LA_INFO(64, 1050, VI_0, 23 : 16, VI_WSB, true), + LA_INFO(64, 1050, VI_1, 7 : 0, VI_WU, true), + LA_INFO(64, 1050, VI_1, 23 : 16, VI_WV, true), + LA_INFO(64, 1050, VI_2, 7 : 0, VI_WY, true), + +/* end of list. */ + LA_INFO(0, 0, AFI_0, 0 : 0, MAX_ID, false) +}; + +#define DISP1_RA(r) \ + ((u32)IO_ADDRESS(TEGRA_DISPLAY_BASE) + DS_DISP_MCCIF_##r##_HYST) +#define DISP2_RA(r) \ + ((u32)IO_ADDRESS(TEGRA_DISPLAY2_BASE) + DS_DISP_MCCIF_##r##_HYST) + +#define DISP_SCALING_REG_INFO(id, r, ra) \ + { \ + ID(id), \ + ra(r), MASK(15 : 8), SHIFT(15 : 8), \ + ra(r), MASK(23 : 16), SHIFT(15 : 8), \ + ra(r), MASK(7 : 0), SHIFT(15 : 8) \ + } + +struct la_scaling_reg_info disp_info[] = { + DISP_SCALING_REG_INFO(DISPLAY_0A, DISPLAY0A, DISP1_RA), + DISP_SCALING_REG_INFO(DISPLAY_0B, DISPLAY0B, DISP1_RA), + DISP_SCALING_REG_INFO(DISPLAY_0C, DISPLAY0C, DISP1_RA), + DISP_SCALING_REG_INFO(DISPLAY_1B, DISPLAY1B, DISP1_RA), + DISP_SCALING_REG_INFO(MAX_ID, DISPLAY1B, DISP1_RA), /*dummy entry*/ + DISP_SCALING_REG_INFO(DISPLAY_0AB, DISPLAY0AB, DISP2_RA), + DISP_SCALING_REG_INFO(DISPLAY_0BB, DISPLAY0BB, DISP2_RA), + DISP_SCALING_REG_INFO(DISPLAY_0CB, DISPLAY0CB, DISP2_RA), + DISP_SCALING_REG_INFO(DISPLAY_1BB, DISPLAY1BB, DISP2_RA), +}; + +#define VI_TH_RA(r) \ + ((u32)IO_ADDRESS(TEGRA_VI_BASE) + VI_MCCIF_##r##_HYST) +#define VI_TM_RA(r) \ + ((u32)IO_ADDRESS(TEGRA_VI_BASE) + VI_TIMEOUT_WOCAL_VI) +#define VI_TL_RA(r) \ + ((u32)IO_ADDRESS(TEGRA_VI_BASE) + VI_RESERVE_##r) + +struct la_scaling_reg_info vi_info[] = { + { + ID(VI_WSB), + VI_TL_RA(4), MASK(7 : 0), SHIFT(7 : 0), + VI_TM_RA(0), MASK(7 : 0), SHIFT(7 : 0), + VI_TH_RA(VIWSB), MASK(7 : 0), SHIFT(7 : 0) + }, + { + ID(VI_WU), + VI_TL_RA(3), MASK(15 : 8), SHIFT(15 : 8), + VI_TM_RA(0), MASK(15 : 8), SHIFT(15 : 8), + VI_TH_RA(VIWU), MASK(7 : 0), SHIFT(7 : 0) + }, + { + ID(VI_WV), + VI_TL_RA(3), MASK(7 : 0), SHIFT(7 : 0), + VI_TM_RA(0), MASK(23 : 16), SHIFT(23 : 16), + VI_TH_RA(VIWV), MASK(7 : 0), SHIFT(7 : 0) + }, + { + ID(VI_WY), + VI_TL_RA(4), MASK(15 : 8), SHIFT(15 : 8), + VI_TM_RA(0), MASK(31 : 24), SHIFT(31 : 24), + VI_TH_RA(VIWY), MASK(7 : 0), SHIFT(7 : 0) + } +}; + +static int ns_per_tick = 30; +/* Tegra3 MC atom size in bytes */ +static const int normal_atom_size = 16; +#endif + +#endif /* _MACH_TEGRA_TEGRA3_LA_PRIV_H_ */ diff --git a/arch/arm/mach-tegra/tegra3_speedo.c b/arch/arm/mach-tegra/tegra3_speedo.c index 78afb2804088..2889f656f47a 100644 --- a/arch/arm/mach-tegra/tegra3_speedo.c +++ b/arch/arm/mach-tegra/tegra3_speedo.c @@ -1,7 +1,7 @@ /* * arch/arm/mach-tegra/tegra3_speedo.c * - * Copyright (c) 2011, NVIDIA Corporation. + * Copyright (c) 2011-2012, NVIDIA Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,6 +23,8 @@ #include <linux/err.h> #include <mach/iomap.h> #include <mach/tegra_fuse.h> +#include <linux/module.h> +#include <linux/moduleparam.h> #include "fuse.h" @@ -128,6 +130,11 @@ static int core_process_id; static int cpu_speedo_id; static int soc_speedo_id; static int package_id; +/* + * Only AP37 supports App Profile + * This informs user space of support without exposing cpu id's + */ +static int enable_app_profiles; static void fuse_speedo_calib(u32 *speedo_g, u32 *speedo_lp) { @@ -267,6 +274,7 @@ static void rev_sku_to_speedo_ids(int rev, int sku) cpu_speedo_id = 12; soc_speedo_id = 2; threshold_index = 9; + enable_app_profiles = 1; break; default: pr_err("Tegra3 Rev-A02: Reserved pkg: %d\n", @@ -560,3 +568,15 @@ int tegra_core_speedo_mv(void) BUG(); } } + +static int get_enable_app_profiles(char *val, const struct kernel_param *kp) +{ + return param_get_uint(val, kp); +} + +static struct kernel_param_ops tegra_profiles_ops = { + .get = get_enable_app_profiles, +}; + +module_param_cb(tegra_enable_app_profiles, + &tegra_profiles_ops, &enable_app_profiles, 0444); diff --git a/arch/arm/mach-tegra/tegra3_thermal.c b/arch/arm/mach-tegra/tegra3_thermal.c index f36f84ccddf4..9de34a05810c 100644 --- a/arch/arm/mach-tegra/tegra3_thermal.c +++ b/arch/arm/mach-tegra/tegra3_thermal.c @@ -281,9 +281,9 @@ static void tegra_thermal_alert_unlocked(void *data) #ifdef CONFIG_TEGRA_EDP_LIMITS /* inform edp governor */ if (edp_thermal_zone_val != temp_tj) { - long temp_edp = (dev2tj(device, temp_tj) - therm->edp_offset) / 1000; + long temp_edp = (temp_tj - therm->edp_offset) / 1000; tegra_edp_update_thermal_zone(temp_edp); - edp_thermal_zone_val = temp_edp; + edp_thermal_zone_val = temp_tj; } #endif } @@ -441,7 +441,6 @@ int tegra_thermal_device_register(struct tegra_thermal_device *device) tegra_skin_device_register(device); #endif - register_pm_notifier(&tegra_thermal_nb); return 0; } @@ -477,6 +476,8 @@ int __init tegra_thermal_init(struct tegra_thermal_data *data, throttle_list = tlist; throttle_list_size = tlist_size; + register_pm_notifier(&tegra_thermal_nb); + return 0; } diff --git a/arch/arm/mach-tegra/tegra3_usb_phy.c b/arch/arm/mach-tegra/tegra3_usb_phy.c index 3a831c59a750..66637f29b19c 100644 --- a/arch/arm/mach-tegra/tegra3_usb_phy.c +++ b/arch/arm/mach-tegra/tegra3_usb_phy.c @@ -473,6 +473,11 @@ #define PHY_DBG(stuff...) do {} while (0) #endif +/* define HSIC phy params */ +#define HSIC_SYNC_START_DELAY 9 +#define HSIC_IDLE_WAIT_DELAY 17 +#define HSIC_ELASTIC_UNDERRUN_LIMIT 16 +#define HSIC_ELASTIC_OVERRUN_LIMIT 16 static u32 utmip_rctrl_val, utmip_tctrl_val; static DEFINE_SPINLOCK(utmip_pad_lock); @@ -632,12 +637,6 @@ static void utmip_setup_pmc_wake_detect(struct tegra_usb_phy *phy) writel(val, pmc_base + PMC_UTMIP_UHSIC_FAKE); /* Enable which type of event can trigger a walk, - in this case usb_line_wake */ - val = readl(pmc_base + PMC_SLEEPWALK_CFG); - val |= UTMIP_LINEVAL_WALK_EN(inst); - writel(val, pmc_base + PMC_SLEEPWALK_CFG); - - /* Enable which type of event can trigger a walk, * in this case usb_line_wake */ val = readl(pmc_base + PMC_SLEEPWALK_CFG); val |= UTMIP_LINEVAL_WALK_EN(inst); @@ -721,10 +720,6 @@ static void utmip_phy_disable_pmc_bus_ctrl(struct tegra_usb_phy *phy) val |= UTMIP_WAKE_VAL(inst, WAKE_VAL_NONE); writel(val, pmc_base + PMC_SLEEP_CFG); - val = readl(pmc_base + PMC_TRIGGERS); - val |= UTMIP_CLR_WAKE_ALARM(inst) | UTMIP_CLR_WALK_PTR(inst); - writel(val, pmc_base + PMC_TRIGGERS); - val = readl(base + UTMIP_PMC_WAKEUP0); val &= ~EVENT_INT_ENB; writel(val, base + UTMIP_PMC_WAKEUP0); @@ -744,6 +739,11 @@ static void utmip_phy_disable_pmc_bus_ctrl(struct tegra_usb_phy *phy) val |= (USBOP_VAL_PD(inst) | USBON_VAL_PD(inst)); writel(val, pmc_base + PMC_USB_AO); + val = readl(pmc_base + PMC_TRIGGERS); + val |= UTMIP_CLR_WALK_PTR(inst); + val |= UTMIP_CLR_WAKE_ALARM(inst); + writel(val, pmc_base + PMC_TRIGGERS); + phy->remote_wakeup = false; PHY_DBG("%s DISABLE_PMC inst = %d\n", __func__, inst); } @@ -766,8 +766,7 @@ bool utmi_phy_remotewake_detected(struct tegra_usb_phy *phy) writel(val, pmc_base + PMC_SLEEP_CFG); val = readl(pmc_base + PMC_TRIGGERS); - val |= UTMIP_CLR_WAKE_ALARM(inst) | - UTMIP_CLR_WALK_PTR(inst); + val |= UTMIP_CLR_WAKE_ALARM(inst); writel(val, pmc_base + PMC_TRIGGERS); val = readl(base + UTMIP_PMC_WAKEUP0); @@ -989,7 +988,8 @@ static int usb_phy_bringup_host_controller(struct tegra_usb_phy *phy) /* Program the field PTC based on the saved speed mode */ val = readl(base + USB_PORTSC); val &= ~USB_PORTSC_PTC(~0); - if (phy->port_speed == USB_PHY_PORT_SPEED_HIGH) + if ((phy->port_speed == USB_PHY_PORT_SPEED_HIGH) || + (phy->pdata->phy_intf == TEGRA_USB_PHY_INTF_HSIC)) val |= USB_PORTSC_PTC(5); else if (phy->port_speed == USB_PHY_PORT_SPEED_FULL) val |= USB_PORTSC_PTC(6); @@ -1222,19 +1222,23 @@ static int utmi_phy_irq(struct tegra_usb_phy *phy) { void __iomem *base = phy->regs; unsigned long val = 0; + bool remote_wakeup = false; + int irq_status = IRQ_HANDLED; if (phy->phy_clk_on) { DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst); DBG("USB_USBSTS[0x%x] USB_PORTSC[0x%x]\n", - readl(base + USB_USBSTS), readl(base + USB_PORTSC)); + readl(base + USB_USBSTS), readl(base + USB_PORTSC)); DBG("USB_USBMODE[0x%x] USB_USBCMD[0x%x]\n", - readl(base + USB_USBMODE), readl(base + USB_USBCMD)); + readl(base + USB_USBMODE), readl(base + USB_USBCMD)); } usb_phy_fence_read(phy); /* check if there is any remote wake event */ - if (utmi_phy_remotewake_detected(phy)) + if (utmi_phy_remotewake_detected(phy)) { pr_info("%s: utmip remote wake detected\n", __func__); + remote_wakeup = true; + } if (phy->pdata->u_data.host.hot_plug) { val = readl(base + USB_SUSP_CTRL); @@ -1242,19 +1246,36 @@ static int utmi_phy_irq(struct tegra_usb_phy *phy) val &= ~USB_PHY_CLK_VALID_INT_ENB | USB_PHY_CLK_VALID_INT_STS; writel(val , (base + USB_SUSP_CTRL)); - pr_info("%s: usb device plugged-in\n", __func__); - val = readl(base + USB_USBSTS); - if (!(val & USB_USBSTS_PCI)) - return IRQ_NONE; - val = readl(base + USB_PORTSC); - val &= ~(USB_PORTSC_WKCN | USB_PORTSC_RWC_BITS); - writel(val , (base + USB_PORTSC)); + + /* In case of remote wakeup PHY clock will not up + immediately, so should not access any controller + register but normal plug-in/plug-out should be + executed */ + if (!remote_wakeup) { + val = readl(base + USB_USBSTS); + if (!(val & USB_USBSTS_PCI)) { + irq_status = IRQ_NONE; + goto exit; + } + + val = readl(base + USB_PORTSC); + if (val & USB_PORTSC_CCS) + val &= ~USB_PORTSC_WKCN; + else + val &= ~USB_PORTSC_WKDS; + val &= ~USB_PORTSC_RWC_BITS; + writel(val , (base + USB_PORTSC)); + } } else if (!phy->phy_clk_on) { - return IRQ_NONE; + if (remote_wakeup) + irq_status = IRQ_HANDLED; + else + irq_status = IRQ_NONE; + goto exit; } } - - return IRQ_HANDLED; +exit: + return irq_status; } static void utmi_phy_enable_obs_bus(struct tegra_usb_phy *phy) @@ -1466,8 +1487,12 @@ static int utmi_phy_power_off(struct tegra_usb_phy *phy) enable_hotplug = (val & USB_ID_STATUS) ? false : true; } if (enable_hotplug) { + /* Enable wakeup event of device plug-in/plug-out */ val = readl(base + USB_PORTSC); - val |= USB_PORTSC_WKCN; + if (val & USB_PORTSC_CCS) + val |= USB_PORTSC_WKDS; + else + val |= USB_PORTSC_WKCN; writel(val, base + USB_PORTSC); val = readl(base + USB_SUSP_CTRL); @@ -1481,6 +1506,7 @@ static int utmi_phy_power_off(struct tegra_usb_phy *phy) } } + /* Disable PHY clock */ val = readl(base + HOSTPC1_DEVLC); val |= HOSTPC1_DEVLC_PHCD; writel(val, base + HOSTPC1_DEVLC); @@ -1647,11 +1673,11 @@ static void utmi_phy_restore_start(struct tegra_usb_phy *phy) if (UTMIP_WALK_PTR_VAL(inst) & val) { phy->remote_wakeup = true; } else if(!phy->remote_wakeup) { - if (!((UTMIP_USBON_VAL(phy->inst) | - UTMIP_USBOP_VAL(phy->inst)) & val)) { - utmip_phy_disable_pmc_bus_ctrl(phy); - } + val = readl(pmc_base + PMC_SLEEP_CFG); + if (val & UTMIP_MASTER_ENABLE(inst)) + utmip_phy_disable_pmc_bus_ctrl(phy); } + utmi_phy_enable_obs_bus(phy); } @@ -1669,7 +1695,9 @@ static void utmi_phy_restore_end(struct tegra_usb_phy *phy) val = readl(base + USB_PORTSC); udelay(1); if (wait_time_us == 0) { - PHY_DBG("%s PMC REMOTE WAKEUP FPR timeout val = 0x%x instance = %d\n", __func__, val, phy->inst); + PHY_DBG("%s PMC REMOTE WAKEUP FPR timeout" + "val = 0x%lx instance = %d\n", + __func__, val, phy->inst); utmip_phy_disable_pmc_bus_ctrl(phy); utmi_phy_post_resume(phy); return; @@ -1810,6 +1838,31 @@ static void uhsic_powerup_pmc_wake_detect(struct tegra_usb_phy *phy) mdelay(1); } +static void uhsic_powerdown_pmc_wake_detect(struct tegra_usb_phy *phy) +{ + unsigned long val; + void __iomem *pmc_base = IO_ADDRESS(TEGRA_PMC_BASE); + + DBG("%s:%d\n", __func__, __LINE__); + + /* turn off pad detectors for HSIC*/ + val = readl(pmc_base + PMC_USB_AO); + val |= (HSIC_RESERVED_P0 | STROBE_VAL_PD_P0 | DATA_VAL_PD_P0); + writel(val, pmc_base + PMC_USB_AO); + + /* enable pull downs on HSIC PMC */ + val = UHSIC_STROBE_RPD_A | UHSIC_DATA_RPD_A | UHSIC_STROBE_RPD_B | + UHSIC_DATA_RPD_B | UHSIC_STROBE_RPD_C | UHSIC_DATA_RPD_C | + UHSIC_STROBE_RPD_D | UHSIC_DATA_RPD_D; + writel(val, pmc_base + PMC_SLEEPWALK_UHSIC); + + /* Turn over pad configuration to PMC */ + val = readl(pmc_base + PMC_SLEEP_CFG); + val &= ~UHSIC_WAKE_VAL_P0(~0); + val |= UHSIC_WAKE_VAL_P0(WAKE_VAL_NONE) | UHSIC_MASTER_ENABLE_P0; + writel(val, pmc_base + PMC_SLEEP_CFG); +} + static void uhsic_setup_pmc_wake_detect(struct tegra_usb_phy *phy) { unsigned long val; @@ -1844,6 +1897,30 @@ static void uhsic_setup_pmc_wake_detect(struct tegra_usb_phy *phy) val |= UHSIC_PWR; writel(val, pmc_base + PMC_UTMIP_MASTER_CONFIG); + /* Make sure nothing is happening on the line with respect to PMC */ + val = readl(pmc_base + PMC_UTMIP_UHSIC_FAKE); + val &= ~UHSIC_STROBE_VAL; + val &= ~UHSIC_DATA_VAL; + writel(val, pmc_base + PMC_UTMIP_UHSIC_FAKE); + + /* Clear walk enable */ + val = readl(pmc_base + PMC_SLEEPWALK_CFG); + val &= ~UHSIC_LINEVAL_WALK_EN; + writel(val, pmc_base + PMC_SLEEPWALK_CFG); + + /* Make sure wake value for line is none */ + val = readl(pmc_base + PMC_SLEEP_CFG); + val &= ~UHSIC_WAKE_VAL(WAKE_VAL_ANY); + val |= UHSIC_WAKE_VAL(WAKE_VAL_NONE); + writel(val, pmc_base + PMC_SLEEP_CFG); + + /* turn on pad detectors */ + val = readl(pmc_base + PMC_USB_AO); + val &= ~(STROBE_VAL_PD_P0 | DATA_VAL_PD_P0); + writel(val, pmc_base + PMC_USB_AO); + + /* Add small delay before usb detectors provide stable line values */ + udelay(1); /* Enable which type of event can trigger a walk, * in this case usb_line_wake */ @@ -1860,19 +1937,16 @@ static void uhsic_setup_pmc_wake_detect(struct tegra_usb_phy *phy) val |= UHSIC_DATA_RPD_A; val &= ~UHSIC_STROBE_RPD_A; val |= UHSIC_STROBE_RPU_A; - writel(val, pmc_base + PMC_SLEEPWALK_UHSIC); val &= ~UHSIC_DATA_RPD_B; val |= UHSIC_DATA_RPU_B; val &= ~UHSIC_STROBE_RPU_B; val |= UHSIC_STROBE_RPD_B; - writel(val, pmc_base + PMC_SLEEPWALK_UHSIC); val &= ~UHSIC_DATA_RPD_C; val |= UHSIC_DATA_RPU_C; val &= ~UHSIC_STROBE_RPU_C; val |= UHSIC_STROBE_RPD_C; - writel(val, pmc_base + PMC_SLEEPWALK_UHSIC); val &= ~UHSIC_DATA_RPD_D; val |= UHSIC_DATA_RPU_D; @@ -1880,19 +1954,21 @@ static void uhsic_setup_pmc_wake_detect(struct tegra_usb_phy *phy) val |= UHSIC_STROBE_RPD_D; writel(val, pmc_base + PMC_SLEEPWALK_UHSIC); - /* turn on pad detectors */ - val = readl(pmc_base + PMC_USB_AO); - val &= ~(STROBE_VAL_PD_P0 | DATA_VAL_PD_P0); - writel(val, pmc_base + PMC_USB_AO); - /* Add small delay before usb detectors provide stable line values */ - udelay(1); - phy->remote_wakeup = false; - /* Turn over pad configuration to PMC for line wake events*/ + /* Setting Wake event*/ val = readl(pmc_base + PMC_SLEEP_CFG); - val &= ~UHSIC_WAKE_VAL(~0); + val &= ~UHSIC_WAKE_VAL(WAKE_VAL_ANY); val |= UHSIC_WAKE_VAL(WAKE_VAL_SD10); + writel(val, pmc_base + PMC_SLEEP_CFG); + + /* Clear the walk pointers and wake alarm */ + val = readl(pmc_base + PMC_TRIGGERS); + val |= UHSIC_CLR_WAKE_ALARM_P0 | UHSIC_CLR_WALK_PTR_P0; + writel(val, pmc_base + PMC_TRIGGERS); + + /* Turn over pad configuration to PMC for line wake events*/ + val = readl(pmc_base + PMC_SLEEP_CFG); val |= UHSIC_MASTER_ENABLE; writel(val, pmc_base + PMC_SLEEP_CFG); @@ -1911,14 +1987,10 @@ static void uhsic_phy_disable_pmc_bus_ctrl(struct tegra_usb_phy *phy) DBG("%s (%d)\n", __func__, __LINE__); val = readl(pmc_base + PMC_SLEEP_CFG); - val &= ~UHSIC_WAKE_VAL(0x0); + val &= ~UHSIC_WAKE_VAL(WAKE_VAL_ANY); val |= UHSIC_WAKE_VAL(WAKE_VAL_NONE); writel(val, pmc_base + PMC_SLEEP_CFG); - val = readl(pmc_base + PMC_TRIGGERS); - val |= UHSIC_CLR_WAKE_ALARM_P0 | UHSIC_CLR_WALK_PTR_P0; - writel(val, pmc_base + PMC_TRIGGERS); - val = readl(base + UHSIC_PMC_WAKEUP0); val &= ~EVENT_INT_ENB; writel(val, base + UHSIC_PMC_WAKEUP0); @@ -1933,6 +2005,10 @@ static void uhsic_phy_disable_pmc_bus_ctrl(struct tegra_usb_phy *phy) val |= (STROBE_VAL_PD_P0 | DATA_VAL_PD_P0); writel(val, pmc_base + PMC_USB_AO); + val = readl(pmc_base + PMC_TRIGGERS); + val |= (UHSIC_CLR_WALK_PTR_P0 | UHSIC_CLR_WAKE_ALARM_P0); + writel(val, pmc_base + PMC_TRIGGERS); + phy->remote_wakeup = false; } @@ -1947,12 +2023,12 @@ static bool uhsic_phy_remotewake_detected(struct tegra_usb_phy *phy) val = readl(pmc_base + UTMIP_UHSIC_STATUS); if (UHSIC_WAKE_ALARM & val) { val = readl(pmc_base + PMC_SLEEP_CFG); - val &= ~UHSIC_WAKE_VAL(0x0); + val &= ~UHSIC_WAKE_VAL(WAKE_VAL_ANY); val |= UHSIC_WAKE_VAL(WAKE_VAL_NONE); writel(val, pmc_base + PMC_SLEEP_CFG); val = readl(pmc_base + PMC_TRIGGERS); - val |= UHSIC_CLR_WAKE_ALARM_P0 | UHSIC_CLR_WALK_PTR_P0; + val |= UHSIC_CLR_WAKE_ALARM_P0; writel(val, pmc_base + PMC_TRIGGERS); val = readl(base + UHSIC_PMC_WAKEUP0); @@ -2003,14 +2079,10 @@ static void uhsic_phy_restore_start(struct tegra_usb_phy *phy) if (UHSIC_WALK_PTR_VAL & val) { phy->remote_wakeup = true; } else { - if (!((UHSIC_STROBE_VAL_P0 | UHSIC_DATA_VAL_P0) & val)) { - uhsic_phy_disable_pmc_bus_ctrl(phy); - } else { - DBG("%s(%d): setting pretend connect\n", __func__, __LINE__); - val = readl(base + UHSIC_CMD_CFG0); - val |= UHSIC_PRETEND_CONNECT_DETECT; - writel(val, base + UHSIC_CMD_CFG0); - } + DBG("%s(%d): setting pretend connect\n", __func__, __LINE__); + val = readl(base + UHSIC_CMD_CFG0); + val |= UHSIC_PRETEND_CONNECT_DETECT; + writel(val, base + UHSIC_CMD_CFG0); } } @@ -2019,7 +2091,7 @@ static void uhsic_phy_restore_end(struct tegra_usb_phy *phy) unsigned long val; void __iomem *base = phy->regs; - int wait_time_us = 3000; /* FPR should be set by this time */ + int wait_time_us = 25000; /* FPR should be set by this time */ DBG("%s(%d)\n", __func__, __LINE__); @@ -2035,9 +2107,8 @@ static void uhsic_phy_restore_end(struct tegra_usb_phy *phy) return; } wait_time_us--; - } while (!(val & USB_PORTSC_RESUME)); - /* wait for 25 ms to port resume complete */ - msleep(25); + } while (val & (USB_PORTSC_RESUME | USB_PORTSC_SUSP)); + /* disable PMC master control */ uhsic_phy_disable_pmc_bus_ctrl(phy); @@ -2050,25 +2121,73 @@ static void uhsic_phy_restore_end(struct tegra_usb_phy *phy) pr_warn("%s: timeout waiting for SOF\n", __func__); } uhsic_phy_post_resume(phy); + + /* Set RUN bit */ + 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; + } } else { uhsic_phy_disable_pmc_bus_ctrl(phy); } +} - /* Set RUN bit */ - 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; +static int hsic_rail_enable(struct tegra_usb_phy *phy) +{ + int ret; + + if (phy->hsic_reg == NULL) { + phy->hsic_reg = regulator_get(NULL, "avdd_hsic"); + if (IS_ERR_OR_NULL(phy->hsic_reg)) { + pr_err("HSIC: Could not get regulator avdd_hsic\n"); + phy->hsic_reg = NULL; + return PTR_ERR(phy->hsic_reg); + } } + + ret = regulator_enable(phy->hsic_reg); + if (ret < 0) { + pr_err("%s avdd_hsic could not be enabled\n", __func__); + return ret; + } + + return 0; +} + +static int hsic_rail_disable(struct tegra_usb_phy *phy) +{ + int ret; + + if (phy->hsic_reg == NULL) { + pr_warn("%s: unbalanced disable\n", __func__); + return -EIO; + } + + ret = regulator_disable(phy->hsic_reg); + if (ret < 0) { + pr_err("HSIC regulator avdd_hsic cannot be disabled\n"); + return ret; + } + + return 0; } static int uhsic_phy_open(struct tegra_usb_phy *phy) { unsigned long parent_rate; int i; + int ret; + + phy->hsic_reg = NULL; + ret = hsic_rail_enable(phy); + if (ret < 0) { + pr_err("%s avdd_hsic could not be enabled\n", __func__); + return ret; + } DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst); parent_rate = clk_get_rate(clk_get_parent(phy->pllu_clk)); @@ -2088,6 +2207,18 @@ static int uhsic_phy_open(struct tegra_usb_phy *phy) return 0; } +static void uhsic_phy_close(struct tegra_usb_phy *phy) +{ + int ret; + + DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst); + uhsic_powerdown_pmc_wake_detect(phy); + + ret = hsic_rail_disable(phy); + if (ret < 0) + pr_err("%s avdd_hsic could not be disabled\n", __func__); +} + static int uhsic_phy_irq(struct tegra_usb_phy *phy) { usb_phy_fence_read(phy); @@ -2101,7 +2232,6 @@ static int uhsic_phy_power_on(struct tegra_usb_phy *phy) { unsigned long val; void __iomem *base = phy->regs; - struct tegra_hsic_config *config = &phy->pdata->u_cfg.hsic; DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst); @@ -2127,13 +2257,13 @@ static int uhsic_phy_power_on(struct tegra_usb_phy *phy) writel(val, base + USB_SUSP_CTRL); val = readl(base + UHSIC_HSRX_CFG0); - val |= UHSIC_IDLE_WAIT(config->idle_wait_delay); - val |= UHSIC_ELASTIC_UNDERRUN_LIMIT(config->elastic_underrun_limit); - val |= UHSIC_ELASTIC_OVERRUN_LIMIT(config->elastic_overrun_limit); + val |= UHSIC_IDLE_WAIT(HSIC_IDLE_WAIT_DELAY); + val |= UHSIC_ELASTIC_UNDERRUN_LIMIT(HSIC_ELASTIC_UNDERRUN_LIMIT); + val |= UHSIC_ELASTIC_OVERRUN_LIMIT(HSIC_ELASTIC_OVERRUN_LIMIT); writel(val, base + UHSIC_HSRX_CFG0); val = readl(base + UHSIC_HSRX_CFG1); - val |= UHSIC_HS_SYNC_START_DLY(config->sync_start_delay); + val |= UHSIC_HS_SYNC_START_DLY(HSIC_SYNC_START_DELAY); writel(val, base + UHSIC_HSRX_CFG1); /* WAR HSIC TX */ @@ -2173,8 +2303,6 @@ static int uhsic_phy_power_on(struct tegra_usb_phy *phy) val = readl(base + HOSTPC1_DEVLC); val &= ~HOSTPC1_DEVLC_PTS(HOSTPC1_DEVLC_PTS_MASK); val |= HOSTPC1_DEVLC_PTS(HOSTPC1_DEVLC_PTS_HSIC); - val &= ~HOSTPC1_DEVLC_PSPD(HOSTPC1_DEVLC_PSPD_MASK); - val |= HOSTPC1_DEVLC_PSPD(HOSTPC1_DEVLC_PSPD_HIGH_SPEED); val &= ~HOSTPC1_DEVLC_STS; writel(val, base + HOSTPC1_DEVLC); @@ -2203,6 +2331,15 @@ static int uhsic_phy_power_on(struct tegra_usb_phy *phy) phy->phy_clk_on = true; phy->hw_accessible = true; + if (phy->pmc_sleepwalk) { + DBG("%s(%d) inst:[%d] restore phy\n", __func__, __LINE__, + phy->inst); + uhsic_phy_restore_start(phy); + usb_phy_bringup_host_controller(phy); + uhsic_phy_restore_end(phy); + phy->pmc_sleepwalk = false; + } + return 0; } @@ -2224,12 +2361,20 @@ static int uhsic_phy_power_off(struct tegra_usb_phy *phy) /* Disable interrupts */ writel(0, base + USB_USBINTR); - uhsic_setup_pmc_wake_detect(phy); + if (phy->pmc_sleepwalk == false) { + uhsic_setup_pmc_wake_detect(phy); + phy->pmc_sleepwalk = true; + } val = readl(base + HOSTPC1_DEVLC); val |= HOSTPC1_DEVLC_PHCD; writel(val, base + HOSTPC1_DEVLC); + /* Remove power downs for HSIC from PADS CFG1 register */ + val = readl(base + UHSIC_PADS_CFG1); + val |= (UHSIC_PD_BG |UHSIC_PD_TRK | UHSIC_PD_RX | + UHSIC_PD_ZI | UHSIC_PD_TX); + writel(val, base + UHSIC_PADS_CFG1); phy->phy_clk_on = false; phy->hw_accessible = false; @@ -2251,8 +2396,6 @@ int uhsic_phy_bus_port_power(struct tegra_usb_phy *phy) val = readl(base + HOSTPC1_DEVLC); val &= ~(HOSTPC1_DEVLC_PTS(HOSTPC1_DEVLC_PTS_MASK)); val |= HOSTPC1_DEVLC_PTS(HOSTPC1_DEVLC_PTS_HSIC); - val &= ~(HOSTPC1_DEVLC_PSPD(HOSTPC1_DEVLC_PSPD_MASK)); - val |= HOSTPC1_DEVLC_PSPD(HOSTPC1_DEVLC_PSPD_HIGH_SPEED); writel(val, base + HOSTPC1_DEVLC); val = readl(base + UHSIC_MISC_CFG0); @@ -2292,8 +2435,6 @@ static int uhsic_phy_bus_reset(struct tegra_usb_phy *phy) val = readl(base + HOSTPC1_DEVLC); val &= ~HOSTPC1_DEVLC_PTS(HOSTPC1_DEVLC_PTS_MASK); val |= HOSTPC1_DEVLC_PTS(HOSTPC1_DEVLC_PTS_HSIC); - val &= ~HOSTPC1_DEVLC_PSPD(HOSTPC1_DEVLC_PSPD_MASK); - val |= HOSTPC1_DEVLC_PSPD(HOSTPC1_DEVLC_PSPD_HIGH_SPEED); val &= ~HOSTPC1_DEVLC_STS; writel(val, base + HOSTPC1_DEVLC); /* wait here, otherwise HOSTPC1_DEVLC_PSPD will timeout */ @@ -2373,10 +2514,6 @@ int uhsic_phy_resume(struct tegra_usb_phy *phy) { DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst); - uhsic_phy_restore_start(phy); - usb_phy_bringup_host_controller(phy); - uhsic_phy_restore_end(phy); - return 0; } @@ -2528,6 +2665,9 @@ static void ulpi_null_phy_close(struct tegra_usb_phy *phy) static int ulpi_null_phy_power_off(struct tegra_usb_phy *phy) { + unsigned int val; + void __iomem *base = phy->regs; + DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst); if (!phy->phy_clk_on) { @@ -2539,6 +2679,9 @@ static int ulpi_null_phy_power_off(struct tegra_usb_phy *phy) phy->phy_clk_on = false; phy->hw_accessible = false; ulpi_null_phy_set_tristate(true); + val = readl(base + ULPIS2S_CTRL); + val &= ~ULPIS2S_PLLU_MASTER_BLASTER60; + writel(val, base + ULPIS2S_CTRL); return 0; } @@ -2563,7 +2706,16 @@ static int ulpi_null_phy_init(struct tegra_usb_phy *phy) static int ulpi_null_phy_irq(struct tegra_usb_phy *phy) { + unsigned long val; + void __iomem *base = phy->regs; + usb_phy_fence_read(phy); + if (phy->bus_reseting){ + val = readl(base + USB_USBCMD); + val |= USB_USBCMD_RS; + writel(val, base + USB_USBCMD); + phy->bus_reseting = false; + } return IRQ_HANDLED; } @@ -2589,6 +2741,23 @@ static int ulpi_null_phy_cmd_reset(struct tegra_usb_phy *phy) return 0; } +static int ulpi_phy_bus_reset(struct tegra_usb_phy *phy) +{ + unsigned long val; + void __iomem *base = phy->regs; + + DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst); + + /*DISABLE RUN BIT */ + + val = readl(base + USB_USBCMD); + val &= ~USB_USBCMD_RS; + writel(val, base + USB_USBCMD); + phy->bus_reseting = true; + + return 0; +} + static int ulpi_null_phy_restore(struct tegra_usb_phy *phy) { struct tegra_ulpi_config *config = &phy->pdata->u_cfg.ulpi; @@ -2761,6 +2930,7 @@ static int ulpi_null_phy_power_on(struct tegra_usb_phy *phy) } udelay(10); + phy->bus_reseting = false; phy->phy_clk_on = true; phy->hw_accessible = true; @@ -2823,6 +2993,7 @@ static struct tegra_usb_phy_ops utmi_phy_ops = { static struct tegra_usb_phy_ops uhsic_phy_ops = { .open = uhsic_phy_open, + .close = uhsic_phy_close, .irq = uhsic_phy_irq, .power_on = uhsic_phy_power_on, .power_off = uhsic_phy_power_off, @@ -2844,6 +3015,7 @@ static struct tegra_usb_phy_ops ulpi_null_phy_ops = { .resume = ulpi_null_phy_resume, .post_resume = ulpi_null_phy_post_resume, .reset = ulpi_null_phy_cmd_reset, + .bus_reset = ulpi_phy_bus_reset, }; static struct tegra_usb_phy_ops ulpi_link_phy_ops; diff --git a/arch/arm/mach-tegra/fuse.c b/arch/arm/mach-tegra/tegra_fuse.c index 6df9da994fb9..11328c4cada3 100644 --- a/arch/arm/mach-tegra/fuse.c +++ b/arch/arm/mach-tegra/tegra_fuse.c @@ -1,5 +1,5 @@ /* - * arch/arm/mach-tegra/fuse.c + * arch/arm/mach-tegra/tegra_fuse.c * * Copyright (C) 2010 Google, Inc. * Copyright (C) 2010-2012 NVIDIA Corp. @@ -62,6 +62,21 @@ #endif +#define TEGRA_AGE_0_6 0x2cc /*Spare bit 34*/ +#define TEGRA_AGE_1_6 0x308 /*Spare bit 49*/ +#define TEGRA_AGE_0_5 0x2c8 /*Spare bit 33*/ +#define TEGRA_AGE_1_5 0x304 /*Spare bit 48*/ +#define TEGRA_AGE_0_4 0x2c4 /*Spare bit 32*/ +#define TEGRA_AGE_1_4 0x300 /*Spare bit 47*/ +#define TEGRA_AGE_0_3 0x2c0 /*Spare bit 31*/ +#define TEGRA_AGE_1_3 0x2fc /*Spare bit 46*/ +#define TEGRA_AGE_0_2 0x2bc /*Spare bit 30*/ +#define TEGRA_AGE_1_2 0x2f8 /*Spare bit 45*/ +#define TEGRA_AGE_0_1 0x2b8 /*Spare bit 29*/ +#define TEGRA_AGE_1_1 0x2f4 /*Spare bit 44*/ +#define TEGRA_AGE_0_0 0x2b4 /*Spare bit 28*/ +#define TEGRA_AGE_1_0 0x2f0 /*Spare bit 43*/ + struct tegra_id { enum tegra_chipid chipid; unsigned int major, minor, netlist, patch; @@ -172,6 +187,35 @@ int tegra_fuse_get_tsensor_spare_bits(u32 *spare_bits) EXPORT_SYMBOL(tegra_fuse_get_tsensor_spare_bits); #endif +#define TEGRA_READ_AGE_BIT(n, bit, age) {\ + bit = tegra_fuse_readl(TEGRA_AGE_0_##n);\ + bit |= tegra_fuse_readl(TEGRA_AGE_1_##n);\ + bit = bit << n;\ + age |= bit;\ +} + +int tegra_get_age(void) +{ + int linear_age, age_bit; + linear_age = age_bit = 0; + + TEGRA_READ_AGE_BIT(6, age_bit, linear_age); + TEGRA_READ_AGE_BIT(5, age_bit, linear_age); + TEGRA_READ_AGE_BIT(4, age_bit, linear_age); + TEGRA_READ_AGE_BIT(3, age_bit, linear_age); + TEGRA_READ_AGE_BIT(2, age_bit, linear_age); + TEGRA_READ_AGE_BIT(1, age_bit, linear_age); + TEGRA_READ_AGE_BIT(0, age_bit, linear_age); + + /*Default Aug, 2012*/ + if (linear_age <= 0) + linear_age = 8; + + pr_info("TEGRA: Linear age: %d\n", linear_age); + + return linear_age; +} + unsigned long long tegra_chip_uid(void) { #if defined(CONFIG_ARCH_TEGRA_2x_SOC) diff --git a/arch/arm/mach-tegra/tegra_odm_fuses.c b/arch/arm/mach-tegra/tegra_odm_fuses.c index 06b831c31967..ae82ed56f0f0 100644 --- a/arch/arm/mach-tegra/tegra_odm_fuses.c +++ b/arch/arm/mach-tegra/tegra_odm_fuses.c @@ -53,6 +53,7 @@ #define NFUSES 64 #define STATE_IDLE (0x4 << 16) +#define SENSE_DONE (0x1 << 30) /* since fuse burning is irreversible, use this for testing */ #define ENABLE_FUSE_BURNING 1 @@ -607,6 +608,17 @@ static void fuse_program_array(int pgm_cycles) } fuse_power_disable(); + + /* + * Wait until done (polling) + * this one needs to use fuse_sense done, the FSM follows a periodic + * sequence that includes idle + */ + do { + udelay(1); + reg = tegra_fuse_readl(FUSE_CTRL); + } while ((reg & (0x1 << 30)) != SENSE_DONE); + } static int fuse_set(enum fuse_io_param io_param, u32 *param, int size) diff --git a/arch/arm/mach-tegra/tegra_usb_modem_power.c b/arch/arm/mach-tegra/tegra_usb_modem_power.c index bb9495a329a6..8e93a7cdca97 100644 --- a/arch/arm/mach-tegra/tegra_usb_modem_power.c +++ b/arch/arm/mach-tegra/tegra_usb_modem_power.c @@ -307,8 +307,6 @@ static int mdm_request_wakeable_irq(struct tegra_usb_modem *modem, if (ret) return ret; - tegra_gpio_enable(irq_gpio); - /* enable IRQ for GPIO */ *irq = gpio_to_irq(irq_gpio); @@ -400,7 +398,8 @@ static ssize_t load_unload_usb_host(struct device *dev, return count; } -static DEVICE_ATTR(load_host, 0666, show_usb_host, load_unload_usb_host); +static DEVICE_ATTR(load_host, S_IRUSR | S_IWUSR, show_usb_host, + load_unload_usb_host); static int mdm_init(struct tegra_usb_modem *modem, struct platform_device *pdev) { diff --git a/arch/arm/mach-tegra/tegra_usb_phy.h b/arch/arm/mach-tegra/tegra_usb_phy.h index 0dc4cd73c5e7..05aa88296619 100644 --- a/arch/arm/mach-tegra/tegra_usb_phy.h +++ b/arch/arm/mach-tegra/tegra_usb_phy.h @@ -80,6 +80,7 @@ struct tegra_usb_phy { struct clk *emc_clk; struct clk *sys_clk; struct regulator *vdd_reg; + struct regulator *hsic_reg; struct regulator *vbus_reg; struct tegra_usb_phy_ops *ops; struct tegra_xtal_freq *freq; @@ -95,6 +96,9 @@ struct tegra_usb_phy { bool remote_wakeup; bool hw_accessible; bool ulpi_clk_padout_ena; + bool pmc_sleepwalk; + bool bus_reseting; + bool linkphy_init; }; int usb_phy_reg_status_wait(void __iomem *reg, u32 mask, diff --git a/arch/arm/mach-tegra/timer-t3.c b/arch/arm/mach-tegra/timer-t3.c index f23873b214b2..b58fc9bbc4c0 100644 --- a/arch/arm/mach-tegra/timer-t3.c +++ b/arch/arm/mach-tegra/timer-t3.c @@ -72,10 +72,8 @@ static void __iomem *timer_reg_base = IO_ADDRESS(TEGRA_TMR1_BASE); #if defined(CONFIG_PM_SLEEP) static cpumask_t wake_timer_canceled; -#if defined(CONFIG_HOTPLUG_CPU) static cpumask_t wake_timer_ready; #endif -#endif #define timer_writel(value, reg) \ __raw_writel(value, (u32)timer_reg_base + (reg)) diff --git a/arch/arm/mach-tegra/timer.c b/arch/arm/mach-tegra/timer.c index 83d0e17b50c1..5771bfc9bdde 100644 --- a/arch/arm/mach-tegra/timer.c +++ b/arch/arm/mach-tegra/timer.c @@ -31,6 +31,7 @@ #include <linux/clk.h> #include <linux/io.h> #include <linux/syscore_ops.h> +#include <linux/rtc.h> #include <asm/mach/time.h> #include <asm/localtimer.h> @@ -238,6 +239,96 @@ void tegra_twd_resume(struct tegra_twd_context *context) } #endif +#ifdef CONFIG_RTC_CLASS +/** + * has_readtime - check rtc device has readtime ability + * @dev: current device + * @name_ptr: name to be returned + * + * This helper function checks to see if the rtc device can be + * used for reading time + */ +static int has_readtime(struct device *dev, void *name_ptr) +{ + struct rtc_device *candidate = to_rtc_device(dev); + + if (!candidate->ops->read_time) + return 0; + + return 1; +} + +/** + * tegra_get_linear_age - helper function to return linear age + * from Jan 2012. + * + * @return + * 1 - Jan 2012, + * 2 - Feb 2012, + * ..... + * 13 - Jan 2013 + */ +int tegra_get_linear_age(void) +{ + struct rtc_time tm; + int year, month, linear_age; + struct rtc_device *rtc_dev = NULL; + const char *name = NULL; + int ret; + struct device *dev = NULL; + + linear_age = -1; + year = month = 0; + dev = class_find_device(rtc_class, NULL, &name, has_readtime); + + if (!dev) { + pr_err("DVFS: No device with readtime capability\n"); + goto done; + } + + name = dev_name(dev); + + pr_info("DVFS: Got RTC device name:%s\n", name); + + if (name) + rtc_dev = rtc_class_open((char *)name); + + if (!rtc_dev) { + pr_err("DVFS: No RTC device\n"); + goto error_dev; + } + + ret = rtc_read_time(rtc_dev, &tm); + + if (ret < 0) { + pr_err("DVFS: Can't read RTC time\n"); + goto error_rtc; + } + + year = tm.tm_year; + /*Normalize it to 2012*/ + year -= 112; + month = tm.tm_mon + 1; + + if (year >= 0) + linear_age = year * 12 + month; + +error_rtc: + rtc_class_close(rtc_dev); +error_dev: + put_device(dev); +done: + return linear_age; + +} + +#else +int tegra_get_linear_age() +{ + return -1; +} +#endif + static void __init tegra_init_timer(void) { struct clk *clk; diff --git a/arch/arm/mach-tegra/timer.h b/arch/arm/mach-tegra/timer.h index 4a91792f5d99..47628330dceb 100644 --- a/arch/arm/mach-tegra/timer.h +++ b/arch/arm/mach-tegra/timer.h @@ -45,11 +45,14 @@ struct tegra_twd_context { int tegra_twd_get_state(struct tegra_twd_context *context); void tegra_twd_suspend(struct tegra_twd_context *context); void tegra_twd_resume(struct tegra_twd_context *context); +int tegra_get_linear_age(void); #else static inline int tegra_twd_get_state(struct tegra_twd_context *context) { return -ENODEV; } static inline void tegra_twd_suspend(struct tegra_twd_context *context) {} static inline void tegra_twd_resume(struct tegra_twd_context *context) {} +static inline int tegra_get_linear_age() +{ return -1; } #endif #endif /* _MACH_TEGRA_TIMER_H_ */ diff --git a/arch/arm/mach-tegra/usb_phy.c b/arch/arm/mach-tegra/usb_phy.c index 654976b7b1c1..b5d3dc575e0c 100644 --- a/arch/arm/mach-tegra/usb_phy.c +++ b/arch/arm/mach-tegra/usb_phy.c @@ -137,7 +137,7 @@ static irqreturn_t usb_phy_dev_vbus_pmu_irq_thr(int irq, void *pdata) if (phy->vdd_reg && !phy->vdd_reg_on) { regulator_enable(phy->vdd_reg); - phy->vdd_reg_on = 1; + phy->vdd_reg_on = true; /* * Optimal time to get the regulator turned on * before detecting vbus interrupt. @@ -224,7 +224,6 @@ fail_ctrlr_clk: clk_put(phy->pllu_clk); fail_pll: - return err; } @@ -234,29 +233,34 @@ struct tegra_usb_phy *tegra_usb_phy_open(struct platform_device *pdev) struct tegra_usb_platform_data *pdata; struct resource *res; int err; + int plat_data_size = sizeof(struct tegra_usb_platform_data); DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, pdev->id); pdata = dev_get_platdata(&pdev->dev); if (!pdata) { dev_err(&pdev->dev, "inst:[%d] Platform data missing\n", pdev->id); - return ERR_PTR(-EINVAL); + err = -EINVAL; + goto fail_inval; } - phy = kzalloc(sizeof(struct tegra_usb_phy), GFP_KERNEL); + phy = devm_kzalloc(&pdev->dev, sizeof(struct tegra_usb_phy), GFP_KERNEL); if (!phy) { ERR("inst:[%d] malloc usb phy failed\n", pdev->id); - return ERR_PTR(-ENOMEM); + err = -ENOMEM; + goto fail_nomem; } - phy->pdata = kzalloc(sizeof(struct tegra_usb_platform_data), GFP_KERNEL); + phy->pdata = devm_kzalloc(&pdev->dev, plat_data_size, GFP_KERNEL); if (!phy->pdata) { ERR("inst:[%d] malloc usb phy pdata failed\n", pdev->id); - kfree(phy); - return ERR_PTR(-ENOMEM); + devm_kfree(&pdev->dev, phy); + err = -ENOMEM; + goto fail_nomem; } - memcpy(phy->pdata, pdata, sizeof(struct tegra_usb_platform_data)); + memcpy(phy->pdata, pdata, plat_data_size); + phy->pdev = pdev; phy->inst = pdev->id; @@ -276,7 +280,7 @@ struct tegra_usb_phy *tegra_usb_phy_open(struct platform_device *pdev) goto fail_io; } - phy->vdd_reg = regulator_get(NULL, "avdd_usb"); + phy->vdd_reg = regulator_get(&pdev->dev, "avdd_usb"); if (IS_ERR_OR_NULL(phy->vdd_reg)) { ERR("inst:[%d] couldn't get regulator avdd_usb: %ld\n", phy->inst, PTR_ERR(phy->vdd_reg)); @@ -312,6 +316,7 @@ struct tegra_usb_phy *tegra_usb_phy_open(struct platform_device *pdev) instance : %d\n", PTR_ERR(phy->vbus_reg), phy->inst); err = PTR_ERR(phy->vbus_reg); + phy->vbus_reg = NULL; goto fail_init; } } else { @@ -322,8 +327,6 @@ struct tegra_usb_phy *tegra_usb_phy_open(struct platform_device *pdev) req failed\n", phy->inst); goto fail_init; } - if (gpio < TEGRA_NR_GPIOS) - tegra_gpio_enable(gpio); if (gpio_direction_output(gpio, !phy->pdata->u_data.host.vbus_gpio_inverted) < 0) { ERR("inst:[%d] host vbus gpio \ dir failed\n", phy->inst); @@ -377,8 +380,11 @@ fail_clk: regulator_put(phy->vdd_reg); iounmap(phy->regs); fail_io: - kfree(phy); + devm_kfree(&pdev->dev, phy->pdata); + devm_kfree(&pdev->dev, phy); +fail_nomem: +fail_inval: return ERR_PTR(err); } EXPORT_SYMBOL_GPL(tegra_usb_phy_open); @@ -418,11 +424,10 @@ void tegra_usb_phy_close(struct tegra_usb_phy *phy) regulator_put(phy->vdd_reg); } - tegra_usb_phy_release_clocks(phy); - kfree(phy->pdata); - kfree(phy); + devm_kfree(&phy->pdev->dev, phy->pdata); + devm_kfree(&phy->pdev->dev, phy); } EXPORT_SYMBOL_GPL(tegra_usb_phy_close); @@ -435,6 +440,7 @@ irqreturn_t tegra_usb_phy_irq(struct tegra_usb_phy *phy) return status; } + int tegra_usb_phy_init(struct tegra_usb_phy *phy) { int status = 0; @@ -472,25 +478,30 @@ int tegra_usb_phy_power_off(struct tegra_usb_phy *phy) clk_disable(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) + !phy->pdata->u_data.host.remote_wakeup_supported) { clk_disable(phy->ctrlr_clk); + phy->ctrl_clk_on = false; + if (phy->vdd_reg && phy->vdd_reg_on) { + regulator_disable(phy->vdd_reg); + phy->vdd_reg_on = false; + } + } } 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 + /* In device mode clock regulator/clocks will be turned off + * only if pmu interrupt is present on the board and host mode + * support through OTG is supported on the board. */ - if (phy->pdata->u_data.dev.vbus_pmu_irq) { + if (phy->pdata->u_data.dev.vbus_pmu_irq && + phy->pdata->builtin_host_disabled) { clk_disable(phy->ctrlr_clk); phy->ctrl_clk_on = false; + if (phy->vdd_reg && phy->vdd_reg_on) { + regulator_disable(phy->vdd_reg); + phy->vdd_reg_on = false; + } } } - if (phy->vdd_reg && phy->vdd_reg_on) - if (phy->pdata->has_hostpc || - phy->pdata->builtin_host_disabled) { - regulator_disable(phy->vdd_reg); - phy->vdd_reg_on = false; - } - phy->phy_power_on = false; return err; @@ -552,6 +563,7 @@ int tegra_usb_phy_reset(struct tegra_usb_phy *phy) return status; } + int tegra_usb_phy_pre_suspend(struct tegra_usb_phy *phy) { int status = 0; @@ -566,6 +578,7 @@ int tegra_usb_phy_pre_suspend(struct tegra_usb_phy *phy) return status; } + int tegra_usb_phy_suspend(struct tegra_usb_phy *phy) { int err = 0; @@ -581,6 +594,7 @@ int tegra_usb_phy_suspend(struct tegra_usb_phy *phy) return err; } + int tegra_usb_phy_post_suspend(struct tegra_usb_phy *phy) { int status = 0; @@ -595,6 +609,7 @@ int tegra_usb_phy_post_suspend(struct tegra_usb_phy *phy) return status; } + int tegra_usb_phy_pre_resume(struct tegra_usb_phy *phy, bool remote_wakeup) { int status = 0; @@ -609,6 +624,7 @@ int tegra_usb_phy_pre_resume(struct tegra_usb_phy *phy, bool remote_wakeup) return status; } + int tegra_usb_phy_resume(struct tegra_usb_phy *phy) { int err = 0; @@ -625,6 +641,7 @@ int tegra_usb_phy_resume(struct tegra_usb_phy *phy) return err; } + int tegra_usb_phy_post_resume(struct tegra_usb_phy *phy) { int status = 0; @@ -639,6 +656,7 @@ int tegra_usb_phy_post_resume(struct tegra_usb_phy *phy) return status; } + int tegra_usb_phy_port_power(struct tegra_usb_phy *phy) { int status = 0; @@ -650,6 +668,7 @@ int tegra_usb_phy_port_power(struct tegra_usb_phy *phy) return status; } + int tegra_usb_phy_bus_reset(struct tegra_usb_phy *phy) { int status = 0; diff --git a/arch/arm/mach-tegra/wakeups-t2.h b/arch/arm/mach-tegra/wakeups-t2.h index 955b351a71fa..142d4c76558b 100644 --- a/arch/arm/mach-tegra/wakeups-t2.h +++ b/arch/arm/mach-tegra/wakeups-t2.h @@ -27,9 +27,6 @@ #error "Tegra 2 wakeup sources valid only for CONFIG_ARCH_TEGRA_2x_SOC" #endif -int tegra_irq_to_wake(int irq); -int tegra_wake_to_irq(int wake); - #define TEGRA_WAKE_GPIO_PO5 0 #define TEGRA_WAKE_GPIO_PV3 1 #define TEGRA_WAKE_GPIO_PL1 2 diff --git a/arch/arm/mach-tegra/wakeups-t3.c b/arch/arm/mach-tegra/wakeups-t3.c index ef471cb035db..dd042f8fafc0 100644 --- a/arch/arm/mach-tegra/wakeups-t3.c +++ b/arch/arm/mach-tegra/wakeups-t3.c @@ -66,7 +66,8 @@ static struct tegra_wake_info tegra_wake_event_data_t3[] = { {-EINVAL, POLARITY_NONE}, /* TEGRA_USB3_ID, */ /* wake38 */ {INT_USB, POLARITY_LEVEL_HI}, /* TEGRA_USB1_UTMIP, */ /* wake39 */ {INT_USB2, POLARITY_LEVEL_HI}, /* TEGRA_USB2_UTMIP, */ /* wake40 */ - {INT_USB3, POLARITY_LEVEL_HI} /* TEGRA_USB3_UTMIP, */ /* wake41 */ + {INT_USB3, POLARITY_LEVEL_HI}, /* TEGRA_USB3_UTMIP, */ /* wake41 */ + {INT_USB2, POLARITY_LEVEL_HI}, /* TEGRA_USB2_UHSIC, */ /* wake42 */ }; struct tegra_wake_info *tegra_wake_event_data = tegra_wake_event_data_t3; |