/*
* Driver for the ADC present in the Atmel AT91 evaluation boards.
*
* Copyright 2011 Free Electrons
*
* Licensed under the GPLv2 or later.
*/
#include <linux/bitmap.h>
#include <linux/bitops.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/jiffies.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/wait.h>
#include <linux/platform_data/at91_adc.h>
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
#include <linux/iio/trigger.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
#include <mach/at91_adc.h>
#define AT91_ADC_CHAN(st, ch) \
(st->registers->channel_base + (ch * 4))
#define at91_adc_readl(st, reg) \
(readl_relaxed(st->reg_base + reg))
#define at91_adc_writel(st, reg, val) \
(writel_relaxed(val, st->reg_base + reg))
#define DRIVER_NAME "at91_adc"
#define MAX_POS_BITS 12
#define TOUCH_SAMPLE_PERIOD_US 2000 /* 2ms */
#define TOUCH_PEN_DETECT_DEBOUNCE_US 200
struct at91_adc_caps {
bool has_ts; /* Support touch screen */
bool has_tsmr; /* only at91sam9x5, sama5d3 have TSMR reg */
/*
* Numbers of sampling data will be averaged. Can be 0~3.
* Hardware can average (2 ^ ts_filter_average) sample data.
*/
u8 ts_filter_average;
/* Pen Detection input pull-up resistor, can be 0~3 */
u8 ts_pen_detect_sensitivity;
/* startup time calculate function */
u32 (*calc_startup_ticks)(u8 startup_time, u32 adc_clk_khz);
u8 num_channels;
struct at91_adc_reg_desc registers;
};
enum atmel_adc_ts_type {
ATMEL_ADC_TOUCHSCREEN_NONE = 0,
ATMEL_ADC_TOUCHSCREEN_4WIRE = 4,
ATMEL_ADC_TOUCHSCREEN_5WIRE = 5,
};
struct at91_adc_state {
struct clk *adc_clk;
u16 *buffer;
unsigned long channels_mask;
struct clk *clk;
bool done;
int irq;
u16 last_value;
struct mutex lock;
u8 num_channels;
void __iomem *reg_base;
struct at91_adc_reg_desc *registers;
u8 startup_time;
u8 sample_hold_time;
bool sleep_mode;
struct iio_trigger **trig;
struct at91_adc_trigger *trigger_list;
u32 trigger_number;
bool use_external;
u32 vref_mv;
u32 res; /* resolution used for convertions */
bool low_res; /* the resolution corresponds to the lowest one */
wait_queue_head_t wq_data_avail;
struct at91_adc_caps *caps;
/*
* Following ADC channels are shared by touchscreen:
*
* CH0 -- Touch screen XP/UL
* CH1 -- Touch screen XM/UR
* CH2 -- Touch screen YP/LL
* CH3 -- Touch screen YM/Sense
* CH4 -- Touch screen LR(5-wire only)
*
* The bitfields below represents the reserved channel in the
* touchscreen mode.
*/
#define CHAN_MASK_TOUCHSCREEN_4WIRE (0xf << 0)
#define CHAN_MASK_TOUCHSCREEN_5WIRE (0x1f << 0)
enum atmel_adc_ts_type touchscreen_type;
struct input_dev *ts_input;
u16 ts_sample_period_val;
u32 ts_pressure_threshold;
};
static irqreturn_t at91_adc_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
struct iio_dev *idev = pf->indio_dev;
struct at91_adc_state *st = iio_priv(idev);
int i, j = 0;
for (i = 0; i < idev->masklength; i++) {
if (!test_bit(i, idev->active_scan_mask))
continue;
st->buffer[j] = at91_adc_readl(st, AT91_ADC_CHAN(st, i));
j++;
}
iio_push_to_buffers_with_timestamp(idev, st->buffer, pf->timestamp);
iio_trigger_notify_done(idev->trig);
/* Needed to ACK the DRDY interruption */
at91_adc_readl(st, AT91_ADC_LCDR);
enable_irq(st->irq);
return IRQ_HANDLED;
}
/* Handler for classic adc channel eoc trigger */
void handle_adc_eoc_trigger