summaryrefslogtreecommitdiff
path: root/arch/arm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm')
-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
40 files changed, 5817 insertions, 4069 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;
-}
-