/******************************************************************************* | |
* (c) Copyright 2008-2013 Microsemi SoC Products Group. All rights reserved. | |
* | |
* SmartFusion2 microcontroller subsystem GPIO bare metal driver implementation. | |
* | |
* SVN $Revision: 5394 $ | |
* SVN $Date: 2013-03-27 20:56:36 +0000 (Wed, 27 Mar 2013) $ | |
*/ | |
#include "mss_gpio.h" | |
#include "../../CMSIS/mss_assert.h" | |
#ifdef __cplusplus | |
extern "C" { | |
#endif | |
/*-------------------------------------------------------------------------*//** | |
* Defines. | |
*/ | |
#define GPIO_INT_ENABLE_MASK ((uint32_t)0x00000008uL) | |
#define OUTPUT_BUFFER_ENABLE_MASK 0x00000004u | |
#define NB_OF_GPIO ((uint32_t)32) | |
/*-------------------------------------------------------------------------*//** | |
* Lookup table of GPIO configuration registers address indexed on GPIO ID. | |
*/ | |
static uint32_t volatile * const g_config_reg_lut[NB_OF_GPIO] = | |
{ | |
&(GPIO->GPIO_0_CFG), | |
&(GPIO->GPIO_1_CFG), | |
&(GPIO->GPIO_2_CFG), | |
&(GPIO->GPIO_3_CFG), | |
&(GPIO->GPIO_4_CFG), | |
&(GPIO->GPIO_5_CFG), | |
&(GPIO->GPIO_6_CFG), | |
&(GPIO->GPIO_7_CFG), | |
&(GPIO->GPIO_8_CFG), | |
&(GPIO->GPIO_9_CFG), | |
&(GPIO->GPIO_10_CFG), | |
&(GPIO->GPIO_11_CFG), | |
&(GPIO->GPIO_12_CFG), | |
&(GPIO->GPIO_13_CFG), | |
&(GPIO->GPIO_14_CFG), | |
&(GPIO->GPIO_15_CFG), | |
&(GPIO->GPIO_16_CFG), | |
&(GPIO->GPIO_17_CFG), | |
&(GPIO->GPIO_18_CFG), | |
&(GPIO->GPIO_19_CFG), | |
&(GPIO->GPIO_20_CFG), | |
&(GPIO->GPIO_21_CFG), | |
&(GPIO->GPIO_22_CFG), | |
&(GPIO->GPIO_23_CFG), | |
&(GPIO->GPIO_24_CFG), | |
&(GPIO->GPIO_25_CFG), | |
&(GPIO->GPIO_26_CFG), | |
&(GPIO->GPIO_27_CFG), | |
&(GPIO->GPIO_28_CFG), | |
&(GPIO->GPIO_29_CFG), | |
&(GPIO->GPIO_30_CFG), | |
&(GPIO->GPIO_31_CFG) | |
}; | |
/*-------------------------------------------------------------------------*//** | |
* Lookup table of Cortex-M3 GPIO interrupt number indexed on GPIO ID. | |
*/ | |
static const IRQn_Type g_gpio_irqn_lut[NB_OF_GPIO] = | |
{ | |
GPIO0_IRQn, | |
GPIO1_IRQn, | |
GPIO2_IRQn, | |
GPIO3_IRQn, | |
GPIO4_IRQn, | |
GPIO5_IRQn, | |
GPIO6_IRQn, | |
GPIO7_IRQn, | |
GPIO8_IRQn, | |
GPIO9_IRQn, | |
GPIO10_IRQn, | |
GPIO11_IRQn, | |
GPIO12_IRQn, | |
GPIO13_IRQn, | |
GPIO14_IRQn, | |
GPIO15_IRQn, | |
GPIO16_IRQn, | |
GPIO17_IRQn, | |
GPIO18_IRQn, | |
GPIO19_IRQn, | |
GPIO20_IRQn, | |
GPIO21_IRQn, | |
GPIO22_IRQn, | |
GPIO23_IRQn, | |
GPIO24_IRQn, | |
GPIO25_IRQn, | |
GPIO26_IRQn, | |
GPIO27_IRQn, | |
GPIO28_IRQn, | |
GPIO29_IRQn, | |
GPIO30_IRQn, | |
GPIO31_IRQn | |
}; | |
/*-------------------------------------------------------------------------*//** | |
* MSS_GPIO_init | |
* See "mss_gpio.h" for details of how to use this function. | |
*/ | |
void MSS_GPIO_init( void ) | |
{ | |
uint32_t inc; | |
/* reset MSS GPIO hardware */ | |
SYSREG->SOFT_RST_CR |= SYSREG_GPIO_SOFTRESET_MASK; | |
SYSREG->SOFT_RST_CR |= (SYSREG_GPIO_7_0_SOFTRESET_MASK | | |
SYSREG_GPIO_15_8_SOFTRESET_MASK | | |
SYSREG_GPIO_23_16_SOFTRESET_MASK | | |
SYSREG_GPIO_31_24_SOFTRESET_MASK); | |
/* Clear any previously pended MSS GPIO interrupt */ | |
for(inc = 0U; inc < NB_OF_GPIO; ++inc) | |
{ | |
NVIC_DisableIRQ(g_gpio_irqn_lut[inc]); | |
NVIC_ClearPendingIRQ(g_gpio_irqn_lut[inc]); | |
} | |
/* Take MSS GPIO hardware out of reset. */ | |
SYSREG->SOFT_RST_CR &= ~(SYSREG_GPIO_7_0_SOFTRESET_MASK | | |
SYSREG_GPIO_15_8_SOFTRESET_MASK | | |
SYSREG_GPIO_23_16_SOFTRESET_MASK | | |
SYSREG_GPIO_31_24_SOFTRESET_MASK); | |
SYSREG->SOFT_RST_CR &= ~SYSREG_GPIO_SOFTRESET_MASK; | |
} | |
/*-------------------------------------------------------------------------*//** | |
* MSS_GPIO_config | |
* See "mss_gpio.h" for details of how to use this function. | |
*/ | |
void MSS_GPIO_config | |
( | |
mss_gpio_id_t port_id, | |
uint32_t config | |
) | |
{ | |
uint32_t gpio_idx = (uint32_t)port_id; | |
ASSERT(gpio_idx < NB_OF_GPIO); | |
if(gpio_idx < NB_OF_GPIO) | |
{ | |
*(g_config_reg_lut[gpio_idx]) = config; | |
} | |
} | |
/*-------------------------------------------------------------------------*//** | |
* MSS_GPIO_set_output | |
* See "mss_gpio.h" for details of how to use this function. | |
*/ | |
void MSS_GPIO_set_output | |
( | |
mss_gpio_id_t port_id, | |
uint8_t value | |
) | |
{ | |
uint32_t gpio_setting; | |
uint32_t gpio_idx = (uint32_t)port_id; | |
ASSERT(gpio_idx < NB_OF_GPIO); | |
if(gpio_idx < NB_OF_GPIO) | |
{ | |
gpio_setting = GPIO->GPIO_OUT; | |
gpio_setting &= ~((uint32_t)0x01u << gpio_idx); | |
gpio_setting |= ((uint32_t)value & 0x01u) << gpio_idx; | |
GPIO->GPIO_OUT = gpio_setting; | |
} | |
} | |
/*-------------------------------------------------------------------------*//** | |
* MSS_GPIO_drive_inout | |
* See "mss_gpio.h" for details of how to use this function. | |
*/ | |
void MSS_GPIO_drive_inout | |
( | |
mss_gpio_id_t port_id, | |
mss_gpio_inout_state_t inout_state | |
) | |
{ | |
uint32_t outputs_state; | |
uint32_t config; | |
uint32_t gpio_idx = (uint32_t)port_id; | |
ASSERT(gpio_idx < NB_OF_GPIO); | |
if(gpio_idx < NB_OF_GPIO) | |
{ | |
switch(inout_state) | |
{ | |
case MSS_GPIO_DRIVE_HIGH: | |
/* Set output high */ | |
outputs_state = GPIO->GPIO_OUT; | |
outputs_state |= (uint32_t)1 << gpio_idx; | |
GPIO->GPIO_OUT = outputs_state; | |
/* Enable output buffer */ | |
config = *(g_config_reg_lut[gpio_idx]); | |
config |= OUTPUT_BUFFER_ENABLE_MASK; | |
*(g_config_reg_lut[gpio_idx]) = config; | |
break; | |
case MSS_GPIO_DRIVE_LOW: | |
/* Set output low */ | |
outputs_state = GPIO->GPIO_OUT; | |
outputs_state &= ~((uint32_t)((uint32_t)1 << gpio_idx)); | |
GPIO->GPIO_OUT = outputs_state; | |
/* Enable output buffer */ | |
config = *(g_config_reg_lut[gpio_idx]); | |
config |= OUTPUT_BUFFER_ENABLE_MASK; | |
*(g_config_reg_lut[gpio_idx]) = config; | |
break; | |
case MSS_GPIO_HIGH_Z: | |
/* Disable output buffer */ | |
config = *(g_config_reg_lut[gpio_idx]); | |
config &= ~OUTPUT_BUFFER_ENABLE_MASK; | |
*(g_config_reg_lut[gpio_idx]) = config; | |
break; | |
default: | |
ASSERT(0); | |
break; | |
} | |
} | |
} | |
/*-------------------------------------------------------------------------*//** | |
* MSS_GPIO_enable_irq | |
* See "mss_gpio.h" for details of how to use this function. | |
*/ | |
void MSS_GPIO_enable_irq | |
( | |
mss_gpio_id_t port_id | |
) | |
{ | |
uint32_t cfg_value; | |
uint32_t gpio_idx = (uint32_t)port_id; | |
ASSERT(gpio_idx < NB_OF_GPIO); | |
if(gpio_idx < NB_OF_GPIO) | |
{ | |
cfg_value = *(g_config_reg_lut[gpio_idx]); | |
*(g_config_reg_lut[gpio_idx]) = (cfg_value | GPIO_INT_ENABLE_MASK); | |
NVIC_EnableIRQ(g_gpio_irqn_lut[gpio_idx]); | |
} | |
} | |
/*-------------------------------------------------------------------------*//** | |
* MSS_GPIO_disable_irq | |
* See "mss_gpio.h" for details of how to use this function. | |
*/ | |
void MSS_GPIO_disable_irq | |
( | |
mss_gpio_id_t port_id | |
) | |
{ | |
uint32_t cfg_value; | |
uint32_t gpio_idx = (uint32_t)port_id; | |
ASSERT(gpio_idx < NB_OF_GPIO); | |
if(gpio_idx < NB_OF_GPIO) | |
{ | |
cfg_value = *(g_config_reg_lut[gpio_idx]); | |
*(g_config_reg_lut[gpio_idx]) = (cfg_value & ~GPIO_INT_ENABLE_MASK); | |
} | |
} | |
/*-------------------------------------------------------------------------*//** | |
* MSS_GPIO_clear_irq | |
* See "mss_gpio.h" for details of how to use this function. | |
*/ | |
void MSS_GPIO_clear_irq | |
( | |
mss_gpio_id_t port_id | |
) | |
{ | |
uint32_t gpio_idx = (uint32_t)port_id; | |
ASSERT(gpio_idx < NB_OF_GPIO); | |
if(gpio_idx < NB_OF_GPIO) | |
{ | |
GPIO->GPIO_IRQ = ((uint32_t)1) << gpio_idx; | |
} | |
} | |
#ifdef __cplusplus | |
} | |
#endif | |