arch/arm/src/max326xx/max32660: Add GPIO driver and GPIO interrupt support.

This commit is contained in:
Gregory Nutt
2018-11-18 11:22:51 -06:00
parent 74cd8a53d5
commit 169198ff38
7 changed files with 960 additions and 12 deletions
+14 -1
View File
@@ -104,7 +104,20 @@
/* Number of external interrupts and total number of vectors */
#define MAX326_IRQ_NEXTINT 50
#define NR_IRQS (MAX326_IRQ_EXTINT + MAX326_IRQ_NEXTINT)
#define MAX326_IRQ_NVECTORS (MAX326_IRQ_EXTINT + MAX326_IRQ_NEXTINT)
/* If GPIO pin interrupts are used then there is a second level of interrupt decode */
#ifdef CONFIG_MAX326_GPIOIRQ
#warning Missing logic
#else
# define MAX326_IRQ_NPININT 0
#endif
/* Total number of interrupts handled by the OS */
#define NR_IRQS (MAX326_IRQ_NVECTORS + MAX326_IRQ_NPININT)
/************************************************************************************************
* Public Types
+33 -2
View File
@@ -86,10 +86,41 @@
/* 46-48 Reserved */
#define MAX326_IRQ_SPIS (MAX326_IRQ_EXTINT + 49) /* 49 SPI Slave */
/* Number of external interrupts and total number of vectors */
/* Number of external interrupts and number of true interrupt vectors */
#define MAX326_IRQ_NEXTINT 50
#define NR_IRQS (MAX326_IRQ_EXTINT + MAX326_IRQ_NEXTINT)
#define MAX326_IRQ_NVECTORS (MAX326_IRQ_EXTINT + MAX326_IRQ_NEXTINT)
/* If GPIO pin interrupts are used then there is a second level of interrupt decode */
#ifdef CONFIG_MAX326_GPIOIRQ
/* Up to 14 pins are available as interrupt sources, depending on the MAX32660 package */
# define MAX326_IRQ_P0_0 (MAX326_IRQ_NEXTINT + 0)
# define MAX326_IRQ_P0_1 (MAX326_IRQ_NEXTINT + 1)
# define MAX326_IRQ_P0_2 (MAX326_IRQ_NEXTINT + 2)
# define MAX326_IRQ_P0_3 (MAX326_IRQ_NEXTINT + 3)
# define MAX326_IRQ_P0_4 (MAX326_IRQ_NEXTINT + 4)
# define MAX326_IRQ_P0_5 (MAX326_IRQ_NEXTINT + 5)
# define MAX326_IRQ_P0_6 (MAX326_IRQ_NEXTINT + 6)
# define MAX326_IRQ_P0_7 (MAX326_IRQ_NEXTINT + 7)
# define MAX326_IRQ_P0_8 (MAX326_IRQ_NEXTINT + 8)
# define MAX326_IRQ_P0_9 (MAX326_IRQ_NEXTINT + 9)
# define MAX326_IRQ_P0_10 (MAX326_IRQ_NEXTINT + 10)
# define MAX326_IRQ_P0_11 (MAX326_IRQ_NEXTINT + 11)
# define MAX326_IRQ_P0_12 (MAX326_IRQ_NEXTINT + 12)
# define MAX326_IRQ_P0_13 (MAX326_IRQ_NEXTINT + 13)
# define MAX326_IRQ_GPIO1ST MAX326_IRQ_P0_0
# define MAX326_IRQ_GPIOLAST MAX326_IRQ_P0_13
# define MAX326_IRQ_NPININT 14
#else
# define MAX326_IRQ_NPININT 0
#endif
/* Total number of interrupts handled by the OS */
#define NR_IRQS (MAX326_IRQ_NVECTORS + MAX326_IRQ_NPININT)
/************************************************************************************************
* Public Types
+26 -1
View File
@@ -439,6 +439,15 @@ void up_disable_irq(int irq)
uint32_t regval;
uint32_t bit;
#ifdef CONFIG_MAX326_GPIOIRQ
/* Handle "fake" GPIO irq */
if (irq >= MAX326_IRQ_GPIO1ST && irq <= MAX326_IRQ_GPIOLAST)
{
max326_gpio_irqdisable(irq);
}
else
#endif
if (max326_irqinfo(irq, &regaddr, &bit, NVIC_CLRENA_OFFSET) == 0)
{
/* Modify the appropriate bit in the register to disable the interrupt.
@@ -476,6 +485,15 @@ void up_enable_irq(int irq)
uint32_t regval;
uint32_t bit;
#ifdef CONFIG_MAX326_GPIOIRQ
/* Handle "fake" GPIO irq */
if (irq >= MAX326_IRQ_GPIO1ST && irq <= MAX326_IRQ_GPIOLAST)
{
max326_gpio_irqensable(irq);
}
else
#endif
if (max326_irqinfo(irq, &regaddr, &bit, NVIC_ENA_OFFSET) == 0)
{
/* Modify the appropriate bit in the register to enable the interrupt.
@@ -542,13 +560,20 @@ int up_prioritize_irq(int irq, int priority)
regaddr = NVIC_SYSH_PRIORITY(irq);
irq -= 4;
}
else
else if (irq < MAX326_IRQ_NVECTORS)
{
/* NVIC_IRQ_PRIORITY() maps {0..} to one of many priority registers */
irq -= MAX326_IRQ_EXTINT;
regaddr = NVIC_IRQ_PRIORITY(irq);
}
else
{
#ifndef CONFIG_MAX326_GPIOIRQ
DEBUGPANIC();
#endif
return;
}
regval = getreg32(regaddr);
shift = ((irq & 3) << 3);
File diff suppressed because it is too large Load Diff
@@ -69,10 +69,9 @@
#define GPIO_FUNC_MASK (15 << GPIO_FUNC_SHIFT)
# define GPIO_INPUT (0 << GPIO_FUNC_SHIFT) /* 0000 GPIO input pin */
# define GPIO_OUTPUT (1 << GPIO_FUNC_SHIFT) /* 0001 GPIO output pin */
# define GPIO_ALT0 (4 << GPIO_FUNC_SHIFT) /* 0100 GPIO Alternate function 0 */
# define GPIO_ALT1 (5 << GPIO_FUNC_SHIFT) /* 0101 GPIO Alternate function 1 */
# define GPIO_ALT2 (6 << GPIO_FUNC_SHIFT) /* 0110 GPIO Alternate function 2 */
# define GPIO_ALT3 (7 << GPIO_FUNC_SHIFT) /* 0111 GPIO Alternate function 3 */
# define GPIO_ALT1 (5 << GPIO_FUNC_SHIFT) /* 0100 GPIO Alternate function 1 */
# define GPIO_ALT2 (6 << GPIO_FUNC_SHIFT) /* 0101 GPIO Alternate function 2 */
# define GPIO_ALT3 (7 << GPIO_FUNC_SHIFT) /* 0110 GPIO Alternate function 3 */
# define GPIO_INTFE (9 << GPIO_FUNC_SHIFT) /* 1001 GPIO interrupt falling edge */
# define GPIO_INTRE (10 << GPIO_FUNC_SHIFT) /* 1010 GPIO interrupt rising edge */
# define GPIO_INTBOTH (11 << GPIO_FUNC_SHIFT) /* 1011 GPIO interrupt both edges */
@@ -94,7 +93,7 @@
#define GPIO_IS_GPIO(ps) (((uint16_t)(ps) & GPIO_GPIO_MASK) == GPIO_GPIO_CODE)
#define GPIO_IS_ALT(ps) (((uint16_t)(ps) & GPIO_ALT_MASK) == GPIO_ALT_CODE)
#define GPIO_IS_INTR(ps) (((uint16_t)(ps) & GPIO_ALT_MASK) == GPIO_ALT_CODE)
#define GPIO_IS_INTR(ps) (((uint16_t)(ps) & GPIO_ALT_MASK) == GPIO_INTR_CODE)
#define GPIO_IS_INTEDGE(ps) (((uint16_t)(ps) & GPIO_INTEDGE_MASK) == GPIO_INTEDGE_CODE)
#define GPIO_IS_INTLVL(ps) (((uint16_t)(ps) & GPIO_INTLVL_MASK) == GPIO_INTLVL_CODE)
@@ -180,6 +179,9 @@
# define GPIO_PIN12 (12 << GPIO_PIN_SHIFT)
# define GPIO_PIN13 (13 << GPIO_PIN_SHIFT)
# define GPIO_PINMIN 0
# define GPIO_PINMAX 13
/************************************************************************************
* Public Types
************************************************************************************/
@@ -0,0 +1,226 @@
/****************************************************************************
* arch/arm/src/max32660/max326_gpioirq.c
*
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* 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 <nuttx/config.h>
#include <debug.h>
#include <nuttx/irq.h>
#include "up_arch.h"
#include "max326_gpio.h"
#ifdef CONFIG_MAX326_GPIOIRQ
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: max326_gpio_irqinitialize
*
* Description:
* Initialize logic to support interrupting GPIO pins. This function is
* called by the OS initialization logic and is not a user interface.
*
* Assumptions:
* Called early in the boot-up sequence
*
****************************************************************************/
void max326_gpio_irqinitialize(void);
{
/* Attach the GPIO0 interrupt handler and enable interrupts */
DEBUGVERIFY(irq_attach, MAX326_IRQ_GPIO0, NULL);
up_enable_irq(MAX326_IRQ_GPIO0);
}
/****************************************************************************
* Name: max326_gpio_irqconfig
*
* Description:
* Configure a pin for interrupt operation. This function should not be
* called directory but, rather, indirectly through max326_gpio_config().
*
* Assumptions:
* - The pin interrupt has been disabled and all interrupt related bits
* have been set to zero by max436_gpio_config().
* - We are called in a critical section.
*
****************************************************************************/
void max326_gpio_irqconfig(max326_pinset_t cfgset)
{
unsigned int pin;
uint32_t pinmask;
uint32_t intmode;
uint32_t intpol;
uint32_t intdual;
uint32_t regval;
pin = (cfgset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT;
DEBUGASSERT(pin <= GPIO_PINMAX);
pinmask = 1 << pin;
intmode = 0;
intpol = 0;
intdual = 0;
switch (cfgset & GPIO_FUNC_MASK)
{
default:
case GPIO_INPUT:
case GPIO_OUTPUT:
case GPIO_ALT1:
case GPIO_ALT2:
case GPIO_ALT3:
DEBUGPANIC();
return;
case GPIO_INTFE: /* Edge triggered, falling edge */
intmode = pinmask; /* Edge triggered */
break;
case GPIO_INTRE: /* Edge triggered, rising edge */
intmode = pinmask; /* Edge triggered */
intpol = pinmask; /* Rising edge */
break;
case GPIO_INTBOTH: /* Edge triggered, both edges */
intmode = pinmask; /* Edge triggered */
intdual = pinmask; /* Both edges */
break;
case GPIO_INTLOW: /* Level triggered, low level */
break;
case GPIO_INTHIGH: /* Level triggered, high level */
intpol = pinmask; /* High level */
break;
}
/* Configure the interrupt */
regval = getreg32(MAX326_GPIO0_INTMODE);
regval &= ~pinmask;
regval |= intmode;
putreg32(regval, MAX326_GPIO0_INTMODE)
regval = getreg32(MAX326_GPIO0_INTPOL);
regval &= ~pinmask;
regval |= intpol;
putreg32(regval, MAX326_GPIO0_INTPOL)
regval = getreg32(MAX326_GPIO0_INTDUALEDGE);
regval &= ~pinmask;
regval |= intdual;
putreg32(regval, MAX326_GPIO0_INTDUALEDGE)
}
/************************************************************************************
* Name: max326_gpio_irqdisable
*
* Description:
* Disable a GPIO pin interrupt. This function should not be called directly but,
* rather through up_disable_irq();
*
* Assumptions:
* We are in a critical section.
*
************************************************************************************/
void max326_gpio_irqdisable(int irq)
{
unsigned int pin;
uint32_t pinmask;
uint32_t regval;
irqset_t flags;
pin = (cfgset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT;
DEBUGASSERT(pin <= GPIO_PINMAX);
pinmask = 1 << pin;
/* Modification of registers must be atomic */
flags = spin_lock_irqsave();
regval = getreg32(MAX326_GPIO0_INTEN);
regval &= ~pinmask;
putreg32(regval, MAX326_GPIO0_INTEN)
spin_unlock_restore(flags);
}
/************************************************************************************
* Name: max326_gpio_irqenable
*
* Description:
* Enable a GPIO pin interrupt. This function should not be called directly but,
* rather through up_enable_irq();
*
* Assumptions:
* We are in a critical section.
*
************************************************************************************/
void max326_gpio_irqenable(int irq)
{
unsigned int pin;
uint32_t pinmask;
uint32_t regval;
irqset_t flags;
pin = (cfgset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT;
DEBUGASSERT(pin <= GPIO_PINMAX);
pinmask = 1 << pin;
/* Modification of registers must be atomic */
flags = spin_lock_irqsave();
regval = getreg32(MAX326_GPIO0_INTEN);
regval |= pinmask;
putreg32(regval, MAX326_GPIO0_INTEN)
spin_unlock_restore(flags);
}
#endif /* CONFIG_MAX326_GPIOIRQ */
+55 -3
View File
@@ -86,12 +86,13 @@ extern "C"
* Initialize logic to support interrupting GPIO pins. This function is called by
* the OS initialization logic and is not a user interface.
*
* Assumptions:
* Called early in the boot-up sequence
*
************************************************************************************/
#ifdef CONFIG_MAX326_GPIOIRQ
void max326_gpio_irqinitialize(void);
#else
# define max326_gpio_irqinitialize()
#endif
/************************************************************************************
@@ -100,10 +101,28 @@ void max326_gpio_irqinitialize(void);
* Description:
* Configure a GPIO pin based on bit-encoded description of the pin.
*
* Assumptions:
* - The pin interrupt has been disabled and all interrupt related bits
* have been set to zero by max436_gpio_config().
* - We are called in a critical section.
*
************************************************************************************/
int max326_gpio_config(max326_pinset_t cfgset);
/************************************************************************************
* Name: max326_gpio_irqconfig
*
* Description:
* Configure a pin for interrupt operation. This function should not be called
* directory but, rather, indirectly through max326_gpio_config().
*
************************************************************************************/
#ifdef CONFIG_MAX326_GPIOIRQ
void max326_gpio_irqconfig(max326_pinset_t cfgset);
#endif
/************************************************************************************
* Name: max326_gpio_write
*
@@ -124,11 +143,44 @@ void max326_gpio_write(max326_pinset_t pinset, bool value);
bool max326_gpio_read(max326_pinset_t pinset);
/************************************************************************************
* Name: max326_gpio_irqdisable
*
* Description:
* Disable a GPIO pin interrupt. This function should not be called directly but,
* rather through up_disable_irq();
*
* Assumptions:
* We are in a critical section.
*
************************************************************************************/
#ifdef CONFIG_MAX326_GPIOIRQ
void max326_gpio_irqdisable(int irq);
#endif
/************************************************************************************
* Name: max326_gpio_irqenable
*
* Description:
* Enable a GPIO pin interrupt. This function should not be called directly but,
* rather through up_enable_irq();
*
* Assumptions:
* We are in a critical section.
*
************************************************************************************/
#ifdef CONFIG_MAX326_GPIOIRQ
void max326_gpio_irqenable(int irq);
#endif
/************************************************************************************
* Function: max326_gpio_dump
*
* Description:
* Dump all GPIO registers associated with the base address of the provided pinset.
* Decode and dump all GPIO registers associated with the port and pin
* numbers in the provided pinset.
*
************************************************************************************/