* [PATCH 2/2] ARM: omap: timers: reduce rating of gp_timer clocksource
From: Keerthy @ 2016-12-05 4:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161202183139.GF4705@atomide.com>
On Saturday 03 December 2016 12:01 AM, Tony Lindgren wrote:
> * Grygorii Strashko <grygorii.strashko@ti.com> [161202 10:02]:
>>
>>
>> On 12/02/2016 10:47 AM, Tony Lindgren wrote:
>>> * Grygorii Strashko <grygorii.strashko@ti.com> [161129 08:43]:
>>>>
>>>>
>>>> On 11/24/2016 12:19 AM, Keerthy wrote:
>>>>> From: Grygorii Strashko <grygorii.strashko@ti.com>
>>>>>
>>>>> Now ARM Global timer (rating 300) will not be selected as clocksource,
>>>>> because it's initialized after OMAP GP Timer (rating 300) and
>>>>> Timekeeping core will not allow to replace clocksource with new one if
>>>>> both of them have the same rating.
>>>>>
>>>>> Reduce rating of OMAP GP Timer (300->290) when it's used as
>>>>> clocksource device - this will allow to select ARM Global timer (300)
>>>>> as clocksource when enabled.
>>>>>
>>>>> Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
>>>>> Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
>>>>> Signed-off-by: Keerthy <j-keerthy@ti.com>
>>>>
>>>> Unfortunately, this patch has dependency [1] and can't be used alone as
>>>> it will cause ARM Global timer to be selected as clocksource
>>>> always on am437x and this will kill cpuidle, because ARM Global timer
>>>> is not in always_on domain.
>>>>
>>>> The intention of enabling ARM Global timer is only for non-pm aware use
>>>> cases for RT-kernel latency improvement - where deep cpuidle states are not
>>>> enabled.
>>>
>>> Yeah we need to fix up things to be able to change the clocksource
>>> in addition to clockevent. However, currently only cpuidle_coupled
>>> knows when the whole system is idle, so quite a bit of work is
>>> needed to do that in a sane way.
>>
>> Also sched_clock and timer_delay ;)
>
> Yeah sched_clock would need something to save and restore it..
> Not nice :)
>
>>> What about the first patch in this series?
>>>
>>
>> Fist one is ok. It was originally posted long time ago.
>
> OK so can you please resend that one more time with proper
> Fixes tag on it?
Tony,
I have posted a v2 with the proper Fixes tag.
- Keerthy
>
> Regards,
>
> Tony
>
^ permalink raw reply
* [PATCH v2] ARM: omap2: am437x: rollback to use omap3_gptimer_timer_init()
From: Keerthy @ 2016-12-05 3:57 UTC (permalink / raw)
To: linux-arm-kernel
From: Grygorii Strashko <grygorii.strashko@ti.com>
The commit 55ee7017ee31 ("arm: omap2: board-generic: use
omap4_local_timer_init for AM437x") unintentionally changes the
clocksource devices for AM437x from OMAP GP Timer to SyncTimer32K.
Unfortunately, the SyncTimer32K is starving from frequency deviation
as mentioned in commit 5b5c01359152 ("ARM: OMAP2+: AM43x: Use gptimer
as clocksource") and, as reported by Franklin [1], even its monotonic
nature is under question (most probably there is a HW issue, but it's
still under investigation).
Taking into account above facts It's reasonable to rollback to the use
of omap3_gptimer_timer_init().
[1] http://www.spinics.net/lists/linux-omap/msg127425.html
Fixes: 55ee7017ee31 ("arm: omap2: board-generic: use
omap4_local_timer_init for AM437x")
Reported-by: Cooper Jr., Franklin <fcooper@ti.com>
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
Signed-off-by: Keerthy <j-keerthy@ti.com>
---
Changes in v2:
* Added a proper Fixes tag with the commit ID.
arch/arm/mach-omap2/board-generic.c | 2 +-
arch/arm/mach-omap2/timer.c | 9 +++++----
2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
index 36d9943..dc9e34e 100644
--- a/arch/arm/mach-omap2/board-generic.c
+++ b/arch/arm/mach-omap2/board-generic.c
@@ -304,7 +304,7 @@ static void __init rx51_reserve(void)
.init_late = am43xx_init_late,
.init_irq = omap_gic_of_init,
.init_machine = omap_generic_init,
- .init_time = omap4_local_timer_init,
+ .init_time = omap3_gptimer_timer_init,
.dt_compat = am43_boards_compat,
.restart = omap44xx_restart,
MACHINE_END
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index 5e2e221..b2f2448 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -510,18 +510,19 @@ void __init omap3_secure_sync32k_timer_init(void)
}
#endif /* CONFIG_ARCH_OMAP3 */
-#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_SOC_AM33XX)
+#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_SOC_AM33XX) || \
+ defined(CONFIG_SOC_AM43XX)
void __init omap3_gptimer_timer_init(void)
{
__omap_sync32k_timer_init(2, "timer_sys_ck", NULL,
1, "timer_sys_ck", "ti,timer-alwon", true);
-
- clocksource_probe();
+ if (of_have_populated_dt())
+ clocksource_probe();
}
#endif
#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) || \
- defined(CONFIG_SOC_DRA7XX) || defined(CONFIG_SOC_AM43XX)
+ defined(CONFIG_SOC_DRA7XX)
static void __init omap4_sync32k_timer_init(void)
{
__omap_sync32k_timer_init(1, "timer_32k_ck", "ti,timer-alwon",
--
1.9.1
^ permalink raw reply related
* [PATCH v4] ARM: davinci: da8xx: Fix sleeping function called from invalid context
From: David Lechner @ 2016-12-05 3:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480690380-13216-1-git-send-email-abailon@baylibre.com>
On 12/02/2016 08:53 AM, Alexandre Bailon wrote:
> Everytime the usb20 phy is enabled, there is a
> "sleeping function called from invalid context" BUG.
>
> clk_enable() from arch/arm/mach-davinci/clock.c uses spin_lock_irqsave()
> before to invoke the callback usb20_phy_clk_enable().
> usb20_phy_clk_enable() uses clk_get() and clk_enable_prepapre()
> which may sleep.
> Move clk_get() to da8xx_register_usb20_phy_clk() and
> replace clk_prepare_enable() by clk_enable().
>
> Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
> ---
> arch/arm/mach-davinci/usb-da8xx.c | 28 +++++++++++++++-------------
> 1 file changed, 15 insertions(+), 13 deletions(-)
>
> diff --git a/arch/arm/mach-davinci/usb-da8xx.c b/arch/arm/mach-davinci/usb-da8xx.c
> index b010e5f..704f506 100644
> --- a/arch/arm/mach-davinci/usb-da8xx.c
> +++ b/arch/arm/mach-davinci/usb-da8xx.c
> @@ -22,6 +22,8 @@
> #define DA8XX_USB0_BASE 0x01e00000
> #define DA8XX_USB1_BASE 0x01e25000
>
> +static struct clk *usb20_clk;
> +
> static struct platform_device da8xx_usb_phy = {
> .name = "da8xx-usb-phy",
> .id = -1,
> @@ -158,21 +160,14 @@ int __init da8xx_register_usb_refclkin(int rate)
>
> static void usb20_phy_clk_enable(struct clk *clk)
> {
> - struct clk *usb20_clk;
> int err;
> u32 val;
> u32 timeout = 500000; /* 500 msec */
>
> val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
>
> - usb20_clk = clk_get(&da8xx_usb20_dev.dev, "usb20");
> - if (IS_ERR(usb20_clk)) {
> - pr_err("could not get usb20 clk: %ld\n", PTR_ERR(usb20_clk));
> - return;
> - }
> -
> /* The USB 2.O PLL requires that the USB 2.O PSC is enabled as well. */
> - err = clk_prepare_enable(usb20_clk);
> + err = clk_enable(usb20_clk);
> if (err) {
> pr_err("failed to enable usb20 clk: %d\n", err);
> clk_put(usb20_clk);
Need to remove clk_put() here.
> @@ -197,8 +192,7 @@ static void usb20_phy_clk_enable(struct clk *clk)
>
> pr_err("Timeout waiting for USB 2.0 PHY clock good\n");
> done:
> - clk_disable_unprepare(usb20_clk);
> - clk_put(usb20_clk);
> + clk_disable(usb20_clk);
> }
>
> static void usb20_phy_clk_disable(struct clk *clk)
> @@ -285,11 +279,19 @@ static struct clk_lookup usb20_phy_clk_lookup =
> int __init da8xx_register_usb20_phy_clk(bool use_usb_refclkin)
> {
> struct clk *parent;
> - int ret = 0;
> + int ret;
> +
> + usb20_clk = clk_get(&da8xx_usb20_dev.dev, "usb20");
> + ret = PTR_ERR_OR_ZERO(usb20_clk);
> + if (ret)
> + return ret;
>
> parent = clk_get(NULL, use_usb_refclkin ? "usb_refclkin" : "pll0_aux");
> - if (IS_ERR(parent))
> - return PTR_ERR(parent);
> + ret = PTR_ERR_OR_ZERO(parent);
> + if (ret) {
> + clk_put(usb20_clk);
> + return ret;
> + }
>
> usb20_phy_clk.parent = parent;
> ret = clk_register(&usb20_phy_clk);
>
I have just tried this patch with a bunch of kernel hacking options
enabled. I am getting the message show at the end of this email. We
still have the problem of nested spin locks due to nested calls to
clk_enable(). So, really, we need to use __clk_enable() and
__clk_disable() from arch/arm/mach-davinci/clock.c in
usb20_phy_clk_enable() above.
Applying the following patch on top of your patch fixed the recursive
lock message.
---
diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c
index df42c93..4fba579 100644
--- a/arch/arm/mach-davinci/clock.c
+++ b/arch/arm/mach-davinci/clock.c
@@ -31,7 +31,7 @@ static LIST_HEAD(clocks);
static DEFINE_MUTEX(clocks_mutex);
static DEFINE_SPINLOCK(clockfw_lock);
-static void __clk_enable(struct clk *clk)
+void __clk_enable(struct clk *clk)
{
if (clk->parent)
__clk_enable(clk->parent);
@@ -44,7 +44,7 @@ static void __clk_enable(struct clk *clk)
}
}
-static void __clk_disable(struct clk *clk)
+void __clk_disable(struct clk *clk)
{
if (WARN_ON(clk->usecount == 0))
return;
diff --git a/arch/arm/mach-davinci/clock.h b/arch/arm/mach-davinci/clock.h
index e2a5437..8493242 100644
--- a/arch/arm/mach-davinci/clock.h
+++ b/arch/arm/mach-davinci/clock.h
@@ -136,6 +136,9 @@ int davinci_clk_reset(struct clk *clk, bool reset);
extern struct platform_device davinci_wdt_device;
extern void davinci_watchdog_reset(struct platform_device *);
+void __clk_enable(struct clk *clk);
+void __clk_disable(struct clk *clk);
+
#endif
#endif
diff --git a/arch/arm/mach-davinci/usb-da8xx.c
b/arch/arm/mach-davinci/usb-da8xx
.c
index 896d014..80ba0df 100644
--- a/arch/arm/mach-davinci/usb-da8xx.c
+++ b/arch/arm/mach-davinci/usb-da8xx.c
@@ -160,19 +160,13 @@ int __init da8xx_register_usb_refclkin(int rate)
static void usb20_phy_clk_enable(struct clk *clk)
{
- int err;
u32 val;
u32 timeout = 500000; /* 500 msec */
val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
/* The USB 2.O PLL requires that the USB 2.O PSC is enabled as
well. */
- err = clk_enable(usb20_clk);
- if (err) {
- pr_err("failed to enable usb20 clk: %d\n", err);
- clk_put(usb20_clk);
- return;
- }
+ __clk_enable(usb20_clk);
/*
* Turn on the USB 2.0 PHY, but just the PLL, and not OTG. The
USB 1.1
@@ -192,7 +186,7 @@ static void usb20_phy_clk_enable(struct clk *clk)
pr_err("Timeout waiting for USB 2.0 PHY clock good\n");
done:
- clk_disable(usb20_clk);
+ __clk_disable(usb20_clk);
}
static void usb20_phy_clk_disable(struct clk *clk)
---
=============================================
[ INFO: possible recursive locking detected ]
4.9.0-rc8-dlech-ev3-lms2012+ #22 Not tainted
---------------------------------------------
swapper/1 is trying to acquire lock:
(
clockfw_lock
){......}
, at:
[<c0014884>] clk_enable+0x24/0x50
k:
(
clockfw_lock
){......}
, at:
[<c0014884>] clk_enable+0x24/0x50
ebug this:
Possible unsafe locking scenario:
CPU0
----
lock(
clockfw_lock
);
lock(
clockfw_lock
);
May be due to missing lock nesting notation
4 locks held by swapper/1:
#0:
(
&dev->mutex
){......}
, at:
[<c02bd60c>] __driver_attach+0x68/0xb4
#1:
(
&dev->mutex
){......}
, at:
[<c02bd61c>] __driver_attach+0x78/0xb4
#2:
(
&phy->mutex
){+.+...}
, at:
[<c025ee18>] phy_power_on+0x5c/0xe4
#3:
(
clockfw_lock
){......}
, at:
[<c0014884>] clk_enable+0x24/0x50
CPU: 0 PID: 1 Comm: swapper Not tainted 4.9.0-rc8-dlech-ev3-lms2012+ #22
Hardware name: Generic DA850/OMAP-L138/AM18x
Backtrace:
[<c000d824>] (dump_backtrace) from [<c000dac4>] (show_stack+0x18/0x1c)
r7:c0e998a4 r6:c0820750 r5:c0820750 r4:c3838000
[<c000daac>] (show_stack) from [<c02393dc>] (dump_stack+0x20/0x28)
[<c02393bc>] (dump_stack) from [<c004bd7c>] (__lock_acquire+0x10f4/0x167c)
[<c004ac88>] (__lock_acquire) from [<c004c6ac>] (lock_acquire+0x78/0x98)
r10:00000000 r9:c06a5ed4 r8:00000000 r7:00000001 r6:60000093 r5:00000000
r4:ffffe000
[<c004c634>] (lock_acquire) from [<c04d8fac>]
(_raw_spin_lock_irqsave+0x60/0x74)
r7:0000003b r6:c0014884 r5:80000093 r4:c06b09a0
[<c04d8f4c>] (_raw_spin_lock_irqsave) from [<c0014884>]
(clk_enable+0x24/0x50)
r6:c06f69f4 r5:0001ef02 r4:c06b3398
[<c0014860>] (clk_enable) from [<c0015c74>] (usb20_phy_clk_enable+0x24/0xb8)
r5:0001ef02 r4:c06f69f0
[<c0015c50>] (usb20_phy_clk_enable) from [<c0014858>]
(__clk_enable+0x74/0x7c)
r9:c06a5ed4 r8:00000000 r7:0000003b r6:c3a6ca00 r5:80000013 r4:c06b7ee8
[<c00147e4>] (__clk_enable) from [<c0014808>] (__clk_enable+0x24/0x7c)
r4:c06b8648
[<c00147e4>] (__clk_enable) from [<c0014890>] (clk_enable+0x30/0x50)
r4:c06b8648
[<c0014860>] (clk_enable) from [<c025f43c>]
(da8xx_usb11_phy_power_on+0x30/0x80)
r5:c3a54050 r4:c06b8648
[<c025f40c>] (da8xx_usb11_phy_power_on) from [<c025ee3c>]
(phy_power_on+0x80/0xe4)
r5:c3a6c800 r4:fffffdf4
[<c025edbc>] (phy_power_on) from [<c032243c>] (ohci_da8xx_enable+0x4c/0x80)
r7:0000003b r6:c3af6000 r5:c3af6000 r4:00000000
[<c03223f0>] (ohci_da8xx_enable) from [<c03224f0>]
(ohci_da8xx_reset+0x1c/0xd8)
r5:00000000 r4:c3af6000
[<c03224d4>] (ohci_da8xx_reset) from [<c0309118>] (usb_add_hcd+0x314/0x834)
r7:0000003b r6:ffffffed r5:00000000 r4:c3af6000
[<c0308e04>] (usb_add_hcd) from [<c032200c>] (ohci_da8xx_probe+0x14c/0x21c)
r9:c06a5ed4 r8:00000000 r7:c38bd010 r6:c38bd000 r5:c3af6000 r4:c38af900
[<c0321ec0>] (ohci_da8xx_probe) from [<c02bec44>]
(platform_drv_probe+0x40/0x8c)
r7:c06e610c r6:c06e610c r5:c38bd010 r4:c0321ec0
[<c02bec04>] (platform_drv_probe) from [<c02bd438>]
(driver_probe_device+0x138/0x2a4)
r7:c06e610c r6:c0e9db10 r5:00000000 r4:c38bd010
[<c02bd300>] (driver_probe_device) from [<c02bd634>]
(__driver_attach+0x90/0xb4)
r9:c06a5ed4 r8:c06f66e0 r7:c06e1250 r6:c06e610c r5:c38bd044 r4:c38bd010
[<c02bd5a4>] (__driver_attach) from [<c02bba5c>]
(bus_for_each_dev+0x74/0x98)
r7:c06e1250 r6:c02bd5a4 r5:c06e610c r4:00000000
[<c02bb9e8>] (bus_for_each_dev) from [<c02bcf2c>] (driver_attach+0x20/0x28)
r6:c39a2300 r5:00000000 r4:c06e610c
[<c02bcf0c>] (driver_attach) from [<c02bca80>] (bus_add_driver+0xd4/0x1f0)
[<c02bc9ac>] (bus_add_driver) from [<c02bdcec>] (driver_register+0xa4/0xe8)
r7:c0698850 r6:00000000 r5:00000000 r4:c06e610c
[<c02bdc48>] (driver_register) from [<c02bebac>]
(__platform_driver_register+0x38/0x4c)
r5:00000000 r4:c06acce4
[<c02beb74>] (__platform_driver_register) from [<c068da20>]
(ohci_da8xx_init+0x64/0x90)
[<c068d9bc>] (ohci_da8xx_init) from [<c00096c0>]
(do_one_initcall+0xb0/0x168)
r5:c068d9bc r4:ffffe000
[<c0009610>] (do_one_initcall) from [<c0676e14>]
(kernel_init_freeable+0x110/0x1cc)
r9:c06a5ed4 r8:c06f66e0 r7:c0698850 r6:000000c1 r5:c06f66e0 r4:00000007
[<c0676d04>] (kernel_init_freeable) from [<c04d37e4>]
(kernel_init+0x10/0xf8)
r9:00000000 r8:00000000 r7:00000000 r6:00000000 r5:c04d37d4 r4:00000000
[<c04d37d4>] (kernel_init) from [<c000a2ac>] (ret_from_fork+0x14/0x28)
r5:c04d37d4 r4:00000000
BUG: spinlock lockup suspected on CPU#0, swapper/1
lock: clockfw_lock+0x0/0x20, .magic: dead4ead, .owner: swapper/1,
.owner_cpu: 0
CPU: 0 PID: 1 Comm: swapper Not tainted 4.9.0-rc8-dlech-ev3-lms2012+ #22
Hardware name: Generic DA850/OMAP-L138/AM18x
Backtrace:
[<c000d824>] (dump_backtrace) from [<c000dac4>] (show_stack+0x18/0x1c)
r7:00000000 r6:04605000 r5:c06b09a0 r4:c3838000
[<c000daac>] (show_stack) from [<c02393dc>] (dump_stack+0x20/0x28)
[<c02393bc>] (dump_stack) from [<c004f140>] (spin_dump+0x80/0x94)
[<c004f0c0>] (spin_dump) from [<c004f2c4>] (do_raw_spin_lock+0xdc/0x11c)
r5:00000000 r4:c06b09a0
[<c004f1e8>] (do_raw_spin_lock) from [<c04d8fb4>]
(_raw_spin_lock_irqsave+0x68/0x74)
r10:00000000 r9:c06a5ed4 r8:00000000 r7:0000003b r6:c0014884 r5:80000093
r4:c06b09a0 r3:c3838000
[<c04d8f4c>] (_raw_spin_lock_irqsave) from [<c0014884>]
(clk_enable+0x24/0x50)
r6:c06f69f4 r5:0001ef02 r4:c06b3398
[<c0014860>] (clk_enable) from [<c0015c74>] (usb20_phy_clk_enable+0x24/0xb8)
r5:0001ef02 r4:c06f69f0
[<c0015c50>] (usb20_phy_clk_enable) from [<c0014858>]
(__clk_enable+0x74/0x7c)
r9:c06a5ed4 r8:00000000 r7:0000003b r6:c3a6ca00 r5:80000013 r4:c06b7ee8
[<c00147e4>] (__clk_enable) from [<c0014808>] (__clk_enable+0x24/0x7c)
r4:c06b8648
[<c00147e4>] (__clk_enable) from [<c0014890>] (clk_enable+0x30/0x50)
r4:c06b8648
[<c0014860>] (clk_enable) from [<c025f43c>]
(da8xx_usb11_phy_power_on+0x30/0x80)
r5:c3a54050 r4:c06b8648
[<c025f40c>] (da8xx_usb11_phy_power_on) from [<c025ee3c>]
(phy_power_on+0x80/0xe4)
r5:c3a6c800 r4:fffffdf4
[<c025edbc>] (phy_power_on) from [<c032243c>] (ohci_da8xx_enable+0x4c/0x80)
r7:0000003b r6:c3af6000 r5:c3af6000 r4:00000000
[<c03223f0>] (ohci_da8xx_enable) from [<c03224f0>]
(ohci_da8xx_reset+0x1c/0xd8)
r5:00000000 r4:c3af6000
[<c03224d4>] (ohci_da8xx_reset) from [<c0309118>] (usb_add_hcd+0x314/0x834)
r7:0000003b r6:ffffffed r5:00000000 r4:c3af6000
[<c0308e04>] (usb_add_hcd) from [<c032200c>] (ohci_da8xx_probe+0x14c/0x21c)
r9:c06a5ed4 r8:00000000 r7:c38bd010 r6:c38bd000 r5:c3af6000 r4:c38af900
[<c0321ec0>] (ohci_da8xx_probe) from [<c02bec44>]
(platform_drv_probe+0x40/0x8c)
r7:c06e610c r6:c06e610c r5:c38bd010 r4:c0321ec0
[<c02bec04>] (platform_drv_probe) from [<c02bd438>]
(driver_probe_device+0x138/0x2a4)
r7:c06e610c r6:c0e9db10 r5:00000000 r4:c38bd010
[<c02bd300>] (driver_probe_device) from [<c02bd634>]
(__driver_attach+0x90/0xb4)
r9:c06a5ed4 r8:c06f66e0 r7:c06e1250 r6:c06e610c r5:c38bd044 r4:c38bd010
[<c02bd5a4>] (__driver_attach) from [<c02bba5c>]
(bus_for_each_dev+0x74/0x98)
r7:c06e1250 r6:c02bd5a4 r5:c06e610c r4:00000000
[<c02bb9e8>] (bus_for_each_dev) from [<c02bcf2c>] (driver_attach+0x20/0x28)
r6:c39a2300 r5:00000000 r4:c06e610c
[<c02bcf0c>] (driver_attach) from [<c02bca80>] (bus_add_driver+0xd4/0x1f0)
[<c02bc9ac>] (bus_add_driver) from [<c02bdcec>] (driver_register+0xa4/0xe8)
r7:c0698850 r6:00000000 r5:00000000 r4:c06e610c
[<c02bdc48>] (driver_register) from [<c02bebac>]
(__platform_driver_register+0x38/0x4c)
r5:00000000 r4:c06acce4
[<c02beb74>] (__platform_driver_register) from [<c068da20>]
(ohci_da8xx_init+0x64/0x90)
[<c068d9bc>] (ohci_da8xx_init) from [<c00096c0>]
(do_one_initcall+0xb0/0x168)
r5:c068d9bc r4:ffffe000
[<c0009610>] (do_one_initcall) from [<c0676e14>]
(kernel_init_freeable+0x110/0x1cc)
r9:c06a5ed4 r8:c06f66e0 r7:c0698850 r6:000000c1 r5:c06f66e0 r4:00000007
[<c0676d04>] (kernel_init_freeable) from [<c04d37e4>]
(kernel_init+0x10/0xf8)
r9:00000000 r8:00000000 r7:00000000 r6:00000000 r5:c04d37d4 r4:00000000
[<c04d37d4>] (kernel_init) from [<c000a2ac>] (ret_from_fork+0x14/0x28)
r5:c04d37d4 r4:00000000
^ permalink raw reply related
* [PATCH v2 3/3] ARM: da850: fix da850_set_pll0rate()
From: Viresh Kumar @ 2016-12-05 3:34 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480693134-31324-4-git-send-email-bgolaszewski@baylibre.com>
Good to see you again Bartosz :)
On 02-12-16, 16:38, Bartosz Golaszewski wrote:
> This function is broken - its second argument is an index to the freq
> table, not the requested clock rate in Hz. It leads to an oops when
> called from clk_set_rate() since this argument isn't bounds checked
> either.
>
> Fix it by iterating over the array of supported frequencies and
> selecting a one that matches or returning -EINVAL for unsupported
> rates.
>
> Also: update the davinci cpufreq driver. It's the only user of this
> clock and currently it passes the cpufreq table index to
> clk_set_rate(), which is confusing. Make it pass the requested clock
> rate in Hz.
>
> Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
> ---
> arch/arm/mach-davinci/da850.c | 22 ++++++++++++++++++----
> drivers/cpufreq/davinci-cpufreq.c | 2 +-
> 2 files changed, 19 insertions(+), 5 deletions(-)
>
> diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
> index a55101c..92e3303 100644
> --- a/arch/arm/mach-davinci/da850.c
> +++ b/arch/arm/mach-davinci/da850.c
> @@ -1179,14 +1179,28 @@ static int da850_set_armrate(struct clk *clk, unsigned long index)
> return clk_set_rate(pllclk, index);
> }
>
> -static int da850_set_pll0rate(struct clk *clk, unsigned long index)
> +static int da850_set_pll0rate(struct clk *clk, unsigned long rate)
> {
> - unsigned int prediv, mult, postdiv;
> - struct da850_opp *opp;
> struct pll_data *pll = clk->pll_data;
> + struct cpufreq_frequency_table *freq;
> + unsigned int prediv, mult, postdiv;
> + struct da850_opp *opp = NULL;
> int ret;
>
> - opp = (struct da850_opp *) cpufreq_info.freq_table[index].driver_data;
> + for (freq = da850_freq_table;
> + freq->frequency != CPUFREQ_TABLE_END; freq++) {
> + /* requested_rate is in Hz, freq->frequency is in KHz */
> + unsigned long freq_rate = freq->frequency * 1000;
> +
> + if (freq_rate == rate) {
> + opp = (struct da850_opp *)freq->driver_data;
> + break;
> + }
> + }
> +
> + if (opp == NULL)
> + return -EINVAL;
> +
> prediv = opp->prediv;
> mult = opp->mult;
> postdiv = opp->postdiv;
> diff --git a/drivers/cpufreq/davinci-cpufreq.c b/drivers/cpufreq/davinci-cpufreq.c
> index b95a872..d54a27c 100644
> --- a/drivers/cpufreq/davinci-cpufreq.c
> +++ b/drivers/cpufreq/davinci-cpufreq.c
> @@ -55,7 +55,7 @@ static int davinci_target(struct cpufreq_policy *policy, unsigned int idx)
> return ret;
> }
>
> - ret = clk_set_rate(armclk, idx);
> + ret = clk_set_rate(armclk, new_freq * 1000);
> if (ret)
> return ret;
I haven't checked the internal of davinci or the way rate is changed now, but
from cpufreq's perspective, fee free to add my:
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
--
viresh
^ permalink raw reply
* [PATCH 2/2] soc: zte: pm_domains: Add support for zx296718 driver
From: Jun Nie @ 2016-12-05 3:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480774291-6211-2-git-send-email-baoyou.xie@linaro.org>
2016-12-03 22:11 GMT+08:00 Baoyou Xie <baoyou.xie@linaro.org>:
> This patch introduces the power domain driver of zx296718
> which belongs to zte's 2967 family.
>
> Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org>
> ---
> drivers/soc/zte/Makefile | 3 +
> drivers/soc/zte/zx296718_pm_domains.c | 162 ++++++++++++++++++++++++++++++++++
> 2 files changed, 165 insertions(+)
> create mode 100644 drivers/soc/zte/zx296718_pm_domains.c
>
> diff --git a/drivers/soc/zte/Makefile b/drivers/soc/zte/Makefile
> index 97ac8ea..a6e7bfe 100644
> --- a/drivers/soc/zte/Makefile
> +++ b/drivers/soc/zte/Makefile
> @@ -2,3 +2,6 @@
> # zx SOC drivers
> #
> obj-$(CONFIG_ZX_PM_DOMAINS) += pm_domains.o
> +ifeq ($(CONFIG_ZX_PM_DOMAINS), y)
> + obj-y += zx296718_pm_domains.o
> +endif
Follow unified style for Makefile:
obj-$(CONFIG_ZX_PM_DOMAINS) += zx296718_pm_domains.o
> diff --git a/drivers/soc/zte/zx296718_pm_domains.c b/drivers/soc/zte/zx296718_pm_domains.c
> new file mode 100644
> index 0000000..fc16dfd
> --- /dev/null
> +++ b/drivers/soc/zte/zx296718_pm_domains.c
> @@ -0,0 +1,162 @@
> +/*
> + * Copyright (C) 2015 ZTE Ltd.
> + *
> + * Author: Baoyou Xie <baoyou.xie@linaro.org>
> + * License terms: GNU General Public License (GPL) version 2
> + */
> +#include "pm_domains.h"
> +
> +enum {
> + PCU_DM_VOU = 0,
> + PCU_DM_SAPPU,
> + PCU_DM_VDE,
> + PCU_DM_VCE,
> + PCU_DM_HDE,
> + PCU_DM_VIU,
> + PCU_DM_USB20,
> + PCU_DM_USB21,
> + PCU_DM_USB30,
> + PCU_DM_HSIC,
> + PCU_DM_GMAC,
> + PCU_DM_TS,
> +};
> +
> +static struct zx_pm_domain vou_domain = {
> + .dm = {
> + .name = "vou_domain",
> + .power_off = zx_normal_power_off,
> + .power_on = zx_normal_power_on,
> + },
> + .bit = PCU_DM_VOU,
> +};
> +static struct zx_pm_domain sappu_domain = {
> + .dm = {
> + .name = "sappu_domain",
> + .power_off = zx_normal_power_off,
> + .power_on = zx_normal_power_on,
> + },
> + .bit = PCU_DM_SAPPU,
> +};
> +static struct zx_pm_domain vde_domain = {
> + .dm = {
> + .name = "vde_domain",
> + .power_off = zx_normal_power_off,
> + .power_on = zx_normal_power_on,
> + },
> + .bit = PCU_DM_VDE,
> +};
> +static struct zx_pm_domain vce_domain = {
> + .dm = {
> + .name = "vce_domain",
> + .power_off = zx_normal_power_off,
> + .power_on = zx_normal_power_on,
> + },
> + .bit = PCU_DM_VCE,
> +};
> +static struct zx_pm_domain hde_domain = {
> + .dm = {
> + .name = "hde_domain",
> + .power_off = zx_normal_power_off,
> + .power_on = zx_normal_power_on,
> + },
> + .bit = PCU_DM_HDE,
> +};
> +
> +static struct zx_pm_domain viu_domain = {
> + .dm = {
> + .name = "viu_domain",
> + .power_off = zx_normal_power_off,
> + .power_on = zx_normal_power_on,
> + },
> + .bit = PCU_DM_VIU,
> +};
> +static struct zx_pm_domain usb20_domain = {
> + .dm = {
> + .name = "usb20_domain",
> + .power_off = zx_normal_power_off,
> + .power_on = zx_normal_power_on,
> + },
> + .bit = PCU_DM_USB20,
> +};
> +static struct zx_pm_domain usb21_domain = {
> + .dm = {
> + .name = "usb21_domain",
> + .power_off = zx_normal_power_off,
> + .power_on = zx_normal_power_on,
> + },
> + .bit = PCU_DM_USB21,
> +};
> +static struct zx_pm_domain usb30_domain = {
> + .dm = {
> + .name = "usb30_domain",
> + .power_off = zx_normal_power_off,
> + .power_on = zx_normal_power_on,
> + },
> + .bit = PCU_DM_USB30,
> +};
> +static struct zx_pm_domain hsic_domain = {
> + .dm = {
> + .name = "hsic_domain",
> + .power_off = zx_normal_power_off,
> + .power_on = zx_normal_power_on,
> + },
> + .bit = PCU_DM_HSIC,
> +};
> +static struct zx_pm_domain gmac_domain = {
> + .dm = {
> + .name = "gmac_domain",
> + .power_off = zx_normal_power_off,
> + .power_on = zx_normal_power_on,
> + },
> + .bit = PCU_DM_GMAC,
> +};
> +static struct zx_pm_domain ts_domain = {
> + .dm = {
> + .name = "ts_domain",
> + .power_off = zx_normal_power_off,
> + .power_on = zx_normal_power_on,
> + },
> + .bit = PCU_DM_TS,
> +};
> +struct generic_pm_domain *zx296718_pm_domains[] = {
> + //&vou_domain.dm,
Remove this line.
> + &sappu_domain.dm,
If you can add an index and add the index definition in devicetree
header file, it will be more convenient when binding power domain to
device in DT file. such as
[ZX296718_PM_VDE] = &vde_domain.dm,
> + &vde_domain.dm,
> + &vce_domain.dm,
> + &hde_domain.dm,
> + &viu_domain.dm,
> + &usb20_domain.dm,
> + &usb21_domain.dm,
> + &usb30_domain.dm,
> + &hsic_domain.dm,
> + &gmac_domain.dm,
> + &ts_domain.dm,
> + &vou_domain.dm,
> +};
> +
> +static int zx296718_pd_probe(struct platform_device *pdev)
> +{
> + return zx_pd_probe(pdev,
> + zx296718_pm_domains,
> + ARRAY_SIZE(zx296718_pm_domains));
> +}
> +
> +static const struct of_device_id zx296718_pm_domain_matches[] = {
> + { .compatible = "zte,zx296718-pcu", },
Suggest to rename probe function and of_device_id to a generic zx
name, then add compatible data so that probe function can be shared.
Probe function can find SoC specific data via comparing compatible
string and initialize device accordingly.
> + { },
> +};
> +
> +static struct platform_driver zx296718_pd_driver = {
> + .driver = {
> + .name = "zx-powerdomain",
> + .owner = THIS_MODULE,
> + .of_match_table = zx296718_pm_domain_matches,
> + },
> + .probe = zx296718_pd_probe,
> +};
> +
> +static int __init zx296718_pd_init(void)
> +{
> + return platform_driver_register(&zx296718_pd_driver);
> +}
> +subsys_initcall(zx296718_pd_init);
> --
> 2.7.4
>
^ permalink raw reply
* [PATCH] arm64: dts: zx: add pcu_domain node for zx296718
From: Shawn Guo @ 2016-12-05 3:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480766354-25168-1-git-send-email-baoyou.xie@linaro.org>
On Sat, Dec 03, 2016 at 07:59:14PM +0800, Baoyou Xie wrote:
> This patch adds the pcu_domain node, so it can be used
> by zte-soc's power domain driver.
>
> Furthermore, it adds the document of the node.
>
> Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org>
> ---
> Documentation/devicetree/bindings/arm/zte.txt | 11 +++++++++++
DT bindings doc should be a separate patch, and goes together with
driver changes using the bindings through subsystem maintainers, rather
than dts patches.
> arch/arm64/boot/dts/zte/zx296718.dtsi | 7 +++++++
> 2 files changed, 18 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/arm/zte.txt b/Documentation/devicetree/bindings/arm/zte.txt
> index 83369785..19a7e1b 100644
> --- a/Documentation/devicetree/bindings/arm/zte.txt
> +++ b/Documentation/devicetree/bindings/arm/zte.txt
> @@ -27,6 +27,9 @@ System management required properties:
> - compatible = "zte,zx296718-aon-sysctrl"
> - compatible = "zte,zx296718-sysctrl"
>
> +Low power management required properties:
> + - compatible = "zte,zx296718-pcu"
> +
> Example:
> aon_sysctrl: aon-sysctrl at 116000 {
> compatible = "zte,zx296718-aon-sysctrl", "syscon";
> @@ -37,3 +40,11 @@ sysctrl: sysctrl at 1463000 {
> compatible = "zte,zx296718-sysctrl", "syscon";
> reg = <0x1463000 0x1000>;
> };
> +
> +pcu_domain: pcu at 0x00117000 {
> + compatible = "zte,zx296718-pcu";
> + reg = <0x00117000 0x1000>;
> + #power-domain-cells = <1>;
> + status = "ok";
> +};
> +
I think we should have a separate bindings doc for PCU power domain
block in Documentation/devicetree/bindings/soc/zte.
> diff --git a/arch/arm64/boot/dts/zte/zx296718.dtsi b/arch/arm64/boot/dts/zte/zx296718.dtsi
> index b44d1d1..39e70c7 100644
> --- a/arch/arm64/boot/dts/zte/zx296718.dtsi
> +++ b/arch/arm64/boot/dts/zte/zx296718.dtsi
> @@ -351,5 +351,12 @@
> reg = <0x01480000 0x1000>;
> #clock-cells = <1>;
> };
> +
> + pcu_domain: pcu at 0x00117000 {
Please drop the 0x and leading zeros in unit-address after node name.
That said, the node name should be written like below:
pcu at 117000 {
Also, please sort the node with unit-address in order of the address.
That means that pcu node should be put after aon-sysctrl at 116000.
> + compatible = "zte,zx296718-pcu";
> + reg = <0x00117000 0x1000>;
> + #power-domain-cells = <1>;
> + status = "ok";
The property 'status' is generally used to enable devices that have
board-level pin-out or configuration in board dts. It's not really
necessary for pcu here.
Shawn
> + };
> };
> };
> --
> 2.7.4
>
^ permalink raw reply
* [PATCH 1/2] soc: zte: pm_domains: Prepare for supporting ARMv8 2967 family
From: Jun Nie @ 2016-12-05 3:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480774291-6211-1-git-send-email-baoyou.xie@linaro.org>
2016-12-03 22:11 GMT+08:00 Baoyou Xie <baoyou.xie@linaro.org>:
> The ARMv8 2967 family (296718, 296716 etc) uses different value
> for controlling the power domain on/off registers, Choose the
> value depending on the compatible.
>
> Multiple domains are prepared for the family, it's privated by
> the drivers of boards.
>
> This patch prepares the common functions.
>
> Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org>
> ---
> MAINTAINERS | 1 +
> drivers/soc/Kconfig | 1 +
> drivers/soc/Makefile | 1 +
> drivers/soc/zte/Kconfig | 13 ++++
> drivers/soc/zte/Makefile | 4 ++
> drivers/soc/zte/pm_domains.c | 138 +++++++++++++++++++++++++++++++++++++++++++
> drivers/soc/zte/pm_domains.h | 29 +++++++++
> 7 files changed, 187 insertions(+)
> create mode 100644 drivers/soc/zte/Kconfig
> create mode 100644 drivers/soc/zte/Makefile
> create mode 100644 drivers/soc/zte/pm_domains.c
> create mode 100644 drivers/soc/zte/pm_domains.h
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index ad199da..8198389 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1979,6 +1979,7 @@ L: linux-arm-kernel at lists.infradead.org (moderated for non-subscribers)
> S: Maintained
> F: arch/arm/mach-zx/
> F: drivers/clk/zte/
> +F: drivers/soc/zte/
> F: Documentation/devicetree/bindings/arm/zte.txt
> F: Documentation/devicetree/bindings/clock/zx296702-clk.txt
>
> diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
> index f31bceb..f09023f 100644
> --- a/drivers/soc/Kconfig
> +++ b/drivers/soc/Kconfig
> @@ -11,5 +11,6 @@ source "drivers/soc/tegra/Kconfig"
> source "drivers/soc/ti/Kconfig"
> source "drivers/soc/ux500/Kconfig"
> source "drivers/soc/versatile/Kconfig"
> +source "drivers/soc/zte/Kconfig"
>
> endmenu
> diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
> index 50c23d0..05eae52 100644
> --- a/drivers/soc/Makefile
> +++ b/drivers/soc/Makefile
> @@ -16,3 +16,4 @@ obj-$(CONFIG_ARCH_TEGRA) += tegra/
> obj-$(CONFIG_SOC_TI) += ti/
> obj-$(CONFIG_ARCH_U8500) += ux500/
> obj-$(CONFIG_PLAT_VERSATILE) += versatile/
> +obj-$(CONFIG_ARCH_ZX) += zte/
> diff --git a/drivers/soc/zte/Kconfig b/drivers/soc/zte/Kconfig
> new file mode 100644
> index 0000000..4953c3fa
> --- /dev/null
> +++ b/drivers/soc/zte/Kconfig
> @@ -0,0 +1,13 @@
> +#
> +# zx SoC drivers
> +#
> +menuconfig SOC_ZX
> + bool "zx SoC driver support"
Why not reuse ARCH_ZX ?
> +
> +if SOC_ZX
> +
> +config ZX_PM_DOMAINS
> + bool "zx PM domains"
> + depends on PM_GENERIC_DOMAINS
> +
> +endif
> diff --git a/drivers/soc/zte/Makefile b/drivers/soc/zte/Makefile
> new file mode 100644
> index 0000000..97ac8ea
> --- /dev/null
> +++ b/drivers/soc/zte/Makefile
> @@ -0,0 +1,4 @@
> +#
> +# zx SOC drivers
> +#
> +obj-$(CONFIG_ZX_PM_DOMAINS) += pm_domains.o
> diff --git a/drivers/soc/zte/pm_domains.c b/drivers/soc/zte/pm_domains.c
> new file mode 100644
> index 0000000..5792f21
> --- /dev/null
> +++ b/drivers/soc/zte/pm_domains.c
> @@ -0,0 +1,138 @@
> +/*
> + * Copyright (C) 2015 ZTE Ltd.
> + *
> + * Author: Baoyou Xie <baoyou.xie@linaro.org>
> + * License terms: GNU General Public License (GPL) version 2
> + */
> +#include <linux/delay.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/of.h>
> +#include "pm_domains.h"
> +
> +#define PCU_DM_CLKEN 0x18
> +#define PCU_DM_RSTEN 0x20
> +#define PCU_DM_ISOEN 0x1c
List registers with ascending sequence.
I find these registers offset is different with existing 296702
register offset. So I suggest to use offset table to resolve the
conflict so that this driver is extendable for more SoC with different
register offset if you want. You can reference
drivers/tty/serial/amba-pl011.c for register offset handling.
> +#define PCU_DM_PWREN 0x24
> +#define PCU_DM_ACK_SYNC 0x28
> +
> +static void __iomem *pcubase;
> +
> +int zx_normal_power_on(struct generic_pm_domain *domain)
> +{
> + struct zx_pm_domain *zpd = (struct zx_pm_domain *)domain;
> + unsigned long loop = 20000;
> + u32 val;
> +
> + loop = 1000;
> + do {
> + val = readl_relaxed(pcubase + PCU_DM_PWREN);
> + val |= BIT(zpd->bit);
bit polarity can also be configurable if you want support more SoCs
with different polarity setting.
> + writel_relaxed(val, pcubase + PCU_DM_PWREN);
> +
> + udelay(1);
> + val = readl_relaxed(pcubase + PCU_DM_ACK_SYNC) & BIT(zpd->bit);
> + } while (--loop && !val);
> +
> + if (!loop) {
> + pr_err("Error: %s %s fail\n", __func__, domain->name);
> + return -EIO;
> + }
> +
> + val = readl_relaxed(pcubase + PCU_DM_RSTEN);
> + val &= ~BIT(zpd->bit);
> + writel_relaxed(val | BIT(zpd->bit), pcubase + PCU_DM_RSTEN);
> + udelay(5);
> +
> + val = readl_relaxed(pcubase + PCU_DM_ISOEN);
> + val &= ~BIT(zpd->bit);
> + writel_relaxed(val, pcubase + PCU_DM_ISOEN);
> + udelay(5);
> +
> + val = readl_relaxed(pcubase + PCU_DM_CLKEN);
> + val &= ~BIT(zpd->bit);
> + writel_relaxed(val | BIT(zpd->bit), pcubase + PCU_DM_CLKEN);
> + udelay(5);
> +
> + pr_info("normal poweron %s\n", domain->name);
> +
> + return 0;
> +}
> +
> +int zx_normal_power_off(struct generic_pm_domain *domain)
> +{
> + struct zx_pm_domain *zpd = (struct zx_pm_domain *)domain;
> + unsigned long loop = 1000;
> + u32 val;
> +
> + val = readl_relaxed(pcubase + PCU_DM_CLKEN);
> + val &= ~BIT(zpd->bit);
> + writel_relaxed(val, pcubase + PCU_DM_CLKEN);
> + udelay(5);
> +
> + val = readl_relaxed(pcubase + PCU_DM_ISOEN);
> + val &= ~BIT(zpd->bit);
> + writel_relaxed(val | BIT(zpd->bit), pcubase + PCU_DM_ISOEN);
> + udelay(5);
> +
> + val = readl_relaxed(pcubase + PCU_DM_RSTEN);
> + val &= ~BIT(zpd->bit);
> + writel_relaxed(val, pcubase + PCU_DM_RSTEN);
> + udelay(5);
> +
> + loop = 1000;
> + do {
> + val = readl_relaxed(pcubase + PCU_DM_PWREN);
> + val &= ~BIT(zpd->bit);
> + writel_relaxed(val, pcubase + PCU_DM_PWREN);
> +
> + udelay(1);
> +
> + val = readl_relaxed(pcubase + PCU_DM_ACK_SYNC) & BIT(zpd->bit);
> + } while (--loop && val);
> +
> + if (!loop) {
> + pr_err("Error: %s %s fail\n", __func__, domain->name);
> + return -EIO;
> + }
> +
> + pr_info("normal poweroff %s\n", domain->name);
> +
> + return 0;
> +}
> +
> +int
> +zx_pd_probe(struct platform_device *pdev,
> + struct generic_pm_domain **zx_pm_domains,
> + int domain_num)
> +{
> + struct genpd_onecell_data *genpd_data;
> + struct resource *res;
> + int i;
> +
> + genpd_data = devm_kzalloc(&pdev->dev, sizeof(*genpd_data), GFP_KERNEL);
> + if (!genpd_data)
> + return -ENOMEM;
> +
> + genpd_data->domains = zx_pm_domains;
> + genpd_data->num_domains = domain_num;
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + if (!res) {
> + dev_err(&pdev->dev, "no memory resource defined\n");
> + return -ENODEV;
> + }
> +
> + pcubase = devm_ioremap_resource(&pdev->dev, res);
> + if (!pcubase) {
> + dev_err(&pdev->dev, "ioremap fail.\n");
> + return -EIO;
> + }
> +
> + for (i = 0; i < domain_num; ++i)
> + pm_genpd_init(zx_pm_domains[i], NULL, false);
> +
> + of_genpd_add_provider_onecell(pdev->dev.of_node, genpd_data);
> + dev_info(&pdev->dev, "powerdomain init ok\n");
> + return 0;
> +}
> diff --git a/drivers/soc/zte/pm_domains.h b/drivers/soc/zte/pm_domains.h
> new file mode 100644
> index 0000000..613e0be
> --- /dev/null
> +++ b/drivers/soc/zte/pm_domains.h
> @@ -0,0 +1,29 @@
> +/*
> + * Copyright (c) 2015 ZTE Co., Ltd.
> + * http://www.zte.com.cn
> + *
> + * Header for ZTE's Power Domain Driver support
> + *
> + * 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.
> + */
> +
> +#ifndef __ZTE_PM_DOMAIN_H
> +#define __ZTE_PM_DOMAIN_H
> +
> +#include <linux/platform_device.h>
> +#include <linux/pm_domain.h>
> +
> +struct zx_pm_domain {
> + struct generic_pm_domain dm;
> + unsigned int bit;
> +};
> +
> +extern int zx_normal_power_on(struct generic_pm_domain *domain);
> +extern int zx_normal_power_off(struct generic_pm_domain *domain);
> +extern int
> +zx_pd_probe(struct platform_device *pdev,
> + struct generic_pm_domain **zx_pm_domains,
> + int domain_num);
> +#endif /* __ZTE_PM_DOMAIN_H */
> --
> 2.7.4
>
^ permalink raw reply
* [PATCH V2 fix 5/6] mm: hugetlb: add a new function to allocate a new gigantic page
From: Huang Shijie @ 2016-12-05 3:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161202140325.GM6830@dhcp22.suse.cz>
On Fri, Dec 02, 2016 at 03:03:30PM +0100, Michal Hocko wrote:
> On Wed 16-11-16 14:55:04, Huang Shijie wrote:
> > There are three ways we can allocate a new gigantic page:
> >
> > 1. When the NUMA is not enabled, use alloc_gigantic_page() to get
> > the gigantic page.
> >
> > 2. The NUMA is enabled, but the vma is NULL.
> > There is no memory policy we can refer to.
> > So create a @nodes_allowed, initialize it with init_nodemask_of_mempolicy()
> > or init_nodemask_of_node(). Then use alloc_fresh_gigantic_page() to get
> > the gigantic page.
> >
> > 3. The NUMA is enabled, and the vma is valid.
> > We can follow the memory policy of the @vma.
> >
> > Get @nodes_allowed by huge_nodemask(), and use alloc_fresh_gigantic_page()
> > to get the gigantic page.
>
> Again __hugetlb_alloc_gigantic_page is not used and it is hard to deduce
> its usage from this commit. The above shouldn't be really much different from
Okay, I will merge it into the later patch.
> what we do in alloc_pages_vma so please make sure to check it before
> coming up with something hugetlb specific.
No problem. Thanks for the hint.
Thanks
Huang Shijie
^ permalink raw reply
* [PATCH V2 fix 4/6] mm: mempolicy: intruduce a helper huge_nodemask()
From: Huang Shijie @ 2016-12-05 3:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161202135845.GL6830@dhcp22.suse.cz>
On Fri, Dec 02, 2016 at 02:58:46PM +0100, Michal Hocko wrote:
> On Wed 16-11-16 14:53:02, Huang Shijie wrote:
> > This patch intruduces a new helper huge_nodemask(),
> > we can use it to get the node mask.
> >
> > This idea of the function is from the init_nodemask_of_mempolicy():
> > Return true if we can succeed in extracting the node_mask
> > for 'bind' or 'interleave' policy or initializing the node_mask
> > to contain the single node for 'preferred' or 'local' policy.
>
> It is absolutely unclear how this is going to be used from this patch.
> Please make sure to also use a newly added function in the same patch.
>
Okay, I will merge this patch into the later patch.
Thanks
Huang Shijie
^ permalink raw reply
* [PATCH v2 3/6] mm: hugetlb: change the return type for alloc_fresh_gigantic_page
From: Huang Shijie @ 2016-12-05 3:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161202135643.GK6830@dhcp22.suse.cz>
On Fri, Dec 02, 2016 at 02:56:43PM +0100, Michal Hocko wrote:
> On Mon 14-11-16 15:07:36, Huang Shijie wrote:
> > This patch changes the return type to "struct page*" for
> > alloc_fresh_gigantic_page().
>
> OK, this makes somme sense. Other hugetlb allocation function (and page
> allocator in general) return struct page as well. Besides that int would
> make sense if we wanted to convey an error code but 0 vs. 1 just doesn't
> make any sense.
>
> But if you are changing that then alloc_fresh_huge_page should be
> changed as well.
Okay.
>
> > This patch makes preparation for later patch.
> >
> > Signed-off-by: Huang Shijie <shijie.huang@arm.com>
>
> Acked-by: Michal Hocko <mhocko@suse.com>
Thanks a lot.
Thanks
Huang Shijie
^ permalink raw reply
* [PATCH v2 2/6] mm: hugetlb: add a new parameter for some functions
From: Huang Shijie @ 2016-12-05 3:05 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161202135229.GJ6830@dhcp22.suse.cz>
On Fri, Dec 02, 2016 at 02:52:30PM +0100, Michal Hocko wrote:
> On Mon 14-11-16 15:07:35, Huang Shijie wrote:
> > This patch adds a new parameter, the "no_init", for these functions:
> > alloc_fresh_gigantic_page_node()
> > alloc_fresh_gigantic_page()
> >
> > The prep_new_huge_page() does some initialization for the new page.
> > But sometime, we do not need it to do so, such as in the surplus case
> > in later patch.
> >
> > With this parameter, the prep_new_huge_page() can be called by needed:
> > If the "no_init" is false, calls the prep_new_huge_page() in
> > the alloc_fresh_gigantic_page_node();
>
> This double negative just makes my head spin. I haven't got to later
> patch to understand the motivation but if anything bool do_prep would
> be much more clear. In general doing these "init if a parameter is
Okay, I will use the "do_prep" for the new parameter.
thanks for the code review.
Huang Shijie
^ permalink raw reply
* [PATCH v2] arm64: dts: zx: support cpu-freq for zx296718
From: Shawn Guo @ 2016-12-05 2:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480657956-8140-1-git-send-email-baoyou.xie@linaro.org>
On Fri, Dec 02, 2016 at 01:52:36PM +0800, Baoyou Xie wrote:
> This patch adds the CPU clock phandle in CPU's node
> and uses operating-points-v2 to register operating points.
>
> So it can be used by cpufreq-dt driver.
>
> Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org>
Applied, thanks.
^ permalink raw reply
* [PATCH v2] arm64: dts: zx: support cpu-freq for zx296718
From: Jun Nie @ 2016-12-05 2:35 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161202060000.GE7682@vireshk-i7>
2016-12-02 14:00 GMT+08:00 Viresh Kumar <viresh.kumar@linaro.org>:
> On 02-12-16, 13:58, Baoyou Xie wrote:
>> + Viresh, the author of the bindings.
>>
>> On 2 December 2016 at 13:52, Baoyou Xie <baoyou.xie@linaro.org> wrote:
>>
>> > This patch adds the CPU clock phandle in CPU's node
>> > and uses operating-points-v2 to register operating points.
>> >
>> > So it can be used by cpufreq-dt driver.
>> >
>> > Signed-off-by: Baoyou Xie <baoyou.xie@linaro.org>
>> > ---
>> > arch/arm64/boot/dts/zte/zx296718.dtsi | 39 ++++++++++++++++++++++++++++++
>> > +++++
>> > 1 file changed, 39 insertions(+)
Reviewed-by: Jun Nie <jun.nie@linaro.org>
>
> Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
>
> --
> viresh
^ permalink raw reply
* [PATCH v3 -next 1/2] ARM: sunxi: add support for H2+ SoC
From: Alexey Kardashevskiy @ 2016-12-05 2:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161202150513.34691-1-icenowy@aosc.xyz>
On 03/12/16 02:05, Icenowy Zheng wrote:
> Allwinner H2+ is a quad-core Cortex-A7 SoC.
>
> It is very like H3, that they share the same SoC ID (0x1680), and H3
> memory maps as well as drivers works well on the SoC.
What git tree is this made against of? Thanks.
>
> Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
> ---
> Changes since v2:
> - Changed compatible from allwinner,sun8i-h2plus to allwinner,sun8i-h2-plus.
> Documentation/arm/sunxi/README | 4 ++++
> Documentation/devicetree/bindings/arm/sunxi.txt | 1 +
> arch/arm/mach-sunxi/sunxi.c | 1 +
> 3 files changed, 6 insertions(+)
>
> diff --git a/Documentation/arm/sunxi/README b/Documentation/arm/sunxi/README
> index cd02433..1fe4d99c 100644
> --- a/Documentation/arm/sunxi/README
> +++ b/Documentation/arm/sunxi/README
> @@ -63,6 +63,10 @@ SunXi family
> + User Manual
> http://dl.linux-sunxi.org/A33/A33%20user%20manual%20release%201.1.pdf
>
> + - Allwinner H2+ (sun8i)
> + + No document available now, but is known to be working properly with
> + H3 drivers and memory map.
> +
> - Allwinner H3 (sun8i)
> + Datasheet
> http://dl.linux-sunxi.org/H3/Allwinner_H3_Datasheet_V1.0.pdf
> diff --git a/Documentation/devicetree/bindings/arm/sunxi.txt b/Documentation/devicetree/bindings/arm/sunxi.txt
> index 4d6467c..59b143f 100644
> --- a/Documentation/devicetree/bindings/arm/sunxi.txt
> +++ b/Documentation/devicetree/bindings/arm/sunxi.txt
> @@ -13,6 +13,7 @@ using one of the following compatible strings:
> allwinner,sun8i-a33
> allwinner,sun8i-a83t
> allwinner,sun8i-h3
> + allwinner,sun8i-h2-plus
> allwinner,sun9i-a80
> allwinner,sun50i-a64
> nextthing,gr8
> diff --git a/arch/arm/mach-sunxi/sunxi.c b/arch/arm/mach-sunxi/sunxi.c
> index 2e2bde2..320d2af 100644
> --- a/arch/arm/mach-sunxi/sunxi.c
> +++ b/arch/arm/mach-sunxi/sunxi.c
> @@ -63,6 +63,7 @@ static const char * const sun8i_board_dt_compat[] = {
> "allwinner,sun8i-a23",
> "allwinner,sun8i-a33",
> "allwinner,sun8i-a83t",
> + "allwinner,sun8i-h2-plus",
> "allwinner,sun8i-h3",
> NULL,
> };
>
--
Alexey
^ permalink raw reply
* [PATCH v2 1/2] arm64: dts: zx: Fix gic GICR property
From: Shawn Guo @ 2016-12-05 2:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <3937871.l5gZt4hBke@wuerfel>
Hi Arnd,
On Fri, Dec 02, 2016 at 09:28:58PM +0100, Arnd Bergmann wrote:
> Given that there is any concern about the patch now, and the merge
> window is almost open, I'm moving both patches to the
> next/fixes-non-critical branch and will merge it for v4.10 instead
> of sending it for v4.9.
>
> If you end up deciding that the patch is wrong, please follow up
> with a fix on top. Once the situation is resolved and the patch
> merged upstream, feel free to ask stable at vger.kernel.org for a
> backport to stable kernels to get it into v4.9.x.
The patch is correct, though it can be cleaned up a bit further per
Marc's suggestion. Since we now have 4.9-rc8, I'm wondering if we can
still get this into 4.9 to save the stable kernel backport.
I sent you a cleanup patch on top of this one yesterday. If you like,
I can quickly resend the patch with the cleanup squashed.
Thanks,
Shawn
^ permalink raw reply
* [PATCH 1/3] arm: hisi: add ARCH_MULTI_V5 support
From: Jiancheng Xue @ 2016-12-05 2:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <5893354.6MrIxqzRoI@wuerfel>
Hi Arnd,
On 2016/10/17 21:48, Arnd Bergmann wrote:
> On Monday, October 17, 2016 8:07:03 PM CEST Pan Wen wrote:
>> Add support for some HiSilicon SoCs which depend on ARCH_MULTI_V5.
>>
>> Signed-off-by: Pan Wen <wenpan@hisilicon.com>
>>
>
> Looks ok. I've added Marty Plummer to Cc, he was recently proposing
> patches for Hi3520, which I think is closely related to this one.
> Please try to work together so the patches don't conflict. It should
> be fairly straightforward since you are basically doing the same
> change here.
>
Marty hasn't give any replies about this thread until now. I reviewed
the patch for Hi3520. And I think this patch won't conflict with Hi3520.
Could you help us to ack this patch?
Thanks,
Jiancheng
^ permalink raw reply
* [PATCH] ARM: dts: imx7d: fix LCDIF clock assignment
From: Shawn Guo @ 2016-12-05 2:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <7e4829f484f6c4425fc9d01bea1a094f@agner.ch>
Hi Arnd, Olof,
On Sun, Dec 04, 2016 at 05:26:58PM -0800, Stefan Agner wrote:
> Hi Shawn
>
> On 2016-11-23 15:02, Fabio Estevam wrote:
> > On Tue, Nov 22, 2016 at 10:42 PM, Stefan Agner <stefan@agner.ch> wrote:
> >> The eLCDIF IP of the i.MX 7 SoC knows multiple clocks and lists them
> >> separately:
> >>
> >> Clock Clock Root Description
> >> apb_clk MAIN_AXI_CLK_ROOT AXI clock
> >> pix_clk LCDIF_PIXEL_CLK_ROOT Pixel clock
> >> ipg_clk_s MAIN_AXI_CLK_ROOT Peripheral access clock
> >>
> >> All of them are switched by a single gate, which is part of the
> >> IMX7D_LCDIF_PIXEL_ROOT_CLK clock. Hence using that clock also for
> >> the AXI bus clock (clock-name "axi") makes sure the gate gets
> >> enabled when accessing registers.
> >>
> >> There seem to be no separate AXI display clock, and the clock is
> >> optional. Hence remove the dummy clock.
> >>
> >> This fixes kernel freezes when starting the X-Server (which
> >> disables/re-enables the display controller).
> >>
> >> Signed-off-by: Stefan Agner <stefan@agner.ch>
> >
> > Reviewed-by: Fabio Estevam <fabio.estevam@nxp.com>
>
> Since this fixes a kernel freeze, is there a chance to get this still in
> 4.9?
Since we get one more week to the final 4.9, is it possible for you to
send this fix for 4.9 inclusion? Thanks.
For the patch,
Acked-by: Shawn Guo <shawnguo@kernel.org>
Shawn
^ permalink raw reply
* [PATCH 2/2] ARM: dts: sun8i: Specify memblock for Nano Pi Neo
From: Milo Kim @ 2016-12-05 2:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161205020032.26586-1-woogyom.kim@gmail.com>
The board has DDR3 256MB. This patch helps scanning the memory and
adding memblock through the DT.
Signed-off-by: Milo Kim <woogyom.kim@gmail.com>
---
arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts b/arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts
index 8d2cc6e..433f55d 100644
--- a/arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts
+++ b/arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts
@@ -45,4 +45,9 @@
/ {
model = "FriendlyARM NanoPi NEO";
compatible = "friendlyarm,nanopi-neo", "allwinner,sun8i-h3";
+
+ memory at 40000000 {
+ device_type = "memory";
+ reg = <0x40000000 0x10000000>;
+ };
};
--
2.9.3
^ permalink raw reply related
* [PATCH 1/2] ARM: dts: sun8i: Specify memblock for Nano Pi M1
From: Milo Kim @ 2016-12-05 2:00 UTC (permalink / raw)
To: linux-arm-kernel
The board has DDR3 512MB. This patch helps scanning the memory and
adding memblock through the DT.
Signed-off-by: Milo Kim <woogyom.kim@gmail.com>
---
arch/arm/boot/dts/sun8i-h3-nanopi-m1.dts | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/arm/boot/dts/sun8i-h3-nanopi-m1.dts b/arch/arm/boot/dts/sun8i-h3-nanopi-m1.dts
index ec63d10..be3668f 100644
--- a/arch/arm/boot/dts/sun8i-h3-nanopi-m1.dts
+++ b/arch/arm/boot/dts/sun8i-h3-nanopi-m1.dts
@@ -45,6 +45,11 @@
/ {
model = "FriendlyArm NanoPi M1";
compatible = "friendlyarm,nanopi-m1", "allwinner,sun8i-h3";
+
+ memory at 40000000 {
+ device_type = "memory";
+ reg = <0x40000000 0x20000000>;
+ };
};
&ehci1 {
--
2.9.3
^ permalink raw reply related
* [v2, PATCH] pinctrl: mt8173: set GPIO16 to usb iddig mode
From: Chunfeng Yun @ 2016-12-05 1:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1480901933-6971-1-git-send-email-chunfeng.yun@mediatek.com>
Hi,
On Mon, 2016-12-05 at 09:38 +0800, Chunfeng Yun wrote:
> the default mode of GPIO16 pin is gpio, when set EINT16 to
> IRQ_TYPE_LEVEL_HIGH, no interrupt is triggered, it can be
> fixed when set its default mode as usb iddig.
>
> Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> Acked-by: Hongzhou Yang <hongzhou.yang@mediatek.com>
Please ignore the v2 patch, just add Acked-by, sorry
> ---
> drivers/pinctrl/mediatek/pinctrl-mtk-mt8173.h | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-mt8173.h b/drivers/pinctrl/mediatek/pinctrl-mtk-mt8173.h
> index 13e5b68..9b018fd 100644
> --- a/drivers/pinctrl/mediatek/pinctrl-mtk-mt8173.h
> +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-mt8173.h
> @@ -201,7 +201,7 @@
> MTK_PIN(
> PINCTRL_PIN(16, "IDDIG"),
> NULL, "mt8173",
> - MTK_EINT_FUNCTION(0, 16),
> + MTK_EINT_FUNCTION(1, 16),
> MTK_FUNCTION(0, "GPIO16"),
> MTK_FUNCTION(1, "IDDIG"),
> MTK_FUNCTION(2, "CMFLASH"),
^ permalink raw reply
* [PATCH] Input: lpc32xx-keys - fix invalid error handling of a requested irq
From: Vladimir Zapolskiy @ 2016-12-05 1:47 UTC (permalink / raw)
To: linux-arm-kernel
Semantics of NR_IRQS is different on machines with SPARSE_IRQ option
disabled or enabled, in the latter case IRQs are allocated starting
at least from the value specified by NR_IRQS and going upwards, so
the check of (irq >= NR_IRQ) to decide about an error code returned by
platform_get_irq() is completely invalid, don't attempt to overrule
irq subsystem in the driver.
The change fixes lpc32xx_keys driver initialization on boot:
lpc32xx_keys 40050000.key: failed to get platform irq
lpc32xx_keys: probe of 40050000.key failed with error -22
Signed-off-by: Vladimir Zapolskiy <vz@mleia.com>
---
drivers/input/keyboard/lpc32xx-keys.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/input/keyboard/lpc32xx-keys.c b/drivers/input/keyboard/lpc32xx-keys.c
index 265d641..632523d 100644
--- a/drivers/input/keyboard/lpc32xx-keys.c
+++ b/drivers/input/keyboard/lpc32xx-keys.c
@@ -182,7 +182,7 @@ static int lpc32xx_kscan_probe(struct platform_device *pdev)
}
irq = platform_get_irq(pdev, 0);
- if (irq < 0 || irq >= NR_IRQS) {
+ if (irq < 0) {
dev_err(&pdev->dev, "failed to get platform irq\n");
return -EINVAL;
}
--
2.10.2
^ permalink raw reply related
* [PATCH] mtd: nand: lpc32xx: fix invalid error handling of a requested irq
From: Vladimir Zapolskiy @ 2016-12-05 1:47 UTC (permalink / raw)
To: linux-arm-kernel
Semantics of NR_IRQS is different on machines with SPARSE_IRQ option
disabled or enabled, in the latter case IRQs are allocated starting
at least from the value specified by NR_IRQS and going upwards, so
the check of (irq >= NR_IRQ) to decide about an error code returned by
platform_get_irq() is completely invalid, don't attempt to overrule
irq subsystem in the driver.
The change fixes LPC32xx NAND MLC driver initialization on boot.
Signed-off-by: Vladimir Zapolskiy <vz@mleia.com>
---
drivers/mtd/nand/lpc32xx_mlc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/mtd/nand/lpc32xx_mlc.c b/drivers/mtd/nand/lpc32xx_mlc.c
index 8523881..bc6e49a 100644
--- a/drivers/mtd/nand/lpc32xx_mlc.c
+++ b/drivers/mtd/nand/lpc32xx_mlc.c
@@ -776,7 +776,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
init_completion(&host->comp_controller);
host->irq = platform_get_irq(pdev, 0);
- if ((host->irq < 0) || (host->irq >= NR_IRQS)) {
+ if (host->irq < 0) {
dev_err(&pdev->dev, "failed to get platform irq\n");
res = -EINVAL;
goto err_exit3;
--
2.10.2
^ permalink raw reply related
* [PATCH 3/3] pwm: lpc32xx: remove handling of PWM channels
From: Vladimir Zapolskiy @ 2016-12-05 1:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161205014237.1689-1-vz@mleia.com>
Because LPC32xx PWM controllers have single output which is registered as
the only PWM device/channel per controller, it is known in advance that
pwm->hwpwm value is always 0. On basis of this fact simplify the code
by removing operations with pwm->hwpwm, there is no controls which require
channel number as input.
Signed-off-by: Vladimir Zapolskiy <vz@mleia.com>
---
drivers/pwm/pwm-lpc32xx.c | 20 +++++++++-----------
1 file changed, 9 insertions(+), 11 deletions(-)
diff --git a/drivers/pwm/pwm-lpc32xx.c b/drivers/pwm/pwm-lpc32xx.c
index ce84181..786c887 100644
--- a/drivers/pwm/pwm-lpc32xx.c
+++ b/drivers/pwm/pwm-lpc32xx.c
@@ -55,10 +55,10 @@ static int lpc32xx_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
if (duty_cycles > 255)
duty_cycles = 255;
- val = readl(lpc32xx->base + (pwm->hwpwm << 2));
+ val = readl(lpc32xx->base);
val &= ~0xFFFF;
val |= (period_cycles << 8) | duty_cycles;
- writel(val, lpc32xx->base + (pwm->hwpwm << 2));
+ writel(val, lpc32xx->base);
return 0;
}
@@ -73,9 +73,9 @@ static int lpc32xx_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
if (ret)
return ret;
- val = readl(lpc32xx->base + (pwm->hwpwm << 2));
+ val = readl(lpc32xx->base);
val |= PWM_ENABLE;
- writel(val, lpc32xx->base + (pwm->hwpwm << 2));
+ writel(val, lpc32xx->base);
return 0;
}
@@ -85,9 +85,9 @@ static void lpc32xx_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
struct lpc32xx_pwm_chip *lpc32xx = to_lpc32xx_pwm_chip(chip);
u32 val;
- val = readl(lpc32xx->base + (pwm->hwpwm << 2));
+ val = readl(lpc32xx->base);
val &= ~PWM_ENABLE;
- writel(val, lpc32xx->base + (pwm->hwpwm << 2));
+ writel(val, lpc32xx->base);
clk_disable_unprepare(lpc32xx->clk);
}
@@ -147,9 +147,9 @@ static int lpc32xx_pwm_probe(struct platform_device *pdev)
}
/* When PWM is disable, configure the output to the default value */
- val = readl(lpc32xx->base + (lpc32xx->chip.pwms[0].hwpwm << 2));
+ val = readl(lpc32xx->base);
val &= ~PWM_PIN_LEVEL;
- writel(val, lpc32xx->base + (lpc32xx->chip.pwms[0].hwpwm << 2));
+ writel(val, lpc32xx->base);
platform_set_drvdata(pdev, lpc32xx);
@@ -159,10 +159,8 @@ static int lpc32xx_pwm_probe(struct platform_device *pdev)
static int lpc32xx_pwm_remove(struct platform_device *pdev)
{
struct lpc32xx_pwm_chip *lpc32xx = platform_get_drvdata(pdev);
- unsigned int i;
- for (i = 0; i < lpc32xx->chip.npwm; i++)
- pwm_disable(&lpc32xx->chip.pwms[i]);
+ pwm_disable(&lpc32xx->chip.pwms[0]);
return pwmchip_remove(&lpc32xx->chip);
}
--
2.10.2
^ permalink raw reply related
* [PATCH 2/3] pwm: lpc32xx: switch driver to one phandle argument for PWM consumers
From: Vladimir Zapolskiy @ 2016-12-05 1:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161205014237.1689-1-vz@mleia.com>
NXP LPC32xx SoCs have two simple independent PWM controllers with a single
output each, in this case there is no need to specify PWM channel argument
on client side, one cell for setting PWM output frequency is sufficient.
The change adds private of_xlate() handling of a single cell value given
with a PWM phandle on client side, the handling is taken from the PXA PWM
driver.
Signed-off-by: Vladimir Zapolskiy <vz@mleia.com>
---
drivers/pwm/pwm-lpc32xx.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/drivers/pwm/pwm-lpc32xx.c b/drivers/pwm/pwm-lpc32xx.c
index a9b3cff..ce84181 100644
--- a/drivers/pwm/pwm-lpc32xx.c
+++ b/drivers/pwm/pwm-lpc32xx.c
@@ -92,6 +92,20 @@ static void lpc32xx_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
clk_disable_unprepare(lpc32xx->clk);
}
+static struct pwm_device *lpc32xx_pwm_of_xlate(struct pwm_chip *pc,
+ const struct of_phandle_args *args)
+{
+ struct pwm_device *pwm;
+
+ pwm = pwm_request_from_chip(pc, 0, NULL);
+ if (IS_ERR(pwm))
+ return pwm;
+
+ pwm->args.period = args->args[0];
+
+ return pwm;
+}
+
static const struct pwm_ops lpc32xx_pwm_ops = {
.config = lpc32xx_pwm_config,
.enable = lpc32xx_pwm_enable,
@@ -123,6 +137,8 @@ static int lpc32xx_pwm_probe(struct platform_device *pdev)
lpc32xx->chip.ops = &lpc32xx_pwm_ops;
lpc32xx->chip.npwm = 1;
lpc32xx->chip.base = -1;
+ lpc32xx->chip.of_xlate = lpc32xx_pwm_of_xlate;
+ lpc32xx->chip.of_pwm_n_cells = 1;
ret = pwmchip_add(&lpc32xx->chip);
if (ret < 0) {
--
2.10.2
^ permalink raw reply related
* [PATCH 1/3] dt: pwm: lpc32xx: add description of clocks and #pwm-cells properties
From: Vladimir Zapolskiy @ 2016-12-05 1:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161205014237.1689-1-vz@mleia.com>
NXP LPC32xx SoCs have two simple independent PWM controllers with a single
output each, in this case there is no need to specify PWM channel argument
on client side, one cell for setting PWM output frequency is sufficient.
Another added to the description property 'clocks' has a standard meaning
of a controller supply clock, in the LPC32xx User's Manual the clock is
denoted as PWM1_CLK or PWM2_CLK clock.
Signed-off-by: Vladimir Zapolskiy <vz@mleia.com>
---
Documentation/devicetree/bindings/pwm/lpc32xx-pwm.txt | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/Documentation/devicetree/bindings/pwm/lpc32xx-pwm.txt b/Documentation/devicetree/bindings/pwm/lpc32xx-pwm.txt
index 74b5bc5..523d796 100644
--- a/Documentation/devicetree/bindings/pwm/lpc32xx-pwm.txt
+++ b/Documentation/devicetree/bindings/pwm/lpc32xx-pwm.txt
@@ -3,15 +3,22 @@ LPC32XX PWM controller
Required properties:
- compatible: should be "nxp,lpc3220-pwm"
- reg: physical base address and length of the controller's registers
+- clocks: clock phandle and clock specifier pair
+- #pwm-cells: should be 1, the cell is used to specify the period in
+ nanoseconds.
Examples:
pwm at 4005c000 {
compatible = "nxp,lpc3220-pwm";
reg = <0x4005c000 0x4>;
+ clocks = <&clk LPC32XX_CLK_PWM1>;
+ #pwm-cells = <1>;
};
pwm at 4005c004 {
compatible = "nxp,lpc3220-pwm";
reg = <0x4005c004 0x4>;
+ clocks = <&clk LPC32XX_CLK_PWM2>;
+ #pwm-cells = <1>;
};
--
2.10.2
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox