rtc: tps80031: register as mfd sub device
[linux-2.6.git] / arch / arm / mach-tegra / wakeups.c
1 /*
2  * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms and conditions of the GNU General Public License,
6  * version 2, as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope it will be useful, but WITHOUT
9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
11  * more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15  */
16
17 #include <linux/kernel.h>
18 #include <linux/gpio.h>
19 #include <linux/init.h>
20 #include <linux/io.h>
21 #include <linux/interrupt.h>
22
23 #include <mach/iomap.h>
24 #include <mach/irqs.h>
25 #include <mach/gpio.h>
26
27 #include "gpio-names.h"
28 #include "wakeups.h"
29
30 extern struct tegra_wake_info *tegra_wake_event_data;
31 extern unsigned int tegra_wake_event_data_size;
32
33 /*
34  * FIXME: unable to pass rising and falling
35  * flags from usb driver hence using polarity field
36  * from wake table to set wake_mask_any
37  * for selected usb wake sources - VBUS and ID
38  */
39 static int update_wake_mask(unsigned int index, int flow_type,
40         struct wake_mask_types *wake_msk)
41 {
42         int trigger_val;
43         /*
44          * set wake function calls with flow_type as -1
45          * set wake type function calls update_wake_mask with
46          * the wake polarity
47          */
48         if (flow_type == -1) {
49                 pr_debug("Wake%d flow_type=%d\n",
50                         index, flow_type);
51                 /* use argument wake_mask_hi to return mask */
52                 wake_msk->wake_mask_hi |= (1ULL << index);
53         } else {
54                 trigger_val = (flow_type & IRQF_TRIGGER_MASK);
55                 if ((tegra_wake_event_data[index].polarity ==
56                         POLARITY_EDGE_ANY) ||
57                         (trigger_val ==
58                         (IRQF_TRIGGER_RISING |
59                         IRQF_TRIGGER_FALLING))) {
60                         pr_debug("Wake%d flow_type=ANY\n", index);
61                         wake_msk->wake_mask_any |= (1ULL << index);
62                 } else if ((trigger_val == IRQF_TRIGGER_HIGH) ||
63                         (trigger_val == IRQF_TRIGGER_RISING)) {
64                         pr_debug("Wake%d flow_type=HI\n", index);
65                         wake_msk->wake_mask_hi |= (1ULL << index);
66                 } else if ((trigger_val == IRQF_TRIGGER_LOW) ||
67                         (trigger_val == IRQF_TRIGGER_FALLING)) {
68                         pr_debug("Wake%d flow_type=LO\n", index);
69                         wake_msk->wake_mask_lo |= (1ULL << index);
70                 } else {
71                         pr_err("Error: Wake%d UNKNOWN flow_type=%d\n",
72                                 index, flow_type);
73                         return -EINVAL;
74                 }
75         }
76         return 0;
77 }
78
79 int tegra_irq_to_wake(unsigned int irq, int flow_type,
80         struct wake_mask_types *wake_msk)
81 {
82         int i;
83         int err;
84
85         wake_msk->wake_mask_hi = 0ULL;
86         wake_msk->wake_mask_lo = 0ULL;
87         wake_msk->wake_mask_any = 0ULL;
88         /*
89          * check for irq based on tegra_wake_event_data table
90          */
91         for (i = 0; i < tegra_wake_event_data_size; i++) {
92                 if (tegra_wake_event_data[i].irq == irq) {
93                         err = update_wake_mask(i, flow_type, wake_msk);
94                         if (err)
95                                 return err;
96                         continue;
97                 }
98         }
99
100         if (wake_msk->wake_mask_hi || wake_msk->wake_mask_lo ||
101                 wake_msk->wake_mask_any) {
102                 pr_debug("Enabling wake sources for irq=%d, mask hi=%#llx, lo=%#llx, any=%#llx, flow_type=%d\n",
103                         irq, wake_msk->wake_mask_hi, wake_msk->wake_mask_lo,
104                         wake_msk->wake_mask_any, flow_type);
105                 return 0;
106         }
107         return -EINVAL;
108 }
109
110 int tegra_wake_to_irq(int wake)
111 {
112         if (wake < 0)
113                 return -EINVAL;
114
115         if (wake >= tegra_wake_event_data_size)
116                 return -EINVAL;
117
118         return tegra_wake_event_data[wake].irq;
119 }
120
121 int tegra_disable_wake_source(int wake)
122 {
123         if (wake >= tegra_wake_event_data_size)
124                 return -EINVAL;
125
126         tegra_wake_event_data[wake].irq = -EINVAL;
127
128         return 0;
129 }
130