diff options
Diffstat (limited to 'drivers/pwm/pwm-omap-dmtimer.c')
-rw-r--r-- | drivers/pwm/pwm-omap-dmtimer.c | 34 |
1 files changed, 30 insertions, 4 deletions
diff --git a/drivers/pwm/pwm-omap-dmtimer.c b/drivers/pwm/pwm-omap-dmtimer.c index 0083e75d950f..54641e45f45b 100644 --- a/drivers/pwm/pwm-omap-dmtimer.c +++ b/drivers/pwm/pwm-omap-dmtimer.c | |||
@@ -119,15 +119,13 @@ static int pwm_omap_dmtimer_config(struct pwm_chip *chip, | |||
119 | fclk = omap->pdata->get_fclk(omap->dm_timer); | 119 | fclk = omap->pdata->get_fclk(omap->dm_timer); |
120 | if (!fclk) { | 120 | if (!fclk) { |
121 | dev_err(chip->dev, "invalid pmtimer fclk\n"); | 121 | dev_err(chip->dev, "invalid pmtimer fclk\n"); |
122 | mutex_unlock(&omap->mutex); | 122 | goto err_einval; |
123 | return -EINVAL; | ||
124 | } | 123 | } |
125 | 124 | ||
126 | clk_rate = clk_get_rate(fclk); | 125 | clk_rate = clk_get_rate(fclk); |
127 | if (!clk_rate) { | 126 | if (!clk_rate) { |
128 | dev_err(chip->dev, "invalid pmtimer fclk rate\n"); | 127 | dev_err(chip->dev, "invalid pmtimer fclk rate\n"); |
129 | mutex_unlock(&omap->mutex); | 128 | goto err_einval; |
130 | return -EINVAL; | ||
131 | } | 129 | } |
132 | 130 | ||
133 | dev_dbg(chip->dev, "clk rate: %luHz\n", clk_rate); | 131 | dev_dbg(chip->dev, "clk rate: %luHz\n", clk_rate); |
@@ -142,6 +140,8 @@ static int pwm_omap_dmtimer_config(struct pwm_chip *chip, | |||
142 | * The non-active time is the remainder: (DM_TIMER_MAX-match_value) | 140 | * The non-active time is the remainder: (DM_TIMER_MAX-match_value) |
143 | * clock cycles. | 141 | * clock cycles. |
144 | * | 142 | * |
143 | * NOTE: It is required that: load_value <= match_value < DM_TIMER_MAX | ||
144 | * | ||
145 | * References: | 145 | * References: |
146 | * OMAP4430/60/70 TRM sections 22.2.4.10 and 22.2.4.11 | 146 | * OMAP4430/60/70 TRM sections 22.2.4.10 and 22.2.4.11 |
147 | * AM335x Sitara TRM sections 20.1.3.5 and 20.1.3.6 | 147 | * AM335x Sitara TRM sections 20.1.3.5 and 20.1.3.6 |
@@ -149,6 +149,27 @@ static int pwm_omap_dmtimer_config(struct pwm_chip *chip, | |||
149 | period_cycles = pwm_omap_dmtimer_get_clock_cycles(clk_rate, period_ns); | 149 | period_cycles = pwm_omap_dmtimer_get_clock_cycles(clk_rate, period_ns); |
150 | duty_cycles = pwm_omap_dmtimer_get_clock_cycles(clk_rate, duty_ns); | 150 | duty_cycles = pwm_omap_dmtimer_get_clock_cycles(clk_rate, duty_ns); |
151 | 151 | ||
152 | if (period_cycles < 2) { | ||
153 | dev_info(chip->dev, | ||
154 | "period %d ns too short for clock rate %lu Hz\n", | ||
155 | period_ns, clk_rate); | ||
156 | goto err_einval; | ||
157 | } | ||
158 | |||
159 | if (duty_cycles < 1) { | ||
160 | dev_dbg(chip->dev, | ||
161 | "duty cycle %d ns is too short for clock rate %lu Hz\n", | ||
162 | duty_ns, clk_rate); | ||
163 | dev_dbg(chip->dev, "using minimum of 1 clock cycle\n"); | ||
164 | duty_cycles = 1; | ||
165 | } else if (duty_cycles >= period_cycles) { | ||
166 | dev_dbg(chip->dev, | ||
167 | "duty cycle %d ns is too long for period %d ns at clock rate %lu Hz\n", | ||
168 | duty_ns, period_ns, clk_rate); | ||
169 | dev_dbg(chip->dev, "using maximum of 1 clock cycle less than period\n"); | ||
170 | duty_cycles = period_cycles - 1; | ||
171 | } | ||
172 | |||
152 | load_value = (DM_TIMER_MAX - period_cycles) + 1; | 173 | load_value = (DM_TIMER_MAX - period_cycles) + 1; |
153 | match_value = load_value + duty_cycles - 1; | 174 | match_value = load_value + duty_cycles - 1; |
154 | 175 | ||
@@ -179,6 +200,11 @@ static int pwm_omap_dmtimer_config(struct pwm_chip *chip, | |||
179 | mutex_unlock(&omap->mutex); | 200 | mutex_unlock(&omap->mutex); |
180 | 201 | ||
181 | return 0; | 202 | return 0; |
203 | |||
204 | err_einval: | ||
205 | mutex_unlock(&omap->mutex); | ||
206 | |||
207 | return -EINVAL; | ||
182 | } | 208 | } |
183 | 209 | ||
184 | static int pwm_omap_dmtimer_set_polarity(struct pwm_chip *chip, | 210 | static int pwm_omap_dmtimer_set_polarity(struct pwm_chip *chip, |