brintos

brintos / linux-shallow public Read only

0
0
Text · 18.9 KiB · 100ecce Raw
712 lines · c
1// SPDX-License-Identifier: GPL-2.02/* ADC driver for sunxi platforms' (A10, A13 and A31) GPADC3 *4 * Copyright (c) 2016 Quentin Schulz <quentin.schulz@free-electrons.com>5 *6 * The Allwinner SoCs all have an ADC that can also act as a touchscreen7 * controller and a thermal sensor.8 * The thermal sensor works only when the ADC acts as a touchscreen controller9 * and is configured to throw an interrupt every fixed periods of time (let say10 * every X seconds).11 * One would be tempted to disable the IP on the hardware side rather than12 * disabling interrupts to save some power but that resets the internal clock of13 * the IP, resulting in having to wait X seconds every time we want to read the14 * value of the thermal sensor.15 * This is also the reason of using autosuspend in pm_runtime. If there was no16 * autosuspend, the thermal sensor would need X seconds after every17 * pm_runtime_get_sync to get a value from the ADC. The autosuspend allows the18 * thermal sensor to be requested again in a certain time span before it gets19 * shutdown for not being used.20 */21 22#include <linux/completion.h>23#include <linux/interrupt.h>24#include <linux/io.h>25#include <linux/module.h>26#include <linux/of.h>27#include <linux/platform_device.h>28#include <linux/pm_runtime.h>29#include <linux/regmap.h>30#include <linux/thermal.h>31#include <linux/delay.h>32 33#include <linux/iio/iio.h>34#include <linux/iio/driver.h>35#include <linux/iio/machine.h>36#include <linux/mfd/sun4i-gpadc.h>37 38static unsigned int sun4i_gpadc_chan_select(unsigned int chan)39{40	return SUN4I_GPADC_CTRL1_ADC_CHAN_SELECT(chan);41}42 43static unsigned int sun6i_gpadc_chan_select(unsigned int chan)44{45	return SUN6I_GPADC_CTRL1_ADC_CHAN_SELECT(chan);46}47 48struct gpadc_data {49	int		temp_offset;50	int		temp_scale;51	unsigned int	tp_mode_en;52	unsigned int	tp_adc_select;53	unsigned int	(*adc_chan_select)(unsigned int chan);54	unsigned int	adc_chan_mask;55};56 57static const struct gpadc_data sun4i_gpadc_data = {58	.temp_offset = -1932,59	.temp_scale = 133,60	.tp_mode_en = SUN4I_GPADC_CTRL1_TP_MODE_EN,61	.tp_adc_select = SUN4I_GPADC_CTRL1_TP_ADC_SELECT,62	.adc_chan_select = &sun4i_gpadc_chan_select,63	.adc_chan_mask = SUN4I_GPADC_CTRL1_ADC_CHAN_MASK,64};65 66static const struct gpadc_data sun5i_gpadc_data = {67	.temp_offset = -1447,68	.temp_scale = 100,69	.tp_mode_en = SUN4I_GPADC_CTRL1_TP_MODE_EN,70	.tp_adc_select = SUN4I_GPADC_CTRL1_TP_ADC_SELECT,71	.adc_chan_select = &sun4i_gpadc_chan_select,72	.adc_chan_mask = SUN4I_GPADC_CTRL1_ADC_CHAN_MASK,73};74 75static const struct gpadc_data sun6i_gpadc_data = {76	.temp_offset = -1623,77	.temp_scale = 167,78	.tp_mode_en = SUN6I_GPADC_CTRL1_TP_MODE_EN,79	.tp_adc_select = SUN6I_GPADC_CTRL1_TP_ADC_SELECT,80	.adc_chan_select = &sun6i_gpadc_chan_select,81	.adc_chan_mask = SUN6I_GPADC_CTRL1_ADC_CHAN_MASK,82};83 84static const struct gpadc_data sun8i_a33_gpadc_data = {85	.temp_offset = -1662,86	.temp_scale = 162,87	.tp_mode_en = SUN8I_GPADC_CTRL1_CHOP_TEMP_EN,88};89 90struct sun4i_gpadc_iio {91	struct iio_dev			*indio_dev;92	struct completion		completion;93	int				temp_data;94	u32				adc_data;95	struct regmap			*regmap;96	unsigned int			fifo_data_irq;97	atomic_t			ignore_fifo_data_irq;98	unsigned int			temp_data_irq;99	atomic_t			ignore_temp_data_irq;100	const struct gpadc_data		*data;101	bool				no_irq;102	/* prevents concurrent reads of temperature and ADC */103	struct mutex			mutex;104	struct thermal_zone_device	*tzd;105	struct device			*sensor_device;106};107 108#define SUN4I_GPADC_ADC_CHANNEL(_channel, _name) {		\109	.type = IIO_VOLTAGE,					\110	.indexed = 1,						\111	.channel = _channel,					\112	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\113	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\114	.datasheet_name = _name,				\115}116 117static struct iio_map sun4i_gpadc_hwmon_maps[] = {118	{119		.adc_channel_label = "temp_adc",120		.consumer_dev_name = "iio_hwmon.0",121	},122	{ /* sentinel */ },123};124 125static const struct iio_chan_spec sun4i_gpadc_channels[] = {126	SUN4I_GPADC_ADC_CHANNEL(0, "adc_chan0"),127	SUN4I_GPADC_ADC_CHANNEL(1, "adc_chan1"),128	SUN4I_GPADC_ADC_CHANNEL(2, "adc_chan2"),129	SUN4I_GPADC_ADC_CHANNEL(3, "adc_chan3"),130	{131		.type = IIO_TEMP,132		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |133				      BIT(IIO_CHAN_INFO_SCALE) |134				      BIT(IIO_CHAN_INFO_OFFSET),135		.datasheet_name = "temp_adc",136	},137};138 139static const struct iio_chan_spec sun4i_gpadc_channels_no_temp[] = {140	SUN4I_GPADC_ADC_CHANNEL(0, "adc_chan0"),141	SUN4I_GPADC_ADC_CHANNEL(1, "adc_chan1"),142	SUN4I_GPADC_ADC_CHANNEL(2, "adc_chan2"),143	SUN4I_GPADC_ADC_CHANNEL(3, "adc_chan3"),144};145 146static const struct iio_chan_spec sun8i_a33_gpadc_channels[] = {147	{148		.type = IIO_TEMP,149		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |150				      BIT(IIO_CHAN_INFO_SCALE) |151				      BIT(IIO_CHAN_INFO_OFFSET),152		.datasheet_name = "temp_adc",153	},154};155 156static const struct regmap_config sun4i_gpadc_regmap_config = {157	.reg_bits = 32,158	.val_bits = 32,159	.reg_stride = 4,160	.fast_io = true,161};162 163static int sun4i_prepare_for_irq(struct iio_dev *indio_dev, int channel,164				 unsigned int irq)165{166	struct sun4i_gpadc_iio *info = iio_priv(indio_dev);167	int ret;168	u32 reg;169 170	pm_runtime_get_sync(indio_dev->dev.parent);171 172	reinit_completion(&info->completion);173 174	ret = regmap_write(info->regmap, SUN4I_GPADC_INT_FIFOC,175			   SUN4I_GPADC_INT_FIFOC_TP_FIFO_TRIG_LEVEL(1) |176			   SUN4I_GPADC_INT_FIFOC_TP_FIFO_FLUSH);177	if (ret)178		return ret;179 180	ret = regmap_read(info->regmap, SUN4I_GPADC_CTRL1, &reg);181	if (ret)182		return ret;183 184	if (irq == info->fifo_data_irq) {185		ret = regmap_write(info->regmap, SUN4I_GPADC_CTRL1,186				   info->data->tp_mode_en |187				   info->data->tp_adc_select |188				   info->data->adc_chan_select(channel));189		/*190		 * When the IP changes channel, it needs a bit of time to get191		 * correct values.192		 */193		if ((reg & info->data->adc_chan_mask) !=194			 info->data->adc_chan_select(channel))195			mdelay(10);196 197	} else {198		/*199		 * The temperature sensor returns valid data only when the ADC200		 * operates in touchscreen mode.201		 */202		ret = regmap_write(info->regmap, SUN4I_GPADC_CTRL1,203				   info->data->tp_mode_en);204	}205 206	if (ret)207		return ret;208 209	/*210	 * When the IP changes mode between ADC or touchscreen, it211	 * needs a bit of time to get correct values.212	 */213	if ((reg & info->data->tp_adc_select) != info->data->tp_adc_select)214		mdelay(100);215 216	return 0;217}218 219static int sun4i_gpadc_read(struct iio_dev *indio_dev, int channel, int *val,220			    unsigned int irq)221{222	struct sun4i_gpadc_iio *info = iio_priv(indio_dev);223	int ret;224 225	mutex_lock(&info->mutex);226 227	ret = sun4i_prepare_for_irq(indio_dev, channel, irq);228	if (ret)229		goto err;230 231	enable_irq(irq);232 233	/*234	 * The temperature sensor throws an interruption periodically (currently235	 * set at periods of ~0.6s in sun4i_gpadc_runtime_resume). A 1s delay236	 * makes sure an interruption occurs in normal conditions. If it doesn't237	 * occur, then there is a timeout.238	 */239	if (!wait_for_completion_timeout(&info->completion,240					 msecs_to_jiffies(1000))) {241		ret = -ETIMEDOUT;242		goto err;243	}244 245	if (irq == info->fifo_data_irq)246		*val = info->adc_data;247	else248		*val = info->temp_data;249 250	ret = 0;251	pm_runtime_mark_last_busy(indio_dev->dev.parent);252 253err:254	pm_runtime_put_autosuspend(indio_dev->dev.parent);255	disable_irq(irq);256	mutex_unlock(&info->mutex);257 258	return ret;259}260 261static int sun4i_gpadc_adc_read(struct iio_dev *indio_dev, int channel,262				int *val)263{264	struct sun4i_gpadc_iio *info = iio_priv(indio_dev);265 266	return sun4i_gpadc_read(indio_dev, channel, val, info->fifo_data_irq);267}268 269static int sun4i_gpadc_temp_read(struct iio_dev *indio_dev, int *val)270{271	struct sun4i_gpadc_iio *info = iio_priv(indio_dev);272 273	if (info->no_irq) {274		pm_runtime_get_sync(indio_dev->dev.parent);275 276		regmap_read(info->regmap, SUN4I_GPADC_TEMP_DATA, val);277 278		pm_runtime_mark_last_busy(indio_dev->dev.parent);279		pm_runtime_put_autosuspend(indio_dev->dev.parent);280 281		return 0;282	}283 284	return sun4i_gpadc_read(indio_dev, 0, val, info->temp_data_irq);285}286 287static int sun4i_gpadc_temp_offset(struct iio_dev *indio_dev, int *val)288{289	struct sun4i_gpadc_iio *info = iio_priv(indio_dev);290 291	*val = info->data->temp_offset;292 293	return 0;294}295 296static int sun4i_gpadc_temp_scale(struct iio_dev *indio_dev, int *val)297{298	struct sun4i_gpadc_iio *info = iio_priv(indio_dev);299 300	*val = info->data->temp_scale;301 302	return 0;303}304 305static int sun4i_gpadc_read_raw(struct iio_dev *indio_dev,306				struct iio_chan_spec const *chan, int *val,307				int *val2, long mask)308{309	int ret;310 311	switch (mask) {312	case IIO_CHAN_INFO_OFFSET:313		ret = sun4i_gpadc_temp_offset(indio_dev, val);314		if (ret)315			return ret;316 317		return IIO_VAL_INT;318	case IIO_CHAN_INFO_RAW:319		if (chan->type == IIO_VOLTAGE)320			ret = sun4i_gpadc_adc_read(indio_dev, chan->channel,321						   val);322		else323			ret = sun4i_gpadc_temp_read(indio_dev, val);324 325		if (ret)326			return ret;327 328		return IIO_VAL_INT;329	case IIO_CHAN_INFO_SCALE:330		if (chan->type == IIO_VOLTAGE) {331			/* 3000mV / 4096 * raw */332			*val = 0;333			*val2 = 732421875;334			return IIO_VAL_INT_PLUS_NANO;335		}336 337		ret = sun4i_gpadc_temp_scale(indio_dev, val);338		if (ret)339			return ret;340 341		return IIO_VAL_INT;342	default:343		return -EINVAL;344	}345 346	return -EINVAL;347}348 349static const struct iio_info sun4i_gpadc_iio_info = {350	.read_raw = sun4i_gpadc_read_raw,351};352 353static irqreturn_t sun4i_gpadc_temp_data_irq_handler(int irq, void *dev_id)354{355	struct sun4i_gpadc_iio *info = dev_id;356 357	if (atomic_read(&info->ignore_temp_data_irq))358		goto out;359 360	if (!regmap_read(info->regmap, SUN4I_GPADC_TEMP_DATA, &info->temp_data))361		complete(&info->completion);362 363out:364	return IRQ_HANDLED;365}366 367static irqreturn_t sun4i_gpadc_fifo_data_irq_handler(int irq, void *dev_id)368{369	struct sun4i_gpadc_iio *info = dev_id;370 371	if (atomic_read(&info->ignore_fifo_data_irq))372		goto out;373 374	if (!regmap_read(info->regmap, SUN4I_GPADC_DATA, &info->adc_data))375		complete(&info->completion);376 377out:378	return IRQ_HANDLED;379}380 381static int sun4i_gpadc_runtime_suspend(struct device *dev)382{383	struct sun4i_gpadc_iio *info = iio_priv(dev_get_drvdata(dev));384 385	/* Disable the ADC on IP */386	regmap_write(info->regmap, SUN4I_GPADC_CTRL1, 0);387	/* Disable temperature sensor on IP */388	regmap_write(info->regmap, SUN4I_GPADC_TPR, 0);389 390	return 0;391}392 393static int sun4i_gpadc_runtime_resume(struct device *dev)394{395	struct sun4i_gpadc_iio *info = iio_priv(dev_get_drvdata(dev));396 397	/* clkin = 6MHz */398	regmap_write(info->regmap, SUN4I_GPADC_CTRL0,399		     SUN4I_GPADC_CTRL0_ADC_CLK_DIVIDER(2) |400		     SUN4I_GPADC_CTRL0_FS_DIV(7) |401		     SUN4I_GPADC_CTRL0_T_ACQ(63));402	regmap_write(info->regmap, SUN4I_GPADC_CTRL1, info->data->tp_mode_en);403	regmap_write(info->regmap, SUN4I_GPADC_CTRL3,404		     SUN4I_GPADC_CTRL3_FILTER_EN |405		     SUN4I_GPADC_CTRL3_FILTER_TYPE(1));406	/* period = SUN4I_GPADC_TPR_TEMP_PERIOD * 256 * 16 / clkin; ~0.6s */407	regmap_write(info->regmap, SUN4I_GPADC_TPR,408		     SUN4I_GPADC_TPR_TEMP_ENABLE |409		     SUN4I_GPADC_TPR_TEMP_PERIOD(800));410 411	return 0;412}413 414static int sun4i_gpadc_get_temp(struct thermal_zone_device *tz, int *temp)415{416	struct sun4i_gpadc_iio *info = thermal_zone_device_priv(tz);417	int val, scale, offset;418 419	if (sun4i_gpadc_temp_read(info->indio_dev, &val))420		return -ETIMEDOUT;421 422	sun4i_gpadc_temp_scale(info->indio_dev, &scale);423	sun4i_gpadc_temp_offset(info->indio_dev, &offset);424 425	*temp = (val + offset) * scale;426 427	return 0;428}429 430static const struct thermal_zone_device_ops sun4i_ts_tz_ops = {431	.get_temp = &sun4i_gpadc_get_temp,432};433 434static const struct dev_pm_ops sun4i_gpadc_pm_ops = {435	.runtime_suspend = &sun4i_gpadc_runtime_suspend,436	.runtime_resume = &sun4i_gpadc_runtime_resume,437};438 439static int sun4i_irq_init(struct platform_device *pdev, const char *name,440			  irq_handler_t handler, const char *devname,441			  unsigned int *irq, atomic_t *atomic)442{443	int ret;444	struct sun4i_gpadc_dev *mfd_dev = dev_get_drvdata(pdev->dev.parent);445	struct sun4i_gpadc_iio *info = iio_priv(dev_get_drvdata(&pdev->dev));446 447	/*448	 * Once the interrupt is activated, the IP continuously performs449	 * conversions thus throws interrupts. The interrupt is activated right450	 * after being requested but we want to control when these interrupts451	 * occur thus we disable it right after being requested. However, an452	 * interrupt might occur between these two instructions and we have to453	 * make sure that does not happen, by using atomic flags. We set the454	 * flag before requesting the interrupt and unset it right after455	 * disabling the interrupt. When an interrupt occurs between these two456	 * instructions, reading the atomic flag will tell us to ignore the457	 * interrupt.458	 */459	atomic_set(atomic, 1);460 461	ret = platform_get_irq_byname(pdev, name);462	if (ret < 0)463		return ret;464 465	ret = regmap_irq_get_virq(mfd_dev->regmap_irqc, ret);466	if (ret < 0) {467		dev_err(&pdev->dev, "failed to get virq for irq %s\n", name);468		return ret;469	}470 471	*irq = ret;472	ret = devm_request_any_context_irq(&pdev->dev, *irq, handler,473					   IRQF_NO_AUTOEN,474					   devname, info);475	if (ret < 0) {476		dev_err(&pdev->dev, "could not request %s interrupt: %d\n",477			name, ret);478		return ret;479	}480 481	atomic_set(atomic, 0);482 483	return 0;484}485 486static const struct of_device_id sun4i_gpadc_of_id[] = {487	{488		.compatible = "allwinner,sun8i-a33-ths",489		.data = &sun8i_a33_gpadc_data,490	},491	{ /* sentinel */ }492};493 494static int sun4i_gpadc_probe_dt(struct platform_device *pdev,495				struct iio_dev *indio_dev)496{497	struct sun4i_gpadc_iio *info = iio_priv(indio_dev);498	void __iomem *base;499	int ret;500 501	info->data = of_device_get_match_data(&pdev->dev);502	if (!info->data)503		return -ENODEV;504 505	info->no_irq = true;506	indio_dev->num_channels = ARRAY_SIZE(sun8i_a33_gpadc_channels);507	indio_dev->channels = sun8i_a33_gpadc_channels;508 509	base = devm_platform_ioremap_resource(pdev, 0);510	if (IS_ERR(base))511		return PTR_ERR(base);512 513	info->regmap = devm_regmap_init_mmio(&pdev->dev, base,514					     &sun4i_gpadc_regmap_config);515	if (IS_ERR(info->regmap)) {516		ret = PTR_ERR(info->regmap);517		dev_err(&pdev->dev, "failed to init regmap: %d\n", ret);518		return ret;519	}520 521	if (IS_ENABLED(CONFIG_THERMAL_OF))522		info->sensor_device = &pdev->dev;523 524	return 0;525}526 527static int sun4i_gpadc_probe_mfd(struct platform_device *pdev,528				 struct iio_dev *indio_dev)529{530	struct sun4i_gpadc_iio *info = iio_priv(indio_dev);531	struct sun4i_gpadc_dev *sun4i_gpadc_dev =532		dev_get_drvdata(pdev->dev.parent);533	int ret;534 535	info->no_irq = false;536	info->regmap = sun4i_gpadc_dev->regmap;537 538	indio_dev->num_channels = ARRAY_SIZE(sun4i_gpadc_channels);539	indio_dev->channels = sun4i_gpadc_channels;540 541	info->data = (struct gpadc_data *)platform_get_device_id(pdev)->driver_data;542 543	/*544	 * Since the controller needs to be in touchscreen mode for its thermal545	 * sensor to operate properly, and that switching between the two modes546	 * needs a delay, always registering in the thermal framework will547	 * significantly slow down the conversion rate of the ADCs.548	 *549	 * Therefore, instead of depending on THERMAL_OF in Kconfig, we only550	 * register the sensor if that option is enabled, eventually leaving551	 * that choice to the user.552	 */553 554	if (IS_ENABLED(CONFIG_THERMAL_OF)) {555		/*556		 * This driver is a child of an MFD which has a node in the DT557		 * but not its children, because of DT backward compatibility558		 * for A10, A13 and A31 SoCs. Therefore, the resulting devices559		 * of this driver do not have an of_node variable.560		 * However, its parent (the MFD driver) has an of_node variable561		 * and since devm_thermal_zone_of_sensor_register uses its first562		 * argument to match the phandle defined in the node of the563		 * thermal driver with the of_node of the device passed as first564		 * argument and the third argument to call ops from565		 * thermal_zone_of_device_ops, the solution is to use the parent566		 * device as first argument to match the phandle with its567		 * of_node, and the device from this driver as third argument to568		 * return the temperature.569		 */570		info->sensor_device = pdev->dev.parent;571	} else {572		indio_dev->num_channels =573			ARRAY_SIZE(sun4i_gpadc_channels_no_temp);574		indio_dev->channels = sun4i_gpadc_channels_no_temp;575	}576 577	if (IS_ENABLED(CONFIG_THERMAL_OF)) {578		ret = sun4i_irq_init(pdev, "TEMP_DATA_PENDING",579				     sun4i_gpadc_temp_data_irq_handler,580				     "temp_data", &info->temp_data_irq,581				     &info->ignore_temp_data_irq);582		if (ret < 0)583			return ret;584	}585 586	ret = sun4i_irq_init(pdev, "FIFO_DATA_PENDING",587			     sun4i_gpadc_fifo_data_irq_handler, "fifo_data",588			     &info->fifo_data_irq, &info->ignore_fifo_data_irq);589	if (ret < 0)590		return ret;591 592	if (IS_ENABLED(CONFIG_THERMAL_OF)) {593		ret = iio_map_array_register(indio_dev, sun4i_gpadc_hwmon_maps);594		if (ret < 0) {595			dev_err(&pdev->dev,596				"failed to register iio map array\n");597			return ret;598		}599	}600 601	return 0;602}603 604static int sun4i_gpadc_probe(struct platform_device *pdev)605{606	struct sun4i_gpadc_iio *info;607	struct iio_dev *indio_dev;608	int ret;609 610	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*info));611	if (!indio_dev)612		return -ENOMEM;613 614	info = iio_priv(indio_dev);615	platform_set_drvdata(pdev, indio_dev);616 617	mutex_init(&info->mutex);618	info->indio_dev = indio_dev;619	init_completion(&info->completion);620	indio_dev->name = dev_name(&pdev->dev);621	indio_dev->info = &sun4i_gpadc_iio_info;622	indio_dev->modes = INDIO_DIRECT_MODE;623 624	if (pdev->dev.of_node)625		ret = sun4i_gpadc_probe_dt(pdev, indio_dev);626	else627		ret = sun4i_gpadc_probe_mfd(pdev, indio_dev);628 629	if (ret)630		return ret;631 632	pm_runtime_set_autosuspend_delay(&pdev->dev,633					 SUN4I_GPADC_AUTOSUSPEND_DELAY);634	pm_runtime_use_autosuspend(&pdev->dev);635	pm_runtime_set_suspended(&pdev->dev);636	pm_runtime_enable(&pdev->dev);637 638	if (IS_ENABLED(CONFIG_THERMAL_OF)) {639		info->tzd = devm_thermal_of_zone_register(info->sensor_device,640							  0, info,641							  &sun4i_ts_tz_ops);642		/*643		 * Do not fail driver probing when failing to register in644		 * thermal because no thermal DT node is found.645		 */646		if (IS_ERR(info->tzd) && PTR_ERR(info->tzd) != -ENODEV) {647			dev_err(&pdev->dev,648				"could not register thermal sensor: %ld\n",649				PTR_ERR(info->tzd));650			return PTR_ERR(info->tzd);651		}652	}653 654	ret = devm_iio_device_register(&pdev->dev, indio_dev);655	if (ret < 0) {656		dev_err(&pdev->dev, "could not register the device\n");657		goto err_map;658	}659 660	return 0;661 662err_map:663	if (!info->no_irq && IS_ENABLED(CONFIG_THERMAL_OF))664		iio_map_array_unregister(indio_dev);665 666	pm_runtime_put(&pdev->dev);667	pm_runtime_disable(&pdev->dev);668 669	return ret;670}671 672static void sun4i_gpadc_remove(struct platform_device *pdev)673{674	struct iio_dev *indio_dev = platform_get_drvdata(pdev);675	struct sun4i_gpadc_iio *info = iio_priv(indio_dev);676 677	pm_runtime_put(&pdev->dev);678	pm_runtime_disable(&pdev->dev);679 680	if (!IS_ENABLED(CONFIG_THERMAL_OF))681		return;682 683	if (!info->no_irq)684		iio_map_array_unregister(indio_dev);685}686 687static const struct platform_device_id sun4i_gpadc_id[] = {688	{ "sun4i-a10-gpadc-iio", (kernel_ulong_t)&sun4i_gpadc_data },689	{ "sun5i-a13-gpadc-iio", (kernel_ulong_t)&sun5i_gpadc_data },690	{ "sun6i-a31-gpadc-iio", (kernel_ulong_t)&sun6i_gpadc_data },691	{ /* sentinel */ },692};693MODULE_DEVICE_TABLE(platform, sun4i_gpadc_id);694 695static struct platform_driver sun4i_gpadc_driver = {696	.driver = {697		.name = "sun4i-gpadc-iio",698		.of_match_table = sun4i_gpadc_of_id,699		.pm = &sun4i_gpadc_pm_ops,700	},701	.id_table = sun4i_gpadc_id,702	.probe = sun4i_gpadc_probe,703	.remove_new = sun4i_gpadc_remove,704};705MODULE_DEVICE_TABLE(of, sun4i_gpadc_of_id);706 707module_platform_driver(sun4i_gpadc_driver);708 709MODULE_DESCRIPTION("ADC driver for sunxi platforms");710MODULE_AUTHOR("Quentin Schulz <quentin.schulz@free-electrons.com>");711MODULE_LICENSE("GPL v2");712