Add a new interface sam_pio_forceclk() that can be used to force PIO clocking on. I am afraid I was too conservative with PIO clocking in the initial design; this is the price

This commit is contained in:
Gregory Nutt 2014-07-09 11:26:07 -06:00
parent f8e772a3ae
commit a966e4f30b
2 changed files with 85 additions and 9 deletions

View File

@ -131,6 +131,10 @@ static const bool g_piointerrupt[SAM_NPIO] =
#endif
};
/* This is an array of ports that PIO enable forced on */
static uint32_t g_forced[SAM_NPIO];
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
@ -160,11 +164,11 @@ static inline uintptr_t sam_piobase(pio_pinset_t cfgset)
* Name: sam_piopin
*
* Description:
* Return the base address of the PIO register set
* Return a bitmask corresponding to the bit position in a PIO register
*
****************************************************************************/
static inline int sam_piopin(pio_pinset_t cfgset)
static inline uint32_t sam_piopin(pio_pinset_t cfgset)
{
return 1 << ((cfgset & PIO_PIN_MASK) >> PIO_PIN_SHIFT);
}
@ -228,9 +232,11 @@ static void sam_pio_disableclk(pio_pinset_t cfgset)
uintptr_t base;
int pid;
/* Leave clocking enabled for configured interrupt ports */
/* Leave clocking enabled for configured interrupt ports or for ports that
* have forced enabling of PIO clocking.
*/
if (port < SAM_NPIO && !g_piointerrupt[port])
if (port < SAM_NPIO && !g_piointerrupt[port] && g_forced[port] == 0)
{
/* Get the base address of the PIO port */
@ -437,7 +443,10 @@ static inline int sam_configoutput(uintptr_t base, uint32_t pin,
putreg32(pin, base + SAM_PIO_MDDR_OFFSET);
}
/* Set default value */
/* 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.
*/
if ((cfgset & PIO_OUTPUT_SET) != 0)
{
@ -723,6 +732,56 @@ bool sam_pioread(pio_pinset_t pinset)
return 0;
}
/************************************************************************************
* 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.
*
************************************************************************************/
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;
sam_pio_enableclk(pinset);
}
else
{
/* Clocking is no longer forced for this pin */
g_forced[port] &= ~pin;
sam_pio_disableclk(pinset);
}
irqrestore(flags);
}
/************************************************************************************
* Function: sam_dumppio
*

View File

@ -335,6 +335,23 @@ void sam_pioirqdisable(int irq);
# define sam_pioirqdisable(irq)
#endif
/************************************************************************************
* 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.
*
************************************************************************************/
void sam_pio_forceclk(pio_pinset_t pinset, bool enable);
/************************************************************************************
* Function: sam_dumppio
*