/* * Copyright (c) 2011-2012, Freescale Semiconductor, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * o Redistributions of source code must retain the above copyright notice, this list * of conditions and the following disclaimer. * * o Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * * o Neither the name of Freescale Semiconductor, Inc. nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __IMX_I2C_H__ #define __IMX_I2C_H__ #include "sdk_types.h" //! @addtogroup diag_i2c //! @{ //////////////////////////////////////////////////////////////////////////////// // Definitions //////////////////////////////////////////////////////////////////////////////// //! @brief Read/write address bits //! //! Bit 0 of the i2c device address cycle to indicate r/w. 0 is for write, 1 is for read. enum _i2c_rq { I2C_WRITE = 0, I2C_READ = 1 }; //! @brief I2C Error Codes enum _i2c_err { ERR_TX = -1, ERR_RX = -2, ERR_ARB_LOST = -3, ERR_NO_ACK = -4, ERR_XFER = -5, ERR_RX_ACK = -6, ERR_NO_ACK_ON_START = -7, ERR_INVALID_REQUEST = -8 }; //! Default slave address used for the MX6. enum _i2c_slave_id { IMX6_DEFAULT_SLAVE_ID = 0x60 }; //! @brief Info required to talk to an I2C device. //! //! Pairs an I2C port number with a device address. //! //! While the device address is often fixed and known in advance by the driver, //! some devices have configurable addresses that can be changed with pin //! settings. Thus, the same device may have different adresses on different //! boards depending on how these pins are tied. //! //! Note that the @a address member's value is @i not pre-shifted. The 7-bit //! address is right aligned within the byte, and the top bit is always set to 0. typedef struct i2c_device_info { uint8_t port; //!< I2C controller instance to which the device is connected. Starts at 1. uint8_t address; //!< I2C device address in lower 7 bits. uint32_t freq; //!< Maximum transfer speed in bits per second. } i2c_device_info_t; /*! * @brief An I2C transfer descriptor. * * To perform an I2C transfer, the caller first fills in an instance of this struct. Then * i2c_xfer() is called, passing a pointer to the #imx_i2c_request_t struct. * * @a ctl_addr should be set to either a valid controller instance number from 1 through * the number of I2C instances on the chip, or the base address of the controller. * * If @a device is set to a non-NULL value, it is a pointer to an #i2c_device_info_t struct * to use instead of the @a ctl_addr and @a dev_addr members of this struct. */ typedef struct imx_i2c_request { uint32_t ctl_addr; //!< Either the I2C controller base address or instance number starting at 1. uint32_t dev_addr; //!< The I2C device address. uint32_t reg_addr; //!< The register address within the target device. uint32_t reg_addr_sz; //!< Number of bytes for the address of I2C device register. uint8_t *buffer; //!< Buffer to hold the data. uint32_t buffer_sz; //!< The number of bytes for read/write. int32_t (*slave_receive) (const struct imx_i2c_request *rq); //!< Function for slave to receive data from master. int32_t (*slave_transmit) (const struct imx_i2c_request *rq); //!< Function for slave to transmit data to master. const i2c_device_info_t * device; //!< Optional pointer to device info struct. Overrides @a ctl_addr and @a dev_addr if set. } imx_i2c_request_t; //////////////////////////////////////////////////////////////////////////////// // API //////////////////////////////////////////////////////////////////////////////// #if defined(__cplusplus) extern "C" { #endif /*! * @brief Initialize the I2C module * * Mainly enable the I2C clock, module itself and the I2C clock prescaler. * * @param base Either the base address of I2C module or the module's instance number. (also assigned for I2Cx_CLK) * @param baud The desired data rate in bits per second. * * @return 0 if successful; non-zero otherwise */ int i2c_init(uint32_t base, uint32_t baud); /*! * @brief Perform a single I2C transfer in the selected direction. * * This is a rather simple function that can be used for most I2C devices. * * Common steps for both READ and WRITE: * - step 1: issue start signal * - step 2: put I2C device addr on the bus (always 1 byte write. the dir always I2C_WRITE) * - step 3: offset of the I2C device write (offset within the device. can be 1-4 bytes) * * For READ: * - step 4: do repeat-start * - step 5: send slave address again, but indicate a READ operation by setting LSB bit * - Step 6: change to receive mode * - Step 7: dummy read * - Step 8: reading * * For WRITE: * - Step 4: do data write * - Step 5: generate STOP by clearing MSTA bit * * @param rq Pointer to #imx_i2c_request_t. * @param dir #I2C_READ or #I2C_WRITE * * @return 0 on success; non-zero otherwise */ int i2c_xfer(const imx_i2c_request_t *rq, int dir); /*! * @brief Perform I2C read transfer. * * @param rq Pointer to #imx_i2c_request_t. */ int i2c_read(const imx_i2c_request_t *rq); /*! * @brief Perform I2C write transfer. * * @param rq Pointer to #imx_i2c_request_t. */ int i2c_write(const imx_i2c_request_t *rq); /*! * @brief I2C handler for the slave mode. * * The function is based on the flow chart for typical I2C polling routine described in the * I2C controller chapter of the reference manual. * * @param rq Pointer to #imx_i2c_request_t. */ void i2c_slave_handler(const imx_i2c_request_t *rq); /*! * @brief Handle the I2C transfers in slave mode. * * The slave mode behaves like any device with g_addr_cycle of address + g_data_cycle of data. * Master read = * START - SLAVE_ID/W - ACK - MEM_ADDR - ACK - START - SLAVE_ID/R - ACK - DATAx - NACK - STOP * * Example for a 16-bit address access: * - 1st IRQ - receive the slave address and Write flag from master. * - 2nd IRQ - receive the lower byte of the requested 16-bit address. * - 3rd IRQ - receive the higher byte of the requested 16-bit address. * - 4th IRQ - receive the slave address and Read flag from master. * - 5th and next IRQ - transmit the data as long as NACK and STOP is not asserted. * * Master write = * START - SLAVE_ID/W - ACK - MEM_ADDR - ACK - DATAx - NACK - STOP * * - 1st IRQ - receive the slave address and Write flag from master. * - 2nd IRQ - receive the lower byte of the requested 16-bit address. * - 3rd IRQ - receive the higher byte of the requested 16-bit address. * - 4th and next IRQ - receive the data as long STOP is not asserted. * * @param port Pointer to the I2C module structure. * @param rq Pointer to #imx_i2c_request_t. */ void i2c_slave_xfer(imx_i2c_request_t *rq); //////////////////////////////////////////////////////////////////////////////// // Board support //////////////////////////////////////////////////////////////////////////////// //! @name Board support functions //! //! These functions are called by the driver in order to factor out board //! specific functionality. They must be defined by the board support //! library or the application. //@{ //! @brief Configure IOMUX for the I2C driver. void i2c_iomux_config(int instance); //@} #if defined(__cplusplus) } #endif //! @} #endif /* __IMX_I2C_H__ */ //////////////////////////////////////////////////////////////////////////////// // EOF ////////////////////////////////////////////////////////////////////////////////