diff options
author | Fabrice Gasnier <fabrice.gasnier@st.com> | 2017-07-27 12:19:00 -0400 |
---|---|---|
committer | Jonathan Cameron <Jonathan.Cameron@huawei.com> | 2017-07-30 09:48:14 -0400 |
commit | 90938ca432e6b8f6bb1c22a24984738fc3d906ed (patch) | |
tree | 327d2c8c8a0dd35f5fcec8c86746990074754279 /drivers/iio/trigger/stm32-timer-trigger.c | |
parent | 06e3fe89988b1c99a3d9953b1d3b1faf3f047017 (diff) |
iio: trigger: stm32-timer: add enable attribute
In order to use encoder mode, timers needs to be enabled (e.g. CEN bit)
along with peripheral clock.
Add IIO_CHAN_INFO_ENABLE attribute to handle this.
Also, in triggered mode, CEN bit is set automatically in hardware.
Then clock must be enabled before starting triggered mode.
Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
Acked-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Diffstat (limited to 'drivers/iio/trigger/stm32-timer-trigger.c')
-rw-r--r-- | drivers/iio/trigger/stm32-timer-trigger.c | 55 |
1 files changed, 41 insertions, 14 deletions
diff --git a/drivers/iio/trigger/stm32-timer-trigger.c b/drivers/iio/trigger/stm32-timer-trigger.c index d28aa02b85e8..14e6eb04bbb0 100644 --- a/drivers/iio/trigger/stm32-timer-trigger.c +++ b/drivers/iio/trigger/stm32-timer-trigger.c | |||
@@ -366,34 +366,32 @@ static int stm32_counter_read_raw(struct iio_dev *indio_dev, | |||
366 | int *val, int *val2, long mask) | 366 | int *val, int *val2, long mask) |
367 | { | 367 | { |
368 | struct stm32_timer_trigger *priv = iio_priv(indio_dev); | 368 | struct stm32_timer_trigger *priv = iio_priv(indio_dev); |
369 | u32 dat; | ||
369 | 370 | ||
370 | switch (mask) { | 371 | switch (mask) { |
371 | case IIO_CHAN_INFO_RAW: | 372 | case IIO_CHAN_INFO_RAW: |
372 | { | 373 | regmap_read(priv->regmap, TIM_CNT, &dat); |
373 | u32 cnt; | 374 | *val = dat; |
374 | 375 | return IIO_VAL_INT; | |
375 | regmap_read(priv->regmap, TIM_CNT, &cnt); | ||
376 | *val = cnt; | ||
377 | 376 | ||
377 | case IIO_CHAN_INFO_ENABLE: | ||
378 | regmap_read(priv->regmap, TIM_CR1, &dat); | ||
379 | *val = (dat & TIM_CR1_CEN) ? 1 : 0; | ||
378 | return IIO_VAL_INT; | 380 | return IIO_VAL_INT; |
379 | } | ||
380 | case IIO_CHAN_INFO_SCALE: | ||
381 | { | ||
382 | u32 smcr; | ||
383 | 381 | ||
384 | regmap_read(priv->regmap, TIM_SMCR, &smcr); | 382 | case IIO_CHAN_INFO_SCALE: |
385 | smcr &= TIM_SMCR_SMS; | 383 | regmap_read(priv->regmap, TIM_SMCR, &dat); |
384 | dat &= TIM_SMCR_SMS; | ||
386 | 385 | ||
387 | *val = 1; | 386 | *val = 1; |
388 | *val2 = 0; | 387 | *val2 = 0; |
389 | 388 | ||
390 | /* in quadrature case scale = 0.25 */ | 389 | /* in quadrature case scale = 0.25 */ |
391 | if (smcr == 3) | 390 | if (dat == 3) |
392 | *val2 = 2; | 391 | *val2 = 2; |
393 | 392 | ||
394 | return IIO_VAL_FRACTIONAL_LOG2; | 393 | return IIO_VAL_FRACTIONAL_LOG2; |
395 | } | 394 | } |
396 | } | ||
397 | 395 | ||
398 | return -EINVAL; | 396 | return -EINVAL; |
399 | } | 397 | } |
@@ -403,6 +401,7 @@ static int stm32_counter_write_raw(struct iio_dev *indio_dev, | |||
403 | int val, int val2, long mask) | 401 | int val, int val2, long mask) |
404 | { | 402 | { |
405 | struct stm32_timer_trigger *priv = iio_priv(indio_dev); | 403 | struct stm32_timer_trigger *priv = iio_priv(indio_dev); |
404 | u32 dat; | ||
406 | 405 | ||
407 | switch (mask) { | 406 | switch (mask) { |
408 | case IIO_CHAN_INFO_RAW: | 407 | case IIO_CHAN_INFO_RAW: |
@@ -411,6 +410,22 @@ static int stm32_counter_write_raw(struct iio_dev *indio_dev, | |||
411 | case IIO_CHAN_INFO_SCALE: | 410 | case IIO_CHAN_INFO_SCALE: |
412 | /* fixed scale */ | 411 | /* fixed scale */ |
413 | return -EINVAL; | 412 | return -EINVAL; |
413 | |||
414 | case IIO_CHAN_INFO_ENABLE: | ||
415 | if (val) { | ||
416 | regmap_read(priv->regmap, TIM_CR1, &dat); | ||
417 | if (!(dat & TIM_CR1_CEN)) | ||
418 | clk_enable(priv->clk); | ||
419 | regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, | ||
420 | TIM_CR1_CEN); | ||
421 | } else { | ||
422 | regmap_read(priv->regmap, TIM_CR1, &dat); | ||
423 | regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, | ||
424 | 0); | ||
425 | if (dat & TIM_CR1_CEN) | ||
426 | clk_disable(priv->clk); | ||
427 | } | ||
428 | return 0; | ||
414 | } | 429 | } |
415 | 430 | ||
416 | return -EINVAL; | 431 | return -EINVAL; |
@@ -506,9 +521,19 @@ static int stm32_set_enable_mode(struct iio_dev *indio_dev, | |||
506 | { | 521 | { |
507 | struct stm32_timer_trigger *priv = iio_priv(indio_dev); | 522 | struct stm32_timer_trigger *priv = iio_priv(indio_dev); |
508 | int sms = stm32_enable_mode2sms(mode); | 523 | int sms = stm32_enable_mode2sms(mode); |
524 | u32 val; | ||
509 | 525 | ||
510 | if (sms < 0) | 526 | if (sms < 0) |
511 | return sms; | 527 | return sms; |
528 | /* | ||
529 | * Triggered mode sets CEN bit automatically by hardware. So, first | ||
530 | * enable counter clock, so it can use it. Keeps it in sync with CEN. | ||
531 | */ | ||
532 | if (sms == 6) { | ||
533 | regmap_read(priv->regmap, TIM_CR1, &val); | ||
534 | if (!(val & TIM_CR1_CEN)) | ||
535 | clk_enable(priv->clk); | ||
536 | } | ||
512 | 537 | ||
513 | regmap_update_bits(priv->regmap, TIM_SMCR, TIM_SMCR_SMS, sms); | 538 | regmap_update_bits(priv->regmap, TIM_SMCR, TIM_SMCR_SMS, sms); |
514 | 539 | ||
@@ -681,7 +706,9 @@ static const struct iio_chan_spec_ext_info stm32_trigger_count_info[] = { | |||
681 | static const struct iio_chan_spec stm32_trigger_channel = { | 706 | static const struct iio_chan_spec stm32_trigger_channel = { |
682 | .type = IIO_COUNT, | 707 | .type = IIO_COUNT, |
683 | .channel = 0, | 708 | .channel = 0, |
684 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), | 709 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | |
710 | BIT(IIO_CHAN_INFO_ENABLE) | | ||
711 | BIT(IIO_CHAN_INFO_SCALE), | ||
685 | .ext_info = stm32_trigger_count_info, | 712 | .ext_info = stm32_trigger_count_info, |
686 | .indexed = 1 | 713 | .indexed = 1 |
687 | }; | 714 | }; |