linux-iio.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2] iio: adc: add CSR SiRFSoC internal ADC driver
@ 2014-07-17  9:22 Guoying Zhang
  2014-07-20 14:33 ` Jonathan Cameron
  2014-07-27 12:04 ` Hartmut Knaack
  0 siblings, 2 replies; 5+ messages in thread
From: Guoying Zhang @ 2014-07-17  9:22 UTC (permalink / raw)
  To: jic23; +Cc: linux-iio, workgroup.linux, Guoying Zhang, Peter Meerwald,
	Barry Song

SiRFSoC internal ADC provides touchscreen single or dual touch
channels, and provides several auxiliary channels to measure
temperature, battery and so on.

Cc: Peter Meerwald <pmeerw@pmeerw.net>
Signed-off-by: Guoying Zhang <Guoying.Zhang@csr.com>
Signed-off-by: Barry Song <Baohua.Song@csr.com>
---
 -v2: fix many issues from Peter and Jonathan's feedbacks

 .../devicetree/bindings/iio/adc/sirfsoc_adc.txt    |  33 +
 drivers/iio/adc/Kconfig                            |  10 +
 drivers/iio/adc/Makefile                           |   1 +
 drivers/iio/adc/sirfsoc_adc.c                      | 755 +++++++++++++++++++++
 4 files changed, 799 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/adc/sirfsoc_adc.txt
 create mode 100644 drivers/iio/adc/sirfsoc_adc.c

diff --git a/Documentation/devicetree/bindings/iio/adc/sirfsoc_adc.txt b/Documentation/devicetree/bindings/iio/adc/sirfsoc_adc.txt
new file mode 100644
index 0000000..70eaf40
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/adc/sirfsoc_adc.txt
@@ -0,0 +1,33 @@
+Sirfsoc inner Analog to Digital Converter bindings
+
+The devicetree bindings are for the new ADC driver written for
+Prima2/Atlas6 CSR.
+
+Required properties:
+- compatible: Should be one of
+	* "sirf,prima2-adc": When use Prima2 SOC
+	* "sirf,atlas6-adc": When use Atlas6 SOC
+- reg: Offset and length of the register set for the device
+- interrupts: Should contain the interrupt for the device
+- clocks: The clock is needed by the ADC controller
+- resets: The reset for the device
+- #io-channel-cells: Should be set to <1>
+
+Example:
+	adc: adc@b0110000 {
+		compatible = "sirf,prima2-adc";
+		reg = <0xb0110000 0x10000>;
+		interrupts = <34>;
+		clocks = <&clks 16>;
+		resets = <&rstc 32>;
+		#io-channel-cells = <1>;
+	};
+
+	adc: adc@b0110000 {
+		compatible = "sirf,atlas6-adc";
+		reg = <0xb0110000 0x10000>;
+		interrupts = <34>;
+		clocks = <&clks 16>;
+		resets = <&rstc 32>;
+		#io-channel-cells = <1>;
+	};
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index a80d236..6b803d5 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -187,6 +187,16 @@ config NAU7802
 	  To compile this driver as a module, choose M here: the
 	  module will be called nau7802.
 
+config SIRFSOC_ADC
+	tristate "SiRFSoC ADC"
+	depends on ARCH_SIRF
+	help
+	  If you say yes here you get support for CSR SiRFSoC internal
+	  ADC.
+
+	  This driver can also be built as a module. If so, the module will be
+	  called sirfsoc_adc.
+
 config TI_ADC081C
 	tristate "Texas Instruments ADC081C021/027"
 	depends on I2C
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 9d60f2d..2912e58 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_MCP320X) += mcp320x.o
 obj-$(CONFIG_MCP3422) += mcp3422.o
 obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o
 obj-$(CONFIG_NAU7802) += nau7802.o
+obj-$(CONFIG_SIRFSOC_ADC) += sirfsoc_adc.o
 obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o
 obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o
 obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o
diff --git a/drivers/iio/adc/sirfsoc_adc.c b/drivers/iio/adc/sirfsoc_adc.c
new file mode 100644
index 0000000..ae11a36
--- /dev/null
+++ b/drivers/iio/adc/sirfsoc_adc.c
@@ -0,0 +1,755 @@
+/*
+* ADC Driver for CSR SiRFSoC
+*
+* Copyright (c) 2014 Cambridge Silicon Radio Limited, a CSR plc group company.
+*
+* Licensed under GPLv2.
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/of.h>
+#include <linux/pm.h>
+#include <linux/platform_device.h>
+#include <linux/of_platform.h>
+#include <linux/reset.h>
+#include <linux/rtc/sirfsoc_rtciobrg.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/machine.h>
+#include <linux/iio/driver.h>
+
+#define DRIVER_NAME "sirfsoc_adc"
+
+#define SIRFSOC_PWR_WAKEEN_TSC_SHIFT	23
+#define SIRFSOC_PWR_WAKEEN_TS_SHIFT	5
+#define SIRFSOC_PWRC_TRIGGER_EN		0x8
+#define SIRFSOC_PWRC_BASE		0x3000
+
+/* Registers offset */
+#define SIRFSOC_ADC_CONTROL1		0x00
+#define SIRFSOC_ADC_CONTROL2		0x04
+#define SIRFSOC_ADC_INTR		0x08
+#define SIRFSOC_ADC_COORD		0x0C
+#define SIRFSOC_ADC_PRESSURE		0x10
+#define SIRFSOC_ADC_AUX1		0x14
+/* Atlas6 AUX2 and AUX4 reserved*/
+#define SIRFSOC_ADC_AUX2		0x18
+#define SIRFSOC_ADC_AUX3		0x1C
+#define SIRFSOC_ADC_AUX4		0x20
+#define SIRFSOC_ADC_AUX5		0x24
+#define SIRFSOC_ADC_AUX6		0x28
+/* Read Back calibration register */
+#define SIRFSOC_ADC_CB			0x2C
+#define SIRFSOC_ADC_COORD2		0x30
+#define SIRFSOC_ADC_COORD3		0x34
+#define SIRFSOC_ADC_COORD4		0x38
+
+/* CTRL1 defines */
+#define SIRFSOC_ADC_RESET_QUANT_EN	BIT(24)
+#define SIRFSOC_ADC_RST_B		BIT(23)
+#define SIRFSOC_ADC_RESOLUTION_12	BIT(22)
+#define SIRFSOC_ADC_RBAT_DISABLE	(0x0 << 21)
+#define SIRFSOC_ADC_RBAT_ENABLE		(0x1 << 21)
+#define SIRFSOC_ADC_EXTCM(x)		(((x) & 0x3) << 19)
+#define SIRFSOC_ADC_SGAIN(x)		(((x) & 0x7) << 16)
+#define SIRFSOC_ADC_POLL		BIT(15)
+#define SIRFSOC_ADC_SEL(x)		(((x) & 0xF) << 11)
+#define SIRFSOC_ADC_FREQ_6K		(0x0 << 8)
+#define SIRFSOC_ADC_FREQ_13K		BIT(8)
+#define SIRFSOC_ADC_DEL_SET(x)		(((x) & 0xF) << 4)
+#define SIRFSOC_ADC_TP_TIME(x)		(((x) & 0x7) << 0)
+
+/* CTRL2 defines */
+/* Pen detector off, digitizer off */
+#define SIRFSOC_ADC_PRP_MODE0		(0 << 14)
+/* Pen detector on, digitizer off, digitizer wakes up on pen detect */
+#define SIRFSOC_ADC_PRP_MODE1		BIT(14)
+/* Pen detector on, digitizer off, no wake up on pen detect */
+#define SIRFSOC_ADC_PRP_MODE2		(2 << 14)
+/* Pen detector on, digitizer on */
+#define SIRFSOC_ADC_PRP_MODE3		(3 << 14)
+#define SIRFSOC_ADC_RTOUCH(x)		(((x) & 0x3) << 12)
+#define SIRFSOC_ADC_DEL_PRE(x)		(((x) & 0xF) << 4)
+#define SIRFSOC_ADC_DEL_DIS(x)		(((x) & 0xF) << 0)
+
+/* INTR register defines */
+#define SIRFSOC_ADC_PEN_INTR_EN		BIT(5)
+#define SIRFSOC_ADC_DATA_INTR_EN	BIT(4)
+#define SIRFSOC_ADC_PEN_INTR		BIT(1)
+#define SIRFSOC_ADC_DATA_INTR		BIT(0)
+
+/* DATA register defines */
+#define SIRFSOC_ADC_PEN_DOWN		BIT(31)
+#define SIRFSOC_ADC_DATA_AUXVALID	BIT(30)
+#define SIRFSOC_ADC_DATA_CB_VALID	BIT(30)
+#define SIRFSOC_ADC_ADC_DATA_MASK(x)	(0x3FFF << (x))
+#define SIRFSOC_ADC_DATA_AUXMASK	SIRFSOC_ADC_ADC_DATA_MASK(0)
+#define SIRFSOC_ADC_DATA_CBMASK		SIRFSOC_ADC_ADC_DATA_MASK(0)
+
+#define SIRFSOC_ADC_MORE_CTL1	(of_machine_is_compatible("sirf,atlas6") ?\
+				(SIRFSOC_ADC_RESET_QUANT_EN |\
+				SIRFSOC_ADC_RST_B) : (0))
+
+/* Select AD samples to read (SEL bits in ADC_CONTROL1 register) */
+#define SIRFSOC_ADC_AUX1_SEL	0x04
+#define SIRFSOC_ADC_AUX2_SEL	0x05
+#define SIRFSOC_ADC_AUX3_SEL	0x06
+#define SIRFSOC_ADC_AUX4_SEL	0x07
+#define SIRFSOC_ADC_AUX5_SEL	0x08
+#define SIRFSOC_ADC_AUX6_SEL	0x09
+#define SIRFSOC_ADC_TS_SEL	0x0A    /* Sample for single touch*/
+#define SIRFSOC_ADC_GROUND_SEL	0x0B    /* Gound for offset calibration */
+#define SIRFSOC_ADC_BANDGAP_SEL	0x0C    /* Bandgap for gain calibration */
+#define SIRFSOC_ADC_TS_SEL_DUAL	0x0F    /* Samples for dual touch */
+
+#define SIRFSOC_ADC_TS_SAMPLE_SIZE	4
+#define SIRFSOC_ADC_CTL1(sel)    (SIRFSOC_ADC_POLL | SIRFSOC_ADC_SEL(sel) |\
+		SIRFSOC_ADC_DEL_SET(6) | SIRFSOC_ADC_FREQ_6K |\
+		SIRFSOC_ADC_TP_TIME(0) | SIRFSOC_ADC_SGAIN(0) |\
+		SIRFSOC_ADC_EXTCM(0) | SIRFSOC_ADC_RBAT_DISABLE |\
+		SIRFSOC_ADC_MORE_CTL1)
+
+enum sirfsoc_adc_chips {
+	PRIMA2,
+	ATLAS6,
+};
+
+struct sirfsoc_adc_chip_info {
+	const struct iio_chan_spec *channels;
+	unsigned int num_channels;
+	unsigned int flags;
+	const struct iio_info *iio_info;
+
+	u32 (*calculate_volt)(u32, u32, u32);
+	const u32 *channel_sel;
+};
+
+struct sirfsoc_adc_request {
+	u16 mode;
+	u16 extcm;
+	u16 reference;
+	u8 delay_bits;
+	u32 s_gain_bits;
+	u16 read_back_data;
+};
+
+struct sirfsoc_adc {
+	const struct sirfsoc_adc_chip_info	*chip_info;
+	struct clk	*clk;
+	void __iomem	*base;
+	struct sirfsoc_adc_request req;
+	struct completion	done;
+	struct mutex	adc_lock;
+};
+
+static const u32 sirfsoc_adc_ts_reg[SIRFSOC_ADC_TS_SAMPLE_SIZE] = {
+	/* Dual touch samples read registers*/
+	SIRFSOC_ADC_COORD, SIRFSOC_ADC_COORD2,
+	SIRFSOC_ADC_COORD3, SIRFSOC_ADC_COORD4
+};
+
+enum sirfsoc_adc_ts_type {
+	SINGLE_TOUCH,
+	DUAL_TOUCH,
+};
+
+static int sirfsoc_adc_get_ts_sample(
+	struct sirfsoc_adc *adc, int *sample, int touch_type)
+{
+	int adc_intr;
+	int ret = 0;
+	int i;
+
+	mutex_lock(&adc->adc_lock);
+	adc_intr = readl(adc->base + SIRFSOC_ADC_INTR);
+	if (adc_intr & SIRFSOC_ADC_PEN_INTR)
+		writel(SIRFSOC_ADC_PEN_INTR | SIRFSOC_ADC_PEN_INTR_EN |
+			SIRFSOC_ADC_DATA_INTR_EN,
+			adc->base + SIRFSOC_ADC_INTR);
+
+	/* check pen status */
+	if (!(readl(adc->base + SIRFSOC_ADC_COORD) & SIRFSOC_ADC_PEN_DOWN)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (SINGLE_TOUCH == touch_type)
+		writel(SIRFSOC_ADC_CTL1(SIRFSOC_ADC_TS_SEL),
+			adc->base + SIRFSOC_ADC_CONTROL1);
+	else
+		writel(SIRFSOC_ADC_CTL1(SIRFSOC_ADC_TS_SEL_DUAL),
+			adc->base + SIRFSOC_ADC_CONTROL1);
+
+	if (!wait_for_completion_timeout(&adc->done,
+		msecs_to_jiffies(50))) {
+		ret = -EIO;
+		goto out;
+	}
+
+	if (SINGLE_TOUCH == touch_type)
+		*sample = readl(adc->base + SIRFSOC_ADC_COORD);
+	else
+		for (i = 0; i < SIRFSOC_ADC_TS_SAMPLE_SIZE; i++)
+			sample[i] = readl(adc->base + sirfsoc_adc_ts_reg[i]);
+
+out:
+	mutex_unlock(&adc->adc_lock);
+	return ret;
+}
+
+/* get touchscreen coordinates for single touch */
+static int sirfsoc_adc_single_ts_sample(struct sirfsoc_adc *adc, int *sample)
+{
+	return sirfsoc_adc_get_ts_sample(adc, sample, SINGLE_TOUCH);
+}
+
+/* get touchscreen coordinates for dual touch */
+static int sirfsoc_adc_dual_ts_sample(struct sirfsoc_adc *adc, int *samples)
+{
+	return sirfsoc_adc_get_ts_sample(adc, samples, DUAL_TOUCH);
+}
+
+static int sirfsoc_adc_send_request(struct sirfsoc_adc_request *req)
+{
+	struct sirfsoc_adc *adc = container_of(req, struct sirfsoc_adc, req);
+	int control1, control2, intr;
+	int data, reg_offset;
+	int ret = 0;
+
+	mutex_lock(&adc->adc_lock);
+
+	/* Store registers for recover */
+	intr = readl(adc->base + SIRFSOC_ADC_INTR);
+	control1 = readl(adc->base + SIRFSOC_ADC_CONTROL1);
+	control2 = readl(adc->base + SIRFSOC_ADC_CONTROL2);
+
+	writel(intr | SIRFSOC_ADC_DATA_INTR_EN | SIRFSOC_ADC_DATA_INTR,
+		adc->base + SIRFSOC_ADC_INTR);
+	writel(SIRFSOC_ADC_PRP_MODE3 | req->reference,
+		adc->base + SIRFSOC_ADC_CONTROL2);
+	writel(SIRFSOC_ADC_POLL | SIRFSOC_ADC_MORE_CTL1 | req->mode |
+		req->extcm | req->delay_bits | SIRFSOC_ADC_RESOLUTION_12,
+		adc->base + SIRFSOC_ADC_CONTROL1);
+
+	if (!wait_for_completion_timeout(&adc->done,
+		msecs_to_jiffies(50))) {
+		ret = -EIO;
+		goto out;
+	}
+
+	switch (req->mode) {
+	case SIRFSOC_ADC_SEL(SIRFSOC_ADC_AUX1_SEL):
+	case SIRFSOC_ADC_SEL(SIRFSOC_ADC_AUX2_SEL):
+	case SIRFSOC_ADC_SEL(SIRFSOC_ADC_AUX3_SEL):
+	case SIRFSOC_ADC_SEL(SIRFSOC_ADC_AUX4_SEL):
+	case SIRFSOC_ADC_SEL(SIRFSOC_ADC_AUX5_SEL):
+	case SIRFSOC_ADC_SEL(SIRFSOC_ADC_AUX6_SEL):
+		/* Calculate aux offset from mode */
+		reg_offset = 0x14 + ((req->mode >> 11) - 0x04) * 4;
+		data = readl(adc->base + reg_offset);
+		if (data & SIRFSOC_ADC_DATA_AUXVALID)
+			req->read_back_data = data & SIRFSOC_ADC_DATA_AUXMASK;
+		break;
+	case SIRFSOC_ADC_SEL(SIRFSOC_ADC_GROUND_SEL):
+	case SIRFSOC_ADC_SEL(SIRFSOC_ADC_BANDGAP_SEL):
+		reg_offset = SIRFSOC_ADC_CB;
+		data = readl(adc->base + reg_offset);
+		if (data & SIRFSOC_ADC_DATA_CB_VALID)
+			req->read_back_data = data & SIRFSOC_ADC_DATA_CBMASK;
+		break;
+	default:
+		break;
+	}
+
+out:
+	writel(intr, adc->base + SIRFSOC_ADC_INTR);
+	writel(control1, adc->base + SIRFSOC_ADC_CONTROL1);
+	writel(control2, adc->base + SIRFSOC_ADC_CONTROL2);
+	mutex_unlock(&adc->adc_lock);
+	return ret;
+}
+
+/* Store params to calibrate */
+struct sirfsoc_adc_cali_data {
+	u32 digital_offset;
+	u32 digital_again;
+	bool is_calibration;
+};
+
+/* Offset Calibration calibrates the ADC offset error */
+static u32 sirfsoc_adc_offset_cali(struct sirfsoc_adc_request *req)
+{
+	u32 i, digital_offset = 0, count = 0, sum = 0;
+	/* To set the registers in order to get the ADC offset */
+	req->mode = SIRFSOC_ADC_SEL(SIRFSOC_ADC_GROUND_SEL);
+	req->extcm = SIRFSOC_ADC_EXTCM(0);
+	req->s_gain_bits = SIRFSOC_ADC_SGAIN(7);
+	req->delay_bits = SIRFSOC_ADC_DEL_SET(4);
+
+	for (i = 0; i < 10; i++) {
+		if (sirfsoc_adc_send_request(req))
+			break;
+		digital_offset = req->read_back_data;
+		sum += digital_offset;
+		count++;
+	}
+	if (!count)
+		digital_offset = 0;
+	else
+		digital_offset = sum / count;
+
+	return digital_offset;
+}
+
+
+/* Gain Calibration calibrates the ADC gain error */
+static u32 sirfsoc_adc_gain_cali(struct sirfsoc_adc_request *req)
+{
+	u32 i, digital_gain = 0, count = 0, sum = 0;
+	/* To set the registers in order to get the ADC gain */
+	req->mode = SIRFSOC_ADC_SEL(SIRFSOC_ADC_BANDGAP_SEL);
+	req->extcm = SIRFSOC_ADC_EXTCM(0);
+	req->s_gain_bits = SIRFSOC_ADC_SGAIN(1);
+	req->delay_bits = SIRFSOC_ADC_DEL_SET(4);
+
+	for (i = 0; i < 10; i++) {
+		if (sirfsoc_adc_send_request(req))
+			break;
+		digital_gain = req->read_back_data;
+		sum += digital_gain;
+		count++;
+	}
+	if (!count)
+		digital_gain = 0;
+	else
+		digital_gain = sum / count;
+
+	return digital_gain;
+}
+
+/* Absolute gain calibration */
+static int sirfsoc_adc_adc_cali(struct sirfsoc_adc_request *req,
+				struct sirfsoc_adc_cali_data *cali_data)
+{
+	cali_data->digital_offset = sirfsoc_adc_offset_cali(req);
+	if (!cali_data->digital_offset)
+		return -EINVAL;
+	cali_data->digital_again = sirfsoc_adc_gain_cali(req);
+	if (!cali_data->digital_again)
+		return -EINVAL;
+
+	return 0;
+}
+
+/* Get voltage after ADC conversion */
+static u32 sirfsoc_adc_get_adc_volt(struct sirfsoc_adc *adc,
+				struct sirfsoc_adc_cali_data *cali_data)
+{
+	u32 digital_out, volt;
+	struct sirfsoc_adc_request *req = &adc->req;
+
+	req->s_gain_bits = SIRFSOC_ADC_SGAIN(0);
+	req->delay_bits = SIRFSOC_ADC_DEL_SET(4);
+
+	/*
+	 * First read original data
+	 * then read calibrate errors
+	 */
+	sirfsoc_adc_send_request(req);
+	if (req->read_back_data) {
+		digital_out = req->read_back_data;
+		/* Get errors for each sample */
+		if (!cali_data->is_calibration) {
+			if (sirfsoc_adc_adc_cali(req, cali_data))
+				return 0;
+			cali_data->is_calibration = true;
+		}
+
+		volt = adc->chip_info->calculate_volt(digital_out,
+			cali_data->digital_offset,
+			cali_data->digital_again);
+	} else {
+		return 0;
+	}
+
+	return volt;
+}
+
+static u32 prima2_adc_calculate_volt(u32 digital_out,
+				u32 digital_offset, u32 digital_again)
+{
+	u32 volt, digital_ideal, digital_convert;
+
+	/*
+	 * see Equation 3.2 of SiRFPrimaII™ Internal ADC and Touch
+	 * User Guide
+	 */
+	digital_ideal = (5522 * 1200) / (7 * 333);
+	/*
+	 * see Equation 3.3 of SiRFatlasVI™ Internal ADC and Touch
+	 */
+	digital_convert = (digital_out - 11645 * digital_offset /
+		140000) * digital_ideal / (digital_again
+		- digital_offset * 11645 / 70000);
+	volt = 14 * 333 * digital_convert / 5522;
+
+	return volt;
+}
+
+static u32 atlas6_adc_calculate_volt(u32 digital_out,
+				u32 digital_offset, u32 digital_again)
+{
+	u32 volt, digital_ideal, digital_convert;
+
+	/*
+	 * see Equation 3.2 of SiRFatlasVI™ Internal ADC and Touch
+	 * User Guide
+	 */
+	digital_ideal = (3986 * 12100) / (7 * 3333);
+	/*
+	 * see Equation 3.3 of SiRFatlasVI™ Internal ADC and Touch
+	 */
+	digital_offset &= 0xfff;
+	digital_convert = abs(digital_out - 2 * digital_offset)
+		* digital_ideal / (digital_again
+		- digital_offset * 2);
+	volt = 14 * 333 * digital_convert / 3986;
+	volt = volt / 2;
+	if (volt > 1500)
+		volt = volt - (volt - 1500) / 15;
+	else
+		volt = volt + (1500 - volt) / 28;
+
+	return volt;
+}
+
+static irqreturn_t sirfsoc_adc_data_irq(int irq, void *handle)
+{
+	struct iio_dev *indio_dev = handle;
+	struct sirfsoc_adc *adc = iio_priv(indio_dev);
+	int val;
+
+	val = readl(adc->base + SIRFSOC_ADC_INTR);
+
+	writel(SIRFSOC_ADC_PEN_INTR | SIRFSOC_ADC_PEN_INTR_EN |
+		SIRFSOC_ADC_DATA_INTR | SIRFSOC_ADC_DATA_INTR_EN,
+		adc->base + SIRFSOC_ADC_INTR);
+
+	if (val & SIRFSOC_ADC_DATA_INTR)
+		complete(&adc->done);
+
+	return IRQ_HANDLED;
+}
+
+static int sirfsoc_adc_read_raw(struct iio_dev *indio_dev,
+				struct iio_chan_spec const *chan,
+				int *val,
+				int *val2,
+				long mask)
+{
+	struct sirfsoc_adc *adc = iio_priv(indio_dev);
+	struct sirfsoc_adc_cali_data cali_data;
+	int ret;
+
+	cali_data.is_calibration = false;
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		if (0 == chan->channel)
+			ret = sirfsoc_adc_single_ts_sample(adc, val);
+		else
+			ret = sirfsoc_adc_dual_ts_sample(adc, val);
+
+		if (ret)
+			return ret;
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_PROCESSED:
+		adc->req.mode = SIRFSOC_ADC_SEL(
+			adc->chip_info->channel_sel[chan->channel]);
+		adc->req.extcm = SIRFSOC_ADC_EXTCM(0);
+		*val = sirfsoc_adc_get_adc_volt(adc, &cali_data);
+		return IIO_VAL_INT;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int sirfsoc_adc_suspend(struct device *dev)
+{
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct sirfsoc_adc *adc = iio_priv(indio_dev);
+
+	sirfsoc_rtc_iobrg_writel(sirfsoc_rtc_iobrg_readl(
+		SIRFSOC_PWRC_BASE + SIRFSOC_PWRC_TRIGGER_EN)
+		& ~BIT(SIRFSOC_PWR_WAKEEN_TSC_SHIFT),
+		SIRFSOC_PWRC_BASE + SIRFSOC_PWRC_TRIGGER_EN);
+
+	clk_disable_unprepare(adc->clk);
+
+	return 0;
+}
+
+static int sirfsoc_adc_resume(struct device *dev)
+{
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct sirfsoc_adc *adc = iio_priv(indio_dev);
+	int ret;
+	int val;
+
+	clk_prepare_enable(adc->clk);
+
+	sirfsoc_rtc_iobrg_writel(sirfsoc_rtc_iobrg_readl(
+		SIRFSOC_PWRC_BASE + SIRFSOC_PWRC_TRIGGER_EN) |
+		BIT(SIRFSOC_PWR_WAKEEN_TS_SHIFT),
+		SIRFSOC_PWRC_BASE + SIRFSOC_PWRC_TRIGGER_EN);
+
+	ret = device_reset(dev);
+	if (ret) {
+		dev_err(dev, "Failed to reset\n");
+		return ret;
+	}
+
+	writel(SIRFSOC_ADC_PRP_MODE3 | SIRFSOC_ADC_RTOUCH(1) |
+		SIRFSOC_ADC_DEL_PRE(2) | SIRFSOC_ADC_DEL_DIS(5),
+		adc->base + SIRFSOC_ADC_CONTROL2);
+
+	val = readl(adc->base + SIRFSOC_ADC_INTR);
+
+	/* Clear interrupts and enable PEN interrupt */
+	writel(val | SIRFSOC_ADC_PEN_INTR | SIRFSOC_ADC_DATA_INTR |
+		SIRFSOC_ADC_PEN_INTR_EN | SIRFSOC_ADC_DATA_INTR_EN,
+		adc->base + SIRFSOC_ADC_INTR);
+
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops sirfsoc_adc_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(sirfsoc_adc_suspend, sirfsoc_adc_resume)
+};
+
+#define SIRFSOC_ADC_CHANNEL(_channel, _type, _name, _mask) {	\
+	.type = _type,					\
+	.indexed = 1,					\
+	.channel = _channel,				\
+	.datasheet_name = _name,			\
+	.info_mask_separate = BIT(_mask),		\
+}
+
+#define SIRFSOC_ADC_TS_CHANNEL(_channel, _name)		\
+	SIRFSOC_ADC_CHANNEL(_channel, IIO_VOLTAGE,	\
+	_name, IIO_CHAN_INFO_RAW)
+
+#define SIRFSOC_ADC_AUX_CHANNEL(_channel, _name)	\
+	SIRFSOC_ADC_CHANNEL(_channel, IIO_VOLTAGE,	\
+	_name, IIO_CHAN_INFO_PROCESSED)
+
+static const struct iio_chan_spec prima2_adc_iio_channels[] = {
+	/* Channels to get the touch data */
+	SIRFSOC_ADC_TS_CHANNEL(0, "touch_coord"),
+	/* Channels to get the pin input */
+	SIRFSOC_ADC_AUX_CHANNEL(1, "auxiliary1"),
+	SIRFSOC_ADC_AUX_CHANNEL(2, "auxiliary2"),
+	SIRFSOC_ADC_AUX_CHANNEL(3, "auxiliary3"),
+	SIRFSOC_ADC_AUX_CHANNEL(4, "auxiliary4"),
+	SIRFSOC_ADC_AUX_CHANNEL(5, "auxiliary5"),
+	SIRFSOC_ADC_AUX_CHANNEL(6, "auxiliary6"),
+};
+
+static const u32 prima2_adc_channel_sel[] = {
+	0, SIRFSOC_ADC_AUX1_SEL, SIRFSOC_ADC_AUX2_SEL,
+	SIRFSOC_ADC_AUX3_SEL, SIRFSOC_ADC_AUX4_SEL,
+	SIRFSOC_ADC_AUX5_SEL, SIRFSOC_ADC_AUX6_SEL
+};
+
+static const struct iio_chan_spec atlas6_adc_iio_channels[] = {
+	/* Channels to get the touch data */
+	SIRFSOC_ADC_TS_CHANNEL(0, "touch_coord"),
+	SIRFSOC_ADC_TS_CHANNEL(1, "dual_touch_coord"),
+	/* Channels to get the pin input */
+	SIRFSOC_ADC_AUX_CHANNEL(2, "auxiliary1"),
+	/* Atlas6 has no auxiliary2 and auxiliary3 */
+	SIRFSOC_ADC_AUX_CHANNEL(3, "auxiliary4"),
+	SIRFSOC_ADC_AUX_CHANNEL(4, "auxiliary5"),
+	SIRFSOC_ADC_AUX_CHANNEL(5, "auxiliary6"),
+};
+
+static const u32 atlas6_adc_channel_sel[] = {
+	0, 0, SIRFSOC_ADC_AUX1_SEL, SIRFSOC_ADC_AUX4_SEL,
+	SIRFSOC_ADC_AUX5_SEL, SIRFSOC_ADC_AUX6_SEL
+};
+
+static const struct iio_info sirfsoc_adc_info = {
+	.read_raw = &sirfsoc_adc_read_raw,
+	.driver_module = THIS_MODULE,
+};
+
+static const struct sirfsoc_adc_chip_info sirfsoc_adc_chip_info_tbl[] = {
+	[PRIMA2] = {
+		.channels = prima2_adc_iio_channels,
+		.num_channels = ARRAY_SIZE(prima2_adc_iio_channels),
+		.iio_info = &sirfsoc_adc_info,
+		.calculate_volt = prima2_adc_calculate_volt,
+		.channel_sel = prima2_adc_channel_sel,
+	},
+	[ATLAS6] = {
+		.channels = atlas6_adc_iio_channels,
+		.num_channels = ARRAY_SIZE(atlas6_adc_iio_channels),
+		.iio_info = &sirfsoc_adc_info,
+		.calculate_volt = atlas6_adc_calculate_volt,
+		.channel_sel = atlas6_adc_channel_sel,
+	},
+};
+
+static const struct of_device_id sirfsoc_adc_of_match[] = {
+	{ .compatible = "sirf,prima2-adc",
+	  .data = &sirfsoc_adc_chip_info_tbl[PRIMA2] },
+	{ .compatible = "sirf,atlas6-adc",
+	  .data = &sirfsoc_adc_chip_info_tbl[ATLAS6] },
+	{}
+};
+MODULE_DEVICE_TABLE(of, sirfsoc_adc_of_match);
+
+static int sirfsoc_adc_probe(struct platform_device *pdev)
+{
+	struct resource	*mem_res;
+	struct sirfsoc_adc *adc;
+	struct iio_dev *indio_dev;
+	const struct of_device_id *match;
+	int irq;
+	int ret;
+
+	indio_dev = devm_iio_device_alloc(&pdev->dev,
+			sizeof(struct sirfsoc_adc));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	adc = iio_priv(indio_dev);
+
+	/* ADC specific data */
+	match = of_match_device(
+		of_match_ptr(sirfsoc_adc_of_match), &pdev->dev);
+	adc->chip_info = match->data;
+
+	indio_dev->info = adc->chip_info->iio_info;
+	indio_dev->channels = adc->chip_info->channels;
+	indio_dev->num_channels = adc->chip_info->num_channels;
+	indio_dev->name = "sirfsoc adc";
+	indio_dev->dev.parent = &pdev->dev;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	platform_set_drvdata(pdev, indio_dev);
+
+	adc->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(adc->clk)) {
+		dev_err(&pdev->dev, "Get adc clk failed\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+	clk_prepare_enable(adc->clk);
+
+	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem_res) {
+		dev_err(&pdev->dev, "Unable to get io resource\n");
+		ret = -ENODEV;
+		goto err;
+	}
+
+	adc->base = devm_request_and_ioremap(&pdev->dev, mem_res);
+	if (!adc->base) {
+		dev_err(&pdev->dev, "IO remap failed!\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	init_completion(&adc->done);
+	mutex_init(&adc->adc_lock);
+
+	sirfsoc_rtc_iobrg_writel(sirfsoc_rtc_iobrg_readl(SIRFSOC_PWRC_BASE +
+		SIRFSOC_PWRC_TRIGGER_EN) | BIT(SIRFSOC_PWR_WAKEEN_TS_SHIFT),
+		SIRFSOC_PWRC_BASE + SIRFSOC_PWRC_TRIGGER_EN);
+
+	ret = device_reset(&pdev->dev);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to reset\n");
+		goto err;
+	}
+
+	writel(SIRFSOC_ADC_PRP_MODE3 | SIRFSOC_ADC_RTOUCH(1) |
+		SIRFSOC_ADC_DEL_PRE(2) | SIRFSOC_ADC_DEL_DIS(5),
+		adc->base + SIRFSOC_ADC_CONTROL2);
+
+	/* Clear interrupts and enable PEN INTR */
+	writel(readl(adc->base + SIRFSOC_ADC_INTR) | SIRFSOC_ADC_PEN_INTR |
+		SIRFSOC_ADC_DATA_INTR | SIRFSOC_ADC_PEN_INTR_EN |
+		SIRFSOC_ADC_DATA_INTR_EN,  adc->base + SIRFSOC_ADC_INTR);
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "Failed to get IRQ!\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	ret = devm_request_irq(&pdev->dev, irq, sirfsoc_adc_data_irq,
+		0, DRIVER_NAME, indio_dev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Failed to register irq handler\n");
+		ret = -ENODEV;
+		goto err;
+	}
+
+	ret = of_platform_populate(pdev->dev.of_node, sirfsoc_adc_of_match,
+		NULL, &pdev->dev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Failed to add child nodes\n");
+		goto err;
+	}
+
+	ret = iio_device_register(indio_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to register adc iio dev\n");
+		goto err;
+	}
+
+	return 0;
+
+err:
+	clk_disable_unprepare(adc->clk);
+
+	return ret;
+}
+
+static int sirfsoc_adc_remove(struct platform_device *pdev)
+{
+	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+	struct sirfsoc_adc *adc = iio_priv(indio_dev);
+
+	iio_device_unregister(indio_dev);
+	clk_disable_unprepare(adc->clk);
+
+	return 0;
+}
+
+static struct platform_driver sirfsoc_adc_driver = {
+	.driver = {
+		.name	= DRIVER_NAME,
+		.of_match_table = sirfsoc_adc_of_match,
+		.pm	= &sirfsoc_adc_pm_ops,
+	},
+	.probe		= sirfsoc_adc_probe,
+	.remove		= sirfsoc_adc_remove,
+};
+
+module_platform_driver(sirfsoc_adc_driver);
+
+MODULE_AUTHOR("Guoying Zhang <Guoying.Zhang@csr.com>");
+MODULE_DESCRIPTION("SiRF SoC On-chip ADC driver");
+MODULE_LICENSE("GPL v2");
-- 
1.9.1



Member of the CSR plc group of companies. CSR plc registered in England and Wales, registered number 4187346, registered office Churchill House, Cambridge Business Park, Cowley Road, Cambridge, CB4 0WZ, United Kingdom
More information can be found at www.csr.com. Keep up to date with CSR on our technical blog, www.csr.com/blog, CSR people blog, www.csr.com/people, YouTube, www.youtube.com/user/CSRplc, Facebook, www.facebook.com/pages/CSR/191038434253534, or follow us on Twitter at www.twitter.com/CSR_plc.
New for 2014, you can now access the wide range of products powered by aptX at www.aptx.com.

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v2] iio: adc: add CSR SiRFSoC internal ADC driver
  2014-07-17  9:22 [PATCH v2] iio: adc: add CSR SiRFSoC internal ADC driver Guoying Zhang
@ 2014-07-20 14:33 ` Jonathan Cameron
  2014-07-21  6:21   ` Barry Song
  2014-07-27 12:04 ` Hartmut Knaack
  1 sibling, 1 reply; 5+ messages in thread
From: Jonathan Cameron @ 2014-07-20 14:33 UTC (permalink / raw)
  To: Guoying Zhang; +Cc: linux-iio, workgroup.linux, Peter Meerwald, Barry Song

On 17/07/14 10:22, Guoying Zhang wrote:
> SiRFSoC internal ADC provides touchscreen single or dual touch
> channels, and provides several auxiliary channels to measure
> temperature, battery and so on.
>
> Cc: Peter Meerwald <pmeerw@pmeerw.net>
> Signed-off-by: Guoying Zhang <Guoying.Zhang@csr.com>
> Signed-off-by: Barry Song <Baohua.Song@csr.com>

Hi,

The way the touchscreen side is pushed into here causes a number of issues.
You try to push multiple coordinates out through a poll interface that only
allows one.

I would suggest you effectively rip the touchscreen channels out of the IIO
elements of the driver and support them via the input subsystem (within this
single driver is fine).

I'm currious to note that there was a sirfsoc_rs touchscreen driver posted
a while back.  Why was that not pursued futher?

I'm reasonably happy with the aux channels side of things.  It's just the
touchscreen being blugeoned into an incorrect interface that is causing
trouble here.

Various other bits inline.

Jonathan
> ---
>   -v2: fix many issues from Peter and Jonathan's feedbacks
>
>   .../devicetree/bindings/iio/adc/sirfsoc_adc.txt    |  33 +
>   drivers/iio/adc/Kconfig                            |  10 +
>   drivers/iio/adc/Makefile                           |   1 +
>   drivers/iio/adc/sirfsoc_adc.c                      | 755 +++++++++++++++++++++
>   4 files changed, 799 insertions(+)
>   create mode 100644 Documentation/devicetree/bindings/iio/adc/sirfsoc_adc.txt
>   create mode 100644 drivers/iio/adc/sirfsoc_adc.c
>
> diff --git a/Documentation/devicetree/bindings/iio/adc/sirfsoc_adc.txt b/Documentation/devicetree/bindings/iio/adc/sirfsoc_adc.txt
> new file mode 100644
> index 0000000..70eaf40
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/iio/adc/sirfsoc_adc.txt
> @@ -0,0 +1,33 @@
> +Sirfsoc inner Analog to Digital Converter bindings
> +
> +The devicetree bindings are for the new ADC driver written for
> +Prima2/Atlas6 CSR.
> +
> +Required properties:
> +- compatible: Should be one of
> +	* "sirf,prima2-adc": When use Prima2 SOC
> +	* "sirf,atlas6-adc": When use Atlas6 SOC
> +- reg: Offset and length of the register set for the device
> +- interrupts: Should contain the interrupt for the device
> +- clocks: The clock is needed by the ADC controller
> +- resets: The reset for the device
> +- #io-channel-cells: Should be set to <1>
> +
> +Example:
> +	adc: adc@b0110000 {
> +		compatible = "sirf,prima2-adc";
> +		reg = <0xb0110000 0x10000>;
> +		interrupts = <34>;
> +		clocks = <&clks 16>;
> +		resets = <&rstc 32>;
> +		#io-channel-cells = <1>;
> +	};
> +
> +	adc: adc@b0110000 {
> +		compatible = "sirf,atlas6-adc";
> +		reg = <0xb0110000 0x10000>;
> +		interrupts = <34>;
> +		clocks = <&clks 16>;
> +		resets = <&rstc 32>;
> +		#io-channel-cells = <1>;
> +	};
> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> index a80d236..6b803d5 100644
> --- a/drivers/iio/adc/Kconfig
> +++ b/drivers/iio/adc/Kconfig
> @@ -187,6 +187,16 @@ config NAU7802
>   	  To compile this driver as a module, choose M here: the
>   	  module will be called nau7802.
>
> +config SIRFSOC_ADC
> +	tristate "SiRFSoC ADC"
> +	depends on ARCH_SIRF
> +	help
> +	  If you say yes here you get support for CSR SiRFSoC internal
> +	  ADC.
> +
> +	  This driver can also be built as a module. If so, the module will be
> +	  called sirfsoc_adc.
> +
>   config TI_ADC081C
>   	tristate "Texas Instruments ADC081C021/027"
>   	depends on I2C
> diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
> index 9d60f2d..2912e58 100644
> --- a/drivers/iio/adc/Makefile
> +++ b/drivers/iio/adc/Makefile
> @@ -20,6 +20,7 @@ obj-$(CONFIG_MCP320X) += mcp320x.o
>   obj-$(CONFIG_MCP3422) += mcp3422.o
>   obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o
>   obj-$(CONFIG_NAU7802) += nau7802.o
> +obj-$(CONFIG_SIRFSOC_ADC) += sirfsoc_adc.o
>   obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o
>   obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o
>   obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o
> diff --git a/drivers/iio/adc/sirfsoc_adc.c b/drivers/iio/adc/sirfsoc_adc.c
> new file mode 100644
> index 0000000..ae11a36
> --- /dev/null
> +++ b/drivers/iio/adc/sirfsoc_adc.c
> @@ -0,0 +1,755 @@
> +/*
> +* ADC Driver for CSR SiRFSoC
> +*
> +* Copyright (c) 2014 Cambridge Silicon Radio Limited, a CSR plc group company.
> +*
> +* Licensed under GPLv2.
> +*/
> +
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/init.h>
> +#include <linux/clk.h>
> +#include <linux/io.h>
> +#include <linux/interrupt.h>
> +#include <linux/of.h>
> +#include <linux/pm.h>
> +#include <linux/platform_device.h>
> +#include <linux/of_platform.h>
> +#include <linux/reset.h>
> +#include <linux/rtc/sirfsoc_rtciobrg.h>
> +
> +#include <linux/iio/iio.h>
> +#include <linux/iio/machine.h>
> +#include <linux/iio/driver.h>
> +
> +#define DRIVER_NAME "sirfsoc_adc"
> +
> +#define SIRFSOC_PWR_WAKEEN_TSC_SHIFT	23
> +#define SIRFSOC_PWR_WAKEEN_TS_SHIFT	5
> +#define SIRFSOC_PWRC_TRIGGER_EN		0x8
> +#define SIRFSOC_PWRC_BASE		0x3000
> +
> +/* Registers offset */
> +#define SIRFSOC_ADC_CONTROL1		0x00
> +#define SIRFSOC_ADC_CONTROL2		0x04
> +#define SIRFSOC_ADC_INTR		0x08
> +#define SIRFSOC_ADC_COORD		0x0C
> +#define SIRFSOC_ADC_PRESSURE		0x10
> +#define SIRFSOC_ADC_AUX1		0x14
> +/* Atlas6 AUX2 and AUX4 reserved*/
> +#define SIRFSOC_ADC_AUX2		0x18
> +#define SIRFSOC_ADC_AUX3		0x1C
> +#define SIRFSOC_ADC_AUX4		0x20
> +#define SIRFSOC_ADC_AUX5		0x24
> +#define SIRFSOC_ADC_AUX6		0x28
> +/* Read Back calibration register */
> +#define SIRFSOC_ADC_CB			0x2C
> +#define SIRFSOC_ADC_COORD2		0x30
> +#define SIRFSOC_ADC_COORD3		0x34
> +#define SIRFSOC_ADC_COORD4		0x38
> +
> +/* CTRL1 defines */
> +#define SIRFSOC_ADC_RESET_QUANT_EN	BIT(24)
> +#define SIRFSOC_ADC_RST_B		BIT(23)
> +#define SIRFSOC_ADC_RESOLUTION_12	BIT(22)
> +#define SIRFSOC_ADC_RBAT_DISABLE	(0x0 << 21)
> +#define SIRFSOC_ADC_RBAT_ENABLE		(0x1 << 21)
> +#define SIRFSOC_ADC_EXTCM(x)		(((x) & 0x3) << 19)
> +#define SIRFSOC_ADC_SGAIN(x)		(((x) & 0x7) << 16)
> +#define SIRFSOC_ADC_POLL		BIT(15)
> +#define SIRFSOC_ADC_SEL(x)		(((x) & 0xF) << 11)
> +#define SIRFSOC_ADC_FREQ_6K		(0x0 << 8)
> +#define SIRFSOC_ADC_FREQ_13K		BIT(8)
> +#define SIRFSOC_ADC_DEL_SET(x)		(((x) & 0xF) << 4)
> +#define SIRFSOC_ADC_TP_TIME(x)		(((x) & 0x7) << 0)
> +
> +/* CTRL2 defines */
> +/* Pen detector off, digitizer off */
> +#define SIRFSOC_ADC_PRP_MODE0		(0 << 14)
> +/* Pen detector on, digitizer off, digitizer wakes up on pen detect */
> +#define SIRFSOC_ADC_PRP_MODE1		BIT(14)
> +/* Pen detector on, digitizer off, no wake up on pen detect */
> +#define SIRFSOC_ADC_PRP_MODE2		(2 << 14)
> +/* Pen detector on, digitizer on */
> +#define SIRFSOC_ADC_PRP_MODE3		(3 << 14)
> +#define SIRFSOC_ADC_RTOUCH(x)		(((x) & 0x3) << 12)
> +#define SIRFSOC_ADC_DEL_PRE(x)		(((x) & 0xF) << 4)
> +#define SIRFSOC_ADC_DEL_DIS(x)		(((x) & 0xF) << 0)
> +
> +/* INTR register defines */
> +#define SIRFSOC_ADC_PEN_INTR_EN		BIT(5)
> +#define SIRFSOC_ADC_DATA_INTR_EN	BIT(4)
> +#define SIRFSOC_ADC_PEN_INTR		BIT(1)
> +#define SIRFSOC_ADC_DATA_INTR		BIT(0)
> +
> +/* DATA register defines */
> +#define SIRFSOC_ADC_PEN_DOWN		BIT(31)
> +#define SIRFSOC_ADC_DATA_AUXVALID	BIT(30)
> +#define SIRFSOC_ADC_DATA_CB_VALID	BIT(30)
> +#define SIRFSOC_ADC_ADC_DATA_MASK(x)	(0x3FFF << (x))
> +#define SIRFSOC_ADC_DATA_AUXMASK	SIRFSOC_ADC_ADC_DATA_MASK(0)
> +#define SIRFSOC_ADC_DATA_CBMASK		SIRFSOC_ADC_ADC_DATA_MASK(0)
> +
> +#define SIRFSOC_ADC_MORE_CTL1	(of_machine_is_compatible("sirf,atlas6") ?\
> +				(SIRFSOC_ADC_RESET_QUANT_EN |\
> +				SIRFSOC_ADC_RST_B) : (0))
> +
> +/* Select AD samples to read (SEL bits in ADC_CONTROL1 register) */
> +#define SIRFSOC_ADC_AUX1_SEL	0x04
> +#define SIRFSOC_ADC_AUX2_SEL	0x05
> +#define SIRFSOC_ADC_AUX3_SEL	0x06
> +#define SIRFSOC_ADC_AUX4_SEL	0x07
> +#define SIRFSOC_ADC_AUX5_SEL	0x08
> +#define SIRFSOC_ADC_AUX6_SEL	0x09
> +#define SIRFSOC_ADC_TS_SEL	0x0A    /* Sample for single touch*/
> +#define SIRFSOC_ADC_GROUND_SEL	0x0B    /* Gound for offset calibration */
> +#define SIRFSOC_ADC_BANDGAP_SEL	0x0C    /* Bandgap for gain calibration */
> +#define SIRFSOC_ADC_TS_SEL_DUAL	0x0F    /* Samples for dual touch */
> +
> +#define SIRFSOC_ADC_TS_SAMPLE_SIZE	4
> +#define SIRFSOC_ADC_CTL1(sel)    (SIRFSOC_ADC_POLL | SIRFSOC_ADC_SEL(sel) |\
> +		SIRFSOC_ADC_DEL_SET(6) | SIRFSOC_ADC_FREQ_6K |\
> +		SIRFSOC_ADC_TP_TIME(0) | SIRFSOC_ADC_SGAIN(0) |\
> +		SIRFSOC_ADC_EXTCM(0) | SIRFSOC_ADC_RBAT_DISABLE |\
> +		SIRFSOC_ADC_MORE_CTL1)
> +
> +enum sirfsoc_adc_chips {
> +	PRIMA2,
> +	ATLAS6,
> +};
> +
> +struct sirfsoc_adc_chip_info {
> +	const struct iio_chan_spec *channels;
> +	unsigned int num_channels;
> +	unsigned int flags;
> +	const struct iio_info *iio_info;
> +
> +	u32 (*calculate_volt)(u32, u32, u32);
I'd definitely put parameter names in here to act as some
form of minimal documentation of what is needed.
> +	const u32 *channel_sel;
> +};
> +
> +struct sirfsoc_adc_request {
> +	u16 mode;
> +	u16 extcm;
> +	u16 reference;
> +	u8 delay_bits;
> +	u32 s_gain_bits;
> +	u16 read_back_data;
> +};
> +
> +struct sirfsoc_adc {
> +	const struct sirfsoc_adc_chip_info	*chip_info;
> +	struct clk	*clk;
> +	void __iomem	*base;
> +	struct sirfsoc_adc_request req;
> +	struct completion	done;
> +	struct mutex	adc_lock;
> +};
> +
> +static const u32 sirfsoc_adc_ts_reg[SIRFSOC_ADC_TS_SAMPLE_SIZE] = {
> +	/* Dual touch samples read registers*/
> +	SIRFSOC_ADC_COORD, SIRFSOC_ADC_COORD2,
> +	SIRFSOC_ADC_COORD3, SIRFSOC_ADC_COORD4
> +};
> +
> +enum sirfsoc_adc_ts_type {
> +	SINGLE_TOUCH,
> +	DUAL_TOUCH,
> +};
> +
> +static int sirfsoc_adc_get_ts_sample(
> +	struct sirfsoc_adc *adc, int *sample, int touch_type)
> +{
> +	int adc_intr;
> +	int ret = 0;
> +	int i;
> +
> +	mutex_lock(&adc->adc_lock);
> +	adc_intr = readl(adc->base + SIRFSOC_ADC_INTR);
> +	if (adc_intr & SIRFSOC_ADC_PEN_INTR)
> +		writel(SIRFSOC_ADC_PEN_INTR | SIRFSOC_ADC_PEN_INTR_EN |
> +			SIRFSOC_ADC_DATA_INTR_EN,
> +			adc->base + SIRFSOC_ADC_INTR);
> +
> +	/* check pen status */
> +	if (!(readl(adc->base + SIRFSOC_ADC_COORD) & SIRFSOC_ADC_PEN_DOWN)) {
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	if (SINGLE_TOUCH == touch_type)
> +		writel(SIRFSOC_ADC_CTL1(SIRFSOC_ADC_TS_SEL),
> +			adc->base + SIRFSOC_ADC_CONTROL1);
> +	else
> +		writel(SIRFSOC_ADC_CTL1(SIRFSOC_ADC_TS_SEL_DUAL),
> +			adc->base + SIRFSOC_ADC_CONTROL1);
> +
> +	if (!wait_for_completion_timeout(&adc->done,
> +		msecs_to_jiffies(50))) {
> +		ret = -EIO;
> +		goto out;
> +	}
> +
> +	if (SINGLE_TOUCH == touch_type)
> +		*sample = readl(adc->base + SIRFSOC_ADC_COORD);
Err, silly question but what the heck is the format of this?  Please don't
send multiple channels of real data through as 'RAW'.  If you do they'll
never work with anything other than carefully contrived non standard userspace.
> +	else
> +		for (i = 0; i < SIRFSOC_ADC_TS_SAMPLE_SIZE; i++)
> +			sample[i] = readl(adc->base + sirfsoc_adc_ts_reg[i]);
Sample is a pointer to a single element so you can't do this.
> +
> +out:
> +	mutex_unlock(&adc->adc_lock);
> +	return ret;
> +}
> +
> +/* get touchscreen coordinates for single touch */
> +static int sirfsoc_adc_single_ts_sample(struct sirfsoc_adc *adc, int *sample)
> +{
sample is pointing to a single integer...
> +	return sirfsoc_adc_get_ts_sample(adc, sample, SINGLE_TOUCH);
> +}
> +
> +/* get touchscreen coordinates for dual touch */
> +static int sirfsoc_adc_dual_ts_sample(struct sirfsoc_adc *adc, int *samples)
> +{
> +	return sirfsoc_adc_get_ts_sample(adc, samples, DUAL_TOUCH);
> +}
> +
> +static int sirfsoc_adc_send_request(struct sirfsoc_adc_request *req)
> +{
> +	struct sirfsoc_adc *adc = container_of(req, struct sirfsoc_adc, req);
> +	int control1, control2, intr;
> +	int data, reg_offset;
> +	int ret = 0;
> +
> +	mutex_lock(&adc->adc_lock);
> +
> +	/* Store registers for recover */
> +	intr = readl(adc->base + SIRFSOC_ADC_INTR);
> +	control1 = readl(adc->base + SIRFSOC_ADC_CONTROL1);
> +	control2 = readl(adc->base + SIRFSOC_ADC_CONTROL2);
> +
> +	writel(intr | SIRFSOC_ADC_DATA_INTR_EN | SIRFSOC_ADC_DATA_INTR,
> +		adc->base + SIRFSOC_ADC_INTR);
> +	writel(SIRFSOC_ADC_PRP_MODE3 | req->reference,
> +		adc->base + SIRFSOC_ADC_CONTROL2);
> +	writel(SIRFSOC_ADC_POLL | SIRFSOC_ADC_MORE_CTL1 | req->mode |
> +		req->extcm | req->delay_bits | SIRFSOC_ADC_RESOLUTION_12,
> +		adc->base + SIRFSOC_ADC_CONTROL1);
> +
> +	if (!wait_for_completion_timeout(&adc->done,
> +		msecs_to_jiffies(50))) {
> +		ret = -EIO;
> +		goto out;
> +	}
> +
> +	switch (req->mode) {
> +	case SIRFSOC_ADC_SEL(SIRFSOC_ADC_AUX1_SEL):
> +	case SIRFSOC_ADC_SEL(SIRFSOC_ADC_AUX2_SEL):
> +	case SIRFSOC_ADC_SEL(SIRFSOC_ADC_AUX3_SEL):
> +	case SIRFSOC_ADC_SEL(SIRFSOC_ADC_AUX4_SEL):
> +	case SIRFSOC_ADC_SEL(SIRFSOC_ADC_AUX5_SEL):
> +	case SIRFSOC_ADC_SEL(SIRFSOC_ADC_AUX6_SEL):
> +		/* Calculate aux offset from mode */
> +		reg_offset = 0x14 + ((req->mode >> 11) - 0x04) * 4;
> +		data = readl(adc->base + reg_offset);
> +		if (data & SIRFSOC_ADC_DATA_AUXVALID)
> +			req->read_back_data = data & SIRFSOC_ADC_DATA_AUXMASK;
> +		break;
> +	case SIRFSOC_ADC_SEL(SIRFSOC_ADC_GROUND_SEL):
> +	case SIRFSOC_ADC_SEL(SIRFSOC_ADC_BANDGAP_SEL):
> +		reg_offset = SIRFSOC_ADC_CB;
> +		data = readl(adc->base + reg_offset);
> +		if (data & SIRFSOC_ADC_DATA_CB_VALID)
> +			req->read_back_data = data & SIRFSOC_ADC_DATA_CBMASK;
> +		break;
> +	default:
> +		break;
> +	}
> +
> +out:
> +	writel(intr, adc->base + SIRFSOC_ADC_INTR);
> +	writel(control1, adc->base + SIRFSOC_ADC_CONTROL1);
> +	writel(control2, adc->base + SIRFSOC_ADC_CONTROL2);
> +	mutex_unlock(&adc->adc_lock);
> +	return ret;
> +}
> +
> +/* Store params to calibrate */
> +struct sirfsoc_adc_cali_data {
> +	u32 digital_offset;
> +	u32 digital_again;
> +	bool is_calibration;
> +};
> +
> +/* Offset Calibration calibrates the ADC offset error */
> +static u32 sirfsoc_adc_offset_cali(struct sirfsoc_adc_request *req)
> +{
> +	u32 i, digital_offset = 0, count = 0, sum = 0;
> +	/* To set the registers in order to get the ADC offset */
> +	req->mode = SIRFSOC_ADC_SEL(SIRFSOC_ADC_GROUND_SEL);
> +	req->extcm = SIRFSOC_ADC_EXTCM(0);
> +	req->s_gain_bits = SIRFSOC_ADC_SGAIN(7);
> +	req->delay_bits = SIRFSOC_ADC_DEL_SET(4);
> +
> +	for (i = 0; i < 10; i++) {
> +		if (sirfsoc_adc_send_request(req))
> +			break;
> +		digital_offset = req->read_back_data;
> +		sum += digital_offset;
> +		count++;
> +	}
> +	if (!count)
> +		digital_offset = 0;
> +	else
> +		digital_offset = sum / count;
> +
> +	return digital_offset;
> +}
> +
> +
> +/* Gain Calibration calibrates the ADC gain error */
> +static u32 sirfsoc_adc_gain_cali(struct sirfsoc_adc_request *req)
> +{
> +	u32 i, digital_gain = 0, count = 0, sum = 0;
> +	/* To set the registers in order to get the ADC gain */
> +	req->mode = SIRFSOC_ADC_SEL(SIRFSOC_ADC_BANDGAP_SEL);
> +	req->extcm = SIRFSOC_ADC_EXTCM(0);
> +	req->s_gain_bits = SIRFSOC_ADC_SGAIN(1);
> +	req->delay_bits = SIRFSOC_ADC_DEL_SET(4);
> +
> +	for (i = 0; i < 10; i++) {
> +		if (sirfsoc_adc_send_request(req))
> +			break;
> +		digital_gain = req->read_back_data;
> +		sum += digital_gain;
> +		count++;
> +	}
> +	if (!count)
> +		digital_gain = 0;
> +	else
> +		digital_gain = sum / count;
> +
> +	return digital_gain;
> +}
> +
> +/* Absolute gain calibration */
> +static int sirfsoc_adc_adc_cali(struct sirfsoc_adc_request *req,
> +				struct sirfsoc_adc_cali_data *cali_data)
> +{
> +	cali_data->digital_offset = sirfsoc_adc_offset_cali(req);
> +	if (!cali_data->digital_offset)
> +		return -EINVAL;
> +	cali_data->digital_again = sirfsoc_adc_gain_cali(req);
> +	if (!cali_data->digital_again)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +/* Get voltage after ADC conversion */
> +static u32 sirfsoc_adc_get_adc_volt(struct sirfsoc_adc *adc,
> +				struct sirfsoc_adc_cali_data *cali_data)
> +{
> +	u32 digital_out, volt;
> +	struct sirfsoc_adc_request *req = &adc->req;
> +
> +	req->s_gain_bits = SIRFSOC_ADC_SGAIN(0);
> +	req->delay_bits = SIRFSOC_ADC_DEL_SET(4);
> +
> +	/*
> +	 * First read original data
> +	 * then read calibrate errors
> +	 */
> +	sirfsoc_adc_send_request(req);
> +	if (req->read_back_data) {
> +		digital_out = req->read_back_data;
> +		/* Get errors for each sample */
> +		if (!cali_data->is_calibration) {
> +			if (sirfsoc_adc_adc_cali(req, cali_data))
> +				return 0;
> +			cali_data->is_calibration = true;
> +		}
> +
> +		volt = adc->chip_info->calculate_volt(digital_out,
> +			cali_data->digital_offset,
> +			cali_data->digital_again);
> +	} else {
> +		return 0;
> +	}
> +
> +	return volt;
> +}
> +
> +static u32 prima2_adc_calculate_volt(u32 digital_out,
> +				u32 digital_offset, u32 digital_again)
> +{
> +	u32 volt, digital_ideal, digital_convert;
> +
> +	/*
> +	 * see Equation 3.2 of SiRFPrimaII™ Internal ADC and Touch
> +	 * User Guide
> +	 */
> +	digital_ideal = (5522 * 1200) / (7 * 333);
> +	/*
> +	 * see Equation 3.3 of SiRFatlasVI™ Internal ADC and Touch
> +	 */
> +	digital_convert = (digital_out - 11645 * digital_offset /
> +		140000) * digital_ideal / (digital_again
> +		- digital_offset * 11645 / 70000);
> +	volt = 14 * 333 * digital_convert / 5522;
> +
> +	return volt;
> +}
> +
> +static u32 atlas6_adc_calculate_volt(u32 digital_out,
> +				u32 digital_offset, u32 digital_again)
> +{
> +	u32 volt, digital_ideal, digital_convert;
> +
> +	/*
> +	 * see Equation 3.2 of SiRFatlasVI™ Internal ADC and Touch
> +	 * User Guide
> +	 */
> +	digital_ideal = (3986 * 12100) / (7 * 3333);
> +	/*
> +	 * see Equation 3.3 of SiRFatlasVI™ Internal ADC and Touch
> +	 */
> +	digital_offset &= 0xfff;
> +	digital_convert = abs(digital_out - 2 * digital_offset)
> +		* digital_ideal / (digital_again
> +		- digital_offset * 2);
> +	volt = 14 * 333 * digital_convert / 3986;
> +	volt = volt / 2;
> +	if (volt > 1500)
> +		volt = volt - (volt - 1500) / 15;
> +	else
> +		volt = volt + (1500 - volt) / 28;
> +
> +	return volt;
> +}
> +
> +static irqreturn_t sirfsoc_adc_data_irq(int irq, void *handle)
> +{
> +	struct iio_dev *indio_dev = handle;
> +	struct sirfsoc_adc *adc = iio_priv(indio_dev);
> +	int val;
> +
> +	val = readl(adc->base + SIRFSOC_ADC_INTR);
> +
> +	writel(SIRFSOC_ADC_PEN_INTR | SIRFSOC_ADC_PEN_INTR_EN |
> +		SIRFSOC_ADC_DATA_INTR | SIRFSOC_ADC_DATA_INTR_EN,
> +		adc->base + SIRFSOC_ADC_INTR);
> +
> +	if (val & SIRFSOC_ADC_DATA_INTR)
> +		complete(&adc->done);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int sirfsoc_adc_read_raw(struct iio_dev *indio_dev,
> +				struct iio_chan_spec const *chan,
> +				int *val,
> +				int *val2,
> +				long mask)
> +{
> +	struct sirfsoc_adc *adc = iio_priv(indio_dev);
> +	struct sirfsoc_adc_cali_data cali_data;
> +	int ret;
> +
> +	cali_data.is_calibration = false;
> +	switch (mask) {
> +	case IIO_CHAN_INFO_RAW:
> +		if (0 == chan->channel)
> +			ret = sirfsoc_adc_single_ts_sample(adc, val);
> +		else
> +			ret = sirfsoc_adc_dual_ts_sample(adc, val);
> +
> +		if (ret)
> +			return ret;
> +		return IIO_VAL_INT;
This will result in the first value only being output.  More to the
point *val only points to a single integer so chances are you'll crash
the kernel. I don't think it would be appropriate to use our more recent
support for multiple element outputs.  The two axes are independent after
all.  I'd really be happier seeing this done via the input subsystem.
(note that would require these channels not to be polled as done here, but
driven by interrupt or perhaps timer).

> +	case IIO_CHAN_INFO_PROCESSED:
> +		adc->req.mode = SIRFSOC_ADC_SEL(
> +			adc->chip_info->channel_sel[chan->channel]);
> +		adc->req.extcm = SIRFSOC_ADC_EXTCM(0);
> +		*val = sirfsoc_adc_get_adc_volt(adc, &cali_data);
> +		return IIO_VAL_INT;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +#ifdef CONFIG_PM_SLEEP
> +static int sirfsoc_adc_suspend(struct device *dev)
> +{
> +	struct iio_dev *indio_dev = dev_get_drvdata(dev);
> +	struct sirfsoc_adc *adc = iio_priv(indio_dev);
> +
> +	sirfsoc_rtc_iobrg_writel(sirfsoc_rtc_iobrg_readl(
> +		SIRFSOC_PWRC_BASE + SIRFSOC_PWRC_TRIGGER_EN)
> +		& ~BIT(SIRFSOC_PWR_WAKEEN_TSC_SHIFT),
> +		SIRFSOC_PWRC_BASE + SIRFSOC_PWRC_TRIGGER_EN);
> +
> +	clk_disable_unprepare(adc->clk);
> +
> +	return 0;
> +}
> +
> +static int sirfsoc_adc_resume(struct device *dev)
> +{
> +	struct iio_dev *indio_dev = dev_get_drvdata(dev);
> +	struct sirfsoc_adc *adc = iio_priv(indio_dev);
> +	int ret;
> +	int val;
> +
> +	clk_prepare_enable(adc->clk);
> +
> +	sirfsoc_rtc_iobrg_writel(sirfsoc_rtc_iobrg_readl(
> +		SIRFSOC_PWRC_BASE + SIRFSOC_PWRC_TRIGGER_EN) |
> +		BIT(SIRFSOC_PWR_WAKEEN_TS_SHIFT),
> +		SIRFSOC_PWRC_BASE + SIRFSOC_PWRC_TRIGGER_EN);
> +
> +	ret = device_reset(dev);
> +	if (ret) {
> +		dev_err(dev, "Failed to reset\n");
> +		return ret;
> +	}
> +
> +	writel(SIRFSOC_ADC_PRP_MODE3 | SIRFSOC_ADC_RTOUCH(1) |
> +		SIRFSOC_ADC_DEL_PRE(2) | SIRFSOC_ADC_DEL_DIS(5),
> +		adc->base + SIRFSOC_ADC_CONTROL2);
> +
> +	val = readl(adc->base + SIRFSOC_ADC_INTR);
> +
> +	/* Clear interrupts and enable PEN interrupt */
> +	writel(val | SIRFSOC_ADC_PEN_INTR | SIRFSOC_ADC_DATA_INTR |
> +		SIRFSOC_ADC_PEN_INTR_EN | SIRFSOC_ADC_DATA_INTR_EN,
> +		adc->base + SIRFSOC_ADC_INTR);
> +
> +	return 0;
> +}
> +#endif
> +
> +static const struct dev_pm_ops sirfsoc_adc_pm_ops = {
> +	SET_SYSTEM_SLEEP_PM_OPS(sirfsoc_adc_suspend, sirfsoc_adc_resume)
> +};
> +
> +#define SIRFSOC_ADC_CHANNEL(_channel, _type, _name, _mask) {	\
> +	.type = _type,					\
> +	.indexed = 1,					\
> +	.channel = _channel,				\
> +	.datasheet_name = _name,			\
> +	.info_mask_separate = BIT(_mask),		\
> +}
> +
> +#define SIRFSOC_ADC_TS_CHANNEL(_channel, _name)		\
> +	SIRFSOC_ADC_CHANNEL(_channel, IIO_VOLTAGE,	\
> +	_name, IIO_CHAN_INFO_RAW)
> +
> +#define SIRFSOC_ADC_AUX_CHANNEL(_channel, _name)	\
> +	SIRFSOC_ADC_CHANNEL(_channel, IIO_VOLTAGE,	\
> +	_name, IIO_CHAN_INFO_PROCESSED)
> +
> +static const struct iio_chan_spec prima2_adc_iio_channels[] = {
> +	/* Channels to get the touch data */
> +	SIRFSOC_ADC_TS_CHANNEL(0, "touch_coord"),
Passing a pair of coordinates through a single channel doesn't
really make sense. I'd be inclined to say you want a basic
input driver in here as well to handle these channels appropriately.
See the at91_adc driver for example.

> +	/* Channels to get the pin input */
> +	SIRFSOC_ADC_AUX_CHANNEL(1, "auxiliary1"),
> +	SIRFSOC_ADC_AUX_CHANNEL(2, "auxiliary2"),
> +	SIRFSOC_ADC_AUX_CHANNEL(3, "auxiliary3"),
> +	SIRFSOC_ADC_AUX_CHANNEL(4, "auxiliary4"),
> +	SIRFSOC_ADC_AUX_CHANNEL(5, "auxiliary5"),
> +	SIRFSOC_ADC_AUX_CHANNEL(6, "auxiliary6"),
> +};
> +
> +static const u32 prima2_adc_channel_sel[] = {
> +	0, SIRFSOC_ADC_AUX1_SEL, SIRFSOC_ADC_AUX2_SEL,
> +	SIRFSOC_ADC_AUX3_SEL, SIRFSOC_ADC_AUX4_SEL,
> +	SIRFSOC_ADC_AUX5_SEL, SIRFSOC_ADC_AUX6_SEL
> +};
> +
> +static const struct iio_chan_spec atlas6_adc_iio_channels[] = {
> +	/* Channels to get the touch data */
> +	SIRFSOC_ADC_TS_CHANNEL(0, "touch_coord"),
> +	SIRFSOC_ADC_TS_CHANNEL(1, "dual_touch_coord"),
> +	/* Channels to get the pin input */
> +	SIRFSOC_ADC_AUX_CHANNEL(2, "auxiliary1"),
> +	/* Atlas6 has no auxiliary2 and auxiliary3 */
> +	SIRFSOC_ADC_AUX_CHANNEL(3, "auxiliary4"),
> +	SIRFSOC_ADC_AUX_CHANNEL(4, "auxiliary5"),
> +	SIRFSOC_ADC_AUX_CHANNEL(5, "auxiliary6"),
> +};
> +
> +static const u32 atlas6_adc_channel_sel[] = {
> +	0, 0, SIRFSOC_ADC_AUX1_SEL, SIRFSOC_ADC_AUX4_SEL,
> +	SIRFSOC_ADC_AUX5_SEL, SIRFSOC_ADC_AUX6_SEL
> +};
> +
> +static const struct iio_info sirfsoc_adc_info = {
> +	.read_raw = &sirfsoc_adc_read_raw,
> +	.driver_module = THIS_MODULE,
> +};
> +
> +static const struct sirfsoc_adc_chip_info sirfsoc_adc_chip_info_tbl[] = {
> +	[PRIMA2] = {
> +		.channels = prima2_adc_iio_channels,
> +		.num_channels = ARRAY_SIZE(prima2_adc_iio_channels),
> +		.iio_info = &sirfsoc_adc_info,
> +		.calculate_volt = prima2_adc_calculate_volt,
> +		.channel_sel = prima2_adc_channel_sel,
> +	},
> +	[ATLAS6] = {
> +		.channels = atlas6_adc_iio_channels,
> +		.num_channels = ARRAY_SIZE(atlas6_adc_iio_channels),
> +		.iio_info = &sirfsoc_adc_info,
> +		.calculate_volt = atlas6_adc_calculate_volt,
> +		.channel_sel = atlas6_adc_channel_sel,
> +	},
> +};
> +
> +static const struct of_device_id sirfsoc_adc_of_match[] = {
> +	{ .compatible = "sirf,prima2-adc",
> +	  .data = &sirfsoc_adc_chip_info_tbl[PRIMA2] },
> +	{ .compatible = "sirf,atlas6-adc",
> +	  .data = &sirfsoc_adc_chip_info_tbl[ATLAS6] },
> +	{}
> +};
> +MODULE_DEVICE_TABLE(of, sirfsoc_adc_of_match);
> +
> +static int sirfsoc_adc_probe(struct platform_device *pdev)
> +{
> +	struct resource	*mem_res;
> +	struct sirfsoc_adc *adc;
> +	struct iio_dev *indio_dev;
> +	const struct of_device_id *match;
> +	int irq;
> +	int ret;
> +
> +	indio_dev = devm_iio_device_alloc(&pdev->dev,
> +			sizeof(struct sirfsoc_adc));
sizeof(*adc)); Shorter and slightly more obviously correct given that's what
you sent to iio_priv(indio_dev);
> +	if (!indio_dev)
> +		return -ENOMEM;
> +
> +	adc = iio_priv(indio_dev);
> +
> +	/* ADC specific data */
> +	match = of_match_device(
> +		of_match_ptr(sirfsoc_adc_of_match), &pdev->dev);
> +	adc->chip_info = match->data;
> +
> +	indio_dev->info = adc->chip_info->iio_info;
> +	indio_dev->channels = adc->chip_info->channels;
> +	indio_dev->num_channels = adc->chip_info->num_channels;
> +	indio_dev->name = "sirfsoc adc";
> +	indio_dev->dev.parent = &pdev->dev;
> +	indio_dev->modes = INDIO_DIRECT_MODE;
> +
> +	platform_set_drvdata(pdev, indio_dev);
> +
> +	adc->clk = devm_clk_get(&pdev->dev, NULL);
> +	if (IS_ERR(adc->clk)) {
> +		dev_err(&pdev->dev, "Get adc clk failed\n");
> +		ret = -ENOMEM;
> +		goto err;
> +	}
> +	clk_prepare_enable(adc->clk);
Is it just me who feels that a devm_clk_prepare_enable would be nice, or
for really short code : devm_clk_get_prepare_enable :)
Also, clk_prepare_enable can return errors so should be checked.
> +
> +	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!mem_res) {
> +		dev_err(&pdev->dev, "Unable to get io resource\n");
> +		ret = -ENODEV;
> +		goto err;
> +	}
> +
> +	adc->base = devm_request_and_ioremap(&pdev->dev, mem_res);
Quoting from a review Lars did earlier today:

devm_request_and_ioremap() is deprecated an will be removed in the next
release[1]. Use devm_ioremap_resource(), note that devm_ioremap_resource()
returns a ERR_PTR instead of NULL on error.

[1] https://lkml.org/lkml/2014/6/11/26

> +	if (!adc->base) {
> +		dev_err(&pdev->dev, "IO remap failed!\n");
> +		ret = -ENOMEM;
> +		goto err;
> +	}
> +
> +	init_completion(&adc->done);
> +	mutex_init(&adc->adc_lock);
> +
> +	sirfsoc_rtc_iobrg_writel(sirfsoc_rtc_iobrg_readl(SIRFSOC_PWRC_BASE +
> +		SIRFSOC_PWRC_TRIGGER_EN) | BIT(SIRFSOC_PWR_WAKEEN_TS_SHIFT),
> +		SIRFSOC_PWRC_BASE + SIRFSOC_PWRC_TRIGGER_EN);
> +
> +	ret = device_reset(&pdev->dev);
> +	if (ret) {
> +		dev_err(&pdev->dev, "Failed to reset\n");
> +		goto err;
> +	}
> +
> +	writel(SIRFSOC_ADC_PRP_MODE3 | SIRFSOC_ADC_RTOUCH(1) |
> +		SIRFSOC_ADC_DEL_PRE(2) | SIRFSOC_ADC_DEL_DIS(5),
> +		adc->base + SIRFSOC_ADC_CONTROL2);
> +
> +	/* Clear interrupts and enable PEN INTR */
> +	writel(readl(adc->base + SIRFSOC_ADC_INTR) | SIRFSOC_ADC_PEN_INTR |
> +		SIRFSOC_ADC_DATA_INTR | SIRFSOC_ADC_PEN_INTR_EN |
> +		SIRFSOC_ADC_DATA_INTR_EN,  adc->base + SIRFSOC_ADC_INTR);
> +
double space above.

> +	irq = platform_get_irq(pdev, 0);
> +	if (irq < 0) {
> +		dev_err(&pdev->dev, "Failed to get IRQ!\n");
> +		ret = -ENOMEM;
> +		goto err;
> +	}
> +
> +	ret = devm_request_irq(&pdev->dev, irq, sirfsoc_adc_data_irq,
> +		0, DRIVER_NAME, indio_dev);
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "Failed to register irq handler\n");
> +		ret = -ENODEV;
> +		goto err;
> +	}
> +
> +	ret = of_platform_populate(pdev->dev.of_node, sirfsoc_adc_of_match,
> +		NULL, &pdev->dev);
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "Failed to add child nodes\n");
> +		goto err;
> +	}
> +
> +	ret = iio_device_register(indio_dev);
> +	if (ret) {
> +		dev_err(&pdev->dev, "Failed to register adc iio dev\n");
Nitpick: ADC IIO
> +		goto err;
> +	}
> +
> +	return 0;
> +
> +err:
> +	clk_disable_unprepare(adc->clk);
> +
> +	return ret;
> +}
> +
> +static int sirfsoc_adc_remove(struct platform_device *pdev)
> +{
> +	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
> +	struct sirfsoc_adc *adc = iio_priv(indio_dev);
> +
> +	iio_device_unregister(indio_dev);
> +	clk_disable_unprepare(adc->clk);
> +
> +	return 0;
> +}
> +
> +static struct platform_driver sirfsoc_adc_driver = {
> +	.driver = {
> +		.name	= DRIVER_NAME,
> +		.of_match_table = sirfsoc_adc_of_match,
> +		.pm	= &sirfsoc_adc_pm_ops,
> +	},
> +	.probe		= sirfsoc_adc_probe,
> +	.remove		= sirfsoc_adc_remove,
> +};
> +
> +module_platform_driver(sirfsoc_adc_driver);
> +
> +MODULE_AUTHOR("Guoying Zhang <Guoying.Zhang@csr.com>");
> +MODULE_DESCRIPTION("SiRF SoC On-chip ADC driver");
> +MODULE_LICENSE("GPL v2");
>


^ permalink raw reply	[flat|nested] 5+ messages in thread

* RE: [PATCH v2] iio: adc: add CSR SiRFSoC internal ADC driver
  2014-07-20 14:33 ` Jonathan Cameron
@ 2014-07-21  6:21   ` Barry Song
  0 siblings, 0 replies; 5+ messages in thread
From: Barry Song @ 2014-07-21  6:21 UTC (permalink / raw)
  To: Jonathan Cameron, Guoying Zhang
  Cc: linux-iio@vger.kernel.org, Peter Meerwald, DL-SHA-WorkGroupLinux

PiAtLS0tLU9yaWdpbmFsIE1lc3NhZ2UtLS0tLQ0KPiBGcm9tOiBKb25hdGhh
biBDYW1lcm9uIFttYWlsdG86amljMjNAa2VybmVsLm9yZ10NCj4gU2VudDog
U3VuZGF5LCBKdWx5IDIwLCAyMDE0IDEwOjM0IFBNDQo+IFRvOiBHdW95aW5n
IFpoYW5nDQo+IENjOiBsaW51eC1paW9Admdlci5rZXJuZWwub3JnOyBETC1T
SEEtV29ya0dyb3VwTGludXg7IFBldGVyIE1lZXJ3YWxkOw0KPiBCYXJyeSBT
b25nDQo+IFN1YmplY3Q6IFJlOiBbUEFUQ0ggdjJdIGlpbzogYWRjOiBhZGQg
Q1NSIFNpUkZTb0MgaW50ZXJuYWwgQURDIGRyaXZlcg0KPiANCj4gT24gMTcv
MDcvMTQgMTA6MjIsIEd1b3lpbmcgWmhhbmcgd3JvdGU6DQo+ID4gU2lSRlNv
QyBpbnRlcm5hbCBBREMgcHJvdmlkZXMgdG91Y2hzY3JlZW4gc2luZ2xlIG9y
IGR1YWwgdG91Y2gNCj4gPiBjaGFubmVscywgYW5kIHByb3ZpZGVzIHNldmVy
YWwgYXV4aWxpYXJ5IGNoYW5uZWxzIHRvIG1lYXN1cmUNCj4gPiB0ZW1wZXJh
dHVyZSwgYmF0dGVyeSBhbmQgc28gb24uDQo+ID4NCj4gPiBDYzogUGV0ZXIg
TWVlcndhbGQgPHBtZWVyd0BwbWVlcncubmV0Pg0KPiA+IFNpZ25lZC1vZmYt
Ynk6IEd1b3lpbmcgWmhhbmcgPEd1b3lpbmcuWmhhbmdAY3NyLmNvbT4NCj4g
PiBTaWduZWQtb2ZmLWJ5OiBCYXJyeSBTb25nIDxCYW9odWEuU29uZ0Bjc3Iu
Y29tPg0KPiANCj4gSGksDQo+IA0KPiBUaGUgd2F5IHRoZSB0b3VjaHNjcmVl
biBzaWRlIGlzIHB1c2hlZCBpbnRvIGhlcmUgY2F1c2VzIGEgbnVtYmVyIG9m
IGlzc3Vlcy4NCj4gWW91IHRyeSB0byBwdXNoIG11bHRpcGxlIGNvb3JkaW5h
dGVzIG91dCB0aHJvdWdoIGEgcG9sbCBpbnRlcmZhY2UgdGhhdCBvbmx5DQo+
IGFsbG93cyBvbmUuDQo+IA0KPiBJIHdvdWxkIHN1Z2dlc3QgeW91IGVmZmVj
dGl2ZWx5IHJpcCB0aGUgdG91Y2hzY3JlZW4gY2hhbm5lbHMgb3V0IG9mIHRo
ZSBJSU8NCj4gZWxlbWVudHMgb2YgdGhlIGRyaXZlciBhbmQgc3VwcG9ydCB0
aGVtIHZpYSB0aGUgaW5wdXQgc3Vic3lzdGVtICh3aXRoaW4gdGhpcw0KPiBz
aW5nbGUgZHJpdmVyIGlzIGZpbmUpLg0KPiANCj4gSSdtIGN1cnJpb3VzIHRv
IG5vdGUgdGhhdCB0aGVyZSB3YXMgYSBzaXJmc29jX3JzIHRvdWNoc2NyZWVu
IGRyaXZlciBwb3N0ZWQgYQ0KPiB3aGlsZSBiYWNrLiAgV2h5IHdhcyB0aGF0
IG5vdCBwdXJzdWVkIGZ1dGhlcj8NCj4gDQo+IEknbSByZWFzb25hYmx5IGhh
cHB5IHdpdGggdGhlIGF1eCBjaGFubmVscyBzaWRlIG9mIHRoaW5ncy4gIEl0
J3MganVzdCB0aGUNCj4gdG91Y2hzY3JlZW4gYmVpbmcgYmx1Z2VvbmVkIGlu
dG8gYW4gaW5jb3JyZWN0IGludGVyZmFjZSB0aGF0IGlzIGNhdXNpbmcNCj4g
dHJvdWJsZSBoZXJlLg0KPiANCj4gVmFyaW91cyBvdGhlciBiaXRzIGlubGlu
ZS4NCj4gDQo+IEpvbmF0aGFuDQpbQmFycnkgU29uZ10gDQpKb25hdGhhbiwg
SSB1bmRlcnN0YW5kIHdoYXQgeW91IG1lYW4gYW5kIHVuZGVyc3RhbmQgeW91
ciBjb25jZXJuLiBXaGVuIHRoaXMgcGF0Y2ggY2FtZSB0byBvdXIgbG9jYWwg
Z2Vycml0IGZyb20gR3VveWluZywgSSBwdXQgdGhlIHNhbWUgY29tbWVudHMu
DQoiIG15IG9ubHkgY29uY2VybiBpcyB0aGF0IGlpbyBpcyBhY3R1YWxseSBw
cm92aWRpbmcgcmF3IGNoYW5uZWwgZGF0YS4gaGVyZSB5b3UgYXJlIHdyYXBw
aW5nIHRoZSByYXcgYWRjIGNoYW5uZWxzIHRvIGJhdHRlcnkvc2luZ2xlL2R1
YWwgdG91Y2ggbG9naWMgY2hhbm5lbC4gaXQgc2VlbXMgaXQgaXMgbm90IG1h
dGNoaW5nIHdpdGggaWlvLiAiDQoNCkJ1dCBoZXJlIEkgdGhvdWdodCB3ZSBj
YW4gaGF2ZSBhIHRyeS4gSWYgeW91IGNvbnNpZGVyIGlpbyBjYW4gcHJvdmlk
ZSBzb21lIGxvZ2ljIGNoYW5uZWxzIGluc3RlYWQgb2YgcHVyZSByYXcgZGF0
YSwgaXQgbWlnaHQgYmUgYmV0dGVyIGZvciB0aGVzZSB0d28gZHJpdmVycy4g
IHRoZSByZWxhdGVkIGNoYW5uZWxzIGFyZSBvbmx5IGZvciB0b3VjaHNjcmVl
biBhcyB3ZWxsLiAgVGhlIHNpcmZzb2NfdHMgc2ltcGx5IHRha2VzIHNhbXBs
ZWQgZGF0YSBmcm9tIGlpbywgYW5kIGxldCBpaW8gaGFuZGxlcyBhbGwgb2Yg
dGhlIHNhbXBsaW5nIHRoaW5ncy4NCg0KLWJhcnJ5DQoNCj4gPiAtLS0NCj4g
PiAgIC12MjogZml4IG1hbnkgaXNzdWVzIGZyb20gUGV0ZXIgYW5kIEpvbmF0
aGFuJ3MgZmVlZGJhY2tzDQo+ID4NCj4gPiAgIC4uLi9kZXZpY2V0cmVlL2Jp
bmRpbmdzL2lpby9hZGMvc2lyZnNvY19hZGMudHh0ICAgIHwgIDMzICsNCj4g
PiAgIGRyaXZlcnMvaWlvL2FkYy9LY29uZmlnICAgICAgICAgICAgICAgICAg
ICAgICAgICAgIHwgIDEwICsNCj4gPiAgIGRyaXZlcnMvaWlvL2FkYy9NYWtl
ZmlsZSAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgICAxICsNCj4gPiAg
IGRyaXZlcnMvaWlvL2FkYy9zaXJmc29jX2FkYy5jICAgICAgICAgICAgICAg
ICAgICAgIHwgNzU1ICsrKysrKysrKysrKysrKysrKysrKw0KPiA+ICAgNCBm
aWxlcyBjaGFuZ2VkLCA3OTkgaW5zZXJ0aW9ucygrKQ0KPiA+ICAgY3JlYXRl
IG1vZGUgMTAwNjQ0DQo+IERvY3VtZW50YXRpb24vZGV2aWNldHJlZS9iaW5k
aW5ncy9paW8vYWRjL3NpcmZzb2NfYWRjLnR4dA0KPiA+ICAgY3JlYXRlIG1v
ZGUgMTAwNjQ0IGRyaXZlcnMvaWlvL2FkYy9zaXJmc29jX2FkYy5jDQo+ID4N
Cj4gPiBkaWZmIC0tZ2l0IGEvRG9jdW1lbnRhdGlvbi9kZXZpY2V0cmVlL2Jp
bmRpbmdzL2lpby9hZGMvc2lyZnNvY19hZGMudHh0DQo+ID4gYi9Eb2N1bWVu
dGF0aW9uL2RldmljZXRyZWUvYmluZGluZ3MvaWlvL2FkYy9zaXJmc29jX2Fk
Yy50eHQNCj4gPiBuZXcgZmlsZSBtb2RlIDEwMDY0NA0KPiA+IGluZGV4IDAw
MDAwMDAuLjcwZWFmNDANCj4gPiAtLS0gL2Rldi9udWxsDQo+ID4gKysrIGIv
RG9jdW1lbnRhdGlvbi9kZXZpY2V0cmVlL2JpbmRpbmdzL2lpby9hZGMvc2ly
ZnNvY19hZGMudHh0DQo+ID4gQEAgLTAsMCArMSwzMyBAQA0KPiA+ICtTaXJm
c29jIGlubmVyIEFuYWxvZyB0byBEaWdpdGFsIENvbnZlcnRlciBiaW5kaW5n
cw0KPiA+ICsNCj4gPiArVGhlIGRldmljZXRyZWUgYmluZGluZ3MgYXJlIGZv
ciB0aGUgbmV3IEFEQyBkcml2ZXIgd3JpdHRlbiBmb3INCj4gPiArUHJpbWEy
L0F0bGFzNiBDU1IuDQo+ID4gKw0KPiA+ICtSZXF1aXJlZCBwcm9wZXJ0aWVz
Og0KPiA+ICstIGNvbXBhdGlibGU6IFNob3VsZCBiZSBvbmUgb2YNCj4gPiAr
CSogInNpcmYscHJpbWEyLWFkYyI6IFdoZW4gdXNlIFByaW1hMiBTT0MNCj4g
PiArCSogInNpcmYsYXRsYXM2LWFkYyI6IFdoZW4gdXNlIEF0bGFzNiBTT0MN
Cj4gPiArLSByZWc6IE9mZnNldCBhbmQgbGVuZ3RoIG9mIHRoZSByZWdpc3Rl
ciBzZXQgZm9yIHRoZSBkZXZpY2UNCj4gPiArLSBpbnRlcnJ1cHRzOiBTaG91
bGQgY29udGFpbiB0aGUgaW50ZXJydXB0IGZvciB0aGUgZGV2aWNlDQo+ID4g
Ky0gY2xvY2tzOiBUaGUgY2xvY2sgaXMgbmVlZGVkIGJ5IHRoZSBBREMgY29u
dHJvbGxlcg0KPiA+ICstIHJlc2V0czogVGhlIHJlc2V0IGZvciB0aGUgZGV2
aWNlDQo+ID4gKy0gI2lvLWNoYW5uZWwtY2VsbHM6IFNob3VsZCBiZSBzZXQg
dG8gPDE+DQo+ID4gKw0KPiA+ICtFeGFtcGxlOg0KPiA+ICsJYWRjOiBhZGNA
YjAxMTAwMDAgew0KPiA+ICsJCWNvbXBhdGlibGUgPSAic2lyZixwcmltYTIt
YWRjIjsNCj4gPiArCQlyZWcgPSA8MHhiMDExMDAwMCAweDEwMDAwPjsNCj4g
PiArCQlpbnRlcnJ1cHRzID0gPDM0PjsNCj4gPiArCQljbG9ja3MgPSA8JmNs
a3MgMTY+Ow0KPiA+ICsJCXJlc2V0cyA9IDwmcnN0YyAzMj47DQo+ID4gKwkJ
I2lvLWNoYW5uZWwtY2VsbHMgPSA8MT47DQo+ID4gKwl9Ow0KPiA+ICsNCj4g
PiArCWFkYzogYWRjQGIwMTEwMDAwIHsNCj4gPiArCQljb21wYXRpYmxlID0g
InNpcmYsYXRsYXM2LWFkYyI7DQo+ID4gKwkJcmVnID0gPDB4YjAxMTAwMDAg
MHgxMDAwMD47DQo+ID4gKwkJaW50ZXJydXB0cyA9IDwzND47DQo+ID4gKwkJ
Y2xvY2tzID0gPCZjbGtzIDE2PjsNCj4gPiArCQlyZXNldHMgPSA8JnJzdGMg
MzI+Ow0KPiA+ICsJCSNpby1jaGFubmVsLWNlbGxzID0gPDE+Ow0KPiA+ICsJ
fTsNCj4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9paW8vYWRjL0tjb25maWcg
Yi9kcml2ZXJzL2lpby9hZGMvS2NvbmZpZyBpbmRleA0KPiA+IGE4MGQyMzYu
LjZiODAzZDUgMTAwNjQ0DQo+ID4gLS0tIGEvZHJpdmVycy9paW8vYWRjL0tj
b25maWcNCj4gPiArKysgYi9kcml2ZXJzL2lpby9hZGMvS2NvbmZpZw0KPiA+
IEBAIC0xODcsNiArMTg3LDE2IEBAIGNvbmZpZyBOQVU3ODAyDQo+ID4gICAJ
ICBUbyBjb21waWxlIHRoaXMgZHJpdmVyIGFzIGEgbW9kdWxlLCBjaG9vc2Ug
TSBoZXJlOiB0aGUNCj4gPiAgIAkgIG1vZHVsZSB3aWxsIGJlIGNhbGxlZCBu
YXU3ODAyLg0KPiA+DQo+ID4gK2NvbmZpZyBTSVJGU09DX0FEQw0KPiA+ICsJ
dHJpc3RhdGUgIlNpUkZTb0MgQURDIg0KPiA+ICsJZGVwZW5kcyBvbiBBUkNI
X1NJUkYNCj4gPiArCWhlbHANCj4gPiArCSAgSWYgeW91IHNheSB5ZXMgaGVy
ZSB5b3UgZ2V0IHN1cHBvcnQgZm9yIENTUiBTaVJGU29DIGludGVybmFsDQo+
ID4gKwkgIEFEQy4NCj4gPiArDQo+ID4gKwkgIFRoaXMgZHJpdmVyIGNhbiBh
bHNvIGJlIGJ1aWx0IGFzIGEgbW9kdWxlLiBJZiBzbywgdGhlIG1vZHVsZSB3
aWxsIGJlDQo+ID4gKwkgIGNhbGxlZCBzaXJmc29jX2FkYy4NCj4gPiArDQo+
ID4gICBjb25maWcgVElfQURDMDgxQw0KPiA+ICAgCXRyaXN0YXRlICJUZXhh
cyBJbnN0cnVtZW50cyBBREMwODFDMDIxLzAyNyINCj4gPiAgIAlkZXBlbmRz
IG9uIEkyQw0KPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL2lpby9hZGMvTWFr
ZWZpbGUgYi9kcml2ZXJzL2lpby9hZGMvTWFrZWZpbGUgaW5kZXgNCj4gPiA5
ZDYwZjJkLi4yOTEyZTU4IDEwMDY0NA0KPiA+IC0tLSBhL2RyaXZlcnMvaWlv
L2FkYy9NYWtlZmlsZQ0KPiA+ICsrKyBiL2RyaXZlcnMvaWlvL2FkYy9NYWtl
ZmlsZQ0KPiA+IEBAIC0yMCw2ICsyMCw3IEBAIG9iai0kKENPTkZJR19NQ1Az
MjBYKSArPSBtY3AzMjB4Lm8NCj4gPiAgIG9iai0kKENPTkZJR19NQ1AzNDIy
KSArPSBtY3AzNDIyLm8NCj4gPiAgIG9iai0kKENPTkZJR19NRU5fWjE4OF9B
REMpICs9IG1lbl96MTg4X2FkYy5vDQo+ID4gICBvYmotJChDT05GSUdfTkFV
NzgwMikgKz0gbmF1NzgwMi5vDQo+ID4gK29iai0kKENPTkZJR19TSVJGU09D
X0FEQykgKz0gc2lyZnNvY19hZGMubw0KPiA+ICAgb2JqLSQoQ09ORklHX1RJ
X0FEQzA4MUMpICs9IHRpLWFkYzA4MWMubw0KPiA+ICAgb2JqLSQoQ09ORklH
X1RJX0FNMzM1WF9BREMpICs9IHRpX2FtMzM1eF9hZGMubw0KPiA+ICAgb2Jq
LSQoQ09ORklHX1RXTDQwMzBfTUFEQykgKz0gdHdsNDAzMC1tYWRjLm8gZGlm
ZiAtLWdpdA0KPiA+IGEvZHJpdmVycy9paW8vYWRjL3NpcmZzb2NfYWRjLmMg
Yi9kcml2ZXJzL2lpby9hZGMvc2lyZnNvY19hZGMuYyBuZXcNCj4gPiBmaWxl
IG1vZGUgMTAwNjQ0IGluZGV4IDAwMDAwMDAuLmFlMTFhMzYNCj4gPiAtLS0g
L2Rldi9udWxsDQo+ID4gKysrIGIvZHJpdmVycy9paW8vYWRjL3NpcmZzb2Nf
YWRjLmMNCj4gPiBAQCAtMCwwICsxLDc1NSBAQA0KPiA+ICsvKg0KPiA+ICsq
IEFEQyBEcml2ZXIgZm9yIENTUiBTaVJGU29DDQo+ID4gKyoNCj4gPiArKiBD
b3B5cmlnaHQgKGMpIDIwMTQgQ2FtYnJpZGdlIFNpbGljb24gUmFkaW8gTGlt
aXRlZCwgYSBDU1IgcGxjIGdyb3VwDQo+IGNvbXBhbnkuDQo+ID4gKyoNCj4g
PiArKiBMaWNlbnNlZCB1bmRlciBHUEx2Mi4NCj4gPiArKi8NCj4gPiArDQo+
ID4gKyNpbmNsdWRlIDxsaW51eC9tb2R1bGUuaD4NCj4gPiArI2luY2x1ZGUg
PGxpbnV4L2tlcm5lbC5oPg0KPiA+ICsjaW5jbHVkZSA8bGludXgvaW5pdC5o
Pg0KPiA+ICsjaW5jbHVkZSA8bGludXgvY2xrLmg+DQo+ID4gKyNpbmNsdWRl
IDxsaW51eC9pby5oPg0KPiA+ICsjaW5jbHVkZSA8bGludXgvaW50ZXJydXB0
Lmg+DQo+ID4gKyNpbmNsdWRlIDxsaW51eC9vZi5oPg0KPiA+ICsjaW5jbHVk
ZSA8bGludXgvcG0uaD4NCj4gPiArI2luY2x1ZGUgPGxpbnV4L3BsYXRmb3Jt
X2RldmljZS5oPg0KPiA+ICsjaW5jbHVkZSA8bGludXgvb2ZfcGxhdGZvcm0u
aD4NCj4gPiArI2luY2x1ZGUgPGxpbnV4L3Jlc2V0Lmg+DQo+ID4gKyNpbmNs
dWRlIDxsaW51eC9ydGMvc2lyZnNvY19ydGNpb2JyZy5oPg0KPiA+ICsNCj4g
PiArI2luY2x1ZGUgPGxpbnV4L2lpby9paW8uaD4NCj4gPiArI2luY2x1ZGUg
PGxpbnV4L2lpby9tYWNoaW5lLmg+DQo+ID4gKyNpbmNsdWRlIDxsaW51eC9p
aW8vZHJpdmVyLmg+DQo+ID4gKw0KPiA+ICsjZGVmaW5lIERSSVZFUl9OQU1F
ICJzaXJmc29jX2FkYyINCj4gPiArDQo+ID4gKyNkZWZpbmUgU0lSRlNPQ19Q
V1JfV0FLRUVOX1RTQ19TSElGVAkyMw0KPiA+ICsjZGVmaW5lIFNJUkZTT0Nf
UFdSX1dBS0VFTl9UU19TSElGVAk1DQo+ID4gKyNkZWZpbmUgU0lSRlNPQ19Q
V1JDX1RSSUdHRVJfRU4JCTB4OA0KPiA+ICsjZGVmaW5lIFNJUkZTT0NfUFdS
Q19CQVNFCQkweDMwMDANCj4gPiArDQo+ID4gKy8qIFJlZ2lzdGVycyBvZmZz
ZXQgKi8NCj4gPiArI2RlZmluZSBTSVJGU09DX0FEQ19DT05UUk9MMQkJMHgw
MA0KPiA+ICsjZGVmaW5lIFNJUkZTT0NfQURDX0NPTlRST0wyCQkweDA0DQo+
ID4gKyNkZWZpbmUgU0lSRlNPQ19BRENfSU5UUgkJMHgwOA0KPiA+ICsjZGVm
aW5lIFNJUkZTT0NfQURDX0NPT1JECQkweDBDDQo+ID4gKyNkZWZpbmUgU0lS
RlNPQ19BRENfUFJFU1NVUkUJCTB4MTANCj4gPiArI2RlZmluZSBTSVJGU09D
X0FEQ19BVVgxCQkweDE0DQo+ID4gKy8qIEF0bGFzNiBBVVgyIGFuZCBBVVg0
IHJlc2VydmVkKi8NCj4gPiArI2RlZmluZSBTSVJGU09DX0FEQ19BVVgyCQkw
eDE4DQo+ID4gKyNkZWZpbmUgU0lSRlNPQ19BRENfQVVYMwkJMHgxQw0KPiA+
ICsjZGVmaW5lIFNJUkZTT0NfQURDX0FVWDQJCTB4MjANCj4gPiArI2RlZmlu
ZSBTSVJGU09DX0FEQ19BVVg1CQkweDI0DQo+ID4gKyNkZWZpbmUgU0lSRlNP
Q19BRENfQVVYNgkJMHgyOA0KPiA+ICsvKiBSZWFkIEJhY2sgY2FsaWJyYXRp
b24gcmVnaXN0ZXIgKi8NCj4gPiArI2RlZmluZSBTSVJGU09DX0FEQ19DQgkJ
CTB4MkMNCj4gPiArI2RlZmluZSBTSVJGU09DX0FEQ19DT09SRDIJCTB4MzAN
Cj4gPiArI2RlZmluZSBTSVJGU09DX0FEQ19DT09SRDMJCTB4MzQNCj4gPiAr
I2RlZmluZSBTSVJGU09DX0FEQ19DT09SRDQJCTB4MzgNCj4gPiArDQo+ID4g
Ky8qIENUUkwxIGRlZmluZXMgKi8NCj4gPiArI2RlZmluZSBTSVJGU09DX0FE
Q19SRVNFVF9RVUFOVF9FTglCSVQoMjQpDQo+ID4gKyNkZWZpbmUgU0lSRlNP
Q19BRENfUlNUX0IJCUJJVCgyMykNCj4gPiArI2RlZmluZSBTSVJGU09DX0FE
Q19SRVNPTFVUSU9OXzEyCUJJVCgyMikNCj4gPiArI2RlZmluZSBTSVJGU09D
X0FEQ19SQkFUX0RJU0FCTEUJKDB4MCA8PCAyMSkNCj4gPiArI2RlZmluZSBT
SVJGU09DX0FEQ19SQkFUX0VOQUJMRQkJKDB4MSA8PCAyMSkNCj4gPiArI2Rl
ZmluZSBTSVJGU09DX0FEQ19FWFRDTSh4KQkJKCgoeCkgJiAweDMpIDw8IDE5
KQ0KPiA+ICsjZGVmaW5lIFNJUkZTT0NfQURDX1NHQUlOKHgpCQkoKCh4KSAm
IDB4NykgPDwgMTYpDQo+ID4gKyNkZWZpbmUgU0lSRlNPQ19BRENfUE9MTAkJ
QklUKDE1KQ0KPiA+ICsjZGVmaW5lIFNJUkZTT0NfQURDX1NFTCh4KQkJKCgo
eCkgJiAweEYpIDw8IDExKQ0KPiA+ICsjZGVmaW5lIFNJUkZTT0NfQURDX0ZS
RVFfNksJCSgweDAgPDwgOCkNCj4gPiArI2RlZmluZSBTSVJGU09DX0FEQ19G
UkVRXzEzSwkJQklUKDgpDQo+ID4gKyNkZWZpbmUgU0lSRlNPQ19BRENfREVM
X1NFVCh4KQkJKCgoeCkgJiAweEYpIDw8IDQpDQo+ID4gKyNkZWZpbmUgU0lS
RlNPQ19BRENfVFBfVElNRSh4KQkJKCgoeCkgJiAweDcpIDw8IDApDQo+ID4g
Kw0KPiA+ICsvKiBDVFJMMiBkZWZpbmVzICovDQo+ID4gKy8qIFBlbiBkZXRl
Y3RvciBvZmYsIGRpZ2l0aXplciBvZmYgKi8NCj4gPiArI2RlZmluZSBTSVJG
U09DX0FEQ19QUlBfTU9ERTAJCSgwIDw8IDE0KQ0KPiA+ICsvKiBQZW4gZGV0
ZWN0b3Igb24sIGRpZ2l0aXplciBvZmYsIGRpZ2l0aXplciB3YWtlcyB1cCBv
biBwZW4gZGV0ZWN0ICovDQo+ID4gKyNkZWZpbmUgU0lSRlNPQ19BRENfUFJQ
X01PREUxCQlCSVQoMTQpDQo+ID4gKy8qIFBlbiBkZXRlY3RvciBvbiwgZGln
aXRpemVyIG9mZiwgbm8gd2FrZSB1cCBvbiBwZW4gZGV0ZWN0ICovDQo+ID4g
KyNkZWZpbmUgU0lSRlNPQ19BRENfUFJQX01PREUyCQkoMiA8PCAxNCkNCj4g
PiArLyogUGVuIGRldGVjdG9yIG9uLCBkaWdpdGl6ZXIgb24gKi8NCj4gPiAr
I2RlZmluZSBTSVJGU09DX0FEQ19QUlBfTU9ERTMJCSgzIDw8IDE0KQ0KPiA+
ICsjZGVmaW5lIFNJUkZTT0NfQURDX1JUT1VDSCh4KQkJKCgoeCkgJiAweDMp
IDw8IDEyKQ0KPiA+ICsjZGVmaW5lIFNJUkZTT0NfQURDX0RFTF9QUkUoeCkJ
CSgoKHgpICYgMHhGKSA8PCA0KQ0KPiA+ICsjZGVmaW5lIFNJUkZTT0NfQURD
X0RFTF9ESVMoeCkJCSgoKHgpICYgMHhGKSA8PCAwKQ0KPiA+ICsNCj4gPiAr
LyogSU5UUiByZWdpc3RlciBkZWZpbmVzICovDQo+ID4gKyNkZWZpbmUgU0lS
RlNPQ19BRENfUEVOX0lOVFJfRU4JCUJJVCg1KQ0KPiA+ICsjZGVmaW5lIFNJ
UkZTT0NfQURDX0RBVEFfSU5UUl9FTglCSVQoNCkNCj4gPiArI2RlZmluZSBT
SVJGU09DX0FEQ19QRU5fSU5UUgkJQklUKDEpDQo+ID4gKyNkZWZpbmUgU0lS
RlNPQ19BRENfREFUQV9JTlRSCQlCSVQoMCkNCj4gPiArDQo+ID4gKy8qIERB
VEEgcmVnaXN0ZXIgZGVmaW5lcyAqLw0KPiA+ICsjZGVmaW5lIFNJUkZTT0Nf
QURDX1BFTl9ET1dOCQlCSVQoMzEpDQo+ID4gKyNkZWZpbmUgU0lSRlNPQ19B
RENfREFUQV9BVVhWQUxJRAlCSVQoMzApDQo+ID4gKyNkZWZpbmUgU0lSRlNP
Q19BRENfREFUQV9DQl9WQUxJRAlCSVQoMzApDQo+ID4gKyNkZWZpbmUgU0lS
RlNPQ19BRENfQURDX0RBVEFfTUFTSyh4KQkoMHgzRkZGIDw8ICh4KSkNCj4g
PiArI2RlZmluZSBTSVJGU09DX0FEQ19EQVRBX0FVWE1BU0sNCj4gCVNJUkZT
T0NfQURDX0FEQ19EQVRBX01BU0soMCkNCj4gPiArI2RlZmluZSBTSVJGU09D
X0FEQ19EQVRBX0NCTUFTSw0KPiAJU0lSRlNPQ19BRENfQURDX0RBVEFfTUFT
SygwKQ0KPiA+ICsNCj4gPiArI2RlZmluZSBTSVJGU09DX0FEQ19NT1JFX0NU
TDENCj4gCShvZl9tYWNoaW5lX2lzX2NvbXBhdGlibGUoInNpcmYsYXRsYXM2
IikgP1wNCj4gPiArCQkJCShTSVJGU09DX0FEQ19SRVNFVF9RVUFOVF9FTiB8
XA0KPiA+ICsJCQkJU0lSRlNPQ19BRENfUlNUX0IpIDogKDApKQ0KPiA+ICsN
Cj4gPiArLyogU2VsZWN0IEFEIHNhbXBsZXMgdG8gcmVhZCAoU0VMIGJpdHMg
aW4gQURDX0NPTlRST0wxIHJlZ2lzdGVyKSAqLw0KPiA+ICsjZGVmaW5lIFNJ
UkZTT0NfQURDX0FVWDFfU0VMCTB4MDQNCj4gPiArI2RlZmluZSBTSVJGU09D
X0FEQ19BVVgyX1NFTAkweDA1DQo+ID4gKyNkZWZpbmUgU0lSRlNPQ19BRENf
QVVYM19TRUwJMHgwNg0KPiA+ICsjZGVmaW5lIFNJUkZTT0NfQURDX0FVWDRf
U0VMCTB4MDcNCj4gPiArI2RlZmluZSBTSVJGU09DX0FEQ19BVVg1X1NFTAkw
eDA4DQo+ID4gKyNkZWZpbmUgU0lSRlNPQ19BRENfQVVYNl9TRUwJMHgwOQ0K
PiA+ICsjZGVmaW5lIFNJUkZTT0NfQURDX1RTX1NFTAkweDBBICAgIC8qIFNh
bXBsZSBmb3Igc2luZ2xlIHRvdWNoKi8NCj4gPiArI2RlZmluZSBTSVJGU09D
X0FEQ19HUk9VTkRfU0VMCTB4MEIgICAgLyogR291bmQgZm9yIG9mZnNldA0K
PiBjYWxpYnJhdGlvbiAqLw0KPiA+ICsjZGVmaW5lIFNJUkZTT0NfQURDX0JB
TkRHQVBfU0VMCTB4MEMgICAgLyogQmFuZGdhcCBmb3IgZ2Fpbg0KPiBjYWxp
YnJhdGlvbiAqLw0KPiA+ICsjZGVmaW5lIFNJUkZTT0NfQURDX1RTX1NFTF9E
VUFMCTB4MEYgICAgLyogU2FtcGxlcyBmb3IgZHVhbA0KPiB0b3VjaCAqLw0K
PiA+ICsNCj4gPiArI2RlZmluZSBTSVJGU09DX0FEQ19UU19TQU1QTEVfU0la
RQk0DQo+ID4gKyNkZWZpbmUgU0lSRlNPQ19BRENfQ1RMMShzZWwpICAgIChT
SVJGU09DX0FEQ19QT0xMIHwNCj4gU0lSRlNPQ19BRENfU0VMKHNlbCkgfFwN
Cj4gPiArCQlTSVJGU09DX0FEQ19ERUxfU0VUKDYpIHwgU0lSRlNPQ19BRENf
RlJFUV82SyB8XA0KPiA+ICsJCVNJUkZTT0NfQURDX1RQX1RJTUUoMCkgfCBT
SVJGU09DX0FEQ19TR0FJTigwKSB8XA0KPiA+ICsJCVNJUkZTT0NfQURDX0VY
VENNKDApIHwgU0lSRlNPQ19BRENfUkJBVF9ESVNBQkxFIHxcDQo+ID4gKwkJ
U0lSRlNPQ19BRENfTU9SRV9DVEwxKQ0KPiA+ICsNCj4gPiArZW51bSBzaXJm
c29jX2FkY19jaGlwcyB7DQo+ID4gKwlQUklNQTIsDQo+ID4gKwlBVExBUzYs
DQo+ID4gK307DQo+ID4gKw0KPiA+ICtzdHJ1Y3Qgc2lyZnNvY19hZGNfY2hp
cF9pbmZvIHsNCj4gPiArCWNvbnN0IHN0cnVjdCBpaW9fY2hhbl9zcGVjICpj
aGFubmVsczsNCj4gPiArCXVuc2lnbmVkIGludCBudW1fY2hhbm5lbHM7DQo+
ID4gKwl1bnNpZ25lZCBpbnQgZmxhZ3M7DQo+ID4gKwljb25zdCBzdHJ1Y3Qg
aWlvX2luZm8gKmlpb19pbmZvOw0KPiA+ICsNCj4gPiArCXUzMiAoKmNhbGN1
bGF0ZV92b2x0KSh1MzIsIHUzMiwgdTMyKTsNCj4gSSdkIGRlZmluaXRlbHkg
cHV0IHBhcmFtZXRlciBuYW1lcyBpbiBoZXJlIHRvIGFjdCBhcyBzb21lIGZv
cm0gb2YgbWluaW1hbA0KPiBkb2N1bWVudGF0aW9uIG9mIHdoYXQgaXMgbmVl
ZGVkLg0KPiA+ICsJY29uc3QgdTMyICpjaGFubmVsX3NlbDsNCj4gPiArfTsN
Cj4gPiArDQo+ID4gK3N0cnVjdCBzaXJmc29jX2FkY19yZXF1ZXN0IHsNCj4g
PiArCXUxNiBtb2RlOw0KPiA+ICsJdTE2IGV4dGNtOw0KPiA+ICsJdTE2IHJl
ZmVyZW5jZTsNCj4gPiArCXU4IGRlbGF5X2JpdHM7DQo+ID4gKwl1MzIgc19n
YWluX2JpdHM7DQo+ID4gKwl1MTYgcmVhZF9iYWNrX2RhdGE7DQo+ID4gK307
DQo+ID4gKw0KPiA+ICtzdHJ1Y3Qgc2lyZnNvY19hZGMgew0KPiA+ICsJY29u
c3Qgc3RydWN0IHNpcmZzb2NfYWRjX2NoaXBfaW5mbwkqY2hpcF9pbmZvOw0K
PiA+ICsJc3RydWN0IGNsawkqY2xrOw0KPiA+ICsJdm9pZCBfX2lvbWVtCSpi
YXNlOw0KPiA+ICsJc3RydWN0IHNpcmZzb2NfYWRjX3JlcXVlc3QgcmVxOw0K
PiA+ICsJc3RydWN0IGNvbXBsZXRpb24JZG9uZTsNCj4gPiArCXN0cnVjdCBt
dXRleAlhZGNfbG9jazsNCj4gPiArfTsNCj4gPiArDQo+ID4gK3N0YXRpYyBj
b25zdCB1MzIgc2lyZnNvY19hZGNfdHNfcmVnW1NJUkZTT0NfQURDX1RTX1NB
TVBMRV9TSVpFXSA9IHsNCj4gPiArCS8qIER1YWwgdG91Y2ggc2FtcGxlcyBy
ZWFkIHJlZ2lzdGVycyovDQo+ID4gKwlTSVJGU09DX0FEQ19DT09SRCwgU0lS
RlNPQ19BRENfQ09PUkQyLA0KPiA+ICsJU0lSRlNPQ19BRENfQ09PUkQzLCBT
SVJGU09DX0FEQ19DT09SRDQgfTsNCj4gPiArDQo+ID4gK2VudW0gc2lyZnNv
Y19hZGNfdHNfdHlwZSB7DQo+ID4gKwlTSU5HTEVfVE9VQ0gsDQo+ID4gKwlE
VUFMX1RPVUNILA0KPiA+ICt9Ow0KPiA+ICsNCj4gPiArc3RhdGljIGludCBz
aXJmc29jX2FkY19nZXRfdHNfc2FtcGxlKA0KPiA+ICsJc3RydWN0IHNpcmZz
b2NfYWRjICphZGMsIGludCAqc2FtcGxlLCBpbnQgdG91Y2hfdHlwZSkgew0K
PiA+ICsJaW50IGFkY19pbnRyOw0KPiA+ICsJaW50IHJldCA9IDA7DQo+ID4g
KwlpbnQgaTsNCj4gPiArDQo+ID4gKwltdXRleF9sb2NrKCZhZGMtPmFkY19s
b2NrKTsNCj4gPiArCWFkY19pbnRyID0gcmVhZGwoYWRjLT5iYXNlICsgU0lS
RlNPQ19BRENfSU5UUik7DQo+ID4gKwlpZiAoYWRjX2ludHIgJiBTSVJGU09D
X0FEQ19QRU5fSU5UUikNCj4gPiArCQl3cml0ZWwoU0lSRlNPQ19BRENfUEVO
X0lOVFIgfA0KPiBTSVJGU09DX0FEQ19QRU5fSU5UUl9FTiB8DQo+ID4gKwkJ
CVNJUkZTT0NfQURDX0RBVEFfSU5UUl9FTiwNCj4gPiArCQkJYWRjLT5iYXNl
ICsgU0lSRlNPQ19BRENfSU5UUik7DQo+ID4gKw0KPiA+ICsJLyogY2hlY2sg
cGVuIHN0YXR1cyAqLw0KPiA+ICsJaWYgKCEocmVhZGwoYWRjLT5iYXNlICsg
U0lSRlNPQ19BRENfQ09PUkQpICYNCj4gU0lSRlNPQ19BRENfUEVOX0RPV04p
KSB7DQo+ID4gKwkJcmV0ID0gLUVJTlZBTDsNCj4gPiArCQlnb3RvIG91dDsN
Cj4gPiArCX0NCj4gPiArDQo+ID4gKwlpZiAoU0lOR0xFX1RPVUNIID09IHRv
dWNoX3R5cGUpDQo+ID4gKwkJd3JpdGVsKFNJUkZTT0NfQURDX0NUTDEoU0lS
RlNPQ19BRENfVFNfU0VMKSwNCj4gPiArCQkJYWRjLT5iYXNlICsgU0lSRlNP
Q19BRENfQ09OVFJPTDEpOw0KPiA+ICsJZWxzZQ0KPiA+ICsJCXdyaXRlbChT
SVJGU09DX0FEQ19DVEwxKFNJUkZTT0NfQURDX1RTX1NFTF9EVUFMKSwNCj4g
PiArCQkJYWRjLT5iYXNlICsgU0lSRlNPQ19BRENfQ09OVFJPTDEpOw0KPiA+
ICsNCj4gPiArCWlmICghd2FpdF9mb3JfY29tcGxldGlvbl90aW1lb3V0KCZh
ZGMtPmRvbmUsDQo+ID4gKwkJbXNlY3NfdG9famlmZmllcyg1MCkpKSB7DQo+
ID4gKwkJcmV0ID0gLUVJTzsNCj4gPiArCQlnb3RvIG91dDsNCj4gPiArCX0N
Cj4gPiArDQo+ID4gKwlpZiAoU0lOR0xFX1RPVUNIID09IHRvdWNoX3R5cGUp
DQo+ID4gKwkJKnNhbXBsZSA9IHJlYWRsKGFkYy0+YmFzZSArIFNJUkZTT0Nf
QURDX0NPT1JEKTsNCj4gRXJyLCBzaWxseSBxdWVzdGlvbiBidXQgd2hhdCB0
aGUgaGVjayBpcyB0aGUgZm9ybWF0IG9mIHRoaXM/ICBQbGVhc2UgZG9uJ3Qg
c2VuZA0KPiBtdWx0aXBsZSBjaGFubmVscyBvZiByZWFsIGRhdGEgdGhyb3Vn
aCBhcyAnUkFXJy4gIElmIHlvdSBkbyB0aGV5J2xsIG5ldmVyIHdvcmsNCj4g
d2l0aCBhbnl0aGluZyBvdGhlciB0aGFuIGNhcmVmdWxseSBjb250cml2ZWQg
bm9uIHN0YW5kYXJkIHVzZXJzcGFjZS4NCj4gPiArCWVsc2UNCj4gPiArCQlm
b3IgKGkgPSAwOyBpIDwgU0lSRlNPQ19BRENfVFNfU0FNUExFX1NJWkU7IGkr
KykNCj4gPiArCQkJc2FtcGxlW2ldID0gcmVhZGwoYWRjLT5iYXNlICsgc2ly
ZnNvY19hZGNfdHNfcmVnW2ldKTsNCj4gU2FtcGxlIGlzIGEgcG9pbnRlciB0
byBhIHNpbmdsZSBlbGVtZW50IHNvIHlvdSBjYW4ndCBkbyB0aGlzLg0KPiA+
ICsNCj4gPiArb3V0Og0KPiA+ICsJbXV0ZXhfdW5sb2NrKCZhZGMtPmFkY19s
b2NrKTsNCj4gPiArCXJldHVybiByZXQ7DQo+ID4gK30NCj4gPiArDQo+ID4g
Ky8qIGdldCB0b3VjaHNjcmVlbiBjb29yZGluYXRlcyBmb3Igc2luZ2xlIHRv
dWNoICovIHN0YXRpYyBpbnQNCj4gPiArc2lyZnNvY19hZGNfc2luZ2xlX3Rz
X3NhbXBsZShzdHJ1Y3Qgc2lyZnNvY19hZGMgKmFkYywgaW50ICpzYW1wbGUp
IHsNCj4gc2FtcGxlIGlzIHBvaW50aW5nIHRvIGEgc2luZ2xlIGludGVnZXIu
Li4NCj4gPiArCXJldHVybiBzaXJmc29jX2FkY19nZXRfdHNfc2FtcGxlKGFk
Yywgc2FtcGxlLCBTSU5HTEVfVE9VQ0gpOyB9DQo+ID4gKw0KPiA+ICsvKiBn
ZXQgdG91Y2hzY3JlZW4gY29vcmRpbmF0ZXMgZm9yIGR1YWwgdG91Y2ggKi8g
c3RhdGljIGludA0KPiA+ICtzaXJmc29jX2FkY19kdWFsX3RzX3NhbXBsZShz
dHJ1Y3Qgc2lyZnNvY19hZGMgKmFkYywgaW50ICpzYW1wbGVzKSB7DQo+ID4g
KwlyZXR1cm4gc2lyZnNvY19hZGNfZ2V0X3RzX3NhbXBsZShhZGMsIHNhbXBs
ZXMsIERVQUxfVE9VQ0gpOyB9DQo+ID4gKw0KPiA+ICtzdGF0aWMgaW50IHNp
cmZzb2NfYWRjX3NlbmRfcmVxdWVzdChzdHJ1Y3Qgc2lyZnNvY19hZGNfcmVx
dWVzdCAqcmVxKQ0KPiA+ICt7DQo+ID4gKwlzdHJ1Y3Qgc2lyZnNvY19hZGMg
KmFkYyA9IGNvbnRhaW5lcl9vZihyZXEsIHN0cnVjdCBzaXJmc29jX2FkYywg
cmVxKTsNCj4gPiArCWludCBjb250cm9sMSwgY29udHJvbDIsIGludHI7DQo+
ID4gKwlpbnQgZGF0YSwgcmVnX29mZnNldDsNCj4gPiArCWludCByZXQgPSAw
Ow0KPiA+ICsNCj4gPiArCW11dGV4X2xvY2soJmFkYy0+YWRjX2xvY2spOw0K
PiA+ICsNCj4gPiArCS8qIFN0b3JlIHJlZ2lzdGVycyBmb3IgcmVjb3ZlciAq
Lw0KPiA+ICsJaW50ciA9IHJlYWRsKGFkYy0+YmFzZSArIFNJUkZTT0NfQURD
X0lOVFIpOw0KPiA+ICsJY29udHJvbDEgPSByZWFkbChhZGMtPmJhc2UgKyBT
SVJGU09DX0FEQ19DT05UUk9MMSk7DQo+ID4gKwljb250cm9sMiA9IHJlYWRs
KGFkYy0+YmFzZSArIFNJUkZTT0NfQURDX0NPTlRST0wyKTsNCj4gPiArDQo+
ID4gKwl3cml0ZWwoaW50ciB8IFNJUkZTT0NfQURDX0RBVEFfSU5UUl9FTiB8
DQo+IFNJUkZTT0NfQURDX0RBVEFfSU5UUiwNCj4gPiArCQlhZGMtPmJhc2Ug
KyBTSVJGU09DX0FEQ19JTlRSKTsNCj4gPiArCXdyaXRlbChTSVJGU09DX0FE
Q19QUlBfTU9ERTMgfCByZXEtPnJlZmVyZW5jZSwNCj4gPiArCQlhZGMtPmJh
c2UgKyBTSVJGU09DX0FEQ19DT05UUk9MMik7DQo+ID4gKwl3cml0ZWwoU0lS
RlNPQ19BRENfUE9MTCB8IFNJUkZTT0NfQURDX01PUkVfQ1RMMSB8IHJlcS0N
Cj4gPm1vZGUgfA0KPiA+ICsJCXJlcS0+ZXh0Y20gfCByZXEtPmRlbGF5X2Jp
dHMgfA0KPiBTSVJGU09DX0FEQ19SRVNPTFVUSU9OXzEyLA0KPiA+ICsJCWFk
Yy0+YmFzZSArIFNJUkZTT0NfQURDX0NPTlRST0wxKTsNCj4gPiArDQo+ID4g
KwlpZiAoIXdhaXRfZm9yX2NvbXBsZXRpb25fdGltZW91dCgmYWRjLT5kb25l
LA0KPiA+ICsJCW1zZWNzX3RvX2ppZmZpZXMoNTApKSkgew0KPiA+ICsJCXJl
dCA9IC1FSU87DQo+ID4gKwkJZ290byBvdXQ7DQo+ID4gKwl9DQo+ID4gKw0K
PiA+ICsJc3dpdGNoIChyZXEtPm1vZGUpIHsNCj4gPiArCWNhc2UgU0lSRlNP
Q19BRENfU0VMKFNJUkZTT0NfQURDX0FVWDFfU0VMKToNCj4gPiArCWNhc2Ug
U0lSRlNPQ19BRENfU0VMKFNJUkZTT0NfQURDX0FVWDJfU0VMKToNCj4gPiAr
CWNhc2UgU0lSRlNPQ19BRENfU0VMKFNJUkZTT0NfQURDX0FVWDNfU0VMKToN
Cj4gPiArCWNhc2UgU0lSRlNPQ19BRENfU0VMKFNJUkZTT0NfQURDX0FVWDRf
U0VMKToNCj4gPiArCWNhc2UgU0lSRlNPQ19BRENfU0VMKFNJUkZTT0NfQURD
X0FVWDVfU0VMKToNCj4gPiArCWNhc2UgU0lSRlNPQ19BRENfU0VMKFNJUkZT
T0NfQURDX0FVWDZfU0VMKToNCj4gPiArCQkvKiBDYWxjdWxhdGUgYXV4IG9m
ZnNldCBmcm9tIG1vZGUgKi8NCj4gPiArCQlyZWdfb2Zmc2V0ID0gMHgxNCAr
ICgocmVxLT5tb2RlID4+IDExKSAtIDB4MDQpICogNDsNCj4gPiArCQlkYXRh
ID0gcmVhZGwoYWRjLT5iYXNlICsgcmVnX29mZnNldCk7DQo+ID4gKwkJaWYg
KGRhdGEgJiBTSVJGU09DX0FEQ19EQVRBX0FVWFZBTElEKQ0KPiA+ICsJCQly
ZXEtPnJlYWRfYmFja19kYXRhID0gZGF0YSAmDQo+IFNJUkZTT0NfQURDX0RB
VEFfQVVYTUFTSzsNCj4gPiArCQlicmVhazsNCj4gPiArCWNhc2UgU0lSRlNP
Q19BRENfU0VMKFNJUkZTT0NfQURDX0dST1VORF9TRUwpOg0KPiA+ICsJY2Fz
ZSBTSVJGU09DX0FEQ19TRUwoU0lSRlNPQ19BRENfQkFOREdBUF9TRUwpOg0K
PiA+ICsJCXJlZ19vZmZzZXQgPSBTSVJGU09DX0FEQ19DQjsNCj4gPiArCQlk
YXRhID0gcmVhZGwoYWRjLT5iYXNlICsgcmVnX29mZnNldCk7DQo+ID4gKwkJ
aWYgKGRhdGEgJiBTSVJGU09DX0FEQ19EQVRBX0NCX1ZBTElEKQ0KPiA+ICsJ
CQlyZXEtPnJlYWRfYmFja19kYXRhID0gZGF0YSAmDQo+IFNJUkZTT0NfQURD
X0RBVEFfQ0JNQVNLOw0KPiA+ICsJCWJyZWFrOw0KPiA+ICsJZGVmYXVsdDoN
Cj4gPiArCQlicmVhazsNCj4gPiArCX0NCj4gPiArDQo+ID4gK291dDoNCj4g
PiArCXdyaXRlbChpbnRyLCBhZGMtPmJhc2UgKyBTSVJGU09DX0FEQ19JTlRS
KTsNCj4gPiArCXdyaXRlbChjb250cm9sMSwgYWRjLT5iYXNlICsgU0lSRlNP
Q19BRENfQ09OVFJPTDEpOw0KPiA+ICsJd3JpdGVsKGNvbnRyb2wyLCBhZGMt
PmJhc2UgKyBTSVJGU09DX0FEQ19DT05UUk9MMik7DQo+ID4gKwltdXRleF91
bmxvY2soJmFkYy0+YWRjX2xvY2spOw0KPiA+ICsJcmV0dXJuIHJldDsNCj4g
PiArfQ0KPiA+ICsNCj4gPiArLyogU3RvcmUgcGFyYW1zIHRvIGNhbGlicmF0
ZSAqLw0KPiA+ICtzdHJ1Y3Qgc2lyZnNvY19hZGNfY2FsaV9kYXRhIHsNCj4g
PiArCXUzMiBkaWdpdGFsX29mZnNldDsNCj4gPiArCXUzMiBkaWdpdGFsX2Fn
YWluOw0KPiA+ICsJYm9vbCBpc19jYWxpYnJhdGlvbjsNCj4gPiArfTsNCj4g
PiArDQo+ID4gKy8qIE9mZnNldCBDYWxpYnJhdGlvbiBjYWxpYnJhdGVzIHRo
ZSBBREMgb2Zmc2V0IGVycm9yICovIHN0YXRpYyB1MzINCj4gPiArc2lyZnNv
Y19hZGNfb2Zmc2V0X2NhbGkoc3RydWN0IHNpcmZzb2NfYWRjX3JlcXVlc3Qg
KnJlcSkgew0KPiA+ICsJdTMyIGksIGRpZ2l0YWxfb2Zmc2V0ID0gMCwgY291
bnQgPSAwLCBzdW0gPSAwOw0KPiA+ICsJLyogVG8gc2V0IHRoZSByZWdpc3Rl
cnMgaW4gb3JkZXIgdG8gZ2V0IHRoZSBBREMgb2Zmc2V0ICovDQo+ID4gKwly
ZXEtPm1vZGUgPSBTSVJGU09DX0FEQ19TRUwoU0lSRlNPQ19BRENfR1JPVU5E
X1NFTCk7DQo+ID4gKwlyZXEtPmV4dGNtID0gU0lSRlNPQ19BRENfRVhUQ00o
MCk7DQo+ID4gKwlyZXEtPnNfZ2Fpbl9iaXRzID0gU0lSRlNPQ19BRENfU0dB
SU4oNyk7DQo+ID4gKwlyZXEtPmRlbGF5X2JpdHMgPSBTSVJGU09DX0FEQ19E
RUxfU0VUKDQpOw0KPiA+ICsNCj4gPiArCWZvciAoaSA9IDA7IGkgPCAxMDsg
aSsrKSB7DQo+ID4gKwkJaWYgKHNpcmZzb2NfYWRjX3NlbmRfcmVxdWVzdChy
ZXEpKQ0KPiA+ICsJCQlicmVhazsNCj4gPiArCQlkaWdpdGFsX29mZnNldCA9
IHJlcS0+cmVhZF9iYWNrX2RhdGE7DQo+ID4gKwkJc3VtICs9IGRpZ2l0YWxf
b2Zmc2V0Ow0KPiA+ICsJCWNvdW50Kys7DQo+ID4gKwl9DQo+ID4gKwlpZiAo
IWNvdW50KQ0KPiA+ICsJCWRpZ2l0YWxfb2Zmc2V0ID0gMDsNCj4gPiArCWVs
c2UNCj4gPiArCQlkaWdpdGFsX29mZnNldCA9IHN1bSAvIGNvdW50Ow0KPiA+
ICsNCj4gPiArCXJldHVybiBkaWdpdGFsX29mZnNldDsNCj4gPiArfQ0KPiA+
ICsNCj4gPiArDQo+ID4gKy8qIEdhaW4gQ2FsaWJyYXRpb24gY2FsaWJyYXRl
cyB0aGUgQURDIGdhaW4gZXJyb3IgKi8gc3RhdGljIHUzMg0KPiA+ICtzaXJm
c29jX2FkY19nYWluX2NhbGkoc3RydWN0IHNpcmZzb2NfYWRjX3JlcXVlc3Qg
KnJlcSkgew0KPiA+ICsJdTMyIGksIGRpZ2l0YWxfZ2FpbiA9IDAsIGNvdW50
ID0gMCwgc3VtID0gMDsNCj4gPiArCS8qIFRvIHNldCB0aGUgcmVnaXN0ZXJz
IGluIG9yZGVyIHRvIGdldCB0aGUgQURDIGdhaW4gKi8NCj4gPiArCXJlcS0+
bW9kZSA9IFNJUkZTT0NfQURDX1NFTChTSVJGU09DX0FEQ19CQU5ER0FQX1NF
TCk7DQo+ID4gKwlyZXEtPmV4dGNtID0gU0lSRlNPQ19BRENfRVhUQ00oMCk7
DQo+ID4gKwlyZXEtPnNfZ2Fpbl9iaXRzID0gU0lSRlNPQ19BRENfU0dBSU4o
MSk7DQo+ID4gKwlyZXEtPmRlbGF5X2JpdHMgPSBTSVJGU09DX0FEQ19ERUxf
U0VUKDQpOw0KPiA+ICsNCj4gPiArCWZvciAoaSA9IDA7IGkgPCAxMDsgaSsr
KSB7DQo+ID4gKwkJaWYgKHNpcmZzb2NfYWRjX3NlbmRfcmVxdWVzdChyZXEp
KQ0KPiA+ICsJCQlicmVhazsNCj4gPiArCQlkaWdpdGFsX2dhaW4gPSByZXEt
PnJlYWRfYmFja19kYXRhOw0KPiA+ICsJCXN1bSArPSBkaWdpdGFsX2dhaW47
DQo+ID4gKwkJY291bnQrKzsNCj4gPiArCX0NCj4gPiArCWlmICghY291bnQp
DQo+ID4gKwkJZGlnaXRhbF9nYWluID0gMDsNCj4gPiArCWVsc2UNCj4gPiAr
CQlkaWdpdGFsX2dhaW4gPSBzdW0gLyBjb3VudDsNCj4gPiArDQo+ID4gKwly
ZXR1cm4gZGlnaXRhbF9nYWluOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICsvKiBB
YnNvbHV0ZSBnYWluIGNhbGlicmF0aW9uICovDQo+ID4gK3N0YXRpYyBpbnQg
c2lyZnNvY19hZGNfYWRjX2NhbGkoc3RydWN0IHNpcmZzb2NfYWRjX3JlcXVl
c3QgKnJlcSwNCj4gPiArCQkJCXN0cnVjdCBzaXJmc29jX2FkY19jYWxpX2Rh
dGEgKmNhbGlfZGF0YSkgew0KPiA+ICsJY2FsaV9kYXRhLT5kaWdpdGFsX29m
ZnNldCA9IHNpcmZzb2NfYWRjX29mZnNldF9jYWxpKHJlcSk7DQo+ID4gKwlp
ZiAoIWNhbGlfZGF0YS0+ZGlnaXRhbF9vZmZzZXQpDQo+ID4gKwkJcmV0dXJu
IC1FSU5WQUw7DQo+ID4gKwljYWxpX2RhdGEtPmRpZ2l0YWxfYWdhaW4gPSBz
aXJmc29jX2FkY19nYWluX2NhbGkocmVxKTsNCj4gPiArCWlmICghY2FsaV9k
YXRhLT5kaWdpdGFsX2FnYWluKQ0KPiA+ICsJCXJldHVybiAtRUlOVkFMOw0K
PiA+ICsNCj4gPiArCXJldHVybiAwOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICsv
KiBHZXQgdm9sdGFnZSBhZnRlciBBREMgY29udmVyc2lvbiAqLyBzdGF0aWMg
dTMyDQo+ID4gK3NpcmZzb2NfYWRjX2dldF9hZGNfdm9sdChzdHJ1Y3Qgc2ly
ZnNvY19hZGMgKmFkYywNCj4gPiArCQkJCXN0cnVjdCBzaXJmc29jX2FkY19j
YWxpX2RhdGEgKmNhbGlfZGF0YSkgew0KPiA+ICsJdTMyIGRpZ2l0YWxfb3V0
LCB2b2x0Ow0KPiA+ICsJc3RydWN0IHNpcmZzb2NfYWRjX3JlcXVlc3QgKnJl
cSA9ICZhZGMtPnJlcTsNCj4gPiArDQo+ID4gKwlyZXEtPnNfZ2Fpbl9iaXRz
ID0gU0lSRlNPQ19BRENfU0dBSU4oMCk7DQo+ID4gKwlyZXEtPmRlbGF5X2Jp
dHMgPSBTSVJGU09DX0FEQ19ERUxfU0VUKDQpOw0KPiA+ICsNCj4gPiArCS8q
DQo+ID4gKwkgKiBGaXJzdCByZWFkIG9yaWdpbmFsIGRhdGENCj4gPiArCSAq
IHRoZW4gcmVhZCBjYWxpYnJhdGUgZXJyb3JzDQo+ID4gKwkgKi8NCj4gPiAr
CXNpcmZzb2NfYWRjX3NlbmRfcmVxdWVzdChyZXEpOw0KPiA+ICsJaWYgKHJl
cS0+cmVhZF9iYWNrX2RhdGEpIHsNCj4gPiArCQlkaWdpdGFsX291dCA9IHJl
cS0+cmVhZF9iYWNrX2RhdGE7DQo+ID4gKwkJLyogR2V0IGVycm9ycyBmb3Ig
ZWFjaCBzYW1wbGUgKi8NCj4gPiArCQlpZiAoIWNhbGlfZGF0YS0+aXNfY2Fs
aWJyYXRpb24pIHsNCj4gPiArCQkJaWYgKHNpcmZzb2NfYWRjX2FkY19jYWxp
KHJlcSwgY2FsaV9kYXRhKSkNCj4gPiArCQkJCXJldHVybiAwOw0KPiA+ICsJ
CQljYWxpX2RhdGEtPmlzX2NhbGlicmF0aW9uID0gdHJ1ZTsNCj4gPiArCQl9
DQo+ID4gKw0KPiA+ICsJCXZvbHQgPSBhZGMtPmNoaXBfaW5mby0+Y2FsY3Vs
YXRlX3ZvbHQoZGlnaXRhbF9vdXQsDQo+ID4gKwkJCWNhbGlfZGF0YS0+ZGln
aXRhbF9vZmZzZXQsDQo+ID4gKwkJCWNhbGlfZGF0YS0+ZGlnaXRhbF9hZ2Fp
bik7DQo+ID4gKwl9IGVsc2Ugew0KPiA+ICsJCXJldHVybiAwOw0KPiA+ICsJ
fQ0KPiA+ICsNCj4gPiArCXJldHVybiB2b2x0Ow0KPiA+ICt9DQo+ID4gKw0K
PiA+ICtzdGF0aWMgdTMyIHByaW1hMl9hZGNfY2FsY3VsYXRlX3ZvbHQodTMy
IGRpZ2l0YWxfb3V0LA0KPiA+ICsJCQkJdTMyIGRpZ2l0YWxfb2Zmc2V0LCB1
MzIgZGlnaXRhbF9hZ2Fpbikgew0KPiA+ICsJdTMyIHZvbHQsIGRpZ2l0YWxf
aWRlYWwsIGRpZ2l0YWxfY29udmVydDsNCj4gPiArDQo+ID4gKwkvKg0KPiA+
ICsJICogc2VlIEVxdWF0aW9uIDMuMiBvZiBTaVJGUHJpbWFJSeKEoiBJbnRl
cm5hbCBBREMgYW5kIFRvdWNoDQo+ID4gKwkgKiBVc2VyIEd1aWRlDQo+ID4g
KwkgKi8NCj4gPiArCWRpZ2l0YWxfaWRlYWwgPSAoNTUyMiAqIDEyMDApIC8g
KDcgKiAzMzMpOw0KPiA+ICsJLyoNCj4gPiArCSAqIHNlZSBFcXVhdGlvbiAz
LjMgb2YgU2lSRmF0bGFzVknihKIgSW50ZXJuYWwgQURDIGFuZCBUb3VjaA0K
PiA+ICsJICovDQo+ID4gKwlkaWdpdGFsX2NvbnZlcnQgPSAoZGlnaXRhbF9v
dXQgLSAxMTY0NSAqIGRpZ2l0YWxfb2Zmc2V0IC8NCj4gPiArCQkxNDAwMDAp
ICogZGlnaXRhbF9pZGVhbCAvIChkaWdpdGFsX2FnYWluDQo+ID4gKwkJLSBk
aWdpdGFsX29mZnNldCAqIDExNjQ1IC8gNzAwMDApOw0KPiA+ICsJdm9sdCA9
IDE0ICogMzMzICogZGlnaXRhbF9jb252ZXJ0IC8gNTUyMjsNCj4gPiArDQo+
ID4gKwlyZXR1cm4gdm9sdDsNCj4gPiArfQ0KPiA+ICsNCj4gPiArc3RhdGlj
IHUzMiBhdGxhczZfYWRjX2NhbGN1bGF0ZV92b2x0KHUzMiBkaWdpdGFsX291
dCwNCj4gPiArCQkJCXUzMiBkaWdpdGFsX29mZnNldCwgdTMyIGRpZ2l0YWxf
YWdhaW4pIHsNCj4gPiArCXUzMiB2b2x0LCBkaWdpdGFsX2lkZWFsLCBkaWdp
dGFsX2NvbnZlcnQ7DQo+ID4gKw0KPiA+ICsJLyoNCj4gPiArCSAqIHNlZSBF
cXVhdGlvbiAzLjIgb2YgU2lSRmF0bGFzVknihKIgSW50ZXJuYWwgQURDIGFu
ZCBUb3VjaA0KPiA+ICsJICogVXNlciBHdWlkZQ0KPiA+ICsJICovDQo+ID4g
KwlkaWdpdGFsX2lkZWFsID0gKDM5ODYgKiAxMjEwMCkgLyAoNyAqIDMzMzMp
Ow0KPiA+ICsJLyoNCj4gPiArCSAqIHNlZSBFcXVhdGlvbiAzLjMgb2YgU2lS
RmF0bGFzVknihKIgSW50ZXJuYWwgQURDIGFuZCBUb3VjaA0KPiA+ICsJICov
DQo+ID4gKwlkaWdpdGFsX29mZnNldCAmPSAweGZmZjsNCj4gPiArCWRpZ2l0
YWxfY29udmVydCA9IGFicyhkaWdpdGFsX291dCAtIDIgKiBkaWdpdGFsX29m
ZnNldCkNCj4gPiArCQkqIGRpZ2l0YWxfaWRlYWwgLyAoZGlnaXRhbF9hZ2Fp
bg0KPiA+ICsJCS0gZGlnaXRhbF9vZmZzZXQgKiAyKTsNCj4gPiArCXZvbHQg
PSAxNCAqIDMzMyAqIGRpZ2l0YWxfY29udmVydCAvIDM5ODY7DQo+ID4gKwl2
b2x0ID0gdm9sdCAvIDI7DQo+ID4gKwlpZiAodm9sdCA+IDE1MDApDQo+ID4g
KwkJdm9sdCA9IHZvbHQgLSAodm9sdCAtIDE1MDApIC8gMTU7DQo+ID4gKwll
bHNlDQo+ID4gKwkJdm9sdCA9IHZvbHQgKyAoMTUwMCAtIHZvbHQpIC8gMjg7
DQo+ID4gKw0KPiA+ICsJcmV0dXJuIHZvbHQ7DQo+ID4gK30NCj4gPiArDQo+
ID4gK3N0YXRpYyBpcnFyZXR1cm5fdCBzaXJmc29jX2FkY19kYXRhX2lycShp
bnQgaXJxLCB2b2lkICpoYW5kbGUpIHsNCj4gPiArCXN0cnVjdCBpaW9fZGV2
ICppbmRpb19kZXYgPSBoYW5kbGU7DQo+ID4gKwlzdHJ1Y3Qgc2lyZnNvY19h
ZGMgKmFkYyA9IGlpb19wcml2KGluZGlvX2Rldik7DQo+ID4gKwlpbnQgdmFs
Ow0KPiA+ICsNCj4gPiArCXZhbCA9IHJlYWRsKGFkYy0+YmFzZSArIFNJUkZT
T0NfQURDX0lOVFIpOw0KPiA+ICsNCj4gPiArCXdyaXRlbChTSVJGU09DX0FE
Q19QRU5fSU5UUiB8IFNJUkZTT0NfQURDX1BFTl9JTlRSX0VOIHwNCj4gPiAr
CQlTSVJGU09DX0FEQ19EQVRBX0lOVFIgfCBTSVJGU09DX0FEQ19EQVRBX0lO
VFJfRU4sDQo+ID4gKwkJYWRjLT5iYXNlICsgU0lSRlNPQ19BRENfSU5UUik7
DQo+ID4gKw0KPiA+ICsJaWYgKHZhbCAmIFNJUkZTT0NfQURDX0RBVEFfSU5U
UikNCj4gPiArCQljb21wbGV0ZSgmYWRjLT5kb25lKTsNCj4gPiArDQo+ID4g
KwlyZXR1cm4gSVJRX0hBTkRMRUQ7DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0
YXRpYyBpbnQgc2lyZnNvY19hZGNfcmVhZF9yYXcoc3RydWN0IGlpb19kZXYg
KmluZGlvX2RldiwNCj4gPiArCQkJCXN0cnVjdCBpaW9fY2hhbl9zcGVjIGNv
bnN0ICpjaGFuLA0KPiA+ICsJCQkJaW50ICp2YWwsDQo+ID4gKwkJCQlpbnQg
KnZhbDIsDQo+ID4gKwkJCQlsb25nIG1hc2spDQo+ID4gK3sNCj4gPiArCXN0
cnVjdCBzaXJmc29jX2FkYyAqYWRjID0gaWlvX3ByaXYoaW5kaW9fZGV2KTsN
Cj4gPiArCXN0cnVjdCBzaXJmc29jX2FkY19jYWxpX2RhdGEgY2FsaV9kYXRh
Ow0KPiA+ICsJaW50IHJldDsNCj4gPiArDQo+ID4gKwljYWxpX2RhdGEuaXNf
Y2FsaWJyYXRpb24gPSBmYWxzZTsNCj4gPiArCXN3aXRjaCAobWFzaykgew0K
PiA+ICsJY2FzZSBJSU9fQ0hBTl9JTkZPX1JBVzoNCj4gPiArCQlpZiAoMCA9
PSBjaGFuLT5jaGFubmVsKQ0KPiA+ICsJCQlyZXQgPSBzaXJmc29jX2FkY19z
aW5nbGVfdHNfc2FtcGxlKGFkYywgdmFsKTsNCj4gPiArCQllbHNlDQo+ID4g
KwkJCXJldCA9IHNpcmZzb2NfYWRjX2R1YWxfdHNfc2FtcGxlKGFkYywgdmFs
KTsNCj4gPiArDQo+ID4gKwkJaWYgKHJldCkNCj4gPiArCQkJcmV0dXJuIHJl
dDsNCj4gPiArCQlyZXR1cm4gSUlPX1ZBTF9JTlQ7DQo+IFRoaXMgd2lsbCBy
ZXN1bHQgaW4gdGhlIGZpcnN0IHZhbHVlIG9ubHkgYmVpbmcgb3V0cHV0LiAg
TW9yZSB0byB0aGUgcG9pbnQgKnZhbA0KPiBvbmx5IHBvaW50cyB0byBhIHNp
bmdsZSBpbnRlZ2VyIHNvIGNoYW5jZXMgYXJlIHlvdSdsbCBjcmFzaCB0aGUg
a2VybmVsLiBJIGRvbid0DQo+IHRoaW5rIGl0IHdvdWxkIGJlIGFwcHJvcHJp
YXRlIHRvIHVzZSBvdXIgbW9yZSByZWNlbnQgc3VwcG9ydCBmb3IgbXVsdGlw
bGUNCj4gZWxlbWVudCBvdXRwdXRzLiAgVGhlIHR3byBheGVzIGFyZSBpbmRl
cGVuZGVudCBhZnRlciBhbGwuICBJJ2QgcmVhbGx5IGJlDQo+IGhhcHBpZXIg
c2VlaW5nIHRoaXMgZG9uZSB2aWEgdGhlIGlucHV0IHN1YnN5c3RlbS4NCj4g
KG5vdGUgdGhhdCB3b3VsZCByZXF1aXJlIHRoZXNlIGNoYW5uZWxzIG5vdCB0
byBiZSBwb2xsZWQgYXMgZG9uZSBoZXJlLCBidXQNCj4gZHJpdmVuIGJ5IGlu
dGVycnVwdCBvciBwZXJoYXBzIHRpbWVyKS4NCj4gDQo+ID4gKwljYXNlIElJ
T19DSEFOX0lORk9fUFJPQ0VTU0VEOg0KPiA+ICsJCWFkYy0+cmVxLm1vZGUg
PSBTSVJGU09DX0FEQ19TRUwoDQo+ID4gKwkJCWFkYy0+Y2hpcF9pbmZvLT5j
aGFubmVsX3NlbFtjaGFuLT5jaGFubmVsXSk7DQo+ID4gKwkJYWRjLT5yZXEu
ZXh0Y20gPSBTSVJGU09DX0FEQ19FWFRDTSgwKTsNCj4gPiArCQkqdmFsID0g
c2lyZnNvY19hZGNfZ2V0X2FkY192b2x0KGFkYywgJmNhbGlfZGF0YSk7DQo+
ID4gKwkJcmV0dXJuIElJT19WQUxfSU5UOw0KPiA+ICsJZGVmYXVsdDoNCj4g
PiArCQlyZXR1cm4gLUVJTlZBTDsNCj4gPiArCX0NCj4gPiArDQo+ID4gKwly
ZXR1cm4gMDsNCj4gPiArfQ0KPiA+ICsNCj4gPiArI2lmZGVmIENPTkZJR19Q
TV9TTEVFUA0KPiA+ICtzdGF0aWMgaW50IHNpcmZzb2NfYWRjX3N1c3BlbmQo
c3RydWN0IGRldmljZSAqZGV2KSB7DQo+ID4gKwlzdHJ1Y3QgaWlvX2RldiAq
aW5kaW9fZGV2ID0gZGV2X2dldF9kcnZkYXRhKGRldik7DQo+ID4gKwlzdHJ1
Y3Qgc2lyZnNvY19hZGMgKmFkYyA9IGlpb19wcml2KGluZGlvX2Rldik7DQo+
ID4gKw0KPiA+ICsJc2lyZnNvY19ydGNfaW9icmdfd3JpdGVsKHNpcmZzb2Nf
cnRjX2lvYnJnX3JlYWRsKA0KPiA+ICsJCVNJUkZTT0NfUFdSQ19CQVNFICsg
U0lSRlNPQ19QV1JDX1RSSUdHRVJfRU4pDQo+ID4gKwkJJiB+QklUKFNJUkZT
T0NfUFdSX1dBS0VFTl9UU0NfU0hJRlQpLA0KPiA+ICsJCVNJUkZTT0NfUFdS
Q19CQVNFICsgU0lSRlNPQ19QV1JDX1RSSUdHRVJfRU4pOw0KPiA+ICsNCj4g
PiArCWNsa19kaXNhYmxlX3VucHJlcGFyZShhZGMtPmNsayk7DQo+ID4gKw0K
PiA+ICsJcmV0dXJuIDA7DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyBp
bnQgc2lyZnNvY19hZGNfcmVzdW1lKHN0cnVjdCBkZXZpY2UgKmRldikgew0K
PiA+ICsJc3RydWN0IGlpb19kZXYgKmluZGlvX2RldiA9IGRldl9nZXRfZHJ2
ZGF0YShkZXYpOw0KPiA+ICsJc3RydWN0IHNpcmZzb2NfYWRjICphZGMgPSBp
aW9fcHJpdihpbmRpb19kZXYpOw0KPiA+ICsJaW50IHJldDsNCj4gPiArCWlu
dCB2YWw7DQo+ID4gKw0KPiA+ICsJY2xrX3ByZXBhcmVfZW5hYmxlKGFkYy0+
Y2xrKTsNCj4gPiArDQo+ID4gKwlzaXJmc29jX3J0Y19pb2JyZ193cml0ZWwo
c2lyZnNvY19ydGNfaW9icmdfcmVhZGwoDQo+ID4gKwkJU0lSRlNPQ19QV1JD
X0JBU0UgKyBTSVJGU09DX1BXUkNfVFJJR0dFUl9FTikgfA0KPiA+ICsJCUJJ
VChTSVJGU09DX1BXUl9XQUtFRU5fVFNfU0hJRlQpLA0KPiA+ICsJCVNJUkZT
T0NfUFdSQ19CQVNFICsgU0lSRlNPQ19QV1JDX1RSSUdHRVJfRU4pOw0KPiA+
ICsNCj4gPiArCXJldCA9IGRldmljZV9yZXNldChkZXYpOw0KPiA+ICsJaWYg
KHJldCkgew0KPiA+ICsJCWRldl9lcnIoZGV2LCAiRmFpbGVkIHRvIHJlc2V0
XG4iKTsNCj4gPiArCQlyZXR1cm4gcmV0Ow0KPiA+ICsJfQ0KPiA+ICsNCj4g
PiArCXdyaXRlbChTSVJGU09DX0FEQ19QUlBfTU9ERTMgfCBTSVJGU09DX0FE
Q19SVE9VQ0goMSkgfA0KPiA+ICsJCVNJUkZTT0NfQURDX0RFTF9QUkUoMikg
fCBTSVJGU09DX0FEQ19ERUxfRElTKDUpLA0KPiA+ICsJCWFkYy0+YmFzZSAr
IFNJUkZTT0NfQURDX0NPTlRST0wyKTsNCj4gPiArDQo+ID4gKwl2YWwgPSBy
ZWFkbChhZGMtPmJhc2UgKyBTSVJGU09DX0FEQ19JTlRSKTsNCj4gPiArDQo+
ID4gKwkvKiBDbGVhciBpbnRlcnJ1cHRzIGFuZCBlbmFibGUgUEVOIGludGVy
cnVwdCAqLw0KPiA+ICsJd3JpdGVsKHZhbCB8IFNJUkZTT0NfQURDX1BFTl9J
TlRSIHwgU0lSRlNPQ19BRENfREFUQV9JTlRSIHwNCj4gPiArCQlTSVJGU09D
X0FEQ19QRU5fSU5UUl9FTiB8DQo+IFNJUkZTT0NfQURDX0RBVEFfSU5UUl9F
TiwNCj4gPiArCQlhZGMtPmJhc2UgKyBTSVJGU09DX0FEQ19JTlRSKTsNCj4g
PiArDQo+ID4gKwlyZXR1cm4gMDsNCj4gPiArfQ0KPiA+ICsjZW5kaWYNCj4g
PiArDQo+ID4gK3N0YXRpYyBjb25zdCBzdHJ1Y3QgZGV2X3BtX29wcyBzaXJm
c29jX2FkY19wbV9vcHMgPSB7DQo+ID4gKwlTRVRfU1lTVEVNX1NMRUVQX1BN
X09QUyhzaXJmc29jX2FkY19zdXNwZW5kLA0KPiBzaXJmc29jX2FkY19yZXN1
bWUpIH07DQo+ID4gKw0KPiA+ICsjZGVmaW5lIFNJUkZTT0NfQURDX0NIQU5O
RUwoX2NoYW5uZWwsIF90eXBlLCBfbmFtZSwgX21hc2spIHsJXA0KPiA+ICsJ
LnR5cGUgPSBfdHlwZSwJCQkJCVwNCj4gPiArCS5pbmRleGVkID0gMSwJCQkJ
CVwNCj4gPiArCS5jaGFubmVsID0gX2NoYW5uZWwsCQkJCVwNCj4gPiArCS5k
YXRhc2hlZXRfbmFtZSA9IF9uYW1lLAkJCVwNCj4gPiArCS5pbmZvX21hc2tf
c2VwYXJhdGUgPSBCSVQoX21hc2spLAkJXA0KPiA+ICt9DQo+ID4gKw0KPiA+
ICsjZGVmaW5lIFNJUkZTT0NfQURDX1RTX0NIQU5ORUwoX2NoYW5uZWwsIF9u
YW1lKQkJXA0KPiA+ICsJU0lSRlNPQ19BRENfQ0hBTk5FTChfY2hhbm5lbCwg
SUlPX1ZPTFRBR0UsCVwNCj4gPiArCV9uYW1lLCBJSU9fQ0hBTl9JTkZPX1JB
VykNCj4gPiArDQo+ID4gKyNkZWZpbmUgU0lSRlNPQ19BRENfQVVYX0NIQU5O
RUwoX2NoYW5uZWwsIF9uYW1lKQlcDQo+ID4gKwlTSVJGU09DX0FEQ19DSEFO
TkVMKF9jaGFubmVsLCBJSU9fVk9MVEFHRSwJXA0KPiA+ICsJX25hbWUsIElJ
T19DSEFOX0lORk9fUFJPQ0VTU0VEKQ0KPiA+ICsNCj4gPiArc3RhdGljIGNv
bnN0IHN0cnVjdCBpaW9fY2hhbl9zcGVjIHByaW1hMl9hZGNfaWlvX2NoYW5u
ZWxzW10gPSB7DQo+ID4gKwkvKiBDaGFubmVscyB0byBnZXQgdGhlIHRvdWNo
IGRhdGEgKi8NCj4gPiArCVNJUkZTT0NfQURDX1RTX0NIQU5ORUwoMCwgInRv
dWNoX2Nvb3JkIiksDQo+IFBhc3NpbmcgYSBwYWlyIG9mIGNvb3JkaW5hdGVz
IHRocm91Z2ggYSBzaW5nbGUgY2hhbm5lbCBkb2Vzbid0IHJlYWxseSBtYWtl
DQo+IHNlbnNlLiBJJ2QgYmUgaW5jbGluZWQgdG8gc2F5IHlvdSB3YW50IGEg
YmFzaWMgaW5wdXQgZHJpdmVyIGluIGhlcmUgYXMgd2VsbCB0bw0KPiBoYW5k
bGUgdGhlc2UgY2hhbm5lbHMgYXBwcm9wcmlhdGVseS4NCj4gU2VlIHRoZSBh
dDkxX2FkYyBkcml2ZXIgZm9yIGV4YW1wbGUuDQo+IA0KPiA+ICsJLyogQ2hh
bm5lbHMgdG8gZ2V0IHRoZSBwaW4gaW5wdXQgKi8NCj4gPiArCVNJUkZTT0Nf
QURDX0FVWF9DSEFOTkVMKDEsICJhdXhpbGlhcnkxIiksDQo+ID4gKwlTSVJG
U09DX0FEQ19BVVhfQ0hBTk5FTCgyLCAiYXV4aWxpYXJ5MiIpLA0KPiA+ICsJ
U0lSRlNPQ19BRENfQVVYX0NIQU5ORUwoMywgImF1eGlsaWFyeTMiKSwNCj4g
PiArCVNJUkZTT0NfQURDX0FVWF9DSEFOTkVMKDQsICJhdXhpbGlhcnk0Iiks
DQo+ID4gKwlTSVJGU09DX0FEQ19BVVhfQ0hBTk5FTCg1LCAiYXV4aWxpYXJ5
NSIpLA0KPiA+ICsJU0lSRlNPQ19BRENfQVVYX0NIQU5ORUwoNiwgImF1eGls
aWFyeTYiKSwgfTsNCj4gPiArDQo+ID4gK3N0YXRpYyBjb25zdCB1MzIgcHJp
bWEyX2FkY19jaGFubmVsX3NlbFtdID0gew0KPiA+ICsJMCwgU0lSRlNPQ19B
RENfQVVYMV9TRUwsIFNJUkZTT0NfQURDX0FVWDJfU0VMLA0KPiA+ICsJU0lS
RlNPQ19BRENfQVVYM19TRUwsIFNJUkZTT0NfQURDX0FVWDRfU0VMLA0KPiA+
ICsJU0lSRlNPQ19BRENfQVVYNV9TRUwsIFNJUkZTT0NfQURDX0FVWDZfU0VM
IH07DQo+ID4gKw0KPiA+ICtzdGF0aWMgY29uc3Qgc3RydWN0IGlpb19jaGFu
X3NwZWMgYXRsYXM2X2FkY19paW9fY2hhbm5lbHNbXSA9IHsNCj4gPiArCS8q
IENoYW5uZWxzIHRvIGdldCB0aGUgdG91Y2ggZGF0YSAqLw0KPiA+ICsJU0lS
RlNPQ19BRENfVFNfQ0hBTk5FTCgwLCAidG91Y2hfY29vcmQiKSwNCj4gPiAr
CVNJUkZTT0NfQURDX1RTX0NIQU5ORUwoMSwgImR1YWxfdG91Y2hfY29vcmQi
KSwNCj4gPiArCS8qIENoYW5uZWxzIHRvIGdldCB0aGUgcGluIGlucHV0ICov
DQo+ID4gKwlTSVJGU09DX0FEQ19BVVhfQ0hBTk5FTCgyLCAiYXV4aWxpYXJ5
MSIpLA0KPiA+ICsJLyogQXRsYXM2IGhhcyBubyBhdXhpbGlhcnkyIGFuZCBh
dXhpbGlhcnkzICovDQo+ID4gKwlTSVJGU09DX0FEQ19BVVhfQ0hBTk5FTCgz
LCAiYXV4aWxpYXJ5NCIpLA0KPiA+ICsJU0lSRlNPQ19BRENfQVVYX0NIQU5O
RUwoNCwgImF1eGlsaWFyeTUiKSwNCj4gPiArCVNJUkZTT0NfQURDX0FVWF9D
SEFOTkVMKDUsICJhdXhpbGlhcnk2IiksIH07DQo+ID4gKw0KPiA+ICtzdGF0
aWMgY29uc3QgdTMyIGF0bGFzNl9hZGNfY2hhbm5lbF9zZWxbXSA9IHsNCj4g
PiArCTAsIDAsIFNJUkZTT0NfQURDX0FVWDFfU0VMLCBTSVJGU09DX0FEQ19B
VVg0X1NFTCwNCj4gPiArCVNJUkZTT0NfQURDX0FVWDVfU0VMLCBTSVJGU09D
X0FEQ19BVVg2X1NFTCB9Ow0KPiA+ICsNCj4gPiArc3RhdGljIGNvbnN0IHN0
cnVjdCBpaW9faW5mbyBzaXJmc29jX2FkY19pbmZvID0gew0KPiA+ICsJLnJl
YWRfcmF3ID0gJnNpcmZzb2NfYWRjX3JlYWRfcmF3LA0KPiA+ICsJLmRyaXZl
cl9tb2R1bGUgPSBUSElTX01PRFVMRSwNCj4gPiArfTsNCj4gPiArDQo+ID4g
K3N0YXRpYyBjb25zdCBzdHJ1Y3Qgc2lyZnNvY19hZGNfY2hpcF9pbmZvIHNp
cmZzb2NfYWRjX2NoaXBfaW5mb190YmxbXSA9IHsNCj4gPiArCVtQUklNQTJd
ID0gew0KPiA+ICsJCS5jaGFubmVscyA9IHByaW1hMl9hZGNfaWlvX2NoYW5u
ZWxzLA0KPiA+ICsJCS5udW1fY2hhbm5lbHMgPSBBUlJBWV9TSVpFKHByaW1h
Ml9hZGNfaWlvX2NoYW5uZWxzKSwNCj4gPiArCQkuaWlvX2luZm8gPSAmc2ly
ZnNvY19hZGNfaW5mbywNCj4gPiArCQkuY2FsY3VsYXRlX3ZvbHQgPSBwcmlt
YTJfYWRjX2NhbGN1bGF0ZV92b2x0LA0KPiA+ICsJCS5jaGFubmVsX3NlbCA9
IHByaW1hMl9hZGNfY2hhbm5lbF9zZWwsDQo+ID4gKwl9LA0KPiA+ICsJW0FU
TEFTNl0gPSB7DQo+ID4gKwkJLmNoYW5uZWxzID0gYXRsYXM2X2FkY19paW9f
Y2hhbm5lbHMsDQo+ID4gKwkJLm51bV9jaGFubmVscyA9IEFSUkFZX1NJWkUo
YXRsYXM2X2FkY19paW9fY2hhbm5lbHMpLA0KPiA+ICsJCS5paW9faW5mbyA9
ICZzaXJmc29jX2FkY19pbmZvLA0KPiA+ICsJCS5jYWxjdWxhdGVfdm9sdCA9
IGF0bGFzNl9hZGNfY2FsY3VsYXRlX3ZvbHQsDQo+ID4gKwkJLmNoYW5uZWxf
c2VsID0gYXRsYXM2X2FkY19jaGFubmVsX3NlbCwNCj4gPiArCX0sDQo+ID4g
K307DQo+ID4gKw0KPiA+ICtzdGF0aWMgY29uc3Qgc3RydWN0IG9mX2Rldmlj
ZV9pZCBzaXJmc29jX2FkY19vZl9tYXRjaFtdID0gew0KPiA+ICsJeyAuY29t
cGF0aWJsZSA9ICJzaXJmLHByaW1hMi1hZGMiLA0KPiA+ICsJICAuZGF0YSA9
ICZzaXJmc29jX2FkY19jaGlwX2luZm9fdGJsW1BSSU1BMl0gfSwNCj4gPiAr
CXsgLmNvbXBhdGlibGUgPSAic2lyZixhdGxhczYtYWRjIiwNCj4gPiArCSAg
LmRhdGEgPSAmc2lyZnNvY19hZGNfY2hpcF9pbmZvX3RibFtBVExBUzZdIH0s
DQo+ID4gKwl7fQ0KPiA+ICt9Ow0KPiA+ICtNT0RVTEVfREVWSUNFX1RBQkxF
KG9mLCBzaXJmc29jX2FkY19vZl9tYXRjaCk7DQo+ID4gKw0KPiA+ICtzdGF0
aWMgaW50IHNpcmZzb2NfYWRjX3Byb2JlKHN0cnVjdCBwbGF0Zm9ybV9kZXZp
Y2UgKnBkZXYpIHsNCj4gPiArCXN0cnVjdCByZXNvdXJjZQkqbWVtX3JlczsN
Cj4gPiArCXN0cnVjdCBzaXJmc29jX2FkYyAqYWRjOw0KPiA+ICsJc3RydWN0
IGlpb19kZXYgKmluZGlvX2RldjsNCj4gPiArCWNvbnN0IHN0cnVjdCBvZl9k
ZXZpY2VfaWQgKm1hdGNoOw0KPiA+ICsJaW50IGlycTsNCj4gPiArCWludCBy
ZXQ7DQo+ID4gKw0KPiA+ICsJaW5kaW9fZGV2ID0gZGV2bV9paW9fZGV2aWNl
X2FsbG9jKCZwZGV2LT5kZXYsDQo+ID4gKwkJCXNpemVvZihzdHJ1Y3Qgc2ly
ZnNvY19hZGMpKTsNCj4gc2l6ZW9mKCphZGMpKTsgU2hvcnRlciBhbmQgc2xp
Z2h0bHkgbW9yZSBvYnZpb3VzbHkgY29ycmVjdCBnaXZlbiB0aGF0J3Mgd2hh
dA0KPiB5b3Ugc2VudCB0byBpaW9fcHJpdihpbmRpb19kZXYpOw0KPiA+ICsJ
aWYgKCFpbmRpb19kZXYpDQo+ID4gKwkJcmV0dXJuIC1FTk9NRU07DQo+ID4g
Kw0KPiA+ICsJYWRjID0gaWlvX3ByaXYoaW5kaW9fZGV2KTsNCj4gPiArDQo+
ID4gKwkvKiBBREMgc3BlY2lmaWMgZGF0YSAqLw0KPiA+ICsJbWF0Y2ggPSBv
Zl9tYXRjaF9kZXZpY2UoDQo+ID4gKwkJb2ZfbWF0Y2hfcHRyKHNpcmZzb2Nf
YWRjX29mX21hdGNoKSwgJnBkZXYtPmRldik7DQo+ID4gKwlhZGMtPmNoaXBf
aW5mbyA9IG1hdGNoLT5kYXRhOw0KPiA+ICsNCj4gPiArCWluZGlvX2Rldi0+
aW5mbyA9IGFkYy0+Y2hpcF9pbmZvLT5paW9faW5mbzsNCj4gPiArCWluZGlv
X2Rldi0+Y2hhbm5lbHMgPSBhZGMtPmNoaXBfaW5mby0+Y2hhbm5lbHM7DQo+
ID4gKwlpbmRpb19kZXYtPm51bV9jaGFubmVscyA9IGFkYy0+Y2hpcF9pbmZv
LT5udW1fY2hhbm5lbHM7DQo+ID4gKwlpbmRpb19kZXYtPm5hbWUgPSAic2ly
ZnNvYyBhZGMiOw0KPiA+ICsJaW5kaW9fZGV2LT5kZXYucGFyZW50ID0gJnBk
ZXYtPmRldjsNCj4gPiArCWluZGlvX2Rldi0+bW9kZXMgPSBJTkRJT19ESVJF
Q1RfTU9ERTsNCj4gPiArDQo+ID4gKwlwbGF0Zm9ybV9zZXRfZHJ2ZGF0YShw
ZGV2LCBpbmRpb19kZXYpOw0KPiA+ICsNCj4gPiArCWFkYy0+Y2xrID0gZGV2
bV9jbGtfZ2V0KCZwZGV2LT5kZXYsIE5VTEwpOw0KPiA+ICsJaWYgKElTX0VS
UihhZGMtPmNsaykpIHsNCj4gPiArCQlkZXZfZXJyKCZwZGV2LT5kZXYsICJH
ZXQgYWRjIGNsayBmYWlsZWRcbiIpOw0KPiA+ICsJCXJldCA9IC1FTk9NRU07
DQo+ID4gKwkJZ290byBlcnI7DQo+ID4gKwl9DQo+ID4gKwljbGtfcHJlcGFy
ZV9lbmFibGUoYWRjLT5jbGspOw0KPiBJcyBpdCBqdXN0IG1lIHdobyBmZWVs
cyB0aGF0IGEgZGV2bV9jbGtfcHJlcGFyZV9lbmFibGUgd291bGQgYmUgbmlj
ZSwgb3IgZm9yDQo+IHJlYWxseSBzaG9ydCBjb2RlIDogZGV2bV9jbGtfZ2V0
X3ByZXBhcmVfZW5hYmxlIDopIEFsc28sIGNsa19wcmVwYXJlX2VuYWJsZQ0K
PiBjYW4gcmV0dXJuIGVycm9ycyBzbyBzaG91bGQgYmUgY2hlY2tlZC4NCj4g
PiArDQo+ID4gKwltZW1fcmVzID0gcGxhdGZvcm1fZ2V0X3Jlc291cmNlKHBk
ZXYsIElPUkVTT1VSQ0VfTUVNLCAwKTsNCj4gPiArCWlmICghbWVtX3Jlcykg
ew0KPiA+ICsJCWRldl9lcnIoJnBkZXYtPmRldiwgIlVuYWJsZSB0byBnZXQg
aW8gcmVzb3VyY2VcbiIpOw0KPiA+ICsJCXJldCA9IC1FTk9ERVY7DQo+ID4g
KwkJZ290byBlcnI7DQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJYWRjLT5iYXNl
ID0gZGV2bV9yZXF1ZXN0X2FuZF9pb3JlbWFwKCZwZGV2LT5kZXYsIG1lbV9y
ZXMpOw0KPiBRdW90aW5nIGZyb20gYSByZXZpZXcgTGFycyBkaWQgZWFybGll
ciB0b2RheToNCj4gDQo+IGRldm1fcmVxdWVzdF9hbmRfaW9yZW1hcCgpIGlz
IGRlcHJlY2F0ZWQgYW4gd2lsbCBiZSByZW1vdmVkIGluIHRoZSBuZXh0DQo+
IHJlbGVhc2VbMV0uIFVzZSBkZXZtX2lvcmVtYXBfcmVzb3VyY2UoKSwgbm90
ZSB0aGF0DQo+IGRldm1faW9yZW1hcF9yZXNvdXJjZSgpIHJldHVybnMgYSBF
UlJfUFRSIGluc3RlYWQgb2YgTlVMTCBvbiBlcnJvci4NCj4gDQo+IFsxXSBo
dHRwczovL2xrbWwub3JnL2xrbWwvMjAxNC82LzExLzI2DQo+IA0KPiA+ICsJ
aWYgKCFhZGMtPmJhc2UpIHsNCj4gPiArCQlkZXZfZXJyKCZwZGV2LT5kZXYs
ICJJTyByZW1hcCBmYWlsZWQhXG4iKTsNCj4gPiArCQlyZXQgPSAtRU5PTUVN
Ow0KPiA+ICsJCWdvdG8gZXJyOw0KPiA+ICsJfQ0KPiA+ICsNCj4gPiArCWlu
aXRfY29tcGxldGlvbigmYWRjLT5kb25lKTsNCj4gPiArCW11dGV4X2luaXQo
JmFkYy0+YWRjX2xvY2spOw0KPiA+ICsNCj4gPiArDQo+IAlzaXJmc29jX3J0
Y19pb2JyZ193cml0ZWwoc2lyZnNvY19ydGNfaW9icmdfcmVhZGwoU0lSRlNP
Q19QV1JDX0JBDQo+IFNFICsNCj4gPiArCQlTSVJGU09DX1BXUkNfVFJJR0dF
Ul9FTikgfA0KPiBCSVQoU0lSRlNPQ19QV1JfV0FLRUVOX1RTX1NISUZUKSwN
Cj4gPiArCQlTSVJGU09DX1BXUkNfQkFTRSArIFNJUkZTT0NfUFdSQ19UUklH
R0VSX0VOKTsNCj4gPiArDQo+ID4gKwlyZXQgPSBkZXZpY2VfcmVzZXQoJnBk
ZXYtPmRldik7DQo+ID4gKwlpZiAocmV0KSB7DQo+ID4gKwkJZGV2X2Vycigm
cGRldi0+ZGV2LCAiRmFpbGVkIHRvIHJlc2V0XG4iKTsNCj4gPiArCQlnb3Rv
IGVycjsNCj4gPiArCX0NCj4gPiArDQo+ID4gKwl3cml0ZWwoU0lSRlNPQ19B
RENfUFJQX01PREUzIHwgU0lSRlNPQ19BRENfUlRPVUNIKDEpIHwNCj4gPiAr
CQlTSVJGU09DX0FEQ19ERUxfUFJFKDIpIHwgU0lSRlNPQ19BRENfREVMX0RJ
Uyg1KSwNCj4gPiArCQlhZGMtPmJhc2UgKyBTSVJGU09DX0FEQ19DT05UUk9M
Mik7DQo+ID4gKw0KPiA+ICsJLyogQ2xlYXIgaW50ZXJydXB0cyBhbmQgZW5h
YmxlIFBFTiBJTlRSICovDQo+ID4gKwl3cml0ZWwocmVhZGwoYWRjLT5iYXNl
ICsgU0lSRlNPQ19BRENfSU5UUikgfA0KPiBTSVJGU09DX0FEQ19QRU5fSU5U
UiB8DQo+ID4gKwkJU0lSRlNPQ19BRENfREFUQV9JTlRSIHwgU0lSRlNPQ19B
RENfUEVOX0lOVFJfRU4gfA0KPiA+ICsJCVNJUkZTT0NfQURDX0RBVEFfSU5U
Ul9FTiwgIGFkYy0+YmFzZSArDQo+IFNJUkZTT0NfQURDX0lOVFIpOw0KPiA+
ICsNCj4gZG91YmxlIHNwYWNlIGFib3ZlLg0KPiANCj4gPiArCWlycSA9IHBs
YXRmb3JtX2dldF9pcnEocGRldiwgMCk7DQo+ID4gKwlpZiAoaXJxIDwgMCkg
ew0KPiA+ICsJCWRldl9lcnIoJnBkZXYtPmRldiwgIkZhaWxlZCB0byBnZXQg
SVJRIVxuIik7DQo+ID4gKwkJcmV0ID0gLUVOT01FTTsNCj4gPiArCQlnb3Rv
IGVycjsNCj4gPiArCX0NCj4gPiArDQo+ID4gKwlyZXQgPSBkZXZtX3JlcXVl
c3RfaXJxKCZwZGV2LT5kZXYsIGlycSwgc2lyZnNvY19hZGNfZGF0YV9pcnEs
DQo+ID4gKwkJMCwgRFJJVkVSX05BTUUsIGluZGlvX2Rldik7DQo+ID4gKwlp
ZiAocmV0IDwgMCkgew0KPiA+ICsJCWRldl9lcnIoJnBkZXYtPmRldiwgIkZh
aWxlZCB0byByZWdpc3RlciBpcnEgaGFuZGxlclxuIik7DQo+ID4gKwkJcmV0
ID0gLUVOT0RFVjsNCj4gPiArCQlnb3RvIGVycjsNCj4gPiArCX0NCj4gPiAr
DQo+ID4gKwlyZXQgPSBvZl9wbGF0Zm9ybV9wb3B1bGF0ZShwZGV2LT5kZXYu
b2Zfbm9kZSwNCj4gc2lyZnNvY19hZGNfb2ZfbWF0Y2gsDQo+ID4gKwkJTlVM
TCwgJnBkZXYtPmRldik7DQo+ID4gKwlpZiAocmV0IDwgMCkgew0KPiA+ICsJ
CWRldl9lcnIoJnBkZXYtPmRldiwgIkZhaWxlZCB0byBhZGQgY2hpbGQgbm9k
ZXNcbiIpOw0KPiA+ICsJCWdvdG8gZXJyOw0KPiA+ICsJfQ0KPiA+ICsNCj4g
PiArCXJldCA9IGlpb19kZXZpY2VfcmVnaXN0ZXIoaW5kaW9fZGV2KTsNCj4g
PiArCWlmIChyZXQpIHsNCj4gPiArCQlkZXZfZXJyKCZwZGV2LT5kZXYsICJG
YWlsZWQgdG8gcmVnaXN0ZXIgYWRjIGlpbyBkZXZcbiIpOw0KPiBOaXRwaWNr
OiBBREMgSUlPDQo+ID4gKwkJZ290byBlcnI7DQo+ID4gKwl9DQo+ID4gKw0K
PiA+ICsJcmV0dXJuIDA7DQo+ID4gKw0KPiA+ICtlcnI6DQo+ID4gKwljbGtf
ZGlzYWJsZV91bnByZXBhcmUoYWRjLT5jbGspOw0KPiA+ICsNCj4gPiArCXJl
dHVybiByZXQ7DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyBpbnQgc2ly
ZnNvY19hZGNfcmVtb3ZlKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYp
IHsNCj4gPiArCXN0cnVjdCBpaW9fZGV2ICppbmRpb19kZXYgPSBwbGF0Zm9y
bV9nZXRfZHJ2ZGF0YShwZGV2KTsNCj4gPiArCXN0cnVjdCBzaXJmc29jX2Fk
YyAqYWRjID0gaWlvX3ByaXYoaW5kaW9fZGV2KTsNCj4gPiArDQo+ID4gKwlp
aW9fZGV2aWNlX3VucmVnaXN0ZXIoaW5kaW9fZGV2KTsNCj4gPiArCWNsa19k
aXNhYmxlX3VucHJlcGFyZShhZGMtPmNsayk7DQo+ID4gKw0KPiA+ICsJcmV0
dXJuIDA7DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyBzdHJ1Y3QgcGxh
dGZvcm1fZHJpdmVyIHNpcmZzb2NfYWRjX2RyaXZlciA9IHsNCj4gPiArCS5k
cml2ZXIgPSB7DQo+ID4gKwkJLm5hbWUJPSBEUklWRVJfTkFNRSwNCj4gPiAr
CQkub2ZfbWF0Y2hfdGFibGUgPSBzaXJmc29jX2FkY19vZl9tYXRjaCwNCj4g
PiArCQkucG0JPSAmc2lyZnNvY19hZGNfcG1fb3BzLA0KPiA+ICsJfSwNCj4g
PiArCS5wcm9iZQkJPSBzaXJmc29jX2FkY19wcm9iZSwNCj4gPiArCS5yZW1v
dmUJCT0gc2lyZnNvY19hZGNfcmVtb3ZlLA0KPiA+ICt9Ow0KPiA+ICsNCj4g
PiArbW9kdWxlX3BsYXRmb3JtX2RyaXZlcihzaXJmc29jX2FkY19kcml2ZXIp
Ow0KPiA+ICsNCj4gPiArTU9EVUxFX0FVVEhPUigiR3VveWluZyBaaGFuZyA8
R3VveWluZy5aaGFuZ0Bjc3IuY29tPiIpOw0KPiA+ICtNT0RVTEVfREVTQ1JJ
UFRJT04oIlNpUkYgU29DIE9uLWNoaXAgQURDIGRyaXZlciIpOw0KPiA+ICtN
T0RVTEVfTElDRU5TRSgiR1BMIHYyIik7DQoNCgoKTWVtYmVyIG9mIHRoZSBD
U1IgcGxjIGdyb3VwIG9mIGNvbXBhbmllcy4gQ1NSIHBsYyByZWdpc3RlcmVk
IGluIEVuZ2xhbmQgYW5kIFdhbGVzLCByZWdpc3RlcmVkIG51bWJlciA0MTg3
MzQ2LCByZWdpc3RlcmVkIG9mZmljZSBDaHVyY2hpbGwgSG91c2UsIENhbWJy
aWRnZSBCdXNpbmVzcyBQYXJrLCBDb3dsZXkgUm9hZCwgQ2FtYnJpZGdlLCBD
QjQgMFdaLCBVbml0ZWQgS2luZ2RvbQpNb3JlIGluZm9ybWF0aW9uIGNhbiBi
ZSBmb3VuZCBhdCB3d3cuY3NyLmNvbS4gS2VlcCB1cCB0byBkYXRlIHdpdGgg
Q1NSIG9uIG91ciB0ZWNobmljYWwgYmxvZywgd3d3LmNzci5jb20vYmxvZywg
Q1NSIHBlb3BsZSBibG9nLCB3d3cuY3NyLmNvbS9wZW9wbGUsIFlvdVR1YmUs
IHd3dy55b3V0dWJlLmNvbS91c2VyL0NTUnBsYywgRmFjZWJvb2ssIHd3dy5m
YWNlYm9vay5jb20vcGFnZXMvQ1NSLzE5MTAzODQzNDI1MzUzNCwgb3IgZm9s
bG93IHVzIG9uIFR3aXR0ZXIgYXQgd3d3LnR3aXR0ZXIuY29tL0NTUl9wbGMu
Ck5ldyBmb3IgMjAxNCwgeW91IGNhbiBub3cgYWNjZXNzIHRoZSB3aWRlIHJh
bmdlIG9mIHByb2R1Y3RzIHBvd2VyZWQgYnkgYXB0WCBhdCB3d3cuYXB0eC5j
b20uCg==

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2] iio: adc: add CSR SiRFSoC internal ADC driver
  2014-07-17  9:22 [PATCH v2] iio: adc: add CSR SiRFSoC internal ADC driver Guoying Zhang
  2014-07-20 14:33 ` Jonathan Cameron
@ 2014-07-27 12:04 ` Hartmut Knaack
  2014-07-30  8:28   ` Guoying Zhang
  1 sibling, 1 reply; 5+ messages in thread
From: Hartmut Knaack @ 2014-07-27 12:04 UTC (permalink / raw)
  To: Guoying Zhang, jic23
  Cc: linux-iio, workgroup.linux, Peter Meerwald, Barry Song

Guoying Zhang schrieb:
> SiRFSoC internal ADC provides touchscreen single or dual touch
> channels, and provides several auxiliary channels to measure
> temperature, battery and so on.
>
> Cc: Peter Meerwald <pmeerw@pmeerw.net>
> Signed-off-by: Guoying Zhang <Guoying.Zhang@csr.com>
> Signed-off-by: Barry Song <Baohua.Song@csr.com>
> ---
>  -v2: fix many issues from Peter and Jonathan's feedbacks
>
>  .../devicetree/bindings/iio/adc/sirfsoc_adc.txt    |  33 +
>  drivers/iio/adc/Kconfig                            |  10 +
>  drivers/iio/adc/Makefile                           |   1 +
>  drivers/iio/adc/sirfsoc_adc.c                      | 755 +++++++++++++++++++++
>  4 files changed, 799 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/iio/adc/sirfsoc_adc.txt
>  create mode 100644 drivers/iio/adc/sirfsoc_adc.c
>
> diff --git a/Documentation/devicetree/bindings/iio/adc/sirfsoc_adc.txt b/Documentation/devicetree/bindings/iio/adc/sirfsoc_adc.txt
> new file mode 100644
> index 0000000..70eaf40
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/iio/adc/sirfsoc_adc.txt
> @@ -0,0 +1,33 @@
> +Sirfsoc inner Analog to Digital Converter bindings
> +
> +The devicetree bindings are for the new ADC driver written for
> +Prima2/Atlas6 CSR.
> +
> +Required properties:
> +- compatible: Should be one of
> +	* "sirf,prima2-adc": When use Prima2 SOC
> +	* "sirf,atlas6-adc": When use Atlas6 SOC
> +- reg: Offset and length of the register set for the device
> +- interrupts: Should contain the interrupt for the device
> +- clocks: The clock is needed by the ADC controller
> +- resets: The reset for the device
> +- #io-channel-cells: Should be set to <1>
> +
> +Example:
> +	adc: adc@b0110000 {
> +		compatible = "sirf,prima2-adc";
> +		reg = <0xb0110000 0x10000>;
> +		interrupts = <34>;
> +		clocks = <&clks 16>;
> +		resets = <&rstc 32>;
> +		#io-channel-cells = <1>;
> +	};
> +
> +	adc: adc@b0110000 {
> +		compatible = "sirf,atlas6-adc";
> +		reg = <0xb0110000 0x10000>;
> +		interrupts = <34>;
> +		clocks = <&clks 16>;
> +		resets = <&rstc 32>;
> +		#io-channel-cells = <1>;
> +	};
> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> index a80d236..6b803d5 100644
> --- a/drivers/iio/adc/Kconfig
> +++ b/drivers/iio/adc/Kconfig
> @@ -187,6 +187,16 @@ config NAU7802
>  	  To compile this driver as a module, choose M here: the
>  	  module will be called nau7802.
>  
> +config SIRFSOC_ADC
> +	tristate "SiRFSoC ADC"
> +	depends on ARCH_SIRF
> +	help
> +	  If you say yes here you get support for CSR SiRFSoC internal
> +	  ADC.
> +
> +	  This driver can also be built as a module. If so, the module will be
> +	  called sirfsoc_adc.
> +
>  config TI_ADC081C
>  	tristate "Texas Instruments ADC081C021/027"
>  	depends on I2C
> diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
> index 9d60f2d..2912e58 100644
> --- a/drivers/iio/adc/Makefile
> +++ b/drivers/iio/adc/Makefile
> @@ -20,6 +20,7 @@ obj-$(CONFIG_MCP320X) += mcp320x.o
>  obj-$(CONFIG_MCP3422) += mcp3422.o
>  obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o
>  obj-$(CONFIG_NAU7802) += nau7802.o
> +obj-$(CONFIG_SIRFSOC_ADC) += sirfsoc_adc.o
>  obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o
>  obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o
>  obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o
> diff --git a/drivers/iio/adc/sirfsoc_adc.c b/drivers/iio/adc/sirfsoc_adc.c
> new file mode 100644
> index 0000000..ae11a36
> --- /dev/null
> +++ b/drivers/iio/adc/sirfsoc_adc.c
> @@ -0,0 +1,755 @@
> +/*
> +* ADC Driver for CSR SiRFSoC
> +*
> +* Copyright (c) 2014 Cambridge Silicon Radio Limited, a CSR plc group company.
> +*
> +* Licensed under GPLv2.
> +*/
> +
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/init.h>
> +#include <linux/clk.h>
> +#include <linux/io.h>
> +#include <linux/interrupt.h>
> +#include <linux/of.h>
> +#include <linux/pm.h>
> +#include <linux/platform_device.h>
> +#include <linux/of_platform.h>
> +#include <linux/reset.h>
> +#include <linux/rtc/sirfsoc_rtciobrg.h>
> +
> +#include <linux/iio/iio.h>
> +#include <linux/iio/machine.h>
> +#include <linux/iio/driver.h>
> +
> +#define DRIVER_NAME "sirfsoc_adc"
> +
> +#define SIRFSOC_PWR_WAKEEN_TSC_SHIFT	23
> +#define SIRFSOC_PWR_WAKEEN_TS_SHIFT	5
> +#define SIRFSOC_PWRC_TRIGGER_EN		0x8
> +#define SIRFSOC_PWRC_BASE		0x3000
> +
> +/* Registers offset */
> +#define SIRFSOC_ADC_CONTROL1		0x00
> +#define SIRFSOC_ADC_CONTROL2		0x04
> +#define SIRFSOC_ADC_INTR		0x08
> +#define SIRFSOC_ADC_COORD		0x0C
> +#define SIRFSOC_ADC_PRESSURE		0x10
> +#define SIRFSOC_ADC_AUX1		0x14
> +/* Atlas6 AUX2 and AUX4 reserved*/
Whitespace missing at the end of the comment.
> +#define SIRFSOC_ADC_AUX2		0x18
> +#define SIRFSOC_ADC_AUX3		0x1C
> +#define SIRFSOC_ADC_AUX4		0x20
> +#define SIRFSOC_ADC_AUX5		0x24
> +#define SIRFSOC_ADC_AUX6		0x28
> +/* Read Back calibration register */
> +#define SIRFSOC_ADC_CB			0x2C
> +#define SIRFSOC_ADC_COORD2		0x30
> +#define SIRFSOC_ADC_COORD3		0x34
> +#define SIRFSOC_ADC_COORD4		0x38
> +
> +/* CTRL1 defines */
> +#define SIRFSOC_ADC_RESET_QUANT_EN	BIT(24)
> +#define SIRFSOC_ADC_RST_B		BIT(23)
> +#define SIRFSOC_ADC_RESOLUTION_12	BIT(22)
> +#define SIRFSOC_ADC_RBAT_DISABLE	(0x0 << 21)
> +#define SIRFSOC_ADC_RBAT_ENABLE		(0x1 << 21)
BIT(21) to keep it consitent.
> +#define SIRFSOC_ADC_EXTCM(x)		(((x) & 0x3) << 19)
> +#define SIRFSOC_ADC_SGAIN(x)		(((x) & 0x7) << 16)
> +#define SIRFSOC_ADC_POLL		BIT(15)
> +#define SIRFSOC_ADC_SEL(x)		(((x) & 0xF) << 11)
> +#define SIRFSOC_ADC_FREQ_6K		(0x0 << 8)
> +#define SIRFSOC_ADC_FREQ_13K		BIT(8)
> +#define SIRFSOC_ADC_DEL_SET(x)		(((x) & 0xF) << 4)
> +#define SIRFSOC_ADC_TP_TIME(x)		(((x) & 0x7) << 0)
> +
> +/* CTRL2 defines */
> +/* Pen detector off, digitizer off */
> +#define SIRFSOC_ADC_PRP_MODE0		(0 << 14)
> +/* Pen detector on, digitizer off, digitizer wakes up on pen detect */
> +#define SIRFSOC_ADC_PRP_MODE1		BIT(14)
> +/* Pen detector on, digitizer off, no wake up on pen detect */
> +#define SIRFSOC_ADC_PRP_MODE2		(2 << 14)
> +/* Pen detector on, digitizer on */
> +#define SIRFSOC_ADC_PRP_MODE3		(3 << 14)
> +#define SIRFSOC_ADC_RTOUCH(x)		(((x) & 0x3) << 12)
> +#define SIRFSOC_ADC_DEL_PRE(x)		(((x) & 0xF) << 4)
> +#define SIRFSOC_ADC_DEL_DIS(x)		(((x) & 0xF) << 0)
> +
> +/* INTR register defines */
> +#define SIRFSOC_ADC_PEN_INTR_EN		BIT(5)
> +#define SIRFSOC_ADC_DATA_INTR_EN	BIT(4)
> +#define SIRFSOC_ADC_PEN_INTR		BIT(1)
> +#define SIRFSOC_ADC_DATA_INTR		BIT(0)
> +
> +/* DATA register defines */
> +#define SIRFSOC_ADC_PEN_DOWN		BIT(31)
> +#define SIRFSOC_ADC_DATA_AUXVALID	BIT(30)
> +#define SIRFSOC_ADC_DATA_CB_VALID	BIT(30)
> +#define SIRFSOC_ADC_ADC_DATA_MASK(x)	(0x3FFF << (x))
> +#define SIRFSOC_ADC_DATA_AUXMASK	SIRFSOC_ADC_ADC_DATA_MASK(0)
> +#define SIRFSOC_ADC_DATA_CBMASK		SIRFSOC_ADC_ADC_DATA_MASK(0)
> +
> +#define SIRFSOC_ADC_MORE_CTL1	(of_machine_is_compatible("sirf,atlas6") ?\
> +				(SIRFSOC_ADC_RESET_QUANT_EN |\
> +				SIRFSOC_ADC_RST_B) : (0))
> +
> +/* Select AD samples to read (SEL bits in ADC_CONTROL1 register) */
> +#define SIRFSOC_ADC_AUX1_SEL	0x04
> +#define SIRFSOC_ADC_AUX2_SEL	0x05
> +#define SIRFSOC_ADC_AUX3_SEL	0x06
> +#define SIRFSOC_ADC_AUX4_SEL	0x07
> +#define SIRFSOC_ADC_AUX5_SEL	0x08
> +#define SIRFSOC_ADC_AUX6_SEL	0x09
> +#define SIRFSOC_ADC_TS_SEL	0x0A    /* Sample for single touch*/
> +#define SIRFSOC_ADC_GROUND_SEL	0x0B    /* Gound for offset calibration */
Ground
> +#define SIRFSOC_ADC_BANDGAP_SEL	0x0C    /* Bandgap for gain calibration */
> +#define SIRFSOC_ADC_TS_SEL_DUAL	0x0F    /* Samples for dual touch */
> +
> +#define SIRFSOC_ADC_TS_SAMPLE_SIZE	4
> +#define SIRFSOC_ADC_CTL1(sel)    (SIRFSOC_ADC_POLL | SIRFSOC_ADC_SEL(sel) |\
> +		SIRFSOC_ADC_DEL_SET(6) | SIRFSOC_ADC_FREQ_6K |\
> +		SIRFSOC_ADC_TP_TIME(0) | SIRFSOC_ADC_SGAIN(0) |\
> +		SIRFSOC_ADC_EXTCM(0) | SIRFSOC_ADC_RBAT_DISABLE |\
> +		SIRFSOC_ADC_MORE_CTL1)
> +
> +enum sirfsoc_adc_chips {
> +	PRIMA2,
> +	ATLAS6,
> +};
> +
> +struct sirfsoc_adc_chip_info {
> +	const struct iio_chan_spec *channels;
> +	unsigned int num_channels;
> +	unsigned int flags;
> +	const struct iio_info *iio_info;
> +
> +	u32 (*calculate_volt)(u32, u32, u32);
> +	const u32 *channel_sel;
> +};
> +
> +struct sirfsoc_adc_request {
> +	u16 mode;
> +	u16 extcm;
> +	u16 reference;
> +	u8 delay_bits;
> +	u32 s_gain_bits;
> +	u16 read_back_data;
> +};
> +
> +struct sirfsoc_adc {
> +	const struct sirfsoc_adc_chip_info	*chip_info;
> +	struct clk	*clk;
> +	void __iomem	*base;
> +	struct sirfsoc_adc_request req;
> +	struct completion	done;
> +	struct mutex	adc_lock;
> +};
> +
> +static const u32 sirfsoc_adc_ts_reg[SIRFSOC_ADC_TS_SAMPLE_SIZE] = {
> +	/* Dual touch samples read registers*/
> +	SIRFSOC_ADC_COORD, SIRFSOC_ADC_COORD2,
> +	SIRFSOC_ADC_COORD3, SIRFSOC_ADC_COORD4
> +};
> +
> +enum sirfsoc_adc_ts_type {
> +	SINGLE_TOUCH,
> +	DUAL_TOUCH,
> +};
> +
> +static int sirfsoc_adc_get_ts_sample(
> +	struct sirfsoc_adc *adc, int *sample, int touch_type)
The first two parameters fit into the first line, the third one should be aligned with the opening parenthesis.
> +{
> +	int adc_intr;
> +	int ret = 0;
> +	int i;
> +
> +	mutex_lock(&adc->adc_lock);
> +	adc_intr = readl(adc->base + SIRFSOC_ADC_INTR);
> +	if (adc_intr & SIRFSOC_ADC_PEN_INTR)
> +		writel(SIRFSOC_ADC_PEN_INTR | SIRFSOC_ADC_PEN_INTR_EN |
> +			SIRFSOC_ADC_DATA_INTR_EN,
> +			adc->base + SIRFSOC_ADC_INTR);
> +
> +	/* check pen status */
> +	if (!(readl(adc->base + SIRFSOC_ADC_COORD) & SIRFSOC_ADC_PEN_DOWN)) {
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	if (SINGLE_TOUCH == touch_type)
> +		writel(SIRFSOC_ADC_CTL1(SIRFSOC_ADC_TS_SEL),
> +			adc->base + SIRFSOC_ADC_CONTROL1);
> +	else
> +		writel(SIRFSOC_ADC_CTL1(SIRFSOC_ADC_TS_SEL_DUAL),
> +			adc->base + SIRFSOC_ADC_CONTROL1);
> +
> +	if (!wait_for_completion_timeout(&adc->done,
> +		msecs_to_jiffies(50))) {
Don't split it into 2 lines (with misleading indentation), it perfectly fits into one line.
> +		ret = -EIO;
> +		goto out;
> +	}
> +
> +	if (SINGLE_TOUCH == touch_type)
> +		*sample = readl(adc->base + SIRFSOC_ADC_COORD);
> +	else
> +		for (i = 0; i < SIRFSOC_ADC_TS_SAMPLE_SIZE; i++)
> +			sample[i] = readl(adc->base + sirfsoc_adc_ts_reg[i]);
> +
> +out:
> +	mutex_unlock(&adc->adc_lock);
> +	return ret;
> +}
> +
> +/* get touchscreen coordinates for single touch */
> +static int sirfsoc_adc_single_ts_sample(struct sirfsoc_adc *adc, int *sample)
> +{
> +	return sirfsoc_adc_get_ts_sample(adc, sample, SINGLE_TOUCH);
> +}
> +
> +/* get touchscreen coordinates for dual touch */
> +static int sirfsoc_adc_dual_ts_sample(struct sirfsoc_adc *adc, int *samples)
> +{
> +	return sirfsoc_adc_get_ts_sample(adc, samples, DUAL_TOUCH);
> +}
> +
> +static int sirfsoc_adc_send_request(struct sirfsoc_adc_request *req)
> +{
> +	struct sirfsoc_adc *adc = container_of(req, struct sirfsoc_adc, req);
> +	int control1, control2, intr;
> +	int data, reg_offset;
> +	int ret = 0;
> +
> +	mutex_lock(&adc->adc_lock);
> +
> +	/* Store registers for recover */
> +	intr = readl(adc->base + SIRFSOC_ADC_INTR);
> +	control1 = readl(adc->base + SIRFSOC_ADC_CONTROL1);
> +	control2 = readl(adc->base + SIRFSOC_ADC_CONTROL2);
> +
> +	writel(intr | SIRFSOC_ADC_DATA_INTR_EN | SIRFSOC_ADC_DATA_INTR,
> +		adc->base + SIRFSOC_ADC_INTR);
> +	writel(SIRFSOC_ADC_PRP_MODE3 | req->reference,
> +		adc->base + SIRFSOC_ADC_CONTROL2);
> +	writel(SIRFSOC_ADC_POLL | SIRFSOC_ADC_MORE_CTL1 | req->mode |
> +		req->extcm | req->delay_bits | SIRFSOC_ADC_RESOLUTION_12,
> +		adc->base + SIRFSOC_ADC_CONTROL1);
> +
> +	if (!wait_for_completion_timeout(&adc->done,
> +		msecs_to_jiffies(50))) {
One line.
> +		ret = -EIO;
> +		goto out;
> +	}
> +
> +	switch (req->mode) {
> +	case SIRFSOC_ADC_SEL(SIRFSOC_ADC_AUX1_SEL):
> +	case SIRFSOC_ADC_SEL(SIRFSOC_ADC_AUX2_SEL):
> +	case SIRFSOC_ADC_SEL(SIRFSOC_ADC_AUX3_SEL):
> +	case SIRFSOC_ADC_SEL(SIRFSOC_ADC_AUX4_SEL):
> +	case SIRFSOC_ADC_SEL(SIRFSOC_ADC_AUX5_SEL):
> +	case SIRFSOC_ADC_SEL(SIRFSOC_ADC_AUX6_SEL):
> +		/* Calculate aux offset from mode */
> +		reg_offset = 0x14 + ((req->mode >> 11) - 0x04) * 4;
> +		data = readl(adc->base + reg_offset);
> +		if (data & SIRFSOC_ADC_DATA_AUXVALID)
> +			req->read_back_data = data & SIRFSOC_ADC_DATA_AUXMASK;
> +		break;
> +	case SIRFSOC_ADC_SEL(SIRFSOC_ADC_GROUND_SEL):
> +	case SIRFSOC_ADC_SEL(SIRFSOC_ADC_BANDGAP_SEL):
> +		reg_offset = SIRFSOC_ADC_CB;
> +		data = readl(adc->base + reg_offset);
> +		if (data & SIRFSOC_ADC_DATA_CB_VALID)
> +			req->read_back_data = data & SIRFSOC_ADC_DATA_CBMASK;
> +		break;
> +	default:
> +		break;
You may want to put ret = -EINVAL into the default section, or drop it completely.
> +	}
> +
> +out:
> +	writel(intr, adc->base + SIRFSOC_ADC_INTR);
> +	writel(control1, adc->base + SIRFSOC_ADC_CONTROL1);
> +	writel(control2, adc->base + SIRFSOC_ADC_CONTROL2);
> +	mutex_unlock(&adc->adc_lock);
> +	return ret;
> +}
> +
> +/* Store params to calibrate */
> +struct sirfsoc_adc_cali_data {
> +	u32 digital_offset;
> +	u32 digital_again;
> +	bool is_calibration;
> +};
> +
> +/* Offset Calibration calibrates the ADC offset error */
> +static u32 sirfsoc_adc_offset_cali(struct sirfsoc_adc_request *req)
> +{
> +	u32 i, digital_offset = 0, count = 0, sum = 0;
> +	/* To set the registers in order to get the ADC offset */
> +	req->mode = SIRFSOC_ADC_SEL(SIRFSOC_ADC_GROUND_SEL);
> +	req->extcm = SIRFSOC_ADC_EXTCM(0);
req->extcm is of type u16, but SIRFSOC_ADC_EXTCM does a left-shift of a two bit value by 19 bits. That does not fit properly.
> +	req->s_gain_bits = SIRFSOC_ADC_SGAIN(7);
> +	req->delay_bits = SIRFSOC_ADC_DEL_SET(4);
> +
> +	for (i = 0; i < 10; i++) {
> +		if (sirfsoc_adc_send_request(req))
> +			break;
> +		digital_offset = req->read_back_data;
> +		sum += digital_offset;
> +		count++;
> +	}
> +	if (!count)
> +		digital_offset = 0;
> +	else
> +		digital_offset = sum / count;
> +
> +	return digital_offset;
> +}
> +
> +
> +/* Gain Calibration calibrates the ADC gain error */
> +static u32 sirfsoc_adc_gain_cali(struct sirfsoc_adc_request *req)
> +{
> +	u32 i, digital_gain = 0, count = 0, sum = 0;
> +	/* To set the registers in order to get the ADC gain */
> +	req->mode = SIRFSOC_ADC_SEL(SIRFSOC_ADC_BANDGAP_SEL);
> +	req->extcm = SIRFSOC_ADC_EXTCM(0);
> +	req->s_gain_bits = SIRFSOC_ADC_SGAIN(1);
> +	req->delay_bits = SIRFSOC_ADC_DEL_SET(4);
> +
> +	for (i = 0; i < 10; i++) {
> +		if (sirfsoc_adc_send_request(req))
> +			break;
> +		digital_gain = req->read_back_data;
> +		sum += digital_gain;
> +		count++;
> +	}
> +	if (!count)
> +		digital_gain = 0;
> +	else
> +		digital_gain = sum / count;
> +
> +	return digital_gain;
> +}
> +
Those two functions are apart of setting different values to req->mode and req->s_gain_bits totally equal. It would make sense to consolidate them into one function with an additional parameter specifying weather to do gain or offset calibration.
> +/* Absolute gain calibration */
> +static int sirfsoc_adc_adc_cali(struct sirfsoc_adc_request *req,
> +				struct sirfsoc_adc_cali_data *cali_data)
> +{
> +	cali_data->digital_offset = sirfsoc_adc_offset_cali(req);
> +	if (!cali_data->digital_offset)
> +		return -EINVAL;
> +	cali_data->digital_again = sirfsoc_adc_gain_cali(req);
> +	if (!cali_data->digital_again)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +/* Get voltage after ADC conversion */
> +static u32 sirfsoc_adc_get_adc_volt(struct sirfsoc_adc *adc,
> +				struct sirfsoc_adc_cali_data *cali_data)
> +{
> +	u32 digital_out, volt;
> +	struct sirfsoc_adc_request *req = &adc->req;
> +
> +	req->s_gain_bits = SIRFSOC_ADC_SGAIN(0);
> +	req->delay_bits = SIRFSOC_ADC_DEL_SET(4);
> +
> +	/*
> +	 * First read original data
> +	 * then read calibrate errors
> +	 */
> +	sirfsoc_adc_send_request(req);
> +	if (req->read_back_data) {
> +		digital_out = req->read_back_data;
> +		/* Get errors for each sample */
> +		if (!cali_data->is_calibration) {
> +			if (sirfsoc_adc_adc_cali(req, cali_data))
> +				return 0;
> +			cali_data->is_calibration = true;
> +		}
> +
> +		volt = adc->chip_info->calculate_volt(digital_out,
> +			cali_data->digital_offset,
> +			cali_data->digital_again);
Indent parameters with parenthesis. Also, you can drop the variable volt and directly return the value here.
> +	} else {
> +		return 0;
> +	}
> +
> +	return volt;
> +}
> +
> +static u32 prima2_adc_calculate_volt(u32 digital_out,
> +				u32 digital_offset, u32 digital_again)
> +{
> +	u32 volt, digital_ideal, digital_convert;
> +
> +	/*
> +	 * see Equation 3.2 of SiRFPrimaII™ Internal ADC and Touch
> +	 * User Guide
> +	 */
> +	digital_ideal = (5522 * 1200) / (7 * 333);
> +	/*
> +	 * see Equation 3.3 of SiRFatlasVI™ Internal ADC and Touch
> +	 */
> +	digital_convert = (digital_out - 11645 * digital_offset /
> +		140000) * digital_ideal / (digital_again
> +		- digital_offset * 11645 / 70000);
> +	volt = 14 * 333 * digital_convert / 5522;
> +
> +	return volt;
Drop volt here as well?
> +}
> +
> +static u32 atlas6_adc_calculate_volt(u32 digital_out,
> +				u32 digital_offset, u32 digital_again)
> +{
> +	u32 volt, digital_ideal, digital_convert;
> +
> +	/*
> +	 * see Equation 3.2 of SiRFatlasVI™ Internal ADC and Touch
> +	 * User Guide
> +	 */
> +	digital_ideal = (3986 * 12100) / (7 * 3333);
> +	/*
> +	 * see Equation 3.3 of SiRFatlasVI™ Internal ADC and Touch
> +	 */
> +	digital_offset &= 0xfff;
> +	digital_convert = abs(digital_out - 2 * digital_offset)
> +		* digital_ideal / (digital_again
> +		- digital_offset * 2);
> +	volt = 14 * 333 * digital_convert / 3986;
> +	volt = volt / 2;
> +	if (volt > 1500)
> +		volt = volt - (volt - 1500) / 15;
> +	else
> +		volt = volt + (1500 - volt) / 28;
> +
> +	return volt;
> +}
> +
> +static irqreturn_t sirfsoc_adc_data_irq(int irq, void *handle)
> +{
> +	struct iio_dev *indio_dev = handle;
> +	struct sirfsoc_adc *adc = iio_priv(indio_dev);
> +	int val;
> +
> +	val = readl(adc->base + SIRFSOC_ADC_INTR);
> +
> +	writel(SIRFSOC_ADC_PEN_INTR | SIRFSOC_ADC_PEN_INTR_EN |
> +		SIRFSOC_ADC_DATA_INTR | SIRFSOC_ADC_DATA_INTR_EN,
> +		adc->base + SIRFSOC_ADC_INTR);
> +
> +	if (val & SIRFSOC_ADC_DATA_INTR)
> +		complete(&adc->done);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int sirfsoc_adc_read_raw(struct iio_dev *indio_dev,
> +				struct iio_chan_spec const *chan,
> +				int *val,
> +				int *val2,
> +				long mask)
> +{
> +	struct sirfsoc_adc *adc = iio_priv(indio_dev);
> +	struct sirfsoc_adc_cali_data cali_data;
> +	int ret;
> +
> +	cali_data.is_calibration = false;
> +	switch (mask) {
> +	case IIO_CHAN_INFO_RAW:
> +		if (0 == chan->channel)
> +			ret = sirfsoc_adc_single_ts_sample(adc, val);
> +		else
> +			ret = sirfsoc_adc_dual_ts_sample(adc, val);
> +
> +		if (ret)
> +			return ret;
> +		return IIO_VAL_INT;
> +	case IIO_CHAN_INFO_PROCESSED:
> +		adc->req.mode = SIRFSOC_ADC_SEL(
> +			adc->chip_info->channel_sel[chan->channel]);
> +		adc->req.extcm = SIRFSOC_ADC_EXTCM(0);
> +		*val = sirfsoc_adc_get_adc_volt(adc, &cali_data);
> +		return IIO_VAL_INT;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +#ifdef CONFIG_PM_SLEEP
> +static int sirfsoc_adc_suspend(struct device *dev)
> +{
> +	struct iio_dev *indio_dev = dev_get_drvdata(dev);
> +	struct sirfsoc_adc *adc = iio_priv(indio_dev);
> +
> +	sirfsoc_rtc_iobrg_writel(sirfsoc_rtc_iobrg_readl(
> +		SIRFSOC_PWRC_BASE + SIRFSOC_PWRC_TRIGGER_EN)
> +		& ~BIT(SIRFSOC_PWR_WAKEEN_TSC_SHIFT),
> +		SIRFSOC_PWRC_BASE + SIRFSOC_PWRC_TRIGGER_EN);
> +
> +	clk_disable_unprepare(adc->clk);
> +
> +	return 0;
> +}
> +
> +static int sirfsoc_adc_resume(struct device *dev)
> +{
> +	struct iio_dev *indio_dev = dev_get_drvdata(dev);
> +	struct sirfsoc_adc *adc = iio_priv(indio_dev);
> +	int ret;
> +	int val;
> +
> +	clk_prepare_enable(adc->clk);
> +
> +	sirfsoc_rtc_iobrg_writel(sirfsoc_rtc_iobrg_readl(
> +		SIRFSOC_PWRC_BASE + SIRFSOC_PWRC_TRIGGER_EN) |
> +		BIT(SIRFSOC_PWR_WAKEEN_TS_SHIFT),
> +		SIRFSOC_PWRC_BASE + SIRFSOC_PWRC_TRIGGER_EN);
> +
> +	ret = device_reset(dev);
> +	if (ret) {
> +		dev_err(dev, "Failed to reset\n");
> +		return ret;
> +	}
> +
> +	writel(SIRFSOC_ADC_PRP_MODE3 | SIRFSOC_ADC_RTOUCH(1) |
> +		SIRFSOC_ADC_DEL_PRE(2) | SIRFSOC_ADC_DEL_DIS(5),
> +		adc->base + SIRFSOC_ADC_CONTROL2);
> +
> +	val = readl(adc->base + SIRFSOC_ADC_INTR);
> +
> +	/* Clear interrupts and enable PEN interrupt */
> +	writel(val | SIRFSOC_ADC_PEN_INTR | SIRFSOC_ADC_DATA_INTR |
> +		SIRFSOC_ADC_PEN_INTR_EN | SIRFSOC_ADC_DATA_INTR_EN,
> +		adc->base + SIRFSOC_ADC_INTR);
> +
> +	return 0;
> +}
> +#endif
> +
> +static const struct dev_pm_ops sirfsoc_adc_pm_ops = {
> +	SET_SYSTEM_SLEEP_PM_OPS(sirfsoc_adc_suspend, sirfsoc_adc_resume)
> +};
> +
> +#define SIRFSOC_ADC_CHANNEL(_channel, _type, _name, _mask) {	\
> +	.type = _type,					\
> +	.indexed = 1,					\
> +	.channel = _channel,				\
> +	.datasheet_name = _name,			\
> +	.info_mask_separate = BIT(_mask),		\
> +}
> +
> +#define SIRFSOC_ADC_TS_CHANNEL(_channel, _name)		\
> +	SIRFSOC_ADC_CHANNEL(_channel, IIO_VOLTAGE,	\
> +	_name, IIO_CHAN_INFO_RAW)
> +
> +#define SIRFSOC_ADC_AUX_CHANNEL(_channel, _name)	\
> +	SIRFSOC_ADC_CHANNEL(_channel, IIO_VOLTAGE,	\
> +	_name, IIO_CHAN_INFO_PROCESSED)
> +
> +static const struct iio_chan_spec prima2_adc_iio_channels[] = {
> +	/* Channels to get the touch data */
> +	SIRFSOC_ADC_TS_CHANNEL(0, "touch_coord"),
> +	/* Channels to get the pin input */
> +	SIRFSOC_ADC_AUX_CHANNEL(1, "auxiliary1"),
> +	SIRFSOC_ADC_AUX_CHANNEL(2, "auxiliary2"),
> +	SIRFSOC_ADC_AUX_CHANNEL(3, "auxiliary3"),
> +	SIRFSOC_ADC_AUX_CHANNEL(4, "auxiliary4"),
> +	SIRFSOC_ADC_AUX_CHANNEL(5, "auxiliary5"),
> +	SIRFSOC_ADC_AUX_CHANNEL(6, "auxiliary6"),
> +};
> +
> +static const u32 prima2_adc_channel_sel[] = {
> +	0, SIRFSOC_ADC_AUX1_SEL, SIRFSOC_ADC_AUX2_SEL,
> +	SIRFSOC_ADC_AUX3_SEL, SIRFSOC_ADC_AUX4_SEL,
> +	SIRFSOC_ADC_AUX5_SEL, SIRFSOC_ADC_AUX6_SEL
> +};
> +
> +static const struct iio_chan_spec atlas6_adc_iio_channels[] = {
> +	/* Channels to get the touch data */
> +	SIRFSOC_ADC_TS_CHANNEL(0, "touch_coord"),
> +	SIRFSOC_ADC_TS_CHANNEL(1, "dual_touch_coord"),
> +	/* Channels to get the pin input */
> +	SIRFSOC_ADC_AUX_CHANNEL(2, "auxiliary1"),
> +	/* Atlas6 has no auxiliary2 and auxiliary3 */
> +	SIRFSOC_ADC_AUX_CHANNEL(3, "auxiliary4"),
> +	SIRFSOC_ADC_AUX_CHANNEL(4, "auxiliary5"),
> +	SIRFSOC_ADC_AUX_CHANNEL(5, "auxiliary6"),
> +};
> +
> +static const u32 atlas6_adc_channel_sel[] = {
> +	0, 0, SIRFSOC_ADC_AUX1_SEL, SIRFSOC_ADC_AUX4_SEL,
> +	SIRFSOC_ADC_AUX5_SEL, SIRFSOC_ADC_AUX6_SEL
> +};
> +
> +static const struct iio_info sirfsoc_adc_info = {
> +	.read_raw = &sirfsoc_adc_read_raw,
> +	.driver_module = THIS_MODULE,
> +};
> +
> +static const struct sirfsoc_adc_chip_info sirfsoc_adc_chip_info_tbl[] = {
> +	[PRIMA2] = {
> +		.channels = prima2_adc_iio_channels,
> +		.num_channels = ARRAY_SIZE(prima2_adc_iio_channels),
> +		.iio_info = &sirfsoc_adc_info,
> +		.calculate_volt = prima2_adc_calculate_volt,
> +		.channel_sel = prima2_adc_channel_sel,
> +	},
> +	[ATLAS6] = {
> +		.channels = atlas6_adc_iio_channels,
> +		.num_channels = ARRAY_SIZE(atlas6_adc_iio_channels),
> +		.iio_info = &sirfsoc_adc_info,
> +		.calculate_volt = atlas6_adc_calculate_volt,
> +		.channel_sel = atlas6_adc_channel_sel,
> +	},
> +};
> +
> +static const struct of_device_id sirfsoc_adc_of_match[] = {
> +	{ .compatible = "sirf,prima2-adc",
> +	  .data = &sirfsoc_adc_chip_info_tbl[PRIMA2] },
> +	{ .compatible = "sirf,atlas6-adc",
> +	  .data = &sirfsoc_adc_chip_info_tbl[ATLAS6] },
> +	{}
> +};
> +MODULE_DEVICE_TABLE(of, sirfsoc_adc_of_match);
> +
> +static int sirfsoc_adc_probe(struct platform_device *pdev)
> +{
> +	struct resource	*mem_res;
> +	struct sirfsoc_adc *adc;
> +	struct iio_dev *indio_dev;
> +	const struct of_device_id *match;
> +	int irq;
> +	int ret;
> +
> +	indio_dev = devm_iio_device_alloc(&pdev->dev,
> +			sizeof(struct sirfsoc_adc));
> +	if (!indio_dev)
> +		return -ENOMEM;
> +
> +	adc = iio_priv(indio_dev);
> +
> +	/* ADC specific data */
> +	match = of_match_device(
> +		of_match_ptr(sirfsoc_adc_of_match), &pdev->dev);
> +	adc->chip_info = match->data;
> +
> +	indio_dev->info = adc->chip_info->iio_info;
> +	indio_dev->channels = adc->chip_info->channels;
> +	indio_dev->num_channels = adc->chip_info->num_channels;
> +	indio_dev->name = "sirfsoc adc";
> +	indio_dev->dev.parent = &pdev->dev;
> +	indio_dev->modes = INDIO_DIRECT_MODE;
> +
> +	platform_set_drvdata(pdev, indio_dev);
> +
> +	adc->clk = devm_clk_get(&pdev->dev, NULL);
> +	if (IS_ERR(adc->clk)) {
> +		dev_err(&pdev->dev, "Get adc clk failed\n");
> +		ret = -ENOMEM;
> +		goto err;
Isn't it a bit too early to call clk_disable_unprepare? Also, wouldn't it make more sense to return the error value from devm_clk_get?
> +	}
> +	clk_prepare_enable(adc->clk);
> +
> +	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!mem_res) {
> +		dev_err(&pdev->dev, "Unable to get io resource\n");
> +		ret = -ENODEV;
> +		goto err;
> +	}
> +
> +	adc->base = devm_request_and_ioremap(&pdev->dev, mem_res);
> +	if (!adc->base) {
> +		dev_err(&pdev->dev, "IO remap failed!\n");
> +		ret = -ENOMEM;
> +		goto err;
> +	}
> +
> +	init_completion(&adc->done);
> +	mutex_init(&adc->adc_lock);
> +
> +	sirfsoc_rtc_iobrg_writel(sirfsoc_rtc_iobrg_readl(SIRFSOC_PWRC_BASE +
> +		SIRFSOC_PWRC_TRIGGER_EN) | BIT(SIRFSOC_PWR_WAKEEN_TS_SHIFT),
> +		SIRFSOC_PWRC_BASE + SIRFSOC_PWRC_TRIGGER_EN);
> +
> +	ret = device_reset(&pdev->dev);
> +	if (ret) {
> +		dev_err(&pdev->dev, "Failed to reset\n");
> +		goto err;
> +	}
> +
> +	writel(SIRFSOC_ADC_PRP_MODE3 | SIRFSOC_ADC_RTOUCH(1) |
> +		SIRFSOC_ADC_DEL_PRE(2) | SIRFSOC_ADC_DEL_DIS(5),
> +		adc->base + SIRFSOC_ADC_CONTROL2);
> +
> +	/* Clear interrupts and enable PEN INTR */
> +	writel(readl(adc->base + SIRFSOC_ADC_INTR) | SIRFSOC_ADC_PEN_INTR |
> +		SIRFSOC_ADC_DATA_INTR | SIRFSOC_ADC_PEN_INTR_EN |
> +		SIRFSOC_ADC_DATA_INTR_EN,  adc->base + SIRFSOC_ADC_INTR);
> +
> +	irq = platform_get_irq(pdev, 0);
> +	if (irq < 0) {
> +		dev_err(&pdev->dev, "Failed to get IRQ!\n");
> +		ret = -ENOMEM;
ret = irq;?
> +		goto err;
> +	}
> +
> +	ret = devm_request_irq(&pdev->dev, irq, sirfsoc_adc_data_irq,
> +		0, DRIVER_NAME, indio_dev);
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "Failed to register irq handler\n");
> +		ret = -ENODEV;
Pass ret unchanged?
> +		goto err;
> +	}
> +
> +	ret = of_platform_populate(pdev->dev.of_node, sirfsoc_adc_of_match,
> +		NULL, &pdev->dev);
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "Failed to add child nodes\n");
> +		goto err;
> +	}
> +
> +	ret = iio_device_register(indio_dev);
> +	if (ret) {
> +		dev_err(&pdev->dev, "Failed to register adc iio dev\n");
> +		goto err;
> +	}
> +
> +	return 0;
> +
> +err:
> +	clk_disable_unprepare(adc->clk);
> +
> +	return ret;
> +}
> +
> +static int sirfsoc_adc_remove(struct platform_device *pdev)
> +{
> +	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
> +	struct sirfsoc_adc *adc = iio_priv(indio_dev);
> +
> +	iio_device_unregister(indio_dev);
> +	clk_disable_unprepare(adc->clk);
> +
> +	return 0;
> +}
> +
> +static struct platform_driver sirfsoc_adc_driver = {
> +	.driver = {
> +		.name	= DRIVER_NAME,
> +		.of_match_table = sirfsoc_adc_of_match,
> +		.pm	= &sirfsoc_adc_pm_ops,
> +	},
> +	.probe		= sirfsoc_adc_probe,
> +	.remove		= sirfsoc_adc_remove,
> +};
> +
> +module_platform_driver(sirfsoc_adc_driver);
> +
> +MODULE_AUTHOR("Guoying Zhang <Guoying.Zhang@csr.com>");
> +MODULE_DESCRIPTION("SiRF SoC On-chip ADC driver");
> +MODULE_LICENSE("GPL v2");


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2] iio: adc: add CSR SiRFSoC internal ADC driver
  2014-07-27 12:04 ` Hartmut Knaack
@ 2014-07-30  8:28   ` Guoying Zhang
  0 siblings, 0 replies; 5+ messages in thread
From: Guoying Zhang @ 2014-07-30  8:28 UTC (permalink / raw)
  To: Hartmut Knaack
  Cc: jic23@kernel.org, linux-iio@vger.kernel.org,
	DL-SHA-WorkGroupLinux, Peter Meerwald, Barry Song

T24gMjAxNC0wNy0yNyAxNDowNCArMDIwMO+8jEhhcnRtdXQgS25hYWNrIHdy
b3Rl77yaCj4gR3VveWluZyBaaGFuZyBzY2hyaWViOgo+ID4gU2lSRlNvQyBp
bnRlcm5hbCBBREMgcHJvdmlkZXMgdG91Y2hzY3JlZW4gc2luZ2xlIG9yIGR1
YWwgdG91Y2gKPiA+IGNoYW5uZWxzLCBhbmQgcHJvdmlkZXMgc2V2ZXJhbCBh
dXhpbGlhcnkgY2hhbm5lbHMgdG8gbWVhc3VyZQo+ID4gdGVtcGVyYXR1cmUs
IGJhdHRlcnkgYW5kIHNvIG9uLgo+ID4KPiA+IENjOiBQZXRlciBNZWVyd2Fs
ZCA8cG1lZXJ3QHBtZWVydy5uZXQ+Cj4gPiBTaWduZWQtb2ZmLWJ5OiBHdW95
aW5nIFpoYW5nIDxHdW95aW5nLlpoYW5nQGNzci5jb20+Cj4gPiBTaWduZWQt
b2ZmLWJ5OiBCYXJyeSBTb25nIDxCYW9odWEuU29uZ0Bjc3IuY29tPgo+ID4g
LS0tCj4gPiAgLXYyOiBmaXggbWFueSBpc3N1ZXMgZnJvbSBQZXRlciBhbmQg
Sm9uYXRoYW4ncyBmZWVkYmFja3MKPiA+Cj4gPiAgLi4uL2RldmljZXRyZWUv
YmluZGluZ3MvaWlvL2FkYy9zaXJmc29jX2FkYy50eHQgICAgfCAgMzMgKwo+
ID4gIGRyaXZlcnMvaWlvL2FkYy9LY29uZmlnICAgICAgICAgICAgICAgICAg
ICAgICAgICAgIHwgIDEwICsKPiA+ICBkcml2ZXJzL2lpby9hZGMvTWFrZWZp
bGUgICAgICAgICAgICAgICAgICAgICAgICAgICB8ICAgMSArCj4gPiAgZHJp
dmVycy9paW8vYWRjL3NpcmZzb2NfYWRjLmMgICAgICAgICAgICAgICAgICAg
ICAgfCA3NTUgKysrKysrKysrKysrKysrKysrKysrCj4gPiAgNCBmaWxlcyBj
aGFuZ2VkLCA3OTkgaW5zZXJ0aW9ucygrKQo+ID4gIGNyZWF0ZSBtb2RlIDEw
MDY0NCBEb2N1bWVudGF0aW9uL2RldmljZXRyZWUvYmluZGluZ3MvaWlvL2Fk
Yy9zaXJmc29jX2FkYy50eHQKPiA+ICBjcmVhdGUgbW9kZSAxMDA2NDQgZHJp
dmVycy9paW8vYWRjL3NpcmZzb2NfYWRjLmMKPiA+Cj4gPiBkaWZmIC0tZ2l0
IGEvRG9jdW1lbnRhdGlvbi9kZXZpY2V0cmVlL2JpbmRpbmdzL2lpby9hZGMv
c2lyZnNvY19hZGMudHh0IGIvRG9jdW1lbnRhdGlvbi9kZXZpY2V0cmVlL2Jp
bmRpbmdzL2lpby9hZGMvc2lyZnNvY19hZGMudHh0Cj4gPiBuZXcgZmlsZSBt
b2RlIDEwMDY0NAo+ID4gaW5kZXggMDAwMDAwMC4uNzBlYWY0MAo+ID4gLS0t
IC9kZXYvbnVsbAo+ID4gKysrIGIvRG9jdW1lbnRhdGlvbi9kZXZpY2V0cmVl
L2JpbmRpbmdzL2lpby9hZGMvc2lyZnNvY19hZGMudHh0Cj4gPiBAQCAtMCww
ICsxLDMzIEBACj4gPiArU2lyZnNvYyBpbm5lciBBbmFsb2cgdG8gRGlnaXRh
bCBDb252ZXJ0ZXIgYmluZGluZ3MKPiA+ICsKPiA+ICtUaGUgZGV2aWNldHJl
ZSBiaW5kaW5ncyBhcmUgZm9yIHRoZSBuZXcgQURDIGRyaXZlciB3cml0dGVu
IGZvcgo+ID4gK1ByaW1hMi9BdGxhczYgQ1NSLgo+ID4gKwo+ID4gK1JlcXVp
cmVkIHByb3BlcnRpZXM6Cj4gPiArLSBjb21wYXRpYmxlOiBTaG91bGQgYmUg
b25lIG9mCj4gPiArCSogInNpcmYscHJpbWEyLWFkYyI6IFdoZW4gdXNlIFBy
aW1hMiBTT0MKPiA+ICsJKiAic2lyZixhdGxhczYtYWRjIjogV2hlbiB1c2Ug
QXRsYXM2IFNPQwo+ID4gKy0gcmVnOiBPZmZzZXQgYW5kIGxlbmd0aCBvZiB0
aGUgcmVnaXN0ZXIgc2V0IGZvciB0aGUgZGV2aWNlCj4gPiArLSBpbnRlcnJ1
cHRzOiBTaG91bGQgY29udGFpbiB0aGUgaW50ZXJydXB0IGZvciB0aGUgZGV2
aWNlCj4gPiArLSBjbG9ja3M6IFRoZSBjbG9jayBpcyBuZWVkZWQgYnkgdGhl
IEFEQyBjb250cm9sbGVyCj4gPiArLSByZXNldHM6IFRoZSByZXNldCBmb3Ig
dGhlIGRldmljZQo+ID4gKy0gI2lvLWNoYW5uZWwtY2VsbHM6IFNob3VsZCBi
ZSBzZXQgdG8gPDE+Cj4gPiArCj4gPiArRXhhbXBsZToKPiA+ICsJYWRjOiBh
ZGNAYjAxMTAwMDAgewo+ID4gKwkJY29tcGF0aWJsZSA9ICJzaXJmLHByaW1h
Mi1hZGMiOwo+ID4gKwkJcmVnID0gPDB4YjAxMTAwMDAgMHgxMDAwMD47Cj4g
PiArCQlpbnRlcnJ1cHRzID0gPDM0PjsKPiA+ICsJCWNsb2NrcyA9IDwmY2xr
cyAxNj47Cj4gPiArCQlyZXNldHMgPSA8JnJzdGMgMzI+Owo+ID4gKwkJI2lv
LWNoYW5uZWwtY2VsbHMgPSA8MT47Cj4gPiArCX07Cj4gPiArCj4gPiArCWFk
YzogYWRjQGIwMTEwMDAwIHsKPiA+ICsJCWNvbXBhdGlibGUgPSAic2lyZixh
dGxhczYtYWRjIjsKPiA+ICsJCXJlZyA9IDwweGIwMTEwMDAwIDB4MTAwMDA+
Owo+ID4gKwkJaW50ZXJydXB0cyA9IDwzND47Cj4gPiArCQljbG9ja3MgPSA8
JmNsa3MgMTY+Owo+ID4gKwkJcmVzZXRzID0gPCZyc3RjIDMyPjsKPiA+ICsJ
CSNpby1jaGFubmVsLWNlbGxzID0gPDE+Owo+ID4gKwl9Owo+ID4gZGlmZiAt
LWdpdCBhL2RyaXZlcnMvaWlvL2FkYy9LY29uZmlnIGIvZHJpdmVycy9paW8v
YWRjL0tjb25maWcKPiA+IGluZGV4IGE4MGQyMzYuLjZiODAzZDUgMTAwNjQ0
Cj4gPiAtLS0gYS9kcml2ZXJzL2lpby9hZGMvS2NvbmZpZwo+ID4gKysrIGIv
ZHJpdmVycy9paW8vYWRjL0tjb25maWcKPiA+IEBAIC0xODcsNiArMTg3LDE2
IEBAIGNvbmZpZyBOQVU3ODAyCj4gPiAgCSAgVG8gY29tcGlsZSB0aGlzIGRy
aXZlciBhcyBhIG1vZHVsZSwgY2hvb3NlIE0gaGVyZTogdGhlCj4gPiAgCSAg
bW9kdWxlIHdpbGwgYmUgY2FsbGVkIG5hdTc4MDIuCj4gPiAgCj4gPiArY29u
ZmlnIFNJUkZTT0NfQURDCj4gPiArCXRyaXN0YXRlICJTaVJGU29DIEFEQyIK
PiA+ICsJZGVwZW5kcyBvbiBBUkNIX1NJUkYKPiA+ICsJaGVscAo+ID4gKwkg
IElmIHlvdSBzYXkgeWVzIGhlcmUgeW91IGdldCBzdXBwb3J0IGZvciBDU1Ig
U2lSRlNvQyBpbnRlcm5hbAo+ID4gKwkgIEFEQy4KPiA+ICsKPiA+ICsJICBU
aGlzIGRyaXZlciBjYW4gYWxzbyBiZSBidWlsdCBhcyBhIG1vZHVsZS4gSWYg
c28sIHRoZSBtb2R1bGUgd2lsbCBiZQo+ID4gKwkgIGNhbGxlZCBzaXJmc29j
X2FkYy4KPiA+ICsKPiA+ICBjb25maWcgVElfQURDMDgxQwo+ID4gIAl0cmlz
dGF0ZSAiVGV4YXMgSW5zdHJ1bWVudHMgQURDMDgxQzAyMS8wMjciCj4gPiAg
CWRlcGVuZHMgb24gSTJDCj4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9paW8v
YWRjL01ha2VmaWxlIGIvZHJpdmVycy9paW8vYWRjL01ha2VmaWxlCj4gPiBp
bmRleCA5ZDYwZjJkLi4yOTEyZTU4IDEwMDY0NAo+ID4gLS0tIGEvZHJpdmVy
cy9paW8vYWRjL01ha2VmaWxlCj4gPiArKysgYi9kcml2ZXJzL2lpby9hZGMv
TWFrZWZpbGUKPiA+IEBAIC0yMCw2ICsyMCw3IEBAIG9iai0kKENPTkZJR19N
Q1AzMjBYKSArPSBtY3AzMjB4Lm8KPiA+ICBvYmotJChDT05GSUdfTUNQMzQy
MikgKz0gbWNwMzQyMi5vCj4gPiAgb2JqLSQoQ09ORklHX01FTl9aMTg4X0FE
QykgKz0gbWVuX3oxODhfYWRjLm8KPiA+ICBvYmotJChDT05GSUdfTkFVNzgw
MikgKz0gbmF1NzgwMi5vCj4gPiArb2JqLSQoQ09ORklHX1NJUkZTT0NfQURD
KSArPSBzaXJmc29jX2FkYy5vCj4gPiAgb2JqLSQoQ09ORklHX1RJX0FEQzA4
MUMpICs9IHRpLWFkYzA4MWMubwo+ID4gIG9iai0kKENPTkZJR19USV9BTTMz
NVhfQURDKSArPSB0aV9hbTMzNXhfYWRjLm8KPiA+ICBvYmotJChDT05GSUdf
VFdMNDAzMF9NQURDKSArPSB0d2w0MDMwLW1hZGMubwo+ID4gZGlmZiAtLWdp
dCBhL2RyaXZlcnMvaWlvL2FkYy9zaXJmc29jX2FkYy5jIGIvZHJpdmVycy9p
aW8vYWRjL3NpcmZzb2NfYWRjLmMKPiA+IG5ldyBmaWxlIG1vZGUgMTAwNjQ0
Cj4gPiBpbmRleCAwMDAwMDAwLi5hZTExYTM2Cj4gPiAtLS0gL2Rldi9udWxs
Cj4gPiArKysgYi9kcml2ZXJzL2lpby9hZGMvc2lyZnNvY19hZGMuYwo+ID4g
QEAgLTAsMCArMSw3NTUgQEAKPiA+ICsvKgo+ID4gKyogQURDIERyaXZlciBm
b3IgQ1NSIFNpUkZTb0MKPiA+ICsqCj4gPiArKiBDb3B5cmlnaHQgKGMpIDIw
MTQgQ2FtYnJpZGdlIFNpbGljb24gUmFkaW8gTGltaXRlZCwgYSBDU1IgcGxj
IGdyb3VwIGNvbXBhbnkuCj4gPiArKgo+ID4gKyogTGljZW5zZWQgdW5kZXIg
R1BMdjIuCj4gPiArKi8KPiA+ICsKPiA+ICsjaW5jbHVkZSA8bGludXgvbW9k
dWxlLmg+Cj4gPiArI2luY2x1ZGUgPGxpbnV4L2tlcm5lbC5oPgo+ID4gKyNp
bmNsdWRlIDxsaW51eC9pbml0Lmg+Cj4gPiArI2luY2x1ZGUgPGxpbnV4L2Ns
ay5oPgo+ID4gKyNpbmNsdWRlIDxsaW51eC9pby5oPgo+ID4gKyNpbmNsdWRl
IDxsaW51eC9pbnRlcnJ1cHQuaD4KPiA+ICsjaW5jbHVkZSA8bGludXgvb2Yu
aD4KPiA+ICsjaW5jbHVkZSA8bGludXgvcG0uaD4KPiA+ICsjaW5jbHVkZSA8
bGludXgvcGxhdGZvcm1fZGV2aWNlLmg+Cj4gPiArI2luY2x1ZGUgPGxpbnV4
L29mX3BsYXRmb3JtLmg+Cj4gPiArI2luY2x1ZGUgPGxpbnV4L3Jlc2V0Lmg+
Cj4gPiArI2luY2x1ZGUgPGxpbnV4L3J0Yy9zaXJmc29jX3J0Y2lvYnJnLmg+
Cj4gPiArCj4gPiArI2luY2x1ZGUgPGxpbnV4L2lpby9paW8uaD4KPiA+ICsj
aW5jbHVkZSA8bGludXgvaWlvL21hY2hpbmUuaD4KPiA+ICsjaW5jbHVkZSA8
bGludXgvaWlvL2RyaXZlci5oPgo+ID4gKwo+ID4gKyNkZWZpbmUgRFJJVkVS
X05BTUUgInNpcmZzb2NfYWRjIgo+ID4gKwo+ID4gKyNkZWZpbmUgU0lSRlNP
Q19QV1JfV0FLRUVOX1RTQ19TSElGVAkyMwo+ID4gKyNkZWZpbmUgU0lSRlNP
Q19QV1JfV0FLRUVOX1RTX1NISUZUCTUKPiA+ICsjZGVmaW5lIFNJUkZTT0Nf
UFdSQ19UUklHR0VSX0VOCQkweDgKPiA+ICsjZGVmaW5lIFNJUkZTT0NfUFdS
Q19CQVNFCQkweDMwMDAKPiA+ICsKPiA+ICsvKiBSZWdpc3RlcnMgb2Zmc2V0
ICovCj4gPiArI2RlZmluZSBTSVJGU09DX0FEQ19DT05UUk9MMQkJMHgwMAo+
ID4gKyNkZWZpbmUgU0lSRlNPQ19BRENfQ09OVFJPTDIJCTB4MDQKPiA+ICsj
ZGVmaW5lIFNJUkZTT0NfQURDX0lOVFIJCTB4MDgKPiA+ICsjZGVmaW5lIFNJ
UkZTT0NfQURDX0NPT1JECQkweDBDCj4gPiArI2RlZmluZSBTSVJGU09DX0FE
Q19QUkVTU1VSRQkJMHgxMAo+ID4gKyNkZWZpbmUgU0lSRlNPQ19BRENfQVVY
MQkJMHgxNAo+ID4gKy8qIEF0bGFzNiBBVVgyIGFuZCBBVVg0IHJlc2VydmVk
Ki8KPiBXaGl0ZXNwYWNlIG1pc3NpbmcgYXQgdGhlIGVuZCBvZiB0aGUgY29t
bWVudC4KPiA+ICsjZGVmaW5lIFNJUkZTT0NfQURDX0FVWDIJCTB4MTgKPiA+
ICsjZGVmaW5lIFNJUkZTT0NfQURDX0FVWDMJCTB4MUMKPiA+ICsjZGVmaW5l
IFNJUkZTT0NfQURDX0FVWDQJCTB4MjAKPiA+ICsjZGVmaW5lIFNJUkZTT0Nf
QURDX0FVWDUJCTB4MjQKPiA+ICsjZGVmaW5lIFNJUkZTT0NfQURDX0FVWDYJ
CTB4MjgKPiA+ICsvKiBSZWFkIEJhY2sgY2FsaWJyYXRpb24gcmVnaXN0ZXIg
Ki8KPiA+ICsjZGVmaW5lIFNJUkZTT0NfQURDX0NCCQkJMHgyQwo+ID4gKyNk
ZWZpbmUgU0lSRlNPQ19BRENfQ09PUkQyCQkweDMwCj4gPiArI2RlZmluZSBT
SVJGU09DX0FEQ19DT09SRDMJCTB4MzQKPiA+ICsjZGVmaW5lIFNJUkZTT0Nf
QURDX0NPT1JENAkJMHgzOAo+ID4gKwo+ID4gKy8qIENUUkwxIGRlZmluZXMg
Ki8KPiA+ICsjZGVmaW5lIFNJUkZTT0NfQURDX1JFU0VUX1FVQU5UX0VOCUJJ
VCgyNCkKPiA+ICsjZGVmaW5lIFNJUkZTT0NfQURDX1JTVF9CCQlCSVQoMjMp
Cj4gPiArI2RlZmluZSBTSVJGU09DX0FEQ19SRVNPTFVUSU9OXzEyCUJJVCgy
MikKPiA+ICsjZGVmaW5lIFNJUkZTT0NfQURDX1JCQVRfRElTQUJMRQkoMHgw
IDw8IDIxKQo+ID4gKyNkZWZpbmUgU0lSRlNPQ19BRENfUkJBVF9FTkFCTEUJ
CSgweDEgPDwgMjEpCj4gQklUKDIxKSB0byBrZWVwIGl0IGNvbnNpdGVudC4K
PiA+ICsjZGVmaW5lIFNJUkZTT0NfQURDX0VYVENNKHgpCQkoKCh4KSAmIDB4
MykgPDwgMTkpCj4gPiArI2RlZmluZSBTSVJGU09DX0FEQ19TR0FJTih4KQkJ
KCgoeCkgJiAweDcpIDw8IDE2KQo+ID4gKyNkZWZpbmUgU0lSRlNPQ19BRENf
UE9MTAkJQklUKDE1KQo+ID4gKyNkZWZpbmUgU0lSRlNPQ19BRENfU0VMKHgp
CQkoKCh4KSAmIDB4RikgPDwgMTEpCj4gPiArI2RlZmluZSBTSVJGU09DX0FE
Q19GUkVRXzZLCQkoMHgwIDw8IDgpCj4gPiArI2RlZmluZSBTSVJGU09DX0FE
Q19GUkVRXzEzSwkJQklUKDgpCj4gPiArI2RlZmluZSBTSVJGU09DX0FEQ19E
RUxfU0VUKHgpCQkoKCh4KSAmIDB4RikgPDwgNCkKPiA+ICsjZGVmaW5lIFNJ
UkZTT0NfQURDX1RQX1RJTUUoeCkJCSgoKHgpICYgMHg3KSA8PCAwKQo+ID4g
Kwo+ID4gKy8qIENUUkwyIGRlZmluZXMgKi8KPiA+ICsvKiBQZW4gZGV0ZWN0
b3Igb2ZmLCBkaWdpdGl6ZXIgb2ZmICovCj4gPiArI2RlZmluZSBTSVJGU09D
X0FEQ19QUlBfTU9ERTAJCSgwIDw8IDE0KQo+ID4gKy8qIFBlbiBkZXRlY3Rv
ciBvbiwgZGlnaXRpemVyIG9mZiwgZGlnaXRpemVyIHdha2VzIHVwIG9uIHBl
biBkZXRlY3QgKi8KPiA+ICsjZGVmaW5lIFNJUkZTT0NfQURDX1BSUF9NT0RF
MQkJQklUKDE0KQo+ID4gKy8qIFBlbiBkZXRlY3RvciBvbiwgZGlnaXRpemVy
IG9mZiwgbm8gd2FrZSB1cCBvbiBwZW4gZGV0ZWN0ICovCj4gPiArI2RlZmlu
ZSBTSVJGU09DX0FEQ19QUlBfTU9ERTIJCSgyIDw8IDE0KQo+ID4gKy8qIFBl
biBkZXRlY3RvciBvbiwgZGlnaXRpemVyIG9uICovCj4gPiArI2RlZmluZSBT
SVJGU09DX0FEQ19QUlBfTU9ERTMJCSgzIDw8IDE0KQo+ID4gKyNkZWZpbmUg
U0lSRlNPQ19BRENfUlRPVUNIKHgpCQkoKCh4KSAmIDB4MykgPDwgMTIpCj4g
PiArI2RlZmluZSBTSVJGU09DX0FEQ19ERUxfUFJFKHgpCQkoKCh4KSAmIDB4
RikgPDwgNCkKPiA+ICsjZGVmaW5lIFNJUkZTT0NfQURDX0RFTF9ESVMoeCkJ
CSgoKHgpICYgMHhGKSA8PCAwKQo+ID4gKwo+ID4gKy8qIElOVFIgcmVnaXN0
ZXIgZGVmaW5lcyAqLwo+ID4gKyNkZWZpbmUgU0lSRlNPQ19BRENfUEVOX0lO
VFJfRU4JCUJJVCg1KQo+ID4gKyNkZWZpbmUgU0lSRlNPQ19BRENfREFUQV9J
TlRSX0VOCUJJVCg0KQo+ID4gKyNkZWZpbmUgU0lSRlNPQ19BRENfUEVOX0lO
VFIJCUJJVCgxKQo+ID4gKyNkZWZpbmUgU0lSRlNPQ19BRENfREFUQV9JTlRS
CQlCSVQoMCkKPiA+ICsKPiA+ICsvKiBEQVRBIHJlZ2lzdGVyIGRlZmluZXMg
Ki8KPiA+ICsjZGVmaW5lIFNJUkZTT0NfQURDX1BFTl9ET1dOCQlCSVQoMzEp
Cj4gPiArI2RlZmluZSBTSVJGU09DX0FEQ19EQVRBX0FVWFZBTElECUJJVCgz
MCkKPiA+ICsjZGVmaW5lIFNJUkZTT0NfQURDX0RBVEFfQ0JfVkFMSUQJQklU
KDMwKQo+ID4gKyNkZWZpbmUgU0lSRlNPQ19BRENfQURDX0RBVEFfTUFTSyh4
KQkoMHgzRkZGIDw8ICh4KSkKPiA+ICsjZGVmaW5lIFNJUkZTT0NfQURDX0RB
VEFfQVVYTUFTSwlTSVJGU09DX0FEQ19BRENfREFUQV9NQVNLKDApCj4gPiAr
I2RlZmluZSBTSVJGU09DX0FEQ19EQVRBX0NCTUFTSwkJU0lSRlNPQ19BRENf
QURDX0RBVEFfTUFTSygwKQo+ID4gKwo+ID4gKyNkZWZpbmUgU0lSRlNPQ19B
RENfTU9SRV9DVEwxCShvZl9tYWNoaW5lX2lzX2NvbXBhdGlibGUoInNpcmYs
YXRsYXM2IikgP1wKPiA+ICsJCQkJKFNJUkZTT0NfQURDX1JFU0VUX1FVQU5U
X0VOIHxcCj4gPiArCQkJCVNJUkZTT0NfQURDX1JTVF9CKSA6ICgwKSkKPiA+
ICsKPiA+ICsvKiBTZWxlY3QgQUQgc2FtcGxlcyB0byByZWFkIChTRUwgYml0
cyBpbiBBRENfQ09OVFJPTDEgcmVnaXN0ZXIpICovCj4gPiArI2RlZmluZSBT
SVJGU09DX0FEQ19BVVgxX1NFTAkweDA0Cj4gPiArI2RlZmluZSBTSVJGU09D
X0FEQ19BVVgyX1NFTAkweDA1Cj4gPiArI2RlZmluZSBTSVJGU09DX0FEQ19B
VVgzX1NFTAkweDA2Cj4gPiArI2RlZmluZSBTSVJGU09DX0FEQ19BVVg0X1NF
TAkweDA3Cj4gPiArI2RlZmluZSBTSVJGU09DX0FEQ19BVVg1X1NFTAkweDA4
Cj4gPiArI2RlZmluZSBTSVJGU09DX0FEQ19BVVg2X1NFTAkweDA5Cj4gPiAr
I2RlZmluZSBTSVJGU09DX0FEQ19UU19TRUwJMHgwQSAgICAvKiBTYW1wbGUg
Zm9yIHNpbmdsZSB0b3VjaCovCj4gPiArI2RlZmluZSBTSVJGU09DX0FEQ19H
Uk9VTkRfU0VMCTB4MEIgICAgLyogR291bmQgZm9yIG9mZnNldCBjYWxpYnJh
dGlvbiAqLwo+IEdyb3VuZAo+ID4gKyNkZWZpbmUgU0lSRlNPQ19BRENfQkFO
REdBUF9TRUwJMHgwQyAgICAvKiBCYW5kZ2FwIGZvciBnYWluIGNhbGlicmF0
aW9uICovCj4gPiArI2RlZmluZSBTSVJGU09DX0FEQ19UU19TRUxfRFVBTAkw
eDBGICAgIC8qIFNhbXBsZXMgZm9yIGR1YWwgdG91Y2ggKi8KPiA+ICsKPiA+
ICsjZGVmaW5lIFNJUkZTT0NfQURDX1RTX1NBTVBMRV9TSVpFCTQKPiA+ICsj
ZGVmaW5lIFNJUkZTT0NfQURDX0NUTDEoc2VsKSAgICAoU0lSRlNPQ19BRENf
UE9MTCB8IFNJUkZTT0NfQURDX1NFTChzZWwpIHxcCj4gPiArCQlTSVJGU09D
X0FEQ19ERUxfU0VUKDYpIHwgU0lSRlNPQ19BRENfRlJFUV82SyB8XAo+ID4g
KwkJU0lSRlNPQ19BRENfVFBfVElNRSgwKSB8IFNJUkZTT0NfQURDX1NHQUlO
KDApIHxcCj4gPiArCQlTSVJGU09DX0FEQ19FWFRDTSgwKSB8IFNJUkZTT0Nf
QURDX1JCQVRfRElTQUJMRSB8XAo+ID4gKwkJU0lSRlNPQ19BRENfTU9SRV9D
VEwxKQo+ID4gKwo+ID4gK2VudW0gc2lyZnNvY19hZGNfY2hpcHMgewo+ID4g
KwlQUklNQTIsCj4gPiArCUFUTEFTNiwKPiA+ICt9Owo+ID4gKwo+ID4gK3N0
cnVjdCBzaXJmc29jX2FkY19jaGlwX2luZm8gewo+ID4gKwljb25zdCBzdHJ1
Y3QgaWlvX2NoYW5fc3BlYyAqY2hhbm5lbHM7Cj4gPiArCXVuc2lnbmVkIGlu
dCBudW1fY2hhbm5lbHM7Cj4gPiArCXVuc2lnbmVkIGludCBmbGFnczsKPiA+
ICsJY29uc3Qgc3RydWN0IGlpb19pbmZvICppaW9faW5mbzsKPiA+ICsKPiA+
ICsJdTMyICgqY2FsY3VsYXRlX3ZvbHQpKHUzMiwgdTMyLCB1MzIpOwo+ID4g
Kwljb25zdCB1MzIgKmNoYW5uZWxfc2VsOwo+ID4gK307Cj4gPiArCj4gPiAr
c3RydWN0IHNpcmZzb2NfYWRjX3JlcXVlc3Qgewo+ID4gKwl1MTYgbW9kZTsK
PiA+ICsJdTE2IGV4dGNtOwo+ID4gKwl1MTYgcmVmZXJlbmNlOwo+ID4gKwl1
OCBkZWxheV9iaXRzOwo+ID4gKwl1MzIgc19nYWluX2JpdHM7Cj4gPiArCXUx
NiByZWFkX2JhY2tfZGF0YTsKPiA+ICt9Owo+ID4gKwo+ID4gK3N0cnVjdCBz
aXJmc29jX2FkYyB7Cj4gPiArCWNvbnN0IHN0cnVjdCBzaXJmc29jX2FkY19j
aGlwX2luZm8JKmNoaXBfaW5mbzsKPiA+ICsJc3RydWN0IGNsawkqY2xrOwo+
ID4gKwl2b2lkIF9faW9tZW0JKmJhc2U7Cj4gPiArCXN0cnVjdCBzaXJmc29j
X2FkY19yZXF1ZXN0IHJlcTsKPiA+ICsJc3RydWN0IGNvbXBsZXRpb24JZG9u
ZTsKPiA+ICsJc3RydWN0IG11dGV4CWFkY19sb2NrOwo+ID4gK307Cj4gPiAr
Cj4gPiArc3RhdGljIGNvbnN0IHUzMiBzaXJmc29jX2FkY190c19yZWdbU0lS
RlNPQ19BRENfVFNfU0FNUExFX1NJWkVdID0gewo+ID4gKwkvKiBEdWFsIHRv
dWNoIHNhbXBsZXMgcmVhZCByZWdpc3RlcnMqLwo+ID4gKwlTSVJGU09DX0FE
Q19DT09SRCwgU0lSRlNPQ19BRENfQ09PUkQyLAo+ID4gKwlTSVJGU09DX0FE
Q19DT09SRDMsIFNJUkZTT0NfQURDX0NPT1JENAo+ID4gK307Cj4gPiArCj4g
PiArZW51bSBzaXJmc29jX2FkY190c190eXBlIHsKPiA+ICsJU0lOR0xFX1RP
VUNILAo+ID4gKwlEVUFMX1RPVUNILAo+ID4gK307Cj4gPiArCj4gPiArc3Rh
dGljIGludCBzaXJmc29jX2FkY19nZXRfdHNfc2FtcGxlKAo+ID4gKwlzdHJ1
Y3Qgc2lyZnNvY19hZGMgKmFkYywgaW50ICpzYW1wbGUsIGludCB0b3VjaF90
eXBlKQo+IFRoZSBmaXJzdCB0d28gcGFyYW1ldGVycyBmaXQgaW50byB0aGUg
Zmlyc3QgbGluZSwgdGhlIHRoaXJkIG9uZSBzaG91bGQgYmUgYWxpZ25lZCB3
aXRoIHRoZSBvcGVuaW5nIHBhcmVudGhlc2lzLgo+ID4gK3sKPiA+ICsJaW50
IGFkY19pbnRyOwo+ID4gKwlpbnQgcmV0ID0gMDsKPiA+ICsJaW50IGk7Cj4g
PiArCj4gPiArCW11dGV4X2xvY2soJmFkYy0+YWRjX2xvY2spOwo+ID4gKwlh
ZGNfaW50ciA9IHJlYWRsKGFkYy0+YmFzZSArIFNJUkZTT0NfQURDX0lOVFIp
Owo+ID4gKwlpZiAoYWRjX2ludHIgJiBTSVJGU09DX0FEQ19QRU5fSU5UUikK
PiA+ICsJCXdyaXRlbChTSVJGU09DX0FEQ19QRU5fSU5UUiB8IFNJUkZTT0Nf
QURDX1BFTl9JTlRSX0VOIHwKPiA+ICsJCQlTSVJGU09DX0FEQ19EQVRBX0lO
VFJfRU4sCj4gPiArCQkJYWRjLT5iYXNlICsgU0lSRlNPQ19BRENfSU5UUik7
Cj4gPiArCj4gPiArCS8qIGNoZWNrIHBlbiBzdGF0dXMgKi8KPiA+ICsJaWYg
KCEocmVhZGwoYWRjLT5iYXNlICsgU0lSRlNPQ19BRENfQ09PUkQpICYgU0lS
RlNPQ19BRENfUEVOX0RPV04pKSB7Cj4gPiArCQlyZXQgPSAtRUlOVkFMOwo+
ID4gKwkJZ290byBvdXQ7Cj4gPiArCX0KPiA+ICsKPiA+ICsJaWYgKFNJTkdM
RV9UT1VDSCA9PSB0b3VjaF90eXBlKQo+ID4gKwkJd3JpdGVsKFNJUkZTT0Nf
QURDX0NUTDEoU0lSRlNPQ19BRENfVFNfU0VMKSwKPiA+ICsJCQlhZGMtPmJh
c2UgKyBTSVJGU09DX0FEQ19DT05UUk9MMSk7Cj4gPiArCWVsc2UKPiA+ICsJ
CXdyaXRlbChTSVJGU09DX0FEQ19DVEwxKFNJUkZTT0NfQURDX1RTX1NFTF9E
VUFMKSwKPiA+ICsJCQlhZGMtPmJhc2UgKyBTSVJGU09DX0FEQ19DT05UUk9M
MSk7Cj4gPiArCj4gPiArCWlmICghd2FpdF9mb3JfY29tcGxldGlvbl90aW1l
b3V0KCZhZGMtPmRvbmUsCj4gPiArCQltc2Vjc190b19qaWZmaWVzKDUwKSkp
IHsKPiBEb24ndCBzcGxpdCBpdCBpbnRvIDIgbGluZXMgKHdpdGggbWlzbGVh
ZGluZyBpbmRlbnRhdGlvbiksIGl0IHBlcmZlY3RseSBmaXRzIGludG8gb25l
IGxpbmUuCj4gPiArCQlyZXQgPSAtRUlPOwo+ID4gKwkJZ290byBvdXQ7Cj4g
PiArCX0KPiA+ICsKPiA+ICsJaWYgKFNJTkdMRV9UT1VDSCA9PSB0b3VjaF90
eXBlKQo+ID4gKwkJKnNhbXBsZSA9IHJlYWRsKGFkYy0+YmFzZSArIFNJUkZT
T0NfQURDX0NPT1JEKTsKPiA+ICsJZWxzZQo+ID4gKwkJZm9yIChpID0gMDsg
aSA8IFNJUkZTT0NfQURDX1RTX1NBTVBMRV9TSVpFOyBpKyspCj4gPiArCQkJ
c2FtcGxlW2ldID0gcmVhZGwoYWRjLT5iYXNlICsgc2lyZnNvY19hZGNfdHNf
cmVnW2ldKTsKPiA+ICsKPiA+ICtvdXQ6Cj4gPiArCW11dGV4X3VubG9jaygm
YWRjLT5hZGNfbG9jayk7Cj4gPiArCXJldHVybiByZXQ7Cj4gPiArfQo+ID4g
Kwo+ID4gKy8qIGdldCB0b3VjaHNjcmVlbiBjb29yZGluYXRlcyBmb3Igc2lu
Z2xlIHRvdWNoICovCj4gPiArc3RhdGljIGludCBzaXJmc29jX2FkY19zaW5n
bGVfdHNfc2FtcGxlKHN0cnVjdCBzaXJmc29jX2FkYyAqYWRjLCBpbnQgKnNh
bXBsZSkKPiA+ICt7Cj4gPiArCXJldHVybiBzaXJmc29jX2FkY19nZXRfdHNf
c2FtcGxlKGFkYywgc2FtcGxlLCBTSU5HTEVfVE9VQ0gpOwo+ID4gK30KPiA+
ICsKPiA+ICsvKiBnZXQgdG91Y2hzY3JlZW4gY29vcmRpbmF0ZXMgZm9yIGR1
YWwgdG91Y2ggKi8KPiA+ICtzdGF0aWMgaW50IHNpcmZzb2NfYWRjX2R1YWxf
dHNfc2FtcGxlKHN0cnVjdCBzaXJmc29jX2FkYyAqYWRjLCBpbnQgKnNhbXBs
ZXMpCj4gPiArewo+ID4gKwlyZXR1cm4gc2lyZnNvY19hZGNfZ2V0X3RzX3Nh
bXBsZShhZGMsIHNhbXBsZXMsIERVQUxfVE9VQ0gpOwo+ID4gK30KPiA+ICsK
PiA+ICtzdGF0aWMgaW50IHNpcmZzb2NfYWRjX3NlbmRfcmVxdWVzdChzdHJ1
Y3Qgc2lyZnNvY19hZGNfcmVxdWVzdCAqcmVxKQo+ID4gK3sKPiA+ICsJc3Ry
dWN0IHNpcmZzb2NfYWRjICphZGMgPSBjb250YWluZXJfb2YocmVxLCBzdHJ1
Y3Qgc2lyZnNvY19hZGMsIHJlcSk7Cj4gPiArCWludCBjb250cm9sMSwgY29u
dHJvbDIsIGludHI7Cj4gPiArCWludCBkYXRhLCByZWdfb2Zmc2V0Owo+ID4g
KwlpbnQgcmV0ID0gMDsKPiA+ICsKPiA+ICsJbXV0ZXhfbG9jaygmYWRjLT5h
ZGNfbG9jayk7Cj4gPiArCj4gPiArCS8qIFN0b3JlIHJlZ2lzdGVycyBmb3Ig
cmVjb3ZlciAqLwo+ID4gKwlpbnRyID0gcmVhZGwoYWRjLT5iYXNlICsgU0lS
RlNPQ19BRENfSU5UUik7Cj4gPiArCWNvbnRyb2wxID0gcmVhZGwoYWRjLT5i
YXNlICsgU0lSRlNPQ19BRENfQ09OVFJPTDEpOwo+ID4gKwljb250cm9sMiA9
IHJlYWRsKGFkYy0+YmFzZSArIFNJUkZTT0NfQURDX0NPTlRST0wyKTsKPiA+
ICsKPiA+ICsJd3JpdGVsKGludHIgfCBTSVJGU09DX0FEQ19EQVRBX0lOVFJf
RU4gfCBTSVJGU09DX0FEQ19EQVRBX0lOVFIsCj4gPiArCQlhZGMtPmJhc2Ug
KyBTSVJGU09DX0FEQ19JTlRSKTsKPiA+ICsJd3JpdGVsKFNJUkZTT0NfQURD
X1BSUF9NT0RFMyB8IHJlcS0+cmVmZXJlbmNlLAo+ID4gKwkJYWRjLT5iYXNl
ICsgU0lSRlNPQ19BRENfQ09OVFJPTDIpOwo+ID4gKwl3cml0ZWwoU0lSRlNP
Q19BRENfUE9MTCB8IFNJUkZTT0NfQURDX01PUkVfQ1RMMSB8IHJlcS0+bW9k
ZSB8Cj4gPiArCQlyZXEtPmV4dGNtIHwgcmVxLT5kZWxheV9iaXRzIHwgU0lS
RlNPQ19BRENfUkVTT0xVVElPTl8xMiwKPiA+ICsJCWFkYy0+YmFzZSArIFNJ
UkZTT0NfQURDX0NPTlRST0wxKTsKPiA+ICsKPiA+ICsJaWYgKCF3YWl0X2Zv
cl9jb21wbGV0aW9uX3RpbWVvdXQoJmFkYy0+ZG9uZSwKPiA+ICsJCW1zZWNz
X3RvX2ppZmZpZXMoNTApKSkgewo+IE9uZSBsaW5lLgo+ID4gKwkJcmV0ID0g
LUVJTzsKPiA+ICsJCWdvdG8gb3V0Owo+ID4gKwl9Cj4gPiArCj4gPiArCXN3
aXRjaCAocmVxLT5tb2RlKSB7Cj4gPiArCWNhc2UgU0lSRlNPQ19BRENfU0VM
KFNJUkZTT0NfQURDX0FVWDFfU0VMKToKPiA+ICsJY2FzZSBTSVJGU09DX0FE
Q19TRUwoU0lSRlNPQ19BRENfQVVYMl9TRUwpOgo+ID4gKwljYXNlIFNJUkZT
T0NfQURDX1NFTChTSVJGU09DX0FEQ19BVVgzX1NFTCk6Cj4gPiArCWNhc2Ug
U0lSRlNPQ19BRENfU0VMKFNJUkZTT0NfQURDX0FVWDRfU0VMKToKPiA+ICsJ
Y2FzZSBTSVJGU09DX0FEQ19TRUwoU0lSRlNPQ19BRENfQVVYNV9TRUwpOgo+
ID4gKwljYXNlIFNJUkZTT0NfQURDX1NFTChTSVJGU09DX0FEQ19BVVg2X1NF
TCk6Cj4gPiArCQkvKiBDYWxjdWxhdGUgYXV4IG9mZnNldCBmcm9tIG1vZGUg
Ki8KPiA+ICsJCXJlZ19vZmZzZXQgPSAweDE0ICsgKChyZXEtPm1vZGUgPj4g
MTEpIC0gMHgwNCkgKiA0Owo+ID4gKwkJZGF0YSA9IHJlYWRsKGFkYy0+YmFz
ZSArIHJlZ19vZmZzZXQpOwo+ID4gKwkJaWYgKGRhdGEgJiBTSVJGU09DX0FE
Q19EQVRBX0FVWFZBTElEKQo+ID4gKwkJCXJlcS0+cmVhZF9iYWNrX2RhdGEg
PSBkYXRhICYgU0lSRlNPQ19BRENfREFUQV9BVVhNQVNLOwo+ID4gKwkJYnJl
YWs7Cj4gPiArCWNhc2UgU0lSRlNPQ19BRENfU0VMKFNJUkZTT0NfQURDX0dS
T1VORF9TRUwpOgo+ID4gKwljYXNlIFNJUkZTT0NfQURDX1NFTChTSVJGU09D
X0FEQ19CQU5ER0FQX1NFTCk6Cj4gPiArCQlyZWdfb2Zmc2V0ID0gU0lSRlNP
Q19BRENfQ0I7Cj4gPiArCQlkYXRhID0gcmVhZGwoYWRjLT5iYXNlICsgcmVn
X29mZnNldCk7Cj4gPiArCQlpZiAoZGF0YSAmIFNJUkZTT0NfQURDX0RBVEFf
Q0JfVkFMSUQpCj4gPiArCQkJcmVxLT5yZWFkX2JhY2tfZGF0YSA9IGRhdGEg
JiBTSVJGU09DX0FEQ19EQVRBX0NCTUFTSzsKPiA+ICsJCWJyZWFrOwo+ID4g
KwlkZWZhdWx0Ogo+ID4gKwkJYnJlYWs7Cj4gWW91IG1heSB3YW50IHRvIHB1
dCByZXQgPSAtRUlOVkFMIGludG8gdGhlIGRlZmF1bHQgc2VjdGlvbiwgb3Ig
ZHJvcCBpdCBjb21wbGV0ZWx5Lgo+ID4gKwl9Cj4gPiArCj4gPiArb3V0Ogo+
ID4gKwl3cml0ZWwoaW50ciwgYWRjLT5iYXNlICsgU0lSRlNPQ19BRENfSU5U
Uik7Cj4gPiArCXdyaXRlbChjb250cm9sMSwgYWRjLT5iYXNlICsgU0lSRlNP
Q19BRENfQ09OVFJPTDEpOwo+ID4gKwl3cml0ZWwoY29udHJvbDIsIGFkYy0+
YmFzZSArIFNJUkZTT0NfQURDX0NPTlRST0wyKTsKPiA+ICsJbXV0ZXhfdW5s
b2NrKCZhZGMtPmFkY19sb2NrKTsKPiA+ICsJcmV0dXJuIHJldDsKPiA+ICt9
Cj4gPiArCj4gPiArLyogU3RvcmUgcGFyYW1zIHRvIGNhbGlicmF0ZSAqLwo+
ID4gK3N0cnVjdCBzaXJmc29jX2FkY19jYWxpX2RhdGEgewo+ID4gKwl1MzIg
ZGlnaXRhbF9vZmZzZXQ7Cj4gPiArCXUzMiBkaWdpdGFsX2FnYWluOwo+ID4g
Kwlib29sIGlzX2NhbGlicmF0aW9uOwo+ID4gK307Cj4gPiArCj4gPiArLyog
T2Zmc2V0IENhbGlicmF0aW9uIGNhbGlicmF0ZXMgdGhlIEFEQyBvZmZzZXQg
ZXJyb3IgKi8KPiA+ICtzdGF0aWMgdTMyIHNpcmZzb2NfYWRjX29mZnNldF9j
YWxpKHN0cnVjdCBzaXJmc29jX2FkY19yZXF1ZXN0ICpyZXEpCj4gPiArewo+
ID4gKwl1MzIgaSwgZGlnaXRhbF9vZmZzZXQgPSAwLCBjb3VudCA9IDAsIHN1
bSA9IDA7Cj4gPiArCS8qIFRvIHNldCB0aGUgcmVnaXN0ZXJzIGluIG9yZGVy
IHRvIGdldCB0aGUgQURDIG9mZnNldCAqLwo+ID4gKwlyZXEtPm1vZGUgPSBT
SVJGU09DX0FEQ19TRUwoU0lSRlNPQ19BRENfR1JPVU5EX1NFTCk7Cj4gPiAr
CXJlcS0+ZXh0Y20gPSBTSVJGU09DX0FEQ19FWFRDTSgwKTsKPiByZXEtPmV4
dGNtIGlzIG9mIHR5cGUgdTE2LCBidXQgU0lSRlNPQ19BRENfRVhUQ00gZG9l
cyBhIGxlZnQtc2hpZnQgb2YgYSB0d28gYml0IHZhbHVlIGJ5IDE5IGJpdHMu
IFRoYXQgZG9lcyBub3QgZml0IHByb3Blcmx5Lgo+ID4gKwlyZXEtPnNfZ2Fp
bl9iaXRzID0gU0lSRlNPQ19BRENfU0dBSU4oNyk7Cj4gPiArCXJlcS0+ZGVs
YXlfYml0cyA9IFNJUkZTT0NfQURDX0RFTF9TRVQoNCk7Cj4gPiArCj4gPiAr
CWZvciAoaSA9IDA7IGkgPCAxMDsgaSsrKSB7Cj4gPiArCQlpZiAoc2lyZnNv
Y19hZGNfc2VuZF9yZXF1ZXN0KHJlcSkpCj4gPiArCQkJYnJlYWs7Cj4gPiAr
CQlkaWdpdGFsX29mZnNldCA9IHJlcS0+cmVhZF9iYWNrX2RhdGE7Cj4gPiAr
CQlzdW0gKz0gZGlnaXRhbF9vZmZzZXQ7Cj4gPiArCQljb3VudCsrOwo+ID4g
Kwl9Cj4gPiArCWlmICghY291bnQpCj4gPiArCQlkaWdpdGFsX29mZnNldCA9
IDA7Cj4gPiArCWVsc2UKPiA+ICsJCWRpZ2l0YWxfb2Zmc2V0ID0gc3VtIC8g
Y291bnQ7Cj4gPiArCj4gPiArCXJldHVybiBkaWdpdGFsX29mZnNldDsKPiA+
ICt9Cj4gPiArCj4gPiArCj4gPiArLyogR2FpbiBDYWxpYnJhdGlvbiBjYWxp
YnJhdGVzIHRoZSBBREMgZ2FpbiBlcnJvciAqLwo+ID4gK3N0YXRpYyB1MzIg
c2lyZnNvY19hZGNfZ2Fpbl9jYWxpKHN0cnVjdCBzaXJmc29jX2FkY19yZXF1
ZXN0ICpyZXEpCj4gPiArewo+ID4gKwl1MzIgaSwgZGlnaXRhbF9nYWluID0g
MCwgY291bnQgPSAwLCBzdW0gPSAwOwo+ID4gKwkvKiBUbyBzZXQgdGhlIHJl
Z2lzdGVycyBpbiBvcmRlciB0byBnZXQgdGhlIEFEQyBnYWluICovCj4gPiAr
CXJlcS0+bW9kZSA9IFNJUkZTT0NfQURDX1NFTChTSVJGU09DX0FEQ19CQU5E
R0FQX1NFTCk7Cj4gPiArCXJlcS0+ZXh0Y20gPSBTSVJGU09DX0FEQ19FWFRD
TSgwKTsKPiA+ICsJcmVxLT5zX2dhaW5fYml0cyA9IFNJUkZTT0NfQURDX1NH
QUlOKDEpOwo+ID4gKwlyZXEtPmRlbGF5X2JpdHMgPSBTSVJGU09DX0FEQ19E
RUxfU0VUKDQpOwo+ID4gKwo+ID4gKwlmb3IgKGkgPSAwOyBpIDwgMTA7IGkr
Kykgewo+ID4gKwkJaWYgKHNpcmZzb2NfYWRjX3NlbmRfcmVxdWVzdChyZXEp
KQo+ID4gKwkJCWJyZWFrOwo+ID4gKwkJZGlnaXRhbF9nYWluID0gcmVxLT5y
ZWFkX2JhY2tfZGF0YTsKPiA+ICsJCXN1bSArPSBkaWdpdGFsX2dhaW47Cj4g
PiArCQljb3VudCsrOwo+ID4gKwl9Cj4gPiArCWlmICghY291bnQpCj4gPiAr
CQlkaWdpdGFsX2dhaW4gPSAwOwo+ID4gKwllbHNlCj4gPiArCQlkaWdpdGFs
X2dhaW4gPSBzdW0gLyBjb3VudDsKPiA+ICsKPiA+ICsJcmV0dXJuIGRpZ2l0
YWxfZ2FpbjsKPiA+ICt9Cj4gPiArCj4gVGhvc2UgdHdvIGZ1bmN0aW9ucyBh
cmUgYXBhcnQgb2Ygc2V0dGluZyBkaWZmZXJlbnQgdmFsdWVzIHRvIHJlcS0+
bW9kZSBhbmQgcmVxLT5zX2dhaW5fYml0cyB0b3RhbGx5IGVxdWFsLiBJdCB3
b3VsZCBtYWtlIHNlbnNlIHRvIGNvbnNvbGlkYXRlIHRoZW0gaW50byBvbmUg
ZnVuY3Rpb24gd2l0aCBhbiBhZGRpdGlvbmFsIHBhcmFtZXRlciBzcGVjaWZ5
aW5nIHdlYXRoZXIgdG8gZG8gZ2FpbiBvciBvZmZzZXQgY2FsaWJyYXRpb24u
Cj4gPiArLyogQWJzb2x1dGUgZ2FpbiBjYWxpYnJhdGlvbiAqLwo+ID4gK3N0
YXRpYyBpbnQgc2lyZnNvY19hZGNfYWRjX2NhbGkoc3RydWN0IHNpcmZzb2Nf
YWRjX3JlcXVlc3QgKnJlcSwKPiA+ICsJCQkJc3RydWN0IHNpcmZzb2NfYWRj
X2NhbGlfZGF0YSAqY2FsaV9kYXRhKQo+ID4gK3sKPiA+ICsJY2FsaV9kYXRh
LT5kaWdpdGFsX29mZnNldCA9IHNpcmZzb2NfYWRjX29mZnNldF9jYWxpKHJl
cSk7Cj4gPiArCWlmICghY2FsaV9kYXRhLT5kaWdpdGFsX29mZnNldCkKPiA+
ICsJCXJldHVybiAtRUlOVkFMOwo+ID4gKwljYWxpX2RhdGEtPmRpZ2l0YWxf
YWdhaW4gPSBzaXJmc29jX2FkY19nYWluX2NhbGkocmVxKTsKPiA+ICsJaWYg
KCFjYWxpX2RhdGEtPmRpZ2l0YWxfYWdhaW4pCj4gPiArCQlyZXR1cm4gLUVJ
TlZBTDsKPiA+ICsKPiA+ICsJcmV0dXJuIDA7Cj4gPiArfQo+ID4gKwo+ID4g
Ky8qIEdldCB2b2x0YWdlIGFmdGVyIEFEQyBjb252ZXJzaW9uICovCj4gPiAr
c3RhdGljIHUzMiBzaXJmc29jX2FkY19nZXRfYWRjX3ZvbHQoc3RydWN0IHNp
cmZzb2NfYWRjICphZGMsCj4gPiArCQkJCXN0cnVjdCBzaXJmc29jX2FkY19j
YWxpX2RhdGEgKmNhbGlfZGF0YSkKPiA+ICt7Cj4gPiArCXUzMiBkaWdpdGFs
X291dCwgdm9sdDsKPiA+ICsJc3RydWN0IHNpcmZzb2NfYWRjX3JlcXVlc3Qg
KnJlcSA9ICZhZGMtPnJlcTsKPiA+ICsKPiA+ICsJcmVxLT5zX2dhaW5fYml0
cyA9IFNJUkZTT0NfQURDX1NHQUlOKDApOwo+ID4gKwlyZXEtPmRlbGF5X2Jp
dHMgPSBTSVJGU09DX0FEQ19ERUxfU0VUKDQpOwo+ID4gKwo+ID4gKwkvKgo+
ID4gKwkgKiBGaXJzdCByZWFkIG9yaWdpbmFsIGRhdGEKPiA+ICsJICogdGhl
biByZWFkIGNhbGlicmF0ZSBlcnJvcnMKPiA+ICsJICovCj4gPiArCXNpcmZz
b2NfYWRjX3NlbmRfcmVxdWVzdChyZXEpOwo+ID4gKwlpZiAocmVxLT5yZWFk
X2JhY2tfZGF0YSkgewo+ID4gKwkJZGlnaXRhbF9vdXQgPSByZXEtPnJlYWRf
YmFja19kYXRhOwo+ID4gKwkJLyogR2V0IGVycm9ycyBmb3IgZWFjaCBzYW1w
bGUgKi8KPiA+ICsJCWlmICghY2FsaV9kYXRhLT5pc19jYWxpYnJhdGlvbikg
ewo+ID4gKwkJCWlmIChzaXJmc29jX2FkY19hZGNfY2FsaShyZXEsIGNhbGlf
ZGF0YSkpCj4gPiArCQkJCXJldHVybiAwOwo+ID4gKwkJCWNhbGlfZGF0YS0+
aXNfY2FsaWJyYXRpb24gPSB0cnVlOwo+ID4gKwkJfQo+ID4gKwo+ID4gKwkJ
dm9sdCA9IGFkYy0+Y2hpcF9pbmZvLT5jYWxjdWxhdGVfdm9sdChkaWdpdGFs
X291dCwKPiA+ICsJCQljYWxpX2RhdGEtPmRpZ2l0YWxfb2Zmc2V0LAo+ID4g
KwkJCWNhbGlfZGF0YS0+ZGlnaXRhbF9hZ2Fpbik7Cj4gSW5kZW50IHBhcmFt
ZXRlcnMgd2l0aCBwYXJlbnRoZXNpcy4gQWxzbywgeW91IGNhbiBkcm9wIHRo
ZSB2YXJpYWJsZSB2b2x0IGFuZCBkaXJlY3RseSByZXR1cm4gdGhlIHZhbHVl
IGhlcmUuCj4gPiArCX0gZWxzZSB7Cj4gPiArCQlyZXR1cm4gMDsKPiA+ICsJ
fQo+ID4gKwo+ID4gKwlyZXR1cm4gdm9sdDsKPiA+ICt9Cj4gPiArCj4gPiAr
c3RhdGljIHUzMiBwcmltYTJfYWRjX2NhbGN1bGF0ZV92b2x0KHUzMiBkaWdp
dGFsX291dCwKPiA+ICsJCQkJdTMyIGRpZ2l0YWxfb2Zmc2V0LCB1MzIgZGln
aXRhbF9hZ2FpbikKPiA+ICt7Cj4gPiArCXUzMiB2b2x0LCBkaWdpdGFsX2lk
ZWFsLCBkaWdpdGFsX2NvbnZlcnQ7Cj4gPiArCj4gPiArCS8qCj4gPiArCSAq
IHNlZSBFcXVhdGlvbiAzLjIgb2YgU2lSRlByaW1hSUnihKIgSW50ZXJuYWwg
QURDIGFuZCBUb3VjaAo+ID4gKwkgKiBVc2VyIEd1aWRlCj4gPiArCSAqLwo+
ID4gKwlkaWdpdGFsX2lkZWFsID0gKDU1MjIgKiAxMjAwKSAvICg3ICogMzMz
KTsKPiA+ICsJLyoKPiA+ICsJICogc2VlIEVxdWF0aW9uIDMuMyBvZiBTaVJG
YXRsYXNWSeKEoiBJbnRlcm5hbCBBREMgYW5kIFRvdWNoCj4gPiArCSAqLwo+
ID4gKwlkaWdpdGFsX2NvbnZlcnQgPSAoZGlnaXRhbF9vdXQgLSAxMTY0NSAq
IGRpZ2l0YWxfb2Zmc2V0IC8KPiA+ICsJCTE0MDAwMCkgKiBkaWdpdGFsX2lk
ZWFsIC8gKGRpZ2l0YWxfYWdhaW4KPiA+ICsJCS0gZGlnaXRhbF9vZmZzZXQg
KiAxMTY0NSAvIDcwMDAwKTsKPiA+ICsJdm9sdCA9IDE0ICogMzMzICogZGln
aXRhbF9jb252ZXJ0IC8gNTUyMjsKPiA+ICsKPiA+ICsJcmV0dXJuIHZvbHQ7
Cj4gRHJvcCB2b2x0IGhlcmUgYXMgd2VsbD8KPiA+ICt9Cj4gPiArCj4gPiAr
c3RhdGljIHUzMiBhdGxhczZfYWRjX2NhbGN1bGF0ZV92b2x0KHUzMiBkaWdp
dGFsX291dCwKPiA+ICsJCQkJdTMyIGRpZ2l0YWxfb2Zmc2V0LCB1MzIgZGln
aXRhbF9hZ2FpbikKPiA+ICt7Cj4gPiArCXUzMiB2b2x0LCBkaWdpdGFsX2lk
ZWFsLCBkaWdpdGFsX2NvbnZlcnQ7Cj4gPiArCj4gPiArCS8qCj4gPiArCSAq
IHNlZSBFcXVhdGlvbiAzLjIgb2YgU2lSRmF0bGFzVknihKIgSW50ZXJuYWwg
QURDIGFuZCBUb3VjaAo+ID4gKwkgKiBVc2VyIEd1aWRlCj4gPiArCSAqLwo+
ID4gKwlkaWdpdGFsX2lkZWFsID0gKDM5ODYgKiAxMjEwMCkgLyAoNyAqIDMz
MzMpOwo+ID4gKwkvKgo+ID4gKwkgKiBzZWUgRXF1YXRpb24gMy4zIG9mIFNp
UkZhdGxhc1ZJ4oSiIEludGVybmFsIEFEQyBhbmQgVG91Y2gKPiA+ICsJICov
Cj4gPiArCWRpZ2l0YWxfb2Zmc2V0ICY9IDB4ZmZmOwo+ID4gKwlkaWdpdGFs
X2NvbnZlcnQgPSBhYnMoZGlnaXRhbF9vdXQgLSAyICogZGlnaXRhbF9vZmZz
ZXQpCj4gPiArCQkqIGRpZ2l0YWxfaWRlYWwgLyAoZGlnaXRhbF9hZ2Fpbgo+
ID4gKwkJLSBkaWdpdGFsX29mZnNldCAqIDIpOwo+ID4gKwl2b2x0ID0gMTQg
KiAzMzMgKiBkaWdpdGFsX2NvbnZlcnQgLyAzOTg2Owo+ID4gKwl2b2x0ID0g
dm9sdCAvIDI7Cj4gPiArCWlmICh2b2x0ID4gMTUwMCkKPiA+ICsJCXZvbHQg
PSB2b2x0IC0gKHZvbHQgLSAxNTAwKSAvIDE1Owo+ID4gKwllbHNlCj4gPiAr
CQl2b2x0ID0gdm9sdCArICgxNTAwIC0gdm9sdCkgLyAyODsKPiA+ICsKPiA+
ICsJcmV0dXJuIHZvbHQ7Cj4gPiArfQo+ID4gKwo+ID4gK3N0YXRpYyBpcnFy
ZXR1cm5fdCBzaXJmc29jX2FkY19kYXRhX2lycShpbnQgaXJxLCB2b2lkICpo
YW5kbGUpCj4gPiArewo+ID4gKwlzdHJ1Y3QgaWlvX2RldiAqaW5kaW9fZGV2
ID0gaGFuZGxlOwo+ID4gKwlzdHJ1Y3Qgc2lyZnNvY19hZGMgKmFkYyA9IGlp
b19wcml2KGluZGlvX2Rldik7Cj4gPiArCWludCB2YWw7Cj4gPiArCj4gPiAr
CXZhbCA9IHJlYWRsKGFkYy0+YmFzZSArIFNJUkZTT0NfQURDX0lOVFIpOwo+
ID4gKwo+ID4gKwl3cml0ZWwoU0lSRlNPQ19BRENfUEVOX0lOVFIgfCBTSVJG
U09DX0FEQ19QRU5fSU5UUl9FTiB8Cj4gPiArCQlTSVJGU09DX0FEQ19EQVRB
X0lOVFIgfCBTSVJGU09DX0FEQ19EQVRBX0lOVFJfRU4sCj4gPiArCQlhZGMt
PmJhc2UgKyBTSVJGU09DX0FEQ19JTlRSKTsKPiA+ICsKPiA+ICsJaWYgKHZh
bCAmIFNJUkZTT0NfQURDX0RBVEFfSU5UUikKPiA+ICsJCWNvbXBsZXRlKCZh
ZGMtPmRvbmUpOwo+ID4gKwo+ID4gKwlyZXR1cm4gSVJRX0hBTkRMRUQ7Cj4g
PiArfQo+ID4gKwo+ID4gK3N0YXRpYyBpbnQgc2lyZnNvY19hZGNfcmVhZF9y
YXcoc3RydWN0IGlpb19kZXYgKmluZGlvX2RldiwKPiA+ICsJCQkJc3RydWN0
IGlpb19jaGFuX3NwZWMgY29uc3QgKmNoYW4sCj4gPiArCQkJCWludCAqdmFs
LAo+ID4gKwkJCQlpbnQgKnZhbDIsCj4gPiArCQkJCWxvbmcgbWFzaykKPiA+
ICt7Cj4gPiArCXN0cnVjdCBzaXJmc29jX2FkYyAqYWRjID0gaWlvX3ByaXYo
aW5kaW9fZGV2KTsKPiA+ICsJc3RydWN0IHNpcmZzb2NfYWRjX2NhbGlfZGF0
YSBjYWxpX2RhdGE7Cj4gPiArCWludCByZXQ7Cj4gPiArCj4gPiArCWNhbGlf
ZGF0YS5pc19jYWxpYnJhdGlvbiA9IGZhbHNlOwo+ID4gKwlzd2l0Y2ggKG1h
c2spIHsKPiA+ICsJY2FzZSBJSU9fQ0hBTl9JTkZPX1JBVzoKPiA+ICsJCWlm
ICgwID09IGNoYW4tPmNoYW5uZWwpCj4gPiArCQkJcmV0ID0gc2lyZnNvY19h
ZGNfc2luZ2xlX3RzX3NhbXBsZShhZGMsIHZhbCk7Cj4gPiArCQllbHNlCj4g
PiArCQkJcmV0ID0gc2lyZnNvY19hZGNfZHVhbF90c19zYW1wbGUoYWRjLCB2
YWwpOwo+ID4gKwo+ID4gKwkJaWYgKHJldCkKPiA+ICsJCQlyZXR1cm4gcmV0
Owo+ID4gKwkJcmV0dXJuIElJT19WQUxfSU5UOwo+ID4gKwljYXNlIElJT19D
SEFOX0lORk9fUFJPQ0VTU0VEOgo+ID4gKwkJYWRjLT5yZXEubW9kZSA9IFNJ
UkZTT0NfQURDX1NFTCgKPiA+ICsJCQlhZGMtPmNoaXBfaW5mby0+Y2hhbm5l
bF9zZWxbY2hhbi0+Y2hhbm5lbF0pOwo+ID4gKwkJYWRjLT5yZXEuZXh0Y20g
PSBTSVJGU09DX0FEQ19FWFRDTSgwKTsKPiA+ICsJCSp2YWwgPSBzaXJmc29j
X2FkY19nZXRfYWRjX3ZvbHQoYWRjLCAmY2FsaV9kYXRhKTsKPiA+ICsJCXJl
dHVybiBJSU9fVkFMX0lOVDsKPiA+ICsJZGVmYXVsdDoKPiA+ICsJCXJldHVy
biAtRUlOVkFMOwo+ID4gKwl9Cj4gPiArCj4gPiArCXJldHVybiAwOwo+ID4g
K30KPiA+ICsKPiA+ICsjaWZkZWYgQ09ORklHX1BNX1NMRUVQCj4gPiArc3Rh
dGljIGludCBzaXJmc29jX2FkY19zdXNwZW5kKHN0cnVjdCBkZXZpY2UgKmRl
dikKPiA+ICt7Cj4gPiArCXN0cnVjdCBpaW9fZGV2ICppbmRpb19kZXYgPSBk
ZXZfZ2V0X2RydmRhdGEoZGV2KTsKPiA+ICsJc3RydWN0IHNpcmZzb2NfYWRj
ICphZGMgPSBpaW9fcHJpdihpbmRpb19kZXYpOwo+ID4gKwo+ID4gKwlzaXJm
c29jX3J0Y19pb2JyZ193cml0ZWwoc2lyZnNvY19ydGNfaW9icmdfcmVhZGwo
Cj4gPiArCQlTSVJGU09DX1BXUkNfQkFTRSArIFNJUkZTT0NfUFdSQ19UUklH
R0VSX0VOKQo+ID4gKwkJJiB+QklUKFNJUkZTT0NfUFdSX1dBS0VFTl9UU0Nf
U0hJRlQpLAo+ID4gKwkJU0lSRlNPQ19QV1JDX0JBU0UgKyBTSVJGU09DX1BX
UkNfVFJJR0dFUl9FTik7Cj4gPiArCj4gPiArCWNsa19kaXNhYmxlX3VucHJl
cGFyZShhZGMtPmNsayk7Cj4gPiArCj4gPiArCXJldHVybiAwOwo+ID4gK30K
PiA+ICsKPiA+ICtzdGF0aWMgaW50IHNpcmZzb2NfYWRjX3Jlc3VtZShzdHJ1
Y3QgZGV2aWNlICpkZXYpCj4gPiArewo+ID4gKwlzdHJ1Y3QgaWlvX2RldiAq
aW5kaW9fZGV2ID0gZGV2X2dldF9kcnZkYXRhKGRldik7Cj4gPiArCXN0cnVj
dCBzaXJmc29jX2FkYyAqYWRjID0gaWlvX3ByaXYoaW5kaW9fZGV2KTsKPiA+
ICsJaW50IHJldDsKPiA+ICsJaW50IHZhbDsKPiA+ICsKPiA+ICsJY2xrX3By
ZXBhcmVfZW5hYmxlKGFkYy0+Y2xrKTsKPiA+ICsKPiA+ICsJc2lyZnNvY19y
dGNfaW9icmdfd3JpdGVsKHNpcmZzb2NfcnRjX2lvYnJnX3JlYWRsKAo+ID4g
KwkJU0lSRlNPQ19QV1JDX0JBU0UgKyBTSVJGU09DX1BXUkNfVFJJR0dFUl9F
TikgfAo+ID4gKwkJQklUKFNJUkZTT0NfUFdSX1dBS0VFTl9UU19TSElGVCks
Cj4gPiArCQlTSVJGU09DX1BXUkNfQkFTRSArIFNJUkZTT0NfUFdSQ19UUklH
R0VSX0VOKTsKPiA+ICsKPiA+ICsJcmV0ID0gZGV2aWNlX3Jlc2V0KGRldik7
Cj4gPiArCWlmIChyZXQpIHsKPiA+ICsJCWRldl9lcnIoZGV2LCAiRmFpbGVk
IHRvIHJlc2V0XG4iKTsKPiA+ICsJCXJldHVybiByZXQ7Cj4gPiArCX0KPiA+
ICsKPiA+ICsJd3JpdGVsKFNJUkZTT0NfQURDX1BSUF9NT0RFMyB8IFNJUkZT
T0NfQURDX1JUT1VDSCgxKSB8Cj4gPiArCQlTSVJGU09DX0FEQ19ERUxfUFJF
KDIpIHwgU0lSRlNPQ19BRENfREVMX0RJUyg1KSwKPiA+ICsJCWFkYy0+YmFz
ZSArIFNJUkZTT0NfQURDX0NPTlRST0wyKTsKPiA+ICsKPiA+ICsJdmFsID0g
cmVhZGwoYWRjLT5iYXNlICsgU0lSRlNPQ19BRENfSU5UUik7Cj4gPiArCj4g
PiArCS8qIENsZWFyIGludGVycnVwdHMgYW5kIGVuYWJsZSBQRU4gaW50ZXJy
dXB0ICovCj4gPiArCXdyaXRlbCh2YWwgfCBTSVJGU09DX0FEQ19QRU5fSU5U
UiB8IFNJUkZTT0NfQURDX0RBVEFfSU5UUiB8Cj4gPiArCQlTSVJGU09DX0FE
Q19QRU5fSU5UUl9FTiB8IFNJUkZTT0NfQURDX0RBVEFfSU5UUl9FTiwKPiA+
ICsJCWFkYy0+YmFzZSArIFNJUkZTT0NfQURDX0lOVFIpOwo+ID4gKwo+ID4g
KwlyZXR1cm4gMDsKPiA+ICt9Cj4gPiArI2VuZGlmCj4gPiArCj4gPiArc3Rh
dGljIGNvbnN0IHN0cnVjdCBkZXZfcG1fb3BzIHNpcmZzb2NfYWRjX3BtX29w
cyA9IHsKPiA+ICsJU0VUX1NZU1RFTV9TTEVFUF9QTV9PUFMoc2lyZnNvY19h
ZGNfc3VzcGVuZCwgc2lyZnNvY19hZGNfcmVzdW1lKQo+ID4gK307Cj4gPiAr
Cj4gPiArI2RlZmluZSBTSVJGU09DX0FEQ19DSEFOTkVMKF9jaGFubmVsLCBf
dHlwZSwgX25hbWUsIF9tYXNrKSB7CVwKPiA+ICsJLnR5cGUgPSBfdHlwZSwJ
CQkJCVwKPiA+ICsJLmluZGV4ZWQgPSAxLAkJCQkJXAo+ID4gKwkuY2hhbm5l
bCA9IF9jaGFubmVsLAkJCQlcCj4gPiArCS5kYXRhc2hlZXRfbmFtZSA9IF9u
YW1lLAkJCVwKPiA+ICsJLmluZm9fbWFza19zZXBhcmF0ZSA9IEJJVChfbWFz
ayksCQlcCj4gPiArfQo+ID4gKwo+ID4gKyNkZWZpbmUgU0lSRlNPQ19BRENf
VFNfQ0hBTk5FTChfY2hhbm5lbCwgX25hbWUpCQlcCj4gPiArCVNJUkZTT0Nf
QURDX0NIQU5ORUwoX2NoYW5uZWwsIElJT19WT0xUQUdFLAlcCj4gPiArCV9u
YW1lLCBJSU9fQ0hBTl9JTkZPX1JBVykKPiA+ICsKPiA+ICsjZGVmaW5lIFNJ
UkZTT0NfQURDX0FVWF9DSEFOTkVMKF9jaGFubmVsLCBfbmFtZSkJXAo+ID4g
KwlTSVJGU09DX0FEQ19DSEFOTkVMKF9jaGFubmVsLCBJSU9fVk9MVEFHRSwJ
XAo+ID4gKwlfbmFtZSwgSUlPX0NIQU5fSU5GT19QUk9DRVNTRUQpCj4gPiAr
Cj4gPiArc3RhdGljIGNvbnN0IHN0cnVjdCBpaW9fY2hhbl9zcGVjIHByaW1h
Ml9hZGNfaWlvX2NoYW5uZWxzW10gPSB7Cj4gPiArCS8qIENoYW5uZWxzIHRv
IGdldCB0aGUgdG91Y2ggZGF0YSAqLwo+ID4gKwlTSVJGU09DX0FEQ19UU19D
SEFOTkVMKDAsICJ0b3VjaF9jb29yZCIpLAo+ID4gKwkvKiBDaGFubmVscyB0
byBnZXQgdGhlIHBpbiBpbnB1dCAqLwo+ID4gKwlTSVJGU09DX0FEQ19BVVhf
Q0hBTk5FTCgxLCAiYXV4aWxpYXJ5MSIpLAo+ID4gKwlTSVJGU09DX0FEQ19B
VVhfQ0hBTk5FTCgyLCAiYXV4aWxpYXJ5MiIpLAo+ID4gKwlTSVJGU09DX0FE
Q19BVVhfQ0hBTk5FTCgzLCAiYXV4aWxpYXJ5MyIpLAo+ID4gKwlTSVJGU09D
X0FEQ19BVVhfQ0hBTk5FTCg0LCAiYXV4aWxpYXJ5NCIpLAo+ID4gKwlTSVJG
U09DX0FEQ19BVVhfQ0hBTk5FTCg1LCAiYXV4aWxpYXJ5NSIpLAo+ID4gKwlT
SVJGU09DX0FEQ19BVVhfQ0hBTk5FTCg2LCAiYXV4aWxpYXJ5NiIpLAo+ID4g
K307Cj4gPiArCj4gPiArc3RhdGljIGNvbnN0IHUzMiBwcmltYTJfYWRjX2No
YW5uZWxfc2VsW10gPSB7Cj4gPiArCTAsIFNJUkZTT0NfQURDX0FVWDFfU0VM
LCBTSVJGU09DX0FEQ19BVVgyX1NFTCwKPiA+ICsJU0lSRlNPQ19BRENfQVVY
M19TRUwsIFNJUkZTT0NfQURDX0FVWDRfU0VMLAo+ID4gKwlTSVJGU09DX0FE
Q19BVVg1X1NFTCwgU0lSRlNPQ19BRENfQVVYNl9TRUwKPiA+ICt9Owo+ID4g
Kwo+ID4gK3N0YXRpYyBjb25zdCBzdHJ1Y3QgaWlvX2NoYW5fc3BlYyBhdGxh
czZfYWRjX2lpb19jaGFubmVsc1tdID0gewo+ID4gKwkvKiBDaGFubmVscyB0
byBnZXQgdGhlIHRvdWNoIGRhdGEgKi8KPiA+ICsJU0lSRlNPQ19BRENfVFNf
Q0hBTk5FTCgwLCAidG91Y2hfY29vcmQiKSwKPiA+ICsJU0lSRlNPQ19BRENf
VFNfQ0hBTk5FTCgxLCAiZHVhbF90b3VjaF9jb29yZCIpLAo+ID4gKwkvKiBD
aGFubmVscyB0byBnZXQgdGhlIHBpbiBpbnB1dCAqLwo+ID4gKwlTSVJGU09D
X0FEQ19BVVhfQ0hBTk5FTCgyLCAiYXV4aWxpYXJ5MSIpLAo+ID4gKwkvKiBB
dGxhczYgaGFzIG5vIGF1eGlsaWFyeTIgYW5kIGF1eGlsaWFyeTMgKi8KPiA+
ICsJU0lSRlNPQ19BRENfQVVYX0NIQU5ORUwoMywgImF1eGlsaWFyeTQiKSwK
PiA+ICsJU0lSRlNPQ19BRENfQVVYX0NIQU5ORUwoNCwgImF1eGlsaWFyeTUi
KSwKPiA+ICsJU0lSRlNPQ19BRENfQVVYX0NIQU5ORUwoNSwgImF1eGlsaWFy
eTYiKSwKPiA+ICt9Owo+ID4gKwo+ID4gK3N0YXRpYyBjb25zdCB1MzIgYXRs
YXM2X2FkY19jaGFubmVsX3NlbFtdID0gewo+ID4gKwkwLCAwLCBTSVJGU09D
X0FEQ19BVVgxX1NFTCwgU0lSRlNPQ19BRENfQVVYNF9TRUwsCj4gPiArCVNJ
UkZTT0NfQURDX0FVWDVfU0VMLCBTSVJGU09DX0FEQ19BVVg2X1NFTAo+ID4g
K307Cj4gPiArCj4gPiArc3RhdGljIGNvbnN0IHN0cnVjdCBpaW9faW5mbyBz
aXJmc29jX2FkY19pbmZvID0gewo+ID4gKwkucmVhZF9yYXcgPSAmc2lyZnNv
Y19hZGNfcmVhZF9yYXcsCj4gPiArCS5kcml2ZXJfbW9kdWxlID0gVEhJU19N
T0RVTEUsCj4gPiArfTsKPiA+ICsKPiA+ICtzdGF0aWMgY29uc3Qgc3RydWN0
IHNpcmZzb2NfYWRjX2NoaXBfaW5mbyBzaXJmc29jX2FkY19jaGlwX2luZm9f
dGJsW10gPSB7Cj4gPiArCVtQUklNQTJdID0gewo+ID4gKwkJLmNoYW5uZWxz
ID0gcHJpbWEyX2FkY19paW9fY2hhbm5lbHMsCj4gPiArCQkubnVtX2NoYW5u
ZWxzID0gQVJSQVlfU0laRShwcmltYTJfYWRjX2lpb19jaGFubmVscyksCj4g
PiArCQkuaWlvX2luZm8gPSAmc2lyZnNvY19hZGNfaW5mbywKPiA+ICsJCS5j
YWxjdWxhdGVfdm9sdCA9IHByaW1hMl9hZGNfY2FsY3VsYXRlX3ZvbHQsCj4g
PiArCQkuY2hhbm5lbF9zZWwgPSBwcmltYTJfYWRjX2NoYW5uZWxfc2VsLAo+
ID4gKwl9LAo+ID4gKwlbQVRMQVM2XSA9IHsKPiA+ICsJCS5jaGFubmVscyA9
IGF0bGFzNl9hZGNfaWlvX2NoYW5uZWxzLAo+ID4gKwkJLm51bV9jaGFubmVs
cyA9IEFSUkFZX1NJWkUoYXRsYXM2X2FkY19paW9fY2hhbm5lbHMpLAo+ID4g
KwkJLmlpb19pbmZvID0gJnNpcmZzb2NfYWRjX2luZm8sCj4gPiArCQkuY2Fs
Y3VsYXRlX3ZvbHQgPSBhdGxhczZfYWRjX2NhbGN1bGF0ZV92b2x0LAo+ID4g
KwkJLmNoYW5uZWxfc2VsID0gYXRsYXM2X2FkY19jaGFubmVsX3NlbCwKPiA+
ICsJfSwKPiA+ICt9Owo+ID4gKwo+ID4gK3N0YXRpYyBjb25zdCBzdHJ1Y3Qg
b2ZfZGV2aWNlX2lkIHNpcmZzb2NfYWRjX29mX21hdGNoW10gPSB7Cj4gPiAr
CXsgLmNvbXBhdGlibGUgPSAic2lyZixwcmltYTItYWRjIiwKPiA+ICsJICAu
ZGF0YSA9ICZzaXJmc29jX2FkY19jaGlwX2luZm9fdGJsW1BSSU1BMl0gfSwK
PiA+ICsJeyAuY29tcGF0aWJsZSA9ICJzaXJmLGF0bGFzNi1hZGMiLAo+ID4g
KwkgIC5kYXRhID0gJnNpcmZzb2NfYWRjX2NoaXBfaW5mb190YmxbQVRMQVM2
XSB9LAo+ID4gKwl7fQo+ID4gK307Cj4gPiArTU9EVUxFX0RFVklDRV9UQUJM
RShvZiwgc2lyZnNvY19hZGNfb2ZfbWF0Y2gpOwo+ID4gKwo+ID4gK3N0YXRp
YyBpbnQgc2lyZnNvY19hZGNfcHJvYmUoc3RydWN0IHBsYXRmb3JtX2Rldmlj
ZSAqcGRldikKPiA+ICt7Cj4gPiArCXN0cnVjdCByZXNvdXJjZQkqbWVtX3Jl
czsKPiA+ICsJc3RydWN0IHNpcmZzb2NfYWRjICphZGM7Cj4gPiArCXN0cnVj
dCBpaW9fZGV2ICppbmRpb19kZXY7Cj4gPiArCWNvbnN0IHN0cnVjdCBvZl9k
ZXZpY2VfaWQgKm1hdGNoOwo+ID4gKwlpbnQgaXJxOwo+ID4gKwlpbnQgcmV0
Owo+ID4gKwo+ID4gKwlpbmRpb19kZXYgPSBkZXZtX2lpb19kZXZpY2VfYWxs
b2MoJnBkZXYtPmRldiwKPiA+ICsJCQlzaXplb2Yoc3RydWN0IHNpcmZzb2Nf
YWRjKSk7Cj4gPiArCWlmICghaW5kaW9fZGV2KQo+ID4gKwkJcmV0dXJuIC1F
Tk9NRU07Cj4gPiArCj4gPiArCWFkYyA9IGlpb19wcml2KGluZGlvX2Rldik7
Cj4gPiArCj4gPiArCS8qIEFEQyBzcGVjaWZpYyBkYXRhICovCj4gPiArCW1h
dGNoID0gb2ZfbWF0Y2hfZGV2aWNlKAo+ID4gKwkJb2ZfbWF0Y2hfcHRyKHNp
cmZzb2NfYWRjX29mX21hdGNoKSwgJnBkZXYtPmRldik7Cj4gPiArCWFkYy0+
Y2hpcF9pbmZvID0gbWF0Y2gtPmRhdGE7Cj4gPiArCj4gPiArCWluZGlvX2Rl
di0+aW5mbyA9IGFkYy0+Y2hpcF9pbmZvLT5paW9faW5mbzsKPiA+ICsJaW5k
aW9fZGV2LT5jaGFubmVscyA9IGFkYy0+Y2hpcF9pbmZvLT5jaGFubmVsczsK
PiA+ICsJaW5kaW9fZGV2LT5udW1fY2hhbm5lbHMgPSBhZGMtPmNoaXBfaW5m
by0+bnVtX2NoYW5uZWxzOwo+ID4gKwlpbmRpb19kZXYtPm5hbWUgPSAic2ly
ZnNvYyBhZGMiOwo+ID4gKwlpbmRpb19kZXYtPmRldi5wYXJlbnQgPSAmcGRl
di0+ZGV2Owo+ID4gKwlpbmRpb19kZXYtPm1vZGVzID0gSU5ESU9fRElSRUNU
X01PREU7Cj4gPiArCj4gPiArCXBsYXRmb3JtX3NldF9kcnZkYXRhKHBkZXYs
IGluZGlvX2Rldik7Cj4gPiArCj4gPiArCWFkYy0+Y2xrID0gZGV2bV9jbGtf
Z2V0KCZwZGV2LT5kZXYsIE5VTEwpOwo+ID4gKwlpZiAoSVNfRVJSKGFkYy0+
Y2xrKSkgewo+ID4gKwkJZGV2X2VycigmcGRldi0+ZGV2LCAiR2V0IGFkYyBj
bGsgZmFpbGVkXG4iKTsKPiA+ICsJCXJldCA9IC1FTk9NRU07Cj4gPiArCQln
b3RvIGVycjsKPiBJc24ndCBpdCBhIGJpdCB0b28gZWFybHkgdG8gY2FsbCBj
bGtfZGlzYWJsZV91bnByZXBhcmU/IEFsc28sIHdvdWxkbid0IGl0IG1ha2Ug
bW9yZSBzZW5zZSB0byByZXR1cm4gdGhlIGVycm9yIHZhbHVlIGZyb20gZGV2
bV9jbGtfZ2V0Pwo+ID4gKwl9Cj4gPiArCWNsa19wcmVwYXJlX2VuYWJsZShh
ZGMtPmNsayk7Cj4gPiArCj4gPiArCW1lbV9yZXMgPSBwbGF0Zm9ybV9nZXRf
cmVzb3VyY2UocGRldiwgSU9SRVNPVVJDRV9NRU0sIDApOwo+ID4gKwlpZiAo
IW1lbV9yZXMpIHsKPiA+ICsJCWRldl9lcnIoJnBkZXYtPmRldiwgIlVuYWJs
ZSB0byBnZXQgaW8gcmVzb3VyY2VcbiIpOwo+ID4gKwkJcmV0ID0gLUVOT0RF
VjsKPiA+ICsJCWdvdG8gZXJyOwo+ID4gKwl9Cj4gPiArCj4gPiArCWFkYy0+
YmFzZSA9IGRldm1fcmVxdWVzdF9hbmRfaW9yZW1hcCgmcGRldi0+ZGV2LCBt
ZW1fcmVzKTsKPiA+ICsJaWYgKCFhZGMtPmJhc2UpIHsKPiA+ICsJCWRldl9l
cnIoJnBkZXYtPmRldiwgIklPIHJlbWFwIGZhaWxlZCFcbiIpOwo+ID4gKwkJ
cmV0ID0gLUVOT01FTTsKPiA+ICsJCWdvdG8gZXJyOwo+ID4gKwl9Cj4gPiAr
Cj4gPiArCWluaXRfY29tcGxldGlvbigmYWRjLT5kb25lKTsKPiA+ICsJbXV0
ZXhfaW5pdCgmYWRjLT5hZGNfbG9jayk7Cj4gPiArCj4gPiArCXNpcmZzb2Nf
cnRjX2lvYnJnX3dyaXRlbChzaXJmc29jX3J0Y19pb2JyZ19yZWFkbChTSVJG
U09DX1BXUkNfQkFTRSArCj4gPiArCQlTSVJGU09DX1BXUkNfVFJJR0dFUl9F
TikgfCBCSVQoU0lSRlNPQ19QV1JfV0FLRUVOX1RTX1NISUZUKSwKPiA+ICsJ
CVNJUkZTT0NfUFdSQ19CQVNFICsgU0lSRlNPQ19QV1JDX1RSSUdHRVJfRU4p
Owo+ID4gKwo+ID4gKwlyZXQgPSBkZXZpY2VfcmVzZXQoJnBkZXYtPmRldik7
Cj4gPiArCWlmIChyZXQpIHsKPiA+ICsJCWRldl9lcnIoJnBkZXYtPmRldiwg
IkZhaWxlZCB0byByZXNldFxuIik7Cj4gPiArCQlnb3RvIGVycjsKPiA+ICsJ
fQo+ID4gKwo+ID4gKwl3cml0ZWwoU0lSRlNPQ19BRENfUFJQX01PREUzIHwg
U0lSRlNPQ19BRENfUlRPVUNIKDEpIHwKPiA+ICsJCVNJUkZTT0NfQURDX0RF
TF9QUkUoMikgfCBTSVJGU09DX0FEQ19ERUxfRElTKDUpLAo+ID4gKwkJYWRj
LT5iYXNlICsgU0lSRlNPQ19BRENfQ09OVFJPTDIpOwo+ID4gKwo+ID4gKwkv
KiBDbGVhciBpbnRlcnJ1cHRzIGFuZCBlbmFibGUgUEVOIElOVFIgKi8KPiA+
ICsJd3JpdGVsKHJlYWRsKGFkYy0+YmFzZSArIFNJUkZTT0NfQURDX0lOVFIp
IHwgU0lSRlNPQ19BRENfUEVOX0lOVFIgfAo+ID4gKwkJU0lSRlNPQ19BRENf
REFUQV9JTlRSIHwgU0lSRlNPQ19BRENfUEVOX0lOVFJfRU4gfAo+ID4gKwkJ
U0lSRlNPQ19BRENfREFUQV9JTlRSX0VOLCAgYWRjLT5iYXNlICsgU0lSRlNP
Q19BRENfSU5UUik7Cj4gPiArCj4gPiArCWlycSA9IHBsYXRmb3JtX2dldF9p
cnEocGRldiwgMCk7Cj4gPiArCWlmIChpcnEgPCAwKSB7Cj4gPiArCQlkZXZf
ZXJyKCZwZGV2LT5kZXYsICJGYWlsZWQgdG8gZ2V0IElSUSFcbiIpOwo+ID4g
KwkJcmV0ID0gLUVOT01FTTsKPiByZXQgPSBpcnE7Pwo+ID4gKwkJZ290byBl
cnI7Cj4gPiArCX0KPiA+ICsKPiA+ICsJcmV0ID0gZGV2bV9yZXF1ZXN0X2ly
cSgmcGRldi0+ZGV2LCBpcnEsIHNpcmZzb2NfYWRjX2RhdGFfaXJxLAo+ID4g
KwkJMCwgRFJJVkVSX05BTUUsIGluZGlvX2Rldik7Cj4gPiArCWlmIChyZXQg
PCAwKSB7Cj4gPiArCQlkZXZfZXJyKCZwZGV2LT5kZXYsICJGYWlsZWQgdG8g
cmVnaXN0ZXIgaXJxIGhhbmRsZXJcbiIpOwo+ID4gKwkJcmV0ID0gLUVOT0RF
VjsKPiBQYXNzIHJldCB1bmNoYW5nZWQ/Cj4gPiArCQlnb3RvIGVycjsKPiA+
ICsJfQo+ID4gKwo+ID4gKwlyZXQgPSBvZl9wbGF0Zm9ybV9wb3B1bGF0ZShw
ZGV2LT5kZXYub2Zfbm9kZSwgc2lyZnNvY19hZGNfb2ZfbWF0Y2gsCj4gPiAr
CQlOVUxMLCAmcGRldi0+ZGV2KTsKPiA+ICsJaWYgKHJldCA8IDApIHsKPiA+
ICsJCWRldl9lcnIoJnBkZXYtPmRldiwgIkZhaWxlZCB0byBhZGQgY2hpbGQg
bm9kZXNcbiIpOwo+ID4gKwkJZ290byBlcnI7Cj4gPiArCX0KPiA+ICsKPiA+
ICsJcmV0ID0gaWlvX2RldmljZV9yZWdpc3RlcihpbmRpb19kZXYpOwo+ID4g
KwlpZiAocmV0KSB7Cj4gPiArCQlkZXZfZXJyKCZwZGV2LT5kZXYsICJGYWls
ZWQgdG8gcmVnaXN0ZXIgYWRjIGlpbyBkZXZcbiIpOwo+ID4gKwkJZ290byBl
cnI7Cj4gPiArCX0KPiA+ICsKPiA+ICsJcmV0dXJuIDA7Cj4gPiArCj4gPiAr
ZXJyOgo+ID4gKwljbGtfZGlzYWJsZV91bnByZXBhcmUoYWRjLT5jbGspOwo+
ID4gKwo+ID4gKwlyZXR1cm4gcmV0Owo+ID4gK30KPiA+ICsKPiA+ICtzdGF0
aWMgaW50IHNpcmZzb2NfYWRjX3JlbW92ZShzdHJ1Y3QgcGxhdGZvcm1fZGV2
aWNlICpwZGV2KQo+ID4gK3sKPiA+ICsJc3RydWN0IGlpb19kZXYgKmluZGlv
X2RldiA9IHBsYXRmb3JtX2dldF9kcnZkYXRhKHBkZXYpOwo+ID4gKwlzdHJ1
Y3Qgc2lyZnNvY19hZGMgKmFkYyA9IGlpb19wcml2KGluZGlvX2Rldik7Cj4g
PiArCj4gPiArCWlpb19kZXZpY2VfdW5yZWdpc3RlcihpbmRpb19kZXYpOwo+
ID4gKwljbGtfZGlzYWJsZV91bnByZXBhcmUoYWRjLT5jbGspOwo+ID4gKwo+
ID4gKwlyZXR1cm4gMDsKPiA+ICt9Cj4gPiArCj4gPiArc3RhdGljIHN0cnVj
dCBwbGF0Zm9ybV9kcml2ZXIgc2lyZnNvY19hZGNfZHJpdmVyID0gewo+ID4g
KwkuZHJpdmVyID0gewo+ID4gKwkJLm5hbWUJPSBEUklWRVJfTkFNRSwKPiA+
ICsJCS5vZl9tYXRjaF90YWJsZSA9IHNpcmZzb2NfYWRjX29mX21hdGNoLAo+
ID4gKwkJLnBtCT0gJnNpcmZzb2NfYWRjX3BtX29wcywKPiA+ICsJfSwKPiA+
ICsJLnByb2JlCQk9IHNpcmZzb2NfYWRjX3Byb2JlLAo+ID4gKwkucmVtb3Zl
CQk9IHNpcmZzb2NfYWRjX3JlbW92ZSwKPiA+ICt9Owo+ID4gKwo+ID4gK21v
ZHVsZV9wbGF0Zm9ybV9kcml2ZXIoc2lyZnNvY19hZGNfZHJpdmVyKTsKPiA+
ICsKPiA+ICtNT0RVTEVfQVVUSE9SKCJHdW95aW5nIFpoYW5nIDxHdW95aW5n
LlpoYW5nQGNzci5jb20+Iik7Cj4gPiArTU9EVUxFX0RFU0NSSVBUSU9OKCJT
aVJGIFNvQyBPbi1jaGlwIEFEQyBkcml2ZXIiKTsKPiA+ICtNT0RVTEVfTElD
RU5TRSgiR1BMIHYyIik7CgpPSywgSSdsbCBmaXggaXQKCkJlc3QgUmVnYXJk
cywKR3VveWluZyBaaGFuZwoKCk1lbWJlciBvZiB0aGUgQ1NSIHBsYyBncm91
cCBvZiBjb21wYW5pZXMuIENTUiBwbGMgcmVnaXN0ZXJlZCBpbiBFbmdsYW5k
IGFuZCBXYWxlcywgcmVnaXN0ZXJlZCBudW1iZXIgNDE4NzM0NiwgcmVnaXN0
ZXJlZCBvZmZpY2UgQ2h1cmNoaWxsIEhvdXNlLCBDYW1icmlkZ2UgQnVzaW5l
c3MgUGFyaywgQ293bGV5IFJvYWQsIENhbWJyaWRnZSwgQ0I0IDBXWiwgVW5p
dGVkIEtpbmdkb20KTW9yZSBpbmZvcm1hdGlvbiBjYW4gYmUgZm91bmQgYXQg
d3d3LmNzci5jb20uIEtlZXAgdXAgdG8gZGF0ZSB3aXRoIENTUiBvbiBvdXIg
dGVjaG5pY2FsIGJsb2csIHd3dy5jc3IuY29tL2Jsb2csIENTUiBwZW9wbGUg
YmxvZywgd3d3LmNzci5jb20vcGVvcGxlLCBZb3VUdWJlLCB3d3cueW91dHVi
ZS5jb20vdXNlci9DU1JwbGMsIEZhY2Vib29rLCB3d3cuZmFjZWJvb2suY29t
L3BhZ2VzL0NTUi8xOTEwMzg0MzQyNTM1MzQsIG9yIGZvbGxvdyB1cyBvbiBU
d2l0dGVyIGF0IHd3dy50d2l0dGVyLmNvbS9DU1JfcGxjLgpOZXcgZm9yIDIw
MTQsIHlvdSBjYW4gbm93IGFjY2VzcyB0aGUgd2lkZSByYW5nZSBvZiBwcm9k
dWN0cyBwb3dlcmVkIGJ5IGFwdFggYXQgd3d3LmFwdHguY29tLgo=

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2014-07-30  8:28 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-07-17  9:22 [PATCH v2] iio: adc: add CSR SiRFSoC internal ADC driver Guoying Zhang
2014-07-20 14:33 ` Jonathan Cameron
2014-07-21  6:21   ` Barry Song
2014-07-27 12:04 ` Hartmut Knaack
2014-07-30  8:28   ` Guoying Zhang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).