diff --git a/arch/arm/src/sama5/sama5d2x_pio.c b/arch/arm/src/sama5/sama5d2x_pio.c index b07681db8b0..6b35b7aa190 100644 --- a/arch/arm/src/sama5/sama5d2x_pio.c +++ b/arch/arm/src/sama5/sama5d2x_pio.c @@ -136,63 +136,14 @@ static const char g_portchar[SAM_NPIO] = }; #endif -/* Used to determine if a PIO port is configured to support interrupts */ - -#if SAM_NPIO > 0 -static const bool g_piointerrupt[SAM_NPIO] = -{ -#ifdef CONFIG_SAMA5_PIOA_IRQ - true -#else - false -#endif - -#if SAM_NPIO > 1 -#ifdef CONFIG_SAMA5_PIOB_IRQ - , true -#else - , false -#endif -#endif - -#if SAM_NPIO > 2 -#ifdef CONFIG_SAMA5_PIOC_IRQ - , true -#else - , false -#endif -#endif - -#if SAM_NPIO > 3 -#ifdef CONFIG_SAMA5_PIOD_IRQ - , true -#else - , false -#endif -#endif - -#if SAM_NPIO > 4 -#ifdef CONFIG_SAMA5_PIOE_IRQ - , true -#else - , false -#endif -#endif -}; -#endif - -/* This is an array of ports that PIO enable forced on */ - -static uint32_t g_forced[SAM_NPIO]; - /**************************************************************************** * Private Function Prototypes ****************************************************************************/ /**************************************************************************** - * Name: sam_piobase + * Name: sam_issecure * * Description: - * Return the base address of the PIO register set + * Return true if the configuration selects a secure port. * ****************************************************************************/ @@ -221,10 +172,14 @@ static uintptr_t sam_piobase(pio_pinset_t cfgset) if (sam_issecure(cfgset)) { + /* Return the base address of the secure PIO registers */ + return sam_spion_vbase(port); } else { + /* Return the base address of the un-secured PIO registers */ + return sam_pion_vbase(port); } } @@ -245,6 +200,95 @@ static inline uint32_t sam_piopin(pio_pinset_t cfgset) return 1 << ((cfgset & PIO_PIN_MASK) >> PIO_PIN_SHIFT); } +/**************************************************************************** + * Name: sam_configcommon + * + * Description: + * Configure common PIO pin settings based on bit-encoded description of + * the pin. + * + ****************************************************************************/ + +static uint32_t sam_configcommon(pio_pinset_t cfgset) +{ + uint32_t regval = 0; + + /* Enable/disable the pull-up as requested + * NOTE: Control of the pull-up resistor is possible regardless of the + * configuration of the I/O line (Input, Output, Open-drain). + */ + + if ((cfgset & PIO_CFG_PULLUP) != 0) + { + regval |= PIO_CFGR_PUEN; + } + + /* Enable/disable the pull-down as requested */ + + if ((cfgset & PIO_CFG_PULLDOWN) != 0) + { + regval |= PIO_CFGR_PDEN; + } + + /* Check if filtering should be enabled. + * NOTE: Input filtering and Schmitt triggering apply only to inputs. + */ + + if ((cfgset & PIO_CFG_DEGLITCH) != 0) + { + if ((cfgset & PIO_CFG_DEGLITCH) != 0) + { + regval |= (PIO_CFGR_IFEN | PIO_CFGR_IFSCEN); + } + else + { + regval |= PIO_CFGR_IFEN; + } + } + + /* Enable/disable the Schmitt trigger inputs. + * NOTE: Input filtering and Schmitt triggering apply only to inputs. + */ + + if ((cfgset & PIO_CFG_SCHMITT) != 0) + { + regval |= PIO_CFGR_SCHMITT; + } + + /* Enable the open drain driver if requested. + * NOTE: The open drain apply option applies only to output and + * peripheral pins. + */ + + if ((cfgset & PIO_CFG_OPENDRAIN) != 0) + { + regval |= PIO_CFGR_OPD; + } + + /* Select I/O drive. + * REVISIT: Does't rive strength apply only to output and peripheral + * pins as well? + */ + + switch (cfgset & PIO_DRIVE_MASK) + { + default: + case PIO_DRIVE_LOW: + regval |= PIO_CFGR_DRVSTR_LOW; + break; + + case PIO_DRIVE_MEDIUM: + regval |= PIO_CFGR_DRVSTR_MED; + break; + + case PIO_DRIVE_HIGH: + regval |= PIO_CFGR_DRVSTR_HIGH; + break; + } + + return regval; +} + /**************************************************************************** * Name: sam_configinput * @@ -264,64 +308,9 @@ static inline int sam_configinput(uintptr_t base, uint32_t pin, /* Select GPIO input */ + regval = sam_configcommon(cfgset); regval = (PIO_CFGR_FUNC_GPIO | PIO_CFGR_DIR_INPUT); - /* Enable/disable the pull-up as requested */ - - if ((cfgset & PIO_CFG_PULLUP) != 0) - { - regval |= PIO_CFGR_PUEN; - } - - /* Enable/disable the pull-down as requested */ - - if ((cfgset & PIO_CFG_PULLDOWN) != 0) - { - regval |= PIO_CFGR_PDEN; - } - - /* Check if filtering should be enabled */ - - if ((cfgset & PIO_CFG_DEGLITCH) != 0) - { - if ((cfgset & PIO_CFG_DEGLITCH) != 0) - { - regval |= (PIO_CFGR_IFEN | PIO_CFGR_IFSCEN); - } - else - { - regval |= PIO_CFGR_IFEN; - } - } - - /* Enable/disable the Schmitt trigger inputs */ - - if ((cfgset & PIO_CFG_SCHMITT) != 0) - { - regval |= PIO_CFGR_SCHMITT; - } - - /* Select I/O drive. - * REVISIT: Don't open drain and drive strength apply only to - * output and peripheral pins. - */ - - switch (cfgset & PIO_DRIVE_MASK) - { - default: - case PIO_DRIVE_LOW: - regval |= PIO_CFGR_DRVSTR_LOW; - break; - - case PIO_DRIVE_MEDIUM: - regval |= PIO_CFGR_DRVSTR_MED; - break; - - case PIO_DRIVE_HIGH: - regval |= PIO_CFGR_DRVSTR_HIGH; - break; - } - /* Clear some output only bits. Mostly this just simplifies debug. */ putreg32(pin, base + SAM_PIO_CODR_OFFSET); @@ -351,52 +340,9 @@ static inline int sam_configoutput(uintptr_t base, uint32_t pin, /* Select GPIO output */ + regval = sam_configcommon(cfgset); regval = (PIO_CFGR_FUNC_GPIO | PIO_CFGR_DIR_OUTPUT); - /* Enable/disable the pull-up as requested - * NOTE: Control of the pull-up resistor is possible regardless of the - * configuration of the I/O line (Input, Output, Open-drain). - */ - - if ((cfgset & PIO_CFG_PULLUP) != 0) - { - regval |= PIO_CFGR_PUEN; - } - - /* Enable/disable the pull-down as requested */ - - if ((cfgset & PIO_CFG_PULLDOWN) != 0) - { - regval |= PIO_CFGR_PDEN; - } - - /* Input filtering and Schmitt triggering apply only to inputs */ - - /* Enable the open drain driver if requested */ - - if ((cfgset & PIO_CFG_OPENDRAIN) != 0) - { - regval |= PIO_CFGR_OPD; - } - - /* Select I/O drive */ - - switch (cfgset & PIO_DRIVE_MASK) - { - default: - case PIO_DRIVE_LOW: - regval |= PIO_CFGR_DRVSTR_LOW; - break; - - case PIO_DRIVE_MEDIUM: - regval |= PIO_CFGR_DRVSTR_MED; - break; - - case PIO_DRIVE_HIGH: - regval |= PIO_CFGR_DRVSTR_HIGH; - break; - } - /* Set default value. This is to be done before the pin is configured as * an output in order to avoid any glitches at the time of the * configuration. @@ -440,60 +386,14 @@ static inline int sam_configperiph(uintptr_t base, uint32_t pin, * peripherals. */ - periph = ((cfgset & PIO_CFGR_FUNC_MASK) - PIO_CFGR_FUNC_PERIPHA) >> PIO_CFGR_FUNC_SHIFT; - regval = PIO_CFGR_FUNC_PERIPH(periph); - - /* Enable/disable the pull-up as requested - * NOTE: Control of the pull-up resistor is possible regardless of the - * configuration of the I/O line (Input, Output, Open-drain). - */ - - if ((cfgset & PIO_CFG_PULLUP) != 0) - { - regval |= PIO_CFGR_PUEN; - } - - /* Enable/disable the pull-down as requested */ - - if ((cfgset & PIO_CFG_PULLDOWN) != 0) - { - regval |= PIO_CFGR_PDEN; - } - - /* REVIT: Input filtering and Schmitt triggering apply only to inputs */ - - /* Enable the open drain driver if requested */ - - if ((cfgset & PIO_CFG_OPENDRAIN) != 0) - { - regval |= PIO_CFGR_OPD; - } - - /* Select I/O drive. - * REVISIT: Does this apply to peripherals? - */ - - switch (cfgset & PIO_DRIVE_MASK) - { - default: - case PIO_DRIVE_LOW: - regval |= PIO_CFGR_DRVSTR_LOW; - break; - - case PIO_DRIVE_MEDIUM: - regval |= PIO_CFGR_DRVSTR_MED; - break; - - case PIO_DRIVE_HIGH: - regval |= PIO_CFGR_DRVSTR_HIGH; - break; - } + regval = sam_configcommon(cfgset); + periph = ((cfgset & PIO_CFGR_FUNC_MASK) - PIO_CFGR_FUNC_PERIPHA) >> PIO_CFGR_FUNC_SHIFT; + regval |= PIO_CFGR_FUNC_PERIPH(periph); /* Clear some output only bits. Mostly this just simplifies debug. */ putreg32(pin, base + SAM_PIO_CODR_OFFSET); - /* Configure the pin as a peripheral */ putreg32(regval, base + SAM_PIO_CFGR_OFFSET); @@ -692,48 +592,13 @@ bool sam_pioread(pio_pinset_t pinset) * Name: sam_pio_forceclk * * Description: - * Enable PIO clocking. This logic is overly conservative and does not enable PIO - * clocking unless necessary (PIO input selected, glitch/filtering enable, or PIO - * interrupts enabled). There are, however, certain conditions were we may want - * for force the PIO clock to be enabled. An example is reading the input value - * from an open drain output. - * - * The PIO automatic enable/disable logic is not smart enough enough to know about - * these cases. For those cases, sam_pio_forceclk() is provided. + * Enable PIO clocking. Needed only for SAMA5D3/D4 compatibility. For the SAMA5D2, + * there is a common clock for all PIO ports and that clock is always enabled. * ************************************************************************************/ void sam_pio_forceclk(pio_pinset_t pinset, bool enable) { - unsigned int port; - uint32_t pin; - irqstate_t flags; - - /* Extract the port number */ - - port = (pinset & PIO_PORT_MASK) >> PIO_PORT_SHIFT; - pin = sam_piopin(pinset); - - /* The remainder of this operation must be atomic */ - - flags = irqsave(); - - /* Are we enabling or disabling clocking */ - - if (enable) - { - /* Indicate that clocking is forced and enable the clock */ - - g_forced[port] |= pin; - } - else - { - /* Clocking is no longer forced for this pin */ - - g_forced[port] &= ~pin; - } - - irqrestore(flags); } /************************************************************************************