forked from mirrors/linux
		
	pwm: rcar: Add support "atomic" API
This patch adds support for "atomic" API. This behavior differs with legacy APIs a little. Legacy APIs: The PWMCNT register will be updated in rcar_pwm_config() even if the PWM state is disabled. Atomic API: The PWMCNT register will be updated in rcar_pwm_apply() only if the PWM state is enabled. Otherwize, if a PWM runs with 30% duty cycles and the pwm_apply_state() is called with state->enabled = 0, ->duty_cycle = 60 and ->period = 100, this is possible to output a 60% duty cycle. Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
This commit is contained in:
		
							parent
							
								
									74d0c3b205
								
							
						
					
					
						commit
						7f68ce8287
					
				
					 1 changed files with 37 additions and 0 deletions
				
			
		|  | @ -192,12 +192,49 @@ static void rcar_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) | ||||||
| 	rcar_pwm_update(rp, RCAR_PWMCR_EN0, 0, RCAR_PWMCR); | 	rcar_pwm_update(rp, RCAR_PWMCR_EN0, 0, RCAR_PWMCR); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static int rcar_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, | ||||||
|  | 			  struct pwm_state *state) | ||||||
|  | { | ||||||
|  | 	struct rcar_pwm_chip *rp = to_rcar_pwm_chip(chip); | ||||||
|  | 	struct pwm_state cur_state; | ||||||
|  | 	int div, ret; | ||||||
|  | 
 | ||||||
|  | 	/* This HW/driver only supports normal polarity */ | ||||||
|  | 	pwm_get_state(pwm, &cur_state); | ||||||
|  | 	if (state->polarity != PWM_POLARITY_NORMAL) | ||||||
|  | 		return -ENOTSUPP; | ||||||
|  | 
 | ||||||
|  | 	if (!state->enabled) { | ||||||
|  | 		rcar_pwm_disable(chip, pwm); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	div = rcar_pwm_get_clock_division(rp, state->period); | ||||||
|  | 	if (div < 0) | ||||||
|  | 		return div; | ||||||
|  | 
 | ||||||
|  | 	rcar_pwm_update(rp, RCAR_PWMCR_SYNC, RCAR_PWMCR_SYNC, RCAR_PWMCR); | ||||||
|  | 
 | ||||||
|  | 	ret = rcar_pwm_set_counter(rp, div, state->duty_cycle, state->period); | ||||||
|  | 	if (!ret) | ||||||
|  | 		rcar_pwm_set_clock_control(rp, div); | ||||||
|  | 
 | ||||||
|  | 	/* The SYNC should be set to 0 even if rcar_pwm_set_counter failed */ | ||||||
|  | 	rcar_pwm_update(rp, RCAR_PWMCR_SYNC, 0, RCAR_PWMCR); | ||||||
|  | 
 | ||||||
|  | 	if (!ret && state->enabled) | ||||||
|  | 		ret = rcar_pwm_enable(chip, pwm); | ||||||
|  | 
 | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static const struct pwm_ops rcar_pwm_ops = { | static const struct pwm_ops rcar_pwm_ops = { | ||||||
| 	.request = rcar_pwm_request, | 	.request = rcar_pwm_request, | ||||||
| 	.free = rcar_pwm_free, | 	.free = rcar_pwm_free, | ||||||
| 	.config = rcar_pwm_config, | 	.config = rcar_pwm_config, | ||||||
| 	.enable = rcar_pwm_enable, | 	.enable = rcar_pwm_enable, | ||||||
| 	.disable = rcar_pwm_disable, | 	.disable = rcar_pwm_disable, | ||||||
|  | 	.apply = rcar_pwm_apply, | ||||||
| 	.owner = THIS_MODULE, | 	.owner = THIS_MODULE, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Yoshihiro Shimoda
						Yoshihiro Shimoda