t

Fork of mbed-dev by mbed official

Committer:
amithy
Date:
Thu Nov 09 22:14:37 2017 +0000
Revision:
178:c26431f84b0d
Parent:
150:02e0a0aed4ec
test export

Who changed what in which revision?

UserRevisionLine numberNew contents of line
<> 150:02e0a0aed4ec 1 /*******************************************************************************
<> 150:02e0a0aed4ec 2 * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
<> 150:02e0a0aed4ec 3 *
<> 150:02e0a0aed4ec 4 * Permission is hereby granted, free of charge, to any person obtaining a
<> 150:02e0a0aed4ec 5 * copy of this software and associated documentation files (the "Software"),
<> 150:02e0a0aed4ec 6 * to deal in the Software without restriction, including without limitation
<> 150:02e0a0aed4ec 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
<> 150:02e0a0aed4ec 8 * and/or sell copies of the Software, and to permit persons to whom the
<> 150:02e0a0aed4ec 9 * Software is furnished to do so, subject to the following conditions:
<> 150:02e0a0aed4ec 10 *
<> 150:02e0a0aed4ec 11 * The above copyright notice and this permission notice shall be included
<> 150:02e0a0aed4ec 12 * in all copies or substantial portions of the Software.
<> 150:02e0a0aed4ec 13 *
<> 150:02e0a0aed4ec 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
<> 150:02e0a0aed4ec 15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
<> 150:02e0a0aed4ec 16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
<> 150:02e0a0aed4ec 17 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
<> 150:02e0a0aed4ec 18 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
<> 150:02e0a0aed4ec 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
<> 150:02e0a0aed4ec 20 * OTHER DEALINGS IN THE SOFTWARE.
<> 150:02e0a0aed4ec 21 *
<> 150:02e0a0aed4ec 22 * Except as contained in this notice, the name of Maxim Integrated
<> 150:02e0a0aed4ec 23 * Products, Inc. shall not be used except as stated in the Maxim Integrated
<> 150:02e0a0aed4ec 24 * Products, Inc. Branding Policy.
<> 150:02e0a0aed4ec 25 *
<> 150:02e0a0aed4ec 26 * The mere transfer of this software does not imply any licenses
<> 150:02e0a0aed4ec 27 * of trade secrets, proprietary technology, copyrights, patents,
<> 150:02e0a0aed4ec 28 * trademarks, maskwork rights, or any other form of intellectual
<> 150:02e0a0aed4ec 29 * property whatsoever. Maxim Integrated Products, Inc. retains all
<> 150:02e0a0aed4ec 30 * ownership rights.
<> 150:02e0a0aed4ec 31 *
<> 150:02e0a0aed4ec 32 * $Date: 2016-06-01 08:51:23 -0500 (Wed, 01 Jun 2016) $
<> 150:02e0a0aed4ec 33 * $Revision: 23131 $
<> 150:02e0a0aed4ec 34 *
<> 150:02e0a0aed4ec 35 ******************************************************************************/
<> 150:02e0a0aed4ec 36
<> 150:02e0a0aed4ec 37 /**
<> 150:02e0a0aed4ec 38 * @file i2cm.c
<> 150:02e0a0aed4ec 39 * @brief I2C Master driver source.
<> 150:02e0a0aed4ec 40 */
<> 150:02e0a0aed4ec 41
<> 150:02e0a0aed4ec 42 /***** Includes *****/
<> 150:02e0a0aed4ec 43 #include <string.h>
<> 150:02e0a0aed4ec 44 #include <math.h>
<> 150:02e0a0aed4ec 45 #include "mxc_assert.h"
<> 150:02e0a0aed4ec 46 #include "mxc_lock.h"
<> 150:02e0a0aed4ec 47 #include "mxc_errors.h"
<> 150:02e0a0aed4ec 48 #include "mxc_sys.h"
<> 150:02e0a0aed4ec 49 #include "i2cm.h"
<> 150:02e0a0aed4ec 50
<> 150:02e0a0aed4ec 51 /***** Definitions *****/
<> 150:02e0a0aed4ec 52
<> 150:02e0a0aed4ec 53 #ifndef MXC_I2CM_TX_TIMEOUT
<> 150:02e0a0aed4ec 54 #define MXC_I2CM_TX_TIMEOUT 0x5000
<> 150:02e0a0aed4ec 55 #endif
<> 150:02e0a0aed4ec 56
<> 150:02e0a0aed4ec 57 #ifndef MXC_I2CM_RX_TIMEOUT
<> 150:02e0a0aed4ec 58 #define MXC_I2CM_RX_TIMEOUT 0x5000
<> 150:02e0a0aed4ec 59 #endif
<> 150:02e0a0aed4ec 60
<> 150:02e0a0aed4ec 61 #define I2CM_READ_BIT 0x0001
<> 150:02e0a0aed4ec 62 #define I2CM_FIFO_DEPTH_3Q ((3 * MXC_I2CM_FIFO_DEPTH) / 4)
<> 150:02e0a0aed4ec 63 #define I2CM_FIFO_DEPTH_2Q (MXC_I2CM_FIFO_DEPTH / 2)
<> 150:02e0a0aed4ec 64
<> 150:02e0a0aed4ec 65 /***** Globals *****/
<> 150:02e0a0aed4ec 66
<> 150:02e0a0aed4ec 67 // Saves the state of the non-blocking requests
<> 150:02e0a0aed4ec 68 typedef enum {
<> 150:02e0a0aed4ec 69 I2CM_STATE_READING = 0,
<> 150:02e0a0aed4ec 70 I2CM_STATE_WRITING = 1
<> 150:02e0a0aed4ec 71 } i2cm_state_t;
<> 150:02e0a0aed4ec 72
<> 150:02e0a0aed4ec 73 typedef struct {
<> 150:02e0a0aed4ec 74 i2cm_req_t *req;
<> 150:02e0a0aed4ec 75 i2cm_state_t state;
<> 150:02e0a0aed4ec 76 } i2cm_req_state_t;
<> 150:02e0a0aed4ec 77 static i2cm_req_state_t states[MXC_CFG_I2CM_INSTANCES];
<> 150:02e0a0aed4ec 78
<> 150:02e0a0aed4ec 79 /***** Functions *****/
<> 150:02e0a0aed4ec 80
<> 150:02e0a0aed4ec 81 //static void I2CM_Recover(mxc_i2cm_regs_t *i2cm);
<> 150:02e0a0aed4ec 82 //static int I2CM_WriteTxFifo(mxc_i2cm_regs_t *regs, mxc_i2cm_fifo_regs_t *fifo, const uint16_t data);
<> 150:02e0a0aed4ec 83 //static int I2CM_TxInProgress(mxc_i2cm_regs_t *i2cm);
<> 150:02e0a0aed4ec 84 static void I2CM_FreeCallback(int i2cm_num, int error);
<> 150:02e0a0aed4ec 85 //static int I2CM_Tx(mxc_i2cm_regs_t *i2cm, mxc_i2cm_fifo_regs_t *fifo, uint8_t addr,
<> 150:02e0a0aed4ec 86 // const uint8_t *data, uint32_t len, uint8_t stop);
<> 150:02e0a0aed4ec 87
<> 150:02e0a0aed4ec 88 //static int I2CM_Rx(mxc_i2cm_regs_t *i2cm, mxc_i2cm_fifo_regs_t *fifo, uint8_t addr,
<> 150:02e0a0aed4ec 89 // uint8_t *data, uint32_t len);
<> 150:02e0a0aed4ec 90
<> 150:02e0a0aed4ec 91 static int I2CM_CmdHandler(mxc_i2cm_regs_t *i2cm, mxc_i2cm_fifo_regs_t *fifo, i2cm_req_t *req);
<> 150:02e0a0aed4ec 92 static int I2CM_ReadHandler(mxc_i2cm_regs_t *i2cm, i2cm_req_t *req, int i2cm_num);
<> 150:02e0a0aed4ec 93 static int I2CM_WriteHandler(mxc_i2cm_regs_t *i2cm, i2cm_req_t *req, int i2cm_num);
<> 150:02e0a0aed4ec 94
<> 150:02e0a0aed4ec 95 /******************************************************************************/
<> 150:02e0a0aed4ec 96 int I2CM_Init(mxc_i2cm_regs_t *i2cm, const sys_cfg_i2cm_t *sys_cfg, i2cm_speed_t speed)
<> 150:02e0a0aed4ec 97 {
<> 150:02e0a0aed4ec 98 int err;
<> 150:02e0a0aed4ec 99
<> 150:02e0a0aed4ec 100 // Check the base pointer
<> 150:02e0a0aed4ec 101 MXC_ASSERT(MXC_I2CM_GET_IDX(i2cm) >= 0);
<> 150:02e0a0aed4ec 102
<> 150:02e0a0aed4ec 103 // Set system level configurations
<> 150:02e0a0aed4ec 104 if ((err = SYS_I2CM_Init(i2cm, sys_cfg)) != E_NO_ERROR) {
<> 150:02e0a0aed4ec 105 return err;
<> 150:02e0a0aed4ec 106 }
<> 150:02e0a0aed4ec 107
<> 150:02e0a0aed4ec 108 I2CM_SetFrequency(i2cm,speed);
<> 150:02e0a0aed4ec 109
<> 150:02e0a0aed4ec 110 // Reset module
<> 150:02e0a0aed4ec 111 i2cm->ctrl = MXC_F_I2CM_CTRL_MSTR_RESET_EN;
<> 150:02e0a0aed4ec 112 i2cm->ctrl = 0;
<> 150:02e0a0aed4ec 113
<> 150:02e0a0aed4ec 114 // Set timeout to 255 ms and turn on the auto-stop option
<> 150:02e0a0aed4ec 115 i2cm->timeout = (MXC_F_I2CM_TIMEOUT_TX_TIMEOUT | MXC_F_I2CM_TIMEOUT_AUTO_STOP_EN);
<> 150:02e0a0aed4ec 116
<> 150:02e0a0aed4ec 117 // Enable tx_fifo and rx_fifo
<> 150:02e0a0aed4ec 118 i2cm->ctrl |= (MXC_F_I2CM_CTRL_TX_FIFO_EN | MXC_F_I2CM_CTRL_RX_FIFO_EN);
<> 150:02e0a0aed4ec 119
<> 150:02e0a0aed4ec 120 return E_NO_ERROR;
<> 150:02e0a0aed4ec 121 }
<> 150:02e0a0aed4ec 122
<> 150:02e0a0aed4ec 123 /******************************************************************************/
<> 150:02e0a0aed4ec 124 int I2CM_Shutdown(mxc_i2cm_regs_t *i2cm)
<> 150:02e0a0aed4ec 125 {
<> 150:02e0a0aed4ec 126 int i2cm_num, err;
<> 150:02e0a0aed4ec 127
<> 150:02e0a0aed4ec 128 // Check the base pointer
<> 150:02e0a0aed4ec 129 i2cm_num = MXC_I2CM_GET_IDX(i2cm);
<> 150:02e0a0aed4ec 130 MXC_ASSERT(i2cm_num >= 0);
<> 150:02e0a0aed4ec 131
<> 150:02e0a0aed4ec 132 // Disable and clear interrupts
<> 150:02e0a0aed4ec 133 i2cm->inten = 0;
<> 150:02e0a0aed4ec 134 i2cm->intfl = i2cm->intfl;
<> 150:02e0a0aed4ec 135
<> 150:02e0a0aed4ec 136 // Call all of the pending callbacks for this I2CM
<> 150:02e0a0aed4ec 137 if(states[i2cm_num].req != NULL) {
<> 150:02e0a0aed4ec 138 I2CM_Recover(i2cm);
<> 150:02e0a0aed4ec 139 I2CM_FreeCallback(i2cm_num, E_SHUTDOWN);
<> 150:02e0a0aed4ec 140 }
<> 150:02e0a0aed4ec 141
<> 150:02e0a0aed4ec 142 // Clears system level configurations
<> 150:02e0a0aed4ec 143 if ((err = SYS_I2CM_Shutdown(i2cm)) != E_NO_ERROR) {
<> 150:02e0a0aed4ec 144 return err;
<> 150:02e0a0aed4ec 145 }
<> 150:02e0a0aed4ec 146
<> 150:02e0a0aed4ec 147 return E_NO_ERROR;
<> 150:02e0a0aed4ec 148 }
<> 150:02e0a0aed4ec 149
<> 150:02e0a0aed4ec 150
<> 150:02e0a0aed4ec 151 /******************************************************************************/
<> 150:02e0a0aed4ec 152 int I2CM_Read(mxc_i2cm_regs_t *i2cm, uint8_t addr, const uint8_t *cmd_data,
<> 150:02e0a0aed4ec 153 uint32_t cmd_len, uint8_t* data, uint32_t len)
<> 150:02e0a0aed4ec 154 {
<> 150:02e0a0aed4ec 155 int i2cm_num;
<> 150:02e0a0aed4ec 156 int error = E_NO_ERROR;
<> 150:02e0a0aed4ec 157 int retval = E_NO_ERROR;
<> 150:02e0a0aed4ec 158 mxc_i2cm_fifo_regs_t *fifo;
<> 150:02e0a0aed4ec 159
<> 150:02e0a0aed4ec 160 if(data == NULL) {
<> 150:02e0a0aed4ec 161 return E_NULL_PTR;
<> 150:02e0a0aed4ec 162 }
<> 150:02e0a0aed4ec 163
<> 150:02e0a0aed4ec 164 // Make sure the I2CM has been initialized
<> 150:02e0a0aed4ec 165 if(i2cm->ctrl == 0) {
<> 150:02e0a0aed4ec 166 return E_UNINITIALIZED;
<> 150:02e0a0aed4ec 167 }
<> 150:02e0a0aed4ec 168
<> 150:02e0a0aed4ec 169 if(!(len > 0)) {
<> 150:02e0a0aed4ec 170 return E_NO_ERROR;
<> 150:02e0a0aed4ec 171 }
<> 150:02e0a0aed4ec 172
<> 150:02e0a0aed4ec 173 // Lock this I2CM
<> 150:02e0a0aed4ec 174 i2cm_num = MXC_I2CM_GET_IDX(i2cm);
<> 150:02e0a0aed4ec 175 while(mxc_get_lock((uint32_t*)&states[i2cm_num].req,1) != E_NO_ERROR) {}
<> 150:02e0a0aed4ec 176
<> 150:02e0a0aed4ec 177 // Get the FIFO pointer for this I2CM
<> 150:02e0a0aed4ec 178 fifo = MXC_I2CM_GET_FIFO(i2cm_num);
<> 150:02e0a0aed4ec 179
<> 150:02e0a0aed4ec 180 // Disable and clear the interrupts
<> 150:02e0a0aed4ec 181 i2cm->inten = 0;
<> 150:02e0a0aed4ec 182 i2cm->intfl = i2cm->intfl;
<> 150:02e0a0aed4ec 183
<> 150:02e0a0aed4ec 184 // Transmit the command if there is command data and length
<> 150:02e0a0aed4ec 185 if((cmd_data != NULL) && (cmd_len > 0)) {
<> 150:02e0a0aed4ec 186 retval = I2CM_Tx(i2cm, fifo, addr, cmd_data, cmd_len, 0);
<> 150:02e0a0aed4ec 187 }
<> 150:02e0a0aed4ec 188
<> 150:02e0a0aed4ec 189 // Read data from the slave if we don't have any errors
<> 150:02e0a0aed4ec 190 if(retval == E_NO_ERROR) {
<> 150:02e0a0aed4ec 191 retval = I2CM_Rx(i2cm, fifo, addr, data, len);
<> 150:02e0a0aed4ec 192 }
<> 150:02e0a0aed4ec 193
<> 150:02e0a0aed4ec 194 // Wait for the transaction to complete
<> 150:02e0a0aed4ec 195 if((error = I2CM_TxInProgress(i2cm)) != E_NO_ERROR) {
<> 150:02e0a0aed4ec 196 retval = error;
<> 150:02e0a0aed4ec 197 }
<> 150:02e0a0aed4ec 198
<> 150:02e0a0aed4ec 199 // Unlock this I2CM
<> 150:02e0a0aed4ec 200 mxc_free_lock((uint32_t*)&states[i2cm_num].req);
<> 150:02e0a0aed4ec 201
<> 150:02e0a0aed4ec 202 if(retval != E_NO_ERROR) {
<> 150:02e0a0aed4ec 203 return retval;
<> 150:02e0a0aed4ec 204 }
<> 150:02e0a0aed4ec 205
<> 150:02e0a0aed4ec 206 return len;
<> 150:02e0a0aed4ec 207 }
<> 150:02e0a0aed4ec 208
<> 150:02e0a0aed4ec 209 /******************************************************************************/
<> 150:02e0a0aed4ec 210 int I2CM_Write(mxc_i2cm_regs_t *i2cm, uint8_t addr, const uint8_t *cmd_data,
<> 150:02e0a0aed4ec 211 uint32_t cmd_len, uint8_t* data, uint32_t len)
<> 150:02e0a0aed4ec 212 {
<> 150:02e0a0aed4ec 213 int i2cm_num;
<> 150:02e0a0aed4ec 214 int error = E_NO_ERROR;
<> 150:02e0a0aed4ec 215 int retval = E_NO_ERROR;
<> 150:02e0a0aed4ec 216 mxc_i2cm_fifo_regs_t *fifo;
<> 150:02e0a0aed4ec 217
<> 150:02e0a0aed4ec 218 if(data == NULL) {
<> 150:02e0a0aed4ec 219 return E_NULL_PTR;
<> 150:02e0a0aed4ec 220 }
<> 150:02e0a0aed4ec 221
<> 150:02e0a0aed4ec 222 // Make sure the I2CM has been initialized
<> 150:02e0a0aed4ec 223 if(i2cm->ctrl == 0) {
<> 150:02e0a0aed4ec 224 return E_UNINITIALIZED;
<> 150:02e0a0aed4ec 225 }
<> 150:02e0a0aed4ec 226
<> 150:02e0a0aed4ec 227 if(!(len > 0)) {
<> 150:02e0a0aed4ec 228 return E_NO_ERROR;
<> 150:02e0a0aed4ec 229 }
<> 150:02e0a0aed4ec 230
<> 150:02e0a0aed4ec 231 // Lock this I2CM
<> 150:02e0a0aed4ec 232 i2cm_num = MXC_I2CM_GET_IDX(i2cm);
<> 150:02e0a0aed4ec 233 while(mxc_get_lock((uint32_t*)&states[i2cm_num].req,1) != E_NO_ERROR) {}
<> 150:02e0a0aed4ec 234
<> 150:02e0a0aed4ec 235 // Get the FIFO pointer for this I2CM
<> 150:02e0a0aed4ec 236 fifo = MXC_I2CM_GET_FIFO(i2cm_num);
<> 150:02e0a0aed4ec 237
<> 150:02e0a0aed4ec 238 // Disable and clear the interrupts
<> 150:02e0a0aed4ec 239 i2cm->inten = 0;
<> 150:02e0a0aed4ec 240 i2cm->intfl = i2cm->intfl;
<> 150:02e0a0aed4ec 241
<> 150:02e0a0aed4ec 242 // Transmit the command if there is command data and length, don't send stop bit
<> 150:02e0a0aed4ec 243 if((cmd_data != NULL) && (cmd_len > 0)) {
<> 150:02e0a0aed4ec 244 retval = I2CM_Tx(i2cm, fifo, addr, cmd_data, cmd_len, 0);
<> 150:02e0a0aed4ec 245 }
<> 150:02e0a0aed4ec 246
<> 150:02e0a0aed4ec 247 // Write data to the slave, send the stop bit
<> 150:02e0a0aed4ec 248 if(retval == E_NO_ERROR) {
<> 150:02e0a0aed4ec 249 retval = I2CM_Tx(i2cm, fifo, addr, data, len, 1);
<> 150:02e0a0aed4ec 250 }
<> 150:02e0a0aed4ec 251
<> 150:02e0a0aed4ec 252 // Wait for the transaction to complete
<> 150:02e0a0aed4ec 253 if((error = I2CM_TxInProgress(i2cm)) != E_NO_ERROR) {
<> 150:02e0a0aed4ec 254 retval = error;
<> 150:02e0a0aed4ec 255 }
<> 150:02e0a0aed4ec 256
<> 150:02e0a0aed4ec 257 // Unlock this I2CM
<> 150:02e0a0aed4ec 258 mxc_free_lock((uint32_t*)&states[i2cm_num].req);
<> 150:02e0a0aed4ec 259
<> 150:02e0a0aed4ec 260 if(retval != E_NO_ERROR) {
<> 150:02e0a0aed4ec 261 return retval;
<> 150:02e0a0aed4ec 262 }
<> 150:02e0a0aed4ec 263
<> 150:02e0a0aed4ec 264 return len;
<> 150:02e0a0aed4ec 265 }
<> 150:02e0a0aed4ec 266
<> 150:02e0a0aed4ec 267 /******************************************************************************/
<> 150:02e0a0aed4ec 268 int I2CM_ReadAsync(mxc_i2cm_regs_t *i2cm, i2cm_req_t *req)
<> 150:02e0a0aed4ec 269 {
<> 150:02e0a0aed4ec 270 int i2cm_num, error;
<> 150:02e0a0aed4ec 271
<> 150:02e0a0aed4ec 272 if(req->data == NULL) {
<> 150:02e0a0aed4ec 273 return E_NULL_PTR;
<> 150:02e0a0aed4ec 274 }
<> 150:02e0a0aed4ec 275
<> 150:02e0a0aed4ec 276 // Make sure the I2CM has been initialized
<> 150:02e0a0aed4ec 277 if(i2cm->ctrl == 0) {
<> 150:02e0a0aed4ec 278 return E_UNINITIALIZED;
<> 150:02e0a0aed4ec 279 }
<> 150:02e0a0aed4ec 280
<> 150:02e0a0aed4ec 281 if(!(req->data_len > 0)) {
<> 150:02e0a0aed4ec 282 return E_NO_ERROR;
<> 150:02e0a0aed4ec 283 }
<> 150:02e0a0aed4ec 284
<> 150:02e0a0aed4ec 285 i2cm_num = MXC_I2CM_GET_IDX(i2cm);
<> 150:02e0a0aed4ec 286
<> 150:02e0a0aed4ec 287 // Attempt to register this request
<> 150:02e0a0aed4ec 288 if(mxc_get_lock((uint32_t*)&states[i2cm_num].req, (uint32_t)req) != E_NO_ERROR) {
<> 150:02e0a0aed4ec 289 return E_BUSY;
<> 150:02e0a0aed4ec 290 }
<> 150:02e0a0aed4ec 291
<> 150:02e0a0aed4ec 292 states[i2cm_num].state = I2CM_STATE_READING;
<> 150:02e0a0aed4ec 293
<> 150:02e0a0aed4ec 294 // Clear the number of bytes counter
<> 150:02e0a0aed4ec 295 req->cmd_num = 0;
<> 150:02e0a0aed4ec 296 req->data_num = 0;
<> 150:02e0a0aed4ec 297
<> 150:02e0a0aed4ec 298 // Disable and clear the interrupts
<> 150:02e0a0aed4ec 299 i2cm->inten = 0;
<> 150:02e0a0aed4ec 300 i2cm->intfl = i2cm->intfl;
<> 150:02e0a0aed4ec 301
<> 150:02e0a0aed4ec 302 // Start the read
<> 150:02e0a0aed4ec 303 if((error = I2CM_ReadHandler(i2cm, req, i2cm_num)) != E_NO_ERROR) {
<> 150:02e0a0aed4ec 304 I2CM_Recover(i2cm);
<> 150:02e0a0aed4ec 305 I2CM_FreeCallback(i2cm_num, error);
<> 150:02e0a0aed4ec 306 return error;
<> 150:02e0a0aed4ec 307 }
<> 150:02e0a0aed4ec 308
<> 150:02e0a0aed4ec 309 return E_NO_ERROR;
<> 150:02e0a0aed4ec 310 }
<> 150:02e0a0aed4ec 311
<> 150:02e0a0aed4ec 312 /******************************************************************************/
<> 150:02e0a0aed4ec 313 int I2CM_WriteAsync(mxc_i2cm_regs_t *i2cm, i2cm_req_t *req)
<> 150:02e0a0aed4ec 314 {
<> 150:02e0a0aed4ec 315 int i2cm_num, error;
<> 150:02e0a0aed4ec 316
<> 150:02e0a0aed4ec 317 if(req->data == NULL) {
<> 150:02e0a0aed4ec 318 return E_NULL_PTR;
<> 150:02e0a0aed4ec 319 }
<> 150:02e0a0aed4ec 320
<> 150:02e0a0aed4ec 321 // Make sure the I2CM has been initialized
<> 150:02e0a0aed4ec 322 if(i2cm->ctrl == 0) {
<> 150:02e0a0aed4ec 323 return E_UNINITIALIZED;
<> 150:02e0a0aed4ec 324 }
<> 150:02e0a0aed4ec 325
<> 150:02e0a0aed4ec 326 if(!(req->data_len > 0)) {
<> 150:02e0a0aed4ec 327 return E_NO_ERROR;
<> 150:02e0a0aed4ec 328 }
<> 150:02e0a0aed4ec 329
<> 150:02e0a0aed4ec 330 i2cm_num = MXC_I2CM_GET_IDX(i2cm);
<> 150:02e0a0aed4ec 331
<> 150:02e0a0aed4ec 332 // Attempt to register this request
<> 150:02e0a0aed4ec 333 if(mxc_get_lock((uint32_t*)&states[i2cm_num].req, (uint32_t)req) != E_NO_ERROR) {
<> 150:02e0a0aed4ec 334 return E_BUSY;
<> 150:02e0a0aed4ec 335 }
<> 150:02e0a0aed4ec 336
<> 150:02e0a0aed4ec 337 states[i2cm_num].state = I2CM_STATE_WRITING;
<> 150:02e0a0aed4ec 338
<> 150:02e0a0aed4ec 339 // Clear the number of bytes counter
<> 150:02e0a0aed4ec 340 req->cmd_num = 0;
<> 150:02e0a0aed4ec 341 req->data_num = 0;
<> 150:02e0a0aed4ec 342
<> 150:02e0a0aed4ec 343 // Disable and clear the interrupts
<> 150:02e0a0aed4ec 344 i2cm->inten = 0;
<> 150:02e0a0aed4ec 345 i2cm->intfl = i2cm->intfl;
<> 150:02e0a0aed4ec 346
<> 150:02e0a0aed4ec 347 // Start the Write
<> 150:02e0a0aed4ec 348 if((error = I2CM_WriteHandler(i2cm, req, i2cm_num)) != E_NO_ERROR) {
<> 150:02e0a0aed4ec 349 I2CM_Recover(i2cm);
<> 150:02e0a0aed4ec 350 I2CM_FreeCallback(i2cm_num, error);
<> 150:02e0a0aed4ec 351 return error;
<> 150:02e0a0aed4ec 352 }
<> 150:02e0a0aed4ec 353
<> 150:02e0a0aed4ec 354 return E_NO_ERROR;
<> 150:02e0a0aed4ec 355 }
<> 150:02e0a0aed4ec 356
<> 150:02e0a0aed4ec 357 /******************************************************************************/
<> 150:02e0a0aed4ec 358 int I2CM_AbortAsync(i2cm_req_t *req)
<> 150:02e0a0aed4ec 359 {
<> 150:02e0a0aed4ec 360 int i2cm_num;
<> 150:02e0a0aed4ec 361 mxc_i2cm_regs_t *i2cm;
<> 150:02e0a0aed4ec 362
<> 150:02e0a0aed4ec 363 // Find the request, set to NULL
<> 150:02e0a0aed4ec 364 for(i2cm_num = 0; i2cm_num < MXC_CFG_I2CM_INSTANCES; i2cm_num++) {
<> 150:02e0a0aed4ec 365 if(req == states[i2cm_num].req) {
<> 150:02e0a0aed4ec 366
<> 150:02e0a0aed4ec 367 i2cm = MXC_I2CM_GET_I2CM(i2cm_num);
<> 150:02e0a0aed4ec 368 I2CM_Recover(i2cm);
<> 150:02e0a0aed4ec 369 I2CM_FreeCallback(i2cm_num, E_ABORT);
<> 150:02e0a0aed4ec 370
<> 150:02e0a0aed4ec 371 return E_NO_ERROR;
<> 150:02e0a0aed4ec 372 }
<> 150:02e0a0aed4ec 373 }
<> 150:02e0a0aed4ec 374
<> 150:02e0a0aed4ec 375 return E_BAD_PARAM;
<> 150:02e0a0aed4ec 376 }
<> 150:02e0a0aed4ec 377
<> 150:02e0a0aed4ec 378 /******************************************************************************/
<> 150:02e0a0aed4ec 379 void I2CM_Handler(mxc_i2cm_regs_t *i2cm)
<> 150:02e0a0aed4ec 380 {
<> 150:02e0a0aed4ec 381 uint32_t intfl;
<> 150:02e0a0aed4ec 382 int i2cm_num, error;
<> 150:02e0a0aed4ec 383
<> 150:02e0a0aed4ec 384 // Save and clear the interrupts
<> 150:02e0a0aed4ec 385 intfl = i2cm->intfl;
<> 150:02e0a0aed4ec 386 i2cm->intfl = intfl;
<> 150:02e0a0aed4ec 387
<> 150:02e0a0aed4ec 388 // Mask the disabled interrupts
<> 150:02e0a0aed4ec 389 intfl &= i2cm->inten;
<> 150:02e0a0aed4ec 390
<> 150:02e0a0aed4ec 391 i2cm_num = MXC_I2CM_GET_IDX(i2cm);
<> 150:02e0a0aed4ec 392
<> 150:02e0a0aed4ec 393 // Check for errors
<> 150:02e0a0aed4ec 394 if ((intfl & MXC_F_I2CM_INTFL_TX_NACKED) || (intfl & MXC_F_I2CM_INTFL_TX_LOST_ARBITR)) {
<> 150:02e0a0aed4ec 395 I2CM_Recover(i2cm);
<> 150:02e0a0aed4ec 396 I2CM_FreeCallback(i2cm_num, E_COMM_ERR);
<> 150:02e0a0aed4ec 397 return;
<> 150:02e0a0aed4ec 398 }
<> 150:02e0a0aed4ec 399
<> 150:02e0a0aed4ec 400 if(intfl & MXC_F_I2CM_INTFL_TX_TIMEOUT) {
<> 150:02e0a0aed4ec 401 I2CM_Recover(i2cm);
<> 150:02e0a0aed4ec 402 I2CM_FreeCallback(i2cm_num, E_TIME_OUT);
<> 150:02e0a0aed4ec 403 return;
<> 150:02e0a0aed4ec 404 }
<> 150:02e0a0aed4ec 405
<> 150:02e0a0aed4ec 406 // Read or write
<> 150:02e0a0aed4ec 407 if(states[i2cm_num].state == I2CM_STATE_READING) {
<> 150:02e0a0aed4ec 408 if((error = I2CM_ReadHandler(i2cm, states[i2cm_num].req, i2cm_num)) != E_NO_ERROR) {
<> 150:02e0a0aed4ec 409 I2CM_Recover(i2cm);
<> 150:02e0a0aed4ec 410 I2CM_FreeCallback(i2cm_num, error);
<> 150:02e0a0aed4ec 411 return;
<> 150:02e0a0aed4ec 412 }
<> 150:02e0a0aed4ec 413
<> 150:02e0a0aed4ec 414 } else if(states[i2cm_num].state == I2CM_STATE_WRITING) {
<> 150:02e0a0aed4ec 415 if((error = I2CM_WriteHandler(i2cm, states[i2cm_num].req, i2cm_num)) != E_NO_ERROR) {
<> 150:02e0a0aed4ec 416 I2CM_Recover(i2cm);
<> 150:02e0a0aed4ec 417 I2CM_FreeCallback(i2cm_num, error);
<> 150:02e0a0aed4ec 418 return;
<> 150:02e0a0aed4ec 419 }
<> 150:02e0a0aed4ec 420 }
<> 150:02e0a0aed4ec 421
<> 150:02e0a0aed4ec 422 // Done with the transaction
<> 150:02e0a0aed4ec 423 if(intfl & MXC_F_I2CM_INTFL_TX_DONE) {
<> 150:02e0a0aed4ec 424 I2CM_Recover(i2cm);
<> 150:02e0a0aed4ec 425 I2CM_FreeCallback(i2cm_num, E_NO_ERROR);
<> 150:02e0a0aed4ec 426 }
<> 150:02e0a0aed4ec 427
<> 150:02e0a0aed4ec 428 }
<> 150:02e0a0aed4ec 429
<> 150:02e0a0aed4ec 430 /******************************************************************************/
<> 150:02e0a0aed4ec 431 int I2CM_Busy(mxc_i2cm_regs_t *i2cm)
<> 150:02e0a0aed4ec 432 {
<> 150:02e0a0aed4ec 433 // Check to see if there are any ongoing transactions
<> 150:02e0a0aed4ec 434 if((states[MXC_I2CM_GET_IDX(i2cm)].req == NULL) &&
<> 150:02e0a0aed4ec 435 !(i2cm->trans & MXC_F_I2CM_TRANS_TX_IN_PROGRESS)) {
<> 150:02e0a0aed4ec 436
<> 150:02e0a0aed4ec 437 return E_NO_ERROR;
<> 150:02e0a0aed4ec 438 }
<> 150:02e0a0aed4ec 439
<> 150:02e0a0aed4ec 440 return E_BUSY;
<> 150:02e0a0aed4ec 441 }
<> 150:02e0a0aed4ec 442
<> 150:02e0a0aed4ec 443 /******************************************************************************/
<> 150:02e0a0aed4ec 444 int I2CM_PrepForSleep(mxc_i2cm_regs_t *i2cm)
<> 150:02e0a0aed4ec 445 {
<> 150:02e0a0aed4ec 446 if(I2CM_Busy(i2cm) != E_NO_ERROR) {
<> 150:02e0a0aed4ec 447 return E_BUSY;
<> 150:02e0a0aed4ec 448 }
<> 150:02e0a0aed4ec 449
<> 150:02e0a0aed4ec 450 // Disable interrupts
<> 150:02e0a0aed4ec 451 i2cm->inten = 0;
<> 150:02e0a0aed4ec 452 return E_NO_ERROR;
<> 150:02e0a0aed4ec 453 }
<> 150:02e0a0aed4ec 454
<> 150:02e0a0aed4ec 455 /******************************************************************************/
<> 150:02e0a0aed4ec 456 int I2CM_BusCheck(mxc_i2cm_regs_t *i2cm)
<> 150:02e0a0aed4ec 457 {
<> 150:02e0a0aed4ec 458 // If SCL is low, we don't have the bus
<> 150:02e0a0aed4ec 459 if(!(i2cm->bb & MXC_F_I2CM_BB_BB_SCL_IN_VAL)) {
<> 150:02e0a0aed4ec 460 return E_BUSY;
<> 150:02e0a0aed4ec 461 }
<> 150:02e0a0aed4ec 462
<> 150:02e0a0aed4ec 463 // If SDA is low, we don't have the bus
<> 150:02e0a0aed4ec 464 if(!(i2cm->bb & MXC_F_I2CM_BB_BB_SDA_IN_VAL)) {
<> 150:02e0a0aed4ec 465 return E_BUSY;
<> 150:02e0a0aed4ec 466 }
<> 150:02e0a0aed4ec 467
<> 150:02e0a0aed4ec 468 return E_NO_ERROR;
<> 150:02e0a0aed4ec 469 }
<> 150:02e0a0aed4ec 470
<> 150:02e0a0aed4ec 471 /******************************************************************************/
<> 150:02e0a0aed4ec 472 static void I2CM_FreeCallback(int i2cm_num, int error)
<> 150:02e0a0aed4ec 473 {
<> 150:02e0a0aed4ec 474 // Save the request
<> 150:02e0a0aed4ec 475 i2cm_req_t *temp_req = states[i2cm_num].req;
<> 150:02e0a0aed4ec 476
<> 150:02e0a0aed4ec 477 // Unlock this UART to write
<> 150:02e0a0aed4ec 478 mxc_free_lock((uint32_t*)&states[i2cm_num].req);
<> 150:02e0a0aed4ec 479
<> 150:02e0a0aed4ec 480 // Callback if not NULL
<> 150:02e0a0aed4ec 481 if(temp_req->callback != NULL) {
<> 150:02e0a0aed4ec 482 temp_req->callback(temp_req, error);
<> 150:02e0a0aed4ec 483 }
<> 150:02e0a0aed4ec 484 }
<> 150:02e0a0aed4ec 485
<> 150:02e0a0aed4ec 486 /******************************************************************************/
<> 150:02e0a0aed4ec 487 void I2CM_Recover(mxc_i2cm_regs_t *i2cm)
<> 150:02e0a0aed4ec 488 {
<> 150:02e0a0aed4ec 489 // Disable and clear interrupts
<> 150:02e0a0aed4ec 490 i2cm->inten = 0;
<> 150:02e0a0aed4ec 491 i2cm->intfl = i2cm->intfl;
<> 150:02e0a0aed4ec 492 i2cm->ctrl = MXC_F_I2CM_CTRL_MSTR_RESET_EN;
<> 150:02e0a0aed4ec 493 i2cm->ctrl = MXC_F_I2CM_CTRL_TX_FIFO_EN | MXC_F_I2CM_CTRL_RX_FIFO_EN;
<> 150:02e0a0aed4ec 494 }
<> 150:02e0a0aed4ec 495
<> 150:02e0a0aed4ec 496 /******************************************************************************/
<> 150:02e0a0aed4ec 497 int I2CM_WriteTxFifo(mxc_i2cm_regs_t *i2cm, mxc_i2cm_fifo_regs_t *fifo, const uint16_t data)
<> 150:02e0a0aed4ec 498 {
<> 150:02e0a0aed4ec 499 int32_t timeout = MXC_I2CM_TX_TIMEOUT;
<> 150:02e0a0aed4ec 500
<> 150:02e0a0aed4ec 501 // Read the TX FIFO to determine if it's full
<> 150:02e0a0aed4ec 502 do {
<> 150:02e0a0aed4ec 503
<> 150:02e0a0aed4ec 504 // Wait for the TX FIFO to have room and check for errors
<> 150:02e0a0aed4ec 505 if (i2cm->intfl & (MXC_F_I2CM_INTFL_TX_NACKED |
<> 150:02e0a0aed4ec 506 MXC_F_I2CM_INTFL_TX_LOST_ARBITR)) {
<> 150:02e0a0aed4ec 507
<> 150:02e0a0aed4ec 508 return E_COMM_ERR;
<> 150:02e0a0aed4ec 509 }
<> 150:02e0a0aed4ec 510
<> 150:02e0a0aed4ec 511 if((i2cm->intfl & MXC_F_I2CM_INTFL_TX_TIMEOUT) || !timeout--) {
<> 150:02e0a0aed4ec 512 return E_TIME_OUT;
<> 150:02e0a0aed4ec 513 }
<> 150:02e0a0aed4ec 514
<> 150:02e0a0aed4ec 515 } while (fifo->tx);
<> 150:02e0a0aed4ec 516
<> 150:02e0a0aed4ec 517 fifo->tx = data;
<> 150:02e0a0aed4ec 518
<> 150:02e0a0aed4ec 519 return E_NO_ERROR;
<> 150:02e0a0aed4ec 520 }
<> 150:02e0a0aed4ec 521
<> 150:02e0a0aed4ec 522 /******************************************************************************/
<> 150:02e0a0aed4ec 523 int I2CM_TxInProgress(mxc_i2cm_regs_t *i2cm)
<> 150:02e0a0aed4ec 524 {
<> 150:02e0a0aed4ec 525 int32_t timeout = MXC_I2CM_TX_TIMEOUT;
<> 150:02e0a0aed4ec 526
<> 150:02e0a0aed4ec 527 while ((i2cm->trans & MXC_F_I2CM_TRANS_TX_IN_PROGRESS) && --timeout);
<> 150:02e0a0aed4ec 528
<> 150:02e0a0aed4ec 529 if (i2cm->intfl & (MXC_F_I2CM_INTFL_TX_NACKED |
<> 150:02e0a0aed4ec 530 MXC_F_I2CM_INTFL_TX_LOST_ARBITR)) {
<> 150:02e0a0aed4ec 531
<> 150:02e0a0aed4ec 532 I2CM_Recover(i2cm);
<> 150:02e0a0aed4ec 533 return E_COMM_ERR;
<> 150:02e0a0aed4ec 534 }
<> 150:02e0a0aed4ec 535
<> 150:02e0a0aed4ec 536 if((i2cm->intfl & MXC_F_I2CM_INTFL_TX_TIMEOUT) && !timeout--) {
<> 150:02e0a0aed4ec 537 I2CM_Recover(i2cm);
<> 150:02e0a0aed4ec 538 return E_TIME_OUT;
<> 150:02e0a0aed4ec 539 }
<> 150:02e0a0aed4ec 540
<> 150:02e0a0aed4ec 541 return E_NO_ERROR;
<> 150:02e0a0aed4ec 542 }
<> 150:02e0a0aed4ec 543
<> 150:02e0a0aed4ec 544 /******************************************************************************/
<> 150:02e0a0aed4ec 545 int I2CM_Tx(mxc_i2cm_regs_t *i2cm, mxc_i2cm_fifo_regs_t *fifo, uint8_t addr,
<> 150:02e0a0aed4ec 546 const uint8_t *data, uint32_t len, uint8_t stop)
<> 150:02e0a0aed4ec 547 {
<> 150:02e0a0aed4ec 548 uint32_t i;
<> 150:02e0a0aed4ec 549 int error;
<> 150:02e0a0aed4ec 550
<> 150:02e0a0aed4ec 551 // Write the address to the TXFIFO
<> 150:02e0a0aed4ec 552 if((error = I2CM_WriteTxFifo(i2cm, fifo, (MXC_S_I2CM_TRANS_TAG_START | (addr << 1)))) != E_NO_ERROR) {
<> 150:02e0a0aed4ec 553 return error;
<> 150:02e0a0aed4ec 554 }
<> 150:02e0a0aed4ec 555
<> 150:02e0a0aed4ec 556 // Start the transaction if it is not currently ongoing
<> 150:02e0a0aed4ec 557 if (!(i2cm->trans & MXC_F_I2CM_TRANS_TX_IN_PROGRESS)) {
<> 150:02e0a0aed4ec 558 i2cm->trans |= MXC_F_I2CM_TRANS_TX_START;
<> 150:02e0a0aed4ec 559 }
<> 150:02e0a0aed4ec 560
<> 150:02e0a0aed4ec 561 // Fill the FIFO
<> 150:02e0a0aed4ec 562 for (i = 0; i < len; i++) {
<> 150:02e0a0aed4ec 563 if((error = I2CM_WriteTxFifo(i2cm, fifo, (MXC_S_I2CM_TRANS_TAG_TXDATA_ACK | data[i]))) != E_NO_ERROR) {
<> 150:02e0a0aed4ec 564 return error;
<> 150:02e0a0aed4ec 565 }
<> 150:02e0a0aed4ec 566 }
<> 150:02e0a0aed4ec 567
<> 150:02e0a0aed4ec 568 // Send the stop condition
<> 150:02e0a0aed4ec 569 if(stop) {
<> 150:02e0a0aed4ec 570 if ((error = I2CM_WriteTxFifo(i2cm, fifo, MXC_S_I2CM_TRANS_TAG_STOP)) != E_NO_ERROR) {
<> 150:02e0a0aed4ec 571 return error;
<> 150:02e0a0aed4ec 572 }
<> 150:02e0a0aed4ec 573 }
<> 150:02e0a0aed4ec 574
<> 150:02e0a0aed4ec 575 return E_NO_ERROR;
<> 150:02e0a0aed4ec 576 }
<> 150:02e0a0aed4ec 577
<> 150:02e0a0aed4ec 578 /******************************************************************************/
<> 150:02e0a0aed4ec 579 int I2CM_Rx(mxc_i2cm_regs_t *i2cm, mxc_i2cm_fifo_regs_t *fifo, uint8_t addr,
<> 150:02e0a0aed4ec 580 uint8_t *data, uint32_t len)
<> 150:02e0a0aed4ec 581 {
<> 150:02e0a0aed4ec 582 uint32_t i = len;
<> 150:02e0a0aed4ec 583 int32_t timeout;
<> 150:02e0a0aed4ec 584 uint16_t temp;
<> 150:02e0a0aed4ec 585 int error;
<> 150:02e0a0aed4ec 586
<> 150:02e0a0aed4ec 587 // Write the address to the TXFIFO
<> 150:02e0a0aed4ec 588 if((error = I2CM_WriteTxFifo(i2cm, fifo, (MXC_S_I2CM_TRANS_TAG_START |
<> 150:02e0a0aed4ec 589 (addr << 1) | I2CM_READ_BIT))) != E_NO_ERROR) {
<> 150:02e0a0aed4ec 590
<> 150:02e0a0aed4ec 591 return error;
<> 150:02e0a0aed4ec 592 }
<> 150:02e0a0aed4ec 593
<> 150:02e0a0aed4ec 594 // Write to the TXFIFO the number of bytes we want to read
<> 150:02e0a0aed4ec 595 while(i > 256) {
<> 150:02e0a0aed4ec 596 if((error = I2CM_WriteTxFifo(i2cm, fifo, (MXC_S_I2CM_TRANS_TAG_RXDATA_COUNT | 255))) != E_NO_ERROR) {
<> 150:02e0a0aed4ec 597 return error;
<> 150:02e0a0aed4ec 598 }
<> 150:02e0a0aed4ec 599
<> 150:02e0a0aed4ec 600 i -= 256;
<> 150:02e0a0aed4ec 601 }
<> 150:02e0a0aed4ec 602
<> 150:02e0a0aed4ec 603 if(i > 1) {
<> 150:02e0a0aed4ec 604 if((error = I2CM_WriteTxFifo(i2cm, fifo, (MXC_S_I2CM_TRANS_TAG_RXDATA_COUNT | (i-2)))) != E_NO_ERROR) {
<> 150:02e0a0aed4ec 605 return error;
<> 150:02e0a0aed4ec 606 }
<> 150:02e0a0aed4ec 607 }
<> 150:02e0a0aed4ec 608
<> 150:02e0a0aed4ec 609 // Start the transaction if it is not currently ongoing
<> 150:02e0a0aed4ec 610 if (!(i2cm->trans & MXC_F_I2CM_TRANS_TX_IN_PROGRESS)) {
<> 150:02e0a0aed4ec 611 i2cm->trans |= MXC_F_I2CM_TRANS_TX_START;
<> 150:02e0a0aed4ec 612 }
<> 150:02e0a0aed4ec 613
<> 150:02e0a0aed4ec 614
<> 150:02e0a0aed4ec 615 // NACK the last read byte
<> 150:02e0a0aed4ec 616 if((error = I2CM_WriteTxFifo(i2cm, fifo, (MXC_S_I2CM_TRANS_TAG_RXDATA_NACK))) != E_NO_ERROR) {
<> 150:02e0a0aed4ec 617 return error;
<> 150:02e0a0aed4ec 618 }
<> 150:02e0a0aed4ec 619
<> 150:02e0a0aed4ec 620 // Send the stop condition
<> 150:02e0a0aed4ec 621 if ((error = I2CM_WriteTxFifo(i2cm, fifo, MXC_S_I2CM_TRANS_TAG_STOP)) != E_NO_ERROR) {
<> 150:02e0a0aed4ec 622 return error;
<> 150:02e0a0aed4ec 623 }
<> 150:02e0a0aed4ec 624
<> 150:02e0a0aed4ec 625 // Get the data from the RX FIFO
<> 150:02e0a0aed4ec 626 i = 0;
<> 150:02e0a0aed4ec 627 while (i < len) {
<> 150:02e0a0aed4ec 628
<> 150:02e0a0aed4ec 629 // Wait for there to be data in the RX FIFO
<> 150:02e0a0aed4ec 630 timeout = MXC_I2CM_RX_TIMEOUT;
<> 150:02e0a0aed4ec 631 while (!(i2cm->intfl & MXC_F_I2CM_INTFL_RX_FIFO_NOT_EMPTY) &&
<> 150:02e0a0aed4ec 632 ((i2cm->bb & MXC_F_I2CM_BB_RX_FIFO_CNT) == 0)) {
<> 150:02e0a0aed4ec 633
<> 150:02e0a0aed4ec 634 if((timeout-- < 0) || (i2cm->trans & MXC_F_I2CM_TRANS_TX_TIMEOUT)) {
<> 150:02e0a0aed4ec 635 return E_TIME_OUT;
<> 150:02e0a0aed4ec 636 }
<> 150:02e0a0aed4ec 637
<> 150:02e0a0aed4ec 638 if (i2cm->trans & (MXC_F_I2CM_TRANS_TX_LOST_ARBITR | MXC_F_I2CM_TRANS_TX_NACKED)) {
<> 150:02e0a0aed4ec 639 return E_COMM_ERR;
<> 150:02e0a0aed4ec 640 }
<> 150:02e0a0aed4ec 641 }
<> 150:02e0a0aed4ec 642 i2cm->intfl = MXC_F_I2CM_INTFL_RX_FIFO_NOT_EMPTY;
<> 150:02e0a0aed4ec 643
<> 150:02e0a0aed4ec 644 // Save the data from the RX FIFO
<> 150:02e0a0aed4ec 645 temp = fifo->rx;
<> 150:02e0a0aed4ec 646 if (temp & MXC_S_I2CM_RSTLS_TAG_EMPTY) {
<> 150:02e0a0aed4ec 647 continue;
<> 150:02e0a0aed4ec 648 }
<> 150:02e0a0aed4ec 649 data[i++] = (uint8_t)temp;
<> 150:02e0a0aed4ec 650 }
<> 150:02e0a0aed4ec 651
<> 150:02e0a0aed4ec 652 return E_NO_ERROR;
<> 150:02e0a0aed4ec 653 }
<> 150:02e0a0aed4ec 654
<> 150:02e0a0aed4ec 655 /******************************************************************************/
<> 150:02e0a0aed4ec 656 static int I2CM_CmdHandler(mxc_i2cm_regs_t *i2cm, mxc_i2cm_fifo_regs_t *fifo, i2cm_req_t *req)
<> 150:02e0a0aed4ec 657 {
<> 150:02e0a0aed4ec 658 int error;
<> 150:02e0a0aed4ec 659
<> 150:02e0a0aed4ec 660 // Start of the command
<> 150:02e0a0aed4ec 661 if(req->cmd_num == 0) {
<> 150:02e0a0aed4ec 662
<> 150:02e0a0aed4ec 663 // Write the address to the TXFIFO
<> 150:02e0a0aed4ec 664 if((error = I2CM_WriteTxFifo(i2cm, fifo, (MXC_S_I2CM_TRANS_TAG_START | (req->addr << 1)))) != E_NO_ERROR) {
<> 150:02e0a0aed4ec 665 return error;
<> 150:02e0a0aed4ec 666 }
<> 150:02e0a0aed4ec 667
<> 150:02e0a0aed4ec 668 // Start the transaction if it is not currently ongoing
<> 150:02e0a0aed4ec 669 if (!(i2cm->trans & MXC_F_I2CM_TRANS_TX_IN_PROGRESS)) {
<> 150:02e0a0aed4ec 670 i2cm->trans |= MXC_F_I2CM_TRANS_TX_START;
<> 150:02e0a0aed4ec 671 }
<> 150:02e0a0aed4ec 672 }
<> 150:02e0a0aed4ec 673
<> 150:02e0a0aed4ec 674 // Write to the FIFO until it is full or we run out of command bytes
<> 150:02e0a0aed4ec 675 while((req->cmd_num < req->cmd_len) && (!fifo->tx)) {
<> 150:02e0a0aed4ec 676 fifo->tx = MXC_S_I2CM_TRANS_TAG_TXDATA_ACK | req->cmd_data[req->cmd_num++];
<> 150:02e0a0aed4ec 677 }
<> 150:02e0a0aed4ec 678
<> 150:02e0a0aed4ec 679 return E_NO_ERROR;
<> 150:02e0a0aed4ec 680 }
<> 150:02e0a0aed4ec 681
<> 150:02e0a0aed4ec 682 /******************************************************************************/
<> 150:02e0a0aed4ec 683 static int I2CM_ReadHandler(mxc_i2cm_regs_t *i2cm, i2cm_req_t *req, int i2cm_num)
<> 150:02e0a0aed4ec 684 {
<> 150:02e0a0aed4ec 685 int error, cmd_remain, data_remain;
<> 150:02e0a0aed4ec 686 uint16_t data;
<> 150:02e0a0aed4ec 687 uint32_t temp_len, inten;
<> 150:02e0a0aed4ec 688 mxc_i2cm_fifo_regs_t *fifo;
<> 150:02e0a0aed4ec 689
<> 150:02e0a0aed4ec 690 // Get the FIFO pointer for this I2CM
<> 150:02e0a0aed4ec 691 fifo = MXC_I2CM_GET_FIFO(i2cm_num);
<> 150:02e0a0aed4ec 692
<> 150:02e0a0aed4ec 693 cmd_remain = req->cmd_len - req->cmd_num;
<> 150:02e0a0aed4ec 694 data_remain = req->data_len - req->data_num;
<> 150:02e0a0aed4ec 695
<> 150:02e0a0aed4ec 696 // Process the command portion
<> 150:02e0a0aed4ec 697 if((cmd_remain) && (req->cmd_data != NULL)) {
<> 150:02e0a0aed4ec 698 if((error = I2CM_CmdHandler(i2cm, fifo, req)) != E_NO_ERROR) {
<> 150:02e0a0aed4ec 699 return error;
<> 150:02e0a0aed4ec 700 }
<> 150:02e0a0aed4ec 701
<> 150:02e0a0aed4ec 702 cmd_remain = req->cmd_len - req->cmd_num;
<> 150:02e0a0aed4ec 703 }
<> 150:02e0a0aed4ec 704
<> 150:02e0a0aed4ec 705 // Process the data portion
<> 150:02e0a0aed4ec 706 if((cmd_remain == 0) && (data_remain)) {
<> 150:02e0a0aed4ec 707
<> 150:02e0a0aed4ec 708 // Save the data from the RXFIFO
<> 150:02e0a0aed4ec 709 data = fifo->rx;
<> 150:02e0a0aed4ec 710 while((req->data_num < req->data_len) && !(data & MXC_S_I2CM_RSTLS_TAG_EMPTY)) {
<> 150:02e0a0aed4ec 711 req->data[req->data_num++] = data;
<> 150:02e0a0aed4ec 712 data = fifo->rx;
<> 150:02e0a0aed4ec 713 }
<> 150:02e0a0aed4ec 714
<> 150:02e0a0aed4ec 715 // Start of the data portion
<> 150:02e0a0aed4ec 716 if(req->data_num == 0) {
<> 150:02e0a0aed4ec 717
<> 150:02e0a0aed4ec 718 temp_len = req->data_len;
<> 150:02e0a0aed4ec 719
<> 150:02e0a0aed4ec 720 // Write the address to the TXFIFO
<> 150:02e0a0aed4ec 721 if((error = I2CM_WriteTxFifo(i2cm, fifo, (MXC_S_I2CM_TRANS_TAG_START |
<> 150:02e0a0aed4ec 722 (req->addr << 1) | I2CM_READ_BIT))) != E_NO_ERROR) {
<> 150:02e0a0aed4ec 723
<> 150:02e0a0aed4ec 724 return error;
<> 150:02e0a0aed4ec 725 }
<> 150:02e0a0aed4ec 726
<> 150:02e0a0aed4ec 727 // Write to the TXFIFO the number of bytes we want to read
<> 150:02e0a0aed4ec 728 while(temp_len > 256) {
<> 150:02e0a0aed4ec 729 if((error = I2CM_WriteTxFifo(i2cm, fifo, (MXC_S_I2CM_TRANS_TAG_RXDATA_COUNT | 255))) != E_NO_ERROR) {
<> 150:02e0a0aed4ec 730 return error;
<> 150:02e0a0aed4ec 731 }
<> 150:02e0a0aed4ec 732
<> 150:02e0a0aed4ec 733 temp_len -= 256;
<> 150:02e0a0aed4ec 734 }
<> 150:02e0a0aed4ec 735
<> 150:02e0a0aed4ec 736 if(temp_len > 1) {
<> 150:02e0a0aed4ec 737 if((error = I2CM_WriteTxFifo(i2cm, fifo, (MXC_S_I2CM_TRANS_TAG_RXDATA_COUNT | (temp_len-2)))) != E_NO_ERROR) {
<> 150:02e0a0aed4ec 738 return error;
<> 150:02e0a0aed4ec 739 }
<> 150:02e0a0aed4ec 740 }
<> 150:02e0a0aed4ec 741
<> 150:02e0a0aed4ec 742 // Start the transaction if it is not currently ongoing
<> 150:02e0a0aed4ec 743 if (!(i2cm->trans & MXC_F_I2CM_TRANS_TX_IN_PROGRESS)) {
<> 150:02e0a0aed4ec 744 i2cm->trans |= MXC_F_I2CM_TRANS_TX_START;
<> 150:02e0a0aed4ec 745 }
<> 150:02e0a0aed4ec 746
<> 150:02e0a0aed4ec 747 // NACK the last read byte
<> 150:02e0a0aed4ec 748 if((error = I2CM_WriteTxFifo(i2cm, fifo, (MXC_S_I2CM_TRANS_TAG_RXDATA_NACK))) != E_NO_ERROR) {
<> 150:02e0a0aed4ec 749 return error;
<> 150:02e0a0aed4ec 750 }
<> 150:02e0a0aed4ec 751
<> 150:02e0a0aed4ec 752 // Send the stop condition
<> 150:02e0a0aed4ec 753 if ((error = I2CM_WriteTxFifo(i2cm, fifo, MXC_S_I2CM_TRANS_TAG_STOP)) != E_NO_ERROR) {
<> 150:02e0a0aed4ec 754 return error;
<> 150:02e0a0aed4ec 755 }
<> 150:02e0a0aed4ec 756 }
<> 150:02e0a0aed4ec 757 }
<> 150:02e0a0aed4ec 758
<> 150:02e0a0aed4ec 759 // Enable the required interrupts
<> 150:02e0a0aed4ec 760 inten = MXC_F_I2CM_INTEN_TX_DONE | MXC_F_I2CM_INTEN_TX_NACKED |
<> 150:02e0a0aed4ec 761 MXC_F_I2CM_INTEN_TX_LOST_ARBITR | MXC_F_I2CM_INTEN_TX_TIMEOUT;
<> 150:02e0a0aed4ec 762
<> 150:02e0a0aed4ec 763 if (cmd_remain) {
<> 150:02e0a0aed4ec 764 inten |= (MXC_F_I2CM_INTEN_TX_FIFO_EMPTY | MXC_F_I2CM_INTEN_TX_FIFO_3Q_EMPTY);
<> 150:02e0a0aed4ec 765 }
<> 150:02e0a0aed4ec 766
<> 150:02e0a0aed4ec 767 data_remain = req->data_len - req->data_num;
<> 150:02e0a0aed4ec 768 if (data_remain > I2CM_FIFO_DEPTH_3Q) {
<> 150:02e0a0aed4ec 769 inten |= MXC_F_I2CM_INTEN_RX_FIFO_3Q_FULL;
<> 150:02e0a0aed4ec 770
<> 150:02e0a0aed4ec 771 } else if (data_remain > I2CM_FIFO_DEPTH_2Q) {
<> 150:02e0a0aed4ec 772 inten |= MXC_F_I2CM_INTEN_RX_FIFO_2Q_FULL;
<> 150:02e0a0aed4ec 773
<> 150:02e0a0aed4ec 774 } else if (data_remain > 0) {
<> 150:02e0a0aed4ec 775 inten |= MXC_F_I2CM_INTEN_RX_FIFO_NOT_EMPTY;
<> 150:02e0a0aed4ec 776 }
<> 150:02e0a0aed4ec 777
<> 150:02e0a0aed4ec 778 i2cm->inten = inten;
<> 150:02e0a0aed4ec 779
<> 150:02e0a0aed4ec 780 return E_NO_ERROR;
<> 150:02e0a0aed4ec 781 }
<> 150:02e0a0aed4ec 782
<> 150:02e0a0aed4ec 783 /******************************************************************************/
<> 150:02e0a0aed4ec 784 static int I2CM_WriteHandler(mxc_i2cm_regs_t *i2cm, i2cm_req_t *req, int i2cm_num)
<> 150:02e0a0aed4ec 785 {
<> 150:02e0a0aed4ec 786 int error, cmd_remain, data_remain;
<> 150:02e0a0aed4ec 787 uint32_t inten;
<> 150:02e0a0aed4ec 788 mxc_i2cm_fifo_regs_t *fifo;
<> 150:02e0a0aed4ec 789
<> 150:02e0a0aed4ec 790 // Get the FIFO pointer for this I2CM
<> 150:02e0a0aed4ec 791 fifo = MXC_I2CM_GET_FIFO(i2cm_num);
<> 150:02e0a0aed4ec 792
<> 150:02e0a0aed4ec 793 cmd_remain = req->cmd_len - req->cmd_num;
<> 150:02e0a0aed4ec 794 data_remain = req->data_len - req->data_num;
<> 150:02e0a0aed4ec 795
<> 150:02e0a0aed4ec 796 // Process the command portion
<> 150:02e0a0aed4ec 797 if((cmd_remain) && (req->cmd_data != NULL)) {
<> 150:02e0a0aed4ec 798 if((error = I2CM_CmdHandler(i2cm, fifo, req)) != E_NO_ERROR) {
<> 150:02e0a0aed4ec 799 return error;
<> 150:02e0a0aed4ec 800 }
<> 150:02e0a0aed4ec 801
<> 150:02e0a0aed4ec 802 cmd_remain = req->cmd_len - req->cmd_num;
<> 150:02e0a0aed4ec 803 }
<> 150:02e0a0aed4ec 804
<> 150:02e0a0aed4ec 805 // Process the data portion
<> 150:02e0a0aed4ec 806 if((cmd_remain == 0) && (data_remain)) {
<> 150:02e0a0aed4ec 807
<> 150:02e0a0aed4ec 808 // Start of the data portion
<> 150:02e0a0aed4ec 809 if(req->data_num == 0) {
<> 150:02e0a0aed4ec 810
<> 150:02e0a0aed4ec 811 // Write the address to the TXFIFO
<> 150:02e0a0aed4ec 812 if((error = I2CM_WriteTxFifo(i2cm, fifo, (MXC_S_I2CM_TRANS_TAG_START |
<> 150:02e0a0aed4ec 813 (req->addr << 1)))) != E_NO_ERROR) {
<> 150:02e0a0aed4ec 814
<> 150:02e0a0aed4ec 815 return error;
<> 150:02e0a0aed4ec 816 }
<> 150:02e0a0aed4ec 817
<> 150:02e0a0aed4ec 818 // Start the transaction if it is not currently ongoing
<> 150:02e0a0aed4ec 819 if (!(i2cm->trans & MXC_F_I2CM_TRANS_TX_IN_PROGRESS)) {
<> 150:02e0a0aed4ec 820 i2cm->trans |= MXC_F_I2CM_TRANS_TX_START;
<> 150:02e0a0aed4ec 821 }
<> 150:02e0a0aed4ec 822 }
<> 150:02e0a0aed4ec 823
<> 150:02e0a0aed4ec 824 // Write bytes to the FIFO until it's full or we run out of bytes
<> 150:02e0a0aed4ec 825 while(req->data_num < req->data_len) {
<> 150:02e0a0aed4ec 826 fifo->tx = MXC_S_I2CM_TRANS_TAG_TXDATA_ACK | req->data[req->data_num++];
<> 150:02e0a0aed4ec 827 }
<> 150:02e0a0aed4ec 828
<> 150:02e0a0aed4ec 829 // Send the stop condition
<> 150:02e0a0aed4ec 830 if ((error = I2CM_WriteTxFifo(i2cm, fifo, MXC_S_I2CM_TRANS_TAG_STOP)) != E_NO_ERROR) {
<> 150:02e0a0aed4ec 831 return error;
<> 150:02e0a0aed4ec 832 }
<> 150:02e0a0aed4ec 833 }
<> 150:02e0a0aed4ec 834
<> 150:02e0a0aed4ec 835 // Enable the required interrupts
<> 150:02e0a0aed4ec 836 data_remain = req->data_len - req->data_num;
<> 150:02e0a0aed4ec 837 inten = MXC_F_I2CM_INTEN_TX_DONE | MXC_F_I2CM_INTEN_TX_NACKED |
<> 150:02e0a0aed4ec 838 MXC_F_I2CM_INTEN_TX_LOST_ARBITR | MXC_F_I2CM_INTEN_TX_TIMEOUT;
<> 150:02e0a0aed4ec 839
<> 150:02e0a0aed4ec 840 if(data_remain || cmd_remain) {
<> 150:02e0a0aed4ec 841 inten |= (MXC_F_I2CM_INTEN_TX_FIFO_EMPTY | MXC_F_I2CM_INTEN_TX_FIFO_3Q_EMPTY);
<> 150:02e0a0aed4ec 842 }
<> 150:02e0a0aed4ec 843 i2cm->inten = inten;
<> 150:02e0a0aed4ec 844
<> 150:02e0a0aed4ec 845 return E_NO_ERROR;
<> 150:02e0a0aed4ec 846 }
<> 150:02e0a0aed4ec 847
<> 150:02e0a0aed4ec 848 int I2CM_SetFrequency(mxc_i2cm_regs_t *i2cm, int speed)
<> 150:02e0a0aed4ec 849 {
<> 150:02e0a0aed4ec 850 // Speed converted into Khz
<> 150:02e0a0aed4ec 851 float i2cSpeed = speed / 1000.0f;
<> 150:02e0a0aed4ec 852 //get clk speed into MHz
<> 150:02e0a0aed4ec 853 int sClk = SYS_I2CM_GetFreq(i2cm) / 1000000;
<> 150:02e0a0aed4ec 854 // duty cycle of .67
<> 150:02e0a0aed4ec 855 float dc = 2.0f / 3.0f;
<> 150:02e0a0aed4ec 856 //Hold Time
<> 150:02e0a0aed4ec 857 float hold = (100.0f / i2cSpeed);
<> 150:02e0a0aed4ec 858 int riseTime;
<> 150:02e0a0aed4ec 859 //max rise time based on speed according to the I2C specs
<> 150:02e0a0aed4ec 860 if (i2cSpeed <= 100) {
<> 150:02e0a0aed4ec 861 riseTime = 1000;
<> 150:02e0a0aed4ec 862 } else if (i2cSpeed <= 400) {
<> 150:02e0a0aed4ec 863 riseTime = 300;
<> 150:02e0a0aed4ec 864 } else if (i2cSpeed <= 1000) {
<> 150:02e0a0aed4ec 865 riseTime = 120;
<> 150:02e0a0aed4ec 866 } else {
<> 150:02e0a0aed4ec 867 return E_NOT_SUPPORTED;
<> 150:02e0a0aed4ec 868 }
<> 150:02e0a0aed4ec 869 // Clock cycles to delay
<> 150:02e0a0aed4ec 870 int latency = 4;
<> 150:02e0a0aed4ec 871 int filtDev, sclHi, sclLow;
<> 150:02e0a0aed4ec 872 filtDev = (hold * sClk) / 2;
<> 150:02e0a0aed4ec 873 sclHi = (((dc * sClk * 1000.0f / i2cSpeed) - (((2.5f * filtDev) + (riseTime / 1000.0f * sClk) + latency) * (1.0f + dc))) / (1.0f + dc));
<> 150:02e0a0aed4ec 874 sclLow = ((sClk * 1000.0f / i2cSpeed) - (2.5f * filtDev) - (riseTime / 1000.0f * sClk) - latency - sclHi);
<> 150:02e0a0aed4ec 875
<> 150:02e0a0aed4ec 876 i2cm->fs_clk_div = ((filtDev << MXC_F_I2CM_FS_CLK_DIV_FS_FILTER_CLK_DIV_POS) |
<> 150:02e0a0aed4ec 877 (sclHi << MXC_F_I2CM_FS_CLK_DIV_FS_SCL_HI_CNT_POS) |
<> 150:02e0a0aed4ec 878 (sclLow << MXC_F_I2CM_FS_CLK_DIV_FS_SCL_LO_CNT_POS));
<> 150:02e0a0aed4ec 879 return E_NO_ERROR;
<> 150:02e0a0aed4ec 880 }