All of lore.kernel.org
 help / color / mirror / Atom feed
diff for duplicates of <511E951C.6090604@gmx.de>

diff --git a/a/1.txt b/N1/1.txt
index 4bc82fe..35de0c6 100644
--- a/a/1.txt
+++ b/N1/1.txt
@@ -1,655 +1,333 @@
-I had a quick look over your patches and found some minor typo, see below. I will apply all the patches to see the result.
-Also keep in mind to add some changes to Documentation/hwmon/adt7410 (and add an adt7310 as well?).
-
-Lars-Peter Clausen schrieb:
-<...>
-> diff --git a/drivers/hwmon/adt7310.c b/drivers/hwmon/adt7310.c
-> new file mode 100644
-> index 0000000..0483e6c
-> --- /dev/null
-> +++ b/drivers/hwmon/adt7310.c
-> @@ -0,0 +1,160 @@
-> +/*
-> + * ADT7310/ADT7310 digital temperature sensor driver
-> + *
-> + * Copyright 2010-2013 Analog Devices Inc.
-> + *   Author: Lars-Peter Clausen <lars@metafoo.de>
-> + *
-> + * Licensed under the GPL-2 or later.
-> + */
-> +
-> +#include <linux/module.h>
-> +#include <linux/init.h>
-> +#include <linux/spi/spi.h>
-> +
-> +#include "adt7x10.h"
-> +
-> +static const u8 adt7371_reg_table[] = {
-> +	[ADT7410_TEMPERATURE]   = ADT7310_TEMPERATURE,
-> +	[ADT7410_STATUS]	= ADT7310_STATUS,
-> +	[ADT7410_CONFIG]	= ADT7310_CONFIG,
-> +	[ADT7410_T_ALARM_HIGH]	= ADT7310_T_ALARM_HIGH,
-> +	[ADT7410_T_ALARM_LOW]	= ADT7310_T_ALARM_LOW,
-> +	[ADT7410_T_CRIT]	= ADT7310_T_CRIT,
-> +	[ADT7410_T_HYST]	= ADT7310_T_HYST,
-> +	[ADT7410_ID]		= ADT7310_ID,
-> +};
-Just out of curiousity, whats the reason for the name adt7371 here?
-> +
-> +#define ADT7310_CMD_REG_MASK			0x28
-> +#define ADT7310_CMD_REG_OFFSET			3
-> +#define ADT7310_CMD_READ			0x40
-> +#define ADT7310_CMD_CON_READ			0x4
-> +
-> +#define AD7310_COMMAND(reg) (adt7371_reg_table[(reg)] << ADT7310_CMD_REG_OFFSET)
-> +
-> +static int adt7310_spi_read_word(struct device *dev,
-> +	u8 reg, u16 *data)
-> +{
-> +	struct spi_device *spi = to_spi_device(dev);
-> +	u8 command = AD7310_COMMAND(reg);
-> +	int ret = 0;
-> +
-> +	command |= ADT7310_CMD_READ;
-> +	ret = spi_write(spi, &command, sizeof(command));
-> +	if (ret < 0) {
-> +		dev_err(dev, "SPI write command error\n");
-> +		return ret;
-> +	}
-> +
-> +	ret = spi_read(spi, (u8 *)data, sizeof(*data));
-> +	if (ret < 0) {
-> +		dev_err(dev, "SPI read word error\n");
-> +		return ret;
-> +	}
-> +
-> +	*data = be16_to_cpu(*data);
-> +
-> +	return 0;
-> +}
-> +
-> +static int adt7310_spi_write_word(struct device *dev, u8 reg,
-> +	u16 data)
-> +{
-> +	struct spi_device *spi = to_spi_device(dev);
-> +	u8 buf[3];
-> +	int ret = 0;
-> +
-> +	buf[0] = AD7310_COMMAND(reg);
-> +	buf[1] = (u8)(data >> 8);
-> +	buf[2] = (u8)(data & 0xFF);
-> +
-> +	ret = spi_write(spi, buf, 3);
-> +	if (ret < 0) {
-> +		dev_err(dev, "SPI write word error\n");
-> +		return ret;
-> +	}
-> +
-> +	return ret;
-> +}
-> +
-> +static int adt7310_spi_read_byte(struct device *dev, u8 reg,
-> +	u8 *data)
-> +{
-> +	struct spi_device *spi = to_spi_device(dev);
-> +	u8 command = AD7310_COMMAND(reg);
-> +	int ret = 0;
-> +
-> +	command |= ADT7310_CMD_READ;
-> +	ret = spi_write(spi, &command, sizeof(command));
-> +	if (ret < 0) {
-> +		dev_err(dev, "SPI write command error\n");
-> +		return ret;
-> +	}
-> +
-> +	ret = spi_read(spi, data, sizeof(*data));
-> +	if (ret < 0) {
-> +		dev_err(dev, "SPI read byte error\n");
-> +		return ret;
-> +	}
-> +
-> +	return 0;
-> +}
-> +
-> +static int adt7310_spi_write_byte(struct device *dev, u8 reg,
-> +	u8 data)
-> +{
-> +	struct spi_device *spi = to_spi_device(dev);
-> +	u8 buf[2];
-> +	int ret = 0;
-> +
-> +	buf[0] = AD7310_COMMAND(reg);
-> +	buf[1] = data;
-> +
-> +	ret = spi_write(spi, buf, 2);
-> +	if (ret < 0) {
-> +		dev_err(dev, "SPI write byte error\n");
-> +		return ret;
-> +	}
-> +
-> +	return ret;
-> +}
-> +
-> +static const struct adt7410_ops adt7310_spi_ops = {
-> +	.read_word = adt7310_spi_read_word,
-> +	.write_word = adt7310_spi_write_word,
-> +	.read_byte = adt7310_spi_read_byte,
-> +	.write_byte = adt7310_spi_write_byte,
-> +};
-> +
-> +static int adt7310_spi_probe(struct spi_device *spi)
-> +{
-> +	return adt7410_probe(&spi->dev, spi_get_device_id(spi)->name,
-> +			&adt7310_spi_ops);
-> +}
-> +
-> +static int adt7310_spi_remove(struct spi_device *spi)
-> +{
-> +	return adt7410_remove(&spi->dev);
-> +}
-> +
-> +static const struct spi_device_id adt7310_id[] = {
-> +	{ "adt7310", 0 },
-> +	{ "adt7320", 0 },
-> +	{}
-> +};
-> +MODULE_DEVICE_TABLE(spi, adt7310_id);
-> +
-> +static struct spi_driver adt7310_driver = {
-> +	.driver = {
-> +		.name = "adt7310",
-> +		.owner = THIS_MODULE,
-> +		.pm	= ADT7410_DEV_PM_OPS,
-> +	},
-> +	.probe = adt7310_spi_probe,
-> +	.remove = adt7310_spi_remove,
-> +	.id_table = adt7310_id,
-> +};
-> +module_spi_driver(adt7310_driver);
-> +
-> +MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
-> +MODULE_DESCRIPTION("ADT7310/ADT7420 driver");
-This should be ADT7310/ADT7320, right?
-> +MODULE_LICENSE("GPL");
-<...>
-> --- /dev/null
-> +++ b/drivers/hwmon/adt7x10.c
-> @@ -0,0 +1,476 @@
-> +/*
-> + * adt7410.c - Part of lm_sensors, Linux kernel modules for hardware
-> + *	 monitoring
-> + * This driver handles the ADT7410 and compatible digital temperature sensors.
-> + * Hartmut Knaack <knaack.h@gmx.de> 2012-07-22
-> + * based on lm75.c by Frodo Looijaard <frodol@dds.nl>
-> + * and adt7410.c from iio-staging by Sonic Zhang <sonic.zhang@analog.com>
-> + *
-> + * 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.
-> + *
-> + * You should have received a copy of the GNU General Public License
-> + * along with this program; if not, write to the Free Software
-> + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-> + */
-> +
-> +#include <linux/module.h>
-> +#include <linux/init.h>
-> +#include <linux/slab.h>
-> +#include <linux/jiffies.h>
-> +#include <linux/hwmon.h>
-> +#include <linux/hwmon-sysfs.h>
-> +#include <linux/err.h>
-> +#include <linux/mutex.h>
-> +#include <linux/delay.h>
-> +
-> +#include "adt7x10.h"
-> +
-> +/*
-> + * ADT7410 status
-> + */
-> +#define ADT7410_STAT_T_LOW		(1 << 4)
-> +#define ADT7410_STAT_T_HIGH		(1 << 5)
-> +#define ADT7410_STAT_T_CRIT		(1 << 6)
-> +#define ADT7410_STAT_NOT_RDY		(1 << 7)
-> +
-> +/*
-> + * ADT7410 config
-> + */
-> +#define ADT7410_FAULT_QUEUE_MASK	(1 << 0 | 1 << 1)
-> +#define ADT7410_CT_POLARITY		(1 << 2)
-> +#define ADT7410_INT_POLARITY		(1 << 3)
-> +#define ADT7410_EVENT_MODE		(1 << 4)
-> +#define ADT7410_MODE_MASK		(1 << 5 | 1 << 6)
-> +#define ADT7410_FULL			(0 << 5 | 0 << 6)
-> +#define ADT7410_PD			(1 << 5 | 1 << 6)
-> +#define ADT7410_RESOLUTION		(1 << 7)
-> +
-> +/*
-> + * ADT7410 masks
-> + */
-> +#define ADT7410_T13_VALUE_MASK			0xFFF8
-> +#define ADT7410_T_HYST_MASK			0xF
-> +
-> +/* straight from the datasheet */
-> +#define ADT7410_TEMP_MIN (-55000)
-> +#define ADT7410_TEMP_MAX 150000
-> +
-> +/* Each client has this additional data */
-> +struct adt7410_data {
-> +	const struct adt7410_ops *ops;
-> +	const char		*name;
-> +	struct device		*hwmon_dev;
-> +	struct mutex		update_lock;
-> +	u8			config;
-> +	u8			oldconfig;
-> +	bool			valid;		/* true if registers valid */
-> +	unsigned long		last_updated;	/* In jiffies */
-> +	s16			temp[4];	/* Register values,
-> +						   0 = input
-> +						   1 = high
-> +						   2 = low
-> +						   3 = critical */
-> +	u8			hyst;		/* hysteresis offset */
-> +};
-> +
-> +static int adt7410_read_word(struct device *dev, u8 reg, u16 *data)
-> +{
-> +	struct adt7410_data *d = dev_get_drvdata(dev);
-> +	return d->ops->read_word(dev, reg, data);
-> +}
-> +
-> +static int adt7410_write_word(struct device *dev, u8 reg, u16 data)
-> +{
-> +	struct adt7410_data *d = dev_get_drvdata(dev);
-> +	return d->ops->write_word(dev, reg, data);
-> +}
-> +
-> +static int adt7410_read_byte(struct device *dev, u8 reg, u8 *data)
-> +{
-> +	struct adt7410_data *d = dev_get_drvdata(dev);
-> +	return d->ops->read_byte(dev, reg, data);
-> +}
-> +
-> +static int adt7410_write_byte(struct device *dev, u8 reg, u8 data)
-> +{
-> +	struct adt7410_data *d = dev_get_drvdata(dev);
-> +	return d->ops->write_byte(dev, reg, data);
-> +}
-> +
-> +static const u8 ADT7410_REG_TEMP[4] = {
-> +	ADT7410_TEMPERATURE,		/* input */
-> +	ADT7410_T_ALARM_HIGH,		/* high */
-> +	ADT7410_T_ALARM_LOW,		/* low */
-> +	ADT7410_T_CRIT,			/* critical */
-> +};
-> +
-> +/*
-> + * adt7410 register access by I2C
-> + */
-> +static int adt7410_temp_ready(struct device *dev)
-> +{
-> +	int i, ret;
-> +	u8 status;
-> +
-> +	for (i = 0; i < 6; i++) {
-> +		ret = adt7410_read_byte(dev, ADT7410_STATUS, &status);
-> +		if (ret)
-> +			return ret;
-> +		if (!(status & ADT7410_STAT_NOT_RDY))
-> +			return 0;
-> +		msleep(60);
-> +	}
-> +	return -ETIMEDOUT;
-> +}
-> +
-> +static int adt7410_update_temp(struct device *dev)
-> +{
-> +	struct adt7410_data *data = dev_get_drvdata(dev);
-> +	int ret = 0;
-> +
-> +	mutex_lock(&data->update_lock);
-> +
-> +	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
-> +	    || !data->valid) {
-> +
-> +		dev_dbg(dev, "Starting update\n");
-> +
-> +		ret = adt7410_temp_ready(dev); /* check for new value */
-> +		if (ret)
-> +			goto abort;
-> +
-> +		ret = adt7410_read_word(dev, ADT7410_REG_TEMP[0],
-> +					&data->temp[0]);
-> +		if (ret) {
-> +			dev_dbg(dev, "Failed to read value: reg %d, error %d\n",
-> +				ADT7410_REG_TEMP[0], ret);
-> +			goto abort;
-> +		}
-> +		data->last_updated = jiffies;
-> +		data->valid = true;
-> +	}
-> +
-> +abort:
-> +	mutex_unlock(&data->update_lock);
-> +	return ret;
-> +}
-> +
-> +static int adt7410_fill_cache(struct device *dev)
-> +{
-> +	struct adt7410_data *data = dev_get_drvdata(dev);
-> +	int ret;
-> +	int i;
-> +
-> +	for (i = 1; i < ARRAY_SIZE(data->temp); i++) {
-> +		ret = adt7410_read_word(dev, ADT7410_REG_TEMP[i],
-> +					&data->temp[i]);
-> +		if (ret) {
-> +			dev_dbg(dev, "Failed to read value: reg %d, error %d\n",
-> +				ADT7410_REG_TEMP[0], ret);
-> +			return ret;
-> +		}
-> +	}
-> +
-> +	ret = adt7410_read_byte(dev, ADT7410_T_HYST, &data->hyst);
-> +	if (ret) {
-> +		dev_dbg(dev, "Failed to read value: reg %d, error %d\n",
-> +				ADT7410_T_HYST, ret);
-> +		return ret;
-> +	}
-> +
-> +	return 0;
-> +}
-> +
-> +static s16 ADT7410_TEMP_TO_REG(long temp)
-> +{
-> +	return DIV_ROUND_CLOSEST(clamp_val(temp, ADT7410_TEMP_MIN,
-> +					       ADT7410_TEMP_MAX) * 128, 1000);
-> +}
-> +
-> +static int ADT7410_REG_TO_TEMP(struct adt7410_data *data, s16 reg)
-> +{
-> +	/* in 13 bit mode, bits 0-2 are status flags - mask them out */
-> +	if (!(data->config & ADT7410_RESOLUTION))
-> +		reg &= ADT7410_T13_VALUE_MASK;
-> +	/*
-> +	 * temperature is stored in twos complement format, in steps of
-> +	 * 1/128°C
-> +	 */
-> +	return DIV_ROUND_CLOSEST(reg * 1000, 128);
-> +}
-> +
-> +/*-----------------------------------------------------------------------*/
-> +
-> +/* sysfs attributes for hwmon */
-> +
-> +static ssize_t adt7410_show_temp(struct device *dev,
-> +				 struct device_attribute *da, char *buf)
-> +{
-> +	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
-> +	struct adt7410_data *data = dev_get_drvdata(dev);
-> +
-> +
-> +	if (attr->index == 0) {
-> +		int ret;
-> +
-> +		ret = adt7410_update_temp(dev);
-> +		if (ret)
-> +			return ret;
-> +	}
-> +
-> +	return sprintf(buf, "%d\n", ADT7410_REG_TO_TEMP(data,
-> +		       data->temp[attr->index]));
-> +}
-> +
-> +static ssize_t adt7410_set_temp(struct device *dev,
-> +				struct device_attribute *da,
-> +				const char *buf, size_t count)
-> +{
-> +	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
-> +	struct adt7410_data *data = dev_get_drvdata(dev);
-> +	int nr = attr->index;
-> +	long temp;
-> +	int ret;
-> +
-> +	ret = kstrtol(buf, 10, &temp);
-> +	if (ret)
-> +		return ret;
-> +
-> +	mutex_lock(&data->update_lock);
-> +	data->temp[nr] = ADT7410_TEMP_TO_REG(temp);
-> +	ret = adt7410_write_word(dev, ADT7410_REG_TEMP[nr], data->temp[nr]);
-> +	if (ret)
-> +		count = ret;
-> +	mutex_unlock(&data->update_lock);
-> +	return count;
-> +}
-> +
-> +static ssize_t adt7410_show_t_hyst(struct device *dev,
-> +				   struct device_attribute *da,
-> +				   char *buf)
-> +{
-> +	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
-> +	struct adt7410_data *data = dev_get_drvdata(dev);
-> +	int nr = attr->index;
-> +	int hyst;
-> +
-> +	hyst = (data->hyst & ADT7410_T_HYST_MASK) * 1000;
-> +
-> +	/*
-> +	 * hysteresis is stored as a 4 bit offset in the device, convert it
-> +	 * to an absolute value
-> +	 */
-> +	if (nr == 2)	/* min has positive offset, others have negative */
-> +		hyst = -hyst;
-> +	return sprintf(buf, "%d\n",
-> +		       ADT7410_REG_TO_TEMP(data, data->temp[nr]) - hyst);
-> +}
-> +
-> +static ssize_t adt7410_set_t_hyst(struct device *dev,
-> +				  struct device_attribute *da,
-> +				  const char *buf, size_t count)
-> +{
-> +	struct adt7410_data *data = dev_get_drvdata(dev);
-> +	int limit, ret;
-> +	long hyst;
-> +
-> +	ret = kstrtol(buf, 10, &hyst);
-> +	if (ret)
-> +		return ret;
-> +	/* convert absolute hysteresis value to a 4 bit delta value */
-> +	limit = ADT7410_REG_TO_TEMP(data, data->temp[1]);
-> +	hyst = clamp_val(hyst, ADT7410_TEMP_MIN, ADT7410_TEMP_MAX);
-> +	data->hyst = clamp_val(DIV_ROUND_CLOSEST(limit - hyst, 1000),
-> +				   0, ADT7410_T_HYST_MASK);
-> +	ret = adt7410_write_byte(dev, ADT7410_T_HYST, data->hyst);
-> +	if (ret)
-> +		return ret;
-> +
-> +	return count;
-> +}
-> +
-> +static ssize_t adt7410_show_alarm(struct device *dev,
-> +				  struct device_attribute *da,
-> +				  char *buf)
-> +{
-> +	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
-> +	u8 status;
-> +	int ret;
-> +
-> +	ret = adt7410_read_byte(dev, ADT7410_STATUS, &status);
-> +	if (ret < 0)
-> +		return ret;
-> +
-> +	return sprintf(buf, "%d\n", !!(status & attr->index));
-> +}
-> +
-> +static ssize_t adt7410_show_name(struct device *dev,
-> +				  struct device_attribute *da, char *buf)
-> +{
-> +	struct adt7410_data *data = dev_get_drvdata(dev);
-> +
-> +	return sprintf(buf, "%s\n", data->name);
-> +}
-> +
-> +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, adt7410_show_temp, NULL, 0);
-> +static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO,
-> +			  adt7410_show_temp, adt7410_set_temp, 1);
-> +static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO,
-> +			  adt7410_show_temp, adt7410_set_temp, 2);
-> +static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO,
-> +			  adt7410_show_temp, adt7410_set_temp, 3);
-> +static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO,
-> +			  adt7410_show_t_hyst, adt7410_set_t_hyst, 1);
-> +static SENSOR_DEVICE_ATTR(temp1_min_hyst, S_IRUGO,
-> +			  adt7410_show_t_hyst, NULL, 2);
-> +static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO,
-> +			  adt7410_show_t_hyst, NULL, 3);
-> +static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, adt7410_show_alarm,
-> +			  NULL, ADT7410_STAT_T_LOW);
-> +static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, adt7410_show_alarm,
-> +			  NULL, ADT7410_STAT_T_HIGH);
-> +static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, adt7410_show_alarm,
-> +			  NULL, ADT7410_STAT_T_CRIT);
-> +static DEVICE_ATTR(name, S_IRUGO, adt7410_show_name, NULL);
-> +
-> +static struct attribute *adt7410_attributes[] = {
-> +	&sensor_dev_attr_temp1_input.dev_attr.attr,
-> +	&sensor_dev_attr_temp1_max.dev_attr.attr,
-> +	&sensor_dev_attr_temp1_min.dev_attr.attr,
-> +	&sensor_dev_attr_temp1_crit.dev_attr.attr,
-> +	&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
-> +	&sensor_dev_attr_temp1_min_hyst.dev_attr.attr,
-> +	&sensor_dev_attr_temp1_crit_hyst.dev_attr.attr,
-> +	&sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
-> +	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
-> +	&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
-> +	NULL
-> +};
-> +
-> +static const struct attribute_group adt7410_group = {
-> +	.attrs = adt7410_attributes,
-> +};
-> +
-> +int adt7410_probe(struct device *dev, const char *name,
-> +	const struct adt7410_ops *ops)
-> +{
-> +	struct adt7410_data *data;
-> +	int ret;
-> +
-> +	data = devm_kzalloc(dev, sizeof(struct adt7410_data),
-> +			    GFP_KERNEL);
-> +	if (!data)
-> +		return -ENOMEM;
-> +
-> +	data->ops = ops;
-> +	data->name = name;
-> +
-> +	dev_set_drvdata(dev, data);
-> +	mutex_init(&data->update_lock);
-> +
-> +	/* configure as specified */
-> +	ret = adt7410_read_byte(dev, ADT7410_CONFIG, &data->oldconfig);
-> +	if (ret < 0) {
-> +		dev_dbg(dev, "Can't read config? %d\n", ret);
-> +		return ret;
-> +	}
-> +	/*
-> +	 * Set to 16 bit resolution, continous conversion and comparator mode.
-> +	 */
-> +	data->config = data->oldconfig;
-> +	data->config &= ~ADT7410_MODE_MASK;
-> +	data->config |= ADT7410_FULL | ADT7410_RESOLUTION | ADT7410_EVENT_MODE;
-> +	if (data->config != data->oldconfig) {
-> +		ret = adt7410_write_byte(dev, ADT7410_CONFIG, data->config);
-> +		if (ret)
-> +			return ret;
-> +	}
-> +	dev_dbg(dev, "Config %02x\n", data->config);
-> +
-> +	ret = adt7410_fill_cache(dev);
-> +	if (ret)
-> +		goto exit_restore;
-> +
-> +	/* Register sysfs hooks */
-> +	ret = sysfs_create_group(&dev->kobj, &adt7410_group);
-> +	if (ret)
-> +		goto exit_restore;
-> +
-> +	/*
-> +	 * The I2C device will already have it's own 'name' attribute, but for
-> +	 * the SPI device we need to register it. name will only be non NULL if
-> +	 * the device doesn't register the 'name' attribute on its own.
-> +	 */
-> +	if (name) {
-> +		ret = device_create_file(dev, &dev_attr_name);
-> +		if (ret)
-> +			goto exit_remove;
-> +	}
-> +
-> +	data->hwmon_dev = hwmon_device_register(dev);
-> +	if (IS_ERR(data->hwmon_dev)) {
-> +		ret = PTR_ERR(data->hwmon_dev);
-> +		goto exit_remove_name;
-> +	}
-> +
-> +	return 0;
-> +
-> +exit_remove_name:
-> +	if (name)
-> +		device_remove_file(dev, &dev_attr_name);
-> +exit_remove:
-> +	sysfs_remove_group(&dev->kobj, &adt7410_group);
-> +exit_restore:
-> +	adt7410_write_byte(dev, ADT7410_CONFIG, data->oldconfig);
-> +	return ret;
-> +}
-> +EXPORT_SYMBOL_GPL(adt7410_probe);
-> +
-> +int adt7410_remove(struct device *dev)
-> +{
-> +	struct adt7410_data *data = dev_get_drvdata(dev);
-> +
-> +	hwmon_device_unregister(data->hwmon_dev);
-> +	if (data->name)
-> +		device_remove_file(dev, &dev_attr_name);
-> +	sysfs_remove_group(&dev->kobj, &adt7410_group);
-> +	if (data->oldconfig != data->config)
-> +		adt7410_write_byte(dev, ADT7410_CONFIG,
-> +					  data->oldconfig);
-> +	return 0;
-> +}
-> +EXPORT_SYMBOL_GPL(adt7410_remove);
-> +
-> +#ifdef CONFIG_PM_SLEEP
-> +
-> +static int adt7410_suspend(struct device *dev)
-> +{
-> +	struct adt7410_data *data = dev_get_drvdata(dev);
-> +
-> +	return adt7410_write_byte(dev, ADT7410_CONFIG,
-> +		data->config | ADT7410_PD);
-> +}
-> +
-> +static int adt7410_resume(struct device *dev)
-> +{
-> +	struct adt7410_data *data = dev_get_drvdata(dev);
-> +
-> +	return adt7410_write_byte(dev, ADT7410_CONFIG, data->config);
-> +}
-> +
-> +SIMPLE_DEV_PM_OPS(adt7410_dev_pm_ops, adt7410_suspend, adt7410_resume);
-> +EXPORT_SYMBOL_GPL(adt7410_dev_pm_ops);
-> +
-> +#endif /* CONFIG_PM_SLEEP */
-> +
-> +MODULE_AUTHOR("Hartmut Knaack");
-> +MODULE_DESCRIPTION("ADT7410 driver");
-This description does not seem appropriate any longer.
-> +MODULE_LICENSE("GPL");
-<...>
+SSBoYWQgYSBxdWljayBsb29rIG92ZXIgeW91ciBwYXRjaGVzIGFuZCBmb3VuZCBzb21lIG1pbm9y
+IHR5cG8sIHNlZSBiZWxvdy4gSSB3aWxsIGFwcGx5IGFsbCB0aGUgcGF0Y2hlcyB0byBzZWUgdGhl
+IHJlc3VsdC4KQWxzbyBrZWVwIGluIG1pbmQgdG8gYWRkIHNvbWUgY2hhbmdlcyB0byBEb2N1bWVu
+dGF0aW9uL2h3bW9uL2FkdDc0MTAgKGFuZCBhZGQgYW4gYWR0NzMxMCBhcyB3ZWxsPykuCgpMYXJz
+LVBldGVyIENsYXVzZW4gc2NocmllYjoKPC4uLj4KPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9od21v
+bi9hZHQ3MzEwLmMgYi9kcml2ZXJzL2h3bW9uL2FkdDczMTAuYwo+IG5ldyBmaWxlIG1vZGUgMTAw
+NjQ0Cj4gaW5kZXggMDAwMDAwMC4uMDQ4M2U2Ywo+IC0tLSAvZGV2L251bGwKPiArKysgYi9kcml2
+ZXJzL2h3bW9uL2FkdDczMTAuYwo+IEBAIC0wLDAgKzEsMTYwIEBACj4gKy8qCj4gKyAqIEFEVDcz
+MTAvQURUNzMxMCBkaWdpdGFsIHRlbXBlcmF0dXJlIHNlbnNvciBkcml2ZXIKPiArICoKPiArICog
+Q29weXJpZ2h0IDIwMTAtMjAxMyBBbmFsb2cgRGV2aWNlcyBJbmMuCj4gKyAqICAgQXV0aG9yOiBM
+YXJzLVBldGVyIENsYXVzZW4gPGxhcnNAbWV0YWZvby5kZT4KPiArICoKPiArICogTGljZW5zZWQg
+dW5kZXIgdGhlIEdQTC0yIG9yIGxhdGVyLgo+ICsgKi8KPiArCj4gKyNpbmNsdWRlIDxsaW51eC9t
+b2R1bGUuaD4KPiArI2luY2x1ZGUgPGxpbnV4L2luaXQuaD4KPiArI2luY2x1ZGUgPGxpbnV4L3Nw
+aS9zcGkuaD4KPiArCj4gKyNpbmNsdWRlICJhZHQ3eDEwLmgiCj4gKwo+ICtzdGF0aWMgY29uc3Qg
+dTggYWR0NzM3MV9yZWdfdGFibGVbXSA9IHsKPiArCVtBRFQ3NDEwX1RFTVBFUkFUVVJFXSAgID0g
+QURUNzMxMF9URU1QRVJBVFVSRSwKPiArCVtBRFQ3NDEwX1NUQVRVU10JPSBBRFQ3MzEwX1NUQVRV
+UywKPiArCVtBRFQ3NDEwX0NPTkZJR10JPSBBRFQ3MzEwX0NPTkZJRywKPiArCVtBRFQ3NDEwX1Rf
+QUxBUk1fSElHSF0JPSBBRFQ3MzEwX1RfQUxBUk1fSElHSCwKPiArCVtBRFQ3NDEwX1RfQUxBUk1f
+TE9XXQk9IEFEVDczMTBfVF9BTEFSTV9MT1csCj4gKwlbQURUNzQxMF9UX0NSSVRdCT0gQURUNzMx
+MF9UX0NSSVQsCj4gKwlbQURUNzQxMF9UX0hZU1RdCT0gQURUNzMxMF9UX0hZU1QsCj4gKwlbQURU
+NzQxMF9JRF0JCT0gQURUNzMxMF9JRCwKPiArfTsKSnVzdCBvdXQgb2YgY3VyaW91c2l0eSwgd2hh
+dHMgdGhlIHJlYXNvbiBmb3IgdGhlIG5hbWUgYWR0NzM3MSBoZXJlPwo+ICsKPiArI2RlZmluZSBB
+RFQ3MzEwX0NNRF9SRUdfTUFTSwkJCTB4MjgKPiArI2RlZmluZSBBRFQ3MzEwX0NNRF9SRUdfT0ZG
+U0VUCQkJMwo+ICsjZGVmaW5lIEFEVDczMTBfQ01EX1JFQUQJCQkweDQwCj4gKyNkZWZpbmUgQURU
+NzMxMF9DTURfQ09OX1JFQUQJCQkweDQKPiArCj4gKyNkZWZpbmUgQUQ3MzEwX0NPTU1BTkQocmVn
+KSAoYWR0NzM3MV9yZWdfdGFibGVbKHJlZyldIDw8IEFEVDczMTBfQ01EX1JFR19PRkZTRVQpCj4g
+Kwo+ICtzdGF0aWMgaW50IGFkdDczMTBfc3BpX3JlYWRfd29yZChzdHJ1Y3QgZGV2aWNlICpkZXYs
+Cj4gKwl1OCByZWcsIHUxNiAqZGF0YSkKPiArewo+ICsJc3RydWN0IHNwaV9kZXZpY2UgKnNwaSA9
+IHRvX3NwaV9kZXZpY2UoZGV2KTsKPiArCXU4IGNvbW1hbmQgPSBBRDczMTBfQ09NTUFORChyZWcp
+Owo+ICsJaW50IHJldCA9IDA7Cj4gKwo+ICsJY29tbWFuZCB8PSBBRFQ3MzEwX0NNRF9SRUFEOwo+
+ICsJcmV0ID0gc3BpX3dyaXRlKHNwaSwgJmNvbW1hbmQsIHNpemVvZihjb21tYW5kKSk7Cj4gKwlp
+ZiAocmV0IDwgMCkgewo+ICsJCWRldl9lcnIoZGV2LCAiU1BJIHdyaXRlIGNvbW1hbmQgZXJyb3Jc
+biIpOwo+ICsJCXJldHVybiByZXQ7Cj4gKwl9Cj4gKwo+ICsJcmV0ID0gc3BpX3JlYWQoc3BpLCAo
+dTggKilkYXRhLCBzaXplb2YoKmRhdGEpKTsKPiArCWlmIChyZXQgPCAwKSB7Cj4gKwkJZGV2X2Vy
+cihkZXYsICJTUEkgcmVhZCB3b3JkIGVycm9yXG4iKTsKPiArCQlyZXR1cm4gcmV0Owo+ICsJfQo+
+ICsKPiArCSpkYXRhID0gYmUxNl90b19jcHUoKmRhdGEpOwo+ICsKPiArCXJldHVybiAwOwo+ICt9
+Cj4gKwo+ICtzdGF0aWMgaW50IGFkdDczMTBfc3BpX3dyaXRlX3dvcmQoc3RydWN0IGRldmljZSAq
+ZGV2LCB1OCByZWcsCj4gKwl1MTYgZGF0YSkKPiArewo+ICsJc3RydWN0IHNwaV9kZXZpY2UgKnNw
+aSA9IHRvX3NwaV9kZXZpY2UoZGV2KTsKPiArCXU4IGJ1ZlszXTsKPiArCWludCByZXQgPSAwOwo+
+ICsKPiArCWJ1ZlswXSA9IEFENzMxMF9DT01NQU5EKHJlZyk7Cj4gKwlidWZbMV0gPSAodTgpKGRh
+dGEgPj4gOCk7Cj4gKwlidWZbMl0gPSAodTgpKGRhdGEgJiAweEZGKTsKPiArCj4gKwlyZXQgPSBz
+cGlfd3JpdGUoc3BpLCBidWYsIDMpOwo+ICsJaWYgKHJldCA8IDApIHsKPiArCQlkZXZfZXJyKGRl
+diwgIlNQSSB3cml0ZSB3b3JkIGVycm9yXG4iKTsKPiArCQlyZXR1cm4gcmV0Owo+ICsJfQo+ICsK
+PiArCXJldHVybiByZXQ7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgYWR0NzMxMF9zcGlfcmVhZF9i
+eXRlKHN0cnVjdCBkZXZpY2UgKmRldiwgdTggcmVnLAo+ICsJdTggKmRhdGEpCj4gK3sKPiArCXN0
+cnVjdCBzcGlfZGV2aWNlICpzcGkgPSB0b19zcGlfZGV2aWNlKGRldik7Cj4gKwl1OCBjb21tYW5k
+ID0gQUQ3MzEwX0NPTU1BTkQocmVnKTsKPiArCWludCByZXQgPSAwOwo+ICsKPiArCWNvbW1hbmQg
+fD0gQURUNzMxMF9DTURfUkVBRDsKPiArCXJldCA9IHNwaV93cml0ZShzcGksICZjb21tYW5kLCBz
+aXplb2YoY29tbWFuZCkpOwo+ICsJaWYgKHJldCA8IDApIHsKPiArCQlkZXZfZXJyKGRldiwgIlNQ
+SSB3cml0ZSBjb21tYW5kIGVycm9yXG4iKTsKPiArCQlyZXR1cm4gcmV0Owo+ICsJfQo+ICsKPiAr
+CXJldCA9IHNwaV9yZWFkKHNwaSwgZGF0YSwgc2l6ZW9mKCpkYXRhKSk7Cj4gKwlpZiAocmV0IDwg
+MCkgewo+ICsJCWRldl9lcnIoZGV2LCAiU1BJIHJlYWQgYnl0ZSBlcnJvclxuIik7Cj4gKwkJcmV0
+dXJuIHJldDsKPiArCX0KPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIGludCBh
+ZHQ3MzEwX3NwaV93cml0ZV9ieXRlKHN0cnVjdCBkZXZpY2UgKmRldiwgdTggcmVnLAo+ICsJdTgg
+ZGF0YSkKPiArewo+ICsJc3RydWN0IHNwaV9kZXZpY2UgKnNwaSA9IHRvX3NwaV9kZXZpY2UoZGV2
+KTsKPiArCXU4IGJ1ZlsyXTsKPiArCWludCByZXQgPSAwOwo+ICsKPiArCWJ1ZlswXSA9IEFENzMx
+MF9DT01NQU5EKHJlZyk7Cj4gKwlidWZbMV0gPSBkYXRhOwo+ICsKPiArCXJldCA9IHNwaV93cml0
+ZShzcGksIGJ1ZiwgMik7Cj4gKwlpZiAocmV0IDwgMCkgewo+ICsJCWRldl9lcnIoZGV2LCAiU1BJ
+IHdyaXRlIGJ5dGUgZXJyb3JcbiIpOwo+ICsJCXJldHVybiByZXQ7Cj4gKwl9Cj4gKwo+ICsJcmV0
+dXJuIHJldDsKPiArfQo+ICsKPiArc3RhdGljIGNvbnN0IHN0cnVjdCBhZHQ3NDEwX29wcyBhZHQ3
+MzEwX3NwaV9vcHMgPSB7Cj4gKwkucmVhZF93b3JkID0gYWR0NzMxMF9zcGlfcmVhZF93b3JkLAo+
+ICsJLndyaXRlX3dvcmQgPSBhZHQ3MzEwX3NwaV93cml0ZV93b3JkLAo+ICsJLnJlYWRfYnl0ZSA9
+IGFkdDczMTBfc3BpX3JlYWRfYnl0ZSwKPiArCS53cml0ZV9ieXRlID0gYWR0NzMxMF9zcGlfd3Jp
+dGVfYnl0ZSwKPiArfTsKPiArCj4gK3N0YXRpYyBpbnQgYWR0NzMxMF9zcGlfcHJvYmUoc3RydWN0
+IHNwaV9kZXZpY2UgKnNwaSkKPiArewo+ICsJcmV0dXJuIGFkdDc0MTBfcHJvYmUoJnNwaS0+ZGV2
+LCBzcGlfZ2V0X2RldmljZV9pZChzcGkpLT5uYW1lLAo+ICsJCQkmYWR0NzMxMF9zcGlfb3BzKTsK
+PiArfQo+ICsKPiArc3RhdGljIGludCBhZHQ3MzEwX3NwaV9yZW1vdmUoc3RydWN0IHNwaV9kZXZp
+Y2UgKnNwaSkKPiArewo+ICsJcmV0dXJuIGFkdDc0MTBfcmVtb3ZlKCZzcGktPmRldik7Cj4gK30K
+PiArCj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3Qgc3BpX2RldmljZV9pZCBhZHQ3MzEwX2lkW10gPSB7
+Cj4gKwl7ICJhZHQ3MzEwIiwgMCB9LAo+ICsJeyAiYWR0NzMyMCIsIDAgfSwKPiArCXt9Cj4gK307
+Cj4gK01PRFVMRV9ERVZJQ0VfVEFCTEUoc3BpLCBhZHQ3MzEwX2lkKTsKPiArCj4gK3N0YXRpYyBz
+dHJ1Y3Qgc3BpX2RyaXZlciBhZHQ3MzEwX2RyaXZlciA9IHsKPiArCS5kcml2ZXIgPSB7Cj4gKwkJ
+Lm5hbWUgPSAiYWR0NzMxMCIsCj4gKwkJLm93bmVyID0gVEhJU19NT0RVTEUsCj4gKwkJLnBtCT0g
+QURUNzQxMF9ERVZfUE1fT1BTLAo+ICsJfSwKPiArCS5wcm9iZSA9IGFkdDczMTBfc3BpX3Byb2Jl
+LAo+ICsJLnJlbW92ZSA9IGFkdDczMTBfc3BpX3JlbW92ZSwKPiArCS5pZF90YWJsZSA9IGFkdDcz
+MTBfaWQsCj4gK307Cj4gK21vZHVsZV9zcGlfZHJpdmVyKGFkdDczMTBfZHJpdmVyKTsKPiArCj4g
+K01PRFVMRV9BVVRIT1IoIkxhcnMtUGV0ZXIgQ2xhdXNlbiA8bGFyc0BtZXRhZm9vLmRlPiIpOwo+
+ICtNT0RVTEVfREVTQ1JJUFRJT04oIkFEVDczMTAvQURUNzQyMCBkcml2ZXIiKTsKVGhpcyBzaG91
+bGQgYmUgQURUNzMxMC9BRFQ3MzIwLCByaWdodD8KPiArTU9EVUxFX0xJQ0VOU0UoIkdQTCIpOwo8
+Li4uPgo+IC0tLSAvZGV2L251bGwKPiArKysgYi9kcml2ZXJzL2h3bW9uL2FkdDd4MTAuYwo+IEBA
+IC0wLDAgKzEsNDc2IEBACj4gKy8qCj4gKyAqIGFkdDc0MTAuYyAtIFBhcnQgb2YgbG1fc2Vuc29y
+cywgTGludXgga2VybmVsIG1vZHVsZXMgZm9yIGhhcmR3YXJlCj4gKyAqCSBtb25pdG9yaW5nCj4g
+KyAqIFRoaXMgZHJpdmVyIGhhbmRsZXMgdGhlIEFEVDc0MTAgYW5kIGNvbXBhdGlibGUgZGlnaXRh
+bCB0ZW1wZXJhdHVyZSBzZW5zb3JzLgo+ICsgKiBIYXJ0bXV0IEtuYWFjayA8a25hYWNrLmhAZ214
+LmRlPiAyMDEyLTA3LTIyCj4gKyAqIGJhc2VkIG9uIGxtNzUuYyBieSBGcm9kbyBMb29pamFhcmQg
+PGZyb2RvbEBkZHMubmw+Cj4gKyAqIGFuZCBhZHQ3NDEwLmMgZnJvbSBpaW8tc3RhZ2luZyBieSBT
+b25pYyBaaGFuZyA8c29uaWMuemhhbmdAYW5hbG9nLmNvbT4KPiArICoKPiArICogVGhpcyBwcm9n
+cmFtIGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2Rp
+ZnkKPiArICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGlj
+ZW5zZSBhcyBwdWJsaXNoZWQgYnkKPiArICogdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsg
+ZWl0aGVyIHZlcnNpb24gMiBvZiB0aGUgTGljZW5zZSwgb3IKPiArICogKGF0IHlvdXIgb3B0aW9u
+KSBhbnkgbGF0ZXIgdmVyc2lvbi4KPiArICoKPiArICogVGhpcyBwcm9ncmFtIGlzIGRpc3RyaWJ1
+dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsCj4gKyAqIGJ1dCBXSVRIT1VU
+IEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mCj4gKyAq
+IE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNl
+ZSB0aGUKPiArICogR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4K
+PiArICoKPiArICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdl
+bmVyYWwgUHVibGljIExpY2Vuc2UKPiArICogYWxvbmcgd2l0aCB0aGlzIHByb2dyYW07IGlmIG5v
+dCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmUKPiArICogRm91bmRhdGlvbiwgSW5jLiwgNjc1
+IE1hc3MgQXZlLCBDYW1icmlkZ2UsIE1BIDAyMTM5LCBVU0EuCj4gKyAqLwo+ICsKPiArI2luY2x1
+ZGUgPGxpbnV4L21vZHVsZS5oPgo+ICsjaW5jbHVkZSA8bGludXgvaW5pdC5oPgo+ICsjaW5jbHVk
+ZSA8bGludXgvc2xhYi5oPgo+ICsjaW5jbHVkZSA8bGludXgvamlmZmllcy5oPgo+ICsjaW5jbHVk
+ZSA8bGludXgvaHdtb24uaD4KPiArI2luY2x1ZGUgPGxpbnV4L2h3bW9uLXN5c2ZzLmg+Cj4gKyNp
+bmNsdWRlIDxsaW51eC9lcnIuaD4KPiArI2luY2x1ZGUgPGxpbnV4L211dGV4Lmg+Cj4gKyNpbmNs
+dWRlIDxsaW51eC9kZWxheS5oPgo+ICsKPiArI2luY2x1ZGUgImFkdDd4MTAuaCIKPiArCj4gKy8q
+Cj4gKyAqIEFEVDc0MTAgc3RhdHVzCj4gKyAqLwo+ICsjZGVmaW5lIEFEVDc0MTBfU1RBVF9UX0xP
+VwkJKDEgPDwgNCkKPiArI2RlZmluZSBBRFQ3NDEwX1NUQVRfVF9ISUdICQkoMSA8PCA1KQo+ICsj
+ZGVmaW5lIEFEVDc0MTBfU1RBVF9UX0NSSVQJCSgxIDw8IDYpCj4gKyNkZWZpbmUgQURUNzQxMF9T
+VEFUX05PVF9SRFkJCSgxIDw8IDcpCj4gKwo+ICsvKgo+ICsgKiBBRFQ3NDEwIGNvbmZpZwo+ICsg
+Ki8KPiArI2RlZmluZSBBRFQ3NDEwX0ZBVUxUX1FVRVVFX01BU0sJKDEgPDwgMCB8IDEgPDwgMSkK
+PiArI2RlZmluZSBBRFQ3NDEwX0NUX1BPTEFSSVRZCQkoMSA8PCAyKQo+ICsjZGVmaW5lIEFEVDc0
+MTBfSU5UX1BPTEFSSVRZCQkoMSA8PCAzKQo+ICsjZGVmaW5lIEFEVDc0MTBfRVZFTlRfTU9ERQkJ
+KDEgPDwgNCkKPiArI2RlZmluZSBBRFQ3NDEwX01PREVfTUFTSwkJKDEgPDwgNSB8IDEgPDwgNikK
+PiArI2RlZmluZSBBRFQ3NDEwX0ZVTEwJCQkoMCA8PCA1IHwgMCA8PCA2KQo+ICsjZGVmaW5lIEFE
+VDc0MTBfUEQJCQkoMSA8PCA1IHwgMSA8PCA2KQo+ICsjZGVmaW5lIEFEVDc0MTBfUkVTT0xVVElP
+TgkJKDEgPDwgNykKPiArCj4gKy8qCj4gKyAqIEFEVDc0MTAgbWFza3MKPiArICovCj4gKyNkZWZp
+bmUgQURUNzQxMF9UMTNfVkFMVUVfTUFTSwkJCTB4RkZGOAo+ICsjZGVmaW5lIEFEVDc0MTBfVF9I
+WVNUX01BU0sJCQkweEYKPiArCj4gKy8qIHN0cmFpZ2h0IGZyb20gdGhlIGRhdGFzaGVldCAqLwo+
+ICsjZGVmaW5lIEFEVDc0MTBfVEVNUF9NSU4gKC01NTAwMCkKPiArI2RlZmluZSBBRFQ3NDEwX1RF
+TVBfTUFYIDE1MDAwMAo+ICsKPiArLyogRWFjaCBjbGllbnQgaGFzIHRoaXMgYWRkaXRpb25hbCBk
+YXRhICovCj4gK3N0cnVjdCBhZHQ3NDEwX2RhdGEgewo+ICsJY29uc3Qgc3RydWN0IGFkdDc0MTBf
+b3BzICpvcHM7Cj4gKwljb25zdCBjaGFyCQkqbmFtZTsKPiArCXN0cnVjdCBkZXZpY2UJCSpod21v
+bl9kZXY7Cj4gKwlzdHJ1Y3QgbXV0ZXgJCXVwZGF0ZV9sb2NrOwo+ICsJdTgJCQljb25maWc7Cj4g
+Kwl1OAkJCW9sZGNvbmZpZzsKPiArCWJvb2wJCQl2YWxpZDsJCS8qIHRydWUgaWYgcmVnaXN0ZXJz
+IHZhbGlkICovCj4gKwl1bnNpZ25lZCBsb25nCQlsYXN0X3VwZGF0ZWQ7CS8qIEluIGppZmZpZXMg
+Ki8KPiArCXMxNgkJCXRlbXBbNF07CS8qIFJlZ2lzdGVyIHZhbHVlcywKPiArCQkJCQkJICAgMCA9
+IGlucHV0Cj4gKwkJCQkJCSAgIDEgPSBoaWdoCj4gKwkJCQkJCSAgIDIgPSBsb3cKPiArCQkJCQkJ
+ICAgMyA9IGNyaXRpY2FsICovCj4gKwl1OAkJCWh5c3Q7CQkvKiBoeXN0ZXJlc2lzIG9mZnNldCAq
+Lwo+ICt9Owo+ICsKPiArc3RhdGljIGludCBhZHQ3NDEwX3JlYWRfd29yZChzdHJ1Y3QgZGV2aWNl
+ICpkZXYsIHU4IHJlZywgdTE2ICpkYXRhKQo+ICt7Cj4gKwlzdHJ1Y3QgYWR0NzQxMF9kYXRhICpk
+ID0gZGV2X2dldF9kcnZkYXRhKGRldik7Cj4gKwlyZXR1cm4gZC0+b3BzLT5yZWFkX3dvcmQoZGV2
+LCByZWcsIGRhdGEpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGFkdDc0MTBfd3JpdGVfd29yZChz
+dHJ1Y3QgZGV2aWNlICpkZXYsIHU4IHJlZywgdTE2IGRhdGEpCj4gK3sKPiArCXN0cnVjdCBhZHQ3
+NDEwX2RhdGEgKmQgPSBkZXZfZ2V0X2RydmRhdGEoZGV2KTsKPiArCXJldHVybiBkLT5vcHMtPndy
+aXRlX3dvcmQoZGV2LCByZWcsIGRhdGEpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGFkdDc0MTBf
+cmVhZF9ieXRlKHN0cnVjdCBkZXZpY2UgKmRldiwgdTggcmVnLCB1OCAqZGF0YSkKPiArewo+ICsJ
+c3RydWN0IGFkdDc0MTBfZGF0YSAqZCA9IGRldl9nZXRfZHJ2ZGF0YShkZXYpOwo+ICsJcmV0dXJu
+IGQtPm9wcy0+cmVhZF9ieXRlKGRldiwgcmVnLCBkYXRhKTsKPiArfQo+ICsKPiArc3RhdGljIGlu
+dCBhZHQ3NDEwX3dyaXRlX2J5dGUoc3RydWN0IGRldmljZSAqZGV2LCB1OCByZWcsIHU4IGRhdGEp
+Cj4gK3sKPiArCXN0cnVjdCBhZHQ3NDEwX2RhdGEgKmQgPSBkZXZfZ2V0X2RydmRhdGEoZGV2KTsK
+PiArCXJldHVybiBkLT5vcHMtPndyaXRlX2J5dGUoZGV2LCByZWcsIGRhdGEpOwo+ICt9Cj4gKwo+
+ICtzdGF0aWMgY29uc3QgdTggQURUNzQxMF9SRUdfVEVNUFs0XSA9IHsKPiArCUFEVDc0MTBfVEVN
+UEVSQVRVUkUsCQkvKiBpbnB1dCAqLwo+ICsJQURUNzQxMF9UX0FMQVJNX0hJR0gsCQkvKiBoaWdo
+ICovCj4gKwlBRFQ3NDEwX1RfQUxBUk1fTE9XLAkJLyogbG93ICovCj4gKwlBRFQ3NDEwX1RfQ1JJ
+VCwJCQkvKiBjcml0aWNhbCAqLwo+ICt9Owo+ICsKPiArLyoKPiArICogYWR0NzQxMCByZWdpc3Rl
+ciBhY2Nlc3MgYnkgSTJDCj4gKyAqLwo+ICtzdGF0aWMgaW50IGFkdDc0MTBfdGVtcF9yZWFkeShz
+dHJ1Y3QgZGV2aWNlICpkZXYpCj4gK3sKPiArCWludCBpLCByZXQ7Cj4gKwl1OCBzdGF0dXM7Cj4g
+Kwo+ICsJZm9yIChpID0gMDsgaSA8IDY7IGkrKykgewo+ICsJCXJldCA9IGFkdDc0MTBfcmVhZF9i
+eXRlKGRldiwgQURUNzQxMF9TVEFUVVMsICZzdGF0dXMpOwo+ICsJCWlmIChyZXQpCj4gKwkJCXJl
+dHVybiByZXQ7Cj4gKwkJaWYgKCEoc3RhdHVzICYgQURUNzQxMF9TVEFUX05PVF9SRFkpKQo+ICsJ
+CQlyZXR1cm4gMDsKPiArCQltc2xlZXAoNjApOwo+ICsJfQo+ICsJcmV0dXJuIC1FVElNRURPVVQ7
+Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgYWR0NzQxMF91cGRhdGVfdGVtcChzdHJ1Y3QgZGV2aWNl
+ICpkZXYpCj4gK3sKPiArCXN0cnVjdCBhZHQ3NDEwX2RhdGEgKmRhdGEgPSBkZXZfZ2V0X2RydmRh
+dGEoZGV2KTsKPiArCWludCByZXQgPSAwOwo+ICsKPiArCW11dGV4X2xvY2soJmRhdGEtPnVwZGF0
+ZV9sb2NrKTsKPiArCj4gKwlpZiAodGltZV9hZnRlcihqaWZmaWVzLCBkYXRhLT5sYXN0X3VwZGF0
+ZWQgKyBIWiArIEhaIC8gMikKPiArCSAgICB8fCAhZGF0YS0+dmFsaWQpIHsKPiArCj4gKwkJZGV2
+X2RiZyhkZXYsICJTdGFydGluZyB1cGRhdGVcbiIpOwo+ICsKPiArCQlyZXQgPSBhZHQ3NDEwX3Rl
+bXBfcmVhZHkoZGV2KTsgLyogY2hlY2sgZm9yIG5ldyB2YWx1ZSAqLwo+ICsJCWlmIChyZXQpCj4g
+KwkJCWdvdG8gYWJvcnQ7Cj4gKwo+ICsJCXJldCA9IGFkdDc0MTBfcmVhZF93b3JkKGRldiwgQURU
+NzQxMF9SRUdfVEVNUFswXSwKPiArCQkJCQkmZGF0YS0+dGVtcFswXSk7Cj4gKwkJaWYgKHJldCkg
+ewo+ICsJCQlkZXZfZGJnKGRldiwgIkZhaWxlZCB0byByZWFkIHZhbHVlOiByZWcgJWQsIGVycm9y
+ICVkXG4iLAo+ICsJCQkJQURUNzQxMF9SRUdfVEVNUFswXSwgcmV0KTsKPiArCQkJZ290byBhYm9y
+dDsKPiArCQl9Cj4gKwkJZGF0YS0+bGFzdF91cGRhdGVkID0gamlmZmllczsKPiArCQlkYXRhLT52
+YWxpZCA9IHRydWU7Cj4gKwl9Cj4gKwo+ICthYm9ydDoKPiArCW11dGV4X3VubG9jaygmZGF0YS0+
+dXBkYXRlX2xvY2spOwo+ICsJcmV0dXJuIHJldDsKPiArfQo+ICsKPiArc3RhdGljIGludCBhZHQ3
+NDEwX2ZpbGxfY2FjaGUoc3RydWN0IGRldmljZSAqZGV2KQo+ICt7Cj4gKwlzdHJ1Y3QgYWR0NzQx
+MF9kYXRhICpkYXRhID0gZGV2X2dldF9kcnZkYXRhKGRldik7Cj4gKwlpbnQgcmV0Owo+ICsJaW50
+IGk7Cj4gKwo+ICsJZm9yIChpID0gMTsgaSA8IEFSUkFZX1NJWkUoZGF0YS0+dGVtcCk7IGkrKykg
+ewo+ICsJCXJldCA9IGFkdDc0MTBfcmVhZF93b3JkKGRldiwgQURUNzQxMF9SRUdfVEVNUFtpXSwK
+PiArCQkJCQkmZGF0YS0+dGVtcFtpXSk7Cj4gKwkJaWYgKHJldCkgewo+ICsJCQlkZXZfZGJnKGRl
+diwgIkZhaWxlZCB0byByZWFkIHZhbHVlOiByZWcgJWQsIGVycm9yICVkXG4iLAo+ICsJCQkJQURU
+NzQxMF9SRUdfVEVNUFswXSwgcmV0KTsKPiArCQkJcmV0dXJuIHJldDsKPiArCQl9Cj4gKwl9Cj4g
+Kwo+ICsJcmV0ID0gYWR0NzQxMF9yZWFkX2J5dGUoZGV2LCBBRFQ3NDEwX1RfSFlTVCwgJmRhdGEt
+Pmh5c3QpOwo+ICsJaWYgKHJldCkgewo+ICsJCWRldl9kYmcoZGV2LCAiRmFpbGVkIHRvIHJlYWQg
+dmFsdWU6IHJlZyAlZCwgZXJyb3IgJWRcbiIsCj4gKwkJCQlBRFQ3NDEwX1RfSFlTVCwgcmV0KTsK
+PiArCQlyZXR1cm4gcmV0Owo+ICsJfQo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICtzdGF0
+aWMgczE2IEFEVDc0MTBfVEVNUF9UT19SRUcobG9uZyB0ZW1wKQo+ICt7Cj4gKwlyZXR1cm4gRElW
+X1JPVU5EX0NMT1NFU1QoY2xhbXBfdmFsKHRlbXAsIEFEVDc0MTBfVEVNUF9NSU4sCj4gKwkJCQkJ
+ICAgICAgIEFEVDc0MTBfVEVNUF9NQVgpICogMTI4LCAxMDAwKTsKPiArfQo+ICsKPiArc3RhdGlj
+IGludCBBRFQ3NDEwX1JFR19UT19URU1QKHN0cnVjdCBhZHQ3NDEwX2RhdGEgKmRhdGEsIHMxNiBy
+ZWcpCj4gK3sKPiArCS8qIGluIDEzIGJpdCBtb2RlLCBiaXRzIDAtMiBhcmUgc3RhdHVzIGZsYWdz
+IC0gbWFzayB0aGVtIG91dCAqLwo+ICsJaWYgKCEoZGF0YS0+Y29uZmlnICYgQURUNzQxMF9SRVNP
+TFVUSU9OKSkKPiArCQlyZWcgJj0gQURUNzQxMF9UMTNfVkFMVUVfTUFTSzsKPiArCS8qCj4gKwkg
+KiB0ZW1wZXJhdHVyZSBpcyBzdG9yZWQgaW4gdHdvcyBjb21wbGVtZW50IGZvcm1hdCwgaW4gc3Rl
+cHMgb2YKPiArCSAqIDEvMTI4wrBDCj4gKwkgKi8KPiArCXJldHVybiBESVZfUk9VTkRfQ0xPU0VT
+VChyZWcgKiAxMDAwLCAxMjgpOwo+ICt9Cj4gKwo+ICsvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
+LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi8KPiArCj4g
+Ky8qIHN5c2ZzIGF0dHJpYnV0ZXMgZm9yIGh3bW9uICovCj4gKwo+ICtzdGF0aWMgc3NpemVfdCBh
+ZHQ3NDEwX3Nob3dfdGVtcChzdHJ1Y3QgZGV2aWNlICpkZXYsCj4gKwkJCQkgc3RydWN0IGRldmlj
+ZV9hdHRyaWJ1dGUgKmRhLCBjaGFyICpidWYpCj4gK3sKPiArCXN0cnVjdCBzZW5zb3JfZGV2aWNl
+X2F0dHJpYnV0ZSAqYXR0ciA9IHRvX3NlbnNvcl9kZXZfYXR0cihkYSk7Cj4gKwlzdHJ1Y3QgYWR0
+NzQxMF9kYXRhICpkYXRhID0gZGV2X2dldF9kcnZkYXRhKGRldik7Cj4gKwo+ICsKPiArCWlmIChh
+dHRyLT5pbmRleCA9PSAwKSB7Cj4gKwkJaW50IHJldDsKPiArCj4gKwkJcmV0ID0gYWR0NzQxMF91
+cGRhdGVfdGVtcChkZXYpOwo+ICsJCWlmIChyZXQpCj4gKwkJCXJldHVybiByZXQ7Cj4gKwl9Cj4g
+Kwo+ICsJcmV0dXJuIHNwcmludGYoYnVmLCAiJWRcbiIsIEFEVDc0MTBfUkVHX1RPX1RFTVAoZGF0
+YSwKPiArCQkgICAgICAgZGF0YS0+dGVtcFthdHRyLT5pbmRleF0pKTsKPiArfQo+ICsKPiArc3Rh
+dGljIHNzaXplX3QgYWR0NzQxMF9zZXRfdGVtcChzdHJ1Y3QgZGV2aWNlICpkZXYsCj4gKwkJCQlz
+dHJ1Y3QgZGV2aWNlX2F0dHJpYnV0ZSAqZGEsCj4gKwkJCQljb25zdCBjaGFyICpidWYsIHNpemVf
+dCBjb3VudCkKPiArewo+ICsJc3RydWN0IHNlbnNvcl9kZXZpY2VfYXR0cmlidXRlICphdHRyID0g
+dG9fc2Vuc29yX2Rldl9hdHRyKGRhKTsKPiArCXN0cnVjdCBhZHQ3NDEwX2RhdGEgKmRhdGEgPSBk
+ZXZfZ2V0X2RydmRhdGEoZGV2KTsKPiArCWludCBuciA9IGF0dHItPmluZGV4Owo+ICsJbG9uZyB0
+ZW1wOwo+ICsJaW50IHJldDsKPiArCj4gKwlyZXQgPSBrc3RydG9sKGJ1ZiwgMTAsICZ0ZW1wKTsK
+PiArCWlmIChyZXQpCj4gKwkJcmV0dXJuIHJldDsKPiArCj4gKwltdXRleF9sb2NrKCZkYXRhLT51
+cGRhdGVfbG9jayk7Cj4gKwlkYXRhLT50ZW1wW25yXSA9IEFEVDc0MTBfVEVNUF9UT19SRUcodGVt
+cCk7Cj4gKwlyZXQgPSBhZHQ3NDEwX3dyaXRlX3dvcmQoZGV2LCBBRFQ3NDEwX1JFR19URU1QW25y
+XSwgZGF0YS0+dGVtcFtucl0pOwo+ICsJaWYgKHJldCkKPiArCQljb3VudCA9IHJldDsKPiArCW11
+dGV4X3VubG9jaygmZGF0YS0+dXBkYXRlX2xvY2spOwo+ICsJcmV0dXJuIGNvdW50Owo+ICt9Cj4g
+Kwo+ICtzdGF0aWMgc3NpemVfdCBhZHQ3NDEwX3Nob3dfdF9oeXN0KHN0cnVjdCBkZXZpY2UgKmRl
+diwKPiArCQkJCSAgIHN0cnVjdCBkZXZpY2VfYXR0cmlidXRlICpkYSwKPiArCQkJCSAgIGNoYXIg
+KmJ1ZikKPiArewo+ICsJc3RydWN0IHNlbnNvcl9kZXZpY2VfYXR0cmlidXRlICphdHRyID0gdG9f
+c2Vuc29yX2Rldl9hdHRyKGRhKTsKPiArCXN0cnVjdCBhZHQ3NDEwX2RhdGEgKmRhdGEgPSBkZXZf
+Z2V0X2RydmRhdGEoZGV2KTsKPiArCWludCBuciA9IGF0dHItPmluZGV4Owo+ICsJaW50IGh5c3Q7
+Cj4gKwo+ICsJaHlzdCA9IChkYXRhLT5oeXN0ICYgQURUNzQxMF9UX0hZU1RfTUFTSykgKiAxMDAw
+Owo+ICsKPiArCS8qCj4gKwkgKiBoeXN0ZXJlc2lzIGlzIHN0b3JlZCBhcyBhIDQgYml0IG9mZnNl
+dCBpbiB0aGUgZGV2aWNlLCBjb252ZXJ0IGl0Cj4gKwkgKiB0byBhbiBhYnNvbHV0ZSB2YWx1ZQo+
+ICsJICovCj4gKwlpZiAobnIgPT0gMikJLyogbWluIGhhcyBwb3NpdGl2ZSBvZmZzZXQsIG90aGVy
+cyBoYXZlIG5lZ2F0aXZlICovCj4gKwkJaHlzdCA9IC1oeXN0Owo+ICsJcmV0dXJuIHNwcmludGYo
+YnVmLCAiJWRcbiIsCj4gKwkJICAgICAgIEFEVDc0MTBfUkVHX1RPX1RFTVAoZGF0YSwgZGF0YS0+
+dGVtcFtucl0pIC0gaHlzdCk7Cj4gK30KPiArCj4gK3N0YXRpYyBzc2l6ZV90IGFkdDc0MTBfc2V0
+X3RfaHlzdChzdHJ1Y3QgZGV2aWNlICpkZXYsCj4gKwkJCQkgIHN0cnVjdCBkZXZpY2VfYXR0cmli
+dXRlICpkYSwKPiArCQkJCSAgY29uc3QgY2hhciAqYnVmLCBzaXplX3QgY291bnQpCj4gK3sKPiAr
+CXN0cnVjdCBhZHQ3NDEwX2RhdGEgKmRhdGEgPSBkZXZfZ2V0X2RydmRhdGEoZGV2KTsKPiArCWlu
+dCBsaW1pdCwgcmV0Owo+ICsJbG9uZyBoeXN0Owo+ICsKPiArCXJldCA9IGtzdHJ0b2woYnVmLCAx
+MCwgJmh5c3QpOwo+ICsJaWYgKHJldCkKPiArCQlyZXR1cm4gcmV0Owo+ICsJLyogY29udmVydCBh
+YnNvbHV0ZSBoeXN0ZXJlc2lzIHZhbHVlIHRvIGEgNCBiaXQgZGVsdGEgdmFsdWUgKi8KPiArCWxp
+bWl0ID0gQURUNzQxMF9SRUdfVE9fVEVNUChkYXRhLCBkYXRhLT50ZW1wWzFdKTsKPiArCWh5c3Qg
+PSBjbGFtcF92YWwoaHlzdCwgQURUNzQxMF9URU1QX01JTiwgQURUNzQxMF9URU1QX01BWCk7Cj4g
+KwlkYXRhLT5oeXN0ID0gY2xhbXBfdmFsKERJVl9ST1VORF9DTE9TRVNUKGxpbWl0IC0gaHlzdCwg
+MTAwMCksCj4gKwkJCQkgICAwLCBBRFQ3NDEwX1RfSFlTVF9NQVNLKTsKPiArCXJldCA9IGFkdDc0
+MTBfd3JpdGVfYnl0ZShkZXYsIEFEVDc0MTBfVF9IWVNULCBkYXRhLT5oeXN0KTsKPiArCWlmIChy
+ZXQpCj4gKwkJcmV0dXJuIHJldDsKPiArCj4gKwlyZXR1cm4gY291bnQ7Cj4gK30KPiArCj4gK3N0
+YXRpYyBzc2l6ZV90IGFkdDc0MTBfc2hvd19hbGFybShzdHJ1Y3QgZGV2aWNlICpkZXYsCj4gKwkJ
+CQkgIHN0cnVjdCBkZXZpY2VfYXR0cmlidXRlICpkYSwKPiArCQkJCSAgY2hhciAqYnVmKQo+ICt7
+Cj4gKwlzdHJ1Y3Qgc2Vuc29yX2RldmljZV9hdHRyaWJ1dGUgKmF0dHIgPSB0b19zZW5zb3JfZGV2
+X2F0dHIoZGEpOwo+ICsJdTggc3RhdHVzOwo+ICsJaW50IHJldDsKPiArCj4gKwlyZXQgPSBhZHQ3
+NDEwX3JlYWRfYnl0ZShkZXYsIEFEVDc0MTBfU1RBVFVTLCAmc3RhdHVzKTsKPiArCWlmIChyZXQg
+PCAwKQo+ICsJCXJldHVybiByZXQ7Cj4gKwo+ICsJcmV0dXJuIHNwcmludGYoYnVmLCAiJWRcbiIs
+ICEhKHN0YXR1cyAmIGF0dHItPmluZGV4KSk7Cj4gK30KPiArCj4gK3N0YXRpYyBzc2l6ZV90IGFk
+dDc0MTBfc2hvd19uYW1lKHN0cnVjdCBkZXZpY2UgKmRldiwKPiArCQkJCSAgc3RydWN0IGRldmlj
+ZV9hdHRyaWJ1dGUgKmRhLCBjaGFyICpidWYpCj4gK3sKPiArCXN0cnVjdCBhZHQ3NDEwX2RhdGEg
+KmRhdGEgPSBkZXZfZ2V0X2RydmRhdGEoZGV2KTsKPiArCj4gKwlyZXR1cm4gc3ByaW50ZihidWYs
+ICIlc1xuIiwgZGF0YS0+bmFtZSk7Cj4gK30KPiArCj4gK3N0YXRpYyBTRU5TT1JfREVWSUNFX0FU
+VFIodGVtcDFfaW5wdXQsIFNfSVJVR08sIGFkdDc0MTBfc2hvd190ZW1wLCBOVUxMLCAwKTsKPiAr
+c3RhdGljIFNFTlNPUl9ERVZJQ0VfQVRUUih0ZW1wMV9tYXgsIFNfSVdVU1IgfCBTX0lSVUdPLAo+
+ICsJCQkgIGFkdDc0MTBfc2hvd190ZW1wLCBhZHQ3NDEwX3NldF90ZW1wLCAxKTsKPiArc3RhdGlj
+IFNFTlNPUl9ERVZJQ0VfQVRUUih0ZW1wMV9taW4sIFNfSVdVU1IgfCBTX0lSVUdPLAo+ICsJCQkg
+IGFkdDc0MTBfc2hvd190ZW1wLCBhZHQ3NDEwX3NldF90ZW1wLCAyKTsKPiArc3RhdGljIFNFTlNP
+Ul9ERVZJQ0VfQVRUUih0ZW1wMV9jcml0LCBTX0lXVVNSIHwgU19JUlVHTywKPiArCQkJICBhZHQ3
+NDEwX3Nob3dfdGVtcCwgYWR0NzQxMF9zZXRfdGVtcCwgMyk7Cj4gK3N0YXRpYyBTRU5TT1JfREVW
+SUNFX0FUVFIodGVtcDFfbWF4X2h5c3QsIFNfSVdVU1IgfCBTX0lSVUdPLAo+ICsJCQkgIGFkdDc0
+MTBfc2hvd190X2h5c3QsIGFkdDc0MTBfc2V0X3RfaHlzdCwgMSk7Cj4gK3N0YXRpYyBTRU5TT1Jf
+REVWSUNFX0FUVFIodGVtcDFfbWluX2h5c3QsIFNfSVJVR08sCj4gKwkJCSAgYWR0NzQxMF9zaG93
+X3RfaHlzdCwgTlVMTCwgMik7Cj4gK3N0YXRpYyBTRU5TT1JfREVWSUNFX0FUVFIodGVtcDFfY3Jp
+dF9oeXN0LCBTX0lSVUdPLAo+ICsJCQkgIGFkdDc0MTBfc2hvd190X2h5c3QsIE5VTEwsIDMpOwo+
+ICtzdGF0aWMgU0VOU09SX0RFVklDRV9BVFRSKHRlbXAxX21pbl9hbGFybSwgU19JUlVHTywgYWR0
+NzQxMF9zaG93X2FsYXJtLAo+ICsJCQkgIE5VTEwsIEFEVDc0MTBfU1RBVF9UX0xPVyk7Cj4gK3N0
+YXRpYyBTRU5TT1JfREVWSUNFX0FUVFIodGVtcDFfbWF4X2FsYXJtLCBTX0lSVUdPLCBhZHQ3NDEw
+X3Nob3dfYWxhcm0sCj4gKwkJCSAgTlVMTCwgQURUNzQxMF9TVEFUX1RfSElHSCk7Cj4gK3N0YXRp
+YyBTRU5TT1JfREVWSUNFX0FUVFIodGVtcDFfY3JpdF9hbGFybSwgU19JUlVHTywgYWR0NzQxMF9z
+aG93X2FsYXJtLAo+ICsJCQkgIE5VTEwsIEFEVDc0MTBfU1RBVF9UX0NSSVQpOwo+ICtzdGF0aWMg
+REVWSUNFX0FUVFIobmFtZSwgU19JUlVHTywgYWR0NzQxMF9zaG93X25hbWUsIE5VTEwpOwo+ICsK
+PiArc3RhdGljIHN0cnVjdCBhdHRyaWJ1dGUgKmFkdDc0MTBfYXR0cmlidXRlc1tdID0gewo+ICsJ
+JnNlbnNvcl9kZXZfYXR0cl90ZW1wMV9pbnB1dC5kZXZfYXR0ci5hdHRyLAo+ICsJJnNlbnNvcl9k
+ZXZfYXR0cl90ZW1wMV9tYXguZGV2X2F0dHIuYXR0ciwKPiArCSZzZW5zb3JfZGV2X2F0dHJfdGVt
+cDFfbWluLmRldl9hdHRyLmF0dHIsCj4gKwkmc2Vuc29yX2Rldl9hdHRyX3RlbXAxX2NyaXQuZGV2
+X2F0dHIuYXR0ciwKPiArCSZzZW5zb3JfZGV2X2F0dHJfdGVtcDFfbWF4X2h5c3QuZGV2X2F0dHIu
+YXR0ciwKPiArCSZzZW5zb3JfZGV2X2F0dHJfdGVtcDFfbWluX2h5c3QuZGV2X2F0dHIuYXR0ciwK
+PiArCSZzZW5zb3JfZGV2X2F0dHJfdGVtcDFfY3JpdF9oeXN0LmRldl9hdHRyLmF0dHIsCj4gKwkm
+c2Vuc29yX2Rldl9hdHRyX3RlbXAxX21pbl9hbGFybS5kZXZfYXR0ci5hdHRyLAo+ICsJJnNlbnNv
+cl9kZXZfYXR0cl90ZW1wMV9tYXhfYWxhcm0uZGV2X2F0dHIuYXR0ciwKPiArCSZzZW5zb3JfZGV2
+X2F0dHJfdGVtcDFfY3JpdF9hbGFybS5kZXZfYXR0ci5hdHRyLAo+ICsJTlVMTAo+ICt9Owo+ICsK
+PiArc3RhdGljIGNvbnN0IHN0cnVjdCBhdHRyaWJ1dGVfZ3JvdXAgYWR0NzQxMF9ncm91cCA9IHsK
+PiArCS5hdHRycyA9IGFkdDc0MTBfYXR0cmlidXRlcywKPiArfTsKPiArCj4gK2ludCBhZHQ3NDEw
+X3Byb2JlKHN0cnVjdCBkZXZpY2UgKmRldiwgY29uc3QgY2hhciAqbmFtZSwKPiArCWNvbnN0IHN0
+cnVjdCBhZHQ3NDEwX29wcyAqb3BzKQo+ICt7Cj4gKwlzdHJ1Y3QgYWR0NzQxMF9kYXRhICpkYXRh
+Owo+ICsJaW50IHJldDsKPiArCj4gKwlkYXRhID0gZGV2bV9remFsbG9jKGRldiwgc2l6ZW9mKHN0
+cnVjdCBhZHQ3NDEwX2RhdGEpLAo+ICsJCQkgICAgR0ZQX0tFUk5FTCk7Cj4gKwlpZiAoIWRhdGEp
+Cj4gKwkJcmV0dXJuIC1FTk9NRU07Cj4gKwo+ICsJZGF0YS0+b3BzID0gb3BzOwo+ICsJZGF0YS0+
+bmFtZSA9IG5hbWU7Cj4gKwo+ICsJZGV2X3NldF9kcnZkYXRhKGRldiwgZGF0YSk7Cj4gKwltdXRl
+eF9pbml0KCZkYXRhLT51cGRhdGVfbG9jayk7Cj4gKwo+ICsJLyogY29uZmlndXJlIGFzIHNwZWNp
+ZmllZCAqLwo+ICsJcmV0ID0gYWR0NzQxMF9yZWFkX2J5dGUoZGV2LCBBRFQ3NDEwX0NPTkZJRywg
+JmRhdGEtPm9sZGNvbmZpZyk7Cj4gKwlpZiAocmV0IDwgMCkgewo+ICsJCWRldl9kYmcoZGV2LCAi
+Q2FuJ3QgcmVhZCBjb25maWc/ICVkXG4iLCByZXQpOwo+ICsJCXJldHVybiByZXQ7Cj4gKwl9Cj4g
+KwkvKgo+ICsJICogU2V0IHRvIDE2IGJpdCByZXNvbHV0aW9uLCBjb250aW5vdXMgY29udmVyc2lv
+biBhbmQgY29tcGFyYXRvciBtb2RlLgo+ICsJICovCj4gKwlkYXRhLT5jb25maWcgPSBkYXRhLT5v
+bGRjb25maWc7Cj4gKwlkYXRhLT5jb25maWcgJj0gfkFEVDc0MTBfTU9ERV9NQVNLOwo+ICsJZGF0
+YS0+Y29uZmlnIHw9IEFEVDc0MTBfRlVMTCB8IEFEVDc0MTBfUkVTT0xVVElPTiB8IEFEVDc0MTBf
+RVZFTlRfTU9ERTsKPiArCWlmIChkYXRhLT5jb25maWcgIT0gZGF0YS0+b2xkY29uZmlnKSB7Cj4g
+KwkJcmV0ID0gYWR0NzQxMF93cml0ZV9ieXRlKGRldiwgQURUNzQxMF9DT05GSUcsIGRhdGEtPmNv
+bmZpZyk7Cj4gKwkJaWYgKHJldCkKPiArCQkJcmV0dXJuIHJldDsKPiArCX0KPiArCWRldl9kYmco
+ZGV2LCAiQ29uZmlnICUwMnhcbiIsIGRhdGEtPmNvbmZpZyk7Cj4gKwo+ICsJcmV0ID0gYWR0NzQx
+MF9maWxsX2NhY2hlKGRldik7Cj4gKwlpZiAocmV0KQo+ICsJCWdvdG8gZXhpdF9yZXN0b3JlOwo+
+ICsKPiArCS8qIFJlZ2lzdGVyIHN5c2ZzIGhvb2tzICovCj4gKwlyZXQgPSBzeXNmc19jcmVhdGVf
+Z3JvdXAoJmRldi0+a29iaiwgJmFkdDc0MTBfZ3JvdXApOwo+ICsJaWYgKHJldCkKPiArCQlnb3Rv
+IGV4aXRfcmVzdG9yZTsKPiArCj4gKwkvKgo+ICsJICogVGhlIEkyQyBkZXZpY2Ugd2lsbCBhbHJl
+YWR5IGhhdmUgaXQncyBvd24gJ25hbWUnIGF0dHJpYnV0ZSwgYnV0IGZvcgo+ICsJICogdGhlIFNQ
+SSBkZXZpY2Ugd2UgbmVlZCB0byByZWdpc3RlciBpdC4gbmFtZSB3aWxsIG9ubHkgYmUgbm9uIE5V
+TEwgaWYKPiArCSAqIHRoZSBkZXZpY2UgZG9lc24ndCByZWdpc3RlciB0aGUgJ25hbWUnIGF0dHJp
+YnV0ZSBvbiBpdHMgb3duLgo+ICsJICovCj4gKwlpZiAobmFtZSkgewo+ICsJCXJldCA9IGRldmlj
+ZV9jcmVhdGVfZmlsZShkZXYsICZkZXZfYXR0cl9uYW1lKTsKPiArCQlpZiAocmV0KQo+ICsJCQln
+b3RvIGV4aXRfcmVtb3ZlOwo+ICsJfQo+ICsKPiArCWRhdGEtPmh3bW9uX2RldiA9IGh3bW9uX2Rl
+dmljZV9yZWdpc3RlcihkZXYpOwo+ICsJaWYgKElTX0VSUihkYXRhLT5od21vbl9kZXYpKSB7Cj4g
+KwkJcmV0ID0gUFRSX0VSUihkYXRhLT5od21vbl9kZXYpOwo+ICsJCWdvdG8gZXhpdF9yZW1vdmVf
+bmFtZTsKPiArCX0KPiArCj4gKwlyZXR1cm4gMDsKPiArCj4gK2V4aXRfcmVtb3ZlX25hbWU6Cj4g
+KwlpZiAobmFtZSkKPiArCQlkZXZpY2VfcmVtb3ZlX2ZpbGUoZGV2LCAmZGV2X2F0dHJfbmFtZSk7
+Cj4gK2V4aXRfcmVtb3ZlOgo+ICsJc3lzZnNfcmVtb3ZlX2dyb3VwKCZkZXYtPmtvYmosICZhZHQ3
+NDEwX2dyb3VwKTsKPiArZXhpdF9yZXN0b3JlOgo+ICsJYWR0NzQxMF93cml0ZV9ieXRlKGRldiwg
+QURUNzQxMF9DT05GSUcsIGRhdGEtPm9sZGNvbmZpZyk7Cj4gKwlyZXR1cm4gcmV0Owo+ICt9Cj4g
+K0VYUE9SVF9TWU1CT0xfR1BMKGFkdDc0MTBfcHJvYmUpOwo+ICsKPiAraW50IGFkdDc0MTBfcmVt
+b3ZlKHN0cnVjdCBkZXZpY2UgKmRldikKPiArewo+ICsJc3RydWN0IGFkdDc0MTBfZGF0YSAqZGF0
+YSA9IGRldl9nZXRfZHJ2ZGF0YShkZXYpOwo+ICsKPiArCWh3bW9uX2RldmljZV91bnJlZ2lzdGVy
+KGRhdGEtPmh3bW9uX2Rldik7Cj4gKwlpZiAoZGF0YS0+bmFtZSkKPiArCQlkZXZpY2VfcmVtb3Zl
+X2ZpbGUoZGV2LCAmZGV2X2F0dHJfbmFtZSk7Cj4gKwlzeXNmc19yZW1vdmVfZ3JvdXAoJmRldi0+
+a29iaiwgJmFkdDc0MTBfZ3JvdXApOwo+ICsJaWYgKGRhdGEtPm9sZGNvbmZpZyAhPSBkYXRhLT5j
+b25maWcpCj4gKwkJYWR0NzQxMF93cml0ZV9ieXRlKGRldiwgQURUNzQxMF9DT05GSUcsCj4gKwkJ
+CQkJICBkYXRhLT5vbGRjb25maWcpOwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArRVhQT1JUX1NZTUJP
+TF9HUEwoYWR0NzQxMF9yZW1vdmUpOwo+ICsKPiArI2lmZGVmIENPTkZJR19QTV9TTEVFUAo+ICsK
+PiArc3RhdGljIGludCBhZHQ3NDEwX3N1c3BlbmQoc3RydWN0IGRldmljZSAqZGV2KQo+ICt7Cj4g
+KwlzdHJ1Y3QgYWR0NzQxMF9kYXRhICpkYXRhID0gZGV2X2dldF9kcnZkYXRhKGRldik7Cj4gKwo+
+ICsJcmV0dXJuIGFkdDc0MTBfd3JpdGVfYnl0ZShkZXYsIEFEVDc0MTBfQ09ORklHLAo+ICsJCWRh
+dGEtPmNvbmZpZyB8IEFEVDc0MTBfUEQpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGFkdDc0MTBf
+cmVzdW1lKHN0cnVjdCBkZXZpY2UgKmRldikKPiArewo+ICsJc3RydWN0IGFkdDc0MTBfZGF0YSAq
+ZGF0YSA9IGRldl9nZXRfZHJ2ZGF0YShkZXYpOwo+ICsKPiArCXJldHVybiBhZHQ3NDEwX3dyaXRl
+X2J5dGUoZGV2LCBBRFQ3NDEwX0NPTkZJRywgZGF0YS0+Y29uZmlnKTsKPiArfQo+ICsKPiArU0lN
+UExFX0RFVl9QTV9PUFMoYWR0NzQxMF9kZXZfcG1fb3BzLCBhZHQ3NDEwX3N1c3BlbmQsIGFkdDc0
+MTBfcmVzdW1lKTsKPiArRVhQT1JUX1NZTUJPTF9HUEwoYWR0NzQxMF9kZXZfcG1fb3BzKTsKPiAr
+Cj4gKyNlbmRpZiAvKiBDT05GSUdfUE1fU0xFRVAgKi8KPiArCj4gK01PRFVMRV9BVVRIT1IoIkhh
+cnRtdXQgS25hYWNrIik7Cj4gK01PRFVMRV9ERVNDUklQVElPTigiQURUNzQxMCBkcml2ZXIiKTsK
+VGhpcyBkZXNjcmlwdGlvbiBkb2VzIG5vdCBzZWVtIGFwcHJvcHJpYXRlIGFueSBsb25nZXIuCj4g
+K01PRFVMRV9MSUNFTlNFKCJHUEwiKTsKPC4uLj4KCgpfX19fX19fX19fX19fX19fX19fX19fX19f
+X19fX19fX19fX19fX19fX19fX19fXwpsbS1zZW5zb3JzIG1haWxpbmcgbGlzdApsbS1zZW5zb3Jz
+QGxtLXNlbnNvcnMub3JnCmh0dHA6Ly9saXN0cy5sbS1zZW5zb3JzLm9yZy9tYWlsbWFuL2xpc3Rp
+bmZvL2xtLXNlbnNvcnM
diff --git a/a/content_digest b/N1/content_digest
index 6ea4d58..23c5f60 100644
--- a/a/content_digest
+++ b/N1/content_digest
@@ -1,8 +1,8 @@
  "ref\01360947438-2550-1-git-send-email-lars@metafoo.de\0"
  "ref\01360947438-2550-7-git-send-email-lars@metafoo.de\0"
  "From\0Hartmut Knaack <knaack.h@gmx.de>\0"
- "Subject\0Re: [PATCH 7/9] hwmon: (adt7410) Add support for the adt7310/adt7320\0"
- "Date\0Fri, 15 Feb 2013 21:05:48 +0100\0"
+ "Subject\0Re: [lm-sensors] [PATCH 7/9] hwmon: (adt7410) Add support for the adt7310/adt7320\0"
+ "Date\0Fri, 15 Feb 2013 20:05:48 +0000\0"
  "To\0Lars-Peter Clausen <lars@metafoo.de>\0"
  "Cc\0Jean Delvare <khali@linux-fr.org>"
   Guenter Roeck <linux@roeck-us.net>
@@ -11,660 +11,338 @@
  " linux-iio@vger.kernel.org\0"
  "\00:1\0"
  "b\0"
- "I had a quick look over your patches and found some minor typo, see below. I will apply all the patches to see the result.\n"
- "Also keep in mind to add some changes to Documentation/hwmon/adt7410 (and add an adt7310 as well?).\n"
- "\n"
- "Lars-Peter Clausen schrieb:\n"
- "<...>\n"
- "> diff --git a/drivers/hwmon/adt7310.c b/drivers/hwmon/adt7310.c\n"
- "> new file mode 100644\n"
- "> index 0000000..0483e6c\n"
- "> --- /dev/null\n"
- "> +++ b/drivers/hwmon/adt7310.c\n"
- "> @@ -0,0 +1,160 @@\n"
- "> +/*\n"
- "> + * ADT7310/ADT7310 digital temperature sensor driver\n"
- "> + *\n"
- "> + * Copyright 2010-2013 Analog Devices Inc.\n"
- "> + *   Author: Lars-Peter Clausen <lars@metafoo.de>\n"
- "> + *\n"
- "> + * Licensed under the GPL-2 or later.\n"
- "> + */\n"
- "> +\n"
- "> +#include <linux/module.h>\n"
- "> +#include <linux/init.h>\n"
- "> +#include <linux/spi/spi.h>\n"
- "> +\n"
- "> +#include \"adt7x10.h\"\n"
- "> +\n"
- "> +static const u8 adt7371_reg_table[] = {\n"
- "> +\t[ADT7410_TEMPERATURE]   = ADT7310_TEMPERATURE,\n"
- "> +\t[ADT7410_STATUS]\t= ADT7310_STATUS,\n"
- "> +\t[ADT7410_CONFIG]\t= ADT7310_CONFIG,\n"
- "> +\t[ADT7410_T_ALARM_HIGH]\t= ADT7310_T_ALARM_HIGH,\n"
- "> +\t[ADT7410_T_ALARM_LOW]\t= ADT7310_T_ALARM_LOW,\n"
- "> +\t[ADT7410_T_CRIT]\t= ADT7310_T_CRIT,\n"
- "> +\t[ADT7410_T_HYST]\t= ADT7310_T_HYST,\n"
- "> +\t[ADT7410_ID]\t\t= ADT7310_ID,\n"
- "> +};\n"
- "Just out of curiousity, whats the reason for the name adt7371 here?\n"
- "> +\n"
- "> +#define ADT7310_CMD_REG_MASK\t\t\t0x28\n"
- "> +#define ADT7310_CMD_REG_OFFSET\t\t\t3\n"
- "> +#define ADT7310_CMD_READ\t\t\t0x40\n"
- "> +#define ADT7310_CMD_CON_READ\t\t\t0x4\n"
- "> +\n"
- "> +#define AD7310_COMMAND(reg) (adt7371_reg_table[(reg)] << ADT7310_CMD_REG_OFFSET)\n"
- "> +\n"
- "> +static int adt7310_spi_read_word(struct device *dev,\n"
- "> +\tu8 reg, u16 *data)\n"
- "> +{\n"
- "> +\tstruct spi_device *spi = to_spi_device(dev);\n"
- "> +\tu8 command = AD7310_COMMAND(reg);\n"
- "> +\tint ret = 0;\n"
- "> +\n"
- "> +\tcommand |= ADT7310_CMD_READ;\n"
- "> +\tret = spi_write(spi, &command, sizeof(command));\n"
- "> +\tif (ret < 0) {\n"
- "> +\t\tdev_err(dev, \"SPI write command error\\n\");\n"
- "> +\t\treturn ret;\n"
- "> +\t}\n"
- "> +\n"
- "> +\tret = spi_read(spi, (u8 *)data, sizeof(*data));\n"
- "> +\tif (ret < 0) {\n"
- "> +\t\tdev_err(dev, \"SPI read word error\\n\");\n"
- "> +\t\treturn ret;\n"
- "> +\t}\n"
- "> +\n"
- "> +\t*data = be16_to_cpu(*data);\n"
- "> +\n"
- "> +\treturn 0;\n"
- "> +}\n"
- "> +\n"
- "> +static int adt7310_spi_write_word(struct device *dev, u8 reg,\n"
- "> +\tu16 data)\n"
- "> +{\n"
- "> +\tstruct spi_device *spi = to_spi_device(dev);\n"
- "> +\tu8 buf[3];\n"
- "> +\tint ret = 0;\n"
- "> +\n"
- "> +\tbuf[0] = AD7310_COMMAND(reg);\n"
- "> +\tbuf[1] = (u8)(data >> 8);\n"
- "> +\tbuf[2] = (u8)(data & 0xFF);\n"
- "> +\n"
- "> +\tret = spi_write(spi, buf, 3);\n"
- "> +\tif (ret < 0) {\n"
- "> +\t\tdev_err(dev, \"SPI write word error\\n\");\n"
- "> +\t\treturn ret;\n"
- "> +\t}\n"
- "> +\n"
- "> +\treturn ret;\n"
- "> +}\n"
- "> +\n"
- "> +static int adt7310_spi_read_byte(struct device *dev, u8 reg,\n"
- "> +\tu8 *data)\n"
- "> +{\n"
- "> +\tstruct spi_device *spi = to_spi_device(dev);\n"
- "> +\tu8 command = AD7310_COMMAND(reg);\n"
- "> +\tint ret = 0;\n"
- "> +\n"
- "> +\tcommand |= ADT7310_CMD_READ;\n"
- "> +\tret = spi_write(spi, &command, sizeof(command));\n"
- "> +\tif (ret < 0) {\n"
- "> +\t\tdev_err(dev, \"SPI write command error\\n\");\n"
- "> +\t\treturn ret;\n"
- "> +\t}\n"
- "> +\n"
- "> +\tret = spi_read(spi, data, sizeof(*data));\n"
- "> +\tif (ret < 0) {\n"
- "> +\t\tdev_err(dev, \"SPI read byte error\\n\");\n"
- "> +\t\treturn ret;\n"
- "> +\t}\n"
- "> +\n"
- "> +\treturn 0;\n"
- "> +}\n"
- "> +\n"
- "> +static int adt7310_spi_write_byte(struct device *dev, u8 reg,\n"
- "> +\tu8 data)\n"
- "> +{\n"
- "> +\tstruct spi_device *spi = to_spi_device(dev);\n"
- "> +\tu8 buf[2];\n"
- "> +\tint ret = 0;\n"
- "> +\n"
- "> +\tbuf[0] = AD7310_COMMAND(reg);\n"
- "> +\tbuf[1] = data;\n"
- "> +\n"
- "> +\tret = spi_write(spi, buf, 2);\n"
- "> +\tif (ret < 0) {\n"
- "> +\t\tdev_err(dev, \"SPI write byte error\\n\");\n"
- "> +\t\treturn ret;\n"
- "> +\t}\n"
- "> +\n"
- "> +\treturn ret;\n"
- "> +}\n"
- "> +\n"
- "> +static const struct adt7410_ops adt7310_spi_ops = {\n"
- "> +\t.read_word = adt7310_spi_read_word,\n"
- "> +\t.write_word = adt7310_spi_write_word,\n"
- "> +\t.read_byte = adt7310_spi_read_byte,\n"
- "> +\t.write_byte = adt7310_spi_write_byte,\n"
- "> +};\n"
- "> +\n"
- "> +static int adt7310_spi_probe(struct spi_device *spi)\n"
- "> +{\n"
- "> +\treturn adt7410_probe(&spi->dev, spi_get_device_id(spi)->name,\n"
- "> +\t\t\t&adt7310_spi_ops);\n"
- "> +}\n"
- "> +\n"
- "> +static int adt7310_spi_remove(struct spi_device *spi)\n"
- "> +{\n"
- "> +\treturn adt7410_remove(&spi->dev);\n"
- "> +}\n"
- "> +\n"
- "> +static const struct spi_device_id adt7310_id[] = {\n"
- "> +\t{ \"adt7310\", 0 },\n"
- "> +\t{ \"adt7320\", 0 },\n"
- "> +\t{}\n"
- "> +};\n"
- "> +MODULE_DEVICE_TABLE(spi, adt7310_id);\n"
- "> +\n"
- "> +static struct spi_driver adt7310_driver = {\n"
- "> +\t.driver = {\n"
- "> +\t\t.name = \"adt7310\",\n"
- "> +\t\t.owner = THIS_MODULE,\n"
- "> +\t\t.pm\t= ADT7410_DEV_PM_OPS,\n"
- "> +\t},\n"
- "> +\t.probe = adt7310_spi_probe,\n"
- "> +\t.remove = adt7310_spi_remove,\n"
- "> +\t.id_table = adt7310_id,\n"
- "> +};\n"
- "> +module_spi_driver(adt7310_driver);\n"
- "> +\n"
- "> +MODULE_AUTHOR(\"Lars-Peter Clausen <lars@metafoo.de>\");\n"
- "> +MODULE_DESCRIPTION(\"ADT7310/ADT7420 driver\");\n"
- "This should be ADT7310/ADT7320, right?\n"
- "> +MODULE_LICENSE(\"GPL\");\n"
- "<...>\n"
- "> --- /dev/null\n"
- "> +++ b/drivers/hwmon/adt7x10.c\n"
- "> @@ -0,0 +1,476 @@\n"
- "> +/*\n"
- "> + * adt7410.c - Part of lm_sensors, Linux kernel modules for hardware\n"
- "> + *\t monitoring\n"
- "> + * This driver handles the ADT7410 and compatible digital temperature sensors.\n"
- "> + * Hartmut Knaack <knaack.h@gmx.de> 2012-07-22\n"
- "> + * based on lm75.c by Frodo Looijaard <frodol@dds.nl>\n"
- "> + * and adt7410.c from iio-staging by Sonic Zhang <sonic.zhang@analog.com>\n"
- "> + *\n"
- "> + * This program is free software; you can redistribute it and/or modify\n"
- "> + * it under the terms of the GNU General Public License as published by\n"
- "> + * the Free Software Foundation; either version 2 of the License, or\n"
- "> + * (at your option) any later version.\n"
- "> + *\n"
- "> + * This program is distributed in the hope that it will be useful,\n"
- "> + * but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
- "> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
- "> + * GNU General Public License for more details.\n"
- "> + *\n"
- "> + * You should have received a copy of the GNU General Public License\n"
- "> + * along with this program; if not, write to the Free Software\n"
- "> + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n"
- "> + */\n"
- "> +\n"
- "> +#include <linux/module.h>\n"
- "> +#include <linux/init.h>\n"
- "> +#include <linux/slab.h>\n"
- "> +#include <linux/jiffies.h>\n"
- "> +#include <linux/hwmon.h>\n"
- "> +#include <linux/hwmon-sysfs.h>\n"
- "> +#include <linux/err.h>\n"
- "> +#include <linux/mutex.h>\n"
- "> +#include <linux/delay.h>\n"
- "> +\n"
- "> +#include \"adt7x10.h\"\n"
- "> +\n"
- "> +/*\n"
- "> + * ADT7410 status\n"
- "> + */\n"
- "> +#define ADT7410_STAT_T_LOW\t\t(1 << 4)\n"
- "> +#define ADT7410_STAT_T_HIGH\t\t(1 << 5)\n"
- "> +#define ADT7410_STAT_T_CRIT\t\t(1 << 6)\n"
- "> +#define ADT7410_STAT_NOT_RDY\t\t(1 << 7)\n"
- "> +\n"
- "> +/*\n"
- "> + * ADT7410 config\n"
- "> + */\n"
- "> +#define ADT7410_FAULT_QUEUE_MASK\t(1 << 0 | 1 << 1)\n"
- "> +#define ADT7410_CT_POLARITY\t\t(1 << 2)\n"
- "> +#define ADT7410_INT_POLARITY\t\t(1 << 3)\n"
- "> +#define ADT7410_EVENT_MODE\t\t(1 << 4)\n"
- "> +#define ADT7410_MODE_MASK\t\t(1 << 5 | 1 << 6)\n"
- "> +#define ADT7410_FULL\t\t\t(0 << 5 | 0 << 6)\n"
- "> +#define ADT7410_PD\t\t\t(1 << 5 | 1 << 6)\n"
- "> +#define ADT7410_RESOLUTION\t\t(1 << 7)\n"
- "> +\n"
- "> +/*\n"
- "> + * ADT7410 masks\n"
- "> + */\n"
- "> +#define ADT7410_T13_VALUE_MASK\t\t\t0xFFF8\n"
- "> +#define ADT7410_T_HYST_MASK\t\t\t0xF\n"
- "> +\n"
- "> +/* straight from the datasheet */\n"
- "> +#define ADT7410_TEMP_MIN (-55000)\n"
- "> +#define ADT7410_TEMP_MAX 150000\n"
- "> +\n"
- "> +/* Each client has this additional data */\n"
- "> +struct adt7410_data {\n"
- "> +\tconst struct adt7410_ops *ops;\n"
- "> +\tconst char\t\t*name;\n"
- "> +\tstruct device\t\t*hwmon_dev;\n"
- "> +\tstruct mutex\t\tupdate_lock;\n"
- "> +\tu8\t\t\tconfig;\n"
- "> +\tu8\t\t\toldconfig;\n"
- "> +\tbool\t\t\tvalid;\t\t/* true if registers valid */\n"
- "> +\tunsigned long\t\tlast_updated;\t/* In jiffies */\n"
- "> +\ts16\t\t\ttemp[4];\t/* Register values,\n"
- "> +\t\t\t\t\t\t   0 = input\n"
- "> +\t\t\t\t\t\t   1 = high\n"
- "> +\t\t\t\t\t\t   2 = low\n"
- "> +\t\t\t\t\t\t   3 = critical */\n"
- "> +\tu8\t\t\thyst;\t\t/* hysteresis offset */\n"
- "> +};\n"
- "> +\n"
- "> +static int adt7410_read_word(struct device *dev, u8 reg, u16 *data)\n"
- "> +{\n"
- "> +\tstruct adt7410_data *d = dev_get_drvdata(dev);\n"
- "> +\treturn d->ops->read_word(dev, reg, data);\n"
- "> +}\n"
- "> +\n"
- "> +static int adt7410_write_word(struct device *dev, u8 reg, u16 data)\n"
- "> +{\n"
- "> +\tstruct adt7410_data *d = dev_get_drvdata(dev);\n"
- "> +\treturn d->ops->write_word(dev, reg, data);\n"
- "> +}\n"
- "> +\n"
- "> +static int adt7410_read_byte(struct device *dev, u8 reg, u8 *data)\n"
- "> +{\n"
- "> +\tstruct adt7410_data *d = dev_get_drvdata(dev);\n"
- "> +\treturn d->ops->read_byte(dev, reg, data);\n"
- "> +}\n"
- "> +\n"
- "> +static int adt7410_write_byte(struct device *dev, u8 reg, u8 data)\n"
- "> +{\n"
- "> +\tstruct adt7410_data *d = dev_get_drvdata(dev);\n"
- "> +\treturn d->ops->write_byte(dev, reg, data);\n"
- "> +}\n"
- "> +\n"
- "> +static const u8 ADT7410_REG_TEMP[4] = {\n"
- "> +\tADT7410_TEMPERATURE,\t\t/* input */\n"
- "> +\tADT7410_T_ALARM_HIGH,\t\t/* high */\n"
- "> +\tADT7410_T_ALARM_LOW,\t\t/* low */\n"
- "> +\tADT7410_T_CRIT,\t\t\t/* critical */\n"
- "> +};\n"
- "> +\n"
- "> +/*\n"
- "> + * adt7410 register access by I2C\n"
- "> + */\n"
- "> +static int adt7410_temp_ready(struct device *dev)\n"
- "> +{\n"
- "> +\tint i, ret;\n"
- "> +\tu8 status;\n"
- "> +\n"
- "> +\tfor (i = 0; i < 6; i++) {\n"
- "> +\t\tret = adt7410_read_byte(dev, ADT7410_STATUS, &status);\n"
- "> +\t\tif (ret)\n"
- "> +\t\t\treturn ret;\n"
- "> +\t\tif (!(status & ADT7410_STAT_NOT_RDY))\n"
- "> +\t\t\treturn 0;\n"
- "> +\t\tmsleep(60);\n"
- "> +\t}\n"
- "> +\treturn -ETIMEDOUT;\n"
- "> +}\n"
- "> +\n"
- "> +static int adt7410_update_temp(struct device *dev)\n"
- "> +{\n"
- "> +\tstruct adt7410_data *data = dev_get_drvdata(dev);\n"
- "> +\tint ret = 0;\n"
- "> +\n"
- "> +\tmutex_lock(&data->update_lock);\n"
- "> +\n"
- "> +\tif (time_after(jiffies, data->last_updated + HZ + HZ / 2)\n"
- "> +\t    || !data->valid) {\n"
- "> +\n"
- "> +\t\tdev_dbg(dev, \"Starting update\\n\");\n"
- "> +\n"
- "> +\t\tret = adt7410_temp_ready(dev); /* check for new value */\n"
- "> +\t\tif (ret)\n"
- "> +\t\t\tgoto abort;\n"
- "> +\n"
- "> +\t\tret = adt7410_read_word(dev, ADT7410_REG_TEMP[0],\n"
- "> +\t\t\t\t\t&data->temp[0]);\n"
- "> +\t\tif (ret) {\n"
- "> +\t\t\tdev_dbg(dev, \"Failed to read value: reg %d, error %d\\n\",\n"
- "> +\t\t\t\tADT7410_REG_TEMP[0], ret);\n"
- "> +\t\t\tgoto abort;\n"
- "> +\t\t}\n"
- "> +\t\tdata->last_updated = jiffies;\n"
- "> +\t\tdata->valid = true;\n"
- "> +\t}\n"
- "> +\n"
- "> +abort:\n"
- "> +\tmutex_unlock(&data->update_lock);\n"
- "> +\treturn ret;\n"
- "> +}\n"
- "> +\n"
- "> +static int adt7410_fill_cache(struct device *dev)\n"
- "> +{\n"
- "> +\tstruct adt7410_data *data = dev_get_drvdata(dev);\n"
- "> +\tint ret;\n"
- "> +\tint i;\n"
- "> +\n"
- "> +\tfor (i = 1; i < ARRAY_SIZE(data->temp); i++) {\n"
- "> +\t\tret = adt7410_read_word(dev, ADT7410_REG_TEMP[i],\n"
- "> +\t\t\t\t\t&data->temp[i]);\n"
- "> +\t\tif (ret) {\n"
- "> +\t\t\tdev_dbg(dev, \"Failed to read value: reg %d, error %d\\n\",\n"
- "> +\t\t\t\tADT7410_REG_TEMP[0], ret);\n"
- "> +\t\t\treturn ret;\n"
- "> +\t\t}\n"
- "> +\t}\n"
- "> +\n"
- "> +\tret = adt7410_read_byte(dev, ADT7410_T_HYST, &data->hyst);\n"
- "> +\tif (ret) {\n"
- "> +\t\tdev_dbg(dev, \"Failed to read value: reg %d, error %d\\n\",\n"
- "> +\t\t\t\tADT7410_T_HYST, ret);\n"
- "> +\t\treturn ret;\n"
- "> +\t}\n"
- "> +\n"
- "> +\treturn 0;\n"
- "> +}\n"
- "> +\n"
- "> +static s16 ADT7410_TEMP_TO_REG(long temp)\n"
- "> +{\n"
- "> +\treturn DIV_ROUND_CLOSEST(clamp_val(temp, ADT7410_TEMP_MIN,\n"
- "> +\t\t\t\t\t       ADT7410_TEMP_MAX) * 128, 1000);\n"
- "> +}\n"
- "> +\n"
- "> +static int ADT7410_REG_TO_TEMP(struct adt7410_data *data, s16 reg)\n"
- "> +{\n"
- "> +\t/* in 13 bit mode, bits 0-2 are status flags - mask them out */\n"
- "> +\tif (!(data->config & ADT7410_RESOLUTION))\n"
- "> +\t\treg &= ADT7410_T13_VALUE_MASK;\n"
- "> +\t/*\n"
- "> +\t * temperature is stored in twos complement format, in steps of\n"
- "> +\t * 1/128\302\260C\n"
- "> +\t */\n"
- "> +\treturn DIV_ROUND_CLOSEST(reg * 1000, 128);\n"
- "> +}\n"
- "> +\n"
- "> +/*-----------------------------------------------------------------------*/\n"
- "> +\n"
- "> +/* sysfs attributes for hwmon */\n"
- "> +\n"
- "> +static ssize_t adt7410_show_temp(struct device *dev,\n"
- "> +\t\t\t\t struct device_attribute *da, char *buf)\n"
- "> +{\n"
- "> +\tstruct sensor_device_attribute *attr = to_sensor_dev_attr(da);\n"
- "> +\tstruct adt7410_data *data = dev_get_drvdata(dev);\n"
- "> +\n"
- "> +\n"
- "> +\tif (attr->index == 0) {\n"
- "> +\t\tint ret;\n"
- "> +\n"
- "> +\t\tret = adt7410_update_temp(dev);\n"
- "> +\t\tif (ret)\n"
- "> +\t\t\treturn ret;\n"
- "> +\t}\n"
- "> +\n"
- "> +\treturn sprintf(buf, \"%d\\n\", ADT7410_REG_TO_TEMP(data,\n"
- "> +\t\t       data->temp[attr->index]));\n"
- "> +}\n"
- "> +\n"
- "> +static ssize_t adt7410_set_temp(struct device *dev,\n"
- "> +\t\t\t\tstruct device_attribute *da,\n"
- "> +\t\t\t\tconst char *buf, size_t count)\n"
- "> +{\n"
- "> +\tstruct sensor_device_attribute *attr = to_sensor_dev_attr(da);\n"
- "> +\tstruct adt7410_data *data = dev_get_drvdata(dev);\n"
- "> +\tint nr = attr->index;\n"
- "> +\tlong temp;\n"
- "> +\tint ret;\n"
- "> +\n"
- "> +\tret = kstrtol(buf, 10, &temp);\n"
- "> +\tif (ret)\n"
- "> +\t\treturn ret;\n"
- "> +\n"
- "> +\tmutex_lock(&data->update_lock);\n"
- "> +\tdata->temp[nr] = ADT7410_TEMP_TO_REG(temp);\n"
- "> +\tret = adt7410_write_word(dev, ADT7410_REG_TEMP[nr], data->temp[nr]);\n"
- "> +\tif (ret)\n"
- "> +\t\tcount = ret;\n"
- "> +\tmutex_unlock(&data->update_lock);\n"
- "> +\treturn count;\n"
- "> +}\n"
- "> +\n"
- "> +static ssize_t adt7410_show_t_hyst(struct device *dev,\n"
- "> +\t\t\t\t   struct device_attribute *da,\n"
- "> +\t\t\t\t   char *buf)\n"
- "> +{\n"
- "> +\tstruct sensor_device_attribute *attr = to_sensor_dev_attr(da);\n"
- "> +\tstruct adt7410_data *data = dev_get_drvdata(dev);\n"
- "> +\tint nr = attr->index;\n"
- "> +\tint hyst;\n"
- "> +\n"
- "> +\thyst = (data->hyst & ADT7410_T_HYST_MASK) * 1000;\n"
- "> +\n"
- "> +\t/*\n"
- "> +\t * hysteresis is stored as a 4 bit offset in the device, convert it\n"
- "> +\t * to an absolute value\n"
- "> +\t */\n"
- "> +\tif (nr == 2)\t/* min has positive offset, others have negative */\n"
- "> +\t\thyst = -hyst;\n"
- "> +\treturn sprintf(buf, \"%d\\n\",\n"
- "> +\t\t       ADT7410_REG_TO_TEMP(data, data->temp[nr]) - hyst);\n"
- "> +}\n"
- "> +\n"
- "> +static ssize_t adt7410_set_t_hyst(struct device *dev,\n"
- "> +\t\t\t\t  struct device_attribute *da,\n"
- "> +\t\t\t\t  const char *buf, size_t count)\n"
- "> +{\n"
- "> +\tstruct adt7410_data *data = dev_get_drvdata(dev);\n"
- "> +\tint limit, ret;\n"
- "> +\tlong hyst;\n"
- "> +\n"
- "> +\tret = kstrtol(buf, 10, &hyst);\n"
- "> +\tif (ret)\n"
- "> +\t\treturn ret;\n"
- "> +\t/* convert absolute hysteresis value to a 4 bit delta value */\n"
- "> +\tlimit = ADT7410_REG_TO_TEMP(data, data->temp[1]);\n"
- "> +\thyst = clamp_val(hyst, ADT7410_TEMP_MIN, ADT7410_TEMP_MAX);\n"
- "> +\tdata->hyst = clamp_val(DIV_ROUND_CLOSEST(limit - hyst, 1000),\n"
- "> +\t\t\t\t   0, ADT7410_T_HYST_MASK);\n"
- "> +\tret = adt7410_write_byte(dev, ADT7410_T_HYST, data->hyst);\n"
- "> +\tif (ret)\n"
- "> +\t\treturn ret;\n"
- "> +\n"
- "> +\treturn count;\n"
- "> +}\n"
- "> +\n"
- "> +static ssize_t adt7410_show_alarm(struct device *dev,\n"
- "> +\t\t\t\t  struct device_attribute *da,\n"
- "> +\t\t\t\t  char *buf)\n"
- "> +{\n"
- "> +\tstruct sensor_device_attribute *attr = to_sensor_dev_attr(da);\n"
- "> +\tu8 status;\n"
- "> +\tint ret;\n"
- "> +\n"
- "> +\tret = adt7410_read_byte(dev, ADT7410_STATUS, &status);\n"
- "> +\tif (ret < 0)\n"
- "> +\t\treturn ret;\n"
- "> +\n"
- "> +\treturn sprintf(buf, \"%d\\n\", !!(status & attr->index));\n"
- "> +}\n"
- "> +\n"
- "> +static ssize_t adt7410_show_name(struct device *dev,\n"
- "> +\t\t\t\t  struct device_attribute *da, char *buf)\n"
- "> +{\n"
- "> +\tstruct adt7410_data *data = dev_get_drvdata(dev);\n"
- "> +\n"
- "> +\treturn sprintf(buf, \"%s\\n\", data->name);\n"
- "> +}\n"
- "> +\n"
- "> +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, adt7410_show_temp, NULL, 0);\n"
- "> +static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO,\n"
- "> +\t\t\t  adt7410_show_temp, adt7410_set_temp, 1);\n"
- "> +static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO,\n"
- "> +\t\t\t  adt7410_show_temp, adt7410_set_temp, 2);\n"
- "> +static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO,\n"
- "> +\t\t\t  adt7410_show_temp, adt7410_set_temp, 3);\n"
- "> +static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO,\n"
- "> +\t\t\t  adt7410_show_t_hyst, adt7410_set_t_hyst, 1);\n"
- "> +static SENSOR_DEVICE_ATTR(temp1_min_hyst, S_IRUGO,\n"
- "> +\t\t\t  adt7410_show_t_hyst, NULL, 2);\n"
- "> +static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO,\n"
- "> +\t\t\t  adt7410_show_t_hyst, NULL, 3);\n"
- "> +static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, adt7410_show_alarm,\n"
- "> +\t\t\t  NULL, ADT7410_STAT_T_LOW);\n"
- "> +static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, adt7410_show_alarm,\n"
- "> +\t\t\t  NULL, ADT7410_STAT_T_HIGH);\n"
- "> +static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, adt7410_show_alarm,\n"
- "> +\t\t\t  NULL, ADT7410_STAT_T_CRIT);\n"
- "> +static DEVICE_ATTR(name, S_IRUGO, adt7410_show_name, NULL);\n"
- "> +\n"
- "> +static struct attribute *adt7410_attributes[] = {\n"
- "> +\t&sensor_dev_attr_temp1_input.dev_attr.attr,\n"
- "> +\t&sensor_dev_attr_temp1_max.dev_attr.attr,\n"
- "> +\t&sensor_dev_attr_temp1_min.dev_attr.attr,\n"
- "> +\t&sensor_dev_attr_temp1_crit.dev_attr.attr,\n"
- "> +\t&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,\n"
- "> +\t&sensor_dev_attr_temp1_min_hyst.dev_attr.attr,\n"
- "> +\t&sensor_dev_attr_temp1_crit_hyst.dev_attr.attr,\n"
- "> +\t&sensor_dev_attr_temp1_min_alarm.dev_attr.attr,\n"
- "> +\t&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,\n"
- "> +\t&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,\n"
- "> +\tNULL\n"
- "> +};\n"
- "> +\n"
- "> +static const struct attribute_group adt7410_group = {\n"
- "> +\t.attrs = adt7410_attributes,\n"
- "> +};\n"
- "> +\n"
- "> +int adt7410_probe(struct device *dev, const char *name,\n"
- "> +\tconst struct adt7410_ops *ops)\n"
- "> +{\n"
- "> +\tstruct adt7410_data *data;\n"
- "> +\tint ret;\n"
- "> +\n"
- "> +\tdata = devm_kzalloc(dev, sizeof(struct adt7410_data),\n"
- "> +\t\t\t    GFP_KERNEL);\n"
- "> +\tif (!data)\n"
- "> +\t\treturn -ENOMEM;\n"
- "> +\n"
- "> +\tdata->ops = ops;\n"
- "> +\tdata->name = name;\n"
- "> +\n"
- "> +\tdev_set_drvdata(dev, data);\n"
- "> +\tmutex_init(&data->update_lock);\n"
- "> +\n"
- "> +\t/* configure as specified */\n"
- "> +\tret = adt7410_read_byte(dev, ADT7410_CONFIG, &data->oldconfig);\n"
- "> +\tif (ret < 0) {\n"
- "> +\t\tdev_dbg(dev, \"Can't read config? %d\\n\", ret);\n"
- "> +\t\treturn ret;\n"
- "> +\t}\n"
- "> +\t/*\n"
- "> +\t * Set to 16 bit resolution, continous conversion and comparator mode.\n"
- "> +\t */\n"
- "> +\tdata->config = data->oldconfig;\n"
- "> +\tdata->config &= ~ADT7410_MODE_MASK;\n"
- "> +\tdata->config |= ADT7410_FULL | ADT7410_RESOLUTION | ADT7410_EVENT_MODE;\n"
- "> +\tif (data->config != data->oldconfig) {\n"
- "> +\t\tret = adt7410_write_byte(dev, ADT7410_CONFIG, data->config);\n"
- "> +\t\tif (ret)\n"
- "> +\t\t\treturn ret;\n"
- "> +\t}\n"
- "> +\tdev_dbg(dev, \"Config %02x\\n\", data->config);\n"
- "> +\n"
- "> +\tret = adt7410_fill_cache(dev);\n"
- "> +\tif (ret)\n"
- "> +\t\tgoto exit_restore;\n"
- "> +\n"
- "> +\t/* Register sysfs hooks */\n"
- "> +\tret = sysfs_create_group(&dev->kobj, &adt7410_group);\n"
- "> +\tif (ret)\n"
- "> +\t\tgoto exit_restore;\n"
- "> +\n"
- "> +\t/*\n"
- "> +\t * The I2C device will already have it's own 'name' attribute, but for\n"
- "> +\t * the SPI device we need to register it. name will only be non NULL if\n"
- "> +\t * the device doesn't register the 'name' attribute on its own.\n"
- "> +\t */\n"
- "> +\tif (name) {\n"
- "> +\t\tret = device_create_file(dev, &dev_attr_name);\n"
- "> +\t\tif (ret)\n"
- "> +\t\t\tgoto exit_remove;\n"
- "> +\t}\n"
- "> +\n"
- "> +\tdata->hwmon_dev = hwmon_device_register(dev);\n"
- "> +\tif (IS_ERR(data->hwmon_dev)) {\n"
- "> +\t\tret = PTR_ERR(data->hwmon_dev);\n"
- "> +\t\tgoto exit_remove_name;\n"
- "> +\t}\n"
- "> +\n"
- "> +\treturn 0;\n"
- "> +\n"
- "> +exit_remove_name:\n"
- "> +\tif (name)\n"
- "> +\t\tdevice_remove_file(dev, &dev_attr_name);\n"
- "> +exit_remove:\n"
- "> +\tsysfs_remove_group(&dev->kobj, &adt7410_group);\n"
- "> +exit_restore:\n"
- "> +\tadt7410_write_byte(dev, ADT7410_CONFIG, data->oldconfig);\n"
- "> +\treturn ret;\n"
- "> +}\n"
- "> +EXPORT_SYMBOL_GPL(adt7410_probe);\n"
- "> +\n"
- "> +int adt7410_remove(struct device *dev)\n"
- "> +{\n"
- "> +\tstruct adt7410_data *data = dev_get_drvdata(dev);\n"
- "> +\n"
- "> +\thwmon_device_unregister(data->hwmon_dev);\n"
- "> +\tif (data->name)\n"
- "> +\t\tdevice_remove_file(dev, &dev_attr_name);\n"
- "> +\tsysfs_remove_group(&dev->kobj, &adt7410_group);\n"
- "> +\tif (data->oldconfig != data->config)\n"
- "> +\t\tadt7410_write_byte(dev, ADT7410_CONFIG,\n"
- "> +\t\t\t\t\t  data->oldconfig);\n"
- "> +\treturn 0;\n"
- "> +}\n"
- "> +EXPORT_SYMBOL_GPL(adt7410_remove);\n"
- "> +\n"
- "> +#ifdef CONFIG_PM_SLEEP\n"
- "> +\n"
- "> +static int adt7410_suspend(struct device *dev)\n"
- "> +{\n"
- "> +\tstruct adt7410_data *data = dev_get_drvdata(dev);\n"
- "> +\n"
- "> +\treturn adt7410_write_byte(dev, ADT7410_CONFIG,\n"
- "> +\t\tdata->config | ADT7410_PD);\n"
- "> +}\n"
- "> +\n"
- "> +static int adt7410_resume(struct device *dev)\n"
- "> +{\n"
- "> +\tstruct adt7410_data *data = dev_get_drvdata(dev);\n"
- "> +\n"
- "> +\treturn adt7410_write_byte(dev, ADT7410_CONFIG, data->config);\n"
- "> +}\n"
- "> +\n"
- "> +SIMPLE_DEV_PM_OPS(adt7410_dev_pm_ops, adt7410_suspend, adt7410_resume);\n"
- "> +EXPORT_SYMBOL_GPL(adt7410_dev_pm_ops);\n"
- "> +\n"
- "> +#endif /* CONFIG_PM_SLEEP */\n"
- "> +\n"
- "> +MODULE_AUTHOR(\"Hartmut Knaack\");\n"
- "> +MODULE_DESCRIPTION(\"ADT7410 driver\");\n"
- "This description does not seem appropriate any longer.\n"
- "> +MODULE_LICENSE(\"GPL\");\n"
- <...>
+ "SSBoYWQgYSBxdWljayBsb29rIG92ZXIgeW91ciBwYXRjaGVzIGFuZCBmb3VuZCBzb21lIG1pbm9y\n"
+ "IHR5cG8sIHNlZSBiZWxvdy4gSSB3aWxsIGFwcGx5IGFsbCB0aGUgcGF0Y2hlcyB0byBzZWUgdGhl\n"
+ "IHJlc3VsdC4KQWxzbyBrZWVwIGluIG1pbmQgdG8gYWRkIHNvbWUgY2hhbmdlcyB0byBEb2N1bWVu\n"
+ "dGF0aW9uL2h3bW9uL2FkdDc0MTAgKGFuZCBhZGQgYW4gYWR0NzMxMCBhcyB3ZWxsPykuCgpMYXJz\n"
+ "LVBldGVyIENsYXVzZW4gc2NocmllYjoKPC4uLj4KPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9od21v\n"
+ "bi9hZHQ3MzEwLmMgYi9kcml2ZXJzL2h3bW9uL2FkdDczMTAuYwo+IG5ldyBmaWxlIG1vZGUgMTAw\n"
+ "NjQ0Cj4gaW5kZXggMDAwMDAwMC4uMDQ4M2U2Ywo+IC0tLSAvZGV2L251bGwKPiArKysgYi9kcml2\n"
+ "ZXJzL2h3bW9uL2FkdDczMTAuYwo+IEBAIC0wLDAgKzEsMTYwIEBACj4gKy8qCj4gKyAqIEFEVDcz\n"
+ "MTAvQURUNzMxMCBkaWdpdGFsIHRlbXBlcmF0dXJlIHNlbnNvciBkcml2ZXIKPiArICoKPiArICog\n"
+ "Q29weXJpZ2h0IDIwMTAtMjAxMyBBbmFsb2cgRGV2aWNlcyBJbmMuCj4gKyAqICAgQXV0aG9yOiBM\n"
+ "YXJzLVBldGVyIENsYXVzZW4gPGxhcnNAbWV0YWZvby5kZT4KPiArICoKPiArICogTGljZW5zZWQg\n"
+ "dW5kZXIgdGhlIEdQTC0yIG9yIGxhdGVyLgo+ICsgKi8KPiArCj4gKyNpbmNsdWRlIDxsaW51eC9t\n"
+ "b2R1bGUuaD4KPiArI2luY2x1ZGUgPGxpbnV4L2luaXQuaD4KPiArI2luY2x1ZGUgPGxpbnV4L3Nw\n"
+ "aS9zcGkuaD4KPiArCj4gKyNpbmNsdWRlICJhZHQ3eDEwLmgiCj4gKwo+ICtzdGF0aWMgY29uc3Qg\n"
+ "dTggYWR0NzM3MV9yZWdfdGFibGVbXSA9IHsKPiArCVtBRFQ3NDEwX1RFTVBFUkFUVVJFXSAgID0g\n"
+ "QURUNzMxMF9URU1QRVJBVFVSRSwKPiArCVtBRFQ3NDEwX1NUQVRVU10JPSBBRFQ3MzEwX1NUQVRV\n"
+ "UywKPiArCVtBRFQ3NDEwX0NPTkZJR10JPSBBRFQ3MzEwX0NPTkZJRywKPiArCVtBRFQ3NDEwX1Rf\n"
+ "QUxBUk1fSElHSF0JPSBBRFQ3MzEwX1RfQUxBUk1fSElHSCwKPiArCVtBRFQ3NDEwX1RfQUxBUk1f\n"
+ "TE9XXQk9IEFEVDczMTBfVF9BTEFSTV9MT1csCj4gKwlbQURUNzQxMF9UX0NSSVRdCT0gQURUNzMx\n"
+ "MF9UX0NSSVQsCj4gKwlbQURUNzQxMF9UX0hZU1RdCT0gQURUNzMxMF9UX0hZU1QsCj4gKwlbQURU\n"
+ "NzQxMF9JRF0JCT0gQURUNzMxMF9JRCwKPiArfTsKSnVzdCBvdXQgb2YgY3VyaW91c2l0eSwgd2hh\n"
+ "dHMgdGhlIHJlYXNvbiBmb3IgdGhlIG5hbWUgYWR0NzM3MSBoZXJlPwo+ICsKPiArI2RlZmluZSBB\n"
+ "RFQ3MzEwX0NNRF9SRUdfTUFTSwkJCTB4MjgKPiArI2RlZmluZSBBRFQ3MzEwX0NNRF9SRUdfT0ZG\n"
+ "U0VUCQkJMwo+ICsjZGVmaW5lIEFEVDczMTBfQ01EX1JFQUQJCQkweDQwCj4gKyNkZWZpbmUgQURU\n"
+ "NzMxMF9DTURfQ09OX1JFQUQJCQkweDQKPiArCj4gKyNkZWZpbmUgQUQ3MzEwX0NPTU1BTkQocmVn\n"
+ "KSAoYWR0NzM3MV9yZWdfdGFibGVbKHJlZyldIDw8IEFEVDczMTBfQ01EX1JFR19PRkZTRVQpCj4g\n"
+ "Kwo+ICtzdGF0aWMgaW50IGFkdDczMTBfc3BpX3JlYWRfd29yZChzdHJ1Y3QgZGV2aWNlICpkZXYs\n"
+ "Cj4gKwl1OCByZWcsIHUxNiAqZGF0YSkKPiArewo+ICsJc3RydWN0IHNwaV9kZXZpY2UgKnNwaSA9\n"
+ "IHRvX3NwaV9kZXZpY2UoZGV2KTsKPiArCXU4IGNvbW1hbmQgPSBBRDczMTBfQ09NTUFORChyZWcp\n"
+ "Owo+ICsJaW50IHJldCA9IDA7Cj4gKwo+ICsJY29tbWFuZCB8PSBBRFQ3MzEwX0NNRF9SRUFEOwo+\n"
+ "ICsJcmV0ID0gc3BpX3dyaXRlKHNwaSwgJmNvbW1hbmQsIHNpemVvZihjb21tYW5kKSk7Cj4gKwlp\n"
+ "ZiAocmV0IDwgMCkgewo+ICsJCWRldl9lcnIoZGV2LCAiU1BJIHdyaXRlIGNvbW1hbmQgZXJyb3Jc\n"
+ "biIpOwo+ICsJCXJldHVybiByZXQ7Cj4gKwl9Cj4gKwo+ICsJcmV0ID0gc3BpX3JlYWQoc3BpLCAo\n"
+ "dTggKilkYXRhLCBzaXplb2YoKmRhdGEpKTsKPiArCWlmIChyZXQgPCAwKSB7Cj4gKwkJZGV2X2Vy\n"
+ "cihkZXYsICJTUEkgcmVhZCB3b3JkIGVycm9yXG4iKTsKPiArCQlyZXR1cm4gcmV0Owo+ICsJfQo+\n"
+ "ICsKPiArCSpkYXRhID0gYmUxNl90b19jcHUoKmRhdGEpOwo+ICsKPiArCXJldHVybiAwOwo+ICt9\n"
+ "Cj4gKwo+ICtzdGF0aWMgaW50IGFkdDczMTBfc3BpX3dyaXRlX3dvcmQoc3RydWN0IGRldmljZSAq\n"
+ "ZGV2LCB1OCByZWcsCj4gKwl1MTYgZGF0YSkKPiArewo+ICsJc3RydWN0IHNwaV9kZXZpY2UgKnNw\n"
+ "aSA9IHRvX3NwaV9kZXZpY2UoZGV2KTsKPiArCXU4IGJ1ZlszXTsKPiArCWludCByZXQgPSAwOwo+\n"
+ "ICsKPiArCWJ1ZlswXSA9IEFENzMxMF9DT01NQU5EKHJlZyk7Cj4gKwlidWZbMV0gPSAodTgpKGRh\n"
+ "dGEgPj4gOCk7Cj4gKwlidWZbMl0gPSAodTgpKGRhdGEgJiAweEZGKTsKPiArCj4gKwlyZXQgPSBz\n"
+ "cGlfd3JpdGUoc3BpLCBidWYsIDMpOwo+ICsJaWYgKHJldCA8IDApIHsKPiArCQlkZXZfZXJyKGRl\n"
+ "diwgIlNQSSB3cml0ZSB3b3JkIGVycm9yXG4iKTsKPiArCQlyZXR1cm4gcmV0Owo+ICsJfQo+ICsK\n"
+ "PiArCXJldHVybiByZXQ7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgYWR0NzMxMF9zcGlfcmVhZF9i\n"
+ "eXRlKHN0cnVjdCBkZXZpY2UgKmRldiwgdTggcmVnLAo+ICsJdTggKmRhdGEpCj4gK3sKPiArCXN0\n"
+ "cnVjdCBzcGlfZGV2aWNlICpzcGkgPSB0b19zcGlfZGV2aWNlKGRldik7Cj4gKwl1OCBjb21tYW5k\n"
+ "ID0gQUQ3MzEwX0NPTU1BTkQocmVnKTsKPiArCWludCByZXQgPSAwOwo+ICsKPiArCWNvbW1hbmQg\n"
+ "fD0gQURUNzMxMF9DTURfUkVBRDsKPiArCXJldCA9IHNwaV93cml0ZShzcGksICZjb21tYW5kLCBz\n"
+ "aXplb2YoY29tbWFuZCkpOwo+ICsJaWYgKHJldCA8IDApIHsKPiArCQlkZXZfZXJyKGRldiwgIlNQ\n"
+ "SSB3cml0ZSBjb21tYW5kIGVycm9yXG4iKTsKPiArCQlyZXR1cm4gcmV0Owo+ICsJfQo+ICsKPiAr\n"
+ "CXJldCA9IHNwaV9yZWFkKHNwaSwgZGF0YSwgc2l6ZW9mKCpkYXRhKSk7Cj4gKwlpZiAocmV0IDwg\n"
+ "MCkgewo+ICsJCWRldl9lcnIoZGV2LCAiU1BJIHJlYWQgYnl0ZSBlcnJvclxuIik7Cj4gKwkJcmV0\n"
+ "dXJuIHJldDsKPiArCX0KPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIGludCBh\n"
+ "ZHQ3MzEwX3NwaV93cml0ZV9ieXRlKHN0cnVjdCBkZXZpY2UgKmRldiwgdTggcmVnLAo+ICsJdTgg\n"
+ "ZGF0YSkKPiArewo+ICsJc3RydWN0IHNwaV9kZXZpY2UgKnNwaSA9IHRvX3NwaV9kZXZpY2UoZGV2\n"
+ "KTsKPiArCXU4IGJ1ZlsyXTsKPiArCWludCByZXQgPSAwOwo+ICsKPiArCWJ1ZlswXSA9IEFENzMx\n"
+ "MF9DT01NQU5EKHJlZyk7Cj4gKwlidWZbMV0gPSBkYXRhOwo+ICsKPiArCXJldCA9IHNwaV93cml0\n"
+ "ZShzcGksIGJ1ZiwgMik7Cj4gKwlpZiAocmV0IDwgMCkgewo+ICsJCWRldl9lcnIoZGV2LCAiU1BJ\n"
+ "IHdyaXRlIGJ5dGUgZXJyb3JcbiIpOwo+ICsJCXJldHVybiByZXQ7Cj4gKwl9Cj4gKwo+ICsJcmV0\n"
+ "dXJuIHJldDsKPiArfQo+ICsKPiArc3RhdGljIGNvbnN0IHN0cnVjdCBhZHQ3NDEwX29wcyBhZHQ3\n"
+ "MzEwX3NwaV9vcHMgPSB7Cj4gKwkucmVhZF93b3JkID0gYWR0NzMxMF9zcGlfcmVhZF93b3JkLAo+\n"
+ "ICsJLndyaXRlX3dvcmQgPSBhZHQ3MzEwX3NwaV93cml0ZV93b3JkLAo+ICsJLnJlYWRfYnl0ZSA9\n"
+ "IGFkdDczMTBfc3BpX3JlYWRfYnl0ZSwKPiArCS53cml0ZV9ieXRlID0gYWR0NzMxMF9zcGlfd3Jp\n"
+ "dGVfYnl0ZSwKPiArfTsKPiArCj4gK3N0YXRpYyBpbnQgYWR0NzMxMF9zcGlfcHJvYmUoc3RydWN0\n"
+ "IHNwaV9kZXZpY2UgKnNwaSkKPiArewo+ICsJcmV0dXJuIGFkdDc0MTBfcHJvYmUoJnNwaS0+ZGV2\n"
+ "LCBzcGlfZ2V0X2RldmljZV9pZChzcGkpLT5uYW1lLAo+ICsJCQkmYWR0NzMxMF9zcGlfb3BzKTsK\n"
+ "PiArfQo+ICsKPiArc3RhdGljIGludCBhZHQ3MzEwX3NwaV9yZW1vdmUoc3RydWN0IHNwaV9kZXZp\n"
+ "Y2UgKnNwaSkKPiArewo+ICsJcmV0dXJuIGFkdDc0MTBfcmVtb3ZlKCZzcGktPmRldik7Cj4gK30K\n"
+ "PiArCj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3Qgc3BpX2RldmljZV9pZCBhZHQ3MzEwX2lkW10gPSB7\n"
+ "Cj4gKwl7ICJhZHQ3MzEwIiwgMCB9LAo+ICsJeyAiYWR0NzMyMCIsIDAgfSwKPiArCXt9Cj4gK307\n"
+ "Cj4gK01PRFVMRV9ERVZJQ0VfVEFCTEUoc3BpLCBhZHQ3MzEwX2lkKTsKPiArCj4gK3N0YXRpYyBz\n"
+ "dHJ1Y3Qgc3BpX2RyaXZlciBhZHQ3MzEwX2RyaXZlciA9IHsKPiArCS5kcml2ZXIgPSB7Cj4gKwkJ\n"
+ "Lm5hbWUgPSAiYWR0NzMxMCIsCj4gKwkJLm93bmVyID0gVEhJU19NT0RVTEUsCj4gKwkJLnBtCT0g\n"
+ "QURUNzQxMF9ERVZfUE1fT1BTLAo+ICsJfSwKPiArCS5wcm9iZSA9IGFkdDczMTBfc3BpX3Byb2Jl\n"
+ "LAo+ICsJLnJlbW92ZSA9IGFkdDczMTBfc3BpX3JlbW92ZSwKPiArCS5pZF90YWJsZSA9IGFkdDcz\n"
+ "MTBfaWQsCj4gK307Cj4gK21vZHVsZV9zcGlfZHJpdmVyKGFkdDczMTBfZHJpdmVyKTsKPiArCj4g\n"
+ "K01PRFVMRV9BVVRIT1IoIkxhcnMtUGV0ZXIgQ2xhdXNlbiA8bGFyc0BtZXRhZm9vLmRlPiIpOwo+\n"
+ "ICtNT0RVTEVfREVTQ1JJUFRJT04oIkFEVDczMTAvQURUNzQyMCBkcml2ZXIiKTsKVGhpcyBzaG91\n"
+ "bGQgYmUgQURUNzMxMC9BRFQ3MzIwLCByaWdodD8KPiArTU9EVUxFX0xJQ0VOU0UoIkdQTCIpOwo8\n"
+ "Li4uPgo+IC0tLSAvZGV2L251bGwKPiArKysgYi9kcml2ZXJzL2h3bW9uL2FkdDd4MTAuYwo+IEBA\n"
+ "IC0wLDAgKzEsNDc2IEBACj4gKy8qCj4gKyAqIGFkdDc0MTAuYyAtIFBhcnQgb2YgbG1fc2Vuc29y\n"
+ "cywgTGludXgga2VybmVsIG1vZHVsZXMgZm9yIGhhcmR3YXJlCj4gKyAqCSBtb25pdG9yaW5nCj4g\n"
+ "KyAqIFRoaXMgZHJpdmVyIGhhbmRsZXMgdGhlIEFEVDc0MTAgYW5kIGNvbXBhdGlibGUgZGlnaXRh\n"
+ "bCB0ZW1wZXJhdHVyZSBzZW5zb3JzLgo+ICsgKiBIYXJ0bXV0IEtuYWFjayA8a25hYWNrLmhAZ214\n"
+ "LmRlPiAyMDEyLTA3LTIyCj4gKyAqIGJhc2VkIG9uIGxtNzUuYyBieSBGcm9kbyBMb29pamFhcmQg\n"
+ "PGZyb2RvbEBkZHMubmw+Cj4gKyAqIGFuZCBhZHQ3NDEwLmMgZnJvbSBpaW8tc3RhZ2luZyBieSBT\n"
+ "b25pYyBaaGFuZyA8c29uaWMuemhhbmdAYW5hbG9nLmNvbT4KPiArICoKPiArICogVGhpcyBwcm9n\n"
+ "cmFtIGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2Rp\n"
+ "ZnkKPiArICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGlj\n"
+ "ZW5zZSBhcyBwdWJsaXNoZWQgYnkKPiArICogdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsg\n"
+ "ZWl0aGVyIHZlcnNpb24gMiBvZiB0aGUgTGljZW5zZSwgb3IKPiArICogKGF0IHlvdXIgb3B0aW9u\n"
+ "KSBhbnkgbGF0ZXIgdmVyc2lvbi4KPiArICoKPiArICogVGhpcyBwcm9ncmFtIGlzIGRpc3RyaWJ1\n"
+ "dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsCj4gKyAqIGJ1dCBXSVRIT1VU\n"
+ "IEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mCj4gKyAq\n"
+ "IE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNl\n"
+ "ZSB0aGUKPiArICogR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4K\n"
+ "PiArICoKPiArICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdl\n"
+ "bmVyYWwgUHVibGljIExpY2Vuc2UKPiArICogYWxvbmcgd2l0aCB0aGlzIHByb2dyYW07IGlmIG5v\n"
+ "dCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmUKPiArICogRm91bmRhdGlvbiwgSW5jLiwgNjc1\n"
+ "IE1hc3MgQXZlLCBDYW1icmlkZ2UsIE1BIDAyMTM5LCBVU0EuCj4gKyAqLwo+ICsKPiArI2luY2x1\n"
+ "ZGUgPGxpbnV4L21vZHVsZS5oPgo+ICsjaW5jbHVkZSA8bGludXgvaW5pdC5oPgo+ICsjaW5jbHVk\n"
+ "ZSA8bGludXgvc2xhYi5oPgo+ICsjaW5jbHVkZSA8bGludXgvamlmZmllcy5oPgo+ICsjaW5jbHVk\n"
+ "ZSA8bGludXgvaHdtb24uaD4KPiArI2luY2x1ZGUgPGxpbnV4L2h3bW9uLXN5c2ZzLmg+Cj4gKyNp\n"
+ "bmNsdWRlIDxsaW51eC9lcnIuaD4KPiArI2luY2x1ZGUgPGxpbnV4L211dGV4Lmg+Cj4gKyNpbmNs\n"
+ "dWRlIDxsaW51eC9kZWxheS5oPgo+ICsKPiArI2luY2x1ZGUgImFkdDd4MTAuaCIKPiArCj4gKy8q\n"
+ "Cj4gKyAqIEFEVDc0MTAgc3RhdHVzCj4gKyAqLwo+ICsjZGVmaW5lIEFEVDc0MTBfU1RBVF9UX0xP\n"
+ "VwkJKDEgPDwgNCkKPiArI2RlZmluZSBBRFQ3NDEwX1NUQVRfVF9ISUdICQkoMSA8PCA1KQo+ICsj\n"
+ "ZGVmaW5lIEFEVDc0MTBfU1RBVF9UX0NSSVQJCSgxIDw8IDYpCj4gKyNkZWZpbmUgQURUNzQxMF9T\n"
+ "VEFUX05PVF9SRFkJCSgxIDw8IDcpCj4gKwo+ICsvKgo+ICsgKiBBRFQ3NDEwIGNvbmZpZwo+ICsg\n"
+ "Ki8KPiArI2RlZmluZSBBRFQ3NDEwX0ZBVUxUX1FVRVVFX01BU0sJKDEgPDwgMCB8IDEgPDwgMSkK\n"
+ "PiArI2RlZmluZSBBRFQ3NDEwX0NUX1BPTEFSSVRZCQkoMSA8PCAyKQo+ICsjZGVmaW5lIEFEVDc0\n"
+ "MTBfSU5UX1BPTEFSSVRZCQkoMSA8PCAzKQo+ICsjZGVmaW5lIEFEVDc0MTBfRVZFTlRfTU9ERQkJ\n"
+ "KDEgPDwgNCkKPiArI2RlZmluZSBBRFQ3NDEwX01PREVfTUFTSwkJKDEgPDwgNSB8IDEgPDwgNikK\n"
+ "PiArI2RlZmluZSBBRFQ3NDEwX0ZVTEwJCQkoMCA8PCA1IHwgMCA8PCA2KQo+ICsjZGVmaW5lIEFE\n"
+ "VDc0MTBfUEQJCQkoMSA8PCA1IHwgMSA8PCA2KQo+ICsjZGVmaW5lIEFEVDc0MTBfUkVTT0xVVElP\n"
+ "TgkJKDEgPDwgNykKPiArCj4gKy8qCj4gKyAqIEFEVDc0MTAgbWFza3MKPiArICovCj4gKyNkZWZp\n"
+ "bmUgQURUNzQxMF9UMTNfVkFMVUVfTUFTSwkJCTB4RkZGOAo+ICsjZGVmaW5lIEFEVDc0MTBfVF9I\n"
+ "WVNUX01BU0sJCQkweEYKPiArCj4gKy8qIHN0cmFpZ2h0IGZyb20gdGhlIGRhdGFzaGVldCAqLwo+\n"
+ "ICsjZGVmaW5lIEFEVDc0MTBfVEVNUF9NSU4gKC01NTAwMCkKPiArI2RlZmluZSBBRFQ3NDEwX1RF\n"
+ "TVBfTUFYIDE1MDAwMAo+ICsKPiArLyogRWFjaCBjbGllbnQgaGFzIHRoaXMgYWRkaXRpb25hbCBk\n"
+ "YXRhICovCj4gK3N0cnVjdCBhZHQ3NDEwX2RhdGEgewo+ICsJY29uc3Qgc3RydWN0IGFkdDc0MTBf\n"
+ "b3BzICpvcHM7Cj4gKwljb25zdCBjaGFyCQkqbmFtZTsKPiArCXN0cnVjdCBkZXZpY2UJCSpod21v\n"
+ "bl9kZXY7Cj4gKwlzdHJ1Y3QgbXV0ZXgJCXVwZGF0ZV9sb2NrOwo+ICsJdTgJCQljb25maWc7Cj4g\n"
+ "Kwl1OAkJCW9sZGNvbmZpZzsKPiArCWJvb2wJCQl2YWxpZDsJCS8qIHRydWUgaWYgcmVnaXN0ZXJz\n"
+ "IHZhbGlkICovCj4gKwl1bnNpZ25lZCBsb25nCQlsYXN0X3VwZGF0ZWQ7CS8qIEluIGppZmZpZXMg\n"
+ "Ki8KPiArCXMxNgkJCXRlbXBbNF07CS8qIFJlZ2lzdGVyIHZhbHVlcywKPiArCQkJCQkJICAgMCA9\n"
+ "IGlucHV0Cj4gKwkJCQkJCSAgIDEgPSBoaWdoCj4gKwkJCQkJCSAgIDIgPSBsb3cKPiArCQkJCQkJ\n"
+ "ICAgMyA9IGNyaXRpY2FsICovCj4gKwl1OAkJCWh5c3Q7CQkvKiBoeXN0ZXJlc2lzIG9mZnNldCAq\n"
+ "Lwo+ICt9Owo+ICsKPiArc3RhdGljIGludCBhZHQ3NDEwX3JlYWRfd29yZChzdHJ1Y3QgZGV2aWNl\n"
+ "ICpkZXYsIHU4IHJlZywgdTE2ICpkYXRhKQo+ICt7Cj4gKwlzdHJ1Y3QgYWR0NzQxMF9kYXRhICpk\n"
+ "ID0gZGV2X2dldF9kcnZkYXRhKGRldik7Cj4gKwlyZXR1cm4gZC0+b3BzLT5yZWFkX3dvcmQoZGV2\n"
+ "LCByZWcsIGRhdGEpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGFkdDc0MTBfd3JpdGVfd29yZChz\n"
+ "dHJ1Y3QgZGV2aWNlICpkZXYsIHU4IHJlZywgdTE2IGRhdGEpCj4gK3sKPiArCXN0cnVjdCBhZHQ3\n"
+ "NDEwX2RhdGEgKmQgPSBkZXZfZ2V0X2RydmRhdGEoZGV2KTsKPiArCXJldHVybiBkLT5vcHMtPndy\n"
+ "aXRlX3dvcmQoZGV2LCByZWcsIGRhdGEpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGFkdDc0MTBf\n"
+ "cmVhZF9ieXRlKHN0cnVjdCBkZXZpY2UgKmRldiwgdTggcmVnLCB1OCAqZGF0YSkKPiArewo+ICsJ\n"
+ "c3RydWN0IGFkdDc0MTBfZGF0YSAqZCA9IGRldl9nZXRfZHJ2ZGF0YShkZXYpOwo+ICsJcmV0dXJu\n"
+ "IGQtPm9wcy0+cmVhZF9ieXRlKGRldiwgcmVnLCBkYXRhKTsKPiArfQo+ICsKPiArc3RhdGljIGlu\n"
+ "dCBhZHQ3NDEwX3dyaXRlX2J5dGUoc3RydWN0IGRldmljZSAqZGV2LCB1OCByZWcsIHU4IGRhdGEp\n"
+ "Cj4gK3sKPiArCXN0cnVjdCBhZHQ3NDEwX2RhdGEgKmQgPSBkZXZfZ2V0X2RydmRhdGEoZGV2KTsK\n"
+ "PiArCXJldHVybiBkLT5vcHMtPndyaXRlX2J5dGUoZGV2LCByZWcsIGRhdGEpOwo+ICt9Cj4gKwo+\n"
+ "ICtzdGF0aWMgY29uc3QgdTggQURUNzQxMF9SRUdfVEVNUFs0XSA9IHsKPiArCUFEVDc0MTBfVEVN\n"
+ "UEVSQVRVUkUsCQkvKiBpbnB1dCAqLwo+ICsJQURUNzQxMF9UX0FMQVJNX0hJR0gsCQkvKiBoaWdo\n"
+ "ICovCj4gKwlBRFQ3NDEwX1RfQUxBUk1fTE9XLAkJLyogbG93ICovCj4gKwlBRFQ3NDEwX1RfQ1JJ\n"
+ "VCwJCQkvKiBjcml0aWNhbCAqLwo+ICt9Owo+ICsKPiArLyoKPiArICogYWR0NzQxMCByZWdpc3Rl\n"
+ "ciBhY2Nlc3MgYnkgSTJDCj4gKyAqLwo+ICtzdGF0aWMgaW50IGFkdDc0MTBfdGVtcF9yZWFkeShz\n"
+ "dHJ1Y3QgZGV2aWNlICpkZXYpCj4gK3sKPiArCWludCBpLCByZXQ7Cj4gKwl1OCBzdGF0dXM7Cj4g\n"
+ "Kwo+ICsJZm9yIChpID0gMDsgaSA8IDY7IGkrKykgewo+ICsJCXJldCA9IGFkdDc0MTBfcmVhZF9i\n"
+ "eXRlKGRldiwgQURUNzQxMF9TVEFUVVMsICZzdGF0dXMpOwo+ICsJCWlmIChyZXQpCj4gKwkJCXJl\n"
+ "dHVybiByZXQ7Cj4gKwkJaWYgKCEoc3RhdHVzICYgQURUNzQxMF9TVEFUX05PVF9SRFkpKQo+ICsJ\n"
+ "CQlyZXR1cm4gMDsKPiArCQltc2xlZXAoNjApOwo+ICsJfQo+ICsJcmV0dXJuIC1FVElNRURPVVQ7\n"
+ "Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgYWR0NzQxMF91cGRhdGVfdGVtcChzdHJ1Y3QgZGV2aWNl\n"
+ "ICpkZXYpCj4gK3sKPiArCXN0cnVjdCBhZHQ3NDEwX2RhdGEgKmRhdGEgPSBkZXZfZ2V0X2RydmRh\n"
+ "dGEoZGV2KTsKPiArCWludCByZXQgPSAwOwo+ICsKPiArCW11dGV4X2xvY2soJmRhdGEtPnVwZGF0\n"
+ "ZV9sb2NrKTsKPiArCj4gKwlpZiAodGltZV9hZnRlcihqaWZmaWVzLCBkYXRhLT5sYXN0X3VwZGF0\n"
+ "ZWQgKyBIWiArIEhaIC8gMikKPiArCSAgICB8fCAhZGF0YS0+dmFsaWQpIHsKPiArCj4gKwkJZGV2\n"
+ "X2RiZyhkZXYsICJTdGFydGluZyB1cGRhdGVcbiIpOwo+ICsKPiArCQlyZXQgPSBhZHQ3NDEwX3Rl\n"
+ "bXBfcmVhZHkoZGV2KTsgLyogY2hlY2sgZm9yIG5ldyB2YWx1ZSAqLwo+ICsJCWlmIChyZXQpCj4g\n"
+ "KwkJCWdvdG8gYWJvcnQ7Cj4gKwo+ICsJCXJldCA9IGFkdDc0MTBfcmVhZF93b3JkKGRldiwgQURU\n"
+ "NzQxMF9SRUdfVEVNUFswXSwKPiArCQkJCQkmZGF0YS0+dGVtcFswXSk7Cj4gKwkJaWYgKHJldCkg\n"
+ "ewo+ICsJCQlkZXZfZGJnKGRldiwgIkZhaWxlZCB0byByZWFkIHZhbHVlOiByZWcgJWQsIGVycm9y\n"
+ "ICVkXG4iLAo+ICsJCQkJQURUNzQxMF9SRUdfVEVNUFswXSwgcmV0KTsKPiArCQkJZ290byBhYm9y\n"
+ "dDsKPiArCQl9Cj4gKwkJZGF0YS0+bGFzdF91cGRhdGVkID0gamlmZmllczsKPiArCQlkYXRhLT52\n"
+ "YWxpZCA9IHRydWU7Cj4gKwl9Cj4gKwo+ICthYm9ydDoKPiArCW11dGV4X3VubG9jaygmZGF0YS0+\n"
+ "dXBkYXRlX2xvY2spOwo+ICsJcmV0dXJuIHJldDsKPiArfQo+ICsKPiArc3RhdGljIGludCBhZHQ3\n"
+ "NDEwX2ZpbGxfY2FjaGUoc3RydWN0IGRldmljZSAqZGV2KQo+ICt7Cj4gKwlzdHJ1Y3QgYWR0NzQx\n"
+ "MF9kYXRhICpkYXRhID0gZGV2X2dldF9kcnZkYXRhKGRldik7Cj4gKwlpbnQgcmV0Owo+ICsJaW50\n"
+ "IGk7Cj4gKwo+ICsJZm9yIChpID0gMTsgaSA8IEFSUkFZX1NJWkUoZGF0YS0+dGVtcCk7IGkrKykg\n"
+ "ewo+ICsJCXJldCA9IGFkdDc0MTBfcmVhZF93b3JkKGRldiwgQURUNzQxMF9SRUdfVEVNUFtpXSwK\n"
+ "PiArCQkJCQkmZGF0YS0+dGVtcFtpXSk7Cj4gKwkJaWYgKHJldCkgewo+ICsJCQlkZXZfZGJnKGRl\n"
+ "diwgIkZhaWxlZCB0byByZWFkIHZhbHVlOiByZWcgJWQsIGVycm9yICVkXG4iLAo+ICsJCQkJQURU\n"
+ "NzQxMF9SRUdfVEVNUFswXSwgcmV0KTsKPiArCQkJcmV0dXJuIHJldDsKPiArCQl9Cj4gKwl9Cj4g\n"
+ "Kwo+ICsJcmV0ID0gYWR0NzQxMF9yZWFkX2J5dGUoZGV2LCBBRFQ3NDEwX1RfSFlTVCwgJmRhdGEt\n"
+ "Pmh5c3QpOwo+ICsJaWYgKHJldCkgewo+ICsJCWRldl9kYmcoZGV2LCAiRmFpbGVkIHRvIHJlYWQg\n"
+ "dmFsdWU6IHJlZyAlZCwgZXJyb3IgJWRcbiIsCj4gKwkJCQlBRFQ3NDEwX1RfSFlTVCwgcmV0KTsK\n"
+ "PiArCQlyZXR1cm4gcmV0Owo+ICsJfQo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICtzdGF0\n"
+ "aWMgczE2IEFEVDc0MTBfVEVNUF9UT19SRUcobG9uZyB0ZW1wKQo+ICt7Cj4gKwlyZXR1cm4gRElW\n"
+ "X1JPVU5EX0NMT1NFU1QoY2xhbXBfdmFsKHRlbXAsIEFEVDc0MTBfVEVNUF9NSU4sCj4gKwkJCQkJ\n"
+ "ICAgICAgIEFEVDc0MTBfVEVNUF9NQVgpICogMTI4LCAxMDAwKTsKPiArfQo+ICsKPiArc3RhdGlj\n"
+ "IGludCBBRFQ3NDEwX1JFR19UT19URU1QKHN0cnVjdCBhZHQ3NDEwX2RhdGEgKmRhdGEsIHMxNiBy\n"
+ "ZWcpCj4gK3sKPiArCS8qIGluIDEzIGJpdCBtb2RlLCBiaXRzIDAtMiBhcmUgc3RhdHVzIGZsYWdz\n"
+ "IC0gbWFzayB0aGVtIG91dCAqLwo+ICsJaWYgKCEoZGF0YS0+Y29uZmlnICYgQURUNzQxMF9SRVNP\n"
+ "TFVUSU9OKSkKPiArCQlyZWcgJj0gQURUNzQxMF9UMTNfVkFMVUVfTUFTSzsKPiArCS8qCj4gKwkg\n"
+ "KiB0ZW1wZXJhdHVyZSBpcyBzdG9yZWQgaW4gdHdvcyBjb21wbGVtZW50IGZvcm1hdCwgaW4gc3Rl\n"
+ "cHMgb2YKPiArCSAqIDEvMTI4wrBDCj4gKwkgKi8KPiArCXJldHVybiBESVZfUk9VTkRfQ0xPU0VT\n"
+ "VChyZWcgKiAxMDAwLCAxMjgpOwo+ICt9Cj4gKwo+ICsvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t\n"
+ "LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi8KPiArCj4g\n"
+ "Ky8qIHN5c2ZzIGF0dHJpYnV0ZXMgZm9yIGh3bW9uICovCj4gKwo+ICtzdGF0aWMgc3NpemVfdCBh\n"
+ "ZHQ3NDEwX3Nob3dfdGVtcChzdHJ1Y3QgZGV2aWNlICpkZXYsCj4gKwkJCQkgc3RydWN0IGRldmlj\n"
+ "ZV9hdHRyaWJ1dGUgKmRhLCBjaGFyICpidWYpCj4gK3sKPiArCXN0cnVjdCBzZW5zb3JfZGV2aWNl\n"
+ "X2F0dHJpYnV0ZSAqYXR0ciA9IHRvX3NlbnNvcl9kZXZfYXR0cihkYSk7Cj4gKwlzdHJ1Y3QgYWR0\n"
+ "NzQxMF9kYXRhICpkYXRhID0gZGV2X2dldF9kcnZkYXRhKGRldik7Cj4gKwo+ICsKPiArCWlmIChh\n"
+ "dHRyLT5pbmRleCA9PSAwKSB7Cj4gKwkJaW50IHJldDsKPiArCj4gKwkJcmV0ID0gYWR0NzQxMF91\n"
+ "cGRhdGVfdGVtcChkZXYpOwo+ICsJCWlmIChyZXQpCj4gKwkJCXJldHVybiByZXQ7Cj4gKwl9Cj4g\n"
+ "Kwo+ICsJcmV0dXJuIHNwcmludGYoYnVmLCAiJWRcbiIsIEFEVDc0MTBfUkVHX1RPX1RFTVAoZGF0\n"
+ "YSwKPiArCQkgICAgICAgZGF0YS0+dGVtcFthdHRyLT5pbmRleF0pKTsKPiArfQo+ICsKPiArc3Rh\n"
+ "dGljIHNzaXplX3QgYWR0NzQxMF9zZXRfdGVtcChzdHJ1Y3QgZGV2aWNlICpkZXYsCj4gKwkJCQlz\n"
+ "dHJ1Y3QgZGV2aWNlX2F0dHJpYnV0ZSAqZGEsCj4gKwkJCQljb25zdCBjaGFyICpidWYsIHNpemVf\n"
+ "dCBjb3VudCkKPiArewo+ICsJc3RydWN0IHNlbnNvcl9kZXZpY2VfYXR0cmlidXRlICphdHRyID0g\n"
+ "dG9fc2Vuc29yX2Rldl9hdHRyKGRhKTsKPiArCXN0cnVjdCBhZHQ3NDEwX2RhdGEgKmRhdGEgPSBk\n"
+ "ZXZfZ2V0X2RydmRhdGEoZGV2KTsKPiArCWludCBuciA9IGF0dHItPmluZGV4Owo+ICsJbG9uZyB0\n"
+ "ZW1wOwo+ICsJaW50IHJldDsKPiArCj4gKwlyZXQgPSBrc3RydG9sKGJ1ZiwgMTAsICZ0ZW1wKTsK\n"
+ "PiArCWlmIChyZXQpCj4gKwkJcmV0dXJuIHJldDsKPiArCj4gKwltdXRleF9sb2NrKCZkYXRhLT51\n"
+ "cGRhdGVfbG9jayk7Cj4gKwlkYXRhLT50ZW1wW25yXSA9IEFEVDc0MTBfVEVNUF9UT19SRUcodGVt\n"
+ "cCk7Cj4gKwlyZXQgPSBhZHQ3NDEwX3dyaXRlX3dvcmQoZGV2LCBBRFQ3NDEwX1JFR19URU1QW25y\n"
+ "XSwgZGF0YS0+dGVtcFtucl0pOwo+ICsJaWYgKHJldCkKPiArCQljb3VudCA9IHJldDsKPiArCW11\n"
+ "dGV4X3VubG9jaygmZGF0YS0+dXBkYXRlX2xvY2spOwo+ICsJcmV0dXJuIGNvdW50Owo+ICt9Cj4g\n"
+ "Kwo+ICtzdGF0aWMgc3NpemVfdCBhZHQ3NDEwX3Nob3dfdF9oeXN0KHN0cnVjdCBkZXZpY2UgKmRl\n"
+ "diwKPiArCQkJCSAgIHN0cnVjdCBkZXZpY2VfYXR0cmlidXRlICpkYSwKPiArCQkJCSAgIGNoYXIg\n"
+ "KmJ1ZikKPiArewo+ICsJc3RydWN0IHNlbnNvcl9kZXZpY2VfYXR0cmlidXRlICphdHRyID0gdG9f\n"
+ "c2Vuc29yX2Rldl9hdHRyKGRhKTsKPiArCXN0cnVjdCBhZHQ3NDEwX2RhdGEgKmRhdGEgPSBkZXZf\n"
+ "Z2V0X2RydmRhdGEoZGV2KTsKPiArCWludCBuciA9IGF0dHItPmluZGV4Owo+ICsJaW50IGh5c3Q7\n"
+ "Cj4gKwo+ICsJaHlzdCA9IChkYXRhLT5oeXN0ICYgQURUNzQxMF9UX0hZU1RfTUFTSykgKiAxMDAw\n"
+ "Owo+ICsKPiArCS8qCj4gKwkgKiBoeXN0ZXJlc2lzIGlzIHN0b3JlZCBhcyBhIDQgYml0IG9mZnNl\n"
+ "dCBpbiB0aGUgZGV2aWNlLCBjb252ZXJ0IGl0Cj4gKwkgKiB0byBhbiBhYnNvbHV0ZSB2YWx1ZQo+\n"
+ "ICsJICovCj4gKwlpZiAobnIgPT0gMikJLyogbWluIGhhcyBwb3NpdGl2ZSBvZmZzZXQsIG90aGVy\n"
+ "cyBoYXZlIG5lZ2F0aXZlICovCj4gKwkJaHlzdCA9IC1oeXN0Owo+ICsJcmV0dXJuIHNwcmludGYo\n"
+ "YnVmLCAiJWRcbiIsCj4gKwkJICAgICAgIEFEVDc0MTBfUkVHX1RPX1RFTVAoZGF0YSwgZGF0YS0+\n"
+ "dGVtcFtucl0pIC0gaHlzdCk7Cj4gK30KPiArCj4gK3N0YXRpYyBzc2l6ZV90IGFkdDc0MTBfc2V0\n"
+ "X3RfaHlzdChzdHJ1Y3QgZGV2aWNlICpkZXYsCj4gKwkJCQkgIHN0cnVjdCBkZXZpY2VfYXR0cmli\n"
+ "dXRlICpkYSwKPiArCQkJCSAgY29uc3QgY2hhciAqYnVmLCBzaXplX3QgY291bnQpCj4gK3sKPiAr\n"
+ "CXN0cnVjdCBhZHQ3NDEwX2RhdGEgKmRhdGEgPSBkZXZfZ2V0X2RydmRhdGEoZGV2KTsKPiArCWlu\n"
+ "dCBsaW1pdCwgcmV0Owo+ICsJbG9uZyBoeXN0Owo+ICsKPiArCXJldCA9IGtzdHJ0b2woYnVmLCAx\n"
+ "MCwgJmh5c3QpOwo+ICsJaWYgKHJldCkKPiArCQlyZXR1cm4gcmV0Owo+ICsJLyogY29udmVydCBh\n"
+ "YnNvbHV0ZSBoeXN0ZXJlc2lzIHZhbHVlIHRvIGEgNCBiaXQgZGVsdGEgdmFsdWUgKi8KPiArCWxp\n"
+ "bWl0ID0gQURUNzQxMF9SRUdfVE9fVEVNUChkYXRhLCBkYXRhLT50ZW1wWzFdKTsKPiArCWh5c3Qg\n"
+ "PSBjbGFtcF92YWwoaHlzdCwgQURUNzQxMF9URU1QX01JTiwgQURUNzQxMF9URU1QX01BWCk7Cj4g\n"
+ "KwlkYXRhLT5oeXN0ID0gY2xhbXBfdmFsKERJVl9ST1VORF9DTE9TRVNUKGxpbWl0IC0gaHlzdCwg\n"
+ "MTAwMCksCj4gKwkJCQkgICAwLCBBRFQ3NDEwX1RfSFlTVF9NQVNLKTsKPiArCXJldCA9IGFkdDc0\n"
+ "MTBfd3JpdGVfYnl0ZShkZXYsIEFEVDc0MTBfVF9IWVNULCBkYXRhLT5oeXN0KTsKPiArCWlmIChy\n"
+ "ZXQpCj4gKwkJcmV0dXJuIHJldDsKPiArCj4gKwlyZXR1cm4gY291bnQ7Cj4gK30KPiArCj4gK3N0\n"
+ "YXRpYyBzc2l6ZV90IGFkdDc0MTBfc2hvd19hbGFybShzdHJ1Y3QgZGV2aWNlICpkZXYsCj4gKwkJ\n"
+ "CQkgIHN0cnVjdCBkZXZpY2VfYXR0cmlidXRlICpkYSwKPiArCQkJCSAgY2hhciAqYnVmKQo+ICt7\n"
+ "Cj4gKwlzdHJ1Y3Qgc2Vuc29yX2RldmljZV9hdHRyaWJ1dGUgKmF0dHIgPSB0b19zZW5zb3JfZGV2\n"
+ "X2F0dHIoZGEpOwo+ICsJdTggc3RhdHVzOwo+ICsJaW50IHJldDsKPiArCj4gKwlyZXQgPSBhZHQ3\n"
+ "NDEwX3JlYWRfYnl0ZShkZXYsIEFEVDc0MTBfU1RBVFVTLCAmc3RhdHVzKTsKPiArCWlmIChyZXQg\n"
+ "PCAwKQo+ICsJCXJldHVybiByZXQ7Cj4gKwo+ICsJcmV0dXJuIHNwcmludGYoYnVmLCAiJWRcbiIs\n"
+ "ICEhKHN0YXR1cyAmIGF0dHItPmluZGV4KSk7Cj4gK30KPiArCj4gK3N0YXRpYyBzc2l6ZV90IGFk\n"
+ "dDc0MTBfc2hvd19uYW1lKHN0cnVjdCBkZXZpY2UgKmRldiwKPiArCQkJCSAgc3RydWN0IGRldmlj\n"
+ "ZV9hdHRyaWJ1dGUgKmRhLCBjaGFyICpidWYpCj4gK3sKPiArCXN0cnVjdCBhZHQ3NDEwX2RhdGEg\n"
+ "KmRhdGEgPSBkZXZfZ2V0X2RydmRhdGEoZGV2KTsKPiArCj4gKwlyZXR1cm4gc3ByaW50ZihidWYs\n"
+ "ICIlc1xuIiwgZGF0YS0+bmFtZSk7Cj4gK30KPiArCj4gK3N0YXRpYyBTRU5TT1JfREVWSUNFX0FU\n"
+ "VFIodGVtcDFfaW5wdXQsIFNfSVJVR08sIGFkdDc0MTBfc2hvd190ZW1wLCBOVUxMLCAwKTsKPiAr\n"
+ "c3RhdGljIFNFTlNPUl9ERVZJQ0VfQVRUUih0ZW1wMV9tYXgsIFNfSVdVU1IgfCBTX0lSVUdPLAo+\n"
+ "ICsJCQkgIGFkdDc0MTBfc2hvd190ZW1wLCBhZHQ3NDEwX3NldF90ZW1wLCAxKTsKPiArc3RhdGlj\n"
+ "IFNFTlNPUl9ERVZJQ0VfQVRUUih0ZW1wMV9taW4sIFNfSVdVU1IgfCBTX0lSVUdPLAo+ICsJCQkg\n"
+ "IGFkdDc0MTBfc2hvd190ZW1wLCBhZHQ3NDEwX3NldF90ZW1wLCAyKTsKPiArc3RhdGljIFNFTlNP\n"
+ "Ul9ERVZJQ0VfQVRUUih0ZW1wMV9jcml0LCBTX0lXVVNSIHwgU19JUlVHTywKPiArCQkJICBhZHQ3\n"
+ "NDEwX3Nob3dfdGVtcCwgYWR0NzQxMF9zZXRfdGVtcCwgMyk7Cj4gK3N0YXRpYyBTRU5TT1JfREVW\n"
+ "SUNFX0FUVFIodGVtcDFfbWF4X2h5c3QsIFNfSVdVU1IgfCBTX0lSVUdPLAo+ICsJCQkgIGFkdDc0\n"
+ "MTBfc2hvd190X2h5c3QsIGFkdDc0MTBfc2V0X3RfaHlzdCwgMSk7Cj4gK3N0YXRpYyBTRU5TT1Jf\n"
+ "REVWSUNFX0FUVFIodGVtcDFfbWluX2h5c3QsIFNfSVJVR08sCj4gKwkJCSAgYWR0NzQxMF9zaG93\n"
+ "X3RfaHlzdCwgTlVMTCwgMik7Cj4gK3N0YXRpYyBTRU5TT1JfREVWSUNFX0FUVFIodGVtcDFfY3Jp\n"
+ "dF9oeXN0LCBTX0lSVUdPLAo+ICsJCQkgIGFkdDc0MTBfc2hvd190X2h5c3QsIE5VTEwsIDMpOwo+\n"
+ "ICtzdGF0aWMgU0VOU09SX0RFVklDRV9BVFRSKHRlbXAxX21pbl9hbGFybSwgU19JUlVHTywgYWR0\n"
+ "NzQxMF9zaG93X2FsYXJtLAo+ICsJCQkgIE5VTEwsIEFEVDc0MTBfU1RBVF9UX0xPVyk7Cj4gK3N0\n"
+ "YXRpYyBTRU5TT1JfREVWSUNFX0FUVFIodGVtcDFfbWF4X2FsYXJtLCBTX0lSVUdPLCBhZHQ3NDEw\n"
+ "X3Nob3dfYWxhcm0sCj4gKwkJCSAgTlVMTCwgQURUNzQxMF9TVEFUX1RfSElHSCk7Cj4gK3N0YXRp\n"
+ "YyBTRU5TT1JfREVWSUNFX0FUVFIodGVtcDFfY3JpdF9hbGFybSwgU19JUlVHTywgYWR0NzQxMF9z\n"
+ "aG93X2FsYXJtLAo+ICsJCQkgIE5VTEwsIEFEVDc0MTBfU1RBVF9UX0NSSVQpOwo+ICtzdGF0aWMg\n"
+ "REVWSUNFX0FUVFIobmFtZSwgU19JUlVHTywgYWR0NzQxMF9zaG93X25hbWUsIE5VTEwpOwo+ICsK\n"
+ "PiArc3RhdGljIHN0cnVjdCBhdHRyaWJ1dGUgKmFkdDc0MTBfYXR0cmlidXRlc1tdID0gewo+ICsJ\n"
+ "JnNlbnNvcl9kZXZfYXR0cl90ZW1wMV9pbnB1dC5kZXZfYXR0ci5hdHRyLAo+ICsJJnNlbnNvcl9k\n"
+ "ZXZfYXR0cl90ZW1wMV9tYXguZGV2X2F0dHIuYXR0ciwKPiArCSZzZW5zb3JfZGV2X2F0dHJfdGVt\n"
+ "cDFfbWluLmRldl9hdHRyLmF0dHIsCj4gKwkmc2Vuc29yX2Rldl9hdHRyX3RlbXAxX2NyaXQuZGV2\n"
+ "X2F0dHIuYXR0ciwKPiArCSZzZW5zb3JfZGV2X2F0dHJfdGVtcDFfbWF4X2h5c3QuZGV2X2F0dHIu\n"
+ "YXR0ciwKPiArCSZzZW5zb3JfZGV2X2F0dHJfdGVtcDFfbWluX2h5c3QuZGV2X2F0dHIuYXR0ciwK\n"
+ "PiArCSZzZW5zb3JfZGV2X2F0dHJfdGVtcDFfY3JpdF9oeXN0LmRldl9hdHRyLmF0dHIsCj4gKwkm\n"
+ "c2Vuc29yX2Rldl9hdHRyX3RlbXAxX21pbl9hbGFybS5kZXZfYXR0ci5hdHRyLAo+ICsJJnNlbnNv\n"
+ "cl9kZXZfYXR0cl90ZW1wMV9tYXhfYWxhcm0uZGV2X2F0dHIuYXR0ciwKPiArCSZzZW5zb3JfZGV2\n"
+ "X2F0dHJfdGVtcDFfY3JpdF9hbGFybS5kZXZfYXR0ci5hdHRyLAo+ICsJTlVMTAo+ICt9Owo+ICsK\n"
+ "PiArc3RhdGljIGNvbnN0IHN0cnVjdCBhdHRyaWJ1dGVfZ3JvdXAgYWR0NzQxMF9ncm91cCA9IHsK\n"
+ "PiArCS5hdHRycyA9IGFkdDc0MTBfYXR0cmlidXRlcywKPiArfTsKPiArCj4gK2ludCBhZHQ3NDEw\n"
+ "X3Byb2JlKHN0cnVjdCBkZXZpY2UgKmRldiwgY29uc3QgY2hhciAqbmFtZSwKPiArCWNvbnN0IHN0\n"
+ "cnVjdCBhZHQ3NDEwX29wcyAqb3BzKQo+ICt7Cj4gKwlzdHJ1Y3QgYWR0NzQxMF9kYXRhICpkYXRh\n"
+ "Owo+ICsJaW50IHJldDsKPiArCj4gKwlkYXRhID0gZGV2bV9remFsbG9jKGRldiwgc2l6ZW9mKHN0\n"
+ "cnVjdCBhZHQ3NDEwX2RhdGEpLAo+ICsJCQkgICAgR0ZQX0tFUk5FTCk7Cj4gKwlpZiAoIWRhdGEp\n"
+ "Cj4gKwkJcmV0dXJuIC1FTk9NRU07Cj4gKwo+ICsJZGF0YS0+b3BzID0gb3BzOwo+ICsJZGF0YS0+\n"
+ "bmFtZSA9IG5hbWU7Cj4gKwo+ICsJZGV2X3NldF9kcnZkYXRhKGRldiwgZGF0YSk7Cj4gKwltdXRl\n"
+ "eF9pbml0KCZkYXRhLT51cGRhdGVfbG9jayk7Cj4gKwo+ICsJLyogY29uZmlndXJlIGFzIHNwZWNp\n"
+ "ZmllZCAqLwo+ICsJcmV0ID0gYWR0NzQxMF9yZWFkX2J5dGUoZGV2LCBBRFQ3NDEwX0NPTkZJRywg\n"
+ "JmRhdGEtPm9sZGNvbmZpZyk7Cj4gKwlpZiAocmV0IDwgMCkgewo+ICsJCWRldl9kYmcoZGV2LCAi\n"
+ "Q2FuJ3QgcmVhZCBjb25maWc/ICVkXG4iLCByZXQpOwo+ICsJCXJldHVybiByZXQ7Cj4gKwl9Cj4g\n"
+ "KwkvKgo+ICsJICogU2V0IHRvIDE2IGJpdCByZXNvbHV0aW9uLCBjb250aW5vdXMgY29udmVyc2lv\n"
+ "biBhbmQgY29tcGFyYXRvciBtb2RlLgo+ICsJICovCj4gKwlkYXRhLT5jb25maWcgPSBkYXRhLT5v\n"
+ "bGRjb25maWc7Cj4gKwlkYXRhLT5jb25maWcgJj0gfkFEVDc0MTBfTU9ERV9NQVNLOwo+ICsJZGF0\n"
+ "YS0+Y29uZmlnIHw9IEFEVDc0MTBfRlVMTCB8IEFEVDc0MTBfUkVTT0xVVElPTiB8IEFEVDc0MTBf\n"
+ "RVZFTlRfTU9ERTsKPiArCWlmIChkYXRhLT5jb25maWcgIT0gZGF0YS0+b2xkY29uZmlnKSB7Cj4g\n"
+ "KwkJcmV0ID0gYWR0NzQxMF93cml0ZV9ieXRlKGRldiwgQURUNzQxMF9DT05GSUcsIGRhdGEtPmNv\n"
+ "bmZpZyk7Cj4gKwkJaWYgKHJldCkKPiArCQkJcmV0dXJuIHJldDsKPiArCX0KPiArCWRldl9kYmco\n"
+ "ZGV2LCAiQ29uZmlnICUwMnhcbiIsIGRhdGEtPmNvbmZpZyk7Cj4gKwo+ICsJcmV0ID0gYWR0NzQx\n"
+ "MF9maWxsX2NhY2hlKGRldik7Cj4gKwlpZiAocmV0KQo+ICsJCWdvdG8gZXhpdF9yZXN0b3JlOwo+\n"
+ "ICsKPiArCS8qIFJlZ2lzdGVyIHN5c2ZzIGhvb2tzICovCj4gKwlyZXQgPSBzeXNmc19jcmVhdGVf\n"
+ "Z3JvdXAoJmRldi0+a29iaiwgJmFkdDc0MTBfZ3JvdXApOwo+ICsJaWYgKHJldCkKPiArCQlnb3Rv\n"
+ "IGV4aXRfcmVzdG9yZTsKPiArCj4gKwkvKgo+ICsJICogVGhlIEkyQyBkZXZpY2Ugd2lsbCBhbHJl\n"
+ "YWR5IGhhdmUgaXQncyBvd24gJ25hbWUnIGF0dHJpYnV0ZSwgYnV0IGZvcgo+ICsJICogdGhlIFNQ\n"
+ "SSBkZXZpY2Ugd2UgbmVlZCB0byByZWdpc3RlciBpdC4gbmFtZSB3aWxsIG9ubHkgYmUgbm9uIE5V\n"
+ "TEwgaWYKPiArCSAqIHRoZSBkZXZpY2UgZG9lc24ndCByZWdpc3RlciB0aGUgJ25hbWUnIGF0dHJp\n"
+ "YnV0ZSBvbiBpdHMgb3duLgo+ICsJICovCj4gKwlpZiAobmFtZSkgewo+ICsJCXJldCA9IGRldmlj\n"
+ "ZV9jcmVhdGVfZmlsZShkZXYsICZkZXZfYXR0cl9uYW1lKTsKPiArCQlpZiAocmV0KQo+ICsJCQln\n"
+ "b3RvIGV4aXRfcmVtb3ZlOwo+ICsJfQo+ICsKPiArCWRhdGEtPmh3bW9uX2RldiA9IGh3bW9uX2Rl\n"
+ "dmljZV9yZWdpc3RlcihkZXYpOwo+ICsJaWYgKElTX0VSUihkYXRhLT5od21vbl9kZXYpKSB7Cj4g\n"
+ "KwkJcmV0ID0gUFRSX0VSUihkYXRhLT5od21vbl9kZXYpOwo+ICsJCWdvdG8gZXhpdF9yZW1vdmVf\n"
+ "bmFtZTsKPiArCX0KPiArCj4gKwlyZXR1cm4gMDsKPiArCj4gK2V4aXRfcmVtb3ZlX25hbWU6Cj4g\n"
+ "KwlpZiAobmFtZSkKPiArCQlkZXZpY2VfcmVtb3ZlX2ZpbGUoZGV2LCAmZGV2X2F0dHJfbmFtZSk7\n"
+ "Cj4gK2V4aXRfcmVtb3ZlOgo+ICsJc3lzZnNfcmVtb3ZlX2dyb3VwKCZkZXYtPmtvYmosICZhZHQ3\n"
+ "NDEwX2dyb3VwKTsKPiArZXhpdF9yZXN0b3JlOgo+ICsJYWR0NzQxMF93cml0ZV9ieXRlKGRldiwg\n"
+ "QURUNzQxMF9DT05GSUcsIGRhdGEtPm9sZGNvbmZpZyk7Cj4gKwlyZXR1cm4gcmV0Owo+ICt9Cj4g\n"
+ "K0VYUE9SVF9TWU1CT0xfR1BMKGFkdDc0MTBfcHJvYmUpOwo+ICsKPiAraW50IGFkdDc0MTBfcmVt\n"
+ "b3ZlKHN0cnVjdCBkZXZpY2UgKmRldikKPiArewo+ICsJc3RydWN0IGFkdDc0MTBfZGF0YSAqZGF0\n"
+ "YSA9IGRldl9nZXRfZHJ2ZGF0YShkZXYpOwo+ICsKPiArCWh3bW9uX2RldmljZV91bnJlZ2lzdGVy\n"
+ "KGRhdGEtPmh3bW9uX2Rldik7Cj4gKwlpZiAoZGF0YS0+bmFtZSkKPiArCQlkZXZpY2VfcmVtb3Zl\n"
+ "X2ZpbGUoZGV2LCAmZGV2X2F0dHJfbmFtZSk7Cj4gKwlzeXNmc19yZW1vdmVfZ3JvdXAoJmRldi0+\n"
+ "a29iaiwgJmFkdDc0MTBfZ3JvdXApOwo+ICsJaWYgKGRhdGEtPm9sZGNvbmZpZyAhPSBkYXRhLT5j\n"
+ "b25maWcpCj4gKwkJYWR0NzQxMF93cml0ZV9ieXRlKGRldiwgQURUNzQxMF9DT05GSUcsCj4gKwkJ\n"
+ "CQkJICBkYXRhLT5vbGRjb25maWcpOwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArRVhQT1JUX1NZTUJP\n"
+ "TF9HUEwoYWR0NzQxMF9yZW1vdmUpOwo+ICsKPiArI2lmZGVmIENPTkZJR19QTV9TTEVFUAo+ICsK\n"
+ "PiArc3RhdGljIGludCBhZHQ3NDEwX3N1c3BlbmQoc3RydWN0IGRldmljZSAqZGV2KQo+ICt7Cj4g\n"
+ "KwlzdHJ1Y3QgYWR0NzQxMF9kYXRhICpkYXRhID0gZGV2X2dldF9kcnZkYXRhKGRldik7Cj4gKwo+\n"
+ "ICsJcmV0dXJuIGFkdDc0MTBfd3JpdGVfYnl0ZShkZXYsIEFEVDc0MTBfQ09ORklHLAo+ICsJCWRh\n"
+ "dGEtPmNvbmZpZyB8IEFEVDc0MTBfUEQpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGFkdDc0MTBf\n"
+ "cmVzdW1lKHN0cnVjdCBkZXZpY2UgKmRldikKPiArewo+ICsJc3RydWN0IGFkdDc0MTBfZGF0YSAq\n"
+ "ZGF0YSA9IGRldl9nZXRfZHJ2ZGF0YShkZXYpOwo+ICsKPiArCXJldHVybiBhZHQ3NDEwX3dyaXRl\n"
+ "X2J5dGUoZGV2LCBBRFQ3NDEwX0NPTkZJRywgZGF0YS0+Y29uZmlnKTsKPiArfQo+ICsKPiArU0lN\n"
+ "UExFX0RFVl9QTV9PUFMoYWR0NzQxMF9kZXZfcG1fb3BzLCBhZHQ3NDEwX3N1c3BlbmQsIGFkdDc0\n"
+ "MTBfcmVzdW1lKTsKPiArRVhQT1JUX1NZTUJPTF9HUEwoYWR0NzQxMF9kZXZfcG1fb3BzKTsKPiAr\n"
+ "Cj4gKyNlbmRpZiAvKiBDT05GSUdfUE1fU0xFRVAgKi8KPiArCj4gK01PRFVMRV9BVVRIT1IoIkhh\n"
+ "cnRtdXQgS25hYWNrIik7Cj4gK01PRFVMRV9ERVNDUklQVElPTigiQURUNzQxMCBkcml2ZXIiKTsK\n"
+ "VGhpcyBkZXNjcmlwdGlvbiBkb2VzIG5vdCBzZWVtIGFwcHJvcHJpYXRlIGFueSBsb25nZXIuCj4g\n"
+ "K01PRFVMRV9MSUNFTlNFKCJHUEwiKTsKPC4uLj4KCgpfX19fX19fX19fX19fX19fX19fX19fX19f\n"
+ "X19fX19fX19fX19fX19fX19fX19fXwpsbS1zZW5zb3JzIG1haWxpbmcgbGlzdApsbS1zZW5zb3Jz\n"
+ "QGxtLXNlbnNvcnMub3JnCmh0dHA6Ly9saXN0cy5sbS1zZW5zb3JzLm9yZy9tYWlsbWFuL2xpc3Rp\n"
+ bmZvL2xtLXNlbnNvcnM
 
-0c60dedeaf7e3dae62f889ca03e4f9c17ec1e735983edd37c0c5a0a52f7e6be1
+bf588b90694bc2834dad1a4d900d2dd9dfb61422090daa500576e309049851a8

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.