aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-tegra/board-whistler-baseband.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-tegra/board-whistler-baseband.c')
-rw-r--r--arch/arm/mach-tegra/board-whistler-baseband.c230
1 files changed, 230 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/board-whistler-baseband.c b/arch/arm/mach-tegra/board-whistler-baseband.c
new file mode 100644
index 00000000000..143d14a8721
--- /dev/null
+++ b/arch/arm/mach-tegra/board-whistler-baseband.c
@@ -0,0 +1,230 @@
1/*
2 * arch/arm/mach-tegra/board-whistler-baseband.c
3 *
4 * Copyright (C) 2011 NVIDIA Corporation
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
17#include <linux/kernel.h>
18#include <linux/init.h>
19#include <linux/module.h>
20#include <linux/moduleparam.h>
21#include <linux/tegra_caif.h>
22#include <mach/tegra_usb_modem_power.h>
23
24#include "board.h"
25#include "board-whistler-baseband.h"
26
27static int baseband_phy_on(void);
28static int baseband_phy_off(void);
29static void baseband_phy_restore_start(void);
30static void baseband_phy_restore_end(void);
31
32static struct wake_lock mdm_wake_lock;
33
34static struct gpio modem_gpios[] = {
35 {MODEM_PWR_ON, GPIOF_OUT_INIT_LOW, "MODEM PWR ON"},
36 {MODEM_RESET, GPIOF_IN, "MODEM RESET"},
37 {BB_RST_OUT, GPIOF_IN, "BB RST OUT"},
38 {MDM2AP_ACK, GPIOF_IN, "MDM2AP_ACK"},
39 {AP2MDM_ACK2, GPIOF_OUT_INIT_HIGH, "AP2MDM ACK2"},
40 {AP2MDM_ACK, GPIOF_OUT_INIT_LOW, "AP2MDM ACK"},
41 {ULPI_STP, GPIOF_IN, "ULPI_STP"},
42 {ULPI_DIR, GPIOF_OUT_INIT_LOW, "ULPI_DIR"},
43 {ULPI_D0, GPIOF_OUT_INIT_LOW, "ULPI_D0"},
44 {ULPI_D1, GPIOF_OUT_INIT_LOW, "ULPI_D1"},
45};
46
47static __initdata struct tegra_pingroup_config whistler_null_ulpi_pinmux[] = {
48 {TEGRA_PINGROUP_UAA, TEGRA_MUX_ULPI, TEGRA_PUPD_NORMAL,
49 TEGRA_TRI_NORMAL},
50 {TEGRA_PINGROUP_UAB, TEGRA_MUX_ULPI, TEGRA_PUPD_NORMAL,
51 TEGRA_TRI_NORMAL},
52 {TEGRA_PINGROUP_UDA, TEGRA_MUX_ULPI, TEGRA_PUPD_NORMAL,
53 TEGRA_TRI_NORMAL},
54 {TEGRA_PINGROUP_UAC, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL,
55 TEGRA_TRI_NORMAL},
56 {TEGRA_PINGROUP_SDIO1, TEGRA_MUX_UARTA, TEGRA_PUPD_PULL_UP,
57 TEGRA_TRI_NORMAL},
58};
59
60static struct tegra_ulpi_trimmer e1219_trimmer = { 10, 1, 1, 1 };
61
62static struct tegra_ulpi_config ehci2_null_ulpi_phy_config = {
63 .trimmer = &e1219_trimmer,
64 .post_phy_on = baseband_phy_on,
65 .pre_phy_off = baseband_phy_off,
66 .phy_restore_start = baseband_phy_restore_start,
67 .phy_restore_end = baseband_phy_restore_end,
68 .phy_restore_gpio = MDM2AP_ACK,
69 .ulpi_dir_gpio = ULPI_DIR,
70 .ulpi_d0_gpio = ULPI_D0,
71 .ulpi_d1_gpio = ULPI_D1,
72};
73
74static struct tegra_ehci_platform_data ehci2_null_ulpi_platform_data = {
75 .operating_mode = TEGRA_USB_HOST,
76 .power_down_on_bus_suspend = 0,
77 .phy_config = &ehci2_null_ulpi_phy_config,
78 .phy_type = TEGRA_USB_PHY_TYPE_NULL_ULPI,
79};
80
81static int __init tegra_null_ulpi_init(void)
82{
83 tegra_ehci2_device.dev.platform_data = &ehci2_null_ulpi_platform_data;
84 platform_device_register(&tegra_ehci2_device);
85 return 0;
86}
87
88static irqreturn_t mdm_start_thread(int irq, void *data)
89{
90 if (gpio_get_value(BB_RST_OUT)) {
91 pr_info("BB_RST_OUT high\n");
92 } else {
93 pr_info("BB_RST_OUT low\n");
94 /* hold wait lock to complete the enumeration */
95 wake_lock_timeout(&mdm_wake_lock, HZ * 10);
96 }
97
98 return IRQ_HANDLED;
99}
100
101static int baseband_phy_on(void)
102{
103 static bool phy_init;
104
105 if (!phy_init) {
106 /* set AP2MDM_ACK2 low */
107 gpio_set_value(AP2MDM_ACK2, 0);
108 phy_init = true;
109 }
110 pr_info("%s\n", __func__);
111 return 0;
112}
113
114static int baseband_phy_off(void)
115{
116 pr_info("%s\n", __func__);
117 return 0;
118}
119
120static void baseband_phy_restore_start(void)
121{
122 /* set AP2MDM_ACK2 high */
123 gpio_set_value(AP2MDM_ACK2, 1);
124}
125
126static void baseband_phy_restore_end(void)
127{
128 /* set AP2MDM_ACK2 low */
129 gpio_set_value(AP2MDM_ACK2, 0);
130}
131
132static void baseband_start(void)
133{
134 /*
135 * Leave baseband powered OFF.
136 * User-space daemons will take care of powering it up.
137 */
138 pr_info("%s\n", __func__);
139 gpio_set_value(MODEM_PWR_ON, 0);
140}
141
142static void baseband_reset(void)
143{
144 /* Initiate power cycle on baseband sub system */
145 pr_info("%s\n", __func__);
146 gpio_set_value(MODEM_PWR_ON, 0);
147 mdelay(200);
148 gpio_set_value(MODEM_PWR_ON, 1);
149}
150
151static int baseband_init(void)
152{
153 int irq;
154 int ret;
155
156 ret = gpio_request_array(modem_gpios, ARRAY_SIZE(modem_gpios));
157 if (ret)
158 return ret;
159
160 /* enable pull-up for BB_RST_OUT */
161 tegra_pinmux_set_pullupdown(TEGRA_PINGROUP_UAC,
162 TEGRA_PUPD_PULL_UP);
163
164 tegra_gpio_enable(MODEM_PWR_ON);
165 tegra_gpio_enable(MODEM_RESET);
166 tegra_gpio_enable(AP2MDM_ACK2);
167 tegra_gpio_enable(BB_RST_OUT);
168 tegra_gpio_enable(AP2MDM_ACK);
169 tegra_gpio_enable(MDM2AP_ACK);
170 tegra_gpio_enable(TEGRA_GPIO_PY3);
171 tegra_gpio_enable(TEGRA_GPIO_PY1);
172 tegra_gpio_enable(TEGRA_GPIO_PO1);
173 tegra_gpio_enable(TEGRA_GPIO_PO2);
174
175 /* export GPIO for user space access through sysfs */
176 gpio_export(MODEM_PWR_ON, false);
177
178 /* phy init */
179 tegra_null_ulpi_init();
180
181 wake_lock_init(&mdm_wake_lock, WAKE_LOCK_SUSPEND, "mdm_lock");
182
183 /* enable IRQ for BB_RST_OUT */
184 irq = gpio_to_irq(BB_RST_OUT);
185
186 ret = request_threaded_irq(irq, NULL, mdm_start_thread,
187 IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
188 "mdm_start", NULL);
189 if (ret < 0) {
190 pr_err("%s: request_threaded_irq error\n", __func__);
191 return ret;
192 }
193
194 ret = enable_irq_wake(irq);
195 if (ret) {
196 pr_err("%s: enable_irq_wake error\n", __func__);
197 free_irq(irq, NULL);
198 return ret;
199 }
200
201 return 0;
202}
203
204static const struct tegra_modem_operations baseband_operations = {
205 .init = baseband_init,
206 .start = baseband_start,
207 .reset = baseband_reset,
208};
209
210static struct tegra_usb_modem_power_platform_data baseband_pdata = {
211 .ops = &baseband_operations,
212 .wake_gpio = MDM2AP_ACK2,
213 .flags = IRQF_TRIGGER_FALLING,
214};
215
216static struct platform_device icera_baseband_device = {
217 .name = "tegra_usb_modem_power",
218 .id = -1,
219 .dev = {
220 .platform_data = &baseband_pdata,
221 },
222};
223
224int __init whistler_baseband_init(void)
225{
226 tegra_pinmux_config_table(whistler_null_ulpi_pinmux,
227 ARRAY_SIZE(whistler_null_ulpi_pinmux));
228 platform_device_register(&icera_baseband_device);
229 return 0;
230}