ARM: tegra: enterprise: Remove tegra_gpio_enb/dis
[linux-2.6.git] / arch / arm / mach-tegra / board-enterprise-baseband.c
1 /*
2  * arch/arm/mach-tegra/board-enterprise-baseband.c
3  *
4  * Copyright (c) 2011, NVIDIA Corporation.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14  * more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19  */
20
21 #include <linux/resource.h>
22 #include <linux/platform_device.h>
23 #include <linux/delay.h>
24 #include <linux/gpio.h>
25 #include <linux/interrupt.h>
26 #include <linux/irq.h>
27 #include <linux/err.h>
28 #include <linux/wakelock.h>
29 #include <linux/platform_data/tegra_usb.h>
30 #include <asm/mach-types.h>
31 #include <asm/mach/arch.h>
32 #include <mach/pinmux.h>
33 #include <mach/usb_phy.h>
34 #include <mach/tegra_usb_modem_power.h>
35 #include "devices.h"
36 #include "gpio-names.h"
37
38 /* Tegra3 BB GPIO */
39 #define MODEM_PWR_ON    TEGRA_GPIO_PE0
40 #define MODEM_RESET     TEGRA_GPIO_PE1
41 #define BB_RST_OUT      TEGRA_GPIO_PV1
42
43 /* Icera BB GPIO */
44 #define AP2MDM_ACK      TEGRA_GPIO_PE3
45 #define MDM2AP_ACK      TEGRA_GPIO_PU5
46 #define AP2MDM_ACK2     TEGRA_GPIO_PE2
47 #define MDM2AP_ACK2     TEGRA_GPIO_PV0
48
49 /* ULPI GPIO */
50 #define ULPI_STP        TEGRA_GPIO_PY3
51 #define ULPI_DIR        TEGRA_GPIO_PY1
52 #define ULPI_D0         TEGRA_GPIO_PO1
53 #define ULPI_D1         TEGRA_GPIO_PO2
54
55 static struct wake_lock mdm_wake_lock;
56
57 static struct gpio modem_gpios[] = {
58         {MODEM_PWR_ON, GPIOF_OUT_INIT_LOW, "MODEM PWR ON"},
59         {MODEM_RESET, GPIOF_IN, "MODEM RESET"},
60         {BB_RST_OUT, GPIOF_IN, "BB RST OUT"},
61         {MDM2AP_ACK, GPIOF_IN, "MDM2AP_ACK"},
62         {AP2MDM_ACK2, GPIOF_OUT_INIT_HIGH, "AP2MDM ACK2"},
63         {AP2MDM_ACK, GPIOF_OUT_INIT_LOW, "AP2MDM ACK"},
64         {ULPI_STP, GPIOF_IN, "ULPI_STP"},
65         {ULPI_DIR, GPIOF_OUT_INIT_LOW, "ULPI_DIR"},
66         {ULPI_D0, GPIOF_OUT_INIT_LOW, "ULPI_D0"},
67         {ULPI_D1, GPIOF_OUT_INIT_LOW, "ULPI_D1"},
68 };
69
70 static void baseband_phy_init(void);
71 static void baseband_phy_on(void);
72 static void baseband_pre_phy_off(void);
73 static void baseband_post_phy_off(void);
74 static bool ap2mdm_ack_gpio_off = false;
75
76 static struct tegra_usb_phy_platform_ops ulpi_null_plat_ops = {
77         .init = baseband_phy_init,
78         .pre_phy_off = baseband_pre_phy_off,
79         .post_phy_off = baseband_post_phy_off,
80         .post_phy_on = baseband_phy_on,
81 };
82
83 static struct tegra_usb_platform_data tegra_ehci2_ulpi_null_pdata = {
84         .port_otg = false,
85         .has_hostpc = true,
86         .phy_intf = TEGRA_USB_PHY_INTF_ULPI_NULL,
87         .op_mode        = TEGRA_USB_OPMODE_HOST,
88         .u_data.host = {
89                 .vbus_gpio = -1,
90                 .vbus_reg = NULL,
91                 .hot_plug = false,
92                 .remote_wakeup_supported = false,
93                 .power_off_on_suspend = true,
94         },
95         .u_cfg.ulpi = {
96                 .shadow_clk_delay = 10,
97                 .clock_out_delay = 1,
98                 .data_trimmer = 1,
99                 .stpdirnxt_trimmer = 1,
100                 .dir_trimmer = 1,
101                 .clk = NULL,
102         },
103         .ops = &ulpi_null_plat_ops,
104 };
105
106 static int __init tegra_null_ulpi_init(void)
107 {
108         tegra_ehci2_device.dev.platform_data = &tegra_ehci2_ulpi_null_pdata;
109         platform_device_register(&tegra_ehci2_device);
110         return 0;
111 }
112
113 static irqreturn_t mdm_start_thread(int irq, void *data)
114 {
115         if (gpio_get_value(BB_RST_OUT)) {
116                 pr_info("BB_RST_OUT high\n");
117         } else {
118                 pr_info("BB_RST_OUT low\n");
119         }
120
121         /* hold wait lock to complete the enumeration */
122         wake_lock_timeout(&mdm_wake_lock, HZ * 10);
123
124         return IRQ_HANDLED;
125 }
126
127 static void baseband_phy_init(void)
128 {
129         static bool phy_init = false;
130
131         if (!phy_init) {
132                 /* set AP2MDM_ACK2 low */
133                 gpio_set_value(AP2MDM_ACK2, 0);
134                 phy_init = true;
135         }
136         pr_info("%s\n", __func__);
137 }
138
139 static inline void null_phy_set_tristate(bool enable)
140 {
141         int tristate = (enable) ? TEGRA_TRI_TRISTATE : TEGRA_TRI_NORMAL;
142
143         tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA0, tristate);
144         tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA1, tristate);
145         tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA2, tristate);
146         tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA3, tristate);
147         tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA4, tristate);
148         tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA5, tristate);
149         tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA6, tristate);
150         tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DATA7, tristate);
151         tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_NXT, tristate);
152
153         if (enable)
154                 tegra_pinmux_set_tristate(TEGRA_PINGROUP_ULPI_DIR, tristate);
155 }
156
157
158 static void baseband_post_phy_off(void)
159 {
160         null_phy_set_tristate(true);
161 }
162
163
164 static void baseband_pre_phy_off(void)
165 {
166         /* set AP2MDM_ACK2 high */
167         gpio_set_value(AP2MDM_ACK2, 1);
168         ap2mdm_ack_gpio_off = true;
169 }
170
171 static void baseband_phy_on(void)
172 {
173         if (ap2mdm_ack_gpio_off) {
174
175                 /* driving linestate using GPIO */
176                 gpio_set_value(ULPI_D0, 0);
177                 gpio_set_value(ULPI_D1, 0);
178
179                 /* remove ULPI tristate */
180                 null_phy_set_tristate(false);
181
182                 gpio_set_value(AP2MDM_ACK2, 0);
183
184                 if (gpio_is_valid(MDM2AP_ACK2)) {
185                         int retry = 20000;
186                         while (retry) {
187                                 /* poll phy_restore_gpio high */
188                                 if (gpio_get_value(MDM2AP_ACK2))
189                                         break;
190                                 retry--;
191                         }
192
193                         if (retry == 0)
194                                 pr_info("phy_restore_gpio timeout\n");
195                 }
196                 ap2mdm_ack_gpio_off = false;
197         }
198 }
199
200 static void baseband_start(void)
201 {
202         /*
203          *  Leave baseband powered OFF.
204          *  User-space daemons will take care of powering it up.
205          */
206         pr_info("%s\n", __func__);
207         gpio_set_value(MODEM_PWR_ON, 0);
208 }
209
210 static void baseband_reset(void)
211 {
212         /* Initiate power cycle on baseband sub system */
213         pr_info("%s\n", __func__);
214         gpio_set_value(MODEM_PWR_ON, 0);
215         mdelay(200);
216         gpio_set_value(MODEM_PWR_ON, 1);
217 }
218
219 static int baseband_init(void)
220 {
221         int irq;
222         int ret;
223
224         ret = gpio_request_array(modem_gpios, ARRAY_SIZE(modem_gpios));
225         if (ret)
226                 return ret;
227
228         /* enable pull-up for ULPI STP */
229         tegra_pinmux_set_pullupdown(TEGRA_PINGROUP_ULPI_STP,
230                                     TEGRA_PUPD_PULL_UP);
231
232         /* enable pull-up for MDM2AP_ACK2 */
233         tegra_pinmux_set_pullupdown(TEGRA_PINGROUP_GPIO_PV0,
234                                     TEGRA_PUPD_PULL_UP);
235
236         /* export GPIO for user space access through sysfs */
237         gpio_export(MODEM_PWR_ON, false);
238
239         /* phy init */
240         tegra_null_ulpi_init();
241
242         wake_lock_init(&mdm_wake_lock, WAKE_LOCK_SUSPEND, "mdm_lock");
243
244         /* enable IRQ for BB_RST_OUT */
245         irq = gpio_to_irq(BB_RST_OUT);
246
247         ret = request_threaded_irq(irq, NULL, mdm_start_thread,
248                                    IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
249                                    "mdm_start", NULL);
250         if (ret < 0) {
251                 pr_err("%s: request_threaded_irq error\n", __func__);
252                 return ret;
253         }
254
255         ret = enable_irq_wake(irq);
256         if (ret) {
257                 pr_err("%s: enable_irq_wake error\n", __func__);
258                 free_irq(irq, NULL);
259                 return ret;
260         }
261
262         return 0;
263 }
264
265 static const struct tegra_modem_operations baseband_operations = {
266         .init = baseband_init,
267         .start = baseband_start,
268         .reset = baseband_reset,
269 };
270
271 static struct tegra_usb_modem_power_platform_data baseband_pdata = {
272         .ops = &baseband_operations,
273         .wake_gpio = MDM2AP_ACK2,
274         .flags = IRQF_TRIGGER_FALLING,
275 };
276
277 static struct platform_device icera_baseband_device = {
278         .name = "tegra_usb_modem_power",
279         .id = -1,
280         .dev = {
281                 .platform_data = &baseband_pdata,
282         },
283 };
284
285 int __init enterprise_modem_init(void)
286 {
287         platform_device_register(&icera_baseband_device);
288         return 0;
289 }