Merge branch 'devicetree/next' of git://git.secretlab.ca/git/linux-2.6
[pandora-kernel.git] / drivers / spi / spi-ti-ssp.c
1 /*
2  * Sequencer Serial Port (SSP) based SPI master driver
3  *
4  * Copyright (C) 2010 Texas Instruments Inc
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 as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include <linux/kernel.h>
22 #include <linux/err.h>
23 #include <linux/completion.h>
24 #include <linux/delay.h>
25 #include <linux/platform_device.h>
26 #include <linux/spi/spi.h>
27 #include <linux/mfd/ti_ssp.h>
28
29 #define MODE_BITS       (SPI_CPHA | SPI_CPOL | SPI_CS_HIGH)
30
31 struct ti_ssp_spi {
32         struct spi_master               *master;
33         struct device                   *dev;
34         spinlock_t                      lock;
35         struct list_head                msg_queue;
36         struct completion               complete;
37         bool                            shutdown;
38         struct workqueue_struct         *workqueue;
39         struct work_struct              work;
40         u8                              mode, bpw;
41         int                             cs_active;
42         u32                             pc_en, pc_dis, pc_wr, pc_rd;
43         void                            (*select)(int cs);
44 };
45
46 static u32 ti_ssp_spi_rx(struct ti_ssp_spi *hw)
47 {
48         u32 ret;
49
50         ti_ssp_run(hw->dev, hw->pc_rd, 0, &ret);
51         return ret;
52 }
53
54 static void ti_ssp_spi_tx(struct ti_ssp_spi *hw, u32 data)
55 {
56         ti_ssp_run(hw->dev, hw->pc_wr, data << (32 - hw->bpw), NULL);
57 }
58
59 static int ti_ssp_spi_txrx(struct ti_ssp_spi *hw, struct spi_message *msg,
60                        struct spi_transfer *t)
61 {
62         int count;
63
64         if (hw->bpw <= 8) {
65                 u8              *rx = t->rx_buf;
66                 const u8        *tx = t->tx_buf;
67
68                 for (count = 0; count < t->len; count += 1) {
69                         if (t->tx_buf)
70                                 ti_ssp_spi_tx(hw, *tx++);
71                         if (t->rx_buf)
72                                 *rx++ = ti_ssp_spi_rx(hw);
73                 }
74         } else if (hw->bpw <= 16) {
75                 u16             *rx = t->rx_buf;
76                 const u16       *tx = t->tx_buf;
77
78                 for (count = 0; count < t->len; count += 2) {
79                         if (t->tx_buf)
80                                 ti_ssp_spi_tx(hw, *tx++);
81                         if (t->rx_buf)
82                                 *rx++ = ti_ssp_spi_rx(hw);
83                 }
84         } else {
85                 u32             *rx = t->rx_buf;
86                 const u32       *tx = t->tx_buf;
87
88                 for (count = 0; count < t->len; count += 4) {
89                         if (t->tx_buf)
90                                 ti_ssp_spi_tx(hw, *tx++);
91                         if (t->rx_buf)
92                                 *rx++ = ti_ssp_spi_rx(hw);
93                 }
94         }
95
96         msg->actual_length += count; /* bytes transferred */
97
98         dev_dbg(&msg->spi->dev, "xfer %s%s, %d bytes, %d bpw, count %d%s\n",
99                 t->tx_buf ? "tx" : "", t->rx_buf ? "rx" : "", t->len,
100                 hw->bpw, count, (count < t->len) ? " (under)" : "");
101
102         return (count < t->len) ? -EIO : 0; /* left over data */
103 }
104
105 static void ti_ssp_spi_chip_select(struct ti_ssp_spi *hw, int cs_active)
106 {
107         cs_active = !!cs_active;
108         if (cs_active == hw->cs_active)
109                 return;
110         ti_ssp_run(hw->dev, cs_active ? hw->pc_en : hw->pc_dis, 0, NULL);
111         hw->cs_active = cs_active;
112 }
113
114 #define __SHIFT_OUT(bits)       (SSP_OPCODE_SHIFT | SSP_OUT_MODE | \
115                                  cs_en | clk | SSP_COUNT((bits) * 2 - 1))
116 #define __SHIFT_IN(bits)        (SSP_OPCODE_SHIFT | SSP_IN_MODE  | \
117                                  cs_en | clk | SSP_COUNT((bits) * 2 - 1))
118
119 static int ti_ssp_spi_setup_transfer(struct ti_ssp_spi *hw, u8 bpw, u8 mode)
120 {
121         int error, idx = 0;
122         u32 seqram[16];
123         u32 cs_en, cs_dis, clk;
124         u32 topbits, botbits;
125
126         mode &= MODE_BITS;
127         if (mode == hw->mode && bpw == hw->bpw)
128                 return 0;
129
130         cs_en  = (mode & SPI_CS_HIGH) ? SSP_CS_HIGH : SSP_CS_LOW;
131         cs_dis = (mode & SPI_CS_HIGH) ? SSP_CS_LOW  : SSP_CS_HIGH;
132         clk    = (mode & SPI_CPOL)    ? SSP_CLK_HIGH : SSP_CLK_LOW;
133
134         /* Construct instructions */
135
136         /* Disable Chip Select */
137         hw->pc_dis = idx;
138         seqram[idx++] = SSP_OPCODE_DIRECT | SSP_OUT_MODE | cs_dis | clk;
139         seqram[idx++] = SSP_OPCODE_STOP   | SSP_OUT_MODE | cs_dis | clk;
140
141         /* Enable Chip Select */
142         hw->pc_en = idx;
143         seqram[idx++] = SSP_OPCODE_DIRECT | SSP_OUT_MODE | cs_en | clk;
144         seqram[idx++] = SSP_OPCODE_STOP   | SSP_OUT_MODE | cs_en | clk;
145
146         /* Reads and writes need to be split for bpw > 16 */
147         topbits = (bpw > 16) ? 16 : bpw;
148         botbits = bpw - topbits;
149
150         /* Write */
151         hw->pc_wr = idx;
152         seqram[idx++] = __SHIFT_OUT(topbits) | SSP_ADDR_REG;
153         if (botbits)
154                 seqram[idx++] = __SHIFT_OUT(botbits)  | SSP_DATA_REG;
155         seqram[idx++] = SSP_OPCODE_STOP | SSP_OUT_MODE | cs_en | clk;
156
157         /* Read */
158         hw->pc_rd = idx;
159         if (botbits)
160                 seqram[idx++] = __SHIFT_IN(botbits) | SSP_ADDR_REG;
161         seqram[idx++] = __SHIFT_IN(topbits) | SSP_DATA_REG;
162         seqram[idx++] = SSP_OPCODE_STOP | SSP_OUT_MODE | cs_en | clk;
163
164         error = ti_ssp_load(hw->dev, 0, seqram, idx);
165         if (error < 0)
166                 return error;
167
168         error = ti_ssp_set_mode(hw->dev, ((mode & SPI_CPHA) ?
169                                           0 : SSP_EARLY_DIN));
170         if (error < 0)
171                 return error;
172
173         hw->bpw = bpw;
174         hw->mode = mode;
175
176         return error;
177 }
178
179 static void ti_ssp_spi_work(struct work_struct *work)
180 {
181         struct ti_ssp_spi *hw = container_of(work, struct ti_ssp_spi, work);
182
183         spin_lock(&hw->lock);
184
185          while (!list_empty(&hw->msg_queue)) {
186                 struct spi_message      *m;
187                 struct spi_device       *spi;
188                 struct spi_transfer     *t = NULL;
189                 int                     status = 0;
190
191                 m = container_of(hw->msg_queue.next, struct spi_message,
192                                  queue);
193
194                 list_del_init(&m->queue);
195
196                 spin_unlock(&hw->lock);
197
198                 spi = m->spi;
199
200                 if (hw->select)
201                         hw->select(spi->chip_select);
202
203                 list_for_each_entry(t, &m->transfers, transfer_list) {
204                         int bpw = spi->bits_per_word;
205                         int xfer_status;
206
207                         if (t->bits_per_word)
208                                 bpw = t->bits_per_word;
209
210                         if (ti_ssp_spi_setup_transfer(hw, bpw, spi->mode) < 0)
211                                 break;
212
213                         ti_ssp_spi_chip_select(hw, 1);
214
215                         xfer_status = ti_ssp_spi_txrx(hw, m, t);
216                         if (xfer_status < 0)
217                                 status = xfer_status;
218
219                         if (t->delay_usecs)
220                                 udelay(t->delay_usecs);
221
222                         if (t->cs_change)
223                                 ti_ssp_spi_chip_select(hw, 0);
224                 }
225
226                 ti_ssp_spi_chip_select(hw, 0);
227                 m->status = status;
228                 m->complete(m->context);
229
230                 spin_lock(&hw->lock);
231         }
232
233         if (hw->shutdown)
234                 complete(&hw->complete);
235
236         spin_unlock(&hw->lock);
237 }
238
239 static int ti_ssp_spi_setup(struct spi_device *spi)
240 {
241         if (spi->bits_per_word > 32)
242                 return -EINVAL;
243
244         return 0;
245 }
246
247 static int ti_ssp_spi_transfer(struct spi_device *spi, struct spi_message *m)
248 {
249         struct ti_ssp_spi       *hw;
250         struct spi_transfer     *t;
251         int                     error = 0;
252
253         m->actual_length = 0;
254         m->status = -EINPROGRESS;
255
256         hw = spi_master_get_devdata(spi->master);
257
258         if (list_empty(&m->transfers) || !m->complete)
259                 return -EINVAL;
260
261         list_for_each_entry(t, &m->transfers, transfer_list) {
262                 if (t->len && !(t->rx_buf || t->tx_buf)) {
263                         dev_err(&spi->dev, "invalid xfer, no buffer\n");
264                         return -EINVAL;
265                 }
266
267                 if (t->len && t->rx_buf && t->tx_buf) {
268                         dev_err(&spi->dev, "invalid xfer, full duplex\n");
269                         return -EINVAL;
270                 }
271
272                 if (t->bits_per_word > 32) {
273                         dev_err(&spi->dev, "invalid xfer width %d\n",
274                                 t->bits_per_word);
275                         return -EINVAL;
276                 }
277         }
278
279         spin_lock(&hw->lock);
280         if (hw->shutdown) {
281                 error = -ESHUTDOWN;
282                 goto error_unlock;
283         }
284         list_add_tail(&m->queue, &hw->msg_queue);
285         queue_work(hw->workqueue, &hw->work);
286 error_unlock:
287         spin_unlock(&hw->lock);
288         return error;
289 }
290
291 static int __devinit ti_ssp_spi_probe(struct platform_device *pdev)
292 {
293         const struct ti_ssp_spi_data *pdata;
294         struct ti_ssp_spi *hw;
295         struct spi_master *master;
296         struct device *dev = &pdev->dev;
297         int error = 0;
298
299         pdata = dev->platform_data;
300         if (!pdata) {
301                 dev_err(dev, "platform data not found\n");
302                 return -EINVAL;
303         }
304
305         master = spi_alloc_master(dev, sizeof(struct ti_ssp_spi));
306         if (!master) {
307                 dev_err(dev, "cannot allocate SPI master\n");
308                 return -ENOMEM;
309         }
310
311         hw = spi_master_get_devdata(master);
312         platform_set_drvdata(pdev, hw);
313
314         hw->master = master;
315         hw->dev = dev;
316         hw->select = pdata->select;
317
318         spin_lock_init(&hw->lock);
319         init_completion(&hw->complete);
320         INIT_LIST_HEAD(&hw->msg_queue);
321         INIT_WORK(&hw->work, ti_ssp_spi_work);
322
323         hw->workqueue = create_singlethread_workqueue(dev_name(dev));
324         if (!hw->workqueue) {
325                 error = -ENOMEM;
326                 dev_err(dev, "work queue creation failed\n");
327                 goto error_wq;
328         }
329
330         error = ti_ssp_set_iosel(hw->dev, pdata->iosel);
331         if (error < 0) {
332                 dev_err(dev, "io setup failed\n");
333                 goto error_iosel;
334         }
335
336         master->bus_num         = pdev->id;
337         master->num_chipselect  = pdata->num_cs;
338         master->mode_bits       = MODE_BITS;
339         master->flags           = SPI_MASTER_HALF_DUPLEX;
340         master->setup           = ti_ssp_spi_setup;
341         master->transfer        = ti_ssp_spi_transfer;
342
343         error = spi_register_master(master);
344         if (error) {
345                 dev_err(dev, "master registration failed\n");
346                 goto error_reg;
347         }
348
349         return 0;
350
351 error_reg:
352 error_iosel:
353         destroy_workqueue(hw->workqueue);
354 error_wq:
355         spi_master_put(master);
356         return error;
357 }
358
359 static int __devexit ti_ssp_spi_remove(struct platform_device *pdev)
360 {
361         struct ti_ssp_spi *hw = platform_get_drvdata(pdev);
362         int error;
363
364         hw->shutdown = 1;
365         while (!list_empty(&hw->msg_queue)) {
366                 error = wait_for_completion_interruptible(&hw->complete);
367                 if (error < 0) {
368                         hw->shutdown = 0;
369                         return error;
370                 }
371         }
372         destroy_workqueue(hw->workqueue);
373         spi_unregister_master(hw->master);
374
375         return 0;
376 }
377
378 static struct platform_driver ti_ssp_spi_driver = {
379         .probe          = ti_ssp_spi_probe,
380         .remove         = __devexit_p(ti_ssp_spi_remove),
381         .driver         = {
382                 .name   = "ti-ssp-spi",
383                 .owner  = THIS_MODULE,
384         },
385 };
386
387 static int __init ti_ssp_spi_init(void)
388 {
389         return platform_driver_register(&ti_ssp_spi_driver);
390 }
391 module_init(ti_ssp_spi_init);
392
393 static void __exit ti_ssp_spi_exit(void)
394 {
395         platform_driver_unregister(&ti_ssp_spi_driver);
396 }
397 module_exit(ti_ssp_spi_exit);
398
399 MODULE_DESCRIPTION("SSP SPI Master");
400 MODULE_AUTHOR("Cyril Chemparathy");
401 MODULE_LICENSE("GPL");
402 MODULE_ALIAS("platform:ti-ssp-spi");