2 * Copyright (C) ST-Ericsson AB 2010
3 * Contact: Sjur Brendeland / sjur.brandeland@stericsson.com
4 * Author: Daniel Martensson / Daniel.Martensson@stericsson.com
5 * License terms: GNU General Public License (GPL) version 2.
7 #include <linux/init.h>
8 #include <linux/module.h>
9 #include <linux/device.h>
10 #include <linux/platform_device.h>
11 #include <linux/string.h>
12 #include <linux/semaphore.h>
13 #include <linux/workqueue.h>
14 #include <linux/completion.h>
15 #include <linux/list.h>
16 #include <linux/interrupt.h>
17 #include <linux/dma-mapping.h>
18 #include <linux/delay.h>
19 #include <linux/sched.h>
20 #include <linux/debugfs.h>
21 #include <net/caif/caif_spi.h>
23 #ifndef CONFIG_CAIF_SPI_SYNC
24 #define SPI_DATA_POS 0
25 static inline int forward_to_spi_cmd(struct cfspi
*cfspi
)
27 return cfspi
->rx_cpck_len
;
30 #define SPI_DATA_POS SPI_CMD_SZ
31 static inline int forward_to_spi_cmd(struct cfspi
*cfspi
)
37 int spi_frm_align
= 2;
40 * SPI padding options.
41 * Warning: must be a base of 2 (& operation used) and can not be zero !
43 int spi_up_head_align
= 1 << 1;
44 int spi_up_tail_align
= 1 << 0;
45 int spi_down_head_align
= 1 << 2;
46 int spi_down_tail_align
= 1 << 1;
48 #ifdef CONFIG_DEBUG_FS
49 static inline void debugfs_store_prev(struct cfspi
*cfspi
)
51 /* Store previous command for debugging reasons.*/
52 cfspi
->pcmd
= cfspi
->cmd
;
53 /* Store previous transfer. */
54 cfspi
->tx_ppck_len
= cfspi
->tx_cpck_len
;
55 cfspi
->rx_ppck_len
= cfspi
->rx_cpck_len
;
58 static inline void debugfs_store_prev(struct cfspi
*cfspi
)
63 void cfspi_xfer(struct work_struct
*work
)
69 cfspi
= container_of(work
, struct cfspi
, work
);
71 /* Initialize state. */
72 cfspi
->cmd
= SPI_CMD_EOT
;
76 cfspi_dbg_state(cfspi
, CFSPI_STATE_WAITING
);
78 /* Wait for master talk or transmit event. */
79 wait_event_interruptible(cfspi
->wait
,
80 test_bit(SPI_XFER
, &cfspi
->state
) ||
81 test_bit(SPI_TERMINATE
, &cfspi
->state
));
83 if (test_bit(SPI_TERMINATE
, &cfspi
->state
))
87 /* Prefill buffers for easier debugging. */
88 memset(cfspi
->xfer
.va_tx
, 0xFF, SPI_DMA_BUF_LEN
);
89 memset(cfspi
->xfer
.va_rx
, 0xFF, SPI_DMA_BUF_LEN
);
90 #endif /* CFSPI_DBG_PREFILL */
92 cfspi_dbg_state(cfspi
, CFSPI_STATE_AWAKE
);
94 /* Check whether we have a committed frame. */
95 if (cfspi
->tx_cpck_len
) {
98 cfspi_dbg_state(cfspi
, CFSPI_STATE_FETCH_PKT
);
100 /* Copy committed SPI frames after the SPI indication. */
101 ptr
= (u8
*) cfspi
->xfer
.va_tx
;
103 len
= cfspi_xmitfrm(cfspi
, ptr
, cfspi
->tx_cpck_len
);
104 WARN_ON(len
!= cfspi
->tx_cpck_len
);
107 cfspi_dbg_state(cfspi
, CFSPI_STATE_GET_NEXT
);
109 /* Get length of next frame to commit. */
110 cfspi
->tx_npck_len
= cfspi_xmitlen(cfspi
);
112 WARN_ON(cfspi
->tx_npck_len
> SPI_DMA_BUF_LEN
);
115 * Add indication and length at the beginning of the frame,
116 * using little endian.
118 ptr
= (u8
*) cfspi
->xfer
.va_tx
;
119 *ptr
++ = SPI_CMD_IND
;
120 *ptr
++ = (SPI_CMD_IND
& 0xFF00) >> 8;
121 *ptr
++ = cfspi
->tx_npck_len
& 0x00FF;
122 *ptr
++ = (cfspi
->tx_npck_len
& 0xFF00) >> 8;
124 /* Calculate length of DMAs. */
125 cfspi
->xfer
.tx_dma_len
= cfspi
->tx_cpck_len
+ SPI_IND_SZ
;
126 cfspi
->xfer
.rx_dma_len
= cfspi
->rx_cpck_len
+ SPI_CMD_SZ
;
128 /* Add SPI TX frame alignment padding, if necessary. */
129 if (cfspi
->tx_cpck_len
&&
130 (cfspi
->xfer
.tx_dma_len
% spi_frm_align
)) {
132 cfspi
->xfer
.tx_dma_len
+= spi_frm_align
-
133 (cfspi
->xfer
.tx_dma_len
% spi_frm_align
);
136 /* Add SPI RX frame alignment padding, if necessary. */
137 if (cfspi
->rx_cpck_len
&&
138 (cfspi
->xfer
.rx_dma_len
% spi_frm_align
)) {
140 cfspi
->xfer
.rx_dma_len
+= spi_frm_align
-
141 (cfspi
->xfer
.rx_dma_len
% spi_frm_align
);
144 cfspi_dbg_state(cfspi
, CFSPI_STATE_INIT_XFER
);
146 /* Start transfer. */
147 ret
= cfspi
->dev
->init_xfer(&cfspi
->xfer
, cfspi
->dev
);
150 cfspi_dbg_state(cfspi
, CFSPI_STATE_WAIT_ACTIVE
);
153 * TODO: We might be able to make an assumption if this is the
154 * first loop. Make sure that minimum toggle time is respected.
156 udelay(MIN_TRANSITION_TIME_USEC
);
158 cfspi_dbg_state(cfspi
, CFSPI_STATE_SIG_ACTIVE
);
160 /* Signal that we are ready to receive data. */
161 cfspi
->dev
->sig_xfer(true, cfspi
->dev
);
163 cfspi_dbg_state(cfspi
, CFSPI_STATE_WAIT_XFER_DONE
);
165 /* Wait for transfer completion. */
166 wait_for_completion(&cfspi
->comp
);
168 cfspi_dbg_state(cfspi
, CFSPI_STATE_XFER_DONE
);
170 if (cfspi
->cmd
== SPI_CMD_EOT
) {
172 * Clear the master talk bit. A xfer is always at
175 clear_bit(SPI_SS_ON
, &cfspi
->state
);
178 cfspi_dbg_state(cfspi
, CFSPI_STATE_WAIT_INACTIVE
);
180 /* Make sure that the minimum toggle time is respected. */
181 if (SPI_XFER_TIME_USEC(cfspi
->xfer
.tx_dma_len
,
182 cfspi
->dev
->clk_mhz
) <
183 MIN_TRANSITION_TIME_USEC
) {
185 udelay(MIN_TRANSITION_TIME_USEC
-
187 (cfspi
->xfer
.tx_dma_len
, cfspi
->dev
->clk_mhz
));
190 cfspi_dbg_state(cfspi
, CFSPI_STATE_SIG_INACTIVE
);
192 /* De-assert transfer signal. */
193 cfspi
->dev
->sig_xfer(false, cfspi
->dev
);
195 /* Check whether we received a CAIF packet. */
196 if (cfspi
->rx_cpck_len
) {
199 cfspi_dbg_state(cfspi
, CFSPI_STATE_DELIVER_PKT
);
201 /* Parse SPI frame. */
202 ptr
= ((u8
*)(cfspi
->xfer
.va_rx
+ SPI_DATA_POS
));
204 len
= cfspi_rxfrm(cfspi
, ptr
, cfspi
->rx_cpck_len
);
205 WARN_ON(len
!= cfspi
->rx_cpck_len
);
208 /* Check the next SPI command and length. */
209 ptr
= (u8
*) cfspi
->xfer
.va_rx
;
211 ptr
+= forward_to_spi_cmd(cfspi
);
214 cfspi
->cmd
|= ((*ptr
++) << 8) & 0xFF00;
215 cfspi
->rx_npck_len
= *ptr
++;
216 cfspi
->rx_npck_len
|= ((*ptr
++) << 8) & 0xFF00;
218 WARN_ON(cfspi
->rx_npck_len
> SPI_DMA_BUF_LEN
);
219 WARN_ON(cfspi
->cmd
> SPI_CMD_EOT
);
221 debugfs_store_prev(cfspi
);
223 /* Check whether the master issued an EOT command. */
224 if (cfspi
->cmd
== SPI_CMD_EOT
) {
226 cfspi
->tx_cpck_len
= 0;
227 cfspi
->rx_cpck_len
= 0;
230 cfspi
->tx_cpck_len
= cfspi
->tx_npck_len
;
231 cfspi
->rx_cpck_len
= cfspi
->rx_npck_len
;
235 * Check whether we need to clear the xfer bit.
236 * Spin lock needed for packet insertion.
237 * Test and clear of different bits
240 spin_lock_irqsave(&cfspi
->lock
, flags
);
241 if (cfspi
->cmd
== SPI_CMD_EOT
&& !cfspi_xmitlen(cfspi
)
242 && !test_bit(SPI_SS_ON
, &cfspi
->state
))
243 clear_bit(SPI_XFER
, &cfspi
->state
);
245 spin_unlock_irqrestore(&cfspi
->lock
, flags
);
249 struct platform_driver cfspi_spi_driver
= {
250 .probe
= cfspi_spi_probe
,
251 .remove
= cfspi_spi_remove
,
253 .name
= "cfspi_sspi",
254 .owner
= THIS_MODULE
,