summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorMarcel Ziswiler <marcel.ziswiler@toradex.com>2012-09-10 14:53:27 +0200
committerMarcel Ziswiler <marcel.ziswiler@toradex.com>2012-09-10 15:04:19 +0200
commitd5bbf34613a877dbe3da847fa0432da8c6721e73 (patch)
tree902a90fd7eda61aad7abae9c35b0da2e7a786995 /arch
parentc6c1f7a2c194f1a2291a15c6691c0d6785f8976e (diff)
parent336961dd3cf9c39456dd9657e8f205718740c797 (diff)
Merge branch 'l4t/l4t-r16' into colibri
Merge with latest NVIDIA L4T R16. Only real conflict concerning inverted VBUS gpio support.
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/Kconfig20
-rw-r--r--arch/arm/common/fiq_debugger.c3
-rw-r--r--arch/arm/configs/tegra3_android_defconfig22
-rw-r--r--arch/arm/configs/tegra3_defconfig11
-rw-r--r--arch/arm/configs/tegra_android_defconfig7
-rw-r--r--arch/arm/configs/tegra_defconfig3
-rw-r--r--arch/arm/configs/tegra_p1852_gnu_linux_defconfig7
-rw-r--r--arch/arm/configs/tegra_p852_gnu_linux_defconfig1
-rw-r--r--arch/arm/include/asm/dma-mapping.h36
-rw-r--r--arch/arm/include/asm/mach/map.h2
-rw-r--r--arch/arm/include/asm/memory.h7
-rw-r--r--arch/arm/kernel/sleep.S4
-rw-r--r--arch/arm/mach-tegra/Kconfig55
-rw-r--r--arch/arm/mach-tegra/Makefile16
-rw-r--r--arch/arm/mach-tegra/ahb.c3
-rw-r--r--arch/arm/mach-tegra/apbio.c24
-rw-r--r--arch/arm/mach-tegra/apbio.h12
-rw-r--r--arch/arm/mach-tegra/baseband-xmm-power.c815
-rw-r--r--arch/arm/mach-tegra/baseband-xmm-power.h25
-rw-r--r--arch/arm/mach-tegra/baseband-xmm-power2.c525
-rw-r--r--arch/arm/mach-tegra/board-aruba-panel.c5
-rw-r--r--arch/arm/mach-tegra/board-aruba-power.c1
-rw-r--r--arch/arm/mach-tegra/board-aruba.c8
-rw-r--r--arch/arm/mach-tegra/board-cardhu-kbc.c15
-rw-r--r--arch/arm/mach-tegra/board-cardhu-memory.c722
-rw-r--r--arch/arm/mach-tegra/board-cardhu-panel.c661
-rw-r--r--arch/arm/mach-tegra/board-cardhu-pinmux.c46
-rw-r--r--arch/arm/mach-tegra/board-cardhu-pm298-power-rails.c11
-rw-r--r--arch/arm/mach-tegra/board-cardhu-pm299-power-rails.c11
-rw-r--r--arch/arm/mach-tegra/board-cardhu-power.c70
-rw-r--r--arch/arm/mach-tegra/board-cardhu-sdhci.c21
-rw-r--r--arch/arm/mach-tegra/board-cardhu-sensors.c219
-rw-r--r--arch/arm/mach-tegra/board-cardhu.c586
-rw-r--r--arch/arm/mach-tegra/board-cardhu.h5
-rw-r--r--arch/arm/mach-tegra/board-enterprise-baseband.c165
-rw-r--r--arch/arm/mach-tegra/board-enterprise-memory.c735
-rw-r--r--arch/arm/mach-tegra/board-enterprise-panel.c58
-rw-r--r--arch/arm/mach-tegra/board-enterprise-pinmux.c10
-rw-r--r--arch/arm/mach-tegra/board-enterprise-power.c76
-rw-r--r--arch/arm/mach-tegra/board-enterprise-sdhci.c12
-rw-r--r--arch/arm/mach-tegra/board-enterprise-sensors.c9
-rw-r--r--arch/arm/mach-tegra/board-enterprise.c380
-rw-r--r--arch/arm/mach-tegra/board-enterprise.h3
-rw-r--r--arch/arm/mach-tegra/board-harmony-panel.c5
-rw-r--r--arch/arm/mach-tegra/board-harmony-pcie.c3
-rw-r--r--arch/arm/mach-tegra/board-harmony.c155
-rw-r--r--arch/arm/mach-tegra/board-kai-kbc.c10
-rw-r--r--arch/arm/mach-tegra/board-kai-panel.c74
-rw-r--r--arch/arm/mach-tegra/board-kai-pinmux.c8
-rw-r--r--arch/arm/mach-tegra/board-kai-power.c21
-rw-r--r--arch/arm/mach-tegra/board-kai-sdhci.c18
-rw-r--r--arch/arm/mach-tegra/board-kai-sensors.c118
-rw-r--r--arch/arm/mach-tegra/board-kai.c251
-rw-r--r--arch/arm/mach-tegra/board-kai.h3
-rw-r--r--arch/arm/mach-tegra/board-p1852-panel.c64
-rw-r--r--arch/arm/mach-tegra/board-p1852-pinmux.c213
-rw-r--r--arch/arm/mach-tegra/board-p1852-sdhci.c17
-rw-r--r--arch/arm/mach-tegra/board-p1852.c357
-rw-r--r--arch/arm/mach-tegra/board-p1852.h6
-rw-r--r--arch/arm/mach-tegra/board-trimslice.c3
-rw-r--r--arch/arm/mach-tegra/board-ventana-panel.c34
-rw-r--r--arch/arm/mach-tegra/board-ventana-pinmux.c4
-rw-r--r--arch/arm/mach-tegra/board-ventana-power.c13
-rw-r--r--arch/arm/mach-tegra/board-ventana-sdhci.c13
-rw-r--r--arch/arm/mach-tegra/board-ventana-sensors.c149
-rw-r--r--arch/arm/mach-tegra/board-ventana.c250
-rw-r--r--arch/arm/mach-tegra/board-whistler-baseband.c154
-rw-r--r--arch/arm/mach-tegra/board-whistler-panel.c23
-rw-r--r--arch/arm/mach-tegra/board-whistler-pinmux.c14
-rw-r--r--arch/arm/mach-tegra/board-whistler-power.c1
-rw-r--r--arch/arm/mach-tegra/board-whistler-sdhci.c11
-rw-r--r--arch/arm/mach-tegra/board-whistler-sensors.c16
-rw-r--r--arch/arm/mach-tegra/board-whistler.c154
-rw-r--r--arch/arm/mach-tegra/board.h17
-rw-r--r--arch/arm/mach-tegra/clock.c32
-rw-r--r--arch/arm/mach-tegra/clock.h12
-rw-r--r--arch/arm/mach-tegra/common-t2.c6
-rw-r--r--arch/arm/mach-tegra/common.c149
-rw-r--r--arch/arm/mach-tegra/cpu-tegra.c13
-rw-r--r--arch/arm/mach-tegra/cpu-tegra.h1
-rw-r--r--arch/arm/mach-tegra/cpu-tegra3.c90
-rw-r--r--arch/arm/mach-tegra/cpuquiet.c433
-rw-r--r--arch/arm/mach-tegra/devices.c133
-rw-r--r--arch/arm/mach-tegra/devices.h11
-rw-r--r--arch/arm/mach-tegra/dvfs.c25
-rw-r--r--arch/arm/mach-tegra/dvfs.h23
-rw-r--r--arch/arm/mach-tegra/headsmp.S4
-rw-r--r--arch/arm/mach-tegra/include/mach/clk.h12
-rw-r--r--arch/arm/mach-tegra/include/mach/dc.h23
-rw-r--r--arch/arm/mach-tegra/include/mach/iomap.h9
-rw-r--r--arch/arm/mach-tegra/include/mach/iovmm.h67
-rw-r--r--arch/arm/mach-tegra/include/mach/latency_allowance.h4
-rw-r--r--arch/arm/mach-tegra/include/mach/legacy_irq.h2
-rw-r--r--arch/arm/mach-tegra/include/mach/nvmap.h158
-rw-r--r--arch/arm/mach-tegra/include/mach/sdhci.h9
-rw-r--r--arch/arm/mach-tegra/include/mach/tegra_p1852_pdata.h7
-rw-r--r--arch/arm/mach-tegra/include/mach/tegra_usb_modem_power.h12
-rw-r--r--arch/arm/mach-tegra/include/mach/thermal.h91
-rw-r--r--arch/arm/mach-tegra/include/mach/usb_phy.h239
-rw-r--r--arch/arm/mach-tegra/iovmm-gart.c6
-rw-r--r--arch/arm/mach-tegra/iovmm-smmu.c50
-rw-r--r--arch/arm/mach-tegra/iovmm.c2
-rw-r--r--arch/arm/mach-tegra/irq.c52
-rw-r--r--arch/arm/mach-tegra/p852/board-p852-panel.c5
-rw-r--r--arch/arm/mach-tegra/p852/board-p852.c144
-rw-r--r--arch/arm/mach-tegra/p852/board-p852.h1
-rw-r--r--arch/arm/mach-tegra/pcie.c569
-rw-r--r--arch/arm/mach-tegra/pinmux-t2-tables.c4
-rw-r--r--arch/arm/mach-tegra/pinmux-t3-tables.c473
-rw-r--r--arch/arm/mach-tegra/platsmp.c5
-rw-r--r--arch/arm/mach-tegra/pm-irq.c63
-rw-r--r--arch/arm/mach-tegra/pm-irq.h2
-rw-r--r--arch/arm/mach-tegra/pm.c28
-rw-r--r--arch/arm/mach-tegra/powergate.c2
-rw-r--r--arch/arm/mach-tegra/sleep-t3.S5
-rw-r--r--arch/arm/mach-tegra/sleep.h10
-rw-r--r--arch/arm/mach-tegra/syncpt.c100
-rw-r--r--arch/arm/mach-tegra/tegra2_clocks.c47
-rw-r--r--arch/arm/mach-tegra/tegra2_host1x_devices.h26
-rw-r--r--arch/arm/mach-tegra/tegra2_mc.c9
-rw-r--r--arch/arm/mach-tegra/tegra2_usb_phy.c1938
-rw-r--r--arch/arm/mach-tegra/tegra3_actmon.c4
-rw-r--r--arch/arm/mach-tegra/tegra3_clocks.c301
-rw-r--r--arch/arm/mach-tegra/tegra3_dvfs.c276
-rw-r--r--arch/arm/mach-tegra/tegra3_emc.c241
-rw-r--r--arch/arm/mach-tegra/tegra3_emc.h4
-rw-r--r--arch/arm/mach-tegra/tegra3_host1x_devices.h26
-rw-r--r--arch/arm/mach-tegra/tegra3_speedo.c37
-rw-r--r--arch/arm/mach-tegra/tegra3_thermal.c712
-rw-r--r--arch/arm/mach-tegra/tegra3_throttle.c326
-rw-r--r--arch/arm/mach-tegra/tegra3_tsensor.c6
-rw-r--r--arch/arm/mach-tegra/tegra3_usb_phy.c2870
-rw-r--r--arch/arm/mach-tegra/tegra_odm_fuses.c2
-rw-r--r--arch/arm/mach-tegra/tegra_usb_modem_power.c331
-rw-r--r--arch/arm/mach-tegra/tegra_usb_phy.h107
-rw-r--r--arch/arm/mach-tegra/timer-t3.c7
-rw-r--r--arch/arm/mach-tegra/usb_phy.c3460
-rw-r--r--arch/arm/mach-tegra/wakeups-t2.c120
-rw-r--r--arch/arm/mach-tegra/wakeups-t2.h62
-rw-r--r--arch/arm/mach-tegra/wakeups-t3.c140
-rw-r--r--arch/arm/mach-tegra/wakeups-t3.h76
-rw-r--r--arch/arm/mach-tegra/wakeups.c130
-rw-r--r--arch/arm/mach-tegra/wakeups.h48
-rw-r--r--arch/arm/mach-tegra/wdt-recovery.c10
-rw-r--r--arch/arm/mm/Kconfig11
-rw-r--r--arch/arm/mm/Makefile8
-rw-r--r--arch/arm/mm/dma-na-mapping.c748
-rw-r--r--arch/arm/mm/init.c3
-rw-r--r--arch/arm/mm/mm.h5
-rw-r--r--arch/arm/mm/mmu.c36
-rw-r--r--arch/arm/mm/pageattr.c9
-rw-r--r--arch/arm/mm/proc-v7.S6
-rw-r--r--arch/arm/vfp/vfpmodule.c16
153 files changed, 14863 insertions, 7987 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 3c3b868948aa..16b259ab7aac 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1155,6 +1155,14 @@ config ARM_ERRATA_460075
ACTLR register. Note that setting specific bits in the ACTLR register
may not be available in non-secure mode.
+config ARM_ERRATA_716044
+ bool "ARM errata: an uncacheable load multiple instruction can cause a deadlock"
+ depends on CPU_V7
+ help
+ Under some rare circumstances, an uncacheable load multiple
+ instruction (LDRD, LDM, VLDM, VLD1, VLD2, VLD3, VLD4) can cause
+ a processor deadlock.
+
config ARM_ERRATA_742230
bool "ARM errata: DMB operation may be faulty"
depends on CPU_V7 && SMP
@@ -1396,6 +1404,8 @@ config PCI_HOST_ITE8152
source "drivers/pci/Kconfig"
+source "drivers/pci/pcie/Kconfig"
+
source "drivers/pcmcia/Kconfig"
endmenu
@@ -1688,6 +1698,14 @@ config HW_PERF_EVENTS
Enable hardware performance counter support for perf events. If
disabled, perf events will use software events only.
+config ARCH_HAS_SUSPEND_PAGETABLE
+ bool
+ help
+ This option indicates the platform architecture installs its own
+ 1:1 pagetable during CPU suspend/resume codepaths. This means the
+ patching of the pagetable as part of reenabling the MMU isn't
+ needed in the ARM common CPU resume codepath. If in doubt, say N.
+
source "mm/Kconfig"
config FORCE_MAX_ZONEORDER
@@ -2103,6 +2121,8 @@ endif
source "drivers/cpuidle/Kconfig"
+source "drivers/cpuquiet/Kconfig"
+
endmenu
menu "Floating point emulation"
diff --git a/arch/arm/common/fiq_debugger.c b/arch/arm/common/fiq_debugger.c
index 3ed18ae2ed80..a98d4a3b8fac 100644
--- a/arch/arm/common/fiq_debugger.c
+++ b/arch/arm/common/fiq_debugger.c
@@ -827,6 +827,9 @@ static void debug_fiq(struct fiq_glue_handler *h, void *regs, void *svc_sp)
unsigned int this_cpu = THREAD_INFO(svc_sp)->cpu;
bool need_irq;
+ /* Spew regs and callstack immediately after entering FIQ handler */
+ debug_fiq_exec(state, "allregs", regs, svc_sp);
+ debug_fiq_exec(state, "bt", regs, svc_sp);
need_irq = debug_handle_uart_interrupt(state, this_cpu, regs, svc_sp);
if (need_irq)
debug_force_irq(state);
diff --git a/arch/arm/configs/tegra3_android_defconfig b/arch/arm/configs/tegra3_android_defconfig
index 4aab2283e215..0ab4493d3205 100644
--- a/arch/arm/configs/tegra3_android_defconfig
+++ b/arch/arm/configs/tegra3_android_defconfig
@@ -26,6 +26,9 @@ CONFIG_ARCH_TEGRA=y
CONFIG_GPIO_PCA953X=y
CONFIG_ARCH_TEGRA_3x_SOC=y
CONFIG_TEGRA_PCI=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_PCIEASPM=y
+CONFIG_PCIEASPM_POWERSAVE=y
CONFIG_MACH_CARDHU=y
CONFIG_MACH_TEGRA_ENTERPRISE=y
CONFIG_MACH_KAI=y
@@ -173,13 +176,13 @@ CONFIG_BT_HCIUART=y
CONFIG_BT_HCIUART_H4=y
CONFIG_BT_HCIUART_LL=y
CONFIG_BT_BLUESLEEP=y
-CONFIG_BT_TIBLUESLEEP=y
CONFIG_BT_WILINK=m
CONFIG_CFG80211=m
CONFIG_NL80211_TESTMODE=y
CONFIG_LIB80211=m
CONFIG_MAC80211=m
CONFIG_RFKILL=y
+CONFIG_RFKILL_GPIO=y
CONFIG_CAIF=y
CONFIG_NFC=y
CONFIG_PN544_NFC=y
@@ -191,7 +194,7 @@ CONFIG_AD525X_DPOT_I2C=y
CONFIG_APDS9802ALS=y
CONFIG_SENSORS_NCT1008=y
CONFIG_UID_STAT=y
-CONFIG_BCM4329_RFKILL=y
+# CONFIG_BCM4329_RFKILL is not set
CONFIG_TEGRA_CRYPTO_DEV=y
CONFIG_MAX1749_VIBRATOR=y
CONFIG_EEPROM_AT24=y
@@ -219,6 +222,7 @@ CONFIG_DM_CRYPT=y
CONFIG_DM_UEVENT=y
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
+CONFIG_TUN=y
# CONFIG_NETDEV_10000 is not set
CONFIG_BCM4329=m
CONFIG_BCM4329_FIRST_SCAN=y
@@ -229,6 +233,7 @@ CONFIG_BCM4329_HW_OOB=y
CONFIG_BCM4329_OOB_INTR_ONLY=y
CONFIG_BCM4329_CSCAN_ENABLE=y
CONFIG_BCMDHD=m
+CONFIG_DHD_ENABLE_P2P=y
CONFIG_BCMDHD_CFG80211=y
CONFIG_BCMDHD_WIFI_CONTROL_FUNC=y
CONFIG_BCMDHD_HW_OOB=y
@@ -292,6 +297,7 @@ CONFIG_SPI_TEGRA=y
CONFIG_SPI_SLAVE_TEGRA=y
CONFIG_DEBUG_GPIO=y
CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_RC5T583=y
CONFIG_POWER_SUPPLY=y
CONFIG_BATTERY_BQ20Z75=y
CONFIG_BATTERY_BQ27x00=y
@@ -307,16 +313,22 @@ CONFIG_MFD_TPS6586X=y
CONFIG_MFD_TPS65910=y
CONFIG_MFD_MAX77663=y
CONFIG_MFD_TPS6591X=y
+CONFIG_MFD_RC5T583=y
CONFIG_MFD_TPS80031=y
CONFIG_GPADC_TPS80031=y
CONFIG_MFD_RICOH583=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_VIRTUAL_CONSUMER=y
+CONFIG_REGULATOR_USERSPACE_CONSUMER=y
+CONFIG_REGULATOR_GPIO=y
+CONFIG_REGULATOR_MAX8973=y
CONFIG_REGULATOR_MAX77663=y
+CONFIG_REGULATOR_RC5T583=y
CONFIG_REGULATOR_TPS6586X=y
CONFIG_REGULATOR_TPS65910=y
CONFIG_REGULATOR_TPS62360=y
+CONFIG_REGULATOR_TPS6238X0=y
CONFIG_REGULATOR_TPS6591X=y
CONFIG_REGULATOR_TPS80031=y
CONFIG_REGULATOR_RICOH583=y
@@ -328,13 +340,16 @@ CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
# CONFIG_TEGRA_AVP is not set
# CONFIG_TEGRA_MEDIASERVER is not set
CONFIG_TEGRA_NVAVP=y
+CONFIG_TEGRA_NVAVP_AUDIO=y
CONFIG_VIDEO_OV5650=y
+CONFIG_VIDEO_OV5640=y
CONFIG_VIDEO_OV9726=y
CONFIG_VIDEO_OV2710=y
CONFIG_VIDEO_AR0832=y
CONFIG_TORCH_SSL3250A=y
CONFIG_TORCH_TPS61050=y
CONFIG_VIDEO_SH532U=y
+CONFIG_VIDEO_AD5816=y
CONFIG_USB_VIDEO_CLASS=y
# CONFIG_USB_GSPCA is not set
# CONFIG_RADIO_ADAPTERS is not set
@@ -381,7 +396,7 @@ CONFIG_USB_SERIAL_OPTION=y
CONFIG_USB_SERIAL_BASEBAND=m
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_VBUS_DRAW=500
-CONFIG_USB_FSL_USB2=y
+CONFIG_USB_TEGRA=y
CONFIG_USB_G_ANDROID=y
CONFIG_USB_TEGRA_OTG=y
CONFIG_MMC=y
@@ -436,6 +451,7 @@ CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
CONFIG_PRINTK_TIME=y
CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_SECTION_MISMATCH=y
CONFIG_DEBUG_FS=y
CONFIG_LOCKUP_DETECTOR=y
# CONFIG_DETECT_HUNG_TASK is not set
diff --git a/arch/arm/configs/tegra3_defconfig b/arch/arm/configs/tegra3_defconfig
index 1243cb8ac51e..86d74c113a23 100644
--- a/arch/arm/configs/tegra3_defconfig
+++ b/arch/arm/configs/tegra3_defconfig
@@ -27,6 +27,9 @@ CONFIG_ARCH_TEGRA=y
CONFIG_GPIO_PCA953X=y
CONFIG_ARCH_TEGRA_3x_SOC=y
CONFIG_TEGRA_PCI=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_PCIEASPM=y
+CONFIG_PCIEASPM_POWERSAVE=y
CONFIG_MACH_CARDHU=y
CONFIG_MACH_TEGRA_ENTERPRISE=y
CONFIG_TEGRA_PWM=y
@@ -180,6 +183,7 @@ CONFIG_BT_HCIUART=y
CONFIG_BT_HCIUART_H4=y
CONFIG_BT_HCIUART_LL=y
CONFIG_BT_BLUESLEEP=y
+CONFIG_CFG80211=y
CONFIG_RFKILL=y
CONFIG_CAIF=y
CONFIG_NFC=y
@@ -192,7 +196,6 @@ CONFIG_AD525X_DPOT=y
CONFIG_AD525X_DPOT_I2C=y
CONFIG_ICS932S401=y
CONFIG_APDS9802ALS=y
-CONFIG_ISL29003=y
CONFIG_SENSORS_NCT1008=y
CONFIG_UID_STAT=y
CONFIG_BCM4329_RFKILL=y
@@ -290,8 +293,8 @@ CONFIG_SENSORS_TEGRA_TSENSOR=y
CONFIG_SENSORS_INA219=y
CONFIG_THERMAL=y
CONFIG_MFD_TPS6586X=y
-CONFIG_MFD_MAX8907C=y
CONFIG_MFD_TPS65910=y
+CONFIG_MFD_MAX8907C=y
CONFIG_MFD_MAX77663=y
CONFIG_MFD_TPS6591X=y
CONFIG_MFD_TPS80031=y
@@ -300,6 +303,7 @@ CONFIG_MFD_RICOH583=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_VIRTUAL_CONSUMER=y
+CONFIG_REGULATOR_USERSPACE_CONSUMER=y
CONFIG_REGULATOR_MAX8907C=y
CONFIG_REGULATOR_MAX77663=y
CONFIG_REGULATOR_TPS6586X=y
@@ -364,7 +368,7 @@ CONFIG_USB_SERIAL_OPTION=y
CONFIG_USB_SERIAL_BASEBAND=m
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_VBUS_DRAW=500
-CONFIG_USB_FSL_USB2=y
+CONFIG_USB_TEGRA=y
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_TEGRA_OTG=y
CONFIG_MMC=y
@@ -383,6 +387,7 @@ CONFIG_RTC_DRV_TPS80031=y
CONFIG_RTC_DRV_RC5T583=y
CONFIG_STAGING=y
CONFIG_IIO=y
+CONFIG_SENSORS_ISL29028=y
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT2_FS_POSIX_ACL=y
diff --git a/arch/arm/configs/tegra_android_defconfig b/arch/arm/configs/tegra_android_defconfig
index b679b4096996..eb6abec87b70 100644
--- a/arch/arm/configs/tegra_android_defconfig
+++ b/arch/arm/configs/tegra_android_defconfig
@@ -170,6 +170,7 @@ CONFIG_BT_HCIUART_LL=y
CONFIG_BT_BLUESLEEP=y
CONFIG_CFG80211=y
CONFIG_RFKILL=y
+CONFIG_RFKILL_GPIO=y
# CONFIG_FIRMWARE_IN_KERNEL is not set
CONFIG_BLK_DEV_LOOP=y
CONFIG_MISC_DEVICES=y
@@ -178,7 +179,7 @@ CONFIG_AD525X_DPOT_I2C=y
CONFIG_APDS9802ALS=y
CONFIG_SENSORS_NCT1008=y
CONFIG_UID_STAT=y
-CONFIG_BCM4329_RFKILL=y
+# CONFIG_BCM4329_RFKILL is not set
CONFIG_TEGRA_CRYPTO_DEV=y
CONFIG_MAX1749_VIBRATOR=y
CONFIG_MPU_SENSORS_TIMERIRQ=y
@@ -200,6 +201,7 @@ CONFIG_DM_CRYPT=y
CONFIG_DM_UEVENT=y
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
+CONFIG_TUN=y
CONFIG_R8169=y
# CONFIG_NETDEV_10000 is not set
CONFIG_BCM4329=m
@@ -324,7 +326,7 @@ CONFIG_USB_SERIAL_PL2303=y
CONFIG_USB_SERIAL_OPTION=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_VBUS_DRAW=500
-CONFIG_USB_FSL_USB2=y
+CONFIG_USB_TEGRA=y
CONFIG_USB_G_ANDROID=y
CONFIG_USB_TEGRA_OTG=y
CONFIG_MMC=y
@@ -380,6 +382,7 @@ CONFIG_TIMER_STATS=y
# CONFIG_DEBUG_PREEMPT is not set
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_VM=y
+CONFIG_FUNCTION_TRACER=y
CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_TWOFISH=y
# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/arm/configs/tegra_defconfig b/arch/arm/configs/tegra_defconfig
index 39a9d7314a12..e7b72881f054 100644
--- a/arch/arm/configs/tegra_defconfig
+++ b/arch/arm/configs/tegra_defconfig
@@ -271,6 +271,7 @@ CONFIG_BATTERY_BQ20Z75=y
CONFIG_CHARGER_GPIO=y
CONFIG_SENSORS_ADT7461=y
CONFIG_SENSORS_LM90=y
+CONFIG_THERMAL=y
CONFIG_MFD_TPS6586X=y
CONFIG_MFD_MAX8907C=y
CONFIG_REGULATOR=y
@@ -328,7 +329,7 @@ CONFIG_USB_SERIAL_PL2303=y
CONFIG_USB_SERIAL_OPTION=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_VBUS_DRAW=500
-CONFIG_USB_FSL_USB2=y
+CONFIG_USB_TEGRA=y
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_TEGRA_OTG=y
CONFIG_MMC=y
diff --git a/arch/arm/configs/tegra_p1852_gnu_linux_defconfig b/arch/arm/configs/tegra_p1852_gnu_linux_defconfig
index 1afacd7b3cb9..7a1435a4024a 100644
--- a/arch/arm/configs/tegra_p1852_gnu_linux_defconfig
+++ b/arch/arm/configs/tegra_p1852_gnu_linux_defconfig
@@ -31,9 +31,12 @@ CONFIG_ARCH_TEGRA_3x_SOC=y
CONFIG_TEGRA_PCI=y
CONFIG_MACH_P1852=y
CONFIG_TEGRA_PWM=y
+CONFIG_TEGRA_P1852_TDM=y
# CONFIG_TEGRA_CPU_DVFS is not set
CONFIG_TEGRA_CLOCK_DEBUG_WRITE=y
# CONFIG_TEGRA_MC_EARLY_ACK is not set
+CONFIG_NON_ALIASED_COHERENT_MEM=y
+CONFIG_ARM_ERRATA_742230=y
CONFIG_ARM_ERRATA_743622=y
CONFIG_ARM_ERRATA_751472=y
CONFIG_ARM_ERRATA_752520=y
@@ -133,7 +136,6 @@ CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_VIRTUAL_CONSUMER=y
CONFIG_REGULATOR_TPS6591X=y
-CONFIG_REGULATOR_TPS6236X=y
CONFIG_MEDIA_SUPPORT=y
CONFIG_VIDEO_DEV=y
# CONFIG_TEGRA_AVP is not set
@@ -144,8 +146,6 @@ CONFIG_VIDEO_OUTPUT_CONTROL=y
CONFIG_FB=y
CONFIG_TEGRA_GRHOST=y
CONFIG_TEGRA_DC=y
-CONFIG_TEGRA_DC_EXTENSIONS=y
-CONFIG_NVMAP_SEARCH_GLOBAL_HANDLES=y
CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_LCD_CLASS_DEVICE=y
CONFIG_BACKLIGHT_CLASS_DEVICE=y
@@ -170,6 +170,7 @@ CONFIG_MMC_EMBEDDED_SDIO=y
CONFIG_MMC_PARANOID_SD_INIT=y
# CONFIG_MMC_BLOCK_BOUNCE is not set
CONFIG_MMC_BLOCK_DEFERRED_RESUME=y
+CONFIG_MMC_BKOPS=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMC_SDHCI_TEGRA=y
diff --git a/arch/arm/configs/tegra_p852_gnu_linux_defconfig b/arch/arm/configs/tegra_p852_gnu_linux_defconfig
index 7539158200c1..9f7e71711c4f 100644
--- a/arch/arm/configs/tegra_p852_gnu_linux_defconfig
+++ b/arch/arm/configs/tegra_p852_gnu_linux_defconfig
@@ -248,6 +248,7 @@ CONFIG_USB_SERIAL_GENERIC=y
CONFIG_USB_SERIAL_PL2303=y
CONFIG_USB_TEGRA_OTG=y
CONFIG_MMC=y
+CONFIG_MMC_BKOPS=y
CONFIG_MMC_UNSAFE_RESUME=y
# CONFIG_MMC_BLOCK_BOUNCE is not set
CONFIG_MMC_SDHCI=y
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
index 7a21d0bf7134..19e3c8c77f01 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -75,6 +75,27 @@ static inline dma_addr_t virt_to_dma(struct device *dev, void *addr)
* Private support functions: these are not part of the API and are
* liable to change. Drivers must not use these.
*/
+#if defined(CONFIG_NON_ALIASED_COHERENT_MEM)
+static inline void __dma_single_cpu_to_dev(struct device *dev,
+ const void *kaddr, size_t size, enum dma_data_direction dir)
+{
+ extern void ___dma_single_cpu_to_dev(struct device *dev,
+ const void *, size_t, enum dma_data_direction);
+
+ if (!arch_is_coherent())
+ ___dma_single_cpu_to_dev(dev, kaddr, size, dir);
+}
+
+static inline void __dma_single_dev_to_cpu(struct device *dev,
+ const void *kaddr, size_t size, enum dma_data_direction dir)
+{
+ extern void ___dma_single_dev_to_cpu(struct device *dev,
+ const void *, size_t, enum dma_data_direction);
+
+ if (!arch_is_coherent())
+ ___dma_single_dev_to_cpu(dev, kaddr, size, dir);
+}
+#else
static inline void __dma_single_cpu_to_dev(const void *kaddr, size_t size,
enum dma_data_direction dir)
{
@@ -94,6 +115,7 @@ static inline void __dma_single_dev_to_cpu(const void *kaddr, size_t size,
if (!arch_is_coherent())
___dma_single_dev_to_cpu(kaddr, size, dir);
}
+#endif
static inline void __dma_page_cpu_to_dev(struct page *page, unsigned long off,
size_t size, enum dma_data_direction dir)
@@ -199,8 +221,12 @@ int dma_mmap_coherent(struct device *, struct vm_area_struct *,
extern void *dma_alloc_writecombine(struct device *, size_t, dma_addr_t *,
gfp_t);
+#if defined(CONFIG_NON_ALIASED_COHERENT_MEM)
+extern void dma_free_writecombine(struct device *, size_t, void *, dma_addr_t);
+#else
#define dma_free_writecombine(dev,size,cpu_addr,handle) \
dma_free_coherent(dev,size,cpu_addr,handle)
+#endif
int dma_mmap_writecombine(struct device *, struct vm_area_struct *,
void *, dma_addr_t, size_t);
@@ -421,7 +447,12 @@ static inline void dma_sync_single_range_for_cpu(struct device *dev,
if (!dmabounce_sync_for_cpu(dev, handle, offset, size, dir))
return;
+#if defined(CONFIG_NON_ALIASED_COHERENT_MEM)
+ __dma_single_dev_to_cpu(dev, dma_to_virt(dev, handle) + offset,
+ size, dir);
+#else
__dma_single_dev_to_cpu(dma_to_virt(dev, handle) + offset, size, dir);
+#endif
}
static inline void dma_sync_single_range_for_device(struct device *dev,
@@ -435,7 +466,12 @@ static inline void dma_sync_single_range_for_device(struct device *dev,
if (!dmabounce_sync_for_device(dev, handle, offset, size, dir))
return;
+#if defined(CONFIG_NON_ALIASED_COHERENT_MEM)
+ __dma_single_cpu_to_dev(dev, dma_to_virt(dev, handle) + offset,
+ size, dir);
+#else
__dma_single_cpu_to_dev(dma_to_virt(dev, handle) + offset, size, dir);
+#endif
}
static inline void dma_sync_single_for_cpu(struct device *dev,
diff --git a/arch/arm/include/asm/mach/map.h b/arch/arm/include/asm/mach/map.h
index d2fedb5aeb1f..3845215404dd 100644
--- a/arch/arm/include/asm/mach/map.h
+++ b/arch/arm/include/asm/mach/map.h
@@ -29,6 +29,8 @@ struct map_desc {
#define MT_MEMORY_NONCACHED 11
#define MT_MEMORY_DTCM 12
#define MT_MEMORY_ITCM 13
+#define MT_DMA_COHERENT 14
+#define MT_WC_COHERENT 15
#ifdef CONFIG_MMU
extern void iotable_init(struct map_desc *, int);
diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h
index 25669795d80d..cf7c02042f60 100644
--- a/arch/arm/include/asm/memory.h
+++ b/arch/arm/include/asm/memory.h
@@ -88,6 +88,13 @@
#define CONSISTENT_END (0xffe00000UL)
#define CONSISTENT_BASE (CONSISTENT_END - CONSISTENT_DMA_SIZE)
+#ifndef CONSISTENT_WC_SIZE
+#define CONSISTENT_WC_SIZE SZ_2M
+#endif
+
+#define CONSISTENT_WC_END CONSISTENT_BASE
+#define CONSISTENT_WC_BASE (CONSISTENT_WC_END - CONSISTENT_WC_SIZE)
+
#else /* CONFIG_MMU */
/*
diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
index e87f5f243012..714664b2b2ee 100644
--- a/arch/arm/kernel/sleep.S
+++ b/arch/arm/kernel/sleep.S
@@ -72,12 +72,14 @@ ENDPROC(cpu_suspend_abort)
* r3 = L1 section flags
*/
ENTRY(cpu_resume_mmu)
+#ifndef CONFIG_ARCH_HAS_SUSPEND_PAGETABLE
adr r4, cpu_resume_turn_mmu_on
mov r4, r4, lsr #20
orr r3, r3, r4, lsl #20
ldr r5, [r2, r4, lsl #2] @ save old mapping
str r3, [r2, r4, lsl #2] @ setup 1:1 mapping for mmu code
sub r2, r2, r1
+#endif
ldr r3, =cpu_resume_after_mmu
bic r1, r0, #CR_C @ ensure D-cache is disabled
b cpu_resume_turn_mmu_on
@@ -92,7 +94,9 @@ cpu_resume_turn_mmu_on:
mov pc, r3 @ jump to virtual address
ENDPROC(cpu_resume_turn_mmu_on)
cpu_resume_after_mmu:
+#ifndef CONFIG_ARCH_HAS_SUSPEND_PAGETABLE
str r5, [r2, r4, lsl #2] @ restore old mapping
+#endif
mcr p15, 0, r0, c1, c0, 0 @ turn on D-cache
mov r0, #0 @ return zero on success
ldmfd sp!, {r4 - r11, pc}
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index 0684e13f7e9c..722cba16101a 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -21,6 +21,10 @@ config ARCH_TEGRA_2x_SOC
select ARCH_SUPPORTS_MSI if TEGRA_PCI
select PCI_MSI if TEGRA_PCI
select CPA
+ select ARM_ERRATA_716044
+ select ARM_ERRATA_764369 if SMP
+ select ARCH_HAS_SUSPEND_PAGETABLE
+ select NVMAP_CACHE_MAINT_BY_SET_WAYS
help
Support for NVIDIA Tegra AP20 and T20 processors, based on the
ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
@@ -44,8 +48,11 @@ config ARCH_TEGRA_3x_SOC
select ARCH_SUPPORTS_MSI if TEGRA_PCI
select PCI_MSI if TEGRA_PCI
select ARM_ERRATA_754322
+ select ARM_ERRATA_764369 if SMP
select TEGRA_LP2_ARM_TWD if HAVE_ARM_TWD && !TEGRA_RAIL_OFF_MULTIPLE_CPUS
select CPA
+ select ARCH_HAS_SUSPEND_PAGETABLE
+ select NVMAP_CACHE_MAINT_BY_SET_WAYS
help
Support for NVIDIA Tegra 3 family of SoCs, based upon the
ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
@@ -255,6 +262,14 @@ config TEGRA_FIQ_DEBUGGER
help
Enables the FIQ serial debugger on Tegra
+config TEGRA_P1852_TDM
+ bool "Enable TDM mode for P1852 SKUs"
+ default n
+ depends on MACH_P1852
+ help
+ Enables TDM mode driver for P1852 SKUs. If this
+ is not defined then I2S mode is selected by default.
+
config TEGRA_CARDHU_DSI
bool "Support DSI panel on Cardhu"
depends on MACH_CARDHU
@@ -262,6 +277,13 @@ config TEGRA_CARDHU_DSI
help
Support for DSI Panel on Nvidia Cardhu
+config TEGRA_CARDHU_DUAL_DSI_PANEL
+ bool "Support Dual DSI panel on Cardhu"
+ default n
+ depends on TEGRA_CARDHU_DSI
+ help
+ Support for Dual DSI Panel on Nvidia Cardhu
+
config TEGRA_EMC_SCALING_ENABLE
bool "Enable scaling the memory frequency"
depends on TEGRA_SILICON_PLATFORM
@@ -280,7 +302,7 @@ config TEGRA_CORE_DVFS
config TEGRA_IOVMM_GART
bool "Enable I/O virtual memory manager for GART"
- depends on ARCH_TEGRA_2x_SOC
+ depends on ARCH_TEGRA_2x_SOC && !TEGRA_IOMMU_GART
default y
select TEGRA_IOVMM
help
@@ -291,7 +313,7 @@ config TEGRA_IOVMM_GART
config TEGRA_IOVMM_SMMU
bool "Enable I/O virtual memory manager for SMMU"
- depends on ARCH_TEGRA_3x_SOC
+ depends on ARCH_TEGRA_3x_SOC && !TEGRA_IOMMU_SMMU
default y
select TEGRA_IOVMM
help
@@ -308,6 +330,7 @@ config TEGRA_IOVMM_SMMU_SYSFS
Enables SMMU register access through /sys/devices/smmu/* files.
config TEGRA_IOVMM
+ depends on TEGRA_IOVMM_GART || TEGRA_IOVMM_SMMU
bool
config TEGRA_AVP_KERNEL_ON_MMU
@@ -319,7 +342,7 @@ config TEGRA_AVP_KERNEL_ON_MMU
config TEGRA_AVP_KERNEL_ON_SMMU
bool "Use SMMU to relocate AVP kernel"
- depends on TEGRA_IOVMM_SMMU
+ depends on TEGRA_IOVMM_SMMU || TEGRA_IOMMU_SMMU
default y
help
Use SMMU to relocate AVP kernel (nvrm_avp.bin).
@@ -331,6 +354,7 @@ config TEGRA_THERMAL_THROTTLE
bool "Enable throttling of CPU speed on overtemp"
depends on TEGRA_SILICON_PLATFORM
depends on CPU_FREQ
+ depends on THERMAL
default y
help
Also requires enabling a temperature sensor such as NCT1008.
@@ -410,6 +434,17 @@ config USB_HOTPLUG
bool "Enabling the USB hotplug"
default n
+config TEGRA_GADGET_BOOST_CPU_FREQ
+ int "Boost cpu frequency for tegra usb gadget (0-1300 mhz)"
+ range 0 1300
+ default 0
+ help
+ Devices need to boost frequency of CPU when they are connected
+ to host pc through usb cable for better performance. This value
+ is the amount of the frequency (in mhz) to be boosted. If it is
+ zero boosting frequency will not be enabled. This value will be
+ used only by usb gadget driver.
+
config TEGRA_DYNAMIC_PWRDET
bool "Enable dynamic activation of IO level auto-detection"
depends on TEGRA_SILICON_PLATFORM
@@ -451,11 +486,6 @@ config TEGRA_BB_XMM_POWER2
insert this LKM to initiate 2nd USB enumeration power sequence
- after modem software has been downloaded to flashless device.
-config TEGRA_THERMAL_SYSFS
- bool "Enable Thermal driver to use Thermal Sysfs infrastructure"
- depends on THERMAL
- default y
-
config TEGRA_PLLM_RESTRICTED
bool "Restrict PLLM usage as module clock source"
depends on !ARCH_TEGRA_2x_SOC
@@ -498,4 +528,13 @@ config TEGRA_PREPOWER_WIFI
default n
help
Pre-power up the on board WiFi chip
+
+config TEGRA_SKIN_THROTTLE
+ bool "Skin Temperature throttling"
+ depends on TEGRA_THERMAL_THROTTLE
+ depends on THERM_EST
+ default n
+ help
+ Enable throttling to control the temperature of the skin/case
+ of the device.
endif
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index 874527b41830..c2d78afc94b1 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -1,5 +1,7 @@
GCOV_PROFILE := y
+subdir-ccflags-y := -Werror
+
obj-y += ahb.o
obj-y += apbio.o
obj-y += common.o
@@ -8,7 +10,6 @@ obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += common-t2.o
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += common-t3.o
obj-y += io.o
obj-y += irq.o
-obj-$(CONFIG_TEGRA_GRHOST) += syncpt.o
obj-y += clock.o
obj-y += clock-common.o
obj-y += timer.o
@@ -28,7 +29,13 @@ obj-y += pm.o
obj-$(CONFIG_TEGRA_WDT_RECOVERY) += wdt-recovery.o
obj-$(CONFIG_PM_SLEEP) += pm-irq.o
obj-y += gic.o
+
+
obj-y += sleep.o
+
+plus_sec := $(call as-instr,.arch_extension sec,+sec)
+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
@@ -39,6 +46,8 @@ obj-y += i2c_error_recovery.o
obj-y += mc.o
obj-$(CONFIG_TEGRA_STAT_MON) += tegra2_statmon.o
obj-$(CONFIG_USB_SUPPORT) += usb_phy.o
+obj-$(CONFIG_USB_SUPPORT) += tegra3_usb_phy.o
+obj-$(CONFIG_USB_SUPPORT) += tegra2_usb_phy.o
obj-$(CONFIG_FIQ) += fiq.o
obj-$(CONFIG_TEGRA_FIQ_DEBUGGER) += tegra_fiq_debugger.o
obj-$(CONFIG_TEGRA_PWM) += pwm.o
@@ -60,6 +69,7 @@ obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_emc.o
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra3_emc.o
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += wakeups-t2.o
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += wakeups-t3.o
+obj-y += wakeups.o
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += pm-t2.o
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += pm-t3.o
@@ -73,8 +83,12 @@ obj-y += reset.o
obj-$(CONFIG_TEGRA_SYSTEM_DMA) += dma.o
obj-$(CONFIG_CPU_FREQ) += cpu-tegra.o
ifeq ($(CONFIG_TEGRA_AUTO_HOTPLUG),y)
+ifeq ($(CONFIG_CPUQUIET_FRAMEWORK),y)
+obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += cpuquiet.o
+else
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += cpu-tegra3.o
endif
+endif
obj-$(CONFIG_TEGRA_PCI) += pcie.o
obj-$(CONFIG_USB_SUPPORT) += usb_phy.o
ifeq ($(CONFIG_CPU_IDLE),y)
diff --git a/arch/arm/mach-tegra/ahb.c b/arch/arm/mach-tegra/ahb.c
index b7f3fb5219bb..e27ba582fff6 100644
--- a/arch/arm/mach-tegra/ahb.c
+++ b/arch/arm/mach-tegra/ahb.c
@@ -87,9 +87,10 @@ static inline void gizmo_writel(unsigned long value, unsigned long offset)
writel(value, IO_TO_VIRT(TEGRA_AHB_GIZMO_BASE + offset));
}
+#ifdef CONFIG_PM
+
static u32 ahb_gizmo[29];
-#ifdef CONFIG_PM
int tegra_ahbgizmo_suspend(void)
{
ahb_gizmo[0] = gizmo_readl(AHB_ARBITRATION_DISABLE);
diff --git a/arch/arm/mach-tegra/apbio.c b/arch/arm/mach-tegra/apbio.c
index e227331c2f0f..5f3944993804 100644
--- a/arch/arm/mach-tegra/apbio.c
+++ b/arch/arm/mach-tegra/apbio.c
@@ -30,7 +30,7 @@
static DEFINE_MUTEX(tegra_apb_dma_lock);
-#ifdef CONFIG_TEGRA_SYSTEM_DMA
+#if defined(CONFIG_TEGRA_SYSTEM_DMA) && defined(CONFIG_ARCH_TEGRA_2x_SOC)
static struct tegra_dma_channel *tegra_apb_dma;
static u32 *tegra_apb_bb;
static dma_addr_t tegra_apb_bb_phys;
@@ -68,6 +68,8 @@ static inline u32 apb_readl(unsigned long offset)
req.source_wrap = 4;
req.req_sel = 0;
req.size = 4;
+ dma_sync_single_for_device(NULL, tegra_apb_bb_phys,
+ sizeof(u32), DMA_FROM_DEVICE);
INIT_COMPLETION(tegra_apb_wait);
@@ -81,6 +83,8 @@ static inline u32 apb_readl(unsigned long offset)
*(u32 *)tegra_apb_bb = 0;
}
+ dma_sync_single_for_cpu(NULL, tegra_apb_bb_phys,
+ sizeof(u32), DMA_FROM_DEVICE);
mutex_unlock(&tegra_apb_dma_lock);
return *((u32 *)tegra_apb_bb);
}
@@ -97,6 +101,8 @@ static inline void apb_writel(u32 value, unsigned long offset)
}
mutex_lock(&tegra_apb_dma_lock);
+ dma_sync_single_for_cpu(NULL, tegra_apb_bb_phys,
+ sizeof(u32), DMA_TO_DEVICE);
*((u32 *)tegra_apb_bb) = value;
req.complete = apb_dma_complete;
req.to_memory = 0;
@@ -111,6 +117,8 @@ static inline void apb_writel(u32 value, unsigned long offset)
INIT_COMPLETION(tegra_apb_wait);
+ dma_sync_single_for_device(NULL, tegra_apb_bb_phys,
+ sizeof(u32), DMA_TO_DEVICE);
tegra_dma_enqueue_req(tegra_apb_dma, &req);
ret = wait_for_completion_timeout(&tegra_apb_wait,
@@ -121,17 +129,6 @@ static inline void apb_writel(u32 value, unsigned long offset)
mutex_unlock(&tegra_apb_dma_lock);
}
-#else
-static inline u32 apb_readl(unsigned long offset)
-{
- return readl(IO_TO_VIRT(offset));
-}
-
-static inline void apb_writel(u32 value, unsigned long offset)
-{
- writel(value, IO_TO_VIRT(offset));
-}
-#endif
u32 tegra_apb_readl(unsigned long offset)
{
@@ -142,10 +139,11 @@ void tegra_apb_writel(u32 value, unsigned long offset)
{
apb_writel(value, offset);
}
+#endif
static int tegra_init_apb_dma(void)
{
-#ifdef CONFIG_TEGRA_SYSTEM_DMA
+#if defined(CONFIG_TEGRA_SYSTEM_DMA) && defined(CONFIG_ARCH_TEGRA_2x_SOC)
tegra_apb_dma = tegra_dma_allocate_channel(TEGRA_DMA_MODE_ONESHOT |
TEGRA_DMA_SHARED, "apbio");
if (!tegra_apb_dma) {
diff --git a/arch/arm/mach-tegra/apbio.h b/arch/arm/mach-tegra/apbio.h
index f0c87f06a209..121fda359e40 100644
--- a/arch/arm/mach-tegra/apbio.h
+++ b/arch/arm/mach-tegra/apbio.h
@@ -15,5 +15,17 @@
*
*/
+#if defined(CONFIG_TEGRA_SYSTEM_DMA) && defined(CONFIG_ARCH_TEGRA_2x_SOC)
u32 tegra_apb_readl(unsigned long offset);
void tegra_apb_writel(u32 value, unsigned long offset);
+#else
+static inline u32 tegra_apb_readl(unsigned long offset)
+{
+ return readl(IO_TO_VIRT(offset));
+}
+
+static inline void tegra_apb_writel(u32 value, unsigned long offset)
+{
+ writel(value, IO_TO_VIRT(offset));
+}
+#endif
diff --git a/arch/arm/mach-tegra/baseband-xmm-power.c b/arch/arm/mach-tegra/baseband-xmm-power.c
index 7659d4f8bbe5..36f5fc6611f9 100644
--- a/arch/arm/mach-tegra/baseband-xmm-power.c
+++ b/arch/arm/mach-tegra/baseband-xmm-power.c
@@ -31,7 +31,9 @@
#include <linux/usb.h>
#include <linux/pm_runtime.h>
#include <linux/suspend.h>
+#include <linux/pm_qos_params.h>
#include <mach/usb_phy.h>
+#include <linux/regulator/consumer.h>
#include "board.h"
#include "board-enterprise.h"
#include "devices.h"
@@ -89,12 +91,12 @@ static enum {
IPC_AP_WAKE_H,
} ipc_ap_wake_state;
-enum baseband_xmm_powerstate_t baseband_xmm_powerstate;
+static enum baseband_xmm_powerstate_t baseband_xmm_powerstate;
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 baseband_power_platform_data *baseband_power_driver_data;
+static struct work_struct autopm_resume_work;
static bool register_hsic_device;
static struct wake_lock wakelock;
static struct usb_device *usbdev;
@@ -102,7 +104,6 @@ static bool CP_initiated_L2toL0;
static bool modem_power_on;
static int power_onoff;
static int reenable_autosuspend;
-static struct work_struct autopm_resume_work;
static bool wakeup_pending;
static bool modem_sleep_flag;
static spinlock_t xmm_lock;
@@ -110,10 +111,15 @@ static DEFINE_MUTEX(xmm_onoff_mutex);
static bool system_suspending;
static struct regulator *enterprise_hsic_reg;
static bool _hsic_reg_status;
+static struct pm_qos_request_list boost_cpu_freq_req;
+static struct delayed_work pm_qos_work;
+#define BOOST_CPU_FREQ_MIN 1500000
-static void baseband_xmm_power_L2_resume(void);
-static int baseband_xmm_power_driver_handle_resume(
- struct baseband_power_platform_data *data);
+/* driver specific data - same structure is used for flashless
+ * & flashed modem drivers i.e. baseband-xmm-power2.c
+ */
+struct xmm_power_data xmm_power_drv_data;
+EXPORT_SYMBOL(xmm_power_drv_data);
static int tegra_baseband_rail_on(void)
{
@@ -175,32 +181,64 @@ static int tegra_baseband_rail_off(void)
static int baseband_modem_power_on(struct baseband_power_platform_data *data)
{
/* set IPC_HSIC_ACTIVE active */
- gpio_set_value(baseband_power_driver_data->
- modem.xmm.ipc_hsic_active, 1);
+ gpio_set_value(data->modem.xmm.ipc_hsic_active, 1);
+
+ /* wait 20 ms */
+ mdelay(20);
/* reset / power on sequence */
- msleep(40);
+ mdelay(40);
gpio_set_value(data->modem.xmm.bb_rst, 1);
mdelay(1);
+
+ gpio_set_value(data->modem.xmm.bb_on, 1);
+ udelay(70);
+ gpio_set_value(data->modem.xmm.bb_on, 0);
+
+ return 0;
+}
+
+/* this function can sleep, do not call in atomic context */
+static int baseband_modem_power_on_async(
+ struct baseband_power_platform_data *data)
+{
+ /* set IPC_HSIC_ACTIVE active */
+ gpio_set_value(data->modem.xmm.ipc_hsic_active, 1);
+
+ /* wait 20 ms */
+ msleep(20);
+
+ /* reset / power on sequence */
+ msleep(40);
+ gpio_set_value(data->modem.xmm.bb_rst, 1);
+ usleep_range(1000, 2000);
+
gpio_set_value(data->modem.xmm.bb_on, 1);
udelay(70);
gpio_set_value(data->modem.xmm.bb_on, 0);
+ pr_debug("%s: pm qos request CPU 1.5GHz\n", __func__);
+ pm_qos_update_request(&boost_cpu_freq_req, (s32)BOOST_CPU_FREQ_MIN);
+ /* Device enumeration should happen in 1 sec however in any case
+ * we want to request it back to normal so schedule work to restore
+ * CPU freq after 2 seconds */
+ schedule_delayed_work(&pm_qos_work, msecs_to_jiffies(2000));
+
return 0;
}
-static int baseband_xmm_power_on(struct platform_device *device)
+static int xmm_power_on(struct platform_device *device)
{
- struct baseband_power_platform_data *data
- = (struct baseband_power_platform_data *)
+ struct baseband_power_platform_data *pdata =
device->dev.platform_data;
+ struct xmm_power_data *data = &xmm_power_drv_data;
int ret;
pr_debug("%s {\n", __func__);
/* check for platform data */
- if (!data) {
- pr_err("%s: !data\n", __func__);
+ if (!pdata) {
+ pr_err("%s: !pdata\n", __func__);
return -EINVAL;
}
if (baseband_xmm_powerstate != BBXMM_PS_UNINIT)
@@ -211,11 +249,7 @@ static int baseband_xmm_power_on(struct platform_device *device)
/* reset the state machine */
baseband_xmm_powerstate = BBXMM_PS_INIT;
modem_sleep_flag = false;
-
- if (modem_ver < XMM_MODEM_VER_1130)
- ipc_ap_wake_state = IPC_AP_WAKE_INIT1;
- else
- ipc_ap_wake_state = IPC_AP_WAKE_INIT2;
+ ipc_ap_wake_state = IPC_AP_WAKE_INIT2;
pr_debug("%s wake_st(%d) modem version %lu\n", __func__,
ipc_ap_wake_state, modem_ver);
@@ -228,24 +262,23 @@ static int baseband_xmm_power_on(struct platform_device *device)
pr_debug("%s: register usb host controller\n",
__func__);
modem_power_on = true;
- if (data->hsic_register)
- data->modem.xmm.hsic_device =
- data->hsic_register();
+ if (pdata->hsic_register)
+ data->hsic_device = pdata->hsic_register();
else
pr_err("%s: hsic_register is missing\n",
__func__);
register_hsic_device = false;
} else {
/* register usb host controller */
- if (data->hsic_register)
- data->modem.xmm.hsic_device =
- data->hsic_register();
+ if (pdata->hsic_register)
+ data->hsic_device = pdata->hsic_register();
/* turn on modem */
- pr_debug("%s call baseband_modem_power_on\n", __func__);
- baseband_modem_power_on(data);
+ pr_debug("%s call baseband_modem_power_on_async\n",
+ __func__);
+ baseband_modem_power_on_async(pdata);
}
}
- ret = enable_irq_wake(gpio_to_irq(data->modem.xmm.ipc_ap_wake));
+ 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__);
pr_debug("%s }\n", __func__);
@@ -253,9 +286,12 @@ static int baseband_xmm_power_on(struct platform_device *device)
return 0;
}
-static int baseband_xmm_power_off(struct platform_device *device)
+static int xmm_power_off(struct platform_device *device)
{
- struct baseband_power_platform_data *data;
+ struct baseband_power_platform_data *pdata =
+ device->dev.platform_data;
+ struct xmm_power_data *data = &xmm_power_drv_data;
+
int ret;
unsigned long flags;
@@ -268,35 +304,33 @@ static int baseband_xmm_power_off(struct platform_device *device)
pr_err("%s: !device\n", __func__);
return -EINVAL;
}
- data = (struct baseband_power_platform_data *)
- device->dev.platform_data;
- if (!data) {
- pr_err("%s: !data\n", __func__);
+ if (!pdata) {
+ pr_err("%s: !pdata\n", __func__);
return -EINVAL;
}
ipc_ap_wake_state = IPC_AP_WAKE_UNINIT;
- ret = disable_irq_wake(gpio_to_irq(data->modem.xmm.ipc_ap_wake));
+ 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 (data->hsic_unregister)
- data->hsic_unregister(data->modem.xmm.hsic_device);
+ if (pdata->hsic_unregister)
+ pdata->hsic_unregister(data->hsic_device);
else
pr_err("%s: hsic_unregister is missing\n", __func__);
/* set IPC_HSIC_ACTIVE low */
- gpio_set_value(baseband_power_driver_data->
- modem.xmm.ipc_hsic_active, 0);
+ gpio_set_value(pdata->modem.xmm.ipc_hsic_active, 0);
/* wait 20 ms */
- mdelay(20);
+ msleep(20);
/* drive bb_rst low */
- gpio_set_value(data->modem.xmm.bb_rst, 0);
- mdelay(1);
+ gpio_set_value(pdata->modem.xmm.bb_rst, 0);
+ /* sleep 1ms */
+ usleep_range(1000, 2000);
baseband_xmm_powerstate = BBXMM_PS_UNINIT;
modem_sleep_flag = false;
@@ -314,9 +348,8 @@ static int baseband_xmm_power_off(struct platform_device *device)
return 0;
}
-static ssize_t baseband_xmm_onoff(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t xmm_onoff(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
int pwr;
int size;
@@ -352,22 +385,88 @@ static ssize_t baseband_xmm_onoff(struct device *dev,
pr_debug("%s power_onoff=%d\n", __func__, power_onoff);
if (power_onoff == 0)
- baseband_xmm_power_off(device);
+ xmm_power_off(device);
else if (power_onoff == 1)
- baseband_xmm_power_on(device);
+ xmm_power_on(device);
mutex_unlock(&xmm_onoff_mutex);
return count;
}
+static void pm_qos_worker(struct work_struct *work)
+{
+ pr_debug("%s - pm qos CPU back to normal\n", __func__);
+ pm_qos_update_request(&boost_cpu_freq_req,
+ (s32)PM_QOS_CPU_FREQ_MIN_DEFAULT_VALUE);
+}
+
static DEVICE_ATTR(xmm_onoff, S_IRUSR | S_IWUSR | S_IRGRP,
- NULL, baseband_xmm_onoff);
+ NULL, xmm_onoff);
+
+/* Do the work for AP/CP initiated L2->L0 */
+static void xmm_power_l2_resume(void)
+{
+ struct baseband_power_platform_data *pdata = xmm_power_drv_data.pdata;
+ struct xmm_power_data *drv = &xmm_power_drv_data;
+ int value;
+ int delay = 1000; /* maxmum delay in msec */
+ unsigned long flags;
+ int ret, rcount = 0;
+
+ pr_debug("%s\n", __func__);
+
+ if (!pdata)
+ 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);
+ 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);
+retry:
+ /* wait for cp */
+ pr_debug("waiting for host wakeup from CP...\n");
+ ret = wait_event_interruptible_timeout(drv->bb_wait,
+ drv->hostwake == 1, msecs_to_jiffies(delay));
+ if (ret == 0) {
+ pr_info("!!AP L2->L0 Failed\n");
+ 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");
+ }
+}
void baseband_xmm_set_power_status(unsigned int status)
{
- struct baseband_power_platform_data *data = baseband_power_driver_data;
+ struct baseband_power_platform_data *data = xmm_power_drv_data.pdata;
int value = 0;
unsigned long flags;
@@ -377,25 +476,24 @@ void baseband_xmm_set_power_status(unsigned int status)
switch (status) {
case BBXMM_PS_L0:
if (modem_sleep_flag) {
- pr_info("%s Resume from L3 without calling resume"
- "function\n", __func__);
- baseband_xmm_power_driver_handle_resume(data);
+ /* 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(&wakelock);
+ wake_lock_timeout(&wakelock, HZ*2);
value = gpio_get_value(data->modem.xmm.ipc_hsic_active);
pr_debug("before L0 ipc_hsic_active=%d\n", value);
if (!value) {
- pr_debug("before L0 gpio set ipc_hsic_active=1 ->\n");
+ pr_debug("L0 gpio set ipc_hsic_active=1 ->\n");
gpio_set_value(data->modem.xmm.ipc_hsic_active, 1);
}
if (modem_power_on) {
modem_power_on = false;
baseband_modem_power_on(data);
}
- pr_debug("gpio host active high->\n");
break;
case BBXMM_PS_L2:
pr_info("L2\n");
@@ -403,7 +501,8 @@ void baseband_xmm_set_power_status(unsigned int status)
spin_lock_irqsave(&xmm_lock, flags);
if (wakeup_pending) {
spin_unlock_irqrestore(&xmm_lock, flags);
- baseband_xmm_power_L2_resume();
+ pr_debug("%s: wakeup pending\n", __func__);
+ xmm_power_l2_resume();
} else {
spin_unlock_irqrestore(&xmm_lock, flags);
if (wake_lock_active(&wakelock))
@@ -411,34 +510,8 @@ void baseband_xmm_set_power_status(unsigned int status)
modem_sleep_flag = true;
}
break;
- case BBXMM_PS_L3:
- if (baseband_xmm_powerstate == BBXMM_PS_L2TOL0) {
- if (!data->modem.xmm.ipc_ap_wake) {
- spin_lock_irqsave(&xmm_lock, flags);
- wakeup_pending = true;
- spin_unlock_irqrestore(&xmm_lock, flags);
- pr_info("%s: L2 race condition-CP wakeup"
- " pending\n", __func__);
- }
- }
- pr_info("L3\n");
- /* system is going to suspend */
- if (baseband_xmm_powerstate == BBXMM_PS_L2)
- tegra_baseband_rail_off();
-
- baseband_xmm_powerstate = status;
- spin_lock_irqsave(&xmm_lock, flags);
- system_suspending = false;
- spin_unlock_irqrestore(&xmm_lock, flags);
- if (wake_lock_active(&wakelock)) {
- pr_info("%s: releasing wakelock before L3\n",
- __func__);
- wake_unlock(&wakelock);
- }
- gpio_set_value(data->modem.xmm.ipc_hsic_active, 0);
- pr_debug("gpio host active low->\n");
- break;
case BBXMM_PS_L2TOL0:
+ pr_debug("L2TOL0\n");
spin_lock_irqsave(&xmm_lock, flags);
system_suspending = false;
wakeup_pending = false;
@@ -447,16 +520,11 @@ void baseband_xmm_set_power_status(unsigned int status)
if (baseband_xmm_powerstate == BBXMM_PS_L2) {
baseband_xmm_powerstate = status;
pr_debug("BB XMM POWER STATE = %d\n", status);
- baseband_xmm_power_L2_resume();
+ xmm_power_l2_resume();
}
baseband_xmm_powerstate = status;
break;
- case BBXMM_PS_L3TOL0:
- /* poweron rail for L3 -> L0 (system resume) */
- pr_debug("L3 -> L0, turning on power rail.\n");
- tegra_baseband_rail_on();
- baseband_xmm_powerstate = status;
- break;
+
default:
baseband_xmm_powerstate = status;
break;
@@ -465,161 +533,153 @@ void baseband_xmm_set_power_status(unsigned int status)
}
EXPORT_SYMBOL_GPL(baseband_xmm_set_power_status);
-irqreturn_t baseband_xmm_power_ipc_ap_wake_irq(int irq, void *dev_id)
+irqreturn_t xmm_power_ipc_ap_wake_irq(int irq, void *dev_id)
{
+ struct baseband_power_platform_data *data = xmm_power_drv_data.pdata;
+ struct xmm_power_data *drv = &xmm_power_drv_data;
int value;
- struct baseband_power_platform_data *data = baseband_power_driver_data;
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);
- if (ipc_ap_wake_state < IPC_AP_WAKE_IRQ_READY) {
+ /* 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__);
+ " - got falling edge\n", __func__);
/* go to IPC_AP_WAKE_INIT1 state */
ipc_ap_wake_state = IPC_AP_WAKE_INIT1;
- /* queue work */
queue_work(workqueue, &init1_work);
- } else {
+ } else
pr_debug("%s - IPC_AP_WAKE_INIT1"
- " - wait for falling edge\n",
- __func__);
- }
+ " - 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__);
+ " - wait for rising edge\n", __func__);
} else {
pr_debug("%s - IPC_AP_WAKE_INIT2"
- " - got rising edge\n",
- __func__);
+ " - got rising edge\n", __func__);
/* go to IPC_AP_WAKE_INIT2 state */
ipc_ap_wake_state = IPC_AP_WAKE_INIT2;
- /* queue work */
queue_work(workqueue, &init2_work);
}
- } else {
- if (!value) {
- pr_debug("%s - falling\n", __func__);
- /* 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;
- 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_L3) {
- spin_unlock(&xmm_lock);
- pr_info(" CP L3 -> L0\n");
- } else if (baseband_xmm_powerstate ==
- BBXMM_PS_L2) {
- 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);
- }
- }
- /* save gpio state */
+ 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);
+ }
+ /* 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;
+ 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 {
- pr_debug("%s - rising\n", __func__);
- 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;
- 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);
+ if (baseband_xmm_powerstate == BBXMM_PS_L2) {
+ 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);
}
- modem_sleep_flag = false;
- baseband_xmm_set_power_status(
- BBXMM_PS_L0);
- /* save gpio state */
+ }
+ /* save gpio state */
+ ipc_ap_wake_state = IPC_AP_WAKE_L;
+ } else {
+ pr_debug("%s - rising\n", __func__);
+ 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;
+ 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;
}
return IRQ_HANDLED;
}
-EXPORT_SYMBOL(baseband_xmm_power_ipc_ap_wake_irq);
+EXPORT_SYMBOL(xmm_power_ipc_ap_wake_irq);
-static void baseband_xmm_power_init1_work(struct work_struct *work)
+static void xmm_power_init1_work(struct work_struct *work)
{
+ struct baseband_power_platform_data *pdata = xmm_power_drv_data.pdata;
int value;
pr_debug("%s {\n", __func__);
/* check if IPC_HSIC_ACTIVE high */
- value = gpio_get_value(baseband_power_driver_data->
- modem.xmm.ipc_hsic_active);
+ 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 */
- mdelay(100);
+ msleep(100);
/* set IPC_HSIC_ACTIVE low */
- gpio_set_value(baseband_power_driver_data->
- modem.xmm.ipc_hsic_active, 0);
+ gpio_set_value(pdata->modem.xmm.ipc_hsic_active, 0);
/* wait 10 ms */
- mdelay(10);
+ usleep_range(10000, 11000);
/* set IPC_HSIC_ACTIVE high */
- gpio_set_value(baseband_power_driver_data->
- modem.xmm.ipc_hsic_active, 1);
+ gpio_set_value(pdata->modem.xmm.ipc_hsic_active, 1);
/* wait 20 ms */
- mdelay(20);
+ msleep(20);
pr_debug("%s }\n", __func__);
}
-static void baseband_xmm_power_init2_work(struct work_struct *work)
+static void xmm_power_init2_work(struct work_struct *work)
{
- struct baseband_power_platform_data *data = baseband_power_driver_data;
+ struct baseband_power_platform_data *pdata = xmm_power_drv_data.pdata;
pr_debug("%s\n", __func__);
/* check input */
- if (!data)
+ if (!pdata)
return;
/* register usb host controller only once */
if (register_hsic_device) {
- if (data->hsic_register)
- data->modem.xmm.hsic_device = data->hsic_register();
+ if (pdata->hsic_register)
+ xmm_power_drv_data.hsic_device = pdata->hsic_register();
else
pr_err("%s: hsic_register is missing\n", __func__);
register_hsic_device = false;
@@ -627,7 +687,7 @@ static void baseband_xmm_power_init2_work(struct work_struct *work)
}
-static void baseband_xmm_power_autopm_resume(struct work_struct *work)
+static void xmm_power_autopm_resume(struct work_struct *work)
{
struct usb_interface *intf;
@@ -646,57 +706,8 @@ static void baseband_xmm_power_autopm_resume(struct work_struct *work)
}
-/* Do the work for AP/CP initiated L2->L0 */
-static void baseband_xmm_power_L2_resume(void)
-{
- struct baseband_power_platform_data *data = baseband_power_driver_data;
- int value;
- int delay = 10000; /* maxmum delay in msec */
- unsigned long flags;
-
- pr_debug("%s\n", __func__);
-
- if (!baseband_power_driver_data)
- return;
-
- /* claim the wakelock here to avoid any system suspend */
- if (!wake_lock_active(&wakelock))
- wake_lock(&wakelock);
- modem_sleep_flag = false;
- spin_lock_irqsave(&xmm_lock, flags);
- 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 L2->L0\n");
- value = gpio_get_value(data->modem.xmm.ipc_ap_wake);
- if (value) {
- pr_debug("waiting for host wakeup from CP...\n");
- /* wake bb */
- gpio_set_value(data->modem.xmm.ipc_bb_wake, 1);
- do {
- mdelay(1);
- value = gpio_get_value(
- data->modem.xmm.ipc_ap_wake);
- delay--;
- } while ((value) && (delay));
- if (delay)
- pr_debug("gpio host wakeup low <-\n");
- else
- pr_info("!!AP L2->L0 Failed\n");
- } else {
- pr_info("CP already ready\n");
- }
- }
-}
-
/* Do the work for CP initiated L2->L0 */
-static void baseband_xmm_power_L2_resume_work(struct work_struct *work)
+static void xmm_power_l2_resume_work(struct work_struct *work)
{
struct usb_interface *intf;
@@ -713,120 +724,78 @@ static void baseband_xmm_power_L2_resume_work(struct work_struct *work)
pr_debug("} %s\n", __func__);
}
-static void baseband_xmm_power_reset_on(void)
+static void xmm_power_reset_on(struct baseband_power_platform_data *pdata)
{
/* reset / power on sequence */
- gpio_set_value(baseband_power_driver_data->modem.xmm.bb_rst, 0);
+ gpio_set_value(pdata->modem.xmm.bb_rst, 0);
msleep(40);
- gpio_set_value(baseband_power_driver_data->modem.xmm.bb_rst, 1);
- mdelay(1);
- gpio_set_value(baseband_power_driver_data->modem.xmm.bb_on, 1);
+ 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(baseband_power_driver_data->modem.xmm.bb_on, 0);
+ gpio_set_value(pdata->modem.xmm.bb_on, 0);
}
-static struct baseband_xmm_power_work_t *baseband_xmm_power_work;
-static void baseband_xmm_power_work_func(struct work_struct *work)
+static void xmm_power_work_func(struct work_struct *work)
{
- struct baseband_xmm_power_work_t *bbxmm_work
- = (struct baseband_xmm_power_work_t *) work;
+ struct xmm_power_data *data =
+ container_of(work, struct xmm_power_data, work);
+ struct baseband_power_platform_data *pdata = data->pdata;
pr_debug("%s\n", __func__);
- switch (bbxmm_work->state) {
+ switch (data->state) {
case BBXMM_WORK_UNINIT:
pr_debug("BBXMM_WORK_UNINIT\n");
break;
case BBXMM_WORK_INIT:
pr_debug("BBXMM_WORK_INIT\n");
/* go to next state */
- bbxmm_work->state = (modem_flash && !modem_pm)
+ data->state = (modem_flash && !modem_pm)
? BBXMM_WORK_INIT_FLASH_STEP1
: (modem_flash && modem_pm)
? BBXMM_WORK_INIT_FLASH_PM_STEP1
: (!modem_flash && modem_pm)
? BBXMM_WORK_INIT_FLASHLESS_PM_STEP1
: BBXMM_WORK_UNINIT;
- pr_debug("Go to next state %d\n", bbxmm_work->state);
+ pr_debug("Go to next state %d\n", data->state);
queue_work(workqueue, work);
break;
case BBXMM_WORK_INIT_FLASH_STEP1:
pr_debug("BBXMM_WORK_INIT_FLASH_STEP1\n");
/* register usb host controller */
pr_debug("%s: register usb host controller\n", __func__);
- if (baseband_power_driver_data->hsic_register)
- baseband_power_driver_data->modem.xmm.hsic_device =
- baseband_power_driver_data->hsic_register();
+ if (pdata->hsic_register)
+ data->hsic_device = pdata->hsic_register();
else
pr_err("%s: hsic_register is missing\n", __func__);
break;
case BBXMM_WORK_INIT_FLASH_PM_STEP1:
pr_debug("BBXMM_WORK_INIT_FLASH_PM_STEP1\n");
- /* [modem ver >= 1130] start with IPC_HSIC_ACTIVE low */
- if (modem_ver >= XMM_MODEM_VER_1130) {
- pr_debug("%s: ver > 1130:"
- " ipc_hsic_active -> 0\n", __func__);
- gpio_set_value(baseband_power_driver_data->
- modem.xmm.ipc_hsic_active, 0);
- }
+ pr_debug("%s: ipc_hsic_active -> 0\n", __func__);
+ gpio_set_value(pdata->modem.xmm.ipc_hsic_active, 1);
/* reset / power on sequence */
- baseband_xmm_power_reset_on();
+ xmm_power_reset_on(pdata);
/* set power status as on */
power_onoff = 1;
- /* optional delay
- * 0 = flashless
- * ==> causes next step to enumerate modem boot rom
- * (058b / 0041)
- * some delay > boot rom timeout
- * ==> causes next step to enumerate modem software
- * (1519 / 0020)
- * (requires modem to be flash version, not flashless
- * version)
+ gpio_set_value(pdata->modem.xmm.ipc_hsic_active, 0);
+
+ /* expecting init2 performs register hsic to enumerate modem
+ * software directly.
*/
- if (enum_delay_ms)
- mdelay(enum_delay_ms);
- /* register usb host controller */
- pr_debug("%s: register usb host controller\n", __func__);
- if (baseband_power_driver_data->hsic_register)
- baseband_power_driver_data->modem.xmm.hsic_device =
- baseband_power_driver_data->hsic_register();
- else
- pr_err("%s: hsic_register is missing\n", __func__);
- /* go to next state */
- bbxmm_work->state = (modem_ver < XMM_MODEM_VER_1130)
- ? BBXMM_WORK_INIT_FLASH_PM_VER_LT_1130_STEP1
- : BBXMM_WORK_INIT_FLASH_PM_VER_GE_1130_STEP1;
- queue_work(workqueue, work);
- pr_debug("Go to next state %d\n", bbxmm_work->state);
- break;
- case BBXMM_WORK_INIT_FLASH_PM_VER_LT_1130_STEP1:
- pr_debug("BBXMM_WORK_INIT_FLASH_PM_VER_LT_1130_STEP1\n");
- break;
- case BBXMM_WORK_INIT_FLASH_PM_VER_GE_1130_STEP1:
- pr_debug("BBXMM_WORK_INIT_FLASH_PM_VER_GE_1130_STEP1\n");
break;
+
case BBXMM_WORK_INIT_FLASHLESS_PM_STEP1:
pr_debug("BBXMM_WORK_INIT_FLASHLESS_PM_STEP1\n");
- /* go to next state */
- bbxmm_work->state = (modem_ver < XMM_MODEM_VER_1130)
- ? BBXMM_WORK_INIT_FLASHLESS_PM_VER_LT_1130_WAIT_IRQ
- : BBXMM_WORK_INIT_FLASHLESS_PM_VER_GE_1130_STEP1;
- queue_work(workqueue, work);
- break;
- case BBXMM_WORK_INIT_FLASHLESS_PM_VER_LT_1130_STEP1:
- pr_debug("BBXMM_WORK_INIT_FLASHLESS_PM_VER_LT_1130_STEP1\n");
- break;
- case BBXMM_WORK_INIT_FLASHLESS_PM_VER_GE_1130_STEP1:
- pr_debug("BBXMM_WORK_INIT_FLASHLESS_PM_VER_GE_1130_STEP1\n");
+ pr_info("%s: flashless is not supported here\n", __func__);
break;
default:
break;
}
-
}
-static void baseband_xmm_device_add_handler(struct usb_device *udev)
+static void xmm_device_add_handler(struct usb_device *udev)
{
struct usb_interface *intf = usb_ifnum_to_if(udev, 0);
const struct usb_device_id *id;
@@ -846,7 +815,7 @@ static void baseband_xmm_device_add_handler(struct usb_device *udev)
}
}
-static void baseband_xmm_device_remove_handler(struct usb_device *udev)
+static void xmm_device_remove_handler(struct usb_device *udev)
{
if (usbdev == udev) {
pr_info("Remove device %d <%s %s>\n", udev->devnum,
@@ -861,10 +830,10 @@ static int usb_xmm_notify(struct notifier_block *self, unsigned long action,
{
switch (action) {
case USB_DEVICE_ADD:
- baseband_xmm_device_add_handler(blob);
+ xmm_device_add_handler(blob);
break;
case USB_DEVICE_REMOVE:
- baseband_xmm_device_remove_handler(blob);
+ xmm_device_remove_handler(blob);
break;
}
@@ -876,13 +845,13 @@ static struct notifier_block usb_xmm_nb = {
.notifier_call = usb_xmm_notify,
};
-static int baseband_xmm_power_pm_notifier_event(struct notifier_block *this,
+static int xmm_power_pm_notifier_event(struct notifier_block *this,
unsigned long event, void *ptr)
{
- struct baseband_power_platform_data *data = baseband_power_driver_data;
+ struct baseband_power_platform_data *pdata = xmm_power_drv_data.pdata;
unsigned long flags;
- if (!data)
+ if (!pdata)
return NOTIFY_DONE;
pr_debug("%s: event %ld\n", __func__, event);
@@ -914,11 +883,9 @@ static int baseband_xmm_power_pm_notifier_event(struct notifier_block *this,
(baseband_xmm_powerstate == BBXMM_PS_L2)) {
wakeup_pending = false;
spin_unlock_irqrestore(&xmm_lock, flags);
- pr_info("%s : Service Pending CP wakeup\n",
- __func__);
+ pr_info("%s : Service Pending CP wakeup\n", __func__);
CP_initiated_L2toL0 = true;
- baseband_xmm_set_power_status
- (BBXMM_PS_L2TOL0);
+ baseband_xmm_set_power_status(BBXMM_PS_L2TOL0);
return NOTIFY_OK;
}
wakeup_pending = false;
@@ -928,16 +895,14 @@ static int baseband_xmm_power_pm_notifier_event(struct notifier_block *this,
return NOTIFY_DONE;
}
-static struct notifier_block baseband_xmm_power_pm_notifier = {
- .notifier_call = baseband_xmm_power_pm_notifier_event,
+static struct notifier_block xmm_power_pm_notifier = {
+ .notifier_call = xmm_power_pm_notifier_event,
};
-static int baseband_xmm_power_driver_probe(struct platform_device *device)
+static int xmm_power_driver_probe(struct platform_device *device)
{
- struct baseband_power_platform_data *data
- = (struct baseband_power_platform_data *)
- device->dev.platform_data;
+ struct baseband_power_platform_data *pdata = device->dev.platform_data;
struct device *dev = &device->dev;
unsigned long flags;
int err;
@@ -946,17 +911,21 @@ static int baseband_xmm_power_driver_probe(struct platform_device *device)
pr_debug("[XMM] enum_delay_ms=%ld\n", enum_delay_ms);
/* check for platform data */
- if (!data)
+ if (!pdata)
return -ENODEV;
/* check if supported modem */
- if (data->baseband_type != BASEBAND_XMM) {
+ if (pdata->baseband_type != BASEBAND_XMM) {
pr_err("unsuppported modem\n");
return -ENODEV;
}
/* save platform data */
- baseband_power_driver_data = data;
+ xmm_power_drv_data.pdata = pdata;
+
+ /* init wait queue */
+ xmm_power_drv_data.hostwake = 1;
+ init_waitqueue_head(&xmm_power_drv_data.bb_wait);
/* create device file */
err = device_create_file(dev, &dev_attr_xmm_onoff);
@@ -971,20 +940,14 @@ static int baseband_xmm_power_driver_probe(struct platform_device *device)
/* init spin lock */
spin_lock_init(&xmm_lock);
/* request baseband gpio(s) */
- tegra_baseband_gpios[0].gpio = baseband_power_driver_data
- ->modem.xmm.bb_rst;
- tegra_baseband_gpios[1].gpio = baseband_power_driver_data
- ->modem.xmm.bb_on;
- tegra_baseband_gpios[2].gpio = baseband_power_driver_data
- ->modem.xmm.ipc_bb_wake;
- tegra_baseband_gpios[3].gpio = baseband_power_driver_data
- ->modem.xmm.ipc_ap_wake;
- tegra_baseband_gpios[4].gpio = baseband_power_driver_data
- ->modem.xmm.ipc_hsic_active;
- tegra_baseband_gpios[5].gpio = baseband_power_driver_data
- ->modem.xmm.ipc_hsic_sus_req;
+ tegra_baseband_gpios[0].gpio = pdata->modem.xmm.bb_rst;
+ tegra_baseband_gpios[1].gpio = pdata->modem.xmm.bb_on;
+ tegra_baseband_gpios[2].gpio = pdata->modem.xmm.ipc_bb_wake;
+ tegra_baseband_gpios[3].gpio = pdata->modem.xmm.ipc_ap_wake;
+ tegra_baseband_gpios[4].gpio = pdata->modem.xmm.ipc_hsic_active;
+ tegra_baseband_gpios[5].gpio = pdata->modem.xmm.ipc_hsic_sus_req;
err = gpio_request_array(tegra_baseband_gpios,
- ARRAY_SIZE(tegra_baseband_gpios));
+ ARRAY_SIZE(tegra_baseband_gpios));
if (err < 0) {
pr_err("%s - request gpio(s) failed\n", __func__);
return -ENODEV;
@@ -995,52 +958,41 @@ static int baseband_xmm_power_driver_probe(struct platform_device *device)
pr_debug("%s: request_irq IPC_AP_WAKE_IRQ\n", __func__);
ipc_ap_wake_state = IPC_AP_WAKE_UNINIT;
err = request_threaded_irq(
- gpio_to_irq(data->modem.xmm.ipc_ap_wake),
- NULL,
- baseband_xmm_power_ipc_ap_wake_irq,
- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
- "IPC_AP_WAKE_IRQ",
- NULL);
+ gpio_to_irq(pdata->modem.xmm.ipc_ap_wake),
+ NULL, xmm_power_ipc_ap_wake_irq,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ "IPC_AP_WAKE_IRQ", NULL);
if (err < 0) {
pr_err("%s - request irq IPC_AP_WAKE_IRQ failed\n",
__func__);
return err;
}
- err = enable_irq_wake(gpio_to_irq(data->modem.xmm.ipc_ap_wake));
+ err = enable_irq_wake(gpio_to_irq(
+ pdata->modem.xmm.ipc_ap_wake));
if (err < 0)
pr_err("%s: enable_irq_wake error\n", __func__);
- ipc_ap_wake_state = IPC_AP_WAKE_IRQ_READY;
- if (modem_ver >= XMM_MODEM_VER_1130) {
- pr_debug("%s: ver > 1130: AP_WAKE_INIT1\n", __func__);
- /* ver 1130 or later starts in INIT1 state */
- ipc_ap_wake_state = IPC_AP_WAKE_INIT1;
- }
+
+ pr_debug("%s: AP_WAKE_INIT1\n", __func__);
+ /* ver 1130 or later starts in INIT1 state */
+ ipc_ap_wake_state = IPC_AP_WAKE_INIT1;
}
/* init work queue */
- workqueue = create_singlethread_workqueue
- ("baseband_xmm_power_workqueue");
+ workqueue = create_singlethread_workqueue("xmm_power_wq");
if (!workqueue) {
pr_err("cannot create workqueue\n");
- return -1;
+ return -ENOMEM;
}
- baseband_xmm_power_work = (struct baseband_xmm_power_work_t *)
- kmalloc(sizeof(struct baseband_xmm_power_work_t), GFP_KERNEL);
- if (!baseband_xmm_power_work) {
- pr_err("cannot allocate baseband_xmm_power_work\n");
- return -1;
- }
- INIT_WORK((struct work_struct *) baseband_xmm_power_work,
- baseband_xmm_power_work_func);
- baseband_xmm_power_work->state = BBXMM_WORK_INIT;
- queue_work(workqueue,
- (struct work_struct *) baseband_xmm_power_work);
+
+ INIT_WORK(&xmm_power_drv_data.work, xmm_power_work_func);
+ xmm_power_drv_data.state = BBXMM_WORK_INIT;
+ queue_work(workqueue, &xmm_power_drv_data.work);
/* init work objects */
- INIT_WORK(&init1_work, baseband_xmm_power_init1_work);
- INIT_WORK(&init2_work, baseband_xmm_power_init2_work);
- INIT_WORK(&L2_resume_work, baseband_xmm_power_L2_resume_work);
- INIT_WORK(&autopm_resume_work, baseband_xmm_power_autopm_resume);
+ 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(&autopm_resume_work, xmm_power_autopm_resume);
/* init state variables */
register_hsic_device = true;
@@ -1052,36 +1004,30 @@ static int baseband_xmm_power_driver_probe(struct platform_device *device)
spin_unlock_irqrestore(&xmm_lock, flags);
usb_register_notify(&usb_xmm_nb);
- register_pm_notifier(&baseband_xmm_power_pm_notifier);
+ register_pm_notifier(&xmm_power_pm_notifier);
pr_debug("%s }\n", __func__);
return 0;
}
-static int baseband_xmm_power_driver_remove(struct platform_device *device)
+static int xmm_power_driver_remove(struct platform_device *device)
{
- struct baseband_power_platform_data *data
- = (struct baseband_power_platform_data *)
- device->dev.platform_data;
+ struct baseband_power_platform_data *pdata = device->dev.platform_data;
+ struct xmm_power_data *data = &xmm_power_drv_data;
struct device *dev = &device->dev;
pr_debug("%s\n", __func__);
/* check for platform data */
- if (!data)
+ if (!pdata)
return 0;
- unregister_pm_notifier(&baseband_xmm_power_pm_notifier);
+ unregister_pm_notifier(&xmm_power_pm_notifier);
usb_unregister_notify(&usb_xmm_nb);
- /* free work structure */
- kfree(baseband_xmm_power_work);
- baseband_xmm_power_work = (struct baseband_xmm_power_work_t *) 0;
-
/* free baseband irq(s) */
if (modem_flash && modem_pm) {
- free_irq(gpio_to_irq(baseband_power_driver_data
- ->modem.xmm.ipc_ap_wake), NULL);
+ free_irq(gpio_to_irq(pdata->modem.xmm.ipc_ap_wake), NULL);
}
/* free baseband gpio(s) */
@@ -1095,86 +1041,48 @@ static int baseband_xmm_power_driver_remove(struct platform_device *device)
device_remove_file(dev, &dev_attr_xmm_onoff);
/* unregister usb host controller */
- if (data->hsic_unregister)
- data->hsic_unregister(data->modem.xmm.hsic_device);
+ if (pdata->hsic_unregister)
+ pdata->hsic_unregister(data->hsic_device);
else
pr_err("%s: hsic_unregister is missing\n", __func__);
return 0;
}
-static int baseband_xmm_power_driver_handle_resume(
- struct baseband_power_platform_data *data)
+#ifdef CONFIG_PM
+static int xmm_power_driver_suspend(struct device *dev)
{
- int value;
- int delay = 1000; /* maxmum delay in msec */
- unsigned long flags;
-
pr_debug("%s\n", __func__);
- if (!data)
- return 0;
/* check if modem is on */
if (power_onoff == 0) {
pr_debug("%s - flight mode - nop\n", __func__);
return 0;
}
-
- modem_sleep_flag = false;
- spin_lock_irqsave(&xmm_lock, flags);
- wakeup_pending = false;
- spin_unlock_irqrestore(&xmm_lock, flags);
-
- /* L3->L0 */
- baseband_xmm_set_power_status(BBXMM_PS_L3TOL0);
- value = gpio_get_value(data->modem.xmm.ipc_ap_wake);
- if (value) {
- pr_info("AP L3 -> L0\n");
- pr_debug("waiting for host wakeup...\n");
- /* wake bb */
- gpio_set_value(data->modem.xmm.ipc_bb_wake, 1);
- do {
- mdelay(1);
- value = gpio_get_value(
- data->modem.xmm.ipc_ap_wake);
- delay--;
- } while ((value) && (delay));
- if (delay)
- pr_debug("gpio host wakeup low <-\n");
- else
- pr_info("!!AP L3->L0 Failed\n");
-
- } else {
- pr_info("CP L3 -> L0\n");
- }
- reenable_autosuspend = true;
-
+ /* PMC is driving hsic bus
+ * tegra_baseband_rail_off();
+ */
return 0;
-
}
-
-#ifdef CONFIG_PM
-static int baseband_xmm_power_driver_suspend(struct device *dev)
+static int xmm_power_driver_resume(struct device *dev)
{
pr_debug("%s\n", __func__);
- return 0;
-}
-
-static int baseband_xmm_power_driver_resume(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct baseband_power_platform_data *data
- = (struct baseband_power_platform_data *)
- pdev->dev.platform_data;
- pr_debug("%s\n", __func__);
- baseband_xmm_power_driver_handle_resume(data);
+ /* check if modem is on */
+ if (power_onoff == 0) {
+ pr_debug("%s - flight mode - nop\n", __func__);
+ return 0;
+ }
+ /* PMC is driving hsic bus
+ * tegra_baseband_rail_on();
+ */
+ reenable_autosuspend = true;
return 0;
}
-static int baseband_xmm_power_suspend_noirq(struct device *dev)
+static int xmm_power_suspend_noirq(struct device *dev)
{
unsigned long flags;
@@ -1191,57 +1099,62 @@ static int baseband_xmm_power_suspend_noirq(struct device *dev)
return 0;
}
-static int baseband_xmm_power_resume_noirq(struct device *dev)
+static int xmm_power_resume_noirq(struct device *dev)
{
pr_debug("%s\n", __func__);
return 0;
}
-static const struct dev_pm_ops baseband_xmm_power_dev_pm_ops = {
- .suspend_noirq = baseband_xmm_power_suspend_noirq,
- .resume_noirq = baseband_xmm_power_resume_noirq,
- .suspend = baseband_xmm_power_driver_suspend,
- .resume = baseband_xmm_power_driver_resume,
+static const struct dev_pm_ops xmm_power_dev_pm_ops = {
+ .suspend_noirq = xmm_power_suspend_noirq,
+ .resume_noirq = xmm_power_resume_noirq,
+ .suspend = xmm_power_driver_suspend,
+ .resume = xmm_power_driver_resume,
};
#endif
-static int baseband_xmm_power_driver_shutdown(struct platform_device *device)
+static void xmm_power_driver_shutdown(struct platform_device *device)
{
- struct baseband_power_platform_data *data =
- (struct baseband_power_platform_data *)
- device->dev.platform_data;
+ struct baseband_power_platform_data *pdata = device->dev.platform_data;
pr_debug("%s\n", __func__);
- disable_irq(gpio_to_irq(data->modem.xmm.ipc_ap_wake));
+ disable_irq(gpio_to_irq(pdata->modem.xmm.ipc_ap_wake));
/* bb_on is already down, to make sure set 0 again */
- gpio_set_value(data->modem.xmm.bb_on, 0);
- gpio_set_value(data->modem.xmm.bb_rst, 0);
- return 0;
+ gpio_set_value(pdata->modem.xmm.bb_on, 0);
+ gpio_set_value(pdata->modem.xmm.bb_rst, 0);
+ return;
}
static struct platform_driver baseband_power_driver = {
- .probe = baseband_xmm_power_driver_probe,
- .remove = baseband_xmm_power_driver_remove,
- .shutdown = baseband_xmm_power_driver_shutdown,
+ .probe = xmm_power_driver_probe,
+ .remove = xmm_power_driver_remove,
+ .shutdown = xmm_power_driver_shutdown,
.driver = {
.name = "baseband_xmm_power",
#ifdef CONFIG_PM
- .pm = &baseband_xmm_power_dev_pm_ops,
+ .pm = &xmm_power_dev_pm_ops,
#endif
},
};
-static int __init baseband_xmm_power_init(void)
+static int __init xmm_power_init(void)
{
pr_debug("%s\n", __func__);
+
+ INIT_DELAYED_WORK(&pm_qos_work, pm_qos_worker);
+ pm_qos_add_request(&boost_cpu_freq_req, PM_QOS_CPU_FREQ_MIN,
+ (s32)PM_QOS_CPU_FREQ_MIN_DEFAULT_VALUE);
+
return platform_driver_register(&baseband_power_driver);
}
-static void __exit baseband_xmm_power_exit(void)
+static void __exit xmm_power_exit(void)
{
pr_debug("%s\n", __func__);
platform_driver_unregister(&baseband_power_driver);
+
+ pm_qos_remove_request(&boost_cpu_freq_req);
}
-module_init(baseband_xmm_power_init)
-module_exit(baseband_xmm_power_exit)
+module_init(xmm_power_init)
+module_exit(xmm_power_exit)
diff --git a/arch/arm/mach-tegra/baseband-xmm-power.h b/arch/arm/mach-tegra/baseband-xmm-power.h
index 0768ed191b05..69140891319d 100644
--- a/arch/arm/mach-tegra/baseband-xmm-power.h
+++ b/arch/arm/mach-tegra/baseband-xmm-power.h
@@ -71,24 +71,22 @@ enum baseband_xmm_power_work_state_t {
BBXMM_WORK_INIT_FLASH_STEP1,
/* initialize flash (with power management support) modem */
BBXMM_WORK_INIT_FLASH_PM_STEP1,
- BBXMM_WORK_INIT_FLASH_PM_VER_LT_1130_STEP1,
- BBXMM_WORK_INIT_FLASH_PM_VER_GE_1130_STEP1,
/* initialize flashless (with power management support) modem */
BBXMM_WORK_INIT_FLASHLESS_PM_STEP1,
- BBXMM_WORK_INIT_FLASHLESS_PM_VER_LT_1130_WAIT_IRQ,
- BBXMM_WORK_INIT_FLASHLESS_PM_VER_LT_1130_STEP1,
- BBXMM_WORK_INIT_FLASHLESS_PM_VER_LT_1130_STEP2,
- BBXMM_WORK_INIT_FLASHLESS_PM_VER_GE_1130_STEP1,
- BBXMM_WORK_INIT_FLASHLESS_PM_VER_GE_1130_STEP2,
- BBXMM_WORK_INIT_FLASHLESS_PM_VER_GE_1130_STEP3,
- BBXMM_WORK_INIT_FLASHLESS_PM_VER_GE_1130_STEP4,
+ BBXMM_WORK_INIT_FLASHLESS_PM_STEP2,
+ BBXMM_WORK_INIT_FLASHLESS_PM_STEP3,
+ BBXMM_WORK_INIT_FLASHLESS_PM_STEP4,
};
-struct baseband_xmm_power_work_t {
- /* work structure must be first structure member */
- struct work_struct work;
+struct xmm_power_data {
/* xmm modem state */
enum baseband_xmm_power_work_state_t state;
+ struct baseband_power_platform_data *pdata;
+ struct work_struct work;
+ struct platform_device *hsic_device;
+ wait_queue_head_t bb_wait;
+ /* host wakeup gpio state*/
+ unsigned int hostwake;
};
enum baseband_xmm_powerstate_t {
@@ -104,8 +102,9 @@ enum baseband_xmm_powerstate_t {
BBXMM_PS_LAST = -1,
};
-irqreturn_t baseband_xmm_power_ipc_ap_wake_irq(int irq, void *dev_id);
+irqreturn_t xmm_power_ipc_ap_wake_irq(int irq, void *dev_id);
void baseband_xmm_set_power_status(unsigned int status);
+extern struct xmm_power_data xmm_power_drv_data;
#endif /* BASREBAND_XMM_POWER_H */
diff --git a/arch/arm/mach-tegra/baseband-xmm-power2.c b/arch/arm/mach-tegra/baseband-xmm-power2.c
index 4295b3958202..3c6285c0a070 100644
--- a/arch/arm/mach-tegra/baseband-xmm-power2.c
+++ b/arch/arm/mach-tegra/baseband-xmm-power2.c
@@ -32,8 +32,6 @@
#include "board.h"
#include "devices.h"
-MODULE_LICENSE("GPL");
-
static unsigned long XYZ = 1000 * 1000000 + 800 * 1000 + 500;
module_param(modem_ver, ulong, 0644);
@@ -49,9 +47,8 @@ module_param(XYZ, ulong, 0644);
MODULE_PARM_DESC(XYZ,
"baseband xmm power2 - timing parameters X/Y/Z delay in ms");
-static struct baseband_power_platform_data *baseband_power2_driver_data;
static struct workqueue_struct *workqueue;
-static struct baseband_xmm_power_work_t *baseband_xmm_power2_work;
+static bool free_ipc_ap_wake_irq;
static enum {
IPC_AP_WAKE_UNINIT,
@@ -62,105 +59,37 @@ static enum {
IPC_AP_WAKE_H,
} ipc_ap_wake_state;
-static irqreturn_t baseband_xmm_power2_ver_lt_1130_ipc_ap_wake_irq2
- (int irq, void *dev_id)
-{
- int value;
-
- pr_debug("%s\n", __func__);
-
- /* check for platform data */
- if (!baseband_power2_driver_data)
- return IRQ_HANDLED;
- value = gpio_get_value(baseband_power2_driver_data->
- modem.xmm.ipc_ap_wake);
-
- /* IPC_AP_WAKE state machine */
- if (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) {
- 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 */
- baseband_xmm_power2_work->state =
- BBXMM_WORK_INIT_FLASHLESS_PM_VER_LT_1130_STEP1;
- queue_work(workqueue, (struct work_struct *)
- baseband_xmm_power2_work);
- } else {
- pr_debug("%s - IPC_AP_WAKE_INIT1"
- " - wait for falling edge\n",
- __func__);
- }
- } 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 */
- baseband_xmm_power2_work->state =
- BBXMM_WORK_INIT_FLASHLESS_PM_VER_LT_1130_STEP2;
- queue_work(workqueue, (struct work_struct *)
- baseband_xmm_power2_work);
- }
- } else {
- if (!value) {
- pr_debug("%s - falling\n", __func__);
- ipc_ap_wake_state = IPC_AP_WAKE_L;
- } else {
- pr_debug("%s - rising\n", __func__);
- ipc_ap_wake_state = IPC_AP_WAKE_H;
- }
- return baseband_xmm_power_ipc_ap_wake_irq(irq, dev_id);
- }
-
- return IRQ_HANDLED;
-}
-
-static irqreturn_t baseband_xmm_power2_ver_ge_1130_ipc_ap_wake_irq2
- (int irq, void *dev_id)
+static irqreturn_t xmm_power2_ipc_ap_wake_irq(int irq, void *dev_id)
{
int value;
+ 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 (!baseband_power2_driver_data)
+ if (!pdata)
return IRQ_HANDLED;
- value = gpio_get_value(baseband_power2_driver_data->
- modem.xmm.ipc_ap_wake);
+ value = gpio_get_value(pdata->modem.xmm.ipc_ap_wake);
/* IPC_AP_WAKE state machine */
- if (ipc_ap_wake_state < IPC_AP_WAKE_IRQ_READY) {
+ 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) {
+ else if (ipc_ap_wake_state == IPC_AP_WAKE_IRQ_READY) {
if (!value) {
- pr_debug("%s - IPC_AP_WAKE_INIT1"
- " - got falling edge\n",
+ pr_debug("%s: IPC_AP_WAKE_INIT1 got falling edge\n",
__func__);
/* go to IPC_AP_WAKE_INIT2 state */
ipc_ap_wake_state = IPC_AP_WAKE_INIT2;
/* queue work */
- baseband_xmm_power2_work->state =
- BBXMM_WORK_INIT_FLASHLESS_PM_VER_GE_1130_STEP2;
- queue_work(workqueue, (struct work_struct *)
- baseband_xmm_power2_work);
- } else {
- pr_debug("%s - IPC_AP_WAKE_INIT1"
- " - wait for falling edge\n",
- __func__);
- }
+ data->state =
+ BBXMM_WORK_INIT_FLASHLESS_PM_STEP2;
+ queue_work(workqueue, &data->work);
+ } else
+ pr_debug("%s: IPC_AP_WAKE_INIT1"
+ " wait for falling edge\n", __func__);
} else {
if (!value) {
pr_debug("%s - falling\n", __func__);
@@ -169,260 +98,154 @@ static irqreturn_t baseband_xmm_power2_ver_ge_1130_ipc_ap_wake_irq2
pr_debug("%s - rising\n", __func__);
ipc_ap_wake_state = IPC_AP_WAKE_H;
}
- return baseband_xmm_power_ipc_ap_wake_irq(irq, dev_id);
+ return xmm_power_ipc_ap_wake_irq(irq, dev_id);
}
return IRQ_HANDLED;
}
-static void baseband_xmm_power2_flashless_pm_ver_lt_1130_step1
- (struct work_struct *work)
-{
- int value;
-
- pr_debug("%s {\n", __func__);
-
- /* check for platform data */
- if (!baseband_power2_driver_data)
- return;
-
- /* check if IPC_HSIC_ACTIVE high */
- value = gpio_get_value(baseband_power2_driver_data->
- modem.xmm.ipc_hsic_active);
- if (value != 1) {
- pr_err("%s - expected IPC_HSIC_ACTIVE high!\n", __func__);
- return;
- }
-
- /* wait 30 ms */
- mdelay(30);
-
- /* set IPC_HSIC_ACTIVE low */
- gpio_set_value(baseband_power2_driver_data->
- modem.xmm.ipc_hsic_active, 0);
-
- pr_debug("%s }\n", __func__);
-}
-
-static void baseband_xmm_power2_flashless_pm_ver_lt_1130_step2
- (struct work_struct *work)
-{
- int value;
-
- pr_debug("%s {\n", __func__);
-
- /* check for platform data */
- if (!baseband_power2_driver_data)
- return;
-
- /* check if IPC_HSIC_ACTIVE low */
- value = gpio_get_value(baseband_power2_driver_data->
- modem.xmm.ipc_hsic_active);
- if (value != 0) {
- pr_err("%s - expected IPC_HSIC_ACTIVE low!\n", __func__);
- return;
- }
-
- /* wait 1 ms */
- mdelay(1);
-
- /* unregister usb host controller */
- if (baseband_power2_driver_data->hsic_unregister)
- baseband_power2_driver_data->hsic_unregister(
- baseband_power2_driver_data->modem.xmm.hsic_device);
- else
- pr_err("%s: hsic_unregister is missing\n", __func__);
-
- /* set IPC_HSIC_ACTIVE high */
- gpio_set_value(baseband_power2_driver_data->
- modem.xmm.ipc_hsic_active, 1);
-
- /* wait 20 ms */
- mdelay(20);
-
- /* set IPC_HSIC_ACTIVE low */
- gpio_set_value(baseband_power2_driver_data->
- modem.xmm.ipc_hsic_active, 0);
-
- /* wait 20 ms */
- mdelay(20);
-
- /* set IPC_HSIC_ACTIVE high */
- gpio_set_value(baseband_power2_driver_data->
- modem.xmm.ipc_hsic_active, 1);
-
- pr_debug("%s }\n", __func__);
-}
-
-static void baseband_xmm_power2_flashless_pm_ver_ge_1130_step1
- (struct work_struct *work)
+static void xmm_power2_step1(struct work_struct *work)
{
+ struct xmm_power_data *data =
+ container_of(work, struct xmm_power_data, work);
+ struct baseband_power_platform_data *pdata = data->pdata;
int X = XYZ / 1000000;
- int Y = XYZ / 1000 - X * 1000;
- int Z = XYZ % 1000;
pr_info("%s {\n", __func__);
- pr_info("XYZ=%ld X=%d Y=%d Z=%d\n", XYZ, X, Y, Z);
-
/* check for platform data */
- if (!baseband_power2_driver_data)
+ if (!pdata)
return;
/* unregister usb host controller */
- if (baseband_power2_driver_data->hsic_unregister)
- baseband_power2_driver_data->hsic_unregister(
- baseband_power2_driver_data->modem.xmm.hsic_device);
+ if (pdata->hsic_unregister)
+ pdata->hsic_unregister(data->hsic_device);
else
pr_err("%s: hsic_unregister is missing\n", __func__);
/* wait X ms */
- mdelay(X);
+ msleep(X);
/* set IPC_HSIC_ACTIVE low */
- gpio_set_value(baseband_power2_driver_data->
- modem.xmm.ipc_hsic_active, 0);
+ gpio_set_value(pdata->modem.xmm.ipc_hsic_active, 0);
pr_info("%s }\n", __func__);
}
-static void baseband_xmm_power2_flashless_pm_ver_ge_1130_step2
- (struct work_struct *work)
+static void xmm_power2_step2(struct work_struct *work)
{
+ struct xmm_power_data *data =
+ container_of(work, struct xmm_power_data, work);
+ struct baseband_power_platform_data *pdata = data->pdata;
int X = XYZ / 1000000;
int Y = XYZ / 1000 - X * 1000;
int Z = XYZ % 1000;
pr_info("%s {\n", __func__);
- pr_info("XYZ=%ld X=%d Y=%d Z=%d\n", XYZ, X, Y, Z);
-
/* check for platform data */
- if (!baseband_power2_driver_data)
+ if (!data || !pdata)
return;
/* wait Y ms */
- mdelay(Y);
+ msleep(Y);
/* register usb host controller */
- if (baseband_power2_driver_data->hsic_register)
- baseband_power2_driver_data->modem.xmm.hsic_device =
- baseband_power2_driver_data->hsic_register();
+ if (pdata->hsic_register)
+ data->hsic_device = pdata->hsic_register();
else
pr_err("%s: hsic_register is missing\n", __func__);
/* wait Z ms */
- mdelay(Z);
+ msleep(Z);
/* set IPC_HSIC_ACTIVE high */
- gpio_set_value(baseband_power2_driver_data->
- modem.xmm.ipc_hsic_active, 1);
+ gpio_set_value(pdata->modem.xmm.ipc_hsic_active, 1);
/* queue work function to check if enumeration succeeded */
- baseband_xmm_power2_work->state =
- BBXMM_WORK_INIT_FLASHLESS_PM_VER_GE_1130_STEP3;
- queue_work(workqueue, (struct work_struct *)
- baseband_xmm_power2_work);
+ data->state = BBXMM_WORK_INIT_FLASHLESS_PM_STEP3;
+ queue_work(workqueue, &data->work);
pr_info("%s }\n", __func__);
}
-static void baseband_xmm_power2_flashless_pm_ver_ge_1130_step3
- (struct work_struct *work)
+static void xmm_power2_step3(struct work_struct *work)
{
- int X = XYZ / 1000000;
- int Y = XYZ / 1000 - X * 1000;
- int Z = XYZ % 1000;
+ struct xmm_power_data *data =
+ container_of(work, struct xmm_power_data, work);
+ struct baseband_power_platform_data *pdata = data->pdata;
int enum_success = 0;
+ mm_segment_t oldfs;
+ struct file *filp;
pr_info("%s {\n", __func__);
- pr_info("XYZ=%ld X=%d Y=%d Z=%d\n", XYZ, X, Y, Z);
-
/* check for platform data */
- if (!baseband_power2_driver_data)
+ if (!data || !pdata)
return;
- /* wait 500 ms */
- mdelay(500);
+ /* wait 1 sec */
+ msleep(1000);
/* check if enumeration succeeded */
- {
- mm_segment_t oldfs;
- struct file *filp;
- oldfs = get_fs();
- set_fs(KERNEL_DS);
- filp = filp_open("/dev/ttyACM0",
- O_RDONLY, 0);
- if (IS_ERR(filp) || (filp == NULL)) {
- pr_err("/dev/ttyACM0 %ld\n",
- PTR_ERR(filp));
- } else {
- filp_close(filp, NULL);
- enum_success = 1;
- }
- set_fs(oldfs);
+ oldfs = get_fs();
+ set_fs(KERNEL_DS);
+ filp = filp_open("/dev/ttyACM0", O_RDONLY, 0);
+ if (IS_ERR(filp) || (filp == NULL))
+ pr_err("failed to open /dev/ttyACM0 %ld\n", PTR_ERR(filp));
+ else {
+ filp_close(filp, NULL);
+ enum_success = 1;
}
+ set_fs(oldfs);
/* if enumeration failed, attempt recovery pulse */
if (!enum_success) {
pr_info("attempting recovery pulse...\n");
/* wait 20 ms */
- mdelay(20);
+ msleep(20);
/* set IPC_HSIC_ACTIVE low */
- gpio_set_value(baseband_power2_driver_data->
- modem.xmm.ipc_hsic_active, 0);
+ gpio_set_value(pdata->modem.xmm.ipc_hsic_active, 0);
/* wait 20 ms */
- mdelay(20);
+ msleep(20);
/* set IPC_HSIC_ACTIVE high */
- gpio_set_value(baseband_power2_driver_data->
- modem.xmm.ipc_hsic_active, 1);
+ gpio_set_value(pdata->modem.xmm.ipc_hsic_active, 1);
/* check if recovery pulse worked */
- baseband_xmm_power2_work->state =
- BBXMM_WORK_INIT_FLASHLESS_PM_VER_GE_1130_STEP4;
- queue_work(workqueue, (struct work_struct *)
- baseband_xmm_power2_work);
+ data->state = BBXMM_WORK_INIT_FLASHLESS_PM_STEP4;
+ queue_work(workqueue, &data->work);
}
pr_info("%s }\n", __func__);
}
-static void baseband_xmm_power2_flashless_pm_ver_ge_1130_step4
- (struct work_struct *work)
+static void xmm_power2_step4(struct work_struct *work)
{
- int X = XYZ / 1000000;
- int Y = XYZ / 1000 - X * 1000;
- int Z = XYZ % 1000;
+ struct xmm_power_data *data =
+ container_of(work, struct xmm_power_data, work);
+ mm_segment_t oldfs;
+ struct file *filp;
int enum_success = 0;
pr_info("%s {\n", __func__);
- pr_info("XYZ=%ld X=%d Y=%d Z=%d\n", XYZ, X, Y, Z);
-
/* check for platform data */
- if (!baseband_power2_driver_data)
+ if (!data)
return;
/* wait 500 ms */
- mdelay(500);
+ msleep(500);
/* check if enumeration succeeded */
- {
- mm_segment_t oldfs;
- struct file *filp;
- oldfs = get_fs();
- set_fs(KERNEL_DS);
- filp = filp_open("/dev/ttyACM0",
- O_RDONLY, 0);
- if (IS_ERR(filp) || (filp == NULL)) {
- pr_err("open /dev/ttyACM0 failed %ld\n",
- PTR_ERR(filp));
- } else {
- filp_close(filp, NULL);
- enum_success = 1;
- }
- set_fs(oldfs);
+ oldfs = get_fs();
+ set_fs(KERNEL_DS);
+ filp = filp_open("/dev/ttyACM0", O_RDONLY, 0);
+ if (IS_ERR(filp) || (filp == NULL))
+ pr_err("failed to open /dev/ttyACM0 %ld\n", PTR_ERR(filp));
+ else {
+ filp_close(filp, NULL);
+ enum_success = 1;
}
+ set_fs(oldfs);
/* if recovery pulse did not fix enumeration, retry from beginning */
if (!enum_success) {
@@ -438,34 +261,31 @@ static void baseband_xmm_power2_flashless_pm_ver_ge_1130_step4
retry);
--retry;
ipc_ap_wake_state = IPC_AP_WAKE_IRQ_READY;
- baseband_xmm_power2_work->state =
- BBXMM_WORK_INIT_FLASHLESS_PM_VER_GE_1130_STEP1;
- queue_work(workqueue, (struct work_struct *)
- baseband_xmm_power2_work);
+ data->state = BBXMM_WORK_INIT_FLASHLESS_PM_STEP1;
+ queue_work(workqueue, &data->work);
}
}
pr_info("%s }\n", __func__);
}
-static int free_ipc_ap_wake_irq;
-
-static void baseband_xmm_power2_work_func(struct work_struct *work)
+static void xmm_power2_work_func(struct work_struct *work)
{
- struct baseband_xmm_power_work_t *bbxmm_work
- = (struct baseband_xmm_power_work_t *) work;
+ struct xmm_power_data *data =
+ container_of(work, struct xmm_power_data, work);
+ struct baseband_power_platform_data *pdata = data->pdata;
int err;
- pr_debug("%s bbxmm_work->state=%d\n", __func__, bbxmm_work->state);
+ pr_debug("%s pdata->state=%d\n", __func__, data->state);
- switch (bbxmm_work->state) {
+ switch (data->state) {
case BBXMM_WORK_UNINIT:
pr_debug("BBXMM_WORK_UNINIT\n");
/* free baseband irq(s) */
if (free_ipc_ap_wake_irq) {
- free_irq(gpio_to_irq(baseband_power2_driver_data
- ->modem.xmm.ipc_ap_wake), NULL);
- free_ipc_ap_wake_irq = 0;
+ free_irq(gpio_to_irq(pdata->modem.xmm.ipc_ap_wake),
+ data);
+ free_ipc_ap_wake_irq = false;
}
break;
case BBXMM_WORK_INIT:
@@ -473,24 +293,20 @@ static void baseband_xmm_power2_work_func(struct work_struct *work)
/* request baseband irq(s) */
ipc_ap_wake_state = IPC_AP_WAKE_UNINIT;
err = request_threaded_irq(
- gpio_to_irq(baseband_power2_driver_data->
- modem.xmm.ipc_ap_wake),
- NULL,
- (modem_ver < XMM_MODEM_VER_1130)
- ? baseband_xmm_power2_ver_lt_1130_ipc_ap_wake_irq2
- : baseband_xmm_power2_ver_ge_1130_ipc_ap_wake_irq2,
- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
- "BBXMM_POWER2_IPC_AP_WAKE_IRQ",
- NULL);
+ gpio_to_irq(pdata->modem.xmm.ipc_ap_wake),
+ NULL, xmm_power2_ipc_ap_wake_irq,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ "xmm_power2_ipc_ap_wake_irq", data);
if (err < 0) {
pr_err("%s - request irq IPC_AP_WAKE_IRQ failed\n",
__func__);
return;
}
- free_ipc_ap_wake_irq = 1;
+ free_ipc_ap_wake_irq = true;
ipc_ap_wake_state = IPC_AP_WAKE_IRQ_READY;
+
/* go to next state */
- bbxmm_work->state = (modem_flash && !modem_pm)
+ data->state = (modem_flash && !modem_pm)
? BBXMM_WORK_INIT_FLASH_STEP1
: (modem_flash && modem_pm)
? BBXMM_WORK_INIT_FLASH_PM_STEP1
@@ -501,130 +317,93 @@ static void baseband_xmm_power2_work_func(struct work_struct *work)
break;
case BBXMM_WORK_INIT_FLASH_STEP1:
pr_debug("BBXMM_WORK_INIT_FLASH_STEP1\n");
+ pr_info("%s: flashed modem is not supported here\n", __func__);
break;
case BBXMM_WORK_INIT_FLASH_PM_STEP1:
pr_debug("BBXMM_WORK_INIT_FLASH_PM_STEP1\n");
- /* go to next state */
- bbxmm_work->state = (modem_ver < XMM_MODEM_VER_1130)
- ? BBXMM_WORK_INIT_FLASH_PM_VER_LT_1130_STEP1
- : BBXMM_WORK_INIT_FLASH_PM_VER_GE_1130_STEP1;
- queue_work(workqueue, work);
- break;
- case BBXMM_WORK_INIT_FLASH_PM_VER_LT_1130_STEP1:
- pr_debug("BBXMM_WORK_INIT_FLASH_PM_VER_LT_1130_STEP1\n");
- break;
- case BBXMM_WORK_INIT_FLASH_PM_VER_GE_1130_STEP1:
- pr_debug("BBXMM_WORK_INIT_FLASH_PM_VER_GE_1130_STEP1\n");
+ pr_info("%s: flashed modem is not supported here\n", __func__);
break;
case BBXMM_WORK_INIT_FLASHLESS_PM_STEP1:
+ /* start flashless modem enum process */
pr_debug("BBXMM_WORK_INIT_FLASHLESS_PM_STEP1\n");
- /* go to next state */
- bbxmm_work->state = (modem_ver < XMM_MODEM_VER_1130)
- ? BBXMM_WORK_INIT_FLASHLESS_PM_VER_LT_1130_WAIT_IRQ
- : BBXMM_WORK_INIT_FLASHLESS_PM_VER_GE_1130_STEP1;
- queue_work(workqueue, work);
- break;
- case BBXMM_WORK_INIT_FLASHLESS_PM_VER_LT_1130_WAIT_IRQ:
- pr_debug("BBXMM_WORK_INIT_FLASHLESS_PM_VER_LT_1130_WAIT_IRQ"
- " - waiting for IPC_AP_WAKE_IRQ to trigger step1\n");
- break;
- case BBXMM_WORK_INIT_FLASHLESS_PM_VER_LT_1130_STEP1:
- pr_debug("BBXMM_WORK_INIT_FLASHLESS_PM_VER_LT_1130_STEP1\n");
- baseband_xmm_power2_flashless_pm_ver_lt_1130_step1(work);
+ xmm_power2_step1(work);
break;
- case BBXMM_WORK_INIT_FLASHLESS_PM_VER_LT_1130_STEP2:
- pr_debug("BBXMM_WORK_INIT_FLASHLESS_PM_VER_LT_1130_STEP2\n");
- baseband_xmm_power2_flashless_pm_ver_lt_1130_step2(work);
+ case BBXMM_WORK_INIT_FLASHLESS_PM_STEP2:
+ pr_debug("BBXMM_WORK_INIT_FLASHLESS_PM_STEP2\n");
+ xmm_power2_step2(work);
break;
- case BBXMM_WORK_INIT_FLASHLESS_PM_VER_GE_1130_STEP1:
- pr_debug("BBXMM_WORK_INIT_FLASHLESS_PM_VER_GE_1130_STEP1\n");
- baseband_xmm_power2_flashless_pm_ver_ge_1130_step1(work);
+ case BBXMM_WORK_INIT_FLASHLESS_PM_STEP3:
+ pr_debug("BBXMM_WORK_INIT_FLASHLESS_PM_STEP3\n");
+ xmm_power2_step3(work);
break;
- case BBXMM_WORK_INIT_FLASHLESS_PM_VER_GE_1130_STEP2:
- pr_debug("BBXMM_WORK_INIT_FLASHLESS_PM_VER_GE_1130_STEP2\n");
- baseband_xmm_power2_flashless_pm_ver_ge_1130_step2(work);
+ case BBXMM_WORK_INIT_FLASHLESS_PM_STEP4:
+ pr_debug("BBXMM_WORK_INIT_FLASHLESS_PM_STEP4\n");
+ xmm_power2_step4(work);
break;
- case BBXMM_WORK_INIT_FLASHLESS_PM_VER_GE_1130_STEP3:
- pr_debug("BBXMM_WORK_INIT_FLASHLESS_PM_VER_GE_1130_STEP3\n");
- baseband_xmm_power2_flashless_pm_ver_ge_1130_step3(work);
- break;
- case BBXMM_WORK_INIT_FLASHLESS_PM_VER_GE_1130_STEP4:
- pr_debug("BBXMM_WORK_INIT_FLASHLESS_PM_VER_GE_1130_STEP4\n");
- baseband_xmm_power2_flashless_pm_ver_ge_1130_step4(work);
+ default:
break;
}
-
}
-static int baseband_xmm_power2_driver_probe(struct platform_device *device)
+static int xmm_power2_probe(struct platform_device *device)
{
- struct baseband_power_platform_data *data
- = (struct baseband_power_platform_data *)
- device->dev.platform_data;
-
pr_debug("%s\n", __func__);
+ if (!device->dev.platform_data) {
+ pr_err("%s: no platform data found\n", __func__);
+ return -ENOMEM;
+ }
- /* save platform data */
- baseband_power2_driver_data = data;
+ xmm_power_drv_data.pdata = device->dev.platform_data;
- /* init work queue */
+ /* create workqueue */
pr_debug("%s: init work queue\n", __func__);
- workqueue = create_singlethread_workqueue
- ("baseband_xmm_power2_workqueue");
- if (!workqueue) {
- pr_err("cannot create workqueue\n");
- return -1;
- }
- baseband_xmm_power2_work = (struct baseband_xmm_power_work_t *)
- kmalloc(sizeof(struct baseband_xmm_power_work_t), GFP_KERNEL);
- if (!baseband_xmm_power2_work) {
- pr_err("cannot allocate baseband_xmm_power2_work\n");
- return -1;
+ workqueue = create_singlethread_workqueue("xmm_power2_wq");
+ if (unlikely(!workqueue)) {
+ pr_err("%s: cannot create workqueue\n", __func__);
+ return -ENOMEM;
}
+
+ /* init work */
pr_debug("%s: BBXMM_WORK_INIT\n", __func__);
- INIT_WORK((struct work_struct *) baseband_xmm_power2_work,
- baseband_xmm_power2_work_func);
- baseband_xmm_power2_work->state = BBXMM_WORK_INIT;
- queue_work(workqueue,
- (struct work_struct *) baseband_xmm_power2_work);
+ INIT_WORK(&xmm_power_drv_data.work, xmm_power2_work_func);
+ xmm_power_drv_data.state = BBXMM_WORK_INIT;
+ queue_work(workqueue, &xmm_power_drv_data.work);
+
return 0;
}
-static int baseband_xmm_power2_driver_remove(struct platform_device *device)
+static int xmm_power2_remove(struct platform_device *device)
{
- struct baseband_power_platform_data *data
- = (struct baseband_power_platform_data *)
+ struct baseband_power_platform_data *pdata =
device->dev.platform_data;
+ struct xmm_power_data *data = &xmm_power_drv_data;
pr_debug("%s\n", __func__);
/* check for platform data */
if (!data)
- return 0;
-
- /* free irq */
- if (free_ipc_ap_wake_irq) {
- free_irq(gpio_to_irq(data->modem.xmm.ipc_ap_wake), NULL);
- free_ipc_ap_wake_irq = 0;
- }
+ return -ENODEV;
- /* free work structure */
+ /* free work queue */
if (workqueue) {
- cancel_work_sync(baseband_xmm_power2_work);
+ cancel_work_sync(&data->work);
destroy_workqueue(workqueue);
}
- kfree(baseband_xmm_power2_work);
- baseband_xmm_power2_work = (struct baseband_xmm_power_work_t *) 0;
+
+ /* free irq */
+ if (free_ipc_ap_wake_irq) {
+ free_irq(gpio_to_irq(pdata->modem.xmm.ipc_ap_wake), data);
+ free_ipc_ap_wake_irq = false;
+ }
return 0;
}
#ifdef CONFIG_PM
-static int baseband_xmm_power2_driver_suspend(struct platform_device *device,
+static int xmm_power2_suspend(struct platform_device *device,
pm_message_t state)
{
- struct baseband_power_platform_data *data
- = (struct baseband_power_platform_data *)
+ struct baseband_power_platform_data *data =
device->dev.platform_data;
pr_debug("%s - nop\n", __func__);
@@ -636,10 +415,9 @@ static int baseband_xmm_power2_driver_suspend(struct platform_device *device,
return 0;
}
-static int baseband_xmm_power2_driver_resume(struct platform_device *device)
+static int xmm_power2_resume(struct platform_device *device)
{
- struct baseband_power_platform_data *data
- = (struct baseband_power_platform_data *)
+ struct baseband_power_platform_data *data =
device->dev.platform_data;
pr_debug("%s - nop\n", __func__);
@@ -653,29 +431,32 @@ static int baseband_xmm_power2_driver_resume(struct platform_device *device)
#endif
static struct platform_driver baseband_power2_driver = {
- .probe = baseband_xmm_power2_driver_probe,
- .remove = baseband_xmm_power2_driver_remove,
+ .probe = xmm_power2_probe,
+ .remove = xmm_power2_remove,
#ifdef CONFIG_PM
- .suspend = baseband_xmm_power2_driver_suspend,
- .resume = baseband_xmm_power2_driver_resume,
+ .suspend = xmm_power2_suspend,
+ .resume = xmm_power2_resume,
#endif
.driver = {
.name = "baseband_xmm_power2",
},
};
-static int __init baseband_xmm_power2_init(void)
+static int __init xmm_power2_init(void)
{
pr_debug("%s\n", __func__);
return platform_driver_register(&baseband_power2_driver);
}
-static void __exit baseband_xmm_power2_exit(void)
+static void __exit xmm_power2_exit(void)
{
pr_debug("%s\n", __func__);
+
platform_driver_unregister(&baseband_power2_driver);
}
-module_init(baseband_xmm_power2_init)
-module_exit(baseband_xmm_power2_exit)
+module_init(xmm_power2_init)
+module_exit(xmm_power2_exit)
+
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-tegra/board-aruba-panel.c b/arch/arm/mach-tegra/board-aruba-panel.c
index b014326fc91b..01ade01a0eb6 100644
--- a/arch/arm/mach-tegra/board-aruba-panel.c
+++ b/arch/arm/mach-tegra/board-aruba-panel.c
@@ -26,7 +26,7 @@
#include <linux/platform_device.h>
#include <linux/pwm_backlight.h>
#include <linux/nvhost.h>
-#include <mach/nvmap.h>
+#include <linux/nvmap.h>
#include <mach/irqs.h>
#include <mach/iomap.h>
#include <mach/dc.h>
@@ -35,6 +35,7 @@
#include "board.h"
#include "devices.h"
#include "gpio-names.h"
+#include "tegra2_host1x_devices.h"
#define aruba_lvds_shutdown TEGRA_GPIO_PB2
#define aruba_bl_enb TEGRA_GPIO_PW1
@@ -228,7 +229,7 @@ int __init aruba_panel_init(void)
#endif
#ifdef CONFIG_TEGRA_GRHOST
- err = nvhost_device_register(&tegra_grhost_device);
+ err = tegra2_register_host1x_devices();
if (err)
return err;
#endif
diff --git a/arch/arm/mach-tegra/board-aruba-power.c b/arch/arm/mach-tegra/board-aruba-power.c
index 4391f6f19b51..b72b82fc144a 100644
--- a/arch/arm/mach-tegra/board-aruba-power.c
+++ b/arch/arm/mach-tegra/board-aruba-power.c
@@ -26,7 +26,6 @@
#include "pm.h"
#include "board.h"
-#include "wakeups-t3.h"
static int ac_online(void)
{
diff --git a/arch/arm/mach-tegra/board-aruba.c b/arch/arm/mach-tegra/board-aruba.c
index 152f34720489..2fc524ccef93 100644
--- a/arch/arm/mach-tegra/board-aruba.c
+++ b/arch/arm/mach-tegra/board-aruba.c
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-tegra/board-aruba.c
*
- * Copyright (c) 2010-2011, NVIDIA Corporation.
+ * Copyright (c) 2010-2012, NVIDIA Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -47,6 +47,7 @@
#include <asm/mach/arch.h>
#include <mach/usb_phy.h>
#include <mach/nand.h>
+#include <mach/tegra_fiq_debugger.h>
#include "board.h"
#include "clock.h"
#include "board-aruba.h"
@@ -446,7 +447,9 @@ static struct platform_device *aruba_devices[] __initdata = {
&tegra_smmu_device,
#endif
&aruba_keys_device,
- &tegra_wdt_device,
+ &tegra_wdt0_device,
+ &tegra_wdt1_device,
+ &tegra_wdt2_device,
#if defined(CONFIG_SND_HDA_TEGRA)
&tegra_hda_device,
#endif
@@ -522,6 +525,7 @@ static void __init tegra_aruba_init(void)
aruba_bt_rfkill();
aruba_sata_init();
tegra_release_bootloader_fb();
+ tegra_serial_debug_init(TEGRA_UARTD_BASE, INT_WDT_CPU, NULL, -1, -1);
}
static void __init tegra_aruba_reserve(void)
diff --git a/arch/arm/mach-tegra/board-cardhu-kbc.c b/arch/arm/mach-tegra/board-cardhu-kbc.c
index 3bf0a3b864fc..c3971403148f 100644
--- a/arch/arm/mach-tegra/board-cardhu-kbc.c
+++ b/arch/arm/mach-tegra/board-cardhu-kbc.c
@@ -174,7 +174,8 @@ static struct gpio_keys_button cardhu_keys_e1291_a04[] = {
[3] = GPIO_KEY(KEY_SEARCH, PQ3, 0),
[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),
+ [6] = GPIO_KEY(KEY_RESERVED, PV0, 1),
+ [7] = GPIO_IKEY(KEY_POWER, TPS6591X_IRQ_BASE + TPS6591X_INT_PWRON, 1, 100),
};
static struct gpio_keys_platform_data cardhu_keys_e1291_pdata = {
@@ -195,12 +196,12 @@ static struct gpio_keys_button cardhu_int_keys[] = {
};
static struct gpio_keys_button cardhu_pm298_int_keys[] = {
- [0] = GPIO_IKEY(KEY_POWER, MAX77663_IRQ_BASE + MAX77663_IRQ_ONOFF_EN0_FALLING, 1, 100),
- [1] = GPIO_IKEY(KEY_POWER, MAX77663_IRQ_BASE + MAX77663_IRQ_ONOFF_EN0_1SEC, 1, 3000),
+ [0] = GPIO_IKEY(KEY_POWER, MAX77663_IRQ_BASE + MAX77663_IRQ_ONOFF_EN0_FALLING, 0, 100),
+ [1] = GPIO_IKEY(KEY_POWER, MAX77663_IRQ_BASE + MAX77663_IRQ_ONOFF_EN0_1SEC, 0, 3000),
};
static struct gpio_keys_button cardhu_pm299_int_keys[] = {
- [0] = GPIO_IKEY(KEY_POWER, RICOH583_IRQ_BASE + RICOH583_IRQ_ONKEY, 1, 100),
+ [0] = GPIO_KEY(KEY_POWER, PV0, 1),
};
static struct gpio_keys_platform_data cardhu_int_keys_pdata = {
@@ -230,6 +231,7 @@ int __init cardhu_keys_init(void)
(board_info.board_id == BOARD_E1257) ||
(board_info.board_id == BOARD_PM305) ||
(board_info.board_id == BOARD_PM311) ||
+ (board_info.board_id == BOARD_PM267) ||
(board_info.board_id == BOARD_PM269)))
return 0;
@@ -250,8 +252,6 @@ int __init cardhu_keys_init(void)
if (get_tegra_image_type() == rck_image)
cardhu_keys_e1291_pdata.buttons[i].code
= KEY_ENTER;
- } else {
- tegra_gpio_enable(gpio_nr);
}
}
@@ -263,8 +263,6 @@ int __init cardhu_keys_init(void)
if (gpio_nr < 0) {
if (get_tegra_image_type() == rck_image)
cardhu_keys_e1198[i].code = KEY_ENTER;
- } else {
- tegra_gpio_enable(gpio_nr);
}
}
@@ -290,6 +288,7 @@ int __init cardhu_keys_init(void)
(board_info.board_id == BOARD_E1186) ||
(board_info.board_id == BOARD_PM305) ||
(board_info.board_id == BOARD_PM311) ||
+ (board_info.board_id == BOARD_PM267) ||
(board_info.board_id == BOARD_PM269)) {
if (get_tegra_image_type() == rck_image)
cardhu_int_keys[0].code = KEY_ENTER;
diff --git a/arch/arm/mach-tegra/board-cardhu-memory.c b/arch/arm/mach-tegra/board-cardhu-memory.c
index 0cd9e0066668..1ed99a9fa1fa 100644
--- a/arch/arm/mach-tegra/board-cardhu-memory.c
+++ b/arch/arm/mach-tegra/board-cardhu-memory.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 NVIDIA, Inc.
+ * 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 version 2 as
@@ -2539,6 +2539,246 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2_2GB1R[] = {
},
{
0x32, /* Rev 3.2 */
+ 400000, /* SDRAM frequency */
+ {
+ 0x00000012, /* EMC_RC */
+ 0x00000066, /* EMC_RFC */
+ 0x0000000c, /* EMC_RAS */
+ 0x00000004, /* EMC_RP */
+ 0x00000003, /* EMC_R2W */
+ 0x00000008, /* EMC_W2R */
+ 0x00000002, /* EMC_R2P */
+ 0x0000000a, /* EMC_W2P */
+ 0x00000004, /* EMC_RD_RCD */
+ 0x00000004, /* EMC_WR_RCD */
+ 0x00000002, /* EMC_RRD */
+ 0x00000001, /* EMC_REXT */
+ 0x00000000, /* EMC_WEXT */
+ 0x00000004, /* EMC_WDV */
+ 0x00000006, /* EMC_QUSE */
+ 0x00000004, /* EMC_QRST */
+ 0x0000000a, /* EMC_QSAFE */
+ 0x0000000d, /* EMC_RDV */
+ 0x00000bf0, /* EMC_REFRESH */
+ 0x00000000, /* EMC_BURST_REFRESH_NUM */
+ 0x000002fc, /* EMC_PRE_REFRESH_REQ_CNT */
+ 0x00000001, /* EMC_PDEX2WR */
+ 0x00000008, /* EMC_PDEX2RD */
+ 0x00000001, /* EMC_PCHG2PDEN */
+ 0x00000000, /* EMC_ACT2PDEN */
+ 0x00000008, /* EMC_AR2PDEN */
+ 0x0000000f, /* EMC_RW2PDEN */
+ 0x0000006c, /* EMC_TXSR */
+ 0x00000200, /* EMC_TXSRDLL */
+ 0x00000004, /* EMC_TCKE */
+ 0x0000000c, /* EMC_TFAW */
+ 0x00000000, /* EMC_TRPAB */
+ 0x00000004, /* EMC_TCLKSTABLE */
+ 0x00000005, /* EMC_TCLKSTOP */
+ 0x00000c30, /* EMC_TREFBW */
+ 0x00000000, /* EMC_QUSE_EXTRA */
+ 0x00000006, /* EMC_FBIO_CFG6 */
+ 0x00000000, /* EMC_ODT_WRITE */
+ 0x00000000, /* EMC_ODT_READ */
+ 0x00007088, /* EMC_FBIO_CFG5 */
+ 0x001d0084, /* EMC_CFG_DIG_DLL */
+ 0x00008000, /* EMC_CFG_DIG_DLL_PERIOD */
+ 0x00038000, /* EMC_DLL_XFORM_DQS0 */
+ 0x00038000, /* EMC_DLL_XFORM_DQS1 */
+ 0x00038000, /* EMC_DLL_XFORM_DQS2 */
+ 0x00038000, /* EMC_DLL_XFORM_DQS3 */
+ 0x00038000, /* EMC_DLL_XFORM_DQS4 */
+ 0x00038000, /* EMC_DLL_XFORM_DQS5 */
+ 0x00038000, /* EMC_DLL_XFORM_DQS6 */
+ 0x00038000, /* 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 */
+ 0x00030000, /* EMC_DLL_XFORM_DQ0 */
+ 0x00030000, /* EMC_DLL_XFORM_DQ1 */
+ 0x00030000, /* EMC_DLL_XFORM_DQ2 */
+ 0x00030000, /* 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 */
+ 0x0158000c, /* EMC_MRS_WAIT_CNT */
+ 0xa0f10000, /* EMC_AUTO_CAL_CONFIG */
+ 0x00000000, /* EMC_CTT */
+ 0x00000000, /* EMC_CTT_DURATION */
+ 0x800018c8, /* EMC_DYN_SELF_REF_CONTROL */
+ 0x00000006, /* MC_EMEM_ARB_CFG */
+ 0x80000048, /* MC_EMEM_ARB_OUTSTANDING_REQ */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_RP */
+ 0x00000009, /* MC_EMEM_ARB_TIMING_RC */
+ 0x00000005, /* MC_EMEM_ARB_TIMING_RAS */
+ 0x00000005, /* 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 */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_W2W */
+ 0x00000003, /* MC_EMEM_ARB_TIMING_R2W */
+ 0x00000006, /* MC_EMEM_ARB_TIMING_W2R */
+ 0x06030202, /* MC_EMEM_ARB_DA_TURNS */
+ 0x000d0709, /* MC_EMEM_ARB_DA_COVERS */
+ 0x7086120a, /* MC_EMEM_ARB_MISC0 */
+ 0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */
+ 0xe8000000, /* EMC_FBIO_SPARE */
+ 0xff00ff89, /* EMC_CFG_RSV */
+ },
+ 0x00000040, /* EMC_ZCAL_WAIT_CNT after clock change */
+ 0x001fffff, /* EMC_AUTO_CAL_INTERVAL */
+ 0x00000000, /* EMC_CFG.PERIODIC_QRST */
+ 0x80000521, /* Mode Register 0 */
+ 0x80100002, /* Mode Register 1 */
+ 0x80200000, /* Mode Register 2 */
+ 0x00000000, /* EMC_CFG.DYN_SELF_REF */
+ },
+ {
+ 0x32, /* Rev 3.2 */
+ 667000, /* SDRAM frequency */
+ {
+ 0x00000023, /* EMC_RC */
+ 0x000000df, /* EMC_RFC */
+ 0x00000019, /* EMC_RAS */
+ 0x00000009, /* EMC_RP */
+ 0x00000005, /* EMC_R2W */
+ 0x0000000d, /* EMC_W2R */
+ 0x00000004, /* EMC_R2P */
+ 0x00000013, /* EMC_W2P */
+ 0x00000009, /* EMC_RD_RCD */
+ 0x00000009, /* EMC_WR_RCD */
+ 0x00000003, /* EMC_RRD */
+ 0x00000001, /* EMC_REXT */
+ 0x00000000, /* EMC_WEXT */
+ 0x00000007, /* EMC_WDV */
+ 0x0000000b, /* EMC_QUSE */
+ 0x00000009, /* EMC_QRST */
+ 0x0000000c, /* EMC_QSAFE */
+ 0x00000011, /* EMC_RDV */
+ 0x00001419, /* EMC_REFRESH */
+ 0x00000000, /* EMC_BURST_REFRESH_NUM */
+ 0x000005a6, /* EMC_PRE_REFRESH_REQ_CNT */
+ 0x00000003, /* EMC_PDEX2WR */
+ 0x00000010, /* EMC_PDEX2RD */
+ 0x00000001, /* EMC_PCHG2PDEN */
+ 0x00000000, /* EMC_ACT2PDEN */
+ 0x0000000e, /* EMC_AR2PDEN */
+ 0x00000018, /* EMC_RW2PDEN */
+ 0x000000e9, /* EMC_TXSR */
+ 0x00000200, /* EMC_TXSRDLL */
+ 0x00000005, /* EMC_TCKE */
+ 0x00000017, /* EMC_TFAW */
+ 0x00000000, /* EMC_TRPAB */
+ 0x00000007, /* EMC_TCLKSTABLE */
+ 0x00000008, /* EMC_TCLKSTOP */
+ 0x000016da, /* EMC_TREFBW */
+ 0x0000000c, /* EMC_QUSE_EXTRA */
+ 0x00000004, /* EMC_FBIO_CFG6 */
+ 0x00000000, /* EMC_ODT_WRITE */
+ 0x00000000, /* EMC_ODT_READ */
+ 0x00005088, /* EMC_FBIO_CFG5 */
+ 0xf0080191, /* 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 */
+ 0x0000000c, /* EMC_DLL_XFORM_DQ0 */
+ 0x0000000c, /* EMC_DLL_XFORM_DQ1 */
+ 0x0000000c, /* EMC_DLL_XFORM_DQ2 */
+ 0x0000000c, /* EMC_DLL_XFORM_DQ3 */
+ 0x000002a0, /* EMC_XM2CMDPADCTRL */
+ 0x0600013d, /* EMC_XM2DQSPADCTRL2 */
+ 0x22220000, /* EMC_XM2DQPADCTRL2 */
+ 0x77fff884, /* EMC_XM2CLKPADCTRL */
+ 0x01f1f501, /* 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 */
+ 0x00df000c, /* EMC_MRS_WAIT_CNT */
+ 0xa0f10000, /* EMC_AUTO_CAL_CONFIG */
+ 0x00000000, /* EMC_CTT */
+ 0x00000000, /* EMC_CTT_DURATION */
+ 0x80002d93, /* EMC_DYN_SELF_REF_CONTROL */
+ 0x0000000b, /* MC_EMEM_ARB_CFG */
+ 0x80000087, /* MC_EMEM_ARB_OUTSTANDING_REQ */
+ 0x00000004, /* MC_EMEM_ARB_TIMING_RCD */
+ 0x00000005, /* MC_EMEM_ARB_TIMING_RP */
+ 0x00000012, /* MC_EMEM_ARB_TIMING_RC */
+ 0x0000000c, /* MC_EMEM_ARB_TIMING_RAS */
+ 0x0000000b, /* MC_EMEM_ARB_TIMING_FAW */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_RRD */
+ 0x00000003, /* MC_EMEM_ARB_TIMING_RAP2PRE */
+ 0x0000000c, /* 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 */
+ 0x00160d12, /* MC_EMEM_ARB_DA_COVERS */
+ 0x73cc2213, /* MC_EMEM_ARB_MISC0 */
+ 0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */
+ 0xf8000000, /* EMC_FBIO_SPARE */
+ 0xff00ff49, /* EMC_CFG_RSV */
+ },
+ 0x00000040, /* EMC_ZCAL_WAIT_CNT after clock change */
+ 0x001fffff, /* EMC_AUTO_CAL_INTERVAL */
+ 0x00000001, /* EMC_CFG.PERIODIC_QRST */
+ 0x80000d71, /* Mode Register 0 */
+ 0x80100002, /* Mode Register 1 */
+ 0x80200018, /* Mode Register 2 */
+ 0x00000000, /* EMC_CFG.DYN_SELF_REF */
+ },
+ {
+ 0x32, /* Rev 3.2 */
750000, /* SDRAM frequency */
{
0x00000023, /* EMC_RC */
@@ -2657,6 +2897,126 @@ static const struct tegra_emc_table cardhu_emc_tables_h5tc2g_a2_2GB1R[] = {
0x80200018, /* Mode Register 2 */
0x00000000, /* EMC_CFG.DYN_SELF_REF */
},
+ {
+ 0x32, /* Rev 3.2 */
+ 800000, /* SDRAM frequency */
+ {
+ 0x00000025, /* EMC_RC */
+ 0x000000ce, /* EMC_RFC */
+ 0x0000001a, /* EMC_RAS */
+ 0x00000009, /* EMC_RP */
+ 0x00000005, /* EMC_R2W */
+ 0x0000000d, /* EMC_W2R */
+ 0x00000004, /* EMC_R2P */
+ 0x00000013, /* EMC_W2P */
+ 0x00000009, /* EMC_RD_RCD */
+ 0x00000009, /* EMC_WR_RCD */
+ 0x00000003, /* EMC_RRD */
+ 0x00000001, /* EMC_REXT */
+ 0x00000000, /* EMC_WEXT */
+ 0x00000007, /* EMC_WDV */
+ 0x0000000b, /* EMC_QUSE */
+ 0x00000009, /* EMC_QRST */
+ 0x0000000c, /* EMC_QSAFE */
+ 0x00000012, /* EMC_RDV */
+ 0x00001820, /* EMC_REFRESH */
+ 0x00000000, /* EMC_BURST_REFRESH_NUM */
+ 0x00000608, /* EMC_PRE_REFRESH_REQ_CNT */
+ 0x00000003, /* EMC_PDEX2WR */
+ 0x00000012, /* EMC_PDEX2RD */
+ 0x00000001, /* EMC_PCHG2PDEN */
+ 0x00000000, /* EMC_ACT2PDEN */
+ 0x0000000f, /* EMC_AR2PDEN */
+ 0x00000018, /* EMC_RW2PDEN */
+ 0x000000d8, /* EMC_TXSR */
+ 0x00000200, /* EMC_TXSRDLL */
+ 0x00000005, /* EMC_TCKE */
+ 0x00000018, /* EMC_TFAW */
+ 0x00000000, /* EMC_TRPAB */
+ 0x00000007, /* EMC_TCLKSTABLE */
+ 0x00000008, /* EMC_TCLKSTOP */
+ 0x00001860, /* EMC_TREFBW */
+ 0x0000000c, /* EMC_QUSE_EXTRA */
+ 0x00000004, /* EMC_FBIO_CFG6 */
+ 0x00000000, /* EMC_ODT_WRITE */
+ 0x00000000, /* EMC_ODT_READ */
+ 0x00005088, /* EMC_FBIO_CFG5 */
+ 0xf0070191, /* EMC_CFG_DIG_DLL */
+ 0x00008000, /* EMC_CFG_DIG_DLL_PERIOD */
+ 0x0000c008, /* 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 */
+ 0x007f800c, /* EMC_DLL_XFORM_DQ0 */
+ 0x007f800c, /* EMC_DLL_XFORM_DQ1 */
+ 0x007f800c, /* EMC_DLL_XFORM_DQ2 */
+ 0x007f800c, /* EMC_DLL_XFORM_DQ3 */
+ 0x000002a0, /* EMC_XM2CMDPADCTRL */
+ 0x0600013d, /* EMC_XM2DQSPADCTRL2 */
+ 0x22220000, /* EMC_XM2DQPADCTRL2 */
+ 0x77fff884, /* EMC_XM2CLKPADCTRL */
+ 0x01f1f501, /* 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 */
+ 0x00f0000c, /* EMC_MRS_WAIT_CNT */
+ 0xa0f10000, /* EMC_AUTO_CAL_CONFIG */
+ 0x00000000, /* EMC_CTT */
+ 0x00000000, /* EMC_CTT_DURATION */
+ 0x8000308c, /* EMC_DYN_SELF_REF_CONTROL */
+ 0x0000000c, /* MC_EMEM_ARB_CFG */
+ 0x80000090, /* MC_EMEM_ARB_OUTSTANDING_REQ */
+ 0x00000004, /* MC_EMEM_ARB_TIMING_RCD */
+ 0x00000005, /* MC_EMEM_ARB_TIMING_RP */
+ 0x00000013, /* MC_EMEM_ARB_TIMING_RC */
+ 0x0000000c, /* MC_EMEM_ARB_TIMING_RAS */
+ 0x0000000b, /* MC_EMEM_ARB_TIMING_FAW */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_RRD */
+ 0x00000003, /* MC_EMEM_ARB_TIMING_RAP2PRE */
+ 0x0000000c, /* 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 */
+ 0x00160d13, /* MC_EMEM_ARB_DA_COVERS */
+ 0x712c2414, /* MC_EMEM_ARB_MISC0 */
+ 0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */
+ 0xf8000000, /* EMC_FBIO_SPARE */
+ 0xff00ff49, /* EMC_CFG_RSV */
+ },
+ 0x00000040, /* EMC_ZCAL_WAIT_CNT after clock change */
+ 0x001fffff, /* EMC_AUTO_CAL_INTERVAL */
+ 0x00000001, /* EMC_CFG.PERIODIC_QRST */
+ 0x80000d71, /* Mode Register 0 */
+ 0x80100002, /* Mode Register 1 */
+ 0x80200018, /* Mode Register 2 */
+ 0x00000000, /* EMC_CFG.DYN_SELF_REF */
+ },
};
static const struct tegra_emc_table cardhu_emc_tables_k4b4g0846b_hyk0[] = {
@@ -3625,6 +3985,126 @@ static const struct tegra_emc_table cardhu_emc_tables_k4b4g0846b_hyk0[] = {
static const struct tegra_emc_table cardhu_emc_tables_k4p8g304eb[] = {
{
0x32, /* Rev 3.2 */
+ 12750, /* SDRAM frequency */
+ {
+ 0x00000000, /* EMC_RC */
+ 0x00000001, /* EMC_RFC */
+ 0x00000002, /* EMC_RAS */
+ 0x00000002, /* EMC_RP */
+ 0x00000004, /* EMC_R2W */
+ 0x00000004, /* EMC_W2R */
+ 0x00000001, /* EMC_R2P */
+ 0x00000005, /* EMC_W2P */
+ 0x00000002, /* EMC_RD_RCD */
+ 0x00000002, /* EMC_WR_RCD */
+ 0x00000001, /* EMC_RRD */
+ 0x00000001, /* EMC_REXT */
+ 0x00000000, /* EMC_WEXT */
+ 0x00000001, /* EMC_WDV */
+ 0x00000003, /* EMC_QUSE */
+ 0x00000001, /* EMC_QRST */
+ 0x00000009, /* EMC_QSAFE */
+ 0x0000000a, /* EMC_RDV */
+ 0x0000002f, /* EMC_REFRESH */
+ 0x00000000, /* EMC_BURST_REFRESH_NUM */
+ 0x0000000b, /* EMC_PRE_REFRESH_REQ_CNT */
+ 0x00000001, /* EMC_PDEX2WR */
+ 0x00000001, /* EMC_PDEX2RD */
+ 0x00000002, /* EMC_PCHG2PDEN */
+ 0x00000000, /* EMC_ACT2PDEN */
+ 0x00000001, /* EMC_AR2PDEN */
+ 0x00000007, /* EMC_RW2PDEN */
+ 0x00000002, /* EMC_TXSR */
+ 0x00000002, /* EMC_TXSRDLL */
+ 0x00000003, /* EMC_TCKE */
+ 0x00000008, /* EMC_TFAW */
+ 0x00000004, /* EMC_TRPAB */
+ 0x00000004, /* EMC_TCLKSTABLE */
+ 0x00000002, /* EMC_TCLKSTOP */
+ 0x00000036, /* EMC_TREFBW */
+ 0x00000004, /* EMC_QUSE_EXTRA */
+ 0x00000004, /* EMC_FBIO_CFG6 */
+ 0x00000000, /* EMC_ODT_WRITE */
+ 0x00000000, /* EMC_ODT_READ */
+ 0x00004282, /* 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 */
+ 0x00100220, /* EMC_XM2CMDPADCTRL */
+ 0x0800201c, /* EMC_XM2DQSPADCTRL2 */
+ 0x00000000, /* EMC_XM2DQPADCTRL2 */
+ 0x77ffc004, /* EMC_XM2CLKPADCTRL */
+ 0x01f1f008, /* EMC_XM2COMPPADCTRL */
+ 0x00000000, /* EMC_XM2VTTGENPADCTRL */
+ 0x00000007, /* EMC_XM2VTTGENPADCTRL2 */
+ 0x08000068, /* EMC_XM2QUSEPADCTRL */
+ 0x08000000, /* EMC_XM2DQSPADCTRL3 */
+ 0x00000802, /* EMC_CTT_TERM_CTRL */
+ 0x00064000, /* EMC_ZCAL_INTERVAL */
+ 0x00000009, /* EMC_ZCAL_WAIT_CNT */
+ 0x00090009, /* EMC_MRS_WAIT_CNT */
+ 0xa0f10000, /* EMC_AUTO_CAL_CONFIG */
+ 0x00000000, /* EMC_CTT */
+ 0x00000000, /* EMC_CTT_DURATION */
+ 0x80000164, /* EMC_DYN_SELF_REF_CONTROL */
+ 0x00020001, /* 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 */
+ 0x00000003, /* MC_EMEM_ARB_TIMING_FAW */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_RRD */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_RAP2PRE */
+ 0x00000004, /* MC_EMEM_ARB_TIMING_WAP2PRE */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_R2R */
+ 0x00000000, /* MC_EMEM_ARB_TIMING_W2W */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_R2W */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_W2R */
+ 0x02020001, /* MC_EMEM_ARB_DA_TURNS */
+ 0x00060402, /* MC_EMEM_ARB_DA_COVERS */
+ 0x77230303, /* MC_EMEM_ARB_MISC0 */
+ 0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */
+ 0xd0000000, /* EMC_FBIO_SPARE */
+ 0xff00ff00, /* EMC_CFG_RSV */
+ },
+ 0x00000009, /* EMC_ZCAL_WAIT_CNT after clock change */
+ 0x001fffff, /* EMC_AUTO_CAL_INTERVAL */
+ 0x00000001, /* EMC_CFG.PERIODIC_QRST */
+ 0x00000000, /* Mode Register 0 */
+ 0x00010022, /* Mode Register 1 */
+ 0x00020001, /* Mode Register 2 */
+ 0x00000001, /* EMC_CFG.DYN_SELF_REF */
+ },
+ {
+ 0x32, /* Rev 3.2 */
25500, /* SDRAM frequency */
{
0x00000001, /* EMC_RC */
@@ -4105,6 +4585,246 @@ static const struct tegra_emc_table cardhu_emc_tables_k4p8g304eb[] = {
},
{
0x32, /* Rev 3.2 */
+ 266500, /* SDRAM frequency */
+ {
+ 0x0000000f, /* EMC_RC */
+ 0x00000022, /* EMC_RFC */
+ 0x0000000b, /* EMC_RAS */
+ 0x00000004, /* EMC_RP */
+ 0x00000005, /* EMC_R2W */
+ 0x00000005, /* EMC_W2R */
+ 0x00000001, /* EMC_R2P */
+ 0x00000007, /* EMC_W2P */
+ 0x00000004, /* EMC_RD_RCD */
+ 0x00000004, /* EMC_WR_RCD */
+ 0x00000002, /* EMC_RRD */
+ 0x00000002, /* EMC_REXT */
+ 0x00000000, /* EMC_WEXT */
+ 0x00000002, /* EMC_WDV */
+ 0x00000005, /* EMC_QUSE */
+ 0x00000002, /* EMC_QRST */
+ 0x0000000c, /* EMC_QSAFE */
+ 0x0000000b, /* EMC_RDV */
+ 0x000003ef, /* EMC_REFRESH */
+ 0x00000000, /* EMC_BURST_REFRESH_NUM */
+ 0x000000fb, /* EMC_PRE_REFRESH_REQ_CNT */
+ 0x00000001, /* EMC_PDEX2WR */
+ 0x00000001, /* EMC_PDEX2RD */
+ 0x00000004, /* EMC_PCHG2PDEN */
+ 0x00000000, /* EMC_ACT2PDEN */
+ 0x00000001, /* EMC_AR2PDEN */
+ 0x00000009, /* EMC_RW2PDEN */
+ 0x00000026, /* EMC_TXSR */
+ 0x00000026, /* EMC_TXSRDLL */
+ 0x00000004, /* EMC_TCKE */
+ 0x0000000e, /* EMC_TFAW */
+ 0x00000006, /* EMC_TRPAB */
+ 0x00000001, /* EMC_TCLKSTABLE */
+ 0x00000002, /* EMC_TCLKSTOP */
+ 0x00000455, /* EMC_TREFBW */
+ 0x00000000, /* EMC_QUSE_EXTRA */
+ 0x00000004, /* EMC_FBIO_CFG6 */
+ 0x00000000, /* EMC_ODT_WRITE */
+ 0x00000000, /* EMC_ODT_READ */
+ 0x00006282, /* EMC_FBIO_CFG5 */
+ 0x003200a4, /* EMC_CFG_DIG_DLL */
+ 0x00008000, /* EMC_CFG_DIG_DLL_PERIOD */
+ 0x00060000, /* EMC_DLL_XFORM_DQS0 */
+ 0x00060000, /* EMC_DLL_XFORM_DQS1 */
+ 0x00060000, /* EMC_DLL_XFORM_DQS2 */
+ 0x00060000, /* EMC_DLL_XFORM_DQS3 */
+ 0x00060000, /* EMC_DLL_XFORM_DQS4 */
+ 0x00060000, /* EMC_DLL_XFORM_DQS5 */
+ 0x00060000, /* EMC_DLL_XFORM_DQS6 */
+ 0x00060000, /* 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 */
+ 0x00068000, /* EMC_DLL_XFORM_DQ0 */
+ 0x00068000, /* EMC_DLL_XFORM_DQ1 */
+ 0x00068000, /* EMC_DLL_XFORM_DQ2 */
+ 0x00068000, /* EMC_DLL_XFORM_DQ3 */
+ 0x000a0220, /* EMC_XM2CMDPADCTRL */
+ 0x0800003d, /* EMC_XM2DQSPADCTRL2 */
+ 0x00000000, /* EMC_XM2DQPADCTRL2 */
+ 0x77ffc004, /* EMC_XM2CLKPADCTRL */
+ 0x01f1f008, /* EMC_XM2COMPPADCTRL */
+ 0x00000000, /* EMC_XM2VTTGENPADCTRL */
+ 0x00000007, /* EMC_XM2VTTGENPADCTRL2 */
+ 0x08000068, /* EMC_XM2QUSEPADCTRL */
+ 0x08000000, /* EMC_XM2DQSPADCTRL3 */
+ 0x00000802, /* EMC_CTT_TERM_CTRL */
+ 0x00064000, /* EMC_ZCAL_INTERVAL */
+ 0x00000060, /* EMC_ZCAL_WAIT_CNT */
+ 0x000a000a, /* EMC_MRS_WAIT_CNT */
+ 0xa0f10000, /* EMC_AUTO_CAL_CONFIG */
+ 0x00000000, /* EMC_CTT */
+ 0x00000000, /* EMC_CTT_DURATION */
+ 0x800008ee, /* EMC_DYN_SELF_REF_CONTROL */
+ 0x00000004, /* MC_EMEM_ARB_CFG */
+ 0x80000030, /* 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 */
+ 0x00000006, /* MC_EMEM_ARB_TIMING_FAW */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_RRD */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_RAP2PRE */
+ 0x00000005, /* MC_EMEM_ARB_TIMING_WAP2PRE */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_R2R */
+ 0x00000000, /* MC_EMEM_ARB_TIMING_W2W */
+ 0x00000003, /* MC_EMEM_ARB_TIMING_R2W */
+ 0x00000003, /* MC_EMEM_ARB_TIMING_W2R */
+ 0x03030001, /* MC_EMEM_ARB_DA_TURNS */
+ 0x00090608, /* MC_EMEM_ARB_DA_COVERS */
+ 0x70040c09, /* MC_EMEM_ARB_MISC0 */
+ 0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */
+ 0xe0000000, /* EMC_FBIO_SPARE */
+ 0xff00ff00, /* EMC_CFG_RSV */
+ },
+ 0x00000018, /* EMC_ZCAL_WAIT_CNT after clock change */
+ 0x001fffff, /* EMC_AUTO_CAL_INTERVAL */
+ 0x00000001, /* EMC_CFG.PERIODIC_QRST */
+ 0x00000000, /* Mode Register 0 */
+ 0x00010042, /* Mode Register 1 */
+ 0x00020002, /* Mode Register 2 */
+ 0x00000000, /* EMC_CFG.DYN_SELF_REF */
+ },
+ {
+ 0x32, /* Rev 3.2 */
+ 437000, /* SDRAM frequency */
+ {
+ 0x0000001a, /* EMC_RC */
+ 0x00000038, /* EMC_RFC */
+ 0x00000012, /* EMC_RAS */
+ 0x00000007, /* EMC_RP */
+ 0x00000007, /* EMC_R2W */
+ 0x00000009, /* EMC_W2R */
+ 0x00000003, /* EMC_R2P */
+ 0x0000000c, /* EMC_W2P */
+ 0x00000007, /* EMC_RD_RCD */
+ 0x00000007, /* EMC_WR_RCD */
+ 0x00000004, /* EMC_RRD */
+ 0x00000002, /* EMC_REXT */
+ 0x00000000, /* EMC_WEXT */
+ 0x00000004, /* EMC_WDV */
+ 0x00000008, /* EMC_QUSE */
+ 0x00000005, /* EMC_QRST */
+ 0x0000000d, /* EMC_QSAFE */
+ 0x0000000f, /* EMC_RDV */
+ 0x00000674, /* EMC_REFRESH */
+ 0x00000000, /* EMC_BURST_REFRESH_NUM */
+ 0x0000019d, /* EMC_PRE_REFRESH_REQ_CNT */
+ 0x00000003, /* EMC_PDEX2WR */
+ 0x00000003, /* EMC_PDEX2RD */
+ 0x00000007, /* EMC_PCHG2PDEN */
+ 0x00000000, /* EMC_ACT2PDEN */
+ 0x00000001, /* EMC_AR2PDEN */
+ 0x0000000d, /* EMC_RW2PDEN */
+ 0x0000003e, /* EMC_TXSR */
+ 0x0000003e, /* EMC_TXSRDLL */
+ 0x00000007, /* EMC_TCKE */
+ 0x00000016, /* EMC_TFAW */
+ 0x0000000a, /* EMC_TRPAB */
+ 0x00000004, /* EMC_TCLKSTABLE */
+ 0x00000002, /* EMC_TCLKSTOP */
+ 0x0000071a, /* EMC_TREFBW */
+ 0x00000000, /* EMC_QUSE_EXTRA */
+ 0x00000004, /* EMC_FBIO_CFG6 */
+ 0x00000000, /* EMC_ODT_WRITE */
+ 0x00000000, /* EMC_ODT_READ */
+ 0x00006282, /* EMC_FBIO_CFG5 */
+ 0x00190084, /* EMC_CFG_DIG_DLL */
+ 0x00008000, /* EMC_CFG_DIG_DLL_PERIOD */
+ 0x00014000, /* EMC_DLL_XFORM_DQS0 */
+ 0x00014000, /* EMC_DLL_XFORM_DQS1 */
+ 0x00014000, /* EMC_DLL_XFORM_DQS2 */
+ 0x00014000, /* EMC_DLL_XFORM_DQS3 */
+ 0x00014000, /* EMC_DLL_XFORM_DQS4 */
+ 0x00014000, /* EMC_DLL_XFORM_DQS5 */
+ 0x00014000, /* EMC_DLL_XFORM_DQS6 */
+ 0x00014000, /* 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 */
+ 0x00038000, /* EMC_DLL_XFORM_DQ0 */
+ 0x00038000, /* EMC_DLL_XFORM_DQ1 */
+ 0x00038000, /* EMC_DLL_XFORM_DQ2 */
+ 0x00038000, /* EMC_DLL_XFORM_DQ3 */
+ 0x00080220, /* EMC_XM2CMDPADCTRL */
+ 0x0800003d, /* EMC_XM2DQSPADCTRL2 */
+ 0x00000000, /* EMC_XM2DQPADCTRL2 */
+ 0x77ffe004, /* EMC_XM2CLKPADCTRL */
+ 0x01f1f408, /* EMC_XM2COMPPADCTRL */
+ 0x00000000, /* EMC_XM2VTTGENPADCTRL */
+ 0x00000007, /* EMC_XM2VTTGENPADCTRL2 */
+ 0x08000068, /* EMC_XM2QUSEPADCTRL */
+ 0x08000000, /* EMC_XM2DQSPADCTRL3 */
+ 0x00000802, /* EMC_CTT_TERM_CTRL */
+ 0x00064000, /* EMC_ZCAL_INTERVAL */
+ 0x0000009e, /* EMC_ZCAL_WAIT_CNT */
+ 0x000d000d, /* EMC_MRS_WAIT_CNT */
+ 0xa0f10202, /* EMC_AUTO_CAL_CONFIG */
+ 0x00000000, /* EMC_CTT */
+ 0x00000000, /* EMC_CTT_DURATION */
+ 0x80000dff, /* EMC_DYN_SELF_REF_CONTROL */
+ 0x00000006, /* MC_EMEM_ARB_CFG */
+ 0xc000004f, /* MC_EMEM_ARB_OUTSTANDING_REQ */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_RCD */
+ 0x00000003, /* MC_EMEM_ARB_TIMING_RP */
+ 0x0000000d, /* MC_EMEM_ARB_TIMING_RC */
+ 0x00000008, /* MC_EMEM_ARB_TIMING_RAS */
+ 0x0000000a, /* MC_EMEM_ARB_TIMING_FAW */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_RRD */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_RAP2PRE */
+ 0x00000007, /* MC_EMEM_ARB_TIMING_WAP2PRE */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_R2R */
+ 0x00000000, /* MC_EMEM_ARB_TIMING_W2W */
+ 0x00000004, /* MC_EMEM_ARB_TIMING_R2W */
+ 0x00000005, /* MC_EMEM_ARB_TIMING_W2R */
+ 0x05040001, /* MC_EMEM_ARB_DA_TURNS */
+ 0x000e090d, /* MC_EMEM_ARB_DA_COVERS */
+ 0x7027140e, /* MC_EMEM_ARB_MISC0 */
+ 0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */
+ 0xe0000000, /* EMC_FBIO_SPARE */
+ 0xff00ff88, /* EMC_CFG_RSV */
+ },
+ 0x00000028, /* EMC_ZCAL_WAIT_CNT after clock change */
+ 0x001fffff, /* EMC_AUTO_CAL_INTERVAL */
+ 0x00000001, /* EMC_CFG.PERIODIC_QRST */
+ 0x00000000, /* Mode Register 0 */
+ 0x000100a2, /* Mode Register 1 */
+ 0x00020005, /* Mode Register 2 */
+ 0x00000000, /* EMC_CFG.DYN_SELF_REF */
+ },
+ {
+ 0x32, /* Rev 3.2 */
533000, /* SDRAM frequency */
{
0x0000001f, /* EMC_RC */
diff --git a/arch/arm/mach-tegra/board-cardhu-panel.c b/arch/arm/mach-tegra/board-cardhu-panel.c
index aaec711677fb..6fa33f919dad 100644
--- a/arch/arm/mach-tegra/board-cardhu-panel.c
+++ b/arch/arm/mach-tegra/board-cardhu-panel.c
@@ -30,7 +30,7 @@
#include <linux/pwm_backlight.h>
#include <asm/atomic.h>
#include <linux/nvhost.h>
-#include <mach/nvmap.h>
+#include <linux/nvmap.h>
#include <mach/irqs.h>
#include <mach/iomap.h>
#include <mach/dc.h>
@@ -41,10 +41,11 @@
#include "board-cardhu.h"
#include "devices.h"
#include "gpio-names.h"
+#include "tegra3_host1x_devices.h"
+
+#define DC_CTRL_MODE (TEGRA_DC_OUT_ONE_SHOT_MODE | \
+ TEGRA_DC_OUT_ONE_SHOT_LP_MODE)
-/* Select panel to be used. */
-#define DSI_PANEL_219 1
-#define DSI_PANEL_218 0
#define AVDD_LCD PMU_TCA6416_GPIO_PORT17
#define DSI_PANEL_RESET 1
@@ -58,7 +59,14 @@
#define pm313_MODE0 TEGRA_GPIO_PZ4
#define pm313_MODE1 TEGRA_GPIO_PW1
#define pm313_BPP TEGRA_GPIO_PN6 /* 0:24bpp, 1:18bpp */
-#define pm313_lvds_shutdown TEGRA_GPIO_PH1
+#define pm313_lvds_shutdown TEGRA_GPIO_PL2
+
+/* E1506 display board pins */
+#define e1506_lcd_te TEGRA_GPIO_PJ1
+#define e1506_dsi_vddio TEGRA_GPIO_PH1
+#define e1506_dsia_bl_pwm TEGRA_GPIO_PH0
+#define e1506_panel_enb TEGRA_GPIO_PW1
+#define e1506_bl_enb TEGRA_GPIO_PH2
/* E1247 reworked for pm269 pins */
#define e1247_pm269_lvds_shutdown TEGRA_GPIO_PN6
@@ -71,12 +79,11 @@
#define cardhu_bl_pwm TEGRA_GPIO_PH0
#define cardhu_hdmi_hpd TEGRA_GPIO_PN7
-#if defined(DSI_PANEL_219) || defined(DSI_PANEL_218)
+/* common dsi panel pins */
#define cardhu_dsia_bl_enb TEGRA_GPIO_PW1
#define cardhu_dsib_bl_enb TEGRA_GPIO_PW0
-#define cardhu_dsi_218_panel_reset TEGRA_GPIO_PD2
-#define cardhu_dsi_219_panel_reset TEGRA_GPIO_PW0
-#endif
+#define cardhu_dsi_pnl_reset TEGRA_GPIO_PD2
+#define cardhu_dsi_219_pnl_reset TEGRA_GPIO_PW0
#ifdef CONFIG_TEGRA_DC
static struct regulator *cardhu_hdmi_reg = NULL;
@@ -86,13 +93,10 @@ static struct regulator *cardhu_hdmi_vddio = NULL;
static atomic_t sd_brightness = ATOMIC_INIT(255);
-#ifdef CONFIG_TEGRA_CARDHU_DSI
static struct regulator *cardhu_dsi_reg = NULL;
-#else
static struct regulator *cardhu_lvds_reg = NULL;
static struct regulator *cardhu_lvds_vdd_bl = NULL;
static struct regulator *cardhu_lvds_vdd_panel = NULL;
-#endif
static struct board_info board_info;
static struct board_info display_board_info;
@@ -132,127 +136,112 @@ static tegra_dc_bl_output cardhu_bl_output_measured = {
248, 249, 250, 251, 252, 253, 254, 255
};
-static p_tegra_dc_bl_output bl_output;
+static p_tegra_dc_bl_output bl_output = cardhu_bl_output_measured;
-static int cardhu_backlight_init(struct device *dev)
+static bool is_panel_218;
+static bool is_panel_219;
+static bool is_panel_1506;
+
+static bool is_dsi_panel(void)
{
- int ret;
+ return is_panel_218 || is_panel_219 || is_panel_1506;
+}
- bl_output = cardhu_bl_output_measured;
+static int cardhu_backlight_init(struct device *dev)
+{
+ int ret = 0;
if (WARN_ON(ARRAY_SIZE(cardhu_bl_output_measured) != 256))
pr_err("bl_output array does not have 256 elements\n");
-#ifndef CONFIG_TEGRA_CARDHU_DSI
- tegra_gpio_disable(cardhu_bl_pwm);
-
- ret = gpio_request(cardhu_bl_enb, "backlight_enb");
- if (ret < 0)
- return ret;
-
- ret = gpio_direction_output(cardhu_bl_enb, 1);
- if (ret < 0)
- gpio_free(cardhu_bl_enb);
- else
- tegra_gpio_enable(cardhu_bl_enb);
-
- return ret;
-#endif
-
-#if DSI_PANEL_218
- /* Enable back light for DSIa panel */
- ret = gpio_request(cardhu_dsia_bl_enb, "dsia_bl_enable");
- if (ret < 0)
- return ret;
+ if (!is_dsi_panel()) {
+ ret = gpio_request(cardhu_bl_enb, "backlight_enb");
+ if (ret < 0)
+ return ret;
- ret = gpio_direction_output(cardhu_dsia_bl_enb, 1);
- if (ret < 0)
- gpio_free(cardhu_dsia_bl_enb);
- else
- tegra_gpio_enable(cardhu_dsia_bl_enb);
+ ret = gpio_direction_output(cardhu_bl_enb, 1);
+ if (ret < 0)
+ gpio_free(cardhu_bl_enb);
+ } else if (is_panel_218) {
+ /* Enable back light for DSIa panel */
+ ret = gpio_request(cardhu_dsia_bl_enb, "dsia_bl_enable");
+ if (ret < 0)
+ return ret;
- /* Enable back light for DSIb panel */
- ret = gpio_request(cardhu_dsib_bl_enb, "dsib_bl_enable");
- if (ret < 0)
- return ret;
+ ret = gpio_direction_output(cardhu_dsia_bl_enb, 1);
+ if (ret < 0)
+ gpio_free(cardhu_dsia_bl_enb);
- ret = gpio_direction_output(cardhu_dsib_bl_enb, 1);
- if (ret < 0)
- gpio_free(cardhu_dsib_bl_enb);
- else
- tegra_gpio_enable(cardhu_dsib_bl_enb);
-#endif
+ /* Enable back light for DSIb panel */
+ ret = gpio_request(cardhu_dsib_bl_enb, "dsib_bl_enable");
+ if (ret < 0)
+ return ret;
-#if DSI_PANEL_219
- /* Enable back light for DSIa panel */
- ret = gpio_request(cardhu_dsia_bl_enb, "dsia_bl_enable");
- if (ret < 0)
- return ret;
+ ret = gpio_direction_output(cardhu_dsib_bl_enb, 1);
+ if (ret < 0)
+ gpio_free(cardhu_dsib_bl_enb);
+ } else if (is_panel_219) {
+ /* Enable back light for DSIa panel */
+ ret = gpio_request(cardhu_dsia_bl_enb, "dsia_bl_enable");
+ if (ret < 0)
+ return ret;
- ret = gpio_direction_output(cardhu_dsia_bl_enb, 1);
- if (ret < 0)
- gpio_free(cardhu_dsia_bl_enb);
- else
- tegra_gpio_enable(cardhu_dsia_bl_enb);
-#endif
+ ret = gpio_direction_output(cardhu_dsia_bl_enb, 1);
+ if (ret < 0)
+ gpio_free(cardhu_dsia_bl_enb);
+ }
return ret;
};
static void cardhu_backlight_exit(struct device *dev)
{
-#ifndef CONFIG_TEGRA_CARDHU_DSI
- /* int ret; */
- /*ret = gpio_request(cardhu_bl_enb, "backlight_enb");*/
- gpio_set_value(cardhu_bl_enb, 0);
- gpio_free(cardhu_bl_enb);
- tegra_gpio_disable(cardhu_bl_enb);
- return;
-#endif
-
-#if DSI_PANEL_218
- /* Disable back light for DSIa panel */
- gpio_set_value(cardhu_dsia_bl_enb, 0);
- gpio_free(cardhu_dsia_bl_enb);
- tegra_gpio_disable(cardhu_dsia_bl_enb);
-
- /* Disable back light for DSIb panel */
- gpio_set_value(cardhu_dsib_bl_enb, 0);
- gpio_free(cardhu_dsib_bl_enb);
- tegra_gpio_disable(cardhu_dsib_bl_enb);
+ if (!is_dsi_panel()) {
+ /* int ret; */
+ /*ret = gpio_request(cardhu_bl_enb, "backlight_enb");*/
+ gpio_set_value(cardhu_bl_enb, 0);
+ gpio_free(cardhu_bl_enb);
+ } else if (is_panel_218) {
+ /* Disable back light for DSIa panel */
+ gpio_set_value(cardhu_dsia_bl_enb, 0);
+ gpio_free(cardhu_dsia_bl_enb);
- gpio_set_value(cardhu_lvds_shutdown, 1);
- mdelay(20);
-#endif
+ /* Disable back light for DSIb panel */
+ gpio_set_value(cardhu_dsib_bl_enb, 0);
+ gpio_free(cardhu_dsib_bl_enb);
-#if DSI_PANEL_219
- /* Disable back light for DSIa panel */
- gpio_set_value(cardhu_dsia_bl_enb, 0);
- gpio_free(cardhu_dsia_bl_enb);
- tegra_gpio_disable(cardhu_dsia_bl_enb);
+ gpio_set_value(cardhu_lvds_shutdown, 1);
+ mdelay(20);
+ } else if (is_panel_219) {
+ /* Disable back light for DSIa panel */
+ gpio_set_value(cardhu_dsia_bl_enb, 0);
+ gpio_free(cardhu_dsia_bl_enb);
- gpio_set_value(cardhu_lvds_shutdown, 1);
- mdelay(20);
-#endif
+ gpio_set_value(cardhu_lvds_shutdown, 1);
+ mdelay(20);
+ }
}
static int cardhu_backlight_notify(struct device *unused, int brightness)
{
int cur_sd_brightness = atomic_read(&sd_brightness);
-#ifndef CONFIG_TEGRA_CARDHU_DSI
- /* Set the backlight GPIO pin mode to 'backlight_enable' */
- gpio_set_value(cardhu_bl_enb, !!brightness);
-#elif DSI_PANEL_218
- /* DSIa */
- gpio_set_value(cardhu_dsia_bl_enb, !!brightness);
-
- /* DSIb */
- gpio_set_value(cardhu_dsib_bl_enb, !!brightness);
-#elif DSI_PANEL_219
- /* DSIa */
- gpio_set_value(cardhu_dsia_bl_enb, !!brightness);
-#endif
+ if (!is_dsi_panel()) {
+ /* Set the backlight GPIO pin mode to 'backlight_enable' */
+ gpio_set_value(cardhu_bl_enb, !!brightness);
+ } else if (is_panel_218) {
+ /* DSIa */
+ gpio_set_value(cardhu_dsia_bl_enb, !!brightness);
+
+ /* DSIb */
+ gpio_set_value(cardhu_dsib_bl_enb, !!brightness);
+ } else if (is_panel_219) {
+ /* DSIa */
+ gpio_set_value(cardhu_dsia_bl_enb, !!brightness);
+ } else if (is_panel_1506) {
+ /* DSIa */
+ gpio_set_value(e1506_bl_enb, !!brightness);
+ }
/* SD brightness is a percentage, 8-bit value. */
brightness = (brightness * cur_sd_brightness) / 255;
@@ -261,13 +250,7 @@ static int cardhu_backlight_notify(struct device *unused, int brightness)
if (brightness > 255) {
pr_info("Error: Brightness > 255!\n");
} else {
- /* This value depends on the panel.
- Current 19X12 panel with PM313 gets
- full brightness when the output is 0. */
- if (display_board_info.board_id == BOARD_DISPLAY_PM313)
- brightness = 255 - bl_output[brightness];
- else
- brightness = bl_output[brightness];
+ brightness = bl_output[brightness];
}
return brightness;
@@ -295,7 +278,6 @@ static struct platform_device cardhu_backlight_device = {
},
};
-#ifndef CONFIG_TEGRA_CARDHU_DSI
static int cardhu_panel_enable(void)
{
if (cardhu_lvds_reg == NULL) {
@@ -377,7 +359,6 @@ static int cardhu_panel_disable(void)
}
return 0;
}
-#endif
#ifdef CONFIG_TEGRA_DC
static int cardhu_hdmi_vddio_enable(void)
@@ -522,7 +503,6 @@ static struct resource cardhu_disp2_resources[] = {
};
#endif
-#ifndef CONFIG_TEGRA_CARDHU_DSI
static struct tegra_dc_mode panel_19X12_modes[] = {
{
.pclk = 154000000,
@@ -600,7 +580,6 @@ static struct tegra_dc_mode cardhu_panel_modes_55hz[] = {
.v_front_porch = 25,
},
};
-#endif
static struct tegra_dc_sd_settings cardhu_sd_settings = {
.enable = 1, /* enabled by default. */
@@ -695,7 +674,6 @@ static struct tegra_dc_sd_settings cardhu_sd_settings = {
};
#ifdef CONFIG_TEGRA_DC
-#ifndef CONFIG_TEGRA_CARDHU_DSI
static struct tegra_fb_data cardhu_fb_data = {
.win = 0,
.xres = 1366,
@@ -703,7 +681,6 @@ static struct tegra_fb_data cardhu_fb_data = {
.bits_per_pixel = 32,
.flags = TEGRA_FB_FLIP_ON_PROBE,
};
-#endif
static struct tegra_fb_data cardhu_hdmi_fb_data = {
.win = 0,
@@ -741,7 +718,6 @@ static struct tegra_dc_platform_data cardhu_disp2_pdata = {
};
#endif
-#ifdef CONFIG_TEGRA_CARDHU_DSI
static int cardhu_dsi_panel_enable(void)
{
int ret;
@@ -754,86 +730,130 @@ static int cardhu_dsi_panel_enable(void)
return PTR_ERR(cardhu_dsi_reg);
}
}
+
regulator_enable(cardhu_dsi_reg);
- ret = gpio_request(AVDD_LCD, "avdd_lcd");
- if (ret < 0)
- gpio_free(AVDD_LCD);
- ret = gpio_direction_output(AVDD_LCD, 1);
- if (ret < 0)
- gpio_free(AVDD_LCD);
- else
- tegra_gpio_enable(AVDD_LCD);
+ if (!is_panel_1506) {
+ ret = gpio_request(AVDD_LCD, "avdd_lcd");
+ if (ret < 0)
+ gpio_free(AVDD_LCD);
+ ret = gpio_direction_output(AVDD_LCD, 1);
+ if (ret < 0)
+ gpio_free(AVDD_LCD);
+ }
-#if DSI_PANEL_219
+ if (is_panel_219) {
+ ret = gpio_request(cardhu_bl_pwm, "bl_pwm");
+ if (ret < 0)
+ return ret;
+ ret = gpio_direction_output(cardhu_bl_pwm, 0);
+ if (ret < 0) {
+ gpio_free(cardhu_bl_pwm);
+ return ret;
+ }
- ret = gpio_request(cardhu_bl_pwm, "bl_pwm");
- if (ret < 0)
- return ret;
- ret = gpio_direction_output(cardhu_bl_pwm, 0);
- if (ret < 0) {
- gpio_free(cardhu_bl_pwm);
- return ret;
- } else
- tegra_gpio_enable(cardhu_bl_pwm);
+ ret = gpio_request(cardhu_bl_enb, "bl_enb");
+ if (ret < 0)
+ return ret;
+ ret = gpio_direction_output(cardhu_bl_enb, 0);
+ if (ret < 0) {
+ gpio_free(cardhu_bl_enb);
+ return ret;
+ }
- ret = gpio_request(cardhu_bl_enb, "bl_enb");
- if (ret < 0)
- return ret;
- ret = gpio_direction_output(cardhu_bl_enb, 0);
- if (ret < 0) {
- gpio_free(cardhu_bl_enb);
- return ret;
- } else
- tegra_gpio_enable(cardhu_bl_enb);
-
- gpio_set_value(cardhu_lvds_shutdown, 1);
- mdelay(20);
- gpio_set_value(cardhu_bl_pwm, 1);
- mdelay(10);
- gpio_set_value(cardhu_bl_enb, 1);
- mdelay(15);
-#endif
+ gpio_set_value(cardhu_lvds_shutdown, 1);
+ mdelay(20);
+ gpio_set_value(cardhu_bl_pwm, 1);
+ mdelay(10);
+ gpio_set_value(cardhu_bl_enb, 1);
+ mdelay(15);
+ } else if (is_panel_1506) {
+ ret = gpio_request(e1506_dsi_vddio, "e1506_dsi_vddio");
+ if (ret < 0)
+ return ret;
+ ret = gpio_direction_output(e1506_dsi_vddio, 0);
+ if (ret < 0) {
+ gpio_free(e1506_dsi_vddio);
+ return ret;
+ }
-#if DSI_PANEL_RESET
-#if DSI_PANEL_218
- ret = gpio_request(cardhu_dsi_218_panel_reset, "dsi_panel_reset");
- if (ret < 0) {
- return ret;
+ ret = gpio_request(e1506_panel_enb, "e1506_panel_enb");
+ if (ret < 0)
+ return ret;
+ ret = gpio_direction_output(e1506_panel_enb, 0);
+ if (ret < 0) {
+ gpio_free(e1506_panel_enb);
+ return ret;
+ }
+
+ ret = gpio_request(e1506_bl_enb, "e1506_bl_enb");
+ if (ret < 0)
+ return ret;
+ ret = gpio_direction_output(e1506_bl_enb, 0);
+ if (ret < 0) {
+ gpio_free(e1506_bl_enb);
+ return ret;
+ }
+
+ gpio_set_value(e1506_dsi_vddio, 1);
+ mdelay(1);
+ gpio_set_value(e1506_panel_enb, 1);
+ mdelay(10);
+ gpio_set_value(e1506_bl_enb, 1);
+ mdelay(15);
}
- ret = gpio_direction_output(cardhu_dsi_218_panel_reset, 0);
- if (ret < 0) {
- gpio_free(cardhu_dsi_218_panel_reset);
- return ret;
- } else
- tegra_gpio_enable(cardhu_dsi_218_panel_reset);
-
- gpio_set_value(cardhu_dsi_218_panel_reset, 1);
- gpio_set_value(cardhu_dsi_218_panel_reset, 0);
- mdelay(2);
- gpio_set_value(cardhu_dsi_218_panel_reset, 1);
- mdelay(2);
-#endif
-#if DSI_PANEL_219
- ret = gpio_request(cardhu_dsi_219_panel_reset, "dsi_panel_reset");
- if (ret < 0)
- return ret;
- ret = gpio_direction_output(cardhu_dsi_219_panel_reset, 0);
- if (ret < 0) {
- gpio_free(cardhu_dsi_219_panel_reset);
- return ret;
- } else
- tegra_gpio_enable(cardhu_dsi_219_panel_reset);
-
- gpio_set_value(cardhu_dsi_219_panel_reset, 0);
- gpio_set_value(cardhu_dsi_219_panel_reset, 1);
- mdelay(10);
- gpio_set_value(cardhu_dsi_219_panel_reset, 0);
- mdelay(10);
- gpio_set_value(cardhu_dsi_219_panel_reset, 1);
- mdelay(15);
-#endif
+#if DSI_PANEL_RESET
+ if (is_panel_218) {
+ ret = gpio_request(cardhu_dsi_pnl_reset, "dsi_panel_reset");
+ if (ret < 0)
+ return ret;
+
+ ret = gpio_direction_output(cardhu_dsi_pnl_reset, 0);
+ if (ret < 0) {
+ gpio_free(cardhu_dsi_pnl_reset);
+ return ret;
+ }
+
+ gpio_set_value(cardhu_dsi_pnl_reset, 1);
+ gpio_set_value(cardhu_dsi_pnl_reset, 0);
+ mdelay(2);
+ gpio_set_value(cardhu_dsi_pnl_reset, 1);
+ mdelay(2);
+ } else if (is_panel_219) {
+ ret = gpio_request(cardhu_dsi_219_pnl_reset, "dsi_panel_reset");
+ if (ret < 0)
+ return ret;
+ ret = gpio_direction_output(cardhu_dsi_219_pnl_reset, 0);
+ if (ret < 0) {
+ gpio_free(cardhu_dsi_219_pnl_reset);
+ return ret;
+ }
+
+ gpio_set_value(cardhu_dsi_219_pnl_reset, 0);
+ gpio_set_value(cardhu_dsi_219_pnl_reset, 1);
+ mdelay(10);
+ gpio_set_value(cardhu_dsi_219_pnl_reset, 0);
+ mdelay(10);
+ gpio_set_value(cardhu_dsi_219_pnl_reset, 1);
+ mdelay(15);
+ } else if (is_panel_1506) {
+ ret = gpio_request(cardhu_dsi_pnl_reset, "dsi_panel_reset");
+ if (ret < 0)
+ return ret;
+ ret = gpio_direction_output(cardhu_dsi_pnl_reset, 0);
+ if (ret < 0) {
+ gpio_free(cardhu_dsi_pnl_reset);
+ return ret;
+ }
+
+ gpio_set_value(cardhu_dsi_pnl_reset, 1);
+ mdelay(1);
+ gpio_set_value(cardhu_dsi_pnl_reset, 0);
+ mdelay(1);
+ gpio_set_value(cardhu_dsi_pnl_reset, 1);
+ mdelay(20);
+ }
#endif
return 0;
@@ -844,24 +864,24 @@ static int cardhu_dsi_panel_disable(void)
int err;
err = 0;
- printk(KERN_INFO "DSI panel disable\n");
-
-#if DSI_PANEL_219
- tegra_gpio_disable(cardhu_dsi_219_panel_reset);
- gpio_free(cardhu_dsi_219_panel_reset);
- tegra_gpio_disable(cardhu_bl_enb);
- gpio_free(cardhu_bl_enb);
- tegra_gpio_disable(cardhu_bl_pwm);
- gpio_free(cardhu_bl_pwm);
- tegra_gpio_disable(cardhu_lvds_shutdown);
- gpio_free(cardhu_lvds_shutdown);
-#endif
-
-#if DSI_PANEL_218
- tegra_gpio_disable(cardhu_dsi_218_panel_reset);
- gpio_free(cardhu_dsi_218_panel_reset);
-#endif
+ if (is_panel_219) {
+ gpio_free(cardhu_dsi_219_pnl_reset);
+ gpio_free(cardhu_bl_enb);
+ gpio_free(cardhu_bl_pwm);
+ gpio_free(cardhu_lvds_shutdown);
+ } 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;
}
@@ -881,10 +901,8 @@ static int cardhu_dsi_panel_postsuspend(void)
cardhu_dsi_reg = NULL;
}
-#if DSI_PANEL_218
- tegra_gpio_disable(AVDD_LCD);
- gpio_free(AVDD_LCD);
-#endif
+ if (is_panel_218)
+ gpio_free(AVDD_LCD);
return err;
}
@@ -892,21 +910,79 @@ static int cardhu_dsi_panel_postsuspend(void)
static struct tegra_dsi_cmd dsi_init_cmd[] = {
DSI_CMD_SHORT(0x05, 0x11, 0x00),
DSI_DLY_MS(150),
+#if (DC_CTRL_MODE & TEGRA_DC_OUT_ONE_SHOT_MODE)
+ DSI_CMD_SHORT(0x15, 0x35, 0x00),
+#endif
DSI_CMD_SHORT(0x05, 0x29, 0x00),
DSI_DLY_MS(20),
};
-static struct tegra_dsi_cmd dsi_suspend_cmd[] = {
+u8 password_array[] = {0xb9, 0xff, 0x83, 0x92};
+
+static struct tegra_dsi_cmd dsi_init_cmd_1506[] = {
+ DSI_CMD_SHORT(0x05, 0x11, 0x00),
+ DSI_DLY_MS(150),
+ DSI_CMD_LONG(0x39, password_array),
+ DSI_DLY_MS(10),
+ DSI_CMD_SHORT(0x15, 0xd4, 0x0c),
+ DSI_DLY_MS(10),
+ DSI_CMD_SHORT(0x15, 0xba, 0x11),
+ DSI_DLY_MS(10),
+#if (DC_CTRL_MODE & TEGRA_DC_OUT_ONE_SHOT_MODE)
+ DSI_CMD_SHORT(0x15, 0x35, 0x00),
+#endif
+ DSI_CMD_SHORT(0x05, 0x29, 0x00),
+ DSI_DLY_MS(20),
+};
+
+static struct tegra_dsi_cmd dsi_early_suspend_cmd[] = {
DSI_CMD_SHORT(0x05, 0x28, 0x00),
DSI_DLY_MS(20),
+#if (DC_CTRL_MODE & TEGRA_DC_OUT_ONE_SHOT_MODE)
+ DSI_CMD_SHORT(0x05, 0x34, 0x00),
+#endif
+};
+
+static struct tegra_dsi_cmd dsi_late_resume_cmd[] = {
+#if (DC_CTRL_MODE & TEGRA_DC_OUT_ONE_SHOT_MODE)
+ DSI_CMD_SHORT(0x15, 0x35, 0x00),
+#endif
+ DSI_CMD_SHORT(0x05, 0x29, 0x00),
+ DSI_DLY_MS(20),
+};
+
+static struct tegra_dsi_cmd dsi_suspend_cmd[] = {
+ DSI_CMD_SHORT(0x05, 0x28, 0x00),
+ DSI_DLY_MS(120),
+#if (DC_CTRL_MODE & TEGRA_DC_OUT_ONE_SHOT_MODE)
+ DSI_CMD_SHORT(0x05, 0x34, 0x00),
+#endif
DSI_CMD_SHORT(0x05, 0x10, 0x00),
DSI_DLY_MS(5),
};
+static struct tegra_dsi_cmd dsi_suspend_cmd_1506[] = {
+ DSI_CMD_SHORT(0x05, 0x28, 0x00),
+ DSI_CMD_SHORT(0x05, 0x10, 0x00),
+ DSI_DLY_MS(120),
+};
+
struct tegra_dsi_out cardhu_dsi = {
.n_data_lanes = 2,
.pixel_format = TEGRA_DSI_PIXEL_FORMAT_24BIT_P,
+
+#if (DC_CTRL_MODE & TEGRA_DC_OUT_ONE_SHOT_MODE)
+ /*
+ * The one-shot frame time must be shorter than the time between TE.
+ * Increasing refresh_rate will result in a decrease in the frame time
+ * for one-shot. rated_refresh_rate is only an approximation of the
+ * TE rate, and is only used to report refresh rate to upper layers.
+ */
+ .refresh_rate = 66,
+ .rated_refresh_rate = 60,
+#else
.refresh_rate = 60,
+#endif
.virtual_channel = TEGRA_DSI_VIRTUAL_CHANNEL_0,
.panel_has_frame_buffer = true,
@@ -918,8 +994,11 @@ struct tegra_dsi_out cardhu_dsi = {
.panel_reset = DSI_PANEL_RESET,
.power_saving_suspend = true,
- .n_init_cmd = ARRAY_SIZE(dsi_init_cmd),
- .dsi_init_cmd = dsi_init_cmd,
+ .n_early_suspend_cmd = ARRAY_SIZE(dsi_early_suspend_cmd),
+ .dsi_early_suspend_cmd = dsi_early_suspend_cmd,
+
+ .n_late_resume_cmd = ARRAY_SIZE(dsi_late_resume_cmd),
+ .dsi_late_resume_cmd = dsi_late_resume_cmd,
.n_suspend_cmd = ARRAY_SIZE(dsi_suspend_cmd),
.dsi_suspend_cmd = dsi_suspend_cmd,
@@ -928,8 +1007,7 @@ struct tegra_dsi_out cardhu_dsi = {
.lp_cmd_mode_freq_khz = 430000,
};
-static struct tegra_dc_mode cardhu_dsi_modes[] = {
-#if DSI_PANEL_219
+static struct tegra_dc_mode cardhu_dsi_modes_219[] = {
{
.pclk = 10000000,
.h_ref_to_sync = 4,
@@ -943,9 +1021,9 @@ static struct tegra_dc_mode cardhu_dsi_modes[] = {
.h_front_porch = 32,
.v_front_porch = 2,
},
-#endif
+};
-#if DSI_PANEL_218
+static struct tegra_dc_mode cardhu_dsi_modes_218[] = {
{
.pclk = 323000000,
.h_ref_to_sync = 11,
@@ -959,28 +1037,30 @@ static struct tegra_dc_mode cardhu_dsi_modes[] = {
.h_front_porch = 16,
.v_front_porch = 4,
},
-#endif
+};
+static struct tegra_dc_mode cardhu_dsi_modes_1506[] = {
+ {
+ .pclk = 61417000,
+ .h_ref_to_sync = 2,
+ .v_ref_to_sync = 2,
+ .h_sync_width = 4,
+ .v_sync_width = 4,
+ .h_back_porch = 100,
+ .v_back_porch = 14,
+ .h_active = 720,
+ .v_active = 1280,
+ .h_front_porch = 4,
+ .v_front_porch = 4,
+ },
};
static struct tegra_fb_data cardhu_dsi_fb_data = {
-#if DSI_PANEL_219
.win = 0,
- .xres = 540,
- .yres = 960,
- .bits_per_pixel = 32,
-#endif
-
-#if DSI_PANEL_218
- .win = 0,
- .xres = 864,
- .yres = 480,
.bits_per_pixel = 32,
-#endif
.flags = TEGRA_FB_FLIP_ON_PROBE,
};
-#endif
static struct tegra_dc_out cardhu_disp1_out = {
.align = TEGRA_DC_ALIGN_MSB,
@@ -988,30 +1068,6 @@ static struct tegra_dc_out cardhu_disp1_out = {
.sd_settings = &cardhu_sd_settings,
.parent_clk = "pll_d_out0",
-#ifndef CONFIG_TEGRA_CARDHU_DSI
- .parent_clk_backup = "pll_d2_out0",
-
- .type = TEGRA_DC_OUT_RGB,
- .depth = 18,
- .dither = TEGRA_DC_ORDERED_DITHER,
-
- .modes = cardhu_panel_modes,
- .n_modes = ARRAY_SIZE(cardhu_panel_modes),
-
- .enable = cardhu_panel_enable,
- .disable = cardhu_panel_disable,
-#else
- .type = TEGRA_DC_OUT_DSI,
-
- .modes = cardhu_dsi_modes,
- .n_modes = ARRAY_SIZE(cardhu_dsi_modes),
-
- .dsi = &cardhu_dsi,
-
- .enable = cardhu_dsi_panel_enable,
- .disable = cardhu_dsi_panel_disable,
- .postsuspend = cardhu_dsi_panel_postsuspend,
-#endif
};
#ifdef CONFIG_TEGRA_DC
@@ -1019,11 +1075,6 @@ static struct tegra_dc_platform_data cardhu_disp1_pdata = {
.flags = TEGRA_DC_FLAG_ENABLED,
.default_out = &cardhu_disp1_out,
.emc_clk_rate = 300000000,
-#ifndef CONFIG_TEGRA_CARDHU_DSI
- .fb = &cardhu_fb_data,
-#else
- .fb = &cardhu_dsi_fb_data,
-#endif
};
static struct nvhost_device cardhu_disp1_device = {
@@ -1172,6 +1223,69 @@ static void cardhu_panel_late_resume(struct early_suspend *h)
}
#endif
+static void cardhu_panel_preinit(void)
+{
+ if (display_board_info.board_id == BOARD_DISPLAY_E1213)
+ is_panel_218 = true;
+ else if (display_board_info.board_id == BOARD_DISPLAY_E1253)
+ is_panel_219 = true;
+ else if (display_board_info.board_id == BOARD_DISPLAY_E1506)
+ is_panel_1506 = true;
+
+ if (!is_dsi_panel()) {
+ cardhu_disp1_out.parent_clk_backup = "pll_d2_out0";
+ cardhu_disp1_out.type = TEGRA_DC_OUT_RGB;
+ cardhu_disp1_out.depth = 18;
+ cardhu_disp1_out.dither = TEGRA_DC_ORDERED_DITHER;
+ cardhu_disp1_out.modes = cardhu_panel_modes;
+ cardhu_disp1_out.n_modes = ARRAY_SIZE(cardhu_panel_modes);
+ cardhu_disp1_out.enable = cardhu_panel_enable;
+ cardhu_disp1_out.disable = cardhu_panel_disable;
+
+ cardhu_disp1_pdata.fb = &cardhu_fb_data;
+ } else {
+ cardhu_disp1_out.flags = DC_CTRL_MODE;
+ cardhu_disp1_out.type = TEGRA_DC_OUT_DSI;
+ cardhu_disp1_out.dsi = &cardhu_dsi;
+ cardhu_disp1_out.enable = cardhu_dsi_panel_enable;
+ cardhu_disp1_out.disable = cardhu_dsi_panel_disable;
+ cardhu_disp1_out.postsuspend = cardhu_dsi_panel_postsuspend;
+
+ cardhu_dsi.n_init_cmd = ARRAY_SIZE(dsi_init_cmd);
+ cardhu_dsi.dsi_init_cmd = dsi_init_cmd;
+ cardhu_dsi.n_suspend_cmd = ARRAY_SIZE(dsi_suspend_cmd);
+ cardhu_dsi.dsi_suspend_cmd = dsi_suspend_cmd;
+
+ if (is_panel_218) {
+ cardhu_disp1_out.modes = cardhu_dsi_modes_218;
+ cardhu_disp1_out.n_modes =
+ ARRAY_SIZE(cardhu_dsi_modes_218);
+ cardhu_dsi_fb_data.xres = 864;
+ cardhu_dsi_fb_data.yres = 480;
+ } 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;
+ } else if (is_panel_1506) {
+ cardhu_disp1_out.modes = cardhu_dsi_modes_1506;
+ cardhu_disp1_out.n_modes =
+ ARRAY_SIZE(cardhu_dsi_modes_1506);
+ cardhu_dsi.n_init_cmd = ARRAY_SIZE(dsi_init_cmd_1506);
+ cardhu_dsi.dsi_init_cmd = dsi_init_cmd_1506;
+ 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_fb_data.xres = 720;
+ cardhu_dsi_fb_data.yres = 1280;
+ }
+
+ cardhu_disp1_pdata.fb = &cardhu_dsi_fb_data;
+ }
+}
+
int __init cardhu_panel_init(void)
{
int err;
@@ -1190,7 +1304,10 @@ int __init cardhu_panel_init(void)
tegra_ion_data.heaps[0].size = tegra_carveout_size;
#endif
-#if defined(CONFIG_TEGRA_DC) && !defined(CONFIG_TEGRA_CARDHU_DSI)
+ cardhu_panel_preinit();
+ if (is_dsi_panel())
+ goto skip_lvds;
+#if defined(CONFIG_TEGRA_DC)
if (WARN_ON(board_info.board_id == BOARD_E1291 &&
((board_info.sku & SKU_TOUCHSCREEN_MECH_FIX) == 0))) {
/* use 55Hz panel timings to reduce noise on sensitive touch */
@@ -1222,28 +1339,22 @@ int __init cardhu_panel_init(void)
/* lvds configuration */
err = gpio_request(pm313_R_FDE, "R_FDE");
err |= gpio_direction_output(pm313_R_FDE, 1);
- tegra_gpio_enable(pm313_R_FDE);
err |= gpio_request(pm313_R_FB, "R_FB");
err |= gpio_direction_output(pm313_R_FB, 1);
- tegra_gpio_enable(pm313_R_FB);
err |= gpio_request(pm313_MODE0, "MODE0");
err |= gpio_direction_output(pm313_MODE0, 1);
- tegra_gpio_enable(pm313_MODE0);
err |= gpio_request(pm313_MODE1, "MODE1");
err |= gpio_direction_output(pm313_MODE1, 0);
- tegra_gpio_enable(pm313_MODE1);
err |= gpio_request(pm313_BPP, "BPP");
err |= gpio_direction_output(pm313_BPP, PM313_LVDS_PANEL_BPP);
- tegra_gpio_enable(pm313_BPP);
err = gpio_request(pm313_lvds_shutdown, "lvds_shutdown");
/* free ride provided by bootloader */
err |= gpio_direction_output(pm313_lvds_shutdown, 1);
- tegra_gpio_enable(pm313_lvds_shutdown);
if (err)
printk(KERN_ERR "ERROR(s) in LVDS configuration\n");
@@ -1254,18 +1365,22 @@ int __init cardhu_panel_init(void)
(board_info.board_id == BOARD_PM311)) {
gpio_request(e1247_pm269_lvds_shutdown, "lvds_shutdown");
gpio_direction_output(e1247_pm269_lvds_shutdown, 1);
- tegra_gpio_enable(e1247_pm269_lvds_shutdown);
} else {
gpio_request(cardhu_lvds_shutdown, "lvds_shutdown");
gpio_direction_output(cardhu_lvds_shutdown, 1);
- tegra_gpio_enable(cardhu_lvds_shutdown);
}
#endif
- tegra_gpio_enable(cardhu_hdmi_hpd);
+skip_lvds:
gpio_request(cardhu_hdmi_hpd, "hdmi_hpd");
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
+
#ifdef CONFIG_HAS_EARLYSUSPEND
cardhu_panel_early_suspender.suspend = cardhu_panel_early_suspend;
cardhu_panel_early_suspender.resume = cardhu_panel_late_resume;
@@ -1274,7 +1389,7 @@ int __init cardhu_panel_init(void)
#endif
#ifdef CONFIG_TEGRA_GRHOST
- err = nvhost_device_register(&tegra_grhost_device);
+ err = tegra3_register_host1x_devices();
if (err)
return err;
#endif
diff --git a/arch/arm/mach-tegra/board-cardhu-pinmux.c b/arch/arm/mach-tegra/board-cardhu-pinmux.c
index ee2b4b48b599..7b98af0f167c 100644
--- a/arch/arm/mach-tegra/board-cardhu-pinmux.c
+++ b/arch/arm/mach-tegra/board-cardhu-pinmux.c
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-tegra/board-cardhu-pinmux.c
*
- * Copyright (C) 2011 NVIDIA Corporation
+ * Copyright (C) 2011-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
@@ -136,6 +136,17 @@ static __initdata struct tegra_drive_pingroup_config cardhu_drive_pinmux[] = {
.od = TEGRA_PIN_OD_DEFAULT, \
.ioreset = TEGRA_PIN_IO_RESET_##_ioreset \
}
+#define CEC_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, \
+ }
static __initdata struct tegra_pingroup_config cardhu_pinmux_common[] = {
/* SDMMC1 pinmux */
@@ -189,6 +200,9 @@ static __initdata struct tegra_pingroup_config cardhu_pinmux_common[] = {
I2C_PINMUX(PWR_I2C_SCL, I2CPWR, NORMAL, NORMAL, INPUT, DISABLE, ENABLE),
I2C_PINMUX(PWR_I2C_SDA, I2CPWR, NORMAL, NORMAL, INPUT, DISABLE, ENABLE),
+ /* HDMI-CEC pinmux */
+ CEC_PINMUX(HDMI_CEC, CEC, NORMAL, NORMAL, INPUT, DISABLE, ENABLE),
+
DEFAULT_PINMUX(ULPI_DATA0, UARTA, NORMAL, NORMAL, OUTPUT),
DEFAULT_PINMUX(ULPI_DATA1, UARTA, NORMAL, NORMAL, INPUT),
DEFAULT_PINMUX(ULPI_DATA2, UARTA, NORMAL, NORMAL, INPUT),
@@ -495,6 +509,11 @@ static __initdata struct tegra_pingroup_config cardhu_pinmux_e1198[] = {
DEFAULT_PINMUX(SPI2_CS2_N, SPI2, PULL_UP, NORMAL, INPUT),
};
+static __initdata struct tegra_pingroup_config cardhu_pinmux_pm269_e1506[] = {
+ DEFAULT_PINMUX(LCD_M1, DISPLAYA, NORMAL, NORMAL, OUTPUT),
+ DEFAULT_PINMUX(LCD_DC1, DISPLAYA, NORMAL, NORMAL, OUTPUT),
+};
+
static __initdata struct tegra_pingroup_config unused_pins_lowpower[] = {
DEFAULT_PINMUX(GMI_WAIT, NAND, PULL_UP, TRISTATE, OUTPUT),
DEFAULT_PINMUX(GMI_ADV_N, NAND, NORMAL, TRISTATE, OUTPUT),
@@ -510,7 +529,6 @@ static __initdata struct tegra_pingroup_config unused_pins_lowpower[] = {
DEFAULT_PINMUX(GMI_AD5, NAND, NORMAL, TRISTATE, OUTPUT),
DEFAULT_PINMUX(GMI_AD6, NAND, NORMAL, TRISTATE, OUTPUT),
DEFAULT_PINMUX(GMI_AD7, NAND, NORMAL, TRISTATE, OUTPUT),
- DEFAULT_PINMUX(GMI_AD9, PWM1, NORMAL, NORMAL, OUTPUT),
DEFAULT_PINMUX(GMI_AD11, NAND, NORMAL, NORMAL, OUTPUT),
DEFAULT_PINMUX(GMI_AD13, NAND, PULL_UP, NORMAL, INPUT),
DEFAULT_PINMUX(GMI_WR_N, NAND, NORMAL, TRISTATE, OUTPUT),
@@ -528,7 +546,6 @@ static __initdata struct tegra_pingroup_config gmi_pins_269[] = {
DEFAULT_PINMUX(GMI_CS6_N, SATA, NORMAL, TRISTATE, OUTPUT),
DEFAULT_PINMUX(GMI_CS7_N, NAND, PULL_UP, NORMAL, INPUT),
DEFAULT_PINMUX(GMI_AD8, PWM0, NORMAL, NORMAL, OUTPUT),
- DEFAULT_PINMUX(GMI_AD9, PWM1, NORMAL, NORMAL, OUTPUT),
DEFAULT_PINMUX(GMI_AD10, NAND, NORMAL, NORMAL, OUTPUT),
DEFAULT_PINMUX(GMI_AD11, NAND, NORMAL, NORMAL, OUTPUT),
DEFAULT_PINMUX(GMI_AD13, NAND, PULL_UP, TRISTATE, OUTPUT),
@@ -543,11 +560,8 @@ static __initdata struct tegra_pingroup_config gmi_pins_269[] = {
static void __init cardhu_pinmux_audio_init(void)
{
- tegra_gpio_enable(TEGRA_GPIO_CDC_IRQ);
gpio_request(TEGRA_GPIO_CDC_IRQ, "wm8903");
gpio_direction_input(TEGRA_GPIO_CDC_IRQ);
-
- tegra_gpio_enable(TEGRA_GPIO_HP_DET);
}
#define GPIO_INIT_PIN_MODE(_gpio, _is_input, _value) \
@@ -622,6 +636,7 @@ static void __init cardhu_gpio_init_configure(void)
int __init cardhu_pinmux_init(void)
{
struct board_info board_info;
+ struct board_info display_board_info;
cardhu_gpio_init_configure();
@@ -630,6 +645,7 @@ int __init cardhu_pinmux_init(void)
ARRAY_SIZE(cardhu_drive_pinmux));
tegra_get_board_info(&board_info);
+ tegra_get_display_board_info(&display_board_info);
switch (board_info.board_id) {
case BOARD_E1198:
tegra_pinmux_config_table(cardhu_pinmux_e1198,
@@ -666,6 +682,12 @@ int __init cardhu_pinmux_init(void)
tegra_pinmux_config_table(cardhu_pinmux_e118x,
ARRAY_SIZE(cardhu_pinmux_e118x));
}
+
+ 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,
ARRAY_SIZE(unused_pins_lowpower));
tegra_pinmux_config_table(gmi_pins_269,
@@ -702,7 +724,6 @@ struct gpio_init_pin_info pin_lpm_cardhu_common[] = {
/* E1198 without PM313 display board */
struct gpio_init_pin_info pin_lpm_cardhu_common_wo_pm313[] = {
- PIN_GPIO_LPM("GMI_AD9", TEGRA_GPIO_PH1, 0, 0),
PIN_GPIO_LPM("GMI_AD11", TEGRA_GPIO_PH3, 0, 0),
};
@@ -722,7 +743,10 @@ struct gpio_init_pin_info vddio_gmi_pins_pm269[] = {
/* PM269 without PM313 display board */
struct gpio_init_pin_info vddio_gmi_pins_pm269_wo_pm313[] = {
PIN_GPIO_LPM("GMI_CS2", TEGRA_GPIO_PK3, 1, 0),
- PIN_GPIO_LPM("GMI_AD9", TEGRA_GPIO_PH1, 0, 0),
+};
+
+struct gpio_init_pin_info vddio_gmi_pins_pm269_e1506[] = {
+ PIN_GPIO_LPM("GMI_CS2", TEGRA_GPIO_PK3, 1, 0),
};
static void set_unused_pin_gpio(struct gpio_init_pin_info *lpm_pin_info,
@@ -754,7 +778,6 @@ static void set_unused_pin_gpio(struct gpio_init_pin_info *lpm_pin_info,
gpio_free(pin_info->gpio_nr);
continue;
}
- tegra_gpio_enable(pin_info->gpio_nr);
}
}
@@ -785,7 +808,10 @@ int __init cardhu_pins_state_init(void)
set_unused_pin_gpio(&vddio_gmi_pins_pm269[0],
ARRAY_SIZE(vddio_gmi_pins_pm269));
- if (display_board_info.board_id != BOARD_DISPLAY_PM313) {
+ 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));
+ } 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-pm298-power-rails.c b/arch/arm/mach-tegra/board-cardhu-pm298-power-rails.c
index 0305ee702cbd..9168d9719b7c 100644
--- a/arch/arm/mach-tegra/board-cardhu-pm298-power-rails.c
+++ b/arch/arm/mach-tegra/board-cardhu-pm298-power-rails.c
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-tegra/board-cardhu-pm298-power-rails.c
*
- * Copyright (C) 2011 NVIDIA, Inc.
+ * Copyright (C) 2011-2012, NVIDIA Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -37,7 +37,6 @@
#include "board.h"
#include "board-cardhu.h"
#include "pm.h"
-#include "wakeups-t3.h"
#define PMC_CTRL 0x0
#define PMC_CTRL_INTR_LOW BIT(17)
@@ -676,7 +675,6 @@ static struct platform_device *fixed_reg_devs_pm269[] = {
int __init cardhu_pm298_gpio_switch_regulator_init(void)
{
- int i;
struct board_info board_info;
struct platform_device **fixed_reg_devs;
int nfixreg_devs;
@@ -698,12 +696,5 @@ int __init cardhu_pm298_gpio_switch_regulator_init(void)
break;
}
- for (i = 0; i < nfixreg_devs; ++i) {
- struct fixed_voltage_config *fixed_reg_pdata =
- fixed_reg_devs[i]->dev.platform_data;
- int gpio_nr = fixed_reg_pdata->gpio;
- if (gpio_nr < TEGRA_NR_GPIOS)
- tegra_gpio_enable(gpio_nr);
- }
return platform_add_devices(fixed_reg_devs, nfixreg_devs);
}
diff --git a/arch/arm/mach-tegra/board-cardhu-pm299-power-rails.c b/arch/arm/mach-tegra/board-cardhu-pm299-power-rails.c
index 0c55aa49acc0..32f07599fea4 100644
--- a/arch/arm/mach-tegra/board-cardhu-pm299-power-rails.c
+++ b/arch/arm/mach-tegra/board-cardhu-pm299-power-rails.c
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-tegra/board-cardhu-pm299-power-rails.c
*
- * Copyright (C) 2011 NVIDIA, Inc.
+ * Copyright (C) 2011-2012, NVIDIA Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -37,7 +37,6 @@
#include "gpio-names.h"
#include "board.h"
#include "board-cardhu.h"
-#include "wakeups-t3.h"
#define PMC_CTRL 0x0
#define PMC_CTRL_INTR_LOW (1 << 17)
@@ -666,7 +665,6 @@ static struct platform_device *fixed_reg_devs_pm269[] = {
int __init cardhu_pm299_gpio_switch_regulator_init(void)
{
- int i;
struct board_info board_info;
struct platform_device **fixed_reg_devs;
int nfixreg_devs;
@@ -688,12 +686,5 @@ int __init cardhu_pm299_gpio_switch_regulator_init(void)
break;
}
- for (i = 0; i < nfixreg_devs; ++i) {
- struct fixed_voltage_config *fixed_reg_pdata =
- fixed_reg_devs[i]->dev.platform_data;
- int gpio_nr = fixed_reg_pdata->gpio;
- if (gpio_nr < TEGRA_NR_GPIOS)
- tegra_gpio_enable(gpio_nr);
- }
return platform_add_devices(fixed_reg_devs, nfixreg_devs);
}
diff --git a/arch/arm/mach-tegra/board-cardhu-power.c b/arch/arm/mach-tegra/board-cardhu-power.c
index 1bc811ef9611..ace103f5ba6b 100644
--- a/arch/arm/mach-tegra/board-cardhu-power.c
+++ b/arch/arm/mach-tegra/board-cardhu-power.c
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-tegra/board-cardhu-power.c
*
- * Copyright (C) 2011 NVIDIA, Inc.
+ * Copyright (C) 2011-2012, NVIDIA Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -42,8 +42,9 @@
#include "board.h"
#include "board-cardhu.h"
#include "pm.h"
-#include "wakeups-t3.h"
#include "tegra3_tsensor.h"
+#include "wakeups.h"
+#include "wakeups-t3.h"
#define PMC_CTRL 0x0
#define PMC_CTRL_INTR_LOW (1 << 17)
@@ -486,7 +487,8 @@ int __init cardhu_regulator_init(void)
/* E1291-A04/A05: Enable DEV_SLP and enable sleep on GPIO2 */
if ((board_info.board_id == BOARD_E1291) &&
((board_info.fab == BOARD_FAB_A04) ||
- (board_info.fab == BOARD_FAB_A05))) {
+ (board_info.fab == BOARD_FAB_A05) ||
+ (board_info.fab == BOARD_FAB_A07))) {
tps_platform.dev_slp_en = true;
tps_platform.gpio_init_data = tps_gpio_pdata_e1291_a04;
tps_platform.num_gpioinit_data =
@@ -603,12 +605,14 @@ static struct regulator_consumer_supply fixed_reg_en_vdd_pnl1_supply[] = {
static struct regulator_consumer_supply fixed_reg_cam1_ldo_en_supply[] = {
REGULATOR_SUPPLY("vdd_2v8_cam1", NULL),
REGULATOR_SUPPLY("avdd", "6-0072"),
+ REGULATOR_SUPPLY("vdd", "6-000e"),
};
/* CAM2_LDO_EN from AP GPIO KB_ROW7 R07*/
static struct regulator_consumer_supply fixed_reg_cam2_ldo_en_supply[] = {
REGULATOR_SUPPLY("vdd_2v8_cam2", NULL),
REGULATOR_SUPPLY("avdd", "7-0072"),
+ REGULATOR_SUPPLY("vdd", "7-000e"),
};
/* CAM3_LDO_EN from AP GPIO KB_ROW8 S00*/
@@ -648,6 +652,8 @@ static struct regulator_consumer_supply fixed_reg_en_1v8_cam_supply[] = {
REGULATOR_SUPPLY("vdd_1v8_cam3", NULL),
REGULATOR_SUPPLY("dvdd", "6-0072"),
REGULATOR_SUPPLY("dvdd", "7-0072"),
+ REGULATOR_SUPPLY("vdd_i2c", "6-000e"),
+ REGULATOR_SUPPLY("vdd_i2c", "7-000e"),
REGULATOR_SUPPLY("vdd_i2c", "2-0033"),
};
@@ -741,9 +747,7 @@ FIXED_REG(3, en_3v3_sys_a04, en_3v3_sys, NULL, 0, 0, TPS6591X_GPIO_
/* Specific to pm269 */
FIXED_REG(4, en_vdd_bl_pm269, en_vdd_bl, NULL, 0, 0, TEGRA_GPIO_PH3, true, 1, 5000);
-#ifndef CONFIG_TEGRA_CARDHU_DSI
FIXED_REG(6, en_vdd_pnl1_pm269, en_vdd_pnl1, FIXED_SUPPLY(en_3v3_sys), 0, 0, TEGRA_GPIO_PW1, true, 1, 3300);
-#endif
FIXED_REG(9, en_3v3_fuse_pm269, en_3v3_fuse, FIXED_SUPPLY(en_3v3_sys), 0, 0, TEGRA_GPIO_PC1, true, 0, 3300);
FIXED_REG(12, en_3v3_pex_hvdd_pm269, en_3v3_pex_hvdd, FIXED_SUPPLY(en_3v3_sys), 0, 0, TEGRA_GPIO_PC6, true, 0, 3300);
@@ -837,6 +841,7 @@ FIXED_REG_OD(17, en_vddio_vid_oc, en_vddio_vid_oc, FIXED_SUPPLY(en_5v0), 0,
ADD_FIXED_REG(en_3v3_pex_hvdd_pm269), \
ADD_FIXED_REG(en_1v8_cam), \
ADD_FIXED_REG(dis_5v_switch_e118x), \
+ ADD_FIXED_REG(en_vbrtr), \
ADD_FIXED_REG(en_usb1_vbus_oc_e118x), \
ADD_FIXED_REG(en_usb3_vbus_oc_e118x), \
ADD_FIXED_REG(en_vddio_vid_oc_pm269),
@@ -861,14 +866,12 @@ FIXED_REG_OD(17, en_vddio_vid_oc, en_vddio_vid_oc, FIXED_SUPPLY(en_5v0), 0,
ADD_FIXED_REG(en_vddio_vid_oc_pm269),
-#ifndef CONFIG_TEGRA_CARDHU_DSI
#define E1247_DISPLAY_FIXED_REG \
ADD_FIXED_REG(en_vdd_bl_pm269), \
ADD_FIXED_REG(en_vdd_pnl1_pm269),
-#else
-#define E1247_DISPLAY_FIXED_REG \
+
+#define E1247_DSI_DISPLAY_FIXED_REG \
ADD_FIXED_REG(en_vdd_bl_pm269),
-#endif
#define PM313_DISPLAY_FIXED_REG \
ADD_FIXED_REG(en_vdd_bl_pm313), \
@@ -915,6 +918,11 @@ static struct platform_device *fixed_reg_devs_e118x[] = {
E1247_DISPLAY_FIXED_REG
};
+static struct platform_device *fixed_reg_devs_e118x_dsi[] = {
+ E118x_FIXED_REG
+ E1247_DSI_DISPLAY_FIXED_REG
+};
+
/* Fixed regulator devices for E1186/E1187/E1256 */
static struct platform_device *fixed_reg_devs_e118x_pm313[] = {
E118x_FIXED_REG
@@ -957,6 +965,11 @@ static struct platform_device *fixed_reg_devs_pm269[] = {
E1247_DISPLAY_FIXED_REG
};
+static struct platform_device *fixed_reg_devs_pm269_dsi[] = {
+ PM269_FIXED_REG
+ E1247_DSI_DISPLAY_FIXED_REG
+};
+
/* Fixed regulator devices for PM269 */
static struct platform_device *fixed_reg_devs_pm269_pm313[] = {
PM269_FIXED_REG
@@ -969,6 +982,11 @@ static struct platform_device *fixed_reg_devs_pm311[] = {
E1247_DISPLAY_FIXED_REG
};
+static struct platform_device *fixed_reg_devs_pm311_dsi[] = {
+ PM311_FIXED_REG
+ E1247_DSI_DISPLAY_FIXED_REG
+};
+
/* Fixed regulator devices for PM11 */
static struct platform_device *fixed_reg_devs_pm311_pm313[] = {
PM311_FIXED_REG
@@ -989,9 +1007,15 @@ static struct platform_device *fixed_reg_devs_e1291_a04[] = {
E1198_FIXED_REG
};
+static bool is_display_board_dsi(u16 display_board_id)
+{
+ return ((display_board_id == BOARD_DISPLAY_E1213) ||
+ (display_board_id == BOARD_DISPLAY_E1253) ||
+ (display_board_id == BOARD_DISPLAY_E1506));
+}
+
int __init cardhu_fixed_regulator_init(void)
{
- int i;
struct board_info board_info;
struct board_info pmu_board_info;
struct board_info display_board_info;
@@ -1027,7 +1051,8 @@ int __init cardhu_fixed_regulator_init(void)
nfixreg_devs = ARRAY_SIZE(fixed_reg_devs_e1291_a03);
fixed_reg_devs = fixed_reg_devs_e1291_a03;
} else if ((board_info.fab == BOARD_FAB_A04) ||
- (board_info.fab == BOARD_FAB_A05)) {
+ (board_info.fab == BOARD_FAB_A05) ||
+ (board_info.fab == BOARD_FAB_A07)) {
nfixreg_devs = ARRAY_SIZE(fixed_reg_devs_e1291_a04);
fixed_reg_devs = fixed_reg_devs_e1291_a04;
} else {
@@ -1043,6 +1068,9 @@ int __init cardhu_fixed_regulator_init(void)
if (display_board_info.board_id == BOARD_DISPLAY_PM313) {
nfixreg_devs = ARRAY_SIZE(fixed_reg_devs_pm311_pm313);
fixed_reg_devs = fixed_reg_devs_pm311_pm313;
+ } else if (is_display_board_dsi(display_board_info.board_id)) {
+ nfixreg_devs = ARRAY_SIZE(fixed_reg_devs_pm311_dsi);
+ fixed_reg_devs = fixed_reg_devs_pm311_dsi;
}
break;
@@ -1053,6 +1081,9 @@ int __init cardhu_fixed_regulator_init(void)
if (display_board_info.board_id == BOARD_DISPLAY_PM313) {
nfixreg_devs = ARRAY_SIZE(fixed_reg_devs_pm269_pm313);
fixed_reg_devs = fixed_reg_devs_pm269_pm313;
+ } else if (is_display_board_dsi(display_board_info.board_id)) {
+ nfixreg_devs = ARRAY_SIZE(fixed_reg_devs_pm269_dsi);
+ fixed_reg_devs = fixed_reg_devs_pm269_dsi;
} else {
nfixreg_devs = ARRAY_SIZE(fixed_reg_devs_pm269);
fixed_reg_devs = fixed_reg_devs_pm269;
@@ -1063,6 +1094,9 @@ int __init cardhu_fixed_regulator_init(void)
if (display_board_info.board_id == BOARD_DISPLAY_PM313) {
nfixreg_devs = ARRAY_SIZE(fixed_reg_devs_e118x_pm313);
fixed_reg_devs = fixed_reg_devs_e118x_pm313;
+ } else if (is_display_board_dsi(display_board_info.board_id)) {
+ nfixreg_devs = ARRAY_SIZE(fixed_reg_devs_e118x_dsi);
+ fixed_reg_devs = fixed_reg_devs_e118x_dsi;
} else {
nfixreg_devs = ARRAY_SIZE(fixed_reg_devs_e118x);
fixed_reg_devs = fixed_reg_devs_e118x;
@@ -1070,13 +1104,6 @@ int __init cardhu_fixed_regulator_init(void)
break;
}
- for (i = 0; i < nfixreg_devs; ++i) {
- struct fixed_voltage_config *fixed_reg_pdata =
- fixed_reg_devs[i]->dev.platform_data;
- int gpio_nr = fixed_reg_pdata->gpio;
- if (gpio_nr < TEGRA_NR_GPIOS)
- tegra_gpio_enable(gpio_nr);
- }
return platform_add_devices(fixed_reg_devs, nfixreg_devs);
}
subsys_initcall_sync(cardhu_fixed_regulator_init);
@@ -1130,8 +1157,15 @@ int __init cardhu_suspend_init(void)
/* CORE_PWR_REQ to be high for E1291-A03 */
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 */
+ 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 */
+ tegra_disable_wake_source(TEGRA_WAKE_USB1_VBUS);
+ break;
case BOARD_PM269:
case BOARD_PM305:
case BOARD_PM311:
diff --git a/arch/arm/mach-tegra/board-cardhu-sdhci.c b/arch/arm/mach-tegra/board-cardhu-sdhci.c
index 73bd1f2c308a..d8be9fe6747f 100644
--- a/arch/arm/mach-tegra/board-cardhu-sdhci.c
+++ b/arch/arm/mach-tegra/board-cardhu-sdhci.c
@@ -2,7 +2,7 @@
* arch/arm/mach-tegra/board-harmony-sdhci.c
*
* Copyright (C) 2010 Google, Inc.
- * Copyright (C) 2011 NVIDIA Corporation.
+ * Copyright (C) 2011-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
@@ -145,6 +145,7 @@ static struct tegra_sdhci_platform_data tegra_sdhci_platform_data2 = {
.embedded_sdio = &embedded_sdio_data2,
#endif
.built_in = 0,
+ .ocr_mask = MMC_OCR_1V8_MASK,
},
#ifndef CONFIG_MMC_EMBEDDED_SDIO
.pm_flags = MMC_PM_KEEP_POWER,
@@ -152,8 +153,9 @@ static struct tegra_sdhci_platform_data tegra_sdhci_platform_data2 = {
.cd_gpio = -1,
.wp_gpio = -1,
.power_gpio = -1,
-/* .tap_delay = 6,
- .is_voltage_switch_supported = false,
+ .tap_delay = 0x0F,
+ .ddr_clk_limit = 41000000,
+/* .is_voltage_switch_supported = false,
.vdd_rail_name = NULL,
.slot_rail_name = NULL,
.vdd_max_uv = -1,
@@ -166,8 +168,9 @@ static struct tegra_sdhci_platform_data tegra_sdhci_platform_data0 = {
.cd_gpio = CARDHU_SD_CD,
.wp_gpio = CARDHU_SD_WP,
.power_gpio = -1,
-/* .tap_delay = 6,
- .is_voltage_switch_supported = true,
+ .tap_delay = 0x0F,
+ .ddr_clk_limit = 41000000,
+/* .is_voltage_switch_supported = true,
.vdd_rail_name = "vddio_sdmmc1",
.slot_rail_name = "vddio_sd_slot",
.vdd_max_uv = 3320000,
@@ -182,11 +185,11 @@ static struct tegra_sdhci_platform_data tegra_sdhci_platform_data3 = {
.power_gpio = -1,
.is_8bit = 1,
.tap_delay = 0x0F,
+ .ddr_clk_limit = 41000000,
.mmc_data = {
.built_in = 1,
}
-/* .tap_delay = 6,
- .is_voltage_switch_supported = false,
+/* .is_voltage_switch_supported = false,
.vdd_rail_name = NULL,
.slot_rail_name = NULL,
.vdd_max_uv = -1,
@@ -278,10 +281,6 @@ static int __init cardhu_wifi_init(void)
if (rc)
pr_err("WLAN_WOW gpio request failed:%d\n", rc);
- tegra_gpio_enable(CARDHU_WLAN_PWR);
- tegra_gpio_enable(CARDHU_WLAN_RST);
- tegra_gpio_enable(CARDHU_WLAN_WOW);
-
rc = gpio_direction_output(CARDHU_WLAN_PWR, 0);
if (rc)
pr_err("WLAN_PWR gpio direction configuration failed:%d\n", rc);
diff --git a/arch/arm/mach-tegra/board-cardhu-sensors.c b/arch/arm/mach-tegra/board-cardhu-sensors.c
index fe3188ec1cfd..bb6a2ae5774d 100644
--- a/arch/arm/mach-tegra/board-cardhu-sensors.c
+++ b/arch/arm/mach-tegra/board-cardhu-sensors.c
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-tegra/board-cardhu-sensors.c
*
- * Copyright (c) 2010-2011, NVIDIA CORPORATION, All rights reserved.
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -40,6 +40,7 @@
#include <mach/fb.h>
#include <mach/gpio.h>
#include <media/ov5650.h>
+#include <media/ov5640.h>
#include <media/ov14810.h>
#include <media/ov2710.h>
#include <media/tps61050.h>
@@ -48,10 +49,12 @@
#include "board.h"
#include <linux/mpu.h>
#include <media/sh532u.h>
+#include <media/ad5816.h>
#include <linux/bq27x00.h>
#include <mach/gpio.h>
#include <mach/edp.h>
#include <mach/thermal.h>
+#include <linux/therm_est.h>
#include "gpio-names.h"
#include "board-cardhu.h"
@@ -86,24 +89,20 @@ static int cardhu_camera_init(void)
* and donot have TCA6416 exp for camera */
if ((board_info.board_id == BOARD_E1198) ||
(board_info.board_id == BOARD_E1291)) {
- tegra_gpio_enable(CAM1_POWER_DWN_GPIO);
ret = gpio_request(CAM1_POWER_DWN_GPIO, "camera_power_en");
if (ret < 0)
pr_err("%s: gpio_request failed for gpio %s\n",
__func__, "CAM1_POWER_DWN_GPIO");
- tegra_gpio_enable(CAM3_POWER_DWN_GPIO);
ret = gpio_request(CAM3_POWER_DWN_GPIO, "cam3_power_en");
if (ret < 0)
pr_err("%s: gpio_request failed for gpio %s\n",
__func__, "CAM3_POWER_DWN_GPIO");
- tegra_gpio_enable(CAM2_POWER_DWN_GPIO);
ret = gpio_request(CAM2_POWER_DWN_GPIO, "camera2_power_en");
if (ret < 0)
pr_err("%s: gpio_request failed for gpio %s\n",
__func__, "CAM2_POWER_DWN_GPIO");
- tegra_gpio_enable(OV5650_RESETN_GPIO);
ret = gpio_request(OV5650_RESETN_GPIO, "camera_reset");
if (ret < 0)
pr_err("%s: gpio_request failed for gpio %s\n",
@@ -123,7 +122,6 @@ static int cardhu_camera_init(void)
}
/* To select the CSIB MUX either for cam2 or cam3 */
- tegra_gpio_enable(CAMERA_CSI_MUX_SEL_GPIO);
ret = gpio_request(CAMERA_CSI_MUX_SEL_GPIO, "camera_csi_sel");
if (ret < 0)
pr_err("%s: gpio_request failed for gpio %s\n",
@@ -464,6 +462,86 @@ struct ov2710_platform_data cardhu_ov2710_data = {
.power_off = cardhu_ov2710_power_off,
};
+static int cardhu_ov5640_power_on(void)
+{
+ /* CSI-B and front sensor are muxed on cardhu */
+ gpio_direction_output(CAMERA_CSI_MUX_SEL_GPIO, 1);
+
+ /* Boards E1198 and E1291 are of Cardhu personality
+ * and donot have TCA6416 exp 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))) {
+ pr_err("%s: couldn't get regulator vdd_cam3: %ld\n",
+ __func__, PTR_ERR(cardhu_vdd_cam3));
+ goto reg_alloc_fail;
+ }
+ }
+ 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;
+ }
+ }
+ regulator_enable(cardhu_1v8_cam3);
+ mdelay(5);
+
+ return 0;
+
+reg_alloc_fail:
+ if (cardhu_1v8_cam3) {
+ regulator_put(cardhu_1v8_cam3);
+ cardhu_1v8_cam3 = NULL;
+ }
+ if (cardhu_vdd_cam3) {
+ regulator_put(cardhu_vdd_cam3);
+ cardhu_vdd_cam3 = NULL;
+ }
+
+ return -ENODEV;
+}
+
+static int cardhu_ov5640_power_off(void)
+{
+ /* CSI-B and front sensor are muxed on cardhu */
+ gpio_direction_output(CAMERA_CSI_MUX_SEL_GPIO, 1);
+
+ /* Boards E1198 and E1291 are of Cardhu personality
+ * and donot have TCA6416 exp for camera */
+ if ((board_info.board_id == BOARD_E1198) ||
+ (board_info.board_id == BOARD_E1291)) {
+ 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_1v8_cam3)
+ regulator_disable(cardhu_1v8_cam3);
+ if (cardhu_vdd_cam3)
+ regulator_disable(cardhu_vdd_cam3);
+
+ return 0;
+}
+
+struct ov5640_platform_data cardhu_ov5640_data = {
+ .power_on = cardhu_ov5640_power_on,
+ .power_off = cardhu_ov5640_power_off,
+};
+
static const struct i2c_board_info cardhu_i2c3_board_info[] = {
{
I2C_BOARD_INFO("pca9546", 0x70),
@@ -499,7 +577,7 @@ static struct nvc_gpio_pdata pm269_sh532u_left_gpio_pdata[] = {
};
static struct sh532u_platform_data pm269_sh532u_left_pdata = {
- .cfg = NVC_CFG_NODEV,
+ .cfg = 0,
.num = 1,
.sync = 2,
.dev_name = "focuser",
@@ -512,7 +590,7 @@ static struct nvc_gpio_pdata pm269_sh532u_right_gpio_pdata[] = {
};
static struct sh532u_platform_data pm269_sh532u_right_pdata = {
- .cfg = NVC_CFG_NODEV,
+ .cfg = 0,
.num = 2,
.sync = 1,
.dev_name = "focuser",
@@ -520,6 +598,54 @@ static struct sh532u_platform_data pm269_sh532u_right_pdata = {
.gpio = pm269_sh532u_right_gpio_pdata,
};
+static struct nvc_gpio_pdata ad5816_gpio_pdata[] = {
+ { AD5816_GPIO_RESET, TEGRA_GPIO_PBB0, false, 0, },
+};
+
+static struct ad5816_platform_data ad5816_left_pdata = {
+ .cfg = 0,
+ .num = 1,
+ .sync = 2,
+ .dev_name = "focuser",
+ .gpio_count = ARRAY_SIZE(ad5816_gpio_pdata),
+ .gpio = ad5816_gpio_pdata,
+};
+
+static struct ad5816_platform_data ad5816_right_pdata = {
+ .cfg = 0,
+ .num = 2,
+ .sync = 1,
+ .dev_name = "focuser",
+ .gpio_count = ARRAY_SIZE(ad5816_gpio_pdata),
+ .gpio = ad5816_gpio_pdata,
+};
+
+static struct nvc_gpio_pdata pm269_ad5816_left_gpio_pdata[] = {
+ { AD5816_GPIO_RESET, CAM1_RST_L_GPIO, false, 0, },
+};
+
+static struct ad5816_platform_data pm269_ad5816_left_pdata = {
+ .cfg = NVC_CFG_NODEV,
+ .num = 1,
+ .sync = 2,
+ .dev_name = "focuser",
+ .gpio_count = ARRAY_SIZE(pm269_ad5816_left_gpio_pdata),
+ .gpio = pm269_ad5816_left_gpio_pdata,
+};
+
+static struct nvc_gpio_pdata pm269_ad5816_right_gpio_pdata[] = {
+ { AD5816_GPIO_RESET, CAM2_RST_L_GPIO, false, 0, },
+};
+
+static struct ad5816_platform_data pm269_ad5816_right_pdata = {
+ .cfg = NVC_CFG_NODEV,
+ .num = 2,
+ .sync = 1,
+ .dev_name = "focuser",
+ .gpio_count = ARRAY_SIZE(pm269_ad5816_right_gpio_pdata),
+ .gpio = pm269_ad5816_right_gpio_pdata,
+};
+
static struct nvc_torch_pin_state cardhu_tps61050_pinstate = {
.mask = 0x0008, /*VGP3*/
@@ -547,6 +673,10 @@ static struct i2c_board_info cardhu_i2c6_board_info[] = {
I2C_BOARD_INFO("sh532u", 0x72),
.platform_data = &sh532u_left_pdata,
},
+ {
+ I2C_BOARD_INFO("ad5816", 0x0E),
+ .platform_data = &ad5816_left_pdata,
+ },
};
static struct i2c_board_info cardhu_i2c7_board_info[] = {
@@ -558,6 +688,10 @@ static struct i2c_board_info cardhu_i2c7_board_info[] = {
I2C_BOARD_INFO("sh532u", 0x72),
.platform_data = &sh532u_right_pdata,
},
+ {
+ I2C_BOARD_INFO("ad5816", 0x0E),
+ .platform_data = &ad5816_right_pdata,
+ },
};
static struct i2c_board_info pm269_i2c6_board_info[] = {
@@ -569,6 +703,10 @@ static struct i2c_board_info pm269_i2c6_board_info[] = {
I2C_BOARD_INFO("sh532u", 0x72),
.platform_data = &pm269_sh532u_left_pdata,
},
+ {
+ I2C_BOARD_INFO("ad5816", 0x0E),
+ .platform_data = &pm269_ad5816_left_pdata,
+ },
};
static struct i2c_board_info pm269_i2c7_board_info[] = {
@@ -580,6 +718,10 @@ static struct i2c_board_info pm269_i2c7_board_info[] = {
I2C_BOARD_INFO("sh532u", 0x72),
.platform_data = &pm269_sh532u_right_pdata,
},
+ {
+ I2C_BOARD_INFO("ad5816", 0x0E),
+ .platform_data = &pm269_ad5816_right_pdata,
+ },
};
static struct i2c_board_info cardhu_i2c8_board_info[] = {
@@ -587,6 +729,10 @@ static struct i2c_board_info cardhu_i2c8_board_info[] = {
I2C_BOARD_INFO("ov2710", 0x36),
.platform_data = &cardhu_ov2710_data,
},
+ {
+ I2C_BOARD_INFO("ov5640", 0x3C),
+ .platform_data = &cardhu_ov5640_data,
+ },
};
static int nct_get_temp(void *_data, long *temp)
@@ -625,27 +771,56 @@ static int nct_set_shutdown_temp(void *_data, long shutdown_temp)
return nct1008_thermal_set_shutdown_temp(data, shutdown_temp);
}
+#ifdef CONFIG_TEGRA_SKIN_THROTTLE
+static int nct_get_itemp(void *dev_data, long *temp)
+{
+ struct nct1008_data *data = dev_data;
+ return nct1008_thermal_get_temps(data, NULL, temp);
+}
+#endif
+
static void nct1008_probe_callback(struct nct1008_data *data)
{
- struct tegra_thermal_device *thermal_device;
+ struct tegra_thermal_device *ext_nct;
- thermal_device = kzalloc(sizeof(struct tegra_thermal_device),
+ ext_nct = kzalloc(sizeof(struct tegra_thermal_device),
GFP_KERNEL);
- if (!thermal_device) {
+ if (!ext_nct) {
pr_err("unable to allocate thermal device\n");
return;
}
- thermal_device->name = "nct1008";
- thermal_device->data = data;
- thermal_device->offset = TDIODE_OFFSET;
- thermal_device->get_temp = nct_get_temp;
- thermal_device->get_temp_low = nct_get_temp_low;
- thermal_device->set_limits = nct_set_limits;
- thermal_device->set_alert = nct_set_alert;
- thermal_device->set_shutdown_temp = nct_set_shutdown_temp;
+ ext_nct->name = "nct_ext";
+ ext_nct->id = THERMAL_DEVICE_ID_NCT_EXT;
+ ext_nct->data = data;
+ ext_nct->offset = TDIODE_OFFSET;
+ ext_nct->get_temp = nct_get_temp;
+ ext_nct->get_temp_low = nct_get_temp_low;
+ ext_nct->set_limits = nct_set_limits;
+ ext_nct->set_alert = nct_set_alert;
+ ext_nct->set_shutdown_temp = nct_set_shutdown_temp;
- tegra_thermal_set_device(thermal_device);
+ tegra_thermal_device_register(ext_nct);
+
+#ifdef CONFIG_TEGRA_SKIN_THROTTLE
+ {
+ struct tegra_thermal_device *int_nct;
+ int_nct = kzalloc(sizeof(struct tegra_thermal_device),
+ GFP_KERNEL);
+ if (!int_nct) {
+ kfree(int_nct);
+ pr_err("unable to allocate thermal device\n");
+ return;
+ }
+
+ int_nct->name = "nct_int";
+ int_nct->id = THERMAL_DEVICE_ID_NCT_INT;
+ int_nct->data = data;
+ int_nct->get_temp = nct_get_itemp;
+
+ tegra_thermal_device_register(int_nct);
+ }
+#endif
}
static struct nct1008_platform_data cardhu_nct1008_pdata = {
@@ -700,8 +875,6 @@ static int cardhu_nct1008_init(void)
ret = gpio_direction_input(nct1008_port);
if (ret < 0)
gpio_free(nct1008_port);
- else
- tegra_gpio_enable(nct1008_port);
}
return ret;
@@ -831,7 +1004,6 @@ static void mpuirq_init(void)
#if (MPU_GYRO_TYPE == MPU_TYPE_MPU3050)
#if MPU_ACCEL_IRQ_GPIO
/* ACCEL-IRQ assignment */
- tegra_gpio_enable(MPU_ACCEL_IRQ_GPIO);
ret = gpio_request(MPU_ACCEL_IRQ_GPIO, MPU_ACCEL_NAME);
if (ret < 0) {
pr_err("%s: gpio_request failed %d\n", __func__, ret);
@@ -848,7 +1020,6 @@ static void mpuirq_init(void)
#endif
/* MPU-IRQ assignment */
- tegra_gpio_enable(MPU_GYRO_IRQ_GPIO);
ret = gpio_request(MPU_GYRO_IRQ_GPIO, MPU_GYRO_NAME);
if (ret < 0) {
pr_err("%s: gpio_request failed %d\n", __func__, ret);
diff --git a/arch/arm/mach-tegra/board-cardhu.c b/arch/arm/mach-tegra/board-cardhu.c
index cce0d4df6885..b5fa3f316698 100644
--- a/arch/arm/mach-tegra/board-cardhu.c
+++ b/arch/arm/mach-tegra/board-cardhu.c
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-tegra/board-cardhu.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
@@ -39,6 +39,7 @@
#include <linux/memblock.h>
#include <linux/spi-tegra.h>
#include <linux/nfc/pn544.h>
+#include <linux/rfkill-gpio.h>
#include <sound/wm8903.h>
#include <sound/max98095.h>
@@ -58,6 +59,7 @@
#include <mach/usb_phy.h>
#include <mach/thermal.h>
#include <mach/pci.h>
+#include <mach/tegra_fiq_debugger.h>
#include "board.h"
#include "clock.h"
@@ -70,75 +72,109 @@
#include "baseband-xmm-power.h"
#include "wdt-recovery.h"
+static struct balanced_throttle throttle_list[] = {
+#ifdef CONFIG_TEGRA_THERMAL_THROTTLE
+ {
+ .id = BALANCED_THROTTLE_ID_TJ,
+ .throt_tab_size = 10,
+ .throt_tab = {
+ { 0, 1000 },
+ { 640000, 1000 },
+ { 640000, 1000 },
+ { 640000, 1000 },
+ { 640000, 1000 },
+ { 640000, 1000 },
+ { 760000, 1000 },
+ { 760000, 1050 },
+ {1000000, 1050 },
+ {1000000, 1100 },
+ },
+ },
+#endif
+#ifdef CONFIG_TEGRA_SKIN_THROTTLE
+ {
+ .id = BALANCED_THROTTLE_ID_SKIN,
+ .throt_tab_size = 6,
+ .throt_tab = {
+ { 640000, 1200 },
+ { 640000, 1200 },
+ { 760000, 1200 },
+ { 760000, 1200 },
+ {1000000, 1200 },
+ {1000000, 1200 },
+ },
+ },
+#endif
+};
+
/* All units are in millicelsius */
static struct tegra_thermal_data thermal_data = {
- .temp_throttle = 85000,
+ .shutdown_device_id = THERMAL_DEVICE_ID_NCT_EXT,
.temp_shutdown = 90000,
- .temp_offset = TDIODE_OFFSET, /* temps based on tdiode */
+
+#if defined(CONFIG_TEGRA_EDP_LIMITS) || defined(CONFIG_TEGRA_THERMAL_THROTTLE)
+ .throttle_edp_device_id = THERMAL_DEVICE_ID_NCT_EXT,
+#endif
#ifdef CONFIG_TEGRA_EDP_LIMITS
.edp_offset = TDIODE_OFFSET, /* edp based on tdiode */
.hysteresis_edp = 3000,
#endif
-#ifdef CONFIG_TEGRA_THERMAL_SYSFS
+#ifdef CONFIG_TEGRA_THERMAL_THROTTLE
+ .temp_throttle = 85000,
.tc1 = 0,
.tc2 = 1,
.passive_delay = 2000,
-#else
- .hysteresis_throttle = 1000,
#endif
-};
-
-/* !!!TODO: Change for cardhu (Taken from Ventana) */
-static struct tegra_utmip_config utmi_phy_config[] = {
- [0] = {
- .hssync_start_delay = 0,
- .idle_wait_delay = 17,
- .elastic_limit = 16,
- .term_range_adj = 6,
- .xcvr_setup = 15,
- .xcvr_setup_offset = 0,
- .xcvr_use_fuses = 1,
- .xcvr_lsfslew = 2,
- .xcvr_lsrslew = 2,
- },
- [1] = {
- .hssync_start_delay = 0,
- .idle_wait_delay = 17,
- .elastic_limit = 16,
- .term_range_adj = 6,
- .xcvr_setup = 15,
- .xcvr_setup_offset = 0,
- .xcvr_use_fuses = 1,
- .xcvr_lsfslew = 2,
- .xcvr_lsrslew = 2,
- },
- [2] = {
- .hssync_start_delay = 0,
- .idle_wait_delay = 17,
- .elastic_limit = 16,
- .term_range_adj = 6,
- .xcvr_setup = 8,
- .xcvr_setup_offset = 0,
- .xcvr_use_fuses = 1,
- .xcvr_lsfslew = 2,
- .xcvr_lsrslew = 2,
+#ifdef CONFIG_TEGRA_SKIN_THROTTLE
+ .skin_device_id = THERMAL_DEVICE_ID_SKIN,
+ .temp_throttle_skin = 43000,
+ .tc1_skin = 0,
+ .tc2_skin = 1,
+ .passive_delay_skin = 5000,
+
+ .skin_temp_offset = 9793,
+ .skin_period = 1100,
+ .skin_devs_size = 2,
+ .skin_devs = {
+ {
+ THERMAL_DEVICE_ID_NCT_EXT,
+ {
+ 2, 1, 1, 1,
+ 1, 1, 1, 1,
+ 1, 1, 1, 0,
+ 1, 1, 0, 0,
+ 0, 0, -1, -7
+ }
+ },
+ {
+ THERMAL_DEVICE_ID_NCT_INT,
+ {
+ -11, -7, -5, -3,
+ -3, -2, -1, 0,
+ 0, 0, 1, 1,
+ 1, 2, 2, 3,
+ 4, 6, 11, 18
+ }
+ },
},
+#endif
};
-static struct resource cardhu_bcm4329_rfkill_resources[] = {
+static struct rfkill_gpio_platform_data cardhu_bt_rfkill_pdata[] = {
{
- .name = "bcm4329_nshutdown_gpio",
- .start = TEGRA_GPIO_PU0,
- .end = TEGRA_GPIO_PU0,
- .flags = IORESOURCE_IO,
+ .name = "bt_rfkill",
+ .shutdown_gpio = TEGRA_GPIO_PU0,
+ .reset_gpio = TEGRA_GPIO_INVALID,
+ .type = RFKILL_TYPE_BLUETOOTH,
},
};
-static struct platform_device cardhu_bcm4329_rfkill_device = {
- .name = "bcm4329_rfkill",
+static struct platform_device cardhu_bt_rfkill_device = {
+ .name = "rfkill_gpio",
.id = -1,
- .num_resources = ARRAY_SIZE(cardhu_bcm4329_rfkill_resources),
- .resource = cardhu_bcm4329_rfkill_resources,
+ .dev = {
+ .platform_data = &cardhu_bt_rfkill_pdata,
+ },
};
static struct resource cardhu_bluesleep_resources[] = {
@@ -172,8 +208,6 @@ static struct platform_device cardhu_bluesleep_device = {
static noinline void __init cardhu_setup_bluesleep(void)
{
platform_device_register(&cardhu_bluesleep_device);
- tegra_gpio_enable(TEGRA_GPIO_PU6);
- tegra_gpio_enable(TEGRA_GPIO_PU1);
return;
}
@@ -200,6 +234,7 @@ static __initdata struct tegra_clk_init_table cardhu_clk_init_table[] = {
{ "i2c3", "pll_p", 3200000, false},
{ "i2c4", "pll_p", 3200000, false},
{ "i2c5", "pll_p", 3200000, false},
+ { "vi", "pll_p", 0, false},
{ NULL, NULL, 0, 0},
};
@@ -228,7 +263,7 @@ static struct tegra_i2c_platform_data cardhu_i2c1_platform_data = {
static struct tegra_i2c_platform_data cardhu_i2c2_platform_data = {
.adapter_nr = 1,
.bus_count = 1,
- .bus_clk_rate = { 100000, 0 },
+ .bus_clk_rate = { 400000, 0 },
.is_clkon_always = true,
.scl_gpio = {TEGRA_GPIO_PT5, 0},
.sda_gpio = {TEGRA_GPIO_PT6, 0},
@@ -728,7 +763,9 @@ static struct platform_device *cardhu_devices[] __initdata = {
#if defined(CONFIG_TEGRA_IOVMM_SMMU) || defined(CONFIG_TEGRA_IOMMU_SMMU)
&tegra_smmu_device,
#endif
- &tegra_wdt_device,
+ &tegra_wdt0_device,
+ &tegra_wdt1_device,
+ &tegra_wdt2_device,
#if defined(CONFIG_TEGRA_AVP)
&tegra_avp_device,
#endif
@@ -747,17 +784,44 @@ static struct platform_device *cardhu_devices[] __initdata = {
&spdif_dit_device,
&bluetooth_dit_device,
&baseband_dit_device,
- &cardhu_bcm4329_rfkill_device,
+ &cardhu_bt_rfkill_device,
&tegra_pcm_device,
&cardhu_audio_wm8903_device,
&cardhu_audio_max98095_device,
&cardhu_audio_aic326x_device,
&tegra_hda_device,
+ &tegra_cec_device,
#if defined(CONFIG_CRYPTO_DEV_TEGRA_AES)
&tegra_aes_device,
#endif
};
+#define E1506_MXT_CONFIG_CRC 0x62F903
+static const u8 e1506_config[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0x32, 0x0A, 0x00, 0x05, 0x01, 0x00,
+ 0x00, 0x1E, 0x0A, 0x8B, 0x00, 0x00, 0x13, 0x0B,
+ 0x00, 0x10, 0x32, 0x03, 0x03, 0x00, 0x03, 0x01,
+ 0x00, 0x0A, 0x0A, 0x0A, 0x0A, 0xBF, 0x03, 0x1B,
+ 0x02, 0x00, 0x00, 0x37, 0x37, 0x00, 0x00, 0x00,
+ 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xA9, 0x7F, 0x9A, 0x0E, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x03, 0x23, 0x00, 0x00, 0x00, 0x0A,
+ 0x0F, 0x14, 0x19, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0x08, 0x10,
+ 0x00
+};
+
#define MXT_CONFIG_CRC 0xD62DE8
static const u8 config[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -823,6 +887,23 @@ static struct mxt_platform_data atmel_mxt_info = {
.read_chg = NULL,
};
+static struct mxt_platform_data e1506_atmel_mxt_info = {
+ .x_line = 19,
+ .y_line = 11,
+ .x_size = 960,
+ .y_size = 540,
+ .blen = 0x10,
+ .threshold = 0x32,
+ .voltage = 3300000, /* 3.3V */
+ .orient = 3,
+ .config = e1506_config,
+ .config_length = 168,
+ .config_crc = E1506_MXT_CONFIG_CRC,
+ .irqflags = IRQF_TRIGGER_FALLING,
+/* .read_chg = &read_chg, */
+ .read_chg = NULL,
+};
+
static struct i2c_board_info __initdata atmel_i2c_info[] = {
{
I2C_BOARD_INFO("atmel_mxt_ts", 0x5A),
@@ -831,6 +912,14 @@ static struct i2c_board_info __initdata atmel_i2c_info[] = {
}
};
+static struct i2c_board_info __initdata e1506_atmel_i2c_info[] = {
+ {
+ I2C_BOARD_INFO("atmel_mxt_ts", 0x4A),
+ .irq = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PH4),
+ .platform_data = &e1506_atmel_mxt_info,
+ }
+};
+
static __initdata struct tegra_clk_init_table spi_clk_init_table[] = {
/* name parent rate enabled */
{ "sbc1", "pll_p", 52000000, true},
@@ -839,17 +928,15 @@ static __initdata struct tegra_clk_init_table spi_clk_init_table[] = {
static int __init cardhu_touch_init(void)
{
- struct board_info BoardInfo;
+ struct board_info BoardInfo, DisplayBoardInfo;
- tegra_get_display_board_info(&BoardInfo);
- if (BoardInfo.board_id == BOARD_DISPLAY_PM313) {
+ tegra_get_board_info(&BoardInfo);
+ tegra_get_display_board_info(&DisplayBoardInfo);
+ if (DisplayBoardInfo.board_id == BOARD_DISPLAY_PM313) {
tegra_clk_init_from_table(spi_clk_init_table);
touch_init_raydium(TEGRA_GPIO_PH4, TEGRA_GPIO_PH6, 2);
} else {
- tegra_gpio_enable(TEGRA_GPIO_PH4);
- tegra_gpio_enable(TEGRA_GPIO_PH6);
-
gpio_request(TEGRA_GPIO_PH4, "atmel-irq");
gpio_direction_input(TEGRA_GPIO_PH4);
@@ -859,147 +946,305 @@ static int __init cardhu_touch_init(void)
gpio_set_value(TEGRA_GPIO_PH6, 1);
msleep(100);
- tegra_get_board_info(&BoardInfo);
if ((BoardInfo.sku & SKU_TOUCH_MASK) == SKU_TOUCH_2000) {
atmel_mxt_info.config = config_sku2000;
atmel_mxt_info.config_crc = MXT_CONFIG_CRC_SKU2000;
}
- i2c_register_board_info(1, atmel_i2c_info, 1);
+ if (DisplayBoardInfo.board_id == BOARD_DISPLAY_E1506)
+ i2c_register_board_info(1, e1506_atmel_i2c_info, 1);
+ else
+ i2c_register_board_info(1, atmel_i2c_info, 1);
}
return 0;
}
-static struct tegra_uhsic_config uhsic_phy_config = {
- .enable_gpio = EN_HSIC_GPIO,
- .reset_gpio = -1,
- .sync_start_delay = 9,
- .idle_wait_delay = 17,
- .term_range_adj = 0,
- .elastic_underrun_limit = 16,
- .elastic_overrun_limit = 16,
-};
-
-static struct tegra_ehci_platform_data tegra_ehci_uhsic_pdata = {
- .phy_type = TEGRA_USB_PHY_TYPE_HSIC,
- .phy_config = &uhsic_phy_config,
- .operating_mode = TEGRA_USB_HOST,
- .power_down_on_bus_suspend = 1,
- .default_enable = true,
-};
-
-static struct tegra_ehci_platform_data tegra_ehci_pdata[] = {
- [0] = {
- .phy_config = &utmi_phy_config[0],
- .operating_mode = TEGRA_USB_HOST,
- .power_down_on_bus_suspend = 1,
- .default_enable = true,
- },
- [1] = {
- .phy_config = &utmi_phy_config[1],
- .operating_mode = TEGRA_USB_HOST,
- .power_down_on_bus_suspend = 1,
- .default_enable = true,
- },
- [2] = {
- .phy_config = &utmi_phy_config[2],
- .operating_mode = TEGRA_USB_HOST,
- .power_down_on_bus_suspend = 1,
- .hotplug = 1,
- .default_enable = true,
- },
-};
-
-static struct tegra_otg_platform_data tegra_otg_pdata = {
- .ehci_device = &tegra_ehci1_device,
- .ehci_pdata = &tegra_ehci_pdata[0],
-};
-
-#ifdef CONFIG_USB_SUPPORT
-static struct usb_phy_plat_data tegra_usb_phy_pdata[] = {
- [0] = {
- .instance = 0,
- .vbus_gpio = -1,
- .vbus_reg_supply = "vdd_vbus_micro_usb",
- },
- [1] = {
- .instance = 1,
- .vbus_gpio = -1,
- },
- [2] = {
- .instance = 2,
- .vbus_gpio = -1,
- .vbus_reg_supply = "vdd_vbus_typea_usb",
- },
-};
+#if defined(CONFIG_USB_SUPPORT)
-static int cardhu_usb_hsic_postsupend(void)
+static void cardu_usb_hsic_postsupend(void)
{
#ifdef CONFIG_TEGRA_BB_XMM_POWER
baseband_xmm_set_power_status(BBXMM_PS_L2);
#endif
- return 0;
}
-static int cardhu_usb_hsic_preresume(void)
+static void cardu_usb_hsic_preresume(void)
{
#ifdef CONFIG_TEGRA_BB_XMM_POWER
baseband_xmm_set_power_status(BBXMM_PS_L2TOL0);
#endif
- return 0;
}
-static int cardhu_usb_hsic_phy_ready(void)
+static void cardu_usb_hsic_phy_ready(void)
{
#ifdef CONFIG_TEGRA_BB_XMM_POWER
baseband_xmm_set_power_status(BBXMM_PS_L0);
#endif
- return 0;
}
-static int cardhu_usb_hsic_phy_off(void)
+static void cardu_usb_hsic_phy_off(void)
{
#ifdef CONFIG_TEGRA_BB_XMM_POWER
baseband_xmm_set_power_status(BBXMM_PS_L3);
#endif
- return 0;
}
+static struct tegra_usb_phy_platform_ops hsic_xmm_plat_ops = {
+ .post_suspend = cardu_usb_hsic_postsupend,
+ .pre_resume = cardu_usb_hsic_preresume,
+ .port_power = cardu_usb_hsic_phy_ready,
+ .post_phy_off = cardu_usb_hsic_phy_off,
+};
+
+static struct tegra_usb_platform_data tegra_ehci2_hsic_xmm_pdata = {
+ .port_otg = false,
+ .has_hostpc = true,
+ .phy_intf = TEGRA_USB_PHY_INTF_HSIC,
+ .op_mode = TEGRA_USB_OPMODE_HOST,
+ .u_data.host = {
+ .vbus_gpio = -1,
+ .hot_plug = false,
+ .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
+
+static int hsic_enable_gpio = -1;
+static int hsic_reset_gpio = -1;
+
+void hsic_platform_open(void)
+{
+ int reset_gpio = 0, enable_gpio = 0;
+
+ if (hsic_enable_gpio != -1)
+ enable_gpio = gpio_request(hsic_enable_gpio, "uhsic_enable");
+ if (hsic_reset_gpio != -1)
+ reset_gpio = gpio_request(hsic_reset_gpio, "uhsic_reset");
+ /* hsic enable signal deasserted, hsic reset asserted */
+ if (!enable_gpio)
+ 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 */
+ if (!enable_gpio)
+ gpio_set_value_cansleep(hsic_enable_gpio, 1);
+ udelay(1000);
+ /* deassert reset */
+ if (!reset_gpio)
+ gpio_set_value_cansleep(hsic_reset_gpio, 1);
+
+}
+
+void hsic_platform_close(void)
+{
+ if (hsic_enable_gpio != -1) {
+ gpio_set_value(hsic_enable_gpio, 0);
+ gpio_free(hsic_enable_gpio);
+ }
+ if (hsic_reset_gpio != -1) {
+ gpio_set_value(hsic_reset_gpio, 0);
+ gpio_free(hsic_reset_gpio);
+ }
+}
+
+void hsic_power_on(void)
+{
+ if (hsic_enable_gpio != -1) {
+ gpio_set_value_cansleep(hsic_enable_gpio, 1);
+ udelay(1000);
+ }
+}
+
+void hsic_power_off(void)
+{
+ if (hsic_enable_gpio != -1) {
+ gpio_set_value_cansleep(hsic_enable_gpio, 0);
+ udelay(1000);
+ }
+}
+
+#if defined(CONFIG_USB_SUPPORT)
+static struct tegra_usb_phy_platform_ops hsic_plat_ops = {
+ .open = hsic_platform_open,
+ .close = hsic_platform_close,
+ .pre_phy_on = hsic_power_on,
+ .post_phy_off = hsic_power_off,
+};
+
+static struct tegra_usb_platform_data tegra_ehci2_hsic_pdata = {
+ .port_otg = false,
+ .has_hostpc = true,
+ .phy_intf = TEGRA_USB_PHY_INTF_HSIC,
+ .op_mode = TEGRA_USB_OPMODE_HOST,
+ .u_data.host = {
+ .vbus_gpio = -1,
+ .hot_plug = false,
+ .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,
+};
+
+static struct tegra_usb_platform_data tegra_udc_pdata = {
+ .port_otg = true,
+ .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,
+ .elastic_limit = 16,
+ .idle_wait_delay = 17,
+ .term_range_adj = 6,
+ .xcvr_setup = 8,
+ .xcvr_lsfslew = 2,
+ .xcvr_lsrslew = 2,
+ .xcvr_setup_offset = 0,
+ .xcvr_use_fuses = 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,
+ .hot_plug = false,
+ .remote_wakeup_supported = true,
+ .power_off_on_suspend = true,
+ },
+ .u_cfg.utmi = {
+ .hssync_start_delay = 0,
+ .elastic_limit = 16,
+ .idle_wait_delay = 17,
+ .term_range_adj = 6,
+ .xcvr_setup = 15,
+ .xcvr_lsfslew = 2,
+ .xcvr_lsrslew = 2,
+ .xcvr_setup_offset = 0,
+ .xcvr_use_fuses = 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 = "vdd_vbus_typea_usb",
+ .hot_plug = true,
+ .remote_wakeup_supported = true,
+ .power_off_on_suspend = true,
+ },
+ .u_cfg.utmi = {
+ .hssync_start_delay = 0,
+ .elastic_limit = 16,
+ .idle_wait_delay = 17,
+ .term_range_adj = 6,
+ .xcvr_setup = 8,
+ .xcvr_lsfslew = 2,
+ .xcvr_lsrslew = 2,
+ .xcvr_setup_offset = 0,
+ .xcvr_use_fuses = 1,
+ },
+};
+
+static struct tegra_usb_platform_data tegra_ehci1_utmi_pdata = {
+ .port_otg = true,
+ .has_hostpc = true,
+ .phy_intf = TEGRA_USB_PHY_INTF_UTMI,
+ .op_mode = TEGRA_USB_OPMODE_HOST,
+ .u_data.host = {
+ .vbus_gpio = -1,
+ .vbus_reg = "vdd_vbus_micro_usb",
+ .hot_plug = true,
+ .remote_wakeup_supported = true,
+ .power_off_on_suspend = true,
+ },
+ .u_cfg.utmi = {
+ .hssync_start_delay = 0,
+ .elastic_limit = 16,
+ .idle_wait_delay = 17,
+ .term_range_adj = 6,
+ .xcvr_setup = 15,
+ .xcvr_lsfslew = 2,
+ .xcvr_lsrslew = 2,
+ .xcvr_setup_offset = 0,
+ .xcvr_use_fuses = 1,
+ },
+};
+
+static struct tegra_usb_otg_data tegra_otg_pdata = {
+ .ehci_device = &tegra_ehci1_device,
+ .ehci_pdata = &tegra_ehci1_utmi_pdata,
+};
+#endif
+
+#if defined(CONFIG_USB_SUPPORT)
static void cardhu_usb_init(void)
{
struct board_info bi;
tegra_get_board_info(&bi);
- tegra_usb_phy_init(tegra_usb_phy_pdata,
- ARRAY_SIZE(tegra_usb_phy_pdata));
-
+ /* OTG should be the first to be registered */
tegra_otg_device.dev.platform_data = &tegra_otg_pdata;
platform_device_register(&tegra_otg_device);
+
+ /* setup the udc platform data */
+ tegra_udc_device.dev.platform_data = &tegra_udc_pdata;
+
if (bi.board_id == BOARD_PM267) {
- uhsic_phy_config.reset_gpio =
- PM267_SMSC4640_HSIC_HUB_RESET_GPIO;
- tegra_ehci2_device.dev.platform_data = &tegra_ehci_uhsic_pdata;
+ hsic_enable_gpio = EN_HSIC_GPIO;
+ hsic_reset_gpio = PM267_SMSC4640_HSIC_HUB_RESET_GPIO;
+ tegra_ehci2_device.dev.platform_data = &tegra_ehci2_hsic_pdata;
platform_device_register(&tegra_ehci2_device);
} else if (bi.board_id == BOARD_E1256) {
- tegra_ehci2_device.dev.platform_data = &tegra_ehci_uhsic_pdata;
+ hsic_enable_gpio = EN_HSIC_GPIO;
+ tegra_ehci2_device.dev.platform_data = &tegra_ehci2_hsic_pdata;
platform_device_register(&tegra_ehci2_device);
} else if (bi.board_id == BOARD_E1186) {
- /* for baseband devices do not switch off phy during suspend */
- tegra_ehci_uhsic_pdata.power_down_on_bus_suspend = 0;
- uhsic_phy_config.postsuspend = cardhu_usb_hsic_postsupend;
- uhsic_phy_config.preresume = cardhu_usb_hsic_preresume;
- uhsic_phy_config.usb_phy_ready = cardhu_usb_hsic_phy_ready;
- uhsic_phy_config.post_phy_off = cardhu_usb_hsic_phy_off;
- tegra_ehci2_device.dev.platform_data = &tegra_ehci_uhsic_pdata;
- /* baseband registration happens in baseband-xmm-power */
+ tegra_ehci2_device.dev.platform_data =
+ &tegra_ehci2_hsic_xmm_pdata;
+ /* ehci2 registration happens in baseband-xmm-power */
} else {
- tegra_ehci2_device.dev.platform_data = &tegra_ehci_pdata[1];
+ tegra_ehci2_device.dev.platform_data = &tegra_ehci2_utmi_pdata;
platform_device_register(&tegra_ehci2_device);
}
- tegra_ehci3_device.dev.platform_data = &tegra_ehci_pdata[2];
+ tegra_ehci3_device.dev.platform_data = &tegra_ehci3_utmi_pdata;
platform_device_register(&tegra_ehci3_device);
}
@@ -1007,19 +1252,6 @@ static void cardhu_usb_init(void)
static void cardhu_usb_init(void) { }
#endif
-static void cardhu_gps_init(void)
-{
- tegra_gpio_enable(TEGRA_GPIO_PU2);
- tegra_gpio_enable(TEGRA_GPIO_PU3);
-}
-
-static void cardhu_nfc_init(void)
-{
- tegra_gpio_enable(TEGRA_GPIO_PX0);
- tegra_gpio_enable(TEGRA_GPIO_PP3);
- tegra_gpio_enable(TEGRA_GPIO_PO7);
-}
-
static struct baseband_power_platform_data tegra_baseband_power_data = {
.baseband_type = BASEBAND_XMM,
.modem = {
@@ -1097,7 +1329,7 @@ static void cardhu_modem_init(void)
} else {
w_disable_gpio = TEGRA_GPIO_PDD5;
}
- tegra_gpio_enable(w_disable_gpio);
+
ret = gpio_request(w_disable_gpio, "w_disable_gpio");
if (ret < 0)
pr_err("%s: gpio_request failed for gpio %d\n",
@@ -1117,22 +1349,9 @@ static void cardhu_modem_init(void)
break;
}
gpio_direction_output(TEGRA_GPIO_PH7, 1);
- tegra_gpio_enable(TEGRA_GPIO_PH7);
}
break;
case BOARD_E1186:
- tegra_gpio_enable(
- tegra_baseband_power_data.modem.xmm.bb_rst);
- tegra_gpio_enable(
- tegra_baseband_power_data.modem.xmm.bb_on);
- tegra_gpio_enable(
- tegra_baseband_power_data.modem.xmm.ipc_bb_wake);
- tegra_gpio_enable(
- tegra_baseband_power_data.modem.xmm.ipc_ap_wake);
- tegra_gpio_enable(
- tegra_baseband_power_data.modem.xmm.ipc_hsic_active);
- tegra_gpio_enable(
- tegra_baseband_power_data.modem.xmm.ipc_hsic_sus_req);
platform_device_register(&tegra_baseband_power_device);
platform_device_register(&tegra_baseband_power2_device);
break;
@@ -1153,7 +1372,9 @@ static void cardhu_sata_init(void) { }
static void __init tegra_cardhu_init(void)
{
- tegra_thermal_init(&thermal_data);
+ tegra_thermal_init(&thermal_data,
+ throttle_list,
+ ARRAY_SIZE(throttle_list));
tegra_clk_init_from_table(cardhu_clk_init_table);
cardhu_pinmux_init();
cardhu_i2c_init();
@@ -1170,7 +1391,6 @@ static void __init tegra_cardhu_init(void)
cardhu_dtv_init();
cardhu_suspend_init();
cardhu_touch_init();
- cardhu_gps_init();
cardhu_modem_init();
cardhu_kbc_init();
cardhu_scroll_init();
@@ -1184,18 +1404,18 @@ static void __init tegra_cardhu_init(void)
cardhu_pins_state_init();
cardhu_emc_init();
tegra_release_bootloader_fb();
- cardhu_nfc_init();
cardhu_pci_init();
#ifdef CONFIG_TEGRA_WDT_RECOVERY
tegra_wdt_recovery_init();
#endif
+ tegra_serial_debug_init(TEGRA_UARTD_BASE, INT_WDT_CPU, NULL, -1, -1);
}
static void __init tegra_cardhu_reserve(void)
{
#if defined(CONFIG_NVMAP_CONVERT_CARVEOUT_TO_IOVMM)
- /* support 1920X1200 with 24bpp */
- tegra_reserve(0, SZ_8M + SZ_1M, SZ_8M + SZ_1M);
+ /* Support 1920X1080 32bpp,double buffered on HDMI*/
+ tegra_reserve(0, SZ_8M + SZ_1M, SZ_16M);
#else
tegra_reserve(SZ_128M, SZ_8M, SZ_8M);
#endif
diff --git a/arch/arm/mach-tegra/board-cardhu.h b/arch/arm/mach-tegra/board-cardhu.h
index ba2a0d05b46c..a8be32ec9cdd 100644
--- a/arch/arm/mach-tegra/board-cardhu.h
+++ b/arch/arm/mach-tegra/board-cardhu.h
@@ -76,10 +76,15 @@
#define BOARD_FAB_A03 0x3
#define BOARD_FAB_A04 0x4
#define BOARD_FAB_A05 0x5
+#define BOARD_FAB_A06 0x6
+#define BOARD_FAB_A07 0x7
/* Display Board ID */
#define BOARD_DISPLAY_PM313 0x030D
+#define BOARD_DISPLAY_E1213 0x0C0D
#define BOARD_DISPLAY_E1247 0x0C2F
+#define BOARD_DISPLAY_E1253 0x0C35
+#define BOARD_DISPLAY_E1506 0x0F06
/* External peripheral act as gpio */
/* TPS6591x GPIOs */
diff --git a/arch/arm/mach-tegra/board-enterprise-baseband.c b/arch/arm/mach-tegra/board-enterprise-baseband.c
index 7552e2871541..c73a7ad5e5b4 100644
--- a/arch/arm/mach-tegra/board-enterprise-baseband.c
+++ b/arch/arm/mach-tegra/board-enterprise-baseband.c
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-tegra/board-enterprise-baseband.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
@@ -22,15 +22,8 @@
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/gpio.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
#include <linux/err.h>
-#include <linux/wakelock.h>
#include <linux/platform_data/tegra_usb.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <mach/pinmux.h>
-#include <mach/usb_phy.h>
#include <mach/tegra_usb_modem_power.h>
#include "devices.h"
#include "gpio-names.h"
@@ -40,111 +33,63 @@
#define MODEM_RESET TEGRA_GPIO_PE1
#define BB_RST_OUT TEGRA_GPIO_PV1
-/* Icera BB GPIO */
+/* Icera modem handshaking GPIO */
#define AP2MDM_ACK TEGRA_GPIO_PE3
#define MDM2AP_ACK TEGRA_GPIO_PU5
#define AP2MDM_ACK2 TEGRA_GPIO_PE2
#define MDM2AP_ACK2 TEGRA_GPIO_PV0
-/* ULPI GPIO */
-#define ULPI_STP TEGRA_GPIO_PY3
-#define ULPI_DIR TEGRA_GPIO_PY1
-#define ULPI_D0 TEGRA_GPIO_PO1
-#define ULPI_D1 TEGRA_GPIO_PO2
-
-static struct wake_lock mdm_wake_lock;
-
static struct gpio modem_gpios[] = {
{MODEM_PWR_ON, GPIOF_OUT_INIT_LOW, "MODEM PWR ON"},
{MODEM_RESET, GPIOF_IN, "MODEM RESET"},
- {BB_RST_OUT, GPIOF_IN, "BB RST OUT"},
- {MDM2AP_ACK, GPIOF_IN, "MDM2AP_ACK"},
{AP2MDM_ACK2, GPIOF_OUT_INIT_HIGH, "AP2MDM ACK2"},
{AP2MDM_ACK, GPIOF_OUT_INIT_LOW, "AP2MDM ACK"},
- {ULPI_STP, GPIOF_IN, "ULPI_STP"},
- {ULPI_DIR, GPIOF_OUT_INIT_LOW, "ULPI_DIR"},
- {ULPI_D0, GPIOF_OUT_INIT_LOW, "ULPI_D0"},
- {ULPI_D1, GPIOF_OUT_INIT_LOW, "ULPI_D1"},
};
-static int baseband_phy_on(void);
-static int baseband_phy_off(void);
-static void baseband_phy_restore_start(void);
-static void baseband_phy_restore_end(void);
-
-static struct tegra_ulpi_trimmer e1219_trimmer = { 10, 1, 1, 1 };
-
-static struct tegra_ulpi_config ehci2_null_ulpi_phy_config = {
- .trimmer = &e1219_trimmer,
- .post_phy_on = baseband_phy_on,
- .pre_phy_off = baseband_phy_off,
- .phy_restore_start = baseband_phy_restore_start,
- .phy_restore_end = baseband_phy_restore_end,
- .phy_restore_gpio = MDM2AP_ACK,
- .ulpi_dir_gpio = ULPI_DIR,
- .ulpi_d0_gpio = ULPI_D0,
- .ulpi_d1_gpio = ULPI_D1,
-};
+static void baseband_post_phy_on(void);
+static void baseband_pre_phy_off(void);
-static struct tegra_ehci_platform_data ehci2_null_ulpi_platform_data = {
- .operating_mode = TEGRA_USB_HOST,
- .power_down_on_bus_suspend = 0,
- .phy_config = &ehci2_null_ulpi_phy_config,
- .phy_type = TEGRA_USB_PHY_TYPE_NULL_ULPI,
+static struct tegra_usb_phy_platform_ops ulpi_null_plat_ops = {
+ .pre_phy_off = baseband_pre_phy_off,
+ .post_phy_on = baseband_post_phy_on,
};
-static int __init tegra_null_ulpi_init(void)
-{
- tegra_ehci2_device.dev.platform_data = &ehci2_null_ulpi_platform_data;
- platform_device_register(&tegra_ehci2_device);
- return 0;
-}
-
-static irqreturn_t mdm_start_thread(int irq, void *data)
-{
- if (gpio_get_value(BB_RST_OUT)) {
- pr_info("BB_RST_OUT high\n");
- } else {
- pr_info("BB_RST_OUT low\n");
- }
-
- /* hold wait lock to complete the enumeration */
- wake_lock_timeout(&mdm_wake_lock, HZ * 10);
-
- return IRQ_HANDLED;
-}
-
-static int baseband_phy_on(void)
-{
- static bool phy_init = false;
-
- if (!phy_init) {
- /* set AP2MDM_ACK2 low */
- gpio_set_value(AP2MDM_ACK2, 0);
- phy_init = true;
- }
- pr_info("%s\n", __func__);
- return 0;
-}
+static struct tegra_usb_platform_data tegra_ehci2_ulpi_null_pdata = {
+ .port_otg = false,
+ .has_hostpc = true,
+ .phy_intf = TEGRA_USB_PHY_INTF_ULPI_NULL,
+ .op_mode = TEGRA_USB_OPMODE_HOST,
+ .u_data.host = {
+ .vbus_gpio = -1,
+ .vbus_reg = NULL,
+ .hot_plug = true,
+ .remote_wakeup_supported = false,
+ .power_off_on_suspend = true,
+ },
+ .u_cfg.ulpi = {
+ .shadow_clk_delay = 10,
+ .clock_out_delay = 1,
+ .data_trimmer = 1,
+ .stpdirnxt_trimmer = 1,
+ .dir_trimmer = 1,
+ .clk = NULL,
+ .phy_restore_gpio = MDM2AP_ACK,
+ },
+ .ops = &ulpi_null_plat_ops,
+};
-static int baseband_phy_off(void)
+static void baseband_post_phy_on(void)
{
- pr_info("%s\n", __func__);
- return 0;
+ /* set AP2MDM_ACK2 low */
+ gpio_set_value(AP2MDM_ACK2, 0);
}
-static void baseband_phy_restore_start(void)
+static void baseband_pre_phy_off(void)
{
/* set AP2MDM_ACK2 high */
gpio_set_value(AP2MDM_ACK2, 1);
}
-static void baseband_phy_restore_end(void)
-{
- /* set AP2MDM_ACK2 low */
- gpio_set_value(AP2MDM_ACK2, 0);
-}
-
static void baseband_start(void)
{
/*
@@ -166,7 +111,6 @@ static void baseband_reset(void)
static int baseband_init(void)
{
- int irq;
int ret;
ret = gpio_request_array(modem_gpios, ARRAY_SIZE(modem_gpios));
@@ -181,42 +125,9 @@ static int baseband_init(void)
tegra_pinmux_set_pullupdown(TEGRA_PINGROUP_GPIO_PV0,
TEGRA_PUPD_PULL_UP);
- tegra_gpio_enable(MODEM_PWR_ON);
- tegra_gpio_enable(MODEM_RESET);
- tegra_gpio_enable(AP2MDM_ACK2);
- tegra_gpio_enable(BB_RST_OUT);
- tegra_gpio_enable(AP2MDM_ACK);
- tegra_gpio_enable(MDM2AP_ACK);
- tegra_gpio_enable(TEGRA_GPIO_PY3);
- tegra_gpio_enable(TEGRA_GPIO_PO1);
- tegra_gpio_enable(TEGRA_GPIO_PO2);
-
/* export GPIO for user space access through sysfs */
gpio_export(MODEM_PWR_ON, false);
- /* phy init */
- tegra_null_ulpi_init();
-
- wake_lock_init(&mdm_wake_lock, WAKE_LOCK_SUSPEND, "mdm_lock");
-
- /* enable IRQ for BB_RST_OUT */
- irq = gpio_to_irq(BB_RST_OUT);
-
- ret = request_threaded_irq(irq, NULL, mdm_start_thread,
- IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
- "mdm_start", NULL);
- if (ret < 0) {
- pr_err("%s: request_threaded_irq error\n", __func__);
- return ret;
- }
-
- ret = enable_irq_wake(irq);
- if (ret) {
- pr_err("%s: enable_irq_wake error\n", __func__);
- free_irq(irq, NULL);
- return ret;
- }
-
return 0;
}
@@ -229,7 +140,13 @@ static const struct tegra_modem_operations baseband_operations = {
static struct tegra_usb_modem_power_platform_data baseband_pdata = {
.ops = &baseband_operations,
.wake_gpio = MDM2AP_ACK2,
- .flags = IRQF_TRIGGER_FALLING,
+ .wake_irq_flags = IRQF_TRIGGER_FALLING,
+ .boot_gpio = BB_RST_OUT,
+ .boot_irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ .autosuspend_delay = 2000,
+ .short_autosuspend_delay = 50,
+ .tegra_ehci_device = &tegra_ehci2_device,
+ .tegra_ehci_pdata = &tegra_ehci2_ulpi_null_pdata,
};
static struct platform_device icera_baseband_device = {
diff --git a/arch/arm/mach-tegra/board-enterprise-memory.c b/arch/arm/mach-tegra/board-enterprise-memory.c
index fca1a08ed701..36a8264c2a21 100644
--- a/arch/arm/mach-tegra/board-enterprise-memory.c
+++ b/arch/arm/mach-tegra/board-enterprise-memory.c
@@ -24,7 +24,7 @@
#include "board.h"
-static const struct tegra_emc_table enterprise_emc_tables_h5tc2g[] = {
+static const struct tegra_emc_table enterprise_emc_tables_kmmll0_a02[] = {
{
0x32, /* Rev 3.2 */
12750, /* SDRAM frequency */
@@ -717,7 +717,7 @@ static const struct tegra_emc_table enterprise_emc_tables_h5tc2g[] = {
0x00000000, /* EMC_CTT_DURATION */
0x80000ce6, /* EMC_DYN_SELF_REF_CONTROL */
0x00000006, /* MC_EMEM_ARB_CFG */
- 0x80000048, /* MC_EMEM_ARB_OUTSTANDING_REQ */
+ 0xc0000048, /* MC_EMEM_ARB_OUTSTANDING_REQ */
0x00000002, /* MC_EMEM_ARB_TIMING_RCD */
0x00000003, /* MC_EMEM_ARB_TIMING_RP */
0x0000000c, /* MC_EMEM_ARB_TIMING_RC */
@@ -747,6 +747,729 @@ static const struct tegra_emc_table enterprise_emc_tables_h5tc2g[] = {
},
};
+static const struct tegra_emc_table enterprise_emc_tables_kmkts0_a03[] = {
+ {
+ 0x32, /* Rev 3.2 */
+ 12750, /* SDRAM frequency */
+ {
+ 0x00000000, /* EMC_RC */
+ 0x00000001, /* EMC_RFC */
+ 0x00000002, /* EMC_RAS */
+ 0x00000002, /* EMC_RP */
+ 0x00000004, /* EMC_R2W */
+ 0x00000004, /* EMC_W2R */
+ 0x00000001, /* EMC_R2P */
+ 0x00000005, /* EMC_W2P */
+ 0x00000002, /* EMC_RD_RCD */
+ 0x00000002, /* EMC_WR_RCD */
+ 0x00000001, /* EMC_RRD */
+ 0x00000001, /* EMC_REXT */
+ 0x00000000, /* EMC_WEXT */
+ 0x00000001, /* EMC_WDV */
+ 0x00000003, /* EMC_QUSE */
+ 0x00000001, /* EMC_QRST */
+ 0x0000000b, /* EMC_QSAFE */
+ 0x0000000a, /* EMC_RDV */
+ 0x0000002f, /* EMC_REFRESH */
+ 0x00000000, /* EMC_BURST_REFRESH_NUM */
+ 0x0000000b, /* EMC_PRE_REFRESH_REQ_CNT */
+ 0x00000001, /* EMC_PDEX2WR */
+ 0x00000001, /* EMC_PDEX2RD */
+ 0x00000002, /* EMC_PCHG2PDEN */
+ 0x00000000, /* EMC_ACT2PDEN */
+ 0x00000001, /* EMC_AR2PDEN */
+ 0x00000007, /* EMC_RW2PDEN */
+ 0x00000002, /* EMC_TXSR */
+ 0x00000002, /* EMC_TXSRDLL */
+ 0x00000003, /* EMC_TCKE */
+ 0x00000008, /* EMC_TFAW */
+ 0x00000004, /* EMC_TRPAB */
+ 0x00000001, /* EMC_TCLKSTABLE */
+ 0x00000002, /* EMC_TCLKSTOP */
+ 0x00000036, /* EMC_TREFBW */
+ 0x00000004, /* EMC_QUSE_EXTRA */
+ 0x00000006, /* EMC_FBIO_CFG6 */
+ 0x00000000, /* EMC_ODT_WRITE */
+ 0x00000000, /* EMC_ODT_READ */
+ 0x00004282, /* 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 */
+ 0x00100220, /* EMC_XM2CMDPADCTRL */
+ 0x0800201c, /* EMC_XM2DQSPADCTRL2 */
+ 0x00000000, /* EMC_XM2DQPADCTRL2 */
+ 0x77ffc004, /* EMC_XM2CLKPADCTRL */
+ 0x01f1f008, /* EMC_XM2COMPPADCTRL */
+ 0x00000000, /* EMC_XM2VTTGENPADCTRL */
+ 0x00000007, /* EMC_XM2VTTGENPADCTRL2 */
+ 0x08000068, /* EMC_XM2QUSEPADCTRL */
+ 0x08000000, /* EMC_XM2DQSPADCTRL3 */
+ 0x00000802, /* EMC_CTT_TERM_CTRL */
+ 0x00064000, /* EMC_ZCAL_INTERVAL */
+ 0x00000009, /* EMC_ZCAL_WAIT_CNT */
+ 0x00090009, /* EMC_MRS_WAIT_CNT */
+ 0xa0f10000, /* EMC_AUTO_CAL_CONFIG */
+ 0x00000000, /* EMC_CTT */
+ 0x00000000, /* EMC_CTT_DURATION */
+ 0x80000164, /* EMC_DYN_SELF_REF_CONTROL */
+ 0x00050001, /* MC_EMEM_ARB_CFG */
+ 0xc0000008, /* 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 */
+ 0x00000003, /* MC_EMEM_ARB_TIMING_FAW */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_RRD */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_RAP2PRE */
+ 0x00000004, /* MC_EMEM_ARB_TIMING_WAP2PRE */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_R2R */
+ 0x00000000, /* MC_EMEM_ARB_TIMING_W2W */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_R2W */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_W2R */
+ 0x02020001, /* MC_EMEM_ARB_DA_TURNS */
+ 0x00060402, /* MC_EMEM_ARB_DA_COVERS */
+ 0x77230303, /* MC_EMEM_ARB_MISC0 */
+ 0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */
+ 0xe0000000, /* EMC_FBIO_SPARE */
+ 0xff00ff00, /* EMC_CFG_RSV */
+ },
+ 0x00000009, /* EMC_ZCAL_WAIT_CNT after clock change */
+ 0x001fffff, /* EMC_AUTO_CAL_INTERVAL */
+ 0x00000001, /* EMC_CFG.PERIODIC_QRST */
+ 0x00000000, /* Mode Register 0 */
+ 0x00010022, /* Mode Register 1 */
+ 0x00020001, /* Mode Register 2 */
+ 0x00000001, /* EMC_CFG.DYN_SELF_REF */
+ },
+ {
+ 0x32, /* Rev 3.2 */
+ 25500, /* SDRAM frequency */
+ {
+ 0x00000001, /* EMC_RC */
+ 0x00000003, /* EMC_RFC */
+ 0x00000002, /* EMC_RAS */
+ 0x00000002, /* EMC_RP */
+ 0x00000004, /* EMC_R2W */
+ 0x00000004, /* EMC_W2R */
+ 0x00000001, /* EMC_R2P */
+ 0x00000005, /* EMC_W2P */
+ 0x00000002, /* EMC_RD_RCD */
+ 0x00000002, /* EMC_WR_RCD */
+ 0x00000001, /* EMC_RRD */
+ 0x00000001, /* EMC_REXT */
+ 0x00000000, /* EMC_WEXT */
+ 0x00000001, /* EMC_WDV */
+ 0x00000003, /* EMC_QUSE */
+ 0x00000001, /* EMC_QRST */
+ 0x0000000b, /* EMC_QSAFE */
+ 0x0000000a, /* EMC_RDV */
+ 0x00000060, /* EMC_REFRESH */
+ 0x00000000, /* EMC_BURST_REFRESH_NUM */
+ 0x00000018, /* EMC_PRE_REFRESH_REQ_CNT */
+ 0x00000001, /* EMC_PDEX2WR */
+ 0x00000001, /* EMC_PDEX2RD */
+ 0x00000002, /* EMC_PCHG2PDEN */
+ 0x00000000, /* EMC_ACT2PDEN */
+ 0x00000001, /* EMC_AR2PDEN */
+ 0x00000007, /* EMC_RW2PDEN */
+ 0x00000004, /* EMC_TXSR */
+ 0x00000004, /* EMC_TXSRDLL */
+ 0x00000003, /* EMC_TCKE */
+ 0x00000008, /* EMC_TFAW */
+ 0x00000004, /* EMC_TRPAB */
+ 0x00000001, /* EMC_TCLKSTABLE */
+ 0x00000002, /* EMC_TCLKSTOP */
+ 0x0000006b, /* EMC_TREFBW */
+ 0x00000004, /* EMC_QUSE_EXTRA */
+ 0x00000006, /* EMC_FBIO_CFG6 */
+ 0x00000000, /* EMC_ODT_WRITE */
+ 0x00000000, /* EMC_ODT_READ */
+ 0x00004282, /* 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 */
+ 0x00100220, /* EMC_XM2CMDPADCTRL */
+ 0x0800201c, /* EMC_XM2DQSPADCTRL2 */
+ 0x00000000, /* EMC_XM2DQPADCTRL2 */
+ 0x77ffc004, /* EMC_XM2CLKPADCTRL */
+ 0x01f1f008, /* EMC_XM2COMPPADCTRL */
+ 0x00000000, /* EMC_XM2VTTGENPADCTRL */
+ 0x00000007, /* EMC_XM2VTTGENPADCTRL2 */
+ 0x08000068, /* EMC_XM2QUSEPADCTRL */
+ 0x08000000, /* EMC_XM2DQSPADCTRL3 */
+ 0x00000802, /* EMC_CTT_TERM_CTRL */
+ 0x00064000, /* EMC_ZCAL_INTERVAL */
+ 0x0000000a, /* EMC_ZCAL_WAIT_CNT */
+ 0x00090009, /* EMC_MRS_WAIT_CNT */
+ 0xa0f10000, /* EMC_AUTO_CAL_CONFIG */
+ 0x00000000, /* EMC_CTT */
+ 0x00000000, /* EMC_CTT_DURATION */
+ 0x800001c5, /* EMC_DYN_SELF_REF_CONTROL */
+ 0x00020001, /* MC_EMEM_ARB_CFG */
+ 0xc0000008, /* 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 */
+ 0x00000003, /* MC_EMEM_ARB_TIMING_FAW */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_RRD */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_RAP2PRE */
+ 0x00000004, /* MC_EMEM_ARB_TIMING_WAP2PRE */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_R2R */
+ 0x00000000, /* MC_EMEM_ARB_TIMING_W2W */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_R2W */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_W2R */
+ 0x02020001, /* MC_EMEM_ARB_DA_TURNS */
+ 0x00060402, /* MC_EMEM_ARB_DA_COVERS */
+ 0x73e30303, /* MC_EMEM_ARB_MISC0 */
+ 0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */
+ 0xe0000000, /* EMC_FBIO_SPARE */
+ 0xff00ff00, /* EMC_CFG_RSV */
+ },
+ 0x00000009, /* EMC_ZCAL_WAIT_CNT after clock change */
+ 0x001fffff, /* EMC_AUTO_CAL_INTERVAL */
+ 0x00000001, /* EMC_CFG.PERIODIC_QRST */
+ 0x00000000, /* Mode Register 0 */
+ 0x00010022, /* Mode Register 1 */
+ 0x00020001, /* Mode Register 2 */
+ 0x00000001, /* EMC_CFG.DYN_SELF_REF */
+ },
+ {
+ 0x32, /* Rev 3.2 */
+ 51000, /* SDRAM frequency */
+ {
+ 0x00000003, /* EMC_RC */
+ 0x00000006, /* EMC_RFC */
+ 0x00000002, /* EMC_RAS */
+ 0x00000002, /* EMC_RP */
+ 0x00000004, /* EMC_R2W */
+ 0x00000004, /* EMC_W2R */
+ 0x00000001, /* EMC_R2P */
+ 0x00000005, /* EMC_W2P */
+ 0x00000002, /* EMC_RD_RCD */
+ 0x00000002, /* EMC_WR_RCD */
+ 0x00000001, /* EMC_RRD */
+ 0x00000001, /* EMC_REXT */
+ 0x00000000, /* EMC_WEXT */
+ 0x00000001, /* EMC_WDV */
+ 0x00000003, /* EMC_QUSE */
+ 0x00000001, /* EMC_QRST */
+ 0x0000000b, /* EMC_QSAFE */
+ 0x0000000a, /* EMC_RDV */
+ 0x000000c0, /* EMC_REFRESH */
+ 0x00000000, /* EMC_BURST_REFRESH_NUM */
+ 0x00000030, /* EMC_PRE_REFRESH_REQ_CNT */
+ 0x00000001, /* EMC_PDEX2WR */
+ 0x00000001, /* EMC_PDEX2RD */
+ 0x00000002, /* EMC_PCHG2PDEN */
+ 0x00000000, /* EMC_ACT2PDEN */
+ 0x00000001, /* EMC_AR2PDEN */
+ 0x00000007, /* EMC_RW2PDEN */
+ 0x00000008, /* EMC_TXSR */
+ 0x00000008, /* EMC_TXSRDLL */
+ 0x00000003, /* EMC_TCKE */
+ 0x00000008, /* EMC_TFAW */
+ 0x00000004, /* EMC_TRPAB */
+ 0x00000001, /* EMC_TCLKSTABLE */
+ 0x00000002, /* EMC_TCLKSTOP */
+ 0x000000d5, /* EMC_TREFBW */
+ 0x00000004, /* EMC_QUSE_EXTRA */
+ 0x00000006, /* EMC_FBIO_CFG6 */
+ 0x00000000, /* EMC_ODT_WRITE */
+ 0x00000000, /* EMC_ODT_READ */
+ 0x00004282, /* 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 */
+ 0x00100220, /* EMC_XM2CMDPADCTRL */
+ 0x0800201c, /* EMC_XM2DQSPADCTRL2 */
+ 0x00000000, /* EMC_XM2DQPADCTRL2 */
+ 0x77ffc004, /* EMC_XM2CLKPADCTRL */
+ 0x01f1f008, /* EMC_XM2COMPPADCTRL */
+ 0x00000000, /* EMC_XM2VTTGENPADCTRL */
+ 0x00000007, /* EMC_XM2VTTGENPADCTRL2 */
+ 0x08000068, /* EMC_XM2QUSEPADCTRL */
+ 0x08000000, /* EMC_XM2DQSPADCTRL3 */
+ 0x00000802, /* EMC_CTT_TERM_CTRL */
+ 0x00064000, /* EMC_ZCAL_INTERVAL */
+ 0x00000013, /* EMC_ZCAL_WAIT_CNT */
+ 0x00090009, /* EMC_MRS_WAIT_CNT */
+ 0xa0f10000, /* EMC_AUTO_CAL_CONFIG */
+ 0x00000000, /* EMC_CTT */
+ 0x00000000, /* EMC_CTT_DURATION */
+ 0x80000287, /* EMC_DYN_SELF_REF_CONTROL */
+ 0x00010001, /* MC_EMEM_ARB_CFG */
+ 0xc000000a, /* 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 */
+ 0x00000003, /* MC_EMEM_ARB_TIMING_FAW */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_RRD */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_RAP2PRE */
+ 0x00000004, /* MC_EMEM_ARB_TIMING_WAP2PRE */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_R2R */
+ 0x00000000, /* MC_EMEM_ARB_TIMING_W2W */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_R2W */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_W2R */
+ 0x02020001, /* MC_EMEM_ARB_DA_TURNS */
+ 0x00060402, /* MC_EMEM_ARB_DA_COVERS */
+ 0x72c30303, /* MC_EMEM_ARB_MISC0 */
+ 0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */
+ 0xe0000000, /* EMC_FBIO_SPARE */
+ 0xff00ff00, /* EMC_CFG_RSV */
+ },
+ 0x00000009, /* EMC_ZCAL_WAIT_CNT after clock change */
+ 0x001fffff, /* EMC_AUTO_CAL_INTERVAL */
+ 0x00000001, /* EMC_CFG.PERIODIC_QRST */
+ 0x00000000, /* Mode Register 0 */
+ 0x00010022, /* Mode Register 1 */
+ 0x00020001, /* Mode Register 2 */
+ 0x00000001, /* EMC_CFG.DYN_SELF_REF */
+ },
+ {
+ 0x32, /* Rev 3.2 */
+ 102000, /* SDRAM frequency */
+ {
+ 0x00000006, /* EMC_RC */
+ 0x0000000d, /* EMC_RFC */
+ 0x00000004, /* EMC_RAS */
+ 0x00000002, /* EMC_RP */
+ 0x00000004, /* EMC_R2W */
+ 0x00000004, /* EMC_W2R */
+ 0x00000002, /* EMC_R2P */
+ 0x00000005, /* EMC_W2P */
+ 0x00000002, /* EMC_RD_RCD */
+ 0x00000002, /* EMC_WR_RCD */
+ 0x00000001, /* EMC_RRD */
+ 0x00000001, /* EMC_REXT */
+ 0x00000000, /* EMC_WEXT */
+ 0x00000001, /* EMC_WDV */
+ 0x00000003, /* EMC_QUSE */
+ 0x00000001, /* EMC_QRST */
+ 0x0000000b, /* EMC_QSAFE */
+ 0x0000000a, /* EMC_RDV */
+ 0x00000181, /* EMC_REFRESH */
+ 0x00000000, /* EMC_BURST_REFRESH_NUM */
+ 0x00000060, /* EMC_PRE_REFRESH_REQ_CNT */
+ 0x00000001, /* EMC_PDEX2WR */
+ 0x00000001, /* EMC_PDEX2RD */
+ 0x00000002, /* EMC_PCHG2PDEN */
+ 0x00000000, /* EMC_ACT2PDEN */
+ 0x00000001, /* EMC_AR2PDEN */
+ 0x00000007, /* EMC_RW2PDEN */
+ 0x0000000f, /* EMC_TXSR */
+ 0x0000000f, /* EMC_TXSRDLL */
+ 0x00000003, /* EMC_TCKE */
+ 0x00000008, /* EMC_TFAW */
+ 0x00000004, /* EMC_TRPAB */
+ 0x00000001, /* EMC_TCLKSTABLE */
+ 0x00000002, /* EMC_TCLKSTOP */
+ 0x000001a9, /* EMC_TREFBW */
+ 0x00000004, /* EMC_QUSE_EXTRA */
+ 0x00000006, /* EMC_FBIO_CFG6 */
+ 0x00000000, /* EMC_ODT_WRITE */
+ 0x00000000, /* EMC_ODT_READ */
+ 0x00004282, /* 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 */
+ 0x00100220, /* EMC_XM2CMDPADCTRL */
+ 0x0800201c, /* EMC_XM2DQSPADCTRL2 */
+ 0x00000000, /* EMC_XM2DQPADCTRL2 */
+ 0x77ffc004, /* EMC_XM2CLKPADCTRL */
+ 0x01f1f008, /* EMC_XM2COMPPADCTRL */
+ 0x00000000, /* EMC_XM2VTTGENPADCTRL */
+ 0x00000007, /* EMC_XM2VTTGENPADCTRL2 */
+ 0x08000068, /* EMC_XM2QUSEPADCTRL */
+ 0x08000000, /* EMC_XM2DQSPADCTRL3 */
+ 0x00000802, /* EMC_CTT_TERM_CTRL */
+ 0x00000000, /* EMC_ZCAL_INTERVAL */
+ 0x0000000a, /* EMC_ZCAL_WAIT_CNT */
+ 0x00090009, /* EMC_MRS_WAIT_CNT */
+ 0xa0f10000, /* EMC_AUTO_CAL_CONFIG */
+ 0x00000000, /* EMC_CTT */
+ 0x00000000, /* EMC_CTT_DURATION */
+ 0x8000040b, /* EMC_DYN_SELF_REF_CONTROL */
+ 0x00000001, /* MC_EMEM_ARB_CFG */
+ 0xc0000013, /* MC_EMEM_ARB_OUTSTANDING_REQ */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */
+ 0x00000003, /* MC_EMEM_ARB_TIMING_RC */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_RAS */
+ 0x00000003, /* MC_EMEM_ARB_TIMING_FAW */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_RRD */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_RAP2PRE */
+ 0x00000004, /* MC_EMEM_ARB_TIMING_WAP2PRE */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_R2R */
+ 0x00000000, /* MC_EMEM_ARB_TIMING_W2W */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_R2W */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_W2R */
+ 0x02020001, /* MC_EMEM_ARB_DA_TURNS */
+ 0x00060403, /* MC_EMEM_ARB_DA_COVERS */
+ 0x72430504, /* MC_EMEM_ARB_MISC0 */
+ 0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */
+ 0xe0000000, /* EMC_FBIO_SPARE */
+ 0xff00ff00, /* EMC_CFG_RSV */
+ },
+ 0x0000000a, /* EMC_ZCAL_WAIT_CNT after clock change */
+ 0x001fffff, /* EMC_AUTO_CAL_INTERVAL */
+ 0x00000001, /* EMC_CFG.PERIODIC_QRST */
+ 0x00000000, /* Mode Register 0 */
+ 0x00010022, /* Mode Register 1 */
+ 0x00020001, /* Mode Register 2 */
+ 0x00000001, /* EMC_CFG.DYN_SELF_REF */
+ },
+ {
+ 0x32, /* Rev 3.2 */
+ 204000, /* SDRAM frequency */
+ {
+ 0x0000000c, /* EMC_RC */
+ 0x0000001a, /* EMC_RFC */
+ 0x00000008, /* EMC_RAS */
+ 0x00000003, /* EMC_RP */
+ 0x00000005, /* EMC_R2W */
+ 0x00000004, /* EMC_W2R */
+ 0x00000002, /* EMC_R2P */
+ 0x00000006, /* EMC_W2P */
+ 0x00000003, /* EMC_RD_RCD */
+ 0x00000003, /* EMC_WR_RCD */
+ 0x00000002, /* EMC_RRD */
+ 0x00000002, /* EMC_REXT */
+ 0x00000000, /* EMC_WEXT */
+ 0x00000001, /* EMC_WDV */
+ 0x00000003, /* EMC_QUSE */
+ 0x00000001, /* EMC_QRST */
+ 0x0000000c, /* EMC_QSAFE */
+ 0x0000000b, /* EMC_RDV */
+ 0x00000303, /* EMC_REFRESH */
+ 0x00000000, /* EMC_BURST_REFRESH_NUM */
+ 0x000000c0, /* EMC_PRE_REFRESH_REQ_CNT */
+ 0x00000001, /* EMC_PDEX2WR */
+ 0x00000001, /* EMC_PDEX2RD */
+ 0x00000003, /* EMC_PCHG2PDEN */
+ 0x00000000, /* EMC_ACT2PDEN */
+ 0x00000001, /* EMC_AR2PDEN */
+ 0x00000007, /* EMC_RW2PDEN */
+ 0x0000001d, /* EMC_TXSR */
+ 0x0000001d, /* EMC_TXSRDLL */
+ 0x00000004, /* EMC_TCKE */
+ 0x0000000b, /* EMC_TFAW */
+ 0x00000005, /* EMC_TRPAB */
+ 0x00000001, /* EMC_TCLKSTABLE */
+ 0x00000002, /* EMC_TCLKSTOP */
+ 0x00000351, /* EMC_TREFBW */
+ 0x00000004, /* EMC_QUSE_EXTRA */
+ 0x00000006, /* EMC_FBIO_CFG6 */
+ 0x00000000, /* EMC_ODT_WRITE */
+ 0x00000000, /* EMC_ODT_READ */
+ 0x00004282, /* EMC_FBIO_CFG5 */
+ 0x004400a4, /* EMC_CFG_DIG_DLL */
+ 0x00008000, /* EMC_CFG_DIG_DLL_PERIOD */
+ 0x0007c000, /* EMC_DLL_XFORM_DQS0 */
+ 0x0007c000, /* EMC_DLL_XFORM_DQS1 */
+ 0x0007c000, /* EMC_DLL_XFORM_DQS2 */
+ 0x0007c000, /* EMC_DLL_XFORM_DQS3 */
+ 0x00072000, /* EMC_DLL_XFORM_DQS4 */
+ 0x00072000, /* EMC_DLL_XFORM_DQS5 */
+ 0x00072000, /* EMC_DLL_XFORM_DQS6 */
+ 0x00072000, /* 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 */
+ 0x00088000, /* EMC_DLL_XFORM_DQ0 */
+ 0x00088000, /* EMC_DLL_XFORM_DQ1 */
+ 0x00088000, /* EMC_DLL_XFORM_DQ2 */
+ 0x00088000, /* EMC_DLL_XFORM_DQ3 */
+ 0x000e0220, /* EMC_XM2CMDPADCTRL */
+ 0x0800201c, /* EMC_XM2DQSPADCTRL2 */
+ 0x00000000, /* EMC_XM2DQPADCTRL2 */
+ 0x77ffc004, /* EMC_XM2CLKPADCTRL */
+ 0x01f1f008, /* EMC_XM2COMPPADCTRL */
+ 0x00000000, /* EMC_XM2VTTGENPADCTRL */
+ 0x00000007, /* EMC_XM2VTTGENPADCTRL2 */
+ 0x08000068, /* EMC_XM2QUSEPADCTRL */
+ 0x08000000, /* EMC_XM2DQSPADCTRL3 */
+ 0x00000802, /* EMC_CTT_TERM_CTRL */
+ 0x00000000, /* EMC_ZCAL_INTERVAL */
+ 0x00000013, /* EMC_ZCAL_WAIT_CNT */
+ 0x00090009, /* 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 */
+ 0xc0000025, /* MC_EMEM_ARB_OUTSTANDING_REQ */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_RCD */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_RP */
+ 0x00000006, /* MC_EMEM_ARB_TIMING_RC */
+ 0x00000003, /* MC_EMEM_ARB_TIMING_RAS */
+ 0x00000005, /* MC_EMEM_ARB_TIMING_FAW */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_RRD */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_RAP2PRE */
+ 0x00000004, /* MC_EMEM_ARB_TIMING_WAP2PRE */
+ 0x00000001, /* MC_EMEM_ARB_TIMING_R2R */
+ 0x00000000, /* MC_EMEM_ARB_TIMING_W2W */
+ 0x00000003, /* MC_EMEM_ARB_TIMING_R2W */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_W2R */
+ 0x02030001, /* MC_EMEM_ARB_DA_TURNS */
+ 0x00070506, /* MC_EMEM_ARB_DA_COVERS */
+ 0x71e40a07, /* MC_EMEM_ARB_MISC0 */
+ 0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */
+ 0xe0000000, /* EMC_FBIO_SPARE */
+ 0xff00ff00, /* EMC_CFG_RSV */
+ },
+ 0x00000013, /* EMC_ZCAL_WAIT_CNT after clock change */
+ 0x001fffff, /* EMC_AUTO_CAL_INTERVAL */
+ 0x00000001, /* EMC_CFG.PERIODIC_QRST */
+ 0x00000000, /* Mode Register 0 */
+ 0x00010042, /* Mode Register 1 */
+ 0x00020001, /* Mode Register 2 */
+ 0x00000001, /* EMC_CFG.DYN_SELF_REF */
+ },
+ {
+ 0x32, /* Rev 3.2 */
+ 533000, /* SDRAM frequency */
+ {
+ 0x0000001f, /* EMC_RC */
+ 0x00000045, /* EMC_RFC */
+ 0x00000016, /* EMC_RAS */
+ 0x00000009, /* EMC_RP */
+ 0x00000008, /* EMC_R2W */
+ 0x00000009, /* EMC_W2R */
+ 0x00000004, /* EMC_R2P */
+ 0x0000000d, /* EMC_W2P */
+ 0x00000009, /* EMC_RD_RCD */
+ 0x00000009, /* EMC_WR_RCD */
+ 0x00000005, /* EMC_RRD */
+ 0x00000003, /* EMC_REXT */
+ 0x00000000, /* EMC_WEXT */
+ 0x00000004, /* EMC_WDV */
+ 0x00000009, /* EMC_QUSE */
+ 0x00000006, /* EMC_QRST */
+ 0x0000000d, /* EMC_QSAFE */
+ 0x00000010, /* EMC_RDV */
+ 0x000007e1, /* EMC_REFRESH */
+ 0x00000000, /* EMC_BURST_REFRESH_NUM */
+ 0x000001f8, /* EMC_PRE_REFRESH_REQ_CNT */
+ 0x00000003, /* EMC_PDEX2WR */
+ 0x00000003, /* EMC_PDEX2RD */
+ 0x00000009, /* EMC_PCHG2PDEN */
+ 0x00000000, /* EMC_ACT2PDEN */
+ 0x00000001, /* EMC_AR2PDEN */
+ 0x0000000f, /* EMC_RW2PDEN */
+ 0x0000004b, /* EMC_TXSR */
+ 0x0000004b, /* EMC_TXSRDLL */
+ 0x00000008, /* EMC_TCKE */
+ 0x0000001b, /* EMC_TFAW */
+ 0x0000000c, /* EMC_TRPAB */
+ 0x00000001, /* EMC_TCLKSTABLE */
+ 0x00000002, /* EMC_TCLKSTOP */
+ 0x000008ab, /* EMC_TREFBW */
+ 0x00000000, /* EMC_QUSE_EXTRA */
+ 0x00000006, /* EMC_FBIO_CFG6 */
+ 0x00000000, /* EMC_ODT_WRITE */
+ 0x00000000, /* EMC_ODT_READ */
+ 0x00006282, /* EMC_FBIO_CFG5 */
+ 0xf0120091, /* 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 */
+ 0x0000000c, /* EMC_DLL_XFORM_DQ0 */
+ 0x0000000c, /* EMC_DLL_XFORM_DQ1 */
+ 0x0000000c, /* EMC_DLL_XFORM_DQ2 */
+ 0x0000000c, /* EMC_DLL_XFORM_DQ3 */
+ 0x000a0220, /* EMC_XM2CMDPADCTRL */
+ 0x0800003d, /* EMC_XM2DQSPADCTRL2 */
+ 0x00000000, /* EMC_XM2DQPADCTRL2 */
+ 0x77ffc004, /* EMC_XM2CLKPADCTRL */
+ 0x01f1f408, /* EMC_XM2COMPPADCTRL */
+ 0x00000000, /* EMC_XM2VTTGENPADCTRL */
+ 0x00000007, /* EMC_XM2VTTGENPADCTRL2 */
+ 0x08000068, /* EMC_XM2QUSEPADCTRL */
+ 0x08000000, /* EMC_XM2DQSPADCTRL3 */
+ 0x00000802, /* EMC_CTT_TERM_CTRL */
+ 0x00064000, /* EMC_ZCAL_INTERVAL */
+ 0x000000c0, /* EMC_ZCAL_WAIT_CNT */
+ 0x000e000e, /* EMC_MRS_WAIT_CNT */
+ 0xa0f10202, /* EMC_AUTO_CAL_CONFIG */
+ 0x00000000, /* EMC_CTT */
+ 0x00000000, /* EMC_CTT_DURATION */
+ 0x800010dc, /* EMC_DYN_SELF_REF_CONTROL */
+ 0x00000008, /* MC_EMEM_ARB_CFG */
+ 0x80000060, /* 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 */
+ 0x0000000d, /* MC_EMEM_ARB_TIMING_FAW */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_RRD */
+ 0x00000003, /* MC_EMEM_ARB_TIMING_RAP2PRE */
+ 0x00000008, /* MC_EMEM_ARB_TIMING_WAP2PRE */
+ 0x00000002, /* MC_EMEM_ARB_TIMING_R2R */
+ 0x00000000, /* MC_EMEM_ARB_TIMING_W2W */
+ 0x00000004, /* MC_EMEM_ARB_TIMING_R2W */
+ 0x00000005, /* MC_EMEM_ARB_TIMING_W2R */
+ 0x05040002, /* MC_EMEM_ARB_DA_TURNS */
+ 0x00110c10, /* MC_EMEM_ARB_DA_COVERS */
+ 0x70281811, /* MC_EMEM_ARB_MISC0 */
+ 0x001f0000, /* MC_EMEM_ARB_RING1_THROTTLE */
+ 0xe0000000, /* EMC_FBIO_SPARE */
+ 0xff00ff88, /* EMC_CFG_RSV */
+ },
+ 0x00000030, /* EMC_ZCAL_WAIT_CNT after clock change */
+ 0x001fffff, /* EMC_AUTO_CAL_INTERVAL */
+ 0x00000001, /* EMC_CFG.PERIODIC_QRST */
+ 0x00000000, /* Mode Register 0 */
+ 0x000100c2, /* Mode Register 1 */
+ 0x00020006, /* Mode Register 2 */
+ 0x00000000, /* EMC_CFG.DYN_SELF_REF */
+ },
+};
+
int enterprise_emc_init(void)
{
struct board_info board_info;
@@ -754,8 +1477,12 @@ int enterprise_emc_init(void)
tegra_get_board_info(&board_info);
if (board_info.fab <= BOARD_FAB_A02)
- tegra_init_emc(enterprise_emc_tables_h5tc2g,
- ARRAY_SIZE(enterprise_emc_tables_h5tc2g));
+ tegra_init_emc(enterprise_emc_tables_kmmll0_a02,
+ ARRAY_SIZE(enterprise_emc_tables_kmmll0_a02));
+ else
+ tegra_init_emc(enterprise_emc_tables_kmkts0_a03,
+ ARRAY_SIZE(enterprise_emc_tables_kmkts0_a03));
+
return 0;
}
diff --git a/arch/arm/mach-tegra/board-enterprise-panel.c b/arch/arm/mach-tegra/board-enterprise-panel.c
index 8ac2e665addb..837635bf0731 100644
--- a/arch/arm/mach-tegra/board-enterprise-panel.c
+++ b/arch/arm/mach-tegra/board-enterprise-panel.c
@@ -26,9 +26,10 @@
#include <linux/platform_device.h>
#include <linux/earlysuspend.h>
#include <linux/tegra_pwm_bl.h>
+#include <linux/pwm_backlight.h>
#include <asm/atomic.h>
#include <linux/nvhost.h>
-#include <mach/nvmap.h>
+#include <linux/nvmap.h>
#include <mach/irqs.h>
#include <mach/iomap.h>
#include <mach/dc.h>
@@ -39,6 +40,7 @@
#include "board-enterprise.h"
#include "devices.h"
#include "gpio-names.h"
+#include "tegra3_host1x_devices.h"
#define DC_CTRL_MODE TEGRA_DC_OUT_ONE_SHOT_MODE
@@ -61,6 +63,8 @@
#define enterprise_lcd_te TEGRA_GPIO_PJ1
+#define enterprise_bl_pwm TEGRA_GPIO_PH3
+
#ifdef CONFIG_TEGRA_DC
static struct regulator *enterprise_dsi_reg;
static bool dsi_regulator_status;
@@ -165,6 +169,17 @@ static int enterprise_backlight_notify(struct device *unused, int brightness)
static int enterprise_disp1_check_fb(struct device *dev, struct fb_info *info);
+#if IS_EXTERNAL_PWM
+static struct platform_pwm_backlight_data enterprise_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,
+};
+#else
/*
* In case which_pwm is TEGRA_PWM_PM0,
* gpio_conf_to_sfio should be TEGRA_GPIO_PW0: set LCD_CS1_N pin to SFIO
@@ -175,7 +190,6 @@ static struct platform_tegra_pwm_backlight_data enterprise_disp1_backlight_data
.which_dc = 0,
.which_pwm = TEGRA_PWM_PM1,
.gpio_conf_to_sfio = TEGRA_GPIO_PW1,
- .switch_to_sfio = &tegra_gpio_disable,
.max_brightness = 255,
.dft_brightness = 224,
.notify = enterprise_backlight_notify,
@@ -185,9 +199,15 @@ static struct platform_tegra_pwm_backlight_data enterprise_disp1_backlight_data
/* Only toggle backlight on fb blank notifications for disp1 */
.check_fb = enterprise_disp1_check_fb,
};
+#endif
+
static struct platform_device enterprise_disp1_backlight_device = {
+#if IS_EXTERNAL_PWM
+ .name = "pwm-backlight",
+#else
.name = "tegra-pwm-bl",
+#endif
.id = -1,
.dev = {
.platform_data = &enterprise_disp1_backlight_data,
@@ -510,8 +530,11 @@ static int enterprise_dsi_panel_enable(void)
if (ret)
return ret;
-#if DSI_PANEL_RESET
+#if IS_EXTERNAL_PWM
+ tegra_gpio_disable(enterprise_bl_pwm);
+#endif
+#if DSI_PANEL_RESET
if (board_info.fab >= BOARD_FAB_A03) {
if (enterprise_lcd_reg == NULL) {
enterprise_lcd_reg = regulator_get(NULL, "lcd_vddio_en");
@@ -541,7 +564,6 @@ static int enterprise_dsi_panel_enable(void)
gpio_free(enterprise_dsi_panel_reset);
return ret;
}
- tegra_gpio_enable(enterprise_dsi_panel_reset);
gpio_set_value(enterprise_dsi_panel_reset, 0);
udelay(2000);
@@ -560,7 +582,6 @@ static int enterprise_dsi_panel_disable(void)
#if DSI_PANEL_RESET
if (kernel_1st_panel_init != true) {
- tegra_gpio_disable(enterprise_dsi_panel_reset);
gpio_free(enterprise_dsi_panel_reset);
} else
kernel_1st_panel_init = false;
@@ -796,7 +817,11 @@ static struct platform_device *enterprise_gfx_devices[] __initdata = {
#if defined(CONFIG_TEGRA_NVMAP)
&enterprise_nvmap_device,
#endif
+#if IS_EXTERNAL_PWM
+ &tegra_pwfm3_device,
+#else
&tegra_pwfm0_device,
+#endif
};
static struct platform_device *enterprise_bl_devices[] = {
@@ -816,17 +841,10 @@ static void enterprise_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_save_default_governor();
- cpufreq_set_conservative_governor();
- cpufreq_set_conservative_governor_param("up_threshold",
- SET_CONSERVATIVE_GOVERNOR_UP_THRESHOLD);
-
- cpufreq_set_conservative_governor_param("down_threshold",
- SET_CONSERVATIVE_GOVERNOR_DOWN_THRESHOLD);
- cpufreq_set_conservative_governor_param("freq_step",
- SET_CONSERVATIVE_GOVERNOR_FREQ_STEP);
+#ifdef CONFIG_TEGRA_CONVSERVATIVE_GOV_ON_EARLYSUPSEND
+ cpufreq_store_default_gov();
+ cpufreq_change_gov(cpufreq_conservative_gov);
#endif
}
@@ -835,7 +853,7 @@ static void enterprise_panel_late_resume(struct early_suspend *h)
unsigned i;
#ifdef CONFIG_TEGRA_CONVSERVATIVE_GOV_ON_EARLYSUPSEND
- cpufreq_restore_default_governor();
+ cpufreq_restore_default_gov();
#endif
for (i = 0; i < num_registered_fb; i++)
fb_blank(registered_fb[i], FB_BLANK_UNBLANK);
@@ -854,7 +872,9 @@ int __init enterprise_panel_init(void)
BUILD_BUG_ON(ARRAY_SIZE(enterprise_bl_output_measured_a02) != 256);
if (board_info.fab >= BOARD_FAB_A03) {
+#if !(IS_EXTERNAL_PWM)
enterprise_disp1_backlight_data.clk_div = 0x1D;
+#endif
bl_output = enterprise_bl_output_measured_a03;
} else
bl_output = enterprise_bl_output_measured_a02;
@@ -867,22 +887,18 @@ int __init enterprise_panel_init(void)
enterprise_carveouts[1].size = tegra_carveout_size;
#endif
- tegra_gpio_enable(enterprise_hdmi_hpd);
gpio_request(enterprise_hdmi_hpd, "hdmi_hpd");
gpio_direction_input(enterprise_hdmi_hpd);
- tegra_gpio_enable(enterprise_lcd_2d_3d);
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);
- tegra_gpio_enable(enterprise_lcd_swp_pl);
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 !(DC_CTRL_MODE & TEGRA_DC_OUT_ONE_SHOT_MODE)
- tegra_gpio_enable(enterprise_lcd_te);
gpio_request(enterprise_lcd_swp_pl, "lcd_te");
gpio_direction_input(enterprise_lcd_te);
#endif
@@ -895,7 +911,7 @@ int __init enterprise_panel_init(void)
#endif
#ifdef CONFIG_TEGRA_GRHOST
- err = nvhost_device_register(&tegra_grhost_device);
+ err = tegra3_register_host1x_devices();
if (err)
return err;
#endif
diff --git a/arch/arm/mach-tegra/board-enterprise-pinmux.c b/arch/arm/mach-tegra/board-enterprise-pinmux.c
index 8d18e3296af3..721eb0d27576 100644
--- a/arch/arm/mach-tegra/board-enterprise-pinmux.c
+++ b/arch/arm/mach-tegra/board-enterprise-pinmux.c
@@ -215,7 +215,7 @@ static __initdata struct tegra_pingroup_config enterprise_pinmux_common[] = {
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, NORMAL, INPUT),
+ 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),
@@ -265,6 +265,9 @@ static __initdata struct tegra_pingroup_config enterprise_pinmux_common[] = {
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),
@@ -379,7 +382,9 @@ static __initdata struct tegra_pingroup_config enterprise_unused_pinmux_common[]
DEFAULT_PINMUX(GMI_AD5, GMI, NORMAL, TRISTATE, OUTPUT),
DEFAULT_PINMUX(GMI_AD6, GMI, NORMAL, TRISTATE, OUTPUT),
DEFAULT_PINMUX(GMI_AD7, GMI, NORMAL, TRISTATE, OUTPUT),
+#if !(IS_EXTERNAL_PWM)
DEFAULT_PINMUX(GMI_AD11, GMI, PULL_DOWN, TRISTATE, OUTPUT),
+#endif
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),
@@ -460,7 +465,9 @@ static __initdata struct pin_info_low_power_mode enterprise_unused_gpio_pins_com
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),
+#if !(IS_EXTERNAL_PWM)
PIN_GPIO_LPM("GMI_AD11", TEGRA_GPIO_PH3, 0, 0),
+#endif
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),
@@ -534,7 +541,6 @@ static void enterprise_set_unused_pin_gpio(struct pin_info_low_power_mode *lpm_p
gpio_free(pin_info->gpio_nr);
continue;
}
- tegra_gpio_enable(pin_info->gpio_nr);
}
}
diff --git a/arch/arm/mach-tegra/board-enterprise-power.c b/arch/arm/mach-tegra/board-enterprise-power.c
index c17c3eaf5cfa..bbe39ec4ad3e 100644
--- a/arch/arm/mach-tegra/board-enterprise-power.c
+++ b/arch/arm/mach-tegra/board-enterprise-power.c
@@ -44,7 +44,6 @@
#include "board.h"
#include "board-enterprise.h"
#include "pm.h"
-#include "wakeups-t3.h"
#include "tegra3_tsensor.h"
#define PMC_CTRL 0x0
@@ -141,9 +140,10 @@ static struct regulator_consumer_supply tps80031_smps4_supply_a03[] = {
REGULATOR_SUPPLY("vddf_core_emmc", NULL),
};
-static struct regulator_consumer_supply tps80031_vana_supply_common[] = {
+static struct regulator_consumer_supply tps80031_vana_supply_a02[] = {
REGULATOR_SUPPLY("unused_vana", NULL),
};
+#define tps80031_vana_supply_a03 tps80031_vana_supply_a02
static struct regulator_consumer_supply tps80031_ldo1_supply_a02[] = {
REGULATOR_SUPPLY("avdd_dsi_csi", NULL),
@@ -269,23 +269,24 @@ TPS_PDATA_INIT(smps1, common, 600, 2100, 0, 0, 0, 0, -1, 0, 0, 0, PWR_REQ_INPUT_
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, 0, 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, 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, 0, 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_OFF_ON_SLEEP, 0);
-TPS_PDATA_INIT(vana, common, 1000, 3300, 0, 0, 0, 0, -1, 0, 0, 0, 0, 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);
static struct tps80031_rtc_platform_data rtc_data = {
@@ -298,6 +299,7 @@ static struct tps80031_rtc_platform_data rtc_data = {
.tm_min = 2,
.tm_sec = 3,
},
+ .msecure_gpio = TEGRA_GPIO_PF7,
};
int battery_charger_init(void *board_data)
@@ -309,7 +311,6 @@ int battery_charger_init(void *board_data)
" charger fails\n", __func__);
}
gpio_direction_output(TEGRA_GPIO_PF6, 1);
- tegra_gpio_enable(TEGRA_GPIO_PF6);
return 0;
}
@@ -362,7 +363,6 @@ static struct tps80031_bg_platform_data battery_gauge_data = {
TPS_REG(SMPS1, smps1, common), \
TPS_REG(SMPS2, smps2, common), \
TPS_REG(SMPS3, smps3, common), \
- TPS_REG(VANA, vana, common), \
TPS_REG(LDO2, ldo2, common), \
TPS_REG(LDO3, ldo3, common), \
TPS_REG(LDO5, ldo5, common), \
@@ -374,8 +374,8 @@ static struct tps80031_bg_platform_data battery_gauge_data = {
static struct tps80031_subdev_info tps80031_devs_a02[] = {
- TPS80031_DEVS_COMMON,
TPS_REG(VIO, vio, a02),
+ TPS80031_DEVS_COMMON,
TPS_REG(SMPS4, smps4, a02),
TPS_REG(LDO1, ldo1, a02),
TPS_REG(LDO4, ldo4, a02),
@@ -383,12 +383,13 @@ static struct tps80031_subdev_info tps80031_devs_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[] = {
- TPS80031_DEVS_COMMON,
TPS_REG(VIO, vio, a03),
+ TPS80031_DEVS_COMMON,
TPS_REG(SMPS4, smps4, a03),
TPS_REG(LDO1, ldo1, a03),
TPS_REG(LDO4, ldo4, a03),
@@ -396,10 +397,11 @@ static struct tps80031_subdev_info tps80031_devs_a03[] = {
TPS_REG(LDO7, ldo7, a03),
TPS_REG(LDOLN, ldoln, a03),
TPS_REG(LDOUSB, ldousb, a03),
+ TPS_REG(VANA, vana, a03),
};
-struct tps80031_clk32k_init_data clk32k_idata[] = {
+static struct tps80031_clk32k_init_data clk32k_idata[] = {
{
.clk32k_nr = TPS80031_CLOCK32K_G,
.enable = true,
@@ -410,6 +412,23 @@ struct tps80031_clk32k_init_data clk32k_idata[] = {
.enable = true,
.ext_ctrl_flag = 0,
},
+
+
+};
+
+static struct tps80031_gpio_init_data gpio_idata_a03[] = {
+ {
+ .gpio_nr = TPS80031_GPIO_REGEN1,
+ .ext_ctrl_flag = PWR_REQ_INPUT_PREQ1,
+ },
+ {
+ .gpio_nr = TPS80031_GPIO_REGEN2,
+ .ext_ctrl_flag = PWR_REQ_INPUT_PREQ1,
+ },
+ {
+ .gpio_nr = TPS80031_GPIO_SYSEN,
+ .ext_ctrl_flag = PWR_REQ_INPUT_PREQ1,
+ },
};
static struct tps80031_pupd_init_data pupd_idata[] = {
@@ -463,7 +482,7 @@ static struct regulator_consumer_supply fixed_reg_vdd_fuse_en_supply[] = {
static struct regulator_consumer_supply gpio_reg_sdmmc3_vdd_sel_supply[] = {
REGULATOR_SUPPLY("vddio_sdmmc3_2v85_1v8", NULL),
REGULATOR_SUPPLY("sdmmc3_compu_pu", NULL),
- REGULATOR_SUPPLY("vddio_sdmmc3", NULL),
+ REGULATOR_SUPPLY("vddio_sdmmc", "sdhci-tegra.2"),
REGULATOR_SUPPLY("vsys_3v7", NULL),
};
@@ -644,8 +663,12 @@ FIXED_REG(8, lcd_1v8_en, NULL,
ADD_FIXED_REG(cam_ldo_1v8_en)
static struct platform_device *fixed_regs_devices_a02[] = {
- FIXED_REGS_COMMON,
- ADD_FIXED_REG(pmu_3v3_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[] = {
@@ -661,7 +684,6 @@ static struct platform_device *gpio_regs_devices[] = {
static int __init enterprise_fixed_regulator_init(void)
{
- int i;
struct board_info board_info;
struct platform_device **fixed_regs_devices;
int nfixreg_devs;
@@ -676,27 +698,11 @@ static int __init enterprise_fixed_regulator_init(void)
nfixreg_devs = ARRAY_SIZE(fixed_regs_devices_a03);
}
- for (i = 0; i < nfixreg_devs; ++i) {
- struct fixed_voltage_config *fixed_reg_pdata =
- fixed_regs_devices[i]->dev.platform_data;
- if (fixed_reg_pdata->gpio < TEGRA_NR_GPIOS)
- tegra_gpio_enable(fixed_reg_pdata->gpio);
- }
return platform_add_devices(fixed_regs_devices, nfixreg_devs);
}
static int __init enterprise_gpio_regulator_init(void)
{
- int i, j;
-
- for (i = 0; i < ARRAY_SIZE(gpio_regs_devices); ++i) {
- struct gpio_regulator_config *gpio_reg_pdata =
- gpio_regs_devices[i]->dev.platform_data;
- for (j = 0; j < gpio_reg_pdata->nr_gpios; ++j) {
- if (gpio_reg_pdata->gpios[j].gpio < TEGRA_NR_GPIOS)
- tegra_gpio_enable(gpio_reg_pdata->gpios[j].gpio);
- }
- }
return platform_add_devices(gpio_regs_devices,
ARRAY_SIZE(gpio_regs_devices));
}
@@ -742,6 +748,8 @@ int __init enterprise_regulator_init(void)
battery_gauge_data.battery_present = 0;
}
+ tegra_gpio_enable(TEGRA_GPIO_PF7);
+
if (board_info.fab < BOARD_FAB_A03) {
tps_platform.num_subdevs = ARRAY_SIZE(tps80031_devs_a02);
tps_platform.subdevs = tps80031_devs_a02;
@@ -750,6 +758,8 @@ int __init enterprise_regulator_init(void)
tps_platform.subdevs = tps80031_devs_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;
+ tps_platform.gpio_init_data_size = ARRAY_SIZE(gpio_idata_a03);
}
i2c_register_board_info(4, enterprise_regulators, 1);
@@ -835,8 +845,6 @@ void __init enterprise_bpc_mgmt_init(void)
{
int int_gpio = TEGRA_GPIO_TO_IRQ(TEGRA_BPC_TRIGGER);
- tegra_gpio_enable(TEGRA_BPC_TRIGGER);
-
#ifdef CONFIG_SMP
cpumask_setall(&(bpc_mgmt_platform_data.affinity_mask));
irq_set_affinity_hint(int_gpio,
diff --git a/arch/arm/mach-tegra/board-enterprise-sdhci.c b/arch/arm/mach-tegra/board-enterprise-sdhci.c
index 4102ef464d1e..7a5632601fe6 100644
--- a/arch/arm/mach-tegra/board-enterprise-sdhci.c
+++ b/arch/arm/mach-tegra/board-enterprise-sdhci.c
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-tegra/board-enterprise-sdhci.c
*
- * Copyright (C) 2011 NVIDIA Corporation.
+ * Copyright (C) 2011-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
@@ -143,13 +143,17 @@ static struct tegra_sdhci_platform_data tegra_sdhci_platform_data0 = {
.cd_gpio = -1,
.wp_gpio = -1,
.power_gpio = -1,
+ .tap_delay = 0x0F,
.max_clk_limit = 45000000,
+ .ddr_clk_limit = 41000000,
};
static struct tegra_sdhci_platform_data tegra_sdhci_platform_data2 = {
.cd_gpio = -1,
.wp_gpio = -1,
.power_gpio = -1,
+ .tap_delay = 0x0F,
+ .ddr_clk_limit = 41000000,
};
static struct tegra_sdhci_platform_data tegra_sdhci_platform_data3 = {
@@ -158,6 +162,7 @@ static struct tegra_sdhci_platform_data tegra_sdhci_platform_data3 = {
.power_gpio = -1,
.is_8bit = 1,
.tap_delay = 0x0F,
+ .ddr_clk_limit = 41000000,
.mmc_data = {
.built_in = 1,
}
@@ -259,10 +264,6 @@ static int __init enterprise_wifi_init(void)
if (rc)
pr_err("WLAN_WOW gpio request failed:%d\n", rc);
- tegra_gpio_enable(ENTERPRISE_WLAN_PWR);
- tegra_gpio_enable(ENTERPRISE_WLAN_RST);
- tegra_gpio_enable(ENTERPRISE_WLAN_WOW);
-
rc = gpio_direction_output(ENTERPRISE_WLAN_PWR, 0);
if (rc)
pr_err("WLAN_PWR gpio direction configuration failed:%d\n", rc);
@@ -281,7 +282,6 @@ int __init enterprise_sdhci_init(void)
{
platform_device_register(&tegra_sdhci_device3);
- tegra_gpio_enable(ENTERPRISE_SD_CD);
tegra_sdhci_platform_data2.cd_gpio = ENTERPRISE_SD_CD;
platform_device_register(&tegra_sdhci_device2);
diff --git a/arch/arm/mach-tegra/board-enterprise-sensors.c b/arch/arm/mach-tegra/board-enterprise-sensors.c
index f775c2bd3b3e..aab409b89ea9 100644
--- a/arch/arm/mach-tegra/board-enterprise-sensors.c
+++ b/arch/arm/mach-tegra/board-enterprise-sensors.c
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-tegra/board-enterprise-sensors.c
*
- * Copyright (c) 2011, NVIDIA CORPORATION, All rights reserved.
+ * Copyright (c) 2011-2012, NVIDIA CORPORATION, All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -101,6 +101,7 @@ static void nct1008_probe_callback(struct nct1008_data *data)
thermal_device->name = "nct1008";
thermal_device->data = data;
+ thermal_device->id = THERMAL_DEVICE_ID_NCT_EXT;
thermal_device->offset = TDIODE_OFFSET;
thermal_device->get_temp = nct_get_temp;
thermal_device->get_temp_low = nct_get_temp_low;
@@ -108,7 +109,7 @@ static void nct1008_probe_callback(struct nct1008_data *data)
thermal_device->set_alert = nct_set_alert;
thermal_device->set_shutdown_temp = nct_set_shutdown_temp;
- tegra_thermal_set_device(thermal_device);
+ tegra_thermal_device_register(thermal_device);
}
static struct nct1008_platform_data enterprise_nct1008_pdata = {
@@ -131,7 +132,6 @@ static void enterprise_nct1008_init(void)
{
int ret;
- tegra_gpio_enable(TEGRA_GPIO_PH7);
ret = gpio_request(TEGRA_GPIO_PH7, "temp_alert");
if (ret < 0) {
pr_err("%s: gpio_request failed %d\n", __func__, ret);
@@ -213,7 +213,6 @@ static void mpuirq_init(void)
#if (MPU_GYRO_TYPE == MPU_TYPE_MPU3050)
#if MPU_ACCEL_IRQ_GPIO
/* ACCEL-IRQ assignment */
- tegra_gpio_enable(MPU_ACCEL_IRQ_GPIO);
ret = gpio_request(MPU_ACCEL_IRQ_GPIO, MPU_ACCEL_NAME);
if (ret < 0) {
pr_err("%s: gpio_request failed %d\n", __func__, ret);
@@ -230,7 +229,6 @@ static void mpuirq_init(void)
#endif
/* MPU-IRQ assignment */
- tegra_gpio_enable(MPU_GYRO_IRQ_GPIO);
ret = gpio_request(MPU_GYRO_IRQ_GPIO, MPU_GYRO_NAME);
if (ret < 0) {
pr_err("%s: gpio_request failed %d\n", __func__, ret);
@@ -589,7 +587,6 @@ static int enterprise_cam_init(void)
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_gpio_enable(enterprise_cam_gpio_data[i].gpio);
}
tegra_get_board_info(&bi);
diff --git a/arch/arm/mach-tegra/board-enterprise.c b/arch/arm/mach-tegra/board-enterprise.c
index fb2b89bcba60..9c8890ed96cf 100644
--- a/arch/arm/mach-tegra/board-enterprise.c
+++ b/arch/arm/mach-tegra/board-enterprise.c
@@ -37,6 +37,7 @@
#include <linux/fsl_devices.h>
#include <linux/i2c/atmel_mxt_ts.h>
#include <linux/memblock.h>
+#include <linux/rfkill-gpio.h>
#include <linux/nfc/pn544.h>
#include <sound/max98088.h>
@@ -54,6 +55,7 @@
#include <mach/tegra_asoc_pdata.h>
#include <mach/thermal.h>
#include <mach/tegra-bb-power.h>
+#include <mach/tegra_fiq_debugger.h>
#include "board.h"
#include "clock.h"
#include "board-enterprise.h"
@@ -63,75 +65,77 @@
#include "fuse.h"
#include "pm.h"
+static struct balanced_throttle throttle_list[] = {
+ {
+ .id = BALANCED_THROTTLE_ID_TJ,
+ .throt_tab_size = 10,
+ .throt_tab = {
+ { 0, 1000 },
+ { 640000, 1000 },
+ { 640000, 1000 },
+ { 640000, 1000 },
+ { 640000, 1000 },
+ { 640000, 1000 },
+ { 760000, 1000 },
+ { 760000, 1050 },
+ {1000000, 1050 },
+ {1000000, 1100 },
+ },
+ },
+#ifdef CONFIG_TEGRA_SKIN_THROTTLE
+ {
+ .id = BALANCED_THROTTLE_ID_SKIN,
+ .throt_tab_size = 6,
+ .throt_tab = {
+ { 640000, 1200 },
+ { 640000, 1200 },
+ { 760000, 1200 },
+ { 760000, 1200 },
+ {1000000, 1200 },
+ {1000000, 1200 },
+ },
+ },
+#endif
+};
+
/* All units are in millicelsius */
static struct tegra_thermal_data thermal_data = {
- .temp_throttle = 85000,
+ .shutdown_device_id = THERMAL_DEVICE_ID_NCT_EXT,
.temp_shutdown = 90000,
- .temp_offset = TDIODE_OFFSET, /* temps based on tdiode */
+#if defined(CONFIG_TEGRA_EDP_LIMITS) || defined(CONFIG_TEGRA_THERMAL_THROTTLE)
+ .throttle_edp_device_id = THERMAL_DEVICE_ID_NCT_EXT,
+#endif
#ifdef CONFIG_TEGRA_EDP_LIMITS
.edp_offset = TDIODE_OFFSET, /* edp based on tdiode */
.hysteresis_edp = 3000,
#endif
-#ifdef CONFIG_TEGRA_THERMAL_SYSFS
+#ifdef CONFIG_TEGRA_THERMAL_THROTTLE
+ .temp_throttle = 85000,
.tc1 = 0,
.tc2 = 1,
.passive_delay = 2000,
-#else
- .hysteresis_throttle = 1000,
+#endif
+#ifdef CONFIG_TEGRA_SKIN_THROTTLE
+ .skin_device_id = THERMAL_DEVICE_ID_SKIN,
+ .temp_throttle_skin = 43000,
#endif
};
-/* !!!TODO: Change for enterprise (Taken from Cardhu) */
-static struct tegra_utmip_config utmi_phy_config[] = {
- [0] = {
- .hssync_start_delay = 0,
- .idle_wait_delay = 17,
- .elastic_limit = 16,
- .term_range_adj = 6,
- .xcvr_setup = 15,
- .xcvr_setup_offset = 0,
- .xcvr_use_fuses = 1,
- .xcvr_lsfslew = 2,
- .xcvr_lsrslew = 2,
- },
- [1] = {
- .hssync_start_delay = 0,
- .idle_wait_delay = 17,
- .elastic_limit = 16,
- .term_range_adj = 6,
- .xcvr_setup = 15,
- .xcvr_setup_offset = 0,
- .xcvr_use_fuses = 1,
- .xcvr_lsfslew = 2,
- .xcvr_lsrslew = 2,
- },
- [2] = {
- .hssync_start_delay = 0,
- .idle_wait_delay = 17,
- .elastic_limit = 16,
- .term_range_adj = 6,
- .xcvr_setup = 8,
- .xcvr_setup_offset = 0,
- .xcvr_use_fuses = 1,
- .xcvr_lsfslew = 2,
- .xcvr_lsrslew = 2,
- },
-};
-
-static struct resource enterprise_bcm4329_rfkill_resources[] = {
+static struct rfkill_gpio_platform_data enterprise_bt_rfkill_pdata[] = {
{
- .name = "bcm4329_nshutdown_gpio",
- .start = TEGRA_GPIO_PE6,
- .end = TEGRA_GPIO_PE6,
- .flags = IORESOURCE_IO,
+ .name = "bt_rfkill",
+ .shutdown_gpio = TEGRA_GPIO_PE6,
+ .reset_gpio = TEGRA_GPIO_INVALID,
+ .type = RFKILL_TYPE_BLUETOOTH,
},
};
-static struct platform_device enterprise_bcm4329_rfkill_device = {
- .name = "bcm4329_rfkill",
+static struct platform_device enterprise_bt_rfkill_device = {
+ .name = "rfkill_gpio",
.id = -1,
- .num_resources = ARRAY_SIZE(enterprise_bcm4329_rfkill_resources),
- .resource = enterprise_bcm4329_rfkill_resources,
+ .dev = {
+ .platform_data = &enterprise_bt_rfkill_pdata,
+ },
};
static struct resource enterprise_bluesleep_resources[] = {
@@ -165,8 +169,6 @@ static struct platform_device enterprise_bluesleep_device = {
static void __init enterprise_setup_bluesleep(void)
{
platform_device_register(&enterprise_bluesleep_device);
- tegra_gpio_enable(TEGRA_GPIO_PS2);
- tegra_gpio_enable(TEGRA_GPIO_PE7);
return;
}
@@ -175,7 +177,7 @@ static __initdata struct tegra_clk_init_table enterprise_clk_init_table[] = {
{ "pll_m", NULL, 0, false},
{ "hda", "pll_p", 108000000, false},
{ "hda2codec_2x","pll_p", 48000000, false},
- { "pwm", "clk_32k", 32768, false},
+ { "pwm", "pll_p", 3187500, false},
{ "blink", "clk_32k", 32768, true},
{ "i2s0", "pll_a_out0", 0, false},
{ "i2s1", "pll_a_out0", 0, false},
@@ -207,7 +209,7 @@ static struct tegra_i2c_platform_data enterprise_i2c1_platform_data = {
static struct tegra_i2c_platform_data enterprise_i2c2_platform_data = {
.adapter_nr = 1,
.bus_count = 1,
- .bus_clk_rate = { 100000, 0 },
+ .bus_clk_rate = { 400000, 0 },
.is_clkon_always = true,
.scl_gpio = {TEGRA_GPIO_PT5, 0},
.sda_gpio = {TEGRA_GPIO_PT6, 0},
@@ -235,7 +237,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 = { 100000, 0 },
+ .bus_clk_rate = { 400000, 0 },
.scl_gpio = {TEGRA_GPIO_PZ6, 0},
.sda_gpio = {TEGRA_GPIO_PZ7, 0},
.arb_recovery = arb_lost_recovery,
@@ -552,12 +554,14 @@ static struct platform_device *enterprise_devices[] __initdata = {
#if defined(CONFIG_TEGRA_IOVMM_SMMU) || defined(CONFIG_TEGRA_IOMMU_SMMU)
&tegra_smmu_device,
#endif
- &tegra_wdt_device,
+ &tegra_wdt0_device,
+ &tegra_wdt1_device,
+ &tegra_wdt2_device,
#if defined(CONFIG_TEGRA_AVP)
&tegra_avp_device,
#endif
&tegra_camera,
- &enterprise_bcm4329_rfkill_device,
+ &enterprise_bt_rfkill_device,
&tegra_spi_device4,
&tegra_hda_device,
#if defined(CONFIG_CRYPTO_DEV_TEGRA_SE)
@@ -638,9 +642,6 @@ static struct i2c_board_info __initdata atmel_i2c_info[] = {
static int __init enterprise_touch_init(void)
{
- tegra_gpio_enable(TEGRA_GPIO_PH6);
- tegra_gpio_enable(TEGRA_GPIO_PF5);
-
gpio_request(TEGRA_GPIO_PH6, "atmel-irq");
gpio_direction_input(TEGRA_GPIO_PH6);
@@ -655,66 +656,122 @@ static int __init enterprise_touch_init(void)
return 0;
}
-static struct usb_phy_plat_data tegra_usb_phy_pdata[] = {
- [0] = {
- .instance = 0,
- .vbus_gpio = -1,
- .vbus_reg_supply = "usb_vbus",
- .vbus_irq = ENT_TPS80031_IRQ_BASE +
- TPS80031_INT_VBUS_DET,
- },
- [1] = {
- .instance = 1,
- .vbus_gpio = -1,
- },
- [2] = {
- .instance = 2,
- .vbus_gpio = -1,
- },
-};
+static void enterprise_usb_hsic_postsupend(void)
+{
+ pr_debug("%s\n", __func__);
+#ifdef CONFIG_TEGRA_BB_XMM_POWER
+ baseband_xmm_set_power_status(BBXMM_PS_L2);
+#endif
+}
-static struct tegra_uhsic_config uhsic_phy_config = {
- .enable_gpio = -1,
- .reset_gpio = -1,
- .sync_start_delay = 9,
- .idle_wait_delay = 17,
- .term_range_adj = 0,
- .elastic_underrun_limit = 16,
- .elastic_overrun_limit = 16,
-};
+static void enterprise_usb_hsic_preresume(void)
+{
+ pr_debug("%s\n", __func__);
+#ifdef CONFIG_TEGRA_BB_XMM_POWER
+ baseband_xmm_set_power_status(BBXMM_PS_L2TOL0);
+#endif
+}
-static struct tegra_ehci_platform_data tegra_ehci_uhsic_pdata = {
- .phy_type = TEGRA_USB_PHY_TYPE_HSIC,
- .phy_config = &uhsic_phy_config,
- .operating_mode = TEGRA_USB_HOST,
- .power_down_on_bus_suspend = 1,
- .default_enable = true,
-};
+static void enterprise_usb_hsic_phy_power(void)
+{
+ pr_debug("%s\n", __func__);
+#ifdef CONFIG_TEGRA_BB_XMM_POWER
+ baseband_xmm_set_power_status(BBXMM_PS_L0);
+#endif
+}
-static struct tegra_ehci_platform_data tegra_ehci_pdata[] = {
- [0] = {
- .phy_config = &utmi_phy_config[0],
- .operating_mode = TEGRA_USB_HOST,
- .power_down_on_bus_suspend = 1,
- .default_enable = false,
- },
- [1] = {
- .phy_config = &utmi_phy_config[1],
- .operating_mode = TEGRA_USB_HOST,
- .power_down_on_bus_suspend = 1,
- .default_enable = false,
- },
- [2] = {
- .phy_config = &utmi_phy_config[2],
- .operating_mode = TEGRA_USB_HOST,
- .power_down_on_bus_suspend = 1,
- .default_enable = false,
- },
-};
+static void enterprise_usb_hsic_post_phy_off(void)
+{
+ pr_debug("%s\n", __func__);
+#ifdef CONFIG_TEGRA_BB_XMM_POWER
+ baseband_xmm_set_power_status(BBXMM_PS_L2);
+#endif
+}
-static struct tegra_otg_platform_data tegra_otg_pdata = {
+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_phy_off = enterprise_usb_hsic_post_phy_off,
+};
+
+static struct tegra_usb_platform_data tegra_ehci2_hsic_xmm_pdata = {
+ .port_otg = false,
+ .has_hostpc = true,
+ .phy_intf = TEGRA_USB_PHY_INTF_HSIC,
+ .op_mode = TEGRA_USB_OPMODE_HOST,
+ .u_data.host = {
+ .vbus_gpio = -1,
+ .hot_plug = false,
+ .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,
+ .phy_intf = TEGRA_USB_PHY_INTF_UTMI,
+ .op_mode = TEGRA_USB_OPMODE_DEVICE,
+ .u_data.dev = {
+ .vbus_pmu_irq = ENT_TPS80031_IRQ_BASE +
+ TPS80031_INT_VBUS_DET,
+ .vbus_gpio = -1,
+ .charging_supported = false,
+ .remote_wakeup_supported = false,
+ },
+ .u_cfg.utmi = {
+ .hssync_start_delay = 0,
+ .elastic_limit = 16,
+ .idle_wait_delay = 17,
+ .term_range_adj = 6,
+ .xcvr_setup = 8,
+ .xcvr_lsfslew = 2,
+ .xcvr_lsrslew = 2,
+ .xcvr_setup_offset = 0,
+ .xcvr_use_fuses = 1,
+ },
+};
+
+static struct tegra_usb_platform_data tegra_ehci1_utmi_pdata = {
+ .port_otg = true,
+ .has_hostpc = true,
+ .builtin_host_disabled = true,
+ .phy_intf = TEGRA_USB_PHY_INTF_UTMI,
+ .op_mode = TEGRA_USB_OPMODE_HOST,
+ .u_data.host = {
+ .vbus_gpio = -1,
+ .vbus_reg = "usb_vbus",
+ .hot_plug = true,
+ .remote_wakeup_supported = true,
+ .power_off_on_suspend = true,
+ },
+ .u_cfg.utmi = {
+ .hssync_start_delay = 0,
+ .elastic_limit = 16,
+ .idle_wait_delay = 17,
+ .term_range_adj = 6,
+ .xcvr_setup = 15,
+ .xcvr_lsfslew = 2,
+ .xcvr_lsrslew = 2,
+ .xcvr_setup_offset = 0,
+ .xcvr_use_fuses = 1,
+ },
+};
+
+static struct tegra_usb_otg_data tegra_otg_pdata = {
.ehci_device = &tegra_ehci1_device,
- .ehci_pdata = &tegra_ehci_pdata[0],
+ .ehci_pdata = &tegra_ehci1_utmi_pdata,
};
struct platform_device *tegra_usb_hsic_host_register(void)
@@ -735,8 +792,8 @@ struct platform_device *tegra_usb_hsic_host_register(void)
pdev->dev.dma_mask = tegra_ehci2_device.dev.dma_mask;
pdev->dev.coherent_dma_mask = tegra_ehci2_device.dev.coherent_dma_mask;
- val = platform_device_add_data(pdev, &tegra_ehci_uhsic_pdata,
- sizeof(struct tegra_ehci_platform_data));
+ val = platform_device_add_data(pdev, &tegra_ehci2_hsic_xmm_pdata,
+ sizeof(struct tegra_usb_platform_data));
if (val)
goto error;
@@ -757,52 +814,12 @@ void tegra_usb_hsic_host_unregister(struct platform_device *pdev)
platform_device_unregister(pdev);
}
-static int enterprise_usb_hsic_postsupend(void)
-{
- pr_debug("%s\n", __func__);
-#ifdef CONFIG_TEGRA_BB_XMM_POWER
- baseband_xmm_set_power_status(BBXMM_PS_L2);
-#endif
- return 0;
-}
-
-static int enterprise_usb_hsic_preresume(void)
-{
- pr_debug("%s\n", __func__);
-#ifdef CONFIG_TEGRA_BB_XMM_POWER
- baseband_xmm_set_power_status(BBXMM_PS_L2TOL0);
-#endif
- return 0;
-}
-
-static int enterprise_usb_hsic_phy_ready(void)
-{
- pr_debug("%s\n", __func__);
-#ifdef CONFIG_TEGRA_BB_XMM_POWER
- baseband_xmm_set_power_status(BBXMM_PS_L0);
-#endif
- return 0;
-}
-
-static int enterprise_usb_hsic_phy_off(void)
-{
- pr_debug("%s\n", __func__);
-#ifdef CONFIG_TEGRA_BB_XMM_POWER
- baseband_xmm_set_power_status(BBXMM_PS_L3);
-#endif
- return 0;
-}
-
static void enterprise_usb_init(void)
{
- struct fsl_usb2_platform_data *udc_pdata;
-
- tegra_usb_phy_init(tegra_usb_phy_pdata, ARRAY_SIZE(tegra_usb_phy_pdata));
+ tegra_udc_device.dev.platform_data = &tegra_udc_pdata;
tegra_otg_device.dev.platform_data = &tegra_otg_pdata;
platform_device_register(&tegra_otg_device);
-
- udc_pdata = tegra_udc_device.dev.platform_data;
}
static struct platform_device *enterprise_audio_devices[] __initdata = {
@@ -836,11 +853,6 @@ static void enterprise_audio_init(void)
ARRAY_SIZE(enterprise_audio_devices));
}
-static void enterprise_gps_init(void)
-{
- tegra_gpio_enable(TEGRA_GPIO_PE4);
- tegra_gpio_enable(TEGRA_GPIO_PE5);
-}
static struct baseband_power_platform_data tegra_baseband_power_data = {
.baseband_type = BASEBAND_XMM,
@@ -912,61 +924,43 @@ static void enterprise_baseband_init(void)
enterprise_modem_init();
break;
case TEGRA_BB_XMM6260: /* XMM6260 HSIC */
- /* xmm baseband - do not switch off phy during suspend */
- tegra_ehci_uhsic_pdata.power_down_on_bus_suspend = 0;
- uhsic_phy_config.postsuspend = enterprise_usb_hsic_postsupend;
- uhsic_phy_config.preresume = enterprise_usb_hsic_preresume;
- uhsic_phy_config.usb_phy_ready = enterprise_usb_hsic_phy_ready;
- uhsic_phy_config.post_phy_off = enterprise_usb_hsic_phy_off;
- /* enable XMM6260 baseband gpio(s) */
- tegra_gpio_enable(tegra_baseband_power_data.modem.generic
- .mdm_reset);
- tegra_gpio_enable(tegra_baseband_power_data.modem.generic
- .mdm_on);
- tegra_gpio_enable(tegra_baseband_power_data.modem.generic
- .ap2mdm_ack);
- tegra_gpio_enable(tegra_baseband_power_data.modem.generic
- .mdm2ap_ack);
- tegra_gpio_enable(tegra_baseband_power_data.modem.generic
- .ap2mdm_ack2);
- tegra_gpio_enable(tegra_baseband_power_data.modem.generic
- .mdm2ap_ack2);
+ /* baseband-power.ko will register ehci2 device */
+ tegra_ehci2_device.dev.platform_data =
+ &tegra_ehci2_hsic_xmm_pdata;
tegra_baseband_power_data.hsic_register =
&tegra_usb_hsic_host_register;
tegra_baseband_power_data.hsic_unregister =
&tegra_usb_hsic_host_unregister;
+
platform_device_register(&tegra_baseband_power_device);
platform_device_register(&tegra_baseband_power2_device);
break;
#ifdef CONFIG_TEGRA_BB_M7400
case TEGRA_BB_M7400: /* M7400 HSIC */
- tegra_ehci_uhsic_pdata.power_down_on_bus_suspend = 0;
+ tegra_ehci2_hsic_xmm_pdata.u_data.host.power_off_on_suspend = 0;
tegra_ehci2_device.dev.platform_data
- = &tegra_ehci_uhsic_pdata;
+ = &tegra_ehci2_hsic_xmm_pdata;
platform_device_register(&tegra_baseband_m7400_device);
break;
#endif
}
}
-
static void enterprise_nfc_init(void)
{
struct board_info bi;
- tegra_gpio_enable(TEGRA_GPIO_PS4);
- tegra_gpio_enable(TEGRA_GPIO_PM6);
-
/* Enable firmware GPIO PX7 for board E1205 */
tegra_get_board_info(&bi);
if (bi.board_id == BOARD_E1205 && bi.fab >= BOARD_FAB_A03) {
nfc_pdata.firm_gpio = TEGRA_GPIO_PX7;
- tegra_gpio_enable(TEGRA_GPIO_PX7);
}
}
static void __init tegra_enterprise_init(void)
{
- tegra_thermal_init(&thermal_data);
+ tegra_thermal_init(&thermal_data,
+ throttle_list,
+ ARRAY_SIZE(throttle_list));
tegra_clk_init_from_table(enterprise_clk_init_table);
enterprise_pinmux_init();
enterprise_i2c_init();
@@ -980,9 +974,9 @@ static void __init tegra_enterprise_init(void)
enterprise_edp_init();
#endif
enterprise_kbc_init();
+ enterprise_nfc_init();
enterprise_touch_init();
enterprise_audio_init();
- enterprise_gps_init();
enterprise_baseband_init();
enterprise_panel_init();
enterprise_setup_bluesleep();
@@ -991,7 +985,7 @@ static void __init tegra_enterprise_init(void)
enterprise_suspend_init();
enterprise_bpc_mgmt_init();
tegra_release_bootloader_fb();
- enterprise_nfc_init();
+ tegra_serial_debug_init(TEGRA_UARTD_BASE, INT_WDT_CPU, NULL, -1, -1);
}
static void __init tegra_enterprise_reserve(void)
diff --git a/arch/arm/mach-tegra/board-enterprise.h b/arch/arm/mach-tegra/board-enterprise.h
index f47672091bf8..3c6d149abdff 100644
--- a/arch/arm/mach-tegra/board-enterprise.h
+++ b/arch/arm/mach-tegra/board-enterprise.h
@@ -158,4 +158,7 @@ enum tegra_bb_type {
TEGRA_BB_M7400,
};
+/* Indicate the pwm of backlight, DC pwm or external pwm3. */
+#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 c24039652bc5..d4cd3f461b66 100644
--- a/arch/arm/mach-tegra/board-harmony-panel.c
+++ b/arch/arm/mach-tegra/board-harmony-panel.c
@@ -26,13 +26,14 @@
#include <mach/dc.h>
#include <mach/irqs.h>
#include <mach/iomap.h>
-#include <mach/nvmap.h>
+#include <linux/nvmap.h>
#include <mach/tegra_fb.h>
#include <mach/fb.h>
#include "devices.h"
#include "gpio-names.h"
#include "board.h"
+#include "tegra2_host1x_devices.h"
#define harmony_bl_enb TEGRA_GPIO_PB5
#define harmony_lvds_shutdown TEGRA_GPIO_PB2
@@ -356,7 +357,7 @@ int __init harmony_panel_init(void)
#endif
#ifdef CONFIG_TEGRA_GRHOST
- err = nvhost_device_register(&tegra_grhost_device);
+ err = tegra2_register_host1x_devices();
if (err)
return err;
#endif
diff --git a/arch/arm/mach-tegra/board-harmony-pcie.c b/arch/arm/mach-tegra/board-harmony-pcie.c
index f3db0eeba2c9..f73cde4c5570 100644
--- a/arch/arm/mach-tegra/board-harmony-pcie.c
+++ b/arch/arm/mach-tegra/board-harmony-pcie.c
@@ -4,6 +4,8 @@
* Copyright (C) 2010 CompuLab, Ltd.
* Mike Rapoport <mike@compulab.co.il>
*
+ * Copyright (C) 2011-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.
@@ -68,7 +70,6 @@ int __init harmony_pcie_init(void)
return 0;
-err_pcie:
tegra_pinmux_set_tristate(TEGRA_PINGROUP_GPV, TEGRA_TRI_TRISTATE);
tegra_pinmux_set_tristate(TEGRA_PINGROUP_SLXA, TEGRA_TRI_TRISTATE);
tegra_pinmux_set_tristate(TEGRA_PINGROUP_SLXK, TEGRA_TRI_TRISTATE);
diff --git a/arch/arm/mach-tegra/board-harmony.c b/arch/arm/mach-tegra/board-harmony.c
index 9bf8cde056a3..dd14435cc17c 100644
--- a/arch/arm/mach-tegra/board-harmony.c
+++ b/arch/arm/mach-tegra/board-harmony.c
@@ -32,6 +32,9 @@
#include <linux/i2c-tegra.h>
#include <linux/memblock.h>
#include <linux/delay.h>
+#include <linux/mfd/tps6586x.h>
+#include <linux/platform_data/tegra_usb.h>
+#include <linux/tegra_uart.h>
#include <sound/wm8903.h>
@@ -81,20 +84,52 @@ static int __init parse_tag_nvidia(const struct tag *tag)
}
__tagtable(ATAG_NVIDIA, parse_tag_nvidia);
-static struct tegra_utmip_config utmi_phy_config = {
- .hssync_start_delay = 0,
- .idle_wait_delay = 17,
- .elastic_limit = 16,
- .term_range_adj = 6,
- .xcvr_setup = 9,
- .xcvr_lsfslew = 2,
- .xcvr_lsrslew = 2,
+
+static struct tegra_usb_platform_data tegra_udc_pdata = {
+ .port_otg = false,
+ .has_hostpc = false,
+ .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,
+ .elastic_limit = 16,
+ .idle_wait_delay = 17,
+ .term_range_adj = 6,
+ .xcvr_setup = 8,
+ .xcvr_lsfslew = 2,
+ .xcvr_lsrslew = 2,
+ .xcvr_setup_offset = 0,
+ .xcvr_use_fuses = 1,
+ },
};
-static struct tegra_ehci_platform_data tegra_ehci_pdata = {
- .phy_config = &utmi_phy_config,
- .operating_mode = TEGRA_USB_HOST,
- .power_down_on_bus_suspend = 1,
+static struct tegra_usb_platform_data tegra_ehci3_utmi_pdata = {
+ .port_otg = false,
+ .has_hostpc = false,
+ .phy_intf = TEGRA_USB_PHY_INTF_UTMI,
+ .op_mode = TEGRA_USB_OPMODE_HOST,
+ .u_data.host = {
+ .vbus_gpio = TEGRA_GPIO_PD3,
+ .vbus_reg = NULL,
+ .hot_plug = true,
+ .remote_wakeup_supported = false,
+ .power_off_on_suspend = true,
+ },
+ .u_cfg.utmi = {
+ .hssync_start_delay = 9,
+ .elastic_limit = 16,
+ .idle_wait_delay = 17,
+ .term_range_adj = 6,
+ .xcvr_setup = 8,
+ .xcvr_lsfslew = 2,
+ .xcvr_lsrslew = 2,
+ },
};
static struct tegra_nand_chip_parms nand_chip_parms[] = {
@@ -283,39 +318,6 @@ static void __init harmony_i2c_init(void)
i2c_register_board_info(0, &wm8903_board_info, 1);
}
-/* OTG gadget device */
-/*static u64 tegra_otg_dmamask = DMA_BIT_MASK(32);
-
-
-static struct resource tegra_otg_resources[] = {
- [0] = {
- .start = TEGRA_USB_BASE,
- .end = TEGRA_USB_BASE + TEGRA_USB_SIZE - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = INT_USB,
- .end = INT_USB,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct fsl_usb2_platform_data tegra_otg_pdata = {
- .operating_mode = FSL_USB2_DR_DEVICE,
- .phy_mode = FSL_USB2_PHY_UTMI,
-};
-
-static struct platform_device tegra_otg = {
- .name = "fsl-tegra-udc",
- .id = -1,
- .dev = {
- .dma_mask = &tegra_otg_dmamask,
- .coherent_dma_mask = 0xffffffff,
- .platform_data = &tegra_otg_pdata,
- },
- .resource = tegra_otg_resources,
- .num_resources = ARRAY_SIZE(tegra_otg_resources),
-};*/
/* PDA power */
static struct pda_power_pdata pda_power_pdata = {
@@ -329,17 +331,36 @@ static struct platform_device pda_power_device = {
},
};
-static void harmony_debug_uart_init(void)
+static struct platform_device *harmony_uart_devices[] __initdata = {
+ &tegra_uartd_device,
+};
+
+static struct uart_clk_parent uart_parent_clk[] __initdata = {
+ [0] = {.name = "pll_p"},
+ [1] = {.name = "pll_m"},
+ [2] = {.name = "clk_m"},
+};
+
+static struct tegra_uart_platform_data harmony_uart_pdata;
+
+static void __init uart_debug_init(void)
{
+ unsigned long rate;
struct clk *c;
- debug_uart_clk = clk_get_sys("serial8250.0", "uartd");
+ /* UARTD is the debug port. */
+ pr_info("Selecting UARTD as the debug console\n");
+ harmony_uart_devices[0] = &debug_uartd_device;
debug_uart_port_base = ((struct plat_serial8250_port *)(
- debug_uartd_device.dev.platform_data))->mapbase;
+ debug_uartd_device.dev.platform_data))->mapbase;
+ debug_uart_clk = clk_get_sys("serial8250.0", "uartd");
+ /* Clock enable for the debug channel */
if (!IS_ERR_OR_NULL(debug_uart_clk)) {
+ rate = ((struct plat_serial8250_port *)(
+ debug_uartd_device.dev.platform_data))->uartclk;
pr_info("The debug console clock name is %s\n",
- debug_uart_clk->name);
+ debug_uart_clk->name);
c = tegra_get_clock_by_name("pll_p");
if (IS_ERR_OR_NULL(c))
pr_err("Not getting the parent clock pll_p\n");
@@ -347,16 +368,41 @@ static void harmony_debug_uart_init(void)
clk_set_parent(debug_uart_clk, c);
clk_enable(debug_uart_clk);
- clk_set_rate(debug_uart_clk, clk_get_rate(c));
+ clk_set_rate(debug_uart_clk, rate);
} else {
pr_err("Not getting the clock %s for debug console\n",
debug_uart_clk->name);
}
- return;
+}
+
+static void __init harmony_uart_init(void)
+{
+ int i;
+ struct clk *c;
+
+ for (i = 0; i < ARRAY_SIZE(uart_parent_clk); ++i) {
+ c = tegra_get_clock_by_name(uart_parent_clk[i].name);
+ if (IS_ERR_OR_NULL(c)) {
+ pr_err("Not able to get the clock for %s\n",
+ uart_parent_clk[i].name);
+ continue;
+ }
+ uart_parent_clk[i].parent_clk = c;
+ uart_parent_clk[i].fixed_clk_rate = clk_get_rate(c);
+ }
+ harmony_uart_pdata.parent_clk_list = uart_parent_clk;
+ harmony_uart_pdata.parent_clk_count = ARRAY_SIZE(uart_parent_clk);
+ tegra_uartd_device.dev.platform_data = &harmony_uart_pdata;
+
+ /* Register low speed only if it is selected */
+ if (!is_tegra_debug_uartport_hs())
+ uart_debug_init();
+
+ platform_add_devices(harmony_uart_devices,
+ ARRAY_SIZE(harmony_uart_devices));
}
static struct platform_device *harmony_devices[] __initdata = {
- &debug_uartd_device,
&tegra_sdhci_device1,
&tegra_sdhci_device2,
&tegra_sdhci_device4,
@@ -470,13 +516,14 @@ static void __init tegra_harmony_init(void)
harmony_keys_init();
- harmony_debug_uart_init();
+ harmony_uart_init();
tegra_sdhci_device1.dev.platform_data = &sdhci_pdata1;
tegra_sdhci_device2.dev.platform_data = &sdhci_pdata2;
tegra_sdhci_device4.dev.platform_data = &sdhci_pdata4;
- tegra_ehci3_device.dev.platform_data = &tegra_ehci_pdata;
+ tegra_udc_device.dev.platform_data = &tegra_udc_pdata;
+ tegra_ehci3_device.dev.platform_data = &tegra_ehci3_utmi_pdata;
platform_add_devices(harmony_devices, ARRAY_SIZE(harmony_devices));
harmony_i2c_init();
diff --git a/arch/arm/mach-tegra/board-kai-kbc.c b/arch/arm/mach-tegra/board-kai-kbc.c
index 928e5de707c9..7f0efdf572b2 100644
--- a/arch/arm/mach-tegra/board-kai-kbc.c
+++ b/arch/arm/mach-tegra/board-kai-kbc.c
@@ -86,17 +86,7 @@ static struct platform_device kai_keys_device = {
int __init kai_keys_init(void)
{
- int i;
-
pr_info("Registering gpio keys\n");
-
- /* Enable gpio mode for other pins */
- for (i = 0; i < kai_keys_platform_data.nbuttons; i++) {
- if (kai_keys_platform_data.buttons[i].gpio < 0)
- continue;
- tegra_gpio_enable(kai_keys_platform_data.buttons[i].gpio);
- }
-
platform_device_register(&kai_keys_device);
return 0;
diff --git a/arch/arm/mach-tegra/board-kai-panel.c b/arch/arm/mach-tegra/board-kai-panel.c
index 53661ced7c8e..e16b17c919ee 100644
--- a/arch/arm/mach-tegra/board-kai-panel.c
+++ b/arch/arm/mach-tegra/board-kai-panel.c
@@ -27,7 +27,7 @@
#include <linux/pwm_backlight.h>
#include <asm/atomic.h>
#include <linux/nvhost.h>
-#include <mach/nvmap.h>
+#include <linux/nvmap.h>
#include <mach/irqs.h>
#include <mach/iomap.h>
#include <mach/dc.h>
@@ -37,6 +37,7 @@
#include "board-kai.h"
#include "devices.h"
#include "gpio-names.h"
+#include "tegra3_host1x_devices.h"
/* kai default display board pins */
#define kai_lvds_avdd_en TEGRA_GPIO_PH6
@@ -111,8 +112,6 @@ static int kai_backlight_init(struct device *dev)
if (WARN_ON(ARRAY_SIZE(kai_bl_output_measured) != 256))
pr_err("bl_output array does not have 256 elements\n");
- tegra_gpio_disable(kai_bl_pwm);
-
ret = gpio_request(kai_bl_enb, "backlight_enb");
if (ret < 0)
return ret;
@@ -120,8 +119,6 @@ static int kai_backlight_init(struct device *dev)
ret = gpio_direction_output(kai_bl_enb, 1);
if (ret < 0)
gpio_free(kai_bl_enb);
- else
- tegra_gpio_enable(kai_bl_enb);
return ret;
};
@@ -132,7 +129,6 @@ static void kai_backlight_exit(struct device *dev)
/*ret = gpio_request(kai_bl_enb, "backlight_enb");*/
gpio_set_value(kai_bl_enb, 0);
gpio_free(kai_bl_enb);
- tegra_gpio_disable(kai_bl_enb);
return;
}
@@ -177,7 +173,7 @@ static struct platform_device kai_backlight_device = {
},
};
-static int kai_panel_enable(void)
+static int kai_panel_postpoweron(void)
{
if (kai_lvds_reg == NULL) {
kai_lvds_reg = regulator_get(NULL, "vdd_lvds");
@@ -188,15 +184,6 @@ static int kai_panel_enable(void)
regulator_enable(kai_lvds_reg);
}
- if (kai_lvds_vdd_panel == NULL) {
- kai_lvds_vdd_panel = regulator_get(NULL, "vdd_lcd_panel");
- if (WARN_ON(IS_ERR(kai_lvds_vdd_panel)))
- pr_err("%s: couldn't get regulator vdd_lcd_panel: %ld\n",
- __func__, PTR_ERR(kai_lvds_vdd_panel));
- else
- regulator_enable(kai_lvds_vdd_panel);
- }
-
mdelay(5);
gpio_set_value(kai_lvds_avdd_en, 1);
@@ -212,8 +199,31 @@ static int kai_panel_enable(void)
return 0;
}
+static int kai_panel_enable(void)
+{
+ if (kai_lvds_vdd_panel == NULL) {
+ kai_lvds_vdd_panel = regulator_get(NULL, "vdd_lcd_panel");
+ if (WARN_ON(IS_ERR(kai_lvds_vdd_panel)))
+ pr_err("%s: couldn't get regulator vdd_lcd_panel: %ld\n",
+ __func__, PTR_ERR(kai_lvds_vdd_panel));
+ else
+ regulator_enable(kai_lvds_vdd_panel);
+ }
+
+ return 0;
+}
+
static int kai_panel_disable(void)
{
+ regulator_disable(kai_lvds_vdd_panel);
+ regulator_put(kai_lvds_vdd_panel);
+ kai_lvds_vdd_panel = NULL;
+
+ return 0;
+}
+
+static int kai_panel_prepoweroff(void)
+{
gpio_set_value(kai_lvds_lr, 0);
gpio_set_value(kai_lvds_shutdown, 0);
gpio_set_value(kai_lvds_rst, 0);
@@ -227,10 +237,6 @@ static int kai_panel_disable(void)
regulator_put(kai_lvds_reg);
kai_lvds_reg = NULL;
- regulator_disable(kai_lvds_vdd_panel);
- regulator_put(kai_lvds_vdd_panel);
- kai_lvds_vdd_panel = NULL;
-
return 0;
}
@@ -530,6 +536,8 @@ static struct tegra_dc_out kai_disp1_out = {
.n_modes = ARRAY_SIZE(kai_panel_modes),
.enable = kai_panel_enable,
+ .postpoweron = kai_panel_postpoweron,
+ .prepoweroff = kai_panel_prepoweroff,
.disable = kai_panel_disable,
};
@@ -620,27 +628,17 @@ static void kai_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_save_default_governor();
- cpufreq_set_conservative_governor();
- cpufreq_set_conservative_governor_param("up_threshold",
- SET_CONSERVATIVE_GOVERNOR_UP_THRESHOLD);
-
- cpufreq_set_conservative_governor_param("down_threshold",
- SET_CONSERVATIVE_GOVERNOR_DOWN_THRESHOLD);
-
- cpufreq_set_conservative_governor_param("freq_step",
- SET_CONSERVATIVE_GOVERNOR_FREQ_STEP);
+ cpufreq_store_default_gov();
+ cpufreq_change_gov(cpufreq_conservative_gov);
#endif
-
}
static void kai_panel_late_resume(struct early_suspend *h)
{
unsigned i;
#ifdef CONFIG_TEGRA_CONVSERVATIVE_GOV_ON_EARLYSUPSEND
- cpufreq_restore_default_governor();
+ cpufreq_restore_default_gov();
#endif
for (i = 0; i < num_registered_fb; i++)
fb_blank(registered_fb[i], FB_BLANK_UNBLANK);
@@ -661,35 +659,27 @@ int __init kai_panel_init(void)
#endif
gpio_request(kai_lvds_avdd_en, "lvds_avdd_en");
gpio_direction_output(kai_lvds_avdd_en, 1);
- tegra_gpio_enable(kai_lvds_avdd_en);
gpio_request(kai_lvds_stdby, "lvds_stdby");
gpio_direction_output(kai_lvds_stdby, 1);
- tegra_gpio_enable(kai_lvds_stdby);
gpio_request(kai_lvds_rst, "lvds_rst");
gpio_direction_output(kai_lvds_rst, 1);
- tegra_gpio_enable(kai_lvds_rst);
if (board_info.fab == BOARD_FAB_A00) {
gpio_request(kai_lvds_rs_a00, "lvds_rs");
gpio_direction_output(kai_lvds_rs_a00, 0);
- tegra_gpio_enable(kai_lvds_rs_a00);
} else {
gpio_request(kai_lvds_rs, "lvds_rs");
gpio_direction_output(kai_lvds_rs, 0);
- tegra_gpio_enable(kai_lvds_rs);
}
gpio_request(kai_lvds_lr, "lvds_lr");
gpio_direction_output(kai_lvds_lr, 1);
- tegra_gpio_enable(kai_lvds_lr);
gpio_request(kai_lvds_shutdown, "lvds_shutdown");
gpio_direction_output(kai_lvds_shutdown, 1);
- tegra_gpio_enable(kai_lvds_shutdown);
- tegra_gpio_enable(kai_hdmi_hpd);
gpio_request(kai_hdmi_hpd, "hdmi_hpd");
gpio_direction_input(kai_hdmi_hpd);
@@ -701,7 +691,7 @@ int __init kai_panel_init(void)
#endif
#ifdef CONFIG_TEGRA_GRHOST
- err = nvhost_device_register(&tegra_grhost_device);
+ err = tegra3_register_host1x_devices();
if (err)
return err;
#endif
diff --git a/arch/arm/mach-tegra/board-kai-pinmux.c b/arch/arm/mach-tegra/board-kai-pinmux.c
index 1bc64bdb1558..be11d4ef6698 100644
--- a/arch/arm/mach-tegra/board-kai-pinmux.c
+++ b/arch/arm/mach-tegra/board-kai-pinmux.c
@@ -379,7 +379,7 @@ static __initdata struct tegra_pingroup_config kai_pinmux_common[] = {
DEFAULT_PINMUX(SPI2_MISO, SPI2, NORMAL, NORMAL, INPUT),
DEFAULT_PINMUX(SPI2_MOSI, SPI2, NORMAL, NORMAL, INPUT),
- DEFAULT_PINMUX(KB_ROW11, KBC, NORMAL, NORMAL, OUTPUT),
+ DEFAULT_PINMUX(KB_ROW11, KBC, PULL_UP, TRISTATE, INPUT),
DEFAULT_PINMUX(KB_ROW12, KBC, NORMAL, TRISTATE, OUTPUT),
DEFAULT_PINMUX(KB_ROW13, KBC, NORMAL, TRISTATE, OUTPUT),
};
@@ -449,13 +449,9 @@ static __initdata struct tegra_pingroup_config unused_pins_lowpower[] = {
static void __init kai_pinmux_audio_init(void)
{
- tegra_gpio_enable(TEGRA_GPIO_CDC_IRQ);
gpio_request(TEGRA_GPIO_CDC_IRQ, "rt5640");
gpio_direction_input(TEGRA_GPIO_CDC_IRQ);
- tegra_gpio_enable(TEGRA_GPIO_HP_DET);
- tegra_gpio_enable(TEGRA_GPIO_INT_MIC_EN);
- tegra_gpio_enable(TEGRA_GPIO_EXT_MIC_EN);
}
/* We are disabling this code for now. */
@@ -469,6 +465,7 @@ static void __init kai_pinmux_audio_init(void)
static struct gpio_init_pin_info init_gpio_mode_kai_common[] = {
GPIO_INIT_PIN_MODE(TEGRA_GPIO_PDD7, false, 0),
GPIO_INIT_PIN_MODE(TEGRA_GPIO_PCC6, false, 0),
+ GPIO_INIT_PIN_MODE(TEGRA_GPIO_PCC7, false, 1),
};
static void __init kai_gpio_init_configure(void)
@@ -550,7 +547,6 @@ static void set_unused_pin_gpio(struct gpio_init_pin_info *lpm_pin_info,
gpio_free(pin_info->gpio_nr);
continue;
}
- tegra_gpio_enable(pin_info->gpio_nr);
}
}
diff --git a/arch/arm/mach-tegra/board-kai-power.c b/arch/arm/mach-tegra/board-kai-power.c
index f397963dba60..6c66f1d2bbe9 100644
--- a/arch/arm/mach-tegra/board-kai-power.c
+++ b/arch/arm/mach-tegra/board-kai-power.c
@@ -40,7 +40,6 @@
#include "board.h"
#include "board-kai.h"
#include "pm.h"
-#include "wakeups-t3.h"
#include "tegra3_tsensor.h"
#define PMC_CTRL 0x0
@@ -178,16 +177,16 @@ static struct max77663_regulator_fps_cfg max77663_fps_cfgs[] = {
}
MAX77663_PDATA_INIT(sd0, 600000, 3387500, NULL, 1, 0, 0,
- 0, 0, -1, FPS_SRC_NONE, -1, -1, EN2_CTRL_SD0 | SD_FSRADE_DISABLE);
+ 0, 0, -1, FPS_SRC_NONE, -1, -1, EN2_CTRL_SD0);
MAX77663_PDATA_INIT(sd1, 800000, 1587500, NULL, 1, 0, 0,
- 1, 1, -1, FPS_SRC_1, -1, -1, SD_FSRADE_DISABLE);
+ 1, 1, -1, FPS_SRC_1, FPS_POWER_PERIOD_1, FPS_POWER_PERIOD_6, 0);
MAX77663_PDATA_INIT(sd2, 1800000, 1800000, NULL, 1, 0, 0,
- 1, 1, -1, FPS_SRC_NONE, -1, -1, 0);
+ 1, 1, -1, FPS_SRC_0, -1, -1, 0);
MAX77663_PDATA_INIT(sd3, 600000, 3387500, NULL, 1, 0, 0,
- 1, 1, -1, FPS_SRC_NONE, -1, -1, 0);
+ 1, 1, -1, FPS_SRC_0, -1, -1, 0);
MAX77663_PDATA_INIT(ldo0, 800000, 2350000, max77663_rails(sd3), 1, 0, 0,
1, 1, -1, FPS_SRC_1, -1, -1, 0);
@@ -199,10 +198,10 @@ MAX77663_PDATA_INIT(ldo2, 800000, 3950000, NULL, 1, 0, 0,
1, 1, -1, FPS_SRC_1, -1, -1, 0);
MAX77663_PDATA_INIT(ldo3, 800000, 3950000, NULL, 1, 0, 0,
- 1, 1, -1, FPS_SRC_NONE, -1, -1, 0);
+ 1, 1, -1, FPS_SRC_1, -1, -1, 0);
MAX77663_PDATA_INIT(ldo4, 800000, 1587500, NULL, 0, 0, 0,
- 1, 1, 1000000, FPS_SRC_NONE, -1, -1, LDO4_EN_TRACKING);
+ 1, 1, 1000000, FPS_SRC_0, -1, -1, LDO4_EN_TRACKING);
MAX77663_PDATA_INIT(ldo5, 800000, 2800000, NULL, 0, 0, 0,
1, 1, -1, FPS_SRC_NONE, -1, -1, 0);
@@ -272,9 +271,9 @@ static struct max77663_gpio_config max77663_gpio_cfgs[] = {
{
.gpio = MAX77663_GPIO3,
.dir = GPIO_DIR_OUT,
- .dout = GPIO_DOUT_HIGH,
+ .dout = GPIO_DOUT_LOW,
.out_drv = GPIO_OUT_DRV_OPEN_DRAIN,
- .alternate = GPIO_ALT_DISABLE,
+ .alternate = GPIO_ALT_ENABLE,
},
{
.gpio = MAX77663_GPIO4,
@@ -485,7 +484,7 @@ FIXED_REG(4, en_vddio_vid_a01, en_vddio_vid, NULL,
FIXED_REG(5, en_3v3_modem_a01, en_3v3_modem, NULL,
0, 1, TEGRA_GPIO_PP0, true, 0, 3300);
FIXED_REG(6, en_vdd_pnl_a01, en_vdd_pnl, FIXED_SUPPLY(en_3v3_sys_a01),
- 0, 0, TEGRA_GPIO_PW1, true, 0, 3300);
+ 0, 1, TEGRA_GPIO_PW1, true, 0, 3300);
FIXED_REG(7, en_cam3_ldo_a01, en_cam3_ldo, FIXED_SUPPLY(en_3v3_sys_a01),
0, 0, TEGRA_GPIO_PR7, true, 0, 3300);
FIXED_REG(8, en_vdd_com_a01, en_vdd_com, FIXED_SUPPLY(en_3v3_sys_a01),
@@ -567,8 +566,6 @@ static int __init kai_fixed_regulator_init(void)
fixed_reg_devs[i]->dev.platform_data;
gpio_nr = fixed_reg_pdata->gpio;
- if (gpio_nr < TEGRA_NR_GPIOS)
- tegra_gpio_enable(gpio_nr);
}
return platform_add_devices(fixed_reg_devs, nfixreg_devs);
diff --git a/arch/arm/mach-tegra/board-kai-sdhci.c b/arch/arm/mach-tegra/board-kai-sdhci.c
index 2a346fa20d4c..0fa39ccf475d 100644
--- a/arch/arm/mach-tegra/board-kai-sdhci.c
+++ b/arch/arm/mach-tegra/board-kai-sdhci.c
@@ -106,6 +106,7 @@ static struct tegra_sdhci_platform_data tegra_sdhci_platform_data2 = {
.mmc_data = {
.register_status_notify = kai_wifi_status_register,
.built_in = 0,
+ .ocr_mask = MMC_OCR_1V8_MASK,
},
#ifndef CONFIG_MMC_EMBEDDED_SDIO
.pm_flags = MMC_PM_KEEP_POWER,
@@ -113,8 +114,9 @@ static struct tegra_sdhci_platform_data tegra_sdhci_platform_data2 = {
.cd_gpio = -1,
.wp_gpio = -1,
.power_gpio = -1,
-/* .tap_delay = 6,
- .is_voltage_switch_supported = false,
+ .tap_delay = 0x0F,
+ .ddr_clk_limit = 41000000,
+/* .is_voltage_switch_supported = false,
.vdd_rail_name = NULL,
.slot_rail_name = NULL,
.vdd_max_uv = -1,
@@ -128,8 +130,9 @@ static struct tegra_sdhci_platform_data tegra_sdhci_platform_data0 = {
.cd_gpio = KAI_SD_CD,
.wp_gpio = -1,
.power_gpio = -1,
-/* .tap_delay = 6,
- .is_voltage_switch_supported = true,
+ .tap_delay = 0x0F,
+ .ddr_clk_limit = 41000000,
+/* .is_voltage_switch_supported = true,
.vdd_rail_name = "vddio_sdmmc1",
.slot_rail_name = "vddio_sd_slot",
.vdd_max_uv = 3320000,
@@ -144,11 +147,11 @@ static struct tegra_sdhci_platform_data tegra_sdhci_platform_data3 = {
.power_gpio = -1,
.is_8bit = 1,
.tap_delay = 0x0F,
+ .ddr_clk_limit = 41000000,
.mmc_data = {
.built_in = 1,
}
-/* .tap_delay = 6,
- .is_voltage_switch_supported = false,
+/* .is_voltage_switch_supported = false,
.vdd_rail_name = NULL,
.slot_rail_name = NULL,
.vdd_max_uv = -1,
@@ -241,9 +244,6 @@ static int __init kai_wifi_init(void)
if (rc)
pr_err("WLAN_IRQ gpio request failed:%d\n", rc);
- tegra_gpio_enable(KAI_WLAN_EN);
- tegra_gpio_enable(KAI_WLAN_IRQ);
-
rc = gpio_direction_output(KAI_WLAN_EN, 0);
if (rc)
pr_err("WLAN_EN gpio direction configuration failed:%d\n", rc);
diff --git a/arch/arm/mach-tegra/board-kai-sensors.c b/arch/arm/mach-tegra/board-kai-sensors.c
index df260a5ec5c5..29d1bea2e8a7 100644
--- a/arch/arm/mach-tegra/board-kai-sensors.c
+++ b/arch/arm/mach-tegra/board-kai-sensors.c
@@ -21,11 +21,14 @@
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/i2c.h>
+#include <linux/nct1008.h>
#include <linux/cm3217.h>
#include <linux/mpu.h>
#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
#include <asm/mach-types.h>
#include <mach/gpio.h>
+#include <mach/thermal.h>
#include <media/ov2710.h>
#include "board.h"
#include "board-kai.h"
@@ -34,6 +37,108 @@
static struct regulator *kai_1v8_cam3;
static struct regulator *kai_vdd_cam3;
+#ifndef CONFIG_TEGRA_INTERNAL_TSENSOR_EDP_SUPPORT
+static int nct_get_temp(void *_data, long *temp)
+{
+ struct nct1008_data *data = _data;
+ return nct1008_thermal_get_temp(data, temp);
+}
+
+static int nct_get_temp_low(void *_data, long *temp)
+{
+ struct nct1008_data *data = _data;
+ return nct1008_thermal_get_temp_low(data, temp);
+}
+
+static int nct_set_limits(void *_data,
+ long lo_limit_milli,
+ long hi_limit_milli)
+{
+ struct nct1008_data *data = _data;
+ return nct1008_thermal_set_limits(data,
+ lo_limit_milli,
+ hi_limit_milli);
+}
+
+static int nct_set_alert(void *_data,
+ void (*alert_func)(void *),
+ void *alert_data)
+{
+ struct nct1008_data *data = _data;
+ return nct1008_thermal_set_alert(data, alert_func, alert_data);
+}
+
+static int nct_set_shutdown_temp(void *_data, long shutdown_temp)
+{
+ struct nct1008_data *data = _data;
+ return nct1008_thermal_set_shutdown_temp(data, shutdown_temp);
+}
+
+static void nct1008_probe_callback(struct nct1008_data *data)
+{
+ struct tegra_thermal_device *thermal_device;
+
+ thermal_device = kzalloc(sizeof(struct tegra_thermal_device),
+ GFP_KERNEL);
+ if (!thermal_device) {
+ pr_err("unable to allocate thermal device\n");
+ return;
+ }
+
+ thermal_device->name = "nct72";
+ thermal_device->data = data;
+ thermal_device->id = THERMAL_DEVICE_ID_NCT_EXT;
+ thermal_device->offset = TDIODE_OFFSET;
+ thermal_device->get_temp = nct_get_temp;
+ thermal_device->get_temp_low = nct_get_temp_low;
+ thermal_device->set_limits = nct_set_limits;
+ thermal_device->set_alert = nct_set_alert;
+ thermal_device->set_shutdown_temp = nct_set_shutdown_temp;
+
+ tegra_thermal_device_register(thermal_device);
+}
+#endif
+
+static struct nct1008_platform_data kai_nct1008_pdata = {
+ .supported_hwrev = true,
+ .ext_range = true,
+ .conv_rate = 0x09, /* 0x09 corresponds to 32Hz conversion rate */
+ .offset = 8, /* 4 * 2C. 1C for device accuracies */
+#ifndef CONFIG_TEGRA_INTERNAL_TSENSOR_EDP_SUPPORT
+ .probe_callback = nct1008_probe_callback,
+#endif
+};
+
+static struct i2c_board_info kai_i2c4_nct1008_board_info[] = {
+ {
+ I2C_BOARD_INFO("nct72", 0x4C),
+ .platform_data = &kai_nct1008_pdata,
+ .irq = -1,
+ }
+};
+
+static int kai_nct1008_init(void)
+{
+ int ret = 0;
+
+ /* FIXME: enable irq when throttling is supported */
+ kai_i2c4_nct1008_board_info[0].irq =
+ TEGRA_GPIO_TO_IRQ(KAI_TEMP_ALERT_GPIO);
+
+ ret = gpio_request(KAI_TEMP_ALERT_GPIO, "temp_alert");
+ if (ret < 0) {
+ pr_err("%s: gpio_request failed\n", __func__);
+ return ret;
+ }
+
+ ret = gpio_direction_input(KAI_TEMP_ALERT_GPIO);
+ if (ret < 0) {
+ pr_err("%s: set gpio to input failed\n", __func__);
+ gpio_free(KAI_TEMP_ALERT_GPIO);
+ }
+ return ret;
+}
+
static struct cm3217_platform_data kai_cm3217_pdata = {
.levels = {10, 160, 225, 320, 640, 1280, 2600, 5800, 8000, 10240},
.golden_adc = 0,
@@ -51,7 +156,6 @@ static int kai_camera_init(void)
{
int ret;
- tegra_gpio_enable(CAM2_POWER_DWN_GPIO);
ret = gpio_request(CAM2_POWER_DWN_GPIO, "cam2_power_en");
if (ret < 0) {
pr_err("%s: gpio_request failed for gpio %s\n",
@@ -61,7 +165,6 @@ static int kai_camera_init(void)
gpio_direction_output(CAM2_POWER_DWN_GPIO, 1);
mdelay(10);
- tegra_gpio_enable(CAM2_RST_GPIO);
ret = gpio_request(CAM2_RST_GPIO, "cam2_reset");
if (ret < 0) {
pr_err("%s: gpio_request failed for gpio %s\n",
@@ -207,7 +310,6 @@ static void mpuirq_init(void)
#if (MPU_GYRO_TYPE == MPU_TYPE_MPU3050)
#if MPU_ACCEL_IRQ_GPIO
/* ACCEL-IRQ assignment */
- tegra_gpio_enable(MPU_ACCEL_IRQ_GPIO);
ret = gpio_request(MPU_ACCEL_IRQ_GPIO, MPU_ACCEL_NAME);
if (ret < 0) {
pr_err("%s: gpio_request failed %d\n", __func__, ret);
@@ -224,7 +326,6 @@ static void mpuirq_init(void)
#endif
/* MPU-IRQ assignment */
- tegra_gpio_enable(MPU_GYRO_IRQ_GPIO);
ret = gpio_request(MPU_GYRO_IRQ_GPIO, MPU_GYRO_NAME);
if (ret < 0) {
pr_err("%s: gpio_request failed %d\n", __func__, ret);
@@ -245,6 +346,15 @@ static void mpuirq_init(void)
int __init kai_sensors_init(void)
{
+ int err;
+
+ err = kai_nct1008_init();
+ if (err)
+ pr_err("%s: nct1008 init failed\n", __func__);
+ else
+ i2c_register_board_info(4, kai_i2c4_nct1008_board_info,
+ ARRAY_SIZE(kai_i2c4_nct1008_board_info));
+
kai_camera_init();
i2c_register_board_info(2, kai_i2c2_board_info,
diff --git a/arch/arm/mach-tegra/board-kai.c b/arch/arm/mach-tegra/board-kai.c
index 38f12f9313d1..bf4ae415072d 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.
+ * 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
@@ -56,70 +56,74 @@
#include <asm/mach/arch.h>
#include <mach/usb_phy.h>
#include <mach/thermal.h>
+#include <mach/tegra_fiq_debugger.h>
#include "board.h"
#include "clock.h"
#include "board-kai.h"
+#include "board-touch.h"
#include "devices.h"
#include "gpio-names.h"
#include "fuse.h"
#include "pm.h"
#include "wdt-recovery.h"
+static struct balanced_throttle throttle_list[] = {
+ {
+ .id = BALANCED_THROTTLE_ID_TJ,
+ .throt_tab_size = 10,
+ .throt_tab = {
+ { 0, 1000 },
+ { 640000, 1000 },
+ { 640000, 1000 },
+ { 640000, 1000 },
+ { 640000, 1000 },
+ { 640000, 1000 },
+ { 760000, 1000 },
+ { 760000, 1050 },
+ {1000000, 1050 },
+ {1000000, 1100 },
+ },
+ },
+#ifdef CONFIG_TEGRA_SKIN_THROTTLE
+ {
+ .id = BALANCED_THROTTLE_ID_SKIN,
+ .throt_tab_size = 6,
+ .throt_tab = {
+ { 640000, 1200 },
+ { 640000, 1200 },
+ { 760000, 1200 },
+ { 760000, 1200 },
+ {1000000, 1200 },
+ {1000000, 1200 },
+ },
+ },
+#endif
+};
+
/* All units are in millicelsius */
static struct tegra_thermal_data thermal_data = {
- .temp_throttle = 85000,
+ .shutdown_device_id = THERMAL_DEVICE_ID_NCT_EXT,
.temp_shutdown = 90000,
- .temp_offset = TDIODE_OFFSET, /* temps based on tdiode */
+#if defined(CONFIG_TEGRA_EDP_LIMITS) || defined(CONFIG_TEGRA_THERMAL_THROTTLE)
+ .throttle_edp_device_id = THERMAL_DEVICE_ID_NCT_EXT,
+#endif
#ifdef CONFIG_TEGRA_EDP_LIMITS
.edp_offset = TDIODE_OFFSET, /* edp based on tdiode */
.hysteresis_edp = 3000,
#endif
-#ifdef CONFIG_TEGRA_THERMAL_SYSFS
+#ifdef CONFIG_TEGRA_THERMAL_THROTTLE
+ .temp_throttle = 85000,
.tc1 = 0,
.tc2 = 1,
.passive_delay = 2000,
-#else
- .hysteresis_throttle = 1000,
+#endif
+#ifdef CONFIG_TEGRA_SKIN_THROTTLE
+ .skin_device_id = THERMAL_DEVICE_ID_SKIN,
+ .temp_throttle_skin = 43000,
#endif
};
-/* !!!TODO: Change for kai (Taken from Ventana) */
-static struct tegra_utmip_config utmi_phy_config[] = {
- [0] = {
- .hssync_start_delay = 0,
- .idle_wait_delay = 17,
- .elastic_limit = 16,
- .term_range_adj = 6,
- .xcvr_setup = 15,
- .xcvr_setup_offset = 0,
- .xcvr_use_fuses = 1,
- .xcvr_lsfslew = 2,
- .xcvr_lsrslew = 2,
- },
- [1] = {
- .hssync_start_delay = 0,
- .idle_wait_delay = 17,
- .elastic_limit = 16,
- .term_range_adj = 6,
- .xcvr_setup = 15,
- .xcvr_setup_offset = 0,
- .xcvr_use_fuses = 1,
- .xcvr_lsfslew = 2,
- .xcvr_lsrslew = 2,
- },
- [2] = {
- .hssync_start_delay = 0,
- .idle_wait_delay = 17,
- .elastic_limit = 16,
- .term_range_adj = 6,
- .xcvr_setup = 8,
- .xcvr_setup_offset = 0,
- .xcvr_use_fuses = 1,
- .xcvr_lsfslew = 2,
- .xcvr_lsrslew = 2,
- },
-};
/* wl128x BT, FM, GPS connectivity chip */
struct ti_st_plat_data kai_wilink_pdata = {
@@ -146,11 +150,16 @@ static noinline void __init kai_bt_st(void)
platform_device_register(&wl128x_device);
platform_device_register(&btwilink_device);
- tegra_gpio_enable(TEGRA_GPIO_PU0);
}
static struct resource kai_bluesleep_resources[] = {
[0] = {
+ .name = "gpio_host_wake",
+ .start = TEGRA_GPIO_PU6,
+ .end = TEGRA_GPIO_PU6,
+ .flags = IORESOURCE_IO,
+ },
+ [1] = {
.name = "host_wake",
.start = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PU6),
.end = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PU6),
@@ -159,7 +168,7 @@ static struct resource kai_bluesleep_resources[] = {
};
static struct platform_device kai_bluesleep_device = {
- .name = "tibluesleep",
+ .name = "bluesleep",
.id = 0,
.num_resources = ARRAY_SIZE(kai_bluesleep_resources),
.resource = kai_bluesleep_resources,
@@ -168,7 +177,6 @@ static struct platform_device kai_bluesleep_device = {
static noinline void __init kai_tegra_setup_tibluesleep(void)
{
platform_device_register(&kai_bluesleep_device);
- tegra_gpio_enable(TEGRA_GPIO_PU6);
}
static __initdata struct tegra_clk_init_table kai_clk_init_table[] = {
@@ -296,11 +304,17 @@ static struct regulator_consumer_supply smb349_vbus_supply[] = {
REGULATOR_SUPPLY("usb_bat_chg", NULL),
};
+static struct regulator_consumer_supply smb349_otg_vbus_supply[] = {
+ REGULATOR_SUPPLY("usb_vbus_otg", NULL),
+};
+
static struct smb349_charger_platform_data smb349_charger_pdata = {
.max_charge_current_mA = 1000,
.charging_term_current_mA = 100,
.consumer_supplies = smb349_vbus_supply,
.num_consumer_supplies = ARRAY_SIZE(smb349_vbus_supply),
+ .otg_consumer_supplies = smb349_otg_vbus_supply,
+ .num_otg_consumer_supplies = ARRAY_SIZE(smb349_otg_vbus_supply),
};
static struct i2c_board_info kai_i2c4_smb349_board_info[] = {
@@ -496,7 +510,6 @@ static struct platform_device tegra_camera = {
};
static struct platform_device *kai_spi_devices[] __initdata = {
- &tegra_spi_device4,
&tegra_spi_device1,
};
@@ -510,11 +523,11 @@ static struct spi_clk_parent spi_parent_clk[] = {
#endif
};
-static struct tegra_spi_platform_data kai_spi_pdata = {
- .is_dma_based = true,
- .max_dma_buffer = (16 * 1024),
- .is_clkon_always = false,
- .max_rate = 100000000,
+static struct tegra_spi_platform_data kai_spi1_pdata = {
+ .is_dma_based = true,
+ .max_dma_buffer = (128),
+ .is_clkon_always = false,
+ .max_rate = 100000000,
};
static void __init kai_spi_init(void)
@@ -532,9 +545,10 @@ static void __init kai_spi_init(void)
spi_parent_clk[i].parent_clk = c;
spi_parent_clk[i].fixed_clk_rate = clk_get_rate(c);
}
- kai_spi_pdata.parent_clk_list = spi_parent_clk;
- kai_spi_pdata.parent_clk_count = ARRAY_SIZE(spi_parent_clk);
- tegra_spi_device4.dev.platform_data = &kai_spi_pdata;
+
+ kai_spi1_pdata.parent_clk_list = spi_parent_clk;
+ kai_spi1_pdata.parent_clk_count = ARRAY_SIZE(spi_parent_clk);
+ tegra_spi_device1.dev.platform_data = &kai_spi1_pdata;
platform_add_devices(kai_spi_devices,
ARRAY_SIZE(kai_spi_devices));
@@ -607,7 +621,9 @@ static struct platform_device *kai_devices[] __initdata = {
#if defined(CONFIG_TEGRA_IOVMM_SMMU) || defined(CONFIG_TEGRA_IOMMU_SMMU)
&tegra_smmu_device,
#endif
- &tegra_wdt_device,
+ &tegra_wdt0_device,
+ &tegra_wdt1_device,
+ &tegra_wdt2_device,
#if defined(CONFIG_TEGRA_AVP)
&tegra_avp_device,
#endif
@@ -651,9 +667,6 @@ static int __init kai_touch_init(void)
{
int touch_id;
- tegra_gpio_enable(KAI_TS_ID1);
- tegra_gpio_enable(KAI_TS_ID2);
-
gpio_request(KAI_TS_ID1, "touch-id1");
gpio_direction_input(KAI_TS_ID1);
@@ -697,47 +710,97 @@ static int __init kai_touch_init(void)
return 0;
}
-static struct tegra_ehci_platform_data tegra_ehci_pdata[] = {
- [0] = {
- .phy_config = &utmi_phy_config[0],
- .operating_mode = TEGRA_USB_HOST,
- .power_down_on_bus_suspend = 1,
- .default_enable = true,
+static struct tegra_usb_platform_data tegra_udc_pdata = {
+ .port_otg = true,
+ .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,
},
- [1] = {
- .phy_config = &utmi_phy_config[1],
- .operating_mode = TEGRA_USB_HOST,
- .power_down_on_bus_suspend = 1,
- .default_enable = false,
+ .u_cfg.utmi = {
+ .hssync_start_delay = 0,
+ .elastic_limit = 16,
+ .idle_wait_delay = 17,
+ .term_range_adj = 6,
+ .xcvr_setup = 8,
+ .xcvr_lsfslew = 2,
+ .xcvr_lsrslew = 2,
+ .xcvr_setup_offset = 0,
+ .xcvr_use_fuses = 1,
},
};
-static struct tegra_otg_platform_data tegra_otg_pdata = {
- .ehci_device = &tegra_ehci1_device,
- .ehci_pdata = &tegra_ehci_pdata[0],
+static struct tegra_usb_platform_data tegra_ehci1_utmi_pdata = {
+ .port_otg = true,
+ .has_hostpc = true,
+ .phy_intf = TEGRA_USB_PHY_INTF_UTMI,
+ .op_mode = TEGRA_USB_OPMODE_HOST,
+ .u_data.host = {
+ .vbus_gpio = -1,
+ .vbus_reg = "usb_vbus_otg",
+ .hot_plug = true,
+ .remote_wakeup_supported = true,
+ .power_off_on_suspend = true,
+ },
+ .u_cfg.utmi = {
+ .hssync_start_delay = 0,
+ .elastic_limit = 16,
+ .idle_wait_delay = 17,
+ .term_range_adj = 6,
+ .xcvr_setup = 15,
+ .xcvr_lsfslew = 2,
+ .xcvr_lsrslew = 2,
+ .xcvr_setup_offset = 0,
+ .xcvr_use_fuses = 1,
+ },
};
-#ifdef CONFIG_USB_SUPPORT
-static struct usb_phy_plat_data tegra_usb_phy_pdata[] = {
- [0] = {
- .instance = 0,
- .vbus_gpio = -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,
+
},
- [1] = {
- .instance = 1,
- .vbus_gpio = -1,
+ .u_cfg.utmi = {
+ .hssync_start_delay = 0,
+ .elastic_limit = 16,
+ .idle_wait_delay = 17,
+ .term_range_adj = 6,
+ .xcvr_setup = 8,
+ .xcvr_lsfslew = 2,
+ .xcvr_lsrslew = 2,
+ .xcvr_setup_offset = 0,
+ .xcvr_use_fuses = 1,
},
};
+static struct tegra_usb_otg_data tegra_otg_pdata = {
+ .ehci_device = &tegra_ehci1_device,
+ .ehci_pdata = &tegra_ehci1_utmi_pdata,
+};
+
+#if CONFIG_USB_SUPPORT
static void kai_usb_init(void)
{
- tegra_usb_phy_init(tegra_usb_phy_pdata,
- ARRAY_SIZE(tegra_usb_phy_pdata));
-
tegra_otg_device.dev.platform_data = &tegra_otg_pdata;
platform_device_register(&tegra_otg_device);
- tegra_ehci2_device.dev.platform_data = &tegra_ehci_pdata[1];
+ /* Setup the udc platform data */
+ tegra_udc_device.dev.platform_data = &tegra_udc_pdata;
+
+ tegra_ehci2_device.dev.platform_data = &tegra_ehci2_utmi_pdata;
platform_device_register(&tegra_ehci2_device);
}
@@ -745,10 +808,6 @@ static void kai_modem_init(void)
{
int ret;
- tegra_gpio_enable(TEGRA_GPIO_W_DISABLE);
- tegra_gpio_enable(TEGRA_GPIO_MODEM_RSVD1);
- tegra_gpio_enable(TEGRA_GPIO_MODEM_RSVD2);
-
ret = gpio_request(TEGRA_GPIO_W_DISABLE, "w_disable_gpio");
if (ret < 0)
pr_err("%s: gpio_request failed for gpio %d\n",
@@ -794,16 +853,11 @@ static void kai_audio_init(void)
}
}
-static void kai_nfc_init(void)
-{
- tegra_gpio_enable(TEGRA_GPIO_PX0);
- tegra_gpio_enable(TEGRA_GPIO_PS7);
- tegra_gpio_enable(TEGRA_GPIO_PR3);
-}
-
static void __init tegra_kai_init(void)
{
- tegra_thermal_init(&thermal_data);
+ tegra_thermal_init(&thermal_data,
+ throttle_list,
+ ARRAY_SIZE(throttle_list));
tegra_clk_init_from_table(kai_clk_init_table);
kai_pinmux_init();
kai_i2c_init();
@@ -813,7 +867,6 @@ static void __init tegra_kai_init(void)
kai_edp_init();
#endif
kai_uart_init();
- kai_tsensor_init();
kai_audio_init();
platform_add_devices(kai_devices, ARRAY_SIZE(kai_devices));
tegra_ram_console_debug_init();
@@ -823,9 +876,8 @@ static void __init tegra_kai_init(void)
kai_touch_init();
kai_keys_init();
kai_panel_init();
- kai_bt_st();
kai_tegra_setup_tibluesleep();
- kai_nfc_init();
+ kai_bt_st();
kai_sensors_init();
kai_pins_state_init();
kai_emc_init();
@@ -834,6 +886,7 @@ static void __init tegra_kai_init(void)
#ifdef CONFIG_TEGRA_WDT_RECOVERY
tegra_wdt_recovery_init();
#endif
+ tegra_serial_debug_init(TEGRA_UARTD_BASE, INT_WDT_CPU, NULL, -1, -1);
}
static void __init kai_ramconsole_reserve(unsigned long size)
diff --git a/arch/arm/mach-tegra/board-kai.h b/arch/arm/mach-tegra/board-kai.h
index 1f7c16ebf590..5039b972d000 100644
--- a/arch/arm/mach-tegra/board-kai.h
+++ b/arch/arm/mach-tegra/board-kai.h
@@ -81,7 +81,6 @@ int kai_pins_state_init(void);
int kai_emc_init(void);
int kai_edp_init(void);
void __init kai_tsensor_init(void);
-int __init touch_init_raydium(int irq_gpio, int reset_gpio, int platform);
int __init touch_init_synaptics_kai(void);
#define TOUCH_GPIO_IRQ_RAYDIUM_SPI TEGRA_GPIO_PZ3
@@ -95,6 +94,8 @@ int __init touch_init_synaptics_kai(void);
#define KAI_TS_ID1_PG TEGRA_PINGROUP_GMI_WAIT
#define KAI_TS_ID2_PG TEGRA_PINGROUP_GMI_WP_N
+#define KAI_TEMP_ALERT_GPIO TEGRA_GPIO_PS3
+
#define MPU_TYPE_MPU3050 1
#define MPU_TYPE_MPU6050 2
#define MPU_GYRO_TYPE MPU_TYPE_MPU6050
diff --git a/arch/arm/mach-tegra/board-p1852-panel.c b/arch/arm/mach-tegra/board-p1852-panel.c
index 8940af0c0b62..4e86476cdd2c 100644
--- a/arch/arm/mach-tegra/board-p1852-panel.c
+++ b/arch/arm/mach-tegra/board-p1852-panel.c
@@ -20,7 +20,7 @@
#include <asm/mach-types.h>
#include <linux/platform_device.h>
#include <linux/nvhost.h>
-#include <mach/nvmap.h>
+#include <linux/nvmap.h>
#include <mach/irqs.h>
#include <mach/iomap.h>
#include <mach/dc.h>
@@ -28,6 +28,7 @@
#include "board.h"
#include "devices.h"
+#include "tegra3_host1x_devices.h"
static int p1852_panel_enable(void)
{
@@ -39,6 +40,63 @@ static int p1852_panel_disable(void)
return 0;
}
+#ifdef CONFIG_TOUCHSCREEN_ATMEL_MXT
+
+static struct tegra_dc_mode p1852_panel_modes[] = {
+ {
+ /* 1366x768@60Hz */
+ .pclk = 74180000,
+ .h_ref_to_sync = 1,
+ .v_ref_to_sync = 1,
+ .h_sync_width = 30,
+ .v_sync_width = 5,
+ .h_back_porch = 52,
+ .v_back_porch = 20,
+ .h_active = 1366,
+ .v_active = 768,
+ .h_front_porch = 64,
+ .v_front_porch = 25,
+ },
+ {
+ /* 1366x768@50Hz */
+ .pclk = 74180000,
+ .h_ref_to_sync = 1,
+ .v_ref_to_sync = 1,
+ .h_sync_width = 30,
+ .v_sync_width = 5,
+ .h_back_porch = 56,
+ .v_back_porch = 80,
+ .h_active = 1366,
+ .v_active = 768,
+ .h_front_porch = 64,
+ .v_front_porch = 125,
+ },
+ {
+ /* 1366x768@48 */
+ .pclk = 74180000,
+ .h_ref_to_sync = 1,
+ .v_ref_to_sync = 1,
+ .h_sync_width = 30,
+ .v_sync_width = 5,
+ .h_back_porch = 52,
+ .v_back_porch = 98,
+ .h_active = 1366,
+ .v_active = 768,
+ .h_front_porch = 64,
+ .v_front_porch = 152,
+ },
+};
+
+static struct tegra_fb_data p1852_fb_data = {
+ .win = 0,
+ .xres = 1366,
+ .yres = 768,
+ .bits_per_pixel = 32,
+};
+
+#else
+
+/* Mode data for primary RGB/LVDS out */
static struct tegra_dc_mode p1852_panel_modes[] = {
{
/* 800x480@60 */
@@ -63,6 +121,8 @@ static struct tegra_fb_data p1852_fb_data = {
.bits_per_pixel = 32,
};
+#endif
+
static struct tegra_dc_out p1852_disp1_out = {
.align = TEGRA_DC_ALIGN_MSB,
.order = TEGRA_DC_ORDER_RED_BLUE,
@@ -126,7 +186,7 @@ int __init p1852_panel_init(void)
res->end = tegra_fb_start + tegra_fb_size - 1;
#ifdef CONFIG_TEGRA_GRHOST
- err = nvhost_device_register(&tegra_grhost_device);
+ err = tegra3_register_host1x_devices();
if (err)
return err;
#endif
diff --git a/arch/arm/mach-tegra/board-p1852-pinmux.c b/arch/arm/mach-tegra/board-p1852-pinmux.c
index a59f6590e332..21f310b0ef16 100644
--- a/arch/arm/mach-tegra/board-p1852-pinmux.c
+++ b/arch/arm/mach-tegra/board-p1852-pinmux.c
@@ -63,14 +63,21 @@
/* !!!FIXME!!!! Update drive strength with characterized value */
static __initdata struct tegra_drive_pingroup_config p1852_drive_pinmux[] = {
- SET_DRIVE(DAP2, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST),
+ /* ATC1 CFG */
+ SET_DRIVE(AT1, ENABLE, ENABLE, DIV_1, 0, 0, SLOWEST, SLOWEST),
+ /* ATC2 CFG */
+ SET_DRIVE(AT2, ENABLE, ENABLE, DIV_1, 0, 0, SLOWEST, SLOWEST),
+ /* ATC3 CFG */
+ SET_DRIVE(AT3, ENABLE, ENABLE, DIV_1, 0, 0, SLOWEST, SLOWEST),
+ /* ATC4 CFG */
+ SET_DRIVE(AT4, DISABLE, DISABLE, DIV_1, 0, 0, SLOWEST, SLOWEST),
/* All I2C pins are driven to maximum drive strength */
/* GEN1 I2C */
SET_DRIVE(DBG, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST),
/* GEN2 I2C */
- SET_DRIVE(AT5, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST),
+ SET_DRIVE(AT5, DISABLE, ENABLE, DIV_1, 12, 30, FASTEST, FASTEST),
/* DDC I2C */
SET_DRIVE(DDC, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST),
@@ -83,6 +90,48 @@ static __initdata struct tegra_drive_pingroup_config p1852_drive_pinmux[] = {
SET_DRIVE(GMF, DISABLE, ENABLE, DIV_1, 0, 0, SLOWEST, SLOWEST),
SET_DRIVE(GMG, DISABLE, ENABLE, DIV_1, 15, 6, SLOWEST, SLOWEST),
SET_DRIVE(GMH, DISABLE, ENABLE, DIV_1, 12, 6, SLOWEST, SLOWEST),
+
+ /* LCD */
+ SET_DRIVE(LCD1, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST),
+ SET_DRIVE(LCD2, DISABLE, ENABLE, DIV_1, 2, 2, FASTEST, FASTEST),
+
+ /* DAP2 */
+ SET_DRIVE(DAP2, ENABLE, ENABLE, DIV_1, 0, 0, SLOWEST, SLOWEST),
+ /* DAP4 */
+ SET_DRIVE(DAP4, ENABLE, ENABLE, DIV_1, 0, 0, SLOWEST, SLOWEST),
+ /* DBG */
+ SET_DRIVE(DBG, ENABLE, ENABLE, DIV_1, 20, 0, SLOWEST, SLOWEST),
+ /* SPI */
+ SET_DRIVE(SPI, ENABLE, ENABLE, DIV_1, 0, 0, SLOWEST, SLOWEST),
+ /* UAA */
+ SET_DRIVE(UAA, DISABLE, DISABLE, DIV_1, 0, 0, SLOWEST, SLOWEST),
+ /* UART2 */
+ SET_DRIVE(UART2, ENABLE, ENABLE, DIV_1, 0, 0, SLOWEST, SLOWEST),
+ /* UART3 */
+ SET_DRIVE(UART3, ENABLE, ENABLE, DIV_1, 0, 0, SLOWEST, SLOWEST),
+ /* GME */
+ SET_DRIVE(GME, DISABLE, ENABLE, DIV_1, 1, 4, SLOWEST, SLOWEST),
+ /* GMF */
+ SET_DRIVE(GMF, DISABLE, ENABLE, DIV_1, 0, 0, SLOWEST, SLOWEST),
+ /* GMG */
+ SET_DRIVE(GMG, DISABLE, ENABLE, DIV_1, 3, 0, SLOWEST, SLOWEST),
+ /* GMH */
+ SET_DRIVE(GMH, DISABLE, ENABLE, DIV_1, 0, 12, SLOWEST, SLOWEST),
+
+ /* I2S/TDM */
+#ifdef CONFIG_TEGRA_MODS
+ SET_DRIVE(DAP1, ENABLE, ENABLE, DIV_1, 20, 20, SLOWEST, SLOWEST),
+ SET_DRIVE(DAP3, ENABLE, ENABLE, DIV_1, 20, 20, SLOWEST, SLOWEST),
+#else
+ SET_DRIVE(DAP1, ENABLE, ENABLE, DIV_1, 3, 3, SLOWEST, SLOWEST),
+ SET_DRIVE(DAP3, ENABLE, ENABLE, DIV_1, 3, 3, SLOWEST, SLOWEST),
+#endif
+
+ /* SPI */
+ SET_DRIVE(UAD, DISABLE, ENABLE, DIV_1, 4, 1, SLOWEST, SLOWEST),
+ SET_DRIVE(UAB, DISABLE, ENABLE, DIV_1, 4, 1, SLOWEST, SLOWEST),
+ SET_DRIVE(SDIO3, DISABLE, ENABLE, DIV_8, 4, 1, FASTEST, FASTEST),
+
};
#define DEFAULT_PINMUX(_pingroup, _mux, _pupd, _tri, _io) \
@@ -121,6 +170,21 @@ static __initdata struct tegra_drive_pingroup_config p1852_drive_pinmux[] = {
.ioreset = TEGRA_PIN_IO_RESET_##_ioreset \
}
+/* For LV(Low voltage) pad groups which has IO_RESET bit */
+#define LVPAD_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 p1852_pinmux_common[] = {
/* SDMMC1 pinmux */
DEFAULT_PINMUX(SDMMC1_CLK, SDMMC1, NORMAL, NORMAL, INPUT),
@@ -142,14 +206,6 @@ static __initdata struct tegra_pingroup_config p1852_pinmux_common[] = {
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),
-
/* SDMMC4 pinmux */
DEFAULT_PINMUX(CAM_MCLK, POPSDMMC4, NORMAL, NORMAL, INPUT),
DEFAULT_PINMUX(GPIO_PCC1, POPSDMMC4, NORMAL, NORMAL, INPUT),
@@ -161,6 +217,7 @@ static __initdata struct tegra_pingroup_config p1852_pinmux_common[] = {
DEFAULT_PINMUX(GPIO_PBB5, POPSDMMC4, PULL_UP, NORMAL, INPUT),
DEFAULT_PINMUX(GPIO_PBB6, POPSDMMC4, PULL_UP, NORMAL, INPUT),
DEFAULT_PINMUX(GPIO_PBB7, POPSDMMC4, PULL_UP, NORMAL, INPUT),
+ DEFAULT_PINMUX(GPIO_PCC2, POPSDMMC4, PULL_UP, NORMAL, INPUT),
/* UART1 pinmux */
DEFAULT_PINMUX(ULPI_DATA0, UARTA, NORMAL, NORMAL, OUTPUT),
@@ -179,10 +236,10 @@ static __initdata struct tegra_pingroup_config p1852_pinmux_common[] = {
DEFAULT_PINMUX(GMI_A19, UARTD, NORMAL, NORMAL, OUTPUT),
/* UART5 pinmux */
- DEFAULT_PINMUX(SDMMC4_DAT0, UARTE, NORMAL, NORMAL, INPUT),
- DEFAULT_PINMUX(SDMMC4_DAT1, UARTE, NORMAL, NORMAL, OUTPUT),
- DEFAULT_PINMUX(SDMMC4_DAT2, UARTE, NORMAL, NORMAL, INPUT),
- DEFAULT_PINMUX(SDMMC4_DAT3, UARTE, NORMAL, NORMAL, OUTPUT),
+ LVPAD_PINMUX(SDMMC4_DAT0, UARTE, NORMAL, NORMAL, OUTPUT, DISABLE, DISABLE),
+ LVPAD_PINMUX(SDMMC4_DAT1, UARTE, NORMAL, NORMAL, INPUT, DISABLE, DISABLE),
+ LVPAD_PINMUX(SDMMC4_DAT2, UARTE, NORMAL, NORMAL, INPUT, DISABLE, DISABLE),
+ LVPAD_PINMUX(SDMMC4_DAT3, UARTE, NORMAL, NORMAL, OUTPUT, DISABLE, DISABLE),
/* I2C1 pinmux */
I2C_PINMUX(GEN1_I2C_SCL, I2C1, NORMAL, NORMAL, INPUT, DISABLE, ENABLE),
@@ -212,6 +269,12 @@ static __initdata struct tegra_pingroup_config p1852_pinmux_common[] = {
DEFAULT_PINMUX(ULPI_DATA6, SPI2, NORMAL, NORMAL, INPUT),
DEFAULT_PINMUX(ULPI_DATA7, SPI2, NORMAL, NORMAL, INPUT),
+ /* SPI3 pinmux */
+ DEFAULT_PINMUX(SDMMC3_CLK, SPI3, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC3_DAT0, SPI3, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC3_DAT1, SPI3, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC3_DAT2, SPI3, NORMAL, NORMAL, INPUT),
+
/* SPDIF pinmux */
DEFAULT_PINMUX(SPDIF_IN, SPDIF, NORMAL, NORMAL, INPUT),
@@ -228,10 +291,10 @@ static __initdata struct tegra_pingroup_config p1852_pinmux_common[] = {
DEFAULT_PINMUX(DAP3_SCLK, I2S2, NORMAL, NORMAL, INPUT),
/* DAP3 */
- 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),
+ 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),
/* NOR pinmux */
DEFAULT_PINMUX(GMI_AD0, GMI, NORMAL, NORMAL, INPUT),
@@ -250,8 +313,8 @@ static __initdata struct tegra_pingroup_config p1852_pinmux_common[] = {
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_ADV_N, NAND, NORMAL, NORMAL, OUTPUT),
+ DEFAULT_PINMUX(GMI_CLK, NAND, 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, NORMAL, NORMAL, OUTPUT),
@@ -327,29 +390,50 @@ static __initdata struct tegra_pingroup_config p1852_pinmux_common[] = {
DEFAULT_PINMUX(PEX_L2_RST_N, PCIE, NORMAL, NORMAL, OUTPUT),
DEFAULT_PINMUX(PEX_L2_CLKREQ_N, PCIE, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(CLK1_OUT, EXTPERIPH1, PULL_DOWN, NORMAL, INPUT),
+
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, OUTPUT, 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, OUTPUT, 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, PULL_UP, TRISTATE, INPUT, DISABLE, DISABLE),
/* pin config for gpios */
- DEFAULT_PINMUX(VI_D0, SAFE, NORMAL, NORMAL, INPUT),
- DEFAULT_PINMUX(CLK1_OUT, RSVD1, NORMAL, NORMAL, INPUT),
- DEFAULT_PINMUX(CLK1_REQ, RSVD2, NORMAL, NORMAL, INPUT),
- DEFAULT_PINMUX(LCD_SCK, SPI5, NORMAL, NORMAL, INPUT),
- DEFAULT_PINMUX(LCD_DC1, RSVD1, NORMAL, NORMAL, INPUT),
- DEFAULT_PINMUX(SDMMC3_DAT4, SDMMC3, NORMAL, NORMAL, INPUT),
- DEFAULT_PINMUX(SDMMC3_DAT5, SDMMC3, NORMAL, NORMAL, INPUT),
- DEFAULT_PINMUX(SPI2_CS1_N, SPI2, NORMAL, NORMAL, INPUT),
- DEFAULT_PINMUX(SPDIF_OUT, SAFE, NORMAL, NORMAL, INPUT),
- DEFAULT_PINMUX(SPI1_SCK, GMI, NORMAL, NORMAL, INPUT),
- DEFAULT_PINMUX(SPI1_CS0_N, GMI, NORMAL, NORMAL, INPUT),
- DEFAULT_PINMUX(SPI1_MISO, SAFE, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(VI_D0, SAFE, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(CLK1_REQ, RSVD2, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_SCK, SPI5, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_DC1, RSVD1, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC3_DAT5, SDMMC3, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SPDIF_OUT, SAFE, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SPI1_SCK, GMI, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SPI1_CS0_N, GMI, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SPI1_MISO, RSVD3, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SPI2_CS2_N, SPI2, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GPIO_PV0, RSVD, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(GPIO_PV1, RSVD, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(CRT_HSYNC, RSVD1, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(CRT_VSYNC, RSVD1, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_CS0_N, RSVD, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_M1, RSVD1, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_PWR0, SPI5, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_PWR1, RSVD1, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_PWR2, SPI5, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_SDIN, RSVD, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(LCD_SDOUT, SPI5, NORMAL, NORMAL, INPUT),
+ 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(SDMMC3_CMD, SDMMC3, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC3_DAT3, RSVD0, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(VI_D1, RSVD1, NORMAL, NORMAL, INPUT),
+ DEFAULT_PINMUX(SDMMC3_DAT4, SDMMC3, NORMAL, TRISTATE, INPUT),
+ DEFAULT_PINMUX(SPI2_CS1_N, SPI2, NORMAL, TRISTATE, INPUT),
+ DEFAULT_PINMUX(HDMI_INT, RSVD0, NORMAL, TRISTATE, INPUT),
};
int __init p1852_pinmux_init(void)
@@ -361,31 +445,58 @@ int __init p1852_pinmux_init(void)
return 0;
}
-static struct gpio p1852_sku8_gpios[] = {
- {TEGRA_GPIO_PW4, GPIOF_OUT_INIT_HIGH, "w4"},
- {TEGRA_GPIO_PEE2, GPIOF_OUT_INIT_HIGH, "ee2"},
- {TEGRA_GPIO_PZ4, GPIOF_OUT_INIT_HIGH, "z4"},
- {TEGRA_GPIO_PD2, GPIOF_OUT_INIT_HIGH, "d2"},
- {TEGRA_GPIO_PD1, GPIOF_OUT_INIT_HIGH, "d1"},
- {TEGRA_GPIO_PD0, GPIOF_OUT_INIT_HIGH, "d0"},
- {TEGRA_GPIO_PW3, GPIOF_IN, "therm_alert"},
- {TEGRA_GPIO_PK5, GPIOF_OUT_INIT_HIGH, "user1"},
- {TEGRA_GPIO_PX5, GPIOF_OUT_INIT_HIGH, "user2"},
- {TEGRA_GPIO_PX6, GPIOF_OUT_INIT_HIGH, "user3"},
- {TEGRA_GPIO_PX7, GPIOF_OUT_INIT_HIGH, "user4"},
+#define GPIO_INIT_PIN_MODE(_gpio, _is_input, _value) \
+ { \
+ .gpio_nr = _gpio, \
+ .is_input = _is_input, \
+ .value = _value, \
+ }
+
+static struct gpio_init_pin_info p1852_sku8_gpios[] = {
+ GPIO_INIT_PIN_MODE(TEGRA_GPIO_PT4, false, 1),
+ GPIO_INIT_PIN_MODE(TEGRA_GPIO_PEE2, false, 1),
+ GPIO_INIT_PIN_MODE(TEGRA_GPIO_PZ4, false, 1),
+ GPIO_INIT_PIN_MODE(TEGRA_GPIO_PD2, false, 1),
+ GPIO_INIT_PIN_MODE(TEGRA_GPIO_PD0, true, 0),
+ GPIO_INIT_PIN_MODE(TEGRA_GPIO_PW3, true, 0),
+ GPIO_INIT_PIN_MODE(TEGRA_GPIO_PK5, false, 1),
+ GPIO_INIT_PIN_MODE(TEGRA_GPIO_PX5, false, 1),
+ GPIO_INIT_PIN_MODE(TEGRA_GPIO_PX6, false, 1),
+ GPIO_INIT_PIN_MODE(TEGRA_GPIO_PX7, false, 1),
+ GPIO_INIT_PIN_MODE(TEGRA_GPIO_PV0, false, 1),
+ GPIO_INIT_PIN_MODE(TEGRA_GPIO_PV1, false, 1),
+ GPIO_INIT_PIN_MODE(TEGRA_GPIO_PV6, false, 1),
+ GPIO_INIT_PIN_MODE(TEGRA_GPIO_PV7, true, 0),
+ GPIO_INIT_PIN_MODE(TEGRA_GPIO_PN4, false, 1),
+ GPIO_INIT_PIN_MODE(TEGRA_GPIO_PN6, false, 1),
+ GPIO_INIT_PIN_MODE(TEGRA_GPIO_PW1, false, 1),
+ GPIO_INIT_PIN_MODE(TEGRA_GPIO_PB2, false, 1),
+ GPIO_INIT_PIN_MODE(TEGRA_GPIO_PC1, false, 1),
+ GPIO_INIT_PIN_MODE(TEGRA_GPIO_PC6, true, 0),
+ GPIO_INIT_PIN_MODE(TEGRA_GPIO_PZ2, false, 1),
+ GPIO_INIT_PIN_MODE(TEGRA_GPIO_PN5, false, 1),
+ GPIO_INIT_PIN_MODE(TEGRA_GPIO_PDD3, false, 1),
+ GPIO_INIT_PIN_MODE(TEGRA_GPIO_PV2, true, 0),
+ GPIO_INIT_PIN_MODE(TEGRA_GPIO_PV3, true, 0),
+ GPIO_INIT_PIN_MODE(TEGRA_GPIO_PD4, true, 0),
+ GPIO_INIT_PIN_MODE(TEGRA_GPIO_PCC4, false, 0),
+ GPIO_INIT_PIN_MODE(TEGRA_GPIO_PA7, false, 1),
+ GPIO_INIT_PIN_MODE(TEGRA_GPIO_PB4, false, 1),
+ GPIO_INIT_PIN_MODE(TEGRA_GPIO_PD5, false, 1),
+ GPIO_INIT_PIN_MODE(TEGRA_GPIO_PN7, true, 0),
};
int __init p1852_gpio_init(void)
{
int i, pin_count = 0;
- struct gpio *gpios_info = NULL;
+ struct gpio_init_pin_info *gpios_info = NULL;
gpios_info = p1852_sku8_gpios;
pin_count = ARRAY_SIZE(p1852_sku8_gpios);
- 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);
+ for (i = 0; i < pin_count; ++i) {
+ tegra_gpio_init_configure(gpios_info->gpio_nr,
+ gpios_info->is_input, gpios_info->value);
+ gpios_info++;
}
return 0;
}
diff --git a/arch/arm/mach-tegra/board-p1852-sdhci.c b/arch/arm/mach-tegra/board-p1852-sdhci.c
index c1aa066ae1b0..17fb451e27c5 100644
--- a/arch/arm/mach-tegra/board-p1852-sdhci.c
+++ b/arch/arm/mach-tegra/board-p1852-sdhci.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2010 Google, Inc.
*
- * 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
@@ -35,9 +35,11 @@
#include "board-p1852.h"
#include "devices.h"
+#define P1852_SD1_CD TEGRA_GPIO_PV2
+
static struct tegra_sdhci_platform_data tegra_sdhci_platform_data1 = {
- .cd_gpio = TEGRA_GPIO_PV2,
- .wp_gpio = TEGRA_GPIO_PD3,
+ .cd_gpio = P1852_SD1_CD,
+ .wp_gpio = -1,
.power_gpio = -1,
.is_8bit = false,
};
@@ -49,13 +51,6 @@ static struct tegra_sdhci_platform_data tegra_sdhci_platform_data2 = {
.is_8bit = true,
};
-static struct tegra_sdhci_platform_data tegra_sdhci_platform_data3 = {
- .cd_gpio = TEGRA_GPIO_PV3,
- .wp_gpio = TEGRA_GPIO_PD4,
- .power_gpio = -1,
- .is_8bit = false,
-};
-
static struct tegra_sdhci_platform_data tegra_sdhci_platform_data4 = {
.cd_gpio = -1,
.wp_gpio = -1,
@@ -67,12 +62,10 @@ int __init p1852_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-p1852.c b/arch/arm/mach-tegra/board-p1852.c
index 020671a7513b..ce7768e19594 100644
--- a/arch/arm/mach-tegra/board-p1852.c
+++ b/arch/arm/mach-tegra/board-p1852.c
@@ -35,6 +35,9 @@
#include <linux/platform_data/tegra_nor.h>
#include <linux/spi/spi.h>
#include <linux/mtd/partitions.h>
+#if defined(CONFIG_TOUCHSCREEN_ATMEL_MXT)
+#include <linux/i2c/atmel_mxt_ts.h>
+#endif
#include <mach/clk.h>
#include <mach/iomap.h>
#include <mach/irqs.h>
@@ -48,6 +51,7 @@
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <mach/usb_phy.h>
+#include <mach/tegra_fiq_debugger.h>
#include <sound/wm8903.h>
#include <mach/tsensor.h>
#include "board.h"
@@ -57,42 +61,6 @@
#include "gpio-names.h"
#include "fuse.h"
-static struct tegra_utmip_config utmi_phy_config[] = {
- [0] = {
- .hssync_start_delay = 0,
- .idle_wait_delay = 17,
- .elastic_limit = 16,
- .term_range_adj = 6,
- .xcvr_setup = 15,
- .xcvr_setup_offset = 0,
- .xcvr_use_fuses = 1,
- .xcvr_lsfslew = 2,
- .xcvr_lsrslew = 2,
- },
- [1] = {
- .hssync_start_delay = 0,
- .idle_wait_delay = 17,
- .elastic_limit = 16,
- .term_range_adj = 6,
- .xcvr_setup = 15,
- .xcvr_setup_offset = 0,
- .xcvr_use_fuses = 1,
- .xcvr_lsfslew = 2,
- .xcvr_lsrslew = 2,
- },
- [2] = {
- .hssync_start_delay = 0,
- .idle_wait_delay = 17,
- .elastic_limit = 16,
- .term_range_adj = 6,
- .xcvr_setup = 8,
- .xcvr_setup_offset = 0,
- .xcvr_use_fuses = 1,
- .xcvr_lsfslew = 2,
- .xcvr_lsrslew = 2,
- },
-};
-
static __initdata struct tegra_clk_init_table p1852_clk_init_table[] = {
/* name parent rate enabled */
{ "pll_m", NULL, 0, true},
@@ -101,9 +69,10 @@ static __initdata struct tegra_clk_init_table p1852_clk_init_table[] = {
{ "pwm", "clk_32k", 32768, false},
{ "blink", "clk_32k", 32768, true},
{ "pll_a", NULL, 552960000, false},
- { "pll_a_out0", NULL, 12288000, false},
- { "d_audio", "pll_a_out0", 12288000, false},
- { "nor", "pll_p", 86500000, true},
+ /* audio cif clock should be faster than i2s */
+ { "pll_a_out0", NULL, 24576000, false},
+ { "d_audio", "pll_a_out0", 24576000, false},
+ { "nor", "pll_p", 102000000, true},
{ "uarta", "pll_p", 480000000, true},
{ "uartd", "pll_p", 480000000, true},
{ "uarte", "pll_p", 480000000, true},
@@ -115,16 +84,11 @@ static __initdata struct tegra_clk_init_table p1852_clk_init_table[] = {
{ "sbc5", "pll_m", 100000000, true},
{ "sbc6", "pll_m", 100000000, true},
{ "cpu_g", "cclk_g", 900000000, true},
- { "i2s0", "pll_a_out0", 12288000, false},
- { "i2s1", "pll_a_out0", 12288000, false},
- { "i2s2", "pll_a_out0", 12288000, false},
- { "i2s3", "pll_a_out0", 12288000, false},
- { "i2s4", "pll_a_out0", 12288000, 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},
+ { "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},
{ "apbif", "clk_m", 12000000, false},
{ "dam0", "clk_m", 12000000, true},
{ "dam1", "clk_m", 12000000, true},
@@ -141,6 +105,7 @@ static __initdata struct tegra_clk_init_table p1852_clk_init_table[] = {
{ "i2c4", "pll_p", 3200000, true},
{ "i2c5", "pll_p", 3200000, true},
{ "sdmmc2", "pll_p", 104000000, false},
+ {"wake.sclk", NULL, 334000000, true },
{ NULL, NULL, 0, 0},
};
@@ -234,26 +199,57 @@ static void __init p1852_uart_init(void)
ARRAY_SIZE(p1852_uart_devices));
}
-static struct tegra_p1852_platform_data p1852_audio_pdata = {
+#if defined(CONFIG_TEGRA_P1852_TDM)
+static struct tegra_p1852_platform_data p1852_audio_tdm_pdata = {
+ .codec_info[0] = {
+ .codec_dai_name = "dit-hifi",
+ .cpu_dai_name = "tegra30-i2s.0",
+ .codec_name = "spdif-dit.0",
+ .name = "tegra-i2s-1",
+ .pcm_driver = "tegra-tdm-pcm-audio",
+ .i2s_format = format_tdm,
+ .master = 1,
+ .num_slots = 4,
+ .slot_width = 32,
+ .tx_mask = 0x0f,
+ .rx_mask = 0x0f,
+ },
+ .codec_info[1] = {
+ .codec_dai_name = "dit-hifi",
+ .cpu_dai_name = "tegra30-i2s.4",
+ .codec_name = "spdif-dit.1",
+ .name = "tegra-i2s-2",
+ .pcm_driver = "tegra-tdm-pcm-audio",
+ .i2s_format = format_tdm,
+ .master = 1,
+ .num_slots = 8,
+ .slot_width = 32,
+ .tx_mask = 0xff,
+ .rx_mask = 0xff,
+ },
+};
+#else
+static struct tegra_p1852_platform_data p1852_audio_i2s_pdata = {
.codec_info[0] = {
.codec_dai_name = "dit-hifi",
.cpu_dai_name = "tegra30-i2s.0",
.codec_name = "spdif-dit.0",
.name = "tegra-i2s-1",
+ .pcm_driver = "tegra-pcm-audio",
.i2s_format = format_i2s,
.master = 1,
},
.codec_info[1] = {
.codec_dai_name = "dit-hifi",
- .cpu_dai_name = "tegra30-i2s.1",
+ .cpu_dai_name = "tegra30-i2s.4",
.codec_name = "spdif-dit.1",
.name = "tegra-i2s-2",
+ .pcm_driver = "tegra-pcm-audio",
.i2s_format = format_i2s,
.master = 0,
},
-
};
-
+#endif
static struct platform_device generic_codec_1 = {
.name = "spdif-dit",
.id = 0,
@@ -267,17 +263,22 @@ static struct platform_device tegra_snd_p1852 = {
.name = "tegra-snd-p1852",
.id = 0,
.dev = {
- .platform_data = &p1852_audio_pdata,
+#if defined(CONFIG_TEGRA_P1852_TDM)
+ .platform_data = &p1852_audio_tdm_pdata,
+#else
+ .platform_data = &p1852_audio_i2s_pdata,
+#endif
},
};
static void p1852_i2s_audio_init(void)
{
platform_device_register(&tegra_pcm_device);
+ platform_device_register(&tegra_tdm_pcm_device);
platform_device_register(&generic_codec_1);
platform_device_register(&generic_codec_2);
platform_device_register(&tegra_i2s_device0);
- platform_device_register(&tegra_i2s_device1);
+ platform_device_register(&tegra_i2s_device4);
platform_device_register(&tegra_ahub_device);
platform_device_register(&tegra_snd_p1852);
}
@@ -305,6 +306,15 @@ static struct spi_board_info tegra_spi_devices[] __initdata = {
},
{
.modalias = "spidev",
+ .bus_num = 2,
+ .chip_select = 0,
+ .mode = SPI_MODE_0,
+ .max_speed_hz = 18000000,
+ .platform_data = NULL,
+ .irq = 0,
+ },
+ {
+ .modalias = "spidev",
.bus_num = 3,
.chip_select = 1,
.mode = SPI_MODE_0,
@@ -329,69 +339,222 @@ static void p1852_spi_init(void)
tegra_spi_device2.name = "spi_slave_tegra";
platform_device_register(&tegra_spi_device1);
platform_device_register(&tegra_spi_device2);
+ platform_device_register(&tegra_spi_device3);
p852_register_spidev();
}
+static struct platform_device tegra_camera = {
+ .name = "tegra_camera",
+ .id = -1,
+};
+
static struct platform_device *p1852_devices[] __initdata = {
-#if defined(CONFIG_TEGRA_IOVMM_SMMU)
+#if defined(CONFIG_TEGRA_IOVMM_SMMU) || defined(CONFIG_TEGRA_IOMMU_SMMU)
&tegra_smmu_device,
#endif
#if defined(CONFIG_TEGRA_AVP)
&tegra_avp_device,
#endif
- &tegra_wdt_device
+ &tegra_camera,
+ &tegra_wdt0_device,
+ &tegra_wdt1_device,
+ &tegra_wdt2_device
};
-static struct usb_phy_plat_data tegra_usb_phy_pdata[] = {
- [0] = {
- .instance = 0,
- .vbus_gpio = -1,
- .vbus_reg_supply = NULL,
- },
- [1] = {
- .instance = 1,
- .vbus_gpio = -1,
+
+#ifdef CONFIG_TOUCHSCREEN_ATMEL_MXT
+
+#define MXT_CONFIG_CRC 0xD62DE8
+static const u8 config[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0x32, 0x0A, 0x00, 0x14, 0x14, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0x00, 0x00,
+ 0x1B, 0x2A, 0x00, 0x20, 0x3C, 0x04, 0x05, 0x00,
+ 0x02, 0x01, 0x00, 0x0A, 0x0A, 0x0A, 0x0A, 0xFF,
+ 0x02, 0x55, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x64, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23,
+ 0x00, 0x00, 0x00, 0x05, 0x0A, 0x15, 0x1E, 0x00,
+ 0x00, 0x04, 0xFF, 0x03, 0x3F, 0x64, 0x64, 0x01,
+ 0x0A, 0x14, 0x28, 0x4B, 0x00, 0x02, 0x00, 0x64,
+ 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x10, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+#define MXT_CONFIG_CRC_SKU2000 0xA24D9A
+static const u8 config_sku2000[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0x32, 0x0A, 0x00, 0x14, 0x14, 0x19,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0x00, 0x00,
+ 0x1B, 0x2A, 0x00, 0x20, 0x3A, 0x04, 0x05, 0x00, //23=thr 2 di
+ 0x04, 0x04, 0x41, 0x0A, 0x0A, 0x0A, 0x0A, 0xFF,
+ 0x02, 0x55, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, //0A=limit
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23,
+ 0x00, 0x00, 0x00, 0x05, 0x0A, 0x15, 0x1E, 0x00,
+ 0x00, 0x04, 0x00, 0x03, 0x3F, 0x64, 0x64, 0x01,
+ 0x0A, 0x14, 0x28, 0x4B, 0x00, 0x02, 0x00, 0x64,
+ 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x10, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static struct mxt_platform_data atmel_mxt_info = {
+ .x_line = 27,
+ .y_line = 42,
+ .x_size = 768,
+ .y_size = 1366,
+ .blen = 0x20,
+ .threshold = 0x3C,
+ .voltage = 3300000, /* 3.3V */
+ .orient = 5,
+ .config = config,
+ .config_length = 157,
+ .config_crc = MXT_CONFIG_CRC,
+ .irqflags = IRQF_TRIGGER_FALLING,
+/* .read_chg = &read_chg, */
+ .read_chg = NULL,
+};
+
+static struct i2c_board_info __initdata atmel_i2c_info[] = {
+ {
+ I2C_BOARD_INFO("atmel_mxt_ts", 0x5A),
+ .irq = TEGRA_GPIO_TO_IRQ(TOUCH_GPIO_IRQ_ATMEL_T9),
+ .platform_data = &atmel_mxt_info,
+ }
+};
+
+static __initdata struct tegra_clk_init_table spi_clk_init_table[] = {
+ /* name parent rate enabled */
+ { "sbc1", "pll_p", 52000000, true},
+ { NULL, NULL, 0, 0},
+};
+
+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);
+
+ gpio_request(TOUCH_GPIO_RST_ATMEL_T9, "atmel-reset");
+ gpio_direction_output(TOUCH_GPIO_RST_ATMEL_T9, 0);
+ msleep(1);
+ gpio_set_value(TOUCH_GPIO_RST_ATMEL_T9, 1);
+ msleep(100);
+
+ atmel_mxt_info.config = config_sku2000;
+ atmel_mxt_info.config_crc = MXT_CONFIG_CRC_SKU2000;
+
+ i2c_register_board_info(TOUCH_BUS_ATMEL_T9, atmel_i2c_info, 1);
+
+ return 0;
+}
+
+#endif // CONFIG_TOUCHSCREEN_ATMEL_MXT
+
+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,
},
- [2] = {
- .instance = 2,
- .vbus_gpio = -1,
- .vbus_reg_supply = NULL,
+ .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_ehci_platform_data tegra_ehci_pdata[] = {
- [0] = {
- .phy_config = &utmi_phy_config[0],
- .operating_mode = TEGRA_USB_HOST,
- .power_down_on_bus_suspend = 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,
},
- [1] = {
- .phy_config = &utmi_phy_config[1],
- .operating_mode = TEGRA_USB_HOST,
- .power_down_on_bus_suspend = 1,
+ .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,
},
- [2] = {
- .phy_config = &utmi_phy_config[2],
- .operating_mode = TEGRA_USB_HOST,
- .power_down_on_bus_suspend = 1,
+ .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 p1852_usb_init(void)
{
- /* Need to parse sku info to decide host/device mode */
- tegra_usb_phy_init(tegra_usb_phy_pdata,
- ARRAY_SIZE(tegra_usb_phy_pdata));
-
- tegra_ehci1_device.dev.platform_data = &tegra_ehci_pdata[0];
+ tegra_ehci1_device.dev.platform_data = &tegra_ehci1_utmi_pdata;
platform_device_register(&tegra_ehci1_device);
- tegra_ehci2_device.dev.platform_data = &tegra_ehci_pdata[1];
+ tegra_ehci2_device.dev.platform_data = &tegra_ehci2_utmi_pdata;
platform_device_register(&tegra_ehci2_device);
- tegra_ehci3_device.dev.platform_data = &tegra_ehci_pdata[2];
+ tegra_ehci3_device.dev.platform_data = &tegra_ehci3_utmi_pdata;
platform_device_register(&tegra_ehci3_device);
-
}
static struct tegra_nor_platform_data p1852_nor_data = {
@@ -402,12 +565,12 @@ static struct tegra_nor_platform_data p1852_nor_data = {
.chip_parms = {
/* FIXME: Need to use characterized value */
.timing_default = {
- .timing0 = 0xA0400273,
- .timing1 = 0x00030402,
+ .timing0 = 0x30300263,
+ .timing1 = 0x00030302,
},
.timing_read = {
- .timing0 = 0xA0400273,
- .timing1 = 0x00030402,
+ .timing0 = 0x30300263,
+ .timing1 = 0x00030302,
},
},
};
@@ -432,9 +595,13 @@ static void __init tegra_p1852_init(void)
p1852_sdhci_init();
p1852_spi_init();
platform_add_devices(p1852_devices, ARRAY_SIZE(p1852_devices));
+#ifdef CONFIG_TOUCHSCREEN_ATMEL_MXT
+ p1852_touch_init();
+#endif
p1852_panel_init();
p1852_nor_init();
p1852_pcie_init();
+ tegra_serial_debug_init(TEGRA_UARTD_BASE, INT_WDT_CPU, NULL, -1, -1);
}
static void __init tegra_p1852_reserve(void)
diff --git a/arch/arm/mach-tegra/board-p1852.h b/arch/arm/mach-tegra/board-p1852.h
index f146f30ed2c5..1ac0968f9518 100644
--- a/arch/arm/mach-tegra/board-p1852.h
+++ b/arch/arm/mach-tegra/board-p1852.h
@@ -96,4 +96,10 @@ int p1852_panel_init(void);
int p1852_gpio_init(void);
int p1852_pins_state_init(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-trimslice.c b/arch/arm/mach-tegra/board-trimslice.c
index 823060ec478f..626cd1b34114 100644
--- a/arch/arm/mach-tegra/board-trimslice.c
+++ b/arch/arm/mach-tegra/board-trimslice.c
@@ -6,6 +6,7 @@
*
* Based on board-harmony.c
* Copyright (C) 2010 Google, Inc.
+ * Copyright (C) 2011-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
@@ -95,7 +96,7 @@ static struct platform_device *trimslice_devices[] __initdata = {
&tegra_das_device,
&tegra_pcm_device,
&trimslice_audio_device,
- &trimslice_pci_platform_data,
+ &tegra_pci_device,
};
static struct i2c_board_info trimslice_i2c3_board_info[] = {
diff --git a/arch/arm/mach-tegra/board-ventana-panel.c b/arch/arm/mach-tegra/board-ventana-panel.c
index d7f607a7ad1b..56a222432fe0 100644
--- a/arch/arm/mach-tegra/board-ventana-panel.c
+++ b/arch/arm/mach-tegra/board-ventana-panel.c
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-tegra/board-ventana-panel.c
*
- * Copyright (c) 2010-2012, NVIDIA Corporation.
+ * Copyright (c) 2010-2012 NVIDIA Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -27,7 +27,7 @@
#include <linux/earlysuspend.h>
#include <linux/pwm_backlight.h>
#include <linux/nvhost.h>
-#include <mach/nvmap.h>
+#include <linux/nvmap.h>
#include <mach/irqs.h>
#include <mach/iomap.h>
#include <mach/dc.h>
@@ -36,6 +36,7 @@
#include "devices.h"
#include "gpio-names.h"
#include "board.h"
+#include "tegra2_host1x_devices.h"
#define ventana_bl_enb TEGRA_GPIO_PD4
#define ventana_lvds_shutdown TEGRA_GPIO_PB2
@@ -63,8 +64,6 @@ static int ventana_backlight_init(struct device *dev) {
ret = gpio_direction_output(ventana_bl_enb, 1);
if (ret < 0)
gpio_free(ventana_bl_enb);
- else
- tegra_gpio_enable(ventana_bl_enb);
return ret;
};
@@ -72,7 +71,6 @@ static int ventana_backlight_init(struct device *dev) {
static void ventana_backlight_exit(struct device *dev) {
gpio_set_value(ventana_bl_enb, 0);
gpio_free(ventana_bl_enb);
- tegra_gpio_disable(ventana_bl_enb);
}
static int ventana_backlight_notify(struct device *unused, int brightness)
@@ -284,7 +282,7 @@ static struct tegra_dc_platform_data ventana_disp1_pdata = {
};
static struct tegra_dc_platform_data ventana_disp2_pdata = {
- .flags = 0,
+ .flags = TEGRA_DC_FLAG_ENABLED,
.default_out = &ventana_disp2_out,
.fb = &ventana_hdmi_fb_data,
};
@@ -349,6 +347,8 @@ static struct platform_device *ventana_gfx_devices[] __initdata = {
&ventana_nvmap_device,
#endif
&tegra_pwfm2_device,
+};
+static struct platform_device *ventana_backlight_devices[] __initdata = {
&ventana_backlight_device,
};
@@ -366,16 +366,8 @@ static void ventana_panel_early_suspend(struct early_suspend *h)
if (num_registered_fb > 1)
fb_blank(registered_fb[1], FB_BLANK_NORMAL);
#ifdef CONFIG_TEGRA_CONVSERVATIVE_GOV_ON_EARLYSUPSEND
- cpufreq_save_default_governor();
- cpufreq_set_conservative_governor();
- cpufreq_set_conservative_governor_param("up_threshold",
- SET_CONSERVATIVE_GOVERNOR_UP_THRESHOLD);
-
- cpufreq_set_conservative_governor_param("down_threshold",
- SET_CONSERVATIVE_GOVERNOR_DOWN_THRESHOLD);
-
- cpufreq_set_conservative_governor_param("freq_step",
- SET_CONSERVATIVE_GOVERNOR_FREQ_STEP);
+ cpufreq_store_default_gov();
+ cpufreq_change_gov(cpufreq_conservative_gov);
#endif
}
@@ -383,7 +375,7 @@ static void ventana_panel_late_resume(struct early_suspend *h)
{
unsigned i;
#ifdef CONFIG_TEGRA_CONVSERVATIVE_GOV_ON_EARLYSUPSEND
- cpufreq_restore_default_governor();
+ cpufreq_restore_default_gov();
#endif
for (i = 0; i < num_registered_fb; i++)
fb_blank(registered_fb[i], FB_BLANK_UNBLANK);
@@ -397,13 +389,10 @@ int __init ventana_panel_init(void)
gpio_request(ventana_lvds_shutdown, "lvds_shdn");
gpio_direction_output(ventana_lvds_shutdown, 1);
- tegra_gpio_enable(ventana_lvds_shutdown);
- tegra_gpio_enable(ventana_hdmi_enb);
gpio_request(ventana_hdmi_enb, "hdmi_5v_en");
gpio_direction_output(ventana_hdmi_enb, 1);
- tegra_gpio_enable(ventana_hdmi_hpd);
gpio_request(ventana_hdmi_hpd, "hdmi_hpd");
gpio_direction_input(ventana_hdmi_hpd);
@@ -420,7 +409,7 @@ int __init ventana_panel_init(void)
#endif
#ifdef CONFIG_TEGRA_GRHOST
- err = nvhost_device_register(&tegra_grhost_device);
+ err = tegra2_register_host1x_devices();
if (err)
return err;
#endif
@@ -457,6 +446,9 @@ int __init ventana_panel_init(void)
err = nvhost_device_register(&ventana_disp2_device);
#endif
+ err = platform_add_devices(ventana_backlight_devices,
+ ARRAY_SIZE(ventana_backlight_devices));
+
return err;
}
diff --git a/arch/arm/mach-tegra/board-ventana-pinmux.c b/arch/arm/mach-tegra/board-ventana-pinmux.c
index 9f3447264599..eb371384ed4c 100644
--- a/arch/arm/mach-tegra/board-ventana-pinmux.c
+++ b/arch/arm/mach-tegra/board-ventana-pinmux.c
@@ -47,11 +47,11 @@
}
static __initdata struct tegra_drive_pingroup_config ventana_drive_pinmux[] = {
- DEFAULT_DRIVE(DDC),
DEFAULT_DRIVE(VI1),
DEFAULT_DRIVE(SDIO1),
SET_DRIVE(DBG, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST),
+ SET_DRIVE(DDC, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST),
SET_DRIVE(VI2, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST),
SET_DRIVE(AT1, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST),
SET_DRIVE(AO1, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST),
@@ -126,7 +126,7 @@ static __initdata struct tegra_pingroup_config ventana_pinmux[] = {
{TEGRA_PINGROUP_LPP, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_LPW0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_LPW1, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_LPW2, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_LPW2, TEGRA_MUX_DISPLAYB, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_LSC0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_LSC1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_LSCK, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
diff --git a/arch/arm/mach-tegra/board-ventana-power.c b/arch/arm/mach-tegra/board-ventana-power.c
index 2acfdfed28e4..aa6f4be203ad 100644
--- a/arch/arm/mach-tegra/board-ventana-power.c
+++ b/arch/arm/mach-tegra/board-ventana-power.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2012 NVIDIA, Inc.
+ * Copyright (C) 2010-2012 NVIDIA Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -34,7 +34,6 @@
#include "gpio-names.h"
#include "fuse.h"
#include "pm.h"
-#include "wakeups-t2.h"
#include "board.h"
#include "board-ventana.h"
@@ -47,7 +46,6 @@ int __init ventana_charge_init(void)
{
gpio_request(CHARGING_DISABLE, "chg_disable");
gpio_direction_output(CHARGING_DISABLE, 0);
- tegra_gpio_enable(CHARGING_DISABLE);
return 0;
}
@@ -255,14 +253,6 @@ static struct platform_device *fixed_voltage_regulators[] __initdata = {
int __init ventana_fixed_voltage_regulator_init(void)
{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(fixed_voltage_regulators); ++i) {
- struct fixed_voltage_config *fixed_voltage_regulators_pdata =
- fixed_voltage_regulators[i]->dev.platform_data;
- if (fixed_voltage_regulators_pdata->gpio < TEGRA_NR_GPIOS)
- tegra_gpio_enable(fixed_voltage_regulators_pdata->gpio);
- }
return platform_add_devices(fixed_voltage_regulators,
ARRAY_SIZE(fixed_voltage_regulators));
}
@@ -317,7 +307,6 @@ static struct platform_device ventana_charger_device = {
int __init ventana_charger_init(void)
{
- tegra_gpio_enable(AC_PRESENT_GPIO);
platform_device_register(&ventana_charger_device);
return 0;
}
diff --git a/arch/arm/mach-tegra/board-ventana-sdhci.c b/arch/arm/mach-tegra/board-ventana-sdhci.c
index 188335ac98c5..9d426aadff79 100644
--- a/arch/arm/mach-tegra/board-ventana-sdhci.c
+++ b/arch/arm/mach-tegra/board-ventana-sdhci.c
@@ -1,7 +1,6 @@
/*
- * arch/arm/mach-tegra/board-harmony-sdhci.c
- *
* Copyright (C) 2010 Google, Inc.
+ * Copyright (C) 2010-2012 NVIDIA Corporation.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -132,6 +131,7 @@ static struct tegra_sdhci_platform_data tegra_sdhci_platform_data0 = {
.embedded_sdio = &embedded_sdio_data0,
#endif
.built_in = 0,
+ .ocr_mask = MMC_OCR_1V8_MASK,
},
#ifndef CONFIG_MMC_EMBEDDED_SDIO
.pm_flags = MMC_PM_KEEP_POWER,
@@ -257,10 +257,6 @@ static int __init ventana_wifi_init(void)
gpio_request(VENTANA_WLAN_RST, "wlan_rst");
gpio_request(VENTANA_WLAN_WOW, "bcmsdh_sdmmc");
- tegra_gpio_enable(VENTANA_WLAN_PWR);
- tegra_gpio_enable(VENTANA_WLAN_RST);
- tegra_gpio_enable(VENTANA_WLAN_WOW);
-
gpio_direction_output(VENTANA_WLAN_PWR, 0);
gpio_direction_output(VENTANA_WLAN_RST, 0);
gpio_direction_input(VENTANA_WLAN_WOW);
@@ -274,11 +270,6 @@ static int __init ventana_wifi_init(void)
}
int __init ventana_sdhci_init(void)
{
- tegra_gpio_enable(tegra_sdhci_platform_data2.power_gpio);
- tegra_gpio_enable(tegra_sdhci_platform_data2.cd_gpio);
- tegra_gpio_enable(tegra_sdhci_platform_data2.wp_gpio);
- tegra_gpio_enable(tegra_sdhci_platform_data3.power_gpio);
-
platform_device_register(&tegra_sdhci_device3);
platform_device_register(&tegra_sdhci_device2);
platform_device_register(&tegra_sdhci_device0);
diff --git a/arch/arm/mach-tegra/board-ventana-sensors.c b/arch/arm/mach-tegra/board-ventana-sensors.c
index 574bdb25fc2a..db6ebfd2e137 100644
--- a/arch/arm/mach-tegra/board-ventana-sensors.c
+++ b/arch/arm/mach-tegra/board-ventana-sensors.c
@@ -186,7 +186,6 @@ static struct ssl3250a_platform_data ventana_ssl3250a_pdata = {
static void ventana_isl29018_init(void)
{
- tegra_gpio_enable(ISL29018_IRQ_GPIO);
gpio_request(ISL29018_IRQ_GPIO, "isl29018");
gpio_direction_input(ISL29018_IRQ_GPIO);
}
@@ -194,7 +193,6 @@ static void ventana_isl29018_init(void)
#ifdef CONFIG_SENSORS_AK8975
static void ventana_akm8975_init(void)
{
- tegra_gpio_enable(AKM8975_IRQ_GPIO);
gpio_request(AKM8975_IRQ_GPIO, "akm8975");
gpio_direction_input(AKM8975_IRQ_GPIO);
}
@@ -202,21 +200,118 @@ static void ventana_akm8975_init(void)
static void ventana_nct1008_init(void)
{
- tegra_gpio_enable(NCT1008_THERM2_GPIO);
gpio_request(NCT1008_THERM2_GPIO, "temp_alert");
gpio_direction_input(NCT1008_THERM2_GPIO);
}
+static long ventana_shutdown_temp = 115000;
+static long ventana_throttle_temp = 90000;
+static long ventana_throttle_hysteresis = 3000;
+static struct nct1008_data *nct_data;
+
+static void ventana_thermal_alert(void *vdata)
+{
+ struct nct1008_data *data = vdata;
+ long temp;
+ long lo_limit, hi_limit;
+ bool is_above_throttle;
+
+ nct1008_thermal_get_temp(data, &temp);
+ is_above_throttle = (temp >= ventana_throttle_temp);
+
+ if (is_above_throttle != tegra_is_throttling())
+ tegra_throttling_enable(is_above_throttle);
+
+ if (is_above_throttle) {
+ lo_limit = ventana_throttle_temp - ventana_throttle_hysteresis;
+ hi_limit = ventana_shutdown_temp;
+ } else {
+ lo_limit = 0;
+ hi_limit = ventana_throttle_temp;
+ }
+
+ nct1008_thermal_set_limits(data, lo_limit, hi_limit);
+}
+
+static void nct1008_probe_callback(struct nct1008_data *data)
+{
+ nct_data = data;
+ nct1008_thermal_set_shutdown_temp(data, ventana_shutdown_temp);
+ nct1008_thermal_set_alert(data, ventana_thermal_alert, data);
+ nct1008_thermal_set_limits(data, 0, ventana_throttle_temp);
+}
+
+#ifdef CONFIG_DEBUG_FS
+static int ventana_thermal_get_throttle_temp(void *data, u64 *val)
+{
+ *val = (u64)ventana_throttle_temp;
+ return 0;
+}
+
+static int ventana_thermal_set_throttle_temp(void *data, u64 val)
+{
+ ventana_throttle_temp = val;
+ if (nct_data)
+ ventana_thermal_alert(nct_data);
+
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(throttle_fops,
+ ventana_thermal_get_throttle_temp,
+ ventana_thermal_set_throttle_temp,
+ "%llu\n");
+
+static int ventana_thermal_get_shutdown_temp(void *data, u64 *val)
+{
+ *val = (u64)ventana_shutdown_temp;
+ return 0;
+}
+
+static int ventana_thermal_set_shutdown_temp(void *data, u64 val)
+{
+ ventana_shutdown_temp = val;
+ if (nct_data)
+ nct1008_thermal_set_shutdown_temp(nct_data,
+ ventana_shutdown_temp);
+
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(shutdown_fops,
+ ventana_thermal_get_shutdown_temp,
+ ventana_thermal_set_shutdown_temp,
+ "%llu\n");
+
+
+static int __init ventana_thermal_debug_init(void)
+{
+ struct dentry *thermal_debugfs_root;
+
+ thermal_debugfs_root = debugfs_create_dir("thermal", 0);
+
+ if (!debugfs_create_file("throttle", 0644, thermal_debugfs_root,
+ NULL, &throttle_fops))
+ return -ENOMEM;
+
+ if (!debugfs_create_file("shutdown", 0644, thermal_debugfs_root,
+ NULL, &shutdown_fops))
+ return -ENOMEM;
+
+ return 0;
+}
+
+late_initcall(ventana_thermal_debug_init);
+
+#endif
+
+
static struct nct1008_platform_data ventana_nct1008_pdata = {
.supported_hwrev = true,
.ext_range = false,
.conv_rate = 0x08,
.offset = 0,
- .hysteresis = 0,
- .shutdown_ext_limit = 115,
- .shutdown_local_limit = 120,
- .throttling_ext_limit = 90,
- .alarm_fn = tegra_throttling_enable,
+ .probe_callback = nct1008_probe_callback,
};
static const struct i2c_board_info ventana_i2c0_board_info[] = {
@@ -379,7 +474,6 @@ static void mpuirq_init(void)
#if (MPU_GYRO_TYPE == MPU_TYPE_MPU3050)
#if MPU_ACCEL_IRQ_GPIO
/* ACCEL-IRQ assignment */
- tegra_gpio_enable(MPU_ACCEL_IRQ_GPIO);
ret = gpio_request(MPU_ACCEL_IRQ_GPIO, MPU_ACCEL_NAME);
if (ret < 0) {
pr_err("%s: gpio_request failed %d\n", __func__, ret);
@@ -396,7 +490,6 @@ static void mpuirq_init(void)
#endif
/* MPU-IRQ assignment */
- tegra_gpio_enable(MPU_GYRO_IRQ_GPIO);
ret = gpio_request(MPU_GYRO_IRQ_GPIO, MPU_GYRO_NAME);
if (ret < 0) {
pr_err("%s: gpio_request failed %d\n", __func__, ret);
@@ -465,37 +558,35 @@ int __init ventana_sensors_init(void)
struct tegra_camera_gpios {
const char *name;
int gpio;
- bool tegra_internal_gpio;
int enabled;
};
-#define TEGRA_CAMERA_GPIO(_name, _gpio, _tegra_internal_gpio, _enabled) \
+#define TEGRA_CAMERA_GPIO(_name, _gpio, _enabled) \
{ \
.name = _name, \
.gpio = _gpio, \
- .tegra_internal_gpio = _tegra_internal_gpio, \
.enabled = _enabled, \
}
static struct tegra_camera_gpios ventana_camera_gpio_keys[] = {
- [0] = TEGRA_CAMERA_GPIO("camera_power_en", CAMERA_POWER_GPIO, true, 1),
- [1] = TEGRA_CAMERA_GPIO("camera_csi_sel", CAMERA_CSI_MUX_SEL_GPIO, true, 0),
- [2] = TEGRA_CAMERA_GPIO("torch_gpio_act", CAMERA_FLASH_ACT_GPIO, true, 0),
+ [0] = TEGRA_CAMERA_GPIO("camera_power_en", CAMERA_POWER_GPIO, 1),
+ [1] = TEGRA_CAMERA_GPIO("camera_csi_sel", CAMERA_CSI_MUX_SEL_GPIO, 0),
+ [2] = TEGRA_CAMERA_GPIO("torch_gpio_act", CAMERA_FLASH_ACT_GPIO, 0),
- [3] = TEGRA_CAMERA_GPIO("en_avdd_csi", AVDD_DSI_CSI_ENB_GPIO, false, 1),
- [4] = TEGRA_CAMERA_GPIO("cam_i2c_mux_rst_lo", CAM_I2C_MUX_RST_GPIO, false, 1),
+ [3] = TEGRA_CAMERA_GPIO("en_avdd_csi", AVDD_DSI_CSI_ENB_GPIO, 1),
+ [4] = TEGRA_CAMERA_GPIO("cam_i2c_mux_rst_lo", CAM_I2C_MUX_RST_GPIO, 1),
- [5] = TEGRA_CAMERA_GPIO("cam2_af_pwdn_lo", CAM2_AF_PWR_DN_L_GPIO, false, 0),
- [6] = TEGRA_CAMERA_GPIO("cam2_pwdn", CAM2_PWR_DN_GPIO, false, 0),
- [7] = TEGRA_CAMERA_GPIO("cam2_rst_lo", CAM2_RST_L_GPIO, false, 1),
+ [5] = TEGRA_CAMERA_GPIO("cam2_af_pwdn_lo", CAM2_AF_PWR_DN_L_GPIO, 0),
+ [6] = TEGRA_CAMERA_GPIO("cam2_pwdn", CAM2_PWR_DN_GPIO, 0),
+ [7] = TEGRA_CAMERA_GPIO("cam2_rst_lo", CAM2_RST_L_GPIO, 1),
- [8] = TEGRA_CAMERA_GPIO("cam3_af_pwdn_lo", CAM3_AF_PWR_DN_L_GPIO, false, 0),
- [9] = TEGRA_CAMERA_GPIO("cam3_pwdn", CAM3_PWR_DN_GPIO, false, 0),
- [10] = TEGRA_CAMERA_GPIO("cam3_rst_lo", CAM3_RST_L_GPIO, false, 1),
+ [8] = TEGRA_CAMERA_GPIO("cam3_af_pwdn_lo", CAM3_AF_PWR_DN_L_GPIO, 0),
+ [9] = TEGRA_CAMERA_GPIO("cam3_pwdn", CAM3_PWR_DN_GPIO, 0),
+ [10] = TEGRA_CAMERA_GPIO("cam3_rst_lo", CAM3_RST_L_GPIO, 1),
- [11] = TEGRA_CAMERA_GPIO("cam1_af_pwdn_lo", CAM1_AF_PWR_DN_L_GPIO, false, 0),
- [12] = TEGRA_CAMERA_GPIO("cam1_pwdn", CAM1_PWR_DN_GPIO, false, 0),
- [13] = TEGRA_CAMERA_GPIO("cam1_rst_lo", CAM1_RST_L_GPIO, false, 1),
+ [11] = TEGRA_CAMERA_GPIO("cam1_af_pwdn_lo", CAM1_AF_PWR_DN_L_GPIO, 0),
+ [12] = TEGRA_CAMERA_GPIO("cam1_pwdn", CAM1_PWR_DN_GPIO, 0),
+ [13] = TEGRA_CAMERA_GPIO("cam1_rst_lo", CAM1_RST_L_GPIO, 1),
};
int __init ventana_camera_late_init(void)
@@ -522,10 +613,6 @@ int __init ventana_camera_late_init(void)
i2c_new_device(i2c_get_adapter(3), ventana_i2c3_board_info_tca6416);
for (i = 0; i < ARRAY_SIZE(ventana_camera_gpio_keys); i++) {
-
- if (ventana_camera_gpio_keys[i].tegra_internal_gpio)
- tegra_gpio_enable(ventana_camera_gpio_keys[i].gpio);
-
ret = gpio_request(ventana_camera_gpio_keys[i].gpio,
ventana_camera_gpio_keys[i].name);
if (ret < 0) {
diff --git a/arch/arm/mach-tegra/board-ventana.c b/arch/arm/mach-tegra/board-ventana.c
index d371e720fdcf..c8c9ac49745f 100644
--- a/arch/arm/mach-tegra/board-ventana.c
+++ b/arch/arm/mach-tegra/board-ventana.c
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-tegra/board-ventana.c
*
- * Copyright (c) 2010-2011, NVIDIA Corporation.
+ * Copyright (c) 2010-2011 NVIDIA Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -38,6 +38,7 @@
#include <linux/memblock.h>
#include <linux/i2c/atmel_mxt_ts.h>
#include <linux/tegra_uart.h>
+#include <linux/rfkill-gpio.h>
#include <sound/wm8903.h>
@@ -63,56 +64,28 @@
#include "wakeups-t2.h"
#include "pm.h"
-static struct tegra_utmip_config utmi_phy_config[] = {
- [0] = {
- .hssync_start_delay = 9,
- .idle_wait_delay = 17,
- .elastic_limit = 16,
- .term_range_adj = 6,
- .xcvr_setup = 15,
- .xcvr_setup_offset = 0,
- .xcvr_use_fuses = 1,
- .xcvr_lsfslew = 2,
- .xcvr_lsrslew = 2,
- },
- [1] = {
- .hssync_start_delay = 9,
- .idle_wait_delay = 17,
- .elastic_limit = 16,
- .term_range_adj = 6,
- .xcvr_setup = 8,
- .xcvr_setup_offset = 0,
- .xcvr_use_fuses = 1,
- .xcvr_lsfslew = 2,
- .xcvr_lsrslew = 2,
- },
-};
-
-static struct tegra_ulpi_config ulpi_phy_config = {
- .reset_gpio = TEGRA_GPIO_PG2,
- .clk = "cdev2",
-};
-static struct resource ventana_bcm4329_rfkill_resources[] = {
+static struct rfkill_gpio_platform_data ventana_bt_rfkill_pdata[] = {
{
- .name = "bcm4329_nshutdown_gpio",
- .start = TEGRA_GPIO_PU0,
- .end = TEGRA_GPIO_PU0,
- .flags = IORESOURCE_IO,
+ .name = "bt_rfkill",
+ .shutdown_gpio = TEGRA_GPIO_PU0,
+ .reset_gpio = TEGRA_GPIO_INVALID,
+ .type = RFKILL_TYPE_BLUETOOTH,
},
};
-static struct platform_device ventana_bcm4329_rfkill_device = {
- .name = "bcm4329_rfkill",
+static struct platform_device ventana_bt_rfkill_device = {
+ .name = "rfkill_gpio",
.id = -1,
- .num_resources = ARRAY_SIZE(ventana_bcm4329_rfkill_resources),
- .resource = ventana_bcm4329_rfkill_resources,
+ .dev = {
+ .platform_data = ventana_bt_rfkill_pdata,
+ },
};
static void __init ventana_bt_rfkill(void)
{
/*Add Clock Resource*/
- clk_add_alias("bcm4329_32k_clk", ventana_bcm4329_rfkill_device.name, \
+ clk_add_alias("bcm4329_32k_clk", ventana_bt_rfkill_device.name, \
"blink", NULL);
return;
}
@@ -148,8 +121,6 @@ static struct platform_device ventana_bluesleep_device = {
static void __init ventana_setup_bluesleep(void)
{
platform_device_register(&ventana_bluesleep_device);
- tegra_gpio_enable(TEGRA_GPIO_PU6);
- tegra_gpio_enable(TEGRA_GPIO_PU1);
return;
}
@@ -164,19 +135,6 @@ static __initdata struct tegra_clk_init_table ventana_clk_init_table[] = {
{ NULL, NULL, 0, 0},
};
-static struct tegra_ulpi_config ventana_ehci2_ulpi_phy_config = {
- .reset_gpio = TEGRA_GPIO_PV1,
- .clk = "cdev2",
-};
-
-static struct tegra_ehci_platform_data ventana_ehci2_ulpi_platform_data = {
- .operating_mode = TEGRA_USB_HOST,
- .power_down_on_bus_suspend = 1,
- .phy_config = &ventana_ehci2_ulpi_phy_config,
- .phy_type = TEGRA_USB_PHY_TYPE_LINK_ULPI,
- .default_enable = true,
-};
-
static struct tegra_i2c_platform_data ventana_i2c1_platform_data = {
.adapter_nr = 0,
.bus_count = 1,
@@ -368,7 +326,8 @@ static int ventana_wakeup_key(void)
unsigned long status =
readl(IO_ADDRESS(TEGRA_PMC_BASE) + PMC_WAKE_STATUS);
- return status & TEGRA_WAKE_GPIO_PV2 ? KEY_POWER : KEY_RESERVED;
+ return (status & (1 << TEGRA_WAKE_GPIO_PV2)) ?
+ KEY_POWER : KEY_RESERVED;
}
static struct gpio_keys_platform_data ventana_keys_platform_data = {
@@ -384,14 +343,6 @@ static struct platform_device ventana_keys_device = {
.platform_data = &ventana_keys_platform_data,
},
};
-
-static void ventana_keys_init(void)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(ventana_keys); i++)
- tegra_gpio_enable(ventana_keys[i].gpio);
-}
#endif
static struct platform_device tegra_camera = {
@@ -431,7 +382,7 @@ static struct platform_device *ventana_devices[] __initdata = {
&tegra_das_device,
&spdif_dit_device,
&bluetooth_dit_device,
- &ventana_bcm4329_rfkill_device,
+ &ventana_bt_rfkill_device,
&tegra_pcm_device,
&ventana_audio_device,
};
@@ -498,73 +449,146 @@ static int __init ventana_touch_init_panjit(void)
return 0;
}
-static struct usb_phy_plat_data tegra_usb_phy_pdata[] = {
- [0] = {
- .instance = 0,
- .vbus_irq = TPS6586X_INT_BASE + TPS6586X_INT_USB_DET,
- .vbus_gpio = TEGRA_GPIO_PD0,
+static int __init ventana_gps_init(void)
+{
+ struct clk *clk32 = clk_get_sys(NULL, "blink");
+ if (!IS_ERR(clk32)) {
+ clk_set_rate(clk32,clk32->parent->rate);
+ clk_enable(clk32);
+ }
+
+ tegra_gpio_enable(TEGRA_GPIO_PZ3);
+ return 0;
+}
+
+static struct tegra_usb_platform_data tegra_udc_pdata = {
+ .port_otg = true,
+ .has_hostpc = false,
+ .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,
},
- [1] = {
- .instance = 1,
- .vbus_gpio = -1,
+ .u_cfg.utmi = {
+ .hssync_start_delay = 0,
+ .elastic_limit = 16,
+ .idle_wait_delay = 17,
+ .term_range_adj = 6,
+ .xcvr_setup = 8,
+ .xcvr_lsfslew = 2,
+ .xcvr_lsrslew = 2,
+ .xcvr_setup_offset = 0,
+ .xcvr_use_fuses = 1,
},
- [2] = {
- .instance = 2,
- .vbus_gpio = TEGRA_GPIO_PD3,
+};
+
+static struct tegra_usb_platform_data tegra_ehci1_utmi_pdata = {
+ .port_otg = true,
+ .has_hostpc = false,
+ .phy_intf = TEGRA_USB_PHY_INTF_UTMI,
+ .op_mode = TEGRA_USB_OPMODE_HOST,
+ .u_data.host = {
+ .vbus_gpio = TEGRA_GPIO_PD0,
+ .vbus_reg = NULL,
+ .hot_plug = true,
+ .remote_wakeup_supported = false,
+ .power_off_on_suspend = true,
+ },
+ .u_cfg.utmi = {
+ .hssync_start_delay = 9,
+ .elastic_limit = 16,
+ .idle_wait_delay = 17,
+ .term_range_adj = 6,
+ .xcvr_setup = 8,
+ .xcvr_lsfslew = 2,
+ .xcvr_lsrslew = 2,
},
};
-static struct tegra_ehci_platform_data tegra_ehci_pdata[] = {
- [0] = {
- .phy_config = &utmi_phy_config[0],
- .operating_mode = TEGRA_USB_HOST,
- .power_down_on_bus_suspend = 1,
- .default_enable = true,
+static void ulpi_link_platform_open(void)
+{
+ int reset_gpio = TEGRA_GPIO_PV1;
+
+ 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);
+}
+
+static struct tegra_usb_phy_platform_ops ulpi_link_plat_ops = {
+ .open = ulpi_link_platform_open,
+};
+
+static struct tegra_usb_platform_data tegra_ehci2_ulpi_link_pdata = {
+ .port_otg = false,
+ .has_hostpc = false,
+ .phy_intf = TEGRA_USB_PHY_INTF_ULPI_LINK,
+ .op_mode = TEGRA_USB_OPMODE_HOST,
+ .u_data.host = {
+ .vbus_gpio = -1,
+ .vbus_reg = NULL,
+ .hot_plug = false,
+ .remote_wakeup_supported = false,
+ .power_off_on_suspend = true,
},
- [1] = {
- .phy_config = &ulpi_phy_config,
- .operating_mode = TEGRA_USB_HOST,
- .power_down_on_bus_suspend = 1,
- .phy_type = TEGRA_USB_PHY_TYPE_LINK_ULPI,
- .default_enable = true,
+ .u_cfg.ulpi = {
+ .shadow_clk_delay = 10,
+ .clock_out_delay = 1,
+ .data_trimmer = 4,
+ .stpdirnxt_trimmer = 4,
+ .dir_trimmer = 4,
+ .clk = "cdev2",
},
- [2] = {
- .phy_config = &utmi_phy_config[1],
- .operating_mode = TEGRA_USB_HOST,
- .power_down_on_bus_suspend = 1,
- .hotplug = 1,
- .default_enable = true,
+ .ops = &ulpi_link_plat_ops,
+};
+
+static struct tegra_usb_platform_data tegra_ehci3_utmi_pdata = {
+ .port_otg = false,
+ .has_hostpc = false,
+ .phy_intf = TEGRA_USB_PHY_INTF_UTMI,
+ .op_mode = TEGRA_USB_OPMODE_HOST,
+ .u_data.host = {
+ .vbus_gpio = TEGRA_GPIO_PD3,
+ .vbus_reg = NULL,
+ .hot_plug = true,
+ .remote_wakeup_supported = false,
+ .power_off_on_suspend = true,
+ },
+ .u_cfg.utmi = {
+ .hssync_start_delay = 9,
+ .elastic_limit = 16,
+ .idle_wait_delay = 17,
+ .term_range_adj = 6,
+ .xcvr_setup = 8,
+ .xcvr_lsfslew = 2,
+ .xcvr_lsrslew = 2,
},
};
-static struct tegra_otg_platform_data tegra_otg_pdata = {
+static struct tegra_usb_otg_data tegra_otg_pdata = {
.ehci_device = &tegra_ehci1_device,
- .ehci_pdata = &tegra_ehci_pdata[0],
+ .ehci_pdata = &tegra_ehci1_utmi_pdata,
};
-static int __init ventana_gps_init(void)
-{
- struct clk *clk32 = clk_get_sys(NULL, "blink");
- if (!IS_ERR(clk32)) {
- clk_set_rate(clk32,clk32->parent->rate);
- clk_enable(clk32);
- }
-
- tegra_gpio_enable(TEGRA_GPIO_PZ3);
- return 0;
-}
-
static void ventana_usb_init(void)
{
- tegra_usb_phy_init(tegra_usb_phy_pdata, ARRAY_SIZE(tegra_usb_phy_pdata));
/* OTG should be the first to be registered */
tegra_otg_device.dev.platform_data = &tegra_otg_pdata;
platform_device_register(&tegra_otg_device);
+ tegra_udc_device.dev.platform_data = &tegra_udc_pdata;
platform_device_register(&tegra_udc_device);
+
+ tegra_ehci2_device.dev.platform_data = &tegra_ehci2_ulpi_link_pdata;
platform_device_register(&tegra_ehci2_device);
- tegra_ehci3_device.dev.platform_data=&tegra_ehci_pdata[2];
+ tegra_ehci3_device.dev.platform_data = &tegra_ehci3_utmi_pdata;
platform_device_register(&tegra_ehci3_device);
}
@@ -576,8 +600,6 @@ static void __init tegra_ventana_init(void)
ventana_pinmux_init();
ventana_i2c_init();
ventana_uart_init();
- tegra_ehci2_device.dev.platform_data
- = &ventana_ehci2_ulpi_platform_data;
platform_add_devices(ventana_devices, ARRAY_SIZE(ventana_devices));
tegra_ram_console_debug_init();
ventana_sdhci_init();
@@ -596,10 +618,6 @@ static void __init tegra_ventana_init(void)
ventana_touch_init_panjit();
}
-#ifdef CONFIG_KEYBOARD_GPIO
- ventana_keys_init();
-#endif
-
ventana_usb_init();
ventana_gps_init();
ventana_panel_init();
diff --git a/arch/arm/mach-tegra/board-whistler-baseband.c b/arch/arm/mach-tegra/board-whistler-baseband.c
index 143d14a8721d..4a479cfb871c 100644
--- a/arch/arm/mach-tegra/board-whistler-baseband.c
+++ b/arch/arm/mach-tegra/board-whistler-baseband.c
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-tegra/board-whistler-baseband.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
@@ -16,32 +16,15 @@
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/tegra_caif.h>
#include <mach/tegra_usb_modem_power.h>
-
#include "board.h"
#include "board-whistler-baseband.h"
-static int baseband_phy_on(void);
-static int baseband_phy_off(void);
-static void baseband_phy_restore_start(void);
-static void baseband_phy_restore_end(void);
-
-static struct wake_lock mdm_wake_lock;
-
static struct gpio modem_gpios[] = {
{MODEM_PWR_ON, GPIOF_OUT_INIT_LOW, "MODEM PWR ON"},
{MODEM_RESET, GPIOF_IN, "MODEM RESET"},
- {BB_RST_OUT, GPIOF_IN, "BB RST OUT"},
- {MDM2AP_ACK, GPIOF_IN, "MDM2AP_ACK"},
{AP2MDM_ACK2, GPIOF_OUT_INIT_HIGH, "AP2MDM ACK2"},
{AP2MDM_ACK, GPIOF_OUT_INIT_LOW, "AP2MDM ACK"},
- {ULPI_STP, GPIOF_IN, "ULPI_STP"},
- {ULPI_DIR, GPIOF_OUT_INIT_LOW, "ULPI_DIR"},
- {ULPI_D0, GPIOF_OUT_INIT_LOW, "ULPI_D0"},
- {ULPI_D1, GPIOF_OUT_INIT_LOW, "ULPI_D1"},
};
static __initdata struct tegra_pingroup_config whistler_null_ulpi_pinmux[] = {
@@ -57,78 +40,50 @@ static __initdata struct tegra_pingroup_config whistler_null_ulpi_pinmux[] = {
TEGRA_TRI_NORMAL},
};
-static struct tegra_ulpi_trimmer e1219_trimmer = { 10, 1, 1, 1 };
-
-static struct tegra_ulpi_config ehci2_null_ulpi_phy_config = {
- .trimmer = &e1219_trimmer,
- .post_phy_on = baseband_phy_on,
- .pre_phy_off = baseband_phy_off,
- .phy_restore_start = baseband_phy_restore_start,
- .phy_restore_end = baseband_phy_restore_end,
- .phy_restore_gpio = MDM2AP_ACK,
- .ulpi_dir_gpio = ULPI_DIR,
- .ulpi_d0_gpio = ULPI_D0,
- .ulpi_d1_gpio = ULPI_D1,
-};
+static void baseband_post_phy_on(void);
+static void baseband_pre_phy_off(void);
-static struct tegra_ehci_platform_data ehci2_null_ulpi_platform_data = {
- .operating_mode = TEGRA_USB_HOST,
- .power_down_on_bus_suspend = 0,
- .phy_config = &ehci2_null_ulpi_phy_config,
- .phy_type = TEGRA_USB_PHY_TYPE_NULL_ULPI,
+static struct tegra_usb_phy_platform_ops ulpi_null_plat_ops = {
+ .pre_phy_off = baseband_pre_phy_off,
+ .post_phy_on = baseband_post_phy_on,
};
-static int __init tegra_null_ulpi_init(void)
-{
- tegra_ehci2_device.dev.platform_data = &ehci2_null_ulpi_platform_data;
- platform_device_register(&tegra_ehci2_device);
- return 0;
-}
-
-static irqreturn_t mdm_start_thread(int irq, void *data)
-{
- if (gpio_get_value(BB_RST_OUT)) {
- pr_info("BB_RST_OUT high\n");
- } else {
- pr_info("BB_RST_OUT low\n");
- /* hold wait lock to complete the enumeration */
- wake_lock_timeout(&mdm_wake_lock, HZ * 10);
- }
-
- return IRQ_HANDLED;
-}
-
-static int baseband_phy_on(void)
-{
- static bool phy_init;
-
- if (!phy_init) {
- /* set AP2MDM_ACK2 low */
- gpio_set_value(AP2MDM_ACK2, 0);
- phy_init = true;
- }
- pr_info("%s\n", __func__);
- return 0;
-}
+static struct tegra_usb_platform_data tegra_ehci2_ulpi_null_pdata = {
+ .port_otg = false,
+ .has_hostpc = false,
+ .phy_intf = TEGRA_USB_PHY_INTF_ULPI_NULL,
+ .op_mode = TEGRA_USB_OPMODE_HOST,
+ .u_data.host = {
+ .vbus_gpio = -1,
+ .vbus_reg = NULL,
+ .hot_plug = false,
+ .remote_wakeup_supported = false,
+ .power_off_on_suspend = true,
+ },
+ .u_cfg.ulpi = {
+ .shadow_clk_delay = 10,
+ .clock_out_delay = 1,
+ .data_trimmer = 1,
+ .stpdirnxt_trimmer = 1,
+ .dir_trimmer = 1,
+ .clk = NULL,
+ .phy_restore_gpio = MDM2AP_ACK,
+ },
+ .ops = &ulpi_null_plat_ops,
+};
-static int baseband_phy_off(void)
+static void baseband_post_phy_on(void)
{
- pr_info("%s\n", __func__);
- return 0;
+ /* set AP2MDM_ACK2 low */
+ gpio_set_value(AP2MDM_ACK2, 0);
}
-static void baseband_phy_restore_start(void)
+static void baseband_pre_phy_off(void)
{
/* set AP2MDM_ACK2 high */
gpio_set_value(AP2MDM_ACK2, 1);
}
-static void baseband_phy_restore_end(void)
-{
- /* set AP2MDM_ACK2 low */
- gpio_set_value(AP2MDM_ACK2, 0);
-}
-
static void baseband_start(void)
{
/*
@@ -150,7 +105,6 @@ static void baseband_reset(void)
static int baseband_init(void)
{
- int irq;
int ret;
ret = gpio_request_array(modem_gpios, ARRAY_SIZE(modem_gpios));
@@ -161,43 +115,9 @@ static int baseband_init(void)
tegra_pinmux_set_pullupdown(TEGRA_PINGROUP_UAC,
TEGRA_PUPD_PULL_UP);
- tegra_gpio_enable(MODEM_PWR_ON);
- tegra_gpio_enable(MODEM_RESET);
- tegra_gpio_enable(AP2MDM_ACK2);
- tegra_gpio_enable(BB_RST_OUT);
- tegra_gpio_enable(AP2MDM_ACK);
- tegra_gpio_enable(MDM2AP_ACK);
- tegra_gpio_enable(TEGRA_GPIO_PY3);
- tegra_gpio_enable(TEGRA_GPIO_PY1);
- tegra_gpio_enable(TEGRA_GPIO_PO1);
- tegra_gpio_enable(TEGRA_GPIO_PO2);
-
/* export GPIO for user space access through sysfs */
gpio_export(MODEM_PWR_ON, false);
- /* phy init */
- tegra_null_ulpi_init();
-
- wake_lock_init(&mdm_wake_lock, WAKE_LOCK_SUSPEND, "mdm_lock");
-
- /* enable IRQ for BB_RST_OUT */
- irq = gpio_to_irq(BB_RST_OUT);
-
- ret = request_threaded_irq(irq, NULL, mdm_start_thread,
- IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
- "mdm_start", NULL);
- if (ret < 0) {
- pr_err("%s: request_threaded_irq error\n", __func__);
- return ret;
- }
-
- ret = enable_irq_wake(irq);
- if (ret) {
- pr_err("%s: enable_irq_wake error\n", __func__);
- free_irq(irq, NULL);
- return ret;
- }
-
return 0;
}
@@ -210,7 +130,13 @@ static const struct tegra_modem_operations baseband_operations = {
static struct tegra_usb_modem_power_platform_data baseband_pdata = {
.ops = &baseband_operations,
.wake_gpio = MDM2AP_ACK2,
- .flags = IRQF_TRIGGER_FALLING,
+ .wake_irq_flags = IRQF_TRIGGER_FALLING,
+ .boot_gpio = BB_RST_OUT,
+ .boot_irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ .autosuspend_delay = 2000,
+ .short_autosuspend_delay = 50,
+ .tegra_ehci_device = &tegra_ehci2_device,
+ .tegra_ehci_pdata = &tegra_ehci2_ulpi_null_pdata,
};
static struct platform_device icera_baseband_device = {
diff --git a/arch/arm/mach-tegra/board-whistler-panel.c b/arch/arm/mach-tegra/board-whistler-panel.c
index 74075d4659c5..d727675c1421 100644
--- a/arch/arm/mach-tegra/board-whistler-panel.c
+++ b/arch/arm/mach-tegra/board-whistler-panel.c
@@ -29,7 +29,7 @@
#include <linux/pwm_backlight.h>
#include <linux/tegra_pwm_bl.h>
#include <linux/nvhost.h>
-#include <mach/nvmap.h>
+#include <linux/nvmap.h>
#include <mach/irqs.h>
#include <mach/iomap.h>
#include <mach/dc.h>
@@ -38,6 +38,7 @@
#include "devices.h"
#include "gpio-names.h"
#include "board.h"
+#include "tegra2_host1x_devices.h"
#define whistler_hdmi_hpd TEGRA_GPIO_PN7
@@ -58,7 +59,6 @@ static struct platform_tegra_pwm_backlight_data whistler_disp1_backlight_data =
.max_brightness = 256,
.dft_brightness = 77,
.gpio_conf_to_sfio = TEGRA_GPIO_PW1,
- .switch_to_sfio = &tegra_gpio_disable,
.period = 0x1F,
.clk_div = 3,
.clk_select = 2,
@@ -318,25 +318,19 @@ static void whistler_panel_early_suspend(struct early_suspend *h)
fb_blank(registered_fb[1], FB_BLANK_NORMAL);
#ifdef CONFIG_TEGRA_CONVSERVATIVE_GOV_ON_EARLYSUPSEND
- cpufreq_save_default_governor();
- cpufreq_set_conservative_governor();
- cpufreq_set_conservative_governor_param("up_threshold",
- SET_CONSERVATIVE_GOVERNOR_UP_THRESHOLD);
-
- cpufreq_set_conservative_governor_param("down_threshold",
- SET_CONSERVATIVE_GOVERNOR_DOWN_THRESHOLD);
-
- cpufreq_set_conservative_governor_param("freq_step",
- SET_CONSERVATIVE_GOVERNOR_FREQ_STEP);
+ cpufreq_store_default_gov();
+ cpufreq_change_gov(cpufreq_conservative_gov);
#endif
}
static void whistler_panel_late_resume(struct early_suspend *h)
{
unsigned i;
+
#ifdef CONFIG_TEGRA_CONVSERVATIVE_GOV_ON_EARLYSUPSEND
- cpufreq_restore_default_governor();
+ cpufreq_restore_default_gov();
#endif
+
for (i = 0; i < num_registered_fb; i++)
fb_blank(registered_fb[i], FB_BLANK_UNBLANK);
}
@@ -347,7 +341,6 @@ int __init whistler_panel_init(void)
int err;
struct resource __maybe_unused *res;
- tegra_gpio_enable(whistler_hdmi_hpd);
gpio_request(whistler_hdmi_hpd, "hdmi_hpd");
gpio_direction_input(whistler_hdmi_hpd);
@@ -364,7 +357,7 @@ int __init whistler_panel_init(void)
#endif
#ifdef CONFIG_TEGRA_GRHOST
- err = nvhost_device_register(&tegra_grhost_device);
+ err = tegra2_register_host1x_devices();
if (err)
return err;
#endif
diff --git a/arch/arm/mach-tegra/board-whistler-pinmux.c b/arch/arm/mach-tegra/board-whistler-pinmux.c
index 22c2f984c662..15ae9c76b19d 100644
--- a/arch/arm/mach-tegra/board-whistler-pinmux.c
+++ b/arch/arm/mach-tegra/board-whistler-pinmux.c
@@ -64,13 +64,15 @@
}
static __initdata struct tegra_drive_pingroup_config whistler_drive_pinmux[] = {
- DEFAULT_DRIVE(DBG),
- DEFAULT_DRIVE(DDC),
DEFAULT_DRIVE(VI1),
- DEFAULT_DRIVE(VI2),
DEFAULT_DRIVE(SDIO1),
SET_DRIVE(DAP2, DISABLE, ENABLE, DIV_1, 46, 46, SLOWEST, SLOWEST),
SET_DRIVE(DAP3, DISABLE, ENABLE, DIV_1, 46, 46, SLOWEST, SLOWEST),
+ SET_DRIVE(DBG, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST), /* I2C1 */
+ SET_DRIVE(DDC, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST), /* I2C2-1 */
+ SET_DRIVE(AT1, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST), /* I2C2-2 */
+ SET_DRIVE(VI2, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST), /* I2C3 */
+ SET_DRIVE(AO1, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST), /* DVC */
};
static __initdata struct tegra_pingroup_config whistler_pinmux[] = {
@@ -93,7 +95,7 @@ static __initdata struct tegra_pingroup_config whistler_pinmux[] = {
{TEGRA_PINGROUP_DTC, TEGRA_MUX_VI, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_DTD, TEGRA_MUX_VI, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_DTE, TEGRA_MUX_RSVD1, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
- {TEGRA_PINGROUP_DTF, TEGRA_MUX_I2C3, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_DTF, TEGRA_MUX_I2C3, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_GMA, TEGRA_MUX_GMI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_GMB, TEGRA_MUX_GMI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_GMC, TEGRA_MUX_GMI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
@@ -103,7 +105,7 @@ static __initdata struct tegra_pingroup_config whistler_pinmux[] = {
{TEGRA_PINGROUP_GPU7, TEGRA_MUX_RTCK, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_GPV, TEGRA_MUX_PCIE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_HDINT, TEGRA_MUX_HDMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_I2CP, TEGRA_MUX_I2C, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_I2CP, TEGRA_MUX_I2C, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_IRRX, TEGRA_MUX_UARTB, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_IRTX, TEGRA_MUX_UARTB, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_KBCA, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
@@ -155,7 +157,7 @@ static __initdata struct tegra_pingroup_config whistler_pinmux[] = {
{TEGRA_PINGROUP_OWC, TEGRA_MUX_OWR, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
{TEGRA_PINGROUP_PMC, TEGRA_MUX_PWR_ON, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_PTA, TEGRA_MUX_HDMI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE},
- {TEGRA_PINGROUP_RM, TEGRA_MUX_I2C, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_RM, TEGRA_MUX_I2C, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_SDB, TEGRA_MUX_SDIO3, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_SDC, TEGRA_MUX_SDIO3, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_SDD, TEGRA_MUX_SDIO3, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
diff --git a/arch/arm/mach-tegra/board-whistler-power.c b/arch/arm/mach-tegra/board-whistler-power.c
index a0eb6686b0db..67663252e0d9 100644
--- a/arch/arm/mach-tegra/board-whistler-power.c
+++ b/arch/arm/mach-tegra/board-whistler-power.c
@@ -31,7 +31,6 @@
#include "gpio-names.h"
#include "fuse.h"
#include "pm.h"
-#include "wakeups-t2.h"
#include "board.h"
#define PMC_CTRL 0x0
diff --git a/arch/arm/mach-tegra/board-whistler-sdhci.c b/arch/arm/mach-tegra/board-whistler-sdhci.c
index d98b1d53a52e..5721a2e179df 100644
--- a/arch/arm/mach-tegra/board-whistler-sdhci.c
+++ b/arch/arm/mach-tegra/board-whistler-sdhci.c
@@ -2,7 +2,7 @@
* arch/arm/mach-tegra/board-whistler-sdhci.c
*
* Copyright (C) 2010 Google, Inc.
- * Copyright (C) 2011 NVIDIA Corporation.
+ * Copyright (C) 2011-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
@@ -168,6 +168,7 @@ static struct tegra_sdhci_platform_data tegra_sdhci_platform_data1 = {
.embedded_sdio = &embedded_sdio_data1,
#endif
.built_in = 0,
+ .ocr_mask = MMC_OCR_1V8_MASK,
},
#ifndef CONFIG_MMC_EMBEDDED_SDIO
.pm_flags = MMC_PM_KEEP_POWER,
@@ -243,10 +244,6 @@ static int __init whistler_wifi_init(void)
gpio_request(WHISTLER_WLAN_RST, "wlan_rst");
gpio_request(WHISTLER_WLAN_WOW, "bcmsdh_sdmmc");
- tegra_gpio_enable(WHISTLER_WLAN_PWR);
- tegra_gpio_enable(WHISTLER_WLAN_RST);
- tegra_gpio_enable(WHISTLER_WLAN_WOW);
-
gpio_direction_output(WHISTLER_WLAN_PWR, 0);
gpio_direction_output(WHISTLER_WLAN_RST, 0);
gpio_direction_input(WHISTLER_WLAN_WOW);
@@ -256,10 +253,6 @@ static int __init whistler_wifi_init(void)
}
int __init whistler_sdhci_init(void)
{
- int ret;
-
- tegra_gpio_enable(WHISTLER_EXT_SDCARD_DETECT);
-
platform_device_register(&tegra_sdhci_device3);
platform_device_register(&tegra_sdhci_device2);
platform_device_register(&tegra_sdhci_device1);
diff --git a/arch/arm/mach-tegra/board-whistler-sensors.c b/arch/arm/mach-tegra/board-whistler-sensors.c
index 95bb2f1dd405..9783347cd631 100644
--- a/arch/arm/mach-tegra/board-whistler-sensors.c
+++ b/arch/arm/mach-tegra/board-whistler-sensors.c
@@ -70,37 +70,30 @@ static struct regulator *reg_vddio_vi; /* LDO18 */
static int whistler_camera_init(void)
{
- tegra_gpio_enable(CAMERA1_PWDN_GPIO);
gpio_request(CAMERA1_PWDN_GPIO, "camera1_powerdown");
gpio_direction_output(CAMERA1_PWDN_GPIO, 0);
gpio_export(CAMERA1_PWDN_GPIO, false);
- tegra_gpio_enable(CAMERA1_RESET_GPIO);
gpio_request(CAMERA1_RESET_GPIO, "camera1_reset");
gpio_direction_output(CAMERA1_RESET_GPIO, 0);
gpio_export(CAMERA1_RESET_GPIO, false);
- tegra_gpio_enable(CAMERA2_PWDN_GPIO);
gpio_request(CAMERA2_PWDN_GPIO, "camera2_powerdown");
gpio_direction_output(CAMERA2_PWDN_GPIO, 0);
gpio_export(CAMERA2_PWDN_GPIO, false);
- tegra_gpio_enable(CAMERA2_RESET_GPIO);
gpio_request(CAMERA2_RESET_GPIO, "camera2_reset");
gpio_direction_output(CAMERA2_RESET_GPIO, 0);
gpio_export(CAMERA2_RESET_GPIO, false);
- tegra_gpio_enable(CAMERA_AF_PD_GPIO);
gpio_request(CAMERA_AF_PD_GPIO, "camera_autofocus");
gpio_direction_output(CAMERA_AF_PD_GPIO, 0);
gpio_export(CAMERA_AF_PD_GPIO, false);
- tegra_gpio_enable(CAMERA_FLASH_EN1_GPIO);
gpio_request(CAMERA_FLASH_EN1_GPIO, "camera_flash_en1");
gpio_direction_output(CAMERA_FLASH_EN1_GPIO, 0);
gpio_export(CAMERA_FLASH_EN1_GPIO, false);
- tegra_gpio_enable(CAMERA_FLASH_EN2_GPIO);
gpio_request(CAMERA_FLASH_EN2_GPIO, "camera_flash_en2");
gpio_direction_output(CAMERA_FLASH_EN2_GPIO, 0);
gpio_export(CAMERA_FLASH_EN2_GPIO, false);
@@ -293,14 +286,12 @@ static struct i2c_board_info whistler_i2c3_board_info[] = {
static void whistler_adxl34x_init(void)
{
- tegra_gpio_enable(ADXL34X_IRQ_GPIO);
gpio_request(ADXL34X_IRQ_GPIO, "adxl34x");
gpio_direction_input(ADXL34X_IRQ_GPIO);
}
static void whistler_isl29018_init(void)
{
- tegra_gpio_enable(ISL29018_IRQ_GPIO);
gpio_request(ISL29018_IRQ_GPIO, "isl29018");
gpio_direction_input(ISL29018_IRQ_GPIO);
}
@@ -316,11 +307,6 @@ static struct i2c_board_info whistler_i2c1_board_info[] = {
},
};
-static void whistler_adt7461_init(void)
-{
- tegra_gpio_enable(ADT7461_IRQ_GPIO);
-}
-
static struct adt7461_platform_data whistler_adt7461_pdata = {
.supported_hwrev = true,
.ext_range = false,
@@ -355,8 +341,6 @@ int __init whistler_sensors_init(void)
whistler_isl29018_init();
- whistler_adt7461_init();
-
i2c_register_board_info(0, whistler_i2c1_board_info,
ARRAY_SIZE(whistler_i2c1_board_info));
diff --git a/arch/arm/mach-tegra/board-whistler.c b/arch/arm/mach-tegra/board-whistler.c
index f1246454ed1b..06e704e47870 100644
--- a/arch/arm/mach-tegra/board-whistler.c
+++ b/arch/arm/mach-tegra/board-whistler.c
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-tegra/board-whistler.c
*
- * Copyright (c) 2010 - 2011, NVIDIA Corporation.
+ * Copyright (c) 2010-2012 NVIDIA Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -37,6 +37,7 @@
#include <linux/mfd/max8907c.h>
#include <linux/memblock.h>
#include <linux/tegra_uart.h>
+#include <linux/rfkill-gpio.h>
#include <mach/clk.h>
#include <mach/iomap.h>
@@ -169,21 +170,21 @@ static void __init whistler_uart_init(void)
platform_add_devices(whistler_uart_devices,
ARRAY_SIZE(whistler_uart_devices));
}
-
-static struct resource whistler_bcm4329_rfkill_resources[] = {
+static struct rfkill_gpio_platform_data whistler_bt_rfkill_pdata[] = {
{
- .name = "bcm4329_nshutdown_gpio",
- .start = TEGRA_GPIO_PU0,
- .end = TEGRA_GPIO_PU0,
- .flags = IORESOURCE_IO,
+ .name = "bt_rfkill",
+ .shutdown_gpio = TEGRA_GPIO_PU0,
+ .reset_gpio = TEGRA_GPIO_INVALID,
+ .type = RFKILL_TYPE_BLUETOOTH,
},
};
-static struct platform_device whistler_bcm4329_rfkill_device = {
- .name = "bcm4329_rfkill",
- .id = -1,
- .num_resources = ARRAY_SIZE(whistler_bcm4329_rfkill_resources),
- .resource = whistler_bcm4329_rfkill_resources,
+static struct platform_device whistler_bt_rfkill_device = {
+ .name = "rfkill_gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = whistler_bt_rfkill_pdata,
+ },
};
static struct resource whistler_bluesleep_resources[] = {
@@ -217,37 +218,9 @@ static struct platform_device whistler_bluesleep_device = {
static void __init whistler_setup_bluesleep(void)
{
platform_device_register(&whistler_bluesleep_device);
- tegra_gpio_enable(TEGRA_GPIO_PU6);
- tegra_gpio_enable(TEGRA_GPIO_PU1);
return;
}
-static struct tegra_utmip_config utmi_phy_config[] = {
- [0] = {
- .hssync_start_delay = 9,
- .idle_wait_delay = 17,
- .elastic_limit = 16,
- .term_range_adj = 6,
- .xcvr_setup = 15,
- .xcvr_lsfslew = 2,
- .xcvr_lsrslew = 2,
- },
- [1] = {
- .hssync_start_delay = 9,
- .idle_wait_delay = 17,
- .elastic_limit = 16,
- .term_range_adj = 6,
- .xcvr_setup = 8,
- .xcvr_lsfslew = 2,
- .xcvr_lsrslew = 2,
- },
-};
-
-static struct tegra_ulpi_config ulpi_phy_config = {
- .reset_gpio = TEGRA_GPIO_PG2,
- .clk = "cdev2",
-};
-
static __initdata struct tegra_clk_init_table whistler_clk_init_table[] = {
/* name parent rate enabled */
{ "pwm", "clk_32k", 32768, false},
@@ -266,6 +239,7 @@ static struct tegra_i2c_platform_data whistler_i2c1_platform_data = {
.scl_gpio = {TEGRA_GPIO_PC4, 0},
.sda_gpio = {TEGRA_GPIO_PC5, 0},
.arb_recovery = arb_lost_recovery,
+ .slave_addr = 0xFC,
};
static const struct tegra_pingroup_config i2c2_ddc = {
@@ -287,6 +261,7 @@ static struct tegra_i2c_platform_data whistler_i2c2_platform_data = {
.scl_gpio = {0, TEGRA_GPIO_PT5},
.sda_gpio = {0, TEGRA_GPIO_PT6},
.arb_recovery = arb_lost_recovery,
+ .slave_addr = 0xFC,
};
static struct tegra_i2c_platform_data whistler_i2c3_platform_data = {
@@ -296,6 +271,7 @@ static struct tegra_i2c_platform_data whistler_i2c3_platform_data = {
.scl_gpio = {TEGRA_GPIO_PBB2, 0},
.sda_gpio = {TEGRA_GPIO_PBB3, 0},
.arb_recovery = arb_lost_recovery,
+ .slave_addr = 0xFC,
};
static struct tegra_i2c_platform_data whistler_dvc_platform_data = {
@@ -416,7 +392,7 @@ static struct platform_device *whistler_devices[] __initdata = {
&spdif_dit_device,
&bluetooth_dit_device,
&baseband_dit_device,
- &whistler_bcm4329_rfkill_device,
+ &whistler_bt_rfkill_device,
&tegra_pcm_device,
&whistler_audio_aic326x_device,
&whistler_audio_wm8753_device,
@@ -437,76 +413,70 @@ static const struct i2c_board_info whistler_i2c_touch_info[] = {
static int __init whistler_touch_init(void)
{
- tegra_gpio_enable(TEGRA_GPIO_PC6);
i2c_register_board_info(0, whistler_i2c_touch_info, 1);
return 0;
}
-static int __init whistler_scroll_init(void)
-{
- int i;
- for (i = 0; i < ARRAY_SIZE(scroll_keys); i++)
- tegra_gpio_enable(scroll_keys[i].gpio);
-
- return 0;
-}
-
-static struct usb_phy_plat_data tegra_usb_phy_pdata[] = {
- [0] = {
- .instance = 0,
- .vbus_irq = MAX8907C_INT_BASE + MAX8907C_IRQ_VCHG_DC_R,
- .vbus_gpio = USB1_VBUS_GPIO,
- },
- [1] = {
- .instance = 1,
- .vbus_gpio = -1,
+static struct tegra_usb_platform_data tegra_udc_pdata = {
+ .port_otg = true,
+ .has_hostpc = false,
+ .phy_intf = TEGRA_USB_PHY_INTF_UTMI,
+ .op_mode = TEGRA_USB_OPMODE_DEVICE,
+ .u_data.dev = {
+ .vbus_pmu_irq = MAX8907C_INT_BASE + MAX8907C_IRQ_VCHG_DC_R,
+ .vbus_gpio = -1,
+ .charging_supported = false,
+ .remote_wakeup_supported = false,
},
- [2] = {
- .instance = 2,
- .vbus_gpio = -1,
+ .u_cfg.utmi = {
+ .hssync_start_delay = 0,
+ .elastic_limit = 16,
+ .idle_wait_delay = 17,
+ .term_range_adj = 6,
+ .xcvr_setup = 8,
+ .xcvr_lsfslew = 2,
+ .xcvr_lsrslew = 2,
+ .xcvr_setup_offset = 0,
+ .xcvr_use_fuses = 1,
},
};
-static struct tegra_ehci_platform_data tegra_ehci_pdata[] = {
- [0] = {
- .phy_config = &utmi_phy_config[0],
- .operating_mode = TEGRA_USB_HOST,
- .power_down_on_bus_suspend = 1,
- .default_enable = false,
- },
- [1] = {
- .phy_config = &ulpi_phy_config,
- .operating_mode = TEGRA_USB_HOST,
- .power_down_on_bus_suspend = 1,
- .default_enable = false,
- },
- [2] = {
- .phy_config = &utmi_phy_config[1],
- .operating_mode = TEGRA_USB_HOST,
- .power_down_on_bus_suspend = 1,
- .default_enable = false,
+static struct tegra_usb_platform_data tegra_ehci1_utmi_pdata = {
+ .port_otg = true,
+ .has_hostpc = false,
+ .phy_intf = TEGRA_USB_PHY_INTF_UTMI,
+ .op_mode = TEGRA_USB_OPMODE_HOST,
+ .u_data.host = {
+ .vbus_gpio = TEGRA_GPIO_PN6,
+ .vbus_reg = NULL,
+ .hot_plug = true,
+ .remote_wakeup_supported = false,
+ .power_off_on_suspend = true,
+ },
+ .u_cfg.utmi = {
+ .hssync_start_delay = 9,
+ .elastic_limit = 16,
+ .idle_wait_delay = 17,
+ .term_range_adj = 6,
+ .xcvr_setup = 8,
+ .xcvr_lsfslew = 2,
+ .xcvr_lsrslew = 2,
},
};
-static struct tegra_otg_platform_data tegra_otg_pdata = {
+static struct tegra_usb_otg_data tegra_otg_pdata = {
.ehci_device = &tegra_ehci1_device,
- .ehci_pdata = &tegra_ehci_pdata[0],
+ .ehci_pdata = &tegra_ehci1_utmi_pdata,
};
-static int __init whistler_gps_init(void)
-{
- tegra_gpio_enable(TEGRA_GPIO_PU4);
- return 0;
-}
-
+#define SERIAL_NUMBER_LENGTH 20
static void whistler_usb_init(void)
{
- tegra_usb_phy_init(tegra_usb_phy_pdata, ARRAY_SIZE(tegra_usb_phy_pdata));
-
tegra_otg_device.dev.platform_data = &tegra_otg_pdata;
platform_device_register(&tegra_otg_device);
+ tegra_udc_device.dev.platform_data = &tegra_udc_pdata;
}
static void __init tegra_whistler_init(void)
@@ -524,9 +494,7 @@ static void __init tegra_whistler_init(void)
whistler_sensors_init();
whistler_touch_init();
whistler_kbc_init();
- whistler_gps_init();
whistler_usb_init();
- whistler_scroll_init();
whistler_emc_init();
if (modem_id == 0x1)
whistler_baseband_init();
diff --git a/arch/arm/mach-tegra/board.h b/arch/arm/mach-tegra/board.h
index c7ab065bc195..7c081fad642a 100644
--- a/arch/arm/mach-tegra/board.h
+++ b/arch/arm/mach-tegra/board.h
@@ -157,16 +157,17 @@ void tegra_get_board_info(struct board_info *);
void tegra_get_pmu_board_info(struct board_info *bi);
void tegra_get_display_board_info(struct board_info *bi);
void tegra_get_camera_board_info(struct board_info *bi);
+
#ifdef CONFIG_TEGRA_CONVSERVATIVE_GOV_ON_EARLYSUPSEND
-#define SET_CONSERVATIVE_GOVERNOR_UP_THRESHOLD 95
-#define SET_CONSERVATIVE_GOVERNOR_DOWN_THRESHOLD 50
-#define SET_CONSERVATIVE_GOVERNOR_FREQ_STEP 3
-
-void cpufreq_save_default_governor(void);
-void cpufreq_restore_default_governor(void);
-void cpufreq_set_conservative_governor(void);
-void cpufreq_set_conservative_governor_param(char *name, int value);
+#define MAX_GOV_NAME_LEN 16
+extern char cpufreq_default_gov[][MAX_GOV_NAME_LEN];
+extern char *cpufreq_conservative_gov;
+
+void cpufreq_store_default_gov(void);
+void cpufreq_restore_default_gov(void);
+void cpufreq_change_gov(char *target_gov);
#endif
+
int get_core_edp(void);
enum panel_type get_panel_type(void);
int tegra_get_modem_id(void);
diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c
index f31da0bf1494..66a954fb6696 100644
--- a/arch/arm/mach-tegra/clock.c
+++ b/arch/arm/mach-tegra/clock.c
@@ -238,16 +238,9 @@ void clk_init(struct clk *c)
static int clk_enable_locked(struct clk *c)
{
int ret = 0;
- int rate = clk_get_rate_locked(c);
- bool set_rate = false;
-
- if (rate > c->max_rate) {
- rate = c->max_rate;
- set_rate = true;
- }
if (clk_is_auto_dvfs(c)) {
- ret = tegra_dvfs_set_rate(c, rate);
+ ret = tegra_dvfs_set_rate(c, clk_get_rate_locked(c));
if (ret)
return ret;
}
@@ -259,9 +252,6 @@ static int clk_enable_locked(struct clk *c)
return ret;
}
- if (set_rate)
- clk_set_rate_locked(c, rate);
-
if (c->ops && c->ops->enable) {
ret = c->ops->enable(c);
trace_clock_enable(c->name, 1, 0);
@@ -525,13 +515,11 @@ unsigned long clk_get_rate_all_locked(struct clk *c)
return rate;
}
-long clk_round_rate(struct clk *c, unsigned long rate)
+long clk_round_rate_locked(struct clk *c, unsigned long rate)
{
- unsigned long flags, max_rate;
+ unsigned long max_rate;
long ret;
- clk_lock_save(c, &flags);
-
if (!c->ops || !c->ops->round_rate) {
ret = -ENOSYS;
goto out;
@@ -544,6 +532,16 @@ long clk_round_rate(struct clk *c, unsigned long rate)
ret = c->ops->round_rate(c, rate);
out:
+ return ret;
+}
+
+long clk_round_rate(struct clk *c, unsigned long rate)
+{
+ unsigned long flags;
+ long ret;
+
+ clk_lock_save(c, &flags);
+ ret = clk_round_rate_locked(c, rate);
clk_unlock_restore(c, &flags);
return ret;
}
@@ -1299,6 +1297,10 @@ static int clk_debugfs_register_one(struct clk *c)
if (!d)
goto err_out;
+ d = debugfs_create_u32("min", S_IRUGO, c->dent, (u32 *)&c->min_rate);
+ if (!d)
+ goto err_out;
+
d = debugfs_create_file(
"parent", parent_rate_mode, c->dent, c, &parent_fops);
if (!d)
diff --git a/arch/arm/mach-tegra/clock.h b/arch/arm/mach-tegra/clock.h
index dde9e07292a7..c27176b1cc0d 100644
--- a/arch/arm/mach-tegra/clock.h
+++ b/arch/arm/mach-tegra/clock.h
@@ -76,6 +76,12 @@ struct clk_mux_sel {
u32 value;
};
+struct clk_backup {
+ struct clk *input;
+ u32 value;
+ unsigned long bus_rate;
+};
+
struct clk_pll_freq_table {
unsigned long input_rate;
unsigned long output_rate;
@@ -152,7 +158,7 @@ struct clk {
u32 reg_shift;
struct list_head shared_bus_list;
- struct clk_mux_sel shared_bus_backup;
+ struct clk_backup shared_bus_backup;
union {
struct {
@@ -240,6 +246,7 @@ unsigned long clk_get_min_rate(struct clk *c);
unsigned long clk_get_rate_locked(struct clk *c);
int clk_set_rate_locked(struct clk *c, unsigned long rate);
int clk_set_parent_locked(struct clk *c, struct clk *parent);
+long clk_round_rate_locked(struct clk *c, unsigned long rate);
int tegra_clk_shared_bus_update(struct clk *c);
void tegra2_sdmmc_tap_delay(struct clk *c, int delay);
void tegra3_set_cpu_skipper_delay(int delay);
@@ -248,9 +255,12 @@ long tegra_emc_round_rate(unsigned long rate);
struct clk *tegra_emc_predict_parent(unsigned long rate, u32 *div_value);
void tegra_emc_timing_invalidate(void);
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
+static inline int tegra_emc_backup(unsigned long rate)
+{ return 0; }
static inline bool tegra_clk_is_parent_allowed(struct clk *c, struct clk *p)
{ return true; }
#else
+int tegra_emc_backup(unsigned long rate);
bool tegra_clk_is_parent_allowed(struct clk *c, struct clk *p);
#endif
diff --git a/arch/arm/mach-tegra/common-t2.c b/arch/arm/mach-tegra/common-t2.c
index 6f9b177892ce..f90dfce6a690 100644
--- a/arch/arm/mach-tegra/common-t2.c
+++ b/arch/arm/mach-tegra/common-t2.c
@@ -3,7 +3,7 @@
*
* Tegra 2 SoC-specific initialization (memory controller, etc.)
*
- * Copyright (c) 2009-2011, NVIDIA Corporation.
+ * Copyright (c) 2009-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
@@ -177,16 +177,18 @@ out:
return IRQ_HANDLED;
}
-void __init tegra_mc_init(void)
+static int __init tegra_mc_init(void)
{
if (request_irq(INT_MC_GENERAL, tegra_mc_error_isr, 0,
"mc_status", NULL)) {
pr_err("%s: unable to register MC error interrupt\n", __func__);
+ return -EINVAL;
} else {
void __iomem *mc = IO_ADDRESS(TEGRA_MC_BASE);
u32 reg = MC_INT_SECURITY_VIOLATION | MC_INT_INVALID_GART_PAGE |
MC_INT_DECERR_EMEM_OTHERS;
writel(reg, mc + MC_INT_MASK);
}
+ return 0;
}
arch_initcall(tegra_mc_init);
diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c
index 2117b3de64e0..e4e22f813171 100644
--- a/arch/arm/mach-tegra/common.c
+++ b/arch/arm/mach-tegra/common.c
@@ -28,6 +28,7 @@
#include <linux/memblock.h>
#include <linux/bitops.h>
#include <linux/sched.h>
+#include <linux/cpufreq.h>
#include <asm/hardware/cache-l2x0.h>
#include <asm/system.h>
@@ -345,6 +346,7 @@ void tegra_init_cache(bool init)
writel(0x770, p + L2X0_DATA_LATENCY_CTRL);
#endif
#endif
+ writel(0x3, p + L2X0_POWER_CTRL);
aux_ctrl = readl(p + L2X0_CACHE_TYPE);
aux_ctrl = (aux_ctrl & 0x700) << (17-8);
aux_ctrl |= 0x7C000001;
@@ -998,118 +1000,77 @@ void __init tegra_release_bootloader_fb(void)
}
#ifdef CONFIG_TEGRA_CONVSERVATIVE_GOV_ON_EARLYSUPSEND
-static char cpufreq_gov_default[32];
-static char *cpufreq_gov_conservative = "conservative";
-static char *cpufreq_sysfs_place_holder="/sys/devices/system/cpu/cpu%i/cpufreq/scaling_governor";
-static char *cpufreq_gov_conservative_param="/sys/devices/system/cpu/cpufreq/conservative/%s";
+char cpufreq_default_gov[CONFIG_NR_CPUS][MAX_GOV_NAME_LEN];
+char *cpufreq_conservative_gov = "conservative";
-static void cpufreq_set_governor(char *governor)
+void cpufreq_store_default_gov(void)
{
- struct file *scaling_gov = NULL;
- mm_segment_t old_fs;
- char buf[128];
- int i = 0;
- loff_t offset = 0;
+ unsigned int cpu = 0;
+ struct cpufreq_policy *policy;
- if (governor == NULL)
- return;
-
- /* change to KERNEL_DS address limit */
- old_fs = get_fs();
- set_fs(KERNEL_DS);
#ifndef CONFIG_TEGRA_AUTO_HOTPLUG
- for_each_online_cpu(i)
+ for_each_online_cpu(cpu)
#endif
{
- sprintf(buf, cpufreq_sysfs_place_holder, i);
- scaling_gov = filp_open(buf, O_RDWR, 0);
- if (scaling_gov != NULL) {
- if (scaling_gov->f_op != NULL &&
- scaling_gov->f_op->write != NULL)
- scaling_gov->f_op->write(scaling_gov,
- governor,
- strlen(governor),
- &offset);
- else
- pr_err("f_op might be null\n");
-
- filp_close(scaling_gov, NULL);
+ policy = cpufreq_cpu_get(cpu);
+ if (policy && policy->governor) {
+ sprintf(cpufreq_default_gov[cpu], "%s",
+ policy->governor->name);
+ cpufreq_cpu_put(policy);
} else {
- pr_err("%s. Can't open %s\n", __func__, buf);
+ /* No policy or no gov set for this
+ * online cpu. If we are here, require
+ * serious debugging hence setting
+ * as pr_error.
+ */
+ pr_err("No gov or No policy for online cpu:%d,"
+ , cpu);
}
}
- set_fs(old_fs);
}
-void cpufreq_save_default_governor(void)
+void cpufreq_change_gov(char *target_gov)
{
- struct file *scaling_gov = NULL;
- mm_segment_t old_fs;
- char buf[128];
- loff_t offset = 0;
-
- /* change to KERNEL_DS address limit */
- old_fs = get_fs();
- set_fs(KERNEL_DS);
-
- buf[127] = 0;
- sprintf(buf, cpufreq_sysfs_place_holder,0);
- scaling_gov = filp_open(buf, O_RDONLY, 0);
- if (scaling_gov != NULL) {
- if (scaling_gov->f_op != NULL &&
- scaling_gov->f_op->read != NULL)
- scaling_gov->f_op->read(scaling_gov,
- cpufreq_gov_default,
- 32,
- &offset);
- else
- pr_err("f_op might be null\n");
+ int ret = -EINVAL;
+ unsigned int cpu = 0;
- filp_close(scaling_gov, NULL);
- } else {
- pr_err("%s. Can't open %s\n", __func__, buf);
+#ifndef CONFIG_TEGRA_AUTO_HOTPLUG
+ for_each_online_cpu(cpu)
+#endif
+ {
+ ret = cpufreq_set_gov(target_gov, cpu);
+ if (ret < 0)
+ /* Unable to set gov for the online cpu.
+ * If it happens, needs to debug.
+ */
+ pr_info("Unable to set gov:%s for online cpu:%d,"
+ , cpufreq_default_gov[cpu]
+ , cpu);
}
- set_fs(old_fs);
}
-void cpufreq_restore_default_governor(void)
+void cpufreq_restore_default_gov(void)
{
- cpufreq_set_governor(cpufreq_gov_default);
-}
+ int ret = -EINVAL;
+ unsigned int cpu = 0;
-void cpufreq_set_conservative_governor_param(char *name, int value)
-{
- struct file *gov_param = NULL;
- mm_segment_t old_fs;
- static char buf[128], param_value[8];
- loff_t offset = 0;
-
- /* change to KERNEL_DS address limit */
- old_fs = get_fs();
- set_fs(KERNEL_DS);
-
- sprintf(param_value, "%d", value);
- sprintf(buf, cpufreq_gov_conservative_param, name);
- gov_param = filp_open(buf, O_RDWR, 0);
- if (gov_param != NULL) {
- if (gov_param->f_op != NULL &&
- gov_param->f_op->write != NULL)
- gov_param->f_op->write(gov_param,
- param_value,
- strlen(param_value),
- &offset);
- else
- pr_err("f_op might be null\n");
-
- filp_close(gov_param, NULL);
- } else {
- pr_err("%s. Can't open %s\n", __func__, buf);
+#ifndef CONFIG_TEGRA_AUTO_HOTPLUG
+ for_each_online_cpu(cpu)
+#endif
+ {
+ if (&cpufreq_default_gov[cpu] &&
+ strlen((const char *)&cpufreq_default_gov[cpu])) {
+ ret = cpufreq_set_gov(cpufreq_default_gov[cpu], cpu);
+ if (ret < 0)
+ /* Unable to restore gov for the cpu as
+ * It was online on suspend and becomes
+ * offline on resume.
+ */
+ pr_info("Unable to restore gov:%s for cpu:%d,"
+ , cpufreq_default_gov[cpu]
+ , cpu);
+ }
+ cpufreq_default_gov[cpu][0] = '\0';
}
- set_fs(old_fs);
-}
-
-void cpufreq_set_conservative_governor(void)
-{
- cpufreq_set_governor(cpufreq_gov_conservative);
}
#endif /* CONFIG_TEGRA_CONVSERVATIVE_GOV_ON_EARLYSUPSEND */
diff --git a/arch/arm/mach-tegra/cpu-tegra.c b/arch/arm/mach-tegra/cpu-tegra.c
index d35c18e533d9..9bed9270b412 100644
--- a/arch/arm/mach-tegra/cpu-tegra.c
+++ b/arch/arm/mach-tegra/cpu-tegra.c
@@ -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, true);
+ tegra_cpu_dvfs_alter(edp_thermal_index, &edp_cpumask, true);
if (target_cpu_speed[0]) {
edp_update_limit();
tegra_cpu_set_speed_cap(NULL);
}
- tegra_cpu_dvfs_alter(edp_thermal_index, false);
+ tegra_cpu_dvfs_alter(edp_thermal_index, &edp_cpumask, false);
mutex_unlock(&tegra_cpu_lock);
return ret;
@@ -321,6 +321,7 @@ 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);
@@ -335,13 +336,16 @@ static int tegra_cpu_edp_notify(
printk(KERN_DEBUG "tegra CPU:%sforce EDP limit %u kHz"
"\n", ret ? " failed to " : " ", new_speed);
}
+ tegra_cpu_dvfs_alter(edp_thermal_index, &edp_cpumask, false);
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);
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;
}
@@ -431,9 +435,6 @@ static int __init tegra_cpu_debug_init(void)
if (!cpu_tegra_debugfs_root)
return -ENOMEM;
- if (tegra_throttle_debug_init(cpu_tegra_debugfs_root))
- goto err_out;
-
if (tegra_edp_debug_init(cpu_tegra_debugfs_root))
goto err_out;
@@ -469,7 +470,7 @@ unsigned int tegra_getspeed(unsigned int cpu)
return rate;
}
-static int tegra_update_cpu_speed(unsigned long rate)
+int tegra_update_cpu_speed(unsigned long rate)
{
int ret = 0;
struct cpufreq_freqs freqs;
diff --git a/arch/arm/mach-tegra/cpu-tegra.h b/arch/arm/mach-tegra/cpu-tegra.h
index 2bba460514f3..0dda294ea2cc 100644
--- a/arch/arm/mach-tegra/cpu-tegra.h
+++ b/arch/arm/mach-tegra/cpu-tegra.h
@@ -22,6 +22,7 @@
#define __MACH_TEGRA_CPU_TEGRA_H
unsigned int tegra_getspeed(unsigned int cpu);
+int tegra_update_cpu_speed(unsigned long rate);
int tegra_cpu_set_speed_cap(unsigned int *speed_cap);
unsigned int tegra_count_slow_cpus(unsigned long speed_limit);
unsigned int tegra_get_slowest_cpu_n(void);
diff --git a/arch/arm/mach-tegra/cpu-tegra3.c b/arch/arm/mach-tegra/cpu-tegra3.c
index b6579b6b5427..051381297f6f 100644
--- a/arch/arm/mach-tegra/cpu-tegra3.c
+++ b/arch/arm/mach-tegra/cpu-tegra3.c
@@ -41,7 +41,7 @@
#define INITIAL_STATE TEGRA_HP_DISABLED
#define UP2G0_DELAY_MS 70
#define UP2Gn_DELAY_MS 100
-#define DOWN_DELAY_MS 2000
+#define DOWN_DELAY_MS 500
static struct mutex *tegra3_cpu_lock;
@@ -66,13 +66,15 @@ module_param(idle_bottom_freq, uint, 0644);
static int mp_overhead = 10;
module_param(mp_overhead, int, 0644);
-static int balance_level = 75;
+static int balance_level = 60;
module_param(balance_level, int, 0644);
static struct clk *cpu_clk;
static struct clk *cpu_g_clk;
static struct clk *cpu_lp_clk;
+static unsigned long last_change_time;
+
static struct {
cputime64_t time_up_total;
u64 last_update;
@@ -186,6 +188,14 @@ enum {
TEGRA_CPU_SPEED_SKEWED,
};
+#define NR_FSHIFT 2
+static unsigned int nr_run_thresholds[] = {
+/* 1, 2, 3, 4 - on-line cpus target */
+ 5, 9, 10, UINT_MAX /* avg run threads * 4 (e.g., 9 = 2.25 threads) */
+};
+static unsigned int nr_run_hysteresis = 2; /* 0.5 thread */
+static unsigned int nr_run_last;
+
static noinline int tegra_cpu_speed_balance(void)
{
unsigned long highest_speed = tegra_cpu_highest_speed();
@@ -194,17 +204,36 @@ static noinline int tegra_cpu_speed_balance(void)
unsigned int nr_cpus = num_online_cpus();
unsigned int max_cpus = pm_qos_request(PM_QOS_MAX_ONLINE_CPUS) ? : 4;
unsigned int min_cpus = pm_qos_request(PM_QOS_MIN_ONLINE_CPUS);
+ unsigned int avg_nr_run = avg_nr_running();
+ unsigned int nr_run;
+
+ /* Evaluate:
+ * - distribution of freq targets for already on-lined CPUs
+ * - average number of runnable threads
+ * - effective MIPS available within EDP frequency limits,
+ * and return:
+ * TEGRA_CPU_SPEED_BALANCED to bring one more CPU core on-line
+ * 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];
+ if (nr_run_last <= nr_run)
+ nr_threshold += nr_run_hysteresis;
+ if (avg_nr_run <= (nr_threshold << (FSHIFT - NR_FSHIFT)))
+ break;
+ }
+ nr_run_last = nr_run;
- /* balanced: freq targets for all CPUs are above 50% of highest speed
- biased: freq target for at least one CPU is below 50% threshold
- skewed: freq targets for at least 2 CPUs are below 25% threshold */
if (((tegra_count_slow_cpus(skewed_speed) >= 2) ||
+ (nr_run < nr_cpus) ||
tegra_cpu_edp_favor_down(nr_cpus, mp_overhead) ||
(highest_speed <= idle_bottom_freq) || (nr_cpus > max_cpus)) &&
(nr_cpus > min_cpus))
return TEGRA_CPU_SPEED_SKEWED;
if (((tegra_count_slow_cpus(balanced_speed) >= 1) ||
+ (nr_run <= nr_cpus) ||
(!tegra_cpu_edp_favor_up(nr_cpus, mp_overhead)) ||
(highest_speed <= idle_bottom_freq) || (nr_cpus == max_cpus)) &&
(nr_cpus >= min_cpus))
@@ -217,6 +246,7 @@ static void tegra_auto_hotplug_work_func(struct work_struct *work)
{
bool up = false;
unsigned int cpu = nr_cpu_ids;
+ unsigned long now = jiffies;
mutex_lock(tegra3_cpu_lock);
@@ -228,23 +258,24 @@ static void tegra_auto_hotplug_work_func(struct work_struct *work)
cpu = tegra_get_slowest_cpu_n();
if (cpu < nr_cpu_ids) {
up = false;
- queue_delayed_work(
- hotplug_wq, &hotplug_work, down_delay);
- hp_stats_update(cpu, false);
- } else if (!is_lp_cluster() && !no_lp) {
+ } else if (!is_lp_cluster() && !no_lp &&
+ !pm_qos_request(PM_QOS_MIN_ONLINE_CPUS) &&
+ ((now - last_change_time) >= down_delay)) {
if(!clk_set_parent(cpu_clk, cpu_lp_clk)) {
hp_stats_update(CONFIG_NR_CPUS, true);
hp_stats_update(0, false);
/* catch-up with governor target speed */
tegra_cpu_set_speed_cap(NULL);
- } else
- queue_delayed_work(
- hotplug_wq, &hotplug_work, down_delay);
+ break;
+ }
}
+ queue_delayed_work(
+ hotplug_wq, &hotplug_work, up2gn_delay);
break;
case TEGRA_HP_UP:
if (is_lp_cluster() && !no_lp) {
if(!clk_set_parent(cpu_clk, cpu_g_clk)) {
+ last_change_time = now;
hp_stats_update(CONFIG_NR_CPUS, false);
hp_stats_update(0, true);
/* catch-up with governor target speed */
@@ -255,18 +286,14 @@ static void tegra_auto_hotplug_work_func(struct work_struct *work)
/* cpu speed is up and balanced - one more on-line */
case TEGRA_CPU_SPEED_BALANCED:
cpu = cpumask_next_zero(0, cpu_online_mask);
- if (cpu < nr_cpu_ids) {
+ if (cpu < nr_cpu_ids)
up = true;
- hp_stats_update(cpu, true);
- }
break;
/* cpu speed is up, but skewed - remove one core */
case TEGRA_CPU_SPEED_SKEWED:
cpu = tegra_get_slowest_cpu_n();
- if (cpu < nr_cpu_ids) {
+ if (cpu < nr_cpu_ids)
up = false;
- hp_stats_update(cpu, false);
- }
break;
/* cpu speed is up, but under-utilized - do nothing */
case TEGRA_CPU_SPEED_BIASED:
@@ -281,6 +308,14 @@ static void tegra_auto_hotplug_work_func(struct work_struct *work)
pr_err("%s: invalid tegra hotplug state %d\n",
__func__, hp_state);
}
+
+ if (!up && ((now - last_change_time) < down_delay))
+ cpu = nr_cpu_ids;
+
+ if (cpu < nr_cpu_ids) {
+ last_change_time = now;
+ hp_stats_update(cpu, up);
+ }
mutex_unlock(tegra3_cpu_lock);
if (cpu < nr_cpu_ids) {
@@ -295,8 +330,14 @@ static int min_cpus_notify(struct notifier_block *nb, unsigned long n, void *p)
{
mutex_lock(tegra3_cpu_lock);
- if ((n >= 2) && is_lp_cluster()) {
+ if ((n >= 1) && is_lp_cluster()) {
+ /* make sure cpu rate is within g-mode range before switching */
+ unsigned int speed = max((unsigned long)tegra_getspeed(0),
+ clk_get_min_rate(cpu_g_clk) / 1000);
+ tegra_update_cpu_speed(speed);
+
if (!clk_set_parent(cpu_clk, cpu_g_clk)) {
+ last_change_time = jiffies;
hp_stats_update(CONFIG_NR_CPUS, false);
hp_stats_update(0, true);
}
@@ -318,7 +359,10 @@ void tegra_auto_hotplug_governor(unsigned int cpu_freq, bool suspend)
if (!is_g_cluster_present())
return;
- if (suspend && (hp_state != TEGRA_HP_DISABLED)) {
+ if (hp_state == TEGRA_HP_DISABLED)
+ return;
+
+ if (suspend) {
hp_state = TEGRA_HP_IDLE;
/* Switch to G-mode if suspend rate is high enough */
@@ -351,8 +395,6 @@ void tegra_auto_hotplug_governor(unsigned int cpu_freq, bool suspend)
}
switch (hp_state) {
- case TEGRA_HP_DISABLED:
- break;
case TEGRA_HP_IDLE:
if (cpu_freq > top_freq) {
hp_state = TEGRA_HP_UP;
@@ -361,7 +403,7 @@ void tegra_auto_hotplug_governor(unsigned int cpu_freq, bool suspend)
} else if (cpu_freq <= bottom_freq) {
hp_state = TEGRA_HP_DOWN;
queue_delayed_work(
- hotplug_wq, &hotplug_work, down_delay);
+ hotplug_wq, &hotplug_work, up_delay);
}
break;
case TEGRA_HP_DOWN:
@@ -377,7 +419,7 @@ void tegra_auto_hotplug_governor(unsigned int cpu_freq, bool suspend)
if (cpu_freq <= bottom_freq) {
hp_state = TEGRA_HP_DOWN;
queue_delayed_work(
- hotplug_wq, &hotplug_work, down_delay);
+ hotplug_wq, &hotplug_work, up_delay);
} else if (cpu_freq <= top_freq) {
hp_state = TEGRA_HP_IDLE;
}
diff --git a/arch/arm/mach-tegra/cpuquiet.c b/arch/arm/mach-tegra/cpuquiet.c
new file mode 100644
index 000000000000..26adce230920
--- /dev/null
+++ b/arch/arm/mach-tegra/cpuquiet.c
@@ -0,0 +1,433 @@
+/*
+ * arch/arm/mach-tegra/cpuquiet.c
+ *
+ * Cpuquiet driver for Tegra3 CPUs
+ *
+ * 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.
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/cpufreq.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/cpu.h>
+#include <linux/clk.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/pm_qos_params.h>
+#include <linux/cpuquiet.h>
+
+#include "pm.h"
+#include "cpu-tegra.h"
+#include "clock.h"
+
+#define INITIAL_STATE TEGRA_CPQ_IDLE
+#define UP_DELAY_MS 70
+#define DOWN_DELAY_MS 2000
+
+static struct mutex *tegra3_cpu_lock;
+static struct workqueue_struct *cpuquiet_wq;
+static struct delayed_work cpuquiet_work;
+static struct work_struct minmax_work;
+
+static struct kobject *tegra_auto_sysfs_kobject;
+
+static bool no_lp;
+static bool enable;
+static unsigned long up_delay;
+static unsigned long down_delay;
+static int mp_overhead = 10;
+static unsigned int idle_top_freq;
+static unsigned int idle_bottom_freq;
+
+static struct clk *cpu_clk;
+static struct clk *cpu_g_clk;
+static struct clk *cpu_lp_clk;
+
+static struct cpumask cr_online_requests;
+
+enum {
+ TEGRA_CPQ_DISABLED = 0,
+ TEGRA_CPQ_IDLE,
+ TEGRA_CPQ_SWITCH_TO_LP,
+ TEGRA_CPQ_SWITCH_TO_G,
+};
+
+static int cpq_state;
+
+static int update_core_config(unsigned int cpunumber, bool up)
+{
+ int ret = -EINVAL;
+ unsigned int nr_cpus = num_online_cpus();
+ 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 || cpunumber >= nr_cpu_ids)
+ return ret;
+
+ if (up) {
+ if(is_lp_cluster()) {
+ cpumask_set_cpu(cpunumber, &cr_online_requests);
+ ret = -EBUSY;
+ } else {
+ if (tegra_cpu_edp_favor_up(nr_cpus, mp_overhead) &&
+ nr_cpus < max_cpus)
+ ret = cpu_up(cpunumber);
+ }
+ } else {
+ if (is_lp_cluster()) {
+ ret = -EBUSY;
+ } else {
+ if (nr_cpus > min_cpus)
+ ret = cpu_down(cpunumber);
+ }
+ }
+
+ return ret;
+}
+
+static int tegra_quiesence_cpu(unsigned int cpunumber)
+{
+ return update_core_config(cpunumber, false);
+}
+
+static int tegra_wake_cpu(unsigned int cpunumber)
+{
+ return update_core_config(cpunumber, true);
+}
+
+static struct cpuquiet_driver tegra_cpuquiet_driver = {
+ .name = "tegra",
+ .quiesence_cpu = tegra_quiesence_cpu,
+ .wake_cpu = tegra_wake_cpu,
+};
+
+static void apply_core_config(void)
+{
+ unsigned int cpu;
+
+ if (is_lp_cluster() || cpq_state == TEGRA_CPQ_DISABLED)
+ return;
+
+ for_each_cpu_mask(cpu, cr_online_requests) {
+ if (cpu < nr_cpu_ids && !cpu_online(cpu))
+ if (!tegra_wake_cpu(cpu))
+ cpumask_clear_cpu(cpu, &cr_online_requests);
+ }
+}
+
+static void tegra_cpuquiet_work_func(struct work_struct *work)
+{
+ bool update_cr_config = false;
+
+ mutex_lock(tegra3_cpu_lock);
+
+ switch(cpq_state) {
+ case TEGRA_CPQ_DISABLED:
+ case TEGRA_CPQ_IDLE:
+ break;
+ case TEGRA_CPQ_SWITCH_TO_G:
+ if (is_lp_cluster()) {
+ if(!clk_set_parent(cpu_clk, cpu_g_clk)) {
+ /*catch-up with governor target speed */
+ tegra_cpu_set_speed_cap(NULL);
+ /* process pending core requests*/
+ update_cr_config = true;
+ }
+ }
+ break;
+ case TEGRA_CPQ_SWITCH_TO_LP:
+ if (!is_lp_cluster() && !no_lp &&
+ !pm_qos_request(PM_QOS_MIN_ONLINE_CPUS)
+ && num_online_cpus() == 1) {
+ if (!clk_set_parent(cpu_clk, cpu_lp_clk)) {
+ /*catch-up with governor target speed*/
+ tegra_cpu_set_speed_cap(NULL);
+ }
+ }
+ break;
+ default:
+ pr_err("%s: invalid tegra hotplug state %d\n",
+ __func__, cpq_state);
+ }
+
+ mutex_unlock(tegra3_cpu_lock);
+
+ if (update_cr_config)
+ apply_core_config();
+}
+
+static void min_max_constraints_workfunc(struct work_struct *work)
+{
+ int count = -1;
+ bool up = false;
+ unsigned int cpu;
+
+ int nr_cpus = num_online_cpus();
+ int max_cpus = pm_qos_request(PM_QOS_MAX_ONLINE_CPUS) ? : 4;
+ int min_cpus = pm_qos_request(PM_QOS_MIN_ONLINE_CPUS);
+
+ if (is_lp_cluster())
+ return;
+
+ if (nr_cpus < min_cpus) {
+ up = true;
+ count = min_cpus - nr_cpus;
+ } else if (nr_cpus > max_cpus && max_cpus >= min_cpus) {
+ count = nr_cpus - max_cpus;
+ }
+
+ for (;count > 0; count--) {
+ if (up) {
+ cpu = cpumask_next_zero(0, cpu_online_mask);
+ if (cpu < nr_cpu_ids)
+ cpu_up(cpu);
+ else
+ break;
+ } else {
+ cpu = cpumask_next(0, cpu_online_mask);
+ if (cpu < nr_cpu_ids)
+ cpu_down(cpu);
+ else
+ break;
+ }
+ }
+}
+
+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()) {
+ /* 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);
+ }
+
+ tegra_cpu_set_speed_cap(NULL);
+ mutex_unlock(tegra3_cpu_lock);
+
+ schedule_work(&minmax_work);
+
+ return NOTIFY_OK;
+}
+
+static int max_cpus_notify(struct notifier_block *nb, unsigned long n, void *p)
+{
+ if (n < num_online_cpus())
+ schedule_work(&minmax_work);
+
+ return NOTIFY_OK;
+}
+
+void tegra_auto_hotplug_governor(unsigned int cpu_freq, bool suspend)
+{
+ if (!is_g_cluster_present())
+ return;
+
+ if (cpq_state == TEGRA_CPQ_DISABLED)
+ return;
+
+ if (suspend) {
+ cpq_state = TEGRA_CPQ_IDLE;
+
+ /* 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);
+ }
+ return;
+ }
+
+ if (is_lp_cluster() && pm_qos_request(PM_QOS_MIN_ONLINE_CPUS) >= 2) {
+ if (cpq_state != TEGRA_CPQ_SWITCH_TO_G) {
+ /* Force switch */
+ cpq_state = TEGRA_CPQ_SWITCH_TO_G;
+ queue_delayed_work(
+ cpuquiet_wq, &cpuquiet_work, up_delay);
+ }
+ return;
+ }
+
+ if (is_lp_cluster() && (cpu_freq >= idle_top_freq || no_lp)) {
+ cpq_state = TEGRA_CPQ_SWITCH_TO_G;
+ queue_delayed_work(cpuquiet_wq, &cpuquiet_work, up_delay);
+ } else if (!is_lp_cluster() && !no_lp &&
+ cpu_freq <= idle_bottom_freq) {
+ cpq_state = TEGRA_CPQ_SWITCH_TO_LP;
+ queue_delayed_work(cpuquiet_wq, &cpuquiet_work, down_delay);
+ } else {
+ cpq_state = TEGRA_CPQ_IDLE;
+ }
+}
+
+static struct notifier_block min_cpus_notifier = {
+ .notifier_call = min_cpus_notify,
+};
+
+static struct notifier_block max_cpus_notifier = {
+ .notifier_call = max_cpus_notify,
+};
+
+static void delay_callback(struct cpuquiet_attribute *attr)
+{
+ unsigned long val;
+
+ if (attr) {
+ val = (*((unsigned long *)(attr->param)));
+ (*((unsigned long *)(attr->param))) = msecs_to_jiffies(val);
+ }
+}
+
+static void enable_callback(struct cpuquiet_attribute *attr)
+{
+ mutex_lock(tegra3_cpu_lock);
+
+ if (!enable && cpq_state != TEGRA_CPQ_DISABLED) {
+ cpq_state = TEGRA_CPQ_DISABLED;
+ mutex_unlock(tegra3_cpu_lock);
+ cancel_delayed_work_sync(&cpuquiet_work);
+ pr_info("Tegra cpuquiet clusterswitch disabled\n");
+ 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);
+ }
+
+ mutex_unlock(tegra3_cpu_lock);
+}
+
+CPQ_BASIC_ATTRIBUTE(no_lp, 0644, bool);
+CPQ_BASIC_ATTRIBUTE(idle_top_freq, 0644, uint);
+CPQ_BASIC_ATTRIBUTE(idle_bottom_freq, 0644, uint);
+CPQ_BASIC_ATTRIBUTE(mp_overhead, 0644, int);
+CPQ_ATTRIBUTE(up_delay, 0644, ulong, delay_callback);
+CPQ_ATTRIBUTE(down_delay, 0644, ulong, delay_callback);
+CPQ_ATTRIBUTE(enable, 0644, bool, enable_callback);
+
+static struct attribute *tegra_auto_attributes[] = {
+ &no_lp_attr.attr,
+ &up_delay_attr.attr,
+ &down_delay_attr.attr,
+ &idle_top_freq_attr.attr,
+ &idle_bottom_freq_attr.attr,
+ &mp_overhead_attr.attr,
+ &enable_attr.attr,
+ NULL,
+};
+
+static const struct sysfs_ops tegra_auto_sysfs_ops = {
+ .show = cpuquiet_auto_sysfs_show,
+ .store = cpuquiet_auto_sysfs_store,
+};
+
+static struct kobj_type ktype_sysfs = {
+ .sysfs_ops = &tegra_auto_sysfs_ops,
+ .default_attrs = tegra_auto_attributes,
+};
+
+static int tegra_auto_sysfs(void)
+{
+ int err;
+
+ tegra_auto_sysfs_kobject = kzalloc(sizeof(*tegra_auto_sysfs_kobject),
+ GFP_KERNEL);
+
+ if (!tegra_auto_sysfs_kobject)
+ return -ENOMEM;
+
+ err = cpuquiet_kobject_init(tegra_auto_sysfs_kobject, &ktype_sysfs,
+ "tegra_cpuquiet");
+
+ if (err)
+ kfree(tegra_auto_sysfs_kobject);
+
+ return err;
+}
+
+int tegra_auto_hotplug_init(struct mutex *cpu_lock)
+{
+ int err;
+
+ cpu_clk = clk_get_sys(NULL, "cpu");
+ cpu_g_clk = clk_get_sys(NULL, "cpu_g");
+ cpu_lp_clk = clk_get_sys(NULL, "cpu_lp");
+
+ if (IS_ERR(cpu_clk) || IS_ERR(cpu_g_clk) || IS_ERR(cpu_lp_clk))
+ return -ENOENT;
+
+ /*
+ * Not bound to the issuer CPU (=> high-priority), has rescue worker
+ * task, single-threaded, freezable.
+ */
+ cpuquiet_wq = alloc_workqueue(
+ "cpuquiet", WQ_UNBOUND | WQ_RESCUER | WQ_FREEZABLE, 1);
+
+ if (!cpuquiet_wq)
+ return -ENOMEM;
+
+ INIT_DELAYED_WORK(&cpuquiet_work, tegra_cpuquiet_work_func);
+ INIT_WORK(&minmax_work, min_max_constraints_workfunc);
+
+ idle_top_freq = clk_get_max_rate(cpu_lp_clk) / 1000;
+ idle_bottom_freq = clk_get_min_rate(cpu_g_clk) / 1000;
+
+ up_delay = msecs_to_jiffies(UP_DELAY_MS);
+ down_delay = msecs_to_jiffies(DOWN_DELAY_MS);
+ cpumask_clear(&cr_online_requests);
+ tegra3_cpu_lock = cpu_lock;
+
+ cpq_state = INITIAL_STATE;
+ enable = cpq_state == TEGRA_CPQ_DISABLED ? false : true;
+
+
+ pr_info("Tegra cpuquiet initialized: %s\n",
+ (cpq_state == TEGRA_CPQ_DISABLED) ? "disabled" : "enabled");
+
+ if (pm_qos_add_notifier(PM_QOS_MIN_ONLINE_CPUS, &min_cpus_notifier))
+ pr_err("%s: Failed to register min cpus PM QoS notifier\n",
+ __func__);
+ if (pm_qos_add_notifier(PM_QOS_MAX_ONLINE_CPUS, &max_cpus_notifier))
+ pr_err("%s: Failed to register max cpus PM QoS notifier\n",
+ __func__);
+
+ err = cpuquiet_register_driver(&tegra_cpuquiet_driver);
+ if (err) {
+ destroy_workqueue(cpuquiet_wq);
+ return err;
+ }
+
+ err = tegra_auto_sysfs();
+ if (err) {
+ cpuquiet_unregister_driver(&tegra_cpuquiet_driver);
+ destroy_workqueue(cpuquiet_wq);
+ }
+
+ return err;
+}
+
+void tegra_auto_hotplug_exit(void)
+{
+ destroy_workqueue(cpuquiet_wq);
+ cpuquiet_unregister_driver(&tegra_cpuquiet_driver);
+ kobject_put(tegra_auto_sysfs_kobject);
+}
diff --git a/arch/arm/mach-tegra/devices.c b/arch/arm/mach-tegra/devices.c
index 079d18e2339b..79f3ccc57f92 100644
--- a/arch/arm/mach-tegra/devices.c
+++ b/arch/arm/mach-tegra/devices.c
@@ -584,28 +584,6 @@ static struct resource tegra_usb3_resources[] = {
},
};
-static struct tegra_ulpi_config tegra_ehci2_ulpi_phy_config = {
- /* All existing boards use GPIO PV0 for phy reset */
- .reset_gpio = TEGRA_GPIO_PV0,
- .clk = "cdev2",
-};
-
-static struct tegra_ehci_platform_data tegra_ehci1_pdata = {
- .operating_mode = TEGRA_USB_OTG,
- .power_down_on_bus_suspend = 1,
-};
-
-static struct tegra_ehci_platform_data tegra_ehci2_pdata = {
- .phy_config = &tegra_ehci2_ulpi_phy_config,
- .operating_mode = TEGRA_USB_HOST,
- .power_down_on_bus_suspend = 1,
-};
-
-static struct tegra_ehci_platform_data tegra_ehci3_pdata = {
- .operating_mode = TEGRA_USB_HOST,
- .power_down_on_bus_suspend = 1,
-};
-
static u64 tegra_ehci_dmamask = DMA_BIT_MASK(32);
struct platform_device tegra_ehci1_device = {
@@ -614,7 +592,6 @@ struct platform_device tegra_ehci1_device = {
.dev = {
.dma_mask = &tegra_ehci_dmamask,
.coherent_dma_mask = DMA_BIT_MASK(32),
- .platform_data = &tegra_ehci1_pdata,
},
.resource = tegra_usb1_resources,
.num_resources = ARRAY_SIZE(tegra_usb1_resources),
@@ -626,7 +603,6 @@ struct platform_device tegra_ehci2_device = {
.dev = {
.dma_mask = &tegra_ehci_dmamask,
.coherent_dma_mask = DMA_BIT_MASK(32),
- .platform_data = &tegra_ehci2_pdata,
},
.resource = tegra_usb2_resources,
.num_resources = ARRAY_SIZE(tegra_usb2_resources),
@@ -638,7 +614,6 @@ struct platform_device tegra_ehci3_device = {
.dev = {
.dma_mask = &tegra_ehci_dmamask,
.coherent_dma_mask = DMA_BIT_MASK(32),
- .platform_data = &tegra_ehci3_pdata,
},
.resource = tegra_usb3_resources,
.num_resources = ARRAY_SIZE(tegra_usb3_resources),
@@ -1216,6 +1191,11 @@ struct platform_device tegra_pcm_device = {
.id = -1,
};
+struct platform_device tegra_tdm_pcm_device = {
+ .name = "tegra-tdm-pcm-audio",
+ .id = -1,
+};
+
static struct resource w1_resources[] = {
[0] = {
.start = INT_OWR,
@@ -1251,18 +1231,12 @@ static struct resource tegra_udc_resources[] = {
static u64 tegra_udc_dmamask = DMA_BIT_MASK(32);
-static struct fsl_usb2_platform_data tegra_udc_pdata = {
- .operating_mode = FSL_USB2_DR_DEVICE,
- .phy_mode = FSL_USB2_PHY_UTMI,
-};
-
struct platform_device tegra_udc_device = {
- .name = "fsl-tegra-udc",
- .id = -1,
+ .name = "tegra-udc",
+ .id = 0,
.dev = {
.dma_mask = &tegra_udc_dmamask,
.coherent_dma_mask = DMA_BIT_MASK(32),
- .platform_data = &tegra_udc_pdata,
},
.resource = tegra_udc_resources,
.num_resources = ARRAY_SIZE(tegra_udc_resources),
@@ -1424,16 +1398,23 @@ static struct resource tegra_wdt_resources[] = {
.flags = IORESOURCE_IRQ,
},
};
+
+struct platform_device tegra_wdt_device = {
+ .name = "tegra_wdt",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(tegra_wdt_resources),
+ .resource = tegra_wdt_resources,
+};
#else
-static struct resource tegra_wdt_resources[] = {
+static struct resource tegra_wdt0_resources[] = {
[0] = {
.start = TEGRA_WDT0_BASE,
.end = TEGRA_WDT0_BASE + TEGRA_WDT0_SIZE - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = TEGRA_TMR10_BASE,
- .end = TEGRA_TMR10_BASE + TEGRA_TMR10_SIZE - 1,
+ .start = TEGRA_TMR7_BASE,
+ .end = TEGRA_TMR7_BASE + TEGRA_TMR7_SIZE - 1,
.flags = IORESOURCE_MEM,
},
[2] = {
@@ -1441,16 +1422,64 @@ static struct resource tegra_wdt_resources[] = {
.end = INT_WDT_CPU,
.flags = IORESOURCE_IRQ,
},
-};
+#ifdef CONFIG_TEGRA_FIQ_DEBUGGER
+ [3] = {
+ .start = TEGRA_QUATERNARY_ICTLR_BASE,
+ .end = TEGRA_QUATERNARY_ICTLR_BASE + \
+ TEGRA_QUATERNARY_ICTLR_SIZE -1,
+ .flags = IORESOURCE_MEM,
+ },
#endif
+};
-struct platform_device tegra_wdt_device = {
+static struct resource tegra_wdt1_resources[] = {
+ [0] = {
+ .start = TEGRA_WDT1_BASE,
+ .end = TEGRA_WDT1_BASE + TEGRA_WDT1_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = TEGRA_TMR8_BASE,
+ .end = TEGRA_TMR8_BASE + TEGRA_TMR8_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct resource tegra_wdt2_resources[] = {
+ [0] = {
+ .start = TEGRA_WDT2_BASE,
+ .end = TEGRA_WDT2_BASE + TEGRA_WDT2_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = TEGRA_TMR9_BASE,
+ .end = TEGRA_TMR9_BASE + TEGRA_TMR9_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+struct platform_device tegra_wdt0_device = {
.name = "tegra_wdt",
- .id = -1,
- .num_resources = ARRAY_SIZE(tegra_wdt_resources),
- .resource = tegra_wdt_resources,
+ .id = 0,
+ .num_resources = ARRAY_SIZE(tegra_wdt0_resources),
+ .resource = tegra_wdt0_resources,
+};
+
+struct platform_device tegra_wdt1_device = {
+ .name = "tegra_wdt",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(tegra_wdt1_resources),
+ .resource = tegra_wdt1_resources,
};
+struct platform_device tegra_wdt2_device = {
+ .name = "tegra_wdt",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(tegra_wdt2_resources),
+ .resource = tegra_wdt2_resources,
+};
+#endif
+
static struct resource tegra_pwfm0_resource = {
.start = TEGRA_PWFM0_BASE,
.end = TEGRA_PWFM0_BASE + TEGRA_PWFM0_SIZE - 1,
@@ -1699,6 +1728,28 @@ struct platform_device tegra_nvmap_device = {
.id = -1,
};
+#ifndef CONFIG_ARCH_TEGRA_2x_SOC
+static struct resource tegra_cec_resources[] = {
+ [0] = {
+ .start = TEGRA_CEC_BASE,
+ .end = TEGRA_CEC_BASE + TEGRA_CEC_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = INT_CEC,
+ .end = INT_CEC,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device tegra_cec_device = {
+ .name = "tegra_cec",
+ .id = -1,
+ .resource = tegra_cec_resources,
+ .num_resources = ARRAY_SIZE(tegra_cec_resources),
+};
+#endif
+
void __init tegra_init_debug_uart_rate(void)
{
unsigned int uartclk;
diff --git a/arch/arm/mach-tegra/devices.h b/arch/arm/mach-tegra/devices.h
index 8b413d45d9b9..c5cf7b708ec4 100644
--- a/arch/arm/mach-tegra/devices.h
+++ b/arch/arm/mach-tegra/devices.h
@@ -69,6 +69,7 @@ extern struct platform_device spdif_dit_device;
extern struct platform_device bluetooth_dit_device;
extern struct platform_device baseband_dit_device;
extern struct platform_device tegra_pcm_device;
+extern struct platform_device tegra_tdm_pcm_device;
extern struct platform_device tegra_w1_device;
extern struct platform_device tegra_udc_device;
extern struct platform_device tegra_ehci1_device;
@@ -97,7 +98,13 @@ extern struct platform_device tegra_gart_device;
#else
extern struct platform_device tegra_smmu_device;
#endif
+#if defined(CONFIG_ARCH_TEGRA_2x_SOC)
extern struct platform_device tegra_wdt_device;
+#else
+extern struct platform_device tegra_wdt0_device;
+extern struct platform_device tegra_wdt1_device;
+extern struct platform_device tegra_wdt2_device;
+#endif
extern struct platform_device tegra_pwfm0_device;
extern struct platform_device tegra_pwfm1_device;
extern struct platform_device tegra_pwfm2_device;
@@ -109,7 +116,6 @@ extern struct platform_device tegra_uartc_device;
extern struct platform_device tegra_uartd_device;
extern struct platform_device tegra_uarte_device;
extern struct platform_device tegra_avp_device;
-extern struct nvhost_device tegra_grhost_device;
extern struct nvhost_device nvavp_device;
extern struct platform_device tegra_aes_device;
#if !defined(CONFIG_ARCH_TEGRA_2x_SOC)
@@ -127,6 +133,9 @@ extern struct platform_device debug_uarte_device;
extern struct nvhost_device tegra_disp1_device;
extern struct platform_device tegra_nvmap_device;
+#ifndef CONFIG_ARCH_TEGRA_2x_SOC
+extern struct platform_device tegra_cec_device;
+#endif
void __init tegra_init_debug_uart_rate(void);
diff --git a/arch/arm/mach-tegra/dvfs.c b/arch/arm/mach-tegra/dvfs.c
index 8723e6fa60df..cb33e3db862f 100644
--- a/arch/arm/mach-tegra/dvfs.c
+++ b/arch/arm/mach-tegra/dvfs.c
@@ -322,8 +322,7 @@ static int dvfs_rail_connect_to_regulator(struct dvfs_rail *rail)
static inline unsigned long *dvfs_get_freqs(struct dvfs *d)
{
- return (d->alt_freqs_state == ALT_FREQS_ENABLED) ?
- &d->alt_freqs[0] : &d->freqs[0];
+ return d->alt_freqs ? : &d->freqs[0];
}
static int
@@ -367,26 +366,16 @@ __tegra_dvfs_set_rate(struct dvfs *d, unsigned long rate)
return ret;
}
-static inline int dvfs_alt_freqs_set(struct dvfs *d, bool enable)
+int tegra_dvfs_alt_freqs_set(struct dvfs *d, unsigned long *alt_freqs)
{
- if (d->alt_freqs_state == ALT_FREQS_NOT_SUPPORTED)
- return -ENOSYS;
-
- d->alt_freqs_state = enable ? ALT_FREQS_ENABLED : ALT_FREQS_DISABLED;
- return 0;
-}
-
-int tegra_dvfs_alt_freqs_set(struct dvfs *d, bool enable)
-{
- int ret;
- enum dvfs_alt_freqs old_state;
+ int ret = 0;
mutex_lock(&dvfs_lock);
- old_state = d->alt_freqs_state;
- ret = dvfs_alt_freqs_set(d, enable);
- if (!ret && (old_state != d->alt_freqs_state))
+ if (d->alt_freqs != alt_freqs) {
+ d->alt_freqs = alt_freqs;
ret = __tegra_dvfs_set_rate(d, d->cur_rate);
+ }
mutex_unlock(&dvfs_lock);
return ret;
@@ -407,7 +396,7 @@ int tegra_dvfs_predict_millivolts(struct clk *c, unsigned long rate)
* frequency limits. For now, just fail the call for clock that has
* alternative limits initialized.
*/
- if (c->dvfs->alt_freqs_state != ALT_FREQS_NOT_SUPPORTED)
+ if (c->dvfs->alt_freqs)
return -ENOSYS;
for (i = 0; i < c->dvfs->num_freqs; i++) {
diff --git a/arch/arm/mach-tegra/dvfs.h b/arch/arm/mach-tegra/dvfs.h
index eaecf425fe87..3bdb13690278 100644
--- a/arch/arm/mach-tegra/dvfs.h
+++ b/arch/arm/mach-tegra/dvfs.h
@@ -21,7 +21,7 @@
#ifndef _TEGRA_DVFS_H_
#define _TEGRA_DVFS_H_
-#define MAX_DVFS_FREQS 18
+#define MAX_DVFS_FREQS 20
#define DVFS_RAIL_STATS_TOP_BIN 40
struct clk;
@@ -73,12 +73,6 @@ struct dvfs_rail {
struct rail_stats stats;
};
-enum dvfs_alt_freqs {
- ALT_FREQS_NOT_SUPPORTED = 0,
- ALT_FREQS_DISABLED,
- ALT_FREQS_ENABLED,
-};
-
struct dvfs {
/* Used only by tegra2_clock.c */
const char *clk_name;
@@ -88,11 +82,10 @@ struct dvfs {
/* Must be initialized before tegra_dvfs_init */
int freqs_mult;
unsigned long freqs[MAX_DVFS_FREQS];
- unsigned long alt_freqs[MAX_DVFS_FREQS];
+ unsigned long *alt_freqs;
const int *millivolts;
struct dvfs_rail *dvfs_rail;
bool auto_dvfs;
- enum dvfs_alt_freqs alt_freqs_state;
/* Filled in by tegra_dvfs_init */
int max_millivolts;
@@ -124,8 +117,9 @@ struct dvfs_rail *tegra_dvfs_get_rail_by_name(const char *reg_id);
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, bool enable);
-void tegra_cpu_dvfs_alter(int edp_thermal_index, bool before_clk_update);
+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);
#else
static inline void tegra_soc_init_dvfs(void)
{}
@@ -160,10 +154,11 @@ static inline void tegra_dvfs_core_cap_enable(bool enable)
{}
static inline void tegra_dvfs_core_cap_level_set(int level)
{}
-static inline int tegra_dvfs_alt_freqs_set(struct dvfs *d, bool enable)
+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,
- bool before_clk_update)
+static inline void tegra_cpu_dvfs_alter(
+ int edp_thermal_index, const cpumask_t *cpus, bool before_clk_update)
{}
#endif
diff --git a/arch/arm/mach-tegra/headsmp.S b/arch/arm/mach-tegra/headsmp.S
index 4a9f03ffd972..4e28a558cc38 100644
--- a/arch/arm/mach-tegra/headsmp.S
+++ b/arch/arm/mach-tegra/headsmp.S
@@ -83,7 +83,9 @@ ENTRY(tegra_resume)
ldr r1, [r0]
orr r1, r1, #1
#if defined(CONFIG_HAVE_ARM_SCU)
- orr r1, r1, #(1 << 3) @ Enabled SCU speculative line fill.
+ 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]
diff --git a/arch/arm/mach-tegra/include/mach/clk.h b/arch/arm/mach-tegra/include/mach/clk.h
index 0fbbf24d5959..01d322a448d1 100644
--- a/arch/arm/mach-tegra/include/mach/clk.h
+++ b/arch/arm/mach-tegra/include/mach/clk.h
@@ -6,7 +6,7 @@
* Author:
* Erik Gilling <konkers@google.com>
*
- * Copyright (C) 2010-2011 NVIDIA Corporation
+ * Copyright (C) 2010-2012 NVIDIA Corporation
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -47,10 +47,20 @@ static inline int tegra_dvfs_set_rate(struct clk *c, unsigned long rate)
unsigned long clk_get_rate_all_locked(struct clk *c);
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
void tegra_sdmmc_tap_delay(struct clk *c, int delay);
+
+static inline int tegra_emc_enable_eack(void) {
+ return 0;
+}
+
+static inline int tegra_emc_disable_eack(void) {
+ return 0;
+}
#else
static inline void tegra_sdmmc_tap_delay(struct clk *c, int delay)
{
}
+int tegra_emc_enable_eack(void);
+int tegra_emc_disable_eack(void);
#endif
int tegra_dvfs_rail_disable_by_name(const char *reg_id);
int tegra_clk_cfg_ex(struct clk *c, enum tegra_clk_ex_param p, u32 setting);
diff --git a/arch/arm/mach-tegra/include/mach/dc.h b/arch/arm/mach-tegra/include/mach/dc.h
index 3b9b431dea82..97f02ce6e95d 100644
--- a/arch/arm/mach-tegra/include/mach/dc.h
+++ b/arch/arm/mach-tegra/include/mach/dc.h
@@ -128,6 +128,13 @@ struct dsi_phy_timing_ns {
u16 t_tago_ns;
};
+/* Aggressiveness level of DSI suspend. The higher, the more aggressive. */
+#define DSI_NO_SUSPEND 0
+#define DSI_HOST_SUSPEND_LV0 1
+#define DSI_HOST_SUSPEND_LV1 2
+#define DSI_HOST_SUSPEND_LV2 3
+#define DSI_SUSPEND_FULL 4
+
struct tegra_dsi_out {
u8 n_data_lanes; /* required */
u8 pixel_format; /* required */
@@ -140,6 +147,7 @@ struct tegra_dsi_out {
u8 chip_rev;
bool panel_has_frame_buffer; /* required*/
+ bool panel_send_dc_frames;
struct tegra_dsi_cmd *dsi_init_cmd; /* required */
u16 n_init_cmd; /* required */
@@ -157,6 +165,8 @@ struct tegra_dsi_out {
u8 video_clock_mode;
u8 video_burst_mode;
+ u8 suspend_aggr;
+
u16 panel_buffer_size_byte;
u16 panel_reset_timeout_msec;
@@ -361,6 +371,7 @@ struct tegra_dc_out {
int (*enable)(void);
int (*postpoweron)(void);
+ int (*prepoweroff)(void);
int (*disable)(void);
int (*hotplug_init)(void);
@@ -377,6 +388,7 @@ struct tegra_dc_out {
#define TEGRA_DC_OUT_CONTINUOUS_MODE (0 << 3)
#define TEGRA_DC_OUT_ONE_SHOT_MODE (1 << 3)
#define TEGRA_DC_OUT_N_SHOT_MODE (1 << 4)
+#define TEGRA_DC_OUT_ONE_SHOT_LP_MODE (1 << 5)
#define TEGRA_DC_ALIGN_MSB 0
#define TEGRA_DC_ALIGN_LSB 1
@@ -384,6 +396,9 @@ struct tegra_dc_out {
#define TEGRA_DC_ORDER_RED_BLUE 0
#define TEGRA_DC_ORDER_BLUE_RED 1
+#define V_BLANK_FLIP 0
+#define V_BLANK_NVSD 1
+
struct tegra_dc;
struct nvmap_handle_ref;
@@ -426,6 +441,7 @@ struct tegra_dc_win {
unsigned out_w;
unsigned out_h;
unsigned z;
+ u8 global_alpha;
struct tegra_dc_csc csc;
@@ -502,6 +518,7 @@ struct tegra_dc_platform_data {
#define TEGRA_DC_FLAG_ENABLED (1 << 0)
+int tegra_dc_get_stride(struct tegra_dc *dc, unsigned win);
struct tegra_dc *tegra_dc_get_dc(unsigned idx);
struct tegra_dc_win *tegra_dc_get_window(struct tegra_dc *dc, unsigned win);
bool tegra_dc_get_connected(struct tegra_dc *);
@@ -538,7 +555,6 @@ unsigned tegra_dc_get_out_max_pixclock(const struct tegra_dc *dc);
struct tegra_dc_pwm_params {
int which_pwm;
- void (*switch_to_sfio)(int);
int gpio_conf_to_sfio;
unsigned int period;
unsigned int clk_div;
@@ -549,7 +565,10 @@ struct tegra_dc_pwm_params {
void tegra_dc_config_pwm(struct tegra_dc *dc, struct tegra_dc_pwm_params *cfg);
int tegra_dsi_send_panel_short_cmd(struct tegra_dc *dc, u8 *pdata, u8 data_len);
-void tegra_dc_host_trigger(struct tegra_dc *dc);
+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);
diff --git a/arch/arm/mach-tegra/include/mach/iomap.h b/arch/arm/mach-tegra/include/mach/iomap.h
index c491abafb8b9..2e205db063dd 100644
--- a/arch/arm/mach-tegra/include/mach/iomap.h
+++ b/arch/arm/mach-tegra/include/mach/iomap.h
@@ -2,7 +2,7 @@
* arch/arm/mach-tegra/include/mach/iomap.h
*
* Copyright (C) 2010 Google, Inc.
- * Copyright (C) 2011 NVIDIA Corporation.
+ * Copyright (C) 2011-2012, NVIDIA Corporation.
*
* Author:
* Colin Cross <ccross@google.com>
@@ -92,6 +92,8 @@
#define TEGRA_GART_BASE 0x58000000
#define TEGRA_GART_SIZE SZ_32M
+#define TEGRA_IOMMU_BASE TEGRA_GART_BASE
+#define TEGRA_IOMMU_SIZE TEGRA_GART_SIZE
#else
@@ -99,6 +101,8 @@
#define TEGRA_SMMU_SIZE_TEGRA3_A01 SZ_256M
#define TEGRA_SMMU_BASE 0x00001000
#define TEGRA_SMMU_SIZE (SZ_1G - SZ_4K * 2)
+#define TEGRA_IOMMU_BASE TEGRA_SMMU_BASE
+#define TEGRA_IOMMU_SIZE TEGRA_SMMU_SIZE
#endif
@@ -263,6 +267,9 @@
#define TEGRA_TSENSOR_BASE 0x70014000
#define TEGRA_TSENSOR_SIZE SZ_4K
+#define TEGRA_CEC_BASE 0x70015000
+#define TEGRA_CEC_SIZE SZ_4K
+
#define TEGRA_HDA_BASE 0x70030000
#define TEGRA_HDA_SIZE SZ_64K
diff --git a/arch/arm/mach-tegra/include/mach/iovmm.h b/arch/arm/mach-tegra/include/mach/iovmm.h
index fd83a326e129..cd56bd835592 100644
--- a/arch/arm/mach-tegra/include/mach/iovmm.h
+++ b/arch/arm/mach-tegra/include/mach/iovmm.h
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-tegra/include/mach/iovmm.h
*
- * Copyright (c) 2010-2011, NVIDIA Corporation.
+ * Copyright (c) 2010-2012, NVIDIA Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -68,6 +68,8 @@ struct tegra_iovmm_domain {
struct iovmm_share_group;
+#if !defined(CONFIG_IOMMU_API)
+
struct tegra_iovmm_client {
const char *name;
unsigned long flags;
@@ -90,6 +92,25 @@ struct tegra_iovmm_area {
struct tegra_iovmm_area_ops *ops;
};
+#else /* CONFIG_IOMMU_API */
+
+/*
+ * To replace IOVMM with IOMMU backend
+ */
+
+struct tegra_iovmm_client {
+ struct device *dev;
+};
+
+struct tegra_iovmm_area {
+ dma_addr_t iovm_start;
+ size_t iovm_length;
+ pgprot_t pgprot;
+ struct device *dev;
+};
+
+#endif /* CONFIG_IOMMU_API */
+
struct tegra_iovmm_device_ops {
/* maps a VMA using the page residency functions provided by the VMA */
int (*map)(struct tegra_iovmm_domain *domain,
@@ -140,9 +161,16 @@ struct tegra_iovmm_area_ops {
* called by clients to allocate an I/O VMM client mapping context which
* will be shared by all clients in the same share_group
*/
-struct tegra_iovmm_client *tegra_iovmm_alloc_client(const char *name,
+struct tegra_iovmm_client *__tegra_iovmm_alloc_client(const char *name,
const char *share_group, struct miscdevice *misc_dev);
+static inline struct tegra_iovmm_client *tegra_iovmm_alloc_client(
+ struct device *dev, const char *share_group,
+ struct miscdevice *misc_dev)
+{
+ return __tegra_iovmm_alloc_client(dev_name(dev), share_group, misc_dev);
+}
+
size_t tegra_iovmm_get_vm_size(struct tegra_iovmm_client *client);
void tegra_iovmm_free_client(struct tegra_iovmm_client *client);
@@ -220,7 +248,8 @@ int tegra_iovmm_unregister(struct tegra_iovmm_device *dev);
#else /* CONFIG_TEGRA_IOVMM */
static inline struct tegra_iovmm_client *tegra_iovmm_alloc_client(
- const char *name, const char *share_group, struct miscdevice *misc_dev)
+ struct device *dev, const char *share_group,
+ struct miscdevice *misc_dev)
{
return NULL;
}
@@ -319,5 +348,37 @@ static inline void tegra_iovmm_resume(void)
{
}
+#ifdef CONFIG_IOMMU_API
+/*
+ * Replace tegra_iovmm_*() with tegra_iommu_*() helpers
+ */
+#include <linux/dma-mapping.h>
+#include <linux/dma-direction.h>
+
+#include <asm/dma-iommu.h>
+
+#define tegra_iovmm_alloc_client(d, s, m) tegra_iommu_alloc_client(d)
+#define tegra_iovmm_free_client(c) tegra_iommu_free_client(c)
+
+#define tegra_iovmm_create_vm(c, o, s, a, p, i) \
+ tegra_iommu_create_vm((c)->dev, i, s, p)
+#define tegra_iovmm_free_vm(v) tegra_iommu_free_vm(v)
+
+#define tegra_iovmm_get_vm_size(c) arm_iommu_iova_avail((c)->dev)
+#define tegra_iovmm_get_max_free(c) arm_iommu_iova_max_free((c)->dev)
+
+#define tegra_iovmm_vm_insert_pfn(a, v, n) \
+ dma_map_page_at((a)->dev, pfn_to_page(n), v, 0, PAGE_SIZE, DMA_NONE);
+
+struct tegra_iovmm_area *tegra_iommu_create_vm(struct device *dev,
+ dma_addr_t req, size_t size, pgprot_t prot);
+
+void tegra_iommu_free_vm(struct tegra_iovmm_area *area);
+
+struct tegra_iovmm_client *tegra_iommu_alloc_client(struct device *dev);
+
+void tegra_iommu_free_client(struct tegra_iovmm_client *client);
+
+#endif /* CONFIG_IOMMU_API */
#endif /* CONFIG_TEGRA_IOVMM */
#endif /* _MACH_TEGRA_IOVMM_H_*/
diff --git a/arch/arm/mach-tegra/include/mach/latency_allowance.h b/arch/arm/mach-tegra/include/mach/latency_allowance.h
index f0d27f0b8ba9..8644075a88b3 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, NVIDIA Corporation.
+ * Copyright (C) 2011-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
@@ -104,7 +104,7 @@ static inline int tegra_enable_latency_scaling(enum tegra_la_id id,
static inline void tegra_disable_latency_scaling(enum tegra_la_id id)
{
- return 0;
+ return;
}
#else
int tegra_set_latency_allowance(enum tegra_la_id id,
diff --git a/arch/arm/mach-tegra/include/mach/legacy_irq.h b/arch/arm/mach-tegra/include/mach/legacy_irq.h
index 86f1ff7d06b0..3cd2d82c342f 100644
--- a/arch/arm/mach-tegra/include/mach/legacy_irq.h
+++ b/arch/arm/mach-tegra/include/mach/legacy_irq.h
@@ -19,5 +19,7 @@
#define _ARCH_ARM_MACH_TEGRA_LEGARY_IRQ_H
void tegra_init_legacy_irq_cop(void);
+/* lp1 wake interrupts enabled or disabled using this API */
+int tegra_update_lp1_irq_wake(unsigned int irq, bool enable);
#endif
diff --git a/arch/arm/mach-tegra/include/mach/nvmap.h b/arch/arm/mach-tegra/include/mach/nvmap.h
deleted file mode 100644
index 88f913fc29dd..000000000000
--- a/arch/arm/mach-tegra/include/mach/nvmap.h
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * arch/arm/mach-tegra/include/mach/nvmap.h
- *
- * structure declarations for nvmem and nvmap user-space ioctls
- *
- * Copyright (c) 2009-2011, NVIDIA Corporation.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * 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.
- */
-
-#include <linux/ioctl.h>
-#include <linux/file.h>
-#include <linux/rbtree.h>
-
-#if !defined(__KERNEL__)
-#define __user
-#endif
-
-#ifndef __NVMAP_H
-#define __NVMAP_H
-
-#define NVMAP_HEAP_SYSMEM (1ul<<31)
-#define NVMAP_HEAP_IOVMM (1ul<<30)
-
-/* common carveout heaps */
-#define NVMAP_HEAP_CARVEOUT_IRAM (1ul<<29)
-#define NVMAP_HEAP_CARVEOUT_VPR (1ul<<28)
-#define NVMAP_HEAP_CARVEOUT_GENERIC (1ul<<0)
-
-#define NVMAP_HEAP_CARVEOUT_MASK (NVMAP_HEAP_IOVMM - 1)
-
-/* allocation flags */
-#define NVMAP_HANDLE_UNCACHEABLE (0x0ul << 0)
-#define NVMAP_HANDLE_WRITE_COMBINE (0x1ul << 0)
-#define NVMAP_HANDLE_INNER_CACHEABLE (0x2ul << 0)
-#define NVMAP_HANDLE_CACHEABLE (0x3ul << 0)
-#define NVMAP_HANDLE_CACHE_FLAG (0x3ul << 0)
-
-#define NVMAP_HANDLE_SECURE (0x1ul << 2)
-
-
-#if defined(__KERNEL__)
-
-#if defined(CONFIG_TEGRA_NVMAP)
-struct nvmap_handle;
-struct nvmap_client;
-struct nvmap_device;
-#define nvmap_ref_to_handle(_ref) (*(struct nvmap_handle **)(_ref))
-/* Convert User space handle to Kernel. */
-#define nvmap_convert_handle_u2k(h) (h)
-#elif defined(CONFIG_ION_TEGRA)
-/* For Ion Mem Manager support through nvmap_* API's. */
-#include "../../../../../drivers/gpu/ion/ion_priv.h"
-
-#define nvmap_client ion_client
-#define nvmap_device ion_device
-#define nvmap_handle ion_handle
-#define nvmap_handle_ref ion_handle
-#define nvmap_ref_to_handle(_ref) (struct ion_handle *)_ref
-/* Convert User space handle to Kernel. */
-#define nvmap_convert_handle_u2k(h) ({ \
- if ((u32)h >= TASK_SIZE) { \
- pr_err("Invalid user space handle."); \
- BUG(); \
- } \
- (*((u32 *)h)); })
-#endif
-
-#define nvmap_id_to_handle(_id) ((struct nvmap_handle *)(_id))
-
-
-struct nvmap_pinarray_elem {
- __u32 patch_mem;
- __u32 patch_offset;
- __u32 pin_mem;
- __u32 pin_offset;
- __u32 reloc_shift;
-};
-
-#if defined(CONFIG_TEGRA_NVMAP)
-/* handle_ref objects are client-local references to an nvmap_handle;
- * they are distinct objects so that handles can be unpinned and
- * unreferenced the correct number of times when a client abnormally
- * terminates */
-struct nvmap_handle_ref {
- struct nvmap_handle *handle;
- struct rb_node node;
- atomic_t dupes; /* number of times to free on file close */
- atomic_t pin; /* number of times to unpin on free */
-};
-#endif
-
-struct nvmap_client *nvmap_create_client(struct nvmap_device *dev,
- const char *name);
-
-struct nvmap_handle_ref *nvmap_alloc(struct nvmap_client *client, size_t size,
- size_t align, unsigned int flags,
- unsigned int heap_mask);
-
-void nvmap_free(struct nvmap_client *client, struct nvmap_handle_ref *r);
-
-void *nvmap_mmap(struct nvmap_handle_ref *r);
-
-void nvmap_munmap(struct nvmap_handle_ref *r, void *addr);
-
-struct nvmap_client *nvmap_client_get_file(int fd);
-
-struct nvmap_client *nvmap_client_get(struct nvmap_client *client);
-
-void nvmap_client_put(struct nvmap_client *c);
-
-phys_addr_t nvmap_pin(struct nvmap_client *c, struct nvmap_handle_ref *r);
-
-phys_addr_t nvmap_handle_address(struct nvmap_client *c, unsigned long id);
-
-void nvmap_unpin(struct nvmap_client *client, struct nvmap_handle_ref *r);
-
-int nvmap_pin_array(struct nvmap_client *client, struct nvmap_handle *gather,
- const struct nvmap_pinarray_elem *arr, int nr,
- struct nvmap_handle **unique);
-
-void nvmap_unpin_handles(struct nvmap_client *client,
- struct nvmap_handle **h, int nr);
-
-int nvmap_patch_word(struct nvmap_client *client,
- struct nvmap_handle *patch,
- u32 patch_offset, u32 patch_value);
-
-struct nvmap_platform_carveout {
- const char *name;
- unsigned int usage_mask;
- phys_addr_t base;
- size_t size;
- size_t buddy_size;
-};
-
-struct nvmap_platform_data {
- const struct nvmap_platform_carveout *carveouts;
- unsigned int nr_carveouts;
-};
-
-extern struct nvmap_device *nvmap_dev;
-
-#endif
-
-#endif
diff --git a/arch/arm/mach-tegra/include/mach/sdhci.h b/arch/arm/mach-tegra/include/mach/sdhci.h
index b48a92887070..e307506eb40b 100644
--- a/arch/arm/mach-tegra/include/mach/sdhci.h
+++ b/arch/arm/mach-tegra/include/mach/sdhci.h
@@ -20,6 +20,14 @@
#include <linux/mmc/host.h>
#include <asm/mach/mmc.h>
+/*
+ * MMC_OCR_1V8_MASK will be used in board sdhci file
+ * Example for cardhu it will be used in board-cardhu-sdhci.c
+ * for built_in = 0 devices enabling ocr_mask to MMC_OCR_1V8_MASK
+ * sets the voltage to 1.8V
+ */
+#define MMC_OCR_1V8_MASK 0x8
+
struct tegra_sdhci_platform_data {
int cd_gpio;
int wp_gpio;
@@ -28,6 +36,7 @@ struct tegra_sdhci_platform_data {
int pm_flags;
int pm_caps;
unsigned int max_clk_limit;
+ unsigned int ddr_clk_limit;
unsigned int tap_delay;
struct mmc_platform_data mmc_data;
};
diff --git a/arch/arm/mach-tegra/include/mach/tegra_p1852_pdata.h b/arch/arm/mach-tegra/include/mach/tegra_p1852_pdata.h
index bfd61c460051..501d815b881b 100644
--- a/arch/arm/mach-tegra/include/mach/tegra_p1852_pdata.h
+++ b/arch/arm/mach-tegra/include/mach/tegra_p1852_pdata.h
@@ -35,8 +35,15 @@ struct codec_info_s {
char *cpu_dai_name;
char *codec_name; /* Name of the Codec Driver */
char *name; /* Name of the Codec-Dai-Link */
+ char *pcm_driver; /* Name of the PCM driver */
enum i2s_data_format i2s_format;
int master; /* Codec is Master or Slave */
+ /* TDM format setttings */
+ 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_p1852_platform_data {
diff --git a/arch/arm/mach-tegra/include/mach/tegra_usb_modem_power.h b/arch/arm/mach-tegra/include/mach/tegra_usb_modem_power.h
index 0ce7fa40eb2e..210b9f61ecb5 100644
--- a/arch/arm/mach-tegra/include/mach/tegra_usb_modem_power.h
+++ b/arch/arm/mach-tegra/include/mach/tegra_usb_modem_power.h
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-tegra/include/mach/tegra_usb_modem_power.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
@@ -40,8 +40,14 @@ struct tegra_modem_operations {
/* tegra usb modem power platform data */
struct tegra_usb_modem_power_platform_data {
const struct tegra_modem_operations *ops;
- unsigned int wake_gpio; /* remote wakeup gpio */
- unsigned int flags; /* remote wakeup irq flags */
+ unsigned int wake_gpio; /* remote wakeup gpio */
+ unsigned long wake_irq_flags; /* remote wakeup irq flags */
+ unsigned int boot_gpio; /* modem boot gpio */
+ unsigned long boot_irq_flags; /* modem boot irq flags */
+ int autosuspend_delay; /* autosuspend delay in milliseconds */
+ int short_autosuspend_delay; /* short autosuspend delay in ms */
+ const struct platform_device *tegra_ehci_device;
+ const struct tegra_usb_platform_data *tegra_ehci_pdata;
};
#endif /* __MACH_TEGRA_USB_MODEM_POWER_H */
diff --git a/arch/arm/mach-tegra/include/mach/thermal.h b/arch/arm/mach-tegra/include/mach/thermal.h
index ab7b34492d9e..ed71d0340a96 100644
--- a/arch/arm/mach-tegra/include/mach/thermal.h
+++ b/arch/arm/mach-tegra/include/mach/thermal.h
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-tegra/thermal.h
*
- * Copyright (C) 2010-2011 NVIDIA Corporation.
+ * Copyright (C) 2010-2012 NVIDIA Corporation.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -17,26 +17,62 @@
#ifndef __MACH_THERMAL_H
#define __MACH_THERMAL_H
+#include <linux/therm_est.h>
+
+enum thermal_device_id {
+ THERMAL_DEVICE_ID_NULL = 0x0,
+ THERMAL_DEVICE_ID_NCT_EXT = 0x1,
+ THERMAL_DEVICE_ID_NCT_INT = 0x2,
+ THERMAL_DEVICE_ID_TSENSOR = 0x4,
+ THERMAL_DEVICE_ID_SKIN = 0x8,
+};
+
+#define THERMAL_DEVICE_MAX (4)
+
+enum balanced_throttle_id {
+ BALANCED_THROTTLE_ID_TJ,
+ BALANCED_THROTTLE_ID_SKIN,
+};
+
+struct skin_therm_est_subdevice {
+ enum thermal_device_id id;
+ long coeffs[HIST_LEN];
+};
+
/* All units in millicelsius */
struct tegra_thermal_data {
- long temp_throttle;
+ enum thermal_device_id shutdown_device_id;
long temp_shutdown;
- long temp_offset;
+#if defined(CONFIG_TEGRA_EDP_LIMITS) || defined(CONFIG_TEGRA_THERMAL_THROTTLE)
+ enum thermal_device_id throttle_edp_device_id;
+#endif
#ifdef CONFIG_TEGRA_EDP_LIMITS
long edp_offset;
long hysteresis_edp;
#endif
-#ifdef CONFIG_TEGRA_THERMAL_SYSFS
+#ifdef CONFIG_TEGRA_THERMAL_THROTTLE
+ long temp_throttle;
int tc1;
int tc2;
long passive_delay;
-#else
- long hysteresis_throttle;
+#endif
+#ifdef CONFIG_TEGRA_SKIN_THROTTLE
+ enum thermal_device_id skin_device_id;
+ long temp_throttle_skin;
+ int tc1_skin;
+ int tc2_skin;
+ int passive_delay_skin;
+
+ long skin_temp_offset;
+ long skin_period;
+ int skin_devs_size;
+ struct skin_therm_est_subdevice skin_devs[];
#endif
};
struct tegra_thermal_device {
char *name;
+ enum thermal_device_id id;
void *data;
long offset;
int (*get_temp) (void *, long *);
@@ -44,16 +80,51 @@ struct tegra_thermal_device {
int (*set_limits) (void *, long, long);
int (*set_alert)(void *, void (*)(void *), void *);
int (*set_shutdown_temp)(void *, long);
+#ifdef CONFIG_TEGRA_THERMAL_THROTTLE
+ struct thermal_zone_device *thz;
+#endif
+ struct list_head node;
+};
+
+struct throttle_table {
+ unsigned int cpu_freq;
+ int core_cap_level;
};
+#define MAX_THROT_TABLE_SIZE (32)
+
+struct balanced_throttle {
+ enum balanced_throttle_id id;
+
+ int is_throttling;
+ int throttle_index;
+ struct thermal_cooling_device *cdev;
+
+ struct list_head node;
+
+ int throt_tab_size;
+ struct throttle_table throt_tab[MAX_THROT_TABLE_SIZE];
+};
+
+#ifdef CONFIG_TEGRA_THERMAL_THROTTLE
+int balanced_throttle_register(struct balanced_throttle *bthrot);
+#else
+static inline int balanced_throttle_register(struct balanced_throttle *bthrot)
+{ return 0; }
+#endif
+
#ifndef CONFIG_ARCH_TEGRA_2x_SOC
-int tegra_thermal_init(struct tegra_thermal_data *data);
-int tegra_thermal_set_device(struct tegra_thermal_device *device);
+int tegra_thermal_init(struct tegra_thermal_data *data,
+ struct balanced_throttle *throttle_list,
+ int throttle_list_size);
+int tegra_thermal_device_register(struct tegra_thermal_device *device);
int tegra_thermal_exit(void);
#else
-static inline int tegra_thermal_init(struct tegra_thermal_data *data)
+static inline int tegra_thermal_init(struct tegra_thermal_data *data,
+ struct balanced_throttle throttle_list,
+ int throttle_list_size);
{ return 0; }
-static inline int tegra_thermal_set_device(struct tegra_thermal_device *dev)
+static int tegra_thermal_device_register(struct tegra_thermal_device *device)
{ return 0; }
static inline int tegra_thermal_exit(void)
{ return 0; }
diff --git a/arch/arm/mach-tegra/include/mach/usb_phy.h b/arch/arm/mach-tegra/include/mach/usb_phy.h
index 46fe8c84a2f3..c721642c4417 100644
--- a/arch/arm/mach-tegra/include/mach/usb_phy.h
+++ b/arch/arm/mach-tegra/include/mach/usb_phy.h
@@ -18,151 +18,120 @@
#ifndef __MACH_USB_PHY_H
#define __MACH_USB_PHY_H
-#include <linux/clk.h>
-#include <linux/regulator/consumer.h>
-#include <linux/usb/otg.h>
-#include <linux/platform_data/tegra_usb.h>
-
-struct tegra_utmip_config {
- u8 hssync_start_delay;
- u8 elastic_limit;
- u8 idle_wait_delay;
- u8 term_range_adj;
- u8 xcvr_setup;
- signed char xcvr_setup_offset;
- u8 xcvr_use_fuses;
- u8 xcvr_lsfslew;
- u8 xcvr_lsrslew;
-};
-
-struct tegra_ulpi_trimmer {
- u8 shadow_clk_delay; /* 0 ~ 31 */
- u8 clock_out_delay; /* 0 ~ 31 */
- u8 data_trimmer; /* 0 ~ 7 */
- u8 stpdirnxt_trimmer; /* 0 ~ 7 */
-};
-
-struct tegra_ulpi_config {
- int enable_gpio;
- int reset_gpio;
- const char *clk;
- const struct tegra_ulpi_trimmer *trimmer;
- int (*pre_phy_on)(void);
- int (*post_phy_on)(void);
- int (*pre_phy_off)(void);
- int (*post_phy_off)(void);
- void (*phy_restore_start)(void);
- void (*phy_restore_end)(void);
- int phy_restore_gpio; /* null phy restore ack from device */
- int ulpi_dir_gpio; /* ulpi dir */
- int ulpi_d0_gpio; /* usb linestate[0] */
- int ulpi_d1_gpio; /* usb linestate[1] */
-};
-
-struct tegra_uhsic_config {
- int enable_gpio;
- int reset_gpio;
- u8 sync_start_delay;
- u8 idle_wait_delay;
- u8 term_range_adj;
- u8 elastic_underrun_limit;
- u8 elastic_overrun_limit;
- int (*postsuspend)(void);
- int (*preresume)(void);
- int (*usb_phy_ready)(void);
- int (*post_phy_off)(void);
-};
-
-enum tegra_usb_phy_port_speed {
- TEGRA_USB_PHY_PORT_SPEED_FULL = 0,
- TEGRA_USB_PHY_PORT_SPEED_LOW,
- TEGRA_USB_PHY_PORT_SPEED_HIGH,
-};
-
-enum tegra_usb_phy_mode {
- TEGRA_USB_PHY_MODE_DEVICE,
- TEGRA_USB_PHY_MODE_HOST,
-};
-
-struct usb_phy_plat_data {
- int instance;
- int vbus_irq;
- int vbus_gpio;
- int vbus_gpio_inverted;
- char * vbus_reg_supply;
-};
-
-struct tegra_xtal_freq;
-
-struct tegra_usb_phy {
- int instance;
- const struct tegra_xtal_freq *freq;
- void __iomem *regs;
- void __iomem *pad_regs;
- struct clk *clk;
- struct clk *pll_u;
- struct clk *pad_clk;
- enum tegra_usb_phy_mode mode;
- void *config;
- struct regulator *reg_vdd;
- struct regulator *reg_vbus;
- enum tegra_usb_phy_type usb_phy_type;
- bool regulator_on;
- struct otg_transceiver *ulpi;
- int initialized;
- bool power_on;
- bool remote_wakeup;
- int hotplug;
- unsigned int xcvr_setup_value;
-};
-
-typedef int (*tegra_phy_fp)(struct tegra_usb_phy *phy, bool is_dpd);
-typedef void (*tegra_phy_restore_start_fp)(struct tegra_usb_phy *phy,
- enum tegra_usb_phy_port_speed);
-typedef void (*tegra_phy_restore_end_fp)(struct tegra_usb_phy *phy);
-
-struct tegra_usb_phy *tegra_usb_phy_open(int instance, void __iomem *regs,
- void *config, enum tegra_usb_phy_mode phy_mode,
- enum tegra_usb_phy_type usb_phy_type);
-
-int tegra_usb_phy_power_on(struct tegra_usb_phy *phy, bool is_dpd);
-
-void tegra_usb_phy_clk_disable(struct tegra_usb_phy *phy);
-
-void tegra_usb_phy_clk_enable(struct tegra_usb_phy *phy);
-
-void tegra_usb_phy_power_off(struct tegra_usb_phy *phy, bool is_dpd);
-
-void tegra_usb_phy_postsuspend(struct tegra_usb_phy *phy, bool is_dpd);
-
-void tegra_usb_phy_preresume(struct tegra_usb_phy *phy, bool is_dpd);
-
-void tegra_usb_phy_postresume(struct tegra_usb_phy *phy, bool is_dpd);
-
-void tegra_ehci_pre_reset(struct tegra_usb_phy *phy, bool is_dpd);
-
-void tegra_ehci_post_reset(struct tegra_usb_phy *phy, bool is_dpd);
-
-void tegra_ehci_phy_restore_start(struct tegra_usb_phy *phy,
- enum tegra_usb_phy_port_speed port_speed);
-
-void tegra_ehci_phy_restore_end(struct tegra_usb_phy *phy);
+/**
+ * Tegra USB phy opaque handle
+ */
+struct tegra_usb_phy;
+
+/**
+ * Opens the usb phy associated to the USB platform device
+ * tegra usb phy open must be called before accessing any phy APIs
+ */
+struct tegra_usb_phy *tegra_usb_phy_open(struct platform_device *pdev);
+/**
+ * Closes the phy controller and its resources
+ */
void tegra_usb_phy_close(struct tegra_usb_phy *phy);
-int tegra_usb_phy_bus_connect(struct tegra_usb_phy *phy);
+/**
+ * Handles interrupts specific to the phy interface
+ * Note: udc or ehci driver will handle the controller interrupts
+ */
+int tegra_usb_phy_irq(struct tegra_usb_phy *phy);
+
+/**
+ * Initializes the phy specific functions after phy is power on
+ */
+int tegra_usb_phy_init(struct tegra_usb_phy *phy);
+
+/**
+ * Handles phy interface specific functionality after driver reset
+ */
+int tegra_usb_phy_reset(struct tegra_usb_phy *phy);
+
+/**
+ * Handles phy interface specific functionality before driver suspend
+ * Also, handles platform specific pre suspend functions
+ */
+int tegra_usb_phy_pre_suspend(struct tegra_usb_phy *phy);
+
+/**
+ * Handles phy interface specific suspend functionality
+ */
+int tegra_usb_phy_suspend(struct tegra_usb_phy *phy);
+
+/**
+ * Handles phy interface specific functionality after driver suspend
+ */
+int tegra_usb_phy_post_suspend(struct tegra_usb_phy *phy);
+
+/**
+ * Handles phy interface specific functionality before driver resume
+ * Also, handles platform specific pre resume functions
+ */
+int tegra_usb_phy_pre_resume(struct tegra_usb_phy *phy, bool remote_wakeup);
+
+/**
+ * Handles phy interface specific resume functionality
+ */
+int tegra_usb_phy_resume(struct tegra_usb_phy *phy);
+/**
+ * Handles phy interface specific functionality after driver resume
+ */
+int tegra_usb_phy_post_resume(struct tegra_usb_phy *phy);
+
+/**
+ * Handles phy interface specific functionality during port power on
+ */
+int tegra_usb_phy_port_power(struct tegra_usb_phy *phy);
+
+/**
+ * Handles phy interface specific functionality during bus reset
+ */
int tegra_usb_phy_bus_reset(struct tegra_usb_phy *phy);
-int tegra_usb_phy_bus_idle(struct tegra_usb_phy *phy);
+/**
+ * Handles phy interface specific functionality for turning off the phy to
+ * put the phy in low power mode
+ */
+int tegra_usb_phy_power_off(struct tegra_usb_phy *phy);
-bool tegra_usb_phy_is_device_connected(struct tegra_usb_phy *phy);
+/**
+ * Handles phy interface specific functionality for turning on the phy to
+ * bring phy out of low power mode
+ */
+int tegra_usb_phy_power_on(struct tegra_usb_phy *phy);
-bool tegra_usb_phy_charger_detect(struct tegra_usb_phy *phy);
+/**
+ * Indicates whether phy registers are accessible or not
+ * if phy is powered off then returns false else true
+ */
+bool tegra_usb_phy_hw_accessible(struct tegra_usb_phy *phy);
+
+/**
+ * Indicates whether compliance charger is connected or not
+ * if compliance charger is detected then returns true else false
+ */
+bool tegra_usb_phy_charger_detected(struct tegra_usb_phy *phy);
+
+/**
+ * Indicates whether phy resumed due to the remote wake event or not
+ * returns true if remote wake is detected.
+ */
+bool tegra_usb_phy_remote_wakeup(struct tegra_usb_phy *phy);
+
+/**
+ * Indicates controller has HOST PC register set or not
+ */
+bool tegra_usb_phy_has_hostpc(struct tegra_usb_phy *phy);
-int __init tegra_usb_phy_init(struct usb_phy_plat_data *pdata, int size);
+/**
+ * Indicates controller port supports OTG or not
+ */
+bool tegra_usb_phy_otg_supported(struct tegra_usb_phy *phy);
-bool tegra_usb_phy_is_remotewake_detected(struct tegra_usb_phy *phy);
void tegra_usb_phy_memory_prefetch_on(struct tegra_usb_phy *phy);
diff --git a/arch/arm/mach-tegra/iovmm-gart.c b/arch/arm/mach-tegra/iovmm-gart.c
index ad1ce3a7afc3..130901cb4883 100644
--- a/arch/arm/mach-tegra/iovmm-gart.c
+++ b/arch/arm/mach-tegra/iovmm-gart.c
@@ -4,7 +4,7 @@
* Tegra I/O VMM implementation for GART devices in Tegra and Tegra 2 series
* systems-on-a-chip.
*
- * Copyright (c) 2010-2012, NVIDIA Corporation.
+ * Copyright (c) 2010-2012 NVIDIA Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -73,7 +73,7 @@ static int gart_map(struct tegra_iovmm_domain *, struct tegra_iovmm_area *);
static void gart_unmap(struct tegra_iovmm_domain *,
struct tegra_iovmm_area *, bool);
static void gart_map_pfn(struct tegra_iovmm_domain *,
- struct tegra_iovmm_area *, tegra_iovmm_addr_t, unsigned long);
+ struct tegra_iovmm_area *, unsigned long, unsigned long);
static struct tegra_iovmm_domain *gart_alloc_domain(
struct tegra_iovmm_device *, struct tegra_iovmm_client *);
@@ -330,7 +330,7 @@ static void gart_unmap(struct tegra_iovmm_domain *domain,
}
static void gart_map_pfn(struct tegra_iovmm_domain *domain,
- struct tegra_iovmm_area *iovma, tegra_iovmm_addr_t offs,
+ struct tegra_iovmm_area *iovma, unsigned long offs,
unsigned long pfn)
{
struct gart_device *gart =
diff --git a/arch/arm/mach-tegra/iovmm-smmu.c b/arch/arm/mach-tegra/iovmm-smmu.c
index 31c7d4884181..6cdeb744a04c 100644
--- a/arch/arm/mach-tegra/iovmm-smmu.c
+++ b/arch/arm/mach-tegra/iovmm-smmu.c
@@ -310,10 +310,14 @@ struct smmu_device {
/*
* Register image savers for suspend/resume
*/
- unsigned long translation_enable_0_0;
- unsigned long translation_enable_1_0;
- unsigned long translation_enable_2_0;
- unsigned long asid_security_0;
+ unsigned long config_0; /* Secure reg */
+ unsigned long tlb_config_0;
+ unsigned long ptc_config_0;
+ unsigned long ptb_asid_0;
+ unsigned long translation_enable_0_0; /* Secure reg */
+ unsigned long translation_enable_1_0; /* Secure reg */
+ unsigned long translation_enable_2_0; /* Secure reg */
+ unsigned long asid_security_0; /* Secure reg */
unsigned long lowest_asid; /* Variables for hardware testing */
unsigned long debug_asid;
@@ -335,13 +339,13 @@ struct smmu_device {
* must have these read-back to ensure the APB/AHB bus transaction is
* complete before initiating activity on the PPSB block.
*/
-#define FLUSH_SMMU_REGS(smmu) (void)readl((smmu)->regs + MC_SMMU_CONFIG_0)
+#define FLUSH_SMMU_REGS(smmu) (void)readl((smmu)->regs + MC_SMMU_PTB_DATA_0)
/*
* Flush all TLB entries and all PTC entries
* Caller must lock smmu
*/
-static void smmu_flush_regs(struct smmu_device *smmu, int enable)
+static void smmu_flush_regs(struct smmu_device *smmu)
{
writel(MC_SMMU_PTC_FLUSH_0_PTC_FLUSH_TYPE_ALL,
smmu->regs + MC_SMMU_PTC_FLUSH_0);
@@ -349,10 +353,6 @@ static void smmu_flush_regs(struct smmu_device *smmu, int enable)
writel(MC_SMMU_TLB_FLUSH_0_TLB_FLUSH_VA_MATCH_ALL |
MC_SMMU_TLB_FLUSH_0_TLB_FLUSH_ASID_MATCH_disable,
smmu->regs + MC_SMMU_TLB_FLUSH_0);
-
- if (enable)
- writel(MC_SMMU_CONFIG_0_SMMU_ENABLE_ENABLE,
- smmu->regs + MC_SMMU_CONFIG_0);
FLUSH_SMMU_REGS(smmu);
}
@@ -388,14 +388,14 @@ static void smmu_setup_regs(struct smmu_device *smmu)
smmu->regs + MC_SMMU_TRANSLATION_ENABLE_1_0);
writel(smmu->translation_enable_2_0,
smmu->regs + MC_SMMU_TRANSLATION_ENABLE_2_0);
- writel(smmu->asid_security_0,
- smmu->regs + MC_SMMU_ASID_SECURITY_0);
- writel(MC_SMMU_TLB_CONFIG_0_RESET_VAL,
- smmu->regs + MC_SMMU_TLB_CONFIG_0);
- writel(MC_SMMU_PTC_CONFIG_0_RESET_VAL,
- smmu->regs + MC_SMMU_PTC_CONFIG_0);
-
- smmu_flush_regs(smmu, 1);
+ writel(smmu->asid_security_0, smmu->regs + MC_SMMU_ASID_SECURITY_0);
+ writel(smmu->ptb_asid_0, smmu->regs + MC_SMMU_PTB_ASID_0);
+ writel(smmu->ptc_config_0, smmu->regs + MC_SMMU_PTC_CONFIG_0);
+ writel(smmu->tlb_config_0, smmu->regs + MC_SMMU_TLB_CONFIG_0);
+ writel(smmu->config_0, smmu->regs + MC_SMMU_CONFIG_0);
+
+ smmu_flush_regs(smmu);
+
writel(
readl(smmu->regs_ahbarb + AHB_ARBITRATION_XBAR_CTRL_0) |
(AHB_ARBITRATION_XBAR_CTRL_0_SMMU_INIT_DONE_DONE <<
@@ -408,6 +408,10 @@ static int smmu_suspend(struct tegra_iovmm_device *dev)
struct smmu_device *smmu =
container_of(dev, struct smmu_device, iovmm_dev);
+ smmu->config_0 = readl(smmu->regs + MC_SMMU_CONFIG_0);
+ smmu->tlb_config_0 = readl(smmu->regs + MC_SMMU_TLB_CONFIG_0);
+ smmu->ptc_config_0 = readl(smmu->regs + MC_SMMU_PTC_CONFIG_0);
+ smmu->ptb_asid_0 = readl(smmu->regs + MC_SMMU_PTB_ASID_0);
smmu->translation_enable_0_0 =
readl(smmu->regs + MC_SMMU_TRANSLATION_ENABLE_0_0);
smmu->translation_enable_1_0 =
@@ -691,10 +695,8 @@ static void smmu_unmap(struct tegra_iovmm_domain *domain,
flush_ptc_and_tlb(as->smmu, as, addr, pte,
page, 0);
kunmap(page);
- if (!--(*pte_counter) && decommit) {
+ if (!--(*pte_counter) && decommit)
free_ptbl(as, addr);
- smmu_flush_regs(as->smmu, 0);
- }
}
}
addr += SMMU_PAGE_SIZE;
@@ -966,10 +968,14 @@ static int smmu_probe(struct platform_device *pdev)
goto fail;
}
+ smmu->config_0 = MC_SMMU_CONFIG_0_SMMU_ENABLE_ENABLE;
+ smmu->tlb_config_0 = MC_SMMU_TLB_CONFIG_0_RESET_VAL;
+ smmu->ptc_config_0 = MC_SMMU_PTC_CONFIG_0_RESET_VAL;
+ smmu->ptb_asid_0 = 0;
smmu->translation_enable_0_0 = ~0;
smmu->translation_enable_1_0 = ~0;
smmu->translation_enable_2_0 = ~0;
- smmu->asid_security_0 = 0;
+ smmu->asid_security_0 = 0;
memcpy(smmu->hwc_state, smmu_hwc_state_init, sizeof(smmu->hwc_state));
diff --git a/arch/arm/mach-tegra/iovmm.c b/arch/arm/mach-tegra/iovmm.c
index 6112128cb743..86a92aec2d28 100644
--- a/arch/arm/mach-tegra/iovmm.c
+++ b/arch/arm/mach-tegra/iovmm.c
@@ -805,7 +805,7 @@ void tegra_iovmm_free_client(struct tegra_iovmm_client *client)
mutex_unlock(&iovmm_group_list_lock);
}
-struct tegra_iovmm_client *tegra_iovmm_alloc_client(const char *name,
+struct tegra_iovmm_client *__tegra_iovmm_alloc_client(const char *name,
const char *share_group, struct miscdevice *misc_dev)
{
struct tegra_iovmm_client *c = kzalloc(sizeof(*c), GFP_KERNEL);
diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c
index 450295d901dd..278912486f40 100644
--- a/arch/arm/mach-tegra/irq.c
+++ b/arch/arm/mach-tegra/irq.c
@@ -26,6 +26,7 @@
#include <asm/hardware/gic.h>
#include <mach/iomap.h>
+#include <mach/gpio.h>
#include <mach/legacy_irq.h>
#include "board.h"
@@ -66,10 +67,34 @@ static void __iomem *ictlr_reg_base[] = {
#ifdef CONFIG_PM_SLEEP
static u32 cop_ier[NUM_ICTLRS];
+static u32 cop_iep[NUM_ICTLRS];
static u32 cpu_ier[NUM_ICTLRS];
static u32 cpu_iep[NUM_ICTLRS];
+
+static u32 ictlr_wake_mask[NUM_ICTLRS];
+#endif
+
+int tegra_update_lp1_irq_wake(unsigned int irq, bool enable)
+{
+#ifdef CONFIG_PM_SLEEP
+ u8 index;
+ u32 mask;
+
+ if (irq < FIRST_LEGACY_IRQ ||
+ irq >= FIRST_LEGACY_IRQ + NUM_ICTLRS * 32)
+ return -EINVAL;
+
+ index = ((irq - FIRST_LEGACY_IRQ) >> 5);
+ mask = BIT((irq - FIRST_LEGACY_IRQ) % 32);
+ if (enable)
+ ictlr_wake_mask[index] |= mask;
+ else
+ ictlr_wake_mask[index] &= ~mask;
#endif
+ return 0;
+}
+
static inline void tegra_irq_write_mask(unsigned int irq, unsigned long reg)
{
void __iomem *base;
@@ -131,11 +156,28 @@ static int tegra_set_type(struct irq_data *d, unsigned int flow_type)
return tegra_pm_irq_set_wake_type(d->irq, flow_type);
}
-
#ifdef CONFIG_PM_SLEEP
+/*
+ * Caller ensures that tegra_set_wake (irq_set_wake callback)
+ * is called for non-gpio wake sources only
+ */
static int tegra_set_wake(struct irq_data *d, unsigned int enable)
{
- return tegra_pm_irq_set_wake(d->irq, enable);
+ int ret;
+
+ /* pmc lp0 wake enable for non-gpio wake sources */
+ ret = tegra_pm_irq_set_wake(d->irq, enable);
+ if (ret)
+ pr_err("Failed lp0 wake %s for irq=%d\n",
+ (enable ? "enable" : "disable"), d->irq);
+
+ /* lp1 wake enable for wake sources */
+ ret = tegra_update_lp1_irq_wake(d->irq, enable);
+ if (ret)
+ pr_err("Failed lp1 wake %s for irq=%d\n",
+ (enable ? "enable" : "disable"), d->irq);
+
+ return ret;
}
static int tegra_legacy_irq_suspend(void)
@@ -146,9 +188,13 @@ static int tegra_legacy_irq_suspend(void)
local_irq_save(flags);
for (i = 0; i < NUM_ICTLRS; i++) {
void __iomem *ictlr = ictlr_reg_base[i];
+ /* save interrupt state */
cpu_ier[i] = readl(ictlr + ICTLR_CPU_IER);
cpu_iep[i] = readl(ictlr + ICTLR_CPU_IEP_CLASS);
cop_ier[i] = readl(ictlr + ICTLR_COP_IER);
+ cop_iep[i] = readl(ictlr + ICTLR_COP_IEP_CLASS);
+
+ /* disable COP interrupts */
writel(~0, ictlr + ICTLR_COP_IER_CLR);
}
local_irq_restore(flags);
@@ -167,7 +213,7 @@ static void tegra_legacy_irq_resume(void)
writel(cpu_iep[i], ictlr + ICTLR_CPU_IEP_CLASS);
writel(~0ul, ictlr + ICTLR_CPU_IER_CLR);
writel(cpu_ier[i], ictlr + ICTLR_CPU_IER_SET);
- writel(0, ictlr + ICTLR_COP_IEP_CLASS);
+ writel(cop_iep[i], ictlr + ICTLR_COP_IEP_CLASS);
writel(~0ul, ictlr + ICTLR_COP_IER_CLR);
writel(cop_ier[i], ictlr + ICTLR_COP_IER_SET);
}
diff --git a/arch/arm/mach-tegra/p852/board-p852-panel.c b/arch/arm/mach-tegra/p852/board-p852-panel.c
index c47032dd4f0a..8ed62f039dc8 100644
--- a/arch/arm/mach-tegra/p852/board-p852-panel.c
+++ b/arch/arm/mach-tegra/p852/board-p852-panel.c
@@ -25,13 +25,14 @@
#include <linux/nvhost.h>
#include <linux/platform_device.h>
#include <asm/mach-types.h>
-#include <mach/nvmap.h>
+#include <linux/nvmap.h>
#include <mach/irqs.h>
#include <mach/iomap.h>
#include <mach/dc.h>
#include <mach/fb.h>
#include "board-p852.h"
+#include "../tegra2_host1x_devices.h"
#define CARVEOUT_IRAM {\
.name = "iram",\
@@ -175,7 +176,7 @@ int __init p852_panel_init(void)
return err;
#ifdef CONFIG_TEGRA_GRHOST
- err = nvhost_device_register(&tegra_grhost_device);
+ err = tegra2_register_host1x_devices();
if (err)
return err;
#endif
diff --git a/arch/arm/mach-tegra/p852/board-p852.c b/arch/arm/mach-tegra/p852/board-p852.c
index 21b867e15177..039d9db6a3a6 100644
--- a/arch/arm/mach-tegra/p852/board-p852.c
+++ b/arch/arm/mach-tegra/p852/board-p852.c
@@ -288,49 +288,6 @@ static struct platform_device debug_uart = {
},
};
-static struct tegra_utmip_config utmi_phy_config[] = {
- [0] = {
- .hssync_start_delay = 0,
- .idle_wait_delay = 17,
- .elastic_limit = 16,
- .term_range_adj = 6,
- .xcvr_setup = 15,
- .xcvr_lsfslew = 2,
- .xcvr_lsrslew = 2,
- },
- [1] = {
- .hssync_start_delay = 0,
- .idle_wait_delay = 17,
- .elastic_limit = 16,
- .term_range_adj = 6,
- .xcvr_setup = 8,
- .xcvr_lsfslew = 2,
- .xcvr_lsrslew = 2,
- },
-};
-
-static struct tegra_ulpi_config ulpi_usb2_config = {
- .reset_gpio = TEGRA_GPIO_PI5,
-};
-
-static struct tegra_ehci_platform_data tegra_ehci_pdata[] = {
- [0] = {
- .phy_config = &utmi_phy_config[0],
- .operating_mode = TEGRA_USB_HOST,
- .power_down_on_bus_suspend = 0,
- },
- [1] = {
- .phy_config = &ulpi_usb2_config,
- .operating_mode = TEGRA_USB_HOST,
- .power_down_on_bus_suspend = 0,
- .phy_type = TEGRA_USB_PHY_TYPE_LINK_ULPI,
- },
- [2] = {
- .phy_config = &utmi_phy_config[1],
- .operating_mode = TEGRA_USB_HOST,
- .power_down_on_bus_suspend = 0,
- },
-};
static void p852_usb_gpio_config(void)
{
@@ -529,6 +486,97 @@ static void __init p852_register_spidev(void)
#define p852_register_spidev() do {} while (0)
#endif
+/*
+ FixMe: Copied below GPIO value from Ventana board.
+ Plz correct it accordingly for embedded board usage
+*/
+#define TEGRA_GPIO_PV1 169
+
+static void ulpi_link_platform_open(void)
+{
+ int reset_gpio = TEGRA_GPIO_PV1;
+
+ 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);
+}
+
+static struct tegra_usb_phy_platform_ops ulpi_link_plat_ops = {
+ .open = ulpi_link_platform_open,
+};
+
+static struct tegra_usb_platform_data tegra_ehci_ulpi_link_pdata = {
+ .port_otg = false,
+ .has_hostpc = false,
+ .phy_intf = TEGRA_USB_PHY_INTF_ULPI_LINK,
+ .op_mode = TEGRA_USB_OPMODE_HOST,
+ .u_data.host = {
+ .vbus_gpio = -1,
+ .vbus_reg = NULL,
+ .hot_plug = false,
+ .remote_wakeup_supported = false,
+ .power_off_on_suspend = false,
+ },
+ .u_cfg.ulpi = {
+ .shadow_clk_delay = 10,
+ .clock_out_delay = 1,
+ .data_trimmer = 4,
+ .stpdirnxt_trimmer = 4,
+ .dir_trimmer = 4,
+ .clk = "cdev2",
+ },
+ .ops = &ulpi_link_plat_ops,
+};
+
+static struct tegra_usb_platform_data tegra_ehci1_utmi_pdata = {
+ .port_otg = false,
+ .has_hostpc = false,
+ .phy_intf = TEGRA_USB_PHY_INTF_UTMI,
+ .op_mode = TEGRA_USB_OPMODE_HOST,
+ .u_data.host = {
+ .vbus_gpio = -1,
+ .vbus_reg = NULL,
+ .hot_plug = true,
+ .remote_wakeup_supported = true,
+ .power_off_on_suspend = false,
+ },
+ .u_cfg.utmi = {
+ .hssync_start_delay = 0,
+ .idle_wait_delay = 17,
+ .elastic_limit = 16,
+ .term_range_adj = 6,
+ .xcvr_setup = 15,
+ .xcvr_lsfslew = 2,
+ .xcvr_lsrslew = 2,
+ },
+};
+
+static struct tegra_usb_platform_data tegra_ehci3_utmi_pdata = {
+ .port_otg = false,
+ .has_hostpc = false,
+ .phy_intf = TEGRA_USB_PHY_INTF_UTMI,
+ .op_mode = TEGRA_USB_OPMODE_HOST,
+ .u_data.host = {
+ .vbus_gpio = -1,
+ .vbus_reg = NULL,
+ .hot_plug = true,
+ .remote_wakeup_supported = true,
+ .power_off_on_suspend = false,
+ },
+ .u_cfg.utmi = {
+ .hssync_start_delay = 0,
+ .idle_wait_delay = 17,
+ .elastic_limit = 16,
+ .term_range_adj = 6,
+ .xcvr_setup = 8,
+ .xcvr_lsfslew = 2,
+ .xcvr_lsrslew = 2,
+ },
+};
static void __init p852_usb_init(void)
{
@@ -541,16 +589,16 @@ static void __init p852_usb_init(void)
else
*/
{
- tegra_ehci1_device.dev.platform_data = &tegra_ehci_pdata[0];
+ tegra_ehci1_device.dev.platform_data = &tegra_ehci1_utmi_pdata;
platform_device_register(&tegra_ehci1_device);
}
if (!(p852_sku_peripherals & P852_SKU_ULPI_DISABLE)) {
- tegra_ehci2_device.dev.platform_data = &tegra_ehci_pdata[1];
+ tegra_ehci2_device.dev.platform_data = &tegra_ehci_ulpi_link_pdata;
platform_device_register(&tegra_ehci2_device);
}
- tegra_ehci3_device.dev.platform_data = &tegra_ehci_pdata[2];
+ tegra_ehci3_device.dev.platform_data = &tegra_ehci3_utmi_pdata;
platform_device_register(&tegra_ehci3_device);
}
@@ -634,10 +682,6 @@ static void __init p852_uart_init(void)
}
}
-static struct platform_device generic_codec_driver = {
- .name = "generic-dit",
-};
-
static void __init p852_flash_init(void)
{
if (p852_sku_peripherals & P852_SKU_NAND_ENABLE)
diff --git a/arch/arm/mach-tegra/p852/board-p852.h b/arch/arm/mach-tegra/p852/board-p852.h
index bb43febb4a2c..8e8f1444029c 100644
--- a/arch/arm/mach-tegra/p852/board-p852.h
+++ b/arch/arm/mach-tegra/p852/board-p852.h
@@ -55,7 +55,6 @@
#include "../pm.h"
#include "../devices.h"
#include "../gpio-names.h"
-#include "../wakeups-t2.h"
#define P852_SKU3 0x030000UL
diff --git a/arch/arm/mach-tegra/pcie.c b/arch/arm/mach-tegra/pcie.c
index 22e60d56f3ca..ec386a51721c 100644
--- a/arch/arm/mach-tegra/pcie.c
+++ b/arch/arm/mach-tegra/pcie.c
@@ -36,6 +36,8 @@
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
+#include <linux/workqueue.h>
+#include <linux/gpio.h>
#include <asm/sizes.h>
#include <asm/mach/pci.h>
@@ -48,51 +50,6 @@
#define MSELECT_CONFIG_0_ENABLE_PCIE_APERTURE 5
-#define PINMUX_AUX_PEX_L0_RST_N_0 0x33bc
-#define PINMUX_AUX_PEX_L0_RST_N_0_E_INPUT 5
-#define PINMUX_AUX_PEX_L0_RST_N_0_E_INPUT_ENABLE 1
-
-#define PINMUX_AUX_PEX_L1_RST_N_0 0x33cc
-#define PINMUX_AUX_PEX_L1_RST_N_0_E_INPUT 5
-#define PINMUX_AUX_PEX_L1_RST_N_0_E_INPUT_ENABLE 1
-
-#define PINMUX_AUX_PEX_L2_RST_N_0 0x33d8
-#define PINMUX_AUX_PEX_L2_RST_N_0_E_INPUT 5
-#define PINMUX_AUX_PEX_L2_RST_N_0_E_INPUT_ENABLE 1
-#define AFI_PEX0_CTRL_0_PEX0_CLKREQ_EN 1
-#define NV_PCIE2_PADS_REFCLK_CFG1 0x000000cc
-#define APBDEV_PMC_SCRATCH42_0_PCX_CLAMP_MASK 0x1
-
-
-#define AFI_MSI_VEC0_0 0x6c
-#define AFI_MSI_VEC1_0 0x70
-#define AFI_MSI_VEC2_0 0x74
-#define AFI_MSI_VEC3_0 0x78
-#define AFI_MSI_VEC4_0 0x7c
-#define AFI_MSI_VEC5_0 0x80
-#define AFI_MSI_VEC6_0 0x84
-#define AFI_MSI_VEC7_0 0x88
-
-#define AFI_MSI_EN_VEC0_0 0x8c
-#define AFI_MSI_EN_VEC1_0 0x90
-#define AFI_MSI_EN_VEC2_0 0x94
-#define AFI_MSI_EN_VEC3_0 0x98
-#define AFI_MSI_EN_VEC4_0 0x9c
-#define AFI_MSI_EN_VEC5_0 0xa0
-#define AFI_MSI_EN_VEC6_0 0xa4
-#define AFI_MSI_EN_VEC7_0 0xa8
-
-#define AFI_MSI_FPCI_BAR_ST_0 0x64
-#define AFI_MSI_BAR_SZ_0 0x60
-#define AFI_MSI_AXI_BAR_ST_0 0x68
-#define AFI_INTR_MASK_0 0xb4
-#define AFI_INTR_MASK_0_INT_MASK 0
-#define AFI_INTR_MASK_0_MSI_MASK 8
-
-
-#define AFI_PEXBIAS_CTRL_0 0x168
-
-
/* register definitions */
#define AFI_OFFSET 0x3800
#define PADS_OFFSET 0x3000
@@ -128,6 +85,24 @@
#define AFI_MSI_FPCI_BAR_ST 0x64
#define AFI_MSI_AXI_BAR_ST 0x68
+#define AFI_MSI_VEC0_0 0x6c
+#define AFI_MSI_VEC1_0 0x70
+#define AFI_MSI_VEC2_0 0x74
+#define AFI_MSI_VEC3_0 0x78
+#define AFI_MSI_VEC4_0 0x7c
+#define AFI_MSI_VEC5_0 0x80
+#define AFI_MSI_VEC6_0 0x84
+#define AFI_MSI_VEC7_0 0x88
+
+#define AFI_MSI_EN_VEC0_0 0x8c
+#define AFI_MSI_EN_VEC1_0 0x90
+#define AFI_MSI_EN_VEC2_0 0x94
+#define AFI_MSI_EN_VEC3_0 0x98
+#define AFI_MSI_EN_VEC4_0 0x9c
+#define AFI_MSI_EN_VEC5_0 0xa0
+#define AFI_MSI_EN_VEC6_0 0xa4
+#define AFI_MSI_EN_VEC7_0 0xa8
+
#define AFI_CONFIGURATION 0xac
#define AFI_CONFIGURATION_EN_FPCI (1 << 0)
@@ -138,19 +113,19 @@
#define AFI_INTR_MASK_MSI_MASK (1 << 8)
#define AFI_INTR_CODE 0xb8
-#define AFI_INTR_CODE_MASK 0xf
-#define AFI_INTR_MASTER_ABORT 4
-#define AFI_INTR_LEGACY 6
+#define AFI_INTR_CODE_MASK 0xf
+#define AFI_INTR_MASTER_ABORT 4
+#define AFI_INTR_LEGACY 6
#define AFI_INTR_SIGNATURE 0xbc
#define AFI_SM_INTR_ENABLE 0xc4
#define AFI_AFI_INTR_ENABLE 0xc8
-#define AFI_INTR_EN_INI_SLVERR (1 << 0)
-#define AFI_INTR_EN_INI_DECERR (1 << 1)
-#define AFI_INTR_EN_TGT_SLVERR (1 << 2)
-#define AFI_INTR_EN_TGT_DECERR (1 << 3)
-#define AFI_INTR_EN_TGT_WRERR (1 << 4)
+#define AFI_INTR_EN_INI_SLVERR (1 << 0)
+#define AFI_INTR_EN_INI_DECERR (1 << 1)
+#define AFI_INTR_EN_TGT_SLVERR (1 << 2)
+#define AFI_INTR_EN_TGT_DECERR (1 << 3)
+#define AFI_INTR_EN_TGT_WRERR (1 << 4)
#define AFI_INTR_EN_DFPCI_DECERR (1 << 5)
#define AFI_INTR_EN_AXI_DECERR (1 << 6)
#define AFI_INTR_EN_FPCI_TIMEOUT (1 << 7)
@@ -172,8 +147,11 @@
#define AFI_PEX1_CTRL 0x118
#define AFI_PEX2_CTRL 0x128
#define AFI_PEX_CTRL_RST (1 << 0)
+#define AFI_PEX_CTRL_CLKREQ_EN (1 << 1)
#define AFI_PEX_CTRL_REFCLK_EN (1 << 3)
+#define AFI_PEXBIAS_CTRL_0 0x168
+
#define RP_VEND_XP 0x00000F00
#define RP_VEND_XP_DL_UP (1 << 30)
@@ -203,6 +181,8 @@
#define PADS_PLL_CTL_TXCLKREF_DIV10 (0 << 20)
#define PADS_PLL_CTL_TXCLKREF_DIV5 (1 << 20)
+#define PADS_REFCLK_CFG1 0x000000CC
+
/* PMC access is required for PCIE xclk (un)clamping */
#define PMC_SCRATCH42 0x144
#define PMC_SCRATCH42_PCX_CLAMP (1 << 0)
@@ -211,6 +191,9 @@
#define PCIE2_RP_PRIV_MISC_CTLR_CLK_CLAMP_ENABLE 1 << 23
#define PCIE2_RP_PRIV_MISC_TMS_CLK_CLAMP_ENABLE 1 << 31
+#define NV_PCIE2_RP_VEND_XP1 0x00000F04
+#define NV_PCIE2_RP_VEND_XP1_LINK_PVT_CTL_L1_ASPM_SUPPORT_ENABLE 1 << 21
+
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
/*
* Tegra2 defines 1GB in the AXI address map for PCIe.
@@ -280,7 +263,7 @@
*/
#define PCIE_IOMAP_SZ (PCIE_REGS_SZ + PCIE_CFG_SZ + PCIE_EXT_CFG_SZ)
-#define MMIO_BASE (TEGRA_PCIE_BASE + SZ_48M)
+#define MMIO_BASE (TEGRA_PCIE_BASE + PCIE_IOMAP_SZ)
#define MMIO_SIZE SZ_1M
#define MEM_BASE_0 (TEGRA_PCIE_BASE + SZ_256M)
#define MEM_SIZE SZ_256M
@@ -308,6 +291,7 @@ struct tegra_pcie_port {
char mem_space_name[16];
char prefetch_space_name[20];
struct resource res[3];
+ struct pci_bus* bus;
};
struct tegra_pcie_info {
@@ -319,6 +303,7 @@ struct tegra_pcie_info {
struct resource res_mmio;
int power_rails_enabled;
int pcie_power_enabled;
+ struct work_struct hotplug_detect;
struct regulator *regulator_hvdd;
struct regulator *regulator_pexio;
@@ -333,8 +318,6 @@ struct tegra_pcie_info {
#define pmc_readl(reg) \
__raw_readl((u32)reg_pmc_base + (reg))
-static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
-
static struct tegra_pcie_info tegra_pcie = {
.res_mmio = {
.name = "PCI IO",
@@ -350,14 +333,11 @@ static struct resource pcie_prefetch_mem_space;
/* disable read write while noirq operation
* is performed since pcie is powered off */
static bool is_pcie_noirq_op = false;
-/* used to backup config space registers of all pcie devices */
-static u32 *pbackup_config_space = NULL;
-static u16 *pbackup_pcie_cap_space = NULL;
-static u16 *pbackup_pcix_cap_space = NULL;
-/* use same save state and position variables to store pcie */
-/* and pcix capability offsets at even & odd index respectively */
-static struct pci_cap_saved_state **pcie_save_state;
-static int *pos;
+/* enable and init msi once during boot or resume */
+static bool msi_enable;
+/* this flag is used for enumeration by hotplug */
+/* when dock is not connected while system boot */
+static bool is_dock_conn_at_boot = true;
void __iomem *tegra_pcie_io_base;
EXPORT_SYMBOL(tegra_pcie_io_base);
@@ -549,7 +529,7 @@ static void __devinit tegra_pcie_relax_enable(struct pci_dev *dev)
}
DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, tegra_pcie_relax_enable);
-static void __init tegra_pcie_preinit(void)
+static void tegra_pcie_preinit(void)
{
pcie_io_space.name = "PCIe I/O Space";
pcie_io_space.start = PCIBIOS_MIN_IO;
@@ -620,6 +600,83 @@ static struct hw_pci tegra_pcie_hw = {
.map_irq = tegra_pcie_map_irq,
};
+#ifdef CONFIG_PM
+static int tegra_pcie_suspend(struct device *dev);
+static int tegra_pcie_resume(struct device *dev);
+
+/* It enumerates the devices when dock is connected after system boot */
+/* this is similar to pcibios_init_hw in bios32.c */
+static void tegra_pcie_hotplug_init(void)
+{
+ struct pci_sys_data *sys = NULL;
+ int ret, nr;
+
+ if (is_dock_conn_at_boot)
+ return;
+
+ tegra_pcie_preinit();
+ for (nr = 0; nr < tegra_pcie_hw.nr_controllers; nr++) {
+ sys = kzalloc(sizeof(struct pci_sys_data), GFP_KERNEL);
+ if (!sys)
+ panic("PCI: unable to allocate sys data!");
+
+#ifdef CONFIG_PCI_DOMAINS
+ sys->domain = tegra_pcie_hw.domain;
+#endif
+ sys->hw = &tegra_pcie_hw;
+ sys->busnr = nr;
+ sys->swizzle = tegra_pcie_hw.swizzle;
+ sys->map_irq = tegra_pcie_hw.map_irq;
+ sys->resource[0] = &ioport_resource;
+ sys->resource[1] = &iomem_resource;
+ ret = tegra_pcie_setup(nr, sys);
+ if (ret > 0)
+ pci_create_bus(NULL, nr, &tegra_pcie_ops, sys);
+ }
+ is_dock_conn_at_boot = true;
+}
+#endif
+
+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
+}
+
+static void tegra_pcie_detach(void)
+{
+#ifdef CONFIG_PM
+ tegra_pcie_suspend(NULL);
+#endif
+}
+
+static void work_hotplug_handler(struct work_struct *work)
+{
+ struct tegra_pcie_info *pcie_driver =
+ container_of(work, struct tegra_pcie_info, hotplug_detect);
+ int val;
+
+ if (pcie_driver->plat_data->gpio == -1)
+ return;
+ val = gpio_get_value(pcie_driver->plat_data->gpio);
+ if (val == 0) {
+ pr_info("Pcie Dock Connected\n");
+ tegra_pcie_attach();
+ } else {
+ pr_info("Pcie Dock DisConnected\n");
+ tegra_pcie_detach();
+ }
+}
+
+static irqreturn_t gpio_pcie_detect_isr(int irq, void *arg)
+{
+ schedule_work(&tegra_pcie.hotplug_detect);
+ return IRQ_HANDLED;
+}
static irqreturn_t tegra_pcie_isr(int irq, void *arg)
{
@@ -735,11 +792,9 @@ static void tegra_pcie_enable_controller(void)
{
u32 val, reg;
int i;
- void __iomem *reg_apb_misc_base;
void __iomem *reg_mselect_base;
- reg_apb_misc_base = IO_ADDRESS(TEGRA_APB_MISC_BASE);
- reg_mselect_base = IO_ADDRESS(TEGRA_MSELECT_BASE);
+ reg_mselect_base = IO_ADDRESS(TEGRA_MSELECT_BASE);
/* select the PCIE APERTURE in MSELECT config */
reg = readl(reg_mselect_base);
reg |= 1 << MSELECT_CONFIG_0_ENABLE_PCIE_APERTURE;
@@ -748,8 +803,7 @@ static void tegra_pcie_enable_controller(void)
/* Enable slot clock and pulse the reset signals */
for (i = 0, reg = AFI_PEX0_CTRL; i < MAX_PCIE_SUPPORTED_PORTS;
i++, reg += (i*8)) {
- val = afi_readl(reg) | AFI_PEX_CTRL_REFCLK_EN |
- (1 << AFI_PEX0_CTRL_0_PEX0_CLKREQ_EN);
+ val = afi_readl(reg) | AFI_PEX_CTRL_CLKREQ_EN | AFI_PEX_CTRL_REFCLK_EN;
afi_writel(val, reg);
val &= ~AFI_PEX_CTRL_RST;
afi_writel(val, reg);
@@ -759,7 +813,8 @@ static void tegra_pcie_enable_controller(void)
}
afi_writel(0, AFI_PEXBIAS_CTRL_0);
- /* Enable dual controller and both ports */
+ /* Enable all PCIE controller and */
+ /* system management configuration of PCIE crossbar */
val = afi_readl(AFI_PCIE_CONFIG);
val &= ~(AFI_PCIE_CONFIG_PCIEC0_DISABLE_DEVICE |
AFI_PCIE_CONFIG_PCIEC1_DISABLE_DEVICE |
@@ -772,6 +827,7 @@ static void tegra_pcie_enable_controller(void)
#endif
afi_writel(val, AFI_PCIE_CONFIG);
+ /* Disable Gen 2 capability of PCIE */
val = afi_readl(AFI_FUSE) & ~AFI_FUSE_PCIE_T0_GEN2_DIS;
afi_writel(val, AFI_FUSE);
@@ -784,15 +840,15 @@ static void tegra_pcie_enable_controller(void)
/*
* set up PHY PLL inputs select PLLE output as refclock,
- * set TX ref sel to div10 (not div5)
+ * set pll TX clock ref to div10 (not div5)
+ * set pll ref clock buf to enable.
*/
val = pads_readl(PADS_PLL_CTL);
val &= ~(PADS_PLL_CTL_REFCLK_MASK | PADS_PLL_CTL_TXCLKREF_MASK);
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
val |= (PADS_PLL_CTL_REFCLK_INTERNAL_CML | PADS_PLL_CTL_TXCLKREF_DIV10);
#else
- val |= (PADS_PLL_CTL_REFCLK_INTERNAL_CML |
- PADS_PLL_CTL_TXCLKREF_BUF_EN);
+ val |= (PADS_PLL_CTL_REFCLK_INTERNAL_CML | PADS_PLL_CTL_TXCLKREF_BUF_EN);
#endif
pads_writel(val, PADS_PLL_CTL);
@@ -805,7 +861,7 @@ static void tegra_pcie_enable_controller(void)
* This doesn't exist in the documentation
*/
pads_writel(0xfa5cfa5c, 0xc8);
- pads_writel(0x0000FA5C, NV_PCIE2_PADS_REFCLK_CFG1);
+ pads_writel(0x0000FA5C, PADS_REFCLK_CFG1);
/* Wait for the PLL to lock */
do {
@@ -844,7 +900,7 @@ static void tegra_pcie_enable_controller(void)
return;
}
-static int tegra_pci_enable_regulators(void)
+static int tegra_pcie_enable_regulators(void)
{
if (tegra_pcie.power_rails_enabled)
return 0;
@@ -897,7 +953,7 @@ static int tegra_pci_enable_regulators(void)
return 0;
}
-static int tegra_pci_disable_regulators(void)
+static int tegra_pcie_disable_regulators(void)
{
int err = 0;
if (tegra_pcie.power_rails_enabled == 0)
@@ -917,24 +973,36 @@ err_exit:
return err;
}
+static int tegra_pcie_power_regate(void)
+{
+ int err;
+ err = tegra_unpowergate_partition_with_clk_on(TEGRA_POWERGATE_PCIE);
+ if (err) {
+ pr_err("PCIE: powerup sequence failed: %d\n", err);
+ return err;
+ }
+ tegra_periph_reset_assert(tegra_pcie.pcie_xclk);
+ return clk_enable(tegra_pcie.pll_e);
+}
+
+#ifdef CONFIG_PM
static int tegra_pcie_power_on(void)
{
int err = 0;
if (tegra_pcie.pcie_power_enabled)
return 0;
- err = tegra_pci_enable_regulators();
+ err = tegra_pcie_enable_regulators();
if (err)
goto err_exit;
- err = tegra_unpowergate_partition_with_clk_on(TEGRA_POWERGATE_PCIE);
+ err = tegra_pcie_power_regate();
if (err)
goto err_exit;
- if (tegra_pcie.pll_e)
- clk_enable(tegra_pcie.pll_e);
tegra_pcie.pcie_power_enabled = 1;
err_exit:
return err;
}
+#endif
static int tegra_pcie_power_off(void)
{
@@ -948,25 +1016,13 @@ static int tegra_pcie_power_off(void)
if (err)
goto err_exit;
- err = tegra_pci_disable_regulators();
+ err = tegra_pcie_disable_regulators();
tegra_pcie.pcie_power_enabled = 0;
err_exit:
return err;
}
-static int tegra_pcie_power_regate(void)
-{
- int err;
- err = tegra_unpowergate_partition_with_clk_on(TEGRA_POWERGATE_PCIE);
- if (err) {
- pr_err("PCIE: powerup sequence failed: %d\n", err);
- return err;
- }
- tegra_periph_reset_assert(tegra_pcie.pcie_xclk);
- return clk_enable(tegra_pcie.pll_e);
-}
-
static int tegra_pcie_clocks_get(void)
{
/* reset the PCIEXCLK */
@@ -999,8 +1055,9 @@ static int tegra_pcie_get_resources(void)
{
struct resource *res_mmio = 0;
int err;
+
tegra_pcie.power_rails_enabled = 0;
- err = tegra_pci_enable_regulators();
+ err = tegra_pcie_enable_regulators();
if (err) {
pr_err("PCIE: failed to enable power rails %d\n", err);
goto err_pwr_on_rail;
@@ -1019,6 +1076,7 @@ static int tegra_pcie_get_resources(void)
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");
@@ -1033,6 +1091,7 @@ static int tegra_pcie_get_resources(void)
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) {
@@ -1062,7 +1121,7 @@ err_map_reg:
err_pwr_on:
tegra_pcie_clocks_put();
err_pwr_on_rail:
- tegra_pci_disable_regulators();
+ tegra_pcie_disable_regulators();
return err;
}
@@ -1108,19 +1167,20 @@ static bool tegra_pcie_check_link(struct tegra_pcie_port *pp, int idx,
}
retry:
- /* Pulse the PEX reset */
- reg = afi_readl(reset_reg) & ~AFI_PEX_CTRL_RST;
- afi_writel(reg, reset_reg);
- reg = afi_readl(reset_reg) | AFI_PEX_CTRL_RST;
- afi_writel(reg, reset_reg);
+ if (--retries) {
+ /* Pulse the PEX reset */
+ reg = afi_readl(reset_reg) & ~AFI_PEX_CTRL_RST;
+ afi_writel(reg, reset_reg);
+ reg = afi_readl(reset_reg) | AFI_PEX_CTRL_RST;
+ afi_writel(reg, reset_reg);
+ }
- retries--;
} while (retries);
return false;
}
-static void tegra_enable_clock_clamp(int index)
+static void tegra_pcie_enable_clock_clamp(int index)
{
unsigned int data;
@@ -1132,6 +1192,16 @@ static void tegra_enable_clock_clamp(int index)
rp_writel(data, NV_PCIE2_RP_PRIV_MISC, index);
}
+static void tegra_pcie_enable_aspm_l1_support(int index)
+{
+ unsigned int data;
+
+ /* Enable ASPM - L1 state support by default */
+ data = rp_readl(NV_PCIE2_RP_VEND_XP1, index);
+ data |= (NV_PCIE2_RP_VEND_XP1_LINK_PVT_CTL_L1_ASPM_SUPPORT_ENABLE);
+ rp_writel(data, NV_PCIE2_RP_VEND_XP1, index);
+}
+
static void tegra_pcie_add_port(int index, u32 offset, u32 reset_reg)
{
struct tegra_pcie_port *pp;
@@ -1147,10 +1217,10 @@ static void tegra_pcie_add_port(int index, u32 offset, u32 reset_reg)
printk(KERN_INFO "PCIE: port %d: link down, ignoring\n", index);
return;
}
- tegra_enable_clock_clamp(index);
+ tegra_pcie_enable_clock_clamp(index);
+ tegra_pcie_enable_aspm_l1_support(index);
tegra_pcie.num_ports++;
pp->index = index;
- pp->root_bus_nr = -1;
memset(pp->res, 0, sizeof(pp->res));
}
@@ -1168,6 +1238,8 @@ static int tegra_pcie_init(void)
pcibios_min_mem = 0x03000000ul;
pcibios_min_io = 0x10000000ul;
#endif
+
+ INIT_WORK(&tegra_pcie.hotplug_detect, work_hotplug_handler);
err = tegra_pcie_get_resources();
if (err)
return err;
@@ -1177,61 +1249,51 @@ static int tegra_pcie_init(void)
tegra_pcie_setup_translations();
for (port = 0; port < MAX_PCIE_SUPPORTED_PORTS; port++) {
ctrl_offset += (port * 8);
- rp_offset = (rp_offset + 0x1000) * port;
+ rp_offset = (rp_offset + RP_OFFSET) * port;
if (tegra_pcie.plat_data->port_status[port])
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;
+
+ pr_info("acquiring dock_detect = %d\n",
+ tegra_pcie.plat_data->gpio);
+ gpio_request(tegra_pcie.plat_data->gpio, "pcie_dock_detect");
+ gpio_direction_input(tegra_pcie.plat_data->gpio);
+ irq = gpio_to_irq(tegra_pcie.plat_data->gpio);
+ if (irq < 0) {
+ pr_err("Unable to get irq number for dock_detect\n");
+ goto err_irq;
+ }
+ err = request_irq(irq,
+ gpio_pcie_detect_isr,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ "pcie_dock_detect",
+ (void *)tegra_pcie.plat_data);
+ if (err < 0) {
+ pr_err("Unable to claim irq number for dock_detect\n");
+ goto err_irq;
+ }
+ }
+
if (tegra_pcie.num_ports)
pci_common_init(&tegra_pcie_hw);
- else
+ else {
+ /* no dock is connected, hotplug will occur after boot */
err = tegra_pcie_power_off();
+ is_dock_conn_at_boot = false;
+ }
- return err;
-}
-
-static int tegra_pcie_allocate_config_states(int ndev, int size)
-{
- /* backup config space registers of all devices since it gets reset in
- save state call from suspend noirq due to disabling of read in it */
- pbackup_config_space = kzalloc(ndev*size*sizeof(u32), GFP_KERNEL);
- if (!pbackup_config_space)
- return -ENODEV;
- pbackup_pcie_cap_space = kzalloc(ndev*PCIE_CTRL_REGS*sizeof(u16), GFP_KERNEL);
- if (!pbackup_pcie_cap_space)
- return -ENODEV;
- pbackup_pcix_cap_space = kzalloc(ndev*sizeof(u16), GFP_KERNEL);
- if (!pbackup_pcix_cap_space)
- return -ENODEV;
- pcie_save_state = kzalloc(COMBINE_PCIE_PCIX_SPACE*ndev*
- sizeof(struct pci_cap_saved_state*), GFP_KERNEL);
- if (!pbackup_pcix_cap_space)
- return -ENODEV;
- pos = kzalloc(COMBINE_PCIE_PCIX_SPACE*ndev*sizeof(int), GFP_KERNEL);
- if (!pos)
- return -ENODEV;
-
- return 0;
-}
+err_irq:
-static void tegra_pcie_deallocate_config_states(void)
-{
- if (pbackup_config_space)
- kzfree(pbackup_config_space);
- if (pbackup_pcie_cap_space)
- kzfree(pbackup_pcie_cap_space);
- if (pbackup_pcix_cap_space)
- kzfree(pbackup_pcix_cap_space);
- if (pcie_save_state)
- kzfree(pcie_save_state);
- if (pos)
- kzfree(pos);
+ return err;
}
-static int tegra_pci_probe(struct platform_device *pdev)
+static int tegra_pcie_probe(struct platform_device *pdev)
{
- int ret, size = 0, ndev = 0;
+ int ret;
struct pci_dev *dev = NULL;
tegra_pcie.plat_data = pdev->dev.platform_data;
@@ -1245,92 +1307,24 @@ static int tegra_pci_probe(struct platform_device *pdev)
/* disable async PM of pci devices to ensure right order */
/* suspend/resume calls of tegra and bus driver */
- for_each_pci_dev(dev){
+ for_each_pci_dev(dev)
device_disable_async_suspend(&dev->dev);
- size = sizeof(dev->saved_config_space) / sizeof(u32);
- ndev++;
- }
- tegra_pcie_allocate_config_states(ndev, size);
return ret;
}
-static int tegra_pcie_save_state(struct pci_dev *pdev, int ndev)
-{
- int size;
-
- /*save pcie control registers */
- pos[ndev] = pci_pcie_cap(pdev);
- if (pos[ndev]){
- pcie_save_state[ndev] = pci_find_saved_cap(pdev, PCI_CAP_ID_EXP);
- if (!pcie_save_state[ndev]) {
- dev_err(&pdev->dev, "buffer not found in %s\n", __func__);
- return -ENOMEM;
- }
- memcpy(&pbackup_pcie_cap_space[PCIE_CTRL_REGS*(ndev/2)],
- pcie_save_state[ndev]->cap.data, PCIE_CTRL_REGS*sizeof(u16));
- }
- /* save pcix state */
- pos[ndev+1] = pci_find_capability(pdev, PCI_CAP_ID_PCIX);
- if (pos[ndev+1] > 0){
- pcie_save_state[ndev+1] = pci_find_saved_cap(pdev, PCI_CAP_ID_PCIX);
- if (!pcie_save_state[ndev+1]) {
- dev_err(&pdev->dev, "buffer not found in %s\n", __func__);
- return -ENOMEM;
- }
- memcpy(&pbackup_pcix_cap_space[ndev/2],
- pcie_save_state[ndev+1]->cap.data, sizeof(u16));
- }
- /* save config space registers */
- size = sizeof(pdev->saved_config_space) / sizeof(u32);
- memcpy(&pbackup_config_space[size*ndev/2],
- pdev->saved_config_space, size*sizeof(u32));
-
- return 0;
-}
-
-static void tegra_pcie_restore_state(struct pci_dev *pdev, int ndev)
-{
- int size;
-
- /* restore pcie control registers */
- if (pcie_save_state[ndev] && (pos[ndev] > 0))
- memcpy(pcie_save_state[ndev]->cap.data,
- &pbackup_pcie_cap_space[PCIE_CTRL_REGS*(ndev/2)],
- PCIE_CTRL_REGS*sizeof(u16));
-
- /* restore pcix state */
- if (pcie_save_state[ndev+1] && (pos[ndev+1] > 0))
- memcpy(pcie_save_state[ndev+1]->cap.data,
- &pbackup_pcix_cap_space[ndev/2], sizeof(u16));
-
- /* restore config space registers */
- size = sizeof(pdev->saved_config_space) / sizeof(u32);
- memcpy(pdev->saved_config_space,
- &pbackup_config_space[size*ndev/2], size*sizeof(u32));
-}
-
-static int tegra_pci_suspend(struct device *dev)
+#ifdef CONFIG_PM
+static int tegra_pcie_suspend(struct device *dev)
{
- int ret = 0, ndev = 0;
+ int ret = 0;
struct pci_dev *pdev = NULL;
if (!tegra_pcie.num_ports)
return ret;
for_each_pci_dev(pdev) {
- /* save state of pcie devices before powering off regulators */
- pci_save_state(pdev);
- if (!pdev->subordinate)
- pci_prepare_to_sleep(pdev);
- }
-
- for_each_pci_dev(pdev) {
- /* save control and config space registers*/
- ret = tegra_pcie_save_state(pdev, ndev*2);
- if (ret < 0)
- return ret;
- ndev++;
+ pci_remove_bus_device(pdev);
+ break;
}
/* disable read/write registers before powering off */
@@ -1338,83 +1332,110 @@ static int tegra_pci_suspend(struct device *dev)
return tegra_pcie_power_off();
}
-static int tegra_pci_resume_noirq(struct device *dev)
-{
- struct pci_dev *pdev = NULL;
- /* set this flag to avoid restore state in resume noirq */
- for_each_pci_dev(pdev)
- pdev->state_saved = 0;
-
- return 0;
+static void tegra_pcie_set_irq(struct pci_bus *bus)
+{
+ struct pci_bus *b;
+ struct pci_dev *pdev;
+
+ list_for_each_entry(pdev, &bus->devices, bus_list) {
+ b = pdev->subordinate;
+ if (!b) {
+ pdev->irq = tegra_pcie_map_irq(pdev,0,0);
+ pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, pdev->irq);
+ continue;
+ }
+ tegra_pcie_set_irq(b);
+ pdev->irq = tegra_pcie_map_irq(pdev,0,0);
+ pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, pdev->irq);
+ }
}
-static int tegra_pci_resume(struct device *dev)
+static int tegra_pcie_resume(struct device *dev)
{
- int ret = 0, ndev = 0;
- struct pci_dev *pdev = NULL;
- int port;
+ int ret = 0;
+ struct pci_bus *bus = NULL;
+ int port, rp_offset = 0;
+ int ctrl_offset = AFI_PEX0_CTRL;
if (!tegra_pcie.num_ports)
return ret;
+
ret = tegra_pcie_power_on();
/* enable read/write registers after powering on */
is_pcie_noirq_op = false;
tegra_pcie_enable_controller();
tegra_pcie_setup_translations();
+ msi_enable = false;
- for (port = 0; port < MAX_PCIE_SUPPORTED_PORTS; port++)
+ /* 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_enable_clock_clamp(port);
+ tegra_pcie_add_port(port, rp_offset, ctrl_offset);
+ }
- for_each_pci_dev(pdev) {
- /* restore control and config space registers*/
- tegra_pcie_restore_state(pdev, ndev*2);
- /* set this flag to force restore state in resume */
- pdev->state_saved = 1;
- ndev++;
+ tegra_pcie_hotplug_init();
+ while ((bus = pci_find_next_bus(bus)) != NULL) {
+ struct pci_dev *dev;
+
+ pci_scan_child_bus(bus);
+
+ list_for_each_entry(dev, &bus->devices, bus_list)
+ if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
+ dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
+ if (dev->subordinate)
+ pci_bus_size_bridges(dev->subordinate);
+
+ /* set irq for all devices */
+ tegra_pcie_set_irq(bus);
+ pci_bus_assign_resources(bus);
+ pci_enable_bridges(bus);
+ pci_bus_add_devices(bus);
}
return ret;
}
+#endif
-static int tegra_pci_remove(struct platform_device *pdev)
+static int tegra_pcie_remove(struct platform_device *pdev)
{
- tegra_pcie_deallocate_config_states();
return 0;
}
+
#ifdef CONFIG_PM
-static const struct dev_pm_ops tegra_pci_pm_ops = {
- .suspend = tegra_pci_suspend,
- .resume = tegra_pci_resume,
- .resume_noirq = tegra_pci_resume_noirq,
+static const struct dev_pm_ops tegra_pcie_pm_ops = {
+ .suspend = tegra_pcie_suspend,
+ .resume = tegra_pcie_resume,
};
#endif
-static struct platform_driver tegra_pci_driver = {
- .probe = tegra_pci_probe,
- .remove = tegra_pci_remove,
+static struct platform_driver tegra_pcie_driver = {
+ .probe = tegra_pcie_probe,
+ .remove = tegra_pcie_remove,
.driver = {
.name = "tegra-pcie",
.owner = THIS_MODULE,
#ifdef CONFIG_PM
- .pm = &tegra_pci_pm_ops,
+ .pm = &tegra_pcie_pm_ops,
#endif
},
};
-static int __init tegra_pci_init_driver(void)
+static int __init tegra_pcie_init_driver(void)
{
- return platform_driver_register(&tegra_pci_driver);
+ return platform_driver_register(&tegra_pcie_driver);
}
-static void __exit tegra_pci_exit_driver(void)
+static void __exit tegra_pcie_exit_driver(void)
{
- platform_driver_unregister(&tegra_pci_driver);
+ platform_driver_unregister(&tegra_pcie_driver);
}
-module_init(tegra_pci_init_driver);
-module_exit(tegra_pci_exit_driver);
+module_init(tegra_pcie_init_driver);
+module_exit(tegra_pcie_exit_driver);
static struct irq_chip tegra_irq_chip_msi_pcie = {
.name = "PCIe-MSI",
@@ -1478,7 +1499,7 @@ void msi_map_release(struct msi_map_entry *entry)
}
}
-static irqreturn_t pci_tegra_msi_isr(int irq, void *arg)
+static irqreturn_t tegra_pcie_msi_isr(int irq, void *arg)
{
int i;
int offset;
@@ -1510,31 +1531,28 @@ static irqreturn_t pci_tegra_msi_isr(int irq, void *arg)
return IRQ_HANDLED;
}
-static bool pci_tegra_enable_msi(void)
+static bool tegra_pcie_enable_msi(void)
{
bool retval = false;
- static bool already_done;
u32 reg;
u32 msi_base = 0;
u32 msi_aligned = 0;
- /* enables MSI interrupts. */
/* this only happens once. */
- if (already_done) {
+ if (msi_enable) {
retval = true;
goto exit;
}
-
msi_map_init();
- if (request_irq(INT_PCIE_MSI, pci_tegra_msi_isr,
+ /* enables MSI interrupts. */
+ if (request_irq(INT_PCIE_MSI, tegra_pcie_msi_isr,
IRQF_SHARED, "PCIe-MSI",
- pci_tegra_msi_isr)) {
+ tegra_pcie_msi_isr)) {
pr_err("%s: Cannot register IRQ %u\n",
__func__, INT_PCIE_MSI);
goto exit;
}
-
/* setup AFI/FPCI range */
/* FIXME do this better! should be based on PAGE_SIZE */
msi_base = __get_free_pages(GFP_KERNEL, 3);
@@ -1542,14 +1560,14 @@ static bool pci_tegra_enable_msi(void)
msi_aligned = virt_to_phys((void *)msi_aligned);
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- afi_writel(msi_aligned, AFI_MSI_FPCI_BAR_ST_0);
+ afi_writel(msi_aligned, AFI_MSI_FPCI_BAR_ST);
#else
/* different from T20!*/
- afi_writel(msi_aligned>>8, AFI_MSI_FPCI_BAR_ST_0);
+ afi_writel(msi_aligned>>8, AFI_MSI_FPCI_BAR_ST);
#endif
- afi_writel(msi_aligned, AFI_MSI_AXI_BAR_ST_0);
+ afi_writel(msi_aligned, AFI_MSI_AXI_BAR_ST);
/* this register is in 4K increments */
- afi_writel(1, AFI_MSI_BAR_SZ_0);
+ afi_writel(1, AFI_MSI_BAR_SZ);
/* enable all MSI vectors */
afi_writel(0xffffffff, AFI_MSI_EN_VEC0_0);
@@ -1563,13 +1581,12 @@ static bool pci_tegra_enable_msi(void)
/* and unmask the MSI interrupt */
reg = 0;
- reg |= ((1 << AFI_INTR_MASK_0_INT_MASK) |
- (1 << AFI_INTR_MASK_0_MSI_MASK));
- afi_writel(reg, AFI_INTR_MASK_0);
+ reg |= (AFI_INTR_MASK_INT_MASK | AFI_INTR_MASK_MSI_MASK);
+ afi_writel(reg, AFI_INTR_MASK);
set_irq_flags(INT_PCIE_MSI, IRQF_VALID);
- already_done = true;
+ msi_enable = true;
retval = true;
exit:
if (!retval) {
@@ -1587,7 +1604,7 @@ int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
struct msi_msg msg;
struct msi_map_entry *map_entry = NULL;
- if (!pci_tegra_enable_msi())
+ if (!tegra_pcie_enable_msi())
goto exit;
map_entry = msi_map_get();
@@ -1602,7 +1619,7 @@ int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
irq_set_msi_desc(map_entry->irq, desc);
set_irq_flags(map_entry->irq, IRQF_VALID);
- msg.address_lo = afi_readl(AFI_MSI_AXI_BAR_ST_0);
+ msg.address_lo = afi_readl(AFI_MSI_AXI_BAR_ST);
/* 32 bit address only */
msg.address_hi = 0;
msg.data = map_entry->index;
diff --git a/arch/arm/mach-tegra/pinmux-t2-tables.c b/arch/arm/mach-tegra/pinmux-t2-tables.c
index 3a39f45cb57e..32e55421c583 100644
--- a/arch/arm/mach-tegra/pinmux-t2-tables.c
+++ b/arch/arm/mach-tegra/pinmux-t2-tables.c
@@ -195,9 +195,9 @@ const struct tegra_drive_pingroup_desc tegra_soc_drive_pingroups[TEGRA_MAX_DRIVE
PINGROUP(LM0, PW0, LCD, DISPLAYA, DISPLAYB, SPI3, RSVD, RSVD4, 0x1C, 24, 0x90, 26, 0xAC, 22),\
PINGROUP(LM1, PW1, LCD, DISPLAYA, DISPLAYB, RSVD, CRT, RSVD3, 0x1C, 25, 0x90, 28, 0xAC, 22),\
PINGROUP(LPP, PM7, LCD, DISPLAYA, DISPLAYB, RSVD, RSVD, RSVD4, 0x20, 8, 0x98, 14, 0xAC, 18),\
- PINGROUP(LPW0, PB2, LCD, DISPLAYA, DISPLAYB, SPI3, HDMI, DISPLAYA, 0x20, 3, 0x90, 0, 0xAC, 20),\
+ PINGROUP(LPW0, PB2, LCD, DISPLAYA, DISPLAYB, SPI3, HDMI, DISPLAYB, 0x20, 3, 0x90, 0, 0xAC, 20),\
PINGROUP(LPW1, PC1, LCD, DISPLAYA, DISPLAYB, RSVD, RSVD, RSVD4, 0x20, 4, 0x90, 2, 0xAC, 20),\
- PINGROUP(LPW2, PC6, LCD, DISPLAYA, DISPLAYB, SPI3, HDMI, DISPLAYA, 0x20, 5, 0x90, 4, 0xAC, 20),\
+ PINGROUP(LPW2, PC6, LCD, DISPLAYA, DISPLAYB, SPI3, HDMI, DISPLAYB, 0x20, 5, 0x90, 4, 0xAC, 20),\
PINGROUP(LSC0, PB3, LCD, DISPLAYA, DISPLAYB, XIO, RSVD, RSVD4, 0x1C, 27, 0x90, 18, 0xAC, 22),\
PINGROUP(LSC1, PZ3, LCD, DISPLAYA, DISPLAYB, SPI3, HDMI, DISPLAYA, 0x1C, 28, 0x90, 20, 0xAC, 20),\
PINGROUP(LSCK, PZ4, LCD, DISPLAYA, DISPLAYB, SPI3, HDMI, DISPLAYA, 0x1C, 29, 0x90, 16, 0xAC, 20),\
diff --git a/arch/arm/mach-tegra/pinmux-t3-tables.c b/arch/arm/mach-tegra/pinmux-t3-tables.c
index 282a34bdd0d3..09729a4cfbae 100644
--- a/arch/arm/mach-tegra/pinmux-t3-tables.c
+++ b/arch/arm/mach-tegra/pinmux-t3-tables.c
@@ -3,7 +3,7 @@
*
* Common pinmux configurations for Tegra 3 SoCs
*
- * Copyright (C) 2010-2011 NVIDIA Corporation
+ * Copyright (c) 2010-2012, NVIDIA Corporation. 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
@@ -64,11 +64,16 @@
const struct tegra_drive_pingroup_desc tegra_soc_drive_pingroups[TEGRA_MAX_DRIVE_PINGROUP] = {
DEFAULT_DRIVE_PINGROUP(AO1, 0x868),
DEFAULT_DRIVE_PINGROUP(AO2, 0x86c),
- DEFAULT_DRIVE_PINGROUP(AT1, 0x870),
- DEFAULT_DRIVE_PINGROUP(AT2, 0x874),
- DEFAULT_DRIVE_PINGROUP(AT3, 0x878),
- DEFAULT_DRIVE_PINGROUP(AT4, 0x87c),
- DEFAULT_DRIVE_PINGROUP(AT5, 0x880),
+ SET_DRIVE_PINGROUP(AT1, 0x870, 14, 0x1f, 19, 0x1f,
+ 24, 0x3, 28, 0x3),
+ SET_DRIVE_PINGROUP(AT2, 0x874, 14, 0x1f, 19, 0x1f,
+ 24, 0x3, 28, 0x3),
+ SET_DRIVE_PINGROUP(AT3, 0x878, 14, 0x1f, 19, 0x1f,
+ 28, 0x3, 30, 0x3),
+ SET_DRIVE_PINGROUP(AT4, 0x87c, 14, 0x1f, 19, 0x1f,
+ 28, 0x3, 30, 0x3),
+ SET_DRIVE_PINGROUP(AT5, 0x880, 14, 0x1f, 19, 0x1f,
+ 28, 0x3, 30, 0x3),
DEFAULT_DRIVE_PINGROUP(CDEV1, 0x884),
DEFAULT_DRIVE_PINGROUP(CDEV2, 0x888),
DEFAULT_DRIVE_PINGROUP(CSUS, 0x88c),
@@ -101,10 +106,14 @@ const struct tegra_drive_pingroup_desc tegra_soc_drive_pingroups[TEGRA_MAX_DRIVE
24, 0xf, 28, 0xf),
SET_DRIVE_PINGROUP(GMD, 0x90c, 14, 0x1f, 19, 0x1f,
24, 0xf, 28, 0xf),
- DEFAULT_DRIVE_PINGROUP(GME, 0x910),
- DEFAULT_DRIVE_PINGROUP(GMF, 0x914),
- DEFAULT_DRIVE_PINGROUP(GMG, 0x918),
- DEFAULT_DRIVE_PINGROUP(GMH, 0x91c),
+ SET_DRIVE_PINGROUP(GME, 0x910, 14, 0x1f, 19, 0x1f,
+ 28, 0x3, 30, 0x3),
+ SET_DRIVE_PINGROUP(GMF, 0x914, 14, 0x1f, 19, 0x1f,
+ 28, 0x3, 30, 0x3),
+ SET_DRIVE_PINGROUP(GMG, 0x918, 14, 0x1f, 19, 0x1f,
+ 28, 0x3, 30, 0x3),
+ SET_DRIVE_PINGROUP(GMH, 0x91c, 14, 0x1f, 19, 0x1f,
+ 28, 0x3, 30, 0x3),
DEFAULT_DRIVE_PINGROUP(OWR, 0x920),
DEFAULT_DRIVE_PINGROUP(UAD, 0x924),
DEFAULT_DRIVE_PINGROUP(GPV, 0x928),
@@ -140,166 +149,166 @@ const struct tegra_drive_pingroup_desc tegra_soc_drive_pingroups[TEGRA_MAX_DRIVE
#define PINGROUPS \
/* NAME GPIO VDD f0 f1 f2 f3 fSafe io reg */\
- PINGROUP(ULPI_DATA0, PO1, BB, SPI3, HSI, UARTA, ULPI, RSVD, INPUT, 0x3000),\
- PINGROUP(ULPI_DATA1, PO2, BB, SPI3, HSI, UARTA, ULPI, RSVD, INPUT, 0x3004),\
- PINGROUP(ULPI_DATA2, PO3, BB, SPI3, HSI, UARTA, ULPI, RSVD, INPUT, 0x3008),\
- PINGROUP(ULPI_DATA3, PO4, BB, SPI3, HSI, UARTA, ULPI, RSVD, INPUT, 0x300c),\
- PINGROUP(ULPI_DATA4, PO5, BB, SPI2, HSI, UARTA, ULPI, RSVD, INPUT, 0x3010),\
- PINGROUP(ULPI_DATA5, PO6, BB, SPI2, HSI, UARTA, ULPI, RSVD, INPUT, 0x3014),\
- PINGROUP(ULPI_DATA6, PO7, BB, SPI2, HSI, UARTA, ULPI, RSVD, INPUT, 0x3018),\
- PINGROUP(ULPI_DATA7, PO0, BB, SPI2, HSI, UARTA, ULPI, RSVD, INPUT, 0x301c),\
- PINGROUP(ULPI_CLK, PY0, BB, SPI1, RSVD, UARTD, ULPI, RSVD, INPUT, 0x3020),\
- PINGROUP(ULPI_DIR, PY1, BB, SPI1, RSVD, UARTD, ULPI, RSVD, INPUT, 0x3024),\
- PINGROUP(ULPI_NXT, PY2, BB, SPI1, RSVD, UARTD, ULPI, RSVD, INPUT, 0x3028),\
- PINGROUP(ULPI_STP, PY3, BB, SPI1, RSVD, UARTD, ULPI, RSVD, INPUT, 0x302c),\
- PINGROUP(DAP3_FS, PP0, BB, I2S2, RSVD1, DISPLAYA, DISPLAYB, RSVD, INPUT, 0x3030),\
- PINGROUP(DAP3_DIN, PP1, BB, I2S2, RSVD1, DISPLAYA, DISPLAYB, RSVD, INPUT, 0x3034),\
- PINGROUP(DAP3_DOUT, PP2, BB, I2S2, RSVD1, DISPLAYA, DISPLAYB, RSVD, INPUT, 0x3038),\
- PINGROUP(DAP3_SCLK, PP3, BB, I2S2, RSVD1, DISPLAYA, DISPLAYB, RSVD, INPUT, 0x303c),\
+ PINGROUP(ULPI_DATA0, PO1, BB, SPI3, HSI, UARTA, ULPI, ULPI, INPUT, 0x3000),\
+ PINGROUP(ULPI_DATA1, PO2, BB, SPI3, HSI, UARTA, ULPI, ULPI, INPUT, 0x3004),\
+ PINGROUP(ULPI_DATA2, PO3, BB, SPI3, HSI, UARTA, ULPI, ULPI, INPUT, 0x3008),\
+ PINGROUP(ULPI_DATA3, PO4, BB, SPI3, HSI, UARTA, ULPI, ULPI, INPUT, 0x300c),\
+ PINGROUP(ULPI_DATA4, PO5, BB, SPI2, HSI, UARTA, ULPI, ULPI, INPUT, 0x3010),\
+ PINGROUP(ULPI_DATA5, PO6, BB, SPI2, HSI, UARTA, ULPI, ULPI, INPUT, 0x3014),\
+ PINGROUP(ULPI_DATA6, PO7, BB, SPI2, HSI, UARTA, ULPI, ULPI, INPUT, 0x3018),\
+ PINGROUP(ULPI_DATA7, PO0, BB, SPI2, HSI, UARTA, ULPI, ULPI, INPUT, 0x301c),\
+ PINGROUP(ULPI_CLK, PY0, BB, SPI1, RSVD, UARTD, ULPI, ULPI, INPUT, 0x3020),\
+ PINGROUP(ULPI_DIR, PY1, BB, SPI1, RSVD, UARTD, ULPI, ULPI, INPUT, 0x3024),\
+ PINGROUP(ULPI_NXT, PY2, BB, SPI1, RSVD, UARTD, ULPI, ULPI, INPUT, 0x3028),\
+ PINGROUP(ULPI_STP, PY3, BB, SPI1, RSVD, UARTD, ULPI, ULPI, INPUT, 0x302c),\
+ PINGROUP(DAP3_FS, PP0, BB, I2S2, RSVD1, DISPLAYA, DISPLAYB, I2S2, INPUT, 0x3030),\
+ PINGROUP(DAP3_DIN, PP1, BB, I2S2, RSVD1, DISPLAYA, DISPLAYB, I2S2, INPUT, 0x3034),\
+ PINGROUP(DAP3_DOUT, PP2, BB, I2S2, RSVD1, DISPLAYA, DISPLAYB, I2S2, INPUT, 0x3038),\
+ PINGROUP(DAP3_SCLK, PP3, BB, I2S2, RSVD1, DISPLAYA, DISPLAYB, I2S2, INPUT, 0x303c),\
PINGROUP(GPIO_PV0, PV0, BB, RSVD, RSVD, RSVD, RSVD, RSVD, INPUT, 0x3040),\
PINGROUP(GPIO_PV1, PV1, BB, RSVD, RSVD, RSVD, RSVD, RSVD, INPUT, 0x3044),\
- PINGROUP(SDMMC1_CLK, PZ0, SDMMC1, SDMMC1, RSVD1, RSVD2, INVALID, RSVD, INPUT, 0x3048),\
- PINGROUP(SDMMC1_CMD, PZ1, SDMMC1, SDMMC1, RSVD1, RSVD2, INVALID, RSVD, INPUT, 0x304c),\
- PINGROUP(SDMMC1_DAT3, PY4, SDMMC1, SDMMC1, RSVD1, UARTE, INVALID, RSVD, INPUT, 0x3050),\
- PINGROUP(SDMMC1_DAT2, PY5, SDMMC1, SDMMC1, RSVD1, UARTE, INVALID, RSVD, INPUT, 0x3054),\
- PINGROUP(SDMMC1_DAT1, PY6, SDMMC1, SDMMC1, RSVD1, UARTE, INVALID, RSVD, INPUT, 0x3058),\
- PINGROUP(SDMMC1_DAT0, PY7, SDMMC1, SDMMC1, RSVD1, UARTE, INVALID, RSVD, INPUT, 0x305c),\
+ PINGROUP(SDMMC1_CLK, PZ0, SDMMC1, SDMMC1, RSVD1, RSVD2, INVALID, SDMMC1, INPUT, 0x3048),\
+ PINGROUP(SDMMC1_CMD, PZ1, SDMMC1, SDMMC1, RSVD1, RSVD2, INVALID, SDMMC1, INPUT, 0x304c),\
+ PINGROUP(SDMMC1_DAT3, PY4, SDMMC1, SDMMC1, RSVD1, UARTE, INVALID, SDMMC1, INPUT, 0x3050),\
+ PINGROUP(SDMMC1_DAT2, PY5, SDMMC1, SDMMC1, RSVD1, UARTE, INVALID, SDMMC1, INPUT, 0x3054),\
+ PINGROUP(SDMMC1_DAT1, PY6, SDMMC1, SDMMC1, RSVD1, UARTE, INVALID, SDMMC1, INPUT, 0x3058),\
+ PINGROUP(SDMMC1_DAT0, PY7, SDMMC1, SDMMC1, RSVD1, UARTE, INVALID, SDMMC1, INPUT, 0x305c),\
PINGROUP(GPIO_PV2, PV2, SDMMC1, OWR, RSVD1, RSVD2, RSVD3, RSVD, INPUT, 0x3060),\
PINGROUP(GPIO_PV3, PV3, SDMMC1, INVALID, RSVD1, RSVD2, RSVD3, RSVD, INPUT, 0x3064),\
- PINGROUP(CLK2_OUT, PW5, SDMMC1, EXTPERIPH2, RSVD1, RSVD2, RSVD3, RSVD, INPUT, 0x3068),\
- PINGROUP(CLK2_REQ, PCC5, SDMMC1, DAP, RSVD1, RSVD2, RSVD3, RSVD, INPUT, 0x306c),\
- PINGROUP(LCD_PWR1, PC1, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x3070),\
- PINGROUP(LCD_PWR2, PC6, LCD, DISPLAYA, DISPLAYB, SPI5, INVALID, RSVD, OUTPUT, 0x3074),\
- PINGROUP(LCD_SDIN, PZ2, LCD, DISPLAYA, DISPLAYB, SPI5, RSVD, RSVD, OUTPUT, 0x3078),\
- PINGROUP(LCD_SDOUT, PN5, LCD, DISPLAYA, DISPLAYB, SPI5, INVALID, RSVD, OUTPUT, 0x307c),\
- PINGROUP(LCD_WR_N, PZ3, LCD, DISPLAYA, DISPLAYB, SPI5, INVALID, RSVD, OUTPUT, 0x3080),\
- PINGROUP(LCD_CS0_N, PN4, LCD, DISPLAYA, DISPLAYB, SPI5, RSVD, RSVD, OUTPUT, 0x3084),\
- PINGROUP(LCD_DC0, PN6, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x3088),\
- PINGROUP(LCD_SCK, PZ4, LCD, DISPLAYA, DISPLAYB, SPI5, INVALID, RSVD, OUTPUT, 0x308c),\
- PINGROUP(LCD_PWR0, PB2, LCD, DISPLAYA, DISPLAYB, SPI5, INVALID, RSVD, OUTPUT, 0x3090),\
- PINGROUP(LCD_PCLK, PB3, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x3094),\
- PINGROUP(LCD_DE, PJ1, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x3098),\
- PINGROUP(LCD_HSYNC, PJ3, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x309c),\
- PINGROUP(LCD_VSYNC, PJ4, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30a0),\
- PINGROUP(LCD_D0, PE0, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30a4),\
- PINGROUP(LCD_D1, PE1, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30a8),\
- PINGROUP(LCD_D2, PE2, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30ac),\
- PINGROUP(LCD_D3, PE3, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30b0),\
- PINGROUP(LCD_D4, PE4, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30b4),\
- PINGROUP(LCD_D5, PE5, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30b8),\
- PINGROUP(LCD_D6, PE6, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30bc),\
- PINGROUP(LCD_D7, PE7, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30c0),\
- PINGROUP(LCD_D8, PF0, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30c4),\
- PINGROUP(LCD_D9, PF1, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30c8),\
- PINGROUP(LCD_D10, PF2, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30cc),\
- PINGROUP(LCD_D11, PF3, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30d0),\
- PINGROUP(LCD_D12, PF4, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30d4),\
- PINGROUP(LCD_D13, PF5, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30d8),\
- PINGROUP(LCD_D14, PF6, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30dc),\
- PINGROUP(LCD_D15, PF7, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30e0),\
- PINGROUP(LCD_D16, PM0, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30e4),\
- PINGROUP(LCD_D17, PM1, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30e8),\
- PINGROUP(LCD_D18, PM2, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30ec),\
- PINGROUP(LCD_D19, PM3, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30f0),\
- PINGROUP(LCD_D20, PM4, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30f4),\
- PINGROUP(LCD_D21, PM5, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30f8),\
- PINGROUP(LCD_D22, PM6, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x30fc),\
- PINGROUP(LCD_D23, PM7, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x3100),\
- PINGROUP(LCD_CS1_N, PW0, LCD, DISPLAYA, DISPLAYB, SPI5, RSVD2, RSVD, OUTPUT, 0x3104),\
- PINGROUP(LCD_M1, PW1, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x3108),\
- PINGROUP(LCD_DC1, PD2, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, RSVD, OUTPUT, 0x310c),\
+ 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_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_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),\
+ PINGROUP(LCD_PWR0, PB2, LCD, DISPLAYA, DISPLAYB, SPI5, INVALID, DISPLAYA, OUTPUT, 0x3090),\
+ PINGROUP(LCD_PCLK, PB3, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, DISPLAYA, OUTPUT, 0x3094),\
+ PINGROUP(LCD_DE, PJ1, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, DISPLAYA, OUTPUT, 0x3098),\
+ PINGROUP(LCD_HSYNC, PJ3, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, DISPLAYA, OUTPUT, 0x309c),\
+ PINGROUP(LCD_VSYNC, PJ4, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, DISPLAYA, OUTPUT, 0x30a0),\
+ PINGROUP(LCD_D0, PE0, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, DISPLAYA, OUTPUT, 0x30a4),\
+ PINGROUP(LCD_D1, PE1, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, DISPLAYA, OUTPUT, 0x30a8),\
+ PINGROUP(LCD_D2, PE2, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, DISPLAYA, OUTPUT, 0x30ac),\
+ PINGROUP(LCD_D3, PE3, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, DISPLAYA, OUTPUT, 0x30b0),\
+ PINGROUP(LCD_D4, PE4, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, DISPLAYA, OUTPUT, 0x30b4),\
+ PINGROUP(LCD_D5, PE5, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, DISPLAYA, OUTPUT, 0x30b8),\
+ PINGROUP(LCD_D6, PE6, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, DISPLAYA, OUTPUT, 0x30bc),\
+ PINGROUP(LCD_D7, PE7, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, DISPLAYA, OUTPUT, 0x30c0),\
+ PINGROUP(LCD_D8, PF0, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, DISPLAYA, OUTPUT, 0x30c4),\
+ PINGROUP(LCD_D9, PF1, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, DISPLAYA, OUTPUT, 0x30c8),\
+ PINGROUP(LCD_D10, PF2, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, DISPLAYA, OUTPUT, 0x30cc),\
+ PINGROUP(LCD_D11, PF3, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, DISPLAYA, OUTPUT, 0x30d0),\
+ PINGROUP(LCD_D12, PF4, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, DISPLAYA, OUTPUT, 0x30d4),\
+ PINGROUP(LCD_D13, PF5, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, DISPLAYA, OUTPUT, 0x30d8),\
+ PINGROUP(LCD_D14, PF6, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, DISPLAYA, OUTPUT, 0x30dc),\
+ PINGROUP(LCD_D15, PF7, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, DISPLAYA, OUTPUT, 0x30e0),\
+ PINGROUP(LCD_D16, PM0, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, DISPLAYA, OUTPUT, 0x30e4),\
+ PINGROUP(LCD_D17, PM1, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, DISPLAYA, OUTPUT, 0x30e8),\
+ PINGROUP(LCD_D18, PM2, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, DISPLAYA, OUTPUT, 0x30ec),\
+ PINGROUP(LCD_D19, PM3, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, DISPLAYA, OUTPUT, 0x30f0),\
+ PINGROUP(LCD_D20, PM4, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, DISPLAYA, OUTPUT, 0x30f4),\
+ PINGROUP(LCD_D21, PM5, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, DISPLAYA, OUTPUT, 0x30f8),\
+ PINGROUP(LCD_D22, PM6, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, DISPLAYA, OUTPUT, 0x30fc),\
+ PINGROUP(LCD_D23, PM7, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, DISPLAYA, OUTPUT, 0x3100),\
+ PINGROUP(LCD_CS1_N, PW0, LCD, DISPLAYA, DISPLAYB, SPI5, RSVD2, DISPLAYA, OUTPUT, 0x3104),\
+ PINGROUP(LCD_M1, PW1, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, DISPLAYA, OUTPUT, 0x3108),\
+ PINGROUP(LCD_DC1, PD2, LCD, DISPLAYA, DISPLAYB, RSVD1, RSVD2, DISPLAYA, OUTPUT, 0x310c),\
PINGROUP(HDMI_INT, PN7, LCD, RSVD, RSVD, RSVD, RSVD, RSVD, INPUT, 0x3110),\
- PINGROUP(DDC_SCL, PV4, LCD, I2C4, RSVD1, RSVD2, RSVD3, RSVD, INPUT, 0x3114),\
- PINGROUP(DDC_SDA, PV5, LCD, I2C4, RSVD1, RSVD2, RSVD3, RSVD, INPUT, 0x3118),\
- PINGROUP(CRT_HSYNC, PV6, LCD, CRT, RSVD1, RSVD2, RSVD3, RSVD, INPUT, 0x311c),\
- PINGROUP(CRT_VSYNC, PV7, LCD, CRT, RSVD1, RSVD2, RSVD3, RSVD, INPUT, 0x3120),\
- PINGROUP(VI_D0, PT4, VI, INVALID, RSVD1, VI, RSVD2, RSVD, INPUT, 0x3124),\
- PINGROUP(VI_D1, PD5, VI, INVALID, SDMMC2, VI, RSVD1, RSVD, INPUT, 0x3128),\
- PINGROUP(VI_D2, PL0, VI, INVALID, SDMMC2, VI, RSVD1, RSVD, INPUT, 0x312c),\
- PINGROUP(VI_D3, PL1, VI, INVALID, SDMMC2, VI, RSVD1, RSVD, INPUT, 0x3130),\
- PINGROUP(VI_D4, PL2, VI, INVALID, SDMMC2, VI, RSVD1, RSVD, INPUT, 0x3134),\
- PINGROUP(VI_D5, PL3, VI, INVALID, SDMMC2, VI, RSVD1, RSVD, INPUT, 0x3138),\
- PINGROUP(VI_D6, PL4, VI, INVALID, SDMMC2, VI, RSVD1, RSVD, INPUT, 0x313c),\
- PINGROUP(VI_D7, PL5, VI, INVALID, SDMMC2, VI, RSVD1, RSVD, INPUT, 0x3140),\
- PINGROUP(VI_D8, PL6, VI, INVALID, SDMMC2, VI, RSVD1, RSVD, INPUT, 0x3144),\
- PINGROUP(VI_D9, PL7, VI, INVALID, SDMMC2, VI, RSVD1, RSVD, INPUT, 0x3148),\
- PINGROUP(VI_D10, PT2, VI, INVALID, RSVD1, VI, RSVD2, RSVD, INPUT, 0x314c),\
- PINGROUP(VI_D11, PT3, VI, INVALID, RSVD1, VI, RSVD2, RSVD, INPUT, 0x3150),\
- PINGROUP(VI_PCLK, PT0, VI, RSVD1, SDMMC2, VI, RSVD2, RSVD, INPUT, 0x3154),\
+ PINGROUP(DDC_SCL, PV4, LCD, I2C4, RSVD1, RSVD2, RSVD3, I2C4, INPUT, 0x3114),\
+ PINGROUP(DDC_SDA, PV5, LCD, I2C4, RSVD1, RSVD2, RSVD3, I2C4, INPUT, 0x3118),\
+ PINGROUP(CRT_HSYNC, PV6, LCD, CRT, RSVD1, RSVD2, RSVD3, CRT, INPUT, 0x311c),\
+ PINGROUP(CRT_VSYNC, PV7, LCD, CRT, RSVD1, RSVD2, RSVD3, CRT, INPUT, 0x3120),\
+ PINGROUP(VI_D0, PT4, VI, INVALID, RSVD1, VI, RSVD2, VI, INPUT, 0x3124),\
+ PINGROUP(VI_D1, PD5, VI, INVALID, SDMMC2, VI, RSVD1, VI, INPUT, 0x3128),\
+ PINGROUP(VI_D2, PL0, VI, INVALID, SDMMC2, VI, RSVD1, VI, INPUT, 0x312c),\
+ PINGROUP(VI_D3, PL1, VI, INVALID, SDMMC2, VI, RSVD1, VI, INPUT, 0x3130),\
+ PINGROUP(VI_D4, PL2, VI, INVALID, SDMMC2, VI, RSVD1, VI, INPUT, 0x3134),\
+ PINGROUP(VI_D5, PL3, VI, INVALID, SDMMC2, VI, RSVD1, VI, INPUT, 0x3138),\
+ PINGROUP(VI_D6, PL4, VI, INVALID, SDMMC2, VI, RSVD1, VI, INPUT, 0x313c),\
+ PINGROUP(VI_D7, PL5, VI, INVALID, SDMMC2, VI, RSVD1, VI, INPUT, 0x3140),\
+ PINGROUP(VI_D8, PL6, VI, INVALID, SDMMC2, VI, RSVD1, VI, INPUT, 0x3144),\
+ PINGROUP(VI_D9, PL7, VI, INVALID, SDMMC2, VI, RSVD1, VI, INPUT, 0x3148),\
+ PINGROUP(VI_D10, PT2, VI, INVALID, RSVD1, VI, RSVD2, VI, INPUT, 0x314c),\
+ PINGROUP(VI_D11, PT3, VI, INVALID, RSVD1, VI, RSVD2, VI, INPUT, 0x3150),\
+ PINGROUP(VI_PCLK, PT0, VI, RSVD1, SDMMC2, VI, RSVD2, VI, INPUT, 0x3154),\
PINGROUP(VI_MCLK, PT1, VI, INVALID, INVALID, INVALID, VI, RSVD, INPUT, 0x3158),\
- PINGROUP(VI_VSYNC, PD6, VI, INVALID, RSVD1, VI, RSVD2, RSVD, INPUT, 0x315c),\
- PINGROUP(VI_HSYNC, PD7, VI, INVALID, RSVD1, VI, RSVD2, RSVD, INPUT, 0x3160),\
- PINGROUP(UART2_RXD, PC3, UART, IRDA, SPDIF, UARTA, SPI4, RSVD, INPUT, 0x3164),\
- PINGROUP(UART2_TXD, PC2, UART, IRDA, SPDIF, UARTA, SPI4, RSVD, INPUT, 0x3168),\
- PINGROUP(UART2_RTS_N, PJ6, UART, UARTA, UARTB, GMI, SPI4, RSVD, INPUT, 0x316c),\
- PINGROUP(UART2_CTS_N, PJ5, UART, UARTA, UARTB, GMI, SPI4, RSVD, INPUT, 0x3170),\
- PINGROUP(UART3_TXD, PW6, UART, UARTC, RSVD1, GMI, RSVD2, RSVD, INPUT, 0x3174),\
- PINGROUP(UART3_RXD, PW7, UART, UARTC, RSVD1, GMI, RSVD2, RSVD, INPUT, 0x3178),\
- PINGROUP(UART3_CTS_N, PA1, UART, UARTC, RSVD1, GMI, RSVD2, RSVD, INPUT, 0x317c),\
- PINGROUP(UART3_RTS_N, PC0, UART, UARTC, PWM0, GMI, RSVD2, RSVD, INPUT, 0x3180),\
- PINGROUP(GPIO_PU0, PU0, UART, OWR, UARTA, GMI, RSVD1, RSVD, INPUT, 0x3184),\
- PINGROUP(GPIO_PU1, PU1, UART, RSVD1, UARTA, GMI, RSVD2, RSVD, INPUT, 0x3188),\
- PINGROUP(GPIO_PU2, PU2, UART, RSVD1, UARTA, GMI, RSVD2, RSVD, INPUT, 0x318c),\
- PINGROUP(GPIO_PU3, PU3, UART, PWM0, UARTA, GMI, RSVD1, RSVD, INPUT, 0x3190),\
- PINGROUP(GPIO_PU4, PU4, UART, PWM1, UARTA, GMI, RSVD1, RSVD, INPUT, 0x3194),\
- PINGROUP(GPIO_PU5, PU5, UART, PWM2, UARTA, GMI, RSVD1, RSVD, INPUT, 0x3198),\
- PINGROUP(GPIO_PU6, PU6, UART, PWM3, UARTA, GMI, RSVD1, RSVD, INPUT, 0x319c),\
- PINGROUP(GEN1_I2C_SDA, PC5, UART, I2C1, RSVD1, RSVD2, RSVD3, RSVD, INPUT, 0x31a0),\
- PINGROUP(GEN1_I2C_SCL, PC4, UART, I2C1, RSVD1, RSVD2, RSVD3, RSVD, INPUT, 0x31a4),\
- PINGROUP(DAP4_FS, PP4, UART, I2S3, RSVD1, GMI, RSVD2, RSVD, INPUT, 0x31a8),\
- PINGROUP(DAP4_DIN, PP5, UART, I2S3, RSVD1, GMI, RSVD2, RSVD, INPUT, 0x31ac),\
- PINGROUP(DAP4_DOUT, PP6, UART, I2S3, RSVD1, GMI, RSVD2, RSVD, INPUT, 0x31b0),\
- PINGROUP(DAP4_SCLK, PP7, UART, I2S3, RSVD1, GMI, RSVD2, RSVD, INPUT, 0x31b4),\
- PINGROUP(CLK3_OUT, PEE0, UART, EXTPERIPH3, RSVD1, RSVD2, RSVD3, RSVD, INPUT, 0x31b8),\
- PINGROUP(CLK3_REQ, PEE1, UART, DEV3, RSVD1, RSVD2, RSVD3, RSVD, INPUT, 0x31bc),\
- PINGROUP(GMI_WP_N, PC7, GMI, RSVD1, NAND, GMI, GMI_ALT, RSVD, INPUT, 0x31c0),\
- PINGROUP(GMI_IORDY, PI5, GMI, RSVD1, NAND, GMI, RSVD2, RSVD, INPUT, 0x31c4),\
- PINGROUP(GMI_WAIT, PI7, GMI, RSVD1, NAND, GMI, RSVD2, RSVD, INPUT, 0x31c8),\
- PINGROUP(GMI_ADV_N, PK0, GMI, RSVD1, NAND, GMI, RSVD2, RSVD, INPUT, 0x31cc),\
- PINGROUP(GMI_CLK, PK1, GMI, RSVD1, NAND, GMI, RSVD2, RSVD, INPUT, 0x31d0),\
- PINGROUP(GMI_CS0_N, PJ0, GMI, RSVD1, NAND, GMI, DTV, RSVD, INPUT, 0x31d4),\
- PINGROUP(GMI_CS1_N, PJ2, GMI, RSVD1, NAND, GMI, DTV, RSVD, INPUT, 0x31d8),\
- PINGROUP(GMI_CS2_N, PK3, GMI, RSVD1, NAND, GMI, RSVD2, RSVD, INPUT, 0x31dc),\
- PINGROUP(GMI_CS3_N, PK4, GMI, RSVD1, NAND, GMI, GMI_ALT, RSVD, INPUT, 0x31e0),\
- PINGROUP(GMI_CS4_N, PK2, GMI, RSVD1, NAND, GMI, RSVD2, RSVD, INPUT, 0x31e4),\
- PINGROUP(GMI_CS6_N, PI3, GMI, NAND, NAND_ALT, GMI, SATA, RSVD, INPUT, 0x31e8),\
- PINGROUP(GMI_CS7_N, PI6, GMI, NAND, NAND_ALT, GMI, GMI_ALT, RSVD, INPUT, 0x31ec),\
- PINGROUP(GMI_AD0, PG0, GMI, RSVD1, NAND, GMI, RSVD2, RSVD, INPUT, 0x31f0),\
- PINGROUP(GMI_AD1, PG1, GMI, RSVD1, NAND, GMI, RSVD2, RSVD, INPUT, 0x31f4),\
- PINGROUP(GMI_AD2, PG2, GMI, RSVD1, NAND, GMI, RSVD2, RSVD, INPUT, 0x31f8),\
- PINGROUP(GMI_AD3, PG3, GMI, RSVD1, NAND, GMI, RSVD2, RSVD, INPUT, 0x31fc),\
- PINGROUP(GMI_AD4, PG4, GMI, RSVD1, NAND, GMI, RSVD2, RSVD, INPUT, 0x3200),\
- PINGROUP(GMI_AD5, PG5, GMI, RSVD1, NAND, GMI, RSVD2, RSVD, INPUT, 0x3204),\
- PINGROUP(GMI_AD6, PG6, GMI, RSVD1, NAND, GMI, RSVD2, RSVD, INPUT, 0x3208),\
- PINGROUP(GMI_AD7, PG7, GMI, RSVD1, NAND, GMI, RSVD2, RSVD, INPUT, 0x320c),\
- PINGROUP(GMI_AD8, PH0, GMI, PWM0, NAND, GMI, RSVD2, RSVD, INPUT, 0x3210),\
- PINGROUP(GMI_AD9, PH1, GMI, PWM1, NAND, GMI, RSVD2, RSVD, INPUT, 0x3214),\
- PINGROUP(GMI_AD10, PH2, GMI, PWM2, NAND, GMI, RSVD2, RSVD, INPUT, 0x3218),\
- PINGROUP(GMI_AD11, PH3, GMI, PWM3, NAND, GMI, RSVD2, RSVD, INPUT, 0x321c),\
- PINGROUP(GMI_AD12, PH4, GMI, RSVD1, NAND, GMI, RSVD2, RSVD, INPUT, 0x3220),\
- PINGROUP(GMI_AD13, PH5, GMI, RSVD1, NAND, GMI, RSVD2, RSVD, INPUT, 0x3224),\
- PINGROUP(GMI_AD14, PH6, GMI, RSVD1, NAND, GMI, RSVD2, RSVD, INPUT, 0x3228),\
- PINGROUP(GMI_AD15, PH7, GMI, RSVD1, NAND, GMI, RSVD2, RSVD, INPUT, 0x322c),\
- PINGROUP(GMI_A16, PJ7, GMI, UARTD, SPI4, GMI, GMI_ALT, RSVD, INPUT, 0x3230),\
- PINGROUP(GMI_A17, PB0, GMI, UARTD, SPI4, GMI, DTV, RSVD, INPUT, 0x3234),\
- PINGROUP(GMI_A18, PB1, GMI, UARTD, SPI4, GMI, DTV, RSVD, INPUT, 0x3238),\
- PINGROUP(GMI_A19, PK7, GMI, UARTD, SPI4, GMI, RSVD3, RSVD, INPUT, 0x323c),\
- PINGROUP(GMI_WR_N, PI0, GMI, RSVD1, NAND, GMI, RSVD3, RSVD, INPUT, 0x3240),\
- PINGROUP(GMI_OE_N, PI1, GMI, RSVD1, NAND, GMI, RSVD3, RSVD, INPUT, 0x3244),\
- PINGROUP(GMI_DQS, PI2, GMI, RSVD1, NAND, GMI, RSVD3, RSVD, INPUT, 0x3248),\
- PINGROUP(GMI_RST_N, PI4, GMI, NAND, NAND_ALT, GMI, RSVD3, RSVD, INPUT, 0x324c),\
- PINGROUP(GEN2_I2C_SCL, PT5, GMI, I2C2, INVALID, GMI, RSVD3, RSVD, INPUT, 0x3250),\
- PINGROUP(GEN2_I2C_SDA, PT6, GMI, I2C2, INVALID, GMI, RSVD3, RSVD, INPUT, 0x3254),\
- PINGROUP(SDMMC4_CLK, PCC4, SDMMC4, INVALID, NAND, GMI, SDMMC4, RSVD, INPUT, 0x3258),\
- PINGROUP(SDMMC4_CMD, PT7, SDMMC4, I2C3, NAND, GMI, SDMMC4, RSVD, INPUT, 0x325c),\
- PINGROUP(SDMMC4_DAT0, PAA0, SDMMC4, UARTE, SPI3, GMI, SDMMC4, RSVD, INPUT, 0x3260),\
- PINGROUP(SDMMC4_DAT1, PAA1, SDMMC4, UARTE, SPI3, GMI, SDMMC4, RSVD, INPUT, 0x3264),\
- PINGROUP(SDMMC4_DAT2, PAA2, SDMMC4, UARTE, SPI3, GMI, SDMMC4, RSVD, INPUT, 0x3268),\
- PINGROUP(SDMMC4_DAT3, PAA3, SDMMC4, UARTE, SPI3, GMI, SDMMC4, RSVD, INPUT, 0x326c),\
- PINGROUP(SDMMC4_DAT4, PAA4, SDMMC4, I2C3, I2S4, GMI, SDMMC4, RSVD, INPUT, 0x3270),\
- PINGROUP(SDMMC4_DAT5, PAA5, SDMMC4, VGP3, I2S4, GMI, SDMMC4, RSVD, INPUT, 0x3274),\
- PINGROUP(SDMMC4_DAT6, PAA6, SDMMC4, VGP4, I2S4, GMI, SDMMC4, RSVD, INPUT, 0x3278),\
- PINGROUP(SDMMC4_DAT7, PAA7, SDMMC4, VGP5, I2S4, GMI, SDMMC4, RSVD, INPUT, 0x327c),\
+ PINGROUP(VI_VSYNC, PD6, VI, INVALID, RSVD1, VI, RSVD2, VI, INPUT, 0x315c),\
+ PINGROUP(VI_HSYNC, PD7, VI, INVALID, RSVD1, VI, RSVD2, VI, INPUT, 0x3160),\
+ PINGROUP(UART2_RXD, PC3, UART, IRDA, SPDIF, UARTA, SPI4, IRDA, INPUT, 0x3164),\
+ PINGROUP(UART2_TXD, PC2, UART, IRDA, SPDIF, UARTA, SPI4, IRDA, INPUT, 0x3168),\
+ PINGROUP(UART2_RTS_N, PJ6, UART, UARTA, UARTB, GMI, SPI4, UARTB, INPUT, 0x316c),\
+ PINGROUP(UART2_CTS_N, PJ5, UART, UARTA, UARTB, GMI, SPI4, UARTB, INPUT, 0x3170),\
+ PINGROUP(UART3_TXD, PW6, UART, UARTC, RSVD1, GMI, RSVD2, UARTC, INPUT, 0x3174),\
+ PINGROUP(UART3_RXD, PW7, UART, UARTC, RSVD1, GMI, RSVD2, UARTC, INPUT, 0x3178),\
+ PINGROUP(UART3_CTS_N, PA1, UART, UARTC, RSVD1, GMI, RSVD2, UARTC, INPUT, 0x317c),\
+ PINGROUP(UART3_RTS_N, PC0, UART, UARTC, PWM0, GMI, RSVD2, UARTC, INPUT, 0x3180),\
+ PINGROUP(GPIO_PU0, PU0, UART, OWR, UARTA, GMI, RSVD1, GMI, INPUT, 0x3184),\
+ PINGROUP(GPIO_PU1, PU1, UART, RSVD1, UARTA, GMI, RSVD2, GMI, INPUT, 0x3188),\
+ PINGROUP(GPIO_PU2, PU2, UART, RSVD1, UARTA, GMI, RSVD2, GMI, INPUT, 0x318c),\
+ PINGROUP(GPIO_PU3, PU3, UART, PWM0, UARTA, GMI, RSVD1, GMI, INPUT, 0x3190),\
+ PINGROUP(GPIO_PU4, PU4, UART, PWM1, UARTA, GMI, RSVD1, GMI, INPUT, 0x3194),\
+ PINGROUP(GPIO_PU5, PU5, UART, PWM2, UARTA, GMI, RSVD1, GMI, INPUT, 0x3198),\
+ PINGROUP(GPIO_PU6, PU6, UART, PWM3, UARTA, GMI, RSVD1, GMI, INPUT, 0x319c),\
+ PINGROUP(GEN1_I2C_SDA, PC5, UART, I2C1, RSVD1, RSVD2, RSVD3, I2C1, INPUT, 0x31a0),\
+ PINGROUP(GEN1_I2C_SCL, PC4, UART, I2C1, RSVD1, RSVD2, RSVD3, I2C1, INPUT, 0x31a4),\
+ PINGROUP(DAP4_FS, PP4, UART, I2S3, RSVD1, GMI, RSVD2, I2S3, INPUT, 0x31a8),\
+ PINGROUP(DAP4_DIN, PP5, UART, I2S3, RSVD1, GMI, RSVD2, I2S3, INPUT, 0x31ac),\
+ PINGROUP(DAP4_DOUT, PP6, UART, I2S3, RSVD1, GMI, RSVD2, I2S3, INPUT, 0x31b0),\
+ PINGROUP(DAP4_SCLK, PP7, UART, I2S3, RSVD1, GMI, RSVD2, I2S3, INPUT, 0x31b4),\
+ PINGROUP(CLK3_OUT, PEE0, UART, EXTPERIPH3, RSVD1, RSVD2, RSVD3, EXTPERIPH3, INPUT, 0x31b8),\
+ PINGROUP(CLK3_REQ, PEE1, UART, DEV3, RSVD1, RSVD2, RSVD3, DEV3, INPUT, 0x31bc),\
+ PINGROUP(GMI_WP_N, PC7, GMI, RSVD1, NAND, GMI, GMI_ALT, GMI, INPUT, 0x31c0),\
+ PINGROUP(GMI_IORDY, PI5, GMI, RSVD1, NAND, GMI, RSVD2, GMI, INPUT, 0x31c4),\
+ PINGROUP(GMI_WAIT, PI7, GMI, RSVD1, NAND, GMI, RSVD2, NAND, INPUT, 0x31c8),\
+ PINGROUP(GMI_ADV_N, PK0, GMI, RSVD1, NAND, GMI, RSVD2, GMI, INPUT, 0x31cc),\
+ PINGROUP(GMI_CLK, PK1, GMI, RSVD1, NAND, GMI, RSVD2, GMI, INPUT, 0x31d0),\
+ PINGROUP(GMI_CS0_N, PJ0, GMI, RSVD1, NAND, GMI, DTV, GMI, INPUT, 0x31d4),\
+ PINGROUP(GMI_CS1_N, PJ2, GMI, RSVD1, NAND, GMI, DTV, GMI, INPUT, 0x31d8),\
+ PINGROUP(GMI_CS2_N, PK3, GMI, RSVD1, NAND, GMI, RSVD2, GMI, INPUT, 0x31dc),\
+ PINGROUP(GMI_CS3_N, PK4, GMI, RSVD1, NAND, GMI, GMI_ALT, GMI, INPUT, 0x31e0),\
+ PINGROUP(GMI_CS4_N, PK2, GMI, RSVD1, NAND, GMI, RSVD2, GMI, INPUT, 0x31e4),\
+ PINGROUP(GMI_CS6_N, PI3, GMI, NAND, NAND_ALT, GMI, SATA, NAND, INPUT, 0x31e8),\
+ PINGROUP(GMI_CS7_N, PI6, GMI, NAND, NAND_ALT, GMI, GMI_ALT, NAND, INPUT, 0x31ec),\
+ PINGROUP(GMI_AD0, PG0, GMI, RSVD1, NAND, GMI, RSVD2, GMI, INPUT, 0x31f0),\
+ PINGROUP(GMI_AD1, PG1, GMI, RSVD1, NAND, GMI, RSVD2, GMI, INPUT, 0x31f4),\
+ PINGROUP(GMI_AD2, PG2, GMI, RSVD1, NAND, GMI, RSVD2, GMI, INPUT, 0x31f8),\
+ PINGROUP(GMI_AD3, PG3, GMI, RSVD1, NAND, GMI, RSVD2, GMI, INPUT, 0x31fc),\
+ PINGROUP(GMI_AD4, PG4, GMI, RSVD1, NAND, GMI, RSVD2, GMI, INPUT, 0x3200),\
+ PINGROUP(GMI_AD5, PG5, GMI, RSVD1, NAND, GMI, RSVD2, GMI, INPUT, 0x3204),\
+ PINGROUP(GMI_AD6, PG6, GMI, RSVD1, NAND, GMI, RSVD2, GMI, INPUT, 0x3208),\
+ PINGROUP(GMI_AD7, PG7, GMI, RSVD1, NAND, GMI, RSVD2, GMI, INPUT, 0x320c),\
+ PINGROUP(GMI_AD8, PH0, GMI, PWM0, NAND, GMI, RSVD2, GMI, INPUT, 0x3210),\
+ PINGROUP(GMI_AD9, PH1, GMI, PWM1, NAND, GMI, RSVD2, GMI, INPUT, 0x3214),\
+ PINGROUP(GMI_AD10, PH2, GMI, PWM2, NAND, GMI, RSVD2, GMI, INPUT, 0x3218),\
+ PINGROUP(GMI_AD11, PH3, GMI, PWM3, NAND, GMI, RSVD2, GMI, INPUT, 0x321c),\
+ PINGROUP(GMI_AD12, PH4, GMI, RSVD1, NAND, GMI, RSVD2, GMI, INPUT, 0x3220),\
+ PINGROUP(GMI_AD13, PH5, GMI, RSVD1, NAND, GMI, RSVD2, GMI, INPUT, 0x3224),\
+ PINGROUP(GMI_AD14, PH6, GMI, RSVD1, NAND, GMI, RSVD2, GMI, INPUT, 0x3228),\
+ PINGROUP(GMI_AD15, PH7, GMI, RSVD1, NAND, GMI, RSVD2, GMI, INPUT, 0x322c),\
+ PINGROUP(GMI_A16, PJ7, GMI, UARTD, SPI4, GMI, GMI_ALT, GMI, INPUT, 0x3230),\
+ PINGROUP(GMI_A17, PB0, GMI, UARTD, SPI4, GMI, DTV, GMI, INPUT, 0x3234),\
+ PINGROUP(GMI_A18, PB1, GMI, UARTD, SPI4, GMI, DTV, GMI, INPUT, 0x3238),\
+ PINGROUP(GMI_A19, PK7, GMI, UARTD, SPI4, GMI, RSVD3, GMI, INPUT, 0x323c),\
+ PINGROUP(GMI_WR_N, PI0, GMI, RSVD1, NAND, GMI, RSVD3, GMI, INPUT, 0x3240),\
+ PINGROUP(GMI_OE_N, PI1, GMI, RSVD1, NAND, GMI, RSVD3, GMI, INPUT, 0x3244),\
+ PINGROUP(GMI_DQS, PI2, GMI, RSVD1, NAND, GMI, RSVD3, NAND, INPUT, 0x3248),\
+ PINGROUP(GMI_RST_N, PI4, GMI, NAND, NAND_ALT, GMI, RSVD3, NAND, INPUT, 0x324c),\
+ PINGROUP(GEN2_I2C_SCL, PT5, GMI, I2C2, INVALID, GMI, RSVD3, I2C2, INPUT, 0x3250),\
+ PINGROUP(GEN2_I2C_SDA, PT6, GMI, I2C2, INVALID, GMI, RSVD3, I2C2, INPUT, 0x3254),\
+ PINGROUP(SDMMC4_CLK, PCC4, SDMMC4, INVALID, NAND, GMI, SDMMC4, GMI, INPUT, 0x3258),\
+ PINGROUP(SDMMC4_CMD, PT7, SDMMC4, I2C3, NAND, GMI, SDMMC4, GMI, INPUT, 0x325c),\
+ PINGROUP(SDMMC4_DAT0, PAA0, SDMMC4, UARTE, SPI3, GMI, SDMMC4, GMI, INPUT, 0x3260),\
+ PINGROUP(SDMMC4_DAT1, PAA1, SDMMC4, UARTE, SPI3, GMI, SDMMC4, GMI, INPUT, 0x3264),\
+ PINGROUP(SDMMC4_DAT2, PAA2, SDMMC4, UARTE, SPI3, GMI, SDMMC4, GMI, INPUT, 0x3268),\
+ PINGROUP(SDMMC4_DAT3, PAA3, SDMMC4, UARTE, SPI3, GMI, SDMMC4, GMI, INPUT, 0x326c),\
+ PINGROUP(SDMMC4_DAT4, PAA4, SDMMC4, I2C3, I2S4, GMI, SDMMC4, GMI, INPUT, 0x3270),\
+ PINGROUP(SDMMC4_DAT5, PAA5, SDMMC4, VGP3, I2S4, GMI, SDMMC4, GMI, INPUT, 0x3274),\
+ PINGROUP(SDMMC4_DAT6, PAA6, SDMMC4, VGP4, I2S4, GMI, SDMMC4, GMI, INPUT, 0x3278),\
+ PINGROUP(SDMMC4_DAT7, PAA7, SDMMC4, VGP5, I2S4, GMI, SDMMC4, GMI, INPUT, 0x327c),\
PINGROUP(SDMMC4_RST_N, PCC3, SDMMC4, VGP6, RSVD1, RSVD2, POPSDMMC4, RSVD, INPUT, 0x3280),\
PINGROUP(CAM_MCLK, PCC0, CAM, VI, INVALID, VI_ALT2, POPSDMMC4, RSVD, INPUT, 0x3284),\
PINGROUP(GPIO_PCC1, PCC1, CAM, I2S4, RSVD1, RSVD2, POPSDMMC4, RSVD, INPUT, 0x3288),\
@@ -311,83 +320,83 @@ 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, RSVD3, RSVD, INPUT, 0x32ac),\
- PINGROUP(JTAG_RTCK, PU7, SYS, RTCK, RSVD1, RSVD2, RSVD3, RSVD, INPUT, 0x32b0),\
- PINGROUP(PWR_I2C_SCL, PZ6, SYS, I2CPWR, RSVD1, RSVD2, RSVD3, RSVD, INPUT, 0x32b4),\
- PINGROUP(PWR_I2C_SDA, PZ7, SYS, I2CPWR, RSVD1, RSVD2, RSVD3, RSVD, INPUT, 0x32b8),\
- PINGROUP(KB_ROW0, PR0, SYS, KBC, INVALID, RSVD2, RSVD3, RSVD, INPUT, 0x32bc),\
- PINGROUP(KB_ROW1, PR1, SYS, KBC, INVALID, RSVD2, RSVD3, RSVD, INPUT, 0x32c0),\
- PINGROUP(KB_ROW2, PR2, SYS, KBC, INVALID, RSVD2, RSVD3, RSVD, INPUT, 0x32c4),\
- PINGROUP(KB_ROW3, PR3, SYS, KBC, INVALID, RSVD2, INVALID, RSVD, INPUT, 0x32c8),\
- PINGROUP(KB_ROW4, PR4, SYS, KBC, INVALID, TRACE, RSVD3, RSVD, INPUT, 0x32cc),\
- PINGROUP(KB_ROW5, PR5, SYS, KBC, INVALID, TRACE, OWR, RSVD, INPUT, 0x32d0),\
- PINGROUP(KB_ROW6, PR6, SYS, KBC, INVALID, SDMMC2, INVALID, RSVD, INPUT, 0x32d4),\
- PINGROUP(KB_ROW7, PR7, SYS, KBC, INVALID, SDMMC2, INVALID, RSVD, INPUT, 0x32d8),\
- PINGROUP(KB_ROW8, PS0, SYS, KBC, INVALID, SDMMC2, INVALID, RSVD, INPUT, 0x32dc),\
- PINGROUP(KB_ROW9, PS1, SYS, KBC, INVALID, SDMMC2, INVALID, RSVD, INPUT, 0x32e0),\
- PINGROUP(KB_ROW10, PS2, SYS, KBC, INVALID, SDMMC2, INVALID, RSVD, INPUT, 0x32e4),\
- PINGROUP(KB_ROW11, PS3, SYS, KBC, INVALID, SDMMC2, INVALID, RSVD, INPUT, 0x32e8),\
- PINGROUP(KB_ROW12, PS4, SYS, KBC, INVALID, SDMMC2, INVALID, RSVD, INPUT, 0x32ec),\
- PINGROUP(KB_ROW13, PS5, SYS, KBC, INVALID, SDMMC2, INVALID, RSVD, INPUT, 0x32f0),\
- PINGROUP(KB_ROW14, PS6, SYS, KBC, INVALID, SDMMC2, INVALID, RSVD, INPUT, 0x32f4),\
- PINGROUP(KB_ROW15, PS7, SYS, KBC, INVALID, SDMMC2, INVALID, RSVD, INPUT, 0x32f8),\
- PINGROUP(KB_COL0, PQ0, SYS, KBC, INVALID, TRACE, INVALID, RSVD, INPUT, 0x32fc),\
- PINGROUP(KB_COL1, PQ1, SYS, KBC, INVALID, TRACE, INVALID, RSVD, INPUT, 0x3300),\
- PINGROUP(KB_COL2, PQ2, SYS, KBC, INVALID, TRACE, RSVD, RSVD, INPUT, 0x3304),\
- PINGROUP(KB_COL3, PQ3, SYS, KBC, INVALID, TRACE, RSVD, RSVD, INPUT, 0x3308),\
- PINGROUP(KB_COL4, PQ4, SYS, KBC, INVALID, TRACE, RSVD, RSVD, INPUT, 0x330c),\
- PINGROUP(KB_COL5, PQ5, SYS, KBC, INVALID, TRACE, RSVD, RSVD, INPUT, 0x3310),\
- PINGROUP(KB_COL6, PQ6, SYS, KBC, INVALID, TRACE, INVALID, RSVD, INPUT, 0x3314),\
- PINGROUP(KB_COL7, PQ7, SYS, KBC, INVALID, TRACE, INVALID, RSVD, INPUT, 0x3318),\
- PINGROUP(CLK_32K_OUT, PA0, SYS, BLINK, RSVD1, RSVD2, RSVD3, RSVD, INPUT, 0x331c),\
- PINGROUP(SYS_CLK_REQ, PZ5, SYS, SYSCLK, RSVD1, RSVD2, RSVD3, RSVD, INPUT, 0x3320),\
+ 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),\
+ PINGROUP(KB_ROW0, PR0, SYS, KBC, INVALID, RSVD2, RSVD3, KBC, INPUT, 0x32bc),\
+ PINGROUP(KB_ROW1, PR1, SYS, KBC, INVALID, RSVD2, RSVD3, KBC, INPUT, 0x32c0),\
+ PINGROUP(KB_ROW2, PR2, SYS, KBC, INVALID, RSVD2, RSVD3, KBC, INPUT, 0x32c4),\
+ PINGROUP(KB_ROW3, PR3, SYS, KBC, INVALID, RSVD2, INVALID, KBC, INPUT, 0x32c8),\
+ PINGROUP(KB_ROW4, PR4, SYS, KBC, INVALID, TRACE, RSVD3, KBC, INPUT, 0x32cc),\
+ PINGROUP(KB_ROW5, PR5, SYS, KBC, INVALID, TRACE, OWR, KBC, INPUT, 0x32d0),\
+ PINGROUP(KB_ROW6, PR6, SYS, KBC, INVALID, SDMMC2, INVALID, KBC, INPUT, 0x32d4),\
+ PINGROUP(KB_ROW7, PR7, SYS, KBC, INVALID, SDMMC2, INVALID, KBC, INPUT, 0x32d8),\
+ PINGROUP(KB_ROW8, PS0, SYS, KBC, INVALID, SDMMC2, INVALID, KBC, INPUT, 0x32dc),\
+ PINGROUP(KB_ROW9, PS1, SYS, KBC, INVALID, SDMMC2, INVALID, KBC, INPUT, 0x32e0),\
+ PINGROUP(KB_ROW10, PS2, SYS, KBC, INVALID, SDMMC2, INVALID, KBC, INPUT, 0x32e4),\
+ PINGROUP(KB_ROW11, PS3, SYS, KBC, INVALID, SDMMC2, INVALID, KBC, INPUT, 0x32e8),\
+ PINGROUP(KB_ROW12, PS4, SYS, KBC, INVALID, SDMMC2, INVALID, KBC, INPUT, 0x32ec),\
+ PINGROUP(KB_ROW13, PS5, SYS, KBC, INVALID, SDMMC2, INVALID, KBC, INPUT, 0x32f0),\
+ PINGROUP(KB_ROW14, PS6, SYS, KBC, INVALID, SDMMC2, INVALID, KBC, INPUT, 0x32f4),\
+ PINGROUP(KB_ROW15, PS7, SYS, KBC, INVALID, SDMMC2, INVALID, KBC, INPUT, 0x32f8),\
+ PINGROUP(KB_COL0, PQ0, SYS, KBC, INVALID, TRACE, INVALID, KBC, INPUT, 0x32fc),\
+ PINGROUP(KB_COL1, PQ1, SYS, KBC, INVALID, TRACE, INVALID, KBC, INPUT, 0x3300),\
+ PINGROUP(KB_COL2, PQ2, SYS, KBC, INVALID, TRACE, RSVD, KBC, INPUT, 0x3304),\
+ PINGROUP(KB_COL3, PQ3, SYS, KBC, INVALID, TRACE, RSVD, KBC, INPUT, 0x3308),\
+ PINGROUP(KB_COL4, PQ4, SYS, KBC, INVALID, TRACE, RSVD, KBC, INPUT, 0x330c),\
+ PINGROUP(KB_COL5, PQ5, SYS, KBC, INVALID, TRACE, RSVD, KBC, INPUT, 0x3310),\
+ PINGROUP(KB_COL6, PQ6, SYS, KBC, INVALID, TRACE, INVALID, KBC, INPUT, 0x3314),\
+ PINGROUP(KB_COL7, PQ7, SYS, KBC, INVALID, TRACE, INVALID, KBC, INPUT, 0x3318),\
+ PINGROUP(CLK_32K_OUT, PA0, SYS, BLINK, RSVD1, RSVD2, RSVD3, BLINK, INPUT, 0x331c),\
+ PINGROUP(SYS_CLK_REQ, PZ5, SYS, SYSCLK, RSVD1, RSVD2, RSVD3, SYSCLK, INPUT, 0x3320),\
PINGROUP(CORE_PWR_REQ, INVALID, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, INPUT, 0x3324),\
PINGROUP(CPU_PWR_REQ, INVALID, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, INPUT, 0x3328),\
PINGROUP(PWR_INT_N, INVALID, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, INPUT, 0x332c),\
PINGROUP(CLK_32K_IN, INVALID, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, INPUT, 0x3330),\
- PINGROUP(OWR, INVALID, SYS, OWR, RSVD, RSVD, RSVD, RSVD, INPUT, 0x3334),\
- PINGROUP(DAP1_FS, PN0, AUDIO, I2S0, HDA, GMI, SDMMC2, RSVD, INPUT, 0x3338),\
- PINGROUP(DAP1_DIN, PN1, AUDIO, I2S0, HDA, GMI, SDMMC2, RSVD, INPUT, 0x333c),\
- PINGROUP(DAP1_DOUT, PN2, AUDIO, I2S0, HDA, GMI, SDMMC2, RSVD, INPUT, 0x3340),\
- PINGROUP(DAP1_SCLK, PN3, AUDIO, I2S0, HDA, GMI, SDMMC2, RSVD, INPUT, 0x3344),\
- PINGROUP(CLK1_REQ, PEE2, AUDIO, DAP, HDA, RSVD2, RSVD3, RSVD, INPUT, 0x3348),\
- PINGROUP(CLK1_OUT, PW4, AUDIO, EXTPERIPH1, RSVD1, RSVD2, RSVD3, RSVD, INPUT, 0x334c),\
+ PINGROUP(OWR, INVALID, SYS, OWR, RSVD, RSVD, RSVD, OWR, INPUT, 0x3334),\
+ PINGROUP(DAP1_FS, PN0, AUDIO, I2S0, HDA, GMI, SDMMC2, I2S0, INPUT, 0x3338),\
+ PINGROUP(DAP1_DIN, PN1, AUDIO, I2S0, HDA, GMI, SDMMC2, I2S0, INPUT, 0x333c),\
+ PINGROUP(DAP1_DOUT, PN2, AUDIO, I2S0, HDA, GMI, SDMMC2, I2S0, INPUT, 0x3340),\
+ PINGROUP(DAP1_SCLK, PN3, AUDIO, I2S0, HDA, GMI, SDMMC2, I2S0, INPUT, 0x3344),\
+ PINGROUP(CLK1_REQ, PEE2, AUDIO, DAP, HDA, RSVD2, RSVD3, DAP, INPUT, 0x3348),\
+ PINGROUP(CLK1_OUT, PW4, AUDIO, EXTPERIPH1, RSVD1, RSVD2, RSVD3, EXTPERIPH1, INPUT, 0x334c),\
PINGROUP(SPDIF_IN, PK6, AUDIO, SPDIF, HDA, INVALID, DAPSDMMC2, RSVD, INPUT, 0x3350),\
PINGROUP(SPDIF_OUT, PK5, AUDIO, SPDIF, RSVD1, INVALID, DAPSDMMC2, RSVD, INPUT, 0x3354),\
- PINGROUP(DAP2_FS, PA2, AUDIO, I2S1, HDA, RSVD2, GMI, RSVD, INPUT, 0x3358),\
- PINGROUP(DAP2_DIN, PA4, AUDIO, I2S1, HDA, RSVD2, GMI, RSVD, INPUT, 0x335c),\
- PINGROUP(DAP2_DOUT, PA5, AUDIO, I2S1, HDA, RSVD2, GMI, RSVD, INPUT, 0x3360),\
- PINGROUP(DAP2_SCLK, PA3, AUDIO, I2S1, HDA, RSVD2, GMI, RSVD, INPUT, 0x3364),\
- PINGROUP(SPI2_MOSI, PX0, AUDIO, SPI6, SPI2, INVALID, GMI, RSVD, INPUT, 0x3368),\
- PINGROUP(SPI2_MISO, PX1, AUDIO, SPI6, SPI2, INVALID, GMI, RSVD, INPUT, 0x336c),\
- PINGROUP(SPI2_CS0_N, PX3, AUDIO, SPI6, SPI2, INVALID, GMI, RSVD, INPUT, 0x3370),\
- PINGROUP(SPI2_SCK, PX2, AUDIO, SPI6, SPI2, INVALID, GMI, RSVD, INPUT, 0x3374),\
- PINGROUP(SPI1_MOSI, PX4, AUDIO, SPI2, SPI1, INVALID, GMI, RSVD, INPUT, 0x3378),\
- PINGROUP(SPI1_SCK, PX5, AUDIO, SPI2, SPI1, INVALID, GMI, RSVD, INPUT, 0x337c),\
- PINGROUP(SPI1_CS0_N, PX6, AUDIO, SPI2, SPI1, INVALID, GMI, RSVD, INPUT, 0x3380),\
+ PINGROUP(DAP2_FS, PA2, AUDIO, I2S1, HDA, RSVD2, GMI, I2S1, INPUT, 0x3358),\
+ PINGROUP(DAP2_DIN, PA4, AUDIO, I2S1, HDA, RSVD2, GMI, I2S1, INPUT, 0x335c),\
+ PINGROUP(DAP2_DOUT, PA5, AUDIO, I2S1, HDA, RSVD2, GMI, I2S1, INPUT, 0x3360),\
+ PINGROUP(DAP2_SCLK, PA3, AUDIO, I2S1, HDA, RSVD2, GMI, I2S1, INPUT, 0x3364),\
+ PINGROUP(SPI2_MOSI, PX0, AUDIO, SPI6, SPI2, INVALID, GMI, SPI6, INPUT, 0x3368),\
+ PINGROUP(SPI2_MISO, PX1, AUDIO, SPI6, SPI2, INVALID, GMI, SPI6, INPUT, 0x336c),\
+ PINGROUP(SPI2_CS0_N, PX3, AUDIO, SPI6, SPI2, INVALID, GMI, SPI6, INPUT, 0x3370),\
+ PINGROUP(SPI2_SCK, PX2, AUDIO, SPI6, SPI2, INVALID, GMI, SPI6, INPUT, 0x3374),\
+ PINGROUP(SPI1_MOSI, PX4, AUDIO, SPI2, SPI1, INVALID, GMI, GMI, INPUT, 0x3378),\
+ PINGROUP(SPI1_SCK, PX5, AUDIO, SPI2, SPI1, INVALID, GMI, GMI, INPUT, 0x337c),\
+ PINGROUP(SPI1_CS0_N, PX6, AUDIO, SPI2, SPI1, INVALID, GMI, GMI, INPUT, 0x3380),\
PINGROUP(SPI1_MISO, PX7, AUDIO, INVALID, SPI1, INVALID, RSVD3, RSVD, INPUT, 0x3384),\
PINGROUP(SPI2_CS1_N, PW2, AUDIO, INVALID, SPI2, INVALID, INVALID, RSVD, INPUT, 0x3388),\
PINGROUP(SPI2_CS2_N, PW3, AUDIO, INVALID, SPI2, INVALID, INVALID, RSVD, INPUT, 0x338c),\
- PINGROUP(SDMMC3_CLK, PA6, SDMMC3, UARTA, PWM2, SDMMC3, INVALID, RSVD, INPUT, 0x3390),\
- PINGROUP(SDMMC3_CMD, PA7, SDMMC3, UARTA, PWM3, SDMMC3, INVALID, RSVD, INPUT, 0x3394),\
- PINGROUP(SDMMC3_DAT0, PB7, SDMMC3, RSVD0, RSVD1, SDMMC3, INVALID, RSVD, INPUT, 0x3398),\
- PINGROUP(SDMMC3_DAT1, PB6, SDMMC3, RSVD0, RSVD1, SDMMC3, INVALID, RSVD, INPUT, 0x339c),\
- PINGROUP(SDMMC3_DAT2, PB5, SDMMC3, RSVD0, PWM1, SDMMC3, INVALID, RSVD, INPUT, 0x33a0),\
- PINGROUP(SDMMC3_DAT3, PB4, SDMMC3, RSVD0, PWM0, SDMMC3, INVALID, RSVD, INPUT, 0x33a4),\
- PINGROUP(SDMMC3_DAT4, PD1, SDMMC3, PWM1, INVALID, SDMMC3, INVALID, RSVD, INPUT, 0x33a8),\
- PINGROUP(SDMMC3_DAT5, PD0, SDMMC3, PWM0, INVALID, SDMMC3, INVALID, RSVD, INPUT, 0x33ac),\
- PINGROUP(SDMMC3_DAT6, PD3, SDMMC3, SPDIF, INVALID, SDMMC3, INVALID, RSVD, INPUT, 0x33b0),\
- PINGROUP(SDMMC3_DAT7, PD4, SDMMC3, SPDIF, INVALID, SDMMC3, INVALID, RSVD, INPUT, 0x33b4),\
- PINGROUP(PEX_L0_PRSNT_N, PDD0, PEXCTL, PCIE, HDA, RSVD2, RSVD3, RSVD, INPUT, 0x33b8),\
- PINGROUP(PEX_L0_RST_N, PDD1, PEXCTL, PCIE, HDA, RSVD2, RSVD3, RSVD, INPUT, 0x33bc),\
- PINGROUP(PEX_L0_CLKREQ_N, PDD2, PEXCTL, PCIE, HDA, RSVD2, RSVD3, RSVD, INPUT, 0x33c0),\
- PINGROUP(PEX_WAKE_N, PDD3, PEXCTL, PCIE, HDA, RSVD2, RSVD3, RSVD, INPUT, 0x33c4),\
- PINGROUP(PEX_L1_PRSNT_N, PDD4, PEXCTL, PCIE, HDA, RSVD2, RSVD3, RSVD, INPUT, 0x33c8),\
- PINGROUP(PEX_L1_RST_N, PDD5, PEXCTL, PCIE, HDA, RSVD2, RSVD3, RSVD, INPUT, 0x33cc),\
- PINGROUP(PEX_L1_CLKREQ_N, PDD6, PEXCTL, PCIE, HDA, RSVD2, RSVD3, RSVD, INPUT, 0x33d0),\
- PINGROUP(PEX_L2_PRSNT_N, PDD7, PEXCTL, PCIE, HDA, RSVD2, RSVD3, RSVD, INPUT, 0x33d4),\
- PINGROUP(PEX_L2_RST_N, PCC6, PEXCTL, PCIE, HDA, RSVD2, RSVD3, RSVD, INPUT, 0x33d8),\
- PINGROUP(PEX_L2_CLKREQ_N, PCC7, PEXCTL, PCIE, HDA, RSVD2, RSVD3, RSVD, INPUT, 0x33dc),\
+ PINGROUP(SDMMC3_CLK, PA6, SDMMC3, UARTA, PWM2, SDMMC3, SPI3, SDMMC3, INPUT, 0x3390),\
+ PINGROUP(SDMMC3_CMD, PA7, SDMMC3, UARTA, PWM3, SDMMC3, INVALID, SDMMC3, INPUT, 0x3394),\
+ PINGROUP(SDMMC3_DAT0, PB7, SDMMC3, RSVD0, RSVD1, SDMMC3, SPI3, SDMMC3, INPUT, 0x3398),\
+ PINGROUP(SDMMC3_DAT1, PB6, SDMMC3, RSVD0, RSVD1, SDMMC3, SPI3, SDMMC3, INPUT, 0x339c),\
+ PINGROUP(SDMMC3_DAT2, PB5, SDMMC3, RSVD0, PWM1, SDMMC3, SPI3, SDMMC3, INPUT, 0x33a0),\
+ PINGROUP(SDMMC3_DAT3, PB4, SDMMC3, RSVD0, PWM0, SDMMC3, INVALID, SDMMC3, INPUT, 0x33a4),\
+ 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(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),\
+ PINGROUP(PEX_WAKE_N, PDD3, PEXCTL, PCIE, HDA, RSVD2, RSVD3, PCIE, INPUT, 0x33c4),\
+ PINGROUP(PEX_L1_PRSNT_N, PDD4, PEXCTL, PCIE, HDA, RSVD2, RSVD3, PCIE, INPUT, 0x33c8),\
+ PINGROUP(PEX_L1_RST_N, PDD5, PEXCTL, PCIE, HDA, RSVD2, RSVD3, PCIE, INPUT, 0x33cc),\
+ PINGROUP(PEX_L1_CLKREQ_N, PDD6, PEXCTL, PCIE, HDA, RSVD2, RSVD3, PCIE, INPUT, 0x33d0),\
+ PINGROUP(PEX_L2_PRSNT_N, PDD7, PEXCTL, PCIE, HDA, RSVD2, RSVD3, PCIE, INPUT, 0x33d4),\
+ PINGROUP(PEX_L2_RST_N, PCC6, PEXCTL, PCIE, HDA, RSVD2, RSVD3, PCIE, INPUT, 0x33d8),\
+ PINGROUP(PEX_L2_CLKREQ_N, PCC7, PEXCTL, PCIE, HDA, RSVD2, RSVD3, PCIE, INPUT, 0x33dc),\
PINGROUP(HDMI_CEC, PEE3, SYS, CEC, RSVD1, RSVD2, RSVD3, RSVD, INPUT, 0x33e0),\
/* END OF LIST */
diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c
index ed6c01fe8544..d1178a820f39 100644
--- a/arch/arm/mach-tegra/platsmp.c
+++ b/arch/arm/mach-tegra/platsmp.c
@@ -290,7 +290,10 @@ void __init platform_smp_prepare_cpus(unsigned int max_cpus)
#if defined(CONFIG_HAVE_ARM_SCU)
{
- u32 scu_ctrl = __raw_readl(scu_base) | 1 << 3;
+ 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);
}
diff --git a/arch/arm/mach-tegra/pm-irq.c b/arch/arm/mach-tegra/pm-irq.c
index 57d21361ca14..4a3f3c31830c 100644
--- a/arch/arm/mach-tegra/pm-irq.c
+++ b/arch/arm/mach-tegra/pm-irq.c
@@ -29,6 +29,7 @@
#include <mach/iomap.h>
#include "pm-irq.h"
+#include "wakeups.h"
#define PMC_CTRL 0x0
#define PMC_CTRL_LATCH_WAKEUPS (1 << 5)
@@ -144,12 +145,15 @@ static inline void clear_pmc_sw_wake_status(void)
int tegra_pm_irq_set_wake(int irq, int enable)
{
- int wake = tegra_irq_to_wake(irq);
+ struct wake_mask_types wake_msk;
+ int flow_type = -1;
+ int err;
- if (wake == -EALREADY) {
+ err = tegra_irq_to_wake(irq, flow_type, &wake_msk);
+ if (err == -EALREADY) {
/* EALREADY means wakeup event already accounted for */
return 0;
- } else if (wake == -ENOTSUPP) {
+ } else if (err == -ENOTSUPP) {
/* ENOTSUPP means LP0 not supported with this wake source */
WARN(enable && warn_prevent_lp0, "irq %d prevents lp0\n", irq);
if (enable)
@@ -157,46 +161,43 @@ int tegra_pm_irq_set_wake(int irq, int enable)
else if (!WARN_ON(tegra_prevent_lp0 == 0))
tegra_prevent_lp0--;
return 0;
- } else if (wake < 0) {
+ } else if (err < 0) {
return -EINVAL;
}
- if (enable) {
- tegra_lp0_wake_enb |= 1ull << wake;
- pr_info("Enabling wake%d\n", wake);
- } else {
- tegra_lp0_wake_enb &= ~(1ull << wake);
- pr_info("Disabling wake%d\n", wake);
- }
+ if (enable)
+ tegra_lp0_wake_enb |= (wake_msk.wake_mask_hi |
+ wake_msk.wake_mask_lo | wake_msk.wake_mask_any);
+ else
+ tegra_lp0_wake_enb &= ~(wake_msk.wake_mask_hi |
+ wake_msk.wake_mask_lo | wake_msk.wake_mask_any);
return 0;
}
int tegra_pm_irq_set_wake_type(int irq, int flow_type)
{
- int wake = tegra_irq_to_wake(irq);
+ struct wake_mask_types wake_msk;
+ int err;
+
+ err = tegra_irq_to_wake(irq, flow_type, &wake_msk);
- if (wake < 0)
+ if (err < 0)
return 0;
- switch (flow_type) {
- case IRQF_TRIGGER_FALLING:
- case IRQF_TRIGGER_LOW:
- tegra_lp0_wake_level &= ~(1ull << wake);
- tegra_lp0_wake_level_any &= ~(1ull << wake);
- break;
- case IRQF_TRIGGER_HIGH:
- case IRQF_TRIGGER_RISING:
- tegra_lp0_wake_level |= (1ull << wake);
- tegra_lp0_wake_level_any &= ~(1ull << wake);
- break;
-
- case IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING:
- tegra_lp0_wake_level_any |= (1ull << wake);
- break;
- default:
- return -EINVAL;
- }
+ /* configure LOW/FALLING polarity wake sources for an irq */
+ tegra_lp0_wake_level &= ~wake_msk.wake_mask_lo;
+ tegra_lp0_wake_level_any &= ~wake_msk.wake_mask_lo;
+
+ /* configure HIGH/RISING polarity wake sources for an irq */
+ tegra_lp0_wake_level |= wake_msk.wake_mask_hi;
+ tegra_lp0_wake_level_any &= ~wake_msk.wake_mask_hi;
+
+ /*
+ * configure RISING and FALLING i.e. ANY polarity wake
+ * sources for an irq
+ */
+ tegra_lp0_wake_level_any |= wake_msk.wake_mask_any;
return 0;
}
diff --git a/arch/arm/mach-tegra/pm-irq.h b/arch/arm/mach-tegra/pm-irq.h
index 8e87b4bba246..639bfe9c4cc9 100644
--- a/arch/arm/mach-tegra/pm-irq.h
+++ b/arch/arm/mach-tegra/pm-irq.h
@@ -22,8 +22,6 @@
int tegra_pm_irq_set_wake(int irq, int enable);
int tegra_pm_irq_set_wake_type(int irq, int flow_type);
bool tegra_pm_irq_lp0_allowed(void);
-int tegra_irq_to_wake(int irq);
-int tegra_wake_to_irq(int wake);
#else
static inline int tegra_pm_irq_set_wake_type(int irq, int flow_type)
{
diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c
index 72ae30a6a29a..7a08bc1aef24 100644
--- a/arch/arm/mach-tegra/pm.c
+++ b/arch/arm/mach-tegra/pm.c
@@ -140,6 +140,11 @@ struct suspend_context tegra_sctx;
#define PMC_CPUPWROFF_TIMER 0xcc
#define PMC_COREPWROFF_TIMER PMC_WAKE_DELAY
+#define PMC_PWRGATE_TOGGLE 0x30
+#define PWRGATE_TOGGLE_START (1 << 8)
+#define UN_PWRGATE_CPU \
+ (PWRGATE_TOGGLE_START | TEGRA_CPU_POWERGATE_ID(TEGRA_POWERGATE_CPU))
+
#ifdef CONFIG_TEGRA_CLUSTER_CONTROL
#define PMC_SCRATCH4_WAKE_CLUSTER_MASK (1<<31)
#endif
@@ -586,7 +591,6 @@ unsigned int tegra_idle_lp2_last(unsigned int sleep_time, unsigned int flags)
mode |= TEGRA_POWER_PWRREQ_OE;
mode &= ~TEGRA_POWER_EFFECT_LP0;
writel(mode, pmc + PMC_CTRL);
- mode |= flags;
tegra_cluster_switch_time(flags, tegra_cluster_switch_time_id_start);
@@ -598,7 +602,17 @@ unsigned int tegra_idle_lp2_last(unsigned int sleep_time, unsigned int flags)
trace_cpu_cluster(POWER_CPU_CLUSTER_START);
set_power_timers(pdata->cpu_timer, 0,
clk_get_rate_all_locked(tegra_pclk));
- tegra_cluster_switch_prolog(mode);
+ if (flags & TEGRA_POWER_CLUSTER_G) {
+ /*
+ * To reduce the vdd_cpu up latency when LP->G
+ * transition. Before the transition, enable
+ * the vdd_cpu rail.
+ */
+ if (is_lp_cluster())
+ writel(UN_PWRGATE_CPU,
+ pmc + PMC_PWRGATE_TOGGLE);
+ }
+ tegra_cluster_switch_prolog(flags);
} else {
set_power_timers(pdata->cpu_timer, pdata->cpu_off_timer,
clk_get_rate_all_locked(tegra_pclk));
@@ -608,7 +622,7 @@ unsigned int tegra_idle_lp2_last(unsigned int sleep_time, unsigned int flags)
tegra_lp2_set_trigger(sleep_time);
cpu_complex_pm_enter();
- suspend_cpu_complex(mode);
+ suspend_cpu_complex(flags);
tegra_cluster_switch_time(flags, tegra_cluster_switch_time_id_prolog);
flush_cache_all();
/*
@@ -625,7 +639,7 @@ unsigned int tegra_idle_lp2_last(unsigned int sleep_time, unsigned int flags)
tegra_init_cache(false);
tegra_cluster_switch_time(flags, tegra_cluster_switch_time_id_switch);
- restore_cpu_complex(mode);
+ restore_cpu_complex(flags);
cpu_complex_pm_exit();
remain = tegra_lp2_timer_remain();
@@ -633,7 +647,7 @@ unsigned int tegra_idle_lp2_last(unsigned int sleep_time, unsigned int flags)
tegra_lp2_set_trigger(0);
if (flags & TEGRA_POWER_CLUSTER_MASK) {
- tegra_cluster_switch_epilog(mode);
+ tegra_cluster_switch_epilog(flags);
trace_cpu_cluster(POWER_CPU_CLUSTER_DONE);
}
tegra_cluster_switch_time(flags, tegra_cluster_switch_time_id_epilog);
@@ -878,6 +892,8 @@ int tegra_suspend_dram(enum tegra_suspend_mode mode, unsigned int flags)
local_fiq_disable();
+ trace_cpu_suspend(CPU_SUSPEND_START);
+
cpu_pm_enter();
cpu_complex_pm_enter();
@@ -941,6 +957,8 @@ int tegra_suspend_dram(enum tegra_suspend_mode mode, unsigned int flags)
if (pdata && pdata->board_resume)
pdata->board_resume(mode, TEGRA_RESUME_AFTER_CPU);
+ trace_cpu_suspend(CPU_SUSPEND_DONE);
+
local_fiq_enable();
tegra_common_resume();
diff --git a/arch/arm/mach-tegra/powergate.c b/arch/arm/mach-tegra/powergate.c
index 27bc3fc67e48..4c0d8bec276e 100644
--- a/arch/arm/mach-tegra/powergate.c
+++ b/arch/arm/mach-tegra/powergate.c
@@ -19,6 +19,7 @@
*/
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/clk.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
@@ -493,6 +494,7 @@ bool tegra_powergate_is_powered(int id)
status = pmc_read(PWRGATE_STATUS) & (1 << id);
return !!status;
}
+EXPORT_SYMBOL(tegra_powergate_is_powered);
int tegra_powergate_remove_clamping(int id)
{
diff --git a/arch/arm/mach-tegra/sleep-t3.S b/arch/arm/mach-tegra/sleep-t3.S
index 4417da33de38..23e96c605b96 100644
--- a/arch/arm/mach-tegra/sleep-t3.S
+++ b/arch/arm/mach-tegra/sleep-t3.S
@@ -92,6 +92,7 @@
#define CLK_RESET_PLLP_OUTB 0xa8
#define PMC_PLLP_WB0_OVERRIDE 0xf8
+#define PMC_PLLM_WB0_OVERRIDE 0x1dc
#define CLK_RESET_CLK_SOURCE_MSELECT 0x3b4
@@ -517,10 +518,12 @@ tegra3_cpu_clk32k:
tst r0, #PMC_CTRL_SIDE_EFFECT_LP0
beq lp1_clocks_prepare
- /* enable PLLM via PMC in LP0 */
+ /* enable PLLM auto-restart via PMC in LP0; restore override settings */
ldr r0, [r4, #PMC_PLLP_WB0_OVERRIDE]
orr r0, r0, #((1 << 12) | (1 << 11))
str r0, [r4, #PMC_PLLP_WB0_OVERRIDE]
+ ldr r0, [r4, #PMC_SCRATCH2]
+ str r0, [r4, #PMC_PLLM_WB0_OVERRIDE]
mov pc, lr
/* start by jumping to clkm to safely disable PLLs, then jump
diff --git a/arch/arm/mach-tegra/sleep.h b/arch/arm/mach-tegra/sleep.h
index 2557c3f687a8..c57399985ecd 100644
--- a/arch/arm/mach-tegra/sleep.h
+++ b/arch/arm/mach-tegra/sleep.h
@@ -50,6 +50,8 @@
#define TEGRA_IRAM_CODE_AREA (TEGRA_IRAM_BASE + SZ_4K)
+/* PMC_SCRATCH2 is used for PLLM boot state if PLLM auto-restart is enabled */
+#define PMC_SCRATCH2 0x58
/* PMC_SCRATCH37-39 and 41 are used for tegra_pen_lock in Tegra2 idle */
#define PMC_SCRATCH37 0x130
#define PMC_SCRATCH38 0x134
@@ -209,8 +211,8 @@ void tegra_sleep_cpu_save(unsigned long v2p);
void tegra_resume(void);
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
-extern void tegra2_iram_start;
-extern void tegra2_iram_end;
+extern unsigned int tegra2_iram_start;
+extern unsigned int tegra2_iram_end;
int tegra2_cpu_is_resettable_soon(void);
void tegra2_cpu_reset(int cpu);
void tegra2_cpu_set_resettable_soon(void);
@@ -219,8 +221,8 @@ void tegra2_sleep_core(unsigned long v2p);
void tegra2_hotplug_shutdown(void);
void tegra2_sleep_wfi(unsigned long v2p);
#else
-extern void tegra3_iram_start;
-extern void tegra3_iram_end;
+extern unsigned int tegra3_iram_start;
+extern unsigned int tegra3_iram_end;
void tegra3_sleep_core(unsigned long v2p);
void tegra3_sleep_cpu_secondary(unsigned long v2p);
void tegra3_hotplug_shutdown(void);
diff --git a/arch/arm/mach-tegra/syncpt.c b/arch/arm/mach-tegra/syncpt.c
deleted file mode 100644
index 8ebab3801a8a..000000000000
--- a/arch/arm/mach-tegra/syncpt.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2010 Google, Inc.
- *
- * Author:
- * Erik Gilling <konkers@google.com>
- *
- * Copyright (C) 2010, 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.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-
-#include <asm/mach/irq.h>
-
-#include <mach/iomap.h>
-#include <mach/irqs.h>
-
-#define HOST1X_SYNC_OFFSET 0x3000
-#define HOST1X_SYNC_SIZE 0x800
-enum {
- HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS = 0x40,
- HOST1X_SYNC_SYNCPT_THRESH_INT_DISABLE = 0x60
-};
-
-static void syncpt_thresh_mask(struct irq_data *data)
-{
- (void)data;
-}
-
-static void syncpt_thresh_unmask(struct irq_data *data)
-{
- (void)data;
-}
-
-static void syncpt_thresh_cascade(unsigned int irq, struct irq_desc *desc)
-{
- void __iomem *sync_regs = irq_desc_get_handler_data(desc);
- unsigned long reg;
- int id;
- struct irq_chip *chip = irq_desc_get_chip(desc);
-
- chained_irq_enter(chip, desc);
-
- reg = readl(sync_regs + HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS);
-
- for_each_set_bit(id, &reg, 32)
- generic_handle_irq(id + INT_SYNCPT_THRESH_BASE);
-
- chained_irq_exit(chip, desc);
-}
-
-static struct irq_chip syncpt_thresh_irq = {
- .name = "syncpt",
- .irq_mask = syncpt_thresh_mask,
- .irq_unmask = syncpt_thresh_unmask
-};
-
-static int __init syncpt_init_irq(void)
-{
- void __iomem *sync_regs;
- unsigned int i;
- int irq;
-
- sync_regs = ioremap(TEGRA_HOST1X_BASE + HOST1X_SYNC_OFFSET,
- HOST1X_SYNC_SIZE);
- BUG_ON(!sync_regs);
-
- writel(0xffffffffUL,
- sync_regs + HOST1X_SYNC_SYNCPT_THRESH_INT_DISABLE);
- writel(0xffffffffUL,
- sync_regs + HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS);
-
- for (i = 0; i < INT_SYNCPT_THRESH_NR; i++) {
- irq = INT_SYNCPT_THRESH_BASE + i;
- irq_set_chip_and_handler(irq, &syncpt_thresh_irq,
- handle_simple_irq);
- irq_set_chip_data(irq, sync_regs);
- set_irq_flags(irq, IRQF_VALID);
- }
- irq_set_chained_handler(INT_HOST1X_MPCORE_SYNCPT,
- syncpt_thresh_cascade);
- irq_set_handler_data(INT_HOST1X_MPCORE_SYNCPT, sync_regs);
-
- return 0;
-}
-
-core_initcall(syncpt_init_irq);
diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c
index 7c42e7b1481a..b1f1dd3f63c6 100644
--- a/arch/arm/mach-tegra/tegra2_clocks.c
+++ b/arch/arm/mach-tegra/tegra2_clocks.c
@@ -779,8 +779,9 @@ static int tegra2_pll_clk_set_rate(struct clk *c, unsigned long rate)
if (sel->input_rate == 0) {
unsigned long cfreq;
- BUG_ON(c->flags & PLLU);
struct clk_pll_freq_table cfg;
+
+ BUG_ON(c->flags & PLLU);
sel = &cfg;
switch (input_rate) {
@@ -2486,10 +2487,12 @@ struct clk tegra_list_periph_clks[] = {
PERIPH_CLK("tvdac", "tvdac", NULL, 53, 0x194, 0x31E, 250000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), /* requires min voltage */
PERIPH_CLK("disp1", "tegradc.0", NULL, 27, 0x138, 0x31E, 600000000, mux_pllp_plld_pllc_clkm, MUX), /* scales with voltage and process_id */
PERIPH_CLK("disp2", "tegradc.1", NULL, 26, 0x13c, 0x31E, 600000000, mux_pllp_plld_pllc_clkm, MUX), /* scales with voltage and process_id */
- PERIPH_CLK("usbd", "fsl-tegra-udc", NULL, 22, 0, 0x31E, 480000000, mux_clk_m, 0), /* requires min voltage */
+ PERIPH_CLK("usbd", "tegra-udc.0", NULL, 22, 0, 0x31E, 480000000, mux_clk_m, 0), /* requires min voltage */
PERIPH_CLK("usb2", "tegra-ehci.1", NULL, 58, 0, 0x31E, 480000000, mux_clk_m, 0), /* requires min voltage */
PERIPH_CLK("usb3", "tegra-ehci.2", NULL, 59, 0, 0x31E, 480000000, mux_clk_m, 0), /* requires min voltage */
PERIPH_CLK("dsia", "tegradc.0", "dsia", 48, 0, 0x31E, 500000000, mux_plld_out0, 0), /* scales with voltage */
+ PERIPH_CLK("dsi1-fixed", "tegradc.0", "dsi-fixed", 0, 0, 0x31E, 108000000, mux_pllp_out3, PERIPH_NO_ENB),
+ PERIPH_CLK("dsi2-fixed", "tegradc.1", "dsi-fixed", 0, 0, 0x31E, 108000000, mux_pllp_out3, PERIPH_NO_ENB),
PERIPH_CLK("csi", "tegra_camera", "csi", 52, 0, 0x31E, 72000000, mux_pllp_out3, 0),
PERIPH_CLK("isp", "tegra_camera", "isp", 23, 0, 0x31E, 150000000, mux_clk_m, 0), /* same frequency as VI */
PERIPH_CLK("csus", "tegra_camera", "csus", 92, 0, 0x31E, 150000000, mux_clk_m, PERIPH_NO_RESET),
@@ -2503,7 +2506,7 @@ struct clk tegra_list_shared_clks[] = {
SHARED_CLK("avp.sclk", "tegra-avp", "sclk", &tegra_clk_virtual_sclk),
SHARED_CLK("mon.sclk", "tegra-stat-mon", "sclk", &tegra_clk_virtual_sclk),
SHARED_CLK("bsea.sclk", "tegra-aes", "sclk", &tegra_clk_virtual_sclk),
- SHARED_CLK("usbd.sclk", "fsl-tegra-udc", "sclk", &tegra_clk_virtual_sclk),
+ SHARED_CLK("usbd.sclk", "tegra-udc.0", "sclk", &tegra_clk_virtual_sclk),
SHARED_CLK("usb1.sclk", "tegra-ehci.0", "sclk", &tegra_clk_virtual_sclk),
SHARED_CLK("usb2.sclk", "tegra-ehci.1", "sclk", &tegra_clk_virtual_sclk),
SHARED_CLK("usb3.sclk", "tegra-ehci.2", "sclk", &tegra_clk_virtual_sclk),
@@ -2519,7 +2522,7 @@ struct clk tegra_list_shared_clks[] = {
SHARED_CLK("3d.emc", "tegra_gr3d", "emc", &tegra_clk_emc),
SHARED_CLK("2d.emc", "tegra_gr2d", "emc", &tegra_clk_emc),
SHARED_CLK("mpe.emc", "tegra_mpe", "emc", &tegra_clk_emc),
- SHARED_CLK("usbd.emc", "fsl-tegra-udc", "emc", &tegra_clk_emc),
+ SHARED_CLK("usbd.emc", "tegra-udc.0", "emc", &tegra_clk_emc),
SHARED_CLK("usb1.emc", "tegra-ehci.0", "emc", &tegra_clk_emc),
SHARED_CLK("usb2.emc", "tegra-ehci.1", "emc", &tegra_clk_emc),
SHARED_CLK("usb3.emc", "tegra-ehci.2", "emc", &tegra_clk_emc),
@@ -2770,7 +2773,7 @@ unsigned long tegra_emc_to_cpu_ratio(unsigned long cpu_rate)
#ifdef CONFIG_PM_SLEEP
static u32 clk_rst_suspend[RST_DEVICES_NUM + CLK_OUT_ENB_NUM +
- PERIPH_CLK_SOURCE_NUM + 22];
+ PERIPH_CLK_SOURCE_NUM + 24];
static int tegra_clk_suspend(void)
{
@@ -2778,6 +2781,8 @@ static int tegra_clk_suspend(void)
u32 *ctx = clk_rst_suspend;
*ctx++ = clk_readl(OSC_CTRL) & OSC_CTRL_MASK;
+ *ctx++ = clk_readl(tegra_pll_p_out1.reg);
+ *ctx++ = clk_readl(tegra_pll_p_out3.reg);
*ctx++ = clk_readl(tegra_pll_c.reg + PLL_BASE);
*ctx++ = clk_readl(tegra_pll_c.reg + PLL_MISC(&tegra_pll_c));
*ctx++ = clk_readl(tegra_pll_a.reg + PLL_BASE);
@@ -2830,11 +2835,26 @@ static void tegra_clk_resume(void)
unsigned long off, i;
const u32 *ctx = clk_rst_suspend;
u32 val;
+ u32 pll_p_out12, pll_p_out34;
+ u32 pll_m_out1, pll_a_out0, pll_c_out1;
val = clk_readl(OSC_CTRL) & ~OSC_CTRL_MASK;
val |= *ctx++;
clk_writel(val, OSC_CTRL);
+ /* Since we are going to reset devices and switch clock sources in this
+ * function, plls and secondary dividers is required to be enabled. The
+ * actual value will be restored back later. Note that boot plls: pllm,
+ * pllp, and pllu are already configured and enabled.
+ */
+
+ val = PLL_OUT_CLKEN | PLL_OUT_RESET_DISABLE;
+ val |= val << 16;
+ pll_p_out12 = *ctx++;
+ clk_writel(pll_p_out12 | val, tegra_pll_p_out1.reg);
+ pll_p_out34 = *ctx++;
+ clk_writel(pll_p_out34 | val, tegra_pll_p_out3.reg);
+
clk_writel(*ctx++, tegra_pll_c.reg + PLL_BASE);
clk_writel(*ctx++, tegra_pll_c.reg + PLL_MISC(&tegra_pll_c));
clk_writel(*ctx++, tegra_pll_a.reg + PLL_BASE);
@@ -2847,9 +2867,13 @@ static void tegra_clk_resume(void)
clk_writel(*ctx++, tegra_pll_u.reg + PLL_MISC(&tegra_pll_u));
udelay(1000);
- clk_writel(*ctx++, tegra_pll_m_out1.reg);
- clk_writel(*ctx++, tegra_pll_a_out0.reg);
- clk_writel(*ctx++, tegra_pll_c_out1.reg);
+ val = PLL_OUT_CLKEN | PLL_OUT_RESET_DISABLE;
+ pll_m_out1 = *ctx++;
+ clk_writel(pll_m_out1 | val, tegra_pll_m_out1.reg);
+ pll_a_out0 = *ctx++;
+ clk_writel(pll_a_out0 | val, tegra_pll_a_out0.reg);
+ pll_c_out1 = *ctx++;
+ clk_writel(pll_c_out1 | val, tegra_pll_c_out1.reg);
clk_writel(*ctx++, tegra_clk_cclk.reg);
clk_writel(*ctx++, tegra_clk_cclk.reg + SUPER_CLK_DIVIDER);
@@ -2886,6 +2910,13 @@ static void tegra_clk_resume(void)
clk_writel(*ctx++, MISC_CLK_ENB);
clk_writel(*ctx++, CLK_MASK_ARM);
+
+ /* Restore back the actual pll and secondary divider values */
+ clk_writel(pll_p_out12, tegra_pll_p_out1.reg);
+ clk_writel(pll_p_out34, tegra_pll_p_out3.reg);
+ clk_writel(pll_m_out1, tegra_pll_m_out1.reg);
+ clk_writel(pll_a_out0, tegra_pll_a_out0.reg);
+ clk_writel(pll_c_out1, tegra_pll_c_out1.reg);
}
#else
diff --git a/arch/arm/mach-tegra/tegra2_host1x_devices.h b/arch/arm/mach-tegra/tegra2_host1x_devices.h
new file mode 100644
index 000000000000..974154a414dd
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra2_host1x_devices.h
@@ -0,0 +1,26 @@
+/*
+ * drivers/video/tegra/host/tegra2_host1x_devices.h
+ *
+ * Tegra2 Graphics Host Devices
+ *
+ * Copyright (c) 2012, NVIDIA Corporation.
+ *
+ * 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 TEGRA2_HOST1X_DEVICES_H
+#define TEGRA2_HOST1X_DEVICES_H
+
+int tegra2_register_host1x_devices(void);
+
+#endif
diff --git a/arch/arm/mach-tegra/tegra2_mc.c b/arch/arm/mach-tegra/tegra2_mc.c
index 6df9c232c02f..f25a1790a087 100644
--- a/arch/arm/mach-tegra/tegra2_mc.c
+++ b/arch/arm/mach-tegra/tegra2_mc.c
@@ -281,7 +281,8 @@ static int tegra_mc_client_parse(const char *buf, size_t count,
};
int ret = 0, i, token, index = 0;
bool aggregate = false;
- int period, *client_ids, mode;
+ int period, *client_ids;
+ int mode = FILTER_NONE;
u64 address_low = 0;
u64 address_length = 1ull << 32;
@@ -896,8 +897,10 @@ static enum hrtimer_restart sample_timer_function(struct hrtimer *handle)
#define REGISTER_SYSFS(_name, _val) \
tegra_mc_dram_##_name##_kobj = \
kobject_create_and_add(#_name, tegra_mc_dram_kobj); \
- sysfs_create_group(tegra_mc_dram_##_name##_kobj, \
- &tegra_mc_dram_##_name##_attr_group);
+ if (sysfs_create_group(tegra_mc_dram_##_name##_kobj, \
+ &tegra_mc_dram_##_name##_attr_group)) \
+ printk(KERN_ERR "\n sysfs_create_group failed at %s" \
+ " line %d\n", __FILE__, __LINE__);
static int tegra_mc_init(void)
{
diff --git a/arch/arm/mach-tegra/tegra2_usb_phy.c b/arch/arm/mach-tegra/tegra2_usb_phy.c
new file mode 100644
index 000000000000..6e0801625614
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra2_usb_phy.c
@@ -0,0 +1,1938 @@
+/*
+ * arch/arm/mach-tegra/tegra2_usb_phy.c
+ *
+ * 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.
+ *
+ */
+#include <linux/resource.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/ulpi.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <linux/platform_data/tegra_usb.h>
+#include <mach/clk.h>
+#include <mach/iomap.h>
+#include <mach/pinmux.h>
+#include <asm/mach-types.h>
+#include <mach/usb_phy.h>
+#include "tegra_usb_phy.h"
+#include "gpio-names.h"
+#include "fuse.h"
+
+
+#define USB_USBCMD 0x140
+#define USB_USBCMD_RS (1 << 0)
+#define USB_USBCMD_RESET (1 << 1)
+
+#define USB_USBSTS 0x144
+#define USB_USBSTS_PCI (1 << 2)
+#define USB_USBSTS_SRI (1 << 7)
+#define USB_USBSTS_HCH (1 << 12)
+
+#define USB_ASYNCLISTADDR 0x158
+
+#define USB_TXFILLTUNING 0x164
+#define USB_FIFO_TXFILL_THRES(x) (((x) & 0x1f) << 16)
+#define USB_FIFO_TXFILL_MASK 0x1f0000
+
+#define ULPI_VIEWPORT 0x170
+#define ULPI_WAKEUP (1 << 31)
+#define ULPI_RUN (1 << 30)
+#define ULPI_RD_WR (1 << 29)
+
+#define USB_PORTSC 0x184
+#define USB_PORTSC_PTS(x) (((x) & 0x3) << 30)
+#define USB_PORTSC_PSPD(x) (((x) & 0x3) << 26)
+#define USB_PORTSC_PHCD (1 << 23)
+#define USB_PORTSC_WKOC (1 << 22)
+#define USB_PORTSC_WKDS (1 << 21)
+#define USB_PORTSC_WKCN (1 << 20)
+#define USB_PORTSC_PTC(x) (((x) & 0xf) << 16)
+#define USB_PORTSC_PP (1 << 12)
+#define USB_PORTSC_LS(x) (((x) & 0x3) << 10)
+#define USB_PORTSC_SUSP (1 << 7)
+#define USB_PORTSC_OCC (1 << 5)
+#define USB_PORTSC_PEC (1 << 3)
+#define USB_PORTSC_PE (1 << 2)
+#define USB_PORTSC_CSC (1 << 1)
+#define USB_PORTSC_CCS (1 << 0)
+#define USB_PORTSC_RWC_BITS (USB_PORTSC_CSC | USB_PORTSC_PEC | USB_PORTSC_OCC)
+#define USB_PORTSC_PSPD_MASK 3
+
+#define USB_USBMODE_REG_OFFSET 0x1a8
+#define USB_USBMODE_MASK (3 << 0)
+#define USB_USBMODE_HOST (3 << 0)
+#define USB_USBMODE_DEVICE (2 << 0)
+
+#define USB_SUSP_CTRL 0x400
+#define USB_WAKE_ON_CNNT_EN_DEV (1 << 3)
+#define USB_WAKE_ON_DISCON_EN_DEV (1 << 4)
+#define USB_SUSP_CLR (1 << 5)
+#define USB_CLKEN (1 << 6)
+#define USB_PHY_CLK_VALID (1 << 7)
+#define USB_PHY_CLK_VALID_INT_ENB (1 << 9)
+#define UTMIP_RESET (1 << 11)
+#define UHSIC_RESET (1 << 11)
+#define UTMIP_PHY_ENABLE (1 << 12)
+#define UHSIC_PHY_ENABLE (1 << 12)
+#define ULPI_PHY_ENABLE (1 << 13)
+#define USB_SUSP_SET (1 << 14)
+#define USB_WAKEUP_DEBOUNCE_COUNT(x) (((x) & 0x7) << 16)
+#define USB_PHY_CLK_VALID_INT_STS (1 << 8)
+
+#define USB_PHY_VBUS_WAKEUP_ID 0x408
+#define VDAT_DET_INT_EN (1 << 16)
+#define VDAT_DET_CHG_DET (1 << 17)
+#define VDAT_DET_STS (1 << 18)
+#define USB_ID_STATUS (1 << 2)
+
+#define USB1_LEGACY_CTRL 0x410
+#define USB1_NO_LEGACY_MODE (1 << 0)
+#define USB1_VBUS_SENSE_CTL_MASK (3 << 1)
+#define USB1_VBUS_SENSE_CTL_VBUS_WAKEUP (0 << 1)
+#define USB1_VBUS_SENSE_CTL_AB_SESS_VLD_OR_VBUS_WAKEUP \
+ (1 << 1)
+#define USB1_VBUS_SENSE_CTL_AB_SESS_VLD (2 << 1)
+#define USB1_VBUS_SENSE_CTL_A_SESS_VLD (3 << 1)
+
+#define ULPIS2S_CTRL 0x418
+#define ULPIS2S_ENA (1 << 0)
+#define ULPIS2S_SUPPORT_DISCONNECT (1 << 2)
+#define ULPIS2S_PLLU_MASTER_BLASTER60 (1 << 3)
+#define ULPIS2S_SPARE(x) (((x) & 0xF) << 8)
+#define ULPIS2S_FORCE_ULPI_CLK_OUT (1 << 12)
+#define ULPIS2S_DISCON_DONT_CHECK_SE0 (1 << 13)
+#define ULPIS2S_SUPPORT_HS_KEEP_ALIVE (1 << 14)
+#define ULPIS2S_DISABLE_STP_PU (1 << 15)
+#define ULPIS2S_SLV0_CLAMP_XMIT (1 << 16)
+
+#define ULPI_TIMING_CTRL_0 0x424
+#define ULPI_CLOCK_OUT_DELAY(x) ((x) & 0x1F)
+#define ULPI_OUTPUT_PINMUX_BYP (1 << 10)
+#define ULPI_CLKOUT_PINMUX_BYP (1 << 11)
+#define ULPI_SHADOW_CLK_LOOPBACK_EN (1 << 12)
+#define ULPI_SHADOW_CLK_SEL (1 << 13)
+#define ULPI_CORE_CLK_SEL (1 << 14)
+#define ULPI_SHADOW_CLK_DELAY(x) (((x) & 0x1F) << 16)
+#define ULPI_LBK_PAD_EN (1 << 26)
+#define ULPI_LBK_PAD_E_INPUT_OR (1 << 27)
+#define ULPI_CLK_OUT_ENA (1 << 28)
+#define ULPI_CLK_PADOUT_ENA (1 << 29)
+
+#define ULPI_TIMING_CTRL_1 0x428
+#define ULPI_DATA_TRIMMER_LOAD (1 << 0)
+#define ULPI_DATA_TRIMMER_SEL(x) (((x) & 0x7) << 1)
+#define ULPI_STPDIRNXT_TRIMMER_LOAD (1 << 16)
+#define ULPI_STPDIRNXT_TRIMMER_SEL(x) (((x) & 0x7) << 17)
+#define ULPI_DIR_TRIMMER_LOAD (1 << 24)
+#define ULPI_DIR_TRIMMER_SEL(x) (((x) & 0x7) << 25)
+
+#define UTMIP_PLL_CFG1 0x804
+#define UHSIC_PLL_CFG1 0x804
+#define UTMIP_XTAL_FREQ_COUNT(x) (((x) & 0xfff) << 0)
+#define UTMIP_PLLU_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 27)
+#define UHSIC_XTAL_FREQ_COUNT(x) (((x) & 0xfff) << 0)
+#define UHSIC_PLLU_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 14)
+
+#define UTMIP_XCVR_UHSIC_HSRX_CFG0 0x808
+#define UTMIP_XCVR_SETUP(x) (((x) & 0xf) << 0)
+#define UHSIC_ELASTIC_UNDERRUN_LIMIT(x) (((x) & 0x1f) << 2)
+#define UHSIC_ELASTIC_OVERRUN_LIMIT(x) (((x) & 0x1f) << 8)
+#define UTMIP_XCVR_LSRSLEW(x) (((x) & 0x3) << 8)
+#define UTMIP_XCVR_LSFSLEW(x) (((x) & 0x3) << 10)
+#define UHSIC_IDLE_WAIT(x) (((x) & 0x1f) << 13)
+#define UTMIP_FORCE_PD_POWERDOWN (1 << 14)
+#define UTMIP_FORCE_PD2_POWERDOWN (1 << 16)
+#define UTMIP_FORCE_PDZI_POWERDOWN (1 << 18)
+#define UTMIP_XCVR_LSBIAS_SEL (1 << 21)
+#define UTMIP_XCVR_SETUP_MSB(x) (((x) & 0x7) << 22)
+#define UTMIP_XCVR_HSSLEW_MSB(x) (((x) & 0x7f) << 25)
+#define UTMIP_XCVR_MAX_OFFSET 2
+#define UTMIP_XCVR_SETUP_MAX_VALUE 0x7f
+#define UTMIP_XCVR_SETUP_MIN_VALUE 0
+#define XCVR_SETUP_MSB_CALIB(x) ((x) >> 4)
+
+#define UTMIP_BIAS_CFG0 0x80c
+#define UTMIP_OTGPD (1 << 11)
+#define UTMIP_BIASPD (1 << 10)
+
+#define UHSIC_HSRX_CFG1 0x80c
+#define UHSIC_HS_SYNC_START_DLY(x) (((x) & 0x1f) << 1)
+
+#define UTMIP_HSRX_CFG0 0x810
+#define UTMIP_ELASTIC_LIMIT(x) (((x) & 0x1f) << 10)
+#define UTMIP_IDLE_WAIT(x) (((x) & 0x1f) << 15)
+
+#define UTMIP_HSRX_CFG1 0x814
+#define UHSIC_MISC_CFG0 0x814
+#define UTMIP_HS_SYNC_START_DLY(x) (((x) & 0x1f) << 1)
+#define UHSIC_SUSPEND_EXIT_ON_EDGE (1 << 7)
+#define UHSIC_DETECT_SHORT_CONNECT (1 << 8)
+#define UHSIC_FORCE_XCVR_MODE (1 << 15)
+
+#define UHSIC_MISC_CFG1 0x818
+#define UHSIC_PLLU_STABLE_COUNT(x) (((x) & 0xfff) << 2)
+
+#define UHSIC_PADS_CFG0 0x81c
+#define UHSIC_TX_RTUNEN 0xf000
+#define UHSIC_TX_RTUNE(x) (((x) & 0xf) << 12)
+
+#define UTMIP_TX_CFG0 0x820
+#define UHSIC_PADS_CFG1 0x820
+#define UHSIC_PD_BG (1 << 2)
+#define UHSIC_PD_TX (1 << 3)
+#define UHSIC_PD_TRK (1 << 4)
+#define UHSIC_PD_RX (1 << 5)
+#define UHSIC_PD_ZI (1 << 6)
+#define UHSIC_RX_SEL (1 << 7)
+#define UHSIC_RPD_DATA (1 << 9)
+#define UHSIC_RPD_STROBE (1 << 10)
+#define UHSIC_RPU_DATA (1 << 11)
+#define UHSIC_RPU_STROBE (1 << 12)
+#define UTMIP_FS_PREABMLE_J (1 << 19)
+#define UTMIP_HS_DISCON_DISABLE (1 << 8)
+
+#define UTMIP_MISC_CFG0 0x824
+#define UTMIP_DPDM_OBSERVE (1 << 26)
+#define UTMIP_DPDM_OBSERVE_SEL(x) (((x) & 0xf) << 27)
+#define UTMIP_DPDM_OBSERVE_SEL_FS_J UTMIP_DPDM_OBSERVE_SEL(0xf)
+#define UTMIP_DPDM_OBSERVE_SEL_FS_K UTMIP_DPDM_OBSERVE_SEL(0xe)
+#define UTMIP_DPDM_OBSERVE_SEL_FS_SE1 UTMIP_DPDM_OBSERVE_SEL(0xd)
+#define UTMIP_DPDM_OBSERVE_SEL_FS_SE0 UTMIP_DPDM_OBSERVE_SEL(0xc)
+#define UTMIP_SUSPEND_EXIT_ON_EDGE (1 << 22)
+#define FORCE_PULLDN_DM (1 << 8)
+#define FORCE_PULLDN_DP (1 << 9)
+#define COMB_TERMS (1 << 0)
+#define ALWAYS_FREE_RUNNING_TERMS (1 << 1)
+
+#define USB1_PREFETCH_ID 6
+#define USB2_PREFETCH_ID 18
+#define USB3_PREFETCH_ID 17
+
+#define UTMIP_MISC_CFG1 0x828
+#define UTMIP_PLL_ACTIVE_DLY_COUNT(x) (((x) & 0x1f) << 18)
+#define UTMIP_PLLU_STABLE_COUNT(x) (((x) & 0xfff) << 6)
+
+#define UHSIC_STAT_CFG0 0x828
+#define UHSIC_CONNECT_DETECT (1 << 0)
+
+#define UTMIP_DEBOUNCE_CFG0 0x82c
+#define UTMIP_BIAS_DEBOUNCE_A(x) (((x) & 0xffff) << 0)
+
+#define UTMIP_BAT_CHRG_CFG0 0x830
+#define UTMIP_PD_CHRG (1 << 0)
+#define UTMIP_ON_SINK_EN (1 << 2)
+#define UTMIP_OP_SRC_EN (1 << 3)
+
+#define UTMIP_SPARE_CFG0 0x834
+#define FUSE_SETUP_SEL (1 << 3)
+#define FUSE_ATERM_SEL (1 << 4)
+
+#define UTMIP_XCVR_CFG1 0x838
+#define UTMIP_FORCE_PDDISC_POWERDOWN (1 << 0)
+#define UTMIP_FORCE_PDCHRP_POWERDOWN (1 << 2)
+#define UTMIP_FORCE_PDDR_POWERDOWN (1 << 4)
+#define UTMIP_XCVR_TERM_RANGE_ADJ(x) (((x) & 0xf) << 18)
+
+#define UTMIP_BIAS_CFG1 0x83c
+#define UTMIP_BIAS_PDTRK_COUNT(x) (((x) & 0x1f) << 3)
+
+#define FUSE_USB_CALIB_0 0x1F0
+#define FUSE_USB_CALIB_XCVR_SETUP(x) (((x) & 0x7F) << 0)
+
+#define APB_MISC_GP_OBSCTRL_0 0x818
+#define APB_MISC_GP_OBSDATA_0 0x81c
+
+/* ULPI GPIO */
+#define ULPI_STP TEGRA_GPIO_PY3
+#define ULPI_DIR TEGRA_GPIO_PY1
+#define ULPI_D0 TEGRA_GPIO_PO1
+#define ULPI_D1 TEGRA_GPIO_PO2
+
+/* These values (in milli second) are taken from the battery charging spec */
+#define TDP_SRC_ON_MS 100
+#define TDPSRC_CON_MS 40
+
+#ifdef DEBUG
+#define DBG(stuff...) pr_info("tegra2_usb_phy: " stuff)
+#else
+#define DBG(stuff...) do {} while (0)
+#endif
+
+
+static DEFINE_SPINLOCK(utmip_pad_lock);
+static int utmip_pad_count;
+static int utmip_pad_state_on;
+
+static struct tegra_xtal_freq utmip_freq_table[] = {
+ {
+ .freq = 12000000,
+ .enable_delay = 0x02,
+ .stable_count = 0x2F,
+ .active_delay = 0x04,
+ .xtal_freq_count = 0x76,
+ .debounce = 0x7530,
+ .pdtrk_count = 5,
+ },
+ {
+ .freq = 13000000,
+ .enable_delay = 0x02,
+ .stable_count = 0x33,
+ .active_delay = 0x05,
+ .xtal_freq_count = 0x7F,
+ .debounce = 0x7EF4,
+ .pdtrk_count = 5,
+ },
+ {
+ .freq = 19200000,
+ .enable_delay = 0x03,
+ .stable_count = 0x4B,
+ .active_delay = 0x06,
+ .xtal_freq_count = 0xBB,
+ .debounce = 0xBB80,
+ .pdtrk_count = 7,
+ },
+ {
+ .freq = 26000000,
+ .enable_delay = 0x04,
+ .stable_count = 0x66,
+ .active_delay = 0x09,
+ .xtal_freq_count = 0xFE,
+ .debounce = 0xFDE8,
+ .pdtrk_count = 9,
+ },
+};
+
+static struct tegra_xtal_freq uhsic_freq_table[] = {
+ {
+ .freq = 12000000,
+ .enable_delay = 0x02,
+ .stable_count = 0x2F,
+ .active_delay = 0x0,
+ .xtal_freq_count = 0x1CA,
+ },
+ {
+ .freq = 13000000,
+ .enable_delay = 0x02,
+ .stable_count = 0x33,
+ .active_delay = 0x0,
+ .xtal_freq_count = 0x1F0,
+ },
+ {
+ .freq = 19200000,
+ .enable_delay = 0x03,
+ .stable_count = 0x4B,
+ .active_delay = 0x0,
+ .xtal_freq_count = 0x2DD,
+ },
+ {
+ .freq = 26000000,
+ .enable_delay = 0x04,
+ .stable_count = 0x66,
+ .active_delay = 0x0,
+ .xtal_freq_count = 0x3E0,
+ },
+};
+
+static void usb_phy_fence_read(struct tegra_usb_phy *phy)
+{
+ /* Fence read for coherency of AHB master intiated writes */
+ if (phy->inst == 0)
+ readb(IO_ADDRESS(IO_PPCS_PHYS + USB1_PREFETCH_ID));
+ else if (phy->inst == 1)
+ readb(IO_ADDRESS(IO_PPCS_PHYS + USB2_PREFETCH_ID));
+ else if (phy->inst == 2)
+ readb(IO_ADDRESS(IO_PPCS_PHYS + USB3_PREFETCH_ID));
+
+ return;
+}
+
+static int usb_phy_bringup_host_controller(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ DBG("USB_USBSTS[0x%x] USB_PORTSC[0x%x] port_speed[%d] - 0\n",
+ readl(base + USB_USBSTS), readl(base + USB_PORTSC),
+ phy->port_speed);
+
+ /* enable host mode */
+ val = readl(base + USB_USBMODE_REG_OFFSET);
+ val |= USB_USBMODE_HOST;
+ writel(val, base + USB_USBMODE_REG_OFFSET);
+
+ /* Enable Port Power */
+ val = readl(base + USB_PORTSC);
+ val |= USB_PORTSC_PP;
+ writel(val, base + USB_PORTSC);
+ udelay(10);
+
+ /* Check if the phy resume from LP0. When the phy resume from LP0
+ * USB register will be reset.to zero */
+ if (!readl(base + USB_ASYNCLISTADDR)) {
+ val = readl(base + USB_USBCMD);
+ val |= USB_USBCMD_RS;
+ writel(val, base + USB_USBCMD);
+
+ /* 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)
+ val |= USB_PORTSC_PTC(5);
+ else if (phy->port_speed == USB_PHY_PORT_SPEED_FULL)
+ val |= USB_PORTSC_PTC(6);
+ else if (phy->port_speed == USB_PHY_PORT_SPEED_LOW)
+ val |= USB_PORTSC_PTC(7);
+ writel(val, base + USB_PORTSC);
+ udelay(10);
+
+ /* Disable test mode by setting PTC field to NORMAL_OP */
+ val = readl(base + USB_PORTSC);
+ val &= ~(USB_PORTSC_PTC(~0));
+ writel(val, base + USB_PORTSC);
+ udelay(10);
+ }
+
+ /* Poll until CCS is enabled */
+ if (usb_phy_reg_status_wait(base + USB_PORTSC, USB_PORTSC_CCS,
+ USB_PORTSC_CCS, 2000)) {
+ pr_err("%s: timeout waiting for USB_PORTSC_CCS\n", __func__);
+ }
+
+ /* Poll until PE is enabled */
+ if (usb_phy_reg_status_wait(base + USB_PORTSC, USB_PORTSC_PE,
+ USB_PORTSC_PE, 2000)) {
+ pr_err("%s: timeout waiting for USB_PORTSC_PE\n", __func__);
+ }
+
+ /* Clear the PCI status, to avoid an interrupt taken upon resume */
+ val = readl(base + USB_USBSTS);
+ val |= USB_USBSTS_PCI;
+ writel(val, base + USB_USBSTS);
+
+ /* Put controller in suspend mode by writing 1 to SUSP bit of PORTSC */
+ val = readl(base + USB_PORTSC);
+ if ((val & USB_PORTSC_PP) && (val & USB_PORTSC_PE)) {
+ val |= USB_PORTSC_SUSP;
+ writel(val, base + USB_PORTSC);
+ /* Need a 4ms delay before the controller goes to suspend */
+ mdelay(4);
+
+ /* Wait until port suspend completes */
+ if (usb_phy_reg_status_wait(base + USB_PORTSC, USB_PORTSC_SUSP,
+ USB_PORTSC_SUSP, 1000)) {
+ pr_err("%s: timeout waiting for PORT_SUSPEND\n",
+ __func__);
+ }
+ }
+
+ DBG("USB_USBSTS[0x%x] USB_PORTSC[0x%x]\n",
+ readl(base + USB_USBSTS), readl(base + USB_PORTSC));
+
+ return 0;
+}
+
+static void usb_phy_wait_for_sof(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ val = readl(base + USB_USBSTS);
+ writel(val, base + USB_USBSTS);
+ udelay(20);
+ /* wait for two SOFs */
+ if (usb_phy_reg_status_wait(base + USB_USBSTS, USB_USBSTS_SRI,
+ USB_USBSTS_SRI, 2500))
+ pr_err("%s: timeout waiting for SOF\n", __func__);
+
+ val = readl(base + USB_USBSTS);
+ writel(val, base + USB_USBSTS);
+ if (usb_phy_reg_status_wait(base + USB_USBSTS, USB_USBSTS_SRI, 0, 2500))
+ pr_err("%s: timeout waiting for SOF\n", __func__);
+
+ if (usb_phy_reg_status_wait(base + USB_USBSTS, USB_USBSTS_SRI,
+ USB_USBSTS_SRI, 2500))
+ pr_err("%s: timeout waiting for SOF\n", __func__);
+
+ udelay(20);
+}
+
+static unsigned int utmi_phy_xcvr_setup_value(struct tegra_usb_phy *phy)
+{
+ struct tegra_utmi_config *cfg = &phy->pdata->u_cfg.utmi;
+ signed long val;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ if (cfg->xcvr_use_fuses) {
+ val = FUSE_USB_CALIB_XCVR_SETUP(
+ tegra_fuse_readl(FUSE_USB_CALIB_0));
+ if (cfg->xcvr_setup_offset <= UTMIP_XCVR_MAX_OFFSET)
+ val = val + cfg->xcvr_setup_offset;
+
+ if (val > UTMIP_XCVR_SETUP_MAX_VALUE) {
+ val = UTMIP_XCVR_SETUP_MAX_VALUE;
+ pr_info("%s: reset XCVR_SETUP to max value\n",
+ __func__);
+ } else if (val < UTMIP_XCVR_SETUP_MIN_VALUE) {
+ val = UTMIP_XCVR_SETUP_MIN_VALUE;
+ pr_info("%s: reset XCVR_SETUP to min value\n",
+ __func__);
+ }
+ } else {
+ val = cfg->xcvr_setup;
+ }
+
+ return (unsigned int) val;
+}
+
+
+static int utmi_phy_open(struct tegra_usb_phy *phy)
+{
+ unsigned long parent_rate;
+ int i;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ phy->utmi_pad_clk = clk_get_sys("utmip-pad", NULL);
+ if (IS_ERR(phy->utmi_pad_clk)) {
+ pr_err("%s: can't get utmip pad clock\n", __func__);
+ return PTR_ERR(phy->utmi_pad_clk);
+ }
+
+ phy->utmi_xcvr_setup = utmi_phy_xcvr_setup_value(phy);
+
+ parent_rate = clk_get_rate(clk_get_parent(phy->pllu_clk));
+ for (i = 0; i < ARRAY_SIZE(utmip_freq_table); i++) {
+ if (utmip_freq_table[i].freq == parent_rate) {
+ phy->freq = &utmip_freq_table[i];
+ break;
+ }
+ }
+ if (!phy->freq) {
+ pr_err("invalid pll_u parent rate %ld\n", parent_rate);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void utmi_phy_close(struct tegra_usb_phy *phy)
+{
+ DBG("%s inst:[%d]\n", __func__, phy->inst);
+
+ clk_put(phy->utmi_pad_clk);
+}
+
+static int utmi_phy_pad_power_on(struct tegra_usb_phy *phy)
+{
+ unsigned long val, flags;
+ void __iomem *pad_base = IO_ADDRESS(TEGRA_USB_BASE);
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ clk_enable(phy->utmi_pad_clk);
+
+ spin_lock_irqsave(&utmip_pad_lock, flags);
+
+ utmip_pad_count++;
+ val = readl(pad_base + UTMIP_BIAS_CFG0);
+ val &= ~(UTMIP_OTGPD | UTMIP_BIASPD);
+ writel(val, pad_base + UTMIP_BIAS_CFG0);
+ utmip_pad_state_on = true;
+
+ spin_unlock_irqrestore(&utmip_pad_lock, flags);
+
+ clk_disable(phy->utmi_pad_clk);
+
+ return 0;
+}
+
+static int utmi_phy_pad_power_off(struct tegra_usb_phy *phy)
+{
+ unsigned long val, flags;
+ void __iomem *pad_base = IO_ADDRESS(TEGRA_USB_BASE);
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ clk_enable(phy->utmi_pad_clk);
+ spin_lock_irqsave(&utmip_pad_lock, flags);
+
+ if (!utmip_pad_count) {
+ pr_err("%s: utmip pad already powered off\n", __func__);
+ goto out;
+ }
+ if (--utmip_pad_count == 0) {
+ val = readl(pad_base + UTMIP_BIAS_CFG0);
+ val |= UTMIP_OTGPD | UTMIP_BIASPD;
+ writel(val, pad_base + UTMIP_BIAS_CFG0);
+ utmip_pad_state_on = false;
+ }
+out:
+ spin_unlock_irqrestore(&utmip_pad_lock, flags);
+ clk_disable(phy->utmi_pad_clk);
+
+ return 0;
+}
+
+static int utmi_phy_irq(struct tegra_usb_phy *phy)
+{
+ void __iomem *base = phy->regs;
+ unsigned long val = 0;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+
+ usb_phy_fence_read(phy);
+ if (phy->pdata->u_data.host.hot_plug) {
+ val = readl(base + USB_SUSP_CTRL);
+ if ((val & USB_PHY_CLK_VALID_INT_STS)) {
+ 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));
+ }
+ } else if (!phy->phy_clk_on) {
+ return IRQ_NONE;
+ }
+
+ return IRQ_HANDLED;
+}
+
+
+static int utmi_phy_post_resume(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+
+ val = readl(base + UTMIP_TX_CFG0);
+ val &= ~UTMIP_HS_DISCON_DISABLE;
+ writel(val, base + UTMIP_TX_CFG0);
+ return 0;
+}
+
+static int utmi_phy_pre_resume(struct tegra_usb_phy *phy, bool remote_wakeup)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ val = readl(base + UTMIP_TX_CFG0);
+ val |= UTMIP_HS_DISCON_DISABLE;
+ writel(val, base + UTMIP_TX_CFG0);
+
+ usb_phy_wait_for_sof(phy);
+
+ return 0;
+}
+
+static int utmi_phy_power_off(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ if (!phy->phy_clk_on) {
+ DBG("%s(%d) inst:[%d] phy clk is already off\n",
+ __func__, __LINE__, phy->inst);
+ return 0;
+ }
+
+ if (phy->pdata->op_mode == TEGRA_USB_OPMODE_DEVICE) {
+ val = readl(base + USB_SUSP_CTRL);
+ val &= ~(USB_WAKEUP_DEBOUNCE_COUNT(~0));
+ val |= USB_WAKE_ON_CNNT_EN_DEV | USB_WAKEUP_DEBOUNCE_COUNT(5);
+ writel(val, base + USB_SUSP_CTRL);
+
+ val = readl(base + UTMIP_BAT_CHRG_CFG0);
+ val |= UTMIP_PD_CHRG;
+ writel(val, base + UTMIP_BAT_CHRG_CFG0);
+ }
+
+ if (!phy->pdata->u_data.host.hot_plug) {
+ val = readl(base + UTMIP_XCVR_UHSIC_HSRX_CFG0);
+ val |= (UTMIP_FORCE_PD_POWERDOWN | UTMIP_FORCE_PD2_POWERDOWN |
+ UTMIP_FORCE_PDZI_POWERDOWN);
+ writel(val, base + UTMIP_XCVR_UHSIC_HSRX_CFG0);
+ }
+
+ val = readl(base + UTMIP_XCVR_CFG1);
+ val |= UTMIP_FORCE_PDDISC_POWERDOWN | UTMIP_FORCE_PDCHRP_POWERDOWN |
+ UTMIP_FORCE_PDDR_POWERDOWN;
+ writel(val, base + UTMIP_XCVR_CFG1);
+
+ if (phy->inst != 0) {
+ val = readl(base + UTMIP_BIAS_CFG0);
+ val |= UTMIP_OTGPD;
+ writel(val, base + UTMIP_BIAS_CFG0);
+ }
+
+ phy->port_speed = (readl(base + USB_PORTSC) >> 26) &
+ USB_PORTSC_PSPD_MASK;
+
+ if (phy->pdata->u_data.host.hot_plug) {
+ bool enable_hotplug = true;
+ /* if it is OTG port then make sure to enable hot-plug feature
+ only if host adaptor is connected, i.e id is low */
+ if (phy->pdata->port_otg) {
+ val = readl(base + USB_PHY_VBUS_WAKEUP_ID);
+ enable_hotplug = (val & USB_ID_STATUS) ? false : true;
+ }
+ if (enable_hotplug) {
+ val = readl(base + USB_PORTSC);
+ 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*/
+ val = readl(base + USB_SUSP_CTRL);
+ val &= ~USB_PHY_CLK_VALID_INT_ENB;
+ writel(val, base + USB_SUSP_CTRL);
+ }
+ }
+
+ if (phy->inst == 2) {
+ val = readl(base + USB_PORTSC);
+ val |= USB_PORTSC_PHCD;
+ writel(val, base + USB_PORTSC);
+ } else {
+ val = readl(base + USB_SUSP_CTRL);
+ val |= USB_SUSP_SET;
+ writel(val, base + USB_SUSP_CTRL);
+ udelay(10);
+ val = readl(base + USB_SUSP_CTRL);
+ val &= ~USB_SUSP_SET;
+ writel(val, base + USB_SUSP_CTRL);
+ }
+
+ if (usb_phy_reg_status_wait(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID,
+ 0, 2500))
+ pr_warn("%s: timeout waiting for phy to stabilize\n", __func__);
+
+ utmi_phy_pad_power_off(phy);
+
+ phy->phy_clk_on = false;
+ phy->hw_accessible = false;
+
+ DBG("%s(%d) inst:[%d]END\n", __func__, __LINE__, phy->inst);
+
+ return 0;
+}
+
+static int utmi_phy_power_on(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+ struct tegra_utmi_config *config = &phy->pdata->u_cfg.utmi;
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ if (phy->phy_clk_on) {
+ DBG("%s(%d) inst:[%d] phy clk is already on\n",
+ __func__, __LINE__, phy->inst);
+ return 0;
+ }
+
+ val = readl(base + USB_SUSP_CTRL);
+ val |= UTMIP_RESET;
+ writel(val, base + USB_SUSP_CTRL);
+
+ val = readl(base + UTMIP_TX_CFG0);
+ val |= UTMIP_FS_PREABMLE_J;
+ writel(val, base + UTMIP_TX_CFG0);
+
+ val = readl(base + UTMIP_HSRX_CFG0);
+ val &= ~(UTMIP_IDLE_WAIT(~0) | UTMIP_ELASTIC_LIMIT(~0));
+ val |= UTMIP_IDLE_WAIT(config->idle_wait_delay);
+ val |= UTMIP_ELASTIC_LIMIT(config->elastic_limit);
+ writel(val, base + UTMIP_HSRX_CFG0);
+
+ val = readl(base + UTMIP_HSRX_CFG1);
+ val &= ~(UTMIP_HS_SYNC_START_DLY(~0));
+ val |= UTMIP_HS_SYNC_START_DLY(config->hssync_start_delay);
+ writel(val, base + UTMIP_HSRX_CFG1);
+
+ val = readl(base + UTMIP_DEBOUNCE_CFG0);
+ val &= ~UTMIP_BIAS_DEBOUNCE_A(~0);
+ val |= UTMIP_BIAS_DEBOUNCE_A(phy->freq->debounce);
+ writel(val, base + UTMIP_DEBOUNCE_CFG0);
+
+ val = readl(base + UTMIP_MISC_CFG0);
+ val &= ~UTMIP_SUSPEND_EXIT_ON_EDGE;
+ writel(val, base + UTMIP_MISC_CFG0);
+
+ val = readl(base + UTMIP_MISC_CFG1);
+ val &= ~(UTMIP_PLL_ACTIVE_DLY_COUNT(~0) | UTMIP_PLLU_STABLE_COUNT(~0));
+ val |= UTMIP_PLL_ACTIVE_DLY_COUNT(phy->freq->active_delay) |
+ UTMIP_PLLU_STABLE_COUNT(phy->freq->stable_count);
+ writel(val, base + UTMIP_MISC_CFG1);
+
+ val = readl(base + UTMIP_PLL_CFG1);
+ val &= ~(UTMIP_XTAL_FREQ_COUNT(~0) | UTMIP_PLLU_ENABLE_DLY_COUNT(~0));
+ val |= UTMIP_XTAL_FREQ_COUNT(phy->freq->xtal_freq_count) |
+ UTMIP_PLLU_ENABLE_DLY_COUNT(phy->freq->enable_delay);
+ writel(val, base + UTMIP_PLL_CFG1);
+
+ if (phy->pdata->op_mode == TEGRA_USB_OPMODE_DEVICE) {
+ val = readl(base + USB_SUSP_CTRL);
+ val &= ~(USB_WAKE_ON_CNNT_EN_DEV | USB_WAKE_ON_DISCON_EN_DEV);
+ writel(val, base + USB_SUSP_CTRL);
+
+ val = readl(base + UTMIP_BAT_CHRG_CFG0);
+ val &= ~UTMIP_PD_CHRG;
+ writel(val, base + UTMIP_BAT_CHRG_CFG0);
+ } else {
+ val = readl(base + UTMIP_BAT_CHRG_CFG0);
+ val |= UTMIP_PD_CHRG;
+ writel(val, base + UTMIP_BAT_CHRG_CFG0);
+ }
+
+ utmi_phy_pad_power_on(phy);
+
+ val = readl(base + UTMIP_XCVR_UHSIC_HSRX_CFG0);
+ val &= ~(UTMIP_XCVR_LSBIAS_SEL | UTMIP_FORCE_PD_POWERDOWN |
+ UTMIP_FORCE_PD2_POWERDOWN | UTMIP_FORCE_PDZI_POWERDOWN |
+ UTMIP_XCVR_SETUP(~0) | UTMIP_XCVR_LSFSLEW(~0) |
+ UTMIP_XCVR_LSRSLEW(~0) | UTMIP_XCVR_HSSLEW_MSB(~0));
+ val |= UTMIP_XCVR_SETUP(phy->utmi_xcvr_setup);
+ val |= UTMIP_XCVR_SETUP_MSB(XCVR_SETUP_MSB_CALIB(phy->utmi_xcvr_setup));
+ val |= UTMIP_XCVR_LSFSLEW(config->xcvr_lsfslew);
+ val |= UTMIP_XCVR_LSRSLEW(config->xcvr_lsrslew);
+
+ writel(val, base + UTMIP_XCVR_UHSIC_HSRX_CFG0);
+
+ val = readl(base + UTMIP_XCVR_CFG1);
+ val &= ~(UTMIP_FORCE_PDDISC_POWERDOWN | UTMIP_FORCE_PDCHRP_POWERDOWN |
+ UTMIP_FORCE_PDDR_POWERDOWN | UTMIP_XCVR_TERM_RANGE_ADJ(~0));
+ val |= UTMIP_XCVR_TERM_RANGE_ADJ(config->term_range_adj);
+ writel(val, base + UTMIP_XCVR_CFG1);
+
+
+ val = readl(base + UTMIP_BIAS_CFG1);
+ val &= ~(UTMIP_BIAS_PDTRK_COUNT(~0));
+ val |= UTMIP_BIAS_PDTRK_COUNT(phy->freq->pdtrk_count);
+ writel(val, base + UTMIP_BIAS_CFG1);
+
+ val = readl(base + UTMIP_SPARE_CFG0);
+ val &= ~FUSE_SETUP_SEL;
+ writel(val, base + UTMIP_SPARE_CFG0);
+
+ val = readl(base + USB_SUSP_CTRL);
+ val |= UTMIP_PHY_ENABLE;
+ writel(val, base + USB_SUSP_CTRL);
+
+ val = readl(base + USB_SUSP_CTRL);
+ val &= ~UTMIP_RESET;
+ writel(val, base + USB_SUSP_CTRL);
+
+ if (phy->inst == 0) {
+ val = readl(base + USB_SUSP_CTRL);
+ val &= ~USB_SUSP_SET;
+ writel(val, base + USB_SUSP_CTRL);
+ } else {
+ val = readl(base + USB_PORTSC);
+ val &= ~USB_PORTSC_PHCD;
+ writel(val, base + USB_PORTSC);
+ }
+
+ if (usb_phy_reg_status_wait(base + USB_SUSP_CTRL,
+ USB_PHY_CLK_VALID, USB_PHY_CLK_VALID, 2500))
+ pr_warn("%s: timeout waiting for phy to stabilize\n", __func__);
+
+ if (phy->inst == 2) {
+ val = readl(base + USB_PORTSC);
+ val &= ~(USB_PORTSC_PTS(~0));
+ writel(val, base + USB_PORTSC);
+ }
+
+ phy->phy_clk_on = true;
+ phy->hw_accessible = true;
+
+ return 0;
+}
+
+static void utmi_phy_restore_start(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ val = readl(base + UTMIP_MISC_CFG0);
+ val &= ~(UTMIP_DPDM_OBSERVE_SEL(~0));
+
+ if (phy->port_speed == USB_PHY_PORT_SPEED_LOW)
+ val |= UTMIP_DPDM_OBSERVE_SEL_FS_K;
+ else
+ val |= UTMIP_DPDM_OBSERVE_SEL_FS_J;
+ writel(val, base + UTMIP_MISC_CFG0);
+ udelay(1);
+
+ val = readl(base + UTMIP_MISC_CFG0);
+ val |= UTMIP_DPDM_OBSERVE;
+ writel(val, base + UTMIP_MISC_CFG0);
+ udelay(10);
+}
+
+static void utmi_phy_restore_end(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ val = readl(base + UTMIP_MISC_CFG0);
+ val &= ~UTMIP_DPDM_OBSERVE;
+ writel(val, base + UTMIP_MISC_CFG0);
+ udelay(10);
+}
+
+
+static int utmi_phy_resume(struct tegra_usb_phy *phy)
+{
+ int status = 0;
+ unsigned long val, flags;
+ void __iomem *base = phy->regs;
+ void __iomem *pad_base = IO_ADDRESS(TEGRA_USB_BASE);
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ if (phy->pdata->op_mode == TEGRA_USB_OPMODE_HOST) {
+ if (phy->port_speed < USB_PHY_PORT_SPEED_UNKNOWN) {
+ utmi_phy_restore_start(phy);
+ usb_phy_bringup_host_controller(phy);
+ utmi_phy_restore_end(phy);
+ } else {
+ /* device is plugged in when system is in LP0 */
+ /* bring up the controller from LP0*/
+ val = readl(base + USB_USBCMD);
+ val |= USB_USBCMD_RESET;
+ writel(val, base + USB_USBCMD);
+
+ if (usb_phy_reg_status_wait(base + USB_USBCMD,
+ USB_USBCMD_RESET, 0, 2500) < 0) {
+ pr_err("%s: timeout waiting for reset\n", __func__);
+ }
+
+ val = readl(base + USB_USBMODE_REG_OFFSET);
+ val &= ~USB_USBMODE_MASK;
+ val |= USB_USBMODE_HOST;
+ writel(val, base + USB_USBMODE_REG_OFFSET);
+
+ if (phy->inst == 2) {
+ val = readl(base + USB_PORTSC);
+ val &= ~USB_PORTSC_PTS(~0);
+ writel(val, base + USB_PORTSC);
+ }
+ writel(USB_USBCMD_RS, base + USB_USBCMD);
+
+ 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__);
+ }
+
+ /* Enable Port Power */
+ val = readl(base + USB_PORTSC);
+ val |= USB_PORTSC_PP;
+ writel(val, base + USB_PORTSC);
+ udelay(10);
+
+ DBG("USB_USBSTS[0x%x] USB_PORTSC[0x%x]\n",
+ readl(base + USB_USBSTS), readl(base + USB_PORTSC));
+ }
+ } else {
+ /* Restoring the pad powers */
+ clk_enable(phy->utmi_pad_clk);
+
+ spin_lock_irqsave(&utmip_pad_lock, flags);
+
+ val = readl(pad_base + UTMIP_BIAS_CFG0);
+ if (utmip_pad_state_on)
+ val &= ~(UTMIP_OTGPD | UTMIP_BIASPD);
+ else
+ val |= (UTMIP_OTGPD | UTMIP_BIASPD);
+ writel(val, pad_base + UTMIP_BIAS_CFG0);
+
+ spin_unlock_irqrestore(&utmip_pad_lock, flags);
+ clk_disable(phy->utmi_pad_clk);
+ }
+
+ return status;
+}
+
+static bool utmi_phy_charger_detect(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+ bool status;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ /* Enable charger detection logic */
+ val = readl(base + UTMIP_BAT_CHRG_CFG0);
+ val |= UTMIP_OP_SRC_EN | UTMIP_ON_SINK_EN;
+ writel(val, base + UTMIP_BAT_CHRG_CFG0);
+
+ /* Source should be on for 100 ms as per USB charging spec */
+ msleep(TDP_SRC_ON_MS);
+
+ val = readl(base + USB_PHY_VBUS_WAKEUP_ID);
+ /* If charger is not connected disable the interrupt */
+ val &= ~VDAT_DET_INT_EN;
+ val |= VDAT_DET_CHG_DET;
+ writel(val, base + USB_PHY_VBUS_WAKEUP_ID);
+
+ val = readl(base + USB_PHY_VBUS_WAKEUP_ID);
+ if (val & VDAT_DET_STS)
+ status = true;
+ else
+ status = false;
+
+ /* Disable charger detection logic */
+ val = readl(base + UTMIP_BAT_CHRG_CFG0);
+ val &= ~(UTMIP_OP_SRC_EN | UTMIP_ON_SINK_EN);
+ writel(val, base + UTMIP_BAT_CHRG_CFG0);
+
+ /* Delay of 40 ms before we pull the D+ as per battery charger spec */
+ msleep(TDPSRC_CON_MS);
+
+ return status;
+}
+
+
+static int uhsic_phy_open(struct tegra_usb_phy *phy)
+{
+ unsigned long parent_rate;
+ int i;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ parent_rate = clk_get_rate(clk_get_parent(phy->pllu_clk));
+ for (i = 0; i < ARRAY_SIZE(uhsic_freq_table); i++) {
+ if (uhsic_freq_table[i].freq == parent_rate) {
+ phy->freq = &uhsic_freq_table[i];
+ break;
+ }
+ }
+ if (!phy->freq) {
+ pr_err("invalid pll_u parent rate %ld\n", parent_rate);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int uhsic_phy_irq(struct tegra_usb_phy *phy)
+{
+ usb_phy_fence_read(phy);
+ return IRQ_HANDLED;
+}
+
+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) {
+ DBG("%s(%d) inst:[%d] phy clk is already On\n", __func__,
+ __LINE__, phy->inst);
+ return 0;
+ }
+
+ val = readl(base + UHSIC_PADS_CFG1);
+ val &= ~(UHSIC_PD_BG | UHSIC_PD_TX | UHSIC_PD_TRK | UHSIC_PD_RX |
+ UHSIC_PD_ZI | UHSIC_RPD_DATA | UHSIC_RPD_STROBE);
+ val |= UHSIC_RX_SEL;
+ writel(val, base + UHSIC_PADS_CFG1);
+ udelay(2);
+
+ val = readl(base + USB_SUSP_CTRL);
+ val |= UHSIC_RESET;
+ writel(val, base + USB_SUSP_CTRL);
+ udelay(30);
+
+ val = readl(base + USB_SUSP_CTRL);
+ val |= UHSIC_PHY_ENABLE;
+ 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);
+ writel(val, base + UTMIP_XCVR_UHSIC_HSRX_CFG0);
+
+ val = readl(base + UHSIC_HSRX_CFG1);
+ val |= UHSIC_HS_SYNC_START_DLY(config->sync_start_delay);
+ writel(val, base + UHSIC_HSRX_CFG1);
+
+ val = readl(base + UHSIC_MISC_CFG0);
+ val |= UHSIC_SUSPEND_EXIT_ON_EDGE;
+ writel(val, base + UHSIC_MISC_CFG0);
+
+ val = readl(base + UHSIC_MISC_CFG1);
+ val |= UHSIC_PLLU_STABLE_COUNT(phy->freq->stable_count);
+ writel(val, base + UHSIC_MISC_CFG1);
+
+ val = readl(base + UHSIC_PLL_CFG1);
+ val |= UHSIC_PLLU_ENABLE_DLY_COUNT(phy->freq->enable_delay);
+ val |= UHSIC_XTAL_FREQ_COUNT(phy->freq->xtal_freq_count);
+ writel(val, base + UHSIC_PLL_CFG1);
+
+ val = readl(base + USB_SUSP_CTRL);
+ val &= ~(UHSIC_RESET);
+ writel(val, base + USB_SUSP_CTRL);
+ udelay(2);
+
+ val = readl(base + USB_PORTSC);
+ val &= ~(USB_PORTSC_PTS(~0));
+ writel(val, base + USB_PORTSC);
+
+ 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);
+ }
+
+ val = readl(base + USB_PORTSC);
+ val &= ~(USB_PORTSC_WKOC | USB_PORTSC_WKDS | USB_PORTSC_WKCN);
+ writel(val, base + USB_PORTSC);
+
+ val = readl(base + UHSIC_PADS_CFG0);
+ val &= ~(UHSIC_TX_RTUNEN);
+ /* set Rtune impedance to 40 ohm */
+ val |= UHSIC_TX_RTUNE(0);
+ writel(val, base + UHSIC_PADS_CFG0);
+
+ if (usb_phy_reg_status_wait(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID,
+ USB_PHY_CLK_VALID, 2500)) {
+ pr_err("%s: timeout waiting for phy to stabilize\n", __func__);
+ return -ETIMEDOUT;
+ }
+
+ phy->phy_clk_on = true;
+ phy->hw_accessible = true;
+
+ return 0;
+}
+
+static int uhsic_phy_power_off(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ if (!phy->phy_clk_on) {
+ DBG("%s(%d) inst:[%d] phy clk is already off\n", __func__,
+ __LINE__, phy->inst);
+ return 0;
+ }
+
+ val = readl(base + UHSIC_PADS_CFG1);
+ val &= ~UHSIC_RPU_STROBE;
+ val |= UHSIC_RPD_STROBE;
+ writel(val, base + UHSIC_PADS_CFG1);
+
+ val = readl(base + USB_SUSP_CTRL);
+ val |= UHSIC_RESET;
+ writel(val, base + USB_SUSP_CTRL);
+ udelay(30);
+
+ val = readl(base + USB_SUSP_CTRL);
+ val &= ~UHSIC_PHY_ENABLE;
+ writel(val, base + USB_SUSP_CTRL);
+
+ phy->phy_clk_on = false;
+ phy->hw_accessible = false;
+
+ return 0;
+}
+
+static int uhsic_phy_bus_port_power(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+
+ val = readl(base + UHSIC_MISC_CFG0);
+ val |= UHSIC_DETECT_SHORT_CONNECT;
+ writel(val, base + UHSIC_MISC_CFG0);
+ udelay(1);
+
+ val = readl(base + UHSIC_MISC_CFG0);
+ val |= UHSIC_FORCE_XCVR_MODE;
+ writel(val, base + UHSIC_MISC_CFG0);
+
+ val = readl(base + UHSIC_PADS_CFG1);
+ val &= ~UHSIC_RPD_STROBE;
+ val |= UHSIC_RPU_STROBE;
+ writel(val, base + UHSIC_PADS_CFG1);
+
+ val = readl(base + USB_USBCMD);
+ val &= ~USB_USBCMD_RS;
+ writel(val, base + USB_USBCMD);
+
+ if (phy->pdata->ops && phy->pdata->ops->port_power)
+ phy->pdata->ops->port_power();
+
+ if (usb_phy_reg_status_wait(base + UHSIC_STAT_CFG0,
+ UHSIC_CONNECT_DETECT, UHSIC_CONNECT_DETECT, 2000)) {
+ pr_err("%s: timeout waiting for UHSIC_CONNECT_DETECT\n",
+ __func__);
+ return -ETIMEDOUT;
+ }
+
+/* FIXME : need to check whether this piece is required or not
+ if (usb_phy_reg_status_wait(base + USB_PORTSC, USB_PORTSC_LS(2),
+ USB_PORTSC_LS(2), 2000)) {
+ pr_err("%s: timeout waiting for dplus state\n", __func__);
+ return -ETIMEDOUT;
+ }
+*/
+ return 0;
+}
+
+
+static int uhsic_phy_bus_reset(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+
+ val = readl(base + USB_PORTSC);
+ val |= USB_PORTSC_PTC(5);
+ writel(val, base + USB_PORTSC);
+ udelay(2);
+
+ val = readl(base + USB_PORTSC);
+ val &= ~(USB_PORTSC_PTC(~0));
+ writel(val, base + USB_PORTSC);
+ udelay(2);
+
+ if (usb_phy_reg_status_wait(base + USB_PORTSC, USB_PORTSC_LS(0),
+ 0, 2000)) {
+ pr_err("%s: timeout waiting for USB_PORTSC_LS\n", __func__);
+ return -ETIMEDOUT;
+ }
+
+ /* Poll until CCS is enabled */
+ if (usb_phy_reg_status_wait(base + USB_PORTSC, USB_PORTSC_CCS,
+ USB_PORTSC_CCS, 2000)) {
+ pr_err("%s: timeout waiting for USB_PORTSC_CCS\n", __func__);
+ return -ETIMEDOUT;
+ }
+
+ if (usb_phy_reg_status_wait(base + USB_PORTSC, USB_PORTSC_PSPD(2),
+ USB_PORTSC_PSPD(2), 2000)) {
+ pr_err("%s: timeout waiting for USB_PORTSC_PSPD\n", __func__);
+ return -ETIMEDOUT;
+ }
+
+ 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__);
+ return -ETIMEDOUT;
+ }
+
+ val = readl(base + UHSIC_PADS_CFG1);
+ val &= ~UHSIC_RPU_STROBE;
+ val |= UHSIC_RPD_STROBE;
+ writel(val, base + UHSIC_PADS_CFG1);
+
+ mdelay(50);
+
+ val = readl(base + UHSIC_PADS_CFG1);
+ val &= ~UHSIC_RPD_STROBE;
+ val |= UHSIC_RPU_STROBE;
+ writel(val, base + UHSIC_PADS_CFG1);
+
+ val = readl(base + USB_USBCMD);
+ val |= USB_USBCMD_RS;
+ writel(val, base + USB_USBCMD);
+
+ val = readl(base + UHSIC_PADS_CFG1);
+ val &= ~UHSIC_RPU_STROBE;
+ writel(val, base + UHSIC_PADS_CFG1);
+
+ if (usb_phy_reg_status_wait(base + USB_USBCMD, USB_USBCMD_RS,
+ USB_USBCMD_RS, 2000)) {
+ pr_err("%s: timeout waiting for USB_USBCMD_RS\n", __func__);
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+
+static int uhsic_phy_pre_resume(struct tegra_usb_phy *phy, bool remote_wakeup)
+{
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ usb_phy_wait_for_sof(phy);
+
+ return 0;
+}
+
+static int uhsic_phy_resume(struct tegra_usb_phy *phy)
+{
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ uhsic_phy_bus_port_power(phy);
+
+ return 0;
+}
+
+
+static int uhsic_phy_post_resume(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ 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);
+ }
+
+ return 0;
+}
+
+static void ulpi_set_trimmer(struct tegra_usb_phy *phy)
+{
+ struct tegra_ulpi_config *config = &phy->pdata->u_cfg.ulpi;
+ void __iomem *base = phy->regs;
+ unsigned long val;
+
+ val = ULPI_DATA_TRIMMER_SEL(config->data_trimmer);
+ val |= ULPI_STPDIRNXT_TRIMMER_SEL(config->stpdirnxt_trimmer);
+ val |= ULPI_DIR_TRIMMER_SEL(config->dir_trimmer);
+ writel(val, base + ULPI_TIMING_CTRL_1);
+ udelay(10);
+
+ val |= ULPI_DATA_TRIMMER_LOAD;
+ val |= ULPI_STPDIRNXT_TRIMMER_LOAD;
+ val |= ULPI_DIR_TRIMMER_LOAD;
+ writel(val, base + ULPI_TIMING_CTRL_1);
+}
+
+
+static int ulpi_link_phy_open(struct tegra_usb_phy *phy)
+{
+ struct tegra_ulpi_config *config = &phy->pdata->u_cfg.ulpi;
+ int err = 0;
+
+ phy->ulpi_clk = NULL;
+
+ if (config->clk) {
+ phy->ulpi_clk = clk_get_sys(NULL, config->clk);
+ if (IS_ERR(phy->ulpi_clk)) {
+ pr_err("%s: can't get ulpi clock\n", __func__);
+ err = -ENXIO;
+ }
+ }
+
+ phy->ulpi_vp = otg_ulpi_create(&ulpi_viewport_access_ops, 0);
+ phy->ulpi_vp->io_priv = phy->regs + ULPI_VIEWPORT;
+
+ return err;
+}
+
+static void ulpi_link_phy_close(struct tegra_usb_phy *phy)
+{
+ DBG("%s inst:[%d]\n", __func__, phy->inst);
+ if (phy->ulpi_clk)
+ clk_put(phy->ulpi_clk);
+}
+
+static int ulpi_link_phy_irq(struct tegra_usb_phy *phy)
+{
+ usb_phy_fence_read(phy);
+ return IRQ_HANDLED;
+}
+
+static int ulpi_link_phy_power_off(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);
+ if (!phy->phy_clk_on) {
+ DBG("%s(%d) inst:[%d] phy clk is already off\n", __func__,
+ __LINE__, phy->inst);
+ return 0;
+ }
+
+ /* Disable VbusValid, SessEnd comparators */
+ ret = otg_io_write(phy->ulpi_vp, 0x00, 0x0D);
+ if (ret)
+ pr_err("%s: ulpi write 0x0D failed\n", __func__);
+
+ ret = otg_io_write(phy->ulpi_vp, 0x00, 0x10);
+ if (ret)
+ pr_err("%s: ulpi write 0x10 failed\n", __func__);
+
+ /* Disable IdFloat comparator */
+ ret = otg_io_write(phy->ulpi_vp, 0x00, 0x19);
+ if (ret)
+ pr_err("%s: ulpi write 0x19 failed\n", __func__);
+
+ ret = otg_io_write(phy->ulpi_vp, 0x00, 0x1D);
+ if (ret)
+ pr_err("%s: ulpi write 0x1D failed\n", __func__);
+
+ phy->port_speed = (readl(base + USB_PORTSC) >> 26) &
+ USB_PORTSC_PSPD_MASK;
+
+ /* Clear WKCN/WKDS/WKOC wake-on events that can cause the USB
+ * Controller to immediately bring the ULPI PHY out of low power
+ */
+ val = readl(base + USB_PORTSC);
+ val &= ~(USB_PORTSC_WKOC | USB_PORTSC_WKDS | USB_PORTSC_WKCN);
+ writel(val, base + USB_PORTSC);
+
+ /* Put the PHY in the low power mode */
+ val = readl(base + USB_PORTSC);
+ val |= USB_PORTSC_PHCD;
+ writel(val, base + USB_PORTSC);
+
+ if (usb_phy_reg_status_wait(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID,
+ 0, 2500)) {
+ pr_err("%s: timeout waiting for phy to stop\n", __func__);
+ }
+
+ if (phy->ulpi_clk)
+ clk_disable(phy->ulpi_clk);
+
+ phy->phy_clk_on = false;
+ phy->hw_accessible = false;
+
+ return 0;
+}
+
+static int ulpi_link_phy_power_on(struct tegra_usb_phy *phy)
+{
+ int ret;
+ unsigned long val;
+ void __iomem *base = phy->regs;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ if (phy->phy_clk_on) {
+ DBG("%s(%d) inst:[%d] phy clk is already On\n", __func__,
+ __LINE__, phy->inst);
+ return 0;
+ }
+
+ if (phy->ulpi_clk) {
+ clk_enable(phy->ulpi_clk);
+ mdelay(1);
+ }
+
+ val = readl(base + USB_SUSP_CTRL);
+ val |= UHSIC_RESET;
+ writel(val, base + USB_SUSP_CTRL);
+
+ val = readl(base + ULPI_TIMING_CTRL_0);
+ val |= ULPI_OUTPUT_PINMUX_BYP | ULPI_CLKOUT_PINMUX_BYP;
+ writel(val, base + ULPI_TIMING_CTRL_0);
+
+ val = readl(base + USB_SUSP_CTRL);
+ val |= ULPI_PHY_ENABLE;
+ writel(val, base + USB_SUSP_CTRL);
+
+ val = readl(base + USB_SUSP_CTRL);
+ val |= USB_SUSP_CLR;
+ writel(val, base + USB_SUSP_CTRL);
+
+ 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__);
+
+ 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__);
+
+ 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);
+
+ ulpi_set_trimmer(phy);
+
+ /* 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;
+ }
+
+ val = readl(base + USB_PORTSC);
+ val |= USB_PORTSC_WKOC | USB_PORTSC_WKDS | USB_PORTSC_WKCN;
+ writel(val, base + USB_PORTSC);
+
+ phy->phy_clk_on = true;
+ phy->hw_accessible = true;
+
+ return 0;
+}
+
+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_UAA, tristate);
+ tegra_pinmux_set_tristate(TEGRA_PINGROUP_UAB, tristate);
+ tegra_pinmux_set_tristate(TEGRA_PINGROUP_UDA, tristate);
+#endif
+}
+
+static void ulpi_link_phy_restore_start(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+
+ /*Tristate ulpi interface before USB controller resume*/
+ ulpi_link_phy_set_tristate(true);
+
+ val = readl(base + ULPI_TIMING_CTRL_0);
+ val &= ~ULPI_OUTPUT_PINMUX_BYP;
+ writel(val, base + ULPI_TIMING_CTRL_0);
+}
+
+static void ulpi_link_phy_restore_end(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+
+ val = readl(base + ULPI_TIMING_CTRL_0);
+ val |= ULPI_OUTPUT_PINMUX_BYP;
+ writel(val, base + ULPI_TIMING_CTRL_0);
+
+ ulpi_link_phy_set_tristate(false);
+}
+
+static int ulpi_link_phy_resume(struct tegra_usb_phy *phy)
+{
+ int status = 0;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ if (phy->pdata->u_data.host.power_off_on_suspend) {
+ status = ulpi_link_phy_power_on(phy);
+ if (phy->port_speed < USB_PHY_PORT_SPEED_UNKNOWN) {
+ ulpi_link_phy_restore_start(phy);
+ usb_phy_bringup_host_controller(phy);
+ ulpi_link_phy_restore_end(phy);
+ }
+ }
+
+ return status;
+}
+
+static inline void ulpi_pinmux_bypass(struct tegra_usb_phy *phy, bool enable)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+
+ val = readl(base + ULPI_TIMING_CTRL_0);
+
+ if (enable)
+ val |= ULPI_OUTPUT_PINMUX_BYP;
+ else
+ val &= ~ULPI_OUTPUT_PINMUX_BYP;
+
+ writel(val, base + ULPI_TIMING_CTRL_0);
+}
+
+static inline void ulpi_null_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_UDA, tristate);
+ tegra_pinmux_set_tristate(TEGRA_PINGROUP_UAA, tristate);
+ tegra_pinmux_set_tristate(TEGRA_PINGROUP_UAB, tristate);
+#endif
+}
+
+static void ulpi_null_phy_obs_read(void)
+{
+ static void __iomem *apb_misc;
+ unsigned slv0_obs, s2s_obs;
+
+ if (!apb_misc)
+ apb_misc = ioremap(TEGRA_APB_MISC_BASE, TEGRA_APB_MISC_SIZE);
+
+ writel(0x80b10034, apb_misc + APB_MISC_GP_OBSCTRL_0);
+ slv0_obs = readl(apb_misc + APB_MISC_GP_OBSDATA_0);
+
+ writel(0x80b10038, apb_misc + APB_MISC_GP_OBSCTRL_0);
+ s2s_obs = readl(apb_misc + APB_MISC_GP_OBSDATA_0);
+
+ pr_debug("slv0 obs: %08x\ns2s obs: %08x\n", slv0_obs, s2s_obs);
+}
+
+static const struct gpio ulpi_gpios[] = {
+ {ULPI_STP, GPIOF_IN, "ULPI_STP"},
+ {ULPI_DIR, GPIOF_OUT_INIT_LOW, "ULPI_DIR"},
+ {ULPI_D0, GPIOF_OUT_INIT_LOW, "ULPI_D0"},
+ {ULPI_D1, GPIOF_OUT_INIT_LOW, "ULPI_D1"},
+};
+
+static int ulpi_null_phy_open(struct tegra_usb_phy *phy)
+{
+ struct tegra_ulpi_config *config = &phy->pdata->u_cfg.ulpi;
+ int ret;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+
+ ret = gpio_request_array(ulpi_gpios, ARRAY_SIZE(ulpi_gpios));
+ if (ret)
+ return ret;
+
+ if (gpio_is_valid(config->phy_restore_gpio)) {
+ ret = gpio_request(config->phy_restore_gpio, "phy_restore");
+ if (ret)
+ goto err_gpio_free;
+
+ gpio_direction_input(config->phy_restore_gpio);
+ }
+
+ tegra_periph_reset_assert(phy->ctrlr_clk);
+ udelay(10);
+ tegra_periph_reset_deassert(phy->ctrlr_clk);
+
+ return 0;
+
+err_gpio_free:
+ gpio_free_array(ulpi_gpios, ARRAY_SIZE(ulpi_gpios));
+ return ret;
+}
+
+static void ulpi_null_phy_close(struct tegra_usb_phy *phy)
+{
+ struct tegra_ulpi_config *config = &phy->pdata->u_cfg.ulpi;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+
+ if (gpio_is_valid(config->phy_restore_gpio))
+ gpio_free(config->phy_restore_gpio);
+
+ gpio_free_array(ulpi_gpios, ARRAY_SIZE(ulpi_gpios));
+}
+
+static int ulpi_null_phy_power_off(struct tegra_usb_phy *phy)
+{
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+
+ if (!phy->phy_clk_on) {
+ DBG("%s(%d) inst:[%d] phy clk is already off\n", __func__,
+ __LINE__, phy->inst);
+ return 0;
+ }
+
+ phy->phy_clk_on = false;
+ phy->hw_accessible = false;
+ ulpi_null_phy_set_tristate(true);
+ return 0;
+}
+
+static int ulpi_null_phy_irq(struct tegra_usb_phy *phy)
+{
+ usb_phy_fence_read(phy);
+ return IRQ_HANDLED;
+}
+
+static int ulpi_null_phy_restore(struct tegra_usb_phy *phy)
+{
+ struct tegra_ulpi_config *config = &phy->pdata->u_cfg.ulpi;
+ unsigned long timeout;
+ int ulpi_stp = ULPI_STP;
+
+ if (gpio_is_valid(config->phy_restore_gpio))
+ ulpi_stp = config->phy_restore_gpio;
+
+ /* disable ULPI pinmux bypass */
+ ulpi_pinmux_bypass(phy, false);
+
+ /* driving linstate by GPIO */
+ gpio_set_value(ULPI_D0, 0);
+ gpio_set_value(ULPI_D1, 0);
+
+ /* driving DIR high */
+ gpio_set_value(ULPI_DIR, 1);
+
+ /* remove ULPI tristate */
+ ulpi_null_phy_set_tristate(false);
+
+ /* wait for STP high */
+ timeout = jiffies + msecs_to_jiffies(25);
+
+ while (!gpio_get_value(ulpi_stp)) {
+ if (time_after(jiffies, timeout)) {
+ pr_warn("phy restore timeout\n");
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int ulpi_null_phy_lp0_resume(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+
+ val = readl(base + USB_USBCMD);
+ val |= USB_USBCMD_RESET;
+ writel(val, base + USB_USBCMD);
+
+ if (usb_phy_reg_status_wait(base + USB_USBCMD,
+ USB_USBCMD_RESET, 0, 2500) < 0) {
+ pr_err("%s: timeout waiting for reset\n", __func__);
+ }
+
+ val = readl(base + USB_USBMODE_REG_OFFSET);
+ val &= ~USB_USBMODE_MASK;
+ val |= USB_USBMODE_HOST;
+ writel(val, base + USB_USBMODE_REG_OFFSET);
+
+ val = readl(base + USB_USBCMD);
+ val |= USB_USBCMD_RS;
+ writel(val, base + USB_USBCMD);
+ if (usb_phy_reg_status_wait(base + USB_USBCMD, USB_USBCMD_RS,
+ USB_USBCMD_RS, 2000)) {
+ pr_err("%s: timeout waiting for USB_USBCMD_RS\n", __func__);
+ return -ETIMEDOUT;
+ }
+
+ /* Enable Port Power */
+ val = readl(base + USB_PORTSC);
+ val |= USB_PORTSC_PP;
+ writel(val, base + USB_PORTSC);
+ udelay(10);
+
+ ulpi_null_phy_restore(phy);
+
+ return 0;
+}
+
+static int ulpi_null_phy_power_on(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+ struct tegra_ulpi_config *config = &phy->pdata->u_cfg.ulpi;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ if (phy->phy_clk_on) {
+ DBG("%s(%d) inst:[%d] phy clk is already On\n", __func__,
+ __LINE__, phy->inst);
+ return 0;
+ }
+
+ val = readl(base + USB_SUSP_CTRL);
+ val |= UHSIC_RESET;
+ writel(val, base + USB_SUSP_CTRL);
+
+ val = readl(base + ULPI_TIMING_CTRL_0);
+ val |= ULPI_OUTPUT_PINMUX_BYP | ULPI_CLKOUT_PINMUX_BYP;
+ writel(val, base + ULPI_TIMING_CTRL_0);
+
+ val = readl(base + USB_SUSP_CTRL);
+ val |= ULPI_PHY_ENABLE;
+ writel(val, base + USB_SUSP_CTRL);
+ udelay(10);
+
+ /* set timming parameters */
+ val = readl(base + ULPI_TIMING_CTRL_0);
+ val |= ULPI_SHADOW_CLK_LOOPBACK_EN;
+ val |= ULPI_SHADOW_CLK_SEL;
+ val |= ULPI_LBK_PAD_EN;
+ val |= ULPI_SHADOW_CLK_DELAY(config->shadow_clk_delay);
+ val |= ULPI_CLOCK_OUT_DELAY(config->clock_out_delay);
+ val |= ULPI_LBK_PAD_E_INPUT_OR;
+ writel(val, base + ULPI_TIMING_CTRL_0);
+
+ writel(0, base + ULPI_TIMING_CTRL_1);
+ udelay(10);
+
+ /* start internal 60MHz clock */
+ val = readl(base + ULPIS2S_CTRL);
+ val |= ULPIS2S_ENA;
+ val |= ULPIS2S_SUPPORT_DISCONNECT;
+ val |= ULPIS2S_SPARE((phy->pdata->op_mode == TEGRA_USB_OPMODE_HOST) ? 3 : 1);
+ val |= ULPIS2S_PLLU_MASTER_BLASTER60;
+ writel(val, base + ULPIS2S_CTRL);
+
+ /* select ULPI_CORE_CLK_SEL to SHADOW_CLK */
+ val = readl(base + ULPI_TIMING_CTRL_0);
+ val |= ULPI_CORE_CLK_SEL;
+ writel(val, base + ULPI_TIMING_CTRL_0);
+ udelay(10);
+
+ /* enable ULPI null phy clock - can't set the trimmers before this */
+ val = readl(base + ULPI_TIMING_CTRL_0);
+ val |= ULPI_CLK_OUT_ENA;
+ writel(val, base + ULPI_TIMING_CTRL_0);
+ udelay(10);
+
+ if (usb_phy_reg_status_wait(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID,
+ USB_PHY_CLK_VALID, 2500)) {
+ pr_err("%s: timeout waiting for phy to stabilize\n", __func__);
+ return -ETIMEDOUT;
+ }
+
+ /* set ULPI trimmers */
+ ulpi_set_trimmer(phy);
+
+ if (!phy->ulpi_clk_padout_ena) {
+ val = readl(base + ULPI_TIMING_CTRL_0);
+ val |= ULPI_CLK_PADOUT_ENA;
+ writel(val, base + ULPI_TIMING_CTRL_0);
+ phy->ulpi_clk_padout_ena = true;
+ } else {
+ if (!readl(base + USB_ASYNCLISTADDR))
+ ulpi_null_phy_lp0_resume(phy);
+ }
+ udelay(10);
+
+ phy->phy_clk_on = true;
+ phy->hw_accessible = true;
+
+ return 0;
+}
+
+static int ulpi_null_phy_pre_resume(struct tegra_usb_phy *phy,
+ bool remote_wakeup)
+{
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ ulpi_null_phy_obs_read();
+ usb_phy_wait_for_sof(phy);
+ ulpi_null_phy_obs_read();
+ return 0;
+}
+
+static int ulpi_null_phy_post_resume(struct tegra_usb_phy *phy)
+{
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ ulpi_null_phy_obs_read();
+ return 0;
+}
+
+static int ulpi_null_phy_resume(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+
+ if (!readl(base + USB_ASYNCLISTADDR)) {
+ /* enable ULPI CLK output pad */
+ val = readl(base + ULPI_TIMING_CTRL_0);
+ val |= ULPI_CLK_PADOUT_ENA;
+ writel(val, base + ULPI_TIMING_CTRL_0);
+
+ /* enable ULPI pinmux bypass */
+ ulpi_pinmux_bypass(phy, true);
+ udelay(5);
+ }
+
+ return 0;
+}
+
+
+
+static struct tegra_usb_phy_ops utmi_phy_ops = {
+ .open = utmi_phy_open,
+ .close = utmi_phy_close,
+ .irq = utmi_phy_irq,
+ .power_on = utmi_phy_power_on,
+ .power_off = utmi_phy_power_off,
+ .pre_resume = utmi_phy_pre_resume,
+ .resume = utmi_phy_resume,
+ .post_resume = utmi_phy_post_resume,
+ .charger_detect = utmi_phy_charger_detect,
+};
+
+static struct tegra_usb_phy_ops uhsic_phy_ops = {
+ .open = uhsic_phy_open,
+ .irq = uhsic_phy_irq,
+ .power_on = uhsic_phy_power_on,
+ .power_off = uhsic_phy_power_off,
+ .pre_resume = uhsic_phy_pre_resume,
+ .resume = uhsic_phy_resume,
+ .post_resume = uhsic_phy_post_resume,
+ .port_power = uhsic_phy_bus_port_power,
+ .bus_reset = uhsic_phy_bus_reset,
+};
+
+static struct tegra_usb_phy_ops ulpi_link_phy_ops = {
+ .open = ulpi_link_phy_open,
+ .close = ulpi_link_phy_close,
+ .irq = ulpi_link_phy_irq,
+ .power_on = ulpi_link_phy_power_on,
+ .power_off = ulpi_link_phy_power_off,
+ .resume = ulpi_link_phy_resume,
+};
+
+static struct tegra_usb_phy_ops ulpi_null_phy_ops = {
+ .open = ulpi_null_phy_open,
+ .close = ulpi_null_phy_close,
+ .irq = ulpi_null_phy_irq,
+ .power_on = ulpi_null_phy_power_on,
+ .power_off = ulpi_null_phy_power_off,
+ .pre_resume = ulpi_null_phy_pre_resume,
+ .resume = ulpi_null_phy_resume,
+ .post_resume = ulpi_null_phy_post_resume,
+};
+
+static struct tegra_usb_phy_ops icusb_phy_ops;
+
+
+static struct tegra_usb_phy_ops *phy_ops[] = {
+ [TEGRA_USB_PHY_INTF_UTMI] = &utmi_phy_ops,
+ [TEGRA_USB_PHY_INTF_ULPI_LINK] = &ulpi_link_phy_ops,
+ [TEGRA_USB_PHY_INTF_ULPI_NULL] = &ulpi_null_phy_ops,
+ [TEGRA_USB_PHY_INTF_HSIC] = &uhsic_phy_ops,
+ [TEGRA_USB_PHY_INTF_ICUSB] = &icusb_phy_ops,
+};
+
+int tegra2_usb_phy_init_ops(struct tegra_usb_phy *phy)
+{
+ phy->ops = phy_ops[phy->pdata->phy_intf];
+
+ return 0;
+}
diff --git a/arch/arm/mach-tegra/tegra3_actmon.c b/arch/arm/mach-tegra/tegra3_actmon.c
index 5df6ed1fc471..a76d0a963d90 100644
--- a/arch/arm/mach-tegra/tegra3_actmon.c
+++ b/arch/arm/mach-tegra/tegra3_actmon.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 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
@@ -532,7 +532,7 @@ static struct actmon_dev actmon_dev_avp = {
.boost_freq_step = 8000,
.boost_up_coef = 200,
.boost_down_coef = 50,
- .boost_up_threshold = 75,
+ .boost_up_threshold = 85,
.boost_down_threshold = 50,
.up_wmark_window = 1,
diff --git a/arch/arm/mach-tegra/tegra3_clocks.c b/arch/arm/mach-tegra/tegra3_clocks.c
index 262b7a5cedad..110c8d4e601c 100644
--- a/arch/arm/mach-tegra/tegra3_clocks.c
+++ b/arch/arm/mach-tegra/tegra3_clocks.c
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-tegra/tegra3_clocks.c
*
- * 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
@@ -228,6 +228,14 @@
#define PMC_PLLP_WB0_OVERRIDE 0xf8
#define PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE (1 << 12)
+#define PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE (1 << 11)
+#define PMC_PLLM_WB0_OVERRIDE 0x1dc
+#define PMC_PLLM_WB0_OVERRIDE_DIVP_MASK (0x7<<15)
+#define PMC_PLLM_WB0_OVERRIDE_DIVP_SHIFT 15
+#define PMC_PLLM_WB0_OVERRIDE_DIVN_MASK (0x3FF<<5)
+#define PMC_PLLM_WB0_OVERRIDE_DIVN_SHIFT 5
+#define PMC_PLLM_WB0_OVERRIDE_DIVM_MASK (0x1F)
+#define PMC_PLLM_WB0_OVERRIDE_DIVM_SHIFT 0
#define UTMIP_PLL_CFG2 0x488
#define UTMIP_PLL_CFG2_STABLE_COUNT(x) (((x) & 0xfff) << 6)
@@ -284,7 +292,7 @@
#define PLLE_SS_COEFFICIENTS_12MHZ \
((0x18<<PLLE_SS_INCINTRV_SHIFT) | (0x1<<PLLE_SS_INC_SHIFT) | \
(0x24<<PLLE_SS_MAX_SHIFT))
-#define PLLE_SS_DISABLE ((1<<12) | (1<<11) | (1<<10))
+#define PLLE_SS_DISABLE ((1<<14) | (1<<12) | (1<<11) | (1<<10))
#define PLLE_AUX 0x48c
#define PLLE_AUX_PLLP_SEL (1<<2)
@@ -306,6 +314,8 @@
static void tegra3_pllp_init_dependencies(unsigned long pllp_rate);
static int tegra3_clk_shared_bus_update(struct clk *bus);
+static int tegra3_emc_relock_set_rate(struct clk *emc, unsigned long old_rate,
+ unsigned long new_rate, unsigned long new_pll_rate);
static unsigned long cpu_stay_on_backup_max;
static struct clk *emc_bridge;
@@ -1457,6 +1467,30 @@ static void tegra3_utmi_param_configure(struct clk *c)
clk_writel(reg, UTMIP_PLL_CFG1);
}
+static void tegra3_pll_m_override_update(struct clk *c, bool init)
+{
+ u32 val = pmc_readl(PMC_PLLP_WB0_OVERRIDE);
+
+ if (!(val & PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE))
+ return;
+
+ /* override PLLM state with PMC settings */
+ c->state = (val & PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE) ? ON : OFF;
+
+ val = pmc_readl(PMC_PLLM_WB0_OVERRIDE);
+ c->mul = (val & PMC_PLLM_WB0_OVERRIDE_DIVN_MASK) >>
+ PMC_PLLM_WB0_OVERRIDE_DIVN_SHIFT;
+ c->div = (val & PMC_PLLM_WB0_OVERRIDE_DIVM_MASK) >>
+ PMC_PLLM_WB0_OVERRIDE_DIVM_SHIFT;
+ c->div *= (0x1 << ((val & PMC_PLLM_WB0_OVERRIDE_DIVP_MASK) >>
+ PMC_PLLM_WB0_OVERRIDE_DIVP_SHIFT));
+
+ /* Save initial override settings in Scratch2 register; will be used by
+ LP0 entry code to restore PLLM boot configuration */
+ if (init)
+ pmc_writel(val, PMC_SCRATCH2);
+}
+
static void tegra3_pll_clk_init(struct clk *c)
{
u32 val = clk_readl(c->reg + PLL_BASE);
@@ -1498,6 +1532,9 @@ static void tegra3_pll_clk_init(struct clk *c)
if (c->flags & PLLU) {
tegra3_utmi_param_configure(c);
}
+
+ if (c->flags & PLLM)
+ tegra3_pll_m_override_update(c, true);
}
static int tegra3_pll_clk_enable(struct clk *c)
@@ -1542,6 +1579,27 @@ static void tegra3_pll_clk_disable(struct clk *c)
}
}
+static int tegra3_pllm_override_rate(
+ struct clk *c, const struct clk_pll_freq_table *sel, u32 p_div)
+{
+ u32 val, old_base;
+
+ old_base = val = pmc_readl(PMC_PLLM_WB0_OVERRIDE);
+
+ /* Keep default CPCON and DCCON in override configuration */
+ val &= ~(PMC_PLLM_WB0_OVERRIDE_DIVM_MASK |
+ PMC_PLLM_WB0_OVERRIDE_DIVN_MASK |
+ PMC_PLLM_WB0_OVERRIDE_DIVP_MASK);
+ val |= (sel->m << PMC_PLLM_WB0_OVERRIDE_DIVM_SHIFT) |
+ (sel->n << PMC_PLLM_WB0_OVERRIDE_DIVN_SHIFT) |
+ (p_div << PMC_PLLM_WB0_OVERRIDE_DIVP_SHIFT);
+
+ if (val != old_base)
+ pmc_writel(val, PMC_PLLM_WB0_OVERRIDE);
+
+ return 0;
+}
+
static int tegra3_pll_clk_set_rate(struct clk *c, unsigned long rate)
{
u32 val, p_div, old_base;
@@ -1561,7 +1619,7 @@ static int tegra3_pll_clk_set_rate(struct clk *c, unsigned long rate)
return ret;
}
- if (c->flags & PLLM) {
+ if ((c->flags & PLLM) && (c->state == ON)) {
if (rate != clk_get_rate_locked(c)) {
pr_err("%s: Can not change memory %s rate in flight\n",
__func__, c->name);
@@ -1643,6 +1701,13 @@ static int tegra3_pll_clk_set_rate(struct clk *c, unsigned long rate)
c->mul = sel->n;
c->div = sel->m * sel->p;
+ if (c->flags & PLLM) {
+ val = pmc_readl(PMC_PLLP_WB0_OVERRIDE);
+ if (val & PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE)
+ return tegra3_pllm_override_rate(
+ c, sel, p_div >> PLL_BASE_DIVP_SHIFT);
+ }
+
old_base = val = clk_readl(c->reg + PLL_BASE);
val &= ~(PLL_BASE_DIVM_MASK | PLL_BASE_DIVN_MASK |
((c->flags & PLLU) ? PLLU_BASE_POST_DIV : PLL_BASE_DIVP_MASK));
@@ -1692,12 +1757,14 @@ static void tegra3_pllp_clk_init(struct clk *c)
tegra3_pllp_init_dependencies(c->u.pll.fixed_rate);
}
+#if defined(CONFIG_PM_SLEEP)
static void tegra3_pllp_clk_resume(struct clk *c)
{
unsigned long rate = c->u.pll.fixed_rate;
tegra3_pll_clk_init(c);
BUG_ON(rate != c->u.pll.fixed_rate);
}
+#endif
static struct clk_ops tegra_pllp_ops = {
.init = tegra3_pllp_clk_init,
@@ -2571,8 +2638,15 @@ static int tegra3_emc_clk_set_rate(struct clk *c, unsigned long rate)
* to achieve requested rate. */
p = tegra_emc_predict_parent(rate, &div_value);
div_value += 2; /* emc has fractional DIV_U71 divider */
+
+ /* No matching rate in emc dfs table */
+ if (IS_ERR(p))
+ return PTR_ERR(p);
+
+ /* Table rate found, but need to relock source pll */
if (!p)
- return -EINVAL;
+ return tegra3_emc_relock_set_rate(c, clk_get_rate_locked(c),
+ rate, rate * (div_value / 2));
if (p == c->parent) {
if (div_value == c->div)
@@ -2775,6 +2849,9 @@ static void tegra3_clk_cbus_init(struct clk *c)
{
c->state = OFF;
c->set = true;
+ c->shared_bus_backup.bus_rate =
+ clk_get_rate(c->shared_bus_backup.input) /
+ c->shared_bus_backup.value;
}
static int tegra3_clk_cbus_enable(struct clk *c)
@@ -3011,7 +3088,8 @@ static int tegra3_clk_shared_bus_update(struct clk *bus)
(c->u.shared_bus_user.mode == SHARED_CEILING)) {
switch (c->u.shared_bus_user.mode) {
case SHARED_BW:
- bw += c->u.shared_bus_user.rate;
+ if (bw < bus->max_rate)
+ bw += c->u.shared_bus_user.rate;
break;
case SHARED_CEILING:
ceiling = min(c->u.shared_bus_user.rate,
@@ -3024,6 +3102,16 @@ 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 = (bw < bus->max_rate / 100) ?
+ (bw * 100) : bus->max_rate;
+ }
+ bw = clk_round_rate_locked(bus, bw);
+ }
rate = min(max(rate, bw), ceiling);
old_rate = clk_get_rate_locked(bus);
@@ -3072,6 +3160,10 @@ static long tegra_clk_shared_bus_round_rate(struct clk *c, unsigned long rate)
if (c->u.shared_bus_user.mode == SHARED_AUTO)
rate = 0;
+ /* BW users should not be rounded until aggregated */
+ if (c->u.shared_bus_user.mode == SHARED_BW)
+ return rate;
+
return clk_round_rate(c->parent, rate);
}
@@ -3993,7 +4085,7 @@ static struct clk_mux_sel mux_pllm_pllc_pllp_plla[] = {
static struct clk_mux_sel mux_pllm_pllc_pllp_clkm[] = {
{ .input = &tegra_pll_m, .value = 0},
- /* { .input = &tegra_pll_c, .value = 1}, not used on tegra3 */
+ { .input = &tegra_pll_c, .value = 1},
{ .input = &tegra_pll_p, .value = 2},
{ .input = &tegra_clk_m, .value = 3},
{ 0, 0},
@@ -4117,6 +4209,9 @@ static struct clk tegra_clk_emc = {
.u.periph = {
.clk_num = 57,
},
+ .shared_bus_backup = {
+ .input = &tegra_pll_c,
+ },
.rate_change_nh = &emc_rate_change_nh,
};
@@ -4233,6 +4328,7 @@ struct clk tegra_list_clks[] = {
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("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),
@@ -4274,11 +4370,13 @@ struct clk tegra_list_clks[] = {
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),
PERIPH_CLK("disp2", "tegradc.1", NULL, 26, 0x13c, 600000000, mux_pllp_pllm_plld_plla_pllc_plld2_clkm, MUX | MUX8),
- PERIPH_CLK("usbd", "fsl-tegra-udc", NULL, 22, 0, 480000000, mux_clk_m, 0), /* requires min voltage */
+ PERIPH_CLK("usbd", "tegra-udc.0", NULL, 22, 0, 480000000, mux_clk_m, 0), /* requires min voltage */
PERIPH_CLK("usb2", "tegra-ehci.1", NULL, 58, 0, 480000000, mux_clk_m, 0), /* requires min voltage */
PERIPH_CLK("usb3", "tegra-ehci.2", NULL, 59, 0, 480000000, mux_clk_m, 0), /* requires min voltage */
PERIPH_CLK("dsia", "tegradc.0", "dsia", 48, 0, 500000000, mux_plld_out0, 0),
PERIPH_CLK_EX("dsib", "tegradc.1", "dsib", 82, 0xd0, 500000000, mux_plld_out0_plld2_out0, MUX | PLLD, &tegra_dsib_clk_ops),
+ PERIPH_CLK("dsi1-fixed", "tegradc.0", "dsi-fixed", 0, 0, 108000000, mux_pllp_out3, PERIPH_NO_ENB),
+ PERIPH_CLK("dsi2-fixed", "tegradc.1", "dsi-fixed", 0, 0, 108000000, mux_pllp_out3, PERIPH_NO_ENB),
PERIPH_CLK("csi", "tegra_camera", "csi", 52, 0, 102000000, mux_pllp_out3, 0),
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),
@@ -4296,7 +4394,7 @@ struct clk tegra_list_clks[] = {
SHARED_CLK("avp.sclk", "tegra-avp", "sclk", &tegra_clk_sbus_cmplx, NULL, 0, 0),
SHARED_CLK("bsea.sclk", "tegra-aes", "sclk", &tegra_clk_sbus_cmplx, NULL, 0, 0),
- SHARED_CLK("usbd.sclk", "fsl-tegra-udc", "sclk", &tegra_clk_sbus_cmplx, NULL, 0, 0),
+ SHARED_CLK("usbd.sclk", "tegra-udc.0", "sclk", &tegra_clk_sbus_cmplx, NULL, 0, 0),
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),
@@ -4316,7 +4414,7 @@ struct clk tegra_list_clks[] = {
SHARED_CLK("disp1.emc", "tegradc.0", "emc", &tegra_clk_emc, NULL, 0, SHARED_BW),
SHARED_CLK("disp2.emc", "tegradc.1", "emc", &tegra_clk_emc, NULL, 0, SHARED_BW),
SHARED_CLK("hdmi.emc", "hdmi", "emc", &tegra_clk_emc, NULL, 0, 0),
- SHARED_CLK("usbd.emc", "fsl-tegra-udc", "emc", &tegra_clk_emc, NULL, 0, 0),
+ SHARED_CLK("usbd.emc", "tegra-udc.0", "emc", &tegra_clk_emc, NULL, 0, 0),
SHARED_CLK("usb1.emc", "tegra-ehci.0", "emc", &tegra_clk_emc, NULL, 0, 0),
SHARED_CLK("usb2.emc", "tegra-ehci.1", "emc", &tegra_clk_emc, NULL, 0, 0),
SHARED_CLK("usb3.emc", "tegra-ehci.2", "emc", &tegra_clk_emc, NULL, 0, 0),
@@ -4325,7 +4423,8 @@ struct clk tegra_list_clks[] = {
SHARED_CLK("3d.emc", "tegra_gr3d", "emc", &tegra_clk_emc, NULL, 0, 0),
SHARED_CLK("2d.emc", "tegra_gr2d", "emc", &tegra_clk_emc, NULL, 0, 0),
SHARED_CLK("mpe.emc", "tegra_mpe", "emc", &tegra_clk_emc, NULL, 0, 0),
- SHARED_CLK("camera.emc", "tegra_camera", "emc", &tegra_clk_emc, NULL, 0, 0),
+ SHARED_CLK("camera.emc", "tegra_camera", "emc", &tegra_clk_emc, NULL, 0, SHARED_BW),
+ SHARED_CLK("sdmmc4.emc", "sdhci-tegra.3", "emc", &tegra_clk_emc, NULL, 0, 0),
SHARED_CLK("floor.emc", "floor.emc", NULL, &tegra_clk_emc, NULL, 0, 0),
SHARED_CLK("host1x.cbus", "tegra_host1x", "host1x", &tegra_clk_cbus, "host1x", 2, SHARED_AUTO),
@@ -4391,6 +4490,7 @@ struct clk_duplicate tegra_clk_duplicates[] = {
CLK_DUPLICATE("avp.sclk", "nvavp", "sclk"),
CLK_DUPLICATE("avp.emc", "nvavp", "emc"),
CLK_DUPLICATE("vde.cbus", "nvavp", "vde"),
+ CLK_DUPLICATE("epp.cbus", "tegra_isp", "epp"),
};
struct clk *tegra_ptr_clks[] = {
@@ -4438,6 +4538,86 @@ struct clk *tegra_ptr_clks[] = {
&tegra_clk_cbus,
};
+static int tegra3_emc_relock_set_rate(struct clk *emc, unsigned long old_rate,
+ unsigned long new_rate, unsigned long new_pll_rate)
+{
+ int ret;
+
+ struct clk *sbus = &tegra_clk_sbus_cmplx;
+ struct clk *cbus = &tegra_clk_cbus;
+ struct clk *pll_m = &tegra_pll_m;
+ unsigned long backup_rate = emc->shared_bus_backup.bus_rate;
+ unsigned long flags;
+
+ bool on_pllm = emc->parent == pll_m;
+
+ /*
+ * Relock procedure pre-conditions:
+ * - LPDDR2 only
+ * - EMC clock is enabled, and EMC backup rate is found in DFS table
+ * - All 3 shared buses: emc, sbus, cbus can sleep
+ */
+ if ((tegra_emc_get_dram_type() != DRAM_TYPE_LPDDR2) || !emc->refcnt ||
+ !backup_rate || (cbus->parent != emc->shared_bus_backup.input) ||
+ !clk_cansleep(emc) || !clk_cansleep(cbus) || !clk_cansleep(sbus))
+ return -ENOSYS;
+
+ /* Move sbus from PLLM by setting it at low rate threshold level */
+ clk_lock_save(sbus, &flags);
+ if (clk_get_rate_locked(sbus) > sbus->u.system.threshold) {
+ ret = clk_set_rate_locked(sbus, sbus->u.system.threshold);
+ if (ret)
+ goto _sbus_out;
+ }
+
+ /* If PLLM is current EMC parent set cbus to backup rate, and move EMC
+ to backup PLLC */
+ if (on_pllm) {
+ clk_lock_save(cbus, &flags);
+ clk_enable(cbus->parent);
+ ret = clk_set_rate_locked(cbus, backup_rate);
+ if (ret) {
+ clk_disable(cbus->parent);
+ goto _cbus_out;
+ }
+
+ ret = tegra_emc_backup(backup_rate);
+ if (ret) {
+ clk_disable(cbus->parent);
+ goto _cbus_out;
+ }
+ clk_disable(emc->parent);
+ clk_reparent(emc, cbus->parent);
+ }
+
+ /*
+ * Re-lock PLLM and switch EMC to it; relocking error indicates that
+ * PLLM has some other than EMC or sbus client. In this case PLLM has
+ * not been changed, and we still can safely switch back. Recursive
+ * tegra3_emc_clk_set_rate() call below will be resolved, since PLLM
+ * is now matching target rate.
+ */
+ ret = clk_set_rate(pll_m, new_pll_rate);
+ if (ret) {
+ if (on_pllm)
+ tegra3_emc_clk_set_rate(emc, old_rate);
+ } else
+ ret = tegra3_emc_clk_set_rate(emc, new_rate);
+
+
+_cbus_out:
+ if (on_pllm) {
+ tegra3_clk_shared_bus_update(cbus);
+ clk_unlock_restore(cbus, &flags);
+ }
+
+_sbus_out:
+ tegra3_clk_shared_bus_update(sbus);
+ clk_unlock_restore(sbus, &flags);
+
+ return ret;
+}
+
/*
* Backup rate targets for each CPU mode is selected below Fmax(Vmin), and
* high enough to avoid voltage droop when CPU clock is switched between
@@ -4620,13 +4800,14 @@ static struct cpufreq_frequency_table freq_table_1p7GHz[] = {
{ 5, 620000 },
{ 6, 760000 },
{ 7, 910000 },
- { 8, 1150000 },
- { 9, 1300000 },
- {10, 1400000 },
- {11, 1500000 },
- {12, 1600000 },
- {13, 1700000 },
- {14, CPUFREQ_TABLE_END },
+ { 8, 1000000 },
+ { 9, 1150000 },
+ {10, 1300000 },
+ {11, 1400000 },
+ {12, 1500000 },
+ {13, 1600000 },
+ {14, 1700000 },
+ {15, CPUFREQ_TABLE_END },
};
static struct tegra_cpufreq_table_data cpufreq_tables[] = {
@@ -4727,10 +4908,10 @@ unsigned long tegra_emc_to_cpu_ratio(unsigned long cpu_rate)
/* Vote on memory bus frequency based on cpu frequency;
cpu rate is in kHz, emc rate is in Hz */
- if (cpu_rate >= 750000)
- return emc_max_rate; /* cpu >= 750 MHz, emc max */
+ if (cpu_rate >= 925000)
+ return emc_max_rate; /* cpu >= 925 MHz, emc max */
else if (cpu_rate >= 450000)
- return emc_max_rate/2; /* cpu >= 500 MHz, emc max/2 */
+ return emc_max_rate/2; /* cpu >= 450 MHz, emc max/2 */
else if (cpu_rate >= 250000)
return 100000000; /* cpu >= 250 MHz, emc 100 MHz */
else
@@ -4963,6 +5144,7 @@ static void tegra_clk_resume(void)
/* Since EMC clock is not restored, and may not preserve parent across
suspend, update current state, and mark EMC DFS as out of sync */
+ tegra3_pll_m_override_update(&tegra_pll_m, false);
p = tegra_clk_emc.parent;
tegra3_periph_clk_init(&tegra_clk_emc);
@@ -5003,9 +5185,17 @@ static struct syscore_ops tegra_clk_syscore_ops = {
#define CLK_RSTENB_DEV_V_0_DAM1_BIT (1 << 13)
#define CLK_RSTENB_DEV_V_0_DAM0_BIT (1 << 12)
#define CLK_RSTENB_DEV_V_0_AUDIO_BIT (1 << 10)
+#define CLK_RSTENB_DEV_V_0_3D2_BIT (1 << 2)
#define CLK_RSTENB_DEV_L_0_HOST1X_BIT (1 << 28)
#define CLK_RSTENB_DEV_L_0_DISP1_BIT (1 << 27)
+#define CLK_RSTENB_DEV_L_0_3D_BIT (1 << 24)
+#define CLK_RSTENB_DEV_L_0_2D_BIT (1 << 21)
+#define CLK_RSTENB_DEV_L_0_VI_BIT (1 << 20)
+#define CLK_RSTENB_DEV_L_0_EPP_BIT (1 << 19)
+
+#define CLK_RSTENB_DEV_H_0_VDE_BIT (1 << 29)
+#define CLK_RSTENB_DEV_H_0_MPE_BIT (1 << 28)
#define DISP1_CLK_REG_OFFSET 0x138
#define DISP1_CLK_SRC_SHIFT 29
@@ -5052,6 +5242,31 @@ static struct syscore_ops tegra_clk_syscore_ops = {
#define AUDIO_CLK_DIV_DEFAULT (\
(0 << AUDIO_CLK_DIV_SHIFT))
+#define VCLK_SRC_SHIFT 30
+#define VCLK_SRC_MASK (0x3 << VCLK_SRC_SHIFT)
+#define VCLK_SRC_PLLM_OUT0 0
+#define VCLK_SRC_PLLC_OUT0 1
+#define VCLK_SRC_PLLP_OUT0 2
+#define VCLK_SRC_PLLA_OUT0 3
+#define VCLK_SRC_DEFAULT (VCLK_SRC_PLLM_OUT0 << VCLK_SRC_SHIFT)
+#define VCLK_IDLE_DIV_SHIFT 8
+#define VCLK_IDLE_DIV_MASK (0xff << VCLK_IDLE_DIV_SHIFT)
+#define VCLK_IDLE_DIV_DEFAULT (0 << VCLK_IDLE_DIV_SHIFT)
+#define VCLK_DIV_SHIFT 0
+#define VCLK_DIV_MASK (0xff << VCLK_DIV_SHIFT)
+#define VCLK_DIV_DEFAULT (0xa << VCLK_DIV_SHIFT)
+
+#define VI_CLK_REG_OFFSET 0x148
+#define VI_CLK_SEL_VI_SENSOR_CLK (1 << 25)
+#define VI_CLK_SEL_EXTERNAL_CLK (1 << 24)
+#define VI_SENSOR_CLK_REG_OFFSET 0x1a8
+#define G3D_CLK_REG_OFFSET 0x158
+#define G2D_CLK_REG_OFFSET 0x15c
+#define EPP_CLK_REG_OFFSET 0x16c
+#define MPE_CLK_REG_OFFSET 0x170
+#define VDE_CLK_REG_OFFSET 0x170
+#define G3D2_CLK_REG_OFFSET 0x3b0
+
static void __init clk_setbit(u32 reg, u32 bit)
{
u32 val = clk_readl(reg);
@@ -5086,6 +5301,43 @@ static void __init clk_setbits(u32 reg, u32 bits, u32 mask)
udelay(2);
}
+static void __init vclk_init(int tag, u32 src, u32 rebit)
+{
+ u32 rst, enb;
+
+ switch (tag) {
+ case 'L':
+ rst = RST_DEVICES_L;
+ enb = CLK_OUT_ENB_L;
+ break;
+ case 'H':
+ rst = RST_DEVICES_H;
+ enb = CLK_OUT_ENB_H;
+ break;
+ case 'U':
+ rst = RST_DEVICES_U;
+ enb = CLK_OUT_ENB_U;
+ break;
+ case 'V':
+ rst = RST_DEVICES_V;
+ enb = CLK_OUT_ENB_V;
+ break;
+ case 'W':
+ rst = RST_DEVICES_W;
+ enb = CLK_OUT_ENB_W;
+ break;
+ default:
+ /* Quietly ignore. */
+ return;
+ }
+
+ clk_setbit(rst, rebit);
+ clk_clrbit(enb, rebit);
+ clk_setbits(src, VCLK_SRC_DEFAULT, VCLK_SRC_MASK);
+ clk_setbits(src, VCLK_DIV_DEFAULT, VCLK_DIV_MASK);
+ clk_clrbit(rst, rebit);
+}
+
static int __init tegra_soc_preinit_clocks(void)
{
/*
@@ -5161,6 +5413,15 @@ static int __init tegra_soc_preinit_clocks(void)
AUDIO_CLK_SRC_DEFAULT, AUDIO_CLK_SRC_MASK);
clk_clrbit(RST_DEVICES_V, CLK_RSTENB_DEV_V_0_AUDIO_BIT);
+ /* Pre-initialize Video clocks. */
+ vclk_init('L', G3D_CLK_REG_OFFSET, CLK_RSTENB_DEV_L_0_3D_BIT);
+ vclk_init('L', G2D_CLK_REG_OFFSET, CLK_RSTENB_DEV_L_0_2D_BIT);
+ vclk_init('L', VI_CLK_REG_OFFSET, CLK_RSTENB_DEV_L_0_VI_BIT);
+ vclk_init('L', EPP_CLK_REG_OFFSET, CLK_RSTENB_DEV_L_0_EPP_BIT);
+ vclk_init('H', VDE_CLK_REG_OFFSET, CLK_RSTENB_DEV_H_0_VDE_BIT);
+ vclk_init('H', MPE_CLK_REG_OFFSET, CLK_RSTENB_DEV_H_0_MPE_BIT);
+ vclk_init('V', G3D2_CLK_REG_OFFSET, CLK_RSTENB_DEV_V_0_3D2_BIT);
+
return 0;
}
#endif /* CONFIG_TEGRA_PREINIT_CLOCKS */
diff --git a/arch/arm/mach-tegra/tegra3_dvfs.c b/arch/arm/mach-tegra/tegra3_dvfs.c
index dcda3f3cae3b..5af1b44cd99c 100644
--- a/arch/arm/mach-tegra/tegra3_dvfs.c
+++ b/arch/arm/mach-tegra/tegra3_dvfs.c
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-tegra/tegra3_dvfs.c
*
- * Copyright (C) 2010-2011 NVIDIA Corporation.
+ * Copyright (C) 2010-2012, NVIDIA Corporation.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -33,10 +33,10 @@ static bool tegra_dvfs_core_disabled;
static struct dvfs *cpu_dvfs;
static const int cpu_millivolts[MAX_DVFS_FREQS] = {
- 800, 825, 850, 875, 900, 912, 975, 1000, 1025, 1050, 1075, 1100, 1125, 1150, 1175, 1200, 1212, 1237};
+ 800, 825, 850, 875, 900, 916, 950, 975, 1000, 1007, 1025, 1050, 1075, 1100, 1125, 1150, 1175, 1200, 1212, 1237};
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};
static const int core_millivolts[MAX_DVFS_FREQS] = {
950, 1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350};
@@ -141,57 +141,59 @@ static struct dvfs_relationship tegra3_dvfs_relationships[] = {
}
static struct dvfs cpu_dvfs_table[] = {
- /* Cpu voltages (mV): 800, 825, 850, 875, 900, 912, 975, 1000, 1025, 1050, 1075, 1100, 1125, 1150, 1175, 1200, 1212, 1237 */
- CPU_DVFS("cpu_g", 0, 0, MHZ, 1, 1, 684, 684, 817, 817, 1026, 1102, 1149, 1187, 1225, 1282, 1300),
- CPU_DVFS("cpu_g", 0, 1, MHZ, 1, 1, 807, 807, 948, 948, 1117, 1171, 1206, 1300),
- CPU_DVFS("cpu_g", 0, 2, MHZ, 1, 1, 883, 883, 1039, 1039, 1178, 1206, 1300),
- CPU_DVFS("cpu_g", 0, 3, MHZ, 1, 1, 931, 931, 1102, 1102, 1216, 1300),
-
- CPU_DVFS("cpu_g", 1, 0, MHZ, 460, 460, 550, 550, 680, 680, 820, 970, 1040, 1080, 1150, 1200, 1280, 1300),
- CPU_DVFS("cpu_g", 1, 1, MHZ, 480, 480, 650, 650, 780, 780, 990, 1040, 1100, 1200, 1300),
- CPU_DVFS("cpu_g", 1, 2, MHZ, 520, 520, 700, 700, 860, 860, 1050, 1150, 1200, 1300),
- CPU_DVFS("cpu_g", 1, 3, MHZ, 550, 550, 770, 770, 910, 910, 1150, 1230, 1300),
-
- CPU_DVFS("cpu_g", 2, 1, MHZ, 480, 480, 650, 650, 780, 780, 990, 1040, 1100, 1200, 1250, 1300, 1330, 1400),
- CPU_DVFS("cpu_g", 2, 2, MHZ, 520, 520, 700, 700, 860, 860, 1050, 1150, 1200, 1280, 1300, 1350, 1400),
- CPU_DVFS("cpu_g", 2, 3, MHZ, 550, 550, 770, 770, 910, 910, 1150, 1230, 1280, 1300, 1350, 1400),
-
- CPU_DVFS("cpu_g", 3, 1, MHZ, 480, 480, 650, 650, 780, 780, 990, 1040, 1100, 1200, 1250, 1300, 1330, 1400),
- CPU_DVFS("cpu_g", 3, 2, MHZ, 520, 520, 700, 700, 860, 860, 1050, 1150, 1200, 1280, 1300, 1350, 1400),
- CPU_DVFS("cpu_g", 3, 3, MHZ, 550, 550, 770, 770, 910, 910, 1150, 1230, 1280, 1300, 1350, 1400),
-
- CPU_DVFS("cpu_g", 4, 0, MHZ, 460, 460, 550, 550, 680, 680, 820, 970, 1040, 1080, 1150, 1200, 1240, 1280, 1320, 1360, 1360, 1500),
- CPU_DVFS("cpu_g", 4, 1, MHZ, 480, 480, 650, 650, 780, 780, 990, 1040, 1100, 1200, 1250, 1300, 1330, 1360, 1400, 1500),
- CPU_DVFS("cpu_g", 4, 2, MHZ, 520, 520, 700, 700, 860, 860, 1050, 1150, 1200, 1280, 1300, 1340, 1380, 1500),
- CPU_DVFS("cpu_g", 4, 3, MHZ, 550, 550, 770, 770, 910, 910, 1150, 1230, 1280, 1330, 1370, 1400, 1500),
-
- CPU_DVFS("cpu_g", 5, 3, MHZ, 550, 550, 770, 770, 910, 910, 1150, 1230, 1280, 1330, 1370, 1400, 1470, 1500, 1500, 1540, 1540, 1700),
- CPU_DVFS("cpu_g", 5, 4, MHZ, 550, 550, 770, 770, 940, 940, 1160, 1240, 1280, 1360, 1390, 1470, 1500, 1520, 1520, 1590, 1700),
-
- CPU_DVFS("cpu_g", 6, 3, MHZ, 550, 550, 770, 770, 910, 910, 1150, 1230, 1280, 1330, 1370, 1400, 1470, 1500, 1500, 1540, 1540, 1700),
- CPU_DVFS("cpu_g", 6, 4, MHZ, 550, 550, 770, 770, 940, 940, 1160, 1240, 1280, 1360, 1390, 1470, 1500, 1520, 1520, 1590, 1700),
-
- CPU_DVFS("cpu_g", 7, 0, MHZ, 460, 460, 550, 550, 680, 680, 820, 970, 1040, 1080, 1150, 1200, 1280, 1300),
- CPU_DVFS("cpu_g", 7, 1, MHZ, 480, 480, 650, 650, 780, 780, 990, 1040, 1100, 1200, 1300),
- CPU_DVFS("cpu_g", 7, 2, MHZ, 520, 520, 700, 700, 860, 860, 1050, 1150, 1200, 1300),
- CPU_DVFS("cpu_g", 7, 3, MHZ, 550, 550, 770, 770, 910, 910, 1150, 1230, 1300),
- CPU_DVFS("cpu_g", 7, 4, MHZ, 550, 550, 770, 770, 940, 940, 1160, 1300),
-
- CPU_DVFS("cpu_g", 8, 0, MHZ, 460, 460, 550, 550, 680, 680, 820, 970, 1040, 1080, 1150, 1200, 1280, 1300),
- CPU_DVFS("cpu_g", 8, 1, MHZ, 480, 480, 650, 650, 780, 780, 990, 1040, 1100, 1200, 1300),
- CPU_DVFS("cpu_g", 8, 2, MHZ, 520, 520, 700, 700, 860, 860, 1050, 1150, 1200, 1300),
- CPU_DVFS("cpu_g", 8, 3, MHZ, 550, 550, 770, 770, 910, 910, 1150, 1230, 1300),
- CPU_DVFS("cpu_g", 8, 4, MHZ, 550, 550, 770, 770, 940, 940, 1160, 1300),
-
- CPU_DVFS("cpu_g", 9, -1, MHZ, 1, 1, 1, 1, 1, 900, 900, 900, 900, 900, 900, 900, 900, 900),
- CPU_DVFS("cpu_g", 10, -1, MHZ, 1, 1, 900, 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),
-
- CPU_DVFS("cpu_g", 12, 3, MHZ, 550, 550, 770, 770, 910, 910, 1150, 1230, 1280, 1330, 1370, 1400, 1470, 1500, 1500, 1540, 1540, 1700),
- CPU_DVFS("cpu_g", 12, 4, MHZ, 550, 550, 770, 770, 940, 940, 1160, 1240, 1280, 1360, 1390, 1470, 1500, 1520, 1520, 1590, 1700),
-
- CPU_DVFS("cpu_g", 13, 3, MHZ, 550, 550, 770, 770, 910, 910, 1150, 1230, 1280, 1330, 1370, 1400, 1470, 1500, 1500, 1540, 1540, 1700),
- CPU_DVFS("cpu_g", 13, 4, MHZ, 550, 550, 770, 770, 940, 940, 1160, 1240, 1280, 1360, 1390, 1470, 1500, 1520, 1520, 1590, 1700),
+ /* 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),
/*
* "Safe entry" to be used when no match for chip speedo, process
@@ -200,6 +202,10 @@ static struct dvfs cpu_dvfs_table[] = {
CPU_DVFS("cpu_g", -1, -1, MHZ, 1, 1, 216, 216, 300),
};
+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 */
+};
+
#define CORE_DVFS(_clk_name, _speedo_id, _auto, _mult, _freqs...) \
{ \
.clk_name = _clk_name, \
@@ -222,13 +228,13 @@ static struct dvfs core_dvfs_table[] = {
CORE_DVFS("emc", 0, 1, KHZ, 1, 266500, 266500, 266500, 266500, 533000, 533000, 533000, 533000),
CORE_DVFS("emc", 1, 1, KHZ, 102000, 408000, 408000, 408000, 408000, 667000, 667000, 667000, 667000),
- CORE_DVFS("emc", 2, 1, KHZ, 102000, 408000, 408000, 408000, 408000, 667000, 667000, 800000, 900000),
+ CORE_DVFS("emc", 2, 1, KHZ, 102000, 450000, 450000, 450000, 450000, 667000, 667000, 800000, 900000),
CORE_DVFS("emc", 3, 1, KHZ, 1, 1, 1, 1, 1, 1, 625000, 625000, 625000),
CORE_DVFS("sbus", 0, 1, KHZ, 1, 136000, 164000, 191000, 216000, 216000, 216000, 216000, 216000),
- CORE_DVFS("sbus", 1, 1, KHZ, 51000, 205000, 205000, 227000, 227000, 267000, 267000, 267000, 267000),
- CORE_DVFS("sbus", 2, 1, KHZ, 51000, 205000, 205000, 227000, 227000, 267000, 334000, 334000, 334000),
- CORE_DVFS("sbus", 3, 1, KHZ, 1, 1, 1, 1, 1, 1, 378000, 378000, 378000),
+ CORE_DVFS("sbus", 1, 1, KHZ, 102000, 205000, 205000, 227000, 227000, 267000, 267000, 267000, 267000),
+ CORE_DVFS("sbus", 2, 1, KHZ, 102000, 205000, 205000, 227000, 227000, 267000, 334000, 334000, 334000),
+ CORE_DVFS("sbus", 3, 1, KHZ, 1, 1, 1, 1, 1, 1, 334000, 334000, 334000),
CORE_DVFS("vi", 0, 1, KHZ, 1, 216000, 285000, 300000, 300000, 300000, 300000, 300000, 300000),
CORE_DVFS("vi", 1, 1, KHZ, 1, 216000, 267000, 300000, 371000, 409000, 409000, 409000, 409000),
@@ -243,21 +249,21 @@ static struct dvfs core_dvfs_table[] = {
CORE_DVFS("3d2", 0, 1, KHZ, 1, 234000, 285000, 332000, 380000, 416000, 416000, 416000, 416000),
CORE_DVFS("se", 0, 1, KHZ, 1, 267000, 285000, 332000, 380000, 416000, 416000, 416000, 416000),
- CORE_DVFS("vde", 1, 1, KHZ, 1, 228000, 275000, 332000, 380000, 416000, 416000, 416000, 416000),
- CORE_DVFS("mpe", 1, 1, KHZ, 1, 234000, 285000, 332000, 380000, 416000, 416000, 416000, 416000),
- CORE_DVFS("2d", 1, 1, KHZ, 1, 267000, 285000, 332000, 380000, 416000, 416000, 416000, 416000),
- CORE_DVFS("epp", 1, 1, KHZ, 1, 267000, 285000, 332000, 380000, 416000, 416000, 416000, 416000),
- CORE_DVFS("3d", 1, 1, KHZ, 1, 234000, 285000, 332000, 380000, 416000, 416000, 416000, 416000),
- CORE_DVFS("3d2", 1, 1, KHZ, 1, 234000, 285000, 332000, 380000, 416000, 416000, 416000, 416000),
- CORE_DVFS("se", 1, 1, KHZ, 1, 267000, 285000, 332000, 380000, 416000, 416000, 416000, 416000),
-
- CORE_DVFS("vde", 2, 1, KHZ, 1, 247000, 304000, 352000, 400000, 437000, 484000, 520000, 600000),
- CORE_DVFS("mpe", 2, 1, KHZ, 1, 247000, 304000, 361000, 408000, 446000, 484000, 520000, 600000),
- CORE_DVFS("2d", 2, 1, KHZ, 1, 267000, 304000, 361000, 408000, 446000, 484000, 520000, 600000),
- CORE_DVFS("epp", 2, 1, KHZ, 1, 267000, 304000, 361000, 408000, 446000, 484000, 520000, 600000),
- CORE_DVFS("3d", 2, 1, KHZ, 1, 247000, 304000, 361000, 408000, 446000, 484000, 520000, 600000),
- CORE_DVFS("3d2", 2, 1, KHZ, 1, 247000, 304000, 361000, 408000, 446000, 484000, 520000, 600000),
- CORE_DVFS("se", 2, 1, KHZ, 1, 267000, 304000, 361000, 408000, 446000, 484000, 520000, 600000),
+ CORE_DVFS("vde", 1, 1, KHZ, 200000, 228000, 275000, 332000, 380000, 416000, 416000, 416000, 416000),
+ CORE_DVFS("mpe", 1, 1, KHZ, 200000, 234000, 285000, 332000, 380000, 416000, 416000, 416000, 416000),
+ CORE_DVFS("2d", 1, 1, KHZ, 200000, 267000, 285000, 332000, 380000, 416000, 416000, 416000, 416000),
+ CORE_DVFS("epp", 1, 1, KHZ, 200000, 267000, 285000, 332000, 380000, 416000, 416000, 416000, 416000),
+ CORE_DVFS("3d", 1, 1, KHZ, 200000, 234000, 285000, 332000, 380000, 416000, 416000, 416000, 416000),
+ CORE_DVFS("3d2", 1, 1, KHZ, 200000, 234000, 285000, 332000, 380000, 416000, 416000, 416000, 416000),
+ CORE_DVFS("se", 1, 1, KHZ, 200000, 267000, 285000, 332000, 380000, 416000, 416000, 416000, 416000),
+
+ CORE_DVFS("vde", 2, 1, KHZ, 200000, 247000, 304000, 352000, 400000, 437000, 484000, 520000, 600000),
+ CORE_DVFS("mpe", 2, 1, KHZ, 200000, 247000, 304000, 361000, 408000, 446000, 484000, 520000, 600000),
+ CORE_DVFS("2d", 2, 1, KHZ, 200000, 267000, 304000, 361000, 408000, 446000, 484000, 520000, 600000),
+ CORE_DVFS("epp", 2, 1, KHZ, 200000, 267000, 304000, 361000, 408000, 446000, 484000, 520000, 600000),
+ CORE_DVFS("3d", 2, 1, KHZ, 200000, 247000, 304000, 361000, 408000, 446000, 484000, 520000, 600000),
+ CORE_DVFS("3d2", 2, 1, KHZ, 200000, 247000, 304000, 361000, 408000, 446000, 484000, 520000, 600000),
+ CORE_DVFS("se", 2, 1, KHZ, 200000, 267000, 304000, 361000, 408000, 446000, 484000, 520000, 600000),
CORE_DVFS("vde", 3, 1, KHZ, 1, 1, 1, 1, 1, 1, 484000, 484000, 484000),
CORE_DVFS("mpe", 3, 1, KHZ, 1, 1, 1, 1, 1, 1, 484000, 484000, 484000),
@@ -268,14 +274,14 @@ static struct dvfs core_dvfs_table[] = {
CORE_DVFS("se", 3, 1, KHZ, 1, 1, 1, 1, 1, 1, 625000, 625000, 625000),
CORE_DVFS("host1x", 0, 1, KHZ, 1, 152000, 188000, 222000, 254000, 267000, 267000, 267000, 267000),
- CORE_DVFS("host1x", 1, 1, KHZ, 1, 152000, 188000, 222000, 254000, 267000, 267000, 267000, 267000),
- CORE_DVFS("host1x", 2, 1, KHZ, 1, 152000, 188000, 222000, 254000, 267000, 267000, 267000, 300000),
+ CORE_DVFS("host1x", 1, 1, KHZ, 100000, 152000, 188000, 222000, 254000, 267000, 267000, 267000, 267000),
+ CORE_DVFS("host1x", 2, 1, KHZ, 100000, 152000, 188000, 222000, 254000, 267000, 267000, 267000, 300000),
CORE_DVFS("host1x", 3, 1, KHZ, 1, 1, 1, 1, 1, 1, 242000, 242000, 242000),
CORE_DVFS("cbus", 0, 1, KHZ, 1, 228000, 275000, 332000, 380000, 416000, 416000, 416000, 416000),
- CORE_DVFS("cbus", 1, 1, KHZ, 1, 228000, 275000, 332000, 380000, 416000, 416000, 416000, 416000),
- CORE_DVFS("cbus", 2, 1, KHZ, 1, 247000, 304000, 352000, 400000, 437000, 484000, 520000, 600000),
- CORE_DVFS("cbus", 3, 1, KHZ, 1, 484000, 484000, 484000, 484000, 484000, 484000, 484000, 484000),
+ CORE_DVFS("cbus", 1, 1, KHZ, 200000, 228000, 275000, 332000, 380000, 416000, 416000, 416000, 416000),
+ CORE_DVFS("cbus", 2, 1, KHZ, 200000, 247000, 304000, 352000, 400000, 437000, 484000, 520000, 600000),
+ CORE_DVFS("cbus", 3, 1, KHZ, 1, 1, 1, 1, 1, 1, 484000, 484000, 484000),
CORE_DVFS("pll_c", -1, 1, KHZ, 533000, 667000, 667000, 800000, 800000, 1066000, 1066000, 1066000, 1200000),
@@ -287,7 +293,7 @@ static struct dvfs core_dvfs_table[] = {
*/
CORE_DVFS("pll_m", -1, 1, KHZ, 533000, 667000, 667000, 800000, 800000, 1066000, 1066000, 1066000, 1066000),
#ifdef CONFIG_TEGRA_PLLM_RESTRICTED
- CORE_DVFS("pll_m", 2, 1, KHZ, 533000, 800000, 800000, 800000, 800000, 1066000, 1066000, 1066000, 1066000),
+ CORE_DVFS("pll_m", 2, 1, KHZ, 533000, 900000, 900000, 900000, 900000, 1066000, 1066000, 1066000, 1066000),
#endif
/* Core voltages (mV): 950, 1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350 */
/* Clock limits for I/O peripherals */
@@ -299,36 +305,27 @@ 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("ndflash", -1, 1, KHZ, 1, 120000, 120000, 120000, 200000, 200000, 200000, 200000, 200000),
+ 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),
- CORE_DVFS("nor", 1, 1, KHZ, 1, 115000, 130000, 130000, 133000, 133000, 133000, 133000, 133000),
- CORE_DVFS("nor", 2, 1, KHZ, 1, 115000, 130000, 130000, 133000, 133000, 133000, 133000, 133000),
+ CORE_DVFS("nor", 1, 1, KHZ, 102000, 115000, 130000, 130000, 133000, 133000, 133000, 133000, 133000),
+ CORE_DVFS("nor", 2, 1, KHZ, 102000, 115000, 130000, 130000, 133000, 133000, 133000, 133000, 133000),
CORE_DVFS("nor", 3, 1, KHZ, 1, 1, 1, 1, 1, 1, 108000, 108000, 108000),
- CORE_DVFS("sbc1", -1, 1, KHZ, 1, 52000, 60000, 60000, 60000, 100000, 100000, 100000, 100000),
- CORE_DVFS("sbc2", -1, 1, KHZ, 1, 52000, 60000, 60000, 60000, 100000, 100000, 100000, 100000),
- CORE_DVFS("sbc3", -1, 1, KHZ, 1, 52000, 60000, 60000, 60000, 100000, 100000, 100000, 100000),
- CORE_DVFS("sbc4", -1, 1, KHZ, 1, 52000, 60000, 60000, 60000, 100000, 100000, 100000, 100000),
- CORE_DVFS("sbc5", -1, 1, KHZ, 1, 52000, 60000, 60000, 60000, 100000, 100000, 100000, 100000),
- CORE_DVFS("sbc6", -1, 1, KHZ, 1, 52000, 60000, 60000, 60000, 100000, 100000, 100000, 100000),
-
- CORE_DVFS("usbd", -1, 1, KHZ, 1, 480000, 480000, 480000, 480000, 480000, 480000, 480000, 480000),
- CORE_DVFS("usb2", -1, 1, KHZ, 1, 480000, 480000, 480000, 480000, 480000, 480000, 480000, 480000),
- CORE_DVFS("usb3", -1, 1, KHZ, 1, 480000, 480000, 480000, 480000, 480000, 480000, 480000, 480000),
+ CORE_DVFS("sbc1", -1, 1, KHZ, 36000, 52000, 60000, 60000, 60000, 100000, 100000, 100000, 100000),
+ CORE_DVFS("sbc2", -1, 1, KHZ, 36000, 52000, 60000, 60000, 60000, 100000, 100000, 100000, 100000),
+ CORE_DVFS("sbc3", -1, 1, KHZ, 36000, 52000, 60000, 60000, 60000, 100000, 100000, 100000, 100000),
+ CORE_DVFS("sbc4", -1, 1, KHZ, 36000, 52000, 60000, 60000, 60000, 100000, 100000, 100000, 100000),
+ CORE_DVFS("sbc5", -1, 1, KHZ, 36000, 52000, 60000, 60000, 60000, 100000, 100000, 100000, 100000),
+ CORE_DVFS("sbc6", -1, 1, KHZ, 36000, 52000, 60000, 60000, 60000, 100000, 100000, 100000, 100000),
CORE_DVFS("sata", -1, 1, KHZ, 1, 216000, 216000, 216000, 216000, 216000, 216000, 216000, 216000),
CORE_DVFS("sata_oob", -1, 1, KHZ, 1, 216000, 216000, 216000, 216000, 216000, 216000, 216000, 216000),
- CORE_DVFS("pcie", -1, 1, KHZ, 1, 250000, 250000, 250000, 250000, 250000, 250000, 250000, 250000),
- CORE_DVFS("afi", -1, 1, KHZ, 1, 250000, 250000, 250000, 250000, 250000, 250000, 250000, 250000),
- CORE_DVFS("pll_e", -1, 1, KHZ, 1, 100000, 100000, 100000, 100000, 100000, 100000, 100000, 100000),
- CORE_DVFS("tvdac", -1, 1, KHZ, 1, 220000, 220000, 220000, 220000, 220000, 220000, 220000, 220000),
CORE_DVFS("tvo", -1, 1, KHZ, 1, 1, 297000, 297000, 297000, 297000, 297000, 297000, 297000),
CORE_DVFS("cve", -1, 1, KHZ, 1, 1, 297000, 297000, 297000, 297000, 297000, 297000, 297000),
- CORE_DVFS("dsia", -1, 1, KHZ, 1, 275000, 275000, 275000, 275000, 275000, 275000, 275000, 275000),
- CORE_DVFS("dsib", -1, 1, KHZ, 1, 275000, 275000, 275000, 275000, 275000, 275000, 275000, 275000),
- CORE_DVFS("hdmi", -1, 1, KHZ, 1, 148500, 148500, 148500, 148500, 148500, 148500, 148500, 148500),
+ CORE_DVFS("dsia", -1, 1, KHZ, 432500, 432500, 432500, 432500, 432500, 432500, 432500, 432500, 432500),
+ CORE_DVFS("dsib", -1, 1, KHZ, 432500, 432500, 432500, 432500, 432500, 432500, 432500, 432500, 432500),
/*
* The clock rate for the display controllers that determines the
@@ -337,19 +334,23 @@ static struct dvfs core_dvfs_table[] = {
* and let the display driver call tegra_dvfs_set_rate manually
*/
CORE_DVFS("disp1", 0, 0, KHZ, 1, 120000, 120000, 120000, 120000, 190000, 190000, 190000, 190000),
- CORE_DVFS("disp1", 1, 0, KHZ, 1, 155000, 268000, 268000, 268000, 268000, 268000, 268000, 268000),
- CORE_DVFS("disp1", 2, 0, KHZ, 1, 155000, 268000, 268000, 268000, 268000, 268000, 268000, 268000),
+ CORE_DVFS("disp1", 1, 0, KHZ, 155000, 155000, 268000, 268000, 268000, 268000, 268000, 268000, 268000),
+ CORE_DVFS("disp1", 2, 0, KHZ, 155000, 155000, 268000, 268000, 268000, 268000, 268000, 268000, 268000),
CORE_DVFS("disp1", 3, 0, KHZ, 1, 120000, 120000, 120000, 120000, 190000, 190000, 190000, 190000),
CORE_DVFS("disp2", 0, 0, KHZ, 1, 120000, 120000, 120000, 120000, 190000, 190000, 190000, 190000),
- CORE_DVFS("disp2", 1, 0, KHZ, 1, 155000, 268000, 268000, 268000, 268000, 268000, 268000, 268000),
- CORE_DVFS("disp2", 2, 0, KHZ, 1, 155000, 268000, 268000, 268000, 268000, 268000, 268000, 268000),
+ CORE_DVFS("disp2", 1, 0, KHZ, 155000, 155000, 268000, 268000, 268000, 268000, 268000, 268000, 268000),
+ CORE_DVFS("disp2", 2, 0, KHZ, 155000, 155000, 268000, 268000, 268000, 268000, 268000, 268000, 268000),
CORE_DVFS("disp2", 3, 0, KHZ, 1, 120000, 120000, 120000, 120000, 190000, 190000, 190000, 190000),
- CORE_DVFS("pwm", -1, 1, KHZ, 1, 408000, 408000, 408000, 408000, 408000, 408000, 408000, 408000),
- CORE_DVFS("spdif_out", -1, 1, KHZ, 1, 26000, 26000, 26000, 26000, 26000, 26000, 26000, 26000),
+ CORE_DVFS("pwm", -1, 1, KHZ, 204000, 408000, 408000, 408000, 408000, 408000, 408000, 408000, 408000),
};
+/* CPU alternative DVFS table for cold zone */
+static unsigned long cpu_cold_freqs[MAX_DVFS_FREQS];
+
+/* CPU alternative DVFS table for single G CPU core 0 */
+static unsigned long *cpu_0_freqs;
int tegra_dvfs_disable_core_set(const char *arg, const struct kernel_param *kp)
{
@@ -471,19 +472,18 @@ static void __init init_dvfs_cold(struct dvfs *d, int nominal_mv_index)
for (i = 0; i < d->num_freqs; i++) {
offs = cpu_cold_offs_mhz[i] * MHZ;
if (i > nominal_mv_index)
- d->alt_freqs[i] = d->alt_freqs[i - 1];
+ cpu_cold_freqs[i] = cpu_cold_freqs[i - 1];
else if (d->freqs[i] > offs)
- d->alt_freqs[i] = d->freqs[i] - offs;
+ cpu_cold_freqs[i] = d->freqs[i] - offs;
else {
- d->alt_freqs[i] = d->freqs[i];
+ cpu_cold_freqs[i] = d->freqs[i];
pr_warn("tegra3_dvfs: cold offset %lu is too high for"
" regular dvfs limit %lu\n", offs, d->freqs[i]);
}
if (i)
- BUG_ON(d->alt_freqs[i] < d->alt_freqs[i - 1]);
+ BUG_ON(cpu_cold_freqs[i] < cpu_cold_freqs[i - 1]);
}
- d->alt_freqs_state = ALT_FREQS_DISABLED;
}
static bool __init match_dvfs_one(struct dvfs *d, int speedo_id, int process_id)
@@ -498,6 +498,35 @@ static bool __init match_dvfs_one(struct dvfs *d, int speedo_id, int process_id)
return true;
}
+static void __init init_cpu_0_dvfs(struct dvfs *cpud)
+{
+ int i;
+ struct dvfs *d = NULL;
+
+ /* Init single G CPU core 0 dvfs if this particular SKU/bin has it.
+ Max rates in multi-core and single-core tables must be the same */
+ for (i = 0; i < ARRAY_SIZE(cpu_0_dvfs_table); i++) {
+ if (match_dvfs_one(&cpu_0_dvfs_table[i],
+ cpud->speedo_id, cpud->process_id)) {
+ d = &cpu_0_dvfs_table[i];
+ break;
+ }
+ }
+
+ if (d) {
+ for (i = 0; i < cpud->num_freqs; i++) {
+ d->freqs[i] *= d->freqs_mult;
+ if (d->freqs[i] == 0) {
+ BUG_ON(i == 0);
+ d->freqs[i] = d->freqs[i - 1];
+ }
+ }
+ BUG_ON(cpud->freqs[cpud->num_freqs - 1] !=
+ d->freqs[cpud->num_freqs - 1]);
+ cpu_0_freqs = d->freqs;
+ }
+}
+
static int __init get_cpu_nominal_mv_index(
int speedo_id, int process_id, struct dvfs **cpu_dvfs)
{
@@ -644,7 +673,10 @@ void __init tegra_soc_init_dvfs(void)
/* Initialize matching cpu dvfs entry already found when nominal
voltage was determined */
init_dvfs_one(cpu_dvfs, cpu_nominal_mv_index);
+
+ /* Initialize alternative cold zone and single core tables */
init_dvfs_cold(cpu_dvfs, cpu_nominal_mv_index);
+ init_cpu_0_dvfs(cpu_dvfs);
/* Finally disable dvfs on rails if necessary */
if (tegra_dvfs_core_disabled)
@@ -660,14 +692,18 @@ void __init tegra_soc_init_dvfs(void)
tegra_dvfs_core_disabled ? "disabled" : "enabled");
}
-void tegra_cpu_dvfs_alter(int edp_thermal_index, bool before_clk_update)
+void tegra_cpu_dvfs_alter(int edp_thermal_index, const cpumask_t *cpus,
+ bool before_clk_update)
{
- bool enable = !edp_thermal_index;
-
- if (enable != before_clk_update) {
- int ret = tegra_dvfs_alt_freqs_set(cpu_dvfs, enable);
- WARN_ONCE(ret, "tegra dvfs: failed to set CPU alternative"
- " frequency limits for cold temeperature\n");
+ 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) {
+ int ret = tegra_dvfs_alt_freqs_set(cpu_dvfs, alt_freqs);
+ WARN_ONCE(ret, "tegra dvfs: failed to update CPU alternative"
+ " frequency limits\n");
}
}
@@ -781,8 +817,6 @@ static void core_cap_update(void)
static void core_cap_enable(bool enable)
{
- int i;
-
if (enable)
tegra3_core_cap.refcnt++;
else if (tegra3_core_cap.refcnt)
@@ -883,7 +917,7 @@ void tegra_dvfs_core_cap_level_set(int level)
static int __init init_core_cap_one(struct clk *c, unsigned long *freqs)
{
- int i, v, next_v;
+ int i, v, next_v = 0;
unsigned long rate, next_rate = 0;
for (i = 0; i < ARRAY_SIZE(core_millivolts); i++) {
@@ -904,7 +938,7 @@ static int __init init_core_cap_one(struct clk *c, unsigned long *freqs)
next_v = tegra_dvfs_predict_millivolts(
c->parent, next_rate);
- if (IS_ERR_VALUE(next_rate)) {
+ if (IS_ERR_VALUE(next_v)) {
pr_debug("tegra3_dvfs: failed to predict %s mV"
" for rate %lu", c->name, next_rate);
return -EINVAL;
diff --git a/arch/arm/mach-tegra/tegra3_emc.c b/arch/arm/mach-tegra/tegra3_emc.c
index 0725980bfa40..a138091d9197 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) 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
@@ -45,6 +45,8 @@ static bool emc_enable;
#endif
module_param(emc_enable, bool, 0644);
+u8 tegra_emc_bw_efficiency = 35;
+
#define EMC_MIN_RATE_DDR3 25500000
#define EMC_STATUS_UPDATE_TIMEOUT 100
#define TEGRA_EMC_TABLE_MAX_SIZE 16
@@ -187,7 +189,13 @@ enum {
static int emc_num_burst_regs;
-static struct clk_mux_sel tegra_emc_clk_sel[TEGRA_EMC_TABLE_MAX_SIZE];
+struct emc_sel {
+ struct clk *input;
+ u32 value;
+ unsigned long input_rate;
+};
+
+static struct emc_sel tegra_emc_clk_sel[TEGRA_EMC_TABLE_MAX_SIZE];
static struct tegra_emc_table start_timing;
static const struct tegra_emc_table *emc_timing;
static unsigned long dram_over_temp_state = DRAM_OVER_TEMP_NONE;
@@ -350,6 +358,12 @@ static inline void disable_early_ack(u32 mc_override)
override_val |= mc_override & MC_EMEM_ARB_OVERRIDE_EACK_MASK;
}
+static inline void enable_early_ack(u32 mc_override)
+{
+ mc_writel((mc_override | MC_EMEM_ARB_OVERRIDE_EACK_MASK),
+ MC_EMEM_ARB_OVERRIDE);
+}
+
static inline bool dqs_preset(const struct tegra_emc_table *next_timing,
const struct tegra_emc_table *last_timing)
{
@@ -489,6 +503,7 @@ static inline void do_clock_change(u32 clk_setting)
mc_readl(MC_EMEM_ADR_CFG); /* completes prev writes */
writel(clk_setting, (u32)clk_base + emc->reg);
+ readl((u32)clk_base + emc->reg);/* completes prev write */
err = wait_for_update(EMC_INTSTATUS,
EMC_INTSTATUS_CLKCHANGE_COMPLETE, true);
@@ -702,7 +717,7 @@ static inline void emc_cfg_power_restore(void)
* This function updates the shadow registers for a new clock frequency,
* and relies on the clock lock on the emc clock to avoid races between
* multiple frequency changes */
-int tegra_emc_set_rate(unsigned long rate)
+static int emc_set_rate(unsigned long rate, bool use_backup)
{
int i;
u32 clk_setting;
@@ -735,7 +750,8 @@ int tegra_emc_set_rate(unsigned long rate)
else
last_timing = emc_timing;
- clk_setting = tegra_emc_clk_sel[i].value;
+ clk_setting = use_backup ? emc->shared_bus_backup.value :
+ tegra_emc_clk_sel[i].value;
spin_lock_irqsave(&emc_access_lock, flags);
emc_set_clock(&tegra_emc_table[i], last_timing, clk_setting);
@@ -751,6 +767,17 @@ int tegra_emc_set_rate(unsigned long rate)
return 0;
}
+int tegra_emc_set_rate(unsigned long rate)
+{
+ return emc_set_rate(rate, false);
+}
+
+int tegra_emc_backup(unsigned long rate)
+{
+ BUG_ON(rate != emc->shared_bus_backup.bus_rate);
+ return emc_set_rate(rate, true);
+}
+
/* Select the closest EMC rate that is higher than the requested rate */
long tegra_emc_round_rate(unsigned long rate)
{
@@ -793,7 +820,7 @@ struct clk *tegra_emc_predict_parent(unsigned long rate, u32 *div_value)
int i;
if (!tegra_emc_table)
- return NULL;
+ return ERR_PTR(-ENOENT);
pr_debug("%s: %lu\n", __func__, rate);
@@ -802,33 +829,94 @@ struct clk *tegra_emc_predict_parent(unsigned long rate, u32 *div_value)
for (i = 0; i < tegra_emc_table_size; i++) {
if (tegra_emc_table[i].rate == rate) {
+ struct clk *p = tegra_emc_clk_sel[i].input;
+
*div_value = (tegra_emc_clk_sel[i].value &
EMC_CLK_DIV_MASK) >> EMC_CLK_DIV_SHIFT;
- return tegra_emc_clk_sel[i].input;
+ if (tegra_emc_clk_sel[i].input_rate != clk_get_rate(p))
+ return NULL;
+
+ return p;
}
}
-
- return NULL;
+ return ERR_PTR(-ENOENT);
}
-static const struct clk_mux_sel *find_matching_input(
- unsigned long table_rate,
- u32 *div_value)
+int find_matching_input(unsigned long table_rate, bool mc_same_freq,
+ struct emc_sel *emc_clk_sel, struct clk *cbus)
{
- unsigned long inp_rate;
+ u32 div_value = 0;
+ unsigned long input_rate = 0;
const struct clk_mux_sel *sel;
+ const struct clk_mux_sel *parent_sel = NULL;
+ const struct clk_mux_sel *backup_sel = NULL;
+
+ /* Table entries specify rate in kHz */
+ table_rate *= 1000;
for (sel = emc->inputs; sel->input != NULL; sel++) {
- /* Table entries specify rate in kHz */
- inp_rate = clk_get_rate(sel->input) / 1000;
+ if (sel->input == emc->shared_bus_backup.input) {
+ backup_sel = sel;
+ continue; /* skip backup souce */
+ }
- if ((inp_rate >= table_rate) &&
- (inp_rate % table_rate == 0)) {
- *div_value = 2 * inp_rate / table_rate - 2;
- return sel;
+ if (sel->input == emc->parent)
+ parent_sel = sel;
+
+ input_rate = clk_get_rate(sel->input);
+
+ if ((input_rate >= table_rate) &&
+ (input_rate % table_rate == 0)) {
+ div_value = 2 * input_rate / table_rate - 2;
+ break;
+ }
+ }
+
+#ifdef CONFIG_TEGRA_PLLM_RESTRICTED
+ /*
+ * When match not found, check if this rate can be backed-up by cbus
+ * Then, we will be able to re-lock boot parent PLLM, and use it as
+ * an undivided source. Backup is supported only on LPDDR2 platforms
+ * with restricted PLLM usage. Just one backup entry is recognized,
+ * and it must be between EMC maximum and half maximum rates.
+ */
+ if ((dram_type == DRAM_TYPE_LPDDR2) && (sel->input == NULL) &&
+ (emc->shared_bus_backup.bus_rate == 0) && cbus) {
+ BUG_ON(!parent_sel || !backup_sel);
+
+ if ((table_rate == clk_round_rate(cbus, table_rate)) &&
+ (table_rate < clk_get_max_rate(emc)) &&
+ (table_rate >= clk_get_max_rate(emc) / 2)) {
+ emc->shared_bus_backup.bus_rate = table_rate;
+
+ /* Get ready emc clock backup selection settings */
+ emc->shared_bus_backup.value =
+ (backup_sel->value << EMC_CLK_SOURCE_SHIFT) |
+ (cbus->div << EMC_CLK_DIV_SHIFT) |
+ (mc_same_freq ? EMC_CLK_MC_SAME_FREQ : 0);
+
+ /* Select undivided PLLM as regular source */
+ sel = parent_sel;
+ input_rate = table_rate;
+ div_value = 0;
}
}
- return NULL;
+#endif
+
+ if (sel->input) {
+ emc_clk_sel->input = sel->input;
+ emc_clk_sel->input_rate = input_rate;
+
+ /* Get ready emc clock selection settings for this table rate */
+ emc_clk_sel->value = sel->value << EMC_CLK_SOURCE_SHIFT;
+ emc_clk_sel->value |= (div_value << EMC_CLK_DIV_SHIFT);
+ if ((div_value == 0) && (emc_clk_sel->input == emc->parent))
+ emc_clk_sel->value |= EMC_CLK_LOW_JITTER_ENABLE;
+ if (mc_same_freq)
+ emc_clk_sel->value |= EMC_CLK_MC_SAME_FREQ;
+ return 0;
+ }
+ return -EINVAL;
}
static void adjust_emc_dvfs_table(const struct tegra_emc_table *table,
@@ -932,10 +1020,10 @@ static struct notifier_block tegra_emc_resume_nb = {
void tegra_init_emc(const struct tegra_emc_table *table, int table_size)
{
int i, mv;
- u32 reg, div_value;
+ u32 reg;
bool max_entry = false;
unsigned long boot_rate, max_rate;
- const struct clk_mux_sel *sel;
+ struct clk *cbus = tegra_get_clock_by_name("cbus");
emc_stats.clkchange_count = 0;
spin_lock_init(&emc_stats.spinlock);
@@ -979,14 +1067,16 @@ void tegra_init_emc(const struct tegra_emc_table *table, int table_size)
/* Match EMC source/divider settings with table entries */
for (i = 0; i < tegra_emc_table_size; i++) {
+ bool mc_same_freq = MC_EMEM_ARB_MISC0_EMC_SAME_FREQ &
+ table[i].burst_regs[MC_EMEM_ARB_MISC0_INDEX];
unsigned long table_rate = table[i].rate;
if (!table_rate)
continue;
BUG_ON(table[i].rev != table[0].rev);
- sel = find_matching_input(table_rate, &div_value);
- if (!sel)
+ if (find_matching_input(table_rate, mc_same_freq,
+ &tegra_emc_clk_sel[i], cbus))
continue;
if (table_rate == boot_rate)
@@ -994,21 +1084,6 @@ void tegra_init_emc(const struct tegra_emc_table *table, int table_size)
if (table_rate == max_rate)
max_entry = true;
-
- tegra_emc_clk_sel[i] = *sel;
- BUG_ON(div_value >
- (EMC_CLK_DIV_MASK >> EMC_CLK_DIV_SHIFT));
- tegra_emc_clk_sel[i].value <<= EMC_CLK_SOURCE_SHIFT;
- tegra_emc_clk_sel[i].value |= (div_value << EMC_CLK_DIV_SHIFT);
-
- if ((div_value == 0) &&
- (tegra_emc_clk_sel[i].input == emc->parent)) {
- tegra_emc_clk_sel[i].value |= EMC_CLK_LOW_JITTER_ENABLE;
- }
-
- if (table[i].burst_regs[MC_EMEM_ARB_MISC0_INDEX] &
- MC_EMEM_ARB_MISC0_EMC_SAME_FREQ)
- tegra_emc_clk_sel[i].value |= EMC_CLK_MC_SAME_FREQ;
}
/* Validate EMC rate and voltage limits */
@@ -1163,6 +1238,51 @@ int tegra_emc_set_over_temp_state(unsigned long state)
return 0;
}
+/* non-zero state value will reduce eack_disable_refcnt */
+static int tegra_emc_set_eack_state(unsigned long state)
+{
+ unsigned long flags;
+ u32 mc_override;
+ static int eack_disable_refcnt = 0;
+
+ spin_lock_irqsave(&emc_access_lock, flags);
+
+ /*
+ * refcnt > 0 implies there is at least one client requiring eack
+ * disabled. refcnt of 0 implies eack is enabled
+ */
+ if (eack_disable_refcnt == 1 && state) {
+ mc_override = mc_readl(MC_EMEM_ARB_OVERRIDE);
+ enable_early_ack(mc_override);
+ } else if (eack_disable_refcnt == 0 && !state) {
+ mc_override = mc_readl(MC_EMEM_ARB_OVERRIDE);
+ disable_early_ack(mc_override);
+ }
+
+ if (state) {
+ if (likely(eack_disable_refcnt > 0)) {
+ --eack_disable_refcnt;
+ } else {
+ pr_err("%s: Ignored a request to underflow eack "
+ "disable reference counter\n",__func__);
+ dump_stack();
+ }
+ } else {
+ ++eack_disable_refcnt;
+ }
+
+ spin_unlock_irqrestore(&emc_access_lock, flags);
+ return 0;
+}
+
+int tegra_emc_enable_eack(void) {
+ return tegra_emc_set_eack_state(1);
+}
+
+int tegra_emc_disable_eack(void) {
+ return tegra_emc_set_eack_state(0);
+}
+
#ifdef CONFIG_DEBUG_FS
static struct dentry *emc_debugfs_root;
@@ -1222,6 +1342,43 @@ static int over_temp_state_set(void *data, u64 val)
DEFINE_SIMPLE_ATTRIBUTE(over_temp_state_fops, over_temp_state_get,
over_temp_state_set, "%llu\n");
+static int eack_state_get(void *data, u64 *val)
+{
+ unsigned long flags;
+ u32 mc_override;
+
+ spin_lock_irqsave(&emc_access_lock, flags);
+ mc_override = mc_readl(MC_EMEM_ARB_OVERRIDE);
+ spin_unlock_irqrestore(&emc_access_lock, flags);
+
+ *val = (mc_override & MC_EMEM_ARB_OVERRIDE_EACK_MASK);
+ return 0;
+}
+
+static int eack_state_set(void *data, u64 val)
+{
+ tegra_emc_set_eack_state(val);
+ return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(eack_state_fops, eack_state_get,
+ eack_state_set, "%llu\n");
+
+static int efficiency_get(void *data, u64 *val)
+{
+ *val = tegra_emc_bw_efficiency;
+ return 0;
+}
+static int efficiency_set(void *data, u64 val)
+{
+ tegra_emc_bw_efficiency = (val > 100) ? 100 : val;
+ if (emc)
+ tegra_clk_shared_bus_update(emc);
+
+ return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(efficiency_fops, efficiency_get,
+ efficiency_set, "%llu\n");
+
static int __init tegra_emc_debug_init(void)
{
if (!tegra_emc_table)
@@ -1243,6 +1400,14 @@ static int __init tegra_emc_debug_init(void)
emc_debugfs_root, NULL, &over_temp_state_fops))
goto err_out;
+ if (!debugfs_create_file(
+ "eack_state", S_IRUGO | S_IWUSR, emc_debugfs_root, NULL, &eack_state_fops))
+ goto err_out;
+
+ if (!debugfs_create_file("efficiency", S_IRUGO | S_IWUSR,
+ emc_debugfs_root, NULL, &efficiency_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 cfde92c1355a..f59654295ba4 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) 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
@@ -27,6 +27,8 @@
#define TEGRA_EMC_BRIDGE_RATE_MIN 300000000
#define TEGRA_EMC_BRIDGE_MVOLTS_MIN 1200
+extern u8 tegra_emc_bw_efficiency;
+
struct tegra_emc_table {
u8 rev;
unsigned long rate;
diff --git a/arch/arm/mach-tegra/tegra3_host1x_devices.h b/arch/arm/mach-tegra/tegra3_host1x_devices.h
new file mode 100644
index 000000000000..38a5eabf037f
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra3_host1x_devices.h
@@ -0,0 +1,26 @@
+/*
+ * drivers/video/tegra/host/tegra3_host1x_devices.h
+ *
+ * Tegra3 Graphics Host Devices
+ *
+ * Copyright (c) 2012, NVIDIA Corporation.
+ *
+ * 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 TEGRA3_HOST1X_DEVICES_H
+#define TEGRA3_HOST1X_DEVICES_H
+
+int tegra3_register_host1x_devices(void);
+
+#endif
diff --git a/arch/arm/mach-tegra/tegra3_speedo.c b/arch/arm/mach-tegra/tegra3_speedo.c
index bd880bc7ca8b..78afb2804088 100644
--- a/arch/arm/mach-tegra/tegra3_speedo.c
+++ b/arch/arm/mach-tegra/tegra3_speedo.c
@@ -108,8 +108,8 @@ static const u32 cpu_process_speedos[][CPU_PROCESS_CORNERS_NUM] = {
/* T30 Automotives */
/* threshold_index 12: cpu_speedo_id 9 & 10
- * 0,1,2 values correspond to speedo_id 9
- * 3,4,5 values correspond to speedo_id 10 */
+ * 0,1,2 values correspond to speedo_id 9/14
+ * 3,4,5 values correspond to speedo_id 10/15*/
{300, 311, 360, 371, 381, 415, 431},
{300, 311, 410, 431, UINT_MAX}, /* [13]: cpu_speedo_id 11: T30 auto */
@@ -462,10 +462,31 @@ void tegra_init_speedo_data(void)
soc_speedo_id = 1;
}
if (threshold_index == 12 && cpu_process_id != INVALID_PROCESS_ID) {
- if (cpu_process_id <= 2)
- cpu_speedo_id = 9;
- else if (cpu_process_id >= 3 && cpu_process_id < 6)
- cpu_speedo_id = 10;
+ if (cpu_process_id <= 2) {
+ switch(fuse_sku) {
+ case 0xb0:
+ case 0xb1:
+ cpu_speedo_id = 9;
+ break;
+ case 0x90:
+ case 0x91:
+ cpu_speedo_id = 14;
+ default:
+ break;
+ }
+ } else if (cpu_process_id >= 3 && cpu_process_id < 6) {
+ switch(fuse_sku) {
+ case 0xb0:
+ case 0xb1:
+ cpu_speedo_id = 10;
+ break;
+ case 0x90:
+ case 0x91:
+ cpu_speedo_id = 15;
+ default:
+ break;
+ }
+ }
}
pr_info("Tegra3: CPU Speedo ID %d, Soc Speedo ID %d",
cpu_speedo_id, soc_speedo_id);
@@ -510,8 +531,8 @@ int tegra_package_id(void)
* latter is resolved by the dvfs code)
*/
static const int cpu_speedo_nominal_millivolts[] =
-/* speedo_id 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 */
- { 1125, 1150, 1150, 1150, 1237, 1237, 1237, 1150, 1150, 912, 850, 850, 1237, 1237};
+/* speedo_id 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 */
+ { 1125, 1150, 1150, 1150, 1237, 1237, 1237, 1150, 1150, 1007, 916, 850, 1237, 1237, 950, 900};
int tegra_cpu_speedo_mv(void)
{
diff --git a/arch/arm/mach-tegra/tegra3_thermal.c b/arch/arm/mach-tegra/tegra3_thermal.c
index 27f7a425e02a..f36f84ccddf4 100644
--- a/arch/arm/mach-tegra/tegra3_thermal.c
+++ b/arch/arm/mach-tegra/tegra3_thermal.c
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-tegra/tegra3_thermal.c
*
- * Copyright (C) 2010-2011 NVIDIA Corporation.
+ * Copyright (C) 2010-2012 NVIDIA Corporation.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -28,56 +28,32 @@
#include <mach/thermal.h>
#include <mach/edp.h>
#include <linux/slab.h>
+#include <linux/suspend.h>
#include "clock.h"
#include "cpu-tegra.h"
#include "dvfs.h"
-#define MAX_ZONES (16)
+static struct tegra_thermal_data *therm;
+static LIST_HEAD(tegra_therm_list);
+static DEFINE_MUTEX(tegra_therm_mutex);
-struct tegra_thermal {
- struct tegra_thermal_device *device;
- long temp_throttle_tj;
- long temp_shutdown_tj;
-#ifdef CONFIG_TEGRA_THERMAL_SYSFS
- struct thermal_zone_device *thz;
- int tc1;
- int tc2;
- long passive_delay;
-#else
- long temp_throttle_low_tj;
-#endif
-#ifdef CONFIG_TEGRA_EDP_LIMITS
- int edp_thermal_zone_val;
- long edp_offset;
- long hysteresis_edp;
-#endif
- struct mutex mutex;
-};
+static struct balanced_throttle *throttle_list;
+static int throttle_list_size;
-static struct tegra_thermal thermal_state = {
- .device = NULL,
#ifdef CONFIG_TEGRA_EDP_LIMITS
- .edp_thermal_zone_val = -1,
+static long edp_thermal_zone_val;
#endif
-};
-#ifndef CONFIG_TEGRA_THERMAL_SYSFS
-static bool throttle_enb;
+#ifdef CONFIG_TEGRA_SKIN_THROTTLE
+static int skin_devs_bitmap;
+static struct therm_est_subdevice *skin_devs[THERMAL_DEVICE_MAX];
+static int skin_devs_count;
#endif
+static bool tegra_thermal_suspend;
-#ifdef CONFIG_TEGRA_EDP_LIMITS
-static inline long edp2tj(struct tegra_thermal *thermal,
- long edp_temp)
-{
- return edp_temp + thermal->edp_offset;
-}
-
-static inline long tj2edp(struct tegra_thermal *thermal,
- long temp_tj)
-{
- return temp_tj - thermal->edp_offset;
-}
+#ifdef CONFIG_DEBUG_FS
+static struct dentry *thermal_debugfs_root;
#endif
static inline long dev2tj(struct tegra_thermal_device *dev,
@@ -92,25 +68,74 @@ static inline long tj2dev(struct tegra_thermal_device *dev,
return tj_temp - dev->offset;
}
-#ifdef CONFIG_TEGRA_THERMAL_SYSFS
+static int tegra_thermal_get_temp_unlocked(long *tj_temp, bool offsetted)
+{
+ struct tegra_thermal_device *dev = NULL;
+ int ret = 0;
+
+#if defined(CONFIG_TEGRA_EDP_LIMITS) || defined(CONFIG_TEGRA_THERMAL_THROTTLE)
+ list_for_each_entry(dev, &tegra_therm_list, node)
+ if (dev->id == therm->throttle_edp_device_id)
+ break;
+#endif
+
+ if (dev) {
+ dev->get_temp(dev->data, tj_temp);
+ if (offsetted)
+ *tj_temp = dev2tj(dev, *tj_temp);
+ } else {
+ ret = -1;
+ }
-static int tegra_thermal_zone_bind(struct thermal_zone_device *thermal,
+ return ret;
+}
+
+#ifdef CONFIG_TEGRA_THERMAL_THROTTLE
+
+static int tegra_thermal_zone_bind(struct thermal_zone_device *thz,
struct thermal_cooling_device *cdevice) {
- /* Support only Thermal Throttling (1 trip) for now */
- return thermal_zone_bind_cooling_device(thermal, 0, cdevice);
+
+ struct balanced_throttle *bthrot = cdevice->devdata;
+ struct tegra_thermal_device *device = thz->devdata;
+
+ if ((bthrot->id == BALANCED_THROTTLE_ID_TJ) &&
+ (device->id == therm->throttle_edp_device_id))
+ return thermal_zone_bind_cooling_device(thz, 0, cdevice);
+
+#ifdef CONFIG_TEGRA_SKIN_THROTTLE
+ if ((bthrot->id == BALANCED_THROTTLE_ID_SKIN) &&
+ (device->id == therm->skin_device_id))
+ return thermal_zone_bind_cooling_device(thz, 0, cdevice);
+#endif
+
+ return 0;
}
-static int tegra_thermal_zone_unbind(struct thermal_zone_device *thermal,
+static int tegra_thermal_zone_unbind(struct thermal_zone_device *thz,
struct thermal_cooling_device *cdevice) {
- /* Support only Thermal Throttling (1 trip) for now */
- return thermal_zone_unbind_cooling_device(thermal, 0, cdevice);
+ struct balanced_throttle *bthrot = cdevice->devdata;
+ struct tegra_thermal_device *device = thz->devdata;
+
+ if ((bthrot->id == BALANCED_THROTTLE_ID_TJ) &&
+ (device->id == therm->throttle_edp_device_id))
+ return thermal_zone_unbind_cooling_device(thz, 0, cdevice);
+
+#ifdef CONFIG_TEGRA_SKIN_THROTTLE
+ if ((bthrot->id == BALANCED_THROTTLE_ID_SKIN) &&
+ (device->id == therm->skin_device_id))
+ return thermal_zone_unbind_cooling_device(thz, 0, cdevice);
+#endif
+
+ return 0;
}
static int tegra_thermal_zone_get_temp(struct thermal_zone_device *thz,
unsigned long *temp)
{
- struct tegra_thermal *thermal = thz->devdata;
- thermal->device->get_temp(thermal->device->data, temp);
+ struct tegra_thermal_device *device = thz->devdata;
+
+ if (!tegra_thermal_suspend)
+ device->get_temp(device->data, temp);
return 0;
}
@@ -119,8 +144,6 @@ static int tegra_thermal_zone_get_trip_type(
struct thermal_zone_device *thermal,
int trip,
enum thermal_trip_type *type) {
-
- /* Support only Thermal Throttling (1 trip) for now */
if (trip != 0)
return -EINVAL;
@@ -132,13 +155,19 @@ static int tegra_thermal_zone_get_trip_type(
static int tegra_thermal_zone_get_trip_temp(struct thermal_zone_device *thz,
int trip,
unsigned long *temp) {
- struct tegra_thermal *thermal = thz->devdata;
+ struct tegra_thermal_device *device = thz->devdata;
- /* Support only Thermal Throttling (1 trip) for now */
if (trip != 0)
return -EINVAL;
- *temp = tj2dev(thermal->device, thermal->temp_throttle_tj);
+ if (device->id == therm->throttle_edp_device_id)
+ *temp = therm->temp_throttle;
+#ifdef CONFIG_TEGRA_SKIN_THROTTLE
+ else if (device->id == therm->skin_device_id)
+ *temp = therm->temp_throttle_skin;
+#endif
+ else
+ return -EINVAL;
return 0;
}
@@ -152,26 +181,29 @@ static struct thermal_zone_device_ops tegra_thermal_zone_ops = {
};
#endif
-/* The thermal sysfs handles notifying the throttling
- * cooling device */
-#ifndef CONFIG_TEGRA_THERMAL_SYSFS
-static void tegra_therm_throttle(bool enable)
+static int tegra_thermal_pm_notify(struct notifier_block *nb,
+ unsigned long event, void *data)
{
- if (throttle_enb != enable) {
- mutex_lock(&thermal_state.mutex);
- tegra_throttling_enable(enable);
- throttle_enb = enable;
- mutex_unlock(&thermal_state.mutex);
+ switch (event) {
+ case PM_SUSPEND_PREPARE:
+ tegra_thermal_suspend = true;
+ break;
+ case PM_POST_SUSPEND:
+ tegra_thermal_suspend = false;
+ break;
}
-}
-#endif
-/* Make sure this function remains stateless */
-void tegra_thermal_alert(void *data)
+ return NOTIFY_OK;
+};
+
+static struct notifier_block tegra_thermal_nb = {
+ .notifier_call = tegra_thermal_pm_notify,
+};
+
+static void tegra_thermal_alert_unlocked(void *data)
{
- struct tegra_thermal *thermal = data;
- int err;
- long temp_dev, temp_tj;
+ struct tegra_thermal_device *device = data;
+ long temp_tj;
long lo_limit_throttle_tj, hi_limit_throttle_tj;
long lo_limit_edp_tj = 0, hi_limit_edp_tj = 0;
long temp_low_dev, temp_low_tj;
@@ -182,45 +214,29 @@ void tegra_thermal_alert(void *data)
int i;
#endif
- if (thermal != &thermal_state)
- BUG();
-
- mutex_lock(&thermal_state.mutex);
-
-#ifdef CONFIG_TEGRA_THERMAL_SYSFS
- if (thermal->thz) {
- if (!thermal->thz->passive)
- thermal_zone_device_update(thermal->thz);
+#ifdef CONFIG_TEGRA_THERMAL_THROTTLE
+ if (device->thz) {
+ if ((!device->thz->passive) && (!tegra_thermal_suspend))
+ thermal_zone_device_update(device->thz);
}
#endif
- err = thermal->device->get_temp(thermal->device->data, &temp_dev);
- if (err) {
- pr_err("%s: get temp fail(%d)", __func__, err);
- goto done;
- }
-
/* Convert all temps to tj and then do all work/logic in terms of
tj in order to avoid confusion */
- temp_tj = dev2tj(thermal->device, temp_dev);
- thermal->device->get_temp_low(thermal->device, &temp_low_dev);
- temp_low_tj = dev2tj(thermal->device, temp_low_dev);
+ if (tegra_thermal_get_temp_unlocked(&temp_tj, true))
+ return;
+ device->get_temp_low(device, &temp_low_dev);
+ temp_low_tj = dev2tj(device, temp_low_dev);
lo_limit_throttle_tj = temp_low_tj;
- hi_limit_throttle_tj = thermal->temp_throttle_tj;
-
-#ifndef CONFIG_TEGRA_THERMAL_SYSFS
- /* Check to see if we are currently throttling */
- if ((tegra_is_throttling() &&
- (temp_tj > thermal->temp_throttle_low_tj))
- || (temp_tj >= thermal->temp_throttle_tj)) {
- lo_limit_throttle_tj = thermal->temp_throttle_low_tj;
- hi_limit_throttle_tj = thermal->temp_shutdown_tj;
- }
-#else
- if (temp_tj > thermal->temp_throttle_tj) {
- lo_limit_throttle_tj = thermal->temp_throttle_tj;
- hi_limit_throttle_tj = thermal->temp_shutdown_tj;
+ hi_limit_throttle_tj = dev2tj(device, therm->temp_shutdown);
+
+#ifdef CONFIG_TEGRA_THERMAL_THROTTLE
+ hi_limit_throttle_tj = dev2tj(device, therm->temp_throttle);
+
+ if (temp_tj > dev2tj(device, therm->temp_throttle)) {
+ lo_limit_throttle_tj = dev2tj(device, therm->temp_throttle);
+ hi_limit_throttle_tj = dev2tj(device, therm->temp_shutdown);
}
#endif
@@ -228,21 +244,21 @@ void tegra_thermal_alert(void *data)
tegra_get_cpu_edp_limits(&z, &zones_sz);
/* edp table based off of tdiode measurements */
-#define EDP_TEMP_TJ(_index) edp2tj(thermal, z[_index].temperature * 1000)
+#define EDP_TEMP_TJ(_index) (z[_index].temperature * 1000 + therm->edp_offset)
if (temp_tj < EDP_TEMP_TJ(0)) {
lo_limit_edp_tj = temp_low_tj;
hi_limit_edp_tj = EDP_TEMP_TJ(0);
} else if (temp_tj >= EDP_TEMP_TJ(zones_sz-1)) {
lo_limit_edp_tj = EDP_TEMP_TJ(zones_sz-1) -
- thermal->hysteresis_edp;
- hi_limit_edp_tj = thermal->temp_shutdown_tj;
+ therm->hysteresis_edp;
+ hi_limit_edp_tj = dev2tj(device, therm->temp_shutdown);
} else {
for (i = 0; (i + 1) < zones_sz; i++) {
if ((temp_tj >= EDP_TEMP_TJ(i)) &&
(temp_tj < EDP_TEMP_TJ(i+1))) {
lo_limit_edp_tj = EDP_TEMP_TJ(i) -
- thermal->hysteresis_edp;
+ therm->hysteresis_edp;
hi_limit_edp_tj = EDP_TEMP_TJ(i+1);
break;
}
@@ -251,191 +267,242 @@ void tegra_thermal_alert(void *data)
#undef EDP_TEMP_TJ
#else
lo_limit_edp_tj = temp_low_tj;
- hi_limit_edp_tj = thermal->temp_shutdown_tj;
+ hi_limit_edp_tj = dev2tj(device, therm->temp_shutdown);
#endif
/* Get smallest window size */
lo_limit_tj = max(lo_limit_throttle_tj, lo_limit_edp_tj);
hi_limit_tj = min(hi_limit_throttle_tj, hi_limit_edp_tj);
- thermal->device->set_limits(thermal->device->data,
- tj2dev(thermal->device, lo_limit_tj),
- tj2dev(thermal->device, hi_limit_tj));
-
-#ifndef CONFIG_TEGRA_THERMAL_SYSFS
- if (temp_tj >= thermal->temp_throttle_tj) {
- /* start throttling */
- if (!tegra_is_throttling())
- tegra_therm_throttle(true);
- } else if (temp_tj <= thermal->temp_throttle_low_tj) {
- /* switch off throttling */
- if (tegra_is_throttling())
- tegra_therm_throttle(false);
- }
-#endif
+ device->set_limits(device->data,
+ tj2dev(device, lo_limit_tj),
+ tj2dev(device, hi_limit_tj));
#ifdef CONFIG_TEGRA_EDP_LIMITS
/* inform edp governor */
- if (thermal->edp_thermal_zone_val != temp_tj)
- tegra_edp_update_thermal_zone(tj2edp(thermal, temp_tj)/1000);
-
- thermal->edp_thermal_zone_val = temp_tj;
+ if (edp_thermal_zone_val != temp_tj) {
+ long temp_edp = (dev2tj(device, temp_tj) - therm->edp_offset) / 1000;
+ tegra_edp_update_thermal_zone(temp_edp);
+ edp_thermal_zone_val = temp_edp;
+ }
#endif
-
-done:
- mutex_unlock(&thermal_state.mutex);
}
-int tegra_thermal_set_device(struct tegra_thermal_device *device)
+#ifdef CONFIG_TEGRA_THERMAL_THROTTLE
+/* Make sure this function remains stateless */
+static void tegra_thermal_alert(void *data)
{
-#ifdef CONFIG_TEGRA_THERMAL_SYSFS
- struct thermal_zone_device *thz;
+ mutex_lock(&tegra_therm_mutex);
+ tegra_thermal_alert_unlocked(data);
+ mutex_unlock(&tegra_therm_mutex);
+}
#endif
- /* only support one device */
- if (thermal_state.device)
- return -EINVAL;
-
- thermal_state.device = device;
-
-#ifdef CONFIG_TEGRA_THERMAL_SYSFS
- thz = thermal_zone_device_register(thermal_state.device->name,
- 1, /* trips */
- &thermal_state,
- &tegra_thermal_zone_ops,
- thermal_state.tc1, /* dT/dt */
- thermal_state.tc2, /* throttle */
- thermal_state.passive_delay,
- 0); /* polling delay */
-
- if (IS_ERR(thz)) {
- thz = NULL;
- return -ENODEV;
- }
+#ifdef CONFIG_TEGRA_SKIN_THROTTLE
+static void tegra_skin_thermal_alert(void *data)
+{
+ struct tegra_thermal_device *dev = data;
- thermal_state.thz = thz;
-#endif
- thermal_state.device->set_alert(thermal_state.device->data,
- tegra_thermal_alert,
- &thermal_state);
+ if (!dev->thz->passive)
+ thermal_zone_device_update(dev->thz);
+}
- thermal_state.device->set_shutdown_temp(thermal_state.device->data,
- tj2dev(device, thermal_state.temp_shutdown_tj));
+static int tegra_skin_device_register(struct tegra_thermal_device *device)
+{
+ int i;
+ struct therm_est_subdevice *skin_dev =
+ kzalloc(sizeof(struct therm_est_subdevice), GFP_KERNEL);
+
+ for (i = 0; i < therm->skin_devs_size; i++) {
+ if (therm->skin_devs[i].id == device->id) {
+ memcpy(skin_dev->coeffs,
+ therm->skin_devs[i].coeffs,
+ sizeof(skin_devs[i]->coeffs));
+ break;
+ }
+ }
- /* initialize limits */
- tegra_thermal_alert(&thermal_state);
+ skin_dev->dev_data = device->data;
+ skin_dev->get_temp = device->get_temp;
+
+ skin_devs[skin_devs_count++] = skin_dev;
+
+ /* Create skin thermal device */
+ if (skin_devs_count == therm->skin_devs_size) {
+ struct tegra_thermal_device *thermal_skin_device;
+ struct therm_estimator *skin_estimator;
+
+ skin_estimator = therm_est_register(
+ skin_devs,
+ skin_devs_count,
+ therm->skin_temp_offset,
+ therm->skin_period);
+ thermal_skin_device = kzalloc(sizeof(struct tegra_thermal_device),
+ GFP_KERNEL);
+ thermal_skin_device->name = "skin_pred";
+ thermal_skin_device->id = THERMAL_DEVICE_ID_SKIN;
+ thermal_skin_device->data = skin_estimator;
+ thermal_skin_device->get_temp =
+ (int (*)(void *, long *)) therm_est_get_temp;
+ thermal_skin_device->set_limits =
+ (int (*)(void *, long, long)) therm_est_set_limits;
+ thermal_skin_device->set_alert =
+ (int (*)(void *, void (*)(void *), void *))
+ therm_est_set_alert;
+
+ tegra_thermal_device_register(thermal_skin_device);
+ }
return 0;
}
+#endif
-int __init tegra_thermal_init(struct tegra_thermal_data *data)
+int tegra_thermal_device_register(struct tegra_thermal_device *device)
{
-#ifdef CONFIG_TEGRA_THERMAL_SYSFS
- thermal_state.tc1 = data->tc1;
- thermal_state.tc2 = data->tc2;
- thermal_state.passive_delay = data->passive_delay;
-#else
- thermal_state.temp_throttle_low_tj = data->temp_throttle +
- data->temp_offset -
- data->hysteresis_throttle;
-#endif
- mutex_init(&thermal_state.mutex);
-#ifdef CONFIG_TEGRA_EDP_LIMITS
- thermal_state.edp_offset = data->edp_offset;
- thermal_state.hysteresis_edp = data->hysteresis_edp;
+ struct tegra_thermal_device *dev;
+#ifdef CONFIG_TEGRA_THERMAL_THROTTLE
+ struct thermal_zone_device *thz;
+ int t1 = 0, t2 = 0, pdelay = 0;
+ bool create_thz = false;
#endif
- thermal_state.temp_throttle_tj = data->temp_throttle +
- data->temp_offset;
- thermal_state.temp_shutdown_tj = data->temp_shutdown +
- data->temp_offset;
- return 0;
-}
+ mutex_lock(&tegra_therm_mutex);
+ list_for_each_entry(dev, &tegra_therm_list, node) {
+ if (dev->id == device->id) {
+ mutex_unlock(&tegra_therm_mutex);
+ return -EINVAL;
+ }
+ }
-int tegra_thermal_exit(void)
-{
-#ifdef CONFIG_TEGRA_THERMAL_SYSFS
- if (thermal_state.thz)
- thermal_zone_device_unregister(thermal_state.thz);
+#ifdef CONFIG_TEGRA_THERMAL_THROTTLE
+ if (device->id == therm->throttle_edp_device_id) {
+ t1 = therm->tc1;
+ t2 = therm->tc2;
+ pdelay = therm->passive_delay;
+ create_thz = true;
+ }
+#endif
+#ifdef CONFIG_TEGRA_SKIN_THROTTLE
+ if (device->id == therm->skin_device_id) {
+ t1 = 0;
+ t2 = 1;
+ pdelay = 5000;
+ create_thz = true;
+ }
#endif
- return 0;
-}
+#ifdef CONFIG_TEGRA_THERMAL_THROTTLE
+ if (create_thz) {
+ thz = thermal_zone_device_register(
+ device->name,
+ 1, /* trips */
+ device,
+ &tegra_thermal_zone_ops,
+ t1, /* dT/dt */
+ t2, /* throttle */
+ pdelay,
+ 0); /* polling delay */
+ if (IS_ERR_OR_NULL(thz))
+ return -ENODEV;
+
+ device->thz = thz;
+ }
+#endif
-#ifdef CONFIG_DEBUG_FS
+ list_add(&device->node, &tegra_therm_list);
+ mutex_unlock(&tegra_therm_mutex);
-static int tegra_thermal_throttle_temp_tj_set(void *data, u64 val)
-{
-#ifndef CONFIG_TEGRA_THERMAL_SYSFS
- long throttle_hysteresis = thermal_state.temp_throttle_tj -
- thermal_state.temp_throttle_low_tj;
+ if (device->id == therm->shutdown_device_id) {
+ device->set_shutdown_temp(device->data, therm->temp_shutdown);
+ }
+
+#ifdef CONFIG_TEGRA_SKIN_THROTTLE
+ if (device->id == therm->skin_device_id) {
+ if (create_thz)
+ device->set_alert(device->data,
+ tegra_skin_thermal_alert,
+ device);
+ device->set_limits(device->data, 0, therm->temp_throttle_skin);
+ }
#endif
- mutex_lock(&thermal_state.mutex);
- thermal_state.temp_throttle_tj = val;
-#ifndef CONFIG_TEGRA_THERMAL_SYSFS
- thermal_state.temp_throttle_low_tj = thermal_state.temp_throttle_tj -
- throttle_hysteresis;
+#ifdef CONFIG_TEGRA_THERMAL_THROTTLE
+ if (device->id == therm->throttle_edp_device_id) {
+ device->set_alert(device->data, tegra_thermal_alert, device);
+
+ /* initialize limits */
+ tegra_thermal_alert(device);
+ }
#endif
- mutex_unlock(&thermal_state.mutex);
- tegra_thermal_alert(&thermal_state);
+#ifdef CONFIG_TEGRA_SKIN_THROTTLE
+ if ((therm->skin_device_id == THERMAL_DEVICE_ID_SKIN) &&
+ device->id && skin_devs_bitmap)
+ tegra_skin_device_register(device);
+#endif
+ register_pm_notifier(&tegra_thermal_nb);
return 0;
}
-static int tegra_thermal_throttle_temp_tj_get(void *data, u64 *val)
+/* This needs to be inialized later hand */
+static int __init throttle_list_init(void)
{
- *val = (u64)thermal_state.temp_throttle_tj;
+ int i;
+ for (i = 0; i < throttle_list_size; i++)
+ if (balanced_throttle_register(&throttle_list[i]))
+ return -ENODEV;
+
return 0;
}
+late_initcall(throttle_list_init);
-DEFINE_SIMPLE_ATTRIBUTE(throttle_temp_tj_fops,
- tegra_thermal_throttle_temp_tj_get,
- tegra_thermal_throttle_temp_tj_set,
- "%llu\n");
-
-static int tegra_thermal_shutdown_temp_tj_set(void *data, u64 val)
+int __init tegra_thermal_init(struct tegra_thermal_data *data,
+ struct balanced_throttle *tlist,
+ int tlist_size)
{
- thermal_state.temp_shutdown_tj = val;
+ therm = data;
+#ifdef CONFIG_DEBUG_FS
+ thermal_debugfs_root = debugfs_create_dir("tegra_thermal", 0);
+#endif
- if (thermal_state.device)
- thermal_state.device->set_shutdown_temp(
- thermal_state.device->data,
- tj2dev(thermal_state.device,
- thermal_state.temp_shutdown_tj));
+#ifdef CONFIG_TEGRA_SKIN_THROTTLE
+ {
+ int i;
+ for (i = 0; i < therm->skin_devs_size; i++)
+ skin_devs_bitmap |= therm->skin_devs[i].id;
+ }
+#endif
- tegra_thermal_alert(&thermal_state);
+ throttle_list = tlist;
+ throttle_list_size = tlist_size;
return 0;
}
-static int tegra_thermal_shutdown_temp_tj_get(void *data, u64 *val)
+int tegra_thermal_exit(void)
{
- *val = (u64)thermal_state.temp_shutdown_tj;
+#ifdef CONFIG_TEGRA_THERMAL_THROTTLE
+ struct tegra_thermal_device *dev;
+ mutex_lock(&tegra_therm_mutex);
+ list_for_each_entry(dev, &tegra_therm_list, node) {
+ thermal_zone_device_unregister(dev->thz);
+ }
+ mutex_unlock(&tegra_therm_mutex);
+#endif
+
return 0;
}
-DEFINE_SIMPLE_ATTRIBUTE(shutdown_temp_tj_fops,
- tegra_thermal_shutdown_temp_tj_get,
- tegra_thermal_shutdown_temp_tj_set,
- "%llu\n");
-
-
+#ifdef CONFIG_DEBUG_FS
static int tegra_thermal_temp_tj_get(void *data, u64 *val)
{
- long temp_tj, temp_dev;
-
- if (thermal_state.device) {
- thermal_state.device->get_temp(thermal_state.device->data,
- &temp_dev);
+ long temp_tj;
- /* Convert all temps to tj and then do all work/logic in
- terms of tj in order to avoid confusion */
- temp_tj = dev2tj(thermal_state.device, temp_dev);
- } else {
+ mutex_lock(&tegra_therm_mutex);
+ if (tegra_thermal_get_temp_unlocked(&temp_tj, false))
temp_tj = -1;
- }
+ mutex_unlock(&tegra_therm_mutex);
*val = (u64)temp_tj;
@@ -447,98 +514,101 @@ DEFINE_SIMPLE_ATTRIBUTE(temp_tj_fops,
NULL,
"%llu\n");
-#ifdef CONFIG_TEGRA_THERMAL_SYSFS
-static int tegra_thermal_tc1_set(void *data, u64 val)
+static int __init temp_tj_debug_init(void)
{
- thermal_state.thz->tc1 = val;
+ debugfs_create_file("temp_tj", 0644, thermal_debugfs_root,
+ NULL, &temp_tj_fops);
return 0;
}
-
-static int tegra_thermal_tc1_get(void *data, u64 *val)
-{
- *val = (u64)thermal_state.thz->tc1;
- return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(tc1_fops,
- tegra_thermal_tc1_get,
- tegra_thermal_tc1_set,
- "%llu\n");
-
-static int tegra_thermal_tc2_set(void *data, u64 val)
-{
- thermal_state.thz->tc2 = val;
- return 0;
-}
-
-static int tegra_thermal_tc2_get(void *data, u64 *val)
-{
- *val = (u64)thermal_state.thz->tc2;
- return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(tc2_fops,
- tegra_thermal_tc2_get,
- tegra_thermal_tc2_set,
- "%llu\n");
-
-static int tegra_thermal_passive_delay_set(void *data, u64 val)
-{
- thermal_state.thz->passive_delay = val;
- return 0;
-}
-
-static int tegra_thermal_passive_delay_get(void *data, u64 *val)
-{
- *val = (u64)thermal_state.thz->passive_delay;
- return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(passive_delay_fops,
- tegra_thermal_passive_delay_get,
- tegra_thermal_passive_delay_set,
- "%llu\n");
+late_initcall(temp_tj_debug_init);
+
+
+#define TEGRA_THERM_DEBUGFS(_name, _device_id, throttle, shutdown) \
+ static int tegra_thermal_##_name##_set(void *data, u64 val) \
+ { \
+ struct tegra_thermal_device *dev; \
+ mutex_lock(&tegra_therm_mutex); \
+ therm->_name = val; \
+ list_for_each_entry(dev, &tegra_therm_list, node) \
+ if (dev->id == therm->_device_id) \
+ break; \
+ if (dev) { \
+ if (throttle) \
+ tegra_thermal_alert_unlocked(dev); \
+ if (shutdown) \
+ dev->set_shutdown_temp(dev->data, \
+ therm->temp_shutdown); \
+ } \
+ mutex_unlock(&tegra_therm_mutex); \
+ return 0; \
+ } \
+ static int tegra_thermal_##_name##_get(void *data, u64 *val) \
+ { \
+ *val = (u64)therm->_name; \
+ return 0; \
+ } \
+ DEFINE_SIMPLE_ATTRIBUTE(_name##_fops, \
+ tegra_thermal_##_name##_get, \
+ tegra_thermal_##_name##_set, \
+ "%llu\n"); \
+ static int __init _name##_debug_init(void) \
+ { \
+ debugfs_create_file(#_name, 0644, thermal_debugfs_root, \
+ NULL, &_name##_fops); \
+ return 0; \
+ } \
+ late_initcall(_name##_debug_init);
+
+
+TEGRA_THERM_DEBUGFS(temp_shutdown, shutdown_device_id, false, true);
+#ifdef CONFIG_TEGRA_THERMAL_THROTTLE
+TEGRA_THERM_DEBUGFS(temp_throttle, throttle_edp_device_id, true, false);
#endif
-
-
-static struct dentry *thermal_debugfs_root;
-
-static int __init tegra_thermal_debug_init(void)
-{
- thermal_debugfs_root = debugfs_create_dir("tegra_thermal", 0);
-
- if (!debugfs_create_file("throttle_temp_tj", 0644, thermal_debugfs_root,
- NULL, &throttle_temp_tj_fops))
- goto err_out;
-
- if (!debugfs_create_file("shutdown_temp_tj", 0644, thermal_debugfs_root,
- NULL, &shutdown_temp_tj_fops))
- goto err_out;
-
- if (!debugfs_create_file("temp_tj", 0644, thermal_debugfs_root,
- NULL, &temp_tj_fops))
- goto err_out;
-
-#ifdef CONFIG_TEGRA_THERMAL_SYSFS
- if (!debugfs_create_file("tc1", 0644, thermal_debugfs_root,
- NULL, &tc1_fops))
- goto err_out;
-
- if (!debugfs_create_file("tc2", 0644, thermal_debugfs_root,
- NULL, &tc2_fops))
- goto err_out;
-
- if (!debugfs_create_file("passive_delay", 0644, thermal_debugfs_root,
- NULL, &passive_delay_fops))
- goto err_out;
+#ifdef CONFIG_TEGRA_SKIN_THROTTLE
+TEGRA_THERM_DEBUGFS(temp_throttle_skin, skin_device_id, false, false);
#endif
- return 0;
-
-err_out:
- debugfs_remove_recursive(thermal_debugfs_root);
- return -ENOMEM;
-}
-
-late_initcall(tegra_thermal_debug_init);
+#ifdef CONFIG_TEGRA_THERMAL_THROTTLE
+#define THERM_DEBUGFS(_name) \
+ static int tegra_thermal_##_name##_set(void *data, u64 val) \
+ { \
+ struct tegra_thermal_device *dev; \
+ mutex_lock(&tegra_therm_mutex); \
+ list_for_each_entry(dev, &tegra_therm_list, node) \
+ if (dev->id == therm->throttle_edp_device_id) \
+ break; \
+ if (dev) \
+ dev->thz->_name = val; \
+ mutex_unlock(&tegra_therm_mutex); \
+ return 0; \
+ } \
+ static int tegra_thermal_##_name##_get(void *data, u64 *val) \
+ { \
+ struct tegra_thermal_device *dev; \
+ mutex_lock(&tegra_therm_mutex); \
+ list_for_each_entry(dev, &tegra_therm_list, node) \
+ if (dev->id == therm->throttle_edp_device_id) \
+ break; \
+ if (dev) \
+ *val = (u64)dev->thz->_name; \
+ mutex_unlock(&tegra_therm_mutex); \
+ return 0; \
+ } \
+ DEFINE_SIMPLE_ATTRIBUTE(_name##_fops, \
+ tegra_thermal_##_name##_get, \
+ tegra_thermal_##_name##_set, \
+ "%llu\n"); \
+ static int __init _name##_debug_init(void) \
+ { \
+ debugfs_create_file(#_name, 0644, thermal_debugfs_root, \
+ NULL, &_name##_fops); \
+ return 0; \
+ } \
+ late_initcall(_name##_debug_init);
+
+
+THERM_DEBUGFS(tc1);
+THERM_DEBUGFS(tc2);
+THERM_DEBUGFS(passive_delay);
+#endif
#endif
diff --git a/arch/arm/mach-tegra/tegra3_throttle.c b/arch/arm/mach-tegra/tegra3_throttle.c
index f927be7800d6..d980144ed052 100644
--- a/arch/arm/mach-tegra/tegra3_throttle.c
+++ b/arch/arm/mach-tegra/tegra3_throttle.c
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-tegra/tegra3_throttle.c
*
- * Copyright (c) 2011, NVIDIA Corporation.
+ * 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
@@ -27,44 +27,27 @@
#include <linux/seq_file.h>
#include <linux/uaccess.h>
#include <linux/thermal.h>
+#include <mach/thermal.h>
#include "clock.h"
#include "cpu-tegra.h"
#include "dvfs.h"
-/* tegra throttling require frequencies in the table to be in ascending order */
-static struct cpufreq_frequency_table *cpu_freq_table;
static struct mutex *cpu_throttle_lock;
-
-static struct {
- unsigned int cpu_freq;
- int core_cap_level;
- int ms;
-} throttle_table[] = {
- { 0, 1000, 2000 }, /* placeholder for cpu floor rate */
- { 640000, 1000, 2000 },
- { 640000, 1000, 2000 },
- { 640000, 1000, 2000 },
- { 640000, 1000, 2000 },
- { 640000, 1000, 2000 },
- { 760000, 1000, 2000 },
- { 760000, 1050, 2000 },
- {1000000, 1050, 2000 },
- {1000000, 1100, 2000 },
-};
-
-static int is_throttling;
-static int throttle_index;
-static struct delayed_work throttle_work;
-static struct workqueue_struct *workqueue;
-static DEFINE_MUTEX(tegra_throttle_lock);
-#ifdef CONFIG_TEGRA_THERMAL_SYSFS
-static struct thermal_cooling_device *cdev;
-#endif
+static DEFINE_MUTEX(bthrot_list_lock);
+static LIST_HEAD(bthrot_list);
static unsigned int clip_to_table(unsigned int cpu_freq)
{
int i;
+ struct cpufreq_frequency_table *cpu_freq_table;
+ struct tegra_cpufreq_table_data *table_data =
+ tegra_cpufreq_table_get();
+
+ if (IS_ERR_OR_NULL(table_data))
+ return -EINVAL;
+
+ cpu_freq_table = table_data->freq_table;
for (i = 0; cpu_freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
if (cpu_freq_table[i].frequency > cpu_freq)
@@ -74,100 +57,69 @@ static unsigned int clip_to_table(unsigned int cpu_freq)
return cpu_freq_table[i].frequency;
}
-static void tegra_throttle_work_func(struct work_struct *work)
-{
- unsigned int cpu_freq;
- int core_level;
-
- mutex_lock(cpu_throttle_lock);
- if (!is_throttling) {
- mutex_unlock(cpu_throttle_lock);
- return;
- }
-
- cpu_freq = tegra_getspeed(0);
- throttle_index -= throttle_index ? 1 : 0;
-
- core_level = throttle_table[throttle_index].core_cap_level;
- if (throttle_table[throttle_index].cpu_freq < cpu_freq)
- tegra_cpu_set_speed_cap(NULL);
-
- if (throttle_index || (throttle_table[0].cpu_freq < cpu_freq))
- queue_delayed_work(workqueue, &throttle_work,
- msecs_to_jiffies(throttle_table[throttle_index].ms));
-
- mutex_unlock(cpu_throttle_lock);
-
- tegra_dvfs_core_cap_level_set(core_level);
-}
-
-/*
- * tegra_throttling_enable
- * This function may sleep
- */
-void tegra_throttling_enable(bool enable)
+unsigned int tegra_throttle_governor_speed(unsigned int requested_speed)
{
- mutex_lock(&tegra_throttle_lock);
- mutex_lock(cpu_throttle_lock);
-
- if (enable && !(is_throttling++)) {
- int core_level;
- unsigned int cpu_freq = tegra_getspeed(0);
- throttle_index = ARRAY_SIZE(throttle_table) - 1;
+ struct balanced_throttle *bthrot;
+ unsigned int throttle_speed = requested_speed;
+ int index;
+ unsigned int bthrot_speed;
+ unsigned int lowest_speed;
+ struct cpufreq_frequency_table *cpu_freq_table;
+ struct tegra_cpufreq_table_data *table_data =
+ tegra_cpufreq_table_get();
- core_level = throttle_table[throttle_index].core_cap_level;
- if (throttle_table[throttle_index].cpu_freq < cpu_freq)
- tegra_cpu_set_speed_cap(NULL);
+ if (!table_data)
+ return requested_speed;
- queue_delayed_work(workqueue, &throttle_work,
- msecs_to_jiffies(throttle_table[throttle_index].ms));
- mutex_unlock(cpu_throttle_lock);
+ cpu_freq_table = table_data->freq_table;
+ lowest_speed = cpu_freq_table[table_data->throttle_lowest_index].frequency;
- tegra_dvfs_core_cap_level_set(core_level);
- tegra_dvfs_core_cap_enable(true);
+ mutex_lock(&bthrot_list_lock);
- mutex_unlock(&tegra_throttle_lock);
- return;
- }
+ list_for_each_entry(bthrot, &bthrot_list, node) {
+ if (bthrot->is_throttling) {
+ index = bthrot->throttle_index;
+ bthrot_speed = bthrot->throt_tab[index].cpu_freq;
- if (!enable && is_throttling) {
- if (!(--is_throttling)) {
- /* restore speed requested by governor */
- tegra_cpu_set_speed_cap(NULL);
- mutex_unlock(cpu_throttle_lock);
+ if (bthrot_speed == 0)
+ bthrot_speed = lowest_speed;
+ else
+ bthrot_speed = clip_to_table(bthrot_speed);
- tegra_dvfs_core_cap_enable(false);
- cancel_delayed_work_sync(&throttle_work);
- mutex_unlock(&tegra_throttle_lock);
- return;
+ throttle_speed = min(throttle_speed, bthrot_speed);
}
}
+ mutex_unlock(&bthrot_list_lock);
- mutex_unlock(cpu_throttle_lock);
- mutex_unlock(&tegra_throttle_lock);
-}
-EXPORT_SYMBOL_GPL(tegra_throttling_enable);
-
-unsigned int tegra_throttle_governor_speed(unsigned int requested_speed)
-{
- return is_throttling ?
- min(requested_speed, throttle_table[throttle_index].cpu_freq) :
- requested_speed;
+ return throttle_speed;
}
bool tegra_is_throttling(void)
{
+ struct balanced_throttle *bthrot;
+ bool is_throttling = false;
+
+ mutex_lock(&bthrot_list_lock);
+ list_for_each_entry(bthrot, &bthrot_list, node) {
+ if (bthrot->is_throttling) {
+ is_throttling = true;
+ break;
+ }
+ }
+ mutex_unlock(&bthrot_list_lock);
+
return is_throttling;
}
-#ifdef CONFIG_TEGRA_THERMAL_SYSFS
-
static int
tegra_throttle_get_max_state(struct thermal_cooling_device *cdev,
unsigned long *max_state)
{
- *max_state = ARRAY_SIZE(throttle_table);
+ struct balanced_throttle *bthrot = cdev->devdata;
+
+ *max_state = bthrot->throt_tab_size;
+
return 0;
}
@@ -175,9 +127,11 @@ static int
tegra_throttle_get_cur_state(struct thermal_cooling_device *cdev,
unsigned long *cur_state)
{
+ struct balanced_throttle *bthrot = cdev->devdata;
+
mutex_lock(cpu_throttle_lock);
- *cur_state = is_throttling ?
- (ARRAY_SIZE(throttle_table) - throttle_index) :
+ *cur_state = bthrot->is_throttling ?
+ (bthrot->throt_tab_size - bthrot->throttle_index) :
0;
mutex_unlock(cpu_throttle_lock);
@@ -188,25 +142,28 @@ static int
tegra_throttle_set_cur_state(struct thermal_cooling_device *cdev,
unsigned long cur_state)
{
+ struct balanced_throttle *bthrot = cdev->devdata;
int core_level;
+ int index;
mutex_lock(cpu_throttle_lock);
if (cur_state == 0) {
/* restore speed requested by governor */
- if (is_throttling) {
+ if (bthrot->is_throttling) {
tegra_dvfs_core_cap_enable(false);
- is_throttling = false;
+ bthrot->is_throttling = false;
}
tegra_cpu_set_speed_cap(NULL);
} else {
- if (!is_throttling) {
+ if (!bthrot->is_throttling) {
tegra_dvfs_core_cap_enable(true);
- is_throttling = true;
+ bthrot->is_throttling = true;
}
- throttle_index = ARRAY_SIZE(throttle_table) - cur_state;
- core_level = throttle_table[throttle_index].core_cap_level;
+ bthrot->throttle_index = bthrot->throt_tab_size - cur_state;
+ index = bthrot->throttle_index;
+ core_level = bthrot->throt_tab[index].core_cap_level;
tegra_dvfs_core_cap_level_set(core_level);
tegra_cpu_set_speed_cap(NULL);
@@ -217,88 +174,23 @@ tegra_throttle_set_cur_state(struct thermal_cooling_device *cdev,
return 0;
}
-struct thermal_cooling_device_ops tegra_throttle_cooling_ops = {
+static struct thermal_cooling_device_ops tegra_throttle_cooling_ops = {
.get_max_state = tegra_throttle_get_max_state,
.get_cur_state = tegra_throttle_get_cur_state,
.set_cur_state = tegra_throttle_set_cur_state,
};
-#endif
-
-int __init tegra_throttle_init(struct mutex *cpu_lock)
-{
- int i;
- struct tegra_cpufreq_table_data *table_data =
- tegra_cpufreq_table_get();
- if (IS_ERR_OR_NULL(table_data))
- return -EINVAL;
-
- /*
- * High-priority, others flags default: not bound to a specific
- * CPU, has rescue worker task (in case of allocation deadlock,
- * etc.). Single-threaded.
- */
- workqueue = alloc_workqueue("cpu-tegra",
- WQ_HIGHPRI | WQ_UNBOUND | WQ_RESCUER, 1);
- if (!workqueue)
- return -ENOMEM;
- INIT_DELAYED_WORK(&throttle_work, tegra_throttle_work_func);
-
- cpu_throttle_lock = cpu_lock;
- cpu_freq_table = table_data->freq_table;
- throttle_table[0].cpu_freq =
- cpu_freq_table[table_data->throttle_lowest_index].frequency;
-
- for (i = 0; i < ARRAY_SIZE(throttle_table); i++) {
- unsigned int cpu_freq = throttle_table[i].cpu_freq;
- throttle_table[i].cpu_freq = clip_to_table(cpu_freq);
- }
-
-#ifdef CONFIG_TEGRA_THERMAL_SYSFS
- cdev = thermal_cooling_device_register("Throttle", NULL,
- &tegra_throttle_cooling_ops);
-
- if (IS_ERR(cdev)) {
- cdev = NULL;
- return -ENODEV;
- }
-#endif
-
- return 0;
-}
-
-void tegra_throttle_exit(void)
-{
-#ifdef CONFIG_TEGRA_THERMAL_SYSFS
- if (cdev) {
- thermal_cooling_device_unregister(cdev);
- cdev = NULL;
- }
-#endif
- destroy_workqueue(workqueue);
-}
#ifdef CONFIG_DEBUG_FS
-
-static int throttle_debug_set(void *data, u64 val)
-{
- tegra_throttling_enable(val);
- return 0;
-}
-static int throttle_debug_get(void *data, u64 *val)
-{
- *val = (u64) is_throttling;
- return 0;
-}
-DEFINE_SIMPLE_ATTRIBUTE(throttle_fops, throttle_debug_get, throttle_debug_set,
- "%llu\n");
static int table_show(struct seq_file *s, void *data)
{
+ struct balanced_throttle *bthrot = s->private;
int i;
- for (i = 0; i < ARRAY_SIZE(throttle_table); i++)
- seq_printf(s, "[%d] = %7u %4d %5d\n",
- i, throttle_table[i].cpu_freq,
- throttle_table[i].core_cap_level, throttle_table[i].ms);
+ for (i = 0; i < bthrot->throt_tab_size; i++)
+ seq_printf(s, "[%d] = %7u %4d\n",
+ i, bthrot->throt_tab[i].cpu_freq,
+ bthrot->throt_tab[i].core_cap_level);
+
return 0;
}
@@ -310,11 +202,11 @@ static int table_open(struct inode *inode, struct file *file)
static ssize_t table_write(struct file *file,
const char __user *userbuf, size_t count, loff_t *ppos)
{
+ struct balanced_throttle *bthrot = file->private_data;
char buf[80];
int table_idx;
unsigned int cpu_freq;
int core_cap_level;
- int ms;
if (sizeof(buf) <= count)
return -EINVAL;
@@ -327,17 +219,16 @@ static ssize_t table_write(struct file *file,
buf[count] = '\0';
strim(buf);
- if (sscanf(buf, "[%d] = %u %d %d",
- &table_idx, &cpu_freq, &core_cap_level, &ms) != 4)
+ if (sscanf(buf, "[%d] = %u %d",
+ &table_idx, &cpu_freq, &core_cap_level) != 3)
return -1;
- if ((table_idx < 0) || (table_idx >= ARRAY_SIZE(throttle_table)))
+ if ((table_idx < 0) || (table_idx >= bthrot->throt_tab_size))
return -EINVAL;
/* round new settings before updating table */
- throttle_table[table_idx].cpu_freq = clip_to_table(cpu_freq);
- throttle_table[table_idx].core_cap_level = (core_cap_level / 50) * 50;
- throttle_table[table_idx].ms = jiffies_to_msecs(msecs_to_jiffies(ms));
+ bthrot->throt_tab[table_idx].cpu_freq = clip_to_table(cpu_freq);
+ bthrot->throt_tab[table_idx].core_cap_level = (core_cap_level / 50) * 50;
return count;
}
@@ -350,18 +241,61 @@ static const struct file_operations table_fops = {
.release = single_release,
};
+static struct dentry *throttle_debugfs_root;
+#endif /* CONFIG_DEBUG_FS */
+
-int __init tegra_throttle_debug_init(struct dentry *cpu_tegra_debugfs_root)
+int balanced_throttle_register(struct balanced_throttle *bthrot)
{
- if (!debugfs_create_file("throttle", 0644, cpu_tegra_debugfs_root,
- NULL, &throttle_fops))
- return -ENOMEM;
+#ifdef CONFIG_DEBUG_FS
+ char name[32];
+#endif
+ struct balanced_throttle *dev;
+
+ mutex_lock(&bthrot_list_lock);
+ list_for_each_entry(dev, &bthrot_list, node) {
+ if (dev->id == bthrot->id) {
+ mutex_unlock(&bthrot_list_lock);
+ return -EINVAL;
+ }
+ }
+
- if (!debugfs_create_file("throttle_table", 0644, cpu_tegra_debugfs_root,
- NULL, &table_fops))
- return -ENOMEM;
+ list_add(&bthrot->node, &bthrot_list);
+ mutex_unlock(&bthrot_list_lock);
+
+ bthrot->cdev = thermal_cooling_device_register(
+ "balanced",
+ bthrot,
+ &tegra_throttle_cooling_ops);
+
+ if (IS_ERR(bthrot->cdev)) {
+ bthrot->cdev = NULL;
+ return -ENODEV;
+ }
+
+#ifdef CONFIG_DEBUG_FS
+ sprintf(name, "throttle_table%d", bthrot->id);
+ debugfs_create_file(name,0644, throttle_debugfs_root,
+ bthrot, &table_fops);
+#endif
return 0;
}
-#endif /* CONFIG_DEBUG_FS */
+
+int __init tegra_throttle_init(struct mutex *cpu_lock)
+{
+ cpu_throttle_lock = cpu_lock;
+#ifdef CONFIG_DEBUG_FS
+ throttle_debugfs_root = debugfs_create_dir("tegra_throttle", 0);
+#endif
+ return 0;
+}
+
+void tegra_throttle_exit(void)
+{
+#ifdef CONFIG_DEBUG_FS
+ debugfs_remove_recursive(throttle_debugfs_root);
+#endif
+}
diff --git a/arch/arm/mach-tegra/tegra3_tsensor.c b/arch/arm/mach-tegra/tegra3_tsensor.c
index 01d3cd7ec627..7a1c122099bc 100644
--- a/arch/arm/mach-tegra/tegra3_tsensor.c
+++ b/arch/arm/mach-tegra/tegra3_tsensor.c
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-tegra/tegra3_tsensor.c
*
- * Copyright (C) 2011 NVIDIA Corporation.
+ * Copyright (C) 2011-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
@@ -107,6 +107,7 @@ static void tegra3_tsensor_probe_callback(struct tegra_tsensor_data *data)
thermal_device->name = "tsensor";
thermal_device->data = data;
+ thermal_device->id = THERMAL_DEVICE_ID_TSENSOR;
thermal_device->offset = TSENSOR_OFFSET;
thermal_device->get_temp = tsensor_get_temp;
thermal_device->get_temp_low = tsensor_get_temp_low;
@@ -114,7 +115,8 @@ static void tegra3_tsensor_probe_callback(struct tegra_tsensor_data *data)
thermal_device->set_alert = tsensor_set_alert;
thermal_device->set_shutdown_temp = tsensor_set_shutdown_temp;
- if (tegra_thermal_set_device(thermal_device)) /* This should not fail */
+ /* This should not fail */
+ if (tegra_thermal_device_register(thermal_device))
BUG();
}
diff --git a/arch/arm/mach-tegra/tegra3_usb_phy.c b/arch/arm/mach-tegra/tegra3_usb_phy.c
new file mode 100644
index 000000000000..3a831c59a750
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra3_usb_phy.c
@@ -0,0 +1,2870 @@
+/*
+ * arch/arm/mach-tegra/tegra3_usb_phy.c
+ *
+ * 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.
+ *
+ */
+#include <linux/resource.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <linux/platform_data/tegra_usb.h>
+#include <mach/clk.h>
+#include <mach/iomap.h>
+#include <mach/pinmux.h>
+#include "tegra_usb_phy.h"
+#include "gpio-names.h"
+#include "fuse.h"
+
+#define USB_USBCMD 0x130
+#define USB_USBCMD_RS (1 << 0)
+#define USB_CMD_RESET (1<<1)
+
+#define USB_USBSTS 0x134
+#define USB_USBSTS_PCI (1 << 2)
+#define USB_USBSTS_SRI (1 << 7)
+#define USB_USBSTS_HCH (1 << 12)
+
+#define USB_USBINTR 0x138
+
+#define USB_TXFILLTUNING 0x154
+#define USB_FIFO_TXFILL_THRES(x) (((x) & 0x1f) << 16)
+#define USB_FIFO_TXFILL_MASK 0x1f0000
+
+#define USB_ASYNCLISTADDR 0x148
+
+#define ICUSB_CTRL 0x15c
+
+#define USB_PORTSC 0x174
+#define USB_PORTSC_WKOC (1 << 22)
+#define USB_PORTSC_WKDS (1 << 21)
+#define USB_PORTSC_WKCN (1 << 20)
+#define USB_PORTSC_PTC(x) (((x) & 0xf) << 16)
+#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)
+#define USB_PORTSC_CSC (1 << 1)
+#define USB_PORTSC_CCS (1 << 0)
+#define USB_PORTSC_RWC_BITS (USB_PORTSC_CSC | USB_PORTSC_PEC | USB_PORTSC_OCC)
+
+#define HOSTPC1_DEVLC 0x1b4
+#define HOSTPC1_DEVLC_PHCD (1 << 22)
+#define HOSTPC1_DEVLC_PTS(x) (((x) & 0x7) << 29)
+#define HOSTPC1_DEVLC_PTS_MASK 7
+#define HOSTPC1_DEVLC_PTS_HSIC 4
+#define HOSTPC1_DEVLC_STS (1 << 28)
+#define HOSTPC1_DEVLC_PSPD(x) (((x) & 0x3) << 25)
+#define HOSTPC1_DEVLC_PSPD_MASK 3
+#define HOSTPC1_DEVLC_PSPD_HIGH_SPEED 2
+
+#define USB_USBMODE 0x1f8
+#define USB_USBMODE_MASK (3 << 0)
+#define USB_USBMODE_HOST (3 << 0)
+#define USB_USBMODE_DEVICE (2 << 0)
+
+#define USB_SUSP_CTRL 0x400
+#define USB_WAKE_ON_CNNT_EN_DEV (1 << 3)
+#define USB_WAKE_ON_DISCON_EN_DEV (1 << 4)
+#define USB_SUSP_CLR (1 << 5)
+#define USB_PHY_CLK_VALID (1 << 7)
+#define USB_PHY_CLK_VALID_INT_ENB (1 << 9)
+#define USB_PHY_CLK_VALID_INT_STS (1 << 8)
+#define UTMIP_RESET (1 << 11)
+#define UTMIP_PHY_ENABLE (1 << 12)
+#define ULPI_PHY_ENABLE (1 << 13)
+#define UHSIC_RESET (1 << 14)
+#define USB_WAKEUP_DEBOUNCE_COUNT(x) (((x) & 0x7) << 16)
+#define UHSIC_PHY_ENABLE (1 << 19)
+#define ULPIS2S_SLV0_RESET (1 << 20)
+#define ULPIS2S_SLV1_RESET (1 << 21)
+#define ULPIS2S_LINE_RESET (1 << 22)
+#define ULPI_PADS_RESET (1 << 23)
+#define ULPI_PADS_CLKEN_RESET (1 << 24)
+
+#define USB_PHY_VBUS_WAKEUP_ID 0x408
+#define VDAT_DET_INT_EN (1 << 16)
+#define VDAT_DET_CHG_DET (1 << 17)
+#define VDAT_DET_STS (1 << 18)
+#define USB_ID_STATUS (1 << 2)
+
+#define ULPIS2S_CTRL 0x418
+#define ULPIS2S_ENA (1 << 0)
+#define ULPIS2S_SUPPORT_DISCONNECT (1 << 2)
+#define ULPIS2S_PLLU_MASTER_BLASTER60 (1 << 3)
+#define ULPIS2S_SPARE(x) (((x) & 0xF) << 8)
+#define ULPIS2S_FORCE_ULPI_CLK_OUT (1 << 12)
+#define ULPIS2S_DISCON_DONT_CHECK_SE0 (1 << 13)
+#define ULPIS2S_SUPPORT_HS_KEEP_ALIVE (1 << 14)
+#define ULPIS2S_DISABLE_STP_PU (1 << 15)
+#define ULPIS2S_SLV0_CLAMP_XMIT (1 << 16)
+
+#define ULPI_TIMING_CTRL_0 0x424
+#define ULPI_CLOCK_OUT_DELAY(x) ((x) & 0x1F)
+#define ULPI_OUTPUT_PINMUX_BYP (1 << 10)
+#define ULPI_CLKOUT_PINMUX_BYP (1 << 11)
+#define ULPI_SHADOW_CLK_LOOPBACK_EN (1 << 12)
+#define ULPI_SHADOW_CLK_SEL (1 << 13)
+#define ULPI_CORE_CLK_SEL (1 << 14)
+#define ULPI_SHADOW_CLK_DELAY(x) (((x) & 0x1F) << 16)
+#define ULPI_LBK_PAD_EN (1 << 26)
+#define ULPI_LBK_PAD_E_INPUT_OR (1 << 27)
+#define ULPI_CLK_OUT_ENA (1 << 28)
+#define ULPI_CLK_PADOUT_ENA (1 << 29)
+
+#define ULPI_TIMING_CTRL_1 0x428
+#define ULPI_DATA_TRIMMER_LOAD (1 << 0)
+#define ULPI_DATA_TRIMMER_SEL(x) (((x) & 0x7) << 1)
+#define ULPI_STPDIRNXT_TRIMMER_LOAD (1 << 16)
+#define ULPI_STPDIRNXT_TRIMMER_SEL(x) (((x) & 0x7) << 17)
+#define ULPI_DIR_TRIMMER_LOAD (1 << 24)
+#define ULPI_DIR_TRIMMER_SEL(x) (((x) & 0x7) << 25)
+
+#define UTMIP_XCVR_CFG0 0x808
+#define UTMIP_XCVR_SETUP(x) (((x) & 0xf) << 0)
+#define UTMIP_XCVR_LSRSLEW(x) (((x) & 0x3) << 8)
+#define UTMIP_XCVR_LSFSLEW(x) (((x) & 0x3) << 10)
+#define UTMIP_FORCE_PD_POWERDOWN (1 << 14)
+#define UTMIP_FORCE_PD2_POWERDOWN (1 << 16)
+#define UTMIP_FORCE_PDZI_POWERDOWN (1 << 18)
+#define UTMIP_XCVR_LSBIAS_SEL (1 << 21)
+#define UTMIP_XCVR_SETUP_MSB(x) (((x) & 0x7) << 22)
+#define UTMIP_XCVR_HSSLEW_MSB(x) (((x) & 0x7f) << 25)
+#define UTMIP_XCVR_MAX_OFFSET 2
+#define UTMIP_XCVR_SETUP_MAX_VALUE 0x7f
+#define UTMIP_XCVR_SETUP_MIN_VALUE 0
+#define XCVR_SETUP_MSB_CALIB(x) ((x) >> 4)
+
+#define UTMIP_BIAS_CFG0 0x80c
+#define UTMIP_OTGPD (1 << 11)
+#define UTMIP_BIASPD (1 << 10)
+#define UTMIP_HSSQUELCH_LEVEL(x) (((x) & 0x3) << 0)
+#define UTMIP_HSDISCON_LEVEL(x) (((x) & 0x3) << 2)
+#define UTMIP_HSDISCON_LEVEL_MSB (1 << 24)
+
+#define UTMIP_HSRX_CFG0 0x810
+#define UTMIP_ELASTIC_LIMIT(x) (((x) & 0x1f) << 10)
+#define UTMIP_IDLE_WAIT(x) (((x) & 0x1f) << 15)
+
+#define UTMIP_HSRX_CFG1 0x814
+#define UTMIP_HS_SYNC_START_DLY(x) (((x) & 0x1f) << 1)
+
+#define UTMIP_TX_CFG0 0x820
+#define UTMIP_FS_PREABMLE_J (1 << 19)
+#define UTMIP_HS_DISCON_DISABLE (1 << 8)
+
+#define UTMIP_DEBOUNCE_CFG0 0x82c
+#define UTMIP_BIAS_DEBOUNCE_A(x) (((x) & 0xffff) << 0)
+
+#define UTMIP_BAT_CHRG_CFG0 0x830
+#define UTMIP_PD_CHRG (1 << 0)
+#define UTMIP_ON_SINK_EN (1 << 2)
+#define UTMIP_OP_SRC_EN (1 << 3)
+
+#define UTMIP_XCVR_CFG1 0x838
+#define UTMIP_FORCE_PDDISC_POWERDOWN (1 << 0)
+#define UTMIP_FORCE_PDCHRP_POWERDOWN (1 << 2)
+#define UTMIP_FORCE_PDDR_POWERDOWN (1 << 4)
+#define UTMIP_XCVR_TERM_RANGE_ADJ(x) (((x) & 0xf) << 18)
+
+#define UTMIP_BIAS_CFG1 0x83c
+#define UTMIP_BIAS_PDTRK_COUNT(x) (((x) & 0x1f) << 3)
+#define UTMIP_BIAS_PDTRK_POWERDOWN (1 << 0)
+#define UTMIP_BIAS_PDTRK_POWERUP (1 << 1)
+
+#define UTMIP_MISC_CFG0 0x824
+#define UTMIP_DPDM_OBSERVE (1 << 26)
+#define UTMIP_DPDM_OBSERVE_SEL(x) (((x) & 0xf) << 27)
+#define UTMIP_DPDM_OBSERVE_SEL_FS_J UTMIP_DPDM_OBSERVE_SEL(0xf)
+#define UTMIP_DPDM_OBSERVE_SEL_FS_K UTMIP_DPDM_OBSERVE_SEL(0xe)
+#define UTMIP_DPDM_OBSERVE_SEL_FS_SE1 UTMIP_DPDM_OBSERVE_SEL(0xd)
+#define UTMIP_DPDM_OBSERVE_SEL_FS_SE0 UTMIP_DPDM_OBSERVE_SEL(0xc)
+#define UTMIP_SUSPEND_EXIT_ON_EDGE (1 << 22)
+#define FORCE_PULLDN_DM (1 << 8)
+#define FORCE_PULLDN_DP (1 << 9)
+#define COMB_TERMS (1 << 0)
+#define ALWAYS_FREE_RUNNING_TERMS (1 << 1)
+
+#define UTMIP_SPARE_CFG0 0x834
+#define FUSE_SETUP_SEL (1 << 3)
+#define FUSE_ATERM_SEL (1 << 4)
+
+#define UTMIP_PMC_WAKEUP0 0x84c
+#define EVENT_INT_ENB (1 << 0)
+
+#define UHSIC_PMC_WAKEUP0 0xc34
+
+#define UTMIP_BIAS_STS0 0x840
+#define UTMIP_RCTRL_VAL(x) (((x) & 0xffff) << 0)
+#define UTMIP_TCTRL_VAL(x) (((x) & (0xffff << 16)) >> 16)
+
+#define UHSIC_PLL_CFG1 0xc04
+#define UHSIC_XTAL_FREQ_COUNT(x) (((x) & 0xfff) << 0)
+#define UHSIC_PLLU_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 14)
+
+#define UHSIC_HSRX_CFG0 0xc08
+#define UHSIC_ELASTIC_UNDERRUN_LIMIT(x) (((x) & 0x1f) << 2)
+#define UHSIC_ELASTIC_OVERRUN_LIMIT(x) (((x) & 0x1f) << 8)
+#define UHSIC_IDLE_WAIT(x) (((x) & 0x1f) << 13)
+
+#define UHSIC_HSRX_CFG1 0xc0c
+#define UHSIC_HS_SYNC_START_DLY(x) (((x) & 0x1f) << 1)
+
+#define UHSIC_TX_CFG0 0xc10
+#define UHSIC_HS_READY_WAIT_FOR_VALID (1 << 9)
+#define UHSIC_MISC_CFG0 0xc14
+#define UHSIC_SUSPEND_EXIT_ON_EDGE (1 << 7)
+#define UHSIC_DETECT_SHORT_CONNECT (1 << 8)
+#define UHSIC_FORCE_XCVR_MODE (1 << 15)
+#define UHSIC_DISABLE_BUSRESET (1 << 20)
+#define UHSIC_MISC_CFG1 0xc18
+#define UHSIC_PLLU_STABLE_COUNT(x) (((x) & 0xfff) << 2)
+
+#define UHSIC_PADS_CFG0 0xc1c
+#define UHSIC_TX_RTUNEN 0xf000
+#define UHSIC_TX_RTUNE(x) (((x) & 0xf) << 12)
+
+#define UHSIC_PADS_CFG1 0xc20
+#define UHSIC_PD_BG (1 << 2)
+#define UHSIC_PD_TX (1 << 3)
+#define UHSIC_PD_TRK (1 << 4)
+#define UHSIC_PD_RX (1 << 5)
+#define UHSIC_PD_ZI (1 << 6)
+#define UHSIC_RX_SEL (1 << 7)
+#define UHSIC_RPD_DATA (1 << 9)
+#define UHSIC_RPD_STROBE (1 << 10)
+#define UHSIC_RPU_DATA (1 << 11)
+#define UHSIC_RPU_STROBE (1 << 12)
+
+#define UHSIC_CMD_CFG0 0xc24
+#define UHSIC_PRETEND_CONNECT_DETECT (1 << 5)
+
+#define UHSIC_STAT_CFG0 0xc28
+#define UHSIC_CONNECT_DETECT (1 << 0)
+
+#define PMC_USB_DEBOUNCE 0xec
+#define UTMIP_LINE_DEB_CNT(x) (((x) & 0xf) << 16)
+#define UHSIC_LINE_DEB_CNT(x) (((x) & 0xf) << 20)
+
+#define PMC_USB_AO 0xf0
+
+#define PMC_POWER_DOWN_MASK 0xffff
+#define HSIC_RESERVED_P0 (3 << 14)
+#define STROBE_VAL_PD_P0 (1 << 12)
+#define DATA_VAL_PD_P0 (1 << 13)
+
+#define USB_ID_PD(inst) (1 << ((4*(inst))+3))
+#define VBUS_WAKEUP_PD(inst) (1 << ((4*(inst))+2))
+#define USBON_VAL_PD(inst) (1 << ((4*(inst))+1))
+#define USBON_VAL_PD_P2 (1 << 9)
+#define USBON_VAL_PD_P1 (1 << 5)
+#define USBON_VAL_PD_P0 (1 << 1)
+#define USBOP_VAL_PD(inst) (1 << (4*(inst)))
+#define USBOP_VAL_PD_P2 (1 << 8)
+#define USBOP_VAL_PD_P1 (1 << 4)
+#define USBOP_VAL_PD_P0 (1 << 0)
+#define PMC_USB_AO_PD_P2 (0xf << 8)
+#define PMC_USB_AO_ID_PD_P0 (1 << 3)
+#define PMC_USB_AO_VBUS_WAKEUP_PD_P0 (1 << 2)
+
+#define PMC_TRIGGERS 0x1ec
+
+#define UHSIC_CLR_WALK_PTR_P0 (1 << 3)
+#define UTMIP_CLR_WALK_PTR(inst) (1 << (inst))
+#define UTMIP_CLR_WALK_PTR_P2 (1 << 2)
+#define UTMIP_CLR_WALK_PTR_P1 (1 << 1)
+#define UTMIP_CLR_WALK_PTR_P0 (1 << 0)
+#define UTMIP_CAP_CFG(inst) (1 << ((inst)+4))
+#define UTMIP_CAP_CFG_P2 (1 << 6)
+#define UTMIP_CAP_CFG_P1 (1 << 5)
+#define UTMIP_CAP_CFG_P0 (1 << 4)
+#define UTMIP_CLR_WAKE_ALARM(inst) (1 << ((inst)+12))
+#define UHSIC_CLR_WAKE_ALARM_P0 (1 << 15)
+#define UTMIP_CLR_WAKE_ALARM_P2 (1 << 14)
+
+#define PMC_PAD_CFG (0x1f4)
+
+#define PMC_UTMIP_TERM_PAD_CFG 0x1f8
+#define PMC_TCTRL_VAL(x) (((x) & 0x1f) << 5)
+#define PMC_RCTRL_VAL(x) (((x) & 0x1f) << 0)
+
+#define PMC_SLEEP_CFG 0x1fc
+
+#define UHSIC_MASTER_ENABLE (1 << 24)
+#define UHSIC_WAKE_VAL(x) (((x) & 0xf) << 28)
+#define WAKE_VAL_SD10 0x2
+#define UTMIP_TCTRL_USE_PMC(inst) (1 << ((8*(inst))+3))
+#define UTMIP_TCTRL_USE_PMC_P2 (1 << 19)
+#define UTMIP_TCTRL_USE_PMC_P1 (1 << 11)
+#define UTMIP_TCTRL_USE_PMC_P0 (1 << 3)
+#define UTMIP_RCTRL_USE_PMC(inst) (1 << ((8*(inst))+2))
+#define UTMIP_RCTRL_USE_PMC_P2 (1 << 18)
+#define UTMIP_RCTRL_USE_PMC_P1 (1 << 10)
+#define UTMIP_RCTRL_USE_PMC_P0 (1 << 2)
+#define UTMIP_FSLS_USE_PMC(inst) (1 << ((8*(inst))+1))
+#define UTMIP_FSLS_USE_PMC_P2 (1 << 17)
+#define UTMIP_FSLS_USE_PMC_P1 (1 << 9)
+#define UTMIP_FSLS_USE_PMC_P0 (1 << 1)
+#define UTMIP_MASTER_ENABLE(inst) (1 << (8*(inst)))
+#define UTMIP_MASTER_ENABLE_P2 (1 << 16)
+#define UTMIP_MASTER_ENABLE_P1 (1 << 8)
+#define UTMIP_MASTER_ENABLE_P0 (1 << 0)
+#define UHSIC_MASTER_ENABLE_P0 (1 << 24)
+#define UHSIC_WAKE_VAL_P0(x) (((x) & 0xf) << 28)
+
+#define PMC_SLEEPWALK_CFG 0x200
+
+#define UHSIC_WAKE_WALK_EN_P0 (1 << 30)
+#define UHSIC_LINEVAL_WALK_EN (1 << 31)
+#define UTMIP_LINEVAL_WALK_EN(inst) (1 << ((8*(inst))+7))
+#define UTMIP_LINEVAL_WALK_EN_P2 (1 << 23)
+#define UTMIP_LINEVAL_WALK_EN_P1 (1 << 15)
+#define UTMIP_LINEVAL_WALK_EN_P0 (1 << 7)
+#define UTMIP_WAKE_VAL(inst, x) (((x) & 0xf) << ((8*(inst))+4))
+#define UTMIP_WAKE_VAL_P2(x) (((x) & 0xf) << 20)
+#define UTMIP_WAKE_VAL_P1(x) (((x) & 0xf) << 12)
+#define UTMIP_WAKE_VAL_P0(x) (((x) & 0xf) << 4)
+#define WAKE_VAL_NONE 0xc
+#define WAKE_VAL_ANY 0xF
+#define WAKE_VAL_FSJ 0x2
+#define WAKE_VAL_FSK 0x1
+#define WAKE_VAL_SE0 0x0
+
+#define PMC_SLEEPWALK_REG(inst) (0x204 + (4*(inst)))
+#define UTMIP_USBOP_RPD_A (1 << 0)
+#define UTMIP_USBON_RPD_A (1 << 1)
+#define UTMIP_AP_A (1 << 4)
+#define UTMIP_AN_A (1 << 5)
+#define UTMIP_HIGHZ_A (1 << 6)
+#define UTMIP_USBOP_RPD_B (1 << 8)
+#define UTMIP_USBON_RPD_B (1 << 9)
+#define UTMIP_AP_B (1 << 12)
+#define UTMIP_AN_B (1 << 13)
+#define UTMIP_HIGHZ_B (1 << 14)
+#define UTMIP_USBOP_RPD_C (1 << 16)
+#define UTMIP_USBON_RPD_C (1 << 17)
+#define UTMIP_AP_C (1 << 20)
+#define UTMIP_AN_C (1 << 21)
+#define UTMIP_HIGHZ_C (1 << 22)
+#define UTMIP_USBOP_RPD_D (1 << 24)
+#define UTMIP_USBON_RPD_D (1 << 25)
+#define UTMIP_AP_D (1 << 28)
+#define UTMIP_AN_D (1 << 29)
+#define UTMIP_HIGHZ_D (1 << 30)
+
+#define PMC_SLEEPWALK_UHSIC 0x210
+
+#define UHSIC_STROBE_RPD_A (1 << 0)
+#define UHSIC_DATA_RPD_A (1 << 1)
+#define UHSIC_STROBE_RPU_A (1 << 2)
+#define UHSIC_DATA_RPU_A (1 << 3)
+#define UHSIC_STROBE_RPD_B (1 << 8)
+#define UHSIC_DATA_RPD_B (1 << 9)
+#define UHSIC_STROBE_RPU_B (1 << 10)
+#define UHSIC_DATA_RPU_B (1 << 11)
+#define UHSIC_STROBE_RPD_C (1 << 16)
+#define UHSIC_DATA_RPD_C (1 << 17)
+#define UHSIC_STROBE_RPU_C (1 << 18)
+#define UHSIC_DATA_RPU_C (1 << 19)
+#define UHSIC_STROBE_RPD_D (1 << 24)
+#define UHSIC_DATA_RPD_D (1 << 25)
+#define UHSIC_STROBE_RPU_D (1 << 26)
+#define UHSIC_DATA_RPU_D (1 << 27)
+
+#define UTMIP_UHSIC_STATUS 0x214
+
+#define UTMIP_USBOP_VAL(inst) (1 << ((2*(inst)) + 8))
+#define UTMIP_USBOP_VAL_P2 (1 << 12)
+#define UTMIP_USBOP_VAL_P1 (1 << 10)
+#define UTMIP_USBOP_VAL_P0 (1 << 8)
+#define UTMIP_USBON_VAL(inst) (1 << ((2*(inst)) + 9))
+#define UTMIP_USBON_VAL_P2 (1 << 13)
+#define UTMIP_USBON_VAL_P1 (1 << 11)
+#define UTMIP_USBON_VAL_P0 (1 << 9)
+#define UHSIC_WAKE_ALARM (1 << 19)
+#define UTMIP_WAKE_ALARM(inst) (1 << ((inst) + 16))
+#define UTMIP_WAKE_ALARM_P2 (1 << 18)
+#define UTMIP_WAKE_ALARM_P1 (1 << 17)
+#define UTMIP_WAKE_ALARM_P0 (1 << 16)
+#define UHSIC_DATA_VAL_P0 (1 << 15)
+#define UHSIC_STROBE_VAL_P0 (1 << 14)
+#define UTMIP_WALK_PTR_VAL(inst) (0x3 << ((inst)*2))
+#define UHSIC_WALK_PTR_VAL (0x3 << 6)
+#define UTMIP_WALK_PTR(inst) (1 << ((inst)*2))
+#define UTMIP_WALK_PTR_P2 (1 << 4)
+#define UTMIP_WALK_PTR_P1 (1 << 2)
+#define UTMIP_WALK_PTR_P0 (1 << 0)
+
+#define USB1_PREFETCH_ID 6
+#define USB2_PREFETCH_ID 18
+#define USB3_PREFETCH_ID 17
+
+#define PMC_UTMIP_UHSIC_FAKE 0x218
+
+#define UHSIC_STROBE_VAL (1 << 12)
+#define UHSIC_DATA_VAL (1 << 13)
+#define UHSIC_STROBE_ENB (1 << 14)
+#define UHSIC_DATA_ENB (1 << 15)
+#define USBON_VAL(inst) (1 << ((4*(inst))+1))
+#define USBON_VAL_P2 (1 << 9)
+#define USBON_VAL_P1 (1 << 5)
+#define USBON_VAL_P0 (1 << 1)
+#define USBOP_VAL(inst) (1 << (4*(inst)))
+#define USBOP_VAL_P2 (1 << 8)
+#define USBOP_VAL_P1 (1 << 4)
+#define USBOP_VAL_P0 (1 << 0)
+
+#define PMC_UTMIP_BIAS_MASTER_CNTRL 0x30c
+#define BIAS_MASTER_PROG_VAL (1 << 1)
+
+#define PMC_UTMIP_MASTER_CONFIG 0x310
+
+#define UTMIP_PWR(inst) (1 << (inst))
+#define UHSIC_PWR (1 << 3)
+
+#define FUSE_USB_CALIB_0 0x1F0
+#define XCVR_SETUP(x) (((x) & 0x7F) << 0)
+#define XCVR_SETUP_LSB_MASK 0xF
+#define XCVR_SETUP_MSB_MASK 0x70
+#define XCVR_SETUP_LSB_MAX_VAL 0xF
+
+#define APB_MISC_GP_OBSCTRL_0 0x818
+#define APB_MISC_GP_OBSDATA_0 0x81c
+
+/* ULPI GPIO */
+#define ULPI_STP TEGRA_GPIO_PY3
+#define ULPI_DIR TEGRA_GPIO_PY1
+#define ULPI_D0 TEGRA_GPIO_PO1
+#define ULPI_D1 TEGRA_GPIO_PO2
+
+/* These values (in milli second) are taken from the battery charging spec */
+#define TDP_SRC_ON_MS 100
+#define TDPSRC_CON_MS 40
+
+#ifdef DEBUG
+#define DBG(stuff...) pr_info("tegra3_usb_phy: " stuff)
+#else
+#define DBG(stuff...) do {} while (0)
+#endif
+
+#if 0
+#define PHY_DBG(stuff...) pr_info("tegra3_usb_phy: " stuff)
+#else
+#define PHY_DBG(stuff...) do {} while (0)
+#endif
+
+
+static u32 utmip_rctrl_val, utmip_tctrl_val;
+static DEFINE_SPINLOCK(utmip_pad_lock);
+static int utmip_pad_count;
+
+static struct tegra_xtal_freq utmip_freq_table[] = {
+ {
+ .freq = 12000000,
+ .enable_delay = 0x02,
+ .stable_count = 0x2F,
+ .active_delay = 0x04,
+ .xtal_freq_count = 0x76,
+ .debounce = 0x7530,
+ .pdtrk_count = 5,
+ },
+ {
+ .freq = 13000000,
+ .enable_delay = 0x02,
+ .stable_count = 0x33,
+ .active_delay = 0x05,
+ .xtal_freq_count = 0x7F,
+ .debounce = 0x7EF4,
+ .pdtrk_count = 5,
+ },
+ {
+ .freq = 19200000,
+ .enable_delay = 0x03,
+ .stable_count = 0x4B,
+ .active_delay = 0x06,
+ .xtal_freq_count = 0xBB,
+ .debounce = 0xBB80,
+ .pdtrk_count = 7,
+ },
+ {
+ .freq = 26000000,
+ .enable_delay = 0x04,
+ .stable_count = 0x66,
+ .active_delay = 0x09,
+ .xtal_freq_count = 0xFE,
+ .debounce = 0xFDE8,
+ .pdtrk_count = 9,
+ },
+};
+
+static struct tegra_xtal_freq uhsic_freq_table[] = {
+ {
+ .freq = 12000000,
+ .enable_delay = 0x02,
+ .stable_count = 0x2F,
+ .active_delay = 0x0,
+ .xtal_freq_count = 0x1CA,
+ },
+ {
+ .freq = 13000000,
+ .enable_delay = 0x02,
+ .stable_count = 0x33,
+ .active_delay = 0x0,
+ .xtal_freq_count = 0x1F0,
+ },
+ {
+ .freq = 19200000,
+ .enable_delay = 0x03,
+ .stable_count = 0x4B,
+ .active_delay = 0x0,
+ .xtal_freq_count = 0x2DD,
+ },
+ {
+ .freq = 26000000,
+ .enable_delay = 0x04,
+ .stable_count = 0x66,
+ .active_delay = 0x0,
+ .xtal_freq_count = 0x3E0,
+ },
+};
+
+static void usb_phy_fence_read(struct tegra_usb_phy *phy)
+{
+ /* Fence read for coherency of AHB master intiated writes */
+ if (phy->inst == 0)
+ readb(IO_ADDRESS(IO_PPCS_PHYS + USB1_PREFETCH_ID));
+ else if (phy->inst == 1)
+ readb(IO_ADDRESS(IO_PPCS_PHYS + USB2_PREFETCH_ID));
+ else if (phy->inst == 2)
+ readb(IO_ADDRESS(IO_PPCS_PHYS + USB3_PREFETCH_ID));
+
+ return;
+}
+
+static void utmip_setup_pmc_wake_detect(struct tegra_usb_phy *phy)
+{
+ unsigned long val, pmc_pad_cfg_val;
+ void __iomem *pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
+ unsigned int inst = phy->inst;
+ void __iomem *base = phy->regs;
+ bool port_connected;
+ enum usb_phy_port_speed port_speed;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+
+ /* check for port connect status */
+ val = readl(base + USB_PORTSC);
+ port_connected = val & USB_PORTSC_CCS;
+
+ if (!port_connected)
+ return;
+
+ port_speed = (readl(base + HOSTPC1_DEVLC) >> 25) &
+ HOSTPC1_DEVLC_PSPD_MASK;
+ /*Set PMC MASTER bits to do the following
+ * a. Take over the UTMI drivers
+ * b. set up such that it will take over resume
+ * if remote wakeup is detected
+ * Prepare PMC to take over suspend-wake detect-drive resume until USB
+ * controller ready
+ */
+
+ /* disable master enable in PMC */
+ val = readl(pmc_base + PMC_SLEEP_CFG);
+ val &= ~UTMIP_MASTER_ENABLE(inst);
+ writel(val, pmc_base + PMC_SLEEP_CFG);
+
+ /* UTMIP_PWR_PX=1 for power savings mode */
+ val = readl(pmc_base + PMC_UTMIP_MASTER_CONFIG);
+ val |= UTMIP_PWR(inst);
+ writel(val, pmc_base + PMC_UTMIP_MASTER_CONFIG);
+
+ /* config debouncer */
+ val = readl(pmc_base + PMC_USB_DEBOUNCE);
+ val &= ~UTMIP_LINE_DEB_CNT(~0);
+ val |= UTMIP_LINE_DEB_CNT(4);
+ writel(val, pmc_base + PMC_USB_DEBOUNCE);
+
+ /* Make sure nothing is happening on the line with respect to PMC */
+ val = readl(pmc_base + PMC_UTMIP_UHSIC_FAKE);
+ val &= ~USBOP_VAL(inst);
+ val &= ~USBON_VAL(inst);
+ writel(val, pmc_base + PMC_UTMIP_UHSIC_FAKE);
+
+ /* Make sure wake value for line is none */
+ val = readl(pmc_base + PMC_SLEEPWALK_CFG);
+ val &= ~UTMIP_LINEVAL_WALK_EN(inst);
+ writel(val, pmc_base + PMC_SLEEPWALK_CFG);
+ val = readl(pmc_base + PMC_SLEEP_CFG);
+ val &= ~UTMIP_WAKE_VAL(inst, ~0);
+ val |= UTMIP_WAKE_VAL(inst, WAKE_VAL_NONE);
+ writel(val, pmc_base + PMC_SLEEP_CFG);
+
+ /* turn off pad detectors */
+ val = readl(pmc_base + PMC_USB_AO);
+ val |= (USBOP_VAL_PD(inst) | USBON_VAL_PD(inst));
+ writel(val, pmc_base + PMC_USB_AO);
+
+ /* Remove fake values and make synchronizers work a bit */
+ val = readl(pmc_base + PMC_UTMIP_UHSIC_FAKE);
+ val &= ~USBOP_VAL(inst);
+ val &= ~USBON_VAL(inst);
+ 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);
+ writel(val, pmc_base + PMC_SLEEPWALK_CFG);
+
+ /* Capture FS/LS pad configurations */
+ pmc_pad_cfg_val = readl(pmc_base + PMC_PAD_CFG);
+ val = readl(pmc_base + PMC_TRIGGERS);
+ val |= UTMIP_CAP_CFG(inst);
+ writel(val, pmc_base + PMC_TRIGGERS);
+ udelay(1);
+ pmc_pad_cfg_val = readl(pmc_base + PMC_PAD_CFG);
+
+ /* BIAS MASTER_ENABLE=0 */
+ val = readl(pmc_base + PMC_UTMIP_BIAS_MASTER_CNTRL);
+ val &= ~BIAS_MASTER_PROG_VAL;
+ writel(val, pmc_base + PMC_UTMIP_BIAS_MASTER_CNTRL);
+
+ /* program walk sequence, maintain a J, followed by a driven K
+ * to signal a resume once an wake event is detected */
+ val = readl(pmc_base + PMC_SLEEPWALK_REG(inst));
+ val &= ~UTMIP_AP_A;
+ val |= UTMIP_USBOP_RPD_A | UTMIP_USBON_RPD_A | UTMIP_AN_A |UTMIP_HIGHZ_A |
+ UTMIP_USBOP_RPD_B | UTMIP_USBON_RPD_B | UTMIP_AP_B | UTMIP_AN_B |
+ UTMIP_USBOP_RPD_C | UTMIP_USBON_RPD_C | UTMIP_AP_C | UTMIP_AN_C |
+ UTMIP_USBOP_RPD_D | UTMIP_USBON_RPD_D | UTMIP_AP_D | UTMIP_AN_D;
+ writel(val, pmc_base + PMC_SLEEPWALK_REG(inst));
+
+ if (port_speed == USB_PHY_PORT_SPEED_LOW) {
+ val = readl(pmc_base + PMC_SLEEPWALK_REG(inst));
+ val &= ~(UTMIP_AN_B | UTMIP_HIGHZ_B | UTMIP_AN_C |
+ UTMIP_HIGHZ_C | UTMIP_AN_D | UTMIP_HIGHZ_D);
+ writel(val, pmc_base + PMC_SLEEPWALK_REG(inst));
+ } else {
+ val = readl(pmc_base + PMC_SLEEPWALK_REG(inst));
+ val &= ~(UTMIP_AP_B | UTMIP_HIGHZ_B | UTMIP_AP_C |
+ UTMIP_HIGHZ_C | UTMIP_AP_D | UTMIP_HIGHZ_D);
+ writel(val, pmc_base + PMC_SLEEPWALK_REG(inst));
+ }
+
+ /* turn on pad detectors */
+ val = readl(pmc_base + PMC_USB_AO);
+ val &= ~(USBOP_VAL_PD(inst) | USBON_VAL_PD(inst));
+ writel(val, pmc_base + PMC_USB_AO);
+
+ /* Add small delay before usb detectors provide stable line values */
+ mdelay(1);
+
+ /* Program thermally encoded RCTRL_VAL, TCTRL_VAL into PMC space */
+ val = readl(pmc_base + PMC_UTMIP_TERM_PAD_CFG);
+ val = PMC_TCTRL_VAL(utmip_tctrl_val) | PMC_RCTRL_VAL(utmip_rctrl_val);
+ writel(val, pmc_base + PMC_UTMIP_TERM_PAD_CFG);
+
+ phy->remote_wakeup = false;
+
+ /* Turn over pad configuration to PMC for line wake events*/
+ val = readl(pmc_base + PMC_SLEEP_CFG);
+ val &= ~UTMIP_WAKE_VAL(inst, ~0);
+ val |= UTMIP_WAKE_VAL(inst, WAKE_VAL_ANY);
+ val |= UTMIP_RCTRL_USE_PMC(inst) | UTMIP_TCTRL_USE_PMC(inst);
+ val |= UTMIP_MASTER_ENABLE(inst) | UTMIP_FSLS_USE_PMC(inst);
+ writel(val, pmc_base + PMC_SLEEP_CFG);
+
+ val = readl(base + UTMIP_PMC_WAKEUP0);
+ val |= EVENT_INT_ENB;
+ writel(val, base + UTMIP_PMC_WAKEUP0);
+ PHY_DBG("%s ENABLE_PMC inst = %d\n", __func__, inst);
+}
+
+static void utmip_phy_disable_pmc_bus_ctrl(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
+ unsigned int inst = phy->inst;
+ void __iomem *base = phy->regs;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+
+ val = readl(pmc_base + PMC_SLEEP_CFG);
+ val &= ~UTMIP_WAKE_VAL(inst, 0xF);
+ 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);
+
+ /* Disable PMC master mode by clearing MASTER_EN */
+ val = readl(pmc_base + PMC_SLEEP_CFG);
+ val &= ~(UTMIP_RCTRL_USE_PMC(inst) | UTMIP_TCTRL_USE_PMC(inst) |
+ UTMIP_FSLS_USE_PMC(inst) | UTMIP_MASTER_ENABLE(inst));
+ writel(val, pmc_base + PMC_SLEEP_CFG);
+
+ val = readl(pmc_base + PMC_TRIGGERS);
+ val &= ~UTMIP_CAP_CFG(inst);
+ writel(val, pmc_base + PMC_TRIGGERS);
+
+ /* turn off pad detectors */
+ val = readl(pmc_base + PMC_USB_AO);
+ val |= (USBOP_VAL_PD(inst) | USBON_VAL_PD(inst));
+ writel(val, pmc_base + PMC_USB_AO);
+
+ phy->remote_wakeup = false;
+ PHY_DBG("%s DISABLE_PMC inst = %d\n", __func__, inst);
+}
+
+bool utmi_phy_remotewake_detected(struct tegra_usb_phy *phy)
+{
+ void __iomem *pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
+ void __iomem *base = phy->regs;
+ unsigned int inst = phy->inst;
+ u32 val;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ val = readl(base + UTMIP_PMC_WAKEUP0);
+ if (val & EVENT_INT_ENB) {
+ val = readl(pmc_base + UTMIP_UHSIC_STATUS);
+ if (UTMIP_WAKE_ALARM(inst) & val) {
+ val = readl(pmc_base + PMC_SLEEP_CFG);
+ val &= ~UTMIP_WAKE_VAL(inst, 0xF);
+ 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);
+ phy->remote_wakeup = true;
+ return true;
+ }
+ }
+ return false;
+}
+
+static void utmi_phy_enable_trking_data(struct tegra_usb_phy *phy)
+{
+ void __iomem *base = IO_ADDRESS(TEGRA_USB_BASE);
+ void __iomem *pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
+ static bool init_done = false;
+ u32 val;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+
+ /* Should be done only once after system boot */
+ if (init_done)
+ return;
+
+ clk_enable(phy->utmi_pad_clk);
+ /* Bias pad MASTER_ENABLE=1 */
+ val = readl(pmc_base + PMC_UTMIP_BIAS_MASTER_CNTRL);
+ val |= BIAS_MASTER_PROG_VAL;
+ writel(val, pmc_base + PMC_UTMIP_BIAS_MASTER_CNTRL);
+
+ /* Setting the tracking length time */
+ val = readl(base + UTMIP_BIAS_CFG1);
+ val &= ~UTMIP_BIAS_PDTRK_COUNT(~0);
+ val |= UTMIP_BIAS_PDTRK_COUNT(5);
+ writel(val, base + UTMIP_BIAS_CFG1);
+
+ /* Bias PDTRK is Shared and MUST be done from USB1 ONLY, PD_TRK=0 */
+ val = readl(base + UTMIP_BIAS_CFG1);
+ val &= ~UTMIP_BIAS_PDTRK_POWERDOWN;
+ writel(val, base + UTMIP_BIAS_CFG1);
+
+ val = readl(base + UTMIP_BIAS_CFG1);
+ val |= UTMIP_BIAS_PDTRK_POWERUP;
+ writel(val, base + UTMIP_BIAS_CFG1);
+
+ /* Wait for 25usec */
+ udelay(25);
+
+ /* Bias pad MASTER_ENABLE=0 */
+ val = readl(pmc_base + PMC_UTMIP_BIAS_MASTER_CNTRL);
+ val &= ~BIAS_MASTER_PROG_VAL;
+ writel(val, pmc_base + PMC_UTMIP_BIAS_MASTER_CNTRL);
+
+ /* Wait for 1usec */
+ udelay(1);
+
+ /* Bias pad MASTER_ENABLE=1 */
+ val = readl(pmc_base + PMC_UTMIP_BIAS_MASTER_CNTRL);
+ val |= BIAS_MASTER_PROG_VAL;
+ writel(val, pmc_base + PMC_UTMIP_BIAS_MASTER_CNTRL);
+
+ /* Read RCTRL and TCTRL from UTMIP space */
+ val = readl(base + UTMIP_BIAS_STS0);
+ utmip_rctrl_val = ffz(UTMIP_RCTRL_VAL(val));
+ utmip_tctrl_val = ffz(UTMIP_TCTRL_VAL(val));
+
+ /* PD_TRK=1 */
+ val = readl(base + UTMIP_BIAS_CFG1);
+ val |= UTMIP_BIAS_PDTRK_POWERDOWN;
+ writel(val, base + UTMIP_BIAS_CFG1);
+
+ /* Program thermally encoded RCTRL_VAL, TCTRL_VAL into PMC space */
+ val = readl(pmc_base + PMC_UTMIP_TERM_PAD_CFG);
+ val = PMC_TCTRL_VAL(utmip_tctrl_val) | PMC_RCTRL_VAL(utmip_rctrl_val);
+ writel(val, pmc_base + PMC_UTMIP_TERM_PAD_CFG);
+ clk_disable(phy->utmi_pad_clk);
+ init_done = true;
+}
+
+static void utmip_powerdown_pmc_wake_detect(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
+ unsigned int inst = phy->inst;
+
+ /* power down UTMIP interfaces */
+ val = readl(pmc_base + PMC_UTMIP_MASTER_CONFIG);
+ val |= UTMIP_PWR(inst);
+ writel(val, pmc_base + PMC_UTMIP_MASTER_CONFIG);
+
+ /* setup sleep walk usb controller */
+ val = UTMIP_USBOP_RPD_A | UTMIP_USBON_RPD_A | UTMIP_HIGHZ_A |
+ UTMIP_USBOP_RPD_B | UTMIP_USBON_RPD_B | UTMIP_HIGHZ_B |
+ UTMIP_USBOP_RPD_C | UTMIP_USBON_RPD_C | UTMIP_HIGHZ_C |
+ UTMIP_USBOP_RPD_D | UTMIP_USBON_RPD_D | UTMIP_HIGHZ_D;
+ writel(val, pmc_base + PMC_SLEEPWALK_REG(inst));
+
+ /* Program thermally encoded RCTRL_VAL, TCTRL_VAL into PMC space */
+ val = readl(pmc_base + PMC_UTMIP_TERM_PAD_CFG);
+ val = PMC_TCTRL_VAL(utmip_tctrl_val) | PMC_RCTRL_VAL(utmip_rctrl_val);
+ writel(val, pmc_base + PMC_UTMIP_TERM_PAD_CFG);
+
+ /* Turn over pad configuration to PMC */
+ val = readl(pmc_base + PMC_SLEEP_CFG);
+ val &= ~UTMIP_WAKE_VAL(inst, ~0);
+ val |= UTMIP_WAKE_VAL(inst, WAKE_VAL_NONE) |
+ UTMIP_RCTRL_USE_PMC(inst) | UTMIP_TCTRL_USE_PMC(inst) |
+ UTMIP_FSLS_USE_PMC(inst) | UTMIP_MASTER_ENABLE(inst);
+ writel(val, pmc_base + PMC_SLEEP_CFG);
+ PHY_DBG("%s ENABLE_PMC inst = %d\n", __func__, inst);
+}
+
+static void utmip_powerup_pmc_wake_detect(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
+ unsigned int inst = phy->inst;
+
+ /* Disable PMC master mode by clearing MASTER_EN */
+ val = readl(pmc_base + PMC_SLEEP_CFG);
+ val &= ~(UTMIP_RCTRL_USE_PMC(inst) | UTMIP_TCTRL_USE_PMC(inst) |
+ UTMIP_FSLS_USE_PMC(inst) | UTMIP_MASTER_ENABLE(inst));
+ writel(val, pmc_base + PMC_SLEEP_CFG);
+ mdelay(1);
+ PHY_DBG("%s DISABLE_PMC inst = %d\n", __func__, inst);
+}
+
+
+#ifdef KERNEL_WARNING
+static void usb_phy_power_down_pmc(void)
+{
+ unsigned long val;
+ void __iomem *pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
+
+ /* power down all 3 UTMIP interfaces */
+ val = readl(pmc_base + PMC_UTMIP_MASTER_CONFIG);
+ val |= UTMIP_PWR(0) | UTMIP_PWR(1) | UTMIP_PWR(2);
+ writel(val, pmc_base + PMC_UTMIP_MASTER_CONFIG);
+
+ /* turn on pad detectors */
+ writel(PMC_POWER_DOWN_MASK, pmc_base + PMC_USB_AO);
+
+ /* setup sleep walk fl all 3 usb controllers */
+ val = UTMIP_USBOP_RPD_A | UTMIP_USBON_RPD_A | UTMIP_HIGHZ_A |
+ UTMIP_USBOP_RPD_B | UTMIP_USBON_RPD_B | UTMIP_HIGHZ_B |
+ UTMIP_USBOP_RPD_C | UTMIP_USBON_RPD_C | UTMIP_HIGHZ_C |
+ UTMIP_USBOP_RPD_D | UTMIP_USBON_RPD_D | UTMIP_HIGHZ_D;
+ writel(val, pmc_base + PMC_SLEEPWALK_REG(0));
+ writel(val, pmc_base + PMC_SLEEPWALK_REG(1));
+ writel(val, pmc_base + PMC_SLEEPWALK_REG(2));
+
+ /* 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 &= ~UTMIP_WAKE_VAL(0, ~0);
+ val &= ~UTMIP_WAKE_VAL(1, ~0);
+ val &= ~UTMIP_WAKE_VAL(2, ~0);
+ val &= ~UHSIC_WAKE_VAL_P0(~0);
+ val |= UTMIP_WAKE_VAL(0, WAKE_VAL_NONE) | UHSIC_WAKE_VAL_P0(WAKE_VAL_NONE) |
+ UTMIP_WAKE_VAL(1, WAKE_VAL_NONE) | UTMIP_WAKE_VAL(2, WAKE_VAL_NONE) |
+ UTMIP_RCTRL_USE_PMC(0) | UTMIP_RCTRL_USE_PMC(1) | UTMIP_RCTRL_USE_PMC(2) |
+ UTMIP_TCTRL_USE_PMC(0) | UTMIP_TCTRL_USE_PMC(1) | UTMIP_TCTRL_USE_PMC(2) |
+ UTMIP_FSLS_USE_PMC(0) | UTMIP_FSLS_USE_PMC(1) | UTMIP_FSLS_USE_PMC(2) |
+ UTMIP_MASTER_ENABLE(0) | UTMIP_MASTER_ENABLE(1) | UTMIP_MASTER_ENABLE(2) |
+ UHSIC_MASTER_ENABLE_P0;
+ writel(val, pmc_base + PMC_SLEEP_CFG);
+}
+#endif
+
+static int usb_phy_bringup_host_controller(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ PHY_DBG("[%d] USB_USBSTS[0x%x] USB_PORTSC[0x%x] port_speed[%d]\n", __LINE__,
+ readl(base + USB_USBSTS), readl(base + USB_PORTSC),
+ phy->port_speed);
+
+ /* Device is plugged in when system is in LP0 */
+ /* Bring up the controller from LP0*/
+ val = readl(base + USB_USBCMD);
+ val |= USB_CMD_RESET;
+ writel(val, base + USB_USBCMD);
+
+ if (usb_phy_reg_status_wait(base + USB_USBCMD,
+ USB_CMD_RESET, 0, 2500) < 0) {
+ pr_err("%s: timeout waiting for reset\n", __func__);
+ }
+
+ val = readl(base + USB_USBMODE);
+ val &= ~USB_USBMODE_MASK;
+ val |= USB_USBMODE_HOST;
+ writel(val, base + USB_USBMODE);
+ val = readl(base + HOSTPC1_DEVLC);
+ val &= ~HOSTPC1_DEVLC_PTS(~0);
+
+ if (phy->pdata->phy_intf == TEGRA_USB_PHY_INTF_HSIC)
+ val |= HOSTPC1_DEVLC_PTS(HOSTPC1_DEVLC_PTS_HSIC);
+ else
+ val |= HOSTPC1_DEVLC_STS;
+ writel(val, base + HOSTPC1_DEVLC);
+
+ /* Enable Port Power */
+ val = readl(base + USB_PORTSC);
+ val |= USB_PORTSC_PP;
+ writel(val, base + USB_PORTSC);
+ udelay(10);
+
+ /* Check if the phy resume from LP0. When the phy resume from LP0
+ * USB register will be reset.to zero */
+ if (!readl(base + USB_ASYNCLISTADDR)) {
+ /* 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)
+ val |= USB_PORTSC_PTC(5);
+ else if (phy->port_speed == USB_PHY_PORT_SPEED_FULL)
+ val |= USB_PORTSC_PTC(6);
+ else if (phy->port_speed == USB_PHY_PORT_SPEED_LOW)
+ val |= USB_PORTSC_PTC(7);
+ writel(val, base + USB_PORTSC);
+ udelay(10);
+
+ /* Disable test mode by setting PTC field to NORMAL_OP */
+ val = readl(base + USB_PORTSC);
+ val &= ~USB_PORTSC_PTC(~0);
+ writel(val, base + USB_PORTSC);
+ udelay(10);
+ }
+
+ /* Poll until CCS is enabled */
+ if (usb_phy_reg_status_wait(base + USB_PORTSC, USB_PORTSC_CCS,
+ USB_PORTSC_CCS, 2000)) {
+ pr_err("%s: timeout waiting for USB_PORTSC_CCS\n", __func__);
+ }
+
+ /* Poll until PE is enabled */
+ if (usb_phy_reg_status_wait(base + USB_PORTSC, USB_PORTSC_PE,
+ USB_PORTSC_PE, 2000)) {
+ pr_err("%s: timeout waiting for USB_PORTSC_PE\n", __func__);
+ }
+
+ /* Clear the PCI status, to avoid an interrupt taken upon resume */
+ val = readl(base + USB_USBSTS);
+ val |= USB_USBSTS_PCI;
+ writel(val, base + USB_USBSTS);
+
+ if (!phy->remote_wakeup) {
+ /* Put controller in suspend mode by writing 1 to SUSP bit of PORTSC */
+ val = readl(base + USB_PORTSC);
+ if ((val & USB_PORTSC_PP) && (val & USB_PORTSC_PE)) {
+ val |= USB_PORTSC_SUSP;
+ writel(val, base + USB_PORTSC);
+ /* Need a 4ms delay before the controller goes to suspend */
+ mdelay(4);
+
+ /* Wait until port suspend completes */
+ if (usb_phy_reg_status_wait(base + USB_PORTSC, USB_PORTSC_SUSP,
+ USB_PORTSC_SUSP, 1000)) {
+ pr_err("%s: timeout waiting for PORT_SUSPEND\n",
+ __func__);
+ }
+ }
+ }
+ PHY_DBG("[%d] USB_USBSTS[0x%x] USB_PORTSC[0x%x] port_speed[%d]\n", __LINE__,
+ readl(base + USB_USBSTS), readl(base + USB_PORTSC),
+ phy->port_speed);
+
+ DBG("USB_USBSTS[0x%x] USB_PORTSC[0x%x]\n",
+ readl(base + USB_USBSTS), readl(base + USB_PORTSC));
+ return 0;
+}
+
+static void usb_phy_wait_for_sof(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+
+ val = readl(base + USB_USBSTS);
+ writel(val, base + USB_USBSTS);
+ udelay(20);
+ /* wait for two SOFs */
+ if (usb_phy_reg_status_wait(base + USB_USBSTS, USB_USBSTS_SRI,
+ USB_USBSTS_SRI, 2500))
+ pr_err("%s: timeout waiting for SOF\n", __func__);
+
+ val = readl(base + USB_USBSTS);
+ writel(val, base + USB_USBSTS);
+ if (usb_phy_reg_status_wait(base + USB_USBSTS, USB_USBSTS_SRI, 0, 2500))
+ pr_err("%s: timeout waiting for SOF\n", __func__);
+
+ if (usb_phy_reg_status_wait(base + USB_USBSTS, USB_USBSTS_SRI,
+ USB_USBSTS_SRI, 2500))
+ pr_err("%s: timeout waiting for SOF\n", __func__);
+
+ udelay(20);
+}
+
+static unsigned int utmi_phy_xcvr_setup_value(struct tegra_usb_phy *phy)
+{
+ struct tegra_utmi_config *cfg = &phy->pdata->u_cfg.utmi;
+ signed long val;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+
+ if (cfg->xcvr_use_fuses) {
+ val = XCVR_SETUP(tegra_fuse_readl(FUSE_USB_CALIB_0));
+ if (cfg->xcvr_use_lsb) {
+ val = min((unsigned int) ((val & XCVR_SETUP_LSB_MASK)
+ + cfg->xcvr_setup_offset),
+ (unsigned int) XCVR_SETUP_LSB_MAX_VAL);
+ val |= (cfg->xcvr_setup & XCVR_SETUP_MSB_MASK);
+ } else {
+ if (cfg->xcvr_setup_offset <= UTMIP_XCVR_MAX_OFFSET)
+ val = val + cfg->xcvr_setup_offset;
+
+ if (val > UTMIP_XCVR_SETUP_MAX_VALUE) {
+ val = UTMIP_XCVR_SETUP_MAX_VALUE;
+ pr_info("%s: reset XCVR_SETUP to max value\n",
+ __func__);
+ } else if (val < UTMIP_XCVR_SETUP_MIN_VALUE) {
+ val = UTMIP_XCVR_SETUP_MIN_VALUE;
+ pr_info("%s: reset XCVR_SETUP to min value\n",
+ __func__);
+ }
+ }
+ } else {
+ val = cfg->xcvr_setup;
+ }
+
+ return (unsigned int) val;
+}
+
+static int utmi_phy_open(struct tegra_usb_phy *phy)
+{
+ void __iomem *pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
+ unsigned long parent_rate, val;
+ int i;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+
+ phy->utmi_pad_clk = clk_get_sys("utmip-pad", NULL);
+ if (IS_ERR(phy->utmi_pad_clk)) {
+ pr_err("%s: can't get utmip pad clock\n", __func__);
+ return PTR_ERR(phy->utmi_pad_clk);
+ }
+
+ phy->utmi_xcvr_setup = utmi_phy_xcvr_setup_value(phy);
+
+ parent_rate = clk_get_rate(clk_get_parent(phy->pllu_clk));
+ for (i = 0; i < ARRAY_SIZE(utmip_freq_table); i++) {
+ if (utmip_freq_table[i].freq == parent_rate) {
+ phy->freq = &utmip_freq_table[i];
+ break;
+ }
+ }
+ if (!phy->freq) {
+ pr_err("invalid pll_u parent rate %ld\n", parent_rate);
+ return -EINVAL;
+ }
+
+ /* Power-up the VBUS detector for UTMIP PHY */
+ val = readl(pmc_base + PMC_USB_AO);
+ val &= ~(PMC_USB_AO_VBUS_WAKEUP_PD_P0 | PMC_USB_AO_ID_PD_P0);
+ writel((val | PMC_USB_AO_PD_P2), (pmc_base + PMC_USB_AO));
+
+ utmip_powerup_pmc_wake_detect(phy);
+
+ return 0;
+}
+
+static void utmi_phy_close(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+
+ DBG("%s inst:[%d]\n", __func__, phy->inst);
+
+ /* Disable PHY clock valid interrupts while going into suspend*/
+ if (phy->pdata->u_data.host.hot_plug) {
+ val = readl(base + USB_SUSP_CTRL);
+ val &= ~USB_PHY_CLK_VALID_INT_ENB;
+ writel(val, base + USB_SUSP_CTRL);
+ }
+
+ clk_put(phy->utmi_pad_clk);
+}
+
+static int utmi_phy_pad_power_on(struct tegra_usb_phy *phy)
+{
+ unsigned long val, flags;
+ void __iomem *pad_base = IO_ADDRESS(TEGRA_USB_BASE);
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+
+ clk_enable(phy->utmi_pad_clk);
+
+ spin_lock_irqsave(&utmip_pad_lock, flags);
+ utmip_pad_count++;
+
+ val = readl(pad_base + UTMIP_BIAS_CFG0);
+ val &= ~(UTMIP_OTGPD | UTMIP_BIASPD);
+ val |= UTMIP_HSSQUELCH_LEVEL(0x2) | UTMIP_HSDISCON_LEVEL(0x1) |
+ UTMIP_HSDISCON_LEVEL_MSB;
+ writel(val, pad_base + UTMIP_BIAS_CFG0);
+
+ spin_unlock_irqrestore(&utmip_pad_lock, flags);
+
+ clk_disable(phy->utmi_pad_clk);
+
+ return 0;
+}
+
+static int utmi_phy_pad_power_off(struct tegra_usb_phy *phy)
+{
+ unsigned long val, flags;
+ void __iomem *pad_base = IO_ADDRESS(TEGRA_USB_BASE);
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+
+ clk_enable(phy->utmi_pad_clk);
+ spin_lock_irqsave(&utmip_pad_lock, flags);
+
+ if (!utmip_pad_count) {
+ pr_err("%s: utmip pad already powered off\n", __func__);
+ goto out;
+ }
+ if (--utmip_pad_count == 0) {
+ val = readl(pad_base + UTMIP_BIAS_CFG0);
+ val |= UTMIP_OTGPD | UTMIP_BIASPD;
+ val &= ~(UTMIP_HSSQUELCH_LEVEL(~0) | UTMIP_HSDISCON_LEVEL(~0) |
+ UTMIP_HSDISCON_LEVEL_MSB);
+ writel(val, pad_base + UTMIP_BIAS_CFG0);
+ }
+out:
+ spin_unlock_irqrestore(&utmip_pad_lock, flags);
+ clk_disable(phy->utmi_pad_clk);
+
+ return 0;
+}
+
+static int utmi_phy_irq(struct tegra_usb_phy *phy)
+{
+ void __iomem *base = phy->regs;
+ unsigned long val = 0;
+
+ 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));
+ DBG("USB_USBMODE[0x%x] USB_USBCMD[0x%x]\n",
+ 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))
+ pr_info("%s: utmip remote wake detected\n", __func__);
+
+ if (phy->pdata->u_data.host.hot_plug) {
+ val = readl(base + USB_SUSP_CTRL);
+ if ((val & USB_PHY_CLK_VALID_INT_STS)) {
+ 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));
+ } else if (!phy->phy_clk_on) {
+ return IRQ_NONE;
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+static void utmi_phy_enable_obs_bus(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+
+ /* (2LS WAR)is not required for LS and FS devices and is only for HS */
+ if ((phy->port_speed == USB_PHY_PORT_SPEED_LOW) ||
+ (phy->port_speed == USB_PHY_PORT_SPEED_FULL)) {
+ /* do not enable the OBS bus */
+ val = readl(base + UTMIP_MISC_CFG0);
+ val &= ~(UTMIP_DPDM_OBSERVE_SEL(~0));
+ writel(val, base + UTMIP_MISC_CFG0);
+ DBG("%s(%d) Disable OBS bus\n", __func__, __LINE__);
+ return;
+ }
+ /* Force DP/DM pulldown active for Host mode */
+ val = readl(base + UTMIP_MISC_CFG0);
+ val |= FORCE_PULLDN_DM | FORCE_PULLDN_DP |
+ COMB_TERMS | ALWAYS_FREE_RUNNING_TERMS;
+ writel(val, base + UTMIP_MISC_CFG0);
+ val = readl(base + UTMIP_MISC_CFG0);
+ val &= ~UTMIP_DPDM_OBSERVE_SEL(~0);
+ if (phy->port_speed == USB_PHY_PORT_SPEED_LOW)
+ val |= UTMIP_DPDM_OBSERVE_SEL_FS_J;
+ else
+ val |= UTMIP_DPDM_OBSERVE_SEL_FS_K;
+ writel(val, base + UTMIP_MISC_CFG0);
+ udelay(1);
+
+ val = readl(base + UTMIP_MISC_CFG0);
+ val |= UTMIP_DPDM_OBSERVE;
+ writel(val, base + UTMIP_MISC_CFG0);
+ udelay(10);
+ DBG("%s(%d) Enable OBS bus\n", __func__, __LINE__);
+ PHY_DBG("ENABLE_OBS_BUS\n");
+}
+
+static int utmi_phy_disable_obs_bus(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+ unsigned long flags;
+
+ /* check if OBS bus is already enabled */
+ val = readl(base + UTMIP_MISC_CFG0);
+ if (val & UTMIP_DPDM_OBSERVE) {
+ PHY_DBG("DISABLE_OBS_BUS\n");
+
+ /* disable ALL interrupts on current CPU */
+ local_irq_save(flags);
+
+ /* Change the UTMIP OBS bus to drive SE0 */
+ val = readl(base + UTMIP_MISC_CFG0);
+ val &= ~UTMIP_DPDM_OBSERVE_SEL(~0);
+ val |= UTMIP_DPDM_OBSERVE_SEL_FS_SE0;
+ writel(val, base + UTMIP_MISC_CFG0);
+
+ /* Wait for 3us(2 LS bit times) */
+ udelay(3);
+
+ /* Release UTMIP OBS bus */
+ val = readl(base + UTMIP_MISC_CFG0);
+ val &= ~UTMIP_DPDM_OBSERVE;
+ writel(val, base + UTMIP_MISC_CFG0);
+
+ /* Release DP/DM pulldown for Host mode */
+ val = readl(base + UTMIP_MISC_CFG0);
+ val &= ~(FORCE_PULLDN_DM | FORCE_PULLDN_DP |
+ COMB_TERMS | ALWAYS_FREE_RUNNING_TERMS);
+ writel(val, base + UTMIP_MISC_CFG0);
+
+ val = readl(base + USB_USBCMD);
+ val |= USB_USBCMD_RS;
+ writel(val, base + USB_USBCMD);
+
+ /* restore ALL interrupts on current CPU */
+ local_irq_restore(flags);
+
+ if (usb_phy_reg_status_wait(base + USB_USBCMD, USB_USBCMD_RS,
+ USB_USBCMD_RS, 2000)) {
+ pr_err("%s: timeout waiting for USB_USBCMD_RS\n", __func__);
+ return -ETIMEDOUT;
+ }
+ }
+ return 0;
+}
+
+static int utmi_phy_post_resume(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
+ unsigned int inst = phy->inst;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ val = readl(pmc_base + PMC_SLEEP_CFG);
+ /* if PMC is not disabled by now then disable it */
+ if (val & UTMIP_MASTER_ENABLE(inst)) {
+ utmip_phy_disable_pmc_bus_ctrl(phy);
+ }
+
+ utmi_phy_disable_obs_bus(phy);
+
+ return 0;
+}
+
+static int utmi_phy_pre_resume(struct tegra_usb_phy *phy, bool remote_wakeup)
+{
+ unsigned long val;
+ void __iomem *pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
+ void __iomem *base = phy->regs;
+ unsigned int inst = phy->inst;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ phy->port_speed = (readl(base + HOSTPC1_DEVLC) >> 25) &
+ HOSTPC1_DEVLC_PSPD_MASK;
+
+ if (phy->port_speed == USB_PHY_PORT_SPEED_HIGH) {
+ /* Disable interrupts */
+ writel(0, base + USB_USBINTR);
+ /* Clear the run bit to stop SOFs - 2LS WAR */
+ val = readl(base + USB_USBCMD);
+ val &= ~USB_USBCMD_RS;
+ writel(val, base + USB_USBCMD);
+ if (usb_phy_reg_status_wait(base + USB_USBSTS, USB_USBSTS_HCH,
+ USB_USBSTS_HCH, 2000)) {
+ pr_err("%s: timeout waiting for USB_USBSTS_HCH\n", __func__);
+ }
+ }
+
+ val = readl(pmc_base + PMC_SLEEP_CFG);
+ if (val & UTMIP_MASTER_ENABLE(inst)) {
+ if (!remote_wakeup)
+ utmip_phy_disable_pmc_bus_ctrl(phy);
+ } else {
+ utmi_phy_enable_obs_bus(phy);
+ }
+
+ return 0;
+}
+
+static int utmi_phy_power_off(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+
+ PHY_DBG("%s(%d) inst:[%d] BEGIN\n", __func__, __LINE__, phy->inst);
+ if (!phy->phy_clk_on) {
+ PHY_DBG("%s(%d) inst:[%d] phy clk is already off\n",
+ __func__, __LINE__, phy->inst);
+ return 0;
+ }
+
+ if (phy->pdata->op_mode == TEGRA_USB_OPMODE_DEVICE) {
+ utmip_powerdown_pmc_wake_detect(phy);
+
+ val = readl(base + USB_SUSP_CTRL);
+ val &= ~USB_WAKEUP_DEBOUNCE_COUNT(~0);
+ val |= USB_WAKE_ON_CNNT_EN_DEV | USB_WAKEUP_DEBOUNCE_COUNT(5);
+ writel(val, base + USB_SUSP_CTRL);
+
+ val = readl(base + UTMIP_BAT_CHRG_CFG0);
+ val |= UTMIP_PD_CHRG;
+ writel(val, base + UTMIP_BAT_CHRG_CFG0);
+ } else {
+ phy->port_speed = (readl(base + HOSTPC1_DEVLC) >> 25) &
+ HOSTPC1_DEVLC_PSPD_MASK;
+
+ /* Disable interrupts */
+ writel(0, base + USB_USBINTR);
+
+ /* Clear the run bit to stop SOFs - 2LS WAR */
+ val = readl(base + USB_USBCMD);
+ val &= ~USB_USBCMD_RS;
+ writel(val, base + USB_USBCMD);
+
+ if (usb_phy_reg_status_wait(base + USB_USBSTS, USB_USBSTS_HCH,
+ USB_USBSTS_HCH, 2000)) {
+ pr_err("%s: timeout waiting for USB_USBSTS_HCH\n", __func__);
+ }
+ utmip_setup_pmc_wake_detect(phy);
+ }
+
+ if (!phy->pdata->u_data.host.hot_plug) {
+ val = readl(base + UTMIP_XCVR_CFG0);
+ val |= (UTMIP_FORCE_PD_POWERDOWN | UTMIP_FORCE_PD2_POWERDOWN |
+ UTMIP_FORCE_PDZI_POWERDOWN);
+ writel(val, base + UTMIP_XCVR_CFG0);
+ }
+
+ val = readl(base + UTMIP_XCVR_CFG1);
+ val |= UTMIP_FORCE_PDDISC_POWERDOWN | UTMIP_FORCE_PDCHRP_POWERDOWN |
+ UTMIP_FORCE_PDDR_POWERDOWN;
+ writel(val, base + UTMIP_XCVR_CFG1);
+
+ val = readl(base + UTMIP_BIAS_CFG1);
+ val |= UTMIP_BIAS_PDTRK_COUNT(0x5);
+ writel(val, base + UTMIP_BIAS_CFG1);
+
+ utmi_phy_pad_power_off(phy);
+
+ if (phy->pdata->u_data.host.hot_plug) {
+ bool enable_hotplug = true;
+ /* if it is OTG port then make sure to enable hot-plug feature
+ only if host adaptor is connected, i.e id is low */
+ if (phy->pdata->port_otg) {
+ val = readl(base + USB_PHY_VBUS_WAKEUP_ID);
+ enable_hotplug = (val & USB_ID_STATUS) ? false : true;
+ }
+ if (enable_hotplug) {
+ val = readl(base + USB_PORTSC);
+ 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*/
+ val = readl(base + USB_SUSP_CTRL);
+ val &= ~USB_PHY_CLK_VALID_INT_ENB;
+ writel(val, base + USB_SUSP_CTRL);
+ }
+ }
+
+ val = readl(base + HOSTPC1_DEVLC);
+ val |= HOSTPC1_DEVLC_PHCD;
+ writel(val, base + HOSTPC1_DEVLC);
+
+ if (!phy->pdata->u_data.host.hot_plug) {
+ val = readl(base + USB_SUSP_CTRL);
+ val |= UTMIP_RESET;
+ writel(val, base + USB_SUSP_CTRL);
+ }
+
+ phy->phy_clk_on = false;
+ phy->hw_accessible = false;
+
+ PHY_DBG("%s(%d) inst:[%d] END\n", __func__, __LINE__, phy->inst);
+
+ return 0;
+}
+
+
+static int utmi_phy_power_on(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+ struct tegra_utmi_config *config = &phy->pdata->u_cfg.utmi;
+
+ PHY_DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ if (phy->phy_clk_on) {
+ PHY_DBG("%s(%d) inst:[%d] phy clk is already On\n",
+ __func__, __LINE__, phy->inst);
+ return 0;
+ }
+ val = readl(base + USB_SUSP_CTRL);
+ val |= UTMIP_RESET;
+ writel(val, base + USB_SUSP_CTRL);
+
+ val = readl(base + UTMIP_TX_CFG0);
+ val |= UTMIP_FS_PREABMLE_J;
+ writel(val, base + UTMIP_TX_CFG0);
+
+ val = readl(base + UTMIP_HSRX_CFG0);
+ val &= ~(UTMIP_IDLE_WAIT(~0) | UTMIP_ELASTIC_LIMIT(~0));
+ val |= UTMIP_IDLE_WAIT(config->idle_wait_delay);
+ val |= UTMIP_ELASTIC_LIMIT(config->elastic_limit);
+ writel(val, base + UTMIP_HSRX_CFG0);
+
+ val = readl(base + UTMIP_HSRX_CFG1);
+ val &= ~UTMIP_HS_SYNC_START_DLY(~0);
+ val |= UTMIP_HS_SYNC_START_DLY(config->hssync_start_delay);
+ writel(val, base + UTMIP_HSRX_CFG1);
+
+ val = readl(base + UTMIP_DEBOUNCE_CFG0);
+ val &= ~UTMIP_BIAS_DEBOUNCE_A(~0);
+ val |= UTMIP_BIAS_DEBOUNCE_A(phy->freq->debounce);
+ writel(val, base + UTMIP_DEBOUNCE_CFG0);
+
+ val = readl(base + UTMIP_MISC_CFG0);
+ val &= ~UTMIP_SUSPEND_EXIT_ON_EDGE;
+ writel(val, base + UTMIP_MISC_CFG0);
+
+ if (phy->pdata->op_mode == TEGRA_USB_OPMODE_DEVICE) {
+ val = readl(base + USB_SUSP_CTRL);
+ val &= ~(USB_WAKE_ON_CNNT_EN_DEV | USB_WAKE_ON_DISCON_EN_DEV);
+ writel(val, base + USB_SUSP_CTRL);
+
+ val = readl(base + UTMIP_BAT_CHRG_CFG0);
+ val &= ~UTMIP_PD_CHRG;
+ writel(val, base + UTMIP_BAT_CHRG_CFG0);
+ } else {
+ val = readl(base + UTMIP_BAT_CHRG_CFG0);
+ val |= UTMIP_PD_CHRG;
+ writel(val, base + UTMIP_BAT_CHRG_CFG0);
+ }
+
+ utmi_phy_pad_power_on(phy);
+
+ val = readl(base + UTMIP_XCVR_CFG0);
+ val &= ~(UTMIP_XCVR_LSBIAS_SEL | UTMIP_FORCE_PD_POWERDOWN |
+ UTMIP_FORCE_PD2_POWERDOWN | UTMIP_FORCE_PDZI_POWERDOWN |
+ UTMIP_XCVR_SETUP(~0) | UTMIP_XCVR_LSFSLEW(~0) |
+ UTMIP_XCVR_LSRSLEW(~0) | UTMIP_XCVR_HSSLEW_MSB(~0));
+ val |= UTMIP_XCVR_SETUP(phy->utmi_xcvr_setup);
+ val |= UTMIP_XCVR_SETUP_MSB(XCVR_SETUP_MSB_CALIB(phy->utmi_xcvr_setup));
+ val |= UTMIP_XCVR_LSFSLEW(config->xcvr_lsfslew);
+ val |= UTMIP_XCVR_LSRSLEW(config->xcvr_lsrslew);
+ if (!config->xcvr_use_lsb)
+ val |= UTMIP_XCVR_HSSLEW_MSB(0x8);
+ writel(val, base + UTMIP_XCVR_CFG0);
+
+ val = readl(base + UTMIP_XCVR_CFG1);
+ val &= ~(UTMIP_FORCE_PDDISC_POWERDOWN | UTMIP_FORCE_PDCHRP_POWERDOWN |
+ UTMIP_FORCE_PDDR_POWERDOWN | UTMIP_XCVR_TERM_RANGE_ADJ(~0));
+ val |= UTMIP_XCVR_TERM_RANGE_ADJ(config->term_range_adj);
+ writel(val, base + UTMIP_XCVR_CFG1);
+
+ val = readl(base + UTMIP_BIAS_CFG1);
+ val &= ~UTMIP_BIAS_PDTRK_COUNT(~0);
+ val |= UTMIP_BIAS_PDTRK_COUNT(phy->freq->pdtrk_count);
+ writel(val, base + UTMIP_BIAS_CFG1);
+
+ val = readl(base + UTMIP_SPARE_CFG0);
+ val &= ~FUSE_SETUP_SEL;
+ val |= FUSE_ATERM_SEL;
+ writel(val, base + UTMIP_SPARE_CFG0);
+
+ val = readl(base + USB_SUSP_CTRL);
+ val |= UTMIP_PHY_ENABLE;
+ writel(val, base + USB_SUSP_CTRL);
+
+ val = readl(base + USB_SUSP_CTRL);
+ val &= ~UTMIP_RESET;
+ writel(val, base + USB_SUSP_CTRL);
+
+ val = readl(base + HOSTPC1_DEVLC);
+ val &= ~HOSTPC1_DEVLC_PHCD;
+ writel(val, base + HOSTPC1_DEVLC);
+
+ if (usb_phy_reg_status_wait(base + USB_SUSP_CTRL,
+ USB_PHY_CLK_VALID, USB_PHY_CLK_VALID, 2500))
+ pr_warn("%s: timeout waiting for phy to stabilize\n", __func__);
+
+ utmi_phy_enable_trking_data(phy);
+
+ if (phy->inst == 2)
+ writel(0, base + ICUSB_CTRL);
+
+ val = readl(base + USB_USBMODE);
+ val &= ~USB_USBMODE_MASK;
+ if (phy->pdata->op_mode == TEGRA_USB_OPMODE_HOST)
+ val |= USB_USBMODE_HOST;
+ else
+ val |= USB_USBMODE_DEVICE;
+ writel(val, base + USB_USBMODE);
+
+ val = readl(base + HOSTPC1_DEVLC);
+ val &= ~HOSTPC1_DEVLC_PTS(~0);
+ val |= HOSTPC1_DEVLC_STS;
+ writel(val, base + HOSTPC1_DEVLC);
+
+ if (phy->pdata->op_mode == TEGRA_USB_OPMODE_DEVICE)
+ utmip_powerup_pmc_wake_detect(phy);
+ phy->phy_clk_on = true;
+ phy->hw_accessible = true;
+ PHY_DBG("%s(%d) End inst:[%d]\n", __func__, __LINE__, phy->inst);
+ return 0;
+}
+
+static void utmi_phy_restore_start(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
+ int inst = phy->inst;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ val = readl(pmc_base + UTMIP_UHSIC_STATUS);
+ /* Check whether we wake up from the remote resume.
+ For lp1 case, pmc is not responsible for waking the
+ system, it's the flow controller and hence
+ UTMIP_WALK_PTR_VAL(inst) will return 0.
+ Also, for lp1 case phy->remote_wakeup will already be set
+ to true by utmi_phy_irq() when the remote wakeup happens.
+ Hence change the logic in the else part to enter only
+ if phy->remote_wakeup is not set to true by the
+ utmi_phy_irq(). */
+ 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);
+ }
+ }
+ utmi_phy_enable_obs_bus(phy);
+}
+
+static void utmi_phy_restore_end(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+ int wait_time_us = 25000; /* FPR should be set by this time */
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ /* check whether we wake up from the remote resume */
+ if (phy->remote_wakeup) {
+ /* wait until SUSPEND and RESUME bit is cleared on remote resume */
+ do {
+ 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);
+ utmip_phy_disable_pmc_bus_ctrl(phy);
+ utmi_phy_post_resume(phy);
+ return;
+ }
+ wait_time_us--;
+ } while (val & (USB_PORTSC_RESUME | USB_PORTSC_SUSP));
+
+ /* wait for 25 ms to port resume complete */
+ msleep(25);
+ /* disable PMC master control */
+ utmip_phy_disable_pmc_bus_ctrl(phy);
+
+ /* Clear PCI and SRI bits to avoid an interrupt upon resume */
+ val = readl(base + USB_USBSTS);
+ writel(val, base + USB_USBSTS);
+ /* wait to avoid SOF if there is any */
+ if (usb_phy_reg_status_wait(base + USB_USBSTS,
+ USB_USBSTS_SRI, USB_USBSTS_SRI, 2500) < 0) {
+ pr_err("%s: timeout waiting for SOF\n", __func__);
+ }
+ utmi_phy_post_resume(phy);
+ }
+}
+
+static int utmi_phy_resume(struct tegra_usb_phy *phy)
+{
+ int status = 0;
+ unsigned long val;
+ void __iomem *base = phy->regs;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ if (phy->pdata->op_mode == TEGRA_USB_OPMODE_HOST) {
+ if (phy->port_speed < USB_PHY_PORT_SPEED_UNKNOWN) {
+ utmi_phy_restore_start(phy);
+ usb_phy_bringup_host_controller(phy);
+ utmi_phy_restore_end(phy);
+ } else {
+ /* device is plugged in when system is in LP0 */
+ /* bring up the controller from LP0*/
+ val = readl(base + USB_USBCMD);
+ val |= USB_CMD_RESET;
+ writel(val, base + USB_USBCMD);
+
+ if (usb_phy_reg_status_wait(base + USB_USBCMD,
+ USB_CMD_RESET, 0, 2500) < 0) {
+ pr_err("%s: timeout waiting for reset\n", __func__);
+ }
+
+ val = readl(base + USB_USBMODE);
+ val &= ~USB_USBMODE_MASK;
+ val |= USB_USBMODE_HOST;
+ writel(val, base + USB_USBMODE);
+
+ val = readl(base + HOSTPC1_DEVLC);
+ val &= ~HOSTPC1_DEVLC_PTS(~0);
+ val |= HOSTPC1_DEVLC_STS;
+ writel(val, base + HOSTPC1_DEVLC);
+
+ writel(USB_USBCMD_RS, base + USB_USBCMD);
+
+ 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__);
+ }
+
+ /* Enable Port Power */
+ val = readl(base + USB_PORTSC);
+ val |= USB_PORTSC_PP;
+ writel(val, base + USB_PORTSC);
+ udelay(10);
+
+ DBG("USB_USBSTS[0x%x] USB_PORTSC[0x%x]\n",
+ readl(base + USB_USBSTS), readl(base + USB_PORTSC));
+ }
+ }
+
+ return status;
+}
+
+bool utmi_phy_charger_detect(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+ bool status;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ if (phy->pdata->op_mode != TEGRA_USB_OPMODE_DEVICE) {
+ /* Charger detection is not there for ULPI
+ * return Charger not available */
+ return false;
+ }
+
+ /* Enable charger detection logic */
+ val = readl(base + UTMIP_BAT_CHRG_CFG0);
+ val |= UTMIP_OP_SRC_EN | UTMIP_ON_SINK_EN;
+ writel(val, base + UTMIP_BAT_CHRG_CFG0);
+
+ /* Source should be on for 100 ms as per USB charging spec */
+ msleep(TDP_SRC_ON_MS);
+
+ val = readl(base + USB_PHY_VBUS_WAKEUP_ID);
+ /* If charger is not connected disable the interrupt */
+ val &= ~VDAT_DET_INT_EN;
+ val |= VDAT_DET_CHG_DET;
+ writel(val, base + USB_PHY_VBUS_WAKEUP_ID);
+
+ val = readl(base + USB_PHY_VBUS_WAKEUP_ID);
+ if (val & VDAT_DET_STS)
+ status = true;
+ else
+ status = false;
+
+ /* Disable charger detection logic */
+ val = readl(base + UTMIP_BAT_CHRG_CFG0);
+ val &= ~(UTMIP_OP_SRC_EN | UTMIP_ON_SINK_EN);
+ writel(val, base + UTMIP_BAT_CHRG_CFG0);
+
+ /* Delay of 40 ms before we pull the D+ as per battery charger spec */
+ msleep(TDPSRC_CON_MS);
+
+ return status;
+}
+
+static void uhsic_powerup_pmc_wake_detect(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
+
+ /* turn on 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);
+
+ /* Disable PMC master mode by clearing MASTER_EN */
+ val = readl(pmc_base + PMC_SLEEP_CFG);
+ val &= ~(UHSIC_MASTER_ENABLE_P0);
+ writel(val, pmc_base + PMC_SLEEP_CFG);
+ mdelay(1);
+}
+
+static void uhsic_setup_pmc_wake_detect(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
+ void __iomem *base = phy->regs;
+ bool port_connected;
+
+ DBG("%s:%d\n", __func__, __LINE__);
+
+ /* check for port connect status */
+ val = readl(base + USB_PORTSC);
+ port_connected = val & USB_PORTSC_CCS;
+
+ if (!port_connected)
+ return;
+
+ /*Set PMC MASTER bits to do the following
+ * a. Take over the hsic drivers
+ * b. set up such that it will take over resume
+ * if remote wakeup is detected
+ * Prepare PMC to take over suspend-wake detect-drive resume until USB
+ * controller ready
+ */
+
+ /* disable master enable in PMC */
+ val = readl(pmc_base + PMC_SLEEP_CFG);
+ val &= ~UHSIC_MASTER_ENABLE_P0;
+ writel(val, pmc_base + PMC_SLEEP_CFG);
+
+ /* UTMIP_PWR_PX=1 for power savings mode */
+ val = readl(pmc_base + PMC_UTMIP_MASTER_CONFIG);
+ val |= UHSIC_PWR;
+ writel(val, pmc_base + PMC_UTMIP_MASTER_CONFIG);
+
+
+ /* Enable which type of event can trigger a walk,
+ * in this case usb_line_wake */
+ val = readl(pmc_base + PMC_SLEEPWALK_CFG);
+ val |= UHSIC_LINEVAL_WALK_EN;
+ writel(val, pmc_base + PMC_SLEEPWALK_CFG);
+
+ /* program walk sequence, maintain a J, followed by a driven K
+ * to signal a resume once an wake event is detected */
+
+ val = readl(pmc_base + PMC_SLEEPWALK_UHSIC);
+
+ val &= ~UHSIC_DATA_RPU_A;
+ 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;
+ val &= ~UHSIC_STROBE_RPU_D;
+ 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*/
+ val = readl(pmc_base + PMC_SLEEP_CFG);
+ val &= ~UHSIC_WAKE_VAL(~0);
+ val |= UHSIC_WAKE_VAL(WAKE_VAL_SD10);
+ val |= UHSIC_MASTER_ENABLE;
+ writel(val, pmc_base + PMC_SLEEP_CFG);
+
+ val = readl(base + UHSIC_PMC_WAKEUP0);
+ val |= EVENT_INT_ENB;
+ writel(val, base + UHSIC_PMC_WAKEUP0);
+
+ DBG("%s:PMC enabled for HSIC remote wakeup\n", __func__);
+}
+
+static void uhsic_phy_disable_pmc_bus_ctrl(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
+ void __iomem *base = phy->regs;
+
+ DBG("%s (%d)\n", __func__, __LINE__);
+ val = readl(pmc_base + PMC_SLEEP_CFG);
+ val &= ~UHSIC_WAKE_VAL(0x0);
+ 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);
+
+ /* Disable PMC master mode by clearing MASTER_EN */
+ val = readl(pmc_base + PMC_SLEEP_CFG);
+ val &= ~(UHSIC_MASTER_ENABLE);
+ writel(val, pmc_base + PMC_SLEEP_CFG);
+
+ /* turn off 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);
+
+ phy->remote_wakeup = false;
+}
+
+static bool uhsic_phy_remotewake_detected(struct tegra_usb_phy *phy)
+{
+ void __iomem *pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
+ void __iomem *base = phy->regs;
+ u32 val;
+
+ val = readl(base + UHSIC_PMC_WAKEUP0);
+ if (val & EVENT_INT_ENB) {
+ 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_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);
+ phy->remote_wakeup = true;
+ DBG("%s:PMC remote wakeup detected for HSIC\n", __func__);
+ return true;
+ }
+ }
+ return false;
+}
+
+static int uhsic_phy_pre_resume(struct tegra_usb_phy *phy, bool remote_wakeup)
+{
+ DBG("%s(%d)\n", __func__, __LINE__);
+
+ if (!remote_wakeup)
+ usb_phy_wait_for_sof(phy);
+
+ return 0;
+}
+
+static int uhsic_phy_post_resume(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ 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);
+ }
+
+ return 0;
+}
+
+static void uhsic_phy_restore_start(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
+ void __iomem *base = phy->regs;
+
+ val = readl(pmc_base + UTMIP_UHSIC_STATUS);
+
+ /* check whether we wake up from the remote resume */
+ 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);
+ }
+ }
+}
+
+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 */
+
+ DBG("%s(%d)\n", __func__, __LINE__);
+
+ /* check whether we wake up from the remote resume */
+ if (phy->remote_wakeup) {
+ /* wait until FPR bit is set automatically on remote resume */
+ do {
+ val = readl(base + USB_PORTSC);
+ udelay(1);
+ if (wait_time_us == 0) {
+ uhsic_phy_disable_pmc_bus_ctrl(phy);
+ uhsic_phy_post_resume(phy);
+ return;
+ }
+ wait_time_us--;
+ } while (!(val & USB_PORTSC_RESUME));
+ /* wait for 25 ms to port resume complete */
+ msleep(25);
+ /* disable PMC master control */
+ uhsic_phy_disable_pmc_bus_ctrl(phy);
+
+ /* Clear PCI and SRI bits to avoid an interrupt upon resume */
+ val = readl(base + USB_USBSTS);
+ writel(val, base + USB_USBSTS);
+ /* wait to avoid SOF if there is any */
+ if (usb_phy_reg_status_wait(base + USB_USBSTS,
+ USB_USBSTS_SRI, USB_USBSTS_SRI, 2500)) {
+ pr_warn("%s: timeout waiting for SOF\n", __func__);
+ }
+ uhsic_phy_post_resume(phy);
+ } 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 uhsic_phy_open(struct tegra_usb_phy *phy)
+{
+ unsigned long parent_rate;
+ int i;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ parent_rate = clk_get_rate(clk_get_parent(phy->pllu_clk));
+ for (i = 0; i < ARRAY_SIZE(uhsic_freq_table); i++) {
+ if (uhsic_freq_table[i].freq == parent_rate) {
+ phy->freq = &uhsic_freq_table[i];
+ break;
+ }
+ }
+ if (!phy->freq) {
+ pr_err("invalid pll_u parent rate %ld\n", parent_rate);
+ return -EINVAL;
+ }
+
+ uhsic_powerup_pmc_wake_detect(phy);
+
+ return 0;
+}
+
+static int uhsic_phy_irq(struct tegra_usb_phy *phy)
+{
+ usb_phy_fence_read(phy);
+ /* check if there is any remote wake event */
+ if (uhsic_phy_remotewake_detected(phy))
+ pr_info("%s: uhsic remote wake detected\n", __func__);
+ return IRQ_HANDLED;
+}
+
+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) {
+ DBG("%s(%d) inst:[%d] phy clk is already On\n",
+ __func__, __LINE__, phy->inst);
+ return 0;
+ }
+
+ val = readl(base + UHSIC_PADS_CFG1);
+ val &= ~(UHSIC_PD_BG | UHSIC_PD_TRK | UHSIC_PD_RX |
+ UHSIC_PD_ZI | UHSIC_RPD_DATA | UHSIC_RPD_STROBE);
+ val |= (UHSIC_RX_SEL | UHSIC_PD_TX);
+ writel(val, base + UHSIC_PADS_CFG1);
+
+ val = readl(base + USB_SUSP_CTRL);
+ val |= UHSIC_RESET;
+ writel(val, base + USB_SUSP_CTRL);
+ udelay(1);
+
+ val = readl(base + USB_SUSP_CTRL);
+ val |= UHSIC_PHY_ENABLE;
+ 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);
+ writel(val, base + UHSIC_HSRX_CFG0);
+
+ val = readl(base + UHSIC_HSRX_CFG1);
+ val |= UHSIC_HS_SYNC_START_DLY(config->sync_start_delay);
+ writel(val, base + UHSIC_HSRX_CFG1);
+
+ /* WAR HSIC TX */
+ val = readl(base + UHSIC_TX_CFG0);
+ val &= ~UHSIC_HS_READY_WAIT_FOR_VALID;
+ writel(val, base + UHSIC_TX_CFG0);
+
+ val = readl(base + UHSIC_MISC_CFG0);
+ val |= UHSIC_SUSPEND_EXIT_ON_EDGE;
+ /* Disable generic bus reset, to allow AP30 specific bus reset*/
+ val |= UHSIC_DISABLE_BUSRESET;
+ writel(val, base + UHSIC_MISC_CFG0);
+
+ val = readl(base + UHSIC_MISC_CFG1);
+ val |= UHSIC_PLLU_STABLE_COUNT(phy->freq->stable_count);
+ writel(val, base + UHSIC_MISC_CFG1);
+
+ val = readl(base + UHSIC_PLL_CFG1);
+ val |= UHSIC_PLLU_ENABLE_DLY_COUNT(phy->freq->enable_delay);
+ val |= UHSIC_XTAL_FREQ_COUNT(phy->freq->xtal_freq_count);
+ writel(val, base + UHSIC_PLL_CFG1);
+
+ val = readl(base + USB_SUSP_CTRL);
+ val &= ~(UHSIC_RESET);
+ writel(val, base + USB_SUSP_CTRL);
+ udelay(1);
+
+ val = readl(base + UHSIC_PADS_CFG1);
+ val &= ~(UHSIC_PD_TX);
+ writel(val, base + UHSIC_PADS_CFG1);
+
+ val = readl(base + USB_USBMODE);
+ val |= USB_USBMODE_HOST;
+ writel(val, base + USB_USBMODE);
+
+ /* Change the USB controller PHY type to HSIC */
+ 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);
+
+ 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);
+ }
+
+ val = readl(base + USB_PORTSC);
+ val &= ~(USB_PORTSC_WKOC | USB_PORTSC_WKDS | USB_PORTSC_WKCN);
+ writel(val, base + USB_PORTSC);
+
+ val = readl(base + UHSIC_PADS_CFG0);
+ val &= ~(UHSIC_TX_RTUNEN);
+ /* set Rtune impedance to 50 ohm */
+ val |= UHSIC_TX_RTUNE(8);
+ writel(val, base + UHSIC_PADS_CFG0);
+
+ if (usb_phy_reg_status_wait(base + USB_SUSP_CTRL,
+ USB_PHY_CLK_VALID, USB_PHY_CLK_VALID, 2500)) {
+ pr_err("%s: timeout waiting for phy to stabilize\n", __func__);
+ return -ETIMEDOUT;
+ }
+
+ phy->phy_clk_on = true;
+ phy->hw_accessible = true;
+
+ return 0;
+}
+
+static int uhsic_phy_power_off(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ if (!phy->phy_clk_on) {
+ DBG("%s(%d) inst:[%d] phy clk is already off\n",
+ __func__, __LINE__, phy->inst);
+ return 0;
+ }
+
+ phy->port_speed = (readl(base + HOSTPC1_DEVLC) >> 25) &
+ HOSTPC1_DEVLC_PSPD_MASK;
+
+ /* Disable interrupts */
+ writel(0, base + USB_USBINTR);
+
+ uhsic_setup_pmc_wake_detect(phy);
+
+ val = readl(base + HOSTPC1_DEVLC);
+ val |= HOSTPC1_DEVLC_PHCD;
+ writel(val, base + HOSTPC1_DEVLC);
+
+ phy->phy_clk_on = false;
+ phy->hw_accessible = false;
+
+ return 0;
+}
+
+int uhsic_phy_bus_port_power(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+
+ val = readl(base + USB_USBMODE);
+ val |= USB_USBMODE_HOST;
+ writel(val, base + USB_USBMODE);
+
+ /* Change the USB controller PHY type to HSIC */
+ 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);
+ val |= UHSIC_DETECT_SHORT_CONNECT;
+ writel(val, base + UHSIC_MISC_CFG0);
+ udelay(1);
+
+ val = readl(base + UHSIC_MISC_CFG0);
+ val |= UHSIC_FORCE_XCVR_MODE;
+ writel(val, base + UHSIC_MISC_CFG0);
+
+ val = readl(base + UHSIC_PADS_CFG1);
+ val &= ~UHSIC_RPD_STROBE;
+ writel(val, base + UHSIC_PADS_CFG1);
+
+ if (phy->pdata->ops && phy->pdata->ops->port_power)
+ phy->pdata->ops->port_power();
+
+ if (usb_phy_reg_status_wait(base + UHSIC_STAT_CFG0,
+ UHSIC_CONNECT_DETECT, UHSIC_CONNECT_DETECT, 25000)) {
+ pr_err("%s: timeout waiting for UHSIC_CONNECT_DETECT\n",
+ __func__);
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static int uhsic_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);
+
+ /* Change the USB controller PHY type to HSIC */
+ 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 */
+ mdelay(5);
+
+ val = readl(base + USB_PORTSC);
+ val |= USB_PORTSC_PTC(5);
+ writel(val, base + USB_PORTSC);
+ udelay(2);
+
+ val = readl(base + USB_PORTSC);
+ val &= ~(USB_PORTSC_PTC(~0));
+ writel(val, base + USB_PORTSC);
+ udelay(2);
+
+ if (usb_phy_reg_status_wait(base + USB_PORTSC, USB_PORTSC_LS(0),
+ 0, 2000)) {
+ pr_err("%s: timeout waiting for USB_PORTSC_LS\n", __func__);
+ return -ETIMEDOUT;
+ }
+
+ /* Poll until CCS is enabled */
+ if (usb_phy_reg_status_wait(base + USB_PORTSC, USB_PORTSC_CCS,
+ USB_PORTSC_CCS, 2000)) {
+ pr_err("%s: timeout waiting for USB_PORTSC_CCS\n", __func__);
+ return -ETIMEDOUT;
+ }
+
+ if (usb_phy_reg_status_wait(base + HOSTPC1_DEVLC,
+ HOSTPC1_DEVLC_PSPD(2),
+ HOSTPC1_DEVLC_PSPD(2), 2000) < 0) {
+ pr_err("%s: timeout waiting hsic high speed configuration\n",
+ __func__);
+ return -ETIMEDOUT;
+ }
+
+ 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__);
+ return -ETIMEDOUT;
+ }
+
+ val = readl(base + UHSIC_PADS_CFG1);
+ val &= ~UHSIC_RPU_STROBE;
+ val |= UHSIC_RPD_STROBE;
+ writel(val, base + UHSIC_PADS_CFG1);
+
+ mdelay(50);
+
+ val = readl(base + UHSIC_PADS_CFG1);
+ val &= ~UHSIC_RPD_STROBE;
+ val |= UHSIC_RPU_STROBE;
+ writel(val, base + UHSIC_PADS_CFG1);
+
+ val = readl(base + USB_USBCMD);
+ val |= USB_USBCMD_RS;
+ writel(val, base + USB_USBCMD);
+
+ val = readl(base + UHSIC_PADS_CFG1);
+ val &= ~UHSIC_RPU_STROBE;
+ writel(val, base + UHSIC_PADS_CFG1);
+
+ if (usb_phy_reg_status_wait(base + USB_USBCMD, USB_USBCMD_RS,
+ USB_USBCMD_RS, 2000)) {
+ pr_err("%s: timeout waiting for USB_USBCMD_RS\n", __func__);
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+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;
+}
+
+static void ulpi_set_trimmer(struct tegra_usb_phy *phy)
+{
+ struct tegra_ulpi_config *config = &phy->pdata->u_cfg.ulpi;
+ void __iomem *base = phy->regs;
+ unsigned long val;
+
+ val = ULPI_DATA_TRIMMER_SEL(config->data_trimmer);
+ val |= ULPI_STPDIRNXT_TRIMMER_SEL(config->stpdirnxt_trimmer);
+ val |= ULPI_DIR_TRIMMER_SEL(config->dir_trimmer);
+ writel(val, base + ULPI_TIMING_CTRL_1);
+ udelay(10);
+
+ val |= ULPI_DATA_TRIMMER_LOAD;
+ val |= ULPI_STPDIRNXT_TRIMMER_LOAD;
+ val |= ULPI_DIR_TRIMMER_LOAD;
+ writel(val, base + ULPI_TIMING_CTRL_1);
+}
+
+static void reset_utmip_uhsic(void __iomem *base)
+{
+ unsigned long val;
+
+ val = readl(base + USB_SUSP_CTRL);
+ val |= UHSIC_RESET;
+ writel(val, base + USB_SUSP_CTRL);
+
+ val = readl(base + USB_SUSP_CTRL);
+ val |= UTMIP_RESET;
+ writel(val, base + USB_SUSP_CTRL);
+}
+
+static void ulpi_set_host(void __iomem *base)
+{
+ unsigned long val;
+
+ val = readl(base + USB_USBMODE);
+ val &= ~USB_USBMODE_MASK;
+ val |= USB_USBMODE_HOST;
+ writel(val, base + USB_USBMODE);
+
+ val = readl(base + HOSTPC1_DEVLC);
+ val |= HOSTPC1_DEVLC_PTS(2);
+ writel(val, base + HOSTPC1_DEVLC);
+}
+
+static inline void ulpi_pinmux_bypass(struct tegra_usb_phy *phy, bool enable)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+
+ val = readl(base + ULPI_TIMING_CTRL_0);
+
+ if (enable)
+ val |= ULPI_OUTPUT_PINMUX_BYP;
+ else
+ val &= ~ULPI_OUTPUT_PINMUX_BYP;
+
+ writel(val, base + ULPI_TIMING_CTRL_0);
+}
+
+static inline void ulpi_null_phy_set_tristate(bool enable)
+{
+#ifndef CONFIG_ARCH_TEGRA_2x_SOC
+ int tristate = (enable) ? TEGRA_TRI_TRISTATE : TEGRA_TRI_NORMAL;
+
+ tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA0, tristate);
+ tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA1, tristate);
+ tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA2, tristate);
+ tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA3, tristate);
+ tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA4, tristate);
+ tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA5, tristate);
+ tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA6, tristate);
+ tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA7, tristate);
+ tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_NXT, tristate);
+
+ if (enable)
+ tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DIR, tristate);
+#endif
+}
+
+static void ulpi_null_phy_obs_read(void)
+{
+ static void __iomem *apb_misc;
+ unsigned slv0_obs, s2s_obs;
+
+ if (!apb_misc)
+ apb_misc = ioremap(TEGRA_APB_MISC_BASE, TEGRA_APB_MISC_SIZE);
+
+ writel(0x80d1003c, apb_misc + APB_MISC_GP_OBSCTRL_0);
+ slv0_obs = readl(apb_misc + APB_MISC_GP_OBSDATA_0);
+
+ writel(0x80d10040, apb_misc + APB_MISC_GP_OBSCTRL_0);
+ s2s_obs = readl(apb_misc + APB_MISC_GP_OBSDATA_0);
+
+ pr_debug("slv0 obs: %08x\ns2s obs: %08x\n", slv0_obs, s2s_obs);
+}
+
+static const struct gpio ulpi_gpios[] = {
+ {ULPI_STP, GPIOF_IN, "ULPI_STP"},
+ {ULPI_DIR, GPIOF_OUT_INIT_LOW, "ULPI_DIR"},
+ {ULPI_D0, GPIOF_OUT_INIT_LOW, "ULPI_D0"},
+ {ULPI_D1, GPIOF_OUT_INIT_LOW, "ULPI_D1"},
+};
+
+static int ulpi_null_phy_open(struct tegra_usb_phy *phy)
+{
+ struct tegra_ulpi_config *config = &phy->pdata->u_cfg.ulpi;
+ int ret;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+
+ ret = gpio_request_array(ulpi_gpios, ARRAY_SIZE(ulpi_gpios));
+ if (ret)
+ return ret;
+
+ if (gpio_is_valid(config->phy_restore_gpio)) {
+ ret = gpio_request(config->phy_restore_gpio, "phy_restore");
+ if (ret)
+ goto err_gpio_free;
+
+ gpio_direction_input(config->phy_restore_gpio);
+ }
+
+ tegra_periph_reset_assert(phy->ctrlr_clk);
+ udelay(10);
+ tegra_periph_reset_deassert(phy->ctrlr_clk);
+
+ return 0;
+
+err_gpio_free:
+ gpio_free_array(ulpi_gpios, ARRAY_SIZE(ulpi_gpios));
+ return ret;
+}
+
+static void ulpi_null_phy_close(struct tegra_usb_phy *phy)
+{
+ struct tegra_ulpi_config *config = &phy->pdata->u_cfg.ulpi;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+
+ if (gpio_is_valid(config->phy_restore_gpio))
+ gpio_free(config->phy_restore_gpio);
+
+ gpio_free_array(ulpi_gpios, ARRAY_SIZE(ulpi_gpios));
+}
+
+static int ulpi_null_phy_power_off(struct tegra_usb_phy *phy)
+{
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+
+ if (!phy->phy_clk_on) {
+ DBG("%s(%d) inst:[%d] phy clk is already off\n", __func__,
+ __LINE__, phy->inst);
+ return 0;
+ }
+
+ phy->phy_clk_on = false;
+ phy->hw_accessible = false;
+ ulpi_null_phy_set_tristate(true);
+ return 0;
+}
+
+/* NOTE: this function must be called before ehci reset */
+static int ulpi_null_phy_init(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ val = readl(base + ULPIS2S_CTRL);
+ val |= ULPIS2S_SLV0_CLAMP_XMIT;
+ writel(val, base + ULPIS2S_CTRL);
+
+ val = readl(base + USB_SUSP_CTRL);
+ val |= ULPIS2S_SLV0_RESET;
+ writel(val, base + USB_SUSP_CTRL);
+ udelay(10);
+
+ return 0;
+}
+
+static int ulpi_null_phy_irq(struct tegra_usb_phy *phy)
+{
+ usb_phy_fence_read(phy);
+ return IRQ_HANDLED;
+}
+
+/* NOTE: this function must be called after ehci reset */
+static int ulpi_null_phy_cmd_reset(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ ulpi_set_host(base);
+
+ /* remove slave0 reset */
+ val = readl(base + USB_SUSP_CTRL);
+ val &= ~ULPIS2S_SLV0_RESET;
+ writel(val, base + USB_SUSP_CTRL);
+
+ val = readl(base + ULPIS2S_CTRL);
+ val &= ~ULPIS2S_SLV0_CLAMP_XMIT;
+ writel(val, base + ULPIS2S_CTRL);
+ udelay(10);
+
+ return 0;
+}
+
+static int ulpi_null_phy_restore(struct tegra_usb_phy *phy)
+{
+ struct tegra_ulpi_config *config = &phy->pdata->u_cfg.ulpi;
+ unsigned long timeout;
+ int ulpi_stp = ULPI_STP;
+
+ if (gpio_is_valid(config->phy_restore_gpio))
+ ulpi_stp = config->phy_restore_gpio;
+
+ /* disable ULPI pinmux bypass */
+ ulpi_pinmux_bypass(phy, false);
+
+ /* driving linstate by GPIO */
+ gpio_set_value(ULPI_D0, 0);
+ gpio_set_value(ULPI_D1, 0);
+
+ /* driving DIR high */
+ gpio_set_value(ULPI_DIR, 1);
+
+ /* remove ULPI tristate */
+ ulpi_null_phy_set_tristate(false);
+
+ /* wait for STP high */
+ timeout = jiffies + msecs_to_jiffies(25);
+
+ while (!gpio_get_value(ulpi_stp)) {
+ if (time_after(jiffies, timeout)) {
+ pr_warn("phy restore timeout\n");
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int ulpi_null_phy_lp0_resume(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ ulpi_null_phy_init(phy);
+
+ val = readl(base + USB_USBCMD);
+ val |= USB_CMD_RESET;
+ writel(val, base + USB_USBCMD);
+
+ if (usb_phy_reg_status_wait(base + USB_USBCMD,
+ USB_CMD_RESET, 0, 2500) < 0) {
+ pr_err("%s: timeout waiting for reset\n", __func__);
+ }
+
+ ulpi_null_phy_cmd_reset(phy);
+
+ val = readl(base + USB_USBCMD);
+ val |= USB_USBCMD_RS;
+ writel(val, base + USB_USBCMD);
+ if (usb_phy_reg_status_wait(base + USB_USBCMD, USB_USBCMD_RS,
+ USB_USBCMD_RS, 2000)) {
+ pr_err("%s: timeout waiting for USB_USBCMD_RS\n", __func__);
+ return -ETIMEDOUT;
+ }
+
+ /* Enable Port Power */
+ val = readl(base + USB_PORTSC);
+ val |= USB_PORTSC_PP;
+ writel(val, base + USB_PORTSC);
+ udelay(10);
+
+ ulpi_null_phy_restore(phy);
+
+ return 0;
+}
+
+static int ulpi_null_phy_power_on(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+ struct tegra_ulpi_config *config = &phy->pdata->u_cfg.ulpi;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ if (phy->phy_clk_on) {
+ DBG("%s(%d) inst:[%d] phy clk is already On\n", __func__,
+ __LINE__, phy->inst);
+ return 0;
+ }
+ reset_utmip_uhsic(base);
+
+ /* remove ULPI PADS CLKEN reset */
+ val = readl(base + USB_SUSP_CTRL);
+ val &= ~ULPI_PADS_CLKEN_RESET;
+ writel(val, base + USB_SUSP_CTRL);
+ udelay(10);
+
+ val = readl(base + ULPI_TIMING_CTRL_0);
+ val |= ULPI_OUTPUT_PINMUX_BYP | ULPI_CLKOUT_PINMUX_BYP;
+ writel(val, base + ULPI_TIMING_CTRL_0);
+
+ val = readl(base + USB_SUSP_CTRL);
+ val |= ULPI_PHY_ENABLE;
+ writel(val, base + USB_SUSP_CTRL);
+ udelay(10);
+
+ /* set timming parameters */
+ val = readl(base + ULPI_TIMING_CTRL_0);
+ val |= ULPI_SHADOW_CLK_LOOPBACK_EN;
+ val &= ~ULPI_SHADOW_CLK_SEL;
+ val &= ~ULPI_LBK_PAD_EN;
+ val |= ULPI_SHADOW_CLK_DELAY(config->shadow_clk_delay);
+ val |= ULPI_CLOCK_OUT_DELAY(config->clock_out_delay);
+ val |= ULPI_LBK_PAD_E_INPUT_OR;
+ writel(val, base + ULPI_TIMING_CTRL_0);
+
+ writel(0, base + ULPI_TIMING_CTRL_1);
+ udelay(10);
+
+ /* start internal 60MHz clock */
+ val = readl(base + ULPIS2S_CTRL);
+ val |= ULPIS2S_ENA;
+ val |= ULPIS2S_SUPPORT_DISCONNECT;
+ val |= ULPIS2S_SPARE((phy->pdata->op_mode == TEGRA_USB_OPMODE_HOST) ? 3 : 1);
+ val |= ULPIS2S_PLLU_MASTER_BLASTER60;
+ writel(val, base + ULPIS2S_CTRL);
+
+ /* select ULPI_CORE_CLK_SEL to SHADOW_CLK */
+ val = readl(base + ULPI_TIMING_CTRL_0);
+ val |= ULPI_CORE_CLK_SEL;
+ writel(val, base + ULPI_TIMING_CTRL_0);
+ udelay(10);
+
+ /* enable ULPI null phy clock - can't set the trimmers before this */
+ val = readl(base + ULPI_TIMING_CTRL_0);
+ val |= ULPI_CLK_OUT_ENA;
+ writel(val, base + ULPI_TIMING_CTRL_0);
+ udelay(10);
+
+ if (usb_phy_reg_status_wait(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID,
+ USB_PHY_CLK_VALID, 2500)) {
+ pr_err("%s: timeout waiting for phy to stabilize\n", __func__);
+ return -ETIMEDOUT;
+ }
+
+ /* set ULPI trimmers */
+ ulpi_set_trimmer(phy);
+
+ ulpi_set_host(base);
+
+ /* remove slave0 reset */
+ val = readl(base + USB_SUSP_CTRL);
+ val &= ~ULPIS2S_SLV0_RESET;
+ writel(val, base + USB_SUSP_CTRL);
+
+ /* remove slave1 and line reset */
+ val = readl(base + USB_SUSP_CTRL);
+ val &= ~ULPIS2S_SLV1_RESET;
+ val &= ~ULPIS2S_LINE_RESET;
+
+ /* remove ULPI PADS reset */
+ val &= ~ULPI_PADS_RESET;
+ writel(val, base + USB_SUSP_CTRL);
+
+ if (!phy->ulpi_clk_padout_ena) {
+ val = readl(base + ULPI_TIMING_CTRL_0);
+ val |= ULPI_CLK_PADOUT_ENA;
+ writel(val, base + ULPI_TIMING_CTRL_0);
+ phy->ulpi_clk_padout_ena = true;
+ } else {
+ if (!readl(base + USB_ASYNCLISTADDR))
+ ulpi_null_phy_lp0_resume(phy);
+ }
+ udelay(10);
+
+ phy->phy_clk_on = true;
+ phy->hw_accessible = true;
+
+ return 0;
+}
+
+static int ulpi_null_phy_pre_resume(struct tegra_usb_phy *phy,
+ bool remote_wakeup)
+{
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ ulpi_null_phy_obs_read();
+ usb_phy_wait_for_sof(phy);
+ ulpi_null_phy_obs_read();
+ return 0;
+}
+
+static int ulpi_null_phy_post_resume(struct tegra_usb_phy *phy)
+{
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ ulpi_null_phy_obs_read();
+ return 0;
+}
+
+static int ulpi_null_phy_resume(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+
+ if (!readl(base + USB_ASYNCLISTADDR)) {
+ /* enable ULPI CLK output pad */
+ val = readl(base + ULPI_TIMING_CTRL_0);
+ val |= ULPI_CLK_PADOUT_ENA;
+ writel(val, base + ULPI_TIMING_CTRL_0);
+
+ /* enable ULPI pinmux bypass */
+ ulpi_pinmux_bypass(phy, true);
+ udelay(5);
+#ifndef CONFIG_ARCH_TEGRA_2x_SOC
+ /* remove DIR tristate */
+ tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DIR,
+ TEGRA_TRI_NORMAL);
+#endif
+ }
+ return 0;
+}
+
+
+
+static struct tegra_usb_phy_ops utmi_phy_ops = {
+ .open = utmi_phy_open,
+ .close = utmi_phy_close,
+ .irq = utmi_phy_irq,
+ .power_on = utmi_phy_power_on,
+ .power_off = utmi_phy_power_off,
+ .pre_resume = utmi_phy_pre_resume,
+ .resume = utmi_phy_resume,
+ .post_resume = utmi_phy_post_resume,
+ .charger_detect = utmi_phy_charger_detect,
+};
+
+static struct tegra_usb_phy_ops uhsic_phy_ops = {
+ .open = uhsic_phy_open,
+ .irq = uhsic_phy_irq,
+ .power_on = uhsic_phy_power_on,
+ .power_off = uhsic_phy_power_off,
+ .pre_resume = uhsic_phy_pre_resume,
+ .resume = uhsic_phy_resume,
+ .post_resume = uhsic_phy_post_resume,
+ .port_power = uhsic_phy_bus_port_power,
+ .bus_reset = uhsic_phy_bus_reset,
+};
+
+static struct tegra_usb_phy_ops ulpi_null_phy_ops = {
+ .open = ulpi_null_phy_open,
+ .close = ulpi_null_phy_close,
+ .init = ulpi_null_phy_init,
+ .irq = ulpi_null_phy_irq,
+ .power_on = ulpi_null_phy_power_on,
+ .power_off = ulpi_null_phy_power_off,
+ .pre_resume = ulpi_null_phy_pre_resume,
+ .resume = ulpi_null_phy_resume,
+ .post_resume = ulpi_null_phy_post_resume,
+ .reset = ulpi_null_phy_cmd_reset,
+};
+
+static struct tegra_usb_phy_ops ulpi_link_phy_ops;
+static struct tegra_usb_phy_ops icusb_phy_ops;
+
+static struct tegra_usb_phy_ops *phy_ops[] = {
+ [TEGRA_USB_PHY_INTF_UTMI] = &utmi_phy_ops,
+ [TEGRA_USB_PHY_INTF_ULPI_LINK] = &ulpi_link_phy_ops,
+ [TEGRA_USB_PHY_INTF_ULPI_NULL] = &ulpi_null_phy_ops,
+ [TEGRA_USB_PHY_INTF_HSIC] = &uhsic_phy_ops,
+ [TEGRA_USB_PHY_INTF_ICUSB] = &icusb_phy_ops,
+};
+
+int tegra3_usb_phy_init_ops(struct tegra_usb_phy *phy)
+{
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+
+ phy->ops = phy_ops[phy->pdata->phy_intf];
+
+ /* FIXME: uncommenting below line to make USB host mode fail*/
+ /* usb_phy_power_down_pmc(); */
+
+ return 0;
+}
diff --git a/arch/arm/mach-tegra/tegra_odm_fuses.c b/arch/arm/mach-tegra/tegra_odm_fuses.c
index 5dcf24e497b2..06b831c31967 100644
--- a/arch/arm/mach-tegra/tegra_odm_fuses.c
+++ b/arch/arm/mach-tegra/tegra_odm_fuses.c
@@ -885,7 +885,7 @@ static ssize_t fuse_show(struct kobject *kobj, struct kobj_attribute *attr, char
{
enum fuse_io_param param = fuse_name_to_param(attr->attr.name);
u32 data[8];
- char str[8];
+ char str[9]; /* extra byte for null character */
int ret, i;
if ((param == -1) || (param == -ENODATA)) {
diff --git a/arch/arm/mach-tegra/tegra_usb_modem_power.c b/arch/arm/mach-tegra/tegra_usb_modem_power.c
index 88543397f974..bb9495a329a6 100644
--- a/arch/arm/mach-tegra/tegra_usb_modem_power.c
+++ b/arch/arm/mach-tegra/tegra_usb_modem_power.c
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-tegra/tegra_usb_modem_power.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
@@ -22,6 +22,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
+#include <linux/platform_data/tegra_usb.h>
#include <linux/workqueue.h>
#include <linux/gpio.h>
#include <linux/usb.h>
@@ -30,27 +31,46 @@
#include <linux/suspend.h>
#include <linux/slab.h>
#include <linux/wakelock.h>
+#include <linux/pm_qos_params.h>
#include <mach/tegra_usb_modem_power.h>
+#define BOOST_CPU_FREQ_MIN 1200000
+#define BOOST_CPU_FREQ_TIMEOUT 5000
+
+#define WAKELOCK_TIMEOUT_FOR_USB_ENUM (HZ * 10)
+#define WAKELOCK_TIMEOUT_FOR_REMOTE_WAKE (HZ)
+
struct tegra_usb_modem {
- unsigned int wake_gpio; /* remote wakeup gpio */
+ struct tegra_usb_modem_power_platform_data *pdata;
unsigned int wake_cnt; /* remote wakeup counter */
- int irq; /* remote wakeup irq */
+ unsigned int wake_irq; /* remote wakeup irq */
+ unsigned int boot_irq; /* modem boot irq */
struct mutex lock;
struct wake_lock wake_lock; /* modem wake lock */
unsigned int vid; /* modem vendor id */
unsigned int pid; /* modem product id */
struct usb_device *udev; /* modem usb device */
+ struct usb_device *parent; /* parent device */
struct usb_interface *intf; /* first modem usb interface */
struct workqueue_struct *wq; /* modem workqueue */
struct delayed_work recovery_work; /* modem recovery work */
+ struct pm_qos_request_list cpu_boost_req; /* min CPU freq request */
+ struct work_struct cpu_boost_work; /* CPU freq boost work */
+ struct delayed_work cpu_unboost_work; /* CPU freq unboost work */
const struct tegra_modem_operations *ops; /* modem operations */
unsigned int capability; /* modem capability */
int system_suspend; /* system suspend flag */
struct notifier_block pm_notifier; /* pm event notifier */
struct notifier_block usb_notifier; /* usb event notifier */
+ int sysfs_file_created;
+ int short_autosuspend_enabled;
};
+static struct platform_device *hc = NULL; /* USB host controller */
+static struct mutex hc_lock;
+static const struct platform_device *hc_device;
+static const struct tegra_usb_platform_data *hc_pdata;
+
/* supported modems */
static const struct usb_device_id modem_list[] = {
{USB_DEVICE(0x1983, 0x0310), /* Icera 450 rev1 */
@@ -65,27 +85,81 @@ static const struct usb_device_id modem_list[] = {
{}
};
+static void cpu_freq_unboost(struct work_struct *ws)
+{
+ struct tegra_usb_modem *modem = container_of(ws, struct tegra_usb_modem,
+ cpu_unboost_work.work);
+
+ pm_qos_update_request(&modem->cpu_boost_req, PM_QOS_DEFAULT_VALUE);
+}
+
+static void cpu_freq_boost(struct work_struct *ws)
+{
+ struct tegra_usb_modem *modem = container_of(ws, struct tegra_usb_modem,
+ cpu_boost_work);
+
+ cancel_delayed_work_sync(&modem->cpu_unboost_work);
+ pm_qos_update_request(&modem->cpu_boost_req, BOOST_CPU_FREQ_MIN);
+ queue_delayed_work(modem->wq, &modem->cpu_unboost_work,
+ msecs_to_jiffies(BOOST_CPU_FREQ_TIMEOUT));
+}
+
static irqreturn_t tegra_usb_modem_wake_thread(int irq, void *data)
{
struct tegra_usb_modem *modem = (struct tegra_usb_modem *)data;
- wake_lock_timeout(&modem->wake_lock, HZ);
mutex_lock(&modem->lock);
- if (modem->udev) {
+ if (modem->udev && modem->udev->state != USB_STATE_NOTATTACHED) {
pr_info("modem wake (%u)\n", ++(modem->wake_cnt));
if (!modem->system_suspend) {
+ wake_lock_timeout(&modem->wake_lock,
+ WAKELOCK_TIMEOUT_FOR_REMOTE_WAKE);
+
usb_lock_device(modem->udev);
if (usb_autopm_get_interface(modem->intf) == 0)
usb_autopm_put_interface_async(modem->intf);
usb_unlock_device(modem->udev);
}
+#ifdef CONFIG_PM
+ if (modem->capability & TEGRA_MODEM_AUTOSUSPEND &&
+ modem->short_autosuspend_enabled) {
+ pm_runtime_set_autosuspend_delay(&modem->udev->dev,
+ modem->pdata->autosuspend_delay);
+ modem->short_autosuspend_enabled = 0;
+ }
+#endif
}
mutex_unlock(&modem->lock);
return IRQ_HANDLED;
}
+static irqreturn_t tegra_usb_modem_boot_thread(int irq, void *data)
+{
+ struct tegra_usb_modem *modem = (struct tegra_usb_modem *)data;
+
+ if (gpio_get_value(modem->pdata->boot_gpio))
+ pr_info("BB_RST_OUT high\n");
+ else
+ pr_info("BB_RST_OUT low\n");
+
+ /* hold wait lock to complete the enumeration */
+ wake_lock_timeout(&modem->wake_lock, WAKELOCK_TIMEOUT_FOR_USB_ENUM);
+
+ /* boost CPU freq */
+ if (!work_pending(&modem->cpu_boost_work))
+ queue_work(modem->wq, &modem->cpu_boost_work);
+
+ /* USB disconnect maybe on going... */
+ mutex_lock(&modem->lock);
+ if (modem->udev && modem->udev->state != USB_STATE_NOTATTACHED)
+ pr_warn("Device is not disconnected!\n");
+ mutex_unlock(&modem->lock);
+
+ return IRQ_HANDLED;
+}
+
static void tegra_usb_modem_recovery(struct work_struct *ws)
{
struct tegra_usb_modem *modem = container_of(ws, struct tegra_usb_modem,
@@ -108,13 +182,15 @@ static void device_add_handler(struct tegra_usb_modem *modem,
if (id) {
/* hold wakelock to ensure ril has enough time to restart */
- wake_lock_timeout(&modem->wake_lock, HZ * 10);
+ wake_lock_timeout(&modem->wake_lock,
+ WAKELOCK_TIMEOUT_FOR_USB_ENUM);
pr_info("Add device %d <%s %s>\n", udev->devnum,
udev->manufacturer, udev->product);
mutex_lock(&modem->lock);
modem->udev = udev;
+ modem->parent = udev->parent;
modem->intf = intf;
modem->vid = desc->idVendor;
modem->pid = desc->idProduct;
@@ -126,7 +202,9 @@ static void device_add_handler(struct tegra_usb_modem *modem,
#ifdef CONFIG_PM
if (modem->capability & TEGRA_MODEM_AUTOSUSPEND) {
- pm_runtime_set_autosuspend_delay(&udev->dev, 2000);
+ pm_runtime_set_autosuspend_delay(&udev->dev,
+ modem->pdata->autosuspend_delay);
+ modem->short_autosuspend_enabled = 0;
usb_enable_autosuspend(udev);
pr_info("enable autosuspend for %s %s\n",
udev->manufacturer, udev->product);
@@ -140,8 +218,7 @@ static void device_remove_handler(struct tegra_usb_modem *modem,
{
const struct usb_device_descriptor *desc = &udev->descriptor;
- if (desc->idVendor == modem->vid &&
- desc->idProduct == modem->pid) {
+ if (desc->idVendor == modem->vid && desc->idProduct == modem->pid) {
pr_info("Remove device %d <%s %s>\n", udev->devnum,
udev->manufacturer, udev->product);
@@ -158,11 +235,10 @@ static void device_remove_handler(struct tegra_usb_modem *modem,
}
static int mdm_usb_notifier(struct notifier_block *notifier,
- unsigned long usb_event,
- void *udev)
+ unsigned long usb_event, void *udev)
{
struct tegra_usb_modem *modem =
- container_of(notifier, struct tegra_usb_modem, usb_notifier);
+ container_of(notifier, struct tegra_usb_modem, usb_notifier);
switch (usb_event) {
case USB_DEVICE_ADD:
@@ -176,11 +252,10 @@ static int mdm_usb_notifier(struct notifier_block *notifier,
}
static int mdm_pm_notifier(struct notifier_block *notifier,
- unsigned long pm_event,
- void *unused)
+ unsigned long pm_event, void *unused)
{
struct tegra_usb_modem *modem =
- container_of(notifier, struct tegra_usb_modem, pm_notifier);
+ container_of(notifier, struct tegra_usb_modem, pm_notifier);
mutex_lock(&modem->lock);
if (!modem->udev) {
@@ -194,10 +269,20 @@ static int mdm_pm_notifier(struct notifier_block *notifier,
if (wake_lock_active(&modem->wake_lock)) {
pr_warn("%s: wakelock was active, aborting suspend\n",
__func__);
+ mutex_unlock(&modem->lock);
return NOTIFY_STOP;
}
modem->system_suspend = 1;
+#ifdef CONFIG_PM
+ if (modem->capability & TEGRA_MODEM_AUTOSUSPEND &&
+ modem->udev &&
+ modem->udev->state != USB_STATE_NOTATTACHED) {
+ pm_runtime_set_autosuspend_delay(&modem->udev->dev,
+ modem->pdata->short_autosuspend_delay);
+ modem->short_autosuspend_enabled = 1;
+ }
+#endif
mutex_unlock(&modem->lock);
return NOTIFY_OK;
case PM_POST_SUSPEND:
@@ -210,12 +295,125 @@ static int mdm_pm_notifier(struct notifier_block *notifier,
return NOTIFY_DONE;
}
+static int mdm_request_wakeable_irq(struct tegra_usb_modem *modem,
+ irq_handler_t thread_fn,
+ unsigned int irq_gpio,
+ unsigned long irq_flags,
+ const char *label, unsigned int *irq)
+{
+ int ret;
+
+ ret = gpio_request(irq_gpio, label);
+ if (ret)
+ return ret;
+
+ tegra_gpio_enable(irq_gpio);
+
+ /* enable IRQ for GPIO */
+ *irq = gpio_to_irq(irq_gpio);
+
+ /* request threaded irq for GPIO */
+ ret = request_threaded_irq(*irq, NULL, thread_fn, irq_flags, label,
+ modem);
+ if (ret)
+ return ret;
+
+ ret = enable_irq_wake(*irq);
+ if (ret) {
+ free_irq(*irq, modem);
+ return ret;
+ }
+
+ return ret;
+}
+
+/* load USB host controller */
+static struct platform_device *tegra_usb_null_ulpi_host_register(void)
+{
+ struct platform_device *pdev;
+ int val;
+
+ pdev = platform_device_alloc(hc_device->name, hc_device->id);
+ if (!pdev)
+ return NULL;
+
+ val = platform_device_add_resources(pdev, hc_device->resource,
+ hc_device->num_resources);
+ if (val)
+ goto error;
+
+ pdev->dev.dma_mask = hc_device->dev.dma_mask;
+ pdev->dev.coherent_dma_mask = hc_device->dev.coherent_dma_mask;
+
+ val = platform_device_add_data(pdev, hc_pdata,
+ sizeof(struct tegra_usb_platform_data));
+ if (val)
+ goto error;
+
+ val = platform_device_add(pdev);
+ if (val)
+ goto error;
+
+ return pdev;
+
+error:
+ pr_err("%s: err %d\n", __func__, val);
+ platform_device_put(pdev);
+ return NULL;
+}
+
+/* unload USB host controller */
+static void tegra_usb_null_ulpi_host_unregister(struct platform_device *pdev)
+{
+ platform_device_unregister(pdev);
+}
+
+static ssize_t show_usb_host(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n", (hc) ? 1 : 0);
+}
+
+static ssize_t load_unload_usb_host(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int host;
+
+ if (sscanf(buf, "%d", &host) != 1 || host < 0 || host > 1)
+ return -EINVAL;
+
+ pr_info("%s USB host\n", (host) ? "load" : "unload");
+
+ mutex_lock(&hc_lock);
+ if (host) {
+ if (!hc)
+ hc = tegra_usb_null_ulpi_host_register();
+ } else {
+ if (hc) {
+ tegra_usb_null_ulpi_host_unregister(hc);
+ hc = NULL;
+ }
+ }
+ mutex_unlock(&hc_lock);
+
+ return count;
+}
+
+static DEVICE_ATTR(load_host, 0666, show_usb_host, load_unload_usb_host);
+
static int mdm_init(struct tegra_usb_modem *modem, struct platform_device *pdev)
{
struct tegra_usb_modem_power_platform_data *pdata =
pdev->dev.platform_data;
int ret = 0;
+ modem->pdata = pdata;
+
+ hc_device = pdata->tegra_ehci_device;
+ hc_pdata = pdata->tegra_ehci_pdata;
+ mutex_init(&hc_lock);
+
/* get modem operations from platform data */
modem->ops = (const struct tegra_modem_operations *)pdata->ops;
@@ -232,46 +430,47 @@ static int mdm_init(struct tegra_usb_modem *modem, struct platform_device *pdev)
modem->ops->start();
}
+ /* create sysfs node to load/unload host controller */
+ ret = device_create_file(&pdev->dev, &dev_attr_load_host);
+ if (ret) {
+ dev_err(&pdev->dev, "can't create sysfs file\n");
+ goto error;
+ }
+ modem->sysfs_file_created = 1;
+
mutex_init(&(modem->lock));
- wake_lock_init(&modem->wake_lock, WAKE_LOCK_SUSPEND,
- "tegra_usb_mdm_lock");
+ wake_lock_init(&modem->wake_lock, WAKE_LOCK_SUSPEND, "mdm_lock");
- /* create work queue platform_driver_registe*/
+ /* create work queue platform_driver_registe */
modem->wq = create_workqueue("tegra_usb_mdm_queue");
- INIT_DELAYED_WORK(&(modem->recovery_work), tegra_usb_modem_recovery);
+ INIT_DELAYED_WORK(&modem->recovery_work, tegra_usb_modem_recovery);
- /* create threaded irq for remote wakeup */
- if (gpio_is_valid(pdata->wake_gpio)) {
- /* get remote wakeup gpio from platform data */
- modem->wake_gpio = pdata->wake_gpio;
+ INIT_WORK(&modem->cpu_boost_work, cpu_freq_boost);
+ INIT_DELAYED_WORK(&modem->cpu_unboost_work, cpu_freq_unboost);
- ret = gpio_request(modem->wake_gpio, "usb_mdm_wake");
- if (ret)
- return ret;
+ pm_qos_add_request(&modem->cpu_boost_req, PM_QOS_CPU_FREQ_MIN,
+ PM_QOS_DEFAULT_VALUE);
- tegra_gpio_enable(modem->wake_gpio);
-
- /* enable IRQ for remote wakeup */
- modem->irq = gpio_to_irq(modem->wake_gpio);
-
- ret =
- request_threaded_irq(modem->irq, NULL,
- tegra_usb_modem_wake_thread,
- pdata->flags, "tegra_usb_mdm_wake",
- modem);
- if (ret < 0) {
- dev_err(&pdev->dev, "%s: request_threaded_irq error\n",
- __func__);
- return ret;
- }
+ /* request remote wakeup irq from platform data */
+ ret = mdm_request_wakeable_irq(modem,
+ tegra_usb_modem_wake_thread,
+ pdata->wake_gpio,
+ pdata->wake_irq_flags,
+ "mdm_wake", &modem->wake_irq);
+ if (ret) {
+ dev_err(&pdev->dev, "request wake irq error\n");
+ goto error;
+ }
- ret = enable_irq_wake(modem->irq);
- if (ret) {
- dev_err(&pdev->dev, "%s: enable_irq_wake error\n",
- __func__);
- free_irq(modem->irq, modem);
- return ret;
- }
+ /* request boot irq from platform data */
+ ret = mdm_request_wakeable_irq(modem,
+ tegra_usb_modem_boot_thread,
+ pdata->boot_gpio,
+ pdata->boot_irq_flags,
+ "mdm_boot", &modem->boot_irq);
+ if (ret) {
+ dev_err(&pdev->dev, "request boot irq error\n");
+ goto error;
}
modem->pm_notifier.notifier_call = mdm_pm_notifier;
@@ -281,6 +480,21 @@ static int mdm_init(struct tegra_usb_modem *modem, struct platform_device *pdev)
register_pm_notifier(&modem->pm_notifier);
return ret;
+error:
+ if (modem->sysfs_file_created)
+ device_remove_file(&pdev->dev, &dev_attr_load_host);
+
+ if (modem->wake_irq) {
+ disable_irq_wake(modem->wake_irq);
+ free_irq(modem->wake_irq, modem);
+ }
+
+ if (modem->boot_irq) {
+ disable_irq_wake(modem->boot_irq);
+ free_irq(modem->boot_irq, modem);
+ }
+
+ return ret;
}
static int tegra_usb_modem_probe(struct platform_device *pdev)
@@ -319,10 +533,25 @@ static int __exit tegra_usb_modem_remove(struct platform_device *pdev)
unregister_pm_notifier(&modem->pm_notifier);
usb_unregister_notify(&modem->usb_notifier);
- if (modem->irq) {
- disable_irq_wake(modem->irq);
- free_irq(modem->irq, modem);
+ if (modem->wake_irq) {
+ disable_irq_wake(modem->wake_irq);
+ free_irq(modem->wake_irq, modem);
}
+
+ if (modem->boot_irq) {
+ disable_irq_wake(modem->boot_irq);
+ free_irq(modem->boot_irq, modem);
+ }
+
+ if (modem->sysfs_file_created)
+ device_remove_file(&pdev->dev, &dev_attr_load_host);
+
+ cancel_work_sync(&modem->cpu_boost_work);
+ cancel_delayed_work_sync(&modem->cpu_unboost_work);
+ destroy_workqueue(modem->wq);
+
+ pm_qos_remove_request(&modem->cpu_boost_req);
+
kfree(modem);
return 0;
}
diff --git a/arch/arm/mach-tegra/tegra_usb_phy.h b/arch/arm/mach-tegra/tegra_usb_phy.h
new file mode 100644
index 000000000000..0dc4cd73c5e7
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra_usb_phy.h
@@ -0,0 +1,107 @@
+/*
+ * arch/arm/mach-tegra/include/mach/tegra_usb_phy.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_USB_PHY_H
+#define __MACH_TEGRA_USB_PHY_H
+
+/**
+ * defines USB port speeds supported in USB2.0
+ */
+enum usb_phy_port_speed {
+ USB_PHY_PORT_SPEED_FULL = 0,
+ USB_PHY_PORT_SPEED_LOW,
+ USB_PHY_PORT_SPEED_HIGH,
+ USB_PHY_PORT_SPEED_UNKNOWN,
+};
+
+/**
+ * defines structure for oscillator dependent parameters
+ */
+struct tegra_xtal_freq {
+ int freq;
+ u8 enable_delay;
+ u8 stable_count;
+ u8 active_delay;
+ u16 xtal_freq_count;
+ u16 debounce;
+ u8 pdtrk_count;
+};
+
+/**
+ * pre decleration of the usb phy data structure
+ */
+struct tegra_usb_phy;
+
+/**
+ * defines function pointers used for differnt phy interfaces
+ */
+struct tegra_usb_phy_ops {
+ int (*open)(struct tegra_usb_phy *phy);
+ void (*close)(struct tegra_usb_phy *phy);
+ int (*irq)(struct tegra_usb_phy *phy);
+ int (*init)(struct tegra_usb_phy *phy);
+ int (*reset)(struct tegra_usb_phy *phy);
+ int (*pre_suspend)(struct tegra_usb_phy *phy);
+ int (*suspend)(struct tegra_usb_phy *phy);
+ int (*post_suspend)(struct tegra_usb_phy *phy);
+ int (*pre_resume)(struct tegra_usb_phy *phy, bool remote_wakeup);
+ int (*resume)(struct tegra_usb_phy *phy);
+ int (*post_resume)(struct tegra_usb_phy *phy);
+ int (*port_power)(struct tegra_usb_phy *phy);
+ int (*bus_reset)(struct tegra_usb_phy *phy);
+ int (*power_off)(struct tegra_usb_phy *phy);
+ int (*power_on)(struct tegra_usb_phy *phy);
+ bool (*charger_detect)(struct tegra_usb_phy *phy);
+};
+
+/**
+ * defines usb phy data structure
+ */
+struct tegra_usb_phy {
+ struct platform_device *pdev;
+ struct tegra_usb_platform_data *pdata;
+ struct clk *pllu_clk;
+ struct clk *ctrlr_clk;
+ struct clk *ulpi_clk;
+ struct clk *utmi_pad_clk;
+ struct clk *emc_clk;
+ struct clk *sys_clk;
+ struct regulator *vdd_reg;
+ struct regulator *vbus_reg;
+ struct tegra_usb_phy_ops *ops;
+ struct tegra_xtal_freq *freq;
+ struct otg_transceiver *ulpi_vp;
+ enum usb_phy_port_speed port_speed;
+ signed char utmi_xcvr_setup;
+ void __iomem *regs;
+ int inst;
+ bool phy_clk_on;
+ bool ctrl_clk_on;
+ bool vdd_reg_on;
+ bool phy_power_on;
+ bool remote_wakeup;
+ bool hw_accessible;
+ bool ulpi_clk_padout_ena;
+};
+
+int usb_phy_reg_status_wait(void __iomem *reg, u32 mask,
+ u32 result, u32 timeout);
+
+int tegra3_usb_phy_init_ops(struct tegra_usb_phy *phy);
+int tegra2_usb_phy_init_ops(struct tegra_usb_phy *phy);
+
+
+#endif /* __MACH_TEGRA_USB_PHY_H */
diff --git a/arch/arm/mach-tegra/timer-t3.c b/arch/arm/mach-tegra/timer-t3.c
index df964fbce154..f23873b214b2 100644
--- a/arch/arm/mach-tegra/timer-t3.c
+++ b/arch/arm/mach-tegra/timer-t3.c
@@ -69,8 +69,13 @@
#define TIMER6_OFFSET (TEGRA_TMR6_BASE-TEGRA_TMR1_BASE)
static void __iomem *timer_reg_base = IO_ADDRESS(TEGRA_TMR1_BASE);
-static cpumask_t wake_timer_ready;
+
+#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/usb_phy.c b/arch/arm/mach-tegra/usb_phy.c
index c204aa3b49c2..5940b2f2e1df 100644
--- a/arch/arm/mach-tegra/usb_phy.c
+++ b/arch/arm/mach-tegra/usb_phy.c
@@ -2,7 +2,7 @@
* arch/arm/mach-tegra/usb_phy.c
*
* Copyright (C) 2010 Google, Inc.
- * Copyright (C) 2010 - 2011 NVIDIA Corporation
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION. All rights reserved.
*
* Author:
* Erik Gilling <konkers@google.com>
@@ -18,7 +18,6 @@
* GNU General Public License for more details.
*
*/
-
#include <linux/resource.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
@@ -27,582 +26,17 @@
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/gpio.h>
-#include <linux/usb/otg.h>
-#include <linux/usb/ulpi.h>
-#include <asm/mach-types.h>
-#include <mach/usb_phy.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <linux/platform_data/tegra_usb.h>
+#include "tegra_usb_phy.h"
#include <mach/iomap.h>
-#include <mach/pinmux.h>
#include "fuse.h"
-#include "gpio-names.h"
-
-
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
-#define USB_USBCMD 0x140
-#define USB_USBCMD_RS (1 << 0)
-
-#define USB_USBSTS 0x144
-#define USB_USBSTS_PCI (1 << 2)
-#define USB_USBSTS_HCH (1 << 12)
-
-#define USB_TXFILLTUNING 0x164
-#define USB_FIFO_TXFILL_THRES(x) (((x) & 0x1f) << 16)
-#define USB_FIFO_TXFILL_MASK 0x1f0000
-
-#define ULPI_VIEWPORT 0x170
-#define ULPI_WAKEUP (1 << 31)
-#define ULPI_RUN (1 << 30)
-#define ULPI_RD_WR (1 << 29)
-
-#define USB_PORTSC1 0x184
-#define USB_PORTSC1_PTS(x) (((x) & 0x3) << 30)
-#define USB_PORTSC1_PSPD(x) (((x) & 0x3) << 26)
-#define USB_PORTSC1_PHCD (1 << 23)
-#define USB_PORTSC1_WKOC (1 << 22)
-#define USB_PORTSC1_WKDS (1 << 21)
-#define USB_PORTSC1_WKCN (1 << 20)
-#define USB_PORTSC1_PTC(x) (((x) & 0xf) << 16)
-#define USB_PORTSC1_PP (1 << 12)
-#define USB_PORTSC1_LS(x) (((x) & 0x3) << 10)
-#define USB_PORTSC1_SUSP (1 << 7)
-#define USB_PORTSC1_PE (1 << 2)
-#define USB_PORTSC1_CCS (1 << 0)
-
-#define USB_SUSP_CTRL 0x400
-#define USB_WAKE_ON_CNNT_EN_DEV (1 << 3)
-#define USB_WAKE_ON_DISCON_EN_DEV (1 << 4)
-#define USB_SUSP_CLR (1 << 5)
-#define USB_CLKEN (1 << 6)
-#define USB_PHY_CLK_VALID (1 << 7)
-#define USB_PHY_CLK_VALID_INT_ENB (1 << 9)
-#define UTMIP_RESET (1 << 11)
-#define UHSIC_RESET (1 << 11)
-#define UTMIP_PHY_ENABLE (1 << 12)
-#define UHSIC_PHY_ENABLE (1 << 12)
-#define ULPI_PHY_ENABLE (1 << 13)
-#define USB_SUSP_SET (1 << 14)
-#define USB_WAKEUP_DEBOUNCE_COUNT(x) (((x) & 0x7) << 16)
-
-#define USB_PHY_VBUS_WAKEUP_ID 0x408
-#define VDAT_DET_INT_EN (1 << 16)
-#define VDAT_DET_CHG_DET (1 << 17)
-#define VDAT_DET_STS (1 << 18)
-
-#define USB1_LEGACY_CTRL 0x410
-#define USB1_NO_LEGACY_MODE (1 << 0)
-#define USB1_VBUS_SENSE_CTL_MASK (3 << 1)
-#define USB1_VBUS_SENSE_CTL_VBUS_WAKEUP (0 << 1)
-#define USB1_VBUS_SENSE_CTL_AB_SESS_VLD_OR_VBUS_WAKEUP \
- (1 << 1)
-#define USB1_VBUS_SENSE_CTL_AB_SESS_VLD (2 << 1)
-#define USB1_VBUS_SENSE_CTL_A_SESS_VLD (3 << 1)
-
-
-#define UTMIP_PLL_CFG1 0x804
-#define UTMIP_XTAL_FREQ_COUNT(x) (((x) & 0xfff) << 0)
-#define UTMIP_PLLU_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 27)
-
-#define UTMIP_XCVR_CFG0 0x808
-#define UTMIP_XCVR_SETUP(x) (((x) & 0xf) << 0)
-#define UTMIP_XCVR_LSRSLEW(x) (((x) & 0x3) << 8)
-#define UTMIP_XCVR_LSFSLEW(x) (((x) & 0x3) << 10)
-#define UTMIP_FORCE_PD_POWERDOWN (1 << 14)
-#define UTMIP_FORCE_PD2_POWERDOWN (1 << 16)
-#define UTMIP_FORCE_PDZI_POWERDOWN (1 << 18)
-#define UTMIP_XCVR_LSBIAS_SEL (1 << 21)
-#define UTMIP_XCVR_SETUP_MSB(x) (((x) & 0x7) << 22)
-#define UTMIP_XCVR_HSSLEW_MSB(x) (((x) & 0x7f) << 25)
-
-#define UTMIP_XCVR_MAX_OFFSET 2
-#define UTMIP_XCVR_SETUP_MAX_VALUE 0x7f
-#define UTMIP_XCVR_SETUP_MIN_VALUE 0
-#define XCVR_SETUP_MSB_CALIB(x) ((x) >> 4)
-
-#define UTMIP_BIAS_CFG0 0x80c
-#define UTMIP_OTGPD (1 << 11)
-#define UTMIP_BIASPD (1 << 10)
-
-#define UTMIP_HSRX_CFG0 0x810
-#define UTMIP_ELASTIC_LIMIT(x) (((x) & 0x1f) << 10)
-#define UTMIP_IDLE_WAIT(x) (((x) & 0x1f) << 15)
-
-#define UTMIP_HSRX_CFG1 0x814
-#define UTMIP_HS_SYNC_START_DLY(x) (((x) & 0x1f) << 1)
-
-#define UTMIP_TX_CFG0 0x820
-#define UTMIP_FS_PREABMLE_J (1 << 19)
-#define UTMIP_HS_DISCON_DISABLE (1 << 8)
-
-#define UTMIP_MISC_CFG1 0x828
-#define UTMIP_PLL_ACTIVE_DLY_COUNT(x) (((x) & 0x1f) << 18)
-#define UTMIP_PLLU_STABLE_COUNT(x) (((x) & 0xfff) << 6)
-
-#define UTMIP_DEBOUNCE_CFG0 0x82c
-#define UTMIP_BIAS_DEBOUNCE_A(x) (((x) & 0xffff) << 0)
-
-#define UTMIP_BAT_CHRG_CFG0 0x830
-#define UTMIP_PD_CHRG (1 << 0)
-#define UTMIP_ON_SINK_EN (1 << 2)
-#define UTMIP_OP_SRC_EN (1 << 3)
-
-#define UTMIP_XCVR_CFG1 0x838
-#define UTMIP_FORCE_PDDISC_POWERDOWN (1 << 0)
-#define UTMIP_FORCE_PDCHRP_POWERDOWN (1 << 2)
-#define UTMIP_FORCE_PDDR_POWERDOWN (1 << 4)
-#define UTMIP_XCVR_TERM_RANGE_ADJ(x) (((x) & 0xf) << 18)
-
-#define UTMIP_BIAS_CFG1 0x83c
-#define UTMIP_BIAS_PDTRK_COUNT(x) (((x) & 0x1f) << 3)
-
-#define UHSIC_PLL_CFG1 0x804
-#define UHSIC_XTAL_FREQ_COUNT(x) (((x) & 0xfff) << 0)
-#define UHSIC_PLLU_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 14)
-
-#define UHSIC_HSRX_CFG0 0x808
-#define UHSIC_ELASTIC_UNDERRUN_LIMIT(x) (((x) & 0x1f) << 2)
-#define UHSIC_ELASTIC_OVERRUN_LIMIT(x) (((x) & 0x1f) << 8)
-#define UHSIC_IDLE_WAIT(x) (((x) & 0x1f) << 13)
-
-#define UHSIC_HSRX_CFG1 0x80c
-#define UHSIC_HS_SYNC_START_DLY(x) (((x) & 0x1f) << 1)
-
-#define UHSIC_TX_CFG0 0x810
-#define UHSIC_HS_POSTAMBLE_OUTPUT_ENABLE (1 << 6)
-
-#define UHSIC_MISC_CFG0 0x814
-#define UHSIC_SUSPEND_EXIT_ON_EDGE (1 << 7)
-#define UHSIC_DETECT_SHORT_CONNECT (1 << 8)
-#define UHSIC_FORCE_XCVR_MODE (1 << 15)
-
-#define UHSIC_MISC_CFG1 0X818
-#define UHSIC_PLLU_STABLE_COUNT(x) (((x) & 0xfff) << 2)
-
-#define UHSIC_PADS_CFG0 0x81c
-#define UHSIC_TX_RTUNEN 0xf000
-#define UHSIC_TX_RTUNE(x) (((x) & 0xf) << 12)
-
-#define UHSIC_PADS_CFG1 0x820
-#define UHSIC_PD_BG (1 << 2)
-#define UHSIC_PD_TX (1 << 3)
-#define UHSIC_PD_TRK (1 << 4)
-#define UHSIC_PD_RX (1 << 5)
-#define UHSIC_PD_ZI (1 << 6)
-#define UHSIC_RX_SEL (1 << 7)
-#define UHSIC_RPD_DATA (1 << 9)
-#define UHSIC_RPD_STROBE (1 << 10)
-#define UHSIC_RPU_DATA (1 << 11)
-#define UHSIC_RPU_STROBE (1 << 12)
-
-#define UHSIC_STAT_CFG0 0x828
-#define UHSIC_CONNECT_DETECT (1 << 0)
-
-
-#else
-#define USB_USBCMD 0x130
-#define USB_USBCMD_RS (1 << 0)
-
-#define USB_USBSTS 0x134
-#define USB_USBSTS_PCI (1 << 2)
-#define USB_USBSTS_SRI (1 << 7)
-#define USB_USBSTS_HCH (1 << 12)
-
-#define USB_TXFILLTUNING 0x154
-#define USB_FIFO_TXFILL_THRES(x) (((x) & 0x1f) << 16)
-#define USB_FIFO_TXFILL_MASK 0x1f0000
-
-#define ULPI_VIEWPORT 0x160
-
-#define USB_PORTSC1 0x174
-#define USB_PORTSC1_WKOC (1 << 22)
-#define USB_PORTSC1_WKDS (1 << 21)
-#define USB_PORTSC1_WKCN (1 << 20)
-#define USB_PORTSC1_PTC(x) (((x) & 0xf) << 16)
-#define USB_PORTSC1_PP (1 << 12)
-#define USB_PORTSC1_LS(x) (((x) & 0x3) << 10)
-#define USB_PORTSC1_SUSP (1 << 7)
-#define USB_PORTSC1_RESUME (1 << 6)
-#define USB_PORTSC1_PE (1 << 2)
-#define USB_PORTSC1_CCS (1 << 0)
-
-#define USB_SUSP_CTRL 0x400
-#define USB_WAKE_ON_CNNT_EN_DEV (1 << 3)
-#define USB_WAKE_ON_DISCON_EN_DEV (1 << 4)
-#define USB_SUSP_CLR (1 << 5)
-#define USB_PHY_CLK_VALID (1 << 7)
-#define USB_PHY_CLK_VALID_INT_ENB (1 << 9)
-
-
-#define UTMIP_RESET (1 << 11)
-#define UTMIP_PHY_ENABLE (1 << 12)
-#define ULPI_PHY_ENABLE (1 << 13)
-#define UHSIC_RESET (1 << 14)
-
-#define USB_WAKEUP_DEBOUNCE_COUNT(x) (((x) & 0x7) << 16)
-#define UHSIC_PHY_ENABLE (1 << 19)
-#define ULPIS2S_SLV0_RESET (1 << 20)
-#define ULPIS2S_SLV1_RESET (1 << 21)
-#define ULPIS2S_LINE_RESET (1 << 22)
-#define ULPI_PADS_RESET (1 << 23)
-#define ULPI_PADS_CLKEN_RESET (1 << 24)
-
-#define USB_PHY_VBUS_WAKEUP_ID 0x408
-#define VDAT_DET_INT_EN (1 << 16)
-#define VDAT_DET_CHG_DET (1 << 17)
-#define VDAT_DET_STS (1 << 18)
-
-#define USB1_LEGACY_CTRL 0x410
-#define USB1_NO_LEGACY_MODE (1 << 0)
-#define USB1_VBUS_SENSE_CTL_MASK (3 << 1)
-#define USB1_VBUS_SENSE_CTL_VBUS_WAKEUP (0 << 1)
-#define USB1_VBUS_SENSE_CTL_AB_SESS_VLD_OR_VBUS_WAKEUP \
- (1 << 1)
-#define USB1_VBUS_SENSE_CTL_AB_SESS_VLD (2 << 1)
-#define USB1_VBUS_SENSE_CTL_A_SESS_VLD (3 << 1)
-
-#define UTMIP_PLL_CFG1 0x804
-#define UTMIP_XTAL_FREQ_COUNT(x) (((x) & 0xfff) << 0)
-#define UTMIP_PLLU_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 27)
-
-#define UTMIP_XCVR_CFG0 0x808
-#define UTMIP_XCVR_SETUP(x) (((x) & 0xf) << 0)
-#define UTMIP_XCVR_LSRSLEW(x) (((x) & 0x3) << 8)
-#define UTMIP_XCVR_LSFSLEW(x) (((x) & 0x3) << 10)
-#define UTMIP_FORCE_PD_POWERDOWN (1 << 14)
-#define UTMIP_FORCE_PD2_POWERDOWN (1 << 16)
-#define UTMIP_FORCE_PDZI_POWERDOWN (1 << 18)
-#define UTMIP_XCVR_LSBIAS_SEL (1 << 21)
-#define UTMIP_XCVR_SETUP_MSB(x) (((x) & 0x7) << 22)
-#define UTMIP_XCVR_HSSLEW_MSB(x) (((x) & 0x7f) << 25)
-
-#define UTMIP_XCVR_MAX_OFFSET 2
-#define UTMIP_XCVR_SETUP_MAX_VALUE 0x7f
-#define UTMIP_XCVR_SETUP_MIN_VALUE 0
-#define XCVR_SETUP_MSB_CALIB(x) ((x) >> 4)
-
-#define UTMIP_BIAS_CFG0 0x80c
-#define UTMIP_OTGPD (1 << 11)
-#define UTMIP_BIASPD (1 << 10)
-#define UTMIP_HSSQUELCH_LEVEL(x) (((x) & 0x3) << 0)
-#define UTMIP_HSDISCON_LEVEL(x) (((x) & 0x3) << 2)
-#define UTMIP_HSDISCON_LEVEL_MSB (1 << 24)
-
-#define UTMIP_HSRX_CFG0 0x810
-#define UTMIP_ELASTIC_LIMIT(x) (((x) & 0x1f) << 10)
-#define UTMIP_IDLE_WAIT(x) (((x) & 0x1f) << 15)
-
-#define UTMIP_HSRX_CFG1 0x814
-#define UTMIP_HS_SYNC_START_DLY(x) (((x) & 0x1f) << 1)
-
-#define UTMIP_TX_CFG0 0x820
-#define UTMIP_FS_PREABMLE_J (1 << 19)
-#define UTMIP_HS_DISCON_DISABLE (1 << 8)
-
-#define UTMIP_MISC_CFG1 0x828
-#define UTMIP_PLL_ACTIVE_DLY_COUNT(x) (((x) & 0x1f) << 18)
-#define UTMIP_PLLU_STABLE_COUNT(x) (((x) & 0xfff) << 6)
-
-#define UTMIP_DEBOUNCE_CFG0 0x82c
-#define UTMIP_BIAS_DEBOUNCE_A(x) (((x) & 0xffff) << 0)
-
-#define UTMIP_BAT_CHRG_CFG0 0x830
-#define UTMIP_PD_CHRG (1 << 0)
-#define UTMIP_ON_SINK_EN (1 << 2)
-#define UTMIP_OP_SRC_EN (1 << 3)
-
-#define UTMIP_XCVR_CFG1 0x838
-#define UTMIP_FORCE_PDDISC_POWERDOWN (1 << 0)
-#define UTMIP_FORCE_PDCHRP_POWERDOWN (1 << 2)
-#define UTMIP_FORCE_PDDR_POWERDOWN (1 << 4)
-#define UTMIP_XCVR_TERM_RANGE_ADJ(x) (((x) & 0xf) << 18)
-
-#define UTMIP_BIAS_CFG1 0x83c
-#define UTMIP_BIAS_PDTRK_COUNT(x) (((x) & 0x1f) << 3)
-#define UTMIP_BIAS_PDTRK_POWERDOWN (1 << 0)
-#define UTMIP_BIAS_PDTRK_POWERUP (1 << 1)
-
-#define HOSTPC1_DEVLC 0x1b4
-#define HOSTPC1_DEVLC_PHCD (1 << 22)
-#define HOSTPC1_DEVLC_PTS(x) (((x) & 0x7) << 29)
-#define HOSTPC1_DEVLC_PTS_MASK 7
-#define HOSTPC1_DEVLC_PTS_HSIC 4
-#define HOSTPC1_DEVLC_STS (1 << 28)
-#define HOSTPC1_DEVLC_PSPD(x) (((x) & 0x3) << 25)
-#define HOSTPC1_DEVLC_PSPD_MASK 3
-#define HOSTPC1_DEVLC_PSPD_HIGH_SPEED 2
-
-#define TEGRA_USB_USBMODE_REG_OFFSET 0x1f8
-#define TEGRA_USB_USBMODE_HOST (3 << 0)
-
-#define TEGRA_PMC_USB_AO 0xf0
-#define TEGRA_PMC_USB_AO_VBUS_WAKEUP_PD_P0 (1 << 2)
-#define TEGRA_PMC_USB_AO_ID_PD_P0 (1 << 3)
-#define TEGRA_PMC_USB_AO_PD_P2 (0xf << 8)
-
-#define ICUSB_CTRL 0x15c
-
-#define UHSIC_PLL_CFG1 0xc04
-#define UHSIC_XTAL_FREQ_COUNT(x) (((x) & 0xfff) << 0)
-#define UHSIC_PLLU_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 14)
-
-#define UHSIC_HSRX_CFG0 0xc08
-#define UHSIC_ELASTIC_UNDERRUN_LIMIT(x) (((x) & 0x1f) << 2)
-#define UHSIC_ELASTIC_OVERRUN_LIMIT(x) (((x) & 0x1f) << 8)
-#define UHSIC_IDLE_WAIT(x) (((x) & 0x1f) << 13)
-
-#define UHSIC_HSRX_CFG1 0xc0c
-#define UHSIC_HS_SYNC_START_DLY(x) (((x) & 0x1f) << 1)
-
-#define UHSIC_TX_CFG0 0xc10
-#define UHSIC_HS_READY_WAIT_FOR_VALID (1 << 9)
-
-#define UHSIC_MISC_CFG0 0xc14
-#define UHSIC_SUSPEND_EXIT_ON_EDGE (1 << 7)
-#define UHSIC_DETECT_SHORT_CONNECT (1 << 8)
-#define UHSIC_FORCE_XCVR_MODE (1 << 15)
-#define UHSIC_DISABLE_BUSRESET (1 << 20)
-
-#define UHSIC_MISC_CFG1 0xc18
-#define UHSIC_PLLU_STABLE_COUNT(x) (((x) & 0xfff) << 2)
-
-#define UHSIC_PADS_CFG0 0xc1c
-#define UHSIC_TX_RTUNEN 0xf000
-#define UHSIC_TX_RTUNE(x) (((x) & 0xf) << 12)
-
-#define UHSIC_PADS_CFG1 0xc20
-#define UHSIC_PD_BG (1 << 2)
-#define UHSIC_PD_TX (1 << 3)
-#define UHSIC_PD_TRK (1 << 4)
-#define UHSIC_PD_RX (1 << 5)
-#define UHSIC_PD_ZI (1 << 6)
-#define UHSIC_RX_SEL (1 << 7)
-#define UHSIC_RPD_DATA (1 << 9)
-#define UHSIC_RPD_STROBE (1 << 10)
-#define UHSIC_RPU_DATA (1 << 11)
-#define UHSIC_RPU_STROBE (1 << 12)
-
-#define UHSIC_STAT_CFG0 0xc28
-#define UHSIC_CONNECT_DETECT (1 << 0)
-
-#define PMC_UTMIP_MASTER_CONFIG 0x310
-#define UTMIP_PWR(inst) (1 << (inst))
-
-#define PMC_USB_DEBOUNCE 0xec
-#define UTMIP_LINE_DEB_CNT(x) (((x) & 0xf) << 16)
-
-#define PMC_UTMIP_UHSIC_FAKE 0x218
-#define USBON_VAL(inst) (1 << ((4*(inst))+1))
-#define USBON_VAL_P2 (1 << 9)
-#define USBON_VAL_P1 (1 << 5)
-#define USBON_VAL_P0 (1 << 1)
-#define USBOP_VAL(inst) (1 << (4*(inst)))
-#define USBOP_VAL_P2 (1 << 8)
-#define USBOP_VAL_P1 (1 << 4)
-#define USBOP_VAL_P0 (1 << 0)
-
-#define PMC_SLEEPWALK_CFG 0x200
-#define UTMIP_LINEVAL_WALK_EN(inst) (1 << ((8*(inst))+7))
-#define UTMIP_LINEVAL_WALK_EN_P2 (1 << 23)
-#define UTMIP_LINEVAL_WALK_EN_P1 (1 << 15)
-#define UTMIP_LINEVAL_WALK_EN_P0 (1 << 7)
-#define UTMIP_WAKE_VAL(inst, x) (((x) & 0xf) << ((8*(inst))+4))
-#define UTMIP_WAKE_VAL_P2(x) (((x) & 0xf) << 20)
-#define UTMIP_WAKE_VAL_P1(x) (((x) & 0xf) << 12)
-#define UTMIP_WAKE_VAL_P0(x) (((x) & 0xf) << 4)
-#define WAKE_VAL_NONE 0xc
-#define WAKE_VAL_FSJ 0x2
-#define WAKE_VAL_FSK 0x1
-#define WAKE_VAL_SE0 0x0
-#define WAKE_VAL_ANY 0xf
-
-#define PMC_SLEEP_CFG 0x1fc
-#define UTMIP_TCTRL_USE_PMC(inst) (1 << ((8*(inst))+3))
-#define UTMIP_TCTRL_USE_PMC_P2 (1 << 19)
-#define UTMIP_TCTRL_USE_PMC_P1 (1 << 11)
-#define UTMIP_TCTRL_USE_PMC_P0 (1 << 3)
-#define UTMIP_RCTRL_USE_PMC(inst) (1 << ((8*(inst))+2))
-#define UTMIP_RCTRL_USE_PMC_P2 (1 << 18)
-#define UTMIP_RCTRL_USE_PMC_P1 (1 << 10)
-#define UTMIP_RCTRL_USE_PMC_P0 (1 << 2)
-#define UTMIP_FSLS_USE_PMC(inst) (1 << ((8*(inst))+1))
-#define UTMIP_FSLS_USE_PMC_P2 (1 << 17)
-#define UTMIP_FSLS_USE_PMC_P1 (1 << 9)
-#define UTMIP_FSLS_USE_PMC_P0 (1 << 1)
-#define UTMIP_MASTER_ENABLE(inst) (1 << (8*(inst)))
-#define UTMIP_MASTER_ENABLE_P2 (1 << 16)
-#define UTMIP_MASTER_ENABLE_P1 (1 << 8)
-#define UTMIP_MASTER_ENABLE_P0 (1 << 0)
-#define UHSIC_MASTER_ENABLE_P0 (1 << 24)
-#define UHSIC_WAKE_VAL_P0(x) (((x) & 0xf) << 28)
-
-#define PMC_USB_AO 0xf0
-#define PMC_POWER_DOWN_MASK 0xffff
-#define HSIC_RESERVED_P0 (3 << 14)
-#define HSIC_STOBE_VAL_PD_P0 (1 << 13)
-#define HSIC_DATA_VAL_PD_P0 (1 << 12)
-#define USB_ID_PD(inst) (1 << ((4*(inst))+3))
-#define VBUS_WAKEUP_PD(inst) (1 << ((4*(inst))+2))
-#define USBON_VAL_PD(inst) (1 << ((4*(inst))+1))
-#define USBON_VAL_PD_P2 (1 << 9)
-#define USBON_VAL_PD_P1 (1 << 5)
-#define USBON_VAL_PD_P0 (1 << 1)
-#define USBOP_VAL_PD(inst) (1 << (4*(inst)))
-#define USBOP_VAL_PD_P2 (1 << 8)
-#define USBOP_VAL_PD_P1 (1 << 4)
-#define USBOP_VAL_PD_P0 (1 << 0)
-
-#define PMC_TRIGGERS 0x1ec
-#define UTMIP_CLR_WALK_PTR(inst) (1 << (inst))
-#define UTMIP_CLR_WALK_PTR_P2 (1 << 2)
-#define UTMIP_CLR_WALK_PTR_P1 (1 << 1)
-#define UTMIP_CLR_WALK_PTR_P0 (1 << 0)
-#define UTMIP_CAP_CFG(inst) (1 << ((inst)+4))
-#define UTMIP_CAP_CFG_P2 (1 << 6)
-#define UTMIP_CAP_CFG_P1 (1 << 5)
-#define UTMIP_CAP_CFG_P0 (1 << 4)
-#define UTMIP_CLR_WAKE_ALARM(inst) (1 << ((inst)+12))
-#define UTMIP_CLR_WAKE_ALARM_P2 (1 << 14)
-
-#define PMC_PAD_CFG (0x1f4)
-
-#define PMC_UTMIP_BIAS_MASTER_CNTRL 0x30c
-#define BIAS_MASTER_PROG_VAL (1 << 1)
-
-#define PMC_SLEEPWALK_REG(inst) (0x204 + (4*(inst)))
-#define PMC_SLEEPWALK_P0 0x204
-#define PMC_SLEEPWALK_P1 0x208
-#define PMC_SLEEPWALK_P2 0x20c
-#define UTMIP_USBOP_RPD_A (1 << 0)
-#define UTMIP_USBON_RPD_A (1 << 1)
-#define UTMIP_AP_A (1 << 4)
-#define UTMIP_AN_A (1 << 5)
-#define UTMIP_HIGHZ_A (1 << 6)
-#define UTMIP_USBOP_RPD_B (1 << 8)
-#define UTMIP_USBON_RPD_B (1 << 9)
-#define UTMIP_AP_B (1 << 12)
-#define UTMIP_AN_B (1 << 13)
-#define UTMIP_HIGHZ_B (1 << 14)
-#define UTMIP_USBOP_RPD_C (1 << 16)
-#define UTMIP_USBON_RPD_C (1 << 17)
-#define UTMIP_AP_C (1 << 20)
-#define UTMIP_AN_C (1 << 21)
-#define UTMIP_HIGHZ_C (1 << 22)
-#define UTMIP_USBOP_RPD_D (1 << 24)
-#define UTMIP_USBON_RPD_D (1 << 25)
-#define UTMIP_AP_D (1 << 28)
-#define UTMIP_AN_D (1 << 29)
-#define UTMIP_HIGHZ_D (1 << 30)
-
-#define UTMIP_PMC_WAKEUP0 0x84c
-#define EVENT_INT_ENB (1 << 0)
-
-#define UTMIP_UHSIC_STATUS 0x214
-#define UTMIP_WALK_PTR_VAL(inst) (0x3 << ((inst)*2))
-#define UTMIP_USBOP_VAL(inst) (1 << ((2*(inst)) + 8))
-#define UTMIP_USBOP_VAL_P2 (1 << 12)
-#define UTMIP_USBOP_VAL_P1 (1 << 10)
-#define UTMIP_USBOP_VAL_P0 (1 << 8)
-#define UTMIP_USBON_VAL(inst) (1 << ((2*(inst)) + 9))
-#define UTMIP_USBON_VAL_P2 (1 << 13)
-#define UTMIP_USBON_VAL_P1 (1 << 11)
-#define UTMIP_USBON_VAL_P0 (1 << 9)
-#define UTMIP_WAKE_ALARM(inst) (1 << ((inst) + 16))
-#define UTMIP_WAKE_ALARM_P2 (1 << 18)
-#define UTMIP_WAKE_ALARM_P1 (1 << 17)
-#define UTMIP_WAKE_ALARM_P0 (1 << 16)
-#define UTMIP_WALK_PTR(inst) (1 << ((inst)*2))
-#define UTMIP_WALK_PTR_P2 (1 << 4)
-#define UTMIP_WALK_PTR_P1 (1 << 2)
-#define UTMIP_WALK_PTR_P0 (1 << 0)
-
-#define UTMIP_BIAS_STS0 0x840
-#define UTMIP_RCTRL_VAL(x) (((x) & 0xffff) << 0)
-#define UTMIP_TCTRL_VAL(x) (((x) & (0xffff << 16)) >> 16)
-
-#define PMC_UTMIP_TERM_PAD_CFG 0x1f8
-#define PMC_TCTRL_VAL(x) (((x) & 0x1f) << 5)
-#define PMC_RCTRL_VAL(x) (((x) & 0x1f) << 0)
-
-#define UHSIC_SLEEPWALK_REG 0x210
-#define UHSIC_DATA_RPD_D (1 << 25)
-#define UHSIC_STRB_RPD_D (1 << 24)
-#define UHSIC_DATA_RPD_C (1 << 17)
-#define UHSIC_STRB_RPD_C (1 << 16)
-#define UHSIC_DATA_RPD_B (1 << 9)
-#define UHSIC_STRB_RPD_B (1 << 8)
-#define UHSIC_DATA_RPD_A (1 << 1)
-#define UHSIC_STRB_RPD_A (1 << 0)
-
-static u32 utmip_rctrl_val, utmip_tctrl_val;
-
-#endif
-
-/* Common registers */
-#define UTMIP_MISC_CFG0 0x824
-#define UTMIP_DPDM_OBSERVE (1 << 26)
-#define UTMIP_DPDM_OBSERVE_SEL(x) (((x) & 0xf) << 27)
-#define UTMIP_DPDM_OBSERVE_SEL_FS_J UTMIP_DPDM_OBSERVE_SEL(0xf)
-#define UTMIP_DPDM_OBSERVE_SEL_FS_K UTMIP_DPDM_OBSERVE_SEL(0xe)
-#define UTMIP_DPDM_OBSERVE_SEL_FS_SE1 UTMIP_DPDM_OBSERVE_SEL(0xd)
-#define UTMIP_DPDM_OBSERVE_SEL_FS_SE0 UTMIP_DPDM_OBSERVE_SEL(0xc)
-#define UTMIP_SUSPEND_EXIT_ON_EDGE (1 << 22)
-#define FORCE_PULLDN_DM (1 << 8)
-#define FORCE_PULLDN_DP (1 << 9)
-#define COMB_TERMS (1 << 0)
-#define ALWAYS_FREE_RUNNING_TERMS (1 << 1)
-
-#define ULPIS2S_CTRL 0x418
-#define ULPIS2S_ENA (1 << 0)
-#define ULPIS2S_SUPPORT_DISCONNECT (1 << 2)
-#define ULPIS2S_PLLU_MASTER_BLASTER60 (1 << 3)
-#define ULPIS2S_SPARE(x) (((x) & 0xF) << 8)
-#define ULPIS2S_FORCE_ULPI_CLK_OUT (1 << 12)
-#define ULPIS2S_DISCON_DONT_CHECK_SE0 (1 << 13)
-#define ULPIS2S_SUPPORT_HS_KEEP_ALIVE (1 << 14)
-#define ULPIS2S_DISABLE_STP_PU (1 << 15)
-#define ULPIS2S_SLV0_CLAMP_XMIT (1 << 16)
-
-
-#define ULPI_TIMING_CTRL_0 0x424
-#define ULPI_CLOCK_OUT_DELAY(x) ((x) & 0x1F)
-#define ULPI_OUTPUT_PINMUX_BYP (1 << 10)
-#define ULPI_CLKOUT_PINMUX_BYP (1 << 11)
-#define ULPI_SHADOW_CLK_LOOPBACK_EN (1 << 12)
-#define ULPI_SHADOW_CLK_SEL (1 << 13)
-#define ULPI_CORE_CLK_SEL (1 << 14)
-#define ULPI_SHADOW_CLK_DELAY(x) (((x) & 0x1F) << 16)
-#define ULPI_LBK_PAD_EN (1 << 26)
-#define ULPI_LBK_PAD_E_INPUT_OR (1 << 27)
-#define ULPI_CLK_OUT_ENA (1 << 28)
-#define ULPI_CLK_PADOUT_ENA (1 << 29)
-
-#define ULPI_TIMING_CTRL_1 0x428
-#define ULPI_DATA_TRIMMER_LOAD (1 << 0)
-#define ULPI_DATA_TRIMMER_SEL(x) (((x) & 0x7) << 1)
-#define ULPI_STPDIRNXT_TRIMMER_LOAD (1 << 16)
-#define ULPI_STPDIRNXT_TRIMMER_SEL(x) (((x) & 0x7) << 17)
-#define ULPI_DIR_TRIMMER_LOAD (1 << 24)
-#define ULPI_DIR_TRIMMER_SEL(x) (((x) & 0x7) << 25)
-
-#define UTMIP_SPARE_CFG0 0x834
-#define FUSE_SETUP_SEL (1 << 3)
-#define FUSE_ATERM_SEL (1 << 4)
-
-#define FUSE_USB_CALIB_0 0x1F0
-#define FUSE_USB_CALIB_XCVR_SETUP(x) (((x) & 0x7F) << 0)
-
-#define UHSIC_PLL_CFG0 0x800
-
-#define UHSIC_CMD_CFG0 0x824
-#define UHSIC_PRETEND_CONNECT_DETECT (1 << 5)
-
-#define UHSIC_SPARE_CFG0 0x82c
-
-/* These values (in milli second) are taken from the battery charging spec */
-#define TDP_SRC_ON_MS 100
-#define TDPSRC_CON_MS 40
-
-#define CONNECT_DETECT_TIMEOUT 25000
+#define ERR(stuff...) pr_err("usb_phy: " stuff)
+#define WARNING(stuff...) pr_warning("usb_phy: " stuff)
+#define INFO(stuff...) pr_info("usb_phy: " stuff)
#define AHB_MEM_PREFETCH_CFG3 0xe0
#define AHB_MEM_PREFETCH_CFG4 0xe4
@@ -610,2615 +44,654 @@ static u32 utmip_rctrl_val, utmip_tctrl_val;
#define AHB_MEM_PREFETCH_CFG2 0xf0
#define PREFETCH_ENB (1 << 31)
-static DEFINE_SPINLOCK(utmip_pad_lock);
-static int utmip_pad_count;
-
-struct tegra_xtal_freq {
- int freq;
- u8 enable_delay;
- u8 stable_count;
- u8 active_delay;
- u16 xtal_freq_count;
- u16 debounce;
- u8 pdtrk_count;
-};
-
-static const struct tegra_xtal_freq tegra_freq_table[] = {
- {
- .freq = 12000000,
- .enable_delay = 0x02,
- .stable_count = 0x2F,
- .active_delay = 0x04,
- .xtal_freq_count = 0x76,
- .debounce = 0x7530,
- .pdtrk_count = 5,
- },
- {
- .freq = 13000000,
- .enable_delay = 0x02,
- .stable_count = 0x33,
- .active_delay = 0x05,
- .xtal_freq_count = 0x7F,
- .debounce = 0x7EF4,
- .pdtrk_count = 5,
- },
- {
- .freq = 19200000,
- .enable_delay = 0x03,
- .stable_count = 0x4B,
- .active_delay = 0x06,
- .xtal_freq_count = 0xBB,
- .debounce = 0xBB80,
- .pdtrk_count = 7,
- },
- {
- .freq = 26000000,
- .enable_delay = 0x04,
- .stable_count = 0x66,
- .active_delay = 0x09,
- .xtal_freq_count = 0xFE,
- .debounce = 0xFDE8,
- .pdtrk_count = 9,
- },
-};
-
-static const struct tegra_xtal_freq tegra_uhsic_freq_table[] = {
- {
- .freq = 12000000,
- .enable_delay = 0x02,
- .stable_count = 0x2F,
- .active_delay = 0x0,
- .xtal_freq_count = 0x1CA,
- },
- {
- .freq = 13000000,
- .enable_delay = 0x02,
- .stable_count = 0x33,
- .active_delay = 0x0,
- .xtal_freq_count = 0x1F0,
- },
- {
- .freq = 19200000,
- .enable_delay = 0x03,
- .stable_count = 0x4B,
- .active_delay = 0x0,
- .xtal_freq_count = 0x2DD,
- },
- {
- .freq = 26000000,
- .enable_delay = 0x04,
- .stable_count = 0x66,
- .active_delay = 0x0,
- .xtal_freq_count = 0x3E0,
- },
-};
-
-static struct tegra_utmip_config utmip_default[] = {
- [0] = {
- .hssync_start_delay = 9,
- .idle_wait_delay = 17,
- .elastic_limit = 16,
- .term_range_adj = 6,
- .xcvr_setup = 9,
- .xcvr_setup_offset = 0,
- .xcvr_use_fuses = 1,
- .xcvr_lsfslew = 2,
- .xcvr_lsrslew = 2,
- },
- [2] = {
- .hssync_start_delay = 9,
- .idle_wait_delay = 17,
- .elastic_limit = 16,
- .term_range_adj = 6,
- .xcvr_setup_offset = 0,
- .xcvr_use_fuses = 1,
- .xcvr_setup = 9,
- .xcvr_lsfslew = 2,
- .xcvr_lsrslew = 2,
- },
-};
-
-struct usb_phy_plat_data usb_phy_data[] = {
- { 0, 0, -1, (int)NULL},
- { 0, 0, -1, (int)NULL},
- { 0, 0, -1, (int)NULL},
-};
-
-static int utmip_pad_open(struct tegra_usb_phy *phy)
+#ifdef DEBUG
+#define DBG(stuff...) pr_info("usb_phy: " stuff)
+#else
+#define DBG(stuff...) do {} while (0)
+#endif
+
+static void print_usb_plat_data_info(struct tegra_usb_phy *phy)
{
- phy->pad_clk = clk_get_sys("utmip-pad", NULL);
- if (IS_ERR(phy->pad_clk)) {
- pr_err("%s: can't get utmip pad clock\n", __func__);
- return PTR_ERR(phy->pad_clk);
- }
+ struct tegra_usb_platform_data *pdata = phy->pdata;
+ char op_mode[][50] = {
+ "TEGRA_USB_OPMODE_DEVICE",
+ "TEGRA_USB_OPMODE_HOST"
+ };
+ char phy_intf[][50] = {
+ "USB_PHY_INTF_UTMI",
+ "USB_PHY_INTF_ULPI_LINK",
+ "USB_PHY_INTF_ULPI_NULL",
+ "USB_PHY_INTF_HSIC",
+ "USB_PHY_INTF_ICUSB"
+ };
- if (phy->instance == 0) {
- phy->pad_regs = phy->regs;
+ pr_info("tegra USB phy - inst[%d] platform info:\n", phy->inst);
+ pr_info("port_otg: %s\n", pdata->port_otg ? "yes" : "no");
+ pr_info("has_hostpc: %s\n", pdata->has_hostpc ? "yes" : "no");
+ pr_info("phy_interface: %s\n", phy_intf[pdata->phy_intf]);
+ pr_info("op_mode: %s\n", op_mode[pdata->op_mode]);
+ if (pdata->op_mode == TEGRA_USB_OPMODE_DEVICE) {
+ pr_info("vbus_pmu_irq: %d\n", pdata->u_data.dev.vbus_pmu_irq);
+ pr_info("vbus_gpio: %d\n", pdata->u_data.dev.vbus_gpio);
+ pr_info("charging: %s\n", pdata->u_data.dev.charging_supported ?
+ "enabled" : "disabled");
+ pr_info("remote_wakeup: %s\n", pdata->u_data.dev.remote_wakeup_supported
+ ? "enabled" : "disabled");
} else {
- phy->pad_regs = ioremap(TEGRA_USB_BASE, TEGRA_USB_SIZE);
- if (!phy->pad_regs) {
- pr_err("%s: can't remap usb registers\n", __func__);
- clk_put(phy->pad_clk);
- return -ENOMEM;
- }
+ pr_info("vbus_gpio: %d\n", pdata->u_data.host.vbus_gpio);
+ pr_info("vbus_gpio_inverted: %d\n", pdata->u_data.host.vbus_gpio_inverted);
+ pr_info("vbus_reg: %s\n", pdata->u_data.host.vbus_reg ?
+ pdata->u_data.host.vbus_reg : "NULL");
+ pr_info("hot_plug: %s\n", pdata->u_data.host.hot_plug ?
+ "enabled" : "disabled");
+ pr_info("remote_wakeup: %s\n", pdata->u_data.host.remote_wakeup_supported
+ ? "enabled" : "disabled");
}
- return 0;
-}
-
-static void utmip_pad_close(struct tegra_usb_phy *phy)
-{
- if (phy->instance != 0)
- iounmap(phy->pad_regs);
- clk_put(phy->pad_clk);
}
-static int utmip_pad_power_on(struct tegra_usb_phy *phy)
+static void usb_host_vbus_enable(struct tegra_usb_phy *phy, bool enable)
{
- unsigned long val, flags;
- void __iomem *base = phy->pad_regs;
-
- clk_enable(phy->pad_clk);
-
- spin_lock_irqsave(&utmip_pad_lock, flags);
-
- utmip_pad_count++;
- val = readl(base + UTMIP_BIAS_CFG0);
- val &= ~(UTMIP_OTGPD | UTMIP_BIASPD);
-#ifndef CONFIG_ARCH_TEGRA_2x_SOC
- val |= UTMIP_HSSQUELCH_LEVEL(0x2) | UTMIP_HSDISCON_LEVEL(0x1) |
- UTMIP_HSDISCON_LEVEL_MSB;
-#endif
- writel(val, base + UTMIP_BIAS_CFG0);
-
- spin_unlock_irqrestore(&utmip_pad_lock, flags);
-
- clk_disable(phy->pad_clk);
-
- return 0;
-}
-
-static int utmip_pad_power_off(struct tegra_usb_phy *phy, bool is_dpd)
-{
- unsigned long val, flags;
- void __iomem *base = phy->pad_regs;
-
- if (!utmip_pad_count) {
- pr_err("%s: utmip pad already powered off\n", __func__);
- return -EINVAL;
- }
-
- clk_enable(phy->pad_clk);
-
- spin_lock_irqsave(&utmip_pad_lock, flags);
-
- if (--utmip_pad_count == 0 && is_dpd) {
- val = readl(base + UTMIP_BIAS_CFG0);
- val |= UTMIP_OTGPD | UTMIP_BIASPD;
-#ifndef CONFIG_ARCH_TEGRA_2x_SOC
- val &= ~(UTMIP_HSSQUELCH_LEVEL(~0) | UTMIP_HSDISCON_LEVEL(~0) |
- UTMIP_HSDISCON_LEVEL_MSB);
-#endif
- writel(val, base + UTMIP_BIAS_CFG0);
+ if (phy->vbus_reg) {
+ if (enable)
+ regulator_enable(phy->vbus_reg);
+ else
+ regulator_disable(phy->vbus_reg);
+ } else {
+ int gpio = phy->pdata->u_data.host.vbus_gpio;
+ if (gpio == -1)
+ return;
+ gpio_set_value_cansleep(gpio, (enable != phy->pdata->u_data.host.vbus_gpio_inverted)? 1 : 0);
}
-
- spin_unlock_irqrestore(&utmip_pad_lock, flags);
-
- clk_disable(phy->pad_clk);
-
- return 0;
}
-static int utmi_wait_register(void __iomem *reg, u32 mask, u32 result)
+int usb_phy_reg_status_wait(void __iomem *reg, u32 mask,
+ u32 result, u32 timeout)
{
- unsigned long timeout = 2500;
do {
if ((readl(reg) & mask) == result)
return 0;
udelay(1);
timeout--;
} while (timeout);
- return -1;
-}
-static int utmi_wait_register_timeout(void __iomem *reg, u32 mask, u32 result,
- unsigned long timeout)
-{
- do {
- if ((readl(reg) & mask) == result)
- return 0;
- udelay(1);
- timeout--;
- } while (timeout);
return -1;
}
-static void utmi_phy_clk_disable(struct tegra_usb_phy *phy)
+static int tegra_usb_phy_init_ops(struct tegra_usb_phy *phy)
{
- unsigned long val;
- void __iomem *base = phy->regs;
+ int err = 0;
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- if (phy->instance == 0) {
- val = readl(base + USB_SUSP_CTRL);
- val |= USB_SUSP_SET;
- writel(val, base + USB_SUSP_CTRL);
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
- udelay(10);
-
- val = readl(base + USB_SUSP_CTRL);
- val &= ~USB_SUSP_SET;
- writel(val, base + USB_SUSP_CTRL);
- }
-
- if (phy->instance == 2) {
- val = readl(base + USB_PORTSC1);
- val |= USB_PORTSC1_PHCD;
- writel(val, base + USB_PORTSC1);
- }
-#else
- val = readl(base + HOSTPC1_DEVLC);
- val |= HOSTPC1_DEVLC_PHCD;
- writel(val, base + HOSTPC1_DEVLC);
-#endif
- if (phy->hotplug) {
- val = readl(base + USB_SUSP_CTRL);
- val |= USB_PHY_CLK_VALID_INT_ENB;
- writel(val, base + USB_SUSP_CTRL);
- } else {
- val = readl(base + USB_SUSP_CTRL);
- val |= UTMIP_RESET;
- writel(val, base + USB_SUSP_CTRL);
- }
+ if (phy->pdata->has_hostpc)
+ err = tegra3_usb_phy_init_ops(phy);
+ else
+ err = tegra2_usb_phy_init_ops(phy);
- if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, 0) < 0)
- pr_err("%s: timeout waiting for phy to stabilize\n", __func__);
+ return err;
}
-static void utmi_phy_clk_enable(struct tegra_usb_phy *phy)
+static irqreturn_t usb_phy_dev_vbus_pmu_irq_thr(int irq, void *pdata)
{
- unsigned long val;
- void __iomem *base = phy->regs;
-
- if (phy->instance == 0) {
- val = readl(base + USB_SUSP_CTRL);
- val |= USB_SUSP_CLR;
- writel(val, base + USB_SUSP_CTRL);
-
- udelay(10);
+ struct tegra_usb_phy *phy = pdata;
- val = readl(base + USB_SUSP_CTRL);
- val &= ~USB_SUSP_CLR;
- writel(val, base + USB_SUSP_CTRL);
+ if (phy->vdd_reg && !phy->vdd_reg_on) {
+ regulator_enable(phy->vdd_reg);
+ phy->vdd_reg_on = 1;
+ /*
+ * Optimal time to get the regulator turned on
+ * before detecting vbus interrupt.
+ */
+ mdelay(15);
}
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- if (phy->instance == 2) {
- val = readl(base + USB_PORTSC1);
- val &= ~USB_PORTSC1_PHCD;
- writel(val, base + USB_PORTSC1);
+ /* clk is disabled during phy power off and not here*/
+ if (!phy->ctrl_clk_on) {
+ clk_enable(phy->ctrlr_clk);
+ phy->ctrl_clk_on = true;
}
-#endif
-
- if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID,
- USB_PHY_CLK_VALID) < 0)
- pr_err("%s: timeout waiting for phy to stabilize\n", __func__);
-}
-static void vbus_enable(struct tegra_usb_phy *phy)
-{
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- int gpio_status;
- int gpio = usb_phy_data[phy->instance].vbus_gpio;
- int gpio_inverted = usb_phy_data[phy->instance].vbus_gpio_inverted;
-
- if (gpio == -1)
- return;
-
- gpio_status = gpio_request(gpio,"VBUS_USB");
- if (gpio_status < 0) {
- printk("VBUS_USB request GPIO FAILED\n");
- WARN_ON(1);
- return;
- }
- if (gpio < TEGRA_NR_GPIOS) tegra_gpio_enable(gpio);
- gpio_status = gpio_direction_output(gpio, !gpio_inverted);
- if (gpio_status < 0) {
- printk("VBUS_USB request GPIO DIRECTION FAILED \n");
- WARN_ON(1);
- return;
- }
- gpio_set_value_cansleep(gpio, !gpio_inverted);
-#else
- if (phy->reg_vbus)
- regulator_enable(phy->reg_vbus);
-#endif
-}
-
-static void vbus_disable(struct tegra_usb_phy *phy)
-{
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- int gpio = usb_phy_data[phy->instance].vbus_gpio;
- int gpio_inverted = usb_phy_data[phy->instance].vbus_gpio_inverted;
-
- if (gpio == -1)
- return;
-
- gpio_set_value_cansleep(gpio, gpio_inverted);
- gpio_free(gpio);
-#else
- if (phy->reg_vbus)
- regulator_disable(phy->reg_vbus);
-#endif
-}
-
-#ifndef CONFIG_ARCH_TEGRA_2x_SOC
-static void utmip_phy_enable_trking_data(struct tegra_usb_phy *phy)
-{
- void __iomem *base = phy->pad_regs;
- void __iomem *pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
- static bool init_done = false;
- u32 val;
-
- /* Should be done only once after system boot */
- if (init_done)
- return;
-
- clk_enable(phy->pad_clk);
- /* Bias pad MASTER_ENABLE=1 */
- val = readl(pmc_base + PMC_UTMIP_BIAS_MASTER_CNTRL);
- val |= BIAS_MASTER_PROG_VAL;
- writel(val, pmc_base + PMC_UTMIP_BIAS_MASTER_CNTRL);
-
- /* Setting the tracking length time */
- val = readl(base + UTMIP_BIAS_CFG1);
- val &= ~UTMIP_BIAS_PDTRK_COUNT(~0);
- val |= UTMIP_BIAS_PDTRK_COUNT(5);
- writel(val, base + UTMIP_BIAS_CFG1);
-
- /* Bias PDTRK is Shared and MUST be done from USB1 ONLY, PD_TRK=0 */
- val = readl(base + UTMIP_BIAS_CFG1);
- val &= ~ UTMIP_BIAS_PDTRK_POWERDOWN;
- writel(val, base + UTMIP_BIAS_CFG1);
-
- val = readl(base + UTMIP_BIAS_CFG1);
- val |= UTMIP_BIAS_PDTRK_POWERUP;
- writel(val, base + UTMIP_BIAS_CFG1);
-
- /* Wait for 25usec */
- udelay(25);
-
- /* Bias pad MASTER_ENABLE=0 */
- val = readl(pmc_base + PMC_UTMIP_BIAS_MASTER_CNTRL);
- val &= ~BIAS_MASTER_PROG_VAL;
- writel(val, pmc_base + PMC_UTMIP_BIAS_MASTER_CNTRL);
-
- /* Wait for 1usec */
- udelay(1);
-
- /* Bias pad MASTER_ENABLE=1 */
- val = readl(pmc_base + PMC_UTMIP_BIAS_MASTER_CNTRL);
- val |= BIAS_MASTER_PROG_VAL;
- writel(val, pmc_base + PMC_UTMIP_BIAS_MASTER_CNTRL);
-
- /* Read RCTRL and TCTRL from UTMIP space */
- val = readl(base + UTMIP_BIAS_STS0);
- utmip_rctrl_val = ffz(UTMIP_RCTRL_VAL(val));
- utmip_tctrl_val = ffz(UTMIP_TCTRL_VAL(val));
-
- /* PD_TRK=1 */
- val = readl(base + UTMIP_BIAS_CFG1);
- val |= UTMIP_BIAS_PDTRK_POWERDOWN;
- writel(val, base + UTMIP_BIAS_CFG1);
-
- /* Program thermally encoded RCTRL_VAL, TCTRL_VAL into PMC space */
- val = readl(pmc_base + PMC_UTMIP_TERM_PAD_CFG);
- val = PMC_TCTRL_VAL(utmip_tctrl_val) | PMC_RCTRL_VAL(utmip_rctrl_val);
- writel(val, pmc_base + PMC_UTMIP_TERM_PAD_CFG);
- clk_disable(phy->pad_clk);
- init_done = true;
-}
-
-static void utmip_powerdown_pmc_wake_detect(struct tegra_usb_phy *phy)
-{
- unsigned long val;
- void __iomem *pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
- unsigned int inst = phy->instance;
-
- /* power down UTMIP interfaces */
- val = readl(pmc_base + PMC_UTMIP_MASTER_CONFIG);
- val |= UTMIP_PWR(inst);
- writel(val, pmc_base + PMC_UTMIP_MASTER_CONFIG);
-
- /* setup sleep walk usb controller */
- val = UTMIP_USBOP_RPD_A | UTMIP_USBON_RPD_A | UTMIP_HIGHZ_A |
- UTMIP_USBOP_RPD_B | UTMIP_USBON_RPD_B | UTMIP_HIGHZ_B |
- UTMIP_USBOP_RPD_C | UTMIP_USBON_RPD_C | UTMIP_HIGHZ_C |
- UTMIP_USBOP_RPD_D | UTMIP_USBON_RPD_D | UTMIP_HIGHZ_D;
- writel(val, pmc_base + PMC_SLEEPWALK_REG(inst));
-
- /* Program thermally encoded RCTRL_VAL, TCTRL_VAL into PMC space */
- val = readl(pmc_base + PMC_UTMIP_TERM_PAD_CFG);
- val = PMC_TCTRL_VAL(utmip_tctrl_val) | PMC_RCTRL_VAL(utmip_rctrl_val);
- writel(val, pmc_base + PMC_UTMIP_TERM_PAD_CFG);
-
- /* Turn over pad configuration to PMC */
- val = readl(pmc_base + PMC_SLEEP_CFG);
- val &= ~UTMIP_WAKE_VAL(inst, ~0);
- val |= UTMIP_WAKE_VAL(inst, WAKE_VAL_NONE) |
- UTMIP_RCTRL_USE_PMC(inst) | UTMIP_TCTRL_USE_PMC(inst) |
- UTMIP_FSLS_USE_PMC(inst) | UTMIP_MASTER_ENABLE(inst);
- writel(val, pmc_base + PMC_SLEEP_CFG);
-}
-
-static void utmip_powerup_pmc_wake_detect(struct tegra_usb_phy *phy)
-{
- unsigned long val;
- void __iomem *pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
- unsigned int inst = phy->instance;
-
- /* Disable PMC master mode by clearing MASTER_EN */
- val = readl(pmc_base + PMC_SLEEP_CFG);
- val &= ~(UTMIP_RCTRL_USE_PMC(inst) | UTMIP_TCTRL_USE_PMC(inst) |
- UTMIP_FSLS_USE_PMC(inst) | UTMIP_MASTER_ENABLE(inst));
- writel(val, pmc_base + PMC_SLEEP_CFG);
- 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);
-
- /* turn on pad detectors for HSIC*/
- val = readl(pmc_base + PMC_USB_AO);
- val |= (HSIC_RESERVED_P0 | HSIC_STOBE_VAL_PD_P0 | HSIC_DATA_VAL_PD_P0);
- writel(val, pmc_base + PMC_USB_AO);
-
- /* enable pull downs on HSIC PMC */
- val = UHSIC_STRB_RPD_A | UHSIC_DATA_RPD_A | UHSIC_STRB_RPD_B |
- UHSIC_DATA_RPD_B | UHSIC_STRB_RPD_C | UHSIC_DATA_RPD_C |
- UHSIC_STRB_RPD_D | UHSIC_DATA_RPD_D;
- writel(val, pmc_base + UHSIC_SLEEPWALK_REG);
-
- /* 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_powerup_pmc_wake_detect(struct tegra_usb_phy *phy)
-{
- unsigned long val;
- void __iomem *pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
-
- /* turn on pad detectors for HSIC*/
- val = readl(pmc_base + PMC_USB_AO);
- val &= ~(HSIC_RESERVED_P0 | HSIC_STOBE_VAL_PD_P0 | HSIC_DATA_VAL_PD_P0);
- writel(val, pmc_base + PMC_USB_AO);
-
- /* Disable PMC master mode by clearing MASTER_EN */
- val = readl(pmc_base + PMC_SLEEP_CFG);
- val &= ~(UHSIC_MASTER_ENABLE_P0);
- writel(val, pmc_base + PMC_SLEEP_CFG);
- mdelay(1);
+ return IRQ_HANDLED;
}
-#endif
-static unsigned int tegra_phy_xcvr_setup_value(struct tegra_utmip_config *cfg)
+static void tegra_usb_phy_release_clocks(struct tegra_usb_phy *phy)
{
- signed long val;
-
- if (cfg->xcvr_use_fuses) {
- val = FUSE_USB_CALIB_XCVR_SETUP(
- tegra_fuse_readl(FUSE_USB_CALIB_0));
- if (cfg->xcvr_setup_offset <= UTMIP_XCVR_MAX_OFFSET)
- val = val + cfg->xcvr_setup_offset;
-
- if (val > UTMIP_XCVR_SETUP_MAX_VALUE) {
- val = UTMIP_XCVR_SETUP_MAX_VALUE;
- pr_info("%s: reset XCVR_SETUP to max value\n",
- __func__);
- } else if (val < UTMIP_XCVR_SETUP_MIN_VALUE) {
- val = UTMIP_XCVR_SETUP_MIN_VALUE;
- pr_info("%s: reset XCVR_SETUP to min value\n",
- __func__);
- }
- } else {
- val = cfg->xcvr_setup;
- }
-
- return (unsigned int)val;
+ clk_put(phy->emc_clk);
+ clk_put(phy->sys_clk);
+ if (phy->pdata->op_mode == TEGRA_USB_OPMODE_HOST)
+ if (phy->pdata->u_data.host.hot_plug ||
+ phy->pdata->u_data.host.remote_wakeup_supported)
+ clk_disable(phy->ctrlr_clk);
+ clk_put(phy->ctrlr_clk);
+ clk_disable(phy->pllu_clk);
+ clk_put(phy->pllu_clk);
}
-static int utmi_phy_power_on(struct tegra_usb_phy *phy, bool is_dpd)
+static int tegra_usb_phy_get_clocks(struct tegra_usb_phy *phy)
{
- unsigned long val;
- void __iomem *base = phy->regs;
- unsigned int xcvr_setup_value;
- struct tegra_utmip_config *config = phy->config;
-
- val = readl(base + USB_SUSP_CTRL);
- val |= UTMIP_RESET;
- writel(val, base + USB_SUSP_CTRL);
-
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- if (phy->instance == 0) {
- val = readl(base + USB1_LEGACY_CTRL);
- val |= USB1_NO_LEGACY_MODE;
- writel(val, base + USB1_LEGACY_CTRL);
- }
-#endif
-
- val = readl(base + UTMIP_TX_CFG0);
- val |= UTMIP_FS_PREABMLE_J;
- writel(val, base + UTMIP_TX_CFG0);
-
- val = readl(base + UTMIP_HSRX_CFG0);
- val &= ~(UTMIP_IDLE_WAIT(~0) | UTMIP_ELASTIC_LIMIT(~0));
- val |= UTMIP_IDLE_WAIT(config->idle_wait_delay);
- val |= UTMIP_ELASTIC_LIMIT(config->elastic_limit);
- writel(val, base + UTMIP_HSRX_CFG0);
-
- val = readl(base + UTMIP_HSRX_CFG1);
- val &= ~UTMIP_HS_SYNC_START_DLY(~0);
- val |= UTMIP_HS_SYNC_START_DLY(config->hssync_start_delay);
- writel(val, base + UTMIP_HSRX_CFG1);
-
- val = readl(base + UTMIP_DEBOUNCE_CFG0);
- val &= ~UTMIP_BIAS_DEBOUNCE_A(~0);
- val |= UTMIP_BIAS_DEBOUNCE_A(phy->freq->debounce);
- writel(val, base + UTMIP_DEBOUNCE_CFG0);
-
- val = readl(base + UTMIP_MISC_CFG0);
- val &= ~UTMIP_SUSPEND_EXIT_ON_EDGE;
- writel(val, base + UTMIP_MISC_CFG0);
-
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- val = readl(base + UTMIP_MISC_CFG1);
- val &= ~(UTMIP_PLL_ACTIVE_DLY_COUNT(~0) | UTMIP_PLLU_STABLE_COUNT(~0));
- val |= UTMIP_PLL_ACTIVE_DLY_COUNT(phy->freq->active_delay) |
- UTMIP_PLLU_STABLE_COUNT(phy->freq->stable_count);
- writel(val, base + UTMIP_MISC_CFG1);
-
- val = readl(base + UTMIP_PLL_CFG1);
- val &= ~(UTMIP_XTAL_FREQ_COUNT(~0) | UTMIP_PLLU_ENABLE_DLY_COUNT(~0));
- val |= UTMIP_XTAL_FREQ_COUNT(phy->freq->xtal_freq_count) |
- UTMIP_PLLU_ENABLE_DLY_COUNT(phy->freq->enable_delay);
- writel(val, base + UTMIP_PLL_CFG1);
-#endif
+ int err = 0;
- if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE) {
- val = readl(base + USB_SUSP_CTRL);
- val &= ~(USB_WAKE_ON_CNNT_EN_DEV | USB_WAKE_ON_DISCON_EN_DEV);
- writel(val, base + USB_SUSP_CTRL);
+ phy->pllu_clk = clk_get_sys(NULL, "pll_u");
+ if (IS_ERR(phy->pllu_clk)) {
+ ERR("inst:[%d] Can't get pllu_clk clock\n", phy->inst);
+ err = PTR_ERR(phy->pllu_clk);
+ goto fail_pll;
}
+ clk_enable(phy->pllu_clk);
- utmip_pad_power_on(phy);
-
- xcvr_setup_value = phy->xcvr_setup_value;
-
- val = readl(base + UTMIP_XCVR_CFG0);
- val &= ~(UTMIP_XCVR_LSBIAS_SEL | UTMIP_FORCE_PD_POWERDOWN |
- UTMIP_FORCE_PD2_POWERDOWN | UTMIP_FORCE_PDZI_POWERDOWN |
- UTMIP_XCVR_SETUP(~0) | UTMIP_XCVR_LSFSLEW(~0) |
- UTMIP_XCVR_LSRSLEW(~0) | UTMIP_XCVR_HSSLEW_MSB(~0));
- val |= UTMIP_XCVR_SETUP(xcvr_setup_value);
- val |= UTMIP_XCVR_SETUP_MSB(XCVR_SETUP_MSB_CALIB(xcvr_setup_value));
- val |= UTMIP_XCVR_LSFSLEW(config->xcvr_lsfslew);
- val |= UTMIP_XCVR_LSRSLEW(config->xcvr_lsrslew);
-#ifndef CONFIG_ARCH_TEGRA_2x_SOC
- val |= UTMIP_XCVR_HSSLEW_MSB(0x8);
-#endif
- writel(val, base + UTMIP_XCVR_CFG0);
-
- val = readl(base + UTMIP_XCVR_CFG1);
- val &= ~(UTMIP_FORCE_PDDISC_POWERDOWN | UTMIP_FORCE_PDCHRP_POWERDOWN |
- UTMIP_FORCE_PDDR_POWERDOWN | UTMIP_XCVR_TERM_RANGE_ADJ(~0));
- val |= UTMIP_XCVR_TERM_RANGE_ADJ(config->term_range_adj);
- writel(val, base + UTMIP_XCVR_CFG1);
-
- val = readl(base + UTMIP_BAT_CHRG_CFG0);
- if (phy->mode == TEGRA_USB_PHY_MODE_HOST)
- val |= UTMIP_PD_CHRG;
- else
- val &= ~UTMIP_PD_CHRG;
- writel(val, base + UTMIP_BAT_CHRG_CFG0);
-
- val = readl(base + UTMIP_BIAS_CFG1);
- val &= ~UTMIP_BIAS_PDTRK_COUNT(~0);
- val |= UTMIP_BIAS_PDTRK_COUNT(phy->freq->pdtrk_count);
- writel(val, base + UTMIP_BIAS_CFG1);
-
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- val = readl(base + UTMIP_SPARE_CFG0);
- val &= ~FUSE_SETUP_SEL;
- writel(val, base + UTMIP_SPARE_CFG0);
-
- if (phy->instance == 2) {
- val = readl(base + UTMIP_SPARE_CFG0);
- val |= FUSE_SETUP_SEL;
- writel(val, base + UTMIP_SPARE_CFG0);
-
- val = readl(base + USB_SUSP_CTRL);
- val |= UTMIP_PHY_ENABLE;
- writel(val, base + USB_SUSP_CTRL);
- }
-#else
- val = readl(base + UTMIP_SPARE_CFG0);
- val &= ~FUSE_SETUP_SEL;
- val |= FUSE_ATERM_SEL;
- writel(val, base + UTMIP_SPARE_CFG0);
-
- val = readl(base + USB_SUSP_CTRL);
- val |= UTMIP_PHY_ENABLE;
- writel(val, base + USB_SUSP_CTRL);
-#endif
-
- val = readl(base + USB_SUSP_CTRL);
- val &= ~UTMIP_RESET;
- writel(val, base + USB_SUSP_CTRL);
-
- if (phy->instance == 0) {
- val = readl(base + USB1_LEGACY_CTRL);
- val &= ~USB1_VBUS_SENSE_CTL_MASK;
- val |= USB1_VBUS_SENSE_CTL_A_SESS_VLD;
- writel(val, base + USB1_LEGACY_CTRL);
-
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- val = readl(base + USB_SUSP_CTRL);
- val &= ~USB_SUSP_SET;
- writel(val, base + USB_SUSP_CTRL);
-#endif
+ phy->ctrlr_clk = clk_get(&phy->pdev->dev, NULL);
+ if (IS_ERR(phy->ctrlr_clk)) {
+ dev_err(&phy->pdev->dev, "Can't get controller clock\n");
+ err = PTR_ERR(phy->ctrlr_clk);
+ goto fail_ctrlr_clk;
}
- utmi_phy_clk_enable(phy);
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- if (phy->instance == 2) {
- val = readl(base + USB_PORTSC1);
- val &= ~USB_PORTSC1_PTS(~0);
- writel(val, base + USB_PORTSC1);
- }
-#else
- if (phy->instance == 0)
- utmip_phy_enable_trking_data(phy);
+ if (phy->pdata->op_mode == TEGRA_USB_OPMODE_HOST)
+ if (phy->pdata->u_data.host.hot_plug ||
+ phy->pdata->u_data.host.remote_wakeup_supported)
+ clk_enable(phy->ctrlr_clk);
- if(phy->instance == 2) {
- writel(0, base + ICUSB_CTRL);
+ phy->sys_clk = clk_get(&phy->pdev->dev, "sclk");
+ if (IS_ERR(phy->sys_clk)) {
+ dev_err(&phy->pdev->dev, "Can't get sclk clock\n");
+ err = PTR_ERR(phy->sys_clk);
+ goto fail_sclk;
}
+ clk_set_rate(phy->sys_clk, 80000000);
- if (phy->mode == TEGRA_USB_PHY_MODE_HOST) {
- val = readl(base + TEGRA_USB_USBMODE_REG_OFFSET);
- writel((val | TEGRA_USB_USBMODE_HOST),
- (base + TEGRA_USB_USBMODE_REG_OFFSET));
+ phy->emc_clk = clk_get(&phy->pdev->dev, "emc");
+ if (IS_ERR(phy->emc_clk)) {
+ dev_err(&phy->pdev->dev, "Can't get emc clock\n");
+ err = PTR_ERR(phy->emc_clk);
+ goto fail_emc;
}
- val = readl(base + HOSTPC1_DEVLC);
- val &= ~HOSTPC1_DEVLC_PTS(~0);
- val |= HOSTPC1_DEVLC_STS;
- writel(val, base + HOSTPC1_DEVLC);
- if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE)
- utmip_powerup_pmc_wake_detect(phy);
-#endif
-
- return 0;
-}
-
-#ifndef CONFIG_ARCH_TEGRA_2x_SOC
-static void utmip_setup_pmc_wake_detect(struct tegra_usb_phy *phy)
-{
- unsigned long val, pmc_pad_cfg_val;
- void __iomem *pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
- unsigned int inst = phy->instance;
- void __iomem *base = phy->regs;
- bool port_connected;
- enum tegra_usb_phy_port_speed port_speed;
-
- /* check for port connect status */
- val = readl(base + USB_PORTSC1);
- port_connected = val & USB_PORTSC1_CCS;
-
- if (!port_connected)
- return;
-
- port_speed = (readl(base + HOSTPC1_DEVLC) >> 25) &
- HOSTPC1_DEVLC_PSPD_MASK;
- /*Set PMC MASTER bits to do the following
- * a. Take over the UTMI drivers
- * b. set up such that it will take over resume
- * if remote wakeup is detected
- * Prepare PMC to take over suspend-wake detect-drive resume until USB
- * controller ready
- */
-
- /* disable master enable in PMC */
- val = readl(pmc_base + PMC_SLEEP_CFG);
- val &= ~UTMIP_MASTER_ENABLE(inst);
- writel(val, pmc_base + PMC_SLEEP_CFG);
-
- /* UTMIP_PWR_PX=1 for power savings mode */
- val = readl(pmc_base + PMC_UTMIP_MASTER_CONFIG);
- val |= UTMIP_PWR(inst);
- writel(val, pmc_base + PMC_UTMIP_MASTER_CONFIG);
-
- /* config debouncer */
- val = readl(pmc_base + PMC_USB_DEBOUNCE);
- val &= ~UTMIP_LINE_DEB_CNT(~0);
- val |= UTMIP_LINE_DEB_CNT(1);
- writel(val, pmc_base + PMC_USB_DEBOUNCE);
-
- /* Make sure nothing is happening on the line with respect to PMC */
- val = readl(pmc_base + PMC_UTMIP_UHSIC_FAKE);
- val &= ~USBOP_VAL(inst);
- val &= ~USBON_VAL(inst);
- writel(val, pmc_base + PMC_UTMIP_UHSIC_FAKE);
-
- /* Make sure wake value for line is none */
- val = readl(pmc_base + PMC_SLEEPWALK_CFG);
- val &= ~UTMIP_LINEVAL_WALK_EN(inst);
- writel(val, pmc_base + PMC_SLEEPWALK_CFG);
- val = readl(pmc_base + PMC_SLEEP_CFG);
- val &= ~UTMIP_WAKE_VAL(inst, ~0);
- val |= UTMIP_WAKE_VAL(inst, WAKE_VAL_NONE);
- writel(val, pmc_base + PMC_SLEEP_CFG);
-
- /* turn off pad detectors */
- val = readl(pmc_base + PMC_USB_AO);
- val |= (USBOP_VAL_PD(inst) | USBON_VAL_PD(inst));
- writel(val, pmc_base + PMC_USB_AO);
-
- /* Remove fake values and make synchronizers work a bit */
- val = readl(pmc_base + PMC_UTMIP_UHSIC_FAKE);
- val &= ~USBOP_VAL(inst);
- val &= ~USBON_VAL(inst);
- 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);
- writel(val, pmc_base + PMC_SLEEPWALK_CFG);
-
- /* Clear the walk pointers and wake alarm */
- val = readl(pmc_base + PMC_TRIGGERS);
- val |= UTMIP_CLR_WAKE_ALARM(inst) | UTMIP_CLR_WALK_PTR(inst);
- writel(val, pmc_base + PMC_TRIGGERS);
-
-
- /* Capture FS/LS pad configurations */
- pmc_pad_cfg_val = readl(pmc_base + PMC_PAD_CFG);
- val = readl(pmc_base + PMC_TRIGGERS);
- val |= UTMIP_CAP_CFG(inst);
- writel(val, pmc_base + PMC_TRIGGERS);
- udelay(1);
- pmc_pad_cfg_val = readl(pmc_base + PMC_PAD_CFG);
-
- /* BIAS MASTER_ENABLE=0 */
- val = readl(pmc_base + PMC_UTMIP_BIAS_MASTER_CNTRL);
- val &= ~BIAS_MASTER_PROG_VAL;
- writel(val, pmc_base + PMC_UTMIP_BIAS_MASTER_CNTRL);
-
- /* program walk sequence, maintain a J, followed by a driven K
- * to signal a resume once an wake event is detected */
- val = readl(pmc_base + PMC_SLEEPWALK_REG(inst));
- val &= ~UTMIP_AP_A;
- val |= UTMIP_USBOP_RPD_A | UTMIP_USBON_RPD_A| UTMIP_AN_A | UTMIP_HIGHZ_A |
- UTMIP_USBOP_RPD_B | UTMIP_USBON_RPD_B | UTMIP_AP_B | UTMIP_AN_B |
- UTMIP_USBOP_RPD_C | UTMIP_USBON_RPD_C | UTMIP_AP_C | UTMIP_AN_C |
- UTMIP_USBOP_RPD_D | UTMIP_USBON_RPD_D | UTMIP_AP_D | UTMIP_AN_D;
- writel(val, pmc_base + PMC_SLEEPWALK_REG(inst));
-
- if (port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW) {
- val = readl(pmc_base + PMC_SLEEPWALK_REG(inst));
- val &= ~(UTMIP_AN_B | UTMIP_HIGHZ_B | UTMIP_AN_C |
- UTMIP_HIGHZ_C | UTMIP_AN_D | UTMIP_HIGHZ_D);
- writel(val, pmc_base + PMC_SLEEPWALK_REG(inst));
- } else {
- val = readl(pmc_base + PMC_SLEEPWALK_REG(inst));
- val &= ~(UTMIP_AP_B | UTMIP_HIGHZ_B | UTMIP_AP_C |
- UTMIP_HIGHZ_C | UTMIP_AP_D | UTMIP_HIGHZ_D);
- writel(val, pmc_base + PMC_SLEEPWALK_REG(inst));
- }
+ if(phy->pdata->has_hostpc)
+ clk_set_rate(phy->emc_clk, 100000000);
+ else
+ clk_set_rate(phy->emc_clk, 300000000);
- /* turn on pad detectors */
- val = readl(pmc_base + PMC_USB_AO);
- val &= ~(USBOP_VAL_PD(inst) | USBON_VAL_PD(inst));
- writel(val, pmc_base + PMC_USB_AO);
+ return err;
- /* Add small delay before usb detectors provide stable line values */
- mdelay(1);
+fail_emc:
+ clk_put(phy->sys_clk);
- /* Program thermally encoded RCTRL_VAL, TCTRL_VAL into PMC space */
- val = readl(pmc_base + PMC_UTMIP_TERM_PAD_CFG);
- val = PMC_TCTRL_VAL(utmip_tctrl_val) | PMC_RCTRL_VAL(utmip_rctrl_val);
- writel(val, pmc_base + PMC_UTMIP_TERM_PAD_CFG);
+fail_sclk:
+ clk_put(phy->ctrlr_clk);
- phy->remote_wakeup = false;
+fail_ctrlr_clk:
+ clk_disable(phy->pllu_clk);
+ clk_put(phy->pllu_clk);
- /* Turn over pad configuration to PMC for line wake events*/
- val = readl(pmc_base + PMC_SLEEP_CFG);
- val &= ~UTMIP_WAKE_VAL(inst, ~0);
- val |= UTMIP_WAKE_VAL(inst, WAKE_VAL_ANY);
- val |= UTMIP_RCTRL_USE_PMC(inst) | UTMIP_TCTRL_USE_PMC(inst);
- val |= UTMIP_MASTER_ENABLE(inst) | UTMIP_FSLS_USE_PMC(inst);
- writel(val, pmc_base + PMC_SLEEP_CFG);
+fail_pll:
- val = readl(base + UTMIP_PMC_WAKEUP0);
- val |= EVENT_INT_ENB;
- writel(val, base + UTMIP_PMC_WAKEUP0);
+ return err;
}
-#endif
-static int utmi_phy_power_off(struct tegra_usb_phy *phy, bool is_dpd)
+struct tegra_usb_phy *tegra_usb_phy_open(struct platform_device *pdev)
{
- unsigned long val;
- void __iomem *base = phy->regs;
-
-#ifndef CONFIG_ARCH_TEGRA_2x_SOC
- if (phy->mode == TEGRA_USB_PHY_MODE_HOST)
- utmip_setup_pmc_wake_detect(phy);
- else
- utmip_powerdown_pmc_wake_detect(phy);
-#endif
- if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE) {
- val = readl(base + USB_SUSP_CTRL);
- val &= ~USB_WAKEUP_DEBOUNCE_COUNT(~0);
- val |= USB_WAKE_ON_CNNT_EN_DEV | USB_WAKEUP_DEBOUNCE_COUNT(5);
- writel(val, base + USB_SUSP_CTRL);
- }
+ struct tegra_usb_phy *phy;
+ struct tegra_usb_platform_data *pdata;
+ struct resource *res;
+ int err;
- if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE) {
- val = readl(base + UTMIP_BAT_CHRG_CFG0);
- val |= UTMIP_PD_CHRG;
- writel(val, base + UTMIP_BAT_CHRG_CFG0);
+ 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);
}
- if (phy->instance != 2) {
- val = readl(base + UTMIP_XCVR_CFG0);
- val |= (UTMIP_FORCE_PD_POWERDOWN | UTMIP_FORCE_PD2_POWERDOWN |
- UTMIP_FORCE_PDZI_POWERDOWN);
- writel(val, base + UTMIP_XCVR_CFG0);
+ phy = kzalloc(sizeof(struct tegra_usb_phy), GFP_KERNEL);
+ if (!phy) {
+ ERR("inst:[%d] malloc usb phy failed\n", pdev->id);
+ return ERR_PTR(-ENOMEM);
}
- val = readl(base + UTMIP_XCVR_CFG1);
- val |= UTMIP_FORCE_PDDISC_POWERDOWN | UTMIP_FORCE_PDCHRP_POWERDOWN |
- UTMIP_FORCE_PDDR_POWERDOWN;
- writel(val, base + UTMIP_XCVR_CFG1);
-
-#ifndef CONFIG_ARCH_TEGRA_2x_SOC
- val = readl(base + UTMIP_BIAS_CFG1);
- val |= UTMIP_BIAS_PDTRK_COUNT(0x5);
- writel(val, base + UTMIP_BIAS_CFG1);
-#endif
- if (phy->hotplug) {
- val = readl(base + USB_PORTSC1);
- val |= USB_PORTSC1_WKCN;
- writel(val, base + USB_PORTSC1);
- }
- if (phy->instance != 0) {
- val = readl(base + UTMIP_BIAS_CFG0);
- val |= UTMIP_OTGPD;
- writel(val, base + UTMIP_BIAS_CFG0);
+ phy->pdata = kzalloc(sizeof(struct tegra_usb_platform_data), GFP_KERNEL);
+ if (!phy->pdata) {
+ ERR("inst:[%d] malloc usb phy pdata failed\n", pdev->id);
+ kfree(phy);
+ return ERR_PTR(-ENOMEM);
}
- utmi_phy_clk_disable(phy);
-
- utmip_pad_power_off(phy, true);
- return 0;
-}
+ memcpy(phy->pdata, pdata, sizeof(struct tegra_usb_platform_data));
+ phy->pdev = pdev;
+ phy->inst = pdev->id;
-static void utmip_phy_disable_pmc_bus_ctrl(struct tegra_usb_phy *phy)
-{
-#ifndef CONFIG_ARCH_TEGRA_2x_SOC
- unsigned long val;
- void __iomem *pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
- unsigned int inst = phy->instance;
- void __iomem *base = phy->regs;
-
- val = readl(pmc_base + PMC_SLEEP_CFG);
- val &= ~UTMIP_WAKE_VAL(inst, 0x0);
- 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);
-
- /* Disable PMC master mode by clearing MASTER_EN */
- val = readl(pmc_base + PMC_SLEEP_CFG);
- val &= ~(UTMIP_RCTRL_USE_PMC(inst) | UTMIP_TCTRL_USE_PMC(inst) |
- UTMIP_FSLS_USE_PMC(inst) | UTMIP_MASTER_ENABLE(inst));
- writel(val, pmc_base + PMC_SLEEP_CFG);
-
- val = readl(pmc_base + PMC_TRIGGERS);
- val &= ~UTMIP_CAP_CFG(inst);
- writel(val, pmc_base + PMC_TRIGGERS);
-
- /* turn off pad detectors */
- val = readl(pmc_base + PMC_USB_AO);
- val |= (USBOP_VAL_PD(inst) | USBON_VAL_PD(inst));
- writel(val, pmc_base + PMC_USB_AO);
-
- phy->remote_wakeup = false;
-#endif
-}
+ print_usb_plat_data_info(phy);
-static void utmi_phy_enable_obs_bus(struct tegra_usb_phy *phy,
- enum tegra_usb_phy_port_speed port_speed)
-{
- unsigned long val;
- void __iomem *base = phy->regs;
-
- /* (2LS WAR)is not required for LS and FS devices and is only for HS */
- if (port_speed != TEGRA_USB_PHY_PORT_SPEED_HIGH) {
- /* do not enable the OBS bus */
- val = readl(base + UTMIP_MISC_CFG0);
- val &= ~UTMIP_DPDM_OBSERVE_SEL(~0);
- writel(val, base + UTMIP_MISC_CFG0);
- return;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ ERR("inst:[%d] failed to get I/O memory\n", phy->inst);
+ err = -ENXIO;
+ goto fail_io;
}
-#ifndef CONFIG_ARCH_TEGRA_2x_SOC
- /* Force DP/DM pulldown active for Host mode */
- val = readl(base + UTMIP_MISC_CFG0);
- val |= FORCE_PULLDN_DM | FORCE_PULLDN_DP |
- COMB_TERMS | ALWAYS_FREE_RUNNING_TERMS;
- writel(val, base + UTMIP_MISC_CFG0);
-#endif
- val = readl(base + UTMIP_MISC_CFG0);
- val &= ~UTMIP_DPDM_OBSERVE_SEL(~0);
- if (port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW)
- val |= UTMIP_DPDM_OBSERVE_SEL_FS_J;
- else
- val |= UTMIP_DPDM_OBSERVE_SEL_FS_K;
- writel(val, base + UTMIP_MISC_CFG0);
- udelay(1);
-
- val = readl(base + UTMIP_MISC_CFG0);
- val |= UTMIP_DPDM_OBSERVE;
- writel(val, base + UTMIP_MISC_CFG0);
- udelay(10);
-}
-static void utmi_phy_disable_obs_bus(struct tegra_usb_phy *phy)
-{
- unsigned long val;
- void __iomem *base = phy->regs;
-
- /* check if OBS bus is already enabled */
- val = readl(base + UTMIP_MISC_CFG0);
- if (val & UTMIP_DPDM_OBSERVE) {
- /* Change the UTMIP OBS bus to drive SE0 */
- val = readl(base + UTMIP_MISC_CFG0);
- val &= ~UTMIP_DPDM_OBSERVE_SEL(~0);
- val |= UTMIP_DPDM_OBSERVE_SEL_FS_SE0;
- writel(val, base + UTMIP_MISC_CFG0);
-
- /* Wait for 3us(2 LS bit times) */
- udelay (3);
-
- /* Release UTMIP OBS bus */
- val = readl(base + UTMIP_MISC_CFG0);
- val &= ~UTMIP_DPDM_OBSERVE;
- writel(val, base + UTMIP_MISC_CFG0);
-
-#ifndef CONFIG_ARCH_TEGRA_2x_SOC
- /* Release DP/DM pulldown for Host mode */
- val = readl(base + UTMIP_MISC_CFG0);
- val &= ~(FORCE_PULLDN_DM | FORCE_PULLDN_DP |
- COMB_TERMS | ALWAYS_FREE_RUNNING_TERMS);
- writel(val, base + UTMIP_MISC_CFG0);
-#endif
+ phy->regs = ioremap(res->start, resource_size(res));
+ if (!phy->regs) {
+ ERR("inst:[%d] Failed to remap I/O memory\n", phy->inst);
+ err = -ENOMEM;
+ goto fail_io;
}
-}
-
-static int utmi_phy_preresume(struct tegra_usb_phy *phy, bool remote_wakeup)
-{
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- unsigned long val;
- void __iomem *base = phy->regs;
- enum tegra_usb_phy_port_speed port_speed;
-
- val = readl(base + UTMIP_TX_CFG0);
- val |= UTMIP_HS_DISCON_DISABLE;
- writel(val, base + UTMIP_TX_CFG0);
-
- port_speed = (readl(base + USB_PORTSC1) >> 26) & 0x3;
- if (remote_wakeup && (port_speed == TEGRA_USB_PHY_PORT_SPEED_HIGH)) {
- val = readl(base + USB_USBCMD);
- val &= ~USB_USBCMD_RS;
- writel(val, base + USB_USBCMD);
- if (utmi_wait_register(base + USB_USBSTS,
- USB_USBSTS_HCH, USB_USBSTS_HCH) < 0) {
- pr_err("%s: timeout waiting for stopping controller\n", __func__);
- return -ETIMEDOUT;
- }
+ phy->vdd_reg = regulator_get(NULL, "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));
+ phy->vdd_reg = NULL;
}
- utmi_phy_enable_obs_bus(phy, port_speed);
-#else
- unsigned long val;
- void __iomem *pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
- unsigned int inst = phy->instance;
- void __iomem *base = phy->regs;
- enum tegra_usb_phy_port_speed port_speed;
-
- val = readl(pmc_base + PMC_SLEEP_CFG);
- if (val & UTMIP_MASTER_ENABLE(inst)) {
- if (!remote_wakeup)
- utmip_phy_disable_pmc_bus_ctrl(phy);
- } else {
- port_speed = (readl(base + HOSTPC1_DEVLC) >> 25) &
- HOSTPC1_DEVLC_PSPD_MASK;
- utmi_phy_enable_obs_bus(phy, port_speed);
+ err = tegra_usb_phy_get_clocks(phy);
+ if (err) {
+ ERR("inst:[%d] Failed to init clocks\n", phy->inst);
+ goto fail_clk;
}
-#endif
- return 0;
-}
-
-static int utmi_phy_postresume(struct tegra_usb_phy *phy, bool is_dpd)
-{
- unsigned long val;
-#if defined(CONFIG_ARCH_TEGRA_2x_SOC)
- void __iomem *base = phy->regs;
-#else
- void __iomem *pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
- unsigned int inst = phy->instance;
-#endif
-
-#ifndef CONFIG_ARCH_TEGRA_2x_SOC
- val = readl(pmc_base + PMC_SLEEP_CFG);
- /* if PMC is not disabled by now then disable it */
- if (val & UTMIP_MASTER_ENABLE(inst)) {
- utmip_phy_disable_pmc_bus_ctrl(phy);
- }
- utmi_phy_disable_obs_bus(phy);
-#else
- val = readl(base + USB_USBCMD);
- if (val & USB_USBCMD_RS) {
- val &= ~USB_USBCMD_RS;
- writel(val, base + USB_USBCMD);
- if (utmi_wait_register(base + USB_USBSTS,
- USB_USBSTS_HCH, USB_USBSTS_HCH) < 0) {
- pr_err("%s: timeout waiting for stopping controller\n", __func__);
- return -ETIMEDOUT;
+ if (phy->pdata->op_mode == TEGRA_USB_OPMODE_DEVICE) {
+ if (phy->pdata->u_data.dev.vbus_pmu_irq) {
+ err = request_threaded_irq(
+ phy->pdata->u_data.dev.vbus_pmu_irq,
+ NULL, usb_phy_dev_vbus_pmu_irq_thr,
+ IRQF_SHARED, "usb_pmu_vbus_irq", phy);
+ if (err) {
+ ERR("inst:[%d] Failed to register IRQ\n",
+ phy->inst);
+ goto fail_init;
+ }
+ } else {
+ clk_enable(phy->ctrlr_clk);
}
+ } else {
+ if (phy->pdata->u_data.host.vbus_reg) {
+ phy->vbus_reg = regulator_get(NULL,
+ phy->pdata->u_data.host.vbus_reg);
+ if (WARN_ON(IS_ERR_OR_NULL(phy->vbus_reg))) {
+ ERR("failed to get regulator vdd_vbus_usb: %ld,\
+ instance : %d\n", PTR_ERR(phy->vbus_reg),
+ phy->inst);
+ err = PTR_ERR(phy->vbus_reg);
+ goto fail_init;
+ }
+ } else {
+ int gpio = phy->pdata->u_data.host.vbus_gpio;
+ if (gpio != -1) {
+ if (gpio_request(gpio, "usb_host_vbus") < 0) {
+ ERR("inst:[%d] host vbus gpio \
+ 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);
+ goto fail_init;
+ }
+ }
+ }
+ usb_host_vbus_enable(phy, true);
}
- writel(val, base + USB_USBCMD);
- utmi_phy_disable_obs_bus(phy);
- val = readl(base + USB_USBCMD);
- val |= USB_USBCMD_RS;
- writel(val, base + USB_USBCMD);
- val = readl(base + UTMIP_TX_CFG0);
- val &= ~UTMIP_HS_DISCON_DISABLE;
- writel(val, base + UTMIP_TX_CFG0);
-#endif
-
-
- return 0;
-}
-
-static int uhsic_phy_postsuspend(struct tegra_usb_phy *phy, bool is_dpd)
-{
- struct tegra_uhsic_config *uhsic_config = phy->config;
-
- if (uhsic_config->postsuspend)
- uhsic_config->postsuspend();
-
- return 0;
-}
-
-static int uhsic_phy_preresume(struct tegra_usb_phy *phy, bool remote_wakeup)
-{
- struct tegra_uhsic_config *uhsic_config = phy->config;
-
- if (uhsic_config->preresume)
- uhsic_config->preresume();
-
- return 0;
-}
-static int uhsic_phy_postresume(struct tegra_usb_phy *phy, bool is_dpd)
-{
- unsigned long val;
- void __iomem *base = phy->regs;
-
- 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);
+ err = tegra_usb_phy_init_ops(phy);
+ if (err) {
+ ERR("inst:[%d] Failed to init ops\n", phy->inst);
+ goto fail_init;
}
- return 0;
-}
-
-static void utmi_phy_restore_start(struct tegra_usb_phy *phy,
- enum tegra_usb_phy_port_speed port_speed)
-{
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- unsigned long val;
- void __iomem *base = phy->regs;
+ if (phy->pdata->ops && phy->pdata->ops->open)
+ phy->pdata->ops->open();
- val = readl(base + UTMIP_MISC_CFG0);
- val &= ~UTMIP_DPDM_OBSERVE_SEL(~0);
- if (port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW)
- val |= UTMIP_DPDM_OBSERVE_SEL_FS_K;
- else
- val |= UTMIP_DPDM_OBSERVE_SEL_FS_J;
- writel(val, base + UTMIP_MISC_CFG0);
- udelay(1);
-
- val = readl(base + UTMIP_MISC_CFG0);
- val |= UTMIP_DPDM_OBSERVE;
- writel(val, base + UTMIP_MISC_CFG0);
- udelay(10);
-#else
- unsigned long val;
- void __iomem *pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
- int inst = phy->instance;
-
- val = readl(pmc_base + UTMIP_UHSIC_STATUS);
- /* check whether we wake up from the remote resume */
- if (UTMIP_WALK_PTR_VAL(inst) & val) {
- phy->remote_wakeup = true;
- } else {
- if (!((UTMIP_USBON_VAL(phy->instance) |
- UTMIP_USBOP_VAL(phy->instance)) & val)) {
- utmip_phy_disable_pmc_bus_ctrl(phy);
+ if (phy->ops && phy->ops->open) {
+ err = phy->ops->open(phy);
+ if (err) {
+ ERR("inst:[%d] Failed to open hw ops\n", phy->inst);
+ goto fail_init;
}
}
- utmi_phy_enable_obs_bus(phy, port_speed);
-#endif
-}
-static void utmi_phy_restore_end(struct tegra_usb_phy *phy)
-{
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- unsigned long val;
- void __iomem *base = phy->regs;
+ return phy;
- val = readl(base + UTMIP_MISC_CFG0);
- val &= ~UTMIP_DPDM_OBSERVE;
- writel(val, base + UTMIP_MISC_CFG0);
- udelay(10);
-#else
- unsigned long val;
- void __iomem *base = phy->regs;
- int wait_time_us = 3000; /* FPR should be set by this time */
-
- /* check whether we wake up from the remote resume */
- if (phy->remote_wakeup) {
- /* wait until FPR bit is set automatically on remote resume */
- do {
- val = readl(base + USB_PORTSC1);
- udelay(1);
- if (wait_time_us == 0) {
- utmip_phy_disable_pmc_bus_ctrl(phy);
- tegra_usb_phy_postresume(phy, false);
- return;
+fail_init:
+ tegra_usb_phy_release_clocks(phy);
+
+ if (phy->pdata->op_mode == TEGRA_USB_OPMODE_DEVICE) {
+ if (phy->pdata->u_data.dev.vbus_pmu_irq)
+ free_irq(phy->pdata->u_data.dev.vbus_pmu_irq, phy);
+ } else {
+ usb_host_vbus_enable(phy, false);
+
+ if (phy->vbus_reg)
+ regulator_put(phy->vbus_reg);
+ else {
+ int gpio = phy->pdata->u_data.host.vbus_gpio;
+ if (gpio != -1) {
+ gpio_set_value_cansleep(gpio, phy->pdata->u_data.host.vbus_gpio_inverted);
+ gpio_free(gpio);
}
- wait_time_us--;
- } while (!(val & USB_PORTSC1_RESUME));
- /* wait for 25 ms to port resume complete */
- msleep(25);
- /* disable PMC master control */
- utmip_phy_disable_pmc_bus_ctrl(phy);
-
- /* Clear PCI and SRI bits to avoid an interrupt upon resume */
- val = readl(base + USB_USBSTS);
- writel(val, base + USB_USBSTS);
- /* wait to avoid SOF if there is any */
- if (utmi_wait_register(base + USB_USBSTS,
- USB_USBSTS_SRI, USB_USBSTS_SRI) < 0) {
- pr_err("%s: timeout waiting for SOF\n", __func__);
}
- tegra_usb_phy_postresume(phy, false);
}
-#endif
-}
-
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
-static void ulpi_set_tristate(bool enable)
-{
- int tristate = (enable)? TEGRA_TRI_TRISTATE : TEGRA_TRI_NORMAL;
-
- tegra_pinmux_set_tristate(TEGRA_PINGROUP_UAA, tristate);
- tegra_pinmux_set_tristate(TEGRA_PINGROUP_UAB, tristate);
- tegra_pinmux_set_tristate(TEGRA_PINGROUP_UDA, tristate);
-}
-#endif
-
-static void ulpi_phy_reset(void __iomem *base)
-{
- unsigned long val;
-
- val = readl(base + USB_SUSP_CTRL);
- val |= UHSIC_RESET;
- writel(val, base + USB_SUSP_CTRL);
-
-#ifndef CONFIG_ARCH_TEGRA_2x_SOC
- val = readl(base + USB_SUSP_CTRL);
- val |= UTMIP_RESET;
- writel(val, base + USB_SUSP_CTRL);
-#endif
-}
-
-static void ulpi_set_host(void __iomem *base)
-{
-#ifndef CONFIG_ARCH_TEGRA_2x_SOC
- unsigned long val;
-
- val = readl(base + TEGRA_USB_USBMODE_REG_OFFSET);
- val |= TEGRA_USB_USBMODE_HOST;
- writel(val, base + TEGRA_USB_USBMODE_REG_OFFSET);
-
- val = readl(base + HOSTPC1_DEVLC);
- val |= HOSTPC1_DEVLC_PTS(2);
- writel(val, base + HOSTPC1_DEVLC);
-#endif
-}
-
-static void ulpi_set_trimmer(void __iomem *base, u8 data, u8 sdn, u8 dir)
-{
- unsigned long val;
-
- val = ULPI_DATA_TRIMMER_SEL(data);
- val |= ULPI_STPDIRNXT_TRIMMER_SEL(sdn);
- val |= ULPI_DIR_TRIMMER_SEL(dir);
- writel(val, base + ULPI_TIMING_CTRL_1);
- udelay(10);
-
- val |= ULPI_DATA_TRIMMER_LOAD;
- val |= ULPI_STPDIRNXT_TRIMMER_LOAD;
- val |= ULPI_DIR_TRIMMER_LOAD;
- writel(val, base + ULPI_TIMING_CTRL_1);
-}
-
-static inline void ulpi_pinmux_bypass(struct tegra_usb_phy *phy, bool enable)
-{
- unsigned long val;
- void __iomem *base = phy->regs;
-
- val = readl(base + ULPI_TIMING_CTRL_0);
-
- if (enable)
- val |= ULPI_OUTPUT_PINMUX_BYP;
- else
- val &= ~ULPI_OUTPUT_PINMUX_BYP;
-
- writel(val, base + ULPI_TIMING_CTRL_0);
-}
-
-static void ulpi_phy_restore_start(struct tegra_usb_phy *phy,
- enum tegra_usb_phy_port_speed port_speed)
-{
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- unsigned long val;
- void __iomem *base = phy->regs;
- /*Tristate ulpi interface before USB controller resume*/
- ulpi_set_tristate(true);
+fail_clk:
+ regulator_put(phy->vdd_reg);
+ iounmap(phy->regs);
+fail_io:
+ kfree(phy);
- val = readl(base + ULPI_TIMING_CTRL_0);
- val &= ~ULPI_OUTPUT_PINMUX_BYP;
- writel(val, base + ULPI_TIMING_CTRL_0);
-#endif
+ return ERR_PTR(err);
}
-static void ulpi_phy_restore_end(struct tegra_usb_phy *phy)
-{
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- unsigned long val;
- void __iomem *base = phy->regs;
-
- val = readl(base + ULPI_TIMING_CTRL_0);
- val |= ULPI_OUTPUT_PINMUX_BYP;
- writel(val, base + ULPI_TIMING_CTRL_0);
- ulpi_set_tristate(false);
-#endif
-}
-static int ulpi_phy_power_on(struct tegra_usb_phy *phy, bool is_dpd)
+void tegra_usb_phy_close(struct tegra_usb_phy *phy)
{
- int ret;
- unsigned long val;
- void __iomem *base = phy->regs;
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- struct tegra_ulpi_config *config = phy->config;
-#endif
-
- if (phy->clk)
- clk_enable(phy->clk);
-
- msleep(1);
-
- if (!phy->initialized) {
- phy->initialized = 1;
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- gpio_direction_output(config->reset_gpio, 0);
- msleep(5);
- gpio_direction_output(config->reset_gpio, 1);
-#endif
- }
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
- ulpi_phy_reset(base);
- ulpi_set_host(base);
+ if (phy->ops && phy->ops->close)
+ phy->ops->close(phy);
- val = readl(base + ULPI_TIMING_CTRL_0);
- val |= ULPI_OUTPUT_PINMUX_BYP | ULPI_CLKOUT_PINMUX_BYP;
- writel(val, base + ULPI_TIMING_CTRL_0);
+ if (phy->pdata->ops && phy->pdata->ops->close)
+ phy->pdata->ops->close();
- val = readl(base + USB_SUSP_CTRL);
- val |= ULPI_PHY_ENABLE;
- writel(val, base + USB_SUSP_CTRL);
-
- val = readl(base + USB_SUSP_CTRL);
- val |= USB_SUSP_CLR;
- writel(val, base + USB_SUSP_CTRL);
-
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID,
- USB_PHY_CLK_VALID) < 0)
- pr_err("%s: timeout waiting for phy to stabilize\n", __func__);
-
- if (utmi_wait_register(base + USB_SUSP_CTRL, USB_CLKEN, USB_CLKEN) < 0)
- pr_err("%s: timeout waiting for AHB clock\n", __func__);
-#else
- udelay(100);
-#endif
-
- 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);
-
- ulpi_set_trimmer(base, 4, 4, 4);
-
- /* Fix VbusInvalid due to floating VBUS */
- ret = otg_io_write(phy->ulpi, 0x40, 0x08);
- if (ret) {
- pr_err("%s: ulpi write failed\n", __func__);
- return ret;
+ if (phy->pdata->op_mode == TEGRA_USB_OPMODE_DEVICE) {
+ if (phy->pdata->u_data.dev.vbus_pmu_irq)
+ free_irq(phy->pdata->u_data.dev.vbus_pmu_irq, phy);
+ else
+ clk_disable(phy->ctrlr_clk);
+ } else {
+ usb_host_vbus_enable(phy, false);
+
+ if (phy->vbus_reg)
+ regulator_put(phy->vbus_reg);
+ else {
+ int gpio = phy->pdata->u_data.host.vbus_gpio;
+ if (gpio != -1) {
+ gpio_set_value_cansleep(gpio, phy->pdata->u_data.host.vbus_gpio_inverted);
+ gpio_free(gpio);
+ }
+ }
}
- ret = otg_io_write(phy->ulpi, 0x80, 0x0B);
- if (ret) {
- pr_err("%s: ulpi write failed\n", __func__);
- return ret;
+ if (phy->vdd_reg) {
+ if (phy->vdd_reg_on)
+ regulator_disable(phy->vdd_reg);
+ regulator_put(phy->vdd_reg);
}
- val = readl(base + USB_PORTSC1);
- val |= USB_PORTSC1_WKOC | USB_PORTSC1_WKDS | USB_PORTSC1_WKCN;
- writel(val, base + USB_PORTSC1);
-
-//should really all be done in some board specific enable_vbus()
-#ifdef CONFIG_MACH_COLIBRI_T20
- /* Fix Ethernet detection faults */
- mdelay(100);
-
-#define ETHERNET_VBUS_GPIO TEGRA_GPIO_PBB1
-#define ETHERNET_RESET_GPIO TEGRA_GPIO_PV4
- tegra_gpio_enable(ETHERNET_VBUS_GPIO);
- gpio_request(ETHERNET_VBUS_GPIO, "ethernet_vbus");
- gpio_direction_output(ETHERNET_VBUS_GPIO, 1);
- gpio_export(ETHERNET_VBUS_GPIO, false);
+ tegra_usb_phy_release_clocks(phy);
- tegra_gpio_enable(ETHERNET_RESET_GPIO);
- gpio_request(ETHERNET_RESET_GPIO, "ethernet_reset");
- gpio_direction_output(ETHERNET_RESET_GPIO, 1);
- gpio_export(ETHERNET_RESET_GPIO, false);
-#endif /* CONFIG_MACH_COLIBRI_T20 */
-
- return 0;
+ kfree(phy->pdata);
+ kfree(phy);
}
-static int ulpi_phy_power_off(struct tegra_usb_phy *phy, bool is_dpd)
+irqreturn_t tegra_usb_phy_irq(struct tegra_usb_phy *phy)
{
- unsigned long val;
- void __iomem *base = phy->regs;
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- int ret;
-
- /* Disable VbusValid, SessEnd comparators */
- ret = otg_io_write(phy->ulpi, 0x00, 0x0D);
- if (ret)
- pr_err("%s: ulpi write 0x0D failed\n", __func__);
-
- ret = otg_io_write(phy->ulpi, 0x00, 0x10);
- if (ret)
- pr_err("%s: ulpi write 0x10 failed\n", __func__);
-
- /* Disable IdFloat comparator */
- ret = otg_io_write(phy->ulpi, 0x00, 0x19);
- if (ret)
- pr_err("%s: ulpi write 0x19 failed\n", __func__);
-
- ret = otg_io_write(phy->ulpi, 0x00, 0x1D);
- if (ret)
- pr_err("%s: ulpi write 0x1D failed\n", __func__);
-
- /* Clear WKCN/WKDS/WKOC wake-on events that can cause the USB
- * Controller to immediately bring the ULPI PHY out of low power
- */
- val = readl(base + USB_PORTSC1);
- val &= ~(USB_PORTSC1_WKOC | USB_PORTSC1_WKDS | USB_PORTSC1_WKCN);
- writel(val, base + USB_PORTSC1);
+ irqreturn_t status = IRQ_HANDLED;
- /* Put the PHY in the low power mode */
- val = readl(base + USB_PORTSC1);
- val |= USB_PORTSC1_PHCD;
- writel(val, base + USB_PORTSC1);
+ if (phy->ops && phy->ops->irq)
+ status = phy->ops->irq(phy);
- if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, 0) < 0)
- pr_err("%s: timeout waiting for phy to stop\n", __func__);
-#else
- val = readl(base + HOSTPC1_DEVLC);
- val &= ~(HOSTPC1_DEVLC_PHCD);
- writel(val, base + HOSTPC1_DEVLC);
-#endif
-
- if(phy->clk)
- clk_disable(phy->clk);
-
- return 0;
-}
-
-static inline void null_phy_set_tristate(bool enable)
-{
- int tristate = (enable) ? TEGRA_TRI_TRISTATE : TEGRA_TRI_NORMAL;
-
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- tegra_pinmux_set_tristate(TEGRA_PINGROUP_UDA, tristate);
- tegra_pinmux_set_tristate(TEGRA_PINGROUP_UAA, tristate);
- tegra_pinmux_set_tristate(TEGRA_PINGROUP_UAB, tristate);
-#else
- tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA0, tristate);
- tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA1, tristate);
- tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA2, tristate);
- tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA3, tristate);
- tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA4, tristate);
- tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA5, tristate);
- tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA6, tristate);
- tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA7, tristate);
- tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_NXT, tristate);
-
- if (enable)
- tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DIR, tristate);
-#endif
+ return status;
}
-
-static void null_phy_restore_start(struct tegra_usb_phy *phy,
- enum tegra_usb_phy_port_speed port_speed)
+int tegra_usb_phy_init(struct tegra_usb_phy *phy)
{
- struct tegra_ulpi_config *config = phy->config;
-
- if (config->phy_restore_start)
- config->phy_restore_start();
-}
+ int status = 0;
-static void null_phy_restore_end(struct tegra_usb_phy *phy)
-{
- unsigned long val;
- void __iomem *base = phy->regs;
- struct tegra_ulpi_config *config = phy->config;
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
- /* disable ULPI pinmux bypass */
- ulpi_pinmux_bypass(phy, false);
+ if (phy->pdata->ops && phy->pdata->ops->init)
+ phy->pdata->ops->init();
- /* driving linestate using GPIO */
- gpio_set_value(config->ulpi_d0_gpio, 0);
- gpio_set_value(config->ulpi_d1_gpio, 0);
+ if (phy->ops && phy->ops->init)
+ status = phy->ops->init(phy);
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- /* driving DIR high */
- gpio_set_value(config->ulpi_dir_gpio, 1);
-#endif
-
- /* remove ULPI tristate */
- null_phy_set_tristate(false);
-
- if (config->phy_restore_end)
- config->phy_restore_end();
-
- if (gpio_is_valid(config->phy_restore_gpio)) {
- int phy_restore_gpio = config->phy_restore_gpio;
- int retry = 20000;
-
- while (retry) {
- /* poll phy_restore_gpio high */
- if (gpio_get_value(phy_restore_gpio))
- break;
- retry--;
- }
-
- if (retry == 0)
- pr_info("phy_restore_gpio timeout\n");
- }
-
- /* enable ULPI CLK output pad */
- val = readl(base + ULPI_TIMING_CTRL_0);
- val |= ULPI_CLK_PADOUT_ENA;
- writel(val, base + ULPI_TIMING_CTRL_0);
-
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- udelay(5); /* wait for CLK stabilize */
-
- /* enable ULPI pinmux bypass */
- ulpi_pinmux_bypass(phy, true);
-#else
- /* enable ULPI pinmux bypass */
- ulpi_pinmux_bypass(phy, true);
- udelay(5);
-
- /* remove DIR tristate */
- tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DIR, TEGRA_TRI_NORMAL);
-#endif
+ return status;
}
-static int null_phy_power_on(struct tegra_usb_phy *phy, bool is_dpd)
+int tegra_usb_phy_power_off(struct tegra_usb_phy *phy)
{
- const struct tegra_ulpi_trimmer default_trimmer = {0, 0, 4, 4};
- unsigned long val;
- void __iomem *base = phy->regs;
- struct tegra_ulpi_config *config = phy->config;
- static bool cold_boot = true;
+ int err = 0;
- if (!config->trimmer)
- config->trimmer = &default_trimmer;
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
- ulpi_phy_reset(base);
+ if (!phy->phy_power_on)
+ return err;
-#ifndef CONFIG_ARCH_TEGRA_2x_SOC
- /* remove ULPI PADS CLKEN reset */
- val = readl(base + USB_SUSP_CTRL);
- val &= ~ULPI_PADS_CLKEN_RESET;
- writel(val, base + USB_SUSP_CTRL);
- udelay(10);
-#endif
- val = readl(base + ULPI_TIMING_CTRL_0);
- val |= ULPI_OUTPUT_PINMUX_BYP | ULPI_CLKOUT_PINMUX_BYP;
- writel(val, base + ULPI_TIMING_CTRL_0);
-
- if (config->pre_phy_on && config->pre_phy_on())
- return -EAGAIN;
-
- val = readl(base + USB_SUSP_CTRL);
- val |= ULPI_PHY_ENABLE;
- writel(val, base + USB_SUSP_CTRL);
- udelay(10);
-
- /* set timming parameters */
- val = readl(base + ULPI_TIMING_CTRL_0);
- val |= ULPI_SHADOW_CLK_LOOPBACK_EN;
-#ifndef CONFIG_ARCH_TEGRA_2x_SOC
- val &= ~ULPI_SHADOW_CLK_SEL;
- val &= ~ULPI_LBK_PAD_EN;
-#else
- val |= ULPI_SHADOW_CLK_SEL;
- val |= ULPI_LBK_PAD_EN;
-#endif
- val |= ULPI_SHADOW_CLK_DELAY(config->trimmer->shadow_clk_delay);
- val |= ULPI_CLOCK_OUT_DELAY(config->trimmer->clock_out_delay);
- val |= ULPI_LBK_PAD_E_INPUT_OR;
- writel(val, base + ULPI_TIMING_CTRL_0);
-
- writel(0, base + ULPI_TIMING_CTRL_1);
- udelay(10);
-
- /* start internal 60MHz clock */
- val = readl(base + ULPIS2S_CTRL);
- val |= ULPIS2S_ENA;
- val |= ULPIS2S_SUPPORT_DISCONNECT;
- val |= ULPIS2S_SPARE((phy->mode == TEGRA_USB_PHY_MODE_HOST) ? 3 : 1);
- val |= ULPIS2S_PLLU_MASTER_BLASTER60;
- writel(val, base + ULPIS2S_CTRL);
-
- /* select ULPI_CORE_CLK_SEL to SHADOW_CLK */
- val = readl(base + ULPI_TIMING_CTRL_0);
- val |= ULPI_CORE_CLK_SEL;
- writel(val, base + ULPI_TIMING_CTRL_0);
- udelay(10);
-
- /* enable ULPI null phy clock - can't set the trimmers before this */
- val = readl(base + ULPI_TIMING_CTRL_0);
- val |= ULPI_CLK_OUT_ENA;
- writel(val, base + ULPI_TIMING_CTRL_0);
- udelay(10);
-
- if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID,
- USB_PHY_CLK_VALID)) {
- pr_err("%s: timeout waiting for phy to stabilize\n", __func__);
- return -ETIMEDOUT;
+ if (phy->ops && phy->ops->power_off) {
+ if (phy->pdata->ops && phy->pdata->ops->pre_phy_off)
+ phy->pdata->ops->pre_phy_off();
+ err = phy->ops->power_off(phy);
+ if (phy->pdata->ops && phy->pdata->ops->post_phy_off)
+ phy->pdata->ops->post_phy_off();
}
- /* set ULPI trimmers */
- ulpi_set_trimmer(base, config->trimmer->data_trimmer,
- config->trimmer->stpdirnxt_trimmer, 1);
-
- ulpi_set_host(base);
-
-#ifndef CONFIG_ARCH_TEGRA_2x_SOC
- /* remove slave0 reset */
- val = readl(base + USB_SUSP_CTRL);
- val &= ~ULPIS2S_SLV0_RESET;
- writel(val, base + USB_SUSP_CTRL);
-
- /* remove slave1 and line reset */
- val = readl(base + USB_SUSP_CTRL);
- val &= ~ULPIS2S_SLV1_RESET;
- val &= ~ULPIS2S_LINE_RESET;
-
- /* remove ULPI PADS reset */
- val &= ~ULPI_PADS_RESET;
- writel(val, base + USB_SUSP_CTRL);
-#endif
- if (cold_boot) {
- val = readl(base + ULPI_TIMING_CTRL_0);
- val |= ULPI_CLK_PADOUT_ENA;
- writel(val, base + ULPI_TIMING_CTRL_0);
- cold_boot = false;
+ clk_disable(phy->emc_clk);
+ 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)
+ clk_disable(phy->ctrlr_clk);
+ } else {
+ /* In device mode clock is turned on by pmu irq handler
+ * if pmu irq is not available clocks will not be turned off/on
+ */
+ if (phy->pdata->u_data.dev.vbus_pmu_irq) {
+ clk_disable(phy->ctrlr_clk);
+ phy->ctrl_clk_on = false;
+ }
}
- udelay(10);
-
- if (config->post_phy_on && config->post_phy_on())
- return -EAGAIN;
-
- return 0;
-}
-
-static int null_phy_power_off(struct tegra_usb_phy *phy, bool is_dpd)
-{
- struct tegra_ulpi_config *config = phy->config;
-
- if (config->pre_phy_off && config->pre_phy_off())
- return -EAGAIN;
-
- null_phy_set_tristate(true);
-
- if (config->post_phy_off && config->post_phy_off())
- return -EAGAIN;
-
- return 0;
-}
-
-static int null_phy_pre_usbcmd_reset(struct tegra_usb_phy *phy, bool is_dpd)
-{
-#ifndef CONFIG_ARCH_TEGRA_2x_SOC
- unsigned long val;
- void __iomem *base = phy->regs;
-
- val = readl(base + ULPIS2S_CTRL);
- val |= ULPIS2S_SLV0_CLAMP_XMIT;
- writel(val, base + ULPIS2S_CTRL);
-
- val = readl(base + USB_SUSP_CTRL);
- val |= ULPIS2S_SLV0_RESET;
- writel(val, base + USB_SUSP_CTRL);
- udelay(10);
-#endif
- return 0;
-}
-
-static int null_phy_post_usbcmd_reset(struct tegra_usb_phy *phy, bool is_dpd)
-{
-#ifndef CONFIG_ARCH_TEGRA_2x_SOC
- unsigned long val;
- void __iomem *base = phy->regs;
-
- ulpi_set_host(base);
+ 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;
+ }
- /* remove slave0 reset */
- val = readl(base + USB_SUSP_CTRL);
- val &= ~ULPIS2S_SLV0_RESET;
- writel(val, base + USB_SUSP_CTRL);
+ phy->phy_power_on = false;
- val = readl(base + ULPIS2S_CTRL);
- val &= ~ULPIS2S_SLV0_CLAMP_XMIT;
- writel(val, base + ULPIS2S_CTRL);
- udelay(10);
-#endif
- return 0;
+ return err;
}
-static int uhsic_phy_power_on(struct tegra_usb_phy *phy, bool is_dpd)
+int tegra_usb_phy_power_on(struct tegra_usb_phy *phy)
{
- unsigned long val;
- void __iomem *base = phy->regs;
- struct tegra_uhsic_config *uhsic_config = phy->config;
-
-#ifndef CONFIG_ARCH_TEGRA_2x_SOC
- uhsic_powerup_pmc_wake_detect(phy);
-#endif
-
- if (uhsic_config->enable_gpio != -1) {
- gpio_set_value_cansleep(uhsic_config->enable_gpio, 1);
- /* keep hsic reset asserted for 1 ms */
- udelay(1000);
- }
-
- val = readl(base + UHSIC_PADS_CFG1);
- val &= ~(UHSIC_PD_BG | UHSIC_PD_TX | UHSIC_PD_TRK | UHSIC_PD_RX |
- UHSIC_PD_ZI | UHSIC_RPD_DATA | UHSIC_RPD_STROBE);
- val |= UHSIC_RX_SEL;
- writel(val, base + UHSIC_PADS_CFG1);
- udelay(2);
-
- val = readl(base + USB_SUSP_CTRL);
- val |= UHSIC_RESET;
- writel(val, base + USB_SUSP_CTRL);
- udelay(30);
-
- val = readl(base + USB_SUSP_CTRL);
- val |= UHSIC_PHY_ENABLE;
- writel(val, base + USB_SUSP_CTRL);
-
- val = readl(base + UHSIC_HSRX_CFG0);
- val |= UHSIC_IDLE_WAIT(uhsic_config->idle_wait_delay);
- val |= UHSIC_ELASTIC_UNDERRUN_LIMIT(uhsic_config->elastic_underrun_limit);
- val |= UHSIC_ELASTIC_OVERRUN_LIMIT(uhsic_config->elastic_overrun_limit);
- writel(val, base + UHSIC_HSRX_CFG0);
-
- val = readl(base + UHSIC_HSRX_CFG1);
- val |= UHSIC_HS_SYNC_START_DLY(uhsic_config->sync_start_delay);
- writel(val, base + UHSIC_HSRX_CFG1);
-
-#ifdef CONFIG_ARCH_TEGRA_3x_SOC
- /* WAR HSIC TX */
- val = readl(base + UHSIC_TX_CFG0);
- val &= ~UHSIC_HS_READY_WAIT_FOR_VALID;
- writel(val, base + UHSIC_TX_CFG0);
-#endif
-
- val = readl(base + UHSIC_MISC_CFG0);
- val |= UHSIC_SUSPEND_EXIT_ON_EDGE;
-#ifdef CONFIG_ARCH_TEGRA_3x_SOC
- /* Disable generic bus reset, to allow AP30 specific bus reset*/
- val |= UHSIC_DISABLE_BUSRESET;
-#endif
- writel(val, base + UHSIC_MISC_CFG0);
-
- val = readl(base + UHSIC_MISC_CFG1);
- val |= UHSIC_PLLU_STABLE_COUNT(phy->freq->stable_count);
- writel(val, base + UHSIC_MISC_CFG1);
-
- val = readl(base + UHSIC_PLL_CFG1);
- val |= UHSIC_PLLU_ENABLE_DLY_COUNT(phy->freq->enable_delay);
- val |= UHSIC_XTAL_FREQ_COUNT(phy->freq->xtal_freq_count);
- writel(val, base + UHSIC_PLL_CFG1);
+ int status = 0;
- val = readl(base + USB_SUSP_CTRL);
- val &= ~(UHSIC_RESET);
- writel(val, base + USB_SUSP_CTRL);
- udelay(2);
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- val = readl(base + USB_PORTSC1);
- val &= ~USB_PORTSC1_PTS(~0);
- writel(val, base + USB_PORTSC1);
+ if (phy->phy_power_on)
+ return status;
-#endif
-#ifndef CONFIG_ARCH_TEGRA_2x_SOC
- val = readl(base + TEGRA_USB_USBMODE_REG_OFFSET);
- val |= TEGRA_USB_USBMODE_HOST;
- writel(val, base + TEGRA_USB_USBMODE_REG_OFFSET);
-
- /* Change the USB controller PHY type to HSIC */
- 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);
-#endif
- 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);
+ if (phy->vdd_reg && !phy->vdd_reg_on) {
+ regulator_enable(phy->vdd_reg);
+ phy->vdd_reg_on = true;
}
- val = readl(base + USB_PORTSC1);
- val &= ~(USB_PORTSC1_WKOC | USB_PORTSC1_WKDS | USB_PORTSC1_WKCN);
- writel(val, base + USB_PORTSC1);
-
- val = readl(base + UHSIC_PADS_CFG0);
- val &= ~(UHSIC_TX_RTUNEN);
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- /* set Rtune impedance to 40 ohm */
- val |= UHSIC_TX_RTUNE(0);
-#else
- /* set Rtune impedance to 50 ohm */
- val |= UHSIC_TX_RTUNE(8);
-#endif
- writel(val, base + UHSIC_PADS_CFG0);
-
- if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID,
- USB_PHY_CLK_VALID)) {
- pr_err("%s: timeout waiting for phy to stabilize\n", __func__);
- return -ETIMEDOUT;
+ /* In device mode clock is turned on by pmu irq handler
+ * if pmu irq is not available clocks will not be turned off/on
+ */
+ if (phy->pdata->op_mode == TEGRA_USB_OPMODE_HOST) {
+ if (!phy->pdata->u_data.host.hot_plug &&
+ !phy->pdata->u_data.host.remote_wakeup_supported)
+ clk_enable(phy->ctrlr_clk);
+ } else {
+ if (phy->pdata->u_data.dev.vbus_pmu_irq &&
+ !phy->ctrl_clk_on) {
+ clk_enable(phy->ctrlr_clk);
+ phy->ctrl_clk_on = true;
+ }
}
+ clk_enable(phy->sys_clk);
+ clk_enable(phy->emc_clk);
- return 0;
-}
-
-static int uhsic_phy_power_off(struct tegra_usb_phy *phy, bool is_dpd)
-{
- unsigned long val;
- void __iomem *base = phy->regs;
- struct tegra_uhsic_config *uhsic_config = phy->config;
-
- val = readl(base + UHSIC_PADS_CFG1);
- val &= ~UHSIC_RPU_STROBE;
- val |= UHSIC_RPD_STROBE;
- writel(val, base + UHSIC_PADS_CFG1);
-
- val = readl(base + USB_SUSP_CTRL);
- val |= UHSIC_RESET;
- writel(val, base + USB_SUSP_CTRL);
- udelay(30);
-
- if (uhsic_config->enable_gpio != -1) {
- gpio_set_value_cansleep(uhsic_config->enable_gpio, 0);
- /* keep hsic reset de-asserted for 1 ms */
- udelay(1000);
+ if (phy->ops && phy->ops->power_on) {
+ if (phy->pdata->ops && phy->pdata->ops->pre_phy_on)
+ phy->pdata->ops->pre_phy_on();
+ status = phy->ops->power_on(phy);
+ if (phy->pdata->ops && phy->pdata->ops->post_phy_on)
+ phy->pdata->ops->post_phy_on();
}
- if (uhsic_config->post_phy_off && uhsic_config->post_phy_off())
- return -EAGAIN;
-#ifndef CONFIG_ARCH_TEGRA_2x_SOC
- uhsic_powerdown_pmc_wake_detect(phy);
-#endif
+ phy->phy_power_on = true;
- return 0;
+ return status;
}
-#ifdef CONFIG_USB_TEGRA_OTG
-extern void tegra_otg_check_vbus_detection(void);
-#endif
-
-static irqreturn_t usb_phy_vbus_irq_thr(int irq, void *pdata)
+int tegra_usb_phy_reset(struct tegra_usb_phy *phy)
{
- struct tegra_usb_phy *phy = pdata;
-
- if (phy->reg_vdd && !phy->regulator_on) {
- regulator_enable(phy->reg_vdd);
- phy->regulator_on = 1;
- /*
- * Optimal time to get the regulator turned on
- * before detecting vbus interrupt.
- */
- mdelay(15);
- }
+ int status = 0;
-#ifdef CONFIG_USB_TEGRA_OTG
- tegra_otg_check_vbus_detection();
-#endif
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ if (phy->ops && phy->ops->reset)
+ status = phy->ops->reset(phy);
- return IRQ_HANDLED;
+ return status;
}
-
-struct tegra_usb_phy *tegra_usb_phy_open(int instance, void __iomem *regs,
- void *config, enum tegra_usb_phy_mode phy_mode,
- enum tegra_usb_phy_type usb_phy_type)
+int tegra_usb_phy_pre_suspend(struct tegra_usb_phy *phy)
{
- struct tegra_usb_phy *phy;
- struct tegra_ulpi_config *ulpi_config;
- unsigned long parent_rate;
- int i;
- int err;
-#ifndef CONFIG_ARCH_TEGRA_2x_SOC
- struct tegra_uhsic_config *uhsic_config;
- int reset_gpio, enable_gpio;
-#endif
+ int status = 0;
- phy = kzalloc(sizeof(struct tegra_usb_phy), GFP_KERNEL);
- if (!phy)
- return ERR_PTR(-ENOMEM);
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
- phy->instance = instance;
- phy->regs = regs;
- phy->config = config;
- phy->mode = phy_mode;
- phy->usb_phy_type = usb_phy_type;
- phy->initialized = 0;
- phy->regulator_on = 0;
- phy->power_on = 0;
- phy->remote_wakeup = false;
- phy->hotplug = 0;
- phy->xcvr_setup_value = 0;
-
- if (!phy->config) {
- if (phy->usb_phy_type == TEGRA_USB_PHY_TYPE_LINK_ULPI ||
- phy->usb_phy_type == TEGRA_USB_PHY_TYPE_NULL_ULPI) {
- pr_err("%s: ulpi phy configuration missing", __func__);
- err = -EINVAL;
- goto err0;
- } else {
- phy->config = &utmip_default[instance];
- }
- }
+ if (phy->pdata->ops && phy->pdata->ops->pre_suspend)
+ phy->pdata->ops->pre_suspend();
- phy->pll_u = clk_get_sys(NULL, "pll_u");
- if (IS_ERR(phy->pll_u)) {
- pr_err("Can't get pll_u clock\n");
- err = PTR_ERR(phy->pll_u);
- goto err0;
- }
- clk_enable(phy->pll_u);
-
- parent_rate = clk_get_rate(clk_get_parent(phy->pll_u));
- if (phy->usb_phy_type == TEGRA_USB_PHY_TYPE_HSIC) {
- for (i = 0; i < ARRAY_SIZE(tegra_uhsic_freq_table); i++) {
- if (tegra_uhsic_freq_table[i].freq == parent_rate) {
- phy->freq = &tegra_uhsic_freq_table[i];
- break;
- }
- }
- } else {
- for (i = 0; i < ARRAY_SIZE(tegra_freq_table); i++) {
- if (tegra_freq_table[i].freq == parent_rate) {
- phy->freq = &tegra_freq_table[i];
- break;
- }
- }
- }
- if (!phy->freq) {
- pr_err("invalid pll_u parent rate %ld\n", parent_rate);
- err = -EINVAL;
- goto err1;
- }
-
- if (phy->usb_phy_type == TEGRA_USB_PHY_TYPE_UTMIP) {
- err = utmip_pad_open(phy);
- phy->xcvr_setup_value = tegra_phy_xcvr_setup_value(phy->config);
- if (err < 0)
- goto err1;
- } else if (phy->usb_phy_type == TEGRA_USB_PHY_TYPE_LINK_ULPI) {
- ulpi_config = config;
-
- if (ulpi_config->clk) {
- phy->clk = clk_get_sys(NULL, ulpi_config->clk);
- if (IS_ERR(phy->clk)) {
- pr_err("%s: can't get ulpi clock\n", __func__);
- err = -ENXIO;
- goto err1;
- }
- } else {
- /* Some USB ULPI chips are not driven by Tegra clocks or PLL */
- phy->clk = NULL;
- }
- tegra_gpio_enable(ulpi_config->reset_gpio);
- gpio_request(ulpi_config->reset_gpio, "ulpi_phy_reset_b");
- gpio_direction_output(ulpi_config->reset_gpio, 0);
- phy->ulpi = otg_ulpi_create(&ulpi_viewport_access_ops, 0);
- phy->ulpi->io_priv = regs + ULPI_VIEWPORT;
- }
-#ifndef CONFIG_ARCH_TEGRA_2x_SOC
- else if (phy->usb_phy_type == TEGRA_USB_PHY_TYPE_HSIC) {
- uhsic_config = config;
- enable_gpio = gpio_request(uhsic_config->enable_gpio,
- "uhsic_enable");
- reset_gpio = gpio_request(uhsic_config->reset_gpio,
- "uhsic_reset");
- /* hsic enable signal deasserted, hsic reset asserted */
- if (!enable_gpio)
- gpio_direction_output(uhsic_config->enable_gpio,
- 0 /* deasserted */);
- if (!reset_gpio)
- gpio_direction_output(uhsic_config->reset_gpio,
- 0 /* asserted */);
- if (!enable_gpio)
- tegra_gpio_enable(uhsic_config->enable_gpio);
- if (!reset_gpio)
- tegra_gpio_enable(uhsic_config->reset_gpio);
- /* keep hsic reset asserted for 1 ms */
- udelay(1000);
- /* enable (power on) hsic */
- if (!enable_gpio)
- gpio_set_value_cansleep(uhsic_config->enable_gpio, 1);
- udelay(1000);
- /* deassert reset */
- if (!reset_gpio)
- gpio_set_value_cansleep(uhsic_config->reset_gpio, 1);
- }
-#endif
-
- phy->reg_vdd = regulator_get(NULL, "avdd_usb");
- if (IS_ERR_OR_NULL(phy->reg_vdd)) {
- pr_err("couldn't get regulator avdd_usb: %ld \n",
- PTR_ERR(phy->reg_vdd));
- phy->reg_vdd = NULL;
- }
-
- if (instance == 0 && usb_phy_data[0].vbus_irq) {
- err = request_threaded_irq(usb_phy_data[0].vbus_irq, NULL, usb_phy_vbus_irq_thr, IRQF_SHARED,
- "usb_phy_vbus", phy);
- if (err) {
- pr_err("Failed to register IRQ\n");
- goto err1;
- }
- }
-
-#ifndef CONFIG_ARCH_TEGRA_2x_SOC
- /* Power-up the VBUS detector for UTMIP PHY */
- if (phy->usb_phy_type == TEGRA_USB_PHY_TYPE_UTMIP) {
- unsigned long val;
- void __iomem *pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
-
- /* turn on pad detectors for HSIC*/
- val = readl(pmc_base + PMC_USB_AO);
- val &= ~(TEGRA_PMC_USB_AO_VBUS_WAKEUP_PD_P0 | TEGRA_PMC_USB_AO_ID_PD_P0);
- writel(val, pmc_base + PMC_USB_AO);
-
- utmip_powerup_pmc_wake_detect(phy);
-
- if (usb_phy_data[phy->instance].vbus_reg_supply) {
- phy->reg_vbus = regulator_get(NULL, usb_phy_data[phy->instance].vbus_reg_supply);
- if (WARN_ON(IS_ERR_OR_NULL(phy->reg_vbus))) {
- pr_err("couldn't get regulator vdd_vbus_usb: %ld, instance : %d\n",
- PTR_ERR(phy->reg_vbus), phy->instance);
- err = PTR_ERR(phy->reg_vbus);
- goto err1;
- }
- }
- }
- if (phy->usb_phy_type == TEGRA_USB_PHY_TYPE_HSIC) {
- uhsic_powerup_pmc_wake_detect(phy);
- }
+ if (phy->ops && phy->ops->pre_suspend)
+ status = phy->ops->pre_suspend(phy);
-#endif
- if (((instance == 2) || (instance == 0)) &&
- (phy->mode == TEGRA_USB_PHY_MODE_HOST)) {
- vbus_enable(phy);
- }
- return phy;
-
-err1:
- clk_disable(phy->pll_u);
- clk_put(phy->pll_u);
-err0:
- kfree(phy);
- return ERR_PTR(err);
+ return status;
}
-EXPORT_SYMBOL_GPL(tegra_usb_phy_open);
-
-int tegra_usb_phy_power_on(struct tegra_usb_phy *phy, bool is_dpd)
+int tegra_usb_phy_suspend(struct tegra_usb_phy *phy)
{
- int ret = 0;
-
- const tegra_phy_fp power_on[] = {
- utmi_phy_power_on,
- ulpi_phy_power_on,
- null_phy_power_on,
- uhsic_phy_power_on,
- };
+ int err = 0;
- if (phy->power_on)
- return ret;
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
- if ((phy->instance == 0) && usb_phy_data[0].vbus_irq &&
- (phy->mode == TEGRA_USB_PHY_MODE_DEVICE))
- is_dpd = true;
+ if (phy->ops && phy->ops->suspend)
+ err = phy->ops->suspend(phy);
- if (phy->reg_vdd && !phy->regulator_on) {
- regulator_enable(phy->reg_vdd);
- phy->regulator_on = 1;
+ if (!err && phy->pdata->u_data.host.power_off_on_suspend) {
+ tegra_usb_phy_power_off(phy);
}
- if (power_on[phy->usb_phy_type])
- ret = power_on[phy->usb_phy_type](phy, is_dpd);
-
- phy->power_on = true;
- return ret;
+ return err;
}
-EXPORT_SYMBOL_GPL(tegra_usb_phy_power_on);
-
-void tegra_usb_phy_power_off(struct tegra_usb_phy *phy, bool is_dpd)
+int tegra_usb_phy_post_suspend(struct tegra_usb_phy *phy)
{
- const tegra_phy_fp power_off[] = {
- utmi_phy_power_off,
- ulpi_phy_power_off,
- null_phy_power_off,
- uhsic_phy_power_off,
- };
+ int status = 0;
- if (!phy->power_on)
- return;
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
- if ((phy->instance == 0) && usb_phy_data[0].vbus_irq &&
- (phy->mode == TEGRA_USB_PHY_MODE_DEVICE))
- is_dpd = true;
+ if (phy->ops && phy->ops->post_suspend)
+ status = phy->ops->post_suspend(phy);
- if (power_off[phy->usb_phy_type])
- power_off[phy->usb_phy_type](phy, is_dpd);
+ if (phy->pdata->ops && phy->pdata->ops->post_suspend)
+ phy->pdata->ops->post_suspend();
- if (phy->reg_vdd && phy->regulator_on && is_dpd) {
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- if (tegra_get_revision() >= TEGRA_REVISION_A03)
-#endif
- regulator_disable(phy->reg_vdd);
- phy->regulator_on = 0;
- }
- phy->power_on = false;
+ return status;
}
-EXPORT_SYMBOL_GPL(tegra_usb_phy_power_off);
-
-void tegra_usb_phy_preresume(struct tegra_usb_phy *phy, bool remote_wakeup)
+int tegra_usb_phy_pre_resume(struct tegra_usb_phy *phy, bool remote_wakeup)
{
- const tegra_phy_fp preresume[] = {
- utmi_phy_preresume,
- NULL,
- NULL,
- uhsic_phy_preresume,
- };
+ int status = 0;
- if (preresume[phy->usb_phy_type])
- preresume[phy->usb_phy_type](phy, remote_wakeup);
-}
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
-void tegra_usb_phy_postsuspend(struct tegra_usb_phy *phy, bool is_dpd)
+ if (phy->pdata->ops && phy->pdata->ops->pre_resume)
+ phy->pdata->ops->pre_resume();
-{
- const tegra_phy_fp postsuspend[] = {
- NULL,
- NULL,
- NULL,
- uhsic_phy_postsuspend,
- };
+ if (phy->ops && phy->ops->pre_resume)
+ status = phy->ops->pre_resume(phy, remote_wakeup);
- if (postsuspend[phy->usb_phy_type])
- postsuspend[phy->usb_phy_type](phy, is_dpd);
-}
-
-void tegra_usb_phy_postresume(struct tegra_usb_phy *phy, bool is_dpd)
-{
- const tegra_phy_fp postresume[] = {
- utmi_phy_postresume,
- NULL,
- NULL,
- uhsic_phy_postresume,
- };
-
- if (postresume[phy->usb_phy_type])
- postresume[phy->usb_phy_type](phy, is_dpd);
+ return status;
}
-
-void tegra_ehci_pre_reset(struct tegra_usb_phy *phy, bool is_dpd)
+int tegra_usb_phy_resume(struct tegra_usb_phy *phy)
{
- const tegra_phy_fp pre_reset[] = {
- NULL,
- NULL,
- null_phy_pre_usbcmd_reset,
- NULL,
- };
+ int err = 0;
- if (pre_reset[phy->usb_phy_type])
- pre_reset[phy->usb_phy_type](phy, is_dpd);
-}
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
-void tegra_ehci_post_reset(struct tegra_usb_phy *phy, bool is_dpd)
-{
- const tegra_phy_fp post_reset[] = {
- NULL,
- NULL,
- null_phy_post_usbcmd_reset,
- NULL,
- };
+ if (phy->pdata->u_data.host.power_off_on_suspend) {
+ tegra_usb_phy_power_on(phy);
+ }
- if (post_reset[phy->usb_phy_type])
- post_reset[phy->usb_phy_type](phy, is_dpd);
-}
+ if (!err && phy->ops && phy->ops->resume)
+ err = phy->ops->resume(phy);
-void tegra_ehci_phy_restore_start(struct tegra_usb_phy *phy,
- enum tegra_usb_phy_port_speed port_speed)
-{
- const tegra_phy_restore_start_fp phy_restore_start[] = {
- utmi_phy_restore_start,
- ulpi_phy_restore_start,
- null_phy_restore_start,
- NULL,
- };
+ return err;
- if (phy_restore_start[phy->usb_phy_type])
- phy_restore_start[phy->usb_phy_type](phy, port_speed);
}
-
-void tegra_ehci_phy_restore_end(struct tegra_usb_phy *phy)
+int tegra_usb_phy_post_resume(struct tegra_usb_phy *phy)
{
- const tegra_phy_restore_end_fp phy_restore_end[] = {
- utmi_phy_restore_end,
- ulpi_phy_restore_end,
- null_phy_restore_end,
- NULL,
- };
+ int status = 0;
- if (phy_restore_end[phy->usb_phy_type])
- phy_restore_end[phy->usb_phy_type](phy);
-}
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
-void tegra_usb_phy_clk_disable(struct tegra_usb_phy *phy)
-{
- if (phy->usb_phy_type == TEGRA_USB_PHY_TYPE_UTMIP)
- utmi_phy_clk_disable(phy);
-}
+ if (phy->ops && phy->ops->post_resume)
+ status = phy->ops->post_resume(phy);
-void tegra_usb_phy_clk_enable(struct tegra_usb_phy *phy)
-{
- if (phy->usb_phy_type == TEGRA_USB_PHY_TYPE_UTMIP)
- utmi_phy_clk_enable(phy);
-}
+ if (phy->pdata->ops && phy->pdata->ops->post_resume)
+ phy->pdata->ops->post_resume();
-void tegra_usb_phy_close(struct tegra_usb_phy *phy)
-{
- if (phy->usb_phy_type == TEGRA_USB_PHY_TYPE_UTMIP) {
- utmip_pad_close(phy);
- utmip_phy_disable_pmc_bus_ctrl(phy);
- }
- else if (phy->usb_phy_type == TEGRA_USB_PHY_TYPE_LINK_ULPI && phy->clk)
- clk_put(phy->clk);
- if (phy->mode == TEGRA_USB_PHY_MODE_HOST) {
- vbus_disable(phy);
- }
- clk_disable(phy->pll_u);
- clk_put(phy->pll_u);
- if (phy->reg_vbus)
- regulator_put(phy->reg_vbus);
- if (phy->reg_vdd)
- regulator_put(phy->reg_vdd);
- if (phy->instance == 0 && usb_phy_data[0].vbus_irq)
- free_irq(usb_phy_data[0].vbus_irq, phy);
- kfree(phy);
+ return status;
}
-EXPORT_SYMBOL_GPL(tegra_usb_phy_close);
-
-int tegra_usb_phy_bus_connect(struct tegra_usb_phy *phy)
+int tegra_usb_phy_port_power(struct tegra_usb_phy *phy)
{
- unsigned long val;
- void __iomem *base = phy->regs;
- struct tegra_uhsic_config *uhsic_config = phy->config;
-
- if (phy->usb_phy_type == TEGRA_USB_PHY_TYPE_HSIC) {
-#ifndef CONFIG_ARCH_TEGRA_2x_SOC
- val = readl(base + TEGRA_USB_USBMODE_REG_OFFSET);
- val |= TEGRA_USB_USBMODE_HOST;
- writel(val, base + TEGRA_USB_USBMODE_REG_OFFSET);
-
- /* Change the USB controller PHY type to HSIC */
- 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);
-#endif
- val = readl(base + UHSIC_MISC_CFG0);
- val |= UHSIC_DETECT_SHORT_CONNECT;
- writel(val, base + UHSIC_MISC_CFG0);
- udelay(1);
+ int status = 0;
- val = readl(base + UHSIC_MISC_CFG0);
- val |= UHSIC_FORCE_XCVR_MODE;
- writel(val, base + UHSIC_MISC_CFG0);
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
- val = readl(base + UHSIC_PADS_CFG1);
- val &= ~UHSIC_RPD_STROBE;
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- val |= UHSIC_RPU_STROBE;
-#endif
- writel(val, base + UHSIC_PADS_CFG1);
-
- if (uhsic_config->usb_phy_ready &&
- uhsic_config->usb_phy_ready())
- return -EAGAIN;
-
- /* connect detect on T30 requires extra wait */
- if (utmi_wait_register_timeout(base + UHSIC_STAT_CFG0,
- UHSIC_CONNECT_DETECT, UHSIC_CONNECT_DETECT,
- CONNECT_DETECT_TIMEOUT) < 0) {
- pr_err("%s: timeout waiting for hsic connect detect\n", __func__);
- return -ETIMEDOUT;
- }
+ if (phy->ops && phy->ops->port_power)
+ status = phy->ops->port_power(phy);
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- if (utmi_wait_register(base + USB_PORTSC1, USB_PORTSC1_LS(2), USB_PORTSC1_LS(2)) < 0) {
- pr_err("%s: timeout waiting for dplus state\n", __func__);
- return -ETIMEDOUT;
- }
-#endif
- }
-
- return 0;
+ return status;
}
-
int tegra_usb_phy_bus_reset(struct tegra_usb_phy *phy)
{
- unsigned long val;
- void __iomem *base = phy->regs;
-
- if (phy->usb_phy_type == TEGRA_USB_PHY_TYPE_HSIC) {
-#ifndef CONFIG_ARCH_TEGRA_2x_SOC
- /* Change the USB controller PHY type to HSIC */
- 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);
- /* wait here, otherwise HOSTPC1_DEVLC_PSPD will timeout */
- mdelay(5);
-#endif
- val = readl(base + USB_PORTSC1);
- val |= USB_PORTSC1_PTC(5);
- writel(val, base + USB_PORTSC1);
- udelay(2);
-
- val = readl(base + USB_PORTSC1);
- val &= ~USB_PORTSC1_PTC(~0);
- writel(val, base + USB_PORTSC1);
- udelay(2);
-
- if (utmi_wait_register(base + USB_PORTSC1, USB_PORTSC1_LS(0), 0) < 0) {
- pr_err("%s: timeout waiting for SE0\n", __func__);
- return -ETIMEDOUT;
- }
+ int status = 0;
- if (utmi_wait_register(base + USB_PORTSC1, USB_PORTSC1_CCS, USB_PORTSC1_CCS) < 0) {
- pr_err("%s: timeout waiting for connection status\n", __func__);
- return -ETIMEDOUT;
- }
-
-#if defined(CONFIG_ARCH_TEGRA_2x_SOC)
- if (utmi_wait_register(base + USB_PORTSC1, USB_PORTSC1_PSPD(2), USB_PORTSC1_PSPD(2)) < 0) {
- pr_err("%s: timeout waiting hsic high speed configuration\n", __func__);
- return -ETIMEDOUT;
- }
-#elif defined(CONFIG_ARCH_TEGRA_3x_SOC)
- if (utmi_wait_register(base + HOSTPC1_DEVLC,
- HOSTPC1_DEVLC_PSPD(2),
- HOSTPC1_DEVLC_PSPD(2)) < 0) {
- pr_err("%s: timeout waiting hsic high speed configuration\n", __func__);
- return -ETIMEDOUT;
- }
-#endif
- val = readl(base + USB_USBCMD);
- val &= ~USB_USBCMD_RS;
- writel(val, base + USB_USBCMD);
-
- if (utmi_wait_register(base + USB_USBSTS, USB_USBSTS_HCH, USB_USBSTS_HCH) < 0) {
- pr_err("%s: timeout waiting for stopping the controller\n", __func__);
- return -ETIMEDOUT;
- }
-
- val = readl(base + UHSIC_PADS_CFG1);
- val &= ~UHSIC_RPU_STROBE;
- val |= UHSIC_RPD_STROBE;
- writel(val, base + UHSIC_PADS_CFG1);
-
- mdelay(50);
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
- val = readl(base + UHSIC_PADS_CFG1);
- val &= ~UHSIC_RPD_STROBE;
- val |= UHSIC_RPU_STROBE;
- writel(val, base + UHSIC_PADS_CFG1);
+ if (phy->ops && phy->ops->bus_reset)
+ status = phy->ops->bus_reset(phy);
- val = readl(base + USB_USBCMD);
- val |= USB_USBCMD_RS;
- writel(val, base + USB_USBCMD);
-
- val = readl(base + UHSIC_PADS_CFG1);
- val &= ~UHSIC_RPU_STROBE;
- writel(val, base + UHSIC_PADS_CFG1);
-
- if (utmi_wait_register(base + USB_USBCMD, USB_USBCMD_RS, USB_USBCMD_RS) < 0) {
- pr_err("%s: timeout waiting for starting the controller\n", __func__);
- return -ETIMEDOUT;
- }
- }
-
- return 0;
+ return status;
}
-int tegra_usb_phy_bus_idle(struct tegra_usb_phy *phy)
+bool tegra_usb_phy_charger_detected(struct tegra_usb_phy *phy)
{
- unsigned long val;
- void __iomem *base = phy->regs;
- struct tegra_uhsic_config *uhsic_config = phy->config;
-
- if (phy->usb_phy_type == TEGRA_USB_PHY_TYPE_HSIC) {
-
-#ifndef CONFIG_ARCH_TEGRA_2x_SOC
- val = readl(base + TEGRA_USB_USBMODE_REG_OFFSET);
- val |= TEGRA_USB_USBMODE_HOST;
- writel(val, base + TEGRA_USB_USBMODE_REG_OFFSET);
-
- /* Change the USB controller PHY type to HSIC */
- 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);
-#endif
- val = readl(base + UHSIC_MISC_CFG0);
- val |= UHSIC_DETECT_SHORT_CONNECT;
- writel(val, base + UHSIC_MISC_CFG0);
- udelay(1);
+ bool status = 0;
- val = readl(base + UHSIC_MISC_CFG0);
- val |= UHSIC_FORCE_XCVR_MODE;
- writel(val, base + UHSIC_MISC_CFG0);
-
- val = readl(base + UHSIC_PADS_CFG1);
- val &= ~UHSIC_RPD_STROBE;
- /* safe to enable RPU on STROBE at all times during idle */
- val |= UHSIC_RPU_STROBE;
- writel(val, base + UHSIC_PADS_CFG1);
-
- val = readl(base + USB_USBCMD);
- val &= ~USB_USBCMD_RS;
- writel(val, base + USB_USBCMD);
-
- if (uhsic_config->usb_phy_ready &&
- uhsic_config->usb_phy_ready())
- return -EAGAIN;
-
- /* connect detect on T30 requires extra wait */
- if (utmi_wait_register_timeout(base + UHSIC_STAT_CFG0,
- UHSIC_CONNECT_DETECT, UHSIC_CONNECT_DETECT,
- CONNECT_DETECT_TIMEOUT) < 0) {
- pr_err("%s: timeout waiting for hsic connect detect\n",
- __func__);
- return -ETIMEDOUT;
- }
- }
- return 0;
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ if (phy->ops && phy->ops->charger_detect)
+ status = phy->ops->charger_detect(phy);
+
+ return status;
}
-bool tegra_usb_phy_is_device_connected(struct tegra_usb_phy *phy)
+bool tegra_usb_phy_hw_accessible(struct tegra_usb_phy *phy)
{
- void __iomem *base = phy->regs;
+ if (!phy->hw_accessible)
+ DBG("%s(%d) inst:[%d] Not Accessible\n", __func__,
+ __LINE__, phy->inst);
- if (phy->usb_phy_type == TEGRA_USB_PHY_TYPE_HSIC) {
- if (utmi_wait_register(base + UHSIC_STAT_CFG0,
- UHSIC_CONNECT_DETECT, UHSIC_CONNECT_DETECT) < 0) {
- pr_err("%s: no hsic connection\n", __func__);
- return false;
- }
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- if (utmi_wait_register(base + USB_PORTSC1, USB_PORTSC1_LS(2), USB_PORTSC1_LS(2)) < 0) {
- pr_err("%s: timeout waiting for dplus state\n", __func__);
- return false;
- }
-#endif
- }
- return true;
+ return phy->hw_accessible;
}
-bool tegra_usb_phy_charger_detect(struct tegra_usb_phy *phy)
+bool tegra_usb_phy_remote_wakeup(struct tegra_usb_phy *phy)
{
- unsigned long val;
- void __iomem *base = phy->regs;
- bool status;
-
- if (phy->usb_phy_type != TEGRA_USB_PHY_TYPE_UTMIP)
- {
- /* Charger detection is not there for ULPI
- * return Charger not available */
- return false;
- }
-
- /* Enable charger detection logic */
- val = readl(base + UTMIP_BAT_CHRG_CFG0);
- val |= UTMIP_OP_SRC_EN | UTMIP_ON_SINK_EN;
- writel(val, base + UTMIP_BAT_CHRG_CFG0);
-
- /* Source should be on for 100 ms as per USB charging spec */
- msleep(TDP_SRC_ON_MS);
-
- val = readl(base + USB_PHY_VBUS_WAKEUP_ID);
- /* If charger is not connected disable the interrupt */
- val &= ~VDAT_DET_INT_EN;
- val |= VDAT_DET_CHG_DET;
- writel(val,base + USB_PHY_VBUS_WAKEUP_ID);
-
- val = readl(base + USB_PHY_VBUS_WAKEUP_ID);
- if (val & VDAT_DET_STS)
- status = true;
- else
- status = false;
-
- /* Disable charger detection logic */
- val = readl(base + UTMIP_BAT_CHRG_CFG0);
- val &= ~(UTMIP_OP_SRC_EN | UTMIP_ON_SINK_EN);
- writel(val, base + UTMIP_BAT_CHRG_CFG0);
-
- /* Delay of 40 ms before we pull the D+ as per battery charger spec */
- msleep(TDPSRC_CON_MS);
-
- return status;
+ return phy->remote_wakeup;
}
-EXPORT_SYMBOL_GPL(tegra_usb_phy_charger_detect);
-#ifndef CONFIG_ARCH_TEGRA_2x_SOC
-void tegra_usb_phy_power_down_pmc(void)
+bool tegra_usb_phy_has_hostpc(struct tegra_usb_phy *phy)
{
- unsigned long val;
- void __iomem *pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
-
- /* power down all 3 UTMIP interfaces */
- val = readl(pmc_base + PMC_UTMIP_MASTER_CONFIG);
- val |= UTMIP_PWR(0) | UTMIP_PWR(1) | UTMIP_PWR(2);
- writel(val, pmc_base + PMC_UTMIP_MASTER_CONFIG);
-
- /* turn on pad detectors */
- writel(PMC_POWER_DOWN_MASK, pmc_base + PMC_USB_AO);
-
- /* setup sleep walk fl all 3 usb controllers */
- val = UTMIP_USBOP_RPD_A | UTMIP_USBON_RPD_A | UTMIP_HIGHZ_A |
- UTMIP_USBOP_RPD_B | UTMIP_USBON_RPD_B | UTMIP_HIGHZ_B |
- UTMIP_USBOP_RPD_C | UTMIP_USBON_RPD_C | UTMIP_HIGHZ_C |
- UTMIP_USBOP_RPD_D | UTMIP_USBON_RPD_D | UTMIP_HIGHZ_D;
- writel(val, pmc_base + PMC_SLEEPWALK_REG(0));
- writel(val, pmc_base + PMC_SLEEPWALK_REG(1));
- writel(val, pmc_base + PMC_SLEEPWALK_REG(2));
-
- /* enable pull downs on HSIC PMC */
- val = UHSIC_STRB_RPD_A | UHSIC_DATA_RPD_A | UHSIC_STRB_RPD_B |
- UHSIC_DATA_RPD_B | UHSIC_STRB_RPD_C | UHSIC_DATA_RPD_C |
- UHSIC_STRB_RPD_D | UHSIC_DATA_RPD_D;
- writel(val, pmc_base + UHSIC_SLEEPWALK_REG);
-
- /* Turn over pad configuration to PMC */
- val = readl(pmc_base + PMC_SLEEP_CFG);
- val &= ~UTMIP_WAKE_VAL(0, ~0);
- val &= ~UTMIP_WAKE_VAL(1, ~0);
- val &= ~UTMIP_WAKE_VAL(2, ~0);
- val &= ~UHSIC_WAKE_VAL_P0(~0);
- val |= UTMIP_WAKE_VAL(0, WAKE_VAL_NONE) | UHSIC_WAKE_VAL_P0(WAKE_VAL_NONE) |
- UTMIP_WAKE_VAL(1, WAKE_VAL_NONE) | UTMIP_WAKE_VAL(2, WAKE_VAL_NONE) |
- UTMIP_RCTRL_USE_PMC(0) | UTMIP_RCTRL_USE_PMC(1) | UTMIP_RCTRL_USE_PMC(2) |
- UTMIP_TCTRL_USE_PMC(0) | UTMIP_TCTRL_USE_PMC(1) | UTMIP_TCTRL_USE_PMC(2) |
- UTMIP_FSLS_USE_PMC(0) | UTMIP_FSLS_USE_PMC(1) | UTMIP_FSLS_USE_PMC(2) |
- UTMIP_MASTER_ENABLE(0) | UTMIP_MASTER_ENABLE(1) | UTMIP_MASTER_ENABLE(2) |
- UHSIC_MASTER_ENABLE_P0;
- writel(val, pmc_base + PMC_SLEEP_CFG);
+ return phy->pdata->has_hostpc;
}
-#endif
-int __init tegra_usb_phy_init(struct usb_phy_plat_data *pdata, int size)
+bool tegra_usb_phy_otg_supported(struct tegra_usb_phy *phy)
{
- if (pdata) {
- int i;
-
- for (i = 0; i < size; i++, pdata++) {
- usb_phy_data[pdata->instance].instance = pdata->instance;
- usb_phy_data[pdata->instance].vbus_irq = pdata->vbus_irq;
- usb_phy_data[pdata->instance].vbus_gpio = pdata->vbus_gpio;
- usb_phy_data[pdata->instance].vbus_gpio_inverted = pdata->vbus_gpio_inverted;
- usb_phy_data[pdata->instance].vbus_reg_supply = pdata->vbus_reg_supply;
- }
- }
-
-#ifndef CONFIG_ARCH_TEGRA_2x_SOC
- tegra_usb_phy_power_down_pmc();
-#endif
-
- return 0;
+ return phy->pdata->port_otg;
}
void tegra_usb_phy_memory_prefetch_on(struct tegra_usb_phy *phy)
@@ -3226,7 +699,7 @@ void tegra_usb_phy_memory_prefetch_on(struct tegra_usb_phy *phy)
void __iomem *ahb_gizmo = IO_ADDRESS(TEGRA_AHB_GIZMO_BASE);
unsigned long val;
- if (phy->instance == 0 && phy->mode == TEGRA_USB_PHY_MODE_DEVICE) {
+ if (phy->inst == 0 && phy->pdata->op_mode == TEGRA_USB_OPMODE_DEVICE) {
val = readl(ahb_gizmo + AHB_MEM_PREFETCH_CFG1);
val |= PREFETCH_ENB;
writel(val, ahb_gizmo + AHB_MEM_PREFETCH_CFG1);
@@ -3235,14 +708,13 @@ void tegra_usb_phy_memory_prefetch_on(struct tegra_usb_phy *phy)
writel(val, ahb_gizmo + AHB_MEM_PREFETCH_CFG2);
}
}
-EXPORT_SYMBOL_GPL(tegra_usb_phy_memory_prefetch_on);
void tegra_usb_phy_memory_prefetch_off(struct tegra_usb_phy *phy)
{
void __iomem *ahb_gizmo = IO_ADDRESS(TEGRA_AHB_GIZMO_BASE);
unsigned long val;
- if (phy->instance == 0 && phy->mode == TEGRA_USB_PHY_MODE_DEVICE) {
+ if (phy->inst == 0 && phy->pdata->op_mode == TEGRA_USB_OPMODE_DEVICE) {
val = readl(ahb_gizmo + AHB_MEM_PREFETCH_CFG1);
val &= ~(PREFETCH_ENB);
writel(val, ahb_gizmo + AHB_MEM_PREFETCH_CFG1);
@@ -3251,39 +723,3 @@ void tegra_usb_phy_memory_prefetch_off(struct tegra_usb_phy *phy)
writel(val, ahb_gizmo + AHB_MEM_PREFETCH_CFG2);
}
}
-EXPORT_SYMBOL_GPL(tegra_usb_phy_memory_prefetch_off);
-
-/* disable walk and wake events after resume from LP0 */
-bool tegra_usb_phy_is_remotewake_detected(struct tegra_usb_phy *phy)
-{
-#ifndef CONFIG_ARCH_TEGRA_2x_SOC
- void __iomem *pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
- void __iomem *base = phy->regs;
- unsigned int inst = phy->instance;
- u32 val;
-
- val = readl(base + UTMIP_PMC_WAKEUP0);
- if (val & EVENT_INT_ENB) {
- val = readl(pmc_base + UTMIP_UHSIC_STATUS);
- if (UTMIP_WAKE_ALARM(inst) & val) {
- val = readl(pmc_base + PMC_SLEEP_CFG);
- val &= ~UTMIP_WAKE_VAL(inst, 0x0);
- 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);
- phy->remote_wakeup = true;
- return true;
- }
- }
-#endif
- return false;
-}
-
diff --git a/arch/arm/mach-tegra/wakeups-t2.c b/arch/arm/mach-tegra/wakeups-t2.c
index 7c5d12ac60d4..adfe136c8118 100644
--- a/arch/arm/mach-tegra/wakeups-t2.c
+++ b/arch/arm/mach-tegra/wakeups-t2.c
@@ -22,90 +22,42 @@
#include <mach/gpio.h>
#include "gpio-names.h"
-
-static int tegra_wake_event_irq[] = {
- [0] = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PO5),
- [1] = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PV3),
- [2] = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PL1),
- [3] = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PB6),
- [4] = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PN7),
- [5] = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PA0),
- [6] = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PU5),
- [7] = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PU6),
- [8] = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PC7),
- [9] = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PS2),
- [10] = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PAA1),
- [11] = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PW3),
- [12] = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PW2),
- [13] = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PY6),
- [14] = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PV6),
- [15] = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PJ7),
- [16] = INT_RTC,
- [17] = INT_KBC,
- [18] = INT_EXTERNAL_PMU,
- [19] = -EINVAL, /* TEGRA_USB1_VBUS, */
- [20] = -EINVAL, /* TEGRA_USB3_VBUS, */
- [21] = -EINVAL, /* TEGRA_USB1_ID, */
- [22] = -EINVAL, /* TEGRA_USB3_ID, */
- [23] = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PI5),
- [24] = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PV2),
- [25] = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PS4),
- [26] = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PS5),
- [27] = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PS0),
- [28] = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PQ6),
- [29] = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PQ7),
- [30] = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PN2),
+#include "wakeups.h"
+
+static struct tegra_wake_info tegra_wake_event_data_t2[] = {
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PO5), POLARITY_NONE},
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PV3), POLARITY_NONE},
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PL1), POLARITY_NONE},
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PB6), POLARITY_NONE},
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PN7), POLARITY_NONE},
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PA0), POLARITY_NONE},
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PU5), POLARITY_NONE},
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PU6), POLARITY_NONE},
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PC7), POLARITY_NONE},
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PS2), POLARITY_NONE},
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PAA1), POLARITY_NONE},
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PW3), POLARITY_NONE},
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PW2), POLARITY_NONE},
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PY6), POLARITY_NONE},
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PV6), POLARITY_NONE},
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PJ7), POLARITY_NONE},
+ {INT_RTC, POLARITY_NONE},
+ {INT_KBC, POLARITY_NONE},
+ {INT_EXTERNAL_PMU, POLARITY_NONE},
+ {INT_USB, POLARITY_EDGE_ANY}, /* TEGRA_USB1_VBUS, */
+ {-EINVAL, POLARITY_EDGE_ANY}, /* TEGRA_USB3_VBUS, */
+ {-EINVAL, POLARITY_EDGE_ANY}, /* TEGRA_USB1_ID, */
+ {-EINVAL, POLARITY_EDGE_ANY}, /* TEGRA_USB3_ID, */
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PI5), POLARITY_NONE},
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PV2), POLARITY_NONE},
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PS4), POLARITY_NONE},
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PS5), POLARITY_NONE},
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PS0), POLARITY_NONE},
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PQ6), POLARITY_NONE},
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PQ7), POLARITY_NONE},
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PN2), POLARITY_NONE},
};
-int tegra_irq_to_wake(int irq)
-{
- int i;
- int wake_irq;
- int search_gpio;
- static int last_wake = -1;
-
- /* Two level wake irq search for gpio based wakeups -
- * 1. check for GPIO irq(based on tegra_wake_event_irq table)
- * e.g. for a board, wake7 based on GPIO PU6 and irq==358 done first
- * 2. check for gpio bank irq assuming search for GPIO irq
- * preceded this search.
- * e.g. in this step check for gpio bank irq GPIO6 irq==119
- */
- for (i = 0; i < ARRAY_SIZE(tegra_wake_event_irq); i++) {
- /* return if step 1 matches */
- if (tegra_wake_event_irq[i] == irq) {
- pr_info("Wake%d for irq=%d\n", i, irq);
- last_wake = i;
- return i;
- }
-
- /* step 2 below uses saved last_wake from step 1
- * in previous call */
- search_gpio = irq_to_gpio(
- tegra_wake_event_irq[i]);
- if (search_gpio < 0)
- continue;
- wake_irq = tegra_gpio_get_bank_int_nr(search_gpio);
- if (wake_irq < 0)
- continue;
- if ((last_wake == i) &&
- (wake_irq == irq)) {
- pr_info("gpio bank wake found: wake%d for irq=%d\n",
- i, irq);
- return i;
- }
- }
-
- return -EINVAL;
-}
-
-int tegra_wake_to_irq(int wake)
-{
- if (wake < 0)
- return -EINVAL;
-
- if (wake >= ARRAY_SIZE(tegra_wake_event_irq))
- return -EINVAL;
+struct tegra_wake_info *tegra_wake_event_data = tegra_wake_event_data_t2;
+unsigned int tegra_wake_event_data_size = ARRAY_SIZE(tegra_wake_event_data_t2);
- return tegra_wake_event_irq[wake];
-}
diff --git a/arch/arm/mach-tegra/wakeups-t2.h b/arch/arm/mach-tegra/wakeups-t2.h
index eb193c0aaf9e..955b351a71fa 100644
--- a/arch/arm/mach-tegra/wakeups-t2.h
+++ b/arch/arm/mach-tegra/wakeups-t2.h
@@ -30,36 +30,36 @@
int tegra_irq_to_wake(int irq);
int tegra_wake_to_irq(int wake);
-#define TEGRA_WAKE_GPIO_PO5 (1 << 0)
-#define TEGRA_WAKE_GPIO_PV3 (1 << 1)
-#define TEGRA_WAKE_GPIO_PL1 (1 << 2)
-#define TEGRA_WAKE_GPIO_PB6 (1 << 3)
-#define TEGRA_WAKE_GPIO_PN7 (1 << 4)
-#define TEGRA_WAKE_GPIO_PA0 (1 << 5)
-#define TEGRA_WAKE_GPIO_PU5 (1 << 6)
-#define TEGRA_WAKE_GPIO_PU6 (1 << 7)
-#define TEGRA_WAKE_GPIO_PC7 (1 << 8)
-#define TEGRA_WAKE_GPIO_PS2 (1 << 9)
-#define TEGRA_WAKE_GPIO_PAA1 (1 << 10)
-#define TEGRA_WAKE_GPIO_PW3 (1 << 11)
-#define TEGRA_WAKE_GPIO_PW2 (1 << 12)
-#define TEGRA_WAKE_GPIO_PY6 (1 << 13)
-#define TEGRA_WAKE_GPIO_PV6 (1 << 14)
-#define TEGRA_WAKE_GPIO_PJ7 (1 << 15)
-#define TEGRA_WAKE_RTC_ALARM (1 << 16)
-#define TEGRA_WAKE_KBC_EVENT (1 << 17)
-#define TEGRA_WAKE_PWR_INT (1 << 18)
-#define TEGRA_WAKE_USB1_VBUS (1 << 19)
-#define TEGRA_WAKE_USB3_VBUS (1 << 20)
-#define TEGRA_WAKE_USB1_ID (1 << 21)
-#define TEGRA_WAKE_USB3_ID (1 << 22)
-#define TEGRA_WAKE_GPIO_PI5 (1 << 23)
-#define TEGRA_WAKE_GPIO_PV2 (1 << 24)
-#define TEGRA_WAKE_GPIO_PS4 (1 << 25)
-#define TEGRA_WAKE_GPIO_PS5 (1 << 26)
-#define TEGRA_WAKE_GPIO_PS0 (1 << 27)
-#define TEGRA_WAKE_GPIO_PQ6 (1 << 28)
-#define TEGRA_WAKE_GPIO_PQ7 (1 << 29)
-#define TEGRA_WAKE_GPIO_PN2 (1 << 30)
+#define TEGRA_WAKE_GPIO_PO5 0
+#define TEGRA_WAKE_GPIO_PV3 1
+#define TEGRA_WAKE_GPIO_PL1 2
+#define TEGRA_WAKE_GPIO_PB6 3
+#define TEGRA_WAKE_GPIO_PN7 4
+#define TEGRA_WAKE_GPIO_PA0 5
+#define TEGRA_WAKE_GPIO_PU5 6
+#define TEGRA_WAKE_GPIO_PU6 7
+#define TEGRA_WAKE_GPIO_PC7 8
+#define TEGRA_WAKE_GPIO_PS2 9
+#define TEGRA_WAKE_GPIO_PAA1 10
+#define TEGRA_WAKE_GPIO_PW3 11
+#define TEGRA_WAKE_GPIO_PW2 12
+#define TEGRA_WAKE_GPIO_PY6 13
+#define TEGRA_WAKE_GPIO_PV6 14
+#define TEGRA_WAKE_GPIO_PJ7 15
+#define TEGRA_WAKE_RTC_ALARM 16
+#define TEGRA_WAKE_KBC_EVENT 17
+#define TEGRA_WAKE_PWR_INT 18
+#define TEGRA_WAKE_USB1_VBUS 19
+#define TEGRA_WAKE_USB3_VBUS 20
+#define TEGRA_WAKE_USB1_ID 21
+#define TEGRA_WAKE_USB3_ID 22
+#define TEGRA_WAKE_GPIO_PI5 23
+#define TEGRA_WAKE_GPIO_PV2 24
+#define TEGRA_WAKE_GPIO_PS4 25
+#define TEGRA_WAKE_GPIO_PS5 26
+#define TEGRA_WAKE_GPIO_PS0 27
+#define TEGRA_WAKE_GPIO_PQ6 28
+#define TEGRA_WAKE_GPIO_PQ7 29
+#define TEGRA_WAKE_GPIO_PN2 30
#endif
diff --git a/arch/arm/mach-tegra/wakeups-t3.c b/arch/arm/mach-tegra/wakeups-t3.c
index 823736204362..ef471cb035db 100644
--- a/arch/arm/mach-tegra/wakeups-t3.c
+++ b/arch/arm/mach-tegra/wakeups-t3.c
@@ -22,101 +22,53 @@
#include <mach/gpio.h>
#include "gpio-names.h"
+#include "wakeups.h"
-static int tegra_wake_event_irq[] = {
- TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PO5), /* wake0 */
- TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PV1), /* wake1 */
- TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PL1), /* wake2 */
- TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PB6), /* wake3 */
- TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PN7), /* wake4 */
- TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PBB6), /* wake5 */
- TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PU5), /* wake6 */
- TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PU6), /* wake7 */
- TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PC7), /* wake8 */
- TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PS2), /* wake9 */
- TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PAA1), /* wake10 */
- TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PW3), /* wake11 */
- TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PW2), /* wake12 */
- TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PY6), /* wake13 */
- TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PDD3), /* wake14 */
- TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PJ2), /* wake15 */
- INT_RTC, /* wake16 */
- INT_KBC, /* wake17 */
- INT_EXTERNAL_PMU, /* wake18 */
- -EINVAL, /* TEGRA_USB1_VBUS, */ /* wake19 */
- -EINVAL, /* TEGRA_USB2_VBUS, */ /* wake20 */
- -EINVAL, /* TEGRA_USB1_ID, */ /* wake21 */
- -EINVAL, /* TEGRA_USB2_ID, */ /* wake22 */
- TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PI5), /* wake23 */
- TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PV0), /* wake24 */
- TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PS4), /* wake25 */
- TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PS5), /* wake26 */
- TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PS0), /* wake27 */
- TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PS6), /* wake28 */
- TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PS7), /* wake29 */
- TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PN2), /* wake30 */
- -EINVAL, /* not used */ /* wake31 */
- TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PO4), /* wake32 */
- TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PJ0), /* wake33 */
- TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PK2), /* wake34 */
- TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PI6), /* wake35 */
- TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PBB1), /* wake36 */
- -EINVAL, /* TEGRA_USB3_VBUS, */ /* wake37 */
- -EINVAL, /* TEGRA_USB3_ID, */ /* wake38 */
- INT_USB, /* TEGRA_USB1_UTMIP, */ /* wake39 */
- INT_USB2, /* TEGRA_USB2_UTMIP, */ /* wake40 */
- INT_USB3, /* TEGRA_USB3_UTMIP, */ /* wake41 */
+static struct tegra_wake_info tegra_wake_event_data_t3[] = {
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PO5), POLARITY_NONE}, /* wake0 */
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PV1), POLARITY_NONE}, /* wake1 */
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PL1), POLARITY_NONE}, /* wake2 */
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PB6), POLARITY_NONE}, /* wake3 */
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PN7), POLARITY_NONE}, /* wake4 */
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PBB6), POLARITY_NONE}, /* wake5 */
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PU5), POLARITY_NONE}, /* wake6 */
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PU6), POLARITY_NONE}, /* wake7 */
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PC7), POLARITY_NONE}, /* wake8 */
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PS2), POLARITY_NONE}, /* wake9 */
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PAA1), POLARITY_NONE}, /* wake10 */
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PW3), POLARITY_NONE}, /* wake11 */
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PW2), POLARITY_NONE}, /* wake12 */
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PY6), POLARITY_NONE}, /* wake13 */
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PDD3), POLARITY_NONE}, /* wake14 */
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PJ2), POLARITY_NONE}, /* wake15 */
+ {INT_RTC, POLARITY_NONE}, /* wake16 */
+ {INT_KBC, POLARITY_NONE}, /* wake17 */
+ {INT_EXTERNAL_PMU, POLARITY_NONE}, /* wake18 */
+ {INT_USB, POLARITY_EDGE_ANY}, /* TEGRA_USB1_VBUS, */ /* wake19 */
+ {-EINVAL, POLARITY_EDGE_ANY}, /* TEGRA_USB2_VBUS, */ /* wake20 */
+ {INT_USB, POLARITY_EDGE_ANY}, /* TEGRA_USB1_ID, */ /* wake21 */
+ {-EINVAL, POLARITY_EDGE_ANY}, /* TEGRA_USB2_ID, */ /* wake22 */
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PI5), POLARITY_NONE}, /* wake23 */
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PV0), POLARITY_NONE}, /* wake24 */
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PS4), POLARITY_NONE}, /* wake25 */
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PS5), POLARITY_NONE}, /* wake26 */
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PS0), POLARITY_NONE}, /* wake27 */
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PS6), POLARITY_NONE}, /* wake28 */
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PS7), POLARITY_NONE}, /* wake29 */
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PN2), POLARITY_NONE}, /* wake30 */
+ {-EINVAL, POLARITY_NONE}, /* not used */ /* wake31 */
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PO4), POLARITY_NONE}, /* wake32 */
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PJ0), POLARITY_NONE}, /* wake33 */
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PK2), POLARITY_NONE}, /* wake34 */
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PI6), POLARITY_NONE}, /* wake35 */
+ {TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_PBB1), POLARITY_NONE}, /* wake36 */
+ {-EINVAL, POLARITY_NONE}, /* TEGRA_USB3_VBUS, */ /* wake37 */
+ {-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 tegra_irq_to_wake(int irq)
-{
- int i;
- int wake_irq;
- int search_gpio;
- static int last_wake = -1;
+struct tegra_wake_info *tegra_wake_event_data = tegra_wake_event_data_t3;
+unsigned int tegra_wake_event_data_size = ARRAY_SIZE(tegra_wake_event_data_t3);
- /* Two level wake irq search for gpio based wakeups -
- * 1. check for GPIO irq(based on tegra_wake_event_irq table)
- * e.g. for a board, wake7 based on GPIO PU6 and irq==390 done first
- * 2. check for gpio bank irq assuming search for GPIO irq
- * preceded this search.
- * e.g. in this step check for gpio bank irq GPIO6 irq==119
- */
- for (i = 0; i < ARRAY_SIZE(tegra_wake_event_irq); i++) {
- /* return if step 1 matches */
- if (tegra_wake_event_irq[i] == irq) {
- pr_info("Wake%d for irq=%d\n", i, irq);
- last_wake = i;
- return i;
- }
-
- /* step 2 below uses saved last_wake from step 1
- * in previous call */
- search_gpio = irq_to_gpio(
- tegra_wake_event_irq[i]);
- if (search_gpio < 0)
- continue;
- wake_irq = tegra_gpio_get_bank_int_nr(search_gpio);
- if (wake_irq < 0)
- continue;
- if ((last_wake == i) &&
- (wake_irq == irq)) {
- pr_info("gpio bank wake found: wake%d for irq=%d\n",
- i, irq);
- return i;
- }
- }
-
- return -EINVAL;
-}
-
-int tegra_wake_to_irq(int wake)
-{
- if (wake < 0)
- return -EINVAL;
-
- if (wake >= ARRAY_SIZE(tegra_wake_event_irq))
- return -EINVAL;
-
- return tegra_wake_event_irq[wake];
-}
diff --git a/arch/arm/mach-tegra/wakeups-t3.h b/arch/arm/mach-tegra/wakeups-t3.h
index f811d8939387..6c051270cc93 100644
--- a/arch/arm/mach-tegra/wakeups-t3.h
+++ b/arch/arm/mach-tegra/wakeups-t3.h
@@ -27,45 +27,45 @@
#error "Tegra 3 wakeup sources valid only for CONFIG_ARCH_TEGRA_3x_SOC"
#endif
-#define TEGRA_WAKE_GPIO_PO5 (1ull << 0)
-#define TEGRA_WAKE_GPIO_PV1 (1ull << 1)
-#define TEGRA_WAKE_GPIO_PL1 (1ull << 2)
-#define TEGRA_WAKE_GPIO_PB6 (1ull << 3)
-#define TEGRA_WAKE_GPIO_PN7 (1ull << 4)
-#define TEGRA_WAKE_GPIO_PBB6 (1ull << 5)
-#define TEGRA_WAKE_GPIO_PU5 (1ull << 6)
-#define TEGRA_WAKE_GPIO_PU6 (1ull << 7)
-#define TEGRA_WAKE_GPIO_PC7 (1ull << 8)
-#define TEGRA_WAKE_GPIO_PS2 (1ull << 9)
-#define TEGRA_WAKE_GPIO_PAA1 (1ull << 10)
-#define TEGRA_WAKE_GPIO_PW3 (1ull << 11)
-#define TEGRA_WAKE_GPIO_PW2 (1ull << 12)
-#define TEGRA_WAKE_GPIO_PY6 (1ull << 13)
-#define TEGRA_WAKE_GPIO_PDD3 (1ull << 14)
-#define TEGRA_WAKE_GPIO_PJ2 (1ull << 15)
-#define TEGRA_WAKE_RTC_ALARM (1ull << 16)
-#define TEGRA_WAKE_KBC_EVENT (1ull << 17)
-#define TEGRA_WAKE_PWR_INT (1ull << 18)
-#define TEGRA_WAKE_USB1_VBUS (1ull << 19)
-#define TEGRA_WAKE_USB2_VBUS (1ull << 20)
-#define TEGRA_WAKE_USB1_ID (1ull << 21)
-#define TEGRA_WAKE_USB2_ID (1ull << 22)
-#define TEGRA_WAKE_GPIO_PI5 (1ull << 23)
-#define TEGRA_WAKE_GPIO_PV0 (1ull << 24)
-#define TEGRA_WAKE_GPIO_PS4 (1ull << 25)
-#define TEGRA_WAKE_GPIO_PS5 (1ull << 26)
-#define TEGRA_WAKE_GPIO_PS0 (1ull << 27)
-#define TEGRA_WAKE_GPIO_PS6 (1ull << 28)
-#define TEGRA_WAKE_GPIO_PS7 (1ull << 29)
-#define TEGRA_WAKE_GPIO_PN2 (1ull << 30)
+#define TEGRA_WAKE_GPIO_PO5 0
+#define TEGRA_WAKE_GPIO_PV1 1
+#define TEGRA_WAKE_GPIO_PL1 2
+#define TEGRA_WAKE_GPIO_PB6 3
+#define TEGRA_WAKE_GPIO_PN7 4
+#define TEGRA_WAKE_GPIO_PBB6 5
+#define TEGRA_WAKE_GPIO_PU5 6
+#define TEGRA_WAKE_GPIO_PU6 7
+#define TEGRA_WAKE_GPIO_PC7 8
+#define TEGRA_WAKE_GPIO_PS2 9
+#define TEGRA_WAKE_GPIO_PAA1 10
+#define TEGRA_WAKE_GPIO_PW3 11
+#define TEGRA_WAKE_GPIO_PW2 12
+#define TEGRA_WAKE_GPIO_PY6 13
+#define TEGRA_WAKE_GPIO_PDD3 14
+#define TEGRA_WAKE_GPIO_PJ2 15
+#define TEGRA_WAKE_RTC_ALARM 16
+#define TEGRA_WAKE_KBC_EVENT 17
+#define TEGRA_WAKE_PWR_INT 18
+#define TEGRA_WAKE_USB1_VBUS 19
+#define TEGRA_WAKE_USB2_VBUS 20
+#define TEGRA_WAKE_USB1_ID 21
+#define TEGRA_WAKE_USB2_ID 22
+#define TEGRA_WAKE_GPIO_PI5 23
+#define TEGRA_WAKE_GPIO_PV0 24
+#define TEGRA_WAKE_GPIO_PS4 25
+#define TEGRA_WAKE_GPIO_PS5 26
+#define TEGRA_WAKE_GPIO_PS0 27
+#define TEGRA_WAKE_GPIO_PS6 28
+#define TEGRA_WAKE_GPIO_PS7 29
+#define TEGRA_WAKE_GPIO_PN2 30
/* bit 31 is unused */
-#define TEGRA_WAKE_GPIO_PO4 (1ull << 32)
-#define TEGRA_WAKE_GPIO_PJ0 (1ull << 33)
-#define TEGRA_WAKE_GPIO_PK2 (1ull << 34)
-#define TEGRA_WAKE_GPIO_PI6 (1ull << 35)
-#define TEGRA_WAKE_GPIO_PBB1 (1ull << 36)
-#define TEGRA_WAKE_USB3_ID (1ull << 37)
-#define TEGRA_WAKE_USB3_VBUS (1ull << 38)
+#define TEGRA_WAKE_GPIO_PO4 32
+#define TEGRA_WAKE_GPIO_PJ0 33
+#define TEGRA_WAKE_GPIO_PK2 34
+#define TEGRA_WAKE_GPIO_PI6 35
+#define TEGRA_WAKE_GPIO_PBB1 36
+#define TEGRA_WAKE_USB3_ID 37
+#define TEGRA_WAKE_USB3_VBUS 38
#endif
diff --git a/arch/arm/mach-tegra/wakeups.c b/arch/arm/mach-tegra/wakeups.c
new file mode 100644
index 000000000000..a52a4d50c074
--- /dev/null
+++ b/arch/arm/mach-tegra/wakeups.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+
+#include <mach/iomap.h>
+#include <mach/irqs.h>
+#include <mach/gpio.h>
+
+#include "gpio-names.h"
+#include "wakeups.h"
+
+extern struct tegra_wake_info *tegra_wake_event_data;
+extern unsigned int tegra_wake_event_data_size;
+
+/*
+ * FIXME: unable to pass rising and falling
+ * flags from usb driver hence using polarity field
+ * from wake table to set wake_mask_any
+ * for selected usb wake sources - VBUS and ID
+ */
+static int update_wake_mask(unsigned int index, int flow_type,
+ struct wake_mask_types *wake_msk)
+{
+ int trigger_val;
+ /*
+ * set wake function calls with flow_type as -1
+ * set wake type function calls update_wake_mask with
+ * the wake polarity
+ */
+ if (flow_type == -1) {
+ pr_debug("Wake%d flow_type=%d\n",
+ index, flow_type);
+ /* use argument wake_mask_hi to return mask */
+ wake_msk->wake_mask_hi |= (1ULL << index);
+ } else {
+ trigger_val = (flow_type & IRQF_TRIGGER_MASK);
+ if ((tegra_wake_event_data[index].polarity ==
+ POLARITY_EDGE_ANY) ||
+ (trigger_val ==
+ (IRQF_TRIGGER_RISING |
+ IRQF_TRIGGER_FALLING))) {
+ pr_debug("Wake%d flow_type=ANY\n", index);
+ wake_msk->wake_mask_any |= (1ULL << index);
+ } else if ((trigger_val == IRQF_TRIGGER_HIGH) ||
+ (trigger_val == IRQF_TRIGGER_RISING)) {
+ pr_debug("Wake%d flow_type=HI\n", index);
+ wake_msk->wake_mask_hi |= (1ULL << index);
+ } else if ((trigger_val == IRQF_TRIGGER_LOW) ||
+ (trigger_val == IRQF_TRIGGER_FALLING)) {
+ pr_debug("Wake%d flow_type=LO\n", index);
+ wake_msk->wake_mask_lo |= (1ULL << index);
+ } else {
+ pr_err("Error: Wake%d UNKNOWN flow_type=%d\n",
+ index, flow_type);
+ return -EINVAL;
+ }
+ }
+ return 0;
+}
+
+int tegra_irq_to_wake(unsigned int irq, int flow_type,
+ struct wake_mask_types *wake_msk)
+{
+ int i;
+ int err;
+
+ wake_msk->wake_mask_hi = 0ULL;
+ wake_msk->wake_mask_lo = 0ULL;
+ wake_msk->wake_mask_any = 0ULL;
+ /*
+ * check for irq based on tegra_wake_event_data table
+ */
+ for (i = 0; i < tegra_wake_event_data_size; i++) {
+ if (tegra_wake_event_data[i].irq == irq) {
+ err = update_wake_mask(i, flow_type, wake_msk);
+ if (err)
+ return err;
+ continue;
+ }
+ }
+
+ if (wake_msk->wake_mask_hi || wake_msk->wake_mask_lo ||
+ wake_msk->wake_mask_any) {
+ pr_debug("Enabling wake sources for irq=%d, mask hi=%#llx, lo=%#llx, any=%#llx, flow_type=%d\n",
+ irq, wake_msk->wake_mask_hi, wake_msk->wake_mask_lo,
+ wake_msk->wake_mask_any, flow_type);
+ return 0;
+ }
+ return -EINVAL;
+}
+
+int tegra_wake_to_irq(int wake)
+{
+ if (wake < 0)
+ return -EINVAL;
+
+ if (wake >= tegra_wake_event_data_size)
+ return -EINVAL;
+
+ return tegra_wake_event_data[wake].irq;
+}
+
+int tegra_disable_wake_source(int wake)
+{
+ if (wake >= tegra_wake_event_data_size)
+ return -EINVAL;
+
+ tegra_wake_event_data[wake].irq = -EINVAL;
+
+ return 0;
+}
+
diff --git a/arch/arm/mach-tegra/wakeups.h b/arch/arm/mach-tegra/wakeups.h
new file mode 100644
index 000000000000..6d2f5f077601
--- /dev/null
+++ b/arch/arm/mach-tegra/wakeups.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __WAKEUPS_H_
+#define __WAKEUPS_H_
+
+struct wake_mask_types {
+ u64 wake_mask_hi;
+ u64 wake_mask_lo;
+ u64 wake_mask_any;
+};
+
+/* sets 64-bit wake mask argument bits for wake sources given an irq */
+int tegra_irq_to_wake(unsigned int irq, int flow_type,
+ struct wake_mask_types *wake_msk);
+/*
+ * given wake source index, returns irq number or negative value for error
+ */
+int tegra_wake_to_irq(int wake);
+/* disable selected wake source setting for particular board */
+int tegra_disable_wake_source(int wake);
+
+enum wake_polarity {
+ POLARITY_NONE = 0,
+ POLARITY_LEVEL_HI,
+ POLARITY_LEVEL_LO,
+ POLARITY_EDGE_ANY
+};
+
+struct tegra_wake_info {
+ int irq;
+ enum wake_polarity polarity;
+};
+
+#endif /* end __WAKEUPS_H_ */
diff --git a/arch/arm/mach-tegra/wdt-recovery.c b/arch/arm/mach-tegra/wdt-recovery.c
index 537b1c0db853..c0a1a1fea347 100644
--- a/arch/arm/mach-tegra/wdt-recovery.c
+++ b/arch/arm/mach-tegra/wdt-recovery.c
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-tegra/wdt-recovery.c
*
- * 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
@@ -30,7 +30,7 @@
#include <asm/mach/time.h>
#include <asm/localtimer.h>
-#include <mach/nvmap.h>
+#include <linux/nvmap.h>
#include <mach/irqs.h>
#include <mach/iomap.h>
#include <mach/clk.h>
@@ -45,7 +45,7 @@ static int wdt_heartbeat = 30;
#define TIMER_PCR 0x4
#define TIMER_PCR_INTR (1 << 30)
#define WDT_CFG (0)
- #define WDT_CFG_TMR_SRC (7 << 0) /* for TMR7. */
+ #define WDT_CFG_TMR_SRC (0 << 0) /* for TMR10. */
#define WDT_CFG_PERIOD (1 << 4)
#define WDT_CFG_INT_EN (1 << 12)
#define WDT_CFG_SYS_RST_EN (1 << 14)
@@ -56,8 +56,8 @@ static int wdt_heartbeat = 30;
#define WDT_UNLOCK (0xC)
#define WDT_UNLOCK_PATTERN (0xC45A << 0)
-static void __iomem *wdt_timer = IO_ADDRESS(TEGRA_TMR7_BASE);
-static void __iomem *wdt_source = IO_ADDRESS(TEGRA_WDT0_BASE);
+static void __iomem *wdt_timer = IO_ADDRESS(TEGRA_TMR10_BASE);
+static void __iomem *wdt_source = IO_ADDRESS(TEGRA_WDT3_BASE);
static void tegra_wdt_reset_enable(void)
{
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index aaea6d487bae..e23ad5ebc330 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -885,6 +885,17 @@ config ARM_DMA_MEM_BUFFERABLE
You are recommended say 'Y' here and debug any affected drivers.
+config NON_ALIASED_COHERENT_MEM
+ bool "Avoid aliasing mappings in DMA coherent allocator" if CPU_V7
+ help
+ Avoid multiple mappings with DMA coherent/writecombine allocator by
+ pre-allocating the mappings, and removing that memory from the
+ system memory mapping.
+
+ This will make sure DMA memory is fully coherent, so cache
+ dma_sync APIs will not be necessary to maintain cache cohereny
+ for DMA coherent region.
+
config ARCH_HAS_BARRIERS
bool
help
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile
index 47e2e3ba1902..c3ef2961ddff 100644
--- a/arch/arm/mm/Makefile
+++ b/arch/arm/mm/Makefile
@@ -2,9 +2,15 @@
# Makefile for the linux arm-specific parts of the memory manager.
#
-obj-y := dma-mapping.o extable.o fault.o init.o \
+obj-y := extable.o fault.o init.o \
iomap.o
+ifeq ($(CONFIG_NON_ALIASED_COHERENT_MEM),y)
+obj-y += dma-na-mapping.o
+else
+obj-y += dma-mapping.o
+endif
+
obj-$(CONFIG_MMU) += fault-armv.o flush.o idmap.o ioremap.o \
mmap.o pgd.o mmu.o vmregion.o pageattr.o
diff --git a/arch/arm/mm/dma-na-mapping.c b/arch/arm/mm/dma-na-mapping.c
new file mode 100644
index 000000000000..4e5d52dda285
--- /dev/null
+++ b/arch/arm/mm/dma-na-mapping.c
@@ -0,0 +1,748 @@
+/*
+ * linux/arch/arm/mm/dma-mapping.c
+ *
+ * Copyright (C) 2000-2004 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * DMA uncached mapping support.
+ */
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/gfp.h>
+#include <linux/errno.h>
+#include <linux/list.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/highmem.h>
+#include <linux/memblock.h>
+
+#include <asm/memory.h>
+#include <asm/highmem.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+#include <asm/sizes.h>
+#include <asm/mach/map.h>
+
+#include "mm.h"
+
+static u64 get_coherent_dma_mask(struct device *dev)
+{
+ u64 mask = (u64)arm_dma_limit;
+
+ if (dev) {
+ mask = dev->coherent_dma_mask;
+
+ /*
+ * Sanity check the DMA mask - it must be non-zero, and
+ * must be able to be satisfied by a DMA allocation.
+ */
+ if (mask == 0) {
+ dev_warn(dev, "coherent DMA mask is unset\n");
+ return 0;
+ }
+
+ if ((~mask) & (u64)arm_dma_limit) {
+ dev_warn(dev, "coherent DMA mask %#llx is smaller "
+ "than system GFP_DMA mask %#llx\n",
+ mask, (u64)arm_dma_limit);
+ return 0;
+ }
+ }
+
+ return mask;
+}
+
+/*
+ * Allocate a DMA buffer for 'dev' of size 'size' using the
+ * specified gfp mask. Note that 'size' must be page aligned.
+ */
+static struct page *__dma_alloc_buffer(struct device *dev,
+ size_t size, gfp_t gfp)
+{
+ unsigned long order = get_order(size);
+ struct page *page, *p, *e;
+ void *ptr;
+ u64 mask = get_coherent_dma_mask(dev);
+
+#ifdef CONFIG_DMA_API_DEBUG
+ u64 limit = (mask + 1) & ~mask;
+ if (limit && size >= limit) {
+ dev_warn(dev, "coherent allocation too big"
+ "(requested %#x mask %#llx)\n",
+ size, mask);
+ return NULL;
+ }
+#endif
+
+ if (!mask)
+ return NULL;
+
+ if (mask < 0xffffffffULL)
+ gfp |= GFP_DMA;
+
+ page = alloc_pages(gfp, order);
+ if (!page)
+ return NULL;
+
+ /*
+ * Now split the huge page and free the excess pages
+ */
+ split_page(page, order);
+ for (p = page + (size >> PAGE_SHIFT), e = page + (1 << order);
+ p < e; p++)
+ __free_page(p);
+
+ /*
+ * Ensure that the allocated pages are zeroed, and that any data
+ * lurking in the kernel direct-mapped region is invalidated.
+ */
+ ptr = page_address(page);
+ memset(ptr, 0, size);
+ dmac_flush_range(ptr, ptr + size);
+ outer_flush_range(__pa(ptr), __pa(ptr) + size);
+
+ return page;
+}
+
+/*
+ * Free a DMA buffer. 'size' must be page aligned.
+ */
+static void __dma_free_buffer(struct page *page, size_t size)
+{
+ struct page *e = page + (size >> PAGE_SHIFT);
+
+ while (page < e) {
+ __free_page(page);
+ page++;
+ }
+}
+
+#ifdef CONFIG_MMU
+/* Sanity check sizes */
+#if CONSISTENT_DMA_SIZE % SECTION_SIZE
+#error "CONSISTENT_DMA_SIZE must be a multiple of the section size"
+#endif
+#if CONSISTENT_WC_SIZE % SECTION_SIZE
+#error "CONSISTENT_WC_SIZE must be a multiple of the section size"
+#endif
+#if ((CONSISTENT_DMA_SIZE + CONSISTENT_WC_SIZE) % SZ_2M)
+#error "Sum of CONSISTENT_DMA_SIZE and CONSISTENT_WC_SIZE must " \
+ "be multiple of 2MiB"
+#endif
+
+#include "vmregion.h"
+
+struct dma_coherent_area {
+ struct arm_vmregion_head vm;
+ unsigned long pfn;
+ unsigned long pfn_end;
+ unsigned int type;
+ const char *name;
+};
+
+static struct dma_coherent_area coherent_wc_head = {
+ .vm = {
+ .vm_start = CONSISTENT_WC_BASE,
+ .vm_end = CONSISTENT_WC_END,
+ },
+ .pfn = 0,
+ .pfn_end = 0,
+ .type = MT_WC_COHERENT,
+ .name = "WC ",
+};
+
+static struct dma_coherent_area coherent_dma_head = {
+ .vm = {
+ .vm_start = CONSISTENT_BASE,
+ .vm_end = CONSISTENT_END,
+ },
+ .pfn = 0,
+ .pfn_end = 0,
+ .type = MT_DMA_COHERENT,
+ .name = "DMA coherent ",
+};
+
+static struct dma_coherent_area *coherent_areas[2] __initdata = {
+ &coherent_wc_head,
+ &coherent_dma_head
+};
+
+static struct dma_coherent_area *coherent_map[2];
+#define coherent_wc_area coherent_map[0]
+#define coherent_dma_area coherent_map[1]
+
+void dma_coherent_reserve(void)
+{
+ phys_addr_t base;
+ unsigned long size;
+ int can_share, i;
+
+ if (arch_is_coherent())
+ return;
+
+#ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE
+ /* ARMv6: only when DMA_MEM_BUFFERABLE is enabled */
+ can_share = cpu_architecture() >= CPU_ARCH_ARMv6;
+#else
+ /* ARMv7+: WC and DMA areas have the same properties, so can share */
+ can_share = cpu_architecture() >= CPU_ARCH_ARMv7;
+#endif
+ if (can_share) {
+ coherent_wc_head.name = "DMA coherent/WC ";
+ coherent_wc_head.vm.vm_end = coherent_dma_head.vm.vm_end;
+ coherent_dma_head.vm.vm_start = coherent_dma_head.vm.vm_end;
+ coherent_dma_area = coherent_wc_area = &coherent_wc_head;
+ } else {
+ memcpy(coherent_map, coherent_areas, sizeof(coherent_map));
+ }
+
+ for (i = 0; i < ARRAY_SIZE(coherent_areas); i++) {
+ struct dma_coherent_area *area = coherent_areas[i];
+
+ size = area->vm.vm_end - area->vm.vm_start;
+ if (!size)
+ continue;
+
+ spin_lock_init(&area->vm.vm_lock);
+ INIT_LIST_HEAD(&area->vm.vm_list);
+
+ base = memblock_end_of_DRAM() - size;
+ memblock_free(base, size);
+ memblock_remove(base, size);
+
+ area->pfn = __phys_to_pfn(base);
+ area->pfn_end = __phys_to_pfn(base+size);
+
+ pr_info("DMA: %luMiB %smemory allocated at 0x%08llx phys\n",
+ size / 1048576, area->name, (unsigned long long)base);
+ }
+}
+
+void __init dma_coherent_mapping(void)
+{
+ struct map_desc map[ARRAY_SIZE(coherent_areas)];
+ int nr;
+
+ for (nr = 0; nr < ARRAY_SIZE(map); nr++) {
+ struct dma_coherent_area *area = coherent_areas[nr];
+
+ map[nr].pfn = area->pfn;
+ map[nr].virtual = area->vm.vm_start;
+ map[nr].length = area->vm.vm_end - area->vm.vm_start;
+ map[nr].type = area->type;
+ if (map[nr].length == 0)
+ break;
+ }
+
+ iotable_init(map, nr);
+}
+
+static void *dma_alloc_area(size_t size, unsigned long *pfn, gfp_t gfp,
+ struct dma_coherent_area *area)
+{
+ struct arm_vmregion *c;
+ size_t align;
+ int bit;
+
+ /*
+ * Align the virtual region allocation - maximum alignment is
+ * a section size, minimum is a page size. This helps reduce
+ * fragmentation of the DMA space, and also prevents allocations
+ * smaller than a section from crossing a section boundary.
+ */
+ bit = fls(size - 1);
+ if (bit > SECTION_SHIFT)
+ bit = SECTION_SHIFT;
+ align = 1 << bit;
+
+ /*
+ * Allocate a virtual address in the consistent mapping region.
+ */
+ c = arm_vmregion_alloc(&area->vm, align, size,
+ gfp & ~(__GFP_DMA | __GFP_HIGHMEM));
+ if (!c)
+ return NULL;
+
+ memset((void *)c->vm_start, 0, size);
+ *pfn = area->pfn + ((c->vm_start - area->vm.vm_start) >> PAGE_SHIFT);
+ c->vm_pages = pfn_to_page(*pfn);
+
+ return (void *)c->vm_start;
+}
+
+static void dma_free_area(void *cpu_addr, size_t size,
+ struct dma_coherent_area *area)
+{
+ struct arm_vmregion *c;
+
+ c = arm_vmregion_find_remove(&area->vm, (unsigned long)cpu_addr);
+ if (!c) {
+ printk(KERN_ERR "%s: trying to free invalid coherent area: %p\n",
+ __func__, cpu_addr);
+ dump_stack();
+ return;
+ }
+
+ if ((c->vm_end - c->vm_start) != size) {
+ printk(KERN_ERR "%s: freeing wrong coherent size (%ld != %d)\n",
+ __func__, c->vm_end - c->vm_start, size);
+ dump_stack();
+ size = c->vm_end - c->vm_start;
+ }
+
+ arm_vmregion_free(&area->vm, c);
+}
+
+#define nommu() (0)
+
+#else /* !CONFIG_MMU */
+
+#define dma_alloc_area(size, pfn, gfp, area) ({ *(pfn) = 0; NULL })
+#define dma_free_area(addr, size, area) do { } while (0)
+
+#define nommu() (1)
+#define coherent_wc_area NULL
+#define coherent_dma_area NULL
+
+void dma_coherent_reserve(void)
+{
+}
+
+#endif /* CONFIG_MMU */
+
+static void *
+__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp,
+ struct dma_coherent_area *area)
+{
+
+ unsigned long pfn;
+ void *ret;
+ /* Following is a work-around (a.k.a. hack) to prevent pages
+ * with __GFP_COMP being passed to split_page() which cannot
+ * handle them. The real problem is that this flag probably
+ * should be 0 on ARM as it is not supported on this
+ * platform--see CONFIG_HUGETLB_PAGE. */
+ gfp &= ~(__GFP_COMP);
+
+ *handle = ~0;
+ size = PAGE_ALIGN(size);
+
+ if (arch_is_coherent() || nommu()) {
+ struct page *page = __dma_alloc_buffer(dev, size, gfp);
+ if (!page)
+ return NULL;
+ pfn = page_to_pfn(page);
+ ret = page_address(page);
+ } else {
+ ret = dma_alloc_area(size, &pfn, gfp, area);
+ }
+
+ if (ret)
+ *handle = pfn_to_dma(dev, pfn);
+
+ return ret;
+}
+
+static void __dma_free(struct device *dev, size_t size, void *cpu_addr,
+ dma_addr_t handle, struct dma_coherent_area *area)
+{
+ size = PAGE_ALIGN(size);
+
+ if (arch_is_coherent() || nommu())
+ __dma_free_buffer(pfn_to_page(dma_to_pfn(dev, handle)), size);
+ else
+ dma_free_area(cpu_addr, size, area);
+}
+
+/*
+ * Allocate DMA-coherent memory space and return both the kernel remapped
+ * virtual and bus address for that space.
+ */
+void *
+dma_alloc_coherent(struct device *dev, size_t size,
+ dma_addr_t *handle, gfp_t gfp)
+{
+ void *memory;
+
+ if (dma_alloc_from_coherent(dev, size, handle, &memory))
+ return memory;
+
+ return __dma_alloc(dev, size, handle, gfp, coherent_dma_area);
+}
+EXPORT_SYMBOL(dma_alloc_coherent);
+
+/*
+ * Allocate a writecombining region, in much the same way as
+ * dma_alloc_coherent above.
+ */
+void *
+dma_alloc_writecombine(struct device *dev, size_t size,
+ dma_addr_t *handle, gfp_t gfp)
+{
+ return __dma_alloc(dev, size, handle, gfp, coherent_wc_area);
+}
+EXPORT_SYMBOL(dma_alloc_writecombine);
+
+static int dma_mmap(struct device *dev, struct vm_area_struct *vma,
+ void *cpu_addr, dma_addr_t dma_addr, size_t size,
+ struct dma_coherent_area *area)
+{
+ int ret = -ENXIO;
+#ifdef CONFIG_MMU
+ unsigned long user_size, kern_size;
+ struct arm_vmregion *c;
+
+ user_size = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
+
+ c = arm_vmregion_find(&area->vm, (unsigned long)cpu_addr);
+ if (c) {
+ unsigned long off = vma->vm_pgoff;
+
+ kern_size = (c->vm_end - c->vm_start) >> PAGE_SHIFT;
+
+ if (off < kern_size &&
+ user_size <= (kern_size - off)) {
+ ret = remap_pfn_range(vma, vma->vm_start,
+ page_to_pfn(c->vm_pages) + off,
+ user_size << PAGE_SHIFT,
+ vma->vm_page_prot);
+ }
+ }
+#endif /* CONFIG_MMU */
+
+ return ret;
+}
+
+int dma_mmap_coherent(struct device *dev, struct vm_area_struct *vma,
+ void *cpu_addr, dma_addr_t dma_addr, size_t size)
+{
+ vma->vm_page_prot = pgprot_dmacoherent(vma->vm_page_prot);
+ return dma_mmap(dev, vma, cpu_addr, dma_addr, size, coherent_dma_area);
+}
+EXPORT_SYMBOL(dma_mmap_coherent);
+
+int dma_mmap_writecombine(struct device *dev, struct vm_area_struct *vma,
+ void *cpu_addr, dma_addr_t dma_addr, size_t size)
+{
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+ return dma_mmap(dev, vma, cpu_addr, dma_addr, size, coherent_wc_area);
+}
+EXPORT_SYMBOL(dma_mmap_writecombine);
+
+/*
+ * free a page as defined by the above mapping.
+ * Must not be called with IRQs disabled.
+ */
+void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
+ dma_addr_t handle)
+{
+ WARN_ON(irqs_disabled());
+
+ if (dma_release_from_coherent(dev, get_order(size), cpu_addr))
+ return;
+
+ __dma_free(dev, size, cpu_addr, handle, coherent_dma_area);
+}
+EXPORT_SYMBOL(dma_free_coherent);
+
+void dma_free_writecombine(struct device *dev, size_t size, void *cpu_addr,
+ dma_addr_t handle)
+{
+ WARN_ON(irqs_disabled());
+
+ __dma_free(dev, size, cpu_addr, handle, coherent_wc_area);
+}
+EXPORT_SYMBOL(dma_free_writecombine);
+
+#define is_coherent_pfn(x) ((((x) >= coherent_wc_head.pfn) && \
+ ((x) < coherent_wc_head.pfn_end)) || \
+ (((x) >= coherent_dma_head.pfn) && \
+ ((x) < coherent_dma_head.pfn_end)))
+/*
+ * Make an area consistent for devices.
+ * Note: Drivers should NOT use this function directly, as it will break
+ * platforms with CONFIG_DMABOUNCE.
+ * Use the driver DMA support - see dma-mapping.h (dma_sync_*)
+ */
+void ___dma_single_cpu_to_dev(struct device *dev, const void *kaddr,
+ size_t size, enum dma_data_direction dir)
+{
+ unsigned long paddr;
+ unsigned long kaddr_pfn;
+
+ kaddr_pfn = dma_to_pfn(dev, virt_to_dma(dev, (void *)kaddr));
+
+ if (is_coherent_pfn(kaddr_pfn))
+ return;
+
+ BUG_ON(!virt_addr_valid(kaddr) || !virt_addr_valid(kaddr + size - 1));
+
+ dmac_map_area(kaddr, size, dir);
+
+ paddr = __pa(kaddr);
+ if (dir == DMA_FROM_DEVICE)
+ outer_inv_range(paddr, paddr + size);
+ else
+ outer_clean_range(paddr, paddr + size);
+
+ /* FIXME: non-speculating: flush on bidirectional mappings? */
+}
+EXPORT_SYMBOL(___dma_single_cpu_to_dev);
+
+void ___dma_single_dev_to_cpu(struct device *dev, const void *kaddr,
+ size_t size, enum dma_data_direction dir)
+{
+ unsigned long kaddr_pfn;
+
+ kaddr_pfn = dma_to_pfn(dev, virt_to_dma(dev, (void *)kaddr));
+
+ if (is_coherent_pfn(kaddr_pfn))
+ return;
+
+ BUG_ON(!virt_addr_valid(kaddr) || !virt_addr_valid(kaddr + size - 1));
+
+ /* FIXME: non-speculating: not required */
+ /* don't bother invalidating if DMA to device */
+ if (dir != DMA_TO_DEVICE) {
+ unsigned long paddr = __pa(kaddr);
+ outer_inv_range(paddr, paddr + size);
+ }
+
+ dmac_unmap_area(kaddr, size, dir);
+}
+EXPORT_SYMBOL(___dma_single_dev_to_cpu);
+
+static void dma_cache_maint_page(struct page *page, unsigned long offset,
+ size_t size, enum dma_data_direction dir,
+ void (*op)(const void *, size_t, int))
+{
+ /*
+ * A single sg entry may refer to multiple physically contiguous
+ * pages. But we still need to process highmem pages individually.
+ * If highmem is not configured then the bulk of this loop gets
+ * optimized out.
+ */
+ size_t left = size;
+ do {
+ size_t len = left;
+ void *vaddr;
+
+ if (PageHighMem(page)) {
+ if (len + offset > PAGE_SIZE) {
+ if (offset >= PAGE_SIZE) {
+ page += offset / PAGE_SIZE;
+ offset %= PAGE_SIZE;
+ }
+ len = PAGE_SIZE - offset;
+ }
+ vaddr = kmap_high_get(page);
+ if (vaddr) {
+ vaddr += offset;
+ op(vaddr, len, dir);
+ kunmap_high(page);
+ } else if (cache_is_vipt()) {
+ /* unmapped pages might still be cached */
+ vaddr = kmap_atomic(page);
+ op(vaddr + offset, len, dir);
+ kunmap_atomic(vaddr);
+ }
+ } else {
+ vaddr = page_address(page) + offset;
+ op(vaddr, len, dir);
+ }
+ offset = 0;
+ page++;
+ left -= len;
+ } while (left);
+}
+
+void ___dma_page_cpu_to_dev(struct page *page, unsigned long off,
+ size_t size, enum dma_data_direction dir)
+{
+ unsigned long paddr;
+
+ dma_cache_maint_page(page, off, size, dir, dmac_map_area);
+
+ paddr = page_to_phys(page) + off;
+ if (dir == DMA_FROM_DEVICE)
+ outer_inv_range(paddr, paddr + size);
+ else
+ outer_clean_range(paddr, paddr + size);
+ /* FIXME: non-speculating: flush on bidirectional mappings? */
+}
+EXPORT_SYMBOL(___dma_page_cpu_to_dev);
+
+void ___dma_page_dev_to_cpu(struct page *page, unsigned long off,
+ size_t size, enum dma_data_direction dir)
+{
+ unsigned long paddr = page_to_phys(page) + off;
+
+ /* FIXME: non-speculating: not required */
+ /* don't bother invalidating if DMA to device */
+ if (dir != DMA_TO_DEVICE)
+ outer_inv_range(paddr, paddr + size);
+
+ dma_cache_maint_page(page, off, size, dir, dmac_unmap_area);
+
+ /*
+ * Mark the D-cache clean for this page to avoid extra flushing.
+ */
+ if (dir != DMA_TO_DEVICE && off == 0 && size >= PAGE_SIZE)
+ set_bit(PG_dcache_clean, &page->flags);
+}
+EXPORT_SYMBOL(___dma_page_dev_to_cpu);
+
+/**
+ * dma_map_sg - map a set of SG buffers for streaming mode DMA
+ * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
+ * @sg: list of buffers
+ * @nents: number of buffers to map
+ * @dir: DMA transfer direction
+ *
+ * Map a set of buffers described by scatterlist in streaming mode for DMA.
+ * This is the scatter-gather version of the dma_map_single interface.
+ * Here the scatter gather list elements are each tagged with the
+ * appropriate dma address and length. They are obtained via
+ * sg_dma_{address,length}.
+ *
+ * Device ownership issues as mentioned for dma_map_single are the same
+ * here.
+ */
+int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+ enum dma_data_direction dir)
+{
+ struct scatterlist *s;
+ int i, j;
+
+ BUG_ON(!valid_dma_direction(dir));
+
+ for_each_sg(sg, s, nents, i) {
+ s->dma_address = __dma_map_page(dev, sg_page(s), s->offset,
+ s->length, dir);
+ if (dma_mapping_error(dev, s->dma_address))
+ goto bad_mapping;
+ }
+ debug_dma_map_sg(dev, sg, nents, nents, dir);
+ return nents;
+
+ bad_mapping:
+ for_each_sg(sg, s, i, j)
+ __dma_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir);
+ return 0;
+}
+EXPORT_SYMBOL(dma_map_sg);
+
+/**
+ * dma_unmap_sg - unmap a set of SG buffers mapped by dma_map_sg
+ * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
+ * @sg: list of buffers
+ * @nents: number of buffers to unmap (same as was passed to dma_map_sg)
+ * @dir: DMA transfer direction (same as was passed to dma_map_sg)
+ *
+ * Unmap a set of streaming mode DMA translations. Again, CPU access
+ * rules concerning calls here are the same as for dma_unmap_single().
+ */
+void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
+ enum dma_data_direction dir)
+{
+ struct scatterlist *s;
+ int i;
+
+ debug_dma_unmap_sg(dev, sg, nents, dir);
+
+ for_each_sg(sg, s, nents, i)
+ __dma_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir);
+}
+EXPORT_SYMBOL(dma_unmap_sg);
+
+/**
+ * dma_sync_sg_for_cpu
+ * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
+ * @sg: list of buffers
+ * @nents: number of buffers to map (returned from dma_map_sg)
+ * @dir: DMA transfer direction (same as was passed to dma_map_sg)
+ */
+void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
+ int nents, enum dma_data_direction dir)
+{
+ struct scatterlist *s;
+ int i;
+
+ for_each_sg(sg, s, nents, i) {
+ if (!dmabounce_sync_for_cpu(dev, sg_dma_address(s), 0,
+ sg_dma_len(s), dir))
+ continue;
+
+ __dma_page_dev_to_cpu(sg_page(s), s->offset,
+ s->length, dir);
+ }
+
+ debug_dma_sync_sg_for_cpu(dev, sg, nents, dir);
+}
+EXPORT_SYMBOL(dma_sync_sg_for_cpu);
+
+/**
+ * dma_sync_sg_for_device
+ * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
+ * @sg: list of buffers
+ * @nents: number of buffers to map (returned from dma_map_sg)
+ * @dir: DMA transfer direction (same as was passed to dma_map_sg)
+ */
+void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
+ int nents, enum dma_data_direction dir)
+{
+ struct scatterlist *s;
+ int i;
+
+ for_each_sg(sg, s, nents, i) {
+ if (!dmabounce_sync_for_device(dev, sg_dma_address(s), 0,
+ sg_dma_len(s), dir))
+ continue;
+
+ __dma_page_cpu_to_dev(sg_page(s), s->offset,
+ s->length, dir);
+ }
+
+ debug_dma_sync_sg_for_device(dev, sg, nents, dir);
+}
+EXPORT_SYMBOL(dma_sync_sg_for_device);
+
+/*
+ * Return whether the given device DMA address mask can be supported
+ * properly. For example, if your device can only drive the low 24-bits
+ * during bus mastering, then you would pass 0x00ffffff as the mask
+ * to this function.
+ */
+int dma_supported(struct device *dev, u64 mask)
+{
+ if (mask < (u64)arm_dma_limit)
+ return 0;
+ return 1;
+}
+EXPORT_SYMBOL(dma_supported);
+
+int dma_set_mask(struct device *dev, u64 dma_mask)
+{
+ if (!dev->dma_mask || !dma_supported(dev, dma_mask))
+ return -EIO;
+
+#ifndef CONFIG_DMABOUNCE
+ *dev->dma_mask = dma_mask;
+#endif
+
+ return 0;
+}
+EXPORT_SYMBOL(dma_set_mask);
+
+#define PREALLOC_DMA_DEBUG_ENTRIES 4096
+
+static int __init dma_debug_do_init(void)
+{
+ dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
+ return 0;
+}
+fs_initcall(dma_debug_do_init);
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index f8037ba338ac..6f81c8e05c3a 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -364,6 +364,9 @@ void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc)
#endif
arm_mm_memblock_reserve();
+#if defined(CONFIG_NON_ALIASED_COHERENT_MEM)
+ dma_coherent_reserve();
+#endif
arm_dt_memblock_reserve();
/* reserve any platform specific memblock areas */
diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h
index 010566799c80..967a8048f321 100644
--- a/arch/arm/mm/mm.h
+++ b/arch/arm/mm/mm.h
@@ -31,3 +31,8 @@ extern u32 arm_dma_limit;
void __init bootmem_init(void);
void arm_mm_memblock_reserve(void);
+
+#ifdef CONFIG_NON_ALIASED_COHERENT_MEM
+void dma_coherent_reserve(void);
+void dma_coherent_mapping(void);
+#endif
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 4fa9c246ae93..bb80555edac9 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -273,6 +273,18 @@ static struct mem_type mem_types[] = {
.prot_l1 = PMD_TYPE_TABLE,
.domain = DOMAIN_KERNEL,
},
+#ifdef CONFIG_NON_ALIASED_COHERENT_MEM
+ [MT_DMA_COHERENT] = {
+ .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE |
+ PMD_SECT_S,
+ .domain = DOMAIN_IO,
+ },
+ [MT_WC_COHERENT] = {
+ .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE |
+ PMD_SECT_S,
+ .domain = DOMAIN_IO,
+ },
+#endif
};
const struct mem_type *get_mem_type(unsigned int type)
@@ -353,6 +365,9 @@ static void __init build_mem_type_table(void)
mem_types[MT_DEVICE_NONSHARED].prot_sect |= PMD_SECT_XN;
mem_types[MT_DEVICE_CACHED].prot_sect |= PMD_SECT_XN;
mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_XN;
+#ifdef CONFIG_NON_ALIASED_COHERENT_MEM
+ mem_types[MT_DMA_COHERENT].prot_sect |= PMD_SECT_XN;
+#endif
}
if (cpu_arch >= CPU_ARCH_ARMv7 && (cr & CR_TRE)) {
/*
@@ -457,13 +472,30 @@ static void __init build_mem_type_table(void)
/* Non-cacheable Normal is XCB = 001 */
mem_types[MT_MEMORY_NONCACHED].prot_sect |=
PMD_SECT_BUFFERED;
+#ifdef CONFIG_NON_ALIASED_COHERENT_MEM
+ mem_types[MT_WC_COHERENT].prot_sect |=
+ PMD_SECT_BUFFERED;
+ mem_types[MT_DMA_COHERENT].prot_sect |=
+ PMD_SECT_BUFFERED;
+#endif
} else {
/* For both ARMv6 and non-TEX-remapping ARMv7 */
mem_types[MT_MEMORY_NONCACHED].prot_sect |=
PMD_SECT_TEX(1);
+#ifdef CONFIG_NON_ALIASED_COHERENT_MEM
+ mem_types[MT_WC_COHERENT].prot_sect |=
+ PMD_SECT_TEX(1);
+#ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE
+ mem_types[MT_DMA_COHERENT].prot_sect |=
+ PMD_SECT_TEX(1);
+#endif
+#endif
}
} else {
mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_BUFFERABLE;
+#ifdef CONFIG_NON_ALIASED_COHERENT_MEM
+ mem_types[MT_WC_COHERENT].prot_sect |= PMD_SECT_BUFFERED;
+#endif
}
for (i = 0; i < 16; i++) {
@@ -986,6 +1018,10 @@ static void __init devicemaps_init(struct machine_desc *mdesc)
create_mapping(&map);
}
+#ifdef CONFIG_NON_ALIASED_COHERENT_MEM
+ dma_coherent_mapping();
+#endif
+
/*
* Ask the machine support to map in the statically mapped devices.
*/
diff --git a/arch/arm/mm/pageattr.c b/arch/arm/mm/pageattr.c
index 5f8071110e88..b7ff7f19b541 100644
--- a/arch/arm/mm/pageattr.c
+++ b/arch/arm/mm/pageattr.c
@@ -331,6 +331,10 @@ static void __set_pmd_pte(pmd_t *pmd, unsigned long address, pte_t *pte)
cpa_debug("__set_pmd_pte %x %x %x\n", pmd, pte, *pte);
+ /* enforce pte entry stores ordering to avoid pmd writes
+ * bypassing pte stores.
+ */
+ dsb();
/* change init_mm */
pmd_populate_kernel(&init_mm, pmd, pte);
@@ -342,7 +346,10 @@ static void __set_pmd_pte(pmd_t *pmd, unsigned long address, pte_t *pte)
pgd_index(address), address);
pmd_populate_kernel(NULL, pmd, pte);
}
-
+ /* enforce pmd entry stores ordering to avoid tlb flush bypassing
+ * pmd entry stores.
+ */
+ dsb();
}
static int
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index 38c78253f769..a502958a71f8 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -551,6 +551,12 @@ __v7_setup:
mrcge p15, 0, r10, c15, c0, 0 @ read power control register
orrge r10, r10, #1 @ enable dynamic clock gating
mcrge p15, 0, r10, c15, c0, 0 @ write power control register
+#ifdef CONFIG_ARM_ERRATA_716044
+ cmp r6, #0x12 @ present in r1p0 - r1p2
+ mrcle p15, 0, r10, c1, c0, 0
+ orrle r10, r10, #(1 << 14) @ set SCTLR.RR
+ mcrle p15, 0, r10, c1, c0, 0
+#endif
#ifdef CONFIG_ARM_ERRATA_720791
teq r5, #0x00100000 @ only present in r1p*
mrceq p15, 0, r10, c15, c0, 2 @ read "chicken power ctrl" reg
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 6a46b56f7538..462a94d2a2c1 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -11,6 +11,7 @@
#include <linux/module.h>
#include <linux/types.h>
#include <linux/cpu.h>
+#include <linux/hardirq.h>
#include <linux/kernel.h>
#include <linux/notifier.h>
#include <linux/signal.h>
@@ -425,7 +426,10 @@ void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs)
static void vfp_enable(void *unused)
{
- u32 access = get_copro_access();
+ u32 access;
+
+ BUG_ON(preemptible());
+ access = get_copro_access();
/*
* Enable full access to VFP (cp10 and cp11)
@@ -574,11 +578,8 @@ static int __init vfp_init(void)
unsigned int vfpsid;
unsigned int cpu_arch = cpu_architecture();
-#ifdef CONFIG_SMP
- preempt_disable();
-#endif
if (cpu_arch >= CPU_ARCH_ARMv6)
- vfp_enable(NULL);
+ on_each_cpu(vfp_enable, NULL, 1);
/*
* First check that there is a VFP that we can use.
@@ -599,8 +600,6 @@ static int __init vfp_init(void)
} else {
hotcpu_notifier(vfp_hotplug, 0);
- smp_call_function(vfp_enable, NULL, 1);
-
VFP_arch = (vfpsid & FPSID_ARCH_MASK) >> FPSID_ARCH_BIT; /* Extract the architecture version */
printk("implementor %02x architecture %d part %02x variant %x rev %x\n",
(vfpsid & FPSID_IMPLEMENTER_MASK) >> FPSID_IMPLEMENTER_BIT,
@@ -647,9 +646,6 @@ static int __init vfp_init(void)
elf_hwcap |= HWCAP_VFPv4;
}
}
-#ifdef CONFIG_SMP
- preempt_enable();
-#endif
return 0;
}