From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Krzysztof Kozlowski To: Kukjin Kim , Krzysztof Kozlowski , Rob Herring , Mark Rutland , Tejun Heo , Sylwester Nawrocki , Tomasz Figa , Chanwoo Choi , Michael Turquette , Stephen Boyd , "Rafael J. Wysocki" , Viresh Kumar , Zhang Rui , Eduardo Valentin , Russell King , Hans de Goede , Linus Walleij , Andi Shyti , Mark Brown , Bartlomiej Zolnierkiewicz , Alan Stern , Greg Kroah-Hartman , linux-arm-kernel@lists.infradead.org, linux-samsung-soc@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-ide@vger.kernel.org, linux-clk@vger.kernel.org, linux-pm@vger.kernel.org, linux-i2c@vger.kernel.org, linux-gpio@vger.kernel.org, linux-spi@vger.kernel.org, linux-usb@vger.kernel.org Cc: Marek Szyprowski , Arnd Bergmann , Olof Johansson , Jaehoon Chung Subject: [RFC 07/10] pinctrl: samsung: Remove support for Exynos5440 Date: Tue, 24 Apr 2018 22:32:36 +0200 Message-Id: <20180424203239.21885-8-krzk@kernel.org> In-Reply-To: <20180424203239.21885-1-krzk@kernel.org> References: <20180424203239.21885-1-krzk@kernel.org> List-ID: The Exynos5440 is not actively developed, there are no development boards available and probably there are no real products with it. Remove wide-tree support for Exynos5440. Signed-off-by: Krzysztof Kozlowski --- drivers/pinctrl/samsung/Kconfig | 10 +- drivers/pinctrl/samsung/Makefile | 1 - drivers/pinctrl/samsung/pinctrl-exynos5440.c | 1005 -------------------------- 3 files changed, 2 insertions(+), 1014 deletions(-) delete mode 100644 drivers/pinctrl/samsung/pinctrl-exynos5440.c diff --git a/drivers/pinctrl/samsung/Kconfig b/drivers/pinctrl/samsung/Kconfig index 11b5eeb14c4a..425fadd6c346 100644 --- a/drivers/pinctrl/samsung/Kconfig +++ b/drivers/pinctrl/samsung/Kconfig @@ -8,26 +8,20 @@ config PINCTRL_SAMSUNG select PINCONF config PINCTRL_EXYNOS - bool "Pinctrl driver data for Samsung EXYNOS SoCs other than 5440" + bool "Pinctrl driver data for Samsung EXYNOS SoCs" depends on OF && GPIOLIB && (ARCH_EXYNOS || ARCH_S5PV210) select PINCTRL_SAMSUNG select PINCTRL_EXYNOS_ARM if ARM && (ARCH_EXYNOS || ARCH_S5PV210) select PINCTRL_EXYNOS_ARM64 if ARM64 && ARCH_EXYNOS config PINCTRL_EXYNOS_ARM - bool "ARMv7-specific pinctrl driver data for Exynos (except Exynos5440)" if COMPILE_TEST + bool "ARMv7-specific pinctrl driver data for Exynos" if COMPILE_TEST depends on PINCTRL_EXYNOS config PINCTRL_EXYNOS_ARM64 bool "ARMv8-specific pinctrl driver data for Exynos" if COMPILE_TEST depends on PINCTRL_EXYNOS -config PINCTRL_EXYNOS5440 - bool "Samsung EXYNOS5440 SoC pinctrl driver" - depends on SOC_EXYNOS5440 - select PINMUX - select PINCONF - config PINCTRL_S3C24XX bool "Samsung S3C24XX SoC pinctrl driver" depends on ARCH_S3C24XX && OF diff --git a/drivers/pinctrl/samsung/Makefile b/drivers/pinctrl/samsung/Makefile index df426561d067..ed951df6a112 100644 --- a/drivers/pinctrl/samsung/Makefile +++ b/drivers/pinctrl/samsung/Makefile @@ -5,6 +5,5 @@ obj-$(CONFIG_PINCTRL_SAMSUNG) += pinctrl-samsung.o obj-$(CONFIG_PINCTRL_EXYNOS) += pinctrl-exynos.o obj-$(CONFIG_PINCTRL_EXYNOS_ARM) += pinctrl-exynos-arm.o obj-$(CONFIG_PINCTRL_EXYNOS_ARM64) += pinctrl-exynos-arm64.o -obj-$(CONFIG_PINCTRL_EXYNOS5440) += pinctrl-exynos5440.o obj-$(CONFIG_PINCTRL_S3C24XX) += pinctrl-s3c24xx.o obj-$(CONFIG_PINCTRL_S3C64XX) += pinctrl-s3c64xx.o diff --git a/drivers/pinctrl/samsung/pinctrl-exynos5440.c b/drivers/pinctrl/samsung/pinctrl-exynos5440.c deleted file mode 100644 index 3d8d5e812839..000000000000 --- a/drivers/pinctrl/samsung/pinctrl-exynos5440.c +++ /dev/null @@ -1,1005 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -// -// pin-controller/pin-mux/pin-config/gpio-driver for Samsung's EXYNOS5440 SoC. -// -// Author: Thomas Abraham -// -// Copyright (c) 2012 Samsung Electronics Co., Ltd. -// http://www.samsung.com - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../core.h" - -/* EXYNOS5440 GPIO and Pinctrl register offsets */ -#define GPIO_MUX 0x00 -#define GPIO_IE 0x04 -#define GPIO_INT 0x08 -#define GPIO_TYPE 0x0C -#define GPIO_VAL 0x10 -#define GPIO_OE 0x14 -#define GPIO_IN 0x18 -#define GPIO_PE 0x1C -#define GPIO_PS 0x20 -#define GPIO_SR 0x24 -#define GPIO_DS0 0x28 -#define GPIO_DS1 0x2C - -#define EXYNOS5440_MAX_PINS 23 -#define EXYNOS5440_MAX_GPIO_INT 8 -#define PIN_NAME_LENGTH 10 - -#define GROUP_SUFFIX "-grp" -#define FUNCTION_SUFFIX "-mux" - -/* - * pin configuration type and its value are packed together into a 16-bits. - * The upper 8-bits represent the configuration type and the lower 8-bits - * hold the value of the configuration type. - */ -#define PINCFG_TYPE_MASK 0xFF -#define PINCFG_VALUE_SHIFT 8 -#define PINCFG_VALUE_MASK (0xFF << PINCFG_VALUE_SHIFT) -#define PINCFG_PACK(type, value) (((value) << PINCFG_VALUE_SHIFT) | type) -#define PINCFG_UNPACK_TYPE(cfg) ((cfg) & PINCFG_TYPE_MASK) -#define PINCFG_UNPACK_VALUE(cfg) (((cfg) & PINCFG_VALUE_MASK) >> \ - PINCFG_VALUE_SHIFT) - -/** - * enum pincfg_type - possible pin configuration types supported. - * @PINCFG_TYPE_PUD: Pull up/down configuration. - * @PINCFG_TYPE_DRV: Drive strength configuration. - * @PINCFG_TYPE_SKEW_RATE: Skew rate configuration. - * @PINCFG_TYPE_INPUT_TYPE: Pin input type configuration. - */ -enum pincfg_type { - PINCFG_TYPE_PUD, - PINCFG_TYPE_DRV, - PINCFG_TYPE_SKEW_RATE, - PINCFG_TYPE_INPUT_TYPE -}; - -/** - * struct exynos5440_pin_group: represent group of pins for pincfg setting. - * @name: name of the pin group, used to lookup the group. - * @pins: the pins included in this group. - * @num_pins: number of pins included in this group. - */ -struct exynos5440_pin_group { - const char *name; - const unsigned int *pins; - u8 num_pins; -}; - -/** - * struct exynos5440_pmx_func: represent a pin function. - * @name: name of the pin function, used to lookup the function. - * @groups: one or more names of pin groups that provide this function. - * @num_groups: number of groups included in @groups. - * @function: the function number to be programmed when selected. - */ -struct exynos5440_pmx_func { - const char *name; - const char **groups; - u8 num_groups; - unsigned long function; -}; - -/** - * struct exynos5440_pinctrl_priv_data: driver's private runtime data. - * @reg_base: ioremapped based address of the register space. - * @gc: gpio chip registered with gpiolib. - * @pin_groups: list of pin groups parsed from device tree. - * @nr_groups: number of pin groups available. - * @pmx_functions: list of pin functions parsed from device tree. - * @nr_functions: number of pin functions available. - * @range: gpio range to register with pinctrl - */ -struct exynos5440_pinctrl_priv_data { - void __iomem *reg_base; - struct gpio_chip *gc; - struct irq_domain *irq_domain; - - const struct exynos5440_pin_group *pin_groups; - unsigned int nr_groups; - const struct exynos5440_pmx_func *pmx_functions; - unsigned int nr_functions; - struct pinctrl_gpio_range range; -}; - -/** - * struct exynos5440_gpio_intr_data: private data for gpio interrupts. - * @priv: driver's private runtime data. - * @gpio_int: gpio interrupt number. - */ -struct exynos5440_gpio_intr_data { - struct exynos5440_pinctrl_priv_data *priv; - unsigned int gpio_int; -}; - -/* list of all possible config options supported */ -static struct pin_config { - char *prop_cfg; - unsigned int cfg_type; -} pcfgs[] = { - { "samsung,exynos5440-pin-pud", PINCFG_TYPE_PUD }, - { "samsung,exynos5440-pin-drv", PINCFG_TYPE_DRV }, - { "samsung,exynos5440-pin-skew-rate", PINCFG_TYPE_SKEW_RATE }, - { "samsung,exynos5440-pin-input-type", PINCFG_TYPE_INPUT_TYPE }, -}; - -/* check if the selector is a valid pin group selector */ -static int exynos5440_get_group_count(struct pinctrl_dev *pctldev) -{ - struct exynos5440_pinctrl_priv_data *priv; - - priv = pinctrl_dev_get_drvdata(pctldev); - return priv->nr_groups; -} - -/* return the name of the group selected by the group selector */ -static const char *exynos5440_get_group_name(struct pinctrl_dev *pctldev, - unsigned selector) -{ - struct exynos5440_pinctrl_priv_data *priv; - - priv = pinctrl_dev_get_drvdata(pctldev); - return priv->pin_groups[selector].name; -} - -/* return the pin numbers associated with the specified group */ -static int exynos5440_get_group_pins(struct pinctrl_dev *pctldev, - unsigned selector, const unsigned **pins, unsigned *num_pins) -{ - struct exynos5440_pinctrl_priv_data *priv; - - priv = pinctrl_dev_get_drvdata(pctldev); - *pins = priv->pin_groups[selector].pins; - *num_pins = priv->pin_groups[selector].num_pins; - return 0; -} - -/* create pinctrl_map entries by parsing device tree nodes */ -static int exynos5440_dt_node_to_map(struct pinctrl_dev *pctldev, - struct device_node *np, struct pinctrl_map **maps, - unsigned *nmaps) -{ - struct device *dev = pctldev->dev; - struct pinctrl_map *map; - unsigned long *cfg = NULL; - char *gname, *fname; - int cfg_cnt = 0, map_cnt = 0, idx = 0; - - /* count the number of config options specfied in the node */ - for (idx = 0; idx < ARRAY_SIZE(pcfgs); idx++) - if (of_find_property(np, pcfgs[idx].prop_cfg, NULL)) - cfg_cnt++; - - /* - * Find out the number of map entries to create. All the config options - * can be accomadated into a single config map entry. - */ - if (cfg_cnt) - map_cnt = 1; - if (of_find_property(np, "samsung,exynos5440-pin-function", NULL)) - map_cnt++; - if (!map_cnt) { - dev_err(dev, "node %s does not have either config or function " - "configurations\n", np->name); - return -EINVAL; - } - - /* Allocate memory for pin-map entries */ - map = kzalloc(sizeof(*map) * map_cnt, GFP_KERNEL); - if (!map) - return -ENOMEM; - *nmaps = 0; - - /* - * Allocate memory for pin group name. The pin group name is derived - * from the node name from which these map entries are be created. - */ - gname = kasprintf(GFP_KERNEL, "%s%s", np->name, GROUP_SUFFIX); - if (!gname) - goto free_map; - - /* - * don't have config options? then skip over to creating function - * map entries. - */ - if (!cfg_cnt) - goto skip_cfgs; - - /* Allocate memory for config entries */ - cfg = kzalloc(sizeof(*cfg) * cfg_cnt, GFP_KERNEL); - if (!cfg) - goto free_gname; - - /* Prepare a list of config settings */ - for (idx = 0, cfg_cnt = 0; idx < ARRAY_SIZE(pcfgs); idx++) { - u32 value; - if (!of_property_read_u32(np, pcfgs[idx].prop_cfg, &value)) - cfg[cfg_cnt++] = - PINCFG_PACK(pcfgs[idx].cfg_type, value); - } - - /* create the config map entry */ - map[*nmaps].data.configs.group_or_pin = gname; - map[*nmaps].data.configs.configs = cfg; - map[*nmaps].data.configs.num_configs = cfg_cnt; - map[*nmaps].type = PIN_MAP_TYPE_CONFIGS_GROUP; - *nmaps += 1; - -skip_cfgs: - /* create the function map entry */ - if (of_find_property(np, "samsung,exynos5440-pin-function", NULL)) { - fname = kasprintf(GFP_KERNEL, - "%s%s", np->name, FUNCTION_SUFFIX); - if (!fname) - goto free_cfg; - - map[*nmaps].data.mux.group = gname; - map[*nmaps].data.mux.function = fname; - map[*nmaps].type = PIN_MAP_TYPE_MUX_GROUP; - *nmaps += 1; - } - - *maps = map; - return 0; - -free_cfg: - kfree(cfg); -free_gname: - kfree(gname); -free_map: - kfree(map); - return -ENOMEM; -} - -/* free the memory allocated to hold the pin-map table */ -static void exynos5440_dt_free_map(struct pinctrl_dev *pctldev, - struct pinctrl_map *map, unsigned num_maps) -{ - int idx; - - for (idx = 0; idx < num_maps; idx++) { - if (map[idx].type == PIN_MAP_TYPE_MUX_GROUP) { - kfree(map[idx].data.mux.function); - if (!idx) - kfree(map[idx].data.mux.group); - } else if (map->type == PIN_MAP_TYPE_CONFIGS_GROUP) { - kfree(map[idx].data.configs.configs); - if (!idx) - kfree(map[idx].data.configs.group_or_pin); - } - } - - kfree(map); -} - -/* list of pinctrl callbacks for the pinctrl core */ -static const struct pinctrl_ops exynos5440_pctrl_ops = { - .get_groups_count = exynos5440_get_group_count, - .get_group_name = exynos5440_get_group_name, - .get_group_pins = exynos5440_get_group_pins, - .dt_node_to_map = exynos5440_dt_node_to_map, - .dt_free_map = exynos5440_dt_free_map, -}; - -/* check if the selector is a valid pin function selector */ -static int exynos5440_get_functions_count(struct pinctrl_dev *pctldev) -{ - struct exynos5440_pinctrl_priv_data *priv; - - priv = pinctrl_dev_get_drvdata(pctldev); - return priv->nr_functions; -} - -/* return the name of the pin function specified */ -static const char *exynos5440_pinmux_get_fname(struct pinctrl_dev *pctldev, - unsigned selector) -{ - struct exynos5440_pinctrl_priv_data *priv; - - priv = pinctrl_dev_get_drvdata(pctldev); - return priv->pmx_functions[selector].name; -} - -/* return the groups associated for the specified function selector */ -static int exynos5440_pinmux_get_groups(struct pinctrl_dev *pctldev, - unsigned selector, const char * const **groups, - unsigned * const num_groups) -{ - struct exynos5440_pinctrl_priv_data *priv; - - priv = pinctrl_dev_get_drvdata(pctldev); - *groups = priv->pmx_functions[selector].groups; - *num_groups = priv->pmx_functions[selector].num_groups; - return 0; -} - -/* enable or disable a pinmux function */ -static void exynos5440_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector, - unsigned group, bool enable) -{ - struct exynos5440_pinctrl_priv_data *priv; - void __iomem *base; - u32 function; - u32 data; - - priv = pinctrl_dev_get_drvdata(pctldev); - base = priv->reg_base; - function = priv->pmx_functions[selector].function; - - data = readl(base + GPIO_MUX); - if (enable) - data |= (1 << function); - else - data &= ~(1 << function); - writel(data, base + GPIO_MUX); -} - -/* enable a specified pinmux by writing to registers */ -static int exynos5440_pinmux_set_mux(struct pinctrl_dev *pctldev, - unsigned selector, - unsigned group) -{ - exynos5440_pinmux_setup(pctldev, selector, group, true); - return 0; -} - -/* - * The calls to gpio_direction_output() and gpio_direction_input() - * leads to this function call (via the pinctrl_gpio_direction_{input|output}() - * function called from the gpiolib interface). - */ -static int exynos5440_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev, - struct pinctrl_gpio_range *range, unsigned offset, bool input) -{ - return 0; -} - -/* list of pinmux callbacks for the pinmux vertical in pinctrl core */ -static const struct pinmux_ops exynos5440_pinmux_ops = { - .get_functions_count = exynos5440_get_functions_count, - .get_function_name = exynos5440_pinmux_get_fname, - .get_function_groups = exynos5440_pinmux_get_groups, - .set_mux = exynos5440_pinmux_set_mux, - .gpio_set_direction = exynos5440_pinmux_gpio_set_direction, -}; - -/* set the pin config settings for a specified pin */ -static int exynos5440_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, - unsigned long *configs, - unsigned num_configs) -{ - struct exynos5440_pinctrl_priv_data *priv; - void __iomem *base; - enum pincfg_type cfg_type; - u32 cfg_value; - u32 data; - int i; - - priv = pinctrl_dev_get_drvdata(pctldev); - base = priv->reg_base; - - for (i = 0; i < num_configs; i++) { - cfg_type = PINCFG_UNPACK_TYPE(configs[i]); - cfg_value = PINCFG_UNPACK_VALUE(configs[i]); - - switch (cfg_type) { - case PINCFG_TYPE_PUD: - /* first set pull enable/disable bit */ - data = readl(base + GPIO_PE); - data &= ~(1 << pin); - if (cfg_value) - data |= (1 << pin); - writel(data, base + GPIO_PE); - - /* then set pull up/down bit */ - data = readl(base + GPIO_PS); - data &= ~(1 << pin); - if (cfg_value == 2) - data |= (1 << pin); - writel(data, base + GPIO_PS); - break; - - case PINCFG_TYPE_DRV: - /* set the first bit of the drive strength */ - data = readl(base + GPIO_DS0); - data &= ~(1 << pin); - data |= ((cfg_value & 1) << pin); - writel(data, base + GPIO_DS0); - cfg_value >>= 1; - - /* set the second bit of the driver strength */ - data = readl(base + GPIO_DS1); - data &= ~(1 << pin); - data |= ((cfg_value & 1) << pin); - writel(data, base + GPIO_DS1); - break; - case PINCFG_TYPE_SKEW_RATE: - data = readl(base + GPIO_SR); - data &= ~(1 << pin); - data |= ((cfg_value & 1) << pin); - writel(data, base + GPIO_SR); - break; - case PINCFG_TYPE_INPUT_TYPE: - data = readl(base + GPIO_TYPE); - data &= ~(1 << pin); - data |= ((cfg_value & 1) << pin); - writel(data, base + GPIO_TYPE); - break; - default: - WARN_ON(1); - return -EINVAL; - } - } /* for each config */ - - return 0; -} - -/* get the pin config settings for a specified pin */ -static int exynos5440_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin, - unsigned long *config) -{ - struct exynos5440_pinctrl_priv_data *priv; - void __iomem *base; - enum pincfg_type cfg_type = PINCFG_UNPACK_TYPE(*config); - u32 data; - - priv = pinctrl_dev_get_drvdata(pctldev); - base = priv->reg_base; - - switch (cfg_type) { - case PINCFG_TYPE_PUD: - data = readl(base + GPIO_PE); - data = (data >> pin) & 1; - if (!data) - *config = 0; - else - *config = ((readl(base + GPIO_PS) >> pin) & 1) + 1; - break; - case PINCFG_TYPE_DRV: - data = readl(base + GPIO_DS0); - data = (data >> pin) & 1; - *config = data; - data = readl(base + GPIO_DS1); - data = (data >> pin) & 1; - *config |= (data << 1); - break; - case PINCFG_TYPE_SKEW_RATE: - data = readl(base + GPIO_SR); - *config = (data >> pin) & 1; - break; - case PINCFG_TYPE_INPUT_TYPE: - data = readl(base + GPIO_TYPE); - *config = (data >> pin) & 1; - break; - default: - WARN_ON(1); - return -EINVAL; - } - - return 0; -} - -/* set the pin config settings for a specified pin group */ -static int exynos5440_pinconf_group_set(struct pinctrl_dev *pctldev, - unsigned group, unsigned long *configs, - unsigned num_configs) -{ - struct exynos5440_pinctrl_priv_data *priv; - const unsigned int *pins; - unsigned int cnt; - - priv = pinctrl_dev_get_drvdata(pctldev); - pins = priv->pin_groups[group].pins; - - for (cnt = 0; cnt < priv->pin_groups[group].num_pins; cnt++) - exynos5440_pinconf_set(pctldev, pins[cnt], configs, - num_configs); - - return 0; -} - -/* get the pin config settings for a specified pin group */ -static int exynos5440_pinconf_group_get(struct pinctrl_dev *pctldev, - unsigned int group, unsigned long *config) -{ - struct exynos5440_pinctrl_priv_data *priv; - const unsigned int *pins; - - priv = pinctrl_dev_get_drvdata(pctldev); - pins = priv->pin_groups[group].pins; - exynos5440_pinconf_get(pctldev, pins[0], config); - return 0; -} - -/* list of pinconfig callbacks for pinconfig vertical in the pinctrl code */ -static const struct pinconf_ops exynos5440_pinconf_ops = { - .pin_config_get = exynos5440_pinconf_get, - .pin_config_set = exynos5440_pinconf_set, - .pin_config_group_get = exynos5440_pinconf_group_get, - .pin_config_group_set = exynos5440_pinconf_group_set, -}; - -/* gpiolib gpio_set callback function */ -static void exynos5440_gpio_set(struct gpio_chip *gc, unsigned offset, int value) -{ - struct exynos5440_pinctrl_priv_data *priv = gpiochip_get_data(gc); - void __iomem *base = priv->reg_base; - u32 data; - - data = readl(base + GPIO_VAL); - data &= ~(1 << offset); - if (value) - data |= 1 << offset; - writel(data, base + GPIO_VAL); -} - -/* gpiolib gpio_get callback function */ -static int exynos5440_gpio_get(struct gpio_chip *gc, unsigned offset) -{ - struct exynos5440_pinctrl_priv_data *priv = gpiochip_get_data(gc); - void __iomem *base = priv->reg_base; - u32 data; - - data = readl(base + GPIO_IN); - data >>= offset; - data &= 1; - return data; -} - -/* gpiolib gpio_direction_input callback function */ -static int exynos5440_gpio_direction_input(struct gpio_chip *gc, unsigned offset) -{ - struct exynos5440_pinctrl_priv_data *priv = gpiochip_get_data(gc); - void __iomem *base = priv->reg_base; - u32 data; - - /* first disable the data output enable on this pin */ - data = readl(base + GPIO_OE); - data &= ~(1 << offset); - writel(data, base + GPIO_OE); - - /* now enable input on this pin */ - data = readl(base + GPIO_IE); - data |= 1 << offset; - writel(data, base + GPIO_IE); - return 0; -} - -/* gpiolib gpio_direction_output callback function */ -static int exynos5440_gpio_direction_output(struct gpio_chip *gc, unsigned offset, - int value) -{ - struct exynos5440_pinctrl_priv_data *priv = gpiochip_get_data(gc); - void __iomem *base = priv->reg_base; - u32 data; - - exynos5440_gpio_set(gc, offset, value); - - /* first disable the data input enable on this pin */ - data = readl(base + GPIO_IE); - data &= ~(1 << offset); - writel(data, base + GPIO_IE); - - /* now enable output on this pin */ - data = readl(base + GPIO_OE); - data |= 1 << offset; - writel(data, base + GPIO_OE); - return 0; -} - -/* gpiolib gpio_to_irq callback function */ -static int exynos5440_gpio_to_irq(struct gpio_chip *gc, unsigned offset) -{ - struct exynos5440_pinctrl_priv_data *priv = gpiochip_get_data(gc); - unsigned int virq; - - if (offset < 16 || offset > 23) - return -ENXIO; - - if (!priv->irq_domain) - return -ENXIO; - - virq = irq_create_mapping(priv->irq_domain, offset - 16); - return virq ? : -ENXIO; -} - -/* parse the pin numbers listed in the 'samsung,exynos5440-pins' property */ -static int exynos5440_pinctrl_parse_dt_pins(struct platform_device *pdev, - struct device_node *cfg_np, unsigned int **pin_list, - unsigned int *npins) -{ - struct device *dev = &pdev->dev; - struct property *prop; - - prop = of_find_property(cfg_np, "samsung,exynos5440-pins", NULL); - if (!prop) - return -ENOENT; - - *npins = prop->length / sizeof(unsigned long); - if (!*npins) { - dev_err(dev, "invalid pin list in %s node", cfg_np->name); - return -EINVAL; - } - - *pin_list = devm_kzalloc(dev, *npins * sizeof(**pin_list), GFP_KERNEL); - if (!*pin_list) - return -ENOMEM; - - return of_property_read_u32_array(cfg_np, "samsung,exynos5440-pins", - *pin_list, *npins); -} - -/* - * Parse the information about all the available pin groups and pin functions - * from device node of the pin-controller. - */ -static int exynos5440_pinctrl_parse_dt(struct platform_device *pdev, - struct exynos5440_pinctrl_priv_data *priv) -{ - struct device *dev = &pdev->dev; - struct device_node *dev_np = dev->of_node; - struct device_node *cfg_np; - struct exynos5440_pin_group *groups, *grp; - struct exynos5440_pmx_func *functions, *func; - unsigned *pin_list; - unsigned int npins, grp_cnt, func_idx = 0; - char *gname, *fname; - int ret; - - grp_cnt = of_get_child_count(dev_np); - if (!grp_cnt) - return -EINVAL; - - groups = devm_kzalloc(dev, grp_cnt * sizeof(*groups), GFP_KERNEL); - if (!groups) - return -EINVAL; - - grp = groups; - - functions = devm_kzalloc(dev, grp_cnt * sizeof(*functions), GFP_KERNEL); - if (!functions) - return -EINVAL; - - func = functions; - - /* - * Iterate over all the child nodes of the pin controller node - * and create pin groups and pin function lists. - */ - for_each_child_of_node(dev_np, cfg_np) { - u32 function; - - ret = exynos5440_pinctrl_parse_dt_pins(pdev, cfg_np, - &pin_list, &npins); - if (ret) { - gname = NULL; - goto skip_to_pin_function; - } - - /* derive pin group name from the node name */ - gname = devm_kasprintf(dev, GFP_KERNEL, - "%s%s", cfg_np->name, GROUP_SUFFIX); - if (!gname) - return -ENOMEM; - - grp->name = gname; - grp->pins = pin_list; - grp->num_pins = npins; - grp++; - -skip_to_pin_function: - ret = of_property_read_u32(cfg_np, "samsung,exynos5440-pin-function", - &function); - if (ret) - continue; - - /* derive function name from the node name */ - fname = devm_kasprintf(dev, GFP_KERNEL, - "%s%s", cfg_np->name, FUNCTION_SUFFIX); - if (!fname) - return -ENOMEM; - - func->name = fname; - func->groups = devm_kzalloc(dev, sizeof(char *), GFP_KERNEL); - if (!func->groups) - return -ENOMEM; - func->groups[0] = gname; - func->num_groups = gname ? 1 : 0; - func->function = function; - func++; - func_idx++; - } - - priv->pin_groups = groups; - priv->nr_groups = grp_cnt; - priv->pmx_functions = functions; - priv->nr_functions = func_idx; - return 0; -} - -/* register the pinctrl interface with the pinctrl subsystem */ -static int exynos5440_pinctrl_register(struct platform_device *pdev, - struct exynos5440_pinctrl_priv_data *priv) -{ - struct device *dev = &pdev->dev; - struct pinctrl_desc *ctrldesc; - struct pinctrl_dev *pctl_dev; - struct pinctrl_pin_desc *pindesc, *pdesc; - char *pin_names; - int pin, ret; - - ctrldesc = devm_kzalloc(dev, sizeof(*ctrldesc), GFP_KERNEL); - if (!ctrldesc) - return -ENOMEM; - - ctrldesc->name = "exynos5440-pinctrl"; - ctrldesc->owner = THIS_MODULE; - ctrldesc->pctlops = &exynos5440_pctrl_ops; - ctrldesc->pmxops = &exynos5440_pinmux_ops; - ctrldesc->confops = &exynos5440_pinconf_ops; - - pindesc = devm_kzalloc(&pdev->dev, sizeof(*pindesc) * - EXYNOS5440_MAX_PINS, GFP_KERNEL); - if (!pindesc) - return -ENOMEM; - ctrldesc->pins = pindesc; - ctrldesc->npins = EXYNOS5440_MAX_PINS; - - /* dynamically populate the pin number and pin name for pindesc */ - for (pin = 0, pdesc = pindesc; pin < ctrldesc->npins; pin++, pdesc++) - pdesc->number = pin; - - /* - * allocate space for storing the dynamically generated names for all - * the pins which belong to this pin-controller. - */ - pin_names = devm_kzalloc(&pdev->dev, sizeof(char) * PIN_NAME_LENGTH * - ctrldesc->npins, GFP_KERNEL); - if (!pin_names) - return -ENOMEM; - - /* for each pin, set the name of the pin */ - for (pin = 0; pin < ctrldesc->npins; pin++) { - snprintf(pin_names, 6, "gpio%02d", pin); - pdesc = pindesc + pin; - pdesc->name = pin_names; - pin_names += PIN_NAME_LENGTH; - } - - ret = exynos5440_pinctrl_parse_dt(pdev, priv); - if (ret) - return ret; - - pctl_dev = devm_pinctrl_register(&pdev->dev, ctrldesc, priv); - if (IS_ERR(pctl_dev)) { - dev_err(&pdev->dev, "could not register pinctrl driver\n"); - return PTR_ERR(pctl_dev); - } - - priv->range.name = "exynos5440-pctrl-gpio-range"; - priv->range.id = 0; - priv->range.base = 0; - priv->range.npins = EXYNOS5440_MAX_PINS; - priv->range.gc = priv->gc; - pinctrl_add_gpio_range(pctl_dev, &priv->range); - return 0; -} - -/* register the gpiolib interface with the gpiolib subsystem */ -static int exynos5440_gpiolib_register(struct platform_device *pdev, - struct exynos5440_pinctrl_priv_data *priv) -{ - struct gpio_chip *gc; - int ret; - - gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL); - if (!gc) - return -ENOMEM; - - priv->gc = gc; - gc->base = 0; - gc->ngpio = EXYNOS5440_MAX_PINS; - gc->parent = &pdev->dev; - gc->set = exynos5440_gpio_set; - gc->get = exynos5440_gpio_get; - gc->direction_input = exynos5440_gpio_direction_input; - gc->direction_output = exynos5440_gpio_direction_output; - gc->to_irq = exynos5440_gpio_to_irq; - gc->label = "gpiolib-exynos5440"; - gc->owner = THIS_MODULE; - ret = gpiochip_add_data(gc, priv); - if (ret) { - dev_err(&pdev->dev, "failed to register gpio_chip %s, error " - "code: %d\n", gc->label, ret); - return ret; - } - - return 0; -} - -/* unregister the gpiolib interface with the gpiolib subsystem */ -static int exynos5440_gpiolib_unregister(struct platform_device *pdev, - struct exynos5440_pinctrl_priv_data *priv) -{ - gpiochip_remove(priv->gc); - return 0; -} - -static void exynos5440_gpio_irq_unmask(struct irq_data *irqd) -{ - struct exynos5440_pinctrl_priv_data *d; - unsigned long gpio_int; - - d = irq_data_get_irq_chip_data(irqd); - gpio_int = readl(d->reg_base + GPIO_INT); - gpio_int |= 1 << irqd->hwirq; - writel(gpio_int, d->reg_base + GPIO_INT); -} - -static void exynos5440_gpio_irq_mask(struct irq_data *irqd) -{ - struct exynos5440_pinctrl_priv_data *d; - unsigned long gpio_int; - - d = irq_data_get_irq_chip_data(irqd); - gpio_int = readl(d->reg_base + GPIO_INT); - gpio_int &= ~(1 << irqd->hwirq); - writel(gpio_int, d->reg_base + GPIO_INT); -} - -/* irq_chip for gpio interrupts */ -static struct irq_chip exynos5440_gpio_irq_chip = { - .name = "exynos5440_gpio_irq_chip", - .irq_unmask = exynos5440_gpio_irq_unmask, - .irq_mask = exynos5440_gpio_irq_mask, -}; - -/* interrupt handler for GPIO interrupts 0..7 */ -static irqreturn_t exynos5440_gpio_irq(int irq, void *data) -{ - struct exynos5440_gpio_intr_data *intd = data; - struct exynos5440_pinctrl_priv_data *d = intd->priv; - int virq; - - virq = irq_linear_revmap(d->irq_domain, intd->gpio_int); - if (!virq) - return IRQ_NONE; - generic_handle_irq(virq); - return IRQ_HANDLED; -} - -static int exynos5440_gpio_irq_map(struct irq_domain *h, unsigned int virq, - irq_hw_number_t hw) -{ - struct exynos5440_pinctrl_priv_data *d = h->host_data; - - irq_set_chip_data(virq, d); - irq_set_chip_and_handler(virq, &exynos5440_gpio_irq_chip, - handle_level_irq); - return 0; -} - -/* irq domain callbacks for gpio interrupt controller */ -static const struct irq_domain_ops exynos5440_gpio_irqd_ops = { - .map = exynos5440_gpio_irq_map, - .xlate = irq_domain_xlate_twocell, -}; - -/* setup handling of gpio interrupts */ -static int exynos5440_gpio_irq_init(struct platform_device *pdev, - struct exynos5440_pinctrl_priv_data *priv) -{ - struct device *dev = &pdev->dev; - struct exynos5440_gpio_intr_data *intd; - int i, irq, ret; - - intd = devm_kzalloc(dev, sizeof(*intd) * EXYNOS5440_MAX_GPIO_INT, - GFP_KERNEL); - if (!intd) - return -ENOMEM; - - for (i = 0; i < EXYNOS5440_MAX_GPIO_INT; i++) { - irq = irq_of_parse_and_map(dev->of_node, i); - if (irq <= 0) { - dev_err(dev, "irq parsing failed\n"); - return -EINVAL; - } - - intd->gpio_int = i; - intd->priv = priv; - ret = devm_request_irq(dev, irq, exynos5440_gpio_irq, - 0, dev_name(dev), intd++); - if (ret) { - dev_err(dev, "irq request failed\n"); - return -ENXIO; - } - } - - priv->irq_domain = irq_domain_add_linear(dev->of_node, - EXYNOS5440_MAX_GPIO_INT, - &exynos5440_gpio_irqd_ops, priv); - if (!priv->irq_domain) { - dev_err(dev, "failed to create irq domain\n"); - return -ENXIO; - } - - return 0; -} - -static int exynos5440_pinctrl_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct exynos5440_pinctrl_priv_data *priv; - struct resource *res; - int ret; - - if (!dev->of_node) { - dev_err(dev, "device tree node not found\n"); - return -ENODEV; - } - - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->reg_base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(priv->reg_base)) - return PTR_ERR(priv->reg_base); - - ret = exynos5440_gpiolib_register(pdev, priv); - if (ret) - return ret; - - ret = exynos5440_pinctrl_register(pdev, priv); - if (ret) { - exynos5440_gpiolib_unregister(pdev, priv); - return ret; - } - - ret = exynos5440_gpio_irq_init(pdev, priv); - if (ret) { - dev_err(dev, "failed to setup gpio interrupts\n"); - return ret; - } - - platform_set_drvdata(pdev, priv); - dev_info(dev, "EXYNOS5440 pinctrl driver registered\n"); - return 0; -} - -static const struct of_device_id exynos5440_pinctrl_dt_match[] = { - { .compatible = "samsung,exynos5440-pinctrl" }, - {}, -}; - -static struct platform_driver exynos5440_pinctrl_driver = { - .probe = exynos5440_pinctrl_probe, - .driver = { - .name = "exynos5440-pinctrl", - .of_match_table = exynos5440_pinctrl_dt_match, - .suppress_bind_attrs = true, - }, -}; - -static int __init exynos5440_pinctrl_drv_register(void) -{ - return platform_driver_register(&exynos5440_pinctrl_driver); -} -postcore_initcall(exynos5440_pinctrl_drv_register); -- 2.14.1 From mboxrd@z Thu Jan 1 00:00:00 1970 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: base64 Subject: [RFC,07/10] pinctrl: samsung: Remove support for Exynos5440 From: Krzysztof Kozlowski Message-Id: <20180424203239.21885-8-krzk@kernel.org> Date: Tue, 24 Apr 2018 22:32:36 +0200 To: Kukjin Kim , Krzysztof Kozlowski , Rob Herring , Mark Rutland , Tejun Heo , Sylwester Nawrocki , Tomasz Figa , Chanwoo Choi , Michael Turquette , Stephen Boyd , "Rafael J. Wysocki" , Viresh Kumar , Zhang Rui , Eduardo Valentin , Russell King , Hans de Goede , Linus Walleij , Andi Shyti , Mark Brown , Bartlomiej Zolnierkiewicz , Alan Stern , Greg Kroah-Hartman , linux-arm-kernel@lists.infradead.org, linux-samsung-soc@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-ide@vger.kernel.org, linux-clk@vger.kernel.org, linux-pm@vger.kernel.org, linux-i2c@vger.kernel.org, linux-gpio@vger.kernel.org, linux-spi@vger.kernel.org, linux-usb@vger.kernel.org Cc: Marek Szyprowski , Arnd Bergmann , Olof Johansson , Jaehoon Chung List-ID: VGhlIEV4eW5vczU0NDAgaXMgbm90IGFjdGl2ZWx5IGRldmVsb3BlZCwgdGhlcmUgYXJlIG5vIGRl dmVsb3BtZW50CmJvYXJkcyBhdmFpbGFibGUgYW5kIHByb2JhYmx5IHRoZXJlIGFyZSBubyByZWFs IHByb2R1Y3RzIHdpdGggaXQuClJlbW92ZSB3aWRlLXRyZWUgc3VwcG9ydCBmb3IgRXh5bm9zNTQ0 MC4KClNpZ25lZC1vZmYtYnk6IEtyenlzenRvZiBLb3psb3dza2kgPGtyemtAa2VybmVsLm9yZz4K LS0tCiBkcml2ZXJzL3BpbmN0cmwvc2Ftc3VuZy9LY29uZmlnICAgICAgICAgICAgICB8ICAgMTAg Ky0KIGRyaXZlcnMvcGluY3RybC9zYW1zdW5nL01ha2VmaWxlICAgICAgICAgICAgIHwgICAgMSAt CiBkcml2ZXJzL3BpbmN0cmwvc2Ftc3VuZy9waW5jdHJsLWV4eW5vczU0NDAuYyB8IDEwMDUgLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KIDMgZmlsZXMgY2hhbmdlZCwgMiBpbnNlcnRpb25zKCsp LCAxMDE0IGRlbGV0aW9ucygtKQogZGVsZXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvcGluY3RybC9z YW1zdW5nL3BpbmN0cmwtZXh5bm9zNTQ0MC5jCgpkaWZmIC0tZ2l0IGEvZHJpdmVycy9waW5jdHJs L3NhbXN1bmcvS2NvbmZpZyBiL2RyaXZlcnMvcGluY3RybC9zYW1zdW5nL0tjb25maWcKaW5kZXgg MTFiNWVlYjE0YzRhLi40MjVmYWRkNmMzNDYgMTAwNjQ0Ci0tLSBhL2RyaXZlcnMvcGluY3RybC9z YW1zdW5nL0tjb25maWcKKysrIGIvZHJpdmVycy9waW5jdHJsL3NhbXN1bmcvS2NvbmZpZwpAQCAt OCwyNiArOCwyMCBAQCBjb25maWcgUElOQ1RSTF9TQU1TVU5HCiAJc2VsZWN0IFBJTkNPTkYKIAog Y29uZmlnIFBJTkNUUkxfRVhZTk9TCi0JYm9vbCAiUGluY3RybCBkcml2ZXIgZGF0YSBmb3IgU2Ft c3VuZyBFWFlOT1MgU29DcyBvdGhlciB0aGFuIDU0NDAiCisJYm9vbCAiUGluY3RybCBkcml2ZXIg ZGF0YSBmb3IgU2Ftc3VuZyBFWFlOT1MgU29DcyIKIAlkZXBlbmRzIG9uIE9GICYmIEdQSU9MSUIg JiYgKEFSQ0hfRVhZTk9TIHx8IEFSQ0hfUzVQVjIxMCkKIAlzZWxlY3QgUElOQ1RSTF9TQU1TVU5H CiAJc2VsZWN0IFBJTkNUUkxfRVhZTk9TX0FSTSBpZiBBUk0gJiYgKEFSQ0hfRVhZTk9TIHx8IEFS Q0hfUzVQVjIxMCkKIAlzZWxlY3QgUElOQ1RSTF9FWFlOT1NfQVJNNjQgaWYgQVJNNjQgJiYgQVJD SF9FWFlOT1MKIAogY29uZmlnIFBJTkNUUkxfRVhZTk9TX0FSTQotCWJvb2wgIkFSTXY3LXNwZWNp ZmljIHBpbmN0cmwgZHJpdmVyIGRhdGEgZm9yIEV4eW5vcyAoZXhjZXB0IEV4eW5vczU0NDApIiBp ZiBDT01QSUxFX1RFU1QKKwlib29sICJBUk12Ny1zcGVjaWZpYyBwaW5jdHJsIGRyaXZlciBkYXRh IGZvciBFeHlub3MiIGlmIENPTVBJTEVfVEVTVAogCWRlcGVuZHMgb24gUElOQ1RSTF9FWFlOT1MK IAogY29uZmlnIFBJTkNUUkxfRVhZTk9TX0FSTTY0CiAJYm9vbCAiQVJNdjgtc3BlY2lmaWMgcGlu Y3RybCBkcml2ZXIgZGF0YSBmb3IgRXh5bm9zIiBpZiBDT01QSUxFX1RFU1QKIAlkZXBlbmRzIG9u IFBJTkNUUkxfRVhZTk9TCiAKLWNvbmZpZyBQSU5DVFJMX0VYWU5PUzU0NDAKLQlib29sICJTYW1z dW5nIEVYWU5PUzU0NDAgU29DIHBpbmN0cmwgZHJpdmVyIgotCWRlcGVuZHMgb24gU09DX0VYWU5P UzU0NDAKLQlzZWxlY3QgUElOTVVYCi0Jc2VsZWN0IFBJTkNPTkYKLQogY29uZmlnIFBJTkNUUkxf UzNDMjRYWAogCWJvb2wgIlNhbXN1bmcgUzNDMjRYWCBTb0MgcGluY3RybCBkcml2ZXIiCiAJZGVw ZW5kcyBvbiBBUkNIX1MzQzI0WFggJiYgT0YKZGlmZiAtLWdpdCBhL2RyaXZlcnMvcGluY3RybC9z YW1zdW5nL01ha2VmaWxlIGIvZHJpdmVycy9waW5jdHJsL3NhbXN1bmcvTWFrZWZpbGUKaW5kZXgg ZGY0MjY1NjFkMDY3Li5lZDk1MWRmNmExMTIgMTAwNjQ0Ci0tLSBhL2RyaXZlcnMvcGluY3RybC9z YW1zdW5nL01ha2VmaWxlCisrKyBiL2RyaXZlcnMvcGluY3RybC9zYW1zdW5nL01ha2VmaWxlCkBA IC01LDYgKzUsNSBAQCBvYmotJChDT05GSUdfUElOQ1RSTF9TQU1TVU5HKQkrPSBwaW5jdHJsLXNh bXN1bmcubwogb2JqLSQoQ09ORklHX1BJTkNUUkxfRVhZTk9TKQkrPSBwaW5jdHJsLWV4eW5vcy5v CiBvYmotJChDT05GSUdfUElOQ1RSTF9FWFlOT1NfQVJNKQkrPSBwaW5jdHJsLWV4eW5vcy1hcm0u bwogb2JqLSQoQ09ORklHX1BJTkNUUkxfRVhZTk9TX0FSTTY0KQkrPSBwaW5jdHJsLWV4eW5vcy1h cm02NC5vCi1vYmotJChDT05GSUdfUElOQ1RSTF9FWFlOT1M1NDQwKQkrPSBwaW5jdHJsLWV4eW5v czU0NDAubwogb2JqLSQoQ09ORklHX1BJTkNUUkxfUzNDMjRYWCkJKz0gcGluY3RybC1zM2MyNHh4 Lm8KIG9iai0kKENPTkZJR19QSU5DVFJMX1MzQzY0WFgpCSs9IHBpbmN0cmwtczNjNjR4eC5vCmRp ZmYgLS1naXQgYS9kcml2ZXJzL3BpbmN0cmwvc2Ftc3VuZy9waW5jdHJsLWV4eW5vczU0NDAuYyBi L2RyaXZlcnMvcGluY3RybC9zYW1zdW5nL3BpbmN0cmwtZXh5bm9zNTQ0MC5jCmRlbGV0ZWQgZmls ZSBtb2RlIDEwMDY0NAppbmRleCAzZDhkNWU4MTI4MzkuLjAwMDAwMDAwMDAwMAotLS0gYS9kcml2 ZXJzL3BpbmN0cmwvc2Ftc3VuZy9waW5jdHJsLWV4eW5vczU0NDAuYworKysgL2Rldi9udWxsCkBA IC0xLDEwMDUgKzAsMCBAQAotLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEdQTC0yLjArCi0v LwotLy8gcGluLWNvbnRyb2xsZXIvcGluLW11eC9waW4tY29uZmlnL2dwaW8tZHJpdmVyIGZvciBT YW1zdW5nJ3MgRVhZTk9TNTQ0MCBTb0MuCi0vLwotLy8gQXV0aG9yOiBUaG9tYXMgQWJyYWhhbSA8 dGhvbWFzLmFiQHNhbXN1bmcuY29tPgotLy8KLS8vIENvcHlyaWdodCAoYykgMjAxMiBTYW1zdW5n IEVsZWN0cm9uaWNzIENvLiwgTHRkLgotLy8JCWh0dHA6Ly93d3cuc2Ftc3VuZy5jb20KLQotI2lu Y2x1ZGUgPGxpbnV4L2luaXQuaD4KLSNpbmNsdWRlIDxsaW51eC9wbGF0Zm9ybV9kZXZpY2UuaD4K LSNpbmNsdWRlIDxsaW51eC9pby5oPgotI2luY2x1ZGUgPGxpbnV4L3NsYWIuaD4KLSNpbmNsdWRl IDxsaW51eC9lcnIuaD4KLSNpbmNsdWRlIDxsaW51eC9ncGlvL2RyaXZlci5oPgotI2luY2x1ZGUg PGxpbnV4L2RldmljZS5oPgotI2luY2x1ZGUgPGxpbnV4L3BpbmN0cmwvcGluY3RybC5oPgotI2lu Y2x1ZGUgPGxpbnV4L3BpbmN0cmwvcGlubXV4Lmg+Ci0jaW5jbHVkZSA8bGludXgvcGluY3RybC9w aW5jb25mLmg+Ci0jaW5jbHVkZSA8bGludXgvaW50ZXJydXB0Lmg+Ci0jaW5jbHVkZSA8bGludXgv aXJxZG9tYWluLmg+Ci0jaW5jbHVkZSA8bGludXgvb2ZfaXJxLmg+Ci0jaW5jbHVkZSAiLi4vY29y ZS5oIgotCi0vKiBFWFlOT1M1NDQwIEdQSU8gYW5kIFBpbmN0cmwgcmVnaXN0ZXIgb2Zmc2V0cyAq LwotI2RlZmluZSBHUElPX01VWAkJMHgwMAotI2RlZmluZSBHUElPX0lFCQkJMHgwNAotI2RlZmlu ZSBHUElPX0lOVAkJMHgwOAotI2RlZmluZSBHUElPX1RZUEUJCTB4MEMKLSNkZWZpbmUgR1BJT19W QUwJCTB4MTAKLSNkZWZpbmUgR1BJT19PRQkJCTB4MTQKLSNkZWZpbmUgR1BJT19JTgkJCTB4MTgK LSNkZWZpbmUgR1BJT19QRQkJCTB4MUMKLSNkZWZpbmUgR1BJT19QUwkJCTB4MjAKLSNkZWZpbmUg R1BJT19TUgkJCTB4MjQKLSNkZWZpbmUgR1BJT19EUzAJCTB4MjgKLSNkZWZpbmUgR1BJT19EUzEJ CTB4MkMKLQotI2RlZmluZSBFWFlOT1M1NDQwX01BWF9QSU5TCQkyMwotI2RlZmluZSBFWFlOT1M1 NDQwX01BWF9HUElPX0lOVAk4Ci0jZGVmaW5lIFBJTl9OQU1FX0xFTkdUSAkJMTAKLQotI2RlZmlu ZSBHUk9VUF9TVUZGSVgJCSItZ3JwIgotI2RlZmluZSBGVU5DVElPTl9TVUZGSVgJCSItbXV4Igot Ci0vKgotICogcGluIGNvbmZpZ3VyYXRpb24gdHlwZSBhbmQgaXRzIHZhbHVlIGFyZSBwYWNrZWQg dG9nZXRoZXIgaW50byBhIDE2LWJpdHMuCi0gKiBUaGUgdXBwZXIgOC1iaXRzIHJlcHJlc2VudCB0 aGUgY29uZmlndXJhdGlvbiB0eXBlIGFuZCB0aGUgbG93ZXIgOC1iaXRzCi0gKiBob2xkIHRoZSB2 YWx1ZSBvZiB0aGUgY29uZmlndXJhdGlvbiB0eXBlLgotICovCi0jZGVmaW5lIFBJTkNGR19UWVBF X01BU0sJCTB4RkYKLSNkZWZpbmUgUElOQ0ZHX1ZBTFVFX1NISUZUCQk4Ci0jZGVmaW5lIFBJTkNG R19WQUxVRV9NQVNLCQkoMHhGRiA8PCBQSU5DRkdfVkFMVUVfU0hJRlQpCi0jZGVmaW5lIFBJTkNG R19QQUNLKHR5cGUsIHZhbHVlKQkoKCh2YWx1ZSkgPDwgUElOQ0ZHX1ZBTFVFX1NISUZUKSB8IHR5 cGUpCi0jZGVmaW5lIFBJTkNGR19VTlBBQ0tfVFlQRShjZmcpCQkoKGNmZykgJiBQSU5DRkdfVFlQ RV9NQVNLKQotI2RlZmluZSBQSU5DRkdfVU5QQUNLX1ZBTFVFKGNmZykJKCgoY2ZnKSAmIFBJTkNG R19WQUxVRV9NQVNLKSA+PiBcCi0JCQkJCQlQSU5DRkdfVkFMVUVfU0hJRlQpCi0KLS8qKgotICog ZW51bSBwaW5jZmdfdHlwZSAtIHBvc3NpYmxlIHBpbiBjb25maWd1cmF0aW9uIHR5cGVzIHN1cHBv cnRlZC4KLSAqIEBQSU5DRkdfVFlQRV9QVUQ6IFB1bGwgdXAvZG93biBjb25maWd1cmF0aW9uLgot ICogQFBJTkNGR19UWVBFX0RSVjogRHJpdmUgc3RyZW5ndGggY29uZmlndXJhdGlvbi4KLSAqIEBQ SU5DRkdfVFlQRV9TS0VXX1JBVEU6IFNrZXcgcmF0ZSBjb25maWd1cmF0aW9uLgotICogQFBJTkNG R19UWVBFX0lOUFVUX1RZUEU6IFBpbiBpbnB1dCB0eXBlIGNvbmZpZ3VyYXRpb24uCi0gKi8KLWVu dW0gcGluY2ZnX3R5cGUgewotCVBJTkNGR19UWVBFX1BVRCwKLQlQSU5DRkdfVFlQRV9EUlYsCi0J UElOQ0ZHX1RZUEVfU0tFV19SQVRFLAotCVBJTkNGR19UWVBFX0lOUFVUX1RZUEUKLX07Ci0KLS8q KgotICogc3RydWN0IGV4eW5vczU0NDBfcGluX2dyb3VwOiByZXByZXNlbnQgZ3JvdXAgb2YgcGlu cyBmb3IgcGluY2ZnIHNldHRpbmcuCi0gKiBAbmFtZTogbmFtZSBvZiB0aGUgcGluIGdyb3VwLCB1 c2VkIHRvIGxvb2t1cCB0aGUgZ3JvdXAuCi0gKiBAcGluczogdGhlIHBpbnMgaW5jbHVkZWQgaW4g dGhpcyBncm91cC4KLSAqIEBudW1fcGluczogbnVtYmVyIG9mIHBpbnMgaW5jbHVkZWQgaW4gdGhp cyBncm91cC4KLSAqLwotc3RydWN0IGV4eW5vczU0NDBfcGluX2dyb3VwIHsKLQljb25zdCBjaGFy CQkqbmFtZTsKLQljb25zdCB1bnNpZ25lZCBpbnQJKnBpbnM7Ci0JdTgJCQludW1fcGluczsKLX07 Ci0KLS8qKgotICogc3RydWN0IGV4eW5vczU0NDBfcG14X2Z1bmM6IHJlcHJlc2VudCBhIHBpbiBm dW5jdGlvbi4KLSAqIEBuYW1lOiBuYW1lIG9mIHRoZSBwaW4gZnVuY3Rpb24sIHVzZWQgdG8gbG9v a3VwIHRoZSBmdW5jdGlvbi4KLSAqIEBncm91cHM6IG9uZSBvciBtb3JlIG5hbWVzIG9mIHBpbiBn cm91cHMgdGhhdCBwcm92aWRlIHRoaXMgZnVuY3Rpb24uCi0gKiBAbnVtX2dyb3VwczogbnVtYmVy IG9mIGdyb3VwcyBpbmNsdWRlZCBpbiBAZ3JvdXBzLgotICogQGZ1bmN0aW9uOiB0aGUgZnVuY3Rp b24gbnVtYmVyIHRvIGJlIHByb2dyYW1tZWQgd2hlbiBzZWxlY3RlZC4KLSAqLwotc3RydWN0IGV4 eW5vczU0NDBfcG14X2Z1bmMgewotCWNvbnN0IGNoYXIJCSpuYW1lOwotCWNvbnN0IGNoYXIJCSoq Z3JvdXBzOwotCXU4CQkJbnVtX2dyb3VwczsKLQl1bnNpZ25lZCBsb25nCQlmdW5jdGlvbjsKLX07 Ci0KLS8qKgotICogc3RydWN0IGV4eW5vczU0NDBfcGluY3RybF9wcml2X2RhdGE6IGRyaXZlcidz IHByaXZhdGUgcnVudGltZSBkYXRhLgotICogQHJlZ19iYXNlOiBpb3JlbWFwcGVkIGJhc2VkIGFk ZHJlc3Mgb2YgdGhlIHJlZ2lzdGVyIHNwYWNlLgotICogQGdjOiBncGlvIGNoaXAgcmVnaXN0ZXJl ZCB3aXRoIGdwaW9saWIuCi0gKiBAcGluX2dyb3VwczogbGlzdCBvZiBwaW4gZ3JvdXBzIHBhcnNl ZCBmcm9tIGRldmljZSB0cmVlLgotICogQG5yX2dyb3VwczogbnVtYmVyIG9mIHBpbiBncm91cHMg YXZhaWxhYmxlLgotICogQHBteF9mdW5jdGlvbnM6IGxpc3Qgb2YgcGluIGZ1bmN0aW9ucyBwYXJz ZWQgZnJvbSBkZXZpY2UgdHJlZS4KLSAqIEBucl9mdW5jdGlvbnM6IG51bWJlciBvZiBwaW4gZnVu Y3Rpb25zIGF2YWlsYWJsZS4KLSAqIEByYW5nZTogZ3BpbyByYW5nZSB0byByZWdpc3RlciB3aXRo IHBpbmN0cmwKLSAqLwotc3RydWN0IGV4eW5vczU0NDBfcGluY3RybF9wcml2X2RhdGEgewotCXZv aWQgX19pb21lbQkJCSpyZWdfYmFzZTsKLQlzdHJ1Y3QgZ3Bpb19jaGlwCQkqZ2M7Ci0Jc3RydWN0 IGlycV9kb21haW4JCSppcnFfZG9tYWluOwotCi0JY29uc3Qgc3RydWN0IGV4eW5vczU0NDBfcGlu X2dyb3VwCSpwaW5fZ3JvdXBzOwotCXVuc2lnbmVkIGludAkJCW5yX2dyb3VwczsKLQljb25zdCBz dHJ1Y3QgZXh5bm9zNTQ0MF9wbXhfZnVuYwkqcG14X2Z1bmN0aW9uczsKLQl1bnNpZ25lZCBpbnQJ CQlucl9mdW5jdGlvbnM7Ci0Jc3RydWN0IHBpbmN0cmxfZ3Bpb19yYW5nZQlyYW5nZTsKLX07Ci0K LS8qKgotICogc3RydWN0IGV4eW5vczU0NDBfZ3Bpb19pbnRyX2RhdGE6IHByaXZhdGUgZGF0YSBm b3IgZ3BpbyBpbnRlcnJ1cHRzLgotICogQHByaXY6IGRyaXZlcidzIHByaXZhdGUgcnVudGltZSBk YXRhLgotICogQGdwaW9faW50OiBncGlvIGludGVycnVwdCBudW1iZXIuCi0gKi8KLXN0cnVjdCBl eHlub3M1NDQwX2dwaW9faW50cl9kYXRhIHsKLQlzdHJ1Y3QgZXh5bm9zNTQ0MF9waW5jdHJsX3By aXZfZGF0YQkqcHJpdjsKLQl1bnNpZ25lZCBpbnQJCQkJZ3Bpb19pbnQ7Ci19OwotCi0vKiBsaXN0 IG9mIGFsbCBwb3NzaWJsZSBjb25maWcgb3B0aW9ucyBzdXBwb3J0ZWQgKi8KLXN0YXRpYyBzdHJ1 Y3QgcGluX2NvbmZpZyB7Ci0JY2hhcgkJKnByb3BfY2ZnOwotCXVuc2lnbmVkIGludAljZmdfdHlw ZTsKLX0gcGNmZ3NbXSA9IHsKLQl7ICJzYW1zdW5nLGV4eW5vczU0NDAtcGluLXB1ZCIsIFBJTkNG R19UWVBFX1BVRCB9LAotCXsgInNhbXN1bmcsZXh5bm9zNTQ0MC1waW4tZHJ2IiwgUElOQ0ZHX1RZ UEVfRFJWIH0sCi0JeyAic2Ftc3VuZyxleHlub3M1NDQwLXBpbi1za2V3LXJhdGUiLCBQSU5DRkdf VFlQRV9TS0VXX1JBVEUgfSwKLQl7ICJzYW1zdW5nLGV4eW5vczU0NDAtcGluLWlucHV0LXR5cGUi LCBQSU5DRkdfVFlQRV9JTlBVVF9UWVBFIH0sCi19OwotCi0vKiBjaGVjayBpZiB0aGUgc2VsZWN0 b3IgaXMgYSB2YWxpZCBwaW4gZ3JvdXAgc2VsZWN0b3IgKi8KLXN0YXRpYyBpbnQgZXh5bm9zNTQ0 MF9nZXRfZ3JvdXBfY291bnQoc3RydWN0IHBpbmN0cmxfZGV2ICpwY3RsZGV2KQotewotCXN0cnVj dCBleHlub3M1NDQwX3BpbmN0cmxfcHJpdl9kYXRhICpwcml2OwotCi0JcHJpdiA9IHBpbmN0cmxf ZGV2X2dldF9kcnZkYXRhKHBjdGxkZXYpOwotCXJldHVybiBwcml2LT5ucl9ncm91cHM7Ci19Ci0K LS8qIHJldHVybiB0aGUgbmFtZSBvZiB0aGUgZ3JvdXAgc2VsZWN0ZWQgYnkgdGhlIGdyb3VwIHNl bGVjdG9yICovCi1zdGF0aWMgY29uc3QgY2hhciAqZXh5bm9zNTQ0MF9nZXRfZ3JvdXBfbmFtZShz dHJ1Y3QgcGluY3RybF9kZXYgKnBjdGxkZXYsCi0JCQkJCQl1bnNpZ25lZCBzZWxlY3RvcikKLXsK LQlzdHJ1Y3QgZXh5bm9zNTQ0MF9waW5jdHJsX3ByaXZfZGF0YSAqcHJpdjsKLQotCXByaXYgPSBw aW5jdHJsX2Rldl9nZXRfZHJ2ZGF0YShwY3RsZGV2KTsKLQlyZXR1cm4gcHJpdi0+cGluX2dyb3Vw c1tzZWxlY3Rvcl0ubmFtZTsKLX0KLQotLyogcmV0dXJuIHRoZSBwaW4gbnVtYmVycyBhc3NvY2lh dGVkIHdpdGggdGhlIHNwZWNpZmllZCBncm91cCAqLwotc3RhdGljIGludCBleHlub3M1NDQwX2dl dF9ncm91cF9waW5zKHN0cnVjdCBwaW5jdHJsX2RldiAqcGN0bGRldiwKLQkJdW5zaWduZWQgc2Vs ZWN0b3IsIGNvbnN0IHVuc2lnbmVkICoqcGlucywgdW5zaWduZWQgKm51bV9waW5zKQotewotCXN0 cnVjdCBleHlub3M1NDQwX3BpbmN0cmxfcHJpdl9kYXRhICpwcml2OwotCi0JcHJpdiA9IHBpbmN0 cmxfZGV2X2dldF9kcnZkYXRhKHBjdGxkZXYpOwotCSpwaW5zID0gcHJpdi0+cGluX2dyb3Vwc1tz ZWxlY3Rvcl0ucGluczsKLQkqbnVtX3BpbnMgPSBwcml2LT5waW5fZ3JvdXBzW3NlbGVjdG9yXS5u dW1fcGluczsKLQlyZXR1cm4gMDsKLX0KLQotLyogY3JlYXRlIHBpbmN0cmxfbWFwIGVudHJpZXMg YnkgcGFyc2luZyBkZXZpY2UgdHJlZSBub2RlcyAqLwotc3RhdGljIGludCBleHlub3M1NDQwX2R0 X25vZGVfdG9fbWFwKHN0cnVjdCBwaW5jdHJsX2RldiAqcGN0bGRldiwKLQkJCXN0cnVjdCBkZXZp Y2Vfbm9kZSAqbnAsIHN0cnVjdCBwaW5jdHJsX21hcCAqKm1hcHMsCi0JCQl1bnNpZ25lZCAqbm1h cHMpCi17Ci0Jc3RydWN0IGRldmljZSAqZGV2ID0gcGN0bGRldi0+ZGV2OwotCXN0cnVjdCBwaW5j dHJsX21hcCAqbWFwOwotCXVuc2lnbmVkIGxvbmcgKmNmZyA9IE5VTEw7Ci0JY2hhciAqZ25hbWUs ICpmbmFtZTsKLQlpbnQgY2ZnX2NudCA9IDAsIG1hcF9jbnQgPSAwLCBpZHggPSAwOwotCi0JLyog Y291bnQgdGhlIG51bWJlciBvZiBjb25maWcgb3B0aW9ucyBzcGVjZmllZCBpbiB0aGUgbm9kZSAq LwotCWZvciAoaWR4ID0gMDsgaWR4IDwgQVJSQVlfU0laRShwY2Zncyk7IGlkeCsrKQotCQlpZiAo b2ZfZmluZF9wcm9wZXJ0eShucCwgcGNmZ3NbaWR4XS5wcm9wX2NmZywgTlVMTCkpCi0JCQljZmdf Y250Kys7Ci0KLQkvKgotCSAqIEZpbmQgb3V0IHRoZSBudW1iZXIgb2YgbWFwIGVudHJpZXMgdG8g Y3JlYXRlLiBBbGwgdGhlIGNvbmZpZyBvcHRpb25zCi0JICogY2FuIGJlIGFjY29tYWRhdGVkIGlu dG8gYSBzaW5nbGUgY29uZmlnIG1hcCBlbnRyeS4KLQkgKi8KLQlpZiAoY2ZnX2NudCkKLQkJbWFw X2NudCA9IDE7Ci0JaWYgKG9mX2ZpbmRfcHJvcGVydHkobnAsICJzYW1zdW5nLGV4eW5vczU0NDAt cGluLWZ1bmN0aW9uIiwgTlVMTCkpCi0JCW1hcF9jbnQrKzsKLQlpZiAoIW1hcF9jbnQpIHsKLQkJ ZGV2X2VycihkZXYsICJub2RlICVzIGRvZXMgbm90IGhhdmUgZWl0aGVyIGNvbmZpZyBvciBmdW5j dGlvbiAiCi0JCQkJImNvbmZpZ3VyYXRpb25zXG4iLCBucC0+bmFtZSk7Ci0JCXJldHVybiAtRUlO VkFMOwotCX0KLQotCS8qIEFsbG9jYXRlIG1lbW9yeSBmb3IgcGluLW1hcCBlbnRyaWVzICovCi0J bWFwID0ga3phbGxvYyhzaXplb2YoKm1hcCkgKiBtYXBfY250LCBHRlBfS0VSTkVMKTsKLQlpZiAo IW1hcCkKLQkJcmV0dXJuIC1FTk9NRU07Ci0JKm5tYXBzID0gMDsKLQotCS8qCi0JICogQWxsb2Nh dGUgbWVtb3J5IGZvciBwaW4gZ3JvdXAgbmFtZS4gVGhlIHBpbiBncm91cCBuYW1lIGlzIGRlcml2 ZWQKLQkgKiBmcm9tIHRoZSBub2RlIG5hbWUgZnJvbSB3aGljaCB0aGVzZSBtYXAgZW50cmllcyBh cmUgYmUgY3JlYXRlZC4KLQkgKi8KLQlnbmFtZSA9IGthc3ByaW50ZihHRlBfS0VSTkVMLCAiJXMl cyIsIG5wLT5uYW1lLCBHUk9VUF9TVUZGSVgpOwotCWlmICghZ25hbWUpCi0JCWdvdG8gZnJlZV9t YXA7Ci0KLQkvKgotCSAqIGRvbid0IGhhdmUgY29uZmlnIG9wdGlvbnM/IHRoZW4gc2tpcCBvdmVy IHRvIGNyZWF0aW5nIGZ1bmN0aW9uCi0JICogbWFwIGVudHJpZXMuCi0JICovCi0JaWYgKCFjZmdf Y250KQotCQlnb3RvIHNraXBfY2ZnczsKLQotCS8qIEFsbG9jYXRlIG1lbW9yeSBmb3IgY29uZmln IGVudHJpZXMgKi8KLQljZmcgPSBremFsbG9jKHNpemVvZigqY2ZnKSAqIGNmZ19jbnQsIEdGUF9L RVJORUwpOwotCWlmICghY2ZnKQotCQlnb3RvIGZyZWVfZ25hbWU7Ci0KLQkvKiBQcmVwYXJlIGEg bGlzdCBvZiBjb25maWcgc2V0dGluZ3MgKi8KLQlmb3IgKGlkeCA9IDAsIGNmZ19jbnQgPSAwOyBp ZHggPCBBUlJBWV9TSVpFKHBjZmdzKTsgaWR4KyspIHsKLQkJdTMyIHZhbHVlOwotCQlpZiAoIW9m X3Byb3BlcnR5X3JlYWRfdTMyKG5wLCBwY2Znc1tpZHhdLnByb3BfY2ZnLCAmdmFsdWUpKQotCQkJ Y2ZnW2NmZ19jbnQrK10gPQotCQkJCVBJTkNGR19QQUNLKHBjZmdzW2lkeF0uY2ZnX3R5cGUsIHZh bHVlKTsKLQl9Ci0KLQkvKiBjcmVhdGUgdGhlIGNvbmZpZyBtYXAgZW50cnkgKi8KLQltYXBbKm5t YXBzXS5kYXRhLmNvbmZpZ3MuZ3JvdXBfb3JfcGluID0gZ25hbWU7Ci0JbWFwWypubWFwc10uZGF0 YS5jb25maWdzLmNvbmZpZ3MgPSBjZmc7Ci0JbWFwWypubWFwc10uZGF0YS5jb25maWdzLm51bV9j b25maWdzID0gY2ZnX2NudDsKLQltYXBbKm5tYXBzXS50eXBlID0gUElOX01BUF9UWVBFX0NPTkZJ R1NfR1JPVVA7Ci0JKm5tYXBzICs9IDE7Ci0KLXNraXBfY2ZnczoKLQkvKiBjcmVhdGUgdGhlIGZ1 bmN0aW9uIG1hcCBlbnRyeSAqLwotCWlmIChvZl9maW5kX3Byb3BlcnR5KG5wLCAic2Ftc3VuZyxl eHlub3M1NDQwLXBpbi1mdW5jdGlvbiIsIE5VTEwpKSB7Ci0JCWZuYW1lID0ga2FzcHJpbnRmKEdG UF9LRVJORUwsCi0JCQkJICAiJXMlcyIsIG5wLT5uYW1lLCBGVU5DVElPTl9TVUZGSVgpOwotCQlp ZiAoIWZuYW1lKQotCQkJZ290byBmcmVlX2NmZzsKLQotCQltYXBbKm5tYXBzXS5kYXRhLm11eC5n cm91cCA9IGduYW1lOwotCQltYXBbKm5tYXBzXS5kYXRhLm11eC5mdW5jdGlvbiA9IGZuYW1lOwot CQltYXBbKm5tYXBzXS50eXBlID0gUElOX01BUF9UWVBFX01VWF9HUk9VUDsKLQkJKm5tYXBzICs9 IDE7Ci0JfQotCi0JKm1hcHMgPSBtYXA7Ci0JcmV0dXJuIDA7Ci0KLWZyZWVfY2ZnOgotCWtmcmVl KGNmZyk7Ci1mcmVlX2duYW1lOgotCWtmcmVlKGduYW1lKTsKLWZyZWVfbWFwOgotCWtmcmVlKG1h cCk7Ci0JcmV0dXJuIC1FTk9NRU07Ci19Ci0KLS8qIGZyZWUgdGhlIG1lbW9yeSBhbGxvY2F0ZWQg dG8gaG9sZCB0aGUgcGluLW1hcCB0YWJsZSAqLwotc3RhdGljIHZvaWQgZXh5bm9zNTQ0MF9kdF9m cmVlX21hcChzdHJ1Y3QgcGluY3RybF9kZXYgKnBjdGxkZXYsCi0JCQkgICAgIHN0cnVjdCBwaW5j dHJsX21hcCAqbWFwLCB1bnNpZ25lZCBudW1fbWFwcykKLXsKLQlpbnQgaWR4OwotCi0JZm9yIChp ZHggPSAwOyBpZHggPCBudW1fbWFwczsgaWR4KyspIHsKLQkJaWYgKG1hcFtpZHhdLnR5cGUgPT0g UElOX01BUF9UWVBFX01VWF9HUk9VUCkgewotCQkJa2ZyZWUobWFwW2lkeF0uZGF0YS5tdXguZnVu Y3Rpb24pOwotCQkJaWYgKCFpZHgpCi0JCQkJa2ZyZWUobWFwW2lkeF0uZGF0YS5tdXguZ3JvdXAp OwotCQl9IGVsc2UgaWYgKG1hcC0+dHlwZSA9PSBQSU5fTUFQX1RZUEVfQ09ORklHU19HUk9VUCkg ewotCQkJa2ZyZWUobWFwW2lkeF0uZGF0YS5jb25maWdzLmNvbmZpZ3MpOwotCQkJaWYgKCFpZHgp Ci0JCQkJa2ZyZWUobWFwW2lkeF0uZGF0YS5jb25maWdzLmdyb3VwX29yX3Bpbik7Ci0JCX0KLQl9 Ci0KLQlrZnJlZShtYXApOwotfQotCi0vKiBsaXN0IG9mIHBpbmN0cmwgY2FsbGJhY2tzIGZvciB0 aGUgcGluY3RybCBjb3JlICovCi1zdGF0aWMgY29uc3Qgc3RydWN0IHBpbmN0cmxfb3BzIGV4eW5v czU0NDBfcGN0cmxfb3BzID0gewotCS5nZXRfZ3JvdXBzX2NvdW50CT0gZXh5bm9zNTQ0MF9nZXRf Z3JvdXBfY291bnQsCi0JLmdldF9ncm91cF9uYW1lCQk9IGV4eW5vczU0NDBfZ2V0X2dyb3VwX25h bWUsCi0JLmdldF9ncm91cF9waW5zCQk9IGV4eW5vczU0NDBfZ2V0X2dyb3VwX3BpbnMsCi0JLmR0 X25vZGVfdG9fbWFwCQk9IGV4eW5vczU0NDBfZHRfbm9kZV90b19tYXAsCi0JLmR0X2ZyZWVfbWFw CQk9IGV4eW5vczU0NDBfZHRfZnJlZV9tYXAsCi19OwotCi0vKiBjaGVjayBpZiB0aGUgc2VsZWN0 b3IgaXMgYSB2YWxpZCBwaW4gZnVuY3Rpb24gc2VsZWN0b3IgKi8KLXN0YXRpYyBpbnQgZXh5bm9z NTQ0MF9nZXRfZnVuY3Rpb25zX2NvdW50KHN0cnVjdCBwaW5jdHJsX2RldiAqcGN0bGRldikKLXsK LQlzdHJ1Y3QgZXh5bm9zNTQ0MF9waW5jdHJsX3ByaXZfZGF0YSAqcHJpdjsKLQotCXByaXYgPSBw aW5jdHJsX2Rldl9nZXRfZHJ2ZGF0YShwY3RsZGV2KTsKLQlyZXR1cm4gcHJpdi0+bnJfZnVuY3Rp b25zOwotfQotCi0vKiByZXR1cm4gdGhlIG5hbWUgb2YgdGhlIHBpbiBmdW5jdGlvbiBzcGVjaWZp ZWQgKi8KLXN0YXRpYyBjb25zdCBjaGFyICpleHlub3M1NDQwX3Bpbm11eF9nZXRfZm5hbWUoc3Ry dWN0IHBpbmN0cmxfZGV2ICpwY3RsZGV2LAotCQkJCQkJdW5zaWduZWQgc2VsZWN0b3IpCi17Ci0J c3RydWN0IGV4eW5vczU0NDBfcGluY3RybF9wcml2X2RhdGEgKnByaXY7Ci0KLQlwcml2ID0gcGlu Y3RybF9kZXZfZ2V0X2RydmRhdGEocGN0bGRldik7Ci0JcmV0dXJuIHByaXYtPnBteF9mdW5jdGlv bnNbc2VsZWN0b3JdLm5hbWU7Ci19Ci0KLS8qIHJldHVybiB0aGUgZ3JvdXBzIGFzc29jaWF0ZWQg Zm9yIHRoZSBzcGVjaWZpZWQgZnVuY3Rpb24gc2VsZWN0b3IgKi8KLXN0YXRpYyBpbnQgZXh5bm9z NTQ0MF9waW5tdXhfZ2V0X2dyb3VwcyhzdHJ1Y3QgcGluY3RybF9kZXYgKnBjdGxkZXYsCi0JCXVu c2lnbmVkIHNlbGVjdG9yLCBjb25zdCBjaGFyICogY29uc3QgKipncm91cHMsCi0JCXVuc2lnbmVk ICogY29uc3QgbnVtX2dyb3VwcykKLXsKLQlzdHJ1Y3QgZXh5bm9zNTQ0MF9waW5jdHJsX3ByaXZf ZGF0YSAqcHJpdjsKLQotCXByaXYgPSBwaW5jdHJsX2Rldl9nZXRfZHJ2ZGF0YShwY3RsZGV2KTsK LQkqZ3JvdXBzID0gcHJpdi0+cG14X2Z1bmN0aW9uc1tzZWxlY3Rvcl0uZ3JvdXBzOwotCSpudW1f Z3JvdXBzID0gcHJpdi0+cG14X2Z1bmN0aW9uc1tzZWxlY3Rvcl0ubnVtX2dyb3VwczsKLQlyZXR1 cm4gMDsKLX0KLQotLyogZW5hYmxlIG9yIGRpc2FibGUgYSBwaW5tdXggZnVuY3Rpb24gKi8KLXN0 YXRpYyB2b2lkIGV4eW5vczU0NDBfcGlubXV4X3NldHVwKHN0cnVjdCBwaW5jdHJsX2RldiAqcGN0 bGRldiwgdW5zaWduZWQgc2VsZWN0b3IsCi0JCQkJCXVuc2lnbmVkIGdyb3VwLCBib29sIGVuYWJs ZSkKLXsKLQlzdHJ1Y3QgZXh5bm9zNTQ0MF9waW5jdHJsX3ByaXZfZGF0YSAqcHJpdjsKLQl2b2lk IF9faW9tZW0gKmJhc2U7Ci0JdTMyIGZ1bmN0aW9uOwotCXUzMiBkYXRhOwotCi0JcHJpdiA9IHBp bmN0cmxfZGV2X2dldF9kcnZkYXRhKHBjdGxkZXYpOwotCWJhc2UgPSBwcml2LT5yZWdfYmFzZTsK LQlmdW5jdGlvbiA9IHByaXYtPnBteF9mdW5jdGlvbnNbc2VsZWN0b3JdLmZ1bmN0aW9uOwotCi0J ZGF0YSA9IHJlYWRsKGJhc2UgKyBHUElPX01VWCk7Ci0JaWYgKGVuYWJsZSkKLQkJZGF0YSB8PSAo MSA8PCBmdW5jdGlvbik7Ci0JZWxzZQotCQlkYXRhICY9IH4oMSA8PCBmdW5jdGlvbik7Ci0Jd3Jp dGVsKGRhdGEsIGJhc2UgKyBHUElPX01VWCk7Ci19Ci0KLS8qIGVuYWJsZSBhIHNwZWNpZmllZCBw aW5tdXggYnkgd3JpdGluZyB0byByZWdpc3RlcnMgKi8KLXN0YXRpYyBpbnQgZXh5bm9zNTQ0MF9w aW5tdXhfc2V0X211eChzdHJ1Y3QgcGluY3RybF9kZXYgKnBjdGxkZXYsCi0JCQkJICAgICB1bnNp Z25lZCBzZWxlY3RvciwKLQkJCQkgICAgIHVuc2lnbmVkIGdyb3VwKQotewotCWV4eW5vczU0NDBf cGlubXV4X3NldHVwKHBjdGxkZXYsIHNlbGVjdG9yLCBncm91cCwgdHJ1ZSk7Ci0JcmV0dXJuIDA7 Ci19Ci0KLS8qCi0gKiBUaGUgY2FsbHMgdG8gZ3Bpb19kaXJlY3Rpb25fb3V0cHV0KCkgYW5kIGdw aW9fZGlyZWN0aW9uX2lucHV0KCkKLSAqIGxlYWRzIHRvIHRoaXMgZnVuY3Rpb24gY2FsbCAodmlh IHRoZSBwaW5jdHJsX2dwaW9fZGlyZWN0aW9uX3tpbnB1dHxvdXRwdXR9KCkKLSAqIGZ1bmN0aW9u IGNhbGxlZCBmcm9tIHRoZSBncGlvbGliIGludGVyZmFjZSkuCi0gKi8KLXN0YXRpYyBpbnQgZXh5 bm9zNTQ0MF9waW5tdXhfZ3Bpb19zZXRfZGlyZWN0aW9uKHN0cnVjdCBwaW5jdHJsX2RldiAqcGN0 bGRldiwKLQkJc3RydWN0IHBpbmN0cmxfZ3Bpb19yYW5nZSAqcmFuZ2UsIHVuc2lnbmVkIG9mZnNl dCwgYm9vbCBpbnB1dCkKLXsKLQlyZXR1cm4gMDsKLX0KLQotLyogbGlzdCBvZiBwaW5tdXggY2Fs bGJhY2tzIGZvciB0aGUgcGlubXV4IHZlcnRpY2FsIGluIHBpbmN0cmwgY29yZSAqLwotc3RhdGlj IGNvbnN0IHN0cnVjdCBwaW5tdXhfb3BzIGV4eW5vczU0NDBfcGlubXV4X29wcyA9IHsKLQkuZ2V0 X2Z1bmN0aW9uc19jb3VudAk9IGV4eW5vczU0NDBfZ2V0X2Z1bmN0aW9uc19jb3VudCwKLQkuZ2V0 X2Z1bmN0aW9uX25hbWUJPSBleHlub3M1NDQwX3Bpbm11eF9nZXRfZm5hbWUsCi0JLmdldF9mdW5j dGlvbl9ncm91cHMJPSBleHlub3M1NDQwX3Bpbm11eF9nZXRfZ3JvdXBzLAotCS5zZXRfbXV4CQk9 IGV4eW5vczU0NDBfcGlubXV4X3NldF9tdXgsCi0JLmdwaW9fc2V0X2RpcmVjdGlvbgk9IGV4eW5v czU0NDBfcGlubXV4X2dwaW9fc2V0X2RpcmVjdGlvbiwKLX07Ci0KLS8qIHNldCB0aGUgcGluIGNv bmZpZyBzZXR0aW5ncyBmb3IgYSBzcGVjaWZpZWQgcGluICovCi1zdGF0aWMgaW50IGV4eW5vczU0 NDBfcGluY29uZl9zZXQoc3RydWN0IHBpbmN0cmxfZGV2ICpwY3RsZGV2LCB1bnNpZ25lZCBpbnQg cGluLAotCQkJCXVuc2lnbmVkIGxvbmcgKmNvbmZpZ3MsCi0JCQkJdW5zaWduZWQgbnVtX2NvbmZp Z3MpCi17Ci0Jc3RydWN0IGV4eW5vczU0NDBfcGluY3RybF9wcml2X2RhdGEgKnByaXY7Ci0Jdm9p ZCBfX2lvbWVtICpiYXNlOwotCWVudW0gcGluY2ZnX3R5cGUgY2ZnX3R5cGU7Ci0JdTMyIGNmZ192 YWx1ZTsKLQl1MzIgZGF0YTsKLQlpbnQgaTsKLQotCXByaXYgPSBwaW5jdHJsX2Rldl9nZXRfZHJ2 ZGF0YShwY3RsZGV2KTsKLQliYXNlID0gcHJpdi0+cmVnX2Jhc2U7Ci0KLQlmb3IgKGkgPSAwOyBp IDwgbnVtX2NvbmZpZ3M7IGkrKykgewotCQljZmdfdHlwZSA9IFBJTkNGR19VTlBBQ0tfVFlQRShj b25maWdzW2ldKTsKLQkJY2ZnX3ZhbHVlID0gUElOQ0ZHX1VOUEFDS19WQUxVRShjb25maWdzW2ld KTsKLQotCQlzd2l0Y2ggKGNmZ190eXBlKSB7Ci0JCWNhc2UgUElOQ0ZHX1RZUEVfUFVEOgotCQkJ LyogZmlyc3Qgc2V0IHB1bGwgZW5hYmxlL2Rpc2FibGUgYml0ICovCi0JCQlkYXRhID0gcmVhZGwo YmFzZSArIEdQSU9fUEUpOwotCQkJZGF0YSAmPSB+KDEgPDwgcGluKTsKLQkJCWlmIChjZmdfdmFs dWUpCi0JCQkJZGF0YSB8PSAoMSA8PCBwaW4pOwotCQkJd3JpdGVsKGRhdGEsIGJhc2UgKyBHUElP X1BFKTsKLQotCQkJLyogdGhlbiBzZXQgcHVsbCB1cC9kb3duIGJpdCAqLwotCQkJZGF0YSA9IHJl YWRsKGJhc2UgKyBHUElPX1BTKTsKLQkJCWRhdGEgJj0gfigxIDw8IHBpbik7Ci0JCQlpZiAoY2Zn X3ZhbHVlID09IDIpCi0JCQkJZGF0YSB8PSAoMSA8PCBwaW4pOwotCQkJd3JpdGVsKGRhdGEsIGJh c2UgKyBHUElPX1BTKTsKLQkJCWJyZWFrOwotCi0JCWNhc2UgUElOQ0ZHX1RZUEVfRFJWOgotCQkJ Lyogc2V0IHRoZSBmaXJzdCBiaXQgb2YgdGhlIGRyaXZlIHN0cmVuZ3RoICovCi0JCQlkYXRhID0g cmVhZGwoYmFzZSArIEdQSU9fRFMwKTsKLQkJCWRhdGEgJj0gfigxIDw8IHBpbik7Ci0JCQlkYXRh IHw9ICgoY2ZnX3ZhbHVlICYgMSkgPDwgcGluKTsKLQkJCXdyaXRlbChkYXRhLCBiYXNlICsgR1BJ T19EUzApOwotCQkJY2ZnX3ZhbHVlID4+PSAxOwotCi0JCQkvKiBzZXQgdGhlIHNlY29uZCBiaXQg b2YgdGhlIGRyaXZlciBzdHJlbmd0aCAqLwotCQkJZGF0YSA9IHJlYWRsKGJhc2UgKyBHUElPX0RT MSk7Ci0JCQlkYXRhICY9IH4oMSA8PCBwaW4pOwotCQkJZGF0YSB8PSAoKGNmZ192YWx1ZSAmIDEp IDw8IHBpbik7Ci0JCQl3cml0ZWwoZGF0YSwgYmFzZSArIEdQSU9fRFMxKTsKLQkJCWJyZWFrOwot CQljYXNlIFBJTkNGR19UWVBFX1NLRVdfUkFURToKLQkJCWRhdGEgPSByZWFkbChiYXNlICsgR1BJ T19TUik7Ci0JCQlkYXRhICY9IH4oMSA8PCBwaW4pOwotCQkJZGF0YSB8PSAoKGNmZ192YWx1ZSAm IDEpIDw8IHBpbik7Ci0JCQl3cml0ZWwoZGF0YSwgYmFzZSArIEdQSU9fU1IpOwotCQkJYnJlYWs7 Ci0JCWNhc2UgUElOQ0ZHX1RZUEVfSU5QVVRfVFlQRToKLQkJCWRhdGEgPSByZWFkbChiYXNlICsg R1BJT19UWVBFKTsKLQkJCWRhdGEgJj0gfigxIDw8IHBpbik7Ci0JCQlkYXRhIHw9ICgoY2ZnX3Zh bHVlICYgMSkgPDwgcGluKTsKLQkJCXdyaXRlbChkYXRhLCBiYXNlICsgR1BJT19UWVBFKTsKLQkJ CWJyZWFrOwotCQlkZWZhdWx0OgotCQkJV0FSTl9PTigxKTsKLQkJCXJldHVybiAtRUlOVkFMOwot CQl9Ci0JfSAvKiBmb3IgZWFjaCBjb25maWcgKi8KLQotCXJldHVybiAwOwotfQotCi0vKiBnZXQg dGhlIHBpbiBjb25maWcgc2V0dGluZ3MgZm9yIGEgc3BlY2lmaWVkIHBpbiAqLwotc3RhdGljIGlu dCBleHlub3M1NDQwX3BpbmNvbmZfZ2V0KHN0cnVjdCBwaW5jdHJsX2RldiAqcGN0bGRldiwgdW5z aWduZWQgaW50IHBpbiwKLQkJCQkJdW5zaWduZWQgbG9uZyAqY29uZmlnKQotewotCXN0cnVjdCBl eHlub3M1NDQwX3BpbmN0cmxfcHJpdl9kYXRhICpwcml2OwotCXZvaWQgX19pb21lbSAqYmFzZTsK LQllbnVtIHBpbmNmZ190eXBlIGNmZ190eXBlID0gUElOQ0ZHX1VOUEFDS19UWVBFKCpjb25maWcp OwotCXUzMiBkYXRhOwotCi0JcHJpdiA9IHBpbmN0cmxfZGV2X2dldF9kcnZkYXRhKHBjdGxkZXYp OwotCWJhc2UgPSBwcml2LT5yZWdfYmFzZTsKLQotCXN3aXRjaCAoY2ZnX3R5cGUpIHsKLQljYXNl IFBJTkNGR19UWVBFX1BVRDoKLQkJZGF0YSA9IHJlYWRsKGJhc2UgKyBHUElPX1BFKTsKLQkJZGF0 YSA9IChkYXRhID4+IHBpbikgJiAxOwotCQlpZiAoIWRhdGEpCi0JCQkqY29uZmlnID0gMDsKLQkJ ZWxzZQotCQkJKmNvbmZpZyA9ICgocmVhZGwoYmFzZSArIEdQSU9fUFMpID4+IHBpbikgJiAxKSAr IDE7Ci0JCWJyZWFrOwotCWNhc2UgUElOQ0ZHX1RZUEVfRFJWOgotCQlkYXRhID0gcmVhZGwoYmFz ZSArIEdQSU9fRFMwKTsKLQkJZGF0YSA9IChkYXRhID4+IHBpbikgJiAxOwotCQkqY29uZmlnID0g ZGF0YTsKLQkJZGF0YSA9IHJlYWRsKGJhc2UgKyBHUElPX0RTMSk7Ci0JCWRhdGEgPSAoZGF0YSA+ PiBwaW4pICYgMTsKLQkJKmNvbmZpZyB8PSAoZGF0YSA8PCAxKTsKLQkJYnJlYWs7Ci0JY2FzZSBQ SU5DRkdfVFlQRV9TS0VXX1JBVEU6Ci0JCWRhdGEgPSByZWFkbChiYXNlICsgR1BJT19TUik7Ci0J CSpjb25maWcgPSAoZGF0YSA+PiBwaW4pICYgMTsKLQkJYnJlYWs7Ci0JY2FzZSBQSU5DRkdfVFlQ RV9JTlBVVF9UWVBFOgotCQlkYXRhID0gcmVhZGwoYmFzZSArIEdQSU9fVFlQRSk7Ci0JCSpjb25m aWcgPSAoZGF0YSA+PiBwaW4pICYgMTsKLQkJYnJlYWs7Ci0JZGVmYXVsdDoKLQkJV0FSTl9PTigx KTsKLQkJcmV0dXJuIC1FSU5WQUw7Ci0JfQotCi0JcmV0dXJuIDA7Ci19Ci0KLS8qIHNldCB0aGUg cGluIGNvbmZpZyBzZXR0aW5ncyBmb3IgYSBzcGVjaWZpZWQgcGluIGdyb3VwICovCi1zdGF0aWMg aW50IGV4eW5vczU0NDBfcGluY29uZl9ncm91cF9zZXQoc3RydWN0IHBpbmN0cmxfZGV2ICpwY3Rs ZGV2LAotCQkJdW5zaWduZWQgZ3JvdXAsIHVuc2lnbmVkIGxvbmcgKmNvbmZpZ3MsCi0JCQl1bnNp Z25lZCBudW1fY29uZmlncykKLXsKLQlzdHJ1Y3QgZXh5bm9zNTQ0MF9waW5jdHJsX3ByaXZfZGF0 YSAqcHJpdjsKLQljb25zdCB1bnNpZ25lZCBpbnQgKnBpbnM7Ci0JdW5zaWduZWQgaW50IGNudDsK LQotCXByaXYgPSBwaW5jdHJsX2Rldl9nZXRfZHJ2ZGF0YShwY3RsZGV2KTsKLQlwaW5zID0gcHJp di0+cGluX2dyb3Vwc1tncm91cF0ucGluczsKLQotCWZvciAoY250ID0gMDsgY250IDwgcHJpdi0+ cGluX2dyb3Vwc1tncm91cF0ubnVtX3BpbnM7IGNudCsrKQotCQlleHlub3M1NDQwX3BpbmNvbmZf c2V0KHBjdGxkZXYsIHBpbnNbY250XSwgY29uZmlncywKLQkJCQkgICAgICAgbnVtX2NvbmZpZ3Mp OwotCi0JcmV0dXJuIDA7Ci19Ci0KLS8qIGdldCB0aGUgcGluIGNvbmZpZyBzZXR0aW5ncyBmb3Ig YSBzcGVjaWZpZWQgcGluIGdyb3VwICovCi1zdGF0aWMgaW50IGV4eW5vczU0NDBfcGluY29uZl9n cm91cF9nZXQoc3RydWN0IHBpbmN0cmxfZGV2ICpwY3RsZGV2LAotCQkJCXVuc2lnbmVkIGludCBn cm91cCwgdW5zaWduZWQgbG9uZyAqY29uZmlnKQotewotCXN0cnVjdCBleHlub3M1NDQwX3BpbmN0 cmxfcHJpdl9kYXRhICpwcml2OwotCWNvbnN0IHVuc2lnbmVkIGludCAqcGluczsKLQotCXByaXYg PSBwaW5jdHJsX2Rldl9nZXRfZHJ2ZGF0YShwY3RsZGV2KTsKLQlwaW5zID0gcHJpdi0+cGluX2dy b3Vwc1tncm91cF0ucGluczsKLQlleHlub3M1NDQwX3BpbmNvbmZfZ2V0KHBjdGxkZXYsIHBpbnNb MF0sIGNvbmZpZyk7Ci0JcmV0dXJuIDA7Ci19Ci0KLS8qIGxpc3Qgb2YgcGluY29uZmlnIGNhbGxi YWNrcyBmb3IgcGluY29uZmlnIHZlcnRpY2FsIGluIHRoZSBwaW5jdHJsIGNvZGUgKi8KLXN0YXRp YyBjb25zdCBzdHJ1Y3QgcGluY29uZl9vcHMgZXh5bm9zNTQ0MF9waW5jb25mX29wcyA9IHsKLQku cGluX2NvbmZpZ19nZXQJCT0gZXh5bm9zNTQ0MF9waW5jb25mX2dldCwKLQkucGluX2NvbmZpZ19z ZXQJCT0gZXh5bm9zNTQ0MF9waW5jb25mX3NldCwKLQkucGluX2NvbmZpZ19ncm91cF9nZXQJPSBl eHlub3M1NDQwX3BpbmNvbmZfZ3JvdXBfZ2V0LAotCS5waW5fY29uZmlnX2dyb3VwX3NldAk9IGV4 eW5vczU0NDBfcGluY29uZl9ncm91cF9zZXQsCi19OwotCi0vKiBncGlvbGliIGdwaW9fc2V0IGNh bGxiYWNrIGZ1bmN0aW9uICovCi1zdGF0aWMgdm9pZCBleHlub3M1NDQwX2dwaW9fc2V0KHN0cnVj dCBncGlvX2NoaXAgKmdjLCB1bnNpZ25lZCBvZmZzZXQsIGludCB2YWx1ZSkKLXsKLQlzdHJ1Y3Qg ZXh5bm9zNTQ0MF9waW5jdHJsX3ByaXZfZGF0YSAqcHJpdiA9IGdwaW9jaGlwX2dldF9kYXRhKGdj KTsKLQl2b2lkIF9faW9tZW0gKmJhc2UgPSBwcml2LT5yZWdfYmFzZTsKLQl1MzIgZGF0YTsKLQot CWRhdGEgPSByZWFkbChiYXNlICsgR1BJT19WQUwpOwotCWRhdGEgJj0gfigxIDw8IG9mZnNldCk7 Ci0JaWYgKHZhbHVlKQotCQlkYXRhIHw9IDEgPDwgb2Zmc2V0OwotCXdyaXRlbChkYXRhLCBiYXNl ICsgR1BJT19WQUwpOwotfQotCi0vKiBncGlvbGliIGdwaW9fZ2V0IGNhbGxiYWNrIGZ1bmN0aW9u ICovCi1zdGF0aWMgaW50IGV4eW5vczU0NDBfZ3Bpb19nZXQoc3RydWN0IGdwaW9fY2hpcCAqZ2Ms IHVuc2lnbmVkIG9mZnNldCkKLXsKLQlzdHJ1Y3QgZXh5bm9zNTQ0MF9waW5jdHJsX3ByaXZfZGF0 YSAqcHJpdiA9IGdwaW9jaGlwX2dldF9kYXRhKGdjKTsKLQl2b2lkIF9faW9tZW0gKmJhc2UgPSBw cml2LT5yZWdfYmFzZTsKLQl1MzIgZGF0YTsKLQotCWRhdGEgPSByZWFkbChiYXNlICsgR1BJT19J Tik7Ci0JZGF0YSA+Pj0gb2Zmc2V0OwotCWRhdGEgJj0gMTsKLQlyZXR1cm4gZGF0YTsKLX0KLQot LyogZ3Bpb2xpYiBncGlvX2RpcmVjdGlvbl9pbnB1dCBjYWxsYmFjayBmdW5jdGlvbiAqLwotc3Rh dGljIGludCBleHlub3M1NDQwX2dwaW9fZGlyZWN0aW9uX2lucHV0KHN0cnVjdCBncGlvX2NoaXAg KmdjLCB1bnNpZ25lZCBvZmZzZXQpCi17Ci0Jc3RydWN0IGV4eW5vczU0NDBfcGluY3RybF9wcml2 X2RhdGEgKnByaXYgPSBncGlvY2hpcF9nZXRfZGF0YShnYyk7Ci0Jdm9pZCBfX2lvbWVtICpiYXNl ID0gcHJpdi0+cmVnX2Jhc2U7Ci0JdTMyIGRhdGE7Ci0KLQkvKiBmaXJzdCBkaXNhYmxlIHRoZSBk YXRhIG91dHB1dCBlbmFibGUgb24gdGhpcyBwaW4gKi8KLQlkYXRhID0gcmVhZGwoYmFzZSArIEdQ SU9fT0UpOwotCWRhdGEgJj0gfigxIDw8IG9mZnNldCk7Ci0Jd3JpdGVsKGRhdGEsIGJhc2UgKyBH UElPX09FKTsKLQotCS8qIG5vdyBlbmFibGUgaW5wdXQgb24gdGhpcyBwaW4gKi8KLQlkYXRhID0g IHJlYWRsKGJhc2UgKyBHUElPX0lFKTsKLQlkYXRhIHw9IDEgPDwgb2Zmc2V0OwotCXdyaXRlbChk YXRhLCBiYXNlICsgR1BJT19JRSk7Ci0JcmV0dXJuIDA7Ci19Ci0KLS8qIGdwaW9saWIgZ3Bpb19k aXJlY3Rpb25fb3V0cHV0IGNhbGxiYWNrIGZ1bmN0aW9uICovCi1zdGF0aWMgaW50IGV4eW5vczU0 NDBfZ3Bpb19kaXJlY3Rpb25fb3V0cHV0KHN0cnVjdCBncGlvX2NoaXAgKmdjLCB1bnNpZ25lZCBv ZmZzZXQsCi0JCQkJCQkJaW50IHZhbHVlKQotewotCXN0cnVjdCBleHlub3M1NDQwX3BpbmN0cmxf cHJpdl9kYXRhICpwcml2ID0gZ3Bpb2NoaXBfZ2V0X2RhdGEoZ2MpOwotCXZvaWQgX19pb21lbSAq YmFzZSA9IHByaXYtPnJlZ19iYXNlOwotCXUzMiBkYXRhOwotCi0JZXh5bm9zNTQ0MF9ncGlvX3Nl dChnYywgb2Zmc2V0LCB2YWx1ZSk7Ci0KLQkvKiBmaXJzdCBkaXNhYmxlIHRoZSBkYXRhIGlucHV0 IGVuYWJsZSBvbiB0aGlzIHBpbiAqLwotCWRhdGEgPSByZWFkbChiYXNlICsgR1BJT19JRSk7Ci0J ZGF0YSAmPSB+KDEgPDwgb2Zmc2V0KTsKLQl3cml0ZWwoZGF0YSwgYmFzZSArIEdQSU9fSUUpOwot Ci0JLyogbm93IGVuYWJsZSBvdXRwdXQgb24gdGhpcyBwaW4gKi8KLQlkYXRhID0gIHJlYWRsKGJh c2UgKyBHUElPX09FKTsKLQlkYXRhIHw9IDEgPDwgb2Zmc2V0OwotCXdyaXRlbChkYXRhLCBiYXNl ICsgR1BJT19PRSk7Ci0JcmV0dXJuIDA7Ci19Ci0KLS8qIGdwaW9saWIgZ3Bpb190b19pcnEgY2Fs bGJhY2sgZnVuY3Rpb24gKi8KLXN0YXRpYyBpbnQgZXh5bm9zNTQ0MF9ncGlvX3RvX2lycShzdHJ1 Y3QgZ3Bpb19jaGlwICpnYywgdW5zaWduZWQgb2Zmc2V0KQotewotCXN0cnVjdCBleHlub3M1NDQw X3BpbmN0cmxfcHJpdl9kYXRhICpwcml2ID0gZ3Bpb2NoaXBfZ2V0X2RhdGEoZ2MpOwotCXVuc2ln bmVkIGludCB2aXJxOwotCi0JaWYgKG9mZnNldCA8IDE2IHx8IG9mZnNldCA+IDIzKQotCQlyZXR1 cm4gLUVOWElPOwotCi0JaWYgKCFwcml2LT5pcnFfZG9tYWluKQotCQlyZXR1cm4gLUVOWElPOwot Ci0JdmlycSA9IGlycV9jcmVhdGVfbWFwcGluZyhwcml2LT5pcnFfZG9tYWluLCBvZmZzZXQgLSAx Nik7Ci0JcmV0dXJuIHZpcnEgPyA6IC1FTlhJTzsKLX0KLQotLyogcGFyc2UgdGhlIHBpbiBudW1i ZXJzIGxpc3RlZCBpbiB0aGUgJ3NhbXN1bmcsZXh5bm9zNTQ0MC1waW5zJyBwcm9wZXJ0eSAqLwot c3RhdGljIGludCBleHlub3M1NDQwX3BpbmN0cmxfcGFyc2VfZHRfcGlucyhzdHJ1Y3QgcGxhdGZv cm1fZGV2aWNlICpwZGV2LAotCQkJc3RydWN0IGRldmljZV9ub2RlICpjZmdfbnAsIHVuc2lnbmVk IGludCAqKnBpbl9saXN0LAotCQkJdW5zaWduZWQgaW50ICpucGlucykKLXsKLQlzdHJ1Y3QgZGV2 aWNlICpkZXYgPSAmcGRldi0+ZGV2OwotCXN0cnVjdCBwcm9wZXJ0eSAqcHJvcDsKLQotCXByb3Ag PSBvZl9maW5kX3Byb3BlcnR5KGNmZ19ucCwgInNhbXN1bmcsZXh5bm9zNTQ0MC1waW5zIiwgTlVM TCk7Ci0JaWYgKCFwcm9wKQotCQlyZXR1cm4gLUVOT0VOVDsKLQotCSpucGlucyA9IHByb3AtPmxl bmd0aCAvIHNpemVvZih1bnNpZ25lZCBsb25nKTsKLQlpZiAoISpucGlucykgewotCQlkZXZfZXJy KGRldiwgImludmFsaWQgcGluIGxpc3QgaW4gJXMgbm9kZSIsIGNmZ19ucC0+bmFtZSk7Ci0JCXJl dHVybiAtRUlOVkFMOwotCX0KLQotCSpwaW5fbGlzdCA9IGRldm1fa3phbGxvYyhkZXYsICpucGlu cyAqIHNpemVvZigqKnBpbl9saXN0KSwgR0ZQX0tFUk5FTCk7Ci0JaWYgKCEqcGluX2xpc3QpCi0J CXJldHVybiAtRU5PTUVNOwotCi0JcmV0dXJuIG9mX3Byb3BlcnR5X3JlYWRfdTMyX2FycmF5KGNm Z19ucCwgInNhbXN1bmcsZXh5bm9zNTQ0MC1waW5zIiwKLQkJCSpwaW5fbGlzdCwgKm5waW5zKTsK LX0KLQotLyoKLSAqIFBhcnNlIHRoZSBpbmZvcm1hdGlvbiBhYm91dCBhbGwgdGhlIGF2YWlsYWJs ZSBwaW4gZ3JvdXBzIGFuZCBwaW4gZnVuY3Rpb25zCi0gKiBmcm9tIGRldmljZSBub2RlIG9mIHRo ZSBwaW4tY29udHJvbGxlci4KLSAqLwotc3RhdGljIGludCBleHlub3M1NDQwX3BpbmN0cmxfcGFy c2VfZHQoc3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRldiwKLQkJCQlzdHJ1Y3QgZXh5bm9zNTQ0 MF9waW5jdHJsX3ByaXZfZGF0YSAqcHJpdikKLXsKLQlzdHJ1Y3QgZGV2aWNlICpkZXYgPSAmcGRl di0+ZGV2OwotCXN0cnVjdCBkZXZpY2Vfbm9kZSAqZGV2X25wID0gZGV2LT5vZl9ub2RlOwotCXN0 cnVjdCBkZXZpY2Vfbm9kZSAqY2ZnX25wOwotCXN0cnVjdCBleHlub3M1NDQwX3Bpbl9ncm91cCAq Z3JvdXBzLCAqZ3JwOwotCXN0cnVjdCBleHlub3M1NDQwX3BteF9mdW5jICpmdW5jdGlvbnMsICpm dW5jOwotCXVuc2lnbmVkICpwaW5fbGlzdDsKLQl1bnNpZ25lZCBpbnQgbnBpbnMsIGdycF9jbnQs IGZ1bmNfaWR4ID0gMDsKLQljaGFyICpnbmFtZSwgKmZuYW1lOwotCWludCByZXQ7Ci0KLQlncnBf Y250ID0gb2ZfZ2V0X2NoaWxkX2NvdW50KGRldl9ucCk7Ci0JaWYgKCFncnBfY250KQotCQlyZXR1 cm4gLUVJTlZBTDsKLQotCWdyb3VwcyA9IGRldm1fa3phbGxvYyhkZXYsIGdycF9jbnQgKiBzaXpl b2YoKmdyb3VwcyksIEdGUF9LRVJORUwpOwotCWlmICghZ3JvdXBzKQotCQlyZXR1cm4gLUVJTlZB TDsKLQotCWdycCA9IGdyb3VwczsKLQotCWZ1bmN0aW9ucyA9IGRldm1fa3phbGxvYyhkZXYsIGdy cF9jbnQgKiBzaXplb2YoKmZ1bmN0aW9ucyksIEdGUF9LRVJORUwpOwotCWlmICghZnVuY3Rpb25z KQotCQlyZXR1cm4gLUVJTlZBTDsKLQotCWZ1bmMgPSBmdW5jdGlvbnM7Ci0KLQkvKgotCSAqIEl0 ZXJhdGUgb3ZlciBhbGwgdGhlIGNoaWxkIG5vZGVzIG9mIHRoZSBwaW4gY29udHJvbGxlciBub2Rl Ci0JICogYW5kIGNyZWF0ZSBwaW4gZ3JvdXBzIGFuZCBwaW4gZnVuY3Rpb24gbGlzdHMuCi0JICov Ci0JZm9yX2VhY2hfY2hpbGRfb2Zfbm9kZShkZXZfbnAsIGNmZ19ucCkgewotCQl1MzIgZnVuY3Rp b247Ci0KLQkJcmV0ID0gZXh5bm9zNTQ0MF9waW5jdHJsX3BhcnNlX2R0X3BpbnMocGRldiwgY2Zn X25wLAotCQkJCQkmcGluX2xpc3QsICZucGlucyk7Ci0JCWlmIChyZXQpIHsKLQkJCWduYW1lID0g TlVMTDsKLQkJCWdvdG8gc2tpcF90b19waW5fZnVuY3Rpb247Ci0JCX0KLQotCQkvKiBkZXJpdmUg cGluIGdyb3VwIG5hbWUgZnJvbSB0aGUgbm9kZSBuYW1lICovCi0JCWduYW1lID0gZGV2bV9rYXNw cmludGYoZGV2LCBHRlBfS0VSTkVMLAotCQkJCSAgICAgICAiJXMlcyIsIGNmZ19ucC0+bmFtZSwg R1JPVVBfU1VGRklYKTsKLQkJaWYgKCFnbmFtZSkKLQkJCXJldHVybiAtRU5PTUVNOwotCi0JCWdy cC0+bmFtZSA9IGduYW1lOwotCQlncnAtPnBpbnMgPSBwaW5fbGlzdDsKLQkJZ3JwLT5udW1fcGlu cyA9IG5waW5zOwotCQlncnArKzsKLQotc2tpcF90b19waW5fZnVuY3Rpb246Ci0JCXJldCA9IG9m X3Byb3BlcnR5X3JlYWRfdTMyKGNmZ19ucCwgInNhbXN1bmcsZXh5bm9zNTQ0MC1waW4tZnVuY3Rp b24iLAotCQkJCQkJJmZ1bmN0aW9uKTsKLQkJaWYgKHJldCkKLQkJCWNvbnRpbnVlOwotCi0JCS8q IGRlcml2ZSBmdW5jdGlvbiBuYW1lIGZyb20gdGhlIG5vZGUgbmFtZSAqLwotCQlmbmFtZSA9IGRl dm1fa2FzcHJpbnRmKGRldiwgR0ZQX0tFUk5FTCwKLQkJCQkgICAgICAgIiVzJXMiLCBjZmdfbnAt Pm5hbWUsIEZVTkNUSU9OX1NVRkZJWCk7Ci0JCWlmICghZm5hbWUpCi0JCQlyZXR1cm4gLUVOT01F TTsKLQotCQlmdW5jLT5uYW1lID0gZm5hbWU7Ci0JCWZ1bmMtPmdyb3VwcyA9IGRldm1fa3phbGxv YyhkZXYsIHNpemVvZihjaGFyICopLCBHRlBfS0VSTkVMKTsKLQkJaWYgKCFmdW5jLT5ncm91cHMp Ci0JCQlyZXR1cm4gLUVOT01FTTsKLQkJZnVuYy0+Z3JvdXBzWzBdID0gZ25hbWU7Ci0JCWZ1bmMt Pm51bV9ncm91cHMgPSBnbmFtZSA/IDEgOiAwOwotCQlmdW5jLT5mdW5jdGlvbiA9IGZ1bmN0aW9u OwotCQlmdW5jKys7Ci0JCWZ1bmNfaWR4Kys7Ci0JfQotCi0JcHJpdi0+cGluX2dyb3VwcyA9IGdy b3VwczsKLQlwcml2LT5ucl9ncm91cHMgPSBncnBfY250OwotCXByaXYtPnBteF9mdW5jdGlvbnMg PSBmdW5jdGlvbnM7Ci0JcHJpdi0+bnJfZnVuY3Rpb25zID0gZnVuY19pZHg7Ci0JcmV0dXJuIDA7 Ci19Ci0KLS8qIHJlZ2lzdGVyIHRoZSBwaW5jdHJsIGludGVyZmFjZSB3aXRoIHRoZSBwaW5jdHJs IHN1YnN5c3RlbSAqLwotc3RhdGljIGludCBleHlub3M1NDQwX3BpbmN0cmxfcmVnaXN0ZXIoc3Ry dWN0IHBsYXRmb3JtX2RldmljZSAqcGRldiwKLQkJCQlzdHJ1Y3QgZXh5bm9zNTQ0MF9waW5jdHJs X3ByaXZfZGF0YSAqcHJpdikKLXsKLQlzdHJ1Y3QgZGV2aWNlICpkZXYgPSAmcGRldi0+ZGV2Owot CXN0cnVjdCBwaW5jdHJsX2Rlc2MgKmN0cmxkZXNjOwotCXN0cnVjdCBwaW5jdHJsX2RldiAqcGN0 bF9kZXY7Ci0Jc3RydWN0IHBpbmN0cmxfcGluX2Rlc2MgKnBpbmRlc2MsICpwZGVzYzsKLQljaGFy ICpwaW5fbmFtZXM7Ci0JaW50IHBpbiwgcmV0OwotCi0JY3RybGRlc2MgPSBkZXZtX2t6YWxsb2Mo ZGV2LCBzaXplb2YoKmN0cmxkZXNjKSwgR0ZQX0tFUk5FTCk7Ci0JaWYgKCFjdHJsZGVzYykKLQkJ cmV0dXJuIC1FTk9NRU07Ci0KLQljdHJsZGVzYy0+bmFtZSA9ICJleHlub3M1NDQwLXBpbmN0cmwi OwotCWN0cmxkZXNjLT5vd25lciA9IFRISVNfTU9EVUxFOwotCWN0cmxkZXNjLT5wY3Rsb3BzID0g JmV4eW5vczU0NDBfcGN0cmxfb3BzOwotCWN0cmxkZXNjLT5wbXhvcHMgPSAmZXh5bm9zNTQ0MF9w aW5tdXhfb3BzOwotCWN0cmxkZXNjLT5jb25mb3BzID0gJmV4eW5vczU0NDBfcGluY29uZl9vcHM7 Ci0KLQlwaW5kZXNjID0gZGV2bV9remFsbG9jKCZwZGV2LT5kZXYsIHNpemVvZigqcGluZGVzYykg KgotCQkJCUVYWU5PUzU0NDBfTUFYX1BJTlMsIEdGUF9LRVJORUwpOwotCWlmICghcGluZGVzYykK LQkJcmV0dXJuIC1FTk9NRU07Ci0JY3RybGRlc2MtPnBpbnMgPSBwaW5kZXNjOwotCWN0cmxkZXNj LT5ucGlucyA9IEVYWU5PUzU0NDBfTUFYX1BJTlM7Ci0KLQkvKiBkeW5hbWljYWxseSBwb3B1bGF0 ZSB0aGUgcGluIG51bWJlciBhbmQgcGluIG5hbWUgZm9yIHBpbmRlc2MgKi8KLQlmb3IgKHBpbiA9 IDAsIHBkZXNjID0gcGluZGVzYzsgcGluIDwgY3RybGRlc2MtPm5waW5zOyBwaW4rKywgcGRlc2Mr KykKLQkJcGRlc2MtPm51bWJlciA9IHBpbjsKLQotCS8qCi0JICogYWxsb2NhdGUgc3BhY2UgZm9y IHN0b3JpbmcgdGhlIGR5bmFtaWNhbGx5IGdlbmVyYXRlZCBuYW1lcyBmb3IgYWxsCi0JICogdGhl IHBpbnMgd2hpY2ggYmVsb25nIHRvIHRoaXMgcGluLWNvbnRyb2xsZXIuCi0JICovCi0JcGluX25h bWVzID0gZGV2bV9remFsbG9jKCZwZGV2LT5kZXYsIHNpemVvZihjaGFyKSAqIFBJTl9OQU1FX0xF TkdUSCAqCi0JCQkJCWN0cmxkZXNjLT5ucGlucywgR0ZQX0tFUk5FTCk7Ci0JaWYgKCFwaW5fbmFt ZXMpCi0JCXJldHVybiAtRU5PTUVNOwotCi0JLyogZm9yIGVhY2ggcGluLCBzZXQgdGhlIG5hbWUg b2YgdGhlIHBpbiAqLwotCWZvciAocGluID0gMDsgcGluIDwgY3RybGRlc2MtPm5waW5zOyBwaW4r KykgewotCQlzbnByaW50ZihwaW5fbmFtZXMsIDYsICJncGlvJTAyZCIsIHBpbik7Ci0JCXBkZXNj ID0gcGluZGVzYyArIHBpbjsKLQkJcGRlc2MtPm5hbWUgPSBwaW5fbmFtZXM7Ci0JCXBpbl9uYW1l cyArPSBQSU5fTkFNRV9MRU5HVEg7Ci0JfQotCi0JcmV0ID0gZXh5bm9zNTQ0MF9waW5jdHJsX3Bh cnNlX2R0KHBkZXYsIHByaXYpOwotCWlmIChyZXQpCi0JCXJldHVybiByZXQ7Ci0KLQlwY3RsX2Rl diA9IGRldm1fcGluY3RybF9yZWdpc3RlcigmcGRldi0+ZGV2LCBjdHJsZGVzYywgcHJpdik7Ci0J aWYgKElTX0VSUihwY3RsX2RldikpIHsKLQkJZGV2X2VycigmcGRldi0+ZGV2LCAiY291bGQgbm90 IHJlZ2lzdGVyIHBpbmN0cmwgZHJpdmVyXG4iKTsKLQkJcmV0dXJuIFBUUl9FUlIocGN0bF9kZXYp OwotCX0KLQotCXByaXYtPnJhbmdlLm5hbWUgPSAiZXh5bm9zNTQ0MC1wY3RybC1ncGlvLXJhbmdl IjsKLQlwcml2LT5yYW5nZS5pZCA9IDA7Ci0JcHJpdi0+cmFuZ2UuYmFzZSA9IDA7Ci0JcHJpdi0+ cmFuZ2UubnBpbnMgPSBFWFlOT1M1NDQwX01BWF9QSU5TOwotCXByaXYtPnJhbmdlLmdjID0gcHJp di0+Z2M7Ci0JcGluY3RybF9hZGRfZ3Bpb19yYW5nZShwY3RsX2RldiwgJnByaXYtPnJhbmdlKTsK LQlyZXR1cm4gMDsKLX0KLQotLyogcmVnaXN0ZXIgdGhlIGdwaW9saWIgaW50ZXJmYWNlIHdpdGgg dGhlIGdwaW9saWIgc3Vic3lzdGVtICovCi1zdGF0aWMgaW50IGV4eW5vczU0NDBfZ3Bpb2xpYl9y ZWdpc3RlcihzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2LAotCQkJCXN0cnVjdCBleHlub3M1 NDQwX3BpbmN0cmxfcHJpdl9kYXRhICpwcml2KQotewotCXN0cnVjdCBncGlvX2NoaXAgKmdjOwot CWludCByZXQ7Ci0KLQlnYyA9IGRldm1fa3phbGxvYygmcGRldi0+ZGV2LCBzaXplb2YoKmdjKSwg R0ZQX0tFUk5FTCk7Ci0JaWYgKCFnYykKLQkJcmV0dXJuIC1FTk9NRU07Ci0KLQlwcml2LT5nYyA9 IGdjOwotCWdjLT5iYXNlID0gMDsKLQlnYy0+bmdwaW8gPSBFWFlOT1M1NDQwX01BWF9QSU5TOwot CWdjLT5wYXJlbnQgPSAmcGRldi0+ZGV2OwotCWdjLT5zZXQgPSBleHlub3M1NDQwX2dwaW9fc2V0 OwotCWdjLT5nZXQgPSBleHlub3M1NDQwX2dwaW9fZ2V0OwotCWdjLT5kaXJlY3Rpb25faW5wdXQg PSBleHlub3M1NDQwX2dwaW9fZGlyZWN0aW9uX2lucHV0OwotCWdjLT5kaXJlY3Rpb25fb3V0cHV0 ID0gZXh5bm9zNTQ0MF9ncGlvX2RpcmVjdGlvbl9vdXRwdXQ7Ci0JZ2MtPnRvX2lycSA9IGV4eW5v czU0NDBfZ3Bpb190b19pcnE7Ci0JZ2MtPmxhYmVsID0gImdwaW9saWItZXh5bm9zNTQ0MCI7Ci0J Z2MtPm93bmVyID0gVEhJU19NT0RVTEU7Ci0JcmV0ID0gZ3Bpb2NoaXBfYWRkX2RhdGEoZ2MsIHBy aXYpOwotCWlmIChyZXQpIHsKLQkJZGV2X2VycigmcGRldi0+ZGV2LCAiZmFpbGVkIHRvIHJlZ2lz dGVyIGdwaW9fY2hpcCAlcywgZXJyb3IgIgotCQkJCQkiY29kZTogJWRcbiIsIGdjLT5sYWJlbCwg cmV0KTsKLQkJcmV0dXJuIHJldDsKLQl9Ci0KLQlyZXR1cm4gMDsKLX0KLQotLyogdW5yZWdpc3Rl ciB0aGUgZ3Bpb2xpYiBpbnRlcmZhY2Ugd2l0aCB0aGUgZ3Bpb2xpYiBzdWJzeXN0ZW0gKi8KLXN0 YXRpYyBpbnQgZXh5bm9zNTQ0MF9ncGlvbGliX3VucmVnaXN0ZXIoc3RydWN0IHBsYXRmb3JtX2Rl dmljZSAqcGRldiwKLQkJCQlzdHJ1Y3QgZXh5bm9zNTQ0MF9waW5jdHJsX3ByaXZfZGF0YSAqcHJp dikKLXsKLQlncGlvY2hpcF9yZW1vdmUocHJpdi0+Z2MpOwotCXJldHVybiAwOwotfQotCi1zdGF0 aWMgdm9pZCBleHlub3M1NDQwX2dwaW9faXJxX3VubWFzayhzdHJ1Y3QgaXJxX2RhdGEgKmlycWQp Ci17Ci0Jc3RydWN0IGV4eW5vczU0NDBfcGluY3RybF9wcml2X2RhdGEgKmQ7Ci0JdW5zaWduZWQg bG9uZyBncGlvX2ludDsKLQotCWQgPSBpcnFfZGF0YV9nZXRfaXJxX2NoaXBfZGF0YShpcnFkKTsK LQlncGlvX2ludCA9IHJlYWRsKGQtPnJlZ19iYXNlICsgR1BJT19JTlQpOwotCWdwaW9faW50IHw9 IDEgPDwgaXJxZC0+aHdpcnE7Ci0Jd3JpdGVsKGdwaW9faW50LCBkLT5yZWdfYmFzZSArIEdQSU9f SU5UKTsKLX0KLQotc3RhdGljIHZvaWQgZXh5bm9zNTQ0MF9ncGlvX2lycV9tYXNrKHN0cnVjdCBp cnFfZGF0YSAqaXJxZCkKLXsKLQlzdHJ1Y3QgZXh5bm9zNTQ0MF9waW5jdHJsX3ByaXZfZGF0YSAq ZDsKLQl1bnNpZ25lZCBsb25nIGdwaW9faW50OwotCi0JZCA9IGlycV9kYXRhX2dldF9pcnFfY2hp cF9kYXRhKGlycWQpOwotCWdwaW9faW50ID0gcmVhZGwoZC0+cmVnX2Jhc2UgKyBHUElPX0lOVCk7 Ci0JZ3Bpb19pbnQgJj0gfigxIDw8IGlycWQtPmh3aXJxKTsKLQl3cml0ZWwoZ3Bpb19pbnQsIGQt PnJlZ19iYXNlICsgR1BJT19JTlQpOwotfQotCi0vKiBpcnFfY2hpcCBmb3IgZ3BpbyBpbnRlcnJ1 cHRzICovCi1zdGF0aWMgc3RydWN0IGlycV9jaGlwIGV4eW5vczU0NDBfZ3Bpb19pcnFfY2hpcCA9 IHsKLQkubmFtZQkJPSAiZXh5bm9zNTQ0MF9ncGlvX2lycV9jaGlwIiwKLQkuaXJxX3VubWFzawk9 IGV4eW5vczU0NDBfZ3Bpb19pcnFfdW5tYXNrLAotCS5pcnFfbWFzawk9IGV4eW5vczU0NDBfZ3Bp b19pcnFfbWFzaywKLX07Ci0KLS8qIGludGVycnVwdCBoYW5kbGVyIGZvciBHUElPIGludGVycnVw dHMgMC4uNyAqLwotc3RhdGljIGlycXJldHVybl90IGV4eW5vczU0NDBfZ3Bpb19pcnEoaW50IGly cSwgdm9pZCAqZGF0YSkKLXsKLQlzdHJ1Y3QgZXh5bm9zNTQ0MF9ncGlvX2ludHJfZGF0YSAqaW50 ZCA9IGRhdGE7Ci0Jc3RydWN0IGV4eW5vczU0NDBfcGluY3RybF9wcml2X2RhdGEgKmQgPSBpbnRk LT5wcml2OwotCWludCB2aXJxOwotCi0JdmlycSA9IGlycV9saW5lYXJfcmV2bWFwKGQtPmlycV9k b21haW4sIGludGQtPmdwaW9faW50KTsKLQlpZiAoIXZpcnEpCi0JCXJldHVybiBJUlFfTk9ORTsK LQlnZW5lcmljX2hhbmRsZV9pcnEodmlycSk7Ci0JcmV0dXJuIElSUV9IQU5ETEVEOwotfQotCi1z dGF0aWMgaW50IGV4eW5vczU0NDBfZ3Bpb19pcnFfbWFwKHN0cnVjdCBpcnFfZG9tYWluICpoLCB1 bnNpZ25lZCBpbnQgdmlycSwKLQkJCQkJaXJxX2h3X251bWJlcl90IGh3KQotewotCXN0cnVjdCBl eHlub3M1NDQwX3BpbmN0cmxfcHJpdl9kYXRhICpkID0gaC0+aG9zdF9kYXRhOwotCi0JaXJxX3Nl dF9jaGlwX2RhdGEodmlycSwgZCk7Ci0JaXJxX3NldF9jaGlwX2FuZF9oYW5kbGVyKHZpcnEsICZl eHlub3M1NDQwX2dwaW9faXJxX2NoaXAsCi0JCQkJCWhhbmRsZV9sZXZlbF9pcnEpOwotCXJldHVy biAwOwotfQotCi0vKiBpcnEgZG9tYWluIGNhbGxiYWNrcyBmb3IgZ3BpbyBpbnRlcnJ1cHQgY29u dHJvbGxlciAqLwotc3RhdGljIGNvbnN0IHN0cnVjdCBpcnFfZG9tYWluX29wcyBleHlub3M1NDQw X2dwaW9faXJxZF9vcHMgPSB7Ci0JLm1hcAk9IGV4eW5vczU0NDBfZ3Bpb19pcnFfbWFwLAotCS54 bGF0ZQk9IGlycV9kb21haW5feGxhdGVfdHdvY2VsbCwKLX07Ci0KLS8qIHNldHVwIGhhbmRsaW5n IG9mIGdwaW8gaW50ZXJydXB0cyAqLwotc3RhdGljIGludCBleHlub3M1NDQwX2dwaW9faXJxX2lu aXQoc3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRldiwKLQkJCQlzdHJ1Y3QgZXh5bm9zNTQ0MF9w aW5jdHJsX3ByaXZfZGF0YSAqcHJpdikKLXsKLQlzdHJ1Y3QgZGV2aWNlICpkZXYgPSAmcGRldi0+ ZGV2OwotCXN0cnVjdCBleHlub3M1NDQwX2dwaW9faW50cl9kYXRhICppbnRkOwotCWludCBpLCBp cnEsIHJldDsKLQotCWludGQgPSBkZXZtX2t6YWxsb2MoZGV2LCBzaXplb2YoKmludGQpICogRVhZ Tk9TNTQ0MF9NQVhfR1BJT19JTlQsCi0JCQkJCUdGUF9LRVJORUwpOwotCWlmICghaW50ZCkKLQkJ cmV0dXJuIC1FTk9NRU07Ci0KLQlmb3IgKGkgPSAwOyBpIDwgRVhZTk9TNTQ0MF9NQVhfR1BJT19J TlQ7IGkrKykgewotCQlpcnEgPSBpcnFfb2ZfcGFyc2VfYW5kX21hcChkZXYtPm9mX25vZGUsIGkp OwotCQlpZiAoaXJxIDw9IDApIHsKLQkJCWRldl9lcnIoZGV2LCAiaXJxIHBhcnNpbmcgZmFpbGVk XG4iKTsKLQkJCXJldHVybiAtRUlOVkFMOwotCQl9Ci0KLQkJaW50ZC0+Z3Bpb19pbnQgPSBpOwot CQlpbnRkLT5wcml2ID0gcHJpdjsKLQkJcmV0ID0gZGV2bV9yZXF1ZXN0X2lycShkZXYsIGlycSwg ZXh5bm9zNTQ0MF9ncGlvX2lycSwKLQkJCQkJMCwgZGV2X25hbWUoZGV2KSwgaW50ZCsrKTsKLQkJ aWYgKHJldCkgewotCQkJZGV2X2VycihkZXYsICJpcnEgcmVxdWVzdCBmYWlsZWRcbiIpOwotCQkJ cmV0dXJuIC1FTlhJTzsKLQkJfQotCX0KLQotCXByaXYtPmlycV9kb21haW4gPSBpcnFfZG9tYWlu X2FkZF9saW5lYXIoZGV2LT5vZl9ub2RlLAotCQkJCUVYWU5PUzU0NDBfTUFYX0dQSU9fSU5ULAot CQkJCSZleHlub3M1NDQwX2dwaW9faXJxZF9vcHMsIHByaXYpOwotCWlmICghcHJpdi0+aXJxX2Rv bWFpbikgewotCQlkZXZfZXJyKGRldiwgImZhaWxlZCB0byBjcmVhdGUgaXJxIGRvbWFpblxuIik7 Ci0JCXJldHVybiAtRU5YSU87Ci0JfQotCi0JcmV0dXJuIDA7Ci19Ci0KLXN0YXRpYyBpbnQgZXh5 bm9zNTQ0MF9waW5jdHJsX3Byb2JlKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCi17Ci0J c3RydWN0IGRldmljZSAqZGV2ID0gJnBkZXYtPmRldjsKLQlzdHJ1Y3QgZXh5bm9zNTQ0MF9waW5j dHJsX3ByaXZfZGF0YSAqcHJpdjsKLQlzdHJ1Y3QgcmVzb3VyY2UgKnJlczsKLQlpbnQgcmV0Owot Ci0JaWYgKCFkZXYtPm9mX25vZGUpIHsKLQkJZGV2X2VycihkZXYsICJkZXZpY2UgdHJlZSBub2Rl IG5vdCBmb3VuZFxuIik7Ci0JCXJldHVybiAtRU5PREVWOwotCX0KLQotCXByaXYgPSBkZXZtX2t6 YWxsb2MoZGV2LCBzaXplb2YoKnByaXYpLCBHRlBfS0VSTkVMKTsKLQlpZiAoIXByaXYpCi0JCXJl dHVybiAtRU5PTUVNOwotCi0JcmVzID0gcGxhdGZvcm1fZ2V0X3Jlc291cmNlKHBkZXYsIElPUkVT T1VSQ0VfTUVNLCAwKTsKLQlwcml2LT5yZWdfYmFzZSA9IGRldm1faW9yZW1hcF9yZXNvdXJjZSgm cGRldi0+ZGV2LCByZXMpOwotCWlmIChJU19FUlIocHJpdi0+cmVnX2Jhc2UpKQotCQlyZXR1cm4g UFRSX0VSUihwcml2LT5yZWdfYmFzZSk7Ci0KLQlyZXQgPSBleHlub3M1NDQwX2dwaW9saWJfcmVn aXN0ZXIocGRldiwgcHJpdik7Ci0JaWYgKHJldCkKLQkJcmV0dXJuIHJldDsKLQotCXJldCA9IGV4 eW5vczU0NDBfcGluY3RybF9yZWdpc3RlcihwZGV2LCBwcml2KTsKLQlpZiAocmV0KSB7Ci0JCWV4 eW5vczU0NDBfZ3Bpb2xpYl91bnJlZ2lzdGVyKHBkZXYsIHByaXYpOwotCQlyZXR1cm4gcmV0Owot CX0KLQotCXJldCA9IGV4eW5vczU0NDBfZ3Bpb19pcnFfaW5pdChwZGV2LCBwcml2KTsKLQlpZiAo cmV0KSB7Ci0JCWRldl9lcnIoZGV2LCAiZmFpbGVkIHRvIHNldHVwIGdwaW8gaW50ZXJydXB0c1xu Iik7Ci0JCXJldHVybiByZXQ7Ci0JfQotCi0JcGxhdGZvcm1fc2V0X2RydmRhdGEocGRldiwgcHJp dik7Ci0JZGV2X2luZm8oZGV2LCAiRVhZTk9TNTQ0MCBwaW5jdHJsIGRyaXZlciByZWdpc3RlcmVk XG4iKTsKLQlyZXR1cm4gMDsKLX0KLQotc3RhdGljIGNvbnN0IHN0cnVjdCBvZl9kZXZpY2VfaWQg ZXh5bm9zNTQ0MF9waW5jdHJsX2R0X21hdGNoW10gPSB7Ci0JeyAuY29tcGF0aWJsZSA9ICJzYW1z dW5nLGV4eW5vczU0NDAtcGluY3RybCIgfSwKLQl7fSwKLX07Ci0KLXN0YXRpYyBzdHJ1Y3QgcGxh dGZvcm1fZHJpdmVyIGV4eW5vczU0NDBfcGluY3RybF9kcml2ZXIgPSB7Ci0JLnByb2JlCQk9IGV4 eW5vczU0NDBfcGluY3RybF9wcm9iZSwKLQkuZHJpdmVyID0gewotCQkubmFtZQk9ICJleHlub3M1 NDQwLXBpbmN0cmwiLAotCQkub2ZfbWF0Y2hfdGFibGUgPSBleHlub3M1NDQwX3BpbmN0cmxfZHRf bWF0Y2gsCi0JCS5zdXBwcmVzc19iaW5kX2F0dHJzID0gdHJ1ZSwKLQl9LAotfTsKLQotc3RhdGlj IGludCBfX2luaXQgZXh5bm9zNTQ0MF9waW5jdHJsX2Rydl9yZWdpc3Rlcih2b2lkKQotewotCXJl dHVybiBwbGF0Zm9ybV9kcml2ZXJfcmVnaXN0ZXIoJmV4eW5vczU0NDBfcGluY3RybF9kcml2ZXIp OwotfQotcG9zdGNvcmVfaW5pdGNhbGwoZXh5bm9zNTQ0MF9waW5jdHJsX2Rydl9yZWdpc3Rlcik7 Cg== From mboxrd@z Thu Jan 1 00:00:00 1970 From: krzk@kernel.org (Krzysztof Kozlowski) Date: Tue, 24 Apr 2018 22:32:36 +0200 Subject: [RFC 07/10] pinctrl: samsung: Remove support for Exynos5440 In-Reply-To: <20180424203239.21885-1-krzk@kernel.org> References: <20180424203239.21885-1-krzk@kernel.org> Message-ID: <20180424203239.21885-8-krzk@kernel.org> To: linux-arm-kernel@lists.infradead.org List-Id: linux-arm-kernel.lists.infradead.org The Exynos5440 is not actively developed, there are no development boards available and probably there are no real products with it. Remove wide-tree support for Exynos5440. Signed-off-by: Krzysztof Kozlowski --- drivers/pinctrl/samsung/Kconfig | 10 +- drivers/pinctrl/samsung/Makefile | 1 - drivers/pinctrl/samsung/pinctrl-exynos5440.c | 1005 -------------------------- 3 files changed, 2 insertions(+), 1014 deletions(-) delete mode 100644 drivers/pinctrl/samsung/pinctrl-exynos5440.c diff --git a/drivers/pinctrl/samsung/Kconfig b/drivers/pinctrl/samsung/Kconfig index 11b5eeb14c4a..425fadd6c346 100644 --- a/drivers/pinctrl/samsung/Kconfig +++ b/drivers/pinctrl/samsung/Kconfig @@ -8,26 +8,20 @@ config PINCTRL_SAMSUNG select PINCONF config PINCTRL_EXYNOS - bool "Pinctrl driver data for Samsung EXYNOS SoCs other than 5440" + bool "Pinctrl driver data for Samsung EXYNOS SoCs" depends on OF && GPIOLIB && (ARCH_EXYNOS || ARCH_S5PV210) select PINCTRL_SAMSUNG select PINCTRL_EXYNOS_ARM if ARM && (ARCH_EXYNOS || ARCH_S5PV210) select PINCTRL_EXYNOS_ARM64 if ARM64 && ARCH_EXYNOS config PINCTRL_EXYNOS_ARM - bool "ARMv7-specific pinctrl driver data for Exynos (except Exynos5440)" if COMPILE_TEST + bool "ARMv7-specific pinctrl driver data for Exynos" if COMPILE_TEST depends on PINCTRL_EXYNOS config PINCTRL_EXYNOS_ARM64 bool "ARMv8-specific pinctrl driver data for Exynos" if COMPILE_TEST depends on PINCTRL_EXYNOS -config PINCTRL_EXYNOS5440 - bool "Samsung EXYNOS5440 SoC pinctrl driver" - depends on SOC_EXYNOS5440 - select PINMUX - select PINCONF - config PINCTRL_S3C24XX bool "Samsung S3C24XX SoC pinctrl driver" depends on ARCH_S3C24XX && OF diff --git a/drivers/pinctrl/samsung/Makefile b/drivers/pinctrl/samsung/Makefile index df426561d067..ed951df6a112 100644 --- a/drivers/pinctrl/samsung/Makefile +++ b/drivers/pinctrl/samsung/Makefile @@ -5,6 +5,5 @@ obj-$(CONFIG_PINCTRL_SAMSUNG) += pinctrl-samsung.o obj-$(CONFIG_PINCTRL_EXYNOS) += pinctrl-exynos.o obj-$(CONFIG_PINCTRL_EXYNOS_ARM) += pinctrl-exynos-arm.o obj-$(CONFIG_PINCTRL_EXYNOS_ARM64) += pinctrl-exynos-arm64.o -obj-$(CONFIG_PINCTRL_EXYNOS5440) += pinctrl-exynos5440.o obj-$(CONFIG_PINCTRL_S3C24XX) += pinctrl-s3c24xx.o obj-$(CONFIG_PINCTRL_S3C64XX) += pinctrl-s3c64xx.o diff --git a/drivers/pinctrl/samsung/pinctrl-exynos5440.c b/drivers/pinctrl/samsung/pinctrl-exynos5440.c deleted file mode 100644 index 3d8d5e812839..000000000000 --- a/drivers/pinctrl/samsung/pinctrl-exynos5440.c +++ /dev/null @@ -1,1005 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -// -// pin-controller/pin-mux/pin-config/gpio-driver for Samsung's EXYNOS5440 SoC. -// -// Author: Thomas Abraham -// -// Copyright (c) 2012 Samsung Electronics Co., Ltd. -// http://www.samsung.com - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../core.h" - -/* EXYNOS5440 GPIO and Pinctrl register offsets */ -#define GPIO_MUX 0x00 -#define GPIO_IE 0x04 -#define GPIO_INT 0x08 -#define GPIO_TYPE 0x0C -#define GPIO_VAL 0x10 -#define GPIO_OE 0x14 -#define GPIO_IN 0x18 -#define GPIO_PE 0x1C -#define GPIO_PS 0x20 -#define GPIO_SR 0x24 -#define GPIO_DS0 0x28 -#define GPIO_DS1 0x2C - -#define EXYNOS5440_MAX_PINS 23 -#define EXYNOS5440_MAX_GPIO_INT 8 -#define PIN_NAME_LENGTH 10 - -#define GROUP_SUFFIX "-grp" -#define FUNCTION_SUFFIX "-mux" - -/* - * pin configuration type and its value are packed together into a 16-bits. - * The upper 8-bits represent the configuration type and the lower 8-bits - * hold the value of the configuration type. - */ -#define PINCFG_TYPE_MASK 0xFF -#define PINCFG_VALUE_SHIFT 8 -#define PINCFG_VALUE_MASK (0xFF << PINCFG_VALUE_SHIFT) -#define PINCFG_PACK(type, value) (((value) << PINCFG_VALUE_SHIFT) | type) -#define PINCFG_UNPACK_TYPE(cfg) ((cfg) & PINCFG_TYPE_MASK) -#define PINCFG_UNPACK_VALUE(cfg) (((cfg) & PINCFG_VALUE_MASK) >> \ - PINCFG_VALUE_SHIFT) - -/** - * enum pincfg_type - possible pin configuration types supported. - * @PINCFG_TYPE_PUD: Pull up/down configuration. - * @PINCFG_TYPE_DRV: Drive strength configuration. - * @PINCFG_TYPE_SKEW_RATE: Skew rate configuration. - * @PINCFG_TYPE_INPUT_TYPE: Pin input type configuration. - */ -enum pincfg_type { - PINCFG_TYPE_PUD, - PINCFG_TYPE_DRV, - PINCFG_TYPE_SKEW_RATE, - PINCFG_TYPE_INPUT_TYPE -}; - -/** - * struct exynos5440_pin_group: represent group of pins for pincfg setting. - * @name: name of the pin group, used to lookup the group. - * @pins: the pins included in this group. - * @num_pins: number of pins included in this group. - */ -struct exynos5440_pin_group { - const char *name; - const unsigned int *pins; - u8 num_pins; -}; - -/** - * struct exynos5440_pmx_func: represent a pin function. - * @name: name of the pin function, used to lookup the function. - * @groups: one or more names of pin groups that provide this function. - * @num_groups: number of groups included in @groups. - * @function: the function number to be programmed when selected. - */ -struct exynos5440_pmx_func { - const char *name; - const char **groups; - u8 num_groups; - unsigned long function; -}; - -/** - * struct exynos5440_pinctrl_priv_data: driver's private runtime data. - * @reg_base: ioremapped based address of the register space. - * @gc: gpio chip registered with gpiolib. - * @pin_groups: list of pin groups parsed from device tree. - * @nr_groups: number of pin groups available. - * @pmx_functions: list of pin functions parsed from device tree. - * @nr_functions: number of pin functions available. - * @range: gpio range to register with pinctrl - */ -struct exynos5440_pinctrl_priv_data { - void __iomem *reg_base; - struct gpio_chip *gc; - struct irq_domain *irq_domain; - - const struct exynos5440_pin_group *pin_groups; - unsigned int nr_groups; - const struct exynos5440_pmx_func *pmx_functions; - unsigned int nr_functions; - struct pinctrl_gpio_range range; -}; - -/** - * struct exynos5440_gpio_intr_data: private data for gpio interrupts. - * @priv: driver's private runtime data. - * @gpio_int: gpio interrupt number. - */ -struct exynos5440_gpio_intr_data { - struct exynos5440_pinctrl_priv_data *priv; - unsigned int gpio_int; -}; - -/* list of all possible config options supported */ -static struct pin_config { - char *prop_cfg; - unsigned int cfg_type; -} pcfgs[] = { - { "samsung,exynos5440-pin-pud", PINCFG_TYPE_PUD }, - { "samsung,exynos5440-pin-drv", PINCFG_TYPE_DRV }, - { "samsung,exynos5440-pin-skew-rate", PINCFG_TYPE_SKEW_RATE }, - { "samsung,exynos5440-pin-input-type", PINCFG_TYPE_INPUT_TYPE }, -}; - -/* check if the selector is a valid pin group selector */ -static int exynos5440_get_group_count(struct pinctrl_dev *pctldev) -{ - struct exynos5440_pinctrl_priv_data *priv; - - priv = pinctrl_dev_get_drvdata(pctldev); - return priv->nr_groups; -} - -/* return the name of the group selected by the group selector */ -static const char *exynos5440_get_group_name(struct pinctrl_dev *pctldev, - unsigned selector) -{ - struct exynos5440_pinctrl_priv_data *priv; - - priv = pinctrl_dev_get_drvdata(pctldev); - return priv->pin_groups[selector].name; -} - -/* return the pin numbers associated with the specified group */ -static int exynos5440_get_group_pins(struct pinctrl_dev *pctldev, - unsigned selector, const unsigned **pins, unsigned *num_pins) -{ - struct exynos5440_pinctrl_priv_data *priv; - - priv = pinctrl_dev_get_drvdata(pctldev); - *pins = priv->pin_groups[selector].pins; - *num_pins = priv->pin_groups[selector].num_pins; - return 0; -} - -/* create pinctrl_map entries by parsing device tree nodes */ -static int exynos5440_dt_node_to_map(struct pinctrl_dev *pctldev, - struct device_node *np, struct pinctrl_map **maps, - unsigned *nmaps) -{ - struct device *dev = pctldev->dev; - struct pinctrl_map *map; - unsigned long *cfg = NULL; - char *gname, *fname; - int cfg_cnt = 0, map_cnt = 0, idx = 0; - - /* count the number of config options specfied in the node */ - for (idx = 0; idx < ARRAY_SIZE(pcfgs); idx++) - if (of_find_property(np, pcfgs[idx].prop_cfg, NULL)) - cfg_cnt++; - - /* - * Find out the number of map entries to create. All the config options - * can be accomadated into a single config map entry. - */ - if (cfg_cnt) - map_cnt = 1; - if (of_find_property(np, "samsung,exynos5440-pin-function", NULL)) - map_cnt++; - if (!map_cnt) { - dev_err(dev, "node %s does not have either config or function " - "configurations\n", np->name); - return -EINVAL; - } - - /* Allocate memory for pin-map entries */ - map = kzalloc(sizeof(*map) * map_cnt, GFP_KERNEL); - if (!map) - return -ENOMEM; - *nmaps = 0; - - /* - * Allocate memory for pin group name. The pin group name is derived - * from the node name from which these map entries are be created. - */ - gname = kasprintf(GFP_KERNEL, "%s%s", np->name, GROUP_SUFFIX); - if (!gname) - goto free_map; - - /* - * don't have config options? then skip over to creating function - * map entries. - */ - if (!cfg_cnt) - goto skip_cfgs; - - /* Allocate memory for config entries */ - cfg = kzalloc(sizeof(*cfg) * cfg_cnt, GFP_KERNEL); - if (!cfg) - goto free_gname; - - /* Prepare a list of config settings */ - for (idx = 0, cfg_cnt = 0; idx < ARRAY_SIZE(pcfgs); idx++) { - u32 value; - if (!of_property_read_u32(np, pcfgs[idx].prop_cfg, &value)) - cfg[cfg_cnt++] = - PINCFG_PACK(pcfgs[idx].cfg_type, value); - } - - /* create the config map entry */ - map[*nmaps].data.configs.group_or_pin = gname; - map[*nmaps].data.configs.configs = cfg; - map[*nmaps].data.configs.num_configs = cfg_cnt; - map[*nmaps].type = PIN_MAP_TYPE_CONFIGS_GROUP; - *nmaps += 1; - -skip_cfgs: - /* create the function map entry */ - if (of_find_property(np, "samsung,exynos5440-pin-function", NULL)) { - fname = kasprintf(GFP_KERNEL, - "%s%s", np->name, FUNCTION_SUFFIX); - if (!fname) - goto free_cfg; - - map[*nmaps].data.mux.group = gname; - map[*nmaps].data.mux.function = fname; - map[*nmaps].type = PIN_MAP_TYPE_MUX_GROUP; - *nmaps += 1; - } - - *maps = map; - return 0; - -free_cfg: - kfree(cfg); -free_gname: - kfree(gname); -free_map: - kfree(map); - return -ENOMEM; -} - -/* free the memory allocated to hold the pin-map table */ -static void exynos5440_dt_free_map(struct pinctrl_dev *pctldev, - struct pinctrl_map *map, unsigned num_maps) -{ - int idx; - - for (idx = 0; idx < num_maps; idx++) { - if (map[idx].type == PIN_MAP_TYPE_MUX_GROUP) { - kfree(map[idx].data.mux.function); - if (!idx) - kfree(map[idx].data.mux.group); - } else if (map->type == PIN_MAP_TYPE_CONFIGS_GROUP) { - kfree(map[idx].data.configs.configs); - if (!idx) - kfree(map[idx].data.configs.group_or_pin); - } - } - - kfree(map); -} - -/* list of pinctrl callbacks for the pinctrl core */ -static const struct pinctrl_ops exynos5440_pctrl_ops = { - .get_groups_count = exynos5440_get_group_count, - .get_group_name = exynos5440_get_group_name, - .get_group_pins = exynos5440_get_group_pins, - .dt_node_to_map = exynos5440_dt_node_to_map, - .dt_free_map = exynos5440_dt_free_map, -}; - -/* check if the selector is a valid pin function selector */ -static int exynos5440_get_functions_count(struct pinctrl_dev *pctldev) -{ - struct exynos5440_pinctrl_priv_data *priv; - - priv = pinctrl_dev_get_drvdata(pctldev); - return priv->nr_functions; -} - -/* return the name of the pin function specified */ -static const char *exynos5440_pinmux_get_fname(struct pinctrl_dev *pctldev, - unsigned selector) -{ - struct exynos5440_pinctrl_priv_data *priv; - - priv = pinctrl_dev_get_drvdata(pctldev); - return priv->pmx_functions[selector].name; -} - -/* return the groups associated for the specified function selector */ -static int exynos5440_pinmux_get_groups(struct pinctrl_dev *pctldev, - unsigned selector, const char * const **groups, - unsigned * const num_groups) -{ - struct exynos5440_pinctrl_priv_data *priv; - - priv = pinctrl_dev_get_drvdata(pctldev); - *groups = priv->pmx_functions[selector].groups; - *num_groups = priv->pmx_functions[selector].num_groups; - return 0; -} - -/* enable or disable a pinmux function */ -static void exynos5440_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector, - unsigned group, bool enable) -{ - struct exynos5440_pinctrl_priv_data *priv; - void __iomem *base; - u32 function; - u32 data; - - priv = pinctrl_dev_get_drvdata(pctldev); - base = priv->reg_base; - function = priv->pmx_functions[selector].function; - - data = readl(base + GPIO_MUX); - if (enable) - data |= (1 << function); - else - data &= ~(1 << function); - writel(data, base + GPIO_MUX); -} - -/* enable a specified pinmux by writing to registers */ -static int exynos5440_pinmux_set_mux(struct pinctrl_dev *pctldev, - unsigned selector, - unsigned group) -{ - exynos5440_pinmux_setup(pctldev, selector, group, true); - return 0; -} - -/* - * The calls to gpio_direction_output() and gpio_direction_input() - * leads to this function call (via the pinctrl_gpio_direction_{input|output}() - * function called from the gpiolib interface). - */ -static int exynos5440_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev, - struct pinctrl_gpio_range *range, unsigned offset, bool input) -{ - return 0; -} - -/* list of pinmux callbacks for the pinmux vertical in pinctrl core */ -static const struct pinmux_ops exynos5440_pinmux_ops = { - .get_functions_count = exynos5440_get_functions_count, - .get_function_name = exynos5440_pinmux_get_fname, - .get_function_groups = exynos5440_pinmux_get_groups, - .set_mux = exynos5440_pinmux_set_mux, - .gpio_set_direction = exynos5440_pinmux_gpio_set_direction, -}; - -/* set the pin config settings for a specified pin */ -static int exynos5440_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, - unsigned long *configs, - unsigned num_configs) -{ - struct exynos5440_pinctrl_priv_data *priv; - void __iomem *base; - enum pincfg_type cfg_type; - u32 cfg_value; - u32 data; - int i; - - priv = pinctrl_dev_get_drvdata(pctldev); - base = priv->reg_base; - - for (i = 0; i < num_configs; i++) { - cfg_type = PINCFG_UNPACK_TYPE(configs[i]); - cfg_value = PINCFG_UNPACK_VALUE(configs[i]); - - switch (cfg_type) { - case PINCFG_TYPE_PUD: - /* first set pull enable/disable bit */ - data = readl(base + GPIO_PE); - data &= ~(1 << pin); - if (cfg_value) - data |= (1 << pin); - writel(data, base + GPIO_PE); - - /* then set pull up/down bit */ - data = readl(base + GPIO_PS); - data &= ~(1 << pin); - if (cfg_value == 2) - data |= (1 << pin); - writel(data, base + GPIO_PS); - break; - - case PINCFG_TYPE_DRV: - /* set the first bit of the drive strength */ - data = readl(base + GPIO_DS0); - data &= ~(1 << pin); - data |= ((cfg_value & 1) << pin); - writel(data, base + GPIO_DS0); - cfg_value >>= 1; - - /* set the second bit of the driver strength */ - data = readl(base + GPIO_DS1); - data &= ~(1 << pin); - data |= ((cfg_value & 1) << pin); - writel(data, base + GPIO_DS1); - break; - case PINCFG_TYPE_SKEW_RATE: - data = readl(base + GPIO_SR); - data &= ~(1 << pin); - data |= ((cfg_value & 1) << pin); - writel(data, base + GPIO_SR); - break; - case PINCFG_TYPE_INPUT_TYPE: - data = readl(base + GPIO_TYPE); - data &= ~(1 << pin); - data |= ((cfg_value & 1) << pin); - writel(data, base + GPIO_TYPE); - break; - default: - WARN_ON(1); - return -EINVAL; - } - } /* for each config */ - - return 0; -} - -/* get the pin config settings for a specified pin */ -static int exynos5440_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin, - unsigned long *config) -{ - struct exynos5440_pinctrl_priv_data *priv; - void __iomem *base; - enum pincfg_type cfg_type = PINCFG_UNPACK_TYPE(*config); - u32 data; - - priv = pinctrl_dev_get_drvdata(pctldev); - base = priv->reg_base; - - switch (cfg_type) { - case PINCFG_TYPE_PUD: - data = readl(base + GPIO_PE); - data = (data >> pin) & 1; - if (!data) - *config = 0; - else - *config = ((readl(base + GPIO_PS) >> pin) & 1) + 1; - break; - case PINCFG_TYPE_DRV: - data = readl(base + GPIO_DS0); - data = (data >> pin) & 1; - *config = data; - data = readl(base + GPIO_DS1); - data = (data >> pin) & 1; - *config |= (data << 1); - break; - case PINCFG_TYPE_SKEW_RATE: - data = readl(base + GPIO_SR); - *config = (data >> pin) & 1; - break; - case PINCFG_TYPE_INPUT_TYPE: - data = readl(base + GPIO_TYPE); - *config = (data >> pin) & 1; - break; - default: - WARN_ON(1); - return -EINVAL; - } - - return 0; -} - -/* set the pin config settings for a specified pin group */ -static int exynos5440_pinconf_group_set(struct pinctrl_dev *pctldev, - unsigned group, unsigned long *configs, - unsigned num_configs) -{ - struct exynos5440_pinctrl_priv_data *priv; - const unsigned int *pins; - unsigned int cnt; - - priv = pinctrl_dev_get_drvdata(pctldev); - pins = priv->pin_groups[group].pins; - - for (cnt = 0; cnt < priv->pin_groups[group].num_pins; cnt++) - exynos5440_pinconf_set(pctldev, pins[cnt], configs, - num_configs); - - return 0; -} - -/* get the pin config settings for a specified pin group */ -static int exynos5440_pinconf_group_get(struct pinctrl_dev *pctldev, - unsigned int group, unsigned long *config) -{ - struct exynos5440_pinctrl_priv_data *priv; - const unsigned int *pins; - - priv = pinctrl_dev_get_drvdata(pctldev); - pins = priv->pin_groups[group].pins; - exynos5440_pinconf_get(pctldev, pins[0], config); - return 0; -} - -/* list of pinconfig callbacks for pinconfig vertical in the pinctrl code */ -static const struct pinconf_ops exynos5440_pinconf_ops = { - .pin_config_get = exynos5440_pinconf_get, - .pin_config_set = exynos5440_pinconf_set, - .pin_config_group_get = exynos5440_pinconf_group_get, - .pin_config_group_set = exynos5440_pinconf_group_set, -}; - -/* gpiolib gpio_set callback function */ -static void exynos5440_gpio_set(struct gpio_chip *gc, unsigned offset, int value) -{ - struct exynos5440_pinctrl_priv_data *priv = gpiochip_get_data(gc); - void __iomem *base = priv->reg_base; - u32 data; - - data = readl(base + GPIO_VAL); - data &= ~(1 << offset); - if (value) - data |= 1 << offset; - writel(data, base + GPIO_VAL); -} - -/* gpiolib gpio_get callback function */ -static int exynos5440_gpio_get(struct gpio_chip *gc, unsigned offset) -{ - struct exynos5440_pinctrl_priv_data *priv = gpiochip_get_data(gc); - void __iomem *base = priv->reg_base; - u32 data; - - data = readl(base + GPIO_IN); - data >>= offset; - data &= 1; - return data; -} - -/* gpiolib gpio_direction_input callback function */ -static int exynos5440_gpio_direction_input(struct gpio_chip *gc, unsigned offset) -{ - struct exynos5440_pinctrl_priv_data *priv = gpiochip_get_data(gc); - void __iomem *base = priv->reg_base; - u32 data; - - /* first disable the data output enable on this pin */ - data = readl(base + GPIO_OE); - data &= ~(1 << offset); - writel(data, base + GPIO_OE); - - /* now enable input on this pin */ - data = readl(base + GPIO_IE); - data |= 1 << offset; - writel(data, base + GPIO_IE); - return 0; -} - -/* gpiolib gpio_direction_output callback function */ -static int exynos5440_gpio_direction_output(struct gpio_chip *gc, unsigned offset, - int value) -{ - struct exynos5440_pinctrl_priv_data *priv = gpiochip_get_data(gc); - void __iomem *base = priv->reg_base; - u32 data; - - exynos5440_gpio_set(gc, offset, value); - - /* first disable the data input enable on this pin */ - data = readl(base + GPIO_IE); - data &= ~(1 << offset); - writel(data, base + GPIO_IE); - - /* now enable output on this pin */ - data = readl(base + GPIO_OE); - data |= 1 << offset; - writel(data, base + GPIO_OE); - return 0; -} - -/* gpiolib gpio_to_irq callback function */ -static int exynos5440_gpio_to_irq(struct gpio_chip *gc, unsigned offset) -{ - struct exynos5440_pinctrl_priv_data *priv = gpiochip_get_data(gc); - unsigned int virq; - - if (offset < 16 || offset > 23) - return -ENXIO; - - if (!priv->irq_domain) - return -ENXIO; - - virq = irq_create_mapping(priv->irq_domain, offset - 16); - return virq ? : -ENXIO; -} - -/* parse the pin numbers listed in the 'samsung,exynos5440-pins' property */ -static int exynos5440_pinctrl_parse_dt_pins(struct platform_device *pdev, - struct device_node *cfg_np, unsigned int **pin_list, - unsigned int *npins) -{ - struct device *dev = &pdev->dev; - struct property *prop; - - prop = of_find_property(cfg_np, "samsung,exynos5440-pins", NULL); - if (!prop) - return -ENOENT; - - *npins = prop->length / sizeof(unsigned long); - if (!*npins) { - dev_err(dev, "invalid pin list in %s node", cfg_np->name); - return -EINVAL; - } - - *pin_list = devm_kzalloc(dev, *npins * sizeof(**pin_list), GFP_KERNEL); - if (!*pin_list) - return -ENOMEM; - - return of_property_read_u32_array(cfg_np, "samsung,exynos5440-pins", - *pin_list, *npins); -} - -/* - * Parse the information about all the available pin groups and pin functions - * from device node of the pin-controller. - */ -static int exynos5440_pinctrl_parse_dt(struct platform_device *pdev, - struct exynos5440_pinctrl_priv_data *priv) -{ - struct device *dev = &pdev->dev; - struct device_node *dev_np = dev->of_node; - struct device_node *cfg_np; - struct exynos5440_pin_group *groups, *grp; - struct exynos5440_pmx_func *functions, *func; - unsigned *pin_list; - unsigned int npins, grp_cnt, func_idx = 0; - char *gname, *fname; - int ret; - - grp_cnt = of_get_child_count(dev_np); - if (!grp_cnt) - return -EINVAL; - - groups = devm_kzalloc(dev, grp_cnt * sizeof(*groups), GFP_KERNEL); - if (!groups) - return -EINVAL; - - grp = groups; - - functions = devm_kzalloc(dev, grp_cnt * sizeof(*functions), GFP_KERNEL); - if (!functions) - return -EINVAL; - - func = functions; - - /* - * Iterate over all the child nodes of the pin controller node - * and create pin groups and pin function lists. - */ - for_each_child_of_node(dev_np, cfg_np) { - u32 function; - - ret = exynos5440_pinctrl_parse_dt_pins(pdev, cfg_np, - &pin_list, &npins); - if (ret) { - gname = NULL; - goto skip_to_pin_function; - } - - /* derive pin group name from the node name */ - gname = devm_kasprintf(dev, GFP_KERNEL, - "%s%s", cfg_np->name, GROUP_SUFFIX); - if (!gname) - return -ENOMEM; - - grp->name = gname; - grp->pins = pin_list; - grp->num_pins = npins; - grp++; - -skip_to_pin_function: - ret = of_property_read_u32(cfg_np, "samsung,exynos5440-pin-function", - &function); - if (ret) - continue; - - /* derive function name from the node name */ - fname = devm_kasprintf(dev, GFP_KERNEL, - "%s%s", cfg_np->name, FUNCTION_SUFFIX); - if (!fname) - return -ENOMEM; - - func->name = fname; - func->groups = devm_kzalloc(dev, sizeof(char *), GFP_KERNEL); - if (!func->groups) - return -ENOMEM; - func->groups[0] = gname; - func->num_groups = gname ? 1 : 0; - func->function = function; - func++; - func_idx++; - } - - priv->pin_groups = groups; - priv->nr_groups = grp_cnt; - priv->pmx_functions = functions; - priv->nr_functions = func_idx; - return 0; -} - -/* register the pinctrl interface with the pinctrl subsystem */ -static int exynos5440_pinctrl_register(struct platform_device *pdev, - struct exynos5440_pinctrl_priv_data *priv) -{ - struct device *dev = &pdev->dev; - struct pinctrl_desc *ctrldesc; - struct pinctrl_dev *pctl_dev; - struct pinctrl_pin_desc *pindesc, *pdesc; - char *pin_names; - int pin, ret; - - ctrldesc = devm_kzalloc(dev, sizeof(*ctrldesc), GFP_KERNEL); - if (!ctrldesc) - return -ENOMEM; - - ctrldesc->name = "exynos5440-pinctrl"; - ctrldesc->owner = THIS_MODULE; - ctrldesc->pctlops = &exynos5440_pctrl_ops; - ctrldesc->pmxops = &exynos5440_pinmux_ops; - ctrldesc->confops = &exynos5440_pinconf_ops; - - pindesc = devm_kzalloc(&pdev->dev, sizeof(*pindesc) * - EXYNOS5440_MAX_PINS, GFP_KERNEL); - if (!pindesc) - return -ENOMEM; - ctrldesc->pins = pindesc; - ctrldesc->npins = EXYNOS5440_MAX_PINS; - - /* dynamically populate the pin number and pin name for pindesc */ - for (pin = 0, pdesc = pindesc; pin < ctrldesc->npins; pin++, pdesc++) - pdesc->number = pin; - - /* - * allocate space for storing the dynamically generated names for all - * the pins which belong to this pin-controller. - */ - pin_names = devm_kzalloc(&pdev->dev, sizeof(char) * PIN_NAME_LENGTH * - ctrldesc->npins, GFP_KERNEL); - if (!pin_names) - return -ENOMEM; - - /* for each pin, set the name of the pin */ - for (pin = 0; pin < ctrldesc->npins; pin++) { - snprintf(pin_names, 6, "gpio%02d", pin); - pdesc = pindesc + pin; - pdesc->name = pin_names; - pin_names += PIN_NAME_LENGTH; - } - - ret = exynos5440_pinctrl_parse_dt(pdev, priv); - if (ret) - return ret; - - pctl_dev = devm_pinctrl_register(&pdev->dev, ctrldesc, priv); - if (IS_ERR(pctl_dev)) { - dev_err(&pdev->dev, "could not register pinctrl driver\n"); - return PTR_ERR(pctl_dev); - } - - priv->range.name = "exynos5440-pctrl-gpio-range"; - priv->range.id = 0; - priv->range.base = 0; - priv->range.npins = EXYNOS5440_MAX_PINS; - priv->range.gc = priv->gc; - pinctrl_add_gpio_range(pctl_dev, &priv->range); - return 0; -} - -/* register the gpiolib interface with the gpiolib subsystem */ -static int exynos5440_gpiolib_register(struct platform_device *pdev, - struct exynos5440_pinctrl_priv_data *priv) -{ - struct gpio_chip *gc; - int ret; - - gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL); - if (!gc) - return -ENOMEM; - - priv->gc = gc; - gc->base = 0; - gc->ngpio = EXYNOS5440_MAX_PINS; - gc->parent = &pdev->dev; - gc->set = exynos5440_gpio_set; - gc->get = exynos5440_gpio_get; - gc->direction_input = exynos5440_gpio_direction_input; - gc->direction_output = exynos5440_gpio_direction_output; - gc->to_irq = exynos5440_gpio_to_irq; - gc->label = "gpiolib-exynos5440"; - gc->owner = THIS_MODULE; - ret = gpiochip_add_data(gc, priv); - if (ret) { - dev_err(&pdev->dev, "failed to register gpio_chip %s, error " - "code: %d\n", gc->label, ret); - return ret; - } - - return 0; -} - -/* unregister the gpiolib interface with the gpiolib subsystem */ -static int exynos5440_gpiolib_unregister(struct platform_device *pdev, - struct exynos5440_pinctrl_priv_data *priv) -{ - gpiochip_remove(priv->gc); - return 0; -} - -static void exynos5440_gpio_irq_unmask(struct irq_data *irqd) -{ - struct exynos5440_pinctrl_priv_data *d; - unsigned long gpio_int; - - d = irq_data_get_irq_chip_data(irqd); - gpio_int = readl(d->reg_base + GPIO_INT); - gpio_int |= 1 << irqd->hwirq; - writel(gpio_int, d->reg_base + GPIO_INT); -} - -static void exynos5440_gpio_irq_mask(struct irq_data *irqd) -{ - struct exynos5440_pinctrl_priv_data *d; - unsigned long gpio_int; - - d = irq_data_get_irq_chip_data(irqd); - gpio_int = readl(d->reg_base + GPIO_INT); - gpio_int &= ~(1 << irqd->hwirq); - writel(gpio_int, d->reg_base + GPIO_INT); -} - -/* irq_chip for gpio interrupts */ -static struct irq_chip exynos5440_gpio_irq_chip = { - .name = "exynos5440_gpio_irq_chip", - .irq_unmask = exynos5440_gpio_irq_unmask, - .irq_mask = exynos5440_gpio_irq_mask, -}; - -/* interrupt handler for GPIO interrupts 0..7 */ -static irqreturn_t exynos5440_gpio_irq(int irq, void *data) -{ - struct exynos5440_gpio_intr_data *intd = data; - struct exynos5440_pinctrl_priv_data *d = intd->priv; - int virq; - - virq = irq_linear_revmap(d->irq_domain, intd->gpio_int); - if (!virq) - return IRQ_NONE; - generic_handle_irq(virq); - return IRQ_HANDLED; -} - -static int exynos5440_gpio_irq_map(struct irq_domain *h, unsigned int virq, - irq_hw_number_t hw) -{ - struct exynos5440_pinctrl_priv_data *d = h->host_data; - - irq_set_chip_data(virq, d); - irq_set_chip_and_handler(virq, &exynos5440_gpio_irq_chip, - handle_level_irq); - return 0; -} - -/* irq domain callbacks for gpio interrupt controller */ -static const struct irq_domain_ops exynos5440_gpio_irqd_ops = { - .map = exynos5440_gpio_irq_map, - .xlate = irq_domain_xlate_twocell, -}; - -/* setup handling of gpio interrupts */ -static int exynos5440_gpio_irq_init(struct platform_device *pdev, - struct exynos5440_pinctrl_priv_data *priv) -{ - struct device *dev = &pdev->dev; - struct exynos5440_gpio_intr_data *intd; - int i, irq, ret; - - intd = devm_kzalloc(dev, sizeof(*intd) * EXYNOS5440_MAX_GPIO_INT, - GFP_KERNEL); - if (!intd) - return -ENOMEM; - - for (i = 0; i < EXYNOS5440_MAX_GPIO_INT; i++) { - irq = irq_of_parse_and_map(dev->of_node, i); - if (irq <= 0) { - dev_err(dev, "irq parsing failed\n"); - return -EINVAL; - } - - intd->gpio_int = i; - intd->priv = priv; - ret = devm_request_irq(dev, irq, exynos5440_gpio_irq, - 0, dev_name(dev), intd++); - if (ret) { - dev_err(dev, "irq request failed\n"); - return -ENXIO; - } - } - - priv->irq_domain = irq_domain_add_linear(dev->of_node, - EXYNOS5440_MAX_GPIO_INT, - &exynos5440_gpio_irqd_ops, priv); - if (!priv->irq_domain) { - dev_err(dev, "failed to create irq domain\n"); - return -ENXIO; - } - - return 0; -} - -static int exynos5440_pinctrl_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct exynos5440_pinctrl_priv_data *priv; - struct resource *res; - int ret; - - if (!dev->of_node) { - dev_err(dev, "device tree node not found\n"); - return -ENODEV; - } - - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->reg_base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(priv->reg_base)) - return PTR_ERR(priv->reg_base); - - ret = exynos5440_gpiolib_register(pdev, priv); - if (ret) - return ret; - - ret = exynos5440_pinctrl_register(pdev, priv); - if (ret) { - exynos5440_gpiolib_unregister(pdev, priv); - return ret; - } - - ret = exynos5440_gpio_irq_init(pdev, priv); - if (ret) { - dev_err(dev, "failed to setup gpio interrupts\n"); - return ret; - } - - platform_set_drvdata(pdev, priv); - dev_info(dev, "EXYNOS5440 pinctrl driver registered\n"); - return 0; -} - -static const struct of_device_id exynos5440_pinctrl_dt_match[] = { - { .compatible = "samsung,exynos5440-pinctrl" }, - {}, -}; - -static struct platform_driver exynos5440_pinctrl_driver = { - .probe = exynos5440_pinctrl_probe, - .driver = { - .name = "exynos5440-pinctrl", - .of_match_table = exynos5440_pinctrl_dt_match, - .suppress_bind_attrs = true, - }, -}; - -static int __init exynos5440_pinctrl_drv_register(void) -{ - return platform_driver_register(&exynos5440_pinctrl_driver); -} -postcore_initcall(exynos5440_pinctrl_drv_register); -- 2.14.1