From: Andreas Kemnade <andreas@kemnade.info>
To: "Jonathan Neuschäfer" <j.neuschaefer@gmx.net>
Cc: linux-kernel@vger.kernel.org, "Lee Jones" <lee.jones@linaro.org>,
"Rob Herring" <robh+dt@kernel.org>,
"Thierry Reding" <thierry.reding@gmail.com>,
"Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>,
"Alessandro Zummo" <a.zummo@towertech.it>,
"Alexandre Belloni" <alexandre.belloni@bootlin.com>,
"Shawn Guo" <shawnguo@kernel.org>,
"Sascha Hauer" <s.hauer@pengutronix.de>,
"Pengutronix Kernel Team" <kernel@pengutronix.de>,
"Fabio Estevam" <festevam@gmail.com>,
"NXP Linux Team" <linux-imx@nxp.com>,
"Sam Ravnborg" <sam@ravnborg.org>,
"Linus Walleij" <linus.walleij@linaro.org>,
"Heiko Stuebner" <heiko.stuebner@theobroma-systems.com>,
"Stephan Gerhold" <stephan@gerhold.net>,
"Lubomir Rintel" <lkundrak@v3.sk>,
"Mark Brown" <broonie@kernel.org>, allen <allen.chen@ite.com.tw>,
"Mauro Carvalho Chehab" <mchehab+huawei@kernel.org>,
"David S. Miller" <davem@davemloft.net>,
devicetree@vger.kernel.org, linux-pwm@vger.kernel.org,
linux-rtc@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
"Heiko Stuebner" <heiko@sntech.de>,
"Josua Mayer" <josua.mayer@jm0.eu>,
"Arnd Bergmann" <arnd@arndb.de>,
"Daniel Palmer" <daniel@0x0f.com>,
"Andy Shevchenko" <andy.shevchenko@gmail.com>
Subject: Re: [PATCH v7 4/7] pwm: ntxec: Add driver for PWM function in Netronix EC
Date: Tue, 12 Jan 2021 20:39:02 +0100 [thread overview]
Message-ID: <20210112203902.4e196d11@aktux> (raw)
In-Reply-To: <20210109180220.121511-5-j.neuschaefer@gmx.net>
On Sat, 9 Jan 2021 19:02:17 +0100
Jonathan Neuschäfer <j.neuschaefer@gmx.net> wrote:
> The Netronix EC provides a PWM output which is used for the backlight
> on some ebook readers. This patches adds a driver for the PWM output.
>
> The .get_state callback is not implemented, because the PWM state can't
> be read back from the hardware.
>
> Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
> ---
> v7:
> - no changes
>
> v6:
> - https://lore.kernel.org/lkml/20201208011000.3060239-5-j.neuschaefer@gmx.net/
> - Move period / duty cycle setting code to a function
> - Rename pwmchip_to_priv to ntxec_pwm_from_chip
> - Set period and duty cycle only before enabling the output
> - Mention that duty=0, enable=1 is assumed not to happen
> - Interleave writes to the period and duty cycle registers, to minimize the
> window of time that an inconsistent state is configured
>
> v5:
> - https://lore.kernel.org/lkml/20201201011513.1627028-5-j.neuschaefer@gmx.net/
> - Avoid truncation of period and duty cycle to 32 bits
> - Make ntxec_pwm_ops const
> - Use regmap_multi_reg_write
> - Add comment about get_state to ntxec_pwm_ops
> - Add comments about non-atomicity of (period, duty cycle) update
>
> v4:
> - https://lore.kernel.org/lkml/20201122222739.1455132-5-j.neuschaefer@gmx.net/
> - Document hardware/driver limitations
> - Only accept normal polarity
> - Fix a typo ("zone" -> "zero")
> - change MAX_PERIOD_NS to 0xffff * 125
> - Clamp period to the maximum rather than returning an error
> - Rename private struct pointer to priv
> - Rearrage control flow in _probe to save a few lines and a temporary variable
> - Add missing MODULE_ALIAS line
> - Spell out ODM
>
> v3:
> - https://lore.kernel.org/lkml/20200924192455.2484005-5-j.neuschaefer@gmx.net/
> - Relicense as GPLv2 or later
> - Add email address to copyright line
> - Remove OF compatible string and don't include linux/of_device.h
> - Fix bogus ?: in return line
> - Don't use a comma after sentinels
> - Avoid ret |= ... pattern
> - Move 8-bit register conversion to ntxec.h
>
> v2:
> - https://lore.kernel.org/lkml/20200905133230.1014581-6-j.neuschaefer@gmx.net/
> - Various grammar and style improvements, as suggested by Uwe Kleine-König,
> Lee Jones, and Alexandre Belloni
> - Switch to regmap
> - Prefix registers with NTXEC_REG_
> - Add help text to the Kconfig option
> - Use the .apply callback instead of the old API
> - Add a #define for the time base (125ns)
> - Don't change device state in .probe; this avoids multiple problems
> - Rework division and overflow check logic to perform divisions in 32 bits
> - Avoid setting duty cycle to zero, to work around a hardware quirk
> ---
> drivers/pwm/Kconfig | 8 ++
> drivers/pwm/Makefile | 1 +
> drivers/pwm/pwm-ntxec.c | 182 ++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 191 insertions(+)
> create mode 100644 drivers/pwm/pwm-ntxec.c
>
> diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
> index 0937e1c047acb..a2830b8832b97 100644
> --- a/drivers/pwm/Kconfig
> +++ b/drivers/pwm/Kconfig
> @@ -393,6 +393,14 @@ config PWM_MXS
> To compile this driver as a module, choose M here: the module
> will be called pwm-mxs.
>
> +config PWM_NTXEC
> + tristate "Netronix embedded controller PWM support"
> + depends on MFD_NTXEC
> + help
> + Say yes here if you want to support the PWM output of the embedded
> + controller found in certain e-book readers designed by the original
> + design manufacturer Netronix.
> +
> config PWM_OMAP_DMTIMER
> tristate "OMAP Dual-Mode Timer PWM support"
> depends on OF
> diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
> index 18b89d7fd092a..7d97eb595bbef 100644
> --- a/drivers/pwm/Makefile
> +++ b/drivers/pwm/Makefile
> @@ -35,6 +35,7 @@ obj-$(CONFIG_PWM_MESON) += pwm-meson.o
> obj-$(CONFIG_PWM_MEDIATEK) += pwm-mediatek.o
> obj-$(CONFIG_PWM_MTK_DISP) += pwm-mtk-disp.o
> obj-$(CONFIG_PWM_MXS) += pwm-mxs.o
> +obj-$(CONFIG_PWM_NTXEC) += pwm-ntxec.o
> obj-$(CONFIG_PWM_OMAP_DMTIMER) += pwm-omap-dmtimer.o
> obj-$(CONFIG_PWM_PCA9685) += pwm-pca9685.o
> obj-$(CONFIG_PWM_PXA) += pwm-pxa.o
> diff --git a/drivers/pwm/pwm-ntxec.c b/drivers/pwm/pwm-ntxec.c
> new file mode 100644
> index 0000000000000..1db30a6caa3ad
> --- /dev/null
> +++ b/drivers/pwm/pwm-ntxec.c
> @@ -0,0 +1,182 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * The Netronix embedded controller is a microcontroller found in some
> + * e-book readers designed by the original design manufacturer Netronix, Inc.
> + * It contains RTC, battery monitoring, system power management, and PWM
> + * functionality.
> + *
> + * This driver implements PWM output.
> + *
> + * Copyright 2020 Jonathan Neuschäfer <j.neuschaefer@gmx.net>
> + *
> + * Limitations:
> + * - The get_state callback is not implemented, because the current state of
> + * the PWM output can't be read back from the hardware.
> + * - The hardware can only generate normal polarity output.
> + * - The period and duty cycle can't be changed together in one atomic action.
> + */
> +
> +#include <linux/mfd/ntxec.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/pwm.h>
> +#include <linux/regmap.h>
> +#include <linux/types.h>
> +
> +struct ntxec_pwm {
> + struct device *dev;
> + struct ntxec *ec;
> + struct pwm_chip chip;
> +};
> +
> +static struct ntxec_pwm *ntxec_pwm_from_chip(struct pwm_chip *chip)
> +{
> + return container_of(chip, struct ntxec_pwm, chip);
> +}
> +
> +#define NTXEC_REG_AUTO_OFF_HI 0xa1
> +#define NTXEC_REG_AUTO_OFF_LO 0xa2
> +#define NTXEC_REG_ENABLE 0xa3
> +#define NTXEC_REG_PERIOD_LOW 0xa4
> +#define NTXEC_REG_PERIOD_HIGH 0xa5
> +#define NTXEC_REG_DUTY_LOW 0xa6
> +#define NTXEC_REG_DUTY_HIGH 0xa7
> +
> +/*
> + * The time base used in the EC is 8MHz, or 125ns. Period and duty cycle are
> + * measured in this unit.
> + */
> +#define TIME_BASE_NS 125
> +
> +/*
> + * The maximum input value (in nanoseconds) is determined by the time base and
> + * the range of the hardware registers that hold the converted value.
> + * It fits into 32 bits, so we can do our calculations in 32 bits as well.
> + */
> +#define MAX_PERIOD_NS (TIME_BASE_NS * 0xffff)
> +
> +static int ntxec_pwm_set_raw_period_and_duty_cycle(struct pwm_chip *chip,
> + int period, int duty)
> +{
> + struct ntxec_pwm *priv = ntxec_pwm_from_chip(chip);
> +
> + /*
> + * Changes to the period and duty cycle take effect as soon as the
> + * corresponding low byte is written, so the hardware may be configured
> + * to an inconsistent state after the period is written and before the
> + * duty cycle is fully written. If, in such a case, the old duty cycle
> + * is longer than the new period, the EC may output 100% for a moment.
> + *
> + * To minimize the time between the changes to period and duty cycle
> + * taking effect, the writes are interleaved.
> + */
> +
> + struct reg_sequence regs[] = {
> + { NTXEC_REG_PERIOD_HIGH, ntxec_reg8(period >> 8) },
> + { NTXEC_REG_DUTY_HIGH, ntxec_reg8(duty >> 8) },
> + { NTXEC_REG_PERIOD_LOW, ntxec_reg8(period) },
> + { NTXEC_REG_DUTY_LOW, ntxec_reg8(duty) },
> + };
> +
> + return regmap_multi_reg_write(priv->ec->regmap, regs, ARRAY_SIZE(regs));
> +}
> +
> +static int ntxec_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm_dev,
> + const struct pwm_state *state)
> +{
> + struct ntxec_pwm *priv = ntxec_pwm_from_chip(chip);
> + unsigned int period, duty;
> + int res;
> +
> + if (state->polarity != PWM_POLARITY_NORMAL)
> + return -EINVAL;
> +
> + period = min_t(u64, state->period, MAX_PERIOD_NS);
> + duty = min_t(u64, state->duty_cycle, period);
> +
> + period /= TIME_BASE_NS;
> + duty /= TIME_BASE_NS;
> +
> + /*
> + * Writing a duty cycle of zero puts the device into a state where
> + * writing a higher duty cycle doesn't result in the brightness that it
> + * usually results in. This can be fixed by cycling the ENABLE register.
> + *
> + * As a workaround, write ENABLE=0 when the duty cycle is zero.
> + * The case that something has previously set the duty cycle to zero
> + * but ENABLE=1, is not handled.
> + */
> + if (state->enabled && duty != 0) {
> + res = ntxec_pwm_set_raw_period_and_duty_cycle(chip, period, duty);
> + if (res)
> + return res;
> +
> + res = regmap_write(priv->ec->regmap, NTXEC_REG_ENABLE, ntxec_reg8(1));
> + if (res)
> + return res;
> +
> + /* Disable the auto-off timer */
> + res = regmap_write(priv->ec->regmap, NTXEC_REG_AUTO_OFF_HI, ntxec_reg8(0xff));
> + if (res)
> + return res;
> +
> + return regmap_write(priv->ec->regmap, NTXEC_REG_AUTO_OFF_LO, ntxec_reg8(0xff));
> + } else {
> + return regmap_write(priv->ec->regmap, NTXEC_REG_ENABLE, ntxec_reg8(0));
> + }
> +}
> +
> +static const struct pwm_ops ntxec_pwm_ops = {
> + .owner = THIS_MODULE,
> + .apply = ntxec_pwm_apply,
> + /*
> + * No .get_state callback, because the current state cannot be read
> + * back from the hardware.
> + */
> +};
> +
> +static int ntxec_pwm_probe(struct platform_device *pdev)
> +{
> + struct ntxec *ec = dev_get_drvdata(pdev->dev.parent);
> + struct ntxec_pwm *priv;
> + struct pwm_chip *chip;
> +
> + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
> + if (!priv)
> + return -ENOMEM;
> +
> + priv->ec = ec;
> + priv->dev = &pdev->dev;
> +
> + platform_set_drvdata(pdev, priv);
> +
> + chip = &priv->chip;
> + chip->dev = &pdev->dev;
Hmm, I needed
chip->dev = &pdev->dev.parent to use the backlight example
in patch 2/7.
Not sure what the correct solution is. Maybe the pwm deserves its own
devicetree node.
Regards,
Andreas
WARNING: multiple messages have this Message-ID (diff)
From: Andreas Kemnade <andreas@kemnade.info>
To: "Jonathan Neuschäfer" <j.neuschaefer@gmx.net>
Cc: "Alexandre Belloni" <alexandre.belloni@bootlin.com>,
"Heiko Stuebner" <heiko@sntech.de>,
linux-pwm@vger.kernel.org,
"Linus Walleij" <linus.walleij@linaro.org>,
"Thierry Reding" <thierry.reding@gmail.com>,
"Fabio Estevam" <festevam@gmail.com>,
linux-rtc@vger.kernel.org, "Arnd Bergmann" <arnd@arndb.de>,
"Mauro Carvalho Chehab" <mchehab+huawei@kernel.org>,
"Sam Ravnborg" <sam@ravnborg.org>,
"Daniel Palmer" <daniel@0x0f.com>,
"Andy Shevchenko" <andy.shevchenko@gmail.com>,
"NXP Linux Team" <linux-imx@nxp.com>,
"Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>,
devicetree@vger.kernel.org,
"Stephan Gerhold" <stephan@gerhold.net>,
allen <allen.chen@ite.com.tw>,
"Sascha Hauer" <s.hauer@pengutronix.de>,
"Lubomir Rintel" <lkundrak@v3.sk>,
"Rob Herring" <robh+dt@kernel.org>,
"Lee Jones" <lee.jones@linaro.org>,
linux-arm-kernel@lists.infradead.org,
"Alessandro Zummo" <a.zummo@towertech.it>,
linux-kernel@vger.kernel.org, "Mark Brown" <broonie@kernel.org>,
"Pengutronix Kernel Team" <kernel@pengutronix.de>,
"Heiko Stuebner" <heiko.stuebner@theobroma-systems.com>,
"Josua Mayer" <josua.mayer@jm0.eu>,
"Shawn Guo" <shawnguo@kernel.org>,
"David S. Miller" <davem@davemloft.net>
Subject: Re: [PATCH v7 4/7] pwm: ntxec: Add driver for PWM function in Netronix EC
Date: Tue, 12 Jan 2021 20:39:02 +0100 [thread overview]
Message-ID: <20210112203902.4e196d11@aktux> (raw)
In-Reply-To: <20210109180220.121511-5-j.neuschaefer@gmx.net>
On Sat, 9 Jan 2021 19:02:17 +0100
Jonathan Neuschäfer <j.neuschaefer@gmx.net> wrote:
> The Netronix EC provides a PWM output which is used for the backlight
> on some ebook readers. This patches adds a driver for the PWM output.
>
> The .get_state callback is not implemented, because the PWM state can't
> be read back from the hardware.
>
> Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
> ---
> v7:
> - no changes
>
> v6:
> - https://lore.kernel.org/lkml/20201208011000.3060239-5-j.neuschaefer@gmx.net/
> - Move period / duty cycle setting code to a function
> - Rename pwmchip_to_priv to ntxec_pwm_from_chip
> - Set period and duty cycle only before enabling the output
> - Mention that duty=0, enable=1 is assumed not to happen
> - Interleave writes to the period and duty cycle registers, to minimize the
> window of time that an inconsistent state is configured
>
> v5:
> - https://lore.kernel.org/lkml/20201201011513.1627028-5-j.neuschaefer@gmx.net/
> - Avoid truncation of period and duty cycle to 32 bits
> - Make ntxec_pwm_ops const
> - Use regmap_multi_reg_write
> - Add comment about get_state to ntxec_pwm_ops
> - Add comments about non-atomicity of (period, duty cycle) update
>
> v4:
> - https://lore.kernel.org/lkml/20201122222739.1455132-5-j.neuschaefer@gmx.net/
> - Document hardware/driver limitations
> - Only accept normal polarity
> - Fix a typo ("zone" -> "zero")
> - change MAX_PERIOD_NS to 0xffff * 125
> - Clamp period to the maximum rather than returning an error
> - Rename private struct pointer to priv
> - Rearrage control flow in _probe to save a few lines and a temporary variable
> - Add missing MODULE_ALIAS line
> - Spell out ODM
>
> v3:
> - https://lore.kernel.org/lkml/20200924192455.2484005-5-j.neuschaefer@gmx.net/
> - Relicense as GPLv2 or later
> - Add email address to copyright line
> - Remove OF compatible string and don't include linux/of_device.h
> - Fix bogus ?: in return line
> - Don't use a comma after sentinels
> - Avoid ret |= ... pattern
> - Move 8-bit register conversion to ntxec.h
>
> v2:
> - https://lore.kernel.org/lkml/20200905133230.1014581-6-j.neuschaefer@gmx.net/
> - Various grammar and style improvements, as suggested by Uwe Kleine-König,
> Lee Jones, and Alexandre Belloni
> - Switch to regmap
> - Prefix registers with NTXEC_REG_
> - Add help text to the Kconfig option
> - Use the .apply callback instead of the old API
> - Add a #define for the time base (125ns)
> - Don't change device state in .probe; this avoids multiple problems
> - Rework division and overflow check logic to perform divisions in 32 bits
> - Avoid setting duty cycle to zero, to work around a hardware quirk
> ---
> drivers/pwm/Kconfig | 8 ++
> drivers/pwm/Makefile | 1 +
> drivers/pwm/pwm-ntxec.c | 182 ++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 191 insertions(+)
> create mode 100644 drivers/pwm/pwm-ntxec.c
>
> diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
> index 0937e1c047acb..a2830b8832b97 100644
> --- a/drivers/pwm/Kconfig
> +++ b/drivers/pwm/Kconfig
> @@ -393,6 +393,14 @@ config PWM_MXS
> To compile this driver as a module, choose M here: the module
> will be called pwm-mxs.
>
> +config PWM_NTXEC
> + tristate "Netronix embedded controller PWM support"
> + depends on MFD_NTXEC
> + help
> + Say yes here if you want to support the PWM output of the embedded
> + controller found in certain e-book readers designed by the original
> + design manufacturer Netronix.
> +
> config PWM_OMAP_DMTIMER
> tristate "OMAP Dual-Mode Timer PWM support"
> depends on OF
> diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
> index 18b89d7fd092a..7d97eb595bbef 100644
> --- a/drivers/pwm/Makefile
> +++ b/drivers/pwm/Makefile
> @@ -35,6 +35,7 @@ obj-$(CONFIG_PWM_MESON) += pwm-meson.o
> obj-$(CONFIG_PWM_MEDIATEK) += pwm-mediatek.o
> obj-$(CONFIG_PWM_MTK_DISP) += pwm-mtk-disp.o
> obj-$(CONFIG_PWM_MXS) += pwm-mxs.o
> +obj-$(CONFIG_PWM_NTXEC) += pwm-ntxec.o
> obj-$(CONFIG_PWM_OMAP_DMTIMER) += pwm-omap-dmtimer.o
> obj-$(CONFIG_PWM_PCA9685) += pwm-pca9685.o
> obj-$(CONFIG_PWM_PXA) += pwm-pxa.o
> diff --git a/drivers/pwm/pwm-ntxec.c b/drivers/pwm/pwm-ntxec.c
> new file mode 100644
> index 0000000000000..1db30a6caa3ad
> --- /dev/null
> +++ b/drivers/pwm/pwm-ntxec.c
> @@ -0,0 +1,182 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * The Netronix embedded controller is a microcontroller found in some
> + * e-book readers designed by the original design manufacturer Netronix, Inc.
> + * It contains RTC, battery monitoring, system power management, and PWM
> + * functionality.
> + *
> + * This driver implements PWM output.
> + *
> + * Copyright 2020 Jonathan Neuschäfer <j.neuschaefer@gmx.net>
> + *
> + * Limitations:
> + * - The get_state callback is not implemented, because the current state of
> + * the PWM output can't be read back from the hardware.
> + * - The hardware can only generate normal polarity output.
> + * - The period and duty cycle can't be changed together in one atomic action.
> + */
> +
> +#include <linux/mfd/ntxec.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/pwm.h>
> +#include <linux/regmap.h>
> +#include <linux/types.h>
> +
> +struct ntxec_pwm {
> + struct device *dev;
> + struct ntxec *ec;
> + struct pwm_chip chip;
> +};
> +
> +static struct ntxec_pwm *ntxec_pwm_from_chip(struct pwm_chip *chip)
> +{
> + return container_of(chip, struct ntxec_pwm, chip);
> +}
> +
> +#define NTXEC_REG_AUTO_OFF_HI 0xa1
> +#define NTXEC_REG_AUTO_OFF_LO 0xa2
> +#define NTXEC_REG_ENABLE 0xa3
> +#define NTXEC_REG_PERIOD_LOW 0xa4
> +#define NTXEC_REG_PERIOD_HIGH 0xa5
> +#define NTXEC_REG_DUTY_LOW 0xa6
> +#define NTXEC_REG_DUTY_HIGH 0xa7
> +
> +/*
> + * The time base used in the EC is 8MHz, or 125ns. Period and duty cycle are
> + * measured in this unit.
> + */
> +#define TIME_BASE_NS 125
> +
> +/*
> + * The maximum input value (in nanoseconds) is determined by the time base and
> + * the range of the hardware registers that hold the converted value.
> + * It fits into 32 bits, so we can do our calculations in 32 bits as well.
> + */
> +#define MAX_PERIOD_NS (TIME_BASE_NS * 0xffff)
> +
> +static int ntxec_pwm_set_raw_period_and_duty_cycle(struct pwm_chip *chip,
> + int period, int duty)
> +{
> + struct ntxec_pwm *priv = ntxec_pwm_from_chip(chip);
> +
> + /*
> + * Changes to the period and duty cycle take effect as soon as the
> + * corresponding low byte is written, so the hardware may be configured
> + * to an inconsistent state after the period is written and before the
> + * duty cycle is fully written. If, in such a case, the old duty cycle
> + * is longer than the new period, the EC may output 100% for a moment.
> + *
> + * To minimize the time between the changes to period and duty cycle
> + * taking effect, the writes are interleaved.
> + */
> +
> + struct reg_sequence regs[] = {
> + { NTXEC_REG_PERIOD_HIGH, ntxec_reg8(period >> 8) },
> + { NTXEC_REG_DUTY_HIGH, ntxec_reg8(duty >> 8) },
> + { NTXEC_REG_PERIOD_LOW, ntxec_reg8(period) },
> + { NTXEC_REG_DUTY_LOW, ntxec_reg8(duty) },
> + };
> +
> + return regmap_multi_reg_write(priv->ec->regmap, regs, ARRAY_SIZE(regs));
> +}
> +
> +static int ntxec_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm_dev,
> + const struct pwm_state *state)
> +{
> + struct ntxec_pwm *priv = ntxec_pwm_from_chip(chip);
> + unsigned int period, duty;
> + int res;
> +
> + if (state->polarity != PWM_POLARITY_NORMAL)
> + return -EINVAL;
> +
> + period = min_t(u64, state->period, MAX_PERIOD_NS);
> + duty = min_t(u64, state->duty_cycle, period);
> +
> + period /= TIME_BASE_NS;
> + duty /= TIME_BASE_NS;
> +
> + /*
> + * Writing a duty cycle of zero puts the device into a state where
> + * writing a higher duty cycle doesn't result in the brightness that it
> + * usually results in. This can be fixed by cycling the ENABLE register.
> + *
> + * As a workaround, write ENABLE=0 when the duty cycle is zero.
> + * The case that something has previously set the duty cycle to zero
> + * but ENABLE=1, is not handled.
> + */
> + if (state->enabled && duty != 0) {
> + res = ntxec_pwm_set_raw_period_and_duty_cycle(chip, period, duty);
> + if (res)
> + return res;
> +
> + res = regmap_write(priv->ec->regmap, NTXEC_REG_ENABLE, ntxec_reg8(1));
> + if (res)
> + return res;
> +
> + /* Disable the auto-off timer */
> + res = regmap_write(priv->ec->regmap, NTXEC_REG_AUTO_OFF_HI, ntxec_reg8(0xff));
> + if (res)
> + return res;
> +
> + return regmap_write(priv->ec->regmap, NTXEC_REG_AUTO_OFF_LO, ntxec_reg8(0xff));
> + } else {
> + return regmap_write(priv->ec->regmap, NTXEC_REG_ENABLE, ntxec_reg8(0));
> + }
> +}
> +
> +static const struct pwm_ops ntxec_pwm_ops = {
> + .owner = THIS_MODULE,
> + .apply = ntxec_pwm_apply,
> + /*
> + * No .get_state callback, because the current state cannot be read
> + * back from the hardware.
> + */
> +};
> +
> +static int ntxec_pwm_probe(struct platform_device *pdev)
> +{
> + struct ntxec *ec = dev_get_drvdata(pdev->dev.parent);
> + struct ntxec_pwm *priv;
> + struct pwm_chip *chip;
> +
> + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
> + if (!priv)
> + return -ENOMEM;
> +
> + priv->ec = ec;
> + priv->dev = &pdev->dev;
> +
> + platform_set_drvdata(pdev, priv);
> +
> + chip = &priv->chip;
> + chip->dev = &pdev->dev;
Hmm, I needed
chip->dev = &pdev->dev.parent to use the backlight example
in patch 2/7.
Not sure what the correct solution is. Maybe the pwm deserves its own
devicetree node.
Regards,
Andreas
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
next prev parent reply other threads:[~2021-01-12 19:40 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-01-09 18:02 [PATCH v7 0/7] Netronix embedded controller driver for Kobo and Tolino ebook readers Jonathan Neuschäfer
2021-01-09 18:02 ` Jonathan Neuschäfer
2021-01-09 18:02 ` [PATCH v7 1/7] dt-bindings: Add vendor prefix for Netronix, Inc Jonathan Neuschäfer
2021-01-09 18:02 ` Jonathan Neuschäfer
2021-01-09 18:02 ` [PATCH v7 2/7] dt-bindings: mfd: Add binding for Netronix embedded controller Jonathan Neuschäfer
2021-01-09 18:02 ` Jonathan Neuschäfer
2021-01-09 18:02 ` [PATCH v7 3/7] mfd: Add base driver " Jonathan Neuschäfer
2021-01-09 18:02 ` Jonathan Neuschäfer
2021-01-12 19:36 ` Andreas Kemnade
2021-01-12 19:36 ` Andreas Kemnade
2021-01-13 8:03 ` Lee Jones
2021-01-13 8:03 ` Lee Jones
2021-01-14 18:56 ` Jonathan Neuschäfer
2021-01-14 18:56 ` Jonathan Neuschäfer
2021-01-09 18:02 ` [PATCH v7 4/7] pwm: ntxec: Add driver for PWM function in Netronix EC Jonathan Neuschäfer
2021-01-09 18:02 ` Jonathan Neuschäfer
2021-01-11 9:13 ` Uwe Kleine-König
2021-01-11 9:13 ` Uwe Kleine-König
2021-01-11 12:53 ` Thierry Reding
2021-01-11 12:53 ` Thierry Reding
2021-01-11 16:42 ` Lee Jones
2021-01-11 16:42 ` Lee Jones
2021-01-12 19:39 ` Andreas Kemnade [this message]
2021-01-12 19:39 ` Andreas Kemnade
2021-01-13 22:46 ` Andreas Kemnade
2021-01-13 22:46 ` Andreas Kemnade
2021-01-14 22:31 ` Jonathan Neuschäfer
2021-01-14 22:31 ` Jonathan Neuschäfer
2021-01-09 18:02 ` [PATCH v7 5/7] rtc: New driver for RTC in Netronix embedded controller Jonathan Neuschäfer
2021-01-09 18:02 ` [PATCH v7 6/7] MAINTAINERS: Add entry for " Jonathan Neuschäfer
2021-01-09 18:02 ` Jonathan Neuschäfer
2021-01-09 18:02 ` [PATCH v7 7/7] ARM: dts: imx50-kobo-aura: Add " Jonathan Neuschäfer
2021-01-09 18:02 ` Jonathan Neuschäfer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210112203902.4e196d11@aktux \
--to=andreas@kemnade.info \
--cc=a.zummo@towertech.it \
--cc=alexandre.belloni@bootlin.com \
--cc=allen.chen@ite.com.tw \
--cc=andy.shevchenko@gmail.com \
--cc=arnd@arndb.de \
--cc=broonie@kernel.org \
--cc=daniel@0x0f.com \
--cc=davem@davemloft.net \
--cc=devicetree@vger.kernel.org \
--cc=festevam@gmail.com \
--cc=heiko.stuebner@theobroma-systems.com \
--cc=heiko@sntech.de \
--cc=j.neuschaefer@gmx.net \
--cc=josua.mayer@jm0.eu \
--cc=kernel@pengutronix.de \
--cc=lee.jones@linaro.org \
--cc=linus.walleij@linaro.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-imx@nxp.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pwm@vger.kernel.org \
--cc=linux-rtc@vger.kernel.org \
--cc=lkundrak@v3.sk \
--cc=mchehab+huawei@kernel.org \
--cc=robh+dt@kernel.org \
--cc=s.hauer@pengutronix.de \
--cc=sam@ravnborg.org \
--cc=shawnguo@kernel.org \
--cc=stephan@gerhold.net \
--cc=thierry.reding@gmail.com \
--cc=u.kleine-koenig@pengutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.