diff options
-rw-r--r-- | arch/arm/mach-tegra/board-whistler-baseband.c | 368 | ||||
-rw-r--r-- | arch/arm/mach-tegra/board-whistler-baseband.h | 11 | ||||
-rw-r--r-- | arch/arm/mach-tegra/board-whistler.c | 99 |
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(); |