aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRabin Vincent <rabin.vincent@stericsson.com>2010-05-19 05:39:02 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2010-05-27 19:38:00 -0400
commit62579266cf9caca5b999560be2b5ceee42fc4d4d (patch)
treeeda6066624c734ef3057a9dc568ebaf978499c1a
parent75907a1153b42100b7a5e960bfe47d208d726309 (diff)
mfd: New AB8500 driver
Add a new driver to support the AB8500 Power Management chip, replacing the current AB4500. The new driver replaces the old one, instead of an incremental modification, because this is a substantial overhaul including: - Split of the driver into -core and -spi portions, to allow another interface layer to be added - Addition of interrupt support - Switch to MFD core API for handling subdevices - Simplification of the APIs to remove a redundant block parameter - Rename of the APIs and macros from ab4500_* to ab8500_* - Rename of the files from ab4500* to ab8500* - Change of the driver name from ab4500 to ab8500 Acked-by: Linus Walleij <linus.walleij@stericsson.com> Acked-by: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com> Signed-off-by: Rabin Vincent <rabin.vincent@stericsson.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
-rw-r--r--arch/arm/mach-ux500/board-mop500.c2
-rw-r--r--drivers/mfd/Kconfig9
-rw-r--r--drivers/mfd/Makefile2
-rw-r--r--drivers/mfd/ab4500-core.c209
-rw-r--r--drivers/mfd/ab8500-core.c444
-rw-r--r--drivers/mfd/ab8500-spi.c133
-rw-r--r--include/linux/mfd/ab4500.h262
-rw-r--r--include/linux/mfd/ab8500.h128
8 files changed, 712 insertions, 477 deletions
diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c
index 072196c57263..bb8d7b771817 100644
--- a/arch/arm/mach-ux500/board-mop500.c
+++ b/arch/arm/mach-ux500/board-mop500.c
@@ -50,7 +50,7 @@ struct pl022_config_chip ab4500_chip_info = {
50 50
51static struct spi_board_info u8500_spi_devices[] = { 51static struct spi_board_info u8500_spi_devices[] = {
52 { 52 {
53 .modalias = "ab4500", 53 .modalias = "ab8500",
54 .controller_data = &ab4500_chip_info, 54 .controller_data = &ab4500_chip_info,
55 .max_speed_hz = 12000000, 55 .max_speed_hz = 12000000,
56 .bus_num = 0, 56 .bus_num = 0,
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index b84b7078e909..9da0e504bbe9 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -420,11 +420,12 @@ config EZX_PCAP
420 This enables the PCAP ASIC present on EZX Phones. This is 420 This enables the PCAP ASIC present on EZX Phones. This is
421 needed for MMC, TouchScreen, Sound, USB, etc.. 421 needed for MMC, TouchScreen, Sound, USB, etc..
422 422
423config AB4500_CORE 423config AB8500_CORE
424 tristate "ST-Ericsson's AB4500 Mixed Signal Power management chip" 424 bool "ST-Ericsson AB8500 Mixed Signal Power Management chip"
425 depends on SPI 425 depends on SPI=y && GENERIC_HARDIRQS
426 select MFD_CORE
426 help 427 help
427 Select this option to enable access to AB4500 power management 428 Select this option to enable access to AB8500 power management
428 chip. This connects to U8500 on the SSP/SPI bus and exports 429 chip. This connects to U8500 on the SSP/SPI bus and exports
429 read/write functions for the devices to get access to this chip. 430 read/write functions for the devices to get access to this chip.
430 This chip embeds various other multimedia funtionalities as well. 431 This chip embeds various other multimedia funtionalities as well.
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index ca1517e948af..fb503e77dc60 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -64,8 +64,8 @@ obj-$(CONFIG_PCF50633_GPIO) += pcf50633-gpio.o
64obj-$(CONFIG_ABX500_CORE) += abx500-core.o 64obj-$(CONFIG_ABX500_CORE) += abx500-core.o
65obj-$(CONFIG_AB3100_CORE) += ab3100-core.o 65obj-$(CONFIG_AB3100_CORE) += ab3100-core.o
66obj-$(CONFIG_AB3100_OTP) += ab3100-otp.o 66obj-$(CONFIG_AB3100_OTP) += ab3100-otp.o
67obj-$(CONFIG_AB4500_CORE) += ab4500-core.o
68obj-$(CONFIG_AB3550_CORE) += ab3550-core.o 67obj-$(CONFIG_AB3550_CORE) += ab3550-core.o
68obj-$(CONFIG_AB8500_CORE) += ab8500-core.o ab8500-spi.o
69obj-$(CONFIG_MFD_TIMBERDALE) += timberdale.o 69obj-$(CONFIG_MFD_TIMBERDALE) += timberdale.o
70obj-$(CONFIG_PMIC_ADP5520) += adp5520.o 70obj-$(CONFIG_PMIC_ADP5520) += adp5520.o
71obj-$(CONFIG_LPC_SCH) += lpc_sch.o 71obj-$(CONFIG_LPC_SCH) += lpc_sch.o
diff --git a/drivers/mfd/ab4500-core.c b/drivers/mfd/ab4500-core.c
deleted file mode 100644
index c275daa3ab1a..000000000000
--- a/drivers/mfd/ab4500-core.c
+++ /dev/null
@@ -1,209 +0,0 @@
1/*
2 * Copyright (C) 2009 ST-Ericsson
3 *
4 * Author: Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com>
5 *
6 * This program is free software; you can redistribute it
7 * and/or modify it under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation.
9 *
10 * AB4500 is a companion power management chip used with U8500.
11 * On this platform, this is interfaced with SSP0 controller
12 * which is a ARM primecell pl022.
13 *
14 * At the moment the module just exports read/write features.
15 * Interrupt management to be added - TODO.
16 */
17#include <linux/kernel.h>
18#include <linux/slab.h>
19#include <linux/init.h>
20#include <linux/module.h>
21#include <linux/platform_device.h>
22#include <linux/spi/spi.h>
23#include <linux/mfd/ab4500.h>
24
25/* just required if probe fails, we need to
26 * unregister the device
27 */
28static struct spi_driver ab4500_driver;
29
30/*
31 * This funtion writes to any AB4500 registers using
32 * SPI protocol & before it writes it packs the data
33 * in the below 24 bit frame format
34 *
35 * *|------------------------------------|
36 * *| 23|22...18|17.......10|9|8|7......0|
37 * *| r/w bank adr data |
38 * * ------------------------------------
39 *
40 * This function shouldn't be called from interrupt
41 * context
42 */
43int ab4500_write(struct ab4500 *ab4500, unsigned char block,
44 unsigned long addr, unsigned char data)
45{
46 struct spi_transfer xfer;
47 struct spi_message msg;
48 int err;
49 unsigned long spi_data =
50 block << 18 | addr << 10 | data;
51
52 mutex_lock(&ab4500->lock);
53 ab4500->tx_buf[0] = spi_data;
54 ab4500->rx_buf[0] = 0;
55
56 xfer.tx_buf = ab4500->tx_buf;
57 xfer.rx_buf = NULL;
58 xfer.len = sizeof(unsigned long);
59
60 spi_message_init(&msg);
61 spi_message_add_tail(&xfer, &msg);
62
63 err = spi_sync(ab4500->spi, &msg);
64 mutex_unlock(&ab4500->lock);
65
66 return err;
67}
68EXPORT_SYMBOL(ab4500_write);
69
70int ab4500_read(struct ab4500 *ab4500, unsigned char block,
71 unsigned long addr)
72{
73 struct spi_transfer xfer;
74 struct spi_message msg;
75 unsigned long spi_data =
76 1 << 23 | block << 18 | addr << 10;
77
78 mutex_lock(&ab4500->lock);
79 ab4500->tx_buf[0] = spi_data;
80 ab4500->rx_buf[0] = 0;
81
82 xfer.tx_buf = ab4500->tx_buf;
83 xfer.rx_buf = ab4500->rx_buf;
84 xfer.len = sizeof(unsigned long);
85
86 spi_message_init(&msg);
87 spi_message_add_tail(&xfer, &msg);
88
89 spi_sync(ab4500->spi, &msg);
90 mutex_unlock(&ab4500->lock);
91
92 return ab4500->rx_buf[0];
93}
94EXPORT_SYMBOL(ab4500_read);
95
96/* ref: ab3100 core */
97#define AB4500_DEVICE(devname, devid) \
98static struct platform_device ab4500_##devname##_device = { \
99 .name = devid, \
100 .id = -1, \
101}
102
103/* list of childern devices of ab4500 - all are
104 * not populated here - TODO
105 */
106AB4500_DEVICE(charger, "ab4500-charger");
107AB4500_DEVICE(audio, "ab4500-audio");
108AB4500_DEVICE(usb, "ab4500-usb");
109AB4500_DEVICE(tvout, "ab4500-tvout");
110AB4500_DEVICE(sim, "ab4500-sim");
111AB4500_DEVICE(gpadc, "ab4500-gpadc");
112AB4500_DEVICE(clkmgt, "ab4500-clkmgt");
113AB4500_DEVICE(misc, "ab4500-misc");
114
115static struct platform_device *ab4500_platform_devs[] = {
116 &ab4500_charger_device,
117 &ab4500_audio_device,
118 &ab4500_usb_device,
119 &ab4500_tvout_device,
120 &ab4500_sim_device,
121 &ab4500_gpadc_device,
122 &ab4500_clkmgt_device,
123 &ab4500_misc_device,
124};
125
126static int __init ab4500_probe(struct spi_device *spi)
127{
128 struct ab4500 *ab4500;
129 unsigned char revision;
130 int err = 0;
131 int i;
132
133 ab4500 = kzalloc(sizeof *ab4500, GFP_KERNEL);
134 if (!ab4500) {
135 dev_err(&spi->dev, "could not allocate AB4500\n");
136 err = -ENOMEM;
137 goto not_detect;
138 }
139
140 ab4500->spi = spi;
141 spi_set_drvdata(spi, ab4500);
142
143 mutex_init(&ab4500->lock);
144
145 /* read the revision register */
146 revision = ab4500_read(ab4500, AB4500_MISC, AB4500_REV_REG);
147
148 /* revision id 0x0 is for early drop, 0x10 is for cut1.0 */
149 if (revision == 0x0 || revision == 0x10)
150 dev_info(&spi->dev, "Detected chip: %s, revision = %x\n",
151 ab4500_driver.driver.name, revision);
152 else {
153 dev_err(&spi->dev, "unknown chip: 0x%x\n", revision);
154 goto not_detect;
155 }
156
157 for (i = 0; i < ARRAY_SIZE(ab4500_platform_devs); i++) {
158 ab4500_platform_devs[i]->dev.parent =
159 &spi->dev;
160 platform_set_drvdata(ab4500_platform_devs[i], ab4500);
161 }
162
163 /* register the ab4500 platform devices */
164 platform_add_devices(ab4500_platform_devs,
165 ARRAY_SIZE(ab4500_platform_devs));
166
167 return err;
168
169 not_detect:
170 spi_unregister_driver(&ab4500_driver);
171 kfree(ab4500);
172 return err;
173}
174
175static int __devexit ab4500_remove(struct spi_device *spi)
176{
177 struct ab4500 *ab4500 =
178 spi_get_drvdata(spi);
179
180 kfree(ab4500);
181
182 return 0;
183}
184
185static struct spi_driver ab4500_driver = {
186 .driver = {
187 .name = "ab4500",
188 .owner = THIS_MODULE,
189 },
190 .probe = ab4500_probe,
191 .remove = __devexit_p(ab4500_remove)
192};
193
194static int __devinit ab4500_init(void)
195{
196 return spi_register_driver(&ab4500_driver);
197}
198
199static void __exit ab4500_exit(void)
200{
201 spi_unregister_driver(&ab4500_driver);
202}
203
204subsys_initcall(ab4500_init);
205module_exit(ab4500_exit);
206
207MODULE_AUTHOR("Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com");
208MODULE_DESCRIPTION("AB4500 core driver");
209MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
new file mode 100644
index 000000000000..f3d26fa9c34d
--- /dev/null
+++ b/drivers/mfd/ab8500-core.c
@@ -0,0 +1,444 @@
1/*
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>
7 */
8
9#include <linux/kernel.h>
10#include <linux/slab.h>
11#include <linux/init.h>
12#include <linux/irq.h>
13#include <linux/delay.h>
14#include <linux/interrupt.h>
15#include <linux/module.h>
16#include <linux/platform_device.h>
17#include <linux/mfd/core.h>
18#include <linux/mfd/ab8500.h>
19
20/*
21 * Interrupt register offsets
22 * Bank : 0x0E
23 */
24#define AB8500_IT_SOURCE1_REG 0x0E00
25#define AB8500_IT_SOURCE2_REG 0x0E01
26#define AB8500_IT_SOURCE3_REG 0x0E02
27#define AB8500_IT_SOURCE4_REG 0x0E03
28#define AB8500_IT_SOURCE5_REG 0x0E04
29#define AB8500_IT_SOURCE6_REG 0x0E05
30#define AB8500_IT_SOURCE7_REG 0x0E06
31#define AB8500_IT_SOURCE8_REG 0x0E07
32#define AB8500_IT_SOURCE19_REG 0x0E12
33#define AB8500_IT_SOURCE20_REG 0x0E13
34#define AB8500_IT_SOURCE21_REG 0x0E14
35#define AB8500_IT_SOURCE22_REG 0x0E15
36#define AB8500_IT_SOURCE23_REG 0x0E16
37#define AB8500_IT_SOURCE24_REG 0x0E17
38
39/*
40 * latch registers
41 */
42#define AB8500_IT_LATCH1_REG 0x0E20
43#define AB8500_IT_LATCH2_REG 0x0E21
44#define AB8500_IT_LATCH3_REG 0x0E22
45#define AB8500_IT_LATCH4_REG 0x0E23
46#define AB8500_IT_LATCH5_REG 0x0E24
47#define AB8500_IT_LATCH6_REG 0x0E25
48#define AB8500_IT_LATCH7_REG 0x0E26
49#define AB8500_IT_LATCH8_REG 0x0E27
50#define AB8500_IT_LATCH9_REG 0x0E28
51#define AB8500_IT_LATCH10_REG 0x0E29
52#define AB8500_IT_LATCH19_REG 0x0E32
53#define AB8500_IT_LATCH20_REG 0x0E33
54#define AB8500_IT_LATCH21_REG 0x0E34
55#define AB8500_IT_LATCH22_REG 0x0E35
56#define AB8500_IT_LATCH23_REG 0x0E36
57#define AB8500_IT_LATCH24_REG 0x0E37
58
59/*
60 * mask registers
61 */
62
63#define AB8500_IT_MASK1_REG 0x0E40
64#define AB8500_IT_MASK2_REG 0x0E41
65#define AB8500_IT_MASK3_REG 0x0E42
66#define AB8500_IT_MASK4_REG 0x0E43
67#define AB8500_IT_MASK5_REG 0x0E44
68#define AB8500_IT_MASK6_REG 0x0E45
69#define AB8500_IT_MASK7_REG 0x0E46
70#define AB8500_IT_MASK8_REG 0x0E47
71#define AB8500_IT_MASK9_REG 0x0E48
72#define AB8500_IT_MASK10_REG 0x0E49
73#define AB8500_IT_MASK11_REG 0x0E4A
74#define AB8500_IT_MASK12_REG 0x0E4B
75#define AB8500_IT_MASK13_REG 0x0E4C
76#define AB8500_IT_MASK14_REG 0x0E4D
77#define AB8500_IT_MASK15_REG 0x0E4E
78#define AB8500_IT_MASK16_REG 0x0E4F
79#define AB8500_IT_MASK17_REG 0x0E50
80#define AB8500_IT_MASK18_REG 0x0E51
81#define AB8500_IT_MASK19_REG 0x0E52
82#define AB8500_IT_MASK20_REG 0x0E53
83#define AB8500_IT_MASK21_REG 0x0E54
84#define AB8500_IT_MASK22_REG 0x0E55
85#define AB8500_IT_MASK23_REG 0x0E56
86#define AB8500_IT_MASK24_REG 0x0E57
87
88#define AB8500_REV_REG 0x1080
89
90/*
91 * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt
92 * numbers are indexed into this array with (num / 8).
93 *
94 * This is one off from the register names, i.e. AB8500_IT_MASK1_REG is at
95 * offset 0.
96 */
97static const int ab8500_irq_regoffset[AB8500_NUM_IRQ_REGS] = {
98 0, 1, 2, 3, 4, 6, 7, 8, 9, 18, 19, 20, 21,
99};
100
101static int __ab8500_write(struct ab8500 *ab8500, u16 addr, u8 data)
102{
103 int ret;
104
105 dev_vdbg(ab8500->dev, "wr: addr %#x <= %#x\n", addr, data);
106
107 ret = ab8500->write(ab8500, addr, data);
108 if (ret < 0)
109 dev_err(ab8500->dev, "failed to write reg %#x: %d\n",
110 addr, ret);
111
112 return ret;
113}
114
115/**
116 * ab8500_write() - write an AB8500 register
117 * @ab8500: device to write to
118 * @addr: address of the register
119 * @data: value to write
120 */
121int ab8500_write(struct ab8500 *ab8500, u16 addr, u8 data)
122{
123 int ret;
124
125 mutex_lock(&ab8500->lock);
126 ret = __ab8500_write(ab8500, addr, data);
127 mutex_unlock(&ab8500->lock);
128
129 return ret;
130}
131EXPORT_SYMBOL_GPL(ab8500_write);
132
133static int __ab8500_read(struct ab8500 *ab8500, u16 addr)
134{
135 int ret;
136
137 ret = ab8500->read(ab8500, addr);
138 if (ret < 0)
139 dev_err(ab8500->dev, "failed to read reg %#x: %d\n",
140 addr, ret);
141
142 dev_vdbg(ab8500->dev, "rd: addr %#x => data %#x\n", addr, ret);
143
144 return ret;
145}
146
147/**
148 * ab8500_read() - read an AB8500 register
149 * @ab8500: device to read from
150 * @addr: address of the register
151 */
152int ab8500_read(struct ab8500 *ab8500, u16 addr)
153{
154 int ret;
155
156 mutex_lock(&ab8500->lock);
157 ret = __ab8500_read(ab8500, addr);
158 mutex_unlock(&ab8500->lock);
159
160 return ret;
161}
162EXPORT_SYMBOL_GPL(ab8500_read);
163
164/**
165 * ab8500_set_bits() - set a bitfield in an AB8500 register
166 * @ab8500: device to read from
167 * @addr: address of the register
168 * @mask: mask of the bitfield to modify
169 * @data: value to set to the bitfield
170 */
171int ab8500_set_bits(struct ab8500 *ab8500, u16 addr, u8 mask, u8 data)
172{
173 int ret;
174
175 mutex_lock(&ab8500->lock);
176
177 ret = __ab8500_read(ab8500, addr);
178 if (ret < 0)
179 goto out;
180
181 ret &= ~mask;
182 ret |= data;
183
184 ret = __ab8500_write(ab8500, addr, ret);
185
186out:
187 mutex_unlock(&ab8500->lock);
188 return ret;
189}
190EXPORT_SYMBOL_GPL(ab8500_set_bits);
191
192static void ab8500_irq_lock(unsigned int irq)
193{
194 struct ab8500 *ab8500 = get_irq_chip_data(irq);
195
196 mutex_lock(&ab8500->irq_lock);
197}
198
199static void ab8500_irq_sync_unlock(unsigned int irq)
200{
201 struct ab8500 *ab8500 = get_irq_chip_data(irq);
202 int i;
203
204 for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) {
205 u8 old = ab8500->oldmask[i];
206 u8 new = ab8500->mask[i];
207 int reg;
208
209 if (new == old)
210 continue;
211
212 ab8500->oldmask[i] = new;
213
214 reg = AB8500_IT_MASK1_REG + ab8500_irq_regoffset[i];
215 ab8500_write(ab8500, reg, new);
216 }
217
218 mutex_unlock(&ab8500->irq_lock);
219}
220
221static void ab8500_irq_mask(unsigned int irq)
222{
223 struct ab8500 *ab8500 = get_irq_chip_data(irq);
224 int offset = irq - ab8500->irq_base;
225 int index = offset / 8;
226 int mask = 1 << (offset % 8);
227
228 ab8500->mask[index] |= mask;
229}
230
231static void ab8500_irq_unmask(unsigned int irq)
232{
233 struct ab8500 *ab8500 = get_irq_chip_data(irq);
234 int offset = irq - ab8500->irq_base;
235 int index = offset / 8;
236 int mask = 1 << (offset % 8);
237
238 ab8500->mask[index] &= ~mask;
239}
240
241static struct irq_chip ab8500_irq_chip = {
242 .name = "ab8500",
243 .bus_lock = ab8500_irq_lock,
244 .bus_sync_unlock = ab8500_irq_sync_unlock,
245 .mask = ab8500_irq_mask,
246 .unmask = ab8500_irq_unmask,
247};
248
249static irqreturn_t ab8500_irq(int irq, void *dev)
250{
251 struct ab8500 *ab8500 = dev;
252 int i;
253
254 dev_vdbg(ab8500->dev, "interrupt\n");
255
256 for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) {
257 int regoffset = ab8500_irq_regoffset[i];
258 int status;
259
260 status = ab8500_read(ab8500, AB8500_IT_LATCH1_REG + regoffset);
261 if (status <= 0)
262 continue;
263
264 do {
265 int bit = __ffs(status);
266 int line = i * 8 + bit;
267
268 handle_nested_irq(ab8500->irq_base + line);
269 status &= ~(1 << bit);
270 } while (status);
271 }
272
273 return IRQ_HANDLED;
274}
275
276static int ab8500_irq_init(struct ab8500 *ab8500)
277{
278 int base = ab8500->irq_base;
279 int irq;
280
281 for (irq = base; irq < base + AB8500_NR_IRQS; irq++) {
282 set_irq_chip_data(irq, ab8500);
283 set_irq_chip_and_handler(irq, &ab8500_irq_chip,
284 handle_simple_irq);
285 set_irq_nested_thread(irq, 1);
286#ifdef CONFIG_ARM
287 set_irq_flags(irq, IRQF_VALID);
288#else
289 set_irq_noprobe(irq);
290#endif
291 }
292
293 return 0;
294}
295
296static void ab8500_irq_remove(struct ab8500 *ab8500)
297{
298 int base = ab8500->irq_base;
299 int irq;
300
301 for (irq = base; irq < base + AB8500_NR_IRQS; irq++) {
302#ifdef CONFIG_ARM
303 set_irq_flags(irq, 0);
304#endif
305 set_irq_chip_and_handler(irq, NULL, NULL);
306 set_irq_chip_data(irq, NULL);
307 }
308}
309
310static struct resource ab8500_gpadc_resources[] = {
311 {
312 .name = "HW_CONV_END",
313 .start = AB8500_INT_GP_HW_ADC_CONV_END,
314 .end = AB8500_INT_GP_HW_ADC_CONV_END,
315 .flags = IORESOURCE_IRQ,
316 },
317 {
318 .name = "SW_CONV_END",
319 .start = AB8500_INT_GP_SW_ADC_CONV_END,
320 .end = AB8500_INT_GP_SW_ADC_CONV_END,
321 .flags = IORESOURCE_IRQ,
322 },
323};
324
325static struct resource ab8500_rtc_resources[] = {
326 {
327 .name = "60S",
328 .start = AB8500_INT_RTC_60S,
329 .end = AB8500_INT_RTC_60S,
330 .flags = IORESOURCE_IRQ,
331 },
332 {
333 .name = "ALARM",
334 .start = AB8500_INT_RTC_ALARM,
335 .end = AB8500_INT_RTC_ALARM,
336 .flags = IORESOURCE_IRQ,
337 },
338};
339
340static struct mfd_cell ab8500_devs[] = {
341 {
342 .name = "ab8500-gpadc",
343 .num_resources = ARRAY_SIZE(ab8500_gpadc_resources),
344 .resources = ab8500_gpadc_resources,
345 },
346 {
347 .name = "ab8500-rtc",
348 .num_resources = ARRAY_SIZE(ab8500_rtc_resources),
349 .resources = ab8500_rtc_resources,
350 },
351 { .name = "ab8500-charger", },
352 { .name = "ab8500-audio", },
353 { .name = "ab8500-usb", },
354 { .name = "ab8500-pwm", },
355};
356
357int __devinit ab8500_init(struct ab8500 *ab8500)
358{
359 struct ab8500_platform_data *plat = dev_get_platdata(ab8500->dev);
360 int ret;
361 int i;
362
363 if (plat)
364 ab8500->irq_base = plat->irq_base;
365
366 mutex_init(&ab8500->lock);
367 mutex_init(&ab8500->irq_lock);
368
369 ret = ab8500_read(ab8500, AB8500_REV_REG);
370 if (ret < 0)
371 return ret;
372
373 /*
374 * 0x0 - Early Drop
375 * 0x10 - Cut 1.0
376 * 0x11 - Cut 1.1
377 */
378 if (ret == 0x0 || ret == 0x10 || ret == 0x11) {
379 ab8500->revision = ret;
380 dev_info(ab8500->dev, "detected chip, revision: %#x\n", ret);
381 } else {
382 dev_err(ab8500->dev, "unknown chip, revision: %#x\n", ret);
383 return -EINVAL;
384 }
385
386 if (plat && plat->init)
387 plat->init(ab8500);
388
389 /* Clear and mask all interrupts */
390 for (i = 0; i < 10; i++) {
391 ab8500_read(ab8500, AB8500_IT_LATCH1_REG + i);
392 ab8500_write(ab8500, AB8500_IT_MASK1_REG + i, 0xff);
393 }
394
395 for (i = 18; i < 24; i++) {
396 ab8500_read(ab8500, AB8500_IT_LATCH1_REG + i);
397 ab8500_write(ab8500, AB8500_IT_MASK1_REG + i, 0xff);
398 }
399
400 for (i = 0; i < AB8500_NUM_IRQ_REGS; i++)
401 ab8500->mask[i] = ab8500->oldmask[i] = 0xff;
402
403 if (ab8500->irq_base) {
404 ret = ab8500_irq_init(ab8500);
405 if (ret)
406 return ret;
407
408 ret = request_threaded_irq(ab8500->irq, NULL, ab8500_irq,
409 IRQF_ONESHOT, "ab8500", ab8500);
410 if (ret)
411 goto out_removeirq;
412 }
413
414 ret = mfd_add_devices(ab8500->dev, -1, ab8500_devs,
415 ARRAY_SIZE(ab8500_devs), NULL,
416 ab8500->irq_base);
417 if (ret)
418 goto out_freeirq;
419
420 return ret;
421
422out_freeirq:
423 if (ab8500->irq_base) {
424 free_irq(ab8500->irq, ab8500);
425out_removeirq:
426 ab8500_irq_remove(ab8500);
427 }
428 return ret;
429}
430
431int __devexit ab8500_exit(struct ab8500 *ab8500)
432{
433 mfd_remove_devices(ab8500->dev);
434 if (ab8500->irq_base) {
435 free_irq(ab8500->irq, ab8500);
436 ab8500_irq_remove(ab8500);
437 }
438
439 return 0;
440}
441
442MODULE_AUTHOR("Srinidhi Kasagar, Rabin Vincent");
443MODULE_DESCRIPTION("AB8500 MFD core");
444MODULE_LICENSE("GPL v2");
diff --git a/drivers/mfd/ab8500-spi.c b/drivers/mfd/ab8500-spi.c
new file mode 100644
index 000000000000..b81d4f768ef6
--- /dev/null
+++ b/drivers/mfd/ab8500-spi.c
@@ -0,0 +1,133 @@
1/*
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 */
7
8#include <linux/kernel.h>
9#include <linux/slab.h>
10#include <linux/init.h>
11#include <linux/module.h>
12#include <linux/platform_device.h>
13#include <linux/spi/spi.h>
14#include <linux/mfd/ab8500.h>
15
16/*
17 * This funtion writes to any AB8500 registers using
18 * SPI protocol & before it writes it packs the data
19 * in the below 24 bit frame format
20 *
21 * *|------------------------------------|
22 * *| 23|22...18|17.......10|9|8|7......0|
23 * *| r/w bank adr data |
24 * * ------------------------------------
25 *
26 * This function shouldn't be called from interrupt
27 * context
28 */
29static int ab8500_spi_write(struct ab8500 *ab8500, u16 addr, u8 data)
30{
31 struct spi_device *spi = container_of(ab8500->dev, struct spi_device,
32 dev);
33 unsigned long spi_data = addr << 10 | data;
34 struct spi_transfer xfer;
35 struct spi_message msg;
36
37 ab8500->tx_buf[0] = spi_data;
38 ab8500->rx_buf[0] = 0;
39
40 xfer.tx_buf = ab8500->tx_buf;
41 xfer.rx_buf = NULL;
42 xfer.len = sizeof(unsigned long);
43
44 spi_message_init(&msg);
45 spi_message_add_tail(&xfer, &msg);
46
47 return spi_sync(spi, &msg);
48}
49
50static int ab8500_spi_read(struct ab8500 *ab8500, u16 addr)
51{
52 struct spi_device *spi = container_of(ab8500->dev, struct spi_device,
53 dev);
54 unsigned long spi_data = 1 << 23 | addr << 10;
55 struct spi_transfer xfer;
56 struct spi_message msg;
57 int ret;
58
59 ab8500->tx_buf[0] = spi_data;
60 ab8500->rx_buf[0] = 0;
61
62 xfer.tx_buf = ab8500->tx_buf;
63 xfer.rx_buf = ab8500->rx_buf;
64 xfer.len = sizeof(unsigned long);
65
66 spi_message_init(&msg);
67 spi_message_add_tail(&xfer, &msg);
68
69 ret = spi_sync(spi, &msg);
70 if (!ret)
71 ret = ab8500->rx_buf[0];
72
73 return ret;
74}
75
76static int __devinit ab8500_spi_probe(struct spi_device *spi)
77{
78 struct ab8500 *ab8500;
79 int ret;
80
81 ab8500 = kzalloc(sizeof *ab8500, GFP_KERNEL);
82 if (!ab8500)
83 return -ENOMEM;
84
85 ab8500->dev = &spi->dev;
86 ab8500->irq = spi->irq;
87
88 ab8500->read = ab8500_spi_read;
89 ab8500->write = ab8500_spi_write;
90
91 spi_set_drvdata(spi, ab8500);
92
93 ret = ab8500_init(ab8500);
94 if (ret)
95 kfree(ab8500);
96
97 return ret;
98}
99
100static int __devexit ab8500_spi_remove(struct spi_device *spi)
101{
102 struct ab8500 *ab8500 = spi_get_drvdata(spi);
103
104 ab8500_exit(ab8500);
105 kfree(ab8500);
106
107 return 0;
108}
109
110static struct spi_driver ab8500_spi_driver = {
111 .driver = {
112 .name = "ab8500",
113 .owner = THIS_MODULE,
114 },
115 .probe = ab8500_spi_probe,
116 .remove = __devexit_p(ab8500_spi_remove)
117};
118
119static int __init ab8500_spi_init(void)
120{
121 return spi_register_driver(&ab8500_spi_driver);
122}
123subsys_initcall(ab8500_spi_init);
124
125static void __exit ab8500_spi_exit(void)
126{
127 spi_unregister_driver(&ab8500_spi_driver);
128}
129module_exit(ab8500_spi_exit);
130
131MODULE_AUTHOR("Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com");
132MODULE_DESCRIPTION("AB8500 SPI");
133MODULE_LICENSE("GPL v2");
diff --git a/include/linux/mfd/ab4500.h b/include/linux/mfd/ab4500.h
deleted file mode 100644
index a42a7033ae53..000000000000
--- a/include/linux/mfd/ab4500.h
+++ /dev/null
@@ -1,262 +0,0 @@
1/*
2 * Copyright (C) 2009 ST-Ericsson
3 *
4 * Author: Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2, as
8 * published by the Free Software Foundation.
9 *
10 * AB4500 device core funtions, for client access
11 */
12#ifndef MFD_AB4500_H
13#define MFD_AB4500_H
14
15#include <linux/device.h>
16
17/*
18 * AB4500 bank addresses
19 */
20#define AB4500_SYS_CTRL1_BLOCK 0x1
21#define AB4500_SYS_CTRL2_BLOCK 0x2
22#define AB4500_REGU_CTRL1 0x3
23#define AB4500_REGU_CTRL2 0x4
24#define AB4500_USB 0x5
25#define AB4500_TVOUT 0x6
26#define AB4500_DBI 0x7
27#define AB4500_ECI_AV_ACC 0x8
28#define AB4500_RESERVED 0x9
29#define AB4500_GPADC 0xA
30#define AB4500_CHARGER 0xB
31#define AB4500_GAS_GAUGE 0xC
32#define AB4500_AUDIO 0xD
33#define AB4500_INTERRUPT 0xE
34#define AB4500_RTC 0xF
35#define AB4500_MISC 0x10
36#define AB4500_DEBUG 0x12
37#define AB4500_PROD_TEST 0x13
38#define AB4500_OTP_EMUL 0x15
39
40/*
41 * System control 1 register offsets.
42 * Bank = 0x01
43 */
44#define AB4500_TURNON_STAT_REG 0x0100
45#define AB4500_RESET_STAT_REG 0x0101
46#define AB4500_PONKEY1_PRESS_STAT_REG 0x0102
47
48#define AB4500_FSM_STAT1_REG 0x0140
49#define AB4500_FSM_STAT2_REG 0x0141
50#define AB4500_SYSCLK_REQ_STAT_REG 0x0142
51#define AB4500_USB_STAT1_REG 0x0143
52#define AB4500_USB_STAT2_REG 0x0144
53#define AB4500_STATUS_SPARE1_REG 0x0145
54#define AB4500_STATUS_SPARE2_REG 0x0146
55
56#define AB4500_CTRL1_REG 0x0180
57#define AB4500_CTRL2_REG 0x0181
58
59/*
60 * System control 2 register offsets.
61 * bank = 0x02
62 */
63#define AB4500_CTRL3_REG 0x0200
64#define AB4500_MAIN_WDOG_CTRL_REG 0x0201
65#define AB4500_MAIN_WDOG_TIMER_REG 0x0202
66#define AB4500_LOW_BAT_REG 0x0203
67#define AB4500_BATT_OK_REG 0x0204
68#define AB4500_SYSCLK_TIMER_REG 0x0205
69#define AB4500_SMPSCLK_CTRL_REG 0x0206
70#define AB4500_SMPSCLK_SEL1_REG 0x0207
71#define AB4500_SMPSCLK_SEL2_REG 0x0208
72#define AB4500_SMPSCLK_SEL3_REG 0x0209
73#define AB4500_SYSULPCLK_CONF_REG 0x020A
74#define AB4500_SYSULPCLK_CTRL1_REG 0x020B
75#define AB4500_SYSCLK_CTRL_REG 0x020C
76#define AB4500_SYSCLK_REQ1_VALID_REG 0x020D
77#define AB4500_SYSCLK_REQ_VALID_REG 0x020E
78#define AB4500_SYSCTRL_SPARE_REG 0x020F
79#define AB4500_PAD_CONF_REG 0x0210
80
81/*
82 * Regu control1 register offsets
83 * Bank = 0x03
84 */
85#define AB4500_REGU_SERIAL_CTRL1_REG 0x0300
86#define AB4500_REGU_SERIAL_CTRL2_REG 0x0301
87#define AB4500_REGU_SERIAL_CTRL3_REG 0x0302
88#define AB4500_REGU_REQ_CTRL1_REG 0x0303
89#define AB4500_REGU_REQ_CTRL2_REG 0x0304
90#define AB4500_REGU_REQ_CTRL3_REG 0x0305
91#define AB4500_REGU_REQ_CTRL4_REG 0x0306
92#define AB4500_REGU_MISC1_REG 0x0380
93#define AB4500_REGU_OTGSUPPLY_CTRL_REG 0x0381
94#define AB4500_REGU_VUSB_CTRL_REG 0x0382
95#define AB4500_REGU_VAUDIO_SUPPLY_REG 0x0383
96#define AB4500_REGU_CTRL1_SPARE_REG 0x0384
97
98/*
99 * Regu control2 Vmod register offsets
100 */
101#define AB4500_REGU_VMOD_REGU_REG 0x0440
102#define AB4500_REGU_VMOD_SEL1_REG 0x0441
103#define AB4500_REGU_VMOD_SEL2_REG 0x0442
104#define AB4500_REGU_CTRL_DISCH_REG 0x0443
105#define AB4500_REGU_CTRL_DISCH2_REG 0x0444
106
107/*
108 * USB/ULPI register offsets
109 * Bank : 0x5
110 */
111#define AB4500_USB_LINE_STAT_REG 0x0580
112#define AB4500_USB_LINE_CTRL1_REG 0x0581
113#define AB4500_USB_LINE_CTRL2_REG 0x0582
114#define AB4500_USB_LINE_CTRL3_REG 0x0583
115#define AB4500_USB_LINE_CTRL4_REG 0x0584
116#define AB4500_USB_LINE_CTRL5_REG 0x0585
117#define AB4500_USB_OTG_CTRL_REG 0x0587
118#define AB4500_USB_OTG_STAT_REG 0x0588
119#define AB4500_USB_OTG_STAT_REG 0x0588
120#define AB4500_USB_CTRL_SPARE_REG 0x0589
121#define AB4500_USB_PHY_CTRL_REG 0x058A
122
123/*
124 * TVOUT / CTRL register offsets
125 * Bank : 0x06
126 */
127#define AB4500_TVOUT_CTRL_REG 0x0680
128
129/*
130 * DBI register offsets
131 * Bank : 0x07
132 */
133#define AB4500_DBI_REG1_REG 0x0700
134#define AB4500_DBI_REG2_REG 0x0701
135
136/*
137 * ECI regsiter offsets
138 * Bank : 0x08
139 */
140#define AB4500_ECI_CTRL_REG 0x0800
141#define AB4500_ECI_HOOKLEVEL_REG 0x0801
142#define AB4500_ECI_DATAOUT_REG 0x0802
143#define AB4500_ECI_DATAIN_REG 0x0803
144
145/*
146 * AV Connector register offsets
147 * Bank : 0x08
148 */
149#define AB4500_AV_CONN_REG 0x0840
150
151/*
152 * Accessory detection register offsets
153 * Bank : 0x08
154 */
155#define AB4500_ACC_DET_DB1_REG 0x0880
156#define AB4500_ACC_DET_DB2_REG 0x0881
157
158/*
159 * GPADC register offsets
160 * Bank : 0x0A
161 */
162#define AB4500_GPADC_CTRL1_REG 0x0A00
163#define AB4500_GPADC_CTRL2_REG 0x0A01
164#define AB4500_GPADC_CTRL3_REG 0x0A02
165#define AB4500_GPADC_AUTO_TIMER_REG 0x0A03
166#define AB4500_GPADC_STAT_REG 0x0A04
167#define AB4500_GPADC_MANDATAL_REG 0x0A05
168#define AB4500_GPADC_MANDATAH_REG 0x0A06
169#define AB4500_GPADC_AUTODATAL_REG 0x0A07
170#define AB4500_GPADC_AUTODATAH_REG 0x0A08
171#define AB4500_GPADC_MUX_CTRL_REG 0x0A09
172
173/*
174 * Charger / status register offfsets
175 * Bank : 0x0B
176 */
177#define AB4500_CH_STATUS1_REG 0x0B00
178#define AB4500_CH_STATUS2_REG 0x0B01
179#define AB4500_CH_USBCH_STAT1_REG 0x0B02
180#define AB4500_CH_USBCH_STAT2_REG 0x0B03
181#define AB4500_CH_FSM_STAT_REG 0x0B04
182#define AB4500_CH_STAT_REG 0x0B05
183
184/*
185 * Charger / control register offfsets
186 * Bank : 0x0B
187 */
188#define AB4500_CH_VOLT_LVL_REG 0x0B40
189
190/*
191 * Charger / main control register offfsets
192 * Bank : 0x0B
193 */
194#define AB4500_MCH_CTRL1 0x0B80
195#define AB4500_MCH_CTRL2 0x0B81
196#define AB4500_MCH_IPT_CURLVL_REG 0x0B82
197#define AB4500_CH_WD_REG 0x0B83
198
199/*
200 * Charger / USB control register offsets
201 * Bank : 0x0B
202 */
203#define AB4500_USBCH_CTRL1_REG 0x0BC0
204#define AB4500_USBCH_CTRL2_REG 0x0BC1
205#define AB4500_USBCH_IPT_CRNTLVL_REG 0x0BC2
206
207/*
208 * RTC bank register offsets
209 * Bank : 0xF
210 */
211#define AB4500_RTC_SOFF_STAT_REG 0x0F00
212#define AB4500_RTC_CC_CONF_REG 0x0F01
213#define AB4500_RTC_READ_REQ_REG 0x0F02
214#define AB4500_RTC_WATCH_TSECMID_REG 0x0F03
215#define AB4500_RTC_WATCH_TSECHI_REG 0x0F04
216#define AB4500_RTC_WATCH_TMIN_LOW_REG 0x0F05
217#define AB4500_RTC_WATCH_TMIN_MID_REG 0x0F06
218#define AB4500_RTC_WATCH_TMIN_HI_REG 0x0F07
219#define AB4500_RTC_ALRM_MIN_LOW_REG 0x0F08
220#define AB4500_RTC_ALRM_MIN_MID_REG 0x0F09
221#define AB4500_RTC_ALRM_MIN_HI_REG 0x0F0A
222#define AB4500_RTC_STAT_REG 0x0F0B
223#define AB4500_RTC_BKUP_CHG_REG 0x0F0C
224#define AB4500_RTC_FORCE_BKUP_REG 0x0F0D
225#define AB4500_RTC_CALIB_REG 0x0F0E
226#define AB4500_RTC_SWITCH_STAT_REG 0x0F0F
227
228/*
229 * PWM Out generators
230 * Bank: 0x10
231 */
232#define AB4500_PWM_OUT_CTRL1_REG 0x1060
233#define AB4500_PWM_OUT_CTRL2_REG 0x1061
234#define AB4500_PWM_OUT_CTRL3_REG 0x1062
235#define AB4500_PWM_OUT_CTRL4_REG 0x1063
236#define AB4500_PWM_OUT_CTRL5_REG 0x1064
237#define AB4500_PWM_OUT_CTRL6_REG 0x1065
238#define AB4500_PWM_OUT_CTRL7_REG 0x1066
239
240#define AB4500_I2C_PAD_CTRL_REG 0x1067
241#define AB4500_REV_REG 0x1080
242
243/**
244 * struct ab4500
245 * @spi: spi device structure
246 * @tx_buf: transmit buffer
247 * @rx_buf: receive buffer
248 * @lock: sync primitive
249 */
250struct ab4500 {
251 struct spi_device *spi;
252 unsigned long tx_buf[4];
253 unsigned long rx_buf[4];
254 struct mutex lock;
255};
256
257int ab4500_write(struct ab4500 *ab4500, unsigned char block,
258 unsigned long addr, unsigned char data);
259int ab4500_read(struct ab4500 *ab4500, unsigned char block,
260 unsigned long addr);
261
262#endif /* MFD_AB4500_H */
diff --git a/include/linux/mfd/ab8500.h b/include/linux/mfd/ab8500.h
new file mode 100644
index 000000000000..b63ff3ba3351
--- /dev/null
+++ b/include/linux/mfd/ab8500.h
@@ -0,0 +1,128 @@
1/*
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 */
7#ifndef MFD_AB8500_H
8#define MFD_AB8500_H
9
10#include <linux/device.h>
11
12/*
13 * Interrupts
14 */
15
16#define AB8500_INT_MAIN_EXT_CH_NOT_OK 0
17#define AB8500_INT_UN_PLUG_TV_DET 1
18#define AB8500_INT_PLUG_TV_DET 2
19#define AB8500_INT_TEMP_WARM 3
20#define AB8500_INT_PON_KEY2DB_F 4
21#define AB8500_INT_PON_KEY2DB_R 5
22#define AB8500_INT_PON_KEY1DB_F 6
23#define AB8500_INT_PON_KEY1DB_R 7
24#define AB8500_INT_BATT_OVV 8
25#define AB8500_INT_MAIN_CH_UNPLUG_DET 10
26#define AB8500_INT_MAIN_CH_PLUG_DET 11
27#define AB8500_INT_USB_ID_DET_F 12
28#define AB8500_INT_USB_ID_DET_R 13
29#define AB8500_INT_VBUS_DET_F 14
30#define AB8500_INT_VBUS_DET_R 15
31#define AB8500_INT_VBUS_CH_DROP_END 16
32#define AB8500_INT_RTC_60S 17
33#define AB8500_INT_RTC_ALARM 18
34#define AB8500_INT_BAT_CTRL_INDB 20
35#define AB8500_INT_CH_WD_EXP 21
36#define AB8500_INT_VBUS_OVV 22
37#define AB8500_INT_MAIN_CH_DROP_END 23
38#define AB8500_INT_CCN_CONV_ACC 24
39#define AB8500_INT_INT_AUD 25
40#define AB8500_INT_CCEOC 26
41#define AB8500_INT_CC_INT_CALIB 27
42#define AB8500_INT_LOW_BAT_F 28
43#define AB8500_INT_LOW_BAT_R 29
44#define AB8500_INT_BUP_CHG_NOT_OK 30
45#define AB8500_INT_BUP_CHG_OK 31
46#define AB8500_INT_GP_HW_ADC_CONV_END 32
47#define AB8500_INT_ACC_DETECT_1DB_F 33
48#define AB8500_INT_ACC_DETECT_1DB_R 34
49#define AB8500_INT_ACC_DETECT_22DB_F 35
50#define AB8500_INT_ACC_DETECT_22DB_R 36
51#define AB8500_INT_ACC_DETECT_21DB_F 37
52#define AB8500_INT_ACC_DETECT_21DB_R 38
53#define AB8500_INT_GP_SW_ADC_CONV_END 39
54#define AB8500_INT_BTEMP_LOW 72
55#define AB8500_INT_BTEMP_LOW_MEDIUM 73
56#define AB8500_INT_BTEMP_MEDIUM_HIGH 74
57#define AB8500_INT_BTEMP_HIGH 75
58#define AB8500_INT_USB_CHARGER_NOT_OK 81
59#define AB8500_INT_ID_WAKEUP_R 82
60#define AB8500_INT_ID_DET_R1R 84
61#define AB8500_INT_ID_DET_R2R 85
62#define AB8500_INT_ID_DET_R3R 86
63#define AB8500_INT_ID_DET_R4R 87
64#define AB8500_INT_ID_WAKEUP_F 88
65#define AB8500_INT_ID_DET_R1F 90
66#define AB8500_INT_ID_DET_R2F 91
67#define AB8500_INT_ID_DET_R3F 92
68#define AB8500_INT_ID_DET_R4F 93
69#define AB8500_INT_USB_CHG_DET_DONE 94
70#define AB8500_INT_USB_CH_TH_PROT_F 96
71#define AB8500_INT_USB_CH_TH_PROP_R 97
72#define AB8500_INT_MAIN_CH_TH_PROP_F 98
73#define AB8500_INT_MAIN_CH_TH_PROT_R 99
74#define AB8500_INT_USB_CHARGER_NOT_OKF 103
75
76#define AB8500_NR_IRQS 104
77#define AB8500_NUM_IRQ_REGS 13
78
79/**
80 * struct ab8500 - ab8500 internal structure
81 * @dev: parent device
82 * @lock: read/write operations lock
83 * @irq_lock: genirq bus lock
84 * @revision: chip revision
85 * @irq: irq line
86 * @write: register write
87 * @read: register read
88 * @rx_buf: rx buf for SPI
89 * @tx_buf: tx buf for SPI
90 * @mask: cache of IRQ regs for bus lock
91 * @oldmask: cache of previous IRQ regs for bus lock
92 */
93struct ab8500 {
94 struct device *dev;
95 struct mutex lock;
96 struct mutex irq_lock;
97 int revision;
98 int irq_base;
99 int irq;
100
101 int (*write) (struct ab8500 *a8500, u16 addr, u8 data);
102 int (*read) (struct ab8500 *a8500, u16 addr);
103
104 unsigned long tx_buf[4];
105 unsigned long rx_buf[4];
106
107 u8 mask[AB8500_NUM_IRQ_REGS];
108 u8 oldmask[AB8500_NUM_IRQ_REGS];
109};
110
111/**
112 * struct ab8500_platform_data - AB8500 platform data
113 * @irq_base: start of AB8500 IRQs, AB8500_NR_IRQS will be used
114 * @init: board-specific initialization after detection of ab8500
115 */
116struct ab8500_platform_data {
117 int irq_base;
118 void (*init) (struct ab8500 *);
119};
120
121extern int ab8500_write(struct ab8500 *a8500, u16 addr, u8 data);
122extern int ab8500_read(struct ab8500 *a8500, u16 addr);
123extern int ab8500_set_bits(struct ab8500 *a8500, u16 addr, u8 mask, u8 data);
124
125extern int __devinit ab8500_init(struct ab8500 *ab8500);
126extern int __devexit ab8500_exit(struct ab8500 *ab8500);
127
128#endif /* MFD_AB8500_H */