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/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>
24 /* just required if probe fails, we need to
25 * unregister the device
27 static struct spi_driver ab4500_driver
;
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
34 * *|------------------------------------|
35 * *| 23|22...18|17.......10|9|8|7......0|
36 * *| r/w bank adr data |
37 * * ------------------------------------
39 * This function shouldn't be called from interrupt
42 int ab4500_write(struct ab4500
*ab4500
, unsigned char block
,
43 unsigned long addr
, unsigned char data
)
45 struct spi_transfer xfer
;
46 struct spi_message msg
;
48 unsigned long spi_data
=
49 block
<< 18 | addr
<< 10 | data
;
51 mutex_lock(&ab4500
->lock
);
52 ab4500
->tx_buf
[0] = spi_data
;
53 ab4500
->rx_buf
[0] = 0;
55 xfer
.tx_buf
= ab4500
->tx_buf
;
57 xfer
.len
= sizeof(unsigned long);
59 spi_message_init(&msg
);
60 spi_message_add_tail(&xfer
, &msg
);
62 err
= spi_sync(ab4500
->spi
, &msg
);
63 mutex_unlock(&ab4500
->lock
);
67 EXPORT_SYMBOL(ab4500_write
);
69 int ab4500_read(struct ab4500
*ab4500
, unsigned char block
,
72 struct spi_transfer xfer
;
73 struct spi_message msg
;
74 unsigned long spi_data
=
75 1 << 23 | block
<< 18 | addr
<< 10;
77 mutex_lock(&ab4500
->lock
);
78 ab4500
->tx_buf
[0] = spi_data
;
79 ab4500
->rx_buf
[0] = 0;
81 xfer
.tx_buf
= ab4500
->tx_buf
;
82 xfer
.rx_buf
= ab4500
->rx_buf
;
83 xfer
.len
= sizeof(unsigned long);
85 spi_message_init(&msg
);
86 spi_message_add_tail(&xfer
, &msg
);
88 spi_sync(ab4500
->spi
, &msg
);
89 mutex_unlock(&ab4500
->lock
);
91 return ab4500
->rx_buf
[0];
93 EXPORT_SYMBOL(ab4500_read
);
95 /* ref: ab3100 core */
96 #define AB4500_DEVICE(devname, devid) \
97 static struct platform_device ab4500_##devname##_device = { \
102 /* list of childern devices of ab4500 - all are
103 * not populated here - TODO
105 AB4500_DEVICE(charger
, "ab4500-charger");
106 AB4500_DEVICE(audio
, "ab4500-audio");
107 AB4500_DEVICE(usb
, "ab4500-usb");
108 AB4500_DEVICE(tvout
, "ab4500-tvout");
109 AB4500_DEVICE(sim
, "ab4500-sim");
110 AB4500_DEVICE(gpadc
, "ab4500-gpadc");
111 AB4500_DEVICE(clkmgt
, "ab4500-clkmgt");
112 AB4500_DEVICE(misc
, "ab4500-misc");
114 static struct platform_device
*ab4500_platform_devs
[] = {
115 &ab4500_charger_device
,
116 &ab4500_audio_device
,
118 &ab4500_tvout_device
,
120 &ab4500_gpadc_device
,
121 &ab4500_clkmgt_device
,
125 static int __init
ab4500_probe(struct spi_device
*spi
)
127 struct ab4500
*ab4500
;
128 unsigned char revision
;
132 ab4500
= kzalloc(sizeof *ab4500
, GFP_KERNEL
);
134 dev_err(&spi
->dev
, "could not allocate AB4500\n");
140 spi_set_drvdata(spi
, ab4500
);
142 mutex_init(&ab4500
->lock
);
144 /* read the revision register */
145 revision
= ab4500_read(ab4500
, AB4500_MISC
, AB4500_REV_REG
);
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
);
152 dev_err(&spi
->dev
, "unknown chip: 0x%x\n", revision
);
156 for (i
= 0; i
< ARRAY_SIZE(ab4500_platform_devs
); i
++) {
157 ab4500_platform_devs
[i
]->dev
.parent
=
159 platform_set_drvdata(ab4500_platform_devs
[i
], ab4500
);
162 /* register the ab4500 platform devices */
163 platform_add_devices(ab4500_platform_devs
,
164 ARRAY_SIZE(ab4500_platform_devs
));
169 spi_unregister_driver(&ab4500_driver
);
174 static int __devexit
ab4500_remove(struct spi_device
*spi
)
176 struct ab4500
*ab4500
=
177 spi_get_drvdata(spi
);
184 static struct spi_driver ab4500_driver
= {
187 .owner
= THIS_MODULE
,
189 .probe
= ab4500_probe
,
190 .remove
= __devexit_p(ab4500_remove
)
193 static int __devinit
ab4500_init(void)
195 return spi_register_driver(&ab4500_driver
);
198 static void __exit
ab4500_exit(void)
200 spi_unregister_driver(&ab4500_driver
);
203 subsys_initcall(ab4500_init
);
204 module_exit(ab4500_exit
);
206 MODULE_AUTHOR("Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com");
207 MODULE_DESCRIPTION("AB4500 core driver");
208 MODULE_LICENSE("GPL");