162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Atmel ADC driver for SAMA5D2 devices and compatible. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2015 Atmel, 662306a36Sopenharmony_ci * 2015 Ludovic Desroches <ludovic.desroches@atmel.com> 762306a36Sopenharmony_ci * 2021 Microchip Technology, Inc. and its subsidiaries 862306a36Sopenharmony_ci * 2021 Eugen Hristev <eugen.hristev@microchip.com> 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/bitops.h> 1262306a36Sopenharmony_ci#include <linux/clk.h> 1362306a36Sopenharmony_ci#include <linux/delay.h> 1462306a36Sopenharmony_ci#include <linux/dma-mapping.h> 1562306a36Sopenharmony_ci#include <linux/dmaengine.h> 1662306a36Sopenharmony_ci#include <linux/interrupt.h> 1762306a36Sopenharmony_ci#include <linux/io.h> 1862306a36Sopenharmony_ci#include <linux/module.h> 1962306a36Sopenharmony_ci#include <linux/mod_devicetable.h> 2062306a36Sopenharmony_ci#include <linux/platform_device.h> 2162306a36Sopenharmony_ci#include <linux/property.h> 2262306a36Sopenharmony_ci#include <linux/sched.h> 2362306a36Sopenharmony_ci#include <linux/units.h> 2462306a36Sopenharmony_ci#include <linux/wait.h> 2562306a36Sopenharmony_ci#include <linux/iio/iio.h> 2662306a36Sopenharmony_ci#include <linux/iio/sysfs.h> 2762306a36Sopenharmony_ci#include <linux/iio/buffer.h> 2862306a36Sopenharmony_ci#include <linux/iio/trigger.h> 2962306a36Sopenharmony_ci#include <linux/iio/trigger_consumer.h> 3062306a36Sopenharmony_ci#include <linux/iio/triggered_buffer.h> 3162306a36Sopenharmony_ci#include <linux/nvmem-consumer.h> 3262306a36Sopenharmony_ci#include <linux/pinctrl/consumer.h> 3362306a36Sopenharmony_ci#include <linux/pm_runtime.h> 3462306a36Sopenharmony_ci#include <linux/regulator/consumer.h> 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci#include <dt-bindings/iio/adc/at91-sama5d2_adc.h> 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_cistruct at91_adc_reg_layout { 3962306a36Sopenharmony_ci/* Control Register */ 4062306a36Sopenharmony_ci u16 CR; 4162306a36Sopenharmony_ci/* Software Reset */ 4262306a36Sopenharmony_ci#define AT91_SAMA5D2_CR_SWRST BIT(0) 4362306a36Sopenharmony_ci/* Start Conversion */ 4462306a36Sopenharmony_ci#define AT91_SAMA5D2_CR_START BIT(1) 4562306a36Sopenharmony_ci/* Touchscreen Calibration */ 4662306a36Sopenharmony_ci#define AT91_SAMA5D2_CR_TSCALIB BIT(2) 4762306a36Sopenharmony_ci/* Comparison Restart */ 4862306a36Sopenharmony_ci#define AT91_SAMA5D2_CR_CMPRST BIT(4) 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci/* Mode Register */ 5162306a36Sopenharmony_ci u16 MR; 5262306a36Sopenharmony_ci/* Trigger Selection */ 5362306a36Sopenharmony_ci#define AT91_SAMA5D2_MR_TRGSEL(v) ((v) << 1) 5462306a36Sopenharmony_ci/* ADTRG */ 5562306a36Sopenharmony_ci#define AT91_SAMA5D2_MR_TRGSEL_TRIG0 0 5662306a36Sopenharmony_ci/* TIOA0 */ 5762306a36Sopenharmony_ci#define AT91_SAMA5D2_MR_TRGSEL_TRIG1 1 5862306a36Sopenharmony_ci/* TIOA1 */ 5962306a36Sopenharmony_ci#define AT91_SAMA5D2_MR_TRGSEL_TRIG2 2 6062306a36Sopenharmony_ci/* TIOA2 */ 6162306a36Sopenharmony_ci#define AT91_SAMA5D2_MR_TRGSEL_TRIG3 3 6262306a36Sopenharmony_ci/* PWM event line 0 */ 6362306a36Sopenharmony_ci#define AT91_SAMA5D2_MR_TRGSEL_TRIG4 4 6462306a36Sopenharmony_ci/* PWM event line 1 */ 6562306a36Sopenharmony_ci#define AT91_SAMA5D2_MR_TRGSEL_TRIG5 5 6662306a36Sopenharmony_ci/* TIOA3 */ 6762306a36Sopenharmony_ci#define AT91_SAMA5D2_MR_TRGSEL_TRIG6 6 6862306a36Sopenharmony_ci/* RTCOUT0 */ 6962306a36Sopenharmony_ci#define AT91_SAMA5D2_MR_TRGSEL_TRIG7 7 7062306a36Sopenharmony_ci/* Sleep Mode */ 7162306a36Sopenharmony_ci#define AT91_SAMA5D2_MR_SLEEP BIT(5) 7262306a36Sopenharmony_ci/* Fast Wake Up */ 7362306a36Sopenharmony_ci#define AT91_SAMA5D2_MR_FWUP BIT(6) 7462306a36Sopenharmony_ci/* Prescaler Rate Selection */ 7562306a36Sopenharmony_ci#define AT91_SAMA5D2_MR_PRESCAL(v) ((v) << AT91_SAMA5D2_MR_PRESCAL_OFFSET) 7662306a36Sopenharmony_ci#define AT91_SAMA5D2_MR_PRESCAL_OFFSET 8 7762306a36Sopenharmony_ci#define AT91_SAMA5D2_MR_PRESCAL_MAX 0xff 7862306a36Sopenharmony_ci#define AT91_SAMA5D2_MR_PRESCAL_MASK GENMASK(15, 8) 7962306a36Sopenharmony_ci/* Startup Time */ 8062306a36Sopenharmony_ci#define AT91_SAMA5D2_MR_STARTUP(v) ((v) << 16) 8162306a36Sopenharmony_ci#define AT91_SAMA5D2_MR_STARTUP_MASK GENMASK(19, 16) 8262306a36Sopenharmony_ci/* Minimum startup time for temperature sensor */ 8362306a36Sopenharmony_ci#define AT91_SAMA5D2_MR_STARTUP_TS_MIN (50) 8462306a36Sopenharmony_ci/* Analog Change */ 8562306a36Sopenharmony_ci#define AT91_SAMA5D2_MR_ANACH BIT(23) 8662306a36Sopenharmony_ci/* Tracking Time */ 8762306a36Sopenharmony_ci#define AT91_SAMA5D2_MR_TRACKTIM(v) ((v) << 24) 8862306a36Sopenharmony_ci#define AT91_SAMA5D2_MR_TRACKTIM_TS 6 8962306a36Sopenharmony_ci#define AT91_SAMA5D2_MR_TRACKTIM_MAX 0xf 9062306a36Sopenharmony_ci/* Transfer Time */ 9162306a36Sopenharmony_ci#define AT91_SAMA5D2_MR_TRANSFER(v) ((v) << 28) 9262306a36Sopenharmony_ci#define AT91_SAMA5D2_MR_TRANSFER_MAX 0x3 9362306a36Sopenharmony_ci/* Use Sequence Enable */ 9462306a36Sopenharmony_ci#define AT91_SAMA5D2_MR_USEQ BIT(31) 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci/* Channel Sequence Register 1 */ 9762306a36Sopenharmony_ci u16 SEQR1; 9862306a36Sopenharmony_ci/* Channel Sequence Register 2 */ 9962306a36Sopenharmony_ci u16 SEQR2; 10062306a36Sopenharmony_ci/* Channel Enable Register */ 10162306a36Sopenharmony_ci u16 CHER; 10262306a36Sopenharmony_ci/* Channel Disable Register */ 10362306a36Sopenharmony_ci u16 CHDR; 10462306a36Sopenharmony_ci/* Channel Status Register */ 10562306a36Sopenharmony_ci u16 CHSR; 10662306a36Sopenharmony_ci/* Last Converted Data Register */ 10762306a36Sopenharmony_ci u16 LCDR; 10862306a36Sopenharmony_ci/* Interrupt Enable Register */ 10962306a36Sopenharmony_ci u16 IER; 11062306a36Sopenharmony_ci/* Interrupt Enable Register - TS X measurement ready */ 11162306a36Sopenharmony_ci#define AT91_SAMA5D2_IER_XRDY BIT(20) 11262306a36Sopenharmony_ci/* Interrupt Enable Register - TS Y measurement ready */ 11362306a36Sopenharmony_ci#define AT91_SAMA5D2_IER_YRDY BIT(21) 11462306a36Sopenharmony_ci/* Interrupt Enable Register - TS pressure measurement ready */ 11562306a36Sopenharmony_ci#define AT91_SAMA5D2_IER_PRDY BIT(22) 11662306a36Sopenharmony_ci/* Interrupt Enable Register - Data ready */ 11762306a36Sopenharmony_ci#define AT91_SAMA5D2_IER_DRDY BIT(24) 11862306a36Sopenharmony_ci/* Interrupt Enable Register - general overrun error */ 11962306a36Sopenharmony_ci#define AT91_SAMA5D2_IER_GOVRE BIT(25) 12062306a36Sopenharmony_ci/* Interrupt Enable Register - Pen detect */ 12162306a36Sopenharmony_ci#define AT91_SAMA5D2_IER_PEN BIT(29) 12262306a36Sopenharmony_ci/* Interrupt Enable Register - No pen detect */ 12362306a36Sopenharmony_ci#define AT91_SAMA5D2_IER_NOPEN BIT(30) 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci/* Interrupt Disable Register */ 12662306a36Sopenharmony_ci u16 IDR; 12762306a36Sopenharmony_ci/* Interrupt Mask Register */ 12862306a36Sopenharmony_ci u16 IMR; 12962306a36Sopenharmony_ci/* Interrupt Status Register */ 13062306a36Sopenharmony_ci u16 ISR; 13162306a36Sopenharmony_ci/* End of Conversion Interrupt Enable Register */ 13262306a36Sopenharmony_ci u16 EOC_IER; 13362306a36Sopenharmony_ci/* End of Conversion Interrupt Disable Register */ 13462306a36Sopenharmony_ci u16 EOC_IDR; 13562306a36Sopenharmony_ci/* End of Conversion Interrupt Mask Register */ 13662306a36Sopenharmony_ci u16 EOC_IMR; 13762306a36Sopenharmony_ci/* End of Conversion Interrupt Status Register */ 13862306a36Sopenharmony_ci u16 EOC_ISR; 13962306a36Sopenharmony_ci/* Interrupt Status Register - Pen touching sense status */ 14062306a36Sopenharmony_ci#define AT91_SAMA5D2_ISR_PENS BIT(31) 14162306a36Sopenharmony_ci/* Last Channel Trigger Mode Register */ 14262306a36Sopenharmony_ci u16 LCTMR; 14362306a36Sopenharmony_ci/* Last Channel Compare Window Register */ 14462306a36Sopenharmony_ci u16 LCCWR; 14562306a36Sopenharmony_ci/* Overrun Status Register */ 14662306a36Sopenharmony_ci u16 OVER; 14762306a36Sopenharmony_ci/* Extended Mode Register */ 14862306a36Sopenharmony_ci u16 EMR; 14962306a36Sopenharmony_ci/* Extended Mode Register - Oversampling rate */ 15062306a36Sopenharmony_ci#define AT91_SAMA5D2_EMR_OSR(V, M) (((V) << 16) & (M)) 15162306a36Sopenharmony_ci#define AT91_SAMA5D2_EMR_OSR_1SAMPLES 0 15262306a36Sopenharmony_ci#define AT91_SAMA5D2_EMR_OSR_4SAMPLES 1 15362306a36Sopenharmony_ci#define AT91_SAMA5D2_EMR_OSR_16SAMPLES 2 15462306a36Sopenharmony_ci#define AT91_SAMA5D2_EMR_OSR_64SAMPLES 3 15562306a36Sopenharmony_ci#define AT91_SAMA5D2_EMR_OSR_256SAMPLES 4 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci/* Extended Mode Register - TRACKX */ 15862306a36Sopenharmony_ci#define AT91_SAMA5D2_TRACKX_MASK GENMASK(23, 22) 15962306a36Sopenharmony_ci#define AT91_SAMA5D2_TRACKX(x) (((x) << 22) & \ 16062306a36Sopenharmony_ci AT91_SAMA5D2_TRACKX_MASK) 16162306a36Sopenharmony_ci/* TRACKX for temperature sensor. */ 16262306a36Sopenharmony_ci#define AT91_SAMA5D2_TRACKX_TS (1) 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci/* Extended Mode Register - Averaging on single trigger event */ 16562306a36Sopenharmony_ci#define AT91_SAMA5D2_EMR_ASTE(V) ((V) << 20) 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci/* Compare Window Register */ 16862306a36Sopenharmony_ci u16 CWR; 16962306a36Sopenharmony_ci/* Channel Gain Register */ 17062306a36Sopenharmony_ci u16 CGR; 17162306a36Sopenharmony_ci/* Channel Offset Register */ 17262306a36Sopenharmony_ci u16 COR; 17362306a36Sopenharmony_ci/* Channel Offset Register differential offset - constant, not a register */ 17462306a36Sopenharmony_ci u16 COR_diff_offset; 17562306a36Sopenharmony_ci/* Analog Control Register */ 17662306a36Sopenharmony_ci u16 ACR; 17762306a36Sopenharmony_ci/* Analog Control Register - Pen detect sensitivity mask */ 17862306a36Sopenharmony_ci#define AT91_SAMA5D2_ACR_PENDETSENS_MASK GENMASK(1, 0) 17962306a36Sopenharmony_ci/* Analog Control Register - Source last channel */ 18062306a36Sopenharmony_ci#define AT91_SAMA5D2_ACR_SRCLCH BIT(16) 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci/* Touchscreen Mode Register */ 18362306a36Sopenharmony_ci u16 TSMR; 18462306a36Sopenharmony_ci/* Touchscreen Mode Register - No touch mode */ 18562306a36Sopenharmony_ci#define AT91_SAMA5D2_TSMR_TSMODE_NONE 0 18662306a36Sopenharmony_ci/* Touchscreen Mode Register - 4 wire screen, no pressure measurement */ 18762306a36Sopenharmony_ci#define AT91_SAMA5D2_TSMR_TSMODE_4WIRE_NO_PRESS 1 18862306a36Sopenharmony_ci/* Touchscreen Mode Register - 4 wire screen, pressure measurement */ 18962306a36Sopenharmony_ci#define AT91_SAMA5D2_TSMR_TSMODE_4WIRE_PRESS 2 19062306a36Sopenharmony_ci/* Touchscreen Mode Register - 5 wire screen */ 19162306a36Sopenharmony_ci#define AT91_SAMA5D2_TSMR_TSMODE_5WIRE 3 19262306a36Sopenharmony_ci/* Touchscreen Mode Register - Average samples mask */ 19362306a36Sopenharmony_ci#define AT91_SAMA5D2_TSMR_TSAV_MASK GENMASK(5, 4) 19462306a36Sopenharmony_ci/* Touchscreen Mode Register - Average samples */ 19562306a36Sopenharmony_ci#define AT91_SAMA5D2_TSMR_TSAV(x) ((x) << 4) 19662306a36Sopenharmony_ci/* Touchscreen Mode Register - Touch/trigger frequency ratio mask */ 19762306a36Sopenharmony_ci#define AT91_SAMA5D2_TSMR_TSFREQ_MASK GENMASK(11, 8) 19862306a36Sopenharmony_ci/* Touchscreen Mode Register - Touch/trigger frequency ratio */ 19962306a36Sopenharmony_ci#define AT91_SAMA5D2_TSMR_TSFREQ(x) ((x) << 8) 20062306a36Sopenharmony_ci/* Touchscreen Mode Register - Pen Debounce Time mask */ 20162306a36Sopenharmony_ci#define AT91_SAMA5D2_TSMR_PENDBC_MASK GENMASK(31, 28) 20262306a36Sopenharmony_ci/* Touchscreen Mode Register - Pen Debounce Time */ 20362306a36Sopenharmony_ci#define AT91_SAMA5D2_TSMR_PENDBC(x) ((x) << 28) 20462306a36Sopenharmony_ci/* Touchscreen Mode Register - No DMA for touch measurements */ 20562306a36Sopenharmony_ci#define AT91_SAMA5D2_TSMR_NOTSDMA BIT(22) 20662306a36Sopenharmony_ci/* Touchscreen Mode Register - Disable pen detection */ 20762306a36Sopenharmony_ci#define AT91_SAMA5D2_TSMR_PENDET_DIS (0 << 24) 20862306a36Sopenharmony_ci/* Touchscreen Mode Register - Enable pen detection */ 20962306a36Sopenharmony_ci#define AT91_SAMA5D2_TSMR_PENDET_ENA BIT(24) 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci/* Touchscreen X Position Register */ 21262306a36Sopenharmony_ci u16 XPOSR; 21362306a36Sopenharmony_ci/* Touchscreen Y Position Register */ 21462306a36Sopenharmony_ci u16 YPOSR; 21562306a36Sopenharmony_ci/* Touchscreen Pressure Register */ 21662306a36Sopenharmony_ci u16 PRESSR; 21762306a36Sopenharmony_ci/* Trigger Register */ 21862306a36Sopenharmony_ci u16 TRGR; 21962306a36Sopenharmony_ci/* Mask for TRGMOD field of TRGR register */ 22062306a36Sopenharmony_ci#define AT91_SAMA5D2_TRGR_TRGMOD_MASK GENMASK(2, 0) 22162306a36Sopenharmony_ci/* No trigger, only software trigger can start conversions */ 22262306a36Sopenharmony_ci#define AT91_SAMA5D2_TRGR_TRGMOD_NO_TRIGGER 0 22362306a36Sopenharmony_ci/* Trigger Mode external trigger rising edge */ 22462306a36Sopenharmony_ci#define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_RISE 1 22562306a36Sopenharmony_ci/* Trigger Mode external trigger falling edge */ 22662306a36Sopenharmony_ci#define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_FALL 2 22762306a36Sopenharmony_ci/* Trigger Mode external trigger any edge */ 22862306a36Sopenharmony_ci#define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_ANY 3 22962306a36Sopenharmony_ci/* Trigger Mode internal periodic */ 23062306a36Sopenharmony_ci#define AT91_SAMA5D2_TRGR_TRGMOD_PERIODIC 5 23162306a36Sopenharmony_ci/* Trigger Mode - trigger period mask */ 23262306a36Sopenharmony_ci#define AT91_SAMA5D2_TRGR_TRGPER_MASK GENMASK(31, 16) 23362306a36Sopenharmony_ci/* Trigger Mode - trigger period */ 23462306a36Sopenharmony_ci#define AT91_SAMA5D2_TRGR_TRGPER(x) ((x) << 16) 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci/* Correction Select Register */ 23762306a36Sopenharmony_ci u16 COSR; 23862306a36Sopenharmony_ci/* Correction Value Register */ 23962306a36Sopenharmony_ci u16 CVR; 24062306a36Sopenharmony_ci/* Channel Error Correction Register */ 24162306a36Sopenharmony_ci u16 CECR; 24262306a36Sopenharmony_ci/* Write Protection Mode Register */ 24362306a36Sopenharmony_ci u16 WPMR; 24462306a36Sopenharmony_ci/* Write Protection Status Register */ 24562306a36Sopenharmony_ci u16 WPSR; 24662306a36Sopenharmony_ci/* Version Register */ 24762306a36Sopenharmony_ci u16 VERSION; 24862306a36Sopenharmony_ci/* Temperature Sensor Mode Register */ 24962306a36Sopenharmony_ci u16 TEMPMR; 25062306a36Sopenharmony_ci/* Temperature Sensor Mode - Temperature sensor on */ 25162306a36Sopenharmony_ci#define AT91_SAMA5D2_TEMPMR_TEMPON BIT(0) 25262306a36Sopenharmony_ci}; 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_cistatic const struct at91_adc_reg_layout sama5d2_layout = { 25562306a36Sopenharmony_ci .CR = 0x00, 25662306a36Sopenharmony_ci .MR = 0x04, 25762306a36Sopenharmony_ci .SEQR1 = 0x08, 25862306a36Sopenharmony_ci .SEQR2 = 0x0c, 25962306a36Sopenharmony_ci .CHER = 0x10, 26062306a36Sopenharmony_ci .CHDR = 0x14, 26162306a36Sopenharmony_ci .CHSR = 0x18, 26262306a36Sopenharmony_ci .LCDR = 0x20, 26362306a36Sopenharmony_ci .IER = 0x24, 26462306a36Sopenharmony_ci .IDR = 0x28, 26562306a36Sopenharmony_ci .IMR = 0x2c, 26662306a36Sopenharmony_ci .ISR = 0x30, 26762306a36Sopenharmony_ci .LCTMR = 0x34, 26862306a36Sopenharmony_ci .LCCWR = 0x38, 26962306a36Sopenharmony_ci .OVER = 0x3c, 27062306a36Sopenharmony_ci .EMR = 0x40, 27162306a36Sopenharmony_ci .CWR = 0x44, 27262306a36Sopenharmony_ci .CGR = 0x48, 27362306a36Sopenharmony_ci .COR = 0x4c, 27462306a36Sopenharmony_ci .COR_diff_offset = 16, 27562306a36Sopenharmony_ci .ACR = 0x94, 27662306a36Sopenharmony_ci .TSMR = 0xb0, 27762306a36Sopenharmony_ci .XPOSR = 0xb4, 27862306a36Sopenharmony_ci .YPOSR = 0xb8, 27962306a36Sopenharmony_ci .PRESSR = 0xbc, 28062306a36Sopenharmony_ci .TRGR = 0xc0, 28162306a36Sopenharmony_ci .COSR = 0xd0, 28262306a36Sopenharmony_ci .CVR = 0xd4, 28362306a36Sopenharmony_ci .CECR = 0xd8, 28462306a36Sopenharmony_ci .WPMR = 0xe4, 28562306a36Sopenharmony_ci .WPSR = 0xe8, 28662306a36Sopenharmony_ci .VERSION = 0xfc, 28762306a36Sopenharmony_ci}; 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_cistatic const struct at91_adc_reg_layout sama7g5_layout = { 29062306a36Sopenharmony_ci .CR = 0x00, 29162306a36Sopenharmony_ci .MR = 0x04, 29262306a36Sopenharmony_ci .SEQR1 = 0x08, 29362306a36Sopenharmony_ci .SEQR2 = 0x0c, 29462306a36Sopenharmony_ci .CHER = 0x10, 29562306a36Sopenharmony_ci .CHDR = 0x14, 29662306a36Sopenharmony_ci .CHSR = 0x18, 29762306a36Sopenharmony_ci .LCDR = 0x20, 29862306a36Sopenharmony_ci .IER = 0x24, 29962306a36Sopenharmony_ci .IDR = 0x28, 30062306a36Sopenharmony_ci .IMR = 0x2c, 30162306a36Sopenharmony_ci .ISR = 0x30, 30262306a36Sopenharmony_ci .EOC_IER = 0x34, 30362306a36Sopenharmony_ci .EOC_IDR = 0x38, 30462306a36Sopenharmony_ci .EOC_IMR = 0x3c, 30562306a36Sopenharmony_ci .EOC_ISR = 0x40, 30662306a36Sopenharmony_ci .TEMPMR = 0x44, 30762306a36Sopenharmony_ci .OVER = 0x4c, 30862306a36Sopenharmony_ci .EMR = 0x50, 30962306a36Sopenharmony_ci .CWR = 0x54, 31062306a36Sopenharmony_ci .COR = 0x5c, 31162306a36Sopenharmony_ci .COR_diff_offset = 0, 31262306a36Sopenharmony_ci .ACR = 0xe0, 31362306a36Sopenharmony_ci .TRGR = 0x100, 31462306a36Sopenharmony_ci .COSR = 0x104, 31562306a36Sopenharmony_ci .CVR = 0x108, 31662306a36Sopenharmony_ci .CECR = 0x10c, 31762306a36Sopenharmony_ci .WPMR = 0x118, 31862306a36Sopenharmony_ci .WPSR = 0x11c, 31962306a36Sopenharmony_ci .VERSION = 0x130, 32062306a36Sopenharmony_ci}; 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci#define AT91_SAMA5D2_TOUCH_SAMPLE_PERIOD_US 2000 /* 2ms */ 32362306a36Sopenharmony_ci#define AT91_SAMA5D2_TOUCH_PEN_DETECT_DEBOUNCE_US 200 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci#define AT91_SAMA5D2_XYZ_MASK GENMASK(11, 0) 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci#define AT91_SAMA5D2_MAX_POS_BITS 12 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci#define AT91_HWFIFO_MAX_SIZE_STR "128" 33062306a36Sopenharmony_ci#define AT91_HWFIFO_MAX_SIZE 128 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci#define AT91_SAMA5D2_CHAN_SINGLE(index, num, addr) \ 33362306a36Sopenharmony_ci { \ 33462306a36Sopenharmony_ci .type = IIO_VOLTAGE, \ 33562306a36Sopenharmony_ci .channel = num, \ 33662306a36Sopenharmony_ci .address = addr, \ 33762306a36Sopenharmony_ci .scan_index = index, \ 33862306a36Sopenharmony_ci .scan_type = { \ 33962306a36Sopenharmony_ci .sign = 'u', \ 34062306a36Sopenharmony_ci .realbits = 14, \ 34162306a36Sopenharmony_ci .storagebits = 16, \ 34262306a36Sopenharmony_ci }, \ 34362306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 34462306a36Sopenharmony_ci .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 34562306a36Sopenharmony_ci .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ)|\ 34662306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ 34762306a36Sopenharmony_ci .info_mask_shared_by_all_available = \ 34862306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ 34962306a36Sopenharmony_ci .datasheet_name = "CH"#num, \ 35062306a36Sopenharmony_ci .indexed = 1, \ 35162306a36Sopenharmony_ci } 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci#define AT91_SAMA5D2_CHAN_DIFF(index, num, num2, addr) \ 35462306a36Sopenharmony_ci { \ 35562306a36Sopenharmony_ci .type = IIO_VOLTAGE, \ 35662306a36Sopenharmony_ci .differential = 1, \ 35762306a36Sopenharmony_ci .channel = num, \ 35862306a36Sopenharmony_ci .channel2 = num2, \ 35962306a36Sopenharmony_ci .address = addr, \ 36062306a36Sopenharmony_ci .scan_index = index, \ 36162306a36Sopenharmony_ci .scan_type = { \ 36262306a36Sopenharmony_ci .sign = 's', \ 36362306a36Sopenharmony_ci .realbits = 14, \ 36462306a36Sopenharmony_ci .storagebits = 16, \ 36562306a36Sopenharmony_ci }, \ 36662306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 36762306a36Sopenharmony_ci .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 36862306a36Sopenharmony_ci .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ)|\ 36962306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ 37062306a36Sopenharmony_ci .info_mask_shared_by_all_available = \ 37162306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ 37262306a36Sopenharmony_ci .datasheet_name = "CH"#num"-CH"#num2, \ 37362306a36Sopenharmony_ci .indexed = 1, \ 37462306a36Sopenharmony_ci } 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci#define AT91_SAMA5D2_CHAN_TOUCH(num, name, mod) \ 37762306a36Sopenharmony_ci { \ 37862306a36Sopenharmony_ci .type = IIO_POSITIONRELATIVE, \ 37962306a36Sopenharmony_ci .modified = 1, \ 38062306a36Sopenharmony_ci .channel = num, \ 38162306a36Sopenharmony_ci .channel2 = mod, \ 38262306a36Sopenharmony_ci .scan_index = num, \ 38362306a36Sopenharmony_ci .scan_type = { \ 38462306a36Sopenharmony_ci .sign = 'u', \ 38562306a36Sopenharmony_ci .realbits = 12, \ 38662306a36Sopenharmony_ci .storagebits = 16, \ 38762306a36Sopenharmony_ci }, \ 38862306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 38962306a36Sopenharmony_ci .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ)|\ 39062306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ 39162306a36Sopenharmony_ci .info_mask_shared_by_all_available = \ 39262306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ 39362306a36Sopenharmony_ci .datasheet_name = name, \ 39462306a36Sopenharmony_ci } 39562306a36Sopenharmony_ci#define AT91_SAMA5D2_CHAN_PRESSURE(num, name) \ 39662306a36Sopenharmony_ci { \ 39762306a36Sopenharmony_ci .type = IIO_PRESSURE, \ 39862306a36Sopenharmony_ci .channel = num, \ 39962306a36Sopenharmony_ci .scan_index = num, \ 40062306a36Sopenharmony_ci .scan_type = { \ 40162306a36Sopenharmony_ci .sign = 'u', \ 40262306a36Sopenharmony_ci .realbits = 12, \ 40362306a36Sopenharmony_ci .storagebits = 16, \ 40462306a36Sopenharmony_ci }, \ 40562306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 40662306a36Sopenharmony_ci .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ)|\ 40762306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ 40862306a36Sopenharmony_ci .info_mask_shared_by_all_available = \ 40962306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ 41062306a36Sopenharmony_ci .datasheet_name = name, \ 41162306a36Sopenharmony_ci } 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci#define AT91_SAMA5D2_CHAN_TEMP(num, name, addr) \ 41462306a36Sopenharmony_ci { \ 41562306a36Sopenharmony_ci .type = IIO_TEMP, \ 41662306a36Sopenharmony_ci .channel = num, \ 41762306a36Sopenharmony_ci .address = addr, \ 41862306a36Sopenharmony_ci .scan_index = num, \ 41962306a36Sopenharmony_ci .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \ 42062306a36Sopenharmony_ci .info_mask_shared_by_all = \ 42162306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_PROCESSED) | \ 42262306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ 42362306a36Sopenharmony_ci .info_mask_shared_by_all_available = \ 42462306a36Sopenharmony_ci BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ 42562306a36Sopenharmony_ci .datasheet_name = name, \ 42662306a36Sopenharmony_ci } 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci#define at91_adc_readl(st, reg) \ 42962306a36Sopenharmony_ci readl_relaxed((st)->base + (st)->soc_info.platform->layout->reg) 43062306a36Sopenharmony_ci#define at91_adc_read_chan(st, reg) \ 43162306a36Sopenharmony_ci readl_relaxed((st)->base + reg) 43262306a36Sopenharmony_ci#define at91_adc_writel(st, reg, val) \ 43362306a36Sopenharmony_ci writel_relaxed(val, (st)->base + (st)->soc_info.platform->layout->reg) 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci/** 43662306a36Sopenharmony_ci * struct at91_adc_platform - at91-sama5d2 platform information struct 43762306a36Sopenharmony_ci * @layout: pointer to the reg layout struct 43862306a36Sopenharmony_ci * @adc_channels: pointer to an array of channels for registering in 43962306a36Sopenharmony_ci * the iio subsystem 44062306a36Sopenharmony_ci * @nr_channels: number of physical channels available 44162306a36Sopenharmony_ci * @touch_chan_x: index of the touchscreen X channel 44262306a36Sopenharmony_ci * @touch_chan_y: index of the touchscreen Y channel 44362306a36Sopenharmony_ci * @touch_chan_p: index of the touchscreen P channel 44462306a36Sopenharmony_ci * @max_channels: number of total channels 44562306a36Sopenharmony_ci * @max_index: highest channel index (highest index may be higher 44662306a36Sopenharmony_ci * than the total channel number) 44762306a36Sopenharmony_ci * @hw_trig_cnt: number of possible hardware triggers 44862306a36Sopenharmony_ci * @osr_mask: oversampling ratio bitmask on EMR register 44962306a36Sopenharmony_ci * @oversampling_avail: available oversampling values 45062306a36Sopenharmony_ci * @oversampling_avail_no: number of available oversampling values 45162306a36Sopenharmony_ci * @chan_realbits: realbits for registered channels 45262306a36Sopenharmony_ci * @temp_chan: temperature channel index 45362306a36Sopenharmony_ci * @temp_sensor: temperature sensor supported 45462306a36Sopenharmony_ci */ 45562306a36Sopenharmony_cistruct at91_adc_platform { 45662306a36Sopenharmony_ci const struct at91_adc_reg_layout *layout; 45762306a36Sopenharmony_ci const struct iio_chan_spec (*adc_channels)[]; 45862306a36Sopenharmony_ci unsigned int nr_channels; 45962306a36Sopenharmony_ci unsigned int touch_chan_x; 46062306a36Sopenharmony_ci unsigned int touch_chan_y; 46162306a36Sopenharmony_ci unsigned int touch_chan_p; 46262306a36Sopenharmony_ci unsigned int max_channels; 46362306a36Sopenharmony_ci unsigned int max_index; 46462306a36Sopenharmony_ci unsigned int hw_trig_cnt; 46562306a36Sopenharmony_ci unsigned int osr_mask; 46662306a36Sopenharmony_ci unsigned int oversampling_avail[5]; 46762306a36Sopenharmony_ci unsigned int oversampling_avail_no; 46862306a36Sopenharmony_ci unsigned int chan_realbits; 46962306a36Sopenharmony_ci unsigned int temp_chan; 47062306a36Sopenharmony_ci bool temp_sensor; 47162306a36Sopenharmony_ci}; 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci/** 47462306a36Sopenharmony_ci * struct at91_adc_temp_sensor_clb - at91-sama5d2 temperature sensor 47562306a36Sopenharmony_ci * calibration data structure 47662306a36Sopenharmony_ci * @p1: P1 calibration temperature 47762306a36Sopenharmony_ci * @p4: P4 calibration voltage 47862306a36Sopenharmony_ci * @p6: P6 calibration voltage 47962306a36Sopenharmony_ci */ 48062306a36Sopenharmony_cistruct at91_adc_temp_sensor_clb { 48162306a36Sopenharmony_ci u32 p1; 48262306a36Sopenharmony_ci u32 p4; 48362306a36Sopenharmony_ci u32 p6; 48462306a36Sopenharmony_ci}; 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci/** 48762306a36Sopenharmony_ci * enum at91_adc_ts_clb_idx - calibration indexes in NVMEM buffer 48862306a36Sopenharmony_ci * @AT91_ADC_TS_CLB_IDX_P1: index for P1 48962306a36Sopenharmony_ci * @AT91_ADC_TS_CLB_IDX_P4: index for P4 49062306a36Sopenharmony_ci * @AT91_ADC_TS_CLB_IDX_P6: index for P6 49162306a36Sopenharmony_ci * @AT91_ADC_TS_CLB_IDX_MAX: max index for temperature calibration packet in OTP 49262306a36Sopenharmony_ci */ 49362306a36Sopenharmony_cienum at91_adc_ts_clb_idx { 49462306a36Sopenharmony_ci AT91_ADC_TS_CLB_IDX_P1 = 2, 49562306a36Sopenharmony_ci AT91_ADC_TS_CLB_IDX_P4 = 5, 49662306a36Sopenharmony_ci AT91_ADC_TS_CLB_IDX_P6 = 7, 49762306a36Sopenharmony_ci AT91_ADC_TS_CLB_IDX_MAX = 19, 49862306a36Sopenharmony_ci}; 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_ci/* Temperature sensor calibration - Vtemp voltage sensitivity to temperature. */ 50162306a36Sopenharmony_ci#define AT91_ADC_TS_VTEMP_DT (2080U) 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ci/** 50462306a36Sopenharmony_ci * struct at91_adc_soc_info - at91-sama5d2 soc information struct 50562306a36Sopenharmony_ci * @startup_time: device startup time 50662306a36Sopenharmony_ci * @min_sample_rate: minimum sample rate in Hz 50762306a36Sopenharmony_ci * @max_sample_rate: maximum sample rate in Hz 50862306a36Sopenharmony_ci * @platform: pointer to the platform structure 50962306a36Sopenharmony_ci * @temp_sensor_clb: temperature sensor calibration data structure 51062306a36Sopenharmony_ci */ 51162306a36Sopenharmony_cistruct at91_adc_soc_info { 51262306a36Sopenharmony_ci unsigned startup_time; 51362306a36Sopenharmony_ci unsigned min_sample_rate; 51462306a36Sopenharmony_ci unsigned max_sample_rate; 51562306a36Sopenharmony_ci const struct at91_adc_platform *platform; 51662306a36Sopenharmony_ci struct at91_adc_temp_sensor_clb temp_sensor_clb; 51762306a36Sopenharmony_ci}; 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_cistruct at91_adc_trigger { 52062306a36Sopenharmony_ci char *name; 52162306a36Sopenharmony_ci unsigned int trgmod_value; 52262306a36Sopenharmony_ci unsigned int edge_type; 52362306a36Sopenharmony_ci bool hw_trig; 52462306a36Sopenharmony_ci}; 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci/** 52762306a36Sopenharmony_ci * struct at91_adc_dma - at91-sama5d2 dma information struct 52862306a36Sopenharmony_ci * @dma_chan: the dma channel acquired 52962306a36Sopenharmony_ci * @rx_buf: dma coherent allocated area 53062306a36Sopenharmony_ci * @rx_dma_buf: dma handler for the buffer 53162306a36Sopenharmony_ci * @phys_addr: physical address of the ADC base register 53262306a36Sopenharmony_ci * @buf_idx: index inside the dma buffer where reading was last done 53362306a36Sopenharmony_ci * @rx_buf_sz: size of buffer used by DMA operation 53462306a36Sopenharmony_ci * @watermark: number of conversions to copy before DMA triggers irq 53562306a36Sopenharmony_ci * @dma_ts: hold the start timestamp of dma operation 53662306a36Sopenharmony_ci */ 53762306a36Sopenharmony_cistruct at91_adc_dma { 53862306a36Sopenharmony_ci struct dma_chan *dma_chan; 53962306a36Sopenharmony_ci u8 *rx_buf; 54062306a36Sopenharmony_ci dma_addr_t rx_dma_buf; 54162306a36Sopenharmony_ci phys_addr_t phys_addr; 54262306a36Sopenharmony_ci int buf_idx; 54362306a36Sopenharmony_ci int rx_buf_sz; 54462306a36Sopenharmony_ci int watermark; 54562306a36Sopenharmony_ci s64 dma_ts; 54662306a36Sopenharmony_ci}; 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci/** 54962306a36Sopenharmony_ci * struct at91_adc_touch - at91-sama5d2 touchscreen information struct 55062306a36Sopenharmony_ci * @sample_period_val: the value for periodic trigger interval 55162306a36Sopenharmony_ci * @touching: is the pen touching the screen or not 55262306a36Sopenharmony_ci * @x_pos: temporary placeholder for pressure computation 55362306a36Sopenharmony_ci * @channels_bitmask: bitmask with the touchscreen channels enabled 55462306a36Sopenharmony_ci * @workq: workqueue for buffer data pushing 55562306a36Sopenharmony_ci */ 55662306a36Sopenharmony_cistruct at91_adc_touch { 55762306a36Sopenharmony_ci u16 sample_period_val; 55862306a36Sopenharmony_ci bool touching; 55962306a36Sopenharmony_ci u16 x_pos; 56062306a36Sopenharmony_ci unsigned long channels_bitmask; 56162306a36Sopenharmony_ci struct work_struct workq; 56262306a36Sopenharmony_ci}; 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_ci/** 56562306a36Sopenharmony_ci * struct at91_adc_temp - at91-sama5d2 temperature information structure 56662306a36Sopenharmony_ci * @sample_period_val: sample period value 56762306a36Sopenharmony_ci * @saved_sample_rate: saved sample rate 56862306a36Sopenharmony_ci * @saved_oversampling: saved oversampling 56962306a36Sopenharmony_ci */ 57062306a36Sopenharmony_cistruct at91_adc_temp { 57162306a36Sopenharmony_ci u16 sample_period_val; 57262306a36Sopenharmony_ci u16 saved_sample_rate; 57362306a36Sopenharmony_ci u16 saved_oversampling; 57462306a36Sopenharmony_ci}; 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci/* 57762306a36Sopenharmony_ci * Buffer size requirements: 57862306a36Sopenharmony_ci * No channels * bytes_per_channel(2) + timestamp bytes (8) 57962306a36Sopenharmony_ci * Divided by 2 because we need half words. 58062306a36Sopenharmony_ci * We assume 32 channels for now, has to be increased if needed. 58162306a36Sopenharmony_ci * Nobody minds a buffer being too big. 58262306a36Sopenharmony_ci */ 58362306a36Sopenharmony_ci#define AT91_BUFFER_MAX_HWORDS ((32 * 2 + 8) / 2) 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_cistruct at91_adc_state { 58662306a36Sopenharmony_ci void __iomem *base; 58762306a36Sopenharmony_ci int irq; 58862306a36Sopenharmony_ci struct clk *per_clk; 58962306a36Sopenharmony_ci struct regulator *reg; 59062306a36Sopenharmony_ci struct regulator *vref; 59162306a36Sopenharmony_ci int vref_uv; 59262306a36Sopenharmony_ci unsigned int current_sample_rate; 59362306a36Sopenharmony_ci struct iio_trigger *trig; 59462306a36Sopenharmony_ci const struct at91_adc_trigger *selected_trig; 59562306a36Sopenharmony_ci const struct iio_chan_spec *chan; 59662306a36Sopenharmony_ci bool conversion_done; 59762306a36Sopenharmony_ci u32 conversion_value; 59862306a36Sopenharmony_ci unsigned int oversampling_ratio; 59962306a36Sopenharmony_ci struct at91_adc_soc_info soc_info; 60062306a36Sopenharmony_ci wait_queue_head_t wq_data_available; 60162306a36Sopenharmony_ci struct at91_adc_dma dma_st; 60262306a36Sopenharmony_ci struct at91_adc_touch touch_st; 60362306a36Sopenharmony_ci struct at91_adc_temp temp_st; 60462306a36Sopenharmony_ci struct iio_dev *indio_dev; 60562306a36Sopenharmony_ci struct device *dev; 60662306a36Sopenharmony_ci /* Ensure naturally aligned timestamp */ 60762306a36Sopenharmony_ci u16 buffer[AT91_BUFFER_MAX_HWORDS] __aligned(8); 60862306a36Sopenharmony_ci /* 60962306a36Sopenharmony_ci * lock to prevent concurrent 'single conversion' requests through 61062306a36Sopenharmony_ci * sysfs. 61162306a36Sopenharmony_ci */ 61262306a36Sopenharmony_ci struct mutex lock; 61362306a36Sopenharmony_ci}; 61462306a36Sopenharmony_ci 61562306a36Sopenharmony_cistatic const struct at91_adc_trigger at91_adc_trigger_list[] = { 61662306a36Sopenharmony_ci { 61762306a36Sopenharmony_ci .name = "external_rising", 61862306a36Sopenharmony_ci .trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_RISE, 61962306a36Sopenharmony_ci .edge_type = IRQ_TYPE_EDGE_RISING, 62062306a36Sopenharmony_ci .hw_trig = true, 62162306a36Sopenharmony_ci }, 62262306a36Sopenharmony_ci { 62362306a36Sopenharmony_ci .name = "external_falling", 62462306a36Sopenharmony_ci .trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_FALL, 62562306a36Sopenharmony_ci .edge_type = IRQ_TYPE_EDGE_FALLING, 62662306a36Sopenharmony_ci .hw_trig = true, 62762306a36Sopenharmony_ci }, 62862306a36Sopenharmony_ci { 62962306a36Sopenharmony_ci .name = "external_any", 63062306a36Sopenharmony_ci .trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_ANY, 63162306a36Sopenharmony_ci .edge_type = IRQ_TYPE_EDGE_BOTH, 63262306a36Sopenharmony_ci .hw_trig = true, 63362306a36Sopenharmony_ci }, 63462306a36Sopenharmony_ci { 63562306a36Sopenharmony_ci .name = "software", 63662306a36Sopenharmony_ci .trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_NO_TRIGGER, 63762306a36Sopenharmony_ci .edge_type = IRQ_TYPE_NONE, 63862306a36Sopenharmony_ci .hw_trig = false, 63962306a36Sopenharmony_ci }, 64062306a36Sopenharmony_ci}; 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_cistatic const struct iio_chan_spec at91_sama5d2_adc_channels[] = { 64362306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_SINGLE(0, 0, 0x50), 64462306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_SINGLE(1, 1, 0x54), 64562306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_SINGLE(2, 2, 0x58), 64662306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_SINGLE(3, 3, 0x5c), 64762306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_SINGLE(4, 4, 0x60), 64862306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_SINGLE(5, 5, 0x64), 64962306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_SINGLE(6, 6, 0x68), 65062306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_SINGLE(7, 7, 0x6c), 65162306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_SINGLE(8, 8, 0x70), 65262306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_SINGLE(9, 9, 0x74), 65362306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_SINGLE(10, 10, 0x78), 65462306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_SINGLE(11, 11, 0x7c), 65562306a36Sopenharmony_ci /* original ABI has the differential channels with a gap in between */ 65662306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_DIFF(12, 0, 1, 0x50), 65762306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_DIFF(14, 2, 3, 0x58), 65862306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_DIFF(16, 4, 5, 0x60), 65962306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_DIFF(18, 6, 7, 0x68), 66062306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_DIFF(20, 8, 9, 0x70), 66162306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_DIFF(22, 10, 11, 0x78), 66262306a36Sopenharmony_ci IIO_CHAN_SOFT_TIMESTAMP(23), 66362306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_TOUCH(24, "x", IIO_MOD_X), 66462306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_TOUCH(25, "y", IIO_MOD_Y), 66562306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_PRESSURE(26, "pressure"), 66662306a36Sopenharmony_ci}; 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_cistatic const struct iio_chan_spec at91_sama7g5_adc_channels[] = { 66962306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_SINGLE(0, 0, 0x60), 67062306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_SINGLE(1, 1, 0x64), 67162306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_SINGLE(2, 2, 0x68), 67262306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_SINGLE(3, 3, 0x6c), 67362306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_SINGLE(4, 4, 0x70), 67462306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_SINGLE(5, 5, 0x74), 67562306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_SINGLE(6, 6, 0x78), 67662306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_SINGLE(7, 7, 0x7c), 67762306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_SINGLE(8, 8, 0x80), 67862306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_SINGLE(9, 9, 0x84), 67962306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_SINGLE(10, 10, 0x88), 68062306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_SINGLE(11, 11, 0x8c), 68162306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_SINGLE(12, 12, 0x90), 68262306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_SINGLE(13, 13, 0x94), 68362306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_SINGLE(14, 14, 0x98), 68462306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_SINGLE(15, 15, 0x9c), 68562306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_DIFF(16, 0, 1, 0x60), 68662306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_DIFF(17, 2, 3, 0x68), 68762306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_DIFF(18, 4, 5, 0x70), 68862306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_DIFF(19, 6, 7, 0x78), 68962306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_DIFF(20, 8, 9, 0x80), 69062306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_DIFF(21, 10, 11, 0x88), 69162306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_DIFF(22, 12, 13, 0x90), 69262306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_DIFF(23, 14, 15, 0x98), 69362306a36Sopenharmony_ci IIO_CHAN_SOFT_TIMESTAMP(24), 69462306a36Sopenharmony_ci AT91_SAMA5D2_CHAN_TEMP(AT91_SAMA7G5_ADC_TEMP_CHANNEL, "temp", 0xdc), 69562306a36Sopenharmony_ci}; 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_cistatic const struct at91_adc_platform sama5d2_platform = { 69862306a36Sopenharmony_ci .layout = &sama5d2_layout, 69962306a36Sopenharmony_ci .adc_channels = &at91_sama5d2_adc_channels, 70062306a36Sopenharmony_ci#define AT91_SAMA5D2_SINGLE_CHAN_CNT 12 70162306a36Sopenharmony_ci#define AT91_SAMA5D2_DIFF_CHAN_CNT 6 70262306a36Sopenharmony_ci .nr_channels = AT91_SAMA5D2_SINGLE_CHAN_CNT + 70362306a36Sopenharmony_ci AT91_SAMA5D2_DIFF_CHAN_CNT, 70462306a36Sopenharmony_ci#define AT91_SAMA5D2_TOUCH_X_CHAN_IDX (AT91_SAMA5D2_SINGLE_CHAN_CNT + \ 70562306a36Sopenharmony_ci AT91_SAMA5D2_DIFF_CHAN_CNT * 2) 70662306a36Sopenharmony_ci .touch_chan_x = AT91_SAMA5D2_TOUCH_X_CHAN_IDX, 70762306a36Sopenharmony_ci#define AT91_SAMA5D2_TOUCH_Y_CHAN_IDX (AT91_SAMA5D2_TOUCH_X_CHAN_IDX + 1) 70862306a36Sopenharmony_ci .touch_chan_y = AT91_SAMA5D2_TOUCH_Y_CHAN_IDX, 70962306a36Sopenharmony_ci#define AT91_SAMA5D2_TOUCH_P_CHAN_IDX (AT91_SAMA5D2_TOUCH_Y_CHAN_IDX + 1) 71062306a36Sopenharmony_ci .touch_chan_p = AT91_SAMA5D2_TOUCH_P_CHAN_IDX, 71162306a36Sopenharmony_ci#define AT91_SAMA5D2_MAX_CHAN_IDX AT91_SAMA5D2_TOUCH_P_CHAN_IDX 71262306a36Sopenharmony_ci .max_channels = ARRAY_SIZE(at91_sama5d2_adc_channels), 71362306a36Sopenharmony_ci .max_index = AT91_SAMA5D2_MAX_CHAN_IDX, 71462306a36Sopenharmony_ci#define AT91_SAMA5D2_HW_TRIG_CNT 3 71562306a36Sopenharmony_ci .hw_trig_cnt = AT91_SAMA5D2_HW_TRIG_CNT, 71662306a36Sopenharmony_ci .osr_mask = GENMASK(17, 16), 71762306a36Sopenharmony_ci .oversampling_avail = { 1, 4, 16, }, 71862306a36Sopenharmony_ci .oversampling_avail_no = 3, 71962306a36Sopenharmony_ci .chan_realbits = 14, 72062306a36Sopenharmony_ci}; 72162306a36Sopenharmony_ci 72262306a36Sopenharmony_cistatic const struct at91_adc_platform sama7g5_platform = { 72362306a36Sopenharmony_ci .layout = &sama7g5_layout, 72462306a36Sopenharmony_ci .adc_channels = &at91_sama7g5_adc_channels, 72562306a36Sopenharmony_ci#define AT91_SAMA7G5_SINGLE_CHAN_CNT 16 72662306a36Sopenharmony_ci#define AT91_SAMA7G5_DIFF_CHAN_CNT 8 72762306a36Sopenharmony_ci#define AT91_SAMA7G5_TEMP_CHAN_CNT 1 72862306a36Sopenharmony_ci .nr_channels = AT91_SAMA7G5_SINGLE_CHAN_CNT + 72962306a36Sopenharmony_ci AT91_SAMA7G5_DIFF_CHAN_CNT + 73062306a36Sopenharmony_ci AT91_SAMA7G5_TEMP_CHAN_CNT, 73162306a36Sopenharmony_ci#define AT91_SAMA7G5_MAX_CHAN_IDX (AT91_SAMA7G5_SINGLE_CHAN_CNT + \ 73262306a36Sopenharmony_ci AT91_SAMA7G5_DIFF_CHAN_CNT + \ 73362306a36Sopenharmony_ci AT91_SAMA7G5_TEMP_CHAN_CNT) 73462306a36Sopenharmony_ci .max_channels = ARRAY_SIZE(at91_sama7g5_adc_channels), 73562306a36Sopenharmony_ci .max_index = AT91_SAMA7G5_MAX_CHAN_IDX, 73662306a36Sopenharmony_ci#define AT91_SAMA7G5_HW_TRIG_CNT 3 73762306a36Sopenharmony_ci .hw_trig_cnt = AT91_SAMA7G5_HW_TRIG_CNT, 73862306a36Sopenharmony_ci .osr_mask = GENMASK(18, 16), 73962306a36Sopenharmony_ci .oversampling_avail = { 1, 4, 16, 64, 256, }, 74062306a36Sopenharmony_ci .oversampling_avail_no = 5, 74162306a36Sopenharmony_ci .chan_realbits = 16, 74262306a36Sopenharmony_ci .temp_sensor = true, 74362306a36Sopenharmony_ci .temp_chan = AT91_SAMA7G5_ADC_TEMP_CHANNEL, 74462306a36Sopenharmony_ci}; 74562306a36Sopenharmony_ci 74662306a36Sopenharmony_cistatic int at91_adc_chan_xlate(struct iio_dev *indio_dev, int chan) 74762306a36Sopenharmony_ci{ 74862306a36Sopenharmony_ci int i; 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_ci for (i = 0; i < indio_dev->num_channels; i++) { 75162306a36Sopenharmony_ci if (indio_dev->channels[i].scan_index == chan) 75262306a36Sopenharmony_ci return i; 75362306a36Sopenharmony_ci } 75462306a36Sopenharmony_ci return -EINVAL; 75562306a36Sopenharmony_ci} 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_cistatic inline struct iio_chan_spec const * 75862306a36Sopenharmony_ciat91_adc_chan_get(struct iio_dev *indio_dev, int chan) 75962306a36Sopenharmony_ci{ 76062306a36Sopenharmony_ci int index = at91_adc_chan_xlate(indio_dev, chan); 76162306a36Sopenharmony_ci 76262306a36Sopenharmony_ci if (index < 0) 76362306a36Sopenharmony_ci return NULL; 76462306a36Sopenharmony_ci return indio_dev->channels + index; 76562306a36Sopenharmony_ci} 76662306a36Sopenharmony_ci 76762306a36Sopenharmony_cistatic inline int at91_adc_fwnode_xlate(struct iio_dev *indio_dev, 76862306a36Sopenharmony_ci const struct fwnode_reference_args *iiospec) 76962306a36Sopenharmony_ci{ 77062306a36Sopenharmony_ci return at91_adc_chan_xlate(indio_dev, iiospec->args[0]); 77162306a36Sopenharmony_ci} 77262306a36Sopenharmony_ci 77362306a36Sopenharmony_cistatic unsigned int at91_adc_active_scan_mask_to_reg(struct iio_dev *indio_dev) 77462306a36Sopenharmony_ci{ 77562306a36Sopenharmony_ci u32 mask = 0; 77662306a36Sopenharmony_ci u8 bit; 77762306a36Sopenharmony_ci struct at91_adc_state *st = iio_priv(indio_dev); 77862306a36Sopenharmony_ci 77962306a36Sopenharmony_ci for_each_set_bit(bit, indio_dev->active_scan_mask, 78062306a36Sopenharmony_ci indio_dev->num_channels) { 78162306a36Sopenharmony_ci struct iio_chan_spec const *chan = 78262306a36Sopenharmony_ci at91_adc_chan_get(indio_dev, bit); 78362306a36Sopenharmony_ci mask |= BIT(chan->channel); 78462306a36Sopenharmony_ci } 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_ci return mask & GENMASK(st->soc_info.platform->nr_channels, 0); 78762306a36Sopenharmony_ci} 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_cistatic void at91_adc_cor(struct at91_adc_state *st, 79062306a36Sopenharmony_ci struct iio_chan_spec const *chan) 79162306a36Sopenharmony_ci{ 79262306a36Sopenharmony_ci u32 cor, cur_cor; 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_ci cor = BIT(chan->channel) | BIT(chan->channel2); 79562306a36Sopenharmony_ci 79662306a36Sopenharmony_ci cur_cor = at91_adc_readl(st, COR); 79762306a36Sopenharmony_ci cor <<= st->soc_info.platform->layout->COR_diff_offset; 79862306a36Sopenharmony_ci if (chan->differential) 79962306a36Sopenharmony_ci at91_adc_writel(st, COR, cur_cor | cor); 80062306a36Sopenharmony_ci else 80162306a36Sopenharmony_ci at91_adc_writel(st, COR, cur_cor & ~cor); 80262306a36Sopenharmony_ci} 80362306a36Sopenharmony_ci 80462306a36Sopenharmony_cistatic void at91_adc_irq_status(struct at91_adc_state *st, u32 *status, 80562306a36Sopenharmony_ci u32 *eoc) 80662306a36Sopenharmony_ci{ 80762306a36Sopenharmony_ci *status = at91_adc_readl(st, ISR); 80862306a36Sopenharmony_ci if (st->soc_info.platform->layout->EOC_ISR) 80962306a36Sopenharmony_ci *eoc = at91_adc_readl(st, EOC_ISR); 81062306a36Sopenharmony_ci else 81162306a36Sopenharmony_ci *eoc = *status; 81262306a36Sopenharmony_ci} 81362306a36Sopenharmony_ci 81462306a36Sopenharmony_cistatic void at91_adc_irq_mask(struct at91_adc_state *st, u32 *status, u32 *eoc) 81562306a36Sopenharmony_ci{ 81662306a36Sopenharmony_ci *status = at91_adc_readl(st, IMR); 81762306a36Sopenharmony_ci if (st->soc_info.platform->layout->EOC_IMR) 81862306a36Sopenharmony_ci *eoc = at91_adc_readl(st, EOC_IMR); 81962306a36Sopenharmony_ci else 82062306a36Sopenharmony_ci *eoc = *status; 82162306a36Sopenharmony_ci} 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_cistatic void at91_adc_eoc_dis(struct at91_adc_state *st, unsigned int channel) 82462306a36Sopenharmony_ci{ 82562306a36Sopenharmony_ci /* 82662306a36Sopenharmony_ci * On some products having the EOC bits in a separate register, 82762306a36Sopenharmony_ci * errata recommends not writing this register (EOC_IDR). 82862306a36Sopenharmony_ci * On products having the EOC bits in the IDR register, it's fine to write it. 82962306a36Sopenharmony_ci */ 83062306a36Sopenharmony_ci if (!st->soc_info.platform->layout->EOC_IDR) 83162306a36Sopenharmony_ci at91_adc_writel(st, IDR, BIT(channel)); 83262306a36Sopenharmony_ci} 83362306a36Sopenharmony_ci 83462306a36Sopenharmony_cistatic void at91_adc_eoc_ena(struct at91_adc_state *st, unsigned int channel) 83562306a36Sopenharmony_ci{ 83662306a36Sopenharmony_ci if (!st->soc_info.platform->layout->EOC_IDR) 83762306a36Sopenharmony_ci at91_adc_writel(st, IER, BIT(channel)); 83862306a36Sopenharmony_ci else 83962306a36Sopenharmony_ci at91_adc_writel(st, EOC_IER, BIT(channel)); 84062306a36Sopenharmony_ci} 84162306a36Sopenharmony_ci 84262306a36Sopenharmony_cistatic int at91_adc_config_emr(struct at91_adc_state *st, 84362306a36Sopenharmony_ci u32 oversampling_ratio, u32 trackx) 84462306a36Sopenharmony_ci{ 84562306a36Sopenharmony_ci /* configure the extended mode register */ 84662306a36Sopenharmony_ci unsigned int emr, osr; 84762306a36Sopenharmony_ci unsigned int osr_mask = st->soc_info.platform->osr_mask; 84862306a36Sopenharmony_ci int i, ret; 84962306a36Sopenharmony_ci 85062306a36Sopenharmony_ci /* Check against supported oversampling values. */ 85162306a36Sopenharmony_ci for (i = 0; i < st->soc_info.platform->oversampling_avail_no; i++) { 85262306a36Sopenharmony_ci if (oversampling_ratio == st->soc_info.platform->oversampling_avail[i]) 85362306a36Sopenharmony_ci break; 85462306a36Sopenharmony_ci } 85562306a36Sopenharmony_ci if (i == st->soc_info.platform->oversampling_avail_no) 85662306a36Sopenharmony_ci return -EINVAL; 85762306a36Sopenharmony_ci 85862306a36Sopenharmony_ci /* select oversampling ratio from configuration */ 85962306a36Sopenharmony_ci switch (oversampling_ratio) { 86062306a36Sopenharmony_ci case 1: 86162306a36Sopenharmony_ci osr = AT91_SAMA5D2_EMR_OSR(AT91_SAMA5D2_EMR_OSR_1SAMPLES, 86262306a36Sopenharmony_ci osr_mask); 86362306a36Sopenharmony_ci break; 86462306a36Sopenharmony_ci case 4: 86562306a36Sopenharmony_ci osr = AT91_SAMA5D2_EMR_OSR(AT91_SAMA5D2_EMR_OSR_4SAMPLES, 86662306a36Sopenharmony_ci osr_mask); 86762306a36Sopenharmony_ci break; 86862306a36Sopenharmony_ci case 16: 86962306a36Sopenharmony_ci osr = AT91_SAMA5D2_EMR_OSR(AT91_SAMA5D2_EMR_OSR_16SAMPLES, 87062306a36Sopenharmony_ci osr_mask); 87162306a36Sopenharmony_ci break; 87262306a36Sopenharmony_ci case 64: 87362306a36Sopenharmony_ci osr = AT91_SAMA5D2_EMR_OSR(AT91_SAMA5D2_EMR_OSR_64SAMPLES, 87462306a36Sopenharmony_ci osr_mask); 87562306a36Sopenharmony_ci break; 87662306a36Sopenharmony_ci case 256: 87762306a36Sopenharmony_ci osr = AT91_SAMA5D2_EMR_OSR(AT91_SAMA5D2_EMR_OSR_256SAMPLES, 87862306a36Sopenharmony_ci osr_mask); 87962306a36Sopenharmony_ci break; 88062306a36Sopenharmony_ci } 88162306a36Sopenharmony_ci 88262306a36Sopenharmony_ci ret = pm_runtime_resume_and_get(st->dev); 88362306a36Sopenharmony_ci if (ret < 0) 88462306a36Sopenharmony_ci return ret; 88562306a36Sopenharmony_ci 88662306a36Sopenharmony_ci emr = at91_adc_readl(st, EMR); 88762306a36Sopenharmony_ci /* select oversampling per single trigger event */ 88862306a36Sopenharmony_ci emr |= AT91_SAMA5D2_EMR_ASTE(1); 88962306a36Sopenharmony_ci /* delete leftover content if it's the case */ 89062306a36Sopenharmony_ci emr &= ~(osr_mask | AT91_SAMA5D2_TRACKX_MASK); 89162306a36Sopenharmony_ci /* Update osr and trackx. */ 89262306a36Sopenharmony_ci emr |= osr | AT91_SAMA5D2_TRACKX(trackx); 89362306a36Sopenharmony_ci at91_adc_writel(st, EMR, emr); 89462306a36Sopenharmony_ci 89562306a36Sopenharmony_ci pm_runtime_mark_last_busy(st->dev); 89662306a36Sopenharmony_ci pm_runtime_put_autosuspend(st->dev); 89762306a36Sopenharmony_ci 89862306a36Sopenharmony_ci st->oversampling_ratio = oversampling_ratio; 89962306a36Sopenharmony_ci 90062306a36Sopenharmony_ci return 0; 90162306a36Sopenharmony_ci} 90262306a36Sopenharmony_ci 90362306a36Sopenharmony_cistatic int at91_adc_adjust_val_osr(struct at91_adc_state *st, int *val) 90462306a36Sopenharmony_ci{ 90562306a36Sopenharmony_ci int nbits, diff; 90662306a36Sopenharmony_ci 90762306a36Sopenharmony_ci if (st->oversampling_ratio == 1) 90862306a36Sopenharmony_ci nbits = 12; 90962306a36Sopenharmony_ci else if (st->oversampling_ratio == 4) 91062306a36Sopenharmony_ci nbits = 13; 91162306a36Sopenharmony_ci else if (st->oversampling_ratio == 16) 91262306a36Sopenharmony_ci nbits = 14; 91362306a36Sopenharmony_ci else if (st->oversampling_ratio == 64) 91462306a36Sopenharmony_ci nbits = 15; 91562306a36Sopenharmony_ci else if (st->oversampling_ratio == 256) 91662306a36Sopenharmony_ci nbits = 16; 91762306a36Sopenharmony_ci else 91862306a36Sopenharmony_ci /* Should not happen. */ 91962306a36Sopenharmony_ci return -EINVAL; 92062306a36Sopenharmony_ci 92162306a36Sopenharmony_ci /* 92262306a36Sopenharmony_ci * We have nbits of real data and channel is registered as 92362306a36Sopenharmony_ci * st->soc_info.platform->chan_realbits, so shift left diff bits. 92462306a36Sopenharmony_ci */ 92562306a36Sopenharmony_ci diff = st->soc_info.platform->chan_realbits - nbits; 92662306a36Sopenharmony_ci *val <<= diff; 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_ci return IIO_VAL_INT; 92962306a36Sopenharmony_ci} 93062306a36Sopenharmony_ci 93162306a36Sopenharmony_cistatic void at91_adc_adjust_val_osr_array(struct at91_adc_state *st, void *buf, 93262306a36Sopenharmony_ci int len) 93362306a36Sopenharmony_ci{ 93462306a36Sopenharmony_ci int i = 0, val; 93562306a36Sopenharmony_ci u16 *buf_u16 = (u16 *) buf; 93662306a36Sopenharmony_ci 93762306a36Sopenharmony_ci /* 93862306a36Sopenharmony_ci * We are converting each two bytes (each sample). 93962306a36Sopenharmony_ci * First convert the byte based array to u16, and convert each sample 94062306a36Sopenharmony_ci * separately. 94162306a36Sopenharmony_ci * Each value is two bytes in an array of chars, so to not shift 94262306a36Sopenharmony_ci * more than we need, save the value separately. 94362306a36Sopenharmony_ci * len is in bytes, so divide by two to get number of samples. 94462306a36Sopenharmony_ci */ 94562306a36Sopenharmony_ci while (i < len / 2) { 94662306a36Sopenharmony_ci val = buf_u16[i]; 94762306a36Sopenharmony_ci at91_adc_adjust_val_osr(st, &val); 94862306a36Sopenharmony_ci buf_u16[i] = val; 94962306a36Sopenharmony_ci i++; 95062306a36Sopenharmony_ci } 95162306a36Sopenharmony_ci} 95262306a36Sopenharmony_ci 95362306a36Sopenharmony_cistatic int at91_adc_configure_touch(struct at91_adc_state *st, bool state) 95462306a36Sopenharmony_ci{ 95562306a36Sopenharmony_ci u32 clk_khz = st->current_sample_rate / 1000; 95662306a36Sopenharmony_ci int i = 0, ret; 95762306a36Sopenharmony_ci u16 pendbc; 95862306a36Sopenharmony_ci u32 tsmr, acr; 95962306a36Sopenharmony_ci 96062306a36Sopenharmony_ci if (state) { 96162306a36Sopenharmony_ci ret = pm_runtime_resume_and_get(st->dev); 96262306a36Sopenharmony_ci if (ret < 0) 96362306a36Sopenharmony_ci return ret; 96462306a36Sopenharmony_ci } else { 96562306a36Sopenharmony_ci /* disabling touch IRQs and setting mode to no touch enabled */ 96662306a36Sopenharmony_ci at91_adc_writel(st, IDR, 96762306a36Sopenharmony_ci AT91_SAMA5D2_IER_PEN | AT91_SAMA5D2_IER_NOPEN); 96862306a36Sopenharmony_ci at91_adc_writel(st, TSMR, 0); 96962306a36Sopenharmony_ci 97062306a36Sopenharmony_ci pm_runtime_mark_last_busy(st->dev); 97162306a36Sopenharmony_ci pm_runtime_put_autosuspend(st->dev); 97262306a36Sopenharmony_ci return 0; 97362306a36Sopenharmony_ci } 97462306a36Sopenharmony_ci /* 97562306a36Sopenharmony_ci * debounce time is in microseconds, we need it in milliseconds to 97662306a36Sopenharmony_ci * multiply with kilohertz, so, divide by 1000, but after the multiply. 97762306a36Sopenharmony_ci * round up to make sure pendbc is at least 1 97862306a36Sopenharmony_ci */ 97962306a36Sopenharmony_ci pendbc = round_up(AT91_SAMA5D2_TOUCH_PEN_DETECT_DEBOUNCE_US * 98062306a36Sopenharmony_ci clk_khz / 1000, 1); 98162306a36Sopenharmony_ci 98262306a36Sopenharmony_ci /* get the required exponent */ 98362306a36Sopenharmony_ci while (pendbc >> i++) 98462306a36Sopenharmony_ci ; 98562306a36Sopenharmony_ci 98662306a36Sopenharmony_ci pendbc = i; 98762306a36Sopenharmony_ci 98862306a36Sopenharmony_ci tsmr = AT91_SAMA5D2_TSMR_TSMODE_4WIRE_PRESS; 98962306a36Sopenharmony_ci 99062306a36Sopenharmony_ci tsmr |= AT91_SAMA5D2_TSMR_TSAV(2) & AT91_SAMA5D2_TSMR_TSAV_MASK; 99162306a36Sopenharmony_ci tsmr |= AT91_SAMA5D2_TSMR_PENDBC(pendbc) & 99262306a36Sopenharmony_ci AT91_SAMA5D2_TSMR_PENDBC_MASK; 99362306a36Sopenharmony_ci tsmr |= AT91_SAMA5D2_TSMR_NOTSDMA; 99462306a36Sopenharmony_ci tsmr |= AT91_SAMA5D2_TSMR_PENDET_ENA; 99562306a36Sopenharmony_ci tsmr |= AT91_SAMA5D2_TSMR_TSFREQ(2) & AT91_SAMA5D2_TSMR_TSFREQ_MASK; 99662306a36Sopenharmony_ci 99762306a36Sopenharmony_ci at91_adc_writel(st, TSMR, tsmr); 99862306a36Sopenharmony_ci 99962306a36Sopenharmony_ci acr = at91_adc_readl(st, ACR); 100062306a36Sopenharmony_ci acr &= ~AT91_SAMA5D2_ACR_PENDETSENS_MASK; 100162306a36Sopenharmony_ci acr |= 0x02 & AT91_SAMA5D2_ACR_PENDETSENS_MASK; 100262306a36Sopenharmony_ci at91_adc_writel(st, ACR, acr); 100362306a36Sopenharmony_ci 100462306a36Sopenharmony_ci /* Sample Period Time = (TRGPER + 1) / ADCClock */ 100562306a36Sopenharmony_ci st->touch_st.sample_period_val = 100662306a36Sopenharmony_ci round_up((AT91_SAMA5D2_TOUCH_SAMPLE_PERIOD_US * 100762306a36Sopenharmony_ci clk_khz / 1000) - 1, 1); 100862306a36Sopenharmony_ci /* enable pen detect IRQ */ 100962306a36Sopenharmony_ci at91_adc_writel(st, IER, AT91_SAMA5D2_IER_PEN); 101062306a36Sopenharmony_ci 101162306a36Sopenharmony_ci return 0; 101262306a36Sopenharmony_ci} 101362306a36Sopenharmony_ci 101462306a36Sopenharmony_cistatic u16 at91_adc_touch_pos(struct at91_adc_state *st, int reg) 101562306a36Sopenharmony_ci{ 101662306a36Sopenharmony_ci u32 val = 0; 101762306a36Sopenharmony_ci u32 scale, result, pos; 101862306a36Sopenharmony_ci 101962306a36Sopenharmony_ci /* 102062306a36Sopenharmony_ci * to obtain the actual position we must divide by scale 102162306a36Sopenharmony_ci * and multiply with max, where 102262306a36Sopenharmony_ci * max = 2^AT91_SAMA5D2_MAX_POS_BITS - 1 102362306a36Sopenharmony_ci */ 102462306a36Sopenharmony_ci /* first half of register is the x or y, second half is the scale */ 102562306a36Sopenharmony_ci if (reg == st->soc_info.platform->layout->XPOSR) 102662306a36Sopenharmony_ci val = at91_adc_readl(st, XPOSR); 102762306a36Sopenharmony_ci else if (reg == st->soc_info.platform->layout->YPOSR) 102862306a36Sopenharmony_ci val = at91_adc_readl(st, YPOSR); 102962306a36Sopenharmony_ci 103062306a36Sopenharmony_ci if (!val) 103162306a36Sopenharmony_ci dev_dbg(&st->indio_dev->dev, "pos is 0\n"); 103262306a36Sopenharmony_ci 103362306a36Sopenharmony_ci pos = val & AT91_SAMA5D2_XYZ_MASK; 103462306a36Sopenharmony_ci result = (pos << AT91_SAMA5D2_MAX_POS_BITS) - pos; 103562306a36Sopenharmony_ci scale = (val >> 16) & AT91_SAMA5D2_XYZ_MASK; 103662306a36Sopenharmony_ci if (scale == 0) { 103762306a36Sopenharmony_ci dev_err(&st->indio_dev->dev, "scale is 0\n"); 103862306a36Sopenharmony_ci return 0; 103962306a36Sopenharmony_ci } 104062306a36Sopenharmony_ci result /= scale; 104162306a36Sopenharmony_ci 104262306a36Sopenharmony_ci return result; 104362306a36Sopenharmony_ci} 104462306a36Sopenharmony_ci 104562306a36Sopenharmony_cistatic u16 at91_adc_touch_x_pos(struct at91_adc_state *st) 104662306a36Sopenharmony_ci{ 104762306a36Sopenharmony_ci st->touch_st.x_pos = at91_adc_touch_pos(st, st->soc_info.platform->layout->XPOSR); 104862306a36Sopenharmony_ci return st->touch_st.x_pos; 104962306a36Sopenharmony_ci} 105062306a36Sopenharmony_ci 105162306a36Sopenharmony_cistatic u16 at91_adc_touch_y_pos(struct at91_adc_state *st) 105262306a36Sopenharmony_ci{ 105362306a36Sopenharmony_ci return at91_adc_touch_pos(st, st->soc_info.platform->layout->YPOSR); 105462306a36Sopenharmony_ci} 105562306a36Sopenharmony_ci 105662306a36Sopenharmony_cistatic u16 at91_adc_touch_pressure(struct at91_adc_state *st) 105762306a36Sopenharmony_ci{ 105862306a36Sopenharmony_ci u32 val; 105962306a36Sopenharmony_ci u32 z1, z2; 106062306a36Sopenharmony_ci u32 pres; 106162306a36Sopenharmony_ci u32 rxp = 1; 106262306a36Sopenharmony_ci u32 factor = 1000; 106362306a36Sopenharmony_ci 106462306a36Sopenharmony_ci /* calculate the pressure */ 106562306a36Sopenharmony_ci val = at91_adc_readl(st, PRESSR); 106662306a36Sopenharmony_ci z1 = val & AT91_SAMA5D2_XYZ_MASK; 106762306a36Sopenharmony_ci z2 = (val >> 16) & AT91_SAMA5D2_XYZ_MASK; 106862306a36Sopenharmony_ci 106962306a36Sopenharmony_ci if (z1 != 0) 107062306a36Sopenharmony_ci pres = rxp * (st->touch_st.x_pos * factor / 1024) * 107162306a36Sopenharmony_ci (z2 * factor / z1 - factor) / 107262306a36Sopenharmony_ci factor; 107362306a36Sopenharmony_ci else 107462306a36Sopenharmony_ci pres = 0xFFFF; /* no pen contact */ 107562306a36Sopenharmony_ci 107662306a36Sopenharmony_ci /* 107762306a36Sopenharmony_ci * The pressure from device grows down, minimum is 0xFFFF, maximum 0x0. 107862306a36Sopenharmony_ci * We compute it this way, but let's return it in the expected way, 107962306a36Sopenharmony_ci * growing from 0 to 0xFFFF. 108062306a36Sopenharmony_ci */ 108162306a36Sopenharmony_ci return 0xFFFF - pres; 108262306a36Sopenharmony_ci} 108362306a36Sopenharmony_ci 108462306a36Sopenharmony_cistatic int at91_adc_read_position(struct at91_adc_state *st, int chan, u16 *val) 108562306a36Sopenharmony_ci{ 108662306a36Sopenharmony_ci *val = 0; 108762306a36Sopenharmony_ci if (!st->touch_st.touching) 108862306a36Sopenharmony_ci return -ENODATA; 108962306a36Sopenharmony_ci if (chan == st->soc_info.platform->touch_chan_x) 109062306a36Sopenharmony_ci *val = at91_adc_touch_x_pos(st); 109162306a36Sopenharmony_ci else if (chan == st->soc_info.platform->touch_chan_y) 109262306a36Sopenharmony_ci *val = at91_adc_touch_y_pos(st); 109362306a36Sopenharmony_ci else 109462306a36Sopenharmony_ci return -ENODATA; 109562306a36Sopenharmony_ci 109662306a36Sopenharmony_ci return IIO_VAL_INT; 109762306a36Sopenharmony_ci} 109862306a36Sopenharmony_ci 109962306a36Sopenharmony_cistatic int at91_adc_read_pressure(struct at91_adc_state *st, int chan, u16 *val) 110062306a36Sopenharmony_ci{ 110162306a36Sopenharmony_ci *val = 0; 110262306a36Sopenharmony_ci if (!st->touch_st.touching) 110362306a36Sopenharmony_ci return -ENODATA; 110462306a36Sopenharmony_ci if (chan == st->soc_info.platform->touch_chan_p) 110562306a36Sopenharmony_ci *val = at91_adc_touch_pressure(st); 110662306a36Sopenharmony_ci else 110762306a36Sopenharmony_ci return -ENODATA; 110862306a36Sopenharmony_ci 110962306a36Sopenharmony_ci return IIO_VAL_INT; 111062306a36Sopenharmony_ci} 111162306a36Sopenharmony_ci 111262306a36Sopenharmony_cistatic void at91_adc_configure_trigger_registers(struct at91_adc_state *st, 111362306a36Sopenharmony_ci bool state) 111462306a36Sopenharmony_ci{ 111562306a36Sopenharmony_ci u32 status = at91_adc_readl(st, TRGR); 111662306a36Sopenharmony_ci 111762306a36Sopenharmony_ci /* clear TRGMOD */ 111862306a36Sopenharmony_ci status &= ~AT91_SAMA5D2_TRGR_TRGMOD_MASK; 111962306a36Sopenharmony_ci 112062306a36Sopenharmony_ci if (state) 112162306a36Sopenharmony_ci status |= st->selected_trig->trgmod_value; 112262306a36Sopenharmony_ci 112362306a36Sopenharmony_ci /* set/unset hw trigger */ 112462306a36Sopenharmony_ci at91_adc_writel(st, TRGR, status); 112562306a36Sopenharmony_ci} 112662306a36Sopenharmony_ci 112762306a36Sopenharmony_cistatic int at91_adc_configure_trigger(struct iio_trigger *trig, bool state) 112862306a36Sopenharmony_ci{ 112962306a36Sopenharmony_ci struct iio_dev *indio = iio_trigger_get_drvdata(trig); 113062306a36Sopenharmony_ci struct at91_adc_state *st = iio_priv(indio); 113162306a36Sopenharmony_ci int ret; 113262306a36Sopenharmony_ci 113362306a36Sopenharmony_ci if (state) { 113462306a36Sopenharmony_ci ret = pm_runtime_resume_and_get(st->dev); 113562306a36Sopenharmony_ci if (ret < 0) 113662306a36Sopenharmony_ci return ret; 113762306a36Sopenharmony_ci } 113862306a36Sopenharmony_ci 113962306a36Sopenharmony_ci at91_adc_configure_trigger_registers(st, state); 114062306a36Sopenharmony_ci 114162306a36Sopenharmony_ci if (!state) { 114262306a36Sopenharmony_ci pm_runtime_mark_last_busy(st->dev); 114362306a36Sopenharmony_ci pm_runtime_put_autosuspend(st->dev); 114462306a36Sopenharmony_ci } 114562306a36Sopenharmony_ci 114662306a36Sopenharmony_ci return 0; 114762306a36Sopenharmony_ci} 114862306a36Sopenharmony_ci 114962306a36Sopenharmony_cistatic void at91_adc_reenable_trigger(struct iio_trigger *trig) 115062306a36Sopenharmony_ci{ 115162306a36Sopenharmony_ci struct iio_dev *indio = iio_trigger_get_drvdata(trig); 115262306a36Sopenharmony_ci struct at91_adc_state *st = iio_priv(indio); 115362306a36Sopenharmony_ci 115462306a36Sopenharmony_ci /* if we are using DMA, we must not reenable irq after each trigger */ 115562306a36Sopenharmony_ci if (st->dma_st.dma_chan) 115662306a36Sopenharmony_ci return; 115762306a36Sopenharmony_ci 115862306a36Sopenharmony_ci enable_irq(st->irq); 115962306a36Sopenharmony_ci 116062306a36Sopenharmony_ci /* Needed to ACK the DRDY interruption */ 116162306a36Sopenharmony_ci at91_adc_readl(st, LCDR); 116262306a36Sopenharmony_ci} 116362306a36Sopenharmony_ci 116462306a36Sopenharmony_cistatic const struct iio_trigger_ops at91_adc_trigger_ops = { 116562306a36Sopenharmony_ci .set_trigger_state = &at91_adc_configure_trigger, 116662306a36Sopenharmony_ci .reenable = &at91_adc_reenable_trigger, 116762306a36Sopenharmony_ci .validate_device = iio_trigger_validate_own_device, 116862306a36Sopenharmony_ci}; 116962306a36Sopenharmony_ci 117062306a36Sopenharmony_cistatic int at91_adc_dma_size_done(struct at91_adc_state *st) 117162306a36Sopenharmony_ci{ 117262306a36Sopenharmony_ci struct dma_tx_state state; 117362306a36Sopenharmony_ci enum dma_status status; 117462306a36Sopenharmony_ci int i, size; 117562306a36Sopenharmony_ci 117662306a36Sopenharmony_ci status = dmaengine_tx_status(st->dma_st.dma_chan, 117762306a36Sopenharmony_ci st->dma_st.dma_chan->cookie, 117862306a36Sopenharmony_ci &state); 117962306a36Sopenharmony_ci if (status != DMA_IN_PROGRESS) 118062306a36Sopenharmony_ci return 0; 118162306a36Sopenharmony_ci 118262306a36Sopenharmony_ci /* Transferred length is size in bytes from end of buffer */ 118362306a36Sopenharmony_ci i = st->dma_st.rx_buf_sz - state.residue; 118462306a36Sopenharmony_ci 118562306a36Sopenharmony_ci /* Return available bytes */ 118662306a36Sopenharmony_ci if (i >= st->dma_st.buf_idx) 118762306a36Sopenharmony_ci size = i - st->dma_st.buf_idx; 118862306a36Sopenharmony_ci else 118962306a36Sopenharmony_ci size = st->dma_st.rx_buf_sz + i - st->dma_st.buf_idx; 119062306a36Sopenharmony_ci return size; 119162306a36Sopenharmony_ci} 119262306a36Sopenharmony_ci 119362306a36Sopenharmony_cistatic void at91_dma_buffer_done(void *data) 119462306a36Sopenharmony_ci{ 119562306a36Sopenharmony_ci struct iio_dev *indio_dev = data; 119662306a36Sopenharmony_ci 119762306a36Sopenharmony_ci iio_trigger_poll_nested(indio_dev->trig); 119862306a36Sopenharmony_ci} 119962306a36Sopenharmony_ci 120062306a36Sopenharmony_cistatic int at91_adc_dma_start(struct iio_dev *indio_dev) 120162306a36Sopenharmony_ci{ 120262306a36Sopenharmony_ci struct at91_adc_state *st = iio_priv(indio_dev); 120362306a36Sopenharmony_ci struct dma_async_tx_descriptor *desc; 120462306a36Sopenharmony_ci dma_cookie_t cookie; 120562306a36Sopenharmony_ci int ret; 120662306a36Sopenharmony_ci u8 bit; 120762306a36Sopenharmony_ci 120862306a36Sopenharmony_ci if (!st->dma_st.dma_chan) 120962306a36Sopenharmony_ci return 0; 121062306a36Sopenharmony_ci 121162306a36Sopenharmony_ci /* we start a new DMA, so set buffer index to start */ 121262306a36Sopenharmony_ci st->dma_st.buf_idx = 0; 121362306a36Sopenharmony_ci 121462306a36Sopenharmony_ci /* 121562306a36Sopenharmony_ci * compute buffer size w.r.t. watermark and enabled channels. 121662306a36Sopenharmony_ci * scan_bytes is aligned so we need an exact size for DMA 121762306a36Sopenharmony_ci */ 121862306a36Sopenharmony_ci st->dma_st.rx_buf_sz = 0; 121962306a36Sopenharmony_ci 122062306a36Sopenharmony_ci for_each_set_bit(bit, indio_dev->active_scan_mask, 122162306a36Sopenharmony_ci indio_dev->num_channels) { 122262306a36Sopenharmony_ci struct iio_chan_spec const *chan = 122362306a36Sopenharmony_ci at91_adc_chan_get(indio_dev, bit); 122462306a36Sopenharmony_ci 122562306a36Sopenharmony_ci if (!chan) 122662306a36Sopenharmony_ci continue; 122762306a36Sopenharmony_ci 122862306a36Sopenharmony_ci st->dma_st.rx_buf_sz += chan->scan_type.storagebits / 8; 122962306a36Sopenharmony_ci } 123062306a36Sopenharmony_ci st->dma_st.rx_buf_sz *= st->dma_st.watermark; 123162306a36Sopenharmony_ci 123262306a36Sopenharmony_ci /* Prepare a DMA cyclic transaction */ 123362306a36Sopenharmony_ci desc = dmaengine_prep_dma_cyclic(st->dma_st.dma_chan, 123462306a36Sopenharmony_ci st->dma_st.rx_dma_buf, 123562306a36Sopenharmony_ci st->dma_st.rx_buf_sz, 123662306a36Sopenharmony_ci st->dma_st.rx_buf_sz / 2, 123762306a36Sopenharmony_ci DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT); 123862306a36Sopenharmony_ci 123962306a36Sopenharmony_ci if (!desc) { 124062306a36Sopenharmony_ci dev_err(&indio_dev->dev, "cannot prepare DMA cyclic\n"); 124162306a36Sopenharmony_ci return -EBUSY; 124262306a36Sopenharmony_ci } 124362306a36Sopenharmony_ci 124462306a36Sopenharmony_ci desc->callback = at91_dma_buffer_done; 124562306a36Sopenharmony_ci desc->callback_param = indio_dev; 124662306a36Sopenharmony_ci 124762306a36Sopenharmony_ci cookie = dmaengine_submit(desc); 124862306a36Sopenharmony_ci ret = dma_submit_error(cookie); 124962306a36Sopenharmony_ci if (ret) { 125062306a36Sopenharmony_ci dev_err(&indio_dev->dev, "cannot submit DMA cyclic\n"); 125162306a36Sopenharmony_ci dmaengine_terminate_async(st->dma_st.dma_chan); 125262306a36Sopenharmony_ci return ret; 125362306a36Sopenharmony_ci } 125462306a36Sopenharmony_ci 125562306a36Sopenharmony_ci /* enable general overrun error signaling */ 125662306a36Sopenharmony_ci at91_adc_writel(st, IER, AT91_SAMA5D2_IER_GOVRE); 125762306a36Sopenharmony_ci /* Issue pending DMA requests */ 125862306a36Sopenharmony_ci dma_async_issue_pending(st->dma_st.dma_chan); 125962306a36Sopenharmony_ci 126062306a36Sopenharmony_ci /* consider current time as DMA start time for timestamps */ 126162306a36Sopenharmony_ci st->dma_st.dma_ts = iio_get_time_ns(indio_dev); 126262306a36Sopenharmony_ci 126362306a36Sopenharmony_ci dev_dbg(&indio_dev->dev, "DMA cyclic started\n"); 126462306a36Sopenharmony_ci 126562306a36Sopenharmony_ci return 0; 126662306a36Sopenharmony_ci} 126762306a36Sopenharmony_ci 126862306a36Sopenharmony_cistatic bool at91_adc_buffer_check_use_irq(struct iio_dev *indio, 126962306a36Sopenharmony_ci struct at91_adc_state *st) 127062306a36Sopenharmony_ci{ 127162306a36Sopenharmony_ci /* if using DMA, we do not use our own IRQ (we use DMA-controller) */ 127262306a36Sopenharmony_ci if (st->dma_st.dma_chan) 127362306a36Sopenharmony_ci return false; 127462306a36Sopenharmony_ci /* if the trigger is not ours, then it has its own IRQ */ 127562306a36Sopenharmony_ci if (iio_trigger_validate_own_device(indio->trig, indio)) 127662306a36Sopenharmony_ci return false; 127762306a36Sopenharmony_ci return true; 127862306a36Sopenharmony_ci} 127962306a36Sopenharmony_ci 128062306a36Sopenharmony_cistatic bool at91_adc_current_chan_is_touch(struct iio_dev *indio_dev) 128162306a36Sopenharmony_ci{ 128262306a36Sopenharmony_ci struct at91_adc_state *st = iio_priv(indio_dev); 128362306a36Sopenharmony_ci 128462306a36Sopenharmony_ci return !!bitmap_subset(indio_dev->active_scan_mask, 128562306a36Sopenharmony_ci &st->touch_st.channels_bitmask, 128662306a36Sopenharmony_ci st->soc_info.platform->max_index + 1); 128762306a36Sopenharmony_ci} 128862306a36Sopenharmony_ci 128962306a36Sopenharmony_cistatic int at91_adc_buffer_prepare(struct iio_dev *indio_dev) 129062306a36Sopenharmony_ci{ 129162306a36Sopenharmony_ci int ret; 129262306a36Sopenharmony_ci u8 bit; 129362306a36Sopenharmony_ci struct at91_adc_state *st = iio_priv(indio_dev); 129462306a36Sopenharmony_ci 129562306a36Sopenharmony_ci /* check if we are enabling triggered buffer or the touchscreen */ 129662306a36Sopenharmony_ci if (at91_adc_current_chan_is_touch(indio_dev)) 129762306a36Sopenharmony_ci return at91_adc_configure_touch(st, true); 129862306a36Sopenharmony_ci 129962306a36Sopenharmony_ci /* if we are not in triggered mode, we cannot enable the buffer. */ 130062306a36Sopenharmony_ci if (!(iio_device_get_current_mode(indio_dev) & INDIO_ALL_TRIGGERED_MODES)) 130162306a36Sopenharmony_ci return -EINVAL; 130262306a36Sopenharmony_ci 130362306a36Sopenharmony_ci ret = pm_runtime_resume_and_get(st->dev); 130462306a36Sopenharmony_ci if (ret < 0) 130562306a36Sopenharmony_ci return ret; 130662306a36Sopenharmony_ci 130762306a36Sopenharmony_ci /* we continue with the triggered buffer */ 130862306a36Sopenharmony_ci ret = at91_adc_dma_start(indio_dev); 130962306a36Sopenharmony_ci if (ret) { 131062306a36Sopenharmony_ci dev_err(&indio_dev->dev, "buffer prepare failed\n"); 131162306a36Sopenharmony_ci goto pm_runtime_put; 131262306a36Sopenharmony_ci } 131362306a36Sopenharmony_ci 131462306a36Sopenharmony_ci for_each_set_bit(bit, indio_dev->active_scan_mask, 131562306a36Sopenharmony_ci indio_dev->num_channels) { 131662306a36Sopenharmony_ci struct iio_chan_spec const *chan = 131762306a36Sopenharmony_ci at91_adc_chan_get(indio_dev, bit); 131862306a36Sopenharmony_ci if (!chan) 131962306a36Sopenharmony_ci continue; 132062306a36Sopenharmony_ci /* these channel types cannot be handled by this trigger */ 132162306a36Sopenharmony_ci if (chan->type == IIO_POSITIONRELATIVE || 132262306a36Sopenharmony_ci chan->type == IIO_PRESSURE || 132362306a36Sopenharmony_ci chan->type == IIO_TEMP) 132462306a36Sopenharmony_ci continue; 132562306a36Sopenharmony_ci 132662306a36Sopenharmony_ci at91_adc_cor(st, chan); 132762306a36Sopenharmony_ci 132862306a36Sopenharmony_ci at91_adc_writel(st, CHER, BIT(chan->channel)); 132962306a36Sopenharmony_ci } 133062306a36Sopenharmony_ci 133162306a36Sopenharmony_ci if (at91_adc_buffer_check_use_irq(indio_dev, st)) 133262306a36Sopenharmony_ci at91_adc_writel(st, IER, AT91_SAMA5D2_IER_DRDY); 133362306a36Sopenharmony_ci 133462306a36Sopenharmony_cipm_runtime_put: 133562306a36Sopenharmony_ci pm_runtime_mark_last_busy(st->dev); 133662306a36Sopenharmony_ci pm_runtime_put_autosuspend(st->dev); 133762306a36Sopenharmony_ci return ret; 133862306a36Sopenharmony_ci} 133962306a36Sopenharmony_ci 134062306a36Sopenharmony_cistatic int at91_adc_buffer_postdisable(struct iio_dev *indio_dev) 134162306a36Sopenharmony_ci{ 134262306a36Sopenharmony_ci struct at91_adc_state *st = iio_priv(indio_dev); 134362306a36Sopenharmony_ci int ret; 134462306a36Sopenharmony_ci u8 bit; 134562306a36Sopenharmony_ci 134662306a36Sopenharmony_ci /* check if we are disabling triggered buffer or the touchscreen */ 134762306a36Sopenharmony_ci if (at91_adc_current_chan_is_touch(indio_dev)) 134862306a36Sopenharmony_ci return at91_adc_configure_touch(st, false); 134962306a36Sopenharmony_ci 135062306a36Sopenharmony_ci /* if we are not in triggered mode, nothing to do here */ 135162306a36Sopenharmony_ci if (!(iio_device_get_current_mode(indio_dev) & INDIO_ALL_TRIGGERED_MODES)) 135262306a36Sopenharmony_ci return -EINVAL; 135362306a36Sopenharmony_ci 135462306a36Sopenharmony_ci ret = pm_runtime_resume_and_get(st->dev); 135562306a36Sopenharmony_ci if (ret < 0) 135662306a36Sopenharmony_ci return ret; 135762306a36Sopenharmony_ci 135862306a36Sopenharmony_ci /* 135962306a36Sopenharmony_ci * For each enable channel we must disable it in hardware. 136062306a36Sopenharmony_ci * In the case of DMA, we must read the last converted value 136162306a36Sopenharmony_ci * to clear EOC status and not get a possible interrupt later. 136262306a36Sopenharmony_ci * This value is being read by DMA from LCDR anyway, so it's not lost. 136362306a36Sopenharmony_ci */ 136462306a36Sopenharmony_ci for_each_set_bit(bit, indio_dev->active_scan_mask, 136562306a36Sopenharmony_ci indio_dev->num_channels) { 136662306a36Sopenharmony_ci struct iio_chan_spec const *chan = 136762306a36Sopenharmony_ci at91_adc_chan_get(indio_dev, bit); 136862306a36Sopenharmony_ci 136962306a36Sopenharmony_ci if (!chan) 137062306a36Sopenharmony_ci continue; 137162306a36Sopenharmony_ci /* these channel types are virtual, no need to do anything */ 137262306a36Sopenharmony_ci if (chan->type == IIO_POSITIONRELATIVE || 137362306a36Sopenharmony_ci chan->type == IIO_PRESSURE || 137462306a36Sopenharmony_ci chan->type == IIO_TEMP) 137562306a36Sopenharmony_ci continue; 137662306a36Sopenharmony_ci 137762306a36Sopenharmony_ci at91_adc_writel(st, CHDR, BIT(chan->channel)); 137862306a36Sopenharmony_ci 137962306a36Sopenharmony_ci if (st->dma_st.dma_chan) 138062306a36Sopenharmony_ci at91_adc_read_chan(st, chan->address); 138162306a36Sopenharmony_ci } 138262306a36Sopenharmony_ci 138362306a36Sopenharmony_ci if (at91_adc_buffer_check_use_irq(indio_dev, st)) 138462306a36Sopenharmony_ci at91_adc_writel(st, IDR, AT91_SAMA5D2_IER_DRDY); 138562306a36Sopenharmony_ci 138662306a36Sopenharmony_ci /* read overflow register to clear possible overflow status */ 138762306a36Sopenharmony_ci at91_adc_readl(st, OVER); 138862306a36Sopenharmony_ci 138962306a36Sopenharmony_ci /* if we are using DMA we must clear registers and end DMA */ 139062306a36Sopenharmony_ci if (st->dma_st.dma_chan) 139162306a36Sopenharmony_ci dmaengine_terminate_sync(st->dma_st.dma_chan); 139262306a36Sopenharmony_ci 139362306a36Sopenharmony_ci pm_runtime_mark_last_busy(st->dev); 139462306a36Sopenharmony_ci pm_runtime_put_autosuspend(st->dev); 139562306a36Sopenharmony_ci 139662306a36Sopenharmony_ci return 0; 139762306a36Sopenharmony_ci} 139862306a36Sopenharmony_ci 139962306a36Sopenharmony_cistatic const struct iio_buffer_setup_ops at91_buffer_setup_ops = { 140062306a36Sopenharmony_ci .postdisable = &at91_adc_buffer_postdisable, 140162306a36Sopenharmony_ci}; 140262306a36Sopenharmony_ci 140362306a36Sopenharmony_cistatic struct iio_trigger *at91_adc_allocate_trigger(struct iio_dev *indio, 140462306a36Sopenharmony_ci char *trigger_name) 140562306a36Sopenharmony_ci{ 140662306a36Sopenharmony_ci struct iio_trigger *trig; 140762306a36Sopenharmony_ci int ret; 140862306a36Sopenharmony_ci 140962306a36Sopenharmony_ci trig = devm_iio_trigger_alloc(&indio->dev, "%s-dev%d-%s", indio->name, 141062306a36Sopenharmony_ci iio_device_id(indio), trigger_name); 141162306a36Sopenharmony_ci if (!trig) 141262306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 141362306a36Sopenharmony_ci 141462306a36Sopenharmony_ci trig->dev.parent = indio->dev.parent; 141562306a36Sopenharmony_ci iio_trigger_set_drvdata(trig, indio); 141662306a36Sopenharmony_ci trig->ops = &at91_adc_trigger_ops; 141762306a36Sopenharmony_ci 141862306a36Sopenharmony_ci ret = devm_iio_trigger_register(&indio->dev, trig); 141962306a36Sopenharmony_ci if (ret) 142062306a36Sopenharmony_ci return ERR_PTR(ret); 142162306a36Sopenharmony_ci 142262306a36Sopenharmony_ci return trig; 142362306a36Sopenharmony_ci} 142462306a36Sopenharmony_ci 142562306a36Sopenharmony_cistatic void at91_adc_trigger_handler_nodma(struct iio_dev *indio_dev, 142662306a36Sopenharmony_ci struct iio_poll_func *pf) 142762306a36Sopenharmony_ci{ 142862306a36Sopenharmony_ci struct at91_adc_state *st = iio_priv(indio_dev); 142962306a36Sopenharmony_ci int i = 0; 143062306a36Sopenharmony_ci int val; 143162306a36Sopenharmony_ci u8 bit; 143262306a36Sopenharmony_ci u32 mask = at91_adc_active_scan_mask_to_reg(indio_dev); 143362306a36Sopenharmony_ci unsigned int timeout = 50; 143462306a36Sopenharmony_ci u32 status, imr, eoc = 0, eoc_imr; 143562306a36Sopenharmony_ci 143662306a36Sopenharmony_ci /* 143762306a36Sopenharmony_ci * Check if the conversion is ready. If not, wait a little bit, and 143862306a36Sopenharmony_ci * in case of timeout exit with an error. 143962306a36Sopenharmony_ci */ 144062306a36Sopenharmony_ci while (((eoc & mask) != mask) && timeout) { 144162306a36Sopenharmony_ci at91_adc_irq_status(st, &status, &eoc); 144262306a36Sopenharmony_ci at91_adc_irq_mask(st, &imr, &eoc_imr); 144362306a36Sopenharmony_ci usleep_range(50, 100); 144462306a36Sopenharmony_ci timeout--; 144562306a36Sopenharmony_ci } 144662306a36Sopenharmony_ci 144762306a36Sopenharmony_ci /* Cannot read data, not ready. Continue without reporting data */ 144862306a36Sopenharmony_ci if (!timeout) 144962306a36Sopenharmony_ci return; 145062306a36Sopenharmony_ci 145162306a36Sopenharmony_ci for_each_set_bit(bit, indio_dev->active_scan_mask, 145262306a36Sopenharmony_ci indio_dev->num_channels) { 145362306a36Sopenharmony_ci struct iio_chan_spec const *chan = 145462306a36Sopenharmony_ci at91_adc_chan_get(indio_dev, bit); 145562306a36Sopenharmony_ci 145662306a36Sopenharmony_ci if (!chan) 145762306a36Sopenharmony_ci continue; 145862306a36Sopenharmony_ci /* 145962306a36Sopenharmony_ci * Our external trigger only supports the voltage channels. 146062306a36Sopenharmony_ci * In case someone requested a different type of channel 146162306a36Sopenharmony_ci * just put zeroes to buffer. 146262306a36Sopenharmony_ci * This should not happen because we check the scan mode 146362306a36Sopenharmony_ci * and scan mask when we enable the buffer, and we don't allow 146462306a36Sopenharmony_ci * the buffer to start with a mixed mask (voltage and something 146562306a36Sopenharmony_ci * else). 146662306a36Sopenharmony_ci * Thus, emit a warning. 146762306a36Sopenharmony_ci */ 146862306a36Sopenharmony_ci if (chan->type == IIO_VOLTAGE) { 146962306a36Sopenharmony_ci val = at91_adc_read_chan(st, chan->address); 147062306a36Sopenharmony_ci at91_adc_adjust_val_osr(st, &val); 147162306a36Sopenharmony_ci st->buffer[i] = val; 147262306a36Sopenharmony_ci } else { 147362306a36Sopenharmony_ci st->buffer[i] = 0; 147462306a36Sopenharmony_ci WARN(true, "This trigger cannot handle this type of channel"); 147562306a36Sopenharmony_ci } 147662306a36Sopenharmony_ci i++; 147762306a36Sopenharmony_ci } 147862306a36Sopenharmony_ci iio_push_to_buffers_with_timestamp(indio_dev, st->buffer, 147962306a36Sopenharmony_ci pf->timestamp); 148062306a36Sopenharmony_ci} 148162306a36Sopenharmony_ci 148262306a36Sopenharmony_cistatic void at91_adc_trigger_handler_dma(struct iio_dev *indio_dev) 148362306a36Sopenharmony_ci{ 148462306a36Sopenharmony_ci struct at91_adc_state *st = iio_priv(indio_dev); 148562306a36Sopenharmony_ci int transferred_len = at91_adc_dma_size_done(st); 148662306a36Sopenharmony_ci s64 ns = iio_get_time_ns(indio_dev); 148762306a36Sopenharmony_ci s64 interval; 148862306a36Sopenharmony_ci int sample_index = 0, sample_count, sample_size; 148962306a36Sopenharmony_ci 149062306a36Sopenharmony_ci u32 status = at91_adc_readl(st, ISR); 149162306a36Sopenharmony_ci /* if we reached this point, we cannot sample faster */ 149262306a36Sopenharmony_ci if (status & AT91_SAMA5D2_IER_GOVRE) 149362306a36Sopenharmony_ci pr_info_ratelimited("%s: conversion overrun detected\n", 149462306a36Sopenharmony_ci indio_dev->name); 149562306a36Sopenharmony_ci 149662306a36Sopenharmony_ci sample_size = div_s64(st->dma_st.rx_buf_sz, st->dma_st.watermark); 149762306a36Sopenharmony_ci 149862306a36Sopenharmony_ci sample_count = div_s64(transferred_len, sample_size); 149962306a36Sopenharmony_ci 150062306a36Sopenharmony_ci /* 150162306a36Sopenharmony_ci * interval between samples is total time since last transfer handling 150262306a36Sopenharmony_ci * divided by the number of samples (total size divided by sample size) 150362306a36Sopenharmony_ci */ 150462306a36Sopenharmony_ci interval = div_s64((ns - st->dma_st.dma_ts), sample_count); 150562306a36Sopenharmony_ci 150662306a36Sopenharmony_ci while (transferred_len >= sample_size) { 150762306a36Sopenharmony_ci /* 150862306a36Sopenharmony_ci * for all the values in the current sample, 150962306a36Sopenharmony_ci * adjust the values inside the buffer for oversampling 151062306a36Sopenharmony_ci */ 151162306a36Sopenharmony_ci at91_adc_adjust_val_osr_array(st, 151262306a36Sopenharmony_ci &st->dma_st.rx_buf[st->dma_st.buf_idx], 151362306a36Sopenharmony_ci sample_size); 151462306a36Sopenharmony_ci 151562306a36Sopenharmony_ci iio_push_to_buffers_with_timestamp(indio_dev, 151662306a36Sopenharmony_ci (st->dma_st.rx_buf + st->dma_st.buf_idx), 151762306a36Sopenharmony_ci (st->dma_st.dma_ts + interval * sample_index)); 151862306a36Sopenharmony_ci /* adjust remaining length */ 151962306a36Sopenharmony_ci transferred_len -= sample_size; 152062306a36Sopenharmony_ci /* adjust buffer index */ 152162306a36Sopenharmony_ci st->dma_st.buf_idx += sample_size; 152262306a36Sopenharmony_ci /* in case of reaching end of buffer, reset index */ 152362306a36Sopenharmony_ci if (st->dma_st.buf_idx >= st->dma_st.rx_buf_sz) 152462306a36Sopenharmony_ci st->dma_st.buf_idx = 0; 152562306a36Sopenharmony_ci sample_index++; 152662306a36Sopenharmony_ci } 152762306a36Sopenharmony_ci /* adjust saved time for next transfer handling */ 152862306a36Sopenharmony_ci st->dma_st.dma_ts = iio_get_time_ns(indio_dev); 152962306a36Sopenharmony_ci} 153062306a36Sopenharmony_ci 153162306a36Sopenharmony_cistatic irqreturn_t at91_adc_trigger_handler(int irq, void *p) 153262306a36Sopenharmony_ci{ 153362306a36Sopenharmony_ci struct iio_poll_func *pf = p; 153462306a36Sopenharmony_ci struct iio_dev *indio_dev = pf->indio_dev; 153562306a36Sopenharmony_ci struct at91_adc_state *st = iio_priv(indio_dev); 153662306a36Sopenharmony_ci 153762306a36Sopenharmony_ci /* 153862306a36Sopenharmony_ci * If it's not our trigger, start a conversion now, as we are 153962306a36Sopenharmony_ci * actually polling the trigger now. 154062306a36Sopenharmony_ci */ 154162306a36Sopenharmony_ci if (iio_trigger_validate_own_device(indio_dev->trig, indio_dev)) 154262306a36Sopenharmony_ci at91_adc_writel(st, CR, AT91_SAMA5D2_CR_START); 154362306a36Sopenharmony_ci 154462306a36Sopenharmony_ci if (st->dma_st.dma_chan) 154562306a36Sopenharmony_ci at91_adc_trigger_handler_dma(indio_dev); 154662306a36Sopenharmony_ci else 154762306a36Sopenharmony_ci at91_adc_trigger_handler_nodma(indio_dev, pf); 154862306a36Sopenharmony_ci 154962306a36Sopenharmony_ci iio_trigger_notify_done(indio_dev->trig); 155062306a36Sopenharmony_ci 155162306a36Sopenharmony_ci return IRQ_HANDLED; 155262306a36Sopenharmony_ci} 155362306a36Sopenharmony_ci 155462306a36Sopenharmony_cistatic unsigned at91_adc_startup_time(unsigned startup_time_min, 155562306a36Sopenharmony_ci unsigned adc_clk_khz) 155662306a36Sopenharmony_ci{ 155762306a36Sopenharmony_ci static const unsigned int startup_lookup[] = { 155862306a36Sopenharmony_ci 0, 8, 16, 24, 155962306a36Sopenharmony_ci 64, 80, 96, 112, 156062306a36Sopenharmony_ci 512, 576, 640, 704, 156162306a36Sopenharmony_ci 768, 832, 896, 960 156262306a36Sopenharmony_ci }; 156362306a36Sopenharmony_ci unsigned ticks_min, i; 156462306a36Sopenharmony_ci 156562306a36Sopenharmony_ci /* 156662306a36Sopenharmony_ci * Since the adc frequency is checked before, there is no reason 156762306a36Sopenharmony_ci * to not meet the startup time constraint. 156862306a36Sopenharmony_ci */ 156962306a36Sopenharmony_ci 157062306a36Sopenharmony_ci ticks_min = startup_time_min * adc_clk_khz / 1000; 157162306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(startup_lookup); i++) 157262306a36Sopenharmony_ci if (startup_lookup[i] > ticks_min) 157362306a36Sopenharmony_ci break; 157462306a36Sopenharmony_ci 157562306a36Sopenharmony_ci return i; 157662306a36Sopenharmony_ci} 157762306a36Sopenharmony_ci 157862306a36Sopenharmony_cistatic void at91_adc_setup_samp_freq(struct iio_dev *indio_dev, unsigned freq, 157962306a36Sopenharmony_ci unsigned int startup_time, 158062306a36Sopenharmony_ci unsigned int tracktim) 158162306a36Sopenharmony_ci{ 158262306a36Sopenharmony_ci struct at91_adc_state *st = iio_priv(indio_dev); 158362306a36Sopenharmony_ci unsigned f_per, prescal, startup, mr; 158462306a36Sopenharmony_ci int ret; 158562306a36Sopenharmony_ci 158662306a36Sopenharmony_ci f_per = clk_get_rate(st->per_clk); 158762306a36Sopenharmony_ci prescal = (f_per / (2 * freq)) - 1; 158862306a36Sopenharmony_ci 158962306a36Sopenharmony_ci startup = at91_adc_startup_time(startup_time, freq / 1000); 159062306a36Sopenharmony_ci 159162306a36Sopenharmony_ci ret = pm_runtime_resume_and_get(st->dev); 159262306a36Sopenharmony_ci if (ret < 0) 159362306a36Sopenharmony_ci return; 159462306a36Sopenharmony_ci 159562306a36Sopenharmony_ci mr = at91_adc_readl(st, MR); 159662306a36Sopenharmony_ci mr &= ~(AT91_SAMA5D2_MR_STARTUP_MASK | AT91_SAMA5D2_MR_PRESCAL_MASK); 159762306a36Sopenharmony_ci mr |= AT91_SAMA5D2_MR_STARTUP(startup); 159862306a36Sopenharmony_ci mr |= AT91_SAMA5D2_MR_PRESCAL(prescal); 159962306a36Sopenharmony_ci mr |= AT91_SAMA5D2_MR_TRACKTIM(tracktim); 160062306a36Sopenharmony_ci at91_adc_writel(st, MR, mr); 160162306a36Sopenharmony_ci 160262306a36Sopenharmony_ci pm_runtime_mark_last_busy(st->dev); 160362306a36Sopenharmony_ci pm_runtime_put_autosuspend(st->dev); 160462306a36Sopenharmony_ci 160562306a36Sopenharmony_ci dev_dbg(&indio_dev->dev, "freq: %u, startup: %u, prescal: %u, tracktim=%u\n", 160662306a36Sopenharmony_ci freq, startup, prescal, tracktim); 160762306a36Sopenharmony_ci st->current_sample_rate = freq; 160862306a36Sopenharmony_ci} 160962306a36Sopenharmony_ci 161062306a36Sopenharmony_cistatic inline unsigned at91_adc_get_sample_freq(struct at91_adc_state *st) 161162306a36Sopenharmony_ci{ 161262306a36Sopenharmony_ci return st->current_sample_rate; 161362306a36Sopenharmony_ci} 161462306a36Sopenharmony_ci 161562306a36Sopenharmony_cistatic void at91_adc_touch_data_handler(struct iio_dev *indio_dev) 161662306a36Sopenharmony_ci{ 161762306a36Sopenharmony_ci struct at91_adc_state *st = iio_priv(indio_dev); 161862306a36Sopenharmony_ci u8 bit; 161962306a36Sopenharmony_ci u16 val; 162062306a36Sopenharmony_ci int i = 0; 162162306a36Sopenharmony_ci 162262306a36Sopenharmony_ci for_each_set_bit(bit, indio_dev->active_scan_mask, 162362306a36Sopenharmony_ci st->soc_info.platform->max_index + 1) { 162462306a36Sopenharmony_ci struct iio_chan_spec const *chan = 162562306a36Sopenharmony_ci at91_adc_chan_get(indio_dev, bit); 162662306a36Sopenharmony_ci 162762306a36Sopenharmony_ci if (chan->type == IIO_POSITIONRELATIVE) 162862306a36Sopenharmony_ci at91_adc_read_position(st, chan->channel, &val); 162962306a36Sopenharmony_ci else if (chan->type == IIO_PRESSURE) 163062306a36Sopenharmony_ci at91_adc_read_pressure(st, chan->channel, &val); 163162306a36Sopenharmony_ci else 163262306a36Sopenharmony_ci continue; 163362306a36Sopenharmony_ci st->buffer[i] = val; 163462306a36Sopenharmony_ci i++; 163562306a36Sopenharmony_ci } 163662306a36Sopenharmony_ci /* 163762306a36Sopenharmony_ci * Schedule work to push to buffers. 163862306a36Sopenharmony_ci * This is intended to push to the callback buffer that another driver 163962306a36Sopenharmony_ci * registered. We are still in a handler from our IRQ. If we push 164062306a36Sopenharmony_ci * directly, it means the other driver has it's callback called 164162306a36Sopenharmony_ci * from our IRQ context. Which is something we better avoid. 164262306a36Sopenharmony_ci * Let's schedule it after our IRQ is completed. 164362306a36Sopenharmony_ci */ 164462306a36Sopenharmony_ci schedule_work(&st->touch_st.workq); 164562306a36Sopenharmony_ci} 164662306a36Sopenharmony_ci 164762306a36Sopenharmony_cistatic void at91_adc_pen_detect_interrupt(struct at91_adc_state *st) 164862306a36Sopenharmony_ci{ 164962306a36Sopenharmony_ci at91_adc_writel(st, IDR, AT91_SAMA5D2_IER_PEN); 165062306a36Sopenharmony_ci at91_adc_writel(st, IER, AT91_SAMA5D2_IER_NOPEN | 165162306a36Sopenharmony_ci AT91_SAMA5D2_IER_XRDY | AT91_SAMA5D2_IER_YRDY | 165262306a36Sopenharmony_ci AT91_SAMA5D2_IER_PRDY); 165362306a36Sopenharmony_ci at91_adc_writel(st, TRGR, AT91_SAMA5D2_TRGR_TRGMOD_PERIODIC | 165462306a36Sopenharmony_ci AT91_SAMA5D2_TRGR_TRGPER(st->touch_st.sample_period_val)); 165562306a36Sopenharmony_ci st->touch_st.touching = true; 165662306a36Sopenharmony_ci} 165762306a36Sopenharmony_ci 165862306a36Sopenharmony_cistatic void at91_adc_no_pen_detect_interrupt(struct iio_dev *indio_dev) 165962306a36Sopenharmony_ci{ 166062306a36Sopenharmony_ci struct at91_adc_state *st = iio_priv(indio_dev); 166162306a36Sopenharmony_ci 166262306a36Sopenharmony_ci at91_adc_writel(st, TRGR, AT91_SAMA5D2_TRGR_TRGMOD_NO_TRIGGER); 166362306a36Sopenharmony_ci at91_adc_writel(st, IDR, AT91_SAMA5D2_IER_NOPEN | 166462306a36Sopenharmony_ci AT91_SAMA5D2_IER_XRDY | AT91_SAMA5D2_IER_YRDY | 166562306a36Sopenharmony_ci AT91_SAMA5D2_IER_PRDY); 166662306a36Sopenharmony_ci st->touch_st.touching = false; 166762306a36Sopenharmony_ci 166862306a36Sopenharmony_ci at91_adc_touch_data_handler(indio_dev); 166962306a36Sopenharmony_ci 167062306a36Sopenharmony_ci at91_adc_writel(st, IER, AT91_SAMA5D2_IER_PEN); 167162306a36Sopenharmony_ci} 167262306a36Sopenharmony_ci 167362306a36Sopenharmony_cistatic void at91_adc_workq_handler(struct work_struct *workq) 167462306a36Sopenharmony_ci{ 167562306a36Sopenharmony_ci struct at91_adc_touch *touch_st = container_of(workq, 167662306a36Sopenharmony_ci struct at91_adc_touch, workq); 167762306a36Sopenharmony_ci struct at91_adc_state *st = container_of(touch_st, 167862306a36Sopenharmony_ci struct at91_adc_state, touch_st); 167962306a36Sopenharmony_ci struct iio_dev *indio_dev = st->indio_dev; 168062306a36Sopenharmony_ci 168162306a36Sopenharmony_ci iio_push_to_buffers(indio_dev, st->buffer); 168262306a36Sopenharmony_ci} 168362306a36Sopenharmony_ci 168462306a36Sopenharmony_cistatic irqreturn_t at91_adc_interrupt(int irq, void *private) 168562306a36Sopenharmony_ci{ 168662306a36Sopenharmony_ci struct iio_dev *indio = private; 168762306a36Sopenharmony_ci struct at91_adc_state *st = iio_priv(indio); 168862306a36Sopenharmony_ci u32 status, eoc, imr, eoc_imr; 168962306a36Sopenharmony_ci u32 rdy_mask = AT91_SAMA5D2_IER_XRDY | AT91_SAMA5D2_IER_YRDY | 169062306a36Sopenharmony_ci AT91_SAMA5D2_IER_PRDY; 169162306a36Sopenharmony_ci 169262306a36Sopenharmony_ci at91_adc_irq_status(st, &status, &eoc); 169362306a36Sopenharmony_ci at91_adc_irq_mask(st, &imr, &eoc_imr); 169462306a36Sopenharmony_ci 169562306a36Sopenharmony_ci if (!(status & imr) && !(eoc & eoc_imr)) 169662306a36Sopenharmony_ci return IRQ_NONE; 169762306a36Sopenharmony_ci if (status & AT91_SAMA5D2_IER_PEN) { 169862306a36Sopenharmony_ci /* pen detected IRQ */ 169962306a36Sopenharmony_ci at91_adc_pen_detect_interrupt(st); 170062306a36Sopenharmony_ci } else if ((status & AT91_SAMA5D2_IER_NOPEN)) { 170162306a36Sopenharmony_ci /* nopen detected IRQ */ 170262306a36Sopenharmony_ci at91_adc_no_pen_detect_interrupt(indio); 170362306a36Sopenharmony_ci } else if ((status & AT91_SAMA5D2_ISR_PENS) && 170462306a36Sopenharmony_ci ((status & rdy_mask) == rdy_mask)) { 170562306a36Sopenharmony_ci /* periodic trigger IRQ - during pen sense */ 170662306a36Sopenharmony_ci at91_adc_touch_data_handler(indio); 170762306a36Sopenharmony_ci } else if (status & AT91_SAMA5D2_ISR_PENS) { 170862306a36Sopenharmony_ci /* 170962306a36Sopenharmony_ci * touching, but the measurements are not ready yet. 171062306a36Sopenharmony_ci * read and ignore. 171162306a36Sopenharmony_ci */ 171262306a36Sopenharmony_ci status = at91_adc_readl(st, XPOSR); 171362306a36Sopenharmony_ci status = at91_adc_readl(st, YPOSR); 171462306a36Sopenharmony_ci status = at91_adc_readl(st, PRESSR); 171562306a36Sopenharmony_ci } else if (iio_buffer_enabled(indio) && 171662306a36Sopenharmony_ci (status & AT91_SAMA5D2_IER_DRDY)) { 171762306a36Sopenharmony_ci /* triggered buffer without DMA */ 171862306a36Sopenharmony_ci disable_irq_nosync(irq); 171962306a36Sopenharmony_ci iio_trigger_poll(indio->trig); 172062306a36Sopenharmony_ci } else if (iio_buffer_enabled(indio) && st->dma_st.dma_chan) { 172162306a36Sopenharmony_ci /* triggered buffer with DMA - should not happen */ 172262306a36Sopenharmony_ci disable_irq_nosync(irq); 172362306a36Sopenharmony_ci WARN(true, "Unexpected irq occurred\n"); 172462306a36Sopenharmony_ci } else if (!iio_buffer_enabled(indio)) { 172562306a36Sopenharmony_ci /* software requested conversion */ 172662306a36Sopenharmony_ci st->conversion_value = at91_adc_read_chan(st, st->chan->address); 172762306a36Sopenharmony_ci st->conversion_done = true; 172862306a36Sopenharmony_ci wake_up_interruptible(&st->wq_data_available); 172962306a36Sopenharmony_ci } 173062306a36Sopenharmony_ci return IRQ_HANDLED; 173162306a36Sopenharmony_ci} 173262306a36Sopenharmony_ci 173362306a36Sopenharmony_ci/* This needs to be called with direct mode claimed and st->lock locked. */ 173462306a36Sopenharmony_cistatic int at91_adc_read_info_raw(struct iio_dev *indio_dev, 173562306a36Sopenharmony_ci struct iio_chan_spec const *chan, int *val) 173662306a36Sopenharmony_ci{ 173762306a36Sopenharmony_ci struct at91_adc_state *st = iio_priv(indio_dev); 173862306a36Sopenharmony_ci u16 tmp_val; 173962306a36Sopenharmony_ci int ret; 174062306a36Sopenharmony_ci 174162306a36Sopenharmony_ci ret = pm_runtime_resume_and_get(st->dev); 174262306a36Sopenharmony_ci if (ret < 0) 174362306a36Sopenharmony_ci return ret; 174462306a36Sopenharmony_ci 174562306a36Sopenharmony_ci /* 174662306a36Sopenharmony_ci * Keep in mind that we cannot use software trigger or touchscreen 174762306a36Sopenharmony_ci * if external trigger is enabled 174862306a36Sopenharmony_ci */ 174962306a36Sopenharmony_ci if (chan->type == IIO_POSITIONRELATIVE) { 175062306a36Sopenharmony_ci ret = at91_adc_read_position(st, chan->channel, 175162306a36Sopenharmony_ci &tmp_val); 175262306a36Sopenharmony_ci *val = tmp_val; 175362306a36Sopenharmony_ci if (ret > 0) 175462306a36Sopenharmony_ci ret = at91_adc_adjust_val_osr(st, val); 175562306a36Sopenharmony_ci 175662306a36Sopenharmony_ci goto pm_runtime_put; 175762306a36Sopenharmony_ci } 175862306a36Sopenharmony_ci if (chan->type == IIO_PRESSURE) { 175962306a36Sopenharmony_ci ret = at91_adc_read_pressure(st, chan->channel, 176062306a36Sopenharmony_ci &tmp_val); 176162306a36Sopenharmony_ci *val = tmp_val; 176262306a36Sopenharmony_ci if (ret > 0) 176362306a36Sopenharmony_ci ret = at91_adc_adjust_val_osr(st, val); 176462306a36Sopenharmony_ci 176562306a36Sopenharmony_ci goto pm_runtime_put; 176662306a36Sopenharmony_ci } 176762306a36Sopenharmony_ci 176862306a36Sopenharmony_ci /* in this case we have a voltage or temperature channel */ 176962306a36Sopenharmony_ci 177062306a36Sopenharmony_ci st->chan = chan; 177162306a36Sopenharmony_ci 177262306a36Sopenharmony_ci at91_adc_cor(st, chan); 177362306a36Sopenharmony_ci at91_adc_writel(st, CHER, BIT(chan->channel)); 177462306a36Sopenharmony_ci /* 177562306a36Sopenharmony_ci * TEMPMR.TEMPON needs to update after CHER otherwise if none 177662306a36Sopenharmony_ci * of the channels are enabled and TEMPMR.TEMPON = 1 will 177762306a36Sopenharmony_ci * trigger DRDY interruption while preparing for temperature read. 177862306a36Sopenharmony_ci */ 177962306a36Sopenharmony_ci if (chan->type == IIO_TEMP) 178062306a36Sopenharmony_ci at91_adc_writel(st, TEMPMR, AT91_SAMA5D2_TEMPMR_TEMPON); 178162306a36Sopenharmony_ci at91_adc_eoc_ena(st, chan->channel); 178262306a36Sopenharmony_ci at91_adc_writel(st, CR, AT91_SAMA5D2_CR_START); 178362306a36Sopenharmony_ci 178462306a36Sopenharmony_ci ret = wait_event_interruptible_timeout(st->wq_data_available, 178562306a36Sopenharmony_ci st->conversion_done, 178662306a36Sopenharmony_ci msecs_to_jiffies(1000)); 178762306a36Sopenharmony_ci if (ret == 0) 178862306a36Sopenharmony_ci ret = -ETIMEDOUT; 178962306a36Sopenharmony_ci 179062306a36Sopenharmony_ci if (ret > 0) { 179162306a36Sopenharmony_ci *val = st->conversion_value; 179262306a36Sopenharmony_ci ret = at91_adc_adjust_val_osr(st, val); 179362306a36Sopenharmony_ci if (chan->scan_type.sign == 's') 179462306a36Sopenharmony_ci *val = sign_extend32(*val, 179562306a36Sopenharmony_ci chan->scan_type.realbits - 1); 179662306a36Sopenharmony_ci st->conversion_done = false; 179762306a36Sopenharmony_ci } 179862306a36Sopenharmony_ci 179962306a36Sopenharmony_ci at91_adc_eoc_dis(st, st->chan->channel); 180062306a36Sopenharmony_ci if (chan->type == IIO_TEMP) 180162306a36Sopenharmony_ci at91_adc_writel(st, TEMPMR, 0U); 180262306a36Sopenharmony_ci at91_adc_writel(st, CHDR, BIT(chan->channel)); 180362306a36Sopenharmony_ci 180462306a36Sopenharmony_ci /* Needed to ACK the DRDY interruption */ 180562306a36Sopenharmony_ci at91_adc_readl(st, LCDR); 180662306a36Sopenharmony_ci 180762306a36Sopenharmony_cipm_runtime_put: 180862306a36Sopenharmony_ci pm_runtime_mark_last_busy(st->dev); 180962306a36Sopenharmony_ci pm_runtime_put_autosuspend(st->dev); 181062306a36Sopenharmony_ci return ret; 181162306a36Sopenharmony_ci} 181262306a36Sopenharmony_ci 181362306a36Sopenharmony_cistatic int at91_adc_read_info_locked(struct iio_dev *indio_dev, 181462306a36Sopenharmony_ci struct iio_chan_spec const *chan, int *val) 181562306a36Sopenharmony_ci{ 181662306a36Sopenharmony_ci struct at91_adc_state *st = iio_priv(indio_dev); 181762306a36Sopenharmony_ci int ret; 181862306a36Sopenharmony_ci 181962306a36Sopenharmony_ci ret = iio_device_claim_direct_mode(indio_dev); 182062306a36Sopenharmony_ci if (ret) 182162306a36Sopenharmony_ci return ret; 182262306a36Sopenharmony_ci 182362306a36Sopenharmony_ci mutex_lock(&st->lock); 182462306a36Sopenharmony_ci ret = at91_adc_read_info_raw(indio_dev, chan, val); 182562306a36Sopenharmony_ci mutex_unlock(&st->lock); 182662306a36Sopenharmony_ci 182762306a36Sopenharmony_ci iio_device_release_direct_mode(indio_dev); 182862306a36Sopenharmony_ci 182962306a36Sopenharmony_ci return ret; 183062306a36Sopenharmony_ci} 183162306a36Sopenharmony_ci 183262306a36Sopenharmony_cistatic void at91_adc_temp_sensor_configure(struct at91_adc_state *st, 183362306a36Sopenharmony_ci bool start) 183462306a36Sopenharmony_ci{ 183562306a36Sopenharmony_ci u32 sample_rate, oversampling_ratio; 183662306a36Sopenharmony_ci u32 startup_time, tracktim, trackx; 183762306a36Sopenharmony_ci 183862306a36Sopenharmony_ci if (start) { 183962306a36Sopenharmony_ci /* 184062306a36Sopenharmony_ci * Configure the sensor for best accuracy: 10MHz frequency, 184162306a36Sopenharmony_ci * oversampling rate of 256, tracktim=0xf and trackx=1. 184262306a36Sopenharmony_ci */ 184362306a36Sopenharmony_ci sample_rate = 10 * MEGA; 184462306a36Sopenharmony_ci oversampling_ratio = 256; 184562306a36Sopenharmony_ci startup_time = AT91_SAMA5D2_MR_STARTUP_TS_MIN; 184662306a36Sopenharmony_ci tracktim = AT91_SAMA5D2_MR_TRACKTIM_TS; 184762306a36Sopenharmony_ci trackx = AT91_SAMA5D2_TRACKX_TS; 184862306a36Sopenharmony_ci 184962306a36Sopenharmony_ci st->temp_st.saved_sample_rate = st->current_sample_rate; 185062306a36Sopenharmony_ci st->temp_st.saved_oversampling = st->oversampling_ratio; 185162306a36Sopenharmony_ci } else { 185262306a36Sopenharmony_ci /* Go back to previous settings. */ 185362306a36Sopenharmony_ci sample_rate = st->temp_st.saved_sample_rate; 185462306a36Sopenharmony_ci oversampling_ratio = st->temp_st.saved_oversampling; 185562306a36Sopenharmony_ci startup_time = st->soc_info.startup_time; 185662306a36Sopenharmony_ci tracktim = 0; 185762306a36Sopenharmony_ci trackx = 0; 185862306a36Sopenharmony_ci } 185962306a36Sopenharmony_ci 186062306a36Sopenharmony_ci at91_adc_setup_samp_freq(st->indio_dev, sample_rate, startup_time, 186162306a36Sopenharmony_ci tracktim); 186262306a36Sopenharmony_ci at91_adc_config_emr(st, oversampling_ratio, trackx); 186362306a36Sopenharmony_ci} 186462306a36Sopenharmony_ci 186562306a36Sopenharmony_cistatic int at91_adc_read_temp(struct iio_dev *indio_dev, 186662306a36Sopenharmony_ci struct iio_chan_spec const *chan, int *val) 186762306a36Sopenharmony_ci{ 186862306a36Sopenharmony_ci struct at91_adc_state *st = iio_priv(indio_dev); 186962306a36Sopenharmony_ci struct at91_adc_temp_sensor_clb *clb = &st->soc_info.temp_sensor_clb; 187062306a36Sopenharmony_ci u64 div1, div2; 187162306a36Sopenharmony_ci u32 tmp; 187262306a36Sopenharmony_ci int ret, vbg, vtemp; 187362306a36Sopenharmony_ci 187462306a36Sopenharmony_ci ret = iio_device_claim_direct_mode(indio_dev); 187562306a36Sopenharmony_ci if (ret) 187662306a36Sopenharmony_ci return ret; 187762306a36Sopenharmony_ci mutex_lock(&st->lock); 187862306a36Sopenharmony_ci 187962306a36Sopenharmony_ci ret = pm_runtime_resume_and_get(st->dev); 188062306a36Sopenharmony_ci if (ret < 0) 188162306a36Sopenharmony_ci goto unlock; 188262306a36Sopenharmony_ci 188362306a36Sopenharmony_ci at91_adc_temp_sensor_configure(st, true); 188462306a36Sopenharmony_ci 188562306a36Sopenharmony_ci /* Read VBG. */ 188662306a36Sopenharmony_ci tmp = at91_adc_readl(st, ACR); 188762306a36Sopenharmony_ci tmp |= AT91_SAMA5D2_ACR_SRCLCH; 188862306a36Sopenharmony_ci at91_adc_writel(st, ACR, tmp); 188962306a36Sopenharmony_ci ret = at91_adc_read_info_raw(indio_dev, chan, &vbg); 189062306a36Sopenharmony_ci if (ret < 0) 189162306a36Sopenharmony_ci goto restore_config; 189262306a36Sopenharmony_ci 189362306a36Sopenharmony_ci /* Read VTEMP. */ 189462306a36Sopenharmony_ci tmp &= ~AT91_SAMA5D2_ACR_SRCLCH; 189562306a36Sopenharmony_ci at91_adc_writel(st, ACR, tmp); 189662306a36Sopenharmony_ci ret = at91_adc_read_info_raw(indio_dev, chan, &vtemp); 189762306a36Sopenharmony_ci 189862306a36Sopenharmony_cirestore_config: 189962306a36Sopenharmony_ci /* Revert previous settings. */ 190062306a36Sopenharmony_ci at91_adc_temp_sensor_configure(st, false); 190162306a36Sopenharmony_ci pm_runtime_mark_last_busy(st->dev); 190262306a36Sopenharmony_ci pm_runtime_put_autosuspend(st->dev); 190362306a36Sopenharmony_ciunlock: 190462306a36Sopenharmony_ci mutex_unlock(&st->lock); 190562306a36Sopenharmony_ci iio_device_release_direct_mode(indio_dev); 190662306a36Sopenharmony_ci if (ret < 0) 190762306a36Sopenharmony_ci return ret; 190862306a36Sopenharmony_ci 190962306a36Sopenharmony_ci /* 191062306a36Sopenharmony_ci * Temp[milli] = p1[milli] + (vtemp * clb->p6 - clb->p4 * vbg)/ 191162306a36Sopenharmony_ci * (vbg * AT91_ADC_TS_VTEMP_DT) 191262306a36Sopenharmony_ci */ 191362306a36Sopenharmony_ci div1 = DIV_ROUND_CLOSEST_ULL(((u64)vtemp * clb->p6), vbg); 191462306a36Sopenharmony_ci div1 = DIV_ROUND_CLOSEST_ULL((div1 * 1000), AT91_ADC_TS_VTEMP_DT); 191562306a36Sopenharmony_ci div2 = DIV_ROUND_CLOSEST_ULL((u64)clb->p4, AT91_ADC_TS_VTEMP_DT); 191662306a36Sopenharmony_ci div2 *= 1000; 191762306a36Sopenharmony_ci *val = clb->p1 + (int)div1 - (int)div2; 191862306a36Sopenharmony_ci 191962306a36Sopenharmony_ci return ret; 192062306a36Sopenharmony_ci} 192162306a36Sopenharmony_ci 192262306a36Sopenharmony_cistatic int at91_adc_read_raw(struct iio_dev *indio_dev, 192362306a36Sopenharmony_ci struct iio_chan_spec const *chan, 192462306a36Sopenharmony_ci int *val, int *val2, long mask) 192562306a36Sopenharmony_ci{ 192662306a36Sopenharmony_ci struct at91_adc_state *st = iio_priv(indio_dev); 192762306a36Sopenharmony_ci 192862306a36Sopenharmony_ci switch (mask) { 192962306a36Sopenharmony_ci case IIO_CHAN_INFO_RAW: 193062306a36Sopenharmony_ci return at91_adc_read_info_locked(indio_dev, chan, val); 193162306a36Sopenharmony_ci 193262306a36Sopenharmony_ci case IIO_CHAN_INFO_SCALE: 193362306a36Sopenharmony_ci *val = st->vref_uv / 1000; 193462306a36Sopenharmony_ci if (chan->differential) 193562306a36Sopenharmony_ci *val *= 2; 193662306a36Sopenharmony_ci *val2 = chan->scan_type.realbits; 193762306a36Sopenharmony_ci return IIO_VAL_FRACTIONAL_LOG2; 193862306a36Sopenharmony_ci 193962306a36Sopenharmony_ci case IIO_CHAN_INFO_PROCESSED: 194062306a36Sopenharmony_ci if (chan->type != IIO_TEMP) 194162306a36Sopenharmony_ci return -EINVAL; 194262306a36Sopenharmony_ci return at91_adc_read_temp(indio_dev, chan, val); 194362306a36Sopenharmony_ci 194462306a36Sopenharmony_ci case IIO_CHAN_INFO_SAMP_FREQ: 194562306a36Sopenharmony_ci *val = at91_adc_get_sample_freq(st); 194662306a36Sopenharmony_ci return IIO_VAL_INT; 194762306a36Sopenharmony_ci 194862306a36Sopenharmony_ci case IIO_CHAN_INFO_OVERSAMPLING_RATIO: 194962306a36Sopenharmony_ci *val = st->oversampling_ratio; 195062306a36Sopenharmony_ci return IIO_VAL_INT; 195162306a36Sopenharmony_ci 195262306a36Sopenharmony_ci default: 195362306a36Sopenharmony_ci return -EINVAL; 195462306a36Sopenharmony_ci } 195562306a36Sopenharmony_ci} 195662306a36Sopenharmony_ci 195762306a36Sopenharmony_cistatic int at91_adc_write_raw(struct iio_dev *indio_dev, 195862306a36Sopenharmony_ci struct iio_chan_spec const *chan, 195962306a36Sopenharmony_ci int val, int val2, long mask) 196062306a36Sopenharmony_ci{ 196162306a36Sopenharmony_ci struct at91_adc_state *st = iio_priv(indio_dev); 196262306a36Sopenharmony_ci int ret; 196362306a36Sopenharmony_ci 196462306a36Sopenharmony_ci switch (mask) { 196562306a36Sopenharmony_ci case IIO_CHAN_INFO_OVERSAMPLING_RATIO: 196662306a36Sopenharmony_ci /* if no change, optimize out */ 196762306a36Sopenharmony_ci if (val == st->oversampling_ratio) 196862306a36Sopenharmony_ci return 0; 196962306a36Sopenharmony_ci 197062306a36Sopenharmony_ci ret = iio_device_claim_direct_mode(indio_dev); 197162306a36Sopenharmony_ci if (ret) 197262306a36Sopenharmony_ci return ret; 197362306a36Sopenharmony_ci mutex_lock(&st->lock); 197462306a36Sopenharmony_ci /* update ratio */ 197562306a36Sopenharmony_ci ret = at91_adc_config_emr(st, val, 0); 197662306a36Sopenharmony_ci mutex_unlock(&st->lock); 197762306a36Sopenharmony_ci iio_device_release_direct_mode(indio_dev); 197862306a36Sopenharmony_ci return ret; 197962306a36Sopenharmony_ci case IIO_CHAN_INFO_SAMP_FREQ: 198062306a36Sopenharmony_ci if (val < st->soc_info.min_sample_rate || 198162306a36Sopenharmony_ci val > st->soc_info.max_sample_rate) 198262306a36Sopenharmony_ci return -EINVAL; 198362306a36Sopenharmony_ci 198462306a36Sopenharmony_ci ret = iio_device_claim_direct_mode(indio_dev); 198562306a36Sopenharmony_ci if (ret) 198662306a36Sopenharmony_ci return ret; 198762306a36Sopenharmony_ci mutex_lock(&st->lock); 198862306a36Sopenharmony_ci at91_adc_setup_samp_freq(indio_dev, val, 198962306a36Sopenharmony_ci st->soc_info.startup_time, 0); 199062306a36Sopenharmony_ci mutex_unlock(&st->lock); 199162306a36Sopenharmony_ci iio_device_release_direct_mode(indio_dev); 199262306a36Sopenharmony_ci return 0; 199362306a36Sopenharmony_ci default: 199462306a36Sopenharmony_ci return -EINVAL; 199562306a36Sopenharmony_ci } 199662306a36Sopenharmony_ci} 199762306a36Sopenharmony_ci 199862306a36Sopenharmony_cistatic int at91_adc_read_avail(struct iio_dev *indio_dev, 199962306a36Sopenharmony_ci struct iio_chan_spec const *chan, 200062306a36Sopenharmony_ci const int **vals, int *type, int *length, 200162306a36Sopenharmony_ci long mask) 200262306a36Sopenharmony_ci{ 200362306a36Sopenharmony_ci struct at91_adc_state *st = iio_priv(indio_dev); 200462306a36Sopenharmony_ci 200562306a36Sopenharmony_ci switch (mask) { 200662306a36Sopenharmony_ci case IIO_CHAN_INFO_OVERSAMPLING_RATIO: 200762306a36Sopenharmony_ci *vals = (int *)st->soc_info.platform->oversampling_avail; 200862306a36Sopenharmony_ci *type = IIO_VAL_INT; 200962306a36Sopenharmony_ci *length = st->soc_info.platform->oversampling_avail_no; 201062306a36Sopenharmony_ci return IIO_AVAIL_LIST; 201162306a36Sopenharmony_ci default: 201262306a36Sopenharmony_ci return -EINVAL; 201362306a36Sopenharmony_ci } 201462306a36Sopenharmony_ci} 201562306a36Sopenharmony_ci 201662306a36Sopenharmony_cistatic void at91_adc_dma_init(struct at91_adc_state *st) 201762306a36Sopenharmony_ci{ 201862306a36Sopenharmony_ci struct device *dev = &st->indio_dev->dev; 201962306a36Sopenharmony_ci struct dma_slave_config config = {0}; 202062306a36Sopenharmony_ci /* we have 2 bytes for each channel */ 202162306a36Sopenharmony_ci unsigned int sample_size = st->soc_info.platform->nr_channels * 2; 202262306a36Sopenharmony_ci /* 202362306a36Sopenharmony_ci * We make the buffer double the size of the fifo, 202462306a36Sopenharmony_ci * such that DMA uses one half of the buffer (full fifo size) 202562306a36Sopenharmony_ci * and the software uses the other half to read/write. 202662306a36Sopenharmony_ci */ 202762306a36Sopenharmony_ci unsigned int pages = DIV_ROUND_UP(AT91_HWFIFO_MAX_SIZE * 202862306a36Sopenharmony_ci sample_size * 2, PAGE_SIZE); 202962306a36Sopenharmony_ci 203062306a36Sopenharmony_ci if (st->dma_st.dma_chan) 203162306a36Sopenharmony_ci return; 203262306a36Sopenharmony_ci 203362306a36Sopenharmony_ci st->dma_st.dma_chan = dma_request_chan(dev, "rx"); 203462306a36Sopenharmony_ci if (IS_ERR(st->dma_st.dma_chan)) { 203562306a36Sopenharmony_ci dev_info(dev, "can't get DMA channel\n"); 203662306a36Sopenharmony_ci st->dma_st.dma_chan = NULL; 203762306a36Sopenharmony_ci goto dma_exit; 203862306a36Sopenharmony_ci } 203962306a36Sopenharmony_ci 204062306a36Sopenharmony_ci st->dma_st.rx_buf = dma_alloc_coherent(st->dma_st.dma_chan->device->dev, 204162306a36Sopenharmony_ci pages * PAGE_SIZE, 204262306a36Sopenharmony_ci &st->dma_st.rx_dma_buf, 204362306a36Sopenharmony_ci GFP_KERNEL); 204462306a36Sopenharmony_ci if (!st->dma_st.rx_buf) { 204562306a36Sopenharmony_ci dev_info(dev, "can't allocate coherent DMA area\n"); 204662306a36Sopenharmony_ci goto dma_chan_disable; 204762306a36Sopenharmony_ci } 204862306a36Sopenharmony_ci 204962306a36Sopenharmony_ci /* Configure DMA channel to read data register */ 205062306a36Sopenharmony_ci config.direction = DMA_DEV_TO_MEM; 205162306a36Sopenharmony_ci config.src_addr = (phys_addr_t)(st->dma_st.phys_addr 205262306a36Sopenharmony_ci + st->soc_info.platform->layout->LCDR); 205362306a36Sopenharmony_ci config.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; 205462306a36Sopenharmony_ci config.src_maxburst = 1; 205562306a36Sopenharmony_ci config.dst_maxburst = 1; 205662306a36Sopenharmony_ci 205762306a36Sopenharmony_ci if (dmaengine_slave_config(st->dma_st.dma_chan, &config)) { 205862306a36Sopenharmony_ci dev_info(dev, "can't configure DMA slave\n"); 205962306a36Sopenharmony_ci goto dma_free_area; 206062306a36Sopenharmony_ci } 206162306a36Sopenharmony_ci 206262306a36Sopenharmony_ci dev_info(dev, "using %s for rx DMA transfers\n", 206362306a36Sopenharmony_ci dma_chan_name(st->dma_st.dma_chan)); 206462306a36Sopenharmony_ci 206562306a36Sopenharmony_ci return; 206662306a36Sopenharmony_ci 206762306a36Sopenharmony_cidma_free_area: 206862306a36Sopenharmony_ci dma_free_coherent(st->dma_st.dma_chan->device->dev, pages * PAGE_SIZE, 206962306a36Sopenharmony_ci st->dma_st.rx_buf, st->dma_st.rx_dma_buf); 207062306a36Sopenharmony_cidma_chan_disable: 207162306a36Sopenharmony_ci dma_release_channel(st->dma_st.dma_chan); 207262306a36Sopenharmony_ci st->dma_st.dma_chan = NULL; 207362306a36Sopenharmony_cidma_exit: 207462306a36Sopenharmony_ci dev_info(dev, "continuing without DMA support\n"); 207562306a36Sopenharmony_ci} 207662306a36Sopenharmony_ci 207762306a36Sopenharmony_cistatic void at91_adc_dma_disable(struct at91_adc_state *st) 207862306a36Sopenharmony_ci{ 207962306a36Sopenharmony_ci struct device *dev = &st->indio_dev->dev; 208062306a36Sopenharmony_ci /* we have 2 bytes for each channel */ 208162306a36Sopenharmony_ci unsigned int sample_size = st->soc_info.platform->nr_channels * 2; 208262306a36Sopenharmony_ci unsigned int pages = DIV_ROUND_UP(AT91_HWFIFO_MAX_SIZE * 208362306a36Sopenharmony_ci sample_size * 2, PAGE_SIZE); 208462306a36Sopenharmony_ci 208562306a36Sopenharmony_ci /* if we are not using DMA, just return */ 208662306a36Sopenharmony_ci if (!st->dma_st.dma_chan) 208762306a36Sopenharmony_ci return; 208862306a36Sopenharmony_ci 208962306a36Sopenharmony_ci /* wait for all transactions to be terminated first*/ 209062306a36Sopenharmony_ci dmaengine_terminate_sync(st->dma_st.dma_chan); 209162306a36Sopenharmony_ci 209262306a36Sopenharmony_ci dma_free_coherent(st->dma_st.dma_chan->device->dev, pages * PAGE_SIZE, 209362306a36Sopenharmony_ci st->dma_st.rx_buf, st->dma_st.rx_dma_buf); 209462306a36Sopenharmony_ci dma_release_channel(st->dma_st.dma_chan); 209562306a36Sopenharmony_ci st->dma_st.dma_chan = NULL; 209662306a36Sopenharmony_ci 209762306a36Sopenharmony_ci dev_info(dev, "continuing without DMA support\n"); 209862306a36Sopenharmony_ci} 209962306a36Sopenharmony_ci 210062306a36Sopenharmony_cistatic int at91_adc_set_watermark(struct iio_dev *indio_dev, unsigned int val) 210162306a36Sopenharmony_ci{ 210262306a36Sopenharmony_ci struct at91_adc_state *st = iio_priv(indio_dev); 210362306a36Sopenharmony_ci int ret; 210462306a36Sopenharmony_ci 210562306a36Sopenharmony_ci if (val > AT91_HWFIFO_MAX_SIZE) 210662306a36Sopenharmony_ci val = AT91_HWFIFO_MAX_SIZE; 210762306a36Sopenharmony_ci 210862306a36Sopenharmony_ci if (!st->selected_trig->hw_trig) { 210962306a36Sopenharmony_ci dev_dbg(&indio_dev->dev, "we need hw trigger for DMA\n"); 211062306a36Sopenharmony_ci return 0; 211162306a36Sopenharmony_ci } 211262306a36Sopenharmony_ci 211362306a36Sopenharmony_ci dev_dbg(&indio_dev->dev, "new watermark is %u\n", val); 211462306a36Sopenharmony_ci st->dma_st.watermark = val; 211562306a36Sopenharmony_ci 211662306a36Sopenharmony_ci /* 211762306a36Sopenharmony_ci * The logic here is: if we have watermark 1, it means we do 211862306a36Sopenharmony_ci * each conversion with it's own IRQ, thus we don't need DMA. 211962306a36Sopenharmony_ci * If the watermark is higher, we do DMA to do all the transfers in bulk 212062306a36Sopenharmony_ci */ 212162306a36Sopenharmony_ci 212262306a36Sopenharmony_ci if (val == 1) 212362306a36Sopenharmony_ci at91_adc_dma_disable(st); 212462306a36Sopenharmony_ci else if (val > 1) 212562306a36Sopenharmony_ci at91_adc_dma_init(st); 212662306a36Sopenharmony_ci 212762306a36Sopenharmony_ci /* 212862306a36Sopenharmony_ci * We can start the DMA only after setting the watermark and 212962306a36Sopenharmony_ci * having the DMA initialization completed 213062306a36Sopenharmony_ci */ 213162306a36Sopenharmony_ci ret = at91_adc_buffer_prepare(indio_dev); 213262306a36Sopenharmony_ci if (ret) 213362306a36Sopenharmony_ci at91_adc_dma_disable(st); 213462306a36Sopenharmony_ci 213562306a36Sopenharmony_ci return ret; 213662306a36Sopenharmony_ci} 213762306a36Sopenharmony_ci 213862306a36Sopenharmony_cistatic int at91_adc_update_scan_mode(struct iio_dev *indio_dev, 213962306a36Sopenharmony_ci const unsigned long *scan_mask) 214062306a36Sopenharmony_ci{ 214162306a36Sopenharmony_ci struct at91_adc_state *st = iio_priv(indio_dev); 214262306a36Sopenharmony_ci 214362306a36Sopenharmony_ci if (bitmap_subset(scan_mask, &st->touch_st.channels_bitmask, 214462306a36Sopenharmony_ci st->soc_info.platform->max_index + 1)) 214562306a36Sopenharmony_ci return 0; 214662306a36Sopenharmony_ci /* 214762306a36Sopenharmony_ci * if the new bitmap is a combination of touchscreen and regular 214862306a36Sopenharmony_ci * channels, then we are not fine 214962306a36Sopenharmony_ci */ 215062306a36Sopenharmony_ci if (bitmap_intersects(&st->touch_st.channels_bitmask, scan_mask, 215162306a36Sopenharmony_ci st->soc_info.platform->max_index + 1)) 215262306a36Sopenharmony_ci return -EINVAL; 215362306a36Sopenharmony_ci return 0; 215462306a36Sopenharmony_ci} 215562306a36Sopenharmony_ci 215662306a36Sopenharmony_cistatic void at91_adc_hw_init(struct iio_dev *indio_dev) 215762306a36Sopenharmony_ci{ 215862306a36Sopenharmony_ci struct at91_adc_state *st = iio_priv(indio_dev); 215962306a36Sopenharmony_ci 216062306a36Sopenharmony_ci at91_adc_writel(st, CR, AT91_SAMA5D2_CR_SWRST); 216162306a36Sopenharmony_ci if (st->soc_info.platform->layout->EOC_IDR) 216262306a36Sopenharmony_ci at91_adc_writel(st, EOC_IDR, 0xffffffff); 216362306a36Sopenharmony_ci at91_adc_writel(st, IDR, 0xffffffff); 216462306a36Sopenharmony_ci /* 216562306a36Sopenharmony_ci * Transfer field must be set to 2 according to the datasheet and 216662306a36Sopenharmony_ci * allows different analog settings for each channel. 216762306a36Sopenharmony_ci */ 216862306a36Sopenharmony_ci at91_adc_writel(st, MR, 216962306a36Sopenharmony_ci AT91_SAMA5D2_MR_TRANSFER(2) | AT91_SAMA5D2_MR_ANACH); 217062306a36Sopenharmony_ci 217162306a36Sopenharmony_ci at91_adc_setup_samp_freq(indio_dev, st->soc_info.min_sample_rate, 217262306a36Sopenharmony_ci st->soc_info.startup_time, 0); 217362306a36Sopenharmony_ci 217462306a36Sopenharmony_ci /* configure extended mode register */ 217562306a36Sopenharmony_ci at91_adc_config_emr(st, st->oversampling_ratio, 0); 217662306a36Sopenharmony_ci} 217762306a36Sopenharmony_ci 217862306a36Sopenharmony_cistatic ssize_t at91_adc_get_fifo_state(struct device *dev, 217962306a36Sopenharmony_ci struct device_attribute *attr, char *buf) 218062306a36Sopenharmony_ci{ 218162306a36Sopenharmony_ci struct iio_dev *indio_dev = dev_to_iio_dev(dev); 218262306a36Sopenharmony_ci struct at91_adc_state *st = iio_priv(indio_dev); 218362306a36Sopenharmony_ci 218462306a36Sopenharmony_ci return sysfs_emit(buf, "%d\n", !!st->dma_st.dma_chan); 218562306a36Sopenharmony_ci} 218662306a36Sopenharmony_ci 218762306a36Sopenharmony_cistatic ssize_t at91_adc_get_watermark(struct device *dev, 218862306a36Sopenharmony_ci struct device_attribute *attr, char *buf) 218962306a36Sopenharmony_ci{ 219062306a36Sopenharmony_ci struct iio_dev *indio_dev = dev_to_iio_dev(dev); 219162306a36Sopenharmony_ci struct at91_adc_state *st = iio_priv(indio_dev); 219262306a36Sopenharmony_ci 219362306a36Sopenharmony_ci return sysfs_emit(buf, "%d\n", st->dma_st.watermark); 219462306a36Sopenharmony_ci} 219562306a36Sopenharmony_ci 219662306a36Sopenharmony_cistatic IIO_DEVICE_ATTR(hwfifo_enabled, 0444, 219762306a36Sopenharmony_ci at91_adc_get_fifo_state, NULL, 0); 219862306a36Sopenharmony_cistatic IIO_DEVICE_ATTR(hwfifo_watermark, 0444, 219962306a36Sopenharmony_ci at91_adc_get_watermark, NULL, 0); 220062306a36Sopenharmony_ci 220162306a36Sopenharmony_ciIIO_STATIC_CONST_DEVICE_ATTR(hwfifo_watermark_min, "2"); 220262306a36Sopenharmony_ciIIO_STATIC_CONST_DEVICE_ATTR(hwfifo_watermark_max, AT91_HWFIFO_MAX_SIZE_STR); 220362306a36Sopenharmony_ci 220462306a36Sopenharmony_cistatic const struct iio_dev_attr *at91_adc_fifo_attributes[] = { 220562306a36Sopenharmony_ci &iio_dev_attr_hwfifo_watermark_min, 220662306a36Sopenharmony_ci &iio_dev_attr_hwfifo_watermark_max, 220762306a36Sopenharmony_ci &iio_dev_attr_hwfifo_watermark, 220862306a36Sopenharmony_ci &iio_dev_attr_hwfifo_enabled, 220962306a36Sopenharmony_ci NULL, 221062306a36Sopenharmony_ci}; 221162306a36Sopenharmony_ci 221262306a36Sopenharmony_cistatic const struct iio_info at91_adc_info = { 221362306a36Sopenharmony_ci .read_avail = &at91_adc_read_avail, 221462306a36Sopenharmony_ci .read_raw = &at91_adc_read_raw, 221562306a36Sopenharmony_ci .write_raw = &at91_adc_write_raw, 221662306a36Sopenharmony_ci .update_scan_mode = &at91_adc_update_scan_mode, 221762306a36Sopenharmony_ci .fwnode_xlate = &at91_adc_fwnode_xlate, 221862306a36Sopenharmony_ci .hwfifo_set_watermark = &at91_adc_set_watermark, 221962306a36Sopenharmony_ci}; 222062306a36Sopenharmony_ci 222162306a36Sopenharmony_cistatic int at91_adc_buffer_and_trigger_init(struct device *dev, 222262306a36Sopenharmony_ci struct iio_dev *indio) 222362306a36Sopenharmony_ci{ 222462306a36Sopenharmony_ci struct at91_adc_state *st = iio_priv(indio); 222562306a36Sopenharmony_ci const struct iio_dev_attr **fifo_attrs; 222662306a36Sopenharmony_ci int ret; 222762306a36Sopenharmony_ci 222862306a36Sopenharmony_ci if (st->selected_trig->hw_trig) 222962306a36Sopenharmony_ci fifo_attrs = at91_adc_fifo_attributes; 223062306a36Sopenharmony_ci else 223162306a36Sopenharmony_ci fifo_attrs = NULL; 223262306a36Sopenharmony_ci 223362306a36Sopenharmony_ci ret = devm_iio_triggered_buffer_setup_ext(&indio->dev, indio, 223462306a36Sopenharmony_ci &iio_pollfunc_store_time, &at91_adc_trigger_handler, 223562306a36Sopenharmony_ci IIO_BUFFER_DIRECTION_IN, &at91_buffer_setup_ops, fifo_attrs); 223662306a36Sopenharmony_ci if (ret < 0) { 223762306a36Sopenharmony_ci dev_err(dev, "couldn't initialize the buffer.\n"); 223862306a36Sopenharmony_ci return ret; 223962306a36Sopenharmony_ci } 224062306a36Sopenharmony_ci 224162306a36Sopenharmony_ci if (!st->selected_trig->hw_trig) 224262306a36Sopenharmony_ci return 0; 224362306a36Sopenharmony_ci 224462306a36Sopenharmony_ci st->trig = at91_adc_allocate_trigger(indio, st->selected_trig->name); 224562306a36Sopenharmony_ci if (IS_ERR(st->trig)) { 224662306a36Sopenharmony_ci dev_err(dev, "could not allocate trigger\n"); 224762306a36Sopenharmony_ci return PTR_ERR(st->trig); 224862306a36Sopenharmony_ci } 224962306a36Sopenharmony_ci 225062306a36Sopenharmony_ci /* 225162306a36Sopenharmony_ci * Initially the iio buffer has a length of 2 and 225262306a36Sopenharmony_ci * a watermark of 1 225362306a36Sopenharmony_ci */ 225462306a36Sopenharmony_ci st->dma_st.watermark = 1; 225562306a36Sopenharmony_ci 225662306a36Sopenharmony_ci return 0; 225762306a36Sopenharmony_ci} 225862306a36Sopenharmony_ci 225962306a36Sopenharmony_cistatic int at91_adc_temp_sensor_init(struct at91_adc_state *st, 226062306a36Sopenharmony_ci struct device *dev) 226162306a36Sopenharmony_ci{ 226262306a36Sopenharmony_ci struct at91_adc_temp_sensor_clb *clb = &st->soc_info.temp_sensor_clb; 226362306a36Sopenharmony_ci struct nvmem_cell *temp_calib; 226462306a36Sopenharmony_ci u32 *buf; 226562306a36Sopenharmony_ci size_t len; 226662306a36Sopenharmony_ci int ret = 0; 226762306a36Sopenharmony_ci 226862306a36Sopenharmony_ci if (!st->soc_info.platform->temp_sensor) 226962306a36Sopenharmony_ci return 0; 227062306a36Sopenharmony_ci 227162306a36Sopenharmony_ci /* Get the calibration data from NVMEM. */ 227262306a36Sopenharmony_ci temp_calib = devm_nvmem_cell_get(dev, "temperature_calib"); 227362306a36Sopenharmony_ci if (IS_ERR(temp_calib)) { 227462306a36Sopenharmony_ci ret = PTR_ERR(temp_calib); 227562306a36Sopenharmony_ci if (ret != -ENOENT) 227662306a36Sopenharmony_ci dev_err(dev, "Failed to get temperature_calib cell!\n"); 227762306a36Sopenharmony_ci return ret; 227862306a36Sopenharmony_ci } 227962306a36Sopenharmony_ci 228062306a36Sopenharmony_ci buf = nvmem_cell_read(temp_calib, &len); 228162306a36Sopenharmony_ci if (IS_ERR(buf)) { 228262306a36Sopenharmony_ci dev_err(dev, "Failed to read calibration data!\n"); 228362306a36Sopenharmony_ci return PTR_ERR(buf); 228462306a36Sopenharmony_ci } 228562306a36Sopenharmony_ci if (len < AT91_ADC_TS_CLB_IDX_MAX * 4) { 228662306a36Sopenharmony_ci dev_err(dev, "Invalid calibration data!\n"); 228762306a36Sopenharmony_ci ret = -EINVAL; 228862306a36Sopenharmony_ci goto free_buf; 228962306a36Sopenharmony_ci } 229062306a36Sopenharmony_ci 229162306a36Sopenharmony_ci /* Store calibration data for later use. */ 229262306a36Sopenharmony_ci clb->p1 = buf[AT91_ADC_TS_CLB_IDX_P1]; 229362306a36Sopenharmony_ci clb->p4 = buf[AT91_ADC_TS_CLB_IDX_P4]; 229462306a36Sopenharmony_ci clb->p6 = buf[AT91_ADC_TS_CLB_IDX_P6]; 229562306a36Sopenharmony_ci 229662306a36Sopenharmony_ci /* 229762306a36Sopenharmony_ci * We prepare here the conversion to milli to avoid doing it on hotpath. 229862306a36Sopenharmony_ci */ 229962306a36Sopenharmony_ci clb->p1 = clb->p1 * 1000; 230062306a36Sopenharmony_ci 230162306a36Sopenharmony_cifree_buf: 230262306a36Sopenharmony_ci kfree(buf); 230362306a36Sopenharmony_ci return ret; 230462306a36Sopenharmony_ci} 230562306a36Sopenharmony_ci 230662306a36Sopenharmony_cistatic int at91_adc_probe(struct platform_device *pdev) 230762306a36Sopenharmony_ci{ 230862306a36Sopenharmony_ci struct device *dev = &pdev->dev; 230962306a36Sopenharmony_ci struct iio_dev *indio_dev; 231062306a36Sopenharmony_ci struct at91_adc_state *st; 231162306a36Sopenharmony_ci struct resource *res; 231262306a36Sopenharmony_ci int ret, i, num_channels; 231362306a36Sopenharmony_ci u32 edge_type = IRQ_TYPE_NONE; 231462306a36Sopenharmony_ci 231562306a36Sopenharmony_ci indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*st)); 231662306a36Sopenharmony_ci if (!indio_dev) 231762306a36Sopenharmony_ci return -ENOMEM; 231862306a36Sopenharmony_ci 231962306a36Sopenharmony_ci st = iio_priv(indio_dev); 232062306a36Sopenharmony_ci st->indio_dev = indio_dev; 232162306a36Sopenharmony_ci 232262306a36Sopenharmony_ci st->soc_info.platform = device_get_match_data(dev); 232362306a36Sopenharmony_ci 232462306a36Sopenharmony_ci ret = at91_adc_temp_sensor_init(st, &pdev->dev); 232562306a36Sopenharmony_ci /* Don't register temperature channel if initialization failed. */ 232662306a36Sopenharmony_ci if (ret) 232762306a36Sopenharmony_ci num_channels = st->soc_info.platform->max_channels - 1; 232862306a36Sopenharmony_ci else 232962306a36Sopenharmony_ci num_channels = st->soc_info.platform->max_channels; 233062306a36Sopenharmony_ci 233162306a36Sopenharmony_ci indio_dev->name = dev_name(&pdev->dev); 233262306a36Sopenharmony_ci indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE; 233362306a36Sopenharmony_ci indio_dev->info = &at91_adc_info; 233462306a36Sopenharmony_ci indio_dev->channels = *st->soc_info.platform->adc_channels; 233562306a36Sopenharmony_ci indio_dev->num_channels = num_channels; 233662306a36Sopenharmony_ci 233762306a36Sopenharmony_ci bitmap_set(&st->touch_st.channels_bitmask, 233862306a36Sopenharmony_ci st->soc_info.platform->touch_chan_x, 1); 233962306a36Sopenharmony_ci bitmap_set(&st->touch_st.channels_bitmask, 234062306a36Sopenharmony_ci st->soc_info.platform->touch_chan_y, 1); 234162306a36Sopenharmony_ci bitmap_set(&st->touch_st.channels_bitmask, 234262306a36Sopenharmony_ci st->soc_info.platform->touch_chan_p, 1); 234362306a36Sopenharmony_ci 234462306a36Sopenharmony_ci st->oversampling_ratio = 1; 234562306a36Sopenharmony_ci 234662306a36Sopenharmony_ci ret = device_property_read_u32(dev, "atmel,min-sample-rate-hz", 234762306a36Sopenharmony_ci &st->soc_info.min_sample_rate); 234862306a36Sopenharmony_ci if (ret) { 234962306a36Sopenharmony_ci dev_err(&pdev->dev, 235062306a36Sopenharmony_ci "invalid or missing value for atmel,min-sample-rate-hz\n"); 235162306a36Sopenharmony_ci return ret; 235262306a36Sopenharmony_ci } 235362306a36Sopenharmony_ci 235462306a36Sopenharmony_ci ret = device_property_read_u32(dev, "atmel,max-sample-rate-hz", 235562306a36Sopenharmony_ci &st->soc_info.max_sample_rate); 235662306a36Sopenharmony_ci if (ret) { 235762306a36Sopenharmony_ci dev_err(&pdev->dev, 235862306a36Sopenharmony_ci "invalid or missing value for atmel,max-sample-rate-hz\n"); 235962306a36Sopenharmony_ci return ret; 236062306a36Sopenharmony_ci } 236162306a36Sopenharmony_ci 236262306a36Sopenharmony_ci ret = device_property_read_u32(dev, "atmel,startup-time-ms", 236362306a36Sopenharmony_ci &st->soc_info.startup_time); 236462306a36Sopenharmony_ci if (ret) { 236562306a36Sopenharmony_ci dev_err(&pdev->dev, 236662306a36Sopenharmony_ci "invalid or missing value for atmel,startup-time-ms\n"); 236762306a36Sopenharmony_ci return ret; 236862306a36Sopenharmony_ci } 236962306a36Sopenharmony_ci 237062306a36Sopenharmony_ci ret = device_property_read_u32(dev, "atmel,trigger-edge-type", 237162306a36Sopenharmony_ci &edge_type); 237262306a36Sopenharmony_ci if (ret) { 237362306a36Sopenharmony_ci dev_dbg(&pdev->dev, 237462306a36Sopenharmony_ci "atmel,trigger-edge-type not specified, only software trigger available\n"); 237562306a36Sopenharmony_ci } 237662306a36Sopenharmony_ci 237762306a36Sopenharmony_ci st->selected_trig = NULL; 237862306a36Sopenharmony_ci 237962306a36Sopenharmony_ci /* find the right trigger, or no trigger at all */ 238062306a36Sopenharmony_ci for (i = 0; i < st->soc_info.platform->hw_trig_cnt + 1; i++) 238162306a36Sopenharmony_ci if (at91_adc_trigger_list[i].edge_type == edge_type) { 238262306a36Sopenharmony_ci st->selected_trig = &at91_adc_trigger_list[i]; 238362306a36Sopenharmony_ci break; 238462306a36Sopenharmony_ci } 238562306a36Sopenharmony_ci 238662306a36Sopenharmony_ci if (!st->selected_trig) { 238762306a36Sopenharmony_ci dev_err(&pdev->dev, "invalid external trigger edge value\n"); 238862306a36Sopenharmony_ci return -EINVAL; 238962306a36Sopenharmony_ci } 239062306a36Sopenharmony_ci 239162306a36Sopenharmony_ci init_waitqueue_head(&st->wq_data_available); 239262306a36Sopenharmony_ci mutex_init(&st->lock); 239362306a36Sopenharmony_ci INIT_WORK(&st->touch_st.workq, at91_adc_workq_handler); 239462306a36Sopenharmony_ci 239562306a36Sopenharmony_ci st->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); 239662306a36Sopenharmony_ci if (IS_ERR(st->base)) 239762306a36Sopenharmony_ci return PTR_ERR(st->base); 239862306a36Sopenharmony_ci 239962306a36Sopenharmony_ci /* if we plan to use DMA, we need the physical address of the regs */ 240062306a36Sopenharmony_ci st->dma_st.phys_addr = res->start; 240162306a36Sopenharmony_ci 240262306a36Sopenharmony_ci st->irq = platform_get_irq(pdev, 0); 240362306a36Sopenharmony_ci if (st->irq < 0) 240462306a36Sopenharmony_ci return st->irq; 240562306a36Sopenharmony_ci 240662306a36Sopenharmony_ci st->per_clk = devm_clk_get(&pdev->dev, "adc_clk"); 240762306a36Sopenharmony_ci if (IS_ERR(st->per_clk)) 240862306a36Sopenharmony_ci return PTR_ERR(st->per_clk); 240962306a36Sopenharmony_ci 241062306a36Sopenharmony_ci st->reg = devm_regulator_get(&pdev->dev, "vddana"); 241162306a36Sopenharmony_ci if (IS_ERR(st->reg)) 241262306a36Sopenharmony_ci return PTR_ERR(st->reg); 241362306a36Sopenharmony_ci 241462306a36Sopenharmony_ci st->vref = devm_regulator_get(&pdev->dev, "vref"); 241562306a36Sopenharmony_ci if (IS_ERR(st->vref)) 241662306a36Sopenharmony_ci return PTR_ERR(st->vref); 241762306a36Sopenharmony_ci 241862306a36Sopenharmony_ci ret = devm_request_irq(&pdev->dev, st->irq, at91_adc_interrupt, 0, 241962306a36Sopenharmony_ci pdev->dev.driver->name, indio_dev); 242062306a36Sopenharmony_ci if (ret) 242162306a36Sopenharmony_ci return ret; 242262306a36Sopenharmony_ci 242362306a36Sopenharmony_ci ret = regulator_enable(st->reg); 242462306a36Sopenharmony_ci if (ret) 242562306a36Sopenharmony_ci return ret; 242662306a36Sopenharmony_ci 242762306a36Sopenharmony_ci ret = regulator_enable(st->vref); 242862306a36Sopenharmony_ci if (ret) 242962306a36Sopenharmony_ci goto reg_disable; 243062306a36Sopenharmony_ci 243162306a36Sopenharmony_ci st->vref_uv = regulator_get_voltage(st->vref); 243262306a36Sopenharmony_ci if (st->vref_uv <= 0) { 243362306a36Sopenharmony_ci ret = -EINVAL; 243462306a36Sopenharmony_ci goto vref_disable; 243562306a36Sopenharmony_ci } 243662306a36Sopenharmony_ci 243762306a36Sopenharmony_ci ret = clk_prepare_enable(st->per_clk); 243862306a36Sopenharmony_ci if (ret) 243962306a36Sopenharmony_ci goto vref_disable; 244062306a36Sopenharmony_ci 244162306a36Sopenharmony_ci platform_set_drvdata(pdev, indio_dev); 244262306a36Sopenharmony_ci st->dev = &pdev->dev; 244362306a36Sopenharmony_ci pm_runtime_set_autosuspend_delay(st->dev, 500); 244462306a36Sopenharmony_ci pm_runtime_use_autosuspend(st->dev); 244562306a36Sopenharmony_ci pm_runtime_set_active(st->dev); 244662306a36Sopenharmony_ci pm_runtime_enable(st->dev); 244762306a36Sopenharmony_ci pm_runtime_get_noresume(st->dev); 244862306a36Sopenharmony_ci 244962306a36Sopenharmony_ci at91_adc_hw_init(indio_dev); 245062306a36Sopenharmony_ci 245162306a36Sopenharmony_ci ret = at91_adc_buffer_and_trigger_init(&pdev->dev, indio_dev); 245262306a36Sopenharmony_ci if (ret < 0) 245362306a36Sopenharmony_ci goto err_pm_disable; 245462306a36Sopenharmony_ci 245562306a36Sopenharmony_ci if (dma_coerce_mask_and_coherent(&indio_dev->dev, DMA_BIT_MASK(32))) 245662306a36Sopenharmony_ci dev_info(&pdev->dev, "cannot set DMA mask to 32-bit\n"); 245762306a36Sopenharmony_ci 245862306a36Sopenharmony_ci ret = iio_device_register(indio_dev); 245962306a36Sopenharmony_ci if (ret < 0) 246062306a36Sopenharmony_ci goto dma_disable; 246162306a36Sopenharmony_ci 246262306a36Sopenharmony_ci if (st->selected_trig->hw_trig) 246362306a36Sopenharmony_ci dev_info(&pdev->dev, "setting up trigger as %s\n", 246462306a36Sopenharmony_ci st->selected_trig->name); 246562306a36Sopenharmony_ci 246662306a36Sopenharmony_ci dev_info(&pdev->dev, "version: %x\n", 246762306a36Sopenharmony_ci readl_relaxed(st->base + st->soc_info.platform->layout->VERSION)); 246862306a36Sopenharmony_ci 246962306a36Sopenharmony_ci pm_runtime_mark_last_busy(st->dev); 247062306a36Sopenharmony_ci pm_runtime_put_autosuspend(st->dev); 247162306a36Sopenharmony_ci 247262306a36Sopenharmony_ci return 0; 247362306a36Sopenharmony_ci 247462306a36Sopenharmony_cidma_disable: 247562306a36Sopenharmony_ci at91_adc_dma_disable(st); 247662306a36Sopenharmony_cierr_pm_disable: 247762306a36Sopenharmony_ci pm_runtime_put_noidle(st->dev); 247862306a36Sopenharmony_ci pm_runtime_disable(st->dev); 247962306a36Sopenharmony_ci pm_runtime_set_suspended(st->dev); 248062306a36Sopenharmony_ci pm_runtime_dont_use_autosuspend(st->dev); 248162306a36Sopenharmony_ci clk_disable_unprepare(st->per_clk); 248262306a36Sopenharmony_civref_disable: 248362306a36Sopenharmony_ci regulator_disable(st->vref); 248462306a36Sopenharmony_cireg_disable: 248562306a36Sopenharmony_ci regulator_disable(st->reg); 248662306a36Sopenharmony_ci return ret; 248762306a36Sopenharmony_ci} 248862306a36Sopenharmony_ci 248962306a36Sopenharmony_cistatic int at91_adc_remove(struct platform_device *pdev) 249062306a36Sopenharmony_ci{ 249162306a36Sopenharmony_ci struct iio_dev *indio_dev = platform_get_drvdata(pdev); 249262306a36Sopenharmony_ci struct at91_adc_state *st = iio_priv(indio_dev); 249362306a36Sopenharmony_ci 249462306a36Sopenharmony_ci iio_device_unregister(indio_dev); 249562306a36Sopenharmony_ci 249662306a36Sopenharmony_ci at91_adc_dma_disable(st); 249762306a36Sopenharmony_ci 249862306a36Sopenharmony_ci pm_runtime_disable(st->dev); 249962306a36Sopenharmony_ci pm_runtime_set_suspended(st->dev); 250062306a36Sopenharmony_ci clk_disable_unprepare(st->per_clk); 250162306a36Sopenharmony_ci 250262306a36Sopenharmony_ci regulator_disable(st->vref); 250362306a36Sopenharmony_ci regulator_disable(st->reg); 250462306a36Sopenharmony_ci 250562306a36Sopenharmony_ci return 0; 250662306a36Sopenharmony_ci} 250762306a36Sopenharmony_ci 250862306a36Sopenharmony_cistatic int at91_adc_suspend(struct device *dev) 250962306a36Sopenharmony_ci{ 251062306a36Sopenharmony_ci struct iio_dev *indio_dev = dev_get_drvdata(dev); 251162306a36Sopenharmony_ci struct at91_adc_state *st = iio_priv(indio_dev); 251262306a36Sopenharmony_ci int ret; 251362306a36Sopenharmony_ci 251462306a36Sopenharmony_ci ret = pm_runtime_resume_and_get(st->dev); 251562306a36Sopenharmony_ci if (ret < 0) 251662306a36Sopenharmony_ci return ret; 251762306a36Sopenharmony_ci 251862306a36Sopenharmony_ci if (iio_buffer_enabled(indio_dev)) 251962306a36Sopenharmony_ci at91_adc_buffer_postdisable(indio_dev); 252062306a36Sopenharmony_ci 252162306a36Sopenharmony_ci /* 252262306a36Sopenharmony_ci * Do a sofware reset of the ADC before we go to suspend. 252362306a36Sopenharmony_ci * this will ensure that all pins are free from being muxed by the ADC 252462306a36Sopenharmony_ci * and can be used by for other devices. 252562306a36Sopenharmony_ci * Otherwise, ADC will hog them and we can't go to suspend mode. 252662306a36Sopenharmony_ci */ 252762306a36Sopenharmony_ci at91_adc_writel(st, CR, AT91_SAMA5D2_CR_SWRST); 252862306a36Sopenharmony_ci 252962306a36Sopenharmony_ci pm_runtime_mark_last_busy(st->dev); 253062306a36Sopenharmony_ci pm_runtime_put_noidle(st->dev); 253162306a36Sopenharmony_ci clk_disable_unprepare(st->per_clk); 253262306a36Sopenharmony_ci regulator_disable(st->vref); 253362306a36Sopenharmony_ci regulator_disable(st->reg); 253462306a36Sopenharmony_ci 253562306a36Sopenharmony_ci return pinctrl_pm_select_sleep_state(dev); 253662306a36Sopenharmony_ci} 253762306a36Sopenharmony_ci 253862306a36Sopenharmony_cistatic int at91_adc_resume(struct device *dev) 253962306a36Sopenharmony_ci{ 254062306a36Sopenharmony_ci struct iio_dev *indio_dev = dev_get_drvdata(dev); 254162306a36Sopenharmony_ci struct at91_adc_state *st = iio_priv(indio_dev); 254262306a36Sopenharmony_ci int ret; 254362306a36Sopenharmony_ci 254462306a36Sopenharmony_ci ret = pinctrl_pm_select_default_state(dev); 254562306a36Sopenharmony_ci if (ret) 254662306a36Sopenharmony_ci goto resume_failed; 254762306a36Sopenharmony_ci 254862306a36Sopenharmony_ci ret = regulator_enable(st->reg); 254962306a36Sopenharmony_ci if (ret) 255062306a36Sopenharmony_ci goto resume_failed; 255162306a36Sopenharmony_ci 255262306a36Sopenharmony_ci ret = regulator_enable(st->vref); 255362306a36Sopenharmony_ci if (ret) 255462306a36Sopenharmony_ci goto reg_disable_resume; 255562306a36Sopenharmony_ci 255662306a36Sopenharmony_ci ret = clk_prepare_enable(st->per_clk); 255762306a36Sopenharmony_ci if (ret) 255862306a36Sopenharmony_ci goto vref_disable_resume; 255962306a36Sopenharmony_ci 256062306a36Sopenharmony_ci pm_runtime_get_noresume(st->dev); 256162306a36Sopenharmony_ci 256262306a36Sopenharmony_ci at91_adc_hw_init(indio_dev); 256362306a36Sopenharmony_ci 256462306a36Sopenharmony_ci /* reconfiguring trigger hardware state */ 256562306a36Sopenharmony_ci if (iio_buffer_enabled(indio_dev)) { 256662306a36Sopenharmony_ci ret = at91_adc_buffer_prepare(indio_dev); 256762306a36Sopenharmony_ci if (ret) 256862306a36Sopenharmony_ci goto pm_runtime_put; 256962306a36Sopenharmony_ci 257062306a36Sopenharmony_ci at91_adc_configure_trigger_registers(st, true); 257162306a36Sopenharmony_ci } 257262306a36Sopenharmony_ci 257362306a36Sopenharmony_ci pm_runtime_mark_last_busy(st->dev); 257462306a36Sopenharmony_ci pm_runtime_put_autosuspend(st->dev); 257562306a36Sopenharmony_ci 257662306a36Sopenharmony_ci return 0; 257762306a36Sopenharmony_ci 257862306a36Sopenharmony_cipm_runtime_put: 257962306a36Sopenharmony_ci pm_runtime_mark_last_busy(st->dev); 258062306a36Sopenharmony_ci pm_runtime_put_noidle(st->dev); 258162306a36Sopenharmony_ci clk_disable_unprepare(st->per_clk); 258262306a36Sopenharmony_civref_disable_resume: 258362306a36Sopenharmony_ci regulator_disable(st->vref); 258462306a36Sopenharmony_cireg_disable_resume: 258562306a36Sopenharmony_ci regulator_disable(st->reg); 258662306a36Sopenharmony_ciresume_failed: 258762306a36Sopenharmony_ci dev_err(&indio_dev->dev, "failed to resume\n"); 258862306a36Sopenharmony_ci return ret; 258962306a36Sopenharmony_ci} 259062306a36Sopenharmony_ci 259162306a36Sopenharmony_cistatic int at91_adc_runtime_suspend(struct device *dev) 259262306a36Sopenharmony_ci{ 259362306a36Sopenharmony_ci struct iio_dev *indio_dev = dev_get_drvdata(dev); 259462306a36Sopenharmony_ci struct at91_adc_state *st = iio_priv(indio_dev); 259562306a36Sopenharmony_ci 259662306a36Sopenharmony_ci clk_disable(st->per_clk); 259762306a36Sopenharmony_ci 259862306a36Sopenharmony_ci return 0; 259962306a36Sopenharmony_ci} 260062306a36Sopenharmony_ci 260162306a36Sopenharmony_cistatic int at91_adc_runtime_resume(struct device *dev) 260262306a36Sopenharmony_ci{ 260362306a36Sopenharmony_ci struct iio_dev *indio_dev = dev_get_drvdata(dev); 260462306a36Sopenharmony_ci struct at91_adc_state *st = iio_priv(indio_dev); 260562306a36Sopenharmony_ci 260662306a36Sopenharmony_ci return clk_enable(st->per_clk); 260762306a36Sopenharmony_ci} 260862306a36Sopenharmony_ci 260962306a36Sopenharmony_cistatic const struct dev_pm_ops at91_adc_pm_ops = { 261062306a36Sopenharmony_ci SYSTEM_SLEEP_PM_OPS(at91_adc_suspend, at91_adc_resume) 261162306a36Sopenharmony_ci RUNTIME_PM_OPS(at91_adc_runtime_suspend, at91_adc_runtime_resume, 261262306a36Sopenharmony_ci NULL) 261362306a36Sopenharmony_ci}; 261462306a36Sopenharmony_ci 261562306a36Sopenharmony_cistatic const struct of_device_id at91_adc_dt_match[] = { 261662306a36Sopenharmony_ci { 261762306a36Sopenharmony_ci .compatible = "atmel,sama5d2-adc", 261862306a36Sopenharmony_ci .data = (const void *)&sama5d2_platform, 261962306a36Sopenharmony_ci }, { 262062306a36Sopenharmony_ci .compatible = "microchip,sama7g5-adc", 262162306a36Sopenharmony_ci .data = (const void *)&sama7g5_platform, 262262306a36Sopenharmony_ci }, { 262362306a36Sopenharmony_ci /* sentinel */ 262462306a36Sopenharmony_ci } 262562306a36Sopenharmony_ci}; 262662306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, at91_adc_dt_match); 262762306a36Sopenharmony_ci 262862306a36Sopenharmony_cistatic struct platform_driver at91_adc_driver = { 262962306a36Sopenharmony_ci .probe = at91_adc_probe, 263062306a36Sopenharmony_ci .remove = at91_adc_remove, 263162306a36Sopenharmony_ci .driver = { 263262306a36Sopenharmony_ci .name = "at91-sama5d2_adc", 263362306a36Sopenharmony_ci .of_match_table = at91_adc_dt_match, 263462306a36Sopenharmony_ci .pm = pm_ptr(&at91_adc_pm_ops), 263562306a36Sopenharmony_ci }, 263662306a36Sopenharmony_ci}; 263762306a36Sopenharmony_cimodule_platform_driver(at91_adc_driver) 263862306a36Sopenharmony_ci 263962306a36Sopenharmony_ciMODULE_AUTHOR("Ludovic Desroches <ludovic.desroches@microchip.com>"); 264062306a36Sopenharmony_ciMODULE_AUTHOR("Eugen Hristev <eugen.hristev@microchip.com"); 264162306a36Sopenharmony_ciMODULE_DESCRIPTION("Atmel AT91 SAMA5D2 ADC"); 264262306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 2643