/*
* Freescale Vybrid vf610 ADC driver
*
* Copyright 2013 Freescale Semiconductor, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/completion.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/regulator/consumer.h>
#include <linux/of_platform.h>
#include <linux/err.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/driver.h>
/* This will be the driver name the kernel reports */
#define DRIVER_NAME "vf610-adc"
/* Vybrid/IMX ADC registers */
#define VF610_REG_ADC_HC0 0x00
#define VF610_REG_ADC_HC1 0x04
#define VF610_REG_ADC_HS 0x08
#define VF610_REG_ADC_R0 0x0c
#define VF610_REG_ADC_R1 0x10
#define VF610_REG_ADC_CFG 0x14
#define VF610_REG_ADC_GC 0x18
#define VF610_REG_ADC_GS 0x1c
#define VF610_REG_ADC_CV 0x20
#define VF610_REG_ADC_OFS 0x24
#define VF610_REG_ADC_CAL 0x28
#define VF610_REG_ADC_PCTL 0x30
/* Configuration register field define */
#define VF610_ADC_MODE_BIT8 0x00
#define VF610_ADC_MODE_BIT10 0x04
#define VF610_ADC_MODE_BIT12 0x08
#define VF610_ADC_MODE_MASK 0x0c
#define VF610_ADC_BUSCLK2_SEL 0x01
#define VF610_ADC_ALTCLK_SEL 0x02
#define VF610_ADC_ADACK_SEL 0x03
#define VF610_ADC_ADCCLK_MASK 0x03
#define VF610_ADC_CLK_DIV2 0x20
#define VF610_ADC_CLK_DIV4 0x40
#define VF610_ADC_CLK_DIV8 0x60
#define VF610_ADC_CLK_MASK 0x60
#define VF610_ADC_ADLSMP_LONG 0x10
#define VF610_ADC_ADSTS_MASK 0x300
#define VF610_ADC_ADLPC_EN 0x80
#define VF610_ADC_ADHSC_EN 0x400
#define VF610_ADC_REFSEL_VALT 0x100
#define VF610_ADC_REFSEL_VBG 0x1000
#define VF610_ADC_ADTRG_HARD 0x2000
#define VF610_ADC_AVGS_8 0x4000
#define VF610_ADC_AVGS_16 0x8000
#define VF610_ADC_AVGS_32 0xC000
#define VF610_ADC_AVGS_MASK 0xC000
#define VF610_ADC_OVWREN 0x10000
/* General control register field define */
#define VF610_ADC_ADACKEN 0x1
#define VF610_ADC_DMAEN 0x2
#define VF610_ADC_ACREN 0x4
#define VF610_ADC_ACFGT 0x8
#define VF610_ADC_ACFE 0x10
#define VF610_ADC_AVGEN 0x20
#define VF610_ADC_ADCON 0x40
#define VF610_ADC_CAL 0x80
/* Other field define */
#define VF610_ADC_ADCHC(x) ((x) & 0x1F)
#define VF610_ADC_AIEN (0x1 << 7)
#define VF610_ADC_CONV_DISABLE 0x1F
#define VF610_ADC_HS_COCO0 0x1
#define VF610_ADC_CALF 0x2
#define VF610_ADC_TIMEOUT msecs_to_jiffies(100)
enum clk_sel {
VF610_ADCIOC_BUSCLK_SET,
VF610_ADCIOC_ALTCLK_SET,
VF610_ADCIOC_ADACK_SET,
};
enum vol_ref {
VF610_ADCIOC_VR_VREF_SET,
VF610_ADCIOC_VR_VALT_SET,
VF610_ADCIOC_VR_VBG_SET,
};
enum average_sel {
VF610_ADC_SAMPLE_1,
VF610_ADC_SAMPLE_4,
VF610_ADC_SAMPLE_8,
VF610_ADC_SAMPLE_16,
VF610_ADC_SAMPLE_32,
};
struct vf610_adc_feature {
enum clk_sel clk_sel;
enum vol_ref vol_ref;
int clk_div;
int sample_rate;
int res_mode;
bool lpm;
bool calibration;
bool ovwren;
};
struct vf610_adc {
struct device *dev;
void __iomem *regs;
struct clk *clk;
u32 vref_uv;
u32 value;
struct regulator *vref;
struct vf610_adc_feature adc_feature;
struct completion completion;
};
#define VF610_ADC_CHAN(_idx, _chan_type) { \
.type = (_chan_type), \
.indexed = 1, \
.channel = (_idx), \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_SAMP_FREQ), \
}
#define VF610_ADC_TEMPERATURE_CHAN(_idx, _chan_type) { \
.type = (_chan_type), \
.channel = (_idx), \
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \
}
static const struct iio_chan_spec vf610_adc_iio_channels[] = {
VF610_ADC_CHAN(0, IIO_VOLTAGE),
VF610_ADC_CHAN(1, IIO_VOLTAGE),
VF610_ADC_CHAN(2, IIO_VOLTAGE),
VF610_ADC_CHAN(3, IIO_VOLTAGE),
VF610_ADC_CHAN(4, IIO_VOLTAGE),
VF610_ADC_CHAN(5, IIO_VOLTAGE),
VF610_ADC_CHAN(6, IIO_VOLTAGE),
VF610_ADC_CHAN(7, IIO_VOLTAGE),
VF610_ADC_CHAN(8, IIO_VOLTAGE),
VF610_ADC_CHAN(9, IIO_VOLTAGE),
VF610_ADC_CHAN(10, IIO_VOLTAGE),
VF610_ADC_CHAN(11, IIO_VOLTAGE),
VF610_ADC_CHAN(12, IIO_VOLTAGE),
VF610_ADC_CHAN(13, IIO_VOLTAGE),
VF610_ADC_CHAN(14, IIO_VOLTAGE),
VF610_ADC_CHAN(15, IIO_VOLTAGE),
VF610_ADC_TEMPERATURE_CHAN(26, IIO_TEMP),
/* sentinel */
};
/*
* ADC sample frequency, unit is ADCK cycles.
* ADC clk source is ipg clock, which is the same as bus clock.
*
* ADC conversion time = SFCAdder + AverageNum x (BCT + LSTAdder)
* SFCAdder: fixed to 6 ADCK cycles
* AverageNum: 1, 4, 8, 16, 32 samples for hardware average.
* BCT (Base Conversion Time): fixed to 25 ADCK cycles for 12 bit mode
* LSTAdder(Long Sample Time): fixed to 3 ADCK cycles
*
* By default, enable 12 bit resolution mode, clock source
* set to ipg clock, So get below frequency group:
*/
static const u32 vf610_sample_freq_avail[5] =
{1941176, 559332, 286957, 145374, 73171};
static inline void vf610_adc_cfg_init(struct vf610_adc *info)
{
/* set default Configuration for ADC controller */
info->adc_feature.clk_sel = VF610_ADCIOC_BUSCLK_SET;
info->adc_feature.vol_ref = VF610_ADCIOC_VR_VREF_SET;
info->adc_feature.calibration = true;
info->adc_feature.ovwren = true;
info->adc_feature.clk_div = 1;
info->adc_feature.res_mode = 12;
info->adc_feature.sample_rate = 1;
info->adc_feature.lpm = true;
}
static void vf610_adc_cfg_post_set(struct vf610_adc *info)
{
struct vf610_adc_feature *adc_feature = &info->adc_feature;
int cfg_data = 0;
int gc_data = 0;
switch (adc_feature->clk_sel) {
case VF610_ADCIOC_ALTCLK_SET:
cfg_data |= VF610_ADC_ALTCLK_SEL;
break;
case VF610_ADCIOC_ADACK_SET:
cfg_data |= VF610_ADC_ADACK_SEL;
break;
default:
break;
}
/* low power set for calibration */
cfg_data |= VF610_ADC_ADLPC_EN;
/* enable high speed for calibration */
cfg_data |= VF610_ADC_ADHSC_EN;
/* voltage reference */
switch (adc_feature->vol_ref) {
case VF610_ADCIOC_VR_VREF_SET:
break;
case VF610_ADCIOC_VR_VALT_SET:
cfg_data |= VF610_ADC_REFSEL_VALT;
break;
case VF610_ADCIOC_VR_VBG_SET:
cfg_data |= VF610_ADC_REFSEL_VBG;
break;
default:
dev_err(info->dev, "error voltage reference\n");
}
/* data overwrite enable */
if (adc_feature->ovwren)
cfg_data |= VF610_ADC_OVWREN;
writel(cfg_data, info->regs + VF610_REG_ADC_CFG);
writel(gc_data, info->regs + VF610_REG_ADC_GC);
}
static void vf610_adc_calibration(struct vf610_adc *info)
{
int adc_gc, hc_cfg;
int timeout;
if (!info->adc_feature.calibration)
return;
/* enable calibration interrupt */
hc_cfg = VF610_ADC_AIEN | VF610_ADC_CONV_DISABLE;
writel(hc_cfg, info->regs + VF610_REG_ADC_HC0);
adc_gc = readl(info->regs + VF610_REG_ADC_GC);
writel(adc_gc | VF610_ADC_CAL, info->regs + VF610_REG_ADC_GC);
timeout = wait_for_completion_timeout
(&info->completion, VF610_ADC_TIMEOUT);
if (timeout == 0)
dev_err(info->dev, "Timeout for adc calibration\n");
adc_gc = readl(info->regs + VF610_REG_ADC_GS);
if (adc_gc & VF610_ADC_CALF)
dev_err(info->dev, "ADC calibration failed\n");
info->adc_feature.calibration = false;
}
static void vf610_adc_cfg_set(struct vf610_adc *info)
{
struct vf610_adc_feature *adc_feature = &(info->adc_feature);
int cfg_data;
cfg_data = readl(info->regs + VF610_REG_ADC_CFG);
/* low power configuration */
cfg_data &= ~VF61