diff options
author | Uwe Kleine-König <u.kleine-koenig@pengutronix.de> | 2009-11-29 18:53:17 -0500 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2009-12-13 13:21:54 -0500 |
commit | 9e2726776d45b1e383625b3ce4f8b511456e09ad (patch) | |
tree | 732a12aaa78af36fa5cb345a0210ac7e415082b5 /drivers/mfd/mc13783-core.c | |
parent | d7f81c4416a2246c8f03441d52a219af7c109850 (diff) |
mfd: Near complete mc13783 rewrite
This fixes several things while still providing the old API:
- simplify and fix locking
- better error handling
- don't ack all irqs making it impossible to detect a reset of the
rtc
- use a timeout variant to wait for completion of ADC conversion
- provide platform-data to regulator subdevice (This allows making
struct mc13783 opaque for other drivers after the regulator driver is
updated to use its platform_data.)
- expose all interrupts
- use threaded irq
After all users in mainline are converted to the new API, some things
(e.g. mc13783-private.h) can go away.
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Cc: Sascha Hauer <s.hauer@pengutronix.de>
Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/mfd/mc13783-core.c')
-rw-r--r-- | drivers/mfd/mc13783-core.c | 755 |
1 files changed, 506 insertions, 249 deletions
diff --git a/drivers/mfd/mc13783-core.c b/drivers/mfd/mc13783-core.c index e354d2912ef1..dc1add0c4949 100644 --- a/drivers/mfd/mc13783-core.c +++ b/drivers/mfd/mc13783-core.c | |||
@@ -1,286 +1,549 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright 2009 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de> | 2 | * Copyright 2009 Pengutronix |
3 | * | 3 | * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de> |
4 | * This code is in parts based on wm8350-core.c and pcf50633-core.c | ||
5 | * | ||
6 | * Initial development of this code was funded by | ||
7 | * Phytec Messtechnik GmbH, http://www.phytec.de | ||
8 | * | 4 | * |
9 | * This program is free software; you can redistribute it and/or modify | 5 | * loosely based on an earlier driver that has |
10 | * it under the terms of the GNU General Public License as published by | 6 | * Copyright 2009 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de> |
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | 7 | * |
19 | * You should have received a copy of the GNU General Public License | 8 | * This program is free software; you can redistribute it and/or modify it under |
20 | * along with this program; if not, write to the Free Software | 9 | * the terms of the GNU General Public License version 2 as published by the |
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 10 | * Free Software Foundation. |
22 | */ | 11 | */ |
23 | |||
24 | #include <linux/mfd/mc13783-private.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/mfd/mc13783.h> | ||
27 | #include <linux/completion.h> | ||
28 | #include <linux/interrupt.h> | ||
29 | #include <linux/mfd/core.h> | ||
30 | #include <linux/spi/spi.h> | ||
31 | #include <linux/uaccess.h> | ||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/module.h> | 12 | #include <linux/module.h> |
34 | #include <linux/init.h> | 13 | #include <linux/spi/spi.h> |
35 | #include <linux/slab.h> | 14 | #include <linux/mfd/core.h> |
36 | #include <linux/irq.h> | 15 | #include <linux/mfd/mc13783-private.h> |
16 | |||
17 | #define MC13783_IRQSTAT0 0 | ||
18 | #define MC13783_IRQSTAT0_ADCDONEI (1 << 0) | ||
19 | #define MC13783_IRQSTAT0_ADCBISDONEI (1 << 1) | ||
20 | #define MC13783_IRQSTAT0_TSI (1 << 2) | ||
21 | #define MC13783_IRQSTAT0_WHIGHI (1 << 3) | ||
22 | #define MC13783_IRQSTAT0_WLOWI (1 << 4) | ||
23 | #define MC13783_IRQSTAT0_CHGDETI (1 << 6) | ||
24 | #define MC13783_IRQSTAT0_CHGOVI (1 << 7) | ||
25 | #define MC13783_IRQSTAT0_CHGREVI (1 << 8) | ||
26 | #define MC13783_IRQSTAT0_CHGSHORTI (1 << 9) | ||
27 | #define MC13783_IRQSTAT0_CCCVI (1 << 10) | ||
28 | #define MC13783_IRQSTAT0_CHGCURRI (1 << 11) | ||
29 | #define MC13783_IRQSTAT0_BPONI (1 << 12) | ||
30 | #define MC13783_IRQSTAT0_LOBATLI (1 << 13) | ||
31 | #define MC13783_IRQSTAT0_LOBATHI (1 << 14) | ||
32 | #define MC13783_IRQSTAT0_UDPI (1 << 15) | ||
33 | #define MC13783_IRQSTAT0_USBI (1 << 16) | ||
34 | #define MC13783_IRQSTAT0_IDI (1 << 19) | ||
35 | #define MC13783_IRQSTAT0_SE1I (1 << 21) | ||
36 | #define MC13783_IRQSTAT0_CKDETI (1 << 22) | ||
37 | #define MC13783_IRQSTAT0_UDMI (1 << 23) | ||
38 | |||
39 | #define MC13783_IRQMASK0 1 | ||
40 | #define MC13783_IRQMASK0_ADCDONEM MC13783_IRQSTAT0_ADCDONEI | ||
41 | #define MC13783_IRQMASK0_ADCBISDONEM MC13783_IRQSTAT0_ADCBISDONEI | ||
42 | #define MC13783_IRQMASK0_TSM MC13783_IRQSTAT0_TSI | ||
43 | #define MC13783_IRQMASK0_WHIGHM MC13783_IRQSTAT0_WHIGHI | ||
44 | #define MC13783_IRQMASK0_WLOWM MC13783_IRQSTAT0_WLOWI | ||
45 | #define MC13783_IRQMASK0_CHGDETM MC13783_IRQSTAT0_CHGDETI | ||
46 | #define MC13783_IRQMASK0_CHGOVM MC13783_IRQSTAT0_CHGOVI | ||
47 | #define MC13783_IRQMASK0_CHGREVM MC13783_IRQSTAT0_CHGREVI | ||
48 | #define MC13783_IRQMASK0_CHGSHORTM MC13783_IRQSTAT0_CHGSHORTI | ||
49 | #define MC13783_IRQMASK0_CCCVM MC13783_IRQSTAT0_CCCVI | ||
50 | #define MC13783_IRQMASK0_CHGCURRM MC13783_IRQSTAT0_CHGCURRI | ||
51 | #define MC13783_IRQMASK0_BPONM MC13783_IRQSTAT0_BPONI | ||
52 | #define MC13783_IRQMASK0_LOBATLM MC13783_IRQSTAT0_LOBATLI | ||
53 | #define MC13783_IRQMASK0_LOBATHM MC13783_IRQSTAT0_LOBATHI | ||
54 | #define MC13783_IRQMASK0_UDPM MC13783_IRQSTAT0_UDPI | ||
55 | #define MC13783_IRQMASK0_USBM MC13783_IRQSTAT0_USBI | ||
56 | #define MC13783_IRQMASK0_IDM MC13783_IRQSTAT0_IDI | ||
57 | #define MC13783_IRQMASK0_SE1M MC13783_IRQSTAT0_SE1I | ||
58 | #define MC13783_IRQMASK0_CKDETM MC13783_IRQSTAT0_CKDETI | ||
59 | #define MC13783_IRQMASK0_UDMM MC13783_IRQSTAT0_UDMI | ||
60 | |||
61 | #define MC13783_IRQSTAT1 3 | ||
62 | #define MC13783_IRQSTAT1_1HZI (1 << 0) | ||
63 | #define MC13783_IRQSTAT1_TODAI (1 << 1) | ||
64 | #define MC13783_IRQSTAT1_ONOFD1I (1 << 3) | ||
65 | #define MC13783_IRQSTAT1_ONOFD2I (1 << 4) | ||
66 | #define MC13783_IRQSTAT1_ONOFD3I (1 << 5) | ||
67 | #define MC13783_IRQSTAT1_SYSRSTI (1 << 6) | ||
68 | #define MC13783_IRQSTAT1_RTCRSTI (1 << 7) | ||
69 | #define MC13783_IRQSTAT1_PCI (1 << 8) | ||
70 | #define MC13783_IRQSTAT1_WARMI (1 << 9) | ||
71 | #define MC13783_IRQSTAT1_MEMHLDI (1 << 10) | ||
72 | #define MC13783_IRQSTAT1_PWRRDYI (1 << 11) | ||
73 | #define MC13783_IRQSTAT1_THWARNLI (1 << 12) | ||
74 | #define MC13783_IRQSTAT1_THWARNHI (1 << 13) | ||
75 | #define MC13783_IRQSTAT1_CLKI (1 << 14) | ||
76 | #define MC13783_IRQSTAT1_SEMAFI (1 << 15) | ||
77 | #define MC13783_IRQSTAT1_MC2BI (1 << 17) | ||
78 | #define MC13783_IRQSTAT1_HSDETI (1 << 18) | ||
79 | #define MC13783_IRQSTAT1_HSLI (1 << 19) | ||
80 | #define MC13783_IRQSTAT1_ALSPTHI (1 << 20) | ||
81 | #define MC13783_IRQSTAT1_AHSSHORTI (1 << 21) | ||
82 | |||
83 | #define MC13783_IRQMASK1 4 | ||
84 | #define MC13783_IRQMASK1_1HZM MC13783_IRQSTAT1_1HZI | ||
85 | #define MC13783_IRQMASK1_TODAM MC13783_IRQSTAT1_TODAI | ||
86 | #define MC13783_IRQMASK1_ONOFD1M MC13783_IRQSTAT1_ONOFD1I | ||
87 | #define MC13783_IRQMASK1_ONOFD2M MC13783_IRQSTAT1_ONOFD2I | ||
88 | #define MC13783_IRQMASK1_ONOFD3M MC13783_IRQSTAT1_ONOFD3I | ||
89 | #define MC13783_IRQMASK1_SYSRSTM MC13783_IRQSTAT1_SYSRSTI | ||
90 | #define MC13783_IRQMASK1_RTCRSTM MC13783_IRQSTAT1_RTCRSTI | ||
91 | #define MC13783_IRQMASK1_PCM MC13783_IRQSTAT1_PCI | ||
92 | #define MC13783_IRQMASK1_WARMM MC13783_IRQSTAT1_WARMI | ||
93 | #define MC13783_IRQMASK1_MEMHLDM MC13783_IRQSTAT1_MEMHLDI | ||
94 | #define MC13783_IRQMASK1_PWRRDYM MC13783_IRQSTAT1_PWRRDYI | ||
95 | #define MC13783_IRQMASK1_THWARNLM MC13783_IRQSTAT1_THWARNLI | ||
96 | #define MC13783_IRQMASK1_THWARNHM MC13783_IRQSTAT1_THWARNHI | ||
97 | #define MC13783_IRQMASK1_CLKM MC13783_IRQSTAT1_CLKI | ||
98 | #define MC13783_IRQMASK1_SEMAFM MC13783_IRQSTAT1_SEMAFI | ||
99 | #define MC13783_IRQMASK1_MC2BM MC13783_IRQSTAT1_MC2BI | ||
100 | #define MC13783_IRQMASK1_HSDETM MC13783_IRQSTAT1_HSDETI | ||
101 | #define MC13783_IRQMASK1_HSLM MC13783_IRQSTAT1_HSLI | ||
102 | #define MC13783_IRQMASK1_ALSPTHM MC13783_IRQSTAT1_ALSPTHI | ||
103 | #define MC13783_IRQMASK1_AHSSHORTM MC13783_IRQSTAT1_AHSSHORTI | ||
104 | |||
105 | #define MC13783_ADC1 44 | ||
106 | #define MC13783_ADC1_ADEN (1 << 0) | ||
107 | #define MC13783_ADC1_RAND (1 << 1) | ||
108 | #define MC13783_ADC1_ADSEL (1 << 3) | ||
109 | #define MC13783_ADC1_ASC (1 << 20) | ||
110 | #define MC13783_ADC1_ADTRIGIGN (1 << 21) | ||
111 | |||
112 | #define MC13783_NUMREGS 0x3f | ||
113 | |||
114 | void mc13783_lock(struct mc13783 *mc13783) | ||
115 | { | ||
116 | if (!mutex_trylock(&mc13783->lock)) { | ||
117 | dev_dbg(&mc13783->spidev->dev, "wait for %s from %pf\n", | ||
118 | __func__, __builtin_return_address(0)); | ||
119 | |||
120 | mutex_lock(&mc13783->lock); | ||
121 | } | ||
122 | dev_dbg(&mc13783->spidev->dev, "%s from %pf\n", | ||
123 | __func__, __builtin_return_address(0)); | ||
124 | } | ||
125 | EXPORT_SYMBOL(mc13783_lock); | ||
37 | 126 | ||
38 | #define MC13783_MAX_REG_NUM 0x3f | 127 | void mc13783_unlock(struct mc13783 *mc13783) |
39 | #define MC13783_FRAME_MASK 0x00ffffff | 128 | { |
40 | #define MC13783_MAX_REG_NUM 0x3f | 129 | dev_dbg(&mc13783->spidev->dev, "%s from %pf\n", |
41 | #define MC13783_REG_NUM_SHIFT 0x19 | 130 | __func__, __builtin_return_address(0)); |
42 | #define MC13783_WRITE_BIT_SHIFT 31 | 131 | mutex_unlock(&mc13783->lock); |
132 | } | ||
133 | EXPORT_SYMBOL(mc13783_unlock); | ||
43 | 134 | ||
44 | static inline int spi_rw(struct spi_device *spi, u8 * buf, size_t len) | 135 | #define MC13783_REGOFFSET_SHIFT 25 |
136 | int mc13783_reg_read(struct mc13783 *mc13783, unsigned int offset, u32 *val) | ||
45 | { | 137 | { |
46 | struct spi_transfer t = { | 138 | struct spi_transfer t; |
47 | .tx_buf = (const void *)buf, | ||
48 | .rx_buf = buf, | ||
49 | .len = len, | ||
50 | .cs_change = 0, | ||
51 | .delay_usecs = 0, | ||
52 | }; | ||
53 | struct spi_message m; | 139 | struct spi_message m; |
140 | int ret; | ||
141 | |||
142 | BUG_ON(!mutex_is_locked(&mc13783->lock)); | ||
143 | |||
144 | if (offset > MC13783_NUMREGS) | ||
145 | return -EINVAL; | ||
146 | |||
147 | *val = offset << MC13783_REGOFFSET_SHIFT; | ||
148 | |||
149 | memset(&t, 0, sizeof(t)); | ||
150 | |||
151 | t.tx_buf = val; | ||
152 | t.rx_buf = val; | ||
153 | t.len = sizeof(u32); | ||
54 | 154 | ||
55 | spi_message_init(&m); | 155 | spi_message_init(&m); |
56 | spi_message_add_tail(&t, &m); | 156 | spi_message_add_tail(&t, &m); |
57 | if (spi_sync(spi, &m) != 0 || m.status != 0) | ||
58 | return -EINVAL; | ||
59 | return len - m.actual_length; | ||
60 | } | ||
61 | 157 | ||
62 | static int mc13783_read(struct mc13783 *mc13783, int reg_num, u32 *reg_val) | 158 | ret = spi_sync(mc13783->spidev, &m); |
63 | { | ||
64 | unsigned int frame = 0; | ||
65 | int ret = 0; | ||
66 | 159 | ||
67 | if (reg_num > MC13783_MAX_REG_NUM) | 160 | /* error in message.status implies error return from spi_sync */ |
68 | return -EINVAL; | 161 | BUG_ON(!ret && m.status); |
69 | 162 | ||
70 | frame |= reg_num << MC13783_REG_NUM_SHIFT; | 163 | if (ret) |
164 | return ret; | ||
71 | 165 | ||
72 | ret = spi_rw(mc13783->spi_device, (u8 *)&frame, 4); | 166 | *val &= 0xffffff; |
73 | 167 | ||
74 | *reg_val = frame & MC13783_FRAME_MASK; | 168 | dev_vdbg(&mc13783->spidev->dev, "[0x%02x] -> 0x%06x\n", offset, *val); |
75 | 169 | ||
76 | return ret; | 170 | return 0; |
77 | } | 171 | } |
172 | EXPORT_SYMBOL(mc13783_reg_read); | ||
78 | 173 | ||
79 | static int mc13783_write(struct mc13783 *mc13783, int reg_num, u32 reg_val) | 174 | int mc13783_reg_write(struct mc13783 *mc13783, unsigned int offset, u32 val) |
80 | { | 175 | { |
81 | unsigned int frame = 0; | 176 | u32 buf; |
177 | struct spi_transfer t; | ||
178 | struct spi_message m; | ||
179 | int ret; | ||
180 | |||
181 | BUG_ON(!mutex_is_locked(&mc13783->lock)); | ||
82 | 182 | ||
83 | if (reg_num > MC13783_MAX_REG_NUM) | 183 | dev_vdbg(&mc13783->spidev->dev, "[0x%02x] <- 0x%06x\n", offset, val); |
184 | |||
185 | if (offset > MC13783_NUMREGS || val > 0xffffff) | ||
84 | return -EINVAL; | 186 | return -EINVAL; |
85 | 187 | ||
86 | frame |= (1 << MC13783_WRITE_BIT_SHIFT); | 188 | buf = 1 << 31 | offset << MC13783_REGOFFSET_SHIFT | val; |
87 | frame |= reg_num << MC13783_REG_NUM_SHIFT; | 189 | |
88 | frame |= reg_val & MC13783_FRAME_MASK; | 190 | memset(&t, 0, sizeof(t)); |
89 | 191 | ||
90 | return spi_rw(mc13783->spi_device, (u8 *)&frame, 4); | 192 | t.tx_buf = &buf; |
193 | t.rx_buf = &buf; | ||
194 | t.len = sizeof(u32); | ||
195 | |||
196 | spi_message_init(&m); | ||
197 | spi_message_add_tail(&t, &m); | ||
198 | |||
199 | ret = spi_sync(mc13783->spidev, &m); | ||
200 | |||
201 | BUG_ON(!ret && m.status); | ||
202 | |||
203 | if (ret) | ||
204 | return ret; | ||
205 | |||
206 | return 0; | ||
91 | } | 207 | } |
208 | EXPORT_SYMBOL(mc13783_reg_write); | ||
92 | 209 | ||
93 | int mc13783_reg_read(struct mc13783 *mc13783, int reg_num, u32 *reg_val) | 210 | int mc13783_reg_rmw(struct mc13783 *mc13783, unsigned int offset, |
211 | u32 mask, u32 val) | ||
94 | { | 212 | { |
95 | int ret; | 213 | int ret; |
214 | u32 valread; | ||
96 | 215 | ||
97 | mutex_lock(&mc13783->io_lock); | 216 | BUG_ON(val & ~mask); |
98 | ret = mc13783_read(mc13783, reg_num, reg_val); | ||
99 | mutex_unlock(&mc13783->io_lock); | ||
100 | 217 | ||
101 | return ret; | 218 | ret = mc13783_reg_read(mc13783, offset, &valread); |
219 | if (ret) | ||
220 | return ret; | ||
221 | |||
222 | valread = (valread & ~mask) | val; | ||
223 | |||
224 | return mc13783_reg_write(mc13783, offset, valread); | ||
102 | } | 225 | } |
103 | EXPORT_SYMBOL_GPL(mc13783_reg_read); | 226 | EXPORT_SYMBOL(mc13783_reg_rmw); |
104 | 227 | ||
105 | int mc13783_reg_write(struct mc13783 *mc13783, int reg_num, u32 reg_val) | 228 | int mc13783_mask(struct mc13783 *mc13783, int irq) |
106 | { | 229 | { |
107 | int ret; | 230 | int ret; |
231 | unsigned int offmask = irq < 24 ? MC13783_IRQMASK0 : MC13783_IRQMASK1; | ||
232 | u32 irqbit = 1 << (irq < 24 ? irq : irq - 24); | ||
233 | u32 mask; | ||
108 | 234 | ||
109 | mutex_lock(&mc13783->io_lock); | 235 | if (irq < 0 || irq >= MC13783_NUM_IRQ) |
110 | ret = mc13783_write(mc13783, reg_num, reg_val); | 236 | return -EINVAL; |
111 | mutex_unlock(&mc13783->io_lock); | ||
112 | 237 | ||
113 | return ret; | 238 | ret = mc13783_reg_read(mc13783, offmask, &mask); |
239 | if (ret) | ||
240 | return ret; | ||
241 | |||
242 | if (mask & irqbit) | ||
243 | /* already masked */ | ||
244 | return 0; | ||
245 | |||
246 | return mc13783_reg_write(mc13783, offmask, mask | irqbit); | ||
114 | } | 247 | } |
115 | EXPORT_SYMBOL_GPL(mc13783_reg_write); | 248 | EXPORT_SYMBOL(mc13783_mask); |
116 | 249 | ||
117 | /** | 250 | int mc13783_unmask(struct mc13783 *mc13783, int irq) |
118 | * mc13783_set_bits - Bitmask write | ||
119 | * | ||
120 | * @mc13783: Pointer to mc13783 control structure | ||
121 | * @reg: Register to access | ||
122 | * @mask: Mask of bits to change | ||
123 | * @val: Value to set for masked bits | ||
124 | */ | ||
125 | int mc13783_set_bits(struct mc13783 *mc13783, int reg, u32 mask, u32 val) | ||
126 | { | 251 | { |
127 | u32 tmp; | ||
128 | int ret; | 252 | int ret; |
253 | unsigned int offmask = irq < 24 ? MC13783_IRQMASK0 : MC13783_IRQMASK1; | ||
254 | u32 irqbit = 1 << (irq < 24 ? irq : irq - 24); | ||
255 | u32 mask; | ||
129 | 256 | ||
130 | mutex_lock(&mc13783->io_lock); | 257 | if (irq < 0 || irq >= MC13783_NUM_IRQ) |
258 | return -EINVAL; | ||
131 | 259 | ||
132 | ret = mc13783_read(mc13783, reg, &tmp); | 260 | ret = mc13783_reg_read(mc13783, offmask, &mask); |
133 | tmp = (tmp & ~mask) | val; | 261 | if (ret) |
134 | if (ret == 0) | 262 | return ret; |
135 | ret = mc13783_write(mc13783, reg, tmp); | ||
136 | 263 | ||
137 | mutex_unlock(&mc13783->io_lock); | 264 | if (!(mask & irqbit)) |
265 | /* already unmasked */ | ||
266 | return 0; | ||
138 | 267 | ||
139 | return ret; | 268 | return mc13783_reg_write(mc13783, offmask, mask & ~irqbit); |
140 | } | 269 | } |
141 | EXPORT_SYMBOL_GPL(mc13783_set_bits); | 270 | EXPORT_SYMBOL(mc13783_unmask); |
142 | 271 | ||
143 | int mc13783_register_irq(struct mc13783 *mc13783, int irq, | 272 | int mc13783_irq_request_nounmask(struct mc13783 *mc13783, int irq, |
144 | void (*handler) (int, void *), void *data) | 273 | irq_handler_t handler, const char *name, void *dev) |
145 | { | 274 | { |
146 | if (irq < 0 || irq > MC13783_NUM_IRQ || !handler) | 275 | BUG_ON(!mutex_is_locked(&mc13783->lock)); |
276 | BUG_ON(!handler); | ||
277 | |||
278 | if (irq < 0 || irq >= MC13783_NUM_IRQ) | ||
147 | return -EINVAL; | 279 | return -EINVAL; |
148 | 280 | ||
149 | if (WARN_ON(mc13783->irq_handler[irq].handler)) | 281 | if (mc13783->irqhandler[irq]) |
150 | return -EBUSY; | 282 | return -EBUSY; |
151 | 283 | ||
152 | mutex_lock(&mc13783->io_lock); | 284 | mc13783->irqhandler[irq] = handler; |
153 | mc13783->irq_handler[irq].handler = handler; | 285 | mc13783->irqdata[irq] = dev; |
154 | mc13783->irq_handler[irq].data = data; | ||
155 | mutex_unlock(&mc13783->io_lock); | ||
156 | 286 | ||
157 | return 0; | 287 | return 0; |
158 | } | 288 | } |
159 | EXPORT_SYMBOL_GPL(mc13783_register_irq); | 289 | EXPORT_SYMBOL(mc13783_irq_request_nounmask); |
160 | 290 | ||
161 | int mc13783_free_irq(struct mc13783 *mc13783, int irq) | 291 | int mc13783_irq_request(struct mc13783 *mc13783, int irq, |
292 | irq_handler_t handler, const char *name, void *dev) | ||
162 | { | 293 | { |
163 | if (irq < 0 || irq > MC13783_NUM_IRQ) | 294 | int ret; |
295 | |||
296 | ret = mc13783_irq_request_nounmask(mc13783, irq, handler, name, dev); | ||
297 | if (ret) | ||
298 | return ret; | ||
299 | |||
300 | ret = mc13783_unmask(mc13783, irq); | ||
301 | if (ret) { | ||
302 | mc13783->irqhandler[irq] = NULL; | ||
303 | mc13783->irqdata[irq] = NULL; | ||
304 | return ret; | ||
305 | } | ||
306 | |||
307 | return 0; | ||
308 | } | ||
309 | EXPORT_SYMBOL(mc13783_irq_request); | ||
310 | |||
311 | int mc13783_irq_free(struct mc13783 *mc13783, int irq, void *dev) | ||
312 | { | ||
313 | int ret; | ||
314 | BUG_ON(!mutex_is_locked(&mc13783->lock)); | ||
315 | |||
316 | if (irq < 0 || irq >= MC13783_NUM_IRQ || !mc13783->irqhandler[irq] || | ||
317 | mc13783->irqdata[irq] != dev) | ||
164 | return -EINVAL; | 318 | return -EINVAL; |
165 | 319 | ||
166 | mutex_lock(&mc13783->io_lock); | 320 | ret = mc13783_mask(mc13783, irq); |
167 | mc13783->irq_handler[irq].handler = NULL; | 321 | if (ret) |
168 | mutex_unlock(&mc13783->io_lock); | 322 | return ret; |
323 | |||
324 | mc13783->irqhandler[irq] = NULL; | ||
325 | mc13783->irqdata[irq] = NULL; | ||
169 | 326 | ||
170 | return 0; | 327 | return 0; |
171 | } | 328 | } |
172 | EXPORT_SYMBOL_GPL(mc13783_free_irq); | 329 | EXPORT_SYMBOL(mc13783_irq_free); |
173 | 330 | ||
174 | static void mc13783_irq_work(struct work_struct *work) | 331 | static inline irqreturn_t mc13783_irqhandler(struct mc13783 *mc13783, int irq) |
175 | { | 332 | { |
176 | struct mc13783 *mc13783 = container_of(work, struct mc13783, work); | 333 | return mc13783->irqhandler[irq](irq, mc13783->irqdata[irq]); |
177 | int i; | ||
178 | unsigned int adc_sts; | ||
179 | |||
180 | /* check if the adc has finished any completion */ | ||
181 | mc13783_reg_read(mc13783, MC13783_REG_INTERRUPT_STATUS_0, &adc_sts); | ||
182 | mc13783_reg_write(mc13783, MC13783_REG_INTERRUPT_STATUS_0, | ||
183 | adc_sts & MC13783_INT_STAT_ADCDONEI); | ||
184 | |||
185 | if (adc_sts & MC13783_INT_STAT_ADCDONEI) | ||
186 | complete_all(&mc13783->adc_done); | ||
187 | |||
188 | for (i = 0; i < MC13783_NUM_IRQ; i++) | ||
189 | if (mc13783->irq_handler[i].handler) | ||
190 | mc13783->irq_handler[i].handler(i, | ||
191 | mc13783->irq_handler[i].data); | ||
192 | enable_irq(mc13783->irq); | ||
193 | } | 334 | } |
194 | 335 | ||
195 | static irqreturn_t mc13783_interrupt(int irq, void *dev_id) | 336 | int mc13783_ackirq(struct mc13783 *mc13783, int irq) |
196 | { | 337 | { |
197 | struct mc13783 *mc13783 = dev_id; | 338 | unsigned int offstat = irq < 24 ? MC13783_IRQSTAT0 : MC13783_IRQSTAT1; |
339 | unsigned int val = 1 << (irq < 24 ? irq : irq - 24); | ||
198 | 340 | ||
199 | disable_irq_nosync(irq); | 341 | BUG_ON(irq < 0 || irq >= MC13783_NUM_IRQ); |
200 | 342 | ||
201 | schedule_work(&mc13783->work); | 343 | return mc13783_reg_write(mc13783, offstat, val); |
202 | return IRQ_HANDLED; | ||
203 | } | 344 | } |
345 | EXPORT_SYMBOL(mc13783_ackirq); | ||
204 | 346 | ||
205 | /* set adc to ts interrupt mode, which generates touchscreen wakeup interrupt */ | 347 | /* |
206 | static inline void mc13783_adc_set_ts_irq_mode(struct mc13783 *mc13783) | 348 | * returns: number of handled irqs or negative error |
349 | * locking: holds mc13783->lock | ||
350 | */ | ||
351 | static int mc13783_irq_handle(struct mc13783 *mc13783, | ||
352 | unsigned int offstat, unsigned int offmask, int baseirq) | ||
207 | { | 353 | { |
208 | unsigned int reg_adc0, reg_adc1; | 354 | u32 stat, mask; |
355 | int ret = mc13783_reg_read(mc13783, offstat, &stat); | ||
356 | int num_handled = 0; | ||
357 | |||
358 | if (ret) | ||
359 | return ret; | ||
360 | |||
361 | ret = mc13783_reg_read(mc13783, offmask, &mask); | ||
362 | if (ret) | ||
363 | return ret; | ||
364 | |||
365 | while (stat & ~mask) { | ||
366 | int irq = __ffs(stat & ~mask); | ||
367 | |||
368 | stat &= ~(1 << irq); | ||
369 | |||
370 | if (likely(mc13783->irqhandler[baseirq + irq])) { | ||
371 | irqreturn_t handled; | ||
209 | 372 | ||
210 | reg_adc0 = MC13783_ADC0_ADREFEN | MC13783_ADC0_ADREFMODE | 373 | handled = mc13783_irqhandler(mc13783, baseirq + irq); |
211 | | MC13783_ADC0_TSMOD0; | 374 | if (handled == IRQ_HANDLED) |
212 | reg_adc1 = MC13783_ADC1_ADEN | MC13783_ADC1_ADTRIGIGN; | 375 | num_handled++; |
376 | } else { | ||
377 | dev_err(&mc13783->spidev->dev, | ||
378 | "BUG: irq %u but no handler\n", | ||
379 | baseirq + irq); | ||
213 | 380 | ||
214 | mc13783_reg_write(mc13783, MC13783_REG_ADC_0, reg_adc0); | 381 | mask |= 1 << irq; |
215 | mc13783_reg_write(mc13783, MC13783_REG_ADC_1, reg_adc1); | 382 | |
383 | ret = mc13783_reg_write(mc13783, offmask, mask); | ||
384 | } | ||
385 | } | ||
386 | |||
387 | return num_handled; | ||
216 | } | 388 | } |
217 | 389 | ||
390 | static irqreturn_t mc13783_irq_thread(int irq, void *data) | ||
391 | { | ||
392 | struct mc13783 *mc13783 = data; | ||
393 | irqreturn_t ret; | ||
394 | int handled = 0; | ||
395 | |||
396 | mc13783_lock(mc13783); | ||
397 | |||
398 | ret = mc13783_irq_handle(mc13783, MC13783_IRQSTAT0, | ||
399 | MC13783_IRQMASK0, MC13783_IRQ_ADCDONE); | ||
400 | if (ret > 0) | ||
401 | handled = 1; | ||
402 | |||
403 | ret = mc13783_irq_handle(mc13783, MC13783_IRQSTAT1, | ||
404 | MC13783_IRQMASK1, MC13783_IRQ_1HZ); | ||
405 | if (ret > 0) | ||
406 | handled = 1; | ||
407 | |||
408 | mc13783_unlock(mc13783); | ||
409 | |||
410 | return IRQ_RETVAL(handled); | ||
411 | } | ||
412 | |||
413 | #define MC13783_ADC1_CHAN0_SHIFT 5 | ||
414 | #define MC13783_ADC1_CHAN1_SHIFT 8 | ||
415 | |||
416 | struct mc13783_adcdone_data { | ||
417 | struct mc13783 *mc13783; | ||
418 | struct completion done; | ||
419 | }; | ||
420 | |||
421 | static irqreturn_t mc13783_handler_adcdone(int irq, void *data) | ||
422 | { | ||
423 | struct mc13783_adcdone_data *adcdone_data = data; | ||
424 | |||
425 | mc13783_ackirq(adcdone_data->mc13783, irq); | ||
426 | |||
427 | complete_all(&adcdone_data->done); | ||
428 | |||
429 | return IRQ_HANDLED; | ||
430 | } | ||
431 | |||
432 | #define MC13783_ADC_WORKING (1 << 16) | ||
433 | |||
218 | int mc13783_adc_do_conversion(struct mc13783 *mc13783, unsigned int mode, | 434 | int mc13783_adc_do_conversion(struct mc13783 *mc13783, unsigned int mode, |
219 | unsigned int channel, unsigned int *sample) | 435 | unsigned int channel, unsigned int *sample) |
220 | { | 436 | { |
221 | unsigned int reg_adc0, reg_adc1; | 437 | u32 adc0, adc1, old_adc0; |
222 | int i; | 438 | int i, ret; |
439 | struct mc13783_adcdone_data adcdone_data = { | ||
440 | .mc13783 = mc13783, | ||
441 | }; | ||
442 | init_completion(&adcdone_data.done); | ||
443 | |||
444 | dev_dbg(&mc13783->spidev->dev, "%s\n", __func__); | ||
445 | |||
446 | mc13783_lock(mc13783); | ||
447 | |||
448 | if (mc13783->flags & MC13783_ADC_WORKING) { | ||
449 | ret = -EBUSY; | ||
450 | goto out; | ||
451 | } | ||
452 | |||
453 | mc13783->flags |= MC13783_ADC_WORKING; | ||
223 | 454 | ||
224 | mutex_lock(&mc13783->adc_conv_lock); | 455 | mc13783_reg_read(mc13783, MC13783_ADC0, &old_adc0); |
225 | 456 | ||
226 | /* set up auto incrementing anyway to make quick read */ | 457 | adc0 = MC13783_ADC0_ADINC1 | MC13783_ADC0_ADINC2; |
227 | reg_adc0 = MC13783_ADC0_ADINC1 | MC13783_ADC0_ADINC2; | 458 | adc1 = MC13783_ADC1_ADEN | MC13783_ADC1_ADTRIGIGN | MC13783_ADC1_ASC; |
228 | /* enable the adc, ignore external triggering and set ASC to trigger | ||
229 | * conversion */ | ||
230 | reg_adc1 = MC13783_ADC1_ADEN | MC13783_ADC1_ADTRIGIGN | ||
231 | | MC13783_ADC1_ASC; | ||
232 | 459 | ||
233 | /* setup channel number */ | ||
234 | if (channel > 7) | 460 | if (channel > 7) |
235 | reg_adc1 |= MC13783_ADC1_ADSEL; | 461 | adc1 |= MC13783_ADC1_ADSEL; |
236 | 462 | ||
237 | switch (mode) { | 463 | switch (mode) { |
238 | case MC13783_ADC_MODE_TS: | 464 | case MC13783_ADC_MODE_TS: |
239 | /* enables touch screen reference mode and set touchscreen mode | 465 | adc0 |= MC13783_ADC0_ADREFEN | MC13783_ADC0_ADREFMODE |
240 | * to position mode */ | ||
241 | reg_adc0 |= MC13783_ADC0_ADREFEN | MC13783_ADC0_ADREFMODE | ||
242 | | MC13783_ADC0_TSMOD0 | MC13783_ADC0_TSMOD1; | 466 | | MC13783_ADC0_TSMOD0 | MC13783_ADC0_TSMOD1; |
243 | reg_adc1 |= 4 << MC13783_ADC1_CHAN1_SHIFT; | 467 | adc1 |= 4 << MC13783_ADC1_CHAN1_SHIFT; |
244 | break; | 468 | break; |
469 | |||
245 | case MC13783_ADC_MODE_SINGLE_CHAN: | 470 | case MC13783_ADC_MODE_SINGLE_CHAN: |
246 | reg_adc1 |= (channel & 0x7) << MC13783_ADC1_CHAN0_SHIFT; | 471 | adc0 |= old_adc0 & MC13783_ADC0_TSMOD_MASK; |
247 | reg_adc1 |= MC13783_ADC1_RAND; | 472 | adc1 |= (channel & 0x7) << MC13783_ADC1_CHAN0_SHIFT; |
473 | adc1 |= MC13783_ADC1_RAND; | ||
248 | break; | 474 | break; |
475 | |||
249 | case MC13783_ADC_MODE_MULT_CHAN: | 476 | case MC13783_ADC_MODE_MULT_CHAN: |
250 | reg_adc1 |= 4 << MC13783_ADC1_CHAN1_SHIFT; | 477 | adc0 |= old_adc0 & MC13783_ADC0_TSMOD_MASK; |
478 | adc1 |= 4 << MC13783_ADC1_CHAN1_SHIFT; | ||
251 | break; | 479 | break; |
480 | |||
252 | default: | 481 | default: |
482 | mc13783_unlock(mc13783); | ||
253 | return -EINVAL; | 483 | return -EINVAL; |
254 | } | 484 | } |
255 | 485 | ||
256 | mc13783_reg_write(mc13783, MC13783_REG_ADC_0, reg_adc0); | 486 | dev_dbg(&mc13783->spidev->dev, "%s: request irq\n", __func__); |
257 | mc13783_reg_write(mc13783, MC13783_REG_ADC_1, reg_adc1); | 487 | mc13783_irq_request(mc13783, MC13783_IRQ_ADCDONE, |
488 | mc13783_handler_adcdone, __func__, &adcdone_data); | ||
489 | mc13783_ackirq(mc13783, MC13783_IRQ_ADCDONE); | ||
258 | 490 | ||
259 | wait_for_completion_interruptible(&mc13783->adc_done); | 491 | mc13783_reg_write(mc13783, MC13783_REG_ADC_0, adc0); |
492 | mc13783_reg_write(mc13783, MC13783_REG_ADC_1, adc1); | ||
260 | 493 | ||
261 | for (i = 0; i < 4; i++) | 494 | mc13783_unlock(mc13783); |
262 | mc13783_reg_read(mc13783, MC13783_REG_ADC_2, &sample[i]); | ||
263 | 495 | ||
264 | if (mc13783->ts_active) | 496 | ret = wait_for_completion_interruptible_timeout(&adcdone_data.done, HZ); |
265 | mc13783_adc_set_ts_irq_mode(mc13783); | ||
266 | 497 | ||
267 | mutex_unlock(&mc13783->adc_conv_lock); | 498 | if (!ret) |
499 | ret = -ETIMEDOUT; | ||
268 | 500 | ||
269 | return 0; | 501 | mc13783_lock(mc13783); |
502 | |||
503 | mc13783_irq_free(mc13783, MC13783_IRQ_ADCDONE, &adcdone_data); | ||
504 | |||
505 | if (ret > 0) | ||
506 | for (i = 0; i < 4; ++i) { | ||
507 | ret = mc13783_reg_read(mc13783, | ||
508 | MC13783_REG_ADC_2, &sample[i]); | ||
509 | if (ret) | ||
510 | break; | ||
511 | } | ||
512 | |||
513 | if (mode == MC13783_ADC_MODE_TS) | ||
514 | /* restore TSMOD */ | ||
515 | mc13783_reg_write(mc13783, MC13783_REG_ADC_0, old_adc0); | ||
516 | |||
517 | mc13783->flags &= ~MC13783_ADC_WORKING; | ||
518 | out: | ||
519 | mc13783_unlock(mc13783); | ||
520 | |||
521 | return ret; | ||
270 | } | 522 | } |
271 | EXPORT_SYMBOL_GPL(mc13783_adc_do_conversion); | 523 | EXPORT_SYMBOL_GPL(mc13783_adc_do_conversion); |
272 | 524 | ||
273 | void mc13783_adc_set_ts_status(struct mc13783 *mc13783, unsigned int status) | 525 | static int mc13783_add_subdevice_pdata(struct mc13783 *mc13783, |
526 | const char *name, void *pdata, size_t pdata_size) | ||
274 | { | 527 | { |
275 | mc13783->ts_active = status; | 528 | struct mfd_cell cell = { |
529 | .name = name, | ||
530 | .platform_data = pdata, | ||
531 | .data_size = pdata_size, | ||
532 | }; | ||
533 | |||
534 | return mfd_add_devices(&mc13783->spidev->dev, -1, &cell, 1, NULL, 0); | ||
535 | } | ||
536 | |||
537 | static int mc13783_add_subdevice(struct mc13783 *mc13783, const char *name) | ||
538 | { | ||
539 | return mc13783_add_subdevice_pdata(mc13783, name, NULL, 0); | ||
276 | } | 540 | } |
277 | EXPORT_SYMBOL_GPL(mc13783_adc_set_ts_status); | ||
278 | 541 | ||
279 | static int mc13783_check_revision(struct mc13783 *mc13783) | 542 | static int mc13783_check_revision(struct mc13783 *mc13783) |
280 | { | 543 | { |
281 | u32 rev_id, rev1, rev2, finid, icid; | 544 | u32 rev_id, rev1, rev2, finid, icid; |
282 | 545 | ||
283 | mc13783_read(mc13783, MC13783_REG_REVISION, &rev_id); | 546 | mc13783_reg_read(mc13783, MC13783_REG_REVISION, &rev_id); |
284 | 547 | ||
285 | rev1 = (rev_id & 0x018) >> 3; | 548 | rev1 = (rev_id & 0x018) >> 3; |
286 | rev2 = (rev_id & 0x007); | 549 | rev2 = (rev_id & 0x007); |
@@ -292,38 +555,24 @@ static int mc13783_check_revision(struct mc13783 *mc13783) | |||
292 | rev1 = 3; | 555 | rev1 = 3; |
293 | 556 | ||
294 | if (rev1 == 0 || icid != 2) { | 557 | if (rev1 == 0 || icid != 2) { |
295 | dev_err(mc13783->dev, "No MC13783 detected.\n"); | 558 | dev_err(&mc13783->spidev->dev, "No MC13783 detected.\n"); |
296 | return -ENODEV; | 559 | return -ENODEV; |
297 | } | 560 | } |
298 | 561 | ||
299 | mc13783->revision = ((rev1 * 10) + rev2); | 562 | dev_info(&mc13783->spidev->dev, |
300 | dev_info(mc13783->dev, "MC13783 Rev %d.%d FinVer %x detected\n", rev1, | 563 | "MC13783 Rev %d.%d FinVer %x detected\n", |
301 | rev2, finid); | 564 | rev1, rev2, finid); |
302 | 565 | ||
303 | return 0; | 566 | return 0; |
304 | } | 567 | } |
305 | 568 | ||
306 | /* | 569 | static int mc13783_probe(struct spi_device *spi) |
307 | * Register a client device. This is non-fatal since there is no need to | ||
308 | * fail the entire device init due to a single platform device failing. | ||
309 | */ | ||
310 | static void mc13783_client_dev_register(struct mc13783 *mc13783, | ||
311 | const char *name) | ||
312 | { | ||
313 | struct mfd_cell cell = {}; | ||
314 | |||
315 | cell.name = name; | ||
316 | |||
317 | mfd_add_devices(mc13783->dev, -1, &cell, 1, NULL, 0); | ||
318 | } | ||
319 | |||
320 | static int __devinit mc13783_probe(struct spi_device *spi) | ||
321 | { | 570 | { |
322 | struct mc13783 *mc13783; | 571 | struct mc13783 *mc13783; |
323 | struct mc13783_platform_data *pdata = spi->dev.platform_data; | 572 | struct mc13783_platform_data *pdata = dev_get_platdata(&spi->dev); |
324 | int ret; | 573 | int ret; |
325 | 574 | ||
326 | mc13783 = kzalloc(sizeof(struct mc13783), GFP_KERNEL); | 575 | mc13783 = kzalloc(sizeof(*mc13783), GFP_KERNEL); |
327 | if (!mc13783) | 576 | if (!mc13783) |
328 | return -ENOMEM; | 577 | return -ENOMEM; |
329 | 578 | ||
@@ -332,96 +581,104 @@ static int __devinit mc13783_probe(struct spi_device *spi) | |||
332 | spi->bits_per_word = 32; | 581 | spi->bits_per_word = 32; |
333 | spi_setup(spi); | 582 | spi_setup(spi); |
334 | 583 | ||
335 | mc13783->spi_device = spi; | 584 | mc13783->spidev = spi; |
336 | mc13783->dev = &spi->dev; | 585 | |
337 | mc13783->irq = spi->irq; | 586 | mutex_init(&mc13783->lock); |
587 | mc13783_lock(mc13783); | ||
588 | |||
589 | ret = mc13783_check_revision(mc13783); | ||
590 | if (ret) | ||
591 | goto err_revision; | ||
592 | |||
593 | /* mask all irqs */ | ||
594 | ret = mc13783_reg_write(mc13783, MC13783_IRQMASK0, 0x00ffffff); | ||
595 | if (ret) | ||
596 | goto err_mask; | ||
338 | 597 | ||
339 | INIT_WORK(&mc13783->work, mc13783_irq_work); | 598 | ret = mc13783_reg_write(mc13783, MC13783_IRQMASK1, 0x00ffffff); |
340 | mutex_init(&mc13783->io_lock); | 599 | if (ret) |
341 | mutex_init(&mc13783->adc_conv_lock); | 600 | goto err_mask; |
342 | init_completion(&mc13783->adc_done); | 601 | |
602 | ret = request_threaded_irq(spi->irq, NULL, mc13783_irq_thread, | ||
603 | IRQF_ONESHOT | IRQF_TRIGGER_HIGH, "mc13783", mc13783); | ||
604 | |||
605 | if (ret) { | ||
606 | err_mask: | ||
607 | err_revision: | ||
608 | mutex_unlock(&mc13783->lock); | ||
609 | dev_set_drvdata(&spi->dev, NULL); | ||
610 | kfree(mc13783); | ||
611 | return ret; | ||
612 | } | ||
343 | 613 | ||
614 | /* This should go away (BEGIN) */ | ||
344 | if (pdata) { | 615 | if (pdata) { |
345 | mc13783->flags = pdata->flags; | 616 | mc13783->flags = pdata->flags; |
346 | mc13783->regulators = pdata->regulators; | 617 | mc13783->regulators = pdata->regulators; |
347 | mc13783->num_regulators = pdata->num_regulators; | 618 | mc13783->num_regulators = pdata->num_regulators; |
348 | } | 619 | } |
620 | /* This should go away (END) */ | ||
349 | 621 | ||
350 | if (mc13783_check_revision(mc13783)) { | 622 | if (pdata->flags & MC13783_USE_ADC) |
351 | ret = -ENODEV; | 623 | mc13783_add_subdevice(mc13783, "mc13783-adc"); |
352 | goto err_out; | 624 | |
625 | if (pdata->flags & MC13783_USE_CODEC) | ||
626 | mc13783_add_subdevice(mc13783, "mc13783-codec"); | ||
627 | |||
628 | if (pdata->flags & MC13783_USE_REGULATOR) { | ||
629 | struct mc13783_regulator_platform_data regulator_pdata = { | ||
630 | .num_regulators = pdata->num_regulators, | ||
631 | .regulators = pdata->regulators, | ||
632 | }; | ||
633 | |||
634 | mc13783_add_subdevice_pdata(mc13783, "mc13783-regulator", | ||
635 | ®ulator_pdata, sizeof(regulator_pdata)); | ||
353 | } | 636 | } |
354 | 637 | ||
355 | /* clear and mask all interrupts */ | 638 | if (pdata->flags & MC13783_USE_RTC) |
356 | mc13783_reg_write(mc13783, MC13783_REG_INTERRUPT_STATUS_0, 0x00ffffff); | 639 | mc13783_add_subdevice(mc13783, "mc13783-rtc"); |
357 | mc13783_reg_write(mc13783, MC13783_REG_INTERRUPT_MASK_0, 0x00ffffff); | ||
358 | mc13783_reg_write(mc13783, MC13783_REG_INTERRUPT_STATUS_1, 0x00ffffff); | ||
359 | mc13783_reg_write(mc13783, MC13783_REG_INTERRUPT_MASK_1, 0x00ffffff); | ||
360 | 640 | ||
361 | /* unmask adcdone interrupts */ | 641 | if (pdata->flags & MC13783_USE_TOUCHSCREEN) |
362 | mc13783_set_bits(mc13783, MC13783_REG_INTERRUPT_MASK_0, | 642 | mc13783_add_subdevice(mc13783, "mc13783-ts"); |
363 | MC13783_INT_MASK_ADCDONEM, 0); | ||
364 | 643 | ||
365 | ret = request_irq(mc13783->irq, mc13783_interrupt, | 644 | mc13783_unlock(mc13783); |
366 | IRQF_DISABLED | IRQF_TRIGGER_HIGH, "mc13783", | ||
367 | mc13783); | ||
368 | if (ret) | ||
369 | goto err_out; | ||
370 | |||
371 | if (mc13783->flags & MC13783_USE_CODEC) | ||
372 | mc13783_client_dev_register(mc13783, "mc13783-codec"); | ||
373 | if (mc13783->flags & MC13783_USE_ADC) | ||
374 | mc13783_client_dev_register(mc13783, "mc13783-adc"); | ||
375 | if (mc13783->flags & MC13783_USE_RTC) | ||
376 | mc13783_client_dev_register(mc13783, "mc13783-rtc"); | ||
377 | if (mc13783->flags & MC13783_USE_REGULATOR) | ||
378 | mc13783_client_dev_register(mc13783, "mc13783-regulator"); | ||
379 | if (mc13783->flags & MC13783_USE_TOUCHSCREEN) | ||
380 | mc13783_client_dev_register(mc13783, "mc13783-ts"); | ||
381 | 645 | ||
382 | return 0; | 646 | return 0; |
383 | |||
384 | err_out: | ||
385 | kfree(mc13783); | ||
386 | return ret; | ||
387 | } | 647 | } |
388 | 648 | ||
389 | static int __devexit mc13783_remove(struct spi_device *spi) | 649 | static int __devexit mc13783_remove(struct spi_device *spi) |
390 | { | 650 | { |
391 | struct mc13783 *mc13783; | 651 | struct mc13783 *mc13783 = dev_get_drvdata(&spi->dev); |
392 | 652 | ||
393 | mc13783 = dev_get_drvdata(&spi->dev); | 653 | free_irq(mc13783->spidev->irq, mc13783); |
394 | |||
395 | free_irq(mc13783->irq, mc13783); | ||
396 | 654 | ||
397 | mfd_remove_devices(&spi->dev); | 655 | mfd_remove_devices(&spi->dev); |
398 | 656 | ||
399 | return 0; | 657 | return 0; |
400 | } | 658 | } |
401 | 659 | ||
402 | static struct spi_driver pmic_driver = { | 660 | static struct spi_driver mc13783_driver = { |
403 | .driver = { | 661 | .driver = { |
404 | .name = "mc13783", | 662 | .name = "mc13783", |
405 | .bus = &spi_bus_type, | 663 | .bus = &spi_bus_type, |
406 | .owner = THIS_MODULE, | 664 | .owner = THIS_MODULE, |
407 | }, | 665 | }, |
408 | .probe = mc13783_probe, | 666 | .probe = mc13783_probe, |
409 | .remove = __devexit_p(mc13783_remove), | 667 | .remove = __devexit_p(mc13783_remove), |
410 | }; | 668 | }; |
411 | 669 | ||
412 | static int __init pmic_init(void) | 670 | static int __init mc13783_init(void) |
413 | { | 671 | { |
414 | return spi_register_driver(&pmic_driver); | 672 | return spi_register_driver(&mc13783_driver); |
415 | } | 673 | } |
416 | subsys_initcall(pmic_init); | 674 | subsys_initcall(mc13783_init); |
417 | 675 | ||
418 | static void __exit pmic_exit(void) | 676 | static void __exit mc13783_exit(void) |
419 | { | 677 | { |
420 | spi_unregister_driver(&pmic_driver); | 678 | spi_unregister_driver(&mc13783_driver); |
421 | } | 679 | } |
422 | module_exit(pmic_exit); | 680 | module_exit(mc13783_exit); |
423 | |||
424 | MODULE_DESCRIPTION("Core/Protocol driver for Freescale MC13783 PMIC"); | ||
425 | MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); | ||
426 | MODULE_LICENSE("GPL"); | ||
427 | 681 | ||
682 | MODULE_DESCRIPTION("Core driver for Freescale MC13783 PMIC"); | ||
683 | MODULE_AUTHOR("Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>"); | ||
684 | MODULE_LICENSE("GPL v2"); | ||