mbed library sources. Supersedes mbed-src. removed serial

Fork of mbed-dev by mbed official

Committer:
<>
Date:
Thu Feb 02 17:01:33 2017 +0000
Revision:
157:ff67d9f36b67
This updates the lib to the mbed lib v135

Who changed what in which revision?

UserRevisionLine numberNew contents of line
<> 157:ff67d9f36b67 1 /**
<> 157:ff67d9f36b67 2 * @file
<> 157:ff67d9f36b67 3 * @brief Serial Peripheral Interface Master (SPIM) Function Implementations.
<> 157:ff67d9f36b67 4 */
<> 157:ff67d9f36b67 5 /* *****************************************************************************
<> 157:ff67d9f36b67 6 * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
<> 157:ff67d9f36b67 7 *
<> 157:ff67d9f36b67 8 * Permission is hereby granted, free of charge, to any person obtaining a
<> 157:ff67d9f36b67 9 * copy of this software and associated documentation files (the "Software"),
<> 157:ff67d9f36b67 10 * to deal in the Software without restriction, including without limitation
<> 157:ff67d9f36b67 11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
<> 157:ff67d9f36b67 12 * and/or sell copies of the Software, and to permit persons to whom the
<> 157:ff67d9f36b67 13 * Software is furnished to do so, subject to the following conditions:
<> 157:ff67d9f36b67 14 *
<> 157:ff67d9f36b67 15 * The above copyright notice and this permission notice shall be included
<> 157:ff67d9f36b67 16 * in all copies or substantial portions of the Software.
<> 157:ff67d9f36b67 17 *
<> 157:ff67d9f36b67 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
<> 157:ff67d9f36b67 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
<> 157:ff67d9f36b67 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
<> 157:ff67d9f36b67 21 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
<> 157:ff67d9f36b67 22 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
<> 157:ff67d9f36b67 23 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
<> 157:ff67d9f36b67 24 * OTHER DEALINGS IN THE SOFTWARE.
<> 157:ff67d9f36b67 25 *
<> 157:ff67d9f36b67 26 * Except as contained in this notice, the name of Maxim Integrated
<> 157:ff67d9f36b67 27 * Products, Inc. shall not be used except as stated in the Maxim Integrated
<> 157:ff67d9f36b67 28 * Products, Inc. Branding Policy.
<> 157:ff67d9f36b67 29 *
<> 157:ff67d9f36b67 30 * The mere transfer of this software does not imply any licenses
<> 157:ff67d9f36b67 31 * of trade secrets, proprietary technology, copyrights, patents,
<> 157:ff67d9f36b67 32 * trademarks, maskwork rights, or any other form of intellectual
<> 157:ff67d9f36b67 33 * property whatsoever. Maxim Integrated Products, Inc. retains all
<> 157:ff67d9f36b67 34 * ownership rights.
<> 157:ff67d9f36b67 35 *
<> 157:ff67d9f36b67 36 * $Date: 2016-09-08 17:32:38 -0500 (Thu, 08 Sep 2016) $
<> 157:ff67d9f36b67 37 * $Revision: 24324 $
<> 157:ff67d9f36b67 38 *
<> 157:ff67d9f36b67 39 **************************************************************************** */
<> 157:ff67d9f36b67 40
<> 157:ff67d9f36b67 41 /* **** Includes **** */
<> 157:ff67d9f36b67 42 #include <stddef.h>
<> 157:ff67d9f36b67 43 #include <string.h>
<> 157:ff67d9f36b67 44 #include "mxc_config.h"
<> 157:ff67d9f36b67 45 #include "mxc_assert.h"
<> 157:ff67d9f36b67 46 #include "mxc_sys.h"
<> 157:ff67d9f36b67 47 #include "mxc_lock.h"
<> 157:ff67d9f36b67 48 #include "spim.h"
<> 157:ff67d9f36b67 49
<> 157:ff67d9f36b67 50 /**
<> 157:ff67d9f36b67 51 * @ingroup spim
<> 157:ff67d9f36b67 52 * @{
<> 157:ff67d9f36b67 53 */
<> 157:ff67d9f36b67 54 /* **** Definitions **** */
<> 157:ff67d9f36b67 55 #define SPIM_MAX_BYTE_LEN 32
<> 157:ff67d9f36b67 56 #define SPIM_MAX_PAGE_LEN 32
<> 157:ff67d9f36b67 57
<> 157:ff67d9f36b67 58 /* **** Globals **** */
<> 157:ff67d9f36b67 59
<> 157:ff67d9f36b67 60 // Saves the state of the non-blocking requests
<> 157:ff67d9f36b67 61 typedef struct {
<> 157:ff67d9f36b67 62 spim_req_t *req;
<> 157:ff67d9f36b67 63 unsigned head_rem;
<> 157:ff67d9f36b67 64 } spim_req_head_t;
<> 157:ff67d9f36b67 65
<> 157:ff67d9f36b67 66 static spim_req_head_t states[MXC_CFG_SPIM_INSTANCES];
<> 157:ff67d9f36b67 67
<> 157:ff67d9f36b67 68 /* **** Local Function Prototypes **** */
<> 157:ff67d9f36b67 69
<> 157:ff67d9f36b67 70 static unsigned SPIM_ReadRXFIFO(mxc_spim_regs_t *spim, mxc_spim_fifo_regs_t *fifo,
<> 157:ff67d9f36b67 71 uint8_t *data, unsigned len);
<> 157:ff67d9f36b67 72
<> 157:ff67d9f36b67 73 static uint32_t SPIM_TransHandler(mxc_spim_regs_t *spim, spim_req_t *req, int spim_num);
<> 157:ff67d9f36b67 74
<> 157:ff67d9f36b67 75 /* ************************************************************************* */
<> 157:ff67d9f36b67 76 int SPIM_Init(mxc_spim_regs_t *spim, const spim_cfg_t *cfg, const sys_cfg_spim_t *sys_cfg)
<> 157:ff67d9f36b67 77 {
<> 157:ff67d9f36b67 78 int err, spim_num;
<> 157:ff67d9f36b67 79 uint32_t spim_clk, clocks;
<> 157:ff67d9f36b67 80
<> 157:ff67d9f36b67 81 spim_num = MXC_SPIM_GET_IDX(spim);
<> 157:ff67d9f36b67 82 MXC_ASSERT(spim_num >= 0);
<> 157:ff67d9f36b67 83
<> 157:ff67d9f36b67 84 // Check the input parameters
<> 157:ff67d9f36b67 85 if(cfg == NULL)
<> 157:ff67d9f36b67 86 return E_NULL_PTR;
<> 157:ff67d9f36b67 87
<> 157:ff67d9f36b67 88 if(cfg->baud == 0)
<> 157:ff67d9f36b67 89 return E_BAD_PARAM;
<> 157:ff67d9f36b67 90
<> 157:ff67d9f36b67 91 // Set system level configurations
<> 157:ff67d9f36b67 92 if ((err = SYS_SPIM_Init(spim, cfg, sys_cfg)) != E_NO_ERROR) {
<> 157:ff67d9f36b67 93 return err;
<> 157:ff67d9f36b67 94 }
<> 157:ff67d9f36b67 95
<> 157:ff67d9f36b67 96 /* Configure the baud, make sure the SPIM clk is enabled and the baud
<> 157:ff67d9f36b67 97 is less than the maximum */
<> 157:ff67d9f36b67 98 spim_clk = SYS_SPIM_GetFreq(spim);
<> 157:ff67d9f36b67 99 if((spim_clk == 0) || ((spim_clk == SystemCoreClock) && ((spim_clk/2) < cfg->baud))) {
<> 157:ff67d9f36b67 100 return E_BAD_PARAM;
<> 157:ff67d9f36b67 101 }
<> 157:ff67d9f36b67 102
<> 157:ff67d9f36b67 103 // Initialize state pointers
<> 157:ff67d9f36b67 104 states[spim_num].req = NULL;
<> 157:ff67d9f36b67 105 states[spim_num].head_rem = 0;
<> 157:ff67d9f36b67 106
<> 157:ff67d9f36b67 107 // Drain the FIFOs, enable SPIM, enable SCK Feedback
<> 157:ff67d9f36b67 108 spim->gen_ctrl = 0;
<> 157:ff67d9f36b67 109 spim->gen_ctrl = (MXC_F_SPIM_GEN_CTRL_SPI_MSTR_EN | MXC_F_SPIM_GEN_CTRL_TX_FIFO_EN |
<> 157:ff67d9f36b67 110 MXC_F_SPIM_GEN_CTRL_RX_FIFO_EN | MXC_F_SPIM_GEN_CTRL_ENABLE_SCK_FB_MODE);
<> 157:ff67d9f36b67 111
<> 157:ff67d9f36b67 112 // Set mode and page size
<> 157:ff67d9f36b67 113 spim->mstr_cfg = (((cfg->mode << MXC_F_SPIM_MSTR_CFG_SPI_MODE_POS) & MXC_F_SPIM_MSTR_CFG_SPI_MODE) |
<> 157:ff67d9f36b67 114 MXC_S_SPIM_MSTR_CFG_PAGE_32B | (0x2 << MXC_F_SPIM_MSTR_CFG_ACT_DELAY_POS));
<> 157:ff67d9f36b67 115
<> 157:ff67d9f36b67 116 // Configure the SSEL polarity
<> 157:ff67d9f36b67 117 spim->ss_sr_polarity = ((cfg->ssel_pol << MXC_F_SPIM_SS_SR_POLARITY_SS_POLARITY_POS) &
<> 157:ff67d9f36b67 118 MXC_F_SPIM_SS_SR_POLARITY_SS_POLARITY);
<> 157:ff67d9f36b67 119
<> 157:ff67d9f36b67 120 #if(MXC_SPIM_REV == 0)
<> 157:ff67d9f36b67 121 // Disable the feedback clock in modes 1 and 2
<> 157:ff67d9f36b67 122 if((cfg->mode == 1) || (cfg->mode == 2)) {
<> 157:ff67d9f36b67 123 spim->gen_ctrl &= ~MXC_F_SPIM_GEN_CTRL_ENABLE_SCK_FB_MODE;
<> 157:ff67d9f36b67 124 spim->mstr_cfg |= (0x1 << MXC_F_SPIM_MSTR_CFG_SDIO_SAMPLE_POINT_POS);
<> 157:ff67d9f36b67 125 }
<> 157:ff67d9f36b67 126 #else
<> 157:ff67d9f36b67 127 // Increase the RX FIFO margin
<> 157:ff67d9f36b67 128 MXC_SPIM1->spcl_ctrl = ((MXC_SPIM1->spcl_ctrl & ~(MXC_F_SPIM_SPCL_CTRL_RX_FIFO_MARGIN)) |
<> 157:ff67d9f36b67 129 (0x3 << MXC_F_SPIM_SPCL_CTRL_RX_FIFO_MARGIN_POS));
<> 157:ff67d9f36b67 130 #endif
<> 157:ff67d9f36b67 131
<> 157:ff67d9f36b67 132 // Calculate the hi/lo clock setting
<> 157:ff67d9f36b67 133 if(spim_clk/2 > cfg->baud) {
<> 157:ff67d9f36b67 134
<> 157:ff67d9f36b67 135 /* Disable the feedback mode and use the sample mode with an appropriate hi/lo clk
<> 157:ff67d9f36b67 136 to achieve the lower baud rate */
<> 157:ff67d9f36b67 137 spim->gen_ctrl &= ~MXC_F_SPIM_GEN_CTRL_ENABLE_SCK_FB_MODE;
<> 157:ff67d9f36b67 138
<> 157:ff67d9f36b67 139 clocks = (spim_clk / (2*cfg->baud));
<> 157:ff67d9f36b67 140
<> 157:ff67d9f36b67 141 if(clocks == 0 || clocks > 0x10) {
<> 157:ff67d9f36b67 142 return E_BAD_PARAM;
<> 157:ff67d9f36b67 143 }
<> 157:ff67d9f36b67 144
<> 157:ff67d9f36b67 145 // 0 => 16 in the 4 bit field for HI_CLK and LO_CLK
<> 157:ff67d9f36b67 146 if(clocks == 0x10) {
<> 157:ff67d9f36b67 147 clocks = 0;
<> 157:ff67d9f36b67 148 }
<> 157:ff67d9f36b67 149
<> 157:ff67d9f36b67 150 } else {
<> 157:ff67d9f36b67 151 // Continue to use feedback mode and set hi/lo clk to 1
<> 157:ff67d9f36b67 152 clocks = 1;
<> 157:ff67d9f36b67 153 }
<> 157:ff67d9f36b67 154
<> 157:ff67d9f36b67 155 spim->mstr_cfg |= (((clocks << MXC_F_SPIM_MSTR_CFG_SCK_HI_CLK_POS) & MXC_F_SPIM_MSTR_CFG_SCK_HI_CLK) |
<> 157:ff67d9f36b67 156 ((clocks << MXC_F_SPIM_MSTR_CFG_SCK_LO_CLK_POS) & MXC_F_SPIM_MSTR_CFG_SCK_LO_CLK));
<> 157:ff67d9f36b67 157
<> 157:ff67d9f36b67 158 return E_NO_ERROR;
<> 157:ff67d9f36b67 159 }
<> 157:ff67d9f36b67 160
<> 157:ff67d9f36b67 161 /* ************************************************************************* */
<> 157:ff67d9f36b67 162 int SPIM_Shutdown(mxc_spim_regs_t *spim)
<> 157:ff67d9f36b67 163 {
<> 157:ff67d9f36b67 164 int spim_num, err;
<> 157:ff67d9f36b67 165 spim_req_t *temp_req;
<> 157:ff67d9f36b67 166
<> 157:ff67d9f36b67 167 // Disable and clear interrupts
<> 157:ff67d9f36b67 168 spim->inten = 0;
<> 157:ff67d9f36b67 169 spim->intfl = spim->intfl;
<> 157:ff67d9f36b67 170
<> 157:ff67d9f36b67 171 // Disable SPIM and FIFOS
<> 157:ff67d9f36b67 172 spim->gen_ctrl &= ~(MXC_F_SPIM_GEN_CTRL_SPI_MSTR_EN | MXC_F_SPIM_GEN_CTRL_TX_FIFO_EN |
<> 157:ff67d9f36b67 173 MXC_F_SPIM_GEN_CTRL_RX_FIFO_EN);
<> 157:ff67d9f36b67 174
<> 157:ff67d9f36b67 175 // Call all of the pending callbacks for this SPIM
<> 157:ff67d9f36b67 176 spim_num = MXC_SPIM_GET_IDX(spim);
<> 157:ff67d9f36b67 177 if(states[spim_num].req != NULL) {
<> 157:ff67d9f36b67 178
<> 157:ff67d9f36b67 179 // Save the request
<> 157:ff67d9f36b67 180 temp_req = states[spim_num].req;
<> 157:ff67d9f36b67 181
<> 157:ff67d9f36b67 182 // Unlock this SPIM
<> 157:ff67d9f36b67 183 mxc_free_lock((uint32_t*)&states[spim_num].req);
<> 157:ff67d9f36b67 184
<> 157:ff67d9f36b67 185 // Callback if not NULL
<> 157:ff67d9f36b67 186 if(temp_req->callback != NULL) {
<> 157:ff67d9f36b67 187 temp_req->callback(temp_req, E_SHUTDOWN);
<> 157:ff67d9f36b67 188 }
<> 157:ff67d9f36b67 189 }
<> 157:ff67d9f36b67 190
<> 157:ff67d9f36b67 191 // Clear system level configurations
<> 157:ff67d9f36b67 192 if ((err = SYS_SPIM_Shutdown(spim)) != E_NO_ERROR) {
<> 157:ff67d9f36b67 193 return err;
<> 157:ff67d9f36b67 194 }
<> 157:ff67d9f36b67 195
<> 157:ff67d9f36b67 196 return E_NO_ERROR;
<> 157:ff67d9f36b67 197 }
<> 157:ff67d9f36b67 198
<> 157:ff67d9f36b67 199 /* ************************************************************************* */
<> 157:ff67d9f36b67 200 int SPIM_Clocks(mxc_spim_regs_t *spim, uint32_t len, uint8_t ssel, uint8_t deass)
<> 157:ff67d9f36b67 201 {
<> 157:ff67d9f36b67 202 int spim_num;
<> 157:ff67d9f36b67 203 mxc_spim_fifo_regs_t *fifo;
<> 157:ff67d9f36b67 204 uint16_t header = 0x1;
<> 157:ff67d9f36b67 205 uint32_t num = len;
<> 157:ff67d9f36b67 206
<> 157:ff67d9f36b67 207 // Make sure the SPIM has been initialized
<> 157:ff67d9f36b67 208 if((spim->gen_ctrl & MXC_F_SPIM_GEN_CTRL_SPI_MSTR_EN) == 0)
<> 157:ff67d9f36b67 209 return E_UNINITIALIZED;
<> 157:ff67d9f36b67 210
<> 157:ff67d9f36b67 211 if(!(len > 0)) {
<> 157:ff67d9f36b67 212 return E_NO_ERROR;
<> 157:ff67d9f36b67 213 }
<> 157:ff67d9f36b67 214
<> 157:ff67d9f36b67 215 // Check the previous transaction if we're switching the slave select
<> 157:ff67d9f36b67 216 if((ssel != ((spim->mstr_cfg & MXC_F_SPIM_MSTR_CFG_SLAVE_SEL) >>
<> 157:ff67d9f36b67 217 MXC_F_SPIM_MSTR_CFG_SLAVE_SEL_POS)) && (spim->gen_ctrl & MXC_F_SPIM_GEN_CTRL_BB_SS_IN_OUT)) {
<> 157:ff67d9f36b67 218
<> 157:ff67d9f36b67 219 // Return E_BUSY if the slave select is still asserted
<> 157:ff67d9f36b67 220 return E_BUSY;
<> 157:ff67d9f36b67 221 }
<> 157:ff67d9f36b67 222
<> 157:ff67d9f36b67 223 // Attempt to lock this SPIM
<> 157:ff67d9f36b67 224 spim_num = MXC_SPIM_GET_IDX(spim);
<> 157:ff67d9f36b67 225 if(mxc_get_lock((uint32_t*)&states[spim_num].req, 1) != E_NO_ERROR) {
<> 157:ff67d9f36b67 226 return E_BUSY;
<> 157:ff67d9f36b67 227 }
<> 157:ff67d9f36b67 228
<> 157:ff67d9f36b67 229 // Set which slave select we are using
<> 157:ff67d9f36b67 230 spim->mstr_cfg = ((spim->mstr_cfg & ~MXC_F_SPIM_MSTR_CFG_SLAVE_SEL) |
<> 157:ff67d9f36b67 231 ((ssel << MXC_F_SPIM_MSTR_CFG_SLAVE_SEL_POS) & MXC_F_SPIM_MSTR_CFG_SLAVE_SEL));
<> 157:ff67d9f36b67 232
<> 157:ff67d9f36b67 233 //force deass to a 1 or 0
<> 157:ff67d9f36b67 234 deass = !!deass;
<> 157:ff67d9f36b67 235
<> 157:ff67d9f36b67 236 #if(MXC_SPIM_REV == 0)
<> 157:ff67d9f36b67 237 // Wait for all of the data to transmit
<> 157:ff67d9f36b67 238 while(spim->fifo_ctrl & MXC_F_SPIM_FIFO_CTRL_TX_FIFO_USED) {}
<> 157:ff67d9f36b67 239
<> 157:ff67d9f36b67 240 // Disable the feedback clock, save state
<> 157:ff67d9f36b67 241 uint32_t gen_ctrl = spim->gen_ctrl;
<> 157:ff67d9f36b67 242 spim->gen_ctrl &= ~MXC_F_SPIM_GEN_CTRL_ENABLE_SCK_FB_MODE;
<> 157:ff67d9f36b67 243 #endif
<> 157:ff67d9f36b67 244
<> 157:ff67d9f36b67 245 // Get the TX and RX FIFO for this SPIM
<> 157:ff67d9f36b67 246 fifo = MXC_SPIM_GET_SPIM_FIFO(spim_num);
<> 157:ff67d9f36b67 247
<> 157:ff67d9f36b67 248 // Send the headers to transmit the clocks
<> 157:ff67d9f36b67 249 while(len > 32) {
<> 157:ff67d9f36b67 250 fifo->trans_16[0] = header;
<> 157:ff67d9f36b67 251 fifo->trans_16[0] = 0xF000;
<> 157:ff67d9f36b67 252 fifo->trans_16[0] = 0xF000;
<> 157:ff67d9f36b67 253 len -= 32;
<> 157:ff67d9f36b67 254 }
<> 157:ff67d9f36b67 255
<> 157:ff67d9f36b67 256 if(len) {
<> 157:ff67d9f36b67 257 if(len < 32) {
<> 157:ff67d9f36b67 258 header |= (len << 4);
<> 157:ff67d9f36b67 259 }
<> 157:ff67d9f36b67 260 header |= (deass << 13);
<> 157:ff67d9f36b67 261
<> 157:ff67d9f36b67 262 fifo->trans_16[0] = header;
<> 157:ff67d9f36b67 263
<> 157:ff67d9f36b67 264 if(len > 16) {
<> 157:ff67d9f36b67 265 fifo->trans_16[0] = 0xF000;
<> 157:ff67d9f36b67 266 }
<> 157:ff67d9f36b67 267 fifo->trans_16[0] = 0xF000;
<> 157:ff67d9f36b67 268 }
<> 157:ff67d9f36b67 269
<> 157:ff67d9f36b67 270 #if(MXC_SPIM_REV == 0)
<> 157:ff67d9f36b67 271 // Wait for all of the data to transmit
<> 157:ff67d9f36b67 272 while(spim->fifo_ctrl & MXC_F_SPIM_FIFO_CTRL_TX_FIFO_USED) {}
<> 157:ff67d9f36b67 273
<> 157:ff67d9f36b67 274 // Restore feedback clock setting
<> 157:ff67d9f36b67 275 spim->gen_ctrl |= (gen_ctrl & MXC_F_SPIM_GEN_CTRL_ENABLE_SCK_FB_MODE);
<> 157:ff67d9f36b67 276 #endif
<> 157:ff67d9f36b67 277
<> 157:ff67d9f36b67 278 // Unlock this SPIM
<> 157:ff67d9f36b67 279 mxc_free_lock((uint32_t*)&states[spim_num].req);
<> 157:ff67d9f36b67 280
<> 157:ff67d9f36b67 281 return num;
<> 157:ff67d9f36b67 282 }
<> 157:ff67d9f36b67 283
<> 157:ff67d9f36b67 284
<> 157:ff67d9f36b67 285 /* ************************************************************************* */
<> 157:ff67d9f36b67 286 int SPIM_Trans(mxc_spim_regs_t *spim, spim_req_t *req)
<> 157:ff67d9f36b67 287 {
<> 157:ff67d9f36b67 288 int spim_num;
<> 157:ff67d9f36b67 289
<> 157:ff67d9f36b67 290 // Make sure the SPIM has been initialized
<> 157:ff67d9f36b67 291 if((spim->gen_ctrl & MXC_F_SPIM_GEN_CTRL_SPI_MSTR_EN) == 0)
<> 157:ff67d9f36b67 292 return E_UNINITIALIZED;
<> 157:ff67d9f36b67 293
<> 157:ff67d9f36b67 294 // Check the input parameters
<> 157:ff67d9f36b67 295 if(req == NULL)
<> 157:ff67d9f36b67 296 return E_NULL_PTR;
<> 157:ff67d9f36b67 297
<> 157:ff67d9f36b67 298 if((req->rx_data == NULL) && (req->tx_data == NULL))
<> 157:ff67d9f36b67 299 return E_NULL_PTR;
<> 157:ff67d9f36b67 300
<> 157:ff67d9f36b67 301 if(!(req->len > 0)) {
<> 157:ff67d9f36b67 302 return E_NO_ERROR;
<> 157:ff67d9f36b67 303 }
<> 157:ff67d9f36b67 304
<> 157:ff67d9f36b67 305 // Check the previous transaction if we're switching the slave select
<> 157:ff67d9f36b67 306 if((req->ssel != ((spim->mstr_cfg & MXC_F_SPIM_MSTR_CFG_SLAVE_SEL) >>
<> 157:ff67d9f36b67 307 MXC_F_SPIM_MSTR_CFG_SLAVE_SEL_POS)) && (spim->gen_ctrl & MXC_F_SPIM_GEN_CTRL_BB_SS_IN_OUT)) {
<> 157:ff67d9f36b67 308
<> 157:ff67d9f36b67 309 // Return E_BUSY if the slave select is still asserted
<> 157:ff67d9f36b67 310 return E_BUSY;
<> 157:ff67d9f36b67 311 }
<> 157:ff67d9f36b67 312
<> 157:ff67d9f36b67 313 // Attempt to register this write request
<> 157:ff67d9f36b67 314 spim_num = MXC_SPIM_GET_IDX(spim);
<> 157:ff67d9f36b67 315 if(mxc_get_lock((uint32_t*)&states[spim_num].req, (uint32_t)req) != E_NO_ERROR) {
<> 157:ff67d9f36b67 316 return E_BUSY;
<> 157:ff67d9f36b67 317 }
<> 157:ff67d9f36b67 318
<> 157:ff67d9f36b67 319 // Set which slave select we are using
<> 157:ff67d9f36b67 320 spim->mstr_cfg = ((spim->mstr_cfg & ~MXC_F_SPIM_MSTR_CFG_SLAVE_SEL) |
<> 157:ff67d9f36b67 321 ((req->ssel << MXC_F_SPIM_MSTR_CFG_SLAVE_SEL_POS) & MXC_F_SPIM_MSTR_CFG_SLAVE_SEL));
<> 157:ff67d9f36b67 322
<> 157:ff67d9f36b67 323 //force deass to a 1 or 0
<> 157:ff67d9f36b67 324 req->deass = !!req->deass;
<> 157:ff67d9f36b67 325
<> 157:ff67d9f36b67 326 // Clear the number of bytes counter
<> 157:ff67d9f36b67 327 req->read_num = 0;
<> 157:ff67d9f36b67 328 req->write_num = 0;
<> 157:ff67d9f36b67 329 req->callback = NULL;
<> 157:ff67d9f36b67 330 states[spim_num].head_rem = 0;
<> 157:ff67d9f36b67 331
<> 157:ff67d9f36b67 332 // Start the transaction, keep calling the handler until complete
<> 157:ff67d9f36b67 333 while(SPIM_TransHandler(spim, req, spim_num) != 0);
<> 157:ff67d9f36b67 334
<> 157:ff67d9f36b67 335 if(req->tx_data == NULL) {
<> 157:ff67d9f36b67 336 return req->read_num;
<> 157:ff67d9f36b67 337 }
<> 157:ff67d9f36b67 338 return req->write_num;
<> 157:ff67d9f36b67 339 }
<> 157:ff67d9f36b67 340
<> 157:ff67d9f36b67 341 /* ************************************************************************* */
<> 157:ff67d9f36b67 342 int SPIM_TransAsync(mxc_spim_regs_t *spim, spim_req_t *req)
<> 157:ff67d9f36b67 343 {
<> 157:ff67d9f36b67 344 int spim_num;
<> 157:ff67d9f36b67 345
<> 157:ff67d9f36b67 346 // Make sure the SPIM has been initialized
<> 157:ff67d9f36b67 347 if((spim->gen_ctrl & MXC_F_SPIM_GEN_CTRL_SPI_MSTR_EN) == 0)
<> 157:ff67d9f36b67 348 return E_UNINITIALIZED;
<> 157:ff67d9f36b67 349
<> 157:ff67d9f36b67 350 // Check the input parameters
<> 157:ff67d9f36b67 351 if(req == NULL)
<> 157:ff67d9f36b67 352 return E_NULL_PTR;
<> 157:ff67d9f36b67 353
<> 157:ff67d9f36b67 354 if((req->rx_data == NULL) && (req->tx_data == NULL))
<> 157:ff67d9f36b67 355 return E_NULL_PTR;
<> 157:ff67d9f36b67 356
<> 157:ff67d9f36b67 357 if(!(req->len > 0)) {
<> 157:ff67d9f36b67 358 return E_NO_ERROR;
<> 157:ff67d9f36b67 359 }
<> 157:ff67d9f36b67 360
<> 157:ff67d9f36b67 361
<> 157:ff67d9f36b67 362 // Check the previous transaction if we're switching the slave select
<> 157:ff67d9f36b67 363 if((req->ssel != ((spim->mstr_cfg & MXC_F_SPIM_MSTR_CFG_SLAVE_SEL) >>
<> 157:ff67d9f36b67 364 MXC_F_SPIM_MSTR_CFG_SLAVE_SEL_POS)) && (spim->gen_ctrl & MXC_F_SPIM_GEN_CTRL_BB_SS_IN_OUT)) {
<> 157:ff67d9f36b67 365
<> 157:ff67d9f36b67 366 // Return E_BUSY if the slave select is still asserted
<> 157:ff67d9f36b67 367 return E_BUSY;
<> 157:ff67d9f36b67 368 }
<> 157:ff67d9f36b67 369
<> 157:ff67d9f36b67 370 // Attempt to register this write request
<> 157:ff67d9f36b67 371 spim_num = MXC_SPIM_GET_IDX(spim);
<> 157:ff67d9f36b67 372 if(mxc_get_lock((uint32_t*)&states[spim_num].req, (uint32_t)req) != E_NO_ERROR) {
<> 157:ff67d9f36b67 373 return E_BUSY;
<> 157:ff67d9f36b67 374 }
<> 157:ff67d9f36b67 375
<> 157:ff67d9f36b67 376 // Set which slave select we are using
<> 157:ff67d9f36b67 377 spim->mstr_cfg = ((spim->mstr_cfg & ~MXC_F_SPIM_MSTR_CFG_SLAVE_SEL) |
<> 157:ff67d9f36b67 378 ((req->ssel << MXC_F_SPIM_MSTR_CFG_SLAVE_SEL_POS) & MXC_F_SPIM_MSTR_CFG_SLAVE_SEL));
<> 157:ff67d9f36b67 379
<> 157:ff67d9f36b67 380 //force deass to a 1 or 0
<> 157:ff67d9f36b67 381 req->deass = !!req->deass;
<> 157:ff67d9f36b67 382
<> 157:ff67d9f36b67 383 // Clear the number of bytes counter
<> 157:ff67d9f36b67 384 req->read_num = 0;
<> 157:ff67d9f36b67 385 req->write_num = 0;
<> 157:ff67d9f36b67 386 states[spim_num].head_rem = 0;
<> 157:ff67d9f36b67 387
<> 157:ff67d9f36b67 388 // Start the transaction, enable the interrupts
<> 157:ff67d9f36b67 389 spim->inten = SPIM_TransHandler(spim, req, spim_num);
<> 157:ff67d9f36b67 390
<> 157:ff67d9f36b67 391 return E_NO_ERROR;
<> 157:ff67d9f36b67 392 }
<> 157:ff67d9f36b67 393
<> 157:ff67d9f36b67 394 /* ************************************************************************* */
<> 157:ff67d9f36b67 395 int SPIM_AbortAsync(spim_req_t *req)
<> 157:ff67d9f36b67 396 {
<> 157:ff67d9f36b67 397 int spim_num;
<> 157:ff67d9f36b67 398 mxc_spim_regs_t *spim;
<> 157:ff67d9f36b67 399
<> 157:ff67d9f36b67 400 // Check the input parameters
<> 157:ff67d9f36b67 401 if(req == NULL) {
<> 157:ff67d9f36b67 402 return E_BAD_PARAM;
<> 157:ff67d9f36b67 403 }
<> 157:ff67d9f36b67 404
<> 157:ff67d9f36b67 405 // Find the request, set to NULL
<> 157:ff67d9f36b67 406 for(spim_num = 0; spim_num < MXC_CFG_SPIM_INSTANCES; spim_num++) {
<> 157:ff67d9f36b67 407 if(req == states[spim_num].req) {
<> 157:ff67d9f36b67 408
<> 157:ff67d9f36b67 409 spim = MXC_SPIM_GET_SPIM(spim_num);
<> 157:ff67d9f36b67 410
<> 157:ff67d9f36b67 411 // Disable interrupts, clear the flags
<> 157:ff67d9f36b67 412 spim->inten = 0;
<> 157:ff67d9f36b67 413 spim->intfl = spim->intfl;
<> 157:ff67d9f36b67 414
<> 157:ff67d9f36b67 415 // Reset the SPIM to cancel the on ongoing transaction
<> 157:ff67d9f36b67 416 spim->gen_ctrl &= ~(MXC_F_SPIM_GEN_CTRL_SPI_MSTR_EN);
<> 157:ff67d9f36b67 417 spim->gen_ctrl |= (MXC_F_SPIM_GEN_CTRL_SPI_MSTR_EN);
<> 157:ff67d9f36b67 418
<> 157:ff67d9f36b67 419 // Unlock this SPIM
<> 157:ff67d9f36b67 420 mxc_free_lock((uint32_t*)&states[spim_num].req);
<> 157:ff67d9f36b67 421
<> 157:ff67d9f36b67 422 // Callback if not NULL
<> 157:ff67d9f36b67 423 if(req->callback != NULL) {
<> 157:ff67d9f36b67 424 req->callback(req, E_ABORT);
<> 157:ff67d9f36b67 425 }
<> 157:ff67d9f36b67 426
<> 157:ff67d9f36b67 427 return E_NO_ERROR;
<> 157:ff67d9f36b67 428 }
<> 157:ff67d9f36b67 429 }
<> 157:ff67d9f36b67 430
<> 157:ff67d9f36b67 431 return E_BAD_PARAM;
<> 157:ff67d9f36b67 432 }
<> 157:ff67d9f36b67 433
<> 157:ff67d9f36b67 434 /* ************************************************************************* */
<> 157:ff67d9f36b67 435 void SPIM_Handler(mxc_spim_regs_t *spim)
<> 157:ff67d9f36b67 436 {
<> 157:ff67d9f36b67 437 int spim_num;
<> 157:ff67d9f36b67 438 uint32_t flags;
<> 157:ff67d9f36b67 439
<> 157:ff67d9f36b67 440 // Clear the interrupt flags
<> 157:ff67d9f36b67 441 spim->inten = 0;
<> 157:ff67d9f36b67 442 flags = spim->intfl;
<> 157:ff67d9f36b67 443 spim->intfl = flags;
<> 157:ff67d9f36b67 444
<> 157:ff67d9f36b67 445 spim_num = MXC_SPIM_GET_IDX(spim);
<> 157:ff67d9f36b67 446
<> 157:ff67d9f36b67 447 // Figure out if this SPIM has an active request
<> 157:ff67d9f36b67 448 if((states[spim_num].req != NULL) && (flags)) {
<> 157:ff67d9f36b67 449 spim->inten = SPIM_TransHandler(spim, states[spim_num].req, spim_num);
<> 157:ff67d9f36b67 450 }
<> 157:ff67d9f36b67 451 }
<> 157:ff67d9f36b67 452
<> 157:ff67d9f36b67 453 /* ************************************************************************* */
<> 157:ff67d9f36b67 454 int SPIM_Busy(mxc_spim_regs_t *spim)
<> 157:ff67d9f36b67 455 {
<> 157:ff67d9f36b67 456 // Check to see if there are any ongoing transactions
<> 157:ff67d9f36b67 457 if((states[MXC_SPIM_GET_IDX(spim)].req == NULL) &&
<> 157:ff67d9f36b67 458 !(spim->fifo_ctrl & MXC_F_SPIM_FIFO_CTRL_TX_FIFO_USED)) {
<> 157:ff67d9f36b67 459
<> 157:ff67d9f36b67 460 return E_NO_ERROR;
<> 157:ff67d9f36b67 461 }
<> 157:ff67d9f36b67 462
<> 157:ff67d9f36b67 463 return E_BUSY;
<> 157:ff67d9f36b67 464 }
<> 157:ff67d9f36b67 465
<> 157:ff67d9f36b67 466 /* ************************************************************************* */
<> 157:ff67d9f36b67 467 int SPIM_PrepForSleep(mxc_spim_regs_t *spim)
<> 157:ff67d9f36b67 468 {
<> 157:ff67d9f36b67 469 if(SPIM_Busy(spim) != E_NO_ERROR) {
<> 157:ff67d9f36b67 470 return E_BUSY;
<> 157:ff67d9f36b67 471 }
<> 157:ff67d9f36b67 472
<> 157:ff67d9f36b67 473 // Disable interrupts
<> 157:ff67d9f36b67 474 spim->inten = 0;
<> 157:ff67d9f36b67 475 return E_NO_ERROR;
<> 157:ff67d9f36b67 476 }
<> 157:ff67d9f36b67 477
<> 157:ff67d9f36b67 478 /* ************************************************************************* */
<> 157:ff67d9f36b67 479 static unsigned SPIM_ReadRXFIFO(mxc_spim_regs_t *spim, mxc_spim_fifo_regs_t *fifo,
<> 157:ff67d9f36b67 480 uint8_t *data, unsigned len)
<> 157:ff67d9f36b67 481 {
<> 157:ff67d9f36b67 482 unsigned num = 0;
<> 157:ff67d9f36b67 483 unsigned avail = ((spim->fifo_ctrl & MXC_F_SPIM_FIFO_CTRL_RX_FIFO_USED) >>
<> 157:ff67d9f36b67 484 MXC_F_SPIM_FIFO_CTRL_RX_FIFO_USED_POS);
<> 157:ff67d9f36b67 485
<> 157:ff67d9f36b67 486 // Get data from the RXFIFO
<> 157:ff67d9f36b67 487 while(avail && (len - num)) {
<> 157:ff67d9f36b67 488
<> 157:ff67d9f36b67 489 if((avail >= 4) && ((len-num) >= 4)) {
<> 157:ff67d9f36b67 490 // Save data from the RXFIFO
<> 157:ff67d9f36b67 491 uint32_t temp = fifo->rslts_32[0];
<> 157:ff67d9f36b67 492 data[num+0] = ((temp & 0x000000FF) >> 0);
<> 157:ff67d9f36b67 493 data[num+1] = ((temp & 0x0000FF00) >> 8);
<> 157:ff67d9f36b67 494 data[num+2] = ((temp & 0x00FF0000) >> 16);
<> 157:ff67d9f36b67 495 data[num+3] = ((temp & 0xFF000000) >> 24);
<> 157:ff67d9f36b67 496 num+=4;
<> 157:ff67d9f36b67 497 avail-=4;
<> 157:ff67d9f36b67 498 } else if ((avail >= 2) && ((len-num) >= 2)) {
<> 157:ff67d9f36b67 499 // Save data from the RXFIFO
<> 157:ff67d9f36b67 500 uint16_t temp = fifo->rslts_16[0];
<> 157:ff67d9f36b67 501 data[num+0] = ((temp & 0x00FF) >> 0);
<> 157:ff67d9f36b67 502 data[num+1] = ((temp & 0xFF00) >> 8);
<> 157:ff67d9f36b67 503 num+=2;
<> 157:ff67d9f36b67 504 avail-=2;
<> 157:ff67d9f36b67 505 } else {
<> 157:ff67d9f36b67 506 // Save data from the RXFIFO
<> 157:ff67d9f36b67 507 data[num] = fifo->rslts_8[0];
<> 157:ff67d9f36b67 508 num+=1;
<> 157:ff67d9f36b67 509 avail-=1;
<> 157:ff67d9f36b67 510 }
<> 157:ff67d9f36b67 511
<> 157:ff67d9f36b67 512 // Check to see if there is more data in the FIFO
<> 157:ff67d9f36b67 513 if(avail == 0) {
<> 157:ff67d9f36b67 514 avail = ((spim->fifo_ctrl & MXC_F_SPIM_FIFO_CTRL_RX_FIFO_USED) >>
<> 157:ff67d9f36b67 515 MXC_F_SPIM_FIFO_CTRL_RX_FIFO_USED_POS);
<> 157:ff67d9f36b67 516 }
<> 157:ff67d9f36b67 517 }
<> 157:ff67d9f36b67 518
<> 157:ff67d9f36b67 519 return num;
<> 157:ff67d9f36b67 520 }
<> 157:ff67d9f36b67 521
<> 157:ff67d9f36b67 522 uint16_t header_save;
<> 157:ff67d9f36b67 523
<> 157:ff67d9f36b67 524
<> 157:ff67d9f36b67 525 /* ************************************************************************* */
<> 157:ff67d9f36b67 526 static uint32_t SPIM_TransHandler(mxc_spim_regs_t *spim, spim_req_t *req, int spim_num)
<> 157:ff67d9f36b67 527 {
<> 157:ff67d9f36b67 528 uint8_t read, write;
<> 157:ff67d9f36b67 529 uint16_t header;
<> 157:ff67d9f36b67 530 uint32_t pages, bytes, inten;
<> 157:ff67d9f36b67 531 unsigned remain, bytes_read, head_rem_temp, avail;
<> 157:ff67d9f36b67 532 mxc_spim_fifo_regs_t *fifo;
<> 157:ff67d9f36b67 533
<> 157:ff67d9f36b67 534 inten = 0;
<> 157:ff67d9f36b67 535
<> 157:ff67d9f36b67 536 // Get the FIFOS for this UART
<> 157:ff67d9f36b67 537 fifo = MXC_SPIM_GET_SPIM_FIFO(spim_num);
<> 157:ff67d9f36b67 538
<> 157:ff67d9f36b67 539 // Figure out if we're reading
<> 157:ff67d9f36b67 540 if(req->rx_data != NULL) {
<> 157:ff67d9f36b67 541 read = 1;
<> 157:ff67d9f36b67 542 } else {
<> 157:ff67d9f36b67 543 read = 0;
<> 157:ff67d9f36b67 544 }
<> 157:ff67d9f36b67 545
<> 157:ff67d9f36b67 546 // Figure out if we're writing
<> 157:ff67d9f36b67 547 if(req->tx_data != NULL) {
<> 157:ff67d9f36b67 548 write = 1;
<> 157:ff67d9f36b67 549 } else {
<> 157:ff67d9f36b67 550 write = 0;
<> 157:ff67d9f36b67 551 }
<> 157:ff67d9f36b67 552
<> 157:ff67d9f36b67 553 // Read byte from the FIFO if we are reading
<> 157:ff67d9f36b67 554 if(read) {
<> 157:ff67d9f36b67 555
<> 157:ff67d9f36b67 556 // Read all of the data in the RXFIFO, or until we don't need anymore
<> 157:ff67d9f36b67 557 bytes_read = SPIM_ReadRXFIFO(spim, fifo, &req->rx_data[req->read_num],
<> 157:ff67d9f36b67 558 (req->len - req->read_num));
<> 157:ff67d9f36b67 559
<> 157:ff67d9f36b67 560 req->read_num += bytes_read;
<> 157:ff67d9f36b67 561
<> 157:ff67d9f36b67 562 // Adjust head_rem if we are only reading
<> 157:ff67d9f36b67 563 if(!write && (states[spim_num].head_rem > 0)) {
<> 157:ff67d9f36b67 564 states[spim_num].head_rem -= bytes_read;
<> 157:ff67d9f36b67 565 }
<> 157:ff67d9f36b67 566
<> 157:ff67d9f36b67 567 // Figure out how many byte we have left to read
<> 157:ff67d9f36b67 568 if(states[spim_num].head_rem > 0) {
<> 157:ff67d9f36b67 569 remain = states[spim_num].head_rem;
<> 157:ff67d9f36b67 570 } else {
<> 157:ff67d9f36b67 571 remain = req->len - req->read_num;
<> 157:ff67d9f36b67 572 }
<> 157:ff67d9f36b67 573
<> 157:ff67d9f36b67 574 if(remain) {
<> 157:ff67d9f36b67 575
<> 157:ff67d9f36b67 576 // Set the RX interrupts
<> 157:ff67d9f36b67 577 if (remain > MXC_CFG_SPIM_FIFO_DEPTH) {
<> 157:ff67d9f36b67 578 spim->fifo_ctrl = ((spim->fifo_ctrl & ~MXC_F_SPIM_FIFO_CTRL_RX_FIFO_AF_LVL) |
<> 157:ff67d9f36b67 579 ((MXC_CFG_SPIM_FIFO_DEPTH - 2) <<
<> 157:ff67d9f36b67 580 MXC_F_SPIM_FIFO_CTRL_RX_FIFO_AF_LVL_POS));
<> 157:ff67d9f36b67 581
<> 157:ff67d9f36b67 582 } else {
<> 157:ff67d9f36b67 583 spim->fifo_ctrl = ((spim->fifo_ctrl & ~MXC_F_SPIM_FIFO_CTRL_RX_FIFO_AF_LVL) |
<> 157:ff67d9f36b67 584 ((remain - 1) << MXC_F_SPIM_FIFO_CTRL_RX_FIFO_AF_LVL_POS));
<> 157:ff67d9f36b67 585 }
<> 157:ff67d9f36b67 586
<> 157:ff67d9f36b67 587 inten |= MXC_F_SPIM_INTEN_RX_FIFO_AF;
<> 157:ff67d9f36b67 588 }
<> 157:ff67d9f36b67 589 }
<> 157:ff67d9f36b67 590
<> 157:ff67d9f36b67 591 // Figure out how many bytes we have left to send headers for
<> 157:ff67d9f36b67 592 if(write) {
<> 157:ff67d9f36b67 593 remain = req->len - req->write_num;
<> 157:ff67d9f36b67 594 } else {
<> 157:ff67d9f36b67 595 remain = req->len - req->read_num;
<> 157:ff67d9f36b67 596 }
<> 157:ff67d9f36b67 597
<> 157:ff67d9f36b67 598 // See if we need to send a new header
<> 157:ff67d9f36b67 599 if(states[spim_num].head_rem <= 0 && remain) {
<> 157:ff67d9f36b67 600
<> 157:ff67d9f36b67 601 // Set the transaction configuration in the header
<> 157:ff67d9f36b67 602 header = ((write << 0) | (read << 1) | (req->width << 9));
<> 157:ff67d9f36b67 603
<> 157:ff67d9f36b67 604 if(remain >= SPIM_MAX_BYTE_LEN) {
<> 157:ff67d9f36b67 605
<> 157:ff67d9f36b67 606 // Send a 32 byte header
<> 157:ff67d9f36b67 607 if(remain == SPIM_MAX_BYTE_LEN) {
<> 157:ff67d9f36b67 608
<> 157:ff67d9f36b67 609 header |= ((0x1 << 2) | (req->deass << 13));
<> 157:ff67d9f36b67 610
<> 157:ff67d9f36b67 611 // Save the number of bytes we need to write to the FIFO
<> 157:ff67d9f36b67 612 bytes = SPIM_MAX_BYTE_LEN;
<> 157:ff67d9f36b67 613
<> 157:ff67d9f36b67 614 } else {
<> 157:ff67d9f36b67 615 // Send in increments of 32 byte pages
<> 157:ff67d9f36b67 616 header |= (0x2 << 2);
<> 157:ff67d9f36b67 617 pages = remain / SPIM_MAX_PAGE_LEN;
<> 157:ff67d9f36b67 618
<> 157:ff67d9f36b67 619 if(pages >= 32) {
<> 157:ff67d9f36b67 620 // 0 maps to 32 in the header
<> 157:ff67d9f36b67 621 bytes = 32 * SPIM_MAX_PAGE_LEN;
<> 157:ff67d9f36b67 622 } else {
<> 157:ff67d9f36b67 623 header |= (pages << 4);
<> 157:ff67d9f36b67 624 bytes = pages * SPIM_MAX_PAGE_LEN;
<> 157:ff67d9f36b67 625 }
<> 157:ff67d9f36b67 626
<> 157:ff67d9f36b67 627 // Check if this is the last header we will send
<> 157:ff67d9f36b67 628 if((remain - bytes) == 0) {
<> 157:ff67d9f36b67 629 header |= (req->deass << 13);
<> 157:ff67d9f36b67 630 }
<> 157:ff67d9f36b67 631 }
<> 157:ff67d9f36b67 632
<> 157:ff67d9f36b67 633 header_save = header;
<> 157:ff67d9f36b67 634 fifo->trans_16[0] = header;
<> 157:ff67d9f36b67 635
<> 157:ff67d9f36b67 636 // Save the number of bytes we need to write to the FIFO
<> 157:ff67d9f36b67 637 states[spim_num].head_rem = bytes;
<> 157:ff67d9f36b67 638
<> 157:ff67d9f36b67 639 } else {
<> 157:ff67d9f36b67 640
<> 157:ff67d9f36b67 641 // Send final header with the number of bytes remaining and if
<> 157:ff67d9f36b67 642 // we want to de-assert the SS at the end of the transaction
<> 157:ff67d9f36b67 643 header |= ((0x1 << 2) | (remain << 4) | (req->deass << 13));
<> 157:ff67d9f36b67 644 fifo->trans_16[0] = header;
<> 157:ff67d9f36b67 645 states[spim_num].head_rem = remain;
<> 157:ff67d9f36b67 646 }
<> 157:ff67d9f36b67 647 }
<> 157:ff67d9f36b67 648
<> 157:ff67d9f36b67 649 // Put data into the FIFO if we are writing
<> 157:ff67d9f36b67 650 remain = req->len - req->write_num;
<> 157:ff67d9f36b67 651 head_rem_temp = states[spim_num].head_rem;
<> 157:ff67d9f36b67 652 if(write && head_rem_temp) {
<> 157:ff67d9f36b67 653
<> 157:ff67d9f36b67 654 // Fill the FIFO
<> 157:ff67d9f36b67 655 avail = (MXC_CFG_SPIM_FIFO_DEPTH - ((spim->fifo_ctrl & MXC_F_SPIM_FIFO_CTRL_TX_FIFO_USED) >>
<> 157:ff67d9f36b67 656 MXC_F_SPIM_FIFO_CTRL_TX_FIFO_USED_POS));
<> 157:ff67d9f36b67 657
<> 157:ff67d9f36b67 658 // Use memcpy for everything except the last byte in odd length transactions
<> 157:ff67d9f36b67 659 while((avail >= 2) && (head_rem_temp >= 2)) {
<> 157:ff67d9f36b67 660
<> 157:ff67d9f36b67 661 unsigned length;
<> 157:ff67d9f36b67 662 if(head_rem_temp < avail) {
<> 157:ff67d9f36b67 663 length = head_rem_temp;
<> 157:ff67d9f36b67 664 } else {
<> 157:ff67d9f36b67 665 length = avail;
<> 157:ff67d9f36b67 666 }
<> 157:ff67d9f36b67 667
<> 157:ff67d9f36b67 668 // Only memcpy even numbers
<> 157:ff67d9f36b67 669 length = ((length / 2) * 2);
<> 157:ff67d9f36b67 670
<> 157:ff67d9f36b67 671 memcpy((void*)fifo->trans_32, &(req->tx_data[req->write_num]), length);
<> 157:ff67d9f36b67 672
<> 157:ff67d9f36b67 673 head_rem_temp -= length;
<> 157:ff67d9f36b67 674 req->write_num += length;
<> 157:ff67d9f36b67 675
<> 157:ff67d9f36b67 676 avail = (MXC_CFG_SPIM_FIFO_DEPTH - ((spim->fifo_ctrl & MXC_F_SPIM_FIFO_CTRL_TX_FIFO_USED) >>
<> 157:ff67d9f36b67 677 MXC_F_SPIM_FIFO_CTRL_TX_FIFO_USED_POS));
<> 157:ff67d9f36b67 678 }
<> 157:ff67d9f36b67 679
<> 157:ff67d9f36b67 680 // Copy the last byte and pad with 0xF0 to not get confused as header
<> 157:ff67d9f36b67 681 if((avail >= 1) && (head_rem_temp == 1)) {
<> 157:ff67d9f36b67 682
<> 157:ff67d9f36b67 683 // Write the last byte
<> 157:ff67d9f36b67 684 fifo->trans_16[0] = (0xF000 | req->tx_data[req->write_num]);
<> 157:ff67d9f36b67 685
<> 157:ff67d9f36b67 686 avail -= 1;
<> 157:ff67d9f36b67 687 req->write_num += 1;
<> 157:ff67d9f36b67 688 head_rem_temp -= 1;
<> 157:ff67d9f36b67 689 }
<> 157:ff67d9f36b67 690
<> 157:ff67d9f36b67 691 states[spim_num].head_rem = head_rem_temp;
<> 157:ff67d9f36b67 692 remain = req->len - req->write_num;
<> 157:ff67d9f36b67 693
<> 157:ff67d9f36b67 694 // Set the TX interrupts
<> 157:ff67d9f36b67 695 if(remain) {
<> 157:ff67d9f36b67 696
<> 157:ff67d9f36b67 697 // Set the TX FIFO almost empty interrupt if we have to refill
<> 157:ff67d9f36b67 698 spim->fifo_ctrl = ((spim->fifo_ctrl & ~MXC_F_SPIM_FIFO_CTRL_TX_FIFO_AE_LVL) |
<> 157:ff67d9f36b67 699 ((MXC_CFG_SPIM_FIFO_DEPTH - 2) << MXC_F_SPIM_FIFO_CTRL_TX_FIFO_AE_LVL_POS));
<> 157:ff67d9f36b67 700
<> 157:ff67d9f36b67 701 inten |= MXC_F_SPIM_INTEN_TX_FIFO_AE;
<> 157:ff67d9f36b67 702
<> 157:ff67d9f36b67 703 }
<> 157:ff67d9f36b67 704 }
<> 157:ff67d9f36b67 705
<> 157:ff67d9f36b67 706 // Check to see if we've finished reading and writing
<> 157:ff67d9f36b67 707 if(((read && (req->read_num == req->len)) || !read) &&
<> 157:ff67d9f36b67 708 ((req->write_num == req->len) || !write)) {
<> 157:ff67d9f36b67 709
<> 157:ff67d9f36b67 710 // Disable interrupts
<> 157:ff67d9f36b67 711 spim->inten = 0;
<> 157:ff67d9f36b67 712
<> 157:ff67d9f36b67 713 // Unlock this SPIM
<> 157:ff67d9f36b67 714 mxc_free_lock((uint32_t*)&states[spim_num].req);
<> 157:ff67d9f36b67 715
<> 157:ff67d9f36b67 716 // Callback if not NULL
<> 157:ff67d9f36b67 717 if(req->callback != NULL) {
<> 157:ff67d9f36b67 718 req->callback(req, E_NO_ERROR);
<> 157:ff67d9f36b67 719 }
<> 157:ff67d9f36b67 720 }
<> 157:ff67d9f36b67 721
<> 157:ff67d9f36b67 722 // Enable the SPIM interrupts
<> 157:ff67d9f36b67 723 return inten;
<> 157:ff67d9f36b67 724 }
<> 157:ff67d9f36b67 725 /**@} end of ingroup spim */