diff options
| author | Kees Cook <kees+treewide@kernel.org> | 2026-09-02 15:31:14 -0700 |
|---|---|---|
| committer | Kees Cook <kees@kernel.org> | 2026-09-04 21:37:00 -0700 |
| commit | 3a2c4d55e32ad65efebdb6de44eef3bfa08bb49d (patch) | |
| tree | c65086f9bdcd48c6360fb7cb4598bca084da1f32 /drivers/gpio/gpio-tps68470.c | |
| download | linux-stable-3a2c4d55e32ad65efebdb6de44eef3bfa08bb49d.tar.gz linux-stable-3a2c4d55e32ad65efebdb6de44eef3bfa08bb49d.zip | |
treewide: refresh kmalloc_obj() conversionsgrafted
This is another run of the Coccinelle script for converting kmalloc()
family of allocations to kmalloc_obj() via the existing rules in
scripts/coccinelle/api/kmalloc_objs.cocci
This catches both the set of kmalloc() uses added since the first
kmalloc_obj() conversions in v7.0 and adds a large group missed in the
first pass due to Coccinelle not interacting well with the cleanup.h
scoped_...() family of macros[1]. I worked around this with spatch's
"--macro-file" argument to a file with all the scoped_...() macros mapped
to Coccinelle's YACFE_ITERATOR[2] as that was the closest viable control
flow indicator I could find.
Build tested allmodconfig on x86, arm64, arm, loongarch, mips, powerpc,
riscv, and s390 with no new warnings.
Link: https://lore.kernel.org/lkml/202609021314.8A9C0B8@keescook/ [1]
Link: https://github.com/coccinelle/coccinelle/blob/master/standard.h [2]
Signed-off-by: Kees Cook <kees+treewide@kernel.org>
Diffstat (limited to 'drivers/gpio/gpio-tps68470.c')
| -rw-r--r-- | drivers/gpio/gpio-tps68470.c | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/drivers/gpio/gpio-tps68470.c b/drivers/gpio/gpio-tps68470.c new file mode 100644 index 000000000..8541acecf --- /dev/null +++ b/drivers/gpio/gpio-tps68470.c @@ -0,0 +1,184 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * GPIO driver for TPS68470 PMIC + * + * Copyright (C) 2017 Intel Corporation + * + * Authors: + * Antti Laakso <antti.laakso@intel.com> + * Tianshu Qiu <tian.shu.qiu@intel.com> + * Jian Xu Zheng <jian.xu.zheng@intel.com> + * Yuning Pu <yuning.pu@intel.com> + */ + +#include <linux/gpio/driver.h> +#include <linux/mfd/tps68470.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> + +#define TPS68470_N_LOGIC_OUTPUT 3 +#define TPS68470_N_REGULAR_GPIO 7 +#define TPS68470_N_GPIO (TPS68470_N_LOGIC_OUTPUT + TPS68470_N_REGULAR_GPIO) + +struct tps68470_gpio_data { + struct regmap *tps68470_regmap; + struct gpio_chip gc; +}; + +static int tps68470_gpio_get(struct gpio_chip *gc, unsigned int offset) +{ + struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc); + struct regmap *regmap = tps68470_gpio->tps68470_regmap; + unsigned int reg = TPS68470_REG_GPDO; + int val, ret; + + if (offset >= TPS68470_N_REGULAR_GPIO) { + offset -= TPS68470_N_REGULAR_GPIO; + reg = TPS68470_REG_SGPO; + } + + ret = regmap_read(regmap, reg, &val); + if (ret) { + dev_err(tps68470_gpio->gc.parent, "reg 0x%x read failed\n", + TPS68470_REG_SGPO); + return ret; + } + return !!(val & BIT(offset)); +} + +static int tps68470_gpio_get_direction(struct gpio_chip *gc, + unsigned int offset) +{ + struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc); + struct regmap *regmap = tps68470_gpio->tps68470_regmap; + int val, ret; + + /* rest are always outputs */ + if (offset >= TPS68470_N_REGULAR_GPIO) + return GPIO_LINE_DIRECTION_OUT; + + ret = regmap_read(regmap, TPS68470_GPIO_CTL_REG_A(offset), &val); + if (ret) { + dev_err(tps68470_gpio->gc.parent, "reg 0x%x read failed\n", + TPS68470_GPIO_CTL_REG_A(offset)); + return ret; + } + + val &= TPS68470_GPIO_MODE_MASK; + return val >= TPS68470_GPIO_MODE_OUT_CMOS ? GPIO_LINE_DIRECTION_OUT : + GPIO_LINE_DIRECTION_IN; +} + +static int tps68470_gpio_set(struct gpio_chip *gc, unsigned int offset, + int value) +{ + struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc); + struct regmap *regmap = tps68470_gpio->tps68470_regmap; + unsigned int reg = TPS68470_REG_GPDO; + + if (offset >= TPS68470_N_REGULAR_GPIO) { + reg = TPS68470_REG_SGPO; + offset -= TPS68470_N_REGULAR_GPIO; + } + + return regmap_update_bits(regmap, reg, BIT(offset), + value ? BIT(offset) : 0); +} + +static int tps68470_gpio_output(struct gpio_chip *gc, unsigned int offset, + int value) +{ + struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc); + struct regmap *regmap = tps68470_gpio->tps68470_regmap; + int ret; + + /* Set the initial value */ + ret = tps68470_gpio_set(gc, offset, value); + if (ret) + return ret; + + /* rest are always outputs */ + if (offset >= TPS68470_N_REGULAR_GPIO) + return 0; + + return regmap_update_bits(regmap, TPS68470_GPIO_CTL_REG_A(offset), + TPS68470_GPIO_MODE_MASK, + TPS68470_GPIO_MODE_OUT_CMOS); +} + +static int tps68470_gpio_input(struct gpio_chip *gc, unsigned int offset) +{ + struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc); + struct regmap *regmap = tps68470_gpio->tps68470_regmap; + + /* rest are always outputs */ + if (offset >= TPS68470_N_REGULAR_GPIO) + return -EINVAL; + + return regmap_update_bits(regmap, TPS68470_GPIO_CTL_REG_A(offset), + TPS68470_GPIO_MODE_MASK, 0x00); +} + +static int tps68470_enable_i2c_daisy_chain(struct gpio_chip *gc) +{ + int ret; + + ret = tps68470_gpio_input(gc, 1); + if (ret) + return ret; + + return tps68470_gpio_input(gc, 2); +} + +static const char *tps68470_names[TPS68470_N_GPIO] = { + "gpio.0", "gpio.1", "gpio.2", "gpio.3", + "gpio.4", "gpio.5", "gpio.6", + "s_enable", "s_idle", "s_resetn", +}; + +static int tps68470_gpio_probe(struct platform_device *pdev) +{ + struct tps68470_gpio_data *tps68470_gpio; + int ret; + + tps68470_gpio = devm_kzalloc(&pdev->dev, sizeof(*tps68470_gpio), + GFP_KERNEL); + if (!tps68470_gpio) + return -ENOMEM; + + tps68470_gpio->tps68470_regmap = dev_get_drvdata(pdev->dev.parent); + tps68470_gpio->gc.label = "tps68470-gpio"; + tps68470_gpio->gc.owner = THIS_MODULE; + tps68470_gpio->gc.direction_input = tps68470_gpio_input; + tps68470_gpio->gc.direction_output = tps68470_gpio_output; + tps68470_gpio->gc.get = tps68470_gpio_get; + tps68470_gpio->gc.get_direction = tps68470_gpio_get_direction; + tps68470_gpio->gc.set = tps68470_gpio_set; + tps68470_gpio->gc.can_sleep = true; + tps68470_gpio->gc.names = tps68470_names; + tps68470_gpio->gc.ngpio = TPS68470_N_GPIO; + tps68470_gpio->gc.base = -1; + tps68470_gpio->gc.parent = &pdev->dev; + + ret = devm_gpiochip_add_data(&pdev->dev, &tps68470_gpio->gc, tps68470_gpio); + if (ret) + return ret; + + if (device_property_present(&pdev->dev, "daisy-chain-enable")) + ret = tps68470_enable_i2c_daisy_chain(&tps68470_gpio->gc); + + return ret; +} + +static struct platform_driver tps68470_gpio_driver = { + .driver = { + .name = "tps68470-gpio", + }, + .probe = tps68470_gpio_probe, +}; +module_platform_driver(tps68470_gpio_driver); + +MODULE_ALIAS("platform:tps68470-gpio"); +MODULE_DESCRIPTION("GPIO driver for TPS68470 PMIC"); +MODULE_LICENSE("GPL v2"); |
