All of lore.kernel.org
 help / color / mirror / Atom feed
From: Donghwa Lee <dh09.lee@samsung.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH] armv7: s5p: pwm driver support
Date: Wed, 02 Mar 2011 10:44:42 +0900	[thread overview]
Message-ID: <4D6DA10A.6080209@samsung.com> (raw)
In-Reply-To: <AANLkTikWX8TY5eqyKFDHPnsZThAEq1KE01R-45rK7PQ2@mail.gmail.com>

 Dear Minkyu Kang,

On 2011-02-28 8:36 Minkyu Kang wrote:
> Dear Donghwa Lee,
>
> On 24 February 2011 16:56, Donghwa Lee <dh09.lee@samsung.com> wrote:
>> This is common pwm driver of S5P.
>>
>> Signed-off-by: Donghwa Lee <dh09.lee@samsung.com>
>> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
>>
>> ---
>>  arch/arm/cpu/armv7/s5p-common/Makefile  |    1 +
>>  arch/arm/cpu/armv7/s5p-common/pwm.c     |  214 +++++++++++++++++++++++++++++++
>>  arch/arm/include/asm/arch-s5pc1xx/pwm.h |   14 ++
>>  arch/arm/include/asm/arch-s5pc2xx/pwm.h |   14 ++
>>  include/pwm.h                           |   21 +++
>>  5 files changed, 264 insertions(+), 0 deletions(-)
>>  create mode 100644 arch/arm/cpu/armv7/s5p-common/pwm.c
>>  create mode 100644 include/pwm.h
>>
>> diff --git a/arch/arm/cpu/armv7/s5p-common/pwm.c b/arch/arm/cpu/armv7/s5p-common/pwm.c
>> new file mode 100644
>> index 0000000..eed2206
>> --- /dev/null
>> +++ b/arch/arm/cpu/armv7/s5p-common/pwm.c
>> @@ -0,0 +1,214 @@
>> +/*
>> + * Copyright (C) 2011 Samsung Electronics
>> + *
>> + * Donghwa Lee <dh09.lee@samsung.com>
>> + *
>> + * See file CREDITS for list of people who contributed to this
>> + * project.
>> + *
>> + * This program is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU General Public License as
>> + * published by the Free Software Foundation; either version 2 of
>> + * the License, or (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program; if not, write to the Free Software
>> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
>> + * MA 02111-1307 USA
>> + */
>> +
>> +#include <common.h>
>> +#include <errno.h>
>> +#include <pwm.h>
>> +#include <asm/io.h>
>> +#include <asm/arch/pwm.h>
>> +#include <asm/arch/clk.h>
>> +
>> +#define PRESCALER_0            (8 - 1)         /* prescaler of timer 0, 1 */
>> +#define PRESCALER_1            (16 - 1)        /* prescaler of timer 2, 3, 4 */
>> +#define MUX_DIV_1              0               /* 1/1 period */
>> +#define MUX_DIV_2              1               /* 1/2 period */
>> +#define MUX_DIV_4              2               /* 1/4 period */
>> +#define MUX_DIV_8              3               /* 1/8 period */
>> +#define MUX_DIV_16             4               /* 1/16 period */
>> +
>> +#define MUX_DIV_SHIFT(x)       ((x) * 4)
>> +
>> +#define TCON0_TIMER_SHIFT      0
>> +#define TCON_TIMER_SHIFT(x)    (8 + ((x - 1) * 4))
>> +
>> +
> please remove this space
>

Yes, I will remove it.

>> +int pwm_enable(int pwm_id)
>> +{
>> +       const struct s5p_timer *pwm = (struct s5p_timer *)samsung_get_base_timer();
>> +       unsigned long tcon;
>> +
>> +       tcon = readl(&pwm->tcon);
>> +
>> +       if (pwm_id == 0)
>> +               tcon |= TCON0_START;
>> +       else
>> +               tcon |= TCON_START(pwm_id);
>> +       writel(tcon, &pwm->tcon);
>> +
>> +       return 0;
>> +}
>> +
>> +void pwm_disable(int pwm_id)
>> +{
>> +       const struct s5p_timer *pwm = (struct s5p_timer *)samsung_get_base_timer();
>> +       unsigned long tcon;
>> +
>> +       tcon = readl(&pwm->tcon);
>> +       if (pwm_id == 0)
>> +               tcon &= ~TCON0_START;
>> +       else
>> +               tcon &= ~TCON_START(pwm_id);
>> +
>> +       writel(tcon, &pwm->tcon);
>> +
> please remove this space
>

Yes, I will remove it.

>> +}
>> +
>> +static unsigned long pwm_calc_tin(int pwm_id, unsigned long freq)
>> +{
>> +       unsigned long tin_parent_rate;
>> +       unsigned int div;
>> +
>> +       tin_parent_rate = get_pwm_clk();
>> +
>> +       for (div = 2; div <= 16; div *= 2) {
>> +               if ((tin_parent_rate / (div << 16)) < freq)
>> +                       return tin_parent_rate / div;
>> +       }
>> +
>> +       return tin_parent_rate / 16;
>> +}
>> +
>> +#define NS_IN_HZ (1000000000UL)
>> +
>> +int pwm_config(int pwm_id, int duty_ns, int period_ns)
>> +{
>> +       const struct s5p_timer *pwm = (struct s5p_timer *)samsung_get_base_timer();
>> +       unsigned int offset;
>> +       unsigned long tin_rate;
>> +       unsigned long tin_ns;
>> +       unsigned long period;
>> +       unsigned long tcon;
>> +       unsigned long tcnt;
>> +       unsigned long timer_rate_hz;
>> +
> please remove this space
>

Yes, I will remove it.

>> +       long tcmp;
> unsigned long?
>

Yes, I will fix it next version.

>> +
>> +       /* We currently avoid using 64bit arithmetic by using the
>> +        * fact that anything faster than 1GHz is easily representable
>> +        * by 32bits. */
> Please keep multi-line comment rule.
> Please see chapter 8.
> http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=Documentation/CodingStyle
>

Thank you, your comment. I will fix it.

>> +       if (period_ns > NS_IN_HZ || duty_ns > NS_IN_HZ)
>> +               return -ERANGE;
>> +
>> +       if (duty_ns > period_ns)
>> +               return -EINVAL;
>> +
>> +       period = NS_IN_HZ / period_ns;
>> +
>> +       /* Check to see if we are changing the clock rate of the PWM */
>> +       tin_rate = pwm_calc_tin(pwm_id, period);
>> +       timer_rate_hz = tin_rate;
>> +
>> +       tin_ns = NS_IN_HZ / tin_rate;
>> +       tcnt = period_ns / tin_ns;
>> +
>> +       /* Note, counters count down */
>> +       tcmp = duty_ns / tin_ns;
>> +       tcmp = tcnt - tcmp;
>> +
>> +       /* the pwm hw only checks the compare register after a decrement,
>> +          so the pin never toggles if tcmp = tcnt */
>> +       if (tcmp == tcnt)
>> +               tcmp--;
>> +
>> +       if (tcmp < 0)
>> +               tcmp = 0;
>> +
>> +       /* Update the PWM register block. */
>> +       writel(tcmp, &pwm->tcmpb0 + offset);
> offset is not initialized.
> And, timer4 doesn't have tcmpb register.
> Please check pwm_id.
>

offset variable was missed. I will add it next version and fix about timer 4.

>> +       writel(tcnt, &pwm->tcntb0 + offset);
>> +
>> +       tcon = readl(&pwm->tcon);
>> +       if (pwm_id == 0) {
>> +               tcon |= TCON0_UPDATE;
>> +               tcon |= TCON0_AUTO_RELOAD;
>> +       } else {
>> +               tcon |= TCON_UPDATE(pwm_id);
>> +               tcon |= TCON_AUTO_RELOAD(pwm_id);
>> +       }
>> +
>> +       writel(tcon, &pwm->tcon);
>> +
>> +       if (pwm_id == 0)
>> +               tcon &= ~TCON0_UPDATE;
>> +       else
>> +               tcon &= ~TCON_UPDATE(pwm_id);
>> +
>> +       writel(tcon, &pwm->tcon);
>> +
>> +       return 0;
>> +}
>> +
>> +int pwm_init(int pwm_id, int div, int invert)
>> +{
>> +       u32 val;
>> +       const struct s5p_timer *pwm = (struct s5p_timer *)samsung_get_base_timer();
>> +       unsigned long timer_rate_hz;
>> +       unsigned int offset, prescaler;
>> +
>> +       /*
>> +        * @ PWM Timer 0
> Timer 0 is right?
>
>> +        * Timer Freq(HZ) =
>> +        *      PWM_CLK / { (prescaler_value + 1) * (divider_value) }
>> +        */
>> +
>> +       val = readl(&pwm->tcfg0);
>> +       if (pwm_id < 2) {
>> +               prescaler = PRESCALER_0;
>> +               val &= ~0xff;
>> +               val |= (prescaler & 0xff);
>> +       } else {
>> +               prescaler = PRESCALER_1;
>> +               val &= ~(0xff << 8);
>> +               val |= (prescaler & 0xff) << 8;
>> +       }
>> +       writel(val, &pwm->tcfg0);
>> +       val = readl(&pwm->tcfg1);
>> +       val &= ~(0xf << MUX_DIV_SHIFT(pwm_id));
>> +       val |= (div & 0xf) << MUX_DIV_SHIFT(pwm_id);
>> +       writel(val, &pwm->tcfg1);
>> +
>> +       timer_rate_hz = get_pwm_clk() / ((prescaler + 1) *
>> +                       (div + 1));
>> +
>> +       timer_rate_hz = timer_rate_hz / 100;
>> +
>> +       /* set count value */
>> +       offset = pwm_id * 0xc;
>> +       writel(timer_rate_hz, &pwm->tcntb0 + offset);
>> +
>> +       if (pwm_id == 0) {
>> +               val = readl(&pwm->tcon) & ~(0xf << TCON0_TIMER_SHIFT);
>> +               if (invert)
>> +                       val |= TCON0_INVERTER;
>> +       } else {
>> +               val = readl(&pwm->tcon) & ~(0xf << TCON_TIMER_SHIFT(pwm_id));
>> +               if (invert)
>> +                       val |= TCON_INVERT(pwm_id);
> TCON0_INVERTER and TCON_INVERT()..
> inverter or invert?
> Please use same name.
>

Maybe I think INVERTER is right, I will fix it.

>> +       }
>> +
>> +        writel(val, &pwm->tcon);
> Pleas use tap instead of space.
>
>> +       pwm_enable(pwm_id);
>> +
>> +       return 0;
>> +}
>> diff --git a/include/pwm.h b/include/pwm.h
>> new file mode 100644
>> index 0000000..b09a02f
>> --- /dev/null
>> +++ b/include/pwm.h
>> @@ -0,0 +1,21 @@
>> +/*
>> + * header file for pwm driver.
>> + *
>> + * copyright (c) 2011 samsung electronics
>> + * donghwa lee <dh09.lee@samsung.com>
>> + *
>> + * this program is free software; you can redistribute it and/or modify
>> + * it under the terms of the gnu general public license version 2 as
>> + * published by the free software foundation.
> Please write full license.
>

Yes, I will add full license.

> Thanks
> Minkyu Kang

Thank you,
Donghwa Lee

      reply	other threads:[~2011-03-02  1:44 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-02-24  7:56 [U-Boot] [PATCH] armv7: s5p: pwm driver support Donghwa Lee
2011-02-28 11:36 ` Minkyu Kang
2011-03-02  1:44   ` Donghwa Lee [this message]

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=4D6DA10A.6080209@samsung.com \
    --to=dh09.lee@samsung.com \
    --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.