From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id F4061C11F6F for ; Tue, 13 Jul 2021 11:35:57 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E2A0B60240 for ; Tue, 13 Jul 2021 11:35:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235911AbhGMLiq (ORCPT ); Tue, 13 Jul 2021 07:38:46 -0400 Received: from guitar.tcltek.co.il ([192.115.133.116]:52451 "EHLO mx.tkos.co.il" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235623AbhGMLip (ORCPT ); Tue, 13 Jul 2021 07:38:45 -0400 Received: from tarshish.tkos.co.il (unknown [10.0.8.2]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mx.tkos.co.il (Postfix) with ESMTPS id 3D079440510; Tue, 13 Jul 2021 14:35:48 +0300 (IDT) From: Baruch Siach To: Thierry Reding , =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= , Lee Jones Cc: Baruch Siach , Andy Gross , Bjorn Andersson , Balaji Prakash J , Rob Herring , Robert Marko , Kathiravan T , linux-pwm@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-msm@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH v5 2/4] pwm: driver for qualcomm ipq6018 pwm block Date: Tue, 13 Jul 2021 14:35:43 +0300 Message-Id: <1173e7b0b58730fd187871d9e14a02cab85158cc.1626176145.git.baruch@tkos.co.il> X-Mailer: git-send-email 2.30.2 In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org Driver for the PWM block in Qualcomm IPQ6018 line of SoCs. Based on driver from downstream Codeaurora kernel tree. Removed support for older (V1) variants because I have no access to that hardware. Tested on IPQ6010 based hardware. Signed-off-by: Baruch Siach --- v5: Use &tcsr_q6 syscon to access registers (Bjorn Andersson) Address Uwe Kleine-König review comments: Implement .get_state() Add IPQ_PWM_ prefix to local macros Use GENMASK/BIT/FIELD_PREP for register fields access Make type of config_div_and_duty() parameters consistent Derive IPQ_PWM_MIN_PERIOD_NS from IPQ_PWM_CLK_SRC_FREQ Integrate enable/disable into config_div_and_duty() to save register read, and reduce frequency glitch on update Use min() instead of min_t() Fix comment format Use dev_err_probe() to indicate probe step failure Add missing clk_disable_unprepare() in .remove Don't set .owner v4: Use div64_u64() to fix link for 32-bit targets ((kernel test robot , Uwe Kleine-König) v3: s/qcom,pwm-ipq6018/qcom,ipq6018-pwm/ (Rob Herring) Fix integer overflow on 32-bit targets (kernel test robot ) v2: Address Uwe Kleine-König review comments: Fix period calculation when out of range Don't set period larger than requested Remove PWM disable on configuration change Implement .apply instead of non-atomic .config/.enable/.disable Don't modify PWM on .request/.free Check pwm_div underflow Fix various code and comment formatting issues Other changes: Use u64 divisor safe division Remove now empty .request/.free --- drivers/pwm/Kconfig | 12 ++ drivers/pwm/Makefile | 1 + drivers/pwm/pwm-ipq.c | 278 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 291 insertions(+) create mode 100644 drivers/pwm/pwm-ipq.c diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index c76adedd58c9..08add845596f 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -260,6 +260,18 @@ config PWM_INTEL_LGM To compile this driver as a module, choose M here: the module will be called pwm-intel-lgm. +config PWM_IPQ + tristate "IPQ PWM support" + depends on ARCH_QCOM || COMPILE_TEST + depends on HAVE_CLK && HAS_IOMEM + help + Generic PWM framework driver for IPQ PWM block which supports + 4 pwm channels. Each of the these channels can be configured + independent of each other. + + To compile this driver as a module, choose M here: the module + will be called pwm-ipq. + config PWM_IQS620A tristate "Azoteq IQS620A PWM support" depends on MFD_IQS62X || COMPILE_TEST diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile index 708840b7fba8..7402feae4b36 100644 --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_PWM_IMX1) += pwm-imx1.o obj-$(CONFIG_PWM_IMX27) += pwm-imx27.o obj-$(CONFIG_PWM_IMX_TPM) += pwm-imx-tpm.o obj-$(CONFIG_PWM_INTEL_LGM) += pwm-intel-lgm.o +obj-$(CONFIG_PWM_IPQ) += pwm-ipq.o obj-$(CONFIG_PWM_IQS620A) += pwm-iqs620a.o obj-$(CONFIG_PWM_JZ4740) += pwm-jz4740.o obj-$(CONFIG_PWM_KEEMBAY) += pwm-keembay.o diff --git a/drivers/pwm/pwm-ipq.c b/drivers/pwm/pwm-ipq.c new file mode 100644 index 000000000000..ddfbe95816a4 --- /dev/null +++ b/drivers/pwm/pwm-ipq.c @@ -0,0 +1,278 @@ +// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 +/* + * Copyright (c) 2016-2017, 2020 The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IPQ_PWM_MAX_DEVICES 4 + +/* The frequency range supported is 1Hz to 100MHz */ +#define IPQ_PWM_CLK_SRC_FREQ (100*1000*1000) +#define IPQ_PWM_MIN_PERIOD_NS (NSEC_PER_SEC / IPQ_PWM_CLK_SRC_FREQ) +#define IPQ_PWM_MAX_PERIOD_NS ((u64)NSEC_PER_SEC) + +/* + * The max value specified for each field is based on the number of bits + * in the pwm control register for that field + */ +#define IPQ_PWM_MAX_DIV 0xFFFF + +#define IPQ_PWM_CFG_REG0 0 /*PWM_DIV PWM_HI*/ +#define IPQ_PWM_REG0_PWM_DIV GENMASK(15, 0) +#define IPQ_PWM_REG0_HI_DURATION GENMASK(31, 16) + +#define IPQ_PWM_CFG_REG1 1 /*ENABLE UPDATE PWM_PRE_DIV*/ +#define IPQ_PWM_REG1_PRE_DIV GENMASK(15, 0) +/* + * Enable bit is set to enable output toggling in pwm device. + * Update bit is set to reflect the changed divider and high duration + * values in register. + */ +#define IPQ_PWM_REG1_UPDATE BIT(30) +#define IPQ_PWM_REG1_ENABLE BIT(31) + + +struct ipq_pwm_chip { + struct pwm_chip chip; + struct clk *clk; + struct regmap *regmap; + u32 regmap_off; +}; + +static struct ipq_pwm_chip *to_ipq_pwm_chip(struct pwm_chip *chip) +{ + return container_of(chip, struct ipq_pwm_chip, chip); +} + +static unsigned ipq_pwm_reg_offset(struct pwm_device *pwm, unsigned reg) +{ + return ((pwm->hwpwm * 2) + reg) * 4; +} + +static unsigned int ipq_pwm_reg_read(struct pwm_device *pwm, unsigned reg) +{ + struct ipq_pwm_chip *ipq_chip = to_ipq_pwm_chip(pwm->chip); + unsigned int off = ipq_chip->regmap_off + ipq_pwm_reg_offset(pwm, reg); + unsigned int val; + + regmap_read(ipq_chip->regmap, off, &val); + + return val; +} + +static void ipq_pwm_reg_write(struct pwm_device *pwm, unsigned reg, + unsigned val) +{ + struct ipq_pwm_chip *ipq_chip = to_ipq_pwm_chip(pwm->chip); + unsigned int off = ipq_chip->regmap_off + ipq_pwm_reg_offset(pwm, reg); + + regmap_write(ipq_chip->regmap, off, val); +} + +static void config_div_and_duty(struct pwm_device *pwm, unsigned int pre_div, + unsigned int pwm_div, u64 period_ns, u64 duty_ns, + bool enable) +{ + unsigned long hi_dur; + unsigned long long quotient; + unsigned long val = 0; + + /* + * high duration = pwm duty * (pwm div + 1) + * pwm duty = duty_ns / period_ns + */ + quotient = (pwm_div + 1) * duty_ns; + hi_dur = div64_u64(quotient, period_ns); + + val = FIELD_PREP(IPQ_PWM_REG0_HI_DURATION, hi_dur) | + FIELD_PREP(IPQ_PWM_REG0_PWM_DIV, pwm_div); + ipq_pwm_reg_write(pwm, IPQ_PWM_CFG_REG0, val); + + val = FIELD_PREP(IPQ_PWM_REG1_PRE_DIV, pre_div); + ipq_pwm_reg_write(pwm, IPQ_PWM_CFG_REG1, val); + + /* Enable needs a separate write to REG1 */ + val |= IPQ_PWM_REG1_UPDATE; + if (enable) + val |= IPQ_PWM_REG1_ENABLE; + else + val &= ~IPQ_PWM_REG1_ENABLE; + ipq_pwm_reg_write(pwm, IPQ_PWM_CFG_REG1, val); +} + +static int ipq_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + const struct pwm_state *state) +{ + struct ipq_pwm_chip *ipq_chip = to_ipq_pwm_chip(chip); + unsigned long freq; + unsigned int pre_div, pwm_div, close_pre_div, close_pwm_div; + long long diff; + unsigned long rate = clk_get_rate(ipq_chip->clk); + unsigned long min_diff = rate; + uint64_t fin_ps; + u64 period_ns, duty_ns; + + if (state->period < IPQ_PWM_MIN_PERIOD_NS) + return -ERANGE; + + period_ns = min(state->period, IPQ_PWM_MAX_PERIOD_NS); + duty_ns = min(state->duty_cycle, period_ns); + + /* freq in Hz for period in nano second */ + freq = div64_u64(NSEC_PER_SEC, period_ns); + fin_ps = div64_u64(NSEC_PER_SEC * 1000ULL, rate); + close_pre_div = IPQ_PWM_MAX_DIV; + close_pwm_div = IPQ_PWM_MAX_DIV; + + for (pre_div = 0; pre_div <= IPQ_PWM_MAX_DIV; pre_div++) { + pwm_div = DIV64_U64_ROUND_CLOSEST(period_ns * 1000, + fin_ps * (pre_div + 1)); + pwm_div--; + if (pwm_div > IPQ_PWM_MAX_DIV) + continue; + + diff = ((uint64_t)freq * (pre_div + 1) * (pwm_div + 1)) + - (uint64_t)rate; + + if (diff < 0) /* period larger than requested */ + continue; + if (diff == 0) { /* bingo */ + close_pre_div = pre_div; + close_pwm_div = pwm_div; + break; + } + if (diff < min_diff) { + min_diff = diff; + close_pre_div = pre_div; + close_pwm_div = pwm_div; + } + } + + /* config divider values for the closest possible frequency */ + config_div_and_duty(pwm, close_pre_div, close_pwm_div, + period_ns, duty_ns, state->enabled); + + return 0; +} + +static void ipq_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + struct pwm_state *state) +{ + struct ipq_pwm_chip *ipq_chip = to_ipq_pwm_chip(chip); + unsigned long rate = clk_get_rate(ipq_chip->clk); + unsigned int pre_div, pwm_div, hi_dur; + u64 effective_div, hi_div; + u32 reg0, reg1; + + reg0 = ipq_pwm_reg_read(pwm, IPQ_PWM_CFG_REG0); + reg1 = ipq_pwm_reg_read(pwm, IPQ_PWM_CFG_REG1); + + state->polarity = PWM_POLARITY_NORMAL; + state->enabled = reg1 & IPQ_PWM_REG1_ENABLE; + + pwm_div = FIELD_GET(IPQ_PWM_REG0_PWM_DIV, reg0); + hi_dur = FIELD_GET(IPQ_PWM_REG0_HI_DURATION, reg0); + pre_div = FIELD_GET(IPQ_PWM_REG1_PRE_DIV, reg1); + + effective_div = (pre_div + 1) * (pwm_div + 1); + state->period = div64_u64(effective_div * NSEC_PER_SEC, rate); + + hi_div = hi_dur * (pre_div + 1); + state->duty_cycle = div64_u64(hi_div * NSEC_PER_SEC, rate); +} + +static struct pwm_ops ipq_pwm_ops = { + .apply = ipq_pwm_apply, + .get_state = ipq_pwm_get_state, + .owner = THIS_MODULE, +}; + +static int ipq_pwm_probe(struct platform_device *pdev) +{ + struct ipq_pwm_chip *pwm; + struct device *dev = &pdev->dev; + struct of_phandle_args args; + int ret; + + pwm = devm_kzalloc(dev, sizeof(*pwm), GFP_KERNEL); + if (!pwm) + return -ENOMEM; + + platform_set_drvdata(pdev, pwm); + + ret = of_parse_phandle_with_fixed_args(dev->of_node, "qcom,pwm-regs", + 1, 0, &args); + if (ret) + return dev_err_probe(dev, ret, "regs parse failed"); + + pwm->regmap = syscon_node_to_regmap(args.np); + of_node_put(args.np); + if (IS_ERR(pwm->regmap)) + return dev_err_probe(dev, PTR_ERR(pwm->regmap), + "regs map failed"); + pwm->regmap_off = args.args[0]; + + pwm->clk = devm_clk_get(dev, "core"); + if (IS_ERR(pwm->clk)) + return dev_err_probe(dev, PTR_ERR(pwm->clk), + "failed to get core clock"); + + ret = clk_set_rate(pwm->clk, IPQ_PWM_CLK_SRC_FREQ); + if (ret) + return dev_err_probe(dev, ret, "clock rate set failed"); + + ret = clk_prepare_enable(pwm->clk); + if (ret) + return dev_err_probe(dev, ret, "clock enable failed"); + + pwm->chip.dev = dev; + pwm->chip.ops = &ipq_pwm_ops; + pwm->chip.npwm = IPQ_PWM_MAX_DEVICES; + + ret = pwmchip_add(&pwm->chip); + if (ret < 0) { + dev_err_probe(dev, ret, "pwmchip_add() failed\n"); + clk_disable_unprepare(pwm->clk); + return ret; + } + + return 0; +} + +static int ipq_pwm_remove(struct platform_device *pdev) +{ + struct ipq_pwm_chip *pwm = platform_get_drvdata(pdev); + + clk_disable_unprepare(pwm->clk); + pwmchip_remove(&pwm->chip); + + return 0; +} + +static const struct of_device_id pwm_ipq_dt_match[] = { + { .compatible = "qcom,ipq6018-pwm", }, + {} +}; +MODULE_DEVICE_TABLE(of, pwm_ipq_dt_match); + +static struct platform_driver ipq_pwm_driver = { + .driver = { + .name = "ipq-pwm", + .of_match_table = pwm_ipq_dt_match, + }, + .probe = ipq_pwm_probe, + .remove = ipq_pwm_remove, +}; + +module_platform_driver(ipq_pwm_driver); + +MODULE_LICENSE("Dual BSD/GPL"); -- 2.30.2 From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-17.5 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7A72CC07E95 for ; Tue, 13 Jul 2021 11:38:03 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 471CF611C0 for ; Tue, 13 Jul 2021 11:38:03 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 471CF611C0 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=tkos.co.il Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=VIv+JGzC0GSYIYKkwcXQMwXgvv0LBl6lEQhObX61opc=; b=xWqAXrTmIPfllY g1BeTpNPQyIidTGKNe/SAd+aGq94DfqHBa4bsEwTC3rDRYeBoPkk6ai/NYv3vSKFqeUJENdb46+Es u25gcxOe+3pERIJvcvezuJsHhHytUZsFxQLLyfuNgs4i3SaOmAzYhm7pNKXBTa7mY7wBLZicKIRIx Ss//F8pLOf1q9UaXX0bmbHmFq3Soc0a8Crh57wW5ygUMGAQ+EIyfR3/2eI0y+xLMDerjPkcxUs1/q gSIkZKk6qYk5CeMpiIWJ43BCK+AqOIejdlF2BiqpR6efbq4TfOFGB7X9XqL0GMRGVYIi0oLIDthGh k8ZiAfsEYIgyrwk47KWQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1m3GiI-00AF1p-Vs; Tue, 13 Jul 2021 11:36:35 +0000 Received: from guitar.tcltek.co.il ([192.115.133.116] helo=mx.tkos.co.il) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1m3Ghl-00AEwV-1c for linux-arm-kernel@lists.infradead.org; Tue, 13 Jul 2021 11:36:03 +0000 Received: from tarshish.tkos.co.il (unknown [10.0.8.2]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mx.tkos.co.il (Postfix) with ESMTPS id 3D079440510; Tue, 13 Jul 2021 14:35:48 +0300 (IDT) From: Baruch Siach To: Thierry Reding , =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= , Lee Jones Cc: Baruch Siach , Andy Gross , Bjorn Andersson , Balaji Prakash J , Rob Herring , Robert Marko , Kathiravan T , linux-pwm@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-msm@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH v5 2/4] pwm: driver for qualcomm ipq6018 pwm block Date: Tue, 13 Jul 2021 14:35:43 +0300 Message-Id: <1173e7b0b58730fd187871d9e14a02cab85158cc.1626176145.git.baruch@tkos.co.il> X-Mailer: git-send-email 2.30.2 In-Reply-To: References: MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210713_043601_632106_27192BEA X-CRM114-Status: GOOD ( 30.97 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org RHJpdmVyIGZvciB0aGUgUFdNIGJsb2NrIGluIFF1YWxjb21tIElQUTYwMTggbGluZSBvZiBTb0Nz LiBCYXNlZCBvbgpkcml2ZXIgZnJvbSBkb3duc3RyZWFtIENvZGVhdXJvcmEga2VybmVsIHRyZWUu IFJlbW92ZWQgc3VwcG9ydCBmb3Igb2xkZXIKKFYxKSB2YXJpYW50cyBiZWNhdXNlIEkgaGF2ZSBu byBhY2Nlc3MgdG8gdGhhdCBoYXJkd2FyZS4KClRlc3RlZCBvbiBJUFE2MDEwIGJhc2VkIGhhcmR3 YXJlLgoKU2lnbmVkLW9mZi1ieTogQmFydWNoIFNpYWNoIDxiYXJ1Y2hAdGtvcy5jby5pbD4KLS0t CnY1OgoKVXNlICZ0Y3NyX3E2IHN5c2NvbiB0byBhY2Nlc3MgcmVnaXN0ZXJzIChCam9ybiBBbmRl cnNzb24pCgpBZGRyZXNzIFV3ZSBLbGVpbmUtS8O2bmlnIHJldmlldyBjb21tZW50czoKCiAgSW1w bGVtZW50IC5nZXRfc3RhdGUoKQoKICBBZGQgSVBRX1BXTV8gcHJlZml4IHRvIGxvY2FsIG1hY3Jv cwoKICBVc2UgR0VOTUFTSy9CSVQvRklFTERfUFJFUCBmb3IgcmVnaXN0ZXIgZmllbGRzIGFjY2Vz cwoKICBNYWtlIHR5cGUgb2YgY29uZmlnX2Rpdl9hbmRfZHV0eSgpIHBhcmFtZXRlcnMgY29uc2lz dGVudAoKICBEZXJpdmUgSVBRX1BXTV9NSU5fUEVSSU9EX05TIGZyb20gSVBRX1BXTV9DTEtfU1JD X0ZSRVEKCiAgSW50ZWdyYXRlIGVuYWJsZS9kaXNhYmxlIGludG8gY29uZmlnX2Rpdl9hbmRfZHV0 eSgpIHRvIHNhdmUgcmVnaXN0ZXIgcmVhZCwKICBhbmQgcmVkdWNlIGZyZXF1ZW5jeSBnbGl0Y2gg b24gdXBkYXRlCgogIFVzZSBtaW4oKSBpbnN0ZWFkIG9mIG1pbl90KCkKCiAgRml4IGNvbW1lbnQg Zm9ybWF0CgogIFVzZSBkZXZfZXJyX3Byb2JlKCkgdG8gaW5kaWNhdGUgcHJvYmUgc3RlcCBmYWls dXJlCgogIEFkZCBtaXNzaW5nIGNsa19kaXNhYmxlX3VucHJlcGFyZSgpIGluIC5yZW1vdmUKCiAg RG9uJ3Qgc2V0IC5vd25lcgoKdjQ6CgogIFVzZSBkaXY2NF91NjQoKSB0byBmaXggbGluayBmb3Ig MzItYml0IHRhcmdldHMgKChrZXJuZWwgdGVzdCByb2JvdAogIDxsa3BAaW50ZWwuY29tPiwgVXdl IEtsZWluZS1Lw7ZuaWcpCgp2MzoKCiAgcy9xY29tLHB3bS1pcHE2MDE4L3Fjb20saXBxNjAxOC1w d20vIChSb2IgSGVycmluZykKCiAgRml4IGludGVnZXIgb3ZlcmZsb3cgb24gMzItYml0IHRhcmdl dHMgKGtlcm5lbCB0ZXN0IHJvYm90IDxsa3BAaW50ZWwuY29tPikKCnYyOgoKQWRkcmVzcyBVd2Ug S2xlaW5lLUvDtm5pZyByZXZpZXcgY29tbWVudHM6CgogIEZpeCBwZXJpb2QgY2FsY3VsYXRpb24g d2hlbiBvdXQgb2YgcmFuZ2UKCiAgRG9uJ3Qgc2V0IHBlcmlvZCBsYXJnZXIgdGhhbiByZXF1ZXN0 ZWQKCiAgUmVtb3ZlIFBXTSBkaXNhYmxlIG9uIGNvbmZpZ3VyYXRpb24gY2hhbmdlCgogIEltcGxl bWVudCAuYXBwbHkgaW5zdGVhZCBvZiBub24tYXRvbWljIC5jb25maWcvLmVuYWJsZS8uZGlzYWJs ZQoKICBEb24ndCBtb2RpZnkgUFdNIG9uIC5yZXF1ZXN0Ly5mcmVlCgogIENoZWNrIHB3bV9kaXYg dW5kZXJmbG93CgogIEZpeCB2YXJpb3VzIGNvZGUgYW5kIGNvbW1lbnQgZm9ybWF0dGluZyBpc3N1 ZXMKCk90aGVyIGNoYW5nZXM6CgogIFVzZSB1NjQgZGl2aXNvciBzYWZlIGRpdmlzaW9uCgogIFJl bW92ZSBub3cgZW1wdHkgLnJlcXVlc3QvLmZyZWUKLS0tCiBkcml2ZXJzL3B3bS9LY29uZmlnICAg fCAgMTIgKysKIGRyaXZlcnMvcHdtL01ha2VmaWxlICB8ICAgMSArCiBkcml2ZXJzL3B3bS9wd20t aXBxLmMgfCAyNzggKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrCiAz IGZpbGVzIGNoYW5nZWQsIDI5MSBpbnNlcnRpb25zKCspCiBjcmVhdGUgbW9kZSAxMDA2NDQgZHJp dmVycy9wd20vcHdtLWlwcS5jCgpkaWZmIC0tZ2l0IGEvZHJpdmVycy9wd20vS2NvbmZpZyBiL2Ry aXZlcnMvcHdtL0tjb25maWcKaW5kZXggYzc2YWRlZGQ1OGM5Li4wOGFkZDg0NTU5NmYgMTAwNjQ0 Ci0tLSBhL2RyaXZlcnMvcHdtL0tjb25maWcKKysrIGIvZHJpdmVycy9wd20vS2NvbmZpZwpAQCAt MjYwLDYgKzI2MCwxOCBAQCBjb25maWcgUFdNX0lOVEVMX0xHTQogCSAgVG8gY29tcGlsZSB0aGlz IGRyaXZlciBhcyBhIG1vZHVsZSwgY2hvb3NlIE0gaGVyZTogdGhlIG1vZHVsZQogCSAgd2lsbCBi ZSBjYWxsZWQgcHdtLWludGVsLWxnbS4KIAorY29uZmlnIFBXTV9JUFEKKwl0cmlzdGF0ZSAiSVBR IFBXTSBzdXBwb3J0IgorCWRlcGVuZHMgb24gQVJDSF9RQ09NIHx8IENPTVBJTEVfVEVTVAorCWRl cGVuZHMgb24gSEFWRV9DTEsgJiYgSEFTX0lPTUVNCisJaGVscAorCSAgR2VuZXJpYyBQV00gZnJh bWV3b3JrIGRyaXZlciBmb3IgSVBRIFBXTSBibG9jayB3aGljaCBzdXBwb3J0cworCSAgNCBwd20g Y2hhbm5lbHMuIEVhY2ggb2YgdGhlIHRoZXNlIGNoYW5uZWxzIGNhbiBiZSBjb25maWd1cmVkCisJ ICBpbmRlcGVuZGVudCBvZiBlYWNoIG90aGVyLgorCisJICBUbyBjb21waWxlIHRoaXMgZHJpdmVy IGFzIGEgbW9kdWxlLCBjaG9vc2UgTSBoZXJlOiB0aGUgbW9kdWxlCisJICB3aWxsIGJlIGNhbGxl ZCBwd20taXBxLgorCiBjb25maWcgUFdNX0lRUzYyMEEKIAl0cmlzdGF0ZSAiQXpvdGVxIElRUzYy MEEgUFdNIHN1cHBvcnQiCiAJZGVwZW5kcyBvbiBNRkRfSVFTNjJYIHx8IENPTVBJTEVfVEVTVApk aWZmIC0tZ2l0IGEvZHJpdmVycy9wd20vTWFrZWZpbGUgYi9kcml2ZXJzL3B3bS9NYWtlZmlsZQpp bmRleCA3MDg4NDBiN2ZiYTguLjc0MDJmZWFlNGIzNiAxMDA2NDQKLS0tIGEvZHJpdmVycy9wd20v TWFrZWZpbGUKKysrIGIvZHJpdmVycy9wd20vTWFrZWZpbGUKQEAgLTIyLDYgKzIyLDcgQEAgb2Jq LSQoQ09ORklHX1BXTV9JTVgxKQkJKz0gcHdtLWlteDEubwogb2JqLSQoQ09ORklHX1BXTV9JTVgy NykJCSs9IHB3bS1pbXgyNy5vCiBvYmotJChDT05GSUdfUFdNX0lNWF9UUE0pCSs9IHB3bS1pbXgt dHBtLm8KIG9iai0kKENPTkZJR19QV01fSU5URUxfTEdNKQkrPSBwd20taW50ZWwtbGdtLm8KK29i ai0kKENPTkZJR19QV01fSVBRKQkJKz0gcHdtLWlwcS5vCiBvYmotJChDT05GSUdfUFdNX0lRUzYy MEEpCSs9IHB3bS1pcXM2MjBhLm8KIG9iai0kKENPTkZJR19QV01fSlo0NzQwKQkrPSBwd20tano0 NzQwLm8KIG9iai0kKENPTkZJR19QV01fS0VFTUJBWSkJKz0gcHdtLWtlZW1iYXkubwpkaWZmIC0t Z2l0IGEvZHJpdmVycy9wd20vcHdtLWlwcS5jIGIvZHJpdmVycy9wd20vcHdtLWlwcS5jCm5ldyBm aWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAwMDAwMC4uZGRmYmU5NTgxNmE0Ci0tLSAvZGV2 L251bGwKKysrIGIvZHJpdmVycy9wd20vcHdtLWlwcS5jCkBAIC0wLDAgKzEsMjc4IEBACisvLyBT UERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQlNELTMtQ2xhdXNlIE9SIEdQTC0yLjAKKy8qCisgKiBD b3B5cmlnaHQgKGMpIDIwMTYtMjAxNywgMjAyMCBUaGUgTGludXggRm91bmRhdGlvbi4gQWxsIHJp Z2h0cyByZXNlcnZlZC4KKyAqLworCisjaW5jbHVkZSA8bGludXgvbW9kdWxlLmg+CisjaW5jbHVk ZSA8bGludXgvcGxhdGZvcm1fZGV2aWNlLmg+CisjaW5jbHVkZSA8bGludXgvcHdtLmg+CisjaW5j bHVkZSA8bGludXgvY2xrLmg+CisjaW5jbHVkZSA8bGludXgvaW8uaD4KKyNpbmNsdWRlIDxsaW51 eC9tYXRoNjQuaD4KKyNpbmNsdWRlIDxsaW51eC9vZl9kZXZpY2UuaD4KKyNpbmNsdWRlIDxsaW51 eC9tZmQvc3lzY29uLmg+CisjaW5jbHVkZSA8bGludXgvcmVnbWFwLmg+CisKKyNkZWZpbmUgSVBR X1BXTV9NQVhfREVWSUNFUwk0CisKKy8qIFRoZSBmcmVxdWVuY3kgcmFuZ2Ugc3VwcG9ydGVkIGlz IDFIeiB0byAxMDBNSHogKi8KKyNkZWZpbmUgSVBRX1BXTV9DTEtfU1JDX0ZSRVEJKDEwMCoxMDAw KjEwMDApCisjZGVmaW5lIElQUV9QV01fTUlOX1BFUklPRF9OUwkoTlNFQ19QRVJfU0VDIC8gSVBR X1BXTV9DTEtfU1JDX0ZSRVEpCisjZGVmaW5lIElQUV9QV01fTUFYX1BFUklPRF9OUwkoKHU2NClO U0VDX1BFUl9TRUMpCisKKy8qCisgKiBUaGUgbWF4IHZhbHVlIHNwZWNpZmllZCBmb3IgZWFjaCBm aWVsZCBpcyBiYXNlZCBvbiB0aGUgbnVtYmVyIG9mIGJpdHMKKyAqIGluIHRoZSBwd20gY29udHJv bCByZWdpc3RlciBmb3IgdGhhdCBmaWVsZAorICovCisjZGVmaW5lIElQUV9QV01fTUFYX0RJVgkJ MHhGRkZGCisKKyNkZWZpbmUgSVBRX1BXTV9DRkdfUkVHMCAwIC8qUFdNX0RJViBQV01fSEkqLwor I2RlZmluZSBJUFFfUFdNX1JFRzBfUFdNX0RJVgkJR0VOTUFTSygxNSwgMCkKKyNkZWZpbmUgSVBR X1BXTV9SRUcwX0hJX0RVUkFUSU9OCUdFTk1BU0soMzEsIDE2KQorCisjZGVmaW5lIElQUV9QV01f Q0ZHX1JFRzEgMSAvKkVOQUJMRSBVUERBVEUgUFdNX1BSRV9ESVYqLworI2RlZmluZSBJUFFfUFdN X1JFRzFfUFJFX0RJVgkJR0VOTUFTSygxNSwgMCkKKy8qCisgKiBFbmFibGUgYml0IGlzIHNldCB0 byBlbmFibGUgb3V0cHV0IHRvZ2dsaW5nIGluIHB3bSBkZXZpY2UuCisgKiBVcGRhdGUgYml0IGlz IHNldCB0byByZWZsZWN0IHRoZSBjaGFuZ2VkIGRpdmlkZXIgYW5kIGhpZ2ggZHVyYXRpb24KKyAq IHZhbHVlcyBpbiByZWdpc3Rlci4KKyAqLworI2RlZmluZSBJUFFfUFdNX1JFRzFfVVBEQVRFCQlC SVQoMzApCisjZGVmaW5lIElQUV9QV01fUkVHMV9FTkFCTEUJCUJJVCgzMSkKKworCitzdHJ1Y3Qg aXBxX3B3bV9jaGlwIHsKKwlzdHJ1Y3QgcHdtX2NoaXAgY2hpcDsKKwlzdHJ1Y3QgY2xrICpjbGs7 CisJc3RydWN0IHJlZ21hcCAqcmVnbWFwOworCXUzMiByZWdtYXBfb2ZmOworfTsKKworc3RhdGlj IHN0cnVjdCBpcHFfcHdtX2NoaXAgKnRvX2lwcV9wd21fY2hpcChzdHJ1Y3QgcHdtX2NoaXAgKmNo aXApCit7CisJcmV0dXJuIGNvbnRhaW5lcl9vZihjaGlwLCBzdHJ1Y3QgaXBxX3B3bV9jaGlwLCBj aGlwKTsKK30KKworc3RhdGljIHVuc2lnbmVkIGlwcV9wd21fcmVnX29mZnNldChzdHJ1Y3QgcHdt X2RldmljZSAqcHdtLCB1bnNpZ25lZCByZWcpCit7CisJcmV0dXJuICgocHdtLT5od3B3bSAqIDIp ICsgcmVnKSAqIDQ7Cit9CisKK3N0YXRpYyB1bnNpZ25lZCBpbnQgaXBxX3B3bV9yZWdfcmVhZChz dHJ1Y3QgcHdtX2RldmljZSAqcHdtLCB1bnNpZ25lZCByZWcpCit7CisJc3RydWN0IGlwcV9wd21f Y2hpcCAqaXBxX2NoaXAgPSB0b19pcHFfcHdtX2NoaXAocHdtLT5jaGlwKTsKKwl1bnNpZ25lZCBp bnQgb2ZmID0gaXBxX2NoaXAtPnJlZ21hcF9vZmYgKyBpcHFfcHdtX3JlZ19vZmZzZXQocHdtLCBy ZWcpOworCXVuc2lnbmVkIGludCB2YWw7CisKKwlyZWdtYXBfcmVhZChpcHFfY2hpcC0+cmVnbWFw LCBvZmYsICZ2YWwpOworCisJcmV0dXJuIHZhbDsKK30KKworc3RhdGljIHZvaWQgaXBxX3B3bV9y ZWdfd3JpdGUoc3RydWN0IHB3bV9kZXZpY2UgKnB3bSwgdW5zaWduZWQgcmVnLAorCQl1bnNpZ25l ZCB2YWwpCit7CisJc3RydWN0IGlwcV9wd21fY2hpcCAqaXBxX2NoaXAgPSB0b19pcHFfcHdtX2No aXAocHdtLT5jaGlwKTsKKwl1bnNpZ25lZCBpbnQgb2ZmID0gaXBxX2NoaXAtPnJlZ21hcF9vZmYg KyBpcHFfcHdtX3JlZ19vZmZzZXQocHdtLCByZWcpOworCisJcmVnbWFwX3dyaXRlKGlwcV9jaGlw LT5yZWdtYXAsIG9mZiwgdmFsKTsKK30KKworc3RhdGljIHZvaWQgY29uZmlnX2Rpdl9hbmRfZHV0 eShzdHJ1Y3QgcHdtX2RldmljZSAqcHdtLCB1bnNpZ25lZCBpbnQgcHJlX2RpdiwKKwkJCXVuc2ln bmVkIGludCBwd21fZGl2LCB1NjQgcGVyaW9kX25zLCB1NjQgZHV0eV9ucywKKwkJCWJvb2wgZW5h YmxlKQoreworCXVuc2lnbmVkIGxvbmcgaGlfZHVyOworCXVuc2lnbmVkIGxvbmcgbG9uZyBxdW90 aWVudDsKKwl1bnNpZ25lZCBsb25nIHZhbCA9IDA7CisKKwkvKgorCSAqIGhpZ2ggZHVyYXRpb24g PSBwd20gZHV0eSAqIChwd20gZGl2ICsgMSkKKwkgKiBwd20gZHV0eSA9IGR1dHlfbnMgLyBwZXJp b2RfbnMKKwkgKi8KKwlxdW90aWVudCA9IChwd21fZGl2ICsgMSkgKiBkdXR5X25zOworCWhpX2R1 ciA9IGRpdjY0X3U2NChxdW90aWVudCwgcGVyaW9kX25zKTsKKworCXZhbCA9IEZJRUxEX1BSRVAo SVBRX1BXTV9SRUcwX0hJX0RVUkFUSU9OLCBoaV9kdXIpIHwKKwkJRklFTERfUFJFUChJUFFfUFdN X1JFRzBfUFdNX0RJViwgcHdtX2Rpdik7CisJaXBxX3B3bV9yZWdfd3JpdGUocHdtLCBJUFFfUFdN X0NGR19SRUcwLCB2YWwpOworCisJdmFsID0gRklFTERfUFJFUChJUFFfUFdNX1JFRzFfUFJFX0RJ ViwgcHJlX2Rpdik7CisJaXBxX3B3bV9yZWdfd3JpdGUocHdtLCBJUFFfUFdNX0NGR19SRUcxLCB2 YWwpOworCisJLyogRW5hYmxlIG5lZWRzIGEgc2VwYXJhdGUgd3JpdGUgdG8gUkVHMSAqLworCXZh bCB8PSBJUFFfUFdNX1JFRzFfVVBEQVRFOworCWlmIChlbmFibGUpCisJCXZhbCB8PSBJUFFfUFdN X1JFRzFfRU5BQkxFOworCWVsc2UKKwkJdmFsICY9IH5JUFFfUFdNX1JFRzFfRU5BQkxFOworCWlw cV9wd21fcmVnX3dyaXRlKHB3bSwgSVBRX1BXTV9DRkdfUkVHMSwgdmFsKTsKK30KKworc3RhdGlj IGludCBpcHFfcHdtX2FwcGx5KHN0cnVjdCBwd21fY2hpcCAqY2hpcCwgc3RydWN0IHB3bV9kZXZp Y2UgKnB3bSwKKwkJCSBjb25zdCBzdHJ1Y3QgcHdtX3N0YXRlICpzdGF0ZSkKK3sKKwlzdHJ1Y3Qg aXBxX3B3bV9jaGlwICppcHFfY2hpcCA9IHRvX2lwcV9wd21fY2hpcChjaGlwKTsKKwl1bnNpZ25l ZCBsb25nIGZyZXE7CisJdW5zaWduZWQgaW50IHByZV9kaXYsIHB3bV9kaXYsIGNsb3NlX3ByZV9k aXYsIGNsb3NlX3B3bV9kaXY7CisJbG9uZyBsb25nIGRpZmY7CisJdW5zaWduZWQgbG9uZyByYXRl ID0gY2xrX2dldF9yYXRlKGlwcV9jaGlwLT5jbGspOworCXVuc2lnbmVkIGxvbmcgbWluX2RpZmYg PSByYXRlOworCXVpbnQ2NF90IGZpbl9wczsKKwl1NjQgcGVyaW9kX25zLCBkdXR5X25zOworCisJ aWYgKHN0YXRlLT5wZXJpb2QgPCBJUFFfUFdNX01JTl9QRVJJT0RfTlMpCisJCXJldHVybiAtRVJB TkdFOworCisJcGVyaW9kX25zID0gbWluKHN0YXRlLT5wZXJpb2QsIElQUV9QV01fTUFYX1BFUklP RF9OUyk7CisJZHV0eV9ucyA9IG1pbihzdGF0ZS0+ZHV0eV9jeWNsZSwgcGVyaW9kX25zKTsKKwor CS8qIGZyZXEgaW4gSHogZm9yIHBlcmlvZCBpbiBuYW5vIHNlY29uZCAqLworCWZyZXEgPSBkaXY2 NF91NjQoTlNFQ19QRVJfU0VDLCBwZXJpb2RfbnMpOworCWZpbl9wcyA9IGRpdjY0X3U2NChOU0VD X1BFUl9TRUMgKiAxMDAwVUxMLCByYXRlKTsKKwljbG9zZV9wcmVfZGl2ID0gSVBRX1BXTV9NQVhf RElWOworCWNsb3NlX3B3bV9kaXYgPSBJUFFfUFdNX01BWF9ESVY7CisKKwlmb3IgKHByZV9kaXYg PSAwOyBwcmVfZGl2IDw9IElQUV9QV01fTUFYX0RJVjsgcHJlX2RpdisrKSB7CisJCXB3bV9kaXYg PSBESVY2NF9VNjRfUk9VTkRfQ0xPU0VTVChwZXJpb2RfbnMgKiAxMDAwLAorCQkJCQkJICBmaW5f cHMgKiAocHJlX2RpdiArIDEpKTsKKwkJcHdtX2Rpdi0tOworCQlpZiAocHdtX2RpdiA+IElQUV9Q V01fTUFYX0RJVikKKwkJCWNvbnRpbnVlOworCisJCWRpZmYgPSAoKHVpbnQ2NF90KWZyZXEgKiAo cHJlX2RpdiArIDEpICogKHB3bV9kaXYgKyAxKSkKKwkJCS0gKHVpbnQ2NF90KXJhdGU7CisKKwkJ aWYgKGRpZmYgPCAwKSAvKiBwZXJpb2QgbGFyZ2VyIHRoYW4gcmVxdWVzdGVkICovCisJCQljb250 aW51ZTsKKwkJaWYgKGRpZmYgPT0gMCkgeyAvKiBiaW5nbyAqLworCQkJY2xvc2VfcHJlX2RpdiA9 IHByZV9kaXY7CisJCQljbG9zZV9wd21fZGl2ID0gcHdtX2RpdjsKKwkJCWJyZWFrOworCQl9CisJ CWlmIChkaWZmIDwgbWluX2RpZmYpIHsKKwkJCW1pbl9kaWZmID0gZGlmZjsKKwkJCWNsb3NlX3By ZV9kaXYgPSBwcmVfZGl2OworCQkJY2xvc2VfcHdtX2RpdiA9IHB3bV9kaXY7CisJCX0KKwl9CisK KwkvKiBjb25maWcgZGl2aWRlciB2YWx1ZXMgZm9yIHRoZSBjbG9zZXN0IHBvc3NpYmxlIGZyZXF1 ZW5jeSAqLworCWNvbmZpZ19kaXZfYW5kX2R1dHkocHdtLCBjbG9zZV9wcmVfZGl2LCBjbG9zZV9w d21fZGl2LAorCQkJICAgIHBlcmlvZF9ucywgZHV0eV9ucywgc3RhdGUtPmVuYWJsZWQpOworCisJ cmV0dXJuIDA7Cit9CisKK3N0YXRpYyB2b2lkIGlwcV9wd21fZ2V0X3N0YXRlKHN0cnVjdCBwd21f Y2hpcCAqY2hpcCwgc3RydWN0IHB3bV9kZXZpY2UgKnB3bSwKKwkJCSAgICAgIHN0cnVjdCBwd21f c3RhdGUgKnN0YXRlKQoreworCXN0cnVjdCBpcHFfcHdtX2NoaXAgKmlwcV9jaGlwID0gdG9faXBx X3B3bV9jaGlwKGNoaXApOworCXVuc2lnbmVkIGxvbmcgcmF0ZSA9IGNsa19nZXRfcmF0ZShpcHFf Y2hpcC0+Y2xrKTsKKwl1bnNpZ25lZCBpbnQgcHJlX2RpdiwgcHdtX2RpdiwgaGlfZHVyOworCXU2 NCBlZmZlY3RpdmVfZGl2LCBoaV9kaXY7CisJdTMyIHJlZzAsIHJlZzE7CisKKwlyZWcwID0gaXBx X3B3bV9yZWdfcmVhZChwd20sIElQUV9QV01fQ0ZHX1JFRzApOworCXJlZzEgPSBpcHFfcHdtX3Jl Z19yZWFkKHB3bSwgSVBRX1BXTV9DRkdfUkVHMSk7CisKKwlzdGF0ZS0+cG9sYXJpdHkgPSBQV01f UE9MQVJJVFlfTk9STUFMOworCXN0YXRlLT5lbmFibGVkID0gcmVnMSAmIElQUV9QV01fUkVHMV9F TkFCTEU7CisKKwlwd21fZGl2ID0gRklFTERfR0VUKElQUV9QV01fUkVHMF9QV01fRElWLCByZWcw KTsKKwloaV9kdXIgPSBGSUVMRF9HRVQoSVBRX1BXTV9SRUcwX0hJX0RVUkFUSU9OLCByZWcwKTsK KwlwcmVfZGl2ID0gRklFTERfR0VUKElQUV9QV01fUkVHMV9QUkVfRElWLCByZWcxKTsKKworCWVm ZmVjdGl2ZV9kaXYgPSAocHJlX2RpdiArIDEpICogKHB3bV9kaXYgKyAxKTsKKwlzdGF0ZS0+cGVy aW9kID0gZGl2NjRfdTY0KGVmZmVjdGl2ZV9kaXYgKiBOU0VDX1BFUl9TRUMsIHJhdGUpOworCisJ aGlfZGl2ID0gaGlfZHVyICogKHByZV9kaXYgKyAxKTsKKwlzdGF0ZS0+ZHV0eV9jeWNsZSA9IGRp djY0X3U2NChoaV9kaXYgKiBOU0VDX1BFUl9TRUMsIHJhdGUpOworfQorCitzdGF0aWMgc3RydWN0 IHB3bV9vcHMgaXBxX3B3bV9vcHMgPSB7CisJLmFwcGx5ID0gaXBxX3B3bV9hcHBseSwKKwkuZ2V0 X3N0YXRlID0gaXBxX3B3bV9nZXRfc3RhdGUsCisJLm93bmVyID0gVEhJU19NT0RVTEUsCit9Owor CitzdGF0aWMgaW50IGlwcV9wd21fcHJvYmUoc3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRldikK K3sKKwlzdHJ1Y3QgaXBxX3B3bV9jaGlwICpwd207CisJc3RydWN0IGRldmljZSAqZGV2ID0gJnBk ZXYtPmRldjsKKwlzdHJ1Y3Qgb2ZfcGhhbmRsZV9hcmdzIGFyZ3M7CisJaW50IHJldDsKKworCXB3 bSA9IGRldm1fa3phbGxvYyhkZXYsIHNpemVvZigqcHdtKSwgR0ZQX0tFUk5FTCk7CisJaWYgKCFw d20pCisJCXJldHVybiAtRU5PTUVNOworCisJcGxhdGZvcm1fc2V0X2RydmRhdGEocGRldiwgcHdt KTsKKworCXJldCA9IG9mX3BhcnNlX3BoYW5kbGVfd2l0aF9maXhlZF9hcmdzKGRldi0+b2Zfbm9k ZSwgInFjb20scHdtLXJlZ3MiLAorCQkJMSwgMCwgJmFyZ3MpOworCWlmIChyZXQpCisJCXJldHVy biBkZXZfZXJyX3Byb2JlKGRldiwgcmV0LCAicmVncyBwYXJzZSBmYWlsZWQiKTsKKworCXB3bS0+ cmVnbWFwID0gc3lzY29uX25vZGVfdG9fcmVnbWFwKGFyZ3MubnApOworCW9mX25vZGVfcHV0KGFy Z3MubnApOworCWlmIChJU19FUlIocHdtLT5yZWdtYXApKQorCQlyZXR1cm4gZGV2X2Vycl9wcm9i ZShkZXYsIFBUUl9FUlIocHdtLT5yZWdtYXApLAorCQkJCSJyZWdzIG1hcCBmYWlsZWQiKTsKKwlw d20tPnJlZ21hcF9vZmYgPSBhcmdzLmFyZ3NbMF07CisKKwlwd20tPmNsayA9IGRldm1fY2xrX2dl dChkZXYsICJjb3JlIik7CisJaWYgKElTX0VSUihwd20tPmNsaykpCisJCXJldHVybiBkZXZfZXJy X3Byb2JlKGRldiwgUFRSX0VSUihwd20tPmNsayksCisJCQkJImZhaWxlZCB0byBnZXQgY29yZSBj bG9jayIpOworCisJcmV0ID0gY2xrX3NldF9yYXRlKHB3bS0+Y2xrLCBJUFFfUFdNX0NMS19TUkNf RlJFUSk7CisJaWYgKHJldCkKKwkJcmV0dXJuIGRldl9lcnJfcHJvYmUoZGV2LCByZXQsICJjbG9j ayByYXRlIHNldCBmYWlsZWQiKTsKKworCXJldCA9IGNsa19wcmVwYXJlX2VuYWJsZShwd20tPmNs ayk7CisJaWYgKHJldCkKKwkJcmV0dXJuIGRldl9lcnJfcHJvYmUoZGV2LCByZXQsICJjbG9jayBl bmFibGUgZmFpbGVkIik7CisKKwlwd20tPmNoaXAuZGV2ID0gZGV2OworCXB3bS0+Y2hpcC5vcHMg PSAmaXBxX3B3bV9vcHM7CisJcHdtLT5jaGlwLm5wd20gPSBJUFFfUFdNX01BWF9ERVZJQ0VTOwor CisJcmV0ID0gcHdtY2hpcF9hZGQoJnB3bS0+Y2hpcCk7CisJaWYgKHJldCA8IDApIHsKKwkJZGV2 X2Vycl9wcm9iZShkZXYsIHJldCwgInB3bWNoaXBfYWRkKCkgZmFpbGVkXG4iKTsKKwkJY2xrX2Rp c2FibGVfdW5wcmVwYXJlKHB3bS0+Y2xrKTsKKwkJcmV0dXJuIHJldDsKKwl9CisKKwlyZXR1cm4g MDsKK30KKworc3RhdGljIGludCBpcHFfcHdtX3JlbW92ZShzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNl ICpwZGV2KQoreworCXN0cnVjdCBpcHFfcHdtX2NoaXAgKnB3bSA9IHBsYXRmb3JtX2dldF9kcnZk YXRhKHBkZXYpOworCisJY2xrX2Rpc2FibGVfdW5wcmVwYXJlKHB3bS0+Y2xrKTsKKwlwd21jaGlw X3JlbW92ZSgmcHdtLT5jaGlwKTsKKworCXJldHVybiAwOworfQorCitzdGF0aWMgY29uc3Qgc3Ry dWN0IG9mX2RldmljZV9pZCBwd21faXBxX2R0X21hdGNoW10gPSB7CisJeyAuY29tcGF0aWJsZSA9 ICJxY29tLGlwcTYwMTgtcHdtIiwgfSwKKwl7fQorfTsKK01PRFVMRV9ERVZJQ0VfVEFCTEUob2Ys IHB3bV9pcHFfZHRfbWF0Y2gpOworCitzdGF0aWMgc3RydWN0IHBsYXRmb3JtX2RyaXZlciBpcHFf cHdtX2RyaXZlciA9IHsKKwkuZHJpdmVyID0geworCQkubmFtZSA9ICJpcHEtcHdtIiwKKwkJLm9m X21hdGNoX3RhYmxlID0gcHdtX2lwcV9kdF9tYXRjaCwKKwl9LAorCS5wcm9iZSA9IGlwcV9wd21f cHJvYmUsCisJLnJlbW92ZSA9IGlwcV9wd21fcmVtb3ZlLAorfTsKKworbW9kdWxlX3BsYXRmb3Jt X2RyaXZlcihpcHFfcHdtX2RyaXZlcik7CisKK01PRFVMRV9MSUNFTlNFKCJEdWFsIEJTRC9HUEwi KTsKLS0gCjIuMzAuMgoKCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fCmxpbnV4LWFybS1rZXJuZWwgbWFpbGluZyBsaXN0CmxpbnV4LWFybS1rZXJuZWxAbGlz dHMuaW5mcmFkZWFkLm9yZwpodHRwOi8vbGlzdHMuaW5mcmFkZWFkLm9yZy9tYWlsbWFuL2xpc3Rp bmZvL2xpbnV4LWFybS1rZXJuZWwK