aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/tegra-baseband
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/tegra-baseband')
-rw-r--r--drivers/misc/tegra-baseband/Kconfig32
-rw-r--r--drivers/misc/tegra-baseband/Makefile6
-rw-r--r--drivers/misc/tegra-baseband/bb-m7400.c340
-rw-r--r--drivers/misc/tegra-baseband/bb-power.c337
-rw-r--r--drivers/misc/tegra-baseband/bb-power.h99
5 files changed, 814 insertions, 0 deletions
diff --git a/drivers/misc/tegra-baseband/Kconfig b/drivers/misc/tegra-baseband/Kconfig
new file mode 100644
index 00000000000..1f116918296
--- /dev/null
+++ b/drivers/misc/tegra-baseband/Kconfig
@@ -0,0 +1,32 @@
1menuconfig TEGRA_BB_SUPPORT
2 bool "Tegra baseband support"
3 depends on ARCH_TEGRA
4 ---help---
5 Say Y here to get to see options for tegra baseband support.
6 This option alone does not add any kernel code.
7
8 If you say N, all options in this submenu will be skipped and disabled.
9
10if TEGRA_BB_SUPPORT
11
12config TEGRA_BB_POWER
13 bool "Enable tegra baseband power driver"
14 ---help---
15 Adds power management driver for managing different baseband
16 modems with tegra processor.
17
18 This driver should work with at least the following devices:
19
20 * STE M7400
21 * ...
22
23 Disabled by default. Choose Y here if you want to build the driver.
24
25config TEGRA_BB_M7400
26 bool "Enable driver for M7400 modem"
27 ---help---
28 Enables driver for M7400 modem.
29
30 Disabled by default. Choose Y here if you want to build the driver.
31
32endif # TEGRA_BB_SUPPORT
diff --git a/drivers/misc/tegra-baseband/Makefile b/drivers/misc/tegra-baseband/Makefile
new file mode 100644
index 00000000000..a95d84dbf11
--- /dev/null
+++ b/drivers/misc/tegra-baseband/Makefile
@@ -0,0 +1,6 @@
1#
2# Makefile for tegra baseband support.
3#
4
5obj-$(CONFIG_TEGRA_BB_POWER) += bb-power.o
6obj-$(CONFIG_TEGRA_BB_M7400) += bb-m7400.o
diff --git a/drivers/misc/tegra-baseband/bb-m7400.c b/drivers/misc/tegra-baseband/bb-m7400.c
new file mode 100644
index 00000000000..5808a6e321c
--- /dev/null
+++ b/drivers/misc/tegra-baseband/bb-m7400.c
@@ -0,0 +1,340 @@
1/*
2 * drivers/misc/tegra-baseband/bb-m7400.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/device.h>
29#include <linux/usb.h>
30#include <linux/wakelock.h>
31#include <asm/mach-types.h>
32#include <asm/mach/arch.h>
33#include <mach/tegra-bb-power.h>
34#include <mach/usb_phy.h>
35#include "bb-power.h"
36
37static struct tegra_bb_gpio_data m7400_gpios[] = {
38 { { GPIO_INVALID, GPIOF_OUT_INIT_LOW, "MDM_PWR_ON" }, true },
39 { { GPIO_INVALID, GPIOF_IN, "MDM_PWRSTATUS" }, true },
40 { { GPIO_INVALID, GPIOF_OUT_INIT_HIGH, "MDM_SERVICE" }, true },
41 { { GPIO_INVALID, GPIOF_OUT_INIT_LOW, "MDM_USB_AWR" }, false },
42 { { GPIO_INVALID, GPIOF_IN, "MDM_USB_CWR" }, false },
43 { { GPIO_INVALID, GPIOF_IN, "MDM_RESOUT2" }, true },
44 { { GPIO_INVALID, GPIOF_OUT_INIT_LOW, "MDM_USB_ARR" }, false },
45 { { GPIO_INVALID, 0, NULL }, false }, /* End of table */
46};
47static bool ehci_registered;
48static int modem_status;
49static int gpio_awr;
50static int gpio_cwr;
51static int gpio_arr;
52static struct usb_device *m7400_usb_device;
53
54static int gpio_wait_timeout(int gpio, int value, int timeout_msec)
55{
56 int count;
57 for (count = 0; count < timeout_msec; ++count) {
58 if (gpio_get_value(gpio) == value)
59 return 0;
60 mdelay(1);
61 }
62 return -1;
63}
64
65static int m7400_enum_handshake(void)
66{
67 int retval = 0;
68
69 /* Wait for CP to indicate ready - by driving CWR high. */
70 if (gpio_wait_timeout(gpio_cwr, 1, 10) != 0) {
71 pr_info("%s: Error: timeout waiting for modem resume.\n",
72 __func__);
73 retval = -1;
74 }
75
76 /* Signal AP ready - Drive AWR and ARR high. */
77 gpio_set_value(gpio_awr, 1);
78 gpio_set_value(gpio_arr, 1);
79
80 return retval;
81}
82
83static int m7400_apup_handshake(bool checkresponse)
84{
85 int retval = 0;
86
87 /* Signal AP ready - Drive AWR and ARR high. */
88 gpio_set_value(gpio_awr, 1);
89 gpio_set_value(gpio_arr, 1);
90
91 if (checkresponse) {
92 /* Wait for CP ack - by driving CWR high. */
93 if (gpio_wait_timeout(gpio_cwr, 1, 10) != 0) {
94 pr_info("%s: Error: timeout waiting for modem ack.\n",
95 __func__);
96 retval = -1;
97 }
98 }
99 return retval;
100}
101
102static void m7400_apdown_handshake(void)
103{
104 /* Signal AP going down to modem - Drive AWR low. */
105 /* No need to wait for a CP response */
106 gpio_set_value(gpio_awr, 0);
107}
108
109static int m7400_l2_suspend(void)
110{
111 /* Gets called for two cases :
112 a) Port suspend.
113 b) Bus suspend. */
114 if (modem_status == BBSTATE_L2)
115 return 0;
116
117 /* Post bus suspend: Drive ARR low. */
118 gpio_set_value(gpio_arr, 0);
119 modem_status = BBSTATE_L2;
120 return 0;
121}
122
123static int m7400_l2_resume(void)
124{
125 /* Gets called for two cases :
126 a) L2 resume.
127 b) bus resume phase of L3 resume. */
128 if (modem_status == BBSTATE_L0)
129 return 0;
130
131 /* Pre bus resume: Drive ARR high. */
132 gpio_set_value(gpio_arr, 1);
133
134 /* If host initiated resume - Wait for CP ack (CWR goes high). */
135 /* If device initiated resume - CWR will be already high. */
136 if (gpio_wait_timeout(gpio_cwr, 1, 10) != 0) {
137 pr_info("%s: Error: timeout waiting for modem ack.\n",
138 __func__);
139 return -1;
140 }
141 modem_status = BBSTATE_L0;
142 return 0;
143}
144
145static void m7400_l3_suspend(void)
146{
147 m7400_apdown_handshake();
148 modem_status = BBSTATE_L3;
149}
150
151static void m7400_l3_resume(void)
152{
153 m7400_apup_handshake(true);
154 modem_status = BBSTATE_L0;
155}
156
157static irqreturn_t m7400_wake_irq(int irq, void *dev_id)
158{
159 struct usb_interface *intf;
160
161 switch (modem_status) {
162 case BBSTATE_L2:
163 /* Resume usb host activity. */
164 if (m7400_usb_device) {
165 usb_lock_device(m7400_usb_device);
166 intf = usb_ifnum_to_if(m7400_usb_device, 0);
167 usb_autopm_get_interface(intf);
168 usb_autopm_put_interface(intf);
169 usb_unlock_device(m7400_usb_device);
170 }
171 break;
172 default:
173 break;
174 }
175
176 return IRQ_HANDLED;
177}
178
179static int m7400_power(int code)
180{
181 switch (code) {
182 case PWRSTATE_L2L3:
183 m7400_l3_suspend();
184 break;
185 case PWRSTATE_L3L0:
186 m7400_l3_resume();
187 break;
188 default:
189 break;
190 }
191 return 0;
192}
193
194static void m7400_ehci_customize(struct platform_device *pdev)
195{
196 struct tegra_ehci_platform_data *ehci_pdata;
197 struct tegra_uhsic_config *hsic_config;
198
199 ehci_pdata = (struct tegra_ehci_platform_data *)
200 pdev->dev.platform_data;
201 hsic_config = (struct tegra_uhsic_config *)
202 ehci_pdata->phy_config;
203
204 /* Register PHY callbacks */
205 hsic_config->postsuspend = m7400_l2_suspend;
206 hsic_config->preresume = m7400_l2_resume;
207
208 /* Override required settings */
209 ehci_pdata->power_down_on_bus_suspend = 0;
210}
211
212static int m7400_attrib_write(struct device *dev, int value)
213{
214 struct tegra_bb_pdata *pdata;
215 static struct platform_device *ehci_device;
216 static bool first_enum = true;
217
218 if (value > 1 || (!ehci_registered && !value)) {
219 /* Supported values are 0/1. */
220 return -1;
221 }
222
223 pdata = (struct tegra_bb_pdata *) dev->platform_data;
224 if (value) {
225
226 /* Check readiness for enumeration */
227 if (first_enum)
228 first_enum = false;
229 else
230 m7400_enum_handshake();
231
232 /* Register ehci controller */
233 ehci_device = pdata->ehci_register();
234 if (ehci_device == NULL) {
235 pr_info("%s - Error: ehci register failed.\n",
236 __func__);
237 return -1;
238 }
239
240 /* Customize PHY setup/callbacks */
241 m7400_ehci_customize(ehci_device);
242
243 ehci_registered = true;
244 } else {
245 /* Unregister ehci controller */
246 if (ehci_device != NULL)
247 pdata->ehci_unregister(ehci_device);
248
249 /* Signal AP going down */
250 m7400_apdown_handshake();
251 ehci_registered = false;
252 }
253
254 return 0;
255}
256
257static int m7400_registered(struct usb_device *udev)
258{
259 m7400_usb_device = udev;
260 modem_status = BBSTATE_L0;
261 return 0;
262}
263
264static struct tegra_bb_gpio_irqdata m7400_gpioirqs[] = {
265 { GPIO_INVALID, "tegra_bb_wake", m7400_wake_irq,
266 IRQF_TRIGGER_RISING, true, NULL },
267 { GPIO_INVALID, NULL, NULL, 0, NULL }, /* End of table */
268};
269
270static struct tegra_bb_power_gdata m7400_gdata = {
271 .gpio = m7400_gpios,
272 .gpioirq = m7400_gpioirqs,
273};
274
275static struct tegra_bb_power_mdata m7400_mdata = {
276 .vid = 0x04cc,
277 .pid = 0x230f,
278 .wake_capable = true,
279 .autosuspend_ready = true,
280 .reg_cb = m7400_registered,
281};
282
283static struct tegra_bb_power_data m7400_data = {
284 .gpio_data = &m7400_gdata,
285 .modem_data = &m7400_mdata,
286};
287
288static void *m7400_init(void *pdata)
289{
290 struct tegra_bb_pdata *platdata = (struct tegra_bb_pdata *) pdata;
291 union tegra_bb_gpio_id *id = platdata->id;
292
293 /* Fill the gpio ids allocated by hardware */
294 m7400_gpios[0].data.gpio = id->m7400.pwr_on;
295 m7400_gpios[1].data.gpio = id->m7400.pwr_status;
296 m7400_gpios[2].data.gpio = id->m7400.service;
297 m7400_gpios[3].data.gpio = id->m7400.usb_awr;
298 m7400_gpios[4].data.gpio = id->m7400.usb_cwr;
299 m7400_gpios[5].data.gpio = id->m7400.resout2;
300 m7400_gpios[6].data.gpio = id->m7400.uart_awr;
301 m7400_gpioirqs[0].id = id->m7400.usb_cwr;
302
303 if (!platdata->ehci_register || !platdata->ehci_unregister) {
304 pr_info("%s - Error: ehci reg/unreg functions missing.\n"
305 , __func__);
306 return 0;
307 }
308
309 gpio_awr = m7400_gpios[3].data.gpio;
310 gpio_cwr = m7400_gpios[4].data.gpio;
311 gpio_arr = m7400_gpios[6].data.gpio;
312 if (gpio_awr == GPIO_INVALID || gpio_cwr == GPIO_INVALID
313 || gpio_arr == GPIO_INVALID) {
314 pr_info("%s - Error: Invalid gpio data.\n", __func__);
315 return 0;
316 }
317
318 ehci_registered = false;
319 modem_status = BBSTATE_UNKNOWN;
320 return (void *) &m7400_data;
321}
322
323static void *m7400_deinit(void)
324{
325 return (void *) &m7400_data;
326}
327
328static struct tegra_bb_callback m7400_callbacks = {
329 .init = m7400_init,
330 .deinit = m7400_deinit,
331 .attrib = m7400_attrib_write,
332#ifdef CONFIG_PM
333 .power = m7400_power,
334#endif
335};
336
337void *m7400_get_cblist(void)
338{
339 return (void *) &m7400_callbacks;
340}
diff --git a/drivers/misc/tegra-baseband/bb-power.c b/drivers/misc/tegra-baseband/bb-power.c
new file mode 100644
index 00000000000..9210a8f3e84
--- /dev/null
+++ b/drivers/misc/tegra-baseband/bb-power.c
@@ -0,0 +1,337 @@
1/*
2 * drivers/misc/tegra-baseband/bb-power.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/platform_device.h>
22#include <linux/gpio.h>
23#include <linux/interrupt.h>
24#include <linux/workqueue.h>
25#include <linux/delay.h>
26#include <linux/fs.h>
27#include <linux/usb.h>
28#include <linux/uaccess.h>
29#include <linux/platform_data/tegra_usb.h>
30#include <mach/usb_phy.h>
31#include <mach/tegra-bb-power.h>
32#include "bb-power.h"
33
34static struct tegra_bb_callback *callback;
35static int attr_load_val;
36static struct tegra_bb_power_mdata *mdata;
37static bb_get_cblist get_cblist[] = {
38 NULL,
39 NULL,
40 NULL,
41 M7400_CB,
42};
43
44static int tegra_bb_power_gpio_init(struct tegra_bb_power_gdata *gdata)
45{
46 int ret;
47 int irq;
48 unsigned gpio_id;
49 const char *gpio_label;
50 unsigned long gpio_flags;
51 struct tegra_bb_gpio_data *gpiolist;
52 struct tegra_bb_gpio_irqdata *gpioirq;
53
54 gpiolist = gdata->gpio;
55 for (; gpiolist->data.gpio != GPIO_INVALID; ++gpiolist) {
56 gpio_id = (gpiolist->data.gpio);
57 gpio_label = (gpiolist->data.label);
58 gpio_flags = (gpiolist->data.flags);
59
60 /* Request the gpio */
61 ret = gpio_request(gpio_id, gpio_label);
62 if (ret) {
63 pr_err("%s: Error: gpio_request for gpio %d failed.\n",
64 __func__, gpio_id);
65 return ret;
66 }
67
68 /* Set gpio direction, as requested */
69 if (gpio_flags == GPIOF_IN)
70 gpio_direction_input(gpio_id);
71 else
72 gpio_direction_output(gpio_id, (!gpio_flags ? 0 : 1));
73
74 /* Enable the gpio */
75 tegra_gpio_enable(gpio_id);
76
77 /* Create a sysfs node, if requested */
78 if (gpiolist->doexport)
79 gpio_export(gpio_id, false);
80 }
81
82 gpioirq = gdata->gpioirq;
83 for (; gpioirq->id != GPIO_INVALID; ++gpioirq) {
84
85 /* Create interrupt handler, if requested */
86 if (gpioirq->handler != NULL) {
87 irq = gpio_to_irq(gpioirq->id);
88 ret = request_threaded_irq(irq, NULL, gpioirq->handler,
89 gpioirq->flags, gpioirq->name, gpioirq->cookie);
90 if (ret < 0) {
91 pr_err("%s: Error: threaded_irq req fail.\n"
92 , __func__);
93 return ret;
94 }
95
96 if (gpioirq->wake_capable) {
97 ret = enable_irq_wake(irq);
98 if (ret) {
99 pr_err("%s: Error: irqwake req fail.\n",
100 __func__);
101 return ret;
102 }
103 }
104 }
105 }
106 return 0;
107}
108
109static int tegra_bb_power_gpio_deinit(struct tegra_bb_power_gdata *gdata)
110{
111 struct tegra_bb_gpio_data *gpiolist;
112 struct tegra_bb_gpio_irqdata *gpioirq;
113
114 gpiolist = gdata->gpio;
115 for (; gpiolist->data.gpio != GPIO_INVALID; ++gpiolist) {
116
117 /* Free the gpio */
118 gpio_free(gpiolist->data.gpio);
119 }
120
121 gpioirq = gdata->gpioirq;
122 for (; gpioirq->id != GPIO_INVALID; ++gpioirq) {
123
124 /* Free the irq */
125 free_irq(gpio_to_irq(gpioirq->id), gpioirq->cookie);
126 }
127 return 0;
128}
129
130static ssize_t tegra_bb_attr_write(struct device *dev,
131 struct device_attribute *attr,
132 const char *buf, size_t count)
133{
134 int val;
135
136 if (sscanf(buf, "%d", &val) != 1)
137 return -EINVAL;
138
139 if (callback && callback->attrib) {
140 if (!callback->attrib(dev, val))
141 attr_load_val = val;
142 }
143 return count;
144}
145
146static ssize_t tegra_bb_attr_read(struct device *dev,
147 struct device_attribute *attr, char *buf)
148{
149 return sprintf(buf, "%d", attr_load_val);
150}
151
152static DEVICE_ATTR(load, S_IRUSR | S_IWUSR | S_IRGRP,
153 tegra_bb_attr_read, tegra_bb_attr_write);
154
155static void tegra_usbdevice_added(struct usb_device *udev)
156{
157 const struct usb_device_descriptor *desc = &udev->descriptor;
158
159 if (desc->idVendor == mdata->vid &&
160 desc->idProduct == mdata->pid) {
161 pr_debug("%s: Device %s added.\n", udev->product, __func__);
162
163 if (mdata->wake_capable)
164 device_set_wakeup_enable(&udev->dev, true);
165 if (mdata->autosuspend_ready)
166 usb_enable_autosuspend(udev);
167 if (mdata->reg_cb)
168 mdata->reg_cb(udev);
169 }
170}
171
172static void tegra_usbdevice_removed(struct usb_device *udev)
173{
174 const struct usb_device_descriptor *desc = &udev->descriptor;
175
176 if (desc->idVendor == mdata->vid &&
177 desc->idProduct == mdata->pid) {
178 pr_debug("%s: Device %s removed.\n", udev->product, __func__);
179 }
180}
181
182static int tegra_usb_notify(struct notifier_block *self, unsigned long action,
183 void *dev)
184{
185 switch (action) {
186 case USB_DEVICE_ADD:
187 tegra_usbdevice_added((struct usb_device *)dev);
188 break;
189 case USB_DEVICE_REMOVE:
190 tegra_usbdevice_removed((struct usb_device *)dev);
191 break;
192 }
193 return NOTIFY_OK;
194}
195
196static struct notifier_block tegra_usb_nb = {
197 .notifier_call = tegra_usb_notify,
198};
199
200static int tegra_bb_power_probe(struct platform_device *device)
201{
202 struct device *dev = &device->dev;
203 struct tegra_bb_pdata *pdata;
204 struct tegra_bb_power_data *data;
205 struct tegra_bb_power_gdata *gdata;
206 int err;
207 unsigned int bb_id;
208
209 pdata = (struct tegra_bb_pdata *) dev->platform_data;
210 if (!pdata) {
211 pr_err("%s - Error: platform data is empty.\n", __func__);
212 return -ENODEV;
213 }
214
215 /* Obtain BB specific callback list */
216 bb_id = pdata->bb_id;
217 if (get_cblist[bb_id] != NULL) {
218 callback = (struct tegra_bb_callback *) get_cblist[bb_id]();
219 if (callback && callback->init) {
220 data = (struct tegra_bb_power_data *)
221 callback->init((void *)pdata);
222
223 gdata = data->gpio_data;
224 if (!gdata) {
225 pr_err("%s - Error: Gpio data is empty.\n",
226 __func__);
227 return -ENODEV;
228 }
229
230 /* Initialize gpio as required */
231 tegra_bb_power_gpio_init(gdata);
232
233 mdata = data->modem_data;
234 if (mdata && mdata->vid && mdata->pid)
235 /* Register to notifications from usb core */
236 usb_register_notify(&tegra_usb_nb);
237 } else {
238 pr_err("%s - Error: init callback is empty.\n",
239 __func__);
240 return -ENODEV;
241 }
242 } else {
243 pr_err("%s - Error: callback data is empty.\n", __func__);
244 return -ENODEV;
245 }
246
247 /* Create the control sysfs node */
248 err = device_create_file(dev, &dev_attr_load);
249 if (err < 0) {
250 pr_err("%s - Error: device_create_file failed.\n", __func__);
251 return -ENODEV;
252 }
253 attr_load_val = 0;
254
255 return 0;
256}
257
258static int tegra_bb_power_remove(struct platform_device *device)
259{
260 struct device *dev = &device->dev;
261 struct tegra_bb_power_data *data;
262 struct tegra_bb_power_gdata *gdata;
263
264 /* BB specific callback */
265 if (callback && callback->deinit) {
266 data = (struct tegra_bb_power_data *)
267 callback->deinit();
268
269 /* Deinitialize gpios */
270 gdata = data->gpio_data;
271 if (gdata)
272 tegra_bb_power_gpio_deinit(gdata);
273 else {
274 pr_err("%s - Error: Gpio data is empty.\n", __func__);
275 return -ENODEV;
276 }
277
278 mdata = data->modem_data;
279 if (mdata && mdata->vid && mdata->pid)
280 /* Register to notifications from usb core */
281 usb_unregister_notify(&tegra_usb_nb);
282 }
283
284 /* Remove the control sysfs node */
285 device_remove_file(dev, &dev_attr_load);
286
287 return 0;
288}
289
290#ifdef CONFIG_PM
291static int tegra_bb_power_suspend(struct platform_device *device,
292 pm_message_t state)
293{
294 /* BB specific callback */
295 if (callback && callback->power)
296 callback->power(PWRSTATE_L2L3);
297 return 0;
298}
299
300static int tegra_bb_power_resume(struct platform_device *device)
301{
302 /* BB specific callback */
303 if (callback && callback->power)
304 callback->power(PWRSTATE_L3L0);
305 return 0;
306}
307#endif
308
309static struct platform_driver tegra_bb_power_driver = {
310 .probe = tegra_bb_power_probe,
311 .remove = tegra_bb_power_remove,
312#ifdef CONFIG_PM
313 .suspend = tegra_bb_power_suspend,
314 .resume = tegra_bb_power_resume,
315#endif
316 .driver = {
317 .name = "tegra_baseband_power",
318 },
319};
320
321static int __init tegra_baseband_power_init(void)
322{
323 pr_debug("%s\n", __func__);
324 return platform_driver_register(&tegra_bb_power_driver);
325}
326
327static void __exit tegra_baseband_power_exit(void)
328{
329 pr_debug("%s\n", __func__);
330 platform_driver_unregister(&tegra_bb_power_driver);
331}
332
333module_init(tegra_baseband_power_init)
334module_exit(tegra_baseband_power_exit)
335MODULE_AUTHOR("NVIDIA Corporation");
336MODULE_DESCRIPTION("Tegra modem power management driver");
337MODULE_LICENSE("GPL");
diff --git a/drivers/misc/tegra-baseband/bb-power.h b/drivers/misc/tegra-baseband/bb-power.h
new file mode 100644
index 00000000000..cdd69380203
--- /dev/null
+++ b/drivers/misc/tegra-baseband/bb-power.h
@@ -0,0 +1,99 @@
1/*
2 * drivers/misc/tegra-baseband/bb-power.h
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
17enum tegra_bb_state {
18 BBSTATE_UNKNOWN,
19 /* Baseband state L0 - Running */
20 BBSTATE_L0,
21 /* Baseband state L2 - Suspended */
22 BBSTATE_L2,
23 /* Baseband state L3 - Suspended and detached */
24 BBSTATE_L3,
25};
26
27enum tegra_bb_pwrstate {
28 /* System power state - Entering suspend */
29 PWRSTATE_L2L3,
30 /* System power state - Resuming from suspend */
31 PWRSTATE_L3L0,
32 PWRSTATE_INVALID,
33};
34
35struct tegra_bb_gpio_data {
36 /* Baseband gpio data */
37 struct gpio data;
38 /* Baseband gpio - Should it be exported to sysfs ? */
39 bool doexport;
40};
41
42struct tegra_bb_gpio_irqdata {
43 /* Baseband gpio IRQ - Id */
44 int id;
45 /* Baseband gpio IRQ - Friendly name */
46 const char *name;
47 /* Baseband gpio IRQ - IRQ handler */
48 irq_handler_t handler;
49 /* Baseband gpio IRQ - IRQ trigger flags */
50 int flags;
51 /* Baseband gpio IRQ - Can the gpio wake system from sleep ? */
52 bool wake_capable;
53 void *cookie;
54};
55
56typedef void* (*bb_get_cblist)(void);
57typedef void* (*bb_init_cb)(void *pdata);
58typedef void* (*bb_deinit_cb)(void);
59typedef int (*bb_power_cb)(int code);
60typedef int (*bb_attrib_cb)(struct device *dev, int value);
61typedef int (*modem_register_cb)(struct usb_device *udev);
62
63struct tegra_bb_power_gdata {
64 struct tegra_bb_gpio_data *gpio;
65 struct tegra_bb_gpio_irqdata *gpioirq;
66};
67
68struct tegra_bb_power_mdata {
69 /* Baseband USB vendor ID */
70 int vid;
71 /* Baseband USB product ID */
72 int pid;
73 /* Baseband capability - Can it generate a wakeup ? */
74 bool wake_capable;
75 /* Baseband capability - Can it be auto/runtime suspended ? */
76 bool autosuspend_ready;
77 /* Baseband callback after a successful registration */
78 modem_register_cb reg_cb;
79};
80
81struct tegra_bb_power_data {
82 struct tegra_bb_power_gdata *gpio_data;
83 struct tegra_bb_power_mdata *modem_data;
84};
85
86struct tegra_bb_callback {
87 bb_init_cb init;
88 bb_deinit_cb deinit;
89 bb_power_cb power;
90 bb_attrib_cb attrib;
91 bool valid;
92};
93
94#ifdef CONFIG_TEGRA_BB_M7400
95extern void *m7400_get_cblist(void);
96#define M7400_CB m7400_get_cblist
97#else
98#define M7400_CB NULL
99#endif