SAM3/4: Important bugfix. Values read from PIO input pins do not change unless clocking to the PIO block is enabled

This commit is contained in:
Gregory Nutt 2014-06-30 14:26:09 -06:00
parent 588d0178a6
commit c005ac91d7
5 changed files with 244 additions and 28 deletions

View File

@ -2953,17 +2953,19 @@ FAR struct sdio_dev_s *sdio_initialize(int slotno)
/* Configure PIOs for 4-bit, wide-bus operation. NOTE: (1) the chip
* is capable of 8-bit wide bus operation but D4-D7 are not configured,
* (2) any card detection PIOs must be set up in board-specific logic.
*
* REVISIT: What about Slot B?
*/
sam_configpio(PIO_MCI0_DA0); /* Data 0 of Slot A */
sam_configpio(PIO_MCI0_DA1); /* Data 1 of Slot A */
sam_configpio(PIO_MCI0_DA2); /* Data 2 of Slot A */
sam_configpio(PIO_MCI0_DA3); /* Data 3 of Slot A */
sam_configpio(PIO_MCI0_CK); /* SD clock */
sam_configpio(PIO_MCI0_CDA); /* Command/Response */
sam_configpio(PIO_MCI0_CK); /* Common SD clock */
sam_configpio(PIO_MCI0_CDA); /* Command/Response of Slot A*/
/* Enable the HSMCI0 peripheral clock. This really should be done in
* sam_enable (as well as disabling peripheal clocks in sam_disable().
* sam_enable (as well as disabling peripheral clocks in sam_disable().
*/
sam_hsmci0_enableclk();
@ -2990,17 +2992,19 @@ FAR struct sdio_dev_s *sdio_initialize(int slotno)
/* Configure PIOs for 4-bit, wide-bus operation. NOTE: (1) the chip
* is capable of 8-bit wide bus operation but D4-D7 are not configured,
* (2) any card detection PIOs must be set up in board-specific logic.
*
* REVISIT: What about Slot B?
*/
sam_configpio(PIO_MCI1_DA0); /* Data 0 of Slot A */
sam_configpio(PIO_MCI1_DA1); /* Data 1 of Slot A */
sam_configpio(PIO_MCI1_DA2); /* Data 2 of Slot A */
sam_configpio(PIO_MCI1_DA3); /* Data 3 of Slot A */
sam_configpio(PIO_MCI1_CK); /* SD clock */
sam_configpio(PIO_MCI1_CDA); /* Command/Response */
sam_configpio(PIO_MCI1_CK); /* Common SD clock */
sam_configpio(PIO_MCI1_CDA); /* Command/Response of Slot A */
/* Enable the HSMCI1 peripheral clock This really should be done in
* sam_enable (as well as disabling peripheal clocks in sam_disable().
* sam_enable (as well as disabling peripheral clocks in sam_disable().
*/
sam_hsmci1_enableclk();
@ -3027,17 +3031,19 @@ FAR struct sdio_dev_s *sdio_initialize(int slotno)
/* Configure PIOs for 4-bit, wide-bus operation. NOTE: (1) the chip
* is capable of 8-bit wide bus operation but D4-D7 are not configured,
* (2) any card detection PIOs must be set up in board-specific logic.
*
* REVISIT: What about Slot B?
*/
sam_configpio(PIO_MCI2_DA0); /* Data 0 of Slot A */
sam_configpio(PIO_MCI2_DA1); /* Data 1 of Slot A */
sam_configpio(PIO_MCI2_DA2); /* Data 2 of Slot A */
sam_configpio(PIO_MCI1_DA3); /* Data 3 of Slot A */
sam_configpio(PIO_MCI2_DA3); /* SD clock */
sam_configpio(PIO_MCI2_CDA); /* Command/Response */
sam_configpio(PIO_MCI2_CK); /* Common SD clock */
sam_configpio(PIO_MCI2_CDA); /* Command/Response of Slot A */
/* Enable the HSMCI2 peripheral clock This really should be done in
* sam_enable (as well as disabling peripheal clocks in sam_disable().
* sam_enable (as well as disabling peripheral clocks in sam_disable().
*/
sam_hsmci1_enableclk();

View File

@ -51,10 +51,12 @@
#include "up_internal.h"
#include "up_arch.h"
#include "chip.h"
#include "sam_pio.h"
#include "chip/sam_pio.h"
#include "chip.h"
#include "sam_periphclks.h"
#include "sam_pio.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
@ -66,6 +68,7 @@
/****************************************************************************
* Private Data
****************************************************************************/
/* Maps a port number to the standard port character */
#ifdef CONFIG_DEBUG_GPIO
static const char g_portchar[SAM_NPIO] =
@ -74,6 +77,49 @@
};
#endif
/* Map a PIO number to the PIO peripheral identifier (PID) */
static const uint8_t g_piopid[SAM_NPIO] =
{
SAM_PID_PIOA, SAM_PID_PIOB, SAM_PID_PIOC, SAM_PID_PIOD, SAM_PID_PIOE
};
/* Used to determine if a PIO port is configured to support interrupts */
static const bool g_piointterrupts[SAM_NPIO] =
{
#ifdef CONFIG_SAMA5_PIOA_IRQ
true,
#else
false,
#endif
#ifdef CONFIG_SAMA5_PIOB_IRQ
true,
#else
false,
#endif
#ifdef CONFIG_SAMA5_PIOC_IRQ
true,
#else
false,
#endif
#ifdef CONFIG_SAMA5_PIOD_IRQ
true,
#else
false,
#endif
#ifdef CONFIG_SAMA5_PIOE_IRQ
true,
#else
false,
#endif
#ifdef CONFIG_SAMA5_PIOF_IRQ
true,
#else
false,
#endif
};
/* SAM_PION_VBASE will only be defined if the PIO register blocks are
* contiguous. If not defined, then we need to do a table lookup.
*/
@ -117,7 +163,7 @@ static inline uintptr_t sam_piobase(pio_pinset_t cfgset)
* Name: sam_piopin
*
* Description:
* Returun the base address of the PIO register set
* Return the base address of the PIO register set
*
****************************************************************************/
@ -126,6 +172,102 @@ static inline int sam_piopin(pio_pinset_t cfgset)
return 1 << ((cfgset & PIO_PIN_MASK) >> PIO_PIN_SHIFT);
}
/****************************************************************************
* Name: sam_pio_enableclk
*
* Description:
* Enable clocking on the selected PIO
*
****************************************************************************/
static void sam_pio_enableclk(pio_pinset_t cfgset)
{
int port = (cfgset & PIO_PORT_MASK) >> PIO_PORT_SHIFT;
int pid;
if (port < SAM_NPIO)
{
/* Get the peripheral ID associated with the PIO port and enable
* clocking to the PIO block.
*/
pid = g_piopid[port];
if (pid < 32)
{
sam_enableperiph0(pid);
}
else
{
sam_enableperiph1(pid);
}
}
}
/****************************************************************************
* Name: sam_pio_disableclk
*
* Description:
* Disable clocking on the selected PIO if we can. We can that if:
*
* 1) No pins are configured as PIO inputs (peripheral inputs don't need
* clocking, and
* 2) Glitch and debounce filtering are not enabled. Currently, this can
* only happen if the the pin is a PIO input, but we may need to
* implement glitch filtering on peripheral inputs as well in the
* future???
* 3) The port is not configured for PIO interrupts. At present, the logic
* always keeps clocking on to ports that are configured for interrupts,
* but that could be dynamically controlled as well be keeping track
* of which PIOs have interrupts enabled.
*
* My! Wouldn't is be much easier to just keep all of the PIO clocks
* enabled? Is there a power management downside?
*
****************************************************************************/
static void sam_pio_disableclk(pio_pinset_t cfgset)
{
int port = (cfgset & PIO_PORT_MASK) >> PIO_PORT_SHIFT;
uintptr_t base;
int pid;
/* Leave clocking enabled for configured interrupt ports */
if (port < SAM_NPIO && !g_piointerrupt[port])
{
/* Get the base address of the PIO port */
base = g_piobase[port];
/* Are any pins configured as PIO inputs?
*
* PSR - A bit set to "1" means that the corresponding pin is a PIO
* OSR - A bit set to "1" means that the corresponding pin is an output
*/
if ((getreg32(base + SAM_PIO_PSR_OFFSET) &
~getreg32(base + SAM_PIO_PSR_OFFSET)) == 0)
{
/* Any remaining configured pins are either not PIOs or all not
* PIO inputs. Disable clocking to this PIO block.
*
* Get the peripheral ID associated with the PIO port and disable
* clocking to the PIO block.
*/
pid = g_piopid[port];
if (pid < 32)
{
sam_disableperiph0(pid);
}
else
{
sam_disableperiph1(pid);
}
}
}
}
/****************************************************************************
* Name: sam_configinput
*
@ -198,6 +340,7 @@ static inline int sam_configinput(uintptr_t base, uint32_t pin,
{
regval &= ~pin;
}
putreg32(regval, base + SAM_PIO_SCHMITT_OFFSET);
#endif
@ -234,7 +377,13 @@ static inline int sam_configinput(uintptr_t base, uint32_t pin,
* another, new API... perhaps sam_configfilter()
*/
return OK;
/* "Reading the I/O line levels requires the clock of the PIO Controller
* to be enabled, otherwise PIO_PDSR reads the levels present on the I/O
* line at the time the clock was disabled."
*/
sam_pio_enableclk(cfgset);
return OK;
}
/****************************************************************************
@ -276,7 +425,11 @@ static inline int sam_configoutput(uintptr_t base, uint32_t pin,
}
#endif
/* Enable the open drain driver if requrested */
/* Disable glitch filtering */
putreg32(pin, base + SAM_PIO_IFDR_OFFSET);
/* Enable the open drain driver if requested */
if ((cfgset & PIO_CFG_OPENDRAIN) != 0)
{
@ -302,6 +455,10 @@ static inline int sam_configoutput(uintptr_t base, uint32_t pin,
putreg32(pin, base + SAM_PIO_OER_OFFSET);
putreg32(pin, base + SAM_PIO_PER_OFFSET);
/* Clocking to the PIO block may no longer be necessary. */
sam_pio_disableclk(cfgset);
return OK;
}
@ -347,6 +504,10 @@ static inline int sam_configperiph(uintptr_t base, uint32_t pin,
}
#endif
/* Disable glitch filtering */
putreg32(pin, base + SAM_PIO_IFDR_OFFSET);
#ifdef PIO_HAVE_PERIPHCD
/* Configure pin, depending upon the peripheral A, B, C or D
*
@ -366,6 +527,7 @@ static inline int sam_configperiph(uintptr_t base, uint32_t pin,
{
regval |= pin;
}
putreg32(regval, base + SAM_PIO_ABCDSR1_OFFSET);
regval = getreg32(base + SAM_PIO_ABCDSR2_OFFSET);
@ -378,6 +540,7 @@ static inline int sam_configperiph(uintptr_t base, uint32_t pin,
{
regval |= pin;
}
putreg32(regval, base + SAM_PIO_ABCDSR2_OFFSET);
#else
@ -396,12 +559,17 @@ static inline int sam_configperiph(uintptr_t base, uint32_t pin,
{
regval |= pin;
}
putreg32(regval, base + SAM_PIO_ABSR_OFFSET);
#endif
/* Disable PIO functionality */
putreg32(pin, base + SAM_PIO_PDR_OFFSET);
/* Clocking to the PIO block may no longer be necessary. */
sam_pio_disableclk(cfgset);
return OK;
}

View File

@ -196,6 +196,7 @@ static int sam_piointerrupt(uint32_t base, int irq0, void *context)
pending &= ~bit;
}
}
return OK;
}

View File

@ -3330,15 +3330,21 @@ Configurations
will need to install a battery in the battery holder (J12) and close
the jumper, JP13.
8. Support for HSMCI0 and HSMCI1 is built-in by default. The SAMA4D4-EK
provides a two SD memory card slots: (1) a full size SD card slot
(J10), and (2) a microSD memory card slot (J11). The full size SD
card slot connects via HSMCI0; the microSD connects vi HSMCI1.
Support for both SD slots can be enabled with the settings provided
8. Support for HSMCI0 is built-in by default. The SAMA4D4-EK provides
two SD memory card slots: (1) a full size SD card slot (J10), and
(2) a microSD memory card slot (J11). The full size SD card slot
connects via HSMCI0; the microSD connects vi HSMCI1. Support for
the microSD slot could also be enabled with the settings provided
in the paragraph entitled "HSMCI Card Slots" above.
NOTE: For now I am boot off the microSD slot so, unless are booting
in a different manner, this HSMCI1 slot may not be useful to you.
in a different manner, this HSMCI1 slot may not be useful to you
anyway.
STATUS: There is an unresolved issue with HSMCI0 as of this writing.
No errors are reported so most the handshaking signals and command
transfers are working, but all data transfers return the value zero
(with or without DMA). This seems like some pin configuration issue.
9. The SAMA5D4-EK includes for an AT25 serial DataFlash. That support is
NOT enabled in this configuration. Support for that serial FLASH can
@ -3437,7 +3443,11 @@ To-Do List
2) HSCMI TX DMA support is currently commented out.
3) Some drivers may require some adjustments if you intend to run from SDRAM.
3) Currently HSMCI1 does not work correctly. No errors are reported so all of
the card handshakes must be working, but only zero values are read from the
card (with or without DMA). Sounds like a pin configuration issue.
4) Some drivers may require some adjustments if you intend to run from SDRAM.
That is because in this case macros like BOARD_MCK_FREQUENCY are not constants
but are instead function calls: The MCK clock frequency is not known in
advance but instead has to be calculated from the bootloader PLL configuration.

View File

@ -119,6 +119,8 @@ CONFIG_ARMV7A_TOOLCHAIN_CODESOURCERYW=y
# CONFIG_ARMV7A_TOOLCHAIN_GNU_EABIW is not set
# CONFIG_ARMV7A_TOOLCHAIN_GNU_OABI is not set
# CONFIG_ARMV7A_DECODEFIQ is not set
CONFIG_SDIO_DMA=y
# CONFIG_SDIO_WIDTH_D1_ONLY is not set
#
# SAMA5 Configuration Options
@ -187,7 +189,7 @@ CONFIG_SAMA5_USART4=y
# CONFIG_SAMA5_TWI1 is not set
# CONFIG_SAMA5_TWI2 is not set
# CONFIG_SAMA5_TWI3 is not set
# CONFIG_SAMA5_HSMCI0 is not set
CONFIG_SAMA5_HSMCI0=y
# CONFIG_SAMA5_HSMCI1 is not set
# CONFIG_SAMA5_SBM is not set
# CONFIG_SAMA5_SFC is not set
@ -200,7 +202,7 @@ CONFIG_SAMA5_USART4=y
# CONFIG_SAMA5_PWM is not set
# CONFIG_SAMA5_ADC is not set
# CONFIG_SAMA5_XDMAC0 is not set
# CONFIG_SAMA5_XDMAC1 is not set
CONFIG_SAMA5_XDMAC1=y
# CONFIG_SAMA5_UHPHS is not set
# CONFIG_SAMA5_UDPHS is not set
# CONFIG_SAMA5_EMACB is not set
@ -214,7 +216,19 @@ CONFIG_SAMA5_TRNG=y
# CONFIG_SAMA5_FUSE is not set
# CONFIG_SAMA5_MPDDRC is not set
# CONFIG_SAMA5_VDEC is not set
# CONFIG_SAMA5_PIO_IRQ is not set
CONFIG_SAMA5_PIO_IRQ=y
# CONFIG_SAMA5_PIOA_IRQ is not set
# CONFIG_SAMA5_PIOB_IRQ is not set
# CONFIG_SAMA5_PIOC_IRQ is not set
# CONFIG_SAMA5_PIOD_IRQ is not set
CONFIG_SAMA5_PIOE_IRQ=y
#
# HSMCI device driver options
#
CONFIG_SAMA5_HSMCI0_XDMAC1=y
# CONFIG_SAMA5_HSMCI_RDPROOF is not set
# CONFIG_SAMA5_HSMCI_WRPROOF is not set
#
# External Memory Configuration
@ -238,7 +252,7 @@ CONFIG_SAMA5_ISRAM_HEAP=y
#
# CONFIG_ARCH_NOINTC is not set
# CONFIG_ARCH_VECNOTIRQ is not set
# CONFIG_ARCH_DMA is not set
CONFIG_ARCH_DMA=y
CONFIG_ARCH_HAVE_IRQPRIO=y
# CONFIG_CUSTOM_STACK is not set
# CONFIG_ADDRENV is not set
@ -300,6 +314,7 @@ CONFIG_ARCH_HAVE_BUTTONS=y
# CONFIG_ARCH_BUTTONS is not set
CONFIG_ARCH_HAVE_IRQBUTTONS=y
CONFIG_NSH_MMCSDMINOR=0
CONFIG_NSH_MMCSDSLOTNO=0
#
# Board-Specific Options
@ -381,6 +396,7 @@ CONFIG_SIG_SIGUSR1=1
CONFIG_SIG_SIGUSR2=2
CONFIG_SIG_SIGALARM=3
CONFIG_SIG_SIGCONDTIMEDOUT=16
CONFIG_SIG_SIGWORK=17
#
# POSIX Message Queue Options
@ -424,7 +440,17 @@ CONFIG_RTC_DATETIME=y
# CONFIG_BCH is not set
# CONFIG_INPUT is not set
# CONFIG_LCD is not set
# CONFIG_MMCSD is not set
CONFIG_MMCSD=y
CONFIG_MMCSD_NSLOTS=1
# CONFIG_MMCSD_READONLY is not set
# CONFIG_MMCSD_MULTIBLOCK_DISABLE is not set
# CONFIG_MMCSD_MMCSUPPORT is not set
CONFIG_MMCSD_HAVECARDDETECT=y
CONFIG_ARCH_HAVE_SDIO=y
CONFIG_MMCSD_SDIO=y
# CONFIG_SDIO_PREFLIGHT is not set
# CONFIG_SDIO_MUXBUS is not set
CONFIG_SDIO_BLOCKSETUP=y
# CONFIG_MTD is not set
# CONFIG_PIPES is not set
# CONFIG_PM is not set
@ -602,7 +628,12 @@ CONFIG_LIB_SENDFILE_BUFSIZE=512
#
# Non-standard Library Support
#
# CONFIG_SCHED_WORKQUEUE is not set
CONFIG_SCHED_WORKQUEUE=y
CONFIG_SCHED_HPWORK=y
CONFIG_SCHED_WORKPRIORITY=192
CONFIG_SCHED_WORKPERIOD=50000
CONFIG_SCHED_WORKSTACKSIZE=2048
# CONFIG_SCHED_LPWORK is not set
# CONFIG_LIB_KBDCODEC is not set
# CONFIG_LIB_SLCDCODEC is not set
@ -807,7 +838,7 @@ CONFIG_NSH_CONSOLE=y
# USB Trace Support
#
# CONFIG_NSH_ALTCONDEV is not set
# CONFIG_NSH_ARCHINIT is not set
CONFIG_NSH_ARCHINIT=y
#
# NxWidgets/NxWM