summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-tegra/board-whistler-baseband.c368
-rw-r--r--arch/arm/mach-tegra/board-whistler-baseband.h11
-rw-r--r--arch/arm/mach-tegra/board-whistler.c99
3 files changed, 224 insertions, 254 deletions
diff --git a/arch/arm/mach-tegra/board-whistler-baseband.c b/arch/arm/mach-tegra/board-whistler-baseband.c
index 1d3cc7c1f222..ff376d260306 100644
--- a/arch/arm/mach-tegra/board-whistler-baseband.c
+++ b/arch/arm/mach-tegra/board-whistler-baseband.c
@@ -19,175 +19,31 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/tegra_caif.h>
-#include "board-whistler-baseband.h"
-
-unsigned long baseband_type = BOARD_WHISTLER_BASEBAND_U3XX;
-
-module_param(baseband_type, ulong, 0644);
-MODULE_PARM_DESC(baseband_type, "baseband type");
-
-static struct tegra_clk_init_table u3xx_clk[] = {
- /* spi slave controller clock @ 4 x 13 Mhz interface clock */
- { "sbc1", "pll_c", 52000000, true},
- { NULL, NULL, 0, 0},
-};
-
-static struct tegra_clk_init_table n731_clk[] = {
- /* spi master controller clock @ 4 x 12 Mhz interface clock */
- { "sbc1", "pll_c", 48000000, true},
- { NULL, NULL, 0, 0},
-};
-
-static struct tegra_clk_init_table spi_loopback_clk[] = {
- /* spi slave / master controller clocks @ 4 x max interface clock */
- { "sbc1", "pll_c", 60000000, true},
- { "sbc2", "pll_c", 60000000, true},
- { NULL, NULL, 0, 0},
-};
-
-static struct tegra_clk_init_table hsic_clk[] = {
- { NULL, NULL, 0, 0},
-};
-
-static struct platform_device *u3xx_device[] = {
- /* spi slave */
- &tegra_spi_slave_device1,
-};
+#include <mach/tegra_usb_modem_power.h>
-static struct platform_device *n731_device[] = {
- /* spi master */
- &tegra_spi_device1,
-};
-
-static struct platform_device *spi_loopback_device[] = {
- /* spi slave / master */
- &tegra_spi_slave_device1,
- &tegra_spi_device2,
-};
-
-static struct platform_device *hsic_device[] = {
-};
-
-struct tegra_caif_platform_data tegra_whistler_u3xx_plat_data = {
- .reset = TEGRA_CAIF_SSPI_GPIO_RESET,
- .power = TEGRA_CAIF_SSPI_GPIO_POWER,
- .awr = TEGRA_CAIF_SSPI_GPIO_AWR,
- .cwr = TEGRA_CAIF_SSPI_GPIO_CWR,
- .spi_int = TEGRA_CAIF_SSPI_GPIO_SPI_INT,
- .spi_ss = TEGRA_CAIF_SSPI_GPIO_SS,
-};
-
-static struct spi_board_info u3xx_spi_board_info[] = {
- /* spi slave */
- {
- .modalias = "baseband_spi_slave0.0",
- .bus_num = 0,
- .chip_select = 0,
- .mode = SPI_MODE_0,
- .max_speed_hz = 52000000,
- .platform_data = &tegra_whistler_u3xx_plat_data,
- .irq = 0,
- },
-};
+#include "board.h"
+#include "board-whistler-baseband.h"
-static struct spi_board_info n731_spi_board_info[] = {
- /* spi master */
- {
- .modalias = "spi_ipc",
- .bus_num = 0,
- .chip_select = 0,
- .mode = SPI_MODE_1,
- .max_speed_hz = 12000000,
- .platform_data = NULL,
- .irq = 0,
- },
-};
+static int baseband_phy_on(void);
+static int baseband_phy_off(void);
+static void baseband_phy_restore_start(void);
+static void baseband_phy_restore_end(void);
-static struct spi_board_info spi_loopback_spi_board_info[] = {
- /* spi slave <---> spi master */
- {
- .modalias = "baseband_loopback",
- .bus_num = 0,
- .chip_select = 0,
- .mode = SPI_MODE_0,
- .max_speed_hz = 13000000,
- .platform_data = &tegra_whistler_u3xx_plat_data,
- .irq = 0,
- },
- {
- .modalias = "baseband_spi_master1.1",
- .bus_num = 1,
- .chip_select = 1,
- .mode = SPI_MODE_0,
- .max_speed_hz = 13000000,
- .platform_data = NULL,
- .irq = 0,
- },
-};
+static struct wake_lock mdm_wake_lock;
-static struct whistler_baseband whistler_baseband[] = {
- [BOARD_WHISTLER_BASEBAND_U3XX] = {
- .clk_init = u3xx_clk,
- .platform_device = u3xx_device,
- .platform_device_size = ARRAY_SIZE(u3xx_device),
- .spi_board_info = u3xx_spi_board_info,
- .spi_board_info_size = ARRAY_SIZE(u3xx_spi_board_info),
- },
- [BOARD_WHISTLER_BASEBAND_N731] = {
- .clk_init = n731_clk,
- .platform_device = n731_device,
- .platform_device_size = ARRAY_SIZE(n731_device),
- .spi_board_info = n731_spi_board_info,
- .spi_board_info_size = ARRAY_SIZE(n731_spi_board_info),
- },
- [BOARD_WHISTLER_BASEBAND_SPI_LOOPBACK] = {
- .clk_init = spi_loopback_clk,
- .platform_device = spi_loopback_device,
- .platform_device_size = ARRAY_SIZE(spi_loopback_device),
- .spi_board_info = spi_loopback_spi_board_info,
- .spi_board_info_size = ARRAY_SIZE(spi_loopback_spi_board_info),
- },
- [BOARD_WHISTLER_BASEBAND_HSIC] = {
- .clk_init = hsic_clk,
- .platform_device = hsic_device,
- .platform_device_size = ARRAY_SIZE(hsic_device),
- },
+static struct gpio modem_gpios[] = {
+ {MODEM_PWR_ON, GPIOF_OUT_INIT_LOW, "MODEM PWR ON"},
+ {MODEM_RESET, GPIOF_IN, "MODEM RESET"},
+ {BB_RST_OUT, GPIOF_IN, "BB RST OUT"},
+ {MDM2AP_ACK, GPIOF_IN, "MDM2AP_ACK"},
+ {AP2MDM_ACK2, GPIOF_OUT_INIT_HIGH, "AP2MDM ACK2"},
+ {AP2MDM_ACK, GPIOF_OUT_INIT_LOW, "AP2MDM ACK"},
+ {TEGRA_GPIO_PY3, GPIOF_IN, "ULPI_STP"},
+ {TEGRA_GPIO_PY1, GPIOF_OUT_INIT_LOW, "ULPI_DIR"},
+ {TEGRA_GPIO_PO1, GPIOF_OUT_INIT_LOW, "ULPI_D0"},
+ {TEGRA_GPIO_PO2, GPIOF_OUT_INIT_LOW, "ULPI_D1"},
};
-int whistler_baseband_init(void)
-{
- int idx;
- int err;
- idx = baseband_type;
-
- if (whistler_baseband[idx].clk_init)
- tegra_clk_init_from_table(whistler_baseband[idx].clk_init);
-
- if (whistler_baseband[idx].platform_device_size)
- platform_add_devices(whistler_baseband[idx].platform_device,
- whistler_baseband[idx].platform_device_size);
-
- if (whistler_baseband[idx].spi_board_info_size) {
- err = spi_register_board_info(
- whistler_baseband[idx].spi_board_info,
- whistler_baseband[idx].spi_board_info_size);
- if (err < 0)
- pr_err("%s: spi_register_board returned error %d\n",
- __func__, err);
- }
-
- tegra_gpio_enable(TEGRA_CAIF_SSPI_GPIO_RESET);
- tegra_gpio_enable(TEGRA_CAIF_SSPI_GPIO_POWER);
- tegra_gpio_enable(TEGRA_CAIF_SSPI_GPIO_AWR);
- tegra_gpio_enable(TEGRA_CAIF_SSPI_GPIO_CWR);
- tegra_gpio_enable(TEGRA_CAIF_SSPI_GPIO_SPI_INT);
- tegra_gpio_enable(TEGRA_CAIF_SSPI_GPIO_SS);
- return 0;
-}
-
-static int rainbow_570_reset(void);
-static int rainbow_570_handshake(void);
-
static __initdata struct tegra_pingroup_config whistler_null_ulpi_pinmux[] = {
{TEGRA_PINGROUP_UAA, TEGRA_MUX_ULPI, TEGRA_PUPD_NORMAL,
TEGRA_TRI_NORMAL},
@@ -197,20 +53,25 @@ static __initdata struct tegra_pingroup_config whistler_null_ulpi_pinmux[] = {
TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_UAC, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL,
TEGRA_TRI_NORMAL},
+ {TEGRA_PINGROUP_SDIO1, TEGRA_MUX_UARTA, TEGRA_PUPD_PULL_UP,
+ TEGRA_TRI_NORMAL},
};
-static struct tegra_ulpi_trimmer e951_trimmer = { 10, 1, 1, 1 };
+static struct tegra_ulpi_trimmer e1219_trimmer = { 10, 1, 1, 1 };
static struct tegra_ulpi_config ehci2_null_ulpi_phy_config = {
- .trimmer = &e951_trimmer,
- .pre_phy_on = rainbow_570_reset,
- .post_phy_on = rainbow_570_handshake,
+ .trimmer = &e1219_trimmer,
+ .post_phy_on = baseband_phy_on,
+ .pre_phy_off = baseband_phy_off,
+ .phy_restore_start = baseband_phy_restore_start,
+ .phy_restore_end = baseband_phy_restore_end,
};
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 int __init tegra_null_ulpi_init(void)
@@ -220,87 +81,146 @@ static int __init tegra_null_ulpi_init(void)
return 0;
}
-static int __init rainbow_570_init(void)
+static irqreturn_t mdm_start_thread(int irq, void *data)
{
- int ret;
-
- ret = gpio_request(MODEM_PWR_ON, "mdm_power");
- if (ret)
- return ret;
-
- ret = gpio_request(MODEM_RESET, "mdm_reset");
- if (ret) {
- gpio_free(MODEM_PWR_ON);
- return ret;
- }
- ret = gpio_request(AWR, "mdm_awr");
- if (ret) {
- gpio_free(MODEM_PWR_ON);
- gpio_free(MODEM_RESET);
- return ret;
- }
- ret = gpio_request(CWR, "mdm_cwr");
- if (ret) {
- gpio_free(MODEM_PWR_ON);
- gpio_free(MODEM_RESET);
- gpio_free(AWR);
- return ret;
+ if (gpio_get_value(BB_RST_OUT)) {
+ pr_info("BB_RST_OUT high\n");
+ } else {
+ pr_info("BB_RST_OUT low\n");
+ /* hold wait lock to complete the enumeration */
+ wake_lock_timeout(&mdm_wake_lock, HZ * 10);
}
- tegra_gpio_enable(MODEM_PWR_ON);
- tegra_gpio_enable(MODEM_RESET);
- tegra_gpio_enable(AWR);
- tegra_gpio_enable(CWR);
+ return IRQ_HANDLED;
+}
- gpio_direction_output(MODEM_PWR_ON, 0);
- gpio_direction_output(MODEM_RESET, 0);
- gpio_direction_output(AWR, 0);
- gpio_direction_input(CWR);
+static int baseband_phy_on(void)
+{
+ static bool phy_init;
+ if (!phy_init) {
+ /* set AP2MDM_ACK2 low */
+ gpio_set_value(AP2MDM_ACK2, 0);
+ phy_init = true;
+ }
+ pr_info("%s\n", __func__);
return 0;
}
-static int rainbow_570_reset(void)
+static int baseband_phy_off(void)
{
- gpio_set_value(AWR, 0);
- gpio_set_value(MODEM_PWR_ON, 0);
- gpio_set_value(MODEM_RESET, 0);
- mdelay(300);
- gpio_set_value(MODEM_RESET, 1);
- mdelay(300);
-
- /* pulse modem power on for 1200 ms */
- gpio_set_value(MODEM_PWR_ON, 1);
- mdelay(1200);
- gpio_set_value(MODEM_PWR_ON, 0);
- mdelay(100);
-
+ pr_info("%s\n", __func__);
return 0;
}
-static int rainbow_570_handshake(void)
+static void baseband_phy_restore_start(void)
+{
+ /* set AP2MDM_ACK2 high */
+ gpio_set_value(AP2MDM_ACK2, 1);
+}
+
+static void baseband_phy_restore_end(void)
{
- /* set AWR high */
- gpio_set_value(AWR, 1);
+ /* set AP2MDM_ACK2 low */
+ gpio_set_value(AP2MDM_ACK2, 0);
+}
- /* wait for CWR high if modem firmware requires */
+static void baseband_start(void)
+{
+ /*
+ * Leave baseband powered OFF.
+ * User-space daemons will take care of powering it up.
+ */
+ pr_info("%s\n", __func__);
+ gpio_set_value(MODEM_PWR_ON, 0);
+}
- return 0;
+static void baseband_reset(void)
+{
+ /* Initiate power cycle on baseband sub system */
+ pr_info("%s\n", __func__);
+ gpio_set_value(MODEM_PWR_ON, 0);
+ mdelay(200);
+ gpio_set_value(MODEM_PWR_ON, 1);
}
-int __init whistler_baseband_ph450_init(void)
+static int baseband_init(void)
{
+ int irq;
int ret;
- tegra_pinmux_config_table(whistler_null_ulpi_pinmux,
- ARRAY_SIZE(whistler_null_ulpi_pinmux));
+ ret = gpio_request_array(modem_gpios, ARRAY_SIZE(modem_gpios));
+ if (ret)
+ return ret;
+
+ /* enable pull-up for BB_RST_OUT */
+ tegra_pinmux_set_pullupdown(TEGRA_PINGROUP_UAC,
+ TEGRA_PUPD_PULL_UP);
+
+ tegra_gpio_enable(MODEM_PWR_ON);
+ tegra_gpio_enable(MODEM_RESET);
+ tegra_gpio_enable(AP2MDM_ACK2);
+ tegra_gpio_enable(BB_RST_OUT);
+ tegra_gpio_enable(AP2MDM_ACK);
+ tegra_gpio_enable(MDM2AP_ACK);
+ tegra_gpio_enable(TEGRA_GPIO_PY3);
+ tegra_gpio_enable(TEGRA_GPIO_PY1);
+ tegra_gpio_enable(TEGRA_GPIO_PO1);
+ tegra_gpio_enable(TEGRA_GPIO_PO2);
+
+ /* export GPIO for user space access through sysfs */
+ gpio_export(MODEM_PWR_ON, false);
+
+ /* phy init */
+ tegra_null_ulpi_init();
+
+ wake_lock_init(&mdm_wake_lock, WAKE_LOCK_SUSPEND, "mdm_lock");
- ret = rainbow_570_init();
+ /* enable IRQ for BB_RST_OUT */
+ irq = gpio_to_irq(BB_RST_OUT);
+
+ ret = request_threaded_irq(irq, NULL, mdm_start_thread,
+ IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+ "mdm_start", NULL);
+ if (ret < 0) {
+ pr_err("%s: request_threaded_irq error\n", __func__);
+ return ret;
+ }
+
+ ret = enable_irq_wake(irq);
if (ret) {
- pr_err("modem init failed\n");
+ pr_err("%s: enable_irq_wake error\n", __func__);
+ free_irq(irq, NULL);
return ret;
}
- tegra_null_ulpi_init();
+ return 0;
+}
+
+static const struct tegra_modem_operations baseband_operations = {
+ .init = baseband_init,
+ .start = baseband_start,
+ .reset = baseband_reset,
+};
+
+static struct tegra_usb_modem_power_platform_data baseband_pdata = {
+ .ops = &baseband_operations,
+ .wake_gpio = MDM2AP_ACK2,
+ .flags = IRQF_TRIGGER_FALLING,
+};
+
+static struct platform_device icera_baseband_device = {
+ .name = "tegra_usb_modem_power",
+ .id = -1,
+ .dev = {
+ .platform_data = &baseband_pdata,
+ },
+};
+
+int __init whistler_baseband_init(void)
+{
+ tegra_pinmux_config_table(whistler_null_ulpi_pinmux,
+ ARRAY_SIZE(whistler_null_ulpi_pinmux));
+ platform_device_register(&icera_baseband_device);
return 0;
}
diff --git a/arch/arm/mach-tegra/board-whistler-baseband.h b/arch/arm/mach-tegra/board-whistler-baseband.h
index c8f561669468..b9e107f166f4 100644
--- a/arch/arm/mach-tegra/board-whistler-baseband.h
+++ b/arch/arm/mach-tegra/board-whistler-baseband.h
@@ -25,10 +25,12 @@
#include <linux/resource.h>
#include <linux/platform_device.h>
#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/wakelock.h>
#include <asm/mach-types.h>
#include <mach/pinmux.h>
#include <mach/spi.h>
-
#include "clock.h"
#include "devices.h"
#include "gpio-names.h"
@@ -54,9 +56,12 @@
#define SPI_INT TEGRA_GPIO_PO6
#define SPI_SLAVE_SEL TEGRA_GPIO_PV2
-/* PH450 */
+/* Icera 450 GPIO */
+#define AP2MDM_ACK TEGRA_GPIO_PZ0
+#define MDM2AP_ACK TEGRA_GPIO_PY6
#define AP2MDM_ACK2 TEGRA_GPIO_PU2
#define MDM2AP_ACK2 TEGRA_GPIO_PV2
+#define BB_RST_OUT TEGRA_GPIO_PV3
struct whistler_baseband {
@@ -68,6 +73,4 @@ struct whistler_baseband {
};
int whistler_baseband_init(void);
-
#endif /* BOARD_WHISTLER_BASEBAND_H */
-
diff --git a/arch/arm/mach-tegra/board-whistler.c b/arch/arm/mach-tegra/board-whistler.c
index 7df0fc20e0e7..9e5ea0d19df2 100644
--- a/arch/arm/mach-tegra/board-whistler.c
+++ b/arch/arm/mach-tegra/board-whistler.c
@@ -63,7 +63,30 @@
#define USB1_VBUS_GPIO TCA6416_GPIO_BASE
-static struct plat_serial8250_port debug_uart_platform_data[] = {
+static struct plat_serial8250_port debug_uartb_platform_data[] = {
+ {
+ .membase = IO_ADDRESS(TEGRA_UARTB_BASE),
+ .mapbase = TEGRA_UARTB_BASE,
+ .irq = INT_UARTB,
+ .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
+ .type = PORT_TEGRA,
+ .iotype = UPIO_MEM,
+ .regshift = 2,
+ .uartclk = 216000000,
+ }, {
+ .flags = 0,
+ }
+};
+
+static struct platform_device debug_uartb = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_PLATFORM,
+ .dev = {
+ .platform_data = debug_uartb_platform_data,
+ },
+};
+
+static struct plat_serial8250_port debug_uarta_platform_data[] = {
{
.membase = IO_ADDRESS(TEGRA_UARTA_BASE),
.mapbase = TEGRA_UARTA_BASE,
@@ -78,13 +101,14 @@ static struct plat_serial8250_port debug_uart_platform_data[] = {
}
};
-static struct platform_device debug_uart = {
+static struct platform_device debug_uarta = {
.name = "serial8250",
.id = PLAT8250_DEV_PLATFORM,
.dev = {
- .platform_data = debug_uart_platform_data,
+ .platform_data = debug_uarta_platform_data,
},
};
+
static struct platform_device *whistler_uart_devices[] __initdata = {
&tegra_uarta_device,
&tegra_uartb_device,
@@ -104,30 +128,54 @@ static void __init uart_debug_init(void)
unsigned long rate;
struct clk *debug_uart_clk;
struct clk *c;
-
- /* UARTA is the debug port. */
- pr_info("Selecting UARTA as the debug console\n");
- whistler_uart_devices[0] = &debug_uart;
- debug_uart_port_base = ((struct plat_serial8250_port *)(
- debug_uarta_device.dev.platform_data))->mapbase;
- debug_uart_clk = clk_get_sys("serial8250.0", "uarta");
-
- /* Clock enable for the debug channel */
- if (!IS_ERR_OR_NULL(debug_uart_clk)) {
- rate = debug_uart_platform_data[0].uartclk;
- pr_info("The debug console clock name is %s\n",
+ int modem_id = tegra_get_modem_id();
+
+ if (modem_id == 0x1) {
+ /* UARTB is the debug port. */
+ pr_info("Selecting UARTB as the debug console\n");
+ whistler_uart_devices[1] = &debug_uartb;
+ debug_uart_clk = clk_get_sys("serial8250.0", "uartb");
+
+ /* Clock enable for the debug channel */
+ if (!IS_ERR_OR_NULL(debug_uart_clk)) {
+ rate = debug_uartb_platform_data[0].uartclk;
+ pr_info("The debug console clock name is %s\n",
+ debug_uart_clk->name);
+ c = tegra_get_clock_by_name("pll_p");
+ if (IS_ERR_OR_NULL(c))
+ pr_err("Not getting the parent clock pll_p\n");
+ else
+ clk_set_parent(debug_uart_clk, c);
+
+ clk_enable(debug_uart_clk);
+ clk_set_rate(debug_uart_clk, rate);
+ } else {
+ pr_err("Not getting the clock %s for debug console\n",
debug_uart_clk->name);
- c = tegra_get_clock_by_name("pll_p");
- if (IS_ERR_OR_NULL(c))
- pr_err("Not getting the parent clock pll_p\n");
- else
- clk_set_parent(debug_uart_clk, c);
-
- clk_enable(debug_uart_clk);
- clk_set_rate(debug_uart_clk, rate);
+ }
} else {
- pr_err("Not getting the clock %s for debug console\n",
- debug_uart_clk->name);
+ /* UARTA is the debug port. */
+ pr_info("Selecting UARTA as the debug console\n");
+ whistler_uart_devices[0] = &debug_uarta;
+ debug_uart_clk = clk_get_sys("serial8250.0", "uarta");
+
+ /* Clock enable for the debug channel */
+ if (!IS_ERR_OR_NULL(debug_uart_clk)) {
+ rate = debug_uarta_platform_data[0].uartclk;
+ pr_info("The debug console clock name is %s\n",
+ debug_uart_clk->name);
+ c = tegra_get_clock_by_name("pll_p");
+ if (IS_ERR_OR_NULL(c))
+ pr_err("Not getting the parent clock pll_p\n");
+ else
+ clk_set_parent(debug_uart_clk, c);
+
+ clk_enable(debug_uart_clk);
+ clk_set_rate(debug_uart_clk, rate);
+ } else {
+ pr_err("Not getting the clock %s for debug console\n",
+ debug_uart_clk->name);
+ }
}
}
@@ -153,7 +201,6 @@ static void __init whistler_uart_init(void)
tegra_uartb_device.dev.platform_data = &whistler_uart_pdata;
tegra_uartc_device.dev.platform_data = &whistler_uart_pdata;
- /* Register low speed only if it is selected */
if (!is_tegra_debug_uartport_hs())
uart_debug_init();