aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAtsushi Nemoto <anemo@mba.ocn.ne.jp>2007-07-17 07:04:15 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-17 13:23:05 -0400
commitf2cac67dd36626128e06e79fc7ca95d544dcdc67 (patch)
tree689ff4133fa87e2bcbe532158b2fea7684e73a8d /drivers
parentccdc7bf925731ef37f0af95262d675b74544932f (diff)
spi_txx9 controller driver
This is a driver for SPI controller built into TXx9 MIPS SoCs. This driver is derived from arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c. Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/spi/Kconfig6
-rw-r--r--drivers/spi/Makefile1
-rw-r--r--drivers/spi/spi_txx9.c474
3 files changed, 481 insertions, 0 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 5ac498bbf2b6..b91571122daa 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -174,6 +174,12 @@ config SPI_S3C24XX_GPIO
174 the inbuilt hardware cannot provide the transfer mode, or 174 the inbuilt hardware cannot provide the transfer mode, or
175 where the board is using non hardware connected pins. 175 where the board is using non hardware connected pins.
176 176
177config SPI_TXX9
178 tristate "Toshiba TXx9 SPI controller"
179 depends on SPI_MASTER && GENERIC_GPIO && CPU_TX49XX
180 help
181 SPI driver for Toshiba TXx9 MIPS SoCs
182
177config SPI_XILINX 183config SPI_XILINX
178 tristate "Xilinx SPI controller" 184 tristate "Xilinx SPI controller"
179 depends on SPI_MASTER && XILINX_VIRTEX && EXPERIMENTAL 185 depends on SPI_MASTER && XILINX_VIRTEX && EXPERIMENTAL
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index be69667e0871..41fbac45c323 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_SPI_MPC52xx_PSC) += mpc52xx_psc_spi.o
25obj-$(CONFIG_SPI_MPC83xx) += spi_mpc83xx.o 25obj-$(CONFIG_SPI_MPC83xx) += spi_mpc83xx.o
26obj-$(CONFIG_SPI_S3C24XX_GPIO) += spi_s3c24xx_gpio.o 26obj-$(CONFIG_SPI_S3C24XX_GPIO) += spi_s3c24xx_gpio.o
27obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx.o 27obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx.o
28obj-$(CONFIG_SPI_TXX9) += spi_txx9.o
28obj-$(CONFIG_SPI_XILINX) += xilinx_spi.o 29obj-$(CONFIG_SPI_XILINX) += xilinx_spi.o
29# ... add above this line ... 30# ... add above this line ...
30 31
diff --git a/drivers/spi/spi_txx9.c b/drivers/spi/spi_txx9.c
new file mode 100644
index 000000000000..08e981c40646
--- /dev/null
+++ b/drivers/spi/spi_txx9.c
@@ -0,0 +1,474 @@
1/*
2 * spi_txx9.c - TXx9 SPI controller driver.
3 *
4 * Based on linux/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c
5 * Copyright (C) 2000-2001 Toshiba Corporation
6 *
7 * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the
8 * terms of the GNU General Public License version 2. This program is
9 * licensed "as is" without any warranty of any kind, whether express
10 * or implied.
11 *
12 * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
13 *
14 * Convert to generic SPI framework - Atsushi Nemoto (anemo@mba.ocn.ne.jp)
15 */
16#include <linux/init.h>
17#include <linux/delay.h>
18#include <linux/errno.h>
19#include <linux/interrupt.h>
20#include <linux/platform_device.h>
21#include <linux/sched.h>
22#include <linux/spinlock.h>
23#include <linux/workqueue.h>
24#include <linux/spi/spi.h>
25#include <linux/err.h>
26#include <linux/clk.h>
27#include <asm/gpio.h>
28
29
30#define SPI_FIFO_SIZE 4
31
32#define TXx9_SPMCR 0x00
33#define TXx9_SPCR0 0x04
34#define TXx9_SPCR1 0x08
35#define TXx9_SPFS 0x0c
36#define TXx9_SPSR 0x14
37#define TXx9_SPDR 0x18
38
39/* SPMCR : SPI Master Control */
40#define TXx9_SPMCR_OPMODE 0xc0
41#define TXx9_SPMCR_CONFIG 0x40
42#define TXx9_SPMCR_ACTIVE 0x80
43#define TXx9_SPMCR_SPSTP 0x02
44#define TXx9_SPMCR_BCLR 0x01
45
46/* SPCR0 : SPI Control 0 */
47#define TXx9_SPCR0_TXIFL_MASK 0xc000
48#define TXx9_SPCR0_RXIFL_MASK 0x3000
49#define TXx9_SPCR0_SIDIE 0x0800
50#define TXx9_SPCR0_SOEIE 0x0400
51#define TXx9_SPCR0_RBSIE 0x0200
52#define TXx9_SPCR0_TBSIE 0x0100
53#define TXx9_SPCR0_IFSPSE 0x0010
54#define TXx9_SPCR0_SBOS 0x0004
55#define TXx9_SPCR0_SPHA 0x0002
56#define TXx9_SPCR0_SPOL 0x0001
57
58/* SPSR : SPI Status */
59#define TXx9_SPSR_TBSI 0x8000
60#define TXx9_SPSR_RBSI 0x4000
61#define TXx9_SPSR_TBS_MASK 0x3800
62#define TXx9_SPSR_RBS_MASK 0x0700
63#define TXx9_SPSR_SPOE 0x0080
64#define TXx9_SPSR_IFSD 0x0008
65#define TXx9_SPSR_SIDLE 0x0004
66#define TXx9_SPSR_STRDY 0x0002
67#define TXx9_SPSR_SRRDY 0x0001
68
69
70struct txx9spi {
71 struct workqueue_struct *workqueue;
72 struct work_struct work;
73 spinlock_t lock; /* protect 'queue' */
74 struct list_head queue;
75 wait_queue_head_t waitq;
76 void __iomem *membase;
77 int irq;
78 int baseclk;
79 struct clk *clk;
80 u32 max_speed_hz, min_speed_hz;
81 int last_chipselect;
82 int last_chipselect_val;
83};
84
85static u32 txx9spi_rd(struct txx9spi *c, int reg)
86{
87 return __raw_readl(c->membase + reg);
88}
89static void txx9spi_wr(struct txx9spi *c, u32 val, int reg)
90{
91 __raw_writel(val, c->membase + reg);
92}
93
94static void txx9spi_cs_func(struct spi_device *spi, struct txx9spi *c,
95 int on, unsigned int cs_delay)
96{
97 int val = (spi->mode & SPI_CS_HIGH) ? on : !on;
98 if (on) {
99 /* deselect the chip with cs_change hint in last transfer */
100 if (c->last_chipselect >= 0)
101 gpio_set_value(c->last_chipselect,
102 !c->last_chipselect_val);
103 c->last_chipselect = spi->chip_select;
104 c->last_chipselect_val = val;
105 } else {
106 c->last_chipselect = -1;
107 ndelay(cs_delay); /* CS Hold Time */
108 }
109 gpio_set_value(spi->chip_select, val);
110 ndelay(cs_delay); /* CS Setup Time / CS Recovery Time */
111}
112
113/* the spi->mode bits understood by this driver: */
114#define MODEBITS (SPI_CS_HIGH|SPI_CPOL|SPI_CPHA)
115
116static int txx9spi_setup(struct spi_device *spi)
117{
118 struct txx9spi *c = spi_master_get_devdata(spi->master);
119 u8 bits_per_word;
120
121 if (spi->mode & ~MODEBITS)
122 return -EINVAL;
123
124 if (!spi->max_speed_hz
125 || spi->max_speed_hz > c->max_speed_hz
126 || spi->max_speed_hz < c->min_speed_hz)
127 return -EINVAL;
128
129 bits_per_word = spi->bits_per_word ? : 8;
130 if (bits_per_word != 8 && bits_per_word != 16)
131 return -EINVAL;
132
133 if (gpio_direction_output(spi->chip_select,
134 !(spi->mode & SPI_CS_HIGH))) {
135 dev_err(&spi->dev, "Cannot setup GPIO for chipselect.\n");
136 return -EINVAL;
137 }
138
139 /* deselect chip */
140 spin_lock(&c->lock);
141 txx9spi_cs_func(spi, c, 0, (NSEC_PER_SEC / 2) / spi->max_speed_hz);
142 spin_unlock(&c->lock);
143
144 return 0;
145}
146
147static irqreturn_t txx9spi_interrupt(int irq, void *dev_id)
148{
149 struct txx9spi *c = dev_id;
150
151 /* disable rx intr */
152 txx9spi_wr(c, txx9spi_rd(c, TXx9_SPCR0) & ~TXx9_SPCR0_RBSIE,
153 TXx9_SPCR0);
154 wake_up(&c->waitq);
155 return IRQ_HANDLED;
156}
157
158static void txx9spi_work_one(struct txx9spi *c, struct spi_message *m)
159{
160 struct spi_device *spi = m->spi;
161 struct spi_transfer *t;
162 unsigned int cs_delay;
163 unsigned int cs_change = 1;
164 int status = 0;
165 u32 mcr;
166 u32 prev_speed_hz = 0;
167 u8 prev_bits_per_word = 0;
168
169 /* CS setup/hold/recovery time in nsec */
170 cs_delay = 100 + (NSEC_PER_SEC / 2) / spi->max_speed_hz;
171
172 mcr = txx9spi_rd(c, TXx9_SPMCR);
173 if (unlikely((mcr & TXx9_SPMCR_OPMODE) == TXx9_SPMCR_ACTIVE)) {
174 dev_err(&spi->dev, "Bad mode.\n");
175 status = -EIO;
176 goto exit;
177 }
178 mcr &= ~(TXx9_SPMCR_OPMODE | TXx9_SPMCR_SPSTP | TXx9_SPMCR_BCLR);
179
180 /* enter config mode */
181 txx9spi_wr(c, mcr | TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR, TXx9_SPMCR);
182 txx9spi_wr(c, TXx9_SPCR0_SBOS
183 | ((spi->mode & SPI_CPOL) ? TXx9_SPCR0_SPOL : 0)
184 | ((spi->mode & SPI_CPHA) ? TXx9_SPCR0_SPHA : 0)
185 | 0x08,
186 TXx9_SPCR0);
187
188 list_for_each_entry (t, &m->transfers, transfer_list) {
189 const void *txbuf = t->tx_buf;
190 void *rxbuf = t->rx_buf;
191 u32 data;
192 unsigned int len = t->len;
193 unsigned int wsize;
194 u32 speed_hz = t->speed_hz ? : spi->max_speed_hz;
195 u8 bits_per_word = t->bits_per_word ? : spi->bits_per_word;
196
197 bits_per_word = bits_per_word ? : 8;
198 wsize = bits_per_word >> 3; /* in bytes */
199
200 if (prev_speed_hz != speed_hz
201 || prev_bits_per_word != bits_per_word) {
202 u32 n = (c->baseclk + speed_hz - 1) / speed_hz;
203 if (n < 1)
204 n = 1;
205 else if (n > 0xff)
206 n = 0xff;
207 /* enter config mode */
208 txx9spi_wr(c, mcr | TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR,
209 TXx9_SPMCR);
210 txx9spi_wr(c, (n << 8) | bits_per_word, TXx9_SPCR1);
211 /* enter active mode */
212 txx9spi_wr(c, mcr | TXx9_SPMCR_ACTIVE, TXx9_SPMCR);
213
214 prev_speed_hz = speed_hz;
215 prev_bits_per_word = bits_per_word;
216 }
217
218 if (cs_change)
219 txx9spi_cs_func(spi, c, 1, cs_delay);
220 cs_change = t->cs_change;
221 while (len) {
222 unsigned int count = SPI_FIFO_SIZE;
223 int i;
224 u32 cr0;
225
226 if (len < count * wsize)
227 count = len / wsize;
228 /* now tx must be idle... */
229 while (!(txx9spi_rd(c, TXx9_SPSR) & TXx9_SPSR_SIDLE))
230 cpu_relax();
231 cr0 = txx9spi_rd(c, TXx9_SPCR0);
232 cr0 &= ~TXx9_SPCR0_RXIFL_MASK;
233 cr0 |= (count - 1) << 12;
234 /* enable rx intr */
235 cr0 |= TXx9_SPCR0_RBSIE;
236 txx9spi_wr(c, cr0, TXx9_SPCR0);
237 /* send */
238 for (i = 0; i < count; i++) {
239 if (txbuf) {
240 data = (wsize == 1)
241 ? *(const u8 *)txbuf
242 : *(const u16 *)txbuf;
243 txx9spi_wr(c, data, TXx9_SPDR);
244 txbuf += wsize;
245 } else
246 txx9spi_wr(c, 0, TXx9_SPDR);
247 }
248 /* wait all rx data */
249 wait_event(c->waitq,
250 txx9spi_rd(c, TXx9_SPSR) & TXx9_SPSR_RBSI);
251 /* receive */
252 for (i = 0; i < count; i++) {
253 data = txx9spi_rd(c, TXx9_SPDR);
254 if (rxbuf) {
255 if (wsize == 1)
256 *(u8 *)rxbuf = data;
257 else
258 *(u16 *)rxbuf = data;
259 rxbuf += wsize;
260 }
261 }
262 len -= count * wsize;
263 }
264 m->actual_length += t->len;
265 if (t->delay_usecs)
266 udelay(t->delay_usecs);
267
268 if (!cs_change)
269 continue;
270 if (t->transfer_list.next == &m->transfers)
271 break;
272 /* sometimes a short mid-message deselect of the chip
273 * may be needed to terminate a mode or command
274 */
275 txx9spi_cs_func(spi, c, 0, cs_delay);
276 }
277
278exit:
279 m->status = status;
280 m->complete(m->context);
281
282 /* normally deactivate chipselect ... unless no error and
283 * cs_change has hinted that the next message will probably
284 * be for this chip too.
285 */
286 if (!(status == 0 && cs_change))
287 txx9spi_cs_func(spi, c, 0, cs_delay);
288
289 /* enter config mode */
290 txx9spi_wr(c, mcr | TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR, TXx9_SPMCR);
291}
292
293static void txx9spi_work(struct work_struct *work)
294{
295 struct txx9spi *c = container_of(work, struct txx9spi, work);
296 unsigned long flags;
297
298 spin_lock_irqsave(&c->lock, flags);
299 while (!list_empty(&c->queue)) {
300 struct spi_message *m;
301
302 m = container_of(c->queue.next, struct spi_message, queue);
303 list_del_init(&m->queue);
304 spin_unlock_irqrestore(&c->lock, flags);
305
306 txx9spi_work_one(c, m);
307
308 spin_lock_irqsave(&c->lock, flags);
309 }
310 spin_unlock_irqrestore(&c->lock, flags);
311}
312
313static int txx9spi_transfer(struct spi_device *spi, struct spi_message *m)
314{
315 struct spi_master *master = spi->master;
316 struct txx9spi *c = spi_master_get_devdata(master);
317 struct spi_transfer *t;
318 unsigned long flags;
319
320 m->actual_length = 0;
321
322 /* check each transfer's parameters */
323 list_for_each_entry (t, &m->transfers, transfer_list) {
324 u32 speed_hz = t->speed_hz ? : spi->max_speed_hz;
325 u8 bits_per_word = t->bits_per_word ? : spi->bits_per_word;
326
327 bits_per_word = bits_per_word ? : 8;
328 if (!t->tx_buf && !t->rx_buf && t->len)
329 return -EINVAL;
330 if (bits_per_word != 8 && bits_per_word != 16)
331 return -EINVAL;
332 if (t->len & ((bits_per_word >> 3) - 1))
333 return -EINVAL;
334 if (speed_hz < c->min_speed_hz || speed_hz > c->max_speed_hz)
335 return -EINVAL;
336 }
337
338 spin_lock_irqsave(&c->lock, flags);
339 list_add_tail(&m->queue, &c->queue);
340 queue_work(c->workqueue, &c->work);
341 spin_unlock_irqrestore(&c->lock, flags);
342
343 return 0;
344}
345
346static int __init txx9spi_probe(struct platform_device *dev)
347{
348 struct spi_master *master;
349 struct txx9spi *c;
350 struct resource *res;
351 int ret = -ENODEV;
352 u32 mcr;
353
354 master = spi_alloc_master(&dev->dev, sizeof(*c));
355 if (!master)
356 return ret;
357 c = spi_master_get_devdata(master);
358 c->irq = -1;
359 platform_set_drvdata(dev, master);
360
361 INIT_WORK(&c->work, txx9spi_work);
362 spin_lock_init(&c->lock);
363 INIT_LIST_HEAD(&c->queue);
364 init_waitqueue_head(&c->waitq);
365
366 c->clk = clk_get(&dev->dev, "spi-baseclk");
367 if (IS_ERR(c->clk)) {
368 ret = PTR_ERR(c->clk);
369 c->clk = NULL;
370 goto exit;
371 }
372 ret = clk_enable(c->clk);
373 if (ret) {
374 clk_put(c->clk);
375 c->clk = NULL;
376 goto exit;
377 }
378 c->baseclk = clk_get_rate(c->clk);
379 c->min_speed_hz = (c->baseclk + 0xff - 1) / 0xff;
380 c->max_speed_hz = c->baseclk;
381
382 res = platform_get_resource(dev, IORESOURCE_MEM, 0);
383 if (!res)
384 goto exit;
385 c->membase = ioremap(res->start, res->end - res->start + 1);
386 if (!c->membase)
387 goto exit;
388
389 /* enter config mode */
390 mcr = txx9spi_rd(c, TXx9_SPMCR);
391 mcr &= ~(TXx9_SPMCR_OPMODE | TXx9_SPMCR_SPSTP | TXx9_SPMCR_BCLR);
392 txx9spi_wr(c, mcr | TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR, TXx9_SPMCR);
393
394 c->irq = platform_get_irq(dev, 0);
395 if (c->irq < 0)
396 goto exit;
397 ret = request_irq(c->irq, txx9spi_interrupt, 0, dev->name, c);
398 if (ret) {
399 c->irq = -1;
400 goto exit;
401 }
402
403 c->workqueue = create_singlethread_workqueue(master->cdev.dev->bus_id);
404 if (!c->workqueue)
405 goto exit;
406 c->last_chipselect = -1;
407
408 dev_info(&dev->dev, "at %#llx, irq %d, %dMHz\n",
409 (unsigned long long)res->start, c->irq,
410 (c->baseclk + 500000) / 1000000);
411
412 master->bus_num = dev->id;
413 master->setup = txx9spi_setup;
414 master->transfer = txx9spi_transfer;
415 master->num_chipselect = (u16)UINT_MAX; /* any GPIO numbers */
416
417 ret = spi_register_master(master);
418 if (ret)
419 goto exit;
420 return 0;
421exit:
422 if (c->workqueue)
423 destroy_workqueue(c->workqueue);
424 if (c->irq >= 0)
425 free_irq(c->irq, c);
426 if (c->membase)
427 iounmap(c->membase);
428 if (c->clk) {
429 clk_disable(c->clk);
430 clk_put(c->clk);
431 }
432 platform_set_drvdata(dev, NULL);
433 spi_master_put(master);
434 return ret;
435}
436
437static int __exit txx9spi_remove(struct platform_device *dev)
438{
439 struct spi_master *master = spi_master_get(platform_get_drvdata(dev));
440 struct txx9spi *c = spi_master_get_devdata(master);
441
442 spi_unregister_master(master);
443 platform_set_drvdata(dev, NULL);
444 destroy_workqueue(c->workqueue);
445 free_irq(c->irq, c);
446 iounmap(c->membase);
447 clk_disable(c->clk);
448 clk_put(c->clk);
449 spi_master_put(master);
450 return 0;
451}
452
453static struct platform_driver txx9spi_driver = {
454 .remove = __exit_p(txx9spi_remove),
455 .driver = {
456 .name = "txx9spi",
457 .owner = THIS_MODULE,
458 },
459};
460
461static int __init txx9spi_init(void)
462{
463 return platform_driver_probe(&txx9spi_driver, txx9spi_probe);
464}
465subsys_initcall(txx9spi_init);
466
467static void __exit txx9spi_exit(void)
468{
469 platform_driver_unregister(&txx9spi_driver);
470}
471module_exit(txx9spi_exit);
472
473MODULE_DESCRIPTION("TXx9 SPI Driver");
474MODULE_LICENSE("GPL");