From: caesar <caesar.wang-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
To: Thierry Reding <thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Cc: heiko-4mtYJXux2i+zQB+pC5nmwQ@public.gmane.org,
b.galvani-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org,
ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg@public.gmane.org,
rdunlap-wEGCiKHe2LqWVfeAwA7xHQ@public.gmane.org,
galak-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org,
cf-TNX95d0MmH7DzftRWevZcw@public.gmane.org,
huangtao-TNX95d0MmH7DzftRWevZcw@public.gmane.org,
xjq-TNX95d0MmH7DzftRWevZcw@public.gmane.org,
addy.ke-TNX95d0MmH7DzftRWevZcw@public.gmane.org,
cjf-TNX95d0MmH7DzftRWevZcw@public.gmane.org,
hj-TNX95d0MmH7DzftRWevZcw@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
linux-pwm-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-doc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Subject: Re: [PATCH v4 2/2] pwm: rockchip: Added to support for RK3288 SoC
Date: Thu, 07 Aug 2014 21:04:30 +0800 [thread overview]
Message-ID: <53E3795E.4080607@rock-chips.com> (raw)
In-Reply-To: <20140807061842.GB17340@ulmo>
Thierry,
在 2014年08月07日 14:18, Thierry Reding 写道:
> On Thu, Jul 24, 2014 at 06:21:35PM +0800, Caesar Wang wrote:
>> This patch added to support the PWM controller found on
>> RK3288 SoC.
>>
>> Signed-off-by: Caesar Wang <caesar.wang-TNX95d0MmH7DzftRWevZcw@public.gmane.org>
>> ---
>> drivers/pwm/pwm-rockchip.c | 124 ++++++++++++++++++++++++++++++++++++++-------
>> 1 file changed, 105 insertions(+), 19 deletions(-)
>>
>> diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c
>> index eec2145..59c2513 100644
>> --- a/drivers/pwm/pwm-rockchip.c
>> +++ b/drivers/pwm/pwm-rockchip.c
>> @@ -2,6 +2,7 @@
>> * PWM driver for Rockchip SoCs
>> *
>> * Copyright (C) 2014 Beniamino Galvani <b.galvani-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>> + * Copyright (C) 2014 ROCKCHIP, Inc.
>> *
>> * This program is free software; you can redistribute it and/or
>> * modify it under the terms of the GNU General Public License
>> @@ -12,6 +13,7 @@
>> #include <linux/io.h>
>> #include <linux/module.h>
>> #include <linux/of.h>
>> +#include <linux/of_device.h>
>> #include <linux/platform_device.h>
>> #include <linux/pwm.h>
>> #include <linux/time.h>
>> @@ -25,17 +27,72 @@
>>
>> #define PRESCALER 2
>>
>> +#define PWM_ENABLE (1 << 0)
>> +#define PWM_CONTINUOUS (1 << 1)
>> +#define PWM_DUTY_POSITIVE (1 << 3)
>> +#define PWM_INACTIVE_NEGATIVE (0 << 4)
>> +#define PWM_OUTPUT_LEFT (0 << 5)
>> +#define PWM_LP_DISABLE (0 << 8)
>> +
>> struct rockchip_pwm_chip {
>> struct pwm_chip chip;
>> struct clk *clk;
>> + const struct rockchip_pwm_data *data;
>> void __iomem *base;
>> };
>>
>> +struct rockchip_pwm_regs {
>> + unsigned long duty;
>> + unsigned long period;
>> + unsigned long cntr;
>> + unsigned long ctrl;
>> +};
>> +
>> +struct rockchip_pwm_data {
>> + struct rockchip_pwm_regs regs;
>> + unsigned int prescaler;
>> +
>> + void (*set_enable)(struct pwm_chip *chip, bool enable);
>> +};
>> +
>> static inline struct rockchip_pwm_chip *to_rockchip_pwm_chip(struct pwm_chip *c)
>> {
>> return container_of(c, struct rockchip_pwm_chip, chip);
>> }
>>
>> +static void rockchip_pwm_set_enable_v1(struct pwm_chip *chip, bool enable)
>> +{
>> + struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
>> + u32 val = 0;
>> + u32 enable_conf = PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN;
>> +
>> + val = readl_relaxed(pc->base + pc->data->regs.ctrl);
>> +
>> + if (enable)
>> + val |= enable_conf;
>> + else
>> + val &= ~enable_conf;
>> +
>> + writel_relaxed(val, pc->base + pc->data->regs.ctrl);
>> +}
>> +
>> +static void rockchip_pwm_set_enable_v2(struct pwm_chip *chip, bool enable)
>> +{
>> + struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
>> + u32 val = 0;
>> + u32 enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE |
>> + PWM_CONTINUOUS | PWM_DUTY_POSITIVE | PWM_INACTIVE_NEGATIVE;
>> +
>> + val = readl_relaxed(pc->base + pc->data->regs.ctrl);
>> +
>> + if (enable)
>> + val |= enable_conf;
>> + else
>> + val &= ~enable_conf;
>> +
>> + writel_relaxed(val, pc->base + pc->data->regs.ctrl);
>> +}
>> +
>> static int rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
>> int duty_ns, int period_ns)
>> {
>> @@ -52,20 +109,20 @@ static int rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
>> * default prescaler value for all practical clock rate values.
>> */
>> div = clk_rate * period_ns;
>> - do_div(div, PRESCALER * NSEC_PER_SEC);
>> + do_div(div, pc->data->prescaler * NSEC_PER_SEC);
>> period = div;
>>
>> div = clk_rate * duty_ns;
>> - do_div(div, PRESCALER * NSEC_PER_SEC);
>> + do_div(div, pc->data->prescaler * NSEC_PER_SEC);
>> duty = div;
>>
>> ret = clk_enable(pc->clk);
>> if (ret)
>> return ret;
>>
>> - writel(period, pc->base + PWM_LRC);
>> - writel(duty, pc->base + PWM_HRC);
>> - writel(0, pc->base + PWM_CNTR);
>> + writel(period, pc->base + pc->data->regs.period);
>> + writel(duty, pc->base + pc->data->regs.duty);
>> + writel(0, pc->base + pc->data->regs.cntr);
>>
>> clk_disable(pc->clk);
>>
>> @@ -76,15 +133,12 @@ static int rockchip_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
>> {
>> struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
>> int ret;
>> - u32 val;
>>
>> ret = clk_enable(pc->clk);
>> if (ret)
>> return ret;
>>
>> - val = readl_relaxed(pc->base + PWM_CTRL);
>> - val |= PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN;
>> - writel_relaxed(val, pc->base + PWM_CTRL);
>> + pc->data->set_enable(chip, true);
>>
>> return 0;
>> }
>> @@ -92,11 +146,8 @@ static int rockchip_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
>> static void rockchip_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
>> {
>> struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
>> - u32 val;
>>
>> - val = readl_relaxed(pc->base + PWM_CTRL);
>> - val &= ~(PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN);
>> - writel_relaxed(val, pc->base + PWM_CTRL);
>> + pc->data->set_enable(chip, false);
>>
>> clk_disable(pc->clk);
>> }
>> @@ -108,12 +159,52 @@ static const struct pwm_ops rockchip_pwm_ops = {
>> .owner = THIS_MODULE,
>> };
>>
>> +static const struct rockchip_pwm_data pwm_data_v1 = {
>> + .regs.duty = PWM_HRC,
>> + .regs.period = PWM_LRC,
>> + .regs.cntr = PWM_CNTR,
>> + .regs.ctrl = PWM_CTRL,
> Perhaps a slightly more idiomatic way to write this would be:
>
> static const struct rockchip_pwm_data pwm_data_v1 = {
> .regs = {
> .duty = PWM_HRC,
> .period = PWM_LRC,
> .cntr = PWM_CNTR,
> .ctrl = PWM_CTRL,
> },
> ...
> };
>
> And similar for the v2 and vop structures. And like I said in another
> reply, since the defines are now only used in this structure it's a
> little redundant to give them symbolic names, so the above could equally
> well be:
>
> static const struct rockchip_pwm_data pwm_data_v1 = {
> .regs = {
> .duty = 0x04,
> .period = 0x08,
> .cntr = 0x00,
> .ctrl = 0x0c,
> },
> ...
> };
>
>> + .prescaler = PRESCALER,
> Similarly for the prescaler value, it can now simply be 2 here.
>
>> + .set_enable = rockchip_pwm_set_enable_v1,
>> +};
>> +
>> +static const struct rockchip_pwm_data pwm_data_v2 = {
>> + .regs.duty = PWM_LRC,
>> + .regs.period = PWM_HRC,
>> + .regs.cntr = PWM_CNTR,
>> + .regs.ctrl = PWM_CTRL,
>> + .prescaler = PRESCALER-1,
> And 1 here.
>
>> + .set_enable = rockchip_pwm_set_enable_v2,
>> +};
>> +
>> +static const struct rockchip_pwm_data pwm_data_vop = {
>> + .regs.duty = PWM_LRC,
>> + .regs.period = PWM_HRC,
>> + .regs.cntr = PWM_CTRL,
>> + .regs.ctrl = PWM_CNTR,
>> + .prescaler = PRESCALER-1,
> And 1 here.
As you say, I will rewrite the about if it's really need do so it.
For example:
static const struct rockchip_pwm_data pwm_data_v1 = {
.regs = {
.duty = 0x04,
.period = 0x08,
.cntr = 0x00,
.ctrl = 0x0c,
},
.prescaler = 2,
.set_enable = rockchip_pwm_set_enable_v1,
};
static const struct rockchip_pwm_data pwm_data_v2 = {
.regs = {
.duty = 0x08,
.period = 0x04,
.cntr = 0x00,
.ctrl = 0x0c,
},
.prescaler = 1,
.set_enable = rockchip_pwm_set_enable_v2,
};
static const struct rockchip_pwm_data pwm_data_vop = {
.regs = {
.duty = 0x08,
.period = 0x04,
.cntr = 0x0c,
.ctrl = 0x00,
},
.prescaler = 1,
.set_enable = rockchip_pwm_set_enable_v2,
};
Is that right?
>> + .set_enable = rockchip_pwm_set_enable_v2,
>> +};
> No need for the double indirection.
Sorry, I think is need if you mean a double indirection for ".set_enable".
Caesar
>
> Thierry
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
WARNING: multiple messages have this Message-ID (diff)
From: caesar.wang@rock-chips.com (caesar)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v4 2/2] pwm: rockchip: Added to support for RK3288 SoC
Date: Thu, 07 Aug 2014 21:04:30 +0800 [thread overview]
Message-ID: <53E3795E.4080607@rock-chips.com> (raw)
In-Reply-To: <20140807061842.GB17340@ulmo>
Thierry,
? 2014?08?07? 14:18, Thierry Reding ??:
> On Thu, Jul 24, 2014 at 06:21:35PM +0800, Caesar Wang wrote:
>> This patch added to support the PWM controller found on
>> RK3288 SoC.
>>
>> Signed-off-by: Caesar Wang <caesar.wang@rock-chips.com>
>> ---
>> drivers/pwm/pwm-rockchip.c | 124 ++++++++++++++++++++++++++++++++++++++-------
>> 1 file changed, 105 insertions(+), 19 deletions(-)
>>
>> diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c
>> index eec2145..59c2513 100644
>> --- a/drivers/pwm/pwm-rockchip.c
>> +++ b/drivers/pwm/pwm-rockchip.c
>> @@ -2,6 +2,7 @@
>> * PWM driver for Rockchip SoCs
>> *
>> * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com>
>> + * Copyright (C) 2014 ROCKCHIP, Inc.
>> *
>> * This program is free software; you can redistribute it and/or
>> * modify it under the terms of the GNU General Public License
>> @@ -12,6 +13,7 @@
>> #include <linux/io.h>
>> #include <linux/module.h>
>> #include <linux/of.h>
>> +#include <linux/of_device.h>
>> #include <linux/platform_device.h>
>> #include <linux/pwm.h>
>> #include <linux/time.h>
>> @@ -25,17 +27,72 @@
>>
>> #define PRESCALER 2
>>
>> +#define PWM_ENABLE (1 << 0)
>> +#define PWM_CONTINUOUS (1 << 1)
>> +#define PWM_DUTY_POSITIVE (1 << 3)
>> +#define PWM_INACTIVE_NEGATIVE (0 << 4)
>> +#define PWM_OUTPUT_LEFT (0 << 5)
>> +#define PWM_LP_DISABLE (0 << 8)
>> +
>> struct rockchip_pwm_chip {
>> struct pwm_chip chip;
>> struct clk *clk;
>> + const struct rockchip_pwm_data *data;
>> void __iomem *base;
>> };
>>
>> +struct rockchip_pwm_regs {
>> + unsigned long duty;
>> + unsigned long period;
>> + unsigned long cntr;
>> + unsigned long ctrl;
>> +};
>> +
>> +struct rockchip_pwm_data {
>> + struct rockchip_pwm_regs regs;
>> + unsigned int prescaler;
>> +
>> + void (*set_enable)(struct pwm_chip *chip, bool enable);
>> +};
>> +
>> static inline struct rockchip_pwm_chip *to_rockchip_pwm_chip(struct pwm_chip *c)
>> {
>> return container_of(c, struct rockchip_pwm_chip, chip);
>> }
>>
>> +static void rockchip_pwm_set_enable_v1(struct pwm_chip *chip, bool enable)
>> +{
>> + struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
>> + u32 val = 0;
>> + u32 enable_conf = PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN;
>> +
>> + val = readl_relaxed(pc->base + pc->data->regs.ctrl);
>> +
>> + if (enable)
>> + val |= enable_conf;
>> + else
>> + val &= ~enable_conf;
>> +
>> + writel_relaxed(val, pc->base + pc->data->regs.ctrl);
>> +}
>> +
>> +static void rockchip_pwm_set_enable_v2(struct pwm_chip *chip, bool enable)
>> +{
>> + struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
>> + u32 val = 0;
>> + u32 enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE |
>> + PWM_CONTINUOUS | PWM_DUTY_POSITIVE | PWM_INACTIVE_NEGATIVE;
>> +
>> + val = readl_relaxed(pc->base + pc->data->regs.ctrl);
>> +
>> + if (enable)
>> + val |= enable_conf;
>> + else
>> + val &= ~enable_conf;
>> +
>> + writel_relaxed(val, pc->base + pc->data->regs.ctrl);
>> +}
>> +
>> static int rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
>> int duty_ns, int period_ns)
>> {
>> @@ -52,20 +109,20 @@ static int rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
>> * default prescaler value for all practical clock rate values.
>> */
>> div = clk_rate * period_ns;
>> - do_div(div, PRESCALER * NSEC_PER_SEC);
>> + do_div(div, pc->data->prescaler * NSEC_PER_SEC);
>> period = div;
>>
>> div = clk_rate * duty_ns;
>> - do_div(div, PRESCALER * NSEC_PER_SEC);
>> + do_div(div, pc->data->prescaler * NSEC_PER_SEC);
>> duty = div;
>>
>> ret = clk_enable(pc->clk);
>> if (ret)
>> return ret;
>>
>> - writel(period, pc->base + PWM_LRC);
>> - writel(duty, pc->base + PWM_HRC);
>> - writel(0, pc->base + PWM_CNTR);
>> + writel(period, pc->base + pc->data->regs.period);
>> + writel(duty, pc->base + pc->data->regs.duty);
>> + writel(0, pc->base + pc->data->regs.cntr);
>>
>> clk_disable(pc->clk);
>>
>> @@ -76,15 +133,12 @@ static int rockchip_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
>> {
>> struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
>> int ret;
>> - u32 val;
>>
>> ret = clk_enable(pc->clk);
>> if (ret)
>> return ret;
>>
>> - val = readl_relaxed(pc->base + PWM_CTRL);
>> - val |= PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN;
>> - writel_relaxed(val, pc->base + PWM_CTRL);
>> + pc->data->set_enable(chip, true);
>>
>> return 0;
>> }
>> @@ -92,11 +146,8 @@ static int rockchip_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
>> static void rockchip_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
>> {
>> struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
>> - u32 val;
>>
>> - val = readl_relaxed(pc->base + PWM_CTRL);
>> - val &= ~(PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN);
>> - writel_relaxed(val, pc->base + PWM_CTRL);
>> + pc->data->set_enable(chip, false);
>>
>> clk_disable(pc->clk);
>> }
>> @@ -108,12 +159,52 @@ static const struct pwm_ops rockchip_pwm_ops = {
>> .owner = THIS_MODULE,
>> };
>>
>> +static const struct rockchip_pwm_data pwm_data_v1 = {
>> + .regs.duty = PWM_HRC,
>> + .regs.period = PWM_LRC,
>> + .regs.cntr = PWM_CNTR,
>> + .regs.ctrl = PWM_CTRL,
> Perhaps a slightly more idiomatic way to write this would be:
>
> static const struct rockchip_pwm_data pwm_data_v1 = {
> .regs = {
> .duty = PWM_HRC,
> .period = PWM_LRC,
> .cntr = PWM_CNTR,
> .ctrl = PWM_CTRL,
> },
> ...
> };
>
> And similar for the v2 and vop structures. And like I said in another
> reply, since the defines are now only used in this structure it's a
> little redundant to give them symbolic names, so the above could equally
> well be:
>
> static const struct rockchip_pwm_data pwm_data_v1 = {
> .regs = {
> .duty = 0x04,
> .period = 0x08,
> .cntr = 0x00,
> .ctrl = 0x0c,
> },
> ...
> };
>
>> + .prescaler = PRESCALER,
> Similarly for the prescaler value, it can now simply be 2 here.
>
>> + .set_enable = rockchip_pwm_set_enable_v1,
>> +};
>> +
>> +static const struct rockchip_pwm_data pwm_data_v2 = {
>> + .regs.duty = PWM_LRC,
>> + .regs.period = PWM_HRC,
>> + .regs.cntr = PWM_CNTR,
>> + .regs.ctrl = PWM_CTRL,
>> + .prescaler = PRESCALER-1,
> And 1 here.
>
>> + .set_enable = rockchip_pwm_set_enable_v2,
>> +};
>> +
>> +static const struct rockchip_pwm_data pwm_data_vop = {
>> + .regs.duty = PWM_LRC,
>> + .regs.period = PWM_HRC,
>> + .regs.cntr = PWM_CTRL,
>> + .regs.ctrl = PWM_CNTR,
>> + .prescaler = PRESCALER-1,
> And 1 here.
As you say, I will rewrite the about if it's really need do so it.
For example:
static const struct rockchip_pwm_data pwm_data_v1 = {
.regs = {
.duty = 0x04,
.period = 0x08,
.cntr = 0x00,
.ctrl = 0x0c,
},
.prescaler = 2,
.set_enable = rockchip_pwm_set_enable_v1,
};
static const struct rockchip_pwm_data pwm_data_v2 = {
.regs = {
.duty = 0x08,
.period = 0x04,
.cntr = 0x00,
.ctrl = 0x0c,
},
.prescaler = 1,
.set_enable = rockchip_pwm_set_enable_v2,
};
static const struct rockchip_pwm_data pwm_data_vop = {
.regs = {
.duty = 0x08,
.period = 0x04,
.cntr = 0x0c,
.ctrl = 0x00,
},
.prescaler = 1,
.set_enable = rockchip_pwm_set_enable_v2,
};
Is that right?
>> + .set_enable = rockchip_pwm_set_enable_v2,
>> +};
> No need for the double indirection.
Sorry, I think is need if you mean a double indirection for ".set_enable".
Caesar
>
> Thierry
WARNING: multiple messages have this Message-ID (diff)
From: caesar <caesar.wang@rock-chips.com>
To: Thierry Reding <thierry.reding@gmail.com>
Cc: heiko@sntech.de, b.galvani@gmail.com, robh+dt@kernel.org,
ijc+devicetree@hellion.org.uk, rdunlap@infradead.org,
galak@codeaurora.org, cf@rock-chips.com, huangtao@rock-chips.com,
xjq@rock-chips.com, addy.ke@rock-chips.com, cjf@rock-chips.com,
hj@rock-chips.com, linux-arm-kernel@lists.infradead.org,
linux-pwm@vger.kernel.org, linux-kernel@vger.kernel.org,
devicetree@vger.kernel.org, linux-doc@vger.kernel.org
Subject: Re: [PATCH v4 2/2] pwm: rockchip: Added to support for RK3288 SoC
Date: Thu, 07 Aug 2014 21:04:30 +0800 [thread overview]
Message-ID: <53E3795E.4080607@rock-chips.com> (raw)
In-Reply-To: <20140807061842.GB17340@ulmo>
Thierry,
在 2014年08月07日 14:18, Thierry Reding 写道:
> On Thu, Jul 24, 2014 at 06:21:35PM +0800, Caesar Wang wrote:
>> This patch added to support the PWM controller found on
>> RK3288 SoC.
>>
>> Signed-off-by: Caesar Wang <caesar.wang@rock-chips.com>
>> ---
>> drivers/pwm/pwm-rockchip.c | 124 ++++++++++++++++++++++++++++++++++++++-------
>> 1 file changed, 105 insertions(+), 19 deletions(-)
>>
>> diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c
>> index eec2145..59c2513 100644
>> --- a/drivers/pwm/pwm-rockchip.c
>> +++ b/drivers/pwm/pwm-rockchip.c
>> @@ -2,6 +2,7 @@
>> * PWM driver for Rockchip SoCs
>> *
>> * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com>
>> + * Copyright (C) 2014 ROCKCHIP, Inc.
>> *
>> * This program is free software; you can redistribute it and/or
>> * modify it under the terms of the GNU General Public License
>> @@ -12,6 +13,7 @@
>> #include <linux/io.h>
>> #include <linux/module.h>
>> #include <linux/of.h>
>> +#include <linux/of_device.h>
>> #include <linux/platform_device.h>
>> #include <linux/pwm.h>
>> #include <linux/time.h>
>> @@ -25,17 +27,72 @@
>>
>> #define PRESCALER 2
>>
>> +#define PWM_ENABLE (1 << 0)
>> +#define PWM_CONTINUOUS (1 << 1)
>> +#define PWM_DUTY_POSITIVE (1 << 3)
>> +#define PWM_INACTIVE_NEGATIVE (0 << 4)
>> +#define PWM_OUTPUT_LEFT (0 << 5)
>> +#define PWM_LP_DISABLE (0 << 8)
>> +
>> struct rockchip_pwm_chip {
>> struct pwm_chip chip;
>> struct clk *clk;
>> + const struct rockchip_pwm_data *data;
>> void __iomem *base;
>> };
>>
>> +struct rockchip_pwm_regs {
>> + unsigned long duty;
>> + unsigned long period;
>> + unsigned long cntr;
>> + unsigned long ctrl;
>> +};
>> +
>> +struct rockchip_pwm_data {
>> + struct rockchip_pwm_regs regs;
>> + unsigned int prescaler;
>> +
>> + void (*set_enable)(struct pwm_chip *chip, bool enable);
>> +};
>> +
>> static inline struct rockchip_pwm_chip *to_rockchip_pwm_chip(struct pwm_chip *c)
>> {
>> return container_of(c, struct rockchip_pwm_chip, chip);
>> }
>>
>> +static void rockchip_pwm_set_enable_v1(struct pwm_chip *chip, bool enable)
>> +{
>> + struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
>> + u32 val = 0;
>> + u32 enable_conf = PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN;
>> +
>> + val = readl_relaxed(pc->base + pc->data->regs.ctrl);
>> +
>> + if (enable)
>> + val |= enable_conf;
>> + else
>> + val &= ~enable_conf;
>> +
>> + writel_relaxed(val, pc->base + pc->data->regs.ctrl);
>> +}
>> +
>> +static void rockchip_pwm_set_enable_v2(struct pwm_chip *chip, bool enable)
>> +{
>> + struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
>> + u32 val = 0;
>> + u32 enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE |
>> + PWM_CONTINUOUS | PWM_DUTY_POSITIVE | PWM_INACTIVE_NEGATIVE;
>> +
>> + val = readl_relaxed(pc->base + pc->data->regs.ctrl);
>> +
>> + if (enable)
>> + val |= enable_conf;
>> + else
>> + val &= ~enable_conf;
>> +
>> + writel_relaxed(val, pc->base + pc->data->regs.ctrl);
>> +}
>> +
>> static int rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
>> int duty_ns, int period_ns)
>> {
>> @@ -52,20 +109,20 @@ static int rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
>> * default prescaler value for all practical clock rate values.
>> */
>> div = clk_rate * period_ns;
>> - do_div(div, PRESCALER * NSEC_PER_SEC);
>> + do_div(div, pc->data->prescaler * NSEC_PER_SEC);
>> period = div;
>>
>> div = clk_rate * duty_ns;
>> - do_div(div, PRESCALER * NSEC_PER_SEC);
>> + do_div(div, pc->data->prescaler * NSEC_PER_SEC);
>> duty = div;
>>
>> ret = clk_enable(pc->clk);
>> if (ret)
>> return ret;
>>
>> - writel(period, pc->base + PWM_LRC);
>> - writel(duty, pc->base + PWM_HRC);
>> - writel(0, pc->base + PWM_CNTR);
>> + writel(period, pc->base + pc->data->regs.period);
>> + writel(duty, pc->base + pc->data->regs.duty);
>> + writel(0, pc->base + pc->data->regs.cntr);
>>
>> clk_disable(pc->clk);
>>
>> @@ -76,15 +133,12 @@ static int rockchip_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
>> {
>> struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
>> int ret;
>> - u32 val;
>>
>> ret = clk_enable(pc->clk);
>> if (ret)
>> return ret;
>>
>> - val = readl_relaxed(pc->base + PWM_CTRL);
>> - val |= PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN;
>> - writel_relaxed(val, pc->base + PWM_CTRL);
>> + pc->data->set_enable(chip, true);
>>
>> return 0;
>> }
>> @@ -92,11 +146,8 @@ static int rockchip_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
>> static void rockchip_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
>> {
>> struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
>> - u32 val;
>>
>> - val = readl_relaxed(pc->base + PWM_CTRL);
>> - val &= ~(PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN);
>> - writel_relaxed(val, pc->base + PWM_CTRL);
>> + pc->data->set_enable(chip, false);
>>
>> clk_disable(pc->clk);
>> }
>> @@ -108,12 +159,52 @@ static const struct pwm_ops rockchip_pwm_ops = {
>> .owner = THIS_MODULE,
>> };
>>
>> +static const struct rockchip_pwm_data pwm_data_v1 = {
>> + .regs.duty = PWM_HRC,
>> + .regs.period = PWM_LRC,
>> + .regs.cntr = PWM_CNTR,
>> + .regs.ctrl = PWM_CTRL,
> Perhaps a slightly more idiomatic way to write this would be:
>
> static const struct rockchip_pwm_data pwm_data_v1 = {
> .regs = {
> .duty = PWM_HRC,
> .period = PWM_LRC,
> .cntr = PWM_CNTR,
> .ctrl = PWM_CTRL,
> },
> ...
> };
>
> And similar for the v2 and vop structures. And like I said in another
> reply, since the defines are now only used in this structure it's a
> little redundant to give them symbolic names, so the above could equally
> well be:
>
> static const struct rockchip_pwm_data pwm_data_v1 = {
> .regs = {
> .duty = 0x04,
> .period = 0x08,
> .cntr = 0x00,
> .ctrl = 0x0c,
> },
> ...
> };
>
>> + .prescaler = PRESCALER,
> Similarly for the prescaler value, it can now simply be 2 here.
>
>> + .set_enable = rockchip_pwm_set_enable_v1,
>> +};
>> +
>> +static const struct rockchip_pwm_data pwm_data_v2 = {
>> + .regs.duty = PWM_LRC,
>> + .regs.period = PWM_HRC,
>> + .regs.cntr = PWM_CNTR,
>> + .regs.ctrl = PWM_CTRL,
>> + .prescaler = PRESCALER-1,
> And 1 here.
>
>> + .set_enable = rockchip_pwm_set_enable_v2,
>> +};
>> +
>> +static const struct rockchip_pwm_data pwm_data_vop = {
>> + .regs.duty = PWM_LRC,
>> + .regs.period = PWM_HRC,
>> + .regs.cntr = PWM_CTRL,
>> + .regs.ctrl = PWM_CNTR,
>> + .prescaler = PRESCALER-1,
> And 1 here.
As you say, I will rewrite the about if it's really need do so it.
For example:
static const struct rockchip_pwm_data pwm_data_v1 = {
.regs = {
.duty = 0x04,
.period = 0x08,
.cntr = 0x00,
.ctrl = 0x0c,
},
.prescaler = 2,
.set_enable = rockchip_pwm_set_enable_v1,
};
static const struct rockchip_pwm_data pwm_data_v2 = {
.regs = {
.duty = 0x08,
.period = 0x04,
.cntr = 0x00,
.ctrl = 0x0c,
},
.prescaler = 1,
.set_enable = rockchip_pwm_set_enable_v2,
};
static const struct rockchip_pwm_data pwm_data_vop = {
.regs = {
.duty = 0x08,
.period = 0x04,
.cntr = 0x0c,
.ctrl = 0x00,
},
.prescaler = 1,
.set_enable = rockchip_pwm_set_enable_v2,
};
Is that right?
>> + .set_enable = rockchip_pwm_set_enable_v2,
>> +};
> No need for the double indirection.
Sorry, I think is need if you mean a double indirection for ".set_enable".
Caesar
>
> Thierry
next prev parent reply other threads:[~2014-08-07 13:04 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-07-24 10:21 [PATCH v4 0/2] This series adds support for RK3288 SoC integrated PWM Caesar Wang
2014-07-24 10:21 ` Caesar Wang
2014-07-24 10:21 ` [PATCH v4 1/2] pwm: rockchip: document RK3288 SoC compatible Caesar Wang
2014-07-24 10:21 ` Caesar Wang
2014-07-24 10:21 ` [PATCH v4 2/2] pwm: rockchip: Added to support for RK3288 SoC Caesar Wang
2014-07-24 10:21 ` Caesar Wang
2014-08-06 22:46 ` Doug Anderson
2014-08-06 22:46 ` Doug Anderson
2014-08-07 1:27 ` caesar
2014-08-07 1:27 ` caesar
2014-08-07 2:16 ` Doug Anderson
2014-08-07 2:16 ` Doug Anderson
2014-08-07 3:23 ` caesar
2014-08-07 3:23 ` caesar
2014-08-07 3:26 ` Doug Anderson
2014-08-07 3:26 ` Doug Anderson
2014-08-07 3:37 ` caesar
2014-08-07 3:37 ` caesar
2014-08-07 3:46 ` Doug Anderson
2014-08-07 3:46 ` Doug Anderson
2014-08-07 4:05 ` caesar
2014-08-07 4:05 ` caesar
2014-08-07 6:12 ` Thierry Reding
2014-08-07 6:12 ` Thierry Reding
2014-08-07 6:18 ` Thierry Reding
2014-08-07 6:18 ` Thierry Reding
2014-08-07 13:04 ` caesar [this message]
2014-08-07 13:04 ` caesar
2014-08-07 13:04 ` caesar
2014-08-07 13:14 ` Thierry Reding
2014-08-07 13:14 ` Thierry Reding
2014-08-07 13:55 ` caesar
2014-08-07 13:55 ` caesar
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=53E3795E.4080607@rock-chips.com \
--to=caesar.wang-tnx95d0mmh7dzftrwevzcw@public.gmane.org \
--cc=addy.ke-TNX95d0MmH7DzftRWevZcw@public.gmane.org \
--cc=b.galvani-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
--cc=cf-TNX95d0MmH7DzftRWevZcw@public.gmane.org \
--cc=cjf-TNX95d0MmH7DzftRWevZcw@public.gmane.org \
--cc=devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=galak-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org \
--cc=heiko-4mtYJXux2i+zQB+pC5nmwQ@public.gmane.org \
--cc=hj-TNX95d0MmH7DzftRWevZcw@public.gmane.org \
--cc=huangtao-TNX95d0MmH7DzftRWevZcw@public.gmane.org \
--cc=ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg@public.gmane.org \
--cc=linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org \
--cc=linux-doc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=linux-pwm-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=rdunlap-wEGCiKHe2LqWVfeAwA7xHQ@public.gmane.org \
--cc=robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org \
--cc=thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
--cc=xjq-TNX95d0MmH7DzftRWevZcw@public.gmane.org \
/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.