SSP driver fixes for the LPC178x; Fixes for Open1788 touchscreen driver
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5812 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
b99923d973
commit
e1e8f4debe
@ -160,6 +160,6 @@ endif
|
||||
ifeq ($(CONFIG_ARMV6M_TOOLCHAIN),GNU_EABI)
|
||||
CROSSDEV ?= arm-none-eabi-
|
||||
ARCROSSDEV ?= arm-none-eabi-
|
||||
MAXOPTIMIZATION = -O3
|
||||
MAXOPTIMIZATION = -Os
|
||||
ARCHCPUFLAGS = -mcpu=cortex-m0 -mthumb -march=armv6-m -mfloat-abi=soft
|
||||
endif
|
||||
|
@ -89,6 +89,17 @@
|
||||
#define LPC17_SSP1_ICR (LPC17_SSP1_BASE+LPC17_SSP_ICR_OFFSET)
|
||||
#define LPC17_SSP1_DMACR (LPC17_SSP1_BASE+LPC17_SSP_DMACR_OFFSET)
|
||||
|
||||
#define LPC17_SSP2_CR0 (LPC17_SSP2_BASE+LPC17_SSP_CR0_OFFSET)
|
||||
#define LPC17_SSP2_CR1 (LPC17_SSP2_BASE+LPC17_SSP_CR1_OFFSET)
|
||||
#define LPC17_SSP2_DR (LPC17_SSP2_BASE+LPC17_SSP_DR_OFFSET)
|
||||
#define LPC17_SSP2_SR (LPC17_SSP2_BASE+LPC17_SSP_SR_OFFSET)
|
||||
#define LPC17_SSP2_CPSR (LPC17_SSP2_BASE+LPC17_SSP_CPSR_OFFSET)
|
||||
#define LPC17_SSP2_IMSC (LPC17_SSP2_BASE+LPC17_SSP_IMSC_OFFSET)
|
||||
#define LPC17_SSP2_RIS (LPC17_SSP2_BASE+LPC17_SSP_RIS_OFFSET)
|
||||
#define LPC17_SSP2_MIS (LPC17_SSP2_BASE+LPC17_SSP_MIS_OFFSET)
|
||||
#define LPC17_SSP2_ICR (LPC17_SSP2_BASE+LPC17_SSP_ICR_OFFSET)
|
||||
#define LPC17_SSP2_DMACR (LPC17_SSP2_BASE+LPC17_SSP_DMACR_OFFSET)
|
||||
|
||||
/* Register bit definitions *********************************************************/
|
||||
/* Control Register 0 */
|
||||
|
||||
|
@ -52,7 +52,6 @@
|
||||
#include "chip.h"
|
||||
#include "lpc17_gpio.h"
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
@ -92,6 +92,7 @@
|
||||
#endif
|
||||
|
||||
/* SSP Clocking *************************************************************/
|
||||
|
||||
#if defined(LPC176x)
|
||||
/* The CPU clock by 1, 2, 4, or 8 to get the SSP peripheral clock (SSP_CLOCK).
|
||||
* SSP_CLOCK may be further divided by 2-254 to get the SSP clock. If we
|
||||
@ -106,17 +107,16 @@
|
||||
|
||||
# if LPC17_CCLK > 100000000
|
||||
# error "CCLK <= 100,000,000 assumed"
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# define SSP_PCLKSET_DIV SYSCON_PCLKSEL_CCLK
|
||||
# define SSP_CLOCK LPC17_CCLK
|
||||
|
||||
#elif defined(LPC178x)
|
||||
/* All peripherals are clocked by the same peripheral clock in the LPC178x
|
||||
* family.
|
||||
*/
|
||||
|
||||
#elif defined(LPC178x)
|
||||
|
||||
# define SSP_CLOCK BOARD_PCLK_FREQUENCY
|
||||
|
||||
#endif
|
||||
@ -397,10 +397,12 @@ static int ssp_lock(FAR struct spi_dev_s *dev, bool lock)
|
||||
static uint32_t ssp_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency)
|
||||
{
|
||||
FAR struct lpc17_sspdev_s *priv = (FAR struct lpc17_sspdev_s *)dev;
|
||||
uint32_t divisor;
|
||||
uint32_t cpsdvsr;
|
||||
uint32_t scr;
|
||||
uint32_t regval;
|
||||
uint32_t actual;
|
||||
|
||||
/* Check if the requested frequence is the same as the frequency selection */
|
||||
/* Check if the requested frequency is the same as the frequency selection */
|
||||
|
||||
DEBUGASSERT(priv && frequency <= SSP_CLOCK / 2);
|
||||
#ifndef CONFIG_SPI_OWNBUS
|
||||
@ -412,30 +414,65 @@ static uint32_t ssp_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* frequency = SSP_CLOCK / divisor, or divisor = SSP_CLOCK / frequency */
|
||||
/* The SSP bit frequency is given by:
|
||||
*
|
||||
* frequency = SSP_CLOCK / (CPSDVSR * (SCR+1)).
|
||||
*
|
||||
* Let's try for a solution with the smallest value of SCR. NOTES:
|
||||
* (1) In the calculations below, the value of the variable 'scr' is
|
||||
* (SCR+1) in the above equation. (2) On slower LPC17xx parts, SCR
|
||||
* will probably always be zero.
|
||||
*/
|
||||
|
||||
divisor = SSP_CLOCK / frequency;
|
||||
|
||||
/* "In master mode, CPSDVSRmin = 2 or larger (even numbers only)" */
|
||||
|
||||
if (divisor < 2)
|
||||
for (scr = 1; scr <= 256; scr++)
|
||||
{
|
||||
divisor = 2;
|
||||
}
|
||||
else if (divisor > 254)
|
||||
{
|
||||
divisor = 254;
|
||||
/* CPSDVSR = SSP_CLOCK / (SCR + 1) / frequency */
|
||||
|
||||
cpsdvsr = SSP_CLOCK / (scr * frequency);
|
||||
|
||||
/* Break out on the first solution we find with the smallest value
|
||||
* of SCR and with CPSDVSR within the maximum range or 254.
|
||||
*/
|
||||
|
||||
if (cpsdvsr < 255)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
divisor = (divisor + 1) & ~1;
|
||||
DEBUGASSERT(scr <= 256 && cpsdvsr <= 255);
|
||||
|
||||
/* Save the new divisor value */
|
||||
/* "In master mode, CPSDVSRmin = 2 or larger (even numbers only)" */
|
||||
|
||||
if (cpsdvsr < 2)
|
||||
{
|
||||
/* Clip to the minimum value. */
|
||||
|
||||
cpsdvsr = 2;
|
||||
}
|
||||
else if (cpsdvsr > 254)
|
||||
{
|
||||
/* This should never happen */
|
||||
|
||||
cpsdvsr = 254;
|
||||
}
|
||||
|
||||
/* Force even */
|
||||
|
||||
cpsdvsr = (cpsdvsr + 1) & ~1;
|
||||
|
||||
/* Save the new CPSDVSR and SCR values */
|
||||
|
||||
ssp_putreg(priv, LPC17_SSP_CPSR_OFFSET, divisor);
|
||||
ssp_putreg(priv, LPC17_SSP_CPSR_OFFSET, cpsdvsr);
|
||||
|
||||
regval = ssp_getreg(priv, LPC17_SSP_CR0_OFFSET);
|
||||
regval &= ~SSP_CR0_SCR_MASK;
|
||||
regval |= ((scr - 1) << SSP_CR0_SCR_SHIFT);
|
||||
ssp_putreg(priv, LPC17_SSP_CR0_OFFSET, regval);
|
||||
|
||||
/* Calculate the new actual */
|
||||
|
||||
actual = SSP_CLOCK / divisor;
|
||||
actual = SSP_CLOCK / (cpsdvsr * scr);
|
||||
|
||||
/* Save the frequency setting */
|
||||
|
||||
|
@ -453,10 +453,11 @@ CONFIGURATION
|
||||
following ways:
|
||||
|
||||
CONFIG_INPUT=y : Enable support for input devices
|
||||
CONFIG_GPIO_IRQ=y : GPIO interrupt support
|
||||
CONFIG_INPUT_ADS7843E=y : Enable support for the XPT2048
|
||||
CONFIG_ADS7843E_SPIDEV=1 : Use SSP1 for communication
|
||||
CONFIG_SPI=y : Enable SPI support
|
||||
CONFIG_SPI_EXCHANGE=n : exchange() method is not supported
|
||||
CONFIG_GPIO_IRQ=y : GPIO interrupt support
|
||||
CONFIG_LPC17_SSP1=y : Enable support for SSP1
|
||||
CONFIG_EXAMPLES_TOUCHSCREEN=y : Enable the touchscreen built-int test
|
||||
CONFIG_EXAMPLES_TOUCHSCREEN_BUILTIN=y
|
||||
@ -466,7 +467,8 @@ CONFIGURATION
|
||||
You will also have to disable SD card support to use this test. The
|
||||
SD card detect (CD) signal is on P0[13]. This signal is shared. It
|
||||
is also used for MOSI1 and USB_UP_LED. The CD pin may be disconnected.
|
||||
There is a jumper on board that enables the CD pin.
|
||||
There is a jumper on board that enables the CD pin. OR, you can simply
|
||||
remove the SD module so that it does not drive the CD pin.
|
||||
|
||||
CONFIG_LPC17_GPDMA=n : No DMA
|
||||
CONFIG_ARCH_DMA=n
|
||||
|
@ -407,12 +407,6 @@
|
||||
#define GPIO_SSP1_MOSI GPIO_SSP1_MOSI_2
|
||||
#define GPIO_SSP1_SCK GPIO_SSP1_SCK_2
|
||||
|
||||
#define GPIO_SSP1_SSEL_1 (GPIO_ALT2 | GPIO_PULLUP | GPIO_PORT0 | GPIO_PIN6)
|
||||
#define GPIO_SSP1_SSEL_2 (GPIO_ALT2 | GPIO_PULLUP | GPIO_PORT0 | GPIO_PIN14)
|
||||
#define GPIO_SSP1_SSEL_3 (GPIO_ALT5 | GPIO_PULLUP | GPIO_PORT1 | GPIO_PIN26)
|
||||
#define GPIO_SSP1_SSEL_4 (GPIO_ALT3 | GPIO_PULLUP | GPIO_PORT4 | GPIO_PIN21)
|
||||
|
||||
|
||||
/************************************************************************************
|
||||
* Public Types
|
||||
************************************************************************************/
|
||||
|
@ -174,7 +174,7 @@ void lpc17_ssp1select(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool sel
|
||||
sspdbg("devid: %d CS: %s\n", (int)devid, selected ? "assert" : "de-assert");
|
||||
if (devid == SPIDEV_TOUCHSCREEN)
|
||||
{
|
||||
/* Assert/de-assert the CS pin to the card */
|
||||
/* Assert/de-assert the CS pin to the touchscreen */
|
||||
|
||||
ssp_dumpgpio(GPIO_TC_CS, "lpc17_ssp1select() Entry");
|
||||
lpc17_gpiowrite(GPIO_TC_CS, !selected);
|
||||
|
@ -80,17 +80,27 @@
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_ADS7843E_SPIDEV
|
||||
# define CONFIG_ADS7843E_SPIDEV 3
|
||||
# define CONFIG_ADS7843E_SPIDEV 1
|
||||
#endif
|
||||
|
||||
#if CONFIG_ADS7843E_SPIDEV != 3
|
||||
# error "CONFIG_ADS7843E_SPIDEV must be three"
|
||||
#if CONFIG_ADS7843E_SPIDEV != 1
|
||||
# error "CONFIG_ADS7843E_SPIDEV must be one"
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_ADS7843E_DEVMINOR
|
||||
# define CONFIG_ADS7843E_DEVMINOR 0
|
||||
#endif
|
||||
|
||||
/* REVISIT: Currently, XPT2046 reports BUSY all of the time. This is
|
||||
* probably GPIO setting issues. But there is this cryptic statement in
|
||||
* the XPT2046 spec: "No DCLK delay required with dedicated serial port."
|
||||
*
|
||||
* The busy state is used by the XPT2046 driver to control the delay
|
||||
* between sending the command, then reading the returned data.
|
||||
*/
|
||||
|
||||
#define XPT2046_NO_BUSY 1
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
@ -100,12 +110,12 @@
|
||||
****************************************************************************/
|
||||
|
||||
/* IRQ/GPIO access callbacks. These operations all hidden behind
|
||||
* callbacks to isolate the ADS7843E driver from differences in GPIO
|
||||
* callbacks to isolate the XPT2046 driver from differences in GPIO
|
||||
* interrupt handling by varying boards and MCUs. If possible,
|
||||
* interrupts should be configured on both rising and falling edges
|
||||
* so that contact and loss-of-contact events can be detected.
|
||||
*
|
||||
* attach - Attach the ADS7843E interrupt handler to the GPIO interrupt
|
||||
* attach - Attach the XPT2046 interrupt handler to the GPIO interrupt
|
||||
* enable - Enable or disable the GPIO interrupt
|
||||
* clear - Acknowledge/clear any pending GPIO interrupt
|
||||
* pendown - Return the state of the pen down GPIO input
|
||||
@ -121,9 +131,9 @@ static bool tsc_pendown(FAR struct ads7843e_config_s *state);
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/* A reference to a structure of this type must be passed to the ADS7843E
|
||||
/* A reference to a structure of this type must be passed to the XPT2046
|
||||
* driver. This structure provides information about the configuration
|
||||
* of the ADS7843E and provides some board-specific hooks.
|
||||
* of the XPT2046 and provides some board-specific hooks.
|
||||
*
|
||||
* Memory for this structure is provided by the caller. It is not copied
|
||||
* by the driver and is presumed to persist while the driver is active.
|
||||
@ -144,12 +154,12 @@ static struct ads7843e_config_s g_tscinfo =
|
||||
****************************************************************************/
|
||||
|
||||
/* IRQ/GPIO access callbacks. These operations all hidden behind
|
||||
* callbacks to isolate the ADS7843E driver from differences in GPIO
|
||||
* callbacks to isolate the XPT2046 driver from differences in GPIO
|
||||
* interrupt handling by varying boards and MCUs. If possible,
|
||||
* interrupts should be configured on both rising and falling edges
|
||||
* so that contact and loss-of-contact events can be detected.
|
||||
*
|
||||
* attach - Attach the ADS7843E interrupt handler to the GPIO interrupt
|
||||
* attach - Attach the XPT2046 interrupt handler to the GPIO interrupt
|
||||
* enable - Enable or disable the GPIO interrupt
|
||||
* clear - Acknowledge/clear any pending GPIO interrupt
|
||||
* pendown - Return the state of the pen down GPIO input
|
||||
@ -183,6 +193,20 @@ static void tsc_clear(FAR struct ads7843e_config_s *state)
|
||||
|
||||
static bool tsc_busy(FAR struct ads7843e_config_s *state)
|
||||
{
|
||||
/* The busy state is used by the XPT2046 driver to control the delay
|
||||
* between sending the command, then reading the returned data.
|
||||
*/
|
||||
|
||||
#ifdef XPT2046_NO_BUSY
|
||||
/* REVISIT: Currently, XPT2046 reports BUSY all of the time. This is
|
||||
* probably GPIO setting issues. But there is this cryptic statement in
|
||||
* the XPT2046 spec: "No DCLK delay required with dedicated serial port."
|
||||
*/
|
||||
|
||||
return false;
|
||||
|
||||
#else /* XPT2046_NO_BUSY */
|
||||
|
||||
#if defined(CONFIG_DEBUG_INPUT) && defined(CONFIG_DEBUG_VERBOSE)
|
||||
static bool last = (bool)-1;
|
||||
#endif
|
||||
@ -199,6 +223,8 @@ static bool tsc_busy(FAR struct ads7843e_config_s *state)
|
||||
#endif
|
||||
|
||||
return busy;
|
||||
|
||||
#endif /* XPT2046_NO_BUSY */
|
||||
}
|
||||
|
||||
static bool tsc_pendown(FAR struct ads7843e_config_s *state)
|
||||
@ -237,37 +263,50 @@ static bool tsc_pendown(FAR struct ads7843e_config_s *state)
|
||||
|
||||
int arch_tcinitialize(int minor)
|
||||
{
|
||||
static bool initialized = false;
|
||||
FAR struct spi_dev_s *dev;
|
||||
int ret;
|
||||
|
||||
idbg("minor %d\n", minor);
|
||||
idbg("initialized:%d minor:%d\n", initialized, minor);
|
||||
DEBUGASSERT(minor == 0);
|
||||
|
||||
/* Configure and enable the ADS7843E PENIRQ pin as an interrupting input. */
|
||||
/* Since there is no uninitialized logic, this initialization can be
|
||||
* performed only one time.
|
||||
*/
|
||||
|
||||
(void)lpc17_configgpio(GPIO_TC_PENIRQ);
|
||||
|
||||
/* Configure the ADS7843E BUSY pin as a normal input. */
|
||||
|
||||
(void)lpc17_configgpio(GPIO_TC_BUSY);
|
||||
|
||||
/* Get an instance of the SPI interface */
|
||||
|
||||
dev = lpc17_sspinitialize(CONFIG_ADS7843E_SPIDEV);
|
||||
if (!dev)
|
||||
if (!initialized)
|
||||
{
|
||||
idbg("Failed to initialize SPI bus %d\n", CONFIG_ADS7843E_SPIDEV);
|
||||
return -ENODEV;
|
||||
}
|
||||
/* Configure and enable the XPT2046 PENIRQ pin as an interrupting input. */
|
||||
|
||||
/* Initialize and register the SPI touschscreen device */
|
||||
(void)lpc17_configgpio(GPIO_TC_PENIRQ);
|
||||
|
||||
ret = ads7843e_register(dev, &g_tscinfo, CONFIG_ADS7843E_DEVMINOR);
|
||||
if (ret < 0)
|
||||
{
|
||||
idbg("Failed to initialize SPI bus %d\n", CONFIG_ADS7843E_SPIDEV);
|
||||
/* up_spiuninitialize(dev); */
|
||||
return -ENODEV;
|
||||
/* Configure the XPT2046 BUSY pin as a normal input. */
|
||||
|
||||
#ifndef XPT2046_NO_BUSY
|
||||
(void)lpc17_configgpio(GPIO_TC_BUSY);
|
||||
#endif
|
||||
|
||||
/* Get an instance of the SPI interface */
|
||||
|
||||
dev = lpc17_sspinitialize(CONFIG_ADS7843E_SPIDEV);
|
||||
if (!dev)
|
||||
{
|
||||
idbg("Failed to initialize SPI bus %d\n", CONFIG_ADS7843E_SPIDEV);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Initialize and register the SPI touchscreen device */
|
||||
|
||||
ret = ads7843e_register(dev, &g_tscinfo, CONFIG_ADS7843E_DEVMINOR);
|
||||
if (ret < 0)
|
||||
{
|
||||
idbg("Failed to register touchscreen device minor=%d\n",
|
||||
CONFIG_ADS7843E_DEVMINOR);
|
||||
/* up_spiuninitialize(dev); */
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
return OK;
|
||||
@ -291,7 +330,7 @@ int arch_tcinitialize(int minor)
|
||||
|
||||
void arch_tcuninitialize(void)
|
||||
{
|
||||
/* No support for un-initializing the touchscreen ADS7843E device yet */
|
||||
/* No support for un-initializing the touchscreen XPT2046 device yet */
|
||||
}
|
||||
|
||||
#endif /* CONFIG_INPUT_ADS7843E */
|
||||
|
@ -57,13 +57,27 @@ config ADS7843E_NPOLLWAITERS
|
||||
---help---
|
||||
Maximum number of threads that can be waiting on poll()
|
||||
|
||||
config ADS7843E_SPIDEV
|
||||
int "SPI bus number"
|
||||
default 0
|
||||
---help---
|
||||
Selects the SPI bus number identying that SPI interface that
|
||||
connects the ADS843E to the MCU.
|
||||
|
||||
config ADS7843E_DEVMINOR
|
||||
int "Input device minor number"
|
||||
default 0
|
||||
---help---
|
||||
The ADS7843E device will be registered as /dev/inputN where N is the
|
||||
value provided by this setting.
|
||||
|
||||
config ADS7843E_SPIMODE
|
||||
int "SPI mode"
|
||||
default 0
|
||||
range 0,3
|
||||
---help---
|
||||
Controls the SPI mode. The device should work in mode 0, but sometimes
|
||||
you need to experiment.
|
||||
Controls the SPI mode. The device should work in mode 0, but
|
||||
sometimes you need to experiment.
|
||||
|
||||
config ADS7843E_FREQUENCY
|
||||
int "SPI frequency"
|
||||
|
Loading…
x
Reference in New Issue
Block a user