900 lines
30 KiB
C
900 lines
30 KiB
C
/****************************************************************************
|
|
* arch/arm/src/imxrt/imxrt_flexio.c
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* 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/barriers.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 "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 */
|