summaryrefslogtreecommitdiff
path: root/nuttx/arch/arm/src/sam34/sam_gpio.c
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2013-06-02 13:57:22 -0600
committerGregory Nutt <gnutt@nuttx.org>2013-06-02 13:57:22 -0600
commit3d0cc6467f1ce5a998aca982ccbd32d8c886e1b1 (patch)
treefa9f3e4347deba93f0fb4c43c543492d37ab66ac /nuttx/arch/arm/src/sam34/sam_gpio.c
parent0baf7136f9db7b14d5ed01cf753a86d0d38972b5 (diff)
downloadpx4-nuttx-3d0cc6467f1ce5a998aca982ccbd32d8c886e1b1.tar.gz
px4-nuttx-3d0cc6467f1ce5a998aca982ccbd32d8c886e1b1.tar.bz2
px4-nuttx-3d0cc6467f1ce5a998aca982ccbd32d8c886e1b1.zip
Rename sam3u/ architecture directories to sam34/ to include the SAM4L
Diffstat (limited to 'nuttx/arch/arm/src/sam34/sam_gpio.c')
-rw-r--r--nuttx/arch/arm/src/sam34/sam_gpio.c394
1 files changed, 394 insertions, 0 deletions
diff --git a/nuttx/arch/arm/src/sam34/sam_gpio.c b/nuttx/arch/arm/src/sam34/sam_gpio.c
new file mode 100644
index 000000000..123c3d4b9
--- /dev/null
+++ b/nuttx/arch/arm/src/sam34/sam_gpio.c
@@ -0,0 +1,394 @@
+/****************************************************************************
+ * arch/arm/src/sam34/sam_gpio.c
+ *
+ * Copyright (C) 2010, 2013 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 <stdint.h>
+#include <time.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/arch.h>
+#include <arch/board/board.h>
+
+#include "up_internal.h"
+#include "up_arch.h"
+
+#include "chip.h"
+#include "sam_gpio.h"
+#include "chip/sam_pio.h"
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+#ifdef CONFIG_DEBUG_GPIO
+static const char g_portchar[4] = { 'A', 'B', 'C', 'D' };
+#endif
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+/****************************************************************************
+ * Name: sam_gpiobase
+ *
+ * Description:
+ * Return the base address of the GPIO register set
+ *
+ ****************************************************************************/
+
+static inline uintptr_t sam_gpiobase(uint16_t cfgset)
+{
+ int port = (cfgset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
+ return SAM_PION_BASE(port);
+}
+
+/****************************************************************************
+ * Name: sam_gpiopin
+ *
+ * Description:
+ * Returun the base address of the GPIO register set
+ *
+ ****************************************************************************/
+
+static inline int sam_gpiopin(uint16_t cfgset)
+{
+ return 1 << ((cfgset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT);
+}
+
+/****************************************************************************
+ * Name: sam_configinput
+ *
+ * Description:
+ * Configure a GPIO input pin based on bit-encoded description of the pin.
+ *
+ ****************************************************************************/
+
+static inline int sam_configinput(uintptr_t base, uint32_t pin,
+ uint16_t cfgset)
+{
+ /* Disable interrupts on the pin */
+
+ putreg32(pin, base + SAM_PIO_IDR_OFFSET);
+
+ /* Enable/disable the pull-up as requested */
+
+ if ((cfgset & GPIO_CFG_PULLUP) != 0)
+ {
+ putreg32(pin, base + SAM_PIO_PUER_OFFSET);
+ }
+ else
+ {
+ putreg32(pin, base + SAM_PIO_PUDR_OFFSET);
+ }
+
+ /* Check if filtering should be enabled */
+
+ if ((cfgset & GPIO_CFG_DEGLITCH) != 0)
+ {
+ putreg32(pin, base + SAM_PIO_IFER_OFFSET);
+ }
+ else
+ {
+ putreg32(pin, base + SAM_PIO_IFDR_OFFSET);
+ }
+
+ /* Configure the pin as an input and enable the GPIO function */
+
+ putreg32(pin, base + SAM_PIO_ODR_OFFSET);
+ putreg32(pin, base + SAM_PIO_PER_OFFSET);
+
+ /* To-Do: If DEGLITCH is selected, need to configure DIFSR, SCIFSR, and
+ * registers. This would probably best be done with another, new
+ * API... perhaps sam_configfilter()
+ */
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: sam_configoutput
+ *
+ * Description:
+ * Configure a GPIO output pin based on bit-encoded description of the pin.
+ *
+ ****************************************************************************/
+
+static inline int sam_configoutput(uintptr_t base, uint32_t pin,
+ uint16_t cfgset)
+{
+ /* Disable interrupts on the pin */
+
+ putreg32(pin, base + SAM_PIO_IDR_OFFSET);
+
+ /* Enable/disable the pull-up as requested */
+
+ if ((cfgset & GPIO_CFG_PULLUP) != 0)
+ {
+ putreg32(pin, base + SAM_PIO_PUER_OFFSET);
+ }
+ else
+ {
+ putreg32(pin, base + SAM_PIO_PUDR_OFFSET);
+ }
+
+ /* Enable the open drain driver if requrested */
+
+ if ((cfgset & GPIO_CFG_OPENDRAIN) != 0)
+ {
+ putreg32(pin, base + SAM_PIO_MDER_OFFSET);
+ }
+ else
+ {
+ putreg32(pin, base + SAM_PIO_MDDR_OFFSET);
+ }
+
+ /* Set default value */
+
+ if ((cfgset & GPIO_OUTPUT_SET) != 0)
+ {
+ putreg32(pin, base + SAM_PIO_SODR_OFFSET);
+ }
+ else
+ {
+ putreg32(pin, base + SAM_PIO_CODR_OFFSET);
+ }
+
+ /* Configure the pin as an input and enable the GPIO function */
+
+ putreg32(pin, base + SAM_PIO_OER_OFFSET);
+ putreg32(pin, base + SAM_PIO_PER_OFFSET);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: sam_configperiph
+ *
+ * Description:
+ * Configure a GPIO pin driven by a peripheral A or B signal based on
+ * bit-encoded description of the pin.
+ *
+ ****************************************************************************/
+
+static inline int sam_configperiph(uintptr_t base, uint32_t pin,
+ uint16_t cfgset)
+{
+ uint32_t regval;
+
+ /* Disable interrupts on the pin */
+
+ putreg32(pin, base + SAM_PIO_IDR_OFFSET);
+
+ /* Enable/disable the pull-up as requested */
+
+ if ((cfgset & GPIO_CFG_PULLUP) != 0)
+ {
+ putreg32(pin, base + SAM_PIO_PUER_OFFSET);
+ }
+ else
+ {
+ putreg32(pin, base + SAM_PIO_PUDR_OFFSET);
+ }
+
+ /* Configure pin, depending upon the peripheral A or B*/
+
+ regval = getreg32(base + SAM_PIO_ABSR_OFFSET);
+ if ((cfgset & GPIO_MODE_MASK) == GPIO_PERIPHA)
+ {
+ regval &= ~pin;
+ }
+ else
+ {
+ regval |= pin;
+ }
+ putreg32(regval, base + SAM_PIO_ABSR_OFFSET);
+
+ /* Disable PIO functionality */
+
+ putreg32(pin, base + SAM_PIO_PDR_OFFSET);
+ return OK;
+}
+
+/****************************************************************************
+ * Global Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: sam_configgpio
+ *
+ * Description:
+ * Configure a GPIO pin based on bit-encoded description of the pin.
+ *
+ ****************************************************************************/
+
+int sam_configgpio(uint16_t cfgset)
+{
+ uintptr_t base = sam_gpiobase(cfgset);
+ uint32_t pin = sam_gpiopin(cfgset);
+ int ret;
+
+ switch (cfgset & GPIO_MODE_MASK)
+ {
+ case GPIO_INPUT:
+ ret = sam_configinput(base, pin, cfgset);
+ break;
+
+ case GPIO_OUTPUT:
+ ret = sam_configoutput(base, pin, cfgset);
+ break;
+
+ case GPIO_PERIPHA:
+ case GPIO_PERIPHB:
+ ret = sam_configperiph(base, pin, cfgset);
+ break;
+
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+/****************************************************************************
+ * Name: sam_gpiowrite
+ *
+ * Description:
+ * Write one or zero to the selected GPIO pin
+ *
+ ****************************************************************************/
+
+void sam_gpiowrite(uint16_t pinset, bool value)
+{
+ uintptr_t base = sam_gpiobase(pinset);
+ uint32_t pin = sam_gpiopin(pinset);
+
+ if (value)
+ {
+ putreg32(pin, base + SAM_PIO_SODR_OFFSET);
+ }
+ else
+ {
+ putreg32(pin, base + SAM_PIO_CODR_OFFSET);
+ }
+}
+
+/****************************************************************************
+ * Name: sam_gpioread
+ *
+ * Description:
+ * Read one or zero from the selected GPIO pin
+ *
+ ****************************************************************************/
+
+bool sam_gpioread(uint16_t pinset)
+{
+ uintptr_t base = sam_gpiobase(pinset);
+ uint32_t pin = sam_gpiopin(pinset);
+ uint32_t regval;
+
+ if ((pinset & GPIO_MODE_MASK) == GPIO_OUTPUT)
+ {
+ regval = getreg32(base + SAM_PIO_ODSR_OFFSET);
+ }
+ else
+ {
+ regval = getreg32(base + SAM_PIO_PDSR_OFFSET);
+ }
+
+ return (regval & pin) != 0;
+}
+
+/************************************************************************************
+ * Function: sam_dumpgpio
+ *
+ * Description:
+ * Dump all GPIO registers associated with the base address of the provided pinset.
+ *
+ ************************************************************************************/
+
+#ifdef CONFIG_DEBUG_GPIO
+int sam_dumpgpio(uint32_t pinset, const char *msg)
+{
+ irqstate_t flags;
+ uintptr_t base;
+ unsigned int pin;
+ unsigned int port;
+
+ /* Get the base address associated with the PIO port */
+
+ pin = sam_gpiopin(pinset);
+ port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
+ base = SAM_PION_BASE(port);
+
+ /* The following requires exclusive access to the GPIO registers */
+
+ flags = irqsave();
+ lldbg("PIO%c pinset: %08x base: %08x -- %s\n",
+ g_portchar[port], pinset, base, msg);
+ lldbg(" PSR: %08x OSR: %08x IFSR: %08x ODSR: %08x\n",
+ getreg32(base + SAM_PIO_PSR_OFFSET), getreg32(base + SAM_PIO_OSR_OFFSET),
+ getreg32(base + SAM_PIO_IFSR_OFFSET), getreg32(base + SAM_PIO_ODSR_OFFSET));
+ lldbg(" PDSR: %08x IMR: %08x ISR: %08x MDSR: %08x\n",
+ getreg32(base + SAM_PIO_PDSR_OFFSET), getreg32(base + SAM_PIO_IMR_OFFSET),
+ getreg32(base + SAM_PIO_ISR_OFFSET), getreg32(base + SAM_PIO_MDSR_OFFSET));
+ lldbg(" PUSR: %08x ABSR: %08x SCIFSR: %08x DIFSR: %08x\n",
+ getreg32(base + SAM_PIO_PUSR_OFFSET), getreg32(base + SAM_PIO_ABSR_OFFSET),
+ getreg32(base + SAM_PIO_SCIFSR_OFFSET), getreg32(base + SAM_PIO_DIFSR_OFFSET));
+ lldbg(" IFDGSR: %08x SCDR: %08x OWSR: %08x AIMMR: %08x\n",
+ getreg32(base + SAM_PIO_IFDGSR_OFFSET), getreg32(base + SAM_PIO_SCDR_OFFSET),
+ getreg32(base + SAM_PIO_OWSR_OFFSET), getreg32(base + SAM_PIO_AIMMR_OFFSET));
+ lldbg(" ESR: %08x LSR: %08x ELSR: %08x FELLSR: %08x\n",
+ getreg32(base + SAM_PIO_ESR_OFFSET), getreg32(base + SAM_PIO_LSR_OFFSET),
+ getreg32(base + SAM_PIO_ELSR_OFFSET), getreg32(base + SAM_PIO_FELLSR_OFFSET));
+ lldbg(" FRLHSR: %08x LOCKSR: %08x WPMR: %08x WPSR: %08x\n",
+ getreg32(base + SAM_PIO_FRLHSR_OFFSET), getreg32(base + SAM_PIO_LOCKSR_OFFSET),
+ getreg32(base + SAM_PIO_WPMR_OFFSET), getreg32(base + SAM_PIO_WPSR_OFFSET));
+ irqrestore(flags);
+ return OK;
+}
+#endif
+