2 * linux/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c
3 * Copyright (C) 2000-2001 Toshiba Corporation
5 * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the
6 * terms of the GNU General Public License version 2. This program is
7 * licensed "as is" without any warranty of any kind, whether express
10 * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
12 #include <linux/init.h>
13 #include <linux/delay.h>
14 #include <linux/errno.h>
15 #include <linux/interrupt.h>
16 #include <linux/module.h>
17 #include <linux/sched.h>
18 #include <linux/spinlock.h>
19 #include <linux/wait.h>
20 #include <asm/tx4938/spi.h>
21 #include <asm/tx4938/tx4938.h>
23 static int (*txx9_spi_cs_func)(int chipid, int on);
24 static DEFINE_SPINLOCK(txx9_spi_lock);
26 extern unsigned int txx9_gbus_clock;
28 #define SPI_FIFO_SIZE 4
30 void __init txx9_spi_init(unsigned long base, int (*cs_func)(int chipid, int on))
32 txx9_spi_cs_func = cs_func;
33 /* enter config mode */
34 tx4938_spiptr->mcr = TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR;
37 static DECLARE_WAIT_QUEUE_HEAD(txx9_spi_wait);
38 static void txx9_spi_interrupt(int irq, void *dev_id, struct pt_regs *regs)
41 tx4938_spiptr->cr0 &= ~TXx9_SPCR0_RBSIE;
42 wake_up(&txx9_spi_wait);
44 static struct irqaction txx9_spi_action = {
45 txx9_spi_interrupt, 0, 0, "spi", NULL, NULL,
48 void __init txx9_spi_irqinit(int irc_irq)
50 setup_irq(irc_irq, &txx9_spi_action);
53 int txx9_spi_io(int chipid, struct spi_dev_desc *desc,
54 unsigned char **inbufs, unsigned int *incounts,
55 unsigned char **outbufs, unsigned int *outcounts,
58 unsigned int incount, outcount;
59 unsigned char *inp, *outp;
63 spin_lock_irqsave(&txx9_spi_lock, flags);
64 if ((tx4938_spiptr->mcr & TXx9_SPMCR_OPMODE) == TXx9_SPMCR_ACTIVE) {
65 spin_unlock_irqrestore(&txx9_spi_lock, flags);
68 /* enter config mode */
69 tx4938_spiptr->mcr = TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR;
71 (desc->byteorder ? TXx9_SPCR0_SBOS : 0) |
72 (desc->polarity ? TXx9_SPCR0_SPOL : 0) |
73 (desc->phase ? TXx9_SPCR0_SPHA : 0) |
76 (((TXX9_IMCLK + desc->baud) / (2 * desc->baud) - 1) << 8) |
77 0x08 /* 8 bit only */;
78 /* enter active mode */
79 tx4938_spiptr->mcr = TXx9_SPMCR_ACTIVE;
80 spin_unlock_irqrestore(&txx9_spi_lock, flags);
83 if ((ret = txx9_spi_cs_func(chipid, 1)) < 0) {
84 spin_unlock_irqrestore(&txx9_spi_lock, flags);
90 inp = inbufs ? *inbufs : NULL;
91 outp = outbufs ? *outbufs : NULL;
99 incount = incounts ? *incounts++ : 0;
100 inp = (incount && inbufs) ? *inbufs++ : NULL;
103 outcount = outcounts ? *outcounts++ : 0;
104 outp = (outcount && outbufs) ? *outbufs++ : NULL;
108 count = SPI_FIFO_SIZE;
110 count = min(count, incount);
112 count = min(count, outcount);
114 /* now tx must be idle... */
115 while (!(tx4938_spiptr->sr & TXx9_SPSR_SIDLE))
119 (tx4938_spiptr->cr0 & ~TXx9_SPCR0_RXIFL_MASK) |
123 tx4938_spiptr->cr0 |= TXx9_SPCR0_RBSIE;
126 for (i = 0; i < count; i++)
127 tx4938_spiptr->dr = inp ? *inp++ : 0;
128 /* wait all rx data */
130 wait_event(txx9_spi_wait,
131 tx4938_spiptr->sr & TXx9_SPSR_SRRDY);
133 while (!(tx4938_spiptr->sr & TXx9_SPSR_RBSI))
137 for (i = 0; i < count; i++) {
138 data = tx4938_spiptr->dr;
150 txx9_spi_cs_func(chipid, 0);
153 spin_lock_irqsave(&txx9_spi_lock, flags);
154 /* enter config mode */
155 tx4938_spiptr->mcr = TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR;
156 spin_unlock_irqrestore(&txx9_spi_lock, flags);