aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2024-09-18 10:39:35 +0200
committerLinus Torvalds <torvalds@linux-foundation.org>2024-09-18 10:39:35 +0200
commitcc52dc2fe39ff5dee9916ac2d9381ec3cbf650c0 (patch)
tree7aa085ccdae6edb505aa4aa06996305d032f88f0 /drivers
parent7fced2a78a26630a01f872abe21bb3366acacc82 (diff)
parentd242feaf81d63b25d8c1fb1a68738dc33966a376 (diff)
Merge tag 'pwm/for-6.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/ukleinek/linux
Pull pwm updates from Uwe Kleine-König: "This contains some cleanups to the core and some mostly minor updates to a bunch of drivers and device tree bindings. One thing worth pointing out is that it contains an immutable branch containing support for a new mfd chip (Analog Devices ADP5585) with several sub drivers. Thanks go to Andrew Kreimer, Clark Wang, Conor Dooley, David Lechner, Dmitry Rokosov, Frank Li, Geert Uytterhoeven, George Stark, Jiapeng Chong, Krzysztof Kozlowski, Laurent Pinchart, Liao Chen, Liu Ying, Rob Herring and Wolfram Sang for code contributions and reviews and to Lee Jones for preparing the above mentioned immutable branch" * tag 'pwm/for-6.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/ukleinek/linux: (21 commits) pwm: stm32: Fix a typo dt-bindings: pwm: amlogic: Add new bindings for meson A1 PWM dt-bindings: pwm: amlogic: Add optional power-domains pwm: Switch back to struct platform_driver::remove() dt-bindings: pwm: allwinner,sun4i-a10-pwm: add top-level constraints pwm: axi-pwmgen: use shared macro for version reg pwm: atmel-hlcdc: Drop trailing comma pwm: atmel-hlcdc: Enable module autoloading pwm: omap-dmtimer: Use of_property_read_bool() pwm: adp5585: Set OSC_EN bit to 1 when PWM state is enabled pwm: lp3943: Fix an incorrect type in lp3943_pwm_parse_dt() pwm: Simplify pwm_capture() pwm: lp3943: Use of_property_count_u32_elems() to get property length pwm: Don't export pwm_capture() pwm: Make info in traces about affected pwm more useful dt-bindings: pwm: renesas,tpu: Add r8a779h0 support dt-bindings: pwm: renesas,pwm-rcar: Add r8a779h0 support pwm: adp5585: Add Analog Devices ADP5585 support gpio: adp5585: Add Analog Devices ADP5585 support mfd: adp5585: Add Analog Devices ADP5585 core support ...
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpio/Kconfig7
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/gpio-adp5585.c229
-rw-r--r--drivers/mfd/Kconfig12
-rw-r--r--drivers/mfd/Makefile1
-rw-r--r--drivers/mfd/adp5585.c205
-rw-r--r--drivers/pwm/Kconfig7
-rw-r--r--drivers/pwm/Makefile1
-rw-r--r--drivers/pwm/core.c13
-rw-r--r--drivers/pwm/pwm-adp5585.c188
-rw-r--r--drivers/pwm/pwm-atmel-hlcdc.c7
-rw-r--r--drivers/pwm/pwm-atmel-tcb.c2
-rw-r--r--drivers/pwm/pwm-axi-pwmgen.c3
-rw-r--r--drivers/pwm/pwm-clk.c2
-rw-r--r--drivers/pwm/pwm-hibvt.c2
-rw-r--r--drivers/pwm/pwm-img.c2
-rw-r--r--drivers/pwm/pwm-lp3943.c10
-rw-r--r--drivers/pwm/pwm-lpc18xx-sct.c2
-rw-r--r--drivers/pwm/pwm-omap-dmtimer.c4
-rw-r--r--drivers/pwm/pwm-rcar.c2
-rw-r--r--drivers/pwm/pwm-rockchip.c2
-rw-r--r--drivers/pwm/pwm-sifive.c2
-rw-r--r--drivers/pwm/pwm-stm32.c2
-rw-r--r--drivers/pwm/pwm-sun4i.c2
-rw-r--r--drivers/pwm/pwm-tegra.c2
-rw-r--r--drivers/pwm/pwm-tiecap.c2
-rw-r--r--drivers/pwm/pwm-tiehrpwm.c2
27 files changed, 680 insertions, 34 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 58f43bcced7c..d93cd4f722b4 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -1233,6 +1233,13 @@ config GPIO_ADP5520
This option enables support for on-chip GPIO found
on Analog Devices ADP5520 PMICs.
+config GPIO_ADP5585
+ tristate "GPIO Support for ADP5585"
+ depends on MFD_ADP5585
+ help
+ This option enables support for the GPIO function found in the Analog
+ Devices ADP5585.
+
config GPIO_ALTERA_A10SR
tristate "Altera Arria10 System Resource GPIO"
depends on MFD_ALTERA_A10SR
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 64dd6d9d730d..1429e8c0229b 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_GPIO_74X164) += gpio-74x164.o
obj-$(CONFIG_GPIO_74XX_MMIO) += gpio-74xx-mmio.o
obj-$(CONFIG_GPIO_ADNP) += gpio-adnp.o
obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o
+obj-$(CONFIG_GPIO_ADP5585) += gpio-adp5585.o
obj-$(CONFIG_GPIO_AGGREGATOR) += gpio-aggregator.o
obj-$(CONFIG_GPIO_ALTERA_A10SR) += gpio-altera-a10sr.o
obj-$(CONFIG_GPIO_ALTERA) += gpio-altera.o
diff --git a/drivers/gpio/gpio-adp5585.c b/drivers/gpio/gpio-adp5585.c
new file mode 100644
index 000000000000..000d31f09671
--- /dev/null
+++ b/drivers/gpio/gpio-adp5585.c
@@ -0,0 +1,229 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Analog Devices ADP5585 GPIO driver
+ *
+ * Copyright 2022 NXP
+ * Copyright 2024 Ideas on Board Oy
+ */
+
+#include <linux/device.h>
+#include <linux/gpio/driver.h>
+#include <linux/mfd/adp5585.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/types.h>
+
+#define ADP5585_GPIO_MAX 11
+
+struct adp5585_gpio_dev {
+ struct gpio_chip gpio_chip;
+ struct regmap *regmap;
+};
+
+static int adp5585_gpio_get_direction(struct gpio_chip *chip, unsigned int off)
+{
+ struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(chip);
+ unsigned int bank = ADP5585_BANK(off);
+ unsigned int bit = ADP5585_BIT(off);
+ unsigned int val;
+
+ regmap_read(adp5585_gpio->regmap, ADP5585_GPIO_DIRECTION_A + bank, &val);
+
+ return val & bit ? GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN;
+}
+
+static int adp5585_gpio_direction_input(struct gpio_chip *chip, unsigned int off)
+{
+ struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(chip);
+ unsigned int bank = ADP5585_BANK(off);
+ unsigned int bit = ADP5585_BIT(off);
+
+ return regmap_clear_bits(adp5585_gpio->regmap,
+ ADP5585_GPIO_DIRECTION_A + bank, bit);
+}
+
+static int adp5585_gpio_direction_output(struct gpio_chip *chip, unsigned int off, int val)
+{
+ struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(chip);
+ unsigned int bank = ADP5585_BANK(off);
+ unsigned int bit = ADP5585_BIT(off);
+ int ret;
+
+ ret = regmap_update_bits(adp5585_gpio->regmap,
+ ADP5585_GPO_DATA_OUT_A + bank, bit,
+ val ? bit : 0);
+ if (ret)
+ return ret;
+
+ return regmap_set_bits(adp5585_gpio->regmap,
+ ADP5585_GPIO_DIRECTION_A + bank, bit);
+}
+
+static int adp5585_gpio_get_value(struct gpio_chip *chip, unsigned int off)
+{
+ struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(chip);
+ unsigned int bank = ADP5585_BANK(off);
+ unsigned int bit = ADP5585_BIT(off);
+ unsigned int reg;
+ unsigned int val;
+
+ /*
+ * The input status register doesn't reflect the pin state when the
+ * GPIO is configured as an output. Check the direction, and read the
+ * input status from GPI_STATUS or output value from GPO_DATA_OUT
+ * accordingly.
+ *
+ * We don't need any locking, as concurrent access to the same GPIO
+ * isn't allowed by the GPIO API, so there's no risk of the
+ * .direction_input(), .direction_output() or .set() operations racing
+ * with this.
+ */
+ regmap_read(adp5585_gpio->regmap, ADP5585_GPIO_DIRECTION_A + bank, &val);
+ reg = val & bit ? ADP5585_GPO_DATA_OUT_A : ADP5585_GPI_STATUS_A;
+ regmap_read(adp5585_gpio->regmap, reg + bank, &val);
+
+ return !!(val & bit);
+}
+
+static void adp5585_gpio_set_value(struct gpio_chip *chip, unsigned int off, int val)
+{
+ struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(chip);
+ unsigned int bank = ADP5585_BANK(off);
+ unsigned int bit = ADP5585_BIT(off);
+
+ regmap_update_bits(adp5585_gpio->regmap, ADP5585_GPO_DATA_OUT_A + bank,
+ bit, val ? bit : 0);
+}
+
+static int adp5585_gpio_set_bias(struct adp5585_gpio_dev *adp5585_gpio,
+ unsigned int off, unsigned int bias)
+{
+ unsigned int bit, reg, mask, val;
+
+ /*
+ * The bias configuration fields are 2 bits wide and laid down in
+ * consecutive registers ADP5585_RPULL_CONFIG_*, with a hole of 4 bits
+ * after R5.
+ */
+ bit = off * 2 + (off > 5 ? 4 : 0);
+ reg = ADP5585_RPULL_CONFIG_A + bit / 8;
+ mask = ADP5585_Rx_PULL_CFG_MASK << (bit % 8);
+ val = bias << (bit % 8);
+
+ return regmap_update_bits(adp5585_gpio->regmap, reg, mask, val);
+}
+
+static int adp5585_gpio_set_drive(struct adp5585_gpio_dev *adp5585_gpio,
+ unsigned int off, enum pin_config_param drive)
+{
+ unsigned int bank = ADP5585_BANK(off);
+ unsigned int bit = ADP5585_BIT(off);
+
+ return regmap_update_bits(adp5585_gpio->regmap,
+ ADP5585_GPO_OUT_MODE_A + bank, bit,
+ drive == PIN_CONFIG_DRIVE_OPEN_DRAIN ? bit : 0);
+}
+
+static int adp5585_gpio_set_debounce(struct adp5585_gpio_dev *adp5585_gpio,
+ unsigned int off, unsigned int debounce)
+{
+ unsigned int bank = ADP5585_BANK(off);
+ unsigned int bit = ADP5585_BIT(off);
+
+ return regmap_update_bits(adp5585_gpio->regmap,
+ ADP5585_DEBOUNCE_DIS_A + bank, bit,
+ debounce ? 0 : bit);
+}
+
+static int adp5585_gpio_set_config(struct gpio_chip *chip, unsigned int off,
+ unsigned long config)
+{
+ struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(chip);
+ enum pin_config_param param = pinconf_to_config_param(config);
+ u32 arg = pinconf_to_config_argument(config);
+
+ switch (param) {
+ case PIN_CONFIG_BIAS_DISABLE:
+ return adp5585_gpio_set_bias(adp5585_gpio, off,
+ ADP5585_Rx_PULL_CFG_DISABLE);
+
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ return adp5585_gpio_set_bias(adp5585_gpio, off, arg ?
+ ADP5585_Rx_PULL_CFG_PD_300K :
+ ADP5585_Rx_PULL_CFG_DISABLE);
+
+ case PIN_CONFIG_BIAS_PULL_UP:
+ return adp5585_gpio_set_bias(adp5585_gpio, off, arg ?
+ ADP5585_Rx_PULL_CFG_PU_300K :
+ ADP5585_Rx_PULL_CFG_DISABLE);
+
+ case PIN_CONFIG_DRIVE_OPEN_DRAIN:
+ case PIN_CONFIG_DRIVE_PUSH_PULL:
+ return adp5585_gpio_set_drive(adp5585_gpio, off, param);
+
+ case PIN_CONFIG_INPUT_DEBOUNCE:
+ return adp5585_gpio_set_debounce(adp5585_gpio, off, arg);
+
+ default:
+ return -ENOTSUPP;
+ };
+}
+
+static int adp5585_gpio_probe(struct platform_device *pdev)
+{
+ struct adp5585_dev *adp5585 = dev_get_drvdata(pdev->dev.parent);
+ struct adp5585_gpio_dev *adp5585_gpio;
+ struct device *dev = &pdev->dev;
+ struct gpio_chip *gc;
+ int ret;
+
+ adp5585_gpio = devm_kzalloc(dev, sizeof(*adp5585_gpio), GFP_KERNEL);
+ if (!adp5585_gpio)
+ return -ENOMEM;
+
+ adp5585_gpio->regmap = adp5585->regmap;
+
+ device_set_of_node_from_dev(dev, dev->parent);
+
+ gc = &adp5585_gpio->gpio_chip;
+ gc->parent = dev;
+ gc->get_direction = adp5585_gpio_get_direction;
+ gc->direction_input = adp5585_gpio_direction_input;
+ gc->direction_output = adp5585_gpio_direction_output;
+ gc->get = adp5585_gpio_get_value;
+ gc->set = adp5585_gpio_set_value;
+ gc->set_config = adp5585_gpio_set_config;
+ gc->can_sleep = true;
+
+ gc->base = -1;
+ gc->ngpio = ADP5585_GPIO_MAX;
+ gc->label = pdev->name;
+ gc->owner = THIS_MODULE;
+
+ ret = devm_gpiochip_add_data(dev, &adp5585_gpio->gpio_chip,
+ adp5585_gpio);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to add GPIO chip\n");
+
+ return 0;
+}
+
+static const struct platform_device_id adp5585_gpio_id_table[] = {
+ { "adp5585-gpio" },
+ { /* Sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, adp5585_gpio_id_table);
+
+static struct platform_driver adp5585_gpio_driver = {
+ .driver = {
+ .name = "adp5585-gpio",
+ },
+ .probe = adp5585_gpio_probe,
+ .id_table = adp5585_gpio_id_table,
+};
+module_platform_driver(adp5585_gpio_driver);
+
+MODULE_AUTHOR("Haibo Chen <haibo.chen@nxp.com>");
+MODULE_DESCRIPTION("GPIO ADP5585 Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index bc8be2e593b6..f9325bcce1b9 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -20,6 +20,18 @@ config MFD_CS5535
This is the core driver for CS5535/CS5536 MFD functions. This is
necessary for using the board's GPIO and MFGPT functionality.
+config MFD_ADP5585
+ tristate "Analog Devices ADP5585 keypad decoder and I/O expander driver"
+ select MFD_CORE
+ select REGMAP_I2C
+ depends on I2C
+ depends on OF || COMPILE_TEST
+ help
+ Say yes here to add support for the Analog Devices ADP5585 GPIO
+ expander, PWM and keypad controller. This includes the I2C driver and
+ the core APIs _only_, you have to select individual components like
+ the GPIO and PWM functions under the corresponding menus.
+
config MFD_ALTERA_A10SR
bool "Altera Arria10 DevKit System Resource chip"
depends on ARCH_INTEL_SOCFPGA && SPI_MASTER=y && OF
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 02b651cd7535..2a9f91e81af8 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -193,6 +193,7 @@ obj-$(CONFIG_MFD_DB8500_PRCMU) += db8500-prcmu.o
obj-$(CONFIG_AB8500_CORE) += ab8500-core.o ab8500-sysctrl.o
obj-$(CONFIG_MFD_TIMBERDALE) += timberdale.o
obj-$(CONFIG_PMIC_ADP5520) += adp5520.o
+obj-$(CONFIG_MFD_ADP5585) += adp5585.o
obj-$(CONFIG_MFD_KEMPLD) += kempld-core.o
obj-$(CONFIG_MFD_INTEL_QUARK_I2C_GPIO) += intel_quark_i2c_gpio.o
obj-$(CONFIG_LPC_SCH) += lpc_sch.o
diff --git a/drivers/mfd/adp5585.c b/drivers/mfd/adp5585.c
new file mode 100644
index 000000000000..160e0b38106a
--- /dev/null
+++ b/drivers/mfd/adp5585.c
@@ -0,0 +1,205 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Analog Devices ADP5585 I/O expander, PWM controller and keypad controller
+ *
+ * Copyright 2022 NXP
+ * Copyright 2024 Ideas on Board Oy
+ */
+
+#include <linux/array_size.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/mfd/adp5585.h>
+#include <linux/mfd/core.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/types.h>
+
+static const struct mfd_cell adp5585_devs[] = {
+ { .name = "adp5585-gpio", },
+ { .name = "adp5585-pwm", },
+};
+
+static const struct regmap_range adp5585_volatile_ranges[] = {
+ regmap_reg_range(ADP5585_ID, ADP5585_GPI_STATUS_B),
+};
+
+static const struct regmap_access_table adp5585_volatile_regs = {
+ .yes_ranges = adp5585_volatile_ranges,
+ .n_yes_ranges = ARRAY_SIZE(adp5585_volatile_ranges),
+};
+
+/*
+ * Chip variants differ in the default configuration of pull-up and pull-down
+ * resistors, and therefore have different default register values:
+ *
+ * - The -00, -01 and -03 variants (collectively referred to as
+ * ADP5585_REGMAP_00) have pull-up on all GPIO pins by default.
+ * - The -02 variant has no default pull-up or pull-down resistors.
+ * - The -04 variant has default pull-down resistors on all GPIO pins.
+ */
+
+static const u8 adp5585_regmap_defaults_00[ADP5585_MAX_REG + 1] = {
+ /* 0x00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ /* 0x08 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ /* 0x10 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ /* 0x18 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ /* 0x20 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ /* 0x28 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ /* 0x30 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ /* 0x38 */ 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static const u8 adp5585_regmap_defaults_02[ADP5585_MAX_REG + 1] = {
+ /* 0x00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ /* 0x08 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ /* 0x10 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3,
+ /* 0x18 */ 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ /* 0x20 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ /* 0x28 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ /* 0x30 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ /* 0x38 */ 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static const u8 adp5585_regmap_defaults_04[ADP5585_MAX_REG + 1] = {
+ /* 0x00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ /* 0x08 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ /* 0x10 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55,
+ /* 0x18 */ 0x05, 0x55, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ /* 0x20 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ /* 0x28 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ /* 0x30 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ /* 0x38 */ 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+enum adp5585_regmap_type {
+ ADP5585_REGMAP_00,
+ ADP5585_REGMAP_02,
+ ADP5585_REGMAP_04,
+};
+
+static const struct regmap_config adp5585_regmap_configs[] = {
+ [ADP5585_REGMAP_00] = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = ADP5585_MAX_REG,
+ .volatile_table = &adp5585_volatile_regs,
+ .cache_type = REGCACHE_MAPLE,
+ .reg_defaults_raw = adp5585_regmap_defaults_00,
+ .num_reg_defaults_raw = sizeof(adp5585_regmap_defaults_00),
+ },
+ [ADP5585_REGMAP_02] = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = ADP5585_MAX_REG,
+ .volatile_table = &adp5585_volatile_regs,
+ .cache_type = REGCACHE_MAPLE,
+ .reg_defaults_raw = adp5585_regmap_defaults_02,
+ .num_reg_defaults_raw = sizeof(adp5585_regmap_defaults_02),
+ },
+ [ADP5585_REGMAP_04] = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = ADP5585_MAX_REG,
+ .volatile_table = &adp5585_volatile_regs,
+ .cache_type = REGCACHE_MAPLE,
+ .reg_defaults_raw = adp5585_regmap_defaults_04,
+ .num_reg_defaults_raw = sizeof(adp5585_regmap_defaults_04),
+ },
+};
+
+static int adp5585_i2c_probe(struct i2c_client *i2c)
+{
+ const struct regmap_config *regmap_config;
+ struct adp5585_dev *adp5585;
+ unsigned int id;
+ int ret;
+
+ adp5585 = devm_kzalloc(&i2c->dev, sizeof(*adp5585), GFP_KERNEL);
+ if (!adp5585)
+ return -ENOMEM;
+
+ i2c_set_clientdata(i2c, adp5585);
+
+ regmap_config = i2c_get_match_data(i2c);
+ adp5585->regmap = devm_regmap_init_i2c(i2c, regmap_config);
+ if (IS_ERR(adp5585->regmap))
+ return dev_err_probe(&i2c->dev, PTR_ERR(adp5585->regmap),
+ "Failed to initialize register map\n");
+
+ ret = regmap_read(adp5585->regmap, ADP5585_ID, &id);
+ if (ret)
+ return dev_err_probe(&i2c->dev, ret,
+ "Failed to read device ID\n");
+
+ if ((id & ADP5585_MAN_ID_MASK) != ADP5585_MAN_ID_VALUE)
+ return dev_err_probe(&i2c->dev, -ENODEV,
+ "Invalid device ID 0x%02x\n", id);
+
+ ret = devm_mfd_add_devices(&i2c->dev, PLATFORM_DEVID_AUTO,
+ adp5585_devs, ARRAY_SIZE(adp5585_devs),
+ NULL, 0, NULL);
+ if (ret)
+ return dev_err_probe(&i2c->dev, ret,
+ "Failed to add child devices\n");
+
+ return 0;
+}
+
+static int adp5585_suspend(struct device *dev)
+{
+ struct adp5585_dev *adp5585 = dev_get_drvdata(dev);
+
+ regcache_cache_only(adp5585->regmap, true);
+
+ return 0;
+}
+
+static int adp5585_resume(struct device *dev)
+{
+ struct adp5585_dev *adp5585 = dev_get_drvdata(dev);
+
+ regcache_cache_only(adp5585->regmap, false);
+ regcache_mark_dirty(adp5585->regmap);
+
+ return regcache_sync(adp5585->regmap);
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(adp5585_pm, adp5585_suspend, adp5585_resume);
+
+static const struct of_device_id adp5585_of_match[] = {
+ {
+ .compatible = "adi,adp5585-00",
+ .data = &adp5585_regmap_configs[ADP5585_REGMAP_00],
+ }, {
+ .compatible = "adi,adp5585-01",
+ .data = &adp5585_regmap_configs[ADP5585_REGMAP_00],
+ }, {
+ .compatible = "adi,adp5585-02",
+ .data = &adp5585_regmap_configs[ADP5585_REGMAP_02],
+ }, {
+ .compatible = "adi,adp5585-03",
+ .data = &adp5585_regmap_configs[ADP5585_REGMAP_00],
+ }, {
+ .compatible = "adi,adp5585-04",
+ .data = &adp5585_regmap_configs[ADP5585_REGMAP_04],
+ },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, adp5585_of_match);
+
+static struct i2c_driver adp5585_i2c_driver = {
+ .driver = {
+ .name = "adp5585",
+ .of_match_table = adp5585_of_match,
+ .pm = pm_sleep_ptr(&adp5585_pm),
+ },
+ .probe = adp5585_i2c_probe,
+};
+module_i2c_driver(adp5585_i2c_driver);
+
+MODULE_DESCRIPTION("ADP5585 core driver");
+MODULE_AUTHOR("Haibo Chen <haibo.chen@nxp.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index 3e53838990f5..0915c1e7df16 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -47,6 +47,13 @@ config PWM_AB8500
To compile this driver as a module, choose M here: the module
will be called pwm-ab8500.
+config PWM_ADP5585
+ tristate "ADP5585 PWM support"
+ depends on MFD_ADP5585
+ help
+ This option enables support for the PWM function found in the Analog
+ Devices ADP5585.
+
config PWM_APPLE
tristate "Apple SoC PWM support"
depends on ARCH_APPLE || COMPILE_TEST
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index 0be4f3e6dd43..9081e0c0e9e0 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_PWM) += core.o
obj-$(CONFIG_PWM_AB8500) += pwm-ab8500.o
+obj-$(CONFIG_PWM_ADP5585) += pwm-adp5585.o
obj-$(CONFIG_PWM_APPLE) += pwm-apple.o
obj-$(CONFIG_PWM_ATMEL) += pwm-atmel.o
obj-$(CONFIG_PWM_ATMEL_HLCDC_PWM) += pwm-atmel-hlcdc.o
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index 8acbcf5b6673..6e752e148b98 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -325,20 +325,19 @@ EXPORT_SYMBOL_GPL(pwm_adjust_config);
*
* Returns: 0 on success or a negative error code on failure.
*/
-int pwm_capture(struct pwm_device *pwm, struct pwm_capture *result,
- unsigned long timeout)
+static int pwm_capture(struct pwm_device *pwm, struct pwm_capture *result,
+ unsigned long timeout)
{
- if (!pwm || !pwm->chip->ops)
- return -EINVAL;
+ struct pwm_chip *chip = pwm->chip;
+ const struct pwm_ops *ops = chip->ops;
- if (!pwm->chip->ops->capture)
+ if (!ops->capture)
return -ENOSYS;
guard(mutex)(&pwm_lock);
- return pwm->chip->ops->capture(pwm->chip, pwm, result, timeout);
+ return ops->capture(chip, pwm, result, timeout);
}
-EXPORT_SYMBOL_GPL(pwm_capture);
static struct pwm_chip *pwmchip_find_by_name(const char *name)
{
diff --git a/drivers/pwm/pwm-adp5585.c b/drivers/pwm/pwm-adp5585.c
new file mode 100644
index 000000000000..40472ac5db64
--- /dev/null
+++ b/drivers/pwm/pwm-adp5585.c
@@ -0,0 +1,188 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Analog Devices ADP5585 PWM driver
+ *
+ * Copyright 2022 NXP
+ * Copyright 2024 Ideas on Board Oy
+ *
+ * Limitations:
+ * - The .apply() operation executes atomically, but may not wait for the
+ * period to complete (this is not documented and would need to be tested).
+ * - Disabling the PWM drives the output pin to a low level immediately.
+ * - The hardware can only generate normal polarity output.
+ */
+
+#include <asm/byteorder.h>
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/math64.h>
+#include <linux/mfd/adp5585.h>
+#include <linux/minmax.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/regmap.h>
+#include <linux/time.h>
+#include <linux/types.h>
+
+#define ADP5585_PWM_CHAN_NUM 1
+
+#define ADP5585_PWM_OSC_FREQ_HZ 1000000U
+#define ADP5585_PWM_MIN_PERIOD_NS (2ULL * NSEC_PER_SEC / ADP5585_PWM_OSC_FREQ_HZ)
+#define ADP5585_PWM_MAX_PERIOD_NS (2ULL * 0xffff * NSEC_PER_SEC / ADP5585_PWM_OSC_FREQ_HZ)
+
+static int pwm_adp5585_request(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+ struct regmap *regmap = pwmchip_get_drvdata(chip);
+
+ /* Configure the R3 pin as PWM output. */
+ return regmap_update_bits(regmap, ADP5585_PIN_CONFIG_C,
+ ADP5585_R3_EXTEND_CFG_MASK,
+ ADP5585_R3_EXTEND_CFG_PWM_OUT);
+}
+
+static void pwm_adp5585_free(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+ struct regmap *regmap = pwmchip_get_drvdata(chip);
+
+ regmap_update_bits(regmap, ADP5585_PIN_CONFIG_C,
+ ADP5585_R3_EXTEND_CFG_MASK,
+ ADP5585_R3_EXTEND_CFG_GPIO4);
+}
+
+static int pwm_adp5585_apply(struct pwm_chip *chip,
+ struct pwm_device *pwm,
+ const struct pwm_state *state)
+{
+ struct regmap *regmap = pwmchip_get_drvdata(chip);
+ u64 period, duty_cycle;
+ u32 on, off;
+ __le16 val;
+ int ret;
+
+ if (!state->enabled) {
+ regmap_clear_bits(regmap, ADP5585_GENERAL_CFG, ADP5585_OSC_EN);
+ regmap_clear_bits(regmap, ADP5585_PWM_CFG, ADP5585_PWM_EN);
+ return 0;
+ }
+
+ if (state->polarity != PWM_POLARITY_NORMAL)
+ return -EINVAL;
+
+ if (state->period < ADP5585_PWM_MIN_PERIOD_NS)
+ return -EINVAL;
+
+ period = min(state->period, ADP5585_PWM_MAX_PERIOD_NS);
+ duty_cycle = min(state->duty_cycle, period);
+
+ /*
+ * Compute the on and off time. As the internal oscillator frequency is
+ * 1MHz, the calculation can be simplified without loss of precision.
+ */
+ on = div_u64(duty_cycle, NSEC_PER_SEC / ADP5585_PWM_OSC_FREQ_HZ);
+ off = div_u64(period, NSEC_PER_SEC / ADP5585_PWM_OSC_FREQ_HZ) - on;
+
+ val = cpu_to_le16(off);
+ ret = regmap_bulk_write(regmap, ADP5585_PWM_OFFT_LOW, &val, 2);
+ if (ret)
+ return ret;
+
+ val = cpu_to_le16(on);
+ ret = regmap_bulk_write(regmap, ADP5585_PWM_ONT_LOW, &val, 2);
+ if (ret)
+ return ret;
+
+ /* Enable PWM in continuous mode and no external AND'ing. */
+ ret = regmap_update_bits(regmap, ADP5585_PWM_CFG,
+ ADP5585_PWM_IN_AND | ADP5585_PWM_MODE |
+ ADP5585_PWM_EN, ADP5585_PWM_EN);
+ if (ret)
+ return ret;
+
+ ret = regmap_set_bits(regmap, ADP5585_GENERAL_CFG, ADP5585_OSC_EN);
+ if (ret)
+ return ret;
+
+ return regmap_set_bits(regmap, ADP5585_PWM_CFG, ADP5585_PWM_EN);
+}
+
+static int pwm_adp5585_get_state(struct pwm_chip *chip,
+ struct pwm_device *pwm,
+ struct pwm_state *state)
+{
+ struct regmap *regmap = pwmchip_get_drvdata(chip);
+ unsigned int on, off;
+ unsigned int val;
+ __le16 on_off;
+ int ret;
+
+ ret = regmap_bulk_read(regmap, ADP5585_PWM_OFFT_LOW, &on_off, 2);
+ if (ret)
+ return ret;
+ off = le16_to_cpu(on_off);
+
+ ret = regmap_bulk_read(regmap, ADP5585_PWM_ONT_LOW, &on_off, 2);
+ if (ret)
+ return ret;
+ on = le16_to_cpu(on_off);
+
+ state->duty_cycle = on * (NSEC_PER_SEC / ADP5585_PWM_OSC_FREQ_HZ);
+ state->period = (on + off) * (NSEC_PER_SEC / ADP5585_PWM_OSC_FREQ_HZ);
+
+ state->polarity = PWM_POLARITY_NORMAL;
+
+ regmap_read(regmap, ADP5585_PWM_CFG, &val);
+ state->enabled = !!(val & ADP5585_PWM_EN);
+
+ return 0;
+}
+
+static const struct pwm_ops adp5585_pwm_ops = {
+ .request = pwm_adp5585_request,
+ .free = pwm_adp5585_free,
+ .apply = pwm_adp5585_apply,
+ .get_state = pwm_adp5585_get_state,
+};
+
+static int adp5585_pwm_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct adp5585_dev *adp5585 = dev_get_drvdata(dev->parent);
+ struct pwm_chip *chip;
+ int ret;
+
+ chip = devm_pwmchip_alloc(dev, ADP5585_PWM_CHAN_NUM, 0);
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+
+ device_set_of_node_from_dev(dev, dev->parent);
+
+ pwmchip_set_drvdata(chip, adp5585->regmap);
+ chip->ops = &adp5585_pwm_ops;
+
+ ret = devm_pwmchip_add(dev, chip);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to add PWM chip\n");
+
+ return 0;
+}
+
+static const struct platform_device_id adp5585_pwm_id_table[] = {
+ { "adp5585-pwm" },
+ { /* Sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, adp5585_pwm_id_table);
+
+static struct platform_driver adp5585_pwm_driver = {
+ .driver = {
+ .name = "adp5585-pwm",
+ },
+ .probe = adp5585_pwm_probe,
+ .id_table = adp5585_pwm_id_table,
+};
+module_platform_driver(adp5585_pwm_driver);
+
+MODULE_AUTHOR("Xiaoning Wang <xiaoning.wang@nxp.com>");
+MODULE_DESCRIPTION("ADP5585 PWM Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pwm/pwm-atmel-hlcdc.c b/drivers/pwm/pwm-atmel-hlcdc.c
index 2afb302be02c..387a0d1fa4f2 100644
--- a/drivers/pwm/pwm-atmel-hlcdc.c
+++ b/drivers/pwm/pwm-atmel-hlcdc.c
@@ -234,7 +234,7 @@ static const struct of_device_id atmel_hlcdc_dt_ids[] = {
.data = &atmel_hlcdc_pwm_sama5d3_errata,
},
{ .compatible = "microchip,sam9x60-hlcdc", },
- { /* sentinel */ },
+ { /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, atmel_hlcdc_dt_ids);
@@ -288,8 +288,9 @@ static void atmel_hlcdc_pwm_remove(struct platform_device *pdev)
static const struct of_device_id atmel_hlcdc_pwm_dt_ids[] = {
{ .compatible = "atmel,hlcdc-pwm" },
- { /* sentinel */ },
+ { /* sentinel */ }
};
+MODULE_DEVICE_TABLE(of, atmel_hlcdc_pwm_dt_ids);
static struct platform_driver atmel_hlcdc_pwm_driver = {
.driver = {
@@ -298,7 +299,7 @@ static struct platform_driver atmel_hlcdc_pwm_driver = {
.pm = pm_ptr(&atmel_hlcdc_pwm_pm_ops),
},
.probe = atmel_hlcdc_pwm_probe,
- .remove_new = atmel_hlcdc_pwm_remove,
+ .remove = atmel_hlcdc_pwm_remove,
};
module_platform_driver(atmel_hlcdc_pwm_driver);
diff --git a/drivers/pwm/pwm-atmel-tcb.c b/drivers/pwm/pwm-atmel-tcb.c
index f9a9c12cbcdd..5ee4254d1e48 100644
--- a/drivers/pwm/pwm-atmel-tcb.c
+++ b/drivers/pwm/pwm-atmel-tcb.c
@@ -527,7 +527,7 @@ static struct platform_driver atmel_tcb_pwm_driver = {
.pm = pm_ptr(&atmel_tcb_pwm_pm_ops),
},
.probe = atmel_tcb_pwm_probe,
- .remove_new = atmel_tcb_pwm_remove,
+ .remove = atmel_tcb_pwm_remove,
};
module_platform_driver(atmel_tcb_pwm_driver);
diff --git a/drivers/pwm/pwm-axi-pwmgen.c b/drivers/pwm/pwm-axi-pwmgen.c
index 3ad60edf20a5..b5477659ba18 100644
--- a/drivers/pwm/pwm-axi-pwmgen.c
+++ b/drivers/pwm/pwm-axi-pwmgen.c
@@ -29,7 +29,6 @@
#include <linux/regmap.h>
#include <linux/slab.h>
-#define AXI_PWMGEN_REG_CORE_VERSION 0x00
#define AXI_PWMGEN_REG_ID 0x04
#define AXI_PWMGEN_REG_SCRATCHPAD 0x08
#define AXI_PWMGEN_REG_CORE_MAGIC 0x0C
@@ -145,7 +144,7 @@ static int axi_pwmgen_setup(struct regmap *regmap, struct device *dev)
"failed to read expected value from register: got %08x, expected %08x\n",
val, AXI_PWMGEN_REG_CORE_MAGIC_VAL);
- ret = regmap_read(regmap, AXI_PWMGEN_REG_CORE_VERSION, &val);
+ ret = regmap_read(regmap, ADI_AXI_REG_VERSION, &val);
if (ret)
return ret;
diff --git a/drivers/pwm/pwm-clk.c b/drivers/pwm/pwm-clk.c
index c19a482d7e28..f8f5af57acba 100644
--- a/drivers/pwm/pwm-clk.c
+++ b/drivers/pwm/pwm-clk.c
@@ -130,7 +130,7 @@ static struct platform_driver pwm_clk_driver = {
.of_match_table = pwm_clk_dt_ids,
},
.probe = pwm_clk_probe,
- .remove_new = pwm_clk_remove,
+ .remove = pwm_clk_remove,
};
module_platform_driver(pwm_clk_driver);
diff --git a/drivers/pwm/pwm-hibvt.c b/drivers/pwm/pwm-hibvt.c
index 2eb0b13d4e10..e02ee6383dbc 100644
--- a/drivers/pwm/pwm-hibvt.c
+++ b/drivers/pwm/pwm-hibvt.c
@@ -276,7 +276,7 @@ static struct platform_driver hibvt_pwm_driver = {
.of_match_table = hibvt_pwm_of_match,
},
.probe = hibvt_pwm_probe,
- .remove_new = hibvt_pwm_remove,
+ .remove = hibvt_pwm_remove,
};
module_platform_driver(hibvt_pwm_driver);
diff --git a/drivers/pwm/pwm-img.c b/drivers/pwm/pwm-img.c
index d6596583ed4e..71542956feca 100644
--- a/drivers/pwm/pwm-img.c
+++ b/drivers/pwm/pwm-img.c
@@ -416,7 +416,7 @@ static struct platform_driver img_pwm_driver = {
.of_match_table = img_pwm_of_match,
},
.probe = img_pwm_probe,
- .remove_new = img_pwm_remove,
+ .remove = img_pwm_remove,
};
module_platform_driver(img_pwm_driver);
diff --git a/drivers/pwm/pwm-lp3943.c b/drivers/pwm/pwm-lp3943.c
index 61189cea1046..90b0733c00c1 100644
--- a/drivers/pwm/pwm-lp3943.c
+++ b/drivers/pwm/pwm-lp3943.c
@@ -218,8 +218,7 @@ static int lp3943_pwm_parse_dt(struct device *dev,
struct lp3943_platform_data *pdata;
struct lp3943_pwm_map *pwm_map;
enum lp3943_pwm_output *output;
- int i, err, proplen, count = 0;
- u32 num_outputs;
+ int i, err, num_outputs, count = 0;
if (!node)
return -EINVAL;
@@ -234,11 +233,8 @@ static int lp3943_pwm_parse_dt(struct device *dev,
*/
for (i = 0; i < LP3943_NUM_PWMS; i++) {
- if (!of_get_property(node, name[i], &proplen))
- continue;
-
- num_outputs = proplen / sizeof(u32);
- if (num_outputs == 0)
+ num_outputs = of_property_count_u32_elems(node, name[i]);
+ if (num_outputs <= 0)
continue;
output = devm_kcalloc(dev, num_outputs, sizeof(*output),
diff --git a/drivers/pwm/pwm-lpc18xx-sct.c b/drivers/pwm/pwm-lpc18xx-sct.c
index 04b76d257fd8..f351baa63453 100644
--- a/drivers/pwm/pwm-lpc18xx-sct.c
+++ b/drivers/pwm/pwm-lpc18xx-sct.c
@@ -446,7 +446,7 @@ static struct platform_driver lpc18xx_pwm_driver = {
.of_match_table = lpc18xx_pwm_of_match,
},
.probe = lpc18xx_pwm_probe,
- .remove_new = lpc18xx_pwm_remove,
+ .remove = lpc18xx_pwm_remove,
};
module_platform_driver(lpc18xx_pwm_driver);
diff --git a/drivers/pwm/pwm-omap-dmtimer.c b/drivers/pwm/pwm-omap-dmtimer.c
index cd51c4a938f5..1858a77401f8 100644
--- a/drivers/pwm/pwm-omap-dmtimer.c
+++ b/drivers/pwm/pwm-omap-dmtimer.c
@@ -355,7 +355,7 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev)
goto err_platdata;
}
- if (!of_get_property(timer, "ti,timer-pwm", NULL)) {
+ if (!of_property_read_bool(timer, "ti,timer-pwm")) {
dev_err(&pdev->dev, "Missing ti,timer-pwm capability\n");
ret = -ENODEV;
goto err_timer_property;
@@ -455,7 +455,7 @@ static struct platform_driver pwm_omap_dmtimer_driver = {
.of_match_table = pwm_omap_dmtimer_of_match,
},
.probe = pwm_omap_dmtimer_probe,
- .remove_new = pwm_omap_dmtimer_remove,
+ .remove = pwm_omap_dmtimer_remove,
};
module_platform_driver(pwm_omap_dmtimer_driver);
diff --git a/drivers/pwm/pwm-rcar.c b/drivers/pwm/pwm-rcar.c
index 4cfecd88ede0..2261789cc27d 100644
--- a/drivers/pwm/pwm-rcar.c
+++ b/drivers/pwm/pwm-rcar.c
@@ -253,7 +253,7 @@ MODULE_DEVICE_TABLE(of, rcar_pwm_of_table);
static struct platform_driver rcar_pwm_driver = {
.probe = rcar_pwm_probe,
- .remove_new = rcar_pwm_remove,
+ .remove = rcar_pwm_remove,
.driver = {
.name = "pwm-rcar",
.of_match_table = rcar_pwm_of_table,
diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c
index 0fa7575dbb54..c5f50e5eaf41 100644
--- a/drivers/pwm/pwm-rockchip.c
+++ b/drivers/pwm/pwm-rockchip.c
@@ -386,7 +386,7 @@ static struct platform_driver rockchip_pwm_driver = {
.of_match_table = rockchip_pwm_dt_ids,
},
.probe = rockchip_pwm_probe,
- .remove_new = rockchip_pwm_remove,
+ .remove = rockchip_pwm_remove,
};
module_platform_driver(rockchip_pwm_driver);
diff --git a/drivers/pwm/pwm-sifive.c b/drivers/pwm/pwm-sifive.c
index ed7957cc51fd..d5b647e6be78 100644
--- a/drivers/pwm/pwm-sifive.c
+++ b/drivers/pwm/pwm-sifive.c
@@ -336,7 +336,7 @@ MODULE_DEVICE_TABLE(of, pwm_sifive_of_match);
static struct platform_driver pwm_sifive_driver = {
.probe = pwm_sifive_probe,
- .remove_new = pwm_sifive_remove,
+ .remove = pwm_sifive_remove,
.driver = {
.name = "pwm-sifive",
.of_match_table = pwm_sifive_of_match,
diff --git a/drivers/pwm/pwm-stm32.c b/drivers/pwm/pwm-stm32.c
index f85eb41cb084..eb24054f9729 100644
--- a/drivers/pwm/pwm-stm32.c
+++ b/drivers/pwm/pwm-stm32.c
@@ -222,7 +222,7 @@ static int stm32_pwm_capture(struct pwm_chip *chip, struct pwm_device *pwm,
scale = max_arr / min(max_arr, raw_prd);
} else {
- scale = priv->max_arr; /* bellow resolution, use max scale */
+ scale = priv->max_arr; /* below resolution, use max scale */
}
if (psc && scale > 1) {
diff --git a/drivers/pwm/pwm-sun4i.c b/drivers/pwm/pwm-sun4i.c
index 5c29590d1821..e60dc7d6b591 100644
--- a/drivers/pwm/pwm-sun4i.c
+++ b/drivers/pwm/pwm-sun4i.c
@@ -493,7 +493,7 @@ static struct platform_driver sun4i_pwm_driver = {
.of_match_table = sun4i_pwm_dt_ids,
},
.probe = sun4i_pwm_probe,
- .remove_new = sun4i_pwm_remove,
+ .remove = sun4i_pwm_remove,
};
module_platform_driver(sun4i_pwm_driver);
diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c
index a3d69976148f..172063b51d44 100644
--- a/drivers/pwm/pwm-tegra.c
+++ b/drivers/pwm/pwm-tegra.c
@@ -432,7 +432,7 @@ static struct platform_driver tegra_pwm_driver = {
.pm = &tegra_pwm_pm_ops,
},
.probe = tegra_pwm_probe,
- .remove_new = tegra_pwm_remove,
+ .remove = tegra_pwm_remove,
};
module_platform_driver(tegra_pwm_driver);
diff --git a/drivers/pwm/pwm-tiecap.c b/drivers/pwm/pwm-tiecap.c
index d6c2b1b1387e..d91b2bdc88fc 100644
--- a/drivers/pwm/pwm-tiecap.c
+++ b/drivers/pwm/pwm-tiecap.c
@@ -324,7 +324,7 @@ static struct platform_driver ecap_pwm_driver = {
.pm = pm_ptr(&ecap_pwm_pm_ops),
},
.probe = ecap_pwm_probe,
- .remove_new = ecap_pwm_remove,
+ .remove = ecap_pwm_remove,
};
module_platform_driver(ecap_pwm_driver);
diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c
index e5104725d9b7..0125e73b98df 100644
--- a/drivers/pwm/pwm-tiehrpwm.c
+++ b/drivers/pwm/pwm-tiehrpwm.c
@@ -603,7 +603,7 @@ static struct platform_driver ehrpwm_pwm_driver = {
.pm = pm_ptr(&ehrpwm_pwm_pm_ops),
},
.probe = ehrpwm_pwm_probe,
- .remove_new = ehrpwm_pwm_remove,
+ .remove = ehrpwm_pwm_remove,
};
module_platform_driver(ehrpwm_pwm_driver);