cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

imx8qxp-adc.c (13928B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 * NXP i.MX8QXP ADC driver
      4 *
      5 * Based on the work of Haibo Chen <haibo.chen@nxp.com>
      6 * The initial developer of the original code is Haibo Chen.
      7 * Portions created by Haibo Chen are Copyright (C) 2018 NXP.
      8 * All Rights Reserved.
      9 *
     10 * Copyright (C) 2018 NXP
     11 * Copyright (C) 2021 Cai Huoqing
     12 */
     13#include <linux/bitfield.h>
     14#include <linux/bits.h>
     15#include <linux/clk.h>
     16#include <linux/completion.h>
     17#include <linux/delay.h>
     18#include <linux/err.h>
     19#include <linux/interrupt.h>
     20#include <linux/io.h>
     21#include <linux/kernel.h>
     22#include <linux/module.h>
     23#include <linux/platform_device.h>
     24#include <linux/pm_runtime.h>
     25#include <linux/regulator/consumer.h>
     26
     27#include <linux/iio/iio.h>
     28
     29#define ADC_DRIVER_NAME		"imx8qxp-adc"
     30
     31/* Register map definition */
     32#define IMX8QXP_ADR_ADC_CTRL		0x10
     33#define IMX8QXP_ADR_ADC_STAT		0x14
     34#define IMX8QXP_ADR_ADC_IE		0x18
     35#define IMX8QXP_ADR_ADC_DE		0x1c
     36#define IMX8QXP_ADR_ADC_CFG		0x20
     37#define IMX8QXP_ADR_ADC_FCTRL		0x30
     38#define IMX8QXP_ADR_ADC_SWTRIG		0x34
     39#define IMX8QXP_ADR_ADC_TCTRL(tid)	(0xc0 + (tid) * 4)
     40#define IMX8QXP_ADR_ADC_CMDH(cid)	(0x100 + (cid) * 8)
     41#define IMX8QXP_ADR_ADC_CMDL(cid)	(0x104 + (cid) * 8)
     42#define IMX8QXP_ADR_ADC_RESFIFO		0x300
     43#define IMX8QXP_ADR_ADC_TST		0xffc
     44
     45/* ADC bit shift */
     46#define IMX8QXP_ADC_IE_FWMIE_MASK		GENMASK(1, 0)
     47#define IMX8QXP_ADC_CTRL_FIFO_RESET_MASK	BIT(8)
     48#define IMX8QXP_ADC_CTRL_SOFTWARE_RESET_MASK	BIT(1)
     49#define IMX8QXP_ADC_CTRL_ADC_EN_MASK		BIT(0)
     50#define IMX8QXP_ADC_TCTRL_TCMD_MASK		GENMASK(31, 24)
     51#define IMX8QXP_ADC_TCTRL_TDLY_MASK		GENMASK(23, 16)
     52#define IMX8QXP_ADC_TCTRL_TPRI_MASK		GENMASK(15, 8)
     53#define IMX8QXP_ADC_TCTRL_HTEN_MASK		GENMASK(7, 0)
     54#define IMX8QXP_ADC_CMDL_CSCALE_MASK		GENMASK(13, 8)
     55#define IMX8QXP_ADC_CMDL_MODE_MASK		BIT(7)
     56#define IMX8QXP_ADC_CMDL_DIFF_MASK		BIT(6)
     57#define IMX8QXP_ADC_CMDL_ABSEL_MASK		BIT(5)
     58#define IMX8QXP_ADC_CMDL_ADCH_MASK		GENMASK(2, 0)
     59#define IMX8QXP_ADC_CMDH_NEXT_MASK		GENMASK(31, 24)
     60#define IMX8QXP_ADC_CMDH_LOOP_MASK		GENMASK(23, 16)
     61#define IMX8QXP_ADC_CMDH_AVGS_MASK		GENMASK(15, 12)
     62#define IMX8QXP_ADC_CMDH_STS_MASK		BIT(8)
     63#define IMX8QXP_ADC_CMDH_LWI_MASK		GENMASK(7, 7)
     64#define IMX8QXP_ADC_CMDH_CMPEN_MASK		GENMASK(0, 0)
     65#define IMX8QXP_ADC_CFG_PWREN_MASK		BIT(28)
     66#define IMX8QXP_ADC_CFG_PUDLY_MASK		GENMASK(23, 16)
     67#define IMX8QXP_ADC_CFG_REFSEL_MASK		GENMASK(7, 6)
     68#define IMX8QXP_ADC_CFG_PWRSEL_MASK		GENMASK(5, 4)
     69#define IMX8QXP_ADC_CFG_TPRICTRL_MASK		GENMASK(3, 0)
     70#define IMX8QXP_ADC_FCTRL_FWMARK_MASK		GENMASK(20, 16)
     71#define IMX8QXP_ADC_FCTRL_FCOUNT_MASK		GENMASK(4, 0)
     72#define IMX8QXP_ADC_RESFIFO_VAL_MASK		GENMASK(18, 3)
     73
     74/* ADC PARAMETER*/
     75#define IMX8QXP_ADC_CMDL_CHANNEL_SCALE_FULL		GENMASK(5, 0)
     76#define IMX8QXP_ADC_CMDL_SEL_A_A_B_CHANNEL		0
     77#define IMX8QXP_ADC_CMDL_STANDARD_RESOLUTION		0
     78#define IMX8QXP_ADC_CMDL_MODE_SINGLE			0
     79#define IMX8QXP_ADC_CMDH_LWI_INCREMENT_DIS		0
     80#define IMX8QXP_ADC_CMDH_CMPEN_DIS			0
     81#define IMX8QXP_ADC_PAUSE_EN				BIT(31)
     82#define IMX8QXP_ADC_TCTRL_TPRI_PRIORITY_HIGH		0
     83
     84#define IMX8QXP_ADC_TCTRL_HTEN_HW_TIRG_DIS		0
     85
     86#define IMX8QXP_ADC_TIMEOUT		msecs_to_jiffies(100)
     87
     88struct imx8qxp_adc {
     89	struct device *dev;
     90	void __iomem *regs;
     91	struct clk *clk;
     92	struct clk *ipg_clk;
     93	struct regulator *vref;
     94	/* Serialise ADC channel reads */
     95	struct mutex lock;
     96	struct completion completion;
     97};
     98
     99#define IMX8QXP_ADC_CHAN(_idx) {				\
    100	.type = IIO_VOLTAGE,					\
    101	.indexed = 1,						\
    102	.channel = (_idx),					\
    103	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
    104	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |	\
    105				BIT(IIO_CHAN_INFO_SAMP_FREQ),	\
    106}
    107
    108static const struct iio_chan_spec imx8qxp_adc_iio_channels[] = {
    109	IMX8QXP_ADC_CHAN(0),
    110	IMX8QXP_ADC_CHAN(1),
    111	IMX8QXP_ADC_CHAN(2),
    112	IMX8QXP_ADC_CHAN(3),
    113	IMX8QXP_ADC_CHAN(4),
    114	IMX8QXP_ADC_CHAN(5),
    115	IMX8QXP_ADC_CHAN(6),
    116	IMX8QXP_ADC_CHAN(7),
    117};
    118
    119static void imx8qxp_adc_reset(struct imx8qxp_adc *adc)
    120{
    121	u32 ctrl;
    122
    123	/*software reset, need to clear the set bit*/
    124	ctrl = readl(adc->regs + IMX8QXP_ADR_ADC_CTRL);
    125	ctrl |= FIELD_PREP(IMX8QXP_ADC_CTRL_SOFTWARE_RESET_MASK, 1);
    126	writel(ctrl, adc->regs + IMX8QXP_ADR_ADC_CTRL);
    127	udelay(10);
    128	ctrl &= ~FIELD_PREP(IMX8QXP_ADC_CTRL_SOFTWARE_RESET_MASK, 1);
    129	writel(ctrl, adc->regs + IMX8QXP_ADR_ADC_CTRL);
    130
    131	/* reset the fifo */
    132	ctrl |= FIELD_PREP(IMX8QXP_ADC_CTRL_FIFO_RESET_MASK, 1);
    133	writel(ctrl, adc->regs + IMX8QXP_ADR_ADC_CTRL);
    134}
    135
    136static void imx8qxp_adc_reg_config(struct imx8qxp_adc *adc, int channel)
    137{
    138	u32 adc_cfg, adc_tctrl, adc_cmdl, adc_cmdh;
    139
    140	/* ADC configuration */
    141	adc_cfg = FIELD_PREP(IMX8QXP_ADC_CFG_PWREN_MASK, 1) |
    142		  FIELD_PREP(IMX8QXP_ADC_CFG_PUDLY_MASK, 0x80)|
    143		  FIELD_PREP(IMX8QXP_ADC_CFG_REFSEL_MASK, 0) |
    144		  FIELD_PREP(IMX8QXP_ADC_CFG_PWRSEL_MASK, 3) |
    145		  FIELD_PREP(IMX8QXP_ADC_CFG_TPRICTRL_MASK, 0);
    146	writel(adc_cfg, adc->regs + IMX8QXP_ADR_ADC_CFG);
    147
    148	/* config the trigger control */
    149	adc_tctrl = FIELD_PREP(IMX8QXP_ADC_TCTRL_TCMD_MASK, 1) |
    150		    FIELD_PREP(IMX8QXP_ADC_TCTRL_TDLY_MASK, 0) |
    151		    FIELD_PREP(IMX8QXP_ADC_TCTRL_TPRI_MASK, IMX8QXP_ADC_TCTRL_TPRI_PRIORITY_HIGH) |
    152		    FIELD_PREP(IMX8QXP_ADC_TCTRL_HTEN_MASK, IMX8QXP_ADC_TCTRL_HTEN_HW_TIRG_DIS);
    153	writel(adc_tctrl, adc->regs + IMX8QXP_ADR_ADC_TCTRL(0));
    154
    155	/* config the cmd */
    156	adc_cmdl = FIELD_PREP(IMX8QXP_ADC_CMDL_CSCALE_MASK, IMX8QXP_ADC_CMDL_CHANNEL_SCALE_FULL) |
    157		   FIELD_PREP(IMX8QXP_ADC_CMDL_MODE_MASK, IMX8QXP_ADC_CMDL_STANDARD_RESOLUTION) |
    158		   FIELD_PREP(IMX8QXP_ADC_CMDL_DIFF_MASK, IMX8QXP_ADC_CMDL_MODE_SINGLE) |
    159		   FIELD_PREP(IMX8QXP_ADC_CMDL_ABSEL_MASK, IMX8QXP_ADC_CMDL_SEL_A_A_B_CHANNEL) |
    160		   FIELD_PREP(IMX8QXP_ADC_CMDL_ADCH_MASK, channel);
    161	writel(adc_cmdl, adc->regs + IMX8QXP_ADR_ADC_CMDL(0));
    162
    163	adc_cmdh = FIELD_PREP(IMX8QXP_ADC_CMDH_NEXT_MASK, 0) |
    164		   FIELD_PREP(IMX8QXP_ADC_CMDH_LOOP_MASK, 0) |
    165		   FIELD_PREP(IMX8QXP_ADC_CMDH_AVGS_MASK, 7) |
    166		   FIELD_PREP(IMX8QXP_ADC_CMDH_STS_MASK, 0) |
    167		   FIELD_PREP(IMX8QXP_ADC_CMDH_LWI_MASK, IMX8QXP_ADC_CMDH_LWI_INCREMENT_DIS) |
    168		   FIELD_PREP(IMX8QXP_ADC_CMDH_CMPEN_MASK, IMX8QXP_ADC_CMDH_CMPEN_DIS);
    169	writel(adc_cmdh, adc->regs + IMX8QXP_ADR_ADC_CMDH(0));
    170}
    171
    172static void imx8qxp_adc_fifo_config(struct imx8qxp_adc *adc)
    173{
    174	u32 fifo_ctrl, interrupt_en;
    175
    176	fifo_ctrl = readl(adc->regs + IMX8QXP_ADR_ADC_FCTRL);
    177	fifo_ctrl &= ~IMX8QXP_ADC_FCTRL_FWMARK_MASK;
    178	/* set the watermark level to 1 */
    179	fifo_ctrl |= FIELD_PREP(IMX8QXP_ADC_FCTRL_FWMARK_MASK, 0);
    180	writel(fifo_ctrl, adc->regs + IMX8QXP_ADR_ADC_FCTRL);
    181
    182	/* FIFO Watermark Interrupt Enable */
    183	interrupt_en = readl(adc->regs + IMX8QXP_ADR_ADC_IE);
    184	interrupt_en |= FIELD_PREP(IMX8QXP_ADC_IE_FWMIE_MASK, 1);
    185	writel(interrupt_en, adc->regs + IMX8QXP_ADR_ADC_IE);
    186}
    187
    188static void imx8qxp_adc_disable(struct imx8qxp_adc *adc)
    189{
    190	u32 ctrl;
    191
    192	ctrl = readl(adc->regs + IMX8QXP_ADR_ADC_CTRL);
    193	ctrl &= ~FIELD_PREP(IMX8QXP_ADC_CTRL_ADC_EN_MASK, 1);
    194	writel(ctrl, adc->regs + IMX8QXP_ADR_ADC_CTRL);
    195}
    196
    197static int imx8qxp_adc_read_raw(struct iio_dev *indio_dev,
    198				struct iio_chan_spec const *chan,
    199				int *val, int *val2, long mask)
    200{
    201	struct imx8qxp_adc *adc = iio_priv(indio_dev);
    202	struct device *dev = adc->dev;
    203
    204	u32 ctrl, vref_uv;
    205	long ret;
    206
    207	switch (mask) {
    208	case IIO_CHAN_INFO_RAW:
    209		pm_runtime_get_sync(dev);
    210
    211		mutex_lock(&adc->lock);
    212		reinit_completion(&adc->completion);
    213
    214		imx8qxp_adc_reg_config(adc, chan->channel);
    215
    216		imx8qxp_adc_fifo_config(adc);
    217
    218		/* adc enable */
    219		ctrl = readl(adc->regs + IMX8QXP_ADR_ADC_CTRL);
    220		ctrl |= FIELD_PREP(IMX8QXP_ADC_CTRL_ADC_EN_MASK, 1);
    221		writel(ctrl, adc->regs + IMX8QXP_ADR_ADC_CTRL);
    222		/* adc start */
    223		writel(1, adc->regs + IMX8QXP_ADR_ADC_SWTRIG);
    224
    225		ret = wait_for_completion_interruptible_timeout(&adc->completion,
    226								IMX8QXP_ADC_TIMEOUT);
    227
    228		pm_runtime_mark_last_busy(dev);
    229		pm_runtime_put_sync_autosuspend(dev);
    230
    231		if (ret == 0) {
    232			mutex_unlock(&adc->lock);
    233			return -ETIMEDOUT;
    234		}
    235		if (ret < 0) {
    236			mutex_unlock(&adc->lock);
    237			return ret;
    238		}
    239
    240		*val = FIELD_GET(IMX8QXP_ADC_RESFIFO_VAL_MASK,
    241				 readl(adc->regs + IMX8QXP_ADR_ADC_RESFIFO));
    242
    243		mutex_unlock(&adc->lock);
    244		return IIO_VAL_INT;
    245
    246	case IIO_CHAN_INFO_SCALE:
    247		vref_uv = regulator_get_voltage(adc->vref);
    248		*val = vref_uv / 1000;
    249		*val2 = 12;
    250		return IIO_VAL_FRACTIONAL_LOG2;
    251
    252	case IIO_CHAN_INFO_SAMP_FREQ:
    253		*val = clk_get_rate(adc->clk) / 3;
    254		return IIO_VAL_INT;
    255
    256	default:
    257		return -EINVAL;
    258	}
    259}
    260
    261static irqreturn_t imx8qxp_adc_isr(int irq, void *dev_id)
    262{
    263	struct imx8qxp_adc *adc = dev_id;
    264	u32 fifo_count;
    265
    266	fifo_count = FIELD_GET(IMX8QXP_ADC_FCTRL_FCOUNT_MASK,
    267			       readl(adc->regs + IMX8QXP_ADR_ADC_FCTRL));
    268
    269	if (fifo_count)
    270		complete(&adc->completion);
    271
    272	return IRQ_HANDLED;
    273}
    274
    275static int imx8qxp_adc_reg_access(struct iio_dev *indio_dev, unsigned int reg,
    276				  unsigned int writeval, unsigned int *readval)
    277{
    278	struct imx8qxp_adc *adc = iio_priv(indio_dev);
    279	struct device *dev = adc->dev;
    280
    281	if (!readval || reg % 4 || reg > IMX8QXP_ADR_ADC_TST)
    282		return -EINVAL;
    283
    284	pm_runtime_get_sync(dev);
    285
    286	*readval = readl(adc->regs + reg);
    287
    288	pm_runtime_mark_last_busy(dev);
    289	pm_runtime_put_sync_autosuspend(dev);
    290
    291	return 0;
    292}
    293
    294static const struct iio_info imx8qxp_adc_iio_info = {
    295	.read_raw = &imx8qxp_adc_read_raw,
    296	.debugfs_reg_access = &imx8qxp_adc_reg_access,
    297};
    298
    299static int imx8qxp_adc_probe(struct platform_device *pdev)
    300{
    301	struct imx8qxp_adc *adc;
    302	struct iio_dev *indio_dev;
    303	struct device *dev = &pdev->dev;
    304	int irq;
    305	int ret;
    306
    307	indio_dev = devm_iio_device_alloc(dev, sizeof(*adc));
    308	if (!indio_dev) {
    309		dev_err(dev, "Failed allocating iio device\n");
    310		return -ENOMEM;
    311	}
    312
    313	adc = iio_priv(indio_dev);
    314	adc->dev = dev;
    315
    316	mutex_init(&adc->lock);
    317	adc->regs = devm_platform_ioremap_resource(pdev, 0);
    318	if (IS_ERR(adc->regs))
    319		return PTR_ERR(adc->regs);
    320
    321	irq = platform_get_irq(pdev, 0);
    322	if (irq < 0)
    323		return irq;
    324
    325	adc->clk = devm_clk_get(dev, "per");
    326	if (IS_ERR(adc->clk))
    327		return dev_err_probe(dev, PTR_ERR(adc->clk), "Failed getting clock\n");
    328
    329	adc->ipg_clk = devm_clk_get(dev, "ipg");
    330	if (IS_ERR(adc->ipg_clk))
    331		return dev_err_probe(dev, PTR_ERR(adc->ipg_clk), "Failed getting clock\n");
    332
    333	adc->vref = devm_regulator_get(dev, "vref");
    334	if (IS_ERR(adc->vref))
    335		return dev_err_probe(dev, PTR_ERR(adc->vref), "Failed getting reference voltage\n");
    336
    337	ret = regulator_enable(adc->vref);
    338	if (ret) {
    339		dev_err(dev, "Can't enable adc reference top voltage\n");
    340		return ret;
    341	}
    342
    343	platform_set_drvdata(pdev, indio_dev);
    344
    345	init_completion(&adc->completion);
    346
    347	indio_dev->name = ADC_DRIVER_NAME;
    348	indio_dev->info = &imx8qxp_adc_iio_info;
    349	indio_dev->modes = INDIO_DIRECT_MODE;
    350	indio_dev->channels = imx8qxp_adc_iio_channels;
    351	indio_dev->num_channels = ARRAY_SIZE(imx8qxp_adc_iio_channels);
    352
    353	ret = clk_prepare_enable(adc->clk);
    354	if (ret) {
    355		dev_err(&pdev->dev, "Could not prepare or enable the clock.\n");
    356		goto error_regulator_disable;
    357	}
    358
    359	ret = clk_prepare_enable(adc->ipg_clk);
    360	if (ret) {
    361		dev_err(&pdev->dev, "Could not prepare or enable the clock.\n");
    362		goto error_adc_clk_disable;
    363	}
    364
    365	ret = devm_request_irq(dev, irq, imx8qxp_adc_isr, 0, ADC_DRIVER_NAME, adc);
    366	if (ret < 0) {
    367		dev_err(dev, "Failed requesting irq, irq = %d\n", irq);
    368		goto error_ipg_clk_disable;
    369	}
    370
    371	imx8qxp_adc_reset(adc);
    372
    373	ret = iio_device_register(indio_dev);
    374	if (ret) {
    375		imx8qxp_adc_disable(adc);
    376		dev_err(dev, "Couldn't register the device.\n");
    377		goto error_ipg_clk_disable;
    378	}
    379
    380	pm_runtime_set_active(dev);
    381	pm_runtime_set_autosuspend_delay(dev, 50);
    382	pm_runtime_use_autosuspend(dev);
    383	pm_runtime_enable(dev);
    384
    385	return 0;
    386
    387error_ipg_clk_disable:
    388	clk_disable_unprepare(adc->ipg_clk);
    389error_adc_clk_disable:
    390	clk_disable_unprepare(adc->clk);
    391error_regulator_disable:
    392	regulator_disable(adc->vref);
    393
    394	return ret;
    395}
    396
    397static int imx8qxp_adc_remove(struct platform_device *pdev)
    398{
    399	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
    400	struct imx8qxp_adc *adc = iio_priv(indio_dev);
    401	struct device *dev = adc->dev;
    402
    403	pm_runtime_get_sync(dev);
    404
    405	iio_device_unregister(indio_dev);
    406
    407	imx8qxp_adc_disable(adc);
    408
    409	clk_disable_unprepare(adc->clk);
    410	clk_disable_unprepare(adc->ipg_clk);
    411	regulator_disable(adc->vref);
    412
    413	pm_runtime_disable(dev);
    414	pm_runtime_put_noidle(dev);
    415
    416	return 0;
    417}
    418
    419static __maybe_unused int imx8qxp_adc_runtime_suspend(struct device *dev)
    420{
    421	struct iio_dev *indio_dev = dev_get_drvdata(dev);
    422	struct imx8qxp_adc *adc = iio_priv(indio_dev);
    423
    424	imx8qxp_adc_disable(adc);
    425
    426	clk_disable_unprepare(adc->clk);
    427	clk_disable_unprepare(adc->ipg_clk);
    428	regulator_disable(adc->vref);
    429
    430	return 0;
    431}
    432
    433static __maybe_unused int imx8qxp_adc_runtime_resume(struct device *dev)
    434{
    435	struct iio_dev *indio_dev = dev_get_drvdata(dev);
    436	struct imx8qxp_adc *adc = iio_priv(indio_dev);
    437	int ret;
    438
    439	ret = regulator_enable(adc->vref);
    440	if (ret) {
    441		dev_err(dev, "Can't enable adc reference top voltage, err = %d\n", ret);
    442		return ret;
    443	}
    444
    445	ret = clk_prepare_enable(adc->clk);
    446	if (ret) {
    447		dev_err(dev, "Could not prepare or enable clock.\n");
    448		goto err_disable_reg;
    449	}
    450
    451	ret = clk_prepare_enable(adc->ipg_clk);
    452	if (ret) {
    453		dev_err(dev, "Could not prepare or enable clock.\n");
    454		goto err_unprepare_clk;
    455	}
    456
    457	imx8qxp_adc_reset(adc);
    458
    459	return 0;
    460
    461err_unprepare_clk:
    462	clk_disable_unprepare(adc->clk);
    463
    464err_disable_reg:
    465	regulator_disable(adc->vref);
    466
    467	return ret;
    468}
    469
    470static const struct dev_pm_ops imx8qxp_adc_pm_ops = {
    471	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
    472	SET_RUNTIME_PM_OPS(imx8qxp_adc_runtime_suspend, imx8qxp_adc_runtime_resume, NULL)
    473};
    474
    475static const struct of_device_id imx8qxp_adc_match[] = {
    476	{ .compatible = "nxp,imx8qxp-adc", },
    477	{ /* sentinel */ }
    478};
    479MODULE_DEVICE_TABLE(of, imx8qxp_adc_match);
    480
    481static struct platform_driver imx8qxp_adc_driver = {
    482	.probe		= imx8qxp_adc_probe,
    483	.remove		= imx8qxp_adc_remove,
    484	.driver		= {
    485		.name	= ADC_DRIVER_NAME,
    486		.of_match_table = imx8qxp_adc_match,
    487		.pm	= &imx8qxp_adc_pm_ops,
    488	},
    489};
    490
    491module_platform_driver(imx8qxp_adc_driver);
    492
    493MODULE_DESCRIPTION("i.MX8QuadXPlus ADC driver");
    494MODULE_LICENSE("GPL v2");