diff --git a/arch/arm/include/tiva/chip.h b/arch/arm/include/tiva/chip.h index e378312e56..ddb246346d 100644 --- a/arch/arm/include/tiva/chip.h +++ b/arch/arm/include/tiva/chip.h @@ -317,7 +317,7 @@ /* Programmable current source */ # define TIVA_NPWM 0 /* No PWM generator modules */ # define TIVA_NQEI 0 /* No quadrature encoder modules */ -# define TIVA_NPORTS 1 /* One Ports */ +# define TIVA_NPORTS 1 /* One Port */ # define TIVA_NCANCONTROLLER 0 /* No CAN controllers */ # define TIVA_NUSBOTGFS 0 /* No USB 2.0 OTG FS */ # define TIVA_NUSBOTGHS 0 /* No USB 2.0 OTG HS */ @@ -347,7 +347,7 @@ /* Two comparators with reference DAC */ # define TIVA_NPWM 0 /* No PWM generator modules */ # define TIVA_NQEI 0 /* No quadrature encoder modules */ -# define TIVA_NPORTS 1 /* One Ports */ +# define TIVA_NPORTS 1 /* One Port */ # define TIVA_NCANCONTROLLER 0 /* No CAN controllers */ # define TIVA_NUSBOTGFS 0 /* No USB 2.0 OTG FS */ # define TIVA_NUSBOTGHS 0 /* No USB 2.0 OTG HS */ diff --git a/arch/arm/src/tiva/Make.defs b/arch/arm/src/tiva/Make.defs index a8d8fc62a0..a1d791cfd6 100644 --- a/arch/arm/src/tiva/Make.defs +++ b/arch/arm/src/tiva/Make.defs @@ -83,8 +83,20 @@ CMN_CSRCS += up_allocateheap.c endif CHIP_ASRCS = -CHIP_CSRCS = tiva_allocateheap.c tiva_start.c tiva_irq.c tiva_gpio.c -CHIP_CSRCS += tiva_gpioirq.c tiva_lowputc.c tiva_serial.c tiva_ssi.c +CHIP_CSRCS = tiva_allocateheap.c tiva_start.c tiva_irq.c tiva_gpioirq.c +CHIP_CSRCS += tiva_lowputc.c tiva_serial.c tiva_ssi.c + +ifeq ($(CONFIG_ARCH_CHIP_LM3S),y) +CHIP_CSRCS += lm3s_gpio.c +else ifeq ($(CONFIG_ARCH_CHIP_LM4F),y) +CHIP_CSRCS += lm4f_gpio.c +else ifeq ($(CONFIG_ARCH_CHIP_TM4C),y) +CHIP_CSRCS += tm4c_gpio.c +else ifeq ($(CONFIG_ARCH_CHIP_CC13X0),y) +CHIP_CSRCS += cc13c0_gpio.c +else ifeq ($(CONFIG_ARCH_CHIP_CC13X2),y) +CHIP_CSRCS += cc13x2_cc26x2_gpio.c +endif ifeq ($(CONFIG_DEBUG_GPIO_INFO),y) CHIP_CSRCS += tiva_dumpgpio.c diff --git a/arch/arm/src/tiva/hardware/cc13x0/cc13x0_gpio.h b/arch/arm/src/tiva/hardware/cc13x0/cc13x0_gpio.h new file mode 100644 index 0000000000..3571e80bf9 --- /dev/null +++ b/arch/arm/src/tiva/hardware/cc13x0/cc13x0_gpio.h @@ -0,0 +1,134 @@ +/************************************************************************************ + * arch/arm/src/tiva/hardware/cc13x0/cc13x0_gpio.h + * + * Copyright (C) 2018 Gregory Nutt. All rights reserved. + * Authors: Gregory Nutt + * + * 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. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 + * COPYRIGHT OWNER OR CONTRIBUTORS 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. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_TIVA_HARDWARE_CC13X0_CC13X0_GPIO_H +#define __ARCH_ARM_SRC_TIVA_HARDWARE_CC13X0_CC13X0_GPIO_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* GPIO Register Offsets ************************************************************/ + +#define TIVA_GPIO_DOUT_OFFSET(n) ((n) & ~3) +# define TIVA_GPIO_DOUT3_0_OFFSET 0x0000 /* Data Out 0 to 3 */ +# define TIVA_GPIO_DOUT7_4_OFFSET 0x0004 /* Data Out 4 to 7 */ +# define TIVA_GPIO_DOUT11_8_OFFSET 0x0008 /* Data Out 8 to 11 */ +# define TIVA_GPIO_DOUT15_12_OFFSET 0x000c /* Data Out 12 to 15 */ +# define TIVA_GPIO_DOUT19_16_OFFSET 0x0010 /* Data Out 16 to 19 */ +# define TIVA_GPIO_DOUT23_20_OFFSET 0x0014 /* Data Out 20 to 23 */ +# define TIVA_GPIO_DOUT27_24_OFFSET 0x0018 /* Data Out 24 to 27 */ +# define TIVA_GPIO_DOUT31_28_OFFSET 0x001c /* Data Out 28 to 31 */ +#define TIVA_GPIO_DOUT_OFFSET 0x0080 /* Data Output for DIO 0 to 31 */ +#define TIVA_GPIO_DOUTSET_OFFSET 0x0090 /* Data Out Set */ +#define TIVA_GPIO_DOUTCLR_OFFSET 0x00a0 /* Data Out Clear */ +#define TIVA_GPIO_DOUTTGL_OFFSET 0x00b0 /* Data Out Toggle */ +#define TIVA_GPIO_DIN_OFFSET 0x00c0 /* Data Input from DIO 0 to 31 */ +#define TIVA_GPIO_DOE_OFFSET 0x00d0 /* Data Output Enable for DIO 0 to 31 */ +#define TIVA_GPIO_EVFLAGS_OFFSET 0x00e0 /* Event Register for DIO 0 to 31 */ + +/* GPIO Register Addresses **********************************************************/ + +#define TIVA_GPIO_DOUT_BASE(n) (TIVA_GPIO_BASE + TIVA_GPIO_DOUT_OFFSET(n)) +# define TIVA_GPIO_DOUT3_0_OFFSET (TIVA_GPIO_BASE + TIVA_GPIO_DOUT3_0_OFFSET) +# define TIVA_GPIO_DOUT7_4_OFFSET (TIVA_GPIO_BASE + TIVA_GPIO_DOUT7_4_OFFSET) +# define TIVA_GPIO_DOUT11_8_OFFSET (TIVA_GPIO_BASE + TIVA_GPIO_DOUT11_8_OFFSET) +# define TIVA_GPIO_DOUT15_12_OFFSET (TIVA_GPIO_BASE + TIVA_GPIO_DOUT15_12_OFFSET) +# define TIVA_GPIO_DOUT19_16_OFFSET (TIVA_GPIO_BASE + TIVA_GPIO_DOUT19_16_OFFSET) +# define TIVA_GPIO_DOUT23_20_OFFSET (TIVA_GPIO_BASE + TIVA_GPIO_DOUT23_20_OFFSET) +# define TIVA_GPIO_DOUT27_24_OFFSET (TIVA_GPIO_BASE + TIVA_GPIO_DOUT27_24_OFFSET) +# define TIVA_GPIO_DOUT31_28_OFFSET (TIVA_GPIO_BASE + TIVA_GPIO_DOUT31_28_OFFSET) +#define TIVA_GPIO_DOUT_OFFSET (TIVA_GPIO_BASE + TIVA_GPIO_DOUT_OFFSET) +#define TIVA_GPIO_DOUTSET_OFFSET (TIVA_GPIO_BASE + TIVA_GPIO_DOUTSET_OFFSET) +#define TIVA_GPIO_DOUTCLR_OFFSET (TIVA_GPIO_BASE + TIVA_GPIO_DOUTCLR_OFFSET) +#define TIVA_GPIO_DOUTTGL_OFFSET (TIVA_GPIO_BASE + TIVA_GPIO_DOUTTGL_OFFSET) +#define TIVA_GPIO_DIN_OFFSET (TIVA_GPIO_BASE + TIVA_GPIO_DIN_OFFSET) +#define TIVA_GPIO_DOE_OFFSET (TIVA_GPIO_BASE + TIVA_GPIO_DOE_OFFSET) +#define TIVA_GPIO_EVFLAGS_OFFSET (TIVA_GPIO_BASE + TIVA_GPIO_EVFLAGS_OFFSET) + +/* GPIO Register Bitfield Definitions ***********************************************/ + +/* Data Out n to n + 3 */ + +#define GPIO_DOUT_SHIFT(n) (((n) & 3) << 8) +#define GPIO_DOUT_VALUE(n) (1 << GPIO_DOUT_SHIFT(n)) + +/* Data Output for DIO 0 to 31 */ + +#define GPIO_DOUT(n) (1 << (n)) + +/* Data Out Set */ + +#define GPIO_DOUTSET(n) (1 << (n)) + +/* Data Out Clear */ + +#define GPIO_DOUTCLR(n) (1 << (n)) + +/* Data Out Toggle */ + +#define GPIO_DOUTTGL(n) (1 << (n)) + +/* Data Input from DIO 0 to 31 */ + +#define GPIO_DIN(n) (1 << (n)) + +/* Data Output Enable for DIO 0 to 31 */ + +#define GPIO_DOE(n) (1 << (n)) + +/* Event Register for DIO 0 to 31 */ + +#define GPIO_EVFLAGS(n) (1 << (n)) + +/************************************************************************************ + * Public Types + ************************************************************************************/ + +/************************************************************************************ + * Public Data + ************************************************************************************/ + +/************************************************************************************ + * Public Function Prototypes + ************************************************************************************/ + +#endif /* __ARCH_ARM_SRC_TIVA_HARDWARE_CC13X0_CC13X0_GPIO_H */ diff --git a/arch/arm/src/tiva/hardware/cc13x2_cc26x2/cc13x2_cc26x2_gpio.h b/arch/arm/src/tiva/hardware/cc13x2_cc26x2/cc13x2_cc26x2_gpio.h new file mode 100644 index 0000000000..8e252a744a --- /dev/null +++ b/arch/arm/src/tiva/hardware/cc13x2_cc26x2/cc13x2_cc26x2_gpio.h @@ -0,0 +1,134 @@ +/************************************************************************************ + * arch/arm/src/tiva/hardware/cc13x2_cc26x2/cc13x2_cc26x2_gpio.h + * + * Copyright (C) 2018 Gregory Nutt. All rights reserved. + * Authors: Gregory Nutt + * + * 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. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 + * COPYRIGHT OWNER OR CONTRIBUTORS 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. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_TIVA_HARDWARE_CC13X2_CC26X2_CC13X2_CC26X2_GPIO_H +#define __ARCH_ARM_SRC_TIVA_HARDWARE_CC13X2_CC26X2_CC13X2_CC26X2_GPIO_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* GPIO Register Offsets ************************************************************/ + +#define TIVA_GPIO_DOUT_OFFSET(n) ((n) & ~3) +# define TIVA_GPIO_DOUT3_0_OFFSET 0x0000 /* Data Out 0 to 3 */ +# define TIVA_GPIO_DOUT7_4_OFFSET 0x0004 /* Data Out 4 to 7 */ +# define TIVA_GPIO_DOUT11_8_OFFSET 0x0008 /* Data Out 8 to 11 */ +# define TIVA_GPIO_DOUT15_12_OFFSET 0x000c /* Data Out 12 to 15 */ +# define TIVA_GPIO_DOUT19_16_OFFSET 0x0010 /* Data Out 16 to 19 */ +# define TIVA_GPIO_DOUT23_20_OFFSET 0x0014 /* Data Out 20 to 23 */ +# define TIVA_GPIO_DOUT27_24_OFFSET 0x0018 /* Data Out 24 to 27 */ +# define TIVA_GPIO_DOUT31_28_OFFSET 0x001c /* Data Out 28 to 31 */ +#define TIVA_GPIO_DOUT_OFFSET 0x0080 /* Data Output for DIO 0 to 31 */ +#define TIVA_GPIO_DOUTSET_OFFSET 0x0090 /* Data Out Set */ +#define TIVA_GPIO_DOUTCLR_OFFSET 0x00a0 /* Data Out Clear */ +#define TIVA_GPIO_DOUTTGL_OFFSET 0x00b0 /* Data Out Toggle */ +#define TIVA_GPIO_DIN_OFFSET 0x00c0 /* Data Input from DIO 0 to 31 */ +#define TIVA_GPIO_DOE_OFFSET 0x00d0 /* Data Output Enable for DIO 0 to 31 */ +#define TIVA_GPIO_EVFLAGS_OFFSET 0x00e0 /* Event Register for DIO 0 to 31 */ + +/* GPIO Register Addresses **********************************************************/ + +#define TIVA_GPIO_DOUT_BASE(n) (TIVA_GPIO_BASE + TIVA_GPIO_DOUT_OFFSET(n)) +# define TIVA_GPIO_DOUT3_0_OFFSET (TIVA_GPIO_BASE + TIVA_GPIO_DOUT3_0_OFFSET) +# define TIVA_GPIO_DOUT7_4_OFFSET (TIVA_GPIO_BASE + TIVA_GPIO_DOUT7_4_OFFSET) +# define TIVA_GPIO_DOUT11_8_OFFSET (TIVA_GPIO_BASE + TIVA_GPIO_DOUT11_8_OFFSET) +# define TIVA_GPIO_DOUT15_12_OFFSET (TIVA_GPIO_BASE + TIVA_GPIO_DOUT15_12_OFFSET) +# define TIVA_GPIO_DOUT19_16_OFFSET (TIVA_GPIO_BASE + TIVA_GPIO_DOUT19_16_OFFSET) +# define TIVA_GPIO_DOUT23_20_OFFSET (TIVA_GPIO_BASE + TIVA_GPIO_DOUT23_20_OFFSET) +# define TIVA_GPIO_DOUT27_24_OFFSET (TIVA_GPIO_BASE + TIVA_GPIO_DOUT27_24_OFFSET) +# define TIVA_GPIO_DOUT31_28_OFFSET (TIVA_GPIO_BASE + TIVA_GPIO_DOUT31_28_OFFSET) +#define TIVA_GPIO_DOUT_OFFSET (TIVA_GPIO_BASE + TIVA_GPIO_DOUT_OFFSET) +#define TIVA_GPIO_DOUTSET_OFFSET (TIVA_GPIO_BASE + TIVA_GPIO_DOUTSET_OFFSET) +#define TIVA_GPIO_DOUTCLR_OFFSET (TIVA_GPIO_BASE + TIVA_GPIO_DOUTCLR_OFFSET) +#define TIVA_GPIO_DOUTTGL_OFFSET (TIVA_GPIO_BASE + TIVA_GPIO_DOUTTGL_OFFSET) +#define TIVA_GPIO_DIN_OFFSET (TIVA_GPIO_BASE + TIVA_GPIO_DIN_OFFSET) +#define TIVA_GPIO_DOE_OFFSET (TIVA_GPIO_BASE + TIVA_GPIO_DOE_OFFSET) +#define TIVA_GPIO_EVFLAGS_OFFSET (TIVA_GPIO_BASE + TIVA_GPIO_EVFLAGS_OFFSET) + +/* GPIO Register Bitfield Definitions ***********************************************/ + +/* Data Out n to n + 3 */ + +#define GPIO_DOUT_SHIFT(n) (((n) & 3) << 8) +#define GPIO_DOUT_VALUE(n) (1 << GPIO_DOUT_SHIFT(n)) + +/* Data Output for DIO 0 to 31 */ + +#define GPIO_DOUT(n) (1 << (n)) + +/* Data Out Set */ + +#define GPIO_DOUTSET(n) (1 << (n)) + +/* Data Out Clear */ + +#define GPIO_DOUTCLR(n) (1 << (n)) + +/* Data Out Toggle */ + +#define GPIO_DOUTTGL(n) (1 << (n)) + +/* Data Input from DIO 0 to 31 */ + +#define GPIO_DIN(n) (1 << (n)) + +/* Data Output Enable for DIO 0 to 31 */ + +#define GPIO_DOE(n) (1 << (n)) + +/* Event Register for DIO 0 to 31 */ + +#define GPIO_EVFLAGS(n) (1 << (n)) + +/************************************************************************************ + * Public Types + ************************************************************************************/ + +/************************************************************************************ + * Public Data + ************************************************************************************/ + +/************************************************************************************ + * Public Function Prototypes + ************************************************************************************/ + +#endif /* __ARCH_ARM_SRC_TIVA_HARDWARE_CC13X2_CC26X2_CC13X2_CC26X2_GPIO_H */ diff --git a/arch/arm/src/tiva/hardware/tiva_gpio.h b/arch/arm/src/tiva/hardware/tiva_gpio.h index 5dbbb7a5e0..0d3da66198 100644 --- a/arch/arm/src/tiva/hardware/tiva_gpio.h +++ b/arch/arm/src/tiva/hardware/tiva_gpio.h @@ -55,10 +55,8 @@ # include "hardware/tm4c/tm4c129_gpio.h" #elif defined(CONFIG_ARCH_CHIP_CC13X0) # include "hardware/cc13x0/cc13x0_gpio.h" -#elif defined(CONFIG_ARCH_CHIP_CC13X2_V1) -# include "hardware/cc13x2_cc26x2/cc13x2_cc26x2_v1_gpio.h" -#elif defined(CONFIG_ARCH_CHIP_CC13X2_V2) -# include "hardware/cc13x2_cc26x2/cc13x2_cc26x2_v2_gpio.h" +#elif defined(CONFIG_ARCH_CHIP_CC13X2) +# include "hardware/cc13x2_cc26x2/cc13x2_cc26x2_gpio.h" #else # error "Unsupported Tiva/Stellaris system control module" #endif diff --git a/arch/arm/src/tiva/hardware/tm4c/tm4c129_gpio.h b/arch/arm/src/tiva/hardware/tm4c/tm4c129_gpio.h index 4ce77e3e79..c704eb4fe1 100644 --- a/arch/arm/src/tiva/hardware/tm4c/tm4c129_gpio.h +++ b/arch/arm/src/tiva/hardware/tm4c/tm4c129_gpio.h @@ -539,7 +539,6 @@ # define TIVA_GPIOJ_PCELLID3 (TIVA_GPIOJ_BASE + TIVA_GPIO_PCELLID3_OFFSET) #endif - /* GPIO Register Bitfield Definitions ***********************************************/ /* GPIO Interrupt Mask */ diff --git a/arch/arm/src/tiva/lm/lm3s_gpio.c b/arch/arm/src/tiva/lm/lm3s_gpio.c new file mode 100644 index 0000000000..e1c50d4703 --- /dev/null +++ b/arch/arm/src/tiva/lm/lm3s_gpio.c @@ -0,0 +1,866 @@ +/**************************************************************************** + * arch/arm/src/tiva/common/tiva_gpio.c + * + * Copyright (C) 2009-2010, 2014-2015, 2018 Gregory Nutt. All rights + * reserved. + * Author: Gregory Nutt + * + * 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. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 + * COPYRIGHT OWNER OR CONTRIBUTORS 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include + +#include "up_arch.h" +#include "tiva_enablepwr.h" +#include "tiva_enableclks.h" +#include "tiva_gpio.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* These definitions are part of the implementation of the GPIO pad + * configuration of Table 9-1 in the LM3S6918 data sheet. + */ + +#define AMSEL_SHIFT 6 +#define AMSEL_1 (1 << AMSEL_SHIFT) /* Set/clear bit in GPIO AMSEL register */ +#define AMSEL_0 0 +#define AMSEL_X 0 + +#define AFSEL_SHIFT 5 +#define AFSEL_1 (1 << AFSEL_SHIFT) /* Set/clear bit in GPIO AFSEL register */ +#define AFSEL_0 0 +#define AFSEL_X 0 + +#define DIR_SHIFT 4 +#define DIR_1 (1 << DIR_SHIFT) /* Set/clear bit in GPIO DIR register */ +#define DIR_0 0 +#define DIR_X 0 + +#define ODR_SHIFT 3 +#define ODR_1 (1 << ODR_SHIFT) /* Set/clear bit in GPIO ODR register */ +#define ODR_0 0 +#define ODR_X 0 + +#define DEN_SHIFT 2 +#define DEN_1 (1 << DEN_SHIFT) /* Set/clear bit in GPIO DEN register */ +#define DEN_0 0 +#define DEN_X 0 + +#define PUR_SHIFT 1 +#define PUR_1 (1 << PUR_SHIFT) /* Set/clear bit in GPIO PUR register */ +#define PUR_0 0 +#define PUR_X 0 + +#define PDR_SHIFT 0 +#define PDR_1 (1 << PDR_SHIFT) /* Set/clear bit in GPIO PDR register */ +#define PDR_0 0 +#define PDR_X 0 + +#define GPIO_INPUT_SETBITS (AMSEL_0 | AFSEL_0 | DIR_0 | ODR_0 | DEN_1 | PUR_X | PDR_X) +#define GPIO_INPUT_CLRBITS (AMSEL_1 | AFSEL_1 | DIR_1 | ODR_1 | DEN_0 | PUR_X | PDR_X) + +#define GPIO_OUTPUT_SETBITS (AMSEL_0 | AFSEL_0 | DIR_1 | ODR_0 | DEN_1 | PUR_X | PDR_X) +#define GPIO_OUTPUT_CLRBITS (AMSEL_1 | AFSEL_1 | DIR_0 | ODR_1 | DEN_0 | PUR_X | PDR_X) + +#define GPIO_ODINPUT_SETBITS (AMSEL_0 | AFSEL_0 | DIR_0 | ODR_1 | DEN_1 | PUR_X | PDR_X) +#define GPIO_ODINPUT_CLRBITS (AMSEL_1 | AFSEL_1 | DIR_1 | ODR_0 | DEN_0 | PUR_X | PDR_X) + +#define GPIO_ODOUTPUT_SETBITS (AMSEL_0 | AFSEL_0 | DIR_1 | ODR_1 | DEN_1 | PUR_X | PDR_X) +#define GPIO_ODOUTPUT_CLRBITS (AMSEL_1 | AFSEL_1 | DIR_0 | ODR_0 | DEN_0 | PUR_X | PDR_X) + +#define GPIO_PFODIO_SETBITS (AMSEL_0 | AFSEL_1 | DIR_X | ODR_1 | DEN_1 | PUR_X | PDR_X) +#define GPIO_PFODIO_CLRBITS (AMSEL_1 | AFSEL_0 | DIR_X | ODR_0 | DEN_0 | PUR_X | PDR_X) + +#define GPIO_PFIO_SETBITS (AMSEL_0 | AFSEL_1 | DIR_X | ODR_0 | DEN_1 | PUR_X | PDR_X) +#define GPIO_PFIO_CLRBITS (AMSEL_1 | AFSEL_0 | DIR_X | ODR_1 | DEN_0 | PUR_X | PDR_X) + +#define GPIO_ANINPUT_SETBITS (AMSEL_1 | AFSEL_0 | DIR_0 | ODR_0 | DEN_0 | PUR_0 | PDR_0) +#define GPIO_ANINPUT_CLRBITS (AMSEL_0 | AFSEL_1 | DIR_1 | ODR_1 | DEN_1 | PUR_1 | PDR_1) + +#define GPIO_INTERRUPT_SETBITS (AMSEL_0 | AFSEL_0 | DIR_0 | ODR_0 | DEN_1 | PUR_X | PDR_X) +#define GPIO_INTERRUPT_CLRBITS (AMSEL_1 | AFSEL_1 | DIR_1 | ODR_1 | DEN_0 | PUR_X | PDR_X) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct gpio_func_s +{ + uint8_t setbits; /* A set of GPIO register bits to set */ + uint8_t clrbits; /* A set of GPIO register bits to clear */ +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct gpio_func_s g_funcbits[] = +{ + {GPIO_INPUT_SETBITS, GPIO_INPUT_CLRBITS}, /* GPIO_FUNC_INPUT */ + {GPIO_OUTPUT_SETBITS, GPIO_OUTPUT_CLRBITS}, /* GPIO_FUNC_OUTPUT */ + {GPIO_ODINPUT_SETBITS, GPIO_ODINPUT_CLRBITS}, /* GPIO_FUNC_ODINPUT */ + {GPIO_ODOUTPUT_SETBITS, GPIO_ODOUTPUT_CLRBITS}, /* GPIO_FUNC_ODOUTPUT */ + {GPIO_PFODIO_SETBITS, GPIO_PFODIO_CLRBITS}, /* GPIO_FUNC_PFODIO */ + {GPIO_PFIO_SETBITS, GPIO_PFIO_CLRBITS}, /* GPIO_FUNC_PFIO */ + {GPIO_ANINPUT_SETBITS, GPIO_ANINPUT_CLRBITS}, /* GPIO_FUNC_ANINPUT */ + {GPIO_INTERRUPT_SETBITS, GPIO_INTERRUPT_CLRBITS}, /* GPIO_FUNC_INTERRUPT */ +}; + +/* NOTE: this is duplicated in tiva_dumpgpio.c */ + +static const uintptr_t g_gpiobase[TIVA_NPORTS] = +{ +#if TIVA_NPORTS > 0 + TIVA_GPIOA_BASE +#endif +#if TIVA_NPORTS > 1 + , TIVA_GPIOB_BASE +#endif +#if TIVA_NPORTS > 2 + , TIVA_GPIOC_BASE +#endif +#if TIVA_NPORTS > 3 + , TIVA_GPIOD_BASE +#endif +#if TIVA_NPORTS > 4 + , TIVA_GPIOE_BASE +#endif +#if TIVA_NPORTS > 5 + , TIVA_GPIOF_BASE +#endif +#if TIVA_NPORTS > 6 + , TIVA_GPIOG_BASE +#endif +#if TIVA_NPORTS > 7 + , TIVA_GPIOH_BASE +#endif +#if TIVA_NPORTS > 8 + , TIVA_GPIOJ_BASE +#endif +#if TIVA_NPORTS > 9 + , TIVA_GPIOK_BASE +#endif +#if TIVA_NPORTS > 10 + , TIVA_GPIOL_BASE +#endif +#if TIVA_NPORTS > 11 + , TIVA_GPIOM_BASE +#endif +#if TIVA_NPORTS > 12 + , TIVA_GPION_BASE +#endif +#if TIVA_NPORTS > 13 + , TIVA_GPIOP_BASE +#endif +#if TIVA_NPORTS > 14 + , TIVA_GPIOQ_BASE +#endif +#if TIVA_NPORTS > 15 + , TIVA_GPIOR_BASE +#endif +#if TIVA_NPORTS > 16 + , TIVA_GPIOS_BASE +#endif +#if TIVA_NPORTS > 17 + , TIVA_GPIOT_BASE +#endif +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tiva_gpiobaseaddress + * + * Description: + * Given a GPIO enumeration value, return the base address of the + * associated GPIO registers. + * + ****************************************************************************/ + +inline uintptr_t tiva_gpiobaseaddress(unsigned int port) +{ + uintptr_t gpiobase = 0; + if (port < TIVA_NPORTS) + { + gpiobase = g_gpiobase[port]; + } + + return gpiobase; +} + +/**************************************************************************** + * Name: tiva_gpiofunc + * + * Description: + * Configure GPIO registers for a specific function. Overwrites certain + * padtype configurations. + * + ****************************************************************************/ + +static void tiva_gpiofunc(uint32_t base, uint32_t pinno, + const struct gpio_func_s *func) +{ + uint32_t setbit; + uint32_t clrbit; + + /* Set/clear/ignore the GPIO DIR bit. "The GPIODIR register is the data + * direction register. Bits set to 1 in the GPIODIR register configure + * the corresponding pin to be an output, while bits set to 0 configure + * the pins to be inputs. All bits are cleared by a reset, meaning all + * GPIO pins are inputs by default. + */ + + setbit = (((uint32_t)func->setbits >> DIR_SHIFT) & 1) << pinno; + clrbit = (((uint32_t)func->clrbits >> DIR_SHIFT) & 1) << pinno; + + if (setbit || clrbit) + { + modifyreg32(base + TIVA_GPIO_DIR_OFFSET, clrbit, setbit); + } + + /* Set/clear/ignore the GPIO AFSEL bit. "The GPIOAFSEL register is the + * mode control select register. Writing a 1 to any bit in this register + * selects the hardware control for the corresponding GPIO line. All bits + * are cleared by a reset, therefore no GPIO line is set to hardware + * control by default." + * + * NOTE: In order to set JTAG/SWD GPIOs, it is also necessary to lock, + * commit and unlock the GPIO. That is not implemented here. + */ + + setbit = (((uint32_t)func->setbits >> AFSEL_SHIFT) & 1) << pinno; + clrbit = (((uint32_t)func->clrbits >> AFSEL_SHIFT) & 1) << pinno; + + if (setbit || clrbit) + { + modifyreg32(base + TIVA_GPIO_AFSEL_OFFSET, clrbit, setbit); + } + + /* Set/clear/ignore the GPIO ODR bit. "The GPIO ODR register is the open + * drain control register. Setting a bit in this register enables the open + * drain configuration of the corresponding GPIO pad. When open drain mode + * is enabled, the corresponding bit should also be set in the GPIO Digital + * Input Enable (GPIO DEN) register ... Corresponding bits in the drive + * strength registers (GPIO DR2R, GPIO DR4R, GPIO DR8R, and GPIO SLR ) can + * be set to achieve the desired rise and fall times. The GPIO acts as an + * open drain input if the corresponding bit in the GPIO DIR register is + * set to 0; and as an open drain output when set to 1." + */ + + setbit = (((uint32_t)func->setbits >> ODR_SHIFT) & 1) << pinno; + clrbit = (((uint32_t)func->clrbits >> ODR_SHIFT) & 1) << pinno; + + if (setbit || clrbit) + { + modifyreg32(base + TIVA_GPIO_ODR_OFFSET, clrbit, setbit); + } + + /* Set/clear the GPIO PUR bit. "The GPIOPUR register is the pull-up + * control register. When a bit is set to 1, it enables a weak pull-up + * resistor on the corresponding GPIO signal. Setting a bit in GPIOPUR + * automatically clears the corresponding bit in the GPIO Pull-Down + * Select (GPIOPDR) register ..." + */ + + setbit = (((uint32_t)func->setbits >> PUR_SHIFT) & 1) << pinno; + clrbit = (((uint32_t)func->clrbits >> PUR_SHIFT) & 1) << pinno; + + if (setbit || clrbit) + { + modifyreg32(base + TIVA_GPIO_PUR_OFFSET, clrbit, setbit); + } + + /* Set/clear the GPIO PDR bit. "The GPIOPDR register is the pull-down + * control register. When a bit is set to 1, it enables a weak pull-down + * resistor on the corresponding GPIO signal. Setting a bit in GPIOPDR + * automatically clears the corresponding bit in the GPIO Pull-Up Select + * (GPIOPUR) register ..." + */ + + setbit = (((uint32_t)func->setbits >> PDR_SHIFT) & 1) << pinno; + clrbit = (((uint32_t)func->clrbits >> PDR_SHIFT) & 1) << pinno; + + if (setbit || clrbit) + { + modifyreg32(base + TIVA_GPIO_PDR_OFFSET, clrbit, setbit); + } + + /* Set/clear the GPIO DEN bit. "The GPIODEN register is the digital enable + * register. By default, with the exception of the GPIO signals used for + * JTAG/SWD function, all other GPIO signals are configured out of reset + * to be undriven (tristate). Their digital function is disabled; they do + * not drive a logic value on the pin and they do not allow the pin voltage + * into the GPIO receiver. To use the pin in a digital function (either + * GPIO or alternate function), the corresponding GPIODEN bit must be set." + */ + + setbit = (((uint32_t)func->setbits >> DEN_SHIFT) & 1) << pinno; + clrbit = (((uint32_t)func->clrbits >> DEN_SHIFT) & 1) << pinno; + + if (setbit || clrbit) + { + modifyreg32(base + TIVA_GPIO_DEN_OFFSET, clrbit, setbit); + } +} + +/**************************************************************************** + * Name: tiva_gpiopadstrength + * + * Description: + * Set up pad strength and pull-ups + * + ****************************************************************************/ + +static inline void tiva_gpiopadstrength(uint32_t base, uint32_t pin, + uint32_t pinset) +{ + int strength = (pinset & GPIO_STRENGTH_MASK); + uint32_t slrset = 0; + uint32_t slrclr = 0; + uint32_t dr2rset = 0; + uint32_t dr2rclr = 0; + uint32_t dr4rset = 0; + uint32_t dr4rclr = 0; + uint32_t dr8rset = 0; + uint32_t dr8rclr = 0; + + /* Set the output drive strength. */ + + switch (strength) + { + case GPIO_STRENGTH_2MA: + { + dr2rset = pin; + dr4rclr = pin; + dr8rclr = pin; + slrclr = pin; + } + break; + + case GPIO_STRENGTH_4MA: + { + dr2rclr = pin; + dr4rset = pin; + dr8rclr = pin; + slrclr = pin; + } + break; + + case GPIO_STRENGTH_8MA: + { + dr2rclr = pin; + dr4rclr = pin; + dr8rset = pin; + slrclr = pin; + } + break; + + case GPIO_STRENGTH_8MASC: + { + dr2rclr = pin; + dr4rclr = pin; + dr8rset = pin; + slrset = pin; + } + break; + + default: + break; + } + + modifyreg32(base + TIVA_GPIO_DR2R_OFFSET, dr2rclr, dr2rset); + modifyreg32(base + TIVA_GPIO_DR4R_OFFSET, dr4rclr, dr4rset); + modifyreg32(base + TIVA_GPIO_DR8R_OFFSET, dr8rclr, dr8rset); + modifyreg32(base + TIVA_GPIO_SLR_OFFSET, slrclr, slrset); +} + +/**************************************************************************** + * Name: tiva_gpiopadtype + * + * Description: + * Set up pad strength and pull-ups. Some of these values may be over- + * written by tiva_gpiofunc, depending on the function selection. Others + * are optional for different function selections. + * + ****************************************************************************/ + +static inline void tiva_gpiopadtype(uint32_t base, uint32_t pin, + uint32_t pinset) +{ + int padtype = (pinset & GPIO_PADTYPE_MASK); + uint32_t odrset = 0; + uint32_t odrclr = 0; + uint32_t purset = 0; + uint32_t purclr = 0; + uint32_t pdrset = 0; + uint32_t pdrclr = 0; + uint32_t denset = 0; + uint32_t denclr = 0; + + /* Set the pin type. */ + + switch (padtype) + { + case GPIO_PADTYPE_STD: + { + odrclr = pin; + purclr = pin; + pdrclr = pin; + denset = pin; + } + break; + + case GPIO_PADTYPE_STDWPU: + { + odrclr = pin; + purset = pin; + pdrclr = pin; + denset = pin; + } + break; + + case GPIO_PADTYPE_STDWPD: + { + odrclr = pin; + purclr = pin; + pdrset = pin; + denset = pin; + } + break; + + case GPIO_PADTYPE_OD: + { + odrset = pin; + purclr = pin; + pdrclr = pin; + denset = pin; + } + break; + + case GPIO_PADTYPE_ODWPU: + { + odrset = pin; + purset = pin; + pdrclr = pin; + denclr = pin; + } + break; + + case GPIO_PADTYPE_ODWPD: + { + odrset = pin; + purclr = pin; + pdrset = pin; + denclr = pin; + } + break; + + case GPIO_PADTYPE_ANALOG: + { + odrclr = pin; + purclr = pin; + pdrclr = pin; + denclr = pin; + } + break; + + default: + break; + } + + modifyreg32(base + TIVA_GPIO_ODR_OFFSET, odrclr, odrset); + modifyreg32(base + TIVA_GPIO_PUR_OFFSET, purclr, purset); + modifyreg32(base + TIVA_GPIO_PDR_OFFSET, pdrclr, pdrset); + modifyreg32(base + TIVA_GPIO_DEN_OFFSET, denclr, denset); +} + +/**************************************************************************** + * Name: tiva_initoutput + * + * Description: + * Set the GPIO output value + * + ****************************************************************************/ + +static inline void tiva_initoutput(uint32_t pinset) +{ + bool value = ((pinset & GPIO_VALUE_MASK) != GPIO_VALUE_ZERO); + tiva_gpiowrite(pinset, value); +} + +/**************************************************************************** + * Name: tiva_interrupt + * + * Description: + * Configure the interrupt pin. + * + ****************************************************************************/ + +#ifdef CONFIG_TIVA_GPIO_IRQS +static inline void tiva_interrupt(uint32_t pinset) +{ + uint8_t port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; + uint8_t pin = 1 << (pinset & GPIO_PIN_MASK); + uintptr_t base = tiva_gpiobaseaddress(port); + uint32_t inttype = pinset & GPIO_INT_MASK; + + uint32_t isset = 0; + uint32_t ibeset = 0; + uint32_t ievset = 0; + uint32_t isclr = 0; + uint32_t ibeclr = 0; + uint32_t ievclr = 0; + + /* Mask and clear the GPIO interrupt */ + + tiva_gpioirqdisable(port, pin); + tiva_gpioirqclear(port, pin); + + /* handle according to the selected interrupt type */ + + switch (inttype) + { + case GPIO_INT_FALLINGEDGE: + { + isclr = pin; + ibeclr = pin; + ievclr = pin; + } + break; + + case GPIO_INT_RISINGEDGE: + { + isclr = pin; + ibeclr = pin; + ievset = pin; + } + break; + + case GPIO_INT_BOTHEDGES: + { + isclr = pin; + ibeset = pin; + ievclr = pin; + } + break; + + case GPIO_INT_LOWLEVEL: + { + isset = pin; + ibeclr = pin; + ievclr = pin; + } + break; + + case GPIO_INT_HIGHLEVEL: + { + isset = pin; + ibeclr = pin; + ievset = pin; + } + break; + + default: + break; + } + + /* "The GPIO IBE register is the interrupt both-edges register. When the + * corresponding bit in the GPIO Interrupt Sense (GPIO IS) register ... is + * set to detect edges, bits set to High in GPIO IBE configure the + * corresponding pin to detect both rising and falling edges, regardless + * of the corresponding bit in the GPIO Interrupt Event (GPIO IEV) register ... + * Clearing a bit configures the pin to be controlled by GPIOIEV. All bits + * are cleared by a reset. + */ + + modifyreg32(base + TIVA_GPIO_IBE_OFFSET, ibeclr, ibeset); + + /* "The GPIO IS register is the interrupt sense register. Bits set to + * 1 in GPIOIS configure the corresponding pins to detect levels, while + * bits set to 0 configure the pins to detect edges. All bits are cleared + * by a reset. + */ + + modifyreg32(base + TIVA_GPIO_IS_OFFSET, isclr, isset); + + /* "The GPIOIEV register is the interrupt event register. Bits set to + * High in GPIO IEV configure the corresponding pin to detect rising edges + * or high levels, depending on the corresponding bit value in the GPIO + * Interrupt Sense (GPIO IS) register... Clearing a bit configures the pin to + * detect falling edges or low levels, depending on the corresponding bit + * value in GPIOIS. All bits are cleared by a reset. + */ + + modifyreg32(base + TIVA_GPIO_IEV_OFFSET, ievclr, ievset); + +#ifdef CONFIG_DEBUG_GPIO_INFO + uint32_t regval; + + gpioinfo("reg expected actual: [interrupt type=%d]\n", inttype); + + regval = (getreg32(base+TIVA_GPIO_IS_OFFSET) & pin) ? pin : 0; + gpioinfo("IS 0x%08x 0x%08x\n", isset, regval); + + regval = (getreg32(base+TIVA_GPIO_IBE_OFFSET) & pin) ? pin : 0; + gpioinfo("IBE 0x%08x 0x%08x\n", ibeset, regval); + + regval = (getreg32(base+TIVA_GPIO_IEV_OFFSET) & pin) ? pin : 0; + gpioinfo("IEV 0x%08x 0x%08x\n", ievset, regval); +#endif +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tiva_configgpio + * + * Description: + * Configure a GPIO pin based on bit-encoded description of the pin. + * + ****************************************************************************/ + +int tiva_configgpio(uint32_t pinset) +{ + irqstate_t flags; + unsigned int func; + unsigned int port; + unsigned int pinno; + uintptr_t base; + uint32_t pin; + + /* Decode the basics */ + + func = (pinset & GPIO_FUNC_MASK) >> GPIO_FUNC_SHIFT; + port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; + pinno = (pinset & GPIO_PIN_MASK); + pin = (1 << pinno); + + DEBUGASSERT(func <= GPIO_FUNC_MAX); + + /* Get the base address associated with the GPIO port */ + + base = tiva_gpiobaseaddress(port); + DEBUGASSERT(base != 0); + + /* The following requires exclusive access to the GPIO registers */ + + flags = enter_critical_section(); + + /* Enable power and clocking for this GPIO peripheral. Applies both power + * and clocking to the GPIO peripheral, bringing it a fully functional + * state. + */ + + tiva_gpio_enablepwr(port); + tiva_gpio_enableclk(port); + + /* First, set the port to digital input. This is the safest state in which + * to perform reconfiguration. + */ + + tiva_gpiofunc(base, pinno, &g_funcbits[0]); + + /* Then set up pad strengths and pull-ups. These setups should be done before + * setting up the function because some function settings will over-ride these + * user options. + */ + + tiva_gpiopadstrength(base, pin, pinset); + tiva_gpiopadtype(base, pin, pinset); + + /* Then set up the real pin function */ + + tiva_gpiofunc(base, pinno, &g_funcbits[func]); + + /* Special case GPIO digital output pins */ + + if (func == 1 || func == 3 || func == 5) + { + tiva_initoutput(pinset); + } + +#ifdef CONFIG_TIVA_GPIO_IRQS + /* Special setup for interrupt GPIO pins */ + + else if (func == 7) + { + tiva_interrupt(pinset); + } +#endif + + leave_critical_section(flags); + return OK; +} + +/**************************************************************************** + * Name: tiva_gpiowrite + * + * Description: + * Write one or zero to the selected GPIO pin + * + ****************************************************************************/ + +void tiva_gpiowrite(uint32_t pinset, bool value) +{ + unsigned int port; + unsigned int pinno; + uintptr_t base; + + /* Decode the basics */ + + port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; + pinno = (pinset & GPIO_PIN_MASK); + + /* Get the base address associated with the GPIO port */ + + base = tiva_gpiobaseaddress(port); + + /* "The GPIO DATA register is the data register. In software control mode, + * values written in the GPIO DATA register are transferred onto the GPIO + * port pins if the respective pins have been configured as outputs through + * the GPIO Direction (GPIO DIR) register ... + * + * "In order to write to GPIO DATA, the corresponding bits in the mask, + * resulting from the address bus bits [9:2], must be High. Otherwise, the + * bit values remain unchanged by the write. + * + * "... All bits are cleared by a reset." + */ + + putreg32((uint32_t)value << pinno, base + TIVA_GPIO_DATA_OFFSET + (1 << (pinno + 2))); +} + +/**************************************************************************** + * Name: tiva_gpioread + * + * Description: + * Read one or zero from the selected GPIO pin + * + ****************************************************************************/ + +bool tiva_gpioread(uint32_t pinset) +{ + unsigned int port; + unsigned int pinno; + uintptr_t base; + + /* Decode the basics */ + + port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; + pinno = (pinset & GPIO_PIN_MASK); + + /* Get the base address associated with the GPIO port */ + + base = tiva_gpiobaseaddress(port); + + /* "... the values read from this register are determined for each bit + * by the mask bit derived from the address used to access the data register, + * bits [9:2]. Bits that are 1 in the address mask cause the corresponding + * bits in GPIODATA to be read, and bits that are 0 in the address mask cause + * the corresponding bits in GPIO DATA to be read as 0, regardless of their + * value. + * + * "A read from GPIO DATA returns the last bit value written if the respective + * pins are configured as outputs, or it returns the value on the + * corresponding input pin when these are configured as inputs. All bits + * are cleared by a reset." + */ + return (getreg32(base + TIVA_GPIO_DATA_OFFSET + (1 << (pinno + 2))) != 0); +} + +/**************************************************************************** + * Name: tiva_gpio_lockport + * + * Description: + * Certain pins require to be unlocked from the NMI to use for normal GPIO + * use. See table 10-10 in datasheet for pins with special considerations. + * + ****************************************************************************/ + +void tiva_gpio_lockport(uint32_t pinset, bool lock) +{ + unsigned int port; + unsigned int pinno; + uintptr_t base; + uint32_t pinmask; + + /* Decode the basics */ + + port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; + pinno = (pinset & GPIO_PIN_MASK); + pinmask = 1 << pinno; + + /* Get the base address associated with the GPIO port */ + + base = tiva_gpiobaseaddress(port); + + /* allow access to the TIVA_GPIO_CR_OFFSET register */ + + modifyreg32(base + TIVA_GPIO_LOCK_OFFSET, 0, GPIO_LOCK_UNLOCK); + + /* lock or unlock the pin */ + + if (lock) + { + gpioinfo(" locking port=%d pin=%d\n", port, pinno); + modifyreg32(base + TIVA_GPIO_CR_OFFSET, pinmask, 0); + } + else + { + gpioinfo("unlocking port=%d pin=%d\n", port, pinno); + modifyreg32(base + TIVA_GPIO_CR_OFFSET, 0, pinmask); + } + + /* Restrict access to the TIVA_GPIO_CR_OFFSET register */ + + modifyreg32(base + TIVA_GPIO_LOCK_OFFSET, GPIO_LOCK_UNLOCK, GPIO_LOCK_LOCKED); +} diff --git a/arch/arm/src/tiva/lm/lm4f_gpio.c b/arch/arm/src/tiva/lm/lm4f_gpio.c new file mode 100644 index 0000000000..c956f3baa0 --- /dev/null +++ b/arch/arm/src/tiva/lm/lm4f_gpio.c @@ -0,0 +1,930 @@ +/**************************************************************************** + * arch/arm/src/tiva/lm/lm4f_gpio.c + * + * Copyright (C) 2009-2010, 2014-2015, 2018 Gregory Nutt. All rights + * reserved. + * Author: Gregory Nutt + * + * 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. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 + * COPYRIGHT OWNER OR CONTRIBUTORS 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include + +#include "up_arch.h" +#include "tiva_enablepwr.h" +#include "tiva_enableclks.h" +#include "tiva_gpio.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* These definitions are part of the implementation of the GPIO pad + * configuration of Table 9-1 in the LM3S6918 data sheet. + */ + +#define AMSEL_SHIFT 6 +#define AMSEL_1 (1 << AMSEL_SHIFT) /* Set/clear bit in GPIO AMSEL register */ +#define AMSEL_0 0 +#define AMSEL_X 0 + +#define AFSEL_SHIFT 5 +#define AFSEL_1 (1 << AFSEL_SHIFT) /* Set/clear bit in GPIO AFSEL register */ +#define AFSEL_0 0 +#define AFSEL_X 0 + +#define DIR_SHIFT 4 +#define DIR_1 (1 << DIR_SHIFT) /* Set/clear bit in GPIO DIR register */ +#define DIR_0 0 +#define DIR_X 0 + +#define ODR_SHIFT 3 +#define ODR_1 (1 << ODR_SHIFT) /* Set/clear bit in GPIO ODR register */ +#define ODR_0 0 +#define ODR_X 0 + +#define DEN_SHIFT 2 +#define DEN_1 (1 << DEN_SHIFT) /* Set/clear bit in GPIO DEN register */ +#define DEN_0 0 +#define DEN_X 0 + +#define PUR_SHIFT 1 +#define PUR_1 (1 << PUR_SHIFT) /* Set/clear bit in GPIO PUR register */ +#define PUR_0 0 +#define PUR_X 0 + +#define PDR_SHIFT 0 +#define PDR_1 (1 << PDR_SHIFT) /* Set/clear bit in GPIO PDR register */ +#define PDR_0 0 +#define PDR_X 0 + +#define GPIO_INPUT_SETBITS (AMSEL_0 | AFSEL_0 | DIR_0 | ODR_0 | DEN_1 | PUR_X | PDR_X) +#define GPIO_INPUT_CLRBITS (AMSEL_1 | AFSEL_1 | DIR_1 | ODR_1 | DEN_0 | PUR_X | PDR_X) + +#define GPIO_OUTPUT_SETBITS (AMSEL_0 | AFSEL_0 | DIR_1 | ODR_0 | DEN_1 | PUR_X | PDR_X) +#define GPIO_OUTPUT_CLRBITS (AMSEL_1 | AFSEL_1 | DIR_0 | ODR_1 | DEN_0 | PUR_X | PDR_X) + +#define GPIO_ODINPUT_SETBITS (AMSEL_0 | AFSEL_0 | DIR_0 | ODR_1 | DEN_1 | PUR_X | PDR_X) +#define GPIO_ODINPUT_CLRBITS (AMSEL_1 | AFSEL_1 | DIR_1 | ODR_0 | DEN_0 | PUR_X | PDR_X) + +#define GPIO_ODOUTPUT_SETBITS (AMSEL_0 | AFSEL_0 | DIR_1 | ODR_1 | DEN_1 | PUR_X | PDR_X) +#define GPIO_ODOUTPUT_CLRBITS (AMSEL_1 | AFSEL_1 | DIR_0 | ODR_0 | DEN_0 | PUR_X | PDR_X) + +#define GPIO_PFODIO_SETBITS (AMSEL_0 | AFSEL_1 | DIR_X | ODR_1 | DEN_1 | PUR_X | PDR_X) +#define GPIO_PFODIO_CLRBITS (AMSEL_1 | AFSEL_0 | DIR_X | ODR_0 | DEN_0 | PUR_X | PDR_X) + +#define GPIO_PFIO_SETBITS (AMSEL_0 | AFSEL_1 | DIR_X | ODR_0 | DEN_1 | PUR_X | PDR_X) +#define GPIO_PFIO_CLRBITS (AMSEL_1 | AFSEL_0 | DIR_X | ODR_1 | DEN_0 | PUR_X | PDR_X) + +#define GPIO_ANINPUT_SETBITS (AMSEL_1 | AFSEL_0 | DIR_0 | ODR_0 | DEN_0 | PUR_0 | PDR_0) +#define GPIO_ANINPUT_CLRBITS (AMSEL_0 | AFSEL_1 | DIR_1 | ODR_1 | DEN_1 | PUR_1 | PDR_1) + +#define GPIO_INTERRUPT_SETBITS (AMSEL_0 | AFSEL_0 | DIR_0 | ODR_0 | DEN_1 | PUR_X | PDR_X) +#define GPIO_INTERRUPT_CLRBITS (AMSEL_1 | AFSEL_1 | DIR_1 | ODR_1 | DEN_0 | PUR_X | PDR_X) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct gpio_func_s +{ + uint8_t setbits; /* A set of GPIO register bits to set */ + uint8_t clrbits; /* A set of GPIO register bits to clear */ +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct gpio_func_s g_funcbits[] = +{ + {GPIO_INPUT_SETBITS, GPIO_INPUT_CLRBITS}, /* GPIO_FUNC_INPUT */ + {GPIO_OUTPUT_SETBITS, GPIO_OUTPUT_CLRBITS}, /* GPIO_FUNC_OUTPUT */ + {GPIO_ODINPUT_SETBITS, GPIO_ODINPUT_CLRBITS}, /* GPIO_FUNC_ODINPUT */ + {GPIO_ODOUTPUT_SETBITS, GPIO_ODOUTPUT_CLRBITS}, /* GPIO_FUNC_ODOUTPUT */ + {GPIO_PFODIO_SETBITS, GPIO_PFODIO_CLRBITS}, /* GPIO_FUNC_PFODIO */ + {GPIO_PFIO_SETBITS, GPIO_PFIO_CLRBITS}, /* GPIO_FUNC_PFIO */ + {GPIO_ANINPUT_SETBITS, GPIO_ANINPUT_CLRBITS}, /* GPIO_FUNC_ANINPUT */ + {GPIO_INTERRUPT_SETBITS, GPIO_INTERRUPT_CLRBITS}, /* GPIO_FUNC_INTERRUPT */ +}; + +/* NOTE: this is duplicated in tiva_dumpgpio.c */ + +static const uintptr_t g_gpiobase[TIVA_NPORTS] = +{ +#if TIVA_NPORTS > 0 + TIVA_GPIOA_BASE +#endif +#if TIVA_NPORTS > 1 + , TIVA_GPIOB_BASE +#endif +#if TIVA_NPORTS > 2 + , TIVA_GPIOC_BASE +#endif +#if TIVA_NPORTS > 3 + , TIVA_GPIOD_BASE +#endif +#if TIVA_NPORTS > 4 + , TIVA_GPIOE_BASE +#endif +#if TIVA_NPORTS > 5 + , TIVA_GPIOF_BASE +#endif +#if TIVA_NPORTS > 6 + , TIVA_GPIOG_BASE +#endif +#if TIVA_NPORTS > 7 + , TIVA_GPIOH_BASE +#endif +#if TIVA_NPORTS > 8 + , TIVA_GPIOJ_BASE +#endif +#if TIVA_NPORTS > 9 + , TIVA_GPIOK_BASE +#endif +#if TIVA_NPORTS > 10 + , TIVA_GPIOL_BASE +#endif +#if TIVA_NPORTS > 11 + , TIVA_GPIOM_BASE +#endif +#if TIVA_NPORTS > 12 + , TIVA_GPION_BASE +#endif +#if TIVA_NPORTS > 13 + , TIVA_GPIOP_BASE +#endif +#if TIVA_NPORTS > 14 + , TIVA_GPIOQ_BASE +#endif +#if TIVA_NPORTS > 15 + , TIVA_GPIOR_BASE +#endif +#if TIVA_NPORTS > 16 + , TIVA_GPIOS_BASE +#endif +#if TIVA_NPORTS > 17 + , TIVA_GPIOT_BASE +#endif +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tiva_gpiobaseaddress + * + * Description: + * Given a GPIO enumeration value, return the base address of the + * associated GPIO registers. + * + ****************************************************************************/ + +inline uintptr_t tiva_gpiobaseaddress(unsigned int port) +{ + uintptr_t gpiobase = 0; + if (port < TIVA_NPORTS) + { + gpiobase = g_gpiobase[port]; + } + + return gpiobase; +} + +/**************************************************************************** + * Name: tiva_gpiofunc + * + * Description: + * Configure GPIO registers for a specific function. Overwrites certain + * padtype configurations. + * + ****************************************************************************/ + +static void tiva_gpiofunc(uint32_t base, uint32_t pinno, + const struct gpio_func_s *func) +{ + uint32_t setbit; + uint32_t clrbit; + + /* Set/clear/ignore the GPIO DIR bit. "The GPIODIR register is the data + * direction register. Bits set to 1 in the GPIODIR register configure + * the corresponding pin to be an output, while bits set to 0 configure + * the pins to be inputs. All bits are cleared by a reset, meaning all + * GPIO pins are inputs by default. + */ + + setbit = (((uint32_t)func->setbits >> DIR_SHIFT) & 1) << pinno; + clrbit = (((uint32_t)func->clrbits >> DIR_SHIFT) & 1) << pinno; + + if (setbit || clrbit) + { + modifyreg32(base + TIVA_GPIO_DIR_OFFSET, clrbit, setbit); + } + + /* Set/clear/ignore the GPIO AFSEL bit. "The GPIOAFSEL register is the + * mode control select register. Writing a 1 to any bit in this register + * selects the hardware control for the corresponding GPIO line. All bits + * are cleared by a reset, therefore no GPIO line is set to hardware + * control by default." + * + * NOTE: In order to set JTAG/SWD GPIOs, it is also necessary to lock, + * commit and unlock the GPIO. That is not implemented here. + */ + + setbit = (((uint32_t)func->setbits >> AFSEL_SHIFT) & 1) << pinno; + clrbit = (((uint32_t)func->clrbits >> AFSEL_SHIFT) & 1) << pinno; + + if (setbit || clrbit) + { + modifyreg32(base + TIVA_GPIO_AFSEL_OFFSET, clrbit, setbit); + } + + /* Set/clear/ignore the GPIO ODR bit. "The GPIO ODR register is the open + * drain control register. Setting a bit in this register enables the open + * drain configuration of the corresponding GPIO pad. When open drain mode + * is enabled, the corresponding bit should also be set in the GPIO Digital + * Input Enable (GPIO DEN) register ... Corresponding bits in the drive + * strength registers (GPIO DR2R, GPIO DR4R, GPIO DR8R, and GPIO SLR ) can + * be set to achieve the desired rise and fall times. The GPIO acts as an + * open drain input if the corresponding bit in the GPIO DIR register is + * set to 0; and as an open drain output when set to 1." + */ + + setbit = (((uint32_t)func->setbits >> ODR_SHIFT) & 1) << pinno; + clrbit = (((uint32_t)func->clrbits >> ODR_SHIFT) & 1) << pinno; + + if (setbit || clrbit) + { + modifyreg32(base + TIVA_GPIO_ODR_OFFSET, clrbit, setbit); + } + + /* Set/clear the GPIO PUR bit. "The GPIOPUR register is the pull-up + * control register. When a bit is set to 1, it enables a weak pull-up + * resistor on the corresponding GPIO signal. Setting a bit in GPIOPUR + * automatically clears the corresponding bit in the GPIO Pull-Down + * Select (GPIOPDR) register ..." + */ + + setbit = (((uint32_t)func->setbits >> PUR_SHIFT) & 1) << pinno; + clrbit = (((uint32_t)func->clrbits >> PUR_SHIFT) & 1) << pinno; + + if (setbit || clrbit) + { + modifyreg32(base + TIVA_GPIO_PUR_OFFSET, clrbit, setbit); + } + + /* Set/clear the GPIO PDR bit. "The GPIOPDR register is the pull-down + * control register. When a bit is set to 1, it enables a weak pull-down + * resistor on the corresponding GPIO signal. Setting a bit in GPIOPDR + * automatically clears the corresponding bit in the GPIO Pull-Up Select + * (GPIOPUR) register ..." + */ + + setbit = (((uint32_t)func->setbits >> PDR_SHIFT) & 1) << pinno; + clrbit = (((uint32_t)func->clrbits >> PDR_SHIFT) & 1) << pinno; + + if (setbit || clrbit) + { + modifyreg32(base + TIVA_GPIO_PDR_OFFSET, clrbit, setbit); + } + + /* Set/clear the GPIO DEN bit. "The GPIODEN register is the digital enable + * register. By default, with the exception of the GPIO signals used for + * JTAG/SWD function, all other GPIO signals are configured out of reset + * to be undriven (tristate). Their digital function is disabled; they do + * not drive a logic value on the pin and they do not allow the pin voltage + * into the GPIO receiver. To use the pin in a digital function (either + * GPIO or alternate function), the corresponding GPIODEN bit must be set." + */ + + setbit = (((uint32_t)func->setbits >> DEN_SHIFT) & 1) << pinno; + clrbit = (((uint32_t)func->clrbits >> DEN_SHIFT) & 1) << pinno; + + if (setbit || clrbit) + { + modifyreg32(base + TIVA_GPIO_DEN_OFFSET, clrbit, setbit); + } + + /* Set/clear/ignore the GPIO AMSEL bit. "The GPIOAMSEL register controls + * isolation circuits to the analog side of a unified I/O pad. Because + * the GPIOs may be driven by a 5-V source and affect analog operation, + * analog circuitry requires isolation from the pins when they are not + * used in their analog function. Each bit of this register controls the + * isolation circuitry for the corresponding GPIO signal. + */ + + setbit = (((uint32_t)func->setbits >> AMSEL_SHIFT) & 1) << pinno; + clrbit = (((uint32_t)func->clrbits >> AMSEL_SHIFT) & 1) << pinno; + + if (setbit || clrbit) + { + modifyreg32(base + TIVA_GPIO_AMSEL_OFFSET, clrbit, setbit); + } +} + +/**************************************************************************** + * Name: tiva_gpiopadstrength + * + * Description: + * Set up pad strength and pull-ups + * + ****************************************************************************/ + +static inline void tiva_gpiopadstrength(uint32_t base, uint32_t pin, + uint32_t pinset) +{ + int strength = (pinset & GPIO_STRENGTH_MASK); + uint32_t slrset = 0; + uint32_t slrclr = 0; + uint32_t dr2rset = 0; + uint32_t dr2rclr = 0; + uint32_t dr4rset = 0; + uint32_t dr4rclr = 0; + uint32_t dr8rset = 0; + uint32_t dr8rclr = 0; + + /* Set the output drive strength. */ + + switch (strength) + { + case GPIO_STRENGTH_2MA: + { + dr2rset = pin; + dr4rclr = pin; + dr8rclr = pin; + slrclr = pin; + } + break; + + case GPIO_STRENGTH_4MA: + { + dr2rclr = pin; + dr4rset = pin; + dr8rclr = pin; + slrclr = pin; + } + break; + + case GPIO_STRENGTH_8MA: + { + dr2rclr = pin; + dr4rclr = pin; + dr8rset = pin; + slrclr = pin; + } + break; + + case GPIO_STRENGTH_8MASC: + { + dr2rclr = pin; + dr4rclr = pin; + dr8rset = pin; + slrset = pin; + } + break; + + default: + break; + } + + modifyreg32(base + TIVA_GPIO_DR2R_OFFSET, dr2rclr, dr2rset); + modifyreg32(base + TIVA_GPIO_DR4R_OFFSET, dr4rclr, dr4rset); + modifyreg32(base + TIVA_GPIO_DR8R_OFFSET, dr8rclr, dr8rset); + modifyreg32(base + TIVA_GPIO_SLR_OFFSET, slrclr, slrset); +} + +/**************************************************************************** + * Name: tiva_gpiopadtype + * + * Description: + * Set up pad strength and pull-ups. Some of these values may be over- + * written by tiva_gpiofunc, depending on the function selection. Others + * are optional for different function selections. + * + ****************************************************************************/ + +static inline void tiva_gpiopadtype(uint32_t base, uint32_t pin, + uint32_t pinset) +{ + int padtype = (pinset & GPIO_PADTYPE_MASK); + uint32_t odrset = 0; + uint32_t odrclr = 0; + uint32_t purset = 0; + uint32_t purclr = 0; + uint32_t pdrset = 0; + uint32_t pdrclr = 0; + uint32_t denset = 0; + uint32_t denclr = 0; + uint32_t amselset = 0; + uint32_t amselclr = 0; + + /* Set the pin type. */ + + switch (padtype) + { + case GPIO_PADTYPE_STD: + { + odrclr = pin; + purclr = pin; + pdrclr = pin; + denset = pin; + amselclr = pin; + } + break; + + case GPIO_PADTYPE_STDWPU: + { + odrclr = pin; + purset = pin; + pdrclr = pin; + denset = pin; + amselclr = pin; + } + break; + + case GPIO_PADTYPE_STDWPD: + { + odrclr = pin; + purclr = pin; + pdrset = pin; + denset = pin; + amselclr = pin; + } + break; + + case GPIO_PADTYPE_OD: + { + odrset = pin; + purclr = pin; + pdrclr = pin; + denset = pin; + amselclr = pin; + } + break; + + case GPIO_PADTYPE_ODWPU: + { + odrset = pin; + purset = pin; + pdrclr = pin; + denclr = pin; + amselclr = pin; + } + break; + + case GPIO_PADTYPE_ODWPD: + { + odrset = pin; + purclr = pin; + pdrset = pin; + denclr = pin; + amselclr = pin; + } + break; + + case GPIO_PADTYPE_ANALOG: + { + odrclr = pin; + purclr = pin; + pdrclr = pin; + denclr = pin; + amselset = pin; + } + break; + + default: + break; + } + + modifyreg32(base + TIVA_GPIO_ODR_OFFSET, odrclr, odrset); + modifyreg32(base + TIVA_GPIO_PUR_OFFSET, purclr, purset); + modifyreg32(base + TIVA_GPIO_PDR_OFFSET, pdrclr, pdrset); + modifyreg32(base + TIVA_GPIO_DEN_OFFSET, denclr, denset); + modifyreg32(base + TIVA_GPIO_AMSEL_OFFSET, amselclr, amselset); +} + +/**************************************************************************** + * Name: tiva_initoutput + * + * Description: + * Set the GPIO output value + * + ****************************************************************************/ + +static inline void tiva_initoutput(uint32_t pinset) +{ + bool value = ((pinset & GPIO_VALUE_MASK) != GPIO_VALUE_ZERO); + tiva_gpiowrite(pinset, value); +} + +/**************************************************************************** + * Name: tiva_interrupt + * + * Description: + * Configure the interrupt pin. + * + ****************************************************************************/ + +#ifdef CONFIG_TIVA_GPIO_IRQS +static inline void tiva_interrupt(uint32_t pinset) +{ + uint8_t port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; + uint8_t pin = 1 << (pinset & GPIO_PIN_MASK); + uintptr_t base = tiva_gpiobaseaddress(port); + uint32_t inttype = pinset & GPIO_INT_MASK; + + uint32_t isset = 0; + uint32_t ibeset = 0; + uint32_t ievset = 0; + uint32_t isclr = 0; + uint32_t ibeclr = 0; + uint32_t ievclr = 0; + + /* Mask and clear the GPIO interrupt */ + + tiva_gpioirqdisable(port, pin); + tiva_gpioirqclear(port, pin); + + /* handle according to the selected interrupt type */ + + switch (inttype) + { + case GPIO_INT_FALLINGEDGE: + { + isclr = pin; + ibeclr = pin; + ievclr = pin; + } + break; + + case GPIO_INT_RISINGEDGE: + { + isclr = pin; + ibeclr = pin; + ievset = pin; + } + break; + + case GPIO_INT_BOTHEDGES: + { + isclr = pin; + ibeset = pin; + ievclr = pin; + } + break; + + case GPIO_INT_LOWLEVEL: + { + isset = pin; + ibeclr = pin; + ievclr = pin; + } + break; + + case GPIO_INT_HIGHLEVEL: + { + isset = pin; + ibeclr = pin; + ievset = pin; + } + break; + + default: + break; + } + + /* "The GPIO IBE register is the interrupt both-edges register. When the + * corresponding bit in the GPIO Interrupt Sense (GPIO IS) register ... is + * set to detect edges, bits set to High in GPIO IBE configure the + * corresponding pin to detect both rising and falling edges, regardless + * of the corresponding bit in the GPIO Interrupt Event (GPIO IEV) register ... + * Clearing a bit configures the pin to be controlled by GPIOIEV. All bits + * are cleared by a reset. + */ + + modifyreg32(base + TIVA_GPIO_IBE_OFFSET, ibeclr, ibeset); + + /* "The GPIO IS register is the interrupt sense register. Bits set to + * 1 in GPIOIS configure the corresponding pins to detect levels, while + * bits set to 0 configure the pins to detect edges. All bits are cleared + * by a reset. + */ + + modifyreg32(base + TIVA_GPIO_IS_OFFSET, isclr, isset); + + /* "The GPIOIEV register is the interrupt event register. Bits set to + * High in GPIO IEV configure the corresponding pin to detect rising edges + * or high levels, depending on the corresponding bit value in the GPIO + * Interrupt Sense (GPIO IS) register... Clearing a bit configures the pin to + * detect falling edges or low levels, depending on the corresponding bit + * value in GPIOIS. All bits are cleared by a reset. + */ + + modifyreg32(base + TIVA_GPIO_IEV_OFFSET, ievclr, ievset); + +#ifdef CONFIG_DEBUG_GPIO_INFO + uint32_t regval; + + gpioinfo("reg expected actual: [interrupt type=%d]\n", inttype); + + regval = (getreg32(base+TIVA_GPIO_IS_OFFSET) & pin) ? pin : 0; + gpioinfo("IS 0x%08x 0x%08x\n", isset, regval); + + regval = (getreg32(base+TIVA_GPIO_IBE_OFFSET) & pin) ? pin : 0; + gpioinfo("IBE 0x%08x 0x%08x\n", ibeset, regval); + + regval = (getreg32(base+TIVA_GPIO_IEV_OFFSET) & pin) ? pin : 0; + gpioinfo("IEV 0x%08x 0x%08x\n", ievset, regval); +#endif +} +#endif + +/**************************************************************************** + * Name: tiva_portcontrol + * + * Description: + * Set the pin alternate function in the port control register. + * + ****************************************************************************/ + +static inline void tiva_portcontrol(uint32_t base, uint32_t pinno, + uint32_t pinset, + const struct gpio_func_s *func) +{ + uint32_t alt = 0; + uint32_t mask; + uint32_t regval; + + /* Is this pin an alternate function pin? */ + + if ((func->setbits & AFSEL_1) != 0) + { + /* Yes, extract the alternate function number from the pin + * configuration. + */ + + alt = (pinset & GPIO_ALT_MASK) >> GPIO_ALT_SHIFT; + } + + /* Set the alternate function in the port control register */ + + regval = getreg32(base + TIVA_GPIO_PCTL_OFFSET); + mask = GPIO_PCTL_PMC_MASK(pinno); + regval &= ~mask; + regval |= (alt << GPIO_PCTL_PMC_SHIFT(pinno)) & mask; + putreg32(regval, base + TIVA_GPIO_PCTL_OFFSET); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tiva_configgpio + * + * Description: + * Configure a GPIO pin based on bit-encoded description of the pin. + * + ****************************************************************************/ + +int tiva_configgpio(uint32_t pinset) +{ + irqstate_t flags; + unsigned int func; + unsigned int port; + unsigned int pinno; + uintptr_t base; + uint32_t pin; + + /* Decode the basics */ + + func = (pinset & GPIO_FUNC_MASK) >> GPIO_FUNC_SHIFT; + port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; + pinno = (pinset & GPIO_PIN_MASK); + pin = (1 << pinno); + + DEBUGASSERT(func <= GPIO_FUNC_MAX); + + /* Get the base address associated with the GPIO port */ + + base = tiva_gpiobaseaddress(port); + DEBUGASSERT(base != 0); + + /* The following requires exclusive access to the GPIO registers */ + + flags = enter_critical_section(); + + /* Enable power and clocking for this GPIO peripheral. Applies both power + * and clocking to the GPIO peripheral, bringing it a fully functional + * state. + */ + + tiva_gpio_enablepwr(port); + tiva_gpio_enableclk(port); + + /* First, set the port to digital input. This is the safest state in which + * to perform reconfiguration. + */ + + tiva_gpiofunc(base, pinno, &g_funcbits[0]); + tiva_portcontrol(base, pinno, pinset, &g_funcbits[0]); + + /* Then set up pad strengths and pull-ups. These setups should be done before + * setting up the function because some function settings will over-ride these + * user options. + */ + + tiva_gpiopadstrength(base, pin, pinset); + tiva_gpiopadtype(base, pin, pinset); + + /* Then set up the real pin function */ + + tiva_gpiofunc(base, pinno, &g_funcbits[func]); + tiva_portcontrol(base, pinno, pinset, &g_funcbits[func]); + + /* Special case GPIO digital output pins */ + + if (func == 1 || func == 3 || func == 5) + { + tiva_initoutput(pinset); + } + +#ifdef CONFIG_TIVA_GPIO_IRQS + /* Special setup for interrupt GPIO pins */ + + else if (func == 7) + { + tiva_interrupt(pinset); + } +#endif + + leave_critical_section(flags); + return OK; +} + +/**************************************************************************** + * Name: tiva_gpiowrite + * + * Description: + * Write one or zero to the selected GPIO pin + * + ****************************************************************************/ + +void tiva_gpiowrite(uint32_t pinset, bool value) +{ + unsigned int port; + unsigned int pinno; + uintptr_t base; + + /* Decode the basics */ + + port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; + pinno = (pinset & GPIO_PIN_MASK); + + /* Get the base address associated with the GPIO port */ + + base = tiva_gpiobaseaddress(port); + + /* "The GPIO DATA register is the data register. In software control mode, + * values written in the GPIO DATA register are transferred onto the GPIO + * port pins if the respective pins have been configured as outputs through + * the GPIO Direction (GPIO DIR) register ... + * + * "In order to write to GPIO DATA, the corresponding bits in the mask, + * resulting from the address bus bits [9:2], must be High. Otherwise, the + * bit values remain unchanged by the write. + * + * "... All bits are cleared by a reset." + */ + + putreg32((uint32_t)value << pinno, base + TIVA_GPIO_DATA_OFFSET + (1 << (pinno + 2))); +} + +/**************************************************************************** + * Name: tiva_gpioread + * + * Description: + * Read one or zero from the selected GPIO pin + * + ****************************************************************************/ + +bool tiva_gpioread(uint32_t pinset) +{ + unsigned int port; + unsigned int pinno; + uintptr_t base; + + /* Decode the basics */ + + port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; + pinno = (pinset & GPIO_PIN_MASK); + + /* Get the base address associated with the GPIO port */ + + base = tiva_gpiobaseaddress(port); + + /* "... the values read from this register are determined for each bit + * by the mask bit derived from the address used to access the data register, + * bits [9:2]. Bits that are 1 in the address mask cause the corresponding + * bits in GPIODATA to be read, and bits that are 0 in the address mask cause + * the corresponding bits in GPIO DATA to be read as 0, regardless of their + * value. + * + * "A read from GPIO DATA returns the last bit value written if the respective + * pins are configured as outputs, or it returns the value on the + * corresponding input pin when these are configured as inputs. All bits + * are cleared by a reset." + */ + return (getreg32(base + TIVA_GPIO_DATA_OFFSET + (1 << (pinno + 2))) != 0); +} + +/**************************************************************************** + * Name: tiva_gpio_lockport + * + * Description: + * Certain pins require to be unlocked from the NMI to use for normal GPIO + * use. See table 10-10 in datasheet for pins with special considerations. + * + ****************************************************************************/ + +void tiva_gpio_lockport(uint32_t pinset, bool lock) +{ + unsigned int port; + unsigned int pinno; + uintptr_t base; + uint32_t pinmask; + + /* Decode the basics */ + + port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; + pinno = (pinset & GPIO_PIN_MASK); + pinmask = 1 << pinno; + + /* Get the base address associated with the GPIO port */ + + base = tiva_gpiobaseaddress(port); + + /* allow access to the TIVA_GPIO_CR_OFFSET register */ + + modifyreg32(base + TIVA_GPIO_LOCK_OFFSET, 0, GPIO_LOCK_UNLOCK); + + /* lock or unlock the pin */ + + if (lock) + { + gpioinfo(" locking port=%d pin=%d\n", port, pinno); + modifyreg32(base + TIVA_GPIO_CR_OFFSET, pinmask, 0); + } + else + { + gpioinfo("unlocking port=%d pin=%d\n", port, pinno); + modifyreg32(base + TIVA_GPIO_CR_OFFSET, 0, pinmask); + } + + /* Restrict access to the TIVA_GPIO_CR_OFFSET register */ + + modifyreg32(base + TIVA_GPIO_LOCK_OFFSET, GPIO_LOCK_UNLOCK, GPIO_LOCK_LOCKED); +} diff --git a/arch/arm/src/tiva/common/tiva_gpio.c b/arch/arm/src/tiva/tm4c/tm4c_gpio.c similarity index 97% rename from arch/arm/src/tiva/common/tiva_gpio.c rename to arch/arm/src/tiva/tm4c/tm4c_gpio.c index c8e8fd2c82..b43498e4c5 100644 --- a/arch/arm/src/tiva/common/tiva_gpio.c +++ b/arch/arm/src/tiva/tm4c/tm4c_gpio.c @@ -1,7 +1,8 @@ /**************************************************************************** - * arch/arm/src/tiva/common/tiva_gpio.c + * arch/arm/src/tiva/tm4c/tm4c_gpio.c * - * Copyright (C) 2009-2010, 2014-2015 Gregory Nutt. All rights reserved. + * Copyright (C) 2009-2010, 2014-2015, 2018 Gregory Nutt. All rights + * reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -347,7 +348,6 @@ static void tiva_gpiofunc(uint32_t base, uint32_t pinno, modifyreg32(base + TIVA_GPIO_DEN_OFFSET, clrbit, setbit); } -#if defined(LM4F) || defined(TM4C) /* Set/clear/ignore the GPIO AMSEL bit. "The GPIOAMSEL register controls * isolation circuits to the analog side of a unified I/O pad. Because * the GPIOs may be driven by a 5-V source and affect analog operation, @@ -363,7 +363,6 @@ static void tiva_gpiofunc(uint32_t base, uint32_t pinno, { modifyreg32(base + TIVA_GPIO_AMSEL_OFFSET, clrbit, setbit); } -#endif } /**************************************************************************** @@ -499,10 +498,8 @@ static inline void tiva_gpiopadtype(uint32_t base, uint32_t pin, uint32_t pdrclr = 0; uint32_t denset = 0; uint32_t denclr = 0; -#if defined(LM4F) || defined(TM4C) uint32_t amselset = 0; uint32_t amselclr = 0; -#endif /* Set the pin type. */ @@ -514,9 +511,7 @@ static inline void tiva_gpiopadtype(uint32_t base, uint32_t pin, purclr = pin; pdrclr = pin; denset = pin; -#if defined(LM4F) || defined(TM4C) amselclr = pin; -#endif } break; @@ -526,9 +521,7 @@ static inline void tiva_gpiopadtype(uint32_t base, uint32_t pin, purset = pin; pdrclr = pin; denset = pin; -#if defined(LM4F) || defined(TM4C) amselclr = pin; -#endif } break; @@ -538,9 +531,7 @@ static inline void tiva_gpiopadtype(uint32_t base, uint32_t pin, purclr = pin; pdrset = pin; denset = pin; -#if defined(LM4F) || defined(TM4C) amselclr = pin; -#endif } break; @@ -550,9 +541,7 @@ static inline void tiva_gpiopadtype(uint32_t base, uint32_t pin, purclr = pin; pdrclr = pin; denset = pin; -#if defined(LM4F) || defined(TM4C) amselclr = pin; -#endif } break; @@ -562,9 +551,7 @@ static inline void tiva_gpiopadtype(uint32_t base, uint32_t pin, purset = pin; pdrclr = pin; denclr = pin; -#if defined(LM4F) || defined(TM4C) amselclr = pin; -#endif } break; @@ -574,9 +561,7 @@ static inline void tiva_gpiopadtype(uint32_t base, uint32_t pin, purclr = pin; pdrset = pin; denclr = pin; -#if defined(LM4F) || defined(TM4C) amselclr = pin; -#endif } break; @@ -586,9 +571,7 @@ static inline void tiva_gpiopadtype(uint32_t base, uint32_t pin, purclr = pin; pdrclr = pin; denclr = pin; -#if defined(LM4F) || defined(TM4C) amselset = pin; -#endif } break; @@ -600,10 +583,7 @@ static inline void tiva_gpiopadtype(uint32_t base, uint32_t pin, modifyreg32(base + TIVA_GPIO_PUR_OFFSET, purclr, purset); modifyreg32(base + TIVA_GPIO_PDR_OFFSET, pdrclr, pdrset); modifyreg32(base + TIVA_GPIO_DEN_OFFSET, denclr, denset); - -#if defined(LM4F) || defined(TM4C) modifyreg32(base + TIVA_GPIO_AMSEL_OFFSET, amselclr, amselset); -#endif #ifdef CONFIG_ARCH_CHIP_TM4C129 /* Set the wake pin enable register and the wake level register. These @@ -757,7 +737,6 @@ static inline void tiva_interrupt(uint32_t pinset) * ****************************************************************************/ -#if defined(LM4F) || defined(TM4C) static inline void tiva_portcontrol(uint32_t base, uint32_t pinno, uint32_t pinset, const struct gpio_func_s *func) @@ -785,9 +764,6 @@ static inline void tiva_portcontrol(uint32_t base, uint32_t pinno, regval |= (alt << GPIO_PCTL_PMC_SHIFT(pinno)) & mask; putreg32(regval, base + TIVA_GPIO_PCTL_OFFSET); } -#else -# define tiva_portcontrol(b,p,c,f) -#endif /**************************************************************************** * Public Functions