summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/src/hwmgr/alt_i2c.c
diff options
context:
space:
mode:
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.c2004
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;
-}