xref: /openbmc/linux/drivers/iio/adc/stmpe-adc.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
19f3d0849SStefan Agner // SPDX-License-Identifier: GPL-2.0
29f3d0849SStefan Agner /*
39f3d0849SStefan Agner  *  STMicroelectronics STMPE811 IIO ADC Driver
49f3d0849SStefan Agner  *
59f3d0849SStefan Agner  *  4 channel, 10/12-bit ADC
69f3d0849SStefan Agner  *
79f3d0849SStefan Agner  *  Copyright (C) 2013-2018 Toradex AG <stefan.agner@toradex.com>
89f3d0849SStefan Agner  */
99f3d0849SStefan Agner 
109f3d0849SStefan Agner #include <linux/completion.h>
119f3d0849SStefan Agner #include <linux/err.h>
129f3d0849SStefan Agner #include <linux/iio/iio.h>
139f3d0849SStefan Agner #include <linux/interrupt.h>
149f3d0849SStefan Agner #include <linux/kernel.h>
159f3d0849SStefan Agner #include <linux/mfd/stmpe.h>
169f3d0849SStefan Agner #include <linux/module.h>
17*1240c94cSRob Herring #include <linux/of.h>
189f3d0849SStefan Agner #include <linux/platform_device.h>
199f3d0849SStefan Agner #include <linux/device.h>
209f3d0849SStefan Agner 
219f3d0849SStefan Agner #define STMPE_REG_INT_STA		0x0B
229f3d0849SStefan Agner #define STMPE_REG_ADC_INT_EN		0x0E
239f3d0849SStefan Agner #define STMPE_REG_ADC_INT_STA		0x0F
249f3d0849SStefan Agner 
259f3d0849SStefan Agner #define STMPE_REG_ADC_CTRL1		0x20
269f3d0849SStefan Agner #define STMPE_REG_ADC_CTRL2		0x21
279f3d0849SStefan Agner #define STMPE_REG_ADC_CAPT		0x22
289f3d0849SStefan Agner #define STMPE_REG_ADC_DATA_CH(channel)	(0x30 + 2 * (channel))
299f3d0849SStefan Agner 
309f3d0849SStefan Agner #define STMPE_REG_TEMP_CTRL		0x60
319f3d0849SStefan Agner #define STMPE_TEMP_CTRL_ENABLE		BIT(0)
329f3d0849SStefan Agner #define STMPE_TEMP_CTRL_ACQ		BIT(1)
339f3d0849SStefan Agner #define STMPE_TEMP_CTRL_THRES_EN	BIT(3)
349f3d0849SStefan Agner #define STMPE_START_ONE_TEMP_CONV	(STMPE_TEMP_CTRL_ENABLE | \
359f3d0849SStefan Agner 					STMPE_TEMP_CTRL_ACQ | \
369f3d0849SStefan Agner 					STMPE_TEMP_CTRL_THRES_EN)
379f3d0849SStefan Agner #define STMPE_REG_TEMP_DATA		0x61
389f3d0849SStefan Agner #define STMPE_REG_TEMP_TH		0x63
399f3d0849SStefan Agner #define STMPE_ADC_LAST_NR		7
409f3d0849SStefan Agner #define STMPE_TEMP_CHANNEL		(STMPE_ADC_LAST_NR + 1)
419f3d0849SStefan Agner 
429f3d0849SStefan Agner #define STMPE_ADC_CH(channel)		((1 << (channel)) & 0xff)
439f3d0849SStefan Agner 
449f3d0849SStefan Agner #define STMPE_ADC_TIMEOUT		msecs_to_jiffies(1000)
459f3d0849SStefan Agner 
469f3d0849SStefan Agner struct stmpe_adc {
479f3d0849SStefan Agner 	struct stmpe *stmpe;
489f3d0849SStefan Agner 	struct clk *clk;
499f3d0849SStefan Agner 	struct device *dev;
509f3d0849SStefan Agner 	struct mutex lock;
519f3d0849SStefan Agner 
529f3d0849SStefan Agner 	/* We are allocating plus one for the temperature channel */
539f3d0849SStefan Agner 	struct iio_chan_spec stmpe_adc_iio_channels[STMPE_ADC_LAST_NR + 2];
549f3d0849SStefan Agner 
559f3d0849SStefan Agner 	struct completion completion;
569f3d0849SStefan Agner 
579f3d0849SStefan Agner 	u8 channel;
589f3d0849SStefan Agner 	u32 value;
599f3d0849SStefan Agner };
609f3d0849SStefan Agner 
stmpe_read_voltage(struct stmpe_adc * info,struct iio_chan_spec const * chan,int * val)619f3d0849SStefan Agner static int stmpe_read_voltage(struct stmpe_adc *info,
629f3d0849SStefan Agner 		struct iio_chan_spec const *chan, int *val)
639f3d0849SStefan Agner {
64d345b232SMiaoqian Lin 	unsigned long ret;
659f3d0849SStefan Agner 
669f3d0849SStefan Agner 	mutex_lock(&info->lock);
679f3d0849SStefan Agner 
68263d21cdSPhilippe Schenker 	reinit_completion(&info->completion);
69263d21cdSPhilippe Schenker 
709f3d0849SStefan Agner 	info->channel = (u8)chan->channel;
719f3d0849SStefan Agner 
729f3d0849SStefan Agner 	if (info->channel > STMPE_ADC_LAST_NR) {
739f3d0849SStefan Agner 		mutex_unlock(&info->lock);
749f3d0849SStefan Agner 		return -EINVAL;
759f3d0849SStefan Agner 	}
769f3d0849SStefan Agner 
779f3d0849SStefan Agner 	stmpe_reg_write(info->stmpe, STMPE_REG_ADC_CAPT,
789f3d0849SStefan Agner 			STMPE_ADC_CH(info->channel));
799f3d0849SStefan Agner 
80e813dde6SPhilippe Schenker 	ret = wait_for_completion_timeout(&info->completion, STMPE_ADC_TIMEOUT);
819f3d0849SStefan Agner 
82d345b232SMiaoqian Lin 	if (ret == 0) {
83ed1f310eSPhilippe Schenker 		stmpe_reg_write(info->stmpe, STMPE_REG_ADC_INT_STA,
84ed1f310eSPhilippe Schenker 				STMPE_ADC_CH(info->channel));
859f3d0849SStefan Agner 		mutex_unlock(&info->lock);
869f3d0849SStefan Agner 		return -ETIMEDOUT;
879f3d0849SStefan Agner 	}
889f3d0849SStefan Agner 
899f3d0849SStefan Agner 	*val = info->value;
909f3d0849SStefan Agner 
919f3d0849SStefan Agner 	mutex_unlock(&info->lock);
929f3d0849SStefan Agner 
939f3d0849SStefan Agner 	return 0;
949f3d0849SStefan Agner }
959f3d0849SStefan Agner 
stmpe_read_temp(struct stmpe_adc * info,struct iio_chan_spec const * chan,int * val)969f3d0849SStefan Agner static int stmpe_read_temp(struct stmpe_adc *info,
979f3d0849SStefan Agner 		struct iio_chan_spec const *chan, int *val)
989f3d0849SStefan Agner {
99d345b232SMiaoqian Lin 	unsigned long ret;
1009f3d0849SStefan Agner 
1019f3d0849SStefan Agner 	mutex_lock(&info->lock);
1029f3d0849SStefan Agner 
103263d21cdSPhilippe Schenker 	reinit_completion(&info->completion);
104263d21cdSPhilippe Schenker 
1059f3d0849SStefan Agner 	info->channel = (u8)chan->channel;
1069f3d0849SStefan Agner 
1079f3d0849SStefan Agner 	if (info->channel != STMPE_TEMP_CHANNEL) {
1089f3d0849SStefan Agner 		mutex_unlock(&info->lock);
1099f3d0849SStefan Agner 		return -EINVAL;
1109f3d0849SStefan Agner 	}
1119f3d0849SStefan Agner 
1129f3d0849SStefan Agner 	stmpe_reg_write(info->stmpe, STMPE_REG_TEMP_CTRL,
1139f3d0849SStefan Agner 			STMPE_START_ONE_TEMP_CONV);
1149f3d0849SStefan Agner 
115e813dde6SPhilippe Schenker 	ret = wait_for_completion_timeout(&info->completion, STMPE_ADC_TIMEOUT);
1169f3d0849SStefan Agner 
117d345b232SMiaoqian Lin 	if (ret == 0) {
1189f3d0849SStefan Agner 		mutex_unlock(&info->lock);
1199f3d0849SStefan Agner 		return -ETIMEDOUT;
1209f3d0849SStefan Agner 	}
1219f3d0849SStefan Agner 
1229f3d0849SStefan Agner 	/*
1239f3d0849SStefan Agner 	 * absolute temp = +V3.3 * value /7.51 [K]
1249f3d0849SStefan Agner 	 * scale to [milli °C]
1259f3d0849SStefan Agner 	 */
1269f3d0849SStefan Agner 	*val = ((449960l * info->value) / 1024l) - 273150;
1279f3d0849SStefan Agner 
1289f3d0849SStefan Agner 	mutex_unlock(&info->lock);
1299f3d0849SStefan Agner 
1309f3d0849SStefan Agner 	return 0;
1319f3d0849SStefan Agner }
1329f3d0849SStefan Agner 
stmpe_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long mask)1339f3d0849SStefan Agner static int stmpe_read_raw(struct iio_dev *indio_dev,
1349f3d0849SStefan Agner 			  struct iio_chan_spec const *chan,
1359f3d0849SStefan Agner 			  int *val,
1369f3d0849SStefan Agner 			  int *val2,
1379f3d0849SStefan Agner 			  long mask)
1389f3d0849SStefan Agner {
1399f3d0849SStefan Agner 	struct stmpe_adc *info = iio_priv(indio_dev);
1409f3d0849SStefan Agner 	long ret;
1419f3d0849SStefan Agner 
1429f3d0849SStefan Agner 	switch (mask) {
1439f3d0849SStefan Agner 	case IIO_CHAN_INFO_RAW:
1449f3d0849SStefan Agner 	case IIO_CHAN_INFO_PROCESSED:
1459f3d0849SStefan Agner 
1469f3d0849SStefan Agner 		switch (chan->type) {
1479f3d0849SStefan Agner 		case IIO_VOLTAGE:
1489f3d0849SStefan Agner 			ret = stmpe_read_voltage(info, chan, val);
1499f3d0849SStefan Agner 			break;
1509f3d0849SStefan Agner 
1519f3d0849SStefan Agner 		case IIO_TEMP:
1529f3d0849SStefan Agner 			ret = stmpe_read_temp(info, chan, val);
1539f3d0849SStefan Agner 			break;
1549f3d0849SStefan Agner 		default:
1559f3d0849SStefan Agner 			return -EINVAL;
1569f3d0849SStefan Agner 		}
1579f3d0849SStefan Agner 
1589f3d0849SStefan Agner 		if (ret < 0)
1599f3d0849SStefan Agner 			return ret;
1609f3d0849SStefan Agner 
1619f3d0849SStefan Agner 		return IIO_VAL_INT;
1629f3d0849SStefan Agner 
1639f3d0849SStefan Agner 	case IIO_CHAN_INFO_SCALE:
1649f3d0849SStefan Agner 		*val = 3300;
1659f3d0849SStefan Agner 		*val2 = info->stmpe->mod_12b ? 12 : 10;
1669f3d0849SStefan Agner 		return IIO_VAL_FRACTIONAL_LOG2;
1679f3d0849SStefan Agner 
1689f3d0849SStefan Agner 	default:
1699f3d0849SStefan Agner 		break;
1709f3d0849SStefan Agner 	}
1719f3d0849SStefan Agner 
1729f3d0849SStefan Agner 	return -EINVAL;
1739f3d0849SStefan Agner }
1749f3d0849SStefan Agner 
stmpe_adc_isr(int irq,void * dev_id)1759f3d0849SStefan Agner static irqreturn_t stmpe_adc_isr(int irq, void *dev_id)
1769f3d0849SStefan Agner {
1779f3d0849SStefan Agner 	struct stmpe_adc *info = (struct stmpe_adc *)dev_id;
17847f3b26eSJonathan Cameron 	__be16 data;
1799f3d0849SStefan Agner 
1809f3d0849SStefan Agner 	if (info->channel <= STMPE_ADC_LAST_NR) {
1819f3d0849SStefan Agner 		int int_sta;
1829f3d0849SStefan Agner 
1839f3d0849SStefan Agner 		int_sta = stmpe_reg_read(info->stmpe, STMPE_REG_ADC_INT_STA);
1849f3d0849SStefan Agner 
1859f3d0849SStefan Agner 		/* Is the interrupt relevant */
1869f3d0849SStefan Agner 		if (!(int_sta & STMPE_ADC_CH(info->channel)))
1879f3d0849SStefan Agner 			return IRQ_NONE;
1889f3d0849SStefan Agner 
1899f3d0849SStefan Agner 		/* Read value */
1909f3d0849SStefan Agner 		stmpe_block_read(info->stmpe,
1919f3d0849SStefan Agner 			STMPE_REG_ADC_DATA_CH(info->channel), 2, (u8 *) &data);
1929f3d0849SStefan Agner 
1939f3d0849SStefan Agner 		stmpe_reg_write(info->stmpe, STMPE_REG_ADC_INT_STA, int_sta);
1949f3d0849SStefan Agner 	} else if (info->channel == STMPE_TEMP_CHANNEL) {
1959f3d0849SStefan Agner 		/* Read value */
1969f3d0849SStefan Agner 		stmpe_block_read(info->stmpe, STMPE_REG_TEMP_DATA, 2,
1979f3d0849SStefan Agner 				(u8 *) &data);
19817104ca2SNathan Chancellor 	} else {
19917104ca2SNathan Chancellor 		return IRQ_NONE;
2009f3d0849SStefan Agner 	}
2019f3d0849SStefan Agner 
2029f3d0849SStefan Agner 	info->value = (u32) be16_to_cpu(data);
2039f3d0849SStefan Agner 	complete(&info->completion);
2049f3d0849SStefan Agner 
2059f3d0849SStefan Agner 	return IRQ_HANDLED;
2069f3d0849SStefan Agner }
2079f3d0849SStefan Agner 
2089f3d0849SStefan Agner static const struct iio_info stmpe_adc_iio_info = {
2099f3d0849SStefan Agner 	.read_raw = &stmpe_read_raw,
2109f3d0849SStefan Agner };
2119f3d0849SStefan Agner 
stmpe_adc_voltage_chan(struct iio_chan_spec * ics,int chan)2129f3d0849SStefan Agner static void stmpe_adc_voltage_chan(struct iio_chan_spec *ics, int chan)
2139f3d0849SStefan Agner {
2149f3d0849SStefan Agner 	ics->type = IIO_VOLTAGE;
2159f3d0849SStefan Agner 	ics->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
2169f3d0849SStefan Agner 	ics->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE);
2179f3d0849SStefan Agner 	ics->indexed = 1;
2189f3d0849SStefan Agner 	ics->channel = chan;
2199f3d0849SStefan Agner }
2209f3d0849SStefan Agner 
stmpe_adc_temp_chan(struct iio_chan_spec * ics,int chan)2219f3d0849SStefan Agner static void stmpe_adc_temp_chan(struct iio_chan_spec *ics, int chan)
2229f3d0849SStefan Agner {
2239f3d0849SStefan Agner 	ics->type = IIO_TEMP;
2249f3d0849SStefan Agner 	ics->info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED);
2259f3d0849SStefan Agner 	ics->indexed = 1;
2269f3d0849SStefan Agner 	ics->channel = chan;
2279f3d0849SStefan Agner }
2289f3d0849SStefan Agner 
stmpe_adc_init_hw(struct stmpe_adc * adc)2299f3d0849SStefan Agner static int stmpe_adc_init_hw(struct stmpe_adc *adc)
2309f3d0849SStefan Agner {
2319f3d0849SStefan Agner 	int ret;
2329f3d0849SStefan Agner 	struct stmpe *stmpe = adc->stmpe;
2339f3d0849SStefan Agner 
2349f3d0849SStefan Agner 	ret = stmpe_enable(stmpe, STMPE_BLOCK_ADC);
2359f3d0849SStefan Agner 	if (ret) {
2369f3d0849SStefan Agner 		dev_err(stmpe->dev, "Could not enable clock for ADC\n");
2379f3d0849SStefan Agner 		return ret;
2389f3d0849SStefan Agner 	}
2399f3d0849SStefan Agner 
2409f3d0849SStefan Agner 	ret = stmpe811_adc_common_init(stmpe);
2419f3d0849SStefan Agner 	if (ret) {
2429f3d0849SStefan Agner 		stmpe_disable(stmpe, STMPE_BLOCK_ADC);
2439f3d0849SStefan Agner 		return ret;
2449f3d0849SStefan Agner 	}
2459f3d0849SStefan Agner 
2469f3d0849SStefan Agner 	/* use temp irq for each conversion completion */
2479f3d0849SStefan Agner 	stmpe_reg_write(stmpe, STMPE_REG_TEMP_TH, 0);
2489f3d0849SStefan Agner 	stmpe_reg_write(stmpe, STMPE_REG_TEMP_TH + 1, 0);
2499f3d0849SStefan Agner 
2509f3d0849SStefan Agner 	return 0;
2519f3d0849SStefan Agner }
2529f3d0849SStefan Agner 
stmpe_adc_probe(struct platform_device * pdev)2539f3d0849SStefan Agner static int stmpe_adc_probe(struct platform_device *pdev)
2549f3d0849SStefan Agner {
2559f3d0849SStefan Agner 	struct iio_dev *indio_dev;
2569f3d0849SStefan Agner 	struct stmpe_adc *info;
2579f3d0849SStefan Agner 	struct device_node *np;
2589f3d0849SStefan Agner 	u32 norequest_mask = 0;
2593511989cSKees Cook 	unsigned long bits;
2609f3d0849SStefan Agner 	int irq_temp, irq_adc;
2619f3d0849SStefan Agner 	int num_chan = 0;
2629f3d0849SStefan Agner 	int i = 0;
2639f3d0849SStefan Agner 	int ret;
2649f3d0849SStefan Agner 
2659f3d0849SStefan Agner 	irq_adc = platform_get_irq_byname(pdev, "STMPE_ADC");
2669f3d0849SStefan Agner 	if (irq_adc < 0)
2679f3d0849SStefan Agner 		return irq_adc;
2689f3d0849SStefan Agner 
2699f3d0849SStefan Agner 	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(struct stmpe_adc));
2709f3d0849SStefan Agner 	if (!indio_dev) {
2719f3d0849SStefan Agner 		dev_err(&pdev->dev, "failed allocating iio device\n");
2729f3d0849SStefan Agner 		return -ENOMEM;
2739f3d0849SStefan Agner 	}
2749f3d0849SStefan Agner 
2759f3d0849SStefan Agner 	info = iio_priv(indio_dev);
2769f3d0849SStefan Agner 	mutex_init(&info->lock);
2779f3d0849SStefan Agner 
2789f3d0849SStefan Agner 	init_completion(&info->completion);
2799f3d0849SStefan Agner 	ret = devm_request_threaded_irq(&pdev->dev, irq_adc, NULL,
2809f3d0849SStefan Agner 					stmpe_adc_isr, IRQF_ONESHOT,
2819f3d0849SStefan Agner 					"stmpe-adc", info);
2829f3d0849SStefan Agner 	if (ret < 0) {
2839f3d0849SStefan Agner 		dev_err(&pdev->dev, "failed requesting irq, irq = %d\n",
2849f3d0849SStefan Agner 				irq_adc);
2859f3d0849SStefan Agner 		return ret;
2869f3d0849SStefan Agner 	}
2879f3d0849SStefan Agner 
2889f3d0849SStefan Agner 	irq_temp = platform_get_irq_byname(pdev, "STMPE_TEMP_SENS");
2899f3d0849SStefan Agner 	if (irq_temp >= 0) {
2909f3d0849SStefan Agner 		ret = devm_request_threaded_irq(&pdev->dev, irq_temp, NULL,
2919f3d0849SStefan Agner 						stmpe_adc_isr, IRQF_ONESHOT,
2929f3d0849SStefan Agner 						"stmpe-adc", info);
2939f3d0849SStefan Agner 		if (ret < 0)
2949f3d0849SStefan Agner 			dev_warn(&pdev->dev, "failed requesting irq for"
2959f3d0849SStefan Agner 				 " temp sensor, irq = %d\n", irq_temp);
2969f3d0849SStefan Agner 	}
2979f3d0849SStefan Agner 
2989f3d0849SStefan Agner 	platform_set_drvdata(pdev, indio_dev);
2999f3d0849SStefan Agner 
3009f3d0849SStefan Agner 	indio_dev->name		= dev_name(&pdev->dev);
3019f3d0849SStefan Agner 	indio_dev->info		= &stmpe_adc_iio_info;
3029f3d0849SStefan Agner 	indio_dev->modes	= INDIO_DIRECT_MODE;
3039f3d0849SStefan Agner 
3049f3d0849SStefan Agner 	info->stmpe = dev_get_drvdata(pdev->dev.parent);
3059f3d0849SStefan Agner 
3069f3d0849SStefan Agner 	np = pdev->dev.of_node;
3079f3d0849SStefan Agner 
3089f3d0849SStefan Agner 	if (!np)
3099f3d0849SStefan Agner 		dev_err(&pdev->dev, "no device tree node found\n");
3109f3d0849SStefan Agner 
3119f3d0849SStefan Agner 	of_property_read_u32(np, "st,norequest-mask", &norequest_mask);
3129f3d0849SStefan Agner 
3133511989cSKees Cook 	bits = norequest_mask;
3143511989cSKees Cook 	for_each_clear_bit(i, &bits, (STMPE_ADC_LAST_NR + 1)) {
3159f3d0849SStefan Agner 		stmpe_adc_voltage_chan(&info->stmpe_adc_iio_channels[num_chan], i);
3169f3d0849SStefan Agner 		num_chan++;
3179f3d0849SStefan Agner 	}
3189f3d0849SStefan Agner 	stmpe_adc_temp_chan(&info->stmpe_adc_iio_channels[num_chan], i);
3199f3d0849SStefan Agner 	num_chan++;
3209f3d0849SStefan Agner 	indio_dev->channels = info->stmpe_adc_iio_channels;
3219f3d0849SStefan Agner 	indio_dev->num_channels = num_chan;
3229f3d0849SStefan Agner 
3239f3d0849SStefan Agner 	ret = stmpe_adc_init_hw(info);
3249f3d0849SStefan Agner 	if (ret)
3259f3d0849SStefan Agner 		return ret;
3269f3d0849SStefan Agner 
3274bd44bb2SPhilippe Schenker 	stmpe_reg_write(info->stmpe, STMPE_REG_ADC_INT_EN,
3284bd44bb2SPhilippe Schenker 			~(norequest_mask & 0xFF));
3294bd44bb2SPhilippe Schenker 
330ed1f310eSPhilippe Schenker 	stmpe_reg_write(info->stmpe, STMPE_REG_ADC_INT_STA,
331ed1f310eSPhilippe Schenker 			~(norequest_mask & 0xFF));
332ed1f310eSPhilippe Schenker 
3339f3d0849SStefan Agner 	return devm_iio_device_register(&pdev->dev, indio_dev);
3349f3d0849SStefan Agner }
3359f3d0849SStefan Agner 
stmpe_adc_resume(struct device * dev)3360b1e58e9SJonathan Cameron static int stmpe_adc_resume(struct device *dev)
3379f3d0849SStefan Agner {
3389f3d0849SStefan Agner 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
3399f3d0849SStefan Agner 	struct stmpe_adc *info = iio_priv(indio_dev);
3409f3d0849SStefan Agner 
3419f3d0849SStefan Agner 	stmpe_adc_init_hw(info);
3429f3d0849SStefan Agner 
3439f3d0849SStefan Agner 	return 0;
3449f3d0849SStefan Agner }
3459f3d0849SStefan Agner 
3460b1e58e9SJonathan Cameron static DEFINE_SIMPLE_DEV_PM_OPS(stmpe_adc_pm_ops, NULL, stmpe_adc_resume);
3479f3d0849SStefan Agner 
3482abd2937SPhilippe Schenker static const struct of_device_id stmpe_adc_ids[] = {
3492abd2937SPhilippe Schenker 	{ .compatible = "st,stmpe-adc", },
3502abd2937SPhilippe Schenker 	{ },
3512abd2937SPhilippe Schenker };
3522abd2937SPhilippe Schenker MODULE_DEVICE_TABLE(of, stmpe_adc_ids);
3532abd2937SPhilippe Schenker 
354046dab28SKrzysztof Kozlowski static struct platform_driver stmpe_adc_driver = {
355046dab28SKrzysztof Kozlowski 	.probe		= stmpe_adc_probe,
356046dab28SKrzysztof Kozlowski 	.driver		= {
357046dab28SKrzysztof Kozlowski 		.name	= "stmpe-adc",
3580b1e58e9SJonathan Cameron 		.pm	= pm_sleep_ptr(&stmpe_adc_pm_ops),
359046dab28SKrzysztof Kozlowski 		.of_match_table = stmpe_adc_ids,
360046dab28SKrzysztof Kozlowski 	},
361046dab28SKrzysztof Kozlowski };
362046dab28SKrzysztof Kozlowski module_platform_driver(stmpe_adc_driver);
363046dab28SKrzysztof Kozlowski 
3649f3d0849SStefan Agner MODULE_AUTHOR("Stefan Agner <stefan.agner@toradex.com>");
3659f3d0849SStefan Agner MODULE_DESCRIPTION("STMPEXXX ADC driver");
3669f3d0849SStefan Agner MODULE_LICENSE("GPL v2");
3679f3d0849SStefan Agner MODULE_ALIAS("platform:stmpe-adc");
368