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 Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D95D3CCA48C for ; Fri, 22 Jul 2022 16:49:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235575AbiGVQtE (ORCPT ); Fri, 22 Jul 2022 12:49:04 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44232 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229771AbiGVQtA (ORCPT ); Fri, 22 Jul 2022 12:49:00 -0400 Received: from out28-51.mail.aliyun.com (out28-51.mail.aliyun.com [115.124.28.51]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8D98593C2D; Fri, 22 Jul 2022 09:48:57 -0700 (PDT) X-Alimail-AntiSpam: AC=CONTINUE;BC=0.07436282|-1;CH=green;DM=|CONTINUE|false|;DS=CONTINUE|ham_system_inform|0.0318391-0.00029028-0.967871;FP=0|0|0|0|0|-1|-1|-1;HT=ay29a033018047207;MF=zhouyanjie@wanyeetech.com;NM=1;PH=DS;RN=23;RT=23;SR=0;TI=SMTPD_---.Ob0cnP9_1658508531; Received: from localhost.localdomain(mailfrom:zhouyanjie@wanyeetech.com fp:SMTPD_---.Ob0cnP9_1658508531) by smtp.aliyun-inc.com; Sat, 23 Jul 2022 00:48:52 +0800 From: =?UTF-8?q?=E5=91=A8=E7=90=B0=E6=9D=B0=20=28Zhou=20Yanjie=29?= To: tudor.ambarus@microchip.com, p.yadav@ti.com, michael@walle.cc, miquel.raynal@bootlin.com, richard@nod.at, vigneshr@ti.com, broonie@kernel.org, robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org Cc: linux-mtd@lists.infradead.org, linux-spi@vger.kernel.org, linux-mips@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, aidanmacdonald.0x0@gmail.com, tmn505@gmail.com, paul@crapouillou.net, dongsheng.qiu@ingenic.com, aric.pzqi@ingenic.com, rick.tyliu@ingenic.com, jinghui.liu@ingenic.com, sernia.zhou@foxmail.com, reimu@sudomaker.com Subject: [PATCH 3/3] SPI: Ingenic: Add SFC support for Ingenic SoCs. Date: Sat, 23 Jul 2022 00:48:30 +0800 Message-Id: <1658508510-15400-4-git-send-email-zhouyanjie@wanyeetech.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1658508510-15400-1-git-send-email-zhouyanjie@wanyeetech.com> References: <1658508510-15400-1-git-send-email-zhouyanjie@wanyeetech.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add SFC support for the X1000 SoC, the X1600 SoC, and the X2000 SoC from Ingenic. Signed-off-by: 周琰杰 (Zhou Yanjie) --- drivers/spi/Kconfig | 9 + drivers/spi/Makefile | 1 + drivers/spi/spi-ingenic-sfc.c | 662 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 672 insertions(+) create mode 100644 drivers/spi/spi-ingenic-sfc.c diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 3b1044e..1077bd3 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -437,6 +437,15 @@ config SPI_INGENIC To compile this driver as a module, choose M here: the module will be called spi-ingenic. +config SPI_INGENIC_SFC + tristate "Ingenic SoCs SPI Flash Controller" + depends on MACH_INGENIC || COMPILE_TEST + help + This enables support for the Ingenic SoCs SPI flash controller. + + To compile this driver as a module, choose M here: the module + will be called ingenic-sfc. + config SPI_INTEL tristate diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 0f44eb6..f3e42c0 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -62,6 +62,7 @@ obj-$(CONFIG_SPI_HISI_SFC_V3XX) += spi-hisi-sfc-v3xx.o obj-$(CONFIG_SPI_IMG_SPFI) += spi-img-spfi.o obj-$(CONFIG_SPI_IMX) += spi-imx.o obj-$(CONFIG_SPI_INGENIC) += spi-ingenic.o +obj-$(CONFIG_SPI_INGENIC_SFC) += spi-ingenic-sfc.o obj-$(CONFIG_SPI_INTEL) += spi-intel.o obj-$(CONFIG_SPI_INTEL_PCI) += spi-intel-pci.o obj-$(CONFIG_SPI_INTEL_PLATFORM) += spi-intel-platform.o diff --git a/drivers/spi/spi-ingenic-sfc.c b/drivers/spi/spi-ingenic-sfc.c new file mode 100644 index 00000000..a565546 --- /dev/null +++ b/drivers/spi/spi-ingenic-sfc.c @@ -0,0 +1,662 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +/* + * Ingenic SoCs SPI Flash Controller Driver + * Copyright (c) 2022 周琰杰 (Zhou Yanjie) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* SFC register offsets */ +#define SFC_REG_GLB 0x0000 +#define SFC_REG_DEV_CONF 0x0004 +#define SFC_REG_DEV_STA_EXP 0x0008 +#define SFC_REG_DEV_STA_RT 0x000c +#define SFC_REG_DEV_STA_MSK 0x0010 +#define SFC_REG_TRAN_CONF(n) (0x0014 + n * 4) +#define SFC_REG_TRAN_CFG0(n) (0x0014 + n * 4) +#define SFC_REG_TRAN_LEN 0x002c +#define SFC_REG_DEV_ADDR(n) (0x0030 + n * 4) +#define SFC_REG_DEV_ADDR_PLUS(n) (0x0048 + n * 4) +#define SFC_REG_MEM_ADDR 0x0060 +#define SFC_REG_TRIG 0x0064 +#define SFC_REG_SR 0x0068 +#define SFC_REG_SCR 0x006c +#define SFC_REG_INTC 0x0070 +#define SFC_REG_FSM 0x0074 +#define SFC_REG_CGE 0x0078 +#define SFC_REG_TRAN_CFG1(n) (0x009c + n * 4) +#define SFC_REG_DR 0x1000 + +/* bits within the GLB register */ +#define GLB_TRAN_DIR_MASK GENMASK(13, 13) +#define GLB_TRAN_DIR_WRITE 0x1 +#define GLB_TRAN_DIR_READ 0x0 +#define GLB_THRESHOLD_MASK GENMASK(12, 7) +#define GLB_OP_MODE_MASK GENMASK(6, 6) +#define GLB_OP_MODE_DMA 0x1 +#define GLB_OP_MODE_SLAVE 0x0 +#define GLB_PHASE_NUM_MASK GENMASK(5, 3) +#define GLB_WP_EN BIT(2) +#define GLB_BURST_MD_MASK GENMASK(1, 0) +#define GLB_BURST_MD_INCR32 0x3 +#define GLB_BURST_MD_INCR16 0x2 +#define GLB_BURST_MD_INCR8 0x1 +#define GLB_BURST_MD_INCR4 0x0 + +/* bits within the DEV_CONF register */ +#define DEV_CONF_SMP_DELAY_MASK GENMASK(20, 16) +#define DEV_CONF_SMP_DELAY_180DEG 0x4 +#define DEV_CONF_SMP_DELAY_HALF_CYCLE 0x1 +#define DEV_CONF_CMD_TYPE_MASK GENMASK(15, 15) +#define DEV_CONF_CMD_TYPE_16BIT 0x1 +#define DEV_CONF_CMD_TYPE_8BIT 0x0 +#define DEV_CONF_STA_TYPE_MASK GENMASK(14, 13) +#define DEV_CONF_THOLD_MASK GENMASK(12, 11) +#define DEV_CONF_TSETUP_MASK GENMASK(10, 9) +#define DEV_CONF_TSH_MASK GENMASK(8, 5) +#define DEV_CONF_CPHA BIT(4) +#define DEV_CONF_CPOL BIT(3) +#define DEV_CONF_CE_DL BIT(2) +#define DEV_CONF_HOLD_DL BIT(1) +#define DEV_CONF_WP_DL BIT(0) + +/* bits within the TRAN_CONF(n) register */ +#define TRAN_CONF_TRAN_MODE_MASK GENMASK(31, 29) +#define TRAN_CONF_ADDR_WIDTH_MASK GENMASK(28, 26) +#define TRAN_CONF_POLL_EN BIT(25) +#define TRAN_CONF_CMD_EN BIT(24) +#define TRAN_CONF_PHASE_FORMAT_MASK GENMASK(23, 23) +#define TRAN_CONF_DMY_BITS_MASK GENMASK(22, 17) +#define TRAN_CONF_DATA_EN BIT(16) +#define TRAN_CONF_CMD_MASK GENMASK(15, 0) + +/* bits within the TRIG register */ +#define TRIG_FLUSH BIT(2) +#define TRIG_STOP BIT(1) +#define TRIG_START BIT(0) + +/* bits within the SR register */ +#define SR_FIFO_NUM_MASK GENMASK(22, 16) +#define SR_END BIT(4) +#define SR_TRAN_REQ BIT(3) +#define SR_RECE_REQ BIT(2) +#define SR_OVER BIT(1) +#define SR_UNDER BIT(0) + +/* bits within the SCR register */ +#define SCR_CLR_END BIT(4) +#define SCR_CLR_TREQ BIT(3) +#define SCR_CLR_RREQ BIT(2) +#define SCR_CLR_OVER BIT(1) +#define SCR_CLR_UNDER BIT(0) + +/* bits within the INTC register */ +#define INTC_MASK_END BIT(4) +#define INTC_MASK_TREQ BIT(3) +#define INTC_MASK_RREQ BIT(2) +#define INTC_MASK_OVER BIT(1) +#define INTC_MASK_UNDER BIT(0) + +/* bits within the TRAN_CFG1(n) register */ +#define TRAN_CFG1_TRAN_MODE_MASK GENMASK(7, 4) + +#define TRAN_MODE_STANDARD 0 +#define TRAN_MODE_DUAL_DATA 1 +#define TRAN_MODE_DUAL_IO 2 +#define TRAN_MODE_DUAL_FULL 3 +#define TRAN_MODE_QUAD_DATA 5 +#define TRAN_MODE_QUAD_IO 6 +#define TRAN_MODE_QUAD_FULL 7 +#define TRAN_MODE_OCTAL_DATA 9 +#define TRAN_MODE_OCTAL_IO 10 +#define TRAN_MODE_OCTAL_FULL 11 + +#define INGENIC_SFC_FIFO_SIZE (64 * 4) + +#define INGENIC_SFC_TRANSFER_TIMEOUT 1000 + +enum ingenic_sfc_version { + ID_X1000, + ID_X1600, + ID_X2000, +}; + +struct ingenic_soc_info { + enum ingenic_sfc_version version; + + unsigned int max_bus_width; + + const u32 tran_mode_mask; +}; + +struct ingenic_sfc { + const struct ingenic_soc_info *soc_info; + + void __iomem *base; + struct device *dev; + struct clk *clk; + int irq; + + struct completion completion; +}; + +static irqreturn_t ingenic_sfc_irq_handler(int irq, void *data) +{ + struct ingenic_sfc *sfc = data; + + writel(0x1f, sfc->base + SFC_REG_INTC); + + complete(&sfc->completion); + + return IRQ_HANDLED; +} + +static int ingenic_sfc_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op) +{ + uintptr_t addr = (uintptr_t)op->data.buf.in; + + if (op->data.nbytes > INGENIC_SFC_FIFO_SIZE && !IS_ALIGNED(addr, 4)) + op->data.nbytes = INGENIC_SFC_FIFO_SIZE; + + return 0; +} + +static bool ingenic_sfc_supports_op(struct spi_mem *mem, const struct spi_mem_op *op) +{ + struct spi_device *spi = mem->spi; + struct ingenic_sfc *sfc = spi_controller_get_devdata(spi->master); + uintptr_t addr = (uintptr_t)op->data.buf.in; + + /* The controller only supports Standard SPI mode, Duall mode, Quad mode and Octal mode. */ + if (op->cmd.buswidth > sfc->soc_info->max_bus_width || + op->addr.buswidth > sfc->soc_info->max_bus_width || + op->dummy.buswidth > sfc->soc_info->max_bus_width || + op->data.buswidth > sfc->soc_info->max_bus_width) + return false; + + /* Max 32 dummy clock cycles supported */ + if (op->dummy.nbytes && op->dummy.nbytes * 8 / op->dummy.buswidth > 32) + return false; + + /* Max rx data length, check controller limits and alignment */ + if (op->data.dir == SPI_MEM_DATA_IN && + op->data.nbytes > INGENIC_SFC_FIFO_SIZE && !IS_ALIGNED(addr, 4)) + return false; + + /* Max 6 bytes address width supported */ + if (op->addr.nbytes > 6) + return false; + + return spi_mem_default_supports_op(mem, op); +} + +static void ingenic_sfc_set_transfer_mode(struct ingenic_sfc *sfc, const struct spi_mem_op *op) +{ + int val; + + val = readl(sfc->base + (sfc->soc_info->version >= ID_X1600 ? + SFC_REG_TRAN_CFG1(0) : SFC_REG_TRAN_CONF(0))); + val &= ~sfc->soc_info->tran_mode_mask; + if (op->cmd.buswidth == 8) + val |= (TRAN_MODE_OCTAL_FULL << (ffs(sfc->soc_info->tran_mode_mask) - 1)) & + sfc->soc_info->tran_mode_mask; + else if (op->cmd.buswidth == 4) + val |= (TRAN_MODE_QUAD_FULL << (ffs(sfc->soc_info->tran_mode_mask) - 1)) & + sfc->soc_info->tran_mode_mask; + else if (op->cmd.buswidth == 2) + val |= (TRAN_MODE_DUAL_FULL << (ffs(sfc->soc_info->tran_mode_mask) - 1)) & + sfc->soc_info->tran_mode_mask; + else if (op->addr.buswidth == 8) + val |= (TRAN_MODE_OCTAL_IO << (ffs(sfc->soc_info->tran_mode_mask) - 1)) & + sfc->soc_info->tran_mode_mask; + else if (op->addr.buswidth == 4) + val |= (TRAN_MODE_QUAD_IO << (ffs(sfc->soc_info->tran_mode_mask) - 1)) & + sfc->soc_info->tran_mode_mask; + else if (op->addr.buswidth == 2) + val |= (TRAN_MODE_DUAL_IO << (ffs(sfc->soc_info->tran_mode_mask) - 1)) & + sfc->soc_info->tran_mode_mask; + else if (op->data.buswidth == 8) + val |= (TRAN_MODE_OCTAL_DATA << (ffs(sfc->soc_info->tran_mode_mask) - 1)) & + sfc->soc_info->tran_mode_mask; + else if (op->data.buswidth == 4) + val |= (TRAN_MODE_QUAD_DATA << (ffs(sfc->soc_info->tran_mode_mask) - 1)) & + sfc->soc_info->tran_mode_mask; + else if (op->data.buswidth == 2) + val |= (TRAN_MODE_DUAL_DATA << (ffs(sfc->soc_info->tran_mode_mask) - 1)) & + sfc->soc_info->tran_mode_mask; + else + val |= (TRAN_MODE_STANDARD << (ffs(sfc->soc_info->tran_mode_mask) - 1)) & + sfc->soc_info->tran_mode_mask; + writel(val, sfc->base + (sfc->soc_info->version >= ID_X1600 ? + SFC_REG_TRAN_CFG1(0) : SFC_REG_TRAN_CONF(0))); +} + +/* + * We only need PIO mode to handle the SPI_MEM_NO_DATA transfers, + * and the unaligned accesses in SPI_MEM_DATA_IN transfers. + */ +static void ingenic_sfc_read_rxfifo(struct ingenic_sfc *sfc, u8 *to, unsigned int len) +{ + void __iomem *from; + + from = sfc->base + SFC_REG_DR; + + for (; len >= 4; len -= 4, to += 4) { + u32 val = __raw_readl(from); + memcpy(to, &val, 4); + } + + if (len) { + u32 val = __raw_readl(from); + memcpy(to, &val, len); + } +} + +static int ingenic_sfc_exec_op_pio(struct ingenic_sfc *sfc, const struct spi_mem_op *op) +{ + int ret, val; + + val = readl(sfc->base + SFC_REG_GLB); + u32p_replace_bits(&val, GLB_TRAN_DIR_READ, GLB_TRAN_DIR_MASK); + u32p_replace_bits(&val, GLB_OP_MODE_SLAVE, GLB_OP_MODE_MASK); + writel(val, sfc->base + SFC_REG_GLB); + + val = TRAN_CONF_CMD_EN | op->cmd.opcode; + + if (op->addr.nbytes > 0) { + val |= FIELD_PREP(TRAN_CONF_ADDR_WIDTH_MASK, op->addr.nbytes); + + writel(op->addr.val & 0xffffffff, sfc->base + SFC_REG_DEV_ADDR(0)); + writel(op->addr.val >> 32, sfc->base + SFC_REG_DEV_ADDR_PLUS(0)); + } + + if (op->dummy.nbytes > 0) + val |= FIELD_PREP(TRAN_CONF_DMY_BITS_MASK, + op->dummy.nbytes * 8 / op->dummy.buswidth); + + if (op->data.nbytes > 0) + val |= TRAN_CONF_DATA_EN; + + writel(val, sfc->base + SFC_REG_TRAN_CONF(0)); + writel(op->data.nbytes, sfc->base + SFC_REG_TRAN_LEN); + + ingenic_sfc_set_transfer_mode(sfc, op); + + writel(0x1f, sfc->base + SFC_REG_SCR); + writel(~(INTC_MASK_END | INTC_MASK_RREQ), sfc->base + SFC_REG_INTC); + + writel(0, sfc->base + SFC_REG_MEM_ADDR); + + writel(TRIG_FLUSH, sfc->base + SFC_REG_TRIG); + writel(TRIG_START, sfc->base + SFC_REG_TRIG); + + ret = wait_for_completion_timeout(&sfc->completion, + msecs_to_jiffies(INGENIC_SFC_TRANSFER_TIMEOUT)); + if (!ret) { + writel(0x1f, sfc->base + SFC_REG_INTC); + writel(0x1f, sfc->base + SFC_REG_SCR); + dev_err(sfc->dev, "line:%d Timeout for ACK from SFC device\n", __LINE__); + return -ETIMEDOUT; + } + + ingenic_sfc_read_rxfifo(sfc, op->data.buf.in, op->data.nbytes); + readl_poll_timeout(sfc->base + SFC_REG_SR, val, val & SR_END, 10, 0); + + writel(INTC_MASK_END | INTC_MASK_RREQ, sfc->base + SFC_REG_SCR); + writel(TRIG_STOP, sfc->base + SFC_REG_TRIG); + + return 0; +} + +static int ingenic_sfc_exec_op_dma(struct ingenic_sfc *sfc, const struct spi_mem_op *op) +{ + dma_addr_t addr; + int ret, val; + + val = readl(sfc->base + SFC_REG_GLB); + u32p_replace_bits(&val, op->data.dir == SPI_MEM_DATA_IN ? + GLB_TRAN_DIR_READ : GLB_TRAN_DIR_WRITE, GLB_TRAN_DIR_MASK); + u32p_replace_bits(&val, GLB_OP_MODE_DMA, GLB_OP_MODE_MASK); + writel(val, sfc->base + SFC_REG_GLB); + + val = TRAN_CONF_CMD_EN | op->cmd.opcode; + + if (op->addr.nbytes > 0) { + val |= FIELD_PREP(TRAN_CONF_ADDR_WIDTH_MASK, op->addr.nbytes); + writel(op->addr.val & 0xffffffff, sfc->base + SFC_REG_DEV_ADDR(0)); + writel(op->addr.val >> 32, sfc->base + SFC_REG_DEV_ADDR_PLUS(0)); + } + + if (op->dummy.nbytes > 0) + val |= FIELD_PREP(TRAN_CONF_DMY_BITS_MASK, + op->dummy.nbytes * 8 / op->dummy.buswidth); + + if (op->data.nbytes > 0) + val |= TRAN_CONF_DATA_EN; + + writel(val, sfc->base + SFC_REG_TRAN_CONF(0)); + writel(op->data.nbytes, sfc->base + SFC_REG_TRAN_LEN); + + ingenic_sfc_set_transfer_mode(sfc, op); + + writel(0x1f, sfc->base + SFC_REG_SCR); + writel(~INTC_MASK_END, sfc->base + SFC_REG_INTC); + + switch (op->data.dir) { + case SPI_MEM_DATA_IN: + addr = dma_map_single(sfc->dev, op->data.buf.in, op->data.nbytes, DMA_FROM_DEVICE); + if (dma_mapping_error(sfc->dev, addr)) { + dev_err(sfc->dev, "RX DMA memory not mapped\n"); + return -ENOMEM; + } + + writel(addr, sfc->base + SFC_REG_MEM_ADDR); + break; + + case SPI_MEM_DATA_OUT: + addr = dma_map_single(sfc->dev, (void *)op->data.buf.out, + op->data.nbytes, DMA_TO_DEVICE); + if (dma_mapping_error(sfc->dev, addr)) { + dev_err(sfc->dev, "TX DMA memory not mapped\n"); + return -ENOMEM; + } + + writel(addr, sfc->base + SFC_REG_MEM_ADDR); + break; + + default: + return -EINVAL; + } + + writel(TRIG_START, sfc->base + SFC_REG_TRIG); + + ret = wait_for_completion_timeout(&sfc->completion, + msecs_to_jiffies(INGENIC_SFC_TRANSFER_TIMEOUT)); + if (!ret) { + writel(0x1f, sfc->base + SFC_REG_INTC); + writel(0x1f, sfc->base + SFC_REG_SCR); + dev_err(sfc->dev, "line:%d Timeout for ACK from SFC device\n", __LINE__); + return -ETIMEDOUT; + } + + dma_unmap_single(sfc->dev, addr, op->data.nbytes, + op->data.dir == SPI_MEM_DATA_IN ? DMA_FROM_DEVICE : DMA_TO_DEVICE); + + writel(INTC_MASK_END, sfc->base + SFC_REG_SCR); + writel(TRIG_STOP, sfc->base + SFC_REG_TRIG); + + return 0; +} + +static int ingenic_sfc_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) +{ + struct spi_device *spi = mem->spi; + struct ingenic_sfc *sfc = spi_controller_get_devdata(spi->master); + uintptr_t addr = (uintptr_t)op->data.buf.in; + + init_completion(&sfc->completion); + + switch (op->data.dir) { + case SPI_MEM_DATA_IN: + if (sfc->soc_info->version >= ID_X1600 || IS_ALIGNED(addr, 4)) + break; + + fallthrough; + + case SPI_MEM_NO_DATA: + return ingenic_sfc_exec_op_pio(sfc, op); + + default: + break; + } + + return ingenic_sfc_exec_op_dma(sfc, op); +} + +static int ingenic_sfc_poll_status(struct spi_mem *mem, const struct spi_mem_op *op, + u16 mask, u16 match, unsigned long initial_delay_us, + unsigned long polling_delay_us, unsigned long timeout_ms) +{ + struct spi_device *spi = mem->spi; + struct ingenic_sfc *sfc = spi_controller_get_devdata(spi->master); + int ret, val; + + init_completion(&sfc->completion); + + val = readl(sfc->base + SFC_REG_GLB); + u32p_replace_bits(&val, GLB_TRAN_DIR_READ, GLB_TRAN_DIR_MASK); + u32p_replace_bits(&val, GLB_OP_MODE_SLAVE, GLB_OP_MODE_MASK); + writel(val, sfc->base + SFC_REG_GLB); + + writel(match, sfc->base + SFC_REG_DEV_STA_EXP); + writel(mask, sfc->base + SFC_REG_DEV_STA_MSK); + + val = TRAN_CONF_POLL_EN | TRAN_CONF_CMD_EN | op->cmd.opcode; + + if (op->addr.nbytes > 0) { + val |= FIELD_PREP(TRAN_CONF_ADDR_WIDTH_MASK, op->addr.nbytes); + + writel(op->addr.val & 0xffffffff, sfc->base + SFC_REG_DEV_ADDR(0)); + writel(op->addr.val >> 32, sfc->base + SFC_REG_DEV_ADDR_PLUS(0)); + } + + if (op->dummy.nbytes > 0) + val |= FIELD_PREP(TRAN_CONF_DMY_BITS_MASK, + op->dummy.nbytes * 8 / op->dummy.buswidth); + + if (op->data.nbytes > 0) + val |= TRAN_CONF_DATA_EN; + + writel(val, sfc->base + SFC_REG_TRAN_CONF(0)); + writel(op->data.nbytes, sfc->base + SFC_REG_TRAN_LEN); + + ingenic_sfc_set_transfer_mode(sfc, op); + + writel(0x1f, sfc->base + SFC_REG_SCR); + writel(~INTC_MASK_END, sfc->base + SFC_REG_INTC); + + writel(0, sfc->base + SFC_REG_MEM_ADDR); + + writel(TRIG_START, sfc->base + SFC_REG_TRIG); + + ret = wait_for_completion_timeout(&sfc->completion, + msecs_to_jiffies(INGENIC_SFC_TRANSFER_TIMEOUT)); + if (!ret) { + writel(0x1f, sfc->base + SFC_REG_INTC); + writel(0x1f, sfc->base + SFC_REG_SCR); + dev_err(sfc->dev, "line:%d Timeout for ACK from SFC device\n", __LINE__); + return -ETIMEDOUT; + } + + writel(SCR_CLR_END, sfc->base + SFC_REG_SCR); + writel(TRIG_STOP, sfc->base + SFC_REG_TRIG); + + return 0; +} + +static const struct spi_controller_mem_ops ingenic_sfc_mem_ops = { + .adjust_op_size = ingenic_sfc_adjust_op_size, + .supports_op = ingenic_sfc_supports_op, + .exec_op = ingenic_sfc_exec_op, + .poll_status = ingenic_sfc_poll_status, +}; + +static int ingenic_sfc_setup(struct spi_device *spi) +{ + struct ingenic_sfc *sfc = spi_controller_get_devdata(spi->master); + unsigned long rate; + int ret, val; + + if (!spi->max_speed_hz) + return -EINVAL; + + ret = clk_set_rate(sfc->clk, spi->max_speed_hz * 2); + if (ret) + return -EINVAL; + + writel(TRIG_STOP, sfc->base + SFC_REG_TRIG); + writel(0, sfc->base + SFC_REG_DEV_CONF); + writel(0, sfc->base + SFC_REG_CGE); + + val = readl(sfc->base + SFC_REG_GLB); + u32p_replace_bits(&val, 64 - 1, GLB_THRESHOLD_MASK); + writel(val, sfc->base + SFC_REG_GLB); + + val = readl(sfc->base + SFC_REG_DEV_CONF); + + /* cpha bit:0 , cpol bit:0 */ + val &= ~(DEV_CONF_CPHA | DEV_CONF_CPOL); + val |= spi->mode & SPI_CPHA ? DEV_CONF_CPHA : 0; + val |= spi->mode & SPI_CPOL ? DEV_CONF_CPOL : 0; + + /* ce_dl bit:1, hold bit:1, wp bit:1 */ + val |= (DEV_CONF_CE_DL | DEV_CONF_HOLD_DL | DEV_CONF_WP_DL); + + writel(val, sfc->base + SFC_REG_DEV_CONF); + + val = readl(sfc->base + SFC_REG_GLB); + u32p_replace_bits(&val, GLB_OP_MODE_SLAVE, GLB_OP_MODE_MASK); + writel(val, sfc->base + SFC_REG_GLB); + + rate = clk_get_rate(sfc->clk); + val = readl(sfc->base + SFC_REG_DEV_CONF); + if (sfc->soc_info->version >= ID_X1600 && rate >= 200000000) + u32p_replace_bits(&val, DEV_CONF_SMP_DELAY_180DEG, DEV_CONF_SMP_DELAY_MASK); + else if (sfc->soc_info->version == ID_X1000 && rate >= 100000000) + u32p_replace_bits(&val, DEV_CONF_SMP_DELAY_HALF_CYCLE, DEV_CONF_SMP_DELAY_MASK); + writel(val, sfc->base + SFC_REG_DEV_CONF); + + return 0; +} + +static int ingenic_sfc_probe(struct platform_device *pdev) +{ + struct ingenic_sfc *sfc; + struct spi_controller *ctlr; + int ret; + + ctlr = spi_alloc_master(&pdev->dev, sizeof(*sfc)); + if (!ctlr) + return -ENOMEM; + + sfc = spi_controller_get_devdata(ctlr); + + sfc->soc_info = of_device_get_match_data(&pdev->dev); + if (!sfc->soc_info) { + dev_err(&pdev->dev, "No of match data provided\n"); + ret = -ENODEV; + goto err_put_master; + } + + sfc->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(sfc->base)) { + ret = PTR_ERR(sfc->base); + goto err_put_master; + } + + sfc->clk = devm_clk_get(&pdev->dev, "sfc"); + if (IS_ERR(sfc->clk)) { + ret = IS_ERR(sfc->clk); + goto err_put_master; + } + + ret = clk_prepare_enable(sfc->clk); + if (ret) + goto err_put_master; + + sfc->irq = platform_get_irq(pdev, 0); + if (sfc->irq < 0) { + ret = sfc->irq; + goto err_put_master; + } + + sfc->dev = &pdev->dev; + + platform_set_drvdata(pdev, sfc); + + ret = devm_request_irq(&pdev->dev, sfc->irq, ingenic_sfc_irq_handler, 0, + dev_name(&pdev->dev), sfc); + if (ret) { + dev_err(&pdev->dev, "Failed to request irq%d, ret = %d\n", sfc->irq, ret); + goto err_put_master; + } + + ctlr->bus_num = -1; + ctlr->num_chipselect = 1; + ctlr->mem_ops = &ingenic_sfc_mem_ops; + ctlr->dev.of_node = pdev->dev.of_node; + ctlr->setup = ingenic_sfc_setup; + ctlr->mode_bits = SPI_CPHA | SPI_CPOL | + SPI_RX_DUAL | SPI_RX_QUAD | SPI_TX_DUAL | SPI_TX_QUAD; + if (sfc->soc_info->version >= ID_X2000) + ctlr->mode_bits |= SPI_RX_OCTAL | SPI_TX_OCTAL; + + ret = devm_spi_register_controller(&pdev->dev, ctlr); + if (ret) + goto err_put_master; + + return 0; + +err_put_master: + spi_master_put(ctlr); + + return ret; +} + +static const struct ingenic_soc_info x1000_soc_info = { + .version = ID_X1000, + + .max_bus_width = 4, + + .tran_mode_mask = TRAN_CONF_TRAN_MODE_MASK, +}; + +static const struct ingenic_soc_info x1600_soc_info = { + .version = ID_X1600, + + .max_bus_width = 4, + + .tran_mode_mask = TRAN_CONF_TRAN_MODE_MASK, +}; + +static const struct ingenic_soc_info x2000_soc_info = { + .version = ID_X2000, + + .max_bus_width = 8, + + .tran_mode_mask = TRAN_CFG1_TRAN_MODE_MASK, +}; + +static const struct of_device_id ingenic_sfc_of_matches[] = { + { .compatible = "ingenic,x1000-sfc", .data = &x1000_soc_info }, + { .compatible = "ingenic,x1600-sfc", .data = &x1600_soc_info }, + { .compatible = "ingenic,x2000-sfc", .data = &x2000_soc_info }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, ingenic_sfc_of_matches); + +static struct platform_driver ingenic_sfc_driver = { + .driver = { + .name = "ingenic-sfc", + .of_match_table = ingenic_sfc_of_matches, + }, + .probe = ingenic_sfc_probe, +}; +module_platform_driver(ingenic_sfc_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("周琰杰 (Zhou Yanjie) "); +MODULE_DESCRIPTION("Ingenic SoCs SPI Flash Controller Driver"); -- 2.7.4 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 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 smtp.lore.kernel.org (Postfix) with ESMTPS id C9456C433EF for ; Fri, 22 Jul 2022 16:49:31 +0000 (UTC) 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=3Q1H92Fhuo1eD42Z0PgnoqN2vyHyql7Ye4W33j3pPg0=; b=zV0IH2yAzNES+t PQGBJImONqta5sm8iqWPAdTxe+S5E5ymzqtnHeBflwDlfHz4SuQKtuwKWw2eNuMt0VMlJ3BAKUZYH fammwGEMGXSrtQctyFr38KFTzH6xGvpiILdu1z4Ze+7Cr/+Y98kATNT94sli280MKca8FjV/1IAw3 ieXLSmiu94u1e5OuUOt+m7LEMV1YI4t0MA4vJgmZas44zWftjekSHsSAXYAccqCQCp+tyAOouSvFb JJ+Tsgr8bFugHSw0AvkB0BCN6GkSG5jODYY6llZksqOACaiqUSIqt65sssW8KG21EL4HHAMeGgAvo XCtEmdK5v8m0YD+bTAsw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1oEvpy-0083bW-B6; Fri, 22 Jul 2022 16:49:14 +0000 Received: from out28-221.mail.aliyun.com ([115.124.28.221]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1oEvpo-0083TW-Ux for linux-mtd@lists.infradead.org; Fri, 22 Jul 2022 16:49:09 +0000 X-Alimail-AntiSpam: AC=CONTINUE;BC=0.07436282|-1;CH=green;DM=|CONTINUE|false|;DS=CONTINUE|ham_system_inform|0.0318391-0.00029028-0.967871;FP=0|0|0|0|0|-1|-1|-1;HT=ay29a033018047207;MF=zhouyanjie@wanyeetech.com;NM=1;PH=DS;RN=23;RT=23;SR=0;TI=SMTPD_---.Ob0cnP9_1658508531; Received: from localhost.localdomain(mailfrom:zhouyanjie@wanyeetech.com fp:SMTPD_---.Ob0cnP9_1658508531) by smtp.aliyun-inc.com; Sat, 23 Jul 2022 00:48:52 +0800 From: =?UTF-8?q?=E5=91=A8=E7=90=B0=E6=9D=B0=20=28Zhou=20Yanjie=29?= To: tudor.ambarus@microchip.com, p.yadav@ti.com, michael@walle.cc, miquel.raynal@bootlin.com, richard@nod.at, vigneshr@ti.com, broonie@kernel.org, robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org Cc: linux-mtd@lists.infradead.org, linux-spi@vger.kernel.org, linux-mips@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, aidanmacdonald.0x0@gmail.com, tmn505@gmail.com, paul@crapouillou.net, dongsheng.qiu@ingenic.com, aric.pzqi@ingenic.com, rick.tyliu@ingenic.com, jinghui.liu@ingenic.com, sernia.zhou@foxmail.com, reimu@sudomaker.com Subject: [PATCH 3/3] SPI: Ingenic: Add SFC support for Ingenic SoCs. Date: Sat, 23 Jul 2022 00:48:30 +0800 Message-Id: <1658508510-15400-4-git-send-email-zhouyanjie@wanyeetech.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1658508510-15400-1-git-send-email-zhouyanjie@wanyeetech.com> References: <1658508510-15400-1-git-send-email-zhouyanjie@wanyeetech.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220722_094906_273937_81BE6DE9 X-CRM114-Status: GOOD ( 19.49 ) X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+linux-mtd=archiver.kernel.org@lists.infradead.org QWRkIFNGQyBzdXBwb3J0IGZvciB0aGUgWDEwMDAgU29DLCB0aGUgWDE2MDAgU29DLCBhbmQgdGhl IFgyMDAwIFNvQwpmcm9tIEluZ2VuaWMuCgpTaWduZWQtb2ZmLWJ5OiDlkajnkLDmnbAgKFpob3Ug WWFuamllKSA8emhvdXlhbmppZUB3YW55ZWV0ZWNoLmNvbT4KLS0tCiBkcml2ZXJzL3NwaS9LY29u ZmlnICAgICAgICAgICB8ICAgOSArCiBkcml2ZXJzL3NwaS9NYWtlZmlsZSAgICAgICAgICB8ICAg MSArCiBkcml2ZXJzL3NwaS9zcGktaW5nZW5pYy1zZmMuYyB8IDY2MiArKysrKysrKysrKysrKysr KysrKysrKysrKysrKysrKysrKysrKysrKysKIDMgZmlsZXMgY2hhbmdlZCwgNjcyIGluc2VydGlv bnMoKykKIGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL3NwaS9zcGktaW5nZW5pYy1zZmMuYwoK ZGlmZiAtLWdpdCBhL2RyaXZlcnMvc3BpL0tjb25maWcgYi9kcml2ZXJzL3NwaS9LY29uZmlnCmlu ZGV4IDNiMTA0NGUuLjEwNzdiZDMgMTAwNjQ0Ci0tLSBhL2RyaXZlcnMvc3BpL0tjb25maWcKKysr IGIvZHJpdmVycy9zcGkvS2NvbmZpZwpAQCAtNDM3LDYgKzQzNywxNSBAQCBjb25maWcgU1BJX0lO R0VOSUMKIAkgIFRvIGNvbXBpbGUgdGhpcyBkcml2ZXIgYXMgYSBtb2R1bGUsIGNob29zZSBNIGhl cmU6IHRoZSBtb2R1bGUKIAkgIHdpbGwgYmUgY2FsbGVkIHNwaS1pbmdlbmljLgogCitjb25maWcg U1BJX0lOR0VOSUNfU0ZDCisJdHJpc3RhdGUgIkluZ2VuaWMgU29DcyBTUEkgRmxhc2ggQ29udHJv bGxlciIKKwlkZXBlbmRzIG9uIE1BQ0hfSU5HRU5JQyB8fCBDT01QSUxFX1RFU1QKKwloZWxwCisJ ICBUaGlzIGVuYWJsZXMgc3VwcG9ydCBmb3IgdGhlIEluZ2VuaWMgU29DcyBTUEkgZmxhc2ggY29u dHJvbGxlci4KKworCSAgVG8gY29tcGlsZSB0aGlzIGRyaXZlciBhcyBhIG1vZHVsZSwgY2hvb3Nl IE0gaGVyZTogdGhlIG1vZHVsZQorCSAgd2lsbCBiZSBjYWxsZWQgaW5nZW5pYy1zZmMuCisKIGNv bmZpZyBTUElfSU5URUwKIAl0cmlzdGF0ZQogCmRpZmYgLS1naXQgYS9kcml2ZXJzL3NwaS9NYWtl ZmlsZSBiL2RyaXZlcnMvc3BpL01ha2VmaWxlCmluZGV4IDBmNDRlYjYuLmYzZTQyYzAgMTAwNjQ0 Ci0tLSBhL2RyaXZlcnMvc3BpL01ha2VmaWxlCisrKyBiL2RyaXZlcnMvc3BpL01ha2VmaWxlCkBA IC02Miw2ICs2Miw3IEBAIG9iai0kKENPTkZJR19TUElfSElTSV9TRkNfVjNYWCkJCSs9IHNwaS1o aXNpLXNmYy12M3h4Lm8KIG9iai0kKENPTkZJR19TUElfSU1HX1NQRkkpCQkrPSBzcGktaW1nLXNw Zmkubwogb2JqLSQoQ09ORklHX1NQSV9JTVgpCQkJKz0gc3BpLWlteC5vCiBvYmotJChDT05GSUdf U1BJX0lOR0VOSUMpCQkrPSBzcGktaW5nZW5pYy5vCitvYmotJChDT05GSUdfU1BJX0lOR0VOSUNf U0ZDKQkrPSBzcGktaW5nZW5pYy1zZmMubwogb2JqLSQoQ09ORklHX1NQSV9JTlRFTCkJCQkrPSBz cGktaW50ZWwubwogb2JqLSQoQ09ORklHX1NQSV9JTlRFTF9QQ0kpCQkrPSBzcGktaW50ZWwtcGNp Lm8KIG9iai0kKENPTkZJR19TUElfSU5URUxfUExBVEZPUk0pCSs9IHNwaS1pbnRlbC1wbGF0Zm9y bS5vCmRpZmYgLS1naXQgYS9kcml2ZXJzL3NwaS9zcGktaW5nZW5pYy1zZmMuYyBiL2RyaXZlcnMv c3BpL3NwaS1pbmdlbmljLXNmYy5jCm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAw Li5hNTY1NTQ2Ci0tLSAvZGV2L251bGwKKysrIGIvZHJpdmVycy9zcGkvc3BpLWluZ2VuaWMtc2Zj LmMKQEAgLTAsMCArMSw2NjIgQEAKKy8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiAoR1BMLTIu MC1vbmx5IE9SIEJTRC0yLUNsYXVzZSkKKy8qCisgKiBJbmdlbmljIFNvQ3MgU1BJIEZsYXNoIENv bnRyb2xsZXIgRHJpdmVyCisgKiBDb3B5cmlnaHQgKGMpIDIwMjIg5ZGo55Cw5p2wIChaaG91IFlh bmppZSkgPHpob3V5YW5qaWVAd2FueWVldGVjaC5jb20+CisgKi8KKworI2luY2x1ZGUgPGxpbnV4 L2JpdGZpZWxkLmg+CisjaW5jbHVkZSA8bGludXgvYml0b3BzLmg+CisjaW5jbHVkZSA8bGludXgv Y2xrLmg+CisjaW5jbHVkZSA8bGludXgvY29tcGxldGlvbi5oPgorI2luY2x1ZGUgPGxpbnV4L2Rt YS1tYXBwaW5nLmg+CisjaW5jbHVkZSA8bGludXgvaW50ZXJydXB0Lmg+CisjaW5jbHVkZSA8bGlu dXgvaW9wb2xsLmg+CisjaW5jbHVkZSA8bGludXgvbW9kdWxlLmg+CisjaW5jbHVkZSA8bGludXgv bXRkL210ZC5oPgorI2luY2x1ZGUgPGxpbnV4L29mX2RldmljZS5oPgorI2luY2x1ZGUgPGxpbnV4 L3BsYXRmb3JtX2RldmljZS5oPgorI2luY2x1ZGUgPGxpbnV4L3NsYWIuaD4KKyNpbmNsdWRlIDxs aW51eC9zcGkvc3BpLmg+CisjaW5jbHVkZSA8bGludXgvc3BpL3NwaS1tZW0uaD4KKworLyogU0ZD IHJlZ2lzdGVyIG9mZnNldHMgKi8KKyNkZWZpbmUgU0ZDX1JFR19HTEIJCQkJCQkweDAwMDAKKyNk ZWZpbmUgU0ZDX1JFR19ERVZfQ09ORgkJCQkweDAwMDQKKyNkZWZpbmUgU0ZDX1JFR19ERVZfU1RB X0VYUAkJCQkweDAwMDgKKyNkZWZpbmUgU0ZDX1JFR19ERVZfU1RBX1JUCQkJCTB4MDAwYworI2Rl ZmluZSBTRkNfUkVHX0RFVl9TVEFfTVNLCQkJCTB4MDAxMAorI2RlZmluZSBTRkNfUkVHX1RSQU5f Q09ORihuKQkJCSgweDAwMTQgKyBuICogNCkKKyNkZWZpbmUgU0ZDX1JFR19UUkFOX0NGRzAobikJ CQkoMHgwMDE0ICsgbiAqIDQpCisjZGVmaW5lIFNGQ19SRUdfVFJBTl9MRU4JCQkJMHgwMDJjCisj ZGVmaW5lIFNGQ19SRUdfREVWX0FERFIobikJCQkJKDB4MDAzMCArIG4gKiA0KQorI2RlZmluZSBT RkNfUkVHX0RFVl9BRERSX1BMVVMobikJCSgweDAwNDggKyBuICogNCkKKyNkZWZpbmUgU0ZDX1JF R19NRU1fQUREUgkJCQkweDAwNjAKKyNkZWZpbmUgU0ZDX1JFR19UUklHCQkJCQkweDAwNjQKKyNk ZWZpbmUgU0ZDX1JFR19TUgkJCQkJCTB4MDA2OAorI2RlZmluZSBTRkNfUkVHX1NDUgkJCQkJCTB4 MDA2YworI2RlZmluZSBTRkNfUkVHX0lOVEMJCQkJCTB4MDA3MAorI2RlZmluZSBTRkNfUkVHX0ZT TQkJCQkJCTB4MDA3NAorI2RlZmluZSBTRkNfUkVHX0NHRQkJCQkJCTB4MDA3OAorI2RlZmluZSBT RkNfUkVHX1RSQU5fQ0ZHMShuKQkJCSgweDAwOWMgKyBuICogNCkKKyNkZWZpbmUgU0ZDX1JFR19E UgkJCQkJCTB4MTAwMAorCisvKiBiaXRzIHdpdGhpbiB0aGUgR0xCIHJlZ2lzdGVyICovCisjZGVm aW5lIEdMQl9UUkFOX0RJUl9NQVNLCQkJCUdFTk1BU0soMTMsIDEzKQorI2RlZmluZSBHTEJfVFJB Tl9ESVJfV1JJVEUJCQkJMHgxCisjZGVmaW5lIEdMQl9UUkFOX0RJUl9SRUFECQkJCTB4MAorI2Rl ZmluZSBHTEJfVEhSRVNIT0xEX01BU0sJCQkJR0VOTUFTSygxMiwgNykKKyNkZWZpbmUgR0xCX09Q X01PREVfTUFTSwkJCQlHRU5NQVNLKDYsIDYpCisjZGVmaW5lIEdMQl9PUF9NT0RFX0RNQQkJCQkJ MHgxCisjZGVmaW5lIEdMQl9PUF9NT0RFX1NMQVZFCQkJCTB4MAorI2RlZmluZSBHTEJfUEhBU0Vf TlVNX01BU0sJCQkJR0VOTUFTSyg1LCAzKQorI2RlZmluZSBHTEJfV1BfRU4JCQkJCQlCSVQoMikK KyNkZWZpbmUgR0xCX0JVUlNUX01EX01BU0sJCQkJR0VOTUFTSygxLCAwKQorI2RlZmluZSBHTEJf QlVSU1RfTURfSU5DUjMyCQkJCTB4MworI2RlZmluZSBHTEJfQlVSU1RfTURfSU5DUjE2CQkJCTB4 MgorI2RlZmluZSBHTEJfQlVSU1RfTURfSU5DUjgJCQkJMHgxCisjZGVmaW5lIEdMQl9CVVJTVF9N RF9JTkNSNAkJCQkweDAKKworLyogYml0cyB3aXRoaW4gdGhlIERFVl9DT05GIHJlZ2lzdGVyICov CisjZGVmaW5lIERFVl9DT05GX1NNUF9ERUxBWV9NQVNLCQkJR0VOTUFTSygyMCwgMTYpCisjZGVm aW5lIERFVl9DT05GX1NNUF9ERUxBWV8xODBERUcJCTB4NAorI2RlZmluZSBERVZfQ09ORl9TTVBf REVMQVlfSEFMRl9DWUNMRQkweDEKKyNkZWZpbmUgREVWX0NPTkZfQ01EX1RZUEVfTUFTSwkJCUdF Tk1BU0soMTUsIDE1KQorI2RlZmluZSBERVZfQ09ORl9DTURfVFlQRV8xNkJJVAkJCTB4MQorI2Rl ZmluZSBERVZfQ09ORl9DTURfVFlQRV84QklUCQkJMHgwCisjZGVmaW5lIERFVl9DT05GX1NUQV9U WVBFX01BU0sJCQlHRU5NQVNLKDE0LCAxMykKKyNkZWZpbmUgREVWX0NPTkZfVEhPTERfTUFTSwkJ CQlHRU5NQVNLKDEyLCAxMSkKKyNkZWZpbmUgREVWX0NPTkZfVFNFVFVQX01BU0sJCQlHRU5NQVNL KDEwLCA5KQorI2RlZmluZSBERVZfQ09ORl9UU0hfTUFTSwkJCQlHRU5NQVNLKDgsIDUpCisjZGVm aW5lIERFVl9DT05GX0NQSEEJCQkJCUJJVCg0KQorI2RlZmluZSBERVZfQ09ORl9DUE9MCQkJCQlC SVQoMykKKyNkZWZpbmUgREVWX0NPTkZfQ0VfREwJCQkJCUJJVCgyKQorI2RlZmluZSBERVZfQ09O Rl9IT0xEX0RMCQkJCUJJVCgxKQorI2RlZmluZSBERVZfQ09ORl9XUF9ETAkJCQkJQklUKDApCisK Ky8qIGJpdHMgd2l0aGluIHRoZSBUUkFOX0NPTkYobikgcmVnaXN0ZXIgKi8KKyNkZWZpbmUgVFJB Tl9DT05GX1RSQU5fTU9ERV9NQVNLCQlHRU5NQVNLKDMxLCAyOSkKKyNkZWZpbmUgVFJBTl9DT05G X0FERFJfV0lEVEhfTUFTSwkJR0VOTUFTSygyOCwgMjYpCisjZGVmaW5lIFRSQU5fQ09ORl9QT0xM X0VOCQkJCUJJVCgyNSkKKyNkZWZpbmUgVFJBTl9DT05GX0NNRF9FTgkJCQlCSVQoMjQpCisjZGVm aW5lIFRSQU5fQ09ORl9QSEFTRV9GT1JNQVRfTUFTSwkJR0VOTUFTSygyMywgMjMpCisjZGVmaW5l IFRSQU5fQ09ORl9ETVlfQklUU19NQVNLCQkJR0VOTUFTSygyMiwgMTcpCisjZGVmaW5lIFRSQU5f Q09ORl9EQVRBX0VOCQkJCUJJVCgxNikKKyNkZWZpbmUgVFJBTl9DT05GX0NNRF9NQVNLCQkJCUdF Tk1BU0soMTUsIDApCisKKy8qIGJpdHMgd2l0aGluIHRoZSBUUklHIHJlZ2lzdGVyICovCisjZGVm aW5lIFRSSUdfRkxVU0gJCQkJCQlCSVQoMikKKyNkZWZpbmUgVFJJR19TVE9QCQkJCQkJQklUKDEp CisjZGVmaW5lIFRSSUdfU1RBUlQJCQkJCQlCSVQoMCkKKworLyogYml0cyB3aXRoaW4gdGhlIFNS IHJlZ2lzdGVyICovCisjZGVmaW5lIFNSX0ZJRk9fTlVNX01BU0sJCQkJR0VOTUFTSygyMiwgMTYp CisjZGVmaW5lIFNSX0VORAkJCQkJCQlCSVQoNCkKKyNkZWZpbmUgU1JfVFJBTl9SRVEJCQkJCQlC SVQoMykKKyNkZWZpbmUgU1JfUkVDRV9SRVEJCQkJCQlCSVQoMikKKyNkZWZpbmUgU1JfT1ZFUgkJ CQkJCQlCSVQoMSkKKyNkZWZpbmUgU1JfVU5ERVIJCQkJCQlCSVQoMCkKKworLyogYml0cyB3aXRo aW4gdGhlIFNDUiByZWdpc3RlciAqLworI2RlZmluZSBTQ1JfQ0xSX0VORAkJCQkJCUJJVCg0KQor I2RlZmluZSBTQ1JfQ0xSX1RSRVEJCQkJCUJJVCgzKQorI2RlZmluZSBTQ1JfQ0xSX1JSRVEJCQkJ CUJJVCgyKQorI2RlZmluZSBTQ1JfQ0xSX09WRVIJCQkJCUJJVCgxKQorI2RlZmluZSBTQ1JfQ0xS X1VOREVSCQkJCQlCSVQoMCkKKworLyogYml0cyB3aXRoaW4gdGhlIElOVEMgcmVnaXN0ZXIgKi8K KyNkZWZpbmUgSU5UQ19NQVNLX0VORAkJCQkJQklUKDQpCisjZGVmaW5lIElOVENfTUFTS19UUkVR CQkJCQlCSVQoMykKKyNkZWZpbmUgSU5UQ19NQVNLX1JSRVEJCQkJCUJJVCgyKQorI2RlZmluZSBJ TlRDX01BU0tfT1ZFUgkJCQkJQklUKDEpCisjZGVmaW5lIElOVENfTUFTS19VTkRFUgkJCQkJQklU KDApCisKKy8qIGJpdHMgd2l0aGluIHRoZSBUUkFOX0NGRzEobikgcmVnaXN0ZXIgKi8KKyNkZWZp bmUgVFJBTl9DRkcxX1RSQU5fTU9ERV9NQVNLCQlHRU5NQVNLKDcsIDQpCisKKyNkZWZpbmUgVFJB Tl9NT0RFX1NUQU5EQVJECQkJCTAKKyNkZWZpbmUgVFJBTl9NT0RFX0RVQUxfREFUQQkJCQkxCisj ZGVmaW5lIFRSQU5fTU9ERV9EVUFMX0lPCQkJCTIKKyNkZWZpbmUgVFJBTl9NT0RFX0RVQUxfRlVM TAkJCQkzCisjZGVmaW5lIFRSQU5fTU9ERV9RVUFEX0RBVEEJCQkJNQorI2RlZmluZSBUUkFOX01P REVfUVVBRF9JTwkJCQk2CisjZGVmaW5lIFRSQU5fTU9ERV9RVUFEX0ZVTEwJCQkJNworI2RlZmlu ZSBUUkFOX01PREVfT0NUQUxfREFUQQkJCTkKKyNkZWZpbmUgVFJBTl9NT0RFX09DVEFMX0lPCQkJ CTEwCisjZGVmaW5lIFRSQU5fTU9ERV9PQ1RBTF9GVUxMCQkJMTEKKworI2RlZmluZSBJTkdFTklD X1NGQ19GSUZPX1NJWkUJCQkoNjQgKiA0KQorCisjZGVmaW5lIElOR0VOSUNfU0ZDX1RSQU5TRkVS X1RJTUVPVVQJMTAwMAorCitlbnVtIGluZ2VuaWNfc2ZjX3ZlcnNpb24geworCUlEX1gxMDAwLAor CUlEX1gxNjAwLAorCUlEX1gyMDAwLAorfTsKKworc3RydWN0IGluZ2VuaWNfc29jX2luZm8gewor CWVudW0gaW5nZW5pY19zZmNfdmVyc2lvbiB2ZXJzaW9uOworCisJdW5zaWduZWQgaW50IG1heF9i dXNfd2lkdGg7CisKKwljb25zdCB1MzIgdHJhbl9tb2RlX21hc2s7Cit9OworCitzdHJ1Y3QgaW5n ZW5pY19zZmMgeworCWNvbnN0IHN0cnVjdCBpbmdlbmljX3NvY19pbmZvICpzb2NfaW5mbzsKKwor CXZvaWQgX19pb21lbSAqYmFzZTsKKwlzdHJ1Y3QgZGV2aWNlICpkZXY7CisJc3RydWN0IGNsayAq Y2xrOworCWludCBpcnE7CisKKwlzdHJ1Y3QgY29tcGxldGlvbiBjb21wbGV0aW9uOworfTsKKwor c3RhdGljIGlycXJldHVybl90IGluZ2VuaWNfc2ZjX2lycV9oYW5kbGVyKGludCBpcnEsIHZvaWQg KmRhdGEpCit7CisJc3RydWN0IGluZ2VuaWNfc2ZjICpzZmMgPSBkYXRhOworCisJd3JpdGVsKDB4 MWYsIHNmYy0+YmFzZSArIFNGQ19SRUdfSU5UQyk7CisKKwljb21wbGV0ZSgmc2ZjLT5jb21wbGV0 aW9uKTsKKworCXJldHVybiBJUlFfSEFORExFRDsKK30KKworc3RhdGljIGludCBpbmdlbmljX3Nm Y19hZGp1c3Rfb3Bfc2l6ZShzdHJ1Y3Qgc3BpX21lbSAqbWVtLCBzdHJ1Y3Qgc3BpX21lbV9vcCAq b3ApCit7CisJdWludHB0cl90IGFkZHIgPSAodWludHB0cl90KW9wLT5kYXRhLmJ1Zi5pbjsKKwor CWlmIChvcC0+ZGF0YS5uYnl0ZXMgPiBJTkdFTklDX1NGQ19GSUZPX1NJWkUgJiYgIUlTX0FMSUdO RUQoYWRkciwgNCkpCisJCW9wLT5kYXRhLm5ieXRlcyA9IElOR0VOSUNfU0ZDX0ZJRk9fU0laRTsK KworCXJldHVybiAwOworfQorCitzdGF0aWMgYm9vbCBpbmdlbmljX3NmY19zdXBwb3J0c19vcChz dHJ1Y3Qgc3BpX21lbSAqbWVtLCBjb25zdCBzdHJ1Y3Qgc3BpX21lbV9vcCAqb3ApCit7CisJc3Ry dWN0IHNwaV9kZXZpY2UgKnNwaSA9IG1lbS0+c3BpOworCXN0cnVjdCBpbmdlbmljX3NmYyAqc2Zj ID0gc3BpX2NvbnRyb2xsZXJfZ2V0X2RldmRhdGEoc3BpLT5tYXN0ZXIpOworCXVpbnRwdHJfdCBh ZGRyID0gKHVpbnRwdHJfdClvcC0+ZGF0YS5idWYuaW47CisKKwkvKiBUaGUgY29udHJvbGxlciBv bmx5IHN1cHBvcnRzIFN0YW5kYXJkIFNQSSBtb2RlLCBEdWFsbCBtb2RlLCBRdWFkIG1vZGUgYW5k IE9jdGFsIG1vZGUuICovCisJaWYgKG9wLT5jbWQuYnVzd2lkdGggPiBzZmMtPnNvY19pbmZvLT5t YXhfYnVzX3dpZHRoIHx8CisJCW9wLT5hZGRyLmJ1c3dpZHRoID4gc2ZjLT5zb2NfaW5mby0+bWF4 X2J1c193aWR0aCB8fAorCQlvcC0+ZHVtbXkuYnVzd2lkdGggPiBzZmMtPnNvY19pbmZvLT5tYXhf YnVzX3dpZHRoIHx8CisJCW9wLT5kYXRhLmJ1c3dpZHRoID4gc2ZjLT5zb2NfaW5mby0+bWF4X2J1 c193aWR0aCkKKwkJcmV0dXJuIGZhbHNlOworCisJLyogTWF4IDMyIGR1bW15IGNsb2NrIGN5Y2xl cyBzdXBwb3J0ZWQgKi8KKwlpZiAob3AtPmR1bW15Lm5ieXRlcyAmJiBvcC0+ZHVtbXkubmJ5dGVz ICogOCAvIG9wLT5kdW1teS5idXN3aWR0aCA+IDMyKQorCQlyZXR1cm4gZmFsc2U7CisKKwkvKiBN YXggcnggZGF0YSBsZW5ndGgsIGNoZWNrIGNvbnRyb2xsZXIgbGltaXRzIGFuZCBhbGlnbm1lbnQg Ki8KKwlpZiAob3AtPmRhdGEuZGlyID09IFNQSV9NRU1fREFUQV9JTiAmJgorCQlvcC0+ZGF0YS5u Ynl0ZXMgPiBJTkdFTklDX1NGQ19GSUZPX1NJWkUgJiYgIUlTX0FMSUdORUQoYWRkciwgNCkpCisJ CXJldHVybiBmYWxzZTsKKworCS8qIE1heCA2IGJ5dGVzIGFkZHJlc3Mgd2lkdGggc3VwcG9ydGVk ICovCisJaWYgKG9wLT5hZGRyLm5ieXRlcyA+IDYpCisJCXJldHVybiBmYWxzZTsKKworCXJldHVy biBzcGlfbWVtX2RlZmF1bHRfc3VwcG9ydHNfb3AobWVtLCBvcCk7Cit9CisKK3N0YXRpYyB2b2lk IGluZ2VuaWNfc2ZjX3NldF90cmFuc2Zlcl9tb2RlKHN0cnVjdCBpbmdlbmljX3NmYyAqc2ZjLCBj b25zdCBzdHJ1Y3Qgc3BpX21lbV9vcCAqb3ApCit7CisJaW50IHZhbDsKKworCXZhbCA9IHJlYWRs KHNmYy0+YmFzZSArIChzZmMtPnNvY19pbmZvLT52ZXJzaW9uID49IElEX1gxNjAwID8KKwkJCVNG Q19SRUdfVFJBTl9DRkcxKDApIDogU0ZDX1JFR19UUkFOX0NPTkYoMCkpKTsKKwl2YWwgJj0gfnNm Yy0+c29jX2luZm8tPnRyYW5fbW9kZV9tYXNrOworCWlmIChvcC0+Y21kLmJ1c3dpZHRoID09IDgp CisJCXZhbCB8PSAoVFJBTl9NT0RFX09DVEFMX0ZVTEwgPDwgKGZmcyhzZmMtPnNvY19pbmZvLT50 cmFuX21vZGVfbWFzaykgLSAxKSkgJgorCQkJCXNmYy0+c29jX2luZm8tPnRyYW5fbW9kZV9tYXNr OworCWVsc2UgaWYgKG9wLT5jbWQuYnVzd2lkdGggPT0gNCkKKwkJdmFsIHw9IChUUkFOX01PREVf UVVBRF9GVUxMIDw8IChmZnMoc2ZjLT5zb2NfaW5mby0+dHJhbl9tb2RlX21hc2spIC0gMSkpICYK KwkJCQlzZmMtPnNvY19pbmZvLT50cmFuX21vZGVfbWFzazsKKwllbHNlIGlmIChvcC0+Y21kLmJ1 c3dpZHRoID09IDIpCisJCXZhbCB8PSAoVFJBTl9NT0RFX0RVQUxfRlVMTCA8PCAoZmZzKHNmYy0+ c29jX2luZm8tPnRyYW5fbW9kZV9tYXNrKSAtIDEpKSAmCisJCQkJc2ZjLT5zb2NfaW5mby0+dHJh bl9tb2RlX21hc2s7CisJZWxzZSBpZiAob3AtPmFkZHIuYnVzd2lkdGggPT0gOCkKKwkJdmFsIHw9 IChUUkFOX01PREVfT0NUQUxfSU8gPDwgKGZmcyhzZmMtPnNvY19pbmZvLT50cmFuX21vZGVfbWFz aykgLSAxKSkgJgorCQkJCXNmYy0+c29jX2luZm8tPnRyYW5fbW9kZV9tYXNrOworCWVsc2UgaWYg KG9wLT5hZGRyLmJ1c3dpZHRoID09IDQpCisJCXZhbCB8PSAoVFJBTl9NT0RFX1FVQURfSU8gPDwg KGZmcyhzZmMtPnNvY19pbmZvLT50cmFuX21vZGVfbWFzaykgLSAxKSkgJgorCQkJCXNmYy0+c29j X2luZm8tPnRyYW5fbW9kZV9tYXNrOworCWVsc2UgaWYgKG9wLT5hZGRyLmJ1c3dpZHRoID09IDIp CisJCXZhbCB8PSAoVFJBTl9NT0RFX0RVQUxfSU8gPDwgKGZmcyhzZmMtPnNvY19pbmZvLT50cmFu X21vZGVfbWFzaykgLSAxKSkgJgorCQkJCXNmYy0+c29jX2luZm8tPnRyYW5fbW9kZV9tYXNrOwor CWVsc2UgaWYgKG9wLT5kYXRhLmJ1c3dpZHRoID09IDgpCisJCXZhbCB8PSAoVFJBTl9NT0RFX09D VEFMX0RBVEEgPDwgKGZmcyhzZmMtPnNvY19pbmZvLT50cmFuX21vZGVfbWFzaykgLSAxKSkgJgor CQkJCXNmYy0+c29jX2luZm8tPnRyYW5fbW9kZV9tYXNrOworCWVsc2UgaWYgKG9wLT5kYXRhLmJ1 c3dpZHRoID09IDQpCisJCXZhbCB8PSAoVFJBTl9NT0RFX1FVQURfREFUQSA8PCAoZmZzKHNmYy0+ c29jX2luZm8tPnRyYW5fbW9kZV9tYXNrKSAtIDEpKSAmCisJCQkJc2ZjLT5zb2NfaW5mby0+dHJh bl9tb2RlX21hc2s7CisJZWxzZSBpZiAob3AtPmRhdGEuYnVzd2lkdGggPT0gMikKKwkJdmFsIHw9 IChUUkFOX01PREVfRFVBTF9EQVRBIDw8IChmZnMoc2ZjLT5zb2NfaW5mby0+dHJhbl9tb2RlX21h c2spIC0gMSkpICYKKwkJCQlzZmMtPnNvY19pbmZvLT50cmFuX21vZGVfbWFzazsKKwllbHNlCisJ CXZhbCB8PSAoVFJBTl9NT0RFX1NUQU5EQVJEIDw8IChmZnMoc2ZjLT5zb2NfaW5mby0+dHJhbl9t b2RlX21hc2spIC0gMSkpICYKKwkJCQlzZmMtPnNvY19pbmZvLT50cmFuX21vZGVfbWFzazsKKwl3 cml0ZWwodmFsLCBzZmMtPmJhc2UgKyAoc2ZjLT5zb2NfaW5mby0+dmVyc2lvbiA+PSBJRF9YMTYw MCA/CisJCQlTRkNfUkVHX1RSQU5fQ0ZHMSgwKSA6IFNGQ19SRUdfVFJBTl9DT05GKDApKSk7Cit9 CisKKy8qCisgKiBXZSBvbmx5IG5lZWQgUElPIG1vZGUgdG8gaGFuZGxlIHRoZSBTUElfTUVNX05P X0RBVEEgdHJhbnNmZXJzLAorICogYW5kIHRoZSB1bmFsaWduZWQgYWNjZXNzZXMgaW4gU1BJX01F TV9EQVRBX0lOIHRyYW5zZmVycy4KKyAqLworc3RhdGljIHZvaWQgaW5nZW5pY19zZmNfcmVhZF9y eGZpZm8oc3RydWN0IGluZ2VuaWNfc2ZjICpzZmMsIHU4ICp0bywgdW5zaWduZWQgaW50IGxlbikK K3sKKwl2b2lkIF9faW9tZW0gKmZyb207CisKKwlmcm9tID0gc2ZjLT5iYXNlICsgU0ZDX1JFR19E UjsKKworCWZvciAoOyBsZW4gPj0gNDsgbGVuIC09IDQsIHRvICs9IDQpIHsKKwkJdTMyIHZhbCA9 IF9fcmF3X3JlYWRsKGZyb20pOworCQltZW1jcHkodG8sICZ2YWwsIDQpOworCX0KKworCWlmIChs ZW4pIHsKKwkJdTMyIHZhbCA9IF9fcmF3X3JlYWRsKGZyb20pOworCQltZW1jcHkodG8sICZ2YWws IGxlbik7CisJfQorfQorCitzdGF0aWMgaW50IGluZ2VuaWNfc2ZjX2V4ZWNfb3BfcGlvKHN0cnVj dCBpbmdlbmljX3NmYyAqc2ZjLCBjb25zdCBzdHJ1Y3Qgc3BpX21lbV9vcCAqb3ApCit7CisJaW50 IHJldCwgdmFsOworCisJdmFsID0gcmVhZGwoc2ZjLT5iYXNlICsgU0ZDX1JFR19HTEIpOworCXUz MnBfcmVwbGFjZV9iaXRzKCZ2YWwsIEdMQl9UUkFOX0RJUl9SRUFELCBHTEJfVFJBTl9ESVJfTUFT Syk7CisJdTMycF9yZXBsYWNlX2JpdHMoJnZhbCwgR0xCX09QX01PREVfU0xBVkUsIEdMQl9PUF9N T0RFX01BU0spOworCXdyaXRlbCh2YWwsIHNmYy0+YmFzZSArIFNGQ19SRUdfR0xCKTsKKworCXZh bCA9IFRSQU5fQ09ORl9DTURfRU4gfCBvcC0+Y21kLm9wY29kZTsKKworCWlmIChvcC0+YWRkci5u Ynl0ZXMgPiAwKSB7CisJCXZhbCB8PSBGSUVMRF9QUkVQKFRSQU5fQ09ORl9BRERSX1dJRFRIX01B U0ssIG9wLT5hZGRyLm5ieXRlcyk7CisKKwkJd3JpdGVsKG9wLT5hZGRyLnZhbCAmIDB4ZmZmZmZm ZmYsIHNmYy0+YmFzZSArIFNGQ19SRUdfREVWX0FERFIoMCkpOworCQl3cml0ZWwob3AtPmFkZHIu dmFsID4+IDMyLCBzZmMtPmJhc2UgKyBTRkNfUkVHX0RFVl9BRERSX1BMVVMoMCkpOworCX0KKwor CWlmIChvcC0+ZHVtbXkubmJ5dGVzID4gMCkKKwkJdmFsIHw9IEZJRUxEX1BSRVAoVFJBTl9DT05G X0RNWV9CSVRTX01BU0ssCisJCQkJb3AtPmR1bW15Lm5ieXRlcyAqIDggLyBvcC0+ZHVtbXkuYnVz d2lkdGgpOworCisJaWYgKG9wLT5kYXRhLm5ieXRlcyA+IDApCisJCXZhbCB8PSBUUkFOX0NPTkZf REFUQV9FTjsKKworCXdyaXRlbCh2YWwsIHNmYy0+YmFzZSArIFNGQ19SRUdfVFJBTl9DT05GKDAp KTsKKwl3cml0ZWwob3AtPmRhdGEubmJ5dGVzLCBzZmMtPmJhc2UgKyBTRkNfUkVHX1RSQU5fTEVO KTsKKworCWluZ2VuaWNfc2ZjX3NldF90cmFuc2Zlcl9tb2RlKHNmYywgb3ApOworCisJd3JpdGVs KDB4MWYsIHNmYy0+YmFzZSArIFNGQ19SRUdfU0NSKTsKKwl3cml0ZWwofihJTlRDX01BU0tfRU5E IHwgSU5UQ19NQVNLX1JSRVEpLCBzZmMtPmJhc2UgKyBTRkNfUkVHX0lOVEMpOworCisJd3JpdGVs KDAsIHNmYy0+YmFzZSArIFNGQ19SRUdfTUVNX0FERFIpOworCisJd3JpdGVsKFRSSUdfRkxVU0gs IHNmYy0+YmFzZSArIFNGQ19SRUdfVFJJRyk7CisJd3JpdGVsKFRSSUdfU1RBUlQsIHNmYy0+YmFz ZSArIFNGQ19SRUdfVFJJRyk7CisKKwlyZXQgPSB3YWl0X2Zvcl9jb21wbGV0aW9uX3RpbWVvdXQo JnNmYy0+Y29tcGxldGlvbiwKKwkJCW1zZWNzX3RvX2ppZmZpZXMoSU5HRU5JQ19TRkNfVFJBTlNG RVJfVElNRU9VVCkpOworCWlmICghcmV0KSB7CisJCXdyaXRlbCgweDFmLCBzZmMtPmJhc2UgKyBT RkNfUkVHX0lOVEMpOworCQl3cml0ZWwoMHgxZiwgc2ZjLT5iYXNlICsgU0ZDX1JFR19TQ1IpOwor CQlkZXZfZXJyKHNmYy0+ZGV2LCAibGluZTolZCBUaW1lb3V0IGZvciBBQ0sgZnJvbSBTRkMgZGV2 aWNlXG4iLCBfX0xJTkVfXyk7CisJCXJldHVybiAtRVRJTUVET1VUOworCX0KKworCWluZ2VuaWNf c2ZjX3JlYWRfcnhmaWZvKHNmYywgb3AtPmRhdGEuYnVmLmluLCBvcC0+ZGF0YS5uYnl0ZXMpOwor CXJlYWRsX3BvbGxfdGltZW91dChzZmMtPmJhc2UgKyBTRkNfUkVHX1NSLCB2YWwsIHZhbCAmIFNS X0VORCwgMTAsIDApOworCisJd3JpdGVsKElOVENfTUFTS19FTkQgfCBJTlRDX01BU0tfUlJFUSwg c2ZjLT5iYXNlICsgU0ZDX1JFR19TQ1IpOworCXdyaXRlbChUUklHX1NUT1AsIHNmYy0+YmFzZSAr IFNGQ19SRUdfVFJJRyk7CisKKwlyZXR1cm4gMDsKK30KKworc3RhdGljIGludCBpbmdlbmljX3Nm Y19leGVjX29wX2RtYShzdHJ1Y3QgaW5nZW5pY19zZmMgKnNmYywgY29uc3Qgc3RydWN0IHNwaV9t ZW1fb3AgKm9wKQoreworCWRtYV9hZGRyX3QgYWRkcjsKKwlpbnQgcmV0LCB2YWw7CisKKwl2YWwg PSByZWFkbChzZmMtPmJhc2UgKyBTRkNfUkVHX0dMQik7CisJdTMycF9yZXBsYWNlX2JpdHMoJnZh bCwgb3AtPmRhdGEuZGlyID09IFNQSV9NRU1fREFUQV9JTiA/CisJCQlHTEJfVFJBTl9ESVJfUkVB RCA6IEdMQl9UUkFOX0RJUl9XUklURSwgR0xCX1RSQU5fRElSX01BU0spOworCXUzMnBfcmVwbGFj ZV9iaXRzKCZ2YWwsIEdMQl9PUF9NT0RFX0RNQSwgR0xCX09QX01PREVfTUFTSyk7CisJd3JpdGVs KHZhbCwgc2ZjLT5iYXNlICsgU0ZDX1JFR19HTEIpOworCisJdmFsID0gVFJBTl9DT05GX0NNRF9F TiB8IG9wLT5jbWQub3Bjb2RlOworCisJaWYgKG9wLT5hZGRyLm5ieXRlcyA+IDApIHsKKwkJdmFs IHw9IEZJRUxEX1BSRVAoVFJBTl9DT05GX0FERFJfV0lEVEhfTUFTSywgb3AtPmFkZHIubmJ5dGVz KTsKKwkJd3JpdGVsKG9wLT5hZGRyLnZhbCAmIDB4ZmZmZmZmZmYsIHNmYy0+YmFzZSArIFNGQ19S RUdfREVWX0FERFIoMCkpOworCQl3cml0ZWwob3AtPmFkZHIudmFsID4+IDMyLCBzZmMtPmJhc2Ug KyBTRkNfUkVHX0RFVl9BRERSX1BMVVMoMCkpOworCX0KKworCWlmIChvcC0+ZHVtbXkubmJ5dGVz ID4gMCkKKwkJdmFsIHw9IEZJRUxEX1BSRVAoVFJBTl9DT05GX0RNWV9CSVRTX01BU0ssCisJCQkJ b3AtPmR1bW15Lm5ieXRlcyAqIDggLyBvcC0+ZHVtbXkuYnVzd2lkdGgpOworCisJaWYgKG9wLT5k YXRhLm5ieXRlcyA+IDApCisJCXZhbCB8PSBUUkFOX0NPTkZfREFUQV9FTjsKKworCXdyaXRlbCh2 YWwsIHNmYy0+YmFzZSArIFNGQ19SRUdfVFJBTl9DT05GKDApKTsKKwl3cml0ZWwob3AtPmRhdGEu bmJ5dGVzLCBzZmMtPmJhc2UgKyBTRkNfUkVHX1RSQU5fTEVOKTsKKworCWluZ2VuaWNfc2ZjX3Nl dF90cmFuc2Zlcl9tb2RlKHNmYywgb3ApOworCisJd3JpdGVsKDB4MWYsIHNmYy0+YmFzZSArIFNG Q19SRUdfU0NSKTsKKwl3cml0ZWwofklOVENfTUFTS19FTkQsIHNmYy0+YmFzZSArIFNGQ19SRUdf SU5UQyk7CisKKwlzd2l0Y2ggKG9wLT5kYXRhLmRpcikgeworCWNhc2UgU1BJX01FTV9EQVRBX0lO OgorCQlhZGRyID0gZG1hX21hcF9zaW5nbGUoc2ZjLT5kZXYsIG9wLT5kYXRhLmJ1Zi5pbiwgb3At PmRhdGEubmJ5dGVzLCBETUFfRlJPTV9ERVZJQ0UpOworCQlpZiAoZG1hX21hcHBpbmdfZXJyb3Io c2ZjLT5kZXYsIGFkZHIpKSB7CisJCQlkZXZfZXJyKHNmYy0+ZGV2LCAiUlggRE1B44CAbWVtb3J5 IG5vdCBtYXBwZWRcbiIpOworCQkJcmV0dXJuIC1FTk9NRU07CisJCX0KKworCQl3cml0ZWwoYWRk ciwgc2ZjLT5iYXNlICsgU0ZDX1JFR19NRU1fQUREUik7CisJCWJyZWFrOworCisJY2FzZSBTUElf TUVNX0RBVEFfT1VUOgorCQlhZGRyID0gZG1hX21hcF9zaW5nbGUoc2ZjLT5kZXYsICh2b2lkICop b3AtPmRhdGEuYnVmLm91dCwKKwkJCQlvcC0+ZGF0YS5uYnl0ZXMsIERNQV9UT19ERVZJQ0UpOwor CQlpZiAoZG1hX21hcHBpbmdfZXJyb3Ioc2ZjLT5kZXYsIGFkZHIpKSB7CisJCQlkZXZfZXJyKHNm Yy0+ZGV2LCAiVFggRE1B44CAbWVtb3J5IG5vdCBtYXBwZWRcbiIpOworCQkJcmV0dXJuIC1FTk9N RU07CisJCX0KKworCQl3cml0ZWwoYWRkciwgc2ZjLT5iYXNlICsgU0ZDX1JFR19NRU1fQUREUik7 CisJCWJyZWFrOworCisJZGVmYXVsdDoKKwkJcmV0dXJuIC1FSU5WQUw7CisJfQorCisJd3JpdGVs KFRSSUdfU1RBUlQsIHNmYy0+YmFzZSArIFNGQ19SRUdfVFJJRyk7CisKKwlyZXQgPSB3YWl0X2Zv cl9jb21wbGV0aW9uX3RpbWVvdXQoJnNmYy0+Y29tcGxldGlvbiwKKwkJCW1zZWNzX3RvX2ppZmZp ZXMoSU5HRU5JQ19TRkNfVFJBTlNGRVJfVElNRU9VVCkpOworCWlmICghcmV0KSB7CisJCXdyaXRl bCgweDFmLCBzZmMtPmJhc2UgKyBTRkNfUkVHX0lOVEMpOworCQl3cml0ZWwoMHgxZiwgc2ZjLT5i YXNlICsgU0ZDX1JFR19TQ1IpOworCQlkZXZfZXJyKHNmYy0+ZGV2LCAibGluZTolZCBUaW1lb3V0 IGZvciBBQ0sgZnJvbSBTRkMgZGV2aWNlXG4iLCBfX0xJTkVfXyk7CisJCXJldHVybiAtRVRJTUVE T1VUOworCX0KKworCWRtYV91bm1hcF9zaW5nbGUoc2ZjLT5kZXYsIGFkZHIsIG9wLT5kYXRhLm5i eXRlcywKKwkJCW9wLT5kYXRhLmRpciA9PSBTUElfTUVNX0RBVEFfSU4gPyBETUFfRlJPTV9ERVZJ Q0UgOiBETUFfVE9fREVWSUNFKTsKKworCXdyaXRlbChJTlRDX01BU0tfRU5ELCBzZmMtPmJhc2Ug KyBTRkNfUkVHX1NDUik7CisJd3JpdGVsKFRSSUdfU1RPUCwgc2ZjLT5iYXNlICsgU0ZDX1JFR19U UklHKTsKKworCXJldHVybiAwOworfQorCitzdGF0aWMgaW50IGluZ2VuaWNfc2ZjX2V4ZWNfb3Ao c3RydWN0IHNwaV9tZW0gKm1lbSwgY29uc3Qgc3RydWN0IHNwaV9tZW1fb3AgKm9wKQoreworCXN0 cnVjdCBzcGlfZGV2aWNlICpzcGkgPSBtZW0tPnNwaTsKKwlzdHJ1Y3QgaW5nZW5pY19zZmMgKnNm YyA9IHNwaV9jb250cm9sbGVyX2dldF9kZXZkYXRhKHNwaS0+bWFzdGVyKTsKKwl1aW50cHRyX3Qg YWRkciA9ICh1aW50cHRyX3Qpb3AtPmRhdGEuYnVmLmluOworCisJaW5pdF9jb21wbGV0aW9uKCZz ZmMtPmNvbXBsZXRpb24pOworCisJc3dpdGNoIChvcC0+ZGF0YS5kaXIpIHsKKwljYXNlIFNQSV9N RU1fREFUQV9JTjoKKwkJaWYgKHNmYy0+c29jX2luZm8tPnZlcnNpb24gPj0gSURfWDE2MDAgfHwg SVNfQUxJR05FRChhZGRyLCA0KSkKKwkJCWJyZWFrOworCisJCWZhbGx0aHJvdWdoOworCisJY2Fz ZSBTUElfTUVNX05PX0RBVEE6CisJCXJldHVybiBpbmdlbmljX3NmY19leGVjX29wX3BpbyhzZmMs IG9wKTsKKworCWRlZmF1bHQ6CisJCWJyZWFrOworCX0KKworCXJldHVybiBpbmdlbmljX3NmY19l eGVjX29wX2RtYShzZmMsIG9wKTsKK30KKworc3RhdGljIGludCBpbmdlbmljX3NmY19wb2xsX3N0 YXR1cyhzdHJ1Y3Qgc3BpX21lbSAqbWVtLCBjb25zdCBzdHJ1Y3Qgc3BpX21lbV9vcCAqb3AsCisJ CQl1MTYgbWFzaywgdTE2IG1hdGNoLCB1bnNpZ25lZCBsb25nIGluaXRpYWxfZGVsYXlfdXMsCisJ CQl1bnNpZ25lZCBsb25nIHBvbGxpbmdfZGVsYXlfdXMsIHVuc2lnbmVkIGxvbmcgdGltZW91dF9t cykKK3sKKwlzdHJ1Y3Qgc3BpX2RldmljZSAqc3BpID0gbWVtLT5zcGk7CisJc3RydWN0IGluZ2Vu aWNfc2ZjICpzZmMgPSBzcGlfY29udHJvbGxlcl9nZXRfZGV2ZGF0YShzcGktPm1hc3Rlcik7CisJ aW50IHJldCwgdmFsOworCisJaW5pdF9jb21wbGV0aW9uKCZzZmMtPmNvbXBsZXRpb24pOworCisJ dmFsID0gcmVhZGwoc2ZjLT5iYXNlICsgU0ZDX1JFR19HTEIpOworCXUzMnBfcmVwbGFjZV9iaXRz KCZ2YWwsIEdMQl9UUkFOX0RJUl9SRUFELCBHTEJfVFJBTl9ESVJfTUFTSyk7CisJdTMycF9yZXBs YWNlX2JpdHMoJnZhbCwgR0xCX09QX01PREVfU0xBVkUsIEdMQl9PUF9NT0RFX01BU0spOworCXdy aXRlbCh2YWwsIHNmYy0+YmFzZSArIFNGQ19SRUdfR0xCKTsKKworCXdyaXRlbChtYXRjaCwgc2Zj LT5iYXNlICsgU0ZDX1JFR19ERVZfU1RBX0VYUCk7CisJd3JpdGVsKG1hc2ssIHNmYy0+YmFzZSAr IFNGQ19SRUdfREVWX1NUQV9NU0spOworCisJdmFsID0gVFJBTl9DT05GX1BPTExfRU4gfCBUUkFO X0NPTkZfQ01EX0VOIHwgb3AtPmNtZC5vcGNvZGU7CisKKwlpZiAob3AtPmFkZHIubmJ5dGVzID4g MCkgeworCQl2YWwgfD0gRklFTERfUFJFUChUUkFOX0NPTkZfQUREUl9XSURUSF9NQVNLLCBvcC0+ YWRkci5uYnl0ZXMpOworCisJCXdyaXRlbChvcC0+YWRkci52YWwgJiAweGZmZmZmZmZmLCBzZmMt PmJhc2UgKyBTRkNfUkVHX0RFVl9BRERSKDApKTsKKwkJd3JpdGVsKG9wLT5hZGRyLnZhbCA+PiAz Miwgc2ZjLT5iYXNlICsgU0ZDX1JFR19ERVZfQUREUl9QTFVTKDApKTsKKwl9CisKKwlpZiAob3At PmR1bW15Lm5ieXRlcyA+IDApCisJCXZhbCB8PSBGSUVMRF9QUkVQKFRSQU5fQ09ORl9ETVlfQklU U19NQVNLLAorCQkJCW9wLT5kdW1teS5uYnl0ZXMgKiA4IC8gb3AtPmR1bW15LmJ1c3dpZHRoKTsK KworCWlmIChvcC0+ZGF0YS5uYnl0ZXMgPiAwKQorCQl2YWwgfD0gVFJBTl9DT05GX0RBVEFfRU47 CisKKwl3cml0ZWwodmFsLCBzZmMtPmJhc2UgKyBTRkNfUkVHX1RSQU5fQ09ORigwKSk7CisJd3Jp dGVsKG9wLT5kYXRhLm5ieXRlcywgc2ZjLT5iYXNlICsgU0ZDX1JFR19UUkFOX0xFTik7CisKKwlp bmdlbmljX3NmY19zZXRfdHJhbnNmZXJfbW9kZShzZmMsIG9wKTsKKworCXdyaXRlbCgweDFmLCBz ZmMtPmJhc2UgKyBTRkNfUkVHX1NDUik7CisJd3JpdGVsKH5JTlRDX01BU0tfRU5ELCBzZmMtPmJh c2UgKyBTRkNfUkVHX0lOVEMpOworCisJd3JpdGVsKDAsIHNmYy0+YmFzZSArIFNGQ19SRUdfTUVN X0FERFIpOworCisJd3JpdGVsKFRSSUdfU1RBUlQsIHNmYy0+YmFzZSArIFNGQ19SRUdfVFJJRyk7 CisKKwlyZXQgPSB3YWl0X2Zvcl9jb21wbGV0aW9uX3RpbWVvdXQoJnNmYy0+Y29tcGxldGlvbiwK KwkJCW1zZWNzX3RvX2ppZmZpZXMoSU5HRU5JQ19TRkNfVFJBTlNGRVJfVElNRU9VVCkpOworCWlm ICghcmV0KSB7CisJCXdyaXRlbCgweDFmLCBzZmMtPmJhc2UgKyBTRkNfUkVHX0lOVEMpOworCQl3 cml0ZWwoMHgxZiwgc2ZjLT5iYXNlICsgU0ZDX1JFR19TQ1IpOworCQlkZXZfZXJyKHNmYy0+ZGV2 LCAibGluZTolZCBUaW1lb3V0IGZvciBBQ0sgZnJvbSBTRkMgZGV2aWNlXG4iLCBfX0xJTkVfXyk7 CisJCXJldHVybiAtRVRJTUVET1VUOworCX0KKworCXdyaXRlbChTQ1JfQ0xSX0VORCwgc2ZjLT5i YXNlICsgU0ZDX1JFR19TQ1IpOworCXdyaXRlbChUUklHX1NUT1AsIHNmYy0+YmFzZSArIFNGQ19S RUdfVFJJRyk7CisKKwlyZXR1cm4gMDsKK30KKworc3RhdGljIGNvbnN0IHN0cnVjdCBzcGlfY29u dHJvbGxlcl9tZW1fb3BzIGluZ2VuaWNfc2ZjX21lbV9vcHMgPSB7CisJLmFkanVzdF9vcF9zaXpl ID0gaW5nZW5pY19zZmNfYWRqdXN0X29wX3NpemUsCisJLnN1cHBvcnRzX29wID0gaW5nZW5pY19z ZmNfc3VwcG9ydHNfb3AsCisJLmV4ZWNfb3AgPSBpbmdlbmljX3NmY19leGVjX29wLAorCS5wb2xs X3N0YXR1cyA9IGluZ2VuaWNfc2ZjX3BvbGxfc3RhdHVzLAorfTsKKworc3RhdGljIGludCBpbmdl bmljX3NmY19zZXR1cChzdHJ1Y3Qgc3BpX2RldmljZSAqc3BpKQoreworCXN0cnVjdCBpbmdlbmlj X3NmYyAqc2ZjID0gc3BpX2NvbnRyb2xsZXJfZ2V0X2RldmRhdGEoc3BpLT5tYXN0ZXIpOworCXVu c2lnbmVkIGxvbmcgcmF0ZTsKKwlpbnQgcmV0LCB2YWw7CisKKwlpZiAoIXNwaS0+bWF4X3NwZWVk X2h6KQorCQlyZXR1cm4gLUVJTlZBTDsKKworCXJldCA9IGNsa19zZXRfcmF0ZShzZmMtPmNsaywg c3BpLT5tYXhfc3BlZWRfaHogKiAyKTsKKwlpZiAocmV0KQorCQlyZXR1cm4gLUVJTlZBTDsKKwor CXdyaXRlbChUUklHX1NUT1AsIHNmYy0+YmFzZSArIFNGQ19SRUdfVFJJRyk7CisJd3JpdGVsKDAs IHNmYy0+YmFzZSArIFNGQ19SRUdfREVWX0NPTkYpOworCXdyaXRlbCgwLCBzZmMtPmJhc2UgKyBT RkNfUkVHX0NHRSk7CisKKwl2YWwgPSByZWFkbChzZmMtPmJhc2UgKyBTRkNfUkVHX0dMQik7CisJ dTMycF9yZXBsYWNlX2JpdHMoJnZhbCwgNjQgLSAxLCBHTEJfVEhSRVNIT0xEX01BU0spOworCXdy aXRlbCh2YWwsIHNmYy0+YmFzZSArIFNGQ19SRUdfR0xCKTsKKworCXZhbCA9IHJlYWRsKHNmYy0+ YmFzZSArIFNGQ19SRUdfREVWX0NPTkYpOworCisJLyogY3BoYSBiaXQ6MCAsIGNwb2wgYml0OjAg Ki8KKwl2YWwgJj0gfihERVZfQ09ORl9DUEhBIHwgREVWX0NPTkZfQ1BPTCk7CisJdmFsIHw9IHNw aS0+bW9kZSAmIFNQSV9DUEhBID8gREVWX0NPTkZfQ1BIQSA6IDA7CisJdmFsIHw9IHNwaS0+bW9k ZSAmIFNQSV9DUE9MID8gREVWX0NPTkZfQ1BPTCA6IDA7CisKKwkvKiBjZV9kbCBiaXQ6MSwgaG9s ZCBiaXQ6MSwgd3AgYml0OjEgKi8KKwl2YWwgfD0gKERFVl9DT05GX0NFX0RMIHwgREVWX0NPTkZf SE9MRF9ETCB8IERFVl9DT05GX1dQX0RMKTsKKworCXdyaXRlbCh2YWwsIHNmYy0+YmFzZSArIFNG Q19SRUdfREVWX0NPTkYpOworCisJdmFsID0gcmVhZGwoc2ZjLT5iYXNlICsgU0ZDX1JFR19HTEIp OworCXUzMnBfcmVwbGFjZV9iaXRzKCZ2YWwsIEdMQl9PUF9NT0RFX1NMQVZFLCBHTEJfT1BfTU9E RV9NQVNLKTsKKwl3cml0ZWwodmFsLCBzZmMtPmJhc2UgKyBTRkNfUkVHX0dMQik7CisKKwlyYXRl ID0gY2xrX2dldF9yYXRlKHNmYy0+Y2xrKTsKKwl2YWwgPSByZWFkbChzZmMtPmJhc2UgKyBTRkNf UkVHX0RFVl9DT05GKTsKKwlpZiAoc2ZjLT5zb2NfaW5mby0+dmVyc2lvbiA+PSBJRF9YMTYwMCAm JiByYXRlID49IDIwMDAwMDAwMCkKKwkJdTMycF9yZXBsYWNlX2JpdHMoJnZhbCwgREVWX0NPTkZf U01QX0RFTEFZXzE4MERFRywgREVWX0NPTkZfU01QX0RFTEFZX01BU0spOworCWVsc2UgaWYgKHNm Yy0+c29jX2luZm8tPnZlcnNpb24gPT0gSURfWDEwMDAgJiYgcmF0ZSA+PSAxMDAwMDAwMDApCisJ CXUzMnBfcmVwbGFjZV9iaXRzKCZ2YWwsIERFVl9DT05GX1NNUF9ERUxBWV9IQUxGX0NZQ0xFLCBE RVZfQ09ORl9TTVBfREVMQVlfTUFTSyk7CisJd3JpdGVsKHZhbCwgc2ZjLT5iYXNlICsgU0ZDX1JF R19ERVZfQ09ORik7CisKKwlyZXR1cm4gMDsKK30KKworc3RhdGljIGludCBpbmdlbmljX3NmY19w cm9iZShzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2KQoreworCXN0cnVjdCBpbmdlbmljX3Nm YyAqc2ZjOworCXN0cnVjdCBzcGlfY29udHJvbGxlciAqY3RscjsKKwlpbnQgcmV0OworCisJY3Rs ciA9IHNwaV9hbGxvY19tYXN0ZXIoJnBkZXYtPmRldiwgc2l6ZW9mKCpzZmMpKTsKKwlpZiAoIWN0 bHIpCisJCXJldHVybiAtRU5PTUVNOworCisJc2ZjID0gc3BpX2NvbnRyb2xsZXJfZ2V0X2RldmRh dGEoY3Rscik7CisKKwlzZmMtPnNvY19pbmZvID0gb2ZfZGV2aWNlX2dldF9tYXRjaF9kYXRhKCZw ZGV2LT5kZXYpOworCWlmICghc2ZjLT5zb2NfaW5mbykgeworCQlkZXZfZXJyKCZwZGV2LT5kZXYs ICJObyBvZiBtYXRjaCBkYXRhIHByb3ZpZGVkXG4iKTsKKwkJcmV0ID0gLUVOT0RFVjsKKwkJZ290 byBlcnJfcHV0X21hc3RlcjsKKwl9CisKKwlzZmMtPmJhc2UgPSBkZXZtX3BsYXRmb3JtX2lvcmVt YXBfcmVzb3VyY2UocGRldiwgMCk7CisJaWYgKElTX0VSUihzZmMtPmJhc2UpKSB7CisJCXJldCA9 IFBUUl9FUlIoc2ZjLT5iYXNlKTsKKwkJZ290byBlcnJfcHV0X21hc3RlcjsKKwl9CisKKwlzZmMt PmNsayA9IGRldm1fY2xrX2dldCgmcGRldi0+ZGV2LCAic2ZjIik7CisJaWYgKElTX0VSUihzZmMt PmNsaykpIHsKKwkJcmV0ID0gSVNfRVJSKHNmYy0+Y2xrKTsKKwkJZ290byBlcnJfcHV0X21hc3Rl cjsKKwl9CisKKwlyZXQgPSBjbGtfcHJlcGFyZV9lbmFibGUoc2ZjLT5jbGspOworCWlmIChyZXQp CisJCWdvdG8gZXJyX3B1dF9tYXN0ZXI7CisKKwlzZmMtPmlycSA9IHBsYXRmb3JtX2dldF9pcnEo cGRldiwgMCk7CisJaWYgKHNmYy0+aXJxIDwgMCkgeworCQlyZXQgPSBzZmMtPmlycTsKKwkJZ290 byBlcnJfcHV0X21hc3RlcjsKKwl9CisKKwlzZmMtPmRldiA9ICZwZGV2LT5kZXY7CisKKwlwbGF0 Zm9ybV9zZXRfZHJ2ZGF0YShwZGV2LCBzZmMpOworCisJcmV0ID0gZGV2bV9yZXF1ZXN0X2lycSgm cGRldi0+ZGV2LCBzZmMtPmlycSwgaW5nZW5pY19zZmNfaXJxX2hhbmRsZXIsIDAsCisJCQlkZXZf bmFtZSgmcGRldi0+ZGV2KSwgc2ZjKTsKKwlpZiAocmV0KSB7CisJCWRldl9lcnIoJnBkZXYtPmRl diwgIkZhaWxlZCB0byByZXF1ZXN0IGlycSVkLCByZXQgPSAlZFxuIiwgc2ZjLT5pcnEsIHJldCk7 CisJCWdvdG8gZXJyX3B1dF9tYXN0ZXI7CisJfQorCisJY3Rsci0+YnVzX251bSA9IC0xOworCWN0 bHItPm51bV9jaGlwc2VsZWN0ID0gMTsKKwljdGxyLT5tZW1fb3BzID0gJmluZ2VuaWNfc2ZjX21l bV9vcHM7CisJY3Rsci0+ZGV2Lm9mX25vZGUgPSBwZGV2LT5kZXYub2Zfbm9kZTsKKwljdGxyLT5z ZXR1cCA9IGluZ2VuaWNfc2ZjX3NldHVwOworCWN0bHItPm1vZGVfYml0cyA9IFNQSV9DUEhBIHwg U1BJX0NQT0wgfAorCQkJU1BJX1JYX0RVQUwgfCBTUElfUlhfUVVBRCB8IFNQSV9UWF9EVUFMIHwg U1BJX1RYX1FVQUQ7CisJaWYgKHNmYy0+c29jX2luZm8tPnZlcnNpb24gPj0gSURfWDIwMDApCisJ CWN0bHItPm1vZGVfYml0cyB8PSBTUElfUlhfT0NUQUwgfCBTUElfVFhfT0NUQUw7CisKKwlyZXQg PSBkZXZtX3NwaV9yZWdpc3Rlcl9jb250cm9sbGVyKCZwZGV2LT5kZXYsIGN0bHIpOworCWlmIChy ZXQpCisJCWdvdG8gZXJyX3B1dF9tYXN0ZXI7CisKKwlyZXR1cm4gMDsKKworZXJyX3B1dF9tYXN0 ZXI6CisJc3BpX21hc3Rlcl9wdXQoY3Rscik7CisKKwlyZXR1cm4gcmV0OworfQorCitzdGF0aWMg Y29uc3Qgc3RydWN0IGluZ2VuaWNfc29jX2luZm8geDEwMDBfc29jX2luZm8gPSB7CisJLnZlcnNp b24gPSBJRF9YMTAwMCwKKworCS5tYXhfYnVzX3dpZHRoID0gNCwKKworCS50cmFuX21vZGVfbWFz ayA9IFRSQU5fQ09ORl9UUkFOX01PREVfTUFTSywKK307CisKK3N0YXRpYyBjb25zdCBzdHJ1Y3Qg aW5nZW5pY19zb2NfaW5mbyB4MTYwMF9zb2NfaW5mbyA9IHsKKwkudmVyc2lvbiA9IElEX1gxNjAw LAorCisJLm1heF9idXNfd2lkdGggPSA0LAorCisJLnRyYW5fbW9kZV9tYXNrID0gVFJBTl9DT05G X1RSQU5fTU9ERV9NQVNLLAorfTsKKworc3RhdGljIGNvbnN0IHN0cnVjdCBpbmdlbmljX3NvY19p bmZvIHgyMDAwX3NvY19pbmZvID0geworCS52ZXJzaW9uID0gSURfWDIwMDAsCisKKwkubWF4X2J1 c193aWR0aCA9IDgsCisKKwkudHJhbl9tb2RlX21hc2sgPSBUUkFOX0NGRzFfVFJBTl9NT0RFX01B U0ssCit9OworCitzdGF0aWMgY29uc3Qgc3RydWN0IG9mX2RldmljZV9pZCBpbmdlbmljX3NmY19v Zl9tYXRjaGVzW10gPSB7CisJeyAuY29tcGF0aWJsZSA9ICJpbmdlbmljLHgxMDAwLXNmYyIsIC5k YXRhID0gJngxMDAwX3NvY19pbmZvIH0sCisJeyAuY29tcGF0aWJsZSA9ICJpbmdlbmljLHgxNjAw LXNmYyIsIC5kYXRhID0gJngxNjAwX3NvY19pbmZvIH0sCisJeyAuY29tcGF0aWJsZSA9ICJpbmdl bmljLHgyMDAwLXNmYyIsIC5kYXRhID0gJngyMDAwX3NvY19pbmZvIH0sCisJeyAvKiBzZW50aW5l bCAqLyB9Cit9OworTU9EVUxFX0RFVklDRV9UQUJMRShvZiwgaW5nZW5pY19zZmNfb2ZfbWF0Y2hl cyk7CisKK3N0YXRpYyBzdHJ1Y3QgcGxhdGZvcm1fZHJpdmVyIGluZ2VuaWNfc2ZjX2RyaXZlciA9 IHsKKwkuZHJpdmVyID0geworCQkubmFtZSA9ICJpbmdlbmljLXNmYyIsCisJCS5vZl9tYXRjaF90 YWJsZSA9IGluZ2VuaWNfc2ZjX29mX21hdGNoZXMsCisJfSwKKwkucHJvYmUgPSBpbmdlbmljX3Nm Y19wcm9iZSwKK307Cittb2R1bGVfcGxhdGZvcm1fZHJpdmVyKGluZ2VuaWNfc2ZjX2RyaXZlcik7 CisKK01PRFVMRV9MSUNFTlNFKCJHUEwiKTsKK01PRFVMRV9BVVRIT1IoIuWRqOeQsOadsCAoWmhv dSBZYW5qaWUpIDx6aG91eWFuamllQHdhbnllZXRlY2guY29tPiIpOworTU9EVUxFX0RFU0NSSVBU SU9OKCJJbmdlbmljIFNvQ3MgU1BJIEZsYXNoIENvbnRyb2xsZXIgRHJpdmVyIik7Ci0tIAoyLjcu NAoKCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f XwpMaW51eCBNVEQgZGlzY3Vzc2lvbiBtYWlsaW5nIGxpc3QKaHR0cDovL2xpc3RzLmluZnJhZGVh ZC5vcmcvbWFpbG1hbi9saXN0aW5mby9saW51eC1tdGQvCg==