* [PATCH v2 1/1] clk: imx53: Add clocks configuration
From: Fabien Lahoudere @ 2016-09-19 10:30 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160918002451.GE15478@tiger>
From: Kalle Kankare <kalle.kankare@vincit.fi>
Add clocks configuration for CSI, FIRI and IEEE1588.
Signed-off-by: Fabien Lahoudere <fabien.lahoudere@collabora.co.uk>
---
drivers/clk/imx/clk-imx51-imx53.c | 20 ++++++++++++++++++++
include/dt-bindings/clock/imx5-clock.h | 15 ++++++++++++++-
2 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/drivers/clk/imx/clk-imx51-imx53.c b/drivers/clk/imx/clk-imx51-imx53.c
index 29d4c44..1e3c9ea 100644
--- a/drivers/clk/imx/clk-imx51-imx53.c
+++ b/drivers/clk/imx/clk-imx51-imx53.c
@@ -126,6 +126,7 @@ static const char *spdif0_com_sel[] = { "spdif0_podf", "ssi1_root_gate", };
static const char *mx51_spdif1_com_sel[] = { "spdif1_podf", "ssi2_root_gate", };
static const char *step_sels[] = { "lp_apm", };
static const char *cpu_podf_sels[] = { "pll1_sw", "step_sel" };
+static const char *ieee1588_sels[] = { "pll3_sw", "pll4_sw", "dummy" /* usbphy2_clk */, "dummy" /* fec_phy_clk */ };
static struct clk *clk[IMX5_CLK_END];
static struct clk_onecell_data clk_data;
@@ -543,6 +544,25 @@ static void __init mx53_clocks_init(struct device_node *np)
clk[IMX5_CLK_I2C3_GATE] = imx_clk_gate2("i2c3_gate", "per_root", MXC_CCM_CCGR1, 22);
clk[IMX5_CLK_SATA_GATE] = imx_clk_gate2("sata_gate", "ipg", MXC_CCM_CCGR4, 2);
+ clk[IMX5_CLK_FIRI_SEL] = imx_clk_mux("firi_sel", MXC_CCM_CSCMR2, 12, 2,
+ standard_pll_sel, ARRAY_SIZE(standard_pll_sel));
+ clk[IMX5_CLK_FIRI_PRED] = imx_clk_divider("firi_pred", "firi_sel", MXC_CCM_CSCDR3, 6, 3);
+ clk[IMX5_CLK_FIRI_PODF] = imx_clk_divider("firi_podf", "firi_pred", MXC_CCM_CSCDR3, 0, 6);
+ clk[IMX5_CLK_FIRI_SERIAL_GATE] = imx_clk_gate2("firi_serial_gate", "firi_podf", MXC_CCM_CCGR1, 28);
+ clk[IMX5_CLK_FIRI_IPG_GATE] = imx_clk_gate2("firi_ipg_gate", "ipg", MXC_CCM_CCGR1, 26);
+
+ clk[IMX5_CLK_CSI0_MCLK1_SEL] = imx_clk_mux("csi0_mclk1_sel", MXC_CCM_CSCMR2, 22, 2,
+ standard_pll_sel, ARRAY_SIZE(standard_pll_sel));
+ clk[IMX5_CLK_CSI0_MCLK1_PRED] = imx_clk_divider("csi0_mclk1_pred", "csi0_mclk1_sel", MXC_CCM_CSCDR4, 6, 3);
+ clk[IMX5_CLK_CSI0_MCLK1_PODF] = imx_clk_divider("csi0_mclk1_podf", "csi0_mclk1_pred", MXC_CCM_CSCDR4, 0, 6);
+ clk[IMX5_CLK_CSI0_MCLK1_GATE] = imx_clk_gate2("csi0_mclk1_serial_gate", "csi0_mclk1_podf", MXC_CCM_CCGR6, 4);
+
+ clk[IMX5_CLK_IEEE1588_SEL] = imx_clk_mux("ieee1588_sel", MXC_CCM_CSCMR2, 14, 2,
+ ieee1588_sels, ARRAY_SIZE(ieee1588_sels));
+ clk[IMX5_CLK_IEEE1588_PRED] = imx_clk_divider("ieee1588_pred", "ieee1588_sel", MXC_CCM_CSCDR2, 6, 3);
+ clk[IMX5_CLK_IEEE1588_PODF] = imx_clk_divider("ieee1588_podf", "ieee1588_pred", MXC_CCM_CSCDR2, 0, 6);
+ clk[IMX5_CLK_IEEE1588_GATE] = imx_clk_gate2("ieee1588_serial_gate", "ieee1588_podf", MXC_CCM_CCGR7, 6);
+
clk[IMX5_CLK_CKO1_SEL] = imx_clk_mux("cko1_sel", MXC_CCM_CCOSR, 0, 4,
mx53_cko1_sel, ARRAY_SIZE(mx53_cko1_sel));
clk[IMX5_CLK_CKO1_PODF] = imx_clk_divider("cko1_podf", "cko1_sel", MXC_CCM_CCOSR, 4, 3);
diff --git a/include/dt-bindings/clock/imx5-clock.h b/include/dt-bindings/clock/imx5-clock.h
index f4b7478..d382fc7 100644
--- a/include/dt-bindings/clock/imx5-clock.h
+++ b/include/dt-bindings/clock/imx5-clock.h
@@ -201,6 +201,19 @@
#define IMX5_CLK_STEP_SEL 189
#define IMX5_CLK_CPU_PODF_SEL 190
#define IMX5_CLK_ARM 191
-#define IMX5_CLK_END 192
+#define IMX5_CLK_FIRI_PRED 192
+#define IMX5_CLK_FIRI_SEL 193
+#define IMX5_CLK_FIRI_PODF 194
+#define IMX5_CLK_FIRI_SERIAL_GATE 195
+#define IMX5_CLK_FIRI_IPG_GATE 196
+#define IMX5_CLK_CSI0_MCLK1_PRED 197
+#define IMX5_CLK_CSI0_MCLK1_SEL 198
+#define IMX5_CLK_CSI0_MCLK1_PODF 199
+#define IMX5_CLK_CSI0_MCLK1_GATE 200
+#define IMX5_CLK_IEEE1588_PRED 201
+#define IMX5_CLK_IEEE1588_SEL 202
+#define IMX5_CLK_IEEE1588_PODF 203
+#define IMX5_CLK_IEEE1588_GATE 204
+#define IMX5_CLK_END 205
#endif /* __DT_BINDINGS_CLOCK_IMX5_H */
--
2.1.4
^ permalink raw reply related
* next-20160914 build: 2 failures 3 warnings (next-20160914)
From: Arnd Bergmann @ 2016-09-19 10:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160919102150.GI10189@sirena.org.uk>
On Monday, September 19, 2016 11:21:50 AM CEST Mark Brown wrote:
> On Wed, Sep 14, 2016 at 06:11:37PM +0100, Mark Brown wrote:
> > On Wed, Sep 14, 2016 at 09:18:08AM +0100, Build bot for Mark Brown wrote:
>
> > Today's -next fails to build both arm and arm64 allmodconfig due to:
>
> > > arm64-allmodconfig
> > > ERROR: "irq_set_parent" [drivers/mfd/tps65217.ko] undefined!
>
> > > arm-allmodconfig
> > > ERROR: "irq_set_parent" [drivers/mfd/tps65217.ko] undefined!
>
> > due to 262d5cc6ceb293 (mfd: tps65217: Add support for IRQs) since
> > irq_set_parent() isn't exported.
>
> This is still breaking the build, do we have any ETA on getting the
> export added?
Thomas said he'd add it if the export is needed, but so far nobody
could tell if it is, or if the correct fix is something else, so
I have not sent a patch for inclusion.
My guess is that this is indeed the correct fix, but I don't understand
at all what the function does, and Marcin Niestroj said the same thing,
he just copied the code from a driver that is always built-in.
FWIW, the original function is
static int regmap_irq_map(struct irq_domain *h, unsigned int virq,
irq_hw_number_t hw)
{
struct regmap_irq_chip_data *data = h->host_data;
irq_set_chip_data(virq, data);
irq_set_chip(virq, &data->irq_chip);
irq_set_nested_thread(virq, 1);
irq_set_parent(virq, data->irq);
irq_set_noprobe(virq);
return 0;
}
and this is the new one:
static int tps65217_irq_map(struct irq_domain *h, unsigned int virq,
irq_hw_number_t hw)
{
struct tps65217 *tps = h->host_data;
irq_set_chip_data(virq, tps);
irq_set_chip_and_handler(virq, &tps65217_irq_chip, handle_edge_irq);
irq_set_nested_thread(virq, 1);
irq_set_parent(virq, tps->irq);
irq_set_noprobe(virq);
return 0;
}
twl6030_irq_map() has another almost identical copy, and the only
other caller of irq_set_parent() is gpiochip_set_chained_irqchip(),
which is completely different.
Arnd
^ permalink raw reply
* [PATCH] ARM: dts: sun8i: Add accelerometer to polaroid-mid2407pxe03
From: Hans de Goede @ 2016-09-19 10:39 UTC (permalink / raw)
To: linux-arm-kernel
Add a dt node describing the mma7660 accelerometer on the
polaroid-mid2407pxe03 tablet.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
arch/arm/boot/dts/sun8i-a23-polaroid-mid2407pxe03.dts | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/arch/arm/boot/dts/sun8i-a23-polaroid-mid2407pxe03.dts b/arch/arm/boot/dts/sun8i-a23-polaroid-mid2407pxe03.dts
index 6662127..a86cbed 100644
--- a/arch/arm/boot/dts/sun8i-a23-polaroid-mid2407pxe03.dts
+++ b/arch/arm/boot/dts/sun8i-a23-polaroid-mid2407pxe03.dts
@@ -62,6 +62,13 @@
};
};
+&i2c1 {
+ mma7660: accelerometer at 4c {
+ reg = <0x4c>;
+ compatible = "fsl,mma7660";
+ };
+};
+
&mmc1 {
pinctrl-names = "default";
pinctrl-0 = <&mmc1_pins_a>;
--
2.9.3
^ permalink raw reply related
* [PATCH] mtd: s3c2410: add device tree support
From: Sylwester Nawrocki @ 2016-09-19 10:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1474125760-28168-1-git-send-email-sergio.prado@e-labworks.com>
On 09/17/2016 05:22 PM, Sergio Prado wrote:
> +static int s3c24xx_nand_probe_dt(struct platform_device *pdev)
> +{
> + const struct s3c24XX_nand_devtype_data *devtype_data;
> + struct s3c2410_platform_nand *pdata;
> + struct s3c2410_nand_info *info = platform_get_drvdata(pdev);
> + struct device_node *np = pdev->dev.of_node, *child;
> + const struct of_device_id *of_id;
> + struct s3c2410_nand_set *sets;
> +
> + of_id = of_match_device(s3c24xx_nand_dt_ids, &pdev->dev);
> + if (!of_id)
> + return 1;
> +
> + devtype_data = of_id->data;
You could make it a bit simpler with of_device_get_match_data().
--
Thanks,
Sylwester
^ permalink raw reply
* [RFC PATCH 2/8] thread_info: allow custom in-task thread_info
From: Mark Rutland @ 2016-09-19 10:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CALCETrUDWiDmLbMqw9sQYEzvDuSVfmT_UscxQXfmf8YYyTOC=Q@mail.gmail.com>
[Adding Yosinori Sato for h8300]
On Fri, Sep 16, 2016 at 08:11:14AM -0700, Andy Lutomirski wrote:
> > On Thu, Sep 15, 2016 at 11:37:47AM -0700, Andy Lutomirski wrote:
> > > On Thu, Sep 15, 2016 at 6:49 AM, Mark Rutland <mark.rutland@arm.com> wrote:
> > Just to check, what do you mean to happen with the flags field? Should
> > that always be in the generic thread_info? e.g.
> >
> > struct thread_info {
> > u32 flags;
> > #ifdef arch_thread_info
> > struct arch_thread_info arch_ti;
> > #endif
> > };
>
> Exactly. Possibly with a comment that using thread_struct should be
> preferred and that arch_thread_info should be used only if some header
> file requires access via current_thread_info() or task_thread_info().
Sure thing.
While looking at that, I spotted that would cause a circular include on
h8300, but that appears to be because of a larger bug anyhow. It seems
h8300 has thread_info::restart_block, and manipulates this in its signal
code, yet core code manipulates task_struct::restart_block.
I think we need something like the below (which is completely untested).
Thanks,
Mark.
---->8----
>From 4dfbdc7706bfb03a48999ff69e85e0c7361adffe Mon Sep 17 00:00:00 2001
From: Mark Rutland <mark.rutland@arm.com>
Date: Mon, 19 Sep 2016 11:33:42 +0100
Subject: [PATCH] h8300: fix syscall restarting
Back in commit f56141e3e2d9aabf ("all arches, signal: move restart_block
to struct task_struct"), all architectures and core code were changed to
use task_struct::restart_block. However, when h8300 support was
subsequently restored in v4.2, it was not updated to account for this,
and maintains thread_info::restart_block, which is not kept in sync.
This patch drops the redundant restart_block from thread_info, and moves
h8300 to the common one in task_struct, ensuring that syscall restarting
always works as expected.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Yoshinori Sato <ysato@users.sourceforge.jp>
Cc: stable at vger.kernel.org # v4.2+
---
arch/h8300/include/asm/thread_info.h | 4 ----
arch/h8300/kernel/signal.c | 2 +-
2 files changed, 1 insertion(+), 5 deletions(-)
diff --git a/arch/h8300/include/asm/thread_info.h b/arch/h8300/include/asm/thread_info.h
index b408fe6..3cef068 100644
--- a/arch/h8300/include/asm/thread_info.h
+++ b/arch/h8300/include/asm/thread_info.h
@@ -31,7 +31,6 @@ struct thread_info {
int cpu; /* cpu we're on */
int preempt_count; /* 0 => preemptable, <0 => BUG */
mm_segment_t addr_limit;
- struct restart_block restart_block;
};
/*
@@ -44,9 +43,6 @@ struct thread_info {
.cpu = 0, \
.preempt_count = INIT_PREEMPT_COUNT, \
.addr_limit = KERNEL_DS, \
- .restart_block = { \
- .fn = do_no_restart_syscall, \
- }, \
}
#define init_thread_info (init_thread_union.thread_info)
diff --git a/arch/h8300/kernel/signal.c b/arch/h8300/kernel/signal.c
index ad1f81f..7138303 100644
--- a/arch/h8300/kernel/signal.c
+++ b/arch/h8300/kernel/signal.c
@@ -79,7 +79,7 @@ restore_sigcontext(struct sigcontext *usc, int *pd0)
unsigned int er0;
/* Always make any pending restarted system calls return -EINTR */
- current_thread_info()->restart_block.fn = do_no_restart_syscall;
+ current->restart_block.fn = do_no_restart_syscall;
/* restore passed registers */
#define COPY(r) do { err |= get_user(regs->r, &usc->sc_##r); } while (0)
--
1.9.1
^ permalink raw reply related
* [PATCH v3 0/2] KVM: ARM: Enable vtimers with user space gic
From: Alexander Graf @ 2016-09-19 10:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160916133027.GA27036@cbox>
On 16.09.16 15:30, Christoffer Dall wrote:
> On Fri, Sep 16, 2016 at 02:31:42PM +0200, Paolo Bonzini wrote:
>>
>>
>> On 16/09/2016 14:30, Christoffer Dall wrote:
>>>>>> This patch set allows user space to receive vtimer events as well as mask
>>>>>> them, so that we can handle all vtimer related interrupt injection from user
>>>>>> space, enabling us to use architected timer with user space gic emulation.
>>>>>
>>>>> I have already voiced my concerns in the past, including face to face,
>>>>> and I'm going to repeat it: I not keen at all on adding a new userspace
>>>>> interface that is going to bitrot extremely quickly.
>>>>
>>>> You don't have automated tests set up? It's not going to bitrot if you
>>>> test it, either with kvm-unit-tests or just by smoke-testing Linux.
>>>> It's _for_ the raspi, but it's not limited to it.
>>>
>>> Our automated testing situation is not great, no. Something we're
>>> looking at, but have resource problems with.
>>
>> But it's not a good reason to hold back a feature...
>>
>
> I didn't say that exactly, but choosing not to merge something we cannot
> maintain and which we're not paid to look after and where there's a
> minimal interest, is not entirely unreasonable.
>
> That being said, I'm not categorically against these patches, but I
> share Marc's view that we've already seen that non-vgic support had been
> broken for multiple versions without anyone complaining, and without
> automated testing or substantial interest in the work, the patches
> really are likely to bit-rot.
I know that it's very hard to grasp from an upstream maintainer
perspective, but keep in mind where the bulk of execution of kernel code
lies. The average life cycle of a "stable" Linux distribution's kernel
is a few years.
So far all regressions in the user space gic code have been found within
less than 1y of the respective code release. I'd say that counts for
quite a well used feature.
> But I haven't even looked at the patches in detail, I was just replying
> to the comment about testing.
Also keep in mind that without the architected timer support (and/or
without qemu patches than enable user space timers) the user space gic
support is pretty unusable to most people, so you obviously get less
reports.
Alex
^ permalink raw reply
* next-20160914 build: 2 failures 3 warnings (next-20160914)
From: Mark Brown @ 2016-09-19 10:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <2300987.vYzazfRX5F@wuerfel>
On Mon, Sep 19, 2016 at 12:31:04PM +0200, Arnd Bergmann wrote:
> My guess is that this is indeed the correct fix, but I don't understand
> at all what the function does, and Marcin Niestroj said the same thing,
> he just copied the code from a driver that is always built-in.
Yes, most of the code is copied from regmap-irq. Setting the parent is
needed for edge triggered interrupts that don't latch state when
disabled but isn't needed in the general case.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160919/5befb5da/attachment.sig>
^ permalink raw reply
* [PATCH v2 0/5] Add runtime PM support for clocks (on Exynos SoC example)
From: Marek Szyprowski @ 2016-09-19 10:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CGME20160919105545eucas1p1026e435bbaeb1f5c866a9abcdd051464@eucas1p1.samsung.com>
Dear All,
This patchset adds runtime PM support to common clock framework. This is an
attempt to implement support for clock controllers, which belongs to a power
domain. This approach works surprisingly well on Exynos 4412 and 5433 SoCs,
what allowed us to solve various freeze/crash issues related to power
management.
The main idea behind this patchset is to keep clock's controller power domain
enabled every time when at least one of its clock is enabled or access to its
registers is being made. Clock controller driver (clock provider) can
supply a struct device pointer, which is the used by clock core for tracking and
managing clock's controller runtime pm state. Each clk_prepare() operation will
first call pm_runtime_get_sync() on the supplied device, while clk_unprepare()
will do pm_runtime_put() at the end.
This runtime PM feature has been tested with Exynos4412 and Exynos5433 clocks
drivers. Both have some clocks, which belongs to respective power domains and
need special handling during power on/off procedures. Till now it wasn't handled
at all, what caused various problems.
Patches for exynos 4412 and 5433 clocks drivers change the way the clock
provider is initialized. Instead of CLK_OF_DECLARE based initialization, a
complete platform device driver infrastructure is being used. This is needed to
let driver to use runtime pm feature and integrate with generic power domains.
The side-effect of this change is a delay in clock provider registeration
during system boot, so early initialized drivers might get EPROBEDEFER error
when requesting their clocks. This is an issue for IOMMU drivers, so
this patchset will be fully functional once the deferred probe for IOMMU
will be merged.
The side-effect of this patchset is the one can finally read
/sys/kernel/debug/clk/clk_summary on all Exynos4412 boards without any freeze.
If one wants to test this patchset (on Exynos4412 Trats2 device with FIMC-IS
driver), I've provided a branch with all needed patches (fixes for Exynos,
FIMC-IS driver and IOMMU deferred probe):
https://git.linaro.org/people/marek.szyprowski/linux-srpol.git v4.8-clocks-pm-v2
Patches are based on vanilla v4.8-rc7 kernel.
Best regards
Marek Szyprowski
Samsung R&D Institute Poland
Changelog:
v2:
- Simplified clk_pm_runtime_get/put functions, removed workaround for devices
with disabled runtime pm. Such workaround is no longer needed since commit
4d23a5e84806b202d9231929c9507ef7cf7a0185 ("PM / Domains: Allow runtime PM
during system PM phases").
- Added CLK_RUNTIME_PM flag to indicate clocks, for which clock core should
call runtime pm functions. This solves problem with clocks, for which struct
device is already registered, but no runtime pm is enabled.
- Extended commit messages according to Ulf suggestions.
- Fixed some style issues pointed by Barlomiej.
v1: http://www.spinics.net/lists/arm-kernel/msg528128.html
- initial version
Marek Szyprowski (5):
clk: add support for runtime pm
clock: samsung: add support for runtime pm
clocks: exynos4x12: add runtime pm support for ISP clocks
ARM: dts: exynos: add support for ISP power domain to exynos4x12
clocks device
clocks: exynos5433: add runtime pm support
.../devicetree/bindings/clock/exynos4-clock.txt | 22 ++
arch/arm/boot/dts/exynos4x12.dtsi | 5 +
drivers/clk/clk.c | 107 +++++-
drivers/clk/samsung/clk-exynos4.c | 227 ++++++++----
drivers/clk/samsung/clk-exynos5433.c | 385 ++++++++++++++++-----
drivers/clk/samsung/clk-pll.c | 4 +-
drivers/clk/samsung/clk.c | 36 +-
drivers/clk/samsung/clk.h | 7 +
include/linux/clk-provider.h | 1 +
9 files changed, 632 insertions(+), 162 deletions(-)
--
1.9.1
^ permalink raw reply
* [PATCH v2 1/5] clk: add support for runtime pm
From: Marek Szyprowski @ 2016-09-19 10:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1474282525-30441-1-git-send-email-m.szyprowski@samsung.com>
Registers for some clocks might be located in the SOC area, which are under the
power domain. To enable access to those registers respective domain has to be
turned on. Additionally, registers for such clocks will usually loose its
contents when power domain is turned off, so additional saving and restoring of
them might be needed in the clock controller driver.
This patch adds basic infrastructure in the clocks core to allow implementing
driver for such clocks under power domains. Clock provider can supply a
struct device pointer, which is the used by clock core for tracking and managing
clock's controller runtime pm state. Each clk_prepare() operation
will first call pm_runtime_get_sync() on the supplied device, while
clk_unprepare() will do pm_runtime_put() at the end.
Additional calls to pm_runtime_get/put functions are required to ensure that any
register access (like calculating/changing clock rates and unpreparing/disabling
unused clocks on boot) will be done with clock controller in runtime resumend
state.
When one wants to register clock controller, which make use of this feature, he
has to:
1. Provide a struct device to the core when registering the provider and set
CLK_RUNTIME_PM flags for its clocks.
2. It needs to enable runtime PM for that device.
3. It needs to make sure the runtime PM status of the controller device reflects
the HW state.
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
drivers/clk/clk.c | 107 +++++++++++++++++++++++++++++++++++++++----
include/linux/clk-provider.h | 1 +
2 files changed, 98 insertions(+), 10 deletions(-)
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 820a939fb6bb..096a199b8e46 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -21,6 +21,7 @@
#include <linux/of.h>
#include <linux/device.h>
#include <linux/init.h>
+#include <linux/pm_runtime.h>
#include <linux/sched.h>
#include <linux/clkdev.h>
@@ -46,6 +47,7 @@ struct clk_core {
const struct clk_ops *ops;
struct clk_hw *hw;
struct module *owner;
+ struct device *dev;
struct clk_core *parent;
const char **parent_names;
struct clk_core **parents;
@@ -87,6 +89,26 @@ struct clk {
struct hlist_node clks_node;
};
+/*** runtime pm ***/
+static int clk_pm_runtime_get(struct clk_core *core)
+{
+ int ret = 0;
+
+ if (!core->dev)
+ return 0;
+
+ ret = pm_runtime_get_sync(core->dev);
+ return ret < 0 ? ret : 0;
+}
+
+static void clk_pm_runtime_put(struct clk_core *core)
+{
+ if (!core->dev)
+ return;
+
+ pm_runtime_put(core->dev);
+}
+
/*** locking ***/
static void clk_prepare_lock(void)
{
@@ -150,6 +172,8 @@ static void clk_enable_unlock(unsigned long flags)
static bool clk_core_is_prepared(struct clk_core *core)
{
+ bool status;
+
/*
* .is_prepared is optional for clocks that can prepare
* fall back to software usage counter if it is missing
@@ -157,11 +181,17 @@ static bool clk_core_is_prepared(struct clk_core *core)
if (!core->ops->is_prepared)
return core->prepare_count;
- return core->ops->is_prepared(core->hw);
+ clk_pm_runtime_get(core);
+ status = core->ops->is_prepared(core->hw);
+ clk_pm_runtime_put(core);
+
+ return status;
}
static bool clk_core_is_enabled(struct clk_core *core)
{
+ bool status;
+
/*
* .is_enabled is only mandatory for clocks that gate
* fall back to software usage counter if .is_enabled is missing
@@ -169,7 +199,29 @@ static bool clk_core_is_enabled(struct clk_core *core)
if (!core->ops->is_enabled)
return core->enable_count;
- return core->ops->is_enabled(core->hw);
+ /*
+ * Check if runtime pm is enabled before calling .is_enabled callback,
+ * if not assume that clock is disabled, because we might be called
+ * from atomic context, from which pm_runtime_get() is not allowed.
+ * This function is called mainly from clk_disable_unused_subtree,
+ * which ensures proper runtime pm activation of controller before
+ * taking enable spinlock, but the below check is needed if one tries
+ * to call it from other place.
+ */
+ if (core->dev) {
+ pm_runtime_get_noresume(core->dev);
+ if (pm_runtime_suspended(core->dev)) {
+ status = false;
+ goto done;
+ }
+ }
+
+ status = core->ops->is_enabled(core->hw);
+done:
+ if (core->dev)
+ pm_runtime_put(core->dev);
+
+ return status;
}
/*** helper functions ***/
@@ -489,6 +541,8 @@ static void clk_core_unprepare(struct clk_core *core)
if (core->ops->unprepare)
core->ops->unprepare(core->hw);
+ clk_pm_runtime_put(core);
+
trace_clk_unprepare_complete(core);
clk_core_unprepare(core->parent);
}
@@ -530,10 +584,14 @@ static int clk_core_prepare(struct clk_core *core)
return 0;
if (core->prepare_count == 0) {
- ret = clk_core_prepare(core->parent);
+ ret = clk_pm_runtime_get(core);
if (ret)
return ret;
+ ret = clk_core_prepare(core->parent);
+ if (ret)
+ goto runtime_put;
+
trace_clk_prepare(core);
if (core->ops->prepare)
@@ -541,15 +599,18 @@ static int clk_core_prepare(struct clk_core *core)
trace_clk_prepare_complete(core);
- if (ret) {
- clk_core_unprepare(core->parent);
- return ret;
- }
+ if (ret)
+ goto unprepare;
}
core->prepare_count++;
return 0;
+unprepare:
+ clk_core_unprepare(core->parent);
+runtime_put:
+ clk_pm_runtime_put(core);
+ return ret;
}
static int clk_core_prepare_lock(struct clk_core *core)
@@ -745,6 +806,9 @@ static void clk_unprepare_unused_subtree(struct clk_core *core)
if (core->flags & CLK_IGNORE_UNUSED)
return;
+ if (clk_pm_runtime_get(core) != 0)
+ return;
+
if (clk_core_is_prepared(core)) {
trace_clk_unprepare(core);
if (core->ops->unprepare_unused)
@@ -753,6 +817,8 @@ static void clk_unprepare_unused_subtree(struct clk_core *core)
core->ops->unprepare(core->hw);
trace_clk_unprepare_complete(core);
}
+
+ clk_pm_runtime_put(core);
}
static void clk_disable_unused_subtree(struct clk_core *core)
@@ -768,6 +834,9 @@ static void clk_disable_unused_subtree(struct clk_core *core)
if (core->flags & CLK_OPS_PARENT_ENABLE)
clk_core_prepare_enable(core->parent);
+ if (clk_pm_runtime_get(core) != 0)
+ return;
+
flags = clk_enable_lock();
if (core->enable_count)
@@ -794,6 +863,8 @@ unlock_out:
clk_enable_unlock(flags);
if (core->flags & CLK_OPS_PARENT_ENABLE)
clk_core_disable_unprepare(core->parent);
+
+ clk_pm_runtime_put(core);
}
static bool clk_ignore_unused;
@@ -1563,6 +1634,7 @@ static int clk_core_set_rate_nolock(struct clk_core *core,
{
struct clk_core *top, *fail_clk;
unsigned long rate = req_rate;
+ int ret = 0;
if (!core)
return 0;
@@ -1579,21 +1651,28 @@ static int clk_core_set_rate_nolock(struct clk_core *core,
if (!top)
return -EINVAL;
+ ret = clk_pm_runtime_get(core);
+ if (ret)
+ return ret;
+
/* notify that we are about to change rates */
fail_clk = clk_propagate_rate_change(top, PRE_RATE_CHANGE);
if (fail_clk) {
pr_debug("%s: failed to set %s rate\n", __func__,
fail_clk->name);
clk_propagate_rate_change(top, ABORT_RATE_CHANGE);
- return -EBUSY;
+ ret = -EBUSY;
+ goto err;
}
/* change the rates */
clk_change_rate(top);
core->req_rate = req_rate;
+err:
+ clk_pm_runtime_put(core);
- return 0;
+ return ret;
}
/**
@@ -1824,12 +1903,16 @@ static int clk_core_set_parent(struct clk_core *core, struct clk_core *parent)
p_rate = parent->rate;
}
+ ret = clk_pm_runtime_get(core);
+ if (ret)
+ goto out;
+
/* propagate PRE_RATE_CHANGE notifications */
ret = __clk_speculate_rates(core, p_rate);
/* abort if a driver objects */
if (ret & NOTIFY_STOP_MASK)
- goto out;
+ goto runtime_put;
/* do the re-parent */
ret = __clk_set_parent(core, parent, p_index);
@@ -1842,6 +1925,8 @@ static int clk_core_set_parent(struct clk_core *core, struct clk_core *parent)
__clk_recalc_accuracies(core);
}
+runtime_put:
+ clk_pm_runtime_put(core);
out:
clk_prepare_unlock();
@@ -2546,6 +2631,8 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
goto fail_name;
}
core->ops = hw->init->ops;
+ if (dev && (hw->init->flags & CLK_RUNTIME_PM))
+ core->dev = dev;
if (dev && dev->driver)
core->owner = dev->driver->owner;
core->hw = hw;
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index a39c0c530778..8a131eb71fdf 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -35,6 +35,7 @@
#define CLK_IS_CRITICAL BIT(11) /* do not gate, ever */
/* parents need enable during gate/ungate, set rate and re-parent */
#define CLK_OPS_PARENT_ENABLE BIT(12)
+#define CLK_RUNTIME_PM BIT(13)
struct clk;
struct clk_hw;
--
1.9.1
^ permalink raw reply related
* [PATCH v2 2/5] clock: samsung: add support for runtime pm
From: Marek Szyprowski @ 2016-09-19 10:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1474282525-30441-1-git-send-email-m.szyprowski@samsung.com>
This patch adds struct device pointer to samsung_clk_provider and forwarding it
to clk_register_* functions, so drivers can register clocks, which use runtime
pm feature. It also adds CLK_RUNTIME_PM flag to all clocks for which such
device have been provided.
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
drivers/clk/samsung/clk-pll.c | 4 ++--
drivers/clk/samsung/clk.c | 36 ++++++++++++++++++++++++------------
drivers/clk/samsung/clk.h | 1 +
3 files changed, 27 insertions(+), 14 deletions(-)
diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
index 48139bd510f1..fa929ddf3551 100644
--- a/drivers/clk/samsung/clk-pll.c
+++ b/drivers/clk/samsung/clk-pll.c
@@ -1174,7 +1174,7 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx,
}
init.name = pll_clk->name;
- init.flags = pll_clk->flags;
+ init.flags = pll_clk->flags | (ctx->dev ? CLK_RUNTIME_PM : 0);
init.parent_names = &pll_clk->parent_name;
init.num_parents = 1;
@@ -1285,7 +1285,7 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx,
pll->lock_reg = base + pll_clk->lock_offset;
pll->con_reg = base + pll_clk->con_offset;
- clk = clk_register(NULL, &pll->hw);
+ clk = clk_register(ctx->dev, &pll->hw);
if (IS_ERR(clk)) {
pr_err("%s: failed to register pll clock %s : %ld\n",
__func__, pll_clk->name, PTR_ERR(clk));
diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
index b7d87d6db9dc..762019893383 100644
--- a/drivers/clk/samsung/clk.c
+++ b/drivers/clk/samsung/clk.c
@@ -143,8 +143,11 @@ void __init samsung_clk_register_fixed_rate(struct samsung_clk_provider *ctx,
unsigned int idx, ret;
for (idx = 0; idx < nr_clk; idx++, list++) {
- clk = clk_register_fixed_rate(NULL, list->name,
- list->parent_name, list->flags, list->fixed_rate);
+ unsigned int pm_flags = ctx->dev ? CLK_RUNTIME_PM : 0;
+
+ clk = clk_register_fixed_rate(ctx->dev, list->name,
+ list->parent_name, list->flags | pm_flags,
+ list->fixed_rate);
if (IS_ERR(clk)) {
pr_err("%s: failed to register clock %s\n", __func__,
list->name);
@@ -172,8 +175,11 @@ void __init samsung_clk_register_fixed_factor(struct samsung_clk_provider *ctx,
unsigned int idx;
for (idx = 0; idx < nr_clk; idx++, list++) {
- clk = clk_register_fixed_factor(NULL, list->name,
- list->parent_name, list->flags, list->mult, list->div);
+ unsigned int pm_flags = ctx->dev ? CLK_RUNTIME_PM : 0;
+
+ clk = clk_register_fixed_factor(ctx->dev, list->name,
+ list->parent_name, list->flags | pm_flags, list->mult,
+ list->div);
if (IS_ERR(clk)) {
pr_err("%s: failed to register clock %s\n", __func__,
list->name);
@@ -193,8 +199,10 @@ void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx,
unsigned int idx, ret;
for (idx = 0; idx < nr_clk; idx++, list++) {
- clk = clk_register_mux(NULL, list->name, list->parent_names,
- list->num_parents, list->flags,
+ unsigned int pm_flags = ctx->dev ? CLK_RUNTIME_PM : 0;
+
+ clk = clk_register_mux(ctx->dev, list->name, list->parent_names,
+ list->num_parents, list->flags | pm_flags,
ctx->reg_base + list->offset,
list->shift, list->width, list->mux_flags, &ctx->lock);
if (IS_ERR(clk)) {
@@ -225,15 +233,17 @@ void __init samsung_clk_register_div(struct samsung_clk_provider *ctx,
unsigned int idx, ret;
for (idx = 0; idx < nr_clk; idx++, list++) {
+ unsigned int pm_flags = ctx->dev ? CLK_RUNTIME_PM : 0;
+
if (list->table)
- clk = clk_register_divider_table(NULL, list->name,
- list->parent_name, list->flags,
+ clk = clk_register_divider_table(ctx->dev, list->name,
+ list->parent_name, list->flags | pm_flags,
ctx->reg_base + list->offset,
list->shift, list->width, list->div_flags,
list->table, &ctx->lock);
else
- clk = clk_register_divider(NULL, list->name,
- list->parent_name, list->flags,
+ clk = clk_register_divider(ctx->dev, list->name,
+ list->parent_name, list->flags | pm_flags,
ctx->reg_base + list->offset, list->shift,
list->width, list->div_flags, &ctx->lock);
if (IS_ERR(clk)) {
@@ -264,8 +274,10 @@ void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx,
unsigned int idx, ret;
for (idx = 0; idx < nr_clk; idx++, list++) {
- clk = clk_register_gate(NULL, list->name, list->parent_name,
- list->flags, ctx->reg_base + list->offset,
+ unsigned int pm_flags = ctx->dev ? CLK_RUNTIME_PM : 0;
+
+ clk = clk_register_gate(ctx->dev, list->name, list->parent_name,
+ list->flags | pm_flags, ctx->reg_base + list->offset,
list->bit_idx, list->gate_flags, &ctx->lock);
if (IS_ERR(clk)) {
pr_err("%s: failed to register clock %s\n", __func__,
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
index da3bdebabf1e..9263d8a27c6b 100644
--- a/drivers/clk/samsung/clk.h
+++ b/drivers/clk/samsung/clk.h
@@ -26,6 +26,7 @@ struct clk;
*/
struct samsung_clk_provider {
void __iomem *reg_base;
+ struct device *dev;
struct clk_onecell_data clk_data;
spinlock_t lock;
};
--
1.9.1
^ permalink raw reply related
* [PATCH v2 3/5] clocks: exynos4x12: add runtime pm support for ISP clocks
From: Marek Szyprowski @ 2016-09-19 10:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1474282525-30441-1-git-send-email-m.szyprowski@samsung.com>
Exynos4412 clock controller contains some additional clocks for FIMC-ISP
(Camera ISP) subsystem. Registers for those clocks are partially located
in the SOC area, which belongs to ISP power domain.
This patch implements integration of ISP clocks with ISP power domain
by using runtime pm feature of clocks core. This finally solves all the
mysterious freezes in accessing ISP clocks when ISP power domain is disabled.
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
.../devicetree/bindings/clock/exynos4-clock.txt | 22 ++
drivers/clk/samsung/clk-exynos4.c | 227 +++++++++++++++------
2 files changed, 188 insertions(+), 61 deletions(-)
diff --git a/Documentation/devicetree/bindings/clock/exynos4-clock.txt b/Documentation/devicetree/bindings/clock/exynos4-clock.txt
index f5a5b19ed3b2..429dd7e420e4 100644
--- a/Documentation/devicetree/bindings/clock/exynos4-clock.txt
+++ b/Documentation/devicetree/bindings/clock/exynos4-clock.txt
@@ -41,3 +41,25 @@ Example 2: UART controller node that consumes the clock generated by the clock
clocks = <&clock CLK_UART2>, <&clock CLK_SCLK_UART2>;
clock-names = "uart", "clk_uart_baud0";
};
+
+Exynos4412 clock controller contains some additional clocks for FIMC-ISP
+(Camera ISP) subsystem. Registers for those clocks are partially located
+in the SOC area, which belongs to ISP power domain. To properly handle
+additional ISP clocks and their integration with power domains, an
+additional subnode "isp-clock-controller" with "samsung,exynos4412-isp-clock"
+compatible has to be defined under the main Exynos4 clock node. This subnode
+can be then used for linking with respective ISP power domain (for more
+information, see Samsung Exynos power domains bindings).
+
+Example 3: An example of a clock controller for Exynos4412 with ISP clocks.
+
+ clock: clock-controller at 10030000 {
+ compatible = "samsung,exynos4412-clock";
+ reg = <0x10030000 0x20000>;
+ #clock-cells = <1>;
+
+ isp-clock-controller {
+ compatible = "samsung,exynos4412-isp-clock";
+ power-domains = <&pd_isp>;
+ };
+ };
diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
index faab9b31baf5..3d65e3f92f5a 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -16,7 +16,10 @@
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/of_platform.h>
#include <linux/syscore_ops.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include "clk.h"
#include "clk-cpu.h"
@@ -123,6 +126,8 @@
#define CLKOUT_CMU_CPU 0x14a00
#define PWR_CTRL1 0x15020
#define E4X12_PWR_CTRL2 0x15024
+
+/* Exynos4x12 specific registers, which belong to ISP power domain */
#define E4X12_DIV_ISP0 0x18300
#define E4X12_DIV_ISP1 0x18304
#define E4X12_GATE_ISP0 0x18800
@@ -156,6 +161,8 @@ enum exynos4_plls {
static void __iomem *reg_base;
static enum exynos4_soc exynos4_soc;
+static struct samsung_clk_provider *exynos4412_ctx;
+static struct device_node *exynos4412_clk_node;
/*
* Support for CMU save/restore across system suspends
@@ -164,6 +171,7 @@ static enum exynos4_soc exynos4_soc;
static struct samsung_clk_reg_dump *exynos4_save_common;
static struct samsung_clk_reg_dump *exynos4_save_soc;
static struct samsung_clk_reg_dump *exynos4_save_pll;
+static struct samsung_clk_reg_dump *exynos4x12_save_isp;
/*
* list of controller registers to be saved and restored during a
@@ -192,6 +200,13 @@ static const unsigned long exynos4x12_clk_save[] __initconst = {
E4X12_PWR_CTRL2,
};
+static const unsigned long exynos4x12_clk_isp_save[] __initconst = {
+ E4X12_DIV_ISP0,
+ E4X12_DIV_ISP1,
+ E4X12_GATE_ISP0,
+ E4X12_GATE_ISP1,
+};
+
static const unsigned long exynos4_clk_pll_regs[] __initconst = {
EPLL_LOCK,
VPLL_LOCK,
@@ -822,20 +837,21 @@ static const struct samsung_div_clock exynos4x12_div_clks[] __initconst = {
DIV(0, "div_spi1_isp", "mout_spi1_isp", E4X12_DIV_ISP, 16, 4),
DIV(0, "div_spi1_isp_pre", "div_spi1_isp", E4X12_DIV_ISP, 20, 8),
DIV(0, "div_uart_isp", "mout_uart_isp", E4X12_DIV_ISP, 28, 4),
- DIV_F(CLK_DIV_ISP0, "div_isp0", "aclk200", E4X12_DIV_ISP0, 0, 3,
- CLK_GET_RATE_NOCACHE, 0),
- DIV_F(CLK_DIV_ISP1, "div_isp1", "aclk200", E4X12_DIV_ISP0, 4, 3,
- CLK_GET_RATE_NOCACHE, 0),
- DIV(0, "div_mpwm", "div_isp1", E4X12_DIV_ISP1, 0, 3),
- DIV_F(CLK_DIV_MCUISP0, "div_mcuisp0", "aclk400_mcuisp", E4X12_DIV_ISP1,
- 4, 3, CLK_GET_RATE_NOCACHE, 0),
- DIV_F(CLK_DIV_MCUISP1, "div_mcuisp1", "div_mcuisp0", E4X12_DIV_ISP1,
- 8, 3, CLK_GET_RATE_NOCACHE, 0),
DIV(CLK_SCLK_FIMG2D, "sclk_fimg2d", "mout_g2d", DIV_DMC1, 0, 4),
DIV(CLK_DIV_C2C, "div_c2c", "mout_c2c", DIV_DMC1, 4, 3),
DIV(0, "div_c2c_aclk", "div_c2c", DIV_DMC1, 12, 3),
};
+static struct samsung_div_clock exynos4x12_isp_div_clks[] = {
+ DIV_F(CLK_DIV_ISP0, "div_isp0", "aclk200", E4X12_DIV_ISP0, 0, 3, 0, 0),
+ DIV_F(CLK_DIV_ISP1, "div_isp1", "aclk200", E4X12_DIV_ISP0, 4, 3, 0, 0),
+ DIV_F(CLK_DIV_MCUISP0, "div_mcuisp0", "aclk400_mcuisp", E4X12_DIV_ISP1,
+ 4, 3, 0, 0),
+ DIV_F(CLK_DIV_MCUISP1, "div_mcuisp1", "div_mcuisp0", E4X12_DIV_ISP1,
+ 8, 3, 0, 0),
+ DIV_F(0, "div_mpwm", "div_isp1", E4X12_DIV_ISP1, 0, 3, 0, 0),
+};
+
/* list of gate clocks supported in all exynos4 soc's */
static const struct samsung_gate_clock exynos4_gate_clks[] __initconst = {
/*
@@ -1132,64 +1148,41 @@ static const struct samsung_gate_clock exynos4x12_gate_clks[] __initconst = {
0, 0),
GATE(CLK_I2S0, "i2s0", "aclk100", E4X12_GATE_IP_MAUDIO, 3,
0, 0),
- GATE(CLK_FIMC_ISP, "isp", "aclk200", E4X12_GATE_ISP0, 0,
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
- GATE(CLK_FIMC_DRC, "drc", "aclk200", E4X12_GATE_ISP0, 1,
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
- GATE(CLK_FIMC_FD, "fd", "aclk200", E4X12_GATE_ISP0, 2,
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
- GATE(CLK_FIMC_LITE0, "lite0", "aclk200", E4X12_GATE_ISP0, 3,
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
- GATE(CLK_FIMC_LITE1, "lite1", "aclk200", E4X12_GATE_ISP0, 4,
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
- GATE(CLK_MCUISP, "mcuisp", "aclk200", E4X12_GATE_ISP0, 5,
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
- GATE(CLK_GICISP, "gicisp", "aclk200", E4X12_GATE_ISP0, 7,
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
- GATE(CLK_SMMU_ISP, "smmu_isp", "aclk200", E4X12_GATE_ISP0, 8,
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
- GATE(CLK_SMMU_DRC, "smmu_drc", "aclk200", E4X12_GATE_ISP0, 9,
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
- GATE(CLK_SMMU_FD, "smmu_fd", "aclk200", E4X12_GATE_ISP0, 10,
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
- GATE(CLK_SMMU_LITE0, "smmu_lite0", "aclk200", E4X12_GATE_ISP0, 11,
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
- GATE(CLK_SMMU_LITE1, "smmu_lite1", "aclk200", E4X12_GATE_ISP0, 12,
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
- GATE(CLK_PPMUISPMX, "ppmuispmx", "aclk200", E4X12_GATE_ISP0, 20,
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
- GATE(CLK_PPMUISPX, "ppmuispx", "aclk200", E4X12_GATE_ISP0, 21,
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
- GATE(CLK_MCUCTL_ISP, "mcuctl_isp", "aclk200", E4X12_GATE_ISP0, 23,
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
- GATE(CLK_MPWM_ISP, "mpwm_isp", "aclk200", E4X12_GATE_ISP0, 24,
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
- GATE(CLK_I2C0_ISP, "i2c0_isp", "aclk200", E4X12_GATE_ISP0, 25,
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
- GATE(CLK_I2C1_ISP, "i2c1_isp", "aclk200", E4X12_GATE_ISP0, 26,
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
- GATE(CLK_MTCADC_ISP, "mtcadc_isp", "aclk200", E4X12_GATE_ISP0, 27,
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
- GATE(CLK_PWM_ISP, "pwm_isp", "aclk200", E4X12_GATE_ISP0, 28,
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
- GATE(CLK_WDT_ISP, "wdt_isp", "aclk200", E4X12_GATE_ISP0, 30,
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
- GATE(CLK_UART_ISP, "uart_isp", "aclk200", E4X12_GATE_ISP0, 31,
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
- GATE(CLK_ASYNCAXIM, "asyncaxim", "aclk200", E4X12_GATE_ISP1, 0,
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
- GATE(CLK_SMMU_ISPCX, "smmu_ispcx", "aclk200", E4X12_GATE_ISP1, 4,
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
- GATE(CLK_SPI0_ISP, "spi0_isp", "aclk200", E4X12_GATE_ISP1, 12,
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
- GATE(CLK_SPI1_ISP, "spi1_isp", "aclk200", E4X12_GATE_ISP1, 13,
- CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
GATE(CLK_G2D, "g2d", "aclk200", GATE_IP_DMC, 23, 0, 0),
GATE(CLK_SMMU_G2D, "smmu_g2d", "aclk200", GATE_IP_DMC, 24, 0, 0),
GATE(CLK_TMU_APBIF, "tmu_apbif", "aclk100", E4X12_GATE_IP_PERIR, 17, 0,
0),
};
+static struct samsung_gate_clock exynos4x12_isp_gate_clks[] = {
+ GATE(CLK_FIMC_ISP, "isp", "aclk200", E4X12_GATE_ISP0, 0, 0, 0),
+ GATE(CLK_FIMC_DRC, "drc", "aclk200", E4X12_GATE_ISP0, 1, 0, 0),
+ GATE(CLK_FIMC_FD, "fd", "aclk200", E4X12_GATE_ISP0, 2, 0, 0),
+ GATE(CLK_FIMC_LITE0, "lite0", "aclk200", E4X12_GATE_ISP0, 3, 0, 0),
+ GATE(CLK_FIMC_LITE1, "lite1", "aclk200", E4X12_GATE_ISP0, 4, 0, 0),
+ GATE(CLK_MCUISP, "mcuisp", "aclk200", E4X12_GATE_ISP0, 5, 0, 0),
+ GATE(CLK_GICISP, "gicisp", "aclk200", E4X12_GATE_ISP0, 7, 0, 0),
+ GATE(CLK_SMMU_ISP, "smmu_isp", "aclk200", E4X12_GATE_ISP0, 8, 0, 0),
+ GATE(CLK_SMMU_DRC, "smmu_drc", "aclk200", E4X12_GATE_ISP0, 9, 0, 0),
+ GATE(CLK_SMMU_FD, "smmu_fd", "aclk200", E4X12_GATE_ISP0, 10, 0, 0),
+ GATE(CLK_SMMU_LITE0, "smmu_lite0", "aclk200", E4X12_GATE_ISP0, 11, 0, 0),
+ GATE(CLK_SMMU_LITE1, "smmu_lite1", "aclk200", E4X12_GATE_ISP0, 12, 0, 0),
+ GATE(CLK_PPMUISPMX, "ppmuispmx", "aclk200", E4X12_GATE_ISP0, 20, 0, 0),
+ GATE(CLK_PPMUISPX, "ppmuispx", "aclk200", E4X12_GATE_ISP0, 21, 0, 0),
+ GATE(CLK_MCUCTL_ISP, "mcuctl_isp", "aclk200", E4X12_GATE_ISP0, 23, 0, 0),
+ GATE(CLK_MPWM_ISP, "mpwm_isp", "aclk200", E4X12_GATE_ISP0, 24, 0, 0),
+ GATE(CLK_I2C0_ISP, "i2c0_isp", "aclk200", E4X12_GATE_ISP0, 25, 0, 0),
+ GATE(CLK_I2C1_ISP, "i2c1_isp", "aclk200", E4X12_GATE_ISP0, 26, 0, 0),
+ GATE(CLK_MTCADC_ISP, "mtcadc_isp", "aclk200", E4X12_GATE_ISP0, 27, 0, 0),
+ GATE(CLK_PWM_ISP, "pwm_isp", "aclk200", E4X12_GATE_ISP0, 28, 0, 0),
+ GATE(CLK_WDT_ISP, "wdt_isp", "aclk200", E4X12_GATE_ISP0, 30, 0, 0),
+ GATE(CLK_UART_ISP, "uart_isp", "aclk200", E4X12_GATE_ISP0, 31, 0, 0),
+ GATE(CLK_ASYNCAXIM, "asyncaxim", "aclk200", E4X12_GATE_ISP1, 0, 0, 0),
+ GATE(CLK_SMMU_ISPCX, "smmu_ispcx", "aclk200", E4X12_GATE_ISP1, 4, 0, 0),
+ GATE(CLK_SPI0_ISP, "spi0_isp", "aclk200", E4X12_GATE_ISP1, 12, 0, 0),
+ GATE(CLK_SPI1_ISP, "spi1_isp", "aclk200", E4X12_GATE_ISP1, 13, 0, 0),
+};
+
static const struct samsung_clock_alias exynos4_aliases[] __initconst = {
ALIAS(CLK_MOUT_CORE, NULL, "moutcore"),
ALIAS(CLK_ARM_CLK, NULL, "armclk"),
@@ -1438,6 +1431,116 @@ static const struct exynos_cpuclk_cfg_data e4412_armclk_d[] __initconst = {
{ 0 },
};
+static int exynos4x12_isp_clk_suspend(struct device *dev)
+{
+ samsung_clk_save(reg_base, exynos4x12_save_isp,
+ ARRAY_SIZE(exynos4x12_clk_isp_save));
+ return 0;
+}
+
+static int exynos4x12_isp_clk_resume(struct device *dev)
+{
+ samsung_clk_restore(reg_base, exynos4x12_save_isp,
+ ARRAY_SIZE(exynos4x12_clk_isp_save));
+ return 0;
+}
+
+static int __init exynos4x12_isp_clk_probe(struct platform_device *pdev)
+{
+ struct samsung_clk_provider *ctx = exynos4412_ctx;
+
+ if (!ctx)
+ return -ENODEV;
+
+ dev_set_name(&pdev->dev, pdev->dev.of_node->name);
+
+ ctx->dev = &pdev->dev;
+ samsung_clk_register_div(ctx, exynos4x12_isp_div_clks,
+ ARRAY_SIZE(exynos4x12_isp_div_clks));
+
+ samsung_clk_register_gate(ctx, exynos4x12_isp_gate_clks,
+ ARRAY_SIZE(exynos4x12_isp_gate_clks));
+ ctx->dev = NULL;
+
+ exynos4x12_save_isp = samsung_clk_alloc_reg_dump(exynos4x12_clk_isp_save,
+ ARRAY_SIZE(exynos4x12_clk_isp_save));
+ if (!exynos4x12_save_isp)
+ dev_warn(&pdev->dev, "failed to allocate sleep save data, no sleep support!\n");
+ else {
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+ }
+
+ return 0;
+}
+
+static const struct of_device_id exynos4x12_isp_clk_of_match[] = {
+ { .compatible = "samsung,exynos4412-isp-clock", },
+ { },
+};
+
+static const struct dev_pm_ops exynos4x12_isp_pm_ops = {
+ SET_RUNTIME_PM_OPS(exynos4x12_isp_clk_suspend,
+ exynos4x12_isp_clk_resume, NULL)
+ SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+ pm_runtime_force_resume)
+};
+
+static struct platform_driver exynos4x12_isp_clk_driver __refdata = {
+ .driver = {
+ .name = "exynos-isp-clk",
+ .of_match_table = exynos4x12_isp_clk_of_match,
+ .suppress_bind_attrs = true,
+ .pm = &exynos4x12_isp_pm_ops,
+ },
+ .probe = exynos4x12_isp_clk_probe,
+};
+
+static int __init exynos4x12_isp_clk_init(void)
+{
+ struct platform_device *parent_pdev;
+ struct device *parent;
+ int ret;
+
+ if (!exynos4412_clk_node)
+ return 0;
+
+ parent_pdev = of_find_device_by_node(exynos4412_clk_node);
+ if (!parent_pdev)
+ return -ENODEV;
+
+ parent = &parent_pdev->dev;
+ ret = of_platform_populate(parent->of_node, NULL, NULL, parent);
+ if (ret)
+ return ret;
+
+ return platform_driver_register(&exynos4x12_isp_clk_driver);
+}
+arch_initcall_sync(exynos4x12_isp_clk_init);
+
+static void __init exynos4x12_isp_defer_clocks(struct samsung_clk_provider *ctx,
+ struct device_node *parent)
+{
+ struct device_node *np = of_get_next_available_child(parent, NULL);
+ if (!np)
+ return;
+
+ if (of_device_is_compatible(np,
+ exynos4x12_isp_clk_of_match[0].compatible)) {
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(exynos4x12_isp_div_clks); i++)
+ samsung_clk_add_lookup(ctx, ERR_PTR(-EPROBE_DEFER),
+ exynos4x12_isp_div_clks[i].id);
+ for (i = 0; i < ARRAY_SIZE(exynos4x12_isp_gate_clks); i++)
+ samsung_clk_add_lookup(ctx, ERR_PTR(-EPROBE_DEFER),
+ exynos4x12_isp_gate_clks[i].id);
+ exynos4412_ctx = ctx;
+ exynos4412_clk_node = parent;
+ }
+ of_node_put(np);
+}
+
/* register exynos4 clocks */
static void __init exynos4_clk_init(struct device_node *np,
enum exynos4_soc soc)
@@ -1529,6 +1632,8 @@ static void __init exynos4_clk_init(struct device_node *np,
samsung_clk_register_fixed_factor(ctx,
exynos4x12_fixed_factor_clks,
ARRAY_SIZE(exynos4x12_fixed_factor_clks));
+ exynos4x12_isp_defer_clocks(ctx, np);
+
if (of_machine_is_compatible("samsung,exynos4412")) {
exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk",
mout_core_p4x12[0], mout_core_p4x12[1], 0x14200,
--
1.9.1
^ permalink raw reply related
* [PATCH v2 4/5] ARM: dts: exynos: add support for ISP power domain to exynos4x12 clocks device
From: Marek Szyprowski @ 2016-09-19 10:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1474282525-30441-1-git-send-email-m.szyprowski@samsung.com>
Exynos4412 clock controller contains some additional clocks for FIMC-ISP
(Camera ISP) subsystem. Registers for those clocks are partially located
in the SOC area, which belongs to ISP power domain.
This patch implements integration of ISP clocks with ISP power domain.
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
arch/arm/boot/dts/exynos4x12.dtsi | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/arm/boot/dts/exynos4x12.dtsi b/arch/arm/boot/dts/exynos4x12.dtsi
index 3394bdcf10ae..4daea67546b9 100644
--- a/arch/arm/boot/dts/exynos4x12.dtsi
+++ b/arch/arm/boot/dts/exynos4x12.dtsi
@@ -74,6 +74,11 @@
compatible = "samsung,exynos4412-clock";
reg = <0x10030000 0x20000>;
#clock-cells = <1>;
+
+ isp-clock-controller {
+ compatible = "samsung,exynos4412-isp-clock";
+ power-domains = <&pd_isp>;
+ };
};
mct at 10050000 {
--
1.9.1
^ permalink raw reply related
* [PATCH 1/3] nvmem: add NXP LPC18xx OTP driver
From: Srinivas Kandagatla @ 2016-09-19 10:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160913161241.22492-2-manabian@gmail.com>
On 13/09/16 17:12, Joachim Eastwood wrote:
> Add simple read only driver for the internal OTP (One Time Programmable)
> memory found on all NXP LPC18xx and LPC43xx devices.
>
> The OTP memory is split into 4 banks each with 4 32-bits word. Some of
> the banks contain predefined data while others are for general purpose
> and user programmable via the OTP API in ROM. Note that writing to the
> OTP memory is not yet supported.
>
> Signed-off-by: Joachim Eastwood <manabian@gmail.com>
> ---
> drivers/nvmem/Kconfig | 10 ++++
> drivers/nvmem/Makefile | 2 +
> drivers/nvmem/lpc18xx_otp.c | 123 ++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 135 insertions(+)
> create mode 100644 drivers/nvmem/lpc18xx_otp.c
>
Patch looks good to me.
I will pick this patch + bindings patch once rc1 lands in.
Thanks,
srini
^ permalink raw reply
* [PATCH v2 5/5] clocks: exynos5433: add runtime pm support
From: Marek Szyprowski @ 2016-09-19 10:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1474282525-30441-1-git-send-email-m.szyprowski@samsung.com>
Add runtime pm support for all clock controller units (CMU), which belongs
to power domains and require special handling during on/off operations.
Typically special values has to be written to MUX registers to change
internal clocks parents to OSC clock before turning power off. During such
operation all clocks, which enters CMU has to be enabled to let MUX to
stabilize. Also for each CMU there is one special parent clock, which has
to be enabled all the time when any access to CMU registers is done.
This patch solves most of the mysterious external abort and freeze issues
caused by a lack of proper parent CMU clock enabled or incorrect turn off
procedure.
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
drivers/clk/samsung/clk-exynos5433.c | 385 ++++++++++++++++++++++++++++-------
drivers/clk/samsung/clk.h | 6 +
2 files changed, 314 insertions(+), 77 deletions(-)
diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c
index ea1608682d7f..d507f2ace6c2 100644
--- a/drivers/clk/samsung/clk-exynos5433.c
+++ b/drivers/clk/samsung/clk-exynos5433.c
@@ -9,9 +9,14 @@
* Common Clock Framework support for Exynos5443 SoC.
*/
+#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
#include <dt-bindings/clock/exynos5433.h>
@@ -2333,6 +2338,10 @@ static const unsigned long g2d_clk_regs[] __initconst = {
DIV_ENABLE_IP_G2D_SECURE_SMMU_G2D,
};
+static const struct samsung_clk_reg_dump g2d_suspend_regs[] = {
+ { MUX_SEL_G2D0, 0 },
+};
+
/* list of all parent clock list */
PNAME(mout_aclk_g2d_266_user_p) = { "oscclk", "aclk_g2d_266", };
PNAME(mout_aclk_g2d_400_user_p) = { "oscclk", "aclk_g2d_400", };
@@ -2418,16 +2427,11 @@ static const struct samsung_cmu_info g2d_cmu_info __initconst = {
.nr_clk_ids = G2D_NR_CLK,
.clk_regs = g2d_clk_regs,
.nr_clk_regs = ARRAY_SIZE(g2d_clk_regs),
+ .suspend_regs = g2d_suspend_regs,
+ .nr_suspend_regs = ARRAY_SIZE(g2d_suspend_regs),
+ .clk_name = "aclk_g2d_400",
};
-static void __init exynos5433_cmu_g2d_init(struct device_node *np)
-{
- samsung_cmu_register_one(np, &g2d_cmu_info);
-}
-
-CLK_OF_DECLARE(exynos5433_cmu_g2d, "samsung,exynos5433-cmu-g2d",
- exynos5433_cmu_g2d_init);
-
/*
* Register offset definitions for CMU_DISP
*/
@@ -2492,6 +2496,14 @@ static const unsigned long disp_clk_regs[] __initconst = {
CLKOUT_CMU_DISP_DIV_STAT,
};
+static const struct samsung_clk_reg_dump disp_suspend_regs[] = {
+ { MUX_SEL_DISP0, 0 },
+ { MUX_SEL_DISP1, 0 },
+ { MUX_SEL_DISP2, 0 },
+ { MUX_SEL_DISP3, 0 },
+ { MUX_SEL_DISP4, 0 },
+};
+
/* list of all parent clock list */
PNAME(mout_disp_pll_p) = { "oscclk", "fout_disp_pll", };
PNAME(mout_sclk_dsim1_user_p) = { "oscclk", "sclk_dsim1_disp", };
@@ -2837,16 +2849,11 @@ static const struct samsung_cmu_info disp_cmu_info __initconst = {
.nr_clk_ids = DISP_NR_CLK,
.clk_regs = disp_clk_regs,
.nr_clk_regs = ARRAY_SIZE(disp_clk_regs),
+ .suspend_regs = disp_suspend_regs,
+ .nr_suspend_regs = ARRAY_SIZE(disp_suspend_regs),
+ .clk_name = "aclk_disp_333",
};
-static void __init exynos5433_cmu_disp_init(struct device_node *np)
-{
- samsung_cmu_register_one(np, &disp_cmu_info);
-}
-
-CLK_OF_DECLARE(exynos5433_cmu_disp, "samsung,exynos5433-cmu-disp",
- exynos5433_cmu_disp_init);
-
/*
* Register offset definitions for CMU_AUD
*/
@@ -2881,6 +2888,11 @@ static const unsigned long aud_clk_regs[] __initconst = {
ENABLE_IP_AUD1,
};
+static const struct samsung_clk_reg_dump aud_suspend_regs[] = {
+ { MUX_SEL_AUD0, 0 },
+ { MUX_SEL_AUD1, 0 },
+};
+
/* list of all parent clock list */
PNAME(mout_aud_pll_user_aud_p) = { "oscclk", "fout_aud_pll", };
PNAME(mout_sclk_aud_pcm_p) = { "mout_aud_pll_user", "ioclk_audiocdclk0",};
@@ -3007,16 +3019,10 @@ static const struct samsung_cmu_info aud_cmu_info __initconst = {
.nr_clk_ids = AUD_NR_CLK,
.clk_regs = aud_clk_regs,
.nr_clk_regs = ARRAY_SIZE(aud_clk_regs),
+ .suspend_regs = aud_suspend_regs,
+ .nr_suspend_regs = ARRAY_SIZE(aud_suspend_regs),
};
-static void __init exynos5433_cmu_aud_init(struct device_node *np)
-{
- samsung_cmu_register_one(np, &aud_cmu_info);
-}
-CLK_OF_DECLARE(exynos5433_cmu_aud, "samsung,exynos5433-cmu-aud",
- exynos5433_cmu_aud_init);
-
-
/*
* Register offset definitions for CMU_BUS{0|1|2}
*/
@@ -3218,6 +3224,10 @@ static const unsigned long g3d_clk_regs[] __initconst = {
CLK_STOPCTRL,
};
+static const struct samsung_clk_reg_dump g3d_suspend_regs[] = {
+ { MUX_SEL_G3D, 0 },
+};
+
/* list of all parent clock list */
PNAME(mout_aclk_g3d_400_p) = { "mout_g3d_pll", "aclk_g3d_400", };
PNAME(mout_g3d_pll_p) = { "oscclk", "fout_g3d_pll", };
@@ -3291,15 +3301,11 @@ static const struct samsung_cmu_info g3d_cmu_info __initconst = {
.nr_clk_ids = G3D_NR_CLK,
.clk_regs = g3d_clk_regs,
.nr_clk_regs = ARRAY_SIZE(g3d_clk_regs),
+ .suspend_regs = g3d_suspend_regs,
+ .nr_suspend_regs = ARRAY_SIZE(g3d_suspend_regs),
+ .clk_name = "aclk_g3d_400",
};
-static void __init exynos5433_cmu_g3d_init(struct device_node *np)
-{
- samsung_cmu_register_one(np, &g3d_cmu_info);
-}
-CLK_OF_DECLARE(exynos5433_cmu_g3d, "samsung,exynos5433-cmu-g3d",
- exynos5433_cmu_g3d_init);
-
/*
* Register offset definitions for CMU_GSCL
*/
@@ -3338,6 +3344,12 @@ static const unsigned long gscl_clk_regs[] __initconst = {
ENABLE_IP_GSCL_SECURE_SMMU_GSCL2,
};
+static const struct samsung_clk_reg_dump gscl_suspend_regs[] = {
+ { MUX_SEL_GSCL, 0 },
+ { ENABLE_ACLK_GSCL, 0xfff },
+ { ENABLE_PCLK_GSCL, 0xff },
+};
+
/* list of all parent clock list */
PNAME(aclk_gscl_111_user_p) = { "oscclk", "aclk_gscl_111", };
PNAME(aclk_gscl_333_user_p) = { "oscclk", "aclk_gscl_333", };
@@ -3432,15 +3444,11 @@ static const struct samsung_cmu_info gscl_cmu_info __initconst = {
.nr_clk_ids = GSCL_NR_CLK,
.clk_regs = gscl_clk_regs,
.nr_clk_regs = ARRAY_SIZE(gscl_clk_regs),
+ .suspend_regs = gscl_suspend_regs,
+ .nr_suspend_regs = ARRAY_SIZE(gscl_suspend_regs),
+ .clk_name = "aclk_gscl_111",
};
-static void __init exynos5433_cmu_gscl_init(struct device_node *np)
-{
- samsung_cmu_register_one(np, &gscl_cmu_info);
-}
-CLK_OF_DECLARE(exynos5433_cmu_gscl, "samsung,exynos5433-cmu-gscl",
- exynos5433_cmu_gscl_init);
-
/*
* Register offset definitions for CMU_APOLLO
*/
@@ -3966,6 +3974,11 @@ static const unsigned long mscl_clk_regs[] __initconst = {
ENABLE_IP_MSCL_SECURE_SMMU_JPEG,
};
+static const struct samsung_clk_reg_dump mscl_suspend_regs[] = {
+ { MUX_SEL_MSCL0, 0 },
+ { MUX_SEL_MSCL1, 0 },
+};
+
/* list of all parent clock list */
PNAME(mout_sclk_jpeg_user_p) = { "oscclk", "sclk_jpeg_mscl", };
PNAME(mout_aclk_mscl_400_user_p) = { "oscclk", "aclk_mscl_400", };
@@ -4078,15 +4091,11 @@ static const struct samsung_cmu_info mscl_cmu_info __initconst = {
.nr_clk_ids = MSCL_NR_CLK,
.clk_regs = mscl_clk_regs,
.nr_clk_regs = ARRAY_SIZE(mscl_clk_regs),
+ .suspend_regs = mscl_suspend_regs,
+ .nr_suspend_regs = ARRAY_SIZE(mscl_suspend_regs),
+ .clk_name = "aclk_mscl_400",
};
-static void __init exynos5433_cmu_mscl_init(struct device_node *np)
-{
- samsung_cmu_register_one(np, &mscl_cmu_info);
-}
-CLK_OF_DECLARE(exynos5433_cmu_mscl, "samsung,exynos5433-cmu-mscl",
- exynos5433_cmu_mscl_init);
-
/*
* Register offset definitions for CMU_MFC
*/
@@ -4116,6 +4125,10 @@ static const unsigned long mfc_clk_regs[] __initconst = {
ENABLE_IP_MFC_SECURE_SMMU_MFC,
};
+static const struct samsung_clk_reg_dump mfc_suspend_regs[] = {
+ { MUX_SEL_MFC, 0 },
+};
+
PNAME(mout_aclk_mfc_400_user_p) = { "oscclk", "aclk_mfc_400", };
static const struct samsung_mux_clock mfc_mux_clks[] __initconst = {
@@ -4186,15 +4199,11 @@ static const struct samsung_cmu_info mfc_cmu_info __initconst = {
.nr_clk_ids = MFC_NR_CLK,
.clk_regs = mfc_clk_regs,
.nr_clk_regs = ARRAY_SIZE(mfc_clk_regs),
+ .suspend_regs = mfc_suspend_regs,
+ .nr_suspend_regs = ARRAY_SIZE(mfc_suspend_regs),
+ .clk_name = "aclk_mfc_400",
};
-static void __init exynos5433_cmu_mfc_init(struct device_node *np)
-{
- samsung_cmu_register_one(np, &mfc_cmu_info);
-}
-CLK_OF_DECLARE(exynos5433_cmu_mfc, "samsung,exynos5433-cmu-mfc",
- exynos5433_cmu_mfc_init);
-
/*
* Register offset definitions for CMU_HEVC
*/
@@ -4224,6 +4233,10 @@ static const unsigned long hevc_clk_regs[] __initconst = {
ENABLE_IP_HEVC_SECURE_SMMU_HEVC,
};
+static const struct samsung_clk_reg_dump hevc_suspend_regs[] = {
+ { MUX_SEL_HEVC, 0 },
+};
+
PNAME(mout_aclk_hevc_400_user_p) = { "oscclk", "aclk_hevc_400", };
static const struct samsung_mux_clock hevc_mux_clks[] __initconst = {
@@ -4296,15 +4309,11 @@ static const struct samsung_cmu_info hevc_cmu_info __initconst = {
.nr_clk_ids = HEVC_NR_CLK,
.clk_regs = hevc_clk_regs,
.nr_clk_regs = ARRAY_SIZE(hevc_clk_regs),
+ .suspend_regs = hevc_suspend_regs,
+ .nr_suspend_regs = ARRAY_SIZE(hevc_suspend_regs),
+ .clk_name = "aclk_hevc_400",
};
-static void __init exynos5433_cmu_hevc_init(struct device_node *np)
-{
- samsung_cmu_register_one(np, &hevc_cmu_info);
-}
-CLK_OF_DECLARE(exynos5433_cmu_hevc, "samsung,exynos5433-cmu-hevc",
- exynos5433_cmu_hevc_init);
-
/*
* Register offset definitions for CMU_ISP
*/
@@ -4338,6 +4347,10 @@ static const unsigned long isp_clk_regs[] __initconst = {
ENABLE_IP_ISP3,
};
+static const struct samsung_clk_reg_dump isp_suspend_regs[] = {
+ { MUX_SEL_ISP, 0 },
+};
+
PNAME(mout_aclk_isp_dis_400_user_p) = { "oscclk", "aclk_isp_dis_400", };
PNAME(mout_aclk_isp_400_user_p) = { "oscclk", "aclk_isp_400", };
@@ -4549,15 +4562,11 @@ static const struct samsung_cmu_info isp_cmu_info __initconst = {
.nr_clk_ids = ISP_NR_CLK,
.clk_regs = isp_clk_regs,
.nr_clk_regs = ARRAY_SIZE(isp_clk_regs),
+ .suspend_regs = isp_suspend_regs,
+ .nr_suspend_regs = ARRAY_SIZE(isp_suspend_regs),
+ .clk_name = "aclk_isp_400",
};
-static void __init exynos5433_cmu_isp_init(struct device_node *np)
-{
- samsung_cmu_register_one(np, &isp_cmu_info);
-}
-CLK_OF_DECLARE(exynos5433_cmu_isp, "samsung,exynos5433-cmu-isp",
- exynos5433_cmu_isp_init);
-
/*
* Register offset definitions for CMU_CAM0
*/
@@ -4621,6 +4630,15 @@ static const unsigned long cam0_clk_regs[] __initconst = {
ENABLE_IP_CAM02,
ENABLE_IP_CAM03,
};
+
+static const struct samsung_clk_reg_dump cam0_suspend_regs[] = {
+ { MUX_SEL_CAM00, 0 },
+ { MUX_SEL_CAM01, 0 },
+ { MUX_SEL_CAM02, 0 },
+ { MUX_SEL_CAM03, 0 },
+ { MUX_SEL_CAM04, 0 },
+};
+
PNAME(mout_aclk_cam0_333_user_p) = { "oscclk", "aclk_cam0_333", };
PNAME(mout_aclk_cam0_400_user_p) = { "oscclk", "aclk_cam0_400", };
PNAME(mout_aclk_cam0_552_user_p) = { "oscclk", "aclk_cam0_552", };
@@ -5026,15 +5044,11 @@ static const struct samsung_cmu_info cam0_cmu_info __initconst = {
.nr_clk_ids = CAM0_NR_CLK,
.clk_regs = cam0_clk_regs,
.nr_clk_regs = ARRAY_SIZE(cam0_clk_regs),
+ .suspend_regs = cam0_suspend_regs,
+ .nr_suspend_regs = ARRAY_SIZE(cam0_suspend_regs),
+ .clk_name = "aclk_cam0_400",
};
-static void __init exynos5433_cmu_cam0_init(struct device_node *np)
-{
- samsung_cmu_register_one(np, &cam0_cmu_info);
-}
-CLK_OF_DECLARE(exynos5433_cmu_cam0, "samsung,exynos5433-cmu-cam0",
- exynos5433_cmu_cam0_init);
-
/*
* Register offset definitions for CMU_CAM1
*/
@@ -5081,6 +5095,12 @@ static const unsigned long cam1_clk_regs[] __initconst = {
ENABLE_IP_CAM12,
};
+static const struct samsung_clk_reg_dump cam1_suspend_regs[] = {
+ { MUX_SEL_CAM10, 0 },
+ { MUX_SEL_CAM11, 0 },
+ { MUX_SEL_CAM12, 0 },
+};
+
PNAME(mout_sclk_isp_uart_user_p) = { "oscclk", "sclk_isp_uart_cam1", };
PNAME(mout_sclk_isp_spi1_user_p) = { "oscclk", "sclk_isp_spi1_cam1", };
PNAME(mout_sclk_isp_spi0_user_p) = { "oscclk", "sclk_isp_spi0_cam1", };
@@ -5399,11 +5419,222 @@ static const struct samsung_cmu_info cam1_cmu_info __initconst = {
.nr_clk_ids = CAM1_NR_CLK,
.clk_regs = cam1_clk_regs,
.nr_clk_regs = ARRAY_SIZE(cam1_clk_regs),
+ .suspend_regs = cam1_suspend_regs,
+ .nr_suspend_regs = ARRAY_SIZE(cam1_suspend_regs),
+ .clk_name = "aclk_cam1_400",
+};
+
+
+struct exynos5433_cmu_data {
+ struct samsung_clk_provider ctx;
+
+ struct samsung_clk_reg_dump *clk_save;
+ unsigned int nr_clk_save;
+ const struct samsung_clk_reg_dump *clk_suspend;
+ unsigned int nr_clk_suspend;
+
+ struct clk *clk;
+ struct clk **pclks;
+ int nr_pclks;
+};
+
+static int exynos5433_cmu_suspend(struct device *dev)
+{
+ struct exynos5433_cmu_data *data = dev_get_drvdata(dev);
+ int i;
+
+ samsung_clk_save(data->ctx.reg_base, data->clk_save,
+ data->nr_clk_save);
+
+ for (i = 0; i < data->nr_pclks; i++)
+ clk_enable(data->pclks[i]);
+
+ samsung_clk_restore(data->ctx.reg_base, data->clk_suspend,
+ data->nr_clk_suspend);
+
+ for (i = 0; i < data->nr_pclks; i++)
+ clk_disable(data->pclks[i]);
+
+ clk_disable(data->clk);
+
+ return 0;
+}
+
+static int exynos5433_cmu_resume(struct device *dev)
+{
+ struct exynos5433_cmu_data *data = dev_get_drvdata(dev);
+ int i;
+
+ clk_enable(data->clk);
+
+ for (i = 0; i < data->nr_pclks; i++)
+ clk_enable(data->pclks[i]);
+
+ samsung_clk_restore(data->ctx.reg_base, data->clk_save,
+ data->nr_clk_save);
+
+ for (i = 0; i < data->nr_pclks; i++)
+ clk_disable(data->pclks[i]);
+
+ return 0;
+}
+
+static int __init exynos5433_cmu_probe(struct platform_device *pdev)
+{
+ const struct samsung_cmu_info *info;
+ struct exynos5433_cmu_data *data;
+ struct samsung_clk_provider *ctx;
+ struct device *dev = &pdev->dev;
+ struct resource *res;
+ void __iomem *reg_base;
+ struct clk **clk_table;
+ int i;
+
+ info = of_device_get_match_data(dev);
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+ ctx = &data->ctx;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ reg_base = devm_ioremap_resource(dev, res);
+ if (!reg_base) {
+ dev_err(dev, "failed to map registers\n");
+ return -ENOMEM;
+ }
+
+ clk_table = devm_kcalloc(dev, info->nr_clk_ids, sizeof(struct clk *),
+ GFP_KERNEL);
+ if (!clk_table)
+ return -ENOMEM;
+
+ for (i = 0; i < info->nr_clk_ids; ++i)
+ clk_table[i] = ERR_PTR(-ENOENT);
+
+ ctx->clk_data.clks = clk_table;
+ ctx->clk_data.clk_num = info->nr_clk_ids;
+ ctx->reg_base = reg_base;
+ ctx->dev = dev;
+ spin_lock_init(&ctx->lock);
+
+ data->clk_save = samsung_clk_alloc_reg_dump(info->clk_regs,
+ info->nr_clk_regs);
+ data->nr_clk_save = info->nr_clk_regs;
+ data->clk_suspend = info->suspend_regs;
+ data->nr_clk_suspend = info->nr_suspend_regs;
+ data->nr_pclks = of_count_phandle_with_args(dev->of_node, "clocks",
+ "#clock-cells");
+ if (data->nr_pclks > 0) {
+ data->pclks = devm_kcalloc(dev, sizeof(struct clk *),
+ data->nr_pclks, GFP_KERNEL);
+
+ for (i = 0; i < data->nr_pclks; i++) {
+ struct clk *clk = of_clk_get(dev->of_node, i);
+
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+ data->pclks[i] = clk;
+ }
+ }
+
+ /*
+ * Prepare all parent clocks here to avoid potential deadlock caused
+ * by global clock "prepare lock" grabbed by runtime pm callbacks
+ * from pm workers.
+ */
+ for (i = 0; i < data->nr_pclks; i++)
+ clk_prepare(data->pclks[i]);
+
+ if (info->pll_clks)
+ samsung_clk_register_pll(ctx, info->pll_clks, info->nr_pll_clks,
+ reg_base);
+ if (info->mux_clks)
+ samsung_clk_register_mux(ctx, info->mux_clks,
+ info->nr_mux_clks);
+ if (info->div_clks)
+ samsung_clk_register_div(ctx, info->div_clks,
+ info->nr_div_clks);
+ if (info->gate_clks)
+ samsung_clk_register_gate(ctx, info->gate_clks,
+ info->nr_gate_clks);
+ if (info->fixed_clks)
+ samsung_clk_register_fixed_rate(ctx, info->fixed_clks,
+ info->nr_fixed_clks);
+ if (info->fixed_factor_clks)
+ samsung_clk_register_fixed_factor(ctx, info->fixed_factor_clks,
+ info->nr_fixed_factor_clks);
+
+ if (info->clk_name)
+ data->clk = clk_get(dev, info->clk_name);
+ clk_prepare_enable(data->clk);
+
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+
+ platform_set_drvdata(pdev, data);
+ samsung_clk_of_add_provider(dev->of_node, ctx);
+
+ return 0;
+}
+
+static const struct of_device_id exynos5433_cmu_of_match[] = {
+ {
+ .compatible = "samsung,exynos5433-cmu-aud",
+ .data = &aud_cmu_info,
+ }, {
+ .compatible = "samsung,exynos5433-cmu-cam0",
+ .data = &cam0_cmu_info,
+ }, {
+ .compatible = "samsung,exynos5433-cmu-cam1",
+ .data = &cam1_cmu_info,
+ }, {
+ .compatible = "samsung,exynos5433-cmu-disp",
+ .data = &disp_cmu_info,
+ }, {
+ .compatible = "samsung,exynos5433-cmu-g2d",
+ .data = &g2d_cmu_info,
+ }, {
+ .compatible = "samsung,exynos5433-cmu-g3d",
+ .data = &g3d_cmu_info,
+ }, {
+ .compatible = "samsung,exynos5433-cmu-gscl",
+ .data = &gscl_cmu_info,
+ }, {
+ .compatible = "samsung,exynos5433-cmu-mfc",
+ .data = &mfc_cmu_info,
+ }, {
+ .compatible = "samsung,exynos5433-cmu-hevc",
+ .data = &hevc_cmu_info,
+ }, {
+ .compatible = "samsung,exynos5433-cmu-isp",
+ .data = &isp_cmu_info,
+ }, {
+ .compatible = "samsung,exynos5433-cmu-mscl",
+ .data = &mscl_cmu_info,
+ }, {
+ },
+};
+
+static const struct dev_pm_ops exynos5433_cmu_pm_ops = {
+ SET_RUNTIME_PM_OPS(exynos5433_cmu_suspend, exynos5433_cmu_resume,
+ NULL)
+ SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+ pm_runtime_force_resume)
+};
+
+static struct platform_driver exynos5433_cmu_driver __refdata = {
+ .driver = {
+ .name = "exynos5433-cmu",
+ .of_match_table = exynos5433_cmu_of_match,
+ .suppress_bind_attrs = true,
+ .pm = &exynos5433_cmu_pm_ops,
+ },
+ .probe = exynos5433_cmu_probe,
};
-static void __init exynos5433_cmu_cam1_init(struct device_node *np)
+static int __init exynos5433_cmu_init(void)
{
- samsung_cmu_register_one(np, &cam1_cmu_info);
+ return platform_driver_register(&exynos5433_cmu_driver);
}
-CLK_OF_DECLARE(exynos5433_cmu_cam1, "samsung,exynos5433-cmu-cam1",
- exynos5433_cmu_cam1_init);
+core_initcall(exynos5433_cmu_init);
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
index 9263d8a27c6b..664020cb4794 100644
--- a/drivers/clk/samsung/clk.h
+++ b/drivers/clk/samsung/clk.h
@@ -354,6 +354,12 @@ struct samsung_cmu_info {
/* list and number of clocks registers */
const unsigned long *clk_regs;
unsigned int nr_clk_regs;
+
+ /* list and number of clocks registers to set before suspend */
+ const struct samsung_clk_reg_dump *suspend_regs;
+ unsigned int nr_suspend_regs;
+ /* name of the parent clock needed for CMU register access */
+ const char *clk_name;
};
extern struct samsung_clk_provider *__init samsung_clk_init(
--
1.9.1
^ permalink raw reply related
* [PATCH v4 0/7] ARM: dts: bcm283x: add and use pinctrl groups
From: Stefan Wahren @ 2016-09-19 11:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1474274603-24215-1-git-send-email-kraxel@redhat.com>
Am 19.09.2016 um 10:43 schrieb Gerd Hoffmann:
> Hi,
>
> New in v4: Patch #6 has been splitted into two: Patch 6 just moves
> pinctrl from &gpio to &sdhci. Removing the empty now alt3 group
> -- including all references as pointed out by Stefan Wahren in review --
> is done by the new patch 7. Patches 1-5 are unchanged.
Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
for the whole series.
Thanks
Stefan
^ permalink raw reply
* [PATCH v7 0/8] CPUs capacity information for heterogeneous systems
From: Juri Lelli @ 2016-09-19 11:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160912072424.GL10409@e106622-lin>
Hi,
On 12/09/16 08:24, Juri Lelli wrote:
> Hi,
>
> this is a ping for people interested in this series. Patches 2,4,7-8
> still needs ACKs.
>
Weekly ping. :-)
Best,
- Juri
> I know it's only been a week since I posted v7, but this series would
> pair nicely with asym cpu capacity support bits already sitting in
> tip/sched/core. I also know that it might be already late for 4.9 merge
> window; nevertheless, still hoping we can make it.
>
^ permalink raw reply
* [PATCH v4 0/2] KVM: ARM: Enable vtimers with user space gic
From: Alexander Graf @ 2016-09-19 11:14 UTC (permalink / raw)
To: linux-arm-kernel
Some systems out there (well, one type in particular - the Raspberry Pi series)
do have virtualization capabilities in the core, but no ARM GIC interrupt
controller.
To run on these systems, the cleanest route is to just handle all
interrupt delivery in user space and only deal with IRQ pins in the core
side in KVM.
This works pretty well already, but breaks when the guest starts to use
architected timers, as these are handled straight inside kernel space today.
This patch set allows user space to receive vtimer events as well as mask
them, so that we can handle all vtimer related interrupt injection from user
space, enabling us to use architected timer with user space gic emulation.
I have successfully run edk2 as well as Linux using these patches on a
Raspberry Pi 3 system with acceptable speed.
A branch with WIP QEMU code can be found here:
https://github.com/agraf/qemu.git no-kvm-irqchip
To use the user space irqchip, just run it with
$ qemu-system-aarch64 -M virt ...
if you're on a non-vgic host system. Or -M virt,kernel-irqchip=off if your
host system has vgic support.
v1 -> v2:
- Add back curly brace that got lost
v2 -> v3:
- Fix "only only" in documentation
- Split patches
- Remove kvm_emulate.h include
v3 -> v4:
- Improve documentation
Alexander Graf (2):
KVM: arm/arm64: Add vcpu ENABLE_CAP functionality
KVM: arm/arm64: Route vtimer events to user space
Documentation/virtual/kvm/api.txt | 34 ++++++++++-
arch/arm/include/asm/kvm_host.h | 3 +
arch/arm/kvm/arm.c | 47 +++++++++++---
arch/arm64/include/asm/kvm_host.h | 3 +
include/uapi/linux/kvm.h | 14 +++++
virt/kvm/arm/arch_timer.c | 125 +++++++++++++++++++++++++++-----------
6 files changed, 183 insertions(+), 43 deletions(-)
--
1.8.5.6
^ permalink raw reply
* [PATCH v4 1/2] KVM: arm/arm64: Add vcpu ENABLE_CAP functionality
From: Alexander Graf @ 2016-09-19 11:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1474283695-212421-1-git-send-email-agraf@suse.de>
In a follow-up patch we will need to enable capabilities on demand for
backwards compatibility. This patch adds the generic framework to handle
vcpu cap enablement to the arm code base.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
Documentation/virtual/kvm/api.txt | 4 +++-
arch/arm/kvm/arm.c | 25 +++++++++++++++++++++++++
2 files changed, 28 insertions(+), 1 deletion(-)
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index 739db9a..23937e0 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -997,7 +997,9 @@ documentation when it pops into existence).
Capability: KVM_CAP_ENABLE_CAP, KVM_CAP_ENABLE_CAP_VM
Architectures: x86 (only KVM_CAP_ENABLE_CAP_VM),
- mips (only KVM_CAP_ENABLE_CAP), ppc, s390
+ mips (only KVM_CAP_ENABLE_CAP), ppc, s390,
+ arm (only KVM_CAP_ENABLE_CAP),
+ arm64 (only KVM_CAP_ENABLE_CAP)
Type: vcpu ioctl, vm ioctl (with KVM_CAP_ENABLE_CAP_VM)
Parameters: struct kvm_enable_cap (in)
Returns: 0 on success; -1 on error
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 75f130e..c84b6ad 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -878,6 +878,23 @@ static int kvm_arm_vcpu_has_attr(struct kvm_vcpu *vcpu,
return ret;
}
+static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
+ struct kvm_enable_cap *cap)
+{
+ int r;
+
+ if (cap->flags)
+ return -EINVAL;
+
+ switch (cap->cap) {
+ default:
+ r = -EINVAL;
+ break;
+ }
+
+ return r;
+}
+
long kvm_arch_vcpu_ioctl(struct file *filp,
unsigned int ioctl, unsigned long arg)
{
@@ -941,6 +958,14 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
return -EFAULT;
return kvm_arm_vcpu_has_attr(vcpu, &attr);
}
+ case KVM_ENABLE_CAP:
+ {
+ struct kvm_enable_cap cap;
+
+ if (copy_from_user(&cap, argp, sizeof(cap)))
+ return -EFAULT;
+ return kvm_vcpu_ioctl_enable_cap(vcpu, &cap);
+ }
default:
return -EINVAL;
}
--
1.8.5.6
^ permalink raw reply related
* [PATCH v4 2/2] KVM: arm/arm64: Route vtimer events to user space
From: Alexander Graf @ 2016-09-19 11:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1474283695-212421-1-git-send-email-agraf@suse.de>
We have 2 modes for dealing with interrupts in the ARM world. We can either
handle them all using hardware acceleration through the vgic or we can emulate
a gic in user space and only drive CPU IRQ pins from there.
Unfortunately, when driving IRQs from user space, we never tell user space
about timer events that may result in interrupt line state changes, so we
lose out on timer events if we run with user space gic emulation.
This patch fixes that by routing vtimer expiration events to user space.
With this patch I can successfully run edk2 and Linux with user space gic
emulation.
Signed-off-by: Alexander Graf <agraf@suse.de>
---
v1 -> v2:
- Add back curly brace that got lost
v2 -> v3:
- Split into patch set
v3 -> v4:
- Improve documentation
---
Documentation/virtual/kvm/api.txt | 30 ++++++++-
arch/arm/include/asm/kvm_host.h | 3 +
arch/arm/kvm/arm.c | 22 ++++---
arch/arm64/include/asm/kvm_host.h | 3 +
include/uapi/linux/kvm.h | 14 +++++
virt/kvm/arm/arch_timer.c | 125 +++++++++++++++++++++++++++-----------
6 files changed, 155 insertions(+), 42 deletions(-)
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index 23937e0..1c0bd86 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -3202,9 +3202,14 @@ struct kvm_run {
/* in */
__u8 request_interrupt_window;
-Request that KVM_RUN return when it becomes possible to inject external
+[x86] Request that KVM_RUN return when it becomes possible to inject external
interrupts into the guest. Useful in conjunction with KVM_INTERRUPT.
+[arm*] Bits set to 1 in here mask IRQ lines that would otherwise potentially
+trigger forever. These lines are available:
+
+ KVM_IRQWINDOW_VTIMER - Masks hw virtual timer irq while in guest
+
__u8 padding1[7];
/* out */
@@ -3519,6 +3524,18 @@ Hyper-V SynIC state change. Notification is used to remap SynIC
event/message pages and to enable/disable SynIC messages/events processing
in userspace.
+ /* KVM_EXIT_ARM_TIMER */
+ struct {
+ __u8 timesource;
+ } arm_timer;
+
+Indicates that a timer triggered that user space needs to handle and
+potentially mask with vcpu->run->request_interrupt_window to allow the
+guest to proceed. This only happens for timers that got enabled through
+KVM_CAP_ARM_TIMER. The following time sources are available:
+
+ KVM_ARM_TIMER_VTIMER - virtual cpu timer
+
/* Fix the size of the union. */
char padding[256];
};
@@ -3739,6 +3756,17 @@ Once this is done the KVM_REG_MIPS_VEC_* and KVM_REG_MIPS_MSA_* registers can be
accessed, and the Config5.MSAEn bit is accessible via the KVM API and also from
the guest.
+6.11 KVM_CAP_ARM_TIMER
+
+Architectures: arm, arm64
+Target: vcpu
+Parameters: args[0] contains a bitmap of timers to select (see 5.)
+
+This capability allows to route per-core timers into user space. When it's
+enabled and no in-kernel interrupt controller is in use, the timers selected
+by args[0] trigger KVM_EXIT_ARM_TIMER guest exits when they are pending,
+unless masked by vcpu->run->request_interrupt_window (see 5.).
+
7. Capabilities that can be enabled on VMs
------------------------------------------
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index de338d9..77d1f73 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -180,6 +180,9 @@ struct kvm_vcpu_arch {
/* Detect first run of a vcpu */
bool has_run_once;
+
+ /* User space wants timer notifications */
+ bool user_space_arm_timers;
};
struct kvm_vm_stat {
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index c84b6ad..57bdb71 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -187,6 +187,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
case KVM_CAP_ARM_PSCI_0_2:
case KVM_CAP_READONLY_MEM:
case KVM_CAP_MP_STATE:
+ case KVM_CAP_ARM_TIMER:
r = 1;
break;
case KVM_CAP_COALESCED_MMIO:
@@ -474,13 +475,7 @@ static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu)
return ret;
}
- /*
- * Enable the arch timers only if we have an in-kernel VGIC
- * and it has been properly initialized, since we cannot handle
- * interrupts from the virtual timer with a userspace gic.
- */
- if (irqchip_in_kernel(kvm) && vgic_initialized(kvm))
- ret = kvm_timer_enable(vcpu);
+ ret = kvm_timer_enable(vcpu);
return ret;
}
@@ -601,6 +596,13 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
run->exit_reason = KVM_EXIT_INTR;
}
+ if (kvm_check_request(KVM_REQ_PENDING_TIMER, vcpu)) {
+ /* Tell user space about the pending vtimer */
+ ret = 0;
+ run->exit_reason = KVM_EXIT_ARM_TIMER;
+ run->arm_timer.timesource = KVM_ARM_TIMER_VTIMER;
+ }
+
if (ret <= 0 || need_new_vmid_gen(vcpu->kvm) ||
vcpu->arch.power_off || vcpu->arch.pause) {
local_irq_enable();
@@ -887,6 +889,12 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
return -EINVAL;
switch (cap->cap) {
+ case KVM_CAP_ARM_TIMER:
+ r = 0;
+ if (cap->args[0] != KVM_ARM_TIMER_VTIMER)
+ return -EINVAL;
+ vcpu->arch.user_space_arm_timers = true;
+ break;
default:
r = -EINVAL;
break;
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 3eda975..3d01481 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -270,6 +270,9 @@ struct kvm_vcpu_arch {
/* Detect first run of a vcpu */
bool has_run_once;
+
+ /* User space wants timer notifications */
+ bool user_space_arm_timers;
};
#define vcpu_gp_regs(v) (&(v)->arch.ctxt.gp_regs)
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 300ef25..00f4948 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -205,6 +205,7 @@ struct kvm_hyperv_exit {
#define KVM_EXIT_S390_STSI 25
#define KVM_EXIT_IOAPIC_EOI 26
#define KVM_EXIT_HYPERV 27
+#define KVM_EXIT_ARM_TIMER 28
/* For KVM_EXIT_INTERNAL_ERROR */
/* Emulate instruction failed. */
@@ -361,6 +362,10 @@ struct kvm_run {
} eoi;
/* KVM_EXIT_HYPERV */
struct kvm_hyperv_exit hyperv;
+ /* KVM_EXIT_ARM_TIMER */
+ struct {
+ __u8 timesource;
+ } arm_timer;
/* Fix the size of the union. */
char padding[256];
};
@@ -870,6 +875,7 @@ struct kvm_ppc_smmu_info {
#define KVM_CAP_S390_USER_INSTR0 130
#define KVM_CAP_MSI_DEVID 131
#define KVM_CAP_PPC_HTM 132
+#define KVM_CAP_ARM_TIMER 133
#ifdef KVM_CAP_IRQ_ROUTING
@@ -1327,4 +1333,12 @@ struct kvm_assigned_msix_entry {
#define KVM_X2APIC_API_USE_32BIT_IDS (1ULL << 0)
#define KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK (1ULL << 1)
+/* Available with KVM_CAP_ARM_TIMER */
+
+/* Bits for run->request_interrupt_window */
+#define KVM_IRQWINDOW_VTIMER (1 << 0)
+
+/* Bits for run->arm_timer.timesource */
+#define KVM_ARM_TIMER_VTIMER (1 << 0)
+
#endif /* __LINUX_KVM_H */
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 4309b60..cbbb50dd 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -170,16 +170,45 @@ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level)
{
int ret;
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
+ struct kvm_run *run = vcpu->run;
- BUG_ON(!vgic_initialized(vcpu->kvm));
+ BUG_ON(irqchip_in_kernel(vcpu->kvm) && !vgic_initialized(vcpu->kvm));
timer->active_cleared_last = false;
timer->irq.level = new_level;
- trace_kvm_timer_update_irq(vcpu->vcpu_id, timer->irq.irq,
+ trace_kvm_timer_update_irq(vcpu->vcpu_id, host_vtimer_irq,
timer->irq.level);
- ret = kvm_vgic_inject_mapped_irq(vcpu->kvm, vcpu->vcpu_id,
- timer->irq.irq,
- timer->irq.level);
+
+ if (irqchip_in_kernel(vcpu->kvm) && vgic_initialized(vcpu->kvm)) {
+ /* Fire the timer in the VGIC */
+
+ ret = kvm_vgic_inject_mapped_irq(vcpu->kvm, vcpu->vcpu_id,
+ timer->irq.irq,
+ timer->irq.level);
+ } else if (!vcpu->arch.user_space_arm_timers) {
+ /* User space has not activated timer use */
+ ret = 0;
+ } else {
+ /*
+ * Set PENDING_TIMER so that user space can handle the event if
+ *
+ * 1) Level is high
+ * 2) The vtimer is not suppressed by user space
+ * 3) We are not in the timer trigger exit path
+ */
+ if (new_level &&
+ !(run->request_interrupt_window & KVM_IRQWINDOW_VTIMER) &&
+ (run->exit_reason != KVM_EXIT_ARM_TIMER)) {
+ /* KVM_REQ_PENDING_TIMER means vtimer triggered */
+ kvm_make_request(KVM_REQ_PENDING_TIMER, vcpu);
+ }
+
+ /* Force a new level high check on next entry */
+ timer->irq.level = 0;
+
+ ret = 0;
+ }
+
WARN_ON(ret);
}
@@ -197,7 +226,8 @@ static int kvm_timer_update_state(struct kvm_vcpu *vcpu)
* because the guest would never see the interrupt. Instead wait
* until we call this function from kvm_timer_flush_hwstate.
*/
- if (!vgic_initialized(vcpu->kvm) || !timer->enabled)
+ if ((irqchip_in_kernel(vcpu->kvm) && !vgic_initialized(vcpu->kvm)) ||
+ !timer->enabled)
return -ENODEV;
if (kvm_timer_should_fire(vcpu) != timer->irq.level)
@@ -275,35 +305,57 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
* to ensure that hardware interrupts from the timer triggers a guest
* exit.
*/
- phys_active = timer->irq.level ||
- kvm_vgic_map_is_active(vcpu, timer->irq.irq);
-
- /*
- * We want to avoid hitting the (re)distributor as much as
- * possible, as this is a potentially expensive MMIO access
- * (not to mention locks in the irq layer), and a solution for
- * this is to cache the "active" state in memory.
- *
- * Things to consider: we cannot cache an "active set" state,
- * because the HW can change this behind our back (it becomes
- * "clear" in the HW). We must then restrict the caching to
- * the "clear" state.
- *
- * The cache is invalidated on:
- * - vcpu put, indicating that the HW cannot be trusted to be
- * in a sane state on the next vcpu load,
- * - any change in the interrupt state
- *
- * Usage conditions:
- * - cached value is "active clear"
- * - value to be programmed is "active clear"
- */
- if (timer->active_cleared_last && !phys_active)
- return;
+ if (irqchip_in_kernel(vcpu->kvm) && vgic_initialized(vcpu->kvm)) {
+ phys_active = timer->irq.level ||
+ kvm_vgic_map_is_active(vcpu, timer->irq.irq);
+
+ /*
+ * We want to avoid hitting the (re)distributor as much as
+ * possible, as this is a potentially expensive MMIO access
+ * (not to mention locks in the irq layer), and a solution for
+ * this is to cache the "active" state in memory.
+ *
+ * Things to consider: we cannot cache an "active set" state,
+ * because the HW can change this behind our back (it becomes
+ * "clear" in the HW). We must then restrict the caching to
+ * the "clear" state.
+ *
+ * The cache is invalidated on:
+ * - vcpu put, indicating that the HW cannot be trusted to be
+ * in a sane state on the next vcpu load,
+ * - any change in the interrupt state
+ *
+ * Usage conditions:
+ * - cached value is "active clear"
+ * - value to be programmed is "active clear"
+ */
+ if (timer->active_cleared_last && !phys_active)
+ return;
+
+ ret = irq_set_irqchip_state(host_vtimer_irq,
+ IRQCHIP_STATE_ACTIVE,
+ phys_active);
+ } else {
+ /* User space tells us whether the timer is in active mode */
+ phys_active = vcpu->run->request_interrupt_window &
+ KVM_IRQWINDOW_VTIMER;
+
+ /* However if the line is high, we exit anyway, so we want
+ * to keep the IRQ masked */
+ phys_active = phys_active || timer->irq.level;
+
+ /*
+ * So we can just explicitly mask or unmask the IRQ, gaining
+ * more compatibility with oddball irq controllers.
+ */
+ if (phys_active)
+ disable_percpu_irq(host_vtimer_irq);
+ else
+ enable_percpu_irq(host_vtimer_irq, 0);
+
+ ret = 0;
+ }
- ret = irq_set_irqchip_state(host_vtimer_irq,
- IRQCHIP_STATE_ACTIVE,
- phys_active);
WARN_ON(ret);
timer->active_cleared_last = !phys_active;
@@ -479,6 +531,10 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu)
if (timer->enabled)
return 0;
+ /* No need to route physical IRQs when we don't use the vgic */
+ if (!irqchip_in_kernel(vcpu->kvm))
+ goto no_vgic;
+
/*
* Find the physical IRQ number corresponding to the host_vtimer_irq
*/
@@ -502,6 +558,7 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu)
if (ret)
return ret;
+no_vgic:
/*
* There is a potential race here between VCPUs starting for the first
--
1.8.5.6
^ permalink raw reply related
* next-20160914 build: 2 failures 3 warnings (next-20160914)
From: Arnd Bergmann @ 2016-09-19 11:30 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160919105429.GK10189@sirena.org.uk>
On Monday, September 19, 2016 11:54:29 AM CEST Mark Brown wrote:
> On Mon, Sep 19, 2016 at 12:31:04PM +0200, Arnd Bergmann wrote:
>
> > My guess is that this is indeed the correct fix, but I don't understand
> > at all what the function does, and Marcin Niestroj said the same thing,
> > he just copied the code from a driver that is always built-in.
>
> Yes, most of the code is copied from regmap-irq. Setting the parent is
> needed for edge triggered interrupts that don't latch state when
> disabled but isn't needed in the general case.
I found this in the tps65217 data sheet:
9.3.7 Interrupt Pin (nINT)
The interrupt pin is used to signal any event or fault
condition to the host processor. Whenever a fault or event
occurs in the IC the corresponding interrupt bit is set in
the INT register, and the open-drain output is pulled low.
The nINT pin is released (returns to Hi-Z state) and fault
bits are cleared when the INT register is read by the
host. However, if a failure persists, the corresponding
INT bit remains set and the nINT pin is pulled low again
after a maximum of 32 ?s.
Interrupt events include pushbutton pressed/released, USB
and AC voltage status change.
The MASK bits in the INT register are used to mask events
from generating interrupts. The MASK settings affect the
nINT pin only and have no impact on protection and
monitor circuits themselves. Note that persisting event
conditions such as ISINK enabled shutdown can cause the
nINT pin to be pulled low for an extended period of
time which can keep the host in a loop trying to resolve
the interrupt. If this behavior is not desired, set the
corresponding mask bit after receiving the interrupt and
keep polling the INT register to see when the event
condition has disappeared. Then unmask the interrupt bit
again.
Does this tell us if it's needed or not?
Arnd
^ permalink raw reply
* [PATCH v3 0/2] KVM: ARM: Enable vtimers with user space gic
From: Christoffer Dall @ 2016-09-19 11:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <43020f1f-6367-6f11-2534-b26ced13b540@suse.de>
On Mon, Sep 19, 2016 at 12:51:46PM +0200, Alexander Graf wrote:
>
>
> On 16.09.16 15:30, Christoffer Dall wrote:
[...]
> >
> > That being said, I'm not categorically against these patches, but I
> > share Marc's view that we've already seen that non-vgic support had been
> > broken for multiple versions without anyone complaining, and without
> > automated testing or substantial interest in the work, the patches
> > really are likely to bit-rot.
>
> I know that it's very hard to grasp from an upstream maintainer
> perspective,
pfff
> but keep in mind where the bulk of execution of kernel code
> lies. The average life cycle of a "stable" Linux distribution's kernel
> is a few years.
>
> So far all regressions in the user space gic code have been found within
> less than 1y of the respective code release. I'd say that counts for
> quite a well used feature.
>
The only report I can think of about this was Pavel using an upstream
kernel for in-house Samsung development on non-public hardware.
But, again, I didn't look at the patches in detail yet, I'm not
categorically against them, I will take a careful look at them like I do
with all patches on the kvmarm list. There's a risk they'll break in
mainline unless we sort out our testing story, and it may just be
something we'll have to live with.
> > But I haven't even looked at the patches in detail, I was just replying
> > to the comment about testing.
>
> Also keep in mind that without the architected timer support (and/or
> without qemu patches than enable user space timers) the user space gic
> support is pretty unusable to most people, so you obviously get less
> reports.
>
I don't disagree with this. I don't know what this has to do with the
part of my mail you're replying to, but I completely agree that the
current userspace irqchip support has limited value.
-Christoffer
^ permalink raw reply
* [PATCH] ARM: dts: sun8i: Add accelerometer to polaroid-mid2407pxe03
From: Maxime Ripard @ 2016-09-19 11:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160919103925.25149-1-hdegoede@redhat.com>
On Mon, Sep 19, 2016 at 12:39:25PM +0200, Hans de Goede wrote:
> Add a dt node describing the mma7660 accelerometer on the
> polaroid-mid2407pxe03 tablet.
>
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Applied, thanks!
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160919/3a0aef41/attachment.sig>
^ permalink raw reply
* [PATCH v3 0/2] KVM: ARM: Enable vtimers with user space gic
From: Alexander Graf @ 2016-09-19 11:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160919075217.nlxdmoicjhmc2hy6@kamzik.localdomain>
On 19.09.16 09:52, Andrew Jones wrote:
> On Fri, Sep 16, 2016 at 09:36:42PM +0200, Alexander Graf wrote:
>>
>>
>>> Am 16.09.2016 um 15:46 schrieb Andrew Jones <drjones@redhat.com>:
>>>
>>>> On Fri, Sep 16, 2016 at 03:30:27PM +0200, Christoffer Dall wrote:
>>>>> On Fri, Sep 16, 2016 at 02:31:42PM +0200, Paolo Bonzini wrote:
>>>>>
>>>>>
>>>>> On 16/09/2016 14:30, Christoffer Dall wrote:
>>>>>>>>> This patch set allows user space to receive vtimer events as well as mask
>>>>>>>>> them, so that we can handle all vtimer related interrupt injection from user
>>>>>>>>> space, enabling us to use architected timer with user space gic emulation.
>>>>>>>>
>>>>>>>> I have already voiced my concerns in the past, including face to face,
>>>>>>>> and I'm going to repeat it: I not keen at all on adding a new userspace
>>>>>>>> interface that is going to bitrot extremely quickly.
>>>>>>>
>>>>>>> You don't have automated tests set up? It's not going to bitrot if you
>>>>>>> test it, either with kvm-unit-tests or just by smoke-testing Linux.
>>>>>>> It's _for_ the raspi, but it's not limited to it.
>>>>>>
>>>>>> Our automated testing situation is not great, no. Something we're
>>>>>> looking at, but have resource problems with.
>>>>>
>>>>> But it's not a good reason to hold back a feature...
>>>>
>>>> I didn't say that exactly, but choosing not to merge something we cannot
>>>> maintain and which we're not paid to look after and where there's a
>>>> minimal interest, is not entirely unreasonable.
>>>>
>>>> That being said, I'm not categorically against these patches, but I
>>>> share Marc's view that we've already seen that non-vgic support had been
>>>> broken for multiple versions without anyone complaining, and without
>>>> automated testing or substantial interest in the work, the patches
>>>> really are likely to bit-rot.
>>>>
>>>> But I haven't even looked at the patches in detail, I was just replying
>>>> to the comment about testing.
>>>
>>> This may be a great time to start encouraging feature writers to submit
>>> kvm-unit-tests patches at the same time as the feature (Hi Alex :-)
>>
>> I actually started off implementing this with the help of kvm-unit-tests. It's awesome!
>>
>> I'm lacking actual irq support to make the test reasonable though and wanted to get the kernel bits out first :). But I'll sit down on that again soon I hope.
>
> I'm glad it looks like a good base for you. I need to get this series
> https://github.com/rhdrjones/kvm-unit-tests/commits/arm/gic refreshed and
> merged, and also it's time to start looking into adding interrupt
> injection to chr-testdev. With those in place I hope it'll be an even
> better base for you.
Awesome. Let me know when you're further ahead with the gic work then so
that we can actually trigger interrupts and measure irq latencies :).
Until then, I sent the simplistic version that I used for bringup to the
list.
Alex
^ permalink raw reply
* [PATCH] ARM: mvebu: let Armada XP also select corediv clk
From: Gregory CLEMENT @ 2016-09-19 11:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1474276961-4645-1-git-send-email-u.kleine-koenig@pengutronix.de>
Hi Uwe,
On lun., sept. 19 2016, Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de> wrote:
> An Armada XP there is also a marvell,armada-370-corediv-clock
> compatible device that is needed to make the nand device work.
Indeed when I acked the commit bd3677ff31a3 ("clk: mvebu: Remove corediv clock from
Armada XP") I missed that the armada-370-corediv-clock compatible sting
was for Armada 370 and Armada XP. We didn't see it until now because I
used the mvebu_v7_defconfig (or the multi_v7_defconfig) where all the
mvebu SoC are enabled.
But the Armada 39x also need it and actually all the SoC selecting
MVEBU_V7 config need this clock.
So I am sending a patch to fix it and it will part of the pull request
to arm-soc for the fix this week.
Thanks,
Gregory
>
> Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
> ---
> arch/arm/mach-mvebu/Kconfig | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
> index f9b6bd306cfe..2979a9c454f6 100644
> --- a/arch/arm/mach-mvebu/Kconfig
> +++ b/arch/arm/mach-mvebu/Kconfig
> @@ -97,6 +97,7 @@ config MACH_ARMADA_XP
> select CPU_PJ4B
> select MACH_MVEBU_V7
> select PINCTRL_ARMADA_XP
> + select MVEBU_CLK_COREDIV
> help
> Say 'Y' here if you want your kernel to support boards based
> on the Marvell Armada XP SoC with device tree.
> --
> 2.8.1
>
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply
* [PATCH] ARM: mvebu: Select corediv clk for all mvebu v7 SoC
From: Gregory CLEMENT @ 2016-09-19 11:52 UTC (permalink / raw)
To: linux-arm-kernel
Since the commit bd3677ff31a3 ("clk: mvebu: Remove corediv clock from
Armada XP"), the corediv clk is no more selected for Armada XP, however
this clock is used for Armada XP using the compatible
armada-370-corediv-clock.
More over even if with the commit 1594d568c6e3 ("clk: mvebu: Move corediv
config to mvebu config"), it was selected for Armada 38x and Armada 375,
it was still not selected for Armada 39x.
Actually all the SoC selecting MVEBU_V7 config need this clock:
git grep "\-corediv-clock" arch/arm/boot/dts
arch/arm/boot/dts/armada-370-xp.dtsi: compatible = "marvell,armada-370-corediv-clock";
arch/arm/boot/dts/armada-375.dtsi: compatible = "marvell,armada-375-corediv-clock";
arch/arm/boot/dts/armada-38x.dtsi: compatible = "marvell,armada-380-corediv-clock";
arch/arm/boot/dts/armada-39x.dtsi: compatible = "marvell,armada-390-corediv-clock"
This commit now fixes this behavior.
Fixes: bd3677ff31a3 ("clk: mvebu: Remove corediv clock from Armada XP")
Cc: stable at vger.kernel.org
Reported-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---
arch/arm/mach-mvebu/Kconfig | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index f9b6bd306cfe..541647f57192 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -23,6 +23,7 @@ config MACH_MVEBU_V7
select CACHE_L2X0
select ARM_CPU_SUSPEND
select MACH_MVEBU_ANY
+ select MVEBU_CLK_COREDIV
config MACH_ARMADA_370
bool "Marvell Armada 370 boards"
@@ -32,7 +33,6 @@ config MACH_ARMADA_370
select CPU_PJ4B
select MACH_MVEBU_V7
select PINCTRL_ARMADA_370
- select MVEBU_CLK_COREDIV
help
Say 'Y' here if you want your kernel to support boards based
on the Marvell Armada 370 SoC with device tree.
@@ -50,7 +50,6 @@ config MACH_ARMADA_375
select HAVE_SMP
select MACH_MVEBU_V7
select PINCTRL_ARMADA_375
- select MVEBU_CLK_COREDIV
help
Say 'Y' here if you want your kernel to support boards based
on the Marvell Armada 375 SoC with device tree.
@@ -68,7 +67,6 @@ config MACH_ARMADA_38X
select HAVE_SMP
select MACH_MVEBU_V7
select PINCTRL_ARMADA_38X
- select MVEBU_CLK_COREDIV
help
Say 'Y' here if you want your kernel to support boards based
on the Marvell Armada 380/385 SoC with device tree.
--
2.9.3
^ 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