diff options
Diffstat (limited to 'arch/arm/mach-tegra/board-whistler-baseband.c')
-rw-r--r-- | arch/arm/mach-tegra/board-whistler-baseband.c | 60 |
1 files changed, 52 insertions, 8 deletions
diff --git a/arch/arm/mach-tegra/board-whistler-baseband.c b/arch/arm/mach-tegra/board-whistler-baseband.c index eb50fb2f8237..b602cd3f44c1 100644 --- a/arch/arm/mach-tegra/board-whistler-baseband.c +++ b/arch/arm/mach-tegra/board-whistler-baseband.c @@ -26,8 +26,9 @@ static void baseband_phy_init(void); static void baseband_phy_on(void); -static void baseband_phy_off(void); - +static void baseband_pre_phy_off(void); +static void baseband_post_phy_off(void); +static bool ap2mdm_ack_gpio_off = false; static struct wake_lock mdm_wake_lock; static struct gpio modem_gpios[] = { @@ -58,13 +59,14 @@ static __initdata struct tegra_pingroup_config whistler_null_ulpi_pinmux[] = { static struct tegra_usb_phy_platform_ops ulpi_null_plat_ops = { .init = baseband_phy_init, - .pre_phy_off = baseband_phy_off, + .pre_phy_off = baseband_pre_phy_off, + .post_phy_off = baseband_post_phy_off, .post_phy_on = baseband_phy_on, }; static struct tegra_usb_platform_data tegra_ehci2_ulpi_null_pdata = { .port_otg = false, - .has_hostpc = true, + .has_hostpc = false, .phy_intf = TEGRA_USB_PHY_INTF_ULPI_NULL, .op_mode = TEGRA_USB_OPMODE_HOST, .u_data.host = { @@ -105,6 +107,15 @@ static irqreturn_t mdm_start_thread(int irq, void *data) return IRQ_HANDLED; } +static inline void null_phy_set_tristate(bool enable) +{ + int tristate = (enable) ? TEGRA_TRI_TRISTATE : TEGRA_TRI_NORMAL; + + tegra_pinmux_set_tristate(TEGRA_PINGROUP_UDA, tristate); + tegra_pinmux_set_tristate(TEGRA_PINGROUP_UAA, tristate); + tegra_pinmux_set_tristate(TEGRA_PINGROUP_UAB, tristate); +} + static void baseband_phy_init(void) { static bool phy_init; @@ -117,18 +128,51 @@ static void baseband_phy_init(void) pr_info("%s\n", __func__); } -static void baseband_phy_off(void) +static void baseband_pre_phy_off(void) { /* set AP2MDM_ACK2 high */ gpio_set_value(AP2MDM_ACK2, 1); + ap2mdm_ack_gpio_off = true; +} + +static void baseband_post_phy_off(void) +{ + null_phy_set_tristate(true); } -static void baseband_phy_on (void) +static void baseband_phy_on(void) { - /* set AP2MDM_ACK2 low */ - gpio_set_value(AP2MDM_ACK2, 0); + if (ap2mdm_ack_gpio_off) { + + /* driving linestate using GPIO */ + gpio_set_value(ULPI_D0, 0); + gpio_set_value(ULPI_D1, 0); + + /* driving DIR high */ + gpio_set_value(ULPI_DIR, 1); + + /* remove ULPI tristate */ + null_phy_set_tristate(false); + + gpio_set_value(AP2MDM_ACK2, 0); + + if (gpio_is_valid(MDM2AP_ACK2)) { + int retry = 20000; + while (retry) { + /* poll phy_restore_gpio high */ + if (gpio_get_value(MDM2AP_ACK2)) + break; + retry--; + } + + if (retry == 0) + pr_info("phy_restore_gpio timeout\n"); + } + ap2mdm_ack_gpio_off = false; + } } + static void baseband_start(void) { /* |