blob: 9769811c643d2d822300db09951c33b456461d9d [file] [log] [blame]
Ying-Chun Liu (PaulLiu)5ad68bd2011-06-10 10:48:38 +08001/*
2 * Copyright(c) 2009 Dialog Semiconductor Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * da9052-spi.c: SPI SSC (Synchronous Serial Communication) driver for DA9052
10 */
11
Eric Miao20401bf2011-12-05 11:17:01 +080012#include <linux/module.h>
Ying-Chun Liu (PaulLiu)5ad68bd2011-06-10 10:48:38 +080013#include <linux/device.h>
14#include <linux/mfd/core.h>
15#include <linux/spi/spi.h>
16#include <linux/mfd/da9052/da9052.h>
17#include <linux/mfd/da9052/reg.h>
18
19
20struct da9052 *da9052_spi;
21
22#define SPI_CONNECTED 0
23
24static int da9052_spi_is_connected(void)
25{
26
27 struct da9052_ssc_msg msg;
28
29 /* printk("Entered da9052_spi_is_connected.............\n"); */
30
31 msg.addr = DA9052_INTERFACE_REG;
32
33 /* Test spi connectivity by performing read of the GPIO_0-1 register
34 and then verify the read value*/
35 if (0 != da9052_spi_read(da9052_spi, &msg)) {
36 printk(KERN_DEBUG "da9052_spi_is_connected - "\
37 "spi read failed.............\n");
38 return -1;
39 } else if (0x88 != msg.data) {
40 printk(KERN_DEBUG "da9052_spi_is_connected - " \
41 "spi read failed. Msg data =%x ..............\n",
42 msg.data);
43 return -1;
44 }
45
46 return 0;
47
48}
49
50static int da9052_spi_probe(struct spi_device *spi)
51{
52 /* printk("\n\tEntered da9052_spi_probe.....\n"); */
53
54 da9052_spi = kzalloc(sizeof(struct da9052), GFP_KERNEL);
55
56 if (!da9052_spi)
57 return -ENOMEM;
58
59
60 spi->mode = SPI_MODE_0 | SPI_CPOL;
61 spi->bits_per_word = 8;
62 spi_setup(spi);
63
64 da9052_spi->dev = &spi->dev;
65
66 da9052_spi->spi_dev = spi;
67
68 /*
69 * Allocate memory for RX/TX bufferes used in single register
70 * read/write
71 */
72 da9052_spi->spi_rx_buf = kmalloc(2, GFP_KERNEL | GFP_DMA);
73 if (!da9052_spi->spi_rx_buf)
74 return -ENOMEM;
75
76 da9052_spi->spi_tx_buf = kmalloc(2, GFP_KERNEL | GFP_DMA);
77 if (!da9052_spi->spi_tx_buf)
78 return -ENOMEM;
79
80 da9052_spi->spi_active_page = PAGECON_0;
81 da9052_spi->rw_pol = 1;
82
83
84 dev_set_drvdata(&spi->dev, da9052_spi);
85
86
87 /* Validate SPI connectivity */
88 if (SPI_CONNECTED == da9052_spi_is_connected()) {
89 /* SPI is connected */
90 da9052_spi->connecting_device = SPI;
91 if (0 != da9052_ssc_init(da9052_spi))
92 return -ENODEV;
93 } else {
94 return -ENODEV;
95 }
96
97 /* printk("Exiting da9052_spi_probe.....\n"); */
98
99 return 0;
100}
101
102static int da9052_spi_remove(struct spi_device *spi)
103{
104 struct da9052 *da9052 = dev_get_drvdata(&spi->dev);
105
106 printk("Entered da9052_spi_remove()\n");
107 if (SPI == da9052->connecting_device)
108 da9052_ssc_exit(da9052);
109 mfd_remove_devices(&spi->dev);
110 kfree(da9052->spi_rx_buf);
111 kfree(da9052->spi_tx_buf);
112 kfree(da9052);
113 return 0;
114}
115
116static struct spi_driver da9052_spi_driver = {
117 .driver = {
118 .name = DA9052_SSC_SPI_DEVICE_NAME,
119 .bus = &spi_bus_type,
120 .owner = THIS_MODULE,
121 },
122 .probe = da9052_spi_probe,
123 .remove = __devexit_p(da9052_spi_remove),
124};
125
126
127static int da9052_spi_set_page(struct da9052 *da9052, unsigned char page)
128{
129
130 struct da9052_ssc_msg sscmsg;
131 struct spi_message message;
132 struct spi_transfer xfer;
133 int ret = 0;
134
135 printk(KERN_DEBUG "Entered da9052_spi_set_page.....\n");
136 if ((page != PAGECON_0) && ((page != PAGECON_128)))
137 return INVALID_PAGE;
138
139 /* Current configuration is PAGE-0 and write request for PAGE-1 */
140 /* set register address */
141 sscmsg.addr = DA9052_PAGECON0_REG;
142 /* set value */
143 sscmsg.data = page;
144
145 /* Check value of R/W_POL bit of INTERFACE register */
146 if (!da9052->rw_pol) {
147 /* We need to set 0th bit for write operation */
148 sscmsg.addr = ((sscmsg.addr << 1) | RW_POL);
149 } else {
150 /* We need to reset 0th bit for write operation */
151 sscmsg.addr = (sscmsg.addr << 1);
152 }
153
154 /* SMDK-6410 host SPI driver specific stuff */
155
156 /* Build our spi message */
157 printk(KERN_DEBUG "da9052_spi_set_page - "\
158 "Calling spi_message_init.....\n");
159 spi_message_init(&message);
160 memset(&xfer, 0, sizeof(xfer));
161
162 xfer.len = 2;
163 xfer.tx_buf = da9052->spi_tx_buf;
164 xfer.rx_buf = da9052->spi_rx_buf;
165
166 da9052->spi_tx_buf[0] = sscmsg.addr;
167 da9052->spi_tx_buf[1] = sscmsg.data;
168
169 printk(KERN_DEBUG "da9052_spi_set_page - "\
170 "Calling spi_message_add_tail.....\n");
171 spi_message_add_tail(&xfer, &message);
172
173 /* Now, do the i/o */
174 printk(KERN_DEBUG "da9052_spi_set_page - Calling spi_sync.....\n");
175 ret = spi_sync(da9052->spi_dev, &message);
176
177 if (ret == 0) {
178 /* Active Page set successfully */
179 da9052->spi_active_page = page;
180 return 0;
181 } else {
182 /* Error in setting Active Page */
183 return ret;
184 }
185
186 return 0;
187}
188
189int da9052_spi_write(struct da9052 *da9052, struct da9052_ssc_msg *msg)
190{
191
192 struct spi_message message;
193 struct spi_transfer xfer;
194 int ret;
195
196 /*
197 * We need a seperate copy of da9052_ssc_msg so that caller's
198 * copy remains intact
199 */
200 struct da9052_ssc_msg sscmsg;
201
202 /* Copy callers data in to our local copy */
203 sscmsg.addr = msg->addr;
204 sscmsg.data = msg->data;
205
206 if ((sscmsg.addr > PAGE_0_END) &&
207 (da9052->spi_active_page == PAGECON_0)) {
208 /*
209 * Current configuration is PAGE-0 and write request
210 * for PAGE-1
211 */
212 da9052_spi_set_page(da9052, PAGECON_128);
213 /* Set register address accordindly */
214 sscmsg.addr = (sscmsg.addr - PAGE_1_START);
215 } else if ((sscmsg.addr < PAGE_1_START) &&
216 (da9052->spi_active_page == PAGECON_128)) {
217 /*
218 * Current configuration is PAGE-1 and write request
219 * for PAGE-0
220 */
221 da9052_spi_set_page(da9052, PAGECON_0);
222 } else if (sscmsg.addr > PAGE_0_END) {
223 /*
224 * Current configuration is PAGE-1 and write request
225 * for PAGE-1. Just need to adjust register address
226 */
227 sscmsg.addr = (sscmsg.addr - PAGE_1_START);
228 }
229
230 /* Check value of R/W_POL bit of INTERFACE register */
231 if (!da9052->rw_pol) {
232 /* We need to set 0th bit for write operation */
233 sscmsg.addr = ((sscmsg.addr << 1) | RW_POL);
234 } else {
235 /* We need to reset 0th bit for write operation */
236 sscmsg.addr = (sscmsg.addr << 1);
237 }
238
239 /* SMDK-6410 host SPI driver specific stuff */
240
241 /* Build our spi message */
242 spi_message_init(&message);
243 memset(&xfer, 0, sizeof(xfer));
244
245 xfer.len = 2;
246 xfer.tx_buf = da9052->spi_tx_buf;
247 xfer.rx_buf = da9052->spi_rx_buf;
248
249 da9052->spi_tx_buf[0] = sscmsg.addr;
250 da9052->spi_tx_buf[1] = sscmsg.data;
251
252 spi_message_add_tail(&xfer, &message);
253
254 /* Now, do the i/o */
255 ret = spi_sync(da9052->spi_dev, &message);
256
257 return ret;
258}
259
260int da9052_spi_write_many(struct da9052 *da9052, struct da9052_ssc_msg *sscmsg,
261 int msg_no)
262{
263 int cnt, ret = 0;
264
265 for (cnt = 0; cnt < msg_no; cnt++, sscmsg++) {
266 ret = da9052_ssc_write(da9052, sscmsg);
267 if (ret != 0) {
268 printk(KERN_DEBUG "Error in %s\n", __func__);
269 return -EIO;
270 }
271 }
272
273 return 0;
274}
275
276int da9052_spi_read(struct da9052 *da9052, struct da9052_ssc_msg *msg)
277{
278
279 struct spi_message message;
280 struct spi_transfer xfer;
281 int ret;
282
283 /*
284 * We need a seperate copy of da9052_ssc_msg so that
285 * caller's copy remains intact
286 */
287 struct da9052_ssc_msg sscmsg;
288
289
290 /* Copy callers data in to our local copy */
291 sscmsg.addr = msg->addr;
292 sscmsg.data = msg->data;
293
294 if ((sscmsg.addr > PAGE_0_END) &&
295 (da9052->spi_active_page == PAGECON_0)) {
296 /*
297 * Current configuration is PAGE-0 and
298 * read request for PAGE-1
299 */
300 printk(KERN_DEBUG "da9052_spi_read - if PAGECON_128.....\n");
301 da9052_spi_set_page(da9052, PAGECON_128);
302 /* Set register address accordindly */
303 sscmsg.addr = (sscmsg.addr - PAGE_1_START);
304 } else if ((sscmsg.addr < PAGE_1_START) &&
305 (da9052->spi_active_page == PAGECON_128)) {
306 /*
307 * Current configuration is PAGE-1 and
308 * write request for PAGE-0
309 */
310 printk(KERN_DEBUG "da9052_spi_read - if PAGECON_0.....\n");
311 da9052_spi_set_page(da9052, PAGECON_0);
312 } else if (sscmsg.addr > PAGE_0_END) {
313 /*
314 * Current configuration is PAGE-1 and write
315 * request for PAGE-1
316 * Just need to adjust register address
317 */
318 sscmsg.addr = (sscmsg.addr - PAGE_1_START);
319 }
320
321 /* Check value of R/W_POL bit of INTERFACE register */
322 if (da9052->rw_pol) {
323 /* We need to set 0th bit for read operation */
324 sscmsg.addr = ((sscmsg.addr << 1) | RW_POL);
325 } else {
326 /* We need to reset 0th bit for write operation */
327 sscmsg.addr = (sscmsg.addr << 1);
328 }
329
330 /* SMDK-6410 host SPI driver specific stuff */
331
332 /* Build our spi message */
333 spi_message_init(&message);
334 memset(&xfer, 0, sizeof(xfer));
335
336 xfer.len = 2;
337 xfer.tx_buf = da9052->spi_tx_buf;
338 xfer.rx_buf = da9052->spi_rx_buf;
339
340 da9052->spi_tx_buf[0] = sscmsg.addr;
341 da9052->spi_tx_buf[1] = 0xff;
342
343 da9052->spi_rx_buf[0] = 0;
344 da9052->spi_rx_buf[1] = 0;
345
346 spi_message_add_tail(&xfer, &message);
347
348 /* Now, do the i/o */
349 ret = spi_sync(da9052->spi_dev, &message);
350
351 if (ret == 0) {
352 /* Update read value in callers copy */
353 msg->data = da9052->spi_rx_buf[1];
354 return 0;
355 } else {
356 return ret;
357 }
358
359
360 return 0;
361}
362
363int da9052_spi_read_many(struct da9052 *da9052, struct da9052_ssc_msg *sscmsg,
364 int msg_no)
365{
366 int cnt, ret = 0;
367
368 for (cnt = 0; cnt < msg_no; cnt++, sscmsg++) {
369 ret = da9052_ssc_read(da9052, sscmsg);
370 if (ret != 0) {
371 printk(KERN_DEBUG "Error in %s\n", __func__);
372 return -EIO;
373 }
374 }
375
376 return 0;
377}
378
379static int __init da9052_spi_init(void)
380{
381 int ret = 0;
382 /*printk("Entered da9052_spi_init.....\n");*/
383 ret = spi_register_driver(&da9052_spi_driver);
384 if (ret != 0) {
385 printk(KERN_ERR "Unable to register %s\n",
386 DA9052_SSC_SPI_DEVICE_NAME);
387 return ret;
388 }
389 return 0;
390}
391module_init(da9052_spi_init);
392
393static void __exit da9052_spi_exit(void)
394{
395 spi_unregister_driver(&da9052_spi_driver);
396}
397
398module_exit(da9052_spi_exit);
399
400MODULE_AUTHOR("Dialog Semiconductor Ltd <dchen@diasemi.com>");
401MODULE_DESCRIPTION("SPI driver for Dialog DA9052 PMIC");
402MODULE_LICENSE("GPL v2");
403MODULE_ALIAS("platform:" DA9052_SSC_SPI_DEVICE_NAME);