diff options
author | shenwei.wang@nxp.com <shenwei.wang@nxp.com> | 2018-06-08 15:22:35 -0400 |
---|---|---|
committer | Thierry Reding <thierry.reding@gmail.com> | 2018-07-09 13:06:21 -0400 |
commit | db6c51ab156a2ec29edff41b1ebc1fe7d04a9614 (patch) | |
tree | 9ead980e09f479c2cdf72135d3d4bd85f80af7c8 /drivers/pwm | |
parent | 82a9c55a2bb0a47b16c75e93d8ce54e8944758c0 (diff) |
pwm: fsl-ftm: Added the support of per-compatible data
On the i.MX8x SoC family, an additional PWM enable bit is added for each
PWM channel in the register FTM_SC[23:16]. It supports 8 channels. Bit
16 is for channel 0, and bit 23 is for channel 7. As the IP version
information can not be obtained via any of the FTM registers, a property
of "has_enable_bits" is added via per-compatible data structure.
Signed-off-by: Shenwei Wang <shenwei.wang@nxp.com>
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
Diffstat (limited to 'drivers/pwm')
-rw-r--r-- | drivers/pwm/pwm-fsl-ftm.c | 32 |
1 files changed, 30 insertions, 2 deletions
diff --git a/drivers/pwm/pwm-fsl-ftm.c b/drivers/pwm/pwm-fsl-ftm.c index bcc55edad9ec..4d1d116250f6 100644 --- a/drivers/pwm/pwm-fsl-ftm.c +++ b/drivers/pwm/pwm-fsl-ftm.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/mutex.h> | 17 | #include <linux/mutex.h> |
18 | #include <linux/of_address.h> | 18 | #include <linux/of_address.h> |
19 | #include <linux/of_device.h> | ||
19 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
20 | #include <linux/pm.h> | 21 | #include <linux/pm.h> |
21 | #include <linux/pwm.h> | 22 | #include <linux/pwm.h> |
@@ -75,6 +76,10 @@ enum fsl_pwm_clk { | |||
75 | FSL_PWM_CLK_MAX | 76 | FSL_PWM_CLK_MAX |
76 | }; | 77 | }; |
77 | 78 | ||
79 | struct fsl_ftm_soc { | ||
80 | bool has_enable_bits; | ||
81 | }; | ||
82 | |||
78 | struct fsl_pwm_chip { | 83 | struct fsl_pwm_chip { |
79 | struct pwm_chip chip; | 84 | struct pwm_chip chip; |
80 | 85 | ||
@@ -89,6 +94,8 @@ struct fsl_pwm_chip { | |||
89 | 94 | ||
90 | struct clk *ipg_clk; | 95 | struct clk *ipg_clk; |
91 | struct clk *clk[FSL_PWM_CLK_MAX]; | 96 | struct clk *clk[FSL_PWM_CLK_MAX]; |
97 | |||
98 | const struct fsl_ftm_soc *soc; | ||
92 | }; | 99 | }; |
93 | 100 | ||
94 | static inline struct fsl_pwm_chip *to_fsl_chip(struct pwm_chip *chip) | 101 | static inline struct fsl_pwm_chip *to_fsl_chip(struct pwm_chip *chip) |
@@ -98,15 +105,31 @@ static inline struct fsl_pwm_chip *to_fsl_chip(struct pwm_chip *chip) | |||
98 | 105 | ||
99 | static int fsl_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) | 106 | static int fsl_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) |
100 | { | 107 | { |
108 | int ret; | ||
101 | struct fsl_pwm_chip *fpc = to_fsl_chip(chip); | 109 | struct fsl_pwm_chip *fpc = to_fsl_chip(chip); |
102 | 110 | ||
103 | return clk_prepare_enable(fpc->ipg_clk); | 111 | ret = clk_prepare_enable(fpc->ipg_clk); |
112 | if (!ret && fpc->soc->has_enable_bits) { | ||
113 | mutex_lock(&fpc->lock); | ||
114 | regmap_update_bits(fpc->regmap, FTM_SC, BIT(pwm->hwpwm + 16), | ||
115 | BIT(pwm->hwpwm + 16)); | ||
116 | mutex_unlock(&fpc->lock); | ||
117 | } | ||
118 | |||
119 | return ret; | ||
104 | } | 120 | } |
105 | 121 | ||
106 | static void fsl_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) | 122 | static void fsl_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) |
107 | { | 123 | { |
108 | struct fsl_pwm_chip *fpc = to_fsl_chip(chip); | 124 | struct fsl_pwm_chip *fpc = to_fsl_chip(chip); |
109 | 125 | ||
126 | if (fpc->soc->has_enable_bits) { | ||
127 | mutex_lock(&fpc->lock); | ||
128 | regmap_update_bits(fpc->regmap, FTM_SC, BIT(pwm->hwpwm + 16), | ||
129 | 0); | ||
130 | mutex_unlock(&fpc->lock); | ||
131 | } | ||
132 | |||
110 | clk_disable_unprepare(fpc->ipg_clk); | 133 | clk_disable_unprepare(fpc->ipg_clk); |
111 | } | 134 | } |
112 | 135 | ||
@@ -409,6 +432,7 @@ static int fsl_pwm_probe(struct platform_device *pdev) | |||
409 | 432 | ||
410 | mutex_init(&fpc->lock); | 433 | mutex_init(&fpc->lock); |
411 | 434 | ||
435 | fpc->soc = of_device_get_match_data(&pdev->dev); | ||
412 | fpc->chip.dev = &pdev->dev; | 436 | fpc->chip.dev = &pdev->dev; |
413 | 437 | ||
414 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 438 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
@@ -534,8 +558,12 @@ static const struct dev_pm_ops fsl_pwm_pm_ops = { | |||
534 | SET_SYSTEM_SLEEP_PM_OPS(fsl_pwm_suspend, fsl_pwm_resume) | 558 | SET_SYSTEM_SLEEP_PM_OPS(fsl_pwm_suspend, fsl_pwm_resume) |
535 | }; | 559 | }; |
536 | 560 | ||
561 | static const struct fsl_ftm_soc vf610_ftm_pwm = { | ||
562 | .has_enable_bits = false, | ||
563 | }; | ||
564 | |||
537 | static const struct of_device_id fsl_pwm_dt_ids[] = { | 565 | static const struct of_device_id fsl_pwm_dt_ids[] = { |
538 | { .compatible = "fsl,vf610-ftm-pwm", }, | 566 | { .compatible = "fsl,vf610-ftm-pwm", .data = &vf610_ftm_pwm }, |
539 | { /* sentinel */ } | 567 | { /* sentinel */ } |
540 | }; | 568 | }; |
541 | MODULE_DEVICE_TABLE(of, fsl_pwm_dt_ids); | 569 | MODULE_DEVICE_TABLE(of, fsl_pwm_dt_ids); |