ARM: tegra12: set CPU rate to 2.2GHz for sku 0x87
[linux-3.10.git] / arch / arm / mach-tegra / baseband-xmm-power2.c
1 /*
2  * arch/arm/mach-tegra/baseband-xmm-power2.c
3  *
4  * Copyright (C) 2011-2012, NVIDIA Corporation. All Rights Reserved.
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/slab.h>
26 #include <linux/delay.h>
27 #include <linux/fs.h>
28 #include <linux/uaccess.h>
29 #include <linux/wakelock.h>
30 #include <linux/usb/tegra_usb_phy.h>
31 #include "baseband-xmm-power.h"
32 #include "board.h"
33 #include "devices.h"
34
35 static unsigned long XYZ = 1000 * 1000000 + 800 * 1000 + 500;
36
37 module_param(modem_ver, ulong, 0644);
38 MODULE_PARM_DESC(modem_ver,
39         "baseband xmm power2 - modem software version");
40 module_param(modem_flash, ulong, 0644);
41 MODULE_PARM_DESC(modem_flash,
42         "baseband xmm power2 - modem flash (1 = flash, 0 = flashless)");
43 module_param(modem_pm, ulong, 0644);
44 MODULE_PARM_DESC(modem_pm,
45         "baseband xmm power2 - modem power management (1 = pm, 0 = no pm)");
46 module_param(XYZ, ulong, 0644);
47 MODULE_PARM_DESC(XYZ,
48         "baseband xmm power2 - timing parameters X/Y/Z delay in ms");
49
50 static struct workqueue_struct *workqueue;
51 static bool free_ipc_ap_wake_irq;
52 static enum ipc_ap_wake_state_t ipc_ap_wake_state;
53
54 static irqreturn_t xmm_power2_ipc_ap_wake_irq(int irq, void *dev_id)
55 {
56         int value;
57         struct xmm_power_data *data = dev_id;
58         struct baseband_power_platform_data *pdata = data->pdata;
59
60         /* check for platform data */
61         if (!pdata)
62                 return IRQ_HANDLED;
63
64         value = gpio_get_value(pdata->modem.xmm.ipc_ap_wake);
65
66         /* IPC_AP_WAKE state machine */
67         if (unlikely(ipc_ap_wake_state < IPC_AP_WAKE_IRQ_READY))
68                 pr_err("%s - spurious irq\n", __func__);
69         else if (ipc_ap_wake_state == IPC_AP_WAKE_IRQ_READY) {
70                 if (!value) {
71                         pr_debug("%s: IPC_AP_WAKE_IRQ_READY got falling edge\n",
72                                                 __func__);
73                         /* go to IPC_AP_WAKE_INIT2 state */
74                         ipc_ap_wake_state = IPC_AP_WAKE_INIT2;
75                         /* queue work */
76                         data->state =
77                                 BBXMM_WORK_INIT_FLASHLESS_PM_STEP2;
78                         queue_work(workqueue, &data->work);
79                 } else
80                         pr_debug("%s: IPC_AP_WAKE_IRQ_READY"
81                                 " wait for falling edge\n", __func__);
82         } else {
83                 if (!value) {
84                         pr_debug("%s - falling\n", __func__);
85                         ipc_ap_wake_state = IPC_AP_WAKE_L;
86                 } else {
87                         pr_debug("%s - rising\n", __func__);
88                         ipc_ap_wake_state = IPC_AP_WAKE_H;
89                 }
90                 return xmm_power_ipc_ap_wake_irq(value);
91         }
92
93         return IRQ_HANDLED;
94 }
95
96 static void xmm_power2_step1(struct work_struct *work)
97 {
98         struct xmm_power_data *data =
99                         container_of(work, struct xmm_power_data, work);
100         struct baseband_power_platform_data *pdata = data->pdata;
101         int X = XYZ / 1000000;
102
103         pr_info("%s {\n", __func__);
104
105         /* check for platform data */
106         if (!pdata)
107                 return;
108
109         /* unregister usb host controller */
110         if (pdata->hsic_unregister)
111                 pdata->hsic_unregister(&data->hsic_device);
112         else
113                 pr_err("%s: hsic_unregister is missing\n", __func__);
114
115         /* wait X ms */
116         msleep(X);
117
118         /* set IPC_HSIC_ACTIVE low */
119         gpio_set_value(pdata->modem.xmm.ipc_hsic_active, 0);
120
121         pr_info("%s }\n", __func__);
122 }
123
124 static void xmm_power2_step2(struct work_struct *work)
125 {
126         struct xmm_power_data *data =
127                         container_of(work, struct xmm_power_data, work);
128         struct baseband_power_platform_data *pdata = data->pdata;
129         int X = XYZ / 1000000;
130         int Y = XYZ / 1000 - X * 1000;
131         int Z = XYZ % 1000;
132
133         pr_info("%s {\n", __func__);
134
135         /* wait Y ms */
136         msleep(Y);
137
138         /* register usb host controller */
139         if (pdata->hsic_register)
140                 data->hsic_device = pdata->hsic_register(pdata->ehci_device);
141         else
142                 pr_err("%s: hsic_register is missing\n", __func__);
143
144         /* wait Z ms */
145         msleep(Z);
146
147         /* set IPC_HSIC_ACTIVE high */
148         gpio_set_value(pdata->modem.xmm.ipc_hsic_active, 1);
149
150         /* queue work function to check if enumeration succeeded */
151         data->state = BBXMM_WORK_INIT_FLASHLESS_PM_STEP3;
152         queue_work(workqueue, &data->work);
153
154         pr_info("%s }\n", __func__);
155 }
156
157 static void xmm_power2_step3(struct work_struct *work)
158 {
159         struct xmm_power_data *data =
160                         container_of(work, struct xmm_power_data, work);
161         struct baseband_power_platform_data *pdata = data->pdata;
162         int enum_success = 0;
163         mm_segment_t oldfs;
164         struct file *filp;
165
166         pr_info("%s {\n", __func__);
167
168         /* wait 1 sec */
169         msleep(1000);
170
171         /* check if enumeration succeeded */
172         oldfs = get_fs();
173         set_fs(KERNEL_DS);
174         filp = filp_open("/dev/ttyACM0", O_RDONLY, 0);
175         if (IS_ERR(filp) || (filp == NULL))
176                 pr_err("failed to open /dev/ttyACM0 %ld\n", PTR_ERR(filp));
177         else {
178                 filp_close(filp, NULL);
179                 enum_success = 1;
180         }
181         set_fs(oldfs);
182
183         /* if enumeration failed, attempt recovery pulse */
184         if (!enum_success) {
185                 pr_info("attempting recovery pulse...\n");
186                 /* wait 20 ms */
187                 msleep(20);
188                 /* set IPC_HSIC_ACTIVE low */
189                 gpio_set_value(pdata->modem.xmm.ipc_hsic_active, 0);
190                 /* wait 20 ms */
191                 msleep(20);
192                 /* set IPC_HSIC_ACTIVE high */
193                 gpio_set_value(pdata->modem.xmm.ipc_hsic_active, 1);
194                 /* check if recovery pulse worked */
195                 data->state = BBXMM_WORK_INIT_FLASHLESS_PM_STEP4;
196                 queue_work(workqueue, &data->work);
197         }
198
199         pr_info("%s }\n", __func__);
200 }
201
202 static void xmm_power2_step4(struct work_struct *work)
203 {
204         struct xmm_power_data *data =
205                         container_of(work, struct xmm_power_data, work);
206         mm_segment_t oldfs;
207         struct file *filp;
208         int enum_success = 0;
209
210         pr_info("%s {\n", __func__);
211
212         /* check for platform data */
213         if (!data)
214                 return;
215
216         /* wait 500 ms */
217         msleep(500);
218
219         /* check if enumeration succeeded */
220         oldfs = get_fs();
221         set_fs(KERNEL_DS);
222         filp = filp_open("/dev/ttyACM0", O_RDONLY, 0);
223         if (IS_ERR(filp) || (filp == NULL))
224                 pr_err("failed to open /dev/ttyACM0 %ld\n", PTR_ERR(filp));
225         else {
226                 filp_close(filp, NULL);
227                 enum_success = 1;
228         }
229         set_fs(oldfs);
230
231         /* if recovery pulse did not fix enumeration, retry from beginning */
232         if (!enum_success) {
233                 static int retry = 3;
234                 if (!retry) {
235                         pr_info("failed to enumerate modem software"
236                                 " - too many retry attempts\n");
237                 } else {
238                         pr_info("recovery pulse failed to fix modem"
239                                 " enumeration..."
240                                 " restarting from beginning"
241                                 " - attempt #%d\n",
242                                 retry);
243                         --retry;
244                         ipc_ap_wake_state = IPC_AP_WAKE_IRQ_READY;
245                         data->state = BBXMM_WORK_INIT_FLASHLESS_PM_STEP1;
246                         queue_work(workqueue, &data->work);
247                 }
248         }
249
250         pr_info("%s }\n", __func__);
251 }
252
253 static void xmm_power2_work_func(struct work_struct *work)
254 {
255         struct xmm_power_data *data =
256                         container_of(work, struct xmm_power_data, work);
257         struct baseband_power_platform_data *pdata;
258         int err;
259
260         if (!data || !data->pdata)
261                 return;
262         pdata = data->pdata;
263
264         pr_debug("%s pdata->state=%d\n", __func__, data->state);
265
266         switch (data->state) {
267         case BBXMM_WORK_UNINIT:
268                 pr_debug("BBXMM_WORK_UNINIT\n");
269                 /* free baseband irq(s) */
270                 if (free_ipc_ap_wake_irq) {
271                         free_irq(gpio_to_irq(pdata->modem.xmm.ipc_ap_wake),
272                                         data);
273                         free_ipc_ap_wake_irq = false;
274                 }
275                 break;
276         case BBXMM_WORK_INIT:
277                 pr_debug("BBXMM_WORK_INIT\n");
278                 /* request baseband irq(s) */
279                 ipc_ap_wake_state = IPC_AP_WAKE_UNINIT;
280                 err = request_threaded_irq(
281                                 gpio_to_irq(pdata->modem.xmm.ipc_ap_wake),
282                                 NULL, xmm_power2_ipc_ap_wake_irq,
283                                 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
284                                 "xmm_power2_ipc_ap_wake_irq", data);
285                 if (err < 0) {
286                         pr_err("%s - request irq IPC_AP_WAKE_IRQ failed\n",
287                                 __func__);
288                         return;
289                 }
290                 free_ipc_ap_wake_irq = true;
291                 ipc_ap_wake_state = IPC_AP_WAKE_IRQ_READY;
292
293                 /* go to next state */
294                 data->state = (modem_flash && !modem_pm)
295                         ? BBXMM_WORK_INIT_FLASH_STEP1
296                         : (modem_flash && modem_pm)
297                         ? BBXMM_WORK_INIT_FLASH_PM_STEP1
298                         : (!modem_flash && modem_pm)
299                         ? BBXMM_WORK_INIT_FLASHLESS_PM_STEP1
300                         : BBXMM_WORK_UNINIT;
301                 queue_work(workqueue, work);
302                 break;
303         case BBXMM_WORK_INIT_FLASH_STEP1:
304                 pr_debug("BBXMM_WORK_INIT_FLASH_STEP1\n");
305                 pr_info("%s: flashed modem is not supported here\n", __func__);
306                 break;
307         case BBXMM_WORK_INIT_FLASH_PM_STEP1:
308                 pr_debug("BBXMM_WORK_INIT_FLASH_PM_STEP1\n");
309                 pr_info("%s: flashed modem is not supported here\n", __func__);
310                 break;
311         case BBXMM_WORK_INIT_FLASHLESS_PM_STEP1:
312                 /* start flashless modem enum process */
313                 pr_debug("BBXMM_WORK_INIT_FLASHLESS_PM_STEP1\n");
314                 xmm_power2_step1(work);
315                 break;
316         case BBXMM_WORK_INIT_FLASHLESS_PM_STEP2:
317                 pr_debug("BBXMM_WORK_INIT_FLASHLESS_PM_STEP2\n");
318                 xmm_power2_step2(work);
319                 break;
320         case BBXMM_WORK_INIT_FLASHLESS_PM_STEP3:
321                 pr_debug("BBXMM_WORK_INIT_FLASHLESS_PM_STEP3\n");
322                 xmm_power2_step3(work);
323                 break;
324         case BBXMM_WORK_INIT_FLASHLESS_PM_STEP4:
325                 pr_debug("BBXMM_WORK_INIT_FLASHLESS_PM_STEP4\n");
326                 xmm_power2_step4(work);
327                 break;
328         default:
329                 break;
330         }
331 }
332
333 static int xmm_power2_probe(struct platform_device *device)
334 {
335         pr_debug("%s\n", __func__);
336         if (!device->dev.platform_data) {
337                 pr_err("%s: no platform data found\n", __func__);
338                 return -ENOMEM;
339         }
340
341         xmm_power_drv_data.pdata = device->dev.platform_data;
342
343         /* create workqueue */
344         pr_debug("%s: init work queue\n", __func__);
345         workqueue = create_singlethread_workqueue("xmm_power2_wq");
346         if (unlikely(!workqueue)) {
347                 pr_err("%s: cannot create workqueue\n", __func__);
348                 return -ENOMEM;
349         }
350
351         /* init work */
352         pr_debug("%s: BBXMM_WORK_INIT\n", __func__);
353         INIT_WORK(&xmm_power_drv_data.work, xmm_power2_work_func);
354         xmm_power_drv_data.state = BBXMM_WORK_INIT;
355         queue_work(workqueue, &xmm_power_drv_data.work);
356
357         return 0;
358 }
359
360 static int xmm_power2_remove(struct platform_device *device)
361 {
362         struct baseband_power_platform_data *pdata =
363                         device->dev.platform_data;
364         struct xmm_power_data *data = &xmm_power_drv_data;
365
366         pr_debug("%s\n", __func__);
367
368         /* check for platform data */
369         if (!data)
370                 return -ENODEV;
371
372         /* free work queue */
373         if (workqueue) {
374                 cancel_work_sync(&data->work);
375                 destroy_workqueue(workqueue);
376         }
377
378         /* free irq */
379         if (free_ipc_ap_wake_irq) {
380                 free_irq(gpio_to_irq(pdata->modem.xmm.ipc_ap_wake), data);
381                 free_ipc_ap_wake_irq = false;
382         }
383
384         return 0;
385 }
386
387 #ifdef CONFIG_PM
388 static int xmm_power2_suspend(struct platform_device *device,
389         pm_message_t state)
390 {
391         struct baseband_power_platform_data *data =
392                         device->dev.platform_data;
393
394         pr_debug("%s - nop\n", __func__);
395
396         /* check for platform data */
397         if (!data)
398                 return 0;
399
400         return 0;
401 }
402
403 static int xmm_power2_resume(struct platform_device *device)
404 {
405         struct baseband_power_platform_data *data =
406                         device->dev.platform_data;
407
408         pr_debug("%s - nop\n", __func__);
409
410         /* check for platform data */
411         if (!data)
412                 return 0;
413
414         return 0;
415 }
416 #endif
417
418 static struct platform_driver baseband_power2_driver = {
419         .probe = xmm_power2_probe,
420         .remove = xmm_power2_remove,
421 #ifdef CONFIG_PM
422         .suspend = xmm_power2_suspend,
423         .resume = xmm_power2_resume,
424 #endif
425         .driver = {
426                 .name = "baseband_xmm_power2",
427         },
428 };
429
430 static int __init xmm_power2_init(void)
431 {
432         pr_debug("%s\n", __func__);
433
434         return platform_driver_register(&baseband_power2_driver);
435 }
436
437 static void __exit xmm_power2_exit(void)
438 {
439         pr_debug("%s\n", __func__);
440
441         platform_driver_unregister(&baseband_power2_driver);
442 }
443
444 module_init(xmm_power2_init)
445 module_exit(xmm_power2_exit)
446
447 MODULE_LICENSE("GPL");