Commit 62579266cf9caca5b999560be2b5ceee42fc4d4d

Authored by Rabin Vincent
Committed by Samuel Ortiz
1 parent 75907a1153

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>

Showing 8 changed files with 712 additions and 477 deletions Side-by-side Diff

arch/arm/mach-ux500/board-mop500.c
... ... @@ -50,7 +50,7 @@
50 50  
51 51 static struct spi_board_info u8500_spi_devices[] = {
52 52 {
53   - .modalias = "ab4500",
  53 + .modalias = "ab8500",
54 54 .controller_data = &ab4500_chip_info,
55 55 .max_speed_hz = 12000000,
56 56 .bus_num = 0,
... ... @@ -420,11 +420,12 @@
420 420 This enables the PCAP ASIC present on EZX Phones. This is
421 421 needed for MMC, TouchScreen, Sound, USB, etc..
422 422  
423   -config AB4500_CORE
424   - tristate "ST-Ericsson's AB4500 Mixed Signal Power management chip"
425   - depends on SPI
  423 +config AB8500_CORE
  424 + bool "ST-Ericsson AB8500 Mixed Signal Power Management chip"
  425 + depends on SPI=y && GENERIC_HARDIRQS
  426 + select MFD_CORE
426 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 429 chip. This connects to U8500 on the SSP/SPI bus and exports
429 430 read/write functions for the devices to get access to this chip.
430 431 This chip embeds various other multimedia funtionalities as well.
drivers/mfd/Makefile
... ... @@ -64,8 +64,8 @@
64 64 obj-$(CONFIG_ABX500_CORE) += abx500-core.o
65 65 obj-$(CONFIG_AB3100_CORE) += ab3100-core.o
66 66 obj-$(CONFIG_AB3100_OTP) += ab3100-otp.o
67   -obj-$(CONFIG_AB4500_CORE) += ab4500-core.o
68 67 obj-$(CONFIG_AB3550_CORE) += ab3550-core.o
  68 +obj-$(CONFIG_AB8500_CORE) += ab8500-core.o ab8500-spi.o
69 69 obj-$(CONFIG_MFD_TIMBERDALE) += timberdale.o
70 70 obj-$(CONFIG_PMIC_ADP5520) += adp5520.o
71 71 obj-$(CONFIG_LPC_SCH) += lpc_sch.o
drivers/mfd/ab4500-core.c
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   - */
28   -static 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   - */
43   -int 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   -}
68   -EXPORT_SYMBOL(ab4500_write);
69   -
70   -int 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   -}
94   -EXPORT_SYMBOL(ab4500_read);
95   -
96   -/* ref: ab3100 core */
97   -#define AB4500_DEVICE(devname, devid) \
98   -static 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   - */
106   -AB4500_DEVICE(charger, "ab4500-charger");
107   -AB4500_DEVICE(audio, "ab4500-audio");
108   -AB4500_DEVICE(usb, "ab4500-usb");
109   -AB4500_DEVICE(tvout, "ab4500-tvout");
110   -AB4500_DEVICE(sim, "ab4500-sim");
111   -AB4500_DEVICE(gpadc, "ab4500-gpadc");
112   -AB4500_DEVICE(clkmgt, "ab4500-clkmgt");
113   -AB4500_DEVICE(misc, "ab4500-misc");
114   -
115   -static 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   -
126   -static 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   -
175   -static 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   -
185   -static 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   -
194   -static int __devinit ab4500_init(void)
195   -{
196   - return spi_register_driver(&ab4500_driver);
197   -}
198   -
199   -static void __exit ab4500_exit(void)
200   -{
201   - spi_unregister_driver(&ab4500_driver);
202   -}
203   -
204   -subsys_initcall(ab4500_init);
205   -module_exit(ab4500_exit);
206   -
207   -MODULE_AUTHOR("Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com");
208   -MODULE_DESCRIPTION("AB4500 core driver");
209   -MODULE_LICENSE("GPL");
drivers/mfd/ab8500-core.c
  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 + */
  97 +static 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 +
  101 +static 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 + */
  121 +int 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 +}
  131 +EXPORT_SYMBOL_GPL(ab8500_write);
  132 +
  133 +static 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 + */
  152 +int 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 +}
  162 +EXPORT_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 + */
  171 +int 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 +
  186 +out:
  187 + mutex_unlock(&ab8500->lock);
  188 + return ret;
  189 +}
  190 +EXPORT_SYMBOL_GPL(ab8500_set_bits);
  191 +
  192 +static 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 +
  199 +static 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 +
  221 +static 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 +
  231 +static 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 +
  241 +static 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 +
  249 +static 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 +
  276 +static 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 +
  296 +static 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 +
  310 +static 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 +
  325 +static 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 +
  340 +static 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 +
  357 +int __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 +
  422 +out_freeirq:
  423 + if (ab8500->irq_base) {
  424 + free_irq(ab8500->irq, ab8500);
  425 +out_removeirq:
  426 + ab8500_irq_remove(ab8500);
  427 + }
  428 + return ret;
  429 +}
  430 +
  431 +int __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 +
  442 +MODULE_AUTHOR("Srinidhi Kasagar, Rabin Vincent");
  443 +MODULE_DESCRIPTION("AB8500 MFD core");
  444 +MODULE_LICENSE("GPL v2");
drivers/mfd/ab8500-spi.c
  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 + */
  29 +static 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 +
  50 +static 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 +
  76 +static 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 +
  100 +static 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 +
  110 +static 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 +
  119 +static int __init ab8500_spi_init(void)
  120 +{
  121 + return spi_register_driver(&ab8500_spi_driver);
  122 +}
  123 +subsys_initcall(ab8500_spi_init);
  124 +
  125 +static void __exit ab8500_spi_exit(void)
  126 +{
  127 + spi_unregister_driver(&ab8500_spi_driver);
  128 +}
  129 +module_exit(ab8500_spi_exit);
  130 +
  131 +MODULE_AUTHOR("Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com");
  132 +MODULE_DESCRIPTION("AB8500 SPI");
  133 +MODULE_LICENSE("GPL v2");
include/linux/mfd/ab4500.h
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   - */
250   -struct ab4500 {
251   - struct spi_device *spi;
252   - unsigned long tx_buf[4];
253   - unsigned long rx_buf[4];
254   - struct mutex lock;
255   -};
256   -
257   -int ab4500_write(struct ab4500 *ab4500, unsigned char block,
258   - unsigned long addr, unsigned char data);
259   -int ab4500_read(struct ab4500 *ab4500, unsigned char block,
260   - unsigned long addr);
261   -
262   -#endif /* MFD_AB4500_H */
include/linux/mfd/ab8500.h
  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 + */
  93 +struct 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 + */
  116 +struct ab8500_platform_data {
  117 + int irq_base;
  118 + void (*init) (struct ab8500 *);
  119 +};
  120 +
  121 +extern int ab8500_write(struct ab8500 *a8500, u16 addr, u8 data);
  122 +extern int ab8500_read(struct ab8500 *a8500, u16 addr);
  123 +extern int ab8500_set_bits(struct ab8500 *a8500, u16 addr, u8 mask, u8 data);
  124 +
  125 +extern int __devinit ab8500_init(struct ab8500 *ab8500);
  126 +extern int __devexit ab8500_exit(struct ab8500 *ab8500);
  127 +
  128 +#endif /* MFD_AB8500_H */