All of lore.kernel.org
 help / color / mirror / Atom feed
From: Simon Glass <sjg@chromium.org>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH 1/9] Exynos: Change get_timer() to work correctly
Date: Wed, 27 Feb 2013 17:26:51 -0800	[thread overview]
Message-ID: <CAPnjgZ3R9B4=pcc5-dMVD=twdx6r=cwrafu4=hvr-ifEdLCBHA@mail.gmail.com> (raw)
In-Reply-To: <1361959366-27634-2-git-send-email-akshay.s@samsung.com>

On Wed, Feb 27, 2013 at 2:02 AM, Akshay Saraswat <akshay.s@samsung.com> wrote:
> At present get_timer() does not return sane values. It should count up
> smoothly in milliscond intervals.
>
> We can change the PWM to count down at 1MHz, providing a resolution
> of 1us and a range of about an hour between required get_timer() calls.
>
> TEST=sf probe 1:0; time sf read 40008000 0 1000
> Try with different numbers of bytes and see that sane values are obtained
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> Signed-off-by: Akshay Saraswat <akshay.s@samsung.com>

Acked-by: Simon Glass <sjg@chromium.org>

> ---
>  arch/arm/cpu/armv7/s5p-common/pwm.c   |   6 ++
>  arch/arm/cpu/armv7/s5p-common/timer.c | 100 +++++++++++++---------------------
>  2 files changed, 44 insertions(+), 62 deletions(-)
>
> diff --git a/arch/arm/cpu/armv7/s5p-common/pwm.c b/arch/arm/cpu/armv7/s5p-common/pwm.c
> index 44d7bc3..3147f59 100644
> --- a/arch/arm/cpu/armv7/s5p-common/pwm.c
> +++ b/arch/arm/cpu/armv7/s5p-common/pwm.c
> @@ -174,6 +174,12 @@ int pwm_init(int pwm_id, int div, int invert)
>
>         /* set count value */
>         offset = pwm_id * 3;
> +
> +       /*
> +        * TODO(sjg): Use this as a countdown timer for now. We count down
> +        * from the maximum value to 0, then reset.
> +        */
> +       timer_rate_hz = -1;
>         writel(timer_rate_hz, &pwm->tcntb0 + offset);
>
>         val = readl(&pwm->tcon) & ~(0xf << TCON_OFFSET(pwm_id));
> diff --git a/arch/arm/cpu/armv7/s5p-common/timer.c b/arch/arm/cpu/armv7/s5p-common/timer.c
> index e78c716..c48a297 100644
> --- a/arch/arm/cpu/armv7/s5p-common/timer.c
> +++ b/arch/arm/cpu/armv7/s5p-common/timer.c
> @@ -39,13 +39,33 @@ static inline struct s5p_timer *s5p_get_base_timer(void)
>         return (struct s5p_timer *)samsung_get_base_timer();
>  }
>
> +/**
> + * Read the countdown timer.
> + *
> + * This operates at 1MHz and counts downwards. It will wrap about every
> + * hour (2^32 microseconds).
> + *
> + * @return current value of timer
> + */
> +static unsigned long timer_get_us_down(void)
> +{
> +       struct s5p_timer *const timer = s5p_get_base_timer();
> +
> +       return readl(&timer->tcnto4);
> +}
> +
>  int timer_init(void)
>  {
>         /* PWM Timer 4 */
> -       pwm_init(4, MUX_DIV_2, 0);
> +       pwm_init(4, MUX_DIV_4, 0);
>         pwm_config(4, 0, 0);
>         pwm_enable(4);
>
> +       /* Use this as the current monotonic time in us */
> +       gd->arch.timer_reset_value = 0;
> +
> +       /* Use this as the last timer value we saw */
> +       gd->arch.lastinc = timer_get_us_down();
>         reset_timer_masked();
>
>         return 0;
> @@ -56,48 +76,28 @@ int timer_init(void)
>   */
>  unsigned long get_timer(unsigned long base)
>  {
> -       return get_timer_masked() - base;
> +       ulong now = timer_get_us_down();
> +
> +       /*
> +        * Increment the time by the amount elapsed since the last read.
> +        * The timer may have wrapped around, but it makes no difference to
> +        * our arithmetic here.
> +        */
> +       gd->arch.timer_reset_value += gd->arch.lastinc - now;
> +       gd->arch.lastinc = now;
> +
> +       /* Divide by 1000 to convert from us to ms */
> +       return gd->arch.timer_reset_value / 1000 - base;
>  }
>
>  /* delay x useconds */
>  void __udelay(unsigned long usec)
>  {
> -       struct s5p_timer *const timer = s5p_get_base_timer();
> -       unsigned long tmo, tmp, count_value;
> -
> -       count_value = readl(&timer->tcntb4);
> -
> -       if (usec >= 1000) {
> -               /*
> -                * if "big" number, spread normalization
> -                * to seconds
> -                * 1. start to normalize for usec to ticks per sec
> -                * 2. find number of "ticks" to wait to achieve target
> -                * 3. finish normalize.
> -                */
> -               tmo = usec / 1000;
> -               tmo *= (CONFIG_SYS_HZ * count_value);
> -               tmo /= 1000;
> -       } else {
> -               /* else small number, don't kill it prior to HZ multiply */
> -               tmo = usec * CONFIG_SYS_HZ * count_value;
> -               tmo /= (1000 * 1000);
> -       }
> -
> -       /* get current timestamp */
> -       tmp = get_current_tick();
> -
> -       /* if setting this fordward will roll time stamp */
> -       /* reset "advancing" timestamp to 0, set lastinc value */
> -       /* else, set advancing stamp wake up time */
> -       if ((tmo + tmp + 1) < tmp)
> -               reset_timer_masked();
> -       else
> -               tmo += tmp;
> -
> -       /* loop till event */
> -       while (get_current_tick() < tmo)
> -               ;       /* nop */
> +       unsigned long count_value;
> +
> +       count_value = timer_get_us_down();
> +       while ((int)(count_value - timer_get_us_down()) < (int)usec)
> +               ;
>  }
>
>  void reset_timer_masked(void)
> @@ -109,30 +109,6 @@ void reset_timer_masked(void)
>         gd->arch.tbl = 0;
>  }
>
> -unsigned long get_timer_masked(void)
> -{
> -       struct s5p_timer *const timer = s5p_get_base_timer();
> -       unsigned long count_value = readl(&timer->tcntb4);
> -
> -       return get_current_tick() / count_value;
> -}
> -
> -unsigned long get_current_tick(void)
> -{
> -       struct s5p_timer *const timer = s5p_get_base_timer();
> -       unsigned long now = readl(&timer->tcnto4);
> -       unsigned long count_value = readl(&timer->tcntb4);
> -
> -       if (gd->arch.lastinc >= now)
> -               gd->arch.tbl += gd->arch.lastinc - now;
> -       else
> -               gd->arch.tbl += gd->arch.lastinc + count_value - now;
> -
> -       gd->arch.lastinc = now;
> -
> -       return gd->arch.tbl;
> -}
> -
>  /*
>   * This function is derived from PowerPC code (read timebase as long long).
>   * On ARM it just returns the timer value.
> --
> 1.8.0
>

  reply	other threads:[~2013-02-28  1:26 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-02-27 10:02 [U-Boot] [PATCH 0/9] Fix and Re-organise PWM Timer Akshay Saraswat
2013-02-27 10:02 ` [U-Boot] [PATCH 1/9] Exynos: Change get_timer() to work correctly Akshay Saraswat
2013-02-28  1:26   ` Simon Glass [this message]
2013-02-27 10:02 ` [U-Boot] [PATCH 2/9] Exynos: Add timer_get_us function Akshay Saraswat
2013-02-28  1:27   ` Simon Glass
2013-02-27 10:02 ` [U-Boot] [PATCH 3/9] Exynos: pwm: Fix two bugs in the exynos pwm configuration code Akshay Saraswat
2013-02-28  1:29   ` Simon Glass
2013-02-27 10:02 ` [U-Boot] [PATCH 4/9] Exynos: Avoid a divide by zero by specifying a non-zero period for pwm 4 Akshay Saraswat
2013-02-28  1:29   ` Simon Glass
2013-02-27 10:02 ` [U-Boot] [PATCH 5/9] Exynos: Tidy up the pwm_config function in the exynos pwm driver Akshay Saraswat
2013-02-28  1:30   ` Simon Glass
2013-02-27 10:02 ` [U-Boot] [PATCH 6/9] Exynos: Add peripherial id for pwm Akshay Saraswat
2013-02-28  1:31   ` Simon Glass
2013-02-27 10:02 ` [U-Boot] [PATCH 7/9] Exynos: clock: Add generic api to get the clk freq Akshay Saraswat
2013-02-28  1:35   ` Simon Glass
2013-02-27 10:02 ` [U-Boot] [PATCH 8/9] Exynos: clock: Correct pwm source clk selection Akshay Saraswat
2013-02-27 10:02 ` [U-Boot] [PATCH 9/9] Exynos: pwm: Use generic api to get pwm clk freq Akshay Saraswat
2013-02-28  1:36   ` Simon Glass
2013-02-28  5:33   ` Rajeshwari Birje

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAPnjgZ3R9B4=pcc5-dMVD=twdx6r=cwrafu4=hvr-ifEdLCBHA@mail.gmail.com' \
    --to=sjg@chromium.org \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.