Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.7-rc4 256 lines 6.7 kB view raw
1/* 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. 6 */ 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> 22 23#ifndef CONFIG_CAIF_SPI_SYNC 24#define SPI_DATA_POS 0 25static inline int forward_to_spi_cmd(struct cfspi *cfspi) 26{ 27 return cfspi->rx_cpck_len; 28} 29#else 30#define SPI_DATA_POS SPI_CMD_SZ 31static inline int forward_to_spi_cmd(struct cfspi *cfspi) 32{ 33 return 0; 34} 35#endif 36 37int spi_frm_align = 2; 38 39/* 40 * SPI padding options. 41 * Warning: must be a base of 2 (& operation used) and can not be zero ! 42 */ 43int spi_up_head_align = 1 << 1; 44int spi_up_tail_align = 1 << 0; 45int spi_down_head_align = 1 << 2; 46int spi_down_tail_align = 1 << 1; 47 48#ifdef CONFIG_DEBUG_FS 49static inline void debugfs_store_prev(struct cfspi *cfspi) 50{ 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; 56} 57#else 58static inline void debugfs_store_prev(struct cfspi *cfspi) 59{ 60} 61#endif 62 63void cfspi_xfer(struct work_struct *work) 64{ 65 struct cfspi *cfspi; 66 u8 *ptr = NULL; 67 unsigned long flags; 68 int ret; 69 cfspi = container_of(work, struct cfspi, work); 70 71 /* Initialize state. */ 72 cfspi->cmd = SPI_CMD_EOT; 73 74 for (;;) { 75 76 cfspi_dbg_state(cfspi, CFSPI_STATE_WAITING); 77 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)); 82 83 if (test_bit(SPI_TERMINATE, &cfspi->state)) 84 return; 85 86#if CFSPI_DBG_PREFILL 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 */ 91 92 cfspi_dbg_state(cfspi, CFSPI_STATE_AWAKE); 93 94 /* Check whether we have a committed frame. */ 95 if (cfspi->tx_cpck_len) { 96 int len; 97 98 cfspi_dbg_state(cfspi, CFSPI_STATE_FETCH_PKT); 99 100 /* Copy committed SPI frames after the SPI indication. */ 101 ptr = (u8 *) cfspi->xfer.va_tx; 102 ptr += SPI_IND_SZ; 103 len = cfspi_xmitfrm(cfspi, ptr, cfspi->tx_cpck_len); 104 WARN_ON(len != cfspi->tx_cpck_len); 105 } 106 107 cfspi_dbg_state(cfspi, CFSPI_STATE_GET_NEXT); 108 109 /* Get length of next frame to commit. */ 110 cfspi->tx_npck_len = cfspi_xmitlen(cfspi); 111 112 WARN_ON(cfspi->tx_npck_len > SPI_DMA_BUF_LEN); 113 114 /* 115 * Add indication and length at the beginning of the frame, 116 * using little endian. 117 */ 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; 123 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; 127 128 /* Add SPI TX frame alignment padding, if necessary. */ 129 if (cfspi->tx_cpck_len && 130 (cfspi->xfer.tx_dma_len % spi_frm_align)) { 131 132 cfspi->xfer.tx_dma_len += spi_frm_align - 133 (cfspi->xfer.tx_dma_len % spi_frm_align); 134 } 135 136 /* Add SPI RX frame alignment padding, if necessary. */ 137 if (cfspi->rx_cpck_len && 138 (cfspi->xfer.rx_dma_len % spi_frm_align)) { 139 140 cfspi->xfer.rx_dma_len += spi_frm_align - 141 (cfspi->xfer.rx_dma_len % spi_frm_align); 142 } 143 144 cfspi_dbg_state(cfspi, CFSPI_STATE_INIT_XFER); 145 146 /* Start transfer. */ 147 ret = cfspi->dev->init_xfer(&cfspi->xfer, cfspi->dev); 148 WARN_ON(ret); 149 150 cfspi_dbg_state(cfspi, CFSPI_STATE_WAIT_ACTIVE); 151 152 /* 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. 155 */ 156 udelay(MIN_TRANSITION_TIME_USEC); 157 158 cfspi_dbg_state(cfspi, CFSPI_STATE_SIG_ACTIVE); 159 160 /* Signal that we are ready to receive data. */ 161 cfspi->dev->sig_xfer(true, cfspi->dev); 162 163 cfspi_dbg_state(cfspi, CFSPI_STATE_WAIT_XFER_DONE); 164 165 /* Wait for transfer completion. */ 166 wait_for_completion(&cfspi->comp); 167 168 cfspi_dbg_state(cfspi, CFSPI_STATE_XFER_DONE); 169 170 if (cfspi->cmd == SPI_CMD_EOT) { 171 /* 172 * Clear the master talk bit. A xfer is always at 173 * least two bursts. 174 */ 175 clear_bit(SPI_SS_ON, &cfspi->state); 176 } 177 178 cfspi_dbg_state(cfspi, CFSPI_STATE_WAIT_INACTIVE); 179 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) { 184 185 udelay(MIN_TRANSITION_TIME_USEC - 186 SPI_XFER_TIME_USEC 187 (cfspi->xfer.tx_dma_len, cfspi->dev->clk_mhz)); 188 } 189 190 cfspi_dbg_state(cfspi, CFSPI_STATE_SIG_INACTIVE); 191 192 /* De-assert transfer signal. */ 193 cfspi->dev->sig_xfer(false, cfspi->dev); 194 195 /* Check whether we received a CAIF packet. */ 196 if (cfspi->rx_cpck_len) { 197 int len; 198 199 cfspi_dbg_state(cfspi, CFSPI_STATE_DELIVER_PKT); 200 201 /* Parse SPI frame. */ 202 ptr = ((u8 *)(cfspi->xfer.va_rx + SPI_DATA_POS)); 203 204 len = cfspi_rxfrm(cfspi, ptr, cfspi->rx_cpck_len); 205 WARN_ON(len != cfspi->rx_cpck_len); 206 } 207 208 /* Check the next SPI command and length. */ 209 ptr = (u8 *) cfspi->xfer.va_rx; 210 211 ptr += forward_to_spi_cmd(cfspi); 212 213 cfspi->cmd = *ptr++; 214 cfspi->cmd |= ((*ptr++) << 8) & 0xFF00; 215 cfspi->rx_npck_len = *ptr++; 216 cfspi->rx_npck_len |= ((*ptr++) << 8) & 0xFF00; 217 218 WARN_ON(cfspi->rx_npck_len > SPI_DMA_BUF_LEN); 219 WARN_ON(cfspi->cmd > SPI_CMD_EOT); 220 221 debugfs_store_prev(cfspi); 222 223 /* Check whether the master issued an EOT command. */ 224 if (cfspi->cmd == SPI_CMD_EOT) { 225 /* Reset state. */ 226 cfspi->tx_cpck_len = 0; 227 cfspi->rx_cpck_len = 0; 228 } else { 229 /* Update state. */ 230 cfspi->tx_cpck_len = cfspi->tx_npck_len; 231 cfspi->rx_cpck_len = cfspi->rx_npck_len; 232 } 233 234 /* 235 * Check whether we need to clear the xfer bit. 236 * Spin lock needed for packet insertion. 237 * Test and clear of different bits 238 * are not supported. 239 */ 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); 244 245 spin_unlock_irqrestore(&cfspi->lock, flags); 246 } 247} 248 249struct platform_driver cfspi_spi_driver = { 250 .probe = cfspi_spi_probe, 251 .remove = cfspi_spi_remove, 252 .driver = { 253 .name = "cfspi_sspi", 254 .owner = THIS_MODULE, 255 }, 256};