* [PATCH] of: Add vendor prefix for Aries Embedded GmbH
From: Marek Vasut @ 2016-10-24 11:38 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160919213800.9498-1-marex@denx.de>
On 09/19/2016 11:38 PM, Marek Vasut wrote:
> Add vendor prefix for Aries Embedded GmbH
> http://www.aries-embedded.de/
>
> Signed-off-by: Marek Vasut <marex@denx.de>
> Cc: Rob Herring <robh@kernel.org>
Hi, bump ?
> ---
> Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
> index 69caf14..522dd65 100644
> --- a/Documentation/devicetree/bindings/vendor-prefixes.txt
> +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
> @@ -27,6 +27,7 @@ analogix Analogix Semiconductor, Inc.
> apm Applied Micro Circuits Corporation (APM)
> aptina Aptina Imaging
> arasan Arasan Chip Systems
> +aries Aries Embedded GmbH
> arm ARM Ltd.
> armadeus ARMadeus Systems SARL
> arrow Arrow Electronics
>
--
Best regards,
Marek Vasut
^ permalink raw reply
* [SPAM][PATCH 3/4] mtk_mdp_m2m: remove an unused struct
From: Minghsiu Tsai @ 2016-10-24 11:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <624b0ea4550b90318ec2293d80b1caa5bafd2a35.1477058332.git.mchehab@s-opensource.com>
On Fri, 2016-10-21 at 11:59 -0200, Mauro Carvalho Chehab wrote:
> drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c:48:33: warning: ?mtk_mdp_size_align? defined but not used [-Wunused-variable]
> static struct mtk_mdp_pix_align mtk_mdp_size_align = {
> ^~~~~~~~~~~~~~~~~~
>
> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
> ---
> drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c | 7 -------
> 1 file changed, 7 deletions(-)
>
> diff --git a/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c b/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c
> index 065502757133..33124a6c9951 100644
> --- a/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c
> +++ b/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c
> @@ -45,13 +45,6 @@ struct mtk_mdp_pix_limit {
> u16 target_rot_en_h;
> };
>
> -static struct mtk_mdp_pix_align mtk_mdp_size_align = {
> - .org_w = 16,
> - .org_h = 16,
> - .target_w = 2,
> - .target_h = 2,
> -};
> -
Hi Mauro,
The structure is used for the format V4L2_PIX_FMT_MT21C which is added
in the later patch.
"[media] media: mtk-mdp: support pixelformat V4L2_PIX_FMT_MT21C"
I just know checkpatch should be run patch by patch, so this warning
message will be generated without the MT21C patch.
I found all mtk-mdp patches have been merged in media tree, so is this
patch still needed?
If yes, remove 'mtk_mdp_size_align' in this patch, and re-added it in
the MT21C patch.
minghsiu
> static const struct mtk_mdp_fmt mtk_mdp_formats[] = {
> {
> .pixelformat = V4L2_PIX_FMT_NV12M,
^ permalink raw reply
* [PATCH 3/4] mtk_mdp_m2m: remove an unused struct
From: Minghsiu Tsai @ 2016-10-24 11:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <624b0ea4550b90318ec2293d80b1caa5bafd2a35.1477058332.git.mchehab@s-opensource.com>
On Fri, 2016-10-21 at 11:59 -0200, Mauro Carvalho Chehab wrote:
> drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c:48:33: warning: ?mtk_mdp_size_align? defined but not used [-Wunused-variable]
> static struct mtk_mdp_pix_align mtk_mdp_size_align = {
> ^~~~~~~~~~~~~~~~~~
>
> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
> ---
> drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c | 7 -------
> 1 file changed, 7 deletions(-)
>
> diff --git a/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c b/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c
> index 065502757133..33124a6c9951 100644
> --- a/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c
> +++ b/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c
> @@ -45,13 +45,6 @@ struct mtk_mdp_pix_limit {
> u16 target_rot_en_h;
> };
>
> -static struct mtk_mdp_pix_align mtk_mdp_size_align = {
> - .org_w = 16,
> - .org_h = 16,
> - .target_w = 2,
> - .target_h = 2,
> -};
> -
Hi Mauro,
The structure is used for the format V4L2_PIX_FMT_MT21C which is added
in the later patch.
"[media] media: mtk-mdp: support pixelformat V4L2_PIX_FMT_MT21C"
I just know checkpatch should be run patch by patch, so this warning
message will be generated without the MT21C patch.
I found all mtk-mdp patches have been merged in media tree, so is this
patch still needed?
If yes, remove 'mtk_mdp_size_align' in this patch, and re-added it in
the MT21C patch.
minghsiu
> static const struct mtk_mdp_fmt mtk_mdp_formats[] = {
> {
> .pixelformat = V4L2_PIX_FMT_NV12M,
^ permalink raw reply
* [PATCH] Documentation: DMA-API: Clarify semantics of dma_set_mask_and_coherent
From: Punit Agrawal @ 2016-10-24 11:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161021150916.0d274e9f@lwn.net>
Jonathan Corbet <corbet@lwn.net> writes:
> On Mon, 17 Oct 2016 16:26:23 +0100
> Punit Agrawal <punit.agrawal@arm.com> wrote:
>
>> The dma mapping api howto gives the impression that using the
>> dma_set_mask_and_coherent (and related DMA APIs) will cause the kernel
>> to check all the components in the path from the device to memory for
>> addressing restrictions. In systems with address translations between
>> the device and memory (e.g., when using IOMMU), this implies that a
>> successful call to set set dma mask has checked the addressing
>> constraints of the intermediaries as well.
>>
>> For the IOMMU drivers in the tree, the check is actually performed while
>> allocating the DMA buffer rather than when the DMA mask is
>> configured. For MMUs that do not support the full device addressing
>> capability, the allocations are made from a reduced address space.
>>
>> Update the documentation to clarify that even though the call to
>> dma_set_mask_and_coherent succeeds, it may not be possible to use the
>> full addressing capability of the device.
>
> OK, so I guess I can buy this. But...
>
>> Signed-off-by: Punit Agrawal <punit.agrawal@arm.com>
>> Cc: Jonathan Corbet <corbet@lwn.net>
>> ---
>> Documentation/DMA-API-HOWTO.txt | 39 +++++++++++++++++++++++----------------
>> 1 file changed, 23 insertions(+), 16 deletions(-)
>>
>> diff --git a/Documentation/DMA-API-HOWTO.txt b/Documentation/DMA-API-HOWTO.txt
>> index 979228b..240d1ee 100644
>> --- a/Documentation/DMA-API-HOWTO.txt
>> +++ b/Documentation/DMA-API-HOWTO.txt
>> @@ -159,39 +159,46 @@ support 64-bit addressing (DAC) for all transactions. And at least
>> one platform (SGI SN2) requires 64-bit consistent allocations to
>> operate correctly when the IO bus is in PCI-X mode.
>>
>> -For correct operation, you must interrogate the kernel in your device
>> -probe routine to see if the DMA controller on the machine can properly
>> -support the DMA addressing limitation your device has. It is good
>> +For correct operation, you must inform the kernel in your device probe
>> +routine to see if the DMA controller on the machine can properly
>> +support the DMA addressing capabilities your device has. It is good
>
> Here it's still saying "to see if the DMA controller on the machine can
> properly support the DMA addressing capabilities your device has". So
> you've not really changed the sense of this sentence here.
You're right - the changes don't go far enough.
How about dropping the bit so that it now reads -
"For correct operation, in your device probe routine, you must inform
the DMA addressing capabilities of your device to the kernel."
>
> If I understand things correctly, the calls in question are storing the
> device's limitations; they will only fail if the kernel is entirely
> unable to work within the indicated range, right? I don't think there's
> ever been any guarantee that the system as a whole could use the entire
> range that is addressable by the device.
That matches my understanding as well. I was just trying to make it more
explicit with this patch.
> I have no objection to making
> that more clear, but let's actually make it more clear by saying what the
> functions are actually doing.
>
> Make sense, or am I missing something here?
Let me know if the change I suggest is an improvement and I'll send out
a v2.
Thanks,
Punit
>
> Thanks,
>
> jon
^ permalink raw reply
* [PATCH] ARM: imx_v6_v7_defconfig: Increase CMA size
From: Shawn Guo @ 2016-10-24 11:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161017163411.11888-1-marex@denx.de>
On Mon, Oct 17, 2016 at 06:34:11PM +0200, Marek Vasut wrote:
> Increase the CMA size to 64 MiB, otherwise it isn't possible to use
> etnaviv driver on systems with 1920x1080 panel due to insufficient
> memory .
>
> Signed-off-by: Marek Vasut <marex@denx.de>
> Cc: Fabio Estevam <fabio.estevam@nxp.com>
> Cc: Shawn Guo <shawnguo@kernel.org>
Applied, thanks.
^ permalink raw reply
* [PATCH] i2c: rk3x: Give the tuning value 0 during rk3x_i2c_v0_calc_timings
From: Andy Yan @ 2016-10-24 11:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477125822-30644-1-git-send-email-david.wu@rock-chips.com>
Hi:
On 2016?10?22? 16:43, David Wu wrote:
> We found a bug that i2c transfer sometimes failed on 3066a board with
> stabel-4.8, the con register would be updated by uninitialized tuning
> value, it made the i2c transfer failed.
>
> So give the tuning value to be zero during rk3x_i2c_v0_calc_timings.
>
> Signed-off-by: David Wu <david.wu@rock-chips.com>
> ---
> drivers/i2c/busses/i2c-rk3x.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
> index 50702c7..df22066 100644
> --- a/drivers/i2c/busses/i2c-rk3x.c
> +++ b/drivers/i2c/busses/i2c-rk3x.c
> @@ -694,6 +694,8 @@ static int rk3x_i2c_v0_calc_timings(unsigned long clk_rate,
> t_calc->div_low--;
> t_calc->div_high--;
>
> + /* Give the tuning value 0, that would not update con register */
> + t_calc->tuning = 0;
> /* Maximum divider supported by hw is 0xffff */
> if (t_calc->div_low > 0xffff) {
> t_calc->div_low = 0xffff;
rk3066a based board can't boot up(with endless i2c irq messages print
out) from linux-4.8 without this fix.
Tested-by: Andy Yan <andy.yan@rock-chips.com>
^ permalink raw reply
* [PATCH] ARM: imx_v6_v7_defconfig: Select the es8328 codec driver
From: Shawn Guo @ 2016-10-24 11:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161017163433.11938-1-marex@denx.de>
On Mon, Oct 17, 2016 at 06:34:33PM +0200, Marek Vasut wrote:
> Select CONFIG_SND_SOC_ES8328 so that we can have audio functional
> by default on Kosagi Novena boards.
>
> Signed-off-by: Marek Vasut <marex@denx.de>
> Cc: Fabio Estevam <fabio.estevam@nxp.com>
> Cc: Shawn Guo <shawnguo@kernel.org>
Applied, thanks.
^ permalink raw reply
* [PATCH] ARM: dts: novena: Enable PWM1
From: Shawn Guo @ 2016-10-24 11:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161017163449.11990-1-marex@denx.de>
On Mon, Oct 17, 2016 at 06:34:49PM +0200, Marek Vasut wrote:
> Enable PWM1, otherwise the backlight cannot work.
>
> Signed-off-by: Marek Vasut <marex@denx.de>
> Cc: Fabio Estevam <fabio.estevam@nxp.com>
> Cc: Shawn Guo <shawnguo@kernel.org>
Applied, thanks.
^ permalink raw reply
* [PATCH 5/5] ARM: dts: Add LEGO MINDSTORTMS EV3 dts
From: Sekhar Nori @ 2016-10-24 11:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477075018-20176-6-git-send-email-david@lechnology.com>
On Saturday 22 October 2016 12:06 AM, David Lechner wrote:
> This adds a device tree definition file for LEGO MINDSTORMS EV3.
Thanks for the patch!
>
> What is working:
>
> * Pin muxing
> * MicroSD card reader
> * UART on input port 1
>
> What is partially working:
>
> * Buttons - working after GPIO fix
> * LEDs - working after GPIO fix
> * Poweroff/reset - working after GPIO fix
Is the GPIO fix something that will go in v4.9-rc cycle ?
> * Flash memory - driver loads but can't read the block devices - this is
> probably due to the fact that we are not able to configure the SPI to
> use DMA via device tree
Hmm, I would not have expected PIO mode to be so inefficient that you
are unable to even read the block device.
> * EEPROM - there seems to be a hardware bug that causes the first byte
> read to be corrupted - this can be worked around by adding an I2C stop
> between writing the register and reading the data, but the at24 driver
> does not have an option to do this
>
> What is not working/to be added later:
>
> * Display - waiting for "tiny DRM" to be mainlined
> * Speaker - needs new PWM sound driver
> * USB - waiting for OHCI and MUSB device tree support to be mainlined
> * ADC - needs new iio driver
> * GPIOs - broken because of recent changes to core gpio driver
> * Bluetooth - needs new driver for sequencing power/enable/clock
> * Input and output ports - need some sort of new phy or extcon driver
> * Battery - needs new power supply driver (depends on ADC iio driver)
>
> Signed-off-by: David Lechner <david@lechnology.com>
> ---
> arch/arm/boot/dts/Makefile | 3 +-
> arch/arm/boot/dts/lego-ev3.dts | 454 +++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 456 insertions(+), 1 deletion(-)
> create mode 100644 arch/arm/boot/dts/lego-ev3.dts
>
> diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
> index f80f5b7..5f91c1a 100644
> --- a/arch/arm/boot/dts/Makefile
> +++ b/arch/arm/boot/dts/Makefile
> @@ -116,7 +116,8 @@ dtb-$(CONFIG_ARCH_CLPS711X) += \
> dtb-$(CONFIG_ARCH_DAVINCI) += \
> da850-lcdk.dtb \
> da850-enbw-cmc.dtb \
> - da850-evm.dtb
> + da850-evm.dtb \
> + lego-ev3.dtb
> dtb-$(CONFIG_ARCH_DIGICOLOR) += \
> cx92755_equinox.dtb
> dtb-$(CONFIG_ARCH_EFM32) += \
> diff --git a/arch/arm/boot/dts/lego-ev3.dts b/arch/arm/boot/dts/lego-ev3.dts
> new file mode 100644
> index 0000000..a6b4c7d
> --- /dev/null
> +++ b/arch/arm/boot/dts/lego-ev3.dts
> @@ -0,0 +1,454 @@
> +/*
> + * Device tree for LEGO MINDSTORMS EV3
> + *
> + * Copyright (C) 2016 David Lechner <david@lechnology.com>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the
> + * Free Software Foundation, version 2.
> + */
> +
> +/dts-v1/;
> +#include <dt-bindings/gpio/gpio.h>
> +#include <dt-bindings/input/linux-event-codes.h>
> +#include <dt-bindings/pwm/pwm.h>
> +
> +#include "da850.dtsi"
> +
> +/ {
> + compatible = "lego,ev3", "ti,da850";
> + model = "LEGO MINDSTORMS EV3";
> +
> + soc at 1c00000 {
> + /*
> + * (ab)using pinctrl-single to disable all internal pullups/
> + * pulldowns on I/O.
> + */
> + pinmux at 22c00c {
> + compatible = "pinctrl-single";
> + reg = <0x22c00c 0x4>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> + pinctrl-single,bit-per-mux;
> + pinctrl-single,register-width = <32>;
> + pinctrl-single,function-mask = <0xf>;
> + /*
> + * There is a bug in pinctrl-single that prevents us
> + * from setting function-mask to 1, so doing things
> + * in groups of 4. Doesn't really matter since we are
> + * disabling all at once anyway.
> + */
> +
> + pinctrl-names = "default";
> + pinctrl-0 = <&pupu_disable>;
> +
> + pupu_disable: pinmux_all_pins {
> + pinctrl-single,bits = <
> + 0x0 0x00000000 0xffffffff
> + >;
> + };
Sigh. This is quite an abuse :)
I know we don't have a good way to configure this in kernel today. And I
am surprised we never had to care about disabling pullups so far. Can
you clarify why you need it? I assume there is some contention you want
to avoid, but on which interface?
I dont think this can be done this way using pinctrl-single. A small
driver to handle pullup/down control for da850 may have to be added to
drivers/pinctrl. It will be better to check with Linus Walleij on his
thoughts using a new thread ccing the pinctrl subsystem list as well.
[...]
> + in1_pins: pinmux_in1_pins {
> + pinctrl-single,bits = <
> + /* GP0[15] */
> + 0x0 0x00000008 0x0000000f
> + /* GP0[2] */
> + 0x4 0x00800000 0x00f00000
> + /* GP2[2] */
> + 0x18 0x00800000 0x00f00000
> + /* GP8[10], GP8[11] */
> + 0x48 0x88000000 0xff000000
> + >;
> + };
I see that this is not really used. Can you add these when you actually
use them. Looks like that applies to some other definitions like this below.
> +&ehrpwm1 {
> + status = "disabled";
Hmm, disabled? Can you add this node when you actually use it?
> + pinctrl-names = "default";
> + /* MBPWM, MAPWM */
> + pinctrl-0 = <&ehrpwm1a_pins>, <&ehrpwm1b_pins>;
> +};
> +
> +&ecap1 {
> + status = "disabled";
same here and other places below.
> + pinctrl-names = "default";
> + /* MDPWM */
> + pinctrl-0 = <&ecap1_pins>;
> +};
> +
> +&spi0 {
> + status = "okay";
> + pinctrl-names = "default";
> + pinctrl-0 = <&spi0_pins>, <&spi0_cs0_pin>, <&spi0_cs3_pin>;
> + dmas = <&edma0 14 0>, <&edma0 15 0>;
> + dma-names = "rx", "tx";
> +
> + spi-flash at 0 {
> + #address-cells = <1>;
> + #size-cells = <1>;
> + compatible = "n25q128a13", "jedec,spi-nor";
> + reg = <0>;
> + spi-max-frequency = <50000000>;
> + ti,spi-wdelay = <8>;
> +
> + partition at 0 {
> + label = "U-Boot";
> + reg = <0 0x40000>;
Thats 256KB for U-Boot and MLO (I assume in concatenated AIS image). Is
that sufficient for future too? Moving partitions later is tough ask
because that means users will lose data when they upgrade the kernel
because of partitions moving around. Just a suggestion to keep future
U-Boot bloat in mind and not use a "just fits" number.
> + };
> +
> + partition at 40000 {
> + label = "U-Boot Env";
> + reg = <0x40000 0x10000>;
> + };
> +
> + partition at 50000 {
> + label = "Kernel";
> + reg = <0x50000 0x200000>;
> + };
> +
> + partition at 250000 {
> + label = "Filesystem";
> + reg = <0x250000 0xa50000>;
> + };
> +
> + partition at cb0000 {
> + label = "Storage";
> + reg = <0xcb0000 0x2f0000>;
> + };
> + };
> +
> + /* TODO: ADC goes here */
I would drop this comment.
> +};
> +
> +&spi1 {
> + status = "okay";
> + pinctrl-names = "default";
> + pinctrl-0 = <&spi1_pins>, <&spi1_cs0_pin>;
> +
> + /* TODO: LCD Display goes here */
Add this node when you actually have display working.
Thanks,
Sekhar
^ permalink raw reply
* [PATCH 2/4] mtk_mdp_vpu: remove a double unlock at the error path
From: Minghsiu Tsai @ 2016-10-24 11:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <768767961c64dea3fdd86132c9eba87ae652d588.1477058332.git.mchehab@s-opensource.com>
On Fri, 2016-10-21 at 11:59 -0200, Mauro Carvalho Chehab wrote:
> As warned by smatch:
> drivers/media/platform/mtk-mdp/mtk_mdp_vpu.c:98 mtk_mdp_vpu_send_msg() error: double unlock 'mutex:&ctx->mdp_dev->vpulock'
>
> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
> ---
> drivers/media/platform/mtk-mdp/mtk_mdp_vpu.c | 1 -
> 1 file changed, 1 deletion(-)
>
> diff --git a/drivers/media/platform/mtk-mdp/mtk_mdp_vpu.c b/drivers/media/platform/mtk-mdp/mtk_mdp_vpu.c
> index b38d29e99f7a..5c8caa864e32 100644
> --- a/drivers/media/platform/mtk-mdp/mtk_mdp_vpu.c
> +++ b/drivers/media/platform/mtk-mdp/mtk_mdp_vpu.c
> @@ -91,7 +91,6 @@ static int mtk_mdp_vpu_send_msg(void *msg, int len, struct mtk_mdp_vpu *vpu,
> mutex_lock(&ctx->mdp_dev->vpulock);
> err = vpu_ipi_send(vpu->pdev, (enum ipi_id)id, msg, len);
> if (err) {
> - mutex_unlock(&ctx->mdp_dev->vpulock);
Hi Mauro,
It has been fixed by Hans in the later patch.
Author: Hans Verkuil <hverkuil@xs4all.nl>
Date: Mon Sep 19 05:00:34 2016 -0300
[media] mtk-mdp: fix double mutex_unlock
Fix smatch error:
media-git/drivers/media/platform/mtk-mdp/mtk_mdp_vpu.c:100
mtk_mdp_vpu_send_msg() error: double unlock 'mutex:&ctx->
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
minghsiu
> dev_err(&ctx->mdp_dev->pdev->dev,
> "vpu_ipi_send fail status %d\n", err);
> }
^ permalink raw reply
* [PATCH] usb: gadget: udc: atmel: fix endpoint name
From: Nicolas Ferre @ 2016-10-24 11:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <874m535dti.fsf@linux.intel.com>
Le 26/09/2016 ? 09:18, Felipe Balbi a ?crit :
>
> Hi,
>
> Greg Kroah-Hartman <gregkh@linuxfoundation.org> writes:
>> On Fri, Sep 23, 2016 at 04:20:45PM +0200, Nicolas Ferre wrote:
>>> Le 16/09/2016 ? 10:36, Nicolas Ferre a ?crit :
>>>> Le 15/09/2016 ? 17:07, Alexandre Belloni a ?crit :
>>>>> Since commit c32b5bcfa3c4 ("ARM: dts: at91: Fix USB endpoint nodes"),
>>>>> atmel_usba_udc fails with:
>>>>>
>>>>> ------------[ cut here ]------------
>>>>> WARNING: CPU: 0 PID: 0 at include/linux/usb/gadget.h:405
>>>>> ecm_do_notify+0x188/0x1a0
>>>>> Modules linked in:
>>>>> CPU: 0 PID: 0 Comm: swapper Not tainted 4.7.0+ #15
>>>>> Hardware name: Atmel SAMA5
>>>>> [<c010ccfc>] (unwind_backtrace) from [<c010a7ec>] (show_stack+0x10/0x14)
>>>>> [<c010a7ec>] (show_stack) from [<c0115c10>] (__warn+0xe4/0xfc)
>>>>> [<c0115c10>] (__warn) from [<c0115cd8>] (warn_slowpath_null+0x20/0x28)
>>>>> [<c0115cd8>] (warn_slowpath_null) from [<c04377ac>] (ecm_do_notify+0x188/0x1a0)
>>>>> [<c04377ac>] (ecm_do_notify) from [<c04379a4>] (ecm_set_alt+0x74/0x1ac)
>>>>> [<c04379a4>] (ecm_set_alt) from [<c042f74c>] (composite_setup+0xfc0/0x19f8)
>>>>> [<c042f74c>] (composite_setup) from [<c04356e8>] (usba_udc_irq+0x8f4/0xd9c)
>>>>> [<c04356e8>] (usba_udc_irq) from [<c013ec9c>] (handle_irq_event_percpu+0x9c/0x158)
>>>>> [<c013ec9c>] (handle_irq_event_percpu) from [<c013ed80>] (handle_irq_event+0x28/0x3c)
>>>>> [<c013ed80>] (handle_irq_event) from [<c01416d4>] (handle_fasteoi_irq+0xa0/0x168)
>>>>> [<c01416d4>] (handle_fasteoi_irq) from [<c013e3f8>] (generic_handle_irq+0x24/0x34)
>>>>> [<c013e3f8>] (generic_handle_irq) from [<c013e640>] (__handle_domain_irq+0x54/0xa8)
>>>>> [<c013e640>] (__handle_domain_irq) from [<c010b214>] (__irq_svc+0x54/0x70)
>>>>> [<c010b214>] (__irq_svc) from [<c0107eb0>] (arch_cpu_idle+0x38/0x3c)
>>>>> [<c0107eb0>] (arch_cpu_idle) from [<c0137300>] (cpu_startup_entry+0x9c/0xdc)
>>>>> [<c0137300>] (cpu_startup_entry) from [<c0900c40>] (start_kernel+0x354/0x360)
>>>>> [<c0900c40>] (start_kernel) from [<20008078>] (0x20008078)
>>>>> ---[ end trace e7cf9dcebf4815a6 ]---
>>>>>
>>>>> Fixes: c32b5bcfa3c4 ("ARM: dts: at91: Fix USB endpoint nodes")
>>>>> Reported-by: Richard Genoud <richard.genoud@gmail.com>
>>>>> Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
>>>>
>>>> Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
>>>>
>>>> Felipe, Greg,
>>>> It is clearly a regression and material for 4.8-fixes. But I do know
>>>> that we are very late in the process :-(
>>>> Please do what you can to make it progress before 4.8-final but I'm
>>>> truly aware of the challenge.
>>>
>>> Any chance that we can have it (aka ping)?
>>
>> It's Felipe's area, not mine :)
>
> Sorry, I had missed this one. Greg, seems like this would be the only
> pending fix. Do you want it in a pull request or would you prefer to
> just pick it up as a patch? Works either way for me. In case you decide
> to pick it up as a patch:
>
> Acked-by: Felipe Balbi <felipe.balbi@linux.intel.com>
>
> If you prefer to pick it up as a pull request, I already have the patch
> in my 'fixes' branch, just need to tag it and send it to you.
Felipe,
We agreed to delay this patch after the merge window is closed. But I
feel that it's beginning to be urgent to make this patch go forward:
actual users of our kernel are facing the issue:
https://lkml.org/lkml/2016/10/17/493
We're already at -rc2 and I don't see USB-fixes included...
Best regards,
--
Nicolas Ferre
^ permalink raw reply
* [PATCH] ARM: dts: vf610: fix IRQ flag of global timer
From: Shawn Guo @ 2016-10-24 12:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161018015127.16981-1-stefan@agner.ch>
On Mon, Oct 17, 2016 at 06:51:27PM -0700, Stefan Agner wrote:
> The global timer IRQ (PPI[0], PPI 11 in device tree terms) is a
> rising edge interrupt. The ARM Cortex-A5 MPCore TRM in Chapter
> 10.1.2. Interrupt types and sources says:
> "Interrupt is rising-edge sensitive."
>
> The bits seem to be read-only, hence this missconfiguration had
> no negative effect. However, with commit 992345a58e0c
> ("irqchip/gic: WARN if setting the interrupt type for a PPI fails")
> warnings such as this get printed:
> GIC: PPI11 is secure or misconfigured
>
> With this change the new configuration matches the default
> configuration and no warning is printed anymore.
>
> Signed-off-by: Stefan Agner <stefan@agner.ch>
Applied, thanks.
^ permalink raw reply
* [PATCH v1] char: hw_random: atmel-rng: disable TRNG during suspend
From: Nicolas Ferre @ 2016-10-24 12:07 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477296208-28335-1-git-send-email-wenyou.yang@atmel.com>
Le 24/10/2016 ? 10:03, Wenyou Yang a ?crit :
> To fix the over consumption on the VDDCore due to the TRNG enabled,
> disable the TRNG during suspend, not only disable the user interface
> clock (which is controlled by PMC). Because the user interface clock
> is independent from any clock that may be used in the entropy source
> logic circuitry.
>
> Signed-off-by: Wenyou Yang <wenyou.yang@atmel.com>
> ---
>
> drivers/char/hw_random/atmel-rng.c | 16 ++++++++++++++--
> 1 file changed, 14 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/char/hw_random/atmel-rng.c b/drivers/char/hw_random/atmel-rng.c
> index 0fcc9e6..2e2d09a 100644
> --- a/drivers/char/hw_random/atmel-rng.c
> +++ b/drivers/char/hw_random/atmel-rng.c
> @@ -48,6 +48,16 @@ static int atmel_trng_read(struct hwrng *rng, void *buf, size_t max,
> return 0;
> }
>
> +static void atmel_trng_enable(struct atmel_trng *trng)
> +{
> + writel(TRNG_KEY | 1, trng->base + TRNG_CR);
> +}
> +
> +static void atmel_trng_disable(struct atmel_trng *trng)
> +{
> + writel(TRNG_KEY, trng->base + TRNG_CR);
> +}
> +
> static int atmel_trng_probe(struct platform_device *pdev)
> {
> struct atmel_trng *trng;
> @@ -71,7 +81,7 @@ static int atmel_trng_probe(struct platform_device *pdev)
> if (ret)
> return ret;
>
> - writel(TRNG_KEY | 1, trng->base + TRNG_CR);
> + atmel_trng_enable(trng);
> trng->rng.name = pdev->name;
> trng->rng.read = atmel_trng_read;
>
> @@ -94,7 +104,7 @@ static int atmel_trng_remove(struct platform_device *pdev)
>
> hwrng_unregister(&trng->rng);
>
> - writel(TRNG_KEY, trng->base + TRNG_CR);
> + atmel_trng_disable(trng);
> clk_disable_unprepare(trng->clk);
>
> return 0;
> @@ -105,6 +115,7 @@ static int atmel_trng_suspend(struct device *dev)
> {
> struct atmel_trng *trng = dev_get_drvdata(dev);
>
> + atmel_trng_disable(trng);
> clk_disable_unprepare(trng->clk);
>
> return 0;
> @@ -114,6 +125,7 @@ static int atmel_trng_resume(struct device *dev)
> {
> struct atmel_trng *trng = dev_get_drvdata(dev);
>
> + atmel_trng_enable(trng);
> return clk_prepare_enable(trng->clk);
Isn't it the other way around:
enable the user interface first, then enable the internal clock? like:
clk_prepare_enable(trng->clk);
atmel_trng_enable(trng);
Regards,
--
Nicolas Ferre
^ permalink raw reply
* [PATCH] kernel: irq: fix build failure
From: Lee Jones @ 2016-10-24 12:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161024223231.5cdbb2ac@canb.auug.org.au>
On Mon, 24 Oct 2016, Stephen Rothwell wrote:
> On Mon, 24 Oct 2016 11:22:15 +0100 Lee Jones <lee.jones@linaro.org> wrote:
> > On Fri, 21 Oct 2016, Thomas Gleixner wrote:
> >
> > > On Fri, 21 Oct 2016, Stephen Rothwell wrote:
> > > > On Thu, 20 Oct 2016 14:55:45 +0200 (CEST) Thomas Gleixner <tglx@linutronix.de> wrote:
> > > > > I know. This is under discussion with the driver folks as we are not going
> > > > > to blindly export stuff just because someone slapped a irq_set_parent()
> > > > > into the code w/o knowing why.
> > > >
> > > > Do we have any idea if a resolution is close. This was first reported
> > > > in linux-next in September 14/15. :-(
> > >
> > > Grr. Yes. As much as I hate it, I'll go and export it for now. Should be
> > > able to get it into rc2.
> >
> > Did this get in? I still have people complaining about it.
>
> It is in -rc2. Commit 3118dac501bc.
Ah, I was searching for patches authored my Thomas.
I see it now, thanks.
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
^ permalink raw reply
* [PATCH v3 0/5] Add runtime PM support for clocks (on Exynos SoC example)
From: Marek Szyprowski @ 2016-10-24 12:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CGME20161024121224eucas1p1070b72308dc9c8d8d2b10fa5bfeaf5ed@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.9-clocks-pm-v3
Patches are based on vanilla v4.9-rc1 kernel.
Best regards
Marek Szyprowski
Samsung R&D Institute Poland
Changelog:
v3:
- Removed CLK_RUNTIME_PM flag, core now simply checks if runtime pm is enabled
for the provided device during clock registration as suggested by Ulf
- Simplified code for exynos4412 isp clock driver registration
- Resolved some other minor issues pointed by Ulf clk core code
- Rebased onto v4.9-rc1 and new version of IOMMU deferred probe patchset
v2: https://www.spinics.net/lists/arm-kernel/msg532798.html
- 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 | 111 +++++-
drivers/clk/samsung/clk-exynos4.c | 211 +++++++----
drivers/clk/samsung/clk-exynos5433.c | 390 +++++++++++++++++----
drivers/clk/samsung/clk-pll.c | 2 +-
drivers/clk/samsung/clk.c | 12 +-
drivers/clk/samsung/clk.h | 7 +
8 files changed, 605 insertions(+), 155 deletions(-)
--
1.9.1
^ permalink raw reply
* [PATCH v3 1/5] clk: add support for runtime pm
From: Marek Szyprowski @ 2016-10-24 12:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477311130-6534-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.
2. Ensure to enable runtime PM for that device before registering clocks.
3. Make sure that 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 | 111 +++++++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 101 insertions(+), 10 deletions(-)
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 0fb39fe217d1..3cf202ccf5a9 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,20 @@ 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);
+ if (clk_pm_runtime_get(core) == 0) {
+ status = core->ops->is_prepared(core->hw);
+ clk_pm_runtime_put(core);
+ } else {
+ status = false;
+ }
+
+ 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 +202,30 @@ 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 clock controller's device is runtime active 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 places.
+ */
+ if (core->dev) {
+ pm_runtime_get_noresume(core->dev);
+ if (!pm_runtime_active(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 +545,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 +588,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 +603,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 +810,9 @@ static void clk_unprepare_unused_subtree(struct clk_core *core)
if (core->flags & CLK_IGNORE_UNUSED)
return;
+ if (clk_pm_runtime_get(core))
+ return;
+
if (clk_core_is_prepared(core)) {
trace_clk_unprepare(core);
if (core->ops->unprepare_unused)
@@ -753,6 +821,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 +838,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))
+ goto unprepare_out;
+
flags = clk_enable_lock();
if (core->enable_count)
@@ -792,6 +865,8 @@ static void clk_disable_unused_subtree(struct clk_core *core)
unlock_out:
clk_enable_unlock(flags);
+ clk_pm_runtime_put(core);
+unprepare_out:
if (core->flags & CLK_OPS_PARENT_ENABLE)
clk_core_disable_unprepare(core->parent);
}
@@ -1563,6 +1638,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 +1655,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 +1907,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 +1929,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();
@@ -2549,6 +2638,8 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
goto fail_name;
}
core->ops = hw->init->ops;
+ if (dev && pm_runtime_enabled(dev))
+ core->dev = dev;
if (dev && dev->driver)
core->owner = dev->driver->owner;
core->hw = hw;
--
1.9.1
^ permalink raw reply related
* [PATCH v3 2/5] clock: samsung: add support for runtime pm
From: Marek Szyprowski @ 2016-10-24 12:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477311130-6534-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.
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
drivers/clk/samsung/clk-pll.c | 2 +-
drivers/clk/samsung/clk.c | 12 ++++++------
drivers/clk/samsung/clk.h | 1 +
3 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
index 9617825daabb..f5249a7e545d 100644
--- a/drivers/clk/samsung/clk-pll.c
+++ b/drivers/clk/samsung/clk-pll.c
@@ -1345,7 +1345,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..e6923714f024 100644
--- a/drivers/clk/samsung/clk.c
+++ b/drivers/clk/samsung/clk.c
@@ -143,7 +143,7 @@ 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,
+ clk = clk_register_fixed_rate(ctx->dev, list->name,
list->parent_name, list->flags, list->fixed_rate);
if (IS_ERR(clk)) {
pr_err("%s: failed to register clock %s\n", __func__,
@@ -172,7 +172,7 @@ 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,
+ clk = clk_register_fixed_factor(ctx->dev, list->name,
list->parent_name, list->flags, list->mult, list->div);
if (IS_ERR(clk)) {
pr_err("%s: failed to register clock %s\n", __func__,
@@ -193,7 +193,7 @@ 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,
+ clk = clk_register_mux(ctx->dev, list->name, list->parent_names,
list->num_parents, list->flags,
ctx->reg_base + list->offset,
list->shift, list->width, list->mux_flags, &ctx->lock);
@@ -226,13 +226,13 @@ void __init samsung_clk_register_div(struct samsung_clk_provider *ctx,
for (idx = 0; idx < nr_clk; idx++, list++) {
if (list->table)
- clk = clk_register_divider_table(NULL, list->name,
+ clk = clk_register_divider_table(ctx->dev, list->name,
list->parent_name, list->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,
+ clk = clk_register_divider(ctx->dev, list->name,
list->parent_name, list->flags,
ctx->reg_base + list->offset, list->shift,
list->width, list->div_flags, &ctx->lock);
@@ -264,7 +264,7 @@ 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,
+ clk = clk_register_gate(ctx->dev, list->name, list->parent_name,
list->flags, ctx->reg_base + list->offset,
list->bit_idx, list->gate_flags, &ctx->lock);
if (IS_ERR(clk)) {
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 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 v3 3/5] clocks: exynos4x12: add runtime pm support for ISP clocks
From: Marek Szyprowski @ 2016-10-24 12:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477311130-6534-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 | 211 +++++++++++++++------
2 files changed, 172 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..e5165be348ef 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 @@ enum exynos4_plls {
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 @@ enum exynos4_plls {
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 void __init exynos4_clk_sleep_init(void) {}
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 void __init exynos4_clk_sleep_init(void) {}
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,100 @@ static void __init exynos4x12_core_down_clock(void)
{ 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;
+
+ exynos4x12_save_isp = samsung_clk_alloc_reg_dump(exynos4x12_clk_isp_save,
+ ARRAY_SIZE(exynos4x12_clk_isp_save));
+ if (!exynos4x12_save_isp)
+ return -ENOMEM;
+
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+
+ 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));
+
+ 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)
+{
+ if (!exynos4412_clk_node)
+ return 0;
+
+ of_platform_populate(exynos4412_clk_node, NULL, NULL, NULL);
+ return platform_driver_register(&exynos4x12_isp_clk_driver);
+}
+arch_initcall(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 +1616,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 v3 4/5] ARM: dts: exynos: add support for ISP power domain to exynos4x12 clocks device
From: Marek Szyprowski @ 2016-10-24 12:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477311130-6534-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 0074f566cd3b..5667fd33dc98 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 v3 5/5] clocks: exynos5433: add runtime pm support
From: Marek Szyprowski @ 2016-10-24 12:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1477311130-6534-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 | 390 ++++++++++++++++++++++++++++-------
drivers/clk/samsung/clk.h | 6 +
2 files changed, 319 insertions(+), 77 deletions(-)
diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c
index ea1608682d7f..40531652a5a6 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 void __init exynos5433_cmu_fsys_init(struct device_node *np)
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 void __init exynos5433_cmu_fsys_init(struct device_node *np)
.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 void __init exynos5433_cmu_g2d_init(struct device_node *np)
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 void __init exynos5433_cmu_g2d_init(struct device_node *np)
.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 void __init exynos5433_cmu_disp_init(struct device_node *np)
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 void __init exynos5433_cmu_disp_init(struct device_node *np)
.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 void __init exynos5433_cmu_aud_init(struct device_node *np)
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 void __init exynos5433_cmu_aud_init(struct device_node *np)
.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 void __init exynos5433_cmu_g3d_init(struct device_node *np)
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 void __init exynos5433_cmu_g3d_init(struct device_node *np)
.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 void __init exynos5433_cmu_atlas_init(struct device_node *np)
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 void __init exynos5433_cmu_atlas_init(struct device_node *np)
.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 void __init exynos5433_cmu_mscl_init(struct device_node *np)
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 void __init exynos5433_cmu_mscl_init(struct device_node *np)
.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 void __init exynos5433_cmu_mfc_init(struct device_node *np)
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 void __init exynos5433_cmu_mfc_init(struct device_node *np)
.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 void __init exynos5433_cmu_hevc_init(struct device_node *np)
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 void __init exynos5433_cmu_hevc_init(struct device_node *np)
.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 void __init exynos5433_cmu_isp_init(struct device_node *np)
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 void __init exynos5433_cmu_isp_init(struct device_node *np)
.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 void __init exynos5433_cmu_cam0_init(struct device_node *np)
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,227 @@ static void __init exynos5433_cmu_cam0_init(struct device_node *np)
.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->clk_name)
+ data->clk = clk_get(dev, info->clk_name);
+ clk_prepare_enable(data->clk);
+
+ platform_set_drvdata(pdev, data);
+
+ /*
+ * Enable runtime pm here, so clock core with use runtime pm for all
+ * registered clocks.
+ */
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+
+ 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);
+
+ 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 1/2] ARM: dts: imx6ul: Add DTS for liteSOM module
From: Shawn Guo @ 2016-10-24 12:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161021150717.27573-1-m.niestroj@grinn-global.com>
On Fri, Oct 21, 2016 at 05:07:16PM +0200, Marcin Niestroj wrote:
> This is a SOM (System on Module), so it will be part of another boards.
> Hence, this is a "dtsi" file that will be included from another device
> tree files.
>
> Hardware specification:
> * Freescale i.MX6UL SoC
> * up to 512 MB RAM
> * eMMC on uSDHC2
>
> Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
> Reviewed-by: Fabio Estevam <fabio.estevam@nxp.com>
Applied both, thanks.
^ permalink raw reply
* [PATCH v5 02/23] of: device: Export of_device_{get_modalias, uvent_modalias} to modules
From: Chen-Yu Tsai @ 2016-10-24 12:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161018015636.11701-3-stephen.boyd@linaro.org>
Hi,
On Tue, Oct 18, 2016 at 9:56 AM, Stephen Boyd <stephen.boyd@linaro.org> wrote:
> The ULPI bus can be built as a module, and it will soon be
> calling these functions when it supports probing devices from DT.
> Export them so they can be used by the ULPI module.
>
> Acked-by: Rob Herring <robh@kernel.org>
> Cc: <devicetree@vger.kernel.org>
> Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
> ---
> drivers/of/device.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/drivers/of/device.c b/drivers/of/device.c
> index 8a22a253a830..6719ab35b62e 100644
> --- a/drivers/of/device.c
> +++ b/drivers/of/device.c
> @@ -225,6 +225,7 @@ ssize_t of_device_get_modalias(struct device *dev, char *str, ssize_t len)
>
> return tsize;
> }
> +EXPORT_SYMBOL_GPL(of_device_get_modalias);
>
> int of_device_request_module(struct device *dev)
> {
> @@ -290,6 +291,7 @@ void of_device_uevent(struct device *dev, struct kobj_uevent_env *env)
> }
> mutex_unlock(&of_mutex);
> }
> +EXPORT_SYMBOL_GPL(of_device_uevent_modalias);
This is trailing the wrong function.
ChenYu
>
> int of_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env)
> {
> --
> 2.10.0.297.gf6727b0
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH] usb: gadget: udc: atmel: fix endpoint name
From: Alexandre Belloni @ 2016-10-24 12:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <935cce30-cf9d-4605-1f3e-ac8e934993e6@atmel.com>
On 24/10/2016 at 13:59:47 +0200, Nicolas Ferre wrote :
> > Acked-by: Felipe Balbi <felipe.balbi@linux.intel.com>
> >
> > If you prefer to pick it up as a pull request, I already have the patch
> > in my 'fixes' branch, just need to tag it and send it to you.
>
> Felipe,
>
> We agreed to delay this patch after the merge window is closed. But I
> feel that it's beginning to be urgent to make this patch go forward:
> actual users of our kernel are facing the issue:
>
> https://lkml.org/lkml/2016/10/17/493
>
> We're already at -rc2 and I don't see USB-fixes included...
>
It is in Greg's branch:
http://git.kernel.org/cgit/linux/kernel/git/gregkh/usb.git/log/?h=usb-linus
--
Alexandre Belloni, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
^ permalink raw reply
* [PATCH V3 0/8] IOMMU probe deferral support
From: Sricharan @ 2016-10-24 12:30 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <b9e4e81f-3b3e-951f-df62-d640275aae71@samsung.com>
Hi Marek,
>>>> Initial post from Laurent Pinchart[1]. This is
>>>> series calls the dma ops configuration for the devices
>>>> at a generic place so that it works for all busses.
>>>> The dma_configure_ops for a device is now called during
>>>> the device_attach callback just before the probe of the
>>>> bus/driver is called. Similarly dma_deconfigure is called during
>>>> device/driver_detach path.
>>>>
>>>>
>>>> pci_bus_add_devices (platform/amba)(_device_create/driver_register)
>>>> | |
>>>> pci_bus_add_device (device_add/driver_register)
>>>> | |
>>>> device_attach device_initial_probe
>>>> | |
>>>> __device_attach_driver __device_attach_driver
>>>> |
>>>> driver_probe_device
>>>> |
>>>> really_probe
>>>> |
>>>> dma_configure
>>>>
>>>> Similarly on the device/driver_unregister path __device_release_driver is
>>>> called which inturn calls dma_deconfigure.
>>>>
>>>> If the ACPI bus code follows the same, we can add acpi_dma_configure
>>>> at the same place as of_dma_configure.
>>>>
>>>> This series is based on the recently merged Generic DT bindings for
>>>> PCI IOMMUs and ARM SMMU from Robin Murphy robin.murphy at arm.com [2]
>>>>
>>>> This time tested this with platform and pci device for probe deferral
>>>> and reprobe on arm64 based platform. There is an issue on the cleanup
>>>> path for arm64 though, where there is WARN_ON if the dma_ops is reset while
>>>> device is attached to an domain in arch_teardown_dma_ops.
>>>> But with iommu_groups created from the iommu driver, the device is always
>>>> attached to a domain/default_domain. So so the WARN has to be removed/handled
>>>> probably.
>>> Thanks for continuing work on this feature! Your can add my:
>>>
>>> Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
>>>
>> Thanks for testing this. So the for the below fix, the remove_device callback
>> gets called on the dma_ops cleanup path, so would it be easy to remove the
>> data for the device there ?
>
>I assumed that IOMMU driver cannot be removed reliably, so all
>structures that it
>creates are permanent. I didn't use device_add()/device_remove()
>callbacks, because
>in current implementation device_add() is called too late (after
>dma-mapping glue
>triggers device_attach_iommu()).
>
>Maybe once your patchset is merged, I will move creation and management
>of the all
>IOMMU related structures to device_add/remove callbacks.
>
ok understand it.
Regards,
Sricharan
^ permalink raw reply
* [PATCH] ARM: imx: mach-imx6q: Fix the PHY ID mask for AR8031
From: Fabio Estevam @ 2016-10-24 12:32 UTC (permalink / raw)
To: linux-arm-kernel
From: Fabio Estevam <fabio.estevam@nxp.com>
AR8031 and AR8035 have the same PHY ID mask of 0xffffffef.
So fix it and make it match with the PHY ID mask definition
at drivers/net/phy/at803x.c.
Signed-off-by: Fabio Estevam <fabio.estevam@nxp.com>
---
arch/arm/mach-imx/mach-imx6q.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index 97fd251..45801b2 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -173,7 +173,7 @@ static void __init imx6q_enet_phy_init(void)
ksz9021rn_phy_fixup);
phy_register_fixup_for_uid(PHY_ID_KSZ9031, MICREL_PHY_ID_MASK,
ksz9031rn_phy_fixup);
- phy_register_fixup_for_uid(PHY_ID_AR8031, 0xffffffff,
+ phy_register_fixup_for_uid(PHY_ID_AR8031, 0xffffffef,
ar8031_phy_fixup);
phy_register_fixup_for_uid(PHY_ID_AR8035, 0xffffffef,
ar8035_phy_fixup);
--
2.7.4
^ 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