aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mfd/Kconfig10
-rw-r--r--drivers/mfd/Makefile1
-rw-r--r--drivers/mfd/ab4500-core.c207
-rw-r--r--include/linux/mfd/ab4500.h262
4 files changed, 480 insertions, 0 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 26a36f887357..2aea25ba7ba0 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -329,6 +329,16 @@ config MFD_88PM8607
329 individual components like voltage regulators, RTC and 329 individual components like voltage regulators, RTC and
330 battery-charger under the corresponding menus. 330 battery-charger under the corresponding menus.
331 331
332config AB4500_CORE
333 tristate "ST-Ericsson's AB4500 Mixed Signal Power management chip"
334 depends on SPI
335 default y
336 help
337 Select this option to enable access to AB4500 power management
338 chip. This connects to U8500 on the SSP/SPI bus and exports
339 read/write functions for the devices to get access to this chip.
340 This chip embeds various other multimedia funtionalities as well.
341
332endmenu 342endmenu
333 343
334menu "Multimedia Capabilities Port drivers" 344menu "Multimedia Capabilities Port drivers"
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 2596add427a2..1792b1ff8ffc 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -52,4 +52,5 @@ obj-$(CONFIG_PCF50633_ADC) += pcf50633-adc.o
52obj-$(CONFIG_PCF50633_GPIO) += pcf50633-gpio.o 52obj-$(CONFIG_PCF50633_GPIO) += pcf50633-gpio.o
53obj-$(CONFIG_AB3100_CORE) += ab3100-core.o 53obj-$(CONFIG_AB3100_CORE) += ab3100-core.o
54obj-$(CONFIG_AB3100_OTP) += ab3100-otp.o 54obj-$(CONFIG_AB3100_OTP) += ab3100-otp.o
55obj-$(CONFIG_AB4500_CORE) += ab4500-core.o
55obj-$(CONFIG_MFD_88PM8607) += 88pm8607.o 56obj-$(CONFIG_MFD_88PM8607) += 88pm8607.o
diff --git a/drivers/mfd/ab4500-core.c b/drivers/mfd/ab4500-core.c
new file mode 100644
index 000000000000..3ad91f7ee22b
--- /dev/null
+++ b/drivers/mfd/ab4500-core.c
@@ -0,0 +1,207 @@
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/init.h>
19#include <linux/module.h>
20#include <linux/platform_device.h>
21#include <linux/spi/spi.h>
22#include <linux/mfd/ab4500.h>
23
24/* just required if probe fails, we need to
25 * unregister the device
26 */
27static struct spi_driver ab4500_driver;
28
29/*
30 * This funtion writes to any AB4500 registers using
31 * SPI protocol & before it writes it packs the data
32 * in the below 24 bit frame format
33 *
34 * *|------------------------------------|
35 * *| 23|22...18|17.......10|9|8|7......0|
36 * *| r/w bank adr data |
37 * * ------------------------------------
38 *
39 * This function shouldn't be called from interrupt
40 * context
41 */
42int ab4500_write(struct ab4500 *ab4500, unsigned char block,
43 unsigned long addr, unsigned char data)
44{
45 struct spi_transfer xfer;
46 struct spi_message msg;
47 int err;
48 unsigned long spi_data =
49 block << 18 | addr << 10 | data;
50
51 mutex_lock(&ab4500->lock);
52 ab4500->tx_buf[0] = spi_data;
53 ab4500->rx_buf[0] = 0;
54
55 xfer.tx_buf = ab4500->tx_buf;
56 xfer.rx_buf = NULL;
57 xfer.len = sizeof(unsigned long);
58
59 spi_message_init(&msg);
60 spi_message_add_tail(&xfer, &msg);
61
62 err = spi_sync(ab4500->spi, &msg);
63 mutex_unlock(&ab4500->lock);
64
65 return err;
66}
67EXPORT_SYMBOL(ab4500_write);
68
69int ab4500_read(struct ab4500 *ab4500, unsigned char block,
70 unsigned long addr)
71{
72 struct spi_transfer xfer;
73 struct spi_message msg;
74 unsigned long spi_data =
75 1 << 23 | block << 18 | addr << 10;
76
77 mutex_lock(&ab4500->lock);
78 ab4500->tx_buf[0] = spi_data;
79 ab4500->rx_buf[0] = 0;
80
81 xfer.tx_buf = ab4500->tx_buf;
82 xfer.rx_buf = ab4500->rx_buf;
83 xfer.len = sizeof(unsigned long);
84
85 spi_message_init(&msg);
86 spi_message_add_tail(&xfer, &msg);
87
88 spi_sync(ab4500->spi, &msg);
89 mutex_unlock(&ab4500->lock);
90
91 return ab4500->rx_buf[0];
92}
93EXPORT_SYMBOL(ab4500_read);
94
95/* ref: ab3100 core */
96#define AB4500_DEVICE(devname, devid) \
97static struct platform_device ab4500_##devname##_device = { \
98 .name = devid, \
99 .id = -1, \
100}
101
102/* list of childern devices of ab4500 - all are
103 * not populated here - TODO
104 */
105AB4500_DEVICE(charger, "ab4500-charger");
106AB4500_DEVICE(audio, "ab4500-audio");
107AB4500_DEVICE(usb, "ab4500-usb");
108AB4500_DEVICE(tvout, "ab4500-tvout");
109AB4500_DEVICE(sim, "ab4500-sim");
110AB4500_DEVICE(gpadc, "ab4500-gpadc");
111AB4500_DEVICE(clkmgt, "ab4500-clkmgt");
112AB4500_DEVICE(misc, "ab4500-misc");
113
114static struct platform_device *ab4500_platform_devs[] = {
115 &ab4500_charger_device,
116 &ab4500_audio_device,
117 &ab4500_usb_device,
118 &ab4500_tvout_device,
119 &ab4500_sim_device,
120 &ab4500_gpadc_device,
121 &ab4500_clkmgt_device,
122 &ab4500_misc_device,
123};
124
125static int __init ab4500_probe(struct spi_device *spi)
126{
127 struct ab4500 *ab4500;
128 unsigned char revision;
129 int err = 0;
130 int i;
131
132 ab4500 = kzalloc(sizeof *ab4500, GFP_KERNEL);
133 if (!ab4500) {
134 dev_err(&spi->dev, "could not allocate AB4500\n");
135 err = -ENOMEM;
136 goto not_detect;
137 }
138
139 ab4500->spi = spi;
140 spi_set_drvdata(spi, ab4500);
141
142 mutex_init(&ab4500->lock);
143
144 /* read the revision register */
145 revision = ab4500_read(ab4500, AB4500_MISC, AB4500_REV_REG);
146
147 /* revision id 0x0 is for early drop, 0x10 is for cut1.0 */
148 if (revision == 0x0 || revision == 0x10)
149 dev_info(&spi->dev, "Detected chip: %s, revision = %x\n",
150 ab4500_driver.driver.name, revision);
151 else {
152 dev_err(&spi->dev, "unknown chip: 0x%x\n", revision);
153 goto not_detect;
154 }
155
156 for (i = 0; i < ARRAY_SIZE(ab4500_platform_devs); i++) {
157 ab4500_platform_devs[i]->dev.parent =
158 &spi->dev;
159 platform_set_drvdata(ab4500_platform_devs[i], ab4500);
160 }
161
162 /* register the ab4500 platform devices */
163 platform_add_devices(ab4500_platform_devs,
164 ARRAY_SIZE(ab4500_platform_devs));
165
166 return err;
167
168 not_detect:
169 spi_unregister_driver(&ab4500_driver);
170 kfree(ab4500);
171 return err;
172}
173
174static int __devexit ab4500_remove(struct spi_device *spi)
175{
176 struct ab4500 *ab4500 =
177 spi_get_drvdata(spi);
178
179 kfree(ab4500);
180
181 return 0;
182}
183
184static struct spi_driver ab4500_driver = {
185 .driver = {
186 .name = "ab4500",
187 .owner = THIS_MODULE,
188 },
189 .probe = ab4500_probe,
190 .remove = __devexit_p(ab4500_remove)
191};
192
193static int __devinit ab4500_init(void)
194{
195 return spi_register_driver(&ab4500_driver);
196}
197
198static void __exit ab4500_exit(void)
199{
200 spi_unregister_driver(&ab4500_driver);
201}
202
203subsys_initcall_sync(ab4500_init);
204
205MODULE_AUTHOR("Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com");
206MODULE_DESCRIPTION("AB4500 core driver");
207MODULE_LICENSE("GPL");
diff --git a/include/linux/mfd/ab4500.h b/include/linux/mfd/ab4500.h
new file mode 100644
index 000000000000..a42a7033ae53
--- /dev/null
+++ b/include/linux/mfd/ab4500.h
@@ -0,0 +1,262 @@
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 */