Re: [RFC][PATCH] iio: basic ADC support for Freescale i.MX25

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 02/14/2013 10:02 PM, Denis Darwish wrote:
> This patch adds basic support for Freescale i.MX25 ADC in the IIO Subsystem.
> It is provides direct access via sysfs, IRQ not used now.
> Compile tested with linux-next.
> Functionality tested with linux 3.3.0.
> 

Hi,

I realize this is a RFC, but this driver definitily needs quite a bit of
work. There a few code style issues, please run checkpatch.pl on your driver.

> 
> From c57696f02b235837a67e2607da517bdcabaa72a5 Mon Sep 17 00:00:00 2001
> From: ddarwish <darwish.d.d@xxxxxxxxx>

This should be your full name


> Date: Thu, 14 Feb 2013 11:59:07 +0400
> Subject: [PATCH] simple Freescale i.MX25 ADC driver
> 

This needs a commit message and a Signed-off-by.

> ---
>  arch/arm/mach-imx/clk-imx25.c         |    2 +-
>  arch/arm/mach-imx/mx25.h              |    1 +
>  drivers/staging/iio/adc/Kconfig       |   12 +
>  drivers/staging/iio/adc/Makefile      |    1 +
>  drivers/staging/iio/adc/imx25_adc.c   |  456 +++++++++++++++++++++++++++++++++
>  drivers/staging/iio/adc/imx_adc.h     |   13 +
>  drivers/staging/iio/adc/imx_adc_reg.h |  243 ++++++++++++++++++
>  7 files changed, 727 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/staging/iio/adc/imx25_adc.c
>  create mode 100644 drivers/staging/iio/adc/imx_adc.h
>  create mode 100644 drivers/staging/iio/adc/imx_adc_reg.h
> 
[...]
> diff --git a/drivers/staging/iio/adc/Makefile b/drivers/staging/iio/adc/Makefile
> index d285596..b64ec6d 100644
> --- a/drivers/staging/iio/adc/Makefile
> +++ b/drivers/staging/iio/adc/Makefile
> @@ -21,3 +21,4 @@ obj-$(CONFIG_AD7280) += ad7280a.o
>  obj-$(CONFIG_LPC32XX_ADC) += lpc32xx_adc.o
>  obj-$(CONFIG_MXS_LRADC) += mxs-lradc.o
>  obj-$(CONFIG_SPEAR_ADC) += spear_adc.o
> +obj-$(CONFIG_IMX25_ADC) += imx25_adc.o
> diff --git a/drivers/staging/iio/adc/imx25_adc.c b/drivers/staging/iio/adc/imx25_adc.c
> new file mode 100644
> index 0000000..6d3b438
> --- /dev/null
> +++ b/drivers/staging/iio/adc/imx25_adc.c

New drivers should not go into staging. We are trying to move all of the IIO
drivers out of staging.

> @@ -0,0 +1,456 @@
> +/**
> + * Copyright (c) 2013 Denis darwish
> + * Based on code by Freescale Semiconductor
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/slab.h>
> +#include <linux/module.h>
> +#include <linux/moduleparam.h>

No module parameters in this driver

> +#include <linux/platform_device.h>
> +#include <linux/io.h>
> +#include <linux/clk.h>
> +#include <linux/err.h>
> +
> +#include <linux/iio/iio.h>
> +#include <linux/iio/sysfs.h>
> +#include <linux/iio/events.h>
> +#include <linux/iio/buffer.h>
> +
> + #include "imx_adc_reg.h"
> + #include "imx_adc.h"
> +
> +#define IMX_ADC_DATA_BITS (12)
> +
> +struct imx_adc_state {
> +	struct clk				*adc_clk;
> +	unsigned long			channels_mask;

channels_mask never seems to be used.

> +	u16						value;
> +	struct mutex			lock;
> +	u8						num_channels;

num_channels isn't used either other than in probe().

> +	void __iomem			*reg_base;
> +	u32						vref_mv;
> +};
> +
> +static int adc_clk_enable(struct imx_adc_state *st)
> +{
> +	unsigned long reg;
> +	int ret;
> +	
> +	dev_info(NULL, "st point b2 %p \n", st);
> +
> +	ret = clk_enable(st->adc_clk);
> +	reg = __raw_readl(st->reg_base + TGCR);


You shouldn't use __raw_readl/__raw_writel directly. Use
readl_relaxed/writel_releaxed instead.

> +	reg |= TGCR_IPG_CLK_EN;
> +	__raw_writel(reg, st->reg_base + TGCR);

Considering how often you do this sequence (read reg, update value, write
reg) it may make sense to put this in a helper function.

> +	return (ret);

No need for the extra parenthesis.

> +}
> +
[...]
> +
> +void imx_adc_set_chanel(struct imx_adc_state *st, u8 channel) {
> +	unsigned long reg;
> +
> +	reg = __raw_readl(st->reg_base + GCQ_ITEM_7_0);

reg is always overwritten.

> +	switch (channel) {
> +		case 0:
> +			reg =  (GCQ_ITEM_GCC0 << GCQ_ITEM0_SHIFT);
> +			break;
> +		case 1:
> +			reg =  (GCQ_ITEM_GCC1 << GCQ_ITEM0_SHIFT);
> +			break;
> +		case 2:
> +			reg =  (GCQ_ITEM_GCC2 << GCQ_ITEM0_SHIFT);
> +			break;			
> +		default:
> +			break;
> +	}
> +	__raw_writel(reg, st->reg_base + GCQ_ITEM_7_0);
> +
> +}
> +
> +void imx_adc_read_general(unsigned short *result, struct imx_adc_state *st)
> +{
> +	unsigned long reg;
> +
> +	reg = __raw_readl(st->reg_base + GCQCR);
> +	reg |= CQCR_FQS;
> +	__raw_writel(reg, st->reg_base + GCQCR);
> +
> +	while (!(__raw_readl(st->reg_base + GCQSR) & CQSR_EOQ))
> +		continue;

Does the ADC offer a conversion done IRQ? Busy polling isn't the nicest
thing to do.

> +	reg = __raw_readl(st->reg_base + GCQCR);
> +	reg &= ~CQCR_FQS;
> +	__raw_writel(reg, st->reg_base + GCQCR);
> +	reg = __raw_readl(st->reg_base + GCQSR);
> +	reg |= CQSR_EOQ;
> +	__raw_writel(reg, st->reg_base + GCQSR);
> +
> +	while (!(__raw_readl(st->reg_base + GCQSR) & CQSR_EMPT)) {
> +		*result = __raw_readl(st->reg_base + GCQFIFO) >>
> +				 GCQFIFO_ADCOUT_SHIFT;
> +		
> +	}
> +
> +}
> +
> +#define IMX25_ADC_MAX_CH_NUM (3)
> +static struct iio_chan_spec imx_adc_iio_channels[IMX25_ADC_MAX_CH_NUM];
> +
> +static int imx_adc_read_raw(struct iio_dev *idev,
> +			     struct iio_chan_spec const *chan,
> +			     int *val, int *val2, long mask)
> +{
> +	struct imx_adc_state *st= iio_priv(idev);
> +	unsigned short rawresult;
> +
> +
> +	switch (mask) {
> +	case IIO_CHAN_INFO_RAW:
> +		mutex_lock(&st->lock);
> +
> +		imx_adc_set_chanel(st, chan->channel);
> +		imx_adc_read_general (&rawresult, st);
> +		
> +		st->value = rawresult;
> +		*val = st->value;
> +
> +		mutex_unlock(&st->lock);
> +		return IIO_VAL_INT;
> +
> +	case IIO_CHAN_INFO_SCALE:
> +		*val = (st->vref_mv * 1000) >> IMX_ADC_DATA_BITS; 
> +		*val2 = 0;
> +		return IIO_VAL_INT_PLUS_MICRO;

Using
		*val = st->vref_mv;
		*val2 = IMX_ADC_DATA_BITS;
		return IIO_VAL_FRACTIONAL_LOG2;

makes sense here.


> +	default:
> +		break;
> +	}
> +	return -EINVAL;
> +}
> +
> +static const struct iio_info imx_adc_info = {
> +	.driver_module = THIS_MODULE,
> +	.read_raw = &imx_adc_read_raw,
> +};
> +
> +static int imx_adc_probe_dt(struct imx_adc_state *st,
> +			     struct platform_device *pdev)
> +{
> +	//ToDo implement adc_probe_dt function
> +	return 1;
> +}
> +
> +/* platform data file should contain next
> +*
> +* static struct resource adc_resources[] = {
> +*         [0] = {
> +*                 .start  = MX25_TSC_BASE_ADDR,
> +*                 .end    = MX25_TSC_BASE_ADDR + SZ_16K - 1,
> +*                 .flags  = IORESOURCE_MEM,
> +*         },
> +* };
> +*
> +* static struct imx_adc_data mpu5_imx_adc_data = {
> +* 	.channels_used = 0x01,
> +* 	.num_channels = 3,
> +* 	.vref = 2500,
> +* };
> +* 
> +* 
> +* static struct platform_device imx_adc = {
> +* 	.name	= "imx25-adc",
> +* 	.id	= -1,
> +* 	.resource       = adc_resources,
> +* 	.num_resources  = ARRAY_SIZE(adc_resources),
> +* 	.dev = {
> +* 		.platform_data = &mpu5_imx_adc_data,
> +* 	}
> +* };
> +*/
> +
> +static int imx_adc_probe_pdata(struct imx_adc_state *st,
> +			     struct platform_device *pdev)
> +{
> +	struct imx_adc_data *pdata = pdev->dev.platform_data;
> +
> +	if (!pdata)
> +		return -EINVAL;
> +
> +
> +	st->vref_mv = pdata->vref;

Usually we use the regulator framework to get the reference voltage.

> +	st->channels_mask = pdata->channels_used;
> +	st->num_channels = pdata->num_channels;
> +	// st->trigger_number = pdata->trigger_number;
> +	// st->trigger_list = pdata->trigger_list;
> +	// st->registers = pdata->registers;
> +
> +	return 0;
> +}
> +
> +static int imx_adc_probe(struct platform_device *pdev)
> +{
> +	struct imx_adc_state *st;
> +	struct iio_dev *iodev = NULL;

The initialization to NULL is not really necessary, since you overwrite it
just a few lines later. Also most other drivers call the iio_dev variable
indio_dev, it would be good if you could do the same for consistency.

> +	int ret = -ENODEV;
> +	struct resource *res;
> +	int i;
> +
> +	dev_info(&pdev->dev, "version 0.0.5 \n");

All these dev_info's are quite a bit of noise.

> +
> +	iodev = iio_device_alloc(sizeof(struct imx_adc_state));
> +	// iodev = iio_allocate_device(sizeof(struct imx_adc_state)); //legasy name
> +	if (iodev == NULL) {
> +		dev_err(&pdev->dev, "failed allocating iio device\n");
> +		ret = -ENOMEM;
> +		goto error_ret;
> +	}
> +
> +	st = iio_priv(iodev);
> +
> +	if (pdev->dev.of_node)
> +		ret = imx_adc_probe_dt(st, pdev);
> +	else
> +		ret = imx_adc_probe_pdata(st, pdev);
> +
> +	if (ret) {
> +		dev_err(&pdev->dev, "No platform data available.\n");
> +		ret = -EINVAL;
> +		goto error_free_device;
> +	}
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!res) {
> +		dev_err(&pdev->dev, "No resource defined\n");
> +		ret = -ENXIO;
> +		goto error_ret;
> +	}
> +
> +	if (!request_mem_region(res->start, resource_size(res),
> +				"IMX adc registers")) {
> +		dev_err(&pdev->dev, "Resources are unavailable.\n");
> +		ret = -EBUSY;
> +		goto error_free_device;
> +	}
> +
> +	dev_info(&pdev->dev, "res->start %p \n", res->start);
> +
> +	st->reg_base = ioremap(res->start, resource_size(res));
> +	if (!st->reg_base) {
> +		dev_err(&pdev->dev, "Failed to map registers.\n");
> +		ret = -ENOMEM;
> +		goto error_release_mem;
> +	}


devm_ioremap_resource can be put to good use here, it will take care of the
request_mem_region and ioremap, as well as printing appropriate error
messages. So all the lines above basically boil down to:

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	st->reg_base = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(st->reg_base)) {
		ret = PTR_ERR(st->reg_base);
		goto err_free_device;
	}

Using managed resources also frees you from the burden of having to free
them manually.


> +
> +	dev_info(&pdev->dev, "reg_base %p \n", st->reg_base);
> +
> +	st->adc_clk = clk_get(&pdev->dev, NULL);

Could use devm_get_get

> +		if (IS_ERR(st->adc_clk)) {
> +		dev_err(&pdev->dev, "Failed to get the clock.\n");
> +		ret = PTR_ERR(st->adc_clk);
> +		goto error_free_clk;
> +	}
> +
> +	dev_info(&pdev->dev, "st point b1 %p \n", st);
> +	
> +	ret = adc_clk_enable(st);
> +	if (ret) {
> +		dev_err(&pdev->dev, "Could not enable the clock.\n");
> +		goto error_unprepare_clk;
> +	}
> +
> +	dev_info(&pdev->dev, "adc clk enabled\n");
> +
> +	/* Reset */
> +	tsc_self_reset(st);
> +	dev_info(&pdev->dev, "adc reseted\n");
> +
> +	// /* Internal reference */
> +	tsc_intref_enable(st);

If you are using the internal reference shouldn't you set vref_mv to the
voltage of the internal reference.

> +	dev_info(&pdev->dev, "Internal reference enabled\n");
> +
> +	adc_set_clk(st);
> +
> +	/* Set power mode */
> +	adc_set_power_mode(st);
> +
> +	/* Set queue*/
> +	adc_set_queue(st);
> +
> +	platform_set_drvdata(pdev, iodev);
> +
> +	iodev->name = dev_name(&pdev->dev);
> +	iodev->dev.parent = &pdev->dev;
> +	iodev->info = &imx_adc_info;
> +	iodev->modes = INDIO_DIRECT_MODE;
> +
> +	if (st->num_channels > IMX25_ADC_MAX_CH_NUM) {
> +		dev_err(&pdev->dev, "Platform data error. To many adc chanels \n");
> +		ret = -EINVAL;
> +		goto error_dev_cfg;
> +	}
> +	iodev->num_channels = st->num_channels;
> +
> +	for (i = 0; i < st->num_channels; i++) {
> +
> +		imx_adc_iio_channels[i].type = IIO_VOLTAGE;
> +		imx_adc_iio_channels[i].indexed = 1;
> +		imx_adc_iio_channels[i].channel = i;
> +		imx_adc_iio_channels[i].scan_index = 0;
> +		imx_adc_iio_channels[i].scan_type.sign = 'u';
> +		imx_adc_iio_channels[i].scan_type.realbits = 12;
> +		imx_adc_iio_channels[i].scan_type.storagebits = 16;
> +		// imx_adc_iio_channels[0].info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT |
> +		// 		IIO_CHAN_INFO_RAW_SEPARATE_BIT;
> +		imx_adc_iio_channels[i].info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT;

You should statically initialize imx_adc_iio_channels where you declare it.
It's a resource shared between all instances of a driver, so it shouldn't
depend on a specific instance.

> +	}
> +
> +	iodev->channels = imx_adc_iio_channels;
> +
> +	ret = iio_device_register(iodev);
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "Couldn't register the device.\n");
> +		goto error_dev;
> +	}
> +
> +	//ToDo Setup interrupt
> +
> +	mutex_init(&st->lock);

This nees to happen before the iio_device_register call otherwise you risk a
race condition.

> +
> +	//ToDo Setup buffers
> +	//ToDo Setup triggers
> +	//ToDo Setup registers
> +
> +	return 0;
> +
> +error_dev:
> +
> +error_dev_cfg:
> +
> +error_unprepare_clk:
> +	adc_clk_disable(st);
> +error_free_clk:
> +	clk_put(st->adc_clk);
> +error_release_mem:
> +	release_mem_region(res->start, resource_size(res));
> +error_free_device:
> +	iio_device_free(iodev);
> +error_ret:
> +	return ret;
> +}
> +
> +static int imx_adc_remove(struct platform_device *pdev)
> +{
> +	struct iio_dev *iodev = platform_get_drvdata(pdev);
> +	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	struct imx_adc_state *st = iio_priv(iodev);
> +
> +	iio_device_unregister(iodev);
> +
> +	adc_clk_disable(st);
> +	clk_put(st->adc_clk);
> +	release_mem_region(res->start, resource_size(res));
> +
> +	iio_device_free(iodev);
> +
> +	return 0;
> +}
> +
> +
> +static struct platform_driver imx_adc_driver = {
> +	.probe = imx_adc_probe,
> +	.remove = imx_adc_remove,
> +	.driver = {
> +		   .name = "imx25-adc",
> +//		   .of_match_table = of_match_ptr(imx25_adc_dt_ids),
> +	},
> +};
> +
> +module_platform_driver(imx_adc_driver);
> +
> +MODULE_AUTHOR("Denis Darwish <darwish.d.d@xxxxxxxxx>");
> +MODULE_DESCRIPTION("Freescale i.MX25 ADC Driver");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/staging/iio/adc/imx_adc.h b/drivers/staging/iio/adc/imx_adc.h
> new file mode 100644
> index 0000000..9ce3370
> --- /dev/null
> +++ b/drivers/staging/iio/adc/imx_adc.h
> @@ -0,0 +1,13 @@
> +
> +/**
> + * struct imx_adc_data - platform data for ADC driver
> + * @channels_used:              channels in use on the board as a bitmask
> + * @num_channels:               global number of channels available on the board
> + * @vref:                       Reference voltage for the ADC in millivolts
> + */
> + 
> +struct imx_adc_data {
> +		unsigned long	channels_used;
> +		u8				num_channels;
> +		u16				vref;
> +};
> \ No newline at end of file
> diff --git a/drivers/staging/iio/adc/imx_adc_reg.h b/drivers/staging/iio/adc/imx_adc_reg.h
> new file mode 100644
> index 0000000..9d9fc89
> --- /dev/null
> +++ b/drivers/staging/iio/adc/imx_adc_reg.h
> @@ -0,0 +1,243 @@
> +/*
> + * Copyright 2009-2011 Freescale Semiconductor, Inc. All Rights Reserved.
> + */
> +
> +/*
> + * The code contained herein is licensed under the GNU Lesser General
> + * Public License.  You may obtain a copy of the GNU Lesser General
> + * Public License Version 2.1 or later at the following locations:
> + *
> + * http://www.opensource.org/licenses/lgpl-license.html
> + * http://www.gnu.org/copyleft/lgpl.html
> + */
> +
> +#ifndef __IMX_ADC_H__
> +#define __IMX_ADC_H__

These defines don't seem to be shared with any other file, it makes sense to
just put them into the c file directly. Also it would be good to add a
prefix to them., like IMX_ADC_

> +
> +/* TSC General Config Register */
> +#define TGCR                  0x000
> +#define TGCR_IPG_CLK_EN       (1 << 0)
> +#define TGCR_TSC_RST          (1 << 1)
> +#define TGCR_FUNC_RST         (1 << 2)
> +#define TGCR_SLPC             (1 << 4)
> +#define TGCR_STLC             (1 << 5)
> +#define TGCR_HSYNC_EN         (1 << 6)
> +#define TGCR_HSYNC_POL        (1 << 7)
> +#define TGCR_POWERMODE_SHIFT  8
> +#define TGCR_POWER_OFF        (0x0 << TGCR_POWERMODE_SHIFT)
> +#define TGCR_POWER_SAVE       (0x1 << TGCR_POWERMODE_SHIFT)
> +#define TGCR_POWER_ON         (0x3 << TGCR_POWERMODE_SHIFT)
> +#define TGCR_POWER_MASK       (0x3 << TGCR_POWERMODE_SHIFT)
> +#define TGCR_INTREFEN         (1 << 10)
> +#define TGCR_ADCCLKCFG_SHIFT  16
> +#define TGCR_ADCCLKCFG_MASK	  (0x1F << TGCR_ADCCLKCFG_SHIFT)
> +#define TGCR_PD_EN            (1 << 23)
> +#define TGCR_PDB_EN           (1 << 24)
> +#define TGCR_PDBTIME_SHIFT    25
> +#define TGCR_PDBTIME128       (0x3f << TGCR_PDBTIME_SHIFT)
> +#define TGCR_PDBTIME_MASK     (0x7f << TGCR_PDBTIME_SHIFT)
> +
> +/* TSC General Status Register */
> +#define TGSR                  0x004
> +#define TCQ_INT               (1 << 0)
> +#define GCQ_INT               (1 << 1)
> +#define SLP_INT               (1 << 2)
> +#define TCQ_DMA               (1 << 16)
> +#define GCQ_DMA               (1 << 17)
> +
> +/* TSC IDLE Config Register */
> +#define TICR                  0x008
> +
> +/* TouchScreen Convert Queue FIFO Register */
> +#define TCQFIFO               0x400
> +/* TouchScreen Convert Queue Control Register */
> +#define TCQCR                 0x404
> +#define CQCR_QSM_SHIFT        0
> +#define CQCR_QSM_STOP         (0x0 << CQCR_QSM_SHIFT)
> +#define CQCR_QSM_PEN          (0x1 << CQCR_QSM_SHIFT)
> +#define CQCR_QSM_FQS          (0x2 << CQCR_QSM_SHIFT)
> +#define CQCR_QSM_FQS_PEN      (0x3 << CQCR_QSM_SHIFT)
> +#define CQCR_QSM_MASK         (0x3 << CQCR_QSM_SHIFT)
> +#define CQCR_FQS              (1 << 2)
> +#define CQCR_RPT              (1 << 3)
> +#define CQCR_LAST_ITEM_ID_SHIFT   4
> +#define CQCR_LAST_ITEM_ID_MASK    (0xf << CQCR_LAST_ITEM_ID_SHIFT)
> +#define CQCR_FIFOWATERMARK_SHIFT  8
> +#define CQCR_FIFOWATERMARK_MASK   (0xf << CQCR_FIFOWATERMARK_SHIFT)
> +#define CQCR_REPEATWAIT_SHIFT     12
> +#define CQCR_REPEATWAIT_MASK      (0xf << CQCR_REPEATWAIT_SHIFT)
> +#define CQCR_QRST             (1 << 16)
> +#define CQCR_FRST             (1 << 17)
> +#define CQCR_PD_MSK           (1 << 18)
> +#define CQCR_PD_CFG           (1 << 19)
> +
> +/* TouchScreen Convert Queue Status Register */
> +#define TCQSR                 0x408
> +#define CQSR_PD               (1 << 0)
> +#define CQSR_EOQ              (1 << 1)
> +#define CQSR_FOR              (1 << 4)
> +#define CQSR_FUR              (1 << 5)
> +#define CQSR_FER              (1 << 6)
> +#define CQSR_EMPT             (1 << 13)
> +#define CQSR_FULL             (1 << 14)
> +#define CQSR_FDRY             (1 << 15)
> +
> +/* TouchScreen Convert Queue Mask Register */
> +#define TCQMR                 0x40c
> +#define TCQMR_PD_IRQ_MSK      (1 << 0)
> +#define TCQMR_EOQ_IRQ_MSK     (1 << 1)
> +#define TCQMR_FOR_IRQ_MSK     (1 << 4)
> +#define TCQMR_FUR_IRQ_MSK     (1 << 5)
> +#define TCQMR_FER_IRQ_MSK     (1 << 6)
> +#define TCQMR_PD_DMA_MSK      (1 << 16)
> +#define TCQMR_EOQ_DMA_MSK     (1 << 17)
> +#define TCQMR_FOR_DMA_MSK     (1 << 20)
> +#define TCQMR_FUR_DMA_MSK     (1 << 21)
> +#define TCQMR_FER_DMA_MSK     (1 << 22)
> +#define TCQMR_FDRY_DMA_MSK    (1 << 31)
> +
> +/* TouchScreen Convert Queue ITEM 7~0 */
> +#define TCQ_ITEM_7_0          0x420
> +
> +/* TouchScreen Convert Queue ITEM 15~8 */
> +#define TCQ_ITEM_15_8         0x424
> +
> +#define TCQ_ITEM7_SHIFT       28
> +#define TCQ_ITEM6_SHIFT       24
> +#define TCQ_ITEM5_SHIFT       20
> +#define TCQ_ITEM4_SHIFT       16
> +#define TCQ_ITEM3_SHIFT       12
> +#define TCQ_ITEM2_SHIFT       8
> +#define TCQ_ITEM1_SHIFT       4
> +#define TCQ_ITEM0_SHIFT       0
> +
> +#define TCQ_ITEM_TCC0         0x0
> +#define TCQ_ITEM_TCC1         0x1
> +#define TCQ_ITEM_TCC2         0x2
> +#define TCQ_ITEM_TCC3         0x3
> +#define TCQ_ITEM_TCC4         0x4
> +#define TCQ_ITEM_TCC5         0x5
> +#define TCQ_ITEM_TCC6         0x6
> +#define TCQ_ITEM_TCC7         0x7
> +#define TCQ_ITEM_GCC7         0x8
> +#define TCQ_ITEM_GCC6         0x9
> +#define TCQ_ITEM_GCC5         0xa
> +#define TCQ_ITEM_GCC4         0xb
> +#define TCQ_ITEM_GCC3         0xc
> +#define TCQ_ITEM_GCC2         0xd
> +#define TCQ_ITEM_GCC1         0xe
> +#define TCQ_ITEM_GCC0         0xf
> +
> +/* TouchScreen Convert Config 0-7 */
> +#define TCC0                  0x440
> +#define TCC1                  0x444
> +#define TCC2                  0x448
> +#define TCC3                  0x44c
> +#define TCC4                  0x450
> +#define TCC5                  0x454
> +#define TCC6                  0x458
> +#define TCC7                  0x45c
> +#define CC_PEN_IACK           (1 << 1)
> +#define CC_SEL_REFN_SHIFT     2
> +#define CC_SEL_REFN_YNLR      (0x1 << CC_SEL_REFN_SHIFT)
> +#define CC_SEL_REFN_AGND      (0x2 << CC_SEL_REFN_SHIFT)
> +#define CC_SEL_REFN_MASK      (0x3 << CC_SEL_REFN_SHIFT)
> +#define CC_SELIN_SHIFT        4
> +#define CC_SELIN_XPUL         (0x0 << CC_SELIN_SHIFT)
> +#define CC_SELIN_YPLL         (0x1 << CC_SELIN_SHIFT)
> +#define CC_SELIN_XNUR         (0x2 << CC_SELIN_SHIFT)
> +#define CC_SELIN_YNLR         (0x3 << CC_SELIN_SHIFT)
> +#define CC_SELIN_WIPER        (0x4 << CC_SELIN_SHIFT)
> +#define CC_SELIN_INAUX0       (0x5 << CC_SELIN_SHIFT)
> +#define CC_SELIN_INAUX1       (0x6 << CC_SELIN_SHIFT)
> +#define CC_SELIN_INAUX2       (0x7 << CC_SELIN_SHIFT)
> +#define CC_SELIN_MASK         (0x7 << CC_SELIN_SHIFT)
> +#define CC_SELREFP_SHIFT      7
> +#define CC_SELREFP_YPLL       (0x0 << CC_SELREFP_SHIFT)
> +#define CC_SELREFP_XPUL       (0x1 << CC_SELREFP_SHIFT)
> +#define CC_SELREFP_EXT        (0x2 << CC_SELREFP_SHIFT)
> +#define CC_SELREFP_INT        (0x3 << CC_SELREFP_SHIFT)
> +#define CC_SELREFP_MASK       (0x3 << CC_SELREFP_SHIFT)
> +#define CC_XPULSW             (1 << 9)
> +#define CC_XNURSW_SHIFT       10
> +#define CC_XNURSW_HIGH        (0x0 << CC_XNURSW_SHIFT)
> +#define CC_XNURSW_OFF         (0x1 << CC_XNURSW_SHIFT)
> +#define CC_XNURSW_LOW         (0x3 << CC_XNURSW_SHIFT)
> +#define CC_XNURSW_MASK        (0x3 << CC_XNURSW_SHIFT)
> +#define CC_YPLLSW_SHIFT       12
> +#define CC_YPLLSW_MASK        (0x3 << CC_YPLLSW_SHIFT)
> +#define CC_YNLRSW             (1 << 14)
> +#define CC_WIPERSW            (1 << 15)
> +#define CC_NOS_SHIFT          16
> +#define CC_YPLLSW_HIGH        (0x0 << CC_NOS_SHIFT)
> +#define CC_YPLLSW_OFF         (0x1 << CC_NOS_SHIFT)
> +#define CC_YPLLSW_LOW         (0x3 << CC_NOS_SHIFT)
> +#define CC_NOS_MASK           (0xf << CC_NOS_SHIFT)
> +#define CC_IGS                (1 << 20)
> +#define CC_SETTLING_TIME_SHIFT 24
> +#define CC_SETTLING_TIME_MASK (0xff << CC_SETTLING_TIME_SHIFT)
> +
> +#define TSC_4WIRE_PRECHARGE    0x158c
> +#define TSC_4WIRE_TOUCH_DETECT 0x578e
> +
> +#define TSC_4WIRE_X_MEASUMENT  0x1c90
> +#define TSC_4WIRE_Y_MEASUMENT  0x4604
> +
> +#define TSC_GENERAL_ADC_GCC0   0x17dc
> +#define TSC_GENERAL_ADC_GCC1   0x17ec
> +#define TSC_GENERAL_ADC_GCC2   0x17fc
> +
> +/* GeneralADC Convert Queue FIFO Register */
> +#define GCQFIFO                0x800
> +#define GCQFIFO_ADCOUT_SHIFT   4
> +#define GCQFIFO_ADCOUT_MASK    (0xfff << GCQFIFO_ADCOUT_SHIFT)
> +/* GeneralADC Convert Queue Control Register */
> +#define GCQCR                  0x804
> +/* GeneralADC Convert Queue Status Register */
> +#define GCQSR                  0x808
> +/* GeneralADC Convert Queue Mask Register */
> +#define GCQMR                  0x80c
> +
> +/* GeneralADC Convert Queue ITEM 7~0 */
> +#define GCQ_ITEM_7_0           0x820
> +/* GeneralADC Convert Queue ITEM 15~8 */
> +#define GCQ_ITEM_15_8          0x824
> +
> +#define GCQ_ITEM7_SHIFT        28
> +#define GCQ_ITEM6_SHIFT        24
> +#define GCQ_ITEM5_SHIFT        20
> +#define GCQ_ITEM4_SHIFT        16
> +#define GCQ_ITEM3_SHIFT        12
> +#define GCQ_ITEM2_SHIFT        8
> +#define GCQ_ITEM1_SHIFT        4
> +#define GCQ_ITEM0_SHIFT        0
> +
> +#define GCQ_ITEM_GCC0          0x0
> +#define GCQ_ITEM_GCC1          0x1
> +#define GCQ_ITEM_GCC2          0x2
> +#define GCQ_ITEM_GCC3          0x3
> +
> +/* GeneralADC Convert Config 0-7 */
> +#define GCC0                   0x840
> +#define GCC1                   0x844
> +#define GCC2                   0x848
> +#define GCC3                   0x84c
> +#define GCC4                   0x850
> +#define GCC5                   0x854
> +#define GCC6                   0x858
> +#define GCC7                   0x85c
> +
> +/* TSC Test Register R/W */
> +#define TTR                    0xc00
> +/* TSC Monitor Register 1, 2 */
> +#define MNT1                   0xc04
> +#define MNT2                   0xc04
> +
> +#define DETECT_ITEM_ID_1       1
> +#define DETECT_ITEM_ID_2       5
> +#define TS_X_ITEM_ID           2
> +#define TS_Y_ITEM_ID           3
> +#define TSI_DATA               1
> +#define FQS_DATA               0
> +
> +#endif				/* __IMX_ADC_H__ */

--
To unsubscribe from this list: send the line "unsubscribe linux-iio" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Input]     [Linux Kernel]     [Linux SCSI]     [X.org]

  Powered by Linux