diff options
Diffstat (limited to 'drivers/mfd')
32 files changed, 4039 insertions, 2112 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index a67adcbd0fa1..f1391c21ef26 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig | |||
@@ -2,23 +2,8 @@ | |||
2 | # Multifunction miscellaneous devices | 2 | # Multifunction miscellaneous devices |
3 | # | 3 | # |
4 | 4 | ||
5 | menuconfig MFD_SUPPORT | 5 | if HAS_IOMEM |
6 | bool "Multifunction device drivers" | 6 | menu "Multifunction device drivers" |
7 | depends on HAS_IOMEM | ||
8 | default y | ||
9 | help | ||
10 | Multifunction devices embed several functions (e.g. GPIOs, | ||
11 | touchscreens, keyboards, current regulators, power management chips, | ||
12 | etc...) in one single integrated circuit. They usually talk to the | ||
13 | main CPU through one or more IRQ lines and low speed data busses (SPI, | ||
14 | I2C, etc..). They appear as one single device to the main system | ||
15 | through the data bus and the MFD framework allows for sub devices | ||
16 | (a.k.a. functions) to appear as discrete platform devices. | ||
17 | MFDs are typically found on embedded platforms. | ||
18 | |||
19 | This option alone does not add any kernel code. | ||
20 | |||
21 | if MFD_SUPPORT | ||
22 | 7 | ||
23 | config MFD_CORE | 8 | config MFD_CORE |
24 | tristate | 9 | tristate |
@@ -390,6 +375,7 @@ config MFD_WM8400 | |||
390 | tristate "Support Wolfson Microelectronics WM8400" | 375 | tristate "Support Wolfson Microelectronics WM8400" |
391 | select MFD_CORE | 376 | select MFD_CORE |
392 | depends on I2C | 377 | depends on I2C |
378 | select REGMAP_I2C | ||
393 | help | 379 | help |
394 | Support for the Wolfson Microelecronics WM8400 PMIC and audio | 380 | Support for the Wolfson Microelecronics WM8400 PMIC and audio |
395 | CODEC. This driver provides common support for accessing | 381 | CODEC. This driver provides common support for accessing |
@@ -503,6 +489,7 @@ config MFD_WM8994 | |||
503 | config MFD_PCF50633 | 489 | config MFD_PCF50633 |
504 | tristate "Support for NXP PCF50633" | 490 | tristate "Support for NXP PCF50633" |
505 | depends on I2C | 491 | depends on I2C |
492 | select REGMAP_I2C | ||
506 | help | 493 | help |
507 | Say yes here if you have NXP PCF50633 chip on your board. | 494 | Say yes here if you have NXP PCF50633 chip on your board. |
508 | This core driver provides register access and IRQ handling | 495 | This core driver provides register access and IRQ handling |
@@ -579,6 +566,23 @@ config EZX_PCAP | |||
579 | This enables the PCAP ASIC present on EZX Phones. This is | 566 | This enables the PCAP ASIC present on EZX Phones. This is |
580 | needed for MMC, TouchScreen, Sound, USB, etc.. | 567 | needed for MMC, TouchScreen, Sound, USB, etc.. |
581 | 568 | ||
569 | config AB5500_CORE | ||
570 | bool "ST-Ericsson AB5500 Mixed Signal Power Management chip" | ||
571 | depends on ABX500_CORE && MFD_DB5500_PRCMU | ||
572 | select MFD_CORE | ||
573 | help | ||
574 | Select this option to enable access to AB5500 power management | ||
575 | chip. This connects to the db5500 chip via the I2C bus via PRCMU. | ||
576 | This chip embeds various other multimedia funtionalities as well. | ||
577 | |||
578 | config AB5500_DEBUG | ||
579 | bool "Enable debug info via debugfs" | ||
580 | depends on AB5500_CORE && DEBUG_FS | ||
581 | default y if DEBUG_FS | ||
582 | help | ||
583 | Select this option if you want debug information from the AB5500 | ||
584 | using the debug filesystem, debugfs. | ||
585 | |||
582 | config AB8500_CORE | 586 | config AB8500_CORE |
583 | bool "ST-Ericsson AB8500 Mixed Signal Power Management chip" | 587 | bool "ST-Ericsson AB8500 Mixed Signal Power Management chip" |
584 | depends on GENERIC_HARDIRQS && ABX500_CORE | 588 | depends on GENERIC_HARDIRQS && ABX500_CORE |
@@ -615,20 +619,6 @@ config AB8500_GPADC | |||
615 | help | 619 | help |
616 | AB8500 GPADC driver used to convert Acc and battery/ac/usb voltage | 620 | AB8500 GPADC driver used to convert Acc and battery/ac/usb voltage |
617 | 621 | ||
618 | config AB3550_CORE | ||
619 | bool "ST-Ericsson AB3550 Mixed Signal Circuit core functions" | ||
620 | select MFD_CORE | ||
621 | depends on I2C=y && GENERIC_HARDIRQS && ABX500_CORE | ||
622 | help | ||
623 | Select this to enable the AB3550 Mixed Signal IC core | ||
624 | functionality. This connects to a AB3550 on the I2C bus | ||
625 | and expose a number of symbols needed for dependent devices | ||
626 | to read and write registers and subscribe to events from | ||
627 | this multi-functional IC. This is needed to use other features | ||
628 | of the AB3550 such as battery-backed RTC, charging control, | ||
629 | LEDs, vibrator, system power and temperature, power management | ||
630 | and ALSA sound. | ||
631 | |||
632 | config MFD_DB8500_PRCMU | 622 | config MFD_DB8500_PRCMU |
633 | bool "ST-Ericsson DB8500 Power Reset Control Management Unit" | 623 | bool "ST-Ericsson DB8500 Power Reset Control Management Unit" |
634 | depends on UX500_SOC_DB8500 | 624 | depends on UX500_SOC_DB8500 |
@@ -773,7 +763,17 @@ config MFD_AAT2870_CORE | |||
773 | additional drivers must be enabled in order to use the | 763 | additional drivers must be enabled in order to use the |
774 | functionality of the device. | 764 | functionality of the device. |
775 | 765 | ||
776 | endif # MFD_SUPPORT | 766 | config MFD_INTEL_MSIC |
767 | bool "Support for Intel MSIC" | ||
768 | depends on INTEL_SCU_IPC | ||
769 | select MFD_CORE | ||
770 | help | ||
771 | Select this option to enable access to Intel MSIC (Avatele | ||
772 | Passage) chip. This chip embeds audio, battery, GPIO, etc. | ||
773 | devices used in Intel Medfield platforms. | ||
774 | |||
775 | endmenu | ||
776 | endif | ||
777 | 777 | ||
778 | menu "Multimedia Capabilities Port drivers" | 778 | menu "Multimedia Capabilities Port drivers" |
779 | depends on ARCH_SA1100 | 779 | depends on ARCH_SA1100 |
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index c58020303d18..b2292eb75242 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile | |||
@@ -79,7 +79,8 @@ obj-$(CONFIG_PCF50633_GPIO) += pcf50633-gpio.o | |||
79 | obj-$(CONFIG_ABX500_CORE) += abx500-core.o | 79 | obj-$(CONFIG_ABX500_CORE) += abx500-core.o |
80 | obj-$(CONFIG_AB3100_CORE) += ab3100-core.o | 80 | obj-$(CONFIG_AB3100_CORE) += ab3100-core.o |
81 | obj-$(CONFIG_AB3100_OTP) += ab3100-otp.o | 81 | obj-$(CONFIG_AB3100_OTP) += ab3100-otp.o |
82 | obj-$(CONFIG_AB3550_CORE) += ab3550-core.o | 82 | obj-$(CONFIG_AB5500_CORE) += ab5500-core.o |
83 | obj-$(CONFIG_AB5500_DEBUG) += ab5500-debugfs.o | ||
83 | obj-$(CONFIG_AB8500_CORE) += ab8500-core.o ab8500-sysctrl.o | 84 | obj-$(CONFIG_AB8500_CORE) += ab8500-core.o ab8500-sysctrl.o |
84 | obj-$(CONFIG_AB8500_DEBUG) += ab8500-debugfs.o | 85 | obj-$(CONFIG_AB8500_DEBUG) += ab8500-debugfs.o |
85 | obj-$(CONFIG_AB8500_GPADC) += ab8500-gpadc.o | 86 | obj-$(CONFIG_AB8500_GPADC) += ab8500-gpadc.o |
@@ -102,3 +103,4 @@ obj-$(CONFIG_MFD_PM8921_CORE) += pm8921-core.o | |||
102 | obj-$(CONFIG_MFD_PM8XXX_IRQ) += pm8xxx-irq.o | 103 | obj-$(CONFIG_MFD_PM8XXX_IRQ) += pm8xxx-irq.o |
103 | obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o | 104 | obj-$(CONFIG_TPS65911_COMPARATOR) += tps65911-comparator.o |
104 | obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o | 105 | obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o |
106 | obj-$(CONFIG_MFD_INTEL_MSIC) += intel_msic.o | ||
diff --git a/drivers/mfd/aat2870-core.c b/drivers/mfd/aat2870-core.c index 345dc658ef06..02c42015ba51 100644 --- a/drivers/mfd/aat2870-core.c +++ b/drivers/mfd/aat2870-core.c | |||
@@ -295,7 +295,7 @@ static ssize_t aat2870_reg_write_file(struct file *file, | |||
295 | { | 295 | { |
296 | struct aat2870_data *aat2870 = file->private_data; | 296 | struct aat2870_data *aat2870 = file->private_data; |
297 | char buf[32]; | 297 | char buf[32]; |
298 | int buf_size; | 298 | ssize_t buf_size; |
299 | char *start = buf; | 299 | char *start = buf; |
300 | unsigned long addr, val; | 300 | unsigned long addr, val; |
301 | int ret; | 301 | int ret; |
diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c index c2b702182938..60107ee166fc 100644 --- a/drivers/mfd/ab3100-core.c +++ b/drivers/mfd/ab3100-core.c | |||
@@ -810,7 +810,7 @@ struct ab_family_id { | |||
810 | char *name; | 810 | char *name; |
811 | }; | 811 | }; |
812 | 812 | ||
813 | static const struct ab_family_id ids[] __devinitdata = { | 813 | static const struct ab_family_id ids[] __devinitconst = { |
814 | /* AB3100 */ | 814 | /* AB3100 */ |
815 | { | 815 | { |
816 | .id = 0xc0, | 816 | .id = 0xc0, |
diff --git a/drivers/mfd/ab3550-core.c b/drivers/mfd/ab3550-core.c deleted file mode 100644 index 14695d9aa217..000000000000 --- a/drivers/mfd/ab3550-core.c +++ /dev/null | |||
@@ -1,1381 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007-2010 ST-Ericsson | ||
3 | * License terms: GNU General Public License (GPL) version 2 | ||
4 | * Low-level core for exclusive access to the AB3550 IC on the I2C bus | ||
5 | * and some basic chip-configuration. | ||
6 | * Author: Bengt Jonsson <bengt.g.jonsson@stericsson.com> | ||
7 | * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com> | ||
8 | * Author: Mattias Wallin <mattias.wallin@stericsson.com> | ||
9 | * Author: Rickard Andersson <rickard.andersson@stericsson.com> | ||
10 | */ | ||
11 | |||
12 | #include <linux/i2c.h> | ||
13 | #include <linux/mutex.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/err.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <linux/device.h> | ||
19 | #include <linux/irq.h> | ||
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/random.h> | ||
22 | #include <linux/workqueue.h> | ||
23 | #include <linux/debugfs.h> | ||
24 | #include <linux/seq_file.h> | ||
25 | #include <linux/uaccess.h> | ||
26 | #include <linux/mfd/abx500.h> | ||
27 | #include <linux/list.h> | ||
28 | #include <linux/bitops.h> | ||
29 | #include <linux/spinlock.h> | ||
30 | #include <linux/mfd/core.h> | ||
31 | |||
32 | #define AB3550_NAME_STRING "ab3550" | ||
33 | #define AB3550_ID_FORMAT_STRING "AB3550 %s" | ||
34 | #define AB3550_NUM_BANKS 2 | ||
35 | #define AB3550_NUM_EVENT_REG 5 | ||
36 | |||
37 | /* These are the only registers inside AB3550 used in this main file */ | ||
38 | |||
39 | /* Chip ID register */ | ||
40 | #define AB3550_CID_REG 0x20 | ||
41 | |||
42 | /* Interrupt event registers */ | ||
43 | #define AB3550_EVENT_BANK 0 | ||
44 | #define AB3550_EVENT_REG 0x22 | ||
45 | |||
46 | /* Read/write operation values. */ | ||
47 | #define AB3550_PERM_RD (0x01) | ||
48 | #define AB3550_PERM_WR (0x02) | ||
49 | |||
50 | /* Read/write permissions. */ | ||
51 | #define AB3550_PERM_RO (AB3550_PERM_RD) | ||
52 | #define AB3550_PERM_RW (AB3550_PERM_RD | AB3550_PERM_WR) | ||
53 | |||
54 | /** | ||
55 | * struct ab3550 | ||
56 | * @access_mutex: lock out concurrent accesses to the AB registers | ||
57 | * @i2c_client: I2C client for this chip | ||
58 | * @chip_name: name of this chip variant | ||
59 | * @chip_id: 8 bit chip ID for this chip variant | ||
60 | * @mask_work: a worker for writing to mask registers | ||
61 | * @event_lock: a lock to protect the event_mask | ||
62 | * @event_mask: a local copy of the mask event registers | ||
63 | * @startup_events: a copy of the first reading of the event registers | ||
64 | * @startup_events_read: whether the first events have been read | ||
65 | */ | ||
66 | struct ab3550 { | ||
67 | struct mutex access_mutex; | ||
68 | struct i2c_client *i2c_client[AB3550_NUM_BANKS]; | ||
69 | char chip_name[32]; | ||
70 | u8 chip_id; | ||
71 | struct work_struct mask_work; | ||
72 | spinlock_t event_lock; | ||
73 | u8 event_mask[AB3550_NUM_EVENT_REG]; | ||
74 | u8 startup_events[AB3550_NUM_EVENT_REG]; | ||
75 | bool startup_events_read; | ||
76 | #ifdef CONFIG_DEBUG_FS | ||
77 | unsigned int debug_bank; | ||
78 | unsigned int debug_address; | ||
79 | #endif | ||
80 | }; | ||
81 | |||
82 | /** | ||
83 | * struct ab3550_reg_range | ||
84 | * @first: the first address of the range | ||
85 | * @last: the last address of the range | ||
86 | * @perm: access permissions for the range | ||
87 | */ | ||
88 | struct ab3550_reg_range { | ||
89 | u8 first; | ||
90 | u8 last; | ||
91 | u8 perm; | ||
92 | }; | ||
93 | |||
94 | /** | ||
95 | * struct ab3550_reg_ranges | ||
96 | * @count: the number of ranges in the list | ||
97 | * @range: the list of register ranges | ||
98 | */ | ||
99 | struct ab3550_reg_ranges { | ||
100 | u8 count; | ||
101 | const struct ab3550_reg_range *range; | ||
102 | }; | ||
103 | |||
104 | /* | ||
105 | * Permissible register ranges for reading and writing per device and bank. | ||
106 | * | ||
107 | * The ranges must be listed in increasing address order, and no overlaps are | ||
108 | * allowed. It is assumed that write permission implies read permission | ||
109 | * (i.e. only RO and RW permissions should be used). Ranges with write | ||
110 | * permission must not be split up. | ||
111 | */ | ||
112 | |||
113 | #define NO_RANGE {.count = 0, .range = NULL,} | ||
114 | |||
115 | static struct | ||
116 | ab3550_reg_ranges ab3550_reg_ranges[AB3550_NUM_DEVICES][AB3550_NUM_BANKS] = { | ||
117 | [AB3550_DEVID_DAC] = { | ||
118 | NO_RANGE, | ||
119 | { | ||
120 | .count = 2, | ||
121 | .range = (struct ab3550_reg_range[]) { | ||
122 | { | ||
123 | .first = 0xb0, | ||
124 | .last = 0xba, | ||
125 | .perm = AB3550_PERM_RW, | ||
126 | }, | ||
127 | { | ||
128 | .first = 0xbc, | ||
129 | .last = 0xc3, | ||
130 | .perm = AB3550_PERM_RW, | ||
131 | }, | ||
132 | }, | ||
133 | }, | ||
134 | }, | ||
135 | [AB3550_DEVID_LEDS] = { | ||
136 | NO_RANGE, | ||
137 | { | ||
138 | .count = 2, | ||
139 | .range = (struct ab3550_reg_range[]) { | ||
140 | { | ||
141 | .first = 0x5a, | ||
142 | .last = 0x88, | ||
143 | .perm = AB3550_PERM_RW, | ||
144 | }, | ||
145 | { | ||
146 | .first = 0x8a, | ||
147 | .last = 0xad, | ||
148 | .perm = AB3550_PERM_RW, | ||
149 | }, | ||
150 | } | ||
151 | }, | ||
152 | }, | ||
153 | [AB3550_DEVID_POWER] = { | ||
154 | { | ||
155 | .count = 1, | ||
156 | .range = (struct ab3550_reg_range[]) { | ||
157 | { | ||
158 | .first = 0x21, | ||
159 | .last = 0x21, | ||
160 | .perm = AB3550_PERM_RO, | ||
161 | }, | ||
162 | } | ||
163 | }, | ||
164 | NO_RANGE, | ||
165 | }, | ||
166 | [AB3550_DEVID_REGULATORS] = { | ||
167 | { | ||
168 | .count = 1, | ||
169 | .range = (struct ab3550_reg_range[]) { | ||
170 | { | ||
171 | .first = 0x69, | ||
172 | .last = 0xa3, | ||
173 | .perm = AB3550_PERM_RW, | ||
174 | }, | ||
175 | } | ||
176 | }, | ||
177 | { | ||
178 | .count = 1, | ||
179 | .range = (struct ab3550_reg_range[]) { | ||
180 | { | ||
181 | .first = 0x14, | ||
182 | .last = 0x16, | ||
183 | .perm = AB3550_PERM_RW, | ||
184 | }, | ||
185 | } | ||
186 | }, | ||
187 | }, | ||
188 | [AB3550_DEVID_SIM] = { | ||
189 | { | ||
190 | .count = 1, | ||
191 | .range = (struct ab3550_reg_range[]) { | ||
192 | { | ||
193 | .first = 0x21, | ||
194 | .last = 0x21, | ||
195 | .perm = AB3550_PERM_RO, | ||
196 | }, | ||
197 | } | ||
198 | }, | ||
199 | { | ||
200 | .count = 1, | ||
201 | .range = (struct ab3550_reg_range[]) { | ||
202 | { | ||
203 | .first = 0x14, | ||
204 | .last = 0x17, | ||
205 | .perm = AB3550_PERM_RW, | ||
206 | }, | ||
207 | } | ||
208 | |||
209 | }, | ||
210 | }, | ||
211 | [AB3550_DEVID_UART] = { | ||
212 | NO_RANGE, | ||
213 | NO_RANGE, | ||
214 | }, | ||
215 | [AB3550_DEVID_RTC] = { | ||
216 | { | ||
217 | .count = 1, | ||
218 | .range = (struct ab3550_reg_range[]) { | ||
219 | { | ||
220 | .first = 0x00, | ||
221 | .last = 0x0c, | ||
222 | .perm = AB3550_PERM_RW, | ||
223 | }, | ||
224 | } | ||
225 | }, | ||
226 | NO_RANGE, | ||
227 | }, | ||
228 | [AB3550_DEVID_CHARGER] = { | ||
229 | { | ||
230 | .count = 2, | ||
231 | .range = (struct ab3550_reg_range[]) { | ||
232 | { | ||
233 | .first = 0x10, | ||
234 | .last = 0x1a, | ||
235 | .perm = AB3550_PERM_RW, | ||
236 | }, | ||
237 | { | ||
238 | .first = 0x21, | ||
239 | .last = 0x21, | ||
240 | .perm = AB3550_PERM_RO, | ||
241 | }, | ||
242 | } | ||
243 | }, | ||
244 | NO_RANGE, | ||
245 | }, | ||
246 | [AB3550_DEVID_ADC] = { | ||
247 | NO_RANGE, | ||
248 | { | ||
249 | .count = 1, | ||
250 | .range = (struct ab3550_reg_range[]) { | ||
251 | { | ||
252 | .first = 0x20, | ||
253 | .last = 0x56, | ||
254 | .perm = AB3550_PERM_RW, | ||
255 | }, | ||
256 | |||
257 | } | ||
258 | }, | ||
259 | }, | ||
260 | [AB3550_DEVID_FUELGAUGE] = { | ||
261 | { | ||
262 | .count = 1, | ||
263 | .range = (struct ab3550_reg_range[]) { | ||
264 | { | ||
265 | .first = 0x21, | ||
266 | .last = 0x21, | ||
267 | .perm = AB3550_PERM_RO, | ||
268 | }, | ||
269 | } | ||
270 | }, | ||
271 | { | ||
272 | .count = 1, | ||
273 | .range = (struct ab3550_reg_range[]) { | ||
274 | { | ||
275 | .first = 0x00, | ||
276 | .last = 0x0e, | ||
277 | .perm = AB3550_PERM_RW, | ||
278 | }, | ||
279 | } | ||
280 | }, | ||
281 | }, | ||
282 | [AB3550_DEVID_VIBRATOR] = { | ||
283 | NO_RANGE, | ||
284 | { | ||
285 | .count = 1, | ||
286 | .range = (struct ab3550_reg_range[]) { | ||
287 | { | ||
288 | .first = 0x10, | ||
289 | .last = 0x13, | ||
290 | .perm = AB3550_PERM_RW, | ||
291 | }, | ||
292 | |||
293 | } | ||
294 | }, | ||
295 | }, | ||
296 | [AB3550_DEVID_CODEC] = { | ||
297 | { | ||
298 | .count = 2, | ||
299 | .range = (struct ab3550_reg_range[]) { | ||
300 | { | ||
301 | .first = 0x31, | ||
302 | .last = 0x63, | ||
303 | .perm = AB3550_PERM_RW, | ||
304 | }, | ||
305 | { | ||
306 | .first = 0x65, | ||
307 | .last = 0x68, | ||
308 | .perm = AB3550_PERM_RW, | ||
309 | }, | ||
310 | } | ||
311 | }, | ||
312 | NO_RANGE, | ||
313 | }, | ||
314 | }; | ||
315 | |||
316 | static struct mfd_cell ab3550_devs[AB3550_NUM_DEVICES] = { | ||
317 | [AB3550_DEVID_DAC] = { | ||
318 | .name = "ab3550-dac", | ||
319 | .id = AB3550_DEVID_DAC, | ||
320 | .num_resources = 0, | ||
321 | }, | ||
322 | [AB3550_DEVID_LEDS] = { | ||
323 | .name = "ab3550-leds", | ||
324 | .id = AB3550_DEVID_LEDS, | ||
325 | }, | ||
326 | [AB3550_DEVID_POWER] = { | ||
327 | .name = "ab3550-power", | ||
328 | .id = AB3550_DEVID_POWER, | ||
329 | }, | ||
330 | [AB3550_DEVID_REGULATORS] = { | ||
331 | .name = "ab3550-regulators", | ||
332 | .id = AB3550_DEVID_REGULATORS, | ||
333 | }, | ||
334 | [AB3550_DEVID_SIM] = { | ||
335 | .name = "ab3550-sim", | ||
336 | .id = AB3550_DEVID_SIM, | ||
337 | }, | ||
338 | [AB3550_DEVID_UART] = { | ||
339 | .name = "ab3550-uart", | ||
340 | .id = AB3550_DEVID_UART, | ||
341 | }, | ||
342 | [AB3550_DEVID_RTC] = { | ||
343 | .name = "ab3550-rtc", | ||
344 | .id = AB3550_DEVID_RTC, | ||
345 | }, | ||
346 | [AB3550_DEVID_CHARGER] = { | ||
347 | .name = "ab3550-charger", | ||
348 | .id = AB3550_DEVID_CHARGER, | ||
349 | }, | ||
350 | [AB3550_DEVID_ADC] = { | ||
351 | .name = "ab3550-adc", | ||
352 | .id = AB3550_DEVID_ADC, | ||
353 | .num_resources = 10, | ||
354 | .resources = (struct resource[]) { | ||
355 | { | ||
356 | .name = "TRIGGER-0", | ||
357 | .flags = IORESOURCE_IRQ, | ||
358 | .start = 16, | ||
359 | .end = 16, | ||
360 | }, | ||
361 | { | ||
362 | .name = "TRIGGER-1", | ||
363 | .flags = IORESOURCE_IRQ, | ||
364 | .start = 17, | ||
365 | .end = 17, | ||
366 | }, | ||
367 | { | ||
368 | .name = "TRIGGER-2", | ||
369 | .flags = IORESOURCE_IRQ, | ||
370 | .start = 18, | ||
371 | .end = 18, | ||
372 | }, | ||
373 | { | ||
374 | .name = "TRIGGER-3", | ||
375 | .flags = IORESOURCE_IRQ, | ||
376 | .start = 19, | ||
377 | .end = 19, | ||
378 | }, | ||
379 | { | ||
380 | .name = "TRIGGER-4", | ||
381 | .flags = IORESOURCE_IRQ, | ||
382 | .start = 20, | ||
383 | .end = 20, | ||
384 | }, | ||
385 | { | ||
386 | .name = "TRIGGER-5", | ||
387 | .flags = IORESOURCE_IRQ, | ||
388 | .start = 21, | ||
389 | .end = 21, | ||
390 | }, | ||
391 | { | ||
392 | .name = "TRIGGER-6", | ||
393 | .flags = IORESOURCE_IRQ, | ||
394 | .start = 22, | ||
395 | .end = 22, | ||
396 | }, | ||
397 | { | ||
398 | .name = "TRIGGER-7", | ||
399 | .flags = IORESOURCE_IRQ, | ||
400 | .start = 23, | ||
401 | .end = 23, | ||
402 | }, | ||
403 | { | ||
404 | .name = "TRIGGER-VBAT-TXON", | ||
405 | .flags = IORESOURCE_IRQ, | ||
406 | .start = 13, | ||
407 | .end = 13, | ||
408 | }, | ||
409 | { | ||
410 | .name = "TRIGGER-VBAT", | ||
411 | .flags = IORESOURCE_IRQ, | ||
412 | .start = 12, | ||
413 | .end = 12, | ||
414 | }, | ||
415 | }, | ||
416 | }, | ||
417 | [AB3550_DEVID_FUELGAUGE] = { | ||
418 | .name = "ab3550-fuelgauge", | ||
419 | .id = AB3550_DEVID_FUELGAUGE, | ||
420 | }, | ||
421 | [AB3550_DEVID_VIBRATOR] = { | ||
422 | .name = "ab3550-vibrator", | ||
423 | .id = AB3550_DEVID_VIBRATOR, | ||
424 | }, | ||
425 | [AB3550_DEVID_CODEC] = { | ||
426 | .name = "ab3550-codec", | ||
427 | .id = AB3550_DEVID_CODEC, | ||
428 | }, | ||
429 | }; | ||
430 | |||
431 | /* | ||
432 | * I2C transactions with error messages. | ||
433 | */ | ||
434 | static int ab3550_i2c_master_send(struct ab3550 *ab, u8 bank, u8 *data, | ||
435 | u8 count) | ||
436 | { | ||
437 | int err; | ||
438 | |||
439 | err = i2c_master_send(ab->i2c_client[bank], data, count); | ||
440 | if (err < 0) { | ||
441 | dev_err(&ab->i2c_client[0]->dev, "send error: %d\n", err); | ||
442 | return err; | ||
443 | } | ||
444 | return 0; | ||
445 | } | ||
446 | |||
447 | static int ab3550_i2c_master_recv(struct ab3550 *ab, u8 bank, u8 *data, | ||
448 | u8 count) | ||
449 | { | ||
450 | int err; | ||
451 | |||
452 | err = i2c_master_recv(ab->i2c_client[bank], data, count); | ||
453 | if (err < 0) { | ||
454 | dev_err(&ab->i2c_client[0]->dev, "receive error: %d\n", err); | ||
455 | return err; | ||
456 | } | ||
457 | return 0; | ||
458 | } | ||
459 | |||
460 | /* | ||
461 | * Functionality for getting/setting register values. | ||
462 | */ | ||
463 | static int get_register_interruptible(struct ab3550 *ab, u8 bank, u8 reg, | ||
464 | u8 *value) | ||
465 | { | ||
466 | int err; | ||
467 | |||
468 | err = mutex_lock_interruptible(&ab->access_mutex); | ||
469 | if (err) | ||
470 | return err; | ||
471 | |||
472 | err = ab3550_i2c_master_send(ab, bank, ®, 1); | ||
473 | if (!err) | ||
474 | err = ab3550_i2c_master_recv(ab, bank, value, 1); | ||
475 | |||
476 | mutex_unlock(&ab->access_mutex); | ||
477 | return err; | ||
478 | } | ||
479 | |||
480 | static int get_register_page_interruptible(struct ab3550 *ab, u8 bank, | ||
481 | u8 first_reg, u8 *regvals, u8 numregs) | ||
482 | { | ||
483 | int err; | ||
484 | |||
485 | err = mutex_lock_interruptible(&ab->access_mutex); | ||
486 | if (err) | ||
487 | return err; | ||
488 | |||
489 | err = ab3550_i2c_master_send(ab, bank, &first_reg, 1); | ||
490 | if (!err) | ||
491 | err = ab3550_i2c_master_recv(ab, bank, regvals, numregs); | ||
492 | |||
493 | mutex_unlock(&ab->access_mutex); | ||
494 | return err; | ||
495 | } | ||
496 | |||
497 | static int mask_and_set_register_interruptible(struct ab3550 *ab, u8 bank, | ||
498 | u8 reg, u8 bitmask, u8 bitvalues) | ||
499 | { | ||
500 | int err = 0; | ||
501 | |||
502 | if (likely(bitmask)) { | ||
503 | u8 reg_bits[2] = {reg, 0}; | ||
504 | |||
505 | err = mutex_lock_interruptible(&ab->access_mutex); | ||
506 | if (err) | ||
507 | return err; | ||
508 | |||
509 | if (bitmask == 0xFF) /* No need to read in this case. */ | ||
510 | reg_bits[1] = bitvalues; | ||
511 | else { /* Read and modify the register value. */ | ||
512 | u8 bits; | ||
513 | |||
514 | err = ab3550_i2c_master_send(ab, bank, ®, 1); | ||
515 | if (err) | ||
516 | goto unlock_and_return; | ||
517 | err = ab3550_i2c_master_recv(ab, bank, &bits, 1); | ||
518 | if (err) | ||
519 | goto unlock_and_return; | ||
520 | reg_bits[1] = ((~bitmask & bits) | | ||
521 | (bitmask & bitvalues)); | ||
522 | } | ||
523 | /* Write the new value. */ | ||
524 | err = ab3550_i2c_master_send(ab, bank, reg_bits, 2); | ||
525 | unlock_and_return: | ||
526 | mutex_unlock(&ab->access_mutex); | ||
527 | } | ||
528 | return err; | ||
529 | } | ||
530 | |||
531 | /* | ||
532 | * Read/write permission checking functions. | ||
533 | */ | ||
534 | static bool page_write_allowed(const struct ab3550_reg_ranges *ranges, | ||
535 | u8 first_reg, u8 last_reg) | ||
536 | { | ||
537 | u8 i; | ||
538 | |||
539 | if (last_reg < first_reg) | ||
540 | return false; | ||
541 | |||
542 | for (i = 0; i < ranges->count; i++) { | ||
543 | if (first_reg < ranges->range[i].first) | ||
544 | break; | ||
545 | if ((last_reg <= ranges->range[i].last) && | ||
546 | (ranges->range[i].perm & AB3550_PERM_WR)) | ||
547 | return true; | ||
548 | } | ||
549 | return false; | ||
550 | } | ||
551 | |||
552 | static bool reg_write_allowed(const struct ab3550_reg_ranges *ranges, u8 reg) | ||
553 | { | ||
554 | return page_write_allowed(ranges, reg, reg); | ||
555 | } | ||
556 | |||
557 | static bool page_read_allowed(const struct ab3550_reg_ranges *ranges, | ||
558 | u8 first_reg, u8 last_reg) | ||
559 | { | ||
560 | u8 i; | ||
561 | |||
562 | if (last_reg < first_reg) | ||
563 | return false; | ||
564 | /* Find the range (if it exists in the list) that includes first_reg. */ | ||
565 | for (i = 0; i < ranges->count; i++) { | ||
566 | if (first_reg < ranges->range[i].first) | ||
567 | return false; | ||
568 | if (first_reg <= ranges->range[i].last) | ||
569 | break; | ||
570 | } | ||
571 | /* Make sure that the entire range up to and including last_reg is | ||
572 | * readable. This may span several of the ranges in the list. | ||
573 | */ | ||
574 | while ((i < ranges->count) && | ||
575 | (ranges->range[i].perm & AB3550_PERM_RD)) { | ||
576 | if (last_reg <= ranges->range[i].last) | ||
577 | return true; | ||
578 | if ((++i >= ranges->count) || | ||
579 | (ranges->range[i].first != | ||
580 | (ranges->range[i - 1].last + 1))) { | ||
581 | break; | ||
582 | } | ||
583 | } | ||
584 | return false; | ||
585 | } | ||
586 | |||
587 | static bool reg_read_allowed(const struct ab3550_reg_ranges *ranges, u8 reg) | ||
588 | { | ||
589 | return page_read_allowed(ranges, reg, reg); | ||
590 | } | ||
591 | |||
592 | /* | ||
593 | * The register access functionality. | ||
594 | */ | ||
595 | static int ab3550_get_chip_id(struct device *dev) | ||
596 | { | ||
597 | struct ab3550 *ab = dev_get_drvdata(dev->parent); | ||
598 | return (int)ab->chip_id; | ||
599 | } | ||
600 | |||
601 | static int ab3550_mask_and_set_register_interruptible(struct device *dev, | ||
602 | u8 bank, u8 reg, u8 bitmask, u8 bitvalues) | ||
603 | { | ||
604 | struct ab3550 *ab; | ||
605 | struct platform_device *pdev = to_platform_device(dev); | ||
606 | |||
607 | if ((AB3550_NUM_BANKS <= bank) || | ||
608 | !reg_write_allowed(&ab3550_reg_ranges[pdev->id][bank], reg)) | ||
609 | return -EINVAL; | ||
610 | |||
611 | ab = dev_get_drvdata(dev->parent); | ||
612 | return mask_and_set_register_interruptible(ab, bank, reg, | ||
613 | bitmask, bitvalues); | ||
614 | } | ||
615 | |||
616 | static int ab3550_set_register_interruptible(struct device *dev, u8 bank, | ||
617 | u8 reg, u8 value) | ||
618 | { | ||
619 | return ab3550_mask_and_set_register_interruptible(dev, bank, reg, 0xFF, | ||
620 | value); | ||
621 | } | ||
622 | |||
623 | static int ab3550_get_register_interruptible(struct device *dev, u8 bank, | ||
624 | u8 reg, u8 *value) | ||
625 | { | ||
626 | struct ab3550 *ab; | ||
627 | struct platform_device *pdev = to_platform_device(dev); | ||
628 | |||
629 | if ((AB3550_NUM_BANKS <= bank) || | ||
630 | !reg_read_allowed(&ab3550_reg_ranges[pdev->id][bank], reg)) | ||
631 | return -EINVAL; | ||
632 | |||
633 | ab = dev_get_drvdata(dev->parent); | ||
634 | return get_register_interruptible(ab, bank, reg, value); | ||
635 | } | ||
636 | |||
637 | static int ab3550_get_register_page_interruptible(struct device *dev, u8 bank, | ||
638 | u8 first_reg, u8 *regvals, u8 numregs) | ||
639 | { | ||
640 | struct ab3550 *ab; | ||
641 | struct platform_device *pdev = to_platform_device(dev); | ||
642 | |||
643 | if ((AB3550_NUM_BANKS <= bank) || | ||
644 | !page_read_allowed(&ab3550_reg_ranges[pdev->id][bank], | ||
645 | first_reg, (first_reg + numregs - 1))) | ||
646 | return -EINVAL; | ||
647 | |||
648 | ab = dev_get_drvdata(dev->parent); | ||
649 | return get_register_page_interruptible(ab, bank, first_reg, regvals, | ||
650 | numregs); | ||
651 | } | ||
652 | |||
653 | static int ab3550_event_registers_startup_state_get(struct device *dev, | ||
654 | u8 *event) | ||
655 | { | ||
656 | struct ab3550 *ab; | ||
657 | |||
658 | ab = dev_get_drvdata(dev->parent); | ||
659 | if (!ab->startup_events_read) | ||
660 | return -EAGAIN; /* Try again later */ | ||
661 | |||
662 | memcpy(event, ab->startup_events, AB3550_NUM_EVENT_REG); | ||
663 | return 0; | ||
664 | } | ||
665 | |||
666 | static int ab3550_startup_irq_enabled(struct device *dev, unsigned int irq) | ||
667 | { | ||
668 | struct ab3550 *ab; | ||
669 | struct ab3550_platform_data *plf_data; | ||
670 | bool val; | ||
671 | |||
672 | ab = irq_get_chip_data(irq); | ||
673 | plf_data = ab->i2c_client[0]->dev.platform_data; | ||
674 | irq -= plf_data->irq.base; | ||
675 | val = ((ab->startup_events[irq / 8] & BIT(irq % 8)) != 0); | ||
676 | |||
677 | return val; | ||
678 | } | ||
679 | |||
680 | static struct abx500_ops ab3550_ops = { | ||
681 | .get_chip_id = ab3550_get_chip_id, | ||
682 | .get_register = ab3550_get_register_interruptible, | ||
683 | .set_register = ab3550_set_register_interruptible, | ||
684 | .get_register_page = ab3550_get_register_page_interruptible, | ||
685 | .set_register_page = NULL, | ||
686 | .mask_and_set_register = ab3550_mask_and_set_register_interruptible, | ||
687 | .event_registers_startup_state_get = | ||
688 | ab3550_event_registers_startup_state_get, | ||
689 | .startup_irq_enabled = ab3550_startup_irq_enabled, | ||
690 | }; | ||
691 | |||
692 | static irqreturn_t ab3550_irq_handler(int irq, void *data) | ||
693 | { | ||
694 | struct ab3550 *ab = data; | ||
695 | int err; | ||
696 | unsigned int i; | ||
697 | u8 e[AB3550_NUM_EVENT_REG]; | ||
698 | u8 *events; | ||
699 | unsigned long flags; | ||
700 | |||
701 | events = (ab->startup_events_read ? e : ab->startup_events); | ||
702 | |||
703 | err = get_register_page_interruptible(ab, AB3550_EVENT_BANK, | ||
704 | AB3550_EVENT_REG, events, AB3550_NUM_EVENT_REG); | ||
705 | if (err) | ||
706 | goto err_event_rd; | ||
707 | |||
708 | if (!ab->startup_events_read) { | ||
709 | dev_info(&ab->i2c_client[0]->dev, | ||
710 | "startup events 0x%x,0x%x,0x%x,0x%x,0x%x\n", | ||
711 | ab->startup_events[0], ab->startup_events[1], | ||
712 | ab->startup_events[2], ab->startup_events[3], | ||
713 | ab->startup_events[4]); | ||
714 | ab->startup_events_read = true; | ||
715 | goto out; | ||
716 | } | ||
717 | |||
718 | /* The two highest bits in event[4] are not used. */ | ||
719 | events[4] &= 0x3f; | ||
720 | |||
721 | spin_lock_irqsave(&ab->event_lock, flags); | ||
722 | for (i = 0; i < AB3550_NUM_EVENT_REG; i++) | ||
723 | events[i] &= ~ab->event_mask[i]; | ||
724 | spin_unlock_irqrestore(&ab->event_lock, flags); | ||
725 | |||
726 | for (i = 0; i < AB3550_NUM_EVENT_REG; i++) { | ||
727 | u8 bit; | ||
728 | u8 event_reg; | ||
729 | |||
730 | dev_dbg(&ab->i2c_client[0]->dev, "IRQ Event[%d]: 0x%2x\n", | ||
731 | i, events[i]); | ||
732 | |||
733 | event_reg = events[i]; | ||
734 | for (bit = 0; event_reg; bit++, event_reg /= 2) { | ||
735 | if (event_reg % 2) { | ||
736 | unsigned int irq; | ||
737 | struct ab3550_platform_data *plf_data; | ||
738 | |||
739 | plf_data = ab->i2c_client[0]->dev.platform_data; | ||
740 | irq = plf_data->irq.base + (i * 8) + bit; | ||
741 | handle_nested_irq(irq); | ||
742 | } | ||
743 | } | ||
744 | } | ||
745 | out: | ||
746 | return IRQ_HANDLED; | ||
747 | |||
748 | err_event_rd: | ||
749 | dev_dbg(&ab->i2c_client[0]->dev, "error reading event registers\n"); | ||
750 | return IRQ_HANDLED; | ||
751 | } | ||
752 | |||
753 | #ifdef CONFIG_DEBUG_FS | ||
754 | static struct ab3550_reg_ranges debug_ranges[AB3550_NUM_BANKS] = { | ||
755 | { | ||
756 | .count = 6, | ||
757 | .range = (struct ab3550_reg_range[]) { | ||
758 | { | ||
759 | .first = 0x00, | ||
760 | .last = 0x0e, | ||
761 | }, | ||
762 | { | ||
763 | .first = 0x10, | ||
764 | .last = 0x1a, | ||
765 | }, | ||
766 | { | ||
767 | .first = 0x1e, | ||
768 | .last = 0x4f, | ||
769 | }, | ||
770 | { | ||
771 | .first = 0x51, | ||
772 | .last = 0x63, | ||
773 | }, | ||
774 | { | ||
775 | .first = 0x65, | ||
776 | .last = 0xa3, | ||
777 | }, | ||
778 | { | ||
779 | .first = 0xa5, | ||
780 | .last = 0xa8, | ||
781 | }, | ||
782 | } | ||
783 | }, | ||
784 | { | ||
785 | .count = 8, | ||
786 | .range = (struct ab3550_reg_range[]) { | ||
787 | { | ||
788 | .first = 0x00, | ||
789 | .last = 0x0e, | ||
790 | }, | ||
791 | { | ||
792 | .first = 0x10, | ||
793 | .last = 0x17, | ||
794 | }, | ||
795 | { | ||
796 | .first = 0x1a, | ||
797 | .last = 0x1c, | ||
798 | }, | ||
799 | { | ||
800 | .first = 0x20, | ||
801 | .last = 0x56, | ||
802 | }, | ||
803 | { | ||
804 | .first = 0x5a, | ||
805 | .last = 0x88, | ||
806 | }, | ||
807 | { | ||
808 | .first = 0x8a, | ||
809 | .last = 0xad, | ||
810 | }, | ||
811 | { | ||
812 | .first = 0xb0, | ||
813 | .last = 0xba, | ||
814 | }, | ||
815 | { | ||
816 | .first = 0xbc, | ||
817 | .last = 0xc3, | ||
818 | }, | ||
819 | } | ||
820 | }, | ||
821 | }; | ||
822 | |||
823 | static int ab3550_registers_print(struct seq_file *s, void *p) | ||
824 | { | ||
825 | struct ab3550 *ab = s->private; | ||
826 | int bank; | ||
827 | |||
828 | seq_printf(s, AB3550_NAME_STRING " register values:\n"); | ||
829 | |||
830 | for (bank = 0; bank < AB3550_NUM_BANKS; bank++) { | ||
831 | unsigned int i; | ||
832 | |||
833 | seq_printf(s, " bank %d:\n", bank); | ||
834 | for (i = 0; i < debug_ranges[bank].count; i++) { | ||
835 | u8 reg; | ||
836 | |||
837 | for (reg = debug_ranges[bank].range[i].first; | ||
838 | reg <= debug_ranges[bank].range[i].last; | ||
839 | reg++) { | ||
840 | u8 value; | ||
841 | |||
842 | get_register_interruptible(ab, bank, reg, | ||
843 | &value); | ||
844 | seq_printf(s, " [%d/0x%02X]: 0x%02X\n", bank, | ||
845 | reg, value); | ||
846 | } | ||
847 | } | ||
848 | } | ||
849 | return 0; | ||
850 | } | ||
851 | |||
852 | static int ab3550_registers_open(struct inode *inode, struct file *file) | ||
853 | { | ||
854 | return single_open(file, ab3550_registers_print, inode->i_private); | ||
855 | } | ||
856 | |||
857 | static const struct file_operations ab3550_registers_fops = { | ||
858 | .open = ab3550_registers_open, | ||
859 | .read = seq_read, | ||
860 | .llseek = seq_lseek, | ||
861 | .release = single_release, | ||
862 | .owner = THIS_MODULE, | ||
863 | }; | ||
864 | |||
865 | static int ab3550_bank_print(struct seq_file *s, void *p) | ||
866 | { | ||
867 | struct ab3550 *ab = s->private; | ||
868 | |||
869 | seq_printf(s, "%d\n", ab->debug_bank); | ||
870 | return 0; | ||
871 | } | ||
872 | |||
873 | static int ab3550_bank_open(struct inode *inode, struct file *file) | ||
874 | { | ||
875 | return single_open(file, ab3550_bank_print, inode->i_private); | ||
876 | } | ||
877 | |||
878 | static ssize_t ab3550_bank_write(struct file *file, | ||
879 | const char __user *user_buf, | ||
880 | size_t count, loff_t *ppos) | ||
881 | { | ||
882 | struct ab3550 *ab = ((struct seq_file *)(file->private_data))->private; | ||
883 | unsigned long user_bank; | ||
884 | int err; | ||
885 | |||
886 | /* Get userspace string and assure termination */ | ||
887 | err = kstrtoul_from_user(user_buf, count, 0, &user_bank); | ||
888 | if (err) | ||
889 | return err; | ||
890 | |||
891 | if (user_bank >= AB3550_NUM_BANKS) { | ||
892 | dev_err(&ab->i2c_client[0]->dev, | ||
893 | "debugfs error input > number of banks\n"); | ||
894 | return -EINVAL; | ||
895 | } | ||
896 | |||
897 | ab->debug_bank = user_bank; | ||
898 | |||
899 | return count; | ||
900 | } | ||
901 | |||
902 | static int ab3550_address_print(struct seq_file *s, void *p) | ||
903 | { | ||
904 | struct ab3550 *ab = s->private; | ||
905 | |||
906 | seq_printf(s, "0x%02X\n", ab->debug_address); | ||
907 | return 0; | ||
908 | } | ||
909 | |||
910 | static int ab3550_address_open(struct inode *inode, struct file *file) | ||
911 | { | ||
912 | return single_open(file, ab3550_address_print, inode->i_private); | ||
913 | } | ||
914 | |||
915 | static ssize_t ab3550_address_write(struct file *file, | ||
916 | const char __user *user_buf, | ||
917 | size_t count, loff_t *ppos) | ||
918 | { | ||
919 | struct ab3550 *ab = ((struct seq_file *)(file->private_data))->private; | ||
920 | unsigned long user_address; | ||
921 | int err; | ||
922 | |||
923 | /* Get userspace string and assure termination */ | ||
924 | err = kstrtoul_from_user(user_buf, count, 0, &user_address); | ||
925 | if (err) | ||
926 | return err; | ||
927 | |||
928 | if (user_address > 0xff) { | ||
929 | dev_err(&ab->i2c_client[0]->dev, | ||
930 | "debugfs error input > 0xff\n"); | ||
931 | return -EINVAL; | ||
932 | } | ||
933 | ab->debug_address = user_address; | ||
934 | return count; | ||
935 | } | ||
936 | |||
937 | static int ab3550_val_print(struct seq_file *s, void *p) | ||
938 | { | ||
939 | struct ab3550 *ab = s->private; | ||
940 | int err; | ||
941 | u8 regvalue; | ||
942 | |||
943 | err = get_register_interruptible(ab, (u8)ab->debug_bank, | ||
944 | (u8)ab->debug_address, ®value); | ||
945 | if (err) | ||
946 | return -EINVAL; | ||
947 | seq_printf(s, "0x%02X\n", regvalue); | ||
948 | |||
949 | return 0; | ||
950 | } | ||
951 | |||
952 | static int ab3550_val_open(struct inode *inode, struct file *file) | ||
953 | { | ||
954 | return single_open(file, ab3550_val_print, inode->i_private); | ||
955 | } | ||
956 | |||
957 | static ssize_t ab3550_val_write(struct file *file, | ||
958 | const char __user *user_buf, | ||
959 | size_t count, loff_t *ppos) | ||
960 | { | ||
961 | struct ab3550 *ab = ((struct seq_file *)(file->private_data))->private; | ||
962 | unsigned long user_val; | ||
963 | int err; | ||
964 | u8 regvalue; | ||
965 | |||
966 | /* Get userspace string and assure termination */ | ||
967 | err = kstrtoul_from_user(user_buf, count, 0, &user_val); | ||
968 | if (err) | ||
969 | return err; | ||
970 | |||
971 | if (user_val > 0xff) { | ||
972 | dev_err(&ab->i2c_client[0]->dev, | ||
973 | "debugfs error input > 0xff\n"); | ||
974 | return -EINVAL; | ||
975 | } | ||
976 | err = mask_and_set_register_interruptible( | ||
977 | ab, (u8)ab->debug_bank, | ||
978 | (u8)ab->debug_address, 0xFF, (u8)user_val); | ||
979 | if (err) | ||
980 | return -EINVAL; | ||
981 | |||
982 | get_register_interruptible(ab, (u8)ab->debug_bank, | ||
983 | (u8)ab->debug_address, ®value); | ||
984 | if (err) | ||
985 | return -EINVAL; | ||
986 | |||
987 | return count; | ||
988 | } | ||
989 | |||
990 | static const struct file_operations ab3550_bank_fops = { | ||
991 | .open = ab3550_bank_open, | ||
992 | .write = ab3550_bank_write, | ||
993 | .read = seq_read, | ||
994 | .llseek = seq_lseek, | ||
995 | .release = single_release, | ||
996 | .owner = THIS_MODULE, | ||
997 | }; | ||
998 | |||
999 | static const struct file_operations ab3550_address_fops = { | ||
1000 | .open = ab3550_address_open, | ||
1001 | .write = ab3550_address_write, | ||
1002 | .read = seq_read, | ||
1003 | .llseek = seq_lseek, | ||
1004 | .release = single_release, | ||
1005 | .owner = THIS_MODULE, | ||
1006 | }; | ||
1007 | |||
1008 | static const struct file_operations ab3550_val_fops = { | ||
1009 | .open = ab3550_val_open, | ||
1010 | .write = ab3550_val_write, | ||
1011 | .read = seq_read, | ||
1012 | .llseek = seq_lseek, | ||
1013 | .release = single_release, | ||
1014 | .owner = THIS_MODULE, | ||
1015 | }; | ||
1016 | |||
1017 | static struct dentry *ab3550_dir; | ||
1018 | static struct dentry *ab3550_reg_file; | ||
1019 | static struct dentry *ab3550_bank_file; | ||
1020 | static struct dentry *ab3550_address_file; | ||
1021 | static struct dentry *ab3550_val_file; | ||
1022 | |||
1023 | static inline void ab3550_setup_debugfs(struct ab3550 *ab) | ||
1024 | { | ||
1025 | ab->debug_bank = 0; | ||
1026 | ab->debug_address = 0x00; | ||
1027 | |||
1028 | ab3550_dir = debugfs_create_dir(AB3550_NAME_STRING, NULL); | ||
1029 | if (!ab3550_dir) | ||
1030 | goto exit_no_debugfs; | ||
1031 | |||
1032 | ab3550_reg_file = debugfs_create_file("all-registers", | ||
1033 | S_IRUGO, ab3550_dir, ab, &ab3550_registers_fops); | ||
1034 | if (!ab3550_reg_file) | ||
1035 | goto exit_destroy_dir; | ||
1036 | |||
1037 | ab3550_bank_file = debugfs_create_file("register-bank", | ||
1038 | (S_IRUGO | S_IWUSR), ab3550_dir, ab, &ab3550_bank_fops); | ||
1039 | if (!ab3550_bank_file) | ||
1040 | goto exit_destroy_reg; | ||
1041 | |||
1042 | ab3550_address_file = debugfs_create_file("register-address", | ||
1043 | (S_IRUGO | S_IWUSR), ab3550_dir, ab, &ab3550_address_fops); | ||
1044 | if (!ab3550_address_file) | ||
1045 | goto exit_destroy_bank; | ||
1046 | |||
1047 | ab3550_val_file = debugfs_create_file("register-value", | ||
1048 | (S_IRUGO | S_IWUSR), ab3550_dir, ab, &ab3550_val_fops); | ||
1049 | if (!ab3550_val_file) | ||
1050 | goto exit_destroy_address; | ||
1051 | |||
1052 | return; | ||
1053 | |||
1054 | exit_destroy_address: | ||
1055 | debugfs_remove(ab3550_address_file); | ||
1056 | exit_destroy_bank: | ||
1057 | debugfs_remove(ab3550_bank_file); | ||
1058 | exit_destroy_reg: | ||
1059 | debugfs_remove(ab3550_reg_file); | ||
1060 | exit_destroy_dir: | ||
1061 | debugfs_remove(ab3550_dir); | ||
1062 | exit_no_debugfs: | ||
1063 | dev_err(&ab->i2c_client[0]->dev, "failed to create debugfs entries.\n"); | ||
1064 | return; | ||
1065 | } | ||
1066 | |||
1067 | static inline void ab3550_remove_debugfs(void) | ||
1068 | { | ||
1069 | debugfs_remove(ab3550_val_file); | ||
1070 | debugfs_remove(ab3550_address_file); | ||
1071 | debugfs_remove(ab3550_bank_file); | ||
1072 | debugfs_remove(ab3550_reg_file); | ||
1073 | debugfs_remove(ab3550_dir); | ||
1074 | } | ||
1075 | |||
1076 | #else /* !CONFIG_DEBUG_FS */ | ||
1077 | static inline void ab3550_setup_debugfs(struct ab3550 *ab) | ||
1078 | { | ||
1079 | } | ||
1080 | static inline void ab3550_remove_debugfs(void) | ||
1081 | { | ||
1082 | } | ||
1083 | #endif | ||
1084 | |||
1085 | /* | ||
1086 | * Basic set-up, datastructure creation/destruction and I2C interface. | ||
1087 | * This sets up a default config in the AB3550 chip so that it | ||
1088 | * will work as expected. | ||
1089 | */ | ||
1090 | static int __init ab3550_setup(struct ab3550 *ab) | ||
1091 | { | ||
1092 | int err = 0; | ||
1093 | int i; | ||
1094 | struct ab3550_platform_data *plf_data; | ||
1095 | struct abx500_init_settings *settings; | ||
1096 | |||
1097 | plf_data = ab->i2c_client[0]->dev.platform_data; | ||
1098 | settings = plf_data->init_settings; | ||
1099 | |||
1100 | for (i = 0; i < plf_data->init_settings_sz; i++) { | ||
1101 | err = mask_and_set_register_interruptible(ab, | ||
1102 | settings[i].bank, | ||
1103 | settings[i].reg, | ||
1104 | 0xFF, settings[i].setting); | ||
1105 | if (err) | ||
1106 | goto exit_no_setup; | ||
1107 | |||
1108 | /* If event mask register update the event mask in ab3550 */ | ||
1109 | if ((settings[i].bank == 0) && | ||
1110 | (AB3550_IMR1 <= settings[i].reg) && | ||
1111 | (settings[i].reg <= AB3550_IMR5)) { | ||
1112 | ab->event_mask[settings[i].reg - AB3550_IMR1] = | ||
1113 | settings[i].setting; | ||
1114 | } | ||
1115 | } | ||
1116 | exit_no_setup: | ||
1117 | return err; | ||
1118 | } | ||
1119 | |||
1120 | static void ab3550_mask_work(struct work_struct *work) | ||
1121 | { | ||
1122 | struct ab3550 *ab = container_of(work, struct ab3550, mask_work); | ||
1123 | int i; | ||
1124 | unsigned long flags; | ||
1125 | u8 mask[AB3550_NUM_EVENT_REG]; | ||
1126 | |||
1127 | spin_lock_irqsave(&ab->event_lock, flags); | ||
1128 | for (i = 0; i < AB3550_NUM_EVENT_REG; i++) | ||
1129 | mask[i] = ab->event_mask[i]; | ||
1130 | spin_unlock_irqrestore(&ab->event_lock, flags); | ||
1131 | |||
1132 | for (i = 0; i < AB3550_NUM_EVENT_REG; i++) { | ||
1133 | int err; | ||
1134 | |||
1135 | err = mask_and_set_register_interruptible(ab, 0, | ||
1136 | (AB3550_IMR1 + i), ~0, mask[i]); | ||
1137 | if (err) | ||
1138 | dev_err(&ab->i2c_client[0]->dev, | ||
1139 | "ab3550_mask_work failed 0x%x,0x%x\n", | ||
1140 | (AB3550_IMR1 + i), mask[i]); | ||
1141 | } | ||
1142 | } | ||
1143 | |||
1144 | static void ab3550_mask(struct irq_data *data) | ||
1145 | { | ||
1146 | unsigned long flags; | ||
1147 | struct ab3550 *ab; | ||
1148 | struct ab3550_platform_data *plf_data; | ||
1149 | int irq; | ||
1150 | |||
1151 | ab = irq_data_get_irq_chip_data(data); | ||
1152 | plf_data = ab->i2c_client[0]->dev.platform_data; | ||
1153 | irq = data->irq - plf_data->irq.base; | ||
1154 | |||
1155 | spin_lock_irqsave(&ab->event_lock, flags); | ||
1156 | ab->event_mask[irq / 8] |= BIT(irq % 8); | ||
1157 | spin_unlock_irqrestore(&ab->event_lock, flags); | ||
1158 | |||
1159 | schedule_work(&ab->mask_work); | ||
1160 | } | ||
1161 | |||
1162 | static void ab3550_unmask(struct irq_data *data) | ||
1163 | { | ||
1164 | unsigned long flags; | ||
1165 | struct ab3550 *ab; | ||
1166 | struct ab3550_platform_data *plf_data; | ||
1167 | int irq; | ||
1168 | |||
1169 | ab = irq_data_get_irq_chip_data(data); | ||
1170 | plf_data = ab->i2c_client[0]->dev.platform_data; | ||
1171 | irq = data->irq - plf_data->irq.base; | ||
1172 | |||
1173 | spin_lock_irqsave(&ab->event_lock, flags); | ||
1174 | ab->event_mask[irq / 8] &= ~BIT(irq % 8); | ||
1175 | spin_unlock_irqrestore(&ab->event_lock, flags); | ||
1176 | |||
1177 | schedule_work(&ab->mask_work); | ||
1178 | } | ||
1179 | |||
1180 | static void noop(struct irq_data *data) | ||
1181 | { | ||
1182 | } | ||
1183 | |||
1184 | static struct irq_chip ab3550_irq_chip = { | ||
1185 | .name = "ab3550-core", /* Keep the same name as the request */ | ||
1186 | .irq_disable = ab3550_mask, /* No default to mask in chip.c */ | ||
1187 | .irq_ack = noop, | ||
1188 | .irq_mask = ab3550_mask, | ||
1189 | .irq_unmask = ab3550_unmask, | ||
1190 | }; | ||
1191 | |||
1192 | struct ab_family_id { | ||
1193 | u8 id; | ||
1194 | char *name; | ||
1195 | }; | ||
1196 | |||
1197 | static const struct ab_family_id ids[] __initdata = { | ||
1198 | /* AB3550 */ | ||
1199 | { | ||
1200 | .id = AB3550_P1A, | ||
1201 | .name = "P1A" | ||
1202 | }, | ||
1203 | /* Terminator */ | ||
1204 | { | ||
1205 | .id = 0x00, | ||
1206 | } | ||
1207 | }; | ||
1208 | |||
1209 | static int __init ab3550_probe(struct i2c_client *client, | ||
1210 | const struct i2c_device_id *id) | ||
1211 | { | ||
1212 | struct ab3550 *ab; | ||
1213 | struct ab3550_platform_data *ab3550_plf_data = | ||
1214 | client->dev.platform_data; | ||
1215 | int err; | ||
1216 | int i; | ||
1217 | int num_i2c_clients = 0; | ||
1218 | |||
1219 | ab = kzalloc(sizeof(struct ab3550), GFP_KERNEL); | ||
1220 | if (!ab) { | ||
1221 | dev_err(&client->dev, | ||
1222 | "could not allocate " AB3550_NAME_STRING " device\n"); | ||
1223 | return -ENOMEM; | ||
1224 | } | ||
1225 | |||
1226 | /* Initialize data structure */ | ||
1227 | mutex_init(&ab->access_mutex); | ||
1228 | spin_lock_init(&ab->event_lock); | ||
1229 | ab->i2c_client[0] = client; | ||
1230 | |||
1231 | i2c_set_clientdata(client, ab); | ||
1232 | |||
1233 | /* Read chip ID register */ | ||
1234 | err = get_register_interruptible(ab, 0, AB3550_CID_REG, &ab->chip_id); | ||
1235 | if (err) { | ||
1236 | dev_err(&client->dev, "could not communicate with the analog " | ||
1237 | "baseband chip\n"); | ||
1238 | goto exit_no_detect; | ||
1239 | } | ||
1240 | |||
1241 | for (i = 0; ids[i].id != 0x0; i++) { | ||
1242 | if (ids[i].id == ab->chip_id) { | ||
1243 | snprintf(&ab->chip_name[0], sizeof(ab->chip_name) - 1, | ||
1244 | AB3550_ID_FORMAT_STRING, ids[i].name); | ||
1245 | break; | ||
1246 | } | ||
1247 | } | ||
1248 | |||
1249 | if (ids[i].id == 0x0) { | ||
1250 | dev_err(&client->dev, "unknown analog baseband chip id: 0x%x\n", | ||
1251 | ab->chip_id); | ||
1252 | dev_err(&client->dev, "driver not started!\n"); | ||
1253 | goto exit_no_detect; | ||
1254 | } | ||
1255 | |||
1256 | dev_info(&client->dev, "detected AB chip: %s\n", &ab->chip_name[0]); | ||
1257 | |||
1258 | /* Attach other dummy I2C clients. */ | ||
1259 | while (++num_i2c_clients < AB3550_NUM_BANKS) { | ||
1260 | ab->i2c_client[num_i2c_clients] = | ||
1261 | i2c_new_dummy(client->adapter, | ||
1262 | (client->addr + num_i2c_clients)); | ||
1263 | if (!ab->i2c_client[num_i2c_clients]) { | ||
1264 | err = -ENOMEM; | ||
1265 | goto exit_no_dummy_client; | ||
1266 | } | ||
1267 | strlcpy(ab->i2c_client[num_i2c_clients]->name, id->name, | ||
1268 | sizeof(ab->i2c_client[num_i2c_clients]->name)); | ||
1269 | } | ||
1270 | |||
1271 | err = ab3550_setup(ab); | ||
1272 | if (err) | ||
1273 | goto exit_no_setup; | ||
1274 | |||
1275 | INIT_WORK(&ab->mask_work, ab3550_mask_work); | ||
1276 | |||
1277 | for (i = 0; i < ab3550_plf_data->irq.count; i++) { | ||
1278 | unsigned int irq; | ||
1279 | |||
1280 | irq = ab3550_plf_data->irq.base + i; | ||
1281 | irq_set_chip_data(irq, ab); | ||
1282 | irq_set_chip_and_handler(irq, &ab3550_irq_chip, | ||
1283 | handle_simple_irq); | ||
1284 | irq_set_nested_thread(irq, 1); | ||
1285 | #ifdef CONFIG_ARM | ||
1286 | set_irq_flags(irq, IRQF_VALID); | ||
1287 | #else | ||
1288 | irq_set_noprobe(irq); | ||
1289 | #endif | ||
1290 | } | ||
1291 | |||
1292 | err = request_threaded_irq(client->irq, NULL, ab3550_irq_handler, | ||
1293 | IRQF_ONESHOT, "ab3550-core", ab); | ||
1294 | /* This real unpredictable IRQ is of course sampled for entropy */ | ||
1295 | rand_initialize_irq(client->irq); | ||
1296 | |||
1297 | if (err) | ||
1298 | goto exit_no_irq; | ||
1299 | |||
1300 | err = abx500_register_ops(&client->dev, &ab3550_ops); | ||
1301 | if (err) | ||
1302 | goto exit_no_ops; | ||
1303 | |||
1304 | /* Set up and register the platform devices. */ | ||
1305 | for (i = 0; i < AB3550_NUM_DEVICES; i++) { | ||
1306 | ab3550_devs[i].platform_data = ab3550_plf_data->dev_data[i]; | ||
1307 | ab3550_devs[i].pdata_size = ab3550_plf_data->dev_data_sz[i]; | ||
1308 | } | ||
1309 | |||
1310 | err = mfd_add_devices(&client->dev, 0, ab3550_devs, | ||
1311 | ARRAY_SIZE(ab3550_devs), NULL, | ||
1312 | ab3550_plf_data->irq.base); | ||
1313 | |||
1314 | ab3550_setup_debugfs(ab); | ||
1315 | |||
1316 | return 0; | ||
1317 | |||
1318 | exit_no_ops: | ||
1319 | exit_no_irq: | ||
1320 | exit_no_setup: | ||
1321 | exit_no_dummy_client: | ||
1322 | /* Unregister the dummy i2c clients. */ | ||
1323 | while (--num_i2c_clients) | ||
1324 | i2c_unregister_device(ab->i2c_client[num_i2c_clients]); | ||
1325 | exit_no_detect: | ||
1326 | kfree(ab); | ||
1327 | return err; | ||
1328 | } | ||
1329 | |||
1330 | static int __exit ab3550_remove(struct i2c_client *client) | ||
1331 | { | ||
1332 | struct ab3550 *ab = i2c_get_clientdata(client); | ||
1333 | int num_i2c_clients = AB3550_NUM_BANKS; | ||
1334 | |||
1335 | mfd_remove_devices(&client->dev); | ||
1336 | ab3550_remove_debugfs(); | ||
1337 | |||
1338 | while (--num_i2c_clients) | ||
1339 | i2c_unregister_device(ab->i2c_client[num_i2c_clients]); | ||
1340 | |||
1341 | /* | ||
1342 | * At this point, all subscribers should have unregistered | ||
1343 | * their notifiers so deactivate IRQ | ||
1344 | */ | ||
1345 | free_irq(client->irq, ab); | ||
1346 | kfree(ab); | ||
1347 | return 0; | ||
1348 | } | ||
1349 | |||
1350 | static const struct i2c_device_id ab3550_id[] = { | ||
1351 | {AB3550_NAME_STRING, 0}, | ||
1352 | {} | ||
1353 | }; | ||
1354 | MODULE_DEVICE_TABLE(i2c, ab3550_id); | ||
1355 | |||
1356 | static struct i2c_driver ab3550_driver = { | ||
1357 | .driver = { | ||
1358 | .name = AB3550_NAME_STRING, | ||
1359 | .owner = THIS_MODULE, | ||
1360 | }, | ||
1361 | .id_table = ab3550_id, | ||
1362 | .probe = ab3550_probe, | ||
1363 | .remove = __exit_p(ab3550_remove), | ||
1364 | }; | ||
1365 | |||
1366 | static int __init ab3550_i2c_init(void) | ||
1367 | { | ||
1368 | return i2c_add_driver(&ab3550_driver); | ||
1369 | } | ||
1370 | |||
1371 | static void __exit ab3550_i2c_exit(void) | ||
1372 | { | ||
1373 | i2c_del_driver(&ab3550_driver); | ||
1374 | } | ||
1375 | |||
1376 | subsys_initcall(ab3550_i2c_init); | ||
1377 | module_exit(ab3550_i2c_exit); | ||
1378 | |||
1379 | MODULE_AUTHOR("Mattias Wallin <mattias.wallin@stericsson.com>"); | ||
1380 | MODULE_DESCRIPTION("AB3550 core driver"); | ||
1381 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/mfd/ab5500-core.c b/drivers/mfd/ab5500-core.c new file mode 100644 index 000000000000..4175544b491b --- /dev/null +++ b/drivers/mfd/ab5500-core.c | |||
@@ -0,0 +1,1439 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007-2011 ST-Ericsson | ||
3 | * License terms: GNU General Public License (GPL) version 2 | ||
4 | * Low-level core for exclusive access to the AB5500 IC on the I2C bus | ||
5 | * and some basic chip-configuration. | ||
6 | * Author: Bengt Jonsson <bengt.g.jonsson@stericsson.com> | ||
7 | * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com> | ||
8 | * Author: Mattias Wallin <mattias.wallin@stericsson.com> | ||
9 | * Author: Rickard Andersson <rickard.andersson@stericsson.com> | ||
10 | * Author: Karl Komierowski <karl.komierowski@stericsson.com> | ||
11 | * Author: Bibek Basu <bibek.basu@stericsson.com> | ||
12 | * | ||
13 | * TODO: Event handling with irq_chip. Waiting for PRCMU fw support. | ||
14 | */ | ||
15 | |||
16 | #include <linux/mutex.h> | ||
17 | #include <linux/err.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/device.h> | ||
21 | #include <linux/irq.h> | ||
22 | #include <linux/interrupt.h> | ||
23 | #include <linux/random.h> | ||
24 | #include <linux/mfd/ab5500/ab5500.h> | ||
25 | #include <linux/mfd/abx500.h> | ||
26 | #include <linux/list.h> | ||
27 | #include <linux/bitops.h> | ||
28 | #include <linux/spinlock.h> | ||
29 | #include <linux/mfd/core.h> | ||
30 | #include <linux/version.h> | ||
31 | #include <linux/mfd/db5500-prcmu.h> | ||
32 | |||
33 | #include "ab5500-core.h" | ||
34 | #include "ab5500-debugfs.h" | ||
35 | |||
36 | #define AB5500_NUM_EVENT_REG 23 | ||
37 | #define AB5500_IT_LATCH0_REG 0x40 | ||
38 | #define AB5500_IT_MASK0_REG 0x60 | ||
39 | |||
40 | /* | ||
41 | * Permissible register ranges for reading and writing per device and bank. | ||
42 | * | ||
43 | * The ranges must be listed in increasing address order, and no overlaps are | ||
44 | * allowed. It is assumed that write permission implies read permission | ||
45 | * (i.e. only RO and RW permissions should be used). Ranges with write | ||
46 | * permission must not be split up. | ||
47 | */ | ||
48 | |||
49 | #define NO_RANGE {.count = 0, .range = NULL,} | ||
50 | static struct ab5500_i2c_banks ab5500_bank_ranges[AB5500_NUM_DEVICES] = { | ||
51 | [AB5500_DEVID_USB] = { | ||
52 | .nbanks = 1, | ||
53 | .bank = (struct ab5500_i2c_ranges []) { | ||
54 | { | ||
55 | .bankid = AB5500_BANK_USB, | ||
56 | .nranges = 12, | ||
57 | .range = (struct ab5500_reg_range[]) { | ||
58 | { | ||
59 | .first = 0x01, | ||
60 | .last = 0x01, | ||
61 | .perm = AB5500_PERM_RW, | ||
62 | }, | ||
63 | { | ||
64 | .first = 0x80, | ||
65 | .last = 0x83, | ||
66 | .perm = AB5500_PERM_RW, | ||
67 | }, | ||
68 | { | ||
69 | .first = 0x87, | ||
70 | .last = 0x8A, | ||
71 | .perm = AB5500_PERM_RW, | ||
72 | }, | ||
73 | { | ||
74 | .first = 0x8B, | ||
75 | .last = 0x8B, | ||
76 | .perm = AB5500_PERM_RO, | ||
77 | }, | ||
78 | { | ||
79 | .first = 0x91, | ||
80 | .last = 0x92, | ||
81 | .perm = AB5500_PERM_RO, | ||
82 | }, | ||
83 | { | ||
84 | .first = 0x93, | ||
85 | .last = 0x93, | ||
86 | .perm = AB5500_PERM_RW, | ||
87 | }, | ||
88 | { | ||
89 | .first = 0x94, | ||
90 | .last = 0x94, | ||
91 | .perm = AB5500_PERM_RO, | ||
92 | }, | ||
93 | { | ||
94 | .first = 0xA8, | ||
95 | .last = 0xB0, | ||
96 | .perm = AB5500_PERM_RO, | ||
97 | }, | ||
98 | { | ||
99 | .first = 0xB2, | ||
100 | .last = 0xB2, | ||
101 | .perm = AB5500_PERM_RO, | ||
102 | }, | ||
103 | { | ||
104 | .first = 0xB4, | ||
105 | .last = 0xBC, | ||
106 | .perm = AB5500_PERM_RO, | ||
107 | }, | ||
108 | { | ||
109 | .first = 0xBF, | ||
110 | .last = 0xBF, | ||
111 | .perm = AB5500_PERM_RO, | ||
112 | }, | ||
113 | { | ||
114 | .first = 0xC1, | ||
115 | .last = 0xC5, | ||
116 | .perm = AB5500_PERM_RO, | ||
117 | }, | ||
118 | }, | ||
119 | }, | ||
120 | }, | ||
121 | }, | ||
122 | [AB5500_DEVID_ADC] = { | ||
123 | .nbanks = 1, | ||
124 | .bank = (struct ab5500_i2c_ranges []) { | ||
125 | { | ||
126 | .bankid = AB5500_BANK_ADC, | ||
127 | .nranges = 6, | ||
128 | .range = (struct ab5500_reg_range[]) { | ||
129 | { | ||
130 | .first = 0x1F, | ||
131 | .last = 0x22, | ||
132 | .perm = AB5500_PERM_RO, | ||
133 | }, | ||
134 | { | ||
135 | .first = 0x23, | ||
136 | .last = 0x24, | ||
137 | .perm = AB5500_PERM_RW, | ||
138 | }, | ||
139 | { | ||
140 | .first = 0x26, | ||
141 | .last = 0x2D, | ||
142 | .perm = AB5500_PERM_RO, | ||
143 | }, | ||
144 | { | ||
145 | .first = 0x2F, | ||
146 | .last = 0x34, | ||
147 | .perm = AB5500_PERM_RW, | ||
148 | }, | ||
149 | { | ||
150 | .first = 0x37, | ||
151 | .last = 0x57, | ||
152 | .perm = AB5500_PERM_RW, | ||
153 | }, | ||
154 | { | ||
155 | .first = 0x58, | ||
156 | .last = 0x58, | ||
157 | .perm = AB5500_PERM_RO, | ||
158 | }, | ||
159 | }, | ||
160 | }, | ||
161 | }, | ||
162 | }, | ||
163 | [AB5500_DEVID_LEDS] = { | ||
164 | .nbanks = 1, | ||
165 | .bank = (struct ab5500_i2c_ranges []) { | ||
166 | { | ||
167 | .bankid = AB5500_BANK_LED, | ||
168 | .nranges = 1, | ||
169 | .range = (struct ab5500_reg_range[]) { | ||
170 | { | ||
171 | .first = 0x00, | ||
172 | .last = 0x0C, | ||
173 | .perm = AB5500_PERM_RW, | ||
174 | }, | ||
175 | }, | ||
176 | }, | ||
177 | }, | ||
178 | }, | ||
179 | [AB5500_DEVID_VIDEO] = { | ||
180 | .nbanks = 1, | ||
181 | .bank = (struct ab5500_i2c_ranges []) { | ||
182 | { | ||
183 | .bankid = AB5500_BANK_VDENC, | ||
184 | .nranges = 12, | ||
185 | .range = (struct ab5500_reg_range[]) { | ||
186 | { | ||
187 | .first = 0x00, | ||
188 | .last = 0x08, | ||
189 | .perm = AB5500_PERM_RW, | ||
190 | }, | ||
191 | { | ||
192 | .first = 0x09, | ||
193 | .last = 0x09, | ||
194 | .perm = AB5500_PERM_RO, | ||
195 | }, | ||
196 | { | ||
197 | .first = 0x0A, | ||
198 | .last = 0x12, | ||
199 | .perm = AB5500_PERM_RW, | ||
200 | }, | ||
201 | { | ||
202 | .first = 0x15, | ||
203 | .last = 0x19, | ||
204 | .perm = AB5500_PERM_RW, | ||
205 | }, | ||
206 | { | ||
207 | .first = 0x1B, | ||
208 | .last = 0x21, | ||
209 | .perm = AB5500_PERM_RW, | ||
210 | }, | ||
211 | { | ||
212 | .first = 0x27, | ||
213 | .last = 0x2C, | ||
214 | .perm = AB5500_PERM_RW, | ||
215 | }, | ||
216 | { | ||
217 | .first = 0x41, | ||
218 | .last = 0x41, | ||
219 | .perm = AB5500_PERM_RW, | ||
220 | }, | ||
221 | { | ||
222 | .first = 0x45, | ||
223 | .last = 0x5B, | ||
224 | .perm = AB5500_PERM_RW, | ||
225 | }, | ||
226 | { | ||
227 | .first = 0x5D, | ||
228 | .last = 0x5D, | ||
229 | .perm = AB5500_PERM_RW, | ||
230 | }, | ||
231 | { | ||
232 | .first = 0x69, | ||
233 | .last = 0x69, | ||
234 | .perm = AB5500_PERM_RW, | ||
235 | }, | ||
236 | { | ||
237 | .first = 0x6C, | ||
238 | .last = 0x6D, | ||
239 | .perm = AB5500_PERM_RW, | ||
240 | }, | ||
241 | { | ||
242 | .first = 0x80, | ||
243 | .last = 0x81, | ||
244 | .perm = AB5500_PERM_RW, | ||
245 | }, | ||
246 | }, | ||
247 | }, | ||
248 | }, | ||
249 | }, | ||
250 | [AB5500_DEVID_REGULATORS] = { | ||
251 | .nbanks = 2, | ||
252 | .bank = (struct ab5500_i2c_ranges []) { | ||
253 | { | ||
254 | .bankid = AB5500_BANK_STARTUP, | ||
255 | .nranges = 12, | ||
256 | .range = (struct ab5500_reg_range[]) { | ||
257 | { | ||
258 | .first = 0x00, | ||
259 | .last = 0x01, | ||
260 | .perm = AB5500_PERM_RW, | ||
261 | }, | ||
262 | { | ||
263 | .first = 0x1F, | ||
264 | .last = 0x1F, | ||
265 | .perm = AB5500_PERM_RW, | ||
266 | }, | ||
267 | { | ||
268 | .first = 0x2E, | ||
269 | .last = 0x2E, | ||
270 | .perm = AB5500_PERM_RO, | ||
271 | }, | ||
272 | { | ||
273 | .first = 0x2F, | ||
274 | .last = 0x30, | ||
275 | .perm = AB5500_PERM_RW, | ||
276 | }, | ||
277 | { | ||
278 | .first = 0x50, | ||
279 | .last = 0x51, | ||
280 | .perm = AB5500_PERM_RW, | ||
281 | }, | ||
282 | { | ||
283 | .first = 0x60, | ||
284 | .last = 0x61, | ||
285 | .perm = AB5500_PERM_RW, | ||
286 | }, | ||
287 | { | ||
288 | .first = 0x66, | ||
289 | .last = 0x8A, | ||
290 | .perm = AB5500_PERM_RW, | ||
291 | }, | ||
292 | { | ||
293 | .first = 0x8C, | ||
294 | .last = 0x96, | ||
295 | .perm = AB5500_PERM_RW, | ||
296 | }, | ||
297 | { | ||
298 | .first = 0xAA, | ||
299 | .last = 0xB4, | ||
300 | .perm = AB5500_PERM_RW, | ||
301 | }, | ||
302 | { | ||
303 | .first = 0xB7, | ||
304 | .last = 0xBF, | ||
305 | .perm = AB5500_PERM_RW, | ||
306 | }, | ||
307 | { | ||
308 | .first = 0xC1, | ||
309 | .last = 0xCA, | ||
310 | .perm = AB5500_PERM_RW, | ||
311 | }, | ||
312 | { | ||
313 | .first = 0xD3, | ||
314 | .last = 0xE0, | ||
315 | .perm = AB5500_PERM_RW, | ||
316 | }, | ||
317 | }, | ||
318 | }, | ||
319 | { | ||
320 | .bankid = AB5500_BANK_SIM_USBSIM, | ||
321 | .nranges = 1, | ||
322 | .range = (struct ab5500_reg_range[]) { | ||
323 | { | ||
324 | .first = 0x13, | ||
325 | .last = 0x19, | ||
326 | .perm = AB5500_PERM_RW, | ||
327 | }, | ||
328 | }, | ||
329 | }, | ||
330 | }, | ||
331 | }, | ||
332 | [AB5500_DEVID_SIM] = { | ||
333 | .nbanks = 1, | ||
334 | .bank = (struct ab5500_i2c_ranges []) { | ||
335 | { | ||
336 | .bankid = AB5500_BANK_SIM_USBSIM, | ||
337 | .nranges = 1, | ||
338 | .range = (struct ab5500_reg_range[]) { | ||
339 | { | ||
340 | .first = 0x13, | ||
341 | .last = 0x19, | ||
342 | .perm = AB5500_PERM_RW, | ||
343 | }, | ||
344 | }, | ||
345 | }, | ||
346 | }, | ||
347 | }, | ||
348 | [AB5500_DEVID_RTC] = { | ||
349 | .nbanks = 1, | ||
350 | .bank = (struct ab5500_i2c_ranges []) { | ||
351 | { | ||
352 | .bankid = AB5500_BANK_RTC, | ||
353 | .nranges = 2, | ||
354 | .range = (struct ab5500_reg_range[]) { | ||
355 | { | ||
356 | .first = 0x00, | ||
357 | .last = 0x04, | ||
358 | .perm = AB5500_PERM_RW, | ||
359 | }, | ||
360 | { | ||
361 | .first = 0x06, | ||
362 | .last = 0x0C, | ||
363 | .perm = AB5500_PERM_RW, | ||
364 | }, | ||
365 | }, | ||
366 | }, | ||
367 | }, | ||
368 | }, | ||
369 | [AB5500_DEVID_CHARGER] = { | ||
370 | .nbanks = 1, | ||
371 | .bank = (struct ab5500_i2c_ranges []) { | ||
372 | { | ||
373 | .bankid = AB5500_BANK_CHG, | ||
374 | .nranges = 2, | ||
375 | .range = (struct ab5500_reg_range[]) { | ||
376 | { | ||
377 | .first = 0x11, | ||
378 | .last = 0x11, | ||
379 | .perm = AB5500_PERM_RO, | ||
380 | }, | ||
381 | { | ||
382 | .first = 0x12, | ||
383 | .last = 0x1B, | ||
384 | .perm = AB5500_PERM_RW, | ||
385 | }, | ||
386 | }, | ||
387 | }, | ||
388 | }, | ||
389 | }, | ||
390 | [AB5500_DEVID_FUELGAUGE] = { | ||
391 | .nbanks = 1, | ||
392 | .bank = (struct ab5500_i2c_ranges []) { | ||
393 | { | ||
394 | .bankid = AB5500_BANK_FG_BATTCOM_ACC, | ||
395 | .nranges = 2, | ||
396 | .range = (struct ab5500_reg_range[]) { | ||
397 | { | ||
398 | .first = 0x00, | ||
399 | .last = 0x0B, | ||
400 | .perm = AB5500_PERM_RO, | ||
401 | }, | ||
402 | { | ||
403 | .first = 0x0C, | ||
404 | .last = 0x10, | ||
405 | .perm = AB5500_PERM_RW, | ||
406 | }, | ||
407 | }, | ||
408 | }, | ||
409 | }, | ||
410 | }, | ||
411 | [AB5500_DEVID_VIBRATOR] = { | ||
412 | .nbanks = 1, | ||
413 | .bank = (struct ab5500_i2c_ranges []) { | ||
414 | { | ||
415 | .bankid = AB5500_BANK_VIBRA, | ||
416 | .nranges = 2, | ||
417 | .range = (struct ab5500_reg_range[]) { | ||
418 | { | ||
419 | .first = 0x10, | ||
420 | .last = 0x13, | ||
421 | .perm = AB5500_PERM_RW, | ||
422 | }, | ||
423 | { | ||
424 | .first = 0xFE, | ||
425 | .last = 0xFE, | ||
426 | .perm = AB5500_PERM_RW, | ||
427 | }, | ||
428 | }, | ||
429 | }, | ||
430 | }, | ||
431 | }, | ||
432 | [AB5500_DEVID_CODEC] = { | ||
433 | .nbanks = 1, | ||
434 | .bank = (struct ab5500_i2c_ranges []) { | ||
435 | { | ||
436 | .bankid = AB5500_BANK_AUDIO_HEADSETUSB, | ||
437 | .nranges = 2, | ||
438 | .range = (struct ab5500_reg_range[]) { | ||
439 | { | ||
440 | .first = 0x00, | ||
441 | .last = 0x48, | ||
442 | .perm = AB5500_PERM_RW, | ||
443 | }, | ||
444 | { | ||
445 | .first = 0xEB, | ||
446 | .last = 0xFB, | ||
447 | .perm = AB5500_PERM_RW, | ||
448 | }, | ||
449 | }, | ||
450 | }, | ||
451 | }, | ||
452 | }, | ||
453 | [AB5500_DEVID_POWER] = { | ||
454 | .nbanks = 2, | ||
455 | .bank = (struct ab5500_i2c_ranges []) { | ||
456 | { | ||
457 | .bankid = AB5500_BANK_STARTUP, | ||
458 | .nranges = 1, | ||
459 | .range = (struct ab5500_reg_range[]) { | ||
460 | { | ||
461 | .first = 0x30, | ||
462 | .last = 0x30, | ||
463 | .perm = AB5500_PERM_RW, | ||
464 | }, | ||
465 | }, | ||
466 | }, | ||
467 | { | ||
468 | .bankid = AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP, | ||
469 | .nranges = 1, | ||
470 | .range = (struct ab5500_reg_range[]) { | ||
471 | { | ||
472 | .first = 0x01, | ||
473 | .last = 0x01, | ||
474 | .perm = AB5500_PERM_RW, | ||
475 | }, | ||
476 | }, | ||
477 | }, | ||
478 | }, | ||
479 | }, | ||
480 | }; | ||
481 | |||
482 | #define AB5500_IRQ(bank, bit) ((bank) * 8 + (bit)) | ||
483 | |||
484 | /* I appologize for the resource names beeing a mix of upper case | ||
485 | * and lower case but I want them to be exact as the documentation */ | ||
486 | static struct mfd_cell ab5500_devs[AB5500_NUM_DEVICES] = { | ||
487 | [AB5500_DEVID_LEDS] = { | ||
488 | .name = "ab5500-leds", | ||
489 | .id = AB5500_DEVID_LEDS, | ||
490 | }, | ||
491 | [AB5500_DEVID_POWER] = { | ||
492 | .name = "ab5500-power", | ||
493 | .id = AB5500_DEVID_POWER, | ||
494 | }, | ||
495 | [AB5500_DEVID_REGULATORS] = { | ||
496 | .name = "ab5500-regulator", | ||
497 | .id = AB5500_DEVID_REGULATORS, | ||
498 | }, | ||
499 | [AB5500_DEVID_SIM] = { | ||
500 | .name = "ab5500-sim", | ||
501 | .id = AB5500_DEVID_SIM, | ||
502 | .num_resources = 1, | ||
503 | .resources = (struct resource[]) { | ||
504 | { | ||
505 | .name = "SIMOFF", | ||
506 | .flags = IORESOURCE_IRQ, | ||
507 | .start = AB5500_IRQ(2, 0), /*rising*/ | ||
508 | .end = AB5500_IRQ(2, 1), /*falling*/ | ||
509 | }, | ||
510 | }, | ||
511 | }, | ||
512 | [AB5500_DEVID_RTC] = { | ||
513 | .name = "ab5500-rtc", | ||
514 | .id = AB5500_DEVID_RTC, | ||
515 | .num_resources = 1, | ||
516 | .resources = (struct resource[]) { | ||
517 | { | ||
518 | .name = "RTC_Alarm", | ||
519 | .flags = IORESOURCE_IRQ, | ||
520 | .start = AB5500_IRQ(1, 7), | ||
521 | .end = AB5500_IRQ(1, 7), | ||
522 | } | ||
523 | }, | ||
524 | }, | ||
525 | [AB5500_DEVID_CHARGER] = { | ||
526 | .name = "ab5500-charger", | ||
527 | .id = AB5500_DEVID_CHARGER, | ||
528 | }, | ||
529 | [AB5500_DEVID_ADC] = { | ||
530 | .name = "ab5500-adc", | ||
531 | .id = AB5500_DEVID_ADC, | ||
532 | .num_resources = 10, | ||
533 | .resources = (struct resource[]) { | ||
534 | { | ||
535 | .name = "TRIGGER-0", | ||
536 | .flags = IORESOURCE_IRQ, | ||
537 | .start = AB5500_IRQ(0, 0), | ||
538 | .end = AB5500_IRQ(0, 0), | ||
539 | }, | ||
540 | { | ||
541 | .name = "TRIGGER-1", | ||
542 | .flags = IORESOURCE_IRQ, | ||
543 | .start = AB5500_IRQ(0, 1), | ||
544 | .end = AB5500_IRQ(0, 1), | ||
545 | }, | ||
546 | { | ||
547 | .name = "TRIGGER-2", | ||
548 | .flags = IORESOURCE_IRQ, | ||
549 | .start = AB5500_IRQ(0, 2), | ||
550 | .end = AB5500_IRQ(0, 2), | ||
551 | }, | ||
552 | { | ||
553 | .name = "TRIGGER-3", | ||
554 | .flags = IORESOURCE_IRQ, | ||
555 | .start = AB5500_IRQ(0, 3), | ||
556 | .end = AB5500_IRQ(0, 3), | ||
557 | }, | ||
558 | { | ||
559 | .name = "TRIGGER-4", | ||
560 | .flags = IORESOURCE_IRQ, | ||
561 | .start = AB5500_IRQ(0, 4), | ||
562 | .end = AB5500_IRQ(0, 4), | ||
563 | }, | ||
564 | { | ||
565 | .name = "TRIGGER-5", | ||
566 | .flags = IORESOURCE_IRQ, | ||
567 | .start = AB5500_IRQ(0, 5), | ||
568 | .end = AB5500_IRQ(0, 5), | ||
569 | }, | ||
570 | { | ||
571 | .name = "TRIGGER-6", | ||
572 | .flags = IORESOURCE_IRQ, | ||
573 | .start = AB5500_IRQ(0, 6), | ||
574 | .end = AB5500_IRQ(0, 6), | ||
575 | }, | ||
576 | { | ||
577 | .name = "TRIGGER-7", | ||
578 | .flags = IORESOURCE_IRQ, | ||
579 | .start = AB5500_IRQ(0, 7), | ||
580 | .end = AB5500_IRQ(0, 7), | ||
581 | }, | ||
582 | { | ||
583 | .name = "TRIGGER-VBAT", | ||
584 | .flags = IORESOURCE_IRQ, | ||
585 | .start = AB5500_IRQ(0, 8), | ||
586 | .end = AB5500_IRQ(0, 8), | ||
587 | }, | ||
588 | { | ||
589 | .name = "TRIGGER-VBAT-TXON", | ||
590 | .flags = IORESOURCE_IRQ, | ||
591 | .start = AB5500_IRQ(0, 9), | ||
592 | .end = AB5500_IRQ(0, 9), | ||
593 | }, | ||
594 | }, | ||
595 | }, | ||
596 | [AB5500_DEVID_FUELGAUGE] = { | ||
597 | .name = "ab5500-fuelgauge", | ||
598 | .id = AB5500_DEVID_FUELGAUGE, | ||
599 | .num_resources = 6, | ||
600 | .resources = (struct resource[]) { | ||
601 | { | ||
602 | .name = "Batt_attach", | ||
603 | .flags = IORESOURCE_IRQ, | ||
604 | .start = AB5500_IRQ(7, 5), | ||
605 | .end = AB5500_IRQ(7, 5), | ||
606 | }, | ||
607 | { | ||
608 | .name = "Batt_removal", | ||
609 | .flags = IORESOURCE_IRQ, | ||
610 | .start = AB5500_IRQ(7, 6), | ||
611 | .end = AB5500_IRQ(7, 6), | ||
612 | }, | ||
613 | { | ||
614 | .name = "UART_framing", | ||
615 | .flags = IORESOURCE_IRQ, | ||
616 | .start = AB5500_IRQ(7, 7), | ||
617 | .end = AB5500_IRQ(7, 7), | ||
618 | }, | ||
619 | { | ||
620 | .name = "UART_overrun", | ||
621 | .flags = IORESOURCE_IRQ, | ||
622 | .start = AB5500_IRQ(8, 0), | ||
623 | .end = AB5500_IRQ(8, 0), | ||
624 | }, | ||
625 | { | ||
626 | .name = "UART_Rdy_RX", | ||
627 | .flags = IORESOURCE_IRQ, | ||
628 | .start = AB5500_IRQ(8, 1), | ||
629 | .end = AB5500_IRQ(8, 1), | ||
630 | }, | ||
631 | { | ||
632 | .name = "UART_Rdy_TX", | ||
633 | .flags = IORESOURCE_IRQ, | ||
634 | .start = AB5500_IRQ(8, 2), | ||
635 | .end = AB5500_IRQ(8, 2), | ||
636 | }, | ||
637 | }, | ||
638 | }, | ||
639 | [AB5500_DEVID_VIBRATOR] = { | ||
640 | .name = "ab5500-vibrator", | ||
641 | .id = AB5500_DEVID_VIBRATOR, | ||
642 | }, | ||
643 | [AB5500_DEVID_CODEC] = { | ||
644 | .name = "ab5500-codec", | ||
645 | .id = AB5500_DEVID_CODEC, | ||
646 | .num_resources = 3, | ||
647 | .resources = (struct resource[]) { | ||
648 | { | ||
649 | .name = "audio_spkr1_ovc", | ||
650 | .flags = IORESOURCE_IRQ, | ||
651 | .start = AB5500_IRQ(9, 5), | ||
652 | .end = AB5500_IRQ(9, 5), | ||
653 | }, | ||
654 | { | ||
655 | .name = "audio_plllocked", | ||
656 | .flags = IORESOURCE_IRQ, | ||
657 | .start = AB5500_IRQ(9, 6), | ||
658 | .end = AB5500_IRQ(9, 6), | ||
659 | }, | ||
660 | { | ||
661 | .name = "audio_spkr2_ovc", | ||
662 | .flags = IORESOURCE_IRQ, | ||
663 | .start = AB5500_IRQ(17, 4), | ||
664 | .end = AB5500_IRQ(17, 4), | ||
665 | }, | ||
666 | }, | ||
667 | }, | ||
668 | [AB5500_DEVID_USB] = { | ||
669 | .name = "ab5500-usb", | ||
670 | .id = AB5500_DEVID_USB, | ||
671 | .num_resources = 36, | ||
672 | .resources = (struct resource[]) { | ||
673 | { | ||
674 | .name = "Link_Update", | ||
675 | .flags = IORESOURCE_IRQ, | ||
676 | .start = AB5500_IRQ(22, 1), | ||
677 | .end = AB5500_IRQ(22, 1), | ||
678 | }, | ||
679 | { | ||
680 | .name = "DCIO", | ||
681 | .flags = IORESOURCE_IRQ, | ||
682 | .start = AB5500_IRQ(8, 3), | ||
683 | .end = AB5500_IRQ(8, 4), | ||
684 | }, | ||
685 | { | ||
686 | .name = "VBUS_R", | ||
687 | .flags = IORESOURCE_IRQ, | ||
688 | .start = AB5500_IRQ(8, 5), | ||
689 | .end = AB5500_IRQ(8, 5), | ||
690 | }, | ||
691 | { | ||
692 | .name = "VBUS_F", | ||
693 | .flags = IORESOURCE_IRQ, | ||
694 | .start = AB5500_IRQ(8, 6), | ||
695 | .end = AB5500_IRQ(8, 6), | ||
696 | }, | ||
697 | { | ||
698 | .name = "CHGstate_10_PCVBUSchg", | ||
699 | .flags = IORESOURCE_IRQ, | ||
700 | .start = AB5500_IRQ(8, 7), | ||
701 | .end = AB5500_IRQ(8, 7), | ||
702 | }, | ||
703 | { | ||
704 | .name = "DCIOreverse_ovc", | ||
705 | .flags = IORESOURCE_IRQ, | ||
706 | .start = AB5500_IRQ(9, 0), | ||
707 | .end = AB5500_IRQ(9, 0), | ||
708 | }, | ||
709 | { | ||
710 | .name = "USBCharDetDone", | ||
711 | .flags = IORESOURCE_IRQ, | ||
712 | .start = AB5500_IRQ(9, 1), | ||
713 | .end = AB5500_IRQ(9, 1), | ||
714 | }, | ||
715 | { | ||
716 | .name = "DCIO_no_limit", | ||
717 | .flags = IORESOURCE_IRQ, | ||
718 | .start = AB5500_IRQ(9, 2), | ||
719 | .end = AB5500_IRQ(9, 2), | ||
720 | }, | ||
721 | { | ||
722 | .name = "USB_suspend", | ||
723 | .flags = IORESOURCE_IRQ, | ||
724 | .start = AB5500_IRQ(9, 3), | ||
725 | .end = AB5500_IRQ(9, 3), | ||
726 | }, | ||
727 | { | ||
728 | .name = "DCIOreverse_fwdcurrent", | ||
729 | .flags = IORESOURCE_IRQ, | ||
730 | .start = AB5500_IRQ(9, 4), | ||
731 | .end = AB5500_IRQ(9, 4), | ||
732 | }, | ||
733 | { | ||
734 | .name = "Vbus_Imeasmax_change", | ||
735 | .flags = IORESOURCE_IRQ, | ||
736 | .start = AB5500_IRQ(9, 5), | ||
737 | .end = AB5500_IRQ(9, 6), | ||
738 | }, | ||
739 | { | ||
740 | .name = "OVV", | ||
741 | .flags = IORESOURCE_IRQ, | ||
742 | .start = AB5500_IRQ(14, 5), | ||
743 | .end = AB5500_IRQ(14, 5), | ||
744 | }, | ||
745 | { | ||
746 | .name = "USBcharging_NOTok", | ||
747 | .flags = IORESOURCE_IRQ, | ||
748 | .start = AB5500_IRQ(15, 3), | ||
749 | .end = AB5500_IRQ(15, 3), | ||
750 | }, | ||
751 | { | ||
752 | .name = "usb_adp_sensoroff", | ||
753 | .flags = IORESOURCE_IRQ, | ||
754 | .start = AB5500_IRQ(15, 6), | ||
755 | .end = AB5500_IRQ(15, 6), | ||
756 | }, | ||
757 | { | ||
758 | .name = "usb_adp_probeplug", | ||
759 | .flags = IORESOURCE_IRQ, | ||
760 | .start = AB5500_IRQ(15, 7), | ||
761 | .end = AB5500_IRQ(15, 7), | ||
762 | }, | ||
763 | { | ||
764 | .name = "usb_adp_sinkerror", | ||
765 | .flags = IORESOURCE_IRQ, | ||
766 | .start = AB5500_IRQ(16, 0), | ||
767 | .end = AB5500_IRQ(16, 6), | ||
768 | }, | ||
769 | { | ||
770 | .name = "usb_adp_sourceerror", | ||
771 | .flags = IORESOURCE_IRQ, | ||
772 | .start = AB5500_IRQ(16, 1), | ||
773 | .end = AB5500_IRQ(16, 1), | ||
774 | }, | ||
775 | { | ||
776 | .name = "usb_idgnd_r", | ||
777 | .flags = IORESOURCE_IRQ, | ||
778 | .start = AB5500_IRQ(16, 2), | ||
779 | .end = AB5500_IRQ(16, 2), | ||
780 | }, | ||
781 | { | ||
782 | .name = "usb_idgnd_f", | ||
783 | .flags = IORESOURCE_IRQ, | ||
784 | .start = AB5500_IRQ(16, 3), | ||
785 | .end = AB5500_IRQ(16, 3), | ||
786 | }, | ||
787 | { | ||
788 | .name = "usb_iddetR1", | ||
789 | .flags = IORESOURCE_IRQ, | ||
790 | .start = AB5500_IRQ(16, 4), | ||
791 | .end = AB5500_IRQ(16, 5), | ||
792 | }, | ||
793 | { | ||
794 | .name = "usb_iddetR2", | ||
795 | .flags = IORESOURCE_IRQ, | ||
796 | .start = AB5500_IRQ(16, 6), | ||
797 | .end = AB5500_IRQ(16, 7), | ||
798 | }, | ||
799 | { | ||
800 | .name = "usb_iddetR3", | ||
801 | .flags = IORESOURCE_IRQ, | ||
802 | .start = AB5500_IRQ(17, 0), | ||
803 | .end = AB5500_IRQ(17, 1), | ||
804 | }, | ||
805 | { | ||
806 | .name = "usb_iddetR4", | ||
807 | .flags = IORESOURCE_IRQ, | ||
808 | .start = AB5500_IRQ(17, 2), | ||
809 | .end = AB5500_IRQ(17, 3), | ||
810 | }, | ||
811 | { | ||
812 | .name = "CharTempWindowOk", | ||
813 | .flags = IORESOURCE_IRQ, | ||
814 | .start = AB5500_IRQ(17, 7), | ||
815 | .end = AB5500_IRQ(18, 0), | ||
816 | }, | ||
817 | { | ||
818 | .name = "USB_SprDetect", | ||
819 | .flags = IORESOURCE_IRQ, | ||
820 | .start = AB5500_IRQ(18, 1), | ||
821 | .end = AB5500_IRQ(18, 1), | ||
822 | }, | ||
823 | { | ||
824 | .name = "usb_adp_probe_unplug", | ||
825 | .flags = IORESOURCE_IRQ, | ||
826 | .start = AB5500_IRQ(18, 2), | ||
827 | .end = AB5500_IRQ(18, 2), | ||
828 | }, | ||
829 | { | ||
830 | .name = "VBUSChDrop", | ||
831 | .flags = IORESOURCE_IRQ, | ||
832 | .start = AB5500_IRQ(18, 3), | ||
833 | .end = AB5500_IRQ(18, 4), | ||
834 | }, | ||
835 | { | ||
836 | .name = "dcio_char_rec_done", | ||
837 | .flags = IORESOURCE_IRQ, | ||
838 | .start = AB5500_IRQ(18, 5), | ||
839 | .end = AB5500_IRQ(18, 5), | ||
840 | }, | ||
841 | { | ||
842 | .name = "Charging_stopped_by_temp", | ||
843 | .flags = IORESOURCE_IRQ, | ||
844 | .start = AB5500_IRQ(18, 6), | ||
845 | .end = AB5500_IRQ(18, 6), | ||
846 | }, | ||
847 | { | ||
848 | .name = "CHGstate_11_SafeModeVBUS", | ||
849 | .flags = IORESOURCE_IRQ, | ||
850 | .start = AB5500_IRQ(21, 1), | ||
851 | .end = AB5500_IRQ(21, 2), | ||
852 | }, | ||
853 | { | ||
854 | .name = "CHGstate_12_comletedVBUS", | ||
855 | .flags = IORESOURCE_IRQ, | ||
856 | .start = AB5500_IRQ(21, 2), | ||
857 | .end = AB5500_IRQ(21, 2), | ||
858 | }, | ||
859 | { | ||
860 | .name = "CHGstate_13_completedVBUS", | ||
861 | .flags = IORESOURCE_IRQ, | ||
862 | .start = AB5500_IRQ(21, 3), | ||
863 | .end = AB5500_IRQ(21, 3), | ||
864 | }, | ||
865 | { | ||
866 | .name = "CHGstate_14_FullChgDCIO", | ||
867 | .flags = IORESOURCE_IRQ, | ||
868 | .start = AB5500_IRQ(21, 4), | ||
869 | .end = AB5500_IRQ(21, 4), | ||
870 | }, | ||
871 | { | ||
872 | .name = "CHGstate_15_SafeModeDCIO", | ||
873 | .flags = IORESOURCE_IRQ, | ||
874 | .start = AB5500_IRQ(21, 5), | ||
875 | .end = AB5500_IRQ(21, 5), | ||
876 | }, | ||
877 | { | ||
878 | .name = "CHGstate_16_OFFsuspendDCIO", | ||
879 | .flags = IORESOURCE_IRQ, | ||
880 | .start = AB5500_IRQ(21, 6), | ||
881 | .end = AB5500_IRQ(21, 6), | ||
882 | }, | ||
883 | { | ||
884 | .name = "CHGstate_17_completedDCIO", | ||
885 | .flags = IORESOURCE_IRQ, | ||
886 | .start = AB5500_IRQ(21, 7), | ||
887 | .end = AB5500_IRQ(21, 7), | ||
888 | }, | ||
889 | }, | ||
890 | }, | ||
891 | [AB5500_DEVID_OTP] = { | ||
892 | .name = "ab5500-otp", | ||
893 | .id = AB5500_DEVID_OTP, | ||
894 | }, | ||
895 | [AB5500_DEVID_VIDEO] = { | ||
896 | .name = "ab5500-video", | ||
897 | .id = AB5500_DEVID_VIDEO, | ||
898 | .num_resources = 1, | ||
899 | .resources = (struct resource[]) { | ||
900 | { | ||
901 | .name = "plugTVdet", | ||
902 | .flags = IORESOURCE_IRQ, | ||
903 | .start = AB5500_IRQ(22, 2), | ||
904 | .end = AB5500_IRQ(22, 2), | ||
905 | }, | ||
906 | }, | ||
907 | }, | ||
908 | [AB5500_DEVID_DBIECI] = { | ||
909 | .name = "ab5500-dbieci", | ||
910 | .id = AB5500_DEVID_DBIECI, | ||
911 | .num_resources = 10, | ||
912 | .resources = (struct resource[]) { | ||
913 | { | ||
914 | .name = "COLL", | ||
915 | .flags = IORESOURCE_IRQ, | ||
916 | .start = AB5500_IRQ(14, 0), | ||
917 | .end = AB5500_IRQ(14, 0), | ||
918 | }, | ||
919 | { | ||
920 | .name = "RESERR", | ||
921 | .flags = IORESOURCE_IRQ, | ||
922 | .start = AB5500_IRQ(14, 1), | ||
923 | .end = AB5500_IRQ(14, 1), | ||
924 | }, | ||
925 | { | ||
926 | .name = "FRAERR", | ||
927 | .flags = IORESOURCE_IRQ, | ||
928 | .start = AB5500_IRQ(14, 2), | ||
929 | .end = AB5500_IRQ(14, 2), | ||
930 | }, | ||
931 | { | ||
932 | .name = "COMERR", | ||
933 | .flags = IORESOURCE_IRQ, | ||
934 | .start = AB5500_IRQ(14, 3), | ||
935 | .end = AB5500_IRQ(14, 3), | ||
936 | }, | ||
937 | { | ||
938 | .name = "BSI_indicator", | ||
939 | .flags = IORESOURCE_IRQ, | ||
940 | .start = AB5500_IRQ(14, 4), | ||
941 | .end = AB5500_IRQ(14, 4), | ||
942 | }, | ||
943 | { | ||
944 | .name = "SPDSET", | ||
945 | .flags = IORESOURCE_IRQ, | ||
946 | .start = AB5500_IRQ(14, 6), | ||
947 | .end = AB5500_IRQ(14, 6), | ||
948 | }, | ||
949 | { | ||
950 | .name = "DSENT", | ||
951 | .flags = IORESOURCE_IRQ, | ||
952 | .start = AB5500_IRQ(14, 7), | ||
953 | .end = AB5500_IRQ(14, 7), | ||
954 | }, | ||
955 | { | ||
956 | .name = "DREC", | ||
957 | .flags = IORESOURCE_IRQ, | ||
958 | .start = AB5500_IRQ(15, 0), | ||
959 | .end = AB5500_IRQ(15, 0), | ||
960 | }, | ||
961 | { | ||
962 | .name = "ACCINT", | ||
963 | .flags = IORESOURCE_IRQ, | ||
964 | .start = AB5500_IRQ(15, 1), | ||
965 | .end = AB5500_IRQ(15, 1), | ||
966 | }, | ||
967 | { | ||
968 | .name = "NOPINT", | ||
969 | .flags = IORESOURCE_IRQ, | ||
970 | .start = AB5500_IRQ(15, 2), | ||
971 | .end = AB5500_IRQ(15, 2), | ||
972 | }, | ||
973 | }, | ||
974 | }, | ||
975 | [AB5500_DEVID_ONSWA] = { | ||
976 | .name = "ab5500-onswa", | ||
977 | .id = AB5500_DEVID_ONSWA, | ||
978 | .num_resources = 2, | ||
979 | .resources = (struct resource[]) { | ||
980 | { | ||
981 | .name = "ONSWAn_rising", | ||
982 | .flags = IORESOURCE_IRQ, | ||
983 | .start = AB5500_IRQ(1, 3), | ||
984 | .end = AB5500_IRQ(1, 3), | ||
985 | }, | ||
986 | { | ||
987 | .name = "ONSWAn_falling", | ||
988 | .flags = IORESOURCE_IRQ, | ||
989 | .start = AB5500_IRQ(1, 4), | ||
990 | .end = AB5500_IRQ(1, 4), | ||
991 | }, | ||
992 | }, | ||
993 | }, | ||
994 | }; | ||
995 | |||
996 | /* | ||
997 | * Functionality for getting/setting register values. | ||
998 | */ | ||
999 | int ab5500_get_register_interruptible_raw(struct ab5500 *ab, | ||
1000 | u8 bank, u8 reg, | ||
1001 | u8 *value) | ||
1002 | { | ||
1003 | int err; | ||
1004 | |||
1005 | if (bank >= AB5500_NUM_BANKS) | ||
1006 | return -EINVAL; | ||
1007 | |||
1008 | err = mutex_lock_interruptible(&ab->access_mutex); | ||
1009 | if (err) | ||
1010 | return err; | ||
1011 | err = db5500_prcmu_abb_read(bankinfo[bank].slave_addr, reg, value, 1); | ||
1012 | |||
1013 | mutex_unlock(&ab->access_mutex); | ||
1014 | return err; | ||
1015 | } | ||
1016 | |||
1017 | static int get_register_page_interruptible(struct ab5500 *ab, u8 bank, | ||
1018 | u8 first_reg, u8 *regvals, u8 numregs) | ||
1019 | { | ||
1020 | int err; | ||
1021 | |||
1022 | if (bank >= AB5500_NUM_BANKS) | ||
1023 | return -EINVAL; | ||
1024 | |||
1025 | err = mutex_lock_interruptible(&ab->access_mutex); | ||
1026 | if (err) | ||
1027 | return err; | ||
1028 | |||
1029 | while (numregs) { | ||
1030 | /* The hardware limit for get page is 4 */ | ||
1031 | u8 curnum = min_t(u8, numregs, 4u); | ||
1032 | |||
1033 | err = db5500_prcmu_abb_read(bankinfo[bank].slave_addr, | ||
1034 | first_reg, regvals, curnum); | ||
1035 | if (err) | ||
1036 | goto out; | ||
1037 | |||
1038 | numregs -= curnum; | ||
1039 | first_reg += curnum; | ||
1040 | regvals += curnum; | ||
1041 | } | ||
1042 | |||
1043 | out: | ||
1044 | mutex_unlock(&ab->access_mutex); | ||
1045 | return err; | ||
1046 | } | ||
1047 | |||
1048 | int ab5500_mask_and_set_register_interruptible_raw(struct ab5500 *ab, u8 bank, | ||
1049 | u8 reg, u8 bitmask, u8 bitvalues) | ||
1050 | { | ||
1051 | int err = 0; | ||
1052 | |||
1053 | if (bank >= AB5500_NUM_BANKS) | ||
1054 | return -EINVAL; | ||
1055 | |||
1056 | if (bitmask) { | ||
1057 | u8 buf; | ||
1058 | |||
1059 | err = mutex_lock_interruptible(&ab->access_mutex); | ||
1060 | if (err) | ||
1061 | return err; | ||
1062 | |||
1063 | if (bitmask == 0xFF) /* No need to read in this case. */ | ||
1064 | buf = bitvalues; | ||
1065 | else { /* Read and modify the register value. */ | ||
1066 | err = db5500_prcmu_abb_read(bankinfo[bank].slave_addr, | ||
1067 | reg, &buf, 1); | ||
1068 | if (err) | ||
1069 | return err; | ||
1070 | |||
1071 | buf = ((~bitmask & buf) | (bitmask & bitvalues)); | ||
1072 | } | ||
1073 | /* Write the new value. */ | ||
1074 | err = db5500_prcmu_abb_write(bankinfo[bank].slave_addr, reg, | ||
1075 | &buf, 1); | ||
1076 | |||
1077 | mutex_unlock(&ab->access_mutex); | ||
1078 | } | ||
1079 | return err; | ||
1080 | } | ||
1081 | |||
1082 | static int | ||
1083 | set_register_interruptible(struct ab5500 *ab, u8 bank, u8 reg, u8 value) | ||
1084 | { | ||
1085 | return ab5500_mask_and_set_register_interruptible_raw(ab, bank, reg, | ||
1086 | 0xff, value); | ||
1087 | } | ||
1088 | |||
1089 | /* | ||
1090 | * Read/write permission checking functions. | ||
1091 | */ | ||
1092 | static const struct ab5500_i2c_ranges *get_bankref(u8 devid, u8 bank) | ||
1093 | { | ||
1094 | u8 i; | ||
1095 | |||
1096 | if (devid < AB5500_NUM_DEVICES) { | ||
1097 | for (i = 0; i < ab5500_bank_ranges[devid].nbanks; i++) { | ||
1098 | if (ab5500_bank_ranges[devid].bank[i].bankid == bank) | ||
1099 | return &ab5500_bank_ranges[devid].bank[i]; | ||
1100 | } | ||
1101 | } | ||
1102 | return NULL; | ||
1103 | } | ||
1104 | |||
1105 | static bool page_write_allowed(u8 devid, u8 bank, u8 first_reg, u8 last_reg) | ||
1106 | { | ||
1107 | u8 i; /* range loop index */ | ||
1108 | const struct ab5500_i2c_ranges *bankref; | ||
1109 | |||
1110 | bankref = get_bankref(devid, bank); | ||
1111 | if (bankref == NULL || last_reg < first_reg) | ||
1112 | return false; | ||
1113 | |||
1114 | for (i = 0; i < bankref->nranges; i++) { | ||
1115 | if (first_reg < bankref->range[i].first) | ||
1116 | break; | ||
1117 | if ((last_reg <= bankref->range[i].last) && | ||
1118 | (bankref->range[i].perm & AB5500_PERM_WR)) | ||
1119 | return true; | ||
1120 | } | ||
1121 | return false; | ||
1122 | } | ||
1123 | |||
1124 | static bool reg_write_allowed(u8 devid, u8 bank, u8 reg) | ||
1125 | { | ||
1126 | return page_write_allowed(devid, bank, reg, reg); | ||
1127 | } | ||
1128 | |||
1129 | static bool page_read_allowed(u8 devid, u8 bank, u8 first_reg, u8 last_reg) | ||
1130 | { | ||
1131 | u8 i; | ||
1132 | const struct ab5500_i2c_ranges *bankref; | ||
1133 | |||
1134 | bankref = get_bankref(devid, bank); | ||
1135 | if (bankref == NULL || last_reg < first_reg) | ||
1136 | return false; | ||
1137 | |||
1138 | |||
1139 | /* Find the range (if it exists in the list) that includes first_reg. */ | ||
1140 | for (i = 0; i < bankref->nranges; i++) { | ||
1141 | if (first_reg < bankref->range[i].first) | ||
1142 | return false; | ||
1143 | if (first_reg <= bankref->range[i].last) | ||
1144 | break; | ||
1145 | } | ||
1146 | /* Make sure that the entire range up to and including last_reg is | ||
1147 | * readable. This may span several of the ranges in the list. | ||
1148 | */ | ||
1149 | while ((i < bankref->nranges) && | ||
1150 | (bankref->range[i].perm & AB5500_PERM_RD)) { | ||
1151 | if (last_reg <= bankref->range[i].last) | ||
1152 | return true; | ||
1153 | if ((++i >= bankref->nranges) || | ||
1154 | (bankref->range[i].first != | ||
1155 | (bankref->range[i - 1].last + 1))) { | ||
1156 | break; | ||
1157 | } | ||
1158 | } | ||
1159 | return false; | ||
1160 | } | ||
1161 | |||
1162 | static bool reg_read_allowed(u8 devid, u8 bank, u8 reg) | ||
1163 | { | ||
1164 | return page_read_allowed(devid, bank, reg, reg); | ||
1165 | } | ||
1166 | |||
1167 | |||
1168 | /* | ||
1169 | * The exported register access functionality. | ||
1170 | */ | ||
1171 | static int ab5500_get_chip_id(struct device *dev) | ||
1172 | { | ||
1173 | struct ab5500 *ab = dev_get_drvdata(dev->parent); | ||
1174 | |||
1175 | return (int)ab->chip_id; | ||
1176 | } | ||
1177 | |||
1178 | static int ab5500_mask_and_set_register_interruptible(struct device *dev, | ||
1179 | u8 bank, u8 reg, u8 bitmask, u8 bitvalues) | ||
1180 | { | ||
1181 | struct ab5500 *ab; | ||
1182 | struct platform_device *pdev = to_platform_device(dev); | ||
1183 | |||
1184 | if ((AB5500_NUM_BANKS <= bank) || | ||
1185 | !reg_write_allowed(pdev->id, bank, reg)) | ||
1186 | return -EINVAL; | ||
1187 | |||
1188 | ab = dev_get_drvdata(dev->parent); | ||
1189 | return ab5500_mask_and_set_register_interruptible_raw(ab, bank, reg, | ||
1190 | bitmask, bitvalues); | ||
1191 | } | ||
1192 | |||
1193 | static int ab5500_set_register_interruptible(struct device *dev, u8 bank, | ||
1194 | u8 reg, u8 value) | ||
1195 | { | ||
1196 | return ab5500_mask_and_set_register_interruptible(dev, bank, reg, 0xFF, | ||
1197 | value); | ||
1198 | } | ||
1199 | |||
1200 | static int ab5500_get_register_interruptible(struct device *dev, u8 bank, | ||
1201 | u8 reg, u8 *value) | ||
1202 | { | ||
1203 | struct ab5500 *ab; | ||
1204 | struct platform_device *pdev = to_platform_device(dev); | ||
1205 | |||
1206 | if ((AB5500_NUM_BANKS <= bank) || | ||
1207 | !reg_read_allowed(pdev->id, bank, reg)) | ||
1208 | return -EINVAL; | ||
1209 | |||
1210 | ab = dev_get_drvdata(dev->parent); | ||
1211 | return ab5500_get_register_interruptible_raw(ab, bank, reg, value); | ||
1212 | } | ||
1213 | |||
1214 | static int ab5500_get_register_page_interruptible(struct device *dev, u8 bank, | ||
1215 | u8 first_reg, u8 *regvals, u8 numregs) | ||
1216 | { | ||
1217 | struct ab5500 *ab; | ||
1218 | struct platform_device *pdev = to_platform_device(dev); | ||
1219 | |||
1220 | if ((AB5500_NUM_BANKS <= bank) || | ||
1221 | !page_read_allowed(pdev->id, bank, | ||
1222 | first_reg, (first_reg + numregs - 1))) | ||
1223 | return -EINVAL; | ||
1224 | |||
1225 | ab = dev_get_drvdata(dev->parent); | ||
1226 | return get_register_page_interruptible(ab, bank, first_reg, regvals, | ||
1227 | numregs); | ||
1228 | } | ||
1229 | |||
1230 | static int | ||
1231 | ab5500_event_registers_startup_state_get(struct device *dev, u8 *event) | ||
1232 | { | ||
1233 | struct ab5500 *ab; | ||
1234 | |||
1235 | ab = dev_get_drvdata(dev->parent); | ||
1236 | if (!ab->startup_events_read) | ||
1237 | return -EAGAIN; /* Try again later */ | ||
1238 | |||
1239 | memcpy(event, ab->startup_events, AB5500_NUM_EVENT_REG); | ||
1240 | return 0; | ||
1241 | } | ||
1242 | |||
1243 | static struct abx500_ops ab5500_ops = { | ||
1244 | .get_chip_id = ab5500_get_chip_id, | ||
1245 | .get_register = ab5500_get_register_interruptible, | ||
1246 | .set_register = ab5500_set_register_interruptible, | ||
1247 | .get_register_page = ab5500_get_register_page_interruptible, | ||
1248 | .set_register_page = NULL, | ||
1249 | .mask_and_set_register = ab5500_mask_and_set_register_interruptible, | ||
1250 | .event_registers_startup_state_get = | ||
1251 | ab5500_event_registers_startup_state_get, | ||
1252 | .startup_irq_enabled = NULL, | ||
1253 | }; | ||
1254 | |||
1255 | /* | ||
1256 | * ab5500_setup : Basic set-up, datastructure creation/destruction | ||
1257 | * and I2C interface.This sets up a default config | ||
1258 | * in the AB5500 chip so that it will work as expected. | ||
1259 | * @ab : Pointer to ab5500 structure | ||
1260 | * @settings : Pointer to struct abx500_init_settings | ||
1261 | * @size : Size of init data | ||
1262 | */ | ||
1263 | static int __init ab5500_setup(struct ab5500 *ab, | ||
1264 | struct abx500_init_settings *settings, unsigned int size) | ||
1265 | { | ||
1266 | int err = 0; | ||
1267 | int i; | ||
1268 | |||
1269 | for (i = 0; i < size; i++) { | ||
1270 | err = ab5500_mask_and_set_register_interruptible_raw(ab, | ||
1271 | settings[i].bank, | ||
1272 | settings[i].reg, | ||
1273 | 0xFF, settings[i].setting); | ||
1274 | if (err) | ||
1275 | goto exit_no_setup; | ||
1276 | |||
1277 | /* If event mask register update the event mask in ab5500 */ | ||
1278 | if ((settings[i].bank == AB5500_BANK_IT) && | ||
1279 | (AB5500_MASK_BASE <= settings[i].reg) && | ||
1280 | (settings[i].reg <= AB5500_MASK_END)) { | ||
1281 | ab->mask[settings[i].reg - AB5500_MASK_BASE] = | ||
1282 | settings[i].setting; | ||
1283 | } | ||
1284 | } | ||
1285 | exit_no_setup: | ||
1286 | return err; | ||
1287 | } | ||
1288 | |||
1289 | struct ab_family_id { | ||
1290 | u8 id; | ||
1291 | char *name; | ||
1292 | }; | ||
1293 | |||
1294 | static const struct ab_family_id ids[] __initdata = { | ||
1295 | /* AB5500 */ | ||
1296 | { | ||
1297 | .id = AB5500_1_0, | ||
1298 | .name = "1.0" | ||
1299 | }, | ||
1300 | { | ||
1301 | .id = AB5500_1_1, | ||
1302 | .name = "1.1" | ||
1303 | }, | ||
1304 | /* Terminator */ | ||
1305 | { | ||
1306 | .id = 0x00, | ||
1307 | } | ||
1308 | }; | ||
1309 | |||
1310 | static int __init ab5500_probe(struct platform_device *pdev) | ||
1311 | { | ||
1312 | struct ab5500 *ab; | ||
1313 | struct ab5500_platform_data *ab5500_plf_data = | ||
1314 | pdev->dev.platform_data; | ||
1315 | int err; | ||
1316 | int i; | ||
1317 | |||
1318 | ab = kzalloc(sizeof(struct ab5500), GFP_KERNEL); | ||
1319 | if (!ab) { | ||
1320 | dev_err(&pdev->dev, | ||
1321 | "could not allocate ab5500 device\n"); | ||
1322 | return -ENOMEM; | ||
1323 | } | ||
1324 | |||
1325 | /* Initialize data structure */ | ||
1326 | mutex_init(&ab->access_mutex); | ||
1327 | mutex_init(&ab->irq_lock); | ||
1328 | ab->dev = &pdev->dev; | ||
1329 | |||
1330 | platform_set_drvdata(pdev, ab); | ||
1331 | |||
1332 | /* Read chip ID register */ | ||
1333 | err = ab5500_get_register_interruptible_raw(ab, | ||
1334 | AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP, | ||
1335 | AB5500_CHIP_ID, &ab->chip_id); | ||
1336 | if (err) { | ||
1337 | dev_err(&pdev->dev, "could not communicate with the analog " | ||
1338 | "baseband chip\n"); | ||
1339 | goto exit_no_detect; | ||
1340 | } | ||
1341 | |||
1342 | for (i = 0; ids[i].id != 0x0; i++) { | ||
1343 | if (ids[i].id == ab->chip_id) { | ||
1344 | snprintf(&ab->chip_name[0], sizeof(ab->chip_name) - 1, | ||
1345 | "AB5500 %s", ids[i].name); | ||
1346 | break; | ||
1347 | } | ||
1348 | } | ||
1349 | if (ids[i].id == 0x0) { | ||
1350 | dev_err(&pdev->dev, "unknown analog baseband chip id: 0x%x\n", | ||
1351 | ab->chip_id); | ||
1352 | dev_err(&pdev->dev, "driver not started!\n"); | ||
1353 | goto exit_no_detect; | ||
1354 | } | ||
1355 | |||
1356 | /* Clear and mask all interrupts */ | ||
1357 | for (i = 0; i < AB5500_NUM_IRQ_REGS; i++) { | ||
1358 | u8 latchreg = AB5500_IT_LATCH0_REG + i; | ||
1359 | u8 maskreg = AB5500_IT_MASK0_REG + i; | ||
1360 | u8 val; | ||
1361 | |||
1362 | ab5500_get_register_interruptible_raw(ab, AB5500_BANK_IT, | ||
1363 | latchreg, &val); | ||
1364 | set_register_interruptible(ab, AB5500_BANK_IT, maskreg, 0xff); | ||
1365 | ab->mask[i] = ab->oldmask[i] = 0xff; | ||
1366 | } | ||
1367 | |||
1368 | err = abx500_register_ops(&pdev->dev, &ab5500_ops); | ||
1369 | if (err) { | ||
1370 | dev_err(&pdev->dev, "ab5500_register ops error\n"); | ||
1371 | goto exit_no_detect; | ||
1372 | } | ||
1373 | |||
1374 | /* Set up and register the platform devices. */ | ||
1375 | for (i = 0; i < AB5500_NUM_DEVICES; i++) { | ||
1376 | ab5500_devs[i].platform_data = ab5500_plf_data->dev_data[i]; | ||
1377 | ab5500_devs[i].pdata_size = | ||
1378 | sizeof(ab5500_plf_data->dev_data[i]); | ||
1379 | } | ||
1380 | |||
1381 | err = mfd_add_devices(&pdev->dev, 0, ab5500_devs, | ||
1382 | ARRAY_SIZE(ab5500_devs), NULL, | ||
1383 | ab5500_plf_data->irq.base); | ||
1384 | if (err) { | ||
1385 | dev_err(&pdev->dev, "ab5500_mfd_add_device error\n"); | ||
1386 | goto exit_no_detect; | ||
1387 | } | ||
1388 | |||
1389 | err = ab5500_setup(ab, ab5500_plf_data->init_settings, | ||
1390 | ab5500_plf_data->init_settings_sz); | ||
1391 | if (err) { | ||
1392 | dev_err(&pdev->dev, "ab5500_setup error\n"); | ||
1393 | goto exit_no_detect; | ||
1394 | } | ||
1395 | |||
1396 | ab5500_setup_debugfs(ab); | ||
1397 | |||
1398 | dev_info(&pdev->dev, "detected AB chip: %s\n", &ab->chip_name[0]); | ||
1399 | return 0; | ||
1400 | |||
1401 | exit_no_detect: | ||
1402 | kfree(ab); | ||
1403 | return err; | ||
1404 | } | ||
1405 | |||
1406 | static int __exit ab5500_remove(struct platform_device *pdev) | ||
1407 | { | ||
1408 | struct ab5500 *ab = platform_get_drvdata(pdev); | ||
1409 | |||
1410 | ab5500_remove_debugfs(); | ||
1411 | mfd_remove_devices(&pdev->dev); | ||
1412 | kfree(ab); | ||
1413 | return 0; | ||
1414 | } | ||
1415 | |||
1416 | static struct platform_driver ab5500_driver = { | ||
1417 | .driver = { | ||
1418 | .name = "ab5500-core", | ||
1419 | .owner = THIS_MODULE, | ||
1420 | }, | ||
1421 | .remove = __exit_p(ab5500_remove), | ||
1422 | }; | ||
1423 | |||
1424 | static int __init ab5500_core_init(void) | ||
1425 | { | ||
1426 | return platform_driver_probe(&ab5500_driver, ab5500_probe); | ||
1427 | } | ||
1428 | |||
1429 | static void __exit ab5500_core_exit(void) | ||
1430 | { | ||
1431 | platform_driver_unregister(&ab5500_driver); | ||
1432 | } | ||
1433 | |||
1434 | subsys_initcall(ab5500_core_init); | ||
1435 | module_exit(ab5500_core_exit); | ||
1436 | |||
1437 | MODULE_AUTHOR("Mattias Wallin <mattias.wallin@stericsson.com>"); | ||
1438 | MODULE_DESCRIPTION("AB5500 core driver"); | ||
1439 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/mfd/ab5500-core.h b/drivers/mfd/ab5500-core.h new file mode 100644 index 000000000000..63b30b17e4f3 --- /dev/null +++ b/drivers/mfd/ab5500-core.h | |||
@@ -0,0 +1,87 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 ST-Ericsson | ||
3 | * License terms: GNU General Public License (GPL) version 2 | ||
4 | * Shared definitions and data structures for the AB5500 MFD driver | ||
5 | */ | ||
6 | |||
7 | /* Read/write operation values. */ | ||
8 | #define AB5500_PERM_RD (0x01) | ||
9 | #define AB5500_PERM_WR (0x02) | ||
10 | |||
11 | /* Read/write permissions. */ | ||
12 | #define AB5500_PERM_RO (AB5500_PERM_RD) | ||
13 | #define AB5500_PERM_RW (AB5500_PERM_RD | AB5500_PERM_WR) | ||
14 | |||
15 | #define AB5500_MASK_BASE (0x60) | ||
16 | #define AB5500_MASK_END (0x79) | ||
17 | #define AB5500_CHIP_ID (0x20) | ||
18 | |||
19 | /** | ||
20 | * struct ab5500_reg_range | ||
21 | * @first: the first address of the range | ||
22 | * @last: the last address of the range | ||
23 | * @perm: access permissions for the range | ||
24 | */ | ||
25 | struct ab5500_reg_range { | ||
26 | u8 first; | ||
27 | u8 last; | ||
28 | u8 perm; | ||
29 | }; | ||
30 | |||
31 | /** | ||
32 | * struct ab5500_i2c_ranges | ||
33 | * @count: the number of ranges in the list | ||
34 | * @range: the list of register ranges | ||
35 | */ | ||
36 | struct ab5500_i2c_ranges { | ||
37 | u8 nranges; | ||
38 | u8 bankid; | ||
39 | const struct ab5500_reg_range *range; | ||
40 | }; | ||
41 | |||
42 | /** | ||
43 | * struct ab5500_i2c_banks | ||
44 | * @count: the number of ranges in the list | ||
45 | * @range: the list of register ranges | ||
46 | */ | ||
47 | struct ab5500_i2c_banks { | ||
48 | u8 nbanks; | ||
49 | const struct ab5500_i2c_ranges *bank; | ||
50 | }; | ||
51 | |||
52 | /** | ||
53 | * struct ab5500_bank | ||
54 | * @slave_addr: I2C slave_addr found in AB5500 specification | ||
55 | * @name: Documentation name of the bank. For reference | ||
56 | */ | ||
57 | struct ab5500_bank { | ||
58 | u8 slave_addr; | ||
59 | const char *name; | ||
60 | }; | ||
61 | |||
62 | static const struct ab5500_bank bankinfo[AB5500_NUM_BANKS] = { | ||
63 | [AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP] = { | ||
64 | AB5500_ADDR_VIT_IO_I2C_CLK_TST_OTP, "VIT_IO_I2C_CLK_TST_OTP"}, | ||
65 | [AB5500_BANK_VDDDIG_IO_I2C_CLK_TST] = { | ||
66 | AB5500_ADDR_VDDDIG_IO_I2C_CLK_TST, "VDDDIG_IO_I2C_CLK_TST"}, | ||
67 | [AB5500_BANK_VDENC] = {AB5500_ADDR_VDENC, "VDENC"}, | ||
68 | [AB5500_BANK_SIM_USBSIM] = {AB5500_ADDR_SIM_USBSIM, "SIM_USBSIM"}, | ||
69 | [AB5500_BANK_LED] = {AB5500_ADDR_LED, "LED"}, | ||
70 | [AB5500_BANK_ADC] = {AB5500_ADDR_ADC, "ADC"}, | ||
71 | [AB5500_BANK_RTC] = {AB5500_ADDR_RTC, "RTC"}, | ||
72 | [AB5500_BANK_STARTUP] = {AB5500_ADDR_STARTUP, "STARTUP"}, | ||
73 | [AB5500_BANK_DBI_ECI] = {AB5500_ADDR_DBI_ECI, "DBI-ECI"}, | ||
74 | [AB5500_BANK_CHG] = {AB5500_ADDR_CHG, "CHG"}, | ||
75 | [AB5500_BANK_FG_BATTCOM_ACC] = { | ||
76 | AB5500_ADDR_FG_BATTCOM_ACC, "FG_BATCOM_ACC"}, | ||
77 | [AB5500_BANK_USB] = {AB5500_ADDR_USB, "USB"}, | ||
78 | [AB5500_BANK_IT] = {AB5500_ADDR_IT, "IT"}, | ||
79 | [AB5500_BANK_VIBRA] = {AB5500_ADDR_VIBRA, "VIBRA"}, | ||
80 | [AB5500_BANK_AUDIO_HEADSETUSB] = { | ||
81 | AB5500_ADDR_AUDIO_HEADSETUSB, "AUDIO_HEADSETUSB"}, | ||
82 | }; | ||
83 | |||
84 | int ab5500_get_register_interruptible_raw(struct ab5500 *ab, u8 bank, u8 reg, | ||
85 | u8 *value); | ||
86 | int ab5500_mask_and_set_register_interruptible_raw(struct ab5500 *ab, u8 bank, | ||
87 | u8 reg, u8 bitmask, u8 bitvalues); | ||
diff --git a/drivers/mfd/ab5500-debugfs.c b/drivers/mfd/ab5500-debugfs.c new file mode 100644 index 000000000000..6be1fe6b5f9a --- /dev/null +++ b/drivers/mfd/ab5500-debugfs.c | |||
@@ -0,0 +1,806 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 ST-Ericsson | ||
3 | * License terms: GNU General Public License (GPL) version 2 | ||
4 | * Debugfs support for the AB5500 MFD driver | ||
5 | */ | ||
6 | |||
7 | #include <linux/debugfs.h> | ||
8 | #include <linux/seq_file.h> | ||
9 | #include <linux/mfd/ab5500/ab5500.h> | ||
10 | #include <linux/mfd/abx500.h> | ||
11 | #include <linux/uaccess.h> | ||
12 | |||
13 | #include "ab5500-core.h" | ||
14 | #include "ab5500-debugfs.h" | ||
15 | |||
16 | static struct ab5500_i2c_ranges ab5500_reg_ranges[AB5500_NUM_BANKS] = { | ||
17 | [AB5500_BANK_LED] = { | ||
18 | .bankid = AB5500_BANK_LED, | ||
19 | .nranges = 1, | ||
20 | .range = (struct ab5500_reg_range[]) { | ||
21 | { | ||
22 | .first = 0x00, | ||
23 | .last = 0x0C, | ||
24 | .perm = AB5500_PERM_RW, | ||
25 | }, | ||
26 | }, | ||
27 | }, | ||
28 | [AB5500_BANK_ADC] = { | ||
29 | .bankid = AB5500_BANK_ADC, | ||
30 | .nranges = 6, | ||
31 | .range = (struct ab5500_reg_range[]) { | ||
32 | { | ||
33 | .first = 0x1F, | ||
34 | .last = 0x22, | ||
35 | .perm = AB5500_PERM_RO, | ||
36 | }, | ||
37 | { | ||
38 | .first = 0x23, | ||
39 | .last = 0x24, | ||
40 | .perm = AB5500_PERM_RW, | ||
41 | }, | ||
42 | { | ||
43 | .first = 0x26, | ||
44 | .last = 0x2D, | ||
45 | .perm = AB5500_PERM_RO, | ||
46 | }, | ||
47 | { | ||
48 | .first = 0x2F, | ||
49 | .last = 0x34, | ||
50 | .perm = AB5500_PERM_RW, | ||
51 | }, | ||
52 | { | ||
53 | .first = 0x37, | ||
54 | .last = 0x57, | ||
55 | .perm = AB5500_PERM_RW, | ||
56 | }, | ||
57 | { | ||
58 | .first = 0x58, | ||
59 | .last = 0x58, | ||
60 | .perm = AB5500_PERM_RO, | ||
61 | }, | ||
62 | }, | ||
63 | }, | ||
64 | [AB5500_BANK_RTC] = { | ||
65 | .bankid = AB5500_BANK_RTC, | ||
66 | .nranges = 2, | ||
67 | .range = (struct ab5500_reg_range[]) { | ||
68 | { | ||
69 | .first = 0x00, | ||
70 | .last = 0x04, | ||
71 | .perm = AB5500_PERM_RW, | ||
72 | }, | ||
73 | { | ||
74 | .first = 0x06, | ||
75 | .last = 0x0C, | ||
76 | .perm = AB5500_PERM_RW, | ||
77 | }, | ||
78 | }, | ||
79 | }, | ||
80 | [AB5500_BANK_STARTUP] = { | ||
81 | .bankid = AB5500_BANK_STARTUP, | ||
82 | .nranges = 12, | ||
83 | .range = (struct ab5500_reg_range[]) { | ||
84 | { | ||
85 | .first = 0x00, | ||
86 | .last = 0x01, | ||
87 | .perm = AB5500_PERM_RW, | ||
88 | }, | ||
89 | { | ||
90 | .first = 0x1F, | ||
91 | .last = 0x1F, | ||
92 | .perm = AB5500_PERM_RW, | ||
93 | }, | ||
94 | { | ||
95 | .first = 0x2E, | ||
96 | .last = 0x2E, | ||
97 | .perm = AB5500_PERM_RO, | ||
98 | }, | ||
99 | { | ||
100 | .first = 0x2F, | ||
101 | .last = 0x30, | ||
102 | .perm = AB5500_PERM_RW, | ||
103 | }, | ||
104 | { | ||
105 | .first = 0x50, | ||
106 | .last = 0x51, | ||
107 | .perm = AB5500_PERM_RW, | ||
108 | }, | ||
109 | { | ||
110 | .first = 0x60, | ||
111 | .last = 0x61, | ||
112 | .perm = AB5500_PERM_RW, | ||
113 | }, | ||
114 | { | ||
115 | .first = 0x66, | ||
116 | .last = 0x8A, | ||
117 | .perm = AB5500_PERM_RW, | ||
118 | }, | ||
119 | { | ||
120 | .first = 0x8C, | ||
121 | .last = 0x96, | ||
122 | .perm = AB5500_PERM_RW, | ||
123 | }, | ||
124 | { | ||
125 | .first = 0xAA, | ||
126 | .last = 0xB4, | ||
127 | .perm = AB5500_PERM_RW, | ||
128 | }, | ||
129 | { | ||
130 | .first = 0xB7, | ||
131 | .last = 0xBF, | ||
132 | .perm = AB5500_PERM_RW, | ||
133 | }, | ||
134 | { | ||
135 | .first = 0xC1, | ||
136 | .last = 0xCA, | ||
137 | .perm = AB5500_PERM_RW, | ||
138 | }, | ||
139 | { | ||
140 | .first = 0xD3, | ||
141 | .last = 0xE0, | ||
142 | .perm = AB5500_PERM_RW, | ||
143 | }, | ||
144 | }, | ||
145 | }, | ||
146 | [AB5500_BANK_DBI_ECI] = { | ||
147 | .bankid = AB5500_BANK_DBI_ECI, | ||
148 | .nranges = 3, | ||
149 | .range = (struct ab5500_reg_range[]) { | ||
150 | { | ||
151 | .first = 0x00, | ||
152 | .last = 0x07, | ||
153 | .perm = AB5500_PERM_RW, | ||
154 | }, | ||
155 | { | ||
156 | .first = 0x10, | ||
157 | .last = 0x10, | ||
158 | .perm = AB5500_PERM_RW, | ||
159 | }, | ||
160 | { | ||
161 | .first = 0x13, | ||
162 | .last = 0x13, | ||
163 | .perm = AB5500_PERM_RW, | ||
164 | }, | ||
165 | }, | ||
166 | }, | ||
167 | [AB5500_BANK_CHG] = { | ||
168 | .bankid = AB5500_BANK_CHG, | ||
169 | .nranges = 2, | ||
170 | .range = (struct ab5500_reg_range[]) { | ||
171 | { | ||
172 | .first = 0x11, | ||
173 | .last = 0x11, | ||
174 | .perm = AB5500_PERM_RO, | ||
175 | }, | ||
176 | { | ||
177 | .first = 0x12, | ||
178 | .last = 0x1B, | ||
179 | .perm = AB5500_PERM_RW, | ||
180 | }, | ||
181 | }, | ||
182 | }, | ||
183 | [AB5500_BANK_FG_BATTCOM_ACC] = { | ||
184 | .bankid = AB5500_BANK_FG_BATTCOM_ACC, | ||
185 | .nranges = 2, | ||
186 | .range = (struct ab5500_reg_range[]) { | ||
187 | { | ||
188 | .first = 0x00, | ||
189 | .last = 0x0B, | ||
190 | .perm = AB5500_PERM_RO, | ||
191 | }, | ||
192 | { | ||
193 | .first = 0x0C, | ||
194 | .last = 0x10, | ||
195 | .perm = AB5500_PERM_RW, | ||
196 | }, | ||
197 | }, | ||
198 | }, | ||
199 | [AB5500_BANK_USB] = { | ||
200 | .bankid = AB5500_BANK_USB, | ||
201 | .nranges = 12, | ||
202 | .range = (struct ab5500_reg_range[]) { | ||
203 | { | ||
204 | .first = 0x01, | ||
205 | .last = 0x01, | ||
206 | .perm = AB5500_PERM_RW, | ||
207 | }, | ||
208 | { | ||
209 | .first = 0x80, | ||
210 | .last = 0x83, | ||
211 | .perm = AB5500_PERM_RW, | ||
212 | }, | ||
213 | { | ||
214 | .first = 0x87, | ||
215 | .last = 0x8A, | ||
216 | .perm = AB5500_PERM_RW, | ||
217 | }, | ||
218 | { | ||
219 | .first = 0x8B, | ||
220 | .last = 0x8B, | ||
221 | .perm = AB5500_PERM_RO, | ||
222 | }, | ||
223 | { | ||
224 | .first = 0x91, | ||
225 | .last = 0x92, | ||
226 | .perm = AB5500_PERM_RO, | ||
227 | }, | ||
228 | { | ||
229 | .first = 0x93, | ||
230 | .last = 0x93, | ||
231 | .perm = AB5500_PERM_RW, | ||
232 | }, | ||
233 | { | ||
234 | .first = 0x94, | ||
235 | .last = 0x94, | ||
236 | .perm = AB5500_PERM_RO, | ||
237 | }, | ||
238 | { | ||
239 | .first = 0xA8, | ||
240 | .last = 0xB0, | ||
241 | .perm = AB5500_PERM_RO, | ||
242 | }, | ||
243 | { | ||
244 | .first = 0xB2, | ||
245 | .last = 0xB2, | ||
246 | .perm = AB5500_PERM_RO, | ||
247 | }, | ||
248 | { | ||
249 | .first = 0xB4, | ||
250 | .last = 0xBC, | ||
251 | .perm = AB5500_PERM_RO, | ||
252 | }, | ||
253 | { | ||
254 | .first = 0xBF, | ||
255 | .last = 0xBF, | ||
256 | .perm = AB5500_PERM_RO, | ||
257 | }, | ||
258 | { | ||
259 | .first = 0xC1, | ||
260 | .last = 0xC5, | ||
261 | .perm = AB5500_PERM_RO, | ||
262 | }, | ||
263 | }, | ||
264 | }, | ||
265 | [AB5500_BANK_IT] = { | ||
266 | .bankid = AB5500_BANK_IT, | ||
267 | .nranges = 4, | ||
268 | .range = (struct ab5500_reg_range[]) { | ||
269 | { | ||
270 | .first = 0x00, | ||
271 | .last = 0x02, | ||
272 | .perm = AB5500_PERM_RO, | ||
273 | }, | ||
274 | { | ||
275 | .first = 0x20, | ||
276 | .last = 0x36, | ||
277 | .perm = AB5500_PERM_RO, | ||
278 | }, | ||
279 | { | ||
280 | .first = 0x40, | ||
281 | .last = 0x56, | ||
282 | .perm = AB5500_PERM_RO, | ||
283 | }, | ||
284 | { | ||
285 | .first = 0x60, | ||
286 | .last = 0x76, | ||
287 | .perm = AB5500_PERM_RO, | ||
288 | }, | ||
289 | }, | ||
290 | }, | ||
291 | [AB5500_BANK_VDDDIG_IO_I2C_CLK_TST] = { | ||
292 | .bankid = AB5500_BANK_VDDDIG_IO_I2C_CLK_TST, | ||
293 | .nranges = 7, | ||
294 | .range = (struct ab5500_reg_range[]) { | ||
295 | { | ||
296 | .first = 0x02, | ||
297 | .last = 0x02, | ||
298 | .perm = AB5500_PERM_RW, | ||
299 | }, | ||
300 | { | ||
301 | .first = 0x12, | ||
302 | .last = 0x12, | ||
303 | .perm = AB5500_PERM_RW, | ||
304 | }, | ||
305 | { | ||
306 | .first = 0x30, | ||
307 | .last = 0x34, | ||
308 | .perm = AB5500_PERM_RW, | ||
309 | }, | ||
310 | { | ||
311 | .first = 0x40, | ||
312 | .last = 0x44, | ||
313 | .perm = AB5500_PERM_RW, | ||
314 | }, | ||
315 | { | ||
316 | .first = 0x50, | ||
317 | .last = 0x54, | ||
318 | .perm = AB5500_PERM_RW, | ||
319 | }, | ||
320 | { | ||
321 | .first = 0x60, | ||
322 | .last = 0x64, | ||
323 | .perm = AB5500_PERM_RW, | ||
324 | }, | ||
325 | { | ||
326 | .first = 0x70, | ||
327 | .last = 0x74, | ||
328 | .perm = AB5500_PERM_RW, | ||
329 | }, | ||
330 | }, | ||
331 | }, | ||
332 | [AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP] = { | ||
333 | .bankid = AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP, | ||
334 | .nranges = 13, | ||
335 | .range = (struct ab5500_reg_range[]) { | ||
336 | { | ||
337 | .first = 0x01, | ||
338 | .last = 0x01, | ||
339 | .perm = AB5500_PERM_RW, | ||
340 | }, | ||
341 | { | ||
342 | .first = 0x02, | ||
343 | .last = 0x02, | ||
344 | .perm = AB5500_PERM_RO, | ||
345 | }, | ||
346 | { | ||
347 | .first = 0x0D, | ||
348 | .last = 0x0F, | ||
349 | .perm = AB5500_PERM_RW, | ||
350 | }, | ||
351 | { | ||
352 | .first = 0x1C, | ||
353 | .last = 0x1C, | ||
354 | .perm = AB5500_PERM_RW, | ||
355 | }, | ||
356 | { | ||
357 | .first = 0x1E, | ||
358 | .last = 0x1E, | ||
359 | .perm = AB5500_PERM_RW, | ||
360 | }, | ||
361 | { | ||
362 | .first = 0x20, | ||
363 | .last = 0x21, | ||
364 | .perm = AB5500_PERM_RW, | ||
365 | }, | ||
366 | { | ||
367 | .first = 0x25, | ||
368 | .last = 0x25, | ||
369 | .perm = AB5500_PERM_RW, | ||
370 | }, | ||
371 | { | ||
372 | .first = 0x28, | ||
373 | .last = 0x2A, | ||
374 | .perm = AB5500_PERM_RW, | ||
375 | }, | ||
376 | { | ||
377 | .first = 0x30, | ||
378 | .last = 0x33, | ||
379 | .perm = AB5500_PERM_RW, | ||
380 | }, | ||
381 | { | ||
382 | .first = 0x40, | ||
383 | .last = 0x43, | ||
384 | .perm = AB5500_PERM_RW, | ||
385 | }, | ||
386 | { | ||
387 | .first = 0x50, | ||
388 | .last = 0x53, | ||
389 | .perm = AB5500_PERM_RW, | ||
390 | }, | ||
391 | { | ||
392 | .first = 0x60, | ||
393 | .last = 0x63, | ||
394 | .perm = AB5500_PERM_RW, | ||
395 | }, | ||
396 | { | ||
397 | .first = 0x70, | ||
398 | .last = 0x73, | ||
399 | .perm = AB5500_PERM_RW, | ||
400 | }, | ||
401 | }, | ||
402 | }, | ||
403 | [AB5500_BANK_VIBRA] = { | ||
404 | .bankid = AB5500_BANK_VIBRA, | ||
405 | .nranges = 2, | ||
406 | .range = (struct ab5500_reg_range[]) { | ||
407 | { | ||
408 | .first = 0x10, | ||
409 | .last = 0x13, | ||
410 | .perm = AB5500_PERM_RW, | ||
411 | }, | ||
412 | { | ||
413 | .first = 0xFE, | ||
414 | .last = 0xFE, | ||
415 | .perm = AB5500_PERM_RW, | ||
416 | }, | ||
417 | }, | ||
418 | }, | ||
419 | [AB5500_BANK_AUDIO_HEADSETUSB] = { | ||
420 | .bankid = AB5500_BANK_AUDIO_HEADSETUSB, | ||
421 | .nranges = 2, | ||
422 | .range = (struct ab5500_reg_range[]) { | ||
423 | { | ||
424 | .first = 0x00, | ||
425 | .last = 0x48, | ||
426 | .perm = AB5500_PERM_RW, | ||
427 | }, | ||
428 | { | ||
429 | .first = 0xEB, | ||
430 | .last = 0xFB, | ||
431 | .perm = AB5500_PERM_RW, | ||
432 | }, | ||
433 | }, | ||
434 | }, | ||
435 | [AB5500_BANK_SIM_USBSIM] = { | ||
436 | .bankid = AB5500_BANK_SIM_USBSIM, | ||
437 | .nranges = 1, | ||
438 | .range = (struct ab5500_reg_range[]) { | ||
439 | { | ||
440 | .first = 0x13, | ||
441 | .last = 0x19, | ||
442 | .perm = AB5500_PERM_RW, | ||
443 | }, | ||
444 | }, | ||
445 | }, | ||
446 | [AB5500_BANK_VDENC] = { | ||
447 | .bankid = AB5500_BANK_VDENC, | ||
448 | .nranges = 12, | ||
449 | .range = (struct ab5500_reg_range[]) { | ||
450 | { | ||
451 | .first = 0x00, | ||
452 | .last = 0x08, | ||
453 | .perm = AB5500_PERM_RW, | ||
454 | }, | ||
455 | { | ||
456 | .first = 0x09, | ||
457 | .last = 0x09, | ||
458 | .perm = AB5500_PERM_RO, | ||
459 | }, | ||
460 | { | ||
461 | .first = 0x0A, | ||
462 | .last = 0x12, | ||
463 | .perm = AB5500_PERM_RW, | ||
464 | }, | ||
465 | { | ||
466 | .first = 0x15, | ||
467 | .last = 0x19, | ||
468 | .perm = AB5500_PERM_RW, | ||
469 | }, | ||
470 | { | ||
471 | .first = 0x1B, | ||
472 | .last = 0x21, | ||
473 | .perm = AB5500_PERM_RW, | ||
474 | }, | ||
475 | { | ||
476 | .first = 0x27, | ||
477 | .last = 0x2C, | ||
478 | .perm = AB5500_PERM_RW, | ||
479 | }, | ||
480 | { | ||
481 | .first = 0x41, | ||
482 | .last = 0x41, | ||
483 | .perm = AB5500_PERM_RW, | ||
484 | }, | ||
485 | { | ||
486 | .first = 0x45, | ||
487 | .last = 0x5B, | ||
488 | .perm = AB5500_PERM_RW, | ||
489 | }, | ||
490 | { | ||
491 | .first = 0x5D, | ||
492 | .last = 0x5D, | ||
493 | .perm = AB5500_PERM_RW, | ||
494 | }, | ||
495 | { | ||
496 | .first = 0x69, | ||
497 | .last = 0x69, | ||
498 | .perm = AB5500_PERM_RW, | ||
499 | }, | ||
500 | { | ||
501 | .first = 0x6C, | ||
502 | .last = 0x6D, | ||
503 | .perm = AB5500_PERM_RW, | ||
504 | }, | ||
505 | { | ||
506 | .first = 0x80, | ||
507 | .last = 0x81, | ||
508 | .perm = AB5500_PERM_RW, | ||
509 | }, | ||
510 | }, | ||
511 | }, | ||
512 | }; | ||
513 | |||
514 | static int ab5500_registers_print(struct seq_file *s, void *p) | ||
515 | { | ||
516 | struct ab5500 *ab = s->private; | ||
517 | unsigned int i; | ||
518 | u8 bank = (u8)ab->debug_bank; | ||
519 | |||
520 | seq_printf(s, "ab5500 register values:\n"); | ||
521 | for (bank = 0; bank < AB5500_NUM_BANKS; bank++) { | ||
522 | seq_printf(s, " bank %u, %s (0x%x):\n", bank, | ||
523 | bankinfo[bank].name, | ||
524 | bankinfo[bank].slave_addr); | ||
525 | for (i = 0; i < ab5500_reg_ranges[bank].nranges; i++) { | ||
526 | u8 reg; | ||
527 | int err; | ||
528 | |||
529 | for (reg = ab5500_reg_ranges[bank].range[i].first; | ||
530 | reg <= ab5500_reg_ranges[bank].range[i].last; | ||
531 | reg++) { | ||
532 | u8 value; | ||
533 | |||
534 | err = ab5500_get_register_interruptible_raw(ab, | ||
535 | bank, reg, | ||
536 | &value); | ||
537 | if (err < 0) { | ||
538 | dev_err(ab->dev, "get_reg failed %d" | ||
539 | "bank 0x%x reg 0x%x\n", | ||
540 | err, bank, reg); | ||
541 | return err; | ||
542 | } | ||
543 | |||
544 | err = seq_printf(s, "[%d/0x%02X]: 0x%02X\n", | ||
545 | bank, reg, value); | ||
546 | if (err < 0) { | ||
547 | dev_err(ab->dev, | ||
548 | "seq_printf overflow\n"); | ||
549 | /* | ||
550 | * Error is not returned here since | ||
551 | * the output is wanted in any case | ||
552 | */ | ||
553 | return 0; | ||
554 | } | ||
555 | } | ||
556 | } | ||
557 | } | ||
558 | return 0; | ||
559 | } | ||
560 | |||
561 | static int ab5500_registers_open(struct inode *inode, struct file *file) | ||
562 | { | ||
563 | return single_open(file, ab5500_registers_print, inode->i_private); | ||
564 | } | ||
565 | |||
566 | static const struct file_operations ab5500_registers_fops = { | ||
567 | .open = ab5500_registers_open, | ||
568 | .read = seq_read, | ||
569 | .llseek = seq_lseek, | ||
570 | .release = single_release, | ||
571 | .owner = THIS_MODULE, | ||
572 | }; | ||
573 | |||
574 | static int ab5500_bank_print(struct seq_file *s, void *p) | ||
575 | { | ||
576 | struct ab5500 *ab = s->private; | ||
577 | |||
578 | seq_printf(s, "%d\n", ab->debug_bank); | ||
579 | return 0; | ||
580 | } | ||
581 | |||
582 | static int ab5500_bank_open(struct inode *inode, struct file *file) | ||
583 | { | ||
584 | return single_open(file, ab5500_bank_print, inode->i_private); | ||
585 | } | ||
586 | |||
587 | static ssize_t ab5500_bank_write(struct file *file, | ||
588 | const char __user *user_buf, | ||
589 | size_t count, loff_t *ppos) | ||
590 | { | ||
591 | struct ab5500 *ab = ((struct seq_file *)(file->private_data))->private; | ||
592 | char buf[32]; | ||
593 | int buf_size; | ||
594 | unsigned long user_bank; | ||
595 | int err; | ||
596 | |||
597 | /* Get userspace string and assure termination */ | ||
598 | buf_size = min(count, (sizeof(buf) - 1)); | ||
599 | if (copy_from_user(buf, user_buf, buf_size)) | ||
600 | return -EFAULT; | ||
601 | buf[buf_size] = 0; | ||
602 | |||
603 | err = strict_strtoul(buf, 0, &user_bank); | ||
604 | if (err) | ||
605 | return -EINVAL; | ||
606 | |||
607 | if (user_bank >= AB5500_NUM_BANKS) { | ||
608 | dev_err(ab->dev, | ||
609 | "debugfs error input > number of banks\n"); | ||
610 | return -EINVAL; | ||
611 | } | ||
612 | |||
613 | ab->debug_bank = user_bank; | ||
614 | |||
615 | return buf_size; | ||
616 | } | ||
617 | |||
618 | static int ab5500_address_print(struct seq_file *s, void *p) | ||
619 | { | ||
620 | struct ab5500 *ab = s->private; | ||
621 | |||
622 | seq_printf(s, "0x%02X\n", ab->debug_address); | ||
623 | return 0; | ||
624 | } | ||
625 | |||
626 | static int ab5500_address_open(struct inode *inode, struct file *file) | ||
627 | { | ||
628 | return single_open(file, ab5500_address_print, inode->i_private); | ||
629 | } | ||
630 | |||
631 | static ssize_t ab5500_address_write(struct file *file, | ||
632 | const char __user *user_buf, | ||
633 | size_t count, loff_t *ppos) | ||
634 | { | ||
635 | struct ab5500 *ab = ((struct seq_file *)(file->private_data))->private; | ||
636 | char buf[32]; | ||
637 | int buf_size; | ||
638 | unsigned long user_address; | ||
639 | int err; | ||
640 | |||
641 | /* Get userspace string and assure termination */ | ||
642 | buf_size = min(count, (sizeof(buf) - 1)); | ||
643 | if (copy_from_user(buf, user_buf, buf_size)) | ||
644 | return -EFAULT; | ||
645 | buf[buf_size] = 0; | ||
646 | |||
647 | err = strict_strtoul(buf, 0, &user_address); | ||
648 | if (err) | ||
649 | return -EINVAL; | ||
650 | if (user_address > 0xff) { | ||
651 | dev_err(ab->dev, | ||
652 | "debugfs error input > 0xff\n"); | ||
653 | return -EINVAL; | ||
654 | } | ||
655 | ab->debug_address = user_address; | ||
656 | return buf_size; | ||
657 | } | ||
658 | |||
659 | static int ab5500_val_print(struct seq_file *s, void *p) | ||
660 | { | ||
661 | struct ab5500 *ab = s->private; | ||
662 | int err; | ||
663 | u8 regvalue; | ||
664 | |||
665 | err = ab5500_get_register_interruptible_raw(ab, (u8)ab->debug_bank, | ||
666 | (u8)ab->debug_address, ®value); | ||
667 | if (err) { | ||
668 | dev_err(ab->dev, "get_reg failed %d, bank 0x%x" | ||
669 | ", reg 0x%x\n", err, ab->debug_bank, | ||
670 | ab->debug_address); | ||
671 | return -EINVAL; | ||
672 | } | ||
673 | seq_printf(s, "0x%02X\n", regvalue); | ||
674 | |||
675 | return 0; | ||
676 | } | ||
677 | |||
678 | static int ab5500_val_open(struct inode *inode, struct file *file) | ||
679 | { | ||
680 | return single_open(file, ab5500_val_print, inode->i_private); | ||
681 | } | ||
682 | |||
683 | static ssize_t ab5500_val_write(struct file *file, | ||
684 | const char __user *user_buf, | ||
685 | size_t count, loff_t *ppos) | ||
686 | { | ||
687 | struct ab5500 *ab = ((struct seq_file *)(file->private_data))->private; | ||
688 | char buf[32]; | ||
689 | int buf_size; | ||
690 | unsigned long user_val; | ||
691 | int err; | ||
692 | u8 regvalue; | ||
693 | |||
694 | /* Get userspace string and assure termination */ | ||
695 | buf_size = min(count, (sizeof(buf)-1)); | ||
696 | if (copy_from_user(buf, user_buf, buf_size)) | ||
697 | return -EFAULT; | ||
698 | buf[buf_size] = 0; | ||
699 | |||
700 | err = strict_strtoul(buf, 0, &user_val); | ||
701 | if (err) | ||
702 | return -EINVAL; | ||
703 | if (user_val > 0xff) { | ||
704 | dev_err(ab->dev, | ||
705 | "debugfs error input > 0xff\n"); | ||
706 | return -EINVAL; | ||
707 | } | ||
708 | err = ab5500_mask_and_set_register_interruptible_raw( | ||
709 | ab, (u8)ab->debug_bank, | ||
710 | (u8)ab->debug_address, 0xFF, (u8)user_val); | ||
711 | if (err) | ||
712 | return -EINVAL; | ||
713 | |||
714 | ab5500_get_register_interruptible_raw(ab, (u8)ab->debug_bank, | ||
715 | (u8)ab->debug_address, ®value); | ||
716 | if (err) | ||
717 | return -EINVAL; | ||
718 | |||
719 | return buf_size; | ||
720 | } | ||
721 | |||
722 | static const struct file_operations ab5500_bank_fops = { | ||
723 | .open = ab5500_bank_open, | ||
724 | .write = ab5500_bank_write, | ||
725 | .read = seq_read, | ||
726 | .llseek = seq_lseek, | ||
727 | .release = single_release, | ||
728 | .owner = THIS_MODULE, | ||
729 | }; | ||
730 | |||
731 | static const struct file_operations ab5500_address_fops = { | ||
732 | .open = ab5500_address_open, | ||
733 | .write = ab5500_address_write, | ||
734 | .read = seq_read, | ||
735 | .llseek = seq_lseek, | ||
736 | .release = single_release, | ||
737 | .owner = THIS_MODULE, | ||
738 | }; | ||
739 | |||
740 | static const struct file_operations ab5500_val_fops = { | ||
741 | .open = ab5500_val_open, | ||
742 | .write = ab5500_val_write, | ||
743 | .read = seq_read, | ||
744 | .llseek = seq_lseek, | ||
745 | .release = single_release, | ||
746 | .owner = THIS_MODULE, | ||
747 | }; | ||
748 | |||
749 | static struct dentry *ab5500_dir; | ||
750 | static struct dentry *ab5500_reg_file; | ||
751 | static struct dentry *ab5500_bank_file; | ||
752 | static struct dentry *ab5500_address_file; | ||
753 | static struct dentry *ab5500_val_file; | ||
754 | |||
755 | void __init ab5500_setup_debugfs(struct ab5500 *ab) | ||
756 | { | ||
757 | ab->debug_bank = AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP; | ||
758 | ab->debug_address = AB5500_CHIP_ID; | ||
759 | |||
760 | ab5500_dir = debugfs_create_dir("ab5500", NULL); | ||
761 | if (!ab5500_dir) | ||
762 | goto exit_no_debugfs; | ||
763 | |||
764 | ab5500_reg_file = debugfs_create_file("all-bank-registers", | ||
765 | S_IRUGO, ab5500_dir, ab, &ab5500_registers_fops); | ||
766 | if (!ab5500_reg_file) | ||
767 | goto exit_destroy_dir; | ||
768 | |||
769 | ab5500_bank_file = debugfs_create_file("register-bank", | ||
770 | (S_IRUGO | S_IWUGO), ab5500_dir, ab, &ab5500_bank_fops); | ||
771 | if (!ab5500_bank_file) | ||
772 | goto exit_destroy_reg; | ||
773 | |||
774 | ab5500_address_file = debugfs_create_file("register-address", | ||
775 | (S_IRUGO | S_IWUGO), ab5500_dir, ab, &ab5500_address_fops); | ||
776 | if (!ab5500_address_file) | ||
777 | goto exit_destroy_bank; | ||
778 | |||
779 | ab5500_val_file = debugfs_create_file("register-value", | ||
780 | (S_IRUGO | S_IWUGO), ab5500_dir, ab, &ab5500_val_fops); | ||
781 | if (!ab5500_val_file) | ||
782 | goto exit_destroy_address; | ||
783 | |||
784 | return; | ||
785 | |||
786 | exit_destroy_address: | ||
787 | debugfs_remove(ab5500_address_file); | ||
788 | exit_destroy_bank: | ||
789 | debugfs_remove(ab5500_bank_file); | ||
790 | exit_destroy_reg: | ||
791 | debugfs_remove(ab5500_reg_file); | ||
792 | exit_destroy_dir: | ||
793 | debugfs_remove(ab5500_dir); | ||
794 | exit_no_debugfs: | ||
795 | dev_err(ab->dev, "failed to create debugfs entries.\n"); | ||
796 | return; | ||
797 | } | ||
798 | |||
799 | void __exit ab5500_remove_debugfs(void) | ||
800 | { | ||
801 | debugfs_remove(ab5500_val_file); | ||
802 | debugfs_remove(ab5500_address_file); | ||
803 | debugfs_remove(ab5500_bank_file); | ||
804 | debugfs_remove(ab5500_reg_file); | ||
805 | debugfs_remove(ab5500_dir); | ||
806 | } | ||
diff --git a/drivers/mfd/ab5500-debugfs.h b/drivers/mfd/ab5500-debugfs.h new file mode 100644 index 000000000000..7330a9b6afa6 --- /dev/null +++ b/drivers/mfd/ab5500-debugfs.h | |||
@@ -0,0 +1,22 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 ST-Ericsson | ||
3 | * License terms: GNU General Public License (GPL) version 2 | ||
4 | * Debugfs interface to the AB5500 core driver | ||
5 | */ | ||
6 | |||
7 | #ifdef CONFIG_DEBUG_FS | ||
8 | |||
9 | void ab5500_setup_debugfs(struct ab5500 *ab); | ||
10 | void ab5500_remove_debugfs(void); | ||
11 | |||
12 | #else /* !CONFIG_DEBUG_FS */ | ||
13 | |||
14 | static inline void ab5500_setup_debugfs(struct ab5500 *ab) | ||
15 | { | ||
16 | } | ||
17 | |||
18 | static inline void ab5500_remove_debugfs(void) | ||
19 | { | ||
20 | } | ||
21 | |||
22 | #endif | ||
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index 387705e494b9..1e9173804ede 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c | |||
@@ -92,6 +92,8 @@ | |||
92 | #define AB8500_REV_REG 0x80 | 92 | #define AB8500_REV_REG 0x80 |
93 | #define AB8500_SWITCH_OFF_STATUS 0x00 | 93 | #define AB8500_SWITCH_OFF_STATUS 0x00 |
94 | 94 | ||
95 | #define AB8500_TURN_ON_STATUS 0x00 | ||
96 | |||
95 | /* | 97 | /* |
96 | * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt | 98 | * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt |
97 | * numbers are indexed into this array with (num / 8). | 99 | * numbers are indexed into this array with (num / 8). |
@@ -293,6 +295,7 @@ static struct irq_chip ab8500_irq_chip = { | |||
293 | .irq_bus_lock = ab8500_irq_lock, | 295 | .irq_bus_lock = ab8500_irq_lock, |
294 | .irq_bus_sync_unlock = ab8500_irq_sync_unlock, | 296 | .irq_bus_sync_unlock = ab8500_irq_sync_unlock, |
295 | .irq_mask = ab8500_irq_mask, | 297 | .irq_mask = ab8500_irq_mask, |
298 | .irq_disable = ab8500_irq_mask, | ||
296 | .irq_unmask = ab8500_irq_unmask, | 299 | .irq_unmask = ab8500_irq_unmask, |
297 | }; | 300 | }; |
298 | 301 | ||
@@ -811,12 +814,40 @@ static ssize_t show_switch_off_status(struct device *dev, | |||
811 | return sprintf(buf, "%#x\n", value); | 814 | return sprintf(buf, "%#x\n", value); |
812 | } | 815 | } |
813 | 816 | ||
817 | /* | ||
818 | * ab8500 has turned on due to (TURN_ON_STATUS): | ||
819 | * 0x01 PORnVbat | ||
820 | * 0x02 PonKey1dbF | ||
821 | * 0x04 PonKey2dbF | ||
822 | * 0x08 RTCAlarm | ||
823 | * 0x10 MainChDet | ||
824 | * 0x20 VbusDet | ||
825 | * 0x40 UsbIDDetect | ||
826 | * 0x80 Reserved | ||
827 | */ | ||
828 | static ssize_t show_turn_on_status(struct device *dev, | ||
829 | struct device_attribute *attr, char *buf) | ||
830 | { | ||
831 | int ret; | ||
832 | u8 value; | ||
833 | struct ab8500 *ab8500; | ||
834 | |||
835 | ab8500 = dev_get_drvdata(dev); | ||
836 | ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK, | ||
837 | AB8500_TURN_ON_STATUS, &value); | ||
838 | if (ret < 0) | ||
839 | return ret; | ||
840 | return sprintf(buf, "%#x\n", value); | ||
841 | } | ||
842 | |||
814 | static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL); | 843 | static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL); |
815 | static DEVICE_ATTR(switch_off_status, S_IRUGO, show_switch_off_status, NULL); | 844 | static DEVICE_ATTR(switch_off_status, S_IRUGO, show_switch_off_status, NULL); |
845 | static DEVICE_ATTR(turn_on_status, S_IRUGO, show_turn_on_status, NULL); | ||
816 | 846 | ||
817 | static struct attribute *ab8500_sysfs_entries[] = { | 847 | static struct attribute *ab8500_sysfs_entries[] = { |
818 | &dev_attr_chip_id.attr, | 848 | &dev_attr_chip_id.attr, |
819 | &dev_attr_switch_off_status.attr, | 849 | &dev_attr_switch_off_status.attr, |
850 | &dev_attr_turn_on_status.attr, | ||
820 | NULL, | 851 | NULL, |
821 | }; | 852 | }; |
822 | 853 | ||
@@ -843,11 +874,11 @@ int __devinit ab8500_init(struct ab8500 *ab8500) | |||
843 | return ret; | 874 | return ret; |
844 | 875 | ||
845 | switch (value) { | 876 | switch (value) { |
846 | case AB8500_CUTEARLY: | ||
847 | case AB8500_CUT1P0: | 877 | case AB8500_CUT1P0: |
848 | case AB8500_CUT1P1: | 878 | case AB8500_CUT1P1: |
849 | case AB8500_CUT2P0: | 879 | case AB8500_CUT2P0: |
850 | case AB8500_CUT3P0: | 880 | case AB8500_CUT3P0: |
881 | case AB8500_CUT3P3: | ||
851 | dev_info(ab8500->dev, "detected chip, revision: %#x\n", value); | 882 | dev_info(ab8500->dev, "detected chip, revision: %#x\n", value); |
852 | break; | 883 | break; |
853 | default: | 884 | default: |
diff --git a/drivers/mfd/ab8500-gpadc.c b/drivers/mfd/ab8500-gpadc.c index f16afb234ff9..e985d1701a83 100644 --- a/drivers/mfd/ab8500-gpadc.c +++ b/drivers/mfd/ab8500-gpadc.c | |||
@@ -143,12 +143,15 @@ struct ab8500_gpadc *ab8500_gpadc_get(char *name) | |||
143 | } | 143 | } |
144 | EXPORT_SYMBOL(ab8500_gpadc_get); | 144 | EXPORT_SYMBOL(ab8500_gpadc_get); |
145 | 145 | ||
146 | static int ab8500_gpadc_ad_to_voltage(struct ab8500_gpadc *gpadc, u8 input, | 146 | /** |
147 | * ab8500_gpadc_ad_to_voltage() - Convert a raw ADC value to a voltage | ||
148 | */ | ||
149 | int ab8500_gpadc_ad_to_voltage(struct ab8500_gpadc *gpadc, u8 channel, | ||
147 | int ad_value) | 150 | int ad_value) |
148 | { | 151 | { |
149 | int res; | 152 | int res; |
150 | 153 | ||
151 | switch (input) { | 154 | switch (channel) { |
152 | case MAIN_CHARGER_V: | 155 | case MAIN_CHARGER_V: |
153 | /* For some reason we don't have calibrated data */ | 156 | /* For some reason we don't have calibrated data */ |
154 | if (!gpadc->cal_data[ADC_INPUT_VMAIN].gain) { | 157 | if (!gpadc->cal_data[ADC_INPUT_VMAIN].gain) { |
@@ -232,18 +235,46 @@ static int ab8500_gpadc_ad_to_voltage(struct ab8500_gpadc *gpadc, u8 input, | |||
232 | } | 235 | } |
233 | return res; | 236 | return res; |
234 | } | 237 | } |
238 | EXPORT_SYMBOL(ab8500_gpadc_ad_to_voltage); | ||
235 | 239 | ||
236 | /** | 240 | /** |
237 | * ab8500_gpadc_convert() - gpadc conversion | 241 | * ab8500_gpadc_convert() - gpadc conversion |
238 | * @input: analog input to be converted to digital data | 242 | * @channel: analog channel to be converted to digital data |
239 | * | 243 | * |
240 | * This function converts the selected analog i/p to digital | 244 | * This function converts the selected analog i/p to digital |
241 | * data. | 245 | * data. |
242 | */ | 246 | */ |
243 | int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 input) | 247 | int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 channel) |
248 | { | ||
249 | int ad_value; | ||
250 | int voltage; | ||
251 | |||
252 | ad_value = ab8500_gpadc_read_raw(gpadc, channel); | ||
253 | if (ad_value < 0) { | ||
254 | dev_err(gpadc->dev, "GPADC raw value failed ch: %d\n", channel); | ||
255 | return ad_value; | ||
256 | } | ||
257 | |||
258 | voltage = ab8500_gpadc_ad_to_voltage(gpadc, channel, ad_value); | ||
259 | |||
260 | if (voltage < 0) | ||
261 | dev_err(gpadc->dev, "GPADC to voltage conversion failed ch:" | ||
262 | " %d AD: 0x%x\n", channel, ad_value); | ||
263 | |||
264 | return voltage; | ||
265 | } | ||
266 | EXPORT_SYMBOL(ab8500_gpadc_convert); | ||
267 | |||
268 | /** | ||
269 | * ab8500_gpadc_read_raw() - gpadc read | ||
270 | * @channel: analog channel to be read | ||
271 | * | ||
272 | * This function obtains the raw ADC value, this then needs | ||
273 | * to be converted by calling ab8500_gpadc_ad_to_voltage() | ||
274 | */ | ||
275 | int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel) | ||
244 | { | 276 | { |
245 | int ret; | 277 | int ret; |
246 | u16 data = 0; | ||
247 | int looplimit = 0; | 278 | int looplimit = 0; |
248 | u8 val, low_data, high_data; | 279 | u8 val, low_data, high_data; |
249 | 280 | ||
@@ -278,9 +309,9 @@ int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 input) | |||
278 | goto out; | 309 | goto out; |
279 | } | 310 | } |
280 | 311 | ||
281 | /* Select the input source and set average samples to 16 */ | 312 | /* Select the channel source and set average samples to 16 */ |
282 | ret = abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC, | 313 | ret = abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC, |
283 | AB8500_GPADC_CTRL2_REG, (input | SW_AVG_16)); | 314 | AB8500_GPADC_CTRL2_REG, (channel | SW_AVG_16)); |
284 | if (ret < 0) { | 315 | if (ret < 0) { |
285 | dev_err(gpadc->dev, | 316 | dev_err(gpadc->dev, |
286 | "gpadc_conversion: set avg samples failed\n"); | 317 | "gpadc_conversion: set avg samples failed\n"); |
@@ -292,7 +323,7 @@ int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 input) | |||
292 | * charging current sense if it needed, ABB 3.0 needs some special | 323 | * charging current sense if it needed, ABB 3.0 needs some special |
293 | * treatment too. | 324 | * treatment too. |
294 | */ | 325 | */ |
295 | switch (input) { | 326 | switch (channel) { |
296 | case MAIN_CHARGER_C: | 327 | case MAIN_CHARGER_C: |
297 | case USB_CHARGER_C: | 328 | case USB_CHARGER_C: |
298 | ret = abx500_mask_and_set_register_interruptible(gpadc->dev, | 329 | ret = abx500_mask_and_set_register_interruptible(gpadc->dev, |
@@ -359,7 +390,6 @@ int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 input) | |||
359 | goto out; | 390 | goto out; |
360 | } | 391 | } |
361 | 392 | ||
362 | data = (high_data << 8) | low_data; | ||
363 | /* Disable GPADC */ | 393 | /* Disable GPADC */ |
364 | ret = abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC, | 394 | ret = abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC, |
365 | AB8500_GPADC_CTRL1_REG, DIS_GPADC); | 395 | AB8500_GPADC_CTRL1_REG, DIS_GPADC); |
@@ -370,8 +400,8 @@ int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 input) | |||
370 | /* Disable VTVout LDO this is required for GPADC */ | 400 | /* Disable VTVout LDO this is required for GPADC */ |
371 | regulator_disable(gpadc->regu); | 401 | regulator_disable(gpadc->regu); |
372 | mutex_unlock(&gpadc->ab8500_gpadc_lock); | 402 | mutex_unlock(&gpadc->ab8500_gpadc_lock); |
373 | ret = ab8500_gpadc_ad_to_voltage(gpadc, input, data); | 403 | |
374 | return ret; | 404 | return (high_data << 8) | low_data; |
375 | 405 | ||
376 | out: | 406 | out: |
377 | /* | 407 | /* |
@@ -385,10 +415,10 @@ out: | |||
385 | regulator_disable(gpadc->regu); | 415 | regulator_disable(gpadc->regu); |
386 | mutex_unlock(&gpadc->ab8500_gpadc_lock); | 416 | mutex_unlock(&gpadc->ab8500_gpadc_lock); |
387 | dev_err(gpadc->dev, | 417 | dev_err(gpadc->dev, |
388 | "gpadc_conversion: Failed to AD convert channel %d\n", input); | 418 | "gpadc_conversion: Failed to AD convert channel %d\n", channel); |
389 | return ret; | 419 | return ret; |
390 | } | 420 | } |
391 | EXPORT_SYMBOL(ab8500_gpadc_convert); | 421 | EXPORT_SYMBOL(ab8500_gpadc_read_raw); |
392 | 422 | ||
393 | /** | 423 | /** |
394 | * ab8500_bm_gpswadcconvend_handler() - isr for s/w gpadc conversion completion | 424 | * ab8500_bm_gpswadcconvend_handler() - isr for s/w gpadc conversion completion |
diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c index 7d5497388a30..b85bbd7f0d19 100644 --- a/drivers/mfd/asic3.c +++ b/drivers/mfd/asic3.c | |||
@@ -585,7 +585,7 @@ static int asic3_gpio_remove(struct platform_device *pdev) | |||
585 | return gpiochip_remove(&asic->gpio); | 585 | return gpiochip_remove(&asic->gpio); |
586 | } | 586 | } |
587 | 587 | ||
588 | static int asic3_clk_enable(struct asic3 *asic, struct asic3_clk *clk) | 588 | static void asic3_clk_enable(struct asic3 *asic, struct asic3_clk *clk) |
589 | { | 589 | { |
590 | unsigned long flags; | 590 | unsigned long flags; |
591 | u32 cdex; | 591 | u32 cdex; |
@@ -597,8 +597,6 @@ static int asic3_clk_enable(struct asic3 *asic, struct asic3_clk *clk) | |||
597 | asic3_write_register(asic, ASIC3_OFFSET(CLOCK, CDEX), cdex); | 597 | asic3_write_register(asic, ASIC3_OFFSET(CLOCK, CDEX), cdex); |
598 | } | 598 | } |
599 | spin_unlock_irqrestore(&asic->lock, flags); | 599 | spin_unlock_irqrestore(&asic->lock, flags); |
600 | |||
601 | return 0; | ||
602 | } | 600 | } |
603 | 601 | ||
604 | static void asic3_clk_disable(struct asic3 *asic, struct asic3_clk *clk) | 602 | static void asic3_clk_disable(struct asic3 *asic, struct asic3_clk *clk) |
@@ -780,6 +778,8 @@ static struct mfd_cell asic3_cell_mmc = { | |||
780 | .name = "tmio-mmc", | 778 | .name = "tmio-mmc", |
781 | .enable = asic3_mmc_enable, | 779 | .enable = asic3_mmc_enable, |
782 | .disable = asic3_mmc_disable, | 780 | .disable = asic3_mmc_disable, |
781 | .suspend = asic3_mmc_disable, | ||
782 | .resume = asic3_mmc_enable, | ||
783 | .platform_data = &asic3_mmc_data, | 783 | .platform_data = &asic3_mmc_data, |
784 | .pdata_size = sizeof(asic3_mmc_data), | 784 | .pdata_size = sizeof(asic3_mmc_data), |
785 | .num_resources = ARRAY_SIZE(asic3_mmc_resources), | 785 | .num_resources = ARRAY_SIZE(asic3_mmc_resources), |
@@ -812,24 +812,43 @@ static int asic3_leds_disable(struct platform_device *pdev) | |||
812 | return 0; | 812 | return 0; |
813 | } | 813 | } |
814 | 814 | ||
815 | static int asic3_leds_suspend(struct platform_device *pdev) | ||
816 | { | ||
817 | const struct mfd_cell *cell = mfd_get_cell(pdev); | ||
818 | struct asic3 *asic = dev_get_drvdata(pdev->dev.parent); | ||
819 | |||
820 | while (asic3_gpio_get(&asic->gpio, ASIC3_GPIO(C, cell->id)) != 0) | ||
821 | msleep(1); | ||
822 | |||
823 | asic3_clk_disable(asic, &asic->clocks[clock_ledn[cell->id]]); | ||
824 | |||
825 | return 0; | ||
826 | } | ||
827 | |||
815 | static struct mfd_cell asic3_cell_leds[ASIC3_NUM_LEDS] = { | 828 | static struct mfd_cell asic3_cell_leds[ASIC3_NUM_LEDS] = { |
816 | [0] = { | 829 | [0] = { |
817 | .name = "leds-asic3", | 830 | .name = "leds-asic3", |
818 | .id = 0, | 831 | .id = 0, |
819 | .enable = asic3_leds_enable, | 832 | .enable = asic3_leds_enable, |
820 | .disable = asic3_leds_disable, | 833 | .disable = asic3_leds_disable, |
834 | .suspend = asic3_leds_suspend, | ||
835 | .resume = asic3_leds_enable, | ||
821 | }, | 836 | }, |
822 | [1] = { | 837 | [1] = { |
823 | .name = "leds-asic3", | 838 | .name = "leds-asic3", |
824 | .id = 1, | 839 | .id = 1, |
825 | .enable = asic3_leds_enable, | 840 | .enable = asic3_leds_enable, |
826 | .disable = asic3_leds_disable, | 841 | .disable = asic3_leds_disable, |
842 | .suspend = asic3_leds_suspend, | ||
843 | .resume = asic3_leds_enable, | ||
827 | }, | 844 | }, |
828 | [2] = { | 845 | [2] = { |
829 | .name = "leds-asic3", | 846 | .name = "leds-asic3", |
830 | .id = 2, | 847 | .id = 2, |
831 | .enable = asic3_leds_enable, | 848 | .enable = asic3_leds_enable, |
832 | .disable = asic3_leds_disable, | 849 | .disable = asic3_leds_disable, |
850 | .suspend = asic3_leds_suspend, | ||
851 | .resume = asic3_leds_enable, | ||
833 | }, | 852 | }, |
834 | }; | 853 | }; |
835 | 854 | ||
@@ -950,6 +969,7 @@ static int __init asic3_probe(struct platform_device *pdev) | |||
950 | goto out_unmap; | 969 | goto out_unmap; |
951 | } | 970 | } |
952 | 971 | ||
972 | asic->gpio.label = "asic3"; | ||
953 | asic->gpio.base = pdata->gpio_base; | 973 | asic->gpio.base = pdata->gpio_base; |
954 | asic->gpio.ngpio = ASIC3_NUM_GPIOS; | 974 | asic->gpio.ngpio = ASIC3_NUM_GPIOS; |
955 | asic->gpio.get = asic3_gpio_get; | 975 | asic->gpio.get = asic3_gpio_get; |
diff --git a/drivers/mfd/da903x.c b/drivers/mfd/da903x.c index 2fadbaeb1cb1..1b79c37fd599 100644 --- a/drivers/mfd/da903x.c +++ b/drivers/mfd/da903x.c | |||
@@ -523,7 +523,7 @@ static int __devinit da903x_probe(struct i2c_client *client, | |||
523 | chip->ops->read_events(chip, &tmp); | 523 | chip->ops->read_events(chip, &tmp); |
524 | 524 | ||
525 | ret = request_irq(client->irq, da903x_irq_handler, | 525 | ret = request_irq(client->irq, da903x_irq_handler, |
526 | IRQF_DISABLED | IRQF_TRIGGER_FALLING, | 526 | IRQF_TRIGGER_FALLING, |
527 | "da903x", chip); | 527 | "da903x", chip); |
528 | if (ret) { | 528 | if (ret) { |
529 | dev_err(&client->dev, "failed to request irq %d\n", | 529 | dev_err(&client->dev, "failed to request irq %d\n", |
diff --git a/drivers/mfd/db5500-prcmu.c b/drivers/mfd/db5500-prcmu.c index 9dbb3cab4a6f..bb115b2f04e9 100644 --- a/drivers/mfd/db5500-prcmu.c +++ b/drivers/mfd/db5500-prcmu.c | |||
@@ -20,11 +20,11 @@ | |||
20 | #include <linux/jiffies.h> | 20 | #include <linux/jiffies.h> |
21 | #include <linux/bitops.h> | 21 | #include <linux/bitops.h> |
22 | #include <linux/interrupt.h> | 22 | #include <linux/interrupt.h> |
23 | #include <linux/mfd/db5500-prcmu.h> | 23 | #include <linux/mfd/dbx500-prcmu.h> |
24 | #include <mach/hardware.h> | 24 | #include <mach/hardware.h> |
25 | #include <mach/irqs.h> | 25 | #include <mach/irqs.h> |
26 | #include <mach/db5500-regs.h> | 26 | #include <mach/db5500-regs.h> |
27 | #include "db5500-prcmu-regs.h" | 27 | #include "dbx500-prcmu-regs.h" |
28 | 28 | ||
29 | #define _PRCM_MB_HEADER (tcdm_base + 0xFE8) | 29 | #define _PRCM_MB_HEADER (tcdm_base + 0xFE8) |
30 | #define PRCM_REQ_MB0_HEADER (_PRCM_MB_HEADER + 0x0) | 30 | #define PRCM_REQ_MB0_HEADER (_PRCM_MB_HEADER + 0x0) |
@@ -109,15 +109,18 @@ enum mb5_header { | |||
109 | #define PRCMU_DSI_CLOCK_SETTING 0x00000128 | 109 | #define PRCMU_DSI_CLOCK_SETTING 0x00000128 |
110 | /* TVCLK_MGT PLLSW=001 (PLLSOC0) PLLDIV=0x13, = 19.05 MHZ */ | 110 | /* TVCLK_MGT PLLSW=001 (PLLSOC0) PLLDIV=0x13, = 19.05 MHZ */ |
111 | #define PRCMU_DSI_LP_CLOCK_SETTING 0x00000135 | 111 | #define PRCMU_DSI_LP_CLOCK_SETTING 0x00000135 |
112 | #define PRCMU_PLLDSI_FREQ_SETTING 0x0004013C | 112 | #define PRCMU_PLLDSI_FREQ_SETTING 0x00020121 |
113 | #define PRCMU_DSI_PLLOUT_SEL_SETTING 0x00000002 | 113 | #define PRCMU_DSI_PLLOUT_SEL_SETTING 0x00000002 |
114 | #define PRCMU_ENABLE_ESCAPE_CLOCK_DIV 0x03000101 | 114 | #define PRCMU_ENABLE_ESCAPE_CLOCK_DIV 0x03000201 |
115 | #define PRCMU_DISABLE_ESCAPE_CLOCK_DIV 0x00000101 | 115 | #define PRCMU_DISABLE_ESCAPE_CLOCK_DIV 0x00000101 |
116 | 116 | ||
117 | #define PRCMU_ENABLE_PLLDSI 0x00000001 | 117 | #define PRCMU_ENABLE_PLLDSI 0x00000001 |
118 | #define PRCMU_DISABLE_PLLDSI 0x00000000 | 118 | #define PRCMU_DISABLE_PLLDSI 0x00000000 |
119 | 119 | ||
120 | #define PRCMU_DSI_RESET_SW 0x00000003 | 120 | #define PRCMU_DSI_RESET_SW 0x00000003 |
121 | #define PRCMU_RESOUTN0_PIN 0x00000001 | ||
122 | #define PRCMU_RESOUTN1_PIN 0x00000002 | ||
123 | #define PRCMU_RESOUTN2_PIN 0x00000004 | ||
121 | 124 | ||
122 | #define PRCMU_PLLDSI_LOCKP_LOCKED 0x3 | 125 | #define PRCMU_PLLDSI_LOCKP_LOCKED 0x3 |
123 | 126 | ||
@@ -315,31 +318,31 @@ static bool read_mailbox_0(void) | |||
315 | r = false; | 318 | r = false; |
316 | break; | 319 | break; |
317 | } | 320 | } |
318 | writel(MBOX_BIT(0), PRCM_ARM_IT1_CLEAR); | 321 | writel(MBOX_BIT(0), PRCM_ARM_IT1_CLR); |
319 | return r; | 322 | return r; |
320 | } | 323 | } |
321 | 324 | ||
322 | static bool read_mailbox_1(void) | 325 | static bool read_mailbox_1(void) |
323 | { | 326 | { |
324 | writel(MBOX_BIT(1), PRCM_ARM_IT1_CLEAR); | 327 | writel(MBOX_BIT(1), PRCM_ARM_IT1_CLR); |
325 | return false; | 328 | return false; |
326 | } | 329 | } |
327 | 330 | ||
328 | static bool read_mailbox_2(void) | 331 | static bool read_mailbox_2(void) |
329 | { | 332 | { |
330 | writel(MBOX_BIT(2), PRCM_ARM_IT1_CLEAR); | 333 | writel(MBOX_BIT(2), PRCM_ARM_IT1_CLR); |
331 | return false; | 334 | return false; |
332 | } | 335 | } |
333 | 336 | ||
334 | static bool read_mailbox_3(void) | 337 | static bool read_mailbox_3(void) |
335 | { | 338 | { |
336 | writel(MBOX_BIT(3), PRCM_ARM_IT1_CLEAR); | 339 | writel(MBOX_BIT(3), PRCM_ARM_IT1_CLR); |
337 | return false; | 340 | return false; |
338 | } | 341 | } |
339 | 342 | ||
340 | static bool read_mailbox_4(void) | 343 | static bool read_mailbox_4(void) |
341 | { | 344 | { |
342 | writel(MBOX_BIT(4), PRCM_ARM_IT1_CLEAR); | 345 | writel(MBOX_BIT(4), PRCM_ARM_IT1_CLR); |
343 | return false; | 346 | return false; |
344 | } | 347 | } |
345 | 348 | ||
@@ -360,19 +363,19 @@ static bool read_mailbox_5(void) | |||
360 | print_unknown_header_warning(5, header); | 363 | print_unknown_header_warning(5, header); |
361 | break; | 364 | break; |
362 | } | 365 | } |
363 | writel(MBOX_BIT(5), PRCM_ARM_IT1_CLEAR); | 366 | writel(MBOX_BIT(5), PRCM_ARM_IT1_CLR); |
364 | return false; | 367 | return false; |
365 | } | 368 | } |
366 | 369 | ||
367 | static bool read_mailbox_6(void) | 370 | static bool read_mailbox_6(void) |
368 | { | 371 | { |
369 | writel(MBOX_BIT(6), PRCM_ARM_IT1_CLEAR); | 372 | writel(MBOX_BIT(6), PRCM_ARM_IT1_CLR); |
370 | return false; | 373 | return false; |
371 | } | 374 | } |
372 | 375 | ||
373 | static bool read_mailbox_7(void) | 376 | static bool read_mailbox_7(void) |
374 | { | 377 | { |
375 | writel(MBOX_BIT(7), PRCM_ARM_IT1_CLEAR); | 378 | writel(MBOX_BIT(7), PRCM_ARM_IT1_CLR); |
376 | return false; | 379 | return false; |
377 | } | 380 | } |
378 | 381 | ||
@@ -434,7 +437,7 @@ int __init db5500_prcmu_init(void) | |||
434 | return -ENODEV; | 437 | return -ENODEV; |
435 | 438 | ||
436 | /* Clean up the mailbox interrupts after pre-kernel code. */ | 439 | /* Clean up the mailbox interrupts after pre-kernel code. */ |
437 | writel(ALL_MBOX_BITS, PRCM_ARM_IT1_CLEAR); | 440 | writel(ALL_MBOX_BITS, PRCM_ARM_IT1_CLR); |
438 | 441 | ||
439 | r = request_threaded_irq(IRQ_DB5500_PRCMU1, prcmu_irq_handler, | 442 | r = request_threaded_irq(IRQ_DB5500_PRCMU1, prcmu_irq_handler, |
440 | prcmu_irq_thread_fn, 0, "prcmu", NULL); | 443 | prcmu_irq_thread_fn, 0, "prcmu", NULL); |
diff --git a/drivers/mfd/db8500-prcmu-regs.h b/drivers/mfd/db8500-prcmu-regs.h deleted file mode 100644 index 3bbf04d58043..000000000000 --- a/drivers/mfd/db8500-prcmu-regs.h +++ /dev/null | |||
@@ -1,166 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) STMicroelectronics 2009 | ||
3 | * Copyright (C) ST-Ericsson SA 2010 | ||
4 | * | ||
5 | * Author: Kumar Sanghvi <kumar.sanghvi@stericsson.com> | ||
6 | * Author: Sundar Iyer <sundar.iyer@stericsson.com> | ||
7 | * | ||
8 | * License Terms: GNU General Public License v2 | ||
9 | * | ||
10 | * PRCM Unit registers | ||
11 | */ | ||
12 | #ifndef __DB8500_PRCMU_REGS_H | ||
13 | #define __DB8500_PRCMU_REGS_H | ||
14 | |||
15 | #include <linux/bitops.h> | ||
16 | #include <mach/hardware.h> | ||
17 | |||
18 | #define BITS(_start, _end) ((BIT(_end) - BIT(_start)) + BIT(_end)) | ||
19 | |||
20 | #define PRCM_ARM_PLLDIVPS 0x118 | ||
21 | #define PRCM_ARM_PLLDIVPS_ARM_BRM_RATE BITS(0, 5) | ||
22 | #define PRCM_ARM_PLLDIVPS_MAX_MASK 0xF | ||
23 | |||
24 | #define PRCM_PLLARM_LOCKP 0x0A8 | ||
25 | #define PRCM_PLLARM_LOCKP_PRCM_PLLARM_LOCKP3 BIT(1) | ||
26 | |||
27 | #define PRCM_ARM_CHGCLKREQ 0x114 | ||
28 | #define PRCM_ARM_CHGCLKREQ_PRCM_ARM_CHGCLKREQ BIT(0) | ||
29 | |||
30 | #define PRCM_PLLARM_ENABLE 0x98 | ||
31 | #define PRCM_PLLARM_ENABLE_PRCM_PLLARM_ENABLE BIT(0) | ||
32 | #define PRCM_PLLARM_ENABLE_PRCM_PLLARM_COUNTON BIT(8) | ||
33 | |||
34 | #define PRCM_ARMCLKFIX_MGT 0x0 | ||
35 | #define PRCM_A9_RESETN_CLR 0x1f4 | ||
36 | #define PRCM_A9_RESETN_SET 0x1f0 | ||
37 | #define PRCM_ARM_LS_CLAMP 0x30C | ||
38 | #define PRCM_SRAM_A9 0x308 | ||
39 | |||
40 | /* ARM WFI Standby signal register */ | ||
41 | #define PRCM_ARM_WFI_STANDBY 0x130 | ||
42 | #define PRCM_IOCR 0x310 | ||
43 | #define PRCM_IOCR_IOFORCE BIT(0) | ||
44 | |||
45 | /* CPU mailbox registers */ | ||
46 | #define PRCM_MBOX_CPU_VAL 0x0FC | ||
47 | #define PRCM_MBOX_CPU_SET 0x100 | ||
48 | |||
49 | /* Dual A9 core interrupt management unit registers */ | ||
50 | #define PRCM_A9_MASK_REQ 0x328 | ||
51 | #define PRCM_A9_MASK_REQ_PRCM_A9_MASK_REQ BIT(0) | ||
52 | |||
53 | #define PRCM_A9_MASK_ACK 0x32C | ||
54 | #define PRCM_ARMITMSK31TO0 0x11C | ||
55 | #define PRCM_ARMITMSK63TO32 0x120 | ||
56 | #define PRCM_ARMITMSK95TO64 0x124 | ||
57 | #define PRCM_ARMITMSK127TO96 0x128 | ||
58 | #define PRCM_POWER_STATE_VAL 0x25C | ||
59 | #define PRCM_ARMITVAL31TO0 0x260 | ||
60 | #define PRCM_ARMITVAL63TO32 0x264 | ||
61 | #define PRCM_ARMITVAL95TO64 0x268 | ||
62 | #define PRCM_ARMITVAL127TO96 0x26C | ||
63 | |||
64 | #define PRCM_HOSTACCESS_REQ 0x334 | ||
65 | #define PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ BIT(0) | ||
66 | |||
67 | #define PRCM_ARM_IT1_CLR 0x48C | ||
68 | #define PRCM_ARM_IT1_VAL 0x494 | ||
69 | |||
70 | #define PRCM_ITSTATUS0 0x148 | ||
71 | #define PRCM_ITSTATUS1 0x150 | ||
72 | #define PRCM_ITSTATUS2 0x158 | ||
73 | #define PRCM_ITSTATUS3 0x160 | ||
74 | #define PRCM_ITSTATUS4 0x168 | ||
75 | #define PRCM_ITSTATUS5 0x484 | ||
76 | #define PRCM_ITCLEAR5 0x488 | ||
77 | #define PRCM_ARMIT_MASKXP70_IT 0x1018 | ||
78 | |||
79 | /* System reset register */ | ||
80 | #define PRCM_APE_SOFTRST 0x228 | ||
81 | |||
82 | /* Level shifter and clamp control registers */ | ||
83 | #define PRCM_MMIP_LS_CLAMP_SET 0x420 | ||
84 | #define PRCM_MMIP_LS_CLAMP_CLR 0x424 | ||
85 | |||
86 | /* PRCMU HW semaphore */ | ||
87 | #define PRCM_SEM 0x400 | ||
88 | #define PRCM_SEM_PRCM_SEM BIT(0) | ||
89 | |||
90 | /* PRCMU clock/PLL/reset registers */ | ||
91 | #define PRCM_PLLDSI_FREQ 0x500 | ||
92 | #define PRCM_PLLDSI_ENABLE 0x504 | ||
93 | #define PRCM_PLLDSI_LOCKP 0x508 | ||
94 | #define PRCM_DSI_PLLOUT_SEL 0x530 | ||
95 | #define PRCM_DSITVCLK_DIV 0x52C | ||
96 | #define PRCM_APE_RESETN_SET 0x1E4 | ||
97 | #define PRCM_APE_RESETN_CLR 0x1E8 | ||
98 | |||
99 | #define PRCM_TCR 0x1C8 | ||
100 | #define PRCM_TCR_TENSEL_MASK BITS(0, 7) | ||
101 | #define PRCM_TCR_STOP_TIMERS BIT(16) | ||
102 | #define PRCM_TCR_DOZE_MODE BIT(17) | ||
103 | |||
104 | #define PRCM_CLKOCR 0x1CC | ||
105 | #define PRCM_CLKOCR_CLKODIV0_SHIFT 0 | ||
106 | #define PRCM_CLKOCR_CLKODIV0_MASK BITS(0, 5) | ||
107 | #define PRCM_CLKOCR_CLKOSEL0_SHIFT 6 | ||
108 | #define PRCM_CLKOCR_CLKOSEL0_MASK BITS(6, 8) | ||
109 | #define PRCM_CLKOCR_CLKODIV1_SHIFT 16 | ||
110 | #define PRCM_CLKOCR_CLKODIV1_MASK BITS(16, 21) | ||
111 | #define PRCM_CLKOCR_CLKOSEL1_SHIFT 22 | ||
112 | #define PRCM_CLKOCR_CLKOSEL1_MASK BITS(22, 24) | ||
113 | #define PRCM_CLKOCR_CLK1TYPE BIT(28) | ||
114 | |||
115 | #define PRCM_SGACLK_MGT 0x014 | ||
116 | #define PRCM_UARTCLK_MGT 0x018 | ||
117 | #define PRCM_MSP02CLK_MGT 0x01C | ||
118 | #define PRCM_MSP1CLK_MGT 0x288 | ||
119 | #define PRCM_I2CCLK_MGT 0x020 | ||
120 | #define PRCM_SDMMCCLK_MGT 0x024 | ||
121 | #define PRCM_SLIMCLK_MGT 0x028 | ||
122 | #define PRCM_PER1CLK_MGT 0x02C | ||
123 | #define PRCM_PER2CLK_MGT 0x030 | ||
124 | #define PRCM_PER3CLK_MGT 0x034 | ||
125 | #define PRCM_PER5CLK_MGT 0x038 | ||
126 | #define PRCM_PER6CLK_MGT 0x03C | ||
127 | #define PRCM_PER7CLK_MGT 0x040 | ||
128 | #define PRCM_LCDCLK_MGT 0x044 | ||
129 | #define PRCM_BMLCLK_MGT 0x04C | ||
130 | #define PRCM_HSITXCLK_MGT 0x050 | ||
131 | #define PRCM_HSIRXCLK_MGT 0x054 | ||
132 | #define PRCM_HDMICLK_MGT 0x058 | ||
133 | #define PRCM_APEATCLK_MGT 0x05C | ||
134 | #define PRCM_APETRACECLK_MGT 0x060 | ||
135 | #define PRCM_MCDECLK_MGT 0x064 | ||
136 | #define PRCM_IPI2CCLK_MGT 0x068 | ||
137 | #define PRCM_DSIALTCLK_MGT 0x06C | ||
138 | #define PRCM_DMACLK_MGT 0x074 | ||
139 | #define PRCM_B2R2CLK_MGT 0x078 | ||
140 | #define PRCM_TVCLK_MGT 0x07C | ||
141 | #define PRCM_UNIPROCLK_MGT 0x278 | ||
142 | #define PRCM_SSPCLK_MGT 0x280 | ||
143 | #define PRCM_RNGCLK_MGT 0x284 | ||
144 | #define PRCM_UICCCLK_MGT 0x27C | ||
145 | |||
146 | #define PRCM_CLK_MGT_CLKPLLDIV_MASK BITS(0, 4) | ||
147 | #define PRCM_CLK_MGT_CLKPLLSW_MASK BITS(5, 7) | ||
148 | #define PRCM_CLK_MGT_CLKEN BIT(8) | ||
149 | |||
150 | /* ePOD and memory power signal control registers */ | ||
151 | #define PRCM_EPOD_C_SET 0x410 | ||
152 | #define PRCM_SRAM_LS_SLEEP 0x304 | ||
153 | |||
154 | /* Debug power control unit registers */ | ||
155 | #define PRCM_POWER_STATE_SET 0x254 | ||
156 | |||
157 | /* Miscellaneous unit registers */ | ||
158 | #define PRCM_DSI_SW_RESET 0x324 | ||
159 | #define PRCM_GPIOCR 0x138 | ||
160 | |||
161 | /* GPIOCR register */ | ||
162 | #define PRCM_GPIOCR_SPI2_SELECT BIT(23) | ||
163 | |||
164 | #define PRCM_DDR_SUBSYS_APE_MINBW 0x438 | ||
165 | |||
166 | #endif /* __DB8500_PRCMU_REGS_H */ | ||
diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index 02a15d7cb3b0..a25ab9c6b5af 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c | |||
@@ -27,14 +27,14 @@ | |||
27 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
28 | #include <linux/uaccess.h> | 28 | #include <linux/uaccess.h> |
29 | #include <linux/mfd/core.h> | 29 | #include <linux/mfd/core.h> |
30 | #include <linux/mfd/db8500-prcmu.h> | 30 | #include <linux/mfd/dbx500-prcmu.h> |
31 | #include <linux/regulator/db8500-prcmu.h> | 31 | #include <linux/regulator/db8500-prcmu.h> |
32 | #include <linux/regulator/machine.h> | 32 | #include <linux/regulator/machine.h> |
33 | #include <mach/hardware.h> | 33 | #include <mach/hardware.h> |
34 | #include <mach/irqs.h> | 34 | #include <mach/irqs.h> |
35 | #include <mach/db8500-regs.h> | 35 | #include <mach/db8500-regs.h> |
36 | #include <mach/id.h> | 36 | #include <mach/id.h> |
37 | #include "db8500-prcmu-regs.h" | 37 | #include "dbx500-prcmu-regs.h" |
38 | 38 | ||
39 | /* Offset for the firmware version within the TCPM */ | 39 | /* Offset for the firmware version within the TCPM */ |
40 | #define PRCMU_FW_VERSION_OFFSET 0xA4 | 40 | #define PRCMU_FW_VERSION_OFFSET 0xA4 |
@@ -131,12 +131,14 @@ | |||
131 | #define MB1H_REQUEST_APE_OPP_100_VOLT 0x3 | 131 | #define MB1H_REQUEST_APE_OPP_100_VOLT 0x3 |
132 | #define MB1H_RELEASE_APE_OPP_100_VOLT 0x4 | 132 | #define MB1H_RELEASE_APE_OPP_100_VOLT 0x4 |
133 | #define MB1H_RELEASE_USB_WAKEUP 0x5 | 133 | #define MB1H_RELEASE_USB_WAKEUP 0x5 |
134 | #define MB1H_PLL_ON_OFF 0x6 | ||
134 | 135 | ||
135 | /* Mailbox 1 Requests */ | 136 | /* Mailbox 1 Requests */ |
136 | #define PRCM_REQ_MB1_ARM_OPP (PRCM_REQ_MB1 + 0x0) | 137 | #define PRCM_REQ_MB1_ARM_OPP (PRCM_REQ_MB1 + 0x0) |
137 | #define PRCM_REQ_MB1_APE_OPP (PRCM_REQ_MB1 + 0x1) | 138 | #define PRCM_REQ_MB1_APE_OPP (PRCM_REQ_MB1 + 0x1) |
138 | #define PRCM_REQ_MB1_APE_OPP_100_RESTORE (PRCM_REQ_MB1 + 0x4) | 139 | #define PRCM_REQ_MB1_PLL_ON_OFF (PRCM_REQ_MB1 + 0x4) |
139 | #define PRCM_REQ_MB1_ARM_OPP_100_RESTORE (PRCM_REQ_MB1 + 0x8) | 140 | #define PLL_SOC1_OFF 0x4 |
141 | #define PLL_SOC1_ON 0x8 | ||
140 | 142 | ||
141 | /* Mailbox 1 ACKs */ | 143 | /* Mailbox 1 ACKs */ |
142 | #define PRCM_ACK_MB1_CURRENT_ARM_OPP (PRCM_ACK_MB1 + 0x0) | 144 | #define PRCM_ACK_MB1_CURRENT_ARM_OPP (PRCM_ACK_MB1 + 0x0) |
@@ -184,6 +186,11 @@ | |||
184 | #define MB4H_HOTDOG 0x12 | 186 | #define MB4H_HOTDOG 0x12 |
185 | #define MB4H_HOTMON 0x13 | 187 | #define MB4H_HOTMON 0x13 |
186 | #define MB4H_HOT_PERIOD 0x14 | 188 | #define MB4H_HOT_PERIOD 0x14 |
189 | #define MB4H_A9WDOG_CONF 0x16 | ||
190 | #define MB4H_A9WDOG_EN 0x17 | ||
191 | #define MB4H_A9WDOG_DIS 0x18 | ||
192 | #define MB4H_A9WDOG_LOAD 0x19 | ||
193 | #define MB4H_A9WDOG_KICK 0x20 | ||
187 | 194 | ||
188 | /* Mailbox 4 Requests */ | 195 | /* Mailbox 4 Requests */ |
189 | #define PRCM_REQ_MB4_DDR_ST_AP_SLEEP_IDLE (PRCM_REQ_MB4 + 0x0) | 196 | #define PRCM_REQ_MB4_DDR_ST_AP_SLEEP_IDLE (PRCM_REQ_MB4 + 0x0) |
@@ -196,6 +203,13 @@ | |||
196 | #define PRCM_REQ_MB4_HOT_PERIOD (PRCM_REQ_MB4 + 0x0) | 203 | #define PRCM_REQ_MB4_HOT_PERIOD (PRCM_REQ_MB4 + 0x0) |
197 | #define HOTMON_CONFIG_LOW BIT(0) | 204 | #define HOTMON_CONFIG_LOW BIT(0) |
198 | #define HOTMON_CONFIG_HIGH BIT(1) | 205 | #define HOTMON_CONFIG_HIGH BIT(1) |
206 | #define PRCM_REQ_MB4_A9WDOG_0 (PRCM_REQ_MB4 + 0x0) | ||
207 | #define PRCM_REQ_MB4_A9WDOG_1 (PRCM_REQ_MB4 + 0x1) | ||
208 | #define PRCM_REQ_MB4_A9WDOG_2 (PRCM_REQ_MB4 + 0x2) | ||
209 | #define PRCM_REQ_MB4_A9WDOG_3 (PRCM_REQ_MB4 + 0x3) | ||
210 | #define A9WDOG_AUTO_OFF_EN BIT(7) | ||
211 | #define A9WDOG_AUTO_OFF_DIS 0 | ||
212 | #define A9WDOG_ID_MASK 0xf | ||
199 | 213 | ||
200 | /* Mailbox 5 Requests */ | 214 | /* Mailbox 5 Requests */ |
201 | #define PRCM_REQ_MB5_I2C_SLAVE_OP (PRCM_REQ_MB5 + 0x0) | 215 | #define PRCM_REQ_MB5_I2C_SLAVE_OP (PRCM_REQ_MB5 + 0x0) |
@@ -412,7 +426,7 @@ struct clk_mgt { | |||
412 | 426 | ||
413 | static DEFINE_SPINLOCK(clk_mgt_lock); | 427 | static DEFINE_SPINLOCK(clk_mgt_lock); |
414 | 428 | ||
415 | #define CLK_MGT_ENTRY(_name)[PRCMU_##_name] = { (PRCM_##_name##_MGT), 0 } | 429 | #define CLK_MGT_ENTRY(_name)[PRCMU_##_name] = { (PRCM_##_name##_MGT_OFF), 0 } |
416 | struct clk_mgt clk_mgt[PRCMU_NUM_REG_CLOCKS] = { | 430 | struct clk_mgt clk_mgt[PRCMU_NUM_REG_CLOCKS] = { |
417 | CLK_MGT_ENTRY(SGACLK), | 431 | CLK_MGT_ENTRY(SGACLK), |
418 | CLK_MGT_ENTRY(UARTCLK), | 432 | CLK_MGT_ENTRY(UARTCLK), |
@@ -445,6 +459,35 @@ struct clk_mgt clk_mgt[PRCMU_NUM_REG_CLOCKS] = { | |||
445 | CLK_MGT_ENTRY(UICCCLK), | 459 | CLK_MGT_ENTRY(UICCCLK), |
446 | }; | 460 | }; |
447 | 461 | ||
462 | static struct regulator *hwacc_regulator[NUM_HW_ACC]; | ||
463 | static struct regulator *hwacc_ret_regulator[NUM_HW_ACC]; | ||
464 | |||
465 | static bool hwacc_enabled[NUM_HW_ACC]; | ||
466 | static bool hwacc_ret_enabled[NUM_HW_ACC]; | ||
467 | |||
468 | static const char *hwacc_regulator_name[NUM_HW_ACC] = { | ||
469 | [HW_ACC_SVAMMDSP] = "hwacc-sva-mmdsp", | ||
470 | [HW_ACC_SVAPIPE] = "hwacc-sva-pipe", | ||
471 | [HW_ACC_SIAMMDSP] = "hwacc-sia-mmdsp", | ||
472 | [HW_ACC_SIAPIPE] = "hwacc-sia-pipe", | ||
473 | [HW_ACC_SGA] = "hwacc-sga", | ||
474 | [HW_ACC_B2R2] = "hwacc-b2r2", | ||
475 | [HW_ACC_MCDE] = "hwacc-mcde", | ||
476 | [HW_ACC_ESRAM1] = "hwacc-esram1", | ||
477 | [HW_ACC_ESRAM2] = "hwacc-esram2", | ||
478 | [HW_ACC_ESRAM3] = "hwacc-esram3", | ||
479 | [HW_ACC_ESRAM4] = "hwacc-esram4", | ||
480 | }; | ||
481 | |||
482 | static const char *hwacc_ret_regulator_name[NUM_HW_ACC] = { | ||
483 | [HW_ACC_SVAMMDSP] = "hwacc-sva-mmdsp-ret", | ||
484 | [HW_ACC_SIAMMDSP] = "hwacc-sia-mmdsp-ret", | ||
485 | [HW_ACC_ESRAM1] = "hwacc-esram1-ret", | ||
486 | [HW_ACC_ESRAM2] = "hwacc-esram2-ret", | ||
487 | [HW_ACC_ESRAM3] = "hwacc-esram3-ret", | ||
488 | [HW_ACC_ESRAM4] = "hwacc-esram4-ret", | ||
489 | }; | ||
490 | |||
448 | /* | 491 | /* |
449 | * Used by MCDE to setup all necessary PRCMU registers | 492 | * Used by MCDE to setup all necessary PRCMU registers |
450 | */ | 493 | */ |
@@ -493,55 +536,51 @@ static struct { | |||
493 | } prcmu_version; | 536 | } prcmu_version; |
494 | 537 | ||
495 | 538 | ||
496 | int prcmu_enable_dsipll(void) | 539 | int db8500_prcmu_enable_dsipll(void) |
497 | { | 540 | { |
498 | int i; | 541 | int i; |
499 | unsigned int plldsifreq; | 542 | unsigned int plldsifreq; |
500 | 543 | ||
501 | /* Clear DSIPLL_RESETN */ | 544 | /* Clear DSIPLL_RESETN */ |
502 | writel(PRCMU_RESET_DSIPLL, (_PRCMU_BASE + PRCM_APE_RESETN_CLR)); | 545 | writel(PRCMU_RESET_DSIPLL, PRCM_APE_RESETN_CLR); |
503 | /* Unclamp DSIPLL in/out */ | 546 | /* Unclamp DSIPLL in/out */ |
504 | writel(PRCMU_UNCLAMP_DSIPLL, (_PRCMU_BASE + PRCM_MMIP_LS_CLAMP_CLR)); | 547 | writel(PRCMU_UNCLAMP_DSIPLL, PRCM_MMIP_LS_CLAMP_CLR); |
505 | 548 | ||
506 | if (prcmu_is_u8400()) | 549 | if (prcmu_is_u8400()) |
507 | plldsifreq = PRCMU_PLLDSI_FREQ_SETTING_U8400; | 550 | plldsifreq = PRCMU_PLLDSI_FREQ_SETTING_U8400; |
508 | else | 551 | else |
509 | plldsifreq = PRCMU_PLLDSI_FREQ_SETTING; | 552 | plldsifreq = PRCMU_PLLDSI_FREQ_SETTING; |
510 | /* Set DSI PLL FREQ */ | 553 | /* Set DSI PLL FREQ */ |
511 | writel(plldsifreq, (_PRCMU_BASE + PRCM_PLLDSI_FREQ)); | 554 | writel(plldsifreq, PRCM_PLLDSI_FREQ); |
512 | writel(PRCMU_DSI_PLLOUT_SEL_SETTING, | 555 | writel(PRCMU_DSI_PLLOUT_SEL_SETTING, PRCM_DSI_PLLOUT_SEL); |
513 | (_PRCMU_BASE + PRCM_DSI_PLLOUT_SEL)); | ||
514 | /* Enable Escape clocks */ | 556 | /* Enable Escape clocks */ |
515 | writel(PRCMU_ENABLE_ESCAPE_CLOCK_DIV, | 557 | writel(PRCMU_ENABLE_ESCAPE_CLOCK_DIV, PRCM_DSITVCLK_DIV); |
516 | (_PRCMU_BASE + PRCM_DSITVCLK_DIV)); | ||
517 | 558 | ||
518 | /* Start DSI PLL */ | 559 | /* Start DSI PLL */ |
519 | writel(PRCMU_ENABLE_PLLDSI, (_PRCMU_BASE + PRCM_PLLDSI_ENABLE)); | 560 | writel(PRCMU_ENABLE_PLLDSI, PRCM_PLLDSI_ENABLE); |
520 | /* Reset DSI PLL */ | 561 | /* Reset DSI PLL */ |
521 | writel(PRCMU_DSI_RESET_SW, (_PRCMU_BASE + PRCM_DSI_SW_RESET)); | 562 | writel(PRCMU_DSI_RESET_SW, PRCM_DSI_SW_RESET); |
522 | for (i = 0; i < 10; i++) { | 563 | for (i = 0; i < 10; i++) { |
523 | if ((readl(_PRCMU_BASE + PRCM_PLLDSI_LOCKP) & | 564 | if ((readl(PRCM_PLLDSI_LOCKP) & PRCMU_PLLDSI_LOCKP_LOCKED) |
524 | PRCMU_PLLDSI_LOCKP_LOCKED) | ||
525 | == PRCMU_PLLDSI_LOCKP_LOCKED) | 565 | == PRCMU_PLLDSI_LOCKP_LOCKED) |
526 | break; | 566 | break; |
527 | udelay(100); | 567 | udelay(100); |
528 | } | 568 | } |
529 | /* Set DSIPLL_RESETN */ | 569 | /* Set DSIPLL_RESETN */ |
530 | writel(PRCMU_RESET_DSIPLL, (_PRCMU_BASE + PRCM_APE_RESETN_SET)); | 570 | writel(PRCMU_RESET_DSIPLL, PRCM_APE_RESETN_SET); |
531 | return 0; | 571 | return 0; |
532 | } | 572 | } |
533 | 573 | ||
534 | int prcmu_disable_dsipll(void) | 574 | int db8500_prcmu_disable_dsipll(void) |
535 | { | 575 | { |
536 | /* Disable dsi pll */ | 576 | /* Disable dsi pll */ |
537 | writel(PRCMU_DISABLE_PLLDSI, (_PRCMU_BASE + PRCM_PLLDSI_ENABLE)); | 577 | writel(PRCMU_DISABLE_PLLDSI, PRCM_PLLDSI_ENABLE); |
538 | /* Disable escapeclock */ | 578 | /* Disable escapeclock */ |
539 | writel(PRCMU_DISABLE_ESCAPE_CLOCK_DIV, | 579 | writel(PRCMU_DISABLE_ESCAPE_CLOCK_DIV, PRCM_DSITVCLK_DIV); |
540 | (_PRCMU_BASE + PRCM_DSITVCLK_DIV)); | ||
541 | return 0; | 580 | return 0; |
542 | } | 581 | } |
543 | 582 | ||
544 | int prcmu_set_display_clocks(void) | 583 | int db8500_prcmu_set_display_clocks(void) |
545 | { | 584 | { |
546 | unsigned long flags; | 585 | unsigned long flags; |
547 | unsigned int dsiclk; | 586 | unsigned int dsiclk; |
@@ -554,15 +593,15 @@ int prcmu_set_display_clocks(void) | |||
554 | spin_lock_irqsave(&clk_mgt_lock, flags); | 593 | spin_lock_irqsave(&clk_mgt_lock, flags); |
555 | 594 | ||
556 | /* Grab the HW semaphore. */ | 595 | /* Grab the HW semaphore. */ |
557 | while ((readl(_PRCMU_BASE + PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) | 596 | while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) |
558 | cpu_relax(); | 597 | cpu_relax(); |
559 | 598 | ||
560 | writel(dsiclk, (_PRCMU_BASE + PRCM_HDMICLK_MGT)); | 599 | writel(dsiclk, PRCM_HDMICLK_MGT); |
561 | writel(PRCMU_DSI_LP_CLOCK_SETTING, (_PRCMU_BASE + PRCM_TVCLK_MGT)); | 600 | writel(PRCMU_DSI_LP_CLOCK_SETTING, PRCM_TVCLK_MGT); |
562 | writel(PRCMU_DPI_CLOCK_SETTING, (_PRCMU_BASE + PRCM_LCDCLK_MGT)); | 601 | writel(PRCMU_DPI_CLOCK_SETTING, PRCM_LCDCLK_MGT); |
563 | 602 | ||
564 | /* Release the HW semaphore. */ | 603 | /* Release the HW semaphore. */ |
565 | writel(0, (_PRCMU_BASE + PRCM_SEM)); | 604 | writel(0, PRCM_SEM); |
566 | 605 | ||
567 | spin_unlock_irqrestore(&clk_mgt_lock, flags); | 606 | spin_unlock_irqrestore(&clk_mgt_lock, flags); |
568 | 607 | ||
@@ -578,8 +617,8 @@ void prcmu_enable_spi2(void) | |||
578 | unsigned long flags; | 617 | unsigned long flags; |
579 | 618 | ||
580 | spin_lock_irqsave(&gpiocr_lock, flags); | 619 | spin_lock_irqsave(&gpiocr_lock, flags); |
581 | reg = readl(_PRCMU_BASE + PRCM_GPIOCR); | 620 | reg = readl(PRCM_GPIOCR); |
582 | writel(reg | PRCM_GPIOCR_SPI2_SELECT, _PRCMU_BASE + PRCM_GPIOCR); | 621 | writel(reg | PRCM_GPIOCR_SPI2_SELECT, PRCM_GPIOCR); |
583 | spin_unlock_irqrestore(&gpiocr_lock, flags); | 622 | spin_unlock_irqrestore(&gpiocr_lock, flags); |
584 | } | 623 | } |
585 | 624 | ||
@@ -592,8 +631,8 @@ void prcmu_disable_spi2(void) | |||
592 | unsigned long flags; | 631 | unsigned long flags; |
593 | 632 | ||
594 | spin_lock_irqsave(&gpiocr_lock, flags); | 633 | spin_lock_irqsave(&gpiocr_lock, flags); |
595 | reg = readl(_PRCMU_BASE + PRCM_GPIOCR); | 634 | reg = readl(PRCM_GPIOCR); |
596 | writel(reg & ~PRCM_GPIOCR_SPI2_SELECT, _PRCMU_BASE + PRCM_GPIOCR); | 635 | writel(reg & ~PRCM_GPIOCR_SPI2_SELECT, PRCM_GPIOCR); |
597 | spin_unlock_irqrestore(&gpiocr_lock, flags); | 636 | spin_unlock_irqrestore(&gpiocr_lock, flags); |
598 | } | 637 | } |
599 | 638 | ||
@@ -701,7 +740,7 @@ int prcmu_config_clkout(u8 clkout, u8 source, u8 div) | |||
701 | 740 | ||
702 | spin_lock_irqsave(&clkout_lock, flags); | 741 | spin_lock_irqsave(&clkout_lock, flags); |
703 | 742 | ||
704 | val = readl(_PRCMU_BASE + PRCM_CLKOCR); | 743 | val = readl(PRCM_CLKOCR); |
705 | if (val & div_mask) { | 744 | if (val & div_mask) { |
706 | if (div) { | 745 | if (div) { |
707 | if ((val & mask) != bits) { | 746 | if ((val & mask) != bits) { |
@@ -715,7 +754,7 @@ int prcmu_config_clkout(u8 clkout, u8 source, u8 div) | |||
715 | } | 754 | } |
716 | } | 755 | } |
717 | } | 756 | } |
718 | writel((bits | (val & ~mask)), (_PRCMU_BASE + PRCM_CLKOCR)); | 757 | writel((bits | (val & ~mask)), PRCM_CLKOCR); |
719 | requests[clkout] += (div ? 1 : -1); | 758 | requests[clkout] += (div ? 1 : -1); |
720 | 759 | ||
721 | unlock_and_return: | 760 | unlock_and_return: |
@@ -724,7 +763,7 @@ unlock_and_return: | |||
724 | return r; | 763 | return r; |
725 | } | 764 | } |
726 | 765 | ||
727 | int prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll) | 766 | int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll) |
728 | { | 767 | { |
729 | unsigned long flags; | 768 | unsigned long flags; |
730 | 769 | ||
@@ -732,7 +771,7 @@ int prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll) | |||
732 | 771 | ||
733 | spin_lock_irqsave(&mb0_transfer.lock, flags); | 772 | spin_lock_irqsave(&mb0_transfer.lock, flags); |
734 | 773 | ||
735 | while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(0)) | 774 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(0)) |
736 | cpu_relax(); | 775 | cpu_relax(); |
737 | 776 | ||
738 | writeb(MB0H_POWER_STATE_TRANS, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB0)); | 777 | writeb(MB0H_POWER_STATE_TRANS, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB0)); |
@@ -741,7 +780,7 @@ int prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll) | |||
741 | writeb((keep_ulp_clk ? 1 : 0), | 780 | writeb((keep_ulp_clk ? 1 : 0), |
742 | (tcdm_base + PRCM_REQ_MB0_ULP_CLOCK_STATE)); | 781 | (tcdm_base + PRCM_REQ_MB0_ULP_CLOCK_STATE)); |
743 | writeb(0, (tcdm_base + PRCM_REQ_MB0_DO_NOT_WFI)); | 782 | writeb(0, (tcdm_base + PRCM_REQ_MB0_DO_NOT_WFI)); |
744 | writel(MBOX_BIT(0), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); | 783 | writel(MBOX_BIT(0), PRCM_MBOX_CPU_SET); |
745 | 784 | ||
746 | spin_unlock_irqrestore(&mb0_transfer.lock, flags); | 785 | spin_unlock_irqrestore(&mb0_transfer.lock, flags); |
747 | 786 | ||
@@ -770,18 +809,18 @@ static void config_wakeups(void) | |||
770 | return; | 809 | return; |
771 | 810 | ||
772 | for (i = 0; i < 2; i++) { | 811 | for (i = 0; i < 2; i++) { |
773 | while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(0)) | 812 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(0)) |
774 | cpu_relax(); | 813 | cpu_relax(); |
775 | writel(dbb_events, (tcdm_base + PRCM_REQ_MB0_WAKEUP_8500)); | 814 | writel(dbb_events, (tcdm_base + PRCM_REQ_MB0_WAKEUP_8500)); |
776 | writel(abb_events, (tcdm_base + PRCM_REQ_MB0_WAKEUP_4500)); | 815 | writel(abb_events, (tcdm_base + PRCM_REQ_MB0_WAKEUP_4500)); |
777 | writeb(header[i], (tcdm_base + PRCM_MBOX_HEADER_REQ_MB0)); | 816 | writeb(header[i], (tcdm_base + PRCM_MBOX_HEADER_REQ_MB0)); |
778 | writel(MBOX_BIT(0), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); | 817 | writel(MBOX_BIT(0), PRCM_MBOX_CPU_SET); |
779 | } | 818 | } |
780 | last_dbb_events = dbb_events; | 819 | last_dbb_events = dbb_events; |
781 | last_abb_events = abb_events; | 820 | last_abb_events = abb_events; |
782 | } | 821 | } |
783 | 822 | ||
784 | void prcmu_enable_wakeups(u32 wakeups) | 823 | void db8500_prcmu_enable_wakeups(u32 wakeups) |
785 | { | 824 | { |
786 | unsigned long flags; | 825 | unsigned long flags; |
787 | u32 bits; | 826 | u32 bits; |
@@ -802,7 +841,7 @@ void prcmu_enable_wakeups(u32 wakeups) | |||
802 | spin_unlock_irqrestore(&mb0_transfer.lock, flags); | 841 | spin_unlock_irqrestore(&mb0_transfer.lock, flags); |
803 | } | 842 | } |
804 | 843 | ||
805 | void prcmu_config_abb_event_readout(u32 abb_events) | 844 | void db8500_prcmu_config_abb_event_readout(u32 abb_events) |
806 | { | 845 | { |
807 | unsigned long flags; | 846 | unsigned long flags; |
808 | 847 | ||
@@ -814,7 +853,7 @@ void prcmu_config_abb_event_readout(u32 abb_events) | |||
814 | spin_unlock_irqrestore(&mb0_transfer.lock, flags); | 853 | spin_unlock_irqrestore(&mb0_transfer.lock, flags); |
815 | } | 854 | } |
816 | 855 | ||
817 | void prcmu_get_abb_event_buffer(void __iomem **buf) | 856 | void db8500_prcmu_get_abb_event_buffer(void __iomem **buf) |
818 | { | 857 | { |
819 | if (readb(tcdm_base + PRCM_ACK_MB0_READ_POINTER) & 1) | 858 | if (readb(tcdm_base + PRCM_ACK_MB0_READ_POINTER) & 1) |
820 | *buf = (tcdm_base + PRCM_ACK_MB0_WAKEUP_1_4500); | 859 | *buf = (tcdm_base + PRCM_ACK_MB0_WAKEUP_1_4500); |
@@ -823,13 +862,13 @@ void prcmu_get_abb_event_buffer(void __iomem **buf) | |||
823 | } | 862 | } |
824 | 863 | ||
825 | /** | 864 | /** |
826 | * prcmu_set_arm_opp - set the appropriate ARM OPP | 865 | * db8500_prcmu_set_arm_opp - set the appropriate ARM OPP |
827 | * @opp: The new ARM operating point to which transition is to be made | 866 | * @opp: The new ARM operating point to which transition is to be made |
828 | * Returns: 0 on success, non-zero on failure | 867 | * Returns: 0 on success, non-zero on failure |
829 | * | 868 | * |
830 | * This function sets the the operating point of the ARM. | 869 | * This function sets the the operating point of the ARM. |
831 | */ | 870 | */ |
832 | int prcmu_set_arm_opp(u8 opp) | 871 | int db8500_prcmu_set_arm_opp(u8 opp) |
833 | { | 872 | { |
834 | int r; | 873 | int r; |
835 | 874 | ||
@@ -840,14 +879,14 @@ int prcmu_set_arm_opp(u8 opp) | |||
840 | 879 | ||
841 | mutex_lock(&mb1_transfer.lock); | 880 | mutex_lock(&mb1_transfer.lock); |
842 | 881 | ||
843 | while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) | 882 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) |
844 | cpu_relax(); | 883 | cpu_relax(); |
845 | 884 | ||
846 | writeb(MB1H_ARM_APE_OPP, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); | 885 | writeb(MB1H_ARM_APE_OPP, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); |
847 | writeb(opp, (tcdm_base + PRCM_REQ_MB1_ARM_OPP)); | 886 | writeb(opp, (tcdm_base + PRCM_REQ_MB1_ARM_OPP)); |
848 | writeb(APE_NO_CHANGE, (tcdm_base + PRCM_REQ_MB1_APE_OPP)); | 887 | writeb(APE_NO_CHANGE, (tcdm_base + PRCM_REQ_MB1_APE_OPP)); |
849 | 888 | ||
850 | writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); | 889 | writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET); |
851 | wait_for_completion(&mb1_transfer.work); | 890 | wait_for_completion(&mb1_transfer.work); |
852 | 891 | ||
853 | if ((mb1_transfer.ack.header != MB1H_ARM_APE_OPP) || | 892 | if ((mb1_transfer.ack.header != MB1H_ARM_APE_OPP) || |
@@ -860,11 +899,11 @@ int prcmu_set_arm_opp(u8 opp) | |||
860 | } | 899 | } |
861 | 900 | ||
862 | /** | 901 | /** |
863 | * prcmu_get_arm_opp - get the current ARM OPP | 902 | * db8500_prcmu_get_arm_opp - get the current ARM OPP |
864 | * | 903 | * |
865 | * Returns: the current ARM OPP | 904 | * Returns: the current ARM OPP |
866 | */ | 905 | */ |
867 | int prcmu_get_arm_opp(void) | 906 | int db8500_prcmu_get_arm_opp(void) |
868 | { | 907 | { |
869 | return readb(tcdm_base + PRCM_ACK_MB1_CURRENT_ARM_OPP); | 908 | return readb(tcdm_base + PRCM_ACK_MB1_CURRENT_ARM_OPP); |
870 | } | 909 | } |
@@ -876,7 +915,7 @@ int prcmu_get_arm_opp(void) | |||
876 | */ | 915 | */ |
877 | int prcmu_get_ddr_opp(void) | 916 | int prcmu_get_ddr_opp(void) |
878 | { | 917 | { |
879 | return readb(_PRCMU_BASE + PRCM_DDR_SUBSYS_APE_MINBW); | 918 | return readb(PRCM_DDR_SUBSYS_APE_MINBW); |
880 | } | 919 | } |
881 | 920 | ||
882 | /** | 921 | /** |
@@ -892,7 +931,7 @@ int prcmu_set_ddr_opp(u8 opp) | |||
892 | return -EINVAL; | 931 | return -EINVAL; |
893 | /* Changing the DDR OPP can hang the hardware pre-v21 */ | 932 | /* Changing the DDR OPP can hang the hardware pre-v21 */ |
894 | if (cpu_is_u8500v20_or_later() && !cpu_is_u8500v20()) | 933 | if (cpu_is_u8500v20_or_later() && !cpu_is_u8500v20()) |
895 | writeb(opp, (_PRCMU_BASE + PRCM_DDR_SUBSYS_APE_MINBW)); | 934 | writeb(opp, PRCM_DDR_SUBSYS_APE_MINBW); |
896 | 935 | ||
897 | return 0; | 936 | return 0; |
898 | } | 937 | } |
@@ -909,14 +948,14 @@ int prcmu_set_ape_opp(u8 opp) | |||
909 | 948 | ||
910 | mutex_lock(&mb1_transfer.lock); | 949 | mutex_lock(&mb1_transfer.lock); |
911 | 950 | ||
912 | while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) | 951 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) |
913 | cpu_relax(); | 952 | cpu_relax(); |
914 | 953 | ||
915 | writeb(MB1H_ARM_APE_OPP, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); | 954 | writeb(MB1H_ARM_APE_OPP, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); |
916 | writeb(ARM_NO_CHANGE, (tcdm_base + PRCM_REQ_MB1_ARM_OPP)); | 955 | writeb(ARM_NO_CHANGE, (tcdm_base + PRCM_REQ_MB1_ARM_OPP)); |
917 | writeb(opp, (tcdm_base + PRCM_REQ_MB1_APE_OPP)); | 956 | writeb(opp, (tcdm_base + PRCM_REQ_MB1_APE_OPP)); |
918 | 957 | ||
919 | writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); | 958 | writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET); |
920 | wait_for_completion(&mb1_transfer.work); | 959 | wait_for_completion(&mb1_transfer.work); |
921 | 960 | ||
922 | if ((mb1_transfer.ack.header != MB1H_ARM_APE_OPP) || | 961 | if ((mb1_transfer.ack.header != MB1H_ARM_APE_OPP) || |
@@ -966,12 +1005,12 @@ int prcmu_request_ape_opp_100_voltage(bool enable) | |||
966 | header = MB1H_RELEASE_APE_OPP_100_VOLT; | 1005 | header = MB1H_RELEASE_APE_OPP_100_VOLT; |
967 | } | 1006 | } |
968 | 1007 | ||
969 | while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) | 1008 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) |
970 | cpu_relax(); | 1009 | cpu_relax(); |
971 | 1010 | ||
972 | writeb(header, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); | 1011 | writeb(header, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); |
973 | 1012 | ||
974 | writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); | 1013 | writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET); |
975 | wait_for_completion(&mb1_transfer.work); | 1014 | wait_for_completion(&mb1_transfer.work); |
976 | 1015 | ||
977 | if ((mb1_transfer.ack.header != header) || | 1016 | if ((mb1_transfer.ack.header != header) || |
@@ -995,13 +1034,13 @@ int prcmu_release_usb_wakeup_state(void) | |||
995 | 1034 | ||
996 | mutex_lock(&mb1_transfer.lock); | 1035 | mutex_lock(&mb1_transfer.lock); |
997 | 1036 | ||
998 | while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) | 1037 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) |
999 | cpu_relax(); | 1038 | cpu_relax(); |
1000 | 1039 | ||
1001 | writeb(MB1H_RELEASE_USB_WAKEUP, | 1040 | writeb(MB1H_RELEASE_USB_WAKEUP, |
1002 | (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); | 1041 | (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); |
1003 | 1042 | ||
1004 | writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); | 1043 | writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET); |
1005 | wait_for_completion(&mb1_transfer.work); | 1044 | wait_for_completion(&mb1_transfer.work); |
1006 | 1045 | ||
1007 | if ((mb1_transfer.ack.header != MB1H_RELEASE_USB_WAKEUP) || | 1046 | if ((mb1_transfer.ack.header != MB1H_RELEASE_USB_WAKEUP) || |
@@ -1013,15 +1052,169 @@ int prcmu_release_usb_wakeup_state(void) | |||
1013 | return r; | 1052 | return r; |
1014 | } | 1053 | } |
1015 | 1054 | ||
1055 | static int request_pll(u8 clock, bool enable) | ||
1056 | { | ||
1057 | int r = 0; | ||
1058 | |||
1059 | if (clock == PRCMU_PLLSOC1) | ||
1060 | clock = (enable ? PLL_SOC1_ON : PLL_SOC1_OFF); | ||
1061 | else | ||
1062 | return -EINVAL; | ||
1063 | |||
1064 | mutex_lock(&mb1_transfer.lock); | ||
1065 | |||
1066 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) | ||
1067 | cpu_relax(); | ||
1068 | |||
1069 | writeb(MB1H_PLL_ON_OFF, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); | ||
1070 | writeb(clock, (tcdm_base + PRCM_REQ_MB1_PLL_ON_OFF)); | ||
1071 | |||
1072 | writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET); | ||
1073 | wait_for_completion(&mb1_transfer.work); | ||
1074 | |||
1075 | if (mb1_transfer.ack.header != MB1H_PLL_ON_OFF) | ||
1076 | r = -EIO; | ||
1077 | |||
1078 | mutex_unlock(&mb1_transfer.lock); | ||
1079 | |||
1080 | return r; | ||
1081 | } | ||
1082 | |||
1016 | /** | 1083 | /** |
1017 | * prcmu_set_epod - set the state of a EPOD (power domain) | 1084 | * prcmu_set_hwacc - set the power state of a h/w accelerator |
1085 | * @hwacc_dev: The hardware accelerator (enum hw_acc_dev). | ||
1086 | * @state: The new power state (enum hw_acc_state). | ||
1087 | * | ||
1088 | * This function sets the power state of a hardware accelerator. | ||
1089 | * This function should not be called from interrupt context. | ||
1090 | * | ||
1091 | * NOTE! Deprecated, to be removed when all users switched over to use the | ||
1092 | * regulator framework API. | ||
1093 | */ | ||
1094 | int prcmu_set_hwacc(u16 hwacc_dev, u8 state) | ||
1095 | { | ||
1096 | int r = 0; | ||
1097 | bool ram_retention = false; | ||
1098 | bool enable, enable_ret; | ||
1099 | |||
1100 | /* check argument */ | ||
1101 | BUG_ON(hwacc_dev >= NUM_HW_ACC); | ||
1102 | |||
1103 | /* get state of switches */ | ||
1104 | enable = hwacc_enabled[hwacc_dev]; | ||
1105 | enable_ret = hwacc_ret_enabled[hwacc_dev]; | ||
1106 | |||
1107 | /* set flag if retention is possible */ | ||
1108 | switch (hwacc_dev) { | ||
1109 | case HW_ACC_SVAMMDSP: | ||
1110 | case HW_ACC_SIAMMDSP: | ||
1111 | case HW_ACC_ESRAM1: | ||
1112 | case HW_ACC_ESRAM2: | ||
1113 | case HW_ACC_ESRAM3: | ||
1114 | case HW_ACC_ESRAM4: | ||
1115 | ram_retention = true; | ||
1116 | break; | ||
1117 | } | ||
1118 | |||
1119 | /* check argument */ | ||
1120 | BUG_ON(state > HW_ON); | ||
1121 | BUG_ON(state == HW_OFF_RAMRET && !ram_retention); | ||
1122 | |||
1123 | /* modify enable flags */ | ||
1124 | switch (state) { | ||
1125 | case HW_OFF: | ||
1126 | enable_ret = false; | ||
1127 | enable = false; | ||
1128 | break; | ||
1129 | case HW_ON: | ||
1130 | enable = true; | ||
1131 | break; | ||
1132 | case HW_OFF_RAMRET: | ||
1133 | enable_ret = true; | ||
1134 | enable = false; | ||
1135 | break; | ||
1136 | } | ||
1137 | |||
1138 | /* get regulator (lazy) */ | ||
1139 | if (hwacc_regulator[hwacc_dev] == NULL) { | ||
1140 | hwacc_regulator[hwacc_dev] = regulator_get(NULL, | ||
1141 | hwacc_regulator_name[hwacc_dev]); | ||
1142 | if (IS_ERR(hwacc_regulator[hwacc_dev])) { | ||
1143 | pr_err("prcmu: failed to get supply %s\n", | ||
1144 | hwacc_regulator_name[hwacc_dev]); | ||
1145 | r = PTR_ERR(hwacc_regulator[hwacc_dev]); | ||
1146 | goto out; | ||
1147 | } | ||
1148 | } | ||
1149 | |||
1150 | if (ram_retention) { | ||
1151 | if (hwacc_ret_regulator[hwacc_dev] == NULL) { | ||
1152 | hwacc_ret_regulator[hwacc_dev] = regulator_get(NULL, | ||
1153 | hwacc_ret_regulator_name[hwacc_dev]); | ||
1154 | if (IS_ERR(hwacc_ret_regulator[hwacc_dev])) { | ||
1155 | pr_err("prcmu: failed to get supply %s\n", | ||
1156 | hwacc_ret_regulator_name[hwacc_dev]); | ||
1157 | r = PTR_ERR(hwacc_ret_regulator[hwacc_dev]); | ||
1158 | goto out; | ||
1159 | } | ||
1160 | } | ||
1161 | } | ||
1162 | |||
1163 | /* set regulators */ | ||
1164 | if (ram_retention) { | ||
1165 | if (enable_ret && !hwacc_ret_enabled[hwacc_dev]) { | ||
1166 | r = regulator_enable(hwacc_ret_regulator[hwacc_dev]); | ||
1167 | if (r < 0) { | ||
1168 | pr_err("prcmu_set_hwacc: ret enable failed\n"); | ||
1169 | goto out; | ||
1170 | } | ||
1171 | hwacc_ret_enabled[hwacc_dev] = true; | ||
1172 | } | ||
1173 | } | ||
1174 | |||
1175 | if (enable && !hwacc_enabled[hwacc_dev]) { | ||
1176 | r = regulator_enable(hwacc_regulator[hwacc_dev]); | ||
1177 | if (r < 0) { | ||
1178 | pr_err("prcmu_set_hwacc: enable failed\n"); | ||
1179 | goto out; | ||
1180 | } | ||
1181 | hwacc_enabled[hwacc_dev] = true; | ||
1182 | } | ||
1183 | |||
1184 | if (!enable && hwacc_enabled[hwacc_dev]) { | ||
1185 | r = regulator_disable(hwacc_regulator[hwacc_dev]); | ||
1186 | if (r < 0) { | ||
1187 | pr_err("prcmu_set_hwacc: disable failed\n"); | ||
1188 | goto out; | ||
1189 | } | ||
1190 | hwacc_enabled[hwacc_dev] = false; | ||
1191 | } | ||
1192 | |||
1193 | if (ram_retention) { | ||
1194 | if (!enable_ret && hwacc_ret_enabled[hwacc_dev]) { | ||
1195 | r = regulator_disable(hwacc_ret_regulator[hwacc_dev]); | ||
1196 | if (r < 0) { | ||
1197 | pr_err("prcmu_set_hwacc: ret disable failed\n"); | ||
1198 | goto out; | ||
1199 | } | ||
1200 | hwacc_ret_enabled[hwacc_dev] = false; | ||
1201 | } | ||
1202 | } | ||
1203 | |||
1204 | out: | ||
1205 | return r; | ||
1206 | } | ||
1207 | EXPORT_SYMBOL(prcmu_set_hwacc); | ||
1208 | |||
1209 | /** | ||
1210 | * db8500_prcmu_set_epod - set the state of a EPOD (power domain) | ||
1018 | * @epod_id: The EPOD to set | 1211 | * @epod_id: The EPOD to set |
1019 | * @epod_state: The new EPOD state | 1212 | * @epod_state: The new EPOD state |
1020 | * | 1213 | * |
1021 | * This function sets the state of a EPOD (power domain). It may not be called | 1214 | * This function sets the state of a EPOD (power domain). It may not be called |
1022 | * from interrupt context. | 1215 | * from interrupt context. |
1023 | */ | 1216 | */ |
1024 | int prcmu_set_epod(u16 epod_id, u8 epod_state) | 1217 | int db8500_prcmu_set_epod(u16 epod_id, u8 epod_state) |
1025 | { | 1218 | { |
1026 | int r = 0; | 1219 | int r = 0; |
1027 | bool ram_retention = false; | 1220 | bool ram_retention = false; |
@@ -1048,7 +1241,7 @@ int prcmu_set_epod(u16 epod_id, u8 epod_state) | |||
1048 | mutex_lock(&mb2_transfer.lock); | 1241 | mutex_lock(&mb2_transfer.lock); |
1049 | 1242 | ||
1050 | /* wait for mailbox */ | 1243 | /* wait for mailbox */ |
1051 | while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(2)) | 1244 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(2)) |
1052 | cpu_relax(); | 1245 | cpu_relax(); |
1053 | 1246 | ||
1054 | /* fill in mailbox */ | 1247 | /* fill in mailbox */ |
@@ -1058,7 +1251,7 @@ int prcmu_set_epod(u16 epod_id, u8 epod_state) | |||
1058 | 1251 | ||
1059 | writeb(MB2H_DPS, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB2)); | 1252 | writeb(MB2H_DPS, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB2)); |
1060 | 1253 | ||
1061 | writel(MBOX_BIT(2), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); | 1254 | writel(MBOX_BIT(2), PRCM_MBOX_CPU_SET); |
1062 | 1255 | ||
1063 | /* | 1256 | /* |
1064 | * The current firmware version does not handle errors correctly, | 1257 | * The current firmware version does not handle errors correctly, |
@@ -1145,13 +1338,13 @@ static int request_sysclk(bool enable) | |||
1145 | 1338 | ||
1146 | spin_lock_irqsave(&mb3_transfer.lock, flags); | 1339 | spin_lock_irqsave(&mb3_transfer.lock, flags); |
1147 | 1340 | ||
1148 | while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(3)) | 1341 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(3)) |
1149 | cpu_relax(); | 1342 | cpu_relax(); |
1150 | 1343 | ||
1151 | writeb((enable ? ON : OFF), (tcdm_base + PRCM_REQ_MB3_SYSCLK_MGT)); | 1344 | writeb((enable ? ON : OFF), (tcdm_base + PRCM_REQ_MB3_SYSCLK_MGT)); |
1152 | 1345 | ||
1153 | writeb(MB3H_SYSCLK, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB3)); | 1346 | writeb(MB3H_SYSCLK, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB3)); |
1154 | writel(MBOX_BIT(3), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); | 1347 | writel(MBOX_BIT(3), PRCM_MBOX_CPU_SET); |
1155 | 1348 | ||
1156 | spin_unlock_irqrestore(&mb3_transfer.lock, flags); | 1349 | spin_unlock_irqrestore(&mb3_transfer.lock, flags); |
1157 | 1350 | ||
@@ -1177,7 +1370,7 @@ static int request_timclk(bool enable) | |||
1177 | 1370 | ||
1178 | if (!enable) | 1371 | if (!enable) |
1179 | val |= PRCM_TCR_STOP_TIMERS; | 1372 | val |= PRCM_TCR_STOP_TIMERS; |
1180 | writel(val, (_PRCMU_BASE + PRCM_TCR)); | 1373 | writel(val, PRCM_TCR); |
1181 | 1374 | ||
1182 | return 0; | 1375 | return 0; |
1183 | } | 1376 | } |
@@ -1190,7 +1383,7 @@ static int request_reg_clock(u8 clock, bool enable) | |||
1190 | spin_lock_irqsave(&clk_mgt_lock, flags); | 1383 | spin_lock_irqsave(&clk_mgt_lock, flags); |
1191 | 1384 | ||
1192 | /* Grab the HW semaphore. */ | 1385 | /* Grab the HW semaphore. */ |
1193 | while ((readl(_PRCMU_BASE + PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) | 1386 | while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) |
1194 | cpu_relax(); | 1387 | cpu_relax(); |
1195 | 1388 | ||
1196 | val = readl(_PRCMU_BASE + clk_mgt[clock].offset); | 1389 | val = readl(_PRCMU_BASE + clk_mgt[clock].offset); |
@@ -1203,34 +1396,61 @@ static int request_reg_clock(u8 clock, bool enable) | |||
1203 | writel(val, (_PRCMU_BASE + clk_mgt[clock].offset)); | 1396 | writel(val, (_PRCMU_BASE + clk_mgt[clock].offset)); |
1204 | 1397 | ||
1205 | /* Release the HW semaphore. */ | 1398 | /* Release the HW semaphore. */ |
1206 | writel(0, (_PRCMU_BASE + PRCM_SEM)); | 1399 | writel(0, PRCM_SEM); |
1207 | 1400 | ||
1208 | spin_unlock_irqrestore(&clk_mgt_lock, flags); | 1401 | spin_unlock_irqrestore(&clk_mgt_lock, flags); |
1209 | 1402 | ||
1210 | return 0; | 1403 | return 0; |
1211 | } | 1404 | } |
1212 | 1405 | ||
1406 | static int request_sga_clock(u8 clock, bool enable) | ||
1407 | { | ||
1408 | u32 val; | ||
1409 | int ret; | ||
1410 | |||
1411 | if (enable) { | ||
1412 | val = readl(PRCM_CGATING_BYPASS); | ||
1413 | writel(val | PRCM_CGATING_BYPASS_ICN2, PRCM_CGATING_BYPASS); | ||
1414 | } | ||
1415 | |||
1416 | ret = request_reg_clock(clock, enable); | ||
1417 | |||
1418 | if (!ret && !enable) { | ||
1419 | val = readl(PRCM_CGATING_BYPASS); | ||
1420 | writel(val & ~PRCM_CGATING_BYPASS_ICN2, PRCM_CGATING_BYPASS); | ||
1421 | } | ||
1422 | |||
1423 | return ret; | ||
1424 | } | ||
1425 | |||
1213 | /** | 1426 | /** |
1214 | * prcmu_request_clock() - Request for a clock to be enabled or disabled. | 1427 | * db8500_prcmu_request_clock() - Request for a clock to be enabled or disabled. |
1215 | * @clock: The clock for which the request is made. | 1428 | * @clock: The clock for which the request is made. |
1216 | * @enable: Whether the clock should be enabled (true) or disabled (false). | 1429 | * @enable: Whether the clock should be enabled (true) or disabled (false). |
1217 | * | 1430 | * |
1218 | * This function should only be used by the clock implementation. | 1431 | * This function should only be used by the clock implementation. |
1219 | * Do not use it from any other place! | 1432 | * Do not use it from any other place! |
1220 | */ | 1433 | */ |
1221 | int prcmu_request_clock(u8 clock, bool enable) | 1434 | int db8500_prcmu_request_clock(u8 clock, bool enable) |
1222 | { | 1435 | { |
1223 | if (clock < PRCMU_NUM_REG_CLOCKS) | 1436 | switch(clock) { |
1224 | return request_reg_clock(clock, enable); | 1437 | case PRCMU_SGACLK: |
1225 | else if (clock == PRCMU_TIMCLK) | 1438 | return request_sga_clock(clock, enable); |
1439 | case PRCMU_TIMCLK: | ||
1226 | return request_timclk(enable); | 1440 | return request_timclk(enable); |
1227 | else if (clock == PRCMU_SYSCLK) | 1441 | case PRCMU_SYSCLK: |
1228 | return request_sysclk(enable); | 1442 | return request_sysclk(enable); |
1229 | else | 1443 | case PRCMU_PLLSOC1: |
1230 | return -EINVAL; | 1444 | return request_pll(clock, enable); |
1445 | default: | ||
1446 | break; | ||
1447 | } | ||
1448 | if (clock < PRCMU_NUM_REG_CLOCKS) | ||
1449 | return request_reg_clock(clock, enable); | ||
1450 | return -EINVAL; | ||
1231 | } | 1451 | } |
1232 | 1452 | ||
1233 | int prcmu_config_esram0_deep_sleep(u8 state) | 1453 | int db8500_prcmu_config_esram0_deep_sleep(u8 state) |
1234 | { | 1454 | { |
1235 | if ((state > ESRAM0_DEEP_SLEEP_STATE_RET) || | 1455 | if ((state > ESRAM0_DEEP_SLEEP_STATE_RET) || |
1236 | (state < ESRAM0_DEEP_SLEEP_STATE_OFF)) | 1456 | (state < ESRAM0_DEEP_SLEEP_STATE_OFF)) |
@@ -1238,7 +1458,7 @@ int prcmu_config_esram0_deep_sleep(u8 state) | |||
1238 | 1458 | ||
1239 | mutex_lock(&mb4_transfer.lock); | 1459 | mutex_lock(&mb4_transfer.lock); |
1240 | 1460 | ||
1241 | while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(4)) | 1461 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4)) |
1242 | cpu_relax(); | 1462 | cpu_relax(); |
1243 | 1463 | ||
1244 | writeb(MB4H_MEM_ST, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4)); | 1464 | writeb(MB4H_MEM_ST, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4)); |
@@ -1248,7 +1468,7 @@ int prcmu_config_esram0_deep_sleep(u8 state) | |||
1248 | (tcdm_base + PRCM_REQ_MB4_DDR_ST_AP_DEEP_IDLE)); | 1468 | (tcdm_base + PRCM_REQ_MB4_DDR_ST_AP_DEEP_IDLE)); |
1249 | writeb(state, (tcdm_base + PRCM_REQ_MB4_ESRAM0_ST)); | 1469 | writeb(state, (tcdm_base + PRCM_REQ_MB4_ESRAM0_ST)); |
1250 | 1470 | ||
1251 | writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); | 1471 | writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET); |
1252 | wait_for_completion(&mb4_transfer.work); | 1472 | wait_for_completion(&mb4_transfer.work); |
1253 | 1473 | ||
1254 | mutex_unlock(&mb4_transfer.lock); | 1474 | mutex_unlock(&mb4_transfer.lock); |
@@ -1260,13 +1480,13 @@ int prcmu_config_hotdog(u8 threshold) | |||
1260 | { | 1480 | { |
1261 | mutex_lock(&mb4_transfer.lock); | 1481 | mutex_lock(&mb4_transfer.lock); |
1262 | 1482 | ||
1263 | while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(4)) | 1483 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4)) |
1264 | cpu_relax(); | 1484 | cpu_relax(); |
1265 | 1485 | ||
1266 | writeb(threshold, (tcdm_base + PRCM_REQ_MB4_HOTDOG_THRESHOLD)); | 1486 | writeb(threshold, (tcdm_base + PRCM_REQ_MB4_HOTDOG_THRESHOLD)); |
1267 | writeb(MB4H_HOTDOG, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4)); | 1487 | writeb(MB4H_HOTDOG, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4)); |
1268 | 1488 | ||
1269 | writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); | 1489 | writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET); |
1270 | wait_for_completion(&mb4_transfer.work); | 1490 | wait_for_completion(&mb4_transfer.work); |
1271 | 1491 | ||
1272 | mutex_unlock(&mb4_transfer.lock); | 1492 | mutex_unlock(&mb4_transfer.lock); |
@@ -1278,7 +1498,7 @@ int prcmu_config_hotmon(u8 low, u8 high) | |||
1278 | { | 1498 | { |
1279 | mutex_lock(&mb4_transfer.lock); | 1499 | mutex_lock(&mb4_transfer.lock); |
1280 | 1500 | ||
1281 | while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(4)) | 1501 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4)) |
1282 | cpu_relax(); | 1502 | cpu_relax(); |
1283 | 1503 | ||
1284 | writeb(low, (tcdm_base + PRCM_REQ_MB4_HOTMON_LOW)); | 1504 | writeb(low, (tcdm_base + PRCM_REQ_MB4_HOTMON_LOW)); |
@@ -1287,7 +1507,7 @@ int prcmu_config_hotmon(u8 low, u8 high) | |||
1287 | (tcdm_base + PRCM_REQ_MB4_HOTMON_CONFIG)); | 1507 | (tcdm_base + PRCM_REQ_MB4_HOTMON_CONFIG)); |
1288 | writeb(MB4H_HOTMON, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4)); | 1508 | writeb(MB4H_HOTMON, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4)); |
1289 | 1509 | ||
1290 | writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); | 1510 | writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET); |
1291 | wait_for_completion(&mb4_transfer.work); | 1511 | wait_for_completion(&mb4_transfer.work); |
1292 | 1512 | ||
1293 | mutex_unlock(&mb4_transfer.lock); | 1513 | mutex_unlock(&mb4_transfer.lock); |
@@ -1299,13 +1519,13 @@ static int config_hot_period(u16 val) | |||
1299 | { | 1519 | { |
1300 | mutex_lock(&mb4_transfer.lock); | 1520 | mutex_lock(&mb4_transfer.lock); |
1301 | 1521 | ||
1302 | while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(4)) | 1522 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4)) |
1303 | cpu_relax(); | 1523 | cpu_relax(); |
1304 | 1524 | ||
1305 | writew(val, (tcdm_base + PRCM_REQ_MB4_HOT_PERIOD)); | 1525 | writew(val, (tcdm_base + PRCM_REQ_MB4_HOT_PERIOD)); |
1306 | writeb(MB4H_HOT_PERIOD, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4)); | 1526 | writeb(MB4H_HOT_PERIOD, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4)); |
1307 | 1527 | ||
1308 | writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); | 1528 | writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET); |
1309 | wait_for_completion(&mb4_transfer.work); | 1529 | wait_for_completion(&mb4_transfer.work); |
1310 | 1530 | ||
1311 | mutex_unlock(&mb4_transfer.lock); | 1531 | mutex_unlock(&mb4_transfer.lock); |
@@ -1326,6 +1546,78 @@ int prcmu_stop_temp_sense(void) | |||
1326 | return config_hot_period(0xFFFF); | 1546 | return config_hot_period(0xFFFF); |
1327 | } | 1547 | } |
1328 | 1548 | ||
1549 | static int prcmu_a9wdog(u8 cmd, u8 d0, u8 d1, u8 d2, u8 d3) | ||
1550 | { | ||
1551 | |||
1552 | mutex_lock(&mb4_transfer.lock); | ||
1553 | |||
1554 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4)) | ||
1555 | cpu_relax(); | ||
1556 | |||
1557 | writeb(d0, (tcdm_base + PRCM_REQ_MB4_A9WDOG_0)); | ||
1558 | writeb(d1, (tcdm_base + PRCM_REQ_MB4_A9WDOG_1)); | ||
1559 | writeb(d2, (tcdm_base + PRCM_REQ_MB4_A9WDOG_2)); | ||
1560 | writeb(d3, (tcdm_base + PRCM_REQ_MB4_A9WDOG_3)); | ||
1561 | |||
1562 | writeb(cmd, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4)); | ||
1563 | |||
1564 | writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET); | ||
1565 | wait_for_completion(&mb4_transfer.work); | ||
1566 | |||
1567 | mutex_unlock(&mb4_transfer.lock); | ||
1568 | |||
1569 | return 0; | ||
1570 | |||
1571 | } | ||
1572 | |||
1573 | int prcmu_config_a9wdog(u8 num, bool sleep_auto_off) | ||
1574 | { | ||
1575 | BUG_ON(num == 0 || num > 0xf); | ||
1576 | return prcmu_a9wdog(MB4H_A9WDOG_CONF, num, 0, 0, | ||
1577 | sleep_auto_off ? A9WDOG_AUTO_OFF_EN : | ||
1578 | A9WDOG_AUTO_OFF_DIS); | ||
1579 | } | ||
1580 | |||
1581 | int prcmu_enable_a9wdog(u8 id) | ||
1582 | { | ||
1583 | return prcmu_a9wdog(MB4H_A9WDOG_EN, id, 0, 0, 0); | ||
1584 | } | ||
1585 | |||
1586 | int prcmu_disable_a9wdog(u8 id) | ||
1587 | { | ||
1588 | return prcmu_a9wdog(MB4H_A9WDOG_DIS, id, 0, 0, 0); | ||
1589 | } | ||
1590 | |||
1591 | int prcmu_kick_a9wdog(u8 id) | ||
1592 | { | ||
1593 | return prcmu_a9wdog(MB4H_A9WDOG_KICK, id, 0, 0, 0); | ||
1594 | } | ||
1595 | |||
1596 | /* | ||
1597 | * timeout is 28 bit, in ms. | ||
1598 | */ | ||
1599 | #define MAX_WATCHDOG_TIMEOUT 131000 | ||
1600 | int prcmu_load_a9wdog(u8 id, u32 timeout) | ||
1601 | { | ||
1602 | if (timeout > MAX_WATCHDOG_TIMEOUT) | ||
1603 | /* | ||
1604 | * Due to calculation bug in prcmu fw, timeouts | ||
1605 | * can't be bigger than 131 seconds. | ||
1606 | */ | ||
1607 | return -EINVAL; | ||
1608 | |||
1609 | return prcmu_a9wdog(MB4H_A9WDOG_LOAD, | ||
1610 | (id & A9WDOG_ID_MASK) | | ||
1611 | /* | ||
1612 | * Put the lowest 28 bits of timeout at | ||
1613 | * offset 4. Four first bits are used for id. | ||
1614 | */ | ||
1615 | (u8)((timeout << 4) & 0xf0), | ||
1616 | (u8)((timeout >> 4) & 0xff), | ||
1617 | (u8)((timeout >> 12) & 0xff), | ||
1618 | (u8)((timeout >> 20) & 0xff)); | ||
1619 | } | ||
1620 | |||
1329 | /** | 1621 | /** |
1330 | * prcmu_set_clock_divider() - Configure the clock divider. | 1622 | * prcmu_set_clock_divider() - Configure the clock divider. |
1331 | * @clock: The clock for which the request is made. | 1623 | * @clock: The clock for which the request is made. |
@@ -1345,7 +1637,7 @@ int prcmu_set_clock_divider(u8 clock, u8 divider) | |||
1345 | spin_lock_irqsave(&clk_mgt_lock, flags); | 1637 | spin_lock_irqsave(&clk_mgt_lock, flags); |
1346 | 1638 | ||
1347 | /* Grab the HW semaphore. */ | 1639 | /* Grab the HW semaphore. */ |
1348 | while ((readl(_PRCMU_BASE + PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) | 1640 | while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) |
1349 | cpu_relax(); | 1641 | cpu_relax(); |
1350 | 1642 | ||
1351 | val = readl(_PRCMU_BASE + clk_mgt[clock].offset); | 1643 | val = readl(_PRCMU_BASE + clk_mgt[clock].offset); |
@@ -1354,7 +1646,7 @@ int prcmu_set_clock_divider(u8 clock, u8 divider) | |||
1354 | writel(val, (_PRCMU_BASE + clk_mgt[clock].offset)); | 1646 | writel(val, (_PRCMU_BASE + clk_mgt[clock].offset)); |
1355 | 1647 | ||
1356 | /* Release the HW semaphore. */ | 1648 | /* Release the HW semaphore. */ |
1357 | writel(0, (_PRCMU_BASE + PRCM_SEM)); | 1649 | writel(0, PRCM_SEM); |
1358 | 1650 | ||
1359 | spin_unlock_irqrestore(&clk_mgt_lock, flags); | 1651 | spin_unlock_irqrestore(&clk_mgt_lock, flags); |
1360 | 1652 | ||
@@ -1380,7 +1672,7 @@ int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size) | |||
1380 | 1672 | ||
1381 | mutex_lock(&mb5_transfer.lock); | 1673 | mutex_lock(&mb5_transfer.lock); |
1382 | 1674 | ||
1383 | while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(5)) | 1675 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5)) |
1384 | cpu_relax(); | 1676 | cpu_relax(); |
1385 | 1677 | ||
1386 | writeb(PRCMU_I2C_READ(slave), (tcdm_base + PRCM_REQ_MB5_I2C_SLAVE_OP)); | 1678 | writeb(PRCMU_I2C_READ(slave), (tcdm_base + PRCM_REQ_MB5_I2C_SLAVE_OP)); |
@@ -1388,7 +1680,7 @@ int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size) | |||
1388 | writeb(reg, (tcdm_base + PRCM_REQ_MB5_I2C_REG)); | 1680 | writeb(reg, (tcdm_base + PRCM_REQ_MB5_I2C_REG)); |
1389 | writeb(0, (tcdm_base + PRCM_REQ_MB5_I2C_VAL)); | 1681 | writeb(0, (tcdm_base + PRCM_REQ_MB5_I2C_VAL)); |
1390 | 1682 | ||
1391 | writel(MBOX_BIT(5), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); | 1683 | writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET); |
1392 | 1684 | ||
1393 | if (!wait_for_completion_timeout(&mb5_transfer.work, | 1685 | if (!wait_for_completion_timeout(&mb5_transfer.work, |
1394 | msecs_to_jiffies(20000))) { | 1686 | msecs_to_jiffies(20000))) { |
@@ -1426,7 +1718,7 @@ int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size) | |||
1426 | 1718 | ||
1427 | mutex_lock(&mb5_transfer.lock); | 1719 | mutex_lock(&mb5_transfer.lock); |
1428 | 1720 | ||
1429 | while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(5)) | 1721 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5)) |
1430 | cpu_relax(); | 1722 | cpu_relax(); |
1431 | 1723 | ||
1432 | writeb(PRCMU_I2C_WRITE(slave), (tcdm_base + PRCM_REQ_MB5_I2C_SLAVE_OP)); | 1724 | writeb(PRCMU_I2C_WRITE(slave), (tcdm_base + PRCM_REQ_MB5_I2C_SLAVE_OP)); |
@@ -1434,7 +1726,7 @@ int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size) | |||
1434 | writeb(reg, (tcdm_base + PRCM_REQ_MB5_I2C_REG)); | 1726 | writeb(reg, (tcdm_base + PRCM_REQ_MB5_I2C_REG)); |
1435 | writeb(*value, (tcdm_base + PRCM_REQ_MB5_I2C_VAL)); | 1727 | writeb(*value, (tcdm_base + PRCM_REQ_MB5_I2C_VAL)); |
1436 | 1728 | ||
1437 | writel(MBOX_BIT(5), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); | 1729 | writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET); |
1438 | 1730 | ||
1439 | if (!wait_for_completion_timeout(&mb5_transfer.work, | 1731 | if (!wait_for_completion_timeout(&mb5_transfer.work, |
1440 | msecs_to_jiffies(20000))) { | 1732 | msecs_to_jiffies(20000))) { |
@@ -1456,21 +1748,44 @@ int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size) | |||
1456 | void prcmu_ac_wake_req(void) | 1748 | void prcmu_ac_wake_req(void) |
1457 | { | 1749 | { |
1458 | u32 val; | 1750 | u32 val; |
1751 | u32 status; | ||
1459 | 1752 | ||
1460 | mutex_lock(&mb0_transfer.ac_wake_lock); | 1753 | mutex_lock(&mb0_transfer.ac_wake_lock); |
1461 | 1754 | ||
1462 | val = readl(_PRCMU_BASE + PRCM_HOSTACCESS_REQ); | 1755 | val = readl(PRCM_HOSTACCESS_REQ); |
1463 | if (val & PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ) | 1756 | if (val & PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ) |
1464 | goto unlock_and_return; | 1757 | goto unlock_and_return; |
1465 | 1758 | ||
1466 | atomic_set(&ac_wake_req_state, 1); | 1759 | atomic_set(&ac_wake_req_state, 1); |
1467 | 1760 | ||
1468 | writel((val | PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ), | 1761 | retry: |
1469 | (_PRCMU_BASE + PRCM_HOSTACCESS_REQ)); | 1762 | writel((val | PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ), PRCM_HOSTACCESS_REQ); |
1470 | 1763 | ||
1471 | if (!wait_for_completion_timeout(&mb0_transfer.ac_wake_work, | 1764 | if (!wait_for_completion_timeout(&mb0_transfer.ac_wake_work, |
1472 | msecs_to_jiffies(20000))) { | 1765 | msecs_to_jiffies(5000))) { |
1473 | pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n", | 1766 | pr_crit("prcmu: %s timed out (5 s) waiting for a reply.\n", |
1767 | __func__); | ||
1768 | goto unlock_and_return; | ||
1769 | } | ||
1770 | |||
1771 | /* | ||
1772 | * The modem can generate an AC_WAKE_ACK, and then still go to sleep. | ||
1773 | * As a workaround, we wait, and then check that the modem is indeed | ||
1774 | * awake (in terms of the value of the PRCM_MOD_AWAKE_STATUS | ||
1775 | * register, which may not be the whole truth). | ||
1776 | */ | ||
1777 | udelay(400); | ||
1778 | status = (readl(PRCM_MOD_AWAKE_STATUS) & BITS(0, 2)); | ||
1779 | if (status != (PRCM_MOD_AWAKE_STATUS_PRCM_MOD_AAPD_AWAKE | | ||
1780 | PRCM_MOD_AWAKE_STATUS_PRCM_MOD_COREPD_AWAKE)) { | ||
1781 | pr_err("prcmu: %s received ack, but modem not awake (0x%X).\n", | ||
1782 | __func__, status); | ||
1783 | udelay(1200); | ||
1784 | writel(val, PRCM_HOSTACCESS_REQ); | ||
1785 | if (wait_for_completion_timeout(&mb0_transfer.ac_wake_work, | ||
1786 | msecs_to_jiffies(5000))) | ||
1787 | goto retry; | ||
1788 | pr_crit("prcmu: %s timed out (5 s) waiting for AC_SLEEP_ACK.\n", | ||
1474 | __func__); | 1789 | __func__); |
1475 | } | 1790 | } |
1476 | 1791 | ||
@@ -1487,16 +1802,16 @@ void prcmu_ac_sleep_req() | |||
1487 | 1802 | ||
1488 | mutex_lock(&mb0_transfer.ac_wake_lock); | 1803 | mutex_lock(&mb0_transfer.ac_wake_lock); |
1489 | 1804 | ||
1490 | val = readl(_PRCMU_BASE + PRCM_HOSTACCESS_REQ); | 1805 | val = readl(PRCM_HOSTACCESS_REQ); |
1491 | if (!(val & PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ)) | 1806 | if (!(val & PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ)) |
1492 | goto unlock_and_return; | 1807 | goto unlock_and_return; |
1493 | 1808 | ||
1494 | writel((val & ~PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ), | 1809 | writel((val & ~PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ), |
1495 | (_PRCMU_BASE + PRCM_HOSTACCESS_REQ)); | 1810 | PRCM_HOSTACCESS_REQ); |
1496 | 1811 | ||
1497 | if (!wait_for_completion_timeout(&mb0_transfer.ac_wake_work, | 1812 | if (!wait_for_completion_timeout(&mb0_transfer.ac_wake_work, |
1498 | msecs_to_jiffies(20000))) { | 1813 | msecs_to_jiffies(5000))) { |
1499 | pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n", | 1814 | pr_crit("prcmu: %s timed out (5 s) waiting for a reply.\n", |
1500 | __func__); | 1815 | __func__); |
1501 | } | 1816 | } |
1502 | 1817 | ||
@@ -1506,21 +1821,32 @@ unlock_and_return: | |||
1506 | mutex_unlock(&mb0_transfer.ac_wake_lock); | 1821 | mutex_unlock(&mb0_transfer.ac_wake_lock); |
1507 | } | 1822 | } |
1508 | 1823 | ||
1509 | bool prcmu_is_ac_wake_requested(void) | 1824 | bool db8500_prcmu_is_ac_wake_requested(void) |
1510 | { | 1825 | { |
1511 | return (atomic_read(&ac_wake_req_state) != 0); | 1826 | return (atomic_read(&ac_wake_req_state) != 0); |
1512 | } | 1827 | } |
1513 | 1828 | ||
1514 | /** | 1829 | /** |
1515 | * prcmu_system_reset - System reset | 1830 | * db8500_prcmu_system_reset - System reset |
1516 | * | 1831 | * |
1517 | * Saves the reset reason code and then sets the APE_SOFRST register which | 1832 | * Saves the reset reason code and then sets the APE_SOFTRST register which |
1518 | * fires interrupt to fw | 1833 | * fires interrupt to fw |
1519 | */ | 1834 | */ |
1520 | void prcmu_system_reset(u16 reset_code) | 1835 | void db8500_prcmu_system_reset(u16 reset_code) |
1521 | { | 1836 | { |
1522 | writew(reset_code, (tcdm_base + PRCM_SW_RST_REASON)); | 1837 | writew(reset_code, (tcdm_base + PRCM_SW_RST_REASON)); |
1523 | writel(1, (_PRCMU_BASE + PRCM_APE_SOFTRST)); | 1838 | writel(1, PRCM_APE_SOFTRST); |
1839 | } | ||
1840 | |||
1841 | /** | ||
1842 | * db8500_prcmu_get_reset_code - Retrieve SW reset reason code | ||
1843 | * | ||
1844 | * Retrieves the reset reason code stored by prcmu_system_reset() before | ||
1845 | * last restart. | ||
1846 | */ | ||
1847 | u16 db8500_prcmu_get_reset_code(void) | ||
1848 | { | ||
1849 | return readw(tcdm_base + PRCM_SW_RST_REASON); | ||
1524 | } | 1850 | } |
1525 | 1851 | ||
1526 | /** | 1852 | /** |
@@ -1530,11 +1856,11 @@ void prcmu_modem_reset(void) | |||
1530 | { | 1856 | { |
1531 | mutex_lock(&mb1_transfer.lock); | 1857 | mutex_lock(&mb1_transfer.lock); |
1532 | 1858 | ||
1533 | while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) | 1859 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) |
1534 | cpu_relax(); | 1860 | cpu_relax(); |
1535 | 1861 | ||
1536 | writeb(MB1H_RESET_MODEM, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); | 1862 | writeb(MB1H_RESET_MODEM, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); |
1537 | writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); | 1863 | writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET); |
1538 | wait_for_completion(&mb1_transfer.work); | 1864 | wait_for_completion(&mb1_transfer.work); |
1539 | 1865 | ||
1540 | /* | 1866 | /* |
@@ -1551,11 +1877,11 @@ static void ack_dbb_wakeup(void) | |||
1551 | 1877 | ||
1552 | spin_lock_irqsave(&mb0_transfer.lock, flags); | 1878 | spin_lock_irqsave(&mb0_transfer.lock, flags); |
1553 | 1879 | ||
1554 | while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(0)) | 1880 | while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(0)) |
1555 | cpu_relax(); | 1881 | cpu_relax(); |
1556 | 1882 | ||
1557 | writeb(MB0H_READ_WAKEUP_ACK, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB0)); | 1883 | writeb(MB0H_READ_WAKEUP_ACK, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB0)); |
1558 | writel(MBOX_BIT(0), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); | 1884 | writel(MBOX_BIT(0), PRCM_MBOX_CPU_SET); |
1559 | 1885 | ||
1560 | spin_unlock_irqrestore(&mb0_transfer.lock, flags); | 1886 | spin_unlock_irqrestore(&mb0_transfer.lock, flags); |
1561 | } | 1887 | } |
@@ -1600,7 +1926,7 @@ static bool read_mailbox_0(void) | |||
1600 | r = false; | 1926 | r = false; |
1601 | break; | 1927 | break; |
1602 | } | 1928 | } |
1603 | writel(MBOX_BIT(0), (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); | 1929 | writel(MBOX_BIT(0), PRCM_ARM_IT1_CLR); |
1604 | return r; | 1930 | return r; |
1605 | } | 1931 | } |
1606 | 1932 | ||
@@ -1613,7 +1939,7 @@ static bool read_mailbox_1(void) | |||
1613 | PRCM_ACK_MB1_CURRENT_APE_OPP); | 1939 | PRCM_ACK_MB1_CURRENT_APE_OPP); |
1614 | mb1_transfer.ack.ape_voltage_status = readb(tcdm_base + | 1940 | mb1_transfer.ack.ape_voltage_status = readb(tcdm_base + |
1615 | PRCM_ACK_MB1_APE_VOLTAGE_STATUS); | 1941 | PRCM_ACK_MB1_APE_VOLTAGE_STATUS); |
1616 | writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); | 1942 | writel(MBOX_BIT(1), PRCM_ARM_IT1_CLR); |
1617 | complete(&mb1_transfer.work); | 1943 | complete(&mb1_transfer.work); |
1618 | return false; | 1944 | return false; |
1619 | } | 1945 | } |
@@ -1621,14 +1947,14 @@ static bool read_mailbox_1(void) | |||
1621 | static bool read_mailbox_2(void) | 1947 | static bool read_mailbox_2(void) |
1622 | { | 1948 | { |
1623 | mb2_transfer.ack.status = readb(tcdm_base + PRCM_ACK_MB2_DPS_STATUS); | 1949 | mb2_transfer.ack.status = readb(tcdm_base + PRCM_ACK_MB2_DPS_STATUS); |
1624 | writel(MBOX_BIT(2), (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); | 1950 | writel(MBOX_BIT(2), PRCM_ARM_IT1_CLR); |
1625 | complete(&mb2_transfer.work); | 1951 | complete(&mb2_transfer.work); |
1626 | return false; | 1952 | return false; |
1627 | } | 1953 | } |
1628 | 1954 | ||
1629 | static bool read_mailbox_3(void) | 1955 | static bool read_mailbox_3(void) |
1630 | { | 1956 | { |
1631 | writel(MBOX_BIT(3), (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); | 1957 | writel(MBOX_BIT(3), PRCM_ARM_IT1_CLR); |
1632 | return false; | 1958 | return false; |
1633 | } | 1959 | } |
1634 | 1960 | ||
@@ -1643,6 +1969,11 @@ static bool read_mailbox_4(void) | |||
1643 | case MB4H_HOTDOG: | 1969 | case MB4H_HOTDOG: |
1644 | case MB4H_HOTMON: | 1970 | case MB4H_HOTMON: |
1645 | case MB4H_HOT_PERIOD: | 1971 | case MB4H_HOT_PERIOD: |
1972 | case MB4H_A9WDOG_CONF: | ||
1973 | case MB4H_A9WDOG_EN: | ||
1974 | case MB4H_A9WDOG_DIS: | ||
1975 | case MB4H_A9WDOG_LOAD: | ||
1976 | case MB4H_A9WDOG_KICK: | ||
1646 | break; | 1977 | break; |
1647 | default: | 1978 | default: |
1648 | print_unknown_header_warning(4, header); | 1979 | print_unknown_header_warning(4, header); |
@@ -1650,7 +1981,7 @@ static bool read_mailbox_4(void) | |||
1650 | break; | 1981 | break; |
1651 | } | 1982 | } |
1652 | 1983 | ||
1653 | writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); | 1984 | writel(MBOX_BIT(4), PRCM_ARM_IT1_CLR); |
1654 | 1985 | ||
1655 | if (do_complete) | 1986 | if (do_complete) |
1656 | complete(&mb4_transfer.work); | 1987 | complete(&mb4_transfer.work); |
@@ -1662,20 +1993,20 @@ static bool read_mailbox_5(void) | |||
1662 | { | 1993 | { |
1663 | mb5_transfer.ack.status = readb(tcdm_base + PRCM_ACK_MB5_I2C_STATUS); | 1994 | mb5_transfer.ack.status = readb(tcdm_base + PRCM_ACK_MB5_I2C_STATUS); |
1664 | mb5_transfer.ack.value = readb(tcdm_base + PRCM_ACK_MB5_I2C_VAL); | 1995 | mb5_transfer.ack.value = readb(tcdm_base + PRCM_ACK_MB5_I2C_VAL); |
1665 | writel(MBOX_BIT(5), (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); | 1996 | writel(MBOX_BIT(5), PRCM_ARM_IT1_CLR); |
1666 | complete(&mb5_transfer.work); | 1997 | complete(&mb5_transfer.work); |
1667 | return false; | 1998 | return false; |
1668 | } | 1999 | } |
1669 | 2000 | ||
1670 | static bool read_mailbox_6(void) | 2001 | static bool read_mailbox_6(void) |
1671 | { | 2002 | { |
1672 | writel(MBOX_BIT(6), (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); | 2003 | writel(MBOX_BIT(6), PRCM_ARM_IT1_CLR); |
1673 | return false; | 2004 | return false; |
1674 | } | 2005 | } |
1675 | 2006 | ||
1676 | static bool read_mailbox_7(void) | 2007 | static bool read_mailbox_7(void) |
1677 | { | 2008 | { |
1678 | writel(MBOX_BIT(7), (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); | 2009 | writel(MBOX_BIT(7), PRCM_ARM_IT1_CLR); |
1679 | return false; | 2010 | return false; |
1680 | } | 2011 | } |
1681 | 2012 | ||
@@ -1696,7 +2027,7 @@ static irqreturn_t prcmu_irq_handler(int irq, void *data) | |||
1696 | u8 n; | 2027 | u8 n; |
1697 | irqreturn_t r; | 2028 | irqreturn_t r; |
1698 | 2029 | ||
1699 | bits = (readl(_PRCMU_BASE + PRCM_ARM_IT1_VAL) & ALL_MBOX_BITS); | 2030 | bits = (readl(PRCM_ARM_IT1_VAL) & ALL_MBOX_BITS); |
1700 | if (unlikely(!bits)) | 2031 | if (unlikely(!bits)) |
1701 | return IRQ_NONE; | 2032 | return IRQ_NONE; |
1702 | 2033 | ||
@@ -1768,7 +2099,7 @@ static struct irq_chip prcmu_irq_chip = { | |||
1768 | .irq_unmask = prcmu_irq_unmask, | 2099 | .irq_unmask = prcmu_irq_unmask, |
1769 | }; | 2100 | }; |
1770 | 2101 | ||
1771 | void __init prcmu_early_init(void) | 2102 | void __init db8500_prcmu_early_init(void) |
1772 | { | 2103 | { |
1773 | unsigned int i; | 2104 | unsigned int i; |
1774 | 2105 | ||
@@ -1826,6 +2157,16 @@ void __init prcmu_early_init(void) | |||
1826 | } | 2157 | } |
1827 | } | 2158 | } |
1828 | 2159 | ||
2160 | static void __init db8500_prcmu_init_clkforce(void) | ||
2161 | { | ||
2162 | u32 val; | ||
2163 | |||
2164 | val = readl(PRCM_A9PL_FORCE_CLKEN); | ||
2165 | val &= ~(PRCM_A9PL_FORCE_CLKEN_PRCM_A9PL_FORCE_CLKEN | | ||
2166 | PRCM_A9PL_FORCE_CLKEN_PRCM_A9AXI_FORCE_CLKEN); | ||
2167 | writel(val, (PRCM_A9PL_FORCE_CLKEN)); | ||
2168 | } | ||
2169 | |||
1829 | /* | 2170 | /* |
1830 | * Power domain switches (ePODs) modeled as regulators for the DB8500 SoC | 2171 | * Power domain switches (ePODs) modeled as regulators for the DB8500 SoC |
1831 | */ | 2172 | */ |
@@ -1861,7 +2202,42 @@ static struct regulator_consumer_supply db8500_vsmps2_consumers[] = { | |||
1861 | 2202 | ||
1862 | static struct regulator_consumer_supply db8500_b2r2_mcde_consumers[] = { | 2203 | static struct regulator_consumer_supply db8500_b2r2_mcde_consumers[] = { |
1863 | REGULATOR_SUPPLY("vsupply", "b2r2.0"), | 2204 | REGULATOR_SUPPLY("vsupply", "b2r2.0"), |
1864 | REGULATOR_SUPPLY("vsupply", "mcde.0"), | 2205 | REGULATOR_SUPPLY("vsupply", "mcde"), |
2206 | }; | ||
2207 | |||
2208 | /* SVA MMDSP regulator switch */ | ||
2209 | static struct regulator_consumer_supply db8500_svammdsp_consumers[] = { | ||
2210 | REGULATOR_SUPPLY("sva-mmdsp", "cm_control"), | ||
2211 | }; | ||
2212 | |||
2213 | /* SVA pipe regulator switch */ | ||
2214 | static struct regulator_consumer_supply db8500_svapipe_consumers[] = { | ||
2215 | REGULATOR_SUPPLY("sva-pipe", "cm_control"), | ||
2216 | }; | ||
2217 | |||
2218 | /* SIA MMDSP regulator switch */ | ||
2219 | static struct regulator_consumer_supply db8500_siammdsp_consumers[] = { | ||
2220 | REGULATOR_SUPPLY("sia-mmdsp", "cm_control"), | ||
2221 | }; | ||
2222 | |||
2223 | /* SIA pipe regulator switch */ | ||
2224 | static struct regulator_consumer_supply db8500_siapipe_consumers[] = { | ||
2225 | REGULATOR_SUPPLY("sia-pipe", "cm_control"), | ||
2226 | }; | ||
2227 | |||
2228 | static struct regulator_consumer_supply db8500_sga_consumers[] = { | ||
2229 | REGULATOR_SUPPLY("v-mali", NULL), | ||
2230 | }; | ||
2231 | |||
2232 | /* ESRAM1 and 2 regulator switch */ | ||
2233 | static struct regulator_consumer_supply db8500_esram12_consumers[] = { | ||
2234 | REGULATOR_SUPPLY("esram12", "cm_control"), | ||
2235 | }; | ||
2236 | |||
2237 | /* ESRAM3 and 4 regulator switch */ | ||
2238 | static struct regulator_consumer_supply db8500_esram34_consumers[] = { | ||
2239 | REGULATOR_SUPPLY("v-esram34", "mcde"), | ||
2240 | REGULATOR_SUPPLY("esram34", "cm_control"), | ||
1865 | }; | 2241 | }; |
1866 | 2242 | ||
1867 | static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { | 2243 | static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { |
@@ -1923,6 +2299,8 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { | |||
1923 | .name = "db8500-sva-mmdsp", | 2299 | .name = "db8500-sva-mmdsp", |
1924 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, | 2300 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, |
1925 | }, | 2301 | }, |
2302 | .consumer_supplies = db8500_svammdsp_consumers, | ||
2303 | .num_consumer_supplies = ARRAY_SIZE(db8500_svammdsp_consumers), | ||
1926 | }, | 2304 | }, |
1927 | [DB8500_REGULATOR_SWITCH_SVAMMDSPRET] = { | 2305 | [DB8500_REGULATOR_SWITCH_SVAMMDSPRET] = { |
1928 | .constraints = { | 2306 | .constraints = { |
@@ -1937,6 +2315,8 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { | |||
1937 | .name = "db8500-sva-pipe", | 2315 | .name = "db8500-sva-pipe", |
1938 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, | 2316 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, |
1939 | }, | 2317 | }, |
2318 | .consumer_supplies = db8500_svapipe_consumers, | ||
2319 | .num_consumer_supplies = ARRAY_SIZE(db8500_svapipe_consumers), | ||
1940 | }, | 2320 | }, |
1941 | [DB8500_REGULATOR_SWITCH_SIAMMDSP] = { | 2321 | [DB8500_REGULATOR_SWITCH_SIAMMDSP] = { |
1942 | .supply_regulator = "db8500-vape", | 2322 | .supply_regulator = "db8500-vape", |
@@ -1944,6 +2324,8 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { | |||
1944 | .name = "db8500-sia-mmdsp", | 2324 | .name = "db8500-sia-mmdsp", |
1945 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, | 2325 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, |
1946 | }, | 2326 | }, |
2327 | .consumer_supplies = db8500_siammdsp_consumers, | ||
2328 | .num_consumer_supplies = ARRAY_SIZE(db8500_siammdsp_consumers), | ||
1947 | }, | 2329 | }, |
1948 | [DB8500_REGULATOR_SWITCH_SIAMMDSPRET] = { | 2330 | [DB8500_REGULATOR_SWITCH_SIAMMDSPRET] = { |
1949 | .constraints = { | 2331 | .constraints = { |
@@ -1957,6 +2339,8 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { | |||
1957 | .name = "db8500-sia-pipe", | 2339 | .name = "db8500-sia-pipe", |
1958 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, | 2340 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, |
1959 | }, | 2341 | }, |
2342 | .consumer_supplies = db8500_siapipe_consumers, | ||
2343 | .num_consumer_supplies = ARRAY_SIZE(db8500_siapipe_consumers), | ||
1960 | }, | 2344 | }, |
1961 | [DB8500_REGULATOR_SWITCH_SGA] = { | 2345 | [DB8500_REGULATOR_SWITCH_SGA] = { |
1962 | .supply_regulator = "db8500-vape", | 2346 | .supply_regulator = "db8500-vape", |
@@ -1964,6 +2348,9 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { | |||
1964 | .name = "db8500-sga", | 2348 | .name = "db8500-sga", |
1965 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, | 2349 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, |
1966 | }, | 2350 | }, |
2351 | .consumer_supplies = db8500_sga_consumers, | ||
2352 | .num_consumer_supplies = ARRAY_SIZE(db8500_sga_consumers), | ||
2353 | |||
1967 | }, | 2354 | }, |
1968 | [DB8500_REGULATOR_SWITCH_B2R2_MCDE] = { | 2355 | [DB8500_REGULATOR_SWITCH_B2R2_MCDE] = { |
1969 | .supply_regulator = "db8500-vape", | 2356 | .supply_regulator = "db8500-vape", |
@@ -1980,6 +2367,8 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { | |||
1980 | .name = "db8500-esram12", | 2367 | .name = "db8500-esram12", |
1981 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, | 2368 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, |
1982 | }, | 2369 | }, |
2370 | .consumer_supplies = db8500_esram12_consumers, | ||
2371 | .num_consumer_supplies = ARRAY_SIZE(db8500_esram12_consumers), | ||
1983 | }, | 2372 | }, |
1984 | [DB8500_REGULATOR_SWITCH_ESRAM12RET] = { | 2373 | [DB8500_REGULATOR_SWITCH_ESRAM12RET] = { |
1985 | .constraints = { | 2374 | .constraints = { |
@@ -1993,6 +2382,8 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { | |||
1993 | .name = "db8500-esram34", | 2382 | .name = "db8500-esram34", |
1994 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, | 2383 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, |
1995 | }, | 2384 | }, |
2385 | .consumer_supplies = db8500_esram34_consumers, | ||
2386 | .num_consumer_supplies = ARRAY_SIZE(db8500_esram34_consumers), | ||
1996 | }, | 2387 | }, |
1997 | [DB8500_REGULATOR_SWITCH_ESRAM34RET] = { | 2388 | [DB8500_REGULATOR_SWITCH_ESRAM34RET] = { |
1998 | .constraints = { | 2389 | .constraints = { |
@@ -2024,8 +2415,10 @@ static int __init db8500_prcmu_probe(struct platform_device *pdev) | |||
2024 | if (ux500_is_svp()) | 2415 | if (ux500_is_svp()) |
2025 | return -ENODEV; | 2416 | return -ENODEV; |
2026 | 2417 | ||
2418 | db8500_prcmu_init_clkforce(); | ||
2419 | |||
2027 | /* Clean up the mailbox interrupts after pre-kernel code. */ | 2420 | /* Clean up the mailbox interrupts after pre-kernel code. */ |
2028 | writel(ALL_MBOX_BITS, (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); | 2421 | writel(ALL_MBOX_BITS, PRCM_ARM_IT1_CLR); |
2029 | 2422 | ||
2030 | err = request_threaded_irq(IRQ_DB8500_PRCMU1, prcmu_irq_handler, | 2423 | err = request_threaded_irq(IRQ_DB8500_PRCMU1, prcmu_irq_handler, |
2031 | prcmu_irq_thread_fn, IRQF_NO_SUSPEND, "prcmu", NULL); | 2424 | prcmu_irq_thread_fn, IRQF_NO_SUSPEND, "prcmu", NULL); |
diff --git a/drivers/mfd/db5500-prcmu-regs.h b/drivers/mfd/dbx500-prcmu-regs.h index 9a8e9e4ddd33..ec22e9f15d32 100644 --- a/drivers/mfd/db5500-prcmu-regs.h +++ b/drivers/mfd/dbx500-prcmu-regs.h | |||
@@ -10,11 +10,49 @@ | |||
10 | * PRCM Unit registers | 10 | * PRCM Unit registers |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #ifndef __MACH_PRCMU_REGS_H | 13 | #ifndef __DB8500_PRCMU_REGS_H |
14 | #define __MACH_PRCMU_REGS_H | 14 | #define __DB8500_PRCMU_REGS_H |
15 | 15 | ||
16 | #include <mach/hardware.h> | 16 | #include <mach/hardware.h> |
17 | 17 | ||
18 | #define BITS(_start, _end) ((BIT(_end) - BIT(_start)) + BIT(_end)) | ||
19 | |||
20 | #define PRCM_SVACLK_MGT_OFF 0x008 | ||
21 | #define PRCM_SIACLK_MGT_OFF 0x00C | ||
22 | #define PRCM_SGACLK_MGT_OFF 0x014 | ||
23 | #define PRCM_UARTCLK_MGT_OFF 0x018 | ||
24 | #define PRCM_MSP02CLK_MGT_OFF 0x01C | ||
25 | #define PRCM_I2CCLK_MGT_OFF 0x020 | ||
26 | #define PRCM_SDMMCCLK_MGT_OFF 0x024 | ||
27 | #define PRCM_SLIMCLK_MGT_OFF 0x028 | ||
28 | #define PRCM_PER1CLK_MGT_OFF 0x02C | ||
29 | #define PRCM_PER2CLK_MGT_OFF 0x030 | ||
30 | #define PRCM_PER3CLK_MGT_OFF 0x034 | ||
31 | #define PRCM_PER5CLK_MGT_OFF 0x038 | ||
32 | #define PRCM_PER6CLK_MGT_OFF 0x03C | ||
33 | #define PRCM_PER7CLK_MGT_OFF 0x040 | ||
34 | #define PRCM_PWMCLK_MGT_OFF 0x044 /* for DB5500 */ | ||
35 | #define PRCM_IRDACLK_MGT_OFF 0x048 /* for DB5500 */ | ||
36 | #define PRCM_IRRCCLK_MGT_OFF 0x04C /* for DB5500 */ | ||
37 | #define PRCM_LCDCLK_MGT_OFF 0x044 | ||
38 | #define PRCM_BMLCLK_MGT_OFF 0x04C | ||
39 | #define PRCM_HSITXCLK_MGT_OFF 0x050 | ||
40 | #define PRCM_HSIRXCLK_MGT_OFF 0x054 | ||
41 | #define PRCM_HDMICLK_MGT_OFF 0x058 | ||
42 | #define PRCM_APEATCLK_MGT_OFF 0x05C | ||
43 | #define PRCM_APETRACECLK_MGT_OFF 0x060 | ||
44 | #define PRCM_MCDECLK_MGT_OFF 0x064 | ||
45 | #define PRCM_IPI2CCLK_MGT_OFF 0x068 | ||
46 | #define PRCM_DSIALTCLK_MGT_OFF 0x06C | ||
47 | #define PRCM_DMACLK_MGT_OFF 0x074 | ||
48 | #define PRCM_B2R2CLK_MGT_OFF 0x078 | ||
49 | #define PRCM_TVCLK_MGT_OFF 0x07C | ||
50 | #define PRCM_UNIPROCLK_MGT_OFF 0x278 | ||
51 | #define PRCM_SSPCLK_MGT_OFF 0x280 | ||
52 | #define PRCM_RNGCLK_MGT_OFF 0x284 | ||
53 | #define PRCM_UICCCLK_MGT_OFF 0x27C | ||
54 | #define PRCM_MSP1CLK_MGT_OFF 0x288 | ||
55 | |||
18 | #define PRCM_ARM_PLLDIVPS (_PRCMU_BASE + 0x118) | 56 | #define PRCM_ARM_PLLDIVPS (_PRCMU_BASE + 0x118) |
19 | #define PRCM_ARM_PLLDIVPS_ARM_BRM_RATE 0x3f | 57 | #define PRCM_ARM_PLLDIVPS_ARM_BRM_RATE 0x3f |
20 | #define PRCM_ARM_PLLDIVPS_MAX_MASK 0xf | 58 | #define PRCM_ARM_PLLDIVPS_MAX_MASK 0xf |
@@ -30,11 +68,15 @@ | |||
30 | #define PRCM_PLLARM_ENABLE_PRCM_PLLARM_COUNTON 0x100 | 68 | #define PRCM_PLLARM_ENABLE_PRCM_PLLARM_COUNTON 0x100 |
31 | 69 | ||
32 | #define PRCM_ARMCLKFIX_MGT (_PRCMU_BASE + 0x0) | 70 | #define PRCM_ARMCLKFIX_MGT (_PRCMU_BASE + 0x0) |
71 | #define PRCM_A9PL_FORCE_CLKEN (_PRCMU_BASE + 0x19C) | ||
33 | #define PRCM_A9_RESETN_CLR (_PRCMU_BASE + 0x1f4) | 72 | #define PRCM_A9_RESETN_CLR (_PRCMU_BASE + 0x1f4) |
34 | #define PRCM_A9_RESETN_SET (_PRCMU_BASE + 0x1f0) | 73 | #define PRCM_A9_RESETN_SET (_PRCMU_BASE + 0x1f0) |
35 | #define PRCM_ARM_LS_CLAMP (_PRCMU_BASE + 0x30c) | 74 | #define PRCM_ARM_LS_CLAMP (_PRCMU_BASE + 0x30c) |
36 | #define PRCM_SRAM_A9 (_PRCMU_BASE + 0x308) | 75 | #define PRCM_SRAM_A9 (_PRCMU_BASE + 0x308) |
37 | 76 | ||
77 | #define PRCM_A9PL_FORCE_CLKEN_PRCM_A9PL_FORCE_CLKEN BIT(0) | ||
78 | #define PRCM_A9PL_FORCE_CLKEN_PRCM_A9AXI_FORCE_CLKEN BIT(1) | ||
79 | |||
38 | /* ARM WFI Standby signal register */ | 80 | /* ARM WFI Standby signal register */ |
39 | #define PRCM_ARM_WFI_STANDBY (_PRCMU_BASE + 0x130) | 81 | #define PRCM_ARM_WFI_STANDBY (_PRCMU_BASE + 0x130) |
40 | #define PRCM_IOCR (_PRCMU_BASE + 0x310) | 82 | #define PRCM_IOCR (_PRCMU_BASE + 0x310) |
@@ -61,12 +103,18 @@ | |||
61 | #define PRCM_ARMITVAL127TO96 (_PRCMU_BASE + 0x26C) | 103 | #define PRCM_ARMITVAL127TO96 (_PRCMU_BASE + 0x26C) |
62 | 104 | ||
63 | #define PRCM_HOSTACCESS_REQ (_PRCMU_BASE + 0x334) | 105 | #define PRCM_HOSTACCESS_REQ (_PRCMU_BASE + 0x334) |
106 | #define PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ 0x1 | ||
64 | #define ARM_WAKEUP_MODEM 0x1 | 107 | #define ARM_WAKEUP_MODEM 0x1 |
65 | 108 | ||
66 | #define PRCM_ARM_IT1_CLEAR (_PRCMU_BASE + 0x48C) | 109 | #define PRCM_ARM_IT1_CLR (_PRCMU_BASE + 0x48C) |
67 | #define PRCM_ARM_IT1_VAL (_PRCMU_BASE + 0x494) | 110 | #define PRCM_ARM_IT1_VAL (_PRCMU_BASE + 0x494) |
68 | #define PRCM_HOLD_EVT (_PRCMU_BASE + 0x174) | 111 | #define PRCM_HOLD_EVT (_PRCMU_BASE + 0x174) |
69 | 112 | ||
113 | #define PRCM_MOD_AWAKE_STATUS (_PRCMU_BASE + 0x4A0) | ||
114 | #define PRCM_MOD_AWAKE_STATUS_PRCM_MOD_COREPD_AWAKE BIT(0) | ||
115 | #define PRCM_MOD_AWAKE_STATUS_PRCM_MOD_AAPD_AWAKE BIT(1) | ||
116 | #define PRCM_MOD_AWAKE_STATUS_PRCM_MOD_VMODEM_OFF_ISO BIT(2) | ||
117 | |||
70 | #define PRCM_ITSTATUS0 (_PRCMU_BASE + 0x148) | 118 | #define PRCM_ITSTATUS0 (_PRCMU_BASE + 0x148) |
71 | #define PRCM_ITSTATUS1 (_PRCMU_BASE + 0x150) | 119 | #define PRCM_ITSTATUS1 (_PRCMU_BASE + 0x150) |
72 | #define PRCM_ITSTATUS2 (_PRCMU_BASE + 0x158) | 120 | #define PRCM_ITSTATUS2 (_PRCMU_BASE + 0x158) |
@@ -87,16 +135,21 @@ | |||
87 | #define PRCM_PLLDSI_FREQ (_PRCMU_BASE + 0x500) | 135 | #define PRCM_PLLDSI_FREQ (_PRCMU_BASE + 0x500) |
88 | #define PRCM_PLLDSI_ENABLE (_PRCMU_BASE + 0x504) | 136 | #define PRCM_PLLDSI_ENABLE (_PRCMU_BASE + 0x504) |
89 | #define PRCM_PLLDSI_LOCKP (_PRCMU_BASE + 0x508) | 137 | #define PRCM_PLLDSI_LOCKP (_PRCMU_BASE + 0x508) |
90 | #define PRCM_LCDCLK_MGT (_PRCMU_BASE + 0x044) | 138 | #define PRCM_LCDCLK_MGT (_PRCMU_BASE + PRCM_LCDCLK_MGT_OFF) |
91 | #define PRCM_MCDECLK_MGT (_PRCMU_BASE + 0x064) | 139 | #define PRCM_MCDECLK_MGT (_PRCMU_BASE + PRCM_MCDECLK_MGT_OFF) |
92 | #define PRCM_HDMICLK_MGT (_PRCMU_BASE + 0x058) | 140 | #define PRCM_HDMICLK_MGT (_PRCMU_BASE + PRCM_HDMICLK_MGT_OFF) |
93 | #define PRCM_TVCLK_MGT (_PRCMU_BASE + 0x07c) | 141 | #define PRCM_TVCLK_MGT (_PRCMU_BASE + PRCM_TVCLK_MGT_OFF) |
94 | #define PRCM_DSI_PLLOUT_SEL (_PRCMU_BASE + 0x530) | 142 | #define PRCM_DSI_PLLOUT_SEL (_PRCMU_BASE + 0x530) |
95 | #define PRCM_DSITVCLK_DIV (_PRCMU_BASE + 0x52C) | 143 | #define PRCM_DSITVCLK_DIV (_PRCMU_BASE + 0x52C) |
96 | #define PRCM_PLLDSI_LOCKP (_PRCMU_BASE + 0x508) | 144 | #define PRCM_PLLDSI_LOCKP (_PRCMU_BASE + 0x508) |
97 | #define PRCM_APE_RESETN_SET (_PRCMU_BASE + 0x1E4) | 145 | #define PRCM_APE_RESETN_SET (_PRCMU_BASE + 0x1E4) |
98 | #define PRCM_APE_RESETN_CLR (_PRCMU_BASE + 0x1E8) | 146 | #define PRCM_APE_RESETN_CLR (_PRCMU_BASE + 0x1E8) |
147 | |||
99 | #define PRCM_CLKOCR (_PRCMU_BASE + 0x1CC) | 148 | #define PRCM_CLKOCR (_PRCMU_BASE + 0x1CC) |
149 | #define PRCM_CLKOCR_CLKOUT0_REF_CLK (1 << 0) | ||
150 | #define PRCM_CLKOCR_CLKOUT0_MASK BITS(0, 13) | ||
151 | #define PRCM_CLKOCR_CLKOUT1_REF_CLK (1 << 16) | ||
152 | #define PRCM_CLKOCR_CLKOUT1_MASK BITS(16, 29) | ||
100 | 153 | ||
101 | /* ePOD and memory power signal control registers */ | 154 | /* ePOD and memory power signal control registers */ |
102 | #define PRCM_EPOD_C_SET (_PRCMU_BASE + 0x410) | 155 | #define PRCM_EPOD_C_SET (_PRCMU_BASE + 0x410) |
@@ -111,5 +164,41 @@ | |||
111 | #define PRCM_GPIOCR_DBG_STM_MOD_CMD1 0x800 | 164 | #define PRCM_GPIOCR_DBG_STM_MOD_CMD1 0x800 |
112 | #define PRCM_GPIOCR_DBG_UARTMOD_CMD0 0x1 | 165 | #define PRCM_GPIOCR_DBG_UARTMOD_CMD0 0x1 |
113 | 166 | ||
167 | /* PRCMU HW semaphore */ | ||
168 | #define PRCM_SEM (_PRCMU_BASE + 0x400) | ||
169 | #define PRCM_SEM_PRCM_SEM BIT(0) | ||
170 | |||
171 | #define PRCM_TCR (_PRCMU_BASE + 0x1C8) | ||
172 | #define PRCM_TCR_TENSEL_MASK BITS(0, 7) | ||
173 | #define PRCM_TCR_STOP_TIMERS BIT(16) | ||
174 | #define PRCM_TCR_DOZE_MODE BIT(17) | ||
175 | |||
176 | #define PRCM_CLKOCR_CLKODIV0_SHIFT 0 | ||
177 | #define PRCM_CLKOCR_CLKODIV0_MASK BITS(0, 5) | ||
178 | #define PRCM_CLKOCR_CLKOSEL0_SHIFT 6 | ||
179 | #define PRCM_CLKOCR_CLKOSEL0_MASK BITS(6, 8) | ||
180 | #define PRCM_CLKOCR_CLKODIV1_SHIFT 16 | ||
181 | #define PRCM_CLKOCR_CLKODIV1_MASK BITS(16, 21) | ||
182 | #define PRCM_CLKOCR_CLKOSEL1_SHIFT 22 | ||
183 | #define PRCM_CLKOCR_CLKOSEL1_MASK BITS(22, 24) | ||
184 | #define PRCM_CLKOCR_CLK1TYPE BIT(28) | ||
185 | |||
186 | #define PRCM_CLK_MGT_CLKPLLDIV_MASK BITS(0, 4) | ||
187 | #define PRCM_CLK_MGT_CLKPLLSW_MASK BITS(5, 7) | ||
188 | #define PRCM_CLK_MGT_CLKEN BIT(8) | ||
189 | |||
190 | /* GPIOCR register */ | ||
191 | #define PRCM_GPIOCR_SPI2_SELECT BIT(23) | ||
192 | |||
193 | #define PRCM_DDR_SUBSYS_APE_MINBW (_PRCMU_BASE + 0x438) | ||
194 | #define PRCM_CGATING_BYPASS (_PRCMU_BASE + 0x134) | ||
195 | #define PRCM_CGATING_BYPASS_ICN2 BIT(6) | ||
196 | |||
197 | /* Miscellaneous unit registers */ | ||
198 | #define PRCM_RESOUTN_SET (_PRCMU_BASE + 0x214) | ||
199 | #define PRCM_RESOUTN_CLR (_PRCMU_BASE + 0x218) | ||
200 | |||
201 | /* System reset register */ | ||
202 | #define PRCM_APE_SOFTRST (_PRCMU_BASE + 0x228) | ||
114 | 203 | ||
115 | #endif /* __MACH_PRCMU__REGS_H */ | 204 | #endif /* __DB8500_PRCMU_REGS_H */ |
diff --git a/drivers/mfd/intel_msic.c b/drivers/mfd/intel_msic.c new file mode 100644 index 000000000000..97c27762174f --- /dev/null +++ b/drivers/mfd/intel_msic.c | |||
@@ -0,0 +1,502 @@ | |||
1 | /* | ||
2 | * Driver for Intel MSIC | ||
3 | * | ||
4 | * Copyright (C) 2011, Intel Corporation | ||
5 | * Author: Mika Westerberg <mika.westerberg@linux.intel.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/gpio.h> | ||
13 | #include <linux/io.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/mfd/core.h> | ||
16 | #include <linux/mfd/intel_msic.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/slab.h> | ||
19 | |||
20 | #include <asm/intel_scu_ipc.h> | ||
21 | |||
22 | #define MSIC_VENDOR(id) ((id >> 6) & 3) | ||
23 | #define MSIC_VERSION(id) (id & 0x3f) | ||
24 | #define MSIC_MAJOR(id) ('A' + ((id >> 3) & 7)) | ||
25 | #define MSIC_MINOR(id) (id & 7) | ||
26 | |||
27 | /* | ||
28 | * MSIC interrupt tree is readable from SRAM at INTEL_MSIC_IRQ_PHYS_BASE. | ||
29 | * Since IRQ block starts from address 0x002 we need to substract that from | ||
30 | * the actual IRQ status register address. | ||
31 | */ | ||
32 | #define MSIC_IRQ_STATUS(x) (INTEL_MSIC_IRQ_PHYS_BASE + ((x) - 2)) | ||
33 | #define MSIC_IRQ_STATUS_ACCDET MSIC_IRQ_STATUS(INTEL_MSIC_ACCDET) | ||
34 | |||
35 | /* | ||
36 | * The SCU hardware has limitation of 16 bytes per read/write buffer on | ||
37 | * Medfield. | ||
38 | */ | ||
39 | #define SCU_IPC_RWBUF_LIMIT 16 | ||
40 | |||
41 | /** | ||
42 | * struct intel_msic - an MSIC MFD instance | ||
43 | * @pdev: pointer to the platform device | ||
44 | * @vendor: vendor ID | ||
45 | * @version: chip version | ||
46 | * @irq_base: base address of the mapped MSIC SRAM interrupt tree | ||
47 | */ | ||
48 | struct intel_msic { | ||
49 | struct platform_device *pdev; | ||
50 | unsigned vendor; | ||
51 | unsigned version; | ||
52 | void __iomem *irq_base; | ||
53 | }; | ||
54 | |||
55 | static struct resource msic_touch_resources[] = { | ||
56 | { | ||
57 | .flags = IORESOURCE_IRQ, | ||
58 | }, | ||
59 | }; | ||
60 | |||
61 | static struct resource msic_adc_resources[] = { | ||
62 | { | ||
63 | .flags = IORESOURCE_IRQ, | ||
64 | }, | ||
65 | }; | ||
66 | |||
67 | static struct resource msic_battery_resources[] = { | ||
68 | { | ||
69 | .flags = IORESOURCE_IRQ, | ||
70 | }, | ||
71 | }; | ||
72 | |||
73 | static struct resource msic_gpio_resources[] = { | ||
74 | { | ||
75 | .flags = IORESOURCE_IRQ, | ||
76 | }, | ||
77 | }; | ||
78 | |||
79 | static struct resource msic_audio_resources[] = { | ||
80 | { | ||
81 | .name = "IRQ", | ||
82 | .flags = IORESOURCE_IRQ, | ||
83 | }, | ||
84 | /* | ||
85 | * We will pass IRQ_BASE to the driver now but this can be removed | ||
86 | * when/if the driver starts to use intel_msic_irq_read(). | ||
87 | */ | ||
88 | { | ||
89 | .name = "IRQ_BASE", | ||
90 | .flags = IORESOURCE_MEM, | ||
91 | .start = MSIC_IRQ_STATUS_ACCDET, | ||
92 | .end = MSIC_IRQ_STATUS_ACCDET, | ||
93 | }, | ||
94 | }; | ||
95 | |||
96 | static struct resource msic_hdmi_resources[] = { | ||
97 | { | ||
98 | .flags = IORESOURCE_IRQ, | ||
99 | }, | ||
100 | }; | ||
101 | |||
102 | static struct resource msic_thermal_resources[] = { | ||
103 | { | ||
104 | .flags = IORESOURCE_IRQ, | ||
105 | }, | ||
106 | }; | ||
107 | |||
108 | static struct resource msic_power_btn_resources[] = { | ||
109 | { | ||
110 | .flags = IORESOURCE_IRQ, | ||
111 | }, | ||
112 | }; | ||
113 | |||
114 | static struct resource msic_ocd_resources[] = { | ||
115 | { | ||
116 | .flags = IORESOURCE_IRQ, | ||
117 | }, | ||
118 | }; | ||
119 | |||
120 | /* | ||
121 | * Devices that are part of the MSIC and are available via firmware | ||
122 | * populated SFI DEVS table. | ||
123 | */ | ||
124 | static struct mfd_cell msic_devs[] = { | ||
125 | [INTEL_MSIC_BLOCK_TOUCH] = { | ||
126 | .name = "msic_touch", | ||
127 | .num_resources = ARRAY_SIZE(msic_touch_resources), | ||
128 | .resources = msic_touch_resources, | ||
129 | }, | ||
130 | [INTEL_MSIC_BLOCK_ADC] = { | ||
131 | .name = "msic_adc", | ||
132 | .num_resources = ARRAY_SIZE(msic_adc_resources), | ||
133 | .resources = msic_adc_resources, | ||
134 | }, | ||
135 | [INTEL_MSIC_BLOCK_BATTERY] = { | ||
136 | .name = "msic_battery", | ||
137 | .num_resources = ARRAY_SIZE(msic_battery_resources), | ||
138 | .resources = msic_battery_resources, | ||
139 | }, | ||
140 | [INTEL_MSIC_BLOCK_GPIO] = { | ||
141 | .name = "msic_gpio", | ||
142 | .num_resources = ARRAY_SIZE(msic_gpio_resources), | ||
143 | .resources = msic_gpio_resources, | ||
144 | }, | ||
145 | [INTEL_MSIC_BLOCK_AUDIO] = { | ||
146 | .name = "msic_audio", | ||
147 | .num_resources = ARRAY_SIZE(msic_audio_resources), | ||
148 | .resources = msic_audio_resources, | ||
149 | }, | ||
150 | [INTEL_MSIC_BLOCK_HDMI] = { | ||
151 | .name = "msic_hdmi", | ||
152 | .num_resources = ARRAY_SIZE(msic_hdmi_resources), | ||
153 | .resources = msic_hdmi_resources, | ||
154 | }, | ||
155 | [INTEL_MSIC_BLOCK_THERMAL] = { | ||
156 | .name = "msic_thermal", | ||
157 | .num_resources = ARRAY_SIZE(msic_thermal_resources), | ||
158 | .resources = msic_thermal_resources, | ||
159 | }, | ||
160 | [INTEL_MSIC_BLOCK_POWER_BTN] = { | ||
161 | .name = "msic_power_btn", | ||
162 | .num_resources = ARRAY_SIZE(msic_power_btn_resources), | ||
163 | .resources = msic_power_btn_resources, | ||
164 | }, | ||
165 | [INTEL_MSIC_BLOCK_OCD] = { | ||
166 | .name = "msic_ocd", | ||
167 | .num_resources = ARRAY_SIZE(msic_ocd_resources), | ||
168 | .resources = msic_ocd_resources, | ||
169 | }, | ||
170 | }; | ||
171 | |||
172 | /* | ||
173 | * Other MSIC related devices which are not directly available via SFI DEVS | ||
174 | * table. These can be pseudo devices, regulators etc. which are needed for | ||
175 | * different purposes. | ||
176 | * | ||
177 | * These devices appear only after the MSIC driver itself is initialized so | ||
178 | * we can guarantee that the SCU IPC interface is ready. | ||
179 | */ | ||
180 | static struct mfd_cell msic_other_devs[] = { | ||
181 | /* Audio codec in the MSIC */ | ||
182 | { | ||
183 | .id = -1, | ||
184 | .name = "sn95031", | ||
185 | }, | ||
186 | }; | ||
187 | |||
188 | /** | ||
189 | * intel_msic_reg_read - read a single MSIC register | ||
190 | * @reg: register to read | ||
191 | * @val: register value is placed here | ||
192 | * | ||
193 | * Read a single register from MSIC. Returns %0 on success and negative | ||
194 | * errno in case of failure. | ||
195 | * | ||
196 | * Function may sleep. | ||
197 | */ | ||
198 | int intel_msic_reg_read(unsigned short reg, u8 *val) | ||
199 | { | ||
200 | return intel_scu_ipc_ioread8(reg, val); | ||
201 | } | ||
202 | EXPORT_SYMBOL_GPL(intel_msic_reg_read); | ||
203 | |||
204 | /** | ||
205 | * intel_msic_reg_write - write a single MSIC register | ||
206 | * @reg: register to write | ||
207 | * @val: value to write to that register | ||
208 | * | ||
209 | * Write a single MSIC register. Returns 0 on success and negative | ||
210 | * errno in case of failure. | ||
211 | * | ||
212 | * Function may sleep. | ||
213 | */ | ||
214 | int intel_msic_reg_write(unsigned short reg, u8 val) | ||
215 | { | ||
216 | return intel_scu_ipc_iowrite8(reg, val); | ||
217 | } | ||
218 | EXPORT_SYMBOL_GPL(intel_msic_reg_write); | ||
219 | |||
220 | /** | ||
221 | * intel_msic_reg_update - update a single MSIC register | ||
222 | * @reg: register to update | ||
223 | * @val: value to write to the register | ||
224 | * @mask: specifies which of the bits are updated (%0 = don't update, | ||
225 | * %1 = update) | ||
226 | * | ||
227 | * Perform an update to a register @reg. @mask is used to specify which | ||
228 | * bits are updated. Returns %0 in case of success and negative errno in | ||
229 | * case of failure. | ||
230 | * | ||
231 | * Function may sleep. | ||
232 | */ | ||
233 | int intel_msic_reg_update(unsigned short reg, u8 val, u8 mask) | ||
234 | { | ||
235 | return intel_scu_ipc_update_register(reg, val, mask); | ||
236 | } | ||
237 | EXPORT_SYMBOL_GPL(intel_msic_reg_update); | ||
238 | |||
239 | /** | ||
240 | * intel_msic_bulk_read - read an array of registers | ||
241 | * @reg: array of register addresses to read | ||
242 | * @buf: array where the read values are placed | ||
243 | * @count: number of registers to read | ||
244 | * | ||
245 | * Function reads @count registers from the MSIC using addresses passed in | ||
246 | * @reg. Read values are placed in @buf. Reads are performed atomically | ||
247 | * wrt. MSIC. | ||
248 | * | ||
249 | * Returns %0 in case of success and negative errno in case of failure. | ||
250 | * | ||
251 | * Function may sleep. | ||
252 | */ | ||
253 | int intel_msic_bulk_read(unsigned short *reg, u8 *buf, size_t count) | ||
254 | { | ||
255 | if (WARN_ON(count > SCU_IPC_RWBUF_LIMIT)) | ||
256 | return -EINVAL; | ||
257 | |||
258 | return intel_scu_ipc_readv(reg, buf, count); | ||
259 | } | ||
260 | EXPORT_SYMBOL_GPL(intel_msic_bulk_read); | ||
261 | |||
262 | /** | ||
263 | * intel_msic_bulk_write - write an array of values to the MSIC registers | ||
264 | * @reg: array of registers to write | ||
265 | * @buf: values to write to each register | ||
266 | * @count: number of registers to write | ||
267 | * | ||
268 | * Function writes @count registers in @buf to MSIC. Writes are performed | ||
269 | * atomically wrt MSIC. Returns %0 in case of success and negative errno in | ||
270 | * case of failure. | ||
271 | * | ||
272 | * Function may sleep. | ||
273 | */ | ||
274 | int intel_msic_bulk_write(unsigned short *reg, u8 *buf, size_t count) | ||
275 | { | ||
276 | if (WARN_ON(count > SCU_IPC_RWBUF_LIMIT)) | ||
277 | return -EINVAL; | ||
278 | |||
279 | return intel_scu_ipc_writev(reg, buf, count); | ||
280 | } | ||
281 | EXPORT_SYMBOL_GPL(intel_msic_bulk_write); | ||
282 | |||
283 | /** | ||
284 | * intel_msic_irq_read - read a register from an MSIC interrupt tree | ||
285 | * @msic: MSIC instance | ||
286 | * @reg: interrupt register (between %INTEL_MSIC_IRQLVL1 and | ||
287 | * %INTEL_MSIC_RESETIRQ2) | ||
288 | * @val: value of the register is placed here | ||
289 | * | ||
290 | * This function can be used by an MSIC subdevice interrupt handler to read | ||
291 | * a register value from the MSIC interrupt tree. In this way subdevice | ||
292 | * drivers don't have to map in the interrupt tree themselves but can just | ||
293 | * call this function instead. | ||
294 | * | ||
295 | * Function doesn't sleep and is callable from interrupt context. | ||
296 | * | ||
297 | * Returns %-EINVAL if @reg is outside of the allowed register region. | ||
298 | */ | ||
299 | int intel_msic_irq_read(struct intel_msic *msic, unsigned short reg, u8 *val) | ||
300 | { | ||
301 | if (WARN_ON(reg < INTEL_MSIC_IRQLVL1 || reg > INTEL_MSIC_RESETIRQ2)) | ||
302 | return -EINVAL; | ||
303 | |||
304 | *val = readb(msic->irq_base + (reg - INTEL_MSIC_IRQLVL1)); | ||
305 | return 0; | ||
306 | } | ||
307 | EXPORT_SYMBOL_GPL(intel_msic_irq_read); | ||
308 | |||
309 | static int __devinit intel_msic_init_devices(struct intel_msic *msic) | ||
310 | { | ||
311 | struct platform_device *pdev = msic->pdev; | ||
312 | struct intel_msic_platform_data *pdata = pdev->dev.platform_data; | ||
313 | int ret, i; | ||
314 | |||
315 | if (pdata->gpio) { | ||
316 | struct mfd_cell *cell = &msic_devs[INTEL_MSIC_BLOCK_GPIO]; | ||
317 | |||
318 | cell->platform_data = pdata->gpio; | ||
319 | cell->pdata_size = sizeof(*pdata->gpio); | ||
320 | } | ||
321 | |||
322 | if (pdata->ocd) { | ||
323 | unsigned gpio = pdata->ocd->gpio; | ||
324 | |||
325 | ret = gpio_request_one(gpio, GPIOF_IN, "ocd_gpio"); | ||
326 | if (ret) { | ||
327 | dev_err(&pdev->dev, "failed to register OCD GPIO\n"); | ||
328 | return ret; | ||
329 | } | ||
330 | |||
331 | ret = gpio_to_irq(gpio); | ||
332 | if (ret < 0) { | ||
333 | dev_err(&pdev->dev, "no IRQ number for OCD GPIO\n"); | ||
334 | gpio_free(gpio); | ||
335 | return ret; | ||
336 | } | ||
337 | |||
338 | /* Update the IRQ number for the OCD */ | ||
339 | pdata->irq[INTEL_MSIC_BLOCK_OCD] = ret; | ||
340 | } | ||
341 | |||
342 | for (i = 0; i < ARRAY_SIZE(msic_devs); i++) { | ||
343 | if (!pdata->irq[i]) | ||
344 | continue; | ||
345 | |||
346 | ret = mfd_add_devices(&pdev->dev, -1, &msic_devs[i], 1, NULL, | ||
347 | pdata->irq[i]); | ||
348 | if (ret) | ||
349 | goto fail; | ||
350 | } | ||
351 | |||
352 | ret = mfd_add_devices(&pdev->dev, 0, msic_other_devs, | ||
353 | ARRAY_SIZE(msic_other_devs), NULL, 0); | ||
354 | if (ret) | ||
355 | goto fail; | ||
356 | |||
357 | return 0; | ||
358 | |||
359 | fail: | ||
360 | mfd_remove_devices(&pdev->dev); | ||
361 | if (pdata->ocd) | ||
362 | gpio_free(pdata->ocd->gpio); | ||
363 | |||
364 | return ret; | ||
365 | } | ||
366 | |||
367 | static void __devexit intel_msic_remove_devices(struct intel_msic *msic) | ||
368 | { | ||
369 | struct platform_device *pdev = msic->pdev; | ||
370 | struct intel_msic_platform_data *pdata = pdev->dev.platform_data; | ||
371 | |||
372 | mfd_remove_devices(&pdev->dev); | ||
373 | |||
374 | if (pdata->ocd) | ||
375 | gpio_free(pdata->ocd->gpio); | ||
376 | } | ||
377 | |||
378 | static int __devinit intel_msic_probe(struct platform_device *pdev) | ||
379 | { | ||
380 | struct intel_msic_platform_data *pdata = pdev->dev.platform_data; | ||
381 | struct intel_msic *msic; | ||
382 | struct resource *res; | ||
383 | u8 id0, id1; | ||
384 | int ret; | ||
385 | |||
386 | if (!pdata) { | ||
387 | dev_err(&pdev->dev, "no platform data passed\n"); | ||
388 | return -EINVAL; | ||
389 | } | ||
390 | |||
391 | /* First validate that we have an MSIC in place */ | ||
392 | ret = intel_scu_ipc_ioread8(INTEL_MSIC_ID0, &id0); | ||
393 | if (ret) { | ||
394 | dev_err(&pdev->dev, "failed to identify the MSIC chip (ID0)\n"); | ||
395 | return -ENXIO; | ||
396 | } | ||
397 | |||
398 | ret = intel_scu_ipc_ioread8(INTEL_MSIC_ID1, &id1); | ||
399 | if (ret) { | ||
400 | dev_err(&pdev->dev, "failed to identify the MSIC chip (ID1)\n"); | ||
401 | return -ENXIO; | ||
402 | } | ||
403 | |||
404 | if (MSIC_VENDOR(id0) != MSIC_VENDOR(id1)) { | ||
405 | dev_err(&pdev->dev, "invalid vendor ID: %x, %x\n", id0, id1); | ||
406 | return -ENXIO; | ||
407 | } | ||
408 | |||
409 | msic = kzalloc(sizeof(*msic), GFP_KERNEL); | ||
410 | if (!msic) | ||
411 | return -ENOMEM; | ||
412 | |||
413 | msic->vendor = MSIC_VENDOR(id0); | ||
414 | msic->version = MSIC_VERSION(id0); | ||
415 | msic->pdev = pdev; | ||
416 | |||
417 | /* | ||
418 | * Map in the MSIC interrupt tree area in SRAM. This is exposed to | ||
419 | * the clients via intel_msic_irq_read(). | ||
420 | */ | ||
421 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
422 | if (!res) { | ||
423 | dev_err(&pdev->dev, "failed to get SRAM iomem resource\n"); | ||
424 | ret = -ENODEV; | ||
425 | goto fail_free_msic; | ||
426 | } | ||
427 | |||
428 | res = request_mem_region(res->start, resource_size(res), pdev->name); | ||
429 | if (!res) { | ||
430 | ret = -EBUSY; | ||
431 | goto fail_free_msic; | ||
432 | } | ||
433 | |||
434 | msic->irq_base = ioremap_nocache(res->start, resource_size(res)); | ||
435 | if (!msic->irq_base) { | ||
436 | dev_err(&pdev->dev, "failed to map SRAM memory\n"); | ||
437 | ret = -ENOMEM; | ||
438 | goto fail_release_region; | ||
439 | } | ||
440 | |||
441 | platform_set_drvdata(pdev, msic); | ||
442 | |||
443 | ret = intel_msic_init_devices(msic); | ||
444 | if (ret) { | ||
445 | dev_err(&pdev->dev, "failed to initialize MSIC devices\n"); | ||
446 | goto fail_unmap_mem; | ||
447 | } | ||
448 | |||
449 | dev_info(&pdev->dev, "Intel MSIC version %c%d (vendor %#x)\n", | ||
450 | MSIC_MAJOR(msic->version), MSIC_MINOR(msic->version), | ||
451 | msic->vendor); | ||
452 | |||
453 | return 0; | ||
454 | |||
455 | fail_unmap_mem: | ||
456 | iounmap(msic->irq_base); | ||
457 | fail_release_region: | ||
458 | release_mem_region(res->start, resource_size(res)); | ||
459 | fail_free_msic: | ||
460 | kfree(msic); | ||
461 | |||
462 | return ret; | ||
463 | } | ||
464 | |||
465 | static int __devexit intel_msic_remove(struct platform_device *pdev) | ||
466 | { | ||
467 | struct intel_msic *msic = platform_get_drvdata(pdev); | ||
468 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
469 | |||
470 | intel_msic_remove_devices(msic); | ||
471 | platform_set_drvdata(pdev, NULL); | ||
472 | iounmap(msic->irq_base); | ||
473 | release_mem_region(res->start, resource_size(res)); | ||
474 | kfree(msic); | ||
475 | |||
476 | return 0; | ||
477 | } | ||
478 | |||
479 | static struct platform_driver intel_msic_driver = { | ||
480 | .probe = intel_msic_probe, | ||
481 | .remove = __devexit_p(intel_msic_remove), | ||
482 | .driver = { | ||
483 | .name = "intel_msic", | ||
484 | .owner = THIS_MODULE, | ||
485 | }, | ||
486 | }; | ||
487 | |||
488 | static int __init intel_msic_init(void) | ||
489 | { | ||
490 | return platform_driver_register(&intel_msic_driver); | ||
491 | } | ||
492 | module_init(intel_msic_init); | ||
493 | |||
494 | static void __exit intel_msic_exit(void) | ||
495 | { | ||
496 | platform_driver_unregister(&intel_msic_driver); | ||
497 | } | ||
498 | module_exit(intel_msic_exit); | ||
499 | |||
500 | MODULE_DESCRIPTION("Driver for Intel MSIC"); | ||
501 | MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>"); | ||
502 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/mfd/jz4740-adc.c b/drivers/mfd/jz4740-adc.c index 563654c9b19e..1e9ee533eacb 100644 --- a/drivers/mfd/jz4740-adc.c +++ b/drivers/mfd/jz4740-adc.c | |||
@@ -328,7 +328,7 @@ static int __devexit jz4740_adc_remove(struct platform_device *pdev) | |||
328 | return 0; | 328 | return 0; |
329 | } | 329 | } |
330 | 330 | ||
331 | struct platform_driver jz4740_adc_driver = { | 331 | static struct platform_driver jz4740_adc_driver = { |
332 | .probe = jz4740_adc_probe, | 332 | .probe = jz4740_adc_probe, |
333 | .remove = __devexit_p(jz4740_adc_remove), | 333 | .remove = __devexit_p(jz4740_adc_remove), |
334 | .driver = { | 334 | .driver = { |
diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c index 50ad93bb49dd..5be53ae9b61c 100644 --- a/drivers/mfd/max8997.c +++ b/drivers/mfd/max8997.c | |||
@@ -23,6 +23,7 @@ | |||
23 | 23 | ||
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/i2c.h> | 25 | #include <linux/i2c.h> |
26 | #include <linux/interrupt.h> | ||
26 | #include <linux/pm_runtime.h> | 27 | #include <linux/pm_runtime.h> |
27 | #include <linux/module.h> | 28 | #include <linux/module.h> |
28 | #include <linux/mutex.h> | 29 | #include <linux/mutex.h> |
@@ -143,7 +144,6 @@ static int max8997_i2c_probe(struct i2c_client *i2c, | |||
143 | 144 | ||
144 | max8997->irq_base = pdata->irq_base; | 145 | max8997->irq_base = pdata->irq_base; |
145 | max8997->ono = pdata->ono; | 146 | max8997->ono = pdata->ono; |
146 | max8997->wakeup = pdata->wakeup; | ||
147 | 147 | ||
148 | mutex_init(&max8997->iolock); | 148 | mutex_init(&max8997->iolock); |
149 | 149 | ||
@@ -170,6 +170,9 @@ static int max8997_i2c_probe(struct i2c_client *i2c, | |||
170 | if (ret < 0) | 170 | if (ret < 0) |
171 | goto err_mfd; | 171 | goto err_mfd; |
172 | 172 | ||
173 | /* MAX8997 has a power button input. */ | ||
174 | device_init_wakeup(max8997->dev, pdata->wakeup); | ||
175 | |||
173 | return ret; | 176 | return ret; |
174 | 177 | ||
175 | err_mfd: | 178 | err_mfd: |
@@ -399,7 +402,29 @@ static int max8997_restore(struct device *dev) | |||
399 | return 0; | 402 | return 0; |
400 | } | 403 | } |
401 | 404 | ||
405 | static int max8997_suspend(struct device *dev) | ||
406 | { | ||
407 | struct i2c_client *i2c = container_of(dev, struct i2c_client, dev); | ||
408 | struct max8997_dev *max8997 = i2c_get_clientdata(i2c); | ||
409 | |||
410 | if (device_may_wakeup(dev)) | ||
411 | irq_set_irq_wake(max8997->irq, 1); | ||
412 | return 0; | ||
413 | } | ||
414 | |||
415 | static int max8997_resume(struct device *dev) | ||
416 | { | ||
417 | struct i2c_client *i2c = container_of(dev, struct i2c_client, dev); | ||
418 | struct max8997_dev *max8997 = i2c_get_clientdata(i2c); | ||
419 | |||
420 | if (device_may_wakeup(dev)) | ||
421 | irq_set_irq_wake(max8997->irq, 0); | ||
422 | return max8997_irq_resume(max8997); | ||
423 | } | ||
424 | |||
402 | const struct dev_pm_ops max8997_pm = { | 425 | const struct dev_pm_ops max8997_pm = { |
426 | .suspend = max8997_suspend, | ||
427 | .resume = max8997_resume, | ||
403 | .freeze = max8997_freeze, | 428 | .freeze = max8997_freeze, |
404 | .restore = max8997_restore, | 429 | .restore = max8997_restore, |
405 | }; | 430 | }; |
diff --git a/drivers/mfd/mc13xxx-core.c b/drivers/mfd/mc13xxx-core.c index 7e4d44bf92ab..e9619acc0237 100644 --- a/drivers/mfd/mc13xxx-core.c +++ b/drivers/mfd/mc13xxx-core.c | |||
@@ -26,20 +26,10 @@ struct mc13xxx { | |||
26 | 26 | ||
27 | irq_handler_t irqhandler[MC13XXX_NUM_IRQ]; | 27 | irq_handler_t irqhandler[MC13XXX_NUM_IRQ]; |
28 | void *irqdata[MC13XXX_NUM_IRQ]; | 28 | void *irqdata[MC13XXX_NUM_IRQ]; |
29 | }; | ||
30 | |||
31 | struct mc13783 { | ||
32 | struct mc13xxx mc13xxx; | ||
33 | 29 | ||
34 | int adcflags; | 30 | int adcflags; |
35 | }; | 31 | }; |
36 | 32 | ||
37 | struct mc13xxx *mc13783_to_mc13xxx(struct mc13783 *mc13783) | ||
38 | { | ||
39 | return &mc13783->mc13xxx; | ||
40 | } | ||
41 | EXPORT_SYMBOL(mc13783_to_mc13xxx); | ||
42 | |||
43 | #define MC13XXX_IRQSTAT0 0 | 33 | #define MC13XXX_IRQSTAT0 0 |
44 | #define MC13XXX_IRQSTAT0_ADCDONEI (1 << 0) | 34 | #define MC13XXX_IRQSTAT0_ADCDONEI (1 << 0) |
45 | #define MC13XXX_IRQSTAT0_ADCBISDONEI (1 << 1) | 35 | #define MC13XXX_IRQSTAT0_ADCBISDONEI (1 << 1) |
@@ -136,14 +126,14 @@ EXPORT_SYMBOL(mc13783_to_mc13xxx); | |||
136 | #define MC13XXX_REVISION_FAB (0x03 << 11) | 126 | #define MC13XXX_REVISION_FAB (0x03 << 11) |
137 | #define MC13XXX_REVISION_ICIDCODE (0x3f << 13) | 127 | #define MC13XXX_REVISION_ICIDCODE (0x3f << 13) |
138 | 128 | ||
139 | #define MC13783_ADC1 44 | 129 | #define MC13XXX_ADC1 44 |
140 | #define MC13783_ADC1_ADEN (1 << 0) | 130 | #define MC13XXX_ADC1_ADEN (1 << 0) |
141 | #define MC13783_ADC1_RAND (1 << 1) | 131 | #define MC13XXX_ADC1_RAND (1 << 1) |
142 | #define MC13783_ADC1_ADSEL (1 << 3) | 132 | #define MC13XXX_ADC1_ADSEL (1 << 3) |
143 | #define MC13783_ADC1_ASC (1 << 20) | 133 | #define MC13XXX_ADC1_ASC (1 << 20) |
144 | #define MC13783_ADC1_ADTRIGIGN (1 << 21) | 134 | #define MC13XXX_ADC1_ADTRIGIGN (1 << 21) |
145 | 135 | ||
146 | #define MC13783_ADC2 45 | 136 | #define MC13XXX_ADC2 45 |
147 | 137 | ||
148 | #define MC13XXX_NUMREGS 0x3f | 138 | #define MC13XXX_NUMREGS 0x3f |
149 | 139 | ||
@@ -487,7 +477,7 @@ enum mc13xxx_id { | |||
487 | MC13XXX_ID_INVALID, | 477 | MC13XXX_ID_INVALID, |
488 | }; | 478 | }; |
489 | 479 | ||
490 | const char *mc13xxx_chipname[] = { | 480 | static const char *mc13xxx_chipname[] = { |
491 | [MC13XXX_ID_MC13783] = "mc13783", | 481 | [MC13XXX_ID_MC13783] = "mc13783", |
492 | [MC13XXX_ID_MC13892] = "mc13892", | 482 | [MC13XXX_ID_MC13892] = "mc13892", |
493 | }; | 483 | }; |
@@ -558,8 +548,6 @@ static const char *mc13xxx_get_chipname(struct mc13xxx *mc13xxx) | |||
558 | return mc13xxx_chipname[devid->driver_data]; | 548 | return mc13xxx_chipname[devid->driver_data]; |
559 | } | 549 | } |
560 | 550 | ||
561 | #include <linux/mfd/mc13783.h> | ||
562 | |||
563 | int mc13xxx_get_flags(struct mc13xxx *mc13xxx) | 551 | int mc13xxx_get_flags(struct mc13xxx *mc13xxx) |
564 | { | 552 | { |
565 | struct mc13xxx_platform_data *pdata = | 553 | struct mc13xxx_platform_data *pdata = |
@@ -569,15 +557,15 @@ int mc13xxx_get_flags(struct mc13xxx *mc13xxx) | |||
569 | } | 557 | } |
570 | EXPORT_SYMBOL(mc13xxx_get_flags); | 558 | EXPORT_SYMBOL(mc13xxx_get_flags); |
571 | 559 | ||
572 | #define MC13783_ADC1_CHAN0_SHIFT 5 | 560 | #define MC13XXX_ADC1_CHAN0_SHIFT 5 |
573 | #define MC13783_ADC1_CHAN1_SHIFT 8 | 561 | #define MC13XXX_ADC1_CHAN1_SHIFT 8 |
574 | 562 | ||
575 | struct mc13xxx_adcdone_data { | 563 | struct mc13xxx_adcdone_data { |
576 | struct mc13xxx *mc13xxx; | 564 | struct mc13xxx *mc13xxx; |
577 | struct completion done; | 565 | struct completion done; |
578 | }; | 566 | }; |
579 | 567 | ||
580 | static irqreturn_t mc13783_handler_adcdone(int irq, void *data) | 568 | static irqreturn_t mc13xxx_handler_adcdone(int irq, void *data) |
581 | { | 569 | { |
582 | struct mc13xxx_adcdone_data *adcdone_data = data; | 570 | struct mc13xxx_adcdone_data *adcdone_data = data; |
583 | 571 | ||
@@ -588,12 +576,11 @@ static irqreturn_t mc13783_handler_adcdone(int irq, void *data) | |||
588 | return IRQ_HANDLED; | 576 | return IRQ_HANDLED; |
589 | } | 577 | } |
590 | 578 | ||
591 | #define MC13783_ADC_WORKING (1 << 0) | 579 | #define MC13XXX_ADC_WORKING (1 << 0) |
592 | 580 | ||
593 | int mc13783_adc_do_conversion(struct mc13783 *mc13783, unsigned int mode, | 581 | int mc13xxx_adc_do_conversion(struct mc13xxx *mc13xxx, unsigned int mode, |
594 | unsigned int channel, unsigned int *sample) | 582 | unsigned int channel, unsigned int *sample) |
595 | { | 583 | { |
596 | struct mc13xxx *mc13xxx = &mc13783->mc13xxx; | ||
597 | u32 adc0, adc1, old_adc0; | 584 | u32 adc0, adc1, old_adc0; |
598 | int i, ret; | 585 | int i, ret; |
599 | struct mc13xxx_adcdone_data adcdone_data = { | 586 | struct mc13xxx_adcdone_data adcdone_data = { |
@@ -605,51 +592,51 @@ int mc13783_adc_do_conversion(struct mc13783 *mc13783, unsigned int mode, | |||
605 | 592 | ||
606 | mc13xxx_lock(mc13xxx); | 593 | mc13xxx_lock(mc13xxx); |
607 | 594 | ||
608 | if (mc13783->adcflags & MC13783_ADC_WORKING) { | 595 | if (mc13xxx->adcflags & MC13XXX_ADC_WORKING) { |
609 | ret = -EBUSY; | 596 | ret = -EBUSY; |
610 | goto out; | 597 | goto out; |
611 | } | 598 | } |
612 | 599 | ||
613 | mc13783->adcflags |= MC13783_ADC_WORKING; | 600 | mc13xxx->adcflags |= MC13XXX_ADC_WORKING; |
614 | 601 | ||
615 | mc13xxx_reg_read(mc13xxx, MC13783_ADC0, &old_adc0); | 602 | mc13xxx_reg_read(mc13xxx, MC13XXX_ADC0, &old_adc0); |
616 | 603 | ||
617 | adc0 = MC13783_ADC0_ADINC1 | MC13783_ADC0_ADINC2; | 604 | adc0 = MC13XXX_ADC0_ADINC1 | MC13XXX_ADC0_ADINC2; |
618 | adc1 = MC13783_ADC1_ADEN | MC13783_ADC1_ADTRIGIGN | MC13783_ADC1_ASC; | 605 | adc1 = MC13XXX_ADC1_ADEN | MC13XXX_ADC1_ADTRIGIGN | MC13XXX_ADC1_ASC; |
619 | 606 | ||
620 | if (channel > 7) | 607 | if (channel > 7) |
621 | adc1 |= MC13783_ADC1_ADSEL; | 608 | adc1 |= MC13XXX_ADC1_ADSEL; |
622 | 609 | ||
623 | switch (mode) { | 610 | switch (mode) { |
624 | case MC13783_ADC_MODE_TS: | 611 | case MC13XXX_ADC_MODE_TS: |
625 | adc0 |= MC13783_ADC0_ADREFEN | MC13783_ADC0_TSMOD0 | | 612 | adc0 |= MC13XXX_ADC0_ADREFEN | MC13XXX_ADC0_TSMOD0 | |
626 | MC13783_ADC0_TSMOD1; | 613 | MC13XXX_ADC0_TSMOD1; |
627 | adc1 |= 4 << MC13783_ADC1_CHAN1_SHIFT; | 614 | adc1 |= 4 << MC13XXX_ADC1_CHAN1_SHIFT; |
628 | break; | 615 | break; |
629 | 616 | ||
630 | case MC13783_ADC_MODE_SINGLE_CHAN: | 617 | case MC13XXX_ADC_MODE_SINGLE_CHAN: |
631 | adc0 |= old_adc0 & MC13783_ADC0_TSMOD_MASK; | 618 | adc0 |= old_adc0 & MC13XXX_ADC0_TSMOD_MASK; |
632 | adc1 |= (channel & 0x7) << MC13783_ADC1_CHAN0_SHIFT; | 619 | adc1 |= (channel & 0x7) << MC13XXX_ADC1_CHAN0_SHIFT; |
633 | adc1 |= MC13783_ADC1_RAND; | 620 | adc1 |= MC13XXX_ADC1_RAND; |
634 | break; | 621 | break; |
635 | 622 | ||
636 | case MC13783_ADC_MODE_MULT_CHAN: | 623 | case MC13XXX_ADC_MODE_MULT_CHAN: |
637 | adc0 |= old_adc0 & MC13783_ADC0_TSMOD_MASK; | 624 | adc0 |= old_adc0 & MC13XXX_ADC0_TSMOD_MASK; |
638 | adc1 |= 4 << MC13783_ADC1_CHAN1_SHIFT; | 625 | adc1 |= 4 << MC13XXX_ADC1_CHAN1_SHIFT; |
639 | break; | 626 | break; |
640 | 627 | ||
641 | default: | 628 | default: |
642 | mc13783_unlock(mc13783); | 629 | mc13xxx_unlock(mc13xxx); |
643 | return -EINVAL; | 630 | return -EINVAL; |
644 | } | 631 | } |
645 | 632 | ||
646 | dev_dbg(&mc13783->mc13xxx.spidev->dev, "%s: request irq\n", __func__); | 633 | dev_dbg(&mc13xxx->spidev->dev, "%s: request irq\n", __func__); |
647 | mc13xxx_irq_request(mc13xxx, MC13783_IRQ_ADCDONE, | 634 | mc13xxx_irq_request(mc13xxx, MC13XXX_IRQ_ADCDONE, |
648 | mc13783_handler_adcdone, __func__, &adcdone_data); | 635 | mc13xxx_handler_adcdone, __func__, &adcdone_data); |
649 | mc13xxx_irq_ack(mc13xxx, MC13783_IRQ_ADCDONE); | 636 | mc13xxx_irq_ack(mc13xxx, MC13XXX_IRQ_ADCDONE); |
650 | 637 | ||
651 | mc13xxx_reg_write(mc13xxx, MC13783_ADC0, adc0); | 638 | mc13xxx_reg_write(mc13xxx, MC13XXX_ADC0, adc0); |
652 | mc13xxx_reg_write(mc13xxx, MC13783_ADC1, adc1); | 639 | mc13xxx_reg_write(mc13xxx, MC13XXX_ADC1, adc1); |
653 | 640 | ||
654 | mc13xxx_unlock(mc13xxx); | 641 | mc13xxx_unlock(mc13xxx); |
655 | 642 | ||
@@ -660,27 +647,27 @@ int mc13783_adc_do_conversion(struct mc13783 *mc13783, unsigned int mode, | |||
660 | 647 | ||
661 | mc13xxx_lock(mc13xxx); | 648 | mc13xxx_lock(mc13xxx); |
662 | 649 | ||
663 | mc13xxx_irq_free(mc13xxx, MC13783_IRQ_ADCDONE, &adcdone_data); | 650 | mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_ADCDONE, &adcdone_data); |
664 | 651 | ||
665 | if (ret > 0) | 652 | if (ret > 0) |
666 | for (i = 0; i < 4; ++i) { | 653 | for (i = 0; i < 4; ++i) { |
667 | ret = mc13xxx_reg_read(mc13xxx, | 654 | ret = mc13xxx_reg_read(mc13xxx, |
668 | MC13783_ADC2, &sample[i]); | 655 | MC13XXX_ADC2, &sample[i]); |
669 | if (ret) | 656 | if (ret) |
670 | break; | 657 | break; |
671 | } | 658 | } |
672 | 659 | ||
673 | if (mode == MC13783_ADC_MODE_TS) | 660 | if (mode == MC13XXX_ADC_MODE_TS) |
674 | /* restore TSMOD */ | 661 | /* restore TSMOD */ |
675 | mc13xxx_reg_write(mc13xxx, MC13783_ADC0, old_adc0); | 662 | mc13xxx_reg_write(mc13xxx, MC13XXX_ADC0, old_adc0); |
676 | 663 | ||
677 | mc13783->adcflags &= ~MC13783_ADC_WORKING; | 664 | mc13xxx->adcflags &= ~MC13XXX_ADC_WORKING; |
678 | out: | 665 | out: |
679 | mc13xxx_unlock(mc13xxx); | 666 | mc13xxx_unlock(mc13xxx); |
680 | 667 | ||
681 | return ret; | 668 | return ret; |
682 | } | 669 | } |
683 | EXPORT_SYMBOL_GPL(mc13783_adc_do_conversion); | 670 | EXPORT_SYMBOL_GPL(mc13xxx_adc_do_conversion); |
684 | 671 | ||
685 | static int mc13xxx_add_subdevice_pdata(struct mc13xxx *mc13xxx, | 672 | static int mc13xxx_add_subdevice_pdata(struct mc13xxx *mc13xxx, |
686 | const char *format, void *pdata, size_t pdata_size) | 673 | const char *format, void *pdata, size_t pdata_size) |
@@ -716,6 +703,11 @@ static int mc13xxx_probe(struct spi_device *spi) | |||
716 | enum mc13xxx_id id; | 703 | enum mc13xxx_id id; |
717 | int ret; | 704 | int ret; |
718 | 705 | ||
706 | if (!pdata) { | ||
707 | dev_err(&spi->dev, "invalid platform data\n"); | ||
708 | return -EINVAL; | ||
709 | } | ||
710 | |||
719 | mc13xxx = kzalloc(sizeof(*mc13xxx), GFP_KERNEL); | 711 | mc13xxx = kzalloc(sizeof(*mc13xxx), GFP_KERNEL); |
720 | if (!mc13xxx) | 712 | if (!mc13xxx) |
721 | return -ENOMEM; | 713 | return -ENOMEM; |
@@ -763,10 +755,8 @@ err_revision: | |||
763 | if (pdata->flags & MC13XXX_USE_CODEC) | 755 | if (pdata->flags & MC13XXX_USE_CODEC) |
764 | mc13xxx_add_subdevice(mc13xxx, "%s-codec"); | 756 | mc13xxx_add_subdevice(mc13xxx, "%s-codec"); |
765 | 757 | ||
766 | if (pdata->flags & MC13XXX_USE_REGULATOR) { | 758 | mc13xxx_add_subdevice_pdata(mc13xxx, "%s-regulator", |
767 | mc13xxx_add_subdevice_pdata(mc13xxx, "%s-regulator", | 759 | &pdata->regulators, sizeof(pdata->regulators)); |
768 | &pdata->regulators, sizeof(pdata->regulators)); | ||
769 | } | ||
770 | 760 | ||
771 | if (pdata->flags & MC13XXX_USE_RTC) | 761 | if (pdata->flags & MC13XXX_USE_RTC) |
772 | mc13xxx_add_subdevice(mc13xxx, "%s-rtc"); | 762 | mc13xxx_add_subdevice(mc13xxx, "%s-rtc"); |
@@ -774,10 +764,14 @@ err_revision: | |||
774 | if (pdata->flags & MC13XXX_USE_TOUCHSCREEN) | 764 | if (pdata->flags & MC13XXX_USE_TOUCHSCREEN) |
775 | mc13xxx_add_subdevice(mc13xxx, "%s-ts"); | 765 | mc13xxx_add_subdevice(mc13xxx, "%s-ts"); |
776 | 766 | ||
777 | if (pdata->flags & MC13XXX_USE_LED) | 767 | if (pdata->leds) |
778 | mc13xxx_add_subdevice_pdata(mc13xxx, "%s-led", | 768 | mc13xxx_add_subdevice_pdata(mc13xxx, "%s-led", |
779 | pdata->leds, sizeof(*pdata->leds)); | 769 | pdata->leds, sizeof(*pdata->leds)); |
780 | 770 | ||
771 | if (pdata->buttons) | ||
772 | mc13xxx_add_subdevice_pdata(mc13xxx, "%s-pwrbutton", | ||
773 | pdata->buttons, sizeof(*pdata->buttons)); | ||
774 | |||
781 | return 0; | 775 | return 0; |
782 | } | 776 | } |
783 | 777 | ||
diff --git a/drivers/mfd/menelaus.c b/drivers/mfd/menelaus.c index af5d9d061371..cb4910ac4d12 100644 --- a/drivers/mfd/menelaus.c +++ b/drivers/mfd/menelaus.c | |||
@@ -1226,7 +1226,7 @@ static int menelaus_probe(struct i2c_client *client, | |||
1226 | menelaus_write_reg(MENELAUS_MCT_CTRL1, 0x73); | 1226 | menelaus_write_reg(MENELAUS_MCT_CTRL1, 0x73); |
1227 | 1227 | ||
1228 | if (client->irq > 0) { | 1228 | if (client->irq > 0) { |
1229 | err = request_irq(client->irq, menelaus_irq, IRQF_DISABLED, | 1229 | err = request_irq(client->irq, menelaus_irq, 0, |
1230 | DRIVER_NAME, menelaus); | 1230 | DRIVER_NAME, menelaus); |
1231 | if (err) { | 1231 | if (err) { |
1232 | dev_dbg(&client->dev, "can't get IRQ %d, err %d\n", | 1232 | dev_dbg(&client->dev, "can't get IRQ %d, err %d\n", |
diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c index 57868416c760..ff1a7e741ecd 100644 --- a/drivers/mfd/pcf50633-core.c +++ b/drivers/mfd/pcf50633-core.c | |||
@@ -23,45 +23,22 @@ | |||
23 | #include <linux/i2c.h> | 23 | #include <linux/i2c.h> |
24 | #include <linux/pm.h> | 24 | #include <linux/pm.h> |
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/regmap.h> | ||
27 | #include <linux/err.h> | ||
26 | 28 | ||
27 | #include <linux/mfd/pcf50633/core.h> | 29 | #include <linux/mfd/pcf50633/core.h> |
28 | 30 | ||
29 | static int __pcf50633_read(struct pcf50633 *pcf, u8 reg, int num, u8 *data) | ||
30 | { | ||
31 | int ret; | ||
32 | |||
33 | ret = i2c_smbus_read_i2c_block_data(pcf->i2c_client, reg, | ||
34 | num, data); | ||
35 | if (ret < 0) | ||
36 | dev_err(pcf->dev, "Error reading %d regs at %d\n", num, reg); | ||
37 | |||
38 | return ret; | ||
39 | } | ||
40 | |||
41 | static int __pcf50633_write(struct pcf50633 *pcf, u8 reg, int num, u8 *data) | ||
42 | { | ||
43 | int ret; | ||
44 | |||
45 | ret = i2c_smbus_write_i2c_block_data(pcf->i2c_client, reg, | ||
46 | num, data); | ||
47 | if (ret < 0) | ||
48 | dev_err(pcf->dev, "Error writing %d regs at %d\n", num, reg); | ||
49 | |||
50 | return ret; | ||
51 | |||
52 | } | ||
53 | |||
54 | /* Read a block of up to 32 regs */ | 31 | /* Read a block of up to 32 regs */ |
55 | int pcf50633_read_block(struct pcf50633 *pcf, u8 reg, | 32 | int pcf50633_read_block(struct pcf50633 *pcf, u8 reg, |
56 | int nr_regs, u8 *data) | 33 | int nr_regs, u8 *data) |
57 | { | 34 | { |
58 | int ret; | 35 | int ret; |
59 | 36 | ||
60 | mutex_lock(&pcf->lock); | 37 | ret = regmap_raw_read(pcf->regmap, reg, data, nr_regs); |
61 | ret = __pcf50633_read(pcf, reg, nr_regs, data); | 38 | if (ret != 0) |
62 | mutex_unlock(&pcf->lock); | 39 | return ret; |
63 | 40 | ||
64 | return ret; | 41 | return nr_regs; |
65 | } | 42 | } |
66 | EXPORT_SYMBOL_GPL(pcf50633_read_block); | 43 | EXPORT_SYMBOL_GPL(pcf50633_read_block); |
67 | 44 | ||
@@ -71,21 +48,22 @@ int pcf50633_write_block(struct pcf50633 *pcf , u8 reg, | |||
71 | { | 48 | { |
72 | int ret; | 49 | int ret; |
73 | 50 | ||
74 | mutex_lock(&pcf->lock); | 51 | ret = regmap_raw_write(pcf->regmap, reg, data, nr_regs); |
75 | ret = __pcf50633_write(pcf, reg, nr_regs, data); | 52 | if (ret != 0) |
76 | mutex_unlock(&pcf->lock); | 53 | return ret; |
77 | 54 | ||
78 | return ret; | 55 | return nr_regs; |
79 | } | 56 | } |
80 | EXPORT_SYMBOL_GPL(pcf50633_write_block); | 57 | EXPORT_SYMBOL_GPL(pcf50633_write_block); |
81 | 58 | ||
82 | u8 pcf50633_reg_read(struct pcf50633 *pcf, u8 reg) | 59 | u8 pcf50633_reg_read(struct pcf50633 *pcf, u8 reg) |
83 | { | 60 | { |
84 | u8 val; | 61 | unsigned int val; |
62 | int ret; | ||
85 | 63 | ||
86 | mutex_lock(&pcf->lock); | 64 | ret = regmap_read(pcf->regmap, reg, &val); |
87 | __pcf50633_read(pcf, reg, 1, &val); | 65 | if (ret < 0) |
88 | mutex_unlock(&pcf->lock); | 66 | return -1; |
89 | 67 | ||
90 | return val; | 68 | return val; |
91 | } | 69 | } |
@@ -93,56 +71,19 @@ EXPORT_SYMBOL_GPL(pcf50633_reg_read); | |||
93 | 71 | ||
94 | int pcf50633_reg_write(struct pcf50633 *pcf, u8 reg, u8 val) | 72 | int pcf50633_reg_write(struct pcf50633 *pcf, u8 reg, u8 val) |
95 | { | 73 | { |
96 | int ret; | 74 | return regmap_write(pcf->regmap, reg, val); |
97 | |||
98 | mutex_lock(&pcf->lock); | ||
99 | ret = __pcf50633_write(pcf, reg, 1, &val); | ||
100 | mutex_unlock(&pcf->lock); | ||
101 | |||
102 | return ret; | ||
103 | } | 75 | } |
104 | EXPORT_SYMBOL_GPL(pcf50633_reg_write); | 76 | EXPORT_SYMBOL_GPL(pcf50633_reg_write); |
105 | 77 | ||
106 | int pcf50633_reg_set_bit_mask(struct pcf50633 *pcf, u8 reg, u8 mask, u8 val) | 78 | int pcf50633_reg_set_bit_mask(struct pcf50633 *pcf, u8 reg, u8 mask, u8 val) |
107 | { | 79 | { |
108 | int ret; | 80 | return regmap_update_bits(pcf->regmap, reg, mask, val); |
109 | u8 tmp; | ||
110 | |||
111 | val &= mask; | ||
112 | |||
113 | mutex_lock(&pcf->lock); | ||
114 | ret = __pcf50633_read(pcf, reg, 1, &tmp); | ||
115 | if (ret < 0) | ||
116 | goto out; | ||
117 | |||
118 | tmp &= ~mask; | ||
119 | tmp |= val; | ||
120 | ret = __pcf50633_write(pcf, reg, 1, &tmp); | ||
121 | |||
122 | out: | ||
123 | mutex_unlock(&pcf->lock); | ||
124 | |||
125 | return ret; | ||
126 | } | 81 | } |
127 | EXPORT_SYMBOL_GPL(pcf50633_reg_set_bit_mask); | 82 | EXPORT_SYMBOL_GPL(pcf50633_reg_set_bit_mask); |
128 | 83 | ||
129 | int pcf50633_reg_clear_bits(struct pcf50633 *pcf, u8 reg, u8 val) | 84 | int pcf50633_reg_clear_bits(struct pcf50633 *pcf, u8 reg, u8 val) |
130 | { | 85 | { |
131 | int ret; | 86 | return regmap_update_bits(pcf->regmap, reg, val, 0); |
132 | u8 tmp; | ||
133 | |||
134 | mutex_lock(&pcf->lock); | ||
135 | ret = __pcf50633_read(pcf, reg, 1, &tmp); | ||
136 | if (ret < 0) | ||
137 | goto out; | ||
138 | |||
139 | tmp &= ~val; | ||
140 | ret = __pcf50633_write(pcf, reg, 1, &tmp); | ||
141 | |||
142 | out: | ||
143 | mutex_unlock(&pcf->lock); | ||
144 | |||
145 | return ret; | ||
146 | } | 87 | } |
147 | EXPORT_SYMBOL_GPL(pcf50633_reg_clear_bits); | 88 | EXPORT_SYMBOL_GPL(pcf50633_reg_clear_bits); |
148 | 89 | ||
@@ -251,6 +192,11 @@ static int pcf50633_resume(struct device *dev) | |||
251 | 192 | ||
252 | static SIMPLE_DEV_PM_OPS(pcf50633_pm, pcf50633_suspend, pcf50633_resume); | 193 | static SIMPLE_DEV_PM_OPS(pcf50633_pm, pcf50633_suspend, pcf50633_resume); |
253 | 194 | ||
195 | static struct regmap_config pcf50633_regmap_config = { | ||
196 | .reg_bits = 8, | ||
197 | .val_bits = 8, | ||
198 | }; | ||
199 | |||
254 | static int __devinit pcf50633_probe(struct i2c_client *client, | 200 | static int __devinit pcf50633_probe(struct i2c_client *client, |
255 | const struct i2c_device_id *ids) | 201 | const struct i2c_device_id *ids) |
256 | { | 202 | { |
@@ -272,16 +218,23 @@ static int __devinit pcf50633_probe(struct i2c_client *client, | |||
272 | 218 | ||
273 | mutex_init(&pcf->lock); | 219 | mutex_init(&pcf->lock); |
274 | 220 | ||
221 | pcf->regmap = regmap_init_i2c(client, &pcf50633_regmap_config); | ||
222 | if (IS_ERR(pcf->regmap)) { | ||
223 | ret = PTR_ERR(pcf->regmap); | ||
224 | dev_err(pcf->dev, "Failed to allocate register map: %d\n", | ||
225 | ret); | ||
226 | goto err_free; | ||
227 | } | ||
228 | |||
275 | i2c_set_clientdata(client, pcf); | 229 | i2c_set_clientdata(client, pcf); |
276 | pcf->dev = &client->dev; | 230 | pcf->dev = &client->dev; |
277 | pcf->i2c_client = client; | ||
278 | 231 | ||
279 | version = pcf50633_reg_read(pcf, 0); | 232 | version = pcf50633_reg_read(pcf, 0); |
280 | variant = pcf50633_reg_read(pcf, 1); | 233 | variant = pcf50633_reg_read(pcf, 1); |
281 | if (version < 0 || variant < 0) { | 234 | if (version < 0 || variant < 0) { |
282 | dev_err(pcf->dev, "Unable to probe pcf50633\n"); | 235 | dev_err(pcf->dev, "Unable to probe pcf50633\n"); |
283 | ret = -ENODEV; | 236 | ret = -ENODEV; |
284 | goto err_free; | 237 | goto err_regmap; |
285 | } | 238 | } |
286 | 239 | ||
287 | dev_info(pcf->dev, "Probed device version %d variant %d\n", | 240 | dev_info(pcf->dev, "Probed device version %d variant %d\n", |
@@ -328,6 +281,8 @@ static int __devinit pcf50633_probe(struct i2c_client *client, | |||
328 | 281 | ||
329 | return 0; | 282 | return 0; |
330 | 283 | ||
284 | err_regmap: | ||
285 | regmap_exit(pcf->regmap); | ||
331 | err_free: | 286 | err_free: |
332 | kfree(pcf); | 287 | kfree(pcf); |
333 | 288 | ||
@@ -351,6 +306,7 @@ static int __devexit pcf50633_remove(struct i2c_client *client) | |||
351 | for (i = 0; i < PCF50633_NUM_REGULATORS; i++) | 306 | for (i = 0; i < PCF50633_NUM_REGULATORS; i++) |
352 | platform_device_unregister(pcf->regulator_pdev[i]); | 307 | platform_device_unregister(pcf->regulator_pdev[i]); |
353 | 308 | ||
309 | regmap_exit(pcf->regmap); | ||
354 | kfree(pcf); | 310 | kfree(pcf); |
355 | 311 | ||
356 | return 0; | 312 | return 0; |
diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c index c27e515b0722..de979742c6fc 100644 --- a/drivers/mfd/tc3589x.c +++ b/drivers/mfd/tc3589x.c | |||
@@ -357,6 +357,7 @@ static int __devexit tc3589x_remove(struct i2c_client *client) | |||
357 | return 0; | 357 | return 0; |
358 | } | 358 | } |
359 | 359 | ||
360 | #ifdef CONFIG_PM | ||
360 | static int tc3589x_suspend(struct device *dev) | 361 | static int tc3589x_suspend(struct device *dev) |
361 | { | 362 | { |
362 | struct tc3589x *tc3589x = dev_get_drvdata(dev); | 363 | struct tc3589x *tc3589x = dev_get_drvdata(dev); |
@@ -387,6 +388,7 @@ static int tc3589x_resume(struct device *dev) | |||
387 | 388 | ||
388 | static const SIMPLE_DEV_PM_OPS(tc3589x_dev_pm_ops, tc3589x_suspend, | 389 | static const SIMPLE_DEV_PM_OPS(tc3589x_dev_pm_ops, tc3589x_suspend, |
389 | tc3589x_resume); | 390 | tc3589x_resume); |
391 | #endif | ||
390 | 392 | ||
391 | static const struct i2c_device_id tc3589x_id[] = { | 393 | static const struct i2c_device_id tc3589x_id[] = { |
392 | { "tc3589x", 24 }, | 394 | { "tc3589x", 24 }, |
diff --git a/drivers/mfd/timberdale.c b/drivers/mfd/timberdale.c index 696879e2eef7..02d65692ceb4 100644 --- a/drivers/mfd/timberdale.c +++ b/drivers/mfd/timberdale.c | |||
@@ -697,7 +697,7 @@ static int __devinit timb_probe(struct pci_dev *dev, | |||
697 | dev_err(&dev->dev, "The driver supports an older " | 697 | dev_err(&dev->dev, "The driver supports an older " |
698 | "version of the FPGA, please update the driver to " | 698 | "version of the FPGA, please update the driver to " |
699 | "support %d.%d\n", priv->fw.major, priv->fw.minor); | 699 | "support %d.%d\n", priv->fw.major, priv->fw.minor); |
700 | goto err_ioremap; | 700 | goto err_config; |
701 | } | 701 | } |
702 | if (priv->fw.major < TIMB_SUPPORTED_MAJOR || | 702 | if (priv->fw.major < TIMB_SUPPORTED_MAJOR || |
703 | priv->fw.minor < TIMB_REQUIRED_MINOR) { | 703 | priv->fw.minor < TIMB_REQUIRED_MINOR) { |
@@ -705,13 +705,13 @@ static int __devinit timb_probe(struct pci_dev *dev, | |||
705 | "please upgrade the FPGA to at least: %d.%d\n", | 705 | "please upgrade the FPGA to at least: %d.%d\n", |
706 | priv->fw.major, priv->fw.minor, | 706 | priv->fw.major, priv->fw.minor, |
707 | TIMB_SUPPORTED_MAJOR, TIMB_REQUIRED_MINOR); | 707 | TIMB_SUPPORTED_MAJOR, TIMB_REQUIRED_MINOR); |
708 | goto err_ioremap; | 708 | goto err_config; |
709 | } | 709 | } |
710 | 710 | ||
711 | msix_entries = kzalloc(TIMBERDALE_NR_IRQS * sizeof(*msix_entries), | 711 | msix_entries = kzalloc(TIMBERDALE_NR_IRQS * sizeof(*msix_entries), |
712 | GFP_KERNEL); | 712 | GFP_KERNEL); |
713 | if (!msix_entries) | 713 | if (!msix_entries) |
714 | goto err_ioremap; | 714 | goto err_config; |
715 | 715 | ||
716 | for (i = 0; i < TIMBERDALE_NR_IRQS; i++) | 716 | for (i = 0; i < TIMBERDALE_NR_IRQS; i++) |
717 | msix_entries[i].entry = i; | 717 | msix_entries[i].entry = i; |
@@ -825,6 +825,8 @@ err_mfd: | |||
825 | err_create_file: | 825 | err_create_file: |
826 | pci_disable_msix(dev); | 826 | pci_disable_msix(dev); |
827 | err_msix: | 827 | err_msix: |
828 | kfree(msix_entries); | ||
829 | err_config: | ||
828 | iounmap(priv->ctl_membase); | 830 | iounmap(priv->ctl_membase); |
829 | err_ioremap: | 831 | err_ioremap: |
830 | release_mem_region(priv->ctl_mapbase, CHIPCTLSIZE); | 832 | release_mem_region(priv->ctl_mapbase, CHIPCTLSIZE); |
@@ -833,7 +835,6 @@ err_request: | |||
833 | err_start: | 835 | err_start: |
834 | pci_disable_device(dev); | 836 | pci_disable_device(dev); |
835 | err_enable: | 837 | err_enable: |
836 | kfree(msix_entries); | ||
837 | kfree(priv); | 838 | kfree(priv); |
838 | pci_set_drvdata(dev, NULL); | 839 | pci_set_drvdata(dev, NULL); |
839 | return -ENODEV; | 840 | return -ENODEV; |
diff --git a/drivers/mfd/tps65912-core.c b/drivers/mfd/tps65912-core.c index 955bc00e4b20..5fec23a9ac03 100644 --- a/drivers/mfd/tps65912-core.c +++ b/drivers/mfd/tps65912-core.c | |||
@@ -131,9 +131,6 @@ int tps65912_device_init(struct tps65912 *tps65912) | |||
131 | if (init_data == NULL) | 131 | if (init_data == NULL) |
132 | return -ENOMEM; | 132 | return -ENOMEM; |
133 | 133 | ||
134 | init_data->irq = pmic_plat_data->irq; | ||
135 | init_data->irq_base = pmic_plat_data->irq; | ||
136 | |||
137 | mutex_init(&tps65912->io_mutex); | 134 | mutex_init(&tps65912->io_mutex); |
138 | dev_set_drvdata(tps65912->dev, tps65912); | 135 | dev_set_drvdata(tps65912->dev, tps65912); |
139 | 136 | ||
@@ -153,10 +150,13 @@ int tps65912_device_init(struct tps65912 *tps65912) | |||
153 | if (ret < 0) | 150 | if (ret < 0) |
154 | goto err; | 151 | goto err; |
155 | 152 | ||
153 | init_data->irq = pmic_plat_data->irq; | ||
154 | init_data->irq_base = pmic_plat_data->irq; | ||
156 | ret = tps65912_irq_init(tps65912, init_data->irq, init_data); | 155 | ret = tps65912_irq_init(tps65912, init_data->irq, init_data); |
157 | if (ret < 0) | 156 | if (ret < 0) |
158 | goto err; | 157 | goto err; |
159 | 158 | ||
159 | kfree(init_data); | ||
160 | return ret; | 160 | return ret; |
161 | 161 | ||
162 | err: | 162 | err: |
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index 61120fec8895..bfbd66021afd 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c | |||
@@ -110,7 +110,7 @@ | |||
110 | #define twl_has_watchdog() false | 110 | #define twl_has_watchdog() false |
111 | #endif | 111 | #endif |
112 | 112 | ||
113 | #if defined(CONFIG_TWL4030_CODEC) || defined(CONFIG_TWL4030_CODEC_MODULE) ||\ | 113 | #if defined(CONFIG_MFD_TWL4030_AUDIO) || defined(CONFIG_MFD_TWL4030_AUDIO_MODULE) ||\ |
114 | defined(CONFIG_TWL6040_CORE) || defined(CONFIG_TWL6040_CORE_MODULE) | 114 | defined(CONFIG_TWL6040_CORE) || defined(CONFIG_TWL6040_CORE_MODULE) |
115 | #define twl_has_codec() true | 115 | #define twl_has_codec() true |
116 | #else | 116 | #else |
diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c index 8a7ee3139b86..f062c8cc6c38 100644 --- a/drivers/mfd/twl4030-irq.c +++ b/drivers/mfd/twl4030-irq.c | |||
@@ -30,7 +30,6 @@ | |||
30 | #include <linux/init.h> | 30 | #include <linux/init.h> |
31 | #include <linux/interrupt.h> | 31 | #include <linux/interrupt.h> |
32 | #include <linux/irq.h> | 32 | #include <linux/irq.h> |
33 | #include <linux/kthread.h> | ||
34 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
35 | 34 | ||
36 | #include <linux/i2c/twl.h> | 35 | #include <linux/i2c/twl.h> |
@@ -278,59 +277,6 @@ static const struct sih sih_modules_twl5031[8] = { | |||
278 | 277 | ||
279 | static unsigned twl4030_irq_base; | 278 | static unsigned twl4030_irq_base; |
280 | 279 | ||
281 | static struct completion irq_event; | ||
282 | |||
283 | /* | ||
284 | * This thread processes interrupts reported by the Primary Interrupt Handler. | ||
285 | */ | ||
286 | static int twl4030_irq_thread(void *data) | ||
287 | { | ||
288 | long irq = (long)data; | ||
289 | static unsigned i2c_errors; | ||
290 | static const unsigned max_i2c_errors = 100; | ||
291 | |||
292 | |||
293 | current->flags |= PF_NOFREEZE; | ||
294 | |||
295 | while (!kthread_should_stop()) { | ||
296 | int ret; | ||
297 | int module_irq; | ||
298 | u8 pih_isr; | ||
299 | |||
300 | /* Wait for IRQ, then read PIH irq status (also blocking) */ | ||
301 | wait_for_completion_interruptible(&irq_event); | ||
302 | |||
303 | ret = twl_i2c_read_u8(TWL4030_MODULE_PIH, &pih_isr, | ||
304 | REG_PIH_ISR_P1); | ||
305 | if (ret) { | ||
306 | pr_warning("twl4030: I2C error %d reading PIH ISR\n", | ||
307 | ret); | ||
308 | if (++i2c_errors >= max_i2c_errors) { | ||
309 | printk(KERN_ERR "Maximum I2C error count" | ||
310 | " exceeded. Terminating %s.\n", | ||
311 | __func__); | ||
312 | break; | ||
313 | } | ||
314 | complete(&irq_event); | ||
315 | continue; | ||
316 | } | ||
317 | |||
318 | /* these handlers deal with the relevant SIH irq status */ | ||
319 | local_irq_disable(); | ||
320 | for (module_irq = twl4030_irq_base; | ||
321 | pih_isr; | ||
322 | pih_isr >>= 1, module_irq++) { | ||
323 | if (pih_isr & 0x1) | ||
324 | generic_handle_irq(module_irq); | ||
325 | } | ||
326 | local_irq_enable(); | ||
327 | |||
328 | enable_irq(irq); | ||
329 | } | ||
330 | |||
331 | return 0; | ||
332 | } | ||
333 | |||
334 | /* | 280 | /* |
335 | * handle_twl4030_pih() is the desc->handle method for the twl4030 interrupt. | 281 | * handle_twl4030_pih() is the desc->handle method for the twl4030 interrupt. |
336 | * This is a chained interrupt, so there is no desc->action method for it. | 282 | * This is a chained interrupt, so there is no desc->action method for it. |
@@ -342,9 +288,25 @@ static int twl4030_irq_thread(void *data) | |||
342 | */ | 288 | */ |
343 | static irqreturn_t handle_twl4030_pih(int irq, void *devid) | 289 | static irqreturn_t handle_twl4030_pih(int irq, void *devid) |
344 | { | 290 | { |
345 | /* Acknowledge, clear *AND* mask the interrupt... */ | 291 | int module_irq; |
346 | disable_irq_nosync(irq); | 292 | irqreturn_t ret; |
347 | complete(devid); | 293 | u8 pih_isr; |
294 | |||
295 | ret = twl_i2c_read_u8(TWL4030_MODULE_PIH, &pih_isr, | ||
296 | REG_PIH_ISR_P1); | ||
297 | if (ret) { | ||
298 | pr_warning("twl4030: I2C error %d reading PIH ISR\n", ret); | ||
299 | return IRQ_NONE; | ||
300 | } | ||
301 | |||
302 | /* these handlers deal with the relevant SIH irq status */ | ||
303 | for (module_irq = twl4030_irq_base; | ||
304 | pih_isr; | ||
305 | pih_isr >>= 1, module_irq++) { | ||
306 | if (pih_isr & 0x1) | ||
307 | handle_nested_irq(module_irq); | ||
308 | } | ||
309 | |||
348 | return IRQ_HANDLED; | 310 | return IRQ_HANDLED; |
349 | } | 311 | } |
350 | /*----------------------------------------------------------------------*/ | 312 | /*----------------------------------------------------------------------*/ |
@@ -460,113 +422,17 @@ static inline void activate_irq(int irq) | |||
460 | 422 | ||
461 | /*----------------------------------------------------------------------*/ | 423 | /*----------------------------------------------------------------------*/ |
462 | 424 | ||
463 | static DEFINE_SPINLOCK(sih_agent_lock); | ||
464 | |||
465 | static struct workqueue_struct *wq; | ||
466 | |||
467 | struct sih_agent { | 425 | struct sih_agent { |
468 | int irq_base; | 426 | int irq_base; |
469 | const struct sih *sih; | 427 | const struct sih *sih; |
470 | 428 | ||
471 | u32 imr; | 429 | u32 imr; |
472 | bool imr_change_pending; | 430 | bool imr_change_pending; |
473 | struct work_struct mask_work; | ||
474 | |||
475 | u32 edge_change; | ||
476 | struct work_struct edge_work; | ||
477 | }; | ||
478 | |||
479 | static void twl4030_sih_do_mask(struct work_struct *work) | ||
480 | { | ||
481 | struct sih_agent *agent; | ||
482 | const struct sih *sih; | ||
483 | union { | ||
484 | u8 bytes[4]; | ||
485 | u32 word; | ||
486 | } imr; | ||
487 | int status; | ||
488 | 431 | ||
489 | agent = container_of(work, struct sih_agent, mask_work); | ||
490 | |||
491 | /* see what work we have */ | ||
492 | spin_lock_irq(&sih_agent_lock); | ||
493 | if (agent->imr_change_pending) { | ||
494 | sih = agent->sih; | ||
495 | /* byte[0] gets overwritten as we write ... */ | ||
496 | imr.word = cpu_to_le32(agent->imr << 8); | ||
497 | agent->imr_change_pending = false; | ||
498 | } else | ||
499 | sih = NULL; | ||
500 | spin_unlock_irq(&sih_agent_lock); | ||
501 | if (!sih) | ||
502 | return; | ||
503 | |||
504 | /* write the whole mask ... simpler than subsetting it */ | ||
505 | status = twl_i2c_write(sih->module, imr.bytes, | ||
506 | sih->mask[irq_line].imr_offset, sih->bytes_ixr); | ||
507 | if (status) | ||
508 | pr_err("twl4030: %s, %s --> %d\n", __func__, | ||
509 | "write", status); | ||
510 | } | ||
511 | |||
512 | static void twl4030_sih_do_edge(struct work_struct *work) | ||
513 | { | ||
514 | struct sih_agent *agent; | ||
515 | const struct sih *sih; | ||
516 | u8 bytes[6]; | ||
517 | u32 edge_change; | 432 | u32 edge_change; |
518 | int status; | ||
519 | |||
520 | agent = container_of(work, struct sih_agent, edge_work); | ||
521 | |||
522 | /* see what work we have */ | ||
523 | spin_lock_irq(&sih_agent_lock); | ||
524 | edge_change = agent->edge_change; | ||
525 | agent->edge_change = 0; | ||
526 | sih = edge_change ? agent->sih : NULL; | ||
527 | spin_unlock_irq(&sih_agent_lock); | ||
528 | if (!sih) | ||
529 | return; | ||
530 | |||
531 | /* Read, reserving first byte for write scratch. Yes, this | ||
532 | * could be cached for some speedup ... but be careful about | ||
533 | * any processor on the other IRQ line, EDR registers are | ||
534 | * shared. | ||
535 | */ | ||
536 | status = twl_i2c_read(sih->module, bytes + 1, | ||
537 | sih->edr_offset, sih->bytes_edr); | ||
538 | if (status) { | ||
539 | pr_err("twl4030: %s, %s --> %d\n", __func__, | ||
540 | "read", status); | ||
541 | return; | ||
542 | } | ||
543 | |||
544 | /* Modify only the bits we know must change */ | ||
545 | while (edge_change) { | ||
546 | int i = fls(edge_change) - 1; | ||
547 | struct irq_data *idata = irq_get_irq_data(i + agent->irq_base); | ||
548 | int byte = 1 + (i >> 2); | ||
549 | int off = (i & 0x3) * 2; | ||
550 | unsigned int type; | ||
551 | |||
552 | bytes[byte] &= ~(0x03 << off); | ||
553 | 433 | ||
554 | type = irqd_get_trigger_type(idata); | 434 | struct mutex irq_lock; |
555 | if (type & IRQ_TYPE_EDGE_RISING) | 435 | }; |
556 | bytes[byte] |= BIT(off + 1); | ||
557 | if (type & IRQ_TYPE_EDGE_FALLING) | ||
558 | bytes[byte] |= BIT(off + 0); | ||
559 | |||
560 | edge_change &= ~BIT(i); | ||
561 | } | ||
562 | |||
563 | /* Write */ | ||
564 | status = twl_i2c_write(sih->module, bytes, | ||
565 | sih->edr_offset, sih->bytes_edr); | ||
566 | if (status) | ||
567 | pr_err("twl4030: %s, %s --> %d\n", __func__, | ||
568 | "write", status); | ||
569 | } | ||
570 | 436 | ||
571 | /*----------------------------------------------------------------------*/ | 437 | /*----------------------------------------------------------------------*/ |
572 | 438 | ||
@@ -579,50 +445,125 @@ static void twl4030_sih_do_edge(struct work_struct *work) | |||
579 | 445 | ||
580 | static void twl4030_sih_mask(struct irq_data *data) | 446 | static void twl4030_sih_mask(struct irq_data *data) |
581 | { | 447 | { |
582 | struct sih_agent *sih = irq_data_get_irq_chip_data(data); | 448 | struct sih_agent *agent = irq_data_get_irq_chip_data(data); |
583 | unsigned long flags; | 449 | |
584 | 450 | agent->imr |= BIT(data->irq - agent->irq_base); | |
585 | spin_lock_irqsave(&sih_agent_lock, flags); | 451 | agent->imr_change_pending = true; |
586 | sih->imr |= BIT(data->irq - sih->irq_base); | ||
587 | sih->imr_change_pending = true; | ||
588 | queue_work(wq, &sih->mask_work); | ||
589 | spin_unlock_irqrestore(&sih_agent_lock, flags); | ||
590 | } | 452 | } |
591 | 453 | ||
592 | static void twl4030_sih_unmask(struct irq_data *data) | 454 | static void twl4030_sih_unmask(struct irq_data *data) |
593 | { | 455 | { |
594 | struct sih_agent *sih = irq_data_get_irq_chip_data(data); | 456 | struct sih_agent *agent = irq_data_get_irq_chip_data(data); |
595 | unsigned long flags; | 457 | |
596 | 458 | agent->imr &= ~BIT(data->irq - agent->irq_base); | |
597 | spin_lock_irqsave(&sih_agent_lock, flags); | 459 | agent->imr_change_pending = true; |
598 | sih->imr &= ~BIT(data->irq - sih->irq_base); | ||
599 | sih->imr_change_pending = true; | ||
600 | queue_work(wq, &sih->mask_work); | ||
601 | spin_unlock_irqrestore(&sih_agent_lock, flags); | ||
602 | } | 460 | } |
603 | 461 | ||
604 | static int twl4030_sih_set_type(struct irq_data *data, unsigned trigger) | 462 | static int twl4030_sih_set_type(struct irq_data *data, unsigned trigger) |
605 | { | 463 | { |
606 | struct sih_agent *sih = irq_data_get_irq_chip_data(data); | 464 | struct sih_agent *agent = irq_data_get_irq_chip_data(data); |
607 | unsigned long flags; | ||
608 | 465 | ||
609 | if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) | 466 | if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) |
610 | return -EINVAL; | 467 | return -EINVAL; |
611 | 468 | ||
612 | spin_lock_irqsave(&sih_agent_lock, flags); | 469 | if (irqd_get_trigger_type(data) != trigger) |
613 | if (irqd_get_trigger_type(data) != trigger) { | 470 | agent->edge_change |= BIT(data->irq - agent->irq_base); |
614 | sih->edge_change |= BIT(data->irq - sih->irq_base); | 471 | |
615 | queue_work(wq, &sih->edge_work); | ||
616 | } | ||
617 | spin_unlock_irqrestore(&sih_agent_lock, flags); | ||
618 | return 0; | 472 | return 0; |
619 | } | 473 | } |
620 | 474 | ||
475 | static void twl4030_sih_bus_lock(struct irq_data *data) | ||
476 | { | ||
477 | struct sih_agent *agent = irq_data_get_irq_chip_data(data); | ||
478 | |||
479 | mutex_lock(&agent->irq_lock); | ||
480 | } | ||
481 | |||
482 | static void twl4030_sih_bus_sync_unlock(struct irq_data *data) | ||
483 | { | ||
484 | struct sih_agent *agent = irq_data_get_irq_chip_data(data); | ||
485 | const struct sih *sih = agent->sih; | ||
486 | int status; | ||
487 | |||
488 | if (agent->imr_change_pending) { | ||
489 | union { | ||
490 | u32 word; | ||
491 | u8 bytes[4]; | ||
492 | } imr; | ||
493 | |||
494 | /* byte[0] gets overwriten as we write ... */ | ||
495 | imr.word = cpu_to_le32(agent->imr << 8); | ||
496 | agent->imr_change_pending = false; | ||
497 | |||
498 | /* write the whole mask ... simpler than subsetting it */ | ||
499 | status = twl_i2c_write(sih->module, imr.bytes, | ||
500 | sih->mask[irq_line].imr_offset, | ||
501 | sih->bytes_ixr); | ||
502 | if (status) | ||
503 | pr_err("twl4030: %s, %s --> %d\n", __func__, | ||
504 | "write", status); | ||
505 | } | ||
506 | |||
507 | if (agent->edge_change) { | ||
508 | u32 edge_change; | ||
509 | u8 bytes[6]; | ||
510 | |||
511 | edge_change = agent->edge_change; | ||
512 | agent->edge_change = 0; | ||
513 | |||
514 | /* | ||
515 | * Read, reserving first byte for write scratch. Yes, this | ||
516 | * could be cached for some speedup ... but be careful about | ||
517 | * any processor on the other IRQ line, EDR registers are | ||
518 | * shared. | ||
519 | */ | ||
520 | status = twl_i2c_read(sih->module, bytes + 1, | ||
521 | sih->edr_offset, sih->bytes_edr); | ||
522 | if (status) { | ||
523 | pr_err("twl4030: %s, %s --> %d\n", __func__, | ||
524 | "read", status); | ||
525 | return; | ||
526 | } | ||
527 | |||
528 | /* Modify only the bits we know must change */ | ||
529 | while (edge_change) { | ||
530 | int i = fls(edge_change) - 1; | ||
531 | struct irq_data *idata; | ||
532 | int byte = 1 + (i >> 2); | ||
533 | int off = (i & 0x3) * 2; | ||
534 | unsigned int type; | ||
535 | |||
536 | idata = irq_get_irq_data(i + agent->irq_base); | ||
537 | |||
538 | bytes[byte] &= ~(0x03 << off); | ||
539 | |||
540 | type = irqd_get_trigger_type(idata); | ||
541 | if (type & IRQ_TYPE_EDGE_RISING) | ||
542 | bytes[byte] |= BIT(off + 1); | ||
543 | if (type & IRQ_TYPE_EDGE_FALLING) | ||
544 | bytes[byte] |= BIT(off + 0); | ||
545 | |||
546 | edge_change &= ~BIT(i); | ||
547 | } | ||
548 | |||
549 | /* Write */ | ||
550 | status = twl_i2c_write(sih->module, bytes, | ||
551 | sih->edr_offset, sih->bytes_edr); | ||
552 | if (status) | ||
553 | pr_err("twl4030: %s, %s --> %d\n", __func__, | ||
554 | "write", status); | ||
555 | } | ||
556 | |||
557 | mutex_unlock(&agent->irq_lock); | ||
558 | } | ||
559 | |||
621 | static struct irq_chip twl4030_sih_irq_chip = { | 560 | static struct irq_chip twl4030_sih_irq_chip = { |
622 | .name = "twl4030", | 561 | .name = "twl4030", |
623 | .irq_mask = twl4030_sih_mask, | 562 | .irq_mask = twl4030_sih_mask, |
624 | .irq_unmask = twl4030_sih_unmask, | 563 | .irq_unmask = twl4030_sih_unmask, |
625 | .irq_set_type = twl4030_sih_set_type, | 564 | .irq_set_type = twl4030_sih_set_type, |
565 | .irq_bus_lock = twl4030_sih_bus_lock, | ||
566 | .irq_bus_sync_unlock = twl4030_sih_bus_sync_unlock, | ||
626 | }; | 567 | }; |
627 | 568 | ||
628 | /*----------------------------------------------------------------------*/ | 569 | /*----------------------------------------------------------------------*/ |
@@ -655,9 +596,7 @@ static void handle_twl4030_sih(unsigned irq, struct irq_desc *desc) | |||
655 | int isr; | 596 | int isr; |
656 | 597 | ||
657 | /* reading ISR acks the IRQs, using clear-on-read mode */ | 598 | /* reading ISR acks the IRQs, using clear-on-read mode */ |
658 | local_irq_enable(); | ||
659 | isr = sih_read_isr(sih); | 599 | isr = sih_read_isr(sih); |
660 | local_irq_disable(); | ||
661 | 600 | ||
662 | if (isr < 0) { | 601 | if (isr < 0) { |
663 | pr_err("twl4030: %s SIH, read ISR error %d\n", | 602 | pr_err("twl4030: %s SIH, read ISR error %d\n", |
@@ -672,7 +611,7 @@ static void handle_twl4030_sih(unsigned irq, struct irq_desc *desc) | |||
672 | isr &= ~BIT(irq); | 611 | isr &= ~BIT(irq); |
673 | 612 | ||
674 | if (irq < sih->bits) | 613 | if (irq < sih->bits) |
675 | generic_handle_irq(agent->irq_base + irq); | 614 | handle_nested_irq(agent->irq_base + irq); |
676 | else | 615 | else |
677 | pr_err("twl4030: %s SIH, invalid ISR bit %d\n", | 616 | pr_err("twl4030: %s SIH, invalid ISR bit %d\n", |
678 | sih->name, irq); | 617 | sih->name, irq); |
@@ -718,15 +657,14 @@ int twl4030_sih_setup(int module) | |||
718 | agent->irq_base = irq_base; | 657 | agent->irq_base = irq_base; |
719 | agent->sih = sih; | 658 | agent->sih = sih; |
720 | agent->imr = ~0; | 659 | agent->imr = ~0; |
721 | INIT_WORK(&agent->mask_work, twl4030_sih_do_mask); | 660 | mutex_init(&agent->irq_lock); |
722 | INIT_WORK(&agent->edge_work, twl4030_sih_do_edge); | ||
723 | 661 | ||
724 | for (i = 0; i < sih->bits; i++) { | 662 | for (i = 0; i < sih->bits; i++) { |
725 | irq = irq_base + i; | 663 | irq = irq_base + i; |
726 | 664 | ||
665 | irq_set_chip_data(irq, agent); | ||
727 | irq_set_chip_and_handler(irq, &twl4030_sih_irq_chip, | 666 | irq_set_chip_and_handler(irq, &twl4030_sih_irq_chip, |
728 | handle_edge_irq); | 667 | handle_edge_irq); |
729 | irq_set_chip_data(irq, agent); | ||
730 | activate_irq(irq); | 668 | activate_irq(irq); |
731 | } | 669 | } |
732 | 670 | ||
@@ -758,7 +696,6 @@ int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end) | |||
758 | 696 | ||
759 | int status; | 697 | int status; |
760 | int i; | 698 | int i; |
761 | struct task_struct *task; | ||
762 | 699 | ||
763 | /* | 700 | /* |
764 | * Mask and clear all TWL4030 interrupts since initially we do | 701 | * Mask and clear all TWL4030 interrupts since initially we do |
@@ -768,12 +705,6 @@ int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end) | |||
768 | if (status < 0) | 705 | if (status < 0) |
769 | return status; | 706 | return status; |
770 | 707 | ||
771 | wq = create_singlethread_workqueue("twl4030-irqchip"); | ||
772 | if (!wq) { | ||
773 | pr_err("twl4030: workqueue FAIL\n"); | ||
774 | return -ESRCH; | ||
775 | } | ||
776 | |||
777 | twl4030_irq_base = irq_base; | 708 | twl4030_irq_base = irq_base; |
778 | 709 | ||
779 | /* install an irq handler for each of the SIH modules; | 710 | /* install an irq handler for each of the SIH modules; |
@@ -787,6 +718,7 @@ int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end) | |||
787 | for (i = irq_base; i < irq_end; i++) { | 718 | for (i = irq_base; i < irq_end; i++) { |
788 | irq_set_chip_and_handler(i, &twl4030_irq_chip, | 719 | irq_set_chip_and_handler(i, &twl4030_irq_chip, |
789 | handle_simple_irq); | 720 | handle_simple_irq); |
721 | irq_set_nested_thread(i, 1); | ||
790 | activate_irq(i); | 722 | activate_irq(i); |
791 | } | 723 | } |
792 | twl4030_irq_next = i; | 724 | twl4030_irq_next = i; |
@@ -801,34 +733,22 @@ int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end) | |||
801 | } | 733 | } |
802 | 734 | ||
803 | /* install an irq handler to demultiplex the TWL4030 interrupt */ | 735 | /* install an irq handler to demultiplex the TWL4030 interrupt */ |
804 | 736 | status = request_threaded_irq(irq_num, NULL, handle_twl4030_pih, 0, | |
805 | 737 | "TWL4030-PIH", NULL); | |
806 | init_completion(&irq_event); | ||
807 | |||
808 | status = request_irq(irq_num, handle_twl4030_pih, IRQF_DISABLED, | ||
809 | "TWL4030-PIH", &irq_event); | ||
810 | if (status < 0) { | 738 | if (status < 0) { |
811 | pr_err("twl4030: could not claim irq%d: %d\n", irq_num, status); | 739 | pr_err("twl4030: could not claim irq%d: %d\n", irq_num, status); |
812 | goto fail_rqirq; | 740 | goto fail_rqirq; |
813 | } | 741 | } |
814 | 742 | ||
815 | task = kthread_run(twl4030_irq_thread, (void *)(long)irq_num, | ||
816 | "twl4030-irq"); | ||
817 | if (IS_ERR(task)) { | ||
818 | pr_err("twl4030: could not create irq %d thread!\n", irq_num); | ||
819 | status = PTR_ERR(task); | ||
820 | goto fail_kthread; | ||
821 | } | ||
822 | return status; | 743 | return status; |
823 | fail_kthread: | ||
824 | free_irq(irq_num, &irq_event); | ||
825 | fail_rqirq: | 744 | fail_rqirq: |
826 | /* clean up twl4030_sih_setup */ | 745 | /* clean up twl4030_sih_setup */ |
827 | fail: | 746 | fail: |
828 | for (i = irq_base; i < irq_end; i++) | 747 | for (i = irq_base; i < irq_end; i++) { |
748 | irq_set_nested_thread(i, 0); | ||
829 | irq_set_chip_and_handler(i, NULL, NULL); | 749 | irq_set_chip_and_handler(i, NULL, NULL); |
830 | destroy_workqueue(wq); | 750 | } |
831 | wq = NULL; | 751 | |
832 | return status; | 752 | return status; |
833 | } | 753 | } |
834 | 754 | ||
diff --git a/drivers/mfd/twl4030-madc.c b/drivers/mfd/twl4030-madc.c index 7cbf2aa9e64f..834f824d3c11 100644 --- a/drivers/mfd/twl4030-madc.c +++ b/drivers/mfd/twl4030-madc.c | |||
@@ -740,6 +740,28 @@ static int __devinit twl4030_madc_probe(struct platform_device *pdev) | |||
740 | TWL4030_BCI_BCICTL1); | 740 | TWL4030_BCI_BCICTL1); |
741 | goto err_i2c; | 741 | goto err_i2c; |
742 | } | 742 | } |
743 | |||
744 | /* Check that MADC clock is on */ | ||
745 | ret = twl_i2c_read_u8(TWL4030_MODULE_INTBR, ®val, TWL4030_REG_GPBR1); | ||
746 | if (ret) { | ||
747 | dev_err(&pdev->dev, "unable to read reg GPBR1 0x%X\n", | ||
748 | TWL4030_REG_GPBR1); | ||
749 | goto err_i2c; | ||
750 | } | ||
751 | |||
752 | /* If MADC clk is not on, turn it on */ | ||
753 | if (!(regval & TWL4030_GPBR1_MADC_HFCLK_EN)) { | ||
754 | dev_info(&pdev->dev, "clk disabled, enabling\n"); | ||
755 | regval |= TWL4030_GPBR1_MADC_HFCLK_EN; | ||
756 | ret = twl_i2c_write_u8(TWL4030_MODULE_INTBR, regval, | ||
757 | TWL4030_REG_GPBR1); | ||
758 | if (ret) { | ||
759 | dev_err(&pdev->dev, "unable to write reg GPBR1 0x%X\n", | ||
760 | TWL4030_REG_GPBR1); | ||
761 | goto err_i2c; | ||
762 | } | ||
763 | } | ||
764 | |||
743 | platform_set_drvdata(pdev, madc); | 765 | platform_set_drvdata(pdev, madc); |
744 | mutex_init(&madc->lock); | 766 | mutex_init(&madc->lock); |
745 | ret = request_threaded_irq(platform_get_irq(pdev, 0), NULL, | 767 | ret = request_threaded_irq(platform_get_irq(pdev, 0), NULL, |
diff --git a/drivers/mfd/twl6030-irq.c b/drivers/mfd/twl6030-irq.c index b6bea428728e..3eee45ffb096 100644 --- a/drivers/mfd/twl6030-irq.c +++ b/drivers/mfd/twl6030-irq.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/kthread.h> | 38 | #include <linux/kthread.h> |
39 | #include <linux/i2c/twl.h> | 39 | #include <linux/i2c/twl.h> |
40 | #include <linux/platform_device.h> | 40 | #include <linux/platform_device.h> |
41 | #include <linux/suspend.h> | ||
41 | 42 | ||
42 | #include "twl-core.h" | 43 | #include "twl-core.h" |
43 | 44 | ||
@@ -84,8 +85,48 @@ static int twl6030_interrupt_mapping[24] = { | |||
84 | /*----------------------------------------------------------------------*/ | 85 | /*----------------------------------------------------------------------*/ |
85 | 86 | ||
86 | static unsigned twl6030_irq_base; | 87 | static unsigned twl6030_irq_base; |
88 | static int twl_irq; | ||
89 | static bool twl_irq_wake_enabled; | ||
87 | 90 | ||
88 | static struct completion irq_event; | 91 | static struct completion irq_event; |
92 | static atomic_t twl6030_wakeirqs = ATOMIC_INIT(0); | ||
93 | |||
94 | static int twl6030_irq_pm_notifier(struct notifier_block *notifier, | ||
95 | unsigned long pm_event, void *unused) | ||
96 | { | ||
97 | int chained_wakeups; | ||
98 | |||
99 | switch (pm_event) { | ||
100 | case PM_SUSPEND_PREPARE: | ||
101 | chained_wakeups = atomic_read(&twl6030_wakeirqs); | ||
102 | |||
103 | if (chained_wakeups && !twl_irq_wake_enabled) { | ||
104 | if (enable_irq_wake(twl_irq)) | ||
105 | pr_err("twl6030 IRQ wake enable failed\n"); | ||
106 | else | ||
107 | twl_irq_wake_enabled = true; | ||
108 | } else if (!chained_wakeups && twl_irq_wake_enabled) { | ||
109 | disable_irq_wake(twl_irq); | ||
110 | twl_irq_wake_enabled = false; | ||
111 | } | ||
112 | |||
113 | disable_irq(twl_irq); | ||
114 | break; | ||
115 | |||
116 | case PM_POST_SUSPEND: | ||
117 | enable_irq(twl_irq); | ||
118 | break; | ||
119 | |||
120 | default: | ||
121 | break; | ||
122 | } | ||
123 | |||
124 | return NOTIFY_DONE; | ||
125 | } | ||
126 | |||
127 | static struct notifier_block twl6030_irq_pm_notifier_block = { | ||
128 | .notifier_call = twl6030_irq_pm_notifier, | ||
129 | }; | ||
89 | 130 | ||
90 | /* | 131 | /* |
91 | * This thread processes interrupts reported by the Primary Interrupt Handler. | 132 | * This thread processes interrupts reported by the Primary Interrupt Handler. |
@@ -188,6 +229,16 @@ static inline void activate_irq(int irq) | |||
188 | #endif | 229 | #endif |
189 | } | 230 | } |
190 | 231 | ||
232 | int twl6030_irq_set_wake(struct irq_data *d, unsigned int on) | ||
233 | { | ||
234 | if (on) | ||
235 | atomic_inc(&twl6030_wakeirqs); | ||
236 | else | ||
237 | atomic_dec(&twl6030_wakeirqs); | ||
238 | |||
239 | return 0; | ||
240 | } | ||
241 | |||
191 | /*----------------------------------------------------------------------*/ | 242 | /*----------------------------------------------------------------------*/ |
192 | 243 | ||
193 | static unsigned twl6030_irq_next; | 244 | static unsigned twl6030_irq_next; |
@@ -319,10 +370,12 @@ int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end) | |||
319 | twl6030_irq_chip = dummy_irq_chip; | 370 | twl6030_irq_chip = dummy_irq_chip; |
320 | twl6030_irq_chip.name = "twl6030"; | 371 | twl6030_irq_chip.name = "twl6030"; |
321 | twl6030_irq_chip.irq_set_type = NULL; | 372 | twl6030_irq_chip.irq_set_type = NULL; |
373 | twl6030_irq_chip.irq_set_wake = twl6030_irq_set_wake; | ||
322 | 374 | ||
323 | for (i = irq_base; i < irq_end; i++) { | 375 | for (i = irq_base; i < irq_end; i++) { |
324 | irq_set_chip_and_handler(i, &twl6030_irq_chip, | 376 | irq_set_chip_and_handler(i, &twl6030_irq_chip, |
325 | handle_simple_irq); | 377 | handle_simple_irq); |
378 | irq_set_chip_data(i, (void *)irq_num); | ||
326 | activate_irq(i); | 379 | activate_irq(i); |
327 | } | 380 | } |
328 | 381 | ||
@@ -332,6 +385,14 @@ int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end) | |||
332 | 385 | ||
333 | /* install an irq handler to demultiplex the TWL6030 interrupt */ | 386 | /* install an irq handler to demultiplex the TWL6030 interrupt */ |
334 | init_completion(&irq_event); | 387 | init_completion(&irq_event); |
388 | |||
389 | status = request_irq(irq_num, handle_twl6030_pih, 0, | ||
390 | "TWL6030-PIH", &irq_event); | ||
391 | if (status < 0) { | ||
392 | pr_err("twl6030: could not claim irq%d: %d\n", irq_num, status); | ||
393 | goto fail_irq; | ||
394 | } | ||
395 | |||
335 | task = kthread_run(twl6030_irq_thread, (void *)irq_num, "twl6030-irq"); | 396 | task = kthread_run(twl6030_irq_thread, (void *)irq_num, "twl6030-irq"); |
336 | if (IS_ERR(task)) { | 397 | if (IS_ERR(task)) { |
337 | pr_err("twl6030: could not create irq %d thread!\n", irq_num); | 398 | pr_err("twl6030: could not create irq %d thread!\n", irq_num); |
@@ -339,17 +400,14 @@ int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end) | |||
339 | goto fail_kthread; | 400 | goto fail_kthread; |
340 | } | 401 | } |
341 | 402 | ||
342 | status = request_irq(irq_num, handle_twl6030_pih, IRQF_DISABLED, | 403 | twl_irq = irq_num; |
343 | "TWL6030-PIH", &irq_event); | 404 | register_pm_notifier(&twl6030_irq_pm_notifier_block); |
344 | if (status < 0) { | ||
345 | pr_err("twl6030: could not claim irq%d: %d\n", irq_num, status); | ||
346 | goto fail_irq; | ||
347 | } | ||
348 | return status; | 405 | return status; |
349 | fail_irq: | ||
350 | free_irq(irq_num, &irq_event); | ||
351 | 406 | ||
352 | fail_kthread: | 407 | fail_kthread: |
408 | free_irq(irq_num, &irq_event); | ||
409 | |||
410 | fail_irq: | ||
353 | for (i = irq_base; i < irq_end; i++) | 411 | for (i = irq_base; i < irq_end; i++) |
354 | irq_set_chip_and_handler(i, NULL, NULL); | 412 | irq_set_chip_and_handler(i, NULL, NULL); |
355 | return status; | 413 | return status; |
@@ -357,6 +415,7 @@ fail_kthread: | |||
357 | 415 | ||
358 | int twl6030_exit_irq(void) | 416 | int twl6030_exit_irq(void) |
359 | { | 417 | { |
418 | unregister_pm_notifier(&twl6030_irq_pm_notifier_block); | ||
360 | 419 | ||
361 | if (twl6030_irq_base) { | 420 | if (twl6030_irq_base) { |
362 | pr_err("twl6030: can't yet clean up IRQs?\n"); | 421 | pr_err("twl6030: can't yet clean up IRQs?\n"); |
diff --git a/drivers/mfd/wm831x-irq.c b/drivers/mfd/wm831x-irq.c index ada1835a5455..f4747a4a9a93 100644 --- a/drivers/mfd/wm831x-irq.c +++ b/drivers/mfd/wm831x-irq.c | |||
@@ -420,12 +420,19 @@ static int wm831x_irq_set_type(struct irq_data *data, unsigned int type) | |||
420 | switch (type) { | 420 | switch (type) { |
421 | case IRQ_TYPE_EDGE_BOTH: | 421 | case IRQ_TYPE_EDGE_BOTH: |
422 | wm831x->gpio_update[irq] = 0x10000 | WM831X_GPN_INT_MODE; | 422 | wm831x->gpio_update[irq] = 0x10000 | WM831X_GPN_INT_MODE; |
423 | wm831x->gpio_level[irq] = false; | ||
423 | break; | 424 | break; |
424 | case IRQ_TYPE_EDGE_RISING: | 425 | case IRQ_TYPE_EDGE_RISING: |
425 | wm831x->gpio_update[irq] = 0x10000 | WM831X_GPN_POL; | 426 | wm831x->gpio_update[irq] = 0x10000 | WM831X_GPN_POL; |
427 | wm831x->gpio_level[irq] = false; | ||
426 | break; | 428 | break; |
427 | case IRQ_TYPE_EDGE_FALLING: | 429 | case IRQ_TYPE_EDGE_FALLING: |
428 | wm831x->gpio_update[irq] = 0x10000; | 430 | wm831x->gpio_update[irq] = 0x10000; |
431 | wm831x->gpio_level[irq] = false; | ||
432 | break; | ||
433 | case IRQ_TYPE_LEVEL_HIGH: | ||
434 | wm831x->gpio_update[irq] = 0x10000 | WM831X_GPN_POL; | ||
435 | wm831x->gpio_level[irq] = true; | ||
429 | break; | 436 | break; |
430 | default: | 437 | default: |
431 | return -EINVAL; | 438 | return -EINVAL; |
@@ -449,7 +456,7 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data) | |||
449 | { | 456 | { |
450 | struct wm831x *wm831x = data; | 457 | struct wm831x *wm831x = data; |
451 | unsigned int i; | 458 | unsigned int i; |
452 | int primary, status_addr; | 459 | int primary, status_addr, ret; |
453 | int status_regs[WM831X_NUM_IRQ_REGS] = { 0 }; | 460 | int status_regs[WM831X_NUM_IRQ_REGS] = { 0 }; |
454 | int read[WM831X_NUM_IRQ_REGS] = { 0 }; | 461 | int read[WM831X_NUM_IRQ_REGS] = { 0 }; |
455 | int *status; | 462 | int *status; |
@@ -507,6 +514,19 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data) | |||
507 | 514 | ||
508 | if (*status & wm831x_irqs[i].mask) | 515 | if (*status & wm831x_irqs[i].mask) |
509 | handle_nested_irq(wm831x->irq_base + i); | 516 | handle_nested_irq(wm831x->irq_base + i); |
517 | |||
518 | /* Simulate an edge triggered IRQ by polling the input | ||
519 | * status. This is sucky but improves interoperability. | ||
520 | */ | ||
521 | if (primary == WM831X_GP_INT && | ||
522 | wm831x->gpio_level[i - WM831X_IRQ_GPIO_1]) { | ||
523 | ret = wm831x_reg_read(wm831x, WM831X_GPIO_LEVEL); | ||
524 | while (ret & 1 << (i - WM831X_IRQ_GPIO_1)) { | ||
525 | handle_nested_irq(wm831x->irq_base + i); | ||
526 | ret = wm831x_reg_read(wm831x, | ||
527 | WM831X_GPIO_LEVEL); | ||
528 | } | ||
529 | } | ||
510 | } | 530 | } |
511 | 531 | ||
512 | out: | 532 | out: |
@@ -596,8 +616,6 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq) | |||
596 | "No interrupt specified - functionality limited\n"); | 616 | "No interrupt specified - functionality limited\n"); |
597 | } | 617 | } |
598 | 618 | ||
599 | |||
600 | |||
601 | /* Enable top level interrupts, we mask at secondary level */ | 619 | /* Enable top level interrupts, we mask at secondary level */ |
602 | wm831x_reg_write(wm831x, WM831X_SYSTEM_INTERRUPTS_MASK, 0); | 620 | wm831x_reg_write(wm831x, WM831X_SYSTEM_INTERRUPTS_MASK, 0); |
603 | 621 | ||
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c index b03be1d4e0ca..5d6ba132837e 100644 --- a/drivers/mfd/wm8994-core.c +++ b/drivers/mfd/wm8994-core.c | |||
@@ -217,6 +217,47 @@ static int wm8994_suspend(struct device *dev) | |||
217 | return 0; | 217 | return 0; |
218 | } | 218 | } |
219 | 219 | ||
220 | ret = wm8994_reg_read(wm8994, WM8994_POWER_MANAGEMENT_4); | ||
221 | if (ret < 0) { | ||
222 | dev_err(dev, "Failed to read power status: %d\n", ret); | ||
223 | } else if (ret & (WM8994_AIF2ADCL_ENA | WM8994_AIF2ADCR_ENA | | ||
224 | WM8994_AIF1ADC2L_ENA | WM8994_AIF1ADC2R_ENA | | ||
225 | WM8994_AIF1ADC1L_ENA | WM8994_AIF1ADC1R_ENA)) { | ||
226 | dev_dbg(dev, "CODEC still active, ignoring suspend\n"); | ||
227 | return 0; | ||
228 | } | ||
229 | |||
230 | ret = wm8994_reg_read(wm8994, WM8994_POWER_MANAGEMENT_5); | ||
231 | if (ret < 0) { | ||
232 | dev_err(dev, "Failed to read power status: %d\n", ret); | ||
233 | } else if (ret & (WM8994_AIF2DACL_ENA | WM8994_AIF2DACR_ENA | | ||
234 | WM8994_AIF1DAC2L_ENA | WM8994_AIF1DAC2R_ENA | | ||
235 | WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA)) { | ||
236 | dev_dbg(dev, "CODEC still active, ignoring suspend\n"); | ||
237 | return 0; | ||
238 | } | ||
239 | |||
240 | switch (wm8994->type) { | ||
241 | case WM8958: | ||
242 | ret = wm8994_reg_read(wm8994, WM8958_MIC_DETECT_1); | ||
243 | if (ret < 0) { | ||
244 | dev_err(dev, "Failed to read power status: %d\n", ret); | ||
245 | } else if (ret & WM8958_MICD_ENA) { | ||
246 | dev_dbg(dev, "CODEC still active, ignoring suspend\n"); | ||
247 | return 0; | ||
248 | } | ||
249 | break; | ||
250 | default: | ||
251 | break; | ||
252 | } | ||
253 | |||
254 | /* Disable LDO pulldowns while the device is suspended if we | ||
255 | * don't know that something will be driving them. */ | ||
256 | if (!wm8994->ldo_ena_always_driven) | ||
257 | wm8994_set_bits(wm8994, WM8994_PULL_CONTROL_2, | ||
258 | WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD, | ||
259 | WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD); | ||
260 | |||
220 | /* GPIO configuration state is saved here since we may be configuring | 261 | /* GPIO configuration state is saved here since we may be configuring |
221 | * the GPIO alternate functions even if we're not using the gpiolib | 262 | * the GPIO alternate functions even if we're not using the gpiolib |
222 | * driver for them. | 263 | * driver for them. |
@@ -286,6 +327,11 @@ static int wm8994_resume(struct device *dev) | |||
286 | if (ret < 0) | 327 | if (ret < 0) |
287 | dev_err(dev, "Failed to restore GPIO registers: %d\n", ret); | 328 | dev_err(dev, "Failed to restore GPIO registers: %d\n", ret); |
288 | 329 | ||
330 | /* Disable LDO pulldowns while the device is active */ | ||
331 | wm8994_set_bits(wm8994, WM8994_PULL_CONTROL_2, | ||
332 | WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD, | ||
333 | 0); | ||
334 | |||
289 | wm8994->suspended = false; | 335 | wm8994->suspended = false; |
290 | 336 | ||
291 | return 0; | 337 | return 0; |
@@ -467,8 +513,15 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq) | |||
467 | pdata->gpio_defaults[i]); | 513 | pdata->gpio_defaults[i]); |
468 | } | 514 | } |
469 | } | 515 | } |
516 | |||
517 | wm8994->ldo_ena_always_driven = pdata->ldo_ena_always_driven; | ||
470 | } | 518 | } |
471 | 519 | ||
520 | /* Disable LDO pulldowns while the device is active */ | ||
521 | wm8994_set_bits(wm8994, WM8994_PULL_CONTROL_2, | ||
522 | WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD, | ||
523 | 0); | ||
524 | |||
472 | /* In some system designs where the regulators are not in use, | 525 | /* In some system designs where the regulators are not in use, |
473 | * we can achieve a small reduction in leakage currents by | 526 | * we can achieve a small reduction in leakage currents by |
474 | * floating LDO outputs. This bit makes no difference if the | 527 | * floating LDO outputs. This bit makes no difference if the |