diff --git a/arch/arm/include/tms570/tms570ls04x03x_irq.h b/arch/arm/include/tms570/tms570ls04x03x_irq.h index b190dcfe48..9a7543215c 100644 --- a/arch/arm/include/tms570/tms570ls04x03x_irq.h +++ b/arch/arm/include/tms570/tms570ls04x03x_irq.h @@ -58,14 +58,14 @@ /* Default request to channel assignments. Undefined requests are reserved */ -#define TMS570_REQ_ESMHIGH 0 /* ESM High level interrupt (NMI) */ -#define TMS570_REQ_RTICMP0 2 /* RTI compare interrupt 0 */ -#define TMS570_REQ_RTICMP1 3 /* RTI compare interrupt 1 */ -#define TMS570_REQ_RTICMP2 4 /* RTI compare interrupt 2 */ -#define TMS570_REQ_RTICMP3 5 /* RTI compare interrupt 3 */ -#define TMS570_REQ_RTIOVF0 6 /* RTI overflow interrupt 0 */ -#define TMS570_REQ_RTIOVF1 7 /* RTI overflow interrupt 1 */ -#define TMS570_REQ_GIOA 9 /* GIO interrupt A */ +#define TMS570_REQ_ESMHIGH 0 /* ESM High level interrupt (NMI) */ +#define TMS570_REQ_RTICMP0 2 /* RTI compare interrupt 0 */ +#define TMS570_REQ_RTICMP1 3 /* RTI compare interrupt 1 */ +#define TMS570_REQ_RTICMP2 4 /* RTI compare interrupt 2 */ +#define TMS570_REQ_RTICMP3 5 /* RTI compare interrupt 3 */ +#define TMS570_REQ_RTIOVF0 6 /* RTI overflow interrupt 0 */ +#define TMS570_REQ_RTIOVF1 7 /* RTI overflow interrupt 1 */ +#define TMS570_REQ_GIO_0 9 /* GIO level 0 interrupt */ #define TMS570_REQ_N2HET_0 10 /* N2HET level 0 interrupt */ #define TMS570_REQ_HTU_0 11 /* HTU level 0 interrupt */ #define TMS570_REQ_MIBSPI1_0 12 /* MIBSPI1 level 0 interrupt */ @@ -77,7 +77,7 @@ #define TMS570_REQ_ESMLO 20 /* ESM Low level interrupt */ #define TMS570_REQ_SYSTEM 21 /* Software interrupt (SSI) */ #define TMS570_REQ_CPU 22 /* PMU interrupt */ -#define TMS570_REQ_GIOB 23 /* GIO interrupt B */ +#define TMS570_REQ_GIO_1 23 /* GIO level 1 interrupt */ #define TMS570_REQ_N2HET_1 24 /* N2HET level 1 interrupt */ #define TMS570_REQ_HTU_1 25 /* HTU level 1 interrupt */ #define TMS570_REQ_MIBSPI1_1 26 /* MIBSPI1 level 1 interrupt */ diff --git a/arch/arm/src/tms570/Make.defs b/arch/arm/src/tms570/Make.defs index 6083ef9ba4..f630326828 100644 --- a/arch/arm/src/tms570/Make.defs +++ b/arch/arm/src/tms570/Make.defs @@ -104,7 +104,7 @@ CHIP_ASRCS = # SAMA5-specific C source files -CHIP_CSRCS = tms570_boot.c tms570_clockconfig.c tms570_irq.c +CHIP_CSRCS = tms570_boot.c tms570_clockconfig.c tms570_gio.c tms570_irq.c CHIP_CSRCS += tms570_lowputc.c tms570_serial.c # Configuration dependent C and assembly language files @@ -113,6 +113,10 @@ ifneq ($(CONFIG_SCHED_TICKLESS),y) CHIP_CSRCS += tms570_timerisr.c endif -ifneq ($(CONFIG_TMS570_SELFTEST),y) +ifeq ($(CONFIG_TMS570_SELFTEST),y) CHIP_CSRCS += tms570_selftest.c endif + +ifeq ($(CONFIG_TMS570_GIO_IRQ),y) +CHIP_CSRCS += tms570_gioirq.c +endif diff --git a/arch/arm/src/tms570/chip/tms570_gio.h b/arch/arm/src/tms570/chip/tms570_gio.h index c179718bba..1599e58ff5 100644 --- a/arch/arm/src/tms570/chip/tms570_gio.h +++ b/arch/arm/src/tms570/chip/tms570_gio.h @@ -62,6 +62,9 @@ #define TMS570_GIOG 6 #define TMS570_GIOH 7 +#define TMS570_NPORTS 8 +#define TMS570_NIRQPORTS 4 + /* Register Offsets *********************************************************************************/ #define TMS570_GIO_GCR0_OFFSET 0x0000 /* GIO Global Control Register */ @@ -264,6 +267,10 @@ /* GIO Interrupt Detect Register */ +#define GIO_INTDET_PORT_SHIFT(p) ((p) << 3) +#define GIO_INTDET_PORT_MASK(p) (0xff << GIO_INTDET_PORT_SHIFT(p)) +# define GIO_INTDET_PORT_PIN(p,n) (1 << (GIO_INTDET_PORT_SHIFT(p) + (n))) + #define GIO_INTDET_GIOA_SHIFT (0) /* Bits 0-7: Interrupt detection select for pins GIOA[7:0] */ #define GIO_INTDET_GIOA_MASK (0xff << GIO_INTDET_GIOA_SHIFT) # define GIO_INTDET_GIOA_PIN(n) (1 << (GIO_INTDET_GIOA_SHIFT + (n))) @@ -279,6 +286,10 @@ /* GIO Interrupt Polarity Register */ +#define GIO_POL_PORT_SHIFT(p) ((p) << 3) +#define GIO_POL_PORT_MASK(p) (0xff << GIO_POL_PORT_SHIFT(p)) +# define GIO_POL_PORT_PIN(p,n) (1 << (GIO_POL_PORT_SHIFT(p) + (n))) + #define GIO_POL_GIOA_SHIFT (0) /* Bits 0-7: Interrupt polarity select for pins GIOA[7:0] */ #define GIO_POL_GIOA_MASK (0xff << GIO_POL_GIOA_SHIFT) # define GIO_POL_GIOA_PIN(n) (1 << (GIO_POL_GIOA_SHIFT + (n))) @@ -294,6 +305,10 @@ /* GIO Interrupt Enable Set Register */ +#define GIO_ENASET_PORT_SHIFT(p) ((p) << 3) +#define GIO_ENASET_PORT_MASK(p) (0xff << GIO_ENASET_PORT_SHIFT(p)) +# define GIO_ENASET_PORT_PIN(p,n) (1 << (GIO_ENASET_PORT_SHIFT(p) + (n))) + #define GIO_ENASET_GIOA_SHIFT (0) /* Bits 0-7: Interrupt enable for pins GIOA[7:0] */ #define GIO_ENASET_GIOA_MASK (0xff << GIO_ENASET_GIOA_SHIFT) # define GIO_ENASET_GIOA_PIN(n) (1 << (GIO_ENASET_GIOA_SHIFT + (n))) @@ -309,6 +324,10 @@ /* GIO Interrupt Enable Clear Register */ +#define GIO_ENACLR_PORT_SHIFT(p) ((p) << 3) +#define GIO_ENACLR_PORT_MASK(p) (0xff << GIO_ENACLR_PORT_SHIFT(p)) +# define GIO_ENACLR_PORT_PIN(p,n) (1 << (GIO_ENACLR_PORT_SHIFT(p) + (n))) + #define GIO_ENACLR_GIOA_SHIFT (0) /* Bits 0-7: Interrupt disable for pins GIOA[7:0] */ #define GIO_ENACLR_GIOA_MASK (0xff << GIO_ENACLR_GIOA_SHIFT) # define GIO_ENACLR_GIOA_PIN(n) (1 << (GIO_ENACLR_GIOA_SHIFT + (n))) @@ -324,6 +343,10 @@ /* GIO Interrupt Priority Set Register */ +#define GIO_LVLSET_PORT_SHIFT(p) ((p) << 3) +#define GIO_LVLSET_PORT_MASK(p) (0xff << GIO_LVLSET_PORT_SHIFT(p)) +# define GIO_LVLSET_PORT_PIN(p,n) (1 << (GIO_LVLSET_PORT_SHIFT(p) + (n))) + #define GIO_LVLSET_GIOA_SHIFT (0) /* Bits 0-7: Interrupt high level select for pins GIOA[7:0] */ #define GIO_LVLSET_GIOA_MASK (0xff << GIO_LVLSET_GIOA_SHIFT) # define GIO_LVLSET_GIOA_PIN(n) (1 << (GIO_LVLSET_GIOA_SHIFT + (n))) @@ -339,6 +362,10 @@ /* GIO Interrupt Priority Clear Register */ +#define GIO_LVLCLR_PORT_SHIFT(p) ((p) << 3) +#define GIO_LVLCLR_PORT_MASK(p) (0xff << GIO_LVLCLR_PORT_SHIFT(p)) +# define GIO_LVLCLR_PORT_PIN(p,n) (1 << (GIO_LVLCLR_PORT_SHIFT(p) + (n))) + #define GIO_LVLCLR_GIOA_SHIFT (0) /* Bits 0-7: Interrupt low level select for pins GIOA[7:0] */ #define GIO_LVLCLR_GIOA_MASK (0xff << GIO_LVLCLR_GIOA_SHIFT) # define GIO_LVLCLR_GIOA_PIN(n) (1 << (GIO_LVLCLR_GIOA_SHIFT + (n))) @@ -354,6 +381,10 @@ /* GIO Interrupt Flag Register */ +#define GIO_FLG_PORT_SHIFT(p) ((p) << 3) +#define GIO_FLG_PORT_MASK(p) (0xff << GIO_FLG_PORT_SHIFT(p)) +# define GIO_FLG_PORT_PIN(p,n) (1 << (GIO_FLG_PORT_SHIFT(p) + (n))) + #define GIO_FLG_GIOA_SHIFT (0) /* Bits 0-7: Interrupt flag for pins GIOA[7:0] */ #define GIO_FLG_GIOA_MASK (0xff << GIO_FLG_GIOA_SHIFT) # define GIO_FLG_GIOA_PIN(n) (1 << (GIO_FLG_GIOA_SHIFT + (n))) @@ -369,46 +400,46 @@ /* GIO Offset 1/2 Register and GIO Emulation 1/2 Register */ -#define GIO_OFF_MASK (0x3f) /* Bits 0-5: GIO offset */ -# define GIO_OFF_NONE (0x00) /* No interrupt pending */ -# define GIO_OFF_GIOA0 (0x01) /* GIOA0 interrupt pending */ -# define GIO_OFF_GIOA1 (0x02) /* GIOA1 interrupt pending */ -# define GIO_OFF_GIOA2 (0x03) /* GIOA2 interrupt pending */ -# define GIO_OFF_GIOA3 (0x04) /* GIOA3 interrupt pending */ -# define GIO_OFF_GIOA4 (0x05) /* GIOA4 interrupt pending */ -# define GIO_OFF_GIOA5 (0x06) /* GIOA5 interrupt pending */ -# define GIO_OFF_GIOA6 (0x07) /* GIOA6 interrupt pending */ -# define GIO_OFF_GIOA7 (0x08) /* GIOA7 interrupt pending */ -# define GIO_OFF_GIOB0 (0x09) /* GIOB0 interrupt pending */ -# define GIO_OFF_GIOB1 (0x0a) /* GIOB1 interrupt pending */ -# define GIO_OFF_GIOB2 (0x0b) /* GIOB2 interrupt pending */ -# define GIO_OFF_GIOB3 (0x0c) /* GIOB3 interrupt pending */ -# define GIO_OFF_GIOB4 (0x0d) /* GIOB4 interrupt pending */ -# define GIO_OFF_GIOB5 (0x0e) /* GIOB5 interrupt pending */ -# define GIO_OFF_GIOB6 (0x0f) /* GIOB6 interrupt pending */ -# define GIO_OFF_GIOB7 (0x10) /* GIOB7 interrupt pending */ -# define GIO_OFF_GIOC0 (0x11) /* GIOC0 interrupt pending */ -# define GIO_OFF_GIOC1 (0x12) /* GIOC1 interrupt pending */ -# define GIO_OFF_GIOC2 (0x13) /* GIOC2 interrupt pending */ -# define GIO_OFF_GIOC3 (0x14) /* GIOC3 interrupt pending */ -# define GIO_OFF_GIOC4 (0x15) /* GIOC4 interrupt pending */ -# define GIO_OFF_GIOC5 (0x16) /* GIOC5 interrupt pending */ -# define GIO_OFF_GIOC6 (0x17) /* GIOC6 interrupt pending */ -# define GIO_OFF_GIOC7 (0x18) /* GIOC7 interrupt pending */ -# define GIO_OFF_GIOD0 (0x19) /* GIOD0 interrupt pending */ -# define GIO_OFF_GIOD1 (0x1a) /* GIOD1 interrupt pending */ -# define GIO_OFF_GIOD2 (0x1b) /* GIOD2 interrupt pending */ -# define GIO_OFF_GIOD3 (0x1c) /* GIOD3 interrupt pending */ -# define GIO_OFF_GIOD4 (0x1d) /* GIOD4 interrupt pending */ -# define GIO_OFF_GIOD5 (0x1e) /* GIOD5 interrupt pending */ -# define GIO_OFF_GIOD6 (0x1f) /* GIOD6 interrupt pending */ -# define GIO_OFF_GIOD7 (0x20) /* GIOD7 interrupt pending */ +#define GIO_OFF_MASK (0x3f) /* Bits 0-5: GIO offset */ +# define GIO_OFF_NONE (0x00) /* No interrupt pending */ +# define GIO_OFF_GIOA0 (0x01) /* GIOA0 interrupt pending */ +# define GIO_OFF_GIOA1 (0x02) /* GIOA1 interrupt pending */ +# define GIO_OFF_GIOA2 (0x03) /* GIOA2 interrupt pending */ +# define GIO_OFF_GIOA3 (0x04) /* GIOA3 interrupt pending */ +# define GIO_OFF_GIOA4 (0x05) /* GIOA4 interrupt pending */ +# define GIO_OFF_GIOA5 (0x06) /* GIOA5 interrupt pending */ +# define GIO_OFF_GIOA6 (0x07) /* GIOA6 interrupt pending */ +# define GIO_OFF_GIOA7 (0x08) /* GIOA7 interrupt pending */ +# define GIO_OFF_GIOB0 (0x09) /* GIOB0 interrupt pending */ +# define GIO_OFF_GIOB1 (0x0a) /* GIOB1 interrupt pending */ +# define GIO_OFF_GIOB2 (0x0b) /* GIOB2 interrupt pending */ +# define GIO_OFF_GIOB3 (0x0c) /* GIOB3 interrupt pending */ +# define GIO_OFF_GIOB4 (0x0d) /* GIOB4 interrupt pending */ +# define GIO_OFF_GIOB5 (0x0e) /* GIOB5 interrupt pending */ +# define GIO_OFF_GIOB6 (0x0f) /* GIOB6 interrupt pending */ +# define GIO_OFF_GIOB7 (0x10) /* GIOB7 interrupt pending */ +# define GIO_OFF_GIOC0 (0x11) /* GIOC0 interrupt pending */ +# define GIO_OFF_GIOC1 (0x12) /* GIOC1 interrupt pending */ +# define GIO_OFF_GIOC2 (0x13) /* GIOC2 interrupt pending */ +# define GIO_OFF_GIOC3 (0x14) /* GIOC3 interrupt pending */ +# define GIO_OFF_GIOC4 (0x15) /* GIOC4 interrupt pending */ +# define GIO_OFF_GIOC5 (0x16) /* GIOC5 interrupt pending */ +# define GIO_OFF_GIOC6 (0x17) /* GIOC6 interrupt pending */ +# define GIO_OFF_GIOC7 (0x18) /* GIOC7 interrupt pending */ +# define GIO_OFF_GIOD0 (0x19) /* GIOD0 interrupt pending */ +# define GIO_OFF_GIOD1 (0x1a) /* GIOD1 interrupt pending */ +# define GIO_OFF_GIOD2 (0x1b) /* GIOD2 interrupt pending */ +# define GIO_OFF_GIOD3 (0x1c) /* GIOD3 interrupt pending */ +# define GIO_OFF_GIOD4 (0x1d) /* GIOD4 interrupt pending */ +# define GIO_OFF_GIOD5 (0x1e) /* GIOD5 interrupt pending */ +# define GIO_OFF_GIOD6 (0x1f) /* GIOD6 interrupt pending */ +# define GIO_OFF_GIOD7 (0x20) /* GIOD7 interrupt pending */ /* GIO Data Direction Register, GIO Data Input Register, GIO Data Output Register, * GIO Data Set Register, GIO Data Clear Register, GIO Open Drain Register, * GIO Pull Disable Register, and GIO Pull Select Register */ -#define GIO_PIN(n) (1 << (n)) /* Bit n: Corresponds to pin n */ +#define GIO_PIN(n) (1 << (n)) /* Bit n: Corresponds to pin n */ #endif /* __ARCH_ARM_SRC_TMS570_CHIP_TMS570_GIO_H */ diff --git a/arch/arm/src/tms570/tms570_boot.c b/arch/arm/src/tms570/tms570_boot.c index 3130ed122b..8b1cfb2cf8 100644 --- a/arch/arm/src/tms570/tms570_boot.c +++ b/arch/arm/src/tms570/tms570_boot.c @@ -63,6 +63,7 @@ #include "chip/tms570_sys.h" #include "chip/tms570_esm.h" #include "tms570_clockconfig.h" +#include "tms570_gio.h" #include "tms570_boot.h" /**************************************************************************** @@ -316,6 +317,10 @@ void arm_boot(void) arm_data_initialize(); #endif + /* Initialize GIO for use by board initialization logic */ + + tms570_gio_initialize(); + /* Perform board-specific initialization, This must include: * * - Initialization of board-specific memory resources (e.g., SDRAM) diff --git a/arch/arm/src/tms570/tms570_gio.c b/arch/arm/src/tms570/tms570_gio.c new file mode 100644 index 0000000000..e84cbdde3e --- /dev/null +++ b/arch/arm/src/tms570/tms570_gio.c @@ -0,0 +1,330 @@ +/**************************************************************************** + * arch/arm/src/tms570/tms570_gio.c + * + * Copyright (C) 2015 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_internal.h" +#include "up_arch.h" + +#include "chip/tms570_gio.h" +#include "tms570_gio.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_GPIO +static const char g_portchar[TMS570_NPORTS] = +{ + 'A' +#if TMS570_NPORTS > 1 + , 'B' +#endif +#if TMS570_NPORTS > 2 + , 'C' +#endif +#if TMS570_NPORTS > 3 + , 'D' +#endif +#if TMS570_NPORTS > 4 + , 'E' +#endif +#if TMS570_NPORTS > 5 + , 'F' +#endif +#if TMS570_NPORTS > 6 + , 'G' +#endif +#if TMS570_NPORTS > 7 + , 'H' +#endif +}; +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tms570_gio_initialize + * + * Description: + * Take the GIO block out of reset and assure that it is ready for use. + * + ****************************************************************************/ + +int tms570_gio_initialize(void) +{ + /* Take the GIO block out of reset */ + + putreg32(GIO_GCR0_RESET, TMS570_GIO_GCR0); + + /* Disable all pin interrupts on the pin. Make sure they are all level 0. */ + + putreg32(0xffffffff, TMS570_GIO_ENACLR); + putreg32(0xffffffff, TMS570_GIO_LVLCLR); + return OK; +} + +/**************************************************************************** + * Name: tms570_configgio + * + * Description: + * Configure a GIO pin based on bit-encoded description of the pin. + * + ****************************************************************************/ + +int tms570_configgio(gio_pinset_t cfgset) +{ + uint32_t port = tms570_gio_port(cfgset); + uintptr_t base = tms570_gio_base(cfgset); + uint32_t pin = tms570_gio_pin(cfgset); + uint32_t pinmask = tms570_gio_pinmask(cfgset); + uint32_t regval; + irqstate_t flags; + + /* Disable interrupts to prohibit re-entrance. */ + + flags = irqsave(); + + /* Force the pin to be an input for now */ + + regval = getreg32(base + TMS570_GIO_DIR_OFFSET); + regval &= ~pinmask; + putreg32(regval, base + TMS570_GIO_DIR_OFFSET); + + /* Disable interrupts on the pin. Make sure this is a level 0 pin. */ + + putreg32(GIO_ENACLR_PORT_PIN(port, pin), TMS570_GIO_ENACLR); + putreg32(GIO_LVLCLR_PORT_PIN(port, pin), TMS570_GIO_LVLCLR); + + /* Setup settings common to both input and output pins */ + /* Enable/disable the pull-up/down as requested */ + + switch (cfgset & GIO_CFG_MASK) + { + case GIO_CFG_DEFAULT: /* Default, no attribute */ + default: + { + /* Disable pull functionality */ + + regval = getreg32(base + TMS570_GIO_PULDIS_OFFSET); + regval &= ~pinmask; + putreg32(regval, base + TMS570_GIO_PULDIS_OFFSET); + } + break; + + case GIO_CFG_PULLUP: /* Internal pull-up */ + { + /* Select pull-up */ + + regval = getreg32(base + TMS570_GIO_PSL_OFFSET); + regval |= pinmask; + putreg32(regval, base + TMS570_GIO_PSL_OFFSET); + + /* Enable pull functionality */ + + regval = getreg32(base + TMS570_GIO_PULDIS_OFFSET); + regval |= pinmask; + putreg32(regval, base + TMS570_GIO_PULDIS_OFFSET); + } + break; + + case GIO_CFG_PULLDOWN: /* Internal pull-down */ + { + /* Select pull-down */ + + regval = getreg32(base + TMS570_GIO_PSL_OFFSET); + regval |= pinmask; + putreg32(regval, base + TMS570_GIO_PSL_OFFSET); + + /* Enable pull functionality */ + + regval = getreg32(base + TMS570_GIO_DIR_OFFSET); + regval |= pinmask; + putreg32(regval, base + TMS570_GIO_DIR_OFFSET); + } + break; + } + + /* Then do unique operations for an output pin */ + + if ((cfgset & GIO_MODE_MASK) == GIO_OUTPUT) + { + /* Enable the open drain driver if requested */ + + regval = getreg32(base + TMS570_GIO_PDR_OFFSET); + if ((cfgset & GIO_OPENDRAIN) != 0) + { + regval |= pinmask; + } + else + { + regval &= ~pinmask; + } + + putreg32(regval, base + TMS570_GIO_PDR_OFFSET); + + /* Set default output value */ + + if ((cfgset & GIO_OUTPUT_SET) != 0) + { + putreg32(pinmask, base + TMS570_GIO_DSET_OFFSET); + } + else + { + putreg32(pinmask, base + TMS570_GIO_DCLR_OFFSET); + } + + /* Finally, configure the pin as an output */ + + regval = getreg32(base + TMS570_GIO_DIR_OFFSET); + regval |= pinmask; + putreg32(regval, base + TMS570_GIO_DIR_OFFSET); + } + + irqrestore(flags); + return OK; +} + +/**************************************************************************** + * Name: tms570_giowrite + * + * Description: + * Write one or zero to the selected GIO pin + * + ****************************************************************************/ + +void tms570_giowrite(gio_pinset_t pinset, bool value) +{ + uintptr_t base = tms570_gio_base(pinset); + uint32_t pinmask = tms570_gio_pinmask(pinset); + + if (value) + { + putreg32(pinmask, base + TMS570_GIO_DSET_OFFSET); + } + else + { + putreg32(pinmask, base + TMS570_GIO_DCLR_OFFSET); + } +} + +/**************************************************************************** + * Name: tms570_gioread + * + * Description: + * Read one or zero from the selected GIO pin + * + ****************************************************************************/ + +bool tms570_gioread(gio_pinset_t pinset) +{ + uintptr_t base = tms570_gio_base(pinset); + uint32_t pinmask = tms570_gio_pinmask(pinset); + uint32_t regval; + + if ((pinset & GIO_MODE_MASK) == GIO_OUTPUT) + { + regval = getreg32(base + TMS570_GIO_DOUT_OFFSET); + } + else + { + regval = getreg32(base + TMS570_GIO_DIN_OFFSET); + } + + return (regval & pinmask) != 0; +} + +/************************************************************************************ + * Function: tms570_dumpgio + * + * Description: + * Dump all GIO registers associated with the base address of the provided pinset. + * + ************************************************************************************/ + +#ifdef CONFIG_DEBUG_GPIO +int tms570_dumpgio(uint32_t pinset, const char *msg) +{ + irqstate_t flags; + uintptr_t base; + unsigned int port; + + lldbg("GIO%c pinset: %08x base: %08x -- %s\n", + g_portchar[port], pinset, base, msg); + + /* Get the base address associated with the GIO port */ + + port = (pinset & GIO_PORT_MASK) >> GIO_PORT_SHIFT; + base = TMS570_GIO_PORTBASE(port); + + /* The following requires exclusive access to the GIO registers */ + + flags = irqsave(); + + /* Show global GIO registers */ + + lldbg(" GCR0: %08x INTDET: %08x POL: %08x ENA: %08x\n", + getreg32(TMS570_GIO_GCR0), getreg32(TMS570_GIO_INTDET), + getreg32(TMS570_GIO_POL), getreg32(TMS570_GIO_ENASET)); + lldbg(" LVL: %08x FLG: %08x EMU1: %08x EMU2: %08x\n", + getreg32(TMS570_GIO_LVLSET), getreg32(TMS570_GIO_FLG), + getreg32(TMS570_GIO_EMU1), getreg32(TMS570_GIO_EMU2)); + + /* Port specific registers */ + + lldbg(" DIR: %08x DIN: %08x DOUT: %08x PDR: %08x\n", + getreg32(base + TMS570_GIO_DIR_OFFSET), getreg32(base + TMS570_GIO_DIN_OFFSET), + getreg32(base + TMS570_GIO_DOUT_OFFSET), getreg32(base + TMS570_GIO_PDR_OFFSET)); + lldbg(" PULDIS: %08x PSL: %08x\n", + getreg32(base + TMS570_GIO_PULDIS_OFFSET), getreg32(base + TMS570_GIO_PSL_OFFSET)); + + irqrestore(flags); + return OK; +} +#endif diff --git a/arch/arm/src/tms570/tms570_gio.h b/arch/arm/src/tms570/tms570_gio.h index dadb759363..bc59e8b1e2 100644 --- a/arch/arm/src/tms570/tms570_gio.h +++ b/arch/arm/src/tms570/tms570_gio.h @@ -46,6 +46,8 @@ #include #include +#include "chip/tms570_gio.h" + /************************************************************************************ * Pre-processor Definitions ************************************************************************************/ @@ -54,7 +56,7 @@ /* 32-bit Encoding: * - * .... .... .... .... MCCC .IIV PPP. .BBB + * .... .... .... .... M.CC IIOV PPP. .BBB */ /* Input/Output mode: @@ -70,28 +72,34 @@ /* These bits set the configuration of the pin: * NOTE: No definitions for parallel capture mode * - * .... .... .... .... .CCC .... .... .... + * .... .... .... .... ..CC .... .... .... */ #define GIO_CFG_SHIFT (12) /* Bits 12-14: GIO configuration bits */ -#define GIO_CFG_MASK (7 << GIO_CFG_SHIFT) +#define GIO_CFG_MASK (3 << GIO_CFG_SHIFT) # define GIO_CFG_DEFAULT (0 << GIO_CFG_SHIFT) /* Default, no attribute */ # define GIO_CFG_PULLUP (1 << GIO_CFG_SHIFT) /* Bit 16: Internal pull-up */ # define GIO_CFG_PULLDOWN (2 << GIO_CFG_SHIFT) /* Bit 17: Internal pull-down */ -# define GIO_CFG_OPENDRAIN (4 << GIO_CFG_SHIFT) /* Bit 19: Open drain */ /* Interrupt modes: * - * .... .... .... .... .... .II. .... .... + * .... .... .... .... .... II.. .... .... */ -#define GIO_INT_SHIFT (9) /* Bits 9-10: GIO interrupt bits */ +#define GIO_INT_SHIFT (10) /* Bits 10-11: GIO interrupt bits */ #define GIO_INT_MASK (3 << GIO_INT_SHIFT) # define GIO_INT_NONE (0 << GIO_INT_SHIFT) # define GIO_INT_RISING (1 << GIO_INT_SHIFT) # define GIO_INT_FALLING (2 << GIO_INT_SHIFT) # define GIO_INT_BOTHEDGES (3 << GIO_INT_SHIFT) +/* If the pin is an GIO output, then this selects the open drain output + * + * .... .... .... .... .... ..O. .... .... + */ + +#define GIO_OPENDRAIN (1 << 9) /* Bit 9: Open drain mode */ + /* If the pin is an GIO output, then this identifies the initial output value: * * .... .... .... .... .... ...V .... .... @@ -170,7 +178,7 @@ extern "C" static inline uintptr_t tms570_gio_base(gio_pinset_t cfgset) { int port = (cfgset & GIO_PORT_MASK) >> GIO_PORT_SHIFT; - return TMS570_GIO_PORTBASE(n); + return TMS570_GIO_PORTBASE(port); } /**************************************************************************** @@ -216,8 +224,18 @@ static inline int tms570_gio_pinmask(gio_pinset_t cfgset) * Public Function Prototypes ************************************************************************************/ +/**************************************************************************** + * Name: tms570_gio_initialize + * + * Description: + * Take the GIO block out of reset and assure that it is ready for use. + * + ****************************************************************************/ + +int tms570_gio_initialize(void); + /************************************************************************************ - * Name: tms570_gioirqinitialize + * Name: tms570_gioirq_initialize * * Description: * Initialize logic to support a second level of interrupt decoding for GIO pins. @@ -225,9 +243,9 @@ static inline int tms570_gio_pinmask(gio_pinset_t cfgset) ************************************************************************************/ #ifdef CONFIG_TMS570_GIO_IRQ -void tms570_gioirqinitialize(void); +void tms570_gioirq_initialize(void); #else -# define tms570_gioirqinitialize() +# define tms570_gioirq_initialize() #endif /************************************************************************************ @@ -310,7 +328,7 @@ void tms570_gioirqdisable(int irq); * ************************************************************************************/ -#ifdef CONFIG_DEBUG_GIO +#ifdef CONFIG_DEBUG_GPIO int tms570_dumpgio(uint32_t pinset, const char *msg); #else # define tms570_dumpgio(p,m) diff --git a/arch/arm/src/tms570/tms570_gioirq.c b/arch/arm/src/tms570/tms570_gioirq.c new file mode 100644 index 0000000000..1da8d21d1f --- /dev/null +++ b/arch/arm/src/tms570/tms570_gioirq.c @@ -0,0 +1,256 @@ +/**************************************************************************** + * arch/arm/src/tms570/tms570_gioirq.c + * + * Copyright (C) 2015 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 +#include + +#include "up_arch.h" +#include "up_internal.h" + +#include "tms570_gio.h" +#include "chip/tms570_gio.h" + +#ifdef CONFIG_TMS570_GIO_IRQ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tms570_gio_interrupt + * + * Description: + * Receive GIO interrupts + * + ****************************************************************************/ + +static int tms3570_gio_interrupt(int irq, void *context) +{ + uint32_t off1; + int irq2; + + /* Loop until all pending GIO interrupts have been processed */ + + while ((off1 = getreg32(TMS570_GIO_OFF1)) != GIO_OFF_NONE) + { + /* Convert the offset value to the second-level IRQ number */ + + irq2 = off1 + TMS570_IRQ_GIOA0 - 1; + + /* And dispatch the second-level GIO IRQ */ + + irq_dispatch(irq2, context); + } + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tms570_gioirqinitialize + * + * Description: + * Initialize logic to support a second level of interrupt decoding for + * GIO pins. + * + ****************************************************************************/ + +void tms570_gioirqinitialize(void) +{ + /* Disable all pin interrupts on the pin. Make sure they are all level 0. */ + + putreg32(0xffffffff, TMS570_GIO_ENACLR); + putreg32(0xffffffff, TMS570_GIO_LVLCLR); + + /* Attach and enable the GIO level 0 interrupt */ + + DEBUGVERIFY(irq_attach(TMS570_REQ_GIO_0, tms3570_gio_interrupt)); + up_enable_irq(TMS570_REQ_GIO_0); +} + +/************************************************************************************ + * Name: tms570_gioirq + * + * Description: + * Configure an interrupt for the specified GIO pin. + * + ************************************************************************************/ + +void tms570_gioirq(gio_pinset_t pinset) +{ + uint32_t port = tms570_gio_port(pinset); + uint32_t pin = tms570_gio_pin(pinset); + irqstate_t flags; + uint32_t regval; + + /* Start with the pin interrupts disabled. Make sure that level 0 is selected. */ + + putreg32(GIO_ENACLR_PORT_PIN(port, pin), TMS570_GIO_ENACLR); + putreg32(GIO_LVLCLR_PORT_PIN(port, pin), TMS570_GIO_LVLCLR); + + /* Make sure that the pin is configured as an input and that interrupts can e + * supported on this port. + */ + + if ((pinset & GIO_MODE_MASK) == GIO_INPUT && port < TMS570_NIRQPORTS) + { + flags = irqsave(); + switch (pinset & GIO_INT_MASK) + { + case GIO_INT_NONE: + default: + break; + + case GIO_INT_RISING: + { + /* Enable rising edge detectioni */ + + regval = getreg32(TMS570_GIO_POL); + regval |= GIO_POL_PORT_PIN(port, pin); + putreg32(regval, TMS570_GIO_POL); + + /* Disable both rising and falling edge detection */ + + regval = getreg32(TMS570_GIO_INTDET); + regval &= ~GIO_INTDET_PORT_PIN(port, pin); + putreg32(regval, TMS570_GIO_INTDET); + } + break; + + case GIO_INT_FALLING: + { + /* Enable falling edge detectioni */ + + regval = getreg32(TMS570_GIO_POL); + regval &= ~GIO_POL_PORT_PIN(port, pin); + putreg32(regval, TMS570_GIO_POL); + + /* Disable both rising and falling edge detection */ + + regval = getreg32(TMS570_GIO_INTDET); + regval &= ~GIO_INTDET_PORT_PIN(port, pin); + putreg32(regval, TMS570_GIO_INTDET); + } + break; + + case GIO_INT_BOTHEDGES: + { + /* Enable both rising and falling edge detection */ + + regval = getreg32(TMS570_GIO_INTDET); + regval |= GIO_INTDET_PORT_PIN(port, pin); + putreg32(regval, TMS570_GIO_INTDET); + } + break; + } + + irqrestore(flags); + } +} + +/************************************************************************************ + * Name: tms570_gioirqenable + * + * Description: + * Enable the interrupt for specified GIO IRQ + * + ************************************************************************************/ + +void tms570_gioirqenable(int irq) +{ + int offset; + int port; + int pin; + + offset = irq - TMS570_IRQ_GIOA0; + if (offset < TMS570_NGIO_IRQS) + { + /* Convert the offset IRQ number to a port and pin number */ + + pin = offset & 7; + port = offset >> 3; + + /* Enable this pin interrupt */ + + putreg32(GIO_ENACLR_PORT_PIN(port, pin), TMS570_GIO_ENASET); + } +} + +/************************************************************************************ + * Name: tms570_gioirqdisable + * + * Description: + * Disable the interrupt for specified GIO IRQ + * + ************************************************************************************/ + +void tms570_gioirqdisable(int irq) +{ + int offset; + int port; + int pin; + + offset = irq - TMS570_IRQ_GIOA0; + if (offset < TMS570_NGIO_IRQS) + { + /* Convert the offset IRQ number to a port and pin number */ + + pin = offset & 7; + port = offset >> 3; + + /* Enable this pin interrupt */ + + putreg32(GIO_ENACLR_PORT_PIN(port, pin), TMS570_GIO_ENACLR); + } +} + +#endif /* CONFIG_TMS570_GIO_IRQ */ diff --git a/arch/arm/src/tms570/tms570_irq.c b/arch/arm/src/tms570/tms570_irq.c index 847eda8725..3a6fdb295d 100644 --- a/arch/arm/src/tms570/tms570_irq.c +++ b/arch/arm/src/tms570/tms570_irq.c @@ -178,7 +178,7 @@ void up_irqinitialize(void) * GIO pins. */ - tms570_gioirqinitialize(); + tms570_gioirq_initialize(); #endif /* And finally, enable interrupts */