2 * Copyright (C) 2009 ST-Ericsson
4 * Author: Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com>
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.
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.
14 * At the moment the module just exports read/write features.
15 * Interrupt management to be added - TODO.
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>
25 /* just required if probe fails, we need to
26 * unregister the device
28 static struct spi_driver ab4500_driver
;
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
35 * *|------------------------------------|
36 * *| 23|22...18|17.......10|9|8|7......0|
37 * *| r/w bank adr data |
38 * * ------------------------------------
40 * This function shouldn't be called from interrupt
43 int ab4500_write(struct ab4500
*ab4500
, unsigned char block
,
44 unsigned long addr
, unsigned char data
)
46 struct spi_transfer xfer
;
47 struct spi_message msg
;
49 unsigned long spi_data
=
50 block
<< 18 | addr
<< 10 | data
;
52 mutex_lock(&ab4500
->lock
);
53 ab4500
->tx_buf
[0] = spi_data
;
54 ab4500
->rx_buf
[0] = 0;
56 xfer
.tx_buf
= ab4500
->tx_buf
;
58 xfer
.len
= sizeof(unsigned long);
60 spi_message_init(&msg
);
61 spi_message_add_tail(&xfer
, &msg
);
63 err
= spi_sync(ab4500
->spi
, &msg
);
64 mutex_unlock(&ab4500
->lock
);
68 EXPORT_SYMBOL(ab4500_write
);
70 int ab4500_read(struct ab4500
*ab4500
, unsigned char block
,
73 struct spi_transfer xfer
;
74 struct spi_message msg
;
75 unsigned long spi_data
=
76 1 << 23 | block
<< 18 | addr
<< 10;
78 mutex_lock(&ab4500
->lock
);
79 ab4500
->tx_buf
[0] = spi_data
;
80 ab4500
->rx_buf
[0] = 0;
82 xfer
.tx_buf
= ab4500
->tx_buf
;
83 xfer
.rx_buf
= ab4500
->rx_buf
;
84 xfer
.len
= sizeof(unsigned long);
86 spi_message_init(&msg
);
87 spi_message_add_tail(&xfer
, &msg
);
89 spi_sync(ab4500
->spi
, &msg
);
90 mutex_unlock(&ab4500
->lock
);
92 return ab4500
->rx_buf
[0];
94 EXPORT_SYMBOL(ab4500_read
);
96 /* ref: ab3100 core */
97 #define AB4500_DEVICE(devname, devid) \
98 static struct platform_device ab4500_##devname##_device = { \
103 /* list of childern devices of ab4500 - all are
104 * not populated here - TODO
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");
115 static struct platform_device
*ab4500_platform_devs
[] = {
116 &ab4500_charger_device
,
117 &ab4500_audio_device
,
119 &ab4500_tvout_device
,
121 &ab4500_gpadc_device
,
122 &ab4500_clkmgt_device
,
126 static int __init
ab4500_probe(struct spi_device
*spi
)
128 struct ab4500
*ab4500
;
129 unsigned char revision
;
133 ab4500
= kzalloc(sizeof *ab4500
, GFP_KERNEL
);
135 dev_err(&spi
->dev
, "could not allocate AB4500\n");
141 spi_set_drvdata(spi
, ab4500
);
143 mutex_init(&ab4500
->lock
);
145 /* read the revision register */
146 revision
= ab4500_read(ab4500
, AB4500_MISC
, AB4500_REV_REG
);
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
);
153 dev_err(&spi
->dev
, "unknown chip: 0x%x\n", revision
);
157 for (i
= 0; i
< ARRAY_SIZE(ab4500_platform_devs
); i
++) {
158 ab4500_platform_devs
[i
]->dev
.parent
=
160 platform_set_drvdata(ab4500_platform_devs
[i
], ab4500
);
163 /* register the ab4500 platform devices */
164 platform_add_devices(ab4500_platform_devs
,
165 ARRAY_SIZE(ab4500_platform_devs
));
170 spi_unregister_driver(&ab4500_driver
);
175 static int __devexit
ab4500_remove(struct spi_device
*spi
)
177 struct ab4500
*ab4500
=
178 spi_get_drvdata(spi
);
185 static struct spi_driver ab4500_driver
= {
188 .owner
= THIS_MODULE
,
190 .probe
= ab4500_probe
,
191 .remove
= __devexit_p(ab4500_remove
)
194 static int __devinit
ab4500_init(void)
196 return spi_register_driver(&ab4500_driver
);
199 static void __exit
ab4500_exit(void)
201 spi_unregister_driver(&ab4500_driver
);
204 subsys_initcall(ab4500_init
);
205 module_exit(ab4500_exit
);
207 MODULE_AUTHOR("Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com");
208 MODULE_DESCRIPTION("AB4500 core driver");
209 MODULE_LICENSE("GPL");