blob: f3d689176fc2229f5dd1be64af2014af798dac60 [file] [log] [blame]
Rabin Vincent62579262010-05-19 11:39:02 +02001/*
2 * Copyright (C) ST-Ericsson SA 2010
3 *
4 * License Terms: GNU General Public License v2
5 * Author: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
6 * Author: Rabin Vincent <rabin.vincent@stericsson.com>
Mattias Wallinadceed62011-03-02 11:51:11 +01007 * Author: Mattias Wallin <mattias.wallin@stericsson.com>
Rabin Vincent62579262010-05-19 11:39:02 +02008 */
9
10#include <linux/kernel.h>
11#include <linux/slab.h>
12#include <linux/init.h>
13#include <linux/irq.h>
Lee Jones06e589e2012-06-20 13:56:37 +010014#include <linux/irqdomain.h>
Rabin Vincent62579262010-05-19 11:39:02 +020015#include <linux/delay.h>
16#include <linux/interrupt.h>
17#include <linux/module.h>
18#include <linux/platform_device.h>
19#include <linux/mfd/core.h>
Mattias Wallin47c16972010-09-10 17:47:56 +020020#include <linux/mfd/abx500.h>
Linus Walleijee66e652011-12-02 14:16:33 +010021#include <linux/mfd/abx500/ab8500.h>
Lee Jones00441b52013-01-09 10:06:03 +000022#include <linux/mfd/abx500/ab8500-bm.h>
Lee Jonesd28f1db2012-05-19 17:21:37 +020023#include <linux/mfd/dbx500-prcmu.h>
Sundar R Iyer549931f2010-07-13 11:51:28 +053024#include <linux/regulator/ab8500.h>
Lee Jones6bc4a562012-05-17 14:45:13 +010025#include <linux/of.h>
26#include <linux/of_device.h>
Rabin Vincent62579262010-05-19 11:39:02 +020027
28/*
29 * Interrupt register offsets
30 * Bank : 0x0E
31 */
Mattias Wallin47c16972010-09-10 17:47:56 +020032#define AB8500_IT_SOURCE1_REG 0x00
33#define AB8500_IT_SOURCE2_REG 0x01
34#define AB8500_IT_SOURCE3_REG 0x02
35#define AB8500_IT_SOURCE4_REG 0x03
36#define AB8500_IT_SOURCE5_REG 0x04
37#define AB8500_IT_SOURCE6_REG 0x05
38#define AB8500_IT_SOURCE7_REG 0x06
39#define AB8500_IT_SOURCE8_REG 0x07
Linus Walleijd6255522012-02-20 21:42:24 +010040#define AB9540_IT_SOURCE13_REG 0x0C
Mattias Wallin47c16972010-09-10 17:47:56 +020041#define AB8500_IT_SOURCE19_REG 0x12
42#define AB8500_IT_SOURCE20_REG 0x13
43#define AB8500_IT_SOURCE21_REG 0x14
44#define AB8500_IT_SOURCE22_REG 0x15
45#define AB8500_IT_SOURCE23_REG 0x16
46#define AB8500_IT_SOURCE24_REG 0x17
Rabin Vincent62579262010-05-19 11:39:02 +020047
48/*
49 * latch registers
50 */
Mattias Wallin47c16972010-09-10 17:47:56 +020051#define AB8500_IT_LATCH1_REG 0x20
52#define AB8500_IT_LATCH2_REG 0x21
53#define AB8500_IT_LATCH3_REG 0x22
54#define AB8500_IT_LATCH4_REG 0x23
55#define AB8500_IT_LATCH5_REG 0x24
56#define AB8500_IT_LATCH6_REG 0x25
57#define AB8500_IT_LATCH7_REG 0x26
58#define AB8500_IT_LATCH8_REG 0x27
59#define AB8500_IT_LATCH9_REG 0x28
60#define AB8500_IT_LATCH10_REG 0x29
Mattias Wallin92d50a42010-12-07 11:20:47 +010061#define AB8500_IT_LATCH12_REG 0x2B
Linus Walleijd6255522012-02-20 21:42:24 +010062#define AB9540_IT_LATCH13_REG 0x2C
Mattias Wallin47c16972010-09-10 17:47:56 +020063#define AB8500_IT_LATCH19_REG 0x32
64#define AB8500_IT_LATCH20_REG 0x33
65#define AB8500_IT_LATCH21_REG 0x34
66#define AB8500_IT_LATCH22_REG 0x35
67#define AB8500_IT_LATCH23_REG 0x36
68#define AB8500_IT_LATCH24_REG 0x37
Rabin Vincent62579262010-05-19 11:39:02 +020069
70/*
71 * mask registers
72 */
73
Mattias Wallin47c16972010-09-10 17:47:56 +020074#define AB8500_IT_MASK1_REG 0x40
75#define AB8500_IT_MASK2_REG 0x41
76#define AB8500_IT_MASK3_REG 0x42
77#define AB8500_IT_MASK4_REG 0x43
78#define AB8500_IT_MASK5_REG 0x44
79#define AB8500_IT_MASK6_REG 0x45
80#define AB8500_IT_MASK7_REG 0x46
81#define AB8500_IT_MASK8_REG 0x47
82#define AB8500_IT_MASK9_REG 0x48
83#define AB8500_IT_MASK10_REG 0x49
84#define AB8500_IT_MASK11_REG 0x4A
85#define AB8500_IT_MASK12_REG 0x4B
86#define AB8500_IT_MASK13_REG 0x4C
87#define AB8500_IT_MASK14_REG 0x4D
88#define AB8500_IT_MASK15_REG 0x4E
89#define AB8500_IT_MASK16_REG 0x4F
90#define AB8500_IT_MASK17_REG 0x50
91#define AB8500_IT_MASK18_REG 0x51
92#define AB8500_IT_MASK19_REG 0x52
93#define AB8500_IT_MASK20_REG 0x53
94#define AB8500_IT_MASK21_REG 0x54
95#define AB8500_IT_MASK22_REG 0x55
96#define AB8500_IT_MASK23_REG 0x56
97#define AB8500_IT_MASK24_REG 0x57
Lee Jonesa29264b2013-02-25 14:34:26 +000098#define AB8500_IT_MASK25_REG 0x58
Rabin Vincent62579262010-05-19 11:39:02 +020099
Michel JAOUEN7ccfe9b2012-05-07 15:02:03 +0200100/*
101 * latch hierarchy registers
102 */
103#define AB8500_IT_LATCHHIER1_REG 0x60
104#define AB8500_IT_LATCHHIER2_REG 0x61
105#define AB8500_IT_LATCHHIER3_REG 0x62
Lee Jones3e1a4982013-02-25 14:57:35 +0000106#define AB8540_IT_LATCHHIER4_REG 0x63
Michel JAOUEN7ccfe9b2012-05-07 15:02:03 +0200107
108#define AB8500_IT_LATCHHIER_NUM 3
Lee Jones3e1a4982013-02-25 14:57:35 +0000109#define AB8540_IT_LATCHHIER_NUM 4
Michel JAOUEN7ccfe9b2012-05-07 15:02:03 +0200110
Mattias Wallin47c16972010-09-10 17:47:56 +0200111#define AB8500_REV_REG 0x80
Linus Walleij0f6208372012-02-20 21:42:10 +0100112#define AB8500_IC_NAME_REG 0x82
Mattias Walline5c238c2011-03-02 11:52:36 +0100113#define AB8500_SWITCH_OFF_STATUS 0x00
Rabin Vincent62579262010-05-19 11:39:02 +0200114
Andrew Lynnb4a31032011-10-11 10:49:47 +0200115#define AB8500_TURN_ON_STATUS 0x00
Lee Jones500e69a2015-10-28 09:15:02 +0000116#define AB8505_TURN_ON_STATUS_2 0x04
Andrew Lynnb4a31032011-10-11 10:49:47 +0200117
Rajkumar Kasirajanf04a9d82012-05-30 16:32:37 +0530118#define AB8500_CH_USBCH_STAT1_REG 0x02
119#define VBUS_DET_DBNC100 0x02
120#define VBUS_DET_DBNC1 0x01
121
122static DEFINE_SPINLOCK(on_stat_lock);
123static u8 turn_on_stat_mask = 0xFF;
124static u8 turn_on_stat_set;
Rickard Andersson6ef94182012-04-17 09:30:57 +0200125static bool no_bm; /* No battery management */
126module_param(no_bm, bool, S_IRUGO);
127
Linus Walleijd6255522012-02-20 21:42:24 +0100128#define AB9540_MODEM_CTRL2_REG 0x23
129#define AB9540_MODEM_CTRL2_SWDBBRSTN_BIT BIT(2)
130
Rabin Vincent62579262010-05-19 11:39:02 +0200131/*
132 * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt
Linus Walleij2ced4452012-02-20 21:42:17 +0100133 * numbers are indexed into this array with (num / 8). The interupts are
134 * defined in linux/mfd/ab8500.h
Rabin Vincent62579262010-05-19 11:39:02 +0200135 *
136 * This is one off from the register names, i.e. AB8500_IT_MASK1_REG is at
137 * offset 0.
138 */
Linus Walleij2ced4452012-02-20 21:42:17 +0100139/* AB8500 support */
Rabin Vincent62579262010-05-19 11:39:02 +0200140static const int ab8500_irq_regoffset[AB8500_NUM_IRQ_REGS] = {
Mattias Wallin92d50a42010-12-07 11:20:47 +0100141 0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21,
Rabin Vincent62579262010-05-19 11:39:02 +0200142};
143
Lee Jonesa29264b2013-02-25 14:34:26 +0000144/* AB9540 / AB8505 support */
Linus Walleijd6255522012-02-20 21:42:24 +0100145static const int ab9540_irq_regoffset[AB9540_NUM_IRQ_REGS] = {
Lee Jonesa29264b2013-02-25 14:34:26 +0000146 0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 18, 19, 20, 21, 12, 13, 24, 5, 22, 23
Linus Walleijd6255522012-02-20 21:42:24 +0100147};
148
Lee Jones3e1a4982013-02-25 14:57:35 +0000149/* AB8540 support */
150static const int ab8540_irq_regoffset[AB8540_NUM_IRQ_REGS] = {
Lee Jones7ccf40b2014-05-08 14:11:37 +0100151 0, 1, 2, 3, 4, -1, -1, -1, -1, 11, 18, 19, 20, 21, 12, 13, 24, 5, 22,
152 23, 25, 26, 27, 28, 29, 30, 31,
Lee Jones3e1a4982013-02-25 14:57:35 +0000153};
154
Linus Walleij0f6208372012-02-20 21:42:10 +0100155static const char ab8500_version_str[][7] = {
156 [AB8500_VERSION_AB8500] = "AB8500",
157 [AB8500_VERSION_AB8505] = "AB8505",
158 [AB8500_VERSION_AB9540] = "AB9540",
159 [AB8500_VERSION_AB8540] = "AB8540",
160};
161
Lee Jones822672a2012-06-20 13:56:38 +0100162static int ab8500_prcmu_write(struct ab8500 *ab8500, u16 addr, u8 data)
Lee Jonesd28f1db2012-05-19 17:21:37 +0200163{
164 int ret;
165
166 ret = prcmu_abb_write((u8)(addr >> 8), (u8)(addr & 0xFF), &data, 1);
167 if (ret < 0)
168 dev_err(ab8500->dev, "prcmu i2c error %d\n", ret);
169 return ret;
170}
171
Lee Jones822672a2012-06-20 13:56:38 +0100172static int ab8500_prcmu_write_masked(struct ab8500 *ab8500, u16 addr, u8 mask,
Lee Jonesd28f1db2012-05-19 17:21:37 +0200173 u8 data)
174{
175 int ret;
176
177 ret = prcmu_abb_write_masked((u8)(addr >> 8), (u8)(addr & 0xFF), &data,
178 &mask, 1);
179 if (ret < 0)
180 dev_err(ab8500->dev, "prcmu i2c error %d\n", ret);
181 return ret;
182}
183
Lee Jones822672a2012-06-20 13:56:38 +0100184static int ab8500_prcmu_read(struct ab8500 *ab8500, u16 addr)
Lee Jonesd28f1db2012-05-19 17:21:37 +0200185{
186 int ret;
187 u8 data;
188
189 ret = prcmu_abb_read((u8)(addr >> 8), (u8)(addr & 0xFF), &data, 1);
190 if (ret < 0) {
191 dev_err(ab8500->dev, "prcmu i2c error %d\n", ret);
192 return ret;
193 }
194 return (int)data;
195}
196
Mattias Wallin47c16972010-09-10 17:47:56 +0200197static int ab8500_get_chip_id(struct device *dev)
198{
Mattias Wallin6bce7bf2010-12-02 15:08:32 +0100199 struct ab8500 *ab8500;
200
201 if (!dev)
202 return -EINVAL;
203 ab8500 = dev_get_drvdata(dev->parent);
204 return ab8500 ? (int)ab8500->chip_id : -EINVAL;
Mattias Wallin47c16972010-09-10 17:47:56 +0200205}
206
207static int set_register_interruptible(struct ab8500 *ab8500, u8 bank,
208 u8 reg, u8 data)
Rabin Vincent62579262010-05-19 11:39:02 +0200209{
210 int ret;
Mattias Wallin47c16972010-09-10 17:47:56 +0200211 /*
212 * Put the u8 bank and u8 register together into a an u16.
213 * The bank on higher 8 bits and register in lower 8 bits.
Lee Jones500e69a2015-10-28 09:15:02 +0000214 */
Mattias Wallin47c16972010-09-10 17:47:56 +0200215 u16 addr = ((u16)bank) << 8 | reg;
Rabin Vincent62579262010-05-19 11:39:02 +0200216
217 dev_vdbg(ab8500->dev, "wr: addr %#x <= %#x\n", addr, data);
218
Rabin Vincent392cbd12012-03-08 14:01:46 +0100219 mutex_lock(&ab8500->lock);
Mattias Wallin47c16972010-09-10 17:47:56 +0200220
221 ret = ab8500->write(ab8500, addr, data);
222 if (ret < 0)
223 dev_err(ab8500->dev, "failed to write reg %#x: %d\n",
224 addr, ret);
225 mutex_unlock(&ab8500->lock);
226
227 return ret;
228}
229
230static int ab8500_set_register(struct device *dev, u8 bank,
231 u8 reg, u8 value)
232{
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200233 int ret;
Mattias Wallin47c16972010-09-10 17:47:56 +0200234 struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
235
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200236 atomic_inc(&ab8500->transfer_ongoing);
237 ret = set_register_interruptible(ab8500, bank, reg, value);
238 atomic_dec(&ab8500->transfer_ongoing);
239 return ret;
Mattias Wallin47c16972010-09-10 17:47:56 +0200240}
241
242static int get_register_interruptible(struct ab8500 *ab8500, u8 bank,
243 u8 reg, u8 *value)
244{
245 int ret;
Mattias Wallin47c16972010-09-10 17:47:56 +0200246 u16 addr = ((u16)bank) << 8 | reg;
247
Rabin Vincent392cbd12012-03-08 14:01:46 +0100248 mutex_lock(&ab8500->lock);
Mattias Wallin47c16972010-09-10 17:47:56 +0200249
250 ret = ab8500->read(ab8500, addr);
251 if (ret < 0)
252 dev_err(ab8500->dev, "failed to read reg %#x: %d\n",
253 addr, ret);
254 else
255 *value = ret;
256
257 mutex_unlock(&ab8500->lock);
258 dev_vdbg(ab8500->dev, "rd: addr %#x => data %#x\n", addr, ret);
259
260 return ret;
261}
262
263static int ab8500_get_register(struct device *dev, u8 bank,
264 u8 reg, u8 *value)
265{
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200266 int ret;
Mattias Wallin47c16972010-09-10 17:47:56 +0200267 struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
268
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200269 atomic_inc(&ab8500->transfer_ongoing);
270 ret = get_register_interruptible(ab8500, bank, reg, value);
271 atomic_dec(&ab8500->transfer_ongoing);
272 return ret;
Mattias Wallin47c16972010-09-10 17:47:56 +0200273}
274
275static int mask_and_set_register_interruptible(struct ab8500 *ab8500, u8 bank,
276 u8 reg, u8 bitmask, u8 bitvalues)
277{
278 int ret;
Mattias Wallin47c16972010-09-10 17:47:56 +0200279 u16 addr = ((u16)bank) << 8 | reg;
280
Rabin Vincent392cbd12012-03-08 14:01:46 +0100281 mutex_lock(&ab8500->lock);
Mattias Wallin47c16972010-09-10 17:47:56 +0200282
Mattias Nilssonbc628fd2012-03-08 14:02:20 +0100283 if (ab8500->write_masked == NULL) {
284 u8 data;
285
286 ret = ab8500->read(ab8500, addr);
287 if (ret < 0) {
288 dev_err(ab8500->dev, "failed to read reg %#x: %d\n",
289 addr, ret);
290 goto out;
291 }
292
293 data = (u8)ret;
294 data = (~bitmask & data) | (bitmask & bitvalues);
295
296 ret = ab8500->write(ab8500, addr, data);
297 if (ret < 0)
298 dev_err(ab8500->dev, "failed to write reg %#x: %d\n",
299 addr, ret);
300
301 dev_vdbg(ab8500->dev, "mask: addr %#x => data %#x\n", addr,
302 data);
Mattias Wallin47c16972010-09-10 17:47:56 +0200303 goto out;
304 }
Mattias Nilssonbc628fd2012-03-08 14:02:20 +0100305 ret = ab8500->write_masked(ab8500, addr, bitmask, bitvalues);
Rabin Vincent62579262010-05-19 11:39:02 +0200306 if (ret < 0)
Mattias Nilssonbc628fd2012-03-08 14:02:20 +0100307 dev_err(ab8500->dev, "failed to modify reg %#x: %d\n", addr,
308 ret);
Rabin Vincent62579262010-05-19 11:39:02 +0200309out:
310 mutex_unlock(&ab8500->lock);
311 return ret;
312}
Mattias Wallin47c16972010-09-10 17:47:56 +0200313
314static int ab8500_mask_and_set_register(struct device *dev,
315 u8 bank, u8 reg, u8 bitmask, u8 bitvalues)
316{
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200317 int ret;
Mattias Wallin47c16972010-09-10 17:47:56 +0200318 struct ab8500 *ab8500 = dev_get_drvdata(dev->parent);
319
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200320 atomic_inc(&ab8500->transfer_ongoing);
Lee Jones7ccf40b2014-05-08 14:11:37 +0100321 ret = mask_and_set_register_interruptible(ab8500, bank, reg,
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200322 bitmask, bitvalues);
323 atomic_dec(&ab8500->transfer_ongoing);
324 return ret;
Mattias Wallin47c16972010-09-10 17:47:56 +0200325}
326
327static struct abx500_ops ab8500_ops = {
328 .get_chip_id = ab8500_get_chip_id,
329 .get_register = ab8500_get_register,
330 .set_register = ab8500_set_register,
331 .get_register_page = NULL,
332 .set_register_page = NULL,
333 .mask_and_set_register = ab8500_mask_and_set_register,
334 .event_registers_startup_state_get = NULL,
335 .startup_irq_enabled = NULL,
Mian Yousaf Kaukab1d843a62012-01-27 11:35:41 +0100336 .dump_all_banks = ab8500_dump_all_banks,
Mattias Wallin47c16972010-09-10 17:47:56 +0200337};
Rabin Vincent62579262010-05-19 11:39:02 +0200338
Mark Brown9505a0a2010-12-11 13:16:08 +0000339static void ab8500_irq_lock(struct irq_data *data)
Rabin Vincent62579262010-05-19 11:39:02 +0200340{
Mark Brown9505a0a2010-12-11 13:16:08 +0000341 struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
Rabin Vincent62579262010-05-19 11:39:02 +0200342
343 mutex_lock(&ab8500->irq_lock);
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200344 atomic_inc(&ab8500->transfer_ongoing);
Rabin Vincent62579262010-05-19 11:39:02 +0200345}
346
Mark Brown9505a0a2010-12-11 13:16:08 +0000347static void ab8500_irq_sync_unlock(struct irq_data *data)
Rabin Vincent62579262010-05-19 11:39:02 +0200348{
Mark Brown9505a0a2010-12-11 13:16:08 +0000349 struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
Rabin Vincent62579262010-05-19 11:39:02 +0200350 int i;
351
Linus Walleij2ced4452012-02-20 21:42:17 +0100352 for (i = 0; i < ab8500->mask_size; i++) {
Rabin Vincent62579262010-05-19 11:39:02 +0200353 u8 old = ab8500->oldmask[i];
354 u8 new = ab8500->mask[i];
355 int reg;
356
357 if (new == old)
358 continue;
359
Linus Walleij0f6208372012-02-20 21:42:10 +0100360 /*
361 * Interrupt register 12 doesn't exist prior to AB8500 version
362 * 2.0
363 */
364 if (ab8500->irq_reg_offset[i] == 11 &&
365 is_ab8500_1p1_or_earlier(ab8500))
Mattias Wallin92d50a42010-12-07 11:20:47 +0100366 continue;
367
Lee Jones3e1a4982013-02-25 14:57:35 +0000368 if (ab8500->irq_reg_offset[i] < 0)
369 continue;
370
Rabin Vincent62579262010-05-19 11:39:02 +0200371 ab8500->oldmask[i] = new;
372
Linus Walleij2ced4452012-02-20 21:42:17 +0100373 reg = AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i];
Mattias Wallin47c16972010-09-10 17:47:56 +0200374 set_register_interruptible(ab8500, AB8500_INTERRUPT, reg, new);
Rabin Vincent62579262010-05-19 11:39:02 +0200375 }
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200376 atomic_dec(&ab8500->transfer_ongoing);
Rabin Vincent62579262010-05-19 11:39:02 +0200377 mutex_unlock(&ab8500->irq_lock);
378}
379
Mark Brown9505a0a2010-12-11 13:16:08 +0000380static void ab8500_irq_mask(struct irq_data *data)
Rabin Vincent62579262010-05-19 11:39:02 +0200381{
Mark Brown9505a0a2010-12-11 13:16:08 +0000382 struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
Lee Jones06e589e2012-06-20 13:56:37 +0100383 int offset = data->hwirq;
Rabin Vincent62579262010-05-19 11:39:02 +0200384 int index = offset / 8;
385 int mask = 1 << (offset % 8);
386
387 ab8500->mask[index] |= mask;
Lee Jones9c677b92012-12-20 11:23:42 +0000388
389 /* The AB8500 GPIOs have two interrupts each (rising & falling). */
390 if (offset >= AB8500_INT_GPIO6R && offset <= AB8500_INT_GPIO41R)
391 ab8500->mask[index + 2] |= mask;
392 if (offset >= AB9540_INT_GPIO50R && offset <= AB9540_INT_GPIO54R)
393 ab8500->mask[index + 1] |= mask;
394 if (offset == AB8540_INT_GPIO43R || offset == AB8540_INT_GPIO44R)
Linus Walleije2ddf462013-02-06 21:54:34 +0100395 /* Here the falling IRQ is one bit lower */
396 ab8500->mask[index] |= (mask << 1);
Rabin Vincent62579262010-05-19 11:39:02 +0200397}
398
Mark Brown9505a0a2010-12-11 13:16:08 +0000399static void ab8500_irq_unmask(struct irq_data *data)
Rabin Vincent62579262010-05-19 11:39:02 +0200400{
Mark Brown9505a0a2010-12-11 13:16:08 +0000401 struct ab8500 *ab8500 = irq_data_get_irq_chip_data(data);
Lee Jones9c677b92012-12-20 11:23:42 +0000402 unsigned int type = irqd_get_trigger_type(data);
Lee Jones06e589e2012-06-20 13:56:37 +0100403 int offset = data->hwirq;
Rabin Vincent62579262010-05-19 11:39:02 +0200404 int index = offset / 8;
405 int mask = 1 << (offset % 8);
406
Lee Jones9c677b92012-12-20 11:23:42 +0000407 if (type & IRQ_TYPE_EDGE_RISING)
408 ab8500->mask[index] &= ~mask;
409
410 /* The AB8500 GPIOs have two interrupts each (rising & falling). */
411 if (type & IRQ_TYPE_EDGE_FALLING) {
412 if (offset >= AB8500_INT_GPIO6R && offset <= AB8500_INT_GPIO41R)
413 ab8500->mask[index + 2] &= ~mask;
Lee Jones7ccf40b2014-05-08 14:11:37 +0100414 else if (offset >= AB9540_INT_GPIO50R &&
415 offset <= AB9540_INT_GPIO54R)
Lee Jones9c677b92012-12-20 11:23:42 +0000416 ab8500->mask[index + 1] &= ~mask;
Lee Jones7ccf40b2014-05-08 14:11:37 +0100417 else if (offset == AB8540_INT_GPIO43R ||
418 offset == AB8540_INT_GPIO44R)
Linus Walleije2ddf462013-02-06 21:54:34 +0100419 /* Here the falling IRQ is one bit lower */
420 ab8500->mask[index] &= ~(mask << 1);
Lee Jones9c677b92012-12-20 11:23:42 +0000421 else
422 ab8500->mask[index] &= ~mask;
Linus Walleije2ddf462013-02-06 21:54:34 +0100423 } else {
Lee Jones9c677b92012-12-20 11:23:42 +0000424 /* Satisfies the case where type is not set. */
425 ab8500->mask[index] &= ~mask;
Linus Walleije2ddf462013-02-06 21:54:34 +0100426 }
Rabin Vincent62579262010-05-19 11:39:02 +0200427}
428
Lee Jones40f6e5a2013-01-07 12:23:48 +0000429static int ab8500_irq_set_type(struct irq_data *data, unsigned int type)
430{
431 return 0;
Rabin Vincent62579262010-05-19 11:39:02 +0200432}
433
434static struct irq_chip ab8500_irq_chip = {
435 .name = "ab8500",
Mark Brown9505a0a2010-12-11 13:16:08 +0000436 .irq_bus_lock = ab8500_irq_lock,
437 .irq_bus_sync_unlock = ab8500_irq_sync_unlock,
438 .irq_mask = ab8500_irq_mask,
Virupax Sadashivpetimathe6f93062011-10-11 10:49:17 +0200439 .irq_disable = ab8500_irq_mask,
Mark Brown9505a0a2010-12-11 13:16:08 +0000440 .irq_unmask = ab8500_irq_unmask,
Lee Jones40f6e5a2013-01-07 12:23:48 +0000441 .irq_set_type = ab8500_irq_set_type,
Rabin Vincent62579262010-05-19 11:39:02 +0200442};
443
Lee Jones3e1a4982013-02-25 14:57:35 +0000444static void update_latch_offset(u8 *offset, int i)
445{
446 /* Fix inconsistent ITFromLatch25 bit mapping... */
447 if (unlikely(*offset == 17))
Lee Jones500e69a2015-10-28 09:15:02 +0000448 *offset = 24;
Lee Jones3e1a4982013-02-25 14:57:35 +0000449 /* Fix inconsistent ab8540 bit mapping... */
450 if (unlikely(*offset == 16))
Lee Jones500e69a2015-10-28 09:15:02 +0000451 *offset = 25;
Lee Jones7ccf40b2014-05-08 14:11:37 +0100452 if ((i == 3) && (*offset >= 24))
Lee Jones500e69a2015-10-28 09:15:02 +0000453 *offset += 2;
Lee Jones3e1a4982013-02-25 14:57:35 +0000454}
455
Michel JAOUEN7ccfe9b2012-05-07 15:02:03 +0200456static int ab8500_handle_hierarchical_line(struct ab8500 *ab8500,
457 int latch_offset, u8 latch_val)
458{
Fabio Baltieri7a93fb32013-03-21 14:49:44 +0100459 int int_bit, line, i;
Michel JAOUEN7ccfe9b2012-05-07 15:02:03 +0200460
Fabio Baltieri7a93fb32013-03-21 14:49:44 +0100461 for (i = 0; i < ab8500->mask_size; i++)
462 if (ab8500->irq_reg_offset[i] == latch_offset)
463 break;
464
465 if (i >= ab8500->mask_size) {
466 dev_err(ab8500->dev, "Register offset 0x%2x not declared\n",
467 latch_offset);
468 return -ENXIO;
469 }
470
471 /* ignore masked out interrupts */
472 latch_val &= ~ab8500->mask[i];
473
474 while (latch_val) {
Michel JAOUEN7ccfe9b2012-05-07 15:02:03 +0200475 int_bit = __ffs(latch_val);
Michel JAOUEN7ccfe9b2012-05-07 15:02:03 +0200476 line = (i << 3) + int_bit;
477 latch_val &= ~(1 << int_bit);
478
Linus Walleije2ddf462013-02-06 21:54:34 +0100479 /*
480 * This handles the falling edge hwirqs from the GPIO
481 * lines. Route them back to the line registered for the
482 * rising IRQ, as this is merely a flag for the same IRQ
483 * in linux terms.
484 */
485 if (line >= AB8500_INT_GPIO6F && line <= AB8500_INT_GPIO41F)
486 line -= 16;
487 if (line >= AB9540_INT_GPIO50F && line <= AB9540_INT_GPIO54F)
488 line -= 8;
489 if (line == AB8540_INT_GPIO43F || line == AB8540_INT_GPIO44F)
490 line += 1;
491
Linus Walleijed83d302013-12-03 15:11:54 +0100492 handle_nested_irq(irq_create_mapping(ab8500->domain, line));
Fabio Baltieri7a93fb32013-03-21 14:49:44 +0100493 }
Michel JAOUEN7ccfe9b2012-05-07 15:02:03 +0200494
495 return 0;
496}
497
498static int ab8500_handle_hierarchical_latch(struct ab8500 *ab8500,
499 int hier_offset, u8 hier_val)
500{
501 int latch_bit, status;
502 u8 latch_offset, latch_val;
503
504 do {
505 latch_bit = __ffs(hier_val);
506 latch_offset = (hier_offset << 3) + latch_bit;
507
Lee Jones3e1a4982013-02-25 14:57:35 +0000508 update_latch_offset(&latch_offset, hier_offset);
Michel JAOUEN7ccfe9b2012-05-07 15:02:03 +0200509
510 status = get_register_interruptible(ab8500,
511 AB8500_INTERRUPT,
512 AB8500_IT_LATCH1_REG + latch_offset,
513 &latch_val);
514 if (status < 0 || latch_val == 0)
515 goto discard;
516
517 status = ab8500_handle_hierarchical_line(ab8500,
518 latch_offset, latch_val);
519 if (status < 0)
520 return status;
521discard:
522 hier_val &= ~(1 << latch_bit);
523 } while (hier_val);
524
525 return 0;
526}
527
528static irqreturn_t ab8500_hierarchical_irq(int irq, void *dev)
529{
530 struct ab8500 *ab8500 = dev;
531 u8 i;
532
533 dev_vdbg(ab8500->dev, "interrupt\n");
534
535 /* Hierarchical interrupt version */
Lee Jones3e1a4982013-02-25 14:57:35 +0000536 for (i = 0; i < (ab8500->it_latchhier_num); i++) {
Michel JAOUEN7ccfe9b2012-05-07 15:02:03 +0200537 int status;
538 u8 hier_val;
539
540 status = get_register_interruptible(ab8500, AB8500_INTERRUPT,
541 AB8500_IT_LATCHHIER1_REG + i, &hier_val);
542 if (status < 0 || hier_val == 0)
543 continue;
544
545 status = ab8500_handle_hierarchical_latch(ab8500, i, hier_val);
546 if (status < 0)
547 break;
548 }
549 return IRQ_HANDLED;
550}
551
Lee Jones06e589e2012-06-20 13:56:37 +0100552static int ab8500_irq_map(struct irq_domain *d, unsigned int virq,
553 irq_hw_number_t hwirq)
554{
555 struct ab8500 *ab8500 = d->host_data;
556
557 if (!ab8500)
558 return -EINVAL;
559
560 irq_set_chip_data(virq, ab8500);
561 irq_set_chip_and_handler(virq, &ab8500_irq_chip,
562 handle_simple_irq);
563 irq_set_nested_thread(virq, 1);
Lee Jones06e589e2012-06-20 13:56:37 +0100564 irq_set_noprobe(virq);
Rabin Vincent62579262010-05-19 11:39:02 +0200565
566 return 0;
567}
568
Krzysztof Kozlowski7ce7b262015-04-27 21:54:13 +0900569static const struct irq_domain_ops ab8500_irq_ops = {
Lee Jones7ccf40b2014-05-08 14:11:37 +0100570 .map = ab8500_irq_map,
571 .xlate = irq_domain_xlate_twocell,
Lee Jones06e589e2012-06-20 13:56:37 +0100572};
573
574static int ab8500_irq_init(struct ab8500 *ab8500, struct device_node *np)
Rabin Vincent62579262010-05-19 11:39:02 +0200575{
Linus Walleij2ced4452012-02-20 21:42:17 +0100576 int num_irqs;
Rabin Vincent62579262010-05-19 11:39:02 +0200577
Lee Jones3e1a4982013-02-25 14:57:35 +0000578 if (is_ab8540(ab8500))
579 num_irqs = AB8540_NR_IRQS;
580 else if (is_ab9540(ab8500))
Linus Walleijd6255522012-02-20 21:42:24 +0100581 num_irqs = AB9540_NR_IRQS;
Bengt Jonssona9823622012-03-08 14:01:57 +0100582 else if (is_ab8505(ab8500))
583 num_irqs = AB8505_NR_IRQS;
Linus Walleijd6255522012-02-20 21:42:24 +0100584 else
585 num_irqs = AB8500_NR_IRQS;
Linus Walleij2ced4452012-02-20 21:42:17 +0100586
Linus Walleijf1d11f32012-10-18 18:18:44 +0200587 /* If ->irq_base is zero this will give a linear mapping */
Grygorii Strashko7602e052014-06-02 19:27:58 +0300588 ab8500->domain = irq_domain_add_simple(ab8500->dev->of_node,
Lee Jones500e69a2015-10-28 09:15:02 +0000589 num_irqs, 0,
590 &ab8500_irq_ops, ab8500);
Lee Jones06e589e2012-06-20 13:56:37 +0100591
592 if (!ab8500->domain) {
593 dev_err(ab8500->dev, "Failed to create irqdomain\n");
Lee Jones500e69a2015-10-28 09:15:02 +0000594 return -ENODEV;
Lee Jones06e589e2012-06-20 13:56:37 +0100595 }
596
597 return 0;
Rabin Vincent62579262010-05-19 11:39:02 +0200598}
599
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200600int ab8500_suspend(struct ab8500 *ab8500)
601{
602 if (atomic_read(&ab8500->transfer_ongoing))
603 return -EINVAL;
Lee Jonesf3556302014-07-02 11:13:42 +0100604
605 return 0;
Jonas Aaberg112a80d2012-04-17 09:30:33 +0200606}
607
Geert Uytterhoeven5ac98552013-11-18 14:33:06 +0100608static const struct mfd_cell ab8500_bm_devs[] = {
Rickard Andersson6ef94182012-04-17 09:30:57 +0200609 {
610 .name = "ab8500-charger",
Rajanikanth H.V4aef72d2012-11-18 19:17:47 -0800611 .of_compatible = "stericsson,ab8500-charger",
Rajanikanth H.V4aef72d2012-11-18 19:17:47 -0800612 .platform_data = &ab8500_bm_data,
613 .pdata_size = sizeof(ab8500_bm_data),
Rickard Andersson6ef94182012-04-17 09:30:57 +0200614 },
615 {
616 .name = "ab8500-btemp",
Rajanikanth H.Vbd9e8ab2012-11-18 19:16:58 -0800617 .of_compatible = "stericsson,ab8500-btemp",
Rajanikanth H.Vbd9e8ab2012-11-18 19:16:58 -0800618 .platform_data = &ab8500_bm_data,
619 .pdata_size = sizeof(ab8500_bm_data),
Rickard Andersson6ef94182012-04-17 09:30:57 +0200620 },
621 {
622 .name = "ab8500-fg",
Rajanikanth H.Ve0f1abe2012-11-18 18:45:41 -0800623 .of_compatible = "stericsson,ab8500-fg",
Rajanikanth H.Ve0f1abe2012-11-18 18:45:41 -0800624 .platform_data = &ab8500_bm_data,
625 .pdata_size = sizeof(ab8500_bm_data),
Rickard Andersson6ef94182012-04-17 09:30:57 +0200626 },
627 {
628 .name = "ab8500-chargalg",
Rajanikanth H.Va12810a2012-10-31 15:40:33 +0000629 .of_compatible = "stericsson,ab8500-chargalg",
Rajanikanth H.Va12810a2012-10-31 15:40:33 +0000630 .platform_data = &ab8500_bm_data,
631 .pdata_size = sizeof(ab8500_bm_data),
Rickard Andersson6ef94182012-04-17 09:30:57 +0200632 },
633};
634
Geert Uytterhoeven5ac98552013-11-18 14:33:06 +0100635static const struct mfd_cell ab8500_devs[] = {
Lee Jones4b106fb2013-02-25 14:42:00 +0000636#ifdef CONFIG_DEBUG_FS
Linus Walleijd6255522012-02-20 21:42:24 +0100637 {
Lee Jones4b106fb2013-02-25 14:42:00 +0000638 .name = "ab8500-debug",
639 .of_compatible = "stericsson,ab8500-debug",
Lee Jones4b106fb2013-02-25 14:42:00 +0000640 },
641#endif
642 {
643 .name = "ab8500-sysctrl",
644 .of_compatible = "stericsson,ab8500-sysctrl",
645 },
646 {
Lee Jones53f325b2013-06-07 16:07:47 +0100647 .name = "ab8500-ext-regulator",
648 .of_compatible = "stericsson,ab8500-ext-regulator",
649 },
650 {
Lee Jones4b106fb2013-02-25 14:42:00 +0000651 .name = "ab8500-regulator",
652 .of_compatible = "stericsson,ab8500-regulator",
653 },
654 {
655 .name = "abx500-clk",
656 .of_compatible = "stericsson,abx500-clk",
657 },
658 {
659 .name = "ab8500-gpadc",
Lee Jones955de2e2013-05-08 14:29:09 +0100660 .of_compatible = "stericsson,ab8500-gpadc",
Lee Jones4b106fb2013-02-25 14:42:00 +0000661 },
662 {
663 .name = "ab8500-rtc",
664 .of_compatible = "stericsson,ab8500-rtc",
Lee Jones4b106fb2013-02-25 14:42:00 +0000665 },
666 {
667 .name = "ab8500-acc-det",
668 .of_compatible = "stericsson,ab8500-acc-det",
Lee Jones4b106fb2013-02-25 14:42:00 +0000669 },
670 {
671
672 .name = "ab8500-poweron-key",
673 .of_compatible = "stericsson,ab8500-poweron-key",
Lee Jones4b106fb2013-02-25 14:42:00 +0000674 },
675 {
676 .name = "ab8500-pwm",
677 .of_compatible = "stericsson,ab8500-pwm",
678 .id = 1,
679 },
680 {
681 .name = "ab8500-pwm",
682 .of_compatible = "stericsson,ab8500-pwm",
683 .id = 2,
684 },
685 {
686 .name = "ab8500-pwm",
687 .of_compatible = "stericsson,ab8500-pwm",
688 .id = 3,
689 },
690 {
Lee Jones4b106fb2013-02-25 14:42:00 +0000691 .name = "ab8500-denc",
692 .of_compatible = "stericsson,ab8500-denc",
693 },
694 {
Lee Joneseb696c32013-05-07 11:29:55 +0100695 .name = "pinctrl-ab8500",
Lee Jonesbad76992012-07-02 17:10:56 +0200696 .of_compatible = "stericsson,ab8500-gpio",
Linus Walleijd6255522012-02-20 21:42:24 +0100697 },
698 {
Lee Jones4b106fb2013-02-25 14:42:00 +0000699 .name = "abx500-temp",
700 .of_compatible = "stericsson,abx500-temp",
Lee Jones4b106fb2013-02-25 14:42:00 +0000701 },
702 {
Linus Walleijd6255522012-02-20 21:42:24 +0100703 .name = "ab8500-usb",
Fabio Baltierif201f732013-04-09 10:57:21 +0200704 .of_compatible = "stericsson,ab8500-usb",
Linus Walleijd6255522012-02-20 21:42:24 +0100705 },
Virupax Sadashivpetimath44f72e52012-04-17 09:30:14 +0200706 {
707 .name = "ab8500-codec",
Fabio Baltierifccf14a2013-05-30 15:27:45 +0200708 .of_compatible = "stericsson,ab8500-codec",
Lee Jones4b106fb2013-02-25 14:42:00 +0000709 },
710};
711
Geert Uytterhoeven5ac98552013-11-18 14:33:06 +0100712static const struct mfd_cell ab9540_devs[] = {
Lee Jones4b106fb2013-02-25 14:42:00 +0000713#ifdef CONFIG_DEBUG_FS
714 {
715 .name = "ab8500-debug",
Lee Jones4b106fb2013-02-25 14:42:00 +0000716 },
717#endif
718 {
719 .name = "ab8500-sysctrl",
720 },
721 {
Lee Jones53f325b2013-06-07 16:07:47 +0100722 .name = "ab8500-ext-regulator",
723 },
724 {
Lee Jones4b106fb2013-02-25 14:42:00 +0000725 .name = "ab8500-regulator",
Virupax Sadashivpetimath44f72e52012-04-17 09:30:14 +0200726 },
Lee Jonesc0eda9a2013-02-12 15:04:09 +0000727 {
Ulf Hansson9ee17672012-11-20 14:57:25 +0100728 .name = "abx500-clk",
729 .of_compatible = "stericsson,abx500-clk",
730 },
731 {
Lee Jonesc0eda9a2013-02-12 15:04:09 +0000732 .name = "ab8500-gpadc",
733 .of_compatible = "stericsson,ab8500-gpadc",
Lee Jonesc0eda9a2013-02-12 15:04:09 +0000734 },
Lee Jones4b106fb2013-02-25 14:42:00 +0000735 {
736 .name = "ab8500-rtc",
Lee Jones4b106fb2013-02-25 14:42:00 +0000737 },
738 {
739 .name = "ab8500-acc-det",
Lee Jones4b106fb2013-02-25 14:42:00 +0000740 },
741 {
742 .name = "ab8500-poweron-key",
Lee Jones4b106fb2013-02-25 14:42:00 +0000743 },
744 {
745 .name = "ab8500-pwm",
746 .id = 1,
747 },
748 {
Lee Jones4b106fb2013-02-25 14:42:00 +0000749 .name = "abx500-temp",
Lee Jones4b106fb2013-02-25 14:42:00 +0000750 },
Linus Walleijd6255522012-02-20 21:42:24 +0100751 {
Lee Jonese64d9052013-01-16 15:09:36 +0000752 .name = "pinctrl-ab9540",
753 .of_compatible = "stericsson,ab9540-gpio",
Linus Walleijd6255522012-02-20 21:42:24 +0100754 },
755 {
756 .name = "ab9540-usb",
Linus Walleijd6255522012-02-20 21:42:24 +0100757 },
Virupax Sadashivpetimath44f72e52012-04-17 09:30:14 +0200758 {
759 .name = "ab9540-codec",
760 },
Lee Jonesc0eda9a2013-02-12 15:04:09 +0000761 {
Lee Jonesc0eda9a2013-02-12 15:04:09 +0000762 .name = "ab-iddet",
Lee Jonesc0eda9a2013-02-12 15:04:09 +0000763 },
Virupax Sadashivpetimath44f72e52012-04-17 09:30:14 +0200764};
765
Lee Jonesc0eda9a2013-02-12 15:04:09 +0000766/* Device list for ab8505 */
Geert Uytterhoeven5ac98552013-11-18 14:33:06 +0100767static const struct mfd_cell ab8505_devs[] = {
Lee Jones4b106fb2013-02-25 14:42:00 +0000768#ifdef CONFIG_DEBUG_FS
769 {
770 .name = "ab8500-debug",
Lee Jones4b106fb2013-02-25 14:42:00 +0000771 },
772#endif
773 {
774 .name = "ab8500-sysctrl",
775 },
776 {
777 .name = "ab8500-regulator",
778 },
779 {
Ulf Hansson9ee17672012-11-20 14:57:25 +0100780 .name = "abx500-clk",
781 .of_compatible = "stericsson,abx500-clk",
782 },
783 {
Lee Jones4b106fb2013-02-25 14:42:00 +0000784 .name = "ab8500-gpadc",
Lee Jones955de2e2013-05-08 14:29:09 +0100785 .of_compatible = "stericsson,ab8500-gpadc",
Lee Jones4b106fb2013-02-25 14:42:00 +0000786 },
787 {
788 .name = "ab8500-rtc",
Lee Jones4b106fb2013-02-25 14:42:00 +0000789 },
790 {
791 .name = "ab8500-acc-det",
Lee Jones4b106fb2013-02-25 14:42:00 +0000792 },
793 {
794 .name = "ab8500-poweron-key",
Lee Jones4b106fb2013-02-25 14:42:00 +0000795 },
796 {
797 .name = "ab8500-pwm",
798 .id = 1,
799 },
800 {
Lee Joneseb696c32013-05-07 11:29:55 +0100801 .name = "pinctrl-ab8505",
Lee Jones4b106fb2013-02-25 14:42:00 +0000802 },
803 {
804 .name = "ab8500-usb",
Lee Jones4b106fb2013-02-25 14:42:00 +0000805 },
806 {
807 .name = "ab8500-codec",
808 },
Lee Jonesc0eda9a2013-02-12 15:04:09 +0000809 {
810 .name = "ab-iddet",
Lee Jonesc0eda9a2013-02-12 15:04:09 +0000811 },
812};
813
Geert Uytterhoeven5ac98552013-11-18 14:33:06 +0100814static const struct mfd_cell ab8540_devs[] = {
Lee Jones4b106fb2013-02-25 14:42:00 +0000815#ifdef CONFIG_DEBUG_FS
816 {
817 .name = "ab8500-debug",
Lee Jones4b106fb2013-02-25 14:42:00 +0000818 },
819#endif
820 {
821 .name = "ab8500-sysctrl",
822 },
823 {
Lee Jones53f325b2013-06-07 16:07:47 +0100824 .name = "ab8500-ext-regulator",
825 },
826 {
Lee Jones4b106fb2013-02-25 14:42:00 +0000827 .name = "ab8500-regulator",
828 },
829 {
Ulf Hansson9ee17672012-11-20 14:57:25 +0100830 .name = "abx500-clk",
831 .of_compatible = "stericsson,abx500-clk",
832 },
833 {
Lee Jones4b106fb2013-02-25 14:42:00 +0000834 .name = "ab8500-gpadc",
Lee Jones955de2e2013-05-08 14:29:09 +0100835 .of_compatible = "stericsson,ab8500-gpadc",
Lee Jones4b106fb2013-02-25 14:42:00 +0000836 },
837 {
Lee Jones4b106fb2013-02-25 14:42:00 +0000838 .name = "ab8500-acc-det",
Lee Jones4b106fb2013-02-25 14:42:00 +0000839 },
840 {
841 .name = "ab8500-poweron-key",
Lee Jones4b106fb2013-02-25 14:42:00 +0000842 },
843 {
844 .name = "ab8500-pwm",
845 .id = 1,
846 },
847 {
Lee Jones4b106fb2013-02-25 14:42:00 +0000848 .name = "abx500-temp",
Lee Jones4b106fb2013-02-25 14:42:00 +0000849 },
Lee Jonesc0eda9a2013-02-12 15:04:09 +0000850 {
Lee Joneseb696c32013-05-07 11:29:55 +0100851 .name = "pinctrl-ab8540",
Lee Jonesc0eda9a2013-02-12 15:04:09 +0000852 },
853 {
854 .name = "ab8540-usb",
Lee Jonesc0eda9a2013-02-12 15:04:09 +0000855 },
856 {
857 .name = "ab8540-codec",
858 },
859 {
Virupax Sadashivpetimath44f72e52012-04-17 09:30:14 +0200860 .name = "ab-iddet",
Virupax Sadashivpetimath44f72e52012-04-17 09:30:14 +0200861 },
Linus Walleijd6255522012-02-20 21:42:24 +0100862};
863
Geert Uytterhoeven5ac98552013-11-18 14:33:06 +0100864static const struct mfd_cell ab8540_cut1_devs[] = {
Alexandre Torgue9c717cf2013-05-24 11:59:47 +0200865 {
866 .name = "ab8500-rtc",
867 .of_compatible = "stericsson,ab8500-rtc",
Alexandre Torgue9c717cf2013-05-24 11:59:47 +0200868 },
869};
870
Geert Uytterhoeven5ac98552013-11-18 14:33:06 +0100871static const struct mfd_cell ab8540_cut2_devs[] = {
Alexandre Torgue9c717cf2013-05-24 11:59:47 +0200872 {
873 .name = "ab8540-rtc",
874 .of_compatible = "stericsson,ab8540-rtc",
Alexandre Torgue9c717cf2013-05-24 11:59:47 +0200875 },
876};
877
Mattias Wallincca69b62010-12-02 15:09:36 +0100878static ssize_t show_chip_id(struct device *dev,
879 struct device_attribute *attr, char *buf)
880{
881 struct ab8500 *ab8500;
882
883 ab8500 = dev_get_drvdata(dev);
Lee Jonese436ddf2013-02-26 10:09:41 +0000884
Mattias Wallincca69b62010-12-02 15:09:36 +0100885 return sprintf(buf, "%#x\n", ab8500 ? ab8500->chip_id : -EINVAL);
886}
887
Mattias Walline5c238c2011-03-02 11:52:36 +0100888/*
889 * ab8500 has switched off due to (SWITCH_OFF_STATUS):
890 * 0x01 Swoff bit programming
891 * 0x02 Thermal protection activation
892 * 0x04 Vbat lower then BattOk falling threshold
893 * 0x08 Watchdog expired
894 * 0x10 Non presence of 32kHz clock
895 * 0x20 Battery level lower than power on reset threshold
896 * 0x40 Power on key 1 pressed longer than 10 seconds
897 * 0x80 DB8500 thermal shutdown
898 */
899static ssize_t show_switch_off_status(struct device *dev,
900 struct device_attribute *attr, char *buf)
901{
902 int ret;
903 u8 value;
904 struct ab8500 *ab8500;
905
906 ab8500 = dev_get_drvdata(dev);
907 ret = get_register_interruptible(ab8500, AB8500_RTC,
908 AB8500_SWITCH_OFF_STATUS, &value);
909 if (ret < 0)
910 return ret;
911 return sprintf(buf, "%#x\n", value);
912}
913
Rajkumar Kasirajanf04a9d82012-05-30 16:32:37 +0530914/* use mask and set to override the register turn_on_stat value */
915void ab8500_override_turn_on_stat(u8 mask, u8 set)
916{
917 spin_lock(&on_stat_lock);
918 turn_on_stat_mask = mask;
919 turn_on_stat_set = set;
920 spin_unlock(&on_stat_lock);
921}
922
Andrew Lynnb4a31032011-10-11 10:49:47 +0200923/*
924 * ab8500 has turned on due to (TURN_ON_STATUS):
925 * 0x01 PORnVbat
926 * 0x02 PonKey1dbF
927 * 0x04 PonKey2dbF
928 * 0x08 RTCAlarm
929 * 0x10 MainChDet
930 * 0x20 VbusDet
931 * 0x40 UsbIDDetect
932 * 0x80 Reserved
933 */
934static ssize_t show_turn_on_status(struct device *dev,
935 struct device_attribute *attr, char *buf)
936{
937 int ret;
938 u8 value;
939 struct ab8500 *ab8500;
940
941 ab8500 = dev_get_drvdata(dev);
942 ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK,
943 AB8500_TURN_ON_STATUS, &value);
944 if (ret < 0)
945 return ret;
Rajkumar Kasirajanf04a9d82012-05-30 16:32:37 +0530946
947 /*
948 * In L9540, turn_on_status register is not updated correctly if
949 * the device is rebooted with AC/USB charger connected. Due to
950 * this, the device boots android instead of entering into charge
951 * only mode. Read the AC/USB status register to detect the charger
952 * presence and update the turn on status manually.
953 */
954 if (is_ab9540(ab8500)) {
955 spin_lock(&on_stat_lock);
956 value = (value & turn_on_stat_mask) | turn_on_stat_set;
957 spin_unlock(&on_stat_lock);
958 }
959
Andrew Lynnb4a31032011-10-11 10:49:47 +0200960 return sprintf(buf, "%#x\n", value);
961}
962
Lee Jones93ff7222012-05-31 16:16:36 +0200963static ssize_t show_turn_on_status_2(struct device *dev,
964 struct device_attribute *attr, char *buf)
965{
966 int ret;
967 u8 value;
968 struct ab8500 *ab8500;
969
970 ab8500 = dev_get_drvdata(dev);
971 ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK,
972 AB8505_TURN_ON_STATUS_2, &value);
973 if (ret < 0)
974 return ret;
975 return sprintf(buf, "%#x\n", (value & 0x1));
976}
977
Linus Walleijd6255522012-02-20 21:42:24 +0100978static ssize_t show_ab9540_dbbrstn(struct device *dev,
979 struct device_attribute *attr, char *buf)
980{
981 struct ab8500 *ab8500;
982 int ret;
983 u8 value;
984
985 ab8500 = dev_get_drvdata(dev);
986
987 ret = get_register_interruptible(ab8500, AB8500_REGU_CTRL2,
988 AB9540_MODEM_CTRL2_REG, &value);
989 if (ret < 0)
990 return ret;
991
992 return sprintf(buf, "%d\n",
993 (value & AB9540_MODEM_CTRL2_SWDBBRSTN_BIT) ? 1 : 0);
994}
995
996static ssize_t store_ab9540_dbbrstn(struct device *dev,
997 struct device_attribute *attr, const char *buf, size_t count)
998{
999 struct ab8500 *ab8500;
1000 int ret = count;
1001 int err;
1002 u8 bitvalues;
1003
1004 ab8500 = dev_get_drvdata(dev);
1005
1006 if (count > 0) {
1007 switch (buf[0]) {
1008 case '0':
1009 bitvalues = 0;
1010 break;
1011 case '1':
1012 bitvalues = AB9540_MODEM_CTRL2_SWDBBRSTN_BIT;
1013 break;
1014 default:
1015 goto exit;
1016 }
1017
1018 err = mask_and_set_register_interruptible(ab8500,
1019 AB8500_REGU_CTRL2, AB9540_MODEM_CTRL2_REG,
1020 AB9540_MODEM_CTRL2_SWDBBRSTN_BIT, bitvalues);
1021 if (err)
1022 dev_info(ab8500->dev,
1023 "Failed to set DBBRSTN %c, err %#x\n",
1024 buf[0], err);
1025 }
1026
1027exit:
1028 return ret;
1029}
1030
Mattias Wallincca69b62010-12-02 15:09:36 +01001031static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL);
Mattias Walline5c238c2011-03-02 11:52:36 +01001032static DEVICE_ATTR(switch_off_status, S_IRUGO, show_switch_off_status, NULL);
Andrew Lynnb4a31032011-10-11 10:49:47 +02001033static DEVICE_ATTR(turn_on_status, S_IRUGO, show_turn_on_status, NULL);
Lee Jones93ff7222012-05-31 16:16:36 +02001034static DEVICE_ATTR(turn_on_status_2, S_IRUGO, show_turn_on_status_2, NULL);
Linus Walleijd6255522012-02-20 21:42:24 +01001035static DEVICE_ATTR(dbbrstn, S_IRUGO | S_IWUSR,
1036 show_ab9540_dbbrstn, store_ab9540_dbbrstn);
Mattias Wallincca69b62010-12-02 15:09:36 +01001037
1038static struct attribute *ab8500_sysfs_entries[] = {
1039 &dev_attr_chip_id.attr,
Mattias Walline5c238c2011-03-02 11:52:36 +01001040 &dev_attr_switch_off_status.attr,
Andrew Lynnb4a31032011-10-11 10:49:47 +02001041 &dev_attr_turn_on_status.attr,
Mattias Wallincca69b62010-12-02 15:09:36 +01001042 NULL,
1043};
1044
Lee Jones93ff7222012-05-31 16:16:36 +02001045static struct attribute *ab8505_sysfs_entries[] = {
1046 &dev_attr_turn_on_status_2.attr,
1047 NULL,
1048};
1049
Linus Walleijd6255522012-02-20 21:42:24 +01001050static struct attribute *ab9540_sysfs_entries[] = {
1051 &dev_attr_chip_id.attr,
1052 &dev_attr_switch_off_status.attr,
1053 &dev_attr_turn_on_status.attr,
1054 &dev_attr_dbbrstn.attr,
1055 NULL,
1056};
1057
Mattias Wallincca69b62010-12-02 15:09:36 +01001058static struct attribute_group ab8500_attr_group = {
1059 .attrs = ab8500_sysfs_entries,
1060};
1061
Lee Jones93ff7222012-05-31 16:16:36 +02001062static struct attribute_group ab8505_attr_group = {
1063 .attrs = ab8505_sysfs_entries,
1064};
1065
Linus Walleijd6255522012-02-20 21:42:24 +01001066static struct attribute_group ab9540_attr_group = {
1067 .attrs = ab9540_sysfs_entries,
1068};
1069
Bill Pembertonf791be42012-11-19 13:23:04 -05001070static int ab8500_probe(struct platform_device *pdev)
Rabin Vincent62579262010-05-19 11:39:02 +02001071{
Lee Jones500e69a2015-10-28 09:15:02 +00001072 static const char * const switch_off_status[] = {
Jonas Aabergb04c530c2012-06-29 17:46:12 +02001073 "Swoff bit programming",
1074 "Thermal protection activation",
1075 "Vbat lower then BattOk falling threshold",
1076 "Watchdog expired",
1077 "Non presence of 32kHz clock",
1078 "Battery level lower than power on reset threshold",
1079 "Power on key 1 pressed longer than 10 seconds",
1080 "DB8500 thermal shutdown"};
Lee Jones500e69a2015-10-28 09:15:02 +00001081 static const char * const turn_on_status[] = {
Mattias Wallinabee26c2012-09-28 09:34:24 +02001082 "Battery rising (Vbat)",
1083 "Power On Key 1 dbF",
1084 "Power On Key 2 dbF",
1085 "RTC Alarm",
1086 "Main Charger Detect",
1087 "Vbus Detect (USB)",
1088 "USB ID Detect",
1089 "UART Factory Mode Detect"};
Lee Jonesd28f1db2012-05-19 17:21:37 +02001090 struct ab8500_platform_data *plat = dev_get_platdata(&pdev->dev);
1091 const struct platform_device_id *platid = platform_get_device_id(pdev);
Lee Jones6bc4a562012-05-17 14:45:13 +01001092 enum ab8500_version version = AB8500_VERSION_UNDEFINED;
1093 struct device_node *np = pdev->dev.of_node;
Lee Jonesd28f1db2012-05-19 17:21:37 +02001094 struct ab8500 *ab8500;
1095 struct resource *resource;
Rabin Vincent62579262010-05-19 11:39:02 +02001096 int ret;
1097 int i;
Mattias Wallin47c16972010-09-10 17:47:56 +02001098 u8 value;
Rabin Vincent62579262010-05-19 11:39:02 +02001099
Lee Jones7ccf40b2014-05-08 14:11:37 +01001100 ab8500 = devm_kzalloc(&pdev->dev, sizeof(*ab8500), GFP_KERNEL);
Lee Jonesd28f1db2012-05-19 17:21:37 +02001101 if (!ab8500)
1102 return -ENOMEM;
1103
Lee Jonesd28f1db2012-05-19 17:21:37 +02001104 ab8500->dev = &pdev->dev;
1105
1106 resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
Linus Walleijf864c462014-02-04 00:35:56 +01001107 if (!resource) {
1108 dev_err(&pdev->dev, "no IRQ resource\n");
Lee Jones8c4203c2012-11-05 16:10:35 +01001109 return -ENODEV;
Linus Walleijf864c462014-02-04 00:35:56 +01001110 }
Lee Jonesd28f1db2012-05-19 17:21:37 +02001111
1112 ab8500->irq = resource->start;
1113
Lee Jones822672a2012-06-20 13:56:38 +01001114 ab8500->read = ab8500_prcmu_read;
1115 ab8500->write = ab8500_prcmu_write;
1116 ab8500->write_masked = ab8500_prcmu_write_masked;
Lee Jonesd28f1db2012-05-19 17:21:37 +02001117
Rabin Vincent62579262010-05-19 11:39:02 +02001118 mutex_init(&ab8500->lock);
1119 mutex_init(&ab8500->irq_lock);
Jonas Aaberg112a80d2012-04-17 09:30:33 +02001120 atomic_set(&ab8500->transfer_ongoing, 0);
Rabin Vincent62579262010-05-19 11:39:02 +02001121
Lee Jonesd28f1db2012-05-19 17:21:37 +02001122 platform_set_drvdata(pdev, ab8500);
1123
Lee Jones6bc4a562012-05-17 14:45:13 +01001124 if (platid)
1125 version = platid->driver_data;
Lee Jones6bc4a562012-05-17 14:45:13 +01001126
Linus Walleij0f6208372012-02-20 21:42:10 +01001127 if (version != AB8500_VERSION_UNDEFINED)
1128 ab8500->version = version;
1129 else {
1130 ret = get_register_interruptible(ab8500, AB8500_MISC,
1131 AB8500_IC_NAME_REG, &value);
Linus Walleijf864c462014-02-04 00:35:56 +01001132 if (ret < 0) {
1133 dev_err(&pdev->dev, "could not probe HW\n");
Lee Jones8c4203c2012-11-05 16:10:35 +01001134 return ret;
Linus Walleijf864c462014-02-04 00:35:56 +01001135 }
Linus Walleij0f6208372012-02-20 21:42:10 +01001136
1137 ab8500->version = value;
1138 }
1139
Mattias Wallin47c16972010-09-10 17:47:56 +02001140 ret = get_register_interruptible(ab8500, AB8500_MISC,
1141 AB8500_REV_REG, &value);
Rabin Vincent62579262010-05-19 11:39:02 +02001142 if (ret < 0)
Lee Jones8c4203c2012-11-05 16:10:35 +01001143 return ret;
Rabin Vincent62579262010-05-19 11:39:02 +02001144
Mattias Wallin47c16972010-09-10 17:47:56 +02001145 ab8500->chip_id = value;
Rabin Vincent62579262010-05-19 11:39:02 +02001146
Linus Walleij0f6208372012-02-20 21:42:10 +01001147 dev_info(ab8500->dev, "detected chip, %s rev. %1x.%1x\n",
1148 ab8500_version_str[ab8500->version],
1149 ab8500->chip_id >> 4,
1150 ab8500->chip_id & 0x0F);
1151
Lee Jones3e1a4982013-02-25 14:57:35 +00001152 /* Configure AB8540 */
1153 if (is_ab8540(ab8500)) {
1154 ab8500->mask_size = AB8540_NUM_IRQ_REGS;
1155 ab8500->irq_reg_offset = ab8540_irq_regoffset;
1156 ab8500->it_latchhier_num = AB8540_IT_LATCHHIER_NUM;
Lee Jones7ccf40b2014-05-08 14:11:37 +01001157 } /* Configure AB8500 or AB9540 IRQ */
Lee Jones3e1a4982013-02-25 14:57:35 +00001158 else if (is_ab9540(ab8500) || is_ab8505(ab8500)) {
Linus Walleijd6255522012-02-20 21:42:24 +01001159 ab8500->mask_size = AB9540_NUM_IRQ_REGS;
1160 ab8500->irq_reg_offset = ab9540_irq_regoffset;
Lee Jones3e1a4982013-02-25 14:57:35 +00001161 ab8500->it_latchhier_num = AB8500_IT_LATCHHIER_NUM;
Linus Walleijd6255522012-02-20 21:42:24 +01001162 } else {
1163 ab8500->mask_size = AB8500_NUM_IRQ_REGS;
1164 ab8500->irq_reg_offset = ab8500_irq_regoffset;
Lee Jones3e1a4982013-02-25 14:57:35 +00001165 ab8500->it_latchhier_num = AB8500_IT_LATCHHIER_NUM;
Linus Walleijd6255522012-02-20 21:42:24 +01001166 }
Lee Jones7ccf40b2014-05-08 14:11:37 +01001167 ab8500->mask = devm_kzalloc(&pdev->dev, ab8500->mask_size,
1168 GFP_KERNEL);
Linus Walleij2ced4452012-02-20 21:42:17 +01001169 if (!ab8500->mask)
1170 return -ENOMEM;
Lee Jones7ccf40b2014-05-08 14:11:37 +01001171 ab8500->oldmask = devm_kzalloc(&pdev->dev, ab8500->mask_size,
1172 GFP_KERNEL);
Lee Jones8c4203c2012-11-05 16:10:35 +01001173 if (!ab8500->oldmask)
1174 return -ENOMEM;
1175
Mattias Walline5c238c2011-03-02 11:52:36 +01001176 /*
1177 * ab8500 has switched off due to (SWITCH_OFF_STATUS):
1178 * 0x01 Swoff bit programming
1179 * 0x02 Thermal protection activation
1180 * 0x04 Vbat lower then BattOk falling threshold
1181 * 0x08 Watchdog expired
1182 * 0x10 Non presence of 32kHz clock
1183 * 0x20 Battery level lower than power on reset threshold
1184 * 0x40 Power on key 1 pressed longer than 10 seconds
1185 * 0x80 DB8500 thermal shutdown
1186 */
1187
1188 ret = get_register_interruptible(ab8500, AB8500_RTC,
1189 AB8500_SWITCH_OFF_STATUS, &value);
1190 if (ret < 0)
1191 return ret;
Jonas Aabergb04c530c2012-06-29 17:46:12 +02001192 dev_info(ab8500->dev, "switch off cause(s) (%#x): ", value);
1193
1194 if (value) {
1195 for (i = 0; i < ARRAY_SIZE(switch_off_status); i++) {
1196 if (value & 1)
Lee Jones7ccf40b2014-05-08 14:11:37 +01001197 pr_cont(" \"%s\"", switch_off_status[i]);
Jonas Aabergb04c530c2012-06-29 17:46:12 +02001198 value = value >> 1;
1199
1200 }
Lee Jones7ccf40b2014-05-08 14:11:37 +01001201 pr_cont("\n");
Jonas Aabergb04c530c2012-06-29 17:46:12 +02001202 } else {
Lee Jones7ccf40b2014-05-08 14:11:37 +01001203 pr_cont(" None\n");
Jonas Aabergb04c530c2012-06-29 17:46:12 +02001204 }
Mattias Wallinabee26c2012-09-28 09:34:24 +02001205 ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK,
1206 AB8500_TURN_ON_STATUS, &value);
1207 if (ret < 0)
1208 return ret;
1209 dev_info(ab8500->dev, "turn on reason(s) (%#x): ", value);
1210
1211 if (value) {
1212 for (i = 0; i < ARRAY_SIZE(turn_on_status); i++) {
1213 if (value & 1)
Lee Jones7ccf40b2014-05-08 14:11:37 +01001214 pr_cont("\"%s\" ", turn_on_status[i]);
Mattias Wallinabee26c2012-09-28 09:34:24 +02001215 value = value >> 1;
1216 }
Lee Jones7ccf40b2014-05-08 14:11:37 +01001217 pr_cont("\n");
Mattias Wallinabee26c2012-09-28 09:34:24 +02001218 } else {
Lee Jones7ccf40b2014-05-08 14:11:37 +01001219 pr_cont("None\n");
Mattias Wallinabee26c2012-09-28 09:34:24 +02001220 }
Mattias Walline5c238c2011-03-02 11:52:36 +01001221
Rabin Vincent62579262010-05-19 11:39:02 +02001222 if (plat && plat->init)
1223 plat->init(ab8500);
Mattias Wallinabee26c2012-09-28 09:34:24 +02001224
Rajkumar Kasirajanf04a9d82012-05-30 16:32:37 +05301225 if (is_ab9540(ab8500)) {
1226 ret = get_register_interruptible(ab8500, AB8500_CHARGER,
1227 AB8500_CH_USBCH_STAT1_REG, &value);
1228 if (ret < 0)
1229 return ret;
1230 if ((value & VBUS_DET_DBNC1) && (value & VBUS_DET_DBNC100))
1231 ab8500_override_turn_on_stat(~AB8500_POW_KEY_1_ON,
1232 AB8500_VBUS_DET);
1233 }
Rabin Vincent62579262010-05-19 11:39:02 +02001234
1235 /* Clear and mask all interrupts */
Linus Walleij2ced4452012-02-20 21:42:17 +01001236 for (i = 0; i < ab8500->mask_size; i++) {
Linus Walleij0f6208372012-02-20 21:42:10 +01001237 /*
1238 * Interrupt register 12 doesn't exist prior to AB8500 version
1239 * 2.0
1240 */
1241 if (ab8500->irq_reg_offset[i] == 11 &&
1242 is_ab8500_1p1_or_earlier(ab8500))
Mattias Wallin92d50a42010-12-07 11:20:47 +01001243 continue;
Rabin Vincent62579262010-05-19 11:39:02 +02001244
Lee Jones3e1a4982013-02-25 14:57:35 +00001245 if (ab8500->irq_reg_offset[i] < 0)
1246 continue;
1247
Mattias Wallin47c16972010-09-10 17:47:56 +02001248 get_register_interruptible(ab8500, AB8500_INTERRUPT,
Linus Walleij2ced4452012-02-20 21:42:17 +01001249 AB8500_IT_LATCH1_REG + ab8500->irq_reg_offset[i],
Mattias Wallin92d50a42010-12-07 11:20:47 +01001250 &value);
Mattias Wallin47c16972010-09-10 17:47:56 +02001251 set_register_interruptible(ab8500, AB8500_INTERRUPT,
Linus Walleij2ced4452012-02-20 21:42:17 +01001252 AB8500_IT_MASK1_REG + ab8500->irq_reg_offset[i], 0xff);
Rabin Vincent62579262010-05-19 11:39:02 +02001253 }
1254
Mattias Wallin47c16972010-09-10 17:47:56 +02001255 ret = abx500_register_ops(ab8500->dev, &ab8500_ops);
1256 if (ret)
Lee Jones8c4203c2012-11-05 16:10:35 +01001257 return ret;
Mattias Wallin47c16972010-09-10 17:47:56 +02001258
Linus Walleij2ced4452012-02-20 21:42:17 +01001259 for (i = 0; i < ab8500->mask_size; i++)
Rabin Vincent62579262010-05-19 11:39:02 +02001260 ab8500->mask[i] = ab8500->oldmask[i] = 0xff;
1261
Lee Jones06e589e2012-06-20 13:56:37 +01001262 ret = ab8500_irq_init(ab8500, np);
1263 if (ret)
Lee Jones8c4203c2012-11-05 16:10:35 +01001264 return ret;
Rabin Vincent62579262010-05-19 11:39:02 +02001265
Dariusz Szymczakf348fef2012-11-26 13:31:26 +01001266 ret = devm_request_threaded_irq(&pdev->dev, ab8500->irq, NULL,
1267 ab8500_hierarchical_irq,
1268 IRQF_ONESHOT | IRQF_NO_SUSPEND,
1269 "ab8500", ab8500);
1270 if (ret)
1271 return ret;
Rabin Vincent62579262010-05-19 11:39:02 +02001272
Lee Jonesbad76992012-07-02 17:10:56 +02001273 if (is_ab9540(ab8500))
1274 ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs,
1275 ARRAY_SIZE(ab9540_devs), NULL,
Linus Walleijf864c462014-02-04 00:35:56 +01001276 0, ab8500->domain);
Alexandre Torgue9c717cf2013-05-24 11:59:47 +02001277 else if (is_ab8540(ab8500)) {
Lee Jonesc0eda9a2013-02-12 15:04:09 +00001278 ret = mfd_add_devices(ab8500->dev, 0, ab8540_devs,
1279 ARRAY_SIZE(ab8540_devs), NULL,
Linus Walleijf864c462014-02-04 00:35:56 +01001280 0, ab8500->domain);
Alexandre Torgue9c717cf2013-05-24 11:59:47 +02001281 if (ret)
1282 return ret;
1283
1284 if (is_ab8540_1p2_or_earlier(ab8500))
1285 ret = mfd_add_devices(ab8500->dev, 0, ab8540_cut1_devs,
1286 ARRAY_SIZE(ab8540_cut1_devs), NULL,
Linus Walleijf864c462014-02-04 00:35:56 +01001287 0, ab8500->domain);
Alexandre Torgue9c717cf2013-05-24 11:59:47 +02001288 else /* ab8540 >= cut2 */
1289 ret = mfd_add_devices(ab8500->dev, 0, ab8540_cut2_devs,
1290 ARRAY_SIZE(ab8540_cut2_devs), NULL,
Linus Walleijf864c462014-02-04 00:35:56 +01001291 0, ab8500->domain);
Alexandre Torgue9c717cf2013-05-24 11:59:47 +02001292 } else if (is_ab8505(ab8500))
Lee Jonesc0eda9a2013-02-12 15:04:09 +00001293 ret = mfd_add_devices(ab8500->dev, 0, ab8505_devs,
1294 ARRAY_SIZE(ab8505_devs), NULL,
Linus Walleijf864c462014-02-04 00:35:56 +01001295 0, ab8500->domain);
Lee Jonesbad76992012-07-02 17:10:56 +02001296 else
1297 ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs,
1298 ARRAY_SIZE(ab8500_devs), NULL,
Linus Walleijf864c462014-02-04 00:35:56 +01001299 0, ab8500->domain);
Lee Jonesbad76992012-07-02 17:10:56 +02001300 if (ret)
Lee Jones8c4203c2012-11-05 16:10:35 +01001301 return ret;
Linus Walleijd6255522012-02-20 21:42:24 +01001302
Rickard Andersson6ef94182012-04-17 09:30:57 +02001303 if (!no_bm) {
1304 /* Add battery management devices */
1305 ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs,
1306 ARRAY_SIZE(ab8500_bm_devs), NULL,
Linus Walleijf864c462014-02-04 00:35:56 +01001307 0, ab8500->domain);
Rickard Andersson6ef94182012-04-17 09:30:57 +02001308 if (ret)
1309 dev_err(ab8500->dev, "error adding bm devices\n");
1310 }
1311
Lee Jonese436ddf2013-02-26 10:09:41 +00001312 if (((is_ab8505(ab8500) || is_ab9540(ab8500)) &&
1313 ab8500->chip_id >= AB8500_CUT2P0) || is_ab8540(ab8500))
Linus Walleijd6255522012-02-20 21:42:24 +01001314 ret = sysfs_create_group(&ab8500->dev->kobj,
1315 &ab9540_attr_group);
1316 else
1317 ret = sysfs_create_group(&ab8500->dev->kobj,
1318 &ab8500_attr_group);
Lee Jones93ff7222012-05-31 16:16:36 +02001319
1320 if ((is_ab8505(ab8500) || is_ab9540(ab8500)) &&
1321 ab8500->chip_id >= AB8500_CUT2P0)
1322 ret = sysfs_create_group(&ab8500->dev->kobj,
1323 &ab8505_attr_group);
1324
Mattias Wallincca69b62010-12-02 15:09:36 +01001325 if (ret)
1326 dev_err(ab8500->dev, "error creating sysfs entries\n");
Lee Jones06e589e2012-06-20 13:56:37 +01001327
1328 return ret;
Rabin Vincent62579262010-05-19 11:39:02 +02001329}
1330
Bill Pemberton4740f732012-11-19 13:26:01 -05001331static int ab8500_remove(struct platform_device *pdev)
Rabin Vincent62579262010-05-19 11:39:02 +02001332{
Lee Jonesd28f1db2012-05-19 17:21:37 +02001333 struct ab8500 *ab8500 = platform_get_drvdata(pdev);
1334
Lee Jonese436ddf2013-02-26 10:09:41 +00001335 if (((is_ab8505(ab8500) || is_ab9540(ab8500)) &&
1336 ab8500->chip_id >= AB8500_CUT2P0) || is_ab8540(ab8500))
Linus Walleijd6255522012-02-20 21:42:24 +01001337 sysfs_remove_group(&ab8500->dev->kobj, &ab9540_attr_group);
1338 else
1339 sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group);
Lee Jones06e589e2012-06-20 13:56:37 +01001340
Lee Jones93ff7222012-05-31 16:16:36 +02001341 if ((is_ab8505(ab8500) || is_ab9540(ab8500)) &&
1342 ab8500->chip_id >= AB8500_CUT2P0)
1343 sysfs_remove_group(&ab8500->dev->kobj, &ab8505_attr_group);
1344
Rabin Vincent62579262010-05-19 11:39:02 +02001345 mfd_remove_devices(ab8500->dev);
Rabin Vincent62579262010-05-19 11:39:02 +02001346
1347 return 0;
1348}
1349
Lee Jonesd28f1db2012-05-19 17:21:37 +02001350static const struct platform_device_id ab8500_id[] = {
1351 { "ab8500-core", AB8500_VERSION_AB8500 },
1352 { "ab8505-i2c", AB8500_VERSION_AB8505 },
1353 { "ab9540-i2c", AB8500_VERSION_AB9540 },
1354 { "ab8540-i2c", AB8500_VERSION_AB8540 },
1355 { }
1356};
1357
1358static struct platform_driver ab8500_core_driver = {
1359 .driver = {
1360 .name = "ab8500-core",
Lee Jonesd28f1db2012-05-19 17:21:37 +02001361 },
1362 .probe = ab8500_probe,
Bill Pemberton84449212012-11-19 13:20:24 -05001363 .remove = ab8500_remove,
Lee Jonesd28f1db2012-05-19 17:21:37 +02001364 .id_table = ab8500_id,
1365};
1366
1367static int __init ab8500_core_init(void)
1368{
1369 return platform_driver_register(&ab8500_core_driver);
1370}
1371
1372static void __exit ab8500_core_exit(void)
1373{
1374 platform_driver_unregister(&ab8500_core_driver);
1375}
Lee Jonesba7cbc32012-06-11 16:25:00 +01001376core_initcall(ab8500_core_init);
Lee Jonesd28f1db2012-05-19 17:21:37 +02001377module_exit(ab8500_core_exit);
1378
Mattias Wallinadceed62011-03-02 11:51:11 +01001379MODULE_AUTHOR("Mattias Wallin, Srinidhi Kasagar, Rabin Vincent");
Rabin Vincent62579262010-05-19 11:39:02 +02001380MODULE_DESCRIPTION("AB8500 MFD core");
1381MODULE_LICENSE("GPL v2");