forked from xuos/xiuos
support gpio on k210 on nuttx
This commit is contained in:
parent
df32ed24ed
commit
c815bb3b6e
|
@ -39,82 +39,110 @@
|
|||
#include "k210_memorymap.h"
|
||||
#include "k210_gpio.h"
|
||||
#include "k210_fpioa.h"
|
||||
#include "k210_sysctl.h"
|
||||
|
||||
#define GPIO_MAX_PINNO 8
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
* Private Function declaration
|
||||
****************************************************************************/
|
||||
|
||||
#define GPIO_INPUT_VAL_OFFSET 0x00
|
||||
#define GPIO_INPUT_EN_OFFSET 0x04
|
||||
#define GPIO_OUTPUT_EN_OFFSET 0x08
|
||||
#define GPIO_OUTPUT_VAL_OFFSET 0x0c
|
||||
#define GPIO_PULLUP_EN_OFFSET 0x10
|
||||
#define GPIO_DRIVE_OFFSET 0x14
|
||||
|
||||
#define GPIO_INPUT (K210_GPIO_BASE + GPIO_INPUT_VAL_OFFSET)
|
||||
#define GPIO_INPUT_EN (K210_GPIO_BASE + GPIO_INPUT_EN_OFFSET)
|
||||
#define GPIO_OUTPUT (K210_GPIO_BASE + GPIO_OUTPUT_VAL_OFFSET)
|
||||
#define GPIO_OUTPUT_EN (K210_GPIO_BASE + GPIO_OUTPUT_EN_OFFSET)
|
||||
static void set_bit(volatile uint32_t *bits, uint32_t mask, uint32_t value);
|
||||
static void set_bit_offset(volatile uint32_t *bits, uint32_t mask, size_t offset, uint32_t value);
|
||||
static void set_gpio_bit(volatile uint32_t *bits, size_t offset, uint32_t value);
|
||||
static uint32_t get_bit(volatile uint32_t *bits, uint32_t mask, size_t offset);
|
||||
static uint32_t get_gpio_bit(volatile uint32_t *bits, size_t offset);
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
void k210_gpio_set_direction(uint32_t io, gpio_drive_mode_t mode)
|
||||
volatile gpio_t *const gpio = (volatile gpio_t *)K210_GPIO_BASE;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function definition
|
||||
****************************************************************************/
|
||||
static void set_bit(volatile uint32_t *bits, uint32_t mask, uint32_t value)
|
||||
{
|
||||
DEBUGASSERT(io < K210_GPIO_MAX_PINNO);
|
||||
int io_number = k210_fpioa_get_io_by_function(K210_IO_FUNC_GPIO0 + io);
|
||||
DEBUGASSERT(io_number >= 0);
|
||||
|
||||
fpioa_pull_t pull = FPIOA_PULL_NONE;
|
||||
uint32_t dir = 0;
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case GPIO_DM_INPUT:
|
||||
pull = FPIOA_PULL_NONE;
|
||||
dir = 0;
|
||||
break;
|
||||
case GPIO_DM_INPUT_PULL_DOWN:
|
||||
pull = FPIOA_PULL_DOWN;
|
||||
dir = 0;
|
||||
break;
|
||||
case GPIO_DM_INPUT_PULL_UP:
|
||||
pull = FPIOA_PULL_UP;
|
||||
dir = 0;
|
||||
break;
|
||||
case GPIO_DM_OUTPUT:
|
||||
pull = FPIOA_PULL_DOWN;
|
||||
dir = 1;
|
||||
break;
|
||||
default:
|
||||
DEBUGASSERT(!"GPIO drive mode is not supported.");
|
||||
break;
|
||||
}
|
||||
|
||||
fpioa_set_io_pull(io_number, pull);
|
||||
uint32_t outbit = dir << io;
|
||||
uint32_t inbit = (!dir) << io;
|
||||
modifyreg32(GPIO_OUTPUT_EN, inbit, outbit);
|
||||
modifyreg32(GPIO_INPUT_EN, outbit, inbit);
|
||||
uint32_t org = (*bits) & ~mask;
|
||||
*bits = org | (value & mask);
|
||||
}
|
||||
|
||||
void k210_gpio_set_value(uint32_t io, bool val)
|
||||
static void set_bit_offset(volatile uint32_t *bits, uint32_t mask, size_t offset, uint32_t value)
|
||||
{
|
||||
uint32_t setbit = val << io;
|
||||
uint32_t clrbit = (!val) << io;
|
||||
modifyreg32(GPIO_OUTPUT, clrbit, setbit);
|
||||
set_bit(bits, mask << offset, value << offset);
|
||||
}
|
||||
|
||||
bool k210_gpio_get_value(uint32_t io)
|
||||
static void set_gpio_bit(volatile uint32_t *bits, size_t offset, uint32_t value)
|
||||
{
|
||||
uint32_t reg = getreg32(GPIO_INPUT);
|
||||
set_bit_offset(bits, 1, offset, value);
|
||||
}
|
||||
|
||||
if (reg & (1 << io))
|
||||
static uint32_t get_bit(volatile uint32_t *bits, uint32_t mask, size_t offset)
|
||||
{
|
||||
return ((*bits) & (mask << offset)) >> offset;
|
||||
}
|
||||
|
||||
static uint32_t get_gpio_bit(volatile uint32_t *bits, size_t offset)
|
||||
{
|
||||
return get_bit(bits, 1, offset);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function definition
|
||||
****************************************************************************/
|
||||
int gpio_init(void)
|
||||
{
|
||||
return sysctl_clock_enable(SYSCTL_CLOCK_GPIO);
|
||||
}
|
||||
|
||||
void gpio_set_drive_mode(uint8_t pin, gpio_drive_mode_t mode)
|
||||
{
|
||||
DEBUGASSERT(pin < GPIO_MAX_PINNO);
|
||||
int io_number = fpioa_get_io_by_function(K210_IO_FUNC_GPIO0 + pin);
|
||||
DEBUGASSERT(io_number >= 0);
|
||||
|
||||
fpioa_pull_t pull;
|
||||
uint32_t dir;
|
||||
|
||||
switch(mode)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
case GPIO_DM_INPUT:
|
||||
pull = FPIOA_PULL_NONE;
|
||||
dir = 0;
|
||||
break;
|
||||
case GPIO_DM_INPUT_PULL_DOWN:
|
||||
pull = FPIOA_PULL_DOWN;
|
||||
dir = 0;
|
||||
break;
|
||||
case GPIO_DM_INPUT_PULL_UP:
|
||||
pull = FPIOA_PULL_UP;
|
||||
dir = 0;
|
||||
break;
|
||||
case GPIO_DM_OUTPUT:
|
||||
pull = FPIOA_PULL_DOWN;
|
||||
dir = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
fpioa_set_io_pull(io_number, pull);
|
||||
set_gpio_bit(gpio->direction.u32, pin, dir);
|
||||
}
|
||||
|
||||
gpio_pin_value_t gpio_get_pin(uint8_t pin)
|
||||
{
|
||||
DEBUGASSERT(pin < GPIO_MAX_PINNO);
|
||||
uint32_t dir = get_gpio_bit(gpio->direction.u32, pin);
|
||||
volatile uint32_t *reg = dir ? gpio->data_output.u32 : gpio->data_input.u32;
|
||||
return get_gpio_bit(reg, pin);
|
||||
}
|
||||
|
||||
void gpio_set_pin(uint8_t pin, gpio_pin_value_t value)
|
||||
{
|
||||
DEBUGASSERT(pin < GPIO_MAX_PINNO);
|
||||
uint32_t dir = get_gpio_bit(gpio->direction.u32, pin);
|
||||
volatile uint32_t *reg = dir ? gpio->data_output.u32 : gpio->data_input.u32;
|
||||
DEBUGASSERT(dir == 1);
|
||||
set_gpio_bit(reg, pin, value);
|
||||
}
|
||||
|
|
|
@ -38,52 +38,127 @@
|
|||
#include <stdbool.h>
|
||||
#include "k210_gpio_common.h"
|
||||
|
||||
typedef struct _gpio_bits
|
||||
{
|
||||
uint32_t b0 : 1;
|
||||
uint32_t b1 : 1;
|
||||
uint32_t b2 : 1;
|
||||
uint32_t b3 : 1;
|
||||
uint32_t b4 : 1;
|
||||
uint32_t b5 : 1;
|
||||
uint32_t b6 : 1;
|
||||
uint32_t b7 : 1;
|
||||
uint32_t b8 : 1;
|
||||
uint32_t b9 : 1;
|
||||
uint32_t b10 : 1;
|
||||
uint32_t b11 : 1;
|
||||
uint32_t b12 : 1;
|
||||
uint32_t b13 : 1;
|
||||
uint32_t b14 : 1;
|
||||
uint32_t b15 : 1;
|
||||
uint32_t b16 : 1;
|
||||
uint32_t b17 : 1;
|
||||
uint32_t b18 : 1;
|
||||
uint32_t b19 : 1;
|
||||
uint32_t b20 : 1;
|
||||
uint32_t b21 : 1;
|
||||
uint32_t b22 : 1;
|
||||
uint32_t b23 : 1;
|
||||
uint32_t b24 : 1;
|
||||
uint32_t b25 : 1;
|
||||
uint32_t b26 : 1;
|
||||
uint32_t b27 : 1;
|
||||
uint32_t b28 : 1;
|
||||
uint32_t b29 : 1;
|
||||
uint32_t b30 : 1;
|
||||
uint32_t b31 : 1;
|
||||
} __attribute__((packed, aligned(4))) gpio_bits_t;
|
||||
|
||||
/* Structure of templates for accessing GPIO registers */
|
||||
typedef union _gpio_access_tp
|
||||
{
|
||||
/* 32x1 bit mode */
|
||||
uint32_t u32[1];
|
||||
/* 16x2 bit mode */
|
||||
uint16_t u16[2];
|
||||
/* 8x4 bit mode */
|
||||
uint8_t u8[4];
|
||||
/* 1 bit mode */
|
||||
gpio_bits_t bits;
|
||||
} __attribute__((packed, aligned(4))) gpio_access_tp_t;
|
||||
|
||||
/* The GPIO address map */
|
||||
typedef struct _gpio
|
||||
{
|
||||
/* Offset 0x00: Data (output) registers */
|
||||
gpio_access_tp_t data_output;
|
||||
/* Offset 0x04: Data direction registers */
|
||||
gpio_access_tp_t direction;
|
||||
/* Offset 0x08: Data source registers */
|
||||
gpio_access_tp_t source;
|
||||
/* Offset 0x10 - 0x2f: Unused registers, 9x4 bytes */
|
||||
uint32_t unused_0[9];
|
||||
/* Offset 0x30: Interrupt enable/disable registers */
|
||||
gpio_access_tp_t interrupt_enable;
|
||||
/* Offset 0x34: Interrupt mask registers */
|
||||
gpio_access_tp_t interrupt_mask;
|
||||
/* Offset 0x38: Interrupt level registers */
|
||||
gpio_access_tp_t interrupt_level;
|
||||
/* Offset 0x3c: Interrupt polarity registers */
|
||||
gpio_access_tp_t interrupt_polarity;
|
||||
/* Offset 0x40: Interrupt status registers */
|
||||
gpio_access_tp_t interrupt_status;
|
||||
/* Offset 0x44: Raw interrupt status registers */
|
||||
gpio_access_tp_t interrupt_status_raw;
|
||||
/* Offset 0x48: Interrupt debounce registers */
|
||||
gpio_access_tp_t interrupt_debounce;
|
||||
/* Offset 0x4c: Registers for clearing interrupts */
|
||||
gpio_access_tp_t interrupt_clear;
|
||||
/* Offset 0x50: External port (data input) registers */
|
||||
gpio_access_tp_t data_input;
|
||||
/* Offset 0x54 - 0x5f: Unused registers, 3x4 bytes */
|
||||
uint32_t unused_1[3];
|
||||
/* Offset 0x60: Sync level registers */
|
||||
gpio_access_tp_t sync_level;
|
||||
/* Offset 0x64: ID code */
|
||||
gpio_access_tp_t id_code;
|
||||
/* Offset 0x68: Interrupt both edge type */
|
||||
gpio_access_tp_t interrupt_bothedge;
|
||||
} __attribute__((packed, aligned(4))) gpio_t;
|
||||
|
||||
/* Bus GPIO object instance */
|
||||
extern volatile gpio_t *const gpio;
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions Prototypes
|
||||
****************************************************************************/
|
||||
/**
|
||||
* @brief Gpio initialize
|
||||
* @return - 0:Success,Other:Fail
|
||||
*/
|
||||
int gpio_init(void);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: k210_gpio_set_direction
|
||||
*
|
||||
* Description:
|
||||
* Set gpiohs direction
|
||||
*
|
||||
* Input Parameters:
|
||||
* io - IO number
|
||||
* dir - true for output, false for input
|
||||
*
|
||||
****************************************************************************/
|
||||
/**
|
||||
* @brief Set Gpio drive mode
|
||||
* @param[in] pin Gpio pin
|
||||
* @param[in] mode Gpio pin drive mode
|
||||
*/
|
||||
void gpio_set_drive_mode(uint8_t pin, gpio_drive_mode_t mode);
|
||||
|
||||
void k210_gpio_set_direction(uint32_t io, gpio_drive_mode_t mode);
|
||||
/**
|
||||
* @brief Get Gpio pin value
|
||||
* @param[in] pin Gpio pin
|
||||
* @return Pin value
|
||||
* GPIO_PV_Low Gpio pin low
|
||||
* GPIO_PV_High Gpio pin high
|
||||
*/
|
||||
gpio_pin_value_t gpio_get_pin(uint8_t pin);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: k210_gpio_set_value
|
||||
*
|
||||
* Description:
|
||||
* Set gpiohs direction
|
||||
*
|
||||
* Input Parameters:
|
||||
* io - IO number
|
||||
* dir - true for high level, false for low level
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void k210_gpio_set_value(uint32_t io, bool val);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: k210_gpio_get_value
|
||||
*
|
||||
* Description:
|
||||
* Get gpiohs level
|
||||
*
|
||||
* Input Parameters:
|
||||
* io - IO number
|
||||
*
|
||||
* Returned Value:
|
||||
* true for high level, false for low level
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
bool k210_gpio_get_value(uint32_t io);
|
||||
/**
|
||||
* @brief Set Gpio pin value
|
||||
* @param[in] pin Gpio pin
|
||||
* @param[in] value Gpio pin value
|
||||
*/
|
||||
void gpio_set_pin(uint8_t pin, gpio_pin_value_t value);
|
||||
|
||||
#endif /* __ARCH_RISCV_SRC_K210_K210_GPIO_H */
|
||||
|
|
Loading…
Reference in New Issue