]> nv-tegra.nvidia Code Review - linux-2.6.git/blob - arch/arm/mach-tegra/board-enterprise-baseband.c
ARM: tegra: Change pm269 board structure configs
[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-2012, NVIDIA CORPORATION.  All rights reserved.
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
31 #include <mach/pinmux-tegra30.h>
32 #include <mach/tegra_usb_modem_power.h>
33 #include <mach/gpio-tegra.h>
34
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 static struct wake_lock mdm_wake_lock;
50
51 static struct gpio modem_gpios[] = {
52         {MODEM_PWR_ON, GPIOF_OUT_INIT_LOW, "MODEM PWR ON"},
53         {MODEM_RESET, GPIOF_IN, "MODEM RESET"},
54         {BB_RST_OUT, GPIOF_IN, "BB RST OUT"},
55         {AP2MDM_ACK2, GPIOF_OUT_INIT_HIGH, "AP2MDM ACK2"},
56         {AP2MDM_ACK, GPIOF_OUT_INIT_LOW, "AP2MDM ACK"},
57 };
58
59
60 static void baseband_post_phy_on(void);
61 static void baseband_pre_phy_off(void);
62
63 static struct tegra_usb_phy_platform_ops ulpi_null_plat_ops = {
64         .pre_phy_off = baseband_pre_phy_off,
65         .post_phy_on = baseband_post_phy_on,
66 };
67
68 static struct tegra_usb_platform_data tegra_ehci2_ulpi_null_pdata = {
69         .port_otg = false,
70         .has_hostpc = true,
71         .phy_intf = TEGRA_USB_PHY_INTF_ULPI_NULL,
72         .op_mode        = TEGRA_USB_OPMODE_HOST,
73         .u_data.host = {
74                 .vbus_gpio = -1,
75                 .vbus_reg = NULL,
76                 .hot_plug = true,
77                 .remote_wakeup_supported = false,
78                 .power_off_on_suspend = true,
79         },
80         .u_cfg.ulpi = {
81                 .shadow_clk_delay = 10,
82                 .clock_out_delay = 1,
83                 .data_trimmer = 1,
84                 .stpdirnxt_trimmer = 1,
85                 .dir_trimmer = 1,
86                 .clk = NULL,
87                 .phy_restore_gpio = MDM2AP_ACK,
88         },
89         .ops = &ulpi_null_plat_ops,
90 };
91
92 static int __init tegra_null_ulpi_init(void)
93 {
94         tegra_ehci2_device.dev.platform_data = &tegra_ehci2_ulpi_null_pdata;
95         platform_device_register(&tegra_ehci2_device);
96         return 0;
97 }
98
99 static irqreturn_t mdm_start_thread(int irq, void *data)
100 {
101         if (gpio_get_value(BB_RST_OUT)) {
102                 pr_info("BB_RST_OUT high\n");
103         } else {
104                 pr_info("BB_RST_OUT low\n");
105         }
106
107         /* hold wait lock to complete the enumeration */
108         wake_lock_timeout(&mdm_wake_lock, HZ * 10);
109
110         return IRQ_HANDLED;
111 }
112
113 static void baseband_post_phy_on(void)
114 {
115         /* set AP2MDM_ACK2 low */
116         gpio_set_value(AP2MDM_ACK2, 0);
117 }
118
119 static void baseband_pre_phy_off(void)
120 {
121         /* set AP2MDM_ACK2 high */
122         gpio_set_value(AP2MDM_ACK2, 1);
123 }
124
125 static void baseband_start(void)
126 {
127         /*
128          *  Leave baseband powered OFF.
129          *  User-space daemons will take care of powering it up.
130          */
131         pr_info("%s\n", __func__);
132         gpio_set_value(MODEM_PWR_ON, 0);
133 }
134
135 static void baseband_reset(void)
136 {
137         /* Initiate power cycle on baseband sub system */
138         pr_info("%s\n", __func__);
139         gpio_set_value(MODEM_PWR_ON, 0);
140         mdelay(200);
141         gpio_set_value(MODEM_PWR_ON, 1);
142 }
143
144 static int baseband_init(void)
145 {
146         int irq;
147         int ret;
148
149         ret = gpio_request_array(modem_gpios, ARRAY_SIZE(modem_gpios));
150         if (ret)
151                 return ret;
152
153         /* enable pull-up for ULPI STP */
154         tegra_pinmux_set_pullupdown(TEGRA_PINGROUP_ULPI_STP,
155                                     TEGRA_PUPD_PULL_UP);
156
157         /* enable pull-up for MDM2AP_ACK2 */
158         tegra_pinmux_set_pullupdown(TEGRA_PINGROUP_GPIO_PV0,
159                                     TEGRA_PUPD_PULL_UP);
160
161         /* export GPIO for user space access through sysfs */
162         gpio_export(MODEM_PWR_ON, false);
163
164         /* phy init */
165         tegra_null_ulpi_init();
166
167         wake_lock_init(&mdm_wake_lock, WAKE_LOCK_SUSPEND, "mdm_lock");
168
169         /* enable IRQ for BB_RST_OUT */
170         irq = gpio_to_irq(BB_RST_OUT);
171
172         ret = request_threaded_irq(irq, NULL, mdm_start_thread,
173                                    IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
174                                    "mdm_start", NULL);
175         if (ret < 0) {
176                 pr_err("%s: request_threaded_irq error\n", __func__);
177                 return ret;
178         }
179
180         ret = enable_irq_wake(irq);
181         if (ret) {
182                 pr_err("%s: enable_irq_wake error\n", __func__);
183                 free_irq(irq, NULL);
184                 return ret;
185         }
186
187         return 0;
188 }
189
190 static const struct tegra_modem_operations baseband_operations = {
191         .init = baseband_init,
192         .start = baseband_start,
193         .reset = baseband_reset,
194 };
195
196 static struct tegra_usb_modem_power_platform_data baseband_pdata = {
197         .ops = &baseband_operations,
198         .wake_gpio = MDM2AP_ACK2,
199         .flags = IRQF_TRIGGER_FALLING,
200 };
201
202 static struct platform_device icera_baseband_device = {
203         .name = "tegra_usb_modem_power",
204         .id = -1,
205         .dev = {
206                 .platform_data = &baseband_pdata,
207         },
208 };
209
210 int __init enterprise_modem_init(void)
211 {
212         platform_device_register(&icera_baseband_device);
213         return 0;
214 }