summaryrefslogtreecommitdiffstats
path: root/drivers/pwm/pwm-imx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pwm/pwm-imx.c')
-rw-r--r--drivers/pwm/pwm-imx.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/drivers/pwm/pwm-imx.c b/drivers/pwm/pwm-imx.c
index 7a4907b73d7c..6cd3b72fbbc1 100644
--- a/drivers/pwm/pwm-imx.c
+++ b/drivers/pwm/pwm-imx.c
@@ -83,6 +83,9 @@
83 83
84#define MX3_PWM_SWR_LOOP 5 84#define MX3_PWM_SWR_LOOP 5
85 85
86/* PWMPR register value of 0xffff has the same effect as 0xfffe */
87#define MX3_PWMPR_MAX 0xfffe
88
86struct imx_chip { 89struct imx_chip {
87 struct clk *clk_per; 90 struct clk *clk_per;
88 91
@@ -93,6 +96,55 @@ struct imx_chip {
93 96
94#define to_imx_chip(chip) container_of(chip, struct imx_chip, chip) 97#define to_imx_chip(chip) container_of(chip, struct imx_chip, chip)
95 98
99static void imx_pwm_get_state(struct pwm_chip *chip,
100 struct pwm_device *pwm, struct pwm_state *state)
101{
102 struct imx_chip *imx = to_imx_chip(chip);
103 u32 period, prescaler, pwm_clk, ret, val;
104 u64 tmp;
105
106 val = readl(imx->mmio_base + MX3_PWMCR);
107
108 if (val & MX3_PWMCR_EN) {
109 state->enabled = true;
110 ret = clk_prepare_enable(imx->clk_per);
111 if (ret)
112 return;
113 } else {
114 state->enabled = false;
115 }
116
117 switch (FIELD_GET(MX3_PWMCR_POUTC, val)) {
118 case MX3_PWMCR_POUTC_NORMAL:
119 state->polarity = PWM_POLARITY_NORMAL;
120 break;
121 case MX3_PWMCR_POUTC_INVERTED:
122 state->polarity = PWM_POLARITY_INVERSED;
123 break;
124 default:
125 dev_warn(chip->dev, "can't set polarity, output disconnected");
126 }
127
128 prescaler = MX3_PWMCR_PRESCALER_GET(val);
129 pwm_clk = clk_get_rate(imx->clk_per);
130 pwm_clk = DIV_ROUND_CLOSEST_ULL(pwm_clk, prescaler);
131 val = readl(imx->mmio_base + MX3_PWMPR);
132 period = val >= MX3_PWMPR_MAX ? MX3_PWMPR_MAX : val;
133
134 /* PWMOUT (Hz) = PWMCLK / (PWMPR + 2) */
135 tmp = NSEC_PER_SEC * (u64)(period + 2);
136 state->period = DIV_ROUND_CLOSEST_ULL(tmp, pwm_clk);
137
138 /* PWMSAR can be read only if PWM is enabled */
139 if (state->enabled) {
140 val = readl(imx->mmio_base + MX3_PWMSAR);
141 tmp = NSEC_PER_SEC * (u64)(val);
142 state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, pwm_clk);
143 } else {
144 state->duty_cycle = 0;
145 }
146}
147
96static int imx_pwm_config_v1(struct pwm_chip *chip, 148static int imx_pwm_config_v1(struct pwm_chip *chip,
97 struct pwm_device *pwm, int duty_ns, int period_ns) 149 struct pwm_device *pwm, int duty_ns, int period_ns)
98{ 150{
@@ -272,6 +324,7 @@ static const struct pwm_ops imx_pwm_ops_v1 = {
272 324
273static const struct pwm_ops imx_pwm_ops_v2 = { 325static const struct pwm_ops imx_pwm_ops_v2 = {
274 .apply = imx_pwm_apply_v2, 326 .apply = imx_pwm_apply_v2,
327 .get_state = imx_pwm_get_state,
275 .owner = THIS_MODULE, 328 .owner = THIS_MODULE,
276}; 329};
277 330