summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/configs/tegra3_android_defconfig1
-rw-r--r--arch/arm/mach-tegra/Kconfig9
-rw-r--r--arch/arm/mach-tegra/Makefile2
-rw-r--r--arch/arm/mach-tegra/baseband-xmm-power.c1
-rw-r--r--arch/arm/mach-tegra/board-cardhu-kbc.c8
-rw-r--r--arch/arm/mach-tegra/board-cardhu-panel.c45
-rw-r--r--arch/arm/mach-tegra/board-cardhu-pinmux.c5
-rw-r--r--arch/arm/mach-tegra/board-cardhu-pm298-power-rails.c7
-rw-r--r--arch/arm/mach-tegra/board-cardhu-pm299-power-rails.c7
-rw-r--r--arch/arm/mach-tegra/board-cardhu-power.c11
-rw-r--r--arch/arm/mach-tegra/board-cardhu-sdhci.c4
-rw-r--r--arch/arm/mach-tegra/board-cardhu-sensors.c74
-rw-r--r--arch/arm/mach-tegra/board-cardhu.c400
-rw-r--r--arch/arm/mach-tegra/board-enterprise-baseband.c62
-rw-r--r--arch/arm/mach-tegra/board-enterprise.c260
-rw-r--r--arch/arm/mach-tegra/board-harmony-pcie.c3
-rw-r--r--arch/arm/mach-tegra/board-harmony.c94
-rw-r--r--arch/arm/mach-tegra/board-kai.c147
-rw-r--r--arch/arm/mach-tegra/board-p1852.c174
-rw-r--r--arch/arm/mach-tegra/board-trimslice.c3
-rw-r--r--arch/arm/mach-tegra/board-ventana.c207
-rw-r--r--arch/arm/mach-tegra/board-whistler-baseband.c62
-rw-r--r--arch/arm/mach-tegra/board-whistler-sdhci.c4
-rw-r--r--arch/arm/mach-tegra/board-whistler.c118
-rw-r--r--arch/arm/mach-tegra/common-t2.c6
-rw-r--r--arch/arm/mach-tegra/common.c6
-rw-r--r--arch/arm/mach-tegra/devices.c31
-rw-r--r--arch/arm/mach-tegra/include/mach/dc.h1
-rw-r--r--arch/arm/mach-tegra/include/mach/latency_allowance.h4
-rw-r--r--arch/arm/mach-tegra/include/mach/usb_phy.h238
-rw-r--r--arch/arm/mach-tegra/iovmm-gart.c6
-rw-r--r--arch/arm/mach-tegra/p852/board-p852.c140
-rw-r--r--arch/arm/mach-tegra/pcie.c191
-rw-r--r--arch/arm/mach-tegra/tegra2_clocks.c39
-rw-r--r--arch/arm/mach-tegra/tegra2_mc.c6
-rw-r--r--arch/arm/mach-tegra/tegra2_usb_phy.c1598
-rw-r--r--arch/arm/mach-tegra/tegra3_clocks.c8
-rw-r--r--arch/arm/mach-tegra/tegra3_usb_phy.c2409
-rw-r--r--arch/arm/mach-tegra/tegra_usb_phy.h104
-rw-r--r--arch/arm/mach-tegra/usb_phy.c3391
-rw-r--r--chromeos/config/armel/config.common.armel528
-rw-r--r--chromeos/config/armel/config.flavour.chromeos-tegra3125
-rw-r--r--chromeos/config/armel/config.flavour.chromiumos-arm86
-rw-r--r--chromeos/config/config.common.chromeos2039
-rw-r--r--chromeos/config/i386/config.common.i386749
l---------chromeos/config/i386/config.flavour.chromeos-intel-menlow1
-rw-r--r--chromeos/config/i386/config.flavour.chromeos-pinetrail-i38641
-rw-r--r--chromeos/config/i386/config.flavour.chromiumos-i38685
-rw-r--r--chromeos/config/x86_64/config.common.x86_64740
-rw-r--r--chromeos/config/x86_64/config.flavour.chromeos-intel-pineview3
-rwxr-xr-xchromeos/scripts/allconfigs28
-rwxr-xr-xchromeos/scripts/kernelconfig123
-rwxr-xr-xchromeos/scripts/prepareconfig18
-rwxr-xr-xchromeos/scripts/splitconfig49
-rw-r--r--drivers/ata/Kconfig17
-rw-r--r--drivers/ata/Makefile1
-rw-r--r--drivers/ata/ahci-tegra.c2154
-rw-r--r--drivers/i2c/busses/i2c-tegra.c18
-rw-r--r--drivers/media/video/tegra/Kconfig7
-rw-r--r--drivers/media/video/tegra/Makefile1
-rw-r--r--drivers/media/video/tegra/ad5816.c1204
-rw-r--r--drivers/mfd/tps80031.c20
-rw-r--r--drivers/misc/tegra-baseband/bb-m7400.c15
-rw-r--r--drivers/mmc/host/sdhci-tegra.c16
-rw-r--r--drivers/net/wireless/bcm4329/wl_iw.c27
-rw-r--r--drivers/spi/spi-tegra.c405
-rw-r--r--drivers/usb/gadget/Makefile1
-rw-r--r--drivers/usb/gadget/android.c8
-rw-r--r--drivers/usb/gadget/fsl_tegra_udc.c170
-rw-r--r--drivers/usb/gadget/tegra_udc.c141
-rw-r--r--drivers/usb/host/ehci-hub.c12
-rw-r--r--drivers/usb/host/ehci-tegra.c1366
-rw-r--r--drivers/usb/host/ehci.h1
-rw-r--r--drivers/usb/otg/tegra-otg.c153
-rw-r--r--drivers/video/tegra/dc/dc.c17
-rw-r--r--drivers/video/tegra/dc/dc_reg.h2
-rw-r--r--drivers/video/tegra/dc/dsi.c17
-rw-r--r--drivers/video/tegra/fb.c12
-rw-r--r--drivers/video/tegra/host/bus_client.c56
-rw-r--r--drivers/video/tegra/host/chip_support.h12
-rw-r--r--drivers/video/tegra/host/debug.c67
-rw-r--r--drivers/video/tegra/host/gr3d/gr3d_t20.c2
-rw-r--r--drivers/video/tegra/host/gr3d/gr3d_t30.c2
-rw-r--r--drivers/video/tegra/host/host1x/host1x_cdma.c2
-rw-r--r--drivers/video/tegra/host/host1x/host1x_channel.c20
-rw-r--r--drivers/video/tegra/host/host1x/host1x_debug.c132
-rw-r--r--drivers/video/tegra/host/host1x/host1x_syncpt.c64
-rw-r--r--drivers/video/tegra/host/mpe/mpe.c2
-rw-r--r--drivers/video/tegra/host/nvhost_cdma.c45
-rw-r--r--drivers/video/tegra/host/nvhost_cdma.h7
-rw-r--r--drivers/video/tegra/host/nvhost_channel.c24
-rw-r--r--drivers/video/tegra/host/nvhost_channel.h8
-rw-r--r--drivers/video/tegra/host/nvhost_intr.c10
-rw-r--r--drivers/video/tegra/host/nvhost_job.c347
-rw-r--r--drivers/video/tegra/host/nvhost_job.h37
-rw-r--r--drivers/video/tegra/host/nvhost_syncpt.c30
-rw-r--r--drivers/video/tegra/host/nvhost_syncpt.h18
-rw-r--r--drivers/video/tegra/host/t30/t30.c2
-rw-r--r--drivers/video/tegra/nvmap/nvmap.c268
-rw-r--r--drivers/video/tegra/nvmap/nvmap.h86
-rw-r--r--drivers/video/tegra/nvmap/nvmap_dev.c19
-rw-r--r--drivers/video/tegra/nvmap/nvmap_handle.c73
-rw-r--r--include/linux/nvmap.h56
-rw-r--r--include/linux/platform_data/tegra_usb.h139
-rw-r--r--include/media/ad5816.h81
-rw-r--r--include/trace/events/nvhost.h95
-rw-r--r--security/tf_driver/Makefile2
-rw-r--r--security/tf_driver/s_version.h4
-rw-r--r--security/tf_driver/tf_comm_tz.c18
-rw-r--r--security/tf_driver/tf_protocol.h4
-rw-r--r--sound/soc/tegra/Makefile2
-rw-r--r--sound/soc/tegra/tegra20_das.c6
-rw-r--r--sound/soc/tegra/tegra20_das.h4
-rw-r--r--sound/soc/tegra/tegra_aic326x.c4
-rw-r--r--sound/soc/tegra/tegra_asoc_utils.c138
-rw-r--r--sound/soc/tegra/tegra_asoc_utils.h4
-rw-r--r--sound/soc/tegra/tegra_max98088.c4
-rw-r--r--sound/soc/tegra/tegra_max98095.c4
-rw-r--r--sound/soc/tegra/tegra_p1852.c42
-rw-r--r--sound/soc/tegra/tegra_pcm.c18
-rw-r--r--sound/soc/tegra/tegra_pcm.h1
-rw-r--r--sound/soc/tegra/tegra_rt5640.c5
-rw-r--r--sound/soc/tegra/tegra_wm8753.c5
-rw-r--r--sound/soc/tegra/tegra_wm8903.c4
124 files changed, 15562 insertions, 6697 deletions
diff --git a/arch/arm/configs/tegra3_android_defconfig b/arch/arm/configs/tegra3_android_defconfig
index ba20b0ee943f..2b4aee13812b 100644
--- a/arch/arm/configs/tegra3_android_defconfig
+++ b/arch/arm/configs/tegra3_android_defconfig
@@ -340,6 +340,7 @@ 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
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index 1aa448c44fcd..82306bc4aff5 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -22,6 +22,7 @@ config ARCH_TEGRA_2x_SOC
select PCI_MSI if TEGRA_PCI
select CPA
select ARM_ERRATA_716044
+ select ARM_ERRATA_764369 if SMP
select ARCH_HAS_SUSPEND_PAGETABLE
help
Support for NVIDIA Tegra AP20 and T20 processors, based on the
@@ -46,6 +47,7 @@ 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
@@ -259,6 +261,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
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index 6b1c4c52c713..3153203c6efc 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -44,6 +44,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
diff --git a/arch/arm/mach-tegra/baseband-xmm-power.c b/arch/arm/mach-tegra/baseband-xmm-power.c
index 20f8d306f901..4da5d412cf41 100644
--- a/arch/arm/mach-tegra/baseband-xmm-power.c
+++ b/arch/arm/mach-tegra/baseband-xmm-power.c
@@ -33,6 +33,7 @@
#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"
diff --git a/arch/arm/mach-tegra/board-cardhu-kbc.c b/arch/arm/mach-tegra/board-cardhu-kbc.c
index 16e83bbb03f8..c3971403148f 100644
--- a/arch/arm/mach-tegra/board-cardhu-kbc.c
+++ b/arch/arm/mach-tegra/board-cardhu-kbc.c
@@ -196,8 +196,8 @@ 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[] = {
@@ -252,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);
}
}
@@ -265,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);
}
}
diff --git a/arch/arm/mach-tegra/board-cardhu-panel.c b/arch/arm/mach-tegra/board-cardhu-panel.c
index 4899dee38042..a62171060b84 100644
--- a/arch/arm/mach-tegra/board-cardhu-panel.c
+++ b/arch/arm/mach-tegra/board-cardhu-panel.c
@@ -144,8 +144,6 @@ static int cardhu_backlight_init(struct device *dev)
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;
@@ -153,8 +151,6 @@ static int cardhu_backlight_init(struct device *dev)
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
@@ -168,8 +164,6 @@ static int cardhu_backlight_init(struct device *dev)
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);
/* Enable back light for DSIb panel */
ret = gpio_request(cardhu_dsib_bl_enb, "dsib_bl_enable");
@@ -179,8 +173,6 @@ static int cardhu_backlight_init(struct device *dev)
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
#if DSI_PANEL_219
@@ -192,8 +184,6 @@ static int cardhu_backlight_init(struct device *dev)
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
return ret;
@@ -206,7 +196,6 @@ static void cardhu_backlight_exit(struct device *dev)
/*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
@@ -214,12 +203,11 @@ static void cardhu_backlight_exit(struct device *dev)
/* 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);
gpio_set_value(cardhu_lvds_shutdown, 1);
mdelay(20);
@@ -229,7 +217,7 @@ static void cardhu_backlight_exit(struct device *dev)
/* 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);
@@ -762,8 +750,6 @@ static int cardhu_dsi_panel_enable(void)
ret = gpio_direction_output(AVDD_LCD, 1);
if (ret < 0)
gpio_free(AVDD_LCD);
- else
- tegra_gpio_enable(AVDD_LCD);
#if DSI_PANEL_219
@@ -774,8 +760,7 @@ static int cardhu_dsi_panel_enable(void)
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)
@@ -784,8 +769,7 @@ static int cardhu_dsi_panel_enable(void)
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);
@@ -805,8 +789,7 @@ static int cardhu_dsi_panel_enable(void)
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);
@@ -823,8 +806,7 @@ static int cardhu_dsi_panel_enable(void)
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);
@@ -847,18 +829,13 @@ static int cardhu_dsi_panel_disable(void)
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
@@ -882,7 +859,6 @@ static int cardhu_dsi_panel_postsuspend(void)
}
#if DSI_PANEL_218
- tegra_gpio_disable(AVDD_LCD);
gpio_free(AVDD_LCD);
#endif
@@ -1222,28 +1198,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,15 +1224,12 @@ 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);
gpio_request(cardhu_hdmi_hpd, "hdmi_hpd");
gpio_direction_input(cardhu_hdmi_hpd);
diff --git a/arch/arm/mach-tegra/board-cardhu-pinmux.c b/arch/arm/mach-tegra/board-cardhu-pinmux.c
index fd0a6ae34ffc..05e2179682b1 100644
--- a/arch/arm/mach-tegra/board-cardhu-pinmux.c
+++ b/arch/arm/mach-tegra/board-cardhu-pinmux.c
@@ -472,7 +472,6 @@ static __initdata struct tegra_pingroup_config cardhu_pinmux_cardhu_a03[] = {
static __initdata struct tegra_pingroup_config cardhu_pinmux_e1291_a04[] = {
DEFAULT_PINMUX(GMI_AD15, NAND, PULL_DOWN, NORMAL, OUTPUT),
- DEFAULT_PINMUX(ULPI_DATA5, UARTA, PULL_UP, NORMAL, INPUT),
DEFAULT_PINMUX(ULPI_DATA6, UARTA, NORMAL, NORMAL, OUTPUT),
DEFAULT_PINMUX(SPI2_MOSI, SPI6, NORMAL, NORMAL, INPUT),
DEFAULT_PINMUX(DAP3_SCLK, RSVD1, NORMAL, NORMAL, OUTPUT),
@@ -544,11 +543,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) \
@@ -755,7 +751,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-cardhu-pm298-power-rails.c b/arch/arm/mach-tegra/board-cardhu-pm298-power-rails.c
index 0305ee702cbd..f0dc8afa56fe 100644
--- a/arch/arm/mach-tegra/board-cardhu-pm298-power-rails.c
+++ b/arch/arm/mach-tegra/board-cardhu-pm298-power-rails.c
@@ -698,12 +698,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..6d4db73b6ecd 100644
--- a/arch/arm/mach-tegra/board-cardhu-pm299-power-rails.c
+++ b/arch/arm/mach-tegra/board-cardhu-pm299-power-rails.c
@@ -688,12 +688,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 79d8d6116edc..61b5a15ed5c7 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, Inc.
*
* 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
@@ -604,6 +604,7 @@ 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*/
@@ -649,6 +650,7 @@ 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", "2-0033"),
};
@@ -1072,13 +1074,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);
diff --git a/arch/arm/mach-tegra/board-cardhu-sdhci.c b/arch/arm/mach-tegra/board-cardhu-sdhci.c
index c4e631ddc108..cb0684bcc742 100644
--- a/arch/arm/mach-tegra/board-cardhu-sdhci.c
+++ b/arch/arm/mach-tegra/board-cardhu-sdhci.c
@@ -280,10 +280,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 66b3c9dc8ef3..042f740c2935 100644
--- a/arch/arm/mach-tegra/board-cardhu-sensors.c
+++ b/arch/arm/mach-tegra/board-cardhu-sensors.c
@@ -49,6 +49,7 @@
#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>
@@ -87,24 +88,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",
@@ -124,7 +121,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",
@@ -601,6 +597,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 = NVC_CFG_NODEV,
+ .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 = NVC_CFG_NODEV,
+ .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 = 0,
+ .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 = 0,
+ .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*/
@@ -628,6 +672,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[] = {
@@ -639,6 +687,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[] = {
@@ -650,6 +702,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[] = {
@@ -661,6 +717,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[] = {
@@ -785,8 +845,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;
@@ -916,7 +974,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);
@@ -933,7 +990,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 9083828b8352..4480ab3ef47b 100644
--- a/arch/arm/mach-tegra/board-cardhu.c
+++ b/arch/arm/mach-tegra/board-cardhu.c
@@ -86,43 +86,6 @@ static struct tegra_thermal_data thermal_data = {
#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,
- },
-};
-
static struct resource cardhu_bcm4329_rfkill_resources[] = {
{
.name = "bcm4329_nshutdown_gpio",
@@ -170,8 +133,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;
}
@@ -845,9 +806,6 @@ static int __init cardhu_touch_init(void)
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);
@@ -869,135 +827,287 @@ static int __init cardhu_touch_init(void)
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",
- },
-};
-
-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,
+};
+
+
+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);
+ }
+}
+
+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_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_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_otg_data tegra_otg_pdata = {
+ .ehci_device = &tegra_ehci1_device,
+ .ehci_pdata = &tegra_ehci1_utmi_pdata,
+};
+
+#if 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);
}
@@ -1005,19 +1115,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 = {
@@ -1095,7 +1192,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",
@@ -1115,22 +1212,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;
@@ -1168,7 +1252,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();
@@ -1182,7 +1265,6 @@ 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();
diff --git a/arch/arm/mach-tegra/board-enterprise-baseband.c b/arch/arm/mach-tegra/board-enterprise-baseband.c
index 7552e2871541..9143103fd036 100644
--- a/arch/arm/mach-tegra/board-enterprise-baseband.c
+++ b/arch/arm/mach-tegra/board-enterprise-baseband.c
@@ -67,35 +67,42 @@ static struct gpio modem_gpios[] = {
{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 void baseband_phy_init(void);
+static void baseband_phy_on(void);
+static void baseband_phy_off(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,
+static struct tegra_usb_phy_platform_ops ulpi_null_plat_ops = {
+ .init = baseband_phy_init,
.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,
+ .post_phy_on = baseband_phy_on,
};
-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_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 = 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,
+ },
+ .ops = &ulpi_null_plat_ops,
};
static int __init tegra_null_ulpi_init(void)
{
- tegra_ehci2_device.dev.platform_data = &ehci2_null_ulpi_platform_data;
+ tegra_ehci2_device.dev.platform_data = &tegra_ehci2_ulpi_null_pdata;
platform_device_register(&tegra_ehci2_device);
return 0;
}
@@ -114,7 +121,7 @@ static irqreturn_t mdm_start_thread(int irq, void *data)
return IRQ_HANDLED;
}
-static int baseband_phy_on(void)
+static void baseband_phy_init(void)
{
static bool phy_init = false;
@@ -124,22 +131,15 @@ static int baseband_phy_on(void)
phy_init = true;
}
pr_info("%s\n", __func__);
- return 0;
-}
-
-static int baseband_phy_off(void)
-{
- pr_info("%s\n", __func__);
- return 0;
}
-static void baseband_phy_restore_start(void)
+static void baseband_phy_off(void)
{
/* set AP2MDM_ACK2 high */
gpio_set_value(AP2MDM_ACK2, 1);
}
-static void baseband_phy_restore_end(void)
+static void baseband_phy_on(void)
{
/* set AP2MDM_ACK2 low */
gpio_set_value(AP2MDM_ACK2, 0);
diff --git a/arch/arm/mach-tegra/board-enterprise.c b/arch/arm/mach-tegra/board-enterprise.c
index a95ee617b1a8..d92ac57dd054 100644
--- a/arch/arm/mach-tegra/board-enterprise.c
+++ b/arch/arm/mach-tegra/board-enterprise.c
@@ -79,43 +79,6 @@ static struct tegra_thermal_data thermal_data = {
#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[] = {
{
.name = "bcm4329_nshutdown_gpio",
@@ -653,66 +616,120 @@ 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_L3);
+#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 = 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_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",
+ .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)
@@ -733,8 +750,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;
@@ -755,52 +772,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 = {
@@ -910,12 +887,9 @@ 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;
+ /* baseband-power.ko will register ehci2 device */
+ tegra_ehci2_device.dev.platform_data =
+ &tegra_ehci2_hsic_xmm_pdata;
/* enable XMM6260 baseband gpio(s) */
tegra_gpio_enable(tegra_baseband_power_data.modem.generic
.mdm_reset);
@@ -938,9 +912,9 @@ static void enterprise_baseband_init(void)
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
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..638c851fa7a8 100644
--- a/arch/arm/mach-tegra/board-harmony.c
+++ b/arch/arm/mach-tegra/board-harmony.c
@@ -32,6 +32,8 @@
#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 <sound/wm8903.h>
@@ -81,20 +83,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 +317,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 = {
@@ -476,7 +477,8 @@ static void __init tegra_harmony_init(void)
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.c b/arch/arm/mach-tegra/board-kai.c
index c455fba4cef9..193d68632d52 100644
--- a/arch/arm/mach-tegra/board-kai.c
+++ b/arch/arm/mach-tegra/board-kai.c
@@ -82,42 +82,6 @@ static struct tegra_thermal_data thermal_data = {
#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 = {
@@ -165,8 +129,15 @@ static struct platform_device kai_bluesleep_device = {
static noinline void __init kai_tegra_setup_tibluesleep(void)
{
+ int ret;
+
+ ret = gpio_request(TEGRA_GPIO_PU6, "host_wake");
+ if (ret)
+ pr_err("gpio_request failed for gpio: %d\n", TEGRA_GPIO_PU6);
+ else
+ gpio_direction_input(TEGRA_GPIO_PU6);
+
platform_device_register(&kai_bluesleep_device);
- tegra_gpio_enable(TEGRA_GPIO_PU6);
}
static __initdata struct tegra_clk_init_table kai_clk_init_table[] = {
@@ -695,47 +666,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 = NULL,
+ .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);
}
diff --git a/arch/arm/mach-tegra/board-p1852.c b/arch/arm/mach-tegra/board-p1852.c
index 43bef9975187..71c12756539d 100644
--- a/arch/arm/mach-tegra/board-p1852.c
+++ b/arch/arm/mach-tegra/board-p1852.c
@@ -57,42 +57,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 +65,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", 102000000, 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", 86500000, true},
{ "uarta", "pll_p", 480000000, true},
{ "uartd", "pll_p", 480000000, true},
{ "uarte", "pll_p", 480000000, true},
@@ -115,11 +80,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},
+ { "i2s0", "pll_a_out0", 24576000, false},
+ { "i2s1", "pll_a_out0", 24576000, false},
+ { "i2s2", "pll_a_out0", 24576000, false},
+ { "i2s3", "pll_a_out0", 24576000, false},
+ { "i2s4", "pll_a_out0", 24576000, false},
{ "audio0", "i2s0_sync", 12288000, false},
{ "audio1", "i2s1_sync", 12288000, false},
{ "audio2", "i2s2_sync", 12288000, false},
@@ -241,16 +206,24 @@ static struct tegra_p1852_platform_data p1852_audio_pdata = {
.cpu_dai_name = "tegra30-i2s.0",
.codec_name = "spdif-dit.0",
.name = "tegra-i2s-1",
- .i2s_format = format_i2s,
+ .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.1",
+ .cpu_dai_name = "tegra30-i2s.4",
.codec_name = "spdif-dit.1",
.name = "tegra-i2s-2",
- .i2s_format = format_i2s,
- .master = 0,
+ .i2s_format = format_tdm,
+ .master = 1,
+ .num_slots = 8,
+ .slot_width = 32,
+ .tx_mask = 0xff,
+ .rx_mask = 0xff,
},
};
@@ -278,7 +251,7 @@ static void p1852_i2s_audio_init(void)
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);
}
@@ -349,56 +322,91 @@ static struct platform_device *p1852_devices[] __initdata = {
&tegra_wdt_device
};
-static struct usb_phy_plat_data tegra_usb_phy_pdata[] = {
- [0] = {
- .instance = 0,
- .vbus_gpio = -1,
- .vbus_reg_supply = NULL,
+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,
},
- [1] = {
- .instance = 1,
- .vbus_gpio = -1,
- },
- [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 = 15,
+ .xcvr_setup_offset = 0,
+ .xcvr_use_fuses = 1,
+ .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,
+static struct tegra_usb_platform_data tegra_ehci2_utmi_pdata = {
+ .port_otg = false,
+ .has_hostpc = true,
+ .phy_intf = TEGRA_USB_PHY_INTF_UTMI,
+ .op_mode = TEGRA_USB_OPMODE_HOST,
+ .u_data.host = {
+ .vbus_gpio = -1,
+ .vbus_reg = NULL,
+ .hot_plug = false,
+ .remote_wakeup_supported = true,
+ .power_off_on_suspend = true,
+ },
+ .u_cfg.utmi = {
+ .hssync_start_delay = 0,
+ .idle_wait_delay = 17,
+ .elastic_limit = 16,
+ .term_range_adj = 6,
+ .xcvr_setup = 15,
+ .xcvr_setup_offset = 0,
+ .xcvr_use_fuses = 1,
+ .xcvr_lsfslew = 2,
+ .xcvr_lsrslew = 2,
},
- [1] = {
- .phy_config = &utmi_phy_config[1],
- .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 = 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 = 8,
+ .xcvr_setup_offset = 0,
+ .xcvr_use_fuses = 1,
+ .xcvr_lsfslew = 2,
+ .xcvr_lsrslew = 2,
},
};
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 = {
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.c b/arch/arm/mach-tegra/board-ventana.c
index d371e720fdcf..779ffdba0f65 100644
--- a/arch/arm/mach-tegra/board-ventana.c
+++ b/arch/arm/mach-tegra/board-ventana.c
@@ -63,35 +63,6 @@
#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[] = {
{
@@ -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,
@@ -498,73 +456,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 +607,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();
diff --git a/arch/arm/mach-tegra/board-whistler-baseband.c b/arch/arm/mach-tegra/board-whistler-baseband.c
index 143d14a8721d..eb50fb2f8237 100644
--- a/arch/arm/mach-tegra/board-whistler-baseband.c
+++ b/arch/arm/mach-tegra/board-whistler-baseband.c
@@ -24,10 +24,9 @@
#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 void baseband_phy_init(void);
+static void baseband_phy_on(void);
+static void baseband_phy_off(void);
static struct wake_lock mdm_wake_lock;
@@ -57,30 +56,38 @@ 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,
+static struct tegra_usb_phy_platform_ops ulpi_null_plat_ops = {
+ .init = baseband_phy_init,
.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,
+ .post_phy_on = baseband_phy_on,
};
-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_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 = false,
+ .remote_wakeup_supported = false,
+ .power_off_on_suspend = false,
+ },
+ .u_cfg.ulpi = {
+ .shadow_clk_delay = 10,
+ .clock_out_delay = 1,
+ .data_trimmer = 1,
+ .stpdirnxt_trimmer = 1,
+ .dir_trimmer = 1,
+ .clk = NULL,
+ },
+ .ops = &ulpi_null_plat_ops,
};
static int __init tegra_null_ulpi_init(void)
{
- tegra_ehci2_device.dev.platform_data = &ehci2_null_ulpi_platform_data;
+ tegra_ehci2_device.dev.platform_data = &tegra_ehci2_ulpi_null_pdata;
platform_device_register(&tegra_ehci2_device);
return 0;
}
@@ -98,7 +105,7 @@ static irqreturn_t mdm_start_thread(int irq, void *data)
return IRQ_HANDLED;
}
-static int baseband_phy_on(void)
+static void baseband_phy_init(void)
{
static bool phy_init;
@@ -108,22 +115,15 @@ static int baseband_phy_on(void)
phy_init = true;
}
pr_info("%s\n", __func__);
- return 0;
-}
-
-static int baseband_phy_off(void)
-{
- pr_info("%s\n", __func__);
- return 0;
}
-static void baseband_phy_restore_start(void)
+static void baseband_phy_off(void)
{
/* set AP2MDM_ACK2 high */
gpio_set_value(AP2MDM_ACK2, 1);
}
-static void baseband_phy_restore_end(void)
+static void baseband_phy_on (void)
{
/* set AP2MDM_ACK2 low */
gpio_set_value(AP2MDM_ACK2, 0);
diff --git a/arch/arm/mach-tegra/board-whistler-sdhci.c b/arch/arm/mach-tegra/board-whistler-sdhci.c
index d98b1d53a52e..2d2a9c8c01f8 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
@@ -256,8 +256,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);
diff --git a/arch/arm/mach-tegra/board-whistler.c b/arch/arm/mach-tegra/board-whistler.c
index ede0d0b11104..874ef18900e7 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
@@ -222,32 +222,6 @@ static void __init whistler_setup_bluesleep(void)
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},
@@ -455,61 +429,71 @@ static int __init whistler_scroll_init(void)
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 int __init whistler_gps_init(void)
+{
+ tegra_gpio_enable(TEGRA_GPIO_PU4);
+ 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,
},
- [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)
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 78bd77dfb7d2..2986f1cf61ac 100644
--- a/arch/arm/mach-tegra/common.c
+++ b/arch/arm/mach-tegra/common.c
@@ -974,12 +974,14 @@ void cpufreq_store_default_gov(void)
int cpufreq_change_gov(char *target_gov)
{
- unsigned int cpu = 0;
+ unsigned int cpu = 0, ret = -EINVAL;
#ifndef CONFIG_TEGRA_AUTO_HOTPLUG
for_each_online_cpu(cpu)
#endif
- return cpufreq_set_gov(target_gov, cpu);
+ ret = cpufreq_set_gov(target_gov, cpu);
+
+ return ret;
}
int cpufreq_restore_default_gov(void)
diff --git a/arch/arm/mach-tegra/devices.c b/arch/arm/mach-tegra/devices.c
index 2a4f94c4e22d..377772ff4291 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),
@@ -1226,18 +1201,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 = "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),
diff --git a/arch/arm/mach-tegra/include/mach/dc.h b/arch/arm/mach-tegra/include/mach/dc.h
index ab3d4e920f46..71f1be769507 100644
--- a/arch/arm/mach-tegra/include/mach/dc.h
+++ b/arch/arm/mach-tegra/include/mach/dc.h
@@ -503,6 +503,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 *);
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/usb_phy.h b/arch/arm/mach-tegra/include/mach/usb_phy.h
index 3ad1128e2026..c721642c4417 100644
--- a/arch/arm/mach-tegra/include/mach/usb_phy.h
+++ b/arch/arm/mach-tegra/include/mach/usb_phy.h
@@ -18,150 +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;
- 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/p852/board-p852.c b/arch/arm/mach-tegra/p852/board-p852.c
index 21b867e15177..ffdf5d3e4bae 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);
}
diff --git a/arch/arm/mach-tegra/pcie.c b/arch/arm/mach-tegra/pcie.c
index 1c4ee1b1f5ce..80a9a121f193 100644
--- a/arch/arm/mach-tegra/pcie.c
+++ b/arch/arm/mach-tegra/pcie.c
@@ -294,6 +294,9 @@
#define PCIE_CONF_REG(r) \
(((r) & ~0x3) | (((r) < 256) ? PCIE_CFG_OFF : PCIE_EXT_CFG_OFF))
+#define PCIE_CTRL_REGS 7
+#define COMBINE_PCIE_PCIX_SPACE 2
+
struct tegra_pcie_port {
int index;
u8 root_bus_nr;
@@ -349,6 +352,12 @@ static struct resource pcie_prefetch_mem_space;
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;
void __iomem *tegra_pcie_io_base;
EXPORT_SYMBOL(tegra_pcie_io_base);
@@ -986,7 +995,7 @@ static void tegra_pcie_clocks_put(void)
clk_put(tegra_pcie.pcie_xclk);
}
-static int __init tegra_pcie_get_resources(void)
+static int tegra_pcie_get_resources(void)
{
struct resource *res_mmio = 0;
int err;
@@ -1112,11 +1121,22 @@ retry:
return false;
}
-static void __init tegra_pcie_add_port(int index, u32 offset, u32 reset_reg)
+static void tegra_enable_clock_clamp(int index)
{
- struct tegra_pcie_port *pp;
unsigned int data;
+ /* Power mangagement settings */
+ /* Enable clock clamping by default */
+ data = rp_readl(NV_PCIE2_RP_PRIV_MISC, index);
+ data |= (PCIE2_RP_PRIV_MISC_CTLR_CLK_CLAMP_ENABLE) |
+ (PCIE2_RP_PRIV_MISC_TMS_CLK_CLAMP_ENABLE);
+ rp_writel(data, NV_PCIE2_RP_PRIV_MISC, index);
+}
+
+static void tegra_pcie_add_port(int index, u32 offset, u32 reset_reg)
+{
+ struct tegra_pcie_port *pp;
+
pp = tegra_pcie.port + tegra_pcie.num_ports;
pp->index = -1;
@@ -1128,13 +1148,7 @@ static void __init tegra_pcie_add_port(int index, u32 offset, u32 reset_reg)
printk(KERN_INFO "PCIE: port %d: link down, ignoring\n", index);
return;
}
- /* Power mangagement settings */
- /* Enable clock clamping by default */
- data = rp_readl(NV_PCIE2_RP_PRIV_MISC, index);
- data |= (PCIE2_RP_PRIV_MISC_CTLR_CLK_CLAMP_ENABLE) |
- (PCIE2_RP_PRIV_MISC_TMS_CLK_CLAMP_ENABLE);
- rp_writel(data, NV_PCIE2_RP_PRIV_MISC, index);
-
+ tegra_enable_clock_clamp(index);
tegra_pcie.num_ports++;
pp->index = index;
pp->root_bus_nr = -1;
@@ -1178,9 +1192,47 @@ static int tegra_pcie_init(void)
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;
+}
+
+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);
+}
+
static int tegra_pci_probe(struct platform_device *pdev)
{
- int ret;
+ int ret, size = 0, ndev = 0;
struct pci_dev *dev = NULL;
tegra_pcie.plat_data = pdev->dev.platform_data;
@@ -1194,39 +1246,91 @@ 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)
{
- int ret = 0;
+ int ret = 0, ndev = 0;
struct pci_dev *pdev = NULL;
- int i, size, ndev = 0;
if (!tegra_pcie.num_ports)
- return ret;
+ return ret;
for_each_pci_dev(pdev) {
/* save state of pcie devices before powering off regulators */
pci_save_state(pdev);
- size = sizeof(pdev->saved_config_space) / sizeof(u32);
- ndev++;
+ if (!pdev->subordinate)
+ pci_prepare_to_sleep(pdev);
}
- /* 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;
- ndev = 0;
for_each_pci_dev(pdev) {
- for (i = 0;i < size;i++) {
- memcpy(&pbackup_config_space[i + size*ndev],
- &pdev->saved_config_space[i], sizeof(u32));
- }
+ /* save control and config space registers*/
+ ret = tegra_pcie_save_state(pdev, ndev*2);
+ if (ret < 0)
+ return ret;
ndev++;
}
@@ -1239,50 +1343,45 @@ static int tegra_pci_resume_noirq(struct device *dev)
{
struct pci_dev *pdev = NULL;
- for_each_pci_dev(pdev) {
- /* set this flag to avoid restore state in resume noirq */
+ /* set this flag to avoid restore state in resume noirq */
+ for_each_pci_dev(pdev)
pdev->state_saved = 0;
- }
+
return 0;
}
static int tegra_pci_resume(struct device *dev)
{
- int ret = 0;
- int i, size, ndev = 0;
+ int ret = 0, ndev = 0;
struct pci_dev *pdev = NULL;
+ int port;
if (!tegra_pcie.num_ports)
- return ret;
+ 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();
- /* enable read/write registers after powering on */
- is_pcie_noirq_op = false;
+ for (port = 0; port < MAX_PCIE_SUPPORTED_PORTS; port++)
+ if (tegra_pcie.plat_data->port_status[port])
+ tegra_enable_clock_clamp(port);
for_each_pci_dev(pdev) {
- /* do fixup here for all dev's since not done in resume noirq */
- pci_fixup_device(pci_fixup_resume_early, 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;
-
- /* restore config space registers from backup buffer */
- size = sizeof(pdev->saved_config_space) / sizeof(u32);
- for (i = 0;i < size;i++) {
- memcpy(&pdev->saved_config_space[i],
- &pbackup_config_space[i + size*ndev], sizeof(u32));
- }
ndev++;
}
- kzfree(pbackup_config_space);
return ret;
}
static int tegra_pci_remove(struct platform_device *pdev)
{
+ tegra_pcie_deallocate_config_states();
return 0;
}
#ifdef CONFIG_PM
diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c
index af30cf2ea18c..fa88b11552d9 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) {
@@ -2771,7 +2772,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)
{
@@ -2779,6 +2780,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);
@@ -2831,11 +2834,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);
@@ -2848,9 +2866,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);
@@ -2887,6 +2909,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_mc.c b/arch/arm/mach-tegra/tegra2_mc.c
index 6df9c232c02f..1b72af0735f6 100644
--- a/arch/arm/mach-tegra/tegra2_mc.c
+++ b/arch/arm/mach-tegra/tegra2_mc.c
@@ -896,8 +896,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..819721c49a29
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra2_usb_phy.c
@@ -0,0 +1,1598 @@
+/*
+ * arch/arm/mach-tegra/tegra2_usb_phy.c
+ *
+ * Copyright (C) 2011 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/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/iomap.h>
+#include <mach/pinmux.h>
+#include <asm/mach-types.h>
+#include <mach/usb_phy.h>
+#include "tegra_usb_phy.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)
+
+/* 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));
+ }
+ }
+
+ 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 (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 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;
+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_clocks.c b/arch/arm/mach-tegra/tegra3_clocks.c
index 2dfdb1db39b7..9ff183377c2d 100644
--- a/arch/arm/mach-tegra/tegra3_clocks.c
+++ b/arch/arm/mach-tegra/tegra3_clocks.c
@@ -284,7 +284,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)
@@ -3906,7 +3906,7 @@ static struct clk tegra_clk_sclk = {
.reg = 0x28,
.ops = &tegra_super_ops,
.max_rate = 378000000,
- .min_rate = 40000000,
+ .min_rate = 12000000,
};
static struct clk tegra_clk_virtual_cpu_g = {
@@ -3961,7 +3961,7 @@ static struct clk tegra_clk_hclk = {
.reg_shift = 4,
.ops = &tegra_bus_ops,
.max_rate = 378000000,
- .min_rate = 40000000,
+ .min_rate = 12000000,
};
static struct clk tegra_clk_pclk = {
@@ -3972,7 +3972,7 @@ static struct clk tegra_clk_pclk = {
.reg_shift = 0,
.ops = &tegra_bus_ops,
.max_rate = 167000000,
- .min_rate = 40000000,
+ .min_rate = 12000000,
};
static struct raw_notifier_head sbus_rate_change_nh;
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..5b3e51974d3b
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra3_usb_phy.c
@@ -0,0 +1,2409 @@
+/*
+ * arch/arm/mach-tegra/tegra3_usb_phy.c
+ *
+ * Copyright (C) 2011 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/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/iomap.h>
+#include <mach/pinmux.h>
+#include "tegra_usb_phy.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 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_STAT_CFG0 0xc28
+#define UHSIC_CONNECT_DETECT (1 << 0)
+
+#define PMC_USB_DEBOUNCE 0xec
+#define UTMIP_LINE_DEB_CNT(x) (((x) & 0xf) << 16)
+
+#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_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 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_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)
+
+#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_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_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 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 USB1_PREFETCH_ID 6
+#define USB2_PREFETCH_ID 18
+#define USB3_PREFETCH_ID 17
+
+#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_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 FUSE_USB_CALIB_0 0x1F0
+#define FUSE_USB_CALIB_XCVR_SETUP(x) (((x) & 0x7F) << 0)
+
+/* 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);
+
+ /* 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 == 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);
+}
+
+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);
+}
+
+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_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);
+}
+
+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);
+ 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 = 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)
+{
+ 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);
+ }
+
+ val = readl(base + USB_PORTSC);
+ val |= USB_PORTSC_WKCN;
+ writel(val, base + USB_PORTSC);
+
+ 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;
+
+ 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));
+ }
+ }
+
+ 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;
+
+ /* check if OBS bus is already enabled */
+ val = readl(base + UTMIP_MISC_CFG0);
+ if (val & UTMIP_DPDM_OBSERVE) {
+ PHY_DBG("DISABLE_OBS_BUS\n");
+ /* 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);
+ 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);
+
+ val = (readl(base + HOSTPC1_DEVLC) >> 25) &
+ HOSTPC1_DEVLC_PSPD_MASK;
+ if (val == 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);
+ }
+
+ 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 {
+ 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);
+
+ phy->port_speed = (readl(base + HOSTPC1_DEVLC) >> 25) &
+ HOSTPC1_DEVLC_PSPD_MASK;
+
+ if (phy->pdata->u_data.host.hot_plug) {
+ bool enable_hotplug = true;
+ /* if it is OTG port then make sure to enable hot-plug feature
+ 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);
+ 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 */
+ if (UTMIP_WALK_PTR_VAL(inst) & val) {
+ phy->remote_wakeup = true;
+ } else {
+ 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 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;
+ }
+
+ utmip_powerup_pmc_wake_detect(phy);
+
+ 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);
+
+ utmip_powerup_pmc_wake_detect(phy);
+
+ 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 + 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(2);
+
+ 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 + 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;
+ }
+
+ 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);
+
+ utmip_powerdown_pmc_wake_detect(phy);
+
+ 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 + UHSIC_STAT_CFG0);
+ val &= ~UHSIC_CONNECT_DETECT;
+ writel(val, base + UHSIC_STAT_CFG0);
+
+ 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;
+ /* 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 (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);
+ 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_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;
+}
+
+int uhsic_phy_resume(struct tegra_usb_phy *phy)
+{
+ void __iomem *base = phy->regs;
+ unsigned long val;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+
+ /* 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_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);
+
+ /* 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));
+
+ 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 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_HOST;
+ writel(val, base + USB_USBMODE);
+
+ val = readl(base + HOSTPC1_DEVLC);
+ val |= HOSTPC1_DEVLC_PTS(2);
+ writel(val, base + HOSTPC1_DEVLC);
+}
+
+
+
+static inline void null_phy_set_tristate(bool enable)
+{
+#ifndef CONFIG_ARCH_TEGRA_2x_SOC
+ int tristate = (enable) ? TEGRA_TRI_TRISTATE : TEGRA_TRI_NORMAL;
+ DBG("%s(%d) inst:[%s] FIXME enable pin group +++\n", __func__,
+ __LINE__, enable ? "TRISTATE" : "NORMAL");
+
+ tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA0, tristate);
+ tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA1, tristate);
+ tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA2, tristate);
+ tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA3, tristate);
+ tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA4, tristate);
+ tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA5, tristate);
+ tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA6, tristate);
+ tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA7, tristate);
+ tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_NXT, tristate);
+
+ if (enable)
+ tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DIR, tristate);
+#endif
+
+}
+
+
+static int ulpi_null_phy_power_off(struct tegra_usb_phy *phy)
+{
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+
+ if (!phy->phy_clk_on) {
+ DBG("%s(%d) inst:[%d] phy clk is already off\n", __func__,
+ __LINE__, phy->inst);
+ return 0;
+ }
+
+ null_phy_set_tristate(true);
+
+ phy->phy_clk_on = false;
+ phy->hw_accessible = false;
+
+ return 0;
+}
+
+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;
+}
+
+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_power_on(struct tegra_usb_phy *phy)
+{
+ unsigned long val;
+ void __iomem *base = phy->regs;
+ struct tegra_ulpi_config *config = &phy->pdata->u_cfg.ulpi;
+ static bool cold_boot = true;
+
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+ if (phy->phy_clk_on) {
+ DBG("%s(%d) inst:[%d] phy clk is already On\n", __func__,
+ __LINE__, phy->inst);
+ return 0;
+ }
+ 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 (cold_boot) {
+ val = readl(base + ULPI_TIMING_CTRL_0);
+ val |= ULPI_CLK_PADOUT_ENA;
+ writel(val, base + ULPI_TIMING_CTRL_0);
+ cold_boot = false;
+ }
+ udelay(10);
+
+ phy->phy_clk_on = true;
+ phy->hw_accessible = true;
+
+ return 0;
+}
+
+
+int ulpi_null_phy_pre_resume(struct tegra_usb_phy *phy, bool remote_wakeup)
+{
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
+
+ usb_phy_wait_for_sof(phy);
+ return 0;
+}
+
+static 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 = {
+ .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,
+ .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_usb_phy.h b/arch/arm/mach-tegra/tegra_usb_phy.h
new file mode 100644
index 000000000000..36b88db94f52
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra_usb_phy.h
@@ -0,0 +1,104 @@
+/*
+ * arch/arm/mach-tegra/include/mach/tegra_usb_phy.h
+ *
+ * Copyright (C) 2011 NVIDIA Corporation.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __MACH_TEGRA_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 phy_power_on;
+ bool remote_wakeup;
+ bool hw_accessible;
+};
+
+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/usb_phy.c b/arch/arm/mach-tegra/usb_phy.c
index 8c36159e085a..6f568fd2cd29 100644
--- a/arch/arm/mach-tegra/usb_phy.c
+++ b/arch/arm/mach-tegra/usb_phy.c
@@ -18,7 +18,6 @@
* GNU General Public License for more details.
*
*/
-
#include <linux/resource.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
@@ -27,581 +26,16 @@
#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"
-
-
-#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
@@ -609,2587 +43,599 @@ 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, NULL},
- { 0, 0, -1, NULL},
- { 0, 0, -1, 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_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)
+static void usb_host_vbus_enable(struct tegra_usb_phy *phy, bool enable)
{
- if (phy->instance != 0)
- iounmap(phy->pad_regs);
- clk_put(phy->pad_clk);
-}
-
-static int utmip_pad_power_on(struct tegra_usb_phy *phy)
-{
- 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 ? 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)
-{
- unsigned long val;
- void __iomem *base = phy->regs;
-
-#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);
-
- 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 (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, 0) < 0)
- pr_err("%s: timeout waiting for phy to stabilize\n", __func__);
-}
-
-static void utmi_phy_clk_enable(struct tegra_usb_phy *phy)
-{
- 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);
-
- val = readl(base + USB_SUSP_CTRL);
- val &= ~USB_SUSP_CLR;
- writel(val, base + USB_SUSP_CTRL);
- }
-
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- if (phy->instance == 2) {
- val = readl(base + USB_PORTSC1);
- val &= ~USB_PORTSC1_PHCD;
- writel(val, base + USB_PORTSC1);
- }
-#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)
+int tegra_usb_phy_init_ops(struct tegra_usb_phy *phy)
{
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- int gpio_status;
- int gpio = usb_phy_data[phy->instance].vbus_gpio;
-
- 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, 1);
- if (gpio_status < 0) {
- printk("VBUS_USB request GPIO DIRECTION FAILED \n");
- WARN_ON(1);
- return;
- }
- gpio_set_value_cansleep(gpio, 1);
-#else
- if (phy->reg_vbus)
- regulator_enable(phy->reg_vbus);
-#endif
-}
+ int err = 0;
-static void vbus_disable(struct tegra_usb_phy *phy)
-{
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- int gpio = usb_phy_data[phy->instance].vbus_gpio;
-
- if (gpio == -1)
- return;
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
- gpio_set_value_cansleep(gpio, 0);
- 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);
-}
+ if (phy->pdata->has_hostpc)
+ err = tegra3_usb_phy_init_ops(phy);
+ else
+ err = tegra2_usb_phy_init_ops(phy);
-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);
+ return err;
}
-static void uhsic_powerdown_pmc_wake_detect(struct tegra_usb_phy *phy)
+static irqreturn_t usb_phy_dev_vbus_pmu_irq_thr(int irq, void *pdata)
{
- 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);
-}
+ /* FIXME : Need to enable pmu vbus handling */
-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_NONE;
}
-#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);
+ 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);
+ 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;
}
-#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
- }
-
- 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->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);
-#endif
- unsigned int inst = phy->instance;
-
-#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 {
+ 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, 1) < 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
+ 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 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 usb_phy_set_tx_fill_tuning(struct tegra_usb_phy *phy, bool is_dpd)
-{
- unsigned long val;
- void __iomem *base = phy->regs;
+ if (phy->pdata->ops && phy->pdata->ops->open)
+ phy->pdata->ops->open();
- 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->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;
+ }
}
- return 0;
-}
+ if (phy->vdd_reg)
+ regulator_enable(phy->vdd_reg);
-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;
+ return phy;
- 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;
+fail_init:
+ tegra_usb_phy_release_clocks(phy);
- 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;
+ 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 {
- if (!((UTMIP_USBON_VAL(phy->instance) |
- UTMIP_USBOP_VAL(phy->instance)) & val)) {
- utmip_phy_disable_pmc_bus_ctrl(phy);
- }
- }
- 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;
-
- 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;
+ 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, 0);
+ 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);
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
- 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
+ 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, 0);
+ gpio_free(gpio);
+ }
+ }
}
- ulpi_phy_reset(base);
- ulpi_set_host(base);
-
- 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);
-
-#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);
+ tegra_usb_phy_release_clocks(phy);
- 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;
- }
-
- ret = otg_io_write(phy->ulpi, 0x80, 0x0B);
- if (ret) {
- pr_err("%s: ulpi write failed\n", __func__);
- return ret;
+ if (phy->vdd_reg) {
+ 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);
-
- return 0;
-}
-
-static int ulpi_phy_power_off(struct tegra_usb_phy *phy, bool is_dpd)
-{
- 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);
-
- /* Put the PHY in the low power mode */
- val = readl(base + USB_PORTSC1);
- val |= USB_PORTSC1_PHCD;
- writel(val, base + USB_PORTSC1);
-
- 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->ops && phy->ops->close)
+ phy->ops->close(phy);
- if(phy->clk)
- clk_disable(phy->clk);
+ if (phy->pdata->ops && phy->pdata->ops->close)
+ phy->pdata->ops->close();
- return 0;
+ kfree(phy->pdata);
+ kfree(phy);
}
-static inline void null_phy_set_tristate(bool enable)
+irqreturn_t tegra_usb_phy_irq(struct tegra_usb_phy *phy)
{
- 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
-}
+ irqreturn_t status = IRQ_HANDLED;
-static void null_phy_restore_start(struct tegra_usb_phy *phy,
- enum tegra_usb_phy_port_speed port_speed)
-{
- struct tegra_ulpi_config *config = phy->config;
+ if (phy->ops && phy->ops->irq)
+ status = phy->ops->irq(phy);
- if (config->phy_restore_start)
- config->phy_restore_start();
+ return status;
}
-
-static void null_phy_restore_end(struct tegra_usb_phy *phy)
+int tegra_usb_phy_init(struct tegra_usb_phy *phy)
{
- unsigned long val;
- void __iomem *base = phy->regs;
- struct tegra_ulpi_config *config = phy->config;
+ int status = 0;
- /* disable ULPI pinmux bypass */
- ulpi_pinmux_bypass(phy, false);
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
- /* driving linestate using GPIO */
- gpio_set_value(config->ulpi_d0_gpio, 0);
- gpio_set_value(config->ulpi_d1_gpio, 0);
-
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- /* driving DIR high */
- gpio_set_value(config->ulpi_dir_gpio, 1);
-#endif
+ if (phy->pdata->ops && phy->pdata->ops->init)
+ phy->pdata->ops->init();
- /* 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 (phy->ops && phy->ops->init)
+ status = phy->ops->init(phy);
- 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;
-
- if (!config->trimmer)
- config->trimmer = &default_trimmer;
-
- ulpi_phy_reset(base);
-
-#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;
- }
+ int err = 0;
- /* set ULPI trimmers */
- ulpi_set_trimmer(base, config->trimmer->data_trimmer,
- config->trimmer->stpdirnxt_trimmer, 1);
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
- ulpi_set_host(base);
+ if (!phy->phy_power_on)
+ return err;
-#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;
+ 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();
}
- 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);
+ clk_disable(phy->emc_clk);
+ clk_disable(phy->sys_clk);
+ clk_disable(phy->ctrlr_clk);
- if (config->post_phy_off && config->post_phy_off())
- return -EAGAIN;
+ phy->phy_power_on = false;
- 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);
-
- /* 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);
-#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);
-
- val = readl(base + USB_SUSP_CTRL);
- val &= ~(UHSIC_RESET);
- writel(val, base + USB_SUSP_CTRL);
- udelay(2);
-
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- val = readl(base + USB_PORTSC1);
- val &= ~USB_PORTSC1_PTS(~0);
- writel(val, base + USB_PORTSC1);
-
-#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
- usb_phy_set_tx_fill_tuning(phy, is_dpd);
+ int status = 0;
- val = readl(base + USB_PORTSC1);
- val &= ~(USB_PORTSC1_WKOC | USB_PORTSC1_WKDS | USB_PORTSC1_WKCN);
- writel(val, base + USB_PORTSC1);
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
- 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 (phy->phy_power_on)
+ return status;
- 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;
- }
-
- return 0;
-}
+ clk_enable(phy->ctrlr_clk);
+ clk_enable(phy->sys_clk);
+ clk_enable(phy->emc_clk);
-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->ops && phy->ops->pre_suspend)
+ status = phy->ops->pre_suspend(phy);
- 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);
- }
-
-#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;
}
-
-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) {
+ 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();
}
- 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;
}
-
-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;
}
-
-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);
+ return status;
}
-
-void tegra_usb_phy_postresume(struct tegra_usb_phy *phy, bool is_dpd)
+int tegra_usb_phy_resume(struct tegra_usb_phy *phy)
{
- const tegra_phy_fp postresume[] = {
- utmi_phy_postresume,
- NULL,
- NULL,
- NULL,
- };
+ int err = 0;
- usb_phy_set_tx_fill_tuning(phy, is_dpd);
-
- // If Phy type is utmi, call its post resume
- if (phy->usb_phy_type == 0)
- utmi_phy_postresume(phy, is_dpd);
-}
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
-void tegra_ehci_pre_reset(struct tegra_usb_phy *phy, bool is_dpd)
-{
- const tegra_phy_fp pre_reset[] = {
- NULL,
- NULL,
- null_phy_pre_usbcmd_reset,
- NULL,
- };
+ if (phy->pdata->u_data.host.power_off_on_suspend) {
+ if (phy->pdata->ops && phy->pdata->ops->pre_phy_on)
+ phy->pdata->ops->pre_phy_on();
+ err = phy->ops->power_on(phy);
+ if (phy->pdata->ops && phy->pdata->ops->post_phy_on)
+ phy->pdata->ops->post_phy_on();
+ }
- if (pre_reset[phy->usb_phy_type])
- pre_reset[phy->usb_phy_type](phy, is_dpd);
-}
+ if (!err && phy->ops && phy->ops->resume)
+ err = phy->ops->resume(phy);
-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,
- };
+ return err;
- if (post_reset[phy->usb_phy_type])
- post_reset[phy->usb_phy_type](phy, is_dpd);
}
-
-void tegra_ehci_phy_restore_start(struct tegra_usb_phy *phy,
- enum tegra_usb_phy_port_speed port_speed)
+int tegra_usb_phy_post_resume(struct tegra_usb_phy *phy)
{
- const tegra_phy_restore_start_fp phy_restore_start[] = {
- utmi_phy_restore_start,
- ulpi_phy_restore_start,
- null_phy_restore_start,
- NULL,
- };
+ int status = 0;
- if (phy_restore_start[phy->usb_phy_type])
- phy_restore_start[phy->usb_phy_type](phy, port_speed);
-}
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
-void tegra_ehci_phy_restore_end(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,
- };
+ if (phy->ops && phy->ops->post_resume)
+ status = phy->ops->post_resume(phy);
- if (phy_restore_end[phy->usb_phy_type])
- phy_restore_end[phy->usb_phy_type](phy);
-}
+ if (phy->pdata->ops && phy->pdata->ops->post_resume)
+ phy->pdata->ops->post_resume();
-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);
+ return status;
}
-
-void tegra_usb_phy_clk_enable(struct tegra_usb_phy *phy)
+int tegra_usb_phy_port_power(struct tegra_usb_phy *phy)
{
- if (phy->usb_phy_type == TEGRA_USB_PHY_TYPE_UTMIP)
- utmi_phy_clk_enable(phy);
-}
+ int status = 0;
-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);
-}
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
-int tegra_usb_phy_bus_connect(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);
-
- val = readl(base + UHSIC_MISC_CFG0);
- val |= UHSIC_FORCE_XCVR_MODE;
- writel(val, base + UHSIC_MISC_CFG0);
+ if (phy->ops && phy->ops->port_power)
+ status = phy->ops->port_power(phy);
- 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;
- }
-
-#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
- }
+ if (phy->pdata->ops && phy->pdata->ops->port_power)
+ phy->pdata->ops->port_power();
- 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;
- }
+ DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
-#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);
-
- 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 (phy->ops && phy->ops->bus_reset)
+ status = phy->ops->bus_reset(phy);
- 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;
}
-#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_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)
@@ -3197,7 +643,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);
@@ -3212,7 +658,7 @@ 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);
@@ -3221,38 +667,3 @@ void tegra_usb_phy_memory_prefetch_off(struct tegra_usb_phy *phy)
writel(val, ahb_gizmo + AHB_MEM_PREFETCH_CFG2);
}
}
-
-/* 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/chromeos/config/armel/config.common.armel b/chromeos/config/armel/config.common.armel
new file mode 100644
index 000000000000..efc5f4e20ae0
--- /dev/null
+++ b/chromeos/config/armel/config.common.armel
@@ -0,0 +1,528 @@
+#
+# Config options generated by splitconfig
+#
+CONFIG_AEABI=y
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_APM_EMULATION is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_BCMRING is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CNS3XXX is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_EXYNOS4 is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_H720X is not set
+CONFIG_ARCH_HAS_CPUFREQ=y
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_LPC32XX is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_MXS is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_NOMADIK is not set
+CONFIG_ARCH_NR_GPIO=512
+# CONFIG_ARCH_NUC93X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PRIMA2 is not set
+CONFIG_ARCH_PROVIDES_UDELAY=y
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_REALVIEW is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_S5P64X0 is not set
+# CONFIG_ARCH_S5PC100 is not set
+# CONFIG_ARCH_S5PV210 is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_SHMOBILE is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_TCC_926 is not set
+CONFIG_ARCH_TEGRA=y
+CONFIG_ARCH_TEGRA_HAS_PCIE=y
+# CONFIG_ARCH_U300 is not set
+# CONFIG_ARCH_U8500 is not set
+# CONFIG_ARCH_USES_GETTIMEOFFSET is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_VEXPRESS is not set
+# CONFIG_ARCH_VT8500 is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_ZYNQ is not set
+CONFIG_ARM=y
+CONFIG_ARM_DMA_MEM_BUFFERABLE=y
+# CONFIG_ARM_ERRATA_430973 is not set
+# CONFIG_ARM_ERRATA_458693 is not set
+# CONFIG_ARM_ERRATA_460075 is not set
+# CONFIG_ARM_ERRATA_720789 is not set
+# CONFIG_ARM_ERRATA_720791 is not set
+CONFIG_ARM_ERRATA_742230=y
+# CONFIG_ARM_ERRATA_742231 is not set
+# CONFIG_ARM_ERRATA_753970 is not set
+# CONFIG_ARM_ERRATA_754327 is not set
+# CONFIG_ARM_ERRATA_764369 is not set
+# CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART is not set
+CONFIG_ARM_GIC=y
+CONFIG_ARM_L1_CACHE_SHIFT=5
+# CONFIG_ARM_PATCH_PHYS_VIRT is not set
+CONFIG_ARM_SAVE_DEBUG_CONTEXT=y
+CONFIG_ARM_THUMB=y
+CONFIG_ARM_THUMBEE=y
+CONFIG_ARM_UNWIND=y
+# CONFIG_ATA is not set
+# CONFIG_ATH5K is not set
+# CONFIG_ATH5K_PCI is not set
+# CONFIG_ATH6K_LEGACY is not set
+# CONFIG_ATH9K is not set
+# CONFIG_ATL1 is not set
+# CONFIG_ATL1C is not set
+# CONFIG_ATL1E is not set
+# CONFIG_ATL2 is not set
+# CONFIG_AUTO_ZRELADDR is not set
+# CONFIG_AX88796 is not set
+# CONFIG_B44 is not set
+CONFIG_BACKLIGHT_PWM=y
+# CONFIG_BACKLIGHT_TEGRA_PWM is not set
+CONFIG_BATTERY_BQ20Z75=y
+# CONFIG_BCM4329 is not set
+# CONFIG_BCMDHD is not set
+# CONFIG_BE2ISCSI is not set
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_BRCMDBG is not set
+CONFIG_BRCMFMAC=m
+CONFIG_BRCMUTIL=m
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_BT_ATH3K is not set
+# CONFIG_BT_HCIBCM203X is not set
+# CONFIG_BT_HCIBPA10X is not set
+CONFIG_BT_HCIBTSDIO=m
+CONFIG_BT_HCIUART=m
+# CONFIG_BT_HCIUART_ATH3K is not set
+# CONFIG_BT_HCIUART_BCSP is not set
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_LL=y
+CONFIG_CACHE_L2X0=y
+CONFIG_CACHE_PL310=y
+CONFIG_CHARGER_GPIO=y
+# CONFIG_CHARGER_ISP1704 is not set
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_CLKSRC_MMIO=y
+CONFIG_CMDLINE="mem=448M@0M console=ttyS0,115200n8 earlyprintk init=/bin/ash"
+# CONFIG_CMDLINE_EXTEND is not set
+# CONFIG_CMDLINE_FORCE is not set
+CONFIG_CMDLINE_FROM_BOOTLOADER=y
+CONFIG_COMPAT_BRK=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_CPA=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_GOV_USERSPACE is not set
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_HAS_PMU=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+CONFIG_CPU_PABRT_V7=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_V7=y
+# CONFIG_CRASH_DUMP is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_DEV_TEGRA_AES is not set
+# CONFIG_DCC_TTY is not set
+# CONFIG_DEBUG_HIGHMEM is not set
+# CONFIG_DEBUG_ICEDCC is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEPRECATED_PARAM_STRUCT is not set
+# CONFIG_DM9000 is not set
+# CONFIG_DRM is not set
+CONFIG_DTC=y
+# CONFIG_E1000 is not set
+# CONFIG_E1000E is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_TEGRA=y
+# CONFIG_FCOE is not set
+CONFIG_FIQ=y
+# CONFIG_FIQ_DEBUGGER is not set
+CONFIG_FLATMEM=y
+CONFIG_FLATMEM_MANUAL=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_FRAME_WARN=1024
+# CONFIG_FTGMAC100 is not set
+# CONFIG_FTMAC100 is not set
+CONFIG_FUNCTION_GRAPH_TRACER=y
+CONFIG_HARDIRQS_SW_RESEND=y
+# CONFIG_HARDLOCKUP_DETECTOR is not set
+CONFIG_HAVE_AOUT=y
+CONFIG_HAVE_ARCH_PFN_VALID=y
+CONFIG_HAVE_ARM_SCU=y
+CONFIG_HAVE_ARM_TWD=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_HAVE_PWM=y
+CONFIG_HAVE_SCHED_CLOCK=y
+# CONFIG_HID_MICROSOFT is not set
+# CONFIG_HID_PID is not set
+CONFIG_HIGHMEM=y
+# CONFIG_HIGHPTE is not set
+# CONFIG_HOSTAP_PCI is not set
+# CONFIG_HOSTAP_PLX is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HVC_DCC is not set
+CONFIG_HW_PERF_EVENTS=y
+CONFIG_HZ=100
+# CONFIG_I2C_DESIGNWARE is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_PIIX4 is not set
+CONFIG_I2C_TEGRA=y
+# CONFIG_IGBVF is not set
+# CONFIG_INPUT_PWM_BEEPER is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+CONFIG_IRQ_DOMAIN=y
+# CONFIG_ISCSI_BOOT_SYSFS is not set
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_IWL3945 is not set
+# CONFIG_IWL4965 is not set
+# CONFIG_IWLAGN is not set
+# CONFIG_IWM is not set
+# CONFIG_IWMC3200TOP is not set
+# CONFIG_JME is not set
+CONFIG_KEYBOARD_TEGRA=y
+CONFIG_KTIME_SCALAR=y
+CONFIG_LBDAF=y
+CONFIG_LEDS_PWM=y
+# CONFIG_LEDS_REGULATOR is not set
+# CONFIG_LIBERTAS_THINFIRM_USB is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+CONFIG_LOCAL_TIMERS=y
+# CONFIG_LPC_SCH is not set
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_MACH_HAS_SND_SOC_TEGRA_WM8903=y
+# CONFIG_MACH_TEGRA_DT is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_MFD_ASIC3 is not set
+CONFIG_MFD_CORE=y
+# CONFIG_MFD_NVEC is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_MG_DISK is not set
+CONFIG_MMC=y
+# CONFIG_MMC_BKOPS is not set
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set
+CONFIG_MMC_BLOCK_MINORS=16
+# CONFIG_MMC_CB710 is not set
+# CONFIG_MMC_CLKGATE is not set
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_DW is not set
+# CONFIG_MMC_EMBEDDED_SDIO is not set
+# CONFIG_MMC_PARANOID_SD_INIT is not set
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_IO_ACCESSORS=y
+# CONFIG_MMC_SDHCI_PCI is not set
+CONFIG_MMC_SDHCI_PLTFM=y
+# CONFIG_MMC_SDHCI_PXAV2 is not set
+# CONFIG_MMC_SDHCI_PXAV3 is not set
+CONFIG_MMC_SDHCI_TEGRA=y
+# CONFIG_MMC_TEST is not set
+# CONFIG_MMC_TIFM_SD is not set
+CONFIG_MMC_UNSAFE_RESUME=y
+# CONFIG_MMC_USHC is not set
+# CONFIG_MMC_VIA_SDMMC is not set
+# CONFIG_MMC_VUB300 is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_PS2 is not set
+CONFIG_NEED_DMA_MAP_STATE=y
+# CONFIG_NET_PCI is not set
+CONFIG_NVMAP_ALLOW_SYSMEM=y
+CONFIG_NVMAP_CARVEOUT_COMPACTOR=y
+# CONFIG_NVMAP_CARVEOUT_KILLER is not set
+# CONFIG_NVMAP_HIGHMEM_ONLY is not set
+CONFIG_NVMAP_PAGE_POOLS=y
+CONFIG_NVMAP_PAGE_POOL_SIZE=0x0
+CONFIG_NVMAP_RECLAIM_UNPINNED_VM=y
+# CONFIG_NVMAP_VPR is not set
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_OC_ETM is not set
+CONFIG_OF=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_DEVICE=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_GPIO=y
+CONFIG_OF_I2C=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_MDIO=y
+CONFIG_OF_NET=y
+CONFIG_OF_PCI=y
+CONFIG_OF_PCI_IRQ=y
+CONFIG_OF_SPI=y
+CONFIG_OLD_MCOUNT=y
+CONFIG_OUTER_CACHE=y
+CONFIG_OUTER_CACHE_SYNC=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_PCI_SYSCALL=y
+CONFIG_PERF_USE_VMALLOC=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+# CONFIG_PL310_ERRATA_588369 is not set
+# CONFIG_PL310_ERRATA_727915 is not set
+# CONFIG_PL310_ERRATA_769419 is not set
+# CONFIG_PLAT_SPEAR is not set
+CONFIG_PM_CLK=y
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_R8169 is not set
+# CONFIG_RC_CORE is not set
+CONFIG_REGULATOR=y
+# CONFIG_REGULATOR_AD5398 is not set
+# CONFIG_REGULATOR_BQ24022 is not set
+# CONFIG_REGULATOR_DEBUG is not set
+# CONFIG_REGULATOR_DUMMY is not set
+# CONFIG_REGULATOR_FAN53555 is not set
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+# CONFIG_REGULATOR_GPIO is not set
+# CONFIG_REGULATOR_ISL6271A is not set
+# CONFIG_REGULATOR_LP3971 is not set
+# CONFIG_REGULATOR_LP3972 is not set
+# CONFIG_REGULATOR_MAX1586 is not set
+# CONFIG_REGULATOR_MAX8649 is not set
+# CONFIG_REGULATOR_MAX8660 is not set
+# CONFIG_REGULATOR_MAX8952 is not set
+# CONFIG_REGULATOR_MAX8973 is not set
+# CONFIG_REGULATOR_TPS6238X0 is not set
+# CONFIG_REGULATOR_TPS65023 is not set
+# CONFIG_REGULATOR_TPS6507X is not set
+# CONFIG_REGULATOR_TPS6524X is not set
+# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set
+# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
+CONFIG_RFKILL_GPIO=m
+# CONFIG_RFKILL_REGULATOR is not set
+# CONFIG_RT2500USB is not set
+# CONFIG_RT2800USB is not set
+# CONFIG_RT73USB is not set
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_TEGRA is not set
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTL8192CE is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_3W_SAS is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_SCSI_BFA_FC is not set
+# CONFIG_SCSI_BNX2X_FCOE is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_CXGB4_ISCSI is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_HPSA is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_IPS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_MPT2SAS is not set
+# CONFIG_SCSI_MVSAS is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_PM8001 is not set
+# CONFIG_SCSI_PMCRAID is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_SCAN_ASYNC=y
+# CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SD8797 is not set
+# CONFIG_SDIO_UART is not set
+CONFIG_SENSORS_ISL29018=m
+# CONFIG_SENSORS_LIS3_SPI is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_EXTENDED is not set
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_SERIAL_TEGRA is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SMC911X is not set
+CONFIG_SMC91X=m
+CONFIG_SMP_ON_UP=y
+# CONFIG_SMSC911X is not set
+# CONFIG_SND_ARM is not set
+# CONFIG_SND_HDA_INTEL is not set
+CONFIG_SND_PCM=y
+CONFIG_SND_SOC=y
+# CONFIG_SND_SOC_ALL_CODECS is not set
+# CONFIG_SND_SOC_CACHE_LZO is not set
+CONFIG_SND_SOC_I2C_AND_SPI=y
+CONFIG_SND_SOC_SPDIF=y
+CONFIG_SND_SOC_TEGRA=y
+CONFIG_SND_SOC_TEGRA_WM8903=y
+# CONFIG_SND_SOC_TLV320AIC326X is not set
+CONFIG_SND_SOC_WM8903=y
+CONFIG_SND_TIMER=y
+CONFIG_SOC_CAMERA=m
+# CONFIG_SOC_CAMERA_IMX074 is not set
+# CONFIG_SOC_CAMERA_MT9M001 is not set
+# CONFIG_SOC_CAMERA_MT9M111 is not set
+# CONFIG_SOC_CAMERA_MT9T031 is not set
+# CONFIG_SOC_CAMERA_MT9T112 is not set
+# CONFIG_SOC_CAMERA_MT9V022 is not set
+CONFIG_SOC_CAMERA_OV2640=m
+# CONFIG_SOC_CAMERA_OV5642 is not set
+# CONFIG_SOC_CAMERA_OV6650 is not set
+# CONFIG_SOC_CAMERA_OV772X is not set
+# CONFIG_SOC_CAMERA_OV9640 is not set
+CONFIG_SOC_CAMERA_OV9740=m
+# CONFIG_SOC_CAMERA_PLATFORM is not set
+# CONFIG_SOC_CAMERA_RJ54N1 is not set
+# CONFIG_SOC_CAMERA_TW9910 is not set
+# CONFIG_SPARSE_IRQ is not set
+# CONFIG_SPI_SLAVE_TEGRA is not set
+# CONFIG_SPI_TEGRA is not set
+CONFIG_SQUASHFS=y
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+CONFIG_SQUASHFS_LZO=y
+# CONFIG_SQUASHFS_XATTR is not set
+# CONFIG_SQUASHFS_XZ is not set
+CONFIG_SQUASHFS_ZLIB=y
+# CONFIG_SSB is not set
+CONFIG_SWP_EMULATE=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+# CONFIG_TCG_TIS is not set
+# CONFIG_TEGRA_AVP is not set
+# CONFIG_TEGRA_BB_SUPPORT is not set
+# CONFIG_TEGRA_BB_XMM_POWER is not set
+# CONFIG_TEGRA_BB_XMM_POWER2 is not set
+# CONFIG_TEGRA_BPC_MGMT is not set
+CONFIG_TEGRA_CAMERA=y
+CONFIG_TEGRA_CLOCK_DEBUG_WRITE=y
+CONFIG_TEGRA_CORE_DVFS=y
+CONFIG_TEGRA_CPU_DVFS=y
+CONFIG_TEGRA_DC=y
+CONFIG_TEGRA_DC_EXTENSIONS=y
+# CONFIG_TEGRA_DEBUG_UARTC is not set
+# CONFIG_TEGRA_DEBUG_UARTD is not set
+# CONFIG_TEGRA_DEBUG_UARTE is not set
+# CONFIG_TEGRA_DEBUG_UART_NONE is not set
+# CONFIG_TEGRA_DSI is not set
+CONFIG_TEGRA_DTV=y
+CONFIG_TEGRA_EMC_SCALING_ENABLE=y
+# CONFIG_TEGRA_FIQ_DEBUGGER is not set
+# CONFIG_TEGRA_FPGA_PLATFORM is not set
+CONFIG_TEGRA_GRHOST=y
+# CONFIG_TEGRA_HDMI_74MHZ_LIMIT is not set
+# CONFIG_TEGRA_IOMMU_SMMU is not set
+CONFIG_TEGRA_IOVMM=y
+# CONFIG_TEGRA_MC_PROFILE is not set
+# CONFIG_TEGRA_MEDIASERVER is not set
+CONFIG_TEGRA_NVAVP=y
+# CONFIG_TEGRA_NVHDCP is not set
+CONFIG_TEGRA_NVMAP=y
+CONFIG_TEGRA_PWM=y
+CONFIG_TEGRA_RPC=y
+CONFIG_TEGRA_SILICON_PLATFORM=y
+# CONFIG_TEGRA_SIMULATION_PLATFORM is not set
+CONFIG_TEGRA_SYSTEM_DMA=y
+CONFIG_TEGRA_THERMAL_THROTTLE=y
+# CONFIG_TEGRA_USB_MODEM_POWER is not set
+# CONFIG_TEGRA_WDT_RECOVERY is not set
+# CONFIG_THUMB2_KERNEL is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_TORCH_SSL3250A is not set
+# CONFIG_TORCH_TPS61050 is not set
+CONFIG_TOUCHSCREEN_ATMEL_MXT=m
+# CONFIG_TOUCHSCREEN_W90X900 is not set
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+CONFIG_USB_EHCI_TEGRA=y
+# CONFIG_USB_NET_DM9601 is not set
+# CONFIG_USB_NET_NET1080 is not set
+# CONFIG_USB_OHCI_HCD is not set
+CONFIG_USB_OTG_UTILS=y
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_STORAGE_REALTEK is not set
+# CONFIG_USB_TEGRA_OTG is not set
+# CONFIG_USB_UHCI_HCD is not set
+CONFIG_USB_ULPI=y
+CONFIG_USB_ULPI_VIEWPORT=y
+CONFIG_USE_OF=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_VGA_ARB=y
+CONFIG_VGA_ARB_MAX_GPUS=16
+CONFIG_VIDEOBUF2_CORE=m
+CONFIG_VIDEOBUF_GEN=m
+# CONFIG_VIDEO_AD5820 is not set
+# CONFIG_VIDEO_AR0832 is not set
+# CONFIG_VIDEO_OV14810 is not set
+# CONFIG_VIDEO_OV2710 is not set
+# CONFIG_VIDEO_OV5640 is not set
+# CONFIG_VIDEO_OV5650 is not set
+# CONFIG_VIDEO_OV9726 is not set
+# CONFIG_VIDEO_SH532U is not set
+# CONFIG_VIDEO_SH_MOBILE_CEU is not set
+# CONFIG_VIDEO_SH_MOBILE_CSI2 is not set
+# CONFIG_VIDEO_SOC380 is not set
+# CONFIG_VIRTIO_PCI is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_XFRM_USER=m
+# CONFIG_XIP_KERNEL is not set
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_ZBOOT_ROM_TEXT=0x0
+# CONFIG_ZD1211RW is not set
+CONFIG_ZONE_DMA_FLAG=0
diff --git a/chromeos/config/armel/config.flavour.chromeos-tegra3 b/chromeos/config/armel/config.flavour.chromeos-tegra3
new file mode 100644
index 000000000000..3d2488ffab63
--- /dev/null
+++ b/chromeos/config/armel/config.flavour.chromeos-tegra3
@@ -0,0 +1,125 @@
+#
+# Config options generated by splitconfig
+#
+# CONFIG_AFS_FS is not set
+# CONFIG_ANDROID_PARANOID_NETWORK is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+CONFIG_ARCH_TEGRA_3x_SOC=y
+CONFIG_ARCH_TEGRA_HAS_DUAL_3D=y
+CONFIG_ARCH_TEGRA_HAS_DUAL_CPU_CLUSTERS=y
+CONFIG_ARCH_TEGRA_HAS_SATA=y
+# CONFIG_ARM_ERRATA_716044 is not set
+CONFIG_ARM_ERRATA_743622=y
+CONFIG_ARM_ERRATA_751472=y
+CONFIG_ARM_ERRATA_752520=y
+CONFIG_ARM_ERRATA_754322=y
+CONFIG_BATTERY_BQ27X00_I2C=y
+CONFIG_BATTERY_BQ27X00_PLATFORM=y
+CONFIG_BATTERY_BQ27x00=y
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+CONFIG_CRYPTO_CTS=y
+# CONFIG_CRYPTO_DEV_TEGRA_SE is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_DNOTIFY=y
+CONFIG_DNS_RESOLVER=y
+CONFIG_EXPORTFS=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+CONFIG_GIC_SET_MULTIPLE_CPUS=y
+CONFIG_IPV6=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_LZO_COMPRESS=y
+# CONFIG_MACH_ARUBA is not set
+CONFIG_MACH_CARDHU=y
+CONFIG_MACH_HAS_SND_SOC_TEGRA_MAX98095=y
+CONFIG_MACH_HAS_SND_SOC_TEGRA_TLV320AIC326X=y
+# CONFIG_MACH_KAI is not set
+# CONFIG_MACH_P1852 is not set
+# CONFIG_MACH_TEGRA_ENTERPRISE is not set
+# CONFIG_MFD_TPS6586X is not set
+CONFIG_MFD_TPS6591X=y
+# CONFIG_NCP_FS is not set
+CONFIG_NEON=y
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+CONFIG_NFSD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_USE_KERNEL_DNS=y
+# CONFIG_NFS_USE_LEGACY_DNS is not set
+# CONFIG_NFS_USE_NEW_IDMAPPER is not set
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
+CONFIG_NR_CPUS=4
+CONFIG_NVMAP_CONVERT_CARVEOUT_TO_IOVMM=y
+CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_PCI_MSI=y
+CONFIG_REGMAP=y
+CONFIG_REGMAP_I2C=y
+CONFIG_REGULATOR_TPS62360=y
+CONFIG_REGULATOR_TPS6591X=y
+CONFIG_REPORT_PRESENT_CPUS=y
+CONFIG_ROOT_NFS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+CONFIG_RTC_DRV_TPS6591x=y
+CONFIG_SENSORS_ISL29028=m
+CONFIG_SENSORS_NCT1008=y
+# CONFIG_SENSORS_TEGRA_TSENSOR is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+CONFIG_SND_SOC_MAX98095=y
+CONFIG_SND_SOC_TEGRA30_AHUB=y
+CONFIG_SND_SOC_TEGRA30_DAM=y
+CONFIG_SND_SOC_TEGRA30_I2S=y
+CONFIG_SND_SOC_TEGRA30_SPDIF=y
+CONFIG_SND_SOC_TEGRA_MAX98095=y
+# CONFIG_SND_SOC_TEGRA_TLV320AIC326X is not set
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_SWAP=y
+CONFIG_TASK_SIZE=0x7F000000
+CONFIG_TASK_SIZE_2G_LESS_16M=y
+# CONFIG_TASK_SIZE_2G_LESS_24M is not set
+CONFIG_TEGRA_AUTO_HOTPLUG=y
+CONFIG_TEGRA_AVP_KERNEL_ON_SMMU=y
+# CONFIG_TEGRA_CARDHU_DSI is not set
+CONFIG_TEGRA_CLUSTER_CONTROL=y
+CONFIG_TEGRA_DEBUG_UARTA=y
+# CONFIG_TEGRA_DEBUG_UARTB is not set
+CONFIG_TEGRA_DYNAMIC_PWRDET=y
+CONFIG_TEGRA_EDP_EXACT_FREQ=y
+CONFIG_TEGRA_EDP_LIMITS=y
+CONFIG_TEGRA_EMC_TO_DDR_CLOCK=1
+CONFIG_TEGRA_IOVMM_SMMU=y
+# CONFIG_TEGRA_IOVMM_SMMU_SYSFS is not set
+CONFIG_TEGRA_LP2_ARM_TWD=y
+# CONFIG_TEGRA_MC_EARLY_ACK is not set
+CONFIG_TEGRA_PCI=y
+CONFIG_TEGRA_PLLM_RESTRICTED=y
+CONFIG_TEGRA_PREINIT_CLOCKS=y
+CONFIG_TEGRA_PREPOWER_WIFI=y
+CONFIG_TEGRA_SLOW_CSITE=y
+CONFIG_TEGRA_THERMAL_SYSFS=y
+CONFIG_USB_HOTPLUG=y
+CONFIG_USB_NET_AX8817X=y
+CONFIG_USB_NET_CDCETHER=y
+CONFIG_USB_NET_CDC_NCM=y
+CONFIG_USB_NET_MCS7830=y
+CONFIG_USB_NET_RNDIS_HOST=m
+CONFIG_USB_NET_SMSC95XX=y
+CONFIG_USB_USBNET=y
+CONFIG_VMSPLIT_2G=y
+# CONFIG_VMSPLIT_3G is not set
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
diff --git a/chromeos/config/armel/config.flavour.chromiumos-arm b/chromeos/config/armel/config.flavour.chromiumos-arm
new file mode 100644
index 000000000000..3c5ee02c17c1
--- /dev/null
+++ b/chromeos/config/armel/config.flavour.chromiumos-arm
@@ -0,0 +1,86 @@
+#
+# Config options generated by splitconfig
+#
+CONFIG_ANDROID_PARANOID_NETWORK=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+CONFIG_ARCH_TEGRA_2x_SOC=y
+# CONFIG_ARCH_TEGRA_3x_SOC is not set
+CONFIG_ARM_ERRATA_716044=y
+# CONFIG_ARM_ERRATA_743622 is not set
+# CONFIG_ARM_ERRATA_751472 is not set
+# CONFIG_ARM_ERRATA_752520 is not set
+# CONFIG_ARM_ERRATA_754322 is not set
+# CONFIG_BATTERY_BQ27x00 is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_DNS_RESOLVER is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x16=y
+CONFIG_FONT_8x8=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_GIC_SET_MULTIPLE_CPUS is not set
+CONFIG_IPV6=m
+# CONFIG_IP_PNP is not set
+CONFIG_MACH_HARMONY=y
+CONFIG_MACH_KAEN=y
+# CONFIG_MACH_P852 is not set
+# CONFIG_MACH_PAZ00 is not set
+CONFIG_MACH_SEABOARD=y
+# CONFIG_MACH_TRIMSLICE is not set
+# CONFIG_MACH_VENTANA is not set
+CONFIG_MACH_WARIO=y
+# CONFIG_MACH_WHISTLER is not set
+CONFIG_MFD_TPS6586X=y
+# CONFIG_MFD_TPS6591X is not set
+# CONFIG_NEON is not set
+# CONFIG_NETWORK_FILESYSTEMS is not set
+CONFIG_NR_CPUS=2
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_REGULATOR_TPS62360 is not set
+CONFIG_REGULATOR_TPS6586X=y
+# CONFIG_REPORT_PRESENT_CPUS is not set
+CONFIG_RTC_DRV_TPS6586X=y
+# CONFIG_SENSORS_ISL29028 is not set
+# CONFIG_SENSORS_NCT1008 is not set
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+CONFIG_SND_SOC_TEGRA20_DAS=y
+CONFIG_SND_SOC_TEGRA20_I2S=y
+CONFIG_SND_SOC_TEGRA20_SPDIF=y
+# CONFIG_SWAP is not set
+CONFIG_TASK_SIZE=0xBF000000
+CONFIG_TASK_SIZE_3G_LESS_16M=y
+# CONFIG_TASK_SIZE_3G_LESS_24M is not set
+CONFIG_TEGRA_AVP_KERNEL_ON_MMU=y
+# CONFIG_TEGRA_DEBUG_UARTA is not set
+CONFIG_TEGRA_DEBUG_UARTB=y
+# CONFIG_TEGRA_DYNAMIC_PWRDET is not set
+# CONFIG_TEGRA_EDP_LIMITS is not set
+CONFIG_TEGRA_EMC_TO_DDR_CLOCK=2
+# CONFIG_TEGRA_IOMMU_GART is not set
+CONFIG_TEGRA_IOVMM_GART=y
+# CONFIG_TEGRA_PCI is not set
+# CONFIG_TEGRA_PREINIT_CLOCKS is not set
+# CONFIG_TEGRA_PREPOWER_WIFI is not set
+# CONFIG_TEGRA_SLOW_CSITE is not set
+# CONFIG_TEGRA_STAT_MON is not set
+# CONFIG_TEGRA_THERMAL_SYSFS is not set
+# CONFIG_USB_HOTPLUG is not set
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+CONFIG_USB_NET_CDC_NCM=m
+CONFIG_USB_NET_MCS7830=m
+CONFIG_USB_NET_RNDIS_HOST=m
+CONFIG_USB_NET_SMSC95XX=m
+CONFIG_USB_USBNET=m
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VMSPLIT_2G is not set
+CONFIG_VMSPLIT_3G=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
diff --git a/chromeos/config/config.common.chromeos b/chromeos/config/config.common.chromeos
new file mode 100644
index 000000000000..eaea95f28fe6
--- /dev/null
+++ b/chromeos/config/config.common.chromeos
@@ -0,0 +1,2039 @@
+#
+# Config options generated by splitconfig
+#
+# CONFIG_ABX500_CORE is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_ACENIC is not set
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_AD2S120X is not set
+# CONFIG_AD2S1210 is not set
+# CONFIG_AD2S90 is not set
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_AD5446 is not set
+# CONFIG_AD5504 is not set
+# CONFIG_AD5624R_SPI is not set
+# CONFIG_AD5686 is not set
+# CONFIG_AD5791 is not set
+# CONFIG_AD5930 is not set
+# CONFIG_AD7150 is not set
+# CONFIG_AD7152 is not set
+# CONFIG_AD7291 is not set
+# CONFIG_AD7298 is not set
+# CONFIG_AD7314 is not set
+# CONFIG_AD7476 is not set
+# CONFIG_AD7606 is not set
+# CONFIG_AD7745 is not set
+# CONFIG_AD7780 is not set
+# CONFIG_AD7793 is not set
+# CONFIG_AD7816 is not set
+# CONFIG_AD7887 is not set
+# CONFIG_AD799X is not set
+# CONFIG_AD9832 is not set
+# CONFIG_AD9834 is not set
+# CONFIG_AD9850 is not set
+# CONFIG_AD9852 is not set
+# CONFIG_AD9910 is not set
+# CONFIG_AD9951 is not set
+# CONFIG_ADE7753 is not set
+# CONFIG_ADE7754 is not set
+# CONFIG_ADE7758 is not set
+# CONFIG_ADE7759 is not set
+# CONFIG_ADE7854 is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_ADIS16060 is not set
+# CONFIG_ADIS16080 is not set
+# CONFIG_ADIS16130 is not set
+# CONFIG_ADIS16201 is not set
+# CONFIG_ADIS16203 is not set
+# CONFIG_ADIS16204 is not set
+# CONFIG_ADIS16209 is not set
+# CONFIG_ADIS16220 is not set
+# CONFIG_ADIS16240 is not set
+# CONFIG_ADIS16260 is not set
+# CONFIG_ADIS16400 is not set
+# CONFIG_ADM8211 is not set
+# CONFIG_ADT7310 is not set
+# CONFIG_ADT7316 is not set
+# CONFIG_ADT7410 is not set
+# CONFIG_ADT75 is not set
+# CONFIG_ADXRS450 is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_AIO=y
+# CONFIG_ALTERA_STAPL is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ANDROID is not set
+CONFIG_ANON_INODES=y
+# CONFIG_APANIC is not set
+# CONFIG_APDS9802ALS is not set
+# CONFIG_APPLICOM is not set
+CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_ARCNET is not set
+# CONFIG_ARPD is not set
+# CONFIG_ASHMEM is not set
+# CONFIG_ASUS_OLED is not set
+# CONFIG_AT76C50X_USB is not set
+# CONFIG_ATALK is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_ATH9K_HTC is not set
+CONFIG_ATH_COMMON=m
+CONFIG_ATH_DEBUG=y
+# CONFIG_ATM is not set
+# CONFIG_ATMEL is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_AUDIT is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_AUXDISPLAY is not set
+CONFIG_AVERAGE=y
+# CONFIG_B43 is not set
+# CONFIG_B43LEGACY is not set
+# CONFIG_BACKLIGHT_ADP8860 is not set
+# CONFIG_BACKLIGHT_ADP8870 is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_GENERIC=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_BACKTRACE_SELF_TEST is not set
+CONFIG_BASE_FULL=y
+CONFIG_BASE_SMALL=0
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_BATTERY_DS2780 is not set
+# CONFIG_BATTERY_DS2782 is not set
+# CONFIG_BATTERY_MAX17040 is not set
+# CONFIG_BATTERY_MAX17042 is not set
+# CONFIG_BATTERY_MAX17048 is not set
+# CONFIG_BCM4329_RFKILL is not set
+# CONFIG_BCMA is not set
+CONFIG_BCMA_POSSIBLE=y
+# CONFIG_BCM_WIMAX is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+CONFIG_BINARY_PRINTF=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_BITREVERSE=y
+# CONFIG_BLK_CGROUP is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_CPQ_DA is not set
+CONFIG_BLK_DEV=y
+CONFIG_BLK_DEV_BSG=y
+# CONFIG_BLK_DEV_BSGLIB is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+CONFIG_BLK_DEV_DM=y
+# CONFIG_BLK_DEV_DRBD is not set
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_BLK_DEV_INTEGRITY is not set
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=8
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_RBD is not set
+CONFIG_BLK_DEV_SD=y
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLOCK=y
+# CONFIG_BMP085 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_BONDING is not set
+# CONFIG_BOOTPARAM_HARDLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_HARDLOCKUP_PANIC_VALUE=0
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=1
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=1
+# CONFIG_BOOT_PRINTK_DELAY is not set
+CONFIG_BOUNCE=y
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_BRIDGE is not set
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_BT=m
+# CONFIG_BTRFS_FS is not set
+# CONFIG_BT_BLUESLEEP is not set
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIBTUSB=m
+CONFIG_BT_HCIVHCI=m
+# CONFIG_BT_L2CAP is not set
+# CONFIG_BT_MRVL is not set
+# CONFIG_BT_SCO is not set
+# CONFIG_BT_TIBLUESLEEP is not set
+CONFIG_BUG=y
+# CONFIG_C2PORT is not set
+# CONFIG_CAIF is not set
+# CONFIG_CAN is not set
+CONFIG_CAN_PM_TRACE=y
+# CONFIG_CARL9170 is not set
+# CONFIG_CASSINI is not set
+# CONFIG_CB710_CORE is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_CC_STACKPROTECTOR=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_CEPH_LIB is not set
+CONFIG_CFG80211=m
+# CONFIG_CFG80211_ALLOW_RECONNECT is not set
+CONFIG_CFG80211_DEBUGFS=y
+CONFIG_CFG80211_DEFAULT_PS=y
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+# CONFIG_CFG80211_INTERNAL_REGDB is not set
+# CONFIG_CFG80211_REG_DEBUG is not set
+CONFIG_CFG80211_WEXT=y
+CONFIG_CGROUPS=y
+# CONFIG_CGROUP_CPUACCT is not set
+# CONFIG_CGROUP_DEBUG is not set
+# CONFIG_CGROUP_DEVICE is not set
+# CONFIG_CGROUP_FREEZER is not set
+# CONFIG_CGROUP_PERF is not set
+CONFIG_CGROUP_SCHED=y
+# CONFIG_CHARGER_MAX8903 is not set
+# CONFIG_CHARGER_SMB349 is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_CHR_DEV_SCH is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_CLEANCACHE is not set
+# CONFIG_CNIC is not set
+# CONFIG_COMPACTION is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONNECTOR=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
+# CONFIG_CORDIC is not set
+# CONFIG_CPUSETS is not set
+CONFIG_CPU_FREQ=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_GOV_INTERACTIVE is not set
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_STAT=y
+# CONFIG_CPU_FREQ_STAT_DETAILS is not set
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+# CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set
+CONFIG_CPU_RMAP=y
+# CONFIG_CRAMFS is not set
+CONFIG_CRC16=y
+CONFIG_CRC32=y
+CONFIG_CRC7=m
+# CONFIG_CRC8 is not set
+CONFIG_CRC_CCITT=y
+CONFIG_CRC_ITU_T=m
+CONFIG_CRC_T10DIF=m
+CONFIG_CROSS_COMPILE=""
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_AUTHENC=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CCM is not set
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_CTR is not set
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+CONFIG_CRYPTO_ECB=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_GHASH is not set
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_LZO is not set
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_PCBC is not set
+CONFIG_CRYPTO_PCOMP2=y
+# CONFIG_CRYPTO_PCRYPT is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_RNG2=y
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SEQIV is not set
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TEST is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_USER_API_HASH is not set
+# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
+# CONFIG_CRYPTO_VMAC is not set
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYSTALHD is not set
+# CONFIG_CUSE is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_DCB is not set
+# CONFIG_DEBUG_ATOMIC_SLEEP is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_CREDENTIALS is not set
+CONFIG_DEBUG_DEVRES=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_GPIO=y
+# CONFIG_DEBUG_INFO is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_DEBUG_PERF_USE_VMALLOC is not set
+# CONFIG_DEBUG_PER_CPU_MAPS is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DEBUG_SPINLOCK=y
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DECNET is not set
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DEFAULT_CFQ=y
+CONFIG_DEFAULT_CUBIC=y
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_HOSTNAME="(none)"
+CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_DEFAULT_MESSAGE_LOGLEVEL=5
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+# CONFIG_DEFAULT_NOOP is not set
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_DEVKMEM is not set
+CONFIG_DEVMEM=y
+CONFIG_DEVPORT=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_DL2K is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_DMA_SHARED_BUFFER is not set
+# CONFIG_DM_CRYPT is not set
+# CONFIG_DM_DEBUG is not set
+# CONFIG_DM_DELAY is not set
+# CONFIG_DM_FLAKEY is not set
+# CONFIG_DM_MIRROR is not set
+# CONFIG_DM_MULTIPATH is not set
+# CONFIG_DM_RAID is not set
+# CONFIG_DM_SNAPSHOT is not set
+# CONFIG_DM_UEVENT is not set
+# CONFIG_DM_ZERO is not set
+# CONFIG_DNET is not set
+# CONFIG_DS1682 is not set
+# CONFIG_DUMMY is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_DVB_CORE is not set
+# CONFIG_DX_SEP is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+CONFIG_DYNAMIC_FTRACE=y
+CONFIG_EARLY_PRINTK=y
+# CONFIG_EASYCAP is not set
+# CONFIG_ECHO is not set
+# CONFIG_ECONET is not set
+CONFIG_ECRYPT_FS=y
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_EEPROM_93XX46 is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_EFS_FS is not set
+CONFIG_ELF_CORE=y
+CONFIG_EMBEDDED=y
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_ENC28J60 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+CONFIG_EPOLL=y
+# CONFIG_EQUALIZER is not set
+# CONFIG_ET131X is not set
+# CONFIG_ETHOC is not set
+CONFIG_EVENTFD=y
+CONFIG_EVENT_POWER_TRACING_DEPRECATED=y
+CONFIG_EVENT_TRACING=y
+CONFIG_EXPERIMENTAL=y
+CONFIG_EXPERT=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT2_FS_XATTR=y
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_DEFAULTS_TO_ORDERED=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT4_DEBUG is not set
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_EXT4_FS_XATTR=y
+# CONFIG_EZX_PCAP is not set
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_FANOTIFY is not set
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_FAT_FS=m
+# CONFIG_FAULT_INJECTION is not set
+CONFIG_FB=y
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_FB_CARMINE is not set
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_METRONOME is not set
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_PM3 is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_S3 is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_SM7XX is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_TMIO is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_UDL is not set
+# CONFIG_FB_UVESA is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
+# CONFIG_FB_WMT_GE_ROPS is not set
+# CONFIG_FB_XGI is not set
+# CONFIG_FDDI is not set
+# CONFIG_FHANDLE is not set
+CONFIG_FILE_LOCKING=y
+# CONFIG_FIREWIRE is not set
+# CONFIG_FIREWIRE_NOSY is not set
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FIRMWARE_IN_KERNEL=y
+# CONFIG_FIXED_PHY is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_FREEZER=y
+# CONFIG_FSCACHE is not set
+CONFIG_FSNOTIFY=y
+CONFIG_FS_MBCACHE=y
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_FT1000 is not set
+CONFIG_FTRACE=y
+CONFIG_FTRACE_MCOUNT_RECORD=y
+# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_FUNCTION_PROFILER is not set
+CONFIG_FUNCTION_TRACER=y
+CONFIG_FUSE_FS=m
+# CONFIG_FUSION is not set
+CONFIG_FUTEX=y
+CONFIG_FW_LOADER=y
+# CONFIG_GAMEPORT is not set
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_GENERIC_ACL=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_TRACER=y
+# CONFIG_GFS2_FS is not set
+CONFIG_GPIOLIB=y
+# CONFIG_GPIO_74X164 is not set
+# CONFIG_GPIO_ADP5588 is not set
+# CONFIG_GPIO_BT8XX is not set
+# CONFIG_GPIO_GENERIC_PLATFORM is not set
+# CONFIG_GPIO_IT8761E is not set
+# CONFIG_GPIO_MAX7300 is not set
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_MC33880 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_GPIO_ML_IOH is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_RDC321X is not set
+# CONFIG_GPIO_SX150X is not set
+CONFIG_GPIO_SYSFS=y
+# CONFIG_GPIO_VX855 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_HAPPYMEAL is not set
+CONFIG_HAS_DMA=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_GENERIC_HARDIRQS=y
+CONFIG_HAVE_HW_BREAKPOINT=y
+CONFIG_HAVE_IDE=y
+CONFIG_HAVE_IRQ_WORK=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_SPARSE_IRQ=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_HERMES is not set
+CONFIG_HFSPLUS_FS=m
+# CONFIG_HFS_FS is not set
+CONFIG_HID=y
+CONFIG_HIDRAW=y
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_ACRUX is not set
+CONFIG_HID_APPLE=m
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EMS_FF is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_HOLTEK is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_KEYTOUCH is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_LCPOWER is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MONTEREY is not set
+CONFIG_HID_MULTITOUCH=m
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_ORTEK is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_PICOLCD is not set
+# CONFIG_HID_PRODIKEYS is not set
+# CONFIG_HID_QUANTA is not set
+# CONFIG_HID_ROCCAT is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_SONY is not set
+# CONFIG_HID_SPEEDLINK is not set
+# CONFIG_HID_SUNPLUS is not set
+CONFIG_HID_SUPPORT=y
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_TWINHAN is not set
+# CONFIG_HID_UCLOGIC is not set
+# CONFIG_HID_WALTOP is not set
+# CONFIG_HID_ZEROPLUS is not set
+# CONFIG_HID_ZYDACRON is not set
+CONFIG_HIGH_RES_TIMERS=y
+# CONFIG_HIPPI is not set
+# CONFIG_HMC6352 is not set
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_HOTPLUG=y
+CONFIG_HOTPLUG_CPU=y
+# CONFIG_HP100 is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_HP_ILO is not set
+# CONFIG_HTC_I2CPLD is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_HWMON_VID is not set
+CONFIG_HW_CONSOLE=y
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+CONFIG_I2C=y
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=m
+CONFIG_I2C_COMPAT=y
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DIOLAN_U2C is not set
+# CONFIG_I2C_EG20T is not set
+# CONFIG_I2C_GPIO is not set
+CONFIG_I2C_HELPER_AUTO=y
+# CONFIG_I2C_INTEL_MID is not set
+# CONFIG_I2C_ISCH is not set
+# CONFIG_I2C_MUX is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_PXA_PCI is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_SLAVE is not set
+CONFIG_I2C_STUB=m
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_XILINX is not set
+# CONFIG_I2O is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_IDE is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_IGB is not set
+CONFIG_IIO=m
+# CONFIG_IIO_RING_BUFFER is not set
+# CONFIG_IIO_TRIGGER is not set
+CONFIG_IKCONFIG=m
+CONFIG_IKCONFIG_PROC=y
+# CONFIG_IMA is not set
+CONFIG_INET=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+# CONFIG_INET6_XFRM_TUNNEL is not set
+CONFIG_INET_AH=m
+# CONFIG_INET_DIAG is not set
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_LRO=y
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_TUNNEL=m
+# CONFIG_INFINIBAND is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_INIT_ENV_ARG_LIMIT=32
+# CONFIG_INLINE_READ_LOCK is not set
+# CONFIG_INLINE_READ_LOCK_BH is not set
+# CONFIG_INLINE_READ_LOCK_IRQ is not set
+# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_READ_TRYLOCK is not set
+# CONFIG_INLINE_READ_UNLOCK is not set
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQ is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_SPIN_LOCK is not set
+# CONFIG_INLINE_SPIN_LOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_SPIN_TRYLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+# CONFIG_INLINE_SPIN_UNLOCK is not set
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_WRITE_LOCK is not set
+# CONFIG_INLINE_WRITE_LOCK_BH is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_WRITE_TRYLOCK is not set
+# CONFIG_INLINE_WRITE_UNLOCK is not set
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+CONFIG_INOTIFY_USER=y
+CONFIG_INPUT=y
+# CONFIG_INPUT_AD714X is not set
+# CONFIG_INPUT_ADXL34X is not set
+# CONFIG_INPUT_ALPS_GPIO_SCROLLWHEEL is not set
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_CAPELLA_CM3217 is not set
+# CONFIG_INPUT_CM109 is not set
+# CONFIG_INPUT_CMA3000 is not set
+# CONFIG_INPUT_EVBUG is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_GPIO is not set
+# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_JOYSTICK is not set
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_INPUT_KEYCHORD is not set
+# CONFIG_INPUT_KEYRESET is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_KXTJ9 is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_MMA8450 is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_MPU3050 is not set
+# CONFIG_INPUT_PCF8574 is not set
+CONFIG_INPUT_POLLDEV=y
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_INPUT_UINPUT is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INTEL_MID_PTI is not set
+CONFIG_INV_SENSORS=y
+CONFIG_INV_SENSORS_ACCELEROMETERS=y
+CONFIG_INV_SENSORS_COMPASS=y
+CONFIG_INV_SENSORS_PRESSURE=y
+CONFIG_IOMMU_SUPPORT=y
+# CONFIG_ION is not set
+CONFIG_IOSCHED_CFQ=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IP1000 is not set
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+# CONFIG_IP6_NF_TARGET_REJECT_SKERR is not set
+CONFIG_IPC_NS=y
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+CONFIG_IPV6_PRIVACY=y
+# CONFIG_IPV6_ROUTER_PREF is not set
+CONFIG_IPV6_SIT=m
+# CONFIG_IPV6_SIT_6RD is not set
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPW2100 is not set
+# CONFIG_IPW2200 is not set
+# CONFIG_IPX is not set
+CONFIG_IP_ADVANCED_ROUTER=y
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_FIB_TRIE_STATS is not set
+CONFIG_IP_MROUTE=y
+# CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_MULTIPLE_TABLES is not set
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_TARGET_LOG=y
+CONFIG_IP_NF_TARGET_REJECT=y
+# CONFIG_IP_NF_TARGET_REJECT_SKERR is not set
+CONFIG_IP_NF_TARGET_ULOG=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_IP_SET is not set
+# CONFIG_IP_VS is not set
+# CONFIG_IRDA is not set
+# CONFIG_IRQSOFF_TRACER is not set
+CONFIG_IRQ_WORK=y
+# CONFIG_ISDN is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_ISL29020 is not set
+CONFIG_ISO9660_FS=m
+CONFIG_JBD=y
+CONFIG_JBD2=y
+# CONFIG_JBD2_DEBUG is not set
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_JFS_FS is not set
+CONFIG_JOLIET=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_LZO is not set
+# CONFIG_KEXEC is not set
+# CONFIG_KEYBOARD_ADP5588 is not set
+# CONFIG_KEYBOARD_ADP5589 is not set
+CONFIG_KEYBOARD_ATKBD=y
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_KEYBOARD_GPIO_POLLED is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_LM8323 is not set
+# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_MAX7359 is not set
+# CONFIG_KEYBOARD_MCS is not set
+# CONFIG_KEYBOARD_MPR121 is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_QT1070 is not set
+# CONFIG_KEYBOARD_QT2160 is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_TCA6416 is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_KGDB is not set
+# CONFIG_KPROBES is not set
+# CONFIG_KS8851 is not set
+# CONFIG_KS8851_MLL is not set
+# CONFIG_KSM is not set
+# CONFIG_KXSD9 is not set
+# CONFIG_L2TP is not set
+# CONFIG_LAPB is not set
+# CONFIG_LCD_CLASS_DEVICE is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_LEDS_BD2802 is not set
+CONFIG_LEDS_CLASS=y
+# CONFIG_LEDS_DAC124S085 is not set
+# CONFIG_LEDS_GPIO is not set
+# CONFIG_LEDS_LM3530 is not set
+# CONFIG_LEDS_LP3944 is not set
+# CONFIG_LEDS_LP5521 is not set
+# CONFIG_LEDS_LP5523 is not set
+# CONFIG_LEDS_LT3593 is not set
+# CONFIG_LEDS_PCA9532 is not set
+# CONFIG_LEDS_PCA955X is not set
+CONFIG_LEDS_TRIGGERS=y
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
+# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
+# CONFIG_LEDS_TRIGGER_GPIO is not set
+# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
+# CONFIG_LEDS_TRIGGER_TIMER is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_LIB80211=m
+CONFIG_LIB80211_CRYPT_CCMP=m
+CONFIG_LIB80211_CRYPT_TKIP=m
+CONFIG_LIB80211_CRYPT_WEP=m
+# CONFIG_LIB80211_DEBUG is not set
+CONFIG_LIBCRC32C=m
+# CONFIG_LIBERTAS is not set
+CONFIG_LIBERTAS_THINFIRM=m
+# CONFIG_LIBERTAS_THINFIRM_DEBUG is not set
+# CONFIG_LINE6_USB is not set
+# CONFIG_LIS3L02DQ is not set
+# CONFIG_LKDTM is not set
+# CONFIG_LLC2 is not set
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_LOCKUP_DETECTOR=y
+# CONFIG_LOCK_STAT is not set
+# CONFIG_LOGFS is not set
+# CONFIG_LOGO is not set
+CONFIG_LOG_BUF_SHIFT=18
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_LXT_PHY is not set
+CONFIG_MAC80211=m
+CONFIG_MAC80211_DEBUGFS=y
+# CONFIG_MAC80211_DEBUG_MENU is not set
+CONFIG_MAC80211_HAS_RC=y
+CONFIG_MAC80211_HWSIM=m
+CONFIG_MAC80211_LEDS=y
+# CONFIG_MAC80211_MESH is not set
+CONFIG_MAC80211_RC_DEFAULT="minstrel_ht"
+CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y
+CONFIG_MAC80211_RC_MINSTREL=y
+CONFIG_MAC80211_RC_MINSTREL_HT=y
+# CONFIG_MAC80211_RC_PID is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_MAX1363 is not set
+# CONFIG_MAX517 is not set
+CONFIG_MD=y
+# CONFIG_MDIO_BITBANG is not set
+# CONFIG_MEDIA_ATTACH is not set
+# CONFIG_MEDIA_CONTROLLER is not set
+CONFIG_MEDIA_SUPPORT=m
+CONFIG_MEDIA_TUNER=m
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_MEDIA_TUNER_MC44S803=m
+CONFIG_MEDIA_TUNER_MT20XX=m
+CONFIG_MEDIA_TUNER_SIMPLE=m
+CONFIG_MEDIA_TUNER_TDA18271=m
+CONFIG_MEDIA_TUNER_TDA827X=m
+CONFIG_MEDIA_TUNER_TDA8290=m
+CONFIG_MEDIA_TUNER_TDA9887=m
+CONFIG_MEDIA_TUNER_TEA5761=m
+CONFIG_MEDIA_TUNER_TEA5767=m
+CONFIG_MEDIA_TUNER_XC2028=m
+CONFIG_MEDIA_TUNER_XC4000=m
+CONFIG_MEDIA_TUNER_XC5000=m
+# CONFIG_MEMSTICK is not set
+# CONFIG_MFD_88PM860X is not set
+# CONFIG_MFD_AAT2870_CORE is not set
+# CONFIG_MFD_JANZ_CMODIO is not set
+# CONFIG_MFD_MAX77663 is not set
+# CONFIG_MFD_MAX8907C is not set
+# CONFIG_MFD_MAX8925 is not set
+# CONFIG_MFD_MAX8997 is not set
+# CONFIG_MFD_MAX8998 is not set
+# CONFIG_MFD_MC13XXX is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_RC5T583 is not set
+# CONFIG_MFD_RDC321X is not set
+# CONFIG_MFD_RICOH583 is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_STMPE is not set
+CONFIG_MFD_SUPPORT=y
+# CONFIG_MFD_TC3589X is not set
+# CONFIG_MFD_TIMBERDALE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_TPS65090 is not set
+# CONFIG_MFD_TPS65910 is not set
+# CONFIG_MFD_TPS65912_I2C is not set
+# CONFIG_MFD_TPS65912_SPI is not set
+# CONFIG_MFD_TPS80031 is not set
+# CONFIG_MFD_VX855 is not set
+# CONFIG_MFD_WL1273_CORE is not set
+# CONFIG_MFD_WM831X_I2C is not set
+# CONFIG_MFD_WM831X_SPI is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8994 is not set
+# CONFIG_MICREL_PHY is not set
+CONFIG_MII=y
+# CONFIG_MINIX_FS is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+CONFIG_MISC_DEVICES=y
+CONFIG_MISC_FILESYSTEMS=y
+CONFIG_MMU=y
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_GPIO is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_SYNAPTICS_I2C is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MPU_SENSORS_AK8963 is not set
+# CONFIG_MPU_SENSORS_AK8972 is not set
+# CONFIG_MPU_SENSORS_AK8975 is not set
+# CONFIG_MPU_SENSORS_AMI306 is not set
+# CONFIG_MPU_SENSORS_AMI30X is not set
+# CONFIG_MPU_SENSORS_BMA085 is not set
+# CONFIG_MPU_SENSORS_HMC5883 is not set
+# CONFIG_MPU_SENSORS_HSCDTD002B is not set
+# CONFIG_MPU_SENSORS_HSCDTD004A is not set
+# CONFIG_MPU_SENSORS_LSM303DLX_M is not set
+# CONFIG_MPU_SENSORS_MMC314X is not set
+# CONFIG_MPU_SENSORS_MMC314XMS is not set
+# CONFIG_MPU_SENSORS_MPU3050 is not set
+# CONFIG_MPU_SENSORS_MPU6050A2 is not set
+# CONFIG_MPU_SENSORS_MPU6050B1 is not set
+# CONFIG_MPU_SENSORS_TIMERIRQ is not set
+# CONFIG_MPU_SENSORS_YAS530 is not set
+# CONFIG_MPU_USERSPACE_DEBUG is not set
+# CONFIG_MSDOS_FS is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_MTD is not set
+CONFIG_MUTEX_SPIN_ON_OWNER=y
+# CONFIG_MWIFIEX is not set
+# CONFIG_MWL8K is not set
+CONFIG_NAMESPACES=y
+# CONFIG_NATIONAL_PHY is not set
+CONFIG_NET=y
+# CONFIG_NETCONSOLE is not set
+CONFIG_NETDEVICES=y
+CONFIG_NETDEV_1000=y
+# CONFIG_NETDEV_10000 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_ADVANCED is not set
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_NETLINK=y
+CONFIG_NETFILTER_NETLINK_LOG=y
+CONFIG_NETFILTER_XTABLES=y
+CONFIG_NETFILTER_XT_MARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_TARGET_NFLOG=y
+CONFIG_NETFILTER_XT_TARGET_SECMARK=y
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+# CONFIG_NETLABEL is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+CONFIG_NETWORK_SECMARK=y
+# CONFIG_NET_9P is not set
+CONFIG_NET_ACTIVITY_STATS=y
+# CONFIG_NET_CLS_ACT is not set
+# CONFIG_NET_CLS_BASIC is not set
+# CONFIG_NET_CLS_CGROUP is not set
+# CONFIG_NET_CLS_FLOW is not set
+# CONFIG_NET_CLS_FW is not set
+# CONFIG_NET_CLS_ROUTE4 is not set
+# CONFIG_NET_CLS_RSVP is not set
+# CONFIG_NET_CLS_RSVP6 is not set
+# CONFIG_NET_CLS_TCINDEX is not set
+# CONFIG_NET_CLS_U32 is not set
+# CONFIG_NET_DROP_MONITOR is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_NET_EMATCH is not set
+CONFIG_NET_ETHERNET=y
+# CONFIG_NET_FC is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
+# CONFIG_NET_IPIP is not set
+CONFIG_NET_KEY=m
+# CONFIG_NET_KEY_MIGRATE is not set
+# CONFIG_NET_NS is not set
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+CONFIG_NET_SCHED=y
+# CONFIG_NET_SCH_CBQ is not set
+# CONFIG_NET_SCH_CHOKE is not set
+# CONFIG_NET_SCH_DRR is not set
+# CONFIG_NET_SCH_DSMARK is not set
+CONFIG_NET_SCH_FIFO=y
+# CONFIG_NET_SCH_GRED is not set
+# CONFIG_NET_SCH_HFSC is not set
+# CONFIG_NET_SCH_HTB is not set
+# CONFIG_NET_SCH_MQPRIO is not set
+# CONFIG_NET_SCH_MULTIQ is not set
+# CONFIG_NET_SCH_NETEM is not set
+# CONFIG_NET_SCH_PRIO is not set
+# CONFIG_NET_SCH_QFQ is not set
+# CONFIG_NET_SCH_RED is not set
+# CONFIG_NET_SCH_SFB is not set
+# CONFIG_NET_SCH_SFQ is not set
+# CONFIG_NET_SCH_TBF is not set
+# CONFIG_NET_SCH_TEQL is not set
+# CONFIG_NET_TULIP is not set
+# CONFIG_NET_VENDOR_3COM is not set
+CONFIG_NEW_LEDS=y
+# CONFIG_NFC is not set
+CONFIG_NF_CONNTRACK=y
+# CONFIG_NF_CONNTRACK_FTP is not set
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_NF_CONNTRACK_IPV6=m
+# CONFIG_NF_CONNTRACK_IRC is not set
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+# CONFIG_NF_CONNTRACK_SECMARK is not set
+# CONFIG_NF_CONNTRACK_SIP is not set
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NF_DEFRAG_IPV4=y
+CONFIG_NF_DEFRAG_IPV6=m
+# CONFIG_NF_NAT is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_NL80211_TESTMODE=y
+CONFIG_NLATTR=y
+CONFIG_NLS=y
+CONFIG_NLS_ASCII=m
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_CODEPAGE_437=m
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_ISO8859_1=m
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=m
+CONFIG_NOP_TRACER=y
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_NOZOMI is not set
+CONFIG_NO_HZ=y
+# CONFIG_NS83820 is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_N_GSM is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_OPROFILE is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_P54_COMMON is not set
+CONFIG_PACKET=y
+CONFIG_PANIC_TIMEOUT=0
+# CONFIG_PARPORT is not set
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_PCCARD is not set
+# CONFIG_PCH_GBE is not set
+# CONFIG_PCH_PHUB is not set
+CONFIG_PCI=y
+# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_IOV is not set
+CONFIG_PCI_QUIRKS=y
+# CONFIG_PCI_STUB is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_PERF_COUNTERS is not set
+CONFIG_PERF_EVENTS=y
+# CONFIG_PHANTOM is not set
+# CONFIG_PHONE is not set
+# CONFIG_PHONET is not set
+CONFIG_PHYLIB=y
+CONFIG_PID_NS=y
+CONFIG_PM=y
+# CONFIG_PMBUS is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_PM_ADVANCED_DEBUG is not set
+CONFIG_PM_DEBUG=y
+CONFIG_PM_RUNTIME=y
+CONFIG_PM_SLEEP=y
+CONFIG_PM_SLEEP_SMP=y
+# CONFIG_PM_TEST_SUSPEND is not set
+# CONFIG_POHMELFS is not set
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+CONFIG_PPP=m
+# CONFIG_PPPOE is not set
+# CONFIG_PPPOLAC is not set
+# CONFIG_PPPOPNS is not set
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_FILTER is not set
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPS is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_RCU is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_PRINTK=y
+CONFIG_PRINTK_TIME=y
+# CONFIG_PRISM2_USB is not set
+# CONFIG_PRISM54 is not set
+CONFIG_PROC_EVENTS=y
+CONFIG_PROC_FS=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_PROC_SYSCTL=y
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+CONFIG_PROFILING=y
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_PSTORE is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_QUOTACTL is not set
+# CONFIG_R3964 is not set
+# CONFIG_R8187SE is not set
+# CONFIG_R8712U is not set
+# CONFIG_RADIO_ADAPTERS is not set
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_RAMOOPS is not set
+# CONFIG_RAW_DRIVER is not set
+CONFIG_RCU_CPU_STALL_TIMEOUT=60
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_RCU_FAST_NO_HZ is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_TRACE is not set
+# CONFIG_RDS is not set
+# CONFIG_RD_BZIP2 is not set
+CONFIG_RD_GZIP=y
+# CONFIG_RD_LZMA is not set
+# CONFIG_RD_LZO is not set
+# CONFIG_RD_XZ is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_REISERFS_FS is not set
+CONFIG_RELAY=y
+# CONFIG_RESOURCE_COUNTERS is not set
+CONFIG_RFKILL=y
+# CONFIG_RFKILL_INPUT is not set
+CONFIG_RFKILL_LEDS=y
+CONFIG_RFKILL_PM=y
+CONFIG_RFS_ACCEL=y
+CONFIG_RING_BUFFER=y
+# CONFIG_RING_BUFFER_BENCHMARK is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_RPS=y
+# CONFIG_RT2400PCI is not set
+# CONFIG_RT2500PCI is not set
+# CONFIG_RT2800PCI is not set
+CONFIG_RT2X00=m
+# CONFIG_RT61PCI is not set
+CONFIG_RTC_CLASS=y
+# CONFIG_RTC_DEBUG is not set
+# CONFIG_RTC_DRV_BQ32K is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_DS3232 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+# CONFIG_RTC_DRV_EM3027 is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_ISL12022 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_M41T93 is not set
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_PCF2123 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_RV3029C2 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_TEST is not set
+# CONFIG_RTC_DRV_V3020 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+CONFIG_RTC_INTF_ALARM=y
+CONFIG_RTC_INTF_ALARM_DEV=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_LIB=y
+# CONFIG_RTL8180 is not set
+# CONFIG_RTL8187 is not set
+# CONFIG_RTL8192CU is not set
+# CONFIG_RTL8192DE is not set
+# CONFIG_RTL8192E is not set
+# CONFIG_RTL8192SE is not set
+# CONFIG_RTL8192U is not set
+# CONFIG_RTS_PSTOR is not set
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_RT_MUTEXES=y
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_SAMPLES is not set
+CONFIG_SCHEDSTATS=y
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHED_TRACER is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_DH is not set
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_LOGGING is not set
+CONFIG_SCSI_MOD=y
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+CONFIG_SCSI_PROC_FS=y
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+CONFIG_SCSI_SPI_ATTRS=y
+# CONFIG_SCSI_SRP_ATTRS is not set
+# CONFIG_SCSI_TGT is not set
+CONFIG_SCSI_WAIT_SCAN=m
+CONFIG_SECCOMP=y
+CONFIG_SECURITY=y
+CONFIG_SECURITYFS=y
+# CONFIG_SECURITY_APPARMOR is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+CONFIG_SECURITY_NETWORK=y
+# CONFIG_SECURITY_NETWORK_XFRM is not set
+# CONFIG_SECURITY_PATH is not set
+# CONFIG_SECURITY_TOMOYO is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADCXX is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADS1015 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_ADS7871 is not set
+# CONFIG_SENSORS_ADT7411 is not set
+# CONFIG_SENSORS_ADT7461 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7475 is not set
+# CONFIG_SENSORS_AK8975 is not set
+# CONFIG_SENSORS_AMC6821 is not set
+# CONFIG_SENSORS_APDS990X is not set
+# CONFIG_SENSORS_ASC7621 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_BH1770 is not set
+# CONFIG_SENSORS_BH1780 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_DS620 is not set
+# CONFIG_SENSORS_EMC1403 is not set
+# CONFIG_SENSORS_EMC2103 is not set
+# CONFIG_SENSORS_EMC6W201 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_GPIO_FAN is not set
+# CONFIG_SENSORS_HMC5843 is not set
+# CONFIG_SENSORS_I5K_AMB is not set
+# CONFIG_SENSORS_INA219 is not set
+# CONFIG_SENSORS_INA230 is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_JC42 is not set
+# CONFIG_SENSORS_LINEAGE is not set
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_LM73 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LM95241 is not set
+# CONFIG_SENSORS_LM95245 is not set
+# CONFIG_SENSORS_LTC4151 is not set
+# CONFIG_SENSORS_LTC4215 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LTC4261 is not set
+# CONFIG_SENSORS_LTR558 is not set
+# CONFIG_SENSORS_MAX1111 is not set
+# CONFIG_SENSORS_MAX16065 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX1668 is not set
+# CONFIG_SENSORS_MAX6639 is not set
+# CONFIG_SENSORS_MAX6642 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_NTC_THERMISTOR is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_SCH5627 is not set
+# CONFIG_SENSORS_SCH5636 is not set
+# CONFIG_SENSORS_SCH56XX_COMMON is not set
+# CONFIG_SENSORS_SHT15 is not set
+# CONFIG_SENSORS_SHT21 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMM665 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP102 is not set
+# CONFIG_SENSORS_TMP401 is not set
+# CONFIG_SENSORS_TMP421 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+CONFIG_SENSORS_TSL2563=m
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83795 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_IFX6X60 is not set
+# CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_MAX3100 is not set
+# CONFIG_SERIAL_MAX3107 is not set
+# CONFIG_SERIAL_MFD_HSU is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_SERIAL_PCH_UART is not set
+# CONFIG_SERIAL_TIMBERDALE is not set
+# CONFIG_SERIAL_XILINX_PS_UART is not set
+CONFIG_SERIO=y
+# CONFIG_SERIO_ALTERA_PS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_PS2MULT is not set
+CONFIG_SERIO_RAW=y
+CONFIG_SERIO_SERPORT=m
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_SGI_PARTITION is not set
+CONFIG_SHMEM=y
+CONFIG_SIGNALFD=y
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+CONFIG_SLABINFO=y
+CONFIG_SLHC=m
+# CONFIG_SLIP is not set
+# CONFIG_SLOB is not set
+CONFIG_SMP=y
+# CONFIG_SMSC_PHY is not set
+CONFIG_SND=y
+# CONFIG_SND_AD1889 is not set
+# CONFIG_SND_ALI5451 is not set
+# CONFIG_SND_ALOOP is not set
+# CONFIG_SND_ALS300 is not set
+# CONFIG_SND_ATIIXP is not set
+# CONFIG_SND_ATIIXP_MODEM is not set
+# CONFIG_SND_AU8810 is not set
+# CONFIG_SND_AU8820 is not set
+# CONFIG_SND_AU8830 is not set
+# CONFIG_SND_AW2 is not set
+# CONFIG_SND_AZT3328 is not set
+# CONFIG_SND_BT87X is not set
+# CONFIG_SND_CA0106 is not set
+# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_CS4281 is not set
+# CONFIG_SND_CS46XX is not set
+# CONFIG_SND_CS5535AUDIO is not set
+# CONFIG_SND_CTXFI is not set
+# CONFIG_SND_DARLA20 is not set
+# CONFIG_SND_DARLA24 is not set
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+CONFIG_SND_DYNAMIC_MINORS=y
+# CONFIG_SND_ECHO3G is not set
+# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_EMU10K1X is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
+# CONFIG_SND_ENS1370 is not set
+# CONFIG_SND_ENS1371 is not set
+# CONFIG_SND_ES1938 is not set
+# CONFIG_SND_ES1968 is not set
+# CONFIG_SND_FM801 is not set
+# CONFIG_SND_GINA20 is not set
+# CONFIG_SND_GINA24 is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_HDSPM is not set
+CONFIG_SND_HRTIMER=m
+CONFIG_SND_HWDEP=m
+# CONFIG_SND_ICE1712 is not set
+# CONFIG_SND_ICE1724 is not set
+# CONFIG_SND_INDIGO is not set
+# CONFIG_SND_INDIGODJ is not set
+# CONFIG_SND_INDIGODJX is not set
+# CONFIG_SND_INDIGOIO is not set
+# CONFIG_SND_INDIGOIOX is not set
+# CONFIG_SND_INTEL8X0 is not set
+# CONFIG_SND_INTEL8X0M is not set
+CONFIG_SND_JACK=y
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_LAYLA20 is not set
+# CONFIG_SND_LAYLA24 is not set
+# CONFIG_SND_LOLA is not set
+# CONFIG_SND_LX6464ES is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_MIA is not set
+# CONFIG_SND_MIXART is not set
+CONFIG_SND_MIXER_OSS=m
+# CONFIG_SND_MONA is not set
+# CONFIG_SND_MPU401 is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+CONFIG_SND_OSSEMUL=y
+# CONFIG_SND_OXYGEN is not set
+CONFIG_SND_PCI=y
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_PCXHR is not set
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_RAWMIDI_SEQ=m
+# CONFIG_SND_RIPTIDE is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_SEQ_HRTIMER_DEFAULT=y
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_SPI is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+# CONFIG_SND_TRIDENT is not set
+CONFIG_SND_USB=y
+# CONFIG_SND_USB_6FIRE is not set
+CONFIG_SND_USB_AUDIO=m
+# CONFIG_SND_USB_CAIAQ is not set
+# CONFIG_SND_USB_UA101 is not set
+# CONFIG_SND_VERBOSE_PRINTK is not set
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VIA82XX_MODEM is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_VIRTUOSO is not set
+# CONFIG_SND_VX222 is not set
+# CONFIG_SND_YMFPCI is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_SOLO6X10 is not set
+CONFIG_SOUND=y
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SOUND_OSS_CORE_PRECLAIM=y
+# CONFIG_SOUND_PRIME is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_SPEAKUP is not set
+CONFIG_SPI=y
+# CONFIG_SPI_ALTERA is not set
+CONFIG_SPI_BITBANG=m
+# CONFIG_SPI_DEBUG is not set
+# CONFIG_SPI_DESIGNWARE is not set
+# CONFIG_SPI_GPIO is not set
+CONFIG_SPI_MASTER=y
+# CONFIG_SPI_OC_TINY is not set
+# CONFIG_SPI_PXA2XX_PCI is not set
+CONFIG_SPI_SPIDEV=m
+# CONFIG_SPI_TLE62X0 is not set
+# CONFIG_SPI_TOPCLIFF_PCH is not set
+# CONFIG_SPI_XILINX is not set
+CONFIG_SPLIT_PTLOCK_CPUS=999999
+CONFIG_SSB_POSSIBLE=y
+CONFIG_STACKTRACE=y
+CONFIG_STACKTRACE_SUPPORT=y
+# CONFIG_STACK_TRACER is not set
+CONFIG_STAGING=y
+CONFIG_STANDALONE=y
+# CONFIG_STE10XP is not set
+# CONFIG_STMMAC_ETH is not set
+CONFIG_STOP_MACHINE=y
+# CONFIG_STRICT_DEVMEM is not set
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_STUB_POULSBO is not set
+# CONFIG_ST_GPS is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_SUN_PARTITION is not set
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+# CONFIG_SUSPEND_TIME is not set
+# CONFIG_SWITCH is not set
+CONFIG_SYN_COOKIES=y
+CONFIG_SYSCTL=y
+# CONFIG_SYSCTL_SYSCALL is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+CONFIG_SYSFS=y
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_TARGET_CORE is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_TCG_ATMEL is not set
+# CONFIG_TCG_NSC is not set
+CONFIG_TCG_TPM=y
+CONFIG_TCP_CONG_ADVANCED=y
+# CONFIG_TCP_CONG_BIC is not set
+CONFIG_TCP_CONG_CUBIC=y
+# CONFIG_TCP_CONG_HSTCP is not set
+# CONFIG_TCP_CONG_HTCP is not set
+# CONFIG_TCP_CONG_HYBLA is not set
+# CONFIG_TCP_CONG_ILLINOIS is not set
+# CONFIG_TCP_CONG_LP is not set
+# CONFIG_TCP_CONG_SCALABLE is not set
+# CONFIG_TCP_CONG_VEGAS is not set
+# CONFIG_TCP_CONG_VENO is not set
+# CONFIG_TCP_CONG_WESTWOOD is not set
+# CONFIG_TCP_CONG_YEAH is not set
+CONFIG_TCP_MD5SIG=y
+# CONFIG_TEGRA_CRYPTO_DEV is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_TEST_LIST_SORT is not set
+# CONFIG_TEST_POWER is not set
+CONFIG_THERMAL=y
+CONFIG_THERMAL_HWMON=y
+CONFIG_TICK_ONESHOT=y
+# CONFIG_TIFM_CORE is not set
+CONFIG_TIMERFD=y
+CONFIG_TIMER_STATS=y
+# CONFIG_TIPC is not set
+# CONFIG_TI_DAC7512 is not set
+# CONFIG_TI_ST is not set
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_TMPFS_XATTR=y
+# CONFIG_TOUCHSCREEN_AD7877 is not set
+# CONFIG_TOUCHSCREEN_AD7879 is not set
+# CONFIG_TOUCHSCREEN_ADS7846 is not set
+# CONFIG_TOUCHSCREEN_BU21013 is not set
+# CONFIG_TOUCHSCREEN_CLEARPAD_TM1217 is not set
+# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set
+# CONFIG_TOUCHSCREEN_DYNAPRO is not set
+# CONFIG_TOUCHSCREEN_EETI is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MAX11801 is not set
+# CONFIG_TOUCHSCREEN_MCS5000 is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_PANJIT_I2C is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_RM31080A is not set
+# CONFIG_TOUCHSCREEN_ST1232 is not set
+# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI is not set
+# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set
+# CONFIG_TOUCHSCREEN_SYN_RMI4_SPI is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_TPS6507X is not set
+# CONFIG_TOUCHSCREEN_TSC2005 is not set
+# CONFIG_TOUCHSCREEN_TSC2007 is not set
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+# CONFIG_TPS6105X is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TPS6507X is not set
+# CONFIG_TR is not set
+# CONFIG_TRACEDUMP is not set
+# CONFIG_TRACELEVEL is not set
+CONFIG_TRACEPOINTS=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_TRACE_SINK is not set
+CONFIG_TRACING=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_TRANZPORT is not set
+CONFIG_TREE_RCU=y
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_TRUSTED_FOUNDATIONS is not set
+# CONFIG_TRUSTED_KEYS is not set
+# CONFIG_TSL2583 is not set
+# CONFIG_TTY_PRINTK is not set
+CONFIG_TUN=m
+# CONFIG_TWL4030_CORE is not set
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+CONFIG_UEVENT_HELPER_PATH=""
+# CONFIG_UFS_FS is not set
+CONFIG_UID16=y
+# CONFIG_UID_STAT is not set
+# CONFIG_UIO is not set
+# CONFIG_ULTRIX_PARTITION is not set
+CONFIG_UNIX=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_USB=y
+# CONFIG_USBIP_CORE is not set
+CONFIG_USB_ACM=y
+# CONFIG_USB_ADUTUX is not set
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+# CONFIG_USB_APPLEDISPLAY is not set
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_DEBUG is not set
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_ONOFF_FEATURE is not set
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_ENESTORAGE is not set
+# CONFIG_USB_ET61X251 is not set
+# CONFIG_USB_EZUSB is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_GADGET is not set
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_USB_GSPCA is not set
+CONFIG_USB_HID=y
+CONFIG_USB_HIDDEV=y
+# CONFIG_USB_HSO is not set
+# CONFIG_USB_HWA_HCD is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_IPHETH is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_LEGOTOWER is not set
+CONFIG_USB_LIBUSUAL=y
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_NET_CDC_EEM is not set
+# CONFIG_USB_NET_CDC_SUBSET is not set
+# CONFIG_USB_NET_CX82310_ETH is not set
+# CONFIG_USB_NET_GL620A is not set
+# CONFIG_USB_NET_INT51X1 is not set
+# CONFIG_USB_NET_KALMIA is not set
+# CONFIG_USB_NET_PLUSB is not set
+# CONFIG_USB_NET_RAW_IP is not set
+CONFIG_USB_NET_RNDIS_WLAN=m
+# CONFIG_USB_NET_SMSC75XX is not set
+# CONFIG_USB_NET_ZAURUS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_PWC is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_S2255 is not set
+CONFIG_USB_SERIAL=y
+# CONFIG_USB_SERIAL_AIRCABLE is not set
+# CONFIG_USB_SERIAL_ARK3116 is not set
+# CONFIG_USB_SERIAL_BASEBAND is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_CH341 is not set
+# CONFIG_USB_SERIAL_CONSOLE is not set
+# CONFIG_USB_SERIAL_CP210X is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
+# CONFIG_USB_SERIAL_DEBUG is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+# CONFIG_USB_SERIAL_FTDI_SIO is not set
+# CONFIG_USB_SERIAL_FUNSOFT is not set
+# CONFIG_USB_SERIAL_GARMIN is not set
+CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_HP4X is not set
+# CONFIG_USB_SERIAL_IPAQ is not set
+# CONFIG_USB_SERIAL_IPW is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_IUU is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_MOS7720 is not set
+# CONFIG_USB_SERIAL_MOS7840 is not set
+# CONFIG_USB_SERIAL_MOTOROLA is not set
+# CONFIG_USB_SERIAL_NAVMAN is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+# CONFIG_USB_SERIAL_OPTICON is not set
+CONFIG_USB_SERIAL_OPTION=m
+# CONFIG_USB_SERIAL_OTI6858 is not set
+# CONFIG_USB_SERIAL_PL2303 is not set
+# CONFIG_USB_SERIAL_QCAUX is not set
+CONFIG_USB_SERIAL_QUALCOMM=m
+# CONFIG_USB_SERIAL_QUATECH2 is not set
+# CONFIG_USB_SERIAL_QUATECH_USB2 is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_SIEMENS_MPI is not set
+# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set
+# CONFIG_USB_SERIAL_SPCP8X5 is not set
+# CONFIG_USB_SERIAL_SSU100 is not set
+# CONFIG_USB_SERIAL_SYMBOL is not set
+# CONFIG_USB_SERIAL_TI is not set
+# CONFIG_USB_SERIAL_VISOR is not set
+# CONFIG_USB_SERIAL_VIVOPAY_SERIAL is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+CONFIG_USB_SERIAL_WWAN=m
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_ZIO is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_SIERRA_NET is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_SN9C102 is not set
+# CONFIG_USB_STKWEBCAM is not set
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_ENE_UB6250 is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_SUSPEND=y
+# CONFIG_USB_SWITCH_FSA9480 is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_TMC is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_UAS is not set
+CONFIG_USB_VIDEO_CLASS=m
+# CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV is not set
+# CONFIG_USB_VL600 is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+# CONFIG_USB_XHCI_HCD is not set
+# CONFIG_USB_YUREX is not set
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_USB_ZR364XX is not set
+CONFIG_USER_NS=y
+CONFIG_USE_GENERIC_SMP_HELPERS=y
+CONFIG_UTS_NS=y
+# CONFIG_UWB is not set
+# CONFIG_V4L_MEM2MEM_DRIVERS is not set
+CONFIG_V4L_USB_DRIVERS=y
+CONFIG_VETH=m
+CONFIG_VFAT_FS=m
+# CONFIG_VGASTATE is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_VIDEO_ADV7170 is not set
+# CONFIG_VIDEO_ADV7175 is not set
+# CONFIG_VIDEO_ADV7180 is not set
+# CONFIG_VIDEO_ADV7343 is not set
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_AK881X is not set
+# CONFIG_VIDEO_BT819 is not set
+# CONFIG_VIDEO_BT856 is not set
+# CONFIG_VIDEO_BT866 is not set
+# CONFIG_VIDEO_CAFE_CCIC is not set
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_CS5345 is not set
+# CONFIG_VIDEO_CS53L32A is not set
+# CONFIG_VIDEO_CX2341X is not set
+# CONFIG_VIDEO_CX25840 is not set
+CONFIG_VIDEO_DEV=m
+# CONFIG_VIDEO_DT3155 is not set
+# CONFIG_VIDEO_EM28XX is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+# CONFIG_VIDEO_HDPVR is not set
+# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set
+# CONFIG_VIDEO_HEXIUM_GEMINI is not set
+# CONFIG_VIDEO_HEXIUM_ORION is not set
+# CONFIG_VIDEO_KS0127 is not set
+# CONFIG_VIDEO_M52790 is not set
+CONFIG_VIDEO_MEDIA=m
+# CONFIG_VIDEO_MSP3400 is not set
+# CONFIG_VIDEO_MT9V011 is not set
+# CONFIG_VIDEO_MXB is not set
+# CONFIG_VIDEO_NOON010PC30 is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+# CONFIG_VIDEO_OV7670 is not set
+# CONFIG_VIDEO_PVRUSB2 is not set
+# CONFIG_VIDEO_SAA6588 is not set
+# CONFIG_VIDEO_SAA7110 is not set
+# CONFIG_VIDEO_SAA711X is not set
+# CONFIG_VIDEO_SAA7127 is not set
+# CONFIG_VIDEO_SAA7134 is not set
+# CONFIG_VIDEO_SAA717X is not set
+# CONFIG_VIDEO_SAA7185 is not set
+# CONFIG_VIDEO_SAA7191 is not set
+# CONFIG_VIDEO_SR030PC30 is not set
+# CONFIG_VIDEO_TCM825X is not set
+# CONFIG_VIDEO_TDA7432 is not set
+# CONFIG_VIDEO_TDA9840 is not set
+# CONFIG_VIDEO_TEA6415C is not set
+# CONFIG_VIDEO_TEA6420 is not set
+# CONFIG_VIDEO_THS7303 is not set
+# CONFIG_VIDEO_TLV320AIC23B is not set
+# CONFIG_VIDEO_TVAUDIO is not set
+# CONFIG_VIDEO_TVP514X is not set
+# CONFIG_VIDEO_TVP5150 is not set
+# CONFIG_VIDEO_TVP7002 is not set
+# CONFIG_VIDEO_UPD64031A is not set
+# CONFIG_VIDEO_UPD64083 is not set
+# CONFIG_VIDEO_USBVISION is not set
+CONFIG_VIDEO_V4L2=m
+CONFIG_VIDEO_V4L2_COMMON=m
+# CONFIG_VIDEO_VP27SMPX is not set
+# CONFIG_VIDEO_VPX3220 is not set
+# CONFIG_VIDEO_WM8739 is not set
+# CONFIG_VIDEO_WM8775 is not set
+# CONFIG_VIRTIO_BALLOON is not set
+# CONFIG_VIRT_DRIVERS is not set
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_VME_BUS is not set
+# CONFIG_VMXNET3 is not set
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_VT=y
+# CONFIG_VT6655 is not set
+# CONFIG_VT6656 is not set
+CONFIG_VT_CONSOLE=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_W1 is not set
+# CONFIG_W35UND is not set
+# CONFIG_WAKELOCK is not set
+# CONFIG_WAN is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PRIV=y
+CONFIG_WEXT_PROC=y
+CONFIG_WEXT_SPY=y
+# CONFIG_WIFI_CONTROL_FUNC is not set
+# CONFIG_WIMAX is not set
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_EXT=y
+# CONFIG_WIRELESS_EXT_SYSFS is not set
+# CONFIG_WL1251 is not set
+# CONFIG_WL127X_RFKILL is not set
+# CONFIG_WL12XX_MENU is not set
+CONFIG_WLAN=y
+# CONFIG_X25 is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_IPCOMP=m
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFS_FS is not set
+CONFIG_XPS=y
+# CONFIG_XVMALLOC is not set
+# CONFIG_XZ_DEC is not set
+# CONFIG_XZ_DEC_BCJ is not set
+# CONFIG_YELLOWFIN is not set
+CONFIG_ZISOFS=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_ZLIB_INFLATE=y
+# CONFIG_ZRAM is not set
diff --git a/chromeos/config/i386/config.common.i386 b/chromeos/config/i386/config.common.i386
new file mode 100644
index 000000000000..8eb8362d12f4
--- /dev/null
+++ b/chromeos/config/i386/config.common.i386
@@ -0,0 +1,749 @@
+#
+# Config options generated by splitconfig
+#
+# CONFIG_64BIT is not set
+# CONFIG_ACERHDF is not set
+# CONFIG_ACER_WMI is not set
+CONFIG_ACPI=y
+CONFIG_ACPI_AC=y
+# CONFIG_ACPI_APEI is not set
+# CONFIG_ACPI_ASUS is not set
+CONFIG_ACPI_BATTERY=y
+CONFIG_ACPI_BLACKLIST_YEAR=0
+CONFIG_ACPI_BUTTON=y
+# CONFIG_ACPI_CMPC is not set
+CONFIG_ACPI_CONTAINER=y
+# CONFIG_ACPI_CUSTOM_DSDT is not set
+# CONFIG_ACPI_CUSTOM_METHOD is not set
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_DOCK=y
+# CONFIG_ACPI_EC_DEBUGFS is not set
+CONFIG_ACPI_FAN=y
+# CONFIG_ACPI_HED is not set
+CONFIG_ACPI_HOTPLUG_CPU=y
+# CONFIG_ACPI_PCI_SLOT is not set
+CONFIG_ACPI_PROCESSOR=y
+# CONFIG_ACPI_PROCESSOR_AGGREGATOR is not set
+CONFIG_ACPI_PROCFS=y
+CONFIG_ACPI_PROCFS_POWER=y
+CONFIG_ACPI_PROC_EVENT=y
+# CONFIG_ACPI_QUICKSTART is not set
+# CONFIG_ACPI_SBS is not set
+CONFIG_ACPI_SLEEP=y
+CONFIG_ACPI_THERMAL=y
+# CONFIG_ACPI_TOSHIBA is not set
+CONFIG_ACPI_VIDEO=y
+# CONFIG_ADAPTEC_STARFIRE is not set
+CONFIG_AGP=y
+# CONFIG_AGP_ALI is not set
+# CONFIG_AGP_AMD is not set
+# CONFIG_AGP_AMD64 is not set
+# CONFIG_AGP_ATI is not set
+# CONFIG_AGP_EFFICEON is not set
+CONFIG_AGP_INTEL=y
+# CONFIG_AGP_NVIDIA is not set
+# CONFIG_AGP_SIS is not set
+# CONFIG_AGP_SWORKS is not set
+# CONFIG_AGP_VIA is not set
+# CONFIG_AIRO is not set
+CONFIG_AMD_NB=y
+CONFIG_ANDROID_PARANOID_NETWORK=y
+# CONFIG_APM is not set
+CONFIG_ARCH_CPU_PROBE_RELEASE=y
+CONFIG_ARCH_DEFCONFIG="arch/x86/configs/i386_defconfig"
+# CONFIG_ARCH_DMA_ADDR_T_64BIT is not set
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
+CONFIG_ARCH_HAS_CPU_RELAX=y
+CONFIG_ARCH_HAS_DEFAULT_IDLE=y
+CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_HWEIGHT_CFLAGS="-fcall-saved-ecx -fcall-saved-edx"
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_ARCH_PHYS_ADDR_T_64BIT=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
+CONFIG_ARCH_SUPPORTS_MSI=y
+CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y
+CONFIG_ARCH_USES_PG_UNCACHED=y
+CONFIG_ARCH_WANT_FRAME_POINTERS=y
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_ASUS_LAPTOP is not set
+# CONFIG_ASUS_WMI is not set
+CONFIG_ATA=y
+CONFIG_ATA_ACPI=y
+CONFIG_ATA_BMDMA=y
+CONFIG_ATA_GENERIC=y
+# CONFIG_ATA_NONSTANDARD is not set
+CONFIG_ATA_PIIX=y
+CONFIG_ATA_SFF=y
+CONFIG_ATA_VERBOSE_ERROR=y
+CONFIG_ATH5K=m
+# CONFIG_ATH5K_DEBUG is not set
+CONFIG_ATH5K_PCI=y
+# CONFIG_ATH5K_TRACER is not set
+CONFIG_ATH9K=m
+# CONFIG_ATH9K_AHB is not set
+CONFIG_ATH9K_COMMON=m
+CONFIG_ATH9K_DEBUGFS=y
+CONFIG_ATH9K_HW=m
+CONFIG_ATH9K_PCI=y
+CONFIG_ATH9K_RATE_CONTROL=y
+# CONFIG_AUDIT_ARCH is not set
+# CONFIG_BACKLIGHT_APPLE is not set
+# CONFIG_BACKLIGHT_PROGEAR is not set
+# CONFIG_BACKLIGHT_SAHARA is not set
+# CONFIG_BATTERY_BQ20Z75 is not set
+# CONFIG_BATTERY_BQ27x00 is not set
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_BT_ATH3K=m
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+# CONFIG_BT_HCIUART is not set
+# CONFIG_CHARGER_GPIO is not set
+CONFIG_CHECK_SIGNATURE=y
+CONFIG_CLKBLD_I8253=y
+CONFIG_CLKEVT_I8253=y
+CONFIG_CLKSRC_I8253=y
+CONFIG_CLOCKSOURCE_WATCHDOG=y
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_CMPXCHG_DOUBLE=y
+CONFIG_CMPXCHG_LOCAL=y
+# CONFIG_COMEDI is not set
+# CONFIG_COMPAL_LAPTOP is not set
+# CONFIG_COMPAT_BRK is not set
+# CONFIG_COMPAT_VDSO is not set
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
+# CONFIG_CPA_DEBUG is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_GOV_USERSPACE is not set
+CONFIG_CPU_SUP_AMD=y
+CONFIG_CPU_SUP_CENTAUR=y
+CONFIG_CPU_SUP_CYRIX_32=y
+CONFIG_CPU_SUP_INTEL=y
+CONFIG_CPU_SUP_TRANSMETA_32=y
+CONFIG_CPU_SUP_UMC_32=y
+CONFIG_CRYPTO_AES_586=y
+CONFIG_CRYPTO_AES_NI_INTEL=m
+# CONFIG_CRYPTO_CRC32C_INTEL is not set
+CONFIG_CRYPTO_CRYPTD=m
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_DEV_GEODE is not set
+# CONFIG_CRYPTO_DEV_PADLOCK is not set
+# CONFIG_CRYPTO_SALSA20_586 is not set
+# CONFIG_CRYPTO_TWOFISH_586 is not set
+# CONFIG_DCDBAS is not set
+CONFIG_DEBUG_BOOT_PARAMS=y
+# CONFIG_DEBUG_NX_TEST is not set
+CONFIG_DEBUG_RODATA=y
+# CONFIG_DEBUG_RODATA_TEST is not set
+# CONFIG_DEBUG_SET_MODULE_RONX is not set
+CONFIG_DEBUG_STACKOVERFLOW=y
+# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set
+# CONFIG_DEBUG_VIRTUAL is not set
+CONFIG_DEFAULT_IO_DELAY_TYPE=0
+# CONFIG_DELL_RBU is not set
+CONFIG_DELL_WMI=m
+# CONFIG_DELL_WMI_AIO is not set
+CONFIG_DMI=y
+CONFIG_DMIID=y
+# CONFIG_DMI_SYSFS is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_DNS_RESOLVER is not set
+CONFIG_DOUBLEFAULT=y
+CONFIG_DRM=y
+# CONFIG_DRM_I2C_CH7006 is not set
+# CONFIG_DRM_I2C_SIL164 is not set
+# CONFIG_DRM_I810 is not set
+CONFIG_DRM_I915=y
+CONFIG_DRM_I915_KMS=y
+CONFIG_DRM_KMS_HELPER=y
+# CONFIG_DRM_MGA is not set
+# CONFIG_DRM_PSB is not set
+# CONFIG_DRM_R128 is not set
+# CONFIG_DRM_SAVAGE is not set
+# CONFIG_DRM_SIS is not set
+# CONFIG_DRM_TDFX is not set
+# CONFIG_DRM_VIA is not set
+# CONFIG_DRM_VMWGFX is not set
+CONFIG_E100=m
+CONFIG_E1000=m
+CONFIG_E1000E=m
+CONFIG_EARLY_PRINTK_DBGP=y
+# CONFIG_EDAC is not set
+# CONFIG_EDD is not set
+# CONFIG_EEEPC_LAPTOP is not set
+CONFIG_EFI=y
+# CONFIG_EFI_VARS is not set
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_FB_ARC is not set
+# CONFIG_FB_EFI is not set
+# CONFIG_FB_GEODE is not set
+# CONFIG_FB_HGA is not set
+# CONFIG_FB_I810 is not set
+# CONFIG_FB_LE80578 is not set
+# CONFIG_FB_N411 is not set
+# CONFIG_FB_VESA is not set
+# CONFIG_FB_VGA16 is not set
+# CONFIG_FB_VIA is not set
+# CONFIG_FEALNX is not set
+CONFIG_FIRMWARE_MEMMAP=y
+CONFIG_FIX_EARLYCON_MEM=y
+# CONFIG_FLATMEM_MANUAL is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x16=y
+CONFIG_FONT_8x8=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_FRAME_WARN=2048
+CONFIG_FTRACE_NMI_ENTER=y
+CONFIG_FTRACE_SYSCALLS=y
+# CONFIG_FUJITSU_LAPTOP is not set
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_GENERIC_FIND_FIRST_BIT=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_PENDING_IRQ=y
+# CONFIG_GENERIC_TIME_VSYSCALL is not set
+# CONFIG_GOOGLE_FIRMWARE is not set
+# CONFIG_GPIO_LANGWELL is not set
+# CONFIG_GPIO_PCH is not set
+# CONFIG_GPIO_SCH is not set
+# CONFIG_HANGCHECK_TIMER is not set
+CONFIG_HARDLOCKUP_DETECTOR=y
+CONFIG_HAVE_AOUT=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_HAVE_ARCH_KMEMCHECK=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_ATOMIC_IOMAP=y
+# CONFIG_HAVE_CPUMASK_OF_CPU_MAP is not set
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_FTRACE_NMI_ENTER=y
+CONFIG_HAVE_FUNCTION_GRAPH_FP_TEST=y
+CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KERNEL_BZIP2=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KVM=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y
+CONFIG_HAVE_MMIOTRACE_SUPPORT=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_PCSPKR_PLATFORM=y
+CONFIG_HAVE_PERF_EVENTS_NMI=y
+CONFIG_HAVE_SETUP_PER_CPU_AREA=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_TEXT_POKE_SMP=y
+CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y
+CONFIG_HAVE_USER_RETURN_NOTIFIER=y
+CONFIG_HID_MICROSOFT=m
+CONFIG_HID_PID=y
+# CONFIG_HIGHMEM4G is not set
+# CONFIG_HIGHMEM64G is not set
+CONFIG_HOSTAP_PCI=m
+CONFIG_HOSTAP_PLX=m
+CONFIG_HOTPLUG_PCI=y
+# CONFIG_HOTPLUG_PCI_ACPI is not set
+# CONFIG_HOTPLUG_PCI_COMPAQ is not set
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+# CONFIG_HOTPLUG_PCI_FAKE is not set
+# CONFIG_HOTPLUG_PCI_IBM is not set
+CONFIG_HOTPLUG_PCI_PCIE=y
+# CONFIG_HOTPLUG_PCI_SHPC is not set
+CONFIG_HPET=y
+CONFIG_HPET_EMULATE_RTC=y
+# CONFIG_HPET_MMAP is not set
+CONFIG_HPET_TIMER=y
+# CONFIG_HP_ACCEL is not set
+CONFIG_HP_WMI=m
+CONFIG_HT_IRQ=y
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HW_RANDOM_AMD is not set
+# CONFIG_HW_RANDOM_GEODE is not set
+CONFIG_HW_RANDOM_INTEL=y
+# CONFIG_HW_RANDOM_VIA is not set
+# CONFIG_HW_RANDOM_VIRTIO is not set
+# CONFIG_HYPERV is not set
+CONFIG_HZ=1000
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+CONFIG_I2C_ALGOBIT=y
+CONFIG_I2C_I801=m
+CONFIG_I2C_PIIX4=m
+# CONFIG_I2C_SCMI is not set
+# CONFIG_I8K is not set
+# CONFIG_IBM_ASM is not set
+# CONFIG_IBM_RTL is not set
+# CONFIG_IDEAPAD_LAPTOP is not set
+# CONFIG_IDE_PHISON is not set
+CONFIG_IGBVF=m
+CONFIG_ILLEGAL_POINTER_VALUE=0
+# CONFIG_INPUT_APANEL is not set
+# CONFIG_INPUT_ATLAS_BTNS is not set
+CONFIG_INPUT_SPARSEKMAP=m
+# CONFIG_INPUT_WISTRON_BTNS is not set
+CONFIG_INSTRUCTION_DECODER=y
+# CONFIG_INTEL_IDLE is not set
+# CONFIG_INTEL_IOMMU is not set
+# CONFIG_INTEL_IPS is not set
+# CONFIG_INTEL_MEI is not set
+CONFIG_INTEL_MENLOW=m
+# CONFIG_INTEL_OAKTRAIL is not set
+# CONFIG_IOMMU_HELPER is not set
+# CONFIG_IOMMU_STRESS is not set
+CONFIG_IO_DELAY_0X80=y
+# CONFIG_IO_DELAY_0XED is not set
+# CONFIG_IO_DELAY_NONE is not set
+CONFIG_IO_DELAY_TYPE_0X80=0
+CONFIG_IO_DELAY_TYPE_0XED=1
+CONFIG_IO_DELAY_TYPE_NONE=3
+CONFIG_IO_DELAY_TYPE_UDELAY=2
+# CONFIG_IO_DELAY_UDELAY is not set
+CONFIG_IPV6=m
+# CONFIG_IP_PNP is not set
+CONFIG_IRQ_FORCED_THREADING=y
+# CONFIG_IRQ_TIME_ACCOUNTING is not set
+# CONFIG_IR_ENE is not set
+# CONFIG_IR_FINTEK is not set
+# CONFIG_IR_IMON is not set
+# CONFIG_IR_ITE_CIR is not set
+# CONFIG_IR_JVC_DECODER is not set
+# CONFIG_IR_LIRC_CODEC is not set
+# CONFIG_IR_MCEUSB is not set
+CONFIG_IR_MCE_KBD_DECODER=m
+# CONFIG_IR_NEC_DECODER is not set
+# CONFIG_IR_NUVOTON is not set
+# CONFIG_IR_RC5_DECODER is not set
+# CONFIG_IR_RC5_SZ_DECODER is not set
+# CONFIG_IR_RC6_DECODER is not set
+# CONFIG_IR_REDRAT3 is not set
+# CONFIG_IR_SONY_DECODER is not set
+# CONFIG_IR_STREAMZAP is not set
+# CONFIG_IR_WINBOND_CIR is not set
+# CONFIG_ISA is not set
+CONFIG_ISA_DMA_API=y
+# CONFIG_ISCSI_IBFT_FIND is not set
+CONFIG_JME=m
+# CONFIG_JUMP_LABEL is not set
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_XZ is not set
+# CONFIG_KSZ884X_PCI is not set
+CONFIG_KTIME_SCALAR=y
+# CONFIG_KVM is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_LBDAF=y
+# CONFIG_LEDS_ALIX2 is not set
+# CONFIG_LEDS_CLEVO_MAIL is not set
+# CONFIG_LEDS_DELL_NETBOOKS is not set
+# CONFIG_LEDS_INTEL_SS4200 is not set
+# CONFIG_LGUEST is not set
+CONFIG_LIBERTAS_THINFIRM_USB=m
+CONFIG_LIRC=m
+# CONFIG_LIRC_STAGING is not set
+CONFIG_LPC_SCH=m
+# CONFIG_M386 is not set
+# CONFIG_M486 is not set
+# CONFIG_M586 is not set
+# CONFIG_M586MMX is not set
+# CONFIG_M586TSC is not set
+CONFIG_M686=y
+# CONFIG_MACINTOSH_DRIVERS is not set
+# CONFIG_MATH_EMULATION is not set
+# CONFIG_MATOM is not set
+# CONFIG_MCA is not set
+# CONFIG_MCORE2 is not set
+# CONFIG_MCRUSOE is not set
+# CONFIG_MCYRIXIII is not set
+# CONFIG_MEFFICEON is not set
+# CONFIG_MELAN is not set
+# CONFIG_MEMTEST is not set
+CONFIG_MFD_CORE=m
+# CONFIG_MFD_CS5535 is not set
+# CONFIG_MFD_TPS6586X is not set
+# CONFIG_MFD_TPS6591X is not set
+# CONFIG_MGEODEGX1 is not set
+# CONFIG_MGEODE_LX is not set
+CONFIG_MICROCODE=y
+CONFIG_MICROCODE_AMD=y
+CONFIG_MICROCODE_INTEL=y
+CONFIG_MICROCODE_OLD_INTERFACE=y
+# CONFIG_MK6 is not set
+# CONFIG_MK7 is not set
+# CONFIG_MK8 is not set
+# CONFIG_MMC is not set
+# CONFIG_MMIOTRACE is not set
+CONFIG_MOUSE_APPLETOUCH=m
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_ELANTECH=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+# CONFIG_MOUSE_PS2_SENTELIC is not set
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MPENTIUM4 is not set
+# CONFIG_MPENTIUMII is not set
+# CONFIG_MPENTIUMIII is not set
+# CONFIG_MPENTIUMM is not set
+# CONFIG_MSI_LAPTOP is not set
+# CONFIG_MSI_WMI is not set
+CONFIG_MTRR=y
+# CONFIG_MTRR_SANITIZER is not set
+# CONFIG_MVIAC3_2 is not set
+# CONFIG_MVIAC7 is not set
+# CONFIG_MWAVE is not set
+# CONFIG_MWINCHIP3D is not set
+# CONFIG_MWINCHIPC6 is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_NEED_DMA_MAP_STATE is not set
+CONFIG_NEED_NODE_MEMMAP_SIZE=y
+CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y
+CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y
+CONFIG_NEED_SG_DMA_LENGTH=y
+# CONFIG_NETWORK_FILESYSTEMS is not set
+CONFIG_NET_PCI=y
+# CONFIG_NET_SB1000 is not set
+CONFIG_NOHIGHMEM=y
+CONFIG_NO_BOOTMEM=y
+CONFIG_NR_CPUS=4
+# CONFIG_NSC_GPIO is not set
+CONFIG_NVRAM=y
+CONFIG_OPTIMIZE_INLINING=y
+CONFIG_OUTPUT_FORMAT="elf32-i386"
+CONFIG_PAGE_OFFSET=0x80000000
+# CONFIG_PANASONIC_LAPTOP is not set
+# CONFIG_PARAVIRT_GUEST is not set
+# CONFIG_PATA_ACPI is not set
+# CONFIG_PATA_ALI is not set
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_ATP867X is not set
+# CONFIG_PATA_CMD640_PCI is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
+# CONFIG_PATA_CS5535 is not set
+# CONFIG_PATA_CS5536 is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_IT8213 is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_LEGACY is not set
+# CONFIG_PATA_MARVELL is not set
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NINJA32 is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_NS87415 is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_PLATFORM is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RDC is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_SC1200 is not set
+# CONFIG_PATA_SCH is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+# CONFIG_PATA_TOSHIBA is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_VIA is not set
+# CONFIG_PATA_WINBOND is not set
+# CONFIG_PC8736x_GPIO is not set
+CONFIG_PCIEAER=y
+# CONFIG_PCIEAER_INJECT is not set
+CONFIG_PCIEASPM=y
+# CONFIG_PCIEASPM_DEBUG is not set
+CONFIG_PCIEPORTBUS=y
+# CONFIG_PCIE_ECRC is not set
+CONFIG_PCIE_PME=y
+CONFIG_PCI_BIOS=y
+# CONFIG_PCI_CNB20LE_QUIRK is not set
+CONFIG_PCI_DIRECT=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_GOANY=y
+# CONFIG_PCI_GOBIOS is not set
+# CONFIG_PCI_GODIRECT is not set
+# CONFIG_PCI_GOMMCONFIG is not set
+CONFIG_PCI_IOAPIC=y
+CONFIG_PCI_LABEL=y
+CONFIG_PCI_MMCONFIG=y
+CONFIG_PCI_MSI=y
+# CONFIG_PCSPKR_PLATFORM is not set
+# CONFIG_PDC_ADMA is not set
+CONFIG_PHYSICAL_ALIGN=0x200000
+CONFIG_PHYSICAL_START=0x1000000
+CONFIG_PHYS_ADDR_T_64BIT=y
+CONFIG_PM_TRACE=y
+CONFIG_PM_TRACE_RTC=y
+CONFIG_PNP=y
+CONFIG_PNPACPI=y
+CONFIG_PNP_DEBUG_MESSAGES=y
+# CONFIG_PROCESSOR_SELECT is not set
+CONFIG_PROC_KCORE=y
+CONFIG_PROVIDE_OHCI1394_DMA_INIT=y
+# CONFIG_R6040 is not set
+# CONFIG_RAPIDIO is not set
+CONFIG_RC_CORE=m
+# CONFIG_RC_LOOPBACK is not set
+CONFIG_RC_MAP=m
+CONFIG_REALTEK_AUTOPM=y
+# CONFIG_REGULATOR is not set
+# CONFIG_RELOCATABLE is not set
+# CONFIG_REPORT_PRESENT_CPUS is not set
+CONFIG_RTC_DRV_CMOS=m
+# CONFIG_RTC_HCTOSYS is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+# CONFIG_SAMSUNG_LAPTOP is not set
+# CONFIG_SAMSUNG_Q10 is not set
+# CONFIG_SATA_ACARD_AHCI is not set
+CONFIG_SATA_AHCI=y
+# CONFIG_SATA_AHCI_PLATFORM is not set
+# CONFIG_SATA_INIC162X is not set
+# CONFIG_SATA_MV is not set
+# CONFIG_SATA_NV is not set
+# CONFIG_SATA_PMP is not set
+# CONFIG_SATA_PROMISE is not set
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_SIL is not set
+# CONFIG_SATA_SIL24 is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_SVW is not set
+# CONFIG_SATA_SX4 is not set
+# CONFIG_SATA_ULI is not set
+# CONFIG_SATA_VIA is not set
+# CONFIG_SATA_VITESSE is not set
+# CONFIG_SC92031 is not set
+CONFIG_SCHED_HRTICK=y
+CONFIG_SCHED_MC=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_SMT=y
+CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+# CONFIG_SCx200 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_ABITUGURU3 is not set
+# CONFIG_SENSORS_ACPI_POWER is not set
+# CONFIG_SENSORS_APPLESMC is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATK0110 is not set
+CONFIG_SENSORS_CORETEMP=y
+# CONFIG_SENSORS_FAM15H_POWER is not set
+# CONFIG_SENSORS_FSCHMD is not set
+# CONFIG_SENSORS_HDAPS is not set
+# CONFIG_SENSORS_ISL29018 is not set
+# CONFIG_SENSORS_ISL29028 is not set
+# CONFIG_SENSORS_K10TEMP is not set
+# CONFIG_SENSORS_K8TEMP is not set
+# CONFIG_SENSORS_NCT1008 is not set
+# CONFIG_SENSORS_VIA_CPUTEMP is not set
+# CONFIG_SERIAL_8250 is not set
+CONFIG_SERIO_CT82C710=m
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_PCIPS2=m
+# CONFIG_SFI is not set
+# CONFIG_SIGMA is not set
+# CONFIG_SIS900 is not set
+# CONFIG_SLAB is not set
+# CONFIG_SLICOSS is not set
+CONFIG_SLUB=y
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+# CONFIG_SMSC9420 is not set
+# CONFIG_SND_ALS4000 is not set
+# CONFIG_SND_ASIHPI is not set
+# CONFIG_SND_CS5530 is not set
+CONFIG_SND_DMA_SGBUF=y
+CONFIG_SND_HDA_CODEC_ANALOG=y
+CONFIG_SND_HDA_CODEC_CA0110=y
+CONFIG_SND_HDA_CODEC_CA0132=y
+CONFIG_SND_HDA_CODEC_CIRRUS=y
+CONFIG_SND_HDA_CODEC_CMEDIA=y
+CONFIG_SND_HDA_CODEC_CONEXANT=y
+CONFIG_SND_HDA_CODEC_HDMI=y
+CONFIG_SND_HDA_CODEC_REALTEK=y
+CONFIG_SND_HDA_CODEC_SI3054=y
+CONFIG_SND_HDA_CODEC_SIGMATEL=y
+CONFIG_SND_HDA_CODEC_VIA=y
+CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS=y
+CONFIG_SND_HDA_GENERIC=y
+CONFIG_SND_HDA_HWDEP=y
+# CONFIG_SND_HDA_INPUT_BEEP is not set
+CONFIG_SND_HDA_INPUT_JACK=y
+CONFIG_SND_HDA_INTEL=m
+# CONFIG_SND_HDA_PATCH_LOADER is not set
+# CONFIG_SND_HDA_PLATFORM_DRIVER is not set
+CONFIG_SND_HDA_POWER_SAVE=y
+CONFIG_SND_HDA_POWER_SAVE_DEFAULT=5
+CONFIG_SND_HDA_PREALLOC_SIZE=64
+# CONFIG_SND_HDA_RECONFIG is not set
+CONFIG_SND_PCM=m
+# CONFIG_SND_SIS7019 is not set
+# CONFIG_SND_SOC is not set
+CONFIG_SND_TIMER=m
+# CONFIG_SND_USB_US122L is not set
+# CONFIG_SND_USB_USX2Y is not set
+CONFIG_SND_VMASTER=y
+# CONFIG_SOC_CAMERA is not set
+# CONFIG_SONYPI is not set
+# CONFIG_SONY_LAPTOP is not set
+CONFIG_SPARSEMEM=y
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM_STATIC=y
+CONFIG_SPARSE_IRQ=y
+# CONFIG_SPI_PXA2XX is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_SWAP is not set
+# CONFIG_TC1100_WMI is not set
+# CONFIG_TCG_INFINEON is not set
+CONFIG_TCG_TIS=y
+# CONFIG_TELCLOCK is not set
+# CONFIG_THINKPAD_ACPI is not set
+# CONFIG_TLAN is not set
+# CONFIG_TOPSTAR_LAPTOP is not set
+# CONFIG_TOSHIBA is not set
+# CONFIG_TOSHIBA_BT_RFKILL is not set
+# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set
+# CONFIG_TRANSPARENT_HUGEPAGE is not set
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+CONFIG_USB_NET_CDC_NCM=m
+CONFIG_USB_NET_DM9601=m
+CONFIG_USB_NET_MCS7830=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_RNDIS_HOST=m
+CONFIG_USB_NET_SMSC95XX=m
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_STORAGE_REALTEK=y
+CONFIG_USB_UHCI_HCD=y
+CONFIG_USB_USBNET=m
+CONFIG_USER_STACKTRACE_SUPPORT=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
+# CONFIG_VGA_ARB is not set
+CONFIG_VGA_CONSOLE=y
+# CONFIG_VGA_SWITCHEROO is not set
+# CONFIG_VHOST_NET is not set
+# CONFIG_VIDEO_BT848 is not set
+# CONFIG_VIDEO_CX231XX is not set
+# CONFIG_VIDEO_CX88 is not set
+# CONFIG_VIDEO_GO7007 is not set
+# CONFIG_VIDEO_IR_I2C is not set
+# CONFIG_VIDEO_IVTV is not set
+# CONFIG_VIDEO_TM6000 is not set
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_ZORAN is not set
+CONFIG_VIRTIO=m
+CONFIG_VIRTIO_BLK=m
+# CONFIG_VIRTIO_CONSOLE is not set
+CONFIG_VIRTIO_NET=m
+CONFIG_VIRTIO_PCI=m
+CONFIG_VIRTIO_RING=m
+CONFIG_VIRTUALIZATION=y
+# CONFIG_VM86 is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_VMSPLIT_2G=y
+# CONFIG_VMSPLIT_3G is not set
+# CONFIG_VMWARE_BALLOON is not set
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_X86=y
+CONFIG_X86_32=y
+# CONFIG_X86_32_IRIS is not set
+# CONFIG_X86_32_NON_STANDARD is not set
+CONFIG_X86_32_SMP=y
+# CONFIG_X86_64 is not set
+CONFIG_X86_ACPI_CPUFREQ=y
+# CONFIG_X86_ANCIENT_MCE is not set
+# CONFIG_X86_BIGSMP is not set
+CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK=y
+CONFIG_X86_BSWAP=y
+CONFIG_X86_CHECK_BIOS_CORRUPTION=y
+CONFIG_X86_CMOV=y
+CONFIG_X86_CMPXCHG=y
+CONFIG_X86_CMPXCHG64=y
+# CONFIG_X86_CPUFREQ_NFORCE2 is not set
+CONFIG_X86_CPUID=y
+CONFIG_X86_DEBUGCTLMSR=y
+CONFIG_X86_EXTENDED_PLATFORM=y
+# CONFIG_X86_E_POWERSAVER is not set
+# CONFIG_X86_GENERIC is not set
+# CONFIG_X86_GX_SUSPMOD is not set
+CONFIG_X86_HT=y
+# CONFIG_X86_INTEL_MID is not set
+CONFIG_X86_INTERNODE_CACHE_SHIFT=5
+CONFIG_X86_INVLPG=y
+CONFIG_X86_IO_APIC=y
+CONFIG_X86_L1_CACHE_SHIFT=5
+CONFIG_X86_LOCAL_APIC=y
+# CONFIG_X86_LONGHAUL is not set
+# CONFIG_X86_LONGRUN is not set
+CONFIG_X86_MCE=y
+# CONFIG_X86_MCE_AMD is not set
+# CONFIG_X86_MCE_INJECT is not set
+CONFIG_X86_MCE_INTEL=y
+CONFIG_X86_MCE_THRESHOLD=y
+CONFIG_X86_MINIMUM_CPU_FAMILY=5
+CONFIG_X86_MPPARSE=y
+CONFIG_X86_MSR=y
+# CONFIG_X86_P4_CLOCKMOD is not set
+CONFIG_X86_PAE=y
+CONFIG_X86_PAT=y
+# CONFIG_X86_PCC_CPUFREQ is not set
+CONFIG_X86_PLATFORM_DEVICES=y
+CONFIG_X86_PM_TIMER=y
+CONFIG_X86_POPAD_OK=y
+# CONFIG_X86_PPRO_FENCE is not set
+# CONFIG_X86_PTDUMP is not set
+# CONFIG_X86_RDC321X is not set
+# CONFIG_X86_REBOOTFIXUPS is not set
+CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y
+CONFIG_X86_RESERVE_LOW=64
+# CONFIG_X86_SPEEDSTEP_CENTRINO is not set
+# CONFIG_X86_SPEEDSTEP_ICH is not set
+# CONFIG_X86_SPEEDSTEP_LIB is not set
+# CONFIG_X86_SPEEDSTEP_SMI is not set
+CONFIG_X86_THERMAL_VECTOR=y
+CONFIG_X86_TSC=y
+CONFIG_X86_USE_PPRO_CHECKSUM=y
+CONFIG_X86_VERBOSE_BOOTUP=y
+CONFIG_X86_WP_WORKS_OK=y
+CONFIG_X86_XADD=y
+CONFIG_XFRM_USER=y
+# CONFIG_XO15_EBOOK is not set
+CONFIG_ZONE_DMA=y
+# CONFIG_ZONE_DMA32 is not set
+CONFIG_ZONE_DMA_FLAG=1
diff --git a/chromeos/config/i386/config.flavour.chromeos-intel-menlow b/chromeos/config/i386/config.flavour.chromeos-intel-menlow
new file mode 120000
index 000000000000..c867d1c41632
--- /dev/null
+++ b/chromeos/config/i386/config.flavour.chromeos-intel-menlow
@@ -0,0 +1 @@
+config.flavour.chromeos-pinetrail-i386 \ No newline at end of file
diff --git a/chromeos/config/i386/config.flavour.chromeos-pinetrail-i386 b/chromeos/config/i386/config.flavour.chromeos-pinetrail-i386
new file mode 100644
index 000000000000..9a9d2991c3fd
--- /dev/null
+++ b/chromeos/config/i386/config.flavour.chromeos-pinetrail-i386
@@ -0,0 +1,41 @@
+#
+# Config options generated by splitconfig
+#
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+CONFIG_ACPI_WMI=m
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ATL1 is not set
+# CONFIG_ATL1C is not set
+# CONFIG_ATL1E is not set
+# CONFIG_ATL2 is not set
+# CONFIG_B44 is not set
+# CONFIG_BRCMSMAC is not set
+# CONFIG_BRCMUTIL is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_DRM_NOUVEAU is not set
+# CONFIG_DRM_RADEON is not set
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_IWL3945 is not set
+# CONFIG_IWL4965 is not set
+# CONFIG_IWLAGN is not set
+# CONFIG_MXM_WMI is not set
+# CONFIG_PCNET32 is not set
+# CONFIG_R8169 is not set
+# CONFIG_RT2500USB is not set
+# CONFIG_RT2800USB is not set
+# CONFIG_RT73USB is not set
+CONFIG_RTL8192CE=m
+CONFIG_RTL8192C_COMMON=m
+CONFIG_RTLWIFI=m
+# CONFIG_SKY2 is not set
+# CONFIG_SSB is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_X86_POWERNOW_K6 is not set
+# CONFIG_X86_POWERNOW_K7 is not set
+# CONFIG_X86_POWERNOW_K8 is not set
+# CONFIG_ZD1211RW is not set
diff --git a/chromeos/config/i386/config.flavour.chromiumos-i386 b/chromeos/config/i386/config.flavour.chromiumos-i386
new file mode 100644
index 000000000000..244efff4d3ab
--- /dev/null
+++ b/chromeos/config/i386/config.flavour.chromiumos-i386
@@ -0,0 +1,85 @@
+#
+# Config options generated by splitconfig
+#
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+# CONFIG_8139TOO_8129 is not set
+CONFIG_8139TOO_PIO=y
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_ACPI_WMI=y
+CONFIG_AMD8111_ETH=m
+CONFIG_ATL1=m
+CONFIG_ATL1C=m
+CONFIG_ATL1E=m
+CONFIG_ATL2=m
+CONFIG_B44=m
+CONFIG_B44_PCI=y
+CONFIG_B44_PCICORE_AUTOSELECT=y
+CONFIG_B44_PCI_AUTOSELECT=y
+# CONFIG_BRCMDBG is not set
+CONFIG_BRCMSMAC=m
+CONFIG_BRCMUTIL=m
+CONFIG_BROADCOM_PHY=y
+CONFIG_DRM_NOUVEAU=y
+CONFIG_DRM_NOUVEAU_BACKLIGHT=y
+# CONFIG_DRM_NOUVEAU_DEBUG is not set
+CONFIG_DRM_RADEON=y
+CONFIG_DRM_RADEON_KMS=y
+CONFIG_DRM_TTM=y
+CONFIG_EXTRA_FIRMWARE="radeon/PALM_me.bin radeon/PALM_pfp.bin radeon/SUMO_rlc.bin"
+CONFIG_EXTRA_FIRMWARE_DIR="firmware"
+CONFIG_FB_BACKLIGHT=y
+CONFIG_FORCEDETH=m
+CONFIG_IWL3945=m
+CONFIG_IWL4965=m
+CONFIG_IWLAGN=m
+# CONFIG_IWLWIFI_DEBUG is not set
+# CONFIG_IWLWIFI_DEBUGFS is not set
+# CONFIG_IWLWIFI_DEVICE_SVTOOL is not set
+# CONFIG_IWLWIFI_DEVICE_TRACING is not set
+CONFIG_IWLWIFI_LEGACY=m
+# CONFIG_IWLWIFI_LEGACY_DEBUG is not set
+# CONFIG_IWLWIFI_LEGACY_DEBUGFS is not set
+# CONFIG_IWLWIFI_LEGACY_DEVICE_TRACING is not set
+# CONFIG_IWL_P2P is not set
+CONFIG_MXM_WMI=y
+CONFIG_PCNET32=m
+CONFIG_R8169=m
+CONFIG_RT2500USB=m
+CONFIG_RT2800USB=m
+CONFIG_RT2800USB_RT33XX=y
+CONFIG_RT2800USB_RT35XX=y
+# CONFIG_RT2800USB_RT53XX is not set
+# CONFIG_RT2800USB_UNKNOWN is not set
+CONFIG_RT2800_LIB=m
+# CONFIG_RT2X00_DEBUG is not set
+CONFIG_RT2X00_LIB=m
+CONFIG_RT2X00_LIB_CRYPTO=y
+# CONFIG_RT2X00_LIB_DEBUGFS is not set
+CONFIG_RT2X00_LIB_FIRMWARE=y
+CONFIG_RT2X00_LIB_LEDS=y
+CONFIG_RT2X00_LIB_USB=m
+CONFIG_RT73USB=m
+# CONFIG_RTL8192CE is not set
+CONFIG_SKY2=m
+# CONFIG_SKY2_DEBUG is not set
+CONFIG_SSB=m
+# CONFIG_SSB_B43_PCI_BRIDGE is not set
+# CONFIG_SSB_DEBUG is not set
+CONFIG_SSB_DRIVER_PCICORE=y
+CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y
+CONFIG_SSB_PCIHOST=y
+CONFIG_SSB_PCIHOST_POSSIBLE=y
+# CONFIG_SSB_SILENT is not set
+CONFIG_SSB_SPROM=y
+CONFIG_TIGON3=m
+CONFIG_USB_RTL8150=m
+CONFIG_VIA_RHINE=m
+# CONFIG_VIA_RHINE_MMIO is not set
+CONFIG_X86_POWERNOW_K6=y
+CONFIG_X86_POWERNOW_K7=y
+CONFIG_X86_POWERNOW_K7_ACPI=y
+CONFIG_X86_POWERNOW_K8=y
+CONFIG_ZD1211RW=m
+# CONFIG_ZD1211RW_DEBUG is not set
diff --git a/chromeos/config/x86_64/config.common.x86_64 b/chromeos/config/x86_64/config.common.x86_64
new file mode 100644
index 000000000000..ab17b2e1864c
--- /dev/null
+++ b/chromeos/config/x86_64/config.common.x86_64
@@ -0,0 +1,740 @@
+#
+# Config options generated by splitconfig
+#
+CONFIG_64BIT=y
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_ACERHDF is not set
+# CONFIG_ACER_WMI is not set
+CONFIG_ACPI=y
+CONFIG_ACPI_AC=y
+# CONFIG_ACPI_APEI is not set
+# CONFIG_ACPI_ASUS is not set
+CONFIG_ACPI_BATTERY=y
+CONFIG_ACPI_BLACKLIST_YEAR=0
+CONFIG_ACPI_BUTTON=y
+# CONFIG_ACPI_CMPC is not set
+CONFIG_ACPI_CONTAINER=y
+# CONFIG_ACPI_CUSTOM_DSDT is not set
+# CONFIG_ACPI_CUSTOM_METHOD is not set
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_DOCK=y
+# CONFIG_ACPI_EC_DEBUGFS is not set
+CONFIG_ACPI_FAN=y
+# CONFIG_ACPI_HED is not set
+CONFIG_ACPI_HOTPLUG_CPU=y
+# CONFIG_ACPI_PCI_SLOT is not set
+CONFIG_ACPI_PROCESSOR=y
+# CONFIG_ACPI_PROCESSOR_AGGREGATOR is not set
+CONFIG_ACPI_PROCFS=y
+CONFIG_ACPI_PROCFS_POWER=y
+CONFIG_ACPI_PROC_EVENT=y
+# CONFIG_ACPI_QUICKSTART is not set
+# CONFIG_ACPI_SBS is not set
+CONFIG_ACPI_SLEEP=y
+CONFIG_ACPI_THERMAL=y
+# CONFIG_ACPI_TOSHIBA is not set
+CONFIG_ACPI_VIDEO=y
+CONFIG_ACPI_WMI=m
+# CONFIG_ADAPTEC_STARFIRE is not set
+CONFIG_AGP=y
+# CONFIG_AGP_AMD64 is not set
+CONFIG_AGP_INTEL=y
+# CONFIG_AGP_SIS is not set
+# CONFIG_AGP_VIA is not set
+# CONFIG_AIRO is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_AMD_IOMMU is not set
+CONFIG_AMD_NB=y
+CONFIG_ANDROID_PARANOID_NETWORK=y
+CONFIG_ARCH_CLOCKSOURCE_DATA=y
+CONFIG_ARCH_CPU_PROBE_RELEASE=y
+CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig"
+CONFIG_ARCH_DMA_ADDR_T_64BIT=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
+CONFIG_ARCH_HAS_CPU_RELAX=y
+CONFIG_ARCH_HAS_DEFAULT_IDLE=y
+CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_HWEIGHT_CFLAGS="-fcall-saved-rdi -fcall-saved-rsi -fcall-saved-rdx -fcall-saved-rcx -fcall-saved-r8 -fcall-saved-r9 -fcall-saved-r10 -fcall-saved-r11"
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_ARCH_PHYS_ADDR_T_64BIT=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_PROC_KCORE_TEXT=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
+CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y
+CONFIG_ARCH_SUPPORTS_MSI=y
+CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y
+CONFIG_ARCH_USES_PG_UNCACHED=y
+CONFIG_ARCH_WANT_FRAME_POINTERS=y
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_ASUS_LAPTOP is not set
+# CONFIG_ASUS_WMI is not set
+CONFIG_ATA=y
+CONFIG_ATA_ACPI=y
+CONFIG_ATA_BMDMA=y
+CONFIG_ATA_GENERIC=y
+# CONFIG_ATA_NONSTANDARD is not set
+CONFIG_ATA_PIIX=y
+CONFIG_ATA_SFF=y
+CONFIG_ATA_VERBOSE_ERROR=y
+CONFIG_ATH5K=m
+# CONFIG_ATH5K_DEBUG is not set
+CONFIG_ATH5K_PCI=y
+# CONFIG_ATH5K_TRACER is not set
+CONFIG_ATH9K=m
+# CONFIG_ATH9K_AHB is not set
+CONFIG_ATH9K_COMMON=m
+CONFIG_ATH9K_DEBUGFS=y
+CONFIG_ATH9K_HW=m
+CONFIG_ATH9K_PCI=y
+CONFIG_ATH9K_RATE_CONTROL=y
+# CONFIG_ATL1 is not set
+# CONFIG_ATL1C is not set
+# CONFIG_ATL1E is not set
+# CONFIG_ATL2 is not set
+CONFIG_AUDIT_ARCH=y
+# CONFIG_B44 is not set
+# CONFIG_BACKLIGHT_APPLE is not set
+# CONFIG_BACKLIGHT_PROGEAR is not set
+# CONFIG_BACKLIGHT_SAHARA is not set
+# CONFIG_BATTERY_BQ20Z75 is not set
+# CONFIG_BATTERY_BQ27x00 is not set
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_BLOCK_COMPAT=y
+# CONFIG_BPF_JIT is not set
+# CONFIG_BRCMSMAC is not set
+# CONFIG_BRCMUTIL is not set
+# CONFIG_BROADCOM_PHY is not set
+CONFIG_BT_ATH3K=m
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+# CONFIG_BT_HCIUART is not set
+# CONFIG_CALGARY_IOMMU is not set
+# CONFIG_CHARGER_GPIO is not set
+CONFIG_CHECK_SIGNATURE=y
+CONFIG_CLKBLD_I8253=y
+CONFIG_CLKEVT_I8253=y
+CONFIG_CLOCKSOURCE_WATCHDOG=y
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_CMPXCHG_DOUBLE=y
+CONFIG_CMPXCHG_LOCAL=y
+# CONFIG_COMEDI is not set
+# CONFIG_COMPAL_LAPTOP is not set
+CONFIG_COMPAT=y
+CONFIG_COMPAT_BINFMT_ELF=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_COMPAT_FOR_U64_ALIGNMENT=y
+CONFIG_COMPAT_NETLINK_MESSAGES=y
+# CONFIG_COMPAT_VDSO is not set
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
+# CONFIG_CPA_DEBUG is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_SUP_AMD=y
+CONFIG_CPU_SUP_CENTAUR=y
+CONFIG_CPU_SUP_INTEL=y
+# CONFIG_CRASH_DUMP is not set
+CONFIG_CRYPTO_AES_NI_INTEL=m
+CONFIG_CRYPTO_AES_X86_64=m
+# CONFIG_CRYPTO_CRC32C_INTEL is not set
+CONFIG_CRYPTO_CRYPTD=m
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_DEV_PADLOCK is not set
+# CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL is not set
+# CONFIG_CRYPTO_SALSA20_X86_64 is not set
+# CONFIG_CRYPTO_TWOFISH_X86_64 is not set
+# CONFIG_DCDBAS is not set
+CONFIG_DEBUG_BOOT_PARAMS=y
+# CONFIG_DEBUG_NX_TEST is not set
+CONFIG_DEBUG_RODATA=y
+# CONFIG_DEBUG_RODATA_TEST is not set
+# CONFIG_DEBUG_SET_MODULE_RONX is not set
+CONFIG_DEBUG_STACKOVERFLOW=y
+# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set
+# CONFIG_DEBUG_VIRTUAL is not set
+CONFIG_DEFAULT_IO_DELAY_TYPE=0
+# CONFIG_DELL_RBU is not set
+CONFIG_DELL_WMI=m
+# CONFIG_DELL_WMI_AIO is not set
+CONFIG_DIRECT_GBPAGES=y
+CONFIG_DMI=y
+CONFIG_DMIID=y
+# CONFIG_DMI_SYSFS is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_DNS_RESOLVER is not set
+CONFIG_DRM=y
+# CONFIG_DRM_I2C_CH7006 is not set
+# CONFIG_DRM_I2C_SIL164 is not set
+# CONFIG_DRM_I810 is not set
+CONFIG_DRM_I915=y
+CONFIG_DRM_I915_KMS=y
+CONFIG_DRM_KMS_HELPER=y
+# CONFIG_DRM_MGA is not set
+# CONFIG_DRM_NOUVEAU is not set
+# CONFIG_DRM_PSB is not set
+# CONFIG_DRM_R128 is not set
+# CONFIG_DRM_RADEON is not set
+# CONFIG_DRM_SAVAGE is not set
+# CONFIG_DRM_SIS is not set
+# CONFIG_DRM_TDFX is not set
+# CONFIG_DRM_VIA is not set
+# CONFIG_DRM_VMWGFX is not set
+CONFIG_E100=m
+CONFIG_E1000=m
+CONFIG_E1000E=m
+CONFIG_EARLY_PRINTK_DBGP=y
+# CONFIG_EDAC is not set
+# CONFIG_EDD is not set
+# CONFIG_EEEPC_LAPTOP is not set
+CONFIG_EFI=y
+# CONFIG_EFI_VARS is not set
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_EPIC100 is not set
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_FB_ARC is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_EFI is not set
+# CONFIG_FB_GEODE is not set
+# CONFIG_FB_HGA is not set
+# CONFIG_FB_LE80578 is not set
+# CONFIG_FB_N411 is not set
+# CONFIG_FB_VESA is not set
+# CONFIG_FB_VGA16 is not set
+# CONFIG_FB_VIA is not set
+# CONFIG_FEALNX is not set
+CONFIG_FIRMWARE_MEMMAP=y
+CONFIG_FIX_EARLYCON_MEM=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x16=y
+CONFIG_FONT_8x8=y
+# CONFIG_FORCEDETH is not set
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_FRAME_WARN=2048
+CONFIG_FTRACE_NMI_ENTER=y
+CONFIG_FTRACE_SYSCALLS=y
+# CONFIG_FUJITSU_LAPTOP is not set
+CONFIG_FUNCTION_GRAPH_TRACER=y
+CONFIG_GART_IOMMU=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_GENERIC_CPU=y
+CONFIG_GENERIC_FIND_FIRST_BIT=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_PENDING_IRQ=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+# CONFIG_GOOGLE_FIRMWARE is not set
+# CONFIG_GPIO_LANGWELL is not set
+# CONFIG_GPIO_PCH is not set
+# CONFIG_GPIO_SCH is not set
+# CONFIG_HANGCHECK_TIMER is not set
+CONFIG_HARDLOCKUP_DETECTOR=y
+# CONFIG_HAVE_AOUT is not set
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_HAVE_ARCH_KMEMCHECK=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_BPF_JIT=y
+CONFIG_HAVE_CPUMASK_OF_CPU_MAP=y
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_FTRACE_NMI_ENTER=y
+CONFIG_HAVE_FUNCTION_GRAPH_FP_TEST=y
+CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KERNEL_BZIP2=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KVM=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y
+CONFIG_HAVE_MMIOTRACE_SUPPORT=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_PCSPKR_PLATFORM=y
+CONFIG_HAVE_PERF_EVENTS_NMI=y
+CONFIG_HAVE_SETUP_PER_CPU_AREA=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_TEXT_POKE_SMP=y
+CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y
+CONFIG_HAVE_USER_RETURN_NOTIFIER=y
+CONFIG_HID_MICROSOFT=m
+CONFIG_HID_PID=y
+CONFIG_HOSTAP_PCI=m
+CONFIG_HOSTAP_PLX=m
+CONFIG_HOTPLUG_PCI=y
+# CONFIG_HOTPLUG_PCI_ACPI is not set
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+# CONFIG_HOTPLUG_PCI_FAKE is not set
+CONFIG_HOTPLUG_PCI_PCIE=y
+# CONFIG_HOTPLUG_PCI_SHPC is not set
+CONFIG_HPET=y
+CONFIG_HPET_EMULATE_RTC=y
+# CONFIG_HPET_MMAP is not set
+CONFIG_HPET_TIMER=y
+# CONFIG_HP_ACCEL is not set
+CONFIG_HP_WMI=m
+CONFIG_HT_IRQ=y
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HW_RANDOM_AMD is not set
+CONFIG_HW_RANDOM_INTEL=y
+# CONFIG_HW_RANDOM_VIA is not set
+# CONFIG_HW_RANDOM_VIRTIO is not set
+# CONFIG_HYPERV is not set
+CONFIG_HZ=1000
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+CONFIG_I2C_ALGOBIT=y
+CONFIG_I2C_I801=m
+CONFIG_I2C_PIIX4=m
+# CONFIG_I2C_SCMI is not set
+# CONFIG_I7300_IDLE is not set
+# CONFIG_I8K is not set
+# CONFIG_IA32_AOUT is not set
+CONFIG_IA32_EMULATION=y
+# CONFIG_IBM_ASM is not set
+# CONFIG_IBM_RTL is not set
+# CONFIG_IDEAPAD_LAPTOP is not set
+# CONFIG_IDE_PHISON is not set
+CONFIG_IGBVF=m
+CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000
+# CONFIG_INPUT_APANEL is not set
+# CONFIG_INPUT_ATLAS_BTNS is not set
+CONFIG_INPUT_SPARSEKMAP=m
+CONFIG_INSTRUCTION_DECODER=y
+# CONFIG_INTEL_IDLE is not set
+# CONFIG_INTEL_IOMMU is not set
+# CONFIG_INTEL_IPS is not set
+# CONFIG_INTEL_MEI is not set
+CONFIG_INTEL_MENLOW=m
+# CONFIG_INTEL_OAKTRAIL is not set
+# CONFIG_IOMMU_DEBUG is not set
+CONFIG_IOMMU_HELPER=y
+# CONFIG_IOMMU_STRESS is not set
+CONFIG_IO_DELAY_0X80=y
+# CONFIG_IO_DELAY_0XED is not set
+# CONFIG_IO_DELAY_NONE is not set
+CONFIG_IO_DELAY_TYPE_0X80=0
+CONFIG_IO_DELAY_TYPE_0XED=1
+CONFIG_IO_DELAY_TYPE_NONE=3
+CONFIG_IO_DELAY_TYPE_UDELAY=2
+# CONFIG_IO_DELAY_UDELAY is not set
+CONFIG_IPV6=m
+# CONFIG_IP_PNP is not set
+CONFIG_IRQ_FORCED_THREADING=y
+# CONFIG_IRQ_REMAP is not set
+# CONFIG_IRQ_TIME_ACCOUNTING is not set
+# CONFIG_IR_ENE is not set
+# CONFIG_IR_FINTEK is not set
+# CONFIG_IR_IMON is not set
+# CONFIG_IR_ITE_CIR is not set
+# CONFIG_IR_JVC_DECODER is not set
+# CONFIG_IR_LIRC_CODEC is not set
+# CONFIG_IR_MCEUSB is not set
+CONFIG_IR_MCE_KBD_DECODER=m
+# CONFIG_IR_NEC_DECODER is not set
+# CONFIG_IR_NUVOTON is not set
+# CONFIG_IR_RC5_DECODER is not set
+# CONFIG_IR_RC5_SZ_DECODER is not set
+# CONFIG_IR_RC6_DECODER is not set
+# CONFIG_IR_REDRAT3 is not set
+# CONFIG_IR_SONY_DECODER is not set
+# CONFIG_IR_STREAMZAP is not set
+# CONFIG_IR_WINBOND_CIR is not set
+CONFIG_ISA_DMA_API=y
+# CONFIG_ISCSI_IBFT_FIND is not set
+CONFIG_IWL3945=m
+CONFIG_IWL4965=m
+CONFIG_IWLAGN=m
+# CONFIG_IWLWIFI_DEBUG is not set
+# CONFIG_IWLWIFI_DEBUGFS is not set
+# CONFIG_IWLWIFI_DEVICE_SVTOOL is not set
+# CONFIG_IWLWIFI_DEVICE_TRACING is not set
+CONFIG_IWLWIFI_LEGACY=m
+# CONFIG_IWLWIFI_LEGACY_DEBUG is not set
+# CONFIG_IWLWIFI_LEGACY_DEBUGFS is not set
+# CONFIG_IWLWIFI_LEGACY_DEVICE_TRACING is not set
+# CONFIG_IWL_P2P is not set
+CONFIG_JME=m
+# CONFIG_JUMP_LABEL is not set
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_XZ is not set
+CONFIG_KEYS_COMPAT=y
+# CONFIG_KSZ884X_PCI is not set
+# CONFIG_KTIME_SCALAR is not set
+# CONFIG_KVM is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_LEDS_ALIX2 is not set
+# CONFIG_LEDS_CLEVO_MAIL is not set
+# CONFIG_LEDS_DELL_NETBOOKS is not set
+# CONFIG_LEDS_INTEL_SS4200 is not set
+CONFIG_LIBERTAS_THINFIRM_USB=m
+CONFIG_LIRC=m
+# CONFIG_LIRC_STAGING is not set
+CONFIG_LPC_SCH=m
+# CONFIG_MACINTOSH_DRIVERS is not set
+# CONFIG_MATOM is not set
+# CONFIG_MAXSMP is not set
+# CONFIG_MCORE2 is not set
+# CONFIG_MEMORY_FAILURE is not set
+# CONFIG_MEMORY_HOTPLUG is not set
+# CONFIG_MEMTEST is not set
+CONFIG_MFD_CORE=m
+# CONFIG_MFD_CS5535 is not set
+# CONFIG_MFD_TPS6586X is not set
+# CONFIG_MFD_TPS6591X is not set
+CONFIG_MICROCODE=y
+CONFIG_MICROCODE_AMD=y
+CONFIG_MICROCODE_INTEL=y
+CONFIG_MICROCODE_OLD_INTERFACE=y
+# CONFIG_MK8 is not set
+# CONFIG_MMC is not set
+# CONFIG_MMIOTRACE is not set
+CONFIG_MOUSE_APPLETOUCH=m
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_ELANTECH=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+# CONFIG_MOUSE_PS2_SENTELIC is not set
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MPSC is not set
+# CONFIG_MSI_LAPTOP is not set
+# CONFIG_MSI_WMI is not set
+CONFIG_MTRR=y
+# CONFIG_MTRR_SANITIZER is not set
+# CONFIG_MWAVE is not set
+# CONFIG_MXM_WMI is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y
+CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y
+CONFIG_NEED_SG_DMA_LENGTH=y
+# CONFIG_NETWORK_FILESYSTEMS is not set
+CONFIG_NET_PCI=y
+# CONFIG_NET_SB1000 is not set
+CONFIG_NO_BOOTMEM=y
+CONFIG_NR_CPUS=4
+# CONFIG_NUMA is not set
+CONFIG_NVRAM=y
+CONFIG_OPTIMIZE_INLINING=y
+CONFIG_OUTPUT_FORMAT="elf64-x86-64"
+CONFIG_PAGEFLAGS_EXTENDED=y
+# CONFIG_PANASONIC_LAPTOP is not set
+# CONFIG_PARAVIRT_GUEST is not set
+# CONFIG_PATA_ACPI is not set
+# CONFIG_PATA_ALI is not set
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_ATP867X is not set
+# CONFIG_PATA_CMD640_PCI is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
+# CONFIG_PATA_CS5536 is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_IT8213 is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_LEGACY is not set
+# CONFIG_PATA_MARVELL is not set
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NINJA32 is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_NS87415 is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_PLATFORM is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RDC is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_SC1200 is not set
+# CONFIG_PATA_SCH is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+# CONFIG_PATA_TOSHIBA is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_VIA is not set
+# CONFIG_PATA_WINBOND is not set
+CONFIG_PCIEAER=y
+# CONFIG_PCIEAER_INJECT is not set
+CONFIG_PCIEASPM=y
+# CONFIG_PCIEASPM_DEBUG is not set
+CONFIG_PCIEPORTBUS=y
+# CONFIG_PCIE_ECRC is not set
+CONFIG_PCIE_PME=y
+# CONFIG_PCI_CNB20LE_QUIRK is not set
+CONFIG_PCI_DIRECT=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_IOAPIC=y
+CONFIG_PCI_LABEL=y
+CONFIG_PCI_MMCONFIG=y
+CONFIG_PCI_MSI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_PCSPKR_PLATFORM is not set
+# CONFIG_PDC_ADMA is not set
+CONFIG_PHYSICAL_ALIGN=0x1000000
+CONFIG_PHYSICAL_START=0x1000000
+CONFIG_PHYS_ADDR_T_64BIT=y
+CONFIG_PM_TRACE=y
+CONFIG_PM_TRACE_RTC=y
+CONFIG_PNP=y
+CONFIG_PNPACPI=y
+CONFIG_PNP_DEBUG_MESSAGES=y
+# CONFIG_PROCESSOR_SELECT is not set
+CONFIG_PROC_KCORE=y
+CONFIG_PROVIDE_OHCI1394_DMA_INIT=y
+# CONFIG_R6040 is not set
+# CONFIG_R8169 is not set
+# CONFIG_RAPIDIO is not set
+CONFIG_RC_CORE=m
+# CONFIG_RC_LOOPBACK is not set
+CONFIG_RC_MAP=m
+CONFIG_REALTEK_AUTOPM=y
+# CONFIG_REGULATOR is not set
+# CONFIG_RELOCATABLE is not set
+# CONFIG_REPORT_PRESENT_CPUS is not set
+# CONFIG_RT2500USB is not set
+# CONFIG_RT2800USB is not set
+# CONFIG_RT73USB is not set
+CONFIG_RTC_DRV_CMOS=m
+# CONFIG_RTC_HCTOSYS is not set
+CONFIG_RTL8192CE=m
+CONFIG_RTL8192C_COMMON=m
+CONFIG_RTLWIFI=m
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+# CONFIG_SAMSUNG_LAPTOP is not set
+# CONFIG_SAMSUNG_Q10 is not set
+# CONFIG_SATA_ACARD_AHCI is not set
+CONFIG_SATA_AHCI=y
+# CONFIG_SATA_AHCI_PLATFORM is not set
+# CONFIG_SATA_INIC162X is not set
+# CONFIG_SATA_MV is not set
+# CONFIG_SATA_NV is not set
+# CONFIG_SATA_PMP is not set
+# CONFIG_SATA_PROMISE is not set
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_SIL is not set
+# CONFIG_SATA_SIL24 is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_SVW is not set
+# CONFIG_SATA_SX4 is not set
+# CONFIG_SATA_ULI is not set
+# CONFIG_SATA_VIA is not set
+# CONFIG_SATA_VITESSE is not set
+# CONFIG_SC92031 is not set
+CONFIG_SCHED_HRTICK=y
+CONFIG_SCHED_MC=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_SMT=y
+CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_ABITUGURU3 is not set
+# CONFIG_SENSORS_ACPI_POWER is not set
+# CONFIG_SENSORS_APPLESMC is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATK0110 is not set
+CONFIG_SENSORS_CORETEMP=y
+# CONFIG_SENSORS_FAM15H_POWER is not set
+# CONFIG_SENSORS_FSCHMD is not set
+# CONFIG_SENSORS_HDAPS is not set
+# CONFIG_SENSORS_ISL29018 is not set
+# CONFIG_SENSORS_ISL29028 is not set
+# CONFIG_SENSORS_K10TEMP is not set
+# CONFIG_SENSORS_K8TEMP is not set
+# CONFIG_SENSORS_NCT1008 is not set
+# CONFIG_SENSORS_VIA_CPUTEMP is not set
+# CONFIG_SERIAL_8250 is not set
+CONFIG_SERIO_CT82C710=m
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_PCIPS2=m
+# CONFIG_SFI is not set
+# CONFIG_SIGMA is not set
+# CONFIG_SIS900 is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SLAB is not set
+# CONFIG_SLICOSS is not set
+CONFIG_SLUB=y
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+# CONFIG_SMSC9420 is not set
+# CONFIG_SND_ALS4000 is not set
+# CONFIG_SND_ASIHPI is not set
+# CONFIG_SND_CS5530 is not set
+CONFIG_SND_DMA_SGBUF=y
+CONFIG_SND_HDA_CODEC_ANALOG=y
+CONFIG_SND_HDA_CODEC_CA0110=y
+CONFIG_SND_HDA_CODEC_CA0132=y
+CONFIG_SND_HDA_CODEC_CIRRUS=y
+CONFIG_SND_HDA_CODEC_CMEDIA=y
+CONFIG_SND_HDA_CODEC_CONEXANT=y
+CONFIG_SND_HDA_CODEC_HDMI=y
+CONFIG_SND_HDA_CODEC_REALTEK=y
+CONFIG_SND_HDA_CODEC_SI3054=y
+CONFIG_SND_HDA_CODEC_SIGMATEL=y
+CONFIG_SND_HDA_CODEC_VIA=y
+CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS=y
+CONFIG_SND_HDA_GENERIC=y
+CONFIG_SND_HDA_HWDEP=y
+# CONFIG_SND_HDA_INPUT_BEEP is not set
+CONFIG_SND_HDA_INPUT_JACK=y
+CONFIG_SND_HDA_INTEL=m
+# CONFIG_SND_HDA_PATCH_LOADER is not set
+# CONFIG_SND_HDA_PLATFORM_DRIVER is not set
+CONFIG_SND_HDA_POWER_SAVE=y
+CONFIG_SND_HDA_POWER_SAVE_DEFAULT=5
+CONFIG_SND_HDA_PREALLOC_SIZE=64
+# CONFIG_SND_HDA_RECONFIG is not set
+CONFIG_SND_PCM=m
+# CONFIG_SND_SOC is not set
+CONFIG_SND_TIMER=m
+# CONFIG_SND_USB_US122L is not set
+# CONFIG_SND_USB_USX2Y is not set
+CONFIG_SND_VMASTER=y
+# CONFIG_SOC_CAMERA is not set
+# CONFIG_SONY_LAPTOP is not set
+CONFIG_SPARSEMEM=y
+CONFIG_SPARSEMEM_ALLOC_MEM_MAP_TOGETHER=y
+CONFIG_SPARSEMEM_EXTREME=y
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM_VMEMMAP=y
+CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
+CONFIG_SPARSE_IRQ=y
+# CONFIG_SQUASHFS is not set
+# CONFIG_SSB is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_SWAP is not set
+CONFIG_SWIOTLB=y
+CONFIG_SYSVIPC_COMPAT=y
+# CONFIG_TCG_INFINEON is not set
+CONFIG_TCG_TIS=y
+# CONFIG_TELCLOCK is not set
+# CONFIG_THINKPAD_ACPI is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_TLAN is not set
+# CONFIG_TOPSTAR_LAPTOP is not set
+# CONFIG_TOSHIBA_BT_RFKILL is not set
+# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set
+# CONFIG_TRANSPARENT_HUGEPAGE is not set
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+CONFIG_USB_NET_CDC_NCM=m
+CONFIG_USB_NET_DM9601=m
+CONFIG_USB_NET_MCS7830=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_RNDIS_HOST=m
+CONFIG_USB_NET_SMSC95XX=m
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_RTL8150 is not set
+CONFIG_USB_STORAGE_REALTEK=y
+CONFIG_USB_UHCI_HCD=y
+CONFIG_USB_USBNET=m
+CONFIG_USER_STACKTRACE_SUPPORT=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
+# CONFIG_VGA_ARB is not set
+CONFIG_VGA_CONSOLE=y
+# CONFIG_VGA_SWITCHEROO is not set
+# CONFIG_VHOST_NET is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_VIDEO_BT848 is not set
+# CONFIG_VIDEO_CX231XX is not set
+# CONFIG_VIDEO_CX88 is not set
+# CONFIG_VIDEO_GO7007 is not set
+# CONFIG_VIDEO_IR_I2C is not set
+# CONFIG_VIDEO_IVTV is not set
+# CONFIG_VIDEO_TM6000 is not set
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_ZORAN is not set
+CONFIG_VIRTIO=m
+CONFIG_VIRTIO_BLK=m
+# CONFIG_VIRTIO_CONSOLE is not set
+CONFIG_VIRTIO_NET=m
+CONFIG_VIRTIO_PCI=m
+CONFIG_VIRTIO_RING=m
+CONFIG_VIRTUALIZATION=y
+# CONFIG_VMWARE_BALLOON is not set
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_X86=y
+# CONFIG_X86_32 is not set
+CONFIG_X86_64=y
+CONFIG_X86_64_SMP=y
+CONFIG_X86_ACPI_CPUFREQ=y
+CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK=y
+CONFIG_X86_CHECK_BIOS_CORRUPTION=y
+CONFIG_X86_CMOV=y
+CONFIG_X86_CMPXCHG=y
+CONFIG_X86_CMPXCHG64=y
+CONFIG_X86_CPUID=y
+CONFIG_X86_DEBUGCTLMSR=y
+CONFIG_X86_EXTENDED_PLATFORM=y
+CONFIG_X86_HT=y
+CONFIG_X86_INTERNODE_CACHE_SHIFT=6
+CONFIG_X86_IO_APIC=y
+CONFIG_X86_L1_CACHE_SHIFT=6
+CONFIG_X86_LOCAL_APIC=y
+CONFIG_X86_MCE=y
+# CONFIG_X86_MCE_AMD is not set
+# CONFIG_X86_MCE_INJECT is not set
+CONFIG_X86_MCE_INTEL=y
+CONFIG_X86_MCE_THRESHOLD=y
+CONFIG_X86_MINIMUM_CPU_FAMILY=64
+CONFIG_X86_MPPARSE=y
+CONFIG_X86_MSR=y
+# CONFIG_X86_P4_CLOCKMOD is not set
+CONFIG_X86_PAT=y
+# CONFIG_X86_PCC_CPUFREQ is not set
+CONFIG_X86_PLATFORM_DEVICES=y
+CONFIG_X86_PM_TIMER=y
+# CONFIG_X86_POWERNOW_K8 is not set
+# CONFIG_X86_PTDUMP is not set
+CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y
+CONFIG_X86_RESERVE_LOW=64
+# CONFIG_X86_SPEEDSTEP_CENTRINO is not set
+# CONFIG_X86_SPEEDSTEP_LIB is not set
+CONFIG_X86_SUPPORTS_MEMORY_FAILURE=y
+CONFIG_X86_THERMAL_VECTOR=y
+CONFIG_X86_TSC=y
+CONFIG_X86_VERBOSE_BOOTUP=y
+# CONFIG_X86_VSMP is not set
+CONFIG_X86_WP_WORKS_OK=y
+CONFIG_X86_XADD=y
+CONFIG_XFRM_USER=y
+# CONFIG_XO15_EBOOK is not set
+# CONFIG_ZD1211RW is not set
+CONFIG_ZONE_DMA=y
+CONFIG_ZONE_DMA32=y
+CONFIG_ZONE_DMA_FLAG=1
diff --git a/chromeos/config/x86_64/config.flavour.chromeos-intel-pineview b/chromeos/config/x86_64/config.flavour.chromeos-intel-pineview
new file mode 100644
index 000000000000..fad4bbee31e2
--- /dev/null
+++ b/chromeos/config/x86_64/config.flavour.chromeos-intel-pineview
@@ -0,0 +1,3 @@
+#
+# Config options generated by splitconfig
+#
diff --git a/chromeos/scripts/allconfigs b/chromeos/scripts/allconfigs
new file mode 100755
index 000000000000..16431991d4da
--- /dev/null
+++ b/chromeos/scripts/allconfigs
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+bindir="`pwd`/chromeos/scripts"
+confdir="`pwd`/chromeos/config"
+
+get_flavourconfigs() {
+ for file in `find $confdir`; do
+ if echo $file | egrep -q "config\.flavour\..*[^~]$"; then
+ basename $file | awk -F . '{ print $3 }'
+ fi
+ done
+}
+
+get_arch() {
+ if find . -name config.flavour.$1 | grep -q i386; then
+ echo i386
+ else
+ echo arm
+ fi
+}
+
+for flavour in $(get_flavourconfigs); do
+ echo $flavour $(get_arch $flavour)
+ $bindir/prepareconfig $flavour
+ yes "" | make ARCH=$(get_arch $flavour) oldconfig
+ cp .config .config-$flavour
+done
+
diff --git a/chromeos/scripts/kernelconfig b/chromeos/scripts/kernelconfig
new file mode 100755
index 000000000000..c056c8c6086f
--- /dev/null
+++ b/chromeos/scripts/kernelconfig
@@ -0,0 +1,123 @@
+#!/bin/bash
+
+# Script to merge all configs and run 'make silentoldconfig' on it to wade out bad juju.
+# Then split the configs into distro-commmon and flavour-specific parts
+
+# We have to be in the top level kernel source directory
+if [ ! -f MAINTAINERS ] || [ ! -f Makefile ]; then
+ echo "This does not appear to be the kernel source directory." 1>&2
+ exit 1
+fi
+
+mode=${1:?"Usage: $0 [oldconfig|editconfig]"}
+case "$mode" in
+ oldconfig) ;; # All is good
+ editconfig) ;; # All is good
+ genconfig) ;; # All is good
+ *) echo "$0 called with invalid mode" 1>&2
+ exit 1 ;;
+esac
+kerneldir="`pwd`"
+confdir="$kerneldir/chromeos/config"
+archs="x86_64 i386 armel"
+family='chromeos'
+bindir="`pwd`/chromeos/scripts"
+common_conf="$confdir/config.common.$family"
+tmpdir=`mktemp -d`
+
+if [ "$mode" = "genconfig" ]; then
+ keep=1
+ mode="oldconfig"
+ test -d CONFIGS || mkdir CONFIGS
+fi
+
+test -d build || mkdir build
+
+for arch in $archs; do
+ # Map debian archs to kernel archs
+ case "$arch" in
+ amd64) kernarch="x86_64" ;;
+ lpia) kernarch="x86" ;;
+ sparc) kernarch="sparc64" ;;
+ armel) kernarch="arm" ;;
+ *) kernarch="$arch" ;;
+ esac
+
+ echo ""
+ echo "***************************************"
+ echo "* Processing $arch ($kernarch) ... "
+ archconfdir=$confdir/$arch
+ flavourconfigs=$(cd $archconfdir && ls config.flavour.*[^~])
+
+ # Merge configs
+ # We merge config.common.ubuntu + config.common.<arch> +
+ # config.flavour.<flavour>
+
+ for config in $flavourconfigs; do
+ fullconf="$tmpdir/$arch-$config-full"
+ case $config in
+ *)
+ : >"$fullconf"
+ if [ -f $common_conf ]; then
+ cat $common_conf >> "$fullconf"
+ fi
+ if [ -f $archconfdir/config.common.$arch ]; then
+ cat $archconfdir/config.common.$arch >> "$fullconf"
+ fi
+ cat "$archconfdir/$config" >>"$fullconf"
+ ;;
+ esac
+ done
+
+ for config in $flavourconfigs; do
+ if [ -f $archconfdir/$config ]; then
+ fullconf="$tmpdir/$arch-$config-full"
+ cat "$fullconf" > build/.config
+ # Call oldconfig or menuconfig
+ case "$mode" in
+ oldconfig)
+ # Weed out incorrect config parameters
+ echo "* Run silentoldconfig on $arch/$config ..."
+ make O=`pwd`/build ARCH=$kernarch silentoldconfig ;;
+ editconfig)
+ # Interactively edit config parameters
+ echo " * Run menuconfig on $arch/$config... Press a key."
+ read
+ make O=`pwd`/build ARCH=$kernarch menuconfig ;;
+ *) # Bad!
+ exit 1 ;;
+ esac
+ cat build/.config > $archconfdir/$config
+ if [ "$keep" = "1" ]; then
+ cat build/.config > CONFIGS/$arch-$config
+ fi
+ else
+ echo "!! Config not found $archconfdir/$config..."
+ fi
+ done
+
+ echo "Running splitconfig for $arch"
+ echo
+
+ # Can we make this more robust by avoiding $tmpdir completely?
+ # This approach was used for now because I didn't want to change
+ # splitconfig
+ (cd $archconfdir; rm config.common.$arch; $bindir/splitconfig; \
+ mv config.common config.common.$arch; \
+ cp config.common.$arch $tmpdir)
+done
+
+rm -f $common_conf
+
+# Now run splitconfig on all the config.common.<arch> copied to
+# $tmpdir
+(cd $tmpdir; $bindir/splitconfig)
+(
+ cd $confdir;
+ rm -f *-full
+ grep -v 'is UNMERGABLE' <$tmpdir/config.common >$common_conf
+ for arch in $archs; do
+ grep -v 'is UNMERGABLE' <$tmpdir/config.common.$arch \
+ >$arch/config.common.$arch
+ done
+)
diff --git a/chromeos/scripts/prepareconfig b/chromeos/scripts/prepareconfig
new file mode 100755
index 000000000000..b82cf35919fe
--- /dev/null
+++ b/chromeos/scripts/prepareconfig
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+family=chromeos
+
+flavourconf=$(find ${family} -name config.flavour.$1)
+if [ ! -f "${flavourconf}" ]; then
+ echo "Found no flavour configuration for '$1'." 1>&2
+ exit 1
+fi
+
+outputfile="${2:-.config}"
+
+archconfdir=$(dirname ${flavourconf})
+
+# Generate .config
+cat ${family}/config/config.common.${family} \
+ ${archconfdir}/config.common.* \
+ "${flavourconf}" > "${outputfile}"
diff --git a/chromeos/scripts/splitconfig b/chromeos/scripts/splitconfig
new file mode 100755
index 000000000000..262fa2015c1d
--- /dev/null
+++ b/chromeos/scripts/splitconfig
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+
+import os
+import re
+import sys
+
+allconfigs = {}
+
+# Parse config files
+for config in os.listdir("."):
+ # Only config.*
+ if not config.startswith("config."):
+ continue
+ # Ignore emacs backups
+ if config.endswith("~"):
+ continue
+ # Nothing that is disabled, or remnant
+ if re.search("\.(default|disabled|stub)$", config):
+ continue
+
+ allconfigs[config] = set()
+
+ for line in open(config):
+ m = re.match("#*\s*CONFIG_(\w+)[\s=](.*)$", line)
+ if not m:
+ continue
+ option, value = m.groups()
+ allconfigs[config].add((option, value))
+
+# Split out common config options
+common = allconfigs.values()[0].copy()
+for config in allconfigs.keys():
+ common &= allconfigs[config]
+for config in allconfigs.keys():
+ allconfigs[config] -= common
+allconfigs["config.common"] = common
+
+# Generate new splitconfigs
+for config in allconfigs.keys():
+ f = open(config, "w")
+ command = os.path.basename(sys.argv[0])
+ print >>f, "#\n# Config options generated by %s\n#" % command
+ for option, value in sorted(list(allconfigs[config])):
+ if value == "is not set":
+ print >>f, "# CONFIG_%s %s" % (option, value)
+ else:
+ print >>f, "CONFIG_%s=%s" % (option, value)
+
+ f.close()
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 5987e0ba8c2d..3807e572aef7 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -83,6 +83,23 @@ config SATA_AHCI_PLATFORM
If unsure, say N.
+config SATA_AHCI_TEGRA
+ tristate "TEGRA AHCI SATA support"
+ depends on ARCH_TEGRA_3x_SOC
+ help
+ This option enables support for TEGRA AHCI Serial ATA.
+
+ If unsure, say N.
+
+config TEGRA_SATA_IDLE_POWERGATE
+ bool "TEGRA SATA idle power-gating"
+ depends on SATA_AHCI_TEGRA && PM && PM_RUNTIME
+ help
+ This option enables power-gating during SATA idling.
+ This option should not be enabled if sata clocks are in dvfs_table.
+
+ If unsure, say N.
+
config SATA_FSL
tristate "Freescale 3.0Gbps SATA support"
depends on FSL_SOC
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index 9550d691fd19..4245ecf30f05 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -3,6 +3,7 @@ obj-$(CONFIG_ATA) += libata.o
# non-SFF interface
obj-$(CONFIG_SATA_AHCI) += ahci.o libahci.o
+obj-$(CONFIG_SATA_AHCI_TEGRA) += ahci-tegra.o libahci.o
obj-$(CONFIG_SATA_ACARD_AHCI) += acard-ahci.o libahci.o
obj-$(CONFIG_SATA_AHCI_PLATFORM) += ahci_platform.o libahci.o
obj-$(CONFIG_SATA_FSL) += sata_fsl.o
diff --git a/drivers/ata/ahci-tegra.c b/drivers/ata/ahci-tegra.c
new file mode 100644
index 000000000000..5c58da143c5a
--- /dev/null
+++ b/drivers/ata/ahci-tegra.c
@@ -0,0 +1,2154 @@
+/*
+ * ahci-tegra.c - AHCI SATA support for TEGRA AHCI device
+ *
+ * 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 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/>.
+ *
+ *
+ * libata documentation is available via 'make {ps|pdf}docs',
+ * as Documentation/DocBook/libata.*
+ *
+ * AHCI hardware documentation:
+ * http://www.intel.com/technology/serialata/pdf/rev1_0.pdf
+ * http://www.intel.com/technology/serialata/pdf/rev1_1.pdf
+ *
+ */
+
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/device.h>
+#include <linux/dmi.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_cmnd.h>
+#include <linux/libata.h>
+#include <linux/regulator/machine.h>
+#include <linux/pm_runtime.h>
+#include "ahci.h"
+
+#include <linux/clk.h>
+#include <mach/clk.h>
+#include <mach/iomap.h>
+#include <mach/io.h>
+#include <mach/powergate.h>
+
+#define DRV_NAME "tegra-sata"
+#define DRV_VERSION "1.0"
+
+#define ENABLE_AHCI_DBG_PRINT 0
+#if ENABLE_AHCI_DBG_PRINT
+#define AHCI_DBG_PRINT(fmt, arg...) printk(KERN_ERR fmt, ## arg)
+#else
+#define AHCI_DBG_PRINT(fmt, arg...) do {} while (0)
+#endif
+
+/* number of AHCI ports */
+#define TEGRA_AHCI_NUM_PORTS 1
+
+/* idle timeout for PM in msec */
+#define TEGRA_AHCI_MIN_IDLE_TIME 1000
+#define TEGRA_AHCI_DEFAULT_IDLE_TIME 2000
+
+#ifdef CONFIG_TEGRA_SATA_IDLE_POWERGATE
+static u32 tegra_ahci_idle_time = TEGRA_AHCI_DEFAULT_IDLE_TIME;
+#endif
+
+/* Bit 0 (EN_FPCI) to allow FPCI accesses to SATA */
+#define SATA_CONFIGURATION_0_OFFSET 0x180
+#define EN_FPCI (1 << 0)
+
+#define SATA_INTR_MASK_0_OFFSET 0x188
+#define IP_INT_MASK (1 << 16)
+
+/* Need to write 0x00400200 to 0x70020094 */
+#define SATA_FPCI_BAR5_0_OFFSET 0x094
+#define PRI_ICTLR_CPU_IER_SET_0_OFFSET 0x024
+#define CPU_IER_SATA_CTL (1 << 23)
+
+#define AHCI_BAR5_CONFIG_LOCATION 0x24
+#define TEGRA_SATA_BAR5_INIT_PROGRAM 0xFFFFFFFF
+#define TEGRA_SATA_BAR5_FINAL_PROGRAM 0x40020000
+
+#define FUSE_SATA_CALIB_OFFSET 0x224
+#define FUSE_SATA_CALIB_MASK 0x3
+
+#define T_SATA0_CFG_PHY_REG 0x120
+#define PHY_USE_7BIT_ALIGN_DET_FOR_SPD_MASK (1 << 11)
+
+#define T_SATA0_CFG_POWER_GATE 0x4ac
+#define POWER_GATE_SSTS_RESTORED_MASK (1 << 23)
+#define POWER_GATE_SSTS_RESTORED_YES (1 << 23)
+#define POWER_GATE_SSTS_RESTORED_NO (0 << 23)
+
+#define T_SATA0_DBG0_OFFSET 0x550
+
+#define T_SATA0_INDEX_OFFSET 0x680
+#define SATA0_NONE_SELECTED 0
+#define SATA0_CH1_SELECTED (1 << 0)
+
+#define T_SATA0_CHX_PHY_CTRL1_GEN1_OFFSET 0x690
+#define SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_SHIFT 0
+#define SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_MASK (0xff << 0)
+#define SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_SHIFT 8
+#define SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_MASK (0xff << 8)
+
+#define T_SATA0_CHX_PHY_CTRL1_GEN2_OFFSET 0x694
+#define SATA0_CHX_PHY_CTRL1_GEN2_TX_AMP_SHIFT 0
+#define SATA0_CHX_PHY_CTRL1_GEN2_TX_AMP_MASK (0xff << 0)
+#define SATA0_CHX_PHY_CTRL1_GEN2_TX_PEAK_SHIFT 12
+#define SATA0_CHX_PHY_CTRL1_GEN2_TX_PEAK_MASK (0xff << 12)
+#define SATA0_CHX_PHY_CTRL1_GEN2_RX_EQ_SHIFT 24
+#define SATA0_CHX_PHY_CTRL1_GEN2_RX_EQ_MASK (0xf << 24)
+
+/* AHCI config space defines */
+#define TEGRA_PRIVATE_AHCI_CC_BKDR 0x4a4
+#define TEGRA_PRIVATE_AHCI_CC_BKDR_OVERRIDE 0x54c
+#define TEGRA_PRIVATE_AHCI_CC_BKDR_OVERRIDE_EN (1 << 12)
+#define TEGRA_PRIVATE_AHCI_CC_BKDR_PGM 0x01060100
+
+/* AHCI HBA_CAP */
+#define TEGRA_PRIVATE_AHCI_CAP_BKDR 0xa0
+#define T_SATA0_AHCI_HBA_CAP_BKDR 0x300
+
+#define TEGRA_SATA_IO_SPACE_OFFSET 4
+#define TEGRA_SATA_ENABLE_IO_SPACE (1 << 0)
+#define TEGRA_SATA_ENABLE_MEM_SPACE (1 << 1)
+#define TEGRA_SATA_ENABLE_BUS_MASTER (1 << 2)
+#define TEGRA_SATA_ENABLE_SERR (1 << 8)
+
+#define TEGRA_SATA_CORE_CLOCK_FREQ_HZ (108*1000*1000)
+#define TEGRA_SATA_OOB_CLOCK_FREQ_HZ (216*1000*1000)
+
+#define APB_PMC_SATA_PWRGT_0_REG 0x1ac
+#define CLK_RST_SATA_PLL_CFG0_REG 0x490
+#define CLK_RST_SATA_PLL_CFG1_REG 0x494
+#define SATA_AUX_PAD_PLL_CNTL_1_REG 0x1100
+#define SATA_AUX_MISC_CNTL_1_REG 0x1108
+
+/* for APB_PMC_SATA_PWRGT_0_REG */
+#define PG_INFO_MASK (1 << 6)
+#define PG_INFO_ON (1 << 6)
+#define PG_INFO_OFF (0 << 6)
+#define PLLE_IDDQ_SWCTL_MASK (1 << 4)
+#define PLLE_IDDQ_SWCTL_ON (1 << 4)
+#define PLLE_IDDQ_SWCTL_OFF (0 << 4)
+#define PADPHY_IDDQ_OVERRIDE_VALUE_MASK (1 << 3)
+#define PADPHY_IDDQ_OVERRIDE_VALUE_ON (1 << 3)
+#define PADPHY_IDDQ_OVERRIDE_VALUE_OFF (0 << 3)
+#define PADPHY_IDDQ_SWCTL_MASK (1 << 2)
+#define PADPHY_IDDQ_SWCTL_ON (1 << 2)
+#define PADPHY_IDDQ_SWCTL_OFF (0 << 2)
+#define PADPLL_IDDQ_OVERRIDE_VALUE_MASK (1 << 1)
+#define PADPLL_IDDQ_OVERRIDE_VALUE_ON (1 << 1)
+#define PADPLL_IDDQ_OVERRIDE_VALUE_OFF (0 << 1)
+#define PADPLL_IDDQ_SWCTL_MASK (1 << 0)
+#define PADPLL_IDDQ_SWCTL_ON (1 << 0)
+#define PADPLL_IDDQ_SWCTL_OFF (0 << 0)
+
+/* for CLK_RST_SATA_PLL_CFG0_REG */
+#define PADPLL_RESET_OVERRIDE_VALUE_MASK (1 << 1)
+#define PADPLL_RESET_OVERRIDE_VALUE_ON (1 << 1)
+#define PADPLL_RESET_OVERRIDE_VALUE_OFF (0 << 1)
+#define PADPLL_RESET_SWCTL_MASK (1 << 0)
+#define PADPLL_RESET_SWCTL_ON (1 << 0)
+#define PADPLL_RESET_SWCTL_OFF (0 << 0)
+
+/* for CLK_RST_SATA_PLL_CFG1_REG */
+#define IDDQ2LANE_SLUMBER_DLY_MASK (0xffL << 16)
+#define IDDQ2LANE_SLUMBER_DLY_SHIFT 16
+#define IDDQ2LANE_SLUMBER_DLY_3MS (3 << 16)
+#define IDDQ2LANE_IDDQ_DLY_SHIFT 0
+#define IDDQ2LANE_IDDQ_DLY_MASK (0xffL << 0)
+
+/* for SATA_AUX_PAD_PLL_CNTL_1_REG */
+#define REFCLK_SEL_MASK (3 << 11)
+#define REFCLK_SEL_INT_CML (0 << 11)
+#define LOCKDET_FIELD (1 << 6)
+
+/* for SATA_AUX_MISC_CNTL_1_REG */
+#define NVA2SATA_OOB_ON_POR_MASK (1 << 7)
+#define NVA2SATA_OOB_ON_POR_YES (1 << 7)
+#define NVA2SATA_OOB_ON_POR_NO (0 << 7)
+#define L0_RX_IDLE_T_SAX_SHIFT 5
+#define L0_RX_IDLE_T_SAX_MASK (3 << 5)
+#define L0_RX_IDLE_T_NPG_SHIFT 3
+#define L0_RX_IDLE_T_NPG_MASK (3 << 3)
+#define L0_RX_IDLE_T_MUX_MASK (1 << 2)
+#define L0_RX_IDLE_T_MUX_FROM_APB_MISC (1 << 2)
+#define L0_RX_IDLE_T_MUX_FROM_SATA (0 << 2)
+
+#define SSTAT_IPM_STATE_MASK 0xF00
+#define SSTAT_IPM_SLUMBER_STATE 0x600
+
+enum {
+ AHCI_PCI_BAR = 5,
+};
+
+enum port_idle_status {
+ PORT_IS_NOT_IDLE,
+ PORT_IS_IDLE,
+ PORT_IS_IDLE_NOT_SLUMBER,
+ PORT_IS_SLUMBER,
+};
+
+enum sata_state {
+ SATA_ON,
+ SATA_OFF,
+ SATA_GOING_ON,
+ SATA_GOING_OFF,
+ SATA_ABORT_OFF,
+};
+
+char *sata_power_rails[] = {
+ "avdd_sata",
+ "vdd_sata",
+ "hvdd_sata",
+ "avdd_sata_pll"
+};
+
+#define NUM_SATA_POWER_RAILS ARRAY_SIZE(sata_power_rails)
+
+struct tegra_qc_list {
+ struct list_head list;
+ struct ata_queued_cmd *qc;
+};
+
+/*
+ * tegra_ahci_host_priv is the extension of ahci_host_priv
+ * with extra fields: idle_timer, pg_save, pg_state, etc.
+ */
+struct tegra_ahci_host_priv {
+ struct ahci_host_priv ahci_host_priv;
+ struct regulator *power_rails[NUM_SATA_POWER_RAILS];
+ void __iomem *bars_table[6];
+ struct ata_host *host;
+ struct timer_list idle_timer;
+ struct device *dev;
+ void *pg_save;
+ enum sata_state pg_state;
+ struct list_head qc_list;
+};
+
+static int tegra_ahci_init_one(struct platform_device *pdev);
+static int tegra_ahci_remove_one(struct platform_device *pdev);
+
+#ifdef CONFIG_PM
+static bool tegra_ahci_power_un_gate(struct ata_host *host);
+static bool tegra_ahci_power_gate(struct ata_host *host);
+static void tegra_ahci_abort_power_gate(struct ata_host *host);
+static int tegra_ahci_controller_suspend(struct platform_device *pdev);
+static int tegra_ahci_controller_resume(struct platform_device *pdev);
+static int tegra_ahci_suspend(struct platform_device *pdev, pm_message_t mesg);
+static int tegra_ahci_resume(struct platform_device *pdev);
+static enum port_idle_status tegra_ahci_is_port_idle(struct ata_port *ap);
+static enum port_idle_status tegra_ahci_is_port_slumber(struct ata_port *ap);
+static bool tegra_ahci_are_all_ports_idle(struct ata_host *host);
+static bool tegra_ahci_are_all_ports_slumber(struct ata_host *host);
+#ifdef CONFIG_TEGRA_SATA_IDLE_POWERGATE
+static unsigned int tegra_ahci_qc_issue(struct ata_queued_cmd *qc);
+static int tegra_ahci_hardreset(struct ata_link *link, unsigned int *class,
+ unsigned long deadline);
+static int tegra_ahci_runtime_suspend(struct device *dev);
+static int tegra_ahci_runtime_resume(struct device *dev);
+static void tegra_ahci_idle_timer(unsigned long arg);
+static int tegra_ahci_queue_one_qc(struct tegra_ahci_host_priv *tegra_hpriv,
+ struct ata_queued_cmd *qc);
+static void tegra_ahci_dequeue_qcs(struct tegra_ahci_host_priv *tegra_hpriv);
+#endif
+#else
+#define tegra_ahci_controller_suspend NULL
+#define tegra_ahci_controller_resume NULL
+#define tegra_ahci_suspend NULL
+#define tegra_ahci_resume NULL
+#endif
+
+static struct scsi_host_template ahci_sht = {
+ AHCI_SHT("tegra-sata"),
+};
+
+static struct ata_port_operations tegra_ahci_ops = {
+ .inherits = &ahci_ops,
+#ifdef CONFIG_PM
+#ifdef CONFIG_TEGRA_SATA_IDLE_POWERGATE
+ .qc_issue = tegra_ahci_qc_issue,
+ .hardreset = tegra_ahci_hardreset,
+#endif
+#endif
+};
+
+static const struct ata_port_info ahci_port_info = {
+ .flags = AHCI_FLAG_COMMON,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .udma_mask = ATA_UDMA6,
+ .port_ops = &tegra_ahci_ops,
+};
+
+#ifdef CONFIG_TEGRA_SATA_IDLE_POWERGATE
+static const struct dev_pm_ops tegra_ahci_dev_rt_ops = {
+ .runtime_suspend = tegra_ahci_runtime_suspend,
+ .runtime_resume = tegra_ahci_runtime_resume,
+};
+#endif
+
+static struct platform_driver tegra_platform_ahci_driver = {
+ .probe = tegra_ahci_init_one,
+ .remove = __devexit_p(tegra_ahci_remove_one),
+#ifdef CONFIG_PM
+ .suspend = tegra_ahci_suspend,
+ .resume = tegra_ahci_resume,
+ .driver = {
+ .name = DRV_NAME,
+#ifdef CONFIG_TEGRA_SATA_IDLE_POWERGATE
+ .pm = &tegra_ahci_dev_rt_ops,
+#endif
+ }
+#else
+ .driver = {
+ .name = DRV_NAME,
+ }
+#endif
+};
+
+struct tegra_ahci_host_priv *g_tegra_hpriv;
+
+static inline u32 pmc_readl(u32 offset)
+{
+ u32 val;
+ val = readl(IO_ADDRESS(TEGRA_PMC_BASE + offset));
+ AHCI_DBG_PRINT("[0x%x] => 0x%08x\n", TEGRA_PMC_BASE+offset, val);
+ return val;
+}
+
+static inline void pmc_writel(u32 val, u32 offset)
+{
+ AHCI_DBG_PRINT("[0x%x] <= 0x%08x\n", TEGRA_PMC_BASE+offset, val);
+ writel(val, IO_ADDRESS(TEGRA_PMC_BASE + offset));
+}
+
+static inline u32 clk_readl(u32 offset)
+{
+ u32 val;
+
+ val = readl(IO_ADDRESS(TEGRA_CLK_RESET_BASE + offset));
+ AHCI_DBG_PRINT("[0x%x] => 0x%08x\n", TEGRA_CLK_RESET_BASE+offset, val);
+ return val;
+}
+
+static inline void clk_writel(u32 val, u32 offset)
+{
+ AHCI_DBG_PRINT("[0x%x] <= 0x%08x\n", TEGRA_CLK_RESET_BASE+offset, val);
+ writel(val, IO_ADDRESS(TEGRA_CLK_RESET_BASE + offset));
+}
+
+static inline u32 misc_readl(u32 offset)
+{
+ u32 val;
+
+ val = readl(IO_ADDRESS(TEGRA_APB_MISC_BASE + offset));
+ AHCI_DBG_PRINT("[0x%x] => 0x%08x\n", TEGRA_APB_MISC_BASE+offset, val);
+ return val;
+}
+
+static inline void misc_writel(u32 val, u32 offset)
+{
+ AHCI_DBG_PRINT("[0x%x] <= 0x%08x\n", TEGRA_APB_MISC_BASE+offset, val);
+ writel(val, IO_ADDRESS(TEGRA_APB_MISC_BASE + offset));
+}
+
+static inline u32 sata_readl(u32 offset)
+{
+ u32 val;
+
+ val = readl(IO_ADDRESS(TEGRA_SATA_BASE + offset));
+ AHCI_DBG_PRINT("[0x%x] => 0x%08x\n", TEGRA_SATA_BASE+offset, val);
+ return val;
+}
+
+static inline void sata_writel(u32 val, u32 offset)
+{
+ AHCI_DBG_PRINT("[0x%x] <= 0x%08x\n", TEGRA_SATA_BASE+offset, val);
+ writel(val, IO_ADDRESS(TEGRA_SATA_BASE + offset));
+}
+
+static inline u32 scfg_readl(u32 offset)
+{
+ u32 val;
+
+ val = readl(IO_ADDRESS(TEGRA_SATA_CONFIG_BASE + offset));
+ AHCI_DBG_PRINT("[0x%x] => 0x%08x\n", TEGRA_SATA_CONFIG_BASE+offset,
+ val);
+ return val;
+}
+
+static inline void scfg_writel(u32 val, u32 offset)
+{
+ AHCI_DBG_PRINT("[0x%x] <= 0x%08x\n", TEGRA_SATA_CONFIG_BASE+offset,
+ val);
+ writel(val, IO_ADDRESS(TEGRA_SATA_CONFIG_BASE + offset));
+}
+
+static inline u32 pictlr_readl(u32 offset)
+{
+ u32 val;
+
+ val = readl(IO_ADDRESS(TEGRA_PRIMARY_ICTLR_BASE + offset));
+ AHCI_DBG_PRINT("[0x%x] => 0x%08x\n", TEGRA_PRIMARY_ICTLR_BASE+offset,
+ val);
+ return val;
+}
+
+static inline void pictlr_writel(u32 val, u32 offset)
+{
+ AHCI_DBG_PRINT("[0x%x] <= 0x%08x\n", TEGRA_PRIMARY_ICTLR_BASE+offset,
+ val);
+ writel(val, IO_ADDRESS(TEGRA_PRIMARY_ICTLR_BASE + offset));
+}
+
+static inline u32 fuse_readl(u32 offset)
+{
+ u32 val;
+
+ val = readl(IO_ADDRESS(TEGRA_FUSE_BASE + offset));
+ AHCI_DBG_PRINT("[0x%x] => 0x%08x\n", TEGRA_FUSE_BASE+offset, val);
+
+ return val;
+}
+
+/* Sata Pad Cntrl Values */
+struct sata_pad_cntrl {
+ u8 gen1_tx_amp;
+ u8 gen1_tx_peak;
+ u8 gen2_tx_amp;
+ u8 gen2_tx_peak;
+};
+
+static const struct sata_pad_cntrl sata_calib_pad_val[] = {
+ { /* SATA_CALIB[1:0] = 00 */
+ 0x0c,
+ 0x04,
+ 0x0e,
+ 0x0a
+ },
+ { /* SATA_CALIB[1:0] = 01 */
+ 0x0e,
+ 0x04,
+ 0x14,
+ 0x0a
+ },
+ { /* SATA_CALIB[1:0] = 10 */
+ 0x0e,
+ 0x07,
+ 0x1a,
+ 0x0e
+ },
+ { /* SATA_CALIB[1:0] = 11 */
+ 0x14,
+ 0x0e,
+ 0x1a,
+ 0x0e
+ }
+};
+
+static void tegra_ahci_set_pad_cntrl_regs(void)
+{
+ int calib_val;
+ int val;
+ int i;
+
+ calib_val = fuse_readl(FUSE_SATA_CALIB_OFFSET) & FUSE_SATA_CALIB_MASK;
+
+ for (i = 0; i < TEGRA_AHCI_NUM_PORTS; ++i) {
+ scfg_writel((1 << i), T_SATA0_INDEX_OFFSET);
+
+ val = scfg_readl(T_SATA0_CHX_PHY_CTRL1_GEN1_OFFSET);
+ val &= ~SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_MASK;
+ val |= (sata_calib_pad_val[calib_val].gen1_tx_amp <<
+ SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_SHIFT);
+ scfg_writel(val, T_SATA0_CHX_PHY_CTRL1_GEN1_OFFSET);
+
+ val = scfg_readl(T_SATA0_CHX_PHY_CTRL1_GEN1_OFFSET);
+ val &= ~SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_MASK;
+ val |= (sata_calib_pad_val[calib_val].gen1_tx_peak <<
+ SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_SHIFT);
+ scfg_writel(val, T_SATA0_CHX_PHY_CTRL1_GEN1_OFFSET);
+
+ val = scfg_readl(T_SATA0_CHX_PHY_CTRL1_GEN2_OFFSET);
+ val &= ~SATA0_CHX_PHY_CTRL1_GEN2_TX_AMP_MASK;
+ val |= (sata_calib_pad_val[calib_val].gen2_tx_amp <<
+ SATA0_CHX_PHY_CTRL1_GEN2_TX_AMP_SHIFT);
+ scfg_writel(val, T_SATA0_CHX_PHY_CTRL1_GEN2_OFFSET);
+
+ val = scfg_readl(T_SATA0_CHX_PHY_CTRL1_GEN2_OFFSET);
+ val &= ~SATA0_CHX_PHY_CTRL1_GEN2_TX_PEAK_MASK;
+ val |= (sata_calib_pad_val[calib_val].gen2_tx_peak <<
+ SATA0_CHX_PHY_CTRL1_GEN2_TX_PEAK_SHIFT);
+ scfg_writel(val, T_SATA0_CHX_PHY_CTRL1_GEN2_OFFSET);
+
+ /* set 2 to SATA0_CHX_PHY_CTRL1_GEN2_RX_EQ field */
+ val = scfg_readl(T_SATA0_CHX_PHY_CTRL1_GEN2_OFFSET);
+ val &= ~SATA0_CHX_PHY_CTRL1_GEN2_RX_EQ_MASK;
+ val |= (2 << SATA0_CHX_PHY_CTRL1_GEN2_RX_EQ_SHIFT);
+ scfg_writel(val, T_SATA0_CHX_PHY_CTRL1_GEN2_OFFSET);
+ }
+ scfg_writel(SATA0_NONE_SELECTED, T_SATA0_INDEX_OFFSET);
+}
+
+int tegra_ahci_get_rails(struct regulator *regulators[])
+{
+ struct regulator *reg;
+ int i;
+ int ret = 0;
+
+ for (i = 0; i < NUM_SATA_POWER_RAILS; ++i) {
+ reg = regulator_get(NULL, sata_power_rails[i]);
+ if (IS_ERR_OR_NULL(reg)) {
+ pr_err("%s: can't get regulator %s\n",
+ __func__, sata_power_rails[i]);
+ WARN_ON(1);
+ ret = PTR_ERR(reg);
+ goto exit;
+ }
+ regulators[i] = reg;
+ }
+exit:
+ return ret;
+}
+
+void tegra_ahci_put_rails(struct regulator *regulators[])
+{
+ int i;
+
+ for (i = 0; i < NUM_SATA_POWER_RAILS; ++i)
+ regulator_put(regulators[i]);
+}
+
+int tegra_ahci_power_on_rails(struct regulator *regulators[])
+{
+ struct regulator *reg;
+ int i;
+ int ret = 0;
+
+ for (i = 0; i < NUM_SATA_POWER_RAILS; ++i) {
+ reg = regulators[i];
+ ret = regulator_enable(reg);
+ if (ret) {
+ pr_err("%s: can't enable regulator[%d]\n",
+ __func__, i);
+ WARN_ON(1);
+ goto exit;
+ }
+ }
+
+exit:
+ return ret;
+}
+
+int tegra_ahci_power_off_rails(struct regulator *regulators[])
+{
+ struct regulator *reg;
+ int i;
+ int ret = 0;
+
+ for (i = 0; i < NUM_SATA_POWER_RAILS; ++i) {
+ reg = regulators[i];
+ if (!IS_ERR_OR_NULL(reg)) {
+ ret = regulator_disable(reg);
+ if (ret) {
+ pr_err("%s: can't disable regulator[%d]\n",
+ __func__, i);
+ WARN_ON(1);
+ goto exit;
+ }
+ }
+ }
+
+exit:
+ return ret;
+}
+static int tegra_ahci_controller_init(struct tegra_ahci_host_priv *tegra_hpriv)
+{
+ int err;
+ struct clk *clk_sata = NULL;
+ struct clk *clk_sata_oob = NULL;
+ struct clk *clk_sata_cold = NULL;
+ struct clk *clk_pllp = NULL;
+ u32 val;
+ u32 timeout;
+
+ err = tegra_ahci_get_rails(tegra_hpriv->power_rails);
+ if (err) {
+ pr_err("%s: fails to get rails (%d)\n", __func__, err);
+ goto exit;
+ }
+
+ err = tegra_ahci_power_on_rails(tegra_hpriv->power_rails);
+ if (err) {
+ pr_err("%s: fails to power on rails (%d)\n", __func__, err);
+ goto exit;
+ }
+
+ /* pll_p is the parent of tegra_sata and tegra_sata_oob */
+ clk_pllp = clk_get_sys(NULL, "pll_p");
+ if (IS_ERR_OR_NULL(clk_pllp)) {
+ pr_err("%s: unable to get PLL_P clock\n", __func__);
+ err = -ENODEV;
+ goto exit;
+ }
+
+ clk_sata = clk_get_sys("tegra_sata", NULL);
+ if (IS_ERR_OR_NULL(clk_sata)) {
+ pr_err("%s: unable to get SATA clock\n", __func__);
+ err = -ENODEV;
+ goto exit;
+ }
+
+ clk_sata_oob = clk_get_sys("tegra_sata_oob", NULL);
+ if (IS_ERR_OR_NULL(clk_sata_oob)) {
+ pr_err("%s: unable to get SATA OOB clock\n", __func__);
+ err = -ENODEV;
+ goto exit;
+ }
+
+ clk_sata_cold = clk_get_sys("tegra_sata_cold", NULL);
+ if (IS_ERR_OR_NULL(clk_sata_cold)) {
+ pr_err("%s: unable to get SATA COLD clock\n", __func__);
+ err = -ENODEV;
+ goto exit;
+ }
+
+ tegra_periph_reset_assert(clk_sata);
+ tegra_periph_reset_assert(clk_sata_oob);
+ tegra_periph_reset_assert(clk_sata_cold);
+ udelay(10);
+
+ /* need to establish both clocks divisors before setting clk sources */
+ clk_set_rate(clk_sata, clk_get_rate(clk_sata)/10);
+ clk_set_rate(clk_sata_oob, clk_get_rate(clk_sata_oob)/10);
+
+ /* set SATA clk and SATA_OOB clk source */
+ clk_set_parent(clk_sata, clk_pllp);
+ clk_set_parent(clk_sata_oob, clk_pllp);
+
+ /* Configure SATA clocks */
+ /* Core clock runs at 108MHz */
+ if (clk_set_rate(clk_sata, TEGRA_SATA_CORE_CLOCK_FREQ_HZ)) {
+ err = -ENODEV;
+ goto exit;
+ }
+ /* OOB clock runs at 216MHz */
+ if (clk_set_rate(clk_sata_oob, TEGRA_SATA_OOB_CLOCK_FREQ_HZ)) {
+ err = -ENODEV;
+ goto exit;
+ }
+
+ /**** Init the SATA PAD PLL ****/
+ /* SATA_PADPLL_IDDQ_SWCTL=1 and SATA_PADPLL_IDDQ_OVERRIDE_VALUE=1 */
+ val = pmc_readl(APB_PMC_SATA_PWRGT_0_REG);
+ val &= ~(PADPLL_IDDQ_SWCTL_MASK | PADPLL_IDDQ_OVERRIDE_VALUE_MASK);
+ val |= (PADPLL_IDDQ_SWCTL_ON | PADPLL_IDDQ_OVERRIDE_VALUE_ON);
+ pmc_writel(val, APB_PMC_SATA_PWRGT_0_REG);
+
+ /* SATA_PADPLL_RESET_OVERRIDE_VALUE=1 and SATA_PADPLL_RESET_SWCTL=1 */
+ val = clk_readl(CLK_RST_SATA_PLL_CFG0_REG);
+ val &= ~(PADPLL_RESET_OVERRIDE_VALUE_MASK | PADPLL_RESET_SWCTL_MASK);
+ val |= (PADPLL_RESET_OVERRIDE_VALUE_ON | PADPLL_RESET_SWCTL_ON);
+ clk_writel(val, CLK_RST_SATA_PLL_CFG0_REG);
+
+ /* SATA_PADPHY_IDDQ_OVERRIDE_VALUE and SATA_PADPHY_IDDQ_SWCTL = 1 */
+ val = pmc_readl(APB_PMC_SATA_PWRGT_0_REG);
+ val &= ~(PADPHY_IDDQ_OVERRIDE_VALUE_MASK | PADPHY_IDDQ_SWCTL_MASK);
+ val |= (PADPHY_IDDQ_OVERRIDE_VALUE_ON | PADPHY_IDDQ_SWCTL_ON);
+ pmc_writel(val, APB_PMC_SATA_PWRGT_0_REG);
+
+ /* Get SATA pad PLL out of IDDQ mode */
+ val = pmc_readl(APB_PMC_SATA_PWRGT_0_REG);
+ val &= ~PADPLL_IDDQ_OVERRIDE_VALUE_MASK;
+ val |= PADPLL_IDDQ_OVERRIDE_VALUE_OFF;
+ pmc_writel(val, APB_PMC_SATA_PWRGT_0_REG);
+ udelay(3);
+
+ /* select internal CML ref clk
+ * select PLLE as input to IO phy */
+ val = misc_readl(SATA_AUX_PAD_PLL_CNTL_1_REG);
+ val &= ~REFCLK_SEL_MASK;
+ val |= REFCLK_SEL_INT_CML;
+ misc_writel(val, SATA_AUX_PAD_PLL_CNTL_1_REG);
+
+ /* wait for SATA_PADPLL_IDDQ2LANE_SLUMBER_DLY = 3 microseconds. */
+ val = clk_readl(CLK_RST_SATA_PLL_CFG1_REG);
+ val &= ~IDDQ2LANE_SLUMBER_DLY_MASK;
+ val |= IDDQ2LANE_SLUMBER_DLY_3MS;
+ clk_writel(val, CLK_RST_SATA_PLL_CFG1_REG);
+ udelay(3);
+
+ /* de-assert IDDQ mode signal going to PHY */
+ val = pmc_readl(APB_PMC_SATA_PWRGT_0_REG);
+ val &= ~PADPHY_IDDQ_OVERRIDE_VALUE_MASK;
+ val |= PADPHY_IDDQ_OVERRIDE_VALUE_OFF;
+ pmc_writel(val, APB_PMC_SATA_PWRGT_0_REG);
+
+ err = tegra_unpowergate_partition_with_clk_on(TEGRA_POWERGATE_SATA);
+ if (err) {
+ pr_err("%s: ** failed to turn-on SATA (0x%x) **\n",
+ __func__, err);
+ goto exit;
+ }
+
+ /*
+ * place SATA Pad PLL out of reset by writing
+ * SATA_PADPLL_RST_OVERRIDE_VALUE = 0
+ */
+ val = clk_readl(CLK_RST_SATA_PLL_CFG0_REG);
+ val &= ~PADPLL_RESET_OVERRIDE_VALUE_MASK;
+ val |= PADPLL_RESET_OVERRIDE_VALUE_OFF;
+ clk_writel(val, CLK_RST_SATA_PLL_CFG0_REG);
+
+ /*
+ * Wait for SATA_AUX_PAD_PLL_CNTL_1_0_LOCKDET to turn 1 with a timeout
+ * of 15 us.
+ */
+ timeout = 15;
+ while (timeout--) {
+ udelay(1);
+ val = misc_readl(SATA_AUX_PAD_PLL_CNTL_1_REG);
+ if (val & LOCKDET_FIELD)
+ break;
+ }
+ if (timeout == 0)
+ pr_err("%s: AUX_PAD_PLL_CNTL_1 (0x%x) is not locked in 15us.\n",
+ __func__, val);
+
+ /* clear SW control of SATA PADPLL, SATA PHY and PLLE */
+ val = pmc_readl(APB_PMC_SATA_PWRGT_0_REG);
+ val &= ~(PADPLL_IDDQ_SWCTL_MASK | PADPHY_IDDQ_SWCTL_MASK |
+ PLLE_IDDQ_SWCTL_MASK);
+ val |= (PADPLL_IDDQ_SWCTL_OFF | PADPHY_IDDQ_SWCTL_OFF |
+ PLLE_IDDQ_SWCTL_OFF);
+ pmc_writel(val, APB_PMC_SATA_PWRGT_0_REG);
+
+ val = clk_readl(CLK_RST_SATA_PLL_CFG0_REG);
+ val &= ~PADPLL_RESET_SWCTL_MASK;
+ val |= PADPLL_RESET_SWCTL_OFF;
+ clk_writel(val, CLK_RST_SATA_PLL_CFG0_REG);
+
+ /* clear NVA2SATA_OOB_ON_POR in SATA_AUX_MISC_CNTL_1_REG */
+ val = misc_readl(SATA_AUX_MISC_CNTL_1_REG);
+ val &= ~NVA2SATA_OOB_ON_POR_MASK;
+ misc_writel(val, SATA_AUX_MISC_CNTL_1_REG);
+
+ val = sata_readl(SATA_CONFIGURATION_0_OFFSET);
+ val |= EN_FPCI;
+ sata_writel(val, SATA_CONFIGURATION_0_OFFSET);
+
+ /* program sata pad control based on the fuse */
+ tegra_ahci_set_pad_cntrl_regs();
+
+ /*
+ * clear bit T_SATA0_CFG_PHY_0_USE_7BIT_ALIGN_DET_FOR_SPD of
+ * T_SATA0_CFG_PHY_0
+ */
+ val = scfg_readl(T_SATA0_CFG_PHY_REG);
+ val &= ~PHY_USE_7BIT_ALIGN_DET_FOR_SPD_MASK;
+ scfg_writel(val, T_SATA0_CFG_PHY_REG);
+
+ /*
+ * WAR: Before enabling SATA PLL shutdown, lockdet needs to be ignored.
+ * To ignore lockdet, T_SATA0_DBG0_OFFSET register bit 10 needs to
+ * be 1, and bit 8 needs to be 0.
+ */
+ val = scfg_readl(T_SATA0_DBG0_OFFSET);
+ val |= (1 << 10);
+ val &= ~(1 << 8);
+ scfg_writel(val, T_SATA0_DBG0_OFFSET);
+
+ /* program class code and programming interface for AHCI */
+ val = scfg_readl(TEGRA_PRIVATE_AHCI_CC_BKDR_OVERRIDE);
+ val |= TEGRA_PRIVATE_AHCI_CC_BKDR_OVERRIDE_EN;
+ scfg_writel(val, TEGRA_PRIVATE_AHCI_CC_BKDR_OVERRIDE);
+ scfg_writel(TEGRA_PRIVATE_AHCI_CC_BKDR_PGM, TEGRA_PRIVATE_AHCI_CC_BKDR);
+ val &= ~TEGRA_PRIVATE_AHCI_CC_BKDR_OVERRIDE_EN;
+ scfg_writel(val, TEGRA_PRIVATE_AHCI_CC_BKDR_OVERRIDE);
+
+ /* Program config space registers: */
+
+ /* Enable BUS_MASTER+MEM+IO space, and SERR */
+ val = scfg_readl(TEGRA_SATA_IO_SPACE_OFFSET);
+ val |= TEGRA_SATA_ENABLE_IO_SPACE | TEGRA_SATA_ENABLE_MEM_SPACE |
+ TEGRA_SATA_ENABLE_BUS_MASTER | TEGRA_SATA_ENABLE_SERR;
+ scfg_writel(val, TEGRA_SATA_IO_SPACE_OFFSET);
+
+ /* program bar5 space, by first writing 1's to bar5 register */
+ scfg_writel(TEGRA_SATA_BAR5_INIT_PROGRAM, AHCI_BAR5_CONFIG_LOCATION);
+ /* flush */
+ val = scfg_readl(AHCI_BAR5_CONFIG_LOCATION);
+
+ /* then, write the BAR5_FINAL_PROGRAM address */
+ scfg_writel(TEGRA_SATA_BAR5_FINAL_PROGRAM, AHCI_BAR5_CONFIG_LOCATION);
+ /* flush */
+ scfg_readl(AHCI_BAR5_CONFIG_LOCATION);
+
+ sata_writel((TEGRA_SATA_BAR5_FINAL_PROGRAM >> 8),
+ SATA_FPCI_BAR5_0_OFFSET);
+
+ val = scfg_readl(T_SATA0_AHCI_HBA_CAP_BKDR);
+ val |= (HOST_CAP_ALPM | HOST_CAP_SSC | HOST_CAP_PART);
+ scfg_writel(val, T_SATA0_AHCI_HBA_CAP_BKDR);
+
+ /* enable Interrupt channel */
+ val = pictlr_readl(PRI_ICTLR_CPU_IER_SET_0_OFFSET);
+ val |= CPU_IER_SATA_CTL;
+ pictlr_writel(val, PRI_ICTLR_CPU_IER_SET_0_OFFSET);
+
+ /* set IP_INT_MASK */
+ val = sata_readl(SATA_INTR_MASK_0_OFFSET);
+ val |= IP_INT_MASK;
+ sata_writel(val, SATA_INTR_MASK_0_OFFSET);
+
+exit:
+ if (!IS_ERR_OR_NULL(clk_pllp))
+ clk_put(clk_pllp);
+ if (!IS_ERR_OR_NULL(clk_sata))
+ clk_put(clk_sata);
+ if (!IS_ERR_OR_NULL(clk_sata_oob))
+ clk_put(clk_sata_oob);
+ if (!IS_ERR_OR_NULL(clk_sata_cold))
+ clk_put(clk_sata_cold);
+
+ if (err) {
+ /* turn off all SATA power rails; ignore returned status */
+ tegra_ahci_power_off_rails(tegra_hpriv->power_rails);
+ /* return regulators to system */
+ tegra_ahci_put_rails(tegra_hpriv->power_rails);
+ }
+
+ return err;
+}
+
+static void tegra_ahci_save_initial_config(struct platform_device *pdev,
+ struct ahci_host_priv *hpriv)
+{
+ ahci_save_initial_config(&pdev->dev, hpriv, 0, 0);
+}
+
+static void tegra_ahci_controller_remove(struct platform_device *pdev)
+{
+ struct ata_host *host = dev_get_drvdata(&pdev->dev);
+ struct tegra_ahci_host_priv *tegra_hpriv;
+ int status;
+
+ tegra_hpriv = (struct tegra_ahci_host_priv *)host->private_data;
+
+#ifdef CONFIG_PM
+ /* call tegra_ahci_controller_suspend() to power-down the SATA */
+ status = tegra_ahci_controller_suspend(pdev);
+ if (status)
+ dev_err(host->dev, "remove: error suspend SATA (0x%x)\n",
+ status);
+#else
+ /* power off the sata */
+ status = tegra_powergate_partition_with_clk_off(TEGRA_POWERGATE_SATA);
+ if (status)
+ dev_err(host->dev, "remove: error turn-off SATA (0x%x)\n",
+ status);
+ tegra_ahci_power_off_rails(tegra_hpriv->power_rails);
+#endif
+
+ /* return system resources */
+ tegra_ahci_put_rails(tegra_hpriv->power_rails);
+}
+
+#ifdef CONFIG_PM
+static int tegra_ahci_controller_suspend(struct platform_device *pdev)
+{
+ struct ata_host *host = dev_get_drvdata(&pdev->dev);
+ struct tegra_ahci_host_priv *tegra_hpriv;
+ unsigned long flags;
+
+ tegra_hpriv = (struct tegra_ahci_host_priv *)host->private_data;
+
+ /* stop the idle timer */
+ if (timer_pending(&tegra_hpriv->idle_timer))
+ del_timer_sync(&tegra_hpriv->idle_timer);
+
+ spin_lock_irqsave(&host->lock, flags);
+ if (tegra_hpriv->pg_state == SATA_OFF)
+ dev_dbg(host->dev, "suspend: SATA already power gated\n");
+ else {
+ bool pg_ok;
+
+ dev_dbg(host->dev, "suspend: power gating SATA...\n");
+ pg_ok = tegra_ahci_power_gate(host);
+ if (pg_ok) {
+ tegra_hpriv->pg_state = SATA_OFF;
+ dev_dbg(host->dev, "suspend: SATA is power gated\n");
+ } else {
+ dev_err(host->dev, "suspend: abort power gating\n");
+ tegra_ahci_abort_power_gate(host);
+ spin_unlock_irqrestore(&host->lock, flags);
+ return -EBUSY;
+ }
+ }
+ spin_unlock_irqrestore(&host->lock, flags);
+
+ return tegra_ahci_power_off_rails(tegra_hpriv->power_rails);
+}
+
+static int tegra_ahci_controller_resume(struct platform_device *pdev)
+{
+ struct ata_host *host = dev_get_drvdata(&pdev->dev);
+ struct tegra_ahci_host_priv *tegra_hpriv;
+ unsigned long flags;
+ int err;
+
+ tegra_hpriv = (struct tegra_ahci_host_priv *)host->private_data;
+
+ err = tegra_ahci_power_on_rails(tegra_hpriv->power_rails);
+ if (err) {
+ pr_err("%s: fails to power on rails (%d)\n", __func__, err);
+ return err;
+ }
+
+ spin_lock_irqsave(&host->lock, flags);
+ if (!tegra_hpriv->pg_state == SATA_ON) {
+ dev_dbg(host->dev, "resume: SATA already powered on\n");
+ } else {
+ dev_dbg(host->dev, "resume: powering on SATA...\n");
+ tegra_ahci_power_un_gate(host);
+ tegra_hpriv->pg_state = SATA_ON;
+ }
+ spin_unlock_irqrestore(&host->lock, flags);
+
+ return 0;
+}
+
+static int tegra_ahci_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+ struct ata_host *host = dev_get_drvdata(&pdev->dev);
+ void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
+ u32 ctl;
+ int rc;
+
+ dev_dbg(host->dev, "** entering %s: **\n", __func__);
+ if (mesg.event & PM_EVENT_SLEEP) {
+ /*
+ * AHCI spec rev1.1 section 8.3.3:
+ * Software must disable interrupts prior to requesting a
+ * transition of the HBA to D3 state.
+ */
+ ctl = readl(mmio + HOST_CTL);
+ ctl &= ~HOST_IRQ_EN;
+ writel(ctl, mmio + HOST_CTL);
+ readl(mmio + HOST_CTL); /* flush */
+ }
+
+ rc = ata_host_suspend(host, mesg);
+ if (rc)
+ return rc;
+
+ return tegra_ahci_controller_suspend(pdev);
+}
+
+static int tegra_ahci_resume(struct platform_device *pdev)
+{
+ struct ata_host *host = dev_get_drvdata(&pdev->dev);
+ int rc;
+
+ dev_dbg(host->dev, "** entering %s: **\n", __func__);
+ rc = tegra_ahci_controller_resume(pdev);
+ if (rc)
+ return rc;
+
+ if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
+ rc = ahci_reset_controller(host);
+ if (rc)
+ return rc;
+
+ ahci_init_controller(host);
+ }
+
+ ata_host_resume(host);
+ return 0;
+}
+
+#ifdef CONFIG_TEGRA_SATA_IDLE_POWERGATE
+static int tegra_ahci_runtime_suspend(struct device *dev)
+{
+ struct ata_host *host;
+ struct tegra_ahci_host_priv *tegra_hpriv;
+ bool pg_ok;
+ unsigned long flags;
+ int err = 0;
+
+ host = dev_get_drvdata(dev);
+ tegra_hpriv = (struct tegra_ahci_host_priv *)host->private_data;
+
+ spin_lock_irqsave(&host->lock, flags);
+
+ switch (tegra_hpriv->pg_state) {
+ case SATA_OFF:
+ dev_dbg(dev, "** rt-suspend: already power gated **\n");
+ break;
+
+ case SATA_ABORT_OFF:
+ dev_dbg(dev, "** rt-suspend: abort suspend **\n");
+ pm_runtime_get_noresume(dev);
+ tegra_hpriv->pg_state = SATA_ON;
+ tegra_ahci_dequeue_qcs(tegra_hpriv);
+ err = -EBUSY;
+ break;
+
+ case SATA_ON:
+ case SATA_GOING_OFF:
+ if (tegra_ahci_are_all_ports_idle(host)) {
+ /* if all ports are in idle, do power-gate */
+ dev_dbg(dev, "** rt-suspend: power-down sata (%u) **\n",
+ tegra_hpriv->pg_state);
+ pg_ok = tegra_ahci_power_gate(host);
+ dev_dbg(dev, "** rt-suspend: done **\n");
+ if (pg_ok) {
+ tegra_hpriv->pg_state = SATA_OFF;
+ } else {
+ dev_err(dev, "** rt-suspend: abort pg **\n");
+ tegra_ahci_abort_power_gate(host);
+ tegra_hpriv->pg_state = SATA_ON;
+ err = -EBUSY;
+ }
+ } else {
+ dev_dbg(dev, "** rt-suspend: port not idle (%u) **\n",
+ tegra_hpriv->pg_state);
+ err = -EBUSY;
+ }
+ break;
+
+ case SATA_GOING_ON:
+ default:
+ dev_err(dev, "** rt-suspend: bad state (%u) **\n",
+ tegra_hpriv->pg_state);
+ WARN_ON(1);
+ err = -EBUSY;
+ break;
+
+ }
+
+ spin_unlock_irqrestore(&host->lock, flags);
+
+ return err;
+}
+
+static int tegra_ahci_runtime_resume(struct device *dev)
+{
+ struct ata_host *host;
+ struct tegra_ahci_host_priv *tegra_hpriv;
+ unsigned long flags;
+ int err = 0;
+
+ host = dev_get_drvdata(dev);
+ tegra_hpriv = (struct tegra_ahci_host_priv *)host->private_data;
+
+ spin_lock_irqsave(&host->lock, flags);
+
+ if (tegra_hpriv->pg_state == SATA_ON) {
+ dev_dbg(dev, "** rt-resume: already power ungated **\n");
+ goto exit;
+ }
+
+ if ((tegra_hpriv->pg_state == SATA_OFF) ||
+ (tegra_hpriv->pg_state == SATA_GOING_ON)) {
+ dev_dbg(dev, "** rt-resume: power-up sata (%u) **\n",
+ tegra_hpriv->pg_state);
+ tegra_ahci_power_un_gate(host);
+ dev_dbg(dev, "** rt-resume: done **\n");
+ tegra_hpriv->pg_state = SATA_ON;
+
+ /* now qc_issue all qcs in the qc_list */
+ tegra_ahci_dequeue_qcs(tegra_hpriv);
+ } else {
+ dev_err(dev, "** rt-resume: bad state (%u) **\n",
+ tegra_hpriv->pg_state);
+ WARN_ON(1);
+ err = -EBUSY;
+ }
+
+exit:
+ spin_unlock_irqrestore(&host->lock, flags);
+ return err;
+}
+#endif
+
+static u16 pg_save_bar5_registers[] = {
+ 0x018, /* T_AHCI_HBA_CCC_PORTS */
+ 0x004, /* T_AHCI_HBA_GHC */
+ 0x014, /* T_AHCI_HBA_CCC_CTL - OP (optional) */
+ 0x01C, /* T_AHCI_HBA_EM_LOC */
+ 0x020 /* T_AHCI_HBA_EM_CTL - OP */
+};
+
+static u16 pg_save_bar5_port_registers[] = {
+ 0x100, /* T_AHCI_PORT_PXCLB */
+ 0x104, /* T_AHCI_PORT_PXCLBU */
+ 0x108, /* T_AHCI_PORT_PXFB */
+ 0x10C, /* T_AHCI_PORT_PXFBU */
+ 0x114, /* T_AHCI_PORT_PXIE */
+ 0x118, /* T_AHCI_PORT_PXCMD */
+ 0x12C /* T_AHCI_PORT_PXSCTL */
+};
+
+/*
+ * pg_save_bar5_bkdr_registers:
+ * These registers in BAR5 are read only.
+ * To restore back those register values, write the saved value
+ * to the registers specified in pg_restore_bar5_bkdr_registers[].
+ * These pg_restore_bar5_bkdr_registers[] are in SATA_CONFIG space.
+ */
+static u16 pg_save_bar5_bkdr_registers[] = {
+ /* Save and restore via bkdr writes */
+ 0x000, /* T_AHCI_HBA_CAP */
+ 0x00C, /* T_AHCI_HBA_PI */
+ 0x024 /* T_AHCI_HBA_CAP2 */
+};
+
+static u16 pg_restore_bar5_bkdr_registers[] = {
+ /* Save and restore via bkdr writes */
+ 0x300, /* BKDR of T_AHCI_HBA_CAP */
+ 0x33c, /* BKDR of T_AHCI_HBA_PI */
+ 0x330 /* BKDR of T_AHCI_HBA_CAP2 */
+};
+
+/* These registers are saved for each port */
+static u16 pg_save_bar5_bkdr_port_registers[] = {
+ 0x120, /* NV_PROJ__SATA0_CHX_AHCI_PORT_PXTFD */
+ 0x124, /* NV_PROJ__SATA0_CHX_AHCI_PORT_PXSIG */
+ 0x128 /* NV_PROJ__SATA0_CHX_AHCI_PORT_PXSSTS */
+};
+
+static u16 pg_restore_bar5_bkdr_port_registers[] = {
+ /* Save and restore via bkdr writes */
+ 0x790, /* BKDR of NV_PROJ__SATA0_CHX_AHCI_PORT_PXTFD */
+ 0x794, /* BKDR of NV_PROJ__SATA0_CHX_AHCI_PORT_PXSIG */
+ 0x798 /* BKDR of NV_PROJ__SATA0_CHX_AHCI_PORT_PXSSTS */
+};
+
+static u16 pg_save_config_registers[] = {
+ 0x004, /* T_SATA0_CFG_1 */
+ 0x00C, /* T_SATA0_CFG_3 */
+ 0x024, /* T_SATA0_CFG_9 */
+ 0x028, /* T_SATA0_CFG_10 */
+ 0x030, /* T_SATA0_CFG_12 */
+ 0x034, /* T_SATA0_CFG_13 */
+ 0x038, /* T_SATA0_CFG_14 */
+ 0x03C, /* T_SATA0_CFG_15 */
+ 0x040, /* T_SATA0_CFG_16 */
+ 0x044, /* T_SATA0_CFG_17 */
+ 0x048, /* T_SATA0_CFG_18 */
+ 0x0B0, /* T_SATA0_MSI_CTRL */
+ 0x0B4, /* T_SATA0_MSI_ADDR1 */
+ 0x0B8, /* T_SATA0_MSI_ADDR2 */
+ 0x0BC, /* T_SATA0_MSI_DATA */
+ 0x0C0, /* T_SATA0_MSI_QUEUE */
+ 0x0EC, /* T_SATA0_MSI_MAP */
+ 0x124, /* T_SATA0_CFG_PHY_POWER */
+ 0x128, /* T_SATA0_CFG_PHY_POWER_1 */
+ 0x12C, /* T_SATA0_CFG_PHY_1 */
+ 0x174, /* T_SATA0_CFG_LINK_0 */
+ 0x178, /* T_SATA0_CFG_LINK_1 */
+ 0x1D0, /* MCP_SATA0_CFG_TRANS_0 */
+ 0x238, /* T_SATA0_ALPM_CTRL */
+ 0x30C, /* T_SATA0_AHCI_HBA_CYA_0 */
+ 0x320, /* T_SATA0_AHCI_HBA_SPARE_1 */
+ 0x324, /* T_SATA0_AHCI_HBA_SPARE_2 */
+ 0x328, /* T_SATA0_AHCI_HBA_DYN_CLK_CLAMP */
+ 0x32C, /* T_SATA0_AHCI_CFG_ERR_CTRL */
+ 0x338, /* T_SATA0_AHCI_HBA_CYA_1 */
+ 0x340, /* T_SATA0_AHCI_HBA_PRE_STAGING_CONTROL */
+ 0x430, /* T_SATA0_CFG_FPCI_0 */
+ 0x494, /* T_SATA0_CFG_ESATA_CTRL */
+ 0x4A0, /* T_SATA0_CYA1 */
+ 0x4B0, /* T_SATA0_CFG_GLUE */
+ 0x534, /* T_SATA0_PHY_CTRL */
+ 0x540, /* T_SATA0_CTRL */
+ 0x550, /* T_SATA0_DBG0 */
+ 0x554 /* T_SATA0_LOW_POWER_COUNT */
+};
+
+static u16 pg_save_config_port_registers[] = {
+ /* Save and restore per port */
+ /* need to have port selected */
+ 0x530, /* T_SATA0_CHXCFG1 */
+ 0x684, /* T_SATA0_CHX_MISC */
+ 0x700, /* T_SATA0_CHXCFG3 */
+ 0x704, /* T_SATA0_CHXCFG4_CHX */
+ 0x690, /* T_SATA0_CHX_PHY_CTRL1_GEN1 */
+ 0x694, /* T_SATA0_CHX_PHY_CTRL1_GEN2 */
+ 0x698, /* T_SATA0_CHX_PHY_CTRL1_GEN3 */
+ 0x69C, /* T_SATA0_CHX_PHY_CTRL_2 */
+ 0x6B0, /* T_SATA0_CHX_PHY_CTRL_3 */
+ 0x6B4, /* T_SATA0_CHX_PHY_CTRL_4 */
+ 0x6B8, /* T_SATA0_CHX_PHY_CTRL_5 */
+ 0x6BC, /* T_SATA0_CHX_PHY_CTRL_6 */
+ 0x714, /* T_SATA0_PRBS_CHX - OP */
+ 0x750, /* T_SATA0_CHX_LINK0 */
+ 0x7F0 /* T_SATA0_CHX_GLUE */
+};
+
+static u16 pg_save_ipfs_registers[] = {
+ 0x094, /* SATA_FPCI_BAR5_0 */
+ 0x0C0, /* SATA_MSI_BAR_SZ_0 */
+ 0x0C4, /* SATA_MSI_AXI_BAR_ST_0 */
+ 0x0C8, /* SATA_MSI_FPCI_BAR_ST_0 */
+ 0x140, /* SATA_MSI_EN_VEC0_0 */
+ 0x144, /* SATA_MSI_EN_VEC1_0 */
+ 0x148, /* SATA_MSI_EN_VEC2_0 */
+ 0x14C, /* SATA_MSI_EN_VEC3_0 */
+ 0x150, /* SATA_MSI_EN_VEC4_0 */
+ 0x154, /* SATA_MSI_EN_VEC5_0 */
+ 0x158, /* SATA_MSI_EN_VEC6_0 */
+ 0x15C, /* SATA_MSI_EN_VEC7_0 */
+ 0x180, /* SATA_CONFIGURATION_0 */
+ 0x184, /* SATA_FPCI_ERROR_MASKS_0 */
+ 0x188, /* SATA_INTR_MASK_0 */
+ 0x1A0, /* SATA_CFG_REVID_0 */
+ 0x198, /* SATA_IPFS_INTR_ENABLE_0 */
+ 0x1BC, /* SATA_CLKGATE_HYSTERSIS_0 */
+ 0x1DC /* SATA_SATA_MCCIF_FIFOCTRL_0 */
+};
+
+static void tegra_ahci_save_regs(u32 **save_addr,
+ u32 reg_base,
+ u16 reg_array[],
+ u32 regs)
+{
+ u32 i;
+ u32 *dest = (u32 *)*save_addr;
+ u32 base = (u32)IO_ADDRESS(reg_base);
+
+ for (i = 0; i < regs; ++i, ++dest) {
+ *dest = readl(base + (u32)reg_array[i]);
+ AHCI_DBG_PRINT("save: [0x%x]=0x%08x\n",
+ (reg_base+(u32)reg_array[i]), *dest);
+ }
+ *save_addr = dest;
+}
+
+static void tegra_ahci_restore_regs(void **save_addr,
+ u32 reg_base,
+ u16 reg_array[],
+ u32 regs)
+{
+ u32 i;
+ u32 *src = (u32 *)*save_addr;
+ u32 base = (u32)IO_ADDRESS(reg_base);
+
+ for (i = 0; i < regs; ++i, ++src) {
+ writel(*src, base + (u32)reg_array[i]);
+ AHCI_DBG_PRINT("restore: [0x%x]=0x%08x\n",
+ (reg_base+(u32)reg_array[i]), *src);
+ }
+ *save_addr = src;
+}
+
+static void tegra_ahci_pg_save_registers(struct ata_host *host)
+{
+ struct tegra_ahci_host_priv *tegra_hpriv;
+ u32 *pg_save;
+ u32 regs;
+ int i;
+
+ tegra_hpriv = (struct tegra_ahci_host_priv *)host->private_data;
+ pg_save = tegra_hpriv->pg_save;
+
+ /*
+ * Driver should save/restore the registers in the order of
+ * IPFS, CFG, Ext CFG, BAR5.
+ */
+
+ /* save IPFS registers */
+ regs = ARRAY_SIZE(pg_save_ipfs_registers);
+ tegra_ahci_save_regs(&pg_save, TEGRA_SATA_BASE,
+ pg_save_ipfs_registers, regs);
+ /* after the call, pg_save should point to the next address to save */
+
+ /* save CONFIG registers */
+ regs = ARRAY_SIZE(pg_save_config_registers);
+ tegra_ahci_save_regs(&pg_save, TEGRA_SATA_CONFIG_BASE,
+ pg_save_config_registers, regs);
+
+ /* save CONFIG per port registers */
+ for (i = 0; i < TEGRA_AHCI_NUM_PORTS; ++i) {
+ scfg_writel((1 << i), T_SATA0_INDEX_OFFSET);
+ regs = ARRAY_SIZE(pg_save_config_port_registers);
+ tegra_ahci_save_regs(&pg_save, TEGRA_SATA_CONFIG_BASE,
+ pg_save_config_port_registers, regs);
+ }
+ scfg_writel(SATA0_NONE_SELECTED, T_SATA0_INDEX_OFFSET);
+
+ /* save BAR5 registers */
+ regs = ARRAY_SIZE(pg_save_bar5_registers);
+ tegra_ahci_save_regs(&pg_save, TEGRA_SATA_BAR5_BASE,
+ pg_save_bar5_registers, regs);
+
+ /* save BAR5 port_registers */
+ regs = ARRAY_SIZE(pg_save_bar5_port_registers);
+ for (i = 0; i < TEGRA_AHCI_NUM_PORTS; ++i)
+ tegra_ahci_save_regs(&pg_save, TEGRA_SATA_BAR5_BASE + (0x80*i),
+ pg_save_bar5_port_registers, regs);
+
+ /* save bkdr registers */
+ regs = ARRAY_SIZE(pg_save_bar5_bkdr_registers);
+ tegra_ahci_save_regs(&pg_save, TEGRA_SATA_BAR5_BASE,
+ pg_save_bar5_bkdr_registers, regs);
+
+ /* and save bkdr per_port registers */
+ for (i = 0; i < TEGRA_AHCI_NUM_PORTS; ++i) {
+ scfg_writel((1 << i), T_SATA0_INDEX_OFFSET);
+ regs = ARRAY_SIZE(pg_save_bar5_bkdr_port_registers);
+ tegra_ahci_save_regs(&pg_save, TEGRA_SATA_BAR5_BASE + (0x80*i),
+ pg_save_bar5_bkdr_port_registers,
+ regs);
+ }
+ scfg_writel(SATA0_NONE_SELECTED, T_SATA0_INDEX_OFFSET);
+}
+
+static void tegra_ahci_pg_restore_registers(struct ata_host *host)
+{
+ struct tegra_ahci_host_priv *tegra_hpriv;
+ void *pg_save;
+ u32 regs, val;
+ int i;
+
+ tegra_hpriv = (struct tegra_ahci_host_priv *)host->private_data;
+ pg_save = tegra_hpriv->pg_save;
+
+ /*
+ * Driver should restore the registers in the order of
+ * IPFS, CFG, Ext CFG, BAR5.
+ */
+
+ /* restore IPFS registers */
+ regs = ARRAY_SIZE(pg_save_ipfs_registers);
+ tegra_ahci_restore_regs(&pg_save, TEGRA_SATA_BASE,
+ pg_save_ipfs_registers, regs);
+ /* after the call, pg_save should point to the next addr to restore */
+
+ /* restore CONFIG registers */
+ regs = ARRAY_SIZE(pg_save_config_registers);
+ tegra_ahci_restore_regs(&pg_save, TEGRA_SATA_CONFIG_BASE,
+ pg_save_config_registers, regs);
+
+ /* restore CONFIG per port registers */
+ for (i = 0; i < TEGRA_AHCI_NUM_PORTS; ++i) {
+ scfg_writel((1 << i), T_SATA0_INDEX_OFFSET);
+ regs = ARRAY_SIZE(pg_save_config_port_registers);
+ tegra_ahci_restore_regs(&pg_save, TEGRA_SATA_CONFIG_BASE,
+ pg_save_config_port_registers,
+ regs);
+ }
+ scfg_writel(SATA0_NONE_SELECTED, T_SATA0_INDEX_OFFSET);
+
+ /* restore BAR5 registers */
+ regs = ARRAY_SIZE(pg_save_bar5_registers);
+ tegra_ahci_restore_regs(&pg_save, TEGRA_SATA_BAR5_BASE,
+ pg_save_bar5_registers, regs);
+
+ /* restore BAR5 port_registers */
+ regs = ARRAY_SIZE(pg_save_bar5_port_registers);
+ for (i = 0; i < TEGRA_AHCI_NUM_PORTS; ++i)
+ tegra_ahci_restore_regs(&pg_save, TEGRA_SATA_BAR5_BASE+(0x80*i),
+ pg_save_bar5_port_registers, regs);
+
+ /* restore bkdr registers */
+ regs = ARRAY_SIZE(pg_restore_bar5_bkdr_registers);
+ tegra_ahci_restore_regs(&pg_save, TEGRA_SATA_CONFIG_BASE,
+ pg_restore_bar5_bkdr_registers, regs);
+
+ /* and restore BAR5 bkdr per_port registers */
+ for (i = 0; i < TEGRA_AHCI_NUM_PORTS; ++i) {
+ scfg_writel((1 << i), T_SATA0_INDEX_OFFSET);
+ regs = ARRAY_SIZE(pg_restore_bar5_bkdr_port_registers);
+ tegra_ahci_restore_regs(&pg_save, TEGRA_SATA_CONFIG_BASE,
+ pg_restore_bar5_bkdr_port_registers,
+ regs);
+ }
+ scfg_writel(SATA0_NONE_SELECTED, T_SATA0_INDEX_OFFSET);
+
+ /* program class code and programming interface for AHCI */
+ val = scfg_readl(TEGRA_PRIVATE_AHCI_CC_BKDR_OVERRIDE);
+ val |= TEGRA_PRIVATE_AHCI_CC_BKDR_OVERRIDE_EN;
+ scfg_writel(val, TEGRA_PRIVATE_AHCI_CC_BKDR_OVERRIDE);
+ scfg_writel(TEGRA_PRIVATE_AHCI_CC_BKDR_PGM, TEGRA_PRIVATE_AHCI_CC_BKDR);
+ val &= ~TEGRA_PRIVATE_AHCI_CC_BKDR_OVERRIDE_EN;
+ scfg_writel(val, TEGRA_PRIVATE_AHCI_CC_BKDR_OVERRIDE);
+}
+
+static u32 tegra_ahci_port_error(struct ata_port *ap)
+{
+ void __iomem *port_mmio = ahci_port_base(ap);
+ u32 err_status;
+
+ err_status = readl(port_mmio + PORT_IRQ_STAT);
+ /* excludes PhyRdy and Connect Change status */
+ err_status &= (PORT_IRQ_ERROR & (~(PORT_IRQ_PHYRDY|PORT_IRQ_CONNECT)));
+ return err_status;
+}
+
+static bool tegra_ahci_check_errors(struct ata_host *host)
+{ int i;
+ struct ata_port *ap;
+ u32 err;
+
+ for (i = 0; i < host->n_ports; i++) {
+ ap = host->ports[i];
+ err = tegra_ahci_port_error(ap);
+ if (err) {
+ dev_err(host->dev,
+ "pg-chk-err = 0x%08x on port %d\n", err, i);
+ return true;
+ }
+ }
+ return false;
+}
+
+static void tegra_ahci_abort_power_gate(struct ata_host *host)
+{
+ u32 val;
+
+ val = pmc_readl(APB_PMC_SATA_PWRGT_0_REG);
+ val &= ~PG_INFO_MASK;
+ val |= PG_INFO_OFF;
+ pmc_writel(val, APB_PMC_SATA_PWRGT_0_REG);
+}
+
+static bool tegra_ahci_power_gate(struct ata_host *host)
+{
+ u32 val;
+ u32 dat;
+ struct tegra_ahci_host_priv *tegra_hpriv;
+ int status;
+
+ tegra_hpriv = (struct tegra_ahci_host_priv *)host->private_data;
+
+ val = pmc_readl(APB_PMC_SATA_PWRGT_0_REG);
+ val &= ~PG_INFO_MASK;
+ val |= PG_INFO_ON;
+ pmc_writel(val, APB_PMC_SATA_PWRGT_0_REG);
+
+ tegra_ahci_pg_save_registers(host);
+
+ /*
+ * Read SATA_AUX_MISC_CNTL_1_0 register L0_RX_IDLE_T_SAX field and
+ * write that value into same register L0_RX_IDLE_T_NPG field.
+ * And write 1 to L0_RX_IDLE_T_MUX field.
+ */
+ val = misc_readl(SATA_AUX_MISC_CNTL_1_REG);
+ dat = val;
+ dat &= L0_RX_IDLE_T_SAX_MASK;
+ dat >>= L0_RX_IDLE_T_SAX_SHIFT;
+ dat <<= L0_RX_IDLE_T_NPG_SHIFT;
+ val &= ~L0_RX_IDLE_T_NPG_MASK;
+ val |= dat;
+ val &= ~L0_RX_IDLE_T_MUX_MASK;
+ val |= L0_RX_IDLE_T_MUX_FROM_APB_MISC;
+ misc_writel(val, SATA_AUX_MISC_CNTL_1_REG);
+
+ /* abort PG if there are errors occurred */
+ if (tegra_ahci_check_errors(host)) {
+ dev_err(host->dev, "** pg: errors; abort power gating **\n");
+ return false;
+ }
+ /* make sure all ports have no outstanding commands and are idle. */
+ if (!tegra_ahci_are_all_ports_idle(host)) {
+ dev_err(host->dev, "** pg: cmds; abort power gating **\n");
+ return false;
+ }
+
+ /*
+ * Hw wake up is not needed:
+ * Driver/RM shall place the SATA PHY and SATA PADPLL in IDDQ.
+ * SATA_PADPLL_RESET_SWCTL =1
+ * SATA_PADPLL_RESET_OVERRIDE_VALUE=1
+ * SATA_PADPHY_IDDQ_SWCTL=1
+ * SATA_PADPHY_IDDQ_OVERRIDE_VALUE=1
+ */
+ val = clk_readl(CLK_RST_SATA_PLL_CFG0_REG);
+ val &= ~(PADPLL_RESET_SWCTL_MASK | PADPLL_RESET_OVERRIDE_VALUE_MASK);
+ val |= (PADPLL_RESET_SWCTL_ON | PADPLL_RESET_OVERRIDE_VALUE_ON);
+ clk_writel(val, CLK_RST_SATA_PLL_CFG0_REG);
+ val = pmc_readl(APB_PMC_SATA_PWRGT_0_REG);
+ val &= ~(PADPHY_IDDQ_OVERRIDE_VALUE_MASK | PADPHY_IDDQ_SWCTL_MASK);
+ val |= (PADPHY_IDDQ_SWCTL_ON | PADPHY_IDDQ_OVERRIDE_VALUE_ON);
+ pmc_writel(val, APB_PMC_SATA_PWRGT_0_REG);
+
+ /* Wait for time specified in SATA_LANE_IDDQ2_PADPLL_IDDQ */
+ val = clk_readl(CLK_RST_SATA_PLL_CFG1_REG);
+ dat = (val & IDDQ2LANE_IDDQ_DLY_MASK) >> IDDQ2LANE_IDDQ_DLY_SHIFT;
+ udelay(dat);
+
+ /* SATA_PADPLL_IDDQ_SWCTL=1 & SATA_PADPLL_IDDQ_OVERRIDE_VALUE=1 */
+ val = pmc_readl(APB_PMC_SATA_PWRGT_0_REG);
+ val &= ~(PADPLL_IDDQ_OVERRIDE_VALUE_MASK | PADPLL_IDDQ_SWCTL_MASK);
+ val |= (PADPLL_IDDQ_SWCTL_ON | PADPLL_IDDQ_OVERRIDE_VALUE_ON);
+ pmc_writel(val, APB_PMC_SATA_PWRGT_0_REG);
+
+ /* power off the sata */
+ status = tegra_powergate_partition_with_clk_off(TEGRA_POWERGATE_SATA);
+ if (status)
+ dev_err(host->dev, "** failed to turn-off SATA (0x%x) **\n",
+ status);
+
+ return true;
+}
+
+static bool tegra_ahci_power_un_gate(struct ata_host *host)
+{
+ u32 val;
+ u32 dat;
+ u32 timeout;
+ struct tegra_ahci_host_priv *tegra_hpriv;
+ int status;
+
+ tegra_hpriv = (struct tegra_ahci_host_priv *)host->private_data;
+
+ /* get sata phy and pll out of iddq: */
+ val = pmc_readl(APB_PMC_SATA_PWRGT_0_REG);
+ val &= ~PADPLL_IDDQ_OVERRIDE_VALUE_MASK;
+ val |= PADPLL_IDDQ_OVERRIDE_VALUE_OFF;
+ pmc_writel(val, APB_PMC_SATA_PWRGT_0_REG);
+ /* wait for delay of IDDQ2LAND_SLUMBER_DLY */
+ val = clk_readl(CLK_RST_SATA_PLL_CFG1_REG);
+ dat = (val & IDDQ2LANE_SLUMBER_DLY_MASK) >> IDDQ2LANE_SLUMBER_DLY_SHIFT;
+ udelay(dat);
+ val = pmc_readl(APB_PMC_SATA_PWRGT_0_REG);
+ val &= ~PADPHY_IDDQ_OVERRIDE_VALUE_MASK;
+ val |= PADPHY_IDDQ_OVERRIDE_VALUE_OFF;
+ pmc_writel(val, APB_PMC_SATA_PWRGT_0_REG);
+
+ status = tegra_unpowergate_partition_with_clk_on(TEGRA_POWERGATE_SATA);
+ if (status)
+ dev_err(host->dev, "** failed to turn-on SATA (0x%x) **\n",
+ status);
+
+ /* deasset PADPLL and wait until it locks. */
+ val = clk_readl(CLK_RST_SATA_PLL_CFG0_REG);
+ val &= ~PADPLL_RESET_OVERRIDE_VALUE_MASK;
+ val |= PADPLL_RESET_OVERRIDE_VALUE_OFF;
+ clk_writel(val, CLK_RST_SATA_PLL_CFG0_REG);
+
+ /*
+ * Wait for SATA_AUX_PAD_PLL_CNTL_1_0_LOCKDET to turn 1 with a timeout
+ * of 15 us.
+ */
+ timeout = 15;
+ while (timeout--) {
+ udelay(1);
+ val = misc_readl(SATA_AUX_PAD_PLL_CNTL_1_REG);
+ if (val & LOCKDET_FIELD)
+ break;
+ }
+ if (timeout == 0)
+ pr_err("%s: SATA_PAD_PLL is not locked in 15us.\n", __func__);
+
+ /* restore registers */
+ tegra_ahci_pg_restore_registers(host);
+
+ /*
+ * During the restoration of the registers, the driver would now need to
+ * restore the register T_SATA0_CFG_POWER_GATE_SSTS_RESTORED after the
+ * ssts_det, ssts_spd are restored. This register is used to tell the
+ * controller whether a drive existed earlier or not and move the PHY
+ * state machines into either HR_slumber or not.
+ */
+ val = scfg_readl(T_SATA0_CFG_POWER_GATE);
+ val &= ~POWER_GATE_SSTS_RESTORED_MASK;
+ val |= POWER_GATE_SSTS_RESTORED_YES;
+ scfg_writel(val, T_SATA0_CFG_POWER_GATE);
+
+ /*
+ * Driver needs to switch the rx_idle_t driven source back to from
+ * Sata controller after SAX is power-ungated.
+ */
+ val = misc_readl(SATA_AUX_MISC_CNTL_1_REG);
+ val &= ~L0_RX_IDLE_T_MUX_MASK;
+ val |= L0_RX_IDLE_T_MUX_FROM_SATA;
+ misc_writel(val, SATA_AUX_MISC_CNTL_1_REG);
+
+ /*
+ * Driver can start to use main SATA interrupt instead of the
+ * rx_stat_t interrupt.
+ */
+ val = pictlr_readl(PRI_ICTLR_CPU_IER_SET_0_OFFSET);
+ val |= CPU_IER_SATA_CTL;
+ pictlr_writel(val, PRI_ICTLR_CPU_IER_SET_0_OFFSET);
+
+ /* Set the bits in the CAR to allow HW based low power sequencing. */
+ val = clk_readl(CLK_RST_SATA_PLL_CFG0_REG);
+ val &= ~PADPLL_RESET_SWCTL_MASK;
+ val |= PADPLL_RESET_SWCTL_OFF;
+ clk_writel(val, CLK_RST_SATA_PLL_CFG0_REG);
+
+ /*
+ * power un-gating process is complete by clearing
+ * APBDEV_PMC_SATA_PWRGT_0.Pmc2sata_pg_info = 0
+ */
+ val = pmc_readl(APB_PMC_SATA_PWRGT_0_REG);
+ val &= ~PG_INFO_MASK;
+ val |= PG_INFO_OFF;
+ pmc_writel(val, APB_PMC_SATA_PWRGT_0_REG);
+
+ return true;
+}
+
+static enum port_idle_status tegra_ahci_is_port_idle(struct ata_port *ap)
+{
+ void __iomem *port_mmio = ahci_port_base(ap);
+
+ if (readl(port_mmio + PORT_CMD_ISSUE) ||
+ readl(port_mmio + PORT_SCR_ACT))
+ return PORT_IS_NOT_IDLE;
+ return PORT_IS_IDLE;
+}
+
+static enum port_idle_status tegra_ahci_is_port_slumber(struct ata_port *ap)
+{
+ void __iomem *port_mmio = ahci_port_base(ap);
+ u32 sstat;
+
+ if (tegra_ahci_is_port_idle(ap) == PORT_IS_NOT_IDLE)
+ return PORT_IS_NOT_IDLE;
+
+ /* return 1 if PORT_SCR_STAT is in IPM_SLUMBER_STATE */
+ sstat = readl(port_mmio + PORT_SCR_STAT);
+ if ((sstat & SSTAT_IPM_STATE_MASK) == SSTAT_IPM_SLUMBER_STATE)
+ return PORT_IS_SLUMBER;
+ return PORT_IS_IDLE_NOT_SLUMBER;
+}
+
+/* check if all supported ports are idle (no outstanding commands) */
+static bool tegra_ahci_are_all_ports_idle(struct ata_host *host)
+{ int i;
+ struct ata_port *ap;
+
+ for (i = 0; i < host->n_ports; i++) {
+ ap = host->ports[i];
+ if (ap && (tegra_ahci_is_port_idle(ap) == PORT_IS_NOT_IDLE))
+ return false;
+ }
+ return true;
+}
+
+/* check if all supported ports are in slumber */
+static bool tegra_ahci_are_all_ports_slumber(struct ata_host *host)
+{ int i;
+ struct ata_port *ap;
+
+ for (i = 0; i < host->n_ports; i++) {
+ ap = host->ports[i];
+ if (ap && (tegra_ahci_is_port_slumber(ap) != PORT_IS_SLUMBER))
+ return false;
+ }
+ return true;
+}
+
+#ifdef CONFIG_TEGRA_SATA_IDLE_POWERGATE
+static void tegra_ahci_to_add_idle_timer(struct ata_host *host)
+{
+ struct tegra_ahci_host_priv *tegra_hpriv;
+
+ tegra_hpriv = (struct tegra_ahci_host_priv *)host->private_data;
+
+ /* note: the routine is called from interrupt context */
+ spin_lock(&host->lock);
+ /* start idle-timer if all ports have no outstanding commands */
+ if (tegra_ahci_are_all_ports_idle(host)) {
+ /* adjust tegra_ahci_idle_time to minimum if it is too small */
+ tegra_ahci_idle_time = max((u32)TEGRA_AHCI_MIN_IDLE_TIME,
+ tegra_ahci_idle_time);
+ tegra_hpriv->idle_timer.expires =
+ ata_deadline(jiffies, tegra_ahci_idle_time);
+ mod_timer(&tegra_hpriv->idle_timer,
+ tegra_hpriv->idle_timer.expires);
+ }
+ spin_unlock(&host->lock);
+}
+
+static void tegra_ahci_idle_timer(unsigned long arg)
+{
+ struct ata_host *host = (void *)arg;
+ struct tegra_ahci_host_priv *tegra_hpriv;
+ unsigned long flags;
+
+ tegra_hpriv = (struct tegra_ahci_host_priv *)host->private_data;
+
+ spin_lock_irqsave(&host->lock, flags);
+ if (tegra_hpriv->pg_state == SATA_ON)
+ tegra_hpriv->pg_state = SATA_GOING_OFF;
+ else {
+ dev_err(host->dev, "idle_timer: bad state (%u)\n",
+ tegra_hpriv->pg_state);
+ WARN_ON(1);
+ spin_unlock_irqrestore(&host->lock, flags);
+ return;
+ }
+ spin_unlock_irqrestore(&host->lock, flags);
+
+ pm_runtime_put(tegra_hpriv->dev);
+}
+
+static int tegra_ahci_queue_one_qc(struct tegra_ahci_host_priv *tegra_hpriv,
+ struct ata_queued_cmd *qc)
+{
+ struct tegra_qc_list *qc_list;
+
+ qc_list = kmalloc(sizeof(struct tegra_qc_list), GFP_ATOMIC);
+ if (!qc_list) {
+ dev_err(tegra_hpriv->dev, "failed to alloc qc_list\n");
+ return AC_ERR_SYSTEM;
+ }
+ qc_list->qc = qc;
+ list_add_tail(&(qc_list->list), &(tegra_hpriv->qc_list));
+ dev_dbg(tegra_hpriv->dev, "queuing qc=%x\n", (unsigned int)qc);
+ return 0;
+}
+
+static void tegra_ahci_dequeue_qcs(struct tegra_ahci_host_priv *tegra_hpriv)
+{
+ struct list_head *list, *next;
+ struct tegra_qc_list *qc_list;
+ struct ata_queued_cmd *qc;
+
+ /* now qc_issue all qcs in the qc_list */
+ list_for_each_safe(list, next, &tegra_hpriv->qc_list) {
+ qc_list = list_entry(list, struct tegra_qc_list, list);
+ qc = qc_list->qc;
+ dev_dbg(tegra_hpriv->dev, "dequeue qc=%x\n", (unsigned int)qc);
+ ahci_ops.qc_issue(qc);
+ list_del(list);
+ kfree(qc_list);
+ }
+}
+
+static unsigned int tegra_ahci_qc_issue(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ struct ata_host *host = ap->host;
+ struct tegra_ahci_host_priv *tegra_hpriv = host->private_data;
+ int rc;
+
+ /* stop the idle timer */
+ if (timer_pending(&tegra_hpriv->idle_timer))
+ del_timer_sync(&tegra_hpriv->idle_timer);
+
+ /* note: host->lock is locked */
+ switch (tegra_hpriv->pg_state) {
+ case SATA_ON:
+ /* normal case, issue the qc */
+ return ahci_ops.qc_issue(qc);
+ case SATA_GOING_OFF:
+ case SATA_ABORT_OFF:
+ /* SATA is going OFF, let's abort the suspend */
+ dev_dbg(host->dev, "** qc_issue: going OFF **\n");
+ tegra_hpriv->pg_state = SATA_ABORT_OFF;
+ return tegra_ahci_queue_one_qc(tegra_hpriv, qc);
+ case SATA_OFF:
+ dev_dbg(host->dev, "** qc_issue: request power-up sata **\n");
+ rc = pm_runtime_get(tegra_hpriv->dev);
+ /* rc == 0 means the request has been queued successfully */
+ if (rc) {
+ dev_err(host->dev, "** qc_issue: rt_get()=%d **\n",
+ rc);
+ WARN_ON(1);
+ return AC_ERR_SYSTEM;
+ }
+ tegra_hpriv->pg_state = SATA_GOING_ON;
+ /* continue with the following code to queue the qc */
+ case SATA_GOING_ON:
+ return tegra_ahci_queue_one_qc(tegra_hpriv, qc);
+ default:
+ dev_err(host->dev, "** qc_issue: bad state (%u) **\n",
+ tegra_hpriv->pg_state);
+ WARN_ON(1);
+ return AC_ERR_SYSTEM;
+ }
+}
+
+static int tegra_ahci_hardreset(struct ata_link *link, unsigned int *class,
+ unsigned long deadline)
+{
+ struct ata_port *ap = link->ap;
+ struct ata_host *host = ap->host;
+ struct tegra_ahci_host_priv *tegra_hpriv = host->private_data;
+ int rc;
+
+ if (tegra_hpriv->pg_state == SATA_OFF) {
+ dev_dbg(host->dev, "** hreset: request power-up sata **\n");
+ rc = pm_runtime_get_sync(tegra_hpriv->dev);
+ /* rc == 0 means the request has been run successfully */
+ if (rc) {
+ dev_err(host->dev, "** hreset: rt_get()=%d **\n", rc);
+ WARN_ON(1);
+ return AC_ERR_SYSTEM;
+ }
+ tegra_hpriv->pg_state = SATA_ON;
+ }
+
+ return ahci_ops.hardreset(link, class, deadline);
+}
+
+static irqreturn_t tegra_ahci_interrupt(int irq, void *dev_instance)
+{
+ irqreturn_t irq_retval;
+
+ irq_retval = ahci_interrupt(irq, dev_instance);
+ if (irq_retval == IRQ_NONE)
+ return IRQ_NONE;
+
+#ifdef CONFIG_PM
+ tegra_ahci_to_add_idle_timer((struct ata_host *)dev_instance);
+#endif
+
+ return irq_retval;
+}
+#endif
+#endif
+
+static int __devexit tegra_ahci_remove_one(struct platform_device *pdev)
+{
+ struct ata_host *host = dev_get_drvdata(&pdev->dev);
+ struct ahci_host_priv *hpriv;
+
+ BUG_ON(host == NULL);
+ BUG_ON(host->iomap[AHCI_PCI_BAR] == NULL);
+ hpriv = host->private_data;
+
+ tegra_ahci_controller_remove(pdev);
+
+ devm_iounmap(&pdev->dev, host->iomap[AHCI_PCI_BAR]);
+ devres_free(host);
+
+#ifdef CONFIG_PM
+ /* Free PG save/restore area */
+ devm_kfree(&pdev->dev, ((struct tegra_ahci_host_priv *)hpriv)->pg_save);
+
+#ifdef CONFIG_TEGRA_SATA_IDLE_POWERGATE
+ pm_runtime_disable(&pdev->dev);
+#endif
+#endif
+
+ devm_kfree(&pdev->dev, hpriv);
+
+ return 0;
+}
+
+static int __devinit tegra_ahci_init_one(struct platform_device *pdev)
+{
+ struct ata_port_info pi = ahci_port_info;
+ const struct ata_port_info *ppi[] = { &pi, NULL };
+ struct device *dev = &pdev->dev;
+ struct ahci_host_priv *hpriv = NULL;
+ struct tegra_ahci_host_priv *tegra_hpriv;
+ struct ata_host *host = NULL;
+ int n_ports, i, rc;
+ struct resource *res, *irq_res;
+ void __iomem *mmio;
+ u32 save_size;
+ irq_handler_t irq_handler = ahci_interrupt;
+
+ VPRINTK("ENTER\n");
+
+ WARN_ON((int)ATA_MAX_QUEUE > AHCI_MAX_CMDS);
+
+ ata_print_version_once(&pdev->dev, DRV_VERSION);
+
+ /* Simple resource validation */
+ if (pdev->num_resources != 3) {
+ dev_err(dev, "invalid number of resources\n");
+ dev_err(dev, "not enough SATA resources\n");
+ return -EINVAL;
+ }
+
+ /* acquire bar resources */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res == NULL)
+ return -EINVAL;
+
+ /* acquire IRQ resource */
+ irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (irq_res == NULL)
+ return -EINVAL;
+ if (irq_res->start <= 0)
+ return -EINVAL;
+
+ /* allocate sizeof tegra_ahci_host_priv, which contains extra fields */
+ hpriv = devm_kzalloc(dev, sizeof(struct tegra_ahci_host_priv),
+ GFP_KERNEL);
+ if (!hpriv) {
+ rc = -ENOMEM;
+ goto fail;
+ }
+ hpriv->flags |= (unsigned long)pi.private_data;
+ tegra_hpriv = (struct tegra_ahci_host_priv *)hpriv;
+ g_tegra_hpriv = tegra_hpriv;
+
+ /* Call tegra init routine */
+ rc = tegra_ahci_controller_init(tegra_hpriv);
+ if (rc != 0) {
+ dev_err(dev, "TEGRA SATA init failed\n");
+ goto fail;
+ }
+
+ /*
+ * We reserve a table of 6 BARs in tegra_hpriv to store BARs.
+ * Save the mapped AHCI_PCI_BAR address to the table.
+ */
+ mmio = devm_ioremap(dev, res->start, (res->end-res->start+1));
+ tegra_hpriv->bars_table[AHCI_PCI_BAR] = mmio;
+ hpriv->mmio = mmio;
+
+ /* save initial config */
+ tegra_ahci_save_initial_config(pdev, hpriv);
+ dev_dbg(dev, "past save init config\n");
+
+ /* prepare host */
+ if (hpriv->cap & HOST_CAP_NCQ) {
+ pi.flags |= ATA_FLAG_NCQ;
+ pi.flags |= ATA_FLAG_FPDMA_AA;
+ }
+
+ /*
+ * CAP.NP sometimes indicate the index of the last enabled
+ * port, at other times, that of the last possible port, so
+ * determining the maximum port number requires looking at
+ * both CAP.NP and port_map.
+ */
+ n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
+ host = ata_host_alloc_pinfo(dev, ppi, n_ports);
+ if (!host) {
+ rc = -ENOMEM;
+ goto fail;
+ }
+ host->private_data = hpriv;
+ tegra_hpriv->host = host;
+ tegra_hpriv->dev = dev;
+ host->iomap = tegra_hpriv->bars_table;
+
+ if (!(hpriv->cap & HOST_CAP_SSS))
+ host->flags |= ATA_HOST_PARALLEL_SCAN;
+ else
+ printk(KERN_INFO "ahci: SSS flag set, parallel bus scan disabled\n");
+
+ for (i = 0; i < host->n_ports; i++) {
+ struct ata_port *ap = host->ports[i];
+
+ /* set initial link pm policy */
+ ap->target_lpm_policy = ATA_LPM_UNKNOWN;
+
+ /* disabled/not-implemented port */
+ if (!(hpriv->port_map & (1 << i)))
+ ap->ops = &ata_dummy_port_ops;
+ else
+ ap->target_lpm_policy = ATA_LPM_MIN_POWER;
+ }
+
+ rc = ahci_reset_controller(host);
+ if (rc) {
+ dev_err(dev, "Reset controller failed! (rc=%d)\n", rc);
+ goto fail;
+ }
+
+ ahci_init_controller(host);
+ ahci_print_info(host, "TEGRA-SATA");
+ dev_dbg(dev, "controller init okay\n");
+
+#ifdef CONFIG_PM
+ /* Setup PG save/restore area: */
+
+ /* calculate the size */
+ save_size = ARRAY_SIZE(pg_save_ipfs_registers) +
+ ARRAY_SIZE(pg_save_config_registers) +
+ ARRAY_SIZE(pg_save_bar5_registers) +
+ ARRAY_SIZE(pg_save_bar5_bkdr_registers);
+
+ /* and add save port_registers for all the ports */
+ save_size += TEGRA_AHCI_NUM_PORTS *
+ (ARRAY_SIZE(pg_save_config_port_registers) +
+ ARRAY_SIZE(pg_save_bar5_port_registers) +
+ ARRAY_SIZE(pg_save_bar5_bkdr_port_registers));
+
+ /*
+ * save_size is number of registers times number of bytes per
+ * register to get total save size.
+ */
+ save_size *= sizeof(u32);
+ tegra_hpriv->pg_save = devm_kzalloc(dev, save_size, GFP_KERNEL);
+ if (!tegra_hpriv->pg_save) {
+ rc = -ENOMEM;
+ goto fail;
+ }
+
+#ifdef CONFIG_TEGRA_SATA_IDLE_POWERGATE
+ pm_runtime_set_active(dev);
+ pm_suspend_ignore_children(dev, true);
+ pm_runtime_enable(dev);
+
+ tegra_hpriv->pg_state = SATA_ON;
+
+ /* setup sata idle timer */
+ init_timer_deferrable(&tegra_hpriv->idle_timer);
+ tegra_hpriv->idle_timer.function = tegra_ahci_idle_timer;
+ tegra_hpriv->idle_timer.data = (unsigned long)host;
+
+ INIT_LIST_HEAD(&tegra_hpriv->qc_list);
+
+ /* use our own irq handler */
+ irq_handler = tegra_ahci_interrupt;
+#endif
+
+#endif
+
+ rc = ata_host_activate(host, irq_res->start, irq_handler, 0, &ahci_sht);
+ if (rc == 0)
+ return 0;
+
+ /* Free PG save/restore area */
+ devm_kfree(dev, tegra_hpriv->pg_save);
+
+#ifdef CONFIG_TEGRA_SATA_IDLE_POWERGATE
+ pm_runtime_put(dev);
+ pm_runtime_enable(dev);
+#endif
+
+fail:
+ if (host) {
+ if (host->iomap[AHCI_PCI_BAR])
+ devm_iounmap(dev, host->iomap[AHCI_PCI_BAR]);
+ devres_free(host);
+ }
+ if (hpriv)
+ devm_kfree(dev, hpriv);
+
+ return rc;
+}
+
+static int __init ahci_init(void)
+{
+ return platform_driver_register(&tegra_platform_ahci_driver);
+}
+
+static void __exit ahci_exit(void)
+{
+ platform_driver_unregister(&tegra_platform_ahci_driver);
+}
+
+
+#ifdef CONFIG_DEBUG_FS
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+static void dbg_ahci_dump_regs(struct seq_file *s, u32 *ptr, u32 base, u32 regs)
+{
+#define REGS_PER_LINE 4
+
+ u32 i, j;
+ u32 lines = regs / REGS_PER_LINE;
+
+ for (i = 0; i < lines; i++) {
+ seq_printf(s, "0x%08x: ", base+(i*16));
+ for (j = 0; j < REGS_PER_LINE; ++j) {
+ seq_printf(s, "0x%08x ", readl(ptr));
+ ++ptr;
+ }
+ seq_printf(s, "\n");
+ }
+#undef REGS_PER_LINE
+}
+
+static int dbg_ahci_dump_show(struct seq_file *s, void *unused)
+{
+ u32 base;
+ u32 *ptr;
+ u32 i;
+
+ base = TEGRA_SATA_CONFIG_BASE;
+ ptr = (u32 *)IO_TO_VIRT(base);
+ seq_printf(s, "SATA CONFIG Registers:\n");
+ seq_printf(s, "----------------------\n");
+ dbg_ahci_dump_regs(s, ptr, base, 0x200);
+
+ base = TEGRA_SATA_BAR5_BASE;
+ ptr = (u32 *)IO_TO_VIRT(base);
+ seq_printf(s, "\nAHCI HBA Registers:\n");
+ seq_printf(s, "-------------------\n");
+ dbg_ahci_dump_regs(s, ptr, base, 64);
+
+ for (i = 0; i < TEGRA_AHCI_NUM_PORTS; ++i) {
+ base = TEGRA_SATA_BAR5_BASE + 0x100 + (0x80*i);
+ ptr = (u32 *)IO_TO_VIRT(base);
+ seq_printf(s, "\nPort %u Registers:\n", i);
+ seq_printf(s, "---------------\n");
+ dbg_ahci_dump_regs(s, ptr, base, 16);
+ }
+
+#ifdef CONFIG_TEGRA_SATA_IDLE_POWERGATE
+ /* adjust tegra_ahci_idle_time to minimum if it is too small */
+ tegra_ahci_idle_time = max((u32)TEGRA_AHCI_MIN_IDLE_TIME,
+ tegra_ahci_idle_time);
+ seq_printf(s, "\nIdle Timeout = %u milli-seconds.\n",
+ tegra_ahci_idle_time);
+#endif
+
+ if (tegra_powergate_is_powered(TEGRA_POWERGATE_SATA))
+ seq_printf(s, "\n=== SATA controller is powered on ===\n\n");
+ else
+ seq_printf(s, "\n=== SATA controller is powered off ===\n\n");
+
+ return 0;
+}
+
+static int dbg_ahci_dump_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, dbg_ahci_dump_show, &inode->i_private);
+}
+
+static const struct file_operations debug_fops = {
+ .open = dbg_ahci_dump_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int __init tegra_ahci_dump_debuginit(void)
+{
+ (void) debugfs_create_file("tegra_ahci", S_IRUGO,
+ NULL, NULL, &debug_fops);
+#ifdef CONFIG_TEGRA_SATA_IDLE_POWERGATE
+ (void) debugfs_create_u32("tegra_ahci_idle_ms", S_IRWXUGO,
+ NULL, &tegra_ahci_idle_time);
+#endif
+ return 0;
+}
+late_initcall(tegra_ahci_dump_debuginit);
+#endif
+
+MODULE_AUTHOR("NVIDIA");
+MODULE_DESCRIPTION("Tegra AHCI SATA low-level driver");
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION(DRV_VERSION);
+
+module_init(ahci_init);
+module_exit(ahci_exit);
diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 96916bed997f..1358dc70b0e4 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -331,12 +331,19 @@ static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev)
{
u32 val;
int tx_fifo_avail;
- u8 *buf = i2c_dev->msg_buf;
- size_t buf_remaining = i2c_dev->msg_buf_remaining;
+ u8 *buf;
+ size_t buf_remaining;
int words_to_transfer;
unsigned long flags;
spin_lock_irqsave(&i2c_dev->fifo_lock, flags);
+ if (!i2c_dev->msg_buf_remaining) {
+ spin_unlock_irqrestore(&i2c_dev->fifo_lock, flags);
+ return 0;
+ }
+
+ buf = i2c_dev->msg_buf;
+ buf_remaining = i2c_dev->msg_buf_remaining;
val = i2c_readl(i2c_dev, I2C_FIFO_STATUS);
tx_fifo_avail = (val & I2C_FIFO_STATUS_TX_MASK) >>
@@ -375,7 +382,12 @@ static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev)
* boundary and fault.
*/
if (tx_fifo_avail > 0 && buf_remaining > 0) {
- BUG_ON(buf_remaining > 3);
+ if (buf_remaining > 3) {
+ dev_err(i2c_dev->dev,
+ "Remaining buffer more than 3 %d\n",
+ buf_remaining);
+ BUG();
+ }
memcpy(&val, buf, buf_remaining);
/* Again update before writing to FIFO to make sure isr sees. */
diff --git a/drivers/media/video/tegra/Kconfig b/drivers/media/video/tegra/Kconfig
index f5aea996e2d6..5099fe12c3e2 100644
--- a/drivers/media/video/tegra/Kconfig
+++ b/drivers/media/video/tegra/Kconfig
@@ -95,3 +95,10 @@ config VIDEO_AD5820
---help---
This is a driver for the AD5820 focuser
for use with the tegra isp.
+
+config VIDEO_AD5816
+ tristate "AD5816 focuser support"
+ depends on I2C && ARCH_TEGRA
+ ---help---
+ This is a driver for the AD5816 focuser
+ for use with the tegra isp.
diff --git a/drivers/media/video/tegra/Makefile b/drivers/media/video/tegra/Makefile
index 08b81e261611..3c1a0ce4638e 100644
--- a/drivers/media/video/tegra/Makefile
+++ b/drivers/media/video/tegra/Makefile
@@ -18,4 +18,5 @@ obj-$(CONFIG_TORCH_SSL3250A) += ssl3250a.o
obj-$(CONFIG_TORCH_TPS61050) += tps61050.o
obj-$(CONFIG_VIDEO_SH532U) += sh532u.o
obj-$(CONFIG_VIDEO_AD5820) += ad5820.o
+obj-$(CONFIG_VIDEO_AD5816) += ad5816.o
diff --git a/drivers/media/video/tegra/ad5816.c b/drivers/media/video/tegra/ad5816.c
new file mode 100644
index 000000000000..d95368f43cf6
--- /dev/null
+++ b/drivers/media/video/tegra/ad5816.c
@@ -0,0 +1,1204 @@
+/* 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
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307, USA
+ */
+/* This is a NVC kernel driver for a focuser device called
+ * ad5816.
+ */
+/* Implementation
+ * --------------
+ * The board level details about the device need to be provided in the board
+ * file with the <device>_platform_data structure.
+ * Standard among NVC kernel drivers in this structure is:
+ * .cfg = Use the NVC_CFG_ defines that are in nvc.h.
+ * Descriptions of the configuration options are with the defines.
+ * This value is typically 0.
+ * .num = The number of the instance of the device. This should start at 1 and
+ * and increment for each device on the board. This number will be
+ * appended to the MISC driver name, Example: /dev/focuser.1
+ * If not used or 0, then nothing is appended to the name.
+ * .sync = If there is a need to synchronize two devices, then this value is
+ * the number of the device instance (.num above) this device is to
+ * sync to. For example:
+ * Device 1 platform entries =
+ * .num = 1,
+ * .sync = 2,
+ * Device 2 platfrom entries =
+ * .num = 2,
+ * .sync = 1,
+ * The above example sync's device 1 and 2.
+ * To disable sync, set .sync = 0. Note that the .num = 0 device is not
+ * allowed to be synced to.
+ * This is typically used for stereo applications.
+ * .dev_name = The MISC driver name the device registers as. If not used,
+ * then the part number of the device is used for the driver name.
+ * If using the NVC user driver then use the name found in this
+ * driver under _default_pdata.
+ * .gpio_count = The ARRAY_SIZE of the nvc_gpio_pdata table.
+ * .gpio = A pointer to the nvc_gpio_pdata structure's platform GPIO data.
+ * The GPIO mechanism works by cross referencing the .gpio_type key
+ * among the nvc_gpio_pdata GPIO data and the driver's nvc_gpio_init
+ * GPIO data to build a GPIO table the driver can use. The GPIO's
+ * defined in the device header file's _gpio_type enum are the
+ * gpio_type keys for the nvc_gpio_pdata and nvc_gpio_init structures.
+ * These need to be present in the board file's nvc_gpio_pdata
+ * structure for the GPIO's that are used.
+ * The driver's GPIO logic uses assert/deassert throughout until the
+ * low level _gpio_wr/rd calls where the .assert_high is used to
+ * convert the value to the correct signal level.
+ * See the GPIO notes in nvc.h for additional information.
+ *
+ * The following is specific to NVC kernel focus drivers:
+ * .nvc = Pointer to the nvc_focus_nvc structure. This structure needs to
+ * be defined and populated if overriding the driver defaults.
+ * .cap = Pointer to the nvc_focus_cap structure. This structure needs to
+ * be defined and populated if overriding the driver defaults.
+ *
+ * The following is specific to this NVC kernel focus driver:
+ * .info = Pointer to the ad5816_pdata_info structure. This structure does
+ * not need to be defined and populated unless overriding ROM data.
+ *
+ * Power Requirements:
+ * The device's header file defines the voltage regulators needed with the
+ * enumeration <device>_vreg. The order these are enumerated is the order
+ * the regulators will be enabled when powering on the device. When the
+ * device is powered off the regulators are disabled in descending order.
+ * The <device>_vregs table in this driver uses the nvc_regulator_init
+ * structure to define the regulator ID strings that go with the regulators
+ * defined with <device>_vreg. These regulator ID strings (or supply names)
+ * will be used in the regulator_get function in the _vreg_init function.
+ * The board power file and <device>_vregs regulator ID strings must match.
+ */
+
+#include <linux/fs.h>
+#include <linux/i2c.h>
+#include <linux/miscdevice.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/uaccess.h>
+#include <linux/list.h>
+#include <linux/regulator/consumer.h>
+#include <linux/gpio.h>
+#include <media/ad5816.h>
+
+#define AD5816_ID 0x04
+#define AD5816_FOCAL_LENGTH (4.570f)
+#define AD5816_FNUMBER (2.8f)
+#define AD5816_ACTUATOR_RANGE 680
+#define AD5816_SETTLETIME 110
+#define AD5816_FOCUS_MACRO 810
+#define AD5816_FOCUS_INFINITY 50 /* Exact value needs to be decided */
+#define AD5816_POS_LOW_DEFAULT 220
+#define AD5816_POS_HIGH_DEFAULT 900
+/* Need to decide exact value of VCM_THRESHOLD and its use */
+/* define AD5816_VCM_THRESHOLD 20 */
+
+static u8 ad5816_ids[] = {
+ 0x04,
+};
+
+static struct nvc_gpio_init ad5816_gpios[] = {
+ { AD5816_GPIO_RESET, GPIOF_OUT_INIT_LOW, "reset", false, true, },
+ { AD5816_GPIO_I2CMUX, 0, "i2c_mux", 0, false},
+ { AD5816_GPIO_GP1, 0, "gp1", 0, false},
+ { AD5816_GPIO_GP2, 0, "gp2", 0, false},
+ { AD5816_GPIO_GP3, 0, "gp3", 0, false},
+};
+
+static struct nvc_regulator_init ad5816_vregs[] = {
+ { AD5816_VREG_VDD, "vdd"},
+ { AD5816_VREG_VDD_AF, "vdd_af"},
+ { AD5816_VREG_VDD_I2C, "vdd_i2c"},
+};
+
+struct ad5816_info {
+ atomic_t in_use;
+ struct i2c_client *i2c_client;
+ struct ad5816_platform_data *pdata;
+ struct miscdevice miscdev;
+ struct list_head list;
+ struct nvc_gpio gpio[ARRAY_SIZE(ad5816_gpios)];
+ struct nvc_regulator vreg[ARRAY_SIZE(ad5816_vregs)];
+ int pwr_api;
+ int pwr_dev;
+ int id_minor;
+ u32 pos;
+ u8 s_mode;
+ bool reset_flag;
+ struct ad5816_info *s_info;
+ struct nvc_focus_nvc nvc;
+ struct nvc_focus_cap cap;
+ struct ad5816_pdata_info config;
+};
+
+/**
+ * The following are default values
+ */
+
+static struct ad5816_pdata_info ad5816_default_info = {
+ .pos_low = AD5816_POS_LOW_DEFAULT,
+ .pos_high = AD5816_POS_HIGH_DEFAULT,
+};
+
+static struct nvc_focus_cap ad5816_default_cap = {
+ .version = NVC_FOCUS_CAP_VER2,
+ .actuator_range = AD5816_ACTUATOR_RANGE,
+ .settle_time = AD5816_SETTLETIME,
+ .focus_macro = AD5816_FOCUS_MACRO,
+ .focus_infinity = AD5816_FOCUS_INFINITY,
+};
+
+static struct nvc_focus_nvc ad5816_default_nvc = {
+ .focal_length = AD5816_FOCAL_LENGTH,
+ .fnumber = AD5816_FNUMBER,
+};
+
+static struct ad5816_platform_data ad5816_default_pdata = {
+ .cfg = 0,
+ .num = 0,
+ .sync = 0,
+ .dev_name = "focuser",
+};
+static LIST_HEAD(ad5816_info_list);
+static DEFINE_SPINLOCK(ad5816_spinlock);
+
+static int ad5816_i2c_rd8(struct ad5816_info *info, u8 addr, u8 reg, u8 *val)
+{
+ struct i2c_msg msg[2];
+ u8 buf[2];
+ buf[0] = reg;
+ if (addr) {
+ msg[0].addr = addr;
+ msg[1].addr = addr;
+ } else {
+ msg[0].addr = info->i2c_client->addr;
+ msg[1].addr = info->i2c_client->addr;
+ }
+ msg[0].flags = 0;
+ msg[0].len = 1;
+ msg[0].buf = &buf[0];
+ msg[1].flags = I2C_M_RD;
+ msg[1].len = 1;
+ msg[1].buf = &buf[1];
+ *val = 0;
+ if (i2c_transfer(info->i2c_client->adapter, msg, 2) != 2)
+ return -EIO;
+ *val = buf[1];
+ return 0;
+}
+
+static int ad5816_i2c_wr8(struct ad5816_info *info, u8 reg, u8 val)
+{
+ struct i2c_msg msg;
+ u8 buf[2];
+ buf[0] = reg;
+ buf[1] = val;
+ msg.addr = info->i2c_client->addr;
+ msg.flags = 0;
+ msg.len = 2;
+ msg.buf = &buf[0];
+ if (i2c_transfer(info->i2c_client->adapter, &msg, 1) != 1)
+ return -EIO;
+ return 0;
+}
+
+static int ad5816_i2c_rd16(struct ad5816_info *info, u8 reg, u16 *val)
+{
+ struct i2c_msg msg[2];
+ u8 buf[3];
+ buf[0] = reg;
+ msg[0].addr = info->i2c_client->addr;
+ msg[0].flags = 0;
+ msg[0].len = 1;
+ msg[0].buf = &buf[0];
+ msg[1].addr = info->i2c_client->addr;
+ msg[1].flags = I2C_M_RD;
+ msg[1].len = 2;
+ msg[1].buf = &buf[1];
+ if (i2c_transfer(info->i2c_client->adapter, msg, 2) != 2)
+ return -EIO;
+ *val = (((u16)buf[1] << 8) | (u16)buf[2]);
+ return 0;
+}
+
+static int ad5816_i2c_wr16(struct ad5816_info *info, u8 reg, u16 val)
+{
+ struct i2c_msg msg;
+ u8 buf[3];
+ buf[0] = reg;
+ buf[1] = (u8)(val >> 8);
+ buf[2] = (u8)(val & 0xff);
+ msg.addr = info->i2c_client->addr;
+ msg.flags = 0;
+ msg.len = 3;
+ msg.buf = &buf[0];
+ if (i2c_transfer(info->i2c_client->adapter, &msg, 1) != 1)
+ return -EIO;
+ return 0;
+}
+
+static int ad5816_gpio_wr(struct ad5816_info *info,
+ enum ad5816_gpio_types i,
+ int val) /* val: 0=deassert, 1=assert */
+{
+ int err = -EINVAL;
+ if (info->gpio[i].valid) {
+ if (val)
+ val = 1;
+ if (!info->gpio[i].active_high)
+ val = !val;
+ val &= 1;
+ err = val;
+ gpio_set_value_cansleep(info->gpio[i].gpio, val);
+ dev_dbg(&info->i2c_client->dev, "%s %u %d\n", __func__, info->gpio[i].gpio, val);
+ }
+ return err; /* return value written or error */
+}
+
+static int ad5816_gpio_reset(struct ad5816_info *info, int val)
+{
+ int err = 0;
+
+ if (val) {
+ if (!info->reset_flag) {
+ info->reset_flag = true;
+ err = ad5816_gpio_wr(info, AD5816_GPIO_RESET, 1);
+ if (err < 0)
+ return 0; /* flag no reset */
+
+ mdelay(1);
+ ad5816_gpio_wr(info, AD5816_GPIO_RESET, 0);
+ mdelay(10); /* startup delay needs to be modified*/
+ err = 1; /* flag that a reset was done */
+ }
+ } else {
+ info->reset_flag = false;
+ }
+ return err;
+}
+
+static void ad5816_gpio_able(struct ad5816_info *info, int val)
+{
+ /**
+ * This is a feature that allows driver to control GPIOs
+ * that may be needed for the board (not the device).
+ * */
+ if (val) {
+ ad5816_gpio_wr(info, AD5816_GPIO_GP1, val);
+ ad5816_gpio_wr(info, AD5816_GPIO_GP2, val);
+ ad5816_gpio_wr(info, AD5816_GPIO_GP3, val);
+ } else {
+ ad5816_gpio_wr(info, AD5816_GPIO_GP3, val);
+ ad5816_gpio_wr(info, AD5816_GPIO_GP2, val);
+ ad5816_gpio_wr(info, AD5816_GPIO_GP1, val);
+ }
+}
+static void ad5816_gpio_exit(struct ad5816_info *info)
+{
+ unsigned i;
+ for (i = 0; i <= ARRAY_SIZE(ad5816_gpios); i++) {
+ if (info->gpio[i].flag && info->gpio[i].own) {
+ gpio_free(info->gpio[i].gpio);
+ info->gpio[i].own = false;
+ }
+ }
+}
+
+static void ad5816_gpio_init(struct ad5816_info *info)
+{
+ char label[32];
+ unsigned long flags;
+ unsigned type;
+ unsigned i;
+ unsigned j;
+ int err;
+ for (i = 0; i < ARRAY_SIZE(ad5816_gpios); i++)
+ info->gpio[i].flag = false;
+
+ if (!info->pdata->gpio_count || !info->pdata->gpio)
+ return;
+
+ for (i = 0; i < ARRAY_SIZE(ad5816_gpios); i++) {
+ type = ad5816_gpios[i].gpio_type;
+
+ for (j = 0; j < info->pdata->gpio_count; j++) {
+ if (type == info->pdata->gpio[j].gpio_type)
+ break;
+ }
+
+ if (j == info->pdata->gpio_count)
+ continue;
+ info->gpio[type].gpio = info->pdata->gpio[j].gpio;
+ info->gpio[type].flag = true;
+
+ if (ad5816_gpios[i].use_flags) {
+ flags = ad5816_gpios[i].flags;
+ info->gpio[type].active_high = ad5816_gpios[i].active_high;
+ } else {
+ info->gpio[type].active_high = info->pdata->gpio[j].active_high;
+ if (info->gpio[type].active_high)
+ flags = GPIOF_OUT_INIT_LOW;
+ else
+ flags = GPIOF_OUT_INIT_HIGH;
+ }
+
+ if (!info->pdata->gpio[j].init_en)
+ continue;
+ snprintf(label, sizeof(label), "ad5816_%u_%s",
+ info->pdata->num, ad5816_gpios[i].label);
+ err = gpio_request_one(info->gpio[type].gpio, flags, label);
+ if (err) {
+ dev_err(&info->i2c_client->dev, "%s ERR %s %u\n",
+ __func__, label, info->gpio[type].gpio);
+ } else {
+ info->gpio[type].own = true;
+ dev_dbg(&info->i2c_client->dev, "%s %s %u\n",
+ __func__, label, info->gpio[type].gpio);
+ }
+ }
+}
+
+static int ad5816_vreg_dis(struct ad5816_info *info,
+ enum ad5816_vreg i)
+{
+ int err = 0;
+ if (info->vreg[i].vreg_flag && (info->vreg[i].vreg != NULL)) {
+ err = regulator_disable(info->vreg[i].vreg);
+ if (!err)
+ dev_dbg(&info->i2c_client->dev, "%s: %s\n",
+ __func__, info->vreg[i].vreg_name);
+ else
+ dev_err(&info->i2c_client->dev, "%s %s ERR\n",
+ __func__, info->vreg[i].vreg_name);
+ }
+ info->vreg[i].vreg_flag = false;
+ return err;
+}
+
+static int ad5816_vreg_dis_all(struct ad5816_info *info)
+{
+ unsigned i;
+ int err = 0;
+ for (i = ARRAY_SIZE(ad5816_vregs); i > 0; i--)
+ err |= ad5816_vreg_dis(info, (i - 1));
+ return err;
+}
+
+static int ad5816_vreg_en(struct ad5816_info *info,
+ enum ad5816_vreg i)
+{
+ int err = 0;
+ if (!info->vreg[i].vreg_flag && (info->vreg[i].vreg != NULL)) {
+ err = regulator_enable(info->vreg[i].vreg);
+
+ if (!err) {
+ dev_dbg(&info->i2c_client->dev, "%s: %s\n",
+ __func__, info->vreg[i].vreg_name);
+ info->vreg[i].vreg_flag = true;
+ err = 1; /* flag regulator state change */
+ } else {
+ dev_err(&info->i2c_client->dev, "%s %s ERR\n",
+ __func__, info->vreg[i].vreg_name);
+ }
+
+ }
+ return err;
+}
+
+static int ad5816_vreg_en_all(struct ad5816_info *info)
+{
+ unsigned i;
+ int err = 0;
+ for (i = 0; i < ARRAY_SIZE(ad5816_vregs); i++)
+ err |= ad5816_vreg_en(info, i);
+ return err;
+}
+
+static void ad5816_vreg_exit(struct ad5816_info *info)
+{
+ unsigned i;
+ for (i = 0; i < ARRAY_SIZE(ad5816_vregs); i++) {
+ regulator_put(info->vreg[i].vreg);
+ info->vreg[i].vreg = NULL;
+ }
+}
+
+static int ad5816_vreg_init(struct ad5816_info *info)
+{
+ unsigned i;
+ unsigned j;
+ int err = 0;
+ for (i = 0; i < ARRAY_SIZE(ad5816_vregs); i++) {
+ j = ad5816_vregs[i].vreg_num;
+ info->vreg[j].vreg_name = ad5816_vregs[i].vreg_name;
+ info->vreg[j].vreg_flag = false;
+ info->vreg[j].vreg = regulator_get(&info->i2c_client->dev,
+ info->vreg[j].vreg_name);
+ if (IS_ERR_OR_NULL(info->vreg[j].vreg)) {
+ dev_dbg(&info->i2c_client->dev, "%s %s ERR: %d\n",
+ __func__, info->vreg[j].vreg_name,
+ (int)info->vreg[j].vreg);
+ err |= PTR_ERR(info->vreg[j].vreg);
+ info->vreg[j].vreg = NULL;
+ } else {
+ dev_dbg(&info->i2c_client->dev, "%s: %s\n",
+ __func__, info->vreg[j].vreg_name);
+ }
+ }
+ return err;
+}
+
+void ad5816_set_power_down(struct ad5816_info *info)
+{
+ int err;
+ u16 data = 0x0000;
+ err = ad5816_i2c_wr16(info, VCM_CODE_MSB, data);
+ if (err)
+ dev_err(&info->i2c_client->dev, " %s: failed \n",
+ __func__);
+}
+
+void ad5816_set_arc_mode(struct ad5816_info *info)
+{
+ int err = 0;
+ /* set ARC enable */
+ err = ad5816_i2c_wr8(info, CONTROL, 0x02);
+ if (err)
+ dev_err(&info->i2c_client->dev,
+ "%s: CONTROL reg write failed \n", __func__);
+
+ /* set the ARC RES2 */
+ err = ad5816_i2c_wr8(info, MODE, 0x01);
+ if (err)
+ dev_err(&info->i2c_client->dev,
+ "%s: MODE reg write failed \n", __func__);
+
+ /* set the VCM_FREQ to 12.8mS */
+ err = ad5816_i2c_wr8(info, VCM_FREQ, 0x80);
+ if (err)
+ dev_err(&info->i2c_client->dev,
+ "%s: VCM_FREQ reg write failed \n", __func__);
+}
+
+static int ad5816_pm_wr(struct ad5816_info *info, int pwr)
+{
+ int err = 0;
+
+ if ((info->pdata->cfg & (NVC_CFG_OFF2STDBY | NVC_CFG_BOOT_INIT)) &&
+ (pwr == NVC_PWR_OFF ||
+ pwr == NVC_PWR_STDBY_OFF))
+ pwr = NVC_PWR_STDBY;
+
+ if (pwr == info->pwr_dev)
+ return 0;
+
+ switch (pwr)
+ {
+ case NVC_PWR_OFF_FORCE:
+ case NVC_PWR_OFF:
+ err = ad5816_vreg_dis_all(info);
+ ad5816_gpio_able(info, 0);
+ ad5816_gpio_reset(info, 0);
+ break;
+ case NVC_PWR_STDBY_OFF:
+ case NVC_PWR_STDBY:
+ err = ad5816_vreg_en_all(info);
+ ad5816_gpio_able(info, 1);
+ ad5816_gpio_reset(info, 1);
+ break;
+ case NVC_PWR_COMM:
+ case NVC_PWR_ON:
+ err = ad5816_vreg_en_all(info);
+ ad5816_gpio_able(info, 1);
+ ad5816_gpio_reset(info, 1);
+ break;
+ default:
+ err = -EINVAL;
+ break;
+ }
+
+ if (err < 0) {
+ dev_err(&info->i2c_client->dev, "%s err %d\n", __func__, err);
+ pwr = NVC_PWR_ERR;
+ }
+
+ info->pwr_dev = pwr;
+ dev_dbg(&info->i2c_client->dev, "%s pwr_dev=%d\n", __func__, info->pwr_dev);
+
+ if (err > 0)
+ return 0;
+
+ return err;
+}
+static int ad5816_pm_wr_s(struct ad5816_info *info, int pwr)
+{
+ int err1 = 0;
+ int err2 = 0;
+ if ((info->s_mode == NVC_SYNC_OFF) ||
+ (info->s_mode == NVC_SYNC_MASTER) ||
+ (info->s_mode == NVC_SYNC_STEREO))
+ err1 = ad5816_pm_wr(info, pwr);
+ if ((info->s_mode == NVC_SYNC_SLAVE) ||
+ (info->s_mode == NVC_SYNC_STEREO))
+ err2 = ad5816_pm_wr(info->s_info, pwr);
+ return err1 | err2;
+}
+
+static int ad5816_pm_api_wr(struct ad5816_info *info, int pwr)
+{
+ int err = 0;
+ if (!pwr || (pwr > NVC_PWR_ON))
+ return 0;
+ if (pwr > info->pwr_dev) {
+ err = ad5816_pm_wr_s(info, pwr);
+ }
+ if (!err) {
+ info->pwr_api = pwr;
+ } else
+ info->pwr_api = NVC_PWR_ERR;
+ if (info->pdata->cfg & NVC_CFG_NOERR)
+ return 0;
+ return err;
+}
+
+static int ad5816_pm_dev_wr(struct ad5816_info *info, int pwr)
+{
+ if (pwr < info->pwr_api)
+ pwr = info->pwr_api;
+ return ad5816_pm_wr(info, pwr);
+}
+
+static void ad5816_pm_exit(struct ad5816_info *info)
+{
+ ad5816_pm_wr(info, NVC_PWR_OFF_FORCE);
+ ad5816_vreg_exit(info);
+ ad5816_gpio_exit(info);
+}
+static void ad5816_pm_init(struct ad5816_info *info)
+{
+ ad5816_gpio_init(info);
+ ad5816_vreg_init(info);
+}
+
+static int ad5816_reset(struct ad5816_info *info, u32 level)
+{
+ int err;
+ if (level == NVC_RESET_SOFT) {
+ err = ad5816_pm_wr(info, NVC_PWR_COMM);
+ err |= ad5816_i2c_wr8(info, CONTROL, 0x01); /* SW reset */
+ } else {
+ err = ad5816_pm_wr(info, NVC_PWR_OFF_FORCE);
+ }
+ err |= ad5816_pm_wr(info, info->pwr_api);
+ return err;
+}
+
+static int ad5816_dev_id(struct ad5816_info *info)
+{
+ u16 val = 0;
+ unsigned i;
+ int err;
+ ad5816_pm_dev_wr(info, NVC_PWR_COMM);
+ err = ad5816_i2c_rd16(info, IC_INFO, &val);
+ if (!err) {
+ dev_dbg(&info->i2c_client->dev, "%s found devId: %x\n", __func__, val);
+ info->id_minor = 0;
+ val = val & 0xff;
+ for (i = 0; i < ARRAY_SIZE(ad5816_ids); i++) {
+ if (val == ad5816_ids[i]) {
+ info->id_minor = val;
+ break;
+ }
+ }
+ if (!info->id_minor) {
+ err = -ENODEV;
+ dev_dbg(&info->i2c_client->dev, "%s No devId match\n", __func__);
+ }
+ }
+ ad5816_pm_dev_wr(info, NVC_PWR_OFF);
+ return err;
+}
+
+static void ad5816_sts_rd(struct ad5816_info *info)
+{
+ /**
+ * Device specific code for status
+ *
+ * TODO: Ad5816 has support to get status for over/under
+ * voltage conditions but currently this feature is not
+ * required.
+ */
+}
+/**
+ * Below are device specific functions.
+ */
+
+static int ad5816_position_rd(struct ad5816_info *info, unsigned *position)
+{
+
+ u16 pos = 0;
+ u8 t1 = 0;
+ int err = 0;
+
+ err = ad5816_i2c_rd8(info, 0, VCM_CODE_MSB, &t1);
+ pos = t1 & 0x03;
+ err = ad5816_i2c_rd8(info, 0, VCM_CODE_LSB, &t1);
+ pos = (pos << 8) | t1;
+ if(pos)
+ *position = pos - info->config.pos_low;
+ else
+ *position = info->config.pos_low;
+
+ return 0;
+}
+
+static int ad5816_position_wr(struct ad5816_info *info, unsigned position)
+{
+ position = position + info->config.pos_low;
+
+ if(position > info->config.pos_high)
+ position = info->config.pos_high;
+
+ u16 data = position & 0x03ff;
+
+ return ad5816_i2c_wr16(info, VCM_CODE_MSB, data);
+}
+
+static int ad5816_param_rd(struct ad5816_info *info, unsigned long arg)
+{
+ struct nvc_param params;
+ const void *data_ptr;
+ u32 data_size = 0;
+ u32 position;
+ int err;
+ if (copy_from_user(&params,
+ (const void __user *)arg,
+ sizeof(struct nvc_param))) {
+ dev_err(&info->i2c_client->dev, "%s %d copy_from_user err\n", __func__, __LINE__);
+ return -EFAULT;
+ }
+ if (info->s_mode == NVC_SYNC_SLAVE)
+ info = info->s_info;
+ switch (params.param) {
+ case NVC_PARAM_LOCUS:
+ ad5816_pm_dev_wr(info, NVC_PWR_COMM);
+ err = ad5816_position_rd(info, &position);
+ if (err && !(info->pdata->cfg & NVC_CFG_NOERR))
+ return err;
+ data_ptr = &position;
+ data_size = sizeof(position);
+ ad5816_pm_dev_wr(info, NVC_PWR_STDBY);
+ dev_dbg(&info->i2c_client->dev, "%s LOCUS: %d\n",
+ __func__, position);
+ break;
+ case NVC_PARAM_FOCAL_LEN:
+ info->nvc.focal_length = AD5816_FOCAL_LENGTH;
+ data_ptr = &info->nvc.focal_length;
+ data_size = sizeof(info->nvc.focal_length);
+ break;
+ case NVC_PARAM_MAX_APERTURE:
+ data_ptr = &info->nvc.max_aperature;
+ data_size = sizeof(info->nvc.max_aperature);
+ dev_dbg(&info->i2c_client->dev, "%s MAX_APERTURE: %x\n",
+ __func__, info->nvc.max_aperature);
+ break;
+ case NVC_PARAM_FNUMBER:
+ data_ptr = &info->nvc.fnumber;
+ data_size = sizeof(info->nvc.fnumber);
+ dev_dbg(&info->i2c_client->dev, "%s FNUMBER: %u\n",
+ __func__, info->nvc.fnumber);
+ break;
+ case NVC_PARAM_CAPS:
+ data_ptr = &info->cap;
+ /* there are different sizes depending on the version */
+ /* send back just what's requested or our max size */
+ if (params.sizeofvalue < sizeof(info->cap))
+ data_size = params.sizeofvalue;
+ else
+ data_size = sizeof(info->cap);
+ dev_err(&info->i2c_client->dev, "%s CAPS\n", __func__);
+ break;
+ case NVC_PARAM_STS:
+ /*data_ptr = &info->sts;
+ data_size = sizeof(info->sts);*/
+ dev_dbg(&info->i2c_client->dev, "%s \n", __func__);
+ break;
+ case NVC_PARAM_STEREO:
+ data_ptr = &info->s_mode;
+ data_size = sizeof(info->s_mode);
+ dev_err(&info->i2c_client->dev, "%s STEREO: %d\n", __func__, info->s_mode);
+ break;
+ default:
+ dev_err(&info->i2c_client->dev, "%s unsupported parameter: %d\n",
+ __func__, params.param);
+ return -EINVAL;
+ }
+ if (params.sizeofvalue < data_size) {
+ dev_err(&info->i2c_client->dev,
+ "%s data size mismatch %d != %d Param: %d\n",
+ __func__, params.sizeofvalue, data_size, params.param);
+ return -EINVAL;
+ }
+ if (copy_to_user((void __user *)params.p_value, data_ptr, data_size)) {
+ dev_err(&info->i2c_client->dev, "%s copy_to_user err line %d\n",
+ __func__, __LINE__);
+ return -EFAULT;
+ }
+ return 0;
+}
+
+static int ad5816_param_wr_s(struct ad5816_info *info,
+ struct nvc_param *params,
+ u32 u32val)
+{
+ struct nvc_focus_cap cap;
+ u8 u8val;
+ int err = 0;
+ u8val = (u8)u32val;
+ switch (params->param) {
+ case NVC_PARAM_LOCUS:
+ dev_dbg(&info->i2c_client->dev, "%s LOCUS: %u\n", __func__, u32val);
+ err = ad5816_position_wr(info, u32val);
+ return err;
+ case NVC_PARAM_RESET:
+ err = ad5816_reset(info, u32val);
+ dev_dbg(&info->i2c_client->dev, "%s RESET: %d\n", __func__, err);
+ return err;
+ case NVC_PARAM_SELF_TEST:
+ err = 0;
+ dev_dbg(&info->i2c_client->dev, "%s SELF_TEST: %d\n", __func__, err);
+ return err;
+ default:
+ dev_dbg(&info->i2c_client->dev,
+ "%s unsupported parameter: %d\n",
+ __func__, params->param);
+ return -EINVAL;
+ }
+}
+
+static int ad5816_param_wr(struct ad5816_info *info, unsigned long arg)
+{
+ struct nvc_param params;
+ u8 u8val;
+ u32 u32val;
+ int err = 0;
+ if (copy_from_user(&params, (const void __user *)arg,
+ sizeof(struct nvc_param))) {
+ dev_err(&info->i2c_client->dev, "%s copy_from_user err line %d\n",
+ __func__, __LINE__);
+ return -EFAULT;
+ }
+ if (copy_from_user(&u32val, (const void __user *)params.p_value, sizeof(u32val))) {
+ dev_err(&info->i2c_client->dev, "%s %d copy_from_user err\n", __func__, __LINE__);
+ return -EFAULT;
+ }
+ u8val = (u8)u32val;
+ /* parameters independent of sync mode */
+ switch (params.param) {
+ case NVC_PARAM_STEREO:
+ dev_dbg(&info->i2c_client->dev, "%s STEREO: %d\n", __func__, u8val);
+ if (u8val == info->s_mode)
+ return 0;
+ switch (u8val) {
+ case NVC_SYNC_OFF:
+ info->s_mode = u8val;
+ ad5816_gpio_wr(info, AD5816_GPIO_I2CMUX, 0);
+ if (info->s_info != NULL) {
+ info->s_info->s_mode = u8val;
+ ad5816_pm_wr(info->s_info, NVC_PWR_OFF);
+ }
+ break;
+ case NVC_SYNC_MASTER:
+ info->s_mode = u8val;
+ ad5816_gpio_wr(info, AD5816_GPIO_I2CMUX, 0);
+ if (info->s_info != NULL)
+ info->s_info->s_mode = u8val;
+ break;
+ case NVC_SYNC_SLAVE:
+ if (info->s_info != NULL) {
+ /* default slave lens position */
+ err = ad5816_position_wr(info->s_info,
+ info->s_info->cap.focus_infinity);
+ if (!err) {
+ info->s_mode = u8val;
+ info->s_info->s_mode = u8val;
+ ad5816_gpio_wr(info,
+ AD5816_GPIO_I2CMUX, 0);
+ }
+ else {
+ if (info->s_mode != NVC_SYNC_STEREO)
+ ad5816_pm_wr(info->s_info,
+ NVC_PWR_OFF);
+ err = -EIO;
+ }
+ } else {
+ err = -EINVAL;
+ }
+ break;
+ case NVC_SYNC_STEREO:
+ if (info->s_info != NULL) {
+ /* sync power */
+ info->s_info->pwr_api = info->pwr_api;
+ /* move slave lens to master position */
+ err = ad5816_position_wr(info->s_info, info->pos);
+ if (!err) {
+ info->s_mode = u8val;
+ info->s_info->s_mode = u8val;
+ ad5816_gpio_wr(info, AD5816_GPIO_I2CMUX, 1);
+ }
+ else {
+ if (info->s_mode != NVC_SYNC_SLAVE)
+ ad5816_pm_wr(info->s_info, NVC_PWR_OFF);
+ err = -EIO;
+ }
+ } else {
+ err = -EINVAL;
+ }
+ break;
+ default:
+ err = -EINVAL;
+ }
+ if (info->pdata->cfg & NVC_CFG_NOERR)
+ return 0;
+ return err;
+ default:
+ /* parameters dependent on sync mode */
+ switch (info->s_mode) {
+ case NVC_SYNC_OFF:
+ case NVC_SYNC_MASTER:
+ return ad5816_param_wr_s(info, &params, u32val);
+ case NVC_SYNC_SLAVE:
+ return ad5816_param_wr_s(info->s_info, &params, u32val);
+ case NVC_SYNC_STEREO:
+ err = ad5816_param_wr_s(info, &params, u32val);
+ if (!(info->pdata->cfg & NVC_CFG_SYNC_I2C_MUX))
+ err |= ad5816_param_wr_s(info->s_info,
+ &params,
+ u32val);
+ return err;
+ default:
+ dev_err(&info->i2c_client->dev, "%s %d internal err\n",
+ __func__, __LINE__);
+ return -EINVAL;
+ }
+ }
+}
+
+static long ad5816_ioctl(struct file *file,
+ unsigned int cmd,
+ unsigned long arg)
+{
+ struct ad5816_info *info = file->private_data;
+ int pwr;
+ int err = 0;
+ switch (cmd) {
+ case NVC_IOCTL_PARAM_WR:
+ err = ad5816_param_wr(info, arg);
+ return err;
+ case NVC_IOCTL_PARAM_RD:
+ err = ad5816_param_rd(info, arg);
+ return err;
+ case NVC_IOCTL_PWR_WR:
+ /* This is a Guaranteed Level of Service (GLOS) call */
+ pwr = (int)arg * 2;
+ dev_dbg(&info->i2c_client->dev, "%s PWR_WR: %d\n",
+ __func__, pwr);
+ err = ad5816_pm_api_wr(info, pwr);
+ return err;
+ case NVC_IOCTL_PWR_RD:
+ if (info->s_mode == NVC_SYNC_SLAVE)
+ pwr = info->s_info->pwr_api / 2;
+ else
+ pwr = info->pwr_api / 2;
+ dev_dbg(&info->i2c_client->dev, "%s PWR_RD: %d\n",
+ __func__, pwr);
+ if (copy_to_user((void __user *)arg, (const void *)&pwr, sizeof(pwr))) {
+ dev_err(&info->i2c_client->dev, "%s copy_to_user err line %d\n",
+ __func__, __LINE__);
+ return -EFAULT;
+ }
+ return 0;
+ default:
+ dev_dbg(&info->i2c_client->dev, "%s unsupported ioctl: %x\n", __func__, cmd);
+ }
+ return -EINVAL;
+}
+
+
+static void ad5816_sdata_init(struct ad5816_info *info)
+{
+ /* set defaults */
+ memcpy(&info->config, &ad5816_default_info, sizeof(info->config));
+ memcpy(&info->nvc, &ad5816_default_nvc, sizeof(info->nvc));
+ memcpy(&info->cap, &ad5816_default_cap, sizeof(info->cap));
+
+ info->config.settle_time = AD5816_SETTLETIME;
+ info->config.focal_length = AD5816_FOCAL_LENGTH;
+ info->config.fnumber = AD5816_FNUMBER;
+ info->config.pos_low = AD5816_POS_LOW_DEFAULT;
+ info->config.pos_high = AD5816_POS_HIGH_DEFAULT;
+
+ /* set to proper value */
+ info->cap.actuator_range = info->config.pos_high - info->config.pos_low;
+
+ /* set overrides if any */
+ if (info->pdata->nvc) {
+ if (info->pdata->nvc->fnumber)
+ info->nvc.fnumber = info->pdata->nvc->fnumber;
+ if (info->pdata->nvc->focal_length)
+ info->nvc.focal_length = info->pdata->nvc->focal_length;
+ if (info->pdata->nvc->max_aperature)
+ info->nvc.max_aperature = info->pdata->nvc->max_aperature;
+ }
+
+ if (info->pdata->cap) {
+ if (info->pdata->cap->actuator_range)
+ info->cap.actuator_range = info->pdata->cap->actuator_range;
+ if (info->pdata->cap->settle_time)
+ info->cap.settle_time = info->pdata->cap->settle_time;
+ if (info->pdata->cap->focus_macro)
+ info->cap.focus_macro = info->pdata->cap->focus_macro;
+ if (info->pdata->cap->focus_hyper)
+ info->cap.focus_hyper = info->pdata->cap->focus_hyper;
+ if (info->pdata->cap->focus_infinity)
+ info->cap.focus_infinity = info->pdata->cap->focus_infinity;
+ }
+}
+
+static int ad5816_sync_en(unsigned num, unsigned sync)
+{
+ struct ad5816_info *master = NULL;
+ struct ad5816_info *slave = NULL;
+ struct ad5816_info *pos = NULL;
+ rcu_read_lock();
+ list_for_each_entry_rcu(pos, &ad5816_info_list, list) {
+ if (pos->pdata->num == num) {
+ master = pos;
+ break;
+ }
+ }
+ pos = NULL;
+ list_for_each_entry_rcu(pos, &ad5816_info_list, list) {
+ if (pos->pdata->num == sync) {
+ slave = pos;
+ break;
+ }
+ }
+ rcu_read_unlock();
+ if (master != NULL)
+ master->s_info = NULL;
+ if (slave != NULL)
+ slave->s_info = NULL;
+ if (!sync)
+ return 0; /* no err if sync disabled */
+ if (num == sync)
+ return -EINVAL; /* err if sync instance is itself */
+ if ((master != NULL) && (slave != NULL)) {
+ master->s_info = slave;
+ slave->s_info = master;
+ }
+ return 0;
+}
+
+static int ad5816_sync_dis(struct ad5816_info *info)
+{
+ if (info->s_info != NULL) {
+ info->s_info->s_mode = 0;
+ info->s_info->s_info = NULL;
+ info->s_mode = 0;
+ info->s_info = NULL;
+ return 0;
+ }
+ return -EINVAL;
+}
+
+static int ad5816_open(struct inode *inode, struct file *file)
+{
+ struct ad5816_info *info = NULL;
+ struct ad5816_info *pos = NULL;
+ int err;
+ rcu_read_lock();
+ list_for_each_entry_rcu(pos, &ad5816_info_list, list) {
+ if (pos->miscdev.minor == iminor(inode)) {
+ info = pos;
+ break;
+ }
+ }
+ rcu_read_unlock();
+ if (!info)
+ return -ENODEV;
+ err = ad5816_sync_en(info->pdata->num, info->pdata->sync);
+ if (err == -EINVAL)
+ dev_err(&info->i2c_client->dev, "%s err: invalid num (%u) and sync (%u) instance\n",
+ __func__, info->pdata->num, info->pdata->sync);
+ if (atomic_xchg(&info->in_use, 1))
+ return -EBUSY;
+ if (info->s_info != NULL) {
+ if (atomic_xchg(&info->s_info->in_use, 1))
+ return -EBUSY;
+ }
+ file->private_data = info;
+ ad5816_pm_dev_wr(info, NVC_PWR_ON);
+ /* set ARC Mode to ensure faster focus */
+ ad5816_set_arc_mode(info);
+ dev_dbg(&info->i2c_client->dev, "%s\n", __func__);
+
+ return 0;
+}
+
+static int ad5816_release(struct inode *inode, struct file *file)
+{
+ struct ad5816_info *info = file->private_data;
+ dev_dbg(&info->i2c_client->dev, "%s\n", __func__);
+ ad5816_pm_wr_s(info, NVC_PWR_OFF);
+ file->private_data = NULL;
+ WARN_ON(!atomic_xchg(&info->in_use, 0));
+ if (info->s_info != NULL)
+ WARN_ON(!atomic_xchg(&info->s_info->in_use, 0));
+ ad5816_sync_dis(info);
+ return 0;
+}
+
+static const struct file_operations ad5816_fileops = {
+ .owner = THIS_MODULE,
+ .open = ad5816_open,
+ .unlocked_ioctl = ad5816_ioctl,
+ .release = ad5816_release,
+};
+
+static void ad5816_del(struct ad5816_info *info)
+{
+ ad5816_pm_exit(info);
+ if ((info->s_mode == NVC_SYNC_SLAVE) ||
+ (info->s_mode == NVC_SYNC_STEREO))
+ ad5816_pm_exit(info->s_info);
+
+ ad5816_sync_dis(info);
+ spin_lock(&ad5816_spinlock);
+ list_del_rcu(&info->list);
+ spin_unlock(&ad5816_spinlock);
+ synchronize_rcu();
+}
+
+static int ad5816_remove(struct i2c_client *client)
+{
+ struct ad5816_info *info = i2c_get_clientdata(client);
+ dev_dbg(&info->i2c_client->dev, "%s\n", __func__);
+ misc_deregister(&info->miscdev);
+ ad5816_del(info);
+ return 0;
+}
+
+static int ad5816_probe(
+ struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ pr_info("ad5816: probing focuser.\n");
+ struct ad5816_info *info;
+ char dname[16];
+ int err;
+ dev_dbg(&client->dev, "%s\n", __func__);
+ info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL);
+ if (info == NULL) {
+ dev_err(&client->dev, "%s: kzalloc error\n", __func__);
+ return -ENOMEM;
+ }
+ info->i2c_client = client;
+ if (client->dev.platform_data) {
+ info->pdata = client->dev.platform_data;
+ } else {
+ info->pdata = &ad5816_default_pdata;
+ dev_dbg(&client->dev,"%s No platform data. Using defaults.\n", __func__);
+ }
+
+ i2c_set_clientdata(client, info);
+ INIT_LIST_HEAD(&info->list);
+ spin_lock(&ad5816_spinlock);
+ list_add_rcu(&info->list, &ad5816_info_list);
+ spin_unlock(&ad5816_spinlock);
+ ad5816_pm_init(info);
+ ad5816_sdata_init(info);
+
+ err = ad5816_dev_id(info);
+ if (err < 0) {
+ dev_err(&client->dev, "%s device not found\n", __func__);
+ ad5816_pm_wr(info, NVC_PWR_OFF);
+ if (info->pdata->cfg & NVC_CFG_NODEV) {
+ ad5816_del(info);
+ return -ENODEV;
+ }
+ } else {
+ dev_dbg(&client->dev, "%s device found\n", __func__);
+ if (info->pdata->cfg & NVC_CFG_BOOT_INIT) {
+ /* initial move causes full initialization */
+ ad5816_pm_dev_wr(info, NVC_PWR_ON);
+ ad5816_position_wr(info, info->cap.focus_infinity);
+ ad5816_pm_dev_wr(info, NVC_PWR_OFF);
+ }
+ }
+
+ if (info->pdata->dev_name != 0)
+ strcpy(dname, info->pdata->dev_name);
+ else
+ strcpy(dname, "ad5816");
+
+ if (info->pdata->num)
+ snprintf(dname, sizeof(dname), "%s.%u", dname, info->pdata->num);
+
+ info->miscdev.name = dname;
+ info->miscdev.fops = &ad5816_fileops;
+ info->miscdev.minor = MISC_DYNAMIC_MINOR;
+ if (misc_register(&info->miscdev)) {
+ dev_err(&client->dev, "%s unable to register misc device %s\n",
+ __func__, dname);
+ ad5816_del(info);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+
+static const struct i2c_device_id ad5816_id[] = {
+ { "ad5816", 0 },
+ { },
+};
+
+
+MODULE_DEVICE_TABLE(i2c, ad5816_id);
+
+static struct i2c_driver ad5816_i2c_driver = {
+ .driver = {
+ .name = "ad5816",
+ .owner = THIS_MODULE,
+ },
+ .id_table = ad5816_id,
+ .probe = ad5816_probe,
+ .remove = ad5816_remove,
+};
+
+static int __init ad5816_init(void)
+{
+ return i2c_add_driver(&ad5816_i2c_driver);
+}
+
+static void __exit ad5816_exit(void)
+{
+ i2c_del_driver(&ad5816_i2c_driver);
+}
+
+module_init(ad5816_init);
+module_exit(ad5816_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/tps80031.c b/drivers/mfd/tps80031.c
index 94ba777bcdb3..f0f2ce1f6840 100644
--- a/drivers/mfd/tps80031.c
+++ b/drivers/mfd/tps80031.c
@@ -105,6 +105,9 @@
#define TPS80031_CFG_INPUT_PUPD3 0xF2
#define TPS80031_CFG_INPUT_PUPD4 0xF3
+#define TPS80031_BBSPOR_CFG 0xE6
+#define TPS80031_BBSPOR_CHG_EN 0x8
+
struct tps80031_pupd_data {
u8 reg;
u8 pullup_bit;
@@ -568,6 +571,17 @@ static void tps80031_pupd_init(struct tps80031 *tps80031,
}
}
+static void tps80031_backup_battery_charger_control(struct tps80031 *tps80031,
+ int enable)
+{
+ if (enable)
+ tps80031_update(tps80031->dev, SLAVE_ID1, TPS80031_BBSPOR_CFG,
+ TPS80031_BBSPOR_CHG_EN, TPS80031_BBSPOR_CHG_EN);
+ else
+ tps80031_update(tps80031->dev, SLAVE_ID1, TPS80031_BBSPOR_CFG,
+ 0, TPS80031_BBSPOR_CHG_EN);
+}
+
static void tps80031_init_ext_control(struct tps80031 *tps80031,
struct tps80031_platform_data *pdata) {
int ret;
@@ -1287,6 +1301,8 @@ static int __devinit tps80031_i2c_probe(struct i2c_client *client,
tps80031_debuginit(tps80031);
+ tps80031_backup_battery_charger_control(tps80031, 1);
+
if (pdata->use_power_off && !pm_power_off)
pm_power_off = tps80031_power_off;
@@ -1302,13 +1318,17 @@ fail:
#ifdef CONFIG_PM
static int tps80031_i2c_suspend(struct i2c_client *client, pm_message_t state)
{
+ struct tps80031 *tps80031 = i2c_get_clientdata(client);
if (client->irq)
disable_irq(client->irq);
+ tps80031_backup_battery_charger_control(tps80031, 0);
return 0;
}
static int tps80031_i2c_resume(struct i2c_client *client)
{
+ struct tps80031 *tps80031 = i2c_get_clientdata(client);
+ tps80031_backup_battery_charger_control(tps80031, 1);
if (client->irq)
enable_irq(client->irq);
return 0;
diff --git a/drivers/misc/tegra-baseband/bb-m7400.c b/drivers/misc/tegra-baseband/bb-m7400.c
index 5808a6e321cd..99698a860917 100644
--- a/drivers/misc/tegra-baseband/bb-m7400.c
+++ b/drivers/misc/tegra-baseband/bb-m7400.c
@@ -28,10 +28,12 @@
#include <linux/device.h>
#include <linux/usb.h>
#include <linux/wakelock.h>
+#include <linux/platform_data/tegra_usb.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <mach/tegra-bb-power.h>
#include <mach/usb_phy.h>
+
#include "bb-power.h"
static struct tegra_bb_gpio_data m7400_gpios[] = {
@@ -193,20 +195,17 @@ static int m7400_power(int code)
static void m7400_ehci_customize(struct platform_device *pdev)
{
- struct tegra_ehci_platform_data *ehci_pdata;
- struct tegra_uhsic_config *hsic_config;
+ struct tegra_usb_platform_data *ehci_pdata;
- ehci_pdata = (struct tegra_ehci_platform_data *)
+ ehci_pdata = (struct usb_platform_data *)
pdev->dev.platform_data;
- hsic_config = (struct tegra_uhsic_config *)
- ehci_pdata->phy_config;
/* Register PHY callbacks */
- hsic_config->postsuspend = m7400_l2_suspend;
- hsic_config->preresume = m7400_l2_resume;
+ ehci_pdata->ops->post_suspend = m7400_l2_suspend;
+ ehci_pdata->ops->pre_resume = m7400_l2_resume;
/* Override required settings */
- ehci_pdata->power_down_on_bus_suspend = 0;
+ ehci_pdata->u_data.host.power_off_on_suspend = false;
}
static int m7400_attrib_write(struct device *dev, int value)
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 8fec147471a8..609fd6391d1f 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -545,11 +545,6 @@ static int tegra_sdhci_signal_voltage_switch(struct sdhci_host *sdhci,
u16 clk, ctrl;
unsigned int val;
- /* Switch OFF the card clock to prevent glitches on the clock line */
- clk = sdhci_readw(sdhci, SDHCI_CLOCK_CONTROL);
- clk &= ~SDHCI_CLOCK_CARD_EN;
- sdhci_writew(sdhci, clk, SDHCI_CLOCK_CONTROL);
-
ctrl = sdhci_readw(sdhci, SDHCI_HOST_CONTROL2);
if (signal_voltage == MMC_SIGNAL_VOLTAGE_180) {
ctrl |= SDHCI_CTRL_VDD_180;
@@ -559,6 +554,17 @@ static int tegra_sdhci_signal_voltage_switch(struct sdhci_host *sdhci,
if (ctrl & SDHCI_CTRL_VDD_180)
ctrl &= ~SDHCI_CTRL_VDD_180;
}
+
+ /* Check if the slot can support the required voltage */
+ if (min_uV > tegra_host->vddio_max_uv)
+ return 0;
+
+ /* Switch OFF the card clock to prevent glitches on the clock line */
+ clk = sdhci_readw(sdhci, SDHCI_CLOCK_CONTROL);
+ clk &= ~SDHCI_CLOCK_CARD_EN;
+ sdhci_writew(sdhci, clk, SDHCI_CLOCK_CONTROL);
+
+ /* Set/clear the 1.8V signalling */
sdhci_writew(sdhci, ctrl, SDHCI_HOST_CONTROL2);
/* Switch the I/O rail voltage */
diff --git a/drivers/net/wireless/bcm4329/wl_iw.c b/drivers/net/wireless/bcm4329/wl_iw.c
index 434e584f830c..e71ab64c2caa 100644
--- a/drivers/net/wireless/bcm4329/wl_iw.c
+++ b/drivers/net/wireless/bcm4329/wl_iw.c
@@ -5109,6 +5109,7 @@ wl_iw_set_pmksa(
uint i;
int ret = 0;
char eabuf[ETHER_ADDR_STR_LEN];
+ pmkid_t * pmkid_array = pmkid_list.pmkids.pmkid;
WL_WSEC(("%s: SIOCSIWPMKSA\n", dev->name));
CHECK_EXTRA_FOR_NULL(extra);
@@ -5139,18 +5140,18 @@ wl_iw_set_pmksa(
}
for (i = 0; i < pmkid_list.pmkids.npmkid; i++)
- if (!bcmp(&iwpmksa->bssid.sa_data[0], &pmkid_list.pmkids.pmkid[i].BSSID,
+ if (!bcmp(&iwpmksa->bssid.sa_data[0], &pmkid_array[i].BSSID,
ETHER_ADDR_LEN))
break;
if ((pmkid_list.pmkids.npmkid > 0) && (i < pmkid_list.pmkids.npmkid)) {
- bzero(&pmkid_list.pmkids.pmkid[i], sizeof(pmkid_t));
+ bzero(&pmkid_array[i], sizeof(pmkid_t));
for (; i < (pmkid_list.pmkids.npmkid - 1); i++) {
- bcopy(&pmkid_list.pmkids.pmkid[i+1].BSSID,
- &pmkid_list.pmkids.pmkid[i].BSSID,
+ bcopy(&pmkid_array[i+1].BSSID,
+ &pmkid_array[i].BSSID,
ETHER_ADDR_LEN);
- bcopy(&pmkid_list.pmkids.pmkid[i+1].PMKID,
- &pmkid_list.pmkids.pmkid[i].PMKID,
+ bcopy(&pmkid_array[i+1].PMKID,
+ &pmkid_array[i].PMKID,
WPA2_PMKID_LEN);
}
pmkid_list.pmkids.npmkid--;
@@ -5161,14 +5162,14 @@ wl_iw_set_pmksa(
else if (iwpmksa->cmd == IW_PMKSA_ADD) {
for (i = 0; i < pmkid_list.pmkids.npmkid; i++)
- if (!bcmp(&iwpmksa->bssid.sa_data[0], &pmkid_list.pmkids.pmkid[i].BSSID,
+ if (!bcmp(&iwpmksa->bssid.sa_data[0], &pmkid_array[i].BSSID,
ETHER_ADDR_LEN))
break;
if (i < MAXPMKID) {
bcopy(&iwpmksa->bssid.sa_data[0],
- &pmkid_list.pmkids.pmkid[i].BSSID,
+ &pmkid_array[i].BSSID,
ETHER_ADDR_LEN);
- bcopy(&iwpmksa->pmkid[0], &pmkid_list.pmkids.pmkid[i].PMKID,
+ bcopy(&iwpmksa->pmkid[0], &pmkid_array[i].PMKID,
WPA2_PMKID_LEN);
if (i == pmkid_list.pmkids.npmkid)
pmkid_list.pmkids.npmkid++;
@@ -5181,10 +5182,10 @@ wl_iw_set_pmksa(
uint k;
k = pmkid_list.pmkids.npmkid;
WL_WSEC(("wl_iw_set_pmksa,IW_PMKSA_ADD - PMKID: %s = ",
- bcm_ether_ntoa(&pmkid_list.pmkids.pmkid[k].BSSID,
+ bcm_ether_ntoa(&pmkid_array[k].BSSID,
eabuf)));
for (j = 0; j < WPA2_PMKID_LEN; j++)
- WL_WSEC(("%02x ", pmkid_list.pmkids.pmkid[k].PMKID[j]));
+ WL_WSEC(("%02x ", pmkid_array[k].PMKID[j]));
WL_WSEC(("\n"));
}
}
@@ -5192,10 +5193,10 @@ wl_iw_set_pmksa(
for (i = 0; i < pmkid_list.pmkids.npmkid; i++) {
uint j;
WL_WSEC(("PMKID[%d]: %s = ", i,
- bcm_ether_ntoa(&pmkid_list.pmkids.pmkid[i].BSSID,
+ bcm_ether_ntoa(&pmkid_array[i].BSSID,
eabuf)));
for (j = 0; j < WPA2_PMKID_LEN; j++)
- WL_WSEC(("%02x ", pmkid_list.pmkids.pmkid[i].PMKID[j]));
+ WL_WSEC(("%02x ", pmkid_array[i].PMKID[j]));
WL_WSEC(("\n"));
}
WL_WSEC(("\n"));
diff --git a/drivers/spi/spi-tegra.c b/drivers/spi/spi-tegra.c
index 4901114f746c..d4b9c3344eee 100644
--- a/drivers/spi/spi-tegra.c
+++ b/drivers/spi/spi-tegra.c
@@ -144,7 +144,6 @@
#define DATA_DIR_TX (1 << 0)
#define DATA_DIR_RX (1 << 1)
-#define SPI_FIFO_DEPTH 32
#define SLINK_DMA_TIMEOUT (msecs_to_jiffies(1000))
@@ -169,7 +168,7 @@ static const unsigned long spi_tegra_req_sels[] = {
RX_FIFO_FULL_COUNT_ZERO << 16)
#define MAX_CHIP_SELECT 4
-#define SLINK_FIFO_DEPTH 4
+#define SLINK_FIFO_DEPTH 32
struct spi_tegra_data {
struct spi_master *master;
@@ -247,6 +246,9 @@ struct spi_tegra_data {
struct work_struct spi_transfer_work;
};
+static int tegra_spi_runtime_idle(struct device *dev);
+static int tegra_spi_runtime_resume(struct device *dev);
+
static inline unsigned long spi_tegra_readl(struct spi_tegra_data *tspi,
unsigned long reg)
{
@@ -261,6 +263,9 @@ static inline void spi_tegra_writel(struct spi_tegra_data *tspi,
if (!tspi->clk_state)
BUG();
writel(val, tspi->base + reg);
+
+ /* Synchronize write by reading back the register */
+ readl(tspi->base + SLINK_MAS_DATA);
}
static void cancel_dma(struct tegra_dma_channel *dma_chan,
@@ -731,12 +736,7 @@ static void spi_tegra_start_transfer(struct spi_device *spi,
command2 = tspi->def_command2_reg;
if (is_first_of_msg) {
- if (!tspi->is_clkon_always) {
- if (!tspi->clk_state) {
- pm_runtime_get_sync(&tspi->pdev->dev);
- tspi->clk_state = 1;
- }
- }
+ pm_runtime_get_sync(&tspi->pdev->dev);
spi_tegra_clear_status(tspi);
@@ -806,7 +806,7 @@ static void spi_tegra_start_transfer(struct spi_device *spi,
spi_tegra_writel(tspi, command2, SLINK_COMMAND2);
tspi->command2_reg = command2;
- if (total_fifo_words > SPI_FIFO_DEPTH)
+ if (total_fifo_words > SLINK_FIFO_DEPTH)
ret = spi_tegra_start_dma_based_transfer(tspi, t);
else
ret = spi_tegra_start_cpu_based_transfer(tspi, t);
@@ -848,6 +848,8 @@ static int spi_tegra_setup(struct spi_device *spi)
return -EINVAL;
}
+ pm_runtime_get_sync(&tspi->pdev->dev);
+
spin_lock_irqsave(&tspi->lock, flags);
val = tspi->def_command_reg;
if (spi->mode & SPI_CS_HIGH)
@@ -855,20 +857,10 @@ static int spi_tegra_setup(struct spi_device *spi)
else
val &= ~cs_bit;
tspi->def_command_reg = val;
-
- if (!tspi->is_clkon_always && !tspi->clk_state) {
- spin_unlock_irqrestore(&tspi->lock, flags);
- pm_runtime_get_sync(&tspi->pdev->dev);
- spin_lock_irqsave(&tspi->lock, flags);
- tspi->clk_state = 1;
- }
spi_tegra_writel(tspi, tspi->def_command_reg, SLINK_COMMAND);
- if (!tspi->is_clkon_always && tspi->clk_state) {
- tspi->clk_state = 0;
- spin_unlock_irqrestore(&tspi->lock, flags);
- pm_runtime_put_sync(&tspi->pdev->dev);
- } else
- spin_unlock_irqrestore(&tspi->lock, flags);
+ spin_unlock_irqrestore(&tspi->lock, flags);
+
+ pm_runtime_put_sync(&tspi->pdev->dev);
return 0;
}
@@ -1010,19 +1002,11 @@ static void spi_tegra_curr_transfer_complete(struct spi_tegra_data *tspi,
SLINK_COMMAND);
spi_tegra_writel(tspi, tspi->def_command2_reg,
SLINK_COMMAND2);
- if (!tspi->is_clkon_always) {
- if (tspi->clk_state) {
- /* Provide delay to stablize the signal
- state */
- spin_unlock_irqrestore(&tspi->lock,
- *irq_flags);
- udelay(10);
- pm_runtime_put_sync(&tspi->pdev->dev);
- spin_lock_irqsave(&tspi->lock,
- *irq_flags);
- tspi->clk_state = 0;
- }
- }
+ /* Provide delay to stablize the signal state */
+ spin_unlock_irqrestore(&tspi->lock, *irq_flags);
+ udelay(10);
+ pm_runtime_put_sync(&tspi->pdev->dev);
+ spin_lock_irqsave(&tspi->lock, *irq_flags);
tspi->is_transfer_in_progress = false;
/* Check if any new request has come between
* clock disable */
@@ -1173,7 +1157,7 @@ static irqreturn_t spi_tegra_isr_thread(int irq, void *context_data)
/* Continue transfer in current message */
total_fifo_words = spi_tegra_calculate_curr_xfer_param(tspi->cur_spi,
tspi, t);
- if (total_fifo_words > SPI_FIFO_DEPTH)
+ if (total_fifo_words > SLINK_FIFO_DEPTH)
err = spi_tegra_start_dma_based_transfer(tspi, t);
else
err = spi_tegra_start_cpu_based_transfer(tspi, t);
@@ -1201,6 +1185,87 @@ static irqreturn_t spi_tegra_isr(int irq, void *context_data)
return IRQ_WAKE_THREAD;
}
+static void spi_tegra_deinit_dma_param(struct spi_tegra_data *tspi,
+ bool dma_to_memory)
+{
+ struct tegra_dma_channel *tdc;
+ u32 *dma_buf;
+ dma_addr_t dma_phys;
+
+ if (dma_to_memory) {
+ dma_buf = tspi->rx_buf;
+ tdc = tspi->rx_dma;
+ dma_phys = tspi->rx_buf_phys;
+ tspi->rx_dma = NULL;
+ tspi->rx_buf = NULL;
+ } else {
+ dma_buf = tspi->tx_buf;
+ tdc = tspi->tx_dma;
+ dma_phys = tspi->tx_buf_phys;
+ tspi->tx_buf = NULL;
+ tspi->tx_dma = NULL;
+ }
+
+ dma_free_coherent(&tspi->pdev->dev, tspi->dma_buf_size,
+ dma_buf, dma_phys);
+ tegra_dma_free_channel(tdc);
+}
+
+static int __init spi_tegra_init_dma_param(struct spi_tegra_data *tspi,
+ bool dma_to_memory)
+{
+ struct tegra_dma_req *dma_req;
+ struct tegra_dma_channel *tdc;
+ u32 *dma_buf;
+ dma_addr_t dma_phys;
+
+ tdc = tegra_dma_allocate_channel(TEGRA_DMA_MODE_ONESHOT, "spi_%s_%d",
+ (dma_to_memory) ? "rx" : "tx", tspi->pdev->id);
+ if (!tdc) {
+ dev_err(&tspi->pdev->dev, "can not allocate rx dma channel\n");
+ return -ENODEV;
+ }
+
+ dma_buf = dma_alloc_coherent(&tspi->pdev->dev, tspi->dma_buf_size,
+ &dma_phys, GFP_KERNEL);
+ if (!dma_buf) {
+ dev_err(&tspi->pdev->dev, "can not allocate rx bounce buffer");
+ tegra_dma_free_channel(tdc);
+ return -ENOMEM;
+ }
+
+ dma_req = (dma_to_memory) ? &tspi->rx_dma_req : &tspi->tx_dma_req;
+ memset(dma_req, 0, sizeof(*dma_req));
+
+ dma_req->req_sel = spi_tegra_req_sels[tspi->pdev->id];
+ dma_req->dev = tspi;
+ dma_req->dest_bus_width = 32;
+ dma_req->source_bus_width = 32;
+ dma_req->to_memory = (dma_to_memory) ? 1 : 0;
+ dma_req->virt_addr = dma_buf;
+ dma_req->dest_wrap = 0;
+ dma_req->source_wrap = 0;
+
+ if (dma_to_memory) {
+ dma_req->complete = tegra_spi_rx_dma_complete;
+ dma_req->dest_addr = dma_phys;
+ dma_req->source_addr = tspi->phys + SLINK_RX_FIFO;
+ dma_req->source_wrap = 4;
+ tspi->rx_buf_phys = dma_phys;
+ tspi->rx_buf = dma_buf;
+ tspi->rx_dma = tdc;
+ } else {
+ dma_req->complete = tegra_spi_tx_dma_complete;
+ dma_req->dest_addr = tspi->phys + SLINK_TX_FIFO;
+ dma_req->source_addr = dma_phys;
+ dma_req->dest_wrap = 4;
+ tspi->tx_buf = dma_buf;
+ tspi->tx_buf_phys = dma_phys;
+ tspi->tx_dma = tdc;
+ }
+ return 0;
+}
+
static int __init spi_tegra_probe(struct platform_device *pdev)
{
struct spi_master *master;
@@ -1236,55 +1301,50 @@ static int __init spi_tegra_probe(struct platform_device *pdev)
spin_lock_init(&tspi->lock);
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (r == NULL) {
+ if (!r) {
+ dev_err(&pdev->dev, "No IO memory resource\n");
ret = -ENODEV;
- goto fail_no_mem;
- }
-
- if (!request_mem_region(r->start, resource_size(r),
- dev_name(&pdev->dev))) {
- ret = -EBUSY;
- goto fail_no_mem;
+ goto exit_free_master;
}
-
tspi->phys = r->start;
- tspi->base = ioremap(r->start, resource_size(r));
+ tspi->base = devm_request_and_ioremap(&pdev->dev, r);
if (!tspi->base) {
- dev_err(&pdev->dev, "can't ioremap iomem\n");
- ret = -ENOMEM;
- goto fail_io_map;
+ dev_err(&pdev->dev,
+ "Cannot request memregion/iomap dma address\n");
+ ret = -EADDRNOTAVAIL;
+ goto exit_free_master;
}
spi_irq = platform_get_irq(pdev, 0);
if (unlikely(spi_irq < 0)) {
dev_err(&pdev->dev, "can't find irq resource\n");
ret = -ENXIO;
- goto fail_irq_req;
+ goto exit_free_master;
}
tspi->irq = spi_irq;
sprintf(tspi->port_name, "tegra_spi_%d", pdev->id);
- ret = request_threaded_irq(tspi->irq, spi_tegra_isr,
- spi_tegra_isr_thread, IRQF_ONESHOT,
+ ret = devm_request_threaded_irq(&pdev->dev, tspi->irq,
+ spi_tegra_isr, spi_tegra_isr_thread, IRQF_ONESHOT,
tspi->port_name, tspi);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to register ISR for IRQ %d\n",
tspi->irq);
- goto fail_irq_req;
+ goto exit_free_master;
}
- tspi->clk = clk_get(&pdev->dev, "spi");
+ tspi->clk = devm_clk_get(&pdev->dev, "spi");
if (IS_ERR(tspi->clk)) {
dev_err(&pdev->dev, "can not get clock\n");
ret = PTR_ERR(tspi->clk);
- goto fail_clk_get;
+ goto exit_free_master;
}
- tspi->sclk = clk_get(&pdev->dev, "sclk");
+ tspi->sclk = devm_clk_get(&pdev->dev, "sclk");
if (IS_ERR(tspi->sclk)) {
dev_err(&pdev->dev, "can not get sclock\n");
ret = PTR_ERR(tspi->sclk);
- goto fail_sclk_get;
+ goto exit_free_master;
}
INIT_LIST_HEAD(&tspi->queue);
@@ -1327,84 +1387,41 @@ static int __init spi_tegra_probe(struct platform_device *pdev)
init_completion(&tspi->tx_dma_complete);
init_completion(&tspi->rx_dma_complete);
-
- tspi->rx_dma = tegra_dma_allocate_channel(TEGRA_DMA_MODE_ONESHOT,
- "spi_rx_%d", pdev->id);
- if (!tspi->rx_dma) {
- dev_err(&pdev->dev, "can not allocate rx dma channel\n");
- ret = -ENODEV;
- goto fail_rx_dma_alloc;
- }
-
- tspi->rx_buf = dma_alloc_coherent(&pdev->dev, tspi->dma_buf_size,
- &tspi->rx_buf_phys, GFP_KERNEL);
- if (!tspi->rx_buf) {
- dev_err(&pdev->dev, "can not allocate rx bounce buffer\n");
- ret = -ENOMEM;
- goto fail_rx_buf_alloc;
- }
-
- memset(&tspi->rx_dma_req, 0, sizeof(struct tegra_dma_req));
- tspi->rx_dma_req.complete = tegra_spi_rx_dma_complete;
- tspi->rx_dma_req.to_memory = 1;
- tspi->rx_dma_req.dest_addr = tspi->rx_buf_phys;
- tspi->rx_dma_req.virt_addr = tspi->rx_buf;
- tspi->rx_dma_req.dest_bus_width = 32;
- tspi->rx_dma_req.source_addr = tspi->phys + SLINK_RX_FIFO;
- tspi->rx_dma_req.source_bus_width = 32;
- tspi->rx_dma_req.source_wrap = 4;
- tspi->rx_dma_req.dest_wrap = 0;
- tspi->rx_dma_req.req_sel = spi_tegra_req_sels[pdev->id];
- tspi->rx_dma_req.dev = tspi;
-
- tspi->tx_dma = tegra_dma_allocate_channel(TEGRA_DMA_MODE_ONESHOT,
- "spi_tx_%d", pdev->id);
- if (!tspi->tx_dma) {
- dev_err(&pdev->dev, "can not allocate tx dma channel\n");
- ret = -ENODEV;
- goto fail_tx_dma_alloc;
+ ret = spi_tegra_init_dma_param(tspi, true);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Error in rx dma init\n");
+ goto exit_free_master;
}
- tspi->tx_buf = dma_alloc_coherent(&pdev->dev, tspi->dma_buf_size,
- &tspi->tx_buf_phys, GFP_KERNEL);
- if (!tspi->tx_buf) {
- dev_err(&pdev->dev, "can not allocate tx bounce buffer\n");
- ret = -ENOMEM;
- goto fail_tx_buf_alloc;
+ ret = spi_tegra_init_dma_param(tspi, false);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Error in tx dma init\n");
+ goto exit_rx_dma_free;
}
- memset(&tspi->tx_dma_req, 0, sizeof(struct tegra_dma_req));
- tspi->tx_dma_req.complete = tegra_spi_tx_dma_complete;
- tspi->tx_dma_req.to_memory = 0;
- tspi->tx_dma_req.dest_addr = tspi->phys + SLINK_TX_FIFO;
- tspi->tx_dma_req.virt_addr = tspi->tx_buf;
- tspi->tx_dma_req.dest_bus_width = 32;
- tspi->tx_dma_req.dest_wrap = 4;
- tspi->tx_dma_req.source_wrap = 0;
- tspi->tx_dma_req.source_addr = tspi->tx_buf_phys;
- tspi->tx_dma_req.source_bus_width = 32;
- tspi->tx_dma_req.req_sel = spi_tegra_req_sels[pdev->id];
- tspi->tx_dma_req.dev = tspi;
tspi->max_buf_size = tspi->dma_buf_size;
tspi->def_command_reg = SLINK_CS_SW | SLINK_M_S;
tspi->def_command2_reg = SLINK_CS_ACTIVE_BETWEEN;
skip_dma_alloc:
pm_runtime_enable(&pdev->dev);
- pm_runtime_get_sync(&pdev->dev);
- tspi->clk_state = 1;
- master->dev.of_node = pdev->dev.of_node;
- ret = spi_register_master(master);
- if (!tspi->is_clkon_always) {
- if (tspi->clk_state) {
- pm_runtime_put_sync(&pdev->dev);
- tspi->clk_state = 0;
+ if (!pm_runtime_enabled(&pdev->dev)) {
+ ret = tegra_spi_runtime_resume(&pdev->dev);
+ if (ret) {
+ dev_err(&pdev->dev, "runtime resume failed %d", ret);
+ goto exit_pm_disable;
}
}
+ /* Enable clock if it is require to be enable always */
+ if (tspi->is_clkon_always)
+ pm_runtime_get_sync(&pdev->dev);
+
+ master->dev.of_node = pdev->dev.of_node;
+ ret = spi_register_master(master);
if (ret < 0) {
dev_err(&pdev->dev, "can not register to master err %d\n", ret);
- goto fail_master_register;
+ goto exit_pm_suspend;
}
/* create the workqueue for the kbc path */
@@ -1413,42 +1430,32 @@ skip_dma_alloc:
if (!tspi->spi_workqueue) {
dev_err(&pdev->dev, "Failed to create work queue\n");
ret = -ENODEV;
- goto fail_workqueue;
+ goto exit_master_unregister;
}
INIT_WORK(&tspi->spi_transfer_work, tegra_spi_transfer_work);
return ret;
-fail_workqueue:
+exit_master_unregister:
spi_unregister_master(master);
-fail_master_register:
- if (tspi->tx_buf)
- dma_free_coherent(&pdev->dev, tspi->dma_buf_size,
- tspi->tx_buf, tspi->tx_buf_phys);
-fail_tx_buf_alloc:
- if (tspi->tx_dma)
- tegra_dma_free_channel(tspi->tx_dma);
-fail_tx_dma_alloc:
- if (tspi->rx_buf)
- dma_free_coherent(&pdev->dev, tspi->dma_buf_size,
- tspi->rx_buf, tspi->rx_buf_phys);
-fail_rx_buf_alloc:
- if (tspi->rx_dma)
- tegra_dma_free_channel(tspi->rx_dma);
-fail_rx_dma_alloc:
+ if (tspi->is_clkon_always)
+ pm_runtime_put_sync(&pdev->dev);
+
+exit_pm_suspend:
+ if (!pm_runtime_status_suspended(&pdev->dev))
+ tegra_spi_runtime_idle(&pdev->dev);
+
+exit_pm_disable:
pm_runtime_disable(&pdev->dev);
- clk_put(tspi->sclk);
-fail_sclk_get:
- clk_put(tspi->clk);
-fail_clk_get:
- free_irq(tspi->irq, tspi);
-fail_irq_req:
- iounmap(tspi->base);
-fail_io_map:
- release_mem_region(r->start, resource_size(r));
-fail_no_mem:
+
+ spi_tegra_deinit_dma_param(tspi, false);
+
+exit_rx_dma_free:
+ spi_tegra_deinit_dma_param(tspi, true);
+
+exit_free_master:
spi_master_put(master);
return ret;
}
@@ -1457,56 +1464,44 @@ static int __devexit spi_tegra_remove(struct platform_device *pdev)
{
struct spi_master *master;
struct spi_tegra_data *tspi;
- struct resource *r;
master = dev_get_drvdata(&pdev->dev);
tspi = spi_master_get_devdata(master);
spi_unregister_master(master);
- if (tspi->tx_buf)
- dma_free_coherent(&pdev->dev, tspi->dma_buf_size,
- tspi->tx_buf, tspi->tx_buf_phys);
+
if (tspi->tx_dma)
- tegra_dma_free_channel(tspi->tx_dma);
- if (tspi->rx_buf)
- dma_free_coherent(&pdev->dev, tspi->dma_buf_size,
- tspi->rx_buf, tspi->rx_buf_phys);
+ spi_tegra_deinit_dma_param(tspi, false);
+
if (tspi->rx_dma)
- tegra_dma_free_channel(tspi->rx_dma);
+ spi_tegra_deinit_dma_param(tspi, true);
- if (tspi->is_clkon_always) {
+ /* Disable clock if it is always enabled */
+ if (tspi->is_clkon_always)
pm_runtime_put_sync(&pdev->dev);
- tspi->clk_state = 0;
- }
pm_runtime_disable(&pdev->dev);
- clk_put(tspi->sclk);
- clk_put(tspi->clk);
- iounmap(tspi->base);
+ if (!pm_runtime_status_suspended(&pdev->dev))
+ tegra_spi_runtime_idle(&pdev->dev);
destroy_workqueue(tspi->spi_workqueue);
- r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- release_mem_region(r->start, resource_size(r));
-
return 0;
}
#ifdef CONFIG_PM
-static int spi_tegra_suspend(struct platform_device *pdev, pm_message_t state)
+static int spi_tegra_suspend(struct device *dev)
{
- struct spi_master *master;
- struct spi_tegra_data *tspi;
- unsigned limit = 50;
+ struct spi_master *master = dev_get_drvdata(dev);
+ struct spi_tegra_data *tspi = spi_master_get_devdata(master);
+ unsigned limit = 50;
unsigned long flags;
- master = dev_get_drvdata(&pdev->dev);
- tspi = spi_master_get_devdata(master);
spin_lock_irqsave(&tspi->lock, flags);
/* Wait for all transfer completes */
if (!list_empty(&tspi->queue))
- dev_warn(&pdev->dev, "The transfer list is not empty "
+ dev_warn(dev, "The transfer list is not empty "
"Waiting for time %d ms to complete transfer\n",
limit * 20);
@@ -1520,7 +1515,7 @@ static int spi_tegra_suspend(struct platform_device *pdev, pm_message_t state)
tspi->is_suspended = true;
if (!list_empty(&tspi->queue)) {
limit = 50;
- dev_err(&pdev->dev, "All transfer has not completed, "
+ dev_err(dev, "All transfer has not completed, "
"Waiting for %d ms current transfer to complete\n",
limit * 20);
while (tspi->is_transfer_in_progress && limit--) {
@@ -1531,7 +1526,7 @@ static int spi_tegra_suspend(struct platform_device *pdev, pm_message_t state)
}
if (tspi->is_transfer_in_progress) {
- dev_err(&pdev->dev,
+ dev_err(dev,
"Spi transfer is in progress Avoiding suspend\n");
tspi->is_suspended = false;
spin_unlock_irqrestore(&tspi->lock, flags);
@@ -1539,33 +1534,32 @@ static int spi_tegra_suspend(struct platform_device *pdev, pm_message_t state)
}
spin_unlock_irqrestore(&tspi->lock, flags);
- if (tspi->is_clkon_always) {
- pm_runtime_put_sync(&pdev->dev);
- tspi->clk_state = 0;
- }
+
+ /* Disable clock if it is always enabled */
+ if (tspi->is_clkon_always)
+ pm_runtime_put_sync(dev);
+
return 0;
}
-static int spi_tegra_resume(struct platform_device *pdev)
+static int spi_tegra_resume(struct device *dev)
{
- struct spi_master *master;
- struct spi_tegra_data *tspi;
+ struct spi_master *master = dev_get_drvdata(dev);
+ struct spi_tegra_data *tspi = spi_master_get_devdata(master);
struct spi_message *m;
struct spi_device *spi;
struct spi_transfer *t = NULL;
int single_xfer = 0;
unsigned long flags;
- master = dev_get_drvdata(&pdev->dev);
- tspi = spi_master_get_devdata(master);
+ /* Enable clock if it is always enabled */
+ if (tspi->is_clkon_always)
+ pm_runtime_get_sync(dev);
- pm_runtime_get_sync(&pdev->dev);
- tspi->clk_state = 1;
+ pm_runtime_get_sync(dev);
spi_tegra_writel(tspi, tspi->command_reg, SLINK_COMMAND);
- if (!tspi->is_clkon_always) {
- pm_runtime_put_sync(&pdev->dev);
- tspi->clk_state = 0;
- }
+ pm_runtime_put_sync(dev);
+
spin_lock_irqsave(&tspi->lock, flags);
tspi->cur_speed = 0;
@@ -1587,15 +1581,15 @@ static int spi_tegra_resume(struct platform_device *pdev)
}
#endif
-#if defined(CONFIG_PM_RUNTIME)
-
static int tegra_spi_runtime_idle(struct device *dev)
{
- struct spi_master *master;
- struct spi_tegra_data *tspi;
- master = dev_get_drvdata(dev);
- tspi = spi_master_get_devdata(master);
+ struct spi_master *master = dev_get_drvdata(dev);
+ struct spi_tegra_data *tspi = spi_master_get_devdata(master);
+
+ /* Flush all write which are in PPSB queue by reading back */
+ spi_tegra_readl(tspi, SLINK_MAS_DATA);
+ tspi->clk_state = 0;
clk_disable(tspi->clk);
clk_disable(tspi->sclk);
return 0;
@@ -1603,22 +1597,25 @@ static int tegra_spi_runtime_idle(struct device *dev)
static int tegra_spi_runtime_resume(struct device *dev)
{
- struct spi_master *master;
- struct spi_tegra_data *tspi;
- master = dev_get_drvdata(dev);
- tspi = spi_master_get_devdata(master);
+ struct spi_master *master = dev_get_drvdata(dev);
+ struct spi_tegra_data *tspi = spi_master_get_devdata(master);
clk_enable(tspi->sclk);
clk_enable(tspi->clk);
+ tspi->clk_state = 1;
return 0;
}
static const struct dev_pm_ops tegra_spi_dev_pm_ops = {
+#if defined(CONFIG_PM_RUNTIME)
.runtime_idle = tegra_spi_runtime_idle,
.runtime_resume = tegra_spi_runtime_resume,
-};
-
#endif
+#ifdef CONFIG_PM
+ .suspend = spi_tegra_suspend,
+ .resume = spi_tegra_resume,
+#endif
+};
MODULE_ALIAS("platform:spi_tegra");
@@ -1636,16 +1633,10 @@ static struct platform_driver spi_tegra_driver = {
.driver = {
.name = "spi_tegra",
.owner = THIS_MODULE,
-#if defined(CONFIG_PM_RUNTIME)
.pm = &tegra_spi_dev_pm_ops,
-#endif
.of_match_table = spi_tegra_of_match_table,
},
.remove = __devexit_p(spi_tegra_remove),
-#ifdef CONFIG_PM
- .suspend = spi_tegra_suspend,
- .resume = spi_tegra_resume,
-#endif
};
static int __init spi_tegra_init(void)
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index fedd8eef4ae2..c8c7c687010d 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -1,7 +1,6 @@
#
# USB peripheral controller drivers
#
-GCOV_PROFILE_fsl_tegra_udc.o := y
GCOV_PROFILE_tegra_udc.o := y
ccflags-$(CONFIG_USB_GADGET_DEBUG) := -DDEBUG
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index fbafe8a3bca4..4805670cf6e3 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -319,6 +319,13 @@ static int mtp_function_ctrlrequest(struct android_usb_function *f,
return mtp_ctrlrequest(cdev, c);
}
+static int ptp_function_ctrlrequest(struct android_usb_function *f,
+ struct usb_composite_dev *cdev,
+ const struct usb_ctrlrequest *c)
+{
+ return mtp_ctrlrequest(cdev, c);
+}
+
static struct android_usb_function mtp_function = {
.name = "mtp",
.init = mtp_function_init,
@@ -333,6 +340,7 @@ static struct android_usb_function ptp_function = {
.init = ptp_function_init,
.cleanup = ptp_function_cleanup,
.bind_config = ptp_function_bind_config,
+ .ctrlrequest = ptp_function_ctrlrequest,
};
diff --git a/drivers/usb/gadget/fsl_tegra_udc.c b/drivers/usb/gadget/fsl_tegra_udc.c
deleted file mode 100644
index 31b476ad2279..000000000000
--- a/drivers/usb/gadget/fsl_tegra_udc.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Description:
- * Helper functions to support the tegra USB controller
- *
- * 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.
- */
-#include <linux/fsl_devices.h>
-#include <linux/platform_device.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <mach/usb_phy.h>
-
-static struct tegra_usb_phy *phy;
-static struct clk *udc_clk;
-static struct clk *emc_clk;
-static struct clk *sclk_clk;
-static void *udc_base;
-
-int fsl_udc_clk_init(struct platform_device *pdev)
-{
- struct resource *res;
- int err;
- int instance;
- struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
-
-
- udc_clk = clk_get(&pdev->dev, NULL);
- if (IS_ERR(udc_clk)) {
- dev_err(&pdev->dev, "Can't get udc clock\n");
- return PTR_ERR(udc_clk);
- }
-
- clk_enable(udc_clk);
-
- sclk_clk = clk_get(&pdev->dev, "sclk");
- if (IS_ERR(sclk_clk)) {
- dev_err(&pdev->dev, "Can't get sclk clock\n");
- err = PTR_ERR(sclk_clk);
- goto err_sclk;
- }
-
- clk_set_rate(sclk_clk, 80000000);
- clk_enable(sclk_clk);
-
- emc_clk = clk_get(&pdev->dev, "emc");
- if (IS_ERR(emc_clk)) {
- dev_err(&pdev->dev, "Can't get emc clock\n");
- err = PTR_ERR(emc_clk);
- goto err_emc;
- }
-
- clk_enable(emc_clk);
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- /* Set DDR busy hints to 150MHz. For Tegra 2x SOC, DDR rate is half of EMC rate */
- clk_set_rate(emc_clk, 300000000);
-#else
- /* Set DDR busy hints to 100MHz. For Tegra 3x SOC DDR rate equals to EMC rate */
- clk_set_rate(emc_clk, 100000000);
-#endif
-
- /* we have to remap the registers ourselves as fsl_udc does not
- * export them for us.
- */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- err = -ENXIO;
- goto err0;
- }
- udc_base = ioremap(res->start, resource_size(res));
- if (!udc_base) {
- err = -ENOMEM;
- goto err0;
- }
-
- instance = pdev->id;
- if (instance == -1)
- instance = 0;
-
- phy = tegra_usb_phy_open(instance, udc_base, pdata->phy_config,
- TEGRA_USB_PHY_MODE_DEVICE, pdata->usb_phy_type);
- if (IS_ERR(phy)) {
- dev_err(&pdev->dev, "Can't open phy\n");
- err = PTR_ERR(phy);
- goto err1;
- }
- tegra_usb_phy_power_on(phy, true);
-
- return 0;
-err1:
- iounmap(udc_base);
-err0:
- clk_disable(emc_clk);
- clk_put(emc_clk);
-err_emc:
- clk_disable(sclk_clk);
- clk_put(sclk_clk);
-err_sclk:
- clk_disable(udc_clk);
- clk_put(udc_clk);
- return err;
-}
-
-void fsl_udc_clk_finalize(struct platform_device *pdev)
-{
-}
-
-void fsl_udc_clk_release(void)
-{
- tegra_usb_phy_close(phy);
-
- iounmap(udc_base);
-
- clk_disable(udc_clk);
- clk_put(udc_clk);
-
- clk_disable(sclk_clk);
- clk_put(sclk_clk);
-
- clk_disable(emc_clk);
- clk_put(emc_clk);
-}
-
-void fsl_udc_clk_suspend(bool is_dpd)
-{
- tegra_usb_phy_power_off(phy, is_dpd);
- clk_disable(udc_clk);
- clk_disable(sclk_clk);
- clk_disable(emc_clk);
-}
-
-void fsl_udc_clk_resume(bool is_dpd)
-{
- clk_enable(emc_clk);
- clk_enable(sclk_clk);
- clk_enable(udc_clk);
- tegra_usb_phy_power_on(phy, is_dpd);
-}
-
-void fsl_udc_clk_enable(void)
-{
- clk_enable(udc_clk);
-}
-
-void fsl_udc_clk_disable(void)
-{
- clk_disable(udc_clk);
-}
-
-bool fsl_udc_charger_detect(void)
-{
- return tegra_usb_phy_charger_detect(phy);
-}
-
-void fsl_udc_dtd_prepare(void)
-{
- /* When we are programming two DTDs very close to each other,
- * the second DTD is being prefetched before it is actually written
- * to DDR. To prevent this, we disable prefetcher before programming
- * any new DTD and re-enable it before priming endpoint.
- */
- tegra_usb_phy_memory_prefetch_off(phy);
-}
-
-void fsl_udc_ep_barrier(void)
-{
- tegra_usb_phy_memory_prefetch_on(phy);
-}
diff --git a/drivers/usb/gadget/tegra_udc.c b/drivers/usb/gadget/tegra_udc.c
index 978db7ece1de..f978f0f2d1e7 100644
--- a/drivers/usb/gadget/tegra_udc.c
+++ b/drivers/usb/gadget/tegra_udc.c
@@ -37,7 +37,6 @@
#include <linux/workqueue.h>
#include <linux/err.h>
#include <linux/io.h>
-#include <linux/fsl_devices.h> /* check this */
#include <asm/byteorder.h>
#include <asm/io.h>
@@ -50,14 +49,10 @@
#include "tegra_udc.h"
-/* #define IS_NEW_PHY_DRIVER 1 */
-
-#ifndef IS_NEW_PHY_DRIVER
-#include "fsl_tegra_udc.c"
-#endif
#define DRIVER_DESC "Nvidia Tegra High-Speed USB SOC \
- Device Controller driver"
+ Device Controller driver"
+
#define DRIVER_AUTHOR "Venkat Moganty/Rakesh Bodla"
#define DRIVER_VERSION "Apr 30, 2012"
#define USB1_PREFETCH_ID 6
@@ -73,7 +68,6 @@
& USB_DIR_IN) == USB_DIR_IN)
-
static const char driver_name[] = "tegra-udc";
static const char driver_desc[] = DRIVER_DESC;
@@ -136,7 +130,7 @@ static void done(struct tegra_ep *ep, struct tegra_req *req, int status)
unsigned char stopped = ep->stopped;
struct ep_td_struct *curr_td, *next_td;
int j;
-
+ BUG_ON(!(in_irq() || irqs_disabled()));
udc = (struct tegra_udc *)ep->udc;
/* Removed the req from tegra_ep->queue */
list_del_init(&req->queue);
@@ -186,19 +180,20 @@ static void done(struct tegra_ep *ep, struct tegra_req *req, int status)
}
#endif
- spin_unlock(&ep->udc->lock);
/* complete() is from gadget layer,
* eg fsg->bulk_in_complete() */
- if (req->req.complete)
+ if (req->req.complete) {
+ spin_unlock(&ep->udc->lock);
req->req.complete(&ep->ep, &req->req);
+ spin_lock(&ep->udc->lock);
+ }
- spin_lock(&ep->udc->lock);
ep->stopped = stopped;
}
/*
* nuke(): delete all requests related to this ep
- * called with spinlock held
+ * Must be called with spinlock held and interrupt disabled
*/
static void nuke(struct tegra_ep *ep, int status)
{
@@ -733,11 +728,7 @@ static void tegra_queue_td(struct tegra_ep *ep, struct tegra_req *req)
| EP_QUEUE_HEAD_STATUS_HALT));
dQH->size_ioc_int_sts &= temp;
-#ifdef IS_NEW_PHY_DRIVER
tegra_usb_phy_memory_prefetch_on(udc->phy);
-#else
- fsl_udc_ep_barrier();
-#endif
/* Ensure that updates to the QH will occur before priming. */
wmb();
@@ -828,11 +819,7 @@ static int tegra_req_to_dtd(struct tegra_req *req, gfp_t gfp_flags)
struct ep_td_struct *last_dtd = NULL, *dtd;
dma_addr_t dma;
-#ifdef IS_NEW_PHY_DRIVER
tegra_usb_phy_memory_prefetch_off(the_udc->phy);
-#else
- fsl_udc_dtd_prepare();
-#endif
do {
dtd = tegra_build_dtd(req, &count, &dma, &is_last, gfp_flags);
@@ -1229,20 +1216,20 @@ static int tegra_set_selfpowered(struct usb_gadget *gadget, int is_on)
}
/**
- * Notify controller that VBUS is powered, Called by whatever
+ * Notify controller that VBUS is powered, called by whatever
* detects VBUS sessions
*/
static int tegra_vbus_session(struct usb_gadget *gadget, int is_active)
{
struct tegra_udc *udc = container_of(gadget, struct tegra_udc, gadget);
-
+ unsigned long flags;
DBG("%s(%d) turn VBUS state from %s to %s", __func__, __LINE__,
udc->vbus_active ? "on" : "off", is_active ? "on" : "off");
if (udc->vbus_active && !is_active) {
/* If cable disconnected, cancel any delayed work */
cancel_delayed_work(&udc->work);
- spin_lock(&udc->lock);
+ spin_lock_irqsave(&udc->lock, flags);
/* reset all internal Queues and inform client driver */
reset_queues(udc);
/* stop the controller and turn off the clocks */
@@ -1250,23 +1237,15 @@ static int tegra_vbus_session(struct usb_gadget *gadget, int is_active)
dr_controller_reset(udc);
udc->vbus_active = 0;
udc->usb_state = USB_STATE_DEFAULT;
- spin_unlock(&udc->lock);
-#ifdef IS_NEW_PHY_DRIVER
+ spin_unlock_irqrestore(&udc->lock,flags);
tegra_usb_phy_power_off(udc->phy);
-#else
- fsl_udc_clk_suspend(false);
-#endif
if (udc->vbus_reg) {
/* set the current limit to 0mA */
regulator_set_current_limit(
udc->vbus_reg, 0, 0);
}
} else if (!udc->vbus_active && is_active) {
-#ifdef IS_NEW_PHY_DRIVER
tegra_usb_phy_power_on(udc->phy);
-#else
- fsl_udc_clk_resume(false);
-#endif
/* setup the controller in the device mode */
dr_controller_setup(udc);
/* setup EP0 for setup packet */
@@ -1348,12 +1327,7 @@ static void tegra_udc_release(struct device *dev)
struct tegra_udc *udc = platform_get_drvdata(pdev);
complete(udc->done);
-#ifdef IS_NEW_PHY_DRIVER
tegra_usb_phy_close(udc->phy);
-#else
- fsl_udc_clk_suspend(false);
-#endif
-
kfree(udc);
}
@@ -2109,15 +2083,18 @@ static void tegra_udc_irq_work(struct work_struct *irq_work)
{
struct tegra_udc *udc = container_of(irq_work, struct tegra_udc,
irq_work);
+ DBG("%s(%d) BEGIN\n", __func__, __LINE__);
/* Check whether cable is connected*/
if (vbus_enabled(udc))
tegra_vbus_session(&udc->gadget, 1);
else
tegra_vbus_session(&udc->gadget, 0);
+
+ DBG("%s(%d) END\n", __func__, __LINE__);
}
-/*
+/**
* If VBUS is detected and setup packet is not received in 100ms then
* work thread starts and checks for the USB charger detection.
*/
@@ -2127,11 +2104,7 @@ static void tegra_udc_charger_detect_work(struct work_struct *work)
DBG("%s(%d) BEGIN\n", __func__, __LINE__);
/* check for the platform charger detection */
-#ifdef IS_NEW_PHY_DRIVER
if (tegra_usb_phy_charger_detected(udc->phy)) {
-#else
- if (fsl_udc_charger_detect()) {
-#endif
printk(KERN_INFO "USB compliant charger detected\n");
/* check udc regulator is available for drawing vbus current*/
if (udc->vbus_reg) {
@@ -2271,8 +2244,6 @@ static int tegra_udc_start(struct usb_gadget_driver *driver,
if (!udc)
return -ENODEV;
-
-
if (!driver || (driver->speed != USB_SPEED_FULL
&& driver->speed != USB_SPEED_HIGH)
|| !bind || !driver->disconnect
@@ -2404,7 +2375,7 @@ static int tegra_udc_setup_qh(struct tegra_udc *udc)
/* FIXME: tegra_alloc_request() ignores ep argument */
udc->status_req = container_of(tegra_alloc_request(NULL, GFP_KERNEL),
struct tegra_req, req);
- /* allocate a small amount of memory to get valid address */
+ /* Allocate a small amount of memory to get valid address */
udc->status_req->req.buf = dma_alloc_coherent(&udc->pdev->dev,
STATUS_BUFFER_SIZE, &udc->status_req->req.dma,
GFP_KERNEL);
@@ -2552,7 +2523,6 @@ static int __init tegra_udc_probe(struct platform_device *pdev)
goto err_iounmap;
}
-#ifdef IS_NEW_PHY_DRIVER
udc->phy = tegra_usb_phy_open(pdev);
if (IS_ERR(udc->phy)) {
dev_err(&pdev->dev, "failed to open USB phy\n");
@@ -2571,23 +2541,10 @@ static int __init tegra_udc_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "failed to init the phy\n");
goto err_phy;
}
-#else
- /* Initialize USB clocks */
- fsl_udc_clk_init(pdev);
-#endif
spin_lock_init(&udc->lock);
udc->stopped = 1;
udc->pdev = pdev;
-#ifdef IS_NEW_PHY_DRIVER
udc->has_hostpc = tegra_usb_phy_has_hostpc(udc->phy) ? 1 : 0;
-#else
- #ifdef CONFIG_ARCH_TEGRA_2x_SOC
- udc->has_hostpc = 0;
- #else
- udc->has_hostpc = 1;
- #endif
-#endif
-
platform_set_drvdata(pdev, udc);
/* Initialize the udc structure including QH members */
@@ -2597,7 +2554,7 @@ static int __init tegra_udc_probe(struct platform_device *pdev)
goto err_phy;
}
- /* initialize usb hw reg except for regs for EP,
+ /* Initialize usb hw reg except for regs for EP,
* leave usbintr reg untouched */
err = dr_controller_setup(udc);
if (err) {
@@ -2617,7 +2574,7 @@ static int __init tegra_udc_probe(struct platform_device *pdev)
goto err_unregister;
}
- /* use dma_pool for TD management */
+ /* Use dma_pool for TD management */
udc->td_pool = dma_pool_create("udc_td", &pdev->dev,
sizeof(struct ep_td_struct),
DTD_ALIGNMENT, UDC_DMA_BOUNDARY);
@@ -2638,9 +2595,9 @@ static int __init tegra_udc_probe(struct platform_device *pdev)
PM_QOS_DEFAULT_VALUE);
#endif
- /* create a work for controlling clocks to the phy if otg is disabled */
+ /* Create work for controlling clocks to the phy if otg is disabled */
INIT_WORK(&udc->irq_work, tegra_udc_irq_work);
- /* create a delayed work for detecting the USB charger */
+ /* Create a delayed work for detecting the USB charger */
INIT_DELAYED_WORK(&udc->work, tegra_udc_charger_detect_work);
INIT_WORK(&udc->charger_work, tegra_udc_set_current_limit_work);
@@ -2654,35 +2611,21 @@ static int __init tegra_udc_probe(struct platform_device *pdev)
}
#ifdef CONFIG_USB_OTG_UTILS
-
-#ifdef IS_NEW_PHY_DRIVER
if (tegra_usb_phy_otg_supported(udc->phy))
udc->transceiver = otg_get_transceiver();
-#else
- udc->transceiver = otg_get_transceiver();
-#endif
if (udc->transceiver) {
dr_controller_stop(udc);
dr_controller_reset(udc);
-#ifdef IS_NEW_PHY_DRIVER
tegra_usb_phy_power_off(udc->phy);
-#else
- fsl_udc_clk_suspend(false);
-#endif
udc->vbus_active = 0;
udc->usb_state = USB_STATE_DEFAULT;
otg_set_peripheral(udc->transceiver, &udc->gadget);
}
#else
/* Power down the phy if cable is not connected */
- if (!vbus_enabled()) {
-#ifdef IS_NEW_PHY_DRIVER
+ if (!vbus_enabled())
tegra_usb_phy_power_off(udc->phy);
-#else
- fsl_udc_clk_suspend(false);
-#endif
- }
#endif
DBG("%s(%d) END\n", __func__, __LINE__);
@@ -2694,15 +2637,11 @@ err_del_udc:
err_unregister:
device_unregister(&udc->gadget.dev);
-#ifdef IS_NEW_PHY_DRIVER
err_phy:
tegra_usb_phy_close(udc->phy);
err_irq:
free_irq(udc->irq, udc);
-#else
-err_phy:
-#endif
err_iounmap:
iounmap(udc->regs);
@@ -2743,9 +2682,6 @@ static int __exit tegra_udc_remove(struct platform_device *pdev)
if (udc->transceiver)
otg_set_peripheral(udc->transceiver, NULL);
-#ifndef IS_NEW_PHY_DRIVER
- fsl_udc_clk_release();
-#endif
/* Free allocated memory */
dma_free_coherent(&pdev->dev, STATUS_BUFFER_SIZE,
@@ -2760,7 +2696,7 @@ static int __exit tegra_udc_remove(struct platform_device *pdev)
release_mem_region(res->start, res->end - res->start + 1);
device_unregister(&udc->gadget.dev);
- /* free udc --wait for the release() finished */
+ /* Free udc -- wait for the release() finished */
wait_for_completion(&done);
return 0;
@@ -2769,30 +2705,27 @@ static int __exit tegra_udc_remove(struct platform_device *pdev)
static int tegra_udc_suspend(struct platform_device *pdev, pm_message_t state)
{
struct tegra_udc *udc = platform_get_drvdata(pdev);
+ unsigned long flags;
DBG("%s(%d) BEGIN\n", __func__, __LINE__);
- /* if it controller is in otg mode, return */
+ /* If the controller is in otg mode, return */
if (udc->transceiver)
return 0;
if (udc->vbus_active) {
- spin_lock(&udc->lock);
+ spin_lock_irqsave(&udc->lock, flags);
/* Reset all internal Queues and inform client driver */
reset_queues(udc);
udc->vbus_active = 0;
udc->usb_state = USB_STATE_DEFAULT;
- spin_unlock(&udc->lock);
+ spin_unlock_irqrestore(&udc->lock, flags);
}
- /* stop the controller and turn off the clocks */
+ /* Stop the controller and turn off the clocks */
dr_controller_stop(udc);
if (udc->transceiver)
udc->transceiver->state = OTG_STATE_UNDEFINED;
-#ifdef IS_NEW_PHY_DRIVER
tegra_usb_phy_power_off(udc->phy);
-#else
- fsl_udc_clk_suspend(true);
-#endif
DBG("%s(%d) END\n", __func__, __LINE__);
return 0;
@@ -2803,36 +2736,18 @@ static int tegra_udc_resume(struct platform_device *pdev)
struct tegra_udc *udc = platform_get_drvdata(pdev);
DBG("%s(%d) BEGIN\n", __func__, __LINE__);
-#ifndef IS_NEW_PHY_DRIVER
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- /* Work around to get UTMIP_OTGPD, UTMIP_BIASPD values correctly */
- fsl_udc_clk_resume(true);
- fsl_udc_clk_suspend(true);
-#endif
-#endif
-
if (udc->transceiver)
return 0;
-#ifdef IS_NEW_PHY_DRIVER
tegra_usb_phy_power_on(udc->phy);
-#else
- fsl_udc_clk_resume(true);
- fsl_udc_clk_resume(true);
-#endif
tegra_udc_restart(udc);
/* Power down the phy if cable is not connected */
if (!vbus_enabled(udc)) {
udc->vbus_active = 0;
-#ifdef IS_NEW_PHY_DRIVER
tegra_usb_phy_power_off(udc->phy);
-#else
- fsl_udc_clk_suspend(true);
-#endif
}
-
DBG("%s(%d) END\n", __func__, __LINE__);
return 0;
}
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 25ed607aab9a..bf171c180987 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -145,7 +145,7 @@ static __maybe_unused void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
spin_lock_irqsave(&ehci->lock, flags);
/* clear phy low-power mode before changing wakeup flags */
- if (ehci->has_hostpc) {
+ if (ehci->has_hostpc && !ehci->broken_hostpc_phcd) {
port = HCS_N_PORTS(ehci->hcs_params);
while (port--) {
u32 __iomem *hostpc_reg;
@@ -181,7 +181,7 @@ static __maybe_unused void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
}
/* enter phy low-power mode again */
- if (ehci->has_hostpc) {
+ if (ehci->has_hostpc && !ehci->broken_hostpc_phcd) {
port = HCS_N_PORTS(ehci->hcs_params);
while (port--) {
u32 __iomem *hostpc_reg;
@@ -285,7 +285,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
}
}
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- if (changed && ehci->has_hostpc) {
+ if (changed && ehci->has_hostpc && !ehci->broken_hostpc_phcd) {
spin_unlock_irq(&ehci->lock);
msleep(5); /* 5 ms for HCD to enter low-power mode */
spin_lock_irq(&ehci->lock);
@@ -389,7 +389,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
spin_lock_irq(&ehci->lock);
/* clear phy low-power mode before resume */
- if (ehci->bus_suspended && ehci->has_hostpc) {
+ if (ehci->bus_suspended && ehci->has_hostpc && !ehci->broken_hostpc_phcd) {
i = HCS_N_PORTS(ehci->hcs_params);
while (i--) {
if (test_bit(i, &ehci->bus_suspended)) {
@@ -731,7 +731,7 @@ static int ehci_hub_control (
goto error;
/* clear phy low-power mode before resume */
- if (hostpc_reg) {
+ if (hostpc_reg && !ehci->broken_hostpc_phcd) {
temp1 = ehci_readl(ehci, hostpc_reg);
ehci_writel(ehci, temp1 & ~HOSTPC_PHCD,
hostpc_reg);
@@ -979,7 +979,7 @@ static int ehci_hub_control (
temp &= ~PORT_WKCONN_E;
temp |= PORT_WKDISC_E | PORT_WKOC_E;
ehci_writel(ehci, temp | PORT_SUSPEND, status_reg);
- if (hostpc_reg) {
+ if (hostpc_reg && !ehci->broken_hostpc_phcd) {
spin_unlock_irqrestore(&ehci->lock, flags);
msleep(5);/* 5ms for HCD enter low pwr mode */
spin_lock_irqsave(&ehci->lock, flags);
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index 4e7277b2b889..c5fa8160bffe 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -2,7 +2,7 @@
* EHCI-compliant USB host controller driver for NVIDIA Tegra SoCs
*
* Copyright (C) 2010 Google, Inc.
- * Copyright (C) 2009 - 2012 NVIDIA Corporation
+ * 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
@@ -16,7 +16,6 @@
*
*/
-#include <linux/clk.h>
#include <linux/platform_device.h>
#include <linux/platform_data/tegra_usb.h>
#include <linux/irq.h>
@@ -24,191 +23,157 @@
#include <mach/usb_phy.h>
#include <mach/iomap.h>
-#define TEGRA_USB_PORTSC_PHCD (1 << 23)
-
-#define TEGRA_USB_SUSP_CTRL_OFFSET 0x400
-#define TEGRA_USB_SUSP_CLR (1 << 5)
-#define TEGRA_USB_PHY_CLK_VALID (1 << 7)
-#define TEGRA_USB_SRT (1 << 25)
-#define TEGRA_USB_PHY_CLK_VALID_INT_ENB (1 << 9)
-#define TEGRA_USB_PHY_CLK_VALID_INT_STS (1 << 8)
-
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
-#define TEGRA_USB_PORTSC1_OFFSET 0x184
+#if 0
+#define EHCI_DBG(stuff...) pr_info("ehci-tegra: " stuff)
#else
-#define TEGRA_USB_PORTSC1_OFFSET 0x174
+#define EHCI_DBG(stuff...) do {} while (0)
#endif
-#define TEGRA_USB_PORTSC1_WKCN (1 << 20)
-#define TEGRA_LVL2_CLK_GATE_OVRB 0xfc
-#define TEGRA_USB2_CLK_OVR_ON (1 << 10)
+static const char driver_name[] = "tegra-ehci";
#define TEGRA_USB_DMA_ALIGN 32
-#define STS_SRI (1<<7) /* SOF Recieved */
-
-#define HOSTPC_REG_OFFSET 0x1b4
-
-#define HOSTPC1_DEVLC_STS (1 << 28)
-#define HOSTPC1_DEVLC_PTS(x) (((x) & 0x7) << 29)
-
-#define USB1_PREFETCH_ID 6
-#define USB2_PREFETCH_ID 18
-#define USB3_PREFETCH_ID 17
-
struct tegra_ehci_hcd {
struct ehci_hcd *ehci;
struct tegra_usb_phy *phy;
- struct clk *clk;
- struct clk *emc_clk;
- struct clk *sclk_clk;
+#ifdef CONFIG_USB_OTG_UTILS
struct otg_transceiver *transceiver;
- int host_resumed;
- int bus_suspended;
- int port_resuming;
- int power_down_on_bus_suspend;
- int default_enable;
- enum tegra_usb_phy_port_speed port_speed;
- struct work_struct clk_timer_work;
- struct timer_list clk_timer;
- bool clock_enabled;
- bool timer_event;
- struct mutex tegra_ehci_hcd_mutex;
+#endif
+ struct mutex sync_lock;
+ bool port_resuming;
unsigned int irq;
bool bus_suspended_fail;
};
-static void tegra_ehci_power_up(struct usb_hcd *hcd, bool is_dpd)
+struct dma_align_buffer {
+ void *kmalloc_ptr;
+ void *old_xfer_buffer;
+ u8 data[0];
+};
+
+static void free_align_buffer(struct urb *urb)
{
- struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
+ struct dma_align_buffer *temp = container_of(urb->transfer_buffer,
+ struct dma_align_buffer, data);
- if (!tegra->default_enable)
- clk_enable(tegra->clk);
- tegra_usb_phy_power_on(tegra->phy, is_dpd);
- tegra->host_resumed = 1;
+ if (!(urb->transfer_flags & URB_ALIGNED_TEMP_BUFFER))
+ return;
+
+ /* In transaction, DMA from Device */
+ if (usb_urb_dir_in(urb))
+ memcpy(temp->old_xfer_buffer, temp->data,
+ urb->transfer_buffer_length);
+
+ urb->transfer_buffer = temp->old_xfer_buffer;
+ urb->transfer_flags &= ~URB_ALIGNED_TEMP_BUFFER;
+ kfree(temp->kmalloc_ptr);
}
-static void tegra_ehci_power_down(struct usb_hcd *hcd, bool is_dpd)
+static int alloc_align_buffer(struct urb *urb, gfp_t mem_flags)
{
- struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
+ struct dma_align_buffer *temp, *kmalloc_ptr;
+ size_t kmalloc_size;
+
+ if (urb->num_sgs || urb->sg ||
+ urb->transfer_buffer_length == 0 ||
+ !((uintptr_t)urb->transfer_buffer & (TEGRA_USB_DMA_ALIGN - 1)))
+ return 0;
- tegra->host_resumed = 0;
- tegra_usb_phy_power_off(tegra->phy, is_dpd);
- if (!tegra->default_enable)
- clk_disable(tegra->clk);
+ /* Allocate a buffer with enough padding for alignment */
+ kmalloc_size = urb->transfer_buffer_length +
+ sizeof(struct dma_align_buffer) + TEGRA_USB_DMA_ALIGN - 1;
+ kmalloc_ptr = kmalloc(kmalloc_size, mem_flags);
+
+ if (!kmalloc_ptr)
+ return -ENOMEM;
+
+ /* Position our struct dma_align_buffer such that data is aligned */
+ temp = PTR_ALIGN(kmalloc_ptr + 1, TEGRA_USB_DMA_ALIGN) - 1;
+ temp->kmalloc_ptr = kmalloc_ptr;
+ temp->old_xfer_buffer = urb->transfer_buffer;
+ /* OUT transaction, DMA to Device */
+ if (!usb_urb_dir_in(urb))
+ memcpy(temp->data, urb->transfer_buffer,
+ urb->transfer_buffer_length);
+
+ urb->transfer_buffer = temp->data;
+ urb->transfer_flags |= URB_ALIGNED_TEMP_BUFFER;
+
+ return 0;
}
-static int tegra_ehci_internal_port_reset(
- struct ehci_hcd *ehci,
- u32 __iomem *portsc_reg
-)
+static int tegra_ehci_map_urb_for_dma(struct usb_hcd *hcd,
+ struct urb *urb, gfp_t mem_flags)
{
- u32 temp;
- unsigned long flags;
- int retval = 0;
- int i, tries;
- u32 saved_usbintr;
-
- spin_lock_irqsave(&ehci->lock, flags);
- saved_usbintr = ehci_readl(ehci, &ehci->regs->intr_enable);
- /* disable USB interrupt */
- ehci_writel(ehci, 0, &ehci->regs->intr_enable);
- spin_unlock_irqrestore(&ehci->lock, flags);
-
- /*
- * Here we have to do Port Reset at most twice for
- * Port Enable bit to be set.
- */
- for (i = 0; i < 2; i++) {
- temp = ehci_readl(ehci, portsc_reg);
- temp |= PORT_RESET;
- ehci_writel(ehci, temp, portsc_reg);
- mdelay(10);
- temp &= ~PORT_RESET;
- ehci_writel(ehci, temp, portsc_reg);
- mdelay(1);
- tries = 100;
- do {
- mdelay(1);
- /*
- * Up to this point, Port Enable bit is
- * expected to be set after 2 ms waiting.
- * USB1 usually takes extra 45 ms, for safety,
- * we take 100 ms as timeout.
- */
- temp = ehci_readl(ehci, portsc_reg);
- } while (!(temp & PORT_PE) && tries--);
- if (temp & PORT_PE)
- break;
+ int ret;
+
+ ret = alloc_align_buffer(urb, mem_flags);
+ if (ret)
+ return ret;
+
+ ret = usb_hcd_map_urb_for_dma(hcd, urb, mem_flags);
+
+ /* Control packets over dma */
+ if (urb->setup_dma)
+ dma_sync_single_for_device(hcd->self.controller,
+ urb->setup_dma, sizeof(struct usb_ctrlrequest),
+ DMA_TO_DEVICE);
+
+ /* urb buffers over dma */
+ if (urb->transfer_dma) {
+ enum dma_data_direction dir;
+ dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+
+ dma_sync_single_for_device(hcd->self.controller,
+ urb->transfer_dma, urb->transfer_buffer_length, dir);
}
- if (i == 2)
- retval = -ETIMEDOUT;
-
- /*
- * Clear Connect Status Change bit if it's set.
- * We can't clear PORT_PEC. It will also cause PORT_PE to be cleared.
- */
- if (temp & PORT_CSC)
- ehci_writel(ehci, PORT_CSC, portsc_reg);
-
- /*
- * Write to clear any interrupt status bits that might be set
- * during port reset.
- */
- temp = ehci_readl(ehci, &ehci->regs->status);
- ehci_writel(ehci, temp, &ehci->regs->status);
-
- /* restore original interrupt enable bits */
- ehci_writel(ehci, saved_usbintr, &ehci->regs->intr_enable);
- return retval;
+
+ if (ret)
+ free_align_buffer(urb);
+
+ return ret;
}
-static irqreturn_t tegra_ehci_irq (struct usb_hcd *hcd)
+static void tegra_ehci_unmap_urb_for_dma(struct usb_hcd *hcd,
+ struct urb *urb)
+{
+ usb_hcd_unmap_urb_for_dma(hcd, urb);
+ free_align_buffer(urb);
+
+ if (urb->transfer_dma) {
+ enum dma_data_direction dir;
+ dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+ if (dir == DMA_FROM_DEVICE)
+ dma_sync_single_for_cpu(hcd->self.controller,
+ urb->transfer_dma, urb->transfer_buffer_length,
+ DMA_FROM_DEVICE);
+ }
+}
+
+static irqreturn_t tegra_ehci_irq(struct usb_hcd *hcd)
{
- struct ehci_hcd *ehci = hcd_to_ehci (hcd);
- struct ehci_regs __iomem *hw = ehci->regs;
struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
- u32 val;
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
irqreturn_t irq_status;
bool pmc_remote_wakeup = false;
- /* Fence read for coherency of AHB master intiated writes */
- if (tegra->phy->instance == 0)
- readb(IO_ADDRESS(IO_PPCS_PHYS + USB1_PREFETCH_ID));
- else if (tegra->phy->instance == 1)
- readb(IO_ADDRESS(IO_PPCS_PHYS + USB2_PREFETCH_ID));
- else if (tegra->phy->instance == 2)
- readb(IO_ADDRESS(IO_PPCS_PHYS + USB3_PREFETCH_ID));
-
- if ((tegra->phy->usb_phy_type == TEGRA_USB_PHY_TYPE_UTMIP) &&
- (tegra->ehci->has_hostpc)) {
- /* check if there is any remote wake event */
- if (tegra_usb_phy_is_remotewake_detected(tegra->phy)) {
- pmc_remote_wakeup = true;
- spin_lock (&ehci->lock);
- usb_hcd_resume_root_hub(hcd);
- spin_unlock (&ehci->lock);
- }
- }
- if (tegra->phy->hotplug) {
- spin_lock(&ehci->lock);
- val = readl(hcd->regs + TEGRA_USB_SUSP_CTRL_OFFSET);
- if ((val & TEGRA_USB_PHY_CLK_VALID_INT_STS)) {
- val &= ~TEGRA_USB_PHY_CLK_VALID_INT_ENB |
- TEGRA_USB_PHY_CLK_VALID_INT_STS;
- writel(val , (hcd->regs + TEGRA_USB_SUSP_CTRL_OFFSET));
-
- val = readl(&hw->status);
- if (!(val & STS_PCD)) {
- spin_unlock(&ehci->lock);
- return 0;
- }
- val = readl(hcd->regs + TEGRA_USB_PORTSC1_OFFSET);
- val &= ~(TEGRA_USB_PORTSC1_WKCN | PORT_RWC_BITS);
- writel(val , (hcd->regs + TEGRA_USB_PORTSC1_OFFSET));
- }
+ spin_lock(&ehci->lock);
+ irq_status = tegra_usb_phy_irq(tegra->phy);
+ if (irq_status == IRQ_NONE) {
spin_unlock(&ehci->lock);
+ return irq_status;
+ }
+ if (tegra_usb_phy_remote_wakeup(tegra->phy)) {
+ ehci_info(ehci, "remote wakeup detected\n");
+ pmc_remote_wakeup = true;
+ usb_hcd_resume_root_hub(hcd);
}
+ spin_unlock(&ehci->lock);
+
+ EHCI_DBG("%s() cmd = 0x%x, int_sts = 0x%x, portsc = 0x%x\n", __func__,
+ ehci_readl(ehci, &ehci->regs->command),
+ ehci_readl(ehci, &ehci->regs->status),
+ ehci_readl(ehci, &ehci->regs->port_status[0]));
irq_status = ehci_irq(hcd);
@@ -218,61 +183,37 @@ static irqreturn_t tegra_ehci_irq (struct usb_hcd *hcd)
if (ehci->controller_remote_wakeup) {
ehci->controller_remote_wakeup = false;
- /* disable interrupts */
- ehci_writel(ehci, 0, &ehci->regs->intr_enable);
- tegra_usb_phy_preresume(tegra->phy, true);
+ tegra_usb_phy_pre_resume(tegra->phy, true);
tegra->port_resuming = 1;
}
return irq_status;
}
+
static int tegra_ehci_hub_control(
struct usb_hcd *hcd,
- u16 typeReq,
- u16 wValue,
- u16 wIndex,
- char *buf,
- u16 wLength
+ u16 typeReq,
+ u16 wValue,
+ u16 wIndex,
+ char *buf,
+ u16 wLength
)
{
- struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- int ports = HCS_N_PORTS(ehci->hcs_params);
- u32 temp, status, cmd_run;
- u32 __iomem *status_reg;
- u32 usbsts_reg;
-
+ struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
unsigned long flags;
- int retval = 0;
- unsigned selector;
- struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
- bool hsic = false;
+ int retval = 0;
+ u32 __iomem *status_reg;
- mutex_lock(&tegra->tegra_ehci_hcd_mutex);
- if (!tegra->host_resumed) {
+ if (!tegra_usb_phy_hw_accessible(tegra->phy)) {
if (buf)
- memset (buf, 0, wLength);
- mutex_unlock(&tegra->tegra_ehci_hcd_mutex);
+ memset(buf, 0, wLength);
return retval;
}
- hsic = (tegra->phy->usb_phy_type == TEGRA_USB_PHY_TYPE_HSIC);
-
- status_reg = &ehci->regs->port_status[(wIndex & 0xff) - 1];
-
- spin_lock_irqsave(&ehci->lock, flags);
-
- /*
- * In ehci_hub_control() for USB_PORT_FEAT_ENABLE clears the other bits
- * that are write on clear, by writing back the register read value, so
- * USB_PORT_FEAT_ENABLE is handled by masking the set on clear bits
- */
- if (typeReq == ClearPortFeature && wValue == USB_PORT_FEAT_ENABLE) {
- temp = ehci_readl(ehci, status_reg) & ~PORT_RWC_BITS;
- ehci_writel(ehci, temp & ~PORT_PE, status_reg);
- goto done;
- } else if (typeReq == GetPortStatus) {
- temp = ehci_readl(ehci, status_reg);
- /* check port is in resume state */
+ /* Do tegra phy specific actions based on the type request */
+ switch (typeReq) {
+ case GetPortStatus:
if (tegra->port_resuming) {
int delay = ehci->reset_done[wIndex-1] - jiffies;
/* Sometimes it seems we get called too soon... In that case, wait.*/
@@ -280,501 +221,68 @@ static int tegra_ehci_hub_control(
ehci_dbg(ehci, "GetPortStatus called too soon, waiting %dms...\n", delay);
mdelay(jiffies_to_msecs(delay));
}
+ status_reg = &ehci->regs->port_status[(wIndex & 0xff) - 1];
/* Ensure the port PORT_SUSPEND and PORT_RESUME has cleared */
if (handshake(ehci, status_reg, (PORT_SUSPEND | PORT_RESUME), 0, 25000)) {
pr_err("%s: timeout waiting for SUSPEND to clear\n", __func__);
}
+ tegra_usb_phy_post_resume(tegra->phy);
tegra->port_resuming = 0;
- tegra_usb_phy_postresume(tegra->phy, false);
- if (tegra->phy->usb_phy_type == TEGRA_USB_PHY_TYPE_UTMIP) {
+ /* If run bit is not set by now enable it */
+ if (ehci->command & CMD_RUN) {
ehci->command |= CMD_RUN;
- cmd_run = ehci_readl(ehci, &ehci->regs->command);
- cmd_run |= CMD_RUN;
- /*
- * ehci run bit is disabled to avoid SOF.
- * 2LS WAR is executed by now enable the run bit.
- */
- ehci_writel(ehci, cmd_run, &ehci->regs->command);
- /* Now we can safely re-enable irqs */
- ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
+ ehci_writel(ehci, ehci->command, &ehci->regs->command);
}
+ /* Now we can safely re-enable irqs */
+ ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
}
-
- } else if (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_SUSPEND) {
- temp = ehci_readl(ehci, status_reg);
- if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) != 0) {
- retval = -EPIPE;
- goto done;
- }
-
- temp &= ~PORT_WKCONN_E;
- temp |= PORT_WKDISC_E | PORT_WKOC_E;
- ehci_writel(ehci, temp | PORT_SUSPEND, status_reg);
-
- /* Need a 4ms delay before the controller goes to suspend */
- mdelay(4);
-
- /*
- * If a transaction is in progress, there may be a delay in
- * suspending the port. Poll until the port is suspended.
- */
- if (handshake(ehci, status_reg, PORT_SUSPEND,
- PORT_SUSPEND, 5000))
- pr_err("%s: timeout waiting for SUSPEND\n", __func__);
-
- set_bit((wIndex & 0xff) - 1, &ehci->suspended_ports);
- /*
- * If RUN bit is disabled interrupt is not generated after suspend.
- * This change on T20 will allow ASE interrupt generated after suspend
- * which will unlink the qheads.
- */
-#ifndef CONFIG_ARCH_TEGRA_2x_SOC
- if (tegra->phy->usb_phy_type == TEGRA_USB_PHY_TYPE_UTMIP) {
- /* Disable RUN bit. */
- ehci->command &= ~CMD_RUN;
- cmd_run = ehci_readl(ehci, &ehci->regs->command);
- cmd_run &= ~CMD_RUN;
- ehci_writel(ehci, cmd_run, &ehci->regs->command);
- if (handshake (ehci, &ehci->regs->status,
- STS_HALT, STS_HALT, 16 * 125))
- pr_err("%s() timeout waiting for STS_HALT\n", __func__);
+ break;
+ case ClearPortFeature:
+ if (wValue == USB_PORT_FEAT_SUSPEND) {
+ tegra_usb_phy_pre_resume(tegra->phy, false);
+ tegra->port_resuming = 1;
}
-#endif
- tegra_usb_phy_postsuspend(tegra->phy, false);
-
- goto done;
- }
-
- /* For USB1 port we need to issue Port Reset twice internally */
- if (tegra->phy->instance == 0 &&
- (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_RESET)) {
- spin_unlock_irqrestore(&ehci->lock, flags);
- mutex_unlock(&tegra->tegra_ehci_hcd_mutex);
- return tegra_ehci_internal_port_reset(ehci, status_reg);
+ break;
}
- /*
- * Tegra host controller will time the resume operation to clear the bit
- * when the port control state switches to HS or FS Idle. This behavior
- * is different from EHCI where the host controller driver is required
- * to set this bit to a zero after the resume duration is timed in the
- * driver.
- */
- else if (typeReq == ClearPortFeature &&
- wValue == USB_PORT_FEAT_SUSPEND) {
- temp = ehci_readl(ehci, status_reg);
- if ((temp & PORT_RESET) || !(temp & PORT_PE)) {
- retval = -EPIPE;
- goto done;
- }
-
- if (!(temp & PORT_SUSPEND))
- goto done;
-
- tegra->port_resuming = 1;
-
- if (tegra->phy->usb_phy_type == TEGRA_USB_PHY_TYPE_UTMIP) {
- /* disable interrupts */
- ehci_writel(ehci, 0, &ehci->regs->intr_enable);
- /* Disable RUN bit. */
- ehci->command &= ~CMD_RUN;
- cmd_run = ehci_readl(ehci, &ehci->regs->command);
- cmd_run &= ~CMD_RUN;
- ehci_writel(ehci, cmd_run, &ehci->regs->command);
- if (handshake (ehci, &ehci->regs->status,
- STS_HALT, STS_HALT, 16 * 125))
- pr_err("%s() timeout waiting for STS_HALT\n", __func__);
- }
-
- /* Disable disconnect detection during port resume */
- tegra_usb_phy_preresume(tegra->phy, false);
-#ifndef CONFIG_ARCH_TEGRA_2x_SOC
- if (tegra->phy->usb_phy_type != TEGRA_USB_PHY_TYPE_UTMIP) {
-#endif
- ehci_dbg(ehci, "%s:USBSTS = 0x%x", __func__,
- ehci_readl(ehci, &ehci->regs->status));
- usbsts_reg = ehci_readl(ehci, &ehci->regs->status);
- ehci_writel(ehci, usbsts_reg, &ehci->regs->status);
- usbsts_reg = ehci_readl(ehci, &ehci->regs->status);
- udelay(20);
-
- if (handshake(ehci, &ehci->regs->status, STS_SRI, STS_SRI, 2000))
- pr_err("%s: timeout set for STS_SRI\n", __func__);
-
- usbsts_reg = ehci_readl(ehci, &ehci->regs->status);
- ehci_writel(ehci, usbsts_reg, &ehci->regs->status);
-
- if (handshake(ehci, &ehci->regs->status, STS_SRI, 0, 2000))
- pr_err("%s: timeout clear STS_SRI\n", __func__);
-
- if (handshake(ehci, &ehci->regs->status, STS_SRI, STS_SRI, 2000))
- pr_err("%s: timeout set STS_SRI\n", __func__);
-
- udelay(20);
-#ifndef CONFIG_ARCH_TEGRA_2x_SOC
- }
-#endif
- temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
- /* start resume signaling */
- ehci_writel(ehci, temp | PORT_RESUME, status_reg);
-
- ehci->reset_done[wIndex-1] = jiffies + msecs_to_jiffies(25);
- /* whoever resumes must GetPortStatus to complete it!! */
- goto done;
- }
+ /* handle ehci hub control request */
+ retval = ehci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength);
- /* Handle port reset here */
- if ((hsic) && (typeReq == SetPortFeature) &&
- ((wValue == USB_PORT_FEAT_RESET) || (wValue == USB_PORT_FEAT_POWER))) {
- selector = wIndex >> 8;
- wIndex &= 0xff;
- if (!wIndex || wIndex > ports) {
- retval = -EPIPE;
- goto done;
- }
- wIndex--;
- status = 0;
- temp = ehci_readl(ehci, status_reg);
- if (temp & PORT_OWNER)
- goto done;
- temp &= ~PORT_RWC_BITS;
-
- switch (wValue) {
- case USB_PORT_FEAT_RESET:
- {
- if (temp & PORT_RESUME) {
- retval = -EPIPE;
- goto done;
- }
- /* line status bits may report this as low speed,
- * which can be fine if this root hub has a
- * transaction translator built in.
- */
- if ((temp & (PORT_PE|PORT_CONNECT)) == PORT_CONNECT
- && !ehci_is_TDI(ehci) && PORT_USB11 (temp)) {
- ehci_dbg (ehci, "port %d low speed --> companion\n", wIndex + 1);
- temp |= PORT_OWNER;
- ehci_writel(ehci, temp, status_reg);
- } else {
- ehci_vdbg(ehci, "port %d reset\n", wIndex + 1);
- temp &= ~PORT_PE;
- /*
- * caller must wait, then call GetPortStatus
- * usb 2.0 spec says 50 ms resets on root
- */
- ehci->reset_done[wIndex] = jiffies + msecs_to_jiffies(50);
- ehci_writel(ehci, temp, status_reg);
- if (hsic && (wIndex == 0))
+ /* do tegra phy specific actions based on the type request */
+ if (!retval) {
+ switch (typeReq) {
+ case SetPortFeature:
+ if (wValue == USB_PORT_FEAT_SUSPEND) {
+ /* Need a 4ms delay for controller to suspend */
+ mdelay(4);
+ tegra_usb_phy_post_suspend(tegra->phy);
+ } else if (wValue == USB_PORT_FEAT_RESET) {
+ if (ehci->reset_done[0] && wIndex == 0)
tegra_usb_phy_bus_reset(tegra->phy);
+ } else if (wValue == USB_PORT_FEAT_POWER) {
+ if (wIndex == 1)
+ tegra_usb_phy_port_power(tegra->phy);
}
-
break;
}
- case USB_PORT_FEAT_POWER:
- {
- if (HCS_PPC(ehci->hcs_params))
- ehci_writel(ehci, temp | PORT_POWER, status_reg);
- if (hsic && (wIndex == 0))
- tegra_usb_phy_bus_connect(tegra->phy);
- break;
- }
- }
- goto done;
}
- spin_unlock_irqrestore(&ehci->lock, flags);
-
- /* Handle the hub control events here */
- retval = ehci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength);
- mutex_unlock(&tegra->tegra_ehci_hcd_mutex);
- return retval;
-done:
- spin_unlock_irqrestore(&ehci->lock, flags);
- mutex_unlock(&tegra->tegra_ehci_hcd_mutex);
return retval;
}
-#ifdef CONFIG_PM
-static void tegra_ehci_restart(struct usb_hcd *hcd, bool is_dpd)
+static void tegra_ehci_shutdown(struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
- unsigned int temp;
-
- ehci->controller_resets_phy = 0;
- tegra_ehci_pre_reset(tegra->phy, false);
- ehci_reset(ehci);
- tegra_ehci_post_reset(tegra->phy, false);
-
- if (tegra->phy->usb_phy_type == TEGRA_USB_PHY_TYPE_NULL_ULPI)
- ehci->controller_resets_phy = 1;
-
- /* setup the frame list and Async q heads */
- ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list);
- ehci_writel(ehci, (u32)ehci->async->qh_dma, &ehci->regs->async_next);
- /* setup the command register and set the controller in RUN mode */
- ehci->command &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET);
-#ifndef CONFIG_ARCH_TEGRA_2x_SOC
- /* dont start RS here for HSIC, it will be set by bus_reset */
- if (tegra->phy->usb_phy_type != TEGRA_USB_PHY_TYPE_HSIC)
-#endif
- ehci->command |= CMD_RUN;
- ehci_writel(ehci, ehci->command, &ehci->regs->command);
-
- /* Enable the root Port Power */
- if (HCS_PPC(ehci->hcs_params)) {
- temp = ehci_readl(ehci, &ehci->regs->port_status[0]);
- ehci_writel(ehci, temp | PORT_POWER, &ehci->regs->port_status[0]);
- }
-
- down_write(&ehci_cf_port_reset_rwsem);
- if(is_dpd)
- hcd->state = HC_STATE_SUSPENDED;
- else
- hcd->state = HC_STATE_RUNNING;
- ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
- /* flush posted writes */
- ehci_readl(ehci, &ehci->regs->command);
- up_write(&ehci_cf_port_reset_rwsem);
-
- /* Turn On Interrupts */
- ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
-}
-
-static int tegra_usb_suspend(struct usb_hcd *hcd, bool is_dpd)
-{
- struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
- struct ehci_regs __iomem *hw = tegra->ehci->regs;
- unsigned long flags;
- int hsic = 0;
-
- hsic = (tegra->phy->usb_phy_type == TEGRA_USB_PHY_TYPE_HSIC);
-
- spin_lock_irqsave(&tegra->ehci->lock, flags);
-
- if (tegra->ehci->has_hostpc)
- tegra->port_speed = (readl(hcd->regs + HOSTPC_REG_OFFSET) >> 25) & 0x3;
- else
- tegra->port_speed = (readl(&hw->port_status[0]) >> 26) & 0x3;
- ehci_halt(tegra->ehci);
-#ifndef CONFIG_ARCH_TEGRA_2x_SOC
- if (tegra->phy->usb_phy_type == TEGRA_USB_PHY_TYPE_UTMIP) {
- /*
- * Ehci run bit is disabled by now read this into command variable
- * so that bus resume will not enable run bit immedialty.
- * this is required for 2LS WAR on UTMIP interface.
- */
- tegra->ehci->command = ehci_readl(tegra->ehci,
- &tegra->ehci->regs->command);
- }
-#endif
-
- spin_unlock_irqrestore(&tegra->ehci->lock, flags);
-
- tegra_ehci_power_down(hcd, is_dpd);
- return 0;
-}
-
-static int tegra_usb_resume(struct usb_hcd *hcd, bool is_dpd)
-{
- struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
- struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- struct ehci_regs __iomem *hw = ehci->regs;
- unsigned long val;
- bool hsic;
- bool null_ulpi;
- bool utmip_remote_wakeup = false;
-
- null_ulpi = (tegra->phy->usb_phy_type == TEGRA_USB_PHY_TYPE_NULL_ULPI);
- hsic = (tegra->phy->usb_phy_type == TEGRA_USB_PHY_TYPE_HSIC);
-
- tegra_ehci_power_up(hcd, is_dpd);
- set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-
- if ((tegra->port_speed > TEGRA_USB_PHY_PORT_SPEED_HIGH) || (hsic) ||
- (null_ulpi))
- goto restart;
-
- /* Force the phy to keep data lines in suspend state */
- tegra_ehci_phy_restore_start(tegra->phy, tegra->port_speed);
-
- if (tegra->phy->usb_phy_type == TEGRA_USB_PHY_TYPE_UTMIP) {
- ehci_reset(ehci);
- }
-
- /* Enable host mode */
- tdi_reset(ehci);
-
- if ((tegra->phy->usb_phy_type == TEGRA_USB_PHY_TYPE_UTMIP) &&
- (tegra->ehci->has_hostpc)) {
- val = readl(hcd->regs + HOSTPC_REG_OFFSET);
- val &= ~HOSTPC1_DEVLC_PTS(~0);
- val |= HOSTPC1_DEVLC_STS;
- writel(val, hcd->regs + HOSTPC_REG_OFFSET);
- }
-
- /* Enable Port Power */
- val = readl(&hw->port_status[0]);
- val |= PORT_POWER;
- writel(val, &hw->port_status[0]);
- udelay(10);
-
- if ((tegra->phy->usb_phy_type == TEGRA_USB_PHY_TYPE_UTMIP) &&
- (tegra->ehci->has_hostpc) && (tegra->phy->remote_wakeup)) {
- utmip_remote_wakeup = true;
- }
-
- /* Check if the phy resume from LP0. When the phy resume from LP0
- * USB register will be reset. */
- if (!readl(&hw->async_next)) {
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- /* Start the controller */
- val = readl(&hw->command);
- writel((val | CMD_RUN), &hw->command);
-#endif
- /* Program the field PTC based on the saved speed mode */
- val = readl(&hw->port_status[0]);
- val &= ~PORT_TEST(~0);
- if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_HIGH)
- val |= PORT_TEST_FORCE;
- else if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_FULL)
- val |= PORT_TEST(6);
- else if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW)
- val |= PORT_TEST(7);
- writel(val, &hw->port_status[0]);
- udelay(10);
-
- /* Disable test mode by setting PTC field to NORMAL_OP */
- val = readl(&hw->port_status[0]);
- val &= ~PORT_TEST(~0);
- writel(val, &hw->port_status[0]);
- udelay(10);
- }
-
- /* Poll until CCS is enabled */
- if (handshake(ehci, &hw->port_status[0], PORT_CONNECT,
- PORT_CONNECT, 2000)) {
- pr_err("%s: timeout waiting for PORT_CONNECT\n", __func__);
- goto restart;
- }
-
- /* Poll until PE is enabled */
- if (handshake(ehci, &hw->port_status[0], PORT_PE,
- PORT_PE, 2000)) {
- pr_err("%s: timeout waiting for USB_PORTSC1_PE\n", __func__);
- goto restart;
- }
-
- /* Clear the PCI status, to avoid an interrupt taken upon resume */
- val = readl(&hw->status);
- val |= STS_PCD;
- writel(val, &hw->status);
-
- /* Put controller in suspend mode by writing 1 to SUSP bit of PORTSC */
- val = readl(&hw->port_status[0]);
- if ((val & PORT_POWER) && (val & PORT_PE)) {
- val |= PORT_SUSPEND;
- writel(val, &hw->port_status[0]);
-
- /* Need a 4ms delay before the controller goes to suspend */
- mdelay(4);
-
- /* Wait until port suspend completes */
- if (handshake(ehci, &hw->port_status[0], PORT_SUSPEND,
- PORT_SUSPEND, 1000)) {
- pr_err("%s: timeout waiting for PORT_SUSPEND\n",
- __func__);
- goto restart;
- }
- }
-
- tegra_ehci_phy_restore_end(tegra->phy);
- if (utmip_remote_wakeup) {
- ehci->command |= CMD_RUN;
- ehci_writel(ehci, ehci->command, &ehci->regs->command);
- }
- return 0;
-
-restart:
- if (null_ulpi) {
- bool LP0 = !readl(&hw->async_next);
-
- if (LP0) {
- static int cnt = 1;
-
- pr_info("LP0 restart %d\n", cnt++);
- tegra_ehci_phy_restore_start(tegra->phy,
- tegra->port_speed);
- }
-
- val = readl(&hw->port_status[0]);
- if (!((val & PORT_POWER) && (val & PORT_PE))) {
- tegra_ehci_restart(hcd, is_dpd);
- }
-
- if (LP0)
- tegra_ehci_phy_restore_end(tegra->phy);
-
- return 0;
- }
-
- if ((tegra->port_speed <= TEGRA_USB_PHY_PORT_SPEED_HIGH) && (!hsic))
- tegra_ehci_phy_restore_end(tegra->phy);
- if (hsic) {
- val = readl(&hw->port_status[0]);
- if (!((val & PORT_POWER) && (val & PORT_PE)))
- tegra_ehci_restart(hcd, false);
-
- tegra_usb_phy_bus_idle(tegra->phy);
- if (!tegra_usb_phy_is_device_connected(tegra->phy))
- pr_err("%s: no hsic device conenction\n", __func__);
- } else {
- tegra_ehci_restart(hcd, false);
- }
-
- return 0;
-}
-#endif
-
-/*
- * Disable PHY clock valid interrupts and wait for the interrupt handler to
- * finish.
- *
- * Requires a lock on tegra_ehci_hcd_mutex
- * Must not be called with a lock on ehci->lock
- */
-static void tegra_ehci_disable_phy_interrupt(struct usb_hcd *hcd) {
- struct tegra_ehci_hcd *tegra;
- u32 val;
- if (hcd->irq >= 0) {
- tegra = dev_get_drvdata(hcd->self.controller);
- if (tegra->phy->hotplug) {
- /* Disable PHY clock valid interrupts */
- val = readl(hcd->regs + TEGRA_USB_SUSP_CTRL_OFFSET);
- val &= ~TEGRA_USB_PHY_CLK_VALID_INT_ENB;
- writel(val , (hcd->regs + TEGRA_USB_SUSP_CTRL_OFFSET));
- }
- /* Wait for the interrupt handler to finish */
- synchronize_irq(hcd->irq);
- }
-}
-
-static void tegra_ehci_shutdown(struct usb_hcd *hcd)
-{
- struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
-
- mutex_lock(&tegra->tegra_ehci_hcd_mutex);
- tegra_ehci_disable_phy_interrupt(hcd);
- /* ehci_shutdown touches the USB controller registers, make sure
- * controller has clocks to it */
- if (!tegra->host_resumed)
- tegra_ehci_power_up(hcd, false);
-
- ehci_shutdown(hcd);
-
- /* we are ready to shut down, powerdown the phy */
- tegra_ehci_power_down(hcd, false);
- mutex_unlock(&tegra->tegra_ehci_hcd_mutex);
+ mutex_lock(&tegra->sync_lock);
+ del_timer_sync(&ehci->watchdog);
+ del_timer_sync(&ehci->iaa_watchdog);
+ if (tegra_usb_phy_hw_accessible(tegra->phy)) {
+ spin_lock_irq(&ehci->lock);
+ ehci_silence_controller(ehci);
+ spin_unlock_irq(&ehci->lock);
+ }
+ mutex_unlock(&tegra->sync_lock);
}
static int tegra_ehci_setup(struct usb_hcd *hcd)
@@ -786,24 +294,18 @@ static int tegra_ehci_setup(struct usb_hcd *hcd)
/* EHCI registers start at offset 0x100 */
ehci->caps = hcd->regs + 0x100;
ehci->regs = hcd->regs + 0x100 +
- HC_LENGTH(ehci, readl(&ehci->caps->hc_capbase));
+ HC_LENGTH(ehci, readl(&ehci->caps->hc_capbase));
dbg_hcs_params(ehci, "reset");
dbg_hcc_params(ehci, "reset");
/* cache this readonly data; minimize chip reads */
ehci->hcs_params = readl(&ehci->caps->hcs_params);
+ ehci->has_hostpc = tegra_usb_phy_has_hostpc(tegra->phy) ? 1 : 0;
+ ehci->broken_hostpc_phcd = true;
-#ifndef CONFIG_ARCH_TEGRA_2x_SOC
- ehci->has_hostpc = 1;
-#endif
hcd->has_tt = 1;
- if (tegra->phy->usb_phy_type != TEGRA_USB_PHY_TYPE_NULL_ULPI) {
- ehci_reset(ehci);
- tegra_ehci_post_reset(tegra->phy, false);
- }
-
retval = ehci_halt(ehci);
if (retval)
return retval;
@@ -815,267 +317,49 @@ static int tegra_ehci_setup(struct usb_hcd *hcd)
ehci->sbrn = 0x20;
ehci->controller_remote_wakeup = false;
-
- if (tegra->phy->usb_phy_type == TEGRA_USB_PHY_TYPE_NULL_ULPI) {
- tegra_ehci_pre_reset(tegra->phy, false);
- ehci_reset(ehci);
- tegra_ehci_post_reset(tegra->phy, false);
-
- /*
- * Resetting the controller has the side effect of resetting the PHY.
- * So, never reset the controller after the calling
- * tegra_ehci_reinit API.
- */
- ehci->controller_resets_phy = 1;
- }
+ ehci_reset(ehci);
+ tegra_usb_phy_reset(tegra->phy);
ehci_port_power(ehci, 1);
return retval;
}
+
#ifdef CONFIG_PM
static int tegra_ehci_bus_suspend(struct usb_hcd *hcd)
{
struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
- int error_status = 0;
-
- mutex_lock(&tegra->tegra_ehci_hcd_mutex);
+ int err = 0;
+ EHCI_DBG("%s() BEGIN\n", __func__);
+ mutex_lock(&tegra->sync_lock);
tegra->bus_suspended_fail = false;
- tegra_ehci_disable_phy_interrupt(hcd);
- /* ehci_shutdown touches the USB controller registers, make sure
- * controller has clocks to it */
- if (!tegra->host_resumed)
- tegra_ehci_power_up(hcd, false);
- error_status = ehci_bus_suspend(hcd);
- if (error_status)
+ err = ehci_bus_suspend(hcd);
+ if (err)
tegra->bus_suspended_fail = true;
- if (!error_status && tegra->power_down_on_bus_suspend) {
- tegra_usb_suspend(hcd, false);
- tegra->bus_suspended = 1;
- }
- mutex_unlock(&tegra->tegra_ehci_hcd_mutex);
+ else
+ tegra_usb_phy_suspend(tegra->phy);
+ mutex_unlock(&tegra->sync_lock);
+ EHCI_DBG("%s() END\n", __func__);
- return error_status;
+ return err;
}
static int tegra_ehci_bus_resume(struct usb_hcd *hcd)
{
struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
- int ehci_bus_resumed;
+ int err = 0;
+ EHCI_DBG("%s() BEGIN\n", __func__);
- mutex_lock(&tegra->tegra_ehci_hcd_mutex);
- if (tegra->bus_suspended && tegra->power_down_on_bus_suspend) {
- tegra_usb_resume(hcd, false);
- tegra->bus_suspended = 0;
- }
+ mutex_lock(&tegra->sync_lock);
+ tegra_usb_phy_resume(tegra->phy);
+ err = ehci_bus_resume(hcd);
+ mutex_unlock(&tegra->sync_lock);
+ EHCI_DBG("%s() END\n", __func__);
- ehci_bus_resumed = ehci_bus_resume(hcd);
- mutex_unlock(&tegra->tegra_ehci_hcd_mutex);
- return ehci_bus_resumed;
+ return err;
}
#endif
-struct dma_aligned_buffer {
- void *kmalloc_ptr;
- void *old_xfer_buffer;
- u8 data[0];
-};
-
-static void free_dma_aligned_buffer(struct urb *urb)
-{
- struct dma_aligned_buffer *temp = container_of(urb->transfer_buffer,
- struct dma_aligned_buffer, data);
-
- if (!(urb->transfer_flags & URB_ALIGNED_TEMP_BUFFER))
- return;
-
- if(usb_urb_dir_in(urb))
- memcpy(temp->old_xfer_buffer, temp->data,
- urb->transfer_buffer_length);
- urb->transfer_buffer = temp->old_xfer_buffer;
- kfree(temp->kmalloc_ptr);
- urb->transfer_flags &= ~URB_ALIGNED_TEMP_BUFFER;
-}
-
-static int alloc_dma_aligned_buffer(struct urb *urb, gfp_t mem_flags)
-{
- struct dma_aligned_buffer *temp, *kmalloc_ptr;
- size_t kmalloc_size;
-
- if (urb->num_sgs || urb->sg ||
- urb->transfer_buffer_length == 0 ||
- !((uintptr_t)urb->transfer_buffer & (TEGRA_USB_DMA_ALIGN - 1)))
- return 0;
-
- /* Allocate a buffer with enough padding for alignment */
- kmalloc_size = urb->transfer_buffer_length +
- sizeof(struct dma_aligned_buffer) + TEGRA_USB_DMA_ALIGN - 1;
-
- kmalloc_ptr = kmalloc(kmalloc_size, mem_flags);
- if (!kmalloc_ptr)
- return -ENOMEM;
-
- /* Position our struct dma_aligned_buffer such that data is aligned */
- temp = PTR_ALIGN(kmalloc_ptr + 1, TEGRA_USB_DMA_ALIGN) - 1;
- temp->kmalloc_ptr = kmalloc_ptr;
- temp->old_xfer_buffer = urb->transfer_buffer;
- if (!usb_urb_dir_in(urb))
- memcpy(temp->data, urb->transfer_buffer,
- urb->transfer_buffer_length);
- urb->transfer_buffer = temp->data;
- urb->transfer_flags |= URB_ALIGNED_TEMP_BUFFER;
-
- return 0;
-}
-
-static int tegra_ehci_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
- gfp_t mem_flags)
-{
- int ret;
-
- ret = alloc_dma_aligned_buffer(urb, mem_flags);
- if (ret)
- return ret;
-
- ret = usb_hcd_map_urb_for_dma(hcd, urb, mem_flags);
-
- /* control packets over dma */
- if (urb->setup_dma)
- dma_sync_single_for_device(hcd->self.controller,
- urb->setup_dma, sizeof(struct usb_ctrlrequest),
- DMA_TO_DEVICE);
-
- /* urb buffers over dma */
- if (urb->transfer_dma) {
- enum dma_data_direction dir;
- dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
-
- dma_sync_single_for_device(hcd->self.controller,
- urb->transfer_dma, urb->transfer_buffer_length, dir);
- }
-
- if (ret)
- free_dma_aligned_buffer(urb);
-
- return ret;
-}
-
-static void tegra_ehci_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
-{
- struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
-
- /* Fence read for coherency of AHB master intiated writes */
- if (tegra->phy->instance == 0)
- readb(IO_ADDRESS(IO_PPCS_PHYS + USB1_PREFETCH_ID));
- else if (tegra->phy->instance == 1)
- readb(IO_ADDRESS(IO_PPCS_PHYS + USB2_PREFETCH_ID));
- else if (tegra->phy->instance == 2)
- readb(IO_ADDRESS(IO_PPCS_PHYS + USB3_PREFETCH_ID));
-
- if (urb->transfer_dma) {
- enum dma_data_direction dir;
- dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
- if (dir == DMA_FROM_DEVICE)
- dma_sync_single_for_cpu(hcd->self.controller,
- urb->transfer_dma, urb->transfer_buffer_length,
- DMA_FROM_DEVICE);
- }
-
- usb_hcd_unmap_urb_for_dma(hcd, urb);
- free_dma_aligned_buffer(urb);
-}
-
-void clk_timer_callback(unsigned long data)
-{
- struct tegra_ehci_hcd *tegra = (struct tegra_ehci_hcd*) data;
- unsigned long flags;
-
- if (!timer_pending(&tegra->clk_timer)) {
- spin_lock_irqsave(&tegra->ehci->lock, flags);
- tegra->timer_event = 1;
- spin_unlock_irqrestore(&tegra->ehci->lock, flags);
- schedule_work(&tegra->clk_timer_work);
- }
-}
-
-static void clk_timer_work_handler(struct work_struct* clk_timer_work) {
- struct tegra_ehci_hcd *tegra = container_of(clk_timer_work,
- struct tegra_ehci_hcd, clk_timer_work);
- int ret;
- unsigned long flags;
- bool clock_enabled, timer_event;
-
- spin_lock_irqsave(&tegra->ehci->lock, flags);
- clock_enabled = tegra->clock_enabled;
- timer_event = tegra->timer_event;
- spin_unlock_irqrestore(&tegra->ehci->lock, flags);
-
- if (timer_event) {
- spin_lock_irqsave(&tegra->ehci->lock, flags);
- tegra->clock_enabled = 0;
- tegra->timer_event = 0;
- spin_unlock_irqrestore(&tegra->ehci->lock, flags);
- clk_disable(tegra->emc_clk);
- clk_disable(tegra->sclk_clk);
- return;
- }
-
- if ((!clock_enabled)) {
- ret = mod_timer(&tegra->clk_timer, jiffies + msecs_to_jiffies(2000));
- if (ret)
- pr_err("tegra_ehci_urb_enqueue timer modify failed \n");
- clk_enable(tegra->emc_clk);
- clk_enable(tegra->sclk_clk);
- spin_lock_irqsave(&tegra->ehci->lock, flags);
- tegra->clock_enabled = 1;
- spin_unlock_irqrestore(&tegra->ehci->lock, flags);
- } else {
- if (timer_pending(&tegra->clk_timer)) {
- mod_timer_pending (&tegra->clk_timer, jiffies
- + msecs_to_jiffies(2000));
- }
- }
-}
-
-static int tegra_ehci_urb_enqueue (
- struct usb_hcd *hcd,
- struct urb *urb,
- gfp_t mem_flags)
-{
- struct tegra_ehci_hcd *pdata;
- int xfertype;
- int transfer_buffer_length;
- struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- unsigned long flags;
- pdata = dev_get_drvdata(hcd->self.controller);
-
- xfertype = usb_endpoint_type(&urb->ep->desc);
- transfer_buffer_length = urb->transfer_buffer_length;
- spin_lock_irqsave(&ehci->lock,flags);
- /* Turn on the USB busy hints */
- switch (xfertype) {
- case USB_ENDPOINT_XFER_INT:
- if (transfer_buffer_length < 255) {
- /* Do nothing for interrupt buffers < 255 */
- } else {
- /* signal to set the busy hints */
- schedule_work(&pdata->clk_timer_work);
- }
- break;
- case USB_ENDPOINT_XFER_ISOC:
- case USB_ENDPOINT_XFER_BULK:
- /* signal to set the busy hints */
- schedule_work(&pdata->clk_timer_work);
- break;
- case USB_ENDPOINT_XFER_CONTROL:
- default:
- /* Do nothing special here */
- break;
- }
- spin_unlock_irqrestore(&ehci->lock,flags);
- return ehci_urb_enqueue(hcd, urb, mem_flags);
-}
-
static const struct hc_driver tegra_ehci_hc_driver = {
.description = hcd_name,
.product_desc = "Tegra EHCI Host Controller",
@@ -1085,9 +369,10 @@ static const struct hc_driver tegra_ehci_hc_driver = {
/* standard ehci functions */
.start = ehci_run,
.stop = ehci_stop,
+ .urb_enqueue = ehci_urb_enqueue,
.urb_dequeue = ehci_urb_dequeue,
.endpoint_disable = ehci_endpoint_disable,
- .endpoint_reset = ehci_endpoint_reset,
+ .endpoint_reset = ehci_endpoint_reset,
.get_frame_number = ehci_get_frame,
.hub_status_data = ehci_hub_status_data,
.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
@@ -1101,10 +386,9 @@ static const struct hc_driver tegra_ehci_hc_driver = {
.map_urb_for_dma = tegra_ehci_map_urb_for_dma,
.unmap_urb_for_dma = tegra_ehci_unmap_urb_for_dma,
.hub_control = tegra_ehci_hub_control,
- .urb_enqueue = tegra_ehci_urb_enqueue,
#ifdef CONFIG_PM
- .bus_suspend = tegra_ehci_bus_suspend,
- .bus_resume = tegra_ehci_bus_resume,
+ .bus_suspend = tegra_ehci_bus_suspend,
+ .bus_resume = tegra_ehci_bus_resume,
#endif
};
@@ -1113,76 +397,30 @@ static int tegra_ehci_probe(struct platform_device *pdev)
struct resource *res;
struct usb_hcd *hcd;
struct tegra_ehci_hcd *tegra;
- struct tegra_ehci_platform_data *pdata;
int err = 0;
int irq;
- int instance = pdev->id;
-
- pdata = pdev->dev.platform_data;
- if (!pdata) {
- dev_err(&pdev->dev, "Platform data missing\n");
- return -EINVAL;
- }
tegra = kzalloc(sizeof(struct tegra_ehci_hcd), GFP_KERNEL);
- if (!tegra)
+ if (!tegra) {
+ dev_err(&pdev->dev, "memory alloc failed\n");
return -ENOMEM;
+ }
- mutex_init(&tegra->tegra_ehci_hcd_mutex);
+ mutex_init(&tegra->sync_lock);
hcd = usb_create_hcd(&tegra_ehci_hc_driver, &pdev->dev,
dev_name(&pdev->dev));
if (!hcd) {
- dev_err(&pdev->dev, "Unable to create HCD\n");
+ dev_err(&pdev->dev, "unable to create HCD\n");
err = -ENOMEM;
goto fail_hcd;
}
platform_set_drvdata(pdev, tegra);
- tegra->default_enable = pdata->default_enable;
-
- tegra->clk = clk_get(&pdev->dev, NULL);
- if (IS_ERR(tegra->clk)) {
- dev_err(&pdev->dev, "Can't get ehci clock\n");
- err = PTR_ERR(tegra->clk);
- goto fail_clk;
- }
-
- err = clk_enable(tegra->clk);
- if (err)
- goto fail_clken;
-
-
- tegra->sclk_clk = clk_get(&pdev->dev, "sclk");
- if (IS_ERR(tegra->sclk_clk)) {
- dev_err(&pdev->dev, "Can't get sclk clock\n");
- err = PTR_ERR(tegra->sclk_clk);
- goto fail_sclk_clk;
- }
-
- clk_set_rate(tegra->sclk_clk, 80000000);
-
- tegra->emc_clk = clk_get(&pdev->dev, "emc");
- if (IS_ERR(tegra->emc_clk)) {
- dev_err(&pdev->dev, "Can't get emc clock\n");
- err = PTR_ERR(tegra->emc_clk);
- goto fail_emc_clk;
- }
- init_timer(&tegra->clk_timer);
- tegra->clk_timer.function = clk_timer_callback;
- tegra->clk_timer.data = (unsigned long) tegra;
-
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
- /* Set DDR busy hints to 150MHz. For Tegra 2x SOC, DDR rate is half of EMC rate */
- clk_set_rate(tegra->emc_clk, 300000000);
-#else
- /* Set DDR busy hints to 100MHz. For Tegra 3x SOC DDR rate equals to EMC rate */
- clk_set_rate(tegra->emc_clk, 100000000);
-#endif
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
- dev_err(&pdev->dev, "Failed to get I/O memory\n");
+ dev_err(&pdev->dev, "failed to get I/O memory\n");
err = -ENXIO;
goto fail_io;
}
@@ -1190,179 +428,103 @@ static int tegra_ehci_probe(struct platform_device *pdev)
hcd->rsrc_len = resource_size(res);
hcd->regs = ioremap(res->start, resource_size(res));
if (!hcd->regs) {
- dev_err(&pdev->dev, "Failed to remap I/O memory\n");
+ dev_err(&pdev->dev, "failed to remap I/O memory\n");
err = -ENOMEM;
goto fail_io;
}
- INIT_WORK(&tegra->clk_timer_work, clk_timer_work_handler);
+ irq = platform_get_irq(pdev, 0);
+ if (!irq) {
+ dev_err(&pdev->dev, "failed to get IRQ\n");
+ err = -ENODEV;
+ goto fail_irq;
+ }
+ set_irq_flags(irq, IRQF_VALID);
+ tegra->irq = irq;
- tegra->phy = tegra_usb_phy_open(instance, hcd->regs, pdata->phy_config,
- TEGRA_USB_PHY_MODE_HOST, pdata->phy_type);
+ tegra->phy = tegra_usb_phy_open(pdev);
if (IS_ERR(tegra->phy)) {
- dev_err(&pdev->dev, "Failed to open USB phy\n");
+ dev_err(&pdev->dev, "failed to open USB phy\n");
err = -ENXIO;
- goto fail_phy;
+ goto fail_irq;
}
- tegra->phy->hotplug = pdata->hotplug;
- err = tegra_usb_phy_power_on(tegra->phy, true);
+ err = tegra_usb_phy_power_on(tegra->phy);
if (err) {
- dev_err(&pdev->dev, "Failed to power on the phy\n");
- goto fail;
- }
-
- tegra->host_resumed = 1;
- tegra->power_down_on_bus_suspend = pdata->power_down_on_bus_suspend;
- tegra->ehci = hcd_to_ehci(hcd);
-
- irq = platform_get_irq(pdev, 0);
- if (!irq) {
- dev_err(&pdev->dev, "Failed to get IRQ\n");
- err = -ENODEV;
- goto fail;
+ dev_err(&pdev->dev, "failed to power on the phy\n");
+ goto fail_phy;
}
- set_irq_flags(irq, IRQF_VALID);
- tegra->irq = irq;
-#ifdef CONFIG_USB_OTG_UTILS
- if (pdata->operating_mode == TEGRA_USB_OTG) {
- tegra->transceiver = otg_get_transceiver();
- if (tegra->transceiver)
- otg_set_host(tegra->transceiver, &hcd->self);
+ err = tegra_usb_phy_init(tegra->phy);
+ if (err) {
+ dev_err(&pdev->dev, "failed to init the phy\n");
+ goto fail_phy;
}
-#endif
err = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
if (err) {
- dev_err(&pdev->dev, "Failed to add USB HCD error = %d\n", err);
- goto fail;
+ dev_err(&pdev->dev, "Failed to add USB HCD, error=%d\n", err);
+ goto fail_phy;
}
err = enable_irq_wake(tegra->irq);
if (err < 0) {
dev_warn(&pdev->dev,
- "Couldn't enable USB host mode wakeup, irq=%d, "
- "error=%d\n", tegra->irq, err);
+ "Couldn't enable USB host mode wakeup, irq=%d, "
+ "error=%d\n", irq, err);
err = 0;
tegra->irq = 0;
}
- return err;
+ tegra->ehci = hcd_to_ehci(hcd);
-fail:
#ifdef CONFIG_USB_OTG_UTILS
- if (tegra->transceiver) {
- otg_set_host(tegra->transceiver, NULL);
- otg_put_transceiver(tegra->transceiver);
+ if (tegra_usb_phy_otg_supported(tegra->phy)) {
+ tegra->transceiver = otg_get_transceiver();
+ if (tegra->transceiver)
+ otg_set_host(tegra->transceiver, &hcd->self);
}
#endif
- tegra_usb_phy_close(tegra->phy);
+ return err;
+
fail_phy:
+ tegra_usb_phy_close(tegra->phy);
+fail_irq:
iounmap(hcd->regs);
fail_io:
- clk_disable(tegra->emc_clk);
- clk_put(tegra->emc_clk);
-fail_emc_clk:
- clk_disable(tegra->sclk_clk);
- clk_put(tegra->sclk_clk);
-fail_sclk_clk:
- clk_disable(tegra->clk);
-fail_clken:
- clk_put(tegra->clk);
-fail_clk:
usb_put_hcd(hcd);
fail_hcd:
kfree(tegra);
+
return err;
}
+
#ifdef CONFIG_PM
static int tegra_ehci_resume_noirq(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev);
- mutex_lock(&tegra->tegra_ehci_hcd_mutex);
- if ((tegra->bus_suspended) && (tegra->power_down_on_bus_suspend)) {
- if (tegra->default_enable)
- clk_enable(tegra->clk);
- mutex_unlock(&tegra->tegra_ehci_hcd_mutex);
- return 0;
- }
-
- if (tegra->default_enable)
- clk_enable(tegra->clk);
-
- mutex_unlock(&tegra->tegra_ehci_hcd_mutex);
- return 0;
+ return tegra_usb_phy_power_on(tegra->phy);
}
-static int tegra_ehci_resume(struct device *dev)
+static int tegra_ehci_suspend_noirq(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev);
- struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci);
- int ret;
-
- mutex_lock(&tegra->tegra_ehci_hcd_mutex);
- if ((tegra->bus_suspended) && (tegra->power_down_on_bus_suspend)) {
- mutex_unlock(&tegra->tegra_ehci_hcd_mutex);
- return 0;
- }
- ret = tegra_usb_resume(hcd, true);
- mutex_unlock(&tegra->tegra_ehci_hcd_mutex);
- return ret;
-}
-
-static int tegra_ehci_suspend(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev);
- struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci);
- int ret;
- u32 val;
-
- mutex_lock(&tegra->tegra_ehci_hcd_mutex);
- /* if bus suspend is failed means there is remote wakeup resume,
- then abort the PM suspend */
- if (tegra->bus_suspended_fail) {
- tegra->bus_suspended_fail = false;
- pr_err("%s: bus suspend failed, aborting driver suspend\n", __func__);
- mutex_unlock(&tegra->tegra_ehci_hcd_mutex);
+ /* bus suspend could have failed because of remote wakeup resume */
+ if (tegra->bus_suspended_fail)
return -EBUSY;
- }
- if (tegra->phy->hotplug) {
- /* Disable PHY clock valid interrupts while going into suspend*/
- val = readl(hcd->regs + TEGRA_USB_SUSP_CTRL_OFFSET);
- val &= ~TEGRA_USB_PHY_CLK_VALID_INT_ENB;
- writel(val , (hcd->regs + TEGRA_USB_SUSP_CTRL_OFFSET));
- }
-
- if ((tegra->bus_suspended) && (tegra->power_down_on_bus_suspend)) {
- if (tegra->default_enable)
- clk_disable(tegra->clk);
- mutex_unlock(&tegra->tegra_ehci_hcd_mutex);
- return 0;
- }
-
- if (time_before(jiffies, tegra->ehci->next_statechange))
- msleep(10);
-
- ret = tegra_usb_suspend(hcd, true);
- if (tegra->default_enable)
- clk_disable(tegra->clk);
- mutex_unlock(&tegra->tegra_ehci_hcd_mutex);
- return ret;
+ else
+ return tegra_usb_phy_power_off(tegra->phy);
}
static struct dev_pm_ops tegra_ehci_dev_pm_ops = {
- .suspend = tegra_ehci_suspend,
- .resume = tegra_ehci_resume,
- .resume_noirq = tegra_ehci_resume_noirq,
+ .suspend_noirq = tegra_ehci_suspend_noirq,
+ .resume_noirq = tegra_ehci_resume_noirq,
};
-
#endif
static int tegra_ehci_remove(struct platform_device *pdev)
@@ -1372,9 +534,6 @@ static int tegra_ehci_remove(struct platform_device *pdev)
if (tegra == NULL || hcd == NULL)
return -EINVAL;
- /* make sure controller is on as we will touch its registers */
- if (!tegra->host_resumed)
- tegra_ehci_power_up(hcd, true);
#ifdef CONFIG_USB_OTG_UTILS
if (tegra->transceiver) {
@@ -1383,30 +542,15 @@ static int tegra_ehci_remove(struct platform_device *pdev)
}
#endif
- /* Turn Off Interrupts */
- ehci_writel(tegra->ehci, 0, &tegra->ehci->regs->intr_enable);
- clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
if (tegra->irq)
disable_irq_wake(tegra->irq);
usb_remove_hcd(hcd);
usb_put_hcd(hcd);
- tegra_usb_phy_power_off(tegra->phy, true);
+ tegra_usb_phy_power_off(tegra->phy);
tegra_usb_phy_close(tegra->phy);
iounmap(hcd->regs);
-
- del_timer_sync(&tegra->clk_timer);
-
- clk_disable(tegra->clk);
- clk_put(tegra->clk);
-
- if (tegra->clock_enabled) {
- clk_disable(tegra->sclk_clk);
- clk_disable(tegra->emc_clk);
- }
- clk_put(tegra->sclk_clk);
- clk_put(tegra->emc_clk);
-
kfree(tegra);
+
return 0;
}
@@ -1421,12 +565,12 @@ static void tegra_ehci_hcd_shutdown(struct platform_device *pdev)
static struct platform_driver tegra_ehci_driver = {
.probe = tegra_ehci_probe,
- .remove = tegra_ehci_remove,
+ .remove = tegra_ehci_remove,
.shutdown = tegra_ehci_hcd_shutdown,
- .driver = {
- .name = "tegra-ehci",
+ .driver = {
+ .name = driver_name,
#ifdef CONFIG_PM
- .pm = &tegra_ehci_dev_pm_ops,
+ .pm = &tegra_ehci_dev_pm_ops,
#endif
}
};
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 509934ceb4a9..cfbdf32ec0b2 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -143,6 +143,7 @@ struct ehci_hcd { /* one per controller */
#ifdef CONFIG_USB_EHCI_TEGRA
unsigned controller_resets_phy:1;
unsigned controller_remote_wakeup:1;
+ unsigned broken_hostpc_phcd:1;
#endif
/* required for usb32 quirk */
diff --git a/drivers/usb/otg/tegra-otg.c b/drivers/usb/otg/tegra-otg.c
index f72e2225e7c7..4c590076f73e 100644
--- a/drivers/usb/otg/tegra-otg.c
+++ b/drivers/usb/otg/tegra-otg.c
@@ -24,7 +24,6 @@
#include <linux/usb.h>
#include <linux/usb/otg.h>
#include <linux/usb/gadget.h>
-#include <linux/usb/hcd.h>
#include <linux/platform_device.h>
#include <linux/platform_data/tegra_usb.h>
#include <linux/clk.h>
@@ -41,7 +40,6 @@
#define USB_VBUS_INT_EN (1 << 8)
#define USB_VBUS_INT_STATUS (1 << 9)
#define USB_VBUS_STATUS (1 << 10)
-#define USB_INTS (USB_VBUS_INT_STATUS | USB_ID_INT_STATUS)
#define USB_INT_EN (USB_VBUS_INT_EN | USB_ID_INT_EN | \
USB_VBUS_WAKEUP_EN | USB_ID_PIN_WAKEUP_EN)
@@ -67,9 +65,9 @@ struct tegra_otg_data {
bool clk_enabled;
callback_t charger_cb;
void *charger_cb_data;
-
bool interrupt_mode;
};
+
static struct tegra_otg_data *tegra_clone;
static inline unsigned long otg_readl(struct tegra_otg_data *tegra,
@@ -84,20 +82,6 @@ static inline void otg_writel(struct tegra_otg_data *tegra, unsigned long val,
writel(val, tegra->regs + offset);
}
-static void tegra_otg_enable_clk(void)
-{
- if (!tegra_clone->clk_enabled)
- clk_enable(tegra_clone->clk);
- tegra_clone->clk_enabled = true;
-}
-
-static void tegra_otg_disable_clk(void)
-{
- if (tegra_clone->clk_enabled)
- clk_disable(tegra_clone->clk);
- tegra_clone->clk_enabled = false;
-}
-
static const char *tegra_state_name(enum usb_otg_state state)
{
switch (state) {
@@ -132,78 +116,69 @@ static unsigned long enable_interrupt(struct tegra_otg_data *tegra, bool en)
return val;
}
-static struct platform_device *
-tegra_usb_otg_host_register(struct platform_device *ehci_device,
- struct tegra_ehci_platform_data *pdata)
+static void tegra_start_host(struct tegra_otg_data *tegra)
{
- struct platform_device *pdev;
+ struct tegra_usb_otg_data *pdata = tegra->otg.dev->platform_data;
+ struct platform_device *pdev, *ehci_device = pdata->ehci_device;
void *platform_data;
int val;
+ DBG("%s(%d) Begin\n", __func__, __LINE__);
+ if (tegra->pdev)
+ return ;
+
+ /* prepare device structure for registering host*/
pdev = platform_device_alloc(ehci_device->name, ehci_device->id);
if (!pdev)
- return NULL;
+ return ;
val = platform_device_add_resources(pdev, ehci_device->resource,
ehci_device->num_resources);
if (val)
goto error;
- pdev->dev.dma_mask = ehci_device->dev.dma_mask;
+ pdev->dev.dma_mask = ehci_device->dev.dma_mask;
pdev->dev.coherent_dma_mask = ehci_device->dev.coherent_dma_mask;
- platform_data = kmalloc(sizeof(struct tegra_ehci_platform_data),
- GFP_KERNEL);
+ platform_data = kmalloc(sizeof(struct tegra_usb_platform_data), GFP_KERNEL);
if (!platform_data)
goto error;
- memcpy(platform_data, pdata, sizeof(struct tegra_ehci_platform_data));
+ memcpy(platform_data, pdata->ehci_pdata,
+ sizeof(struct tegra_usb_platform_data));
pdev->dev.platform_data = platform_data;
val = platform_device_add(pdev);
if (val)
goto error_add;
- return pdev;
+ tegra->pdev = pdev;
+ DBG("%s(%d) End\n", __func__, __LINE__);
+ return ;
error_add:
kfree(platform_data);
error:
pr_err("%s: failed to add the host controller device\n", __func__);
platform_device_put(pdev);
- return NULL;
-}
-
-static void tegra_usb_otg_host_unregister(struct platform_device *pdev)
-{
- kfree(pdev->dev.platform_data);
- pdev->dev.platform_data = NULL;
- platform_device_unregister(pdev);
+ tegra->pdev = NULL;
}
-void tegra_start_host(struct tegra_otg_data *tegra)
+static void tegra_stop_host(struct tegra_otg_data *tegra)
{
- DBG("%s(%d) BEGIN\n", __func__, __LINE__);
-
- struct tegra_otg_platform_data *pdata = tegra->otg.dev->platform_data;
- if (!tegra->pdev) {
- tegra->pdev = tegra_usb_otg_host_register(pdata->ehci_device,
- pdata->ehci_pdata);
- }
-
- DBG("%s(%d) END\n", __func__, __LINE__);
-}
+ struct platform_device *pdev = tegra->pdev;
-void tegra_stop_host(struct tegra_otg_data *tegra)
-{
- DBG("%s(%d) BEGIN\n", __func__, __LINE__);
+ DBG("%s(%d) Begin\n", __func__, __LINE__);
- if (tegra->pdev) {
- tegra_usb_otg_host_unregister(tegra->pdev);
+ if (pdev) {
+ /* unregister host from otg */
+ kfree(pdev->dev.platform_data);
+ pdev->dev.platform_data = NULL;
+ platform_device_unregister(pdev);
tegra->pdev = NULL;
}
- DBG("%s(%d) END\n", __func__, __LINE__);
+ DBG("%s(%d) End\n", __func__, __LINE__);
}
int register_otg_callback(callback_t cb, void *args)
@@ -263,10 +238,7 @@ static void irq_work(struct work_struct *work)
unsigned long flags;
unsigned long status;
- clk_enable(tegra->clk);
-
spin_lock_irqsave(&tegra->lock, flags);
-
status = tegra->int_status;
/* Debug prints */
@@ -299,8 +271,6 @@ static void irq_work(struct work_struct *work)
spin_unlock_irqrestore(&tegra->lock, flags);
tegra_change_otg_state(tegra, to);
- clk_disable(tegra->clk);
- tegra_otg_disable_clk();
}
static irqreturn_t tegra_otg_irq(int irq, void *data)
@@ -310,8 +280,9 @@ static irqreturn_t tegra_otg_irq(int irq, void *data)
unsigned long val;
spin_lock_irqsave(&tegra->lock, flags);
-
val = otg_readl(tegra, USB_PHY_WAKEUP);
+ DBG("%s(%d) interrupt val = 0x%x\n", __func__, __LINE__, val);
+
if (val & (USB_VBUS_INT_EN | USB_ID_INT_EN)) {
DBG("%s(%d) PHY_WAKEUP = 0x%x\n", __func__, __LINE__, val);
otg_writel(tegra, val, USB_PHY_WAKEUP);
@@ -320,17 +291,11 @@ static irqreturn_t tegra_otg_irq(int irq, void *data)
schedule_work(&tegra->work);
}
}
-
spin_unlock_irqrestore(&tegra->lock, flags);
return IRQ_HANDLED;
}
-void tegra_otg_check_vbus_detection(void)
-{
- tegra_otg_enable_clk();
-}
-EXPORT_SYMBOL(tegra_otg_check_vbus_detection);
static int tegra_otg_set_peripheral(struct otg_transceiver *otg,
struct usb_gadget *gadget)
@@ -353,7 +318,7 @@ static int tegra_otg_set_peripheral(struct otg_transceiver *otg,
if ((val & USB_ID_INT_STATUS) || (val & USB_VBUS_INT_STATUS)) {
tegra->int_status = val;
- schedule_work (&tegra->work);
+ schedule_work(&tegra->work);
}
DBG("%s(%d) END\n", __func__, __LINE__);
@@ -373,7 +338,6 @@ static int tegra_otg_set_host(struct otg_transceiver *otg,
clk_enable(tegra->clk);
val = otg_readl(tegra, USB_PHY_WAKEUP);
val &= ~(USB_VBUS_INT_STATUS | USB_ID_INT_STATUS);
-
val |= (USB_ID_INT_EN | USB_ID_PIN_WAKEUP_EN);
otg_writel(tegra, val, USB_PHY_WAKEUP);
clk_disable(tegra->clk);
@@ -435,8 +399,6 @@ static DEVICE_ATTR(enable_host, 0644, show_host_en, store_host_en);
static int tegra_otg_probe(struct platform_device *pdev)
{
struct tegra_otg_data *tegra;
- struct tegra_otg_platform_data *otg_pdata;
- struct tegra_ehci_platform_data *ehci_pdata;
struct resource *res;
int err;
@@ -445,8 +407,6 @@ static int tegra_otg_probe(struct platform_device *pdev)
return -ENOMEM;
tegra->otg.dev = &pdev->dev;
- otg_pdata = tegra->otg.dev->platform_data;
- ehci_pdata = otg_pdata->ehci_pdata;
tegra->otg.label = "tegra-otg";
tegra->otg.state = OTG_STATE_UNDEFINED;
tegra->otg.set_host = tegra_otg_set_host;
@@ -457,7 +417,6 @@ static int tegra_otg_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, tegra);
tegra_clone = tegra;
- tegra->clk_enabled = false;
tegra->interrupt_mode = true;
tegra->clk = clk_get(&pdev->dev, NULL);
@@ -505,10 +464,8 @@ static int tegra_otg_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "Failed to register IRQ\n");
goto err_irq;
}
- INIT_WORK (&tegra->work, irq_work);
+ INIT_WORK(&tegra->work, irq_work);
- if (!ehci_pdata->default_enable)
- clk_disable(tegra->clk);
dev_info(&pdev->dev, "otg transceiver registered\n");
err = device_create_file(&pdev->dev, &dev_attr_enable_host);
@@ -552,59 +509,57 @@ static int __exit tegra_otg_remove(struct platform_device *pdev)
static int tegra_otg_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
- struct tegra_otg_data *tegra_otg = platform_get_drvdata(pdev);
- struct otg_transceiver *otg = &tegra_otg->otg;
+ struct tegra_otg_data *tegra = platform_get_drvdata(pdev);
+ struct otg_transceiver *otg = &tegra->otg;
int val;
DBG("%s(%d) BEGIN state : %s\n", __func__, __LINE__,
tegra_state_name(otg->state));
- clk_enable(tegra_otg->clk);
- val = readl(tegra_otg->regs + USB_PHY_WAKEUP);
+ clk_enable(tegra->clk);
+ val = readl(tegra->regs + USB_PHY_WAKEUP);
val &= ~USB_INT_EN;
- writel(val, tegra_otg->regs + USB_PHY_WAKEUP);
- clk_disable(tegra_otg->clk);
+ writel(val, tegra->regs + USB_PHY_WAKEUP);
+ clk_disable(tegra->clk);
- /* suspend peripheral mode, host mode is taken care by host driver */
+ /* Suspend peripheral mode, host mode is taken care by host driver */
if (otg->state == OTG_STATE_B_PERIPHERAL)
- tegra_change_otg_state(tegra_otg, OTG_STATE_A_SUSPEND);
+ tegra_change_otg_state(tegra, OTG_STATE_A_SUSPEND);
DBG("%s(%d) END\n", __func__, __LINE__);
- tegra_otg_disable_clk();
return 0;
}
static void tegra_otg_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
- struct tegra_otg_data *tegra_otg = platform_get_drvdata(pdev);
- struct otg_transceiver *otg = &tegra_otg->otg;
-
+ struct tegra_otg_data *tegra = platform_get_drvdata(pdev);
+ struct otg_transceiver *otg = &tegra->otg;
int val;
unsigned long flags;
DBG("%s(%d) BEGIN\n", __func__, __LINE__);
/* Clear pending interrupts */
- clk_enable(tegra_otg->clk);
- val = readl(tegra_otg->regs + USB_PHY_WAKEUP);
- writel(val, tegra_otg->regs + USB_PHY_WAKEUP);
+ clk_enable(tegra->clk);
+ val = readl(tegra->regs + USB_PHY_WAKEUP);
+ writel(val, tegra->regs + USB_PHY_WAKEUP);
DBG("%s(%d) PHY WAKEUP register : 0x%x\n", __func__, __LINE__, val);
- clk_disable(tegra_otg->clk);
+ clk_disable(tegra->clk);
/* Handle if host cable is replaced with device during suspend state */
if (otg->state == OTG_STATE_A_HOST && (val & USB_ID_STATUS))
- tegra_change_otg_state(tegra_otg, OTG_STATE_A_SUSPEND);
+ tegra_change_otg_state(tegra, OTG_STATE_A_SUSPEND);
/* Enable interrupt and call work to set to appropriate state */
- spin_lock_irqsave(&tegra_otg->lock, flags);
- tegra_otg->int_status = (val | USB_INT_EN);
- spin_unlock_irqrestore(&tegra_otg->lock, flags);
- irq_work(&tegra_otg->work);
+ spin_lock_irqsave(&tegra->lock, flags);
+ tegra->int_status = (val | USB_INT_EN);
+ spin_unlock_irqrestore(&tegra->lock, flags);
+ irq_work(&tegra->work);
- clk_enable(tegra_otg->clk);
- val = readl(tegra_otg->regs + USB_PHY_WAKEUP);
+ clk_enable(tegra->clk);
+ val = readl(tegra->regs + USB_PHY_WAKEUP);
val |= USB_INT_EN;
- writel(val, tegra_otg->regs + USB_PHY_WAKEUP);
- clk_disable(tegra_otg->clk);
+ writel(val, tegra->regs + USB_PHY_WAKEUP);
+ clk_disable(tegra->clk);
DBG("%s(%d) END\n", __func__, __LINE__);
}
diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c
index 55d3fccf56b2..df54578a5b5a 100644
--- a/drivers/video/tegra/dc/dc.c
+++ b/drivers/video/tegra/dc/dc.c
@@ -583,6 +583,23 @@ static unsigned int tegra_dc_has_multiple_dc(void)
return (cnt > 1);
}
+/* get the stride size of a window.
+ * return: stride size in bytes for window win. or 0 if unavailble. */
+int tegra_dc_get_stride(struct tegra_dc *dc, unsigned win)
+{
+ u32 tmp;
+ u32 stride;
+
+ if (!dc->enabled)
+ return 0;
+ BUG_ON(win > DC_N_WINDOWS);
+ tegra_dc_writel(dc, WINDOW_A_SELECT << win,
+ DC_CMD_DISPLAY_WINDOW_HEADER);
+ tmp = tegra_dc_readl(dc, DC_WIN_LINE_STRIDE);
+ return GET_LINE_STRIDE(tmp);
+}
+EXPORT_SYMBOL(tegra_dc_get_stride);
+
struct tegra_dc *tegra_dc_get_dc(unsigned idx)
{
if (idx < TEGRA_MAX_DC)
diff --git a/drivers/video/tegra/dc/dc_reg.h b/drivers/video/tegra/dc/dc_reg.h
index ded64de2decc..0b628fc7a14a 100644
--- a/drivers/video/tegra/dc/dc_reg.h
+++ b/drivers/video/tegra/dc/dc_reg.h
@@ -431,6 +431,8 @@
#define DC_WIN_LINE_STRIDE 0x70a
#define LINE_STRIDE(x) (x)
#define UV_LINE_STRIDE(x) (((x) & 0xffff) << 16)
+#define GET_LINE_STRIDE(x) ((x) & 0xffff)
+#define GET_UV_LINE_STRIDE(x) (((x) >> 16) & 0xffff)
#define DC_WIN_BUF_STRIDE 0x70b
#define DC_WIN_UV_BUF_STRIDE 0x70c
#define DC_WIN_BUFFER_ADDR_MODE 0x70d
diff --git a/drivers/video/tegra/dc/dsi.c b/drivers/video/tegra/dc/dsi.c
index 69cc60f70f1c..e402c416b779 100644
--- a/drivers/video/tegra/dc/dsi.c
+++ b/drivers/video/tegra/dc/dsi.c
@@ -1,7 +1,7 @@
/*
* drivers/video/tegra/dc/dsi.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
@@ -31,6 +31,7 @@
#include <mach/dc.h>
#include <mach/fb.h>
#include <mach/csi.h>
+#include <mach/iomap.h>
#include <linux/nvhost.h>
#include "dc_reg.h"
@@ -38,6 +39,9 @@
#include "dsi_regs.h"
#include "dsi.h"
+#define APB_MISC_GP_MIPI_PAD_CTRL_0 (TEGRA_APB_MISC_BASE + 0x820)
+#define DSIB_MODE_ENABLE 0x2
+
#define DSI_USE_SYNC_POINTS 1
#define S_TO_MS(x) (1000 * (x))
@@ -1621,6 +1625,15 @@ static void tegra_dsi_pad_calibration(struct tegra_dc_dsi_data *dsi)
tegra_vi_csi_writel(val, CSI_CIL_PAD_CONFIG);
}
+static void tegra_dsi_panelB_enable()
+{
+ unsigned int val;
+
+ val = readl(IO_ADDRESS(APB_MISC_GP_MIPI_PAD_CTRL_0));
+ val |= DSIB_MODE_ENABLE;
+ writel(val, (IO_ADDRESS(APB_MISC_GP_MIPI_PAD_CTRL_0)));
+}
+
static int tegra_dsi_init_hw(struct tegra_dc *dc,
struct tegra_dc_dsi_data *dsi)
{
@@ -1634,7 +1647,7 @@ static int tegra_dsi_init_hw(struct tegra_dc *dc,
tegra_dsi_set_dsi_clk(dc, dsi, dsi->target_lp_clk_khz);
if (dsi->info.dsi_instance) {
- /* TODO:Set the misc register*/
+ tegra_dsi_panelB_enable();
}
/* TODO: only need to change the timing for bta */
diff --git a/drivers/video/tegra/fb.c b/drivers/video/tegra/fb.c
index 50aa9b383059..1193a2eb8c52 100644
--- a/drivers/video/tegra/fb.c
+++ b/drivers/video/tegra/fb.c
@@ -44,7 +44,7 @@
#include "dc/dc_priv.h"
/* Pad pitch to 16-byte boundary. */
-#define TEGRA_LINEAR_PITCH_ALIGNMENT 16
+#define TEGRA_LINEAR_PITCH_ALIGNMENT 32
struct tegra_fb_info {
struct tegra_dc_win *win;
@@ -527,6 +527,7 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev,
unsigned long fb_size = 0;
unsigned long fb_phys = 0;
int ret = 0;
+ unsigned stride;
win = tegra_dc_get_window(dc, fb_data->win);
if (!win) {
@@ -560,6 +561,11 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev,
tegra_fb->valid = true;
}
+ stride = tegra_dc_get_stride(dc, 0);
+ if (!stride) /* default to pad the stride to 16-byte boundary. */
+ stride = round_up(info->fix.line_length,
+ TEGRA_LINEAR_PITCH_ALIGNMENT);
+
info->fbops = &tegra_fb_ops;
info->pseudo_palette = pseudo_palette;
info->screen_base = fb_base;
@@ -574,9 +580,7 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev,
info->fix.smem_start = fb_phys;
info->fix.smem_len = fb_size;
info->fix.line_length = fb_data->xres * fb_data->bits_per_pixel / 8;
- /* Pad the stride to 16-byte boundary. */
- info->fix.line_length = round_up(info->fix.line_length,
- TEGRA_LINEAR_PITCH_ALIGNMENT);
+ info->fix.line_length = stride;
info->var.xres = fb_data->xres;
info->var.yres = fb_data->yres;
diff --git a/drivers/video/tegra/host/bus_client.c b/drivers/video/tegra/host/bus_client.c
index fd632a6ea9c5..87aa9c64d363 100644
--- a/drivers/video/tegra/host/bus_client.c
+++ b/drivers/video/tegra/host/bus_client.c
@@ -141,12 +141,6 @@ static int nvhost_channelopen(struct inode *inode, struct file *filp)
priv->clientid = atomic_add_return(1,
&nvhost_get_host(ch->dev)->clientid);
priv->timeout = MAX_STUCK_CHECK_COUNT * SYNCPT_CHECK_PERIOD;
-
- priv->job = nvhost_job_alloc(ch, priv->hwctx, &priv->hdr,
- NULL, priv->priority, priv->clientid);
- if (!priv->job)
- goto fail;
-
return 0;
fail:
nvhost_channelrelease(inode, filp);
@@ -166,7 +160,7 @@ static int set_submit(struct nvhost_channel_userctx *ctx)
return -EFAULT;
}
- ctx->job = nvhost_job_realloc(ctx->job,
+ ctx->job = nvhost_job_alloc(ctx->ch,
ctx->hwctx,
&ctx->hdr,
ctx->nvmap,
@@ -238,17 +232,28 @@ static ssize_t nvhost_channelwrite(struct file *filp, const char __user *buf,
cmdbuf.mem, cmdbuf.words, cmdbuf.offset);
hdr->num_cmdbufs--;
} else if (hdr->num_relocs) {
- consumed = sizeof(struct nvhost_reloc);
- if (remaining < consumed)
+ int numrelocs = remaining / sizeof(struct nvhost_reloc);
+ if (!numrelocs)
break;
- if (copy_from_user(&job->pinarray[job->num_pins],
+ numrelocs = min_t(int, numrelocs, priv->hdr.num_relocs);
+ consumed = numrelocs * sizeof(struct nvhost_reloc);
+ if (copy_from_user(&job->relocarray[job->num_relocs],
buf, consumed)) {
err = -EFAULT;
break;
}
- trace_nvhost_channel_write_reloc(chname);
- job->num_pins++;
- hdr->num_relocs--;
+ while (numrelocs) {
+ struct nvhost_reloc *reloc =
+ &job->relocarray[job->num_relocs];
+ trace_nvhost_channel_write_reloc(chname,
+ reloc->cmdbuf_mem,
+ reloc->cmdbuf_offset,
+ reloc->target,
+ reloc->target_offset);
+ job->num_relocs++;
+ hdr->num_relocs--;
+ numrelocs--;
+ }
} else if (hdr->num_waitchks) {
int numwaitchks =
(remaining / sizeof(struct nvhost_waitchk));
@@ -269,17 +274,19 @@ static ssize_t nvhost_channelwrite(struct file *filp, const char __user *buf,
hdr->num_waitchks -= numwaitchks;
} else if (priv->num_relocshifts) {
int next_shift =
- job->num_pins - priv->num_relocshifts;
- consumed = sizeof(struct nvhost_reloc_shift);
- if (remaining < consumed)
+ job->num_relocs - priv->num_relocshifts;
+ int num =
+ (remaining / sizeof(struct nvhost_reloc_shift));
+ if (!num)
break;
- if (copy_from_user(
- &job->pinarray[next_shift].reloc_shift,
+ num = min_t(int, num, priv->num_relocshifts);
+ consumed = num * sizeof(struct nvhost_reloc_shift);
+ if (copy_from_user(&job->relocshiftarray[next_shift],
buf, consumed)) {
err = -EFAULT;
break;
}
- priv->num_relocshifts--;
+ priv->num_relocshifts -= num;
} else {
err = -EFAULT;
break;
@@ -302,7 +309,7 @@ static int nvhost_ioctl_channel_flush(
struct nvhost_get_param_args *args,
int null_kickoff)
{
- struct device *device = &ctx->ch->dev->dev;
+ struct nvhost_device *ndev = to_nvhost_device(&ctx->ch->dev->dev);
int err;
trace_nvhost_ioctl_channel_flush(ctx->ch->dev->name);
@@ -312,13 +319,13 @@ static int nvhost_ioctl_channel_flush(
ctx->hdr.num_cmdbufs ||
ctx->hdr.num_waitchks) {
reset_submit(ctx);
- dev_err(device, "channel submit out of sync\n");
+ dev_err(&ndev->dev, "channel submit out of sync\n");
return -EFAULT;
}
- err = nvhost_job_pin(ctx->job);
+ err = nvhost_job_pin(ctx->job, &nvhost_get_host(ndev)->syncpt);
if (err) {
- dev_warn(device, "nvhost_job_pin failed: %d\n", err);
+ dev_warn(&ndev->dev, "nvhost_job_pin failed: %d\n", err);
return err;
}
@@ -337,6 +344,9 @@ static int nvhost_ioctl_channel_flush(
if (err)
nvhost_job_unpin(ctx->job);
+ nvhost_job_put(ctx->job);
+ ctx->job = NULL;
+
return err;
}
diff --git a/drivers/video/tegra/host/chip_support.h b/drivers/video/tegra/host/chip_support.h
index edc5f6a51574..d69e1c4bccb9 100644
--- a/drivers/video/tegra/host/chip_support.h
+++ b/drivers/video/tegra/host/chip_support.h
@@ -28,10 +28,9 @@ struct output;
struct nvhost_master;
struct nvhost_intr;
struct nvhost_syncpt;
-struct nvhost_waitchk;
struct nvhost_userctx_timeout;
struct nvhost_channel;
-struct nvmap_handle;
+struct nvmap_handle_ref;
struct nvmap_client;
struct nvhost_hwctx;
struct nvhost_cdma;
@@ -77,7 +76,7 @@ struct nvhost_chip_support {
void (*destroy)(struct push_buffer *);
void (*push_to)(struct push_buffer *,
struct nvmap_client *,
- struct nvmap_handle *,
+ struct nvmap_handle_ref *,
u32 op1, u32 op2);
void (*pop_from)(struct push_buffer *,
unsigned int slots);
@@ -106,11 +105,8 @@ struct nvhost_chip_support {
void (*read_wait_base)(struct nvhost_syncpt *, u32 id);
u32 (*update_min)(struct nvhost_syncpt *, u32 id);
void (*cpu_incr)(struct nvhost_syncpt *, u32 id);
- int (*wait_check)(struct nvhost_syncpt *sp,
- struct nvmap_client *nvmap,
- u32 waitchk_mask,
- struct nvhost_waitchk *wait,
- int num_waitchk);
+ int (*patch_wait)(struct nvhost_syncpt *sp,
+ void *patch_addr);
void (*debug)(struct nvhost_syncpt *);
const char * (*name)(struct nvhost_syncpt *, u32 id);
int (*mutex_try_lock)(struct nvhost_syncpt *,
diff --git a/drivers/video/tegra/host/debug.c b/drivers/video/tegra/host/debug.c
index 8a26f92c79f6..820eac85521d 100644
--- a/drivers/video/tegra/host/debug.c
+++ b/drivers/video/tegra/host/debug.c
@@ -106,13 +106,53 @@ static void show_all(struct nvhost_master *m, struct output *o)
nvhost_get_chip_ops()->debug.show_mlocks(m, o);
show_syncpts(m, o);
nvhost_debug_output(o, "---- channels ----\n");
- bus_for_each_dev(&(nvhost_bus_get())->nvhost_bus_type, NULL, o, show_channels);
+ bus_for_each_dev(&(nvhost_bus_get())->nvhost_bus_type, NULL, o,
+ show_channels);
nvhost_module_idle(m->dev);
}
#ifdef CONFIG_DEBUG_FS
-static int nvhost_debug_show(struct seq_file *s, void *unused)
+static int show_channels_no_fifo(struct device *dev, void *data)
+{
+ struct nvhost_channel *ch;
+ struct nvhost_device *nvdev = to_nvhost_device(dev);
+ struct output *o = data;
+ struct nvhost_master *m;
+
+ if (nvdev == NULL)
+ return 0;
+
+ m = nvhost_get_host(nvdev);
+ ch = nvdev->channel;
+ if (ch) {
+ mutex_lock(&ch->reflock);
+ if (ch->refcount) {
+ mutex_lock(&ch->cdma.lock);
+ nvhost_get_chip_ops()->debug.show_channel_cdma(m,
+ ch, o, nvdev->index);
+ mutex_unlock(&ch->cdma.lock);
+ }
+ mutex_unlock(&ch->reflock);
+ }
+
+ return 0;
+}
+
+static void show_all_no_fifo(struct nvhost_master *m, struct output *o)
+{
+ nvhost_module_busy(m->dev);
+
+ nvhost_get_chip_ops()->debug.show_mlocks(m, o);
+ show_syncpts(m, o);
+ nvhost_debug_output(o, "---- channels ----\n");
+ bus_for_each_dev(&(nvhost_bus_get())->nvhost_bus_type, NULL, o,
+ show_channels_no_fifo);
+
+ nvhost_module_idle(m->dev);
+}
+
+static int nvhost_debug_show_all(struct seq_file *s, void *unused)
{
struct output o = {
.fn = write_to_seqfile,
@@ -121,6 +161,27 @@ static int nvhost_debug_show(struct seq_file *s, void *unused)
show_all(s->private, &o);
return 0;
}
+static int nvhost_debug_show(struct seq_file *s, void *unused)
+{
+ struct output o = {
+ .fn = write_to_seqfile,
+ .ctx = s
+ };
+ show_all_no_fifo(s->private, &o);
+ return 0;
+}
+
+static int nvhost_debug_open_all(struct inode *inode, struct file *file)
+{
+ return single_open(file, nvhost_debug_show_all, inode->i_private);
+}
+
+static const struct file_operations nvhost_debug_all_fops = {
+ .open = nvhost_debug_open_all,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
static int nvhost_debug_open(struct inode *inode, struct file *file)
{
@@ -140,6 +201,8 @@ void nvhost_debug_init(struct nvhost_master *master)
debugfs_create_file("status", S_IRUGO, de,
master, &nvhost_debug_fops);
+ debugfs_create_file("status_all", S_IRUGO, de,
+ master, &nvhost_debug_all_fops);
debugfs_create_u32("null_kickoff_pid", S_IRUGO|S_IWUSR, de,
&nvhost_debug_null_kickoff_pid);
diff --git a/drivers/video/tegra/host/gr3d/gr3d_t20.c b/drivers/video/tegra/host/gr3d/gr3d_t20.c
index c0efac03b882..5645f5b2b0c6 100644
--- a/drivers/video/tegra/host/gr3d/gr3d_t20.c
+++ b/drivers/video/tegra/host/gr3d/gr3d_t20.c
@@ -138,7 +138,7 @@ static void save_push_v0(struct nvhost_hwctx *nctx, struct nvhost_cdma *cdma)
nvhost_cdma_push_gather(cdma,
nvhost_get_host(nctx->channel->dev)->nvmap,
- p->save_buf->handle,
+ p->save_buf,
0,
nvhost_opcode_gather(p->save_size),
p->save_phys);
diff --git a/drivers/video/tegra/host/gr3d/gr3d_t30.c b/drivers/video/tegra/host/gr3d/gr3d_t30.c
index 93d98dfa645c..57f4c779eff8 100644
--- a/drivers/video/tegra/host/gr3d/gr3d_t30.c
+++ b/drivers/video/tegra/host/gr3d/gr3d_t30.c
@@ -145,7 +145,7 @@ static void save_push_v1(struct nvhost_hwctx *nctx, struct nvhost_cdma *cdma)
/* gather the save buffer */
nvhost_cdma_push_gather(cdma,
nvhost_get_host(nctx->channel->dev)->nvmap,
- p->save_buf->handle,
+ p->save_buf,
0,
nvhost_opcode_gather(p->save_size),
p->save_phys);
diff --git a/drivers/video/tegra/host/host1x/host1x_cdma.c b/drivers/video/tegra/host/host1x/host1x_cdma.c
index fcb1f05f0025..4569c3d62494 100644
--- a/drivers/video/tegra/host/host1x/host1x_cdma.c
+++ b/drivers/video/tegra/host/host1x/host1x_cdma.c
@@ -137,7 +137,7 @@ static void push_buffer_destroy(struct push_buffer *pb)
*/
static void push_buffer_push_to(struct push_buffer *pb,
struct nvmap_client *client,
- struct nvmap_handle *handle, u32 op1, u32 op2)
+ struct nvmap_handle_ref *handle, u32 op1, u32 op2)
{
u32 cur = pb->cur;
u32 *p = (u32 *)((u32)pb->mapped + cur);
diff --git a/drivers/video/tegra/host/host1x/host1x_channel.c b/drivers/video/tegra/host/host1x/host1x_channel.c
index 8c4a7a5c74ad..c72e6478b806 100644
--- a/drivers/video/tegra/host/host1x/host1x_channel.c
+++ b/drivers/video/tegra/host/host1x/host1x_channel.c
@@ -143,7 +143,7 @@ static void submit_ctxrestore(struct nvhost_job *job)
/* Send restore buffer to channel */
nvhost_cdma_push_gather(&ch->cdma,
host->nvmap,
- nvmap_ref_to_handle(ctx->restore),
+ ctx->restore,
0,
nvhost_opcode_gather(ctx->restore_size),
ctx->restore_phys);
@@ -188,7 +188,7 @@ void submit_gathers(struct nvhost_job *job)
u32 op2 = job->gathers[i].mem;
nvhost_cdma_push_gather(&job->ch->cdma,
job->nvmap,
- nvmap_id_to_handle(job->gathers[i].mem_id),
+ job->gathers[i].ref,
job->gathers[i].offset,
op1, op2);
}
@@ -242,22 +242,6 @@ int host1x_channel_submit(struct nvhost_job *job)
goto error;
}
- /* remove stale waits */
- if (job->num_waitchk) {
- err = nvhost_syncpt_wait_check(sp,
- job->nvmap,
- job->waitchk_mask,
- job->waitchk,
- job->num_waitchk);
- if (err) {
- dev_warn(&ch->dev->dev,
- "nvhost_syncpt_wait_check failed: %d\n", err);
- mutex_unlock(&ch->submitlock);
- nvhost_module_idle(ch->dev);
- goto error;
- }
- }
-
/* begin a CDMA submit */
err = nvhost_cdma_begin(&ch->cdma, job);
if (err) {
diff --git a/drivers/video/tegra/host/host1x/host1x_debug.c b/drivers/video/tegra/host/host1x/host1x_debug.c
index 76483d82528b..7de342298c4d 100644
--- a/drivers/video/tegra/host/host1x/host1x_debug.c
+++ b/drivers/video/tegra/host/host1x/host1x_debug.c
@@ -28,8 +28,8 @@
#include "host1x_hardware.h"
#include "nvhost_cdma.h"
#include "nvhost_channel.h"
-#include "../../nvmap/nvmap.h"
#include "host1x_cdma.h"
+#include "nvhost_job.h"
#define NVHOST_DEBUG_MAX_PAGE_OFFSET 102400
@@ -160,6 +160,34 @@ static void show_channel_word(struct output *o, int *state, int *count,
}
}
+static void do_show_channel_gather(struct output *o,
+ phys_addr_t phys_addr,
+ u32 words, struct nvhost_cdma *cdma,
+ phys_addr_t pin_addr, u32 *map_addr)
+{
+ /* Map dmaget cursor to corresponding nvmap_handle */
+ u32 offset;
+ int state, count, i;
+
+ offset = phys_addr - pin_addr;
+ /*
+ * Sometimes we're given different hardware address to the same
+ * page - in these cases the offset will get an invalid number and
+ * we just have to bail out.
+ */
+ if (offset > NVHOST_DEBUG_MAX_PAGE_OFFSET) {
+ nvhost_debug_output(o, "[address mismatch]\n");
+ } else {
+ /* GATHER buffer starts always with commands */
+ state = NVHOST_DBG_STATE_CMD;
+ for (i = 0; i < words; i++)
+ show_channel_word(o, &state, &count,
+ phys_addr + i * 4,
+ *(map_addr + offset/4 + i),
+ cdma);
+ }
+}
+
static void show_channel_gather(struct output *o, u32 addr,
phys_addr_t phys_addr,
u32 words, struct nvhost_cdma *cdma)
@@ -169,81 +197,36 @@ static void show_channel_gather(struct output *o, u32 addr,
struct push_buffer *pb = &cdma->push_buffer;
u32 cur = addr - pb->phys;
struct nvmap_client_handle *nvmap = &pb->nvmap[cur/8];
- struct nvmap_handle_ref ref;
u32 *map_addr, offset;
phys_addr_t pin_addr;
- int state, count, i;
- if (!nvmap->handle || !nvmap->client
- || atomic_read(&nvmap->handle->ref) < 1) {
+ if (!nvmap || !nvmap->handle || !nvmap->client) {
nvhost_debug_output(o, "[already deallocated]\n");
return;
}
- /* Create a fake nvmap_handle_ref - nvmap requires it
- * but accesses only the first field - nvmap_handle */
- ref.handle = nvmap->handle;
-
- map_addr = nvmap_mmap(&ref);
+ map_addr = nvmap_mmap(nvmap->handle);
if (!map_addr) {
nvhost_debug_output(o, "[could not mmap]\n");
return;
}
/* Get base address from nvmap */
- pin_addr = nvmap_pin(nvmap->client, &ref);
+ pin_addr = nvmap_pin(nvmap->client, nvmap->handle);
if (IS_ERR_VALUE(pin_addr)) {
nvhost_debug_output(o, "[couldn't pin]\n");
- nvmap_munmap(&ref, map_addr);
+ nvmap_munmap(nvmap->handle, map_addr);
return;
}
offset = phys_addr - pin_addr;
- /*
- * Sometimes we're given different hardware address to the same
- * page - in these cases the offset will get an invalid number and
- * we just have to bail out.
- */
- if (offset > NVHOST_DEBUG_MAX_PAGE_OFFSET) {
- nvhost_debug_output(o, "[address mismatch]\n");
- } else {
- /* GATHER buffer starts always with commands */
- state = NVHOST_DBG_STATE_CMD;
- for (i = 0; i < words; i++)
- show_channel_word(o, &state, &count,
- phys_addr + i * 4,
- *(map_addr + offset/4 + i),
- cdma);
- }
- nvmap_unpin(nvmap->client, &ref);
- nvmap_munmap(&ref, map_addr);
+ do_show_channel_gather(o, phys_addr, words, cdma,
+ pin_addr, map_addr);
+ nvmap_unpin(nvmap->client, nvmap->handle);
+ nvmap_munmap(nvmap->handle, map_addr);
#endif
}
-static void show_channel_pair(struct output *o, u32 addr,
- u32 w0, u32 w1, struct nvhost_cdma *cdma)
-{
- int state = NVHOST_DBG_STATE_CMD;
- int count;
-
- show_channel_word(o, &state, &count, addr, w0, cdma);
- show_channel_word(o, &state, &count, addr+4, w1, cdma);
-}
-
-/**
- * Retrieve the op pair at a slot offset from a DMA address
- */
-static void cdma_peek(struct nvhost_cdma *cdma,
- u32 dmaget, int slot, u32 *out)
-{
- u32 offset = dmaget - cdma->push_buffer.phys;
- u32 *p = cdma->push_buffer.mapped;
-
- offset = ((offset + slot * 8) & (PUSH_BUFFER_SIZE - 1)) >> 2;
- out[0] = p[offset];
- out[1] = p[offset + 1];
-}
-
u32 previous_oppair(struct nvhost_cdma *cdma, u32 cur)
{
u32 pb = cdma->push_buffer.phys;
@@ -253,6 +236,42 @@ u32 previous_oppair(struct nvhost_cdma *cdma, u32 cur)
return prev;
}
+void show_channel_gathers(struct output *o, struct nvhost_cdma *cdma)
+{
+ struct nvhost_job *job;
+
+ list_for_each_entry(job, &cdma->sync_queue, list) {
+ int i;
+ nvhost_debug_output(o, "\n%p: JOB, syncpt_id=%d, syncpt_val=%d,"
+ " first_get=%08x, timeout=%d, ctx=%p,"
+ " num_slots=%d, num_handles=%d\n",
+ job,
+ job->syncpt_id,
+ job->syncpt_end,
+ job->first_get,
+ job->timeout,
+ job->hwctx,
+ job->num_slots,
+ job->num_unpins);
+
+ for (i = 0; i < job->num_gathers; i++) {
+ struct nvhost_job_gather *g = &job->gathers[i];
+ u32 *mapped = nvmap_mmap(g->ref);
+ if (!mapped) {
+ nvhost_debug_output(o, "[could not mmap]\n");
+ continue;
+ }
+
+ nvhost_debug_output(o, " GATHER at %08x, %d words\n",
+ g->mem, g->words);
+
+ do_show_channel_gather(o, g->mem + g->offset,
+ g->words, cdma, g->mem, mapped);
+ nvmap_munmap(g->ref, mapped);
+ }
+ }
+}
+
static void t20_debug_show_channel_cdma(struct nvhost_master *m,
struct nvhost_channel *ch, struct output *o, int chid)
{
@@ -261,7 +280,6 @@ static void t20_debug_show_channel_cdma(struct nvhost_master *m,
u32 dmaput, dmaget, dmactrl;
u32 cbstat, cbread;
u32 val, base, baseval;
- u32 pbw[2];
dmaput = readl(channel->aperture + HOST1X_CHANNEL_DMAPUT);
dmaget = readl(channel->aperture + HOST1X_CHANNEL_DMAGET);
@@ -310,9 +328,7 @@ static void t20_debug_show_channel_cdma(struct nvhost_master *m,
dmaput, dmaget, dmactrl);
nvhost_debug_output(o, "CBREAD %08x, CBSTAT %08x\n", cbread, cbstat);
- cdma_peek(cdma, dmaget, -1, pbw);
- show_channel_pair(o, previous_oppair(cdma, dmaget),
- pbw[0], pbw[1], &channel->cdma);
+ show_channel_gathers(o, cdma);
nvhost_debug_output(o, "\n");
}
diff --git a/drivers/video/tegra/host/host1x/host1x_syncpt.c b/drivers/video/tegra/host/host1x/host1x_syncpt.c
index b7d6587acc61..4cc8e9e212fa 100644
--- a/drivers/video/tegra/host/host1x/host1x_syncpt.c
+++ b/drivers/video/tegra/host/host1x/host1x_syncpt.c
@@ -103,62 +103,14 @@ static void t20_syncpt_cpu_incr(struct nvhost_syncpt *sp, u32 id)
wmb();
}
-/* check for old WAITs to be removed (avoiding a wrap) */
-static int t20_syncpt_wait_check(struct nvhost_syncpt *sp,
- struct nvmap_client *nvmap,
- u32 waitchk_mask,
- struct nvhost_waitchk *wait,
- int num_waitchk)
+/* remove a wait pointed to by patch_addr */
+static int host1x_syncpt_patch_wait(struct nvhost_syncpt *sp,
+ void *patch_addr)
{
- u32 idx;
- int err = 0;
-
- /* get current syncpt values */
- for (idx = 0; idx < NV_HOST1X_SYNCPT_NB_PTS; idx++) {
- if (BIT(idx) & waitchk_mask)
- nvhost_syncpt_update_min(sp, idx);
- }
-
- BUG_ON(!wait && !num_waitchk);
-
- /* compare syncpt vs wait threshold */
- while (num_waitchk) {
- u32 override;
-
- BUG_ON(wait->syncpt_id >= NV_HOST1X_SYNCPT_NB_PTS);
- trace_nvhost_syncpt_wait_check(wait->mem, wait->offset,
- wait->syncpt_id, wait->thresh);
- if (nvhost_syncpt_is_expired(sp,
- wait->syncpt_id, wait->thresh)) {
- /*
- * NULL an already satisfied WAIT_SYNCPT host method,
- * by patching its args in the command stream. The
- * method data is changed to reference a reserved
- * (never given out or incr) NVSYNCPT_GRAPHICS_HOST
- * syncpt with a matching threshold value of 0, so
- * is guaranteed to be popped by the host HW.
- */
- dev_dbg(&syncpt_to_dev(sp)->dev->dev,
- "drop WAIT id %d (%s) thresh 0x%x, min 0x%x\n",
- wait->syncpt_id,
- syncpt_op().name(sp, wait->syncpt_id),
- wait->thresh,
- nvhost_syncpt_read_min(sp, wait->syncpt_id));
-
- /* patch the wait */
- override = nvhost_class_host_wait_syncpt(
- NVSYNCPT_GRAPHICS_HOST, 0);
- err = nvmap_patch_word(nvmap,
- (struct nvmap_handle *)wait->mem,
- wait->offset, override);
- if (err)
- break;
- }
-
- wait++;
- num_waitchk--;
- }
- return err;
+ u32 override = nvhost_class_host_wait_syncpt(
+ NVSYNCPT_GRAPHICS_HOST, 0);
+ __raw_writel(override, patch_addr);
+ return 0;
}
@@ -241,7 +193,7 @@ int host1x_init_syncpt_support(struct nvhost_master *host,
op->syncpt.read_wait_base = t20_syncpt_read_wait_base;
op->syncpt.update_min = t20_syncpt_update_min;
op->syncpt.cpu_incr = t20_syncpt_cpu_incr;
- op->syncpt.wait_check = t20_syncpt_wait_check;
+ op->syncpt.patch_wait = host1x_syncpt_patch_wait;
op->syncpt.debug = t20_syncpt_debug;
op->syncpt.name = t20_syncpt_name;
op->syncpt.mutex_try_lock = syncpt_mutex_try_lock;
diff --git a/drivers/video/tegra/host/mpe/mpe.c b/drivers/video/tegra/host/mpe/mpe.c
index d8c9da7e9a76..3fe2fcd8bb50 100644
--- a/drivers/video/tegra/host/mpe/mpe.c
+++ b/drivers/video/tegra/host/mpe/mpe.c
@@ -502,7 +502,7 @@ static void ctxmpe_save_push(struct nvhost_hwctx *nctx,
struct host1x_hwctx_handler *h = host1x_hwctx_handler(ctx);
nvhost_cdma_push_gather(cdma,
nvhost_get_host(nctx->channel->dev)->nvmap,
- h->save_buf->handle,
+ h->save_buf,
0,
nvhost_opcode_gather(h->save_size),
h->save_phys);
diff --git a/drivers/video/tegra/host/nvhost_cdma.c b/drivers/video/tegra/host/nvhost_cdma.c
index a72e18f16ac7..c87415bf5ac2 100644
--- a/drivers/video/tegra/host/nvhost_cdma.c
+++ b/drivers/video/tegra/host/nvhost_cdma.c
@@ -53,6 +53,18 @@ static void add_to_sync_queue(struct nvhost_cdma *cdma,
job->num_slots = nr_slots;
nvhost_job_get(job);
list_add_tail(&job->list, &cdma->sync_queue);
+
+ switch (job->priority) {
+ case NVHOST_PRIORITY_HIGH:
+ cdma->high_prio_count++;
+ break;
+ case NVHOST_PRIORITY_MEDIUM:
+ cdma->med_prio_count++;
+ break;
+ case NVHOST_PRIORITY_LOW:
+ cdma->low_prio_count++;
+ break;
+ }
}
/**
@@ -200,6 +212,19 @@ static void update_cdma_locked(struct nvhost_cdma *cdma)
}
list_del(&job->list);
+
+ switch (job->priority) {
+ case NVHOST_PRIORITY_HIGH:
+ cdma->high_prio_count--;
+ break;
+ case NVHOST_PRIORITY_MEDIUM:
+ cdma->med_prio_count--;
+ break;
+ case NVHOST_PRIORITY_LOW:
+ cdma->low_prio_count--;
+ break;
+ }
+
nvhost_job_put(job);
}
@@ -371,15 +396,13 @@ int nvhost_cdma_begin(struct nvhost_cdma *cdma, struct nvhost_job *job)
}
static void trace_write_gather(struct nvhost_cdma *cdma,
- struct nvmap_handle *handle,
+ struct nvmap_handle_ref *ref,
u32 offset, u32 words)
{
- struct nvmap_handle_ref ref;
void *mem = NULL;
if (nvhost_debug_trace_cmdbuf) {
- ref.handle = handle;
- mem = nvmap_mmap(&ref);
+ mem = nvmap_mmap(ref);
if (IS_ERR_OR_NULL(mem))
mem = NULL;
};
@@ -393,12 +416,12 @@ static void trace_write_gather(struct nvhost_cdma *cdma,
for (i = 0; i < words; i += TRACE_MAX_LENGTH) {
trace_nvhost_cdma_push_gather(
cdma_to_channel(cdma)->dev->name,
- (u32)handle,
+ (u32)ref->handle,
min(words - i, TRACE_MAX_LENGTH),
offset + i * sizeof(u32),
mem);
}
- nvmap_munmap(&ref, mem);
+ nvmap_munmap(ref, mem);
}
}
@@ -421,7 +444,7 @@ void nvhost_cdma_push(struct nvhost_cdma *cdma, u32 op1, u32 op2)
*/
void nvhost_cdma_push_gather(struct nvhost_cdma *cdma,
struct nvmap_client *client,
- struct nvmap_handle *handle,
+ struct nvmap_handle_ref *handle,
u32 offset, u32 op1, u32 op2)
{
u32 slots_free = cdma->slots_free;
@@ -468,6 +491,12 @@ void nvhost_cdma_end(struct nvhost_cdma *cdma,
if (job->timeout && was_idle)
cdma_start_timer_locked(cdma, job);
+ trace_nvhost_cdma_end(job->ch->dev->name,
+ job->priority,
+ job->ch->cdma.high_prio_count,
+ job->ch->cdma.med_prio_count,
+ job->ch->cdma.low_prio_count);
+
mutex_unlock(&cdma->lock);
}
@@ -492,6 +521,8 @@ int nvhost_cdma_flush(struct nvhost_cdma *cdma, int timeout)
unsigned int space, err = 0;
unsigned long end_jiffies = jiffies + msecs_to_jiffies(timeout);
+ trace_nvhost_cdma_flush(cdma_to_channel(cdma)->dev->name, timeout);
+
/*
* Wait for at most timeout ms. Recalculate timeout at each iteration
* to better keep within given timeout.
diff --git a/drivers/video/tegra/host/nvhost_cdma.h b/drivers/video/tegra/host/nvhost_cdma.h
index e6f51179150f..2056774a7bc7 100644
--- a/drivers/video/tegra/host/nvhost_cdma.h
+++ b/drivers/video/tegra/host/nvhost_cdma.h
@@ -48,7 +48,7 @@ struct nvhost_job;
struct nvmap_client_handle {
struct nvmap_client *client;
- struct nvmap_handle *handle;
+ struct nvmap_handle_ref *handle;
};
struct push_buffer {
@@ -99,6 +99,9 @@ struct nvhost_cdma {
struct buffer_timeout timeout; /* channel's timeout state/wq */
bool running;
bool torndown;
+ int high_prio_count;
+ int med_prio_count;
+ int low_prio_count;
};
#define cdma_to_channel(cdma) container_of(cdma, struct nvhost_channel, cdma)
@@ -113,7 +116,7 @@ int nvhost_cdma_begin(struct nvhost_cdma *cdma, struct nvhost_job *job);
void nvhost_cdma_push(struct nvhost_cdma *cdma, u32 op1, u32 op2);
void nvhost_cdma_push_gather(struct nvhost_cdma *cdma,
struct nvmap_client *client,
- struct nvmap_handle *handle, u32 offset, u32 op1, u32 op2);
+ struct nvmap_handle_ref *handle, u32 offset, u32 op1, u32 op2);
void nvhost_cdma_end(struct nvhost_cdma *cdma,
struct nvhost_job *job);
void nvhost_cdma_update(struct nvhost_cdma *cdma);
diff --git a/drivers/video/tegra/host/nvhost_channel.c b/drivers/video/tegra/host/nvhost_channel.c
index ef8886fe4652..ad303cf0a22d 100644
--- a/drivers/video/tegra/host/nvhost_channel.c
+++ b/drivers/video/tegra/host/nvhost_channel.c
@@ -51,10 +51,26 @@ int nvhost_channel_init(struct nvhost_channel *ch,
int nvhost_channel_submit(struct nvhost_job *job)
{
- /* Low priority submits wait until sync queue is empty. Ignores result
- * from nvhost_cdma_flush, as we submit either when push buffer is
- * empty or when we reach the timeout. */
- if (job->priority < NVHOST_PRIORITY_MEDIUM)
+ /*
+ * Check if queue has higher priority jobs running. If so, wait until
+ * queue is empty. Ignores result from nvhost_cdma_flush, as we submit
+ * either when push buffer is empty or when we reach the timeout.
+ */
+ int higher_count = 0;
+
+ switch (job->priority) {
+ case NVHOST_PRIORITY_HIGH:
+ higher_count = 0;
+ break;
+ case NVHOST_PRIORITY_MEDIUM:
+ higher_count = job->ch->cdma.high_prio_count;
+ break;
+ case NVHOST_PRIORITY_LOW:
+ higher_count = job->ch->cdma.high_prio_count
+ + job->ch->cdma.med_prio_count;
+ break;
+ }
+ if (higher_count > 0)
(void)nvhost_cdma_flush(&job->ch->cdma,
NVHOST_CHANNEL_LOW_PRIO_MAX_WAIT);
diff --git a/drivers/video/tegra/host/nvhost_channel.h b/drivers/video/tegra/host/nvhost_channel.h
index eac51731547b..b3a904d5a3ee 100644
--- a/drivers/video/tegra/host/nvhost_channel.h
+++ b/drivers/video/tegra/host/nvhost_channel.h
@@ -31,18 +31,10 @@
#define NVHOST_MAX_POWERGATE_IDS 2
struct nvhost_master;
-struct nvhost_waitchk;
struct nvhost_device;
struct nvhost_channel;
struct nvhost_hwctx;
-struct nvhost_channel_gather {
- u32 words;
- phys_addr_t mem;
- u32 mem_id;
- int offset;
-};
-
struct nvhost_channel {
int refcount;
int chid;
diff --git a/drivers/video/tegra/host/nvhost_intr.c b/drivers/video/tegra/host/nvhost_intr.c
index ba821f694cb4..af2e3ad1bdb5 100644
--- a/drivers/video/tegra/host/nvhost_intr.c
+++ b/drivers/video/tegra/host/nvhost_intr.c
@@ -128,12 +128,16 @@ static void action_submit_complete(struct nvhost_waitlist *waiter)
struct nvhost_channel *channel = waiter->data;
int nr_completed = waiter->count;
+ nvhost_cdma_update(&channel->cdma);
+ nvhost_module_idle_mult(channel->dev, nr_completed);
+
/* Add nr_completed to trace */
trace_nvhost_channel_submit_complete(channel->dev->name,
- nr_completed, waiter->thresh);
+ nr_completed, waiter->thresh,
+ channel->cdma.high_prio_count,
+ channel->cdma.med_prio_count,
+ channel->cdma.low_prio_count);
- nvhost_cdma_update(&channel->cdma);
- nvhost_module_idle_mult(channel->dev, nr_completed);
}
static void action_ctxsave(struct nvhost_waitlist *waiter)
diff --git a/drivers/video/tegra/host/nvhost_job.c b/drivers/video/tegra/host/nvhost_job.c
index 71f2ab0e751f..e029449b6184 100644
--- a/drivers/video/tegra/host/nvhost_job.c
+++ b/drivers/video/tegra/host/nvhost_job.c
@@ -23,9 +23,11 @@
#include <linux/err.h>
#include <linux/vmalloc.h>
#include <linux/nvmap.h>
+#include <trace/events/nvhost.h>
#include "nvhost_channel.h"
#include "nvhost_job.h"
#include "nvhost_hwctx.h"
+#include "nvhost_syncpt.h"
#include "dev.h"
/* Magic to use to fill freed handle slots */
@@ -33,128 +35,44 @@
static int job_size(struct nvhost_submit_hdr_ext *hdr)
{
- int num_pins = hdr ? (hdr->num_relocs + hdr->num_cmdbufs)*2 : 0;
+ int num_relocs = hdr ? hdr->num_relocs : 0;
int num_waitchks = hdr ? hdr->num_waitchks : 0;
+ int num_cmdbufs = hdr ? hdr->num_cmdbufs : 0;
+ int num_unpins = num_cmdbufs + num_relocs;
return sizeof(struct nvhost_job)
- + num_pins * sizeof(struct nvmap_pinarray_elem)
- + num_pins * sizeof(struct nvmap_handle *)
- + num_waitchks * sizeof(struct nvhost_waitchk);
-}
-
-static int gather_size(int num_cmdbufs)
-{
- return num_cmdbufs * sizeof(struct nvhost_channel_gather);
-}
-
-static void free_gathers(struct nvhost_job *job)
-{
- if (job->gathers) {
- nvmap_munmap(job->gather_mem, job->gathers);
- job->gathers = NULL;
- }
- if (job->gather_mem) {
- nvmap_free(job->nvmap, job->gather_mem);
- job->gather_mem = NULL;
- }
-}
-
-static int alloc_gathers(struct nvhost_job *job,
- int num_cmdbufs)
-{
- int err = 0;
-
- job->gather_mem = NULL;
- job->gathers = NULL;
- job->gather_mem_size = 0;
-
- if (num_cmdbufs) {
- /* Allocate memory */
- job->gather_mem = nvmap_alloc(job->nvmap,
- gather_size(num_cmdbufs),
- 32, NVMAP_HANDLE_CACHEABLE, 0);
- if (IS_ERR_OR_NULL(job->gather_mem)) {
- err = job->gather_mem ? PTR_ERR(job->gather_mem) : -ENOMEM;
- job->gather_mem = NULL;
- goto error;
- }
- job->gather_mem_size = gather_size(num_cmdbufs);
-
- /* Map memory to kernel */
- job->gathers = nvmap_mmap(job->gather_mem);
- if (IS_ERR_OR_NULL(job->gathers)) {
- err = job->gathers ? PTR_ERR(job->gathers) : -ENOMEM;
- job->gathers = NULL;
- goto error;
- }
- }
-
- return 0;
-
-error:
- free_gathers(job);
- return err;
-}
-
-static int realloc_gathers(struct nvhost_job *oldjob,
- struct nvhost_job *newjob,
- int num_cmdbufs)
-{
- int err = 0;
-
- /* Check if we can reuse gather buffer */
- if (oldjob->gather_mem_size < gather_size(num_cmdbufs)
- || oldjob->nvmap != newjob->nvmap) {
- free_gathers(oldjob);
- err = alloc_gathers(newjob, num_cmdbufs);
- } else {
- newjob->gather_mem = oldjob->gather_mem;
- newjob->gathers = oldjob->gathers;
- newjob->gather_mem_size = oldjob->gather_mem_size;
-
- oldjob->gather_mem = NULL;
- oldjob->gathers = NULL;
- oldjob->gather_mem_size = 0;
- }
- return err;
+ + num_relocs * sizeof(struct nvhost_reloc)
+ + num_relocs * sizeof(struct nvhost_reloc_shift)
+ + num_unpins * sizeof(struct nvmap_handle_ref *)
+ + num_waitchks * sizeof(struct nvhost_waitchk)
+ + num_cmdbufs * sizeof(struct nvhost_job_gather);
}
static void init_fields(struct nvhost_job *job,
struct nvhost_submit_hdr_ext *hdr,
int priority, int clientid)
{
- int num_pins = hdr ? (hdr->num_relocs + hdr->num_cmdbufs)*2 : 0;
+ int num_relocs = hdr ? hdr->num_relocs : 0;
int num_waitchks = hdr ? hdr->num_waitchks : 0;
+ int num_cmdbufs = hdr ? hdr->num_cmdbufs : 0;
+ int num_unpins = num_cmdbufs + num_relocs;
void *mem = job;
/* First init state to zero */
- job->num_gathers = 0;
- job->num_pins = 0;
- job->num_unpins = 0;
- job->num_waitchk = 0;
- job->waitchk_mask = 0;
- job->syncpt_id = 0;
- job->syncpt_incrs = 0;
- job->syncpt_end = 0;
job->priority = priority;
job->clientid = clientid;
- job->null_kickoff = false;
- job->first_get = 0;
- job->num_slots = 0;
/* Redistribute memory to the structs */
mem += sizeof(struct nvhost_job);
- if (num_pins) {
- job->pinarray = mem;
- mem += num_pins * sizeof(struct nvmap_pinarray_elem);
- job->unpins = mem;
- mem += num_pins * sizeof(struct nvmap_handle *);
- } else {
- job->pinarray = NULL;
- job->unpins = NULL;
- }
-
+ job->relocarray = num_relocs ? mem : NULL;
+ mem += num_relocs * sizeof(struct nvhost_reloc);
+ job->relocshiftarray = num_relocs ? mem : NULL;
+ mem += num_relocs * sizeof(struct nvhost_reloc_shift);
+ job->unpins = num_unpins ? mem : NULL;
+ mem += num_unpins * sizeof(struct nvmap_handle_ref *);
job->waitchk = num_waitchks ? mem : NULL;
+ mem += num_waitchks * sizeof(struct nvhost_waitchk);
+ job->gathers = num_cmdbufs ? mem : NULL;
/* Copy information from header */
if (hdr) {
@@ -172,8 +90,6 @@ struct nvhost_job *nvhost_job_alloc(struct nvhost_channel *ch,
int clientid)
{
struct nvhost_job *job = NULL;
- int num_cmdbufs = hdr ? hdr->num_cmdbufs : 0;
- int err = 0;
job = vzalloc(job_size(hdr));
if (!job)
@@ -186,10 +102,6 @@ struct nvhost_job *nvhost_job_alloc(struct nvhost_channel *ch,
hwctx->h->get(hwctx);
job->nvmap = nvmap ? nvmap_client_get(nvmap) : NULL;
- err = alloc_gathers(job, num_cmdbufs);
- if (err)
- goto error;
-
init_fields(job, hdr, priority, clientid);
return job;
@@ -200,46 +112,6 @@ error:
return NULL;
}
-struct nvhost_job *nvhost_job_realloc(
- struct nvhost_job *oldjob,
- struct nvhost_hwctx *hwctx,
- struct nvhost_submit_hdr_ext *hdr,
- struct nvmap_client *nvmap,
- int priority, int clientid)
-{
- struct nvhost_job *newjob = NULL;
- int num_cmdbufs = hdr ? hdr->num_cmdbufs : 0;
- int err = 0;
-
- newjob = vzalloc(job_size(hdr));
- if (!newjob)
- goto error;
- kref_init(&newjob->ref);
- newjob->ch = oldjob->ch;
- newjob->hwctx = hwctx;
- if (hwctx)
- newjob->hwctx->h->get(newjob->hwctx);
- newjob->timeout = oldjob->timeout;
- newjob->nvmap = nvmap ? nvmap_client_get(nvmap) : NULL;
-
- err = realloc_gathers(oldjob, newjob, num_cmdbufs);
- if (err)
- goto error;
-
- nvhost_job_put(oldjob);
-
- init_fields(newjob, hdr, priority, clientid);
-
- return newjob;
-
-error:
- if (newjob)
- nvhost_job_put(newjob);
- if (oldjob)
- nvhost_job_put(oldjob);
- return NULL;
-}
-
void nvhost_job_get(struct nvhost_job *job)
{
kref_get(&job->ref);
@@ -253,10 +125,6 @@ static void job_free(struct kref *ref)
job->hwctxref->h->put(job->hwctxref);
if (job->hwctx)
job->hwctx->h->put(job->hwctx);
- if (job->gathers)
- nvmap_munmap(job->gather_mem, job->gathers);
- if (job->gather_mem)
- nvmap_free(job->nvmap, job->gather_mem);
if (job->nvmap)
nvmap_client_put(job->nvmap);
vfree(job);
@@ -280,42 +148,177 @@ void nvhost_job_put(struct nvhost_job *job)
void nvhost_job_add_gather(struct nvhost_job *job,
u32 mem_id, u32 words, u32 offset)
{
- struct nvmap_pinarray_elem *pin;
- struct nvhost_channel_gather *cur_gather =
+ struct nvhost_job_gather *cur_gather =
&job->gathers[job->num_gathers];
- pin = &job->pinarray[job->num_pins++];
- pin->patch_mem = (u32)nvmap_ref_to_handle(job->gather_mem);
- pin->patch_offset = (void *)&(cur_gather->mem) - (void *)job->gathers;
- pin->pin_mem = nvmap_convert_handle_u2k(mem_id);
- pin->pin_offset = offset;
cur_gather->words = words;
cur_gather->mem_id = mem_id;
cur_gather->offset = offset;
job->num_gathers += 1;
}
-int nvhost_job_pin(struct nvhost_job *job)
+static int do_relocs(struct nvhost_job *job, u32 cmdbuf_mem, void *cmdbuf_addr)
{
- int err = 0;
+ phys_addr_t target_phys;
+ int i;
+ u32 mem_id = 0;
+ struct nvmap_handle_ref *target_ref = NULL;
+
+ /* pin & patch the relocs for one gather */
+ for (i = 0; i < job->num_relocs; i++) {
+ struct nvhost_reloc *reloc = &job->relocarray[i];
+ struct nvhost_reloc_shift *shift = &job->relocshiftarray[i];
+
+ /* skip all other gathers */
+ if (cmdbuf_mem != reloc->cmdbuf_mem)
+ continue;
+
+ /* check if pin-mem is same as previous */
+ if (reloc->target != mem_id) {
+ target_ref = nvmap_duplicate_handle_id(job->nvmap,
+ reloc->target);
+ if (IS_ERR(target_ref))
+ return PTR_ERR(target_ref);
+
+ target_phys = nvmap_pin(job->nvmap, target_ref);
+ if (IS_ERR((void *)target_phys)) {
+ nvmap_free(job->nvmap, target_ref);
+ return target_phys;
+ }
+
+ mem_id = reloc->target;
+ job->unpins[job->num_unpins++] = target_ref;
+ }
- /* pin mem handles and patch physical addresses */
- job->num_unpins = nvmap_pin_array(job->nvmap,
- nvmap_ref_to_handle(job->gather_mem),
- job->pinarray, job->num_pins,
- job->unpins);
- if (job->num_unpins < 0)
- err = job->num_unpins;
+ __raw_writel(
+ (target_phys + reloc->target_offset) >> shift->shift,
+ (cmdbuf_addr + reloc->cmdbuf_offset));
+
+ /* Different gathers might have same mem_id. This ensures we
+ * perform reloc only once per gather memid. */
+ reloc->cmdbuf_mem = 0;
+ }
+
+ return 0;
+}
+
+/*
+ * Check driver supplied waitchk structs for syncpt thresholds
+ * that have already been satisfied and NULL the comparison (to
+ * avoid a wrap condition in the HW).
+ */
+static int do_waitchks(struct nvhost_job *job, struct nvhost_syncpt *sp,
+ u32 patch_mem, void *patch_addr)
+{
+ int i;
+
+ /* compare syncpt vs wait threshold */
+ for (i = 0; i < job->num_waitchk; i++) {
+ struct nvhost_waitchk *wait = &job->waitchk[i];
+
+ /* skip all other gathers */
+ if (patch_mem != wait->mem)
+ continue;
+
+ trace_nvhost_syncpt_wait_check(wait->mem, wait->offset,
+ wait->syncpt_id, wait->thresh,
+ nvhost_syncpt_read(sp, wait->syncpt_id));
+ if (nvhost_syncpt_is_expired(sp,
+ wait->syncpt_id, wait->thresh)) {
+ /*
+ * NULL an already satisfied WAIT_SYNCPT host method,
+ * by patching its args in the command stream. The
+ * method data is changed to reference a reserved
+ * (never given out or incr) NVSYNCPT_GRAPHICS_HOST
+ * syncpt with a matching threshold value of 0, so
+ * is guaranteed to be popped by the host HW.
+ */
+ dev_dbg(&syncpt_to_dev(sp)->dev->dev,
+ "drop WAIT id %d (%s) thresh 0x%x, min 0x%x\n",
+ wait->syncpt_id,
+ syncpt_op().name(sp, wait->syncpt_id),
+ wait->thresh,
+ nvhost_syncpt_read_min(sp, wait->syncpt_id));
+
+ /* patch the wait */
+ nvhost_syncpt_patch_wait(sp,
+ (patch_addr + wait->offset));
+ }
+
+ wait->mem = 0;
+ }
+ return 0;
+}
+
+int nvhost_job_pin(struct nvhost_job *job, struct nvhost_syncpt *sp)
+{
+ int err = 0, i = 0;
+ phys_addr_t gather_phys = 0;
+ void *gather_addr = NULL;
+ unsigned long waitchk_mask = job->waitchk_mask;
+
+ /* get current syncpt values for waitchk */
+ for_each_set_bit(i, &waitchk_mask, sizeof(job->waitchk_mask))
+ nvhost_syncpt_update_min(sp, i);
+
+ /* pin gathers */
+ for (i = 0; i < job->num_gathers; i++) {
+ struct nvhost_job_gather *g = &job->gathers[i];
+
+ /* process each gather mem only once */
+ if (!g->ref) {
+ g->ref = nvmap_duplicate_handle_id(job->nvmap,
+ job->gathers[i].mem_id);
+ if (IS_ERR(g->ref)) {
+ err = PTR_ERR(g->ref);
+ g->ref = NULL;
+ break;
+ }
+
+ gather_phys = nvmap_pin(job->nvmap, g->ref);
+ if (IS_ERR((void *)gather_phys)) {
+ nvmap_free(job->nvmap, g->ref);
+ err = gather_phys;
+ break;
+ }
+
+ /* store the gather ref into unpin array */
+ job->unpins[job->num_unpins++] = g->ref;
+
+ gather_addr = nvmap_mmap(g->ref);
+ if (!gather_addr) {
+ err = -ENOMEM;
+ break;
+ }
+
+ err = do_relocs(job, g->mem_id, gather_addr);
+ if (!err)
+ err = do_waitchks(job, sp,
+ g->mem_id, gather_addr);
+ nvmap_munmap(g->ref, gather_addr);
+
+ if (err)
+ break;
+ }
+ g->mem = gather_phys + g->offset;
+ }
+ wmb();
return err;
}
void nvhost_job_unpin(struct nvhost_job *job)
{
- nvmap_unpin_handles(job->nvmap, job->unpins,
- job->num_unpins);
+ int i;
+
+ for (i = 0; i < job->num_unpins; i++) {
+ nvmap_unpin(job->nvmap, job->unpins[i]);
+ nvmap_free(job->nvmap, job->unpins[i]);
+ }
+
memset(job->unpins, BAD_MAGIC,
- job->num_unpins * sizeof(struct nvmap_handle *));
+ job->num_unpins * sizeof(struct nvmap_handle_ref *));
+ job->num_unpins = 0;
}
/**
diff --git a/drivers/video/tegra/host/nvhost_job.h b/drivers/video/tegra/host/nvhost_job.h
index ad9d1af60da1..ec1366337279 100644
--- a/drivers/video/tegra/host/nvhost_job.h
+++ b/drivers/video/tegra/host/nvhost_job.h
@@ -27,7 +27,15 @@ struct nvhost_channel;
struct nvhost_hwctx;
struct nvmap_client;
struct nvhost_waitchk;
-struct nvmap_handle;
+struct nvhost_syncpt;
+
+struct nvhost_job_gather {
+ u32 words;
+ phys_addr_t mem;
+ u32 mem_id;
+ int offset;
+ struct nvmap_handle_ref *ref;
+};
/*
* Each submit is tracked as a nvhost_job.
@@ -50,10 +58,8 @@ struct nvhost_job {
struct nvmap_client *nvmap;
/* Gathers and their memory */
- struct nvmap_handle_ref *gather_mem;
- struct nvhost_channel_gather *gathers;
+ struct nvhost_job_gather *gathers;
int num_gathers;
- int gather_mem_size;
/* Wait checks to be processed at submit time */
struct nvhost_waitchk *waitchk;
@@ -61,9 +67,10 @@ struct nvhost_job {
u32 waitchk_mask;
/* Array of handles to be pinned & unpinned */
- struct nvmap_pinarray_elem *pinarray;
- int num_pins;
- struct nvmap_handle **unpins;
+ struct nvhost_reloc *relocarray;
+ struct nvhost_reloc_shift *relocshiftarray;
+ int num_relocs;
+ struct nvmap_handle_ref **unpins;
int num_unpins;
/* Sync point id, number of increments and end related to the submit */
@@ -99,17 +106,6 @@ struct nvhost_job *nvhost_job_alloc(struct nvhost_channel *ch,
int priority, int clientid);
/*
- * Allocate memory for a job. Just enough memory will be allocated to
- * accomodate the submit announced in submit header. Gather memory from
- * oldjob will be reused, and nvhost_job_put() will be called to it.
- */
-struct nvhost_job *nvhost_job_realloc(struct nvhost_job *oldjob,
- struct nvhost_hwctx *hwctx,
- struct nvhost_submit_hdr_ext *hdr,
- struct nvmap_client *nvmap,
- int priority, int clientid);
-
-/*
* Add a gather to a job.
*/
void nvhost_job_add_gather(struct nvhost_job *job,
@@ -134,8 +130,11 @@ void nvhost_job_put(struct nvhost_job *job);
* Pin memory related to job. This handles relocation of addresses to the
* host1x address space. Handles both the gather memory and any other memory
* referred to from the gather buffers.
+ *
+ * Handles also patching out host waits that would wait for an expired sync
+ * point value.
*/
-int nvhost_job_pin(struct nvhost_job *job);
+int nvhost_job_pin(struct nvhost_job *job, struct nvhost_syncpt *sp);
/*
* Unpin memory related to job.
diff --git a/drivers/video/tegra/host/nvhost_syncpt.c b/drivers/video/tegra/host/nvhost_syncpt.c
index 4835d22881b8..7550512b0214 100644
--- a/drivers/video/tegra/host/nvhost_syncpt.c
+++ b/drivers/video/tegra/host/nvhost_syncpt.c
@@ -74,7 +74,7 @@ u32 nvhost_syncpt_update_min(struct nvhost_syncpt *sp, u32 id)
BUG_ON(!syncpt_op().update_min);
- return syncpt_op().update_min(sp, id);
+ val = syncpt_op().update_min(sp, id);
trace_nvhost_syncpt_update_min(id, val);
return val;
@@ -130,6 +130,19 @@ void nvhost_syncpt_incr(struct nvhost_syncpt *sp, u32 id)
}
/**
+ * Updated sync point form hardware, and returns true if syncpoint is expired,
+ * false if we may need to wait
+ */
+static bool syncpt_update_min_is_expired(
+ struct nvhost_syncpt *sp,
+ u32 id,
+ u32 thresh)
+{
+ syncpt_op().update_min(sp, id);
+ return nvhost_syncpt_is_expired(sp, id, thresh);
+}
+
+/**
* Main entrypoint for syncpoint value waits.
*/
int nvhost_syncpt_wait_timeout(struct nvhost_syncpt *sp, u32 id,
@@ -190,9 +203,9 @@ int nvhost_syncpt_wait_timeout(struct nvhost_syncpt *sp, u32 id,
while (timeout) {
u32 check = min_t(u32, SYNCPT_CHECK_PERIOD, timeout);
int remain = wait_event_interruptible_timeout(wq,
- nvhost_syncpt_is_expired(sp, id, thresh),
+ syncpt_update_min_is_expired(sp, id, thresh),
check);
- if (remain > 0) {
+ if (remain > 0 || nvhost_syncpt_is_expired(sp, id, thresh)) {
if (value)
*value = nvhost_syncpt_read_min(sp, id);
err = 0;
@@ -317,15 +330,10 @@ void nvhost_mutex_unlock(struct nvhost_syncpt *sp, int idx)
atomic_dec(&sp->lock_counts[idx]);
}
-/* check for old WAITs to be removed (avoiding a wrap) */
-int nvhost_syncpt_wait_check(struct nvhost_syncpt *sp,
- struct nvmap_client *nvmap,
- u32 waitchk_mask,
- struct nvhost_waitchk *wait,
- int num_waitchk)
+/* remove a wait pointed to by patch_addr */
+int nvhost_syncpt_patch_wait(struct nvhost_syncpt *sp, void *patch_addr)
{
- return syncpt_op().wait_check(sp, nvmap,
- waitchk_mask, wait, num_waitchk);
+ return syncpt_op().patch_wait(sp, patch_addr);
}
/* Displays the current value of the sync point via sysfs */
diff --git a/drivers/video/tegra/host/nvhost_syncpt.h b/drivers/video/tegra/host/nvhost_syncpt.h
index b770ed91c76c..b58921bffa9c 100644
--- a/drivers/video/tegra/host/nvhost_syncpt.h
+++ b/drivers/video/tegra/host/nvhost_syncpt.h
@@ -136,23 +136,7 @@ static inline int nvhost_syncpt_wait(struct nvhost_syncpt *sp, u32 id, u32 thres
MAX_SCHEDULE_TIMEOUT, NULL);
}
-/*
- * Check driver supplied waitchk structs for syncpt thresholds
- * that have already been satisfied and NULL the comparison (to
- * avoid a wrap condition in the HW).
- *
- * @param: sp - global shadowed syncpt struct
- * @param: nvmap - needed to access command buffer
- * @param: mask - bit mask of syncpt IDs referenced in WAITs
- * @param: wait - start of filled in array of waitchk structs
- * @param: waitend - end ptr (one beyond last valid waitchk)
- */
-struct nvhost_waitchk;
-int nvhost_syncpt_wait_check(struct nvhost_syncpt *sp,
- struct nvmap_client *nvmap,
- u32 mask,
- struct nvhost_waitchk *wait,
- int num_waitchk);
+int nvhost_syncpt_patch_wait(struct nvhost_syncpt *sp, void *patch_addr);
void nvhost_syncpt_debug(struct nvhost_syncpt *sp);
diff --git a/drivers/video/tegra/host/t30/t30.c b/drivers/video/tegra/host/t30/t30.c
index 257ba0849277..b2768741546a 100644
--- a/drivers/video/tegra/host/t30/t30.c
+++ b/drivers/video/tegra/host/t30/t30.c
@@ -95,7 +95,7 @@ struct nvhost_device t30_devices[] = {
.waitbases = BIT(NVWAITBASE_2D_0) | BIT(NVWAITBASE_2D_1),
.modulemutexes = BIT(NVMODMUTEX_2D_FULL) | BIT(NVMODMUTEX_2D_SIMPLE) |
BIT(NVMODMUTEX_2D_SB_A) | BIT(NVMODMUTEX_2D_SB_B),
- .clocks = { {"gr2d", UINT_MAX},
+ .clocks = { {"gr2d", 0},
{"epp", 0},
{"emc", 300000000} },
NVHOST_MODULE_NO_POWERGATE_IDS,
diff --git a/drivers/video/tegra/nvmap/nvmap.c b/drivers/video/tegra/nvmap/nvmap.c
index a0c4156668e5..b7fd695d04ee 100644
--- a/drivers/video/tegra/nvmap/nvmap.c
+++ b/drivers/video/tegra/nvmap/nvmap.c
@@ -352,225 +352,6 @@ static phys_addr_t handle_phys(struct nvmap_handle *h)
return addr;
}
-/* stores the physical address (+offset) of each handle relocation entry
- * into its output location. see nvmap_pin_array for more details.
- *
- * each entry in arr (i.e., each relocation request) specifies two handles:
- * the handle to pin (pin), and the handle where the address of pin should be
- * written (patch). in pseudocode, this loop basically looks like:
- *
- * for (i = 0; i < nr; i++) {
- * (pin, pin_offset, patch, patch_offset) = arr[i];
- * patch[patch_offset] = address_of(pin) + pin_offset;
- * }
- */
-static int nvmap_reloc_pin_array(struct nvmap_client *client,
- const struct nvmap_pinarray_elem *arr,
- int nr, struct nvmap_handle *gather)
-{
- struct nvmap_handle *last_patch = NULL;
- unsigned int last_pfn = 0;
- pte_t **pte;
- void *addr;
- int i;
-
- pte = nvmap_alloc_pte(client->dev, &addr);
- if (IS_ERR(pte))
- return PTR_ERR(pte);
-
- for (i = 0; i < nr; i++) {
- struct nvmap_handle *patch;
- struct nvmap_handle *pin;
- phys_addr_t reloc_addr;
- phys_addr_t phys;
- unsigned int pfn;
-
- /* all of the handles are validated and get'ted prior to
- * calling this function, so casting is safe here */
- pin = (struct nvmap_handle *)arr[i].pin_mem;
-
- if (arr[i].patch_mem == (unsigned long)last_patch) {
- patch = last_patch;
- } else if (arr[i].patch_mem == (unsigned long)gather) {
- patch = gather;
- } else {
- if (last_patch)
- nvmap_handle_put(last_patch);
-
- patch = nvmap_get_handle_id(client, arr[i].patch_mem);
- if (!patch) {
- nvmap_free_pte(client->dev, pte);
- return -EPERM;
- }
- last_patch = patch;
- }
-
- if (patch->heap_pgalloc) {
- unsigned int page = arr[i].patch_offset >> PAGE_SHIFT;
- phys = page_to_phys(patch->pgalloc.pages[page]);
- phys += (arr[i].patch_offset & ~PAGE_MASK);
- } else {
- phys = patch->carveout->base + arr[i].patch_offset;
- }
-
- pfn = __phys_to_pfn(phys);
- if (pfn != last_pfn) {
- pgprot_t prot = nvmap_pgprot(patch, pgprot_kernel);
- phys_addr_t kaddr = (phys_addr_t)addr;
- set_pte_at(&init_mm, kaddr, *pte, pfn_pte(pfn, prot));
- flush_tlb_kernel_page(kaddr);
- last_pfn = pfn;
- }
-
- reloc_addr = handle_phys(pin) + arr[i].pin_offset;
- reloc_addr >>= arr[i].reloc_shift;
- __raw_writel(reloc_addr, addr + (phys & ~PAGE_MASK));
- }
-
- nvmap_free_pte(client->dev, pte);
-
- if (last_patch)
- nvmap_handle_put(last_patch);
-
- wmb();
-
- return 0;
-}
-
-static int nvmap_validate_get_pin_array(struct nvmap_client *client,
- const struct nvmap_pinarray_elem *arr,
- int nr, struct nvmap_handle **h)
-{
- int i;
- int ret = 0;
- int count = 0;
-
- nvmap_ref_lock(client);
-
- for (i = 0; i < nr; i++) {
- struct nvmap_handle_ref *ref;
-
- if (need_resched()) {
- nvmap_ref_unlock(client);
- schedule();
- nvmap_ref_lock(client);
- }
-
- ref = _nvmap_validate_id_locked(client, arr[i].pin_mem);
-
- if (!ref)
- nvmap_warn(client, "falied to validate id\n");
- else if (!ref->handle)
- nvmap_warn(client, "id had no associated handle\n");
- else if (!ref->handle->alloc)
- nvmap_warn(client, "handle had no allocation\n");
-
- if (!ref || !ref->handle || !ref->handle->alloc) {
- ret = -EPERM;
- break;
- }
-
- /* a handle may be referenced multiple times in arr, but
- * it will only be pinned once; this ensures that the
- * minimum number of sync-queue slots in the host driver
- * are dedicated to storing unpin lists, which allows
- * for greater parallelism between the CPU and graphics
- * processor */
- if (ref->handle->flags & NVMAP_HANDLE_VISITED)
- continue;
-
- ref->handle->flags |= NVMAP_HANDLE_VISITED;
-
- h[count] = nvmap_handle_get(ref->handle);
- BUG_ON(!h[count]);
- count++;
- }
-
- nvmap_ref_unlock(client);
-
- if (ret) {
- for (i = 0; i < count; i++) {
- h[i]->flags &= ~NVMAP_HANDLE_VISITED;
- nvmap_handle_put(h[i]);
- }
- }
-
- return ret ?: count;
-}
-
-/* a typical mechanism host1x clients use for using the Tegra graphics
- * processor is to build a command buffer which contains relocatable
- * memory handle commands, and rely on the kernel to convert these in-place
- * to addresses which are understood by the GPU hardware.
- *
- * this is implemented by having clients provide a sideband array
- * of relocatable handles (+ offsets) and the location in the command
- * buffer handle to patch with the GPU address when the client submits
- * its command buffer to the host1x driver.
- *
- * the host driver also uses this relocation mechanism internally to
- * relocate the client's (unpinned) command buffers into host-addressable
- * memory.
- *
- * @client: nvmap_client which should be used for validation; should be
- * owned by the process which is submitting command buffers
- * @gather: special handle for relocated command buffer outputs used
- * internally by the host driver. if this handle is encountered
- * as an output handle in the relocation array, it is assumed
- * to be a known-good output and is not validated.
- * @arr: array of ((relocatable handle, offset), (output handle, offset))
- * tuples.
- * @nr: number of entries in arr
- * @unique_arr: list of nvmap_handle objects which were pinned by
- * nvmap_pin_array. must be unpinned by the caller after the
- * command buffers referenced in gather have completed.
- */
-int nvmap_pin_array(struct nvmap_client *client, struct nvmap_handle *gather,
- const struct nvmap_pinarray_elem *arr, int nr,
- struct nvmap_handle **unique_arr)
-{
- int count = 0;
- int ret = 0;
- int i;
-
- if (mutex_lock_interruptible(&client->share->pin_lock)) {
- nvmap_warn(client, "%s interrupted when acquiring pin lock\n",
- current->group_leader->comm);
- return -EINTR;
- }
-
- count = nvmap_validate_get_pin_array(client, arr, nr, unique_arr);
- if (count < 0) {
- mutex_unlock(&client->share->pin_lock);
- nvmap_warn(client, "failed to validate pin array\n");
- return count;
- }
-
- for (i = 0; i < count; i++)
- unique_arr[i]->flags &= ~NVMAP_HANDLE_VISITED;
-
- ret = wait_pin_array_locked(client, unique_arr, count);
-
- mutex_unlock(&client->share->pin_lock);
-
- if (!ret)
- ret = nvmap_reloc_pin_array(client, arr, nr, gather);
-
- if (WARN_ON(ret)) {
- for (i = 0; i < count; i++)
- nvmap_handle_put(unique_arr[i]);
- return ret;
- } else {
- for (i = 0; i < count; i++) {
- if (unique_arr[i]->heap_pgalloc &&
- unique_arr[i]->pgalloc.dirty)
- map_iovmm_area(unique_arr[i]);
- }
- }
-
- return count;
-}
-
phys_addr_t nvmap_pin(struct nvmap_client *client,
struct nvmap_handle_ref *ref)
{
@@ -820,52 +601,3 @@ void nvmap_free(struct nvmap_client *client, struct nvmap_handle_ref *r)
nvmap_free_handle_id(client, nvmap_ref_to_id(r));
}
-
-/*
- * create a mapping to the user's buffer and write it
- * (uses similar logic from nvmap_reloc_pin_array to map the cmdbuf)
- */
-int nvmap_patch_word(struct nvmap_client *client,
- struct nvmap_handle *patch,
- u32 patch_offset, u32 patch_value)
-{
- phys_addr_t phys;
- unsigned long kaddr;
- unsigned int pfn;
- void *addr;
- pte_t **pte;
- pgprot_t prot;
-
- if (patch_offset >= patch->size) {
- nvmap_warn(client, "read/write outside of handle\n");
- return -EFAULT;
- }
-
- pte = nvmap_alloc_pte(client->dev, &addr);
- if (IS_ERR(pte))
- return PTR_ERR(pte);
-
- /* derive physaddr of cmdbuf WAIT to patch */
- if (patch->heap_pgalloc) {
- unsigned int page = patch_offset >> PAGE_SHIFT;
- phys = page_to_phys(patch->pgalloc.pages[page]);
- phys += (patch_offset & ~PAGE_MASK);
- } else {
- phys = patch->carveout->base + patch_offset;
- }
-
- pfn = __phys_to_pfn(phys);
- prot = nvmap_pgprot(patch, pgprot_kernel);
- kaddr = (unsigned long)addr;
-
- /* write PTE, so addr points to cmdbuf PFN */
- set_pte_at(&init_mm, kaddr, *pte, pfn_pte(pfn, prot));
- flush_tlb_kernel_page(kaddr);
-
- /* write patch_value to addr + page offset */
- __raw_writel(patch_value, addr + (phys & ~PAGE_MASK));
-
- nvmap_free_pte(client->dev, pte);
- wmb();
- return 0;
-}
diff --git a/drivers/video/tegra/nvmap/nvmap.h b/drivers/video/tegra/nvmap/nvmap.h
index b0fb70f64a5c..25403f5e7098 100644
--- a/drivers/video/tegra/nvmap/nvmap.h
+++ b/drivers/video/tegra/nvmap/nvmap.h
@@ -37,6 +37,8 @@ struct nvmap_device;
struct page;
struct tegra_iovmm_area;
+void _nvmap_handle_free(struct nvmap_handle *h);
+
#if defined(CONFIG_TEGRA_NVMAP)
#define nvmap_err(_client, _fmt, ...) \
dev_err(nvmap_client_to_device(_client), \
@@ -162,7 +164,46 @@ static inline void nvmap_ref_unlock(struct nvmap_client *priv)
{
mutex_unlock(&priv->ref_lock);
}
-#endif /* CONFIG_TEGRA_NVMAP */
+
+static inline struct nvmap_handle *nvmap_handle_get(struct nvmap_handle *h)
+{
+ if (unlikely(atomic_inc_return(&h->ref) <= 1)) {
+ pr_err("%s: %s getting a freed handle\n",
+ __func__, current->group_leader->comm);
+ if (atomic_read(&h->ref) <= 0)
+ return NULL;
+ }
+ return h;
+}
+
+static inline void nvmap_handle_put(struct nvmap_handle *h)
+{
+ int cnt = atomic_dec_return(&h->ref);
+
+ if (WARN_ON(cnt < 0)) {
+ pr_err("%s: %s put to negative references\n",
+ __func__, current->comm);
+ } else if (cnt == 0)
+ _nvmap_handle_free(h);
+}
+
+static inline pgprot_t nvmap_pgprot(struct nvmap_handle *h, pgprot_t prot)
+{
+ if (h->flags == NVMAP_HANDLE_UNCACHEABLE)
+ return pgprot_noncached(prot);
+ else if (h->flags == NVMAP_HANDLE_WRITE_COMBINE)
+ return pgprot_writecombine(prot);
+ else if (h->flags == NVMAP_HANDLE_INNER_CACHEABLE)
+ return pgprot_inner_writeback(prot);
+ return prot;
+}
+
+#else /* CONFIG_TEGRA_NVMAP */
+struct nvmap_handle *nvmap_handle_get(struct nvmap_handle *h);
+void nvmap_handle_put(struct nvmap_handle *h);
+pgprot_t nvmap_pgprot(struct nvmap_handle *h, pgprot_t prot);
+
+#endif /* !CONFIG_TEGRA_NVMAP */
struct device *nvmap_client_to_device(struct nvmap_client *client);
@@ -216,51 +257,10 @@ int nvmap_pin_ids(struct nvmap_client *client,
void nvmap_unpin_ids(struct nvmap_client *priv,
unsigned int nr, const unsigned long *ids);
-void _nvmap_handle_free(struct nvmap_handle *h);
-
int nvmap_handle_remove(struct nvmap_device *dev, struct nvmap_handle *h);
void nvmap_handle_add(struct nvmap_device *dev, struct nvmap_handle *h);
-#if defined(CONFIG_TEGRA_NVMAP)
-static inline struct nvmap_handle *nvmap_handle_get(struct nvmap_handle *h)
-{
- if (unlikely(atomic_inc_return(&h->ref) <= 1)) {
- pr_err("%s: %s getting a freed handle\n",
- __func__, current->group_leader->comm);
- if (atomic_read(&h->ref) <= 0)
- return NULL;
- }
- return h;
-}
-
-static inline void nvmap_handle_put(struct nvmap_handle *h)
-{
- int cnt = atomic_dec_return(&h->ref);
-
- if (WARN_ON(cnt < 0)) {
- pr_err("%s: %s put to negative references\n",
- __func__, current->comm);
- } else if (cnt == 0)
- _nvmap_handle_free(h);
-}
-
-static inline pgprot_t nvmap_pgprot(struct nvmap_handle *h, pgprot_t prot)
-{
- if (h->flags == NVMAP_HANDLE_UNCACHEABLE)
- return pgprot_noncached(prot);
- else if (h->flags == NVMAP_HANDLE_WRITE_COMBINE)
- return pgprot_writecombine(prot);
- else if (h->flags == NVMAP_HANDLE_INNER_CACHEABLE)
- return pgprot_inner_writeback(prot);
- return prot;
-}
-#else /* CONFIG_TEGRA_NVMAP */
-struct nvmap_handle *nvmap_handle_get(struct nvmap_handle *h);
-void nvmap_handle_put(struct nvmap_handle *h);
-pgprot_t nvmap_pgprot(struct nvmap_handle *h, pgprot_t prot);
-#endif /* !CONFIG_TEGRA_NVMAP */
-
int is_nvmap_vma(struct vm_area_struct *vma);
struct nvmap_handle_ref *nvmap_alloc_iovm(struct nvmap_client *client,
@@ -268,4 +268,4 @@ struct nvmap_handle_ref *nvmap_alloc_iovm(struct nvmap_client *client,
void nvmap_free_iovm(struct nvmap_client *client, struct nvmap_handle_ref *r);
-#endif
+#endif /* __VIDEO_TEGRA_NVMAP_NVMAP_H */
diff --git a/drivers/video/tegra/nvmap/nvmap_dev.c b/drivers/video/tegra/nvmap/nvmap_dev.c
index c78818711f74..9ecce7eeeb17 100644
--- a/drivers/video/tegra/nvmap/nvmap_dev.c
+++ b/drivers/video/tegra/nvmap/nvmap_dev.c
@@ -973,20 +973,17 @@ static void client_stringify(struct nvmap_client *client, struct seq_file *s)
}
static void allocations_stringify(struct nvmap_client *client,
- struct seq_file *s)
+ struct seq_file *s, bool iovmm)
{
- unsigned long base = 0;
struct rb_node *n = rb_first(&client->handle_refs);
for (; n != NULL; n = rb_next(n)) {
struct nvmap_handle_ref *ref =
rb_entry(n, struct nvmap_handle_ref, node);
struct nvmap_handle *handle = ref->handle;
- if (handle->alloc && !handle->heap_pgalloc) {
- seq_printf(s, "%-18s %-18s %8lx %10u %8x\n", "", "",
- (unsigned long)(handle->carveout->base),
- handle->size, handle->userflags);
- } else if (handle->alloc && handle->heap_pgalloc) {
+ if (handle->alloc && handle->heap_pgalloc == iovmm) {
+ unsigned long base = iovmm ? 0:
+ (unsigned long)(handle->carveout->base);
seq_printf(s, "%-18s %-18s %8lx %10u %8x\n", "", "",
base, handle->size, handle->userflags);
}
@@ -1010,7 +1007,7 @@ static int nvmap_debug_allocations_show(struct seq_file *s, void *unused)
get_client_from_carveout_commit(node, commit);
client_stringify(client, s);
seq_printf(s, " %10u\n", commit->commit);
- allocations_stringify(client, s);
+ allocations_stringify(client, s, false);
seq_printf(s, "\n");
total += commit->commit;
}
@@ -1111,14 +1108,14 @@ static int nvmap_debug_iovmm_allocations_show(struct seq_file *s, void *unused)
struct nvmap_device *dev = s->private;
spin_lock_irqsave(&dev->clients_lock, flags);
- seq_printf(s, "%-18s %18s %8s %10s\n", "CLIENT", "PROCESS", "PID",
- "SIZE");
+ seq_printf(s, "%-18s %18s %8s %10s %8s\n", "CLIENT", "PROCESS", "PID",
+ "SIZE", "FLAGS");
seq_printf(s, "%-18s %18s %8s %10s\n", "", "",
"BASE", "SIZE");
list_for_each_entry(client, &dev->clients, list) {
client_stringify(client, s);
seq_printf(s, " %10u\n", atomic_read(&client->iovm_commit));
- allocations_stringify(client, s);
+ allocations_stringify(client, s, true);
seq_printf(s, "\n");
total += atomic_read(&client->iovm_commit);
}
diff --git a/drivers/video/tegra/nvmap/nvmap_handle.c b/drivers/video/tegra/nvmap/nvmap_handle.c
index 2f24ba515862..56e2dab1820c 100644
--- a/drivers/video/tegra/nvmap/nvmap_handle.c
+++ b/drivers/video/tegra/nvmap/nvmap_handle.c
@@ -38,22 +38,12 @@
#include <mach/iovmm.h>
#include <linux/nvmap.h>
-#include <linux/vmstat.h>
-#include <linux/swap.h>
#include <linux/shrinker.h>
#include <linux/moduleparam.h>
-
#include "nvmap.h"
#include "nvmap_mru.h"
#include "nvmap_common.h"
-#define PRINT_CARVEOUT_CONVERSION 0
-#if PRINT_CARVEOUT_CONVERSION
-#define PR_INFO pr_info
-#else
-#define PR_INFO(...)
-#endif
-
#define NVMAP_SECURE_HEAPS (NVMAP_HEAP_CARVEOUT_IRAM | NVMAP_HEAP_IOVMM | \
NVMAP_HEAP_CARVEOUT_VPR)
#ifdef CONFIG_NVMAP_HIGHMEM_ONLY
@@ -646,36 +636,19 @@ fail:
static void alloc_handle(struct nvmap_client *client,
struct nvmap_handle *h, unsigned int type)
{
+ unsigned int carveout_mask = NVMAP_HEAP_CARVEOUT_MASK;
+ unsigned int iovmm_mask = NVMAP_HEAP_IOVMM;
+
BUG_ON(type & (type - 1));
#ifdef CONFIG_NVMAP_CONVERT_CARVEOUT_TO_IOVMM
-#define __NVMAP_HEAP_CARVEOUT (NVMAP_HEAP_CARVEOUT_IRAM | NVMAP_HEAP_CARVEOUT_VPR)
-#define __NVMAP_HEAP_IOVMM (NVMAP_HEAP_IOVMM | NVMAP_HEAP_CARVEOUT_GENERIC)
- if (type & NVMAP_HEAP_CARVEOUT_GENERIC) {
-#ifdef CONFIG_NVMAP_ALLOW_SYSMEM
- if (h->size <= PAGE_SIZE) {
- PR_INFO("###CARVEOUT CONVERTED TO SYSMEM "
- "0x%x bytes %s(%d)###\n",
- h->size, current->comm, current->pid);
- goto sysheap;
- }
-#endif
- PR_INFO("###CARVEOUT CONVERTED TO IOVM "
- "0x%x bytes %s(%d)###\n",
- h->size, current->comm, current->pid);
- }
-#else
-#define __NVMAP_HEAP_CARVEOUT NVMAP_HEAP_CARVEOUT_MASK
-#define __NVMAP_HEAP_IOVMM NVMAP_HEAP_IOVMM
+ /* Convert generic carveout requests to iovmm requests. */
+ carveout_mask &= ~NVMAP_HEAP_CARVEOUT_GENERIC;
+ iovmm_mask |= NVMAP_HEAP_CARVEOUT_GENERIC;
#endif
- if (type & __NVMAP_HEAP_CARVEOUT) {
+ if (type & carveout_mask) {
struct nvmap_heap_block *b;
-#ifdef CONFIG_NVMAP_CONVERT_CARVEOUT_TO_IOVMM
- PR_INFO("###IRAM REQUEST RETAINED "
- "0x%x bytes %s(%d)###\n",
- h->size, current->comm, current->pid);
-#endif
/* Protect handle from relocation */
nvmap_usecount_inc(h);
@@ -689,7 +662,7 @@ static void alloc_handle(struct nvmap_client *client,
}
nvmap_usecount_dec(h);
- } else if (type & __NVMAP_HEAP_IOVMM) {
+ } else if (type & iovmm_mask) {
size_t reserved = PAGE_ALIGN(h->size);
int commit = 0;
int ret;
@@ -713,10 +686,6 @@ static void alloc_handle(struct nvmap_client *client,
}
} else if (type & NVMAP_HEAP_SYSMEM) {
-#if defined(CONFIG_NVMAP_CONVERT_CARVEOUT_TO_IOVMM) && \
- defined(CONFIG_NVMAP_ALLOW_SYSMEM)
-sysheap:
-#endif
if (handle_page_alloc(client, h, true) == 0) {
BUG_ON(!h->pgalloc.contig);
h->heap_pgalloc = true;
@@ -751,10 +720,6 @@ static const unsigned int heap_policy_large[] = {
0,
};
-/* Do not override single page policy if there is not much space to
-avoid invoking system oom killer. */
-#define NVMAP_SMALL_POLICY_SYSMEM_THRESHOLD 50000000
-
int nvmap_alloc_handle_id(struct nvmap_client *client,
unsigned long id, unsigned int heap_mask,
size_t align, unsigned int flags)
@@ -779,32 +744,22 @@ int nvmap_alloc_handle_id(struct nvmap_client *client,
h->align = max_t(size_t, align, L1_CACHE_BYTES);
#ifndef CONFIG_TEGRA_IOVMM
+ /* convert iovmm requests to generic carveout. */
if (heap_mask & NVMAP_HEAP_IOVMM) {
- heap_mask &= NVMAP_HEAP_IOVMM;
- heap_mask |= NVMAP_HEAP_CARVEOUT_GENERIC;
+ heap_mask = heap_mask & ~NVMAP_HEAP_IOVMM |
+ NVMAP_HEAP_CARVEOUT_GENERIC;
}
#endif
-#ifndef CONFIG_NVMAP_CONVERT_CARVEOUT_TO_IOVMM
#ifdef CONFIG_NVMAP_ALLOW_SYSMEM
/* Allow single pages allocations in system memory to save
* carveout space and avoid extra iovm mappings */
if (nr_page == 1) {
- if (heap_mask & NVMAP_HEAP_IOVMM)
+ if (heap_mask &
+ (NVMAP_HEAP_IOVMM | NVMAP_HEAP_CARVEOUT_GENERIC))
heap_mask |= NVMAP_HEAP_SYSMEM;
- else if (heap_mask & NVMAP_HEAP_CARVEOUT_GENERIC) {
- /* Calculate size of free physical pages
- * managed by kernel */
- unsigned long freeMem =
- (global_page_state(NR_FREE_PAGES) +
- global_page_state(NR_FILE_PAGES) -
- total_swapcache_pages) << PAGE_SHIFT;
-
- if (freeMem > NVMAP_SMALL_POLICY_SYSMEM_THRESHOLD)
- heap_mask |= NVMAP_HEAP_SYSMEM;
- }
}
#endif
-
+#ifndef CONFIG_NVMAP_CONVERT_CARVEOUT_TO_IOVMM
/* This restriction is deprecated as alignments greater than
PAGE_SIZE are now correctly handled, but it is retained for
AP20 compatibility. */
diff --git a/include/linux/nvmap.h b/include/linux/nvmap.h
index bea59694ad27..553a7bd01a6d 100644
--- a/include/linux/nvmap.h
+++ b/include/linux/nvmap.h
@@ -28,8 +28,8 @@
#define __user
#endif
-#ifndef __NVMAP_H
-#define __NVMAP_H
+#ifndef _LINUX_NVMAP_H
+#define _LINUX_NVMAP_H
#define NVMAP_HEAP_SYSMEM (1ul<<31)
#define NVMAP_HEAP_IOVMM (1ul<<30)
@@ -50,20 +50,31 @@
#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)
+
+/* 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 */
+};
+
#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
@@ -76,31 +87,10 @@ struct nvmap_device;
BUG(); \
} \
(*((u32 *)h)); })
-#endif
-
-#define nvmap_id_to_handle(_id) ((struct nvmap_handle *)(_id))
+#endif /* CONFIG_ION_TEGRA */
-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
+#define nvmap_id_to_handle(_id) ((struct nvmap_handle *)(_id))
struct nvmap_client *nvmap_create_client(struct nvmap_device *dev,
const char *name);
@@ -127,17 +117,9 @@ 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_handle_ref *nvmap_duplicate_handle_id(struct nvmap_client *client,
unsigned long id);
@@ -156,6 +138,6 @@ struct nvmap_platform_data {
extern struct nvmap_device *nvmap_dev;
-#endif
+#endif /* __KERNEL__ */
-#endif
+#endif /* _LINUX_NVMAP_H */
diff --git a/include/linux/platform_data/tegra_usb.h b/include/linux/platform_data/tegra_usb.h
index e6377c379b48..911175086977 100644
--- a/include/linux/platform_data/tegra_usb.h
+++ b/include/linux/platform_data/tegra_usb.h
@@ -16,33 +16,132 @@
#ifndef _TEGRA_USB_H_
#define _TEGRA_USB_H_
-enum tegra_usb_operating_modes {
- TEGRA_USB_DEVICE,
- TEGRA_USB_HOST,
- TEGRA_USB_OTG,
+/**
+ * defines operation mode of the USB controller
+ */
+enum tegra_usb_operation_mode {
+ TEGRA_USB_OPMODE_DEVICE,
+ TEGRA_USB_OPMODE_HOST,
};
-enum tegra_usb_phy_type {
- TEGRA_USB_PHY_TYPE_UTMIP = 0,
- TEGRA_USB_PHY_TYPE_LINK_ULPI = 1,
- TEGRA_USB_PHY_TYPE_NULL_ULPI = 2,
- TEGRA_USB_PHY_TYPE_HSIC = 3,
- TEGRA_USB_PHY_TYPE_ICUSB = 4,
+/**
+ * defines the various phy interface mode supported by controller
+ */
+enum tegra_usb_phy_interface {
+ TEGRA_USB_PHY_INTF_UTMI = 0,
+ TEGRA_USB_PHY_INTF_ULPI_LINK = 1,
+ TEGRA_USB_PHY_INTF_ULPI_NULL = 2,
+ TEGRA_USB_PHY_INTF_HSIC = 3,
+ TEGRA_USB_PHY_INTF_ICUSB = 4,
};
-struct tegra_ehci_platform_data {
- enum tegra_usb_operating_modes operating_mode;
- /* power down the phy on bus suspend */
- int power_down_on_bus_suspend;
- int hotplug;
- int default_enable;
- void *phy_config;
- enum tegra_usb_phy_type phy_type;
+/**
+ * configuration structure for setting up utmi phy
+ */
+struct tegra_utmi_config {
+ u8 hssync_start_delay;
+ u8 elastic_limit;
+ u8 idle_wait_delay;
+ u8 term_range_adj;
+ u8 xcvr_setup;
+ u8 xcvr_lsfslew;
+ u8 xcvr_lsrslew;
+ signed char xcvr_setup_offset;
+ u8 xcvr_use_fuses;
};
-struct tegra_otg_platform_data {
+/**
+ * configuration structure for setting up ulpi phy
+ */
+struct tegra_ulpi_config {
+ u8 shadow_clk_delay;
+ u8 clock_out_delay;
+ u8 data_trimmer;
+ u8 stpdirnxt_trimmer;
+ u8 dir_trimmer;
+ const char *clk;
+};
+
+/**
+ * configuration structure for setting up hsic phy
+ */
+struct tegra_hsic_config {
+ u8 sync_start_delay;
+ u8 idle_wait_delay;
+ u8 term_range_adj;
+ u8 elastic_underrun_limit;
+ u8 elastic_overrun_limit;
+};
+
+/**
+ * Platform specific operations that will be controlled
+ * during the phy operations.
+ */
+struct tegra_usb_phy_platform_ops {
+ void (*open)(void);
+ void (*init)(void);
+ void (*pre_suspend)(void);
+ void (*post_suspend)(void);
+ void (*pre_resume)(void);
+ void (*post_resume)(void);
+ void (*pre_phy_off)(void);
+ void (*post_phy_off)(void);
+ void (*pre_phy_on)(void);
+ void (*post_phy_on)(void);
+ void (*port_power)(void);
+ void (*close)(void);
+};
+
+/**
+ * defines structure for platform dependent device parameters
+ */
+struct tegra_usb_dev_mode_data {
+ int vbus_pmu_irq;
+ int vbus_gpio;
+ bool charging_supported;
+ bool remote_wakeup_supported;
+};
+
+/**
+ * defines structure for platform dependent host parameters
+ */
+struct tegra_usb_host_mode_data {
+ int vbus_gpio;
+ const char *vbus_reg;
+ bool hot_plug;
+ bool remote_wakeup_supported;
+ bool power_off_on_suspend;
+};
+
+/**
+ * defines structure for usb platform data
+ */
+struct tegra_usb_platform_data {
+ bool port_otg;
+ bool has_hostpc;
+ enum tegra_usb_phy_interface phy_intf;
+ enum tegra_usb_operation_mode op_mode;
+
+ union {
+ struct tegra_usb_dev_mode_data dev;
+ struct tegra_usb_host_mode_data host;
+ } u_data;
+
+ union {
+ struct tegra_utmi_config utmi;
+ struct tegra_ulpi_config ulpi;
+ struct tegra_hsic_config hsic;
+ } u_cfg;
+
+ struct tegra_usb_phy_platform_ops *ops;
+};
+
+/**
+ * defines structure for platform dependent OTG parameters
+ */
+struct tegra_usb_otg_data {
struct platform_device *ehci_device;
- struct tegra_ehci_platform_data *ehci_pdata;
+ struct tegra_usb_platform_data *ehci_pdata;
};
#endif /* _TEGRA_USB_H_ */
diff --git a/include/media/ad5816.h b/include/media/ad5816.h
new file mode 100644
index 000000000000..bfea25ffaddf
--- /dev/null
+++ b/include/media/ad5816.h
@@ -0,0 +1,81 @@
+/*
+ * 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
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307, USA
+ */
+
+#ifndef __AD5816_H__
+#define __AD5816_H__
+
+#include <media/nvc_focus.h>
+#include <media/nvc.h>
+
+typedef enum ad5816_vreg
+{
+ AD5816_VREG_VDD = 0,
+ AD5816_VREG_VDD_AF,
+ AD5816_VREG_VDD_I2C
+};
+
+typedef enum ad5816_gpio_types
+{
+ AD5816_GPIO_RESET = 0,
+ AD5816_GPIO_I2CMUX,
+ AD5816_GPIO_GP1,
+ AD5816_GPIO_GP2,
+ AD5816_GPIO_GP3
+};
+
+
+struct ad5816_platform_data {
+ int cfg;
+ int num;
+ int sync;
+ const char *dev_name;
+ struct nvc_focus_nvc (*nvc);
+ struct nvc_focus_cap (*cap);
+ struct ad5816_pdata_info (*info);
+ int gpio_count;
+ struct nvc_gpio_pdata *gpio;
+};
+
+struct ad5816_pdata_info {
+ float focal_length;
+ float fnumber;
+ __u32 settle_time;
+ __s16 pos_low;
+ __s16 pos_high;
+ __s16 limit_low;
+ __s16 limit_high;
+ int move_timeoutms;
+ __u32 focus_hyper_ratio;
+ __u32 focus_hyper_div;
+};
+
+// Register Definitions
+
+#define IC_INFO 0x00
+#define IC_VERSION 0x01
+#define CONTROL 0x02
+#define VCM_CODE_MSB 0x03
+#define VCM_CODE_LSB 0x04
+#define STATUS 0x05
+#define MODE 0x06
+#define VCM_FREQ 0x07
+#define VCM_THRESHOLD 0x08
+
+
+#endif
+/* __AD5816_H__ */ \ No newline at end of file
diff --git a/include/trace/events/nvhost.h b/include/trace/events/nvhost.h
index 4bb79e30fc19..6506af44e576 100644
--- a/include/trace/events/nvhost.h
+++ b/include/trace/events/nvhost.h
@@ -138,6 +138,52 @@ TRACE_EVENT(nvhost_channel_write_cmdbuf,
__entry->words, __entry->offset)
);
+TRACE_EVENT(nvhost_cdma_end,
+ TP_PROTO(const char *name, int prio,
+ int hi_count, int med_count, int low_count),
+
+ TP_ARGS(name, prio, hi_count, med_count, low_count),
+
+ TP_STRUCT__entry(
+ __field(const char *, name)
+ __field(int, prio)
+ __field(int, hi_count)
+ __field(int, med_count)
+ __field(int, low_count)
+ ),
+
+ TP_fast_assign(
+ __entry->name = name;
+ __entry->prio = prio;
+ __entry->hi_count = hi_count;
+ __entry->med_count = med_count;
+ __entry->low_count = low_count;
+ ),
+
+ TP_printk("name=%s, prio=%d, hi=%d, med=%d, low=%d",
+ __entry->name, __entry->prio,
+ __entry->hi_count, __entry->med_count, __entry->low_count)
+);
+
+TRACE_EVENT(nvhost_cdma_flush,
+ TP_PROTO(const char *name, int timeout),
+
+ TP_ARGS(name, timeout),
+
+ TP_STRUCT__entry(
+ __field(const char *, name)
+ __field(int, timeout)
+ ),
+
+ TP_fast_assign(
+ __entry->name = name;
+ __entry->timeout = timeout;
+ ),
+
+ TP_printk("name=%s, timeout=%d",
+ __entry->name, __entry->timeout)
+);
+
TRACE_EVENT(nvhost_cdma_push,
TP_PROTO(const char *name, u32 op1, u32 op2),
@@ -194,20 +240,30 @@ TRACE_EVENT(nvhost_cdma_push_gather,
);
TRACE_EVENT(nvhost_channel_write_reloc,
- TP_PROTO(const char *name),
+ TP_PROTO(const char *name, u32 cmdbuf_mem, u32 cmdbuf_offset,
+ u32 target, u32 target_offset),
- TP_ARGS(name),
+ TP_ARGS(name, cmdbuf_mem, cmdbuf_offset, target, target_offset),
TP_STRUCT__entry(
__field(const char *, name)
+ __field(u32, cmdbuf_mem)
+ __field(u32, cmdbuf_offset)
+ __field(u32, target)
+ __field(u32, target_offset)
),
TP_fast_assign(
__entry->name = name;
+ __entry->cmdbuf_mem = cmdbuf_mem;
+ __entry->cmdbuf_offset = cmdbuf_offset;
+ __entry->target = target;
+ __entry->target_offset = target_offset;
),
- TP_printk("name=%s",
- __entry->name)
+ TP_printk("name=%s, cmdbuf_mem=%08x, cmdbuf_offset=%04x, target=%08x, target_offset=%04x",
+ __entry->name, __entry->cmdbuf_mem, __entry->cmdbuf_offset,
+ __entry->target, __entry->target_offset)
);
TRACE_EVENT(nvhost_channel_write_waitchks,
@@ -415,24 +471,32 @@ TRACE_EVENT(nvhost_channel_submitted,
);
TRACE_EVENT(nvhost_channel_submit_complete,
- TP_PROTO(const char *name, int count, u32 thresh),
+ TP_PROTO(const char *name, int count, u32 thresh,
+ int hi_count, int med_count, int low_count),
- TP_ARGS(name, count, thresh),
+ TP_ARGS(name, count, thresh, hi_count, med_count, low_count),
TP_STRUCT__entry(
__field(const char *, name)
__field(int, count)
__field(u32, thresh)
+ __field(int, hi_count)
+ __field(int, med_count)
+ __field(int, low_count)
),
TP_fast_assign(
__entry->name = name;
__entry->count = count;
__entry->thresh = thresh;
+ __entry->hi_count = hi_count;
+ __entry->med_count = med_count;
+ __entry->low_count = low_count;
),
- TP_printk("name=%s, count=%d, thresh=%d",
- __entry->name, __entry->count, __entry->thresh)
+ TP_printk("name=%s, count=%d, thresh=%d, hi=%d, med=%d, low=%d",
+ __entry->name, __entry->count, __entry->thresh,
+ __entry->hi_count, __entry->med_count, __entry->low_count)
);
TRACE_EVENT(nvhost_wait_cdma,
@@ -472,27 +536,30 @@ TRACE_EVENT(nvhost_syncpt_update_min,
);
TRACE_EVENT(nvhost_syncpt_wait_check,
- TP_PROTO(u32 mem_id, u32 offset, u32 syncpt_id, u32 val),
+ TP_PROTO(u32 mem_id, u32 offset, u32 syncpt_id, u32 thresh, u32 min),
- TP_ARGS(mem_id, offset, syncpt_id, val),
+ TP_ARGS(mem_id, offset, syncpt_id, thresh, min),
TP_STRUCT__entry(
__field(u32, mem_id)
__field(u32, offset)
__field(u32, syncpt_id)
- __field(u32, val)
+ __field(u32, thresh)
+ __field(u32, min)
),
TP_fast_assign(
__entry->mem_id = mem_id;
__entry->offset = offset;
__entry->syncpt_id = syncpt_id;
- __entry->val = val;
+ __entry->thresh = thresh;
+ __entry->min = min;
),
- TP_printk("mem_id=%08x, offset=%05x, id=%d, val=%d",
+ TP_printk("mem_id=%08x, offset=%05x, id=%d, thresh=%d, current=%d",
__entry->mem_id, __entry->offset,
- __entry->syncpt_id, __entry->val)
+ __entry->syncpt_id, __entry->thresh,
+ __entry->min)
);
#endif /* _TRACE_NVHOST_H */
diff --git a/security/tf_driver/Makefile b/security/tf_driver/Makefile
index dfadb7d97406..5c48f626f5d8 100644
--- a/security/tf_driver/Makefile
+++ b/security/tf_driver/Makefile
@@ -21,7 +21,7 @@
# debug options
#EXTRA_CFLAGS += -O0 -DDEBUG -D_DEBUG -DCONFIG_TF_DRIVER_DEBUG_SUPPORT
EXTRA_CFLAGS += -DNDEBUG
-EXTRA_CFLAGS += -DLINUX -DCONFIG_TF_TRUSTZONE -DCONFIG_TFN
+EXTRA_CFLAGS += -DLINUX -DCONFIG_TF_TRUSTZONE -DCONFIG_TFN -DCONFIG_SECURE_TRACES
ifdef S_VERSION_BUILD
EXTRA_CFLAGS += -DS_VERSION_BUILD=$(S_VERSION_BUILD)
diff --git a/security/tf_driver/s_version.h b/security/tf_driver/s_version.h
index ba4d48c6f417..d812cdca75df 100644
--- a/security/tf_driver/s_version.h
+++ b/security/tf_driver/s_version.h
@@ -33,12 +33,12 @@
*/
#define S_VERSION_OS "A" /* "A" for all Android */
-#define S_VERSION_PLATFORM "A" /* "A" for Tegra2 */
+#define S_VERSION_PLATFORM "B" /* "B" for Tegra3 */
/*
* This version number must be updated for each new release
*/
-#define S_VERSION_MAIN "01.07"
+#define S_VERSION_MAIN "01.08"
/*
* If this is a patch or engineering version use the following
diff --git a/security/tf_driver/tf_comm_tz.c b/security/tf_driver/tf_comm_tz.c
index 4c89de84accf..4628f24f3cf2 100644
--- a/security/tf_driver/tf_comm_tz.c
+++ b/security/tf_driver/tf_comm_tz.c
@@ -194,6 +194,20 @@ static inline void tf_smc_nyield(void)
tf_smc_generic_call(&generic_smc);
}
+#ifdef CONFIG_SECURE_TRACES
+static void tf_print_secure_traces(struct tf_comm *comm)
+{
+ spin_lock(&(comm->lock));
+ if (comm->l1_buffer->traces_status != 0) {
+ if (comm->l1_buffer->traces_status > 1)
+ pr_info("TF : traces lost...\n");
+ pr_info("TF : %s", comm->l1_buffer->traces_buffer);
+ comm->l1_buffer->traces_status = 0;
+ }
+ spin_unlock(&(comm->lock));
+}
+#endif
+
/* Yields the Secure World */
int tf_schedule_secure_world(struct tf_comm *comm)
{
@@ -202,6 +216,10 @@ int tf_schedule_secure_world(struct tf_comm *comm)
/* yield to the Secure World */
tf_smc_nyield();
+#ifdef CONFIG_SECURE_TRACES
+ tf_print_secure_traces(comm);
+#endif
+
return 0;
}
diff --git a/security/tf_driver/tf_protocol.h b/security/tf_driver/tf_protocol.h
index 403df8ec8ef5..b264f04c4454 100644
--- a/security/tf_driver/tf_protocol.h
+++ b/security/tf_driver/tf_protocol.h
@@ -659,6 +659,10 @@ struct tf_l1_shared_buffer {
#ifdef CONFIG_TF_ZEBRA
u8 rpc_trace_buffer[140];
u8 rpc_cus_buffer[180];
+ #elif CONFIG_SECURE_TRACES
+ u32 traces_status;
+ u8 traces_buffer[140];
+ u8 reserved3[176];
#else
u8 reserved3[320];
#endif
diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile
index 9c4346aa265c..7af02a69b8ae 100644
--- a/sound/soc/tegra/Makefile
+++ b/sound/soc/tegra/Makefile
@@ -1,5 +1,7 @@
GCOV_PROFILE := y
+subdir-ccflags-y := -Werror
+
# Tegra platform Support
snd-soc-tegra-pcm-objs := tegra_pcm.o
snd-soc-tegra-tdm-pcm-objs := tegra_tdm_pcm.o
diff --git a/sound/soc/tegra/tegra20_das.c b/sound/soc/tegra/tegra20_das.c
index 0774d360399a..29c4582cfa79 100644
--- a/sound/soc/tegra/tegra20_das.c
+++ b/sound/soc/tegra/tegra20_das.c
@@ -50,7 +50,7 @@ static inline u32 tegra20_das_read(u32 reg)
}
#ifdef CONFIG_PM
-int tegra20_das_resume()
+int tegra20_das_resume(void)
{
int i, reg;
@@ -67,7 +67,7 @@ int tegra20_das_resume()
}
#endif
-int tegra20_das_set_tristate(int dap_id, int is_tristate)
+void tegra20_das_set_tristate(int dap_id, int is_tristate)
{
enum tegra_pingroup pin;
enum tegra_tristate tristate;
@@ -86,7 +86,7 @@ int tegra20_das_set_tristate(int dap_id, int is_tristate)
pin = TEGRA_PINGROUP_DAP4;
break;
default:
- return -EINVAL;
+ return;
}
if (is_tristate)
diff --git a/sound/soc/tegra/tegra20_das.h b/sound/soc/tegra/tegra20_das.h
index 0d58c7d1bc3f..5cd2d07d43b8 100644
--- a/sound/soc/tegra/tegra20_das.h
+++ b/sound/soc/tegra/tegra20_das.h
@@ -98,7 +98,7 @@ struct tegra20_das {
#ifdef CONFIG_PM
/* Restores the das registers from cache */
-extern int tegra20_das_resume();
+extern int tegra20_das_resume(void);
#endif
/*
* Terminology:
@@ -143,6 +143,6 @@ extern int tegra20_das_connect_dap_to_dap(int dap_id, int other_dap_sel,
*/
extern int tegra20_das_connect_dac_to_dap(int dac_id, int dap_sel);
-extern int tegra20_das_set_tristate(int dap_id, int is_tristate);
+extern void tegra20_das_set_tristate(int dap_id, int is_tristate);
#endif
diff --git a/sound/soc/tegra/tegra_aic326x.c b/sound/soc/tegra/tegra_aic326x.c
index a5c6fc0aecb7..4cacb6758eb8 100644
--- a/sound/soc/tegra/tegra_aic326x.c
+++ b/sound/soc/tegra/tegra_aic326x.c
@@ -1062,6 +1062,10 @@ static int tegra_aic326x_init(struct snd_soc_pcm_runtime *rtd)
if (ret < 0)
return ret;
+ ret = tegra_asoc_utils_register_ctls(&machine->util_data);
+ if (ret < 0)
+ return ret;
+
snd_soc_dapm_force_enable_pin(dapm, "MICBIAS_EXT ON");
snd_soc_dapm_force_enable_pin(dapm,"MICBIAS_INT ON");
snd_soc_dapm_sync(dapm);
diff --git a/sound/soc/tegra/tegra_asoc_utils.c b/sound/soc/tegra/tegra_asoc_utils.c
index b134f0808afa..6ab5b2d46a1f 100644
--- a/sound/soc/tegra/tegra_asoc_utils.c
+++ b/sound/soc/tegra/tegra_asoc_utils.c
@@ -27,11 +27,14 @@
#include <mach/clk.h>
+#include <sound/soc.h>
+
+#include "tegra_pcm.h"
#include "tegra_asoc_utils.h"
int g_is_call_mode;
-bool tegra_is_voice_call_active()
+bool tegra_is_voice_call_active(void)
{
if (g_is_call_mode)
return true;
@@ -40,6 +43,115 @@ bool tegra_is_voice_call_active()
}
EXPORT_SYMBOL_GPL(tegra_is_voice_call_active);
+static int tegra_get_avp_device(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct tegra_asoc_utils_data *data = snd_kcontrol_chip(kcontrol);
+
+ ucontrol->value.integer.value[0] = data->avp_device_id;
+ return 0;
+}
+
+static int tegra_set_avp_device(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct tegra_asoc_utils_data *data = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = data->card;
+ struct snd_soc_pcm_runtime *rtd;
+ struct snd_pcm_substream *substream;
+ struct tegra_runtime_data *prtd;
+ int id, old_id = data->avp_device_id;
+
+ id = ucontrol->value.integer.value[0];
+ if ((id >= card->num_rtd) || (id < 0))
+ id = -1;
+
+ if (old_id >= 0) {
+ rtd = &card->rtd[old_id];
+ substream =
+ rtd->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+ if (substream && substream->runtime) {
+ prtd = substream->runtime->private_data;
+ if (prtd->running)
+ return -EBUSY;
+ if (prtd)
+ prtd->disable_intr = false;
+ }
+ }
+
+ if (id >= 0) {
+ rtd = &card->rtd[id];
+ substream =
+ rtd->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+ if (substream && substream->runtime) {
+ prtd = substream->runtime->private_data;
+ if (prtd->running)
+ return -EBUSY;
+ if (prtd)
+ prtd->disable_intr = true;
+ }
+ }
+ data->avp_device_id = id;
+ return 1;
+}
+
+static int tegra_get_dma_ch_id(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct tegra_asoc_utils_data *data = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = data->card;
+ struct snd_soc_pcm_runtime *rtd;
+ struct snd_pcm_substream *substream;
+ struct tegra_runtime_data *prtd;
+
+ ucontrol->value.integer.value[0] = -1;
+ if (data->avp_device_id < 0)
+ return 0;
+
+ rtd = &card->rtd[data->avp_device_id];
+ substream = rtd->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+ if (!substream || !substream->runtime)
+ return 0;
+
+ prtd = substream->runtime->private_data;
+ if (!prtd || !prtd->dma_chan)
+ return 0;
+
+ ucontrol->value.integer.value[0] =
+ tegra_dma_get_channel_id(prtd->dma_chan);
+ return 0;
+}
+
+static int tegra_get_dma_addr(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct tegra_asoc_utils_data *data = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = data->card;
+ struct snd_soc_pcm_runtime *rtd;
+ struct snd_pcm_substream *substream;
+
+ ucontrol->value.integer.value[0] = 0;
+ if (data->avp_device_id < 0)
+ return 0;
+
+ rtd = &card->rtd[data->avp_device_id];
+ substream = rtd->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+ if (!substream || !substream->runtime)
+ return 0;
+
+ ucontrol->value.integer.value[0] = substream->runtime->dma_addr;
+ return 0;
+}
+
+struct snd_kcontrol_new tegra_avp_controls[] = {
+ SOC_SINGLE_EXT("AVP alsa device select", 0, 0, TEGRA_ALSA_MAX_DEVICES, \
+ 0, tegra_get_avp_device, tegra_set_avp_device),
+ SOC_SINGLE_EXT("AVP DMA channel id", 0, 0, TEGRA_DMA_MAX_CHANNELS, \
+ 0, tegra_get_dma_ch_id, NULL),
+ SOC_SINGLE_EXT("AVP DMA address", 0, 0, 0xFFFFFFFF, \
+ 0, tegra_get_dma_addr, NULL),
+};
+
int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,
int mclk)
{
@@ -152,6 +264,26 @@ int tegra_asoc_utils_clk_disable(struct tegra_asoc_utils_data *data)
}
EXPORT_SYMBOL_GPL(tegra_asoc_utils_clk_disable);
+int tegra_asoc_utils_register_ctls(struct tegra_asoc_utils_data *data)
+{
+ int i;
+ int ret = 0;
+
+ /* Add AVP related alsa controls */
+ data->avp_device_id = -1;
+ for (i = 0; i < ARRAY_SIZE(tegra_avp_controls); i++) {
+ ret = snd_ctl_add(data->card->snd_card,
+ snd_ctl_new1(&tegra_avp_controls[i], data));
+ if (ret < 0) {
+ dev_err(data->dev, "Can't add avp alsa controls");
+ return ret;
+ }
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(tegra_asoc_utils_register_ctls);
+
int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data,
struct device *dev, struct snd_soc_card *card)
{
@@ -276,6 +408,10 @@ void tegra_asoc_utils_fini(struct tegra_asoc_utils_data *data)
clk_put(data->clk_out1);
clk_put(data->clk_cdev1);
+ /* Just to make sure that clk_cdev1 should turn off in case if it is
+ * switched on by some codec whose hw switch is not registered.*/
+ if (tegra_is_clk_enabled(data->clk_cdev1))
+ clk_disable(data->clk_cdev1);
if (!IS_ERR(data->clk_pll_a_out0))
clk_put(data->clk_pll_a_out0);
diff --git a/sound/soc/tegra/tegra_asoc_utils.h b/sound/soc/tegra/tegra_asoc_utils.h
index 512df0d54eb1..0423f02b76cc 100644
--- a/sound/soc/tegra/tegra_asoc_utils.h
+++ b/sound/soc/tegra/tegra_asoc_utils.h
@@ -25,6 +25,8 @@
#define TEGRA30_I2S_MASTER_PLAYBACK 1
+#define TEGRA_ALSA_MAX_DEVICES 6
+#define TEGRA_DMA_MAX_CHANNELS 32
struct clk;
struct device;
@@ -41,6 +43,7 @@ struct tegra_asoc_utils_data {
int set_baseclock;
int set_mclk;
int lock_count;
+ int avp_device_id;
};
int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,
@@ -52,6 +55,7 @@ int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data,
void tegra_asoc_utils_fini(struct tegra_asoc_utils_data *data);
int tegra_asoc_utils_clk_enable(struct tegra_asoc_utils_data *data);
int tegra_asoc_utils_clk_disable(struct tegra_asoc_utils_data *data);
+int tegra_asoc_utils_register_ctls(struct tegra_asoc_utils_data *data);
#endif
diff --git a/sound/soc/tegra/tegra_max98088.c b/sound/soc/tegra/tegra_max98088.c
index 8c0e3935ad02..82c2b930a39e 100644
--- a/sound/soc/tegra/tegra_max98088.c
+++ b/sound/soc/tegra/tegra_max98088.c
@@ -1009,6 +1009,10 @@ static int tegra_max98088_init(struct snd_soc_pcm_runtime *rtd)
if (ret < 0)
return ret;
+ ret = tegra_asoc_utils_register_ctls(&machine->util_data);
+ if (ret < 0)
+ return ret;
+
snd_soc_dapm_nc_pin(dapm, "INA1");
snd_soc_dapm_nc_pin(dapm, "INA2");
snd_soc_dapm_nc_pin(dapm, "INB1");
diff --git a/sound/soc/tegra/tegra_max98095.c b/sound/soc/tegra/tegra_max98095.c
index 95295ef4151e..b3bed37ac715 100644
--- a/sound/soc/tegra/tegra_max98095.c
+++ b/sound/soc/tegra/tegra_max98095.c
@@ -542,6 +542,10 @@ static int tegra_max98095_init(struct snd_soc_pcm_runtime *rtd)
tegra_max98095_hp_jack_pins);
#endif
+ ret = tegra_asoc_utils_register_ctls(&machine->util_data);
+ if (ret < 0)
+ return ret;
+
/* max98095_headset_detect(codec, &tegra_max98095_hp_jack,
SND_JACK_HEADSET); */
diff --git a/sound/soc/tegra/tegra_p1852.c b/sound/soc/tegra/tegra_p1852.c
index 9506a1c842df..85b4cee30c5f 100644
--- a/sound/soc/tegra/tegra_p1852.c
+++ b/sound/soc/tegra/tegra_p1852.c
@@ -49,7 +49,8 @@ struct tegra_p1852 {
};
static int tegra_p1852_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+ struct snd_pcm_hw_params *params,
+ int codec_id)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
@@ -61,7 +62,6 @@ static int tegra_p1852_hw_params(struct snd_pcm_substream *substream,
int i2s_daifmt = 0;
int err;
struct tegra_p1852_platform_data *pdata;
- int codec_id = codec_dai->id;
pdata = machine->pdata;
@@ -120,15 +120,39 @@ static int tegra_p1852_hw_params(struct snd_pcm_substream *substream,
dev_err(card->dev, "cpu_dai fmt not set\n");
return err;
}
-
err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
SND_SOC_CLOCK_IN);
if (err < 0)
dev_info(card->dev, "codec_dai clock not set\n");
+ if (pdata->codec_info[codec_id].i2s_format ==
+ format_tdm) {
+ err = snd_soc_dai_set_tdm_slot(cpu_dai,
+ pdata->codec_info[codec_id].rx_mask,
+ pdata->codec_info[codec_id].tx_mask,
+ pdata->codec_info[codec_id].num_slots,
+ pdata->codec_info[codec_id].slot_width);
+ if (err < 0)
+ dev_err(card->dev, "cpu_dai tdm mode setting not done\n");
+ }
+
return 0;
}
+static int tegra_p1852_hw_params_controller1(
+ struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ return tegra_p1852_hw_params(substream, params, 0);
+}
+
+static int tegra_p1852_hw_params_controller2(
+ struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ return tegra_p1852_hw_params(substream, params, 1);
+}
+
static int tegra_hw_free(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -139,8 +163,12 @@ static int tegra_hw_free(struct snd_pcm_substream *substream)
return 0;
}
-static struct snd_soc_ops tegra_p1852_ops = {
- .hw_params = tegra_p1852_hw_params,
+static struct snd_soc_ops tegra_p1852_ops_controller1 = {
+ .hw_params = tegra_p1852_hw_params_controller1,
+ .hw_free = tegra_hw_free,
+};
+static struct snd_soc_ops tegra_p1852_ops_controller2 = {
+ .hw_params = tegra_p1852_hw_params_controller2,
.hw_free = tegra_hw_free,
};
@@ -149,13 +177,13 @@ static struct snd_soc_dai_link tegra_p1852_dai_link[] = {
.name = "I2S-TDM-1",
.stream_name = "TEGRA PCM",
.platform_name = "tegra-pcm-audio",
- .ops = &tegra_p1852_ops,
+ .ops = &tegra_p1852_ops_controller1,
},
{
.name = "I2S-TDM-2",
.stream_name = "TEGRA PCM",
.platform_name = "tegra-pcm-audio",
- .ops = &tegra_p1852_ops,
+ .ops = &tegra_p1852_ops_controller2,
}
};
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c
index 1b4b949841aa..f471fafff2ac 100644
--- a/sound/soc/tegra/tegra_pcm.c
+++ b/sound/soc/tegra/tegra_pcm.c
@@ -52,8 +52,8 @@ static const struct snd_pcm_hardware tegra_pcm_hardware = {
.channels_min = 1,
.channels_max = 2,
.period_bytes_min = 128,
- .period_bytes_max = PAGE_SIZE,
- .periods_min = 2,
+ .period_bytes_max = PAGE_SIZE * 2,
+ .periods_min = 1,
.periods_max = 8,
.buffer_bytes_max = PAGE_SIZE * 8,
.fifo_size = 4,
@@ -272,6 +272,15 @@ int tegra_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
prtd->dma_pos_end = frames_to_bytes(runtime, runtime->periods * runtime->period_size);
prtd->period_index = 0;
prtd->dma_req_idx = 0;
+ if (prtd->disable_intr) {
+ prtd->dma_req_count = 1;
+ prtd->dma_req[0].complete = NULL;
+ } else if (!prtd->dma_req[0].complete) {
+ prtd->dma_req[0].complete = dma_complete_callback;
+ prtd->dma_req_count =
+ (MAX_DMA_REQ_COUNT <= runtime->periods) ?
+ MAX_DMA_REQ_COUNT : runtime->periods;
+ }
/* Fall-through */
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
@@ -289,8 +298,9 @@ int tegra_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
spin_unlock_irqrestore(&prtd->lock, flags);
tegra_dma_cancel(prtd->dma_chan);
for (i = 0; i < prtd->dma_req_count; i++) {
- if (prtd->dma_req[i].status ==
- -TEGRA_DMA_REQ_ERROR_ABORTED)
+ if (prtd->dma_req[i].complete &&
+ (prtd->dma_req[i].status ==
+ -TEGRA_DMA_REQ_ERROR_ABORTED))
prtd->dma_req[i].complete(&prtd->dma_req[i]);
}
break;
diff --git a/sound/soc/tegra/tegra_pcm.h b/sound/soc/tegra/tegra_pcm.h
index 7fe22788004b..b63de32023e8 100644
--- a/sound/soc/tegra/tegra_pcm.h
+++ b/sound/soc/tegra/tegra_pcm.h
@@ -53,6 +53,7 @@ struct tegra_runtime_data {
struct tegra_dma_req dma_req[MAX_DMA_REQ_COUNT];
struct tegra_dma_channel *dma_chan;
int dma_req_count;
+ int disable_intr;
};
int tegra_pcm_trigger(struct snd_pcm_substream *substream, int cmd);
diff --git a/sound/soc/tegra/tegra_rt5640.c b/sound/soc/tegra/tegra_rt5640.c
index 231b0ee61308..765eb59fabae 100644
--- a/sound/soc/tegra/tegra_rt5640.c
+++ b/sound/soc/tegra/tegra_rt5640.c
@@ -547,6 +547,11 @@ static int tegra_rt5640_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_add_routes(dapm, cardhu_audio_map,
ARRAY_SIZE(cardhu_audio_map));
+
+ ret = tegra_asoc_utils_register_ctls(&machine->util_data);
+ if (ret < 0)
+ return ret;
+
/* FIXME: Calculate automatically based on DAPM routes? */
snd_soc_dapm_nc_pin(dapm, "LOUTL");
snd_soc_dapm_nc_pin(dapm, "LOUTR");
diff --git a/sound/soc/tegra/tegra_wm8753.c b/sound/soc/tegra/tegra_wm8753.c
index 795356875ba4..f7c7a4c6b5a1 100644
--- a/sound/soc/tegra/tegra_wm8753.c
+++ b/sound/soc/tegra/tegra_wm8753.c
@@ -379,7 +379,6 @@ static int tegra_bt_call_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *codec_dai = rtd->codec_dai;
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_card *card = codec->card;
struct tegra_wm8753 *machine = snd_soc_card_get_drvdata(card);
@@ -783,6 +782,10 @@ static int tegra_wm8753_init(struct snd_soc_pcm_runtime *rtd)
if (ret < 0)
return ret;
+ ret = tegra_asoc_utils_register_ctls(&machine->util_data);
+ if (ret < 0)
+ return ret;
+
snd_soc_dapm_nc_pin(dapm, "ACIN");
snd_soc_dapm_nc_pin(dapm, "ACOP");
snd_soc_dapm_nc_pin(dapm, "OUT3");
diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c
index ce608b007bef..147546575233 100644
--- a/sound/soc/tegra/tegra_wm8903.c
+++ b/sound/soc/tegra/tegra_wm8903.c
@@ -660,6 +660,10 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd)
wm8903_mic_detect(codec, &tegra_wm8903_mic_jack, SND_JACK_MICROPHONE,
machine_is_cardhu() ? SND_JACK_MICROPHONE : 0);
+ ret = tegra_asoc_utils_register_ctls(&machine->util_data);
+ if (ret < 0)
+ return ret;
+
snd_soc_dapm_force_enable_pin(dapm, "Mic Bias");
/* FIXME: Calculate automatically based on DAPM routes? */