diff options
Diffstat (limited to 'drivers/counter/stm32-timer-cnt.c')
| -rw-r--r-- | drivers/counter/stm32-timer-cnt.c | 55 | 
1 files changed, 33 insertions, 22 deletions
| diff --git a/drivers/counter/stm32-timer-cnt.c b/drivers/counter/stm32-timer-cnt.c index ef2a974a2f10..75bc401fdd18 100644 --- a/drivers/counter/stm32-timer-cnt.c +++ b/drivers/counter/stm32-timer-cnt.c @@ -31,7 +31,7 @@ struct stm32_timer_cnt {  	struct counter_device counter;  	struct regmap *regmap;  	struct clk *clk; -	u32 ceiling; +	u32 max_arr;  	bool enabled;  	struct stm32_timer_regs bak;  }; @@ -44,13 +44,14 @@ struct stm32_timer_cnt {   * @STM32_COUNT_ENCODER_MODE_3: counts on both TI1FP1 and TI2FP2 edges   */  enum stm32_count_function { -	STM32_COUNT_SLAVE_MODE_DISABLED = -1, +	STM32_COUNT_SLAVE_MODE_DISABLED,  	STM32_COUNT_ENCODER_MODE_1,  	STM32_COUNT_ENCODER_MODE_2,  	STM32_COUNT_ENCODER_MODE_3,  };  static enum counter_count_function stm32_count_functions[] = { +	[STM32_COUNT_SLAVE_MODE_DISABLED] = COUNTER_COUNT_FUNCTION_INCREASE,  	[STM32_COUNT_ENCODER_MODE_1] = COUNTER_COUNT_FUNCTION_QUADRATURE_X2_A,  	[STM32_COUNT_ENCODER_MODE_2] = COUNTER_COUNT_FUNCTION_QUADRATURE_X2_B,  	[STM32_COUNT_ENCODER_MODE_3] = COUNTER_COUNT_FUNCTION_QUADRATURE_X4, @@ -73,8 +74,10 @@ static int stm32_count_write(struct counter_device *counter,  			     const unsigned long val)  {  	struct stm32_timer_cnt *const priv = counter->priv; +	u32 ceiling; -	if (val > priv->ceiling) +	regmap_read(priv->regmap, TIM_ARR, &ceiling); +	if (val > ceiling)  		return -EINVAL;  	return regmap_write(priv->regmap, TIM_CNT, val); @@ -90,6 +93,9 @@ static int stm32_count_function_get(struct counter_device *counter,  	regmap_read(priv->regmap, TIM_SMCR, &smcr);  	switch (smcr & TIM_SMCR_SMS) { +	case 0: +		*function = STM32_COUNT_SLAVE_MODE_DISABLED; +		return 0;  	case 1:  		*function = STM32_COUNT_ENCODER_MODE_1;  		return 0; @@ -99,9 +105,9 @@ static int stm32_count_function_get(struct counter_device *counter,  	case 3:  		*function = STM32_COUNT_ENCODER_MODE_3;  		return 0; +	default: +		return -EINVAL;  	} - -	return -EINVAL;  }  static int stm32_count_function_set(struct counter_device *counter, @@ -112,6 +118,9 @@ static int stm32_count_function_set(struct counter_device *counter,  	u32 cr1, sms;  	switch (function) { +	case STM32_COUNT_SLAVE_MODE_DISABLED: +		sms = 0; +		break;  	case STM32_COUNT_ENCODER_MODE_1:  		sms = 1;  		break; @@ -122,8 +131,7 @@ static int stm32_count_function_set(struct counter_device *counter,  		sms = 3;  		break;  	default: -		sms = 0; -		break; +		return -EINVAL;  	}  	/* Store enable status */ @@ -131,10 +139,6 @@ static int stm32_count_function_set(struct counter_device *counter,  	regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, 0); -	/* TIMx_ARR register shouldn't be buffered (ARPE=0) */ -	regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE, 0); -	regmap_write(priv->regmap, TIM_ARR, priv->ceiling); -  	regmap_update_bits(priv->regmap, TIM_SMCR, TIM_SMCR_SMS, sms);  	/* Make sure that registers are updated */ @@ -185,11 +189,13 @@ static ssize_t stm32_count_ceiling_write(struct counter_device *counter,  	if (ret)  		return ret; +	if (ceiling > priv->max_arr) +		return -ERANGE; +  	/* TIMx_ARR register shouldn't be buffered (ARPE=0) */  	regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE, 0);  	regmap_write(priv->regmap, TIM_ARR, ceiling); -	priv->ceiling = ceiling;  	return len;  } @@ -274,31 +280,36 @@ static int stm32_action_get(struct counter_device *counter,  	size_t function;  	int err; -	/* Default action mode (e.g. STM32_COUNT_SLAVE_MODE_DISABLED) */ -	*action = STM32_SYNAPSE_ACTION_NONE; -  	err = stm32_count_function_get(counter, count, &function);  	if (err) -		return 0; +		return err;  	switch (function) { +	case STM32_COUNT_SLAVE_MODE_DISABLED: +		/* counts on internal clock when CEN=1 */ +		*action = STM32_SYNAPSE_ACTION_NONE; +		return 0;  	case STM32_COUNT_ENCODER_MODE_1:  		/* counts up/down on TI1FP1 edge depending on TI2FP2 level */  		if (synapse->signal->id == count->synapses[0].signal->id)  			*action = STM32_SYNAPSE_ACTION_BOTH_EDGES; -		break; +		else +			*action = STM32_SYNAPSE_ACTION_NONE; +		return 0;  	case STM32_COUNT_ENCODER_MODE_2:  		/* counts up/down on TI2FP2 edge depending on TI1FP1 level */  		if (synapse->signal->id == count->synapses[1].signal->id)  			*action = STM32_SYNAPSE_ACTION_BOTH_EDGES; -		break; +		else +			*action = STM32_SYNAPSE_ACTION_NONE; +		return 0;  	case STM32_COUNT_ENCODER_MODE_3:  		/* counts up/down on both TI1FP1 and TI2FP2 edges */  		*action = STM32_SYNAPSE_ACTION_BOTH_EDGES; -		break; +		return 0; +	default: +		return -EINVAL;  	} - -	return 0;  }  static const struct counter_ops stm32_timer_cnt_ops = { @@ -359,7 +370,7 @@ static int stm32_timer_cnt_probe(struct platform_device *pdev)  	priv->regmap = ddata->regmap;  	priv->clk = ddata->clk; -	priv->ceiling = ddata->max_arr; +	priv->max_arr = ddata->max_arr;  	priv->counter.name = dev_name(dev);  	priv->counter.parent = dev; | 
