diff options
Diffstat (limited to 'c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/src/hwmgr/alt_i2c.c')
-rw-r--r-- | c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/src/hwmgr/alt_i2c.c | 2004 |
1 files changed, 0 insertions, 2004 deletions
diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/src/hwmgr/alt_i2c.c b/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/src/hwmgr/alt_i2c.c deleted file mode 100644 index b6279a7938..0000000000 --- a/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/src/hwmgr/alt_i2c.c +++ /dev/null @@ -1,2004 +0,0 @@ -/****************************************************************************** - * - * Copyright 2013 Altera Corporation. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. 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. - * - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "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 AUTHOR 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. - * - ******************************************************************************/ - -#include <bsp/alt_i2c.h> -#include <bsp/alt_reset_manager.h> -#include <stdio.h> - -///// - -// NOTE: To enable debugging output, delete the next line and uncomment the -// line after. -#define dprintf(...) -// #define dprintf(fmt, ...) printf(fmt, ##__VA_ARGS__) - -///// - -#define MIN(a, b) ((a) > (b) ? (b) : (a)) - -///// - -// Timeout for reset manager -#define ALT_I2C_RESET_TMO_INIT 8192 -// Timeout for disable device -#define ALT_I2C_MAX_T_POLL_COUNT 8192 -// Timeout for waiting interrupt -#define ALT_I2C_TMO_WAITER 2500000 - -// Min frequency during standard speed -#define ALT_I2C_SS_MIN_SPEED 8000 -// Max frequency during standard speed -#define ALT_I2C_SS_MAX_SPEED 100000 -// Min frequency during fast speed -#define ALT_I2C_FS_MIN_SPEED 100000 -// Max frequency during fast speed -#define ALT_I2C_FS_MAX_SPEED 400000 -// Default spike suppression limit during standard speed -#define ALT_I2C_SS_DEFAULT_SPKLEN 11 -// Default spike suppression limit during fast speed -#define ALT_I2C_FS_DEFAULT_SPKLEN 4 - -// Diff between SCL LCNT and SCL HCNT -#define ALT_I2C_DIFF_LCNT_HCNT 70 - -// Reserved address from 0x00 to 0x07 -#define ALT_I2C_SLV_RESERVE_ADDR_S_1 0x00 -#define ALT_I2C_SLV_RESERVE_ADDR_F_1 0x07 -// Reserved address from 0x78 to 0x7F -#define ALT_I2C_SLV_RESERVE_ADDR_S_2 0x78 -#define ALT_I2C_SLV_RESERVE_ADDR_F_2 0x7F - -static ALT_STATUS_CODE alt_i2c_is_enabled_helper(ALT_I2C_DEV_t * i2c_dev); - -// -// Check whether i2c space is correct. -// -static ALT_STATUS_CODE alt_i2c_checking(ALT_I2C_DEV_t * i2c_dev) -{ - if ( (i2c_dev->location != (void *)ALT_I2C_I2C0) - && (i2c_dev->location != (void *)ALT_I2C_I2C1) - && (i2c_dev->location != (void *)ALT_I2C_I2C2) - && (i2c_dev->location != (void *)ALT_I2C_I2C3)) - { - // Incorrect device - return ALT_E_FALSE; - } - - // Reset i2c module - return ALT_E_TRUE; -} - -static ALT_STATUS_CODE alt_i2c_rstmgr_set(ALT_I2C_DEV_t * i2c_dev) -{ - uint32_t rst_mask = ALT_RSTMGR_PERMODRST_I2C0_SET_MSK; - - // Assert the appropriate I2C module reset signal via the Reset Manager Peripheral Reset register. - switch ((ALT_I2C_CTLR_t)i2c_dev->location) - { - case ALT_I2C_I2C0: - rst_mask = ALT_RSTMGR_PERMODRST_I2C0_SET_MSK; - break; - case ALT_I2C_I2C1: - rst_mask = ALT_RSTMGR_PERMODRST_I2C1_SET_MSK; - break; - case ALT_I2C_I2C2: - rst_mask = ALT_RSTMGR_PERMODRST_I2C2_SET_MSK; - break; - case ALT_I2C_I2C3: - rst_mask = ALT_RSTMGR_PERMODRST_I2C3_SET_MSK; - break; - default: - return ALT_E_BAD_ARG; - } - - alt_setbits_word(ALT_RSTMGR_PERMODRST_ADDR, rst_mask); - - return ALT_E_SUCCESS; -} - -// -// Reset i2c module by reset manager -// -static ALT_STATUS_CODE alt_i2c_rstmgr_strobe(ALT_I2C_DEV_t * i2c_dev) -{ - uint32_t rst_mask = ALT_RSTMGR_PERMODRST_I2C0_SET_MSK; - - // Assert the appropriate I2C module reset signal via the Reset Manager Peripheral Reset register. - switch ((ALT_I2C_CTLR_t)i2c_dev->location) - { - case ALT_I2C_I2C0: - rst_mask = ALT_RSTMGR_PERMODRST_I2C0_SET_MSK; - break; - case ALT_I2C_I2C1: - rst_mask = ALT_RSTMGR_PERMODRST_I2C1_SET_MSK; - break; - case ALT_I2C_I2C2: - rst_mask = ALT_RSTMGR_PERMODRST_I2C2_SET_MSK; - break; - case ALT_I2C_I2C3: - rst_mask = ALT_RSTMGR_PERMODRST_I2C3_SET_MSK; - break; - default: - return ALT_E_BAD_ARG; - } - - alt_setbits_word(ALT_RSTMGR_PERMODRST_ADDR, rst_mask); - - volatile uint32_t timeout = ALT_I2C_RESET_TMO_INIT; - - // Wait while i2c modure is reseting - while (--timeout) - ; - - // Deassert the appropriate I2C module reset signal via the Reset Manager Peripheral Reset register. - alt_clrbits_word(ALT_RSTMGR_PERMODRST_ADDR, rst_mask); - - return ALT_E_SUCCESS; -} - -// -// Initialize the specified I2C controller instance for use and return a device -// handle referencing it. -// -ALT_STATUS_CODE alt_i2c_init(const ALT_I2C_CTLR_t i2c, - ALT_I2C_DEV_t * i2c_dev) -{ - // Save i2c start address to the instance - i2c_dev->location = (void *)i2c; - - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - if (alt_clk_is_enabled(ALT_CLK_L4_SP) != ALT_E_TRUE) - { - return ALT_E_BAD_CLK; - } - - ///// - - ALT_STATUS_CODE status = ALT_E_SUCCESS; - - if (status == ALT_E_SUCCESS) - { - status = alt_clk_freq_get(ALT_CLK_L4_SP, &i2c_dev->clock_freq); - } - - // Reset i2c module - if (status == ALT_E_SUCCESS) - { - status = alt_i2c_reset(i2c_dev); - } - - return status; -} - -// -// Reset i2c module -// -ALT_STATUS_CODE alt_i2c_reset(ALT_I2C_DEV_t * i2c_dev) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - ALT_STATUS_CODE status = ALT_E_SUCCESS; - - bool already_enabled = (alt_i2c_is_enabled_helper(i2c_dev) == ALT_E_TRUE); - - if (already_enabled) - { - // Temporarily disable controller - status = alt_i2c_disable(i2c_dev); - if (status != ALT_E_SUCCESS) - { - return status; - } - } - - // Reset i2c module by reset manager - alt_i2c_rstmgr_strobe(i2c_dev); - - // Set optimal parameters for all i2c devices on the bus - ALT_I2C_MASTER_CONFIG_t cfg; - cfg.addr_mode = ALT_I2C_ADDR_MODE_7_BIT; - cfg.speed_mode = ALT_I2C_SPEED_STANDARD; - cfg.fs_spklen = ALT_I2C_SS_DEFAULT_SPKLEN; - cfg.restart_enable = ALT_E_TRUE; - cfg.ss_scl_lcnt = cfg.fs_scl_lcnt = 0x2FB; - cfg.ss_scl_hcnt = cfg.fs_scl_hcnt = 0x341; - - alt_i2c_master_config_set(i2c_dev, &cfg); - - // Active master mode - alt_i2c_op_mode_set(i2c_dev, ALT_I2C_MODE_MASTER); - - // Reset the last target address cache. - i2c_dev->last_target = 0xffffffff; - - // Clear interrupts mask and clear interrupt status. - // Interrupts are unmasked by default. - alt_i2c_int_disable(i2c_dev, ALT_I2C_STATUS_INT_ALL); - alt_i2c_int_clear(i2c_dev, ALT_I2C_STATUS_INT_ALL); - - if (already_enabled) - { - // Re-enable controller - status = alt_i2c_enable(i2c_dev); - } - - return status; -} - -// -// Uninitialize the I2C controller referenced by the i2c_dev handle. -// -ALT_STATUS_CODE alt_i2c_uninit(ALT_I2C_DEV_t * i2c_dev) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - ALT_STATUS_CODE status = ALT_E_SUCCESS; - - // Disable i2c controller - if (status == ALT_E_SUCCESS) - { - status = alt_i2c_disable(i2c_dev); - } - - // Reset i2c module by reset manager - if (status == ALT_E_SUCCESS) - { - status = alt_i2c_rstmgr_set(i2c_dev); - } - - return status; -} - -// -// Enables the I2C controller. -// -ALT_STATUS_CODE alt_i2c_enable(ALT_I2C_DEV_t * i2c_dev) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - // Enable DMA by default. - alt_write_word(ALT_I2C_DMA_CR_ADDR(i2c_dev->location), - ALT_I2C_DMA_CR_TDMAE_SET_MSK | ALT_I2C_DMA_CR_RDMAE_SET_MSK); - - alt_setbits_word(ALT_I2C_EN_ADDR(i2c_dev->location), ALT_I2C_EN_EN_SET_MSK); - - return ALT_E_SUCCESS; -} - -// -// Disables the I2C controller -// -ALT_STATUS_CODE alt_i2c_disable(ALT_I2C_DEV_t * i2c_dev) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - // If i2c controller is enabled, return with sucess - if (alt_i2c_is_enabled_helper(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_SUCCESS; - } - - // Else clear enable bit of i2c_enable register - alt_clrbits_word(ALT_I2C_EN_ADDR(i2c_dev->location), ALT_I2C_EN_EN_SET_MSK); - - uint32_t timeout = ALT_I2C_MAX_T_POLL_COUNT; - - // Wait to complete all transfer operations or timeout - while (alt_i2c_is_enabled_helper(i2c_dev) == ALT_E_TRUE) - { - // If controller still are active, return timeout error - if (--timeout == 0) - { - return ALT_E_TMO; - } - } - - // Clear interrupt status - alt_i2c_int_clear(i2c_dev, ALT_I2C_STATUS_INT_ALL); - - return ALT_E_SUCCESS; -} - -// -// Check whether i2c controller is enable -// -static ALT_STATUS_CODE alt_i2c_is_enabled_helper(ALT_I2C_DEV_t * i2c_dev) -{ - if (ALT_I2C_EN_STAT_IC_EN_GET(alt_read_word(ALT_I2C_EN_STAT_ADDR(i2c_dev->location)))) - { - return ALT_E_TRUE; - } - else - { - return ALT_E_FALSE; - } -} - -ALT_STATUS_CODE alt_i2c_is_enabled(ALT_I2C_DEV_t * i2c_dev) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - return alt_i2c_is_enabled_helper(i2c_dev); -} - -// -// Get config parameters from appropriate registers for master mode. -// -ALT_STATUS_CODE alt_i2c_master_config_get(ALT_I2C_DEV_t *i2c_dev, - ALT_I2C_MASTER_CONFIG_t* cfg) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - uint32_t cfg_register = alt_read_word(ALT_I2C_CON_ADDR(i2c_dev->location)); - uint32_t tar_register = alt_read_word(ALT_I2C_TAR_ADDR(i2c_dev->location)); - uint32_t spkl_register = alt_read_word(ALT_I2C_FS_SPKLEN_ADDR(i2c_dev->location)); - - cfg->speed_mode = (ALT_I2C_SPEED_t)ALT_I2C_CON_SPEED_GET(cfg_register); - cfg->fs_spklen = ALT_I2C_FS_SPKLEN_SPKLEN_GET(spkl_register); - cfg->restart_enable = ALT_I2C_CON_IC_RESTART_EN_GET(cfg_register); - cfg->addr_mode = (ALT_I2C_ADDR_MODE_t)ALT_I2C_TAR_IC_10BITADDR_MST_GET(tar_register); - - cfg->ss_scl_lcnt = alt_read_word(ALT_I2C_SS_SCL_LCNT_ADDR(i2c_dev->location)); - cfg->ss_scl_hcnt = alt_read_word(ALT_I2C_SS_SCL_HCNT_ADDR(i2c_dev->location)); - cfg->fs_scl_lcnt = alt_read_word(ALT_I2C_FS_SCL_LCNT_ADDR(i2c_dev->location)); - cfg->fs_scl_hcnt = alt_read_word(ALT_I2C_FS_SCL_HCNT_ADDR(i2c_dev->location)); - - return ALT_E_SUCCESS; -} - -// -// Set config parameters to appropriate registers for master mode. -// -ALT_STATUS_CODE alt_i2c_master_config_set(ALT_I2C_DEV_t *i2c_dev, - const ALT_I2C_MASTER_CONFIG_t* cfg) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - if ( (cfg->speed_mode != ALT_I2C_SPEED_STANDARD) - && (cfg->speed_mode != ALT_I2C_SPEED_FAST)) - { - return ALT_E_BAD_ARG; - } - - if ( (cfg->addr_mode != ALT_I2C_ADDR_MODE_7_BIT) - && (cfg->addr_mode != ALT_I2C_ADDR_MODE_10_BIT)) - { - return ALT_E_ARG_RANGE; - } - - ALT_STATUS_CODE status = ALT_E_SUCCESS; - - bool already_enabled = (alt_i2c_is_enabled_helper(i2c_dev) == ALT_E_TRUE); - - if (already_enabled) - { - // Temporarily disable controller - status = alt_i2c_disable(i2c_dev); - if (status != ALT_E_SUCCESS) - { - return status; - } - } - - // Set config parameters to appropriate registers - - alt_replbits_word(ALT_I2C_CON_ADDR(i2c_dev->location), - ALT_I2C_CON_SPEED_SET_MSK | ALT_I2C_CON_IC_RESTART_EN_SET_MSK, - ALT_I2C_CON_SPEED_SET(cfg->speed_mode) | ALT_I2C_CON_IC_RESTART_EN_SET(cfg->restart_enable)); - - alt_replbits_word(ALT_I2C_TAR_ADDR(i2c_dev->location), - ALT_I2C_TAR_IC_10BITADDR_MST_SET_MSK, - ALT_I2C_TAR_IC_10BITADDR_MST_SET(cfg->addr_mode)); - - alt_replbits_word(ALT_I2C_FS_SPKLEN_ADDR(i2c_dev->location), - ALT_I2C_FS_SPKLEN_SPKLEN_SET_MSK, - ALT_I2C_FS_SPKLEN_SPKLEN_SET(cfg->fs_spklen)); - - alt_replbits_word(ALT_I2C_SS_SCL_LCNT_ADDR(i2c_dev->location), - ALT_I2C_SS_SCL_LCNT_IC_SS_SCL_LCNT_SET_MSK, - ALT_I2C_SS_SCL_LCNT_IC_SS_SCL_LCNT_SET(cfg->ss_scl_lcnt)); - alt_replbits_word(ALT_I2C_SS_SCL_HCNT_ADDR(i2c_dev->location), - ALT_I2C_SS_SCL_HCNT_IC_SS_SCL_HCNT_SET_MSK, - ALT_I2C_SS_SCL_HCNT_IC_SS_SCL_HCNT_SET(cfg->ss_scl_hcnt)); - alt_replbits_word(ALT_I2C_FS_SCL_LCNT_ADDR(i2c_dev->location), - ALT_I2C_FS_SCL_LCNT_IC_FS_SCL_LCNT_SET_MSK, - ALT_I2C_FS_SCL_LCNT_IC_FS_SCL_LCNT_SET(cfg->fs_scl_lcnt)); - alt_replbits_word(ALT_I2C_FS_SCL_HCNT_ADDR(i2c_dev->location), - ALT_I2C_FS_SCL_HCNT_IC_FS_SCL_HCNT_SET_MSK, - ALT_I2C_FS_SCL_HCNT_IC_FS_SCL_HCNT_SET(cfg->fs_scl_hcnt)); - - if (already_enabled) - { - // Re-enable controller - status = alt_i2c_enable(i2c_dev); - } - - return status; -} - -// -// Return bus speed by configuration of i2c controller for master mode. -// -ALT_STATUS_CODE alt_i2c_master_config_speed_get(ALT_I2C_DEV_t *i2c_dev, - const ALT_I2C_MASTER_CONFIG_t * cfg, - uint32_t * speed_in_hz) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - uint32_t scl_lcnt = (cfg->speed_mode == ALT_I2C_SPEED_STANDARD) ? cfg->ss_scl_lcnt : cfg->fs_scl_lcnt; - - if (scl_lcnt == 0) - { - return ALT_E_BAD_ARG; - } - - *speed_in_hz = i2c_dev->clock_freq / (scl_lcnt << 1); - - return ALT_E_SUCCESS; -} - -// -// Fill struct with configuration of i2c controller for master mode by bus speed -// -ALT_STATUS_CODE alt_i2c_master_config_speed_set(ALT_I2C_DEV_t *i2c_dev, - ALT_I2C_MASTER_CONFIG_t * cfg, - uint32_t speed_in_hz) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - // If speed is not standard or fast return range error - if ((speed_in_hz > ALT_I2C_FS_MAX_SPEED) || (speed_in_hz < ALT_I2C_SS_MIN_SPEED)) - { - return ALT_E_ARG_RANGE; - } - - if (speed_in_hz > ALT_I2C_FS_MIN_SPEED) - { - cfg->speed_mode = ALT_I2C_SPEED_FAST; - cfg->fs_spklen = ALT_I2C_FS_DEFAULT_SPKLEN; - } - else - { - cfg->speed_mode = ALT_I2C_SPEED_STANDARD; - cfg->fs_spklen = ALT_I2C_SS_DEFAULT_SPKLEN; - } - - // <lcount> = <internal clock> / 2 * <speed, Hz> - uint32_t scl_lcnt = i2c_dev->clock_freq / (speed_in_hz << 1); - - cfg->ss_scl_lcnt = cfg->fs_scl_lcnt = scl_lcnt; - // hcount = <lcount> + 70 - cfg->ss_scl_hcnt = cfg->fs_scl_hcnt = scl_lcnt - ALT_I2C_DIFF_LCNT_HCNT; - - // lcount = <internal clock> / 2 * <speed, Hz> - - return ALT_E_SUCCESS; -} - -// -// Get config parameters from appropriate registers for slave mode. -// -ALT_STATUS_CODE alt_i2c_slave_config_get(ALT_I2C_DEV_t *i2c_dev, - ALT_I2C_SLAVE_CONFIG_t* cfg) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - uint32_t cfg_register = alt_read_word(ALT_I2C_CON_ADDR(i2c_dev->location)); - uint32_t sar_register = alt_read_word(ALT_I2C_SAR_ADDR(i2c_dev->location)); - uint32_t nack_register = alt_read_word(ALT_I2C_SLV_DATA_NACK_ONLY_ADDR(i2c_dev->location)); - - cfg->addr_mode = (ALT_I2C_ADDR_MODE_t)ALT_I2C_CON_IC_10BITADDR_SLV_GET(cfg_register); - cfg->addr = ALT_I2C_SAR_IC_SAR_GET(sar_register); - cfg->nack_enable = ALT_I2C_SLV_DATA_NACK_ONLY_NACK_GET(nack_register); - - return ALT_E_SUCCESS; -} - -// -// Set config parameters to appropriate registers for slave mode. -// -ALT_STATUS_CODE alt_i2c_slave_config_set(ALT_I2C_DEV_t *i2c_dev, - const ALT_I2C_SLAVE_CONFIG_t* cfg) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - if ( (cfg->addr_mode != ALT_I2C_ADDR_MODE_7_BIT) - && (cfg->addr_mode != ALT_I2C_ADDR_MODE_10_BIT)) - { - return ALT_E_BAD_ARG; - } - - if ( (cfg->addr > ALT_I2C_SAR_IC_SAR_SET_MSK) - || (cfg->addr < ALT_I2C_SLV_RESERVE_ADDR_F_1) - || ((cfg->addr > ALT_I2C_SLV_RESERVE_ADDR_S_2) && (cfg->addr < ALT_I2C_SLV_RESERVE_ADDR_F_2)) - ) - { - return ALT_E_ARG_RANGE; - } - - ALT_STATUS_CODE status = ALT_E_SUCCESS; - - bool already_enabled = (alt_i2c_is_enabled_helper(i2c_dev) == ALT_E_TRUE); - - if (already_enabled) - { - // Temporarily disable controller - status = alt_i2c_disable(i2c_dev); - if (status != ALT_E_SUCCESS) - { - return status; - } - } - - alt_replbits_word(ALT_I2C_CON_ADDR(i2c_dev->location), - ALT_I2C_CON_IC_10BITADDR_SLV_SET_MSK, - ALT_I2C_CON_IC_10BITADDR_SLV_SET(cfg->addr_mode)); - - alt_replbits_word(ALT_I2C_SAR_ADDR(i2c_dev->location), - ALT_I2C_SAR_IC_SAR_SET_MSK, - ALT_I2C_SAR_IC_SAR_SET(cfg->addr)); - alt_replbits_word(ALT_I2C_SLV_DATA_NACK_ONLY_ADDR(i2c_dev->location), - ALT_I2C_SLV_DATA_NACK_ONLY_NACK_SET_MSK, - ALT_I2C_SLV_DATA_NACK_ONLY_NACK_SET(cfg->nack_enable)); - - if (already_enabled) - { - // Re-enable controller - status = alt_i2c_enable(i2c_dev); - } - - return status; -} - -// -// Get hold time (use during slave mode) -// -ALT_STATUS_CODE alt_i2c_sda_hold_time_get(ALT_I2C_DEV_t *i2c_dev, - uint16_t *hold_time) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - uint32_t sda_register = alt_read_word(ALT_I2C_SDA_HOLD_ADDR(i2c_dev->location)); - *hold_time = ALT_I2C_SDA_HOLD_IC_SDA_HOLD_GET(sda_register); - - return ALT_E_SUCCESS; -} - -// -// Set hold time (use during slave mode) -// -ALT_STATUS_CODE alt_i2c_sda_hold_time_set(ALT_I2C_DEV_t *i2c_dev, - const uint16_t hold_time) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - ALT_STATUS_CODE status = ALT_E_SUCCESS; - - bool already_enabled = (alt_i2c_is_enabled_helper(i2c_dev) == ALT_E_TRUE); - - if (already_enabled) - { - // Temporarily disable controller - status = alt_i2c_disable(i2c_dev); - if (status != ALT_E_SUCCESS) - { - return status; - } - } - - alt_replbits_word(ALT_I2C_SDA_HOLD_ADDR(i2c_dev->location), - ALT_I2C_SDA_HOLD_IC_SDA_HOLD_SET_MSK, - ALT_I2C_SDA_HOLD_IC_SDA_HOLD_SET(hold_time)); - - if (already_enabled) - { - // Re-enable controller - status = alt_i2c_enable(i2c_dev); - } - - return status; -} - -// -// Gets the current operational mode of the I2C controller. -// -ALT_STATUS_CODE alt_i2c_op_mode_get(ALT_I2C_DEV_t *i2c_dev, - ALT_I2C_MODE_t* mode) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - uint32_t cfg_register = alt_read_word(ALT_I2C_CON_ADDR(i2c_dev->location)); - uint32_t mst_mod_stat = ALT_I2C_CON_MST_MOD_GET(cfg_register); - uint32_t slv_mod_stat = ALT_I2C_CON_IC_SLV_DIS_GET(cfg_register); - - // Return error if master and slave modes enable or disable at the same time - if ( (mst_mod_stat == ALT_I2C_CON_MST_MOD_E_EN && slv_mod_stat == ALT_I2C_CON_IC_SLV_DIS_E_EN) - || (mst_mod_stat == ALT_I2C_CON_MST_MOD_E_DIS && slv_mod_stat == ALT_I2C_CON_IC_SLV_DIS_E_DIS)) - { - return ALT_E_ERROR; - } - - *mode = (ALT_I2C_MODE_t)mst_mod_stat; - - return ALT_E_SUCCESS; -} - -// -// Sets the operational mode of the I2C controller. -// -ALT_STATUS_CODE alt_i2c_op_mode_set(ALT_I2C_DEV_t *i2c_dev, - const ALT_I2C_MODE_t mode) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - if ( (mode != ALT_I2C_MODE_MASTER) - && (mode != ALT_I2C_MODE_SLAVE)) - { - return ALT_E_ARG_RANGE; - } - - ALT_STATUS_CODE status = ALT_E_SUCCESS; - - bool already_enabled = (alt_i2c_is_enabled_helper(i2c_dev) == ALT_E_TRUE); - - if (already_enabled) - { - // Temporarily disable controller - status = alt_i2c_disable(i2c_dev); - if (status != ALT_E_SUCCESS) - { - return status; - } - } - - if (mode == ALT_I2C_MODE_MASTER) - { - // Enable master, disable slave - alt_replbits_word(ALT_I2C_CON_ADDR(i2c_dev->location), - ALT_I2C_CON_IC_SLV_DIS_SET_MSK | ALT_I2C_CON_MST_MOD_SET_MSK, - ALT_I2C_CON_IC_SLV_DIS_SET(ALT_I2C_CON_IC_SLV_DIS_E_DIS) | ALT_I2C_CON_MST_MOD_SET(ALT_I2C_CON_MST_MOD_E_EN)); - } - else if (mode == ALT_I2C_MODE_SLAVE) - { - // Enable slave, disable master - alt_replbits_word(ALT_I2C_CON_ADDR(i2c_dev->location), - ALT_I2C_CON_IC_SLV_DIS_SET_MSK | ALT_I2C_CON_MST_MOD_SET_MSK, - ALT_I2C_CON_IC_SLV_DIS_SET(ALT_I2C_CON_IC_SLV_DIS_E_EN) | ALT_I2C_CON_MST_MOD_SET(ALT_I2C_CON_MST_MOD_E_DIS)); - } - - if (already_enabled) - { - // Re-enable controller - status = alt_i2c_enable(i2c_dev); - } - - return status; -} - -// -// Returns ALT_E_TRUE if the I2C controller is busy -// -ALT_STATUS_CODE alt_i2c_is_busy(ALT_I2C_DEV_t *i2c_dev) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - if ( ALT_I2C_STAT_ACTIVITY_GET(alt_read_word(ALT_I2C_STAT_ADDR(i2c_dev->location)))) - { - return ALT_E_TRUE; - } - else - { - return ALT_E_FALSE; - } -} - -// -// This function reads a single data byte from the receive FIFO. -// -ALT_STATUS_CODE alt_i2c_read(ALT_I2C_DEV_t *i2c_dev, uint8_t *value) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - if (alt_i2c_is_enabled_helper(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_ERROR; - } - - *value = (uint8_t)(ALT_I2C_DATA_CMD_DAT_GET(alt_read_word(ALT_I2C_DATA_CMD_ADDR(i2c_dev->location)))); - - return ALT_E_SUCCESS; -} - -// -// This function writes a single data byte to the transmit FIFO. -// -ALT_STATUS_CODE alt_i2c_write(ALT_I2C_DEV_t *i2c_dev, const uint8_t value) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - if (alt_i2c_is_enabled_helper(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_ERROR; - } - - alt_write_word(ALT_I2C_DATA_CMD_ADDR(i2c_dev->location), - ALT_I2C_DATA_CMD_DAT_SET(value)); - - return ALT_E_SUCCESS; -} - -// -// This function acts in the role of a slave-receiver by receiving a single data -// byte from the I2C bus in response to a write command from the master. -// -ALT_STATUS_CODE alt_i2c_slave_receive(ALT_I2C_DEV_t * i2c_dev, - uint8_t * data) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - if (alt_i2c_is_enabled_helper(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_ERROR; - } - - // alt_i2c_read(). - *data = (uint8_t)(ALT_I2C_DATA_CMD_DAT_GET(alt_read_word(ALT_I2C_DATA_CMD_ADDR(i2c_dev->location)))); - - return ALT_E_SUCCESS; -} - -// -// This function acts in the role of a slave-transmitter by transmitting a single -// data byte to the I2C bus in response to a read request from the master. -// -ALT_STATUS_CODE alt_i2c_slave_transmit(ALT_I2C_DEV_t *i2c_dev, - const uint8_t data) -{ - // Send bulk of data with one value - return alt_i2c_slave_bulk_transmit(i2c_dev, &data, 1); -} - -// -// This function acts in the role of a slave-transmitter by transmitting data in -// bulk to the I2C bus in response to a series of read requests from a master. -// -ALT_STATUS_CODE alt_i2c_slave_bulk_transmit(ALT_I2C_DEV_t *i2c_dev, - const void * data, - const size_t size) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - if (alt_i2c_is_enabled_helper(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_ERROR; - } - - const char * buffer = data; - for (size_t i = 0; i < size; ++i) - { - alt_write_word(ALT_I2C_DATA_CMD_ADDR(i2c_dev->location), - ALT_I2C_DATA_CMD_DAT_SET(*buffer) - | ALT_I2C_DATA_CMD_STOP_SET(false) - | ALT_I2C_DATA_CMD_RESTART_SET(false)); - - ++buffer; - } - - return ALT_E_SUCCESS; -} - -ALT_STATUS_CODE alt_i2c_master_target_get(ALT_I2C_DEV_t * i2c_dev, uint32_t * target_addr) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - *target_addr = i2c_dev->last_target; - - return ALT_E_SUCCESS; -} - -ALT_STATUS_CODE alt_i2c_master_target_set(ALT_I2C_DEV_t * i2c_dev, uint32_t target_addr) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - ALT_STATUS_CODE status = ALT_E_SUCCESS; - - // Wait until the TX FIFO flushes. This is needed because TAR can only be - // updated under specific conditions. - - if (target_addr != i2c_dev->last_target) - { - uint32_t timeout = 10000; - - while (alt_i2c_tx_fifo_is_empty(i2c_dev) == ALT_E_FALSE) - { - if (--timeout == 0) - { - status = ALT_E_TMO; - break; - } - } - - // Update target address - if (status == ALT_E_SUCCESS) - { - alt_replbits_word(ALT_I2C_TAR_ADDR(i2c_dev->location), - ALT_I2C_TAR_IC_TAR_SET_MSK, - ALT_I2C_TAR_IC_TAR_SET(target_addr)); - - i2c_dev->last_target = target_addr; - } - } - - return status; -} - -// -// Write bulk of data or read requests to tx fifo -// -static ALT_STATUS_CODE alt_i2c_master_transmit_helper(ALT_I2C_DEV_t * i2c_dev, - const uint8_t * buffer, - size_t size, - bool issue_restart, - bool issue_stop) -{ - ALT_STATUS_CODE status = ALT_E_SUCCESS; - - // If the rested size is 1, the restart and stop may need to be sent in the - // same frame. - if (size == 1) - { - if (status == ALT_E_SUCCESS) - { - status = alt_i2c_issue_write(i2c_dev, - *buffer, - issue_restart, - issue_stop); - - ++buffer; - --size; - } - } - else - { - // First byte - - if (status == ALT_E_SUCCESS) - { - status = alt_i2c_issue_write(i2c_dev, - *buffer, - issue_restart, - false); - - ++buffer; - --size; - } - - ///// - - // Middle byte(s) - - if (status == ALT_E_SUCCESS) - { - uint32_t timeout = size * 10000; - - while (size > 1) - { - uint32_t level = 0; - status = alt_i2c_tx_fifo_level_get(i2c_dev, &level); - if (status != ALT_E_SUCCESS) - { - break; - } - - uint32_t space = ALT_I2C_TX_FIFO_NUM_ENTRIES - level; - if (space == 0) - { - if (--timeout == 0) - { - status = ALT_E_TMO; - break; - } - - continue; - } - - // Subtract 1 because the last byte may need to issue_stop - space = MIN(space, size - 1); - - for (uint32_t i = 0; i < space; ++i) - { - alt_write_word(ALT_I2C_DATA_CMD_ADDR(i2c_dev->location), - ALT_I2C_DATA_CMD_DAT_SET(*buffer) - | ALT_I2C_DATA_CMD_STOP_SET(false) - | ALT_I2C_DATA_CMD_RESTART_SET(false)); - - ++buffer; - } - - size -= space; - } - } - - ///// - - // Last byte - - if (status == ALT_E_SUCCESS) - { - status = alt_i2c_issue_write(i2c_dev, - *buffer, - false, - issue_stop); - - ++buffer; - --size; - } - } - - return status; -} - -// -// This function acts in the role of a master-transmitter by issuing a write -// command and transmitting data to the I2C bus. -// -ALT_STATUS_CODE alt_i2c_master_transmit(ALT_I2C_DEV_t *i2c_dev, - const void * data, - const size_t size, - const bool issue_restart, - const bool issue_stop) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - if (alt_i2c_is_enabled_helper(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_ERROR; - } - - if (size == 0) - { - return ALT_E_SUCCESS; - } - - ALT_STATUS_CODE status = ALT_E_SUCCESS; - - if (status == ALT_E_SUCCESS) - { - status = alt_i2c_master_transmit_helper(i2c_dev, - data, - size, - issue_restart, - issue_stop); - } - - // Need reset for set i2c bus in idle state - if (status == ALT_E_TMO) - { - alt_i2c_reset(i2c_dev); - } - - return status; -} - -ALT_STATUS_CODE alt_i2c_master_receive_helper(ALT_I2C_DEV_t *i2c_dev, - uint8_t * buffer, - size_t size, - bool issue_restart, - bool issue_stop) -{ - ALT_STATUS_CODE status = ALT_E_SUCCESS; - - uint32_t issue_left = size; - uint32_t data_left = size; - - uint32_t timeout = size * 10000; - - // Wait for space in the TX FIFO to send the first read request. - // This is needed because the issue restart need to be set. - - if (issue_restart == true) - { - if (status == ALT_E_SUCCESS) - { - while (alt_i2c_tx_fifo_is_full(i2c_dev) == ALT_E_TRUE) - { - if (--timeout == 0) - { - status = ALT_E_TMO; - break; - } - } - } - - // Now send the first request. - - if (status == ALT_E_SUCCESS) - { - alt_write_word(ALT_I2C_DATA_CMD_ADDR(i2c_dev->location), - ALT_I2C_DATA_CMD_CMD_SET(ALT_I2C_DATA_CMD_CMD_E_RD) - | ALT_I2C_DATA_CMD_STOP_SET(false) - | ALT_I2C_DATA_CMD_RESTART_SET(issue_restart)); - - --issue_left; - } - } - - // For the rest of the data ... - - while (data_left > 0) - { - if (status != ALT_E_SUCCESS) - { - break; - } - - // Top up the TX FIFO with read issues - // Special consideration must be made for the last read issue, as it may be necessary to "issue_stop". - - if (issue_left > 0) - { - uint32_t level = 0; - status = alt_i2c_tx_fifo_level_get(i2c_dev, &level); - if (status != ALT_E_SUCCESS) - { - break; - } - - uint32_t space = ALT_I2C_TX_FIFO_NUM_ENTRIES - level; - - if (issue_left == 1) - { - if (space > 0) - { - space = 1; - - alt_write_word(ALT_I2C_DATA_CMD_ADDR(i2c_dev->location), - ALT_I2C_DATA_CMD_CMD_SET(ALT_I2C_DATA_CMD_CMD_E_RD) - | ALT_I2C_DATA_CMD_STOP_SET(issue_stop) - | ALT_I2C_DATA_CMD_RESTART_SET(false)); - } - } - else - { - // Send up to issue_left - 1, as the last issue has special considerations. - space = MIN(issue_left - 1, space); - - for (uint32_t i = 0; i < space; ++i) - { - alt_write_word(ALT_I2C_DATA_CMD_ADDR(i2c_dev->location), - ALT_I2C_DATA_CMD_CMD_SET(ALT_I2C_DATA_CMD_CMD_E_RD) - | ALT_I2C_DATA_CMD_STOP_SET(false) - | ALT_I2C_DATA_CMD_RESTART_SET(false)); - } - } - - issue_left -= space; - } - - // Read out the resulting received data as they come in. - - if (data_left > 0) - { - uint32_t level = 0; - status = alt_i2c_rx_fifo_level_get(i2c_dev, &level); - if (status != ALT_E_SUCCESS) - { - break; - } - - if (level == 0) - { - if (--timeout == 0) - { - status = ALT_E_TMO; - break; - } - } - - level = MIN(data_left, level); - - for (uint32_t i = 0; i < level; ++i) - { - // alt_i2c_read(i2c_dev, &value); - *buffer = (uint8_t)(ALT_I2C_DATA_CMD_DAT_GET(alt_read_word(ALT_I2C_DATA_CMD_ADDR(i2c_dev->location)))); - ++buffer; - } - - data_left -= level; - } - } - - - return status; -} - -// -// This function acts in the role of a master-receiver by receiving one or more -// data bytes transmitted from a slave in response to read requests issued from -// this master. -// -ALT_STATUS_CODE alt_i2c_master_receive(ALT_I2C_DEV_t *i2c_dev, - void * data, - const size_t size, - const bool issue_restart, - const bool issue_stop) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - if (alt_i2c_is_enabled_helper(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_ERROR; - } - - if (size == 0) - { - return ALT_E_SUCCESS; - } - - ALT_STATUS_CODE status = ALT_E_SUCCESS; - - // This I2C controller requires that a read issue be performed for each byte requested. - // Read issue takes space in the TX FIFO, which may asynchronously handling a previous request. - - if (size == 1) - { - uint32_t timeout = 10000; - - // Wait for space in the TX FIFO to send the read request. - - if (status == ALT_E_SUCCESS) - { - while (alt_i2c_tx_fifo_is_full(i2c_dev) == ALT_E_TRUE) - { - if (--timeout == 0) - { - status = ALT_E_TMO; - break; - } - } - } - - // Issue the read request in the TX FIFO. - - if (status == ALT_E_SUCCESS) - { - alt_write_word(ALT_I2C_DATA_CMD_ADDR(i2c_dev->location), - ALT_I2C_DATA_CMD_CMD_SET(ALT_I2C_DATA_CMD_CMD_E_RD) - | ALT_I2C_DATA_CMD_STOP_SET(issue_stop) - | ALT_I2C_DATA_CMD_RESTART_SET(issue_restart)); - - } - - // Wait for data to become available in the RX FIFO. - - if (status == ALT_E_SUCCESS) - { - while (alt_i2c_rx_fifo_is_empty(i2c_dev) == ALT_E_TRUE) - { - if (--timeout == 0) - { - status = ALT_E_TMO; - break; - } - } - } - - // Read the RX FIFO. - - if (status == ALT_E_SUCCESS) - { - uint8_t * buffer = data; - *buffer = (uint8_t)(ALT_I2C_DATA_CMD_DAT_GET(alt_read_word(ALT_I2C_DATA_CMD_ADDR(i2c_dev->location)))); - } - } - else if (size <= 64) - { - if (status == ALT_E_SUCCESS) - { - status = alt_i2c_master_receive_helper(i2c_dev, - data, - size, - issue_restart, - issue_stop); - } - } - else - { - uint8_t * buffer = data; - size_t size_left = size; - - // Send the first ALT_I2C_RX_FIFO_NUM_ENTRIES items - - if (status == ALT_E_SUCCESS) - { - status = alt_i2c_master_receive_helper(i2c_dev, - buffer, - ALT_I2C_RX_FIFO_NUM_ENTRIES, - issue_restart, - false); - } - - buffer += ALT_I2C_RX_FIFO_NUM_ENTRIES; - size_left -= ALT_I2C_RX_FIFO_NUM_ENTRIES; - - while (size_left > 0) - { - if (size_left > ALT_I2C_RX_FIFO_NUM_ENTRIES) - { - if (status == ALT_E_SUCCESS) - { - status = alt_i2c_master_receive_helper(i2c_dev, - buffer, - ALT_I2C_RX_FIFO_NUM_ENTRIES, - false, - false); - } - - buffer += ALT_I2C_RX_FIFO_NUM_ENTRIES; - size_left -= ALT_I2C_RX_FIFO_NUM_ENTRIES; - } - else - { - if (status == ALT_E_SUCCESS) - { - status = alt_i2c_master_receive_helper(i2c_dev, - buffer, - size_left, - false, - issue_stop); - } - - size_left = 0; - } - - if (status != ALT_E_SUCCESS) - { - break; - } - } - } - - // Need reset for set i2c bus in idle state - if (status == ALT_E_TMO) - { - alt_i2c_reset(i2c_dev); - } - - return status; -} - -// -// This function causes the I2C controller master to send data to the bus. -// -ALT_STATUS_CODE alt_i2c_issue_write(ALT_I2C_DEV_t *i2c_dev, - const uint8_t value, - const bool issue_restart, - const bool issue_stop) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - if (alt_i2c_is_enabled_helper(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_ERROR; - } - - // Wait until there is a FIFO spot - uint32_t timeout = 10000; - - while (alt_i2c_tx_fifo_is_full(i2c_dev) == ALT_E_TRUE) - { - if (--timeout == 0) - { - return ALT_E_TMO; - } - } - - alt_write_word(ALT_I2C_DATA_CMD_ADDR(i2c_dev->location), - ALT_I2C_DATA_CMD_DAT_SET(value) - | ALT_I2C_DATA_CMD_STOP_SET(issue_stop) - | ALT_I2C_DATA_CMD_RESTART_SET(issue_restart)); - - return ALT_E_SUCCESS; -} - -// -// This function causes the I2C controller master to issue a READ request on the bus. -// -ALT_STATUS_CODE alt_i2c_issue_read(ALT_I2C_DEV_t *i2c_dev, - const bool issue_restart, - const bool issue_stop) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - if (alt_i2c_is_enabled_helper(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_ERROR; - } - - // Wait until there is a FIFO spot - uint32_t timeout = 10000; - - while (alt_i2c_tx_fifo_is_full(i2c_dev) == ALT_E_TRUE) - { - if (--timeout == 0) - { - return ALT_E_TMO; - } - } - - alt_write_word(ALT_I2C_DATA_CMD_ADDR(i2c_dev->location), - ALT_I2C_DATA_CMD_CMD_SET(ALT_I2C_DATA_CMD_CMD_E_RD) - | ALT_I2C_DATA_CMD_STOP_SET(issue_stop) - | ALT_I2C_DATA_CMD_RESTART_SET(issue_restart)); - - return ALT_E_SUCCESS; -} - -// -// This function acts in the role of a master-transmitter by issuing a general -// call command to all devices connected to the I2C bus. -// -ALT_STATUS_CODE alt_i2c_master_general_call(ALT_I2C_DEV_t *i2c_dev, - const void * data, - const size_t size, - const bool issue_restart, - const bool issue_stop) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - if (alt_i2c_is_enabled_helper(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_ERROR; - } - - ALT_STATUS_CODE status = ALT_E_SUCCESS; - - if (status == ALT_E_SUCCESS) - { - status = alt_i2c_master_target_set(i2c_dev, 0); - } - - // General call is a transmit in master mode (target address are not used during it) - if (status == ALT_E_SUCCESS) - { - status = alt_i2c_master_transmit(i2c_dev, data, size, issue_restart, issue_stop); - } - - return status; -} - -///// - -ALT_STATUS_CODE alt_i2c_general_call_ack_disable(ALT_I2C_DEV_t *i2c_dev) -{ - ALT_STATUS_CODE status = ALT_E_SUCCESS; - - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - bool already_enabled = (alt_i2c_is_enabled_helper(i2c_dev) == ALT_E_TRUE); - - if (already_enabled) - { - // Temporarily disable controller - status = alt_i2c_disable(i2c_dev); - if (status != ALT_E_SUCCESS) - { - return status; - } - } - - alt_replbits_word(ALT_I2C_TAR_ADDR(i2c_dev->location), - ALT_I2C_TAR_SPECIAL_SET_MSK | ALT_I2C_TAR_GC_OR_START_SET_MSK, - ALT_I2C_TAR_SPECIAL_SET(ALT_I2C_TAR_SPECIAL_E_STARTBYTE) | ALT_I2C_TAR_GC_OR_START_SET(ALT_I2C_TAR_GC_OR_START_E_STARTBYTE)); - - if (already_enabled) - { - // Re-enable controller - status = alt_i2c_enable(i2c_dev); - } - - return status; -} - -// -// Enables the I2C controller to respond with an ACK when it receives a General -// Call address. -// -ALT_STATUS_CODE alt_i2c_general_call_ack_enable(ALT_I2C_DEV_t *i2c_dev) -{ - ALT_STATUS_CODE status = ALT_E_SUCCESS; - - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - bool already_enabled = (alt_i2c_is_enabled_helper(i2c_dev) == ALT_E_TRUE); - - if (already_enabled) - { - // Temporarily disable controller - status = alt_i2c_disable(i2c_dev); - if (status != ALT_E_SUCCESS) - { - return status; - } - } - - alt_replbits_word(ALT_I2C_TAR_ADDR(i2c_dev->location), - ALT_I2C_TAR_SPECIAL_SET_MSK | ALT_I2C_TAR_GC_OR_START_SET_MSK, - ALT_I2C_TAR_SPECIAL_SET(ALT_I2C_TAR_SPECIAL_E_GENCALL) | ALT_I2C_TAR_GC_OR_START_SET(ALT_I2C_TAR_GC_OR_START_E_GENCALL)); - - if (already_enabled) - { - // Re-enable controller - status = alt_i2c_enable(i2c_dev); - } - - return status; -} - -// -// Returns ALT_E_TRUE if the I2C controller is enabled to respond to General Call -// addresses. -// -ALT_STATUS_CODE alt_i2c_general_call_ack_is_enabled(ALT_I2C_DEV_t *i2c_dev) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - uint32_t tar_register = alt_read_word(ALT_I2C_TAR_ADDR(i2c_dev->location)); - - if ( (ALT_I2C_TAR_SPECIAL_GET(tar_register) == ALT_I2C_TAR_SPECIAL_E_GENCALL) - && (ALT_I2C_TAR_GC_OR_START_GET(tar_register) == ALT_I2C_TAR_GC_OR_START_E_GENCALL) - ) - { - return ALT_E_TRUE; - } - else - { - return ALT_E_FALSE; - } -} - -// -// Returns the current I2C controller interrupt status conditions. -// -ALT_STATUS_CODE alt_i2c_int_status_get(ALT_I2C_DEV_t *i2c_dev, - uint32_t *status) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - *status = alt_read_word(ALT_I2C_INTR_STAT_ADDR(i2c_dev->location)); - - return ALT_E_SUCCESS; -} - -// -// Returns the I2C controller raw interrupt status conditions irrespective of -// the interrupt status condition enablement state. -// -ALT_STATUS_CODE alt_i2c_int_raw_status_get(ALT_I2C_DEV_t *i2c_dev, - uint32_t *status) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - *status = alt_read_word(ALT_I2C_RAW_INTR_STAT_ADDR(i2c_dev->location)); - - return ALT_E_SUCCESS; -} - -// -// Clears the specified I2C controller interrupt status conditions identified -// in the mask. -// -ALT_STATUS_CODE alt_i2c_int_clear(ALT_I2C_DEV_t *i2c_dev, const uint32_t mask) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - if (mask == ALT_I2C_STATUS_INT_ALL) - { - alt_read_word(ALT_I2C_CLR_INTR_ADDR(i2c_dev->location)); - return ALT_E_SUCCESS; - } - - // For different status clear different register - - if (mask & ALT_I2C_STATUS_RX_UNDER) - { - alt_read_word(ALT_I2C_CLR_RX_UNDER_ADDR(i2c_dev->location)); - } - if (mask & ALT_I2C_STATUS_RX_OVER) - { - alt_read_word(ALT_I2C_CLR_RX_OVER_ADDR(i2c_dev->location)); - } - if (mask & ALT_I2C_STATUS_TX_OVER) - { - alt_read_word(ALT_I2C_CLR_TX_OVER_ADDR(i2c_dev->location)); - } - if (mask & ALT_I2C_STATUS_RD_REQ) - { - alt_read_word(ALT_I2C_CLR_RD_REQ_ADDR(i2c_dev->location)); - } - if (mask & ALT_I2C_STATUS_TX_ABORT) - { - alt_read_word(ALT_I2C_CLR_TX_ABRT_ADDR(i2c_dev->location)); - } - if (mask & ALT_I2C_STATUS_RX_DONE) - { - alt_read_word(ALT_I2C_CLR_RX_DONE_ADDR(i2c_dev->location)); - } - if (mask & ALT_I2C_STATUS_ACTIVITY) - { - alt_read_word(ALT_I2C_CLR_ACTIVITY_ADDR(i2c_dev->location)); - } - if (mask & ALT_I2C_STATUS_STOP_DET) - { - alt_read_word(ALT_I2C_CLR_STOP_DET_ADDR(i2c_dev->location)); - } - if (mask & ALT_I2C_STATUS_START_DET) - { - alt_read_word(ALT_I2C_CLR_START_DET_ADDR(i2c_dev->location)); - } - if (mask & ALT_I2C_STATUS_INT_CALL) - { - alt_read_word(ALT_I2C_CLR_GEN_CALL_ADDR(i2c_dev->location)); - } - - return ALT_E_SUCCESS; -} - -// -// Disable the specified I2C controller interrupt status conditions identified in -// the mask. -// -ALT_STATUS_CODE alt_i2c_int_disable(ALT_I2C_DEV_t *i2c_dev, const uint32_t mask) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - alt_clrbits_word(ALT_I2C_INTR_MSK_ADDR(i2c_dev->location), mask); - - return ALT_E_SUCCESS; -} - -// -// Enable the specified I2C controller interrupt status conditions identified in -// the mask. -// -ALT_STATUS_CODE alt_i2c_int_enable(ALT_I2C_DEV_t *i2c_dev, const uint32_t mask) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - alt_setbits_word(ALT_I2C_INTR_MSK_ADDR(i2c_dev->location), mask); - - return ALT_E_SUCCESS; -} - -///// - -// -// Gets the cause of I2C transmission abort. -// -ALT_STATUS_CODE alt_i2c_tx_abort_cause_get(ALT_I2C_DEV_t *i2c_dev, - ALT_I2C_TX_ABORT_CAUSE_t *cause) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - *cause = (ALT_I2C_TX_ABORT_CAUSE_t)alt_read_word(ALT_I2C_TX_ABRT_SRC_ADDR(i2c_dev->location)); - - return ALT_E_SUCCESS; -} - -///// - -// -// Returns ALT_E_TRUE when the receive FIFO is empty. -// -ALT_STATUS_CODE alt_i2c_rx_fifo_is_empty(ALT_I2C_DEV_t *i2c_dev) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - if (ALT_I2C_STAT_RFNE_GET(alt_read_word(ALT_I2C_STAT_ADDR(i2c_dev->location))) == ALT_I2C_STAT_RFNE_E_EMPTY) - { - return ALT_E_TRUE; - } - else - { - return ALT_E_FALSE; - } -} - -// -// Returns ALT_E_TRUE when the receive FIFO is completely full. -// -ALT_STATUS_CODE alt_i2c_rx_fifo_is_full(ALT_I2C_DEV_t *i2c_dev) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - if (ALT_I2C_STAT_RFF_GET(alt_read_word(ALT_I2C_STAT_ADDR(i2c_dev->location))) == ALT_I2C_STAT_RFF_E_FULL) - { - return ALT_E_TRUE; - } - else - { - return ALT_E_FALSE; - } -} - -// -// Returns the number of valid entries in the receive FIFO. -// -ALT_STATUS_CODE alt_i2c_rx_fifo_level_get(ALT_I2C_DEV_t *i2c_dev, - uint32_t *num_entries) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - *num_entries = ALT_I2C_RXFLR_RXFLR_GET(alt_read_word(ALT_I2C_RXFLR_ADDR(i2c_dev->location))); - - return ALT_E_SUCCESS; -} - -// -// Gets the current receive FIFO threshold level value. -// -ALT_STATUS_CODE alt_i2c_rx_fifo_threshold_get(ALT_I2C_DEV_t *i2c_dev, - uint8_t *threshold) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - *threshold = ALT_I2C_RX_TL_RX_TL_GET(alt_read_word(ALT_I2C_RX_TL_ADDR(i2c_dev->location))); - - return ALT_E_SUCCESS; -} - -// -// Sets the current receive FIFO threshold level value. -// -ALT_STATUS_CODE alt_i2c_rx_fifo_threshold_set(ALT_I2C_DEV_t *i2c_dev, - const uint8_t threshold) -{ - ALT_STATUS_CODE status = ALT_E_SUCCESS; - - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - bool already_enabled = (alt_i2c_is_enabled_helper(i2c_dev) == ALT_E_TRUE); - - if (already_enabled) - { - // Temporarily disable controller - status = alt_i2c_disable(i2c_dev); - if (status != ALT_E_SUCCESS) - { - return status; - } - } - - alt_replbits_word(ALT_I2C_RX_TL_ADDR(i2c_dev->location), - ALT_I2C_RX_TL_RX_TL_SET_MSK, - ALT_I2C_RX_TL_RX_TL_SET(threshold)); - - if (already_enabled) - { - // Re-enable controller - status = alt_i2c_enable(i2c_dev); - } - - return status; -} - -// -// Returns ALT_E_TRUE when the transmit FIFO is empty. -// -ALT_STATUS_CODE alt_i2c_tx_fifo_is_empty(ALT_I2C_DEV_t *i2c_dev) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - if (ALT_I2C_STAT_TFE_GET(alt_read_word(ALT_I2C_STAT_ADDR(i2c_dev->location))) == ALT_I2C_STAT_TFE_E_EMPTY) - { - return ALT_E_TRUE; - } - else - { - return ALT_E_FALSE; - } -} - -// -// Returns ALT_E_TRUE when the transmit FIFO is completely full. -// -ALT_STATUS_CODE alt_i2c_tx_fifo_is_full(ALT_I2C_DEV_t *i2c_dev) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - if (ALT_I2C_STAT_TFNF_GET(alt_read_word(ALT_I2C_STAT_ADDR(i2c_dev->location))) == ALT_I2C_STAT_TFNF_E_FULL) - { - return ALT_E_TRUE; - } - else - { - return ALT_E_FALSE; - } -} - -// -// Returns the number of valid entries in the transmit FIFO. -// -ALT_STATUS_CODE alt_i2c_tx_fifo_level_get(ALT_I2C_DEV_t *i2c_dev, - uint32_t *num_entries) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - *num_entries = ALT_I2C_TXFLR_TXFLR_GET(alt_read_word(ALT_I2C_TXFLR_ADDR(i2c_dev->location))); - - return ALT_E_SUCCESS; -} - -// -// Sets the current transmit FIFO threshold level value. -// -ALT_STATUS_CODE alt_i2c_tx_fifo_threshold_get(ALT_I2C_DEV_t *i2c_dev, - uint8_t *threshold) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - *threshold = ALT_I2C_TX_TL_TX_TL_GET(alt_read_word(ALT_I2C_TX_TL_ADDR(i2c_dev->location))); - - return ALT_E_SUCCESS; -} - -// -// Sets the current transmit FIFO threshold level value. -// -ALT_STATUS_CODE alt_i2c_tx_fifo_threshold_set(ALT_I2C_DEV_t *i2c_dev, - const uint8_t threshold) -{ - ALT_STATUS_CODE status = ALT_E_SUCCESS; - - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - bool already_enabled = (alt_i2c_is_enabled_helper(i2c_dev) == ALT_E_TRUE); - - if (already_enabled) - { - // Temporarily disable controller - status = alt_i2c_disable(i2c_dev); - if (status != ALT_E_SUCCESS) - { - return status; - } - } - - alt_replbits_word(ALT_I2C_TX_TL_ADDR(i2c_dev->location), - ALT_I2C_TX_TL_TX_TL_SET_MSK, - ALT_I2C_TX_TL_TX_TL_SET(threshold)); - - if (already_enabled) - { - // Re-enable controller - status = alt_i2c_enable(i2c_dev); - } - - return status; -} - -///// - -ALT_STATUS_CODE alt_i2c_rx_dma_threshold_get(ALT_I2C_DEV_t * i2c_dev, uint8_t * threshold) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - *threshold = ALT_I2C_DMA_RDLR_DMARDL_GET(alt_read_word(ALT_I2C_DMA_RDLR_ADDR(i2c_dev->location))); - return ALT_E_SUCCESS; -} - -ALT_STATUS_CODE alt_i2c_rx_dma_threshold_set(ALT_I2C_DEV_t * i2c_dev, uint8_t threshold) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - if (threshold > ALT_I2C_DMA_RDLR_DMARDL_SET_MSK) - { - return ALT_E_ARG_RANGE; - } - - alt_write_word(ALT_I2C_DMA_RDLR_ADDR(i2c_dev->location), threshold); - return ALT_E_SUCCESS; - -} - -ALT_STATUS_CODE alt_i2c_tx_dma_threshold_get(ALT_I2C_DEV_t * i2c_dev, uint8_t * threshold) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - *threshold = ALT_I2C_DMA_TDLR_DMATDL_GET(alt_read_word(ALT_I2C_DMA_TDLR_ADDR(i2c_dev->location))); - return ALT_E_SUCCESS; -} - -ALT_STATUS_CODE alt_i2c_tx_dma_threshold_set(ALT_I2C_DEV_t * i2c_dev, uint8_t threshold) -{ - if (alt_i2c_checking(i2c_dev) == ALT_E_FALSE) - { - return ALT_E_BAD_ARG; - } - - if (threshold > ALT_I2C_DMA_TDLR_DMATDL_SET_MSK) - { - return ALT_E_ARG_RANGE; - } - - alt_write_word(ALT_I2C_DMA_TDLR_ADDR(i2c_dev->location), threshold); - return ALT_E_SUCCESS; -} |