saradc: add saradc driver for gxl/gxm

PD#138714: initial add saradc driver
1.add input/saradc
2.saradc support in gxl
3.saradc support in gxm
4.add bindings/amlogic/input/amlogic-saradc.txt

Change-Id: I95f523300c453d59bea6a3e92b962cbb195b613c
Signed-off-by: Xingyu Chen <xingyu.chen@amlogic.com>
This commit is contained in:
Xingyu Chen
2016-10-20 16:36:56 +08:00
committed by Yun Cai
parent 8a62dc1f10
commit d4d32dd85f
14 changed files with 768 additions and 0 deletions

View File

@@ -0,0 +1,24 @@
Amlogic Successive Approximation Register (SAR) A/D Converter bindings
Required properties:
- compatible: Must be "amlogic, saradc".
- clocks: The clock provided by the SoC to the device.
- clock-names: Shall be "saradc_clk" for the device.
- resets: Shall be "GCLK_IDX_SARADC" for the device.
- reg: Physical base address of the controller and length of memory mapped
region.
Optional properties:
- status: Shall be "ok" or "okay" if enabled or "disabled" if disabled.
Default is "ok".
Example:
saradc: saradc {
compatible = "amlogic, saradc";
status = "okay";
clocks = <&clock CLK_XTAL>;
clock-names = "saradc_clk";
resets = <&clock GCLK_IDX_SARADC>;
reg = <0x0 0xc1108680 0x0 0x30
0x0 0xc883c3d8 0x0 0x08>;
};

View File

@@ -13446,3 +13446,7 @@ F: scripts/amlogic/configs/
AMLOGIC CRYPTO DMA
M: Matthew Shyu <matthew.shyu@amlogic.com>
F: drivers/amlogic/crypto/*
AMLOGIC saradc
M: Xingyu Chen <xingyu.chen@amlogic.com>
F: drivers/amlogic/input/saradc/*

View File

@@ -699,5 +699,14 @@
interrupts = <0 188 1 0 189 1>;
reg = <0x0 0xc883e000 0x0 0x28>;
};
saradc: saradc {
compatible = "amlogic, saradc";
status = "okay";
clocks = <&clkc CLKID_SARADC>;
clock-names = "saradc_clk";
reg = <0x0 0xc1108680 0x0 0x30
0x0 0xc883c3d8 0x0 0x08>;
};
};

View File

@@ -744,5 +744,14 @@
interrupts = <0 188 1 0 189 1>;
reg = <0x0 0xc883e000 0x0 0x28>;
};
saradc: saradc {
compatible = "amlogic, saradc";
status = "okay";
clocks = <&clkc CLKID_SARADC>;
clock-names = "saradc_clk";
reg = <0x0 0xc1108680 0x0 0x30
0x0 0xc883c3d8 0x0 0x08>;
};
};

View File

@@ -168,6 +168,8 @@ CONFIG_AMLOGIC_TIMER=y
CONFIG_AMLOGIC_BC_TIMER=y
CONFIG_AMLOGIC_CLK=y
CONFIG_AMLOGIC_CRYPTO=y
CONFIG_AMLOGIC_INPUT=y
CONFIG_AMLOGIC_SARADC=y
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y

View File

@@ -32,5 +32,7 @@ source "drivers/amlogic/clocksource/Kconfig"
source "drivers/amlogic/clk/Kconfig"
source "drivers/amlogic/crypto/Kconfig"
source "drivers/amlogic/input/Kconfig"
endmenu
endif

View File

@@ -29,3 +29,5 @@ obj-$(CONFIG_AMLOGIC_TIMER) += clocksource/
obj-$(CONFIG_AMLOGIC_CLK) += clk/
obj-$(CONFIG_AMLOGIC_CRYPTO) += crypto/
obj-$(CONFIG_AMLOGIC_INPUT) += input/

View File

@@ -0,0 +1,16 @@
#
# Input device configuration
#
menuconfig AMLOGIC_INPUT
bool "Input Device Support"
default n
help
"Input devices include keyboard, touchscreen, remote, sensor, etc."
if AMLOGIC_INPUT
source "drivers/amlogic/input/saradc/Kconfig"
endif

View File

@@ -0,0 +1,8 @@
#
# Makefile for the input core drivers.
#
# Each configuration option enables a list of files.
obj-$(CONFIG_AMLOGIC_INPUT) += saradc/

View File

@@ -0,0 +1,8 @@
#
# Input core configuration
#
config AMLOGIC_SARADC
bool "Meson SAR ADC support"
default n
help
Say Y here if you want to use the Meson SAR ADC.

View File

@@ -0,0 +1,9 @@
#
# Makefile for the input core drivers.
#
# Each configuration option enables a list of files.
obj-$(CONFIG_AMLOGIC_SARADC) += saradc.o

View File

@@ -0,0 +1,566 @@
/*
* drivers/amlogic/input/saradc/saradc.c
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
* 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.
*
*/
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/amlogic/saradc.h>
#include <linux/amlogic/cpu_version.h>
#include <asm/barrier.h>
#include "saradc_reg.h"
/* #define ENABLE_DYNAMIC_POWER */
#define CLEAN_BUFF_BEFORE_SARADC 1
/* flag_12bit = 0 : 10 bit */
/* flag_12bit = 1 : 12 bit */
static char flag_12bit;
#define saradc_info(x...) dev_info(adc->dev, x)
#define saradc_dbg(x...) /* dev_info(adc->dev, x) */
#define saradc_err(x...) dev_err(adc->dev, x)
#define SARADC_STATE_IDLE 0
#define SARADC_STATE_BUSY 1
#define SARADC_STATE_SUSPEND 2
struct saradc {
struct device *dev;
void __iomem *mem_base;
void __iomem *clk_mem_base;
struct clk *clk;
spinlock_t lock;
int ref_val;
int ref_nominal;
int coef;
int state;
};
static struct saradc *gp_saradc;
void setb(
void __iomem *mem_base,
unsigned int bits_desc,
unsigned int bits_val)
{
unsigned int mem_offset, val;
unsigned int bits_offset, bits_mask;
if (IS_ERR(mem_base))
return;
mem_offset = of_mem_offset(bits_desc);
bits_offset = of_bits_offset(bits_desc);
bits_mask = (1L<<of_bits_len(bits_desc))-1;
val = readl(mem_base+mem_offset);
val &= ~(bits_mask << bits_offset);
val |= (bits_val & bits_mask) << bits_offset;
writel(val, mem_base+mem_offset);
}
EXPORT_SYMBOL(setb);
unsigned int getb(
void __iomem *mem_base,
unsigned int bits_desc)
{
unsigned int mem_offset, val;
unsigned int bits_offset, bits_mask;
if (IS_ERR(mem_base))
return -1;
mem_offset = of_mem_offset(bits_desc);
bits_offset = of_bits_offset(bits_desc);
bits_mask = (1L<<of_bits_len(bits_desc))-1;
val = readl(mem_base+mem_offset);
return (val >> bits_offset) & bits_mask;
}
EXPORT_SYMBOL(getb);
static void saradc_power_control(struct saradc *adc, int on)
{
void __iomem *mem_base = adc->mem_base;
if (on) {
setb(mem_base, BANDGAP_EN, 1);
setb(mem_base, ADC_EN, 1);
udelay(5);
setb(mem_base, CLK_EN, 1);
setb(adc->clk_mem_base, REGC_CLK_EN, 1);
} else {
setb(adc->clk_mem_base, REGC_CLK_EN, 0);
setb(mem_base, CLK_EN, 0);
setb(mem_base, ADC_EN, 0);
setb(mem_base, BANDGAP_EN, 0);
}
}
static void saradc_reset(struct saradc *adc)
{
void __iomem *mem_base = adc->mem_base;
int clk_div;
if (getb(mem_base, FLAG_INITIALIZED)) {
saradc_info("initialized by BL30\n");
#ifndef ENABLE_DYNAMIC_POWER
saradc_power_control(adc, 1);
#endif
return;
}
writel(0x84004040, mem_base+SARADC_REG0);
writel(0, mem_base+SARADC_CH_LIST);
writel(0xaaaa, mem_base+SARADC_AVG_CNTL);
if (flag_12bit)
writel(0x9b88000a, mem_base+SARADC_REG3);
else
writel(0x9388000a, mem_base+SARADC_REG3);
/* set SARADC_DELAY with 0x190a380a when 32k */
writel(0x10a000a, mem_base+SARADC_DELAY);
writel(0x3eb1a0c, mem_base+SARADC_AUX_SW);
writel(0x3eb1a0c, mem_base+SARADC_AUX_SW);
writel(0x8c000c, mem_base+SARADC_CH10_SW);
writel(0xc000c, mem_base+SARADC_DETECT_IDLE_SW);
clk_prepare_enable(adc->clk);
clk_div = clk_get_rate(adc->clk) / 1200000;
setb(mem_base, CLK_DIV, clk_div);
setb(adc->clk_mem_base, REGC_CLK_DIV, clk_div);
setb(adc->clk_mem_base, REGC_CLK_SRC, 0);
saradc_info("initialized by kernel, clk_div=%d\n", clk_div);
#ifndef ENABLE_DYNAMIC_POWER
saradc_power_control(adc, 1);
#endif
}
static int saradc_internal_cal(struct saradc *adc)
{
int val[5], nominal[5] = {0, 256, 512, 768, 1023};
int i;
saradc_info("calibration start:\n");
adc->coef = 0;
for (i = 0; i < 5; i++) {
setb(adc->mem_base, CAL_CNTL, i);
udelay(10);
val[i] = get_adc_sample(0, CHAN_7);
saradc_info("nominal=%d, value=%d\n", nominal[i], val[i]);
if (val[i] < 0)
goto cal_end;
}
adc->ref_val = val[2];
adc->ref_nominal = nominal[2];
if (val[3] > val[1]) {
adc->coef = (nominal[3] - nominal[1]) << 12;
adc->coef /= val[3] - val[1];
}
cal_end:
saradc_info("calibration end: coef=%d\n", adc->coef);
setb(adc->mem_base, CAL_CNTL, 7);
return 0;
}
static int saradc_get_cal_value(struct saradc *adc, int val)
{
int nominal;
/*((nominal - ref_nominal) << 10) / (val - ref_val) = coef*/
/*==> nominal = ((val - ref_val) * coef >> 10) + ref_nominal*/
nominal = val;
if ((adc->coef > 0) && (val > 0)) {
nominal = (val - adc->ref_val) * adc->coef;
nominal >>= 12;
nominal += adc->ref_nominal;
}
if (nominal < 0)
nominal = 0;
if (nominal > 1023)
nominal = 1023;
return nominal;
}
static int saradc_get_cal_value_12bit(struct saradc *adc, int val)
{
int nominal;
/*((nominal - ref_nominal) << 10) / (val - ref_val) = coef*/
/*==> nominal = ((val - ref_val) * coef >> 10) + ref_nominal*/
nominal = val;
if ((adc->coef > 0) && (val > 0)) {
nominal = (val - adc->ref_val) * adc->coef;
nominal >>= 12;
nominal += adc->ref_nominal;
}
if (nominal < 0)
nominal = 0;
if (nominal > 4095)
nominal = 4095;
return nominal;
}
/*if_10bit=1:10bit*/
/*if_10bit=0:12bit*/
int get_adc_sample_early(int dev_id, int ch, char if_10bit)
{
struct saradc *adc;
void __iomem *mem_base;
int value, count, sum;
int max = 0;
int min = 0x3ff;
int min_12bit = 0xfff;
unsigned long flags;
if (!if_10bit)
min = min_12bit;
adc = gp_saradc;
mem_base = adc->mem_base;
if (!adc || getb(mem_base, FLAG_BUSY_BL30)
|| (adc->state != SARADC_STATE_IDLE))
return -1;
spin_lock_irqsave(&adc->lock, flags);
adc->state = SARADC_STATE_BUSY;
setb(mem_base, FLAG_BUSY_KERNEL, 1);
isb();
dsb(sy);
udelay(1);
if (getb(mem_base, FLAG_BUSY_BL30)) {
value = -1;
goto end;
}
#ifdef ENABLE_DYNAMIC_POWER
saradc_power_control(adc, 1);
#endif
#if CLEAN_BUFF_BEFORE_SARADC
count = 0;
while (getb(mem_base, FIFO_COUNT) && (count < FIFO_MAX)) {
value = readl(mem_base+SARADC_FIFO_RD);
count++;
}
#endif
writel(ch, mem_base+SARADC_CH_LIST);
setb(mem_base, DETECT_MUX, ch);
setb(mem_base, IDLE_MUX, ch);
setb(mem_base, SAMPLE_ENGINE_EN, 1);
setb(mem_base, START_SAMPLE, 1);
count = 0;
do {
udelay(1);
if (++count > 1000) {
saradc_err("busy, %x\n", readl(mem_base+SARADC_REG0));
value = -1;
goto end1;
}
} while (getb(mem_base, ALL_BUSY));
count = 0;
sum = 0;
while (getb(mem_base, FIFO_COUNT) && (count < FIFO_MAX)) {
value = readl(mem_base+SARADC_FIFO_RD);
if (((value>>12) & 0x07) == ch) {
if (if_10bit) {
if (flag_12bit) {
value &= 0xffc;
value >>= 2;
} else
value &= 0x3ff;
} else
value &= 0xfff;
if (value > max)
max = value;
if (value < min)
min = value;
sum += value;
count++;
}
}
if (!count) {
value = -1;
goto end1;
}
if (count > 2) {
sum -= (max + min);
count -= 2;
}
value = sum / count;
saradc_dbg("before cal: %d, count=%d\n", value, count);
if (adc->coef) {
if (if_10bit)
value = saradc_get_cal_value(adc, value);
else
value = saradc_get_cal_value_12bit(adc, value);
saradc_dbg("after cal: %d\n", value);
}
end1:
setb(mem_base, STOP_SAMPLE, 1);
setb(mem_base, SAMPLE_ENGINE_EN, 0);
#ifdef ENABLE_DYNAMIC_POWER
saradc_power_control(0);
#endif
end:
setb(mem_base, FLAG_BUSY_KERNEL, 0);
isb();
dsb(sy);
udelay(1);
adc->state = SARADC_STATE_IDLE;
spin_unlock_irqrestore(&adc->lock, flags);
return value;
}
int get_adc_sample(int dev_id, int ch)
{
int val;
val = get_adc_sample_early(dev_id, ch, 1);
return val;
}
EXPORT_SYMBOL(get_adc_sample);
int get_adc_sample_12bit(int dev_id, int ch)
{
int val;
val = get_adc_sample_early(dev_id, ch, 0);
return val;
}
EXPORT_SYMBOL(get_adc_sample_12bit);
static void __iomem *
saradc_get_reg_addr(struct platform_device *pdev, int index)
{
struct resource *res;
void __iomem *reg_addr;
res = platform_get_resource(pdev, IORESOURCE_MEM, index);
if (!res) {
dev_err(&pdev->dev, "reg: cannot obtain I/O memory region");
return 0;
}
if (!devm_request_mem_region(&pdev->dev, res->start,
resource_size(res), dev_name(&pdev->dev))) {
dev_err(&pdev->dev, "Memory region busy\n");
return 0;
}
reg_addr = devm_ioremap_nocache(&pdev->dev, res->start,
resource_size(res));
return reg_addr;
}
static ssize_t ch0_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
return sprintf(buf, "%d\n", get_adc_sample(0, 0));
}
static ssize_t ch1_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
return sprintf(buf, "%d\n", get_adc_sample(0, 1));
}
static ssize_t ch2_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
return sprintf(buf, "%d\n", get_adc_sample(0, 2));
}
static ssize_t ch3_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
return sprintf(buf, "%d\n", get_adc_sample(0, 3));
}
static ssize_t ch4_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
return sprintf(buf, "%d\n", get_adc_sample(0, 4));
}
static ssize_t ch5_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
return sprintf(buf, "%d\n", get_adc_sample(0, 5));
}
static ssize_t ch6_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
return sprintf(buf, "%d\n", get_adc_sample(0, 6));
}
static ssize_t ch7_show(struct class *cla,
struct class_attribute *attr, char *buf)
{
return sprintf(buf, "%d\n", get_adc_sample(0, 7));
}
static struct class_attribute saradc_class_attrs[] = {
__ATTR_RO(ch0),
__ATTR_RO(ch1),
__ATTR_RO(ch2),
__ATTR_RO(ch3),
__ATTR_RO(ch4),
__ATTR_RO(ch5),
__ATTR_RO(ch6),
__ATTR_RO(ch7),
__ATTR_NULL
};
static struct class saradc_class = {
.name = "saradc",
.class_attrs = saradc_class_attrs,
};
static int saradc_probe(struct platform_device *pdev)
{
int err;
struct saradc *adc;
if (is_meson_gxbb_cpu() || is_meson_gxtvbb_cpu())
flag_12bit = 0;
else
flag_12bit = 1;
adc = kzalloc(sizeof(struct saradc), GFP_KERNEL);
if (!adc) {
err = -ENOMEM;
goto end_err;
}
adc->dev = &pdev->dev;
if (!pdev->dev.of_node) {
err = -EINVAL;
goto end_free;
}
adc->mem_base = saradc_get_reg_addr(pdev, 0);
if (!adc->mem_base) {
err = -ENODEV;
goto end_free;
}
adc->clk_mem_base = saradc_get_reg_addr(pdev, 1);
adc->clk = devm_clk_get(&pdev->dev, "saradc_clk");
if (IS_ERR(adc->clk)) {
err = -ENOENT;
goto end_free;
}
saradc_reset(adc);
gp_saradc = adc;
dev_set_drvdata(&pdev->dev, adc);
spin_lock_init(&adc->lock);
adc->state = SARADC_STATE_IDLE;
saradc_internal_cal(adc);
return 0;
end_free:
kfree(adc);
end_err:
dev_err(&pdev->dev, "error=%d\n", err);
return err;
}
static int saradc_suspend(struct platform_device *pdev, pm_message_t state)
{
struct saradc *adc = (struct saradc *)dev_get_drvdata(&pdev->dev);
unsigned long flags;
spin_lock_irqsave(&adc->lock, flags);
saradc_power_control(adc, 0);
adc->state = SARADC_STATE_SUSPEND;
spin_unlock_irqrestore(&adc->lock, flags);
return 0;
}
static int saradc_resume(struct platform_device *pdev)
{
struct saradc *adc = (struct saradc *)dev_get_drvdata(&pdev->dev);
unsigned long flags;
spin_lock_irqsave(&adc->lock, flags);
saradc_power_control(adc, 1);
adc->state = SARADC_STATE_IDLE;
spin_unlock_irqrestore(&adc->lock, flags);
return 0;
}
static int saradc_remove(struct platform_device *pdev)
{
struct saradc *adc = (struct saradc *)dev_get_drvdata(&pdev->dev);
unsigned long flags;
spin_lock_irqsave(&adc->lock, flags);
saradc_power_control(adc, 0);
spin_unlock_irqrestore(&adc->lock, flags);
kfree(adc);
return 0;
}
static void saradc_shutdown(struct platform_device *pdev)
{
struct saradc *adc = (struct saradc *)dev_get_drvdata(&pdev->dev);
unsigned long flags;
spin_lock_irqsave(&adc->lock, flags);
saradc_power_control(adc, 0);
spin_unlock_irqrestore(&adc->lock, flags);
}
#ifdef CONFIG_OF
static const struct of_device_id saradc_dt_match[] = {
{ .compatible = "amlogic, saradc"},
{},
};
#else
#define saradc_dt_match NULL
#endif
static struct platform_driver saradc_driver = {
.probe = saradc_probe,
.remove = saradc_remove,
.suspend = saradc_suspend,
.resume = saradc_resume,
.shutdown = saradc_shutdown,
.driver = {
.name = "saradc",
.of_match_table = saradc_dt_match,
},
};
static int __init saradc_init(void)
{
/* printk(KERN_INFO "SARADC Driver init.\n"); */
class_register(&saradc_class);
return platform_driver_register(&saradc_driver);
}
static void __exit saradc_exit(void)
{
/* printk(KERN_INFO "SARADC Driver exit.\n"); */
platform_driver_unregister(&saradc_driver);
class_unregister(&saradc_class);
}
module_init(saradc_init);
module_exit(saradc_exit);
MODULE_AUTHOR("aml");
MODULE_DESCRIPTION("SARADC Driver");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,59 @@
/*
* drivers/amlogic/input/saradc/saradc_reg.h
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
* 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.
*
*/
#ifndef __SARADC_REG_H__
#define __SARADC_REG_H__
#define SARADC_REG0 (0<<2)
#define SARADC_CH_LIST (1<<2)
#define SARADC_AVG_CNTL (2<<2)
#define SARADC_REG3 (3<<2)
#define SARADC_DELAY (4<<2)
#define SARADC_LAST_RD (5<<2)
#define SARADC_FIFO_RD (6<<2)
#define SARADC_AUX_SW (7<<2)
#define SARADC_CH10_SW (8<<2)
#define SARADC_DETECT_IDLE_SW (9<<2)
#define SARADC_DELTA_10 (10<<2)
#define SARADC_REG11 (11<<2)
#define SAMPLE_ENGINE_EN bits_desc(SARADC_REG0, 0, 1)
#define START_SAMPLE bits_desc(SARADC_REG0, 2, 1)
#define STOP_SAMPLE bits_desc(SARADC_REG0, 14, 1)
#define FIFO_COUNT bits_desc(SARADC_REG0, 21, 5)
#define SAMPLE_BUSY bits_desc(SARADC_REG0, 28, 1)
#define AVG_BUSY bits_desc(SARADC_REG0, 29, 1)
#define DELTA_BUSY bits_desc(SARADC_REG0, 30, 1)
#define ALL_BUSY bits_desc(SARADC_REG0, 28, 3)
#define CLK_DIV bits_desc(SARADC_REG3, 10, 1)
#define ADC_EN bits_desc(SARADC_REG3, 21, 1)
#define CAL_CNTL bits_desc(SARADC_REG3, 23, 3)
#define FLAG_INITIALIZED bits_desc(SARADC_REG3, 28, 1) /* for bl30 */
#define CLK_EN bits_desc(SARADC_REG3, 30, 1)
#define FLAG_BUSY_KERNEL bits_desc(SARADC_DELAY, 14, 1) /* for bl30 */
#define FLAG_BUSY_BL30 bits_desc(SARADC_DELAY, 15, 1) /* for bl30 */
#define IDLE_MUX bits_desc(SARADC_DETECT_IDLE_SW, 7, 3)
#define DETECT_MUX bits_desc(SARADC_DETECT_IDLE_SW, 23, 3)
#define BANDGAP_EN bits_desc(SARADC_REG11, 13, 1)
/* saradc clock register */
#define REGC_CLK_DIV bits_desc(0, 0, 8)
#define REGC_CLK_EN bits_desc(0, 8, 1)
#define REGC_CLK_SRC bits_desc(0, 9, 3)
#define FIFO_MAX 32
#endif

View File

@@ -0,0 +1,50 @@
/*
* include/linux/amlogic/saradc.h
*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
* 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.
*
*/
#ifndef __AML_SARADC_H__
#define __AML_SARADC_H__
#include <linux/io.h>
#define SARADC_DEV_NUM 1
enum {
CHAN_0 = 0,
CHAN_1,
CHAN_2,
CHAN_3,
CHAN_4,
CHAN_5,
CHAN_6,
CHAN_7,
SARADC_CHAN_NUM,
};
extern int get_adc_sample(int dev_id, int ch);
extern int get_adc_sample_12bit(int dev_id, int ch);
#define bits_desc(reg_offset, bits_offset, bits_len) \
(((bits_len)<<24)|((bits_offset)<<16)|(reg_offset))
#define of_mem_offset(bd) ((bd)&0xffff)
#define of_bits_offset(bd) (((bd)>>16)&0xff)
#define of_bits_len(bd) (((bd)>>24)&0xff)
extern void setb(void __iomem *mem_base, unsigned int bits_desc,
unsigned int bits_val);
extern unsigned int getb(void __iomem *mem_base, unsigned int bits_desc);
#endif