summaryrefslogtreecommitdiffstats
path: root/drivers/pwm
diff options
context:
space:
mode:
authorAhmad Fatoum <ahmad@a3f.at>2020-03-30 16:57:12 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2020-03-31 09:48:34 +0200
commit91912a0d5576441db1a4c9a03d309258bd49f149 (patch)
tree8bf435ff2fe7ed945da5a00e94cab123ce50cc22 /drivers/pwm
parentbc2c433d1e52833614b0910c545e8b808407a2f5 (diff)
downloadbarebox-91912a0d5576441db1a4c9a03d309258bd49f149.tar.gz
barebox-91912a0d5576441db1a4c9a03d309258bd49f149.tar.xz
PWM: core: apply initial state in of_pwm_request
This functions prepares a state that can later be tweaked and applied to the PWM device with pwm_apply_state(). This is a convenient function that first retrieves the current PWM state and the replaces the period with the reference values defined in pwm->args. Once the function returns, you can adjust the ->enabled and ->duty_cycle fields according to your needs before calling pwm_apply_state(). Signed-off-by: Ahmad Fatoum <ahmad@a3f.at> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/pwm')
-rw-r--r--drivers/pwm/core.c70
1 files changed, 66 insertions, 4 deletions
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index b42b3092a3..9206fc0b9e 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -20,6 +20,23 @@
#include <linux/list.h>
#include <linux/err.h>
+/**
+ * struct pwm_args - board-dependent PWM arguments
+ * @period_ns: reference period
+ *
+ * This structure describes board-dependent arguments attached to a PWM
+ * device. These arguments are usually retrieved from the PWM lookup table or
+ * device tree.
+ *
+ * Do not confuse this with the PWM state: PWM arguments represent the initial
+ * configuration that users want to use on this PWM device rather than the
+ * current PWM hardware state.
+ */
+
+struct pwm_args {
+ unsigned int period_ns;
+};
+
struct pwm_device {
struct pwm_chip *chip;
unsigned long flags;
@@ -29,6 +46,7 @@ struct pwm_device {
struct device_d dev;
struct pwm_state params;
+ struct pwm_args args;
};
static LIST_HEAD(pwm_list);
@@ -194,6 +212,7 @@ struct pwm_device *of_pwm_request(struct device_node *np, const char *con_id)
struct of_phandle_args args;
int index = 0;
struct pwm_device *pwm;
+ struct pwm_state state;
int ret;
if (con_id)
@@ -213,11 +232,17 @@ struct pwm_device *of_pwm_request(struct device_node *np, const char *con_id)
}
if (args.args_count > 1)
- pwm->chip->state.period_ns = args.args[1];
+ pwm->args.period_ns = args.args[1];
ret = __pwm_request(pwm);
if (ret)
- return ERR_PTR(-ret);
+ return ERR_PTR(ret);
+
+ pwm_init_state(pwm, &state);
+
+ ret = pwm_apply_state(pwm, &state);
+ if (ret)
+ return ERR_PTR(ret);
return pwm;
}
@@ -233,13 +258,50 @@ void pwm_free(struct pwm_device *pwm)
}
EXPORT_SYMBOL_GPL(pwm_free);
-void pwm_get_state(const struct pwm_device *pwm,
- struct pwm_state *state)
+void pwm_get_state(const struct pwm_device *pwm, struct pwm_state *state)
{
*state = pwm->chip->state;
}
EXPORT_SYMBOL_GPL(pwm_get_state);
+static void pwm_get_args(const struct pwm_device *pwm, struct pwm_args *args)
+{
+ *args = pwm->args;
+}
+
+/**
+ * pwm_init_state() - prepare a new state to be applied with pwm_apply_state()
+ * @pwm: PWM device
+ * @state: state to fill with the prepared PWM state
+ *
+ * This functions prepares a state that can later be tweaked and applied
+ * to the PWM device with pwm_apply_state(). This is a convenient function
+ * that first retrieves the current PWM state and the replaces the period
+ * with the reference values defined in pwm->args.
+ * Once the function returns, you can adjust the ->enabled and ->duty_cycle
+ * fields according to your needs before calling pwm_apply_state().
+ *
+ * ->duty_cycle is initially set to zero to avoid cases where the current
+ * ->duty_cycle value exceed the pwm_args->period one, which would trigger
+ * an error if the user calls pwm_apply_state() without adjusting ->duty_cycle
+ * first.
+ */
+void pwm_init_state(const struct pwm_device *pwm,
+ struct pwm_state *state)
+{
+ struct pwm_args args;
+
+ /* First get the current state. */
+ pwm_get_state(pwm, state);
+
+ /* Then fill it with the reference config */
+ pwm_get_args(pwm, &args);
+
+ state->period_ns = args.period_ns;
+ state->duty_ns = 0;
+}
+EXPORT_SYMBOL_GPL(pwm_init_state);
+
int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state)
{
struct pwm_chip *chip = pwm->chip;