Fix SAMA5D2 ADC and TSD problems

SAMA5Dx ADC and TSD fixes

Ensures ADC and TSD work together. TSD now works on SAMA5D2 and should be OK, still, for other SAMA5D familiy members

Fix CI error

checkpatch error

Update arch/arm/src/sama5/sam_tsd.h

Squash commits to arch/arm/src/sama5/hardware/sam_adc.h

Update arch/arm/src/sama5/hardware/sam_adc.h

Update arch/arm/src/sama5/hardware/sam_adc.h

Update arch/arm/src/sama5/hardware/sam_adc.h

Update arch/arm/src/sama5/hardware/sam_adc.h

Update arch/arm/src/sama5/hardware/sam_adc.h

Update arch/arm/src/sama5/hardware/sam_adc.h

Update arch/arm/src/sama5/hardware/sam_adc.h

Squash commits to arch/arm/src/sama5/sam_tsd.c

Update arch/arm/src/sama5/sam_tsd.c

Update arch/arm/src/sama5/sam_tsd.c

Update arch/arm/src/sama5/sam_tsd.c

Update sam_tsd.c

Fixes after feedback from PR and additional testing

Update sam_tc.c

checkpatch.sh error was missed when fixing someone else's error...

feedback corrections missed

Co-Authored-By: Xiang Xiao <xiaoxiang781216@gmail.com>
Co-Authored-By: Petro Karashchenko <petro.karashchenko@gmail.com>

squashed everything after 248072e02C
This commit is contained in:
TimJTi 2022-11-14 18:04:46 +00:00 committed by Xiang Xiao
parent 498bc98b1b
commit a634da9a30
6 changed files with 471 additions and 89 deletions

View File

@ -3235,6 +3235,7 @@ config SAMA5_ADC_DMASAMPLES
config SAMA5_ADC_AUTOCALIB
bool "ADC auto-calibration"
depends on ARCH_CHIP_SAMA5D3
default n
---help---
Perform ADC auto-calibration during the ADC initialization sequence
@ -3251,11 +3252,12 @@ config SAMA5_ADC_ANARCH
default n
---help---
This option allows you to select different gain, offset, and single
vs. differential modes for each channel.
vs. differential modes for each channel, depending on ARCH.
if SAMA5_ADC_ANARCH
menu "Channel gain"
depends on ARCH_CHIP_SAMA5D
config SAMA5_ADC_GAIN0
int "Channel 0 gain"
@ -3392,6 +3394,7 @@ config SAMA5_ADC_GAIN11
endmenu # Channel gain
menu "Channel offsets"
depends on ARCH_CHIP_SAMA5D3
config SAMA5_ADC_OFFSET0
bool "Channel 0 offset"
@ -3492,6 +3495,7 @@ config SAMA5_ADC_OFFSET11
endmenu # Channel offsets
menu "Channel differential mode"
depends on ARCH_CHIP_SAMA5D2 || ARCH_CHIP_SAMA5D3
config SAMA5_ADC_DIFFMODE0
bool "Channel 0 differential mode"
@ -3585,25 +3589,28 @@ if !SAMA5_ADC_ANARCH
config SAMA5_ADC_GAIN
int "Analog gain"
default 1
depends on SAMA5_ADC_CHAN0
depends on ARCH_CHIP_SAMA5D3
range 0 3
---help---
Valid gain settings are {0, 1, 2, 3} which may be interpreted as
either {1, 1, 2, 4} if the channels are configured for single ended
mode or as {0.5, 1, 2, 2} if the channels are configured for
differential mode.
differential mode. Applies to all channels.
config SAMA5_ADC_OFFSET
bool "Offset"
default n
depends on ARCH_CHIP_SAMA5D3
---help---
Center the analog signal on Vrefin/2 before the gain scaling.
Center the analog signal on Vrefin/2 before the gain scaling for
all channels.
config SAMA5_ADC_DIFFMODE
bool "Differential mode"
default n
---help---
Selects differential (vs. single-ended mode)
Selects differential (vs. single-ended mode) for all channels.
endif # !SAMA5_ADC_ANARCH
@ -3620,6 +3627,16 @@ config SAMA5_ADC_SWTRIG
---help---
A-to-D Conversion is initiated only by software via an ioctl()
config SAMA5_ADC_PERIODIC_TRIG
bool "Periodic trigger"
---help---
A-to-D Conversion is triggered periodically
config SAMA5_ADC_CONTINUOUS_TRIG
bool "Continuous trigger"
---help---
A-to-D Conversion is continuous
config SAMA5_ADC_ADTRG
bool "External trigger via the ADTRG pin"
---help---
@ -3632,12 +3649,45 @@ config SAMA5_ADC_TIOATRIG
A-to-D Conversion is initiated the A output from one of
Timer/Counter 0 channels.
config SAMA5_ADC_PWMTRIG
bool "PWM Event trigger"
depends on SAMA5_PWM
---help---
A-to-D Conversion is initiated from the PWM event lines
config SAMA5_ADC_RTCOUT
bool "RTC Out trigger"
depends on SAMA5_RTC
depends on ARCH_CHIP_SAMA5D2
---help---
A-to-D Conversion is initiated from the RTC output
endchoice # Trigger mode
if SAMA5_ADC_PWMTRIG
choice
prompt "PWM Event Line Selection"
default SAMA5_ADC_PWMTRIG_LINE0
config SAMA5_ADC_PWM_TRIG_LINE0
bool "PWM event Line 0"
---help---
Trigger A-to-D conversion on PWM event line 0
config SAMA5_ADC_PWM_TRIG_LINE1
bool "PWM event Line 1"
---help---
Trigger A-to-D conversion on PWM event line 1
endchoice # PWM Event Line Selection
endif # SAMA5_ADC_PWMTRIG
if SAMA5_ADC_ADTRG || SAMA5_ADC_TIOATRIG || SAMA5_ADC_PWMTRIG || SAMA5_ADC_RTCOUT
choice
prompt "ADTRG edge"
default SAMA5_ADC_ADTRG_BOTH
depends on SAMA5_ADC_ADTRG
config SAMA5_ADC_ADTRG_RISING
bool "Rising edge"
@ -3655,6 +3705,7 @@ config SAMA5_ADC_ADTRG_BOTH
Trigger A-to-D conversion on both edges of the ADTRG signal
endchoice # ADTRG edge
endif # SAMA5_ADC_ADTRG
if SAMA5_ADC_TIOATRIG
@ -3717,6 +3768,17 @@ config SAMA5_ADC_TIOA_BOTH
endchoice # ADTRG edge
endif # SAMA5_ADC_TIOATRIG
if SAMA5_ADC_PERIODIC_TRIG
config SAMA5_ADC_TRIGGER_PERIOD
int "ADC Periodic Trigger Rate, useconds"
default 50000
---help---
This setting determines the periodic sample trigger rate in useconds.
endif # SAMA5_ADC_TRIGGER_PERIOD
endmenu # ADC Trigger Selection
endif # SAMA5_ADC_HAVE_CHAN
@ -3798,6 +3860,12 @@ config SAMA5_TSD_NPOLLWAITERS
---help---
Maximum number of threads that can be waiting on poll()
config SAMA5_TSD_AUTOCALIB
bool "TSD auto-calibration"
default y
---help---
Perform TSD auto-calibration during the TSD initialization sequence
endif # SAMA5_TSD
endmenu # Touchscreen Configuration
endif # SAMA5_ADC

View File

@ -505,7 +505,7 @@
#define SAM_AIC_VBASE (SAM_PERIPHC_VSECTION+SAM_AIC_OFFSET)
#define SAM_TWI1_VBASE (SAM_PERIPHC_VSECTION+SAM_TWI1_OFFSET)
#define SAM_UDPHS_VBASE (SAM_PERIPHC_VSECTION+SAM_UDPHS_OFFSET)
#define SAM_ADC_VBASE (SAM_PERIPHC_VSECTION+SAM_ADC_OFFSET)
#define SAM_TSADC_VBASE (SAM_PERIPHC_VSECTION+SAM_ADC_OFFSET)
#define SAM_PIO_VBASE (SAM_PERIPHC_VSECTION+SAM_PIO_OFFSET)
#define SAM_MATRIX32_VBASE (SAM_PERIPHC_VSECTION+SAM_MATRIX1_OFFSET)
#define SAM_SECUMOD_VBASE (SAM_PERIPHC_VSECTION+SAM_SECUMOD_OFFSET)

View File

@ -36,7 +36,7 @@
/* General definitions ******************************************************/
#if defined(ATSAMA5D3)
#if defined(ATSAMA5D3) || defined(ATSAMA5D2)
# define SAM_ADC_NCHANNELS 12 /* 12 ADC Channels */
#elif defined(ATSAMA5D4)
# define SAM_ADC_NCHANNELS 5 /* 5 ADC Channels */
@ -67,9 +67,10 @@
#ifdef ATSAMA5D3
# define SAM_ADC_CGR_OFFSET 0x0048 /* Channel Gain Register */
# define SAM_ADC_COR_OFFSET 0x004c /* Channel Offset Register */
#endif
#define SAM_ADC_COR_OFFSET 0x004c /* Channel Offset Register */
#define SAM_ADC_CDR_OFFSET(n) (0x0050+((n)<<2))
#define SAM_ADC_CDR0_OFFSET 0x0050 /* Channel Data Register 0 */
#define SAM_ADC_CDR1_OFFSET 0x0054 /* Channel Data Register 1 */
@ -77,7 +78,7 @@
#define SAM_ADC_CDR3_OFFSET 0x005c /* Channel Data Register 3 */
#define SAM_ADC_CDR4_OFFSET 0x0060 /* Channel Data Register 4 */
#ifdef ATSAMA5D3
#if defined(ATSAMA5D3) || defined(ATSAMA5D2)
# define SAM_ADC_CDR5_OFFSET 0x0064 /* Channel Data Register 5 */
# define SAM_ADC_CDR6_OFFSET 0x0068 /* Channel Data Register 6 */
# define SAM_ADC_CDR7_OFFSET 0x006c /* Channel Data Register 7 */
@ -119,6 +120,9 @@
#ifdef ATSAMA5D3
# define SAM_ADC_CGR (SAM_TSADC_VBASE+SAM_ADC_CGR_OFFSET)
#endif
#if defined(ATSAMA5D3) || defined(ATSAMA5D2)
# define SAM_ADC_COR (SAM_TSADC_VBASE+SAM_ADC_COR_OFFSET)
#endif
@ -129,7 +133,7 @@
#define SAM_ADC_CDR3 (SAM_TSADC_VBASE+SAM_ADC_CDR3_OFFSET)
#define SAM_ADC_CDR4 (SAM_TSADC_VBASE+SAM_ADC_CDR4_OFFSET)
#ifdef ATSAMA5D3
#if defined(ATSAMA5D3) || defined(ATSAMA5D2)
# define SAM_ADC_CDR5 (SAM_TSADC_VBASE+SAM_ADC_CDR5_OFFSET)
# define SAM_ADC_CDR6 (SAM_TSADC_VBASE+SAM_ADC_CDR6_OFFSET)
# define SAM_ADC_CDR7 (SAM_TSADC_VBASE+SAM_ADC_CDR7_OFFSET)
@ -170,6 +174,8 @@
# define ADC_MR_TRGSEL_TIOA2 (3 << ADC_MR_TRGSEL_SHIFT) /* TIOA2 */
# define ADC_MR_TRGSEL_PWM0 (4 << ADC_MR_TRGSEL_SHIFT) /* PWM Event Line 0 */
# define ADC_MR_TRGSEL_PWM1 (5 << ADC_MR_TRGSEL_SHIFT) /* PWM Event Line 1 */
# define ADC_MR_TRGSEL_TIOA3 (6 << ADC_MR_TRGSEL_SHIFT) /* TIOA3 */
# define ADC_MR_TRGSEL_RTC (7 << ADC_MR_TRGSEL_SHIFT) /* RTC Out */
#ifdef ATSAMA5D4
# define ADC_MR_LOWRES (1 << 4) /* Bit 4: LOWRES: Resolution */
@ -186,13 +192,13 @@
# define ADC_MR_PRESCAL(n) ((uint32_t)(n) << ADC_MR_PRESCAL_SHIFT)
#define ADC_MR_STARTUP_SHIFT (16) /* Bits 16-19: Start Up Time */
#define ADC_MR_STARTUP_MASK (15 << ADC_MR_STARTUP_SHIFT)
# define ADC_MR_STARTUP_0 (0 << ADC_MR_STARTUP_SHIFT) /* 0 periods of ADCClock */
# define ADC_MR_STARTUP_8 (1 << ADC_MR_STARTUP_SHIFT) /* 8 periods of ADCClock */
# define ADC_MR_STARTUP_16 (2 << ADC_MR_STARTUP_SHIFT) /* 16 periods of ADCClock */
# define ADC_MR_STARTUP_24 (3 << ADC_MR_STARTUP_SHIFT) /* 24 periods of ADCClock */
# define ADC_MR_STARTUP_64 (4 << ADC_MR_STARTUP_SHIFT) /* 64 periods of ADCClock */
# define ADC_MR_STARTUP_80 (5 << ADC_MR_STARTUP_SHIFT) /* 80 periods of ADCClock */
# define ADC_MR_STARTUP_96 (6 << ADC_MR_STARTUP_SHIFT) /* 96 periods of ADCClock */
# define ADC_MR_STARTUP_0 (0 << ADC_MR_STARTUP_SHIFT) /* 0 periods of ADCClock */
# define ADC_MR_STARTUP_8 (1 << ADC_MR_STARTUP_SHIFT) /* 8 periods of ADCClock */
# define ADC_MR_STARTUP_16 (2 << ADC_MR_STARTUP_SHIFT) /* 16 periods of ADCClock */
# define ADC_MR_STARTUP_24 (3 << ADC_MR_STARTUP_SHIFT) /* 24 periods of ADCClock */
# define ADC_MR_STARTUP_64 (4 << ADC_MR_STARTUP_SHIFT) /* 64 periods of ADCClock */
# define ADC_MR_STARTUP_80 (5 << ADC_MR_STARTUP_SHIFT) /* 80 periods of ADCClock */
# define ADC_MR_STARTUP_96 (6 << ADC_MR_STARTUP_SHIFT) /* 96 periods of ADCClock */
# define ADC_MR_STARTUP_112 (7 << ADC_MR_STARTUP_SHIFT) /* 112 periods of ADCClock */
# define ADC_MR_STARTUP_512 (8 << ADC_MR_STARTUP_SHIFT) /* 512 periods of ADCClock */
# define ADC_MR_STARTUP_576 (9 << ADC_MR_STARTUP_SHIFT) /* 576 periods of ADCClock */
@ -204,13 +210,22 @@
# define ADC_MR_STARTUP_960 (15 << ADC_MR_STARTUP_SHIFT) /* 960 periods of ADCClock */
#ifdef ATSAMA5D3
# define ADC_MR_SETTLING_SHIFT (20) /* Bits 20-21: Analog Settling Time */
# define ADC_MR_SETTLING_SHIFT (20) /* Bits 20-21: Analog Settling Time */
# define ADC_MR_SETTLING_MASK (15 << ADC_MR_SETTLING_SHIFT)
# define ADC_MR_SETTLING_3 (0 << ADC_MR_SETTLING_SHIFT) /* 3 periods of ADCClock */
# define ADC_MR_SETTLING_5 (1 << ADC_MR_SETTLING_SHIFT) /* 5 periods of ADCClock */
# define ADC_MR_SETTLING_9 (2 << ADC_MR_SETTLING_SHIFT) /* 9 periods of ADCClock */
# define ADC_MR_SETTLING_17 (3 << ADC_MR_SETTLING_SHIFT) /* 17 periods of ADCClock */
# define ADC_MR_SETTLING_3 (0 << ADC_MR_SETTLING_SHIFT) /* 3 periods of ADCClock */
# define ADC_MR_SETTLING_5 (1 << ADC_MR_SETTLING_SHIFT) /* 5 periods of ADCClock */
# define ADC_MR_SETTLING_9 (2 << ADC_MR_SETTLING_SHIFT) /* 9 periods of ADCClock */
# define ADC_MR_SETTLING_17 (3 << ADC_MR_SETTLING_SHIFT) /* 17 periods of ADCClock */
#else
# define ADC_MR_SETTLING_SHIFT (20) /* Not present in SAMA5D2 or SAMA5D4 */
# define ADC_MR_SETTLING_MASK (0)
# define ADC_MR_SETTLING_3 (0 << ADC_MR_SETTLING_SHIFT) /* n/a periods of ADCClock */
# define ADC_MR_SETTLING_5 (0 << ADC_MR_SETTLING_SHIFT) /* n/a periods of ADCClock */
# define ADC_MR_SETTLING_9 (0 << ADC_MR_SETTLING_SHIFT) /* n/a periods of ADCClock */
# define ADC_MR_SETTLING_17 (0 << ADC_MR_SETTLING_SHIFT) /* n/a periods of ADCClock */
#endif
#if defined(ATSAMA5D3) || defined(ATSAMA5D2)
# define ADC_MR_ANACH (1 << 23) /* Bit 23: Analog Change */
#endif
@ -218,7 +233,7 @@
#define ADC_MR_TRACKTIM_MASK (15 << ADC_MR_TRACKTIM_SHIFT)
# define ADC_MR_TRACKTIM(n) ((uint32_t)(n) << ADC_MR_TRACKTIM_SHIFT)
#ifdef ATSAMA5D3
#if defined(ATSAMA5D3) || defined(ATSAMA5D2)
# define ADC_MR_TRANSFER_SHIFT (28) /* Bits 28-29: Transfer Period */
# define ADC_MR_TRANSFER_MASK (3 << ADC_MR_TRANSFER_SHIFT)
# define ADC_MR_TRANSFER (2 << ADC_MR_TRANSFER_SHIFT) /* Must be 2 */
@ -259,7 +274,7 @@
# define ADC_SEQR1_USCH8(v) ((uint32_t)(v) << ADC_SEQR1_USCH8_SHIFT)
#endif
#ifdef ATSAMA5D3
#if defined(ATSAMA5D3) || defined(ATSAMA5D2)
/* Channel Sequence Register 2 */
# define ADC_SEQR2_USCH_SHIFT(n) (((n)-9) << 2) /* n=9..11 */
@ -289,7 +304,7 @@
#define ADC_CH4 (1 << 4) /* Bit 4: Channel 4 Enable */
#define ADC_CH5 (1 << 5) /* Bit 5: Channel 5 Enable */
#ifdef ATSAMA5D3
#if defined(ATSAMA5D3) || defined(ATSAMA5D2)
# define ADC_CH6 (1 << 6) /* Bit 6: Channel 6 Enable */
# define ADC_CH7 (1 << 7) /* Bit 7: Channel 7 Enable */
# define ADC_CH8 (1 << 8) /* Bit 8: Channel 8 Enable */
@ -301,7 +316,7 @@
#define TSD_4WIRE_ALL (0x0000000f)
#define TSD_5WIRE_ALL (0x0000001f)
#if defined(ATSAMA5D3)
#if defined(ATSAMA5D3) || defined(ATSAMA5D2)
# define ADC_CHALL (0x00000fff)
#elif defined(ATSAMA5D4)
# define ADC_CHALL (0x0000001f)
@ -327,7 +342,7 @@
#define ADC_INT_EOC3 (1 << 3) /* Bit 3: End of Conversion 3 */
#define ADC_INT_EOC4 (1 << 4) /* Bit 4: End of Conversion 4 */
#if defined(ATSAMA5D3)
#if defined(ATSAMA5D3) || defined(ATSAMA5D2)
# define ADC_INT_EOC5 (1 << 5) /* Bit 5: End of Conversion 5 */
# define ADC_INT_EOC6 (1 << 6) /* Bit 6: End of Conversion 6 */
# define ADC_INT_EOC7 (1 << 7) /* Bit 7: End of Conversion 7 */
@ -355,7 +370,11 @@
#define ADC_INT_NOPEN (1 << 30) /* Bit 30: No Pen Contact Interrupt */
#define ADC_SR_PENS (1 << 31) /* Bit 31: Pen detect Status (SR only) */
#define ADC_INT_ALL (0xe7f00fff)
#if defined(ATSAMA5D3)
# define ADC_INT_ALL (0xe7f00fff)
#elif defined(ATSAMA5D2)
# define ADC_INT_ALL (0x67780fff)
#endif
/* Overrun Status Register */
@ -484,7 +503,12 @@
/* Channel Data Register */
#define ADC_CDR_DATA_SHIFT (0) /* Bits 0-11: Converted Data */
#define ADC_CDR_DATA_MASK (0xfff << ADC_CDR_DATA_SHIFT)
#if defined(ATSAMA5D2)
# define ADC_CDR_DATA_MASK (0x3fff << ADC_CDR_DATA_SHIFT)
#else
# define ADC_CDR_DATA_MASK (0xfff << ADC_CDR_DATA_SHIFT)
#endif
/* Compare Window Register */
@ -501,6 +525,12 @@
#define ADC_ACR_PENDETSENS_MASK (3 << ADC_ACR_PENDETSENS_SHIFT)
# define ADC_ACR_PENDETSENS(n) ((uint32_t)(n) << ADC_ACR_PENDETSENS_SHIFT)
#if defined(ATSAMA5D2)
# define ADC_ACR_IBTL_SHIFT (8) /* Bits 8-9: ADC Bias Current Control */
# define ADC_ACR_IBCTL_MASK (3 << ADC_ACR_IBTL_SHIFT)
# define ADC_ACR_IBCTL(n) ((uint32_t)(n) << ADC_ACR_IBTL_SHIFT)
#endif
/* Touchscreen Mode Register */
#define ADC_TSMR_TSMODE_SHIFT (0) /* Bit 0-1: Touchscreen Mode */

View File

@ -475,6 +475,7 @@ static void sam_adc_gain(struct sam_adc_s *priv);
static void sam_adc_analogchange(struct sam_adc_s *priv);
static void sam_adc_sequencer(struct sam_adc_s *priv);
static void sam_adc_channels(struct sam_adc_s *priv);
static void sam_adc_trigperiod(struct sam_adc_s *priv, uint32_t period);
#endif
/****************************************************************************
@ -834,6 +835,75 @@ static int sam_adc_dmasetup(struct sam_adc_s *priv, uint8_t *buffer,
}
#endif
/****************************************************************************
* Name: sam_tsd_trigperiod
*
* Description:
* Set the TGPER field of the TRGR register in order to define a periodic
* trigger perioc.
*
* Trigger Period = (TRGPER+1) / ADCCLK
*
* Input Parameters:
* priv - A reference to the touchscreen device structure
* time - The new trigger period in microseconds
*
* Returned Value:
* None
*
****************************************************************************/
static void sam_adc_trigperiod(struct sam_adc_s *priv, uint32_t period)
{
uint32_t trigper;
uint32_t regval;
uint32_t div;
/* Divide trigger period avoid overflows. Division by ten is awkard, but
* appropriate here because times are specified in decimal with lots of
* zeroes.
*/
div = 100000;
while (period >= 10 && div >= 10)
{
period /= 10;
div /= 10;
}
/* Calculate and adjust the scaled trigger period:
*
* Trigger Period = (TRGPER+1) / ADCCLK
*/
trigper = (period * BOARD_ADCCLK_FREQUENCY) / div;
if ((trigper % 10) != 0)
{
/* Handle partial values by not decrementing trigper. This is
* basically a 'ceil' operation.
*/
trigper /= 10;
}
else
{
/* The final value needs to be decrement by one */
trigper /= 10;
if (trigper > 0)
{
trigper--;
}
}
/* Set the calculated trigger period in the TRGR register */
regval = sam_adc_getreg(priv, SAM_ADC_TRGR);
regval &= ~ADC_TRGR_TRGPER_MASK;
regval |= ADC_TRGR_TRGPER(trigper);
sam_adc_putreg(priv, SAM_ADC_TRGR, regval);
}
/****************************************************************************
* ADC interrupt handling
****************************************************************************/
@ -865,7 +935,7 @@ static void sam_adc_endconversion(void *arg)
int ret;
DEBUGASSERT(priv != NULL);
ainfo("pending=%08x\n", priv->pending);
ainfo("pending=%08lx\n", priv->pending);
/* Get the set of unmasked, pending ADC interrupts */
@ -1027,9 +1097,7 @@ static int sam_adc_bind(struct adc_dev_s *dev,
static void sam_adc_reset(struct adc_dev_s *dev)
{
#ifdef CONFIG_SAMA5_ADC_DMA
struct sam_adc_s *priv = (struct sam_adc_s *)dev->ad_priv;
#endif
uint32_t regval;
ainfo("Resetting..\n");
@ -1069,10 +1137,13 @@ static void sam_adc_reset(struct adc_dev_s *dev)
/* Reset gain, offset, differential modes */
#if defined (ATSAMA5D3)
sam_adc_putreg(priv, SAM_ADC_CGR, 0);
#endif
sam_adc_putreg(priv, SAM_ADC_COR, 0);
#ifndef CONFIG_SAMA5_ADC_SWTRIG
#if !defined CONFIG_SAMA5_ADC_SWTRIG && !defined CONFIG_SAMA5_TSD
/* Select software trigger (i.e., basically no trigger) */
regval = sam_adc_getreg(priv, SAM_ADC_MR);
@ -1101,11 +1172,12 @@ static int sam_adc_setup(struct adc_dev_s *dev)
{
struct sam_adc_s *priv = (struct sam_adc_s *)dev->ad_priv;
uint32_t regval;
int ret;
ainfo("Setup\n");
/* Enable channel number tag. This bit will force the channel number
* (CHNB) to be included in the LDCR register content.
* (CHNB) to be included in the LDCR register content
*/
regval = sam_adc_getreg(priv, SAM_ADC_EMR);
@ -1121,7 +1193,7 @@ static int sam_adc_setup(struct adc_dev_s *dev)
sam_adc_channels(priv);
/* Enable/disable analog change. This feature permits different settings
* per channel.
* per channel
*/
sam_adc_analogchange(priv);
@ -1153,6 +1225,10 @@ static int sam_adc_setup(struct adc_dev_s *dev)
#endif
/* Now we are initialized */
priv->initialized = true;
/* Configure trigger mode and start conversion */
return sam_adc_trigger(priv);
@ -1179,6 +1255,11 @@ static void sam_adc_shutdown(struct adc_dev_s *dev)
sam_adc_reset(dev);
#ifndef CONFIG_SAMA5_TSD
/* doing this if the TSD is required will stop it working */
/* Needs revisit */
/* Disable ADC interrupts at the level of the AIC */
up_disable_irq(SAM_IRQ_ADC);
@ -1186,6 +1267,7 @@ static void sam_adc_shutdown(struct adc_dev_s *dev)
/* Then detach the ADC interrupt handler. */
irq_detach(SAM_IRQ_ADC);
#endif
}
/****************************************************************************
@ -1335,7 +1417,7 @@ static int sam_adc_settimer(struct sam_adc_s *priv, uint32_t frequency,
priv->tc = sam_tc_allocate(channel, mode);
if (!priv->tc)
{
aerr("ERROR: Failed to allocate channel %d mode %08" PRIx32 "\n",
aerr("ERROR: Failed to allocate channel %d mode %08x\n",
channel, mode);
return -EINVAL;
}
@ -1413,17 +1495,33 @@ static int sam_adc_trigger(struct sam_adc_s *priv)
/* Configure the software trigger */
regval = sam_adc_getreg(priv, SAM_ADC_MR);
regval &= ~ADC_MR_TRGSEL_MASK;
sam_adc_putreg(priv, SAM_ADC_MR, regval);
/* No trigger, only software trigger can start conversions */
regval = sam_adc_getreg(priv, SAM_ADC_TRGR);
regval &= ~ADC_TRGR_TRGMOD_MASK;
regval |= ADC_TRGR_TRGMOD_NOTRIG;
sam_adc_putreg(priv, SAM_ADC_TRGR, regval);
#elif defined(CONFIG_SAMA5_ADC_PERIODIC_TRIG)
ainfo("Setup Periodic Trigger\n");
/* Configure the trigger to be periodic */
sam_adc_trigperiod(priv, CONFIG_SAMA5_ADC_TRIGGER_PERIOD);
regval = sam_adc_getreg(priv, SAM_ADC_TRGR);
regval &= ~ADC_TRGR_TRGMOD_MASK;
regval |= ADC_TRGR_TRGMOD_PERIOD;
sam_adc_putreg(priv, SAM_ADC_TRGR, regval);
#elif defined(CONFIG_SAMA5_ADC_CONTINUOUS_TRIG)
ainfo("Setup Continuous Trigger\n");
/* Configure the trigger to be continuous */
regval = sam_adc_getreg(priv, SAM_ADC_TRGR);
regval &= ~ADC_TRGR_TRGMOD_MASK;
regval |= ADC_TRGR_TRGMOD_CONT;
sam_adc_putreg(priv, SAM_ADC_TRGR, regval);
#elif defined(CONFIG_SAMA5_ADC_ADTRG)
ainfo("Setup ADTRG trigger\n");
@ -1431,7 +1529,70 @@ static int sam_adc_trigger(struct sam_adc_s *priv)
regval = sam_adc_getreg(priv, SAM_ADC_MR);
regval &= ~ADC_MR_TRGSEL_MASK;
regval |= ADC_MR_TRGSEL_ADC_ADTRIG;
regval |= ADC_MR_TRGSEL_ADTRG;
sam_adc_putreg(priv, SAM_ADC_MR, regval);
/* External trigger edge selection */
regval = sam_adc_getreg(priv, SAM_ADC_TRGR);
regval &= ~ADC_TRGR_TRGMOD_MASK;
#if defined(CONFIG_SAMA5_ADC_ADTRG_RISING)
regval |= ADC_TRGR_TRGMOD_EXTRISE;
#elif defined(CONFIG_SAMA5_ADC_ADTRG_FALLING)
regval |= ADC_TRGR_TRGMOD_EXTFALL;
#elif defined(CONFIG_SAMA5_ADC_ADTRG_BOTH)
regval |= ADC_TRGR_TRGMOD_EXTBOTH;
#else
# error External trigger edge not defined
#endif
sam_adc_putreg(priv, SAM_ADC_TRGR, regval);
#elif defined(CONFIG_SAMA5_ADC_PWMTRIG)
ainfo("Setup PWM trigger\n");
/* Configure the trigger via the PWM event lines */
regval = sam_adc_getreg(priv, SAM_ADC_MR);
regval &= ~ADC_MR_TRGSEL_MASK;
#if defined(CONFIG_SAMA5_ADC_PWM_TRIG_LINE0)
regval |= ADC_MR_TRGSEL_PWM0;
#elif defined(CONFIG_SAMA5_ADC_PWM_TRIG_LINE1)
regval |= ADC_MR_TRGSEL_PWM1;
#else
# error PWM event line not defined
#endif
sam_adc_putreg(priv, SAM_ADC_MR, regval);
/* External trigger edge selection */
regval = sam_adc_getreg(priv, SAM_ADC_TRGR);
regval &= ~ADC_TRGR_TRGMOD_MASK;
#if defined(CONFIG_SAMA5_ADC_ADTRG_RISING)
regval |= ADC_TRGR_TRGMOD_EXTRISE;
#elif defined(CONFIG_SAMA5_ADC_ADTRG_FALLING)
regval |= ADC_TRGR_TRGMOD_EXTFALL;
#elif defined(CONFIG_SAMA5_ADC_ADTRG_BOTH)
regval |= ADC_TRGR_TRGMOD_EXTBOTH;
#else
# error External trigger edge not defined
#endif
sam_adc_putreg(priv, SAM_ADC_TRGR, regval);
#elif defined(CONFIG_SAMA5_ADC_RTCOUT)
ainfo("Setup RTC trigger\n");
/* Configure the trigger via the PWM event lines */
regval = sam_adc_getreg(priv, SAM_ADC_MR);
regval &= ~ADC_MR_TRGSEL_MASK;
regval |= ADC_MR_TRGSEL_RTC;
sam_adc_putreg(priv, SAM_ADC_MR, regval);
/* External trigger edge selection */
@ -1674,7 +1835,8 @@ static void sam_adc_offset(struct sam_adc_s *priv)
static void sam_adc_gain(struct sam_adc_s *priv)
{
#ifdef CONFIG_SAMA5_ADC_ANARCH
#ifdef ATSAMA5D3
# ifdef CONFIG_SAMA5_ADC_ANARCH
uint32_t regval;
ainfo("Entry\n");
@ -1728,7 +1890,8 @@ static void sam_adc_gain(struct sam_adc_s *priv)
/* Set GAIN0 only. GAIN0 will be used for all channels. */
sam_adc_putreg(priv, SAM_ADC_CGR, ADC_CGR_GAIN0(CONFIG_SAMA5_ADC_GAIN));
#endif
#endif /* CONFIG_SAMA5_ADC_ANARCH */
#endif /* ATSAMA5D3 */
}
/****************************************************************************
@ -2050,9 +2213,17 @@ struct adc_dev_s *sam_adc_initialize(void)
/* Initialize the public ADC device data structure */
#ifdef SAMA5_ADC_HAVE_CHANNELS
g_adcdev.ad_ops = &g_adcops;
priv->dev = &g_adcdev;
#endif
g_adcdev.ad_priv = priv;
/* Initialize the private ADC device data structure */
nxmutex_init(&priv->lock);
priv->cb = NULL;
#ifdef CONFIG_SAMA5_ADC_DMA
/* Allocate a DMA channel from DMAC1 */
@ -2132,6 +2303,9 @@ struct adc_dev_s *sam_adc_initialize(void)
ADC_MR_SETTLING_MASK);
regval |= (ADC_MR_STARTUP_512 | ADC_MR_TRACKTIM(0) |
ADC_MR_SETTLING_17);
#if defined ATSAMA5D2
regval |= ADC_MR_TRANSFER;
#endif
sam_adc_putreg(priv, SAM_ADC_MR, regval);
/* Attach the ADC interrupt */

View File

@ -137,6 +137,18 @@
# define MAX(a,b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef BOARD_TSSCTIM
# define BOARD_TSSCTIM 0
#endif
#ifndef BOARD_TSD_PENDETSENS
# define BOARD_TSD_PENDETSENS 0
#endif
#if !defined BOARD_TSD_IBCTL && defined ATSAMA5D2
# define BOARD_TSD_IBCTL 0
#endif
/****************************************************************************
* Private Types
****************************************************************************/
@ -449,6 +461,7 @@ static void sam_tsd_setaverage(struct sam_tsd_s *priv, uint32_t tsav)
*/
minfreq = (tsav >> ADC_TSMR_TSAV_SHIFT);
if (minfreq)
{
/* TSFREQ: Defines the Touchscreen Frequency compared to the Trigger
@ -460,9 +473,11 @@ static void sam_tsd_setaverage(struct sam_tsd_s *priv, uint32_t tsav)
{
/* Set TSFREQ = TSAV */
regval &= ~ADC_TSMR_TSFREQ_MASK;
regval |= ADC_TSMR_TSFREQ(minfreq);
tsfreq = minfreq;
}
regval &= ~ADC_TSMR_TSFREQ_MASK;
regval |= ADC_TSMR_TSFREQ(minfreq);
}
/* Save the new filter value */
@ -565,10 +580,12 @@ static void sam_tsd_bottomhalf(void *arg)
sam_tsd_setaverage(priv, ADC_TSMR_TSAV_NOFILTER);
sam_tsd_debounce(priv, BOARD_TSD_DEBOUNCE);
#ifdef SAMA5_TSD_PENDET_TRIG_ALLOWED
regval = sam_adc_getreg(priv->adc, SAM_ADC_TRGR);
regval &= ~ADC_TRGR_TRGMOD_MASK;
regval |= ADC_TRGR_TRGMOD_PEN;
sam_adc_putreg(priv->adc, SAM_ADC_TRGR, regval);
#endif
}
/* It is a pen down event. If the last loss-of-contact event has not been
@ -609,6 +626,39 @@ static void sam_tsd_bottomhalf(void *arg)
/* But don't enable interrupts for the data that we already have */
ier &= ~(pending & TSD_ALLREADY);
/* datasheet suggests that if TSAV != 0 there may not be interrupts
* for TSD channels so periodic or continuous triggers are needed
*
* Testing suggests otherwise, so periodic is used regardless.
*/
#if 0
regval = sam_adc_getreg(priv->adc, SAM_ADC_TSMR);
regval &= ADC_TSMR_TSAV_MASK;
if ((regval & ADC_TSMR_TSAV_MASK) != 0)
#endif
#ifdef SAMA5_TSD_PENDET_TRIG_ALLOWED
{
regval = sam_adc_getreg(priv->adc, SAM_ADC_TRGR);
if ((regval & ADC_TRGR_TRGMOD_MASK) == ADC_TRGR_TRGMOD_PEN)
{
/* Configure for periodic trigger */
regval &= ~ADC_TRGR_TRGMOD_MASK;
regval |= ADC_TRGR_TRGMOD_PERIOD;
sam_adc_putreg(priv->adc, SAM_ADC_TRGR, regval);
}
else
{
regval = sam_adc_getreg(priv->adc, SAM_ADC_TRGR);
regval &= ~ADC_TRGR_TRGMOD_MASK;
regval |= ADC_TRGR_TRGMOD_PEN;
sam_adc_putreg(priv->adc, SAM_ADC_TRGR, regval);
}
}
#endif
goto ignored;
}
@ -704,14 +754,25 @@ static void sam_tsd_bottomhalf(void *arg)
* resistance (Rxp). Three conversions (Xpos, Z1, Z2) are
* necessary to determine the value of Rp (Zaxis resistance).
*
* Rp = Rxp * (Xraw / 1024) * [(Z2 / Z1) - 1]
* Rp = Rxp * (X / 1024) * [(Z2 / Z1) - 1]
*
* Revisited. The ADC is 12 bit not 10 so datasheet is presumed
* incorrect. Formula corrected to cope with uint arithmetic.
*/
z2 = (pressr & ADC_PRESSR_Z2_MASK) >> ADC_PRESSR_Z2_SHIFT;
z1 = (pressr & ADC_PRESSR_Z1_MASK) >> ADC_PRESSR_Z1_SHIFT;
p = CONFIG_SAMA_TSD_RXP * xraw * (z2 - z1) / z1;
priv->sample.p = MIN(p, UINT16_MAX);
if (z1 != 0)
{
p = CONFIG_SAMA_TSD_RXP * xraw * (z2 - z1) / (z1 * 4096);
}
else
{
p = 4096;
}
priv->sample.p = MIN(p, 4096);
#endif
/* The X/Y positional data is now valid */
@ -730,6 +791,7 @@ static void sam_tsd_bottomhalf(void *arg)
priv->sample.contact = CONTACT_DOWN;
#ifdef SAMA5_TSD_PENDET_TRIG_ALLOWED
/* Configure for periodic trigger */
sam_tsd_setaverage(priv, ADC_TSMR_TSAV_8CONV);
@ -739,6 +801,7 @@ static void sam_tsd_bottomhalf(void *arg)
regval &= ~ADC_TRGR_TRGMOD_MASK;
regval |= ADC_TRGR_TRGMOD_PERIOD;
sam_adc_putreg(priv->adc, SAM_ADC_TRGR, regval);
#endif
}
}
@ -833,7 +896,6 @@ static int sam_tsd_open(struct file *filep)
/* Get exclusive access to the device structures */
sam_adc_lock(priv->adc);
/* Increment the count of references to the device. If this the first
* time that the driver has been opened for this device, then initialize
* the device.
@ -1202,67 +1264,67 @@ static void sam_tsd_startuptime(struct sam_tsd_s *priv, uint32_t time)
if (startup > 896)
{
regval = ADC_MR_STARTUP_960;
regval |= ADC_MR_STARTUP_960;
}
else if (startup > 832)
{
regval = ADC_MR_STARTUP_896;
regval |= ADC_MR_STARTUP_896;
}
else if (startup > 768)
{
regval = ADC_MR_STARTUP_832;
regval |= ADC_MR_STARTUP_832;
}
else if (startup > 704)
{
regval = ADC_MR_STARTUP_768;
regval |= ADC_MR_STARTUP_768;
}
else if (startup > 640)
{
regval = ADC_MR_STARTUP_704;
regval |= ADC_MR_STARTUP_704;
}
else if (startup > 576)
{
regval = ADC_MR_STARTUP_640;
regval |= ADC_MR_STARTUP_640;
}
else if (startup > 512)
{
regval = ADC_MR_STARTUP_576;
regval |= ADC_MR_STARTUP_576;
}
else if (startup > 112)
{
regval = ADC_MR_STARTUP_512;
regval |= ADC_MR_STARTUP_512;
}
else if (startup > 96)
{
regval = ADC_MR_STARTUP_112;
regval |= ADC_MR_STARTUP_112;
}
else if (startup > 80)
{
regval = ADC_MR_STARTUP_96;
regval |= ADC_MR_STARTUP_96;
}
else if (startup > 64)
{
regval = ADC_MR_STARTUP_80;
regval |= ADC_MR_STARTUP_80;
}
else if (startup > 24)
{
regval = ADC_MR_STARTUP_64;
regval |= ADC_MR_STARTUP_64;
}
else if (startup > 16)
{
regval = ADC_MR_STARTUP_24;
regval |= ADC_MR_STARTUP_24;
}
else if (startup > 8)
{
regval = ADC_MR_STARTUP_16;
regval |= ADC_MR_STARTUP_16;
}
else if (startup > 0)
{
regval = ADC_MR_STARTUP_8;
regval |= ADC_MR_STARTUP_8;
}
else
{
regval = ADC_MR_STARTUP_0;
regval |= ADC_MR_STARTUP_0;
}
sam_adc_putreg(priv->adc, SAM_ADC_MR, regval);
@ -1291,6 +1353,8 @@ static void sam_tsd_tracking(struct sam_tsd_s *priv, uint32_t time)
uint32_t tracktim;
uint32_t regval;
#if defined(ATSAMA5D4)
/* Formula for SHTIM is:
*
* TRACKTIM = (TrackingTime * ADCCLK) / (1000000000) - 1
@ -1318,7 +1382,11 @@ static void sam_tsd_tracking(struct sam_tsd_s *priv, uint32_t time)
tracktim--;
}
}
#elif defined (ATSAMA5D3)
tracktim = 0;
#else /* ATSAMA5D2*/
tracktim = MAX(time, 15);
#endif
/* Set the neew TRACKTIM field value int he ADC MR register */
regval = sam_adc_getreg(priv->adc, SAM_ADC_MR);
@ -1338,7 +1406,7 @@ static void sam_tsd_tracking(struct sam_tsd_s *priv, uint32_t time)
*
* Input Parameters:
* priv - A reference to the touchscreen device structure
* time - The new trigger period in nanoseconds
* time - The new trigger period in useconds
*
* Returned Value:
* None
@ -1356,7 +1424,7 @@ static void sam_tsd_trigperiod(struct sam_tsd_s *priv, uint32_t period)
* zeroes.
*/
div = 100000000;
div = 100000;
while (period >= 10 && div >= 10)
{
period /= 10;
@ -1488,18 +1556,36 @@ static void sam_tsd_initialize(struct sam_tsd_s *priv)
{
uint32_t regval;
#ifdef SAMA5_TSD_PENDET_TRIG_ALLOWED
/* Disable touch trigger */
regval = sam_adc_getreg(priv->adc, SAM_ADC_TRGR);
regval &= ~ADC_TRGR_TRGMOD_MASK;
regval |= ADC_TRGR_TRGMOD_NOTRIG;
sam_adc_putreg(priv->adc, SAM_ADC_TRGR, regval);
#endif
/* Setup timing */
sam_tsd_startuptime(priv, BOARD_TSD_STARTUP);
sam_tsd_tracking(priv, BOARD_TSD_TRACKTIM);
sam_tsd_trigperiod(priv, 20000000); /* 20ms */
/* set trigger mode to be periodic in case ADC not already
* been initialised. It's the only option allowed and that works.
*/
#ifndef SAMA5_TSD_PENDET_TRIG_ALLOWED
/* if we're allowed to use pendet trigger no need to do this */
regval = sam_adc_getreg(priv, SAM_ADC_TRGR);
regval &= ~ADC_TRGR_TRGMOD_MASK;
regval |= ADC_TRGR_TRGMOD_PERIOD;
sam_adc_putreg(priv, SAM_ADC_TRGR, regval);
sam_tsd_trigperiod(priv, CONFIG_SAMA5_ADC_TRIGGER_PERIOD);
#else
sam_tsd_trigperiod(priv, 20000); /* 20ms */
#endif
/* Setup the touchscreen mode */
@ -1514,25 +1600,15 @@ static void sam_tsd_initialize(struct sam_tsd_s *priv)
regval |= ADC_TSMR_TSMODE_4WIRE;
#endif
regval &= ~ADC_TSMR_TSSCTIM_MASK;
regval |= ADC_TSMR_TSSCTIM(BOARD_TSSCTIM);
sam_adc_putreg(priv->adc, SAM_ADC_TSMR, regval);
/* Disable averaging */
sam_tsd_setaverage(priv, ADC_TSMR_TSAV_NOFILTER);
/* Select 4-wire w/pressure, 4-wire w/o pressure, or 5 wire modes */
regval = sam_adc_getreg(priv->adc, SAM_ADC_TSMR);
regval &= ~ADC_TSMR_TSMODE_MASK;
#if defined(CONFIG_SAMA5_TSD_5WIRE)
regval |= ADC_TSMR_TSMODE_5WIRE;
#elif defined(CONFIG_SAMA5_TSD_4WIRENPM)
regval |= ADC_TSMR_TSMODE_4WIRENPM;
#else /* if defined(CONFIG_SAMA5_TSD_4WIRE) */
regval |= ADC_TSMR_TSMODE_4WIRE;
#endif
/* Disable all TSD-related interrupts */
sam_adc_putreg(priv->adc, SAM_ADC_IDR, ADC_TSD_ALLINTS);
@ -1551,6 +1627,7 @@ static void sam_tsd_initialize(struct sam_tsd_s *priv)
/* Enable pen contact detection */
regval = sam_adc_getreg(priv->adc, SAM_ADC_TSMR);
regval |= ADC_TSMR_PENDET;
sam_adc_putreg(priv->adc, SAM_ADC_TSMR, regval);
@ -1558,14 +1635,36 @@ static void sam_tsd_initialize(struct sam_tsd_s *priv)
sam_tsd_debounce(priv, BOARD_TSD_DEBOUNCE);
/* Configure pen sensitivity */
regval = sam_adc_getreg(priv->adc, SAM_ADC_ACR);
regval &= ~ADC_ACR_PENDETSENS_MASK;
regval |= ADC_ACR_PENDETSENS(BOARD_TSD_PENDETSENS);
#if defined(ATSAMA5D2)
regval &= ~ADC_ACR_IBCTL_MASK;
regval |= ADC_ACR_IBCTL(BOARD_TSD_IBCTL);
#endif
sam_adc_putreg(priv->adc, SAM_ADC_ACR, regval);
#ifdef SAMA5_TSD_PENDET_TRIG_ALLOWED
/* Configure pen interrupt generation */
regval = sam_adc_getreg(priv->adc, SAM_ADC_TRGR);
regval &= ~ADC_TRGR_TRGMOD_MASK;
regval |= ADC_TRGR_TRGMOD_PEN;
sam_adc_putreg(priv->adc, SAM_ADC_TRGR, regval);
#endif
sam_adc_putreg(priv->adc, SAM_ADC_IER, ADC_INT_PEN);
#ifdef CONFIG_SAMA5_TSD_AUTOCALIB
/* Perform a ts calibration */
regval = ADC_CR_TSCALIB | ADC_CR_START;
sam_adc_putreg(priv->adc, SAM_ADC_CR, regval);
#endif
up_enable_irq(SAM_IRQ_ADC);
}
/****************************************************************************
@ -1599,13 +1698,14 @@ static void sam_tsd_uninitialize(struct sam_tsd_s *priv)
*/
sam_adc_putreg(priv->adc, SAM_ADC_IDR, ADC_TSD_ALLINTS);
#ifdef SAMA5_TSD_PENDET_TRIG_ALLOWED
/* Disable touch trigger */
regval = sam_adc_getreg(priv->adc, SAM_ADC_TRGR);
regval &= ~ADC_TRGR_TRGMOD_MASK;
regval |= ADC_TRGR_TRGMOD_NOTRIG;
sam_adc_putreg(priv->adc, SAM_ADC_TRGR, regval);
#endif
/* Disable the touchscreen mode */
@ -1655,7 +1755,7 @@ int sam_tsd_register(struct sam_adc_s *adc, int minor)
/* Initialize the touchscreen device driver instance */
priv->adc = adc; /* Save the ADC device handle */
priv->adc = adc; /* Save the ADC device handle */
/* Register the device as an input device */

View File

@ -36,8 +36,18 @@
/* Configuration ************************************************************/
#ifdef CONFIG_SAMA_TSD_RXP
# define CONFIG_SAMA_TSD_RXP 6
#ifndef CONFIG_SAMA5_TSD_RXP
# define CONFIG_SAMA5_TSD_RXP 6
#endif
#ifndef CONFIG_SAMA5_ADC_TRIGGER_PERIOD
# define CONFIG_SAMA5_ADC_TRIGGER_PERIOD 20000
#endif
/* Only allow Pendet triggering in limited circumstances */
#if defined(CONFIG_SAMA5_ADC_SWTRIG)
# define SAMA5_TSD_PENDET_TRIG_ALLOWED
#endif
/* Touchscreen interrupt event sets