blob: cd94f7a870eafdf467ee34a240726b021a98b165 [file] [log] [blame]
/****************************************************************************
* arch/arm/src/imxrt/imxrt_flexio.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <debug.h>
#include <arch/board/board.h>
#include <nuttx/arch.h>
#include <nuttx/wdog.h>
#include <nuttx/clock.h>
#include <nuttx/kmalloc.h>
#include <nuttx/mutex.h>
#include "arm_internal.h"
#include "barriers.h"
#include "imxrt_gpio.h"
#include "imxrt_periphclks.h"
#include "imxrt_flexio.h"
#include "hardware/imxrt_flexio.h"
#ifdef CONFIG_IMXRT_FLEXIO
/****************************************************************************
* Private Types
****************************************************************************/
/* The state of the FlexIO controller. */
struct imxrt_flexiodev_s
{
struct flexio_dev_s flexio; /* Externally visible part of the FlexIO interface */
uint32_t base; /* FlexIO controller register base address */
bool initialized; /* TRUE: Controller has been initialized */
};
struct flexio_config_s
{
bool enable_flexio; /* Enable/disable FlexIO module */
bool enable_indoze; /* Enable/disable FlexIO operation in doze mode */
bool enable_indebug; /* Enable/disable FlexIO operation in debug mode */
bool enable_fast_access; /* Enable/disable fast access to FlexIO registers, fast access requires
* the FlexIO clock to be at least twice the frequency of the bus clock. */
};
static void imxrt_flexio_reset(struct flexio_dev_s *dev);
static void imxrt_flexio_enable(struct flexio_dev_s *dev, bool enable);
static uint32_t imxrt_flexio_read_pin_input(struct flexio_dev_s *dev);
static uint8_t imxrt_flexio_get_shifter_state(struct flexio_dev_s *dev);
static void imxrt_flexio_set_shifter_config(struct flexio_dev_s *dev,
uint8_t index,
const struct flexio_shifter_config_s *shifter_config);
static void imxrt_flexio_set_timer_config(struct flexio_dev_s *dev,
uint8_t index,
const struct flexio_timer_config_s *timer_config);
static void imxrt_flexio_set_clock_mode(struct flexio_dev_s *dev,
uint8_t index,
enum flexio_timer_decrement_source_e clocksource);
static void imxrt_flexio_enable_shifter_status_interrupts(
struct flexio_dev_s *dev, uint32_t mask);
static void imxrt_flexio_disable_shifter_status_interrupts(
struct flexio_dev_s *dev, uint32_t mask);
static void imxrt_flexio_enable_shifter_error_interrupts(
struct flexio_dev_s *dev, uint32_t mask);
static void imxrt_flexio_disable_shifter_error_interrupts(
struct flexio_dev_s *dev, uint32_t mask);
static void imxrt_flexio_enable_timer_status_interrupts(
struct flexio_dev_s *dev, uint32_t mask);
static void imxrt_flexio_disable_timer_status_interrupts(
struct flexio_dev_s *dev, uint32_t mask);
static uint32_t imxrt_flexio_get_shifter_status_flags(
struct flexio_dev_s *dev);
static void imxrt_flexio_clear_shifter_status_flags(
struct flexio_dev_s *dev, uint32_t mask);
static uint32_t imxrt_flexio_get_shifter_error_flags(
struct flexio_dev_s *dev);
static void imxrt_flexio_clear_shifter_error_flags(
struct flexio_dev_s *dev, uint32_t mask);
static uint32_t imxrt_flexio_get_timer_status_flags(
struct flexio_dev_s *dev);
static void imxrt_flexio_clear_timer_status_flags(
struct flexio_dev_s *dev, uint32_t mask);
static void imxrt_flexio_enable_shifter_status_dma(
struct flexio_dev_s *dev, uint32_t mask, bool enable);
static uint32_t imxrt_flexio_get_shifter_buffer_address(
struct flexio_dev_s *dev,
enum flexio_shifter_buffer_type_e type, uint8_t index);
/****************************************************************************
* Private Data
****************************************************************************/
static const struct flexio_ops_s g_flexio_ops =
{
.reset = imxrt_flexio_reset,
.enable = imxrt_flexio_enable,
.read_pin_input = imxrt_flexio_read_pin_input,
.get_shifter_state = imxrt_flexio_get_shifter_state,
.set_clock_mode = imxrt_flexio_set_clock_mode,
.enable_shifter_status_interrupts =
imxrt_flexio_enable_shifter_status_interrupts,
.disable_shifter_status_interrupts =
imxrt_flexio_disable_shifter_status_interrupts,
.enable_shifter_error_interrupts =
imxrt_flexio_enable_shifter_error_interrupts,
.disable_shifter_error_interrupts =
imxrt_flexio_disable_shifter_error_interrupts,
.enable_timer_status_interrupts =
imxrt_flexio_enable_timer_status_interrupts,
.disable_timer_status_interrupts =
imxrt_flexio_disable_timer_status_interrupts,
.get_shifter_status_flags = imxrt_flexio_get_shifter_status_flags,
.clear_shifter_status_flags = imxrt_flexio_clear_shifter_status_flags,
.get_shifter_error_flags = imxrt_flexio_get_shifter_error_flags,
.clear_shifter_error_flags = imxrt_flexio_clear_shifter_error_flags,
.get_timer_status_flags = imxrt_flexio_get_timer_status_flags,
.clear_timer_status_flags = imxrt_flexio_clear_timer_status_flags,
.enable_shifter_status_dma = imxrt_flexio_enable_shifter_status_dma,
.get_shifter_buffer_address = imxrt_flexio_get_shifter_buffer_address,
.set_shifter_config = imxrt_flexio_set_shifter_config,
.set_timer_config = imxrt_flexio_set_timer_config,
};
#ifdef CONFIG_IMXRT_FLEXIO1
static struct imxrt_flexiodev_s g_flexio1_dev =
{
.flexio =
{
.ops = &g_flexio_ops,
},
.base = IMXRT_FLEXIO1_BASE,
};
#endif
#ifdef CONFIG_IMXRT_FLEXIO2
static struct imxrt_flexiodev_s g_flexio2_dev =
{
.flexio =
{
.ops = &g_flexio_ops,
},
.base = IMXRT_FLEXIO2_BASE,
};
#endif
#ifdef CONFIG_IMXRT_FLEXIO3
static struct imxrt_flexiodev_s g_flexio3_dev =
{
.flexio =
{
.ops = &g_flexio_ops,
},
.base = IMXRT_FLEXIO3_BASE,
};
#endif
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/* Utility functions */
static inline uint32_t imxrt_flexio_getreg32(struct flexio_dev_s *dev,
uint32_t offset);
static inline void imxrt_flexio_putreg32(struct flexio_dev_s *dev,
uint32_t value, uint32_t offset);
static inline void imxrt_flexio_modifyreg32(struct flexio_dev_s *dev,
unsigned int offset,
uint32_t clearbits,
uint32_t setbits);
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: imxrt_flexio_getreg32
*
* Description:
* Get the contents of the ENET register at offset
*
* Input Parameters:
* dev - private FlexIO device structure
* offset - offset to the register of interest
*
* Returned Value:
* The contents of the 32-bit register
*
****************************************************************************/
static inline uint32_t imxrt_flexio_getreg32(struct flexio_dev_s *dev,
uint32_t offset)
{
return getreg32(((struct imxrt_flexiodev_s *)dev)->base + offset);
}
/****************************************************************************
* Name: imxrt_flexio_putreg32
*
* Description:
* Atomically modify the specified bits in a memory mapped register
*
* Input Parameters:
* dev - private FlexIO device structure
* offset - offset to the register of interest
* clearbits - the 32-bit value to be written as 0s
* setbits - the 32-bit value to be written as 1s
*
* Returned Value:
* None
*
****************************************************************************/
static inline void imxrt_flexio_modifyreg32(struct flexio_dev_s *dev,
unsigned int offset,
uint32_t clearbits,
uint32_t setbits)
{
modifyreg32(((struct imxrt_flexiodev_s *)dev)->base + offset, clearbits,
setbits);
}
/****************************************************************************
* Name: imxrt_flexio_putreg32
*
* Description:
* Write a value to the FlexIO register at offset
*
* Input Parameters:
* dev - private FlexIO device structure
* value - the 32-bit value to be written
* offset - offset to the register of interest
*
* Returned Value:
* None
*
****************************************************************************/
static inline void imxrt_flexio_putreg32(struct flexio_dev_s *dev,
uint32_t value, uint32_t offset)
{
putreg32(value, ((struct imxrt_flexiodev_s *)dev)->base + offset);
}
/****************************************************************************
* Public Functions
****************************************************************************/
/* Resets the FlexIO module.
*
* param dev FlexIO device
*/
static void imxrt_flexio_reset(struct flexio_dev_s *dev)
{
/* do software reset, software reset operation affect all other FLEXIO
* registers except CTRL
*/
imxrt_flexio_modifyreg32(dev, IMXRT_FLEXIO_CTRL_OFFSET, 0,
FLEXIO_CTRL_SWRST_MASK);
imxrt_flexio_putreg32(dev, 0, IMXRT_FLEXIO_CTRL_OFFSET);
}
/* Enables the FlexIO module operation.
*
* param dev FlexIO device
* param enable true to enable, false to disable.
*/
static void imxrt_flexio_enable(struct flexio_dev_s *dev, bool enable)
{
if (enable)
{
imxrt_flexio_modifyreg32(dev, IMXRT_FLEXIO_CTRL_OFFSET, 0,
FLEXIO_CTRL_FLEXEN_MASK);
}
else
{
imxrt_flexio_modifyreg32(dev, IMXRT_FLEXIO_CTRL_OFFSET,
FLEXIO_CTRL_FLEXEN_MASK, 0);
}
}
/* Reads the input data on each of the FlexIO pins.
*
* param dev FlexIO device
* return FlexIO pin input data
*/
static uint32_t imxrt_flexio_read_pin_input(struct flexio_dev_s *dev)
{
uint32_t regval;
regval = imxrt_flexio_getreg32(dev, IMXRT_FLEXIO_PIN_OFFSET);
return regval;
}
/* Gets the current state pointer for state mode use.
*
* param dev FlexIO device
* return current State pointer
*/
static uint8_t imxrt_flexio_get_shifter_state(struct flexio_dev_s *dev)
{
uint32_t regval;
regval = imxrt_flexio_getreg32(dev, IMXRT_FLEXIO_SHIFTSTATE_OFFSET);
return ((uint8_t)regval & FLEXIO_SHIFTSTATE_STATE_MASK);
}
/* Configures the shifter with the shifter configuration. The configuration
* structure covers both the SHIFTCTL and SHIFTCFG registers. To configure
* the shifter to the proper mode, select which timer controls the shifter
* to shift, whether to generate start bit/stop bit, and the polarity of
* start bit and stop bit.
*
* Example
* code
* struct flexio_shifter_config_s config = {
* .timer_select = 0,
* .timer_polarity = FLEXIO_SHIFTER_TIMER_POLARITY_ON_POSITIVE,
* .pin_config = FLEXIO_PIN_CONFIG_OPEN_DRAIN_OR_BIDIRECTION,
* .pin_polarity = FLEXIO_PIN_ACTIVE_LOW,
* .shifter_mode = FLEXIO_SHIFTER_MODE_TRANSMIT,
* .input_source = FLEXIO_SHIFTER_INPUT_FROM_PIN,
* .shifter_stop = FLEXIO_SHIFTER_STOP_BIT_HIGH,
* .shifter_start = FLEXIO_SHIFTER_START_BIT_LOW
* };
* imxrt_flexio_set_shifter_config(dev, &config);
* endcode
*
* param dev FlexIO device address
* param index Shifter index
* param shifter_config Pointer to flexio_shifter_config_s structure
*/
static void imxrt_flexio_set_shifter_config(struct flexio_dev_s *dev,
uint8_t index,
const struct flexio_shifter_config_s *shifter_config)
{
uint32_t regval;
regval =
FLEXIO_SHIFTCFG_INSRC(shifter_config->input_source) |
FLEXIO_SHIFTCFG_PWIDTH(shifter_config->parallel_width) |
FLEXIO_SHIFTCFG_SSTOP(shifter_config->shifter_stop) |
FLEXIO_SHIFTCFG_SSTART(shifter_config->shifter_start);
imxrt_flexio_putreg32(dev, regval,
IMXRT_FLEXIO_SHIFTCFG0_OFFSET + index * 0x4);
regval =
FLEXIO_SHIFTCTL_TIMSEL(shifter_config->timer_select) |
FLEXIO_SHIFTCTL_TIMPOL(shifter_config->timer_polarity) |
FLEXIO_SHIFTCTL_PINCFG(shifter_config->pin_config) |
FLEXIO_SHIFTCTL_PINSEL(shifter_config->pin_select) |
FLEXIO_SHIFTCTL_PINPOL(shifter_config->pin_polarity) |
FLEXIO_SHIFTCTL_SMOD(shifter_config->shifter_mode);
imxrt_flexio_putreg32(dev, regval,
IMXRT_FLEXIO_SHIFTCTL0_OFFSET + index * 0x4);
}
/* Configures the timer with the timer configuration. The configuration
* structure covers both the TIMCTL and TIMCFG registers. To configure the
* timer to the proper mode, select trigger source for timer and the timer
* pin output and the timing for timer.
*
* Example
* code
* struct flexio_timer_config_s config = {
* .trigger_select = FLEXIO_TIMER_TRIGGER_SEL_SHIFTnSTAT(0),
* .trigger_polarity = FLEXIO_TIMER_TRIGGER_POLARITY_ACTIVE_LOW,
* .trigger_source = FLEXIO_TIMER_TRIGGER_SOURCE_INTERNAL,
* .pin_config = FLEXIO_PIN_CONFIG_OPEN_DRAIN_OR_BIDIRECTION,
* .pin_select = 0,
* .pin_polarity = FLEXIO_PIN_ACTIVE_HIGH,
* .timer_mode = FLEXIO_TIMER_MODE_DUAL8_BIT_BAUD_BIT,
* .timer_output = FLEXIO_TIMER_OUTPUT_ZERO_NOT_AFFECTED_BY_RESET,
* .timer_decrement =
* FLEXIO_TIMER_DEC_SRC_ON_FLEX_IO_CLOCK_SHIFT_TIMER_OUTPUT,
* .timer_reset = FLEXIO_TIMER_RESET_ON_TIMER_PIN_EQUAL_TO_TIMER_OUTPUT,
* .timer_disable = FLEXIO_TIMER_DISABLE_ON_TIMER_COMPARE,
* .timer_enable = FLEXIO_TIMER_ENABLE_ON_TRIGGER_HIGH,
* .timer_stop = FLEXIO_TIMER_STOP_BIT_ENABLE_ON_TIMER_DISABLE,
* .timer_start = FLEXIO_TIMER_START_BIT_ENABLED
* };
* imxrt_flexio_set_timer_config(dev, &config);
* endcode
*
* param dev FlexIO peripheral dev address
* param index Timer index
* param timer_config Pointer to the flexio_timer_config_s structure
*/
static void imxrt_flexio_set_timer_config(struct flexio_dev_s *dev,
uint8_t index,
const struct flexio_timer_config_s *timer_config)
{
uint32_t regval;
regval =
FLEXIO_TIMCFG_TIMOUT(timer_config->timer_output) |
FLEXIO_TIMCFG_TIMDEC(timer_config->timer_decrement) |
FLEXIO_TIMCFG_TIMRST(timer_config->timer_reset) |
FLEXIO_TIMCFG_TIMDIS(timer_config->timer_disable) |
FLEXIO_TIMCFG_TIMENA(timer_config->timer_enable) |
FLEXIO_TIMCFG_TSTOP(timer_config->timer_stop) |
FLEXIO_TIMCFG_TSTART(timer_config->timer_start);
imxrt_flexio_putreg32(dev, regval,
IMXRT_FLEXIO_TIMCFG0_OFFSET + index * 0x4);
regval = FLEXIO_TIMCMP_CMP(timer_config->timer_compare);
imxrt_flexio_putreg32(dev, regval,
IMXRT_FLEXIO_TIMCMP0_OFFSET + index * 0x4);
regval =
FLEXIO_TIMCTL_TRGSEL(timer_config->trigger_select) |
FLEXIO_TIMCTL_TRGPOL(timer_config->trigger_polarity) |
FLEXIO_TIMCTL_TRGSRC(timer_config->trigger_source) |
FLEXIO_TIMCTL_PINCFG(timer_config->pin_config) |
FLEXIO_TIMCTL_PINSEL(timer_config->pin_select) |
FLEXIO_TIMCTL_PINPOL(timer_config->pin_polarity) |
FLEXIO_TIMCTL_TIMOD(timer_config->timer_mode);
imxrt_flexio_putreg32(dev, regval,
IMXRT_FLEXIO_TIMCTL0_OFFSET + index * 0x4);
}
/* This function set the value of the prescaler on flexio channels
*
* param base Pointer to the FlexIO simulated peripheral type.
* param clocksource Set clock value
*/
static void imxrt_flexio_set_clock_mode(struct flexio_dev_s *dev,
uint8_t index,
enum flexio_timer_decrement_source_e clocksource)
{
imxrt_flexio_modifyreg32(dev, IMXRT_FLEXIO_TIMCFG0_OFFSET + index * 0x4,
FLEXIO_TIMCFG_TIMDEC_MASK,
FLEXIO_TIMCFG_TIMDEC(clocksource));
}
/* Enables the shifter status interrupt. The interrupt generates when the
* corresponding SSF is set.
*
* param dev FlexIO device
* param mask The shifter status mask which can be calculated by
* (1 << shifter index)
* note For multiple shifter status interrupt enable, for example, two
* shifter status enable, can calculate the mask by using
* ((1 << shifter index0) | (1 << shifter index1))
*/
static void imxrt_flexio_enable_shifter_status_interrupts(
struct flexio_dev_s *dev, uint32_t mask)
{
imxrt_flexio_modifyreg32(dev, IMXRT_FLEXIO_SHIFTSIEN_OFFSET, 0, mask);
}
/* Disables the shifter status interrupt. The interrupt won't generate when
* the corresponding SSF is set.
*
* param dev FlexIO device
* param mask The shifter status mask which can be calculated by
* (1 << shifter index)
* note For multiple shifter status interrupt enable, for example, two
* shifter status enable, can calculate the mask by using
* ((1 << shifter index0) | (1 << shifter index1))
*/
static void imxrt_flexio_disable_shifter_status_interrupts(
struct flexio_dev_s *dev, uint32_t mask)
{
imxrt_flexio_modifyreg32(dev, IMXRT_FLEXIO_SHIFTSIEN_OFFSET, mask, 0);
}
/* Enables the shifter error interrupt. The interrupt generates when the
* corresponding SEF is set.
*
* param dev FlexIO device
* param mask The shifter error mask which can be calculated by
* (1 << shifter index)
* note For multiple shifter error interrupt enable, for example, two shifter
* error enable, can calculate the mask by using ((1 << shifter index0)
* | (1 << shifter index1))
*/
static void imxrt_flexio_enable_shifter_error_interrupts(
struct flexio_dev_s *dev, uint32_t mask)
{
imxrt_flexio_modifyreg32(dev, IMXRT_FLEXIO_SHIFTEIEN_OFFSET, 0, mask);
}
/* Disables the shifter error interrupt. The interrupt won't generate when
* the corresponding SEF is set.
*
* param dev FlexIO device
* param mask The shifter error mask which can be calculated by
* (1 << shifter index)
* note For multiple shifter error interrupt enable, for example, two shifter
* error enable, can calculate the mask by using ((1 << shifter index0)
* | (1 << shifter index1))
*/
static void imxrt_flexio_disable_shifter_error_interrupts(
struct flexio_dev_s *dev, uint32_t mask)
{
imxrt_flexio_modifyreg32(dev, IMXRT_FLEXIO_SHIFTEIEN_OFFSET, mask, 0);
}
/* Enables the timer status interrupt. The interrupt generates when the
* corresponding SSF is set.
*
* param dev FlexIO device
* param mask The timer status mask which can be calculated by
* (1 << timer index)
* note For multiple timer status interrupt enable, for example, two timer
* status enable, can calculate the mask by using ((1 << timer index0) |
* (1 << timer index1))
*/
static void imxrt_flexio_enable_timer_status_interrupts(
struct flexio_dev_s *dev, uint32_t mask)
{
imxrt_flexio_modifyreg32(dev, IMXRT_FLEXIO_TIMIEN_OFFSET, 0, mask);
}
/* Disables the timer status interrupt. The interrupt won't generate when the
* corresponding SSF is set.
*
* param dev FlexIO device
* param mask The timer status mask which can be calculated by
* (1 << timer index)
* note For multiple timer status interrupt enable, for example, two timer
* status enable, can calculate the mask by using ((1 << timer index0) |
* (1 << timer index1))
*/
static void imxrt_flexio_disable_timer_status_interrupts(
struct flexio_dev_s *dev, uint32_t mask)
{
imxrt_flexio_modifyreg32(dev, IMXRT_FLEXIO_TIMIEN_OFFSET, mask, 0);
}
/* Gets the shifter status flags.
*
* param dev FlexIO device
* return Shifter status flags
*/
static uint32_t imxrt_flexio_get_shifter_status_flags(
struct flexio_dev_s *dev)
{
uint32_t regval;
regval = imxrt_flexio_getreg32(dev, IMXRT_FLEXIO_SHIFTSTAT_OFFSET);
return (regval & FLEXIO_SHIFTSTAT_SSF_MASK);
}
/* Clears the shifter status flags.
*
* param dev FlexIO device
* param mask The shifter status mask which can be calculated by
* (1 << shifter index)
* note For clearing multiple shifter status flags, for example, two shifter
* status flags, can calculate the mask by using ((1 << shifter index0)
* | (1 << shifter index1))
*/
static void imxrt_flexio_clear_shifter_status_flags(
struct flexio_dev_s *dev, uint32_t mask)
{
imxrt_flexio_putreg32(dev, mask, IMXRT_FLEXIO_SHIFTSTAT_OFFSET);
}
/* Gets the shifter error flags.
*
* param dev FlexIO device
* return Shifter error flags
*/
static uint32_t imxrt_flexio_get_shifter_error_flags(
struct flexio_dev_s *dev)
{
uint32_t regval;
regval = imxrt_flexio_getreg32(dev, IMXRT_FLEXIO_SHIFTERR_OFFSET);
return (regval & FLEXIO_SHIFTERR_SEF_MASK);
}
/* Clears the shifter error flags.
*
* param dev FlexIO device
* param mask The shifter error mask which can be calculated by
* (1 << shifter index)
*
* note For clearing multiple shifter error flags, for example, two shifter
* error flags, can calculate the mask by using ((1 << shifter index0) |
* (1 << shifter index1))
*/
static void imxrt_flexio_clear_shifter_error_flags(struct flexio_dev_s *dev,
uint32_t mask)
{
imxrt_flexio_putreg32(dev, mask, IMXRT_FLEXIO_SHIFTERR_OFFSET);
}
/* Gets the timer status flags.
*
* param dev FlexIO device
* return Timer status flags
*/
static uint32_t imxrt_flexio_get_timer_status_flags(struct flexio_dev_s *dev)
{
uint32_t regval;
regval = imxrt_flexio_getreg32(dev, IMXRT_FLEXIO_TIMSTAT_OFFSET);
return (regval & FLEXIO_TIMSTAT_TSF_MASK);
}
/* Clears the timer status flags.
*
* param dev FlexIO device
* param mask The timer status mask which can be calculated by
* (1 << timer index)
*
* note For clearing multiple timer status flags, for example, two timer
* status flags, can calculate the mask by using ((1 << timer index0) |
* (1 << timer index1))
*/
static void imxrt_flexio_clear_timer_status_flags(struct flexio_dev_s *dev,
uint32_t mask)
{
imxrt_flexio_putreg32(dev, mask, IMXRT_FLEXIO_TIMSTAT_OFFSET);
}
/* Enables/disables the shifter status DMA. The DMA request generates when
* the corresponding SSF is set.
*
* For multiple shifter status DMA enables, for example, calculate
* the mask by using ((1 << shifter index0) | (1 << shifter index1))
*
* param dev FlexIO device
* param mask The shifter status mask which can be calculated by
* (1 << shifter index)
* param enable True to enable, false to disable.
*/
static void imxrt_flexio_enable_shifter_status_dma(struct flexio_dev_s *dev,
uint32_t mask, bool enable)
{
if (enable)
{
imxrt_flexio_modifyreg32(dev, IMXRT_FLEXIO_SHIFTSDEN_OFFSET, 0, mask);
}
else
{
imxrt_flexio_modifyreg32(dev, IMXRT_FLEXIO_SHIFTSDEN_OFFSET, mask, 0);
}
}
/* Configures the FlexIO with a FlexIO configuration. The configuration
* structure can be filled by the user or be set with default values by
* imxrt_flexio_get_default_config().
*
* Example
* code
* struct flexio_config_s config = {
* .enable_flexio = true,
* .enable_indoze = false,
* .enable_indebug = true,
* .enable_fast_access = false
* };
* imxrt_flexio_init(base, &config);
* endcode
*
* param dev FlexIO device
* param user_config pointer to flexio_config_s structure
*/
static void imxrt_flexio_init(struct flexio_dev_s *dev,
const struct flexio_config_s *user_config)
{
imxrt_flexio_reset(dev);
imxrt_flexio_modifyreg32(dev, IMXRT_FLEXIO_CTRL_OFFSET,
(FLEXIO_CTRL_DOZEN_MASK |
FLEXIO_CTRL_DBGE_MASK |
FLEXIO_CTRL_FASTACC_MASK |
FLEXIO_CTRL_FLEXEN_MASK),
(FLEXIO_CTRL_DBGE(user_config->enable_indebug) |
FLEXIO_CTRL_FASTACC(user_config->enable_fast_access) |
FLEXIO_CTRL_FLEXEN(user_config->enable_flexio)));
if (!user_config->enable_indoze)
{
imxrt_flexio_modifyreg32(dev, IMXRT_FLEXIO_CTRL_OFFSET, 0,
FLEXIO_CTRL_DOZEN_MASK);
}
}
/* Gets the default configuration to configure the FlexIO module.
*
* Example:
* code
* struct flexio_config_s config;
* imxrt_flexio_get_default_config(&config);
* endcode
*
* param user_config pointer to flexio_config_s structure
*/
static void imxrt_flexio_get_default_config(
struct flexio_config_s *user_config)
{
DEBUGASSERT(user_config != NULL);
memset(user_config, 0, sizeof(*user_config));
user_config->enable_flexio = true;
user_config->enable_indoze = false;
user_config->enable_indebug = true;
user_config->enable_fast_access = false;
}
/* Gets the shifter buffer address for the DMA transfer usage.
*
* param dev FlexIO peripheral dev address
* param type Shifter type of enum flexio_shifter_buffer_type_e
* param index Shifter index
* return Corresponding shifter buffer address
*/
static uint32_t imxrt_flexio_get_shifter_buffer_address(
struct flexio_dev_s *dev,
enum flexio_shifter_buffer_type_e type, uint8_t index)
{
uint32_t address = 0;
UNUSED(dev);
DEBUGASSERT(index < FLEXIO_SHIFTBUF_COUNT);
switch (type)
{
case FLEXIO_SHIFTER_BUFFER:
address = (uint32_t)(((struct imxrt_flexiodev_s *)dev)->base +
IMXRT_FLEXIO_SHIFTBUF0_OFFSET + index * 0x4);
break;
case FLEXIO_SHIFTER_BUFFER_BIT_SWAPPED:
address = (uint32_t)(((struct imxrt_flexiodev_s *)dev)->base +
IMXRT_FLEXIO_SHIFTBUFBIS0_OFFSET + index * 0x4);
break;
case FLEXIO_SHIFTER_BUFFER_BYTE_SWAPPED:
address = (uint32_t)(((struct imxrt_flexiodev_s *)dev)->base +
IMXRT_FLEXIO_SHIFTBUFBYS0_OFFSET + index * 0x4);
break;
case FLEXIO_SHIFTER_BUFFER_BIT_BYTE_SWAPPED:
address = (uint32_t)(((struct imxrt_flexiodev_s *)dev)->base +
IMXRT_FLEXIO_SHIFTBUFBBS0_OFFSET + index * 0x4);
break;
case FLEXIO_SHIFTER_BUFFER_NIBBLE_BYTE_SWAPPED:
address = (uint32_t)(((struct imxrt_flexiodev_s *)dev)->base +
IMXRT_FLEXIO_SHIFTBUFNBS0_OFFSET + index * 0x4);
break;
case FLEXIO_SHIFTER_BUFFER_HALF_WORD_SWAPPED:
address = (uint32_t)(((struct imxrt_flexiodev_s *)dev)->base +
IMXRT_FLEXIO_SHIFTBUFHWS0_OFFSET + index * 0x4);
break;
case FLEXIO_SHIFTER_BUFFER_NIBBLE_SWAPPED:
address = (uint32_t)(((struct imxrt_flexiodev_s *)dev)->base +
IMXRT_FLEXIO_SHIFTBUFNIS0_OFFSET + index * 0x4);
break;
default:
address = (uint32_t)(((struct imxrt_flexiodev_s *)dev)->base +
IMXRT_FLEXIO_SHIFTBUF0_OFFSET + index * 0x4);
break;
}
return address;
}
/****************************************************************************
* Name: imxrt_flexio_initialize
*
* Description:
* Initialize the selected FlexIO port in master mode
*
* Input Parameters:
* intf - Interface number(must be zero)
*
* Returned Value:
* Valid FlexIO device structure reference on success; a NULL on failure
*
****************************************************************************/
struct flexio_dev_s *imxrt_flexio_initialize(int intf)
{
struct imxrt_flexiodev_s *priv;
struct flexio_config_s flexio_config;
switch (intf)
{
#ifdef CONFIG_IMXRT_FLEXIO1
case 1:
priv = &g_flexio1_dev;
imxrt_clockall_flexio1();
break;
#endif
#ifdef CONFIG_IMXRT_FLEXIO2
case 2:
priv = &g_flexio2_dev;
imxrt_clockall_flexio2();
break;
#endif
#ifdef CONFIG_IMXRT_FLEXIO3
case 3:
priv = &g_flexio3_dev;
imxrt_clockall_flexio2();
break;
#endif
default:
return NULL;
}
/* Has the FlexSPI hardware been initialized? */
if (!priv->initialized)
{
/* Now perform one time initialization */
/* Perform hardware initialization. Puts the FlexIO into an active
* state.
*/
imxrt_flexio_get_default_config(&flexio_config);
imxrt_flexio_init((struct flexio_dev_s *)priv, &flexio_config);
/* Enable interrupts at the NVIC */
priv->initialized = true;
}
return &priv->flexio;
}
#endif /* CONFIG_IMXRT_FLEXIO */