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=-6.8 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED 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 EADD9C54E4A for ; Tue, 12 May 2020 14:42:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B8E36206A5 for ; Tue, 12 May 2020 14:42:05 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=walle.cc header.i=@walle.cc header.b="qAAqAURX" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729583AbgELOmB (ORCPT ); Tue, 12 May 2020 10:42:01 -0400 Received: from ssl.serverraum.org ([176.9.125.105]:36227 "EHLO ssl.serverraum.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726055AbgELOmA (ORCPT ); Tue, 12 May 2020 10:42:00 -0400 Received: from ssl.serverraum.org (web.serverraum.org [172.16.0.2]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ssl.serverraum.org (Postfix) with ESMTPSA id 78C602304C; Tue, 12 May 2020 16:41:48 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=walle.cc; s=mail2016061301; t=1589294514; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=DnMW0hROGkJ7+Z8BPg3hWINAuPg4fq89u8ubVHkhwS4=; b=qAAqAURXOxwJaZet3Bd+wx/MsydwaKkMa4pkZgjescqYmnaxYGkuip5l6EvXCbOR+5tfwk vT6H0gU1o1UUT95Vljpy3c8Nv6V3rtaZisF24n5bjjwV+EL4ufUoFjaaQX4L4yf64csv9s PQbRsvuFI2GO27njR7xA1RODDT30t9U= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit Date: Tue, 12 May 2020 16:41:48 +0200 From: Michael Walle To: Bartosz Golaszewski Cc: Andy Shevchenko , linux-gpio , linux-devicetree , LKML , linux-hwmon@vger.kernel.org, linux-pwm@vger.kernel.org, LINUXWATCHDOG , arm-soc , Linus Walleij , Rob Herring , Jean Delvare , Guenter Roeck , Lee Jones , Thierry Reding , =?UTF-8?Q?Uwe_Kleine-K=C3=B6nig?= , Wim Van Sebroeck , Shawn Guo , Li Yang , Thomas Gleixner , Jason Cooper , Marc Zyngier , Mark Brown , Greg Kroah-Hartman Subject: Re: [PATCH v3 10/16] gpio: add a reusable generic gpio_chip using regmap In-Reply-To: References: <20200423174543.17161-1-michael@walle.cc> <20200423174543.17161-11-michael@walle.cc> User-Agent: Roundcube Webmail/1.4.4 Message-ID: <75bff2917be1badd36af9f980cf59d2c@walle.cc> X-Sender: michael@walle.cc Sender: linux-hwmon-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-hwmon@vger.kernel.org Am 2020-05-12 14:48, schrieb Bartosz Golaszewski: > czw., 23 kwi 2020 o 19:46 Michael Walle napisał(a): >> >> There are quite a lot simple GPIO controller which are using regmap to >> access the hardware. This driver tries to be a base to unify existing >> code into one place. This won't cover everything but it should be a >> good >> starting point. >> >> It does not implement its own irq_chip because there is already a >> generic one for regmap based devices. Instead, the irq_chip will be >> instantiated in the parent driver and its irq domain will be associate >> to this driver. >> >> For now it consists of the usual registers, like set (and an optional >> clear) data register, an input register and direction registers. >> Out-of-the-box, it supports consecutive register mappings and mappings >> where the registers have gaps between them with a linear mapping >> between >> GPIO offset and bit position. For weirder mappings the user can >> register >> its own .xlate(). >> >> Signed-off-by: Michael Walle >> --- > > This looks good to me. Please see some nits below. > >> drivers/gpio/Kconfig | 4 + >> drivers/gpio/Makefile | 1 + >> drivers/gpio/gpio-regmap.c | 343 >> ++++++++++++++++++++++++++++++++++++ >> include/linux/gpio-regmap.h | 69 ++++++++ >> 4 files changed, 417 insertions(+) >> create mode 100644 drivers/gpio/gpio-regmap.c >> create mode 100644 include/linux/gpio-regmap.h >> >> diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig >> index 8ef2179fb999..ae3a49a2e970 100644 >> --- a/drivers/gpio/Kconfig >> +++ b/drivers/gpio/Kconfig >> @@ -73,6 +73,10 @@ config GPIO_GENERIC >> depends on HAS_IOMEM # Only for IOMEM drivers >> tristate >> >> +config GPIO_REGMAP >> + depends on REGMAP >> + tristate >> + >> # put drivers in the right section, in alphabetical order >> >> # This symbol is selected by both I2C and SPI expanders >> diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile >> index b2cfc21a97f3..93e139fdfa57 100644 >> --- a/drivers/gpio/Makefile >> +++ b/drivers/gpio/Makefile >> @@ -12,6 +12,7 @@ obj-$(CONFIG_GPIO_SYSFS) += gpiolib-sysfs.o >> obj-$(CONFIG_GPIO_ACPI) += gpiolib-acpi.o >> >> # Device drivers. Generally keep list sorted alphabetically >> +obj-$(CONFIG_GPIO_REGMAP) += gpio-regmap.o >> obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o >> >> # directly supported by gpio-generic >> diff --git a/drivers/gpio/gpio-regmap.c b/drivers/gpio/gpio-regmap.c >> new file mode 100644 >> index 000000000000..04939c0a22f9 >> --- /dev/null >> +++ b/drivers/gpio/gpio-regmap.c >> @@ -0,0 +1,343 @@ >> +// SPDX-License-Identifier: GPL-2.0-only >> +/* >> + * regmap based generic GPIO driver >> + * >> + * Copyright 2019 Michael Walle >> + */ >> + >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +struct gpio_regmap { >> + struct device *parent; >> + struct regmap *regmap; >> + struct gpio_chip gpio_chip; >> + >> + int reg_stride; >> + int ngpio_per_reg; >> + unsigned int reg_dat_base; >> + unsigned int reg_set_base; >> + unsigned int reg_clr_base; >> + unsigned int reg_dir_in_base; >> + unsigned int reg_dir_out_base; >> + >> + int (*reg_mask_xlate)(struct gpio_regmap *gpio, unsigned int >> base, >> + unsigned int offset, unsigned int *reg, >> + unsigned int *mask); >> + >> + void *driver_data; >> +}; >> + >> +static unsigned int gpio_regmap_addr(unsigned int addr) >> +{ >> + return (addr == GPIO_REGMAP_ADDR_ZERO) ? 0 : addr; >> +} >> + >> +/** >> + * gpio_regmap_simple_xlate() - translate base/offset to reg/mask >> + * >> + * Use a simple linear mapping to translate the offset to the >> bitmask. >> + */ >> +static int gpio_regmap_simple_xlate(struct gpio_regmap *gpio, >> + unsigned int base, unsigned int >> offset, >> + unsigned int *reg, unsigned int >> *mask) >> +{ >> + unsigned int line = offset % gpio->ngpio_per_reg; >> + unsigned int stride = offset / gpio->ngpio_per_reg; >> + >> + *reg = base + stride * gpio->reg_stride; >> + *mask = BIT(line); >> + >> + return 0; >> +} >> + >> +static int gpio_regmap_get(struct gpio_chip *chip, unsigned int >> offset) >> +{ >> + struct gpio_regmap *gpio = gpiochip_get_data(chip); >> + unsigned int base, val, reg, mask; >> + int ret; >> + >> + /* we might not have an output register if we are input only >> */ >> + if (gpio->reg_dat_base) >> + base = gpio_regmap_addr(gpio->reg_dat_base); >> + else >> + base = gpio_regmap_addr(gpio->reg_set_base); >> + >> + ret = gpio->reg_mask_xlate(gpio, base, offset, ®, &mask); >> + if (ret) >> + return ret; >> + >> + ret = regmap_read(gpio->regmap, reg, &val); >> + if (ret) >> + return ret; >> + >> + return (val & mask) ? 1 : 0; >> +} >> + >> +static void gpio_regmap_set(struct gpio_chip *chip, unsigned int >> offset, >> + int val) >> +{ >> + struct gpio_regmap *gpio = gpiochip_get_data(chip); >> + unsigned int base = gpio_regmap_addr(gpio->reg_set_base); >> + unsigned int reg, mask; >> + >> + gpio->reg_mask_xlate(gpio, base, offset, ®, &mask); >> + if (val) >> + regmap_update_bits(gpio->regmap, reg, mask, mask); >> + else >> + regmap_update_bits(gpio->regmap, reg, mask, 0); >> +} >> + >> +static void gpio_regmap_set_with_clear(struct gpio_chip *chip, >> + unsigned int offset, int val) >> +{ >> + struct gpio_regmap *gpio = gpiochip_get_data(chip); >> + unsigned int base, reg, mask; >> + >> + if (val) >> + base = gpio_regmap_addr(gpio->reg_set_base); >> + else >> + base = gpio_regmap_addr(gpio->reg_clr_base); >> + >> + gpio->reg_mask_xlate(gpio, base, offset, ®, &mask); >> + regmap_write(gpio->regmap, reg, mask); >> +} >> + >> +static int gpio_regmap_get_direction(struct gpio_chip *chip, >> + unsigned int offset) >> +{ >> + struct gpio_regmap *gpio = gpiochip_get_data(chip); >> + unsigned int base, val, reg, mask; >> + int invert, ret; >> + >> + if (gpio->reg_dir_out_base) { >> + base = gpio_regmap_addr(gpio->reg_dir_out_base); >> + invert = 0; >> + } else if (gpio->reg_dir_in_base) { >> + base = gpio_regmap_addr(gpio->reg_dir_in_base); >> + invert = 1; >> + } else { >> + return GPIO_LINE_DIRECTION_IN; >> + } >> + >> + ret = gpio->reg_mask_xlate(gpio, base, offset, ®, &mask); >> + if (ret) >> + return ret; >> + >> + ret = regmap_read(gpio->regmap, reg, &val); >> + if (ret) >> + return ret; >> + >> + if (!!(val & mask) ^ invert) >> + return GPIO_LINE_DIRECTION_OUT; >> + else >> + return GPIO_LINE_DIRECTION_IN; >> +} >> + >> +static int gpio_regmap_set_direction(struct gpio_chip *chip, >> + unsigned int offset, bool output) >> +{ >> + struct gpio_regmap *gpio = gpiochip_get_data(chip); >> + unsigned int base, val, reg, mask; >> + int invert, ret; >> + >> + if (gpio->reg_dir_out_base) { >> + base = gpio_regmap_addr(gpio->reg_dir_out_base); >> + invert = 0; >> + } else if (gpio->reg_dir_in_base) { >> + base = gpio_regmap_addr(gpio->reg_dir_in_base); >> + invert = 1; >> + } else { >> + return 0; >> + } >> + >> + ret = gpio->reg_mask_xlate(gpio, base, offset, ®, &mask); >> + if (ret) >> + return ret; >> + >> + if (!invert) >> + val = (output) ? mask : 0; >> + else >> + val = (output) ? 0 : mask; >> + >> + return regmap_update_bits(gpio->regmap, reg, mask, val); >> +} >> + >> +static int gpio_regmap_direction_input(struct gpio_chip *chip, >> + unsigned int offset) >> +{ >> + return gpio_regmap_set_direction(chip, offset, false); >> +} >> + >> +static int gpio_regmap_direction_output(struct gpio_chip *chip, >> + unsigned int offset, int >> value) >> +{ >> + gpio_regmap_set(chip, offset, value); >> + >> + return gpio_regmap_set_direction(chip, offset, true); >> +} >> + >> +void gpio_regmap_set_drvdata(struct gpio_regmap *gpio, void *data) >> +{ >> + gpio->driver_data = data; >> +} >> +EXPORT_SYMBOL_GPL(gpio_regmap_set_drvdata); >> + >> +void *gpio_regmap_get_drvdata(struct gpio_regmap *gpio) >> +{ >> + return gpio->driver_data; >> +} >> +EXPORT_SYMBOL_GPL(gpio_regmap_get_drvdata); >> + >> +/** >> + * gpio_regmap_register() - Register a generic regmap GPIO controller >> + * >> + * @gpio: gpio_regmap device to register >> + * >> + * Returns 0 on success or an errno on failure. >> + */ >> +struct gpio_regmap *gpio_regmap_register(const struct >> gpio_regmap_config *config) >> +{ >> + struct gpio_regmap *gpio; >> + struct gpio_chip *chip; >> + int ret; >> + >> + if (!config->parent) >> + return ERR_PTR(-EINVAL); >> + >> + if (!config->ngpio) >> + return ERR_PTR(-EINVAL); >> + >> + /* we need at least one */ >> + if (!config->reg_dat_base && !config->reg_set_base) >> + return ERR_PTR(-EINVAL); >> + >> + /* we don't support having both registers simulaniously for >> now */ >> + if (config->reg_dir_out_base && config->reg_dir_in_base) >> + return ERR_PTR(-EINVAL); >> + >> + gpio = kzalloc(sizeof(*gpio), GFP_KERNEL); >> + if (!gpio) >> + return ERR_PTR(-ENOMEM); >> + >> + gpio->parent = config->parent; >> + gpio->regmap = config->regmap; >> + gpio->ngpio_per_reg = config->ngpio_per_reg; >> + gpio->reg_stride = config->reg_stride; >> + gpio->reg_mask_xlate = config->reg_mask_xlate; >> + gpio->reg_set_base = config->reg_set_base; >> + gpio->reg_clr_base = config->reg_clr_base; >> + gpio->reg_dir_in_base = config->reg_dir_in_base; >> + gpio->reg_dir_out_base = config->reg_dir_out_base; >> + >> + /* if not set, assume there is only one register */ >> + if (!gpio->ngpio_per_reg) >> + gpio->ngpio_per_reg = config->ngpio; >> + >> + /* if not set, assume they are consecutive */ >> + if (!gpio->reg_stride) >> + gpio->reg_stride = 1; >> + >> + if (!gpio->reg_mask_xlate) >> + gpio->reg_mask_xlate = gpio_regmap_simple_xlate; >> + >> + chip = &gpio->gpio_chip; >> + chip->parent = config->parent; >> + chip->base = -1; >> + chip->ngpio = config->ngpio; >> + chip->can_sleep = true; >> + >> + if (!chip->label) >> + chip->label = dev_name(config->parent); >> + else >> + chip->label = config->label; >> + >> + chip->get = gpio_regmap_get; >> + if (gpio->reg_set_base && gpio->reg_clr_base) >> + chip->set = gpio_regmap_set_with_clear; >> + else if (gpio->reg_set_base) >> + chip->set = gpio_regmap_set; >> + >> + if (gpio->reg_dir_in_base || gpio->reg_dir_out_base) { >> + chip->get_direction = gpio_regmap_get_direction; >> + chip->direction_input = gpio_regmap_direction_input; >> + chip->direction_output = gpio_regmap_direction_output; >> + } >> + >> + ret = gpiochip_add_data(chip, gpio); >> + if (ret < 0) { >> + kfree(gpio); > > Maybe add a second label at the end of the function? sure >> + return ERR_PTR(ret); >> + } >> + >> + if (config->irq_domain) { >> + ret = gpiochip_irqchip_add_domain(chip, >> config->irq_domain); >> + if (ret < 0) >> + goto err; >> + } >> + >> + return gpio; >> + >> +err: >> + gpiochip_remove(chip); >> + kfree(gpio); >> + return ERR_PTR(ret); >> +} >> +EXPORT_SYMBOL_GPL(gpio_regmap_register); >> + >> +/** >> + * gpio_regmap_unregister() - Unregister a generic regmap GPIO >> controller >> + * >> + * @gpio: gpio_regmap device to unregister >> + */ >> +void gpio_regmap_unregister(struct gpio_regmap *gpio) >> +{ >> + gpiochip_remove(&gpio->gpio_chip); >> + kfree(gpio); >> +} >> +EXPORT_SYMBOL_GPL(gpio_regmap_unregister); >> + >> +static void devm_gpio_regmap_unregister(struct device *dev, void >> *res) >> +{ >> + gpio_regmap_unregister(*(struct gpio_regmap **)res); >> +} >> + >> +/** >> + * devm_gpio_regmap_register() - resource managed >> gpio_regmap_register() >> + * >> + * @dev: device that is registering this GPIO device >> + * @gpio: gpio_regmap device to register >> + * >> + * Managed gpio_regmap_register(). For generic regmap GPIO device >> registered by >> + * this function, gpio_regmap_unregister() is automatically called on >> driver >> + * detach. See gpio_regmap_register() for more information. >> + */ >> +struct gpio_regmap *devm_gpio_regmap_register(struct device *dev, >> + const struct >> gpio_regmap_config *config) >> +{ >> + struct gpio_regmap **ptr, *gpio; >> + >> + ptr = devres_alloc(devm_gpio_regmap_unregister, sizeof(*ptr), >> + GFP_KERNEL); >> + if (!ptr) >> + return ERR_PTR(-ENOMEM); >> + >> + gpio = gpio_regmap_register(config); >> + >> + if (!IS_ERR(gpio)) { >> + *ptr = gpio; >> + devres_add(dev, ptr); >> + } else { >> + devres_free(ptr); >> + } >> + >> + return gpio; >> +} >> +EXPORT_SYMBOL_GPL(devm_gpio_regmap_register); >> + >> +MODULE_AUTHOR("Michael Walle "); >> +MODULE_DESCRIPTION("GPIO generic regmap driver core"); >> +MODULE_LICENSE("GPL"); >> diff --git a/include/linux/gpio-regmap.h b/include/linux/gpio-regmap.h >> new file mode 100644 >> index 000000000000..a868cbcde6e9 >> --- /dev/null >> +++ b/include/linux/gpio-regmap.h >> @@ -0,0 +1,69 @@ >> +/* SPDX-License-Identifier: GPL-2.0-only */ >> + >> +#ifndef _LINUX_GPIO_REGMAP_H >> +#define _LINUX_GPIO_REGMAP_H >> + >> +struct gpio_regmap; >> + >> +#define GPIO_REGMAP_ADDR_ZERO ((unsigned long)(-1)) >> +#define GPIO_REGMAP_ADDR(addr) ((addr) ? : GPIO_REGMAP_ADDR_ZERO) >> + > > What if the addr is actually 0? Then the driver has to set GPIO_REGMAP_ADDR_ZERO or use the convenience macro GPIO_REGMAP_ADDR. So you can have struct gpio_regmap_config config = { 0 }; config.reg_dat_base = 0x10; config.reg_dir_out_base = 0x20; or config.reg_dat_base = GPIO_REGMAP_ADDR_ZERO; or if you can't be sure if the RHS value might be zero: config.reg_dat_base = GPIO_REGMAP_ADDR(reg); > Maybe drop GPIO_REGMAP_ADDR and require users to set unused registers > to GPIO_REGMAP_ADDR_ZERO? Thats bad because: * you'd have to set plenty of unused base registers for a simple driver * if there will be additional properties in the future, you have to touch all other drivers, because they are initialized as 0 (ie. valid reg 0). >> +/** >> + * struct gpio_regmap_config - Description of a generic regmap >> gpio_chip. >> + * >> + * @parent: The parent device >> + * @regmap: The regmap used to access the registers >> + * given, the name of the device is used >> + * @label: (Optional) Descriptive name for GPIO >> controller. >> + * If not given, the name of the device is used. >> + * @ngpio: Number of GPIOs >> + * @reg_dat_base: (Optional) (in) register base address >> + * @reg_set_base: (Optional) set register base address >> + * @reg_clr_base: (Optional) clear register base address >> + * @reg_dir_in_base: (Optional) out setting register base address >> + * @reg_dir_out_base: (Optional) in setting register base address > > The two above are inverted I think? good catch. > Also: why the limitation of only supporting one at a time? they should be exclusive, either you have a register where you set the output bits to one, or the input bits. Maybe this need a bit more context above. in gpio-mmio.c you can set both and both are used in set_direction(), but only one is read in get_direction(). That being said, I have no strong opinion wether they should be exclusive or not, besides the symmetry of set_/get_direction(). -michael > >> + * @reg_stride: (Optional) May be set if the registers >> (of the >> + * same type, dat, set, etc) are not consecutive. >> + * @ngpio_per_reg: Number of GPIOs per register >> + * @irq_domain: (Optional) IRQ domain if the >> controller is >> + * interrupt-capable >> + * @reg_mask_xlate: (Optional) Translates base address and GPIO >> + * offset to a register/bitmask pair. If not >> + * given the default gpio_regmap_simple_xlate() >> + * is used. >> + * >> + * The reg_mask_xlate translates a given base address and GPIO offset >> to >> + * register and mask pair. The base address is one of the given >> reg_*_base. >> + * >> + * All base addresses may have the special value >> GPIO_REGMAP_ADDR_ZERO >> + * which forces the address to the value 0. >> + */ >> +struct gpio_regmap_config { >> + struct device *parent; >> + struct regmap *regmap; >> + >> + const char *label; >> + int ngpio; >> + >> + unsigned int reg_dat_base; >> + unsigned int reg_set_base; >> + unsigned int reg_clr_base; >> + unsigned int reg_dir_in_base; >> + unsigned int reg_dir_out_base; >> + int reg_stride; >> + int ngpio_per_reg; >> + struct irq_domain *irq_domain; >> + >> + int (*reg_mask_xlate)(struct gpio_regmap *gpio, unsigned int >> base, >> + unsigned int offset, unsigned int *reg, >> + unsigned int *mask); >> +}; >> + >> +struct gpio_regmap *gpio_regmap_register(const struct >> gpio_regmap_config *config); >> +void gpio_regmap_unregister(struct gpio_regmap *gpio); >> +struct gpio_regmap *devm_gpio_regmap_register(struct device *dev, >> + const struct >> gpio_regmap_config *config); >> +void gpio_regmap_set_drvdata(struct gpio_regmap *gpio, void *data); >> +void *gpio_regmap_get_drvdata(struct gpio_regmap *gpio); >> + >> +#endif /* _LINUX_GPIO_REGMAP_H */ >> -- >> 2.20.1 >> From mboxrd@z Thu Jan 1 00:00:00 1970 From: Michael Walle Subject: Re: [PATCH v3 10/16] gpio: add a reusable generic gpio_chip using regmap Date: Tue, 12 May 2020 16:41:48 +0200 Message-ID: <75bff2917be1badd36af9f980cf59d2c@walle.cc> References: <20200423174543.17161-1-michael@walle.cc> <20200423174543.17161-11-michael@walle.cc> Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit Return-path: In-Reply-To: Sender: linux-gpio-owner@vger.kernel.org To: Bartosz Golaszewski Cc: Andy Shevchenko , linux-gpio , linux-devicetree , LKML , linux-hwmon@vger.kernel.org, linux-pwm@vger.kernel.org, LINUXWATCHDOG , arm-soc , Linus Walleij , Rob Herring , Jean Delvare , Guenter Roeck , Lee Jones , Thierry Reding , =?UTF-8?Q?Uwe_Kleine-K=C3=B6nig?= , Wim Van Sebroeck , Shawn Guo , Li Yang , Thomas Gleixner List-Id: linux-pwm@vger.kernel.org Am 2020-05-12 14:48, schrieb Bartosz Golaszewski: > czw., 23 kwi 2020 o 19:46 Michael Walle napisał(a): >> >> There are quite a lot simple GPIO controller which are using regmap to >> access the hardware. This driver tries to be a base to unify existing >> code into one place. This won't cover everything but it should be a >> good >> starting point. >> >> It does not implement its own irq_chip because there is already a >> generic one for regmap based devices. Instead, the irq_chip will be >> instantiated in the parent driver and its irq domain will be associate >> to this driver. >> >> For now it consists of the usual registers, like set (and an optional >> clear) data register, an input register and direction registers. >> Out-of-the-box, it supports consecutive register mappings and mappings >> where the registers have gaps between them with a linear mapping >> between >> GPIO offset and bit position. For weirder mappings the user can >> register >> its own .xlate(). >> >> Signed-off-by: Michael Walle >> --- > > This looks good to me. Please see some nits below. > >> drivers/gpio/Kconfig | 4 + >> drivers/gpio/Makefile | 1 + >> drivers/gpio/gpio-regmap.c | 343 >> ++++++++++++++++++++++++++++++++++++ >> include/linux/gpio-regmap.h | 69 ++++++++ >> 4 files changed, 417 insertions(+) >> create mode 100644 drivers/gpio/gpio-regmap.c >> create mode 100644 include/linux/gpio-regmap.h >> >> diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig >> index 8ef2179fb999..ae3a49a2e970 100644 >> --- a/drivers/gpio/Kconfig >> +++ b/drivers/gpio/Kconfig >> @@ -73,6 +73,10 @@ config GPIO_GENERIC >> depends on HAS_IOMEM # Only for IOMEM drivers >> tristate >> >> +config GPIO_REGMAP >> + depends on REGMAP >> + tristate >> + >> # put drivers in the right section, in alphabetical order >> >> # This symbol is selected by both I2C and SPI expanders >> diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile >> index b2cfc21a97f3..93e139fdfa57 100644 >> --- a/drivers/gpio/Makefile >> +++ b/drivers/gpio/Makefile >> @@ -12,6 +12,7 @@ obj-$(CONFIG_GPIO_SYSFS) += gpiolib-sysfs.o >> obj-$(CONFIG_GPIO_ACPI) += gpiolib-acpi.o >> >> # Device drivers. Generally keep list sorted alphabetically >> +obj-$(CONFIG_GPIO_REGMAP) += gpio-regmap.o >> obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o >> >> # directly supported by gpio-generic >> diff --git a/drivers/gpio/gpio-regmap.c b/drivers/gpio/gpio-regmap.c >> new file mode 100644 >> index 000000000000..04939c0a22f9 >> --- /dev/null >> +++ b/drivers/gpio/gpio-regmap.c >> @@ -0,0 +1,343 @@ >> +// SPDX-License-Identifier: GPL-2.0-only >> +/* >> + * regmap based generic GPIO driver >> + * >> + * Copyright 2019 Michael Walle >> + */ >> + >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +struct gpio_regmap { >> + struct device *parent; >> + struct regmap *regmap; >> + struct gpio_chip gpio_chip; >> + >> + int reg_stride; >> + int ngpio_per_reg; >> + unsigned int reg_dat_base; >> + unsigned int reg_set_base; >> + unsigned int reg_clr_base; >> + unsigned int reg_dir_in_base; >> + unsigned int reg_dir_out_base; >> + >> + int (*reg_mask_xlate)(struct gpio_regmap *gpio, unsigned int >> base, >> + unsigned int offset, unsigned int *reg, >> + unsigned int *mask); >> + >> + void *driver_data; >> +}; >> + >> +static unsigned int gpio_regmap_addr(unsigned int addr) >> +{ >> + return (addr == GPIO_REGMAP_ADDR_ZERO) ? 0 : addr; >> +} >> + >> +/** >> + * gpio_regmap_simple_xlate() - translate base/offset to reg/mask >> + * >> + * Use a simple linear mapping to translate the offset to the >> bitmask. >> + */ >> +static int gpio_regmap_simple_xlate(struct gpio_regmap *gpio, >> + unsigned int base, unsigned int >> offset, >> + unsigned int *reg, unsigned int >> *mask) >> +{ >> + unsigned int line = offset % gpio->ngpio_per_reg; >> + unsigned int stride = offset / gpio->ngpio_per_reg; >> + >> + *reg = base + stride * gpio->reg_stride; >> + *mask = BIT(line); >> + >> + return 0; >> +} >> + >> +static int gpio_regmap_get(struct gpio_chip *chip, unsigned int >> offset) >> +{ >> + struct gpio_regmap *gpio = gpiochip_get_data(chip); >> + unsigned int base, val, reg, mask; >> + int ret; >> + >> + /* we might not have an output register if we are input only >> */ >> + if (gpio->reg_dat_base) >> + base = gpio_regmap_addr(gpio->reg_dat_base); >> + else >> + base = gpio_regmap_addr(gpio->reg_set_base); >> + >> + ret = gpio->reg_mask_xlate(gpio, base, offset, ®, &mask); >> + if (ret) >> + return ret; >> + >> + ret = regmap_read(gpio->regmap, reg, &val); >> + if (ret) >> + return ret; >> + >> + return (val & mask) ? 1 : 0; >> +} >> + >> +static void gpio_regmap_set(struct gpio_chip *chip, unsigned int >> offset, >> + int val) >> +{ >> + struct gpio_regmap *gpio = gpiochip_get_data(chip); >> + unsigned int base = gpio_regmap_addr(gpio->reg_set_base); >> + unsigned int reg, mask; >> + >> + gpio->reg_mask_xlate(gpio, base, offset, ®, &mask); >> + if (val) >> + regmap_update_bits(gpio->regmap, reg, mask, mask); >> + else >> + regmap_update_bits(gpio->regmap, reg, mask, 0); >> +} >> + >> +static void gpio_regmap_set_with_clear(struct gpio_chip *chip, >> + unsigned int offset, int val) >> +{ >> + struct gpio_regmap *gpio = gpiochip_get_data(chip); >> + unsigned int base, reg, mask; >> + >> + if (val) >> + base = gpio_regmap_addr(gpio->reg_set_base); >> + else >> + base = gpio_regmap_addr(gpio->reg_clr_base); >> + >> + gpio->reg_mask_xlate(gpio, base, offset, ®, &mask); >> + regmap_write(gpio->regmap, reg, mask); >> +} >> + >> +static int gpio_regmap_get_direction(struct gpio_chip *chip, >> + unsigned int offset) >> +{ >> + struct gpio_regmap *gpio = gpiochip_get_data(chip); >> + unsigned int base, val, reg, mask; >> + int invert, ret; >> + >> + if (gpio->reg_dir_out_base) { >> + base = gpio_regmap_addr(gpio->reg_dir_out_base); >> + invert = 0; >> + } else if (gpio->reg_dir_in_base) { >> + base = gpio_regmap_addr(gpio->reg_dir_in_base); >> + invert = 1; >> + } else { >> + return GPIO_LINE_DIRECTION_IN; >> + } >> + >> + ret = gpio->reg_mask_xlate(gpio, base, offset, ®, &mask); >> + if (ret) >> + return ret; >> + >> + ret = regmap_read(gpio->regmap, reg, &val); >> + if (ret) >> + return ret; >> + >> + if (!!(val & mask) ^ invert) >> + return GPIO_LINE_DIRECTION_OUT; >> + else >> + return GPIO_LINE_DIRECTION_IN; >> +} >> + >> +static int gpio_regmap_set_direction(struct gpio_chip *chip, >> + unsigned int offset, bool output) >> +{ >> + struct gpio_regmap *gpio = gpiochip_get_data(chip); >> + unsigned int base, val, reg, mask; >> + int invert, ret; >> + >> + if (gpio->reg_dir_out_base) { >> + base = gpio_regmap_addr(gpio->reg_dir_out_base); >> + invert = 0; >> + } else if (gpio->reg_dir_in_base) { >> + base = gpio_regmap_addr(gpio->reg_dir_in_base); >> + invert = 1; >> + } else { >> + return 0; >> + } >> + >> + ret = gpio->reg_mask_xlate(gpio, base, offset, ®, &mask); >> + if (ret) >> + return ret; >> + >> + if (!invert) >> + val = (output) ? mask : 0; >> + else >> + val = (output) ? 0 : mask; >> + >> + return regmap_update_bits(gpio->regmap, reg, mask, val); >> +} >> + >> +static int gpio_regmap_direction_input(struct gpio_chip *chip, >> + unsigned int offset) >> +{ >> + return gpio_regmap_set_direction(chip, offset, false); >> +} >> + >> +static int gpio_regmap_direction_output(struct gpio_chip *chip, >> + unsigned int offset, int >> value) >> +{ >> + gpio_regmap_set(chip, offset, value); >> + >> + return gpio_regmap_set_direction(chip, offset, true); >> +} >> + >> +void gpio_regmap_set_drvdata(struct gpio_regmap *gpio, void *data) >> +{ >> + gpio->driver_data = data; >> +} >> +EXPORT_SYMBOL_GPL(gpio_regmap_set_drvdata); >> + >> +void *gpio_regmap_get_drvdata(struct gpio_regmap *gpio) >> +{ >> + return gpio->driver_data; >> +} >> +EXPORT_SYMBOL_GPL(gpio_regmap_get_drvdata); >> + >> +/** >> + * gpio_regmap_register() - Register a generic regmap GPIO controller >> + * >> + * @gpio: gpio_regmap device to register >> + * >> + * Returns 0 on success or an errno on failure. >> + */ >> +struct gpio_regmap *gpio_regmap_register(const struct >> gpio_regmap_config *config) >> +{ >> + struct gpio_regmap *gpio; >> + struct gpio_chip *chip; >> + int ret; >> + >> + if (!config->parent) >> + return ERR_PTR(-EINVAL); >> + >> + if (!config->ngpio) >> + return ERR_PTR(-EINVAL); >> + >> + /* we need at least one */ >> + if (!config->reg_dat_base && !config->reg_set_base) >> + return ERR_PTR(-EINVAL); >> + >> + /* we don't support having both registers simulaniously for >> now */ >> + if (config->reg_dir_out_base && config->reg_dir_in_base) >> + return ERR_PTR(-EINVAL); >> + >> + gpio = kzalloc(sizeof(*gpio), GFP_KERNEL); >> + if (!gpio) >> + return ERR_PTR(-ENOMEM); >> + >> + gpio->parent = config->parent; >> + gpio->regmap = config->regmap; >> + gpio->ngpio_per_reg = config->ngpio_per_reg; >> + gpio->reg_stride = config->reg_stride; >> + gpio->reg_mask_xlate = config->reg_mask_xlate; >> + gpio->reg_set_base = config->reg_set_base; >> + gpio->reg_clr_base = config->reg_clr_base; >> + gpio->reg_dir_in_base = config->reg_dir_in_base; >> + gpio->reg_dir_out_base = config->reg_dir_out_base; >> + >> + /* if not set, assume there is only one register */ >> + if (!gpio->ngpio_per_reg) >> + gpio->ngpio_per_reg = config->ngpio; >> + >> + /* if not set, assume they are consecutive */ >> + if (!gpio->reg_stride) >> + gpio->reg_stride = 1; >> + >> + if (!gpio->reg_mask_xlate) >> + gpio->reg_mask_xlate = gpio_regmap_simple_xlate; >> + >> + chip = &gpio->gpio_chip; >> + chip->parent = config->parent; >> + chip->base = -1; >> + chip->ngpio = config->ngpio; >> + chip->can_sleep = true; >> + >> + if (!chip->label) >> + chip->label = dev_name(config->parent); >> + else >> + chip->label = config->label; >> + >> + chip->get = gpio_regmap_get; >> + if (gpio->reg_set_base && gpio->reg_clr_base) >> + chip->set = gpio_regmap_set_with_clear; >> + else if (gpio->reg_set_base) >> + chip->set = gpio_regmap_set; >> + >> + if (gpio->reg_dir_in_base || gpio->reg_dir_out_base) { >> + chip->get_direction = gpio_regmap_get_direction; >> + chip->direction_input = gpio_regmap_direction_input; >> + chip->direction_output = gpio_regmap_direction_output; >> + } >> + >> + ret = gpiochip_add_data(chip, gpio); >> + if (ret < 0) { >> + kfree(gpio); > > Maybe add a second label at the end of the function? sure >> + return ERR_PTR(ret); >> + } >> + >> + if (config->irq_domain) { >> + ret = gpiochip_irqchip_add_domain(chip, >> config->irq_domain); >> + if (ret < 0) >> + goto err; >> + } >> + >> + return gpio; >> + >> +err: >> + gpiochip_remove(chip); >> + kfree(gpio); >> + return ERR_PTR(ret); >> +} >> +EXPORT_SYMBOL_GPL(gpio_regmap_register); >> + >> +/** >> + * gpio_regmap_unregister() - Unregister a generic regmap GPIO >> controller >> + * >> + * @gpio: gpio_regmap device to unregister >> + */ >> +void gpio_regmap_unregister(struct gpio_regmap *gpio) >> +{ >> + gpiochip_remove(&gpio->gpio_chip); >> + kfree(gpio); >> +} >> +EXPORT_SYMBOL_GPL(gpio_regmap_unregister); >> + >> +static void devm_gpio_regmap_unregister(struct device *dev, void >> *res) >> +{ >> + gpio_regmap_unregister(*(struct gpio_regmap **)res); >> +} >> + >> +/** >> + * devm_gpio_regmap_register() - resource managed >> gpio_regmap_register() >> + * >> + * @dev: device that is registering this GPIO device >> + * @gpio: gpio_regmap device to register >> + * >> + * Managed gpio_regmap_register(). For generic regmap GPIO device >> registered by >> + * this function, gpio_regmap_unregister() is automatically called on >> driver >> + * detach. See gpio_regmap_register() for more information. >> + */ >> +struct gpio_regmap *devm_gpio_regmap_register(struct device *dev, >> + const struct >> gpio_regmap_config *config) >> +{ >> + struct gpio_regmap **ptr, *gpio; >> + >> + ptr = devres_alloc(devm_gpio_regmap_unregister, sizeof(*ptr), >> + GFP_KERNEL); >> + if (!ptr) >> + return ERR_PTR(-ENOMEM); >> + >> + gpio = gpio_regmap_register(config); >> + >> + if (!IS_ERR(gpio)) { >> + *ptr = gpio; >> + devres_add(dev, ptr); >> + } else { >> + devres_free(ptr); >> + } >> + >> + return gpio; >> +} >> +EXPORT_SYMBOL_GPL(devm_gpio_regmap_register); >> + >> +MODULE_AUTHOR("Michael Walle "); >> +MODULE_DESCRIPTION("GPIO generic regmap driver core"); >> +MODULE_LICENSE("GPL"); >> diff --git a/include/linux/gpio-regmap.h b/include/linux/gpio-regmap.h >> new file mode 100644 >> index 000000000000..a868cbcde6e9 >> --- /dev/null >> +++ b/include/linux/gpio-regmap.h >> @@ -0,0 +1,69 @@ >> +/* SPDX-License-Identifier: GPL-2.0-only */ >> + >> +#ifndef _LINUX_GPIO_REGMAP_H >> +#define _LINUX_GPIO_REGMAP_H >> + >> +struct gpio_regmap; >> + >> +#define GPIO_REGMAP_ADDR_ZERO ((unsigned long)(-1)) >> +#define GPIO_REGMAP_ADDR(addr) ((addr) ? : GPIO_REGMAP_ADDR_ZERO) >> + > > What if the addr is actually 0? Then the driver has to set GPIO_REGMAP_ADDR_ZERO or use the convenience macro GPIO_REGMAP_ADDR. So you can have struct gpio_regmap_config config = { 0 }; config.reg_dat_base = 0x10; config.reg_dir_out_base = 0x20; or config.reg_dat_base = GPIO_REGMAP_ADDR_ZERO; or if you can't be sure if the RHS value might be zero: config.reg_dat_base = GPIO_REGMAP_ADDR(reg); > Maybe drop GPIO_REGMAP_ADDR and require users to set unused registers > to GPIO_REGMAP_ADDR_ZERO? Thats bad because: * you'd have to set plenty of unused base registers for a simple driver * if there will be additional properties in the future, you have to touch all other drivers, because they are initialized as 0 (ie. valid reg 0). >> +/** >> + * struct gpio_regmap_config - Description of a generic regmap >> gpio_chip. >> + * >> + * @parent: The parent device >> + * @regmap: The regmap used to access the registers >> + * given, the name of the device is used >> + * @label: (Optional) Descriptive name for GPIO >> controller. >> + * If not given, the name of the device is used. >> + * @ngpio: Number of GPIOs >> + * @reg_dat_base: (Optional) (in) register base address >> + * @reg_set_base: (Optional) set register base address >> + * @reg_clr_base: (Optional) clear register base address >> + * @reg_dir_in_base: (Optional) out setting register base address >> + * @reg_dir_out_base: (Optional) in setting register base address > > The two above are inverted I think? good catch. > Also: why the limitation of only supporting one at a time? they should be exclusive, either you have a register where you set the output bits to one, or the input bits. Maybe this need a bit more context above. in gpio-mmio.c you can set both and both are used in set_direction(), but only one is read in get_direction(). That being said, I have no strong opinion wether they should be exclusive or not, besides the symmetry of set_/get_direction(). -michael > >> + * @reg_stride: (Optional) May be set if the registers >> (of the >> + * same type, dat, set, etc) are not consecutive. >> + * @ngpio_per_reg: Number of GPIOs per register >> + * @irq_domain: (Optional) IRQ domain if the >> controller is >> + * interrupt-capable >> + * @reg_mask_xlate: (Optional) Translates base address and GPIO >> + * offset to a register/bitmask pair. If not >> + * given the default gpio_regmap_simple_xlate() >> + * is used. >> + * >> + * The reg_mask_xlate translates a given base address and GPIO offset >> to >> + * register and mask pair. The base address is one of the given >> reg_*_base. >> + * >> + * All base addresses may have the special value >> GPIO_REGMAP_ADDR_ZERO >> + * which forces the address to the value 0. >> + */ >> +struct gpio_regmap_config { >> + struct device *parent; >> + struct regmap *regmap; >> + >> + const char *label; >> + int ngpio; >> + >> + unsigned int reg_dat_base; >> + unsigned int reg_set_base; >> + unsigned int reg_clr_base; >> + unsigned int reg_dir_in_base; >> + unsigned int reg_dir_out_base; >> + int reg_stride; >> + int ngpio_per_reg; >> + struct irq_domain *irq_domain; >> + >> + int (*reg_mask_xlate)(struct gpio_regmap *gpio, unsigned int >> base, >> + unsigned int offset, unsigned int *reg, >> + unsigned int *mask); >> +}; >> + >> +struct gpio_regmap *gpio_regmap_register(const struct >> gpio_regmap_config *config); >> +void gpio_regmap_unregister(struct gpio_regmap *gpio); >> +struct gpio_regmap *devm_gpio_regmap_register(struct device *dev, >> + const struct >> gpio_regmap_config *config); >> +void gpio_regmap_set_drvdata(struct gpio_regmap *gpio, void *data); >> +void *gpio_regmap_get_drvdata(struct gpio_regmap *gpio); >> + >> +#endif /* _LINUX_GPIO_REGMAP_H */ >> -- >> 2.20.1 >> 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=-6.9 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED 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 0AEE6C54E4A for ; Tue, 12 May 2020 14:42:13 +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 C9575206A3 for ; Tue, 12 May 2020 14:42:12 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="XeTCzG3m"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=walle.cc header.i=@walle.cc header.b="qAAqAURX" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org C9575206A3 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=walle.cc Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+infradead-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.20170209; h=Sender:Content-Type: Content-Transfer-Encoding:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:Message-ID:References:In-Reply-To:Subject:To:From: Date:MIME-Version:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=Fn1imXV/P6yPwDUzr+fxnnHf177pW0171adBXt6cVxM=; b=XeTCzG3mdFVjzLrongjTFjidp Dqm/wKIV0FftGT6S+vjXI7HT3GdhtUFPLQ3A4AXpX1OO1yrSiPDaJvNvP1Lmjge/4Oh9AzOP/aZ28 YNF8wmsTGdwkhK2sPJq7CNV9GFDw4avWRGYlJcqReFs+aAvQexAgCwWHvtQ6hkyYnt3xFbEUaGQtB ClwSb7rWnSHxSeXB+oKKrsW0BElMiezLMYFKTY/vJNS38vRn61ub0rEL+461043RCTJ8OquSNiekB wxdX3Vyt4oPysyvnA4MZvUWmiclK1GrQ7homcAON7JuCnHXYTCZbVjH6rh9Djo0PSHmQgreONU8Ez WbK9xBiHQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jYW6l-00025P-K9; Tue, 12 May 2020 14:42:11 +0000 Received: from ssl.serverraum.org ([176.9.125.105]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jYW6h-00024O-TI for linux-arm-kernel@lists.infradead.org; Tue, 12 May 2020 14:42:10 +0000 Received: from ssl.serverraum.org (web.serverraum.org [172.16.0.2]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ssl.serverraum.org (Postfix) with ESMTPSA id 78C602304C; Tue, 12 May 2020 16:41:48 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=walle.cc; s=mail2016061301; t=1589294514; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=DnMW0hROGkJ7+Z8BPg3hWINAuPg4fq89u8ubVHkhwS4=; b=qAAqAURXOxwJaZet3Bd+wx/MsydwaKkMa4pkZgjescqYmnaxYGkuip5l6EvXCbOR+5tfwk vT6H0gU1o1UUT95Vljpy3c8Nv6V3rtaZisF24n5bjjwV+EL4ufUoFjaaQX4L4yf64csv9s PQbRsvuFI2GO27njR7xA1RODDT30t9U= MIME-Version: 1.0 Date: Tue, 12 May 2020 16:41:48 +0200 From: Michael Walle To: Bartosz Golaszewski Subject: Re: [PATCH v3 10/16] gpio: add a reusable generic gpio_chip using regmap In-Reply-To: References: <20200423174543.17161-1-michael@walle.cc> <20200423174543.17161-11-michael@walle.cc> User-Agent: Roundcube Webmail/1.4.4 Message-ID: <75bff2917be1badd36af9f980cf59d2c@walle.cc> X-Sender: michael@walle.cc X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200512_074208_259854_2736E852 X-CRM114-Status: GOOD ( 22.01 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-devicetree , Linus Walleij , Thierry Reding , Lee Jones , Jason Cooper , Andy Shevchenko , Marc Zyngier , =?UTF-8?Q?Uwe_Kleine-K=C3=B6nig?= , Guenter Roeck , linux-pwm@vger.kernel.org, Jean Delvare , LINUXWATCHDOG , linux-gpio , Mark Brown , Thomas Gleixner , Wim Van Sebroeck , arm-soc , linux-hwmon@vger.kernel.org, Greg Kroah-Hartman , LKML , Li Yang , Rob Herring , Shawn Guo Content-Transfer-Encoding: base64 Content-Type: text/plain; charset="utf-8"; Format="flowed" Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+infradead-linux-arm-kernel=archiver.kernel.org@lists.infradead.org QW0gMjAyMC0wNS0xMiAxNDo0OCwgc2NocmllYiBCYXJ0b3N6IEdvbGFzemV3c2tpOgo+IGN6dy4s IDIzIGt3aSAyMDIwIG8gMTk6NDYgTWljaGFlbCBXYWxsZSA8bWljaGFlbEB3YWxsZS5jYz4gbmFw aXNhxYIoYSk6Cj4+IAo+PiBUaGVyZSBhcmUgcXVpdGUgYSBsb3Qgc2ltcGxlIEdQSU8gY29udHJv bGxlciB3aGljaCBhcmUgdXNpbmcgcmVnbWFwIHRvCj4+IGFjY2VzcyB0aGUgaGFyZHdhcmUuIFRo aXMgZHJpdmVyIHRyaWVzIHRvIGJlIGEgYmFzZSB0byB1bmlmeSBleGlzdGluZwo+PiBjb2RlIGlu dG8gb25lIHBsYWNlLiBUaGlzIHdvbid0IGNvdmVyIGV2ZXJ5dGhpbmcgYnV0IGl0IHNob3VsZCBi ZSBhIAo+PiBnb29kCj4+IHN0YXJ0aW5nIHBvaW50Lgo+PiAKPj4gSXQgZG9lcyBub3QgaW1wbGVt ZW50IGl0cyBvd24gaXJxX2NoaXAgYmVjYXVzZSB0aGVyZSBpcyBhbHJlYWR5IGEKPj4gZ2VuZXJp YyBvbmUgZm9yIHJlZ21hcCBiYXNlZCBkZXZpY2VzLiBJbnN0ZWFkLCB0aGUgaXJxX2NoaXAgd2ls bCBiZQo+PiBpbnN0YW50aWF0ZWQgaW4gdGhlIHBhcmVudCBkcml2ZXIgYW5kIGl0cyBpcnEgZG9t YWluIHdpbGwgYmUgYXNzb2NpYXRlCj4+IHRvIHRoaXMgZHJpdmVyLgo+PiAKPj4gRm9yIG5vdyBp dCBjb25zaXN0cyBvZiB0aGUgdXN1YWwgcmVnaXN0ZXJzLCBsaWtlIHNldCAoYW5kIGFuIG9wdGlv bmFsCj4+IGNsZWFyKSBkYXRhIHJlZ2lzdGVyLCBhbiBpbnB1dCByZWdpc3RlciBhbmQgZGlyZWN0 aW9uIHJlZ2lzdGVycy4KPj4gT3V0LW9mLXRoZS1ib3gsIGl0IHN1cHBvcnRzIGNvbnNlY3V0aXZl IHJlZ2lzdGVyIG1hcHBpbmdzIGFuZCBtYXBwaW5ncwo+PiB3aGVyZSB0aGUgcmVnaXN0ZXJzIGhh dmUgZ2FwcyBiZXR3ZWVuIHRoZW0gd2l0aCBhIGxpbmVhciBtYXBwaW5nIAo+PiBiZXR3ZWVuCj4+ IEdQSU8gb2Zmc2V0IGFuZCBiaXQgcG9zaXRpb24uIEZvciB3ZWlyZGVyIG1hcHBpbmdzIHRoZSB1 c2VyIGNhbiAKPj4gcmVnaXN0ZXIKPj4gaXRzIG93biAueGxhdGUoKS4KPj4gCj4+IFNpZ25lZC1v ZmYtYnk6IE1pY2hhZWwgV2FsbGUgPG1pY2hhZWxAd2FsbGUuY2M+Cj4+IC0tLQo+IAo+IFRoaXMg bG9va3MgZ29vZCB0byBtZS4gUGxlYXNlIHNlZSBzb21lIG5pdHMgYmVsb3cuCj4gCj4+ICBkcml2 ZXJzL2dwaW8vS2NvbmZpZyAgICAgICAgfCAgIDQgKwo+PiAgZHJpdmVycy9ncGlvL01ha2VmaWxl ICAgICAgIHwgICAxICsKPj4gIGRyaXZlcnMvZ3Bpby9ncGlvLXJlZ21hcC5jICB8IDM0MyAKPj4g KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrCj4+ICBpbmNsdWRlL2xpbnV4L2dw aW8tcmVnbWFwLmggfCAgNjkgKysrKysrKysKPj4gIDQgZmlsZXMgY2hhbmdlZCwgNDE3IGluc2Vy dGlvbnMoKykKPj4gIGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL2dwaW8vZ3Bpby1yZWdtYXAu Ywo+PiAgY3JlYXRlIG1vZGUgMTAwNjQ0IGluY2x1ZGUvbGludXgvZ3Bpby1yZWdtYXAuaAo+PiAK Pj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvZ3Bpby9LY29uZmlnIGIvZHJpdmVycy9ncGlvL0tjb25m aWcKPj4gaW5kZXggOGVmMjE3OWZiOTk5Li5hZTNhNDlhMmU5NzAgMTAwNjQ0Cj4+IC0tLSBhL2Ry aXZlcnMvZ3Bpby9LY29uZmlnCj4+ICsrKyBiL2RyaXZlcnMvZ3Bpby9LY29uZmlnCj4+IEBAIC03 Myw2ICs3MywxMCBAQCBjb25maWcgR1BJT19HRU5FUklDCj4+ICAgICAgICAgZGVwZW5kcyBvbiBI QVNfSU9NRU0gIyBPbmx5IGZvciBJT01FTSBkcml2ZXJzCj4+ICAgICAgICAgdHJpc3RhdGUKPj4g Cj4+ICtjb25maWcgR1BJT19SRUdNQVAKPj4gKyAgICAgICBkZXBlbmRzIG9uIFJFR01BUAo+PiAr ICAgICAgIHRyaXN0YXRlCj4+ICsKPj4gICMgcHV0IGRyaXZlcnMgaW4gdGhlIHJpZ2h0IHNlY3Rp b24sIGluIGFscGhhYmV0aWNhbCBvcmRlcgo+PiAKPj4gICMgVGhpcyBzeW1ib2wgaXMgc2VsZWN0 ZWQgYnkgYm90aCBJMkMgYW5kIFNQSSBleHBhbmRlcnMKPj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMv Z3Bpby9NYWtlZmlsZSBiL2RyaXZlcnMvZ3Bpby9NYWtlZmlsZQo+PiBpbmRleCBiMmNmYzIxYTk3 ZjMuLjkzZTEzOWZkZmE1NyAxMDA2NDQKPj4gLS0tIGEvZHJpdmVycy9ncGlvL01ha2VmaWxlCj4+ ICsrKyBiL2RyaXZlcnMvZ3Bpby9NYWtlZmlsZQo+PiBAQCAtMTIsNiArMTIsNyBAQCBvYmotJChD T05GSUdfR1BJT19TWVNGUykgICAgICArPSBncGlvbGliLXN5c2ZzLm8KPj4gIG9iai0kKENPTkZJ R19HUElPX0FDUEkpICAgICAgICAgICAgICAgICs9IGdwaW9saWItYWNwaS5vCj4+IAo+PiAgIyBE ZXZpY2UgZHJpdmVycy4gR2VuZXJhbGx5IGtlZXAgbGlzdCBzb3J0ZWQgYWxwaGFiZXRpY2FsbHkK Pj4gK29iai0kKENPTkZJR19HUElPX1JFR01BUCkgICAgICArPSBncGlvLXJlZ21hcC5vCj4+ICBv YmotJChDT05GSUdfR1BJT19HRU5FUklDKSAgICAgKz0gZ3Bpby1nZW5lcmljLm8KPj4gCj4+ICAj IGRpcmVjdGx5IHN1cHBvcnRlZCBieSBncGlvLWdlbmVyaWMKPj4gZGlmZiAtLWdpdCBhL2RyaXZl cnMvZ3Bpby9ncGlvLXJlZ21hcC5jIGIvZHJpdmVycy9ncGlvL2dwaW8tcmVnbWFwLmMKPj4gbmV3 IGZpbGUgbW9kZSAxMDA2NDQKPj4gaW5kZXggMDAwMDAwMDAwMDAwLi4wNDkzOWMwYTIyZjkKPj4g LS0tIC9kZXYvbnVsbAo+PiArKysgYi9kcml2ZXJzL2dwaW8vZ3Bpby1yZWdtYXAuYwo+PiBAQCAt MCwwICsxLDM0MyBAQAo+PiArLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEdQTC0yLjAtb25s eQo+PiArLyoKPj4gKyAqIHJlZ21hcCBiYXNlZCBnZW5lcmljIEdQSU8gZHJpdmVyCj4+ICsgKgo+ PiArICogQ29weXJpZ2h0IDIwMTkgTWljaGFlbCBXYWxsZSA8bWljaGFlbEB3YWxsZS5jYz4KPj4g KyAqLwo+PiArCj4+ICsjaW5jbHVkZSA8bGludXgvZ3Bpby9kcml2ZXIuaD4KPj4gKyNpbmNsdWRl IDxsaW51eC9ncGlvLXJlZ21hcC5oPgo+PiArI2luY2x1ZGUgPGxpbnV4L2tlcm5lbC5oPgo+PiAr I2luY2x1ZGUgPGxpbnV4L21vZHVsZS5oPgo+PiArI2luY2x1ZGUgPGxpbnV4L3JlZ21hcC5oPgo+ PiArCj4+ICtzdHJ1Y3QgZ3Bpb19yZWdtYXAgewo+PiArICAgICAgIHN0cnVjdCBkZXZpY2UgKnBh cmVudDsKPj4gKyAgICAgICBzdHJ1Y3QgcmVnbWFwICpyZWdtYXA7Cj4+ICsgICAgICAgc3RydWN0 IGdwaW9fY2hpcCBncGlvX2NoaXA7Cj4+ICsKPj4gKyAgICAgICBpbnQgcmVnX3N0cmlkZTsKPj4g KyAgICAgICBpbnQgbmdwaW9fcGVyX3JlZzsKPj4gKyAgICAgICB1bnNpZ25lZCBpbnQgcmVnX2Rh dF9iYXNlOwo+PiArICAgICAgIHVuc2lnbmVkIGludCByZWdfc2V0X2Jhc2U7Cj4+ICsgICAgICAg dW5zaWduZWQgaW50IHJlZ19jbHJfYmFzZTsKPj4gKyAgICAgICB1bnNpZ25lZCBpbnQgcmVnX2Rp cl9pbl9iYXNlOwo+PiArICAgICAgIHVuc2lnbmVkIGludCByZWdfZGlyX291dF9iYXNlOwo+PiAr Cj4+ICsgICAgICAgaW50ICgqcmVnX21hc2tfeGxhdGUpKHN0cnVjdCBncGlvX3JlZ21hcCAqZ3Bp bywgdW5zaWduZWQgaW50IAo+PiBiYXNlLAo+PiArICAgICAgICAgICAgICAgICAgICAgICAgICAg ICB1bnNpZ25lZCBpbnQgb2Zmc2V0LCB1bnNpZ25lZCBpbnQgKnJlZywKPj4gKyAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgdW5zaWduZWQgaW50ICptYXNrKTsKPj4gKwo+PiArICAgICAgIHZv aWQgKmRyaXZlcl9kYXRhOwo+PiArfTsKPj4gKwo+PiArc3RhdGljIHVuc2lnbmVkIGludCBncGlv X3JlZ21hcF9hZGRyKHVuc2lnbmVkIGludCBhZGRyKQo+PiArewo+PiArICAgICAgIHJldHVybiAo YWRkciA9PSBHUElPX1JFR01BUF9BRERSX1pFUk8pID8gMCA6IGFkZHI7Cj4+ICt9Cj4+ICsKPj4g Ky8qKgo+PiArICogZ3Bpb19yZWdtYXBfc2ltcGxlX3hsYXRlKCkgLSB0cmFuc2xhdGUgYmFzZS9v ZmZzZXQgdG8gcmVnL21hc2sKPj4gKyAqCj4+ICsgKiBVc2UgYSBzaW1wbGUgbGluZWFyIG1hcHBp bmcgdG8gdHJhbnNsYXRlIHRoZSBvZmZzZXQgdG8gdGhlIAo+PiBiaXRtYXNrLgo+PiArICovCj4+ ICtzdGF0aWMgaW50IGdwaW9fcmVnbWFwX3NpbXBsZV94bGF0ZShzdHJ1Y3QgZ3Bpb19yZWdtYXAg KmdwaW8sCj4+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuc2lnbmVkIGlu dCBiYXNlLCB1bnNpZ25lZCBpbnQgCj4+IG9mZnNldCwKPj4gKyAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgdW5zaWduZWQgaW50ICpyZWcsIHVuc2lnbmVkIGludCAKPj4gKm1hc2sp Cj4+ICt7Cj4+ICsgICAgICAgdW5zaWduZWQgaW50IGxpbmUgPSBvZmZzZXQgJSBncGlvLT5uZ3Bp b19wZXJfcmVnOwo+PiArICAgICAgIHVuc2lnbmVkIGludCBzdHJpZGUgPSBvZmZzZXQgLyBncGlv LT5uZ3Bpb19wZXJfcmVnOwo+PiArCj4+ICsgICAgICAgKnJlZyA9IGJhc2UgKyBzdHJpZGUgKiBn cGlvLT5yZWdfc3RyaWRlOwo+PiArICAgICAgICptYXNrID0gQklUKGxpbmUpOwo+PiArCj4+ICsg ICAgICAgcmV0dXJuIDA7Cj4+ICt9Cj4+ICsKPj4gK3N0YXRpYyBpbnQgZ3Bpb19yZWdtYXBfZ2V0 KHN0cnVjdCBncGlvX2NoaXAgKmNoaXAsIHVuc2lnbmVkIGludCAKPj4gb2Zmc2V0KQo+PiArewo+ PiArICAgICAgIHN0cnVjdCBncGlvX3JlZ21hcCAqZ3BpbyA9IGdwaW9jaGlwX2dldF9kYXRhKGNo aXApOwo+PiArICAgICAgIHVuc2lnbmVkIGludCBiYXNlLCB2YWwsIHJlZywgbWFzazsKPj4gKyAg ICAgICBpbnQgcmV0Owo+PiArCj4+ICsgICAgICAgLyogd2UgbWlnaHQgbm90IGhhdmUgYW4gb3V0 cHV0IHJlZ2lzdGVyIGlmIHdlIGFyZSBpbnB1dCBvbmx5IAo+PiAqLwo+PiArICAgICAgIGlmIChn cGlvLT5yZWdfZGF0X2Jhc2UpCj4+ICsgICAgICAgICAgICAgICBiYXNlID0gZ3Bpb19yZWdtYXBf YWRkcihncGlvLT5yZWdfZGF0X2Jhc2UpOwo+PiArICAgICAgIGVsc2UKPj4gKyAgICAgICAgICAg ICAgIGJhc2UgPSBncGlvX3JlZ21hcF9hZGRyKGdwaW8tPnJlZ19zZXRfYmFzZSk7Cj4+ICsKPj4g KyAgICAgICByZXQgPSBncGlvLT5yZWdfbWFza194bGF0ZShncGlvLCBiYXNlLCBvZmZzZXQsICZy ZWcsICZtYXNrKTsKPj4gKyAgICAgICBpZiAocmV0KQo+PiArICAgICAgICAgICAgICAgcmV0dXJu IHJldDsKPj4gKwo+PiArICAgICAgIHJldCA9IHJlZ21hcF9yZWFkKGdwaW8tPnJlZ21hcCwgcmVn LCAmdmFsKTsKPj4gKyAgICAgICBpZiAocmV0KQo+PiArICAgICAgICAgICAgICAgcmV0dXJuIHJl dDsKPj4gKwo+PiArICAgICAgIHJldHVybiAodmFsICYgbWFzaykgPyAxIDogMDsKPj4gK30KPj4g Kwo+PiArc3RhdGljIHZvaWQgZ3Bpb19yZWdtYXBfc2V0KHN0cnVjdCBncGlvX2NoaXAgKmNoaXAs IHVuc2lnbmVkIGludCAKPj4gb2Zmc2V0LAo+PiArICAgICAgICAgICAgICAgICAgICAgICAgICAg aW50IHZhbCkKPj4gK3sKPj4gKyAgICAgICBzdHJ1Y3QgZ3Bpb19yZWdtYXAgKmdwaW8gPSBncGlv Y2hpcF9nZXRfZGF0YShjaGlwKTsKPj4gKyAgICAgICB1bnNpZ25lZCBpbnQgYmFzZSA9IGdwaW9f cmVnbWFwX2FkZHIoZ3Bpby0+cmVnX3NldF9iYXNlKTsKPj4gKyAgICAgICB1bnNpZ25lZCBpbnQg cmVnLCBtYXNrOwo+PiArCj4+ICsgICAgICAgZ3Bpby0+cmVnX21hc2tfeGxhdGUoZ3BpbywgYmFz ZSwgb2Zmc2V0LCAmcmVnLCAmbWFzayk7Cj4+ICsgICAgICAgaWYgKHZhbCkKPj4gKyAgICAgICAg ICAgICAgIHJlZ21hcF91cGRhdGVfYml0cyhncGlvLT5yZWdtYXAsIHJlZywgbWFzaywgbWFzayk7 Cj4+ICsgICAgICAgZWxzZQo+PiArICAgICAgICAgICAgICAgcmVnbWFwX3VwZGF0ZV9iaXRzKGdw aW8tPnJlZ21hcCwgcmVnLCBtYXNrLCAwKTsKPj4gK30KPj4gKwo+PiArc3RhdGljIHZvaWQgZ3Bp b19yZWdtYXBfc2V0X3dpdGhfY2xlYXIoc3RydWN0IGdwaW9fY2hpcCAqY2hpcCwKPj4gKyAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5zaWduZWQgaW50IG9mZnNldCwgaW50 IHZhbCkKPj4gK3sKPj4gKyAgICAgICBzdHJ1Y3QgZ3Bpb19yZWdtYXAgKmdwaW8gPSBncGlvY2hp cF9nZXRfZGF0YShjaGlwKTsKPj4gKyAgICAgICB1bnNpZ25lZCBpbnQgYmFzZSwgcmVnLCBtYXNr Owo+PiArCj4+ICsgICAgICAgaWYgKHZhbCkKPj4gKyAgICAgICAgICAgICAgIGJhc2UgPSBncGlv X3JlZ21hcF9hZGRyKGdwaW8tPnJlZ19zZXRfYmFzZSk7Cj4+ICsgICAgICAgZWxzZQo+PiArICAg ICAgICAgICAgICAgYmFzZSA9IGdwaW9fcmVnbWFwX2FkZHIoZ3Bpby0+cmVnX2Nscl9iYXNlKTsK Pj4gKwo+PiArICAgICAgIGdwaW8tPnJlZ19tYXNrX3hsYXRlKGdwaW8sIGJhc2UsIG9mZnNldCwg JnJlZywgJm1hc2spOwo+PiArICAgICAgIHJlZ21hcF93cml0ZShncGlvLT5yZWdtYXAsIHJlZywg bWFzayk7Cj4+ICt9Cj4+ICsKPj4gK3N0YXRpYyBpbnQgZ3Bpb19yZWdtYXBfZ2V0X2RpcmVjdGlv bihzdHJ1Y3QgZ3Bpb19jaGlwICpjaGlwLAo+PiArICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgdW5zaWduZWQgaW50IG9mZnNldCkKPj4gK3sKPj4gKyAgICAgICBzdHJ1Y3QgZ3Bp b19yZWdtYXAgKmdwaW8gPSBncGlvY2hpcF9nZXRfZGF0YShjaGlwKTsKPj4gKyAgICAgICB1bnNp Z25lZCBpbnQgYmFzZSwgdmFsLCByZWcsIG1hc2s7Cj4+ICsgICAgICAgaW50IGludmVydCwgcmV0 Owo+PiArCj4+ICsgICAgICAgaWYgKGdwaW8tPnJlZ19kaXJfb3V0X2Jhc2UpIHsKPj4gKyAgICAg ICAgICAgICAgIGJhc2UgPSBncGlvX3JlZ21hcF9hZGRyKGdwaW8tPnJlZ19kaXJfb3V0X2Jhc2Up Owo+PiArICAgICAgICAgICAgICAgaW52ZXJ0ID0gMDsKPj4gKyAgICAgICB9IGVsc2UgaWYgKGdw aW8tPnJlZ19kaXJfaW5fYmFzZSkgewo+PiArICAgICAgICAgICAgICAgYmFzZSA9IGdwaW9fcmVn bWFwX2FkZHIoZ3Bpby0+cmVnX2Rpcl9pbl9iYXNlKTsKPj4gKyAgICAgICAgICAgICAgIGludmVy dCA9IDE7Cj4+ICsgICAgICAgfSBlbHNlIHsKPj4gKyAgICAgICAgICAgICAgIHJldHVybiBHUElP X0xJTkVfRElSRUNUSU9OX0lOOwo+PiArICAgICAgIH0KPj4gKwo+PiArICAgICAgIHJldCA9IGdw aW8tPnJlZ19tYXNrX3hsYXRlKGdwaW8sIGJhc2UsIG9mZnNldCwgJnJlZywgJm1hc2spOwo+PiAr ICAgICAgIGlmIChyZXQpCj4+ICsgICAgICAgICAgICAgICByZXR1cm4gcmV0Owo+PiArCj4+ICsg ICAgICAgcmV0ID0gcmVnbWFwX3JlYWQoZ3Bpby0+cmVnbWFwLCByZWcsICZ2YWwpOwo+PiArICAg ICAgIGlmIChyZXQpCj4+ICsgICAgICAgICAgICAgICByZXR1cm4gcmV0Owo+PiArCj4+ICsgICAg ICAgaWYgKCEhKHZhbCAmIG1hc2spIF4gaW52ZXJ0KQo+PiArICAgICAgICAgICAgICAgcmV0dXJu IEdQSU9fTElORV9ESVJFQ1RJT05fT1VUOwo+PiArICAgICAgIGVsc2UKPj4gKyAgICAgICAgICAg ICAgIHJldHVybiBHUElPX0xJTkVfRElSRUNUSU9OX0lOOwo+PiArfQo+PiArCj4+ICtzdGF0aWMg aW50IGdwaW9fcmVnbWFwX3NldF9kaXJlY3Rpb24oc3RydWN0IGdwaW9fY2hpcCAqY2hpcCwKPj4g KyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuc2lnbmVkIGludCBvZmZzZXQs IGJvb2wgb3V0cHV0KQo+PiArewo+PiArICAgICAgIHN0cnVjdCBncGlvX3JlZ21hcCAqZ3BpbyA9 IGdwaW9jaGlwX2dldF9kYXRhKGNoaXApOwo+PiArICAgICAgIHVuc2lnbmVkIGludCBiYXNlLCB2 YWwsIHJlZywgbWFzazsKPj4gKyAgICAgICBpbnQgaW52ZXJ0LCByZXQ7Cj4+ICsKPj4gKyAgICAg ICBpZiAoZ3Bpby0+cmVnX2Rpcl9vdXRfYmFzZSkgewo+PiArICAgICAgICAgICAgICAgYmFzZSA9 IGdwaW9fcmVnbWFwX2FkZHIoZ3Bpby0+cmVnX2Rpcl9vdXRfYmFzZSk7Cj4+ICsgICAgICAgICAg ICAgICBpbnZlcnQgPSAwOwo+PiArICAgICAgIH0gZWxzZSBpZiAoZ3Bpby0+cmVnX2Rpcl9pbl9i YXNlKSB7Cj4+ICsgICAgICAgICAgICAgICBiYXNlID0gZ3Bpb19yZWdtYXBfYWRkcihncGlvLT5y ZWdfZGlyX2luX2Jhc2UpOwo+PiArICAgICAgICAgICAgICAgaW52ZXJ0ID0gMTsKPj4gKyAgICAg ICB9IGVsc2Ugewo+PiArICAgICAgICAgICAgICAgcmV0dXJuIDA7Cj4+ICsgICAgICAgfQo+PiAr Cj4+ICsgICAgICAgcmV0ID0gZ3Bpby0+cmVnX21hc2tfeGxhdGUoZ3BpbywgYmFzZSwgb2Zmc2V0 LCAmcmVnLCAmbWFzayk7Cj4+ICsgICAgICAgaWYgKHJldCkKPj4gKyAgICAgICAgICAgICAgIHJl dHVybiByZXQ7Cj4+ICsKPj4gKyAgICAgICBpZiAoIWludmVydCkKPj4gKyAgICAgICAgICAgICAg IHZhbCA9IChvdXRwdXQpID8gbWFzayA6IDA7Cj4+ICsgICAgICAgZWxzZQo+PiArICAgICAgICAg ICAgICAgdmFsID0gKG91dHB1dCkgPyAwIDogbWFzazsKPj4gKwo+PiArICAgICAgIHJldHVybiBy ZWdtYXBfdXBkYXRlX2JpdHMoZ3Bpby0+cmVnbWFwLCByZWcsIG1hc2ssIHZhbCk7Cj4+ICt9Cj4+ ICsKPj4gK3N0YXRpYyBpbnQgZ3Bpb19yZWdtYXBfZGlyZWN0aW9uX2lucHV0KHN0cnVjdCBncGlv X2NoaXAgKmNoaXAsCj4+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVu c2lnbmVkIGludCBvZmZzZXQpCj4+ICt7Cj4+ICsgICAgICAgcmV0dXJuIGdwaW9fcmVnbWFwX3Nl dF9kaXJlY3Rpb24oY2hpcCwgb2Zmc2V0LCBmYWxzZSk7Cj4+ICt9Cj4+ICsKPj4gK3N0YXRpYyBp bnQgZ3Bpb19yZWdtYXBfZGlyZWN0aW9uX291dHB1dChzdHJ1Y3QgZ3Bpb19jaGlwICpjaGlwLAo+ PiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5zaWduZWQgaW50IG9m ZnNldCwgaW50IAo+PiB2YWx1ZSkKPj4gK3sKPj4gKyAgICAgICBncGlvX3JlZ21hcF9zZXQoY2hp cCwgb2Zmc2V0LCB2YWx1ZSk7Cj4+ICsKPj4gKyAgICAgICByZXR1cm4gZ3Bpb19yZWdtYXBfc2V0 X2RpcmVjdGlvbihjaGlwLCBvZmZzZXQsIHRydWUpOwo+PiArfQo+PiArCj4+ICt2b2lkIGdwaW9f cmVnbWFwX3NldF9kcnZkYXRhKHN0cnVjdCBncGlvX3JlZ21hcCAqZ3Bpbywgdm9pZCAqZGF0YSkK Pj4gK3sKPj4gKyAgICAgICBncGlvLT5kcml2ZXJfZGF0YSA9IGRhdGE7Cj4+ICt9Cj4+ICtFWFBP UlRfU1lNQk9MX0dQTChncGlvX3JlZ21hcF9zZXRfZHJ2ZGF0YSk7Cj4+ICsKPj4gK3ZvaWQgKmdw aW9fcmVnbWFwX2dldF9kcnZkYXRhKHN0cnVjdCBncGlvX3JlZ21hcCAqZ3BpbykKPj4gK3sKPj4g KyAgICAgICByZXR1cm4gZ3Bpby0+ZHJpdmVyX2RhdGE7Cj4+ICt9Cj4+ICtFWFBPUlRfU1lNQk9M X0dQTChncGlvX3JlZ21hcF9nZXRfZHJ2ZGF0YSk7Cj4+ICsKPj4gKy8qKgo+PiArICogZ3Bpb19y ZWdtYXBfcmVnaXN0ZXIoKSAtIFJlZ2lzdGVyIGEgZ2VuZXJpYyByZWdtYXAgR1BJTyBjb250cm9s bGVyCj4+ICsgKgo+PiArICogQGdwaW86IGdwaW9fcmVnbWFwIGRldmljZSB0byByZWdpc3Rlcgo+ PiArICoKPj4gKyAqIFJldHVybnMgMCBvbiBzdWNjZXNzIG9yIGFuIGVycm5vIG9uIGZhaWx1cmUu Cj4+ICsgKi8KPj4gK3N0cnVjdCBncGlvX3JlZ21hcCAqZ3Bpb19yZWdtYXBfcmVnaXN0ZXIoY29u c3Qgc3RydWN0IAo+PiBncGlvX3JlZ21hcF9jb25maWcgKmNvbmZpZykKPj4gK3sKPj4gKyAgICAg ICBzdHJ1Y3QgZ3Bpb19yZWdtYXAgKmdwaW87Cj4+ICsgICAgICAgc3RydWN0IGdwaW9fY2hpcCAq Y2hpcDsKPj4gKyAgICAgICBpbnQgcmV0Owo+PiArCj4+ICsgICAgICAgaWYgKCFjb25maWctPnBh cmVudCkKPj4gKyAgICAgICAgICAgICAgIHJldHVybiBFUlJfUFRSKC1FSU5WQUwpOwo+PiArCj4+ ICsgICAgICAgaWYgKCFjb25maWctPm5ncGlvKQo+PiArICAgICAgICAgICAgICAgcmV0dXJuIEVS Ul9QVFIoLUVJTlZBTCk7Cj4+ICsKPj4gKyAgICAgICAvKiB3ZSBuZWVkIGF0IGxlYXN0IG9uZSAq Lwo+PiArICAgICAgIGlmICghY29uZmlnLT5yZWdfZGF0X2Jhc2UgJiYgIWNvbmZpZy0+cmVnX3Nl dF9iYXNlKQo+PiArICAgICAgICAgICAgICAgcmV0dXJuIEVSUl9QVFIoLUVJTlZBTCk7Cj4+ICsK Pj4gKyAgICAgICAvKiB3ZSBkb24ndCBzdXBwb3J0IGhhdmluZyBib3RoIHJlZ2lzdGVycyBzaW11 bGFuaW91c2x5IGZvciAKPj4gbm93ICovCj4+ICsgICAgICAgaWYgKGNvbmZpZy0+cmVnX2Rpcl9v dXRfYmFzZSAmJiBjb25maWctPnJlZ19kaXJfaW5fYmFzZSkKPj4gKyAgICAgICAgICAgICAgIHJl dHVybiBFUlJfUFRSKC1FSU5WQUwpOwo+PiArCj4+ICsgICAgICAgZ3BpbyA9IGt6YWxsb2Moc2l6 ZW9mKCpncGlvKSwgR0ZQX0tFUk5FTCk7Cj4+ICsgICAgICAgaWYgKCFncGlvKQo+PiArICAgICAg ICAgICAgICAgcmV0dXJuIEVSUl9QVFIoLUVOT01FTSk7Cj4+ICsKPj4gKyAgICAgICBncGlvLT5w YXJlbnQgPSBjb25maWctPnBhcmVudDsKPj4gKyAgICAgICBncGlvLT5yZWdtYXAgPSBjb25maWct PnJlZ21hcDsKPj4gKyAgICAgICBncGlvLT5uZ3Bpb19wZXJfcmVnID0gY29uZmlnLT5uZ3Bpb19w ZXJfcmVnOwo+PiArICAgICAgIGdwaW8tPnJlZ19zdHJpZGUgPSBjb25maWctPnJlZ19zdHJpZGU7 Cj4+ICsgICAgICAgZ3Bpby0+cmVnX21hc2tfeGxhdGUgPSBjb25maWctPnJlZ19tYXNrX3hsYXRl Owo+PiArICAgICAgIGdwaW8tPnJlZ19zZXRfYmFzZSA9IGNvbmZpZy0+cmVnX3NldF9iYXNlOwo+ PiArICAgICAgIGdwaW8tPnJlZ19jbHJfYmFzZSA9IGNvbmZpZy0+cmVnX2Nscl9iYXNlOwo+PiAr ICAgICAgIGdwaW8tPnJlZ19kaXJfaW5fYmFzZSA9IGNvbmZpZy0+cmVnX2Rpcl9pbl9iYXNlOwo+ PiArICAgICAgIGdwaW8tPnJlZ19kaXJfb3V0X2Jhc2UgPSBjb25maWctPnJlZ19kaXJfb3V0X2Jh c2U7Cj4+ICsKPj4gKyAgICAgICAvKiBpZiBub3Qgc2V0LCBhc3N1bWUgdGhlcmUgaXMgb25seSBv bmUgcmVnaXN0ZXIgKi8KPj4gKyAgICAgICBpZiAoIWdwaW8tPm5ncGlvX3Blcl9yZWcpCj4+ICsg ICAgICAgICAgICAgICBncGlvLT5uZ3Bpb19wZXJfcmVnID0gY29uZmlnLT5uZ3BpbzsKPj4gKwo+ PiArICAgICAgIC8qIGlmIG5vdCBzZXQsIGFzc3VtZSB0aGV5IGFyZSBjb25zZWN1dGl2ZSAqLwo+ PiArICAgICAgIGlmICghZ3Bpby0+cmVnX3N0cmlkZSkKPj4gKyAgICAgICAgICAgICAgIGdwaW8t PnJlZ19zdHJpZGUgPSAxOwo+PiArCj4+ICsgICAgICAgaWYgKCFncGlvLT5yZWdfbWFza194bGF0 ZSkKPj4gKyAgICAgICAgICAgICAgIGdwaW8tPnJlZ19tYXNrX3hsYXRlID0gZ3Bpb19yZWdtYXBf c2ltcGxlX3hsYXRlOwo+PiArCj4+ICsgICAgICAgY2hpcCA9ICZncGlvLT5ncGlvX2NoaXA7Cj4+ ICsgICAgICAgY2hpcC0+cGFyZW50ID0gY29uZmlnLT5wYXJlbnQ7Cj4+ICsgICAgICAgY2hpcC0+ YmFzZSA9IC0xOwo+PiArICAgICAgIGNoaXAtPm5ncGlvID0gY29uZmlnLT5uZ3BpbzsKPj4gKyAg ICAgICBjaGlwLT5jYW5fc2xlZXAgPSB0cnVlOwo+PiArCj4+ICsgICAgICAgaWYgKCFjaGlwLT5s YWJlbCkKPj4gKyAgICAgICAgICAgICAgIGNoaXAtPmxhYmVsID0gZGV2X25hbWUoY29uZmlnLT5w YXJlbnQpOwo+PiArICAgICAgIGVsc2UKPj4gKyAgICAgICAgICAgICAgIGNoaXAtPmxhYmVsID0g Y29uZmlnLT5sYWJlbDsKPj4gKwo+PiArICAgICAgIGNoaXAtPmdldCA9IGdwaW9fcmVnbWFwX2dl dDsKPj4gKyAgICAgICBpZiAoZ3Bpby0+cmVnX3NldF9iYXNlICYmIGdwaW8tPnJlZ19jbHJfYmFz ZSkKPj4gKyAgICAgICAgICAgICAgIGNoaXAtPnNldCA9IGdwaW9fcmVnbWFwX3NldF93aXRoX2Ns ZWFyOwo+PiArICAgICAgIGVsc2UgaWYgKGdwaW8tPnJlZ19zZXRfYmFzZSkKPj4gKyAgICAgICAg ICAgICAgIGNoaXAtPnNldCA9IGdwaW9fcmVnbWFwX3NldDsKPj4gKwo+PiArICAgICAgIGlmIChn cGlvLT5yZWdfZGlyX2luX2Jhc2UgfHwgZ3Bpby0+cmVnX2Rpcl9vdXRfYmFzZSkgewo+PiArICAg ICAgICAgICAgICAgY2hpcC0+Z2V0X2RpcmVjdGlvbiA9IGdwaW9fcmVnbWFwX2dldF9kaXJlY3Rp b247Cj4+ICsgICAgICAgICAgICAgICBjaGlwLT5kaXJlY3Rpb25faW5wdXQgPSBncGlvX3JlZ21h cF9kaXJlY3Rpb25faW5wdXQ7Cj4+ICsgICAgICAgICAgICAgICBjaGlwLT5kaXJlY3Rpb25fb3V0 cHV0ID0gZ3Bpb19yZWdtYXBfZGlyZWN0aW9uX291dHB1dDsKPj4gKyAgICAgICB9Cj4+ICsKPj4g KyAgICAgICByZXQgPSBncGlvY2hpcF9hZGRfZGF0YShjaGlwLCBncGlvKTsKPj4gKyAgICAgICBp ZiAocmV0IDwgMCkgewo+PiArICAgICAgICAgICAgICAga2ZyZWUoZ3Bpbyk7Cj4gCj4gTWF5YmUg YWRkIGEgc2Vjb25kIGxhYmVsIGF0IHRoZSBlbmQgb2YgdGhlIGZ1bmN0aW9uPwpzdXJlCgo+PiAr ICAgICAgICAgICAgICAgcmV0dXJuIEVSUl9QVFIocmV0KTsKPj4gKyAgICAgICB9Cj4+ICsKPj4g KyAgICAgICBpZiAoY29uZmlnLT5pcnFfZG9tYWluKSB7Cj4+ICsgICAgICAgICAgICAgICByZXQg PSBncGlvY2hpcF9pcnFjaGlwX2FkZF9kb21haW4oY2hpcCwgCj4+IGNvbmZpZy0+aXJxX2RvbWFp bik7Cj4+ICsgICAgICAgICAgICAgICBpZiAocmV0IDwgMCkKPj4gKyAgICAgICAgICAgICAgICAg ICAgICAgZ290byBlcnI7Cj4+ICsgICAgICAgfQo+PiArCj4+ICsgICAgICAgcmV0dXJuIGdwaW87 Cj4+ICsKPj4gK2VycjoKPj4gKyAgICAgICBncGlvY2hpcF9yZW1vdmUoY2hpcCk7Cj4+ICsgICAg ICAga2ZyZWUoZ3Bpbyk7Cj4+ICsgICAgICAgcmV0dXJuIEVSUl9QVFIocmV0KTsKPj4gK30KPj4g K0VYUE9SVF9TWU1CT0xfR1BMKGdwaW9fcmVnbWFwX3JlZ2lzdGVyKTsKPj4gKwo+PiArLyoqCj4+ ICsgKiBncGlvX3JlZ21hcF91bnJlZ2lzdGVyKCkgLSBVbnJlZ2lzdGVyIGEgZ2VuZXJpYyByZWdt YXAgR1BJTyAKPj4gY29udHJvbGxlcgo+PiArICoKPj4gKyAqIEBncGlvOiBncGlvX3JlZ21hcCBk ZXZpY2UgdG8gdW5yZWdpc3Rlcgo+PiArICovCj4+ICt2b2lkIGdwaW9fcmVnbWFwX3VucmVnaXN0 ZXIoc3RydWN0IGdwaW9fcmVnbWFwICpncGlvKQo+PiArewo+PiArICAgICAgIGdwaW9jaGlwX3Jl bW92ZSgmZ3Bpby0+Z3Bpb19jaGlwKTsKPj4gKyAgICAgICBrZnJlZShncGlvKTsKPj4gK30KPj4g K0VYUE9SVF9TWU1CT0xfR1BMKGdwaW9fcmVnbWFwX3VucmVnaXN0ZXIpOwo+PiArCj4+ICtzdGF0 aWMgdm9pZCBkZXZtX2dwaW9fcmVnbWFwX3VucmVnaXN0ZXIoc3RydWN0IGRldmljZSAqZGV2LCB2 b2lkIAo+PiAqcmVzKQo+PiArewo+PiArICAgICAgIGdwaW9fcmVnbWFwX3VucmVnaXN0ZXIoKihz dHJ1Y3QgZ3Bpb19yZWdtYXAgKiopcmVzKTsKPj4gK30KPj4gKwo+PiArLyoqCj4+ICsgKiBkZXZt X2dwaW9fcmVnbWFwX3JlZ2lzdGVyKCkgLSByZXNvdXJjZSBtYW5hZ2VkIAo+PiBncGlvX3JlZ21h cF9yZWdpc3RlcigpCj4+ICsgKgo+PiArICogQGRldjogZGV2aWNlIHRoYXQgaXMgcmVnaXN0ZXJp bmcgdGhpcyBHUElPIGRldmljZQo+PiArICogQGdwaW86IGdwaW9fcmVnbWFwIGRldmljZSB0byBy ZWdpc3Rlcgo+PiArICoKPj4gKyAqIE1hbmFnZWQgZ3Bpb19yZWdtYXBfcmVnaXN0ZXIoKS4gRm9y IGdlbmVyaWMgcmVnbWFwIEdQSU8gZGV2aWNlIAo+PiByZWdpc3RlcmVkIGJ5Cj4+ICsgKiB0aGlz IGZ1bmN0aW9uLCBncGlvX3JlZ21hcF91bnJlZ2lzdGVyKCkgaXMgYXV0b21hdGljYWxseSBjYWxs ZWQgb24gCj4+IGRyaXZlcgo+PiArICogZGV0YWNoLiBTZWUgZ3Bpb19yZWdtYXBfcmVnaXN0ZXIo KSBmb3IgbW9yZSBpbmZvcm1hdGlvbi4KPj4gKyAqLwo+PiArc3RydWN0IGdwaW9fcmVnbWFwICpk ZXZtX2dwaW9fcmVnbWFwX3JlZ2lzdGVyKHN0cnVjdCBkZXZpY2UgKmRldiwKPj4gKyAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0cnVjdCAKPj4gZ3Bp b19yZWdtYXBfY29uZmlnICpjb25maWcpCj4+ICt7Cj4+ICsgICAgICAgc3RydWN0IGdwaW9fcmVn bWFwICoqcHRyLCAqZ3BpbzsKPj4gKwo+PiArICAgICAgIHB0ciA9IGRldnJlc19hbGxvYyhkZXZt X2dwaW9fcmVnbWFwX3VucmVnaXN0ZXIsIHNpemVvZigqcHRyKSwKPj4gKyAgICAgICAgICAgICAg ICAgICAgICAgICAgR0ZQX0tFUk5FTCk7Cj4+ICsgICAgICAgaWYgKCFwdHIpCj4+ICsgICAgICAg ICAgICAgICByZXR1cm4gRVJSX1BUUigtRU5PTUVNKTsKPj4gKwo+PiArICAgICAgIGdwaW8gPSBn cGlvX3JlZ21hcF9yZWdpc3Rlcihjb25maWcpOwo+PiArCj4+ICsgICAgICAgaWYgKCFJU19FUlIo Z3BpbykpIHsKPj4gKyAgICAgICAgICAgICAgICpwdHIgPSBncGlvOwo+PiArICAgICAgICAgICAg ICAgZGV2cmVzX2FkZChkZXYsIHB0cik7Cj4+ICsgICAgICAgfSBlbHNlIHsKPj4gKyAgICAgICAg ICAgICAgIGRldnJlc19mcmVlKHB0cik7Cj4+ICsgICAgICAgfQo+PiArCj4+ICsgICAgICAgcmV0 dXJuIGdwaW87Cj4+ICt9Cj4+ICtFWFBPUlRfU1lNQk9MX0dQTChkZXZtX2dwaW9fcmVnbWFwX3Jl Z2lzdGVyKTsKPj4gKwo+PiArTU9EVUxFX0FVVEhPUigiTWljaGFlbCBXYWxsZSA8bWljaGFlbEB3 YWxsZS5jYz4iKTsKPj4gK01PRFVMRV9ERVNDUklQVElPTigiR1BJTyBnZW5lcmljIHJlZ21hcCBk cml2ZXIgY29yZSIpOwo+PiArTU9EVUxFX0xJQ0VOU0UoIkdQTCIpOwo+PiBkaWZmIC0tZ2l0IGEv aW5jbHVkZS9saW51eC9ncGlvLXJlZ21hcC5oIGIvaW5jbHVkZS9saW51eC9ncGlvLXJlZ21hcC5o Cj4+IG5ldyBmaWxlIG1vZGUgMTAwNjQ0Cj4+IGluZGV4IDAwMDAwMDAwMDAwMC4uYTg2OGNiY2Rl NmU5Cj4+IC0tLSAvZGV2L251bGwKPj4gKysrIGIvaW5jbHVkZS9saW51eC9ncGlvLXJlZ21hcC5o Cj4+IEBAIC0wLDAgKzEsNjkgQEAKPj4gKy8qIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBHUEwt Mi4wLW9ubHkgKi8KPj4gKwo+PiArI2lmbmRlZiBfTElOVVhfR1BJT19SRUdNQVBfSAo+PiArI2Rl ZmluZSBfTElOVVhfR1BJT19SRUdNQVBfSAo+PiArCj4+ICtzdHJ1Y3QgZ3Bpb19yZWdtYXA7Cj4+ ICsKPj4gKyNkZWZpbmUgR1BJT19SRUdNQVBfQUREUl9aRVJPICgodW5zaWduZWQgbG9uZykoLTEp KQo+PiArI2RlZmluZSBHUElPX1JFR01BUF9BRERSKGFkZHIpICgoYWRkcikgPyA6IEdQSU9fUkVH TUFQX0FERFJfWkVSTykKPj4gKwo+IAo+IFdoYXQgaWYgdGhlIGFkZHIgaXMgYWN0dWFsbHkgMD8K ClRoZW4gdGhlIGRyaXZlciBoYXMgdG8gc2V0IEdQSU9fUkVHTUFQX0FERFJfWkVSTyBvciB1c2Ug dGhlIGNvbnZlbmllbmNlCm1hY3JvIEdQSU9fUkVHTUFQX0FERFIuCgpTbyB5b3UgY2FuIGhhdmUK CiAgIHN0cnVjdCBncGlvX3JlZ21hcF9jb25maWcgY29uZmlnID0geyAwIH07CiAgIGNvbmZpZy5y ZWdfZGF0X2Jhc2UgPSAweDEwOwogICBjb25maWcucmVnX2Rpcl9vdXRfYmFzZSA9IDB4MjA7Cgpv cgoKICAgY29uZmlnLnJlZ19kYXRfYmFzZSA9IEdQSU9fUkVHTUFQX0FERFJfWkVSTzsKCm9yIGlm IHlvdSBjYW4ndCBiZSBzdXJlIGlmIHRoZSBSSFMgdmFsdWUgbWlnaHQgYmUgemVybzoKCiAgIGNv bmZpZy5yZWdfZGF0X2Jhc2UgPSBHUElPX1JFR01BUF9BRERSKHJlZyk7CgoKPiBNYXliZSBkcm9w IEdQSU9fUkVHTUFQX0FERFIgYW5kIHJlcXVpcmUgdXNlcnMgdG8gc2V0IHVudXNlZCByZWdpc3Rl cnMKPiB0byBHUElPX1JFR01BUF9BRERSX1pFUk8/CgpUaGF0cyBiYWQgYmVjYXVzZToKICAqIHlv dSdkIGhhdmUgdG8gc2V0IHBsZW50eSBvZiB1bnVzZWQgYmFzZSByZWdpc3RlcnMgZm9yIGEgc2lt cGxlIGRyaXZlcgogICogaWYgdGhlcmUgd2lsbCBiZSBhZGRpdGlvbmFsIHByb3BlcnRpZXMgaW4g dGhlIGZ1dHVyZSwgeW91IGhhdmUgdG8gCnRvdWNoCiAgICBhbGwgb3RoZXIgZHJpdmVycywgYmVj YXVzZSB0aGV5IGFyZSBpbml0aWFsaXplZCBhcyAwIChpZS4gdmFsaWQgcmVnIAowKS4KCj4+ICsv KioKPj4gKyAqIHN0cnVjdCBncGlvX3JlZ21hcF9jb25maWcgLSBEZXNjcmlwdGlvbiBvZiBhIGdl bmVyaWMgcmVnbWFwIAo+PiBncGlvX2NoaXAuCj4+ICsgKgo+PiArICogQHBhcmVudDogICAgICAg ICAgICBUaGUgcGFyZW50IGRldmljZQo+PiArICogQHJlZ21hcDogICAgICAgICAgICBUaGUgcmVn bWFwIHVzZWQgdG8gYWNjZXNzIHRoZSByZWdpc3RlcnMKPj4gKyAqICAgICAgICAgICAgICAgICAg ICAgZ2l2ZW4sIHRoZSBuYW1lIG9mIHRoZSBkZXZpY2UgaXMgdXNlZAo+PiArICogQGxhYmVsOiAg ICAgICAgICAgICAoT3B0aW9uYWwpIERlc2NyaXB0aXZlIG5hbWUgZm9yIEdQSU8gCj4+IGNvbnRy b2xsZXIuCj4+ICsgKiAgICAgICAgICAgICAgICAgICAgIElmIG5vdCBnaXZlbiwgdGhlIG5hbWUg b2YgdGhlIGRldmljZSBpcyB1c2VkLgo+PiArICogQG5ncGlvOiAgICAgICAgICAgICBOdW1iZXIg b2YgR1BJT3MKPj4gKyAqIEByZWdfZGF0X2Jhc2U6ICAgICAgKE9wdGlvbmFsKSAoaW4pIHJlZ2lz dGVyIGJhc2UgYWRkcmVzcwo+PiArICogQHJlZ19zZXRfYmFzZTogICAgICAoT3B0aW9uYWwpIHNl dCByZWdpc3RlciBiYXNlIGFkZHJlc3MKPj4gKyAqIEByZWdfY2xyX2Jhc2U6ICAgICAgKE9wdGlv bmFsKSBjbGVhciByZWdpc3RlciBiYXNlIGFkZHJlc3MKPj4gKyAqIEByZWdfZGlyX2luX2Jhc2U6 ICAgKE9wdGlvbmFsKSBvdXQgc2V0dGluZyByZWdpc3RlciBiYXNlIGFkZHJlc3MKPj4gKyAqIEBy ZWdfZGlyX291dF9iYXNlOiAgKE9wdGlvbmFsKSBpbiBzZXR0aW5nIHJlZ2lzdGVyIGJhc2UgYWRk cmVzcwo+IAo+IFRoZSB0d28gYWJvdmUgYXJlIGludmVydGVkIEkgdGhpbms/Cmdvb2QgY2F0Y2gu Cgo+IEFsc286IHdoeSB0aGUgbGltaXRhdGlvbiBvZiBvbmx5IHN1cHBvcnRpbmcgb25lIGF0IGEg dGltZT8KCnRoZXkgc2hvdWxkIGJlIGV4Y2x1c2l2ZSwgZWl0aGVyIHlvdSBoYXZlIGEgcmVnaXN0 ZXIgd2hlcmUgeW91IHNldCB0aGUKb3V0cHV0IGJpdHMgdG8gb25lLCBvciB0aGUgaW5wdXQgYml0 cy4gTWF5YmUgdGhpcyBuZWVkIGEgYml0IG1vcmUgCmNvbnRleHQKYWJvdmUuIGluIGdwaW8tbW1p by5jIHlvdSBjYW4gc2V0IGJvdGggYW5kIGJvdGggYXJlIHVzZWQgaW4Kc2V0X2RpcmVjdGlvbigp LCBidXQgb25seSBvbmUgaXMgcmVhZCBpbiBnZXRfZGlyZWN0aW9uKCkuCgpUaGF0IGJlaW5nIHNh aWQsIEkgaGF2ZSBubyBzdHJvbmcgb3BpbmlvbiB3ZXRoZXIgdGhleSBzaG91bGQgYmUgCmV4Y2x1 c2l2ZQpvciBub3QsIGJlc2lkZXMgdGhlIHN5bW1ldHJ5IG9mIHNldF8vZ2V0X2RpcmVjdGlvbigp LgoKLW1pY2hhZWwKCj4gCj4+ICsgKiBAcmVnX3N0cmlkZTogICAgICAgICAgICAgICAgKE9wdGlv bmFsKSBNYXkgYmUgc2V0IGlmIHRoZSByZWdpc3RlcnMgCj4+IChvZiB0aGUKPj4gKyAqICAgICAg ICAgICAgICAgICAgICAgc2FtZSB0eXBlLCBkYXQsIHNldCwgZXRjKSBhcmUgbm90IGNvbnNlY3V0 aXZlLgo+PiArICogQG5ncGlvX3Blcl9yZWc6ICAgICBOdW1iZXIgb2YgR1BJT3MgcGVyIHJlZ2lz dGVyCj4+ICsgKiBAaXJxX2RvbWFpbjogICAgICAgICAgICAgICAgKE9wdGlvbmFsKSBJUlEgZG9t YWluIGlmIHRoZSAKPj4gY29udHJvbGxlciBpcwo+PiArICogICAgICAgICAgICAgICAgICAgICBp bnRlcnJ1cHQtY2FwYWJsZQo+PiArICogQHJlZ19tYXNrX3hsYXRlOiAgICAgKE9wdGlvbmFsKSBU cmFuc2xhdGVzIGJhc2UgYWRkcmVzcyBhbmQgR1BJTwo+PiArICogICAgICAgICAgICAgICAgICAg ICBvZmZzZXQgdG8gYSByZWdpc3Rlci9iaXRtYXNrIHBhaXIuIElmIG5vdAo+PiArICogICAgICAg ICAgICAgICAgICAgICBnaXZlbiB0aGUgZGVmYXVsdCBncGlvX3JlZ21hcF9zaW1wbGVfeGxhdGUo KQo+PiArICogICAgICAgICAgICAgICAgICAgICBpcyB1c2VkLgo+PiArICoKPj4gKyAqIFRoZSBy ZWdfbWFza194bGF0ZSB0cmFuc2xhdGVzIGEgZ2l2ZW4gYmFzZSBhZGRyZXNzIGFuZCBHUElPIG9m ZnNldCAKPj4gdG8KPj4gKyAqIHJlZ2lzdGVyIGFuZCBtYXNrIHBhaXIuIFRoZSBiYXNlIGFkZHJl c3MgaXMgb25lIG9mIHRoZSBnaXZlbiAKPj4gcmVnXypfYmFzZS4KPj4gKyAqCj4+ICsgKiBBbGwg YmFzZSBhZGRyZXNzZXMgbWF5IGhhdmUgdGhlIHNwZWNpYWwgdmFsdWUgCj4+IEdQSU9fUkVHTUFQ X0FERFJfWkVSTwo+PiArICogd2hpY2ggZm9yY2VzIHRoZSBhZGRyZXNzIHRvIHRoZSB2YWx1ZSAw Lgo+PiArICovCj4+ICtzdHJ1Y3QgZ3Bpb19yZWdtYXBfY29uZmlnIHsKPj4gKyAgICAgICBzdHJ1 Y3QgZGV2aWNlICpwYXJlbnQ7Cj4+ICsgICAgICAgc3RydWN0IHJlZ21hcCAqcmVnbWFwOwo+PiAr Cj4+ICsgICAgICAgY29uc3QgY2hhciAqbGFiZWw7Cj4+ICsgICAgICAgaW50IG5ncGlvOwo+PiAr Cj4+ICsgICAgICAgdW5zaWduZWQgaW50IHJlZ19kYXRfYmFzZTsKPj4gKyAgICAgICB1bnNpZ25l ZCBpbnQgcmVnX3NldF9iYXNlOwo+PiArICAgICAgIHVuc2lnbmVkIGludCByZWdfY2xyX2Jhc2U7 Cj4+ICsgICAgICAgdW5zaWduZWQgaW50IHJlZ19kaXJfaW5fYmFzZTsKPj4gKyAgICAgICB1bnNp Z25lZCBpbnQgcmVnX2Rpcl9vdXRfYmFzZTsKPj4gKyAgICAgICBpbnQgcmVnX3N0cmlkZTsKPj4g KyAgICAgICBpbnQgbmdwaW9fcGVyX3JlZzsKPj4gKyAgICAgICBzdHJ1Y3QgaXJxX2RvbWFpbiAq aXJxX2RvbWFpbjsKPj4gKwo+PiArICAgICAgIGludCAoKnJlZ19tYXNrX3hsYXRlKShzdHJ1Y3Qg Z3Bpb19yZWdtYXAgKmdwaW8sIHVuc2lnbmVkIGludCAKPj4gYmFzZSwKPj4gKyAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgdW5zaWduZWQgaW50IG9mZnNldCwgdW5zaWduZWQgaW50ICpyZWcs Cj4+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuc2lnbmVkIGludCAqbWFzayk7Cj4+ ICt9Owo+PiArCj4+ICtzdHJ1Y3QgZ3Bpb19yZWdtYXAgKmdwaW9fcmVnbWFwX3JlZ2lzdGVyKGNv bnN0IHN0cnVjdCAKPj4gZ3Bpb19yZWdtYXBfY29uZmlnICpjb25maWcpOwo+PiArdm9pZCBncGlv X3JlZ21hcF91bnJlZ2lzdGVyKHN0cnVjdCBncGlvX3JlZ21hcCAqZ3Bpbyk7Cj4+ICtzdHJ1Y3Qg Z3Bpb19yZWdtYXAgKmRldm1fZ3Bpb19yZWdtYXBfcmVnaXN0ZXIoc3RydWN0IGRldmljZSAqZGV2 LAo+PiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qg c3RydWN0IAo+PiBncGlvX3JlZ21hcF9jb25maWcgKmNvbmZpZyk7Cj4+ICt2b2lkIGdwaW9fcmVn bWFwX3NldF9kcnZkYXRhKHN0cnVjdCBncGlvX3JlZ21hcCAqZ3Bpbywgdm9pZCAqZGF0YSk7Cj4+ ICt2b2lkICpncGlvX3JlZ21hcF9nZXRfZHJ2ZGF0YShzdHJ1Y3QgZ3Bpb19yZWdtYXAgKmdwaW8p Owo+PiArCj4+ICsjZW5kaWYgLyogX0xJTlVYX0dQSU9fUkVHTUFQX0ggKi8KPj4gLS0KPj4gMi4y MC4xCj4+IAoKX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18K bGludXgtYXJtLWtlcm5lbCBtYWlsaW5nIGxpc3QKbGludXgtYXJtLWtlcm5lbEBsaXN0cy5pbmZy YWRlYWQub3JnCmh0dHA6Ly9saXN0cy5pbmZyYWRlYWQub3JnL21haWxtYW4vbGlzdGluZm8vbGlu dXgtYXJtLWtlcm5lbAo=