diff --git a/target/linux/ramips/patches-6.12/805-01-v6.9-pinctrl-Add-driver-for-Awinic-AW9523-B-I2C-GPIO-Expa.patch b/target/linux/ramips/patches-6.12/805-01-v6.9-pinctrl-Add-driver-for-Awinic-AW9523-B-I2C-GPIO-Expa.patch deleted file mode 100644 index 84b4571b48f602..00000000000000 --- a/target/linux/ramips/patches-6.12/805-01-v6.9-pinctrl-Add-driver-for-Awinic-AW9523-B-I2C-GPIO-Expa.patch +++ /dev/null @@ -1,1190 +0,0 @@ -From 576623d706613feec2392ef16b84e23a46200552 Mon Sep 17 00:00:00 2001 -From: AngeloGioacchino Del Regno -Date: Fri, 1 Mar 2024 14:29:24 +0100 -Subject: [PATCH] pinctrl: Add driver for Awinic AW9523/B I2C GPIO Expander - -The Awinic AW9523(B) is a multi-function I2C gpio expander in a -TQFN-24L package, featuring PWM (max 37mA per pin, or total max -power 3.2Watts) for LED driving capability. - -It has two ports with 8 pins per port (for a total of 16 pins), -configurable as either PWM with 1/256 stepping or GPIO input/output, -1.8V logic input; each GPIO can be configured as input or output -independently from each other. - -This IC also has an internal interrupt controller, which is capable -of generating an interrupt for each GPIO, depending on the -configuration, and will raise an interrupt on the INTN pin to -advertise this to an external interrupt controller. - -Signed-off-by: AngeloGioacchino Del Regno -Signed-off-by: David Bauer -Link: https://lore.kernel.org/r/20210624214458.68716-2-mail@david-bauer.net -Acked-by: Krzysztof Kozlowski -Signed-off-by: Linus Walleij -Link: https://lore.kernel.org/r/20240301-awinic-aw9523-v8-1-7ec572f5dfb4@linaro.org ---- - drivers/pinctrl/Kconfig | 18 + - drivers/pinctrl/Makefile | 1 + - drivers/pinctrl/pinctrl-aw9523.c | 1118 ++++++++++++++++++++++++++++++ - 3 files changed, 1137 insertions(+) - create mode 100644 drivers/pinctrl/pinctrl-aw9523.c - ---- a/drivers/pinctrl/Kconfig -+++ b/drivers/pinctrl/Kconfig -@@ -127,6 +127,24 @@ config PINCTRL_AXP209 - selected. - Say Y to enable pinctrl and GPIO support for the AXP209 PMIC. - -+config PINCTRL_AW9523 -+ bool "Awinic AW9523/AW9523B I2C GPIO expander pinctrl driver" -+ depends on OF && I2C -+ select PINMUX -+ select PINCONF -+ select GENERIC_PINCONF -+ select GPIOLIB -+ select GPIOLIB_IRQCHIP -+ select REGMAP -+ select REGMAP_I2C -+ help -+ The Awinic AW9523/AW9523B is a multi-function I2C GPIO -+ expander with PWM functionality. This driver bundles a -+ pinctrl driver to select the function muxing and a GPIO -+ driver to handle GPIO, when the GPIO function is selected. -+ -+ Say yes to enable pinctrl and GPIO support for the AW9523(B). -+ - config PINCTRL_BM1880 - bool "Bitmain BM1880 Pinctrl driver" - depends on OF && (ARCH_BITMAIN || COMPILE_TEST) ---- a/drivers/pinctrl/Makefile -+++ b/drivers/pinctrl/Makefile -@@ -15,6 +15,7 @@ obj-$(CONFIG_PINCTRL_ARTPEC6) += pinctrl - obj-$(CONFIG_PINCTRL_AS3722) += pinctrl-as3722.o - obj-$(CONFIG_PINCTRL_AT91) += pinctrl-at91.o - obj-$(CONFIG_PINCTRL_AT91PIO4) += pinctrl-at91-pio4.o -+obj-$(CONFIG_PINCTRL_AW9523) += pinctrl-aw9523.o - obj-$(CONFIG_PINCTRL_AXP209) += pinctrl-axp209.o - obj-$(CONFIG_PINCTRL_BM1880) += pinctrl-bm1880.o - obj-$(CONFIG_PINCTRL_CY8C95X0) += pinctrl-cy8c95x0.o ---- /dev/null -+++ b/drivers/pinctrl/pinctrl-aw9523.c -@@ -0,0 +1,1118 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Awinic AW9523B i2c pin controller driver -+ * Copyright (c) 2020, AngeloGioacchino Del Regno -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define AW9523_MAX_FUNCS 2 -+#define AW9523_NUM_PORTS 2 -+#define AW9523_PINS_PER_PORT 8 -+ -+/* -+ * HW needs at least 20uS for reset and at least 1-2uS to recover from -+ * reset, but we have to account for eventual board quirks, if any: -+ * for this reason, keep reset asserted for 50uS and wait for 20uS -+ * to recover from the reset. -+ */ -+#define AW9523_HW_RESET_US 50 -+#define AW9523_HW_RESET_RECOVERY_US 20 -+ -+/* Port 0: P0_0...P0_7 - Port 1: P1_0...P1_7 */ -+#define AW9523_PIN_TO_PORT(pin) (pin >> 3) -+#define AW9523_REG_IN_STATE(pin) (0x00 + AW9523_PIN_TO_PORT(pin)) -+#define AW9523_REG_OUT_STATE(pin) (0x02 + AW9523_PIN_TO_PORT(pin)) -+#define AW9523_REG_CONF_STATE(pin) (0x04 + AW9523_PIN_TO_PORT(pin)) -+#define AW9523_REG_INTR_DIS(pin) (0x06 + AW9523_PIN_TO_PORT(pin)) -+#define AW9523_REG_CHIPID 0x10 -+#define AW9523_VAL_EXPECTED_CHIPID 0x23 -+ -+#define AW9523_REG_GCR 0x11 -+#define AW9523_GCR_ISEL_MASK GENMASK(0, 1) -+#define AW9523_GCR_GPOMD_MASK BIT(4) -+ -+#define AW9523_REG_PORT_MODE(pin) (0x12 + AW9523_PIN_TO_PORT(pin)) -+#define AW9523_REG_SOFT_RESET 0x7f -+#define AW9523_VAL_RESET 0x00 -+ -+/* -+ * struct aw9523_irq - Interrupt controller structure -+ * @lock: mutex locking for the irq bus -+ * @irqchip: structure holding irqchip params -+ * @cached_gpio: stores the previous gpio status for bit comparison -+ */ -+struct aw9523_irq { -+ struct mutex lock; -+ struct irq_chip *irqchip; -+ u16 cached_gpio; -+}; -+ -+/* -+ * struct aw9523_pinmux - Pin mux params -+ * @name: Name of the mux -+ * @grps: Groups of the mux -+ * @num_grps: Number of groups (sizeof array grps) -+ */ -+struct aw9523_pinmux { -+ const char *name; -+ const char * const *grps; -+ const u8 num_grps; -+}; -+ -+/* -+ * struct aw9523 - Main driver structure -+ * @dev: device handle -+ * @regmap: regmap handle for current device -+ * @i2c_lock: Mutex lock for i2c operations -+ * @reset_gpio: Hardware reset (RSTN) signal GPIO -+ * @vio_vreg: VCC regulator (Optional) -+ * @pctl: pinctrl handle for current device -+ * @gpio: structure holding gpiochip params -+ * @irq: Interrupt controller structure -+ */ -+struct aw9523 { -+ struct device *dev; -+ struct regmap *regmap; -+ struct mutex i2c_lock; -+ struct gpio_desc *reset_gpio; -+ struct regulator *vio_vreg; -+ struct pinctrl_dev *pctl; -+ struct gpio_chip gpio; -+ struct aw9523_irq *irq; -+}; -+ -+static const struct pinctrl_pin_desc aw9523_pins[] = { -+ /* Port 0 */ -+ PINCTRL_PIN(0, "gpio0"), -+ PINCTRL_PIN(1, "gpio1"), -+ PINCTRL_PIN(2, "gpio2"), -+ PINCTRL_PIN(3, "gpio3"), -+ PINCTRL_PIN(4, "gpio4"), -+ PINCTRL_PIN(5, "gpio5"), -+ PINCTRL_PIN(6, "gpio6"), -+ PINCTRL_PIN(7, "gpio7"), -+ -+ /* Port 1 */ -+ PINCTRL_PIN(8, "gpio8"), -+ PINCTRL_PIN(9, "gpio9"), -+ PINCTRL_PIN(10, "gpio10"), -+ PINCTRL_PIN(11, "gpio11"), -+ PINCTRL_PIN(12, "gpio12"), -+ PINCTRL_PIN(13, "gpio13"), -+ PINCTRL_PIN(14, "gpio14"), -+ PINCTRL_PIN(15, "gpio15"), -+}; -+ -+static int aw9523_pinctrl_get_groups_count(struct pinctrl_dev *pctldev) -+{ -+ return ARRAY_SIZE(aw9523_pins); -+} -+ -+static const char *aw9523_pinctrl_get_group_name(struct pinctrl_dev *pctldev, -+ unsigned int selector) -+{ -+ return aw9523_pins[selector].name; -+} -+ -+static int aw9523_pinctrl_get_group_pins(struct pinctrl_dev *pctldev, -+ unsigned int selector, -+ const unsigned int **pins, -+ unsigned int *num_pins) -+{ -+ *pins = &aw9523_pins[selector].number; -+ *num_pins = 1; -+ return 0; -+} -+ -+static const struct pinctrl_ops aw9523_pinctrl_ops = { -+ .get_groups_count = aw9523_pinctrl_get_groups_count, -+ .get_group_pins = aw9523_pinctrl_get_group_pins, -+ .get_group_name = aw9523_pinctrl_get_group_name, -+ .dt_node_to_map = pinconf_generic_dt_node_to_map_pin, -+ .dt_free_map = pinconf_generic_dt_free_map, -+}; -+ -+static const char * const gpio_pwm_groups[] = { -+ "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", -+ "gpio6", "gpio7", "gpio8", "gpio9", "gpio10", "gpio11", -+ "gpio12", "gpio13", "gpio14", "gpio15" -+}; -+ -+/* Warning: Do NOT reorder this array */ -+static const struct aw9523_pinmux aw9523_pmx[] = { -+ { -+ .name = "pwm", -+ .grps = gpio_pwm_groups, -+ .num_grps = ARRAY_SIZE(gpio_pwm_groups), -+ }, -+ { -+ .name = "gpio", -+ .grps = gpio_pwm_groups, -+ .num_grps = ARRAY_SIZE(gpio_pwm_groups), -+ }, -+}; -+ -+static int aw9523_pmx_get_funcs_count(struct pinctrl_dev *pctl) -+{ -+ return ARRAY_SIZE(aw9523_pmx); -+} -+ -+static const char *aw9523_pmx_get_fname(struct pinctrl_dev *pctl, -+ unsigned int sel) -+{ -+ return aw9523_pmx[sel].name; -+} -+ -+static int aw9523_pmx_get_groups(struct pinctrl_dev *pctl, unsigned int sel, -+ const char * const **groups, -+ unsigned int * const num_groups) -+{ -+ *groups = aw9523_pmx[sel].grps; -+ *num_groups = aw9523_pmx[sel].num_grps; -+ return 0; -+} -+ -+static int aw9523_pmx_set_mux(struct pinctrl_dev *pctl, unsigned int fsel, -+ unsigned int grp) -+{ -+ struct aw9523 *awi = pinctrl_dev_get_drvdata(pctl); -+ int ret, pin = aw9523_pins[grp].number % AW9523_PINS_PER_PORT; -+ -+ if (fsel >= ARRAY_SIZE(aw9523_pmx)) -+ return -EINVAL; -+ -+ /* -+ * This maps directly to the aw9523_pmx array: programming a -+ * high bit means "gpio" and a low bit means "pwm". -+ */ -+ mutex_lock(&awi->i2c_lock); -+ ret = regmap_update_bits(awi->regmap, AW9523_REG_PORT_MODE(pin), -+ BIT(pin), (fsel ? BIT(pin) : 0)); -+ mutex_unlock(&awi->i2c_lock); -+ return ret; -+} -+ -+static const struct pinmux_ops aw9523_pinmux_ops = { -+ .get_functions_count = aw9523_pmx_get_funcs_count, -+ .get_function_name = aw9523_pmx_get_fname, -+ .get_function_groups = aw9523_pmx_get_groups, -+ .set_mux = aw9523_pmx_set_mux, -+}; -+ -+static int aw9523_pcfg_param_to_reg(enum pin_config_param pcp, int pin, u8 *r) -+{ -+ u8 reg; -+ -+ switch (pcp) { -+ case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT: -+ case PIN_CONFIG_BIAS_PULL_DOWN: -+ case PIN_CONFIG_BIAS_PULL_UP: -+ reg = AW9523_REG_IN_STATE(pin); -+ break; -+ case PIN_CONFIG_DRIVE_OPEN_DRAIN: -+ case PIN_CONFIG_DRIVE_PUSH_PULL: -+ reg = AW9523_REG_GCR; -+ break; -+ case PIN_CONFIG_INPUT_ENABLE: -+ case PIN_CONFIG_OUTPUT_ENABLE: -+ reg = AW9523_REG_CONF_STATE(pin); -+ break; -+ case PIN_CONFIG_OUTPUT: -+ reg = AW9523_REG_OUT_STATE(pin); -+ break; -+ default: -+ return -EOPNOTSUPP; -+ } -+ *r = reg; -+ -+ return 0; -+} -+ -+static int aw9523_pconf_get(struct pinctrl_dev *pctldev, unsigned int pin, -+ unsigned long *config) -+{ -+ struct aw9523 *awi = pinctrl_dev_get_drvdata(pctldev); -+ enum pin_config_param param = pinconf_to_config_param(*config); -+ int regbit = pin % AW9523_PINS_PER_PORT; -+ unsigned int val; -+ u8 reg; -+ int rc; -+ -+ rc = aw9523_pcfg_param_to_reg(param, pin, ®); -+ if (rc) -+ return rc; -+ -+ mutex_lock(&awi->i2c_lock); -+ rc = regmap_read(awi->regmap, reg, &val); -+ mutex_unlock(&awi->i2c_lock); -+ if (rc) -+ return rc; -+ -+ switch (param) { -+ case PIN_CONFIG_BIAS_PULL_UP: -+ case PIN_CONFIG_INPUT_ENABLE: -+ case PIN_CONFIG_OUTPUT: -+ val &= BIT(regbit); -+ break; -+ case PIN_CONFIG_BIAS_PULL_DOWN: -+ case PIN_CONFIG_OUTPUT_ENABLE: -+ val &= BIT(regbit); -+ val = !val; -+ break; -+ case PIN_CONFIG_DRIVE_OPEN_DRAIN: -+ if (pin >= AW9523_PINS_PER_PORT) -+ val = 0; -+ else -+ val = !FIELD_GET(AW9523_GCR_GPOMD_MASK, val); -+ break; -+ case PIN_CONFIG_DRIVE_PUSH_PULL: -+ if (pin >= AW9523_PINS_PER_PORT) -+ val = 1; -+ else -+ val = FIELD_GET(AW9523_GCR_GPOMD_MASK, val); -+ break; -+ default: -+ return -EOPNOTSUPP; -+ } -+ if (val < 1) -+ return -EINVAL; -+ -+ *config = pinconf_to_config_packed(param, !!val); -+ -+ return rc; -+} -+ -+static int aw9523_pconf_set(struct pinctrl_dev *pctldev, unsigned int pin, -+ unsigned long *configs, unsigned int num_configs) -+{ -+ struct aw9523 *awi = pinctrl_dev_get_drvdata(pctldev); -+ enum pin_config_param param; -+ int regbit = pin % AW9523_PINS_PER_PORT; -+ u32 arg; -+ u8 reg; -+ unsigned int mask, val; -+ int i, rc; -+ -+ mutex_lock(&awi->i2c_lock); -+ for (i = 0; i < num_configs; i++) { -+ param = pinconf_to_config_param(configs[i]); -+ arg = pinconf_to_config_argument(configs[i]); -+ -+ rc = aw9523_pcfg_param_to_reg(param, pin, ®); -+ if (rc) -+ goto end; -+ -+ switch (param) { -+ case PIN_CONFIG_OUTPUT: -+ /* First, enable pin output */ -+ rc = regmap_update_bits(awi->regmap, -+ AW9523_REG_CONF_STATE(pin), -+ BIT(regbit), 0); -+ if (rc) -+ goto end; -+ -+ /* Then, fall through to config output level */ -+ fallthrough; -+ case PIN_CONFIG_OUTPUT_ENABLE: -+ arg = !arg; -+ fallthrough; -+ case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT: -+ case PIN_CONFIG_BIAS_PULL_DOWN: -+ case PIN_CONFIG_BIAS_PULL_UP: -+ case PIN_CONFIG_INPUT_ENABLE: -+ mask = BIT(regbit); -+ val = arg ? BIT(regbit) : 0; -+ break; -+ case PIN_CONFIG_DRIVE_OPEN_DRAIN: -+ /* Open-Drain is supported only on port 0 */ -+ if (pin >= AW9523_PINS_PER_PORT) { -+ rc = -EOPNOTSUPP; -+ goto end; -+ } -+ mask = AW9523_GCR_GPOMD_MASK; -+ val = 0; -+ break; -+ case PIN_CONFIG_DRIVE_PUSH_PULL: -+ /* Port 1 is always Push-Pull */ -+ if (pin >= AW9523_PINS_PER_PORT) { -+ mask = 0; -+ val = 0; -+ continue; -+ } -+ mask = AW9523_GCR_GPOMD_MASK; -+ val = AW9523_GCR_GPOMD_MASK; -+ break; -+ default: -+ rc = -EOPNOTSUPP; -+ goto end; -+ } -+ -+ rc = regmap_update_bits(awi->regmap, reg, mask, val); -+ if (rc) -+ goto end; -+ } -+end: -+ mutex_unlock(&awi->i2c_lock); -+ return rc; -+} -+ -+static const struct pinconf_ops aw9523_pinconf_ops = { -+ .pin_config_get = aw9523_pconf_get, -+ .pin_config_set = aw9523_pconf_set, -+ .is_generic = true, -+}; -+ -+/* -+ * aw9523_get_pin_direction - Get pin direction -+ * @regmap: Regmap structure -+ * @pin: gpiolib pin number -+ * @n: pin index in port register -+ * -+ * Return: Pin direction for success or negative number for error -+ */ -+static int aw9523_get_pin_direction(struct regmap *regmap, u8 pin, u8 n) -+{ -+ int ret; -+ -+ ret = regmap_test_bits(regmap, AW9523_REG_CONF_STATE(pin), BIT(n)); -+ if (ret < 0) -+ return ret; -+ -+ return ret ? GPIO_LINE_DIRECTION_IN : GPIO_LINE_DIRECTION_OUT; -+} -+ -+/* -+ * aw9523_get_port_state - Get input or output state for entire port -+ * @regmap: Regmap structure -+ * @pin: gpiolib pin number -+ * @regbit: hw pin index, used to retrieve port number -+ * @state: returned port state -+ * -+ * Return: Zero for success or negative number for error -+ */ -+static int aw9523_get_port_state(struct regmap *regmap, u8 pin, -+ u8 regbit, unsigned int *state) -+{ -+ u8 reg; -+ int dir; -+ -+ dir = aw9523_get_pin_direction(regmap, pin, regbit); -+ if (dir < 0) -+ return dir; -+ -+ if (dir == GPIO_LINE_DIRECTION_IN) -+ reg = AW9523_REG_IN_STATE(pin); -+ else -+ reg = AW9523_REG_OUT_STATE(pin); -+ -+ return regmap_read(regmap, reg, state); -+} -+ -+static int aw9523_gpio_irq_type(struct irq_data *d, unsigned int type) -+{ -+ switch (type) { -+ case IRQ_TYPE_NONE: -+ case IRQ_TYPE_EDGE_BOTH: -+ return 0; -+ default: -+ return -EINVAL; -+ }; -+} -+ -+/* -+ * aw9523_irq_mask - Mask interrupt -+ * @d: irq data -+ * -+ * Sets which interrupt to mask in the bitmap; -+ * The interrupt will be masked when unlocking the irq bus. -+ */ -+static void aw9523_irq_mask(struct irq_data *d) -+{ -+ struct aw9523 *awi = gpiochip_get_data(irq_data_get_irq_chip_data(d)); -+ unsigned int n = d->hwirq % AW9523_PINS_PER_PORT; -+ -+ regmap_update_bits(awi->regmap, -+ AW9523_REG_INTR_DIS(d->hwirq), -+ BIT(n), BIT(n)); -+ gpiochip_disable_irq(&awi->gpio, irqd_to_hwirq(d)); -+} -+ -+/* -+ * aw9523_irq_unmask - Unmask interrupt -+ * @d: irq data -+ * -+ * Sets which interrupt to unmask in the bitmap; -+ * The interrupt will be masked when unlocking the irq bus. -+ */ -+static void aw9523_irq_unmask(struct irq_data *d) -+{ -+ struct aw9523 *awi = gpiochip_get_data(irq_data_get_irq_chip_data(d)); -+ unsigned int n = d->hwirq % AW9523_PINS_PER_PORT; -+ -+ gpiochip_enable_irq(&awi->gpio, irqd_to_hwirq(d)); -+ regmap_update_bits(awi->regmap, -+ AW9523_REG_INTR_DIS(d->hwirq), -+ BIT(n), 0); -+} -+ -+static irqreturn_t aw9523_irq_thread_func(int irq, void *dev_id) -+{ -+ struct aw9523 *awi = (struct aw9523 *)dev_id; -+ unsigned long n, val = 0; -+ unsigned long changed_gpio; -+ unsigned int tmp, port_pin, i, ret; -+ -+ for (i = 0; i < AW9523_NUM_PORTS; i++) { -+ port_pin = i * AW9523_PINS_PER_PORT; -+ ret = regmap_read(awi->regmap, -+ AW9523_REG_IN_STATE(port_pin), -+ &tmp); -+ if (ret) -+ return ret; -+ val |= (u8)tmp << (i * 8); -+ } -+ -+ /* Handle GPIO input release interrupt as well */ -+ changed_gpio = awi->irq->cached_gpio ^ val; -+ awi->irq->cached_gpio = val; -+ -+ /* -+ * To avoid up to four *slow* i2c reads from any driver hooked -+ * up to our interrupts, just check for the irq_find_mapping -+ * result: if the interrupt is not mapped, then we don't want -+ * to care about it. -+ */ -+ for_each_set_bit(n, &changed_gpio, awi->gpio.ngpio) { -+ tmp = irq_find_mapping(awi->gpio.irq.domain, n); -+ if (tmp <= 0) -+ continue; -+ handle_nested_irq(tmp); -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+/* -+ * aw9523_irq_bus_lock - Grab lock for interrupt operation -+ * @d: irq data -+ */ -+static void aw9523_irq_bus_lock(struct irq_data *d) -+{ -+ struct aw9523 *awi = gpiochip_get_data(irq_data_get_irq_chip_data(d)); -+ -+ mutex_lock(&awi->irq->lock); -+ regcache_cache_only(awi->regmap, true); -+} -+ -+/* -+ * aw9523_irq_bus_sync_unlock - Synchronize state and unlock -+ * @d: irq data -+ * -+ * Writes the interrupt mask bits (found in the bit map) to the -+ * hardware, then unlocks the bus. -+ */ -+static void aw9523_irq_bus_sync_unlock(struct irq_data *d) -+{ -+ struct aw9523 *awi = gpiochip_get_data(irq_data_get_irq_chip_data(d)); -+ -+ regcache_cache_only(awi->regmap, false); -+ regcache_sync(awi->regmap); -+ mutex_unlock(&awi->irq->lock); -+} -+ -+static int aw9523_gpio_get_direction(struct gpio_chip *chip, -+ unsigned int offset) -+{ -+ struct aw9523 *awi = gpiochip_get_data(chip); -+ u8 regbit = offset % AW9523_PINS_PER_PORT; -+ int ret; -+ -+ mutex_lock(&awi->i2c_lock); -+ ret = aw9523_get_pin_direction(awi->regmap, offset, regbit); -+ mutex_unlock(&awi->i2c_lock); -+ -+ return ret; -+} -+ -+static int aw9523_gpio_get(struct gpio_chip *chip, unsigned int offset) -+{ -+ struct aw9523 *awi = gpiochip_get_data(chip); -+ u8 regbit = offset % AW9523_PINS_PER_PORT; -+ unsigned int val; -+ int ret; -+ -+ mutex_lock(&awi->i2c_lock); -+ ret = aw9523_get_port_state(awi->regmap, offset, regbit, &val); -+ mutex_unlock(&awi->i2c_lock); -+ if (ret) -+ return ret; -+ -+ return !!(val & BIT(regbit)); -+} -+ -+/** -+ * _aw9523_gpio_get_multiple - Get I/O state for an entire port -+ * @regmap: Regmap structure -+ * @pin: gpiolib pin number -+ * @regbit: hw pin index, used to retrieve port number -+ * @state: returned port I/O state -+ * -+ * Return: Zero for success or negative number for error -+ */ -+static int _aw9523_gpio_get_multiple(struct aw9523 *awi, u8 regbit, -+ u8 *state, u8 mask) -+{ -+ u32 dir_in, val; -+ u8 m; -+ int ret; -+ -+ /* Registers are 8-bits wide */ -+ ret = regmap_read(awi->regmap, AW9523_REG_CONF_STATE(regbit), &dir_in); -+ if (ret) -+ return ret; -+ *state = 0; -+ -+ m = mask & dir_in; -+ if (m) { -+ ret = regmap_read(awi->regmap, AW9523_REG_IN_STATE(regbit), -+ &val); -+ if (ret) -+ return ret; -+ *state |= (u8)val & m; -+ } -+ -+ m = mask & ~dir_in; -+ if (m) { -+ ret = regmap_read(awi->regmap, AW9523_REG_OUT_STATE(regbit), -+ &val); -+ if (ret) -+ return ret; -+ *state |= (u8)val & m; -+ } -+ -+ return 0; -+} -+ -+static int aw9523_gpio_get_multiple(struct gpio_chip *chip, -+ unsigned long *mask, -+ unsigned long *bits) -+{ -+ struct aw9523 *awi = gpiochip_get_data(chip); -+ u8 m, state = 0; -+ int ret; -+ -+ mutex_lock(&awi->i2c_lock); -+ -+ /* Port 0 (gpio 0-7) */ -+ m = *mask & U8_MAX; -+ if (m) { -+ ret = _aw9523_gpio_get_multiple(awi, 0, &state, m); -+ if (ret) -+ goto out; -+ } -+ *bits = state; -+ -+ /* Port 1 (gpio 8-15) */ -+ m = (*mask >> 8) & U8_MAX; -+ if (m) { -+ ret = _aw9523_gpio_get_multiple(awi, AW9523_PINS_PER_PORT, -+ &state, m); -+ if (ret) -+ goto out; -+ -+ *bits |= (state << 8); -+ } -+out: -+ mutex_unlock(&awi->i2c_lock); -+ return ret; -+} -+ -+static void aw9523_gpio_set_multiple(struct gpio_chip *chip, -+ unsigned long *mask, -+ unsigned long *bits) -+{ -+ struct aw9523 *awi = gpiochip_get_data(chip); -+ u8 mask_lo, mask_hi, bits_lo, bits_hi; -+ unsigned int reg; -+ int ret = 0; -+ -+ mask_lo = *mask & U8_MAX; -+ mask_hi = (*mask >> 8) & U8_MAX; -+ mutex_lock(&awi->i2c_lock); -+ if (mask_hi) { -+ reg = AW9523_REG_OUT_STATE(AW9523_PINS_PER_PORT); -+ bits_hi = (*bits >> 8) & U8_MAX; -+ -+ ret = regmap_write_bits(awi->regmap, reg, mask_hi, bits_hi); -+ if (ret) { -+ dev_warn(awi->dev, "Cannot write port1 out level\n"); -+ goto out; -+ } -+ } -+ if (mask_lo) { -+ reg = AW9523_REG_OUT_STATE(0); -+ bits_lo = *bits & U8_MAX; -+ ret = regmap_write_bits(awi->regmap, reg, mask_lo, bits_lo); -+ if (ret) -+ dev_warn(awi->dev, "Cannot write port0 out level\n"); -+ } -+out: -+ mutex_unlock(&awi->i2c_lock); -+} -+ -+static void aw9523_gpio_set(struct gpio_chip *chip, -+ unsigned int offset, int value) -+{ -+ struct aw9523 *awi = gpiochip_get_data(chip); -+ u8 regbit = offset % AW9523_PINS_PER_PORT; -+ -+ mutex_lock(&awi->i2c_lock); -+ regmap_update_bits(awi->regmap, AW9523_REG_OUT_STATE(offset), -+ BIT(regbit), value ? BIT(regbit) : 0); -+ mutex_unlock(&awi->i2c_lock); -+} -+ -+ -+static int aw9523_direction_input(struct gpio_chip *chip, unsigned int offset) -+{ -+ struct aw9523 *awi = gpiochip_get_data(chip); -+ u8 regbit = offset % AW9523_PINS_PER_PORT; -+ int ret; -+ -+ mutex_lock(&awi->i2c_lock); -+ ret = regmap_update_bits(awi->regmap, AW9523_REG_CONF_STATE(offset), -+ BIT(regbit), BIT(regbit)); -+ mutex_unlock(&awi->i2c_lock); -+ -+ return ret; -+} -+ -+static int aw9523_direction_output(struct gpio_chip *chip, -+ unsigned int offset, int value) -+{ -+ struct aw9523 *awi = gpiochip_get_data(chip); -+ u8 regbit = offset % AW9523_PINS_PER_PORT; -+ int ret; -+ -+ mutex_lock(&awi->i2c_lock); -+ ret = regmap_update_bits(awi->regmap, AW9523_REG_OUT_STATE(offset), -+ BIT(regbit), value ? BIT(regbit) : 0); -+ if (ret) -+ goto end; -+ -+ ret = regmap_update_bits(awi->regmap, AW9523_REG_CONF_STATE(offset), -+ BIT(regbit), 0); -+end: -+ mutex_unlock(&awi->i2c_lock); -+ return ret; -+} -+ -+static int aw9523_drive_reset_gpio(struct aw9523 *awi) -+{ -+ unsigned int chip_id; -+ int ret; -+ -+ /* -+ * If the chip is already configured for any reason, then we -+ * will probably succeed in sending the soft reset signal to -+ * the hardware through I2C: this operation takes less time -+ * compared to a full HW reset and it gives the same results. -+ */ -+ ret = regmap_write(awi->regmap, AW9523_REG_SOFT_RESET, 0); -+ if (ret == 0) -+ goto done; -+ -+ dev_dbg(awi->dev, "Cannot execute soft reset: trying hard reset\n"); -+ ret = gpiod_direction_output(awi->reset_gpio, 0); -+ if (ret) -+ return ret; -+ -+ /* The reset pulse has to be longer than 20uS due to deglitch */ -+ usleep_range(AW9523_HW_RESET_US, AW9523_HW_RESET_US + 1); -+ -+ ret = gpiod_direction_output(awi->reset_gpio, 1); -+ if (ret) -+ return ret; -+done: -+ /* The HW needs at least 1uS to reliably recover after reset */ -+ usleep_range(AW9523_HW_RESET_RECOVERY_US, -+ AW9523_HW_RESET_RECOVERY_US + 1); -+ -+ /* Check the ChipID */ -+ ret = regmap_read(awi->regmap, AW9523_REG_CHIPID, &chip_id); -+ if (ret) { -+ dev_err(awi->dev, "Cannot read Chip ID: %d\n", ret); -+ return ret; -+ } -+ if (chip_id != AW9523_VAL_EXPECTED_CHIPID) { -+ dev_err(awi->dev, "Bad ChipID; read 0x%x, expected 0x%x\n", -+ chip_id, AW9523_VAL_EXPECTED_CHIPID); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static int aw9523_hw_reset(struct aw9523 *awi) -+{ -+ int ret, max_retries = 2; -+ -+ /* Sometimes the chip needs more than one reset cycle */ -+ do { -+ ret = aw9523_drive_reset_gpio(awi); -+ if (ret == 0) -+ break; -+ max_retries--; -+ } while (max_retries); -+ -+ return ret; -+} -+ -+static int aw9523_init_gpiochip(struct aw9523 *awi, unsigned int npins) -+{ -+ struct device *dev = awi->dev; -+ struct gpio_chip *gc = &awi->gpio; -+ -+ gc->label = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL); -+ if (!gc->label) -+ return -ENOMEM; -+ -+ gc->base = -1; -+ gc->ngpio = npins; -+ gc->get_direction = aw9523_gpio_get_direction; -+ gc->direction_input = aw9523_direction_input; -+ gc->direction_output = aw9523_direction_output; -+ gc->get = aw9523_gpio_get; -+ gc->get_multiple = aw9523_gpio_get_multiple; -+ gc->set = aw9523_gpio_set; -+ gc->set_multiple = aw9523_gpio_set_multiple; -+ gc->set_config = gpiochip_generic_config; -+ gc->parent = dev; -+ gc->owner = THIS_MODULE; -+ gc->can_sleep = false; -+ -+ return 0; -+} -+ -+static const struct irq_chip aw9523_irq_chip = { -+ .name = "aw9523", -+ .irq_mask = aw9523_irq_mask, -+ .irq_unmask = aw9523_irq_unmask, -+ .irq_bus_lock = aw9523_irq_bus_lock, -+ .irq_bus_sync_unlock = aw9523_irq_bus_sync_unlock, -+ .irq_set_type = aw9523_gpio_irq_type, -+ .flags = IRQCHIP_IMMUTABLE, -+ GPIOCHIP_IRQ_RESOURCE_HELPERS, -+}; -+ -+static int aw9523_init_irq(struct aw9523 *awi, int irq) -+{ -+ struct device *dev = awi->dev; -+ struct gpio_irq_chip *girq; -+ struct irq_chip *irqchip; -+ int ret; -+ -+ if (!device_property_read_bool(dev, "interrupt-controller")) -+ return 0; -+ -+ irqchip = devm_kzalloc(dev, sizeof(*irqchip), GFP_KERNEL); -+ if (!irqchip) -+ return -ENOMEM; -+ -+ awi->irq = devm_kzalloc(dev, sizeof(*awi->irq), GFP_KERNEL); -+ if (!awi->irq) -+ return -ENOMEM; -+ -+ awi->irq->irqchip = irqchip; -+ mutex_init(&awi->irq->lock); -+ -+ ret = devm_request_threaded_irq(dev, irq, NULL, aw9523_irq_thread_func, -+ IRQF_ONESHOT, dev_name(dev), awi); -+ if (ret) { -+ dev_err(dev, "Failed to request irq %d\n", irq); -+ return ret; -+ } -+ -+ girq = &awi->gpio.irq; -+ gpio_irq_chip_set_chip(girq, &aw9523_irq_chip); -+ girq->parent_handler = NULL; -+ girq->num_parents = 0; -+ girq->parents = NULL; -+ girq->default_type = IRQ_TYPE_EDGE_BOTH; -+ girq->handler = handle_simple_irq; -+ girq->threaded = true; -+ -+ return 0; -+} -+ -+static bool aw9523_is_reg_hole(unsigned int reg) -+{ -+ return (reg > AW9523_REG_PORT_MODE(AW9523_PINS_PER_PORT) && -+ reg < AW9523_REG_SOFT_RESET) || -+ (reg > AW9523_REG_INTR_DIS(AW9523_PINS_PER_PORT) && -+ reg < AW9523_REG_CHIPID); -+} -+ -+static bool aw9523_readable_reg(struct device *dev, unsigned int reg) -+{ -+ /* All available registers (minus holes) can be read */ -+ return !aw9523_is_reg_hole(reg); -+} -+ -+static bool aw9523_volatile_reg(struct device *dev, unsigned int reg) -+{ -+ return aw9523_is_reg_hole(reg) || -+ reg == AW9523_REG_IN_STATE(0) || -+ reg == AW9523_REG_IN_STATE(AW9523_PINS_PER_PORT) || -+ reg == AW9523_REG_CHIPID || -+ reg == AW9523_REG_SOFT_RESET; -+} -+ -+static bool aw9523_writeable_reg(struct device *dev, unsigned int reg) -+{ -+ return !aw9523_is_reg_hole(reg) && reg != AW9523_REG_CHIPID; -+} -+ -+static bool aw9523_precious_reg(struct device *dev, unsigned int reg) -+{ -+ /* Reading AW9523_REG_IN_STATE clears interrupt status */ -+ return aw9523_is_reg_hole(reg) || -+ reg == AW9523_REG_IN_STATE(0) || -+ reg == AW9523_REG_IN_STATE(AW9523_PINS_PER_PORT); -+} -+ -+static const struct regmap_config aw9523_regmap = { -+ .reg_bits = 8, -+ .val_bits = 8, -+ .reg_stride = 1, -+ -+ .precious_reg = aw9523_precious_reg, -+ .readable_reg = aw9523_readable_reg, -+ .volatile_reg = aw9523_volatile_reg, -+ .writeable_reg = aw9523_writeable_reg, -+ -+ .cache_type = REGCACHE_FLAT, -+ .disable_locking = true, -+ -+ .num_reg_defaults_raw = AW9523_REG_SOFT_RESET, -+}; -+ -+static int aw9523_hw_init(struct aw9523 *awi) -+{ -+ u8 p1_pin = AW9523_PINS_PER_PORT; -+ unsigned int val; -+ int ret; -+ -+ /* No register caching during initialization */ -+ regcache_cache_bypass(awi->regmap, true); -+ -+ /* Bring up the chip */ -+ ret = aw9523_hw_reset(awi); -+ if (ret) { -+ dev_err(awi->dev, "HW Reset failed: %d\n", ret); -+ return ret; -+ } -+ -+ /* -+ * This is the expected chip and it is running: it's time to -+ * set a safe default configuration in case the user doesn't -+ * configure (all of the available) pins in this chip. -+ * P.S.: The writes order doesn't matter. -+ */ -+ -+ /* Set all pins as GPIO */ -+ ret = regmap_write(awi->regmap, AW9523_REG_PORT_MODE(0), U8_MAX); -+ if (ret) -+ return ret; -+ ret = regmap_write(awi->regmap, AW9523_REG_PORT_MODE(p1_pin), U8_MAX); -+ if (ret) -+ return ret; -+ -+ /* Set Open-Drain mode on Port 0 (Port 1 is always P-P) */ -+ ret = regmap_write(awi->regmap, AW9523_REG_GCR, 0); -+ if (ret) -+ return ret; -+ -+ /* Set all pins as inputs */ -+ ret = regmap_write(awi->regmap, AW9523_REG_CONF_STATE(0), U8_MAX); -+ if (ret) -+ return ret; -+ ret = regmap_write(awi->regmap, AW9523_REG_CONF_STATE(p1_pin), U8_MAX); -+ if (ret) -+ return ret; -+ -+ /* Disable all interrupts to avoid unreasoned wakeups */ -+ ret = regmap_write(awi->regmap, AW9523_REG_INTR_DIS(0), U8_MAX); -+ if (ret) -+ return ret; -+ ret = regmap_write(awi->regmap, AW9523_REG_INTR_DIS(p1_pin), U8_MAX); -+ if (ret) -+ return ret; -+ -+ /* Clear setup-generated interrupts by performing a port state read */ -+ ret = aw9523_get_port_state(awi->regmap, 0, 0, &val); -+ if (ret) -+ return ret; -+ ret = aw9523_get_port_state(awi->regmap, p1_pin, 0, &val); -+ if (ret) -+ return ret; -+ -+ /* Everything went fine: activate and reinitialize register cache */ -+ regcache_cache_bypass(awi->regmap, false); -+ return regmap_reinit_cache(awi->regmap, &aw9523_regmap); -+} -+ -+static int aw9523_probe(struct i2c_client *client) -+{ -+ struct device *dev = &client->dev; -+ struct pinctrl_desc *pdesc; -+ struct aw9523 *awi; -+ int ret; -+ -+ awi = devm_kzalloc(dev, sizeof(*awi), GFP_KERNEL); -+ if (!awi) -+ return -ENOMEM; -+ -+ i2c_set_clientdata(client, awi); -+ -+ awi->dev = dev; -+ awi->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); -+ if (IS_ERR(awi->reset_gpio)) -+ return PTR_ERR(awi->reset_gpio); -+ gpiod_set_consumer_name(awi->reset_gpio, "aw9523 reset"); -+ -+ awi->regmap = devm_regmap_init_i2c(client, &aw9523_regmap); -+ if (IS_ERR(awi->regmap)) -+ return PTR_ERR(awi->regmap); -+ -+ awi->vio_vreg = devm_regulator_get_optional(dev, "vio"); -+ if (IS_ERR(awi->vio_vreg)) { -+ if (PTR_ERR(awi->vio_vreg) == -EPROBE_DEFER) -+ return -EPROBE_DEFER; -+ awi->vio_vreg = NULL; -+ } else { -+ ret = regulator_enable(awi->vio_vreg); -+ if (ret) -+ return ret; -+ } -+ -+ mutex_init(&awi->i2c_lock); -+ lockdep_set_subclass(&awi->i2c_lock, -+ i2c_adapter_depth(client->adapter)); -+ -+ pdesc = devm_kzalloc(dev, sizeof(*pdesc), GFP_KERNEL); -+ if (!pdesc) -+ return -ENOMEM; -+ -+ ret = aw9523_hw_init(awi); -+ if (ret) -+ goto err_disable_vregs; -+ -+ pdesc->name = dev_name(dev); -+ pdesc->owner = THIS_MODULE; -+ pdesc->pctlops = &aw9523_pinctrl_ops; -+ pdesc->pmxops = &aw9523_pinmux_ops; -+ pdesc->confops = &aw9523_pinconf_ops; -+ pdesc->pins = aw9523_pins; -+ pdesc->npins = ARRAY_SIZE(aw9523_pins); -+ -+ ret = aw9523_init_gpiochip(awi, pdesc->npins); -+ if (ret) -+ goto err_disable_vregs; -+ -+ if (client->irq) { -+ ret = aw9523_init_irq(awi, client->irq); -+ if (ret) -+ goto err_disable_vregs; -+ } -+ -+ awi->pctl = devm_pinctrl_register(dev, pdesc, awi); -+ if (IS_ERR(awi->pctl)) { -+ ret = PTR_ERR(awi->pctl); -+ dev_err(dev, "Cannot register pinctrl: %d", ret); -+ goto err_disable_vregs; -+ } -+ -+ ret = devm_gpiochip_add_data(dev, &awi->gpio, awi); -+ if (ret) -+ goto err_disable_vregs; -+ -+ return ret; -+ -+err_disable_vregs: -+ if (awi->vio_vreg) -+ regulator_disable(awi->vio_vreg); -+ mutex_destroy(&awi->i2c_lock); -+ return ret; -+} -+ -+static void aw9523_remove(struct i2c_client *client) -+{ -+ struct aw9523 *awi = i2c_get_clientdata(client); -+ int ret; -+ -+ if (!awi) -+ return; -+ -+ /* -+ * If the chip VIO is connected to a regulator that we can turn -+ * off, life is easy... otherwise, reinitialize the chip and -+ * set the pins to hardware defaults before removing the driver -+ * to leave it in a clean, safe and predictable state. -+ */ -+ if (awi->vio_vreg) { -+ regulator_disable(awi->vio_vreg); -+ } else { -+ mutex_lock(&awi->i2c_lock); -+ ret = aw9523_hw_init(awi); -+ mutex_unlock(&awi->i2c_lock); -+ if (ret) -+ return; -+ } -+ -+ mutex_destroy(&awi->i2c_lock); -+} -+ -+static const struct i2c_device_id aw9523_i2c_id_table[] = { -+ { "aw9523_i2c", 0 }, -+ { } -+}; -+MODULE_DEVICE_TABLE(i2c, aw9523_i2c_id_table); -+ -+static const struct of_device_id of_aw9523_i2c_match[] = { -+ { .compatible = "awinic,aw9523-pinctrl", }, -+}; -+MODULE_DEVICE_TABLE(of, of_aw9523_i2c_match); -+ -+static struct i2c_driver aw9523_driver = { -+ .driver = { -+ .name = "aw9523-pinctrl", -+ .of_match_table = of_aw9523_i2c_match, -+ }, -+ .probe = aw9523_probe, -+ .remove = aw9523_remove, -+ .id_table = aw9523_i2c_id_table, -+}; -+module_i2c_driver(aw9523_driver); -+ -+MODULE_DESCRIPTION("Awinic AW9523 I2C GPIO Expander driver"); -+MODULE_AUTHOR("AngeloGioacchino Del Regno "); -+MODULE_LICENSE("GPL v2"); diff --git a/target/linux/ramips/patches-6.12/805-02-v6.9-pinctrl-aw9523-Add-proper-terminator.patch b/target/linux/ramips/patches-6.12/805-02-v6.9-pinctrl-aw9523-Add-proper-terminator.patch deleted file mode 100644 index 193c797c21991d..00000000000000 --- a/target/linux/ramips/patches-6.12/805-02-v6.9-pinctrl-aw9523-Add-proper-terminator.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 52279c3d50d964c646692c42a0db87ef7bb451cc Mon Sep 17 00:00:00 2001 -From: Linus Walleij -Date: Wed, 6 Mar 2024 08:54:25 +0100 -Subject: [PATCH] pinctrl: aw9523: Add proper terminator - -The of_device_id array needs to be terminated with a NULL -entry. - -Reported-by: kernel test robot -Closes: https://lore.kernel.org/oe-kbuild-all/202403061147.85XYVsk3-lkp@intel.com/ -Signed-off-by: Linus Walleij -Link: https://lore.kernel.org/r/20240306-fix-aw9523-terminator-v1-1-13f90f87a7f6@linaro.org ---- - drivers/pinctrl/pinctrl-aw9523.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/drivers/pinctrl/pinctrl-aw9523.c -+++ b/drivers/pinctrl/pinctrl-aw9523.c -@@ -1099,6 +1099,7 @@ MODULE_DEVICE_TABLE(i2c, aw9523_i2c_id_t - - static const struct of_device_id of_aw9523_i2c_match[] = { - { .compatible = "awinic,aw9523-pinctrl", }, -+ { } - }; - MODULE_DEVICE_TABLE(of, of_aw9523_i2c_match); - diff --git a/target/linux/ramips/patches-6.12/805-03-v6.10-pinctrl-aw9523-Destroy-mutex-on-remove.patch b/target/linux/ramips/patches-6.12/805-03-v6.10-pinctrl-aw9523-Destroy-mutex-on-remove.patch deleted file mode 100644 index 97d262451e074f..00000000000000 --- a/target/linux/ramips/patches-6.12/805-03-v6.10-pinctrl-aw9523-Destroy-mutex-on-remove.patch +++ /dev/null @@ -1,41 +0,0 @@ -From e5e8a58023707472e5dbe9bc7b473a8703b401e0 Mon Sep 17 00:00:00 2001 -From: Andy Shevchenko -Date: Fri, 29 Mar 2024 12:55:15 +0200 -Subject: [PATCH] pinctrl: aw9523: Destroy mutex on ->remove() - -If aw9523_hw_init() fails on ->remove() the mutex left alive. -Destroy it in that case as well. While at it, remove never -true check at the beginning of the function. - -Signed-off-by: Andy Shevchenko -Message-ID: <20240329105634.712457-2-andy.shevchenko@gmail.com> -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/pinctrl-aw9523.c | 8 +------- - 1 file changed, 1 insertion(+), 7 deletions(-) - ---- a/drivers/pinctrl/pinctrl-aw9523.c -+++ b/drivers/pinctrl/pinctrl-aw9523.c -@@ -1067,10 +1067,6 @@ err_disable_vregs: - static void aw9523_remove(struct i2c_client *client) - { - struct aw9523 *awi = i2c_get_clientdata(client); -- int ret; -- -- if (!awi) -- return; - - /* - * If the chip VIO is connected to a regulator that we can turn -@@ -1082,10 +1078,8 @@ static void aw9523_remove(struct i2c_cli - regulator_disable(awi->vio_vreg); - } else { - mutex_lock(&awi->i2c_lock); -- ret = aw9523_hw_init(awi); -+ aw9523_hw_init(awi); - mutex_unlock(&awi->i2c_lock); -- if (ret) -- return; - } - - mutex_destroy(&awi->i2c_lock); diff --git a/target/linux/ramips/patches-6.12/805-04-v6.10-pinctrl-aw9523-Use-correct-error-code-for-not-suppor.patch b/target/linux/ramips/patches-6.12/805-04-v6.10-pinctrl-aw9523-Use-correct-error-code-for-not-suppor.patch deleted file mode 100644 index 1217a6ce5e517c..00000000000000 --- a/target/linux/ramips/patches-6.12/805-04-v6.10-pinctrl-aw9523-Use-correct-error-code-for-not-suppor.patch +++ /dev/null @@ -1,62 +0,0 @@ -From f91eafcb18e096108cd19d24ab71a0db5bc12416 Mon Sep 17 00:00:00 2001 -From: Andy Shevchenko -Date: Fri, 29 Mar 2024 12:55:16 +0200 -Subject: [PATCH] pinctrl: aw9523: Use correct error code for not supported - functionality - -The pin control subsystem internally uses ENOTSUPP for the not supported -functionality. The checkpatch is false positive about this error code. - -Signed-off-by: Andy Shevchenko -Message-ID: <20240329105634.712457-3-andy.shevchenko@gmail.com> -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/pinctrl-aw9523.c | 9 +++++---- - 1 file changed, 5 insertions(+), 4 deletions(-) - ---- a/drivers/pinctrl/pinctrl-aw9523.c -+++ b/drivers/pinctrl/pinctrl-aw9523.c -@@ -6,6 +6,7 @@ - */ - - #include -+#include - #include - #include - #include -@@ -239,7 +240,7 @@ static int aw9523_pcfg_param_to_reg(enum - reg = AW9523_REG_OUT_STATE(pin); - break; - default: -- return -EOPNOTSUPP; -+ return -ENOTSUPP; - } - *r = reg; - -@@ -290,7 +291,7 @@ static int aw9523_pconf_get(struct pinct - val = FIELD_GET(AW9523_GCR_GPOMD_MASK, val); - break; - default: -- return -EOPNOTSUPP; -+ return -ENOTSUPP; - } - if (val < 1) - return -EINVAL; -@@ -344,7 +345,7 @@ static int aw9523_pconf_set(struct pinct - case PIN_CONFIG_DRIVE_OPEN_DRAIN: - /* Open-Drain is supported only on port 0 */ - if (pin >= AW9523_PINS_PER_PORT) { -- rc = -EOPNOTSUPP; -+ rc = -ENOTSUPP; - goto end; - } - mask = AW9523_GCR_GPOMD_MASK; -@@ -361,7 +362,7 @@ static int aw9523_pconf_set(struct pinct - val = AW9523_GCR_GPOMD_MASK; - break; - default: -- rc = -EOPNOTSUPP; -+ rc = -ENOTSUPP; - goto end; - } - diff --git a/target/linux/ramips/patches-6.12/805-05-v6.10-pinctrl-aw9523-Always-try-both-ports-in-aw9523_gpio_.patch b/target/linux/ramips/patches-6.12/805-05-v6.10-pinctrl-aw9523-Always-try-both-ports-in-aw9523_gpio_.patch deleted file mode 100644 index c90d4dac3202c3..00000000000000 --- a/target/linux/ramips/patches-6.12/805-05-v6.10-pinctrl-aw9523-Always-try-both-ports-in-aw9523_gpio_.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 091655b9285d837db520381924c689bd5dc5d286 Mon Sep 17 00:00:00 2001 -From: Andy Shevchenko -Date: Fri, 29 Mar 2024 12:55:17 +0200 -Subject: [PATCH] pinctrl: aw9523: Always try both ports in - aw9523_gpio_set_multiple() - -The ports are equivalent from the user's point of view. Don't limit -trying them both if writing to one fails. - -Signed-off-by: Andy Shevchenko -Message-ID: <20240329105634.712457-4-andy.shevchenko@gmail.com> -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/pinctrl-aw9523.c | 7 ++----- - 1 file changed, 2 insertions(+), 5 deletions(-) - ---- a/drivers/pinctrl/pinctrl-aw9523.c -+++ b/drivers/pinctrl/pinctrl-aw9523.c -@@ -653,7 +653,7 @@ static void aw9523_gpio_set_multiple(str - struct aw9523 *awi = gpiochip_get_data(chip); - u8 mask_lo, mask_hi, bits_lo, bits_hi; - unsigned int reg; -- int ret = 0; -+ int ret; - - mask_lo = *mask & U8_MAX; - mask_hi = (*mask >> 8) & U8_MAX; -@@ -663,10 +663,8 @@ static void aw9523_gpio_set_multiple(str - bits_hi = (*bits >> 8) & U8_MAX; - - ret = regmap_write_bits(awi->regmap, reg, mask_hi, bits_hi); -- if (ret) { -+ if (ret) - dev_warn(awi->dev, "Cannot write port1 out level\n"); -- goto out; -- } - } - if (mask_lo) { - reg = AW9523_REG_OUT_STATE(0); -@@ -675,7 +673,6 @@ static void aw9523_gpio_set_multiple(str - if (ret) - dev_warn(awi->dev, "Cannot write port0 out level\n"); - } --out: - mutex_unlock(&awi->i2c_lock); - } - diff --git a/target/linux/ramips/patches-6.12/805-06-v6.10-pinctrl-aw9523-Make-use-of-struct-pinfunction-and-PI.patch b/target/linux/ramips/patches-6.12/805-06-v6.10-pinctrl-aw9523-Make-use-of-struct-pinfunction-and-PI.patch deleted file mode 100644 index f300fa0193eb04..00000000000000 --- a/target/linux/ramips/patches-6.12/805-06-v6.10-pinctrl-aw9523-Make-use-of-struct-pinfunction-and-PI.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 418ee9488ff74ab4ada3a539a2840dda9e56f847 Mon Sep 17 00:00:00 2001 -From: Andy Shevchenko -Date: Fri, 29 Mar 2024 12:55:18 +0200 -Subject: [PATCH] pinctrl: aw9523: Make use of struct pinfunction and - PINCTRL_PINFUNCTION() - -Since pin control provides a generic data type and a macro for -the pin function definition, use them in the driver. - -Signed-off-by: Andy Shevchenko -Message-ID: <20240329105634.712457-5-andy.shevchenko@gmail.com> -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/pinctrl-aw9523.c | 32 ++++++-------------------------- - 1 file changed, 6 insertions(+), 26 deletions(-) - ---- a/drivers/pinctrl/pinctrl-aw9523.c -+++ b/drivers/pinctrl/pinctrl-aw9523.c -@@ -67,18 +67,6 @@ struct aw9523_irq { - }; - - /* -- * struct aw9523_pinmux - Pin mux params -- * @name: Name of the mux -- * @grps: Groups of the mux -- * @num_grps: Number of groups (sizeof array grps) -- */ --struct aw9523_pinmux { -- const char *name; -- const char * const *grps; -- const u8 num_grps; --}; -- --/* - * struct aw9523 - Main driver structure - * @dev: device handle - * @regmap: regmap handle for current device -@@ -158,17 +146,9 @@ static const char * const gpio_pwm_group - }; - - /* Warning: Do NOT reorder this array */ --static const struct aw9523_pinmux aw9523_pmx[] = { -- { -- .name = "pwm", -- .grps = gpio_pwm_groups, -- .num_grps = ARRAY_SIZE(gpio_pwm_groups), -- }, -- { -- .name = "gpio", -- .grps = gpio_pwm_groups, -- .num_grps = ARRAY_SIZE(gpio_pwm_groups), -- }, -+static const struct pinfunction aw9523_pmx[] = { -+ PINCTRL_PINFUNCTION("pwm", gpio_pwm_groups, ARRAY_SIZE(gpio_pwm_groups)), -+ PINCTRL_PINFUNCTION("gpio", gpio_pwm_groups, ARRAY_SIZE(gpio_pwm_groups)), - }; - - static int aw9523_pmx_get_funcs_count(struct pinctrl_dev *pctl) -@@ -184,10 +164,10 @@ static const char *aw9523_pmx_get_fname( - - static int aw9523_pmx_get_groups(struct pinctrl_dev *pctl, unsigned int sel, - const char * const **groups, -- unsigned int * const num_groups) -+ unsigned int * const ngroups) - { -- *groups = aw9523_pmx[sel].grps; -- *num_groups = aw9523_pmx[sel].num_grps; -+ *groups = aw9523_pmx[sel].groups; -+ *ngroups = aw9523_pmx[sel].ngroups; - return 0; - } - diff --git a/target/linux/ramips/patches-6.12/805-07-v6.10-pinctrl-aw9523-Use-temporary-variable-for-HW-IRQ-num.patch b/target/linux/ramips/patches-6.12/805-07-v6.10-pinctrl-aw9523-Use-temporary-variable-for-HW-IRQ-num.patch deleted file mode 100644 index 98a1310ad52837..00000000000000 --- a/target/linux/ramips/patches-6.12/805-07-v6.10-pinctrl-aw9523-Use-temporary-variable-for-HW-IRQ-num.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 66413f0468d35adb352c76bc286bf6f6746ba354 Mon Sep 17 00:00:00 2001 -From: Andy Shevchenko -Date: Fri, 29 Mar 2024 12:55:19 +0200 -Subject: [PATCH] pinctrl: aw9523: Use temporary variable for HW IRQ number - -There are two different ways on how to get HW IRQ number in some functions. -Unify that by using temporary variable and irqd_to_hwirq() call. - -Signed-off-by: Andy Shevchenko -Message-ID: <20240329105634.712457-6-andy.shevchenko@gmail.com> -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/pinctrl-aw9523.c | 16 ++++++++-------- - 1 file changed, 8 insertions(+), 8 deletions(-) - ---- a/drivers/pinctrl/pinctrl-aw9523.c -+++ b/drivers/pinctrl/pinctrl-aw9523.c -@@ -428,12 +428,12 @@ static int aw9523_gpio_irq_type(struct i - static void aw9523_irq_mask(struct irq_data *d) - { - struct aw9523 *awi = gpiochip_get_data(irq_data_get_irq_chip_data(d)); -- unsigned int n = d->hwirq % AW9523_PINS_PER_PORT; -+ irq_hw_number_t hwirq = irqd_to_hwirq(d); -+ unsigned int n = hwirq % AW9523_PINS_PER_PORT; - -- regmap_update_bits(awi->regmap, -- AW9523_REG_INTR_DIS(d->hwirq), -+ regmap_update_bits(awi->regmap, AW9523_REG_INTR_DIS(hwirq), - BIT(n), BIT(n)); -- gpiochip_disable_irq(&awi->gpio, irqd_to_hwirq(d)); -+ gpiochip_disable_irq(&awi->gpio, hwirq); - } - - /* -@@ -446,11 +446,11 @@ static void aw9523_irq_mask(struct irq_d - static void aw9523_irq_unmask(struct irq_data *d) - { - struct aw9523 *awi = gpiochip_get_data(irq_data_get_irq_chip_data(d)); -- unsigned int n = d->hwirq % AW9523_PINS_PER_PORT; -+ irq_hw_number_t hwirq = irqd_to_hwirq(d); -+ unsigned int n = hwirq % AW9523_PINS_PER_PORT; - -- gpiochip_enable_irq(&awi->gpio, irqd_to_hwirq(d)); -- regmap_update_bits(awi->regmap, -- AW9523_REG_INTR_DIS(d->hwirq), -+ gpiochip_enable_irq(&awi->gpio, hwirq); -+ regmap_update_bits(awi->regmap, AW9523_REG_INTR_DIS(hwirq), - BIT(n), 0); - } - diff --git a/target/linux/ramips/patches-6.12/805-08-v6.10-pinctrl-aw9523-Get-rid-of-redundant-U8_MAX-pieces.patch b/target/linux/ramips/patches-6.12/805-08-v6.10-pinctrl-aw9523-Get-rid-of-redundant-U8_MAX-pieces.patch deleted file mode 100644 index a9f86481e34fc2..00000000000000 --- a/target/linux/ramips/patches-6.12/805-08-v6.10-pinctrl-aw9523-Get-rid-of-redundant-U8_MAX-pieces.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 4210ef801a248223a0ea5f47b5446081b4925e10 Mon Sep 17 00:00:00 2001 -From: Andy Shevchenko -Date: Fri, 29 Mar 2024 12:55:20 +0200 -Subject: [PATCH] pinctrl: aw9523: Get rid of redundant ' & U8_MAX' pieces - -When the variable is declared as u8, no need to perform ' & U8_MAX' -as it's implied anyway. - -Signed-off-by: Andy Shevchenko -Message-ID: <20240329105634.712457-7-andy.shevchenko@gmail.com> -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/pinctrl-aw9523.c | 14 +++++++------- - 1 file changed, 7 insertions(+), 7 deletions(-) - ---- a/drivers/pinctrl/pinctrl-aw9523.c -+++ b/drivers/pinctrl/pinctrl-aw9523.c -@@ -603,7 +603,7 @@ static int aw9523_gpio_get_multiple(stru - mutex_lock(&awi->i2c_lock); - - /* Port 0 (gpio 0-7) */ -- m = *mask & U8_MAX; -+ m = *mask; - if (m) { - ret = _aw9523_gpio_get_multiple(awi, 0, &state, m); - if (ret) -@@ -612,7 +612,7 @@ static int aw9523_gpio_get_multiple(stru - *bits = state; - - /* Port 1 (gpio 8-15) */ -- m = (*mask >> 8) & U8_MAX; -+ m = *mask >> 8; - if (m) { - ret = _aw9523_gpio_get_multiple(awi, AW9523_PINS_PER_PORT, - &state, m); -@@ -635,20 +635,20 @@ static void aw9523_gpio_set_multiple(str - unsigned int reg; - int ret; - -- mask_lo = *mask & U8_MAX; -- mask_hi = (*mask >> 8) & U8_MAX; -+ mask_lo = *mask; -+ mask_hi = *mask >> 8; -+ bits_lo = *bits; -+ bits_hi = *bits >> 8; -+ - mutex_lock(&awi->i2c_lock); - if (mask_hi) { - reg = AW9523_REG_OUT_STATE(AW9523_PINS_PER_PORT); -- bits_hi = (*bits >> 8) & U8_MAX; -- - ret = regmap_write_bits(awi->regmap, reg, mask_hi, bits_hi); - if (ret) - dev_warn(awi->dev, "Cannot write port1 out level\n"); - } - if (mask_lo) { - reg = AW9523_REG_OUT_STATE(0); -- bits_lo = *bits & U8_MAX; - ret = regmap_write_bits(awi->regmap, reg, mask_lo, bits_lo); - if (ret) - dev_warn(awi->dev, "Cannot write port0 out level\n"); diff --git a/target/linux/ramips/patches-6.12/805-09-v6.10-pinctrl-aw9523-Remove-unused-irqchip-field-in-struct.patch b/target/linux/ramips/patches-6.12/805-09-v6.10-pinctrl-aw9523-Remove-unused-irqchip-field-in-struct.patch deleted file mode 100644 index b37a425e8dfbfe..00000000000000 --- a/target/linux/ramips/patches-6.12/805-09-v6.10-pinctrl-aw9523-Remove-unused-irqchip-field-in-struct.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 6bf270863ade776485d1c6bdb8f69d642b0e5f64 Mon Sep 17 00:00:00 2001 -From: Andy Shevchenko -Date: Fri, 29 Mar 2024 12:55:21 +0200 -Subject: [PATCH] pinctrl: aw9523: Remove unused irqchip field in struct - aw9523_irq - -The irqchip field is allocated, assigned but never used. Remove it. - -Signed-off-by: Andy Shevchenko -Message-ID: <20240329105634.712457-8-andy.shevchenko@gmail.com> -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/pinctrl-aw9523.c | 8 -------- - 1 file changed, 8 deletions(-) - ---- a/drivers/pinctrl/pinctrl-aw9523.c -+++ b/drivers/pinctrl/pinctrl-aw9523.c -@@ -57,12 +57,10 @@ - /* - * struct aw9523_irq - Interrupt controller structure - * @lock: mutex locking for the irq bus -- * @irqchip: structure holding irqchip params - * @cached_gpio: stores the previous gpio status for bit comparison - */ - struct aw9523_irq { - struct mutex lock; -- struct irq_chip *irqchip; - u16 cached_gpio; - }; - -@@ -805,21 +803,15 @@ static int aw9523_init_irq(struct aw9523 - { - struct device *dev = awi->dev; - struct gpio_irq_chip *girq; -- struct irq_chip *irqchip; - int ret; - - if (!device_property_read_bool(dev, "interrupt-controller")) - return 0; - -- irqchip = devm_kzalloc(dev, sizeof(*irqchip), GFP_KERNEL); -- if (!irqchip) -- return -ENOMEM; -- - awi->irq = devm_kzalloc(dev, sizeof(*awi->irq), GFP_KERNEL); - if (!awi->irq) - return -ENOMEM; - -- awi->irq->irqchip = irqchip; - mutex_init(&awi->irq->lock); - - ret = devm_request_threaded_irq(dev, irq, NULL, aw9523_irq_thread_func, diff --git a/target/linux/ramips/patches-6.12/805-10-v6.10-pinctrl-aw9523-Make-use-of-dev_err_probe.patch b/target/linux/ramips/patches-6.12/805-10-v6.10-pinctrl-aw9523-Make-use-of-dev_err_probe.patch deleted file mode 100644 index f1f4e52140e190..00000000000000 --- a/target/linux/ramips/patches-6.12/805-10-v6.10-pinctrl-aw9523-Make-use-of-dev_err_probe.patch +++ /dev/null @@ -1,40 +0,0 @@ -From c567b00cc3d73f3ce4e92126731545d177262090 Mon Sep 17 00:00:00 2001 -From: Andy Shevchenko -Date: Fri, 29 Mar 2024 12:55:22 +0200 -Subject: [PATCH] pinctrl: aw9523: Make use of dev_err_probe() - -Simplify the error handling in probe function by switching from -dev_err() to dev_err_probe(). - -Signed-off-by: Andy Shevchenko -Message-ID: <20240329105634.712457-9-andy.shevchenko@gmail.com> -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/pinctrl-aw9523.c | 9 +++------ - 1 file changed, 3 insertions(+), 6 deletions(-) - ---- a/drivers/pinctrl/pinctrl-aw9523.c -+++ b/drivers/pinctrl/pinctrl-aw9523.c -@@ -816,10 +816,8 @@ static int aw9523_init_irq(struct aw9523 - - ret = devm_request_threaded_irq(dev, irq, NULL, aw9523_irq_thread_func, - IRQF_ONESHOT, dev_name(dev), awi); -- if (ret) { -- dev_err(dev, "Failed to request irq %d\n", irq); -- return ret; -- } -+ if (ret) -+ return dev_err_probe(dev, ret, "Failed to request irq %d\n", irq); - - girq = &awi->gpio.irq; - gpio_irq_chip_set_chip(girq, &aw9523_irq_chip); -@@ -1016,8 +1014,7 @@ static int aw9523_probe(struct i2c_clien - - awi->pctl = devm_pinctrl_register(dev, pdesc, awi); - if (IS_ERR(awi->pctl)) { -- ret = PTR_ERR(awi->pctl); -- dev_err(dev, "Cannot register pinctrl: %d", ret); -+ ret = dev_err_probe(dev, PTR_ERR(awi->pctl), "Cannot register pinctrl"); - goto err_disable_vregs; - } - diff --git a/target/linux/ramips/patches-6.12/805-11-v6.10-pinctrl-aw9523-Sort-headers-and-group-pinctrl.patch b/target/linux/ramips/patches-6.12/805-11-v6.10-pinctrl-aw9523-Sort-headers-and-group-pinctrl.patch deleted file mode 100644 index 4d81c6ae7f3396..00000000000000 --- a/target/linux/ramips/patches-6.12/805-11-v6.10-pinctrl-aw9523-Sort-headers-and-group-pinctrl.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 7b8b9b5450b89d01e4b8f120b903cee85b529231 Mon Sep 17 00:00:00 2001 -From: Andy Shevchenko -Date: Fri, 29 Mar 2024 12:55:23 +0200 -Subject: [PATCH] pinctrl: aw9523: Sort headers and group pinctrl/* - -One header was misplaced and group pinctrl/* ones to show the relation -with the pin control subsystem. - -Signed-off-by: Andy Shevchenko -Message-ID: <20240329105634.712457-10-andy.shevchenko@gmail.com> -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/pinctrl-aw9523.c | 11 ++++++----- - 1 file changed, 6 insertions(+), 5 deletions(-) - ---- a/drivers/pinctrl/pinctrl-aw9523.c -+++ b/drivers/pinctrl/pinctrl-aw9523.c -@@ -13,17 +13,18 @@ - #include - #include - #include --#include - #include --#include --#include --#include --#include -+#include - #include - #include - #include - #include - -+#include -+#include -+#include -+#include -+ - #define AW9523_MAX_FUNCS 2 - #define AW9523_NUM_PORTS 2 - #define AW9523_PINS_PER_PORT 8 diff --git a/target/linux/ramips/patches-6.12/805-12-v6.10-pinctrl-aw9523-Fix-indentation-in-a-few-places.patch b/target/linux/ramips/patches-6.12/805-12-v6.10-pinctrl-aw9523-Fix-indentation-in-a-few-places.patch deleted file mode 100644 index 3ebdcdfa4a8cf6..00000000000000 --- a/target/linux/ramips/patches-6.12/805-12-v6.10-pinctrl-aw9523-Fix-indentation-in-a-few-places.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 4aad0ad20f4ea80180a3e58b04b701728541c0f7 Mon Sep 17 00:00:00 2001 -From: Andy Shevchenko -Date: Fri, 29 Mar 2024 12:55:24 +0200 -Subject: [PATCH] pinctrl: aw9523: Fix indentation in a few places - -In the comment, function prototype, and array of strings indentation -is kinda broken. Reindent that. - -Signed-off-by: Andy Shevchenko -Message-ID: <20240329105634.712457-11-andy.shevchenko@gmail.com> -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/pinctrl-aw9523.c | 17 ++++++++--------- - 1 file changed, 8 insertions(+), 9 deletions(-) - ---- a/drivers/pinctrl/pinctrl-aw9523.c -+++ b/drivers/pinctrl/pinctrl-aw9523.c -@@ -1,8 +1,7 @@ - // SPDX-License-Identifier: GPL-2.0-only - /* - * Awinic AW9523B i2c pin controller driver -- * Copyright (c) 2020, AngeloGioacchino Del Regno -- * -+ * Copyright (c) 2020, AngeloGioacchino Del Regno - */ - - #include -@@ -139,9 +138,10 @@ static const struct pinctrl_ops aw9523_p - }; - - static const char * const gpio_pwm_groups[] = { -- "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", -- "gpio6", "gpio7", "gpio8", "gpio9", "gpio10", "gpio11", -- "gpio12", "gpio13", "gpio14", "gpio15" -+ "gpio0", "gpio1", "gpio2", "gpio3", /* 0-3 */ -+ "gpio4", "gpio5", "gpio6", "gpio7", /* 4-7 */ -+ "gpio8", "gpio9", "gpio10", "gpio11", /* 8-11 */ -+ "gpio12", "gpio13", "gpio14", "gpio15", /* 11-15 */ - }; - - /* Warning: Do NOT reorder this array */ -@@ -388,8 +388,8 @@ static int aw9523_get_pin_direction(stru - * - * Return: Zero for success or negative number for error - */ --static int aw9523_get_port_state(struct regmap *regmap, u8 pin, -- u8 regbit, unsigned int *state) -+static int aw9523_get_port_state(struct regmap *regmap, u8 pin, u8 regbit, -+ unsigned int *state) - { - u8 reg; - int dir; -@@ -984,8 +984,7 @@ static int aw9523_probe(struct i2c_clien - } - - mutex_init(&awi->i2c_lock); -- lockdep_set_subclass(&awi->i2c_lock, -- i2c_adapter_depth(client->adapter)); -+ lockdep_set_subclass(&awi->i2c_lock, i2c_adapter_depth(client->adapter)); - - pdesc = devm_kzalloc(dev, sizeof(*pdesc), GFP_KERNEL); - if (!pdesc)