aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pwm
diff options
context:
space:
mode:
authorFabrice Gasnier <fabrice.gasnier@st.com>2019-10-04 14:53:52 +0200
committerThierry Reding <thierry.reding@gmail.com>2019-10-21 16:50:00 +0200
commit0f9d2ecba883d0788a34414a608055479be81ccd (patch)
tree202a3a1a804e5a1dfab07a2cc5083081afb9d2f9 /drivers/pwm
parentdt-bindings: pwm-stm32: Document pinctrl sleep state (diff)
downloadlinux-dev-0f9d2ecba883d0788a34414a608055479be81ccd.tar.xz
linux-dev-0f9d2ecba883d0788a34414a608055479be81ccd.zip
pwm: stm32: Split breakinput apply routine to ease PM support
Split breakinput routine that configures STM32 timers 'break' safety feature upon probe, into two routines: - stm32_pwm_apply_breakinputs() sets all the break inputs into registers. - stm32_pwm_probe_breakinputs() probes the device tree break input settings before calling stm32_pwm_apply_breakinputs() This is a precursor patch to ease PM support. Registers content may get lost during low power. So, break input settings applied upon probe need to be restored upon resume (e.g. by calling stm32_pwm_apply_breakinputs()). Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com> Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
Diffstat (limited to 'drivers/pwm')
-rw-r--r--drivers/pwm/pwm-stm32.c50
1 files changed, 31 insertions, 19 deletions
diff --git a/drivers/pwm/pwm-stm32.c b/drivers/pwm/pwm-stm32.c
index 359b08596d9e..dd0b27783d02 100644
--- a/drivers/pwm/pwm-stm32.c
+++ b/drivers/pwm/pwm-stm32.c
@@ -19,6 +19,12 @@
#define CCMR_CHANNEL_MASK 0xFF
#define MAX_BREAKINPUT 2
+struct stm32_breakinput {
+ u32 index;
+ u32 level;
+ u32 filter;
+};
+
struct stm32_pwm {
struct pwm_chip chip;
struct mutex lock; /* protect pwm config/enable */
@@ -26,15 +32,11 @@ struct stm32_pwm {
struct regmap *regmap;
u32 max_arr;
bool have_complementary_output;
+ struct stm32_breakinput breakinputs[MAX_BREAKINPUT];
+ unsigned int num_breakinputs;
u32 capture[4] ____cacheline_aligned; /* DMA'able buffer */
};
-struct stm32_breakinput {
- u32 index;
- u32 level;
- u32 filter;
-};
-
static inline struct stm32_pwm *to_stm32_pwm_dev(struct pwm_chip *chip)
{
return container_of(chip, struct stm32_pwm, chip);
@@ -512,11 +514,27 @@ static int stm32_pwm_set_breakinput(struct stm32_pwm *priv,
return (bdtr & bke) ? 0 : -EINVAL;
}
-static int stm32_pwm_apply_breakinputs(struct stm32_pwm *priv,
+static int stm32_pwm_apply_breakinputs(struct stm32_pwm *priv)
+{
+ unsigned int i;
+ int ret;
+
+ for (i = 0; i < priv->num_breakinputs; i++) {
+ ret = stm32_pwm_set_breakinput(priv,
+ priv->breakinputs[i].index,
+ priv->breakinputs[i].level,
+ priv->breakinputs[i].filter);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int stm32_pwm_probe_breakinputs(struct stm32_pwm *priv,
struct device_node *np)
{
- struct stm32_breakinput breakinput[MAX_BREAKINPUT];
- int nb, ret, i, array_size;
+ int nb, ret, array_size;
nb = of_property_count_elems_of_size(np, "st,breakinput",
sizeof(struct stm32_breakinput));
@@ -531,20 +549,14 @@ static int stm32_pwm_apply_breakinputs(struct stm32_pwm *priv,
if (nb > MAX_BREAKINPUT)
return -EINVAL;
+ priv->num_breakinputs = nb;
array_size = nb * sizeof(struct stm32_breakinput) / sizeof(u32);
ret = of_property_read_u32_array(np, "st,breakinput",
- (u32 *)breakinput, array_size);
+ (u32 *)priv->breakinputs, array_size);
if (ret)
return ret;
- for (i = 0; i < nb && !ret; i++) {
- ret = stm32_pwm_set_breakinput(priv,
- breakinput[i].index,
- breakinput[i].level,
- breakinput[i].filter);
- }
-
- return ret;
+ return stm32_pwm_apply_breakinputs(priv);
}
static void stm32_pwm_detect_complementary(struct stm32_pwm *priv)
@@ -614,7 +626,7 @@ static int stm32_pwm_probe(struct platform_device *pdev)
if (!priv->regmap || !priv->clk)
return -EINVAL;
- ret = stm32_pwm_apply_breakinputs(priv, np);
+ ret = stm32_pwm_probe_breakinputs(priv, np);
if (ret)
return ret;