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
);
39 static irqreturn_t
txx9_spi_interrupt(int irq
, void *dev_id
)
42 tx4938_spiptr
->cr0
&= ~TXx9_SPCR0_RBSIE
;
43 wake_up(&txx9_spi_wait
);
48 static struct irqaction txx9_spi_action
= {
49 .handler
= txx9_spi_interrupt
,
53 void __init
txx9_spi_irqinit(int irc_irq
)
55 setup_irq(irc_irq
, &txx9_spi_action
);
58 int txx9_spi_io(int chipid
, struct spi_dev_desc
*desc
,
59 unsigned char **inbufs
, unsigned int *incounts
,
60 unsigned char **outbufs
, unsigned int *outcounts
,
63 unsigned int incount
, outcount
;
64 unsigned char *inp
, *outp
;
68 spin_lock_irqsave(&txx9_spi_lock
, flags
);
69 if ((tx4938_spiptr
->mcr
& TXx9_SPMCR_OPMODE
) == TXx9_SPMCR_ACTIVE
) {
70 spin_unlock_irqrestore(&txx9_spi_lock
, flags
);
73 /* enter config mode */
74 tx4938_spiptr
->mcr
= TXx9_SPMCR_CONFIG
| TXx9_SPMCR_BCLR
;
76 (desc
->byteorder
? TXx9_SPCR0_SBOS
: 0) |
77 (desc
->polarity
? TXx9_SPCR0_SPOL
: 0) |
78 (desc
->phase
? TXx9_SPCR0_SPHA
: 0) |
81 (((TXX9_IMCLK
+ desc
->baud
) / (2 * desc
->baud
) - 1) << 8) |
82 0x08 /* 8 bit only */;
83 /* enter active mode */
84 tx4938_spiptr
->mcr
= TXx9_SPMCR_ACTIVE
;
85 spin_unlock_irqrestore(&txx9_spi_lock
, flags
);
88 if ((ret
= txx9_spi_cs_func(chipid
, 1)) < 0) {
89 spin_unlock_irqrestore(&txx9_spi_lock
, flags
);
95 inp
= inbufs
? *inbufs
: NULL
;
96 outp
= outbufs
? *outbufs
: NULL
;
104 incount
= incounts
? *incounts
++ : 0;
105 inp
= (incount
&& inbufs
) ? *inbufs
++ : NULL
;
108 outcount
= outcounts
? *outcounts
++ : 0;
109 outp
= (outcount
&& outbufs
) ? *outbufs
++ : NULL
;
113 count
= SPI_FIFO_SIZE
;
115 count
= min(count
, incount
);
117 count
= min(count
, outcount
);
119 /* now tx must be idle... */
120 while (!(tx4938_spiptr
->sr
& TXx9_SPSR_SIDLE
))
124 (tx4938_spiptr
->cr0
& ~TXx9_SPCR0_RXIFL_MASK
) |
128 tx4938_spiptr
->cr0
|= TXx9_SPCR0_RBSIE
;
131 for (i
= 0; i
< count
; i
++)
132 tx4938_spiptr
->dr
= inp
? *inp
++ : 0;
133 /* wait all rx data */
135 wait_event(txx9_spi_wait
,
136 tx4938_spiptr
->sr
& TXx9_SPSR_SRRDY
);
138 while (!(tx4938_spiptr
->sr
& TXx9_SPSR_RBSI
))
142 for (i
= 0; i
< count
; i
++) {
143 data
= tx4938_spiptr
->dr
;
155 txx9_spi_cs_func(chipid
, 0);
158 spin_lock_irqsave(&txx9_spi_lock
, flags
);
159 /* enter config mode */
160 tx4938_spiptr
->mcr
= TXx9_SPMCR_CONFIG
| TXx9_SPMCR_BCLR
;
161 spin_unlock_irqrestore(&txx9_spi_lock
, flags
);