* [PATCH v3 5/6] dmaengine: imx-sdma: remove the maximum limation for bd numbers
From: Sascha Hauer @ 2018-06-13 9:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1528729173-28684-6-git-send-email-yibin.gong@nxp.com>
In the subject: s/limation/limitation/
Sascha
On Mon, Jun 11, 2018 at 10:59:32PM +0800, Robin Gong wrote:
> No this limitation now after virtual dma used since bd is allocated
> dynamically instead of static.
>
> Signed-off-by: Robin Gong <yibin.gong@nxp.com>
> ---
> drivers/dma/imx-sdma.c | 14 --------------
> 1 file changed, 14 deletions(-)
>
> diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
> index f150b38..0b0588d2 100644
> --- a/drivers/dma/imx-sdma.c
> +++ b/drivers/dma/imx-sdma.c
> @@ -292,7 +292,6 @@ struct sdma_context_data {
> u32 scratch7;
> } __attribute__ ((packed));
>
> -#define NUM_BD (int)(PAGE_SIZE / sizeof(struct sdma_buffer_descriptor))
>
> struct sdma_engine;
>
> @@ -1296,13 +1295,6 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
> if (ret)
> goto err_bd_out;
>
> - if (sg_len > NUM_BD) {
> - dev_err(sdma->dev, "SDMA channel %d: maximum number of sg exceeded: %d > %d\n",
> - channel, sg_len, NUM_BD);
> - ret = -EINVAL;
> - goto err_bd_out;
> - }
> -
> desc->chn_count = 0;
> for_each_sg(sgl, sg, sg_len, i) {
> struct sdma_buffer_descriptor *bd = &desc->bd[i];
> @@ -1412,12 +1404,6 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
> if (ret)
> goto err_bd_out;
>
> - if (num_periods > NUM_BD) {
> - dev_err(sdma->dev, "SDMA channel %d: maximum number of sg exceeded: %d > %d\n",
> - channel, num_periods, NUM_BD);
> - goto err_bd_out;
> - }
> -
> if (period_len > 0xffff) {
> dev_err(sdma->dev, "SDMA channel %d: maximum period size exceeded: %zu > %d\n",
> channel, period_len, 0xffff);
> --
> 2.7.4
>
>
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply
* [PATCH v2] media: stm32-dcmi: add power saving support
From: Hugues Fruchet @ 2018-06-13 9:59 UTC (permalink / raw)
To: linux-arm-kernel
Implements runtime & system sleep power management ops.
Signed-off-by: Hugues Fruchet <hugues.fruchet@st.com>
---
version 2:
- Fix missing include file detected by kbuild on i386 & sparc64 arch:
- https://www.mail-archive.com/linux-media at vger.kernel.org/msg132766.html
- https://www.mail-archive.com/linux-media at vger.kernel.org/msg132771.html
drivers/media/platform/stm32/stm32-dcmi.c | 81 +++++++++++++++++++++++++------
1 file changed, 65 insertions(+), 16 deletions(-)
diff --git a/drivers/media/platform/stm32/stm32-dcmi.c b/drivers/media/platform/stm32/stm32-dcmi.c
index 2e1933d..2ecf00e 100644
--- a/drivers/media/platform/stm32/stm32-dcmi.c
+++ b/drivers/media/platform/stm32/stm32-dcmi.c
@@ -22,7 +22,9 @@
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_graph.h>
+#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/reset.h>
#include <linux/videodev2.h>
@@ -578,9 +580,9 @@ static int dcmi_start_streaming(struct vb2_queue *vq, unsigned int count)
u32 val = 0;
int ret;
- ret = clk_enable(dcmi->mclk);
+ ret = pm_runtime_get_sync(dcmi->dev);
if (ret) {
- dev_err(dcmi->dev, "%s: Failed to start streaming, cannot enable clock\n",
+ dev_err(dcmi->dev, "%s: Failed to start streaming, cannot get sync\n",
__func__);
goto err_release_buffers;
}
@@ -590,7 +592,7 @@ static int dcmi_start_streaming(struct vb2_queue *vq, unsigned int count)
if (ret && ret != -ENOIOCTLCMD) {
dev_err(dcmi->dev, "%s: Failed to start streaming, subdev streamon error",
__func__);
- goto err_disable_clock;
+ goto err_pm_put;
}
spin_lock_irq(&dcmi->irqlock);
@@ -675,8 +677,8 @@ static int dcmi_start_streaming(struct vb2_queue *vq, unsigned int count)
err_subdev_streamoff:
v4l2_subdev_call(dcmi->entity.subdev, video, s_stream, 0);
-err_disable_clock:
- clk_disable(dcmi->mclk);
+err_pm_put:
+ pm_runtime_put(dcmi->dev);
err_release_buffers:
spin_lock_irq(&dcmi->irqlock);
@@ -749,7 +751,7 @@ static void dcmi_stop_streaming(struct vb2_queue *vq)
/* Stop all pending DMA operations */
dmaengine_terminate_all(dcmi->dma_chan);
- clk_disable(dcmi->mclk);
+ pm_runtime_put(dcmi->dev);
if (dcmi->errors_count)
dev_warn(dcmi->dev, "Some errors found while streaming: errors=%d (overrun=%d), buffers=%d\n",
@@ -1751,12 +1753,6 @@ static int dcmi_probe(struct platform_device *pdev)
return -EPROBE_DEFER;
}
- ret = clk_prepare(mclk);
- if (ret) {
- dev_err(&pdev->dev, "Unable to prepare mclk %p\n", mclk);
- goto err_dma_release;
- }
-
spin_lock_init(&dcmi->irqlock);
mutex_init(&dcmi->lock);
init_completion(&dcmi->complete);
@@ -1772,7 +1768,7 @@ static int dcmi_probe(struct platform_device *pdev)
/* Initialize the top-level structure */
ret = v4l2_device_register(&pdev->dev, &dcmi->v4l2_dev);
if (ret)
- goto err_clk_unprepare;
+ goto err_dma_release;
dcmi->vdev = video_device_alloc();
if (!dcmi->vdev) {
@@ -1832,14 +1828,15 @@ static int dcmi_probe(struct platform_device *pdev)
dev_info(&pdev->dev, "Probe done\n");
platform_set_drvdata(pdev, dcmi);
+
+ pm_runtime_enable(&pdev->dev);
+
return 0;
err_device_release:
video_device_release(dcmi->vdev);
err_device_unregister:
v4l2_device_unregister(&dcmi->v4l2_dev);
-err_clk_unprepare:
- clk_unprepare(dcmi->mclk);
err_dma_release:
dma_release_channel(dcmi->dma_chan);
@@ -1850,20 +1847,72 @@ static int dcmi_remove(struct platform_device *pdev)
{
struct stm32_dcmi *dcmi = platform_get_drvdata(pdev);
+ pm_runtime_disable(&pdev->dev);
+
v4l2_async_notifier_unregister(&dcmi->notifier);
v4l2_device_unregister(&dcmi->v4l2_dev);
- clk_unprepare(dcmi->mclk);
+
dma_release_channel(dcmi->dma_chan);
return 0;
}
+static __maybe_unused int dcmi_runtime_suspend(struct device *dev)
+{
+ struct stm32_dcmi *dcmi = dev_get_drvdata(dev);
+
+ clk_disable_unprepare(dcmi->mclk);
+
+ return 0;
+}
+
+static __maybe_unused int dcmi_runtime_resume(struct device *dev)
+{
+ struct stm32_dcmi *dcmi = dev_get_drvdata(dev);
+ int ret;
+
+ ret = clk_prepare_enable(dcmi->mclk);
+ if (ret)
+ dev_err(dev, "%s: Failed to prepare_enable clock\n", __func__);
+
+ return ret;
+}
+
+static __maybe_unused int dcmi_suspend(struct device *dev)
+{
+ /* disable clock */
+ pm_runtime_force_suspend(dev);
+
+ /* change pinctrl state */
+ pinctrl_pm_select_sleep_state(dev);
+
+ return 0;
+}
+
+static __maybe_unused int dcmi_resume(struct device *dev)
+{
+ /* restore pinctl default state */
+ pinctrl_pm_select_default_state(dev);
+
+ /* clock enable */
+ pm_runtime_force_resume(dev);
+
+ return 0;
+}
+
+static const struct dev_pm_ops dcmi_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(dcmi_suspend, dcmi_resume)
+ SET_RUNTIME_PM_OPS(dcmi_runtime_suspend,
+ dcmi_runtime_resume, NULL)
+};
+
static struct platform_driver stm32_dcmi_driver = {
.probe = dcmi_probe,
.remove = dcmi_remove,
.driver = {
.name = DRV_NAME,
.of_match_table = of_match_ptr(stm32_dcmi_of_match),
+ .pm = &dcmi_pm_ops,
},
};
--
1.9.1
^ permalink raw reply related
* [U-Boot] [RFC PATCH 0/2] ARM: v7: Enable basic framework for supporting bits for CVE-2017-5715
From: Russell King - ARM Linux @ 2018-06-13 10:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180612215834.wrnfrb57ed3uxexa@kahuna>
On Tue, Jun 12, 2018 at 04:58:34PM -0500, Nishanth Menon wrote:
> On 21:40-20180612, Russell King - ARM Linux wrote:
> [...]
> > > I started respinning the series, while there is definitely a use of
> > > implementing in u-boot,
> > > I am starting to wonder if we should also be doing this in kernel.
> >
> > How does the kernel set the bit when the kernel is running in non-secure
> > mode, when the ACTLR is read-only in that mode?
>
> For OMAP5/DRA7 SMP systems, I just posted a patch that seems to resolve
> it:
> https://patchwork.kernel.org/patch/10461273/
>
> This'd be similar in implementation to ARM erratum 801819 workaround
> that needs two pieces (u-boot + kernel). I am not really worried about
> OMAP5/DRA7 since they should'nt loose context in Low power modes.
> Other SoCs need to be aware of the constraints.
>
> /me wishes PSCI was a standard during ARMv7, but it was'nt... So
> legacy v7 SoCs have implementations that are kind of different (even
> smc calling conventions vary).
It may seem to be an easy way out (do everything in the kernel) but
have you considered that the secure world is also vulnerable?
If the IBE bit is not set in the secure world, then the secure world
is not implementing the workarounds, and therefore the non-secure
world has the possibility to use the Spectre vulnerabilities to
exploit the secure world with enough effort and knowledge.
You really need to _also_ fix these vulnerabilities in the secure
world, which includes setting the IBE bit there.
--
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up
^ permalink raw reply
* [PATCH] arm64/mm: Introduce a variable to hold base address of linear region
From: Will Deacon @ 2018-06-13 10:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CACi5LpOJ7Q7nbo9m_HGqr44+n_iEtreZt+Uxtf2PzcHSzTdKuA@mail.gmail.com>
On Wed, Jun 13, 2018 at 10:46:56AM +0530, Bhupesh Sharma wrote:
> On Tue, Jun 12, 2018 at 3:42 PM, James Morse <james.morse@arm.com> wrote:
> > On 12/06/18 09:25, Bhupesh Sharma wrote:
> >> On Tue, Jun 12, 2018 at 12:23 PM, Ard Biesheuvel
> >> <ard.biesheuvel@linaro.org> wrote:
> >>> On 12 June 2018 at 08:36, Bhupesh Sharma <bhsharma@redhat.com> wrote:
> >>>> The start of the linear region map on a KASLR enabled ARM64 machine -
> >>>> which supports a compatible EFI firmware (with EFI_RNG_PROTOCOL
> >>>> support), is no longer correctly represented by the PAGE_OFFSET macro,
> >>>> since it is defined as:
> >>>>
> >>>> (UL(1) << (VA_BITS - 1)) + 1)
> >
> >>> PAGE_OFFSET is the VA of the start of the linear map. The linear map
> >>> can be sparsely populated with actual memory, regardless of whether
> >>> KASLR is in effect or not. The only difference in the presence of
> >>> KASLR is that there may be such a hole at the beginning, but that does
> >>> not mean the linear map has moved, or that the value of PAGE_OFFSET is
> >>> now wrong.
> >
> >>>> So taking an example of a platform with VA_BITS=48, this gives a static
> >>>> value of:
> >>>> PAGE_OFFSET = 0xffff800000000000
> >>>>
> >>>> However, for the KASLR case, we use the 'memstart_offset_seed'
> >>>> to randomize the linear region - since 'memstart_addr' indicates the
> >>>> start of physical RAM, we randomize the same on basis
> >>>> of 'memstart_offset_seed' value.
> >>>>
> >>>> As the PAGE_OFFSET value is used presently by several user space
> >>>> tools (for e.g. makedumpfile and crash tools) to determine the start
> >>>> of linear region and hence to read addresses (like PT_NOTE fields) from
> >>>> '/proc/kcore' for the non-KASLR boot cases, so it would be better to
> >>>> use 'memblock_start_of_DRAM()' value (converted to virtual) as
> >>>> the start of linear region for the KASLR cases and default to
> >>>> the PAGE_OFFSET value for non-KASLR cases to indicate the start of
> >>>> linear region.
> >
> >>> Userland code that assumes that the linear map cannot have a hole at
> >>> the beginning should be fixed.
> >
> >> That is a separate case (although that needs fixing as well via a
> >> kernel patch probably as the user-space tools rely on '/proc/iomem'
> >> contents to determine the first System RAM/reserved range).
> >
> > This is for kexec-tools generating the kdump vmcore ELF headers in user-space?
>
> Yes, but again, I would like to reiterate that the case where I see a
> hole at the start of the System RAM range (as I listed above) is just
> a specific case, which probably deserves a separate patch. The current
> patch though is for a generic issue (please see more details below).
>
> >> 1. In that particular case (see [1]) the EFI firmware sets the first
> >> EFI block as EfiReservedMemType:
> >>
> >> Region1: 0x000000000000-0x000000200000 [EfiReservedMemType]
> >> Region2: 0x000000200000-0x00000021fffff [EfiRuntimeServiceData]
> >>
> >> Since EFI firmware won't return the "EfiReservedMemType" memory to
> >> Linux kernel,
> >
> > (Its linux that makes this choice in
> > drivers/firmware/efi/arm-init.c::is_usable_memory())
> >
> >
> >> so the kernel can't get any info about the first mem
> >> block, and kernel can only see region2 as below:
> >>
> >> efi: Processing EFI memory map:
> >> efi: 0x000000200000-0x00000021ffff [Runtime Data |RUN| | |
> >> | | | | |WB|WT|WC|UC]
> >>
> >> # head -1 /proc/iomem
> >> 00200000-0021ffff : reserved
> >>
> >> 2a. If we add debug prints to 'arch/arm64/mm/init.c' to print the
> >> kernel Virtual map we can see that the memory node is set to:
> >>
> >> # dmesg | grep memory
> >> ..........
> >> memory : 0xffff800000200000 - 0xffff801800000000
> >>
> >> 2b. Now if we use kexec-tools to obtain a crash vmcore we can see that
> >> if we use 'readelf' to get the last program Header from vmcore (logs
> >> below are for the non-kaslr case):
> >>
> >> # readelf -l vmcore
> >>
> >> ELF Header:
> >> ........................
> >>
> >> Program Headers:
> >> Type Offset VirtAddr PhysAddr
> >> FileSiz MemSiz Flags Align
> >> ..............................................................................................................................................................
> >> LOAD 0x0000000076d40000 0xffff80017fe00000 0x0000000180000000
> >> 0x0000001680000000 0x0000001680000000 RWE 0
> >>
> >> 3. So if we do a simple calculation:
> >>
> >> (VirtAddr + MemSiz) = 0xffff80017fe00000 + 0x0000001680000000 =
> >> 0xFFFF8017FFE00000 != 0xffff801800000000.
> >>
> >> which indicates that the end virtual memory nodes are not the same
> >> between vmlinux and vmcore.
> >
> > If I've followed this properly: the problem is that to generate the ELF headers
> > in the post-kdump vmcore, at kdump-load-time kexec-tools has to guess the
> > virtual addresses of the 'System RAM' regions it can see in /proc/iomem.
> >
> > The problem you are hitting is an invisible hole at the beginning of RAM,
> > meaning user-space's guess_phys_to_virt() is off by the size of this hole.
> >
> > Isn't KASLR a special case for this? You must have to correct for that after
> > kdump has happened, based on an elf-note in the vmcore. Can't we always do this?
>
> No, I hit this issue both for the KASLR and non-KASLR boot cases. We
> can fix this either in kernel or user-space.
>
> Fixing this in kernel space seems better to me as the definition of
> 'memstart_addr' is that it indicates the start of the physical ram,
> but since in this case there is a hole at the start of the system ram
> visible in Linux (and thus to user-space), but 'memstart_addr' is
> still 0 which seems contradictory at the least. This causes PHY_OFFSET
> to be 0 as well, which is again contradictory.
Contradictory to who? Userspace has no business messing around with this
stuff and I'm reluctant to make this an ABI by adding a symbol with a
special name. Why can't the various constants needed by these tools be
exported in the ELF headers for kcore/vmcore, or as a NOTE as James
suggests? That sounds a lot less fragile to me.
Will
^ permalink raw reply
* [PATCH] ARM: DRA7/OMAP5: Enable ACTLR[0] (Enable invalidates of BTB) for secondary cores
From: Russell King - ARM Linux @ 2018-06-13 10:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180612213611.2484-1-nm@ti.com>
On Tue, Jun 12, 2018 at 04:36:11PM -0500, Nishanth Menon wrote:
> Call secure services to enable ACTLR[0] (Enable invalidates of BTB with
> ICIALLU) when branch hardening is enabled for kernel.
As mentioned elsewhere, I don't think this is a good idea - if the secure
world is not implementing the Spectre workarounds, then the _system_ is
exploitable.
If the secure world is implementing the spectre workarounds, it will
already have enabled the IBE bit (which is r/w from secure, read only
from non-secure.)
So, basically, lack of the IBE bit being set is basically telling the
kernel that it's running on a vulnerable platform _even if the kernel
were to set it through some means_.
>
> Signed-off-by: Nishanth Menon <nm@ti.com>
> ---
>
> Based on: next-20180612 +
> Uboot series posted: https://marc.info/?l=u-boot&m=152883522011042&w=2
>
> With Just u-boot changes alone: OMAP5-uevm: https://pastebin.ubuntu.com/p/9yDM22bJ6n/
> with kernel changes added on: https://pastebin.ubuntu.com/p/gXPBGGYRPX/
>
> arch/arm/mach-omap2/omap-smp.c | 28 ++++++++++++++++++++++++++++
> 1 file changed, 28 insertions(+)
>
> diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c
> index 69df3620eca5..28fc80ea675b 100644
> --- a/arch/arm/mach-omap2/omap-smp.c
> +++ b/arch/arm/mach-omap2/omap-smp.c
> @@ -109,6 +109,32 @@ void omap5_erratum_workaround_801819(void)
> static inline void omap5_erratum_workaround_801819(void) { }
> #endif
>
> +#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
> +static void omap5_harden_predictor(void)
> +{
> + u32 acr, acr_mask;
> +
> + asm volatile ("mrc p15, 0, %0, c1, c0, 1" : "=r" (acr));
> +
> + /*
> + * BIT(0) - Disables streaming. All write-allocate lines allocate in
> + */
> + acr_mask = BIT(0);
> +
> + /* do we already have it done.. if yes, skip expensive smc */
> + if ((acr & acr_mask) == acr_mask)
> + return;
> +
> + acr |= acr_mask;
> + omap_smc1(OMAP5_DRA7_MON_SET_ACR_INDEX, acr);
> +
> + pr_debug("%s: ARM ACR setup for CVE_2017_5715 applied on CPU%d\n",
> + __func__, smp_processor_id());
> +}
> +#else
> +static inline void omap5_harden_predictor(void) { }
> +#endif
> +
> static void omap4_secondary_init(unsigned int cpu)
> {
> /*
> @@ -131,6 +157,8 @@ static void omap4_secondary_init(unsigned int cpu)
> set_cntfreq();
> /* Configure ACR to disable streaming WA for 801819 */
> omap5_erratum_workaround_801819();
> + /* Enable ACR to allow for ICUALLU workaround */
> + omap5_harden_predictor();
> }
>
> /*
> --
> 2.15.1
>
--
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up
^ permalink raw reply
* [PATCH] arm64/mm: Introduce a variable to hold base address of linear region
From: James Morse @ 2018-06-13 10:29 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CACi5LpOJ7Q7nbo9m_HGqr44+n_iEtreZt+Uxtf2PzcHSzTdKuA@mail.gmail.com>
Hi Bhupesh,
On 13/06/18 06:16, Bhupesh Sharma wrote:
> On Tue, Jun 12, 2018 at 3:42 PM, James Morse <james.morse@arm.com> wrote:
>> On 12/06/18 09:25, Bhupesh Sharma wrote:
>>> On Tue, Jun 12, 2018 at 12:23 PM, Ard Biesheuvel wrote:
>>>> Userland code that assumes that the linear map cannot have a hole at
>>>> the beginning should be fixed.
>>> That is a separate case (although that needs fixing as well via a
>>> kernel patch probably as the user-space tools rely on '/proc/iomem'
>>> contents to determine the first System RAM/reserved range).
>>
>> This is for kexec-tools generating the kdump vmcore ELF headers in user-space?
>
> Yes, but again, I would like to reiterate that the case where I see a
> hole at the start of the System RAM range (as I listed above) is just
> a specific case, which probably deserves a separate patch. The current
> patch though is for a generic issue (please see more details below).
>>> # readelf -l vmcore
>>>
>>> ELF Header:
>>> ........................
>>>
>>> Program Headers:
>>> Type Offset VirtAddr PhysAddr
>>> FileSiz MemSiz Flags Align
>>> ..............................................................................................................................................................
>>> LOAD 0x0000000076d40000 0xffff80017fe00000 0x0000000180000000
>>> 0x0000001680000000 0x0000001680000000 RWE 0
>>>
>>> 3. So if we do a simple calculation:
>>>
>>> (VirtAddr + MemSiz) = 0xffff80017fe00000 + 0x0000001680000000 =
>>> 0xFFFF8017FFE00000 != 0xffff801800000000.
>>>
>>> which indicates that the end virtual memory nodes are not the same
>>> between vmlinux and vmcore.
>>
>> If I've followed this properly: the problem is that to generate the ELF headers
>> in the post-kdump vmcore, at kdump-load-time kexec-tools has to guess the
>> virtual addresses of the 'System RAM' regions it can see in /proc/iomem.
>>
>> The problem you are hitting is an invisible hole at the beginning of RAM,
>> meaning user-space's guess_phys_to_virt() is off by the size of this hole.
>>
>> Isn't KASLR a special case for this? You must have to correct for that after
>> kdump has happened, based on an elf-note in the vmcore. Can't we always do this?
>
> No, I hit this issue both for the KASLR and non-KASLR boot cases.
Because in both cases there is a hole at the beginning of the linear-map. KASLR
is a special-case of this as the kernel adds a variable sized hole to do the
randomization.
Surely treating this as one case makes your user-space code simpler.
> Fixing this in kernel space seems better to me as the definition of
Is there a kernel bug? Changing the definitions of internal kernel variables for
the benefit of code digging in /proc/kcore|/dev/mem isn't going to fly.
> 'memstart_addr' is that it indicates the start of the physical ram,
> but since in this case there is a hole at the start of the system ram
> visible in Linux (and thus to user-space), but 'memstart_addr' is
> still 0 which seems contradictory at the least. This causes PHY_OFFSET
> to be 0 as well, which is again contradictory.
>>> This happens because the kexec-tools rely on 'proc/iomem' contents
>>> while 'memstart_addr' is computed as 0 by kernel (as value of
>>> memblock_start_of_DRAM() < ARM64_MEMSTART_ALIGN).
>>
>>> Returning back to this patch, this is a generic requirement where we
>>> need the linear region start/base addresses in user-space applications
>>> which is used to read addresses which lie in the linear region (for
>>> e.g. when we read /proc/kcore contents).
[...]
>> This patch adds a variable that nothing uses, its going to be removed. You can't
>> depend on reading this via /dev/mem.
>>
>> Could you add the information you need as an elf-note to the vmcore instead? You
>> must already pick these up to handle kaslr. (from memory, this is where the
>> kaslr-offset is described to user-space after we kdump).
> No you are mixing up the two cases (please see above), the issue which
> this patch fixes is for use cases where we don't have the vmcore
> available in case of 'live' debugging via makedumpfile and crash tools
> (we only have '/proc/kcore' or 'vmlinux' available in such cases). I
> detailed the use case in [1] better (in a reply to Ard), I will detail
> the use-case again below:
Okay, so not kdump...
> One specific use case that I am working on at the moment is the
> makedumpfile '--mem-usage', which allows one to see the page numbers
> of current system (1st kernel) in different use (please see
> MAKEDUMPFILE(8) for more details).
https://linux.die.net/man/8/makedumpfile :
| Name: makedumpfile - make a small dumpfile of kdump
... but now we are talking about kdump again ...
> Using this we can know how many pages are dumpable when different
> dump_level is specified when invoking the makedumpfile.
>
> Normally, makedumpfile analyses the contents of '/proc/kcore' (while
> excluding the crashkernel range), and then calculates the page number
> of different kind per vmcoreinfo.
$ apt-get source makedumpfile
$ cd makedumpfile-1.5.3
$ grep -r "kcore" .
$
I suspect there are two pieces of software with the same name here.
> This use case requires directly reading the '/proc/kcore' and the
> hence the PAGE_OFFSET value is used to determine the base address of
> the linear region, whose value is not static in case of KASLR boot.
Eh? I thought PAGE_OFFSET was a compile-time constant, and it was PHYS_OFFSET
has a value other the aligned base of memory for KASLR.
> Another use-case is where the crash-utility uses the PAGE_OFFSET value
> to perform a virtual-to-physical conversion for the address lying in
> the linear region:
In all cases the problem you have is assuming the first 'System RAM' value in
/proc/iomem is the base of DRAM, which you can use a PHYS_OFFSET in your
user-space phys2virt() calculation.
What information do you need to make this work?
You can evidently read kernel variables, why can't you read memstart_addr and do:
| #define __phys_to_virt(x) \
| ((unsigned long)((x) - memstart_addr) | PAGE_OFFSET)
based on the physical addresses in /proc/iomem, and PAGE_OFFSET pulled out of
the vmlinux.
Reading memstart_addr is fragile, we might need to rename it
wednesday_memstart_addr. If user-space needs this value to work with
/proc/{kcore,vmcore} we should expose something like 'p2v_offset' as an elf-note
on those files. (looks like they both have elf-headers).
Thanks,
James
^ permalink raw reply
* [PATCH v2] regulator: core: Enable voltage balancing
From: Maciej Purski @ 2018-06-13 10:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180605044554.GC5738@atomide.com>
Call regulator_balance_voltage() instead of set_voltage_rdev()
in set_voltage_unlocked() and in enabling and disabling functions,
but only if the regulator is coupled.
Signed-off-by: Maciej Purski <m.purski@samsung.com>
---
Changes in v2:
- fix compile errors
- make debug messages more informative
---
drivers/regulator/core.c | 38 ++++++++++++++++++++++++++++----------
1 file changed, 28 insertions(+), 10 deletions(-)
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 2a7ffb7..266f4eb 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -1605,7 +1605,6 @@ static int regulator_resolve_supply(struct regulator_dev *rdev)
struct device *dev = rdev->dev.parent;
int ret;
- pr_err("%s: %d\n", __func__, __LINE__);
/* No supply to resovle? */
if (!rdev->supply_name)
return 0;
@@ -2246,7 +2245,7 @@ static int _regulator_enable(struct regulator_dev *rdev)
{
int ret;
- pr_err("%s: %d\n", __func__, __LINE__);
+ rdev_err(rdev, "%s: %d\n", __func__, __LINE__);
lockdep_assert_held_once(&rdev->mutex);
/* check voltage and requested load before enabling */
@@ -2295,7 +2294,12 @@ int regulator_enable(struct regulator *regulator)
struct regulator_dev *rdev = regulator->rdev;
int ret = 0;
- pr_err("%s: %d\n", __func__, __LINE__);
+ rdev_err(rdev, "%s: %d\n", __func__, __LINE__);
+ if (rdev->coupling_desc.n_resolved != rdev->coupling_desc.n_coupled) {
+ rdev_err(rdev, "not all coupled regulators registered\n");
+ return -EPERM;
+ }
+
if (regulator->always_on)
return 0;
@@ -2307,12 +2311,15 @@ int regulator_enable(struct regulator *regulator)
regulator_lock_dependent(rdev);
ret = _regulator_enable(rdev);
+ /* balance only if there are regulators coupled */
+ if (rdev->coupling_desc.n_coupled > 1)
+ regulator_balance_voltage(rdev, PM_SUSPEND_ON);
regulator_unlock_dependent(rdev);
if (ret != 0 && rdev->supply)
regulator_disable(rdev->supply);
- pr_err("%s: %d\n", __func__, __LINE__);
+ rdev_err(rdev, "%s: %d\n", __func__, __LINE__);
return ret;
}
EXPORT_SYMBOL_GPL(regulator_enable);
@@ -2411,18 +2418,20 @@ int regulator_disable(struct regulator *regulator)
struct regulator_dev *rdev = regulator->rdev;
int ret = 0;
- pr_err("%s: %d\n", __func__, __LINE__);
+ rdev_err(rdev, "%s: %d\n", __func__, __LINE__);
if (regulator->always_on)
return 0;
regulator_lock_dependent(rdev);
ret = _regulator_disable(rdev);
+ if (rdev->coupling_desc.n_coupled > 1)
+ regulator_balance_voltage(rdev, PM_SUSPEND_ON);
regulator_unlock_dependent(rdev);
if (ret == 0 && rdev->supply)
regulator_disable(rdev->supply);
- pr_err("%s: %d\n", __func__, __LINE__);
+ rdev_err(rdev, "%s: %d\n", __func__, __LINE__);
return ret;
}
EXPORT_SYMBOL_GPL(regulator_disable);
@@ -2470,6 +2479,8 @@ int regulator_force_disable(struct regulator *regulator)
regulator_lock_dependent(rdev);
regulator->uA_load = 0;
ret = _regulator_force_disable(regulator->rdev);
+ if (rdev->coupling_desc.n_coupled > 1)
+ regulator_balance_voltage(rdev, PM_SUSPEND_ON);
regulator_unlock_dependent(rdev);
if (rdev->supply)
@@ -2898,7 +2909,7 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
const struct regulator_ops *ops = rdev->desc->ops;
int old_uV = _regulator_get_voltage(rdev);
- pr_err("%s: %d\n", __func__, __LINE__);
+ rdev_err(rdev, "%s: %d\n", __func__, __LINE__);
trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV);
min_uV += rdev->constraints->uV_offset;
@@ -3031,7 +3042,13 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
int old_min_uV, old_max_uV;
int current_uV;
- pr_err("%s: %d\n", __func__, __LINE__);
+ rdev_err(rdev, "%s: %d\n", __func__, __LINE__);
+ if (rdev->coupling_desc.n_resolved != rdev->coupling_desc.n_coupled) {
+ rdev_err(rdev, "not all coupled regulators registered\n");
+ ret = -EPERM;
+ goto out;
+ }
+
/* If we're setting the same range as last time the change
* should be a noop (some cpufreq implementations use the same
* voltage for multiple frequencies, for example).
@@ -3074,7 +3091,8 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
if (ret < 0)
goto out2;
- ret = regulator_set_voltage_rdev(rdev, min_uV, max_uV, state);
+ /* for not coupled regulators this will just set the voltage */
+ ret = regulator_balance_voltage(rdev, state);
if (ret < 0)
goto out2;
@@ -3360,7 +3378,7 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
{
int ret = 0;
- pr_err("%s: %d\n", __func__, __LINE__);
+ rdev_err(regulator->rdev, "%s: %d\n", __func__, __LINE__);
regulator_lock_dependent(regulator->rdev);
ret = regulator_set_voltage_unlocked(regulator, min_uV, max_uV,
--
2.7.4
^ permalink raw reply related
* [RFC V2 3/3] perf: qcom: Add Falkor CPU PMU IMPLEMENTATION DEFINED event support
From: Will Deacon @ 2018-06-13 10:35 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <9957219b64252d3b2e19724db04a1179@codeaurora.org>
On Tue, Jun 12, 2018 at 04:41:32PM -0400, Agustin Vega-Frias wrote:
> Hi Mark,
>
> On 2018-06-12 10:40, Mark Rutland wrote:
> >Hi,
> >
> >On Thu, Jun 07, 2018 at 09:56:48AM -0400, Agustin Vega-Frias wrote:
> >>Selection of these events can be envisioned as indexing them from
> >>a 3D matrix:
> >>- the first index selects a Region Event Selection Register
> >>(PMRESRx_EL0)
> >>- the second index selects a group from which only one event at a time
> >> can be selected
> >>- the third index selects the event
> >>
> >>The event is encoded into perf_event_attr.config as 0xPRCCG, where:
> >> P [config:16 ] = prefix (flag that indicates a matrix-based
> >>event)
> >> R [config:12-15] = register (specifies the PMRESRx_EL0 instance)
> >> G [config:0-3 ] = group (specifies the event group)
> >> CC [config:4-11 ] = code (specifies the event)
> >>
> >>Events with the P flag set to zero are treated as common PMUv3 events
> >>and are directly programmed into PMXEVTYPERx_EL0.
> >>
> >>The first two indexes are set combining the RESR and group number with
> >>a base number and writing it into the architected PMXEVTYPER_EL0
> >>register.
> >>The third index is set by writing the code into the bits corresponding
> >>with the group into the appropriate IMPLEMENTATION DEFINED PMRESRx_EL0
> >>register.
> >
> >When are the IMP DEF registers accessible at EL0? Are those goverend by
> >the same controls as the architected registers?
>
> No, there is a separate IMP DEF register to control access.
Great :( We need to make sure we disable EL0 access during boot then, but
that means we need to prove for the existence of this thing in head.S
(since the PMU driver might not get loaded).
Also, what's the kvm story here so that we don't accidentally open up a
VM-VM side-channel via these registers? How do the EL1 trapping controls
work?
Will
^ permalink raw reply
* [PATCH v1 1/4] clk: imx7d: add IMX7D_MU_ROOT_CLK
From: Dong Aisheng @ 2018-06-13 10:38 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180601065821.28234-2-o.rempel@pengutronix.de>
On Fri, Jun 1, 2018 at 2:58 PM, Oleksij Rempel <o.rempel@pengutronix.de> wrote:
> This clock is needed for iMX mailbox driver
>
> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
> ---
> drivers/clk/imx/clk-imx7d.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c
> index 975a20d3cc94..1c2541dc40e7 100644
> --- a/drivers/clk/imx/clk-imx7d.c
> +++ b/drivers/clk/imx/clk-imx7d.c
> @@ -793,6 +793,7 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
> clks[IMX7D_DRAM_PHYM_ROOT_CLK] = imx_clk_gate4("dram_phym_root_clk", "dram_phym_cg", base + 0x4130, 0);
> clks[IMX7D_DRAM_PHYM_ALT_ROOT_CLK] = imx_clk_gate4("dram_phym_alt_root_clk", "dram_phym_alt_post_div", base + 0x4130, 0);
> clks[IMX7D_DRAM_ALT_ROOT_CLK] = imx_clk_gate4("dram_alt_root_clk", "dram_alt_post_div", base + 0x4130, 0);
> + clks[IMX7D_MU_ROOT_CLK] = imx_clk_gate2("mu_root_clk", "ipg_root_clk", base + 0x4270, 0);
The clock slice on MX7D needs to operate while its parent clock is on.
So this seems ought to be imx_clk_gate4?
Besides that, a nitpick:
although the address is already out of order, but we are still better to keep
in increasing order as long as we can.
Regards
Dong Aisheng
> clks[IMX7D_OCOTP_CLK] = imx_clk_gate4("ocotp_clk", "ipg_root_clk", base + 0x4230, 0);
> clks[IMX7D_SNVS_CLK] = imx_clk_gate4("snvs_clk", "ipg_root_clk", base + 0x4250, 0);
> clks[IMX7D_CAAM_CLK] = imx_clk_gate4("caam_clk", "ipg_root_clk", base + 0x4240, 0);
> --
> 2.17.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-clk" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH 2/4] ARM: dts: Modernize the Vexpress PL111 integration
From: Sudeep Holla @ 2018-06-13 10:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180528122658.3241-3-linus.walleij@linaro.org>
Hi Linus,
I was planning to apply this and observed few things.
On 28/05/18 13:26, Linus Walleij wrote:
> The Versatile Express was submitted with the actual display
> bridges unconnected (but defined in the device tree) and
> mock "panels" encoded in the device tree node of the PL111
> controller.
>
> This doesn't even remotely describe the actual Versatile
> Express hardware. Exploit the SiI9022 bridge by connecting
> the PL111 pads to it, making it use EDID or fallback values
> to drive the monitor.
>
> The also has to use the reserved memory through the
> CMA pool rather than by open coding a memory region and
> remapping it explicitly in the driver. To achieve this,
> a reserved-memory node must exist in the root of the
> device tree, so we need to pull that out of the
> motherboard .dtsi include files, and push it into each
> top-level device tree instead.
>
> We do the same manouver for all the Versatile Express
> boards, taking into account the different location of the
> video RAM depending on which chip select is used on
> each platform.
>
> This plays nicely with the new PL111 DRM driver and
> follows the standard ways of assigning bridges and
> memory pools for graphics.
>
> Cc: Sudeep Holla <sudeep.holla@arm.com>
> Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> Cc: Liviu Dudau <liviu.dudau@arm.com>
> Cc: Mali DP Maintainers <malidp@foss.arm.com>
> Cc: Robin Murphy <robin.murphy@arm.com>
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
> ---
> ChangeLog v1->v2:
> - Fix up the memory address for the -rs1 tiles to 0x18000000
> - Drop a bunch of extraneous reg props from the DVI adapter
> ---
> arch/arm/boot/dts/vexpress-v2m-rs1.dtsi | 44 ++++++------------
> arch/arm/boot/dts/vexpress-v2m.dtsi | 45 ++++++-------------
> arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts | 14 ++++++
> arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts | 14 ++++++
> arch/arm/boot/dts/vexpress-v2p-ca5s.dts | 14 ++++++
> arch/arm/boot/dts/vexpress-v2p-ca9.dts | 41 +++++++----------
> arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts | 14 ++++++
> .../boot/dts/arm/rtsm_ve-motherboard.dtsi | 37 +++------------
> 8 files changed, 105 insertions(+), 118 deletions(-)
>
> diff --git a/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi b/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi
> index 7b8ff5b3b912..69f6a9436325 100644
> --- a/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi
> +++ b/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi
> @@ -43,11 +43,6 @@
> bank-width = <4>;
> };
>
> - v2m_video_ram: vram at 2,00000000 {
> - compatible = "arm,vexpress-vram";
> - reg = <2 0x00000000 0x00800000>;
> - };
> -
> ethernet at 2,02000000 {
> compatible = "smsc,lan9118", "smsc,lan9115";
> reg = <2 0x02000000 0x10000>;
> @@ -224,6 +219,14 @@
> dvi-transmitter at 39 {
> compatible = "sil,sii9022-tpi", "sil,sii9022";
> reg = <0x39>;
> +
> + ports {
> + port at 0 {
May need reg=<0> here, otherwise DTC might complain ?
[...]
> diff --git a/arch/arm/boot/dts/vexpress-v2m.dtsi b/arch/arm/boot/dts/vexpress-v2m.dtsi
> index 9cd5e146abd5..067d84bc61c0 100644
> --- a/arch/arm/boot/dts/vexpress-v2m.dtsi
> +++ b/arch/arm/boot/dts/vexpress-v2m.dtsi
> @@ -43,11 +43,6 @@
> bank-width = <4>;
> };
>
> - v2m_video_ram: vram at 3,00000000 {
> - compatible = "arm,vexpress-vram";
> - reg = <3 0x00000000 0x00800000>;
> - };
> -
> ethernet at 3,02000000 {
> compatible = "smsc,lan9118", "smsc,lan9115";
> reg = <3 0x02000000 0x10000>;
> @@ -224,6 +219,14 @@
> dvi-transmitter at 39 {
> compatible = "sil,sii9022-tpi", "sil,sii9022";
> reg = <0x39>;
> +
> + ports {
> + port at 0 {
Ditto
> + dvi_bridge_in: endpoint {
> + remote-endpoint = <&clcd_pads>;
> + };
> + };
> + };
> };
>
> dvi-transmitter at 60 {
[...]
> diff --git a/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts b/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts
> index 3971427a105b..0dc4277d5f8b 100644
> --- a/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts
> +++ b/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts
> @@ -53,6 +53,20 @@
> reg = <0 0x80000000 0 0x40000000>;
> };
>
> + reserved-memory {
> + #address-cells = <2>;
> + #size-cells = <2>;
> + ranges;
> +
> + /* Chipselect 2 is physically at 0x18000000 */
> + vram: vram at 18000000 {
> + /* 8 MB of designated video RAM */
> + compatible = "shared-dma-pool";
> + reg = <0 0x18000000 0 0x00800000>;
> + no-map;
> + };
> + };
> +
I need to think hard yet, but was hoping to keep these in the
motherboard files itself if possible. I don't like the way we need
to specify the absolute address here.
> hdlcd at 2b000000 {
> compatible = "arm,hdlcd";
> reg = <0 0x2b000000 0 0x1000>;
[...]
> diff --git a/arch/arm64/boot/dts/arm/rtsm_ve-motherboard.dtsi b/arch/arm64/boot/dts/arm/rtsm_ve-motherboard.dtsi
> index 1134e5d8df18..737d0a0c0854 100644
> --- a/arch/arm64/boot/dts/arm/rtsm_ve-motherboard.dtsi
> +++ b/arch/arm64/boot/dts/arm/rtsm_ve-motherboard.dtsi
> @@ -23,11 +23,6 @@
> bank-width = <4>;
> };
>
> - v2m_video_ram: vram at 2,00000000 {
> - compatible = "arm,vexpress-vram";
> - reg = <2 0x00000000 0x00800000>;
> - };
> -
> ethernet at 2,02000000 {
> compatible = "smsc,lan91c111";
> reg = <2 0x02000000 0x10000>;
> @@ -186,38 +181,16 @@
> interrupts = <14>;
> clocks = <&v2m_oscclk1>, <&v2m_clk24mhz>;
> clock-names = "clcdclk", "apb_pclk";
> - arm,pl11x,framebuffer = <0x18000000 0x00180000>;
> - memory-region = <&v2m_video_ram>;
> - max-memory-bandwidth = <130000000>; /* 16bpp @ 63.5MHz */
> + /* 800x600 16bpp @36MHz works fine */
> + max-memory-bandwidth = <54000000>;
> + memory-region = <&vram>;
>
> port {
> - v2m_clcd_pads: endpoint {
> - remote-endpoint = <&v2m_clcd_panel>;
> + clcd_pads: endpoint {
> + remote-endpoint = <&dvi_bridge_in>;
I can't find dvi_bridge_in for this RTSM/FVP model, also not sure if I2C
or DVI transmitter is supported on them.
Liviu, any idea ?
Also you my need to fix arm64 express-v2f-1xv7-ca53x2.dts as it includes
vexpress-v2m-rs1.dtsi
--
Regards,
Sudeep
^ permalink raw reply
* [PATCH/RFT 2/2] arm64: dts: renesas: r8a77965: Add PCIe device nodes
From: Simon Horman @ 2018-06-13 10:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180611082819.rnoiou2t7l6dynju@verge.net.au>
On Mon, Jun 11, 2018 at 10:28:22AM +0200, Simon Horman wrote:
> On Thu, Jun 07, 2018 at 09:11:34PM +0900, Yoshihiro Kaneko wrote:
> > From: Takeshi Kihara <takeshi.kihara.df@renesas.com>
> >
> > This patch adds PCIe{0,1} device nodes to R8A77965 SoC.
> >
> > Based on a similar patches of the R8A7796 device tree
> > by Harunobu Kurokawa <harunobu.kurokawa.dn@renesas.com>.
> >
> > Signed-off-by: Takeshi Kihara <takeshi.kihara.df@renesas.com>
> > Signed-off-by: Yoshihiro Kaneko <ykaneko0929@gmail.com>
>
> Hi,
>
> This looks fine to me but I will wait to see if there are other reviews
> before applying.
>
> Reviewed-by: Simon Horman <horms+renesas@verge.net.au>
Thanks Kaneko-san, applied.
^ permalink raw reply
* [PATCH v1 2/4] dt-bindings: mailbox: provide imx-mailbox documentation
From: Dong Aisheng @ 2018-06-13 11:05 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180601065821.28234-3-o.rempel@pengutronix.de>
Hi Oleksij,
Some more comments besides Rob's:
On Fri, Jun 1, 2018 at 2:58 PM, Oleksij Rempel <o.rempel@pengutronix.de> wrote:
> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
> ---
> .../bindings/mailbox/imx-mailbox.txt | 35 +++++++++++++++++++
> 1 file changed, 35 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
>
> diff --git a/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt b/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
> new file mode 100644
> index 000000000000..a45604b33039
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
> @@ -0,0 +1,35 @@
> +i.MX Messaging Unit
> +===================
> +
> +The i.MX Messaging Unit (MU) contains two register sets: "A" and "B". In most cases
> +they are accessible from all Processor Units. On one hand, at least for mailbox functionality,
> +it makes no difference which application or processor is using which set of the MU. On
> +other hand, the register sets for each of the MU parts are not identical.
> +
> +Required properties:
> +- compatible : Shell be one of:
> + "fsl,imx7s-mu-a" and "fsl,imx7s-mu-b" for i.MX7S or i.MX7D
What's current requirement to distinguish Side A and B?
I see current code, side A only does extra clear of xCR register but none for B.
Is this a generic approach or something customized?
BTW can we name it more generically?e.g. fsl,imx7s-mu.
And using a property to indicate whether it's side A or B if really required.
Furthermore, AFAIK MX7 MU is derived from MX6SX.
Should we add and use fsl,imx6sx-mu instead?
e.g.
- compatible : Shell be one of:
"fsl,imx6sx-mu" and "fsl,imx7s-mu".
Regards
Dong Aisheng
> +- reg : physical base address of the mailbox and length of
> + memory mapped region.
> +- #mbox-cells: Common mailbox binding property to identify the number
> + of cells required for the mailbox specifier. Should be 1.
> +- interrupts : interrupt number. The interrupt specifier format
> + depends on the interrupt controller parent.
> +- clocks : phandle to the input clock.
> +
> +Example:
> + mu0a: mu at 30aa0000 {
> + compatible = "fsl,imx7s-mu-a";
> + reg = <0x30aa0000 0x28>;
> + interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
> + clocks = <&clks IMX7D_MU_ROOT_CLK>;
> + #mbox-cells = <1>;
> + };
> +
> + mu0b: mu at 30ab0000 {
> + compatible = "fsl,imx7s-mu-b";
> + reg = <0x30ab0000 0x28>;
> + interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
> + clocks = <&clks IMX7D_MU_ROOT_CLK>;
> + #mbox-cells = <1>;
> + };
> --
> 2.17.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-clk" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH V5] ARM: shmobile: Rework the PMIC IRQ line quirk
From: Simon Horman @ 2018-06-13 11:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180611121513.9673-1-marek.vasut+renesas@gmail.com>
On Mon, Jun 11, 2018 at 02:15:13PM +0200, Marek Vasut wrote:
> Rather than hard-coding the quirk topology, which stopped scaling,
> parse the information from DT. The code looks for all compatible
> PMICs -- da9063 and da9210 -- and checks if their IRQ line is tied
> to the same pin. If so, the code sends a matching sequence to the
> PMIC to deassert the IRQ.
>
> Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
> Cc: Geert Uytterhoeven <geert+renesas@glider.be>
> Cc: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
> Cc: Simon Horman <horms+renesas@verge.net.au>
> Cc: Wolfram Sang <wsa+renesas@sang-engineering.com>
> Cc: linux-renesas-soc at vger.kernel.org
> Acked-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
> Tested-by: Geert Uytterhoeven <geert+renesas@glider.be> (on Koelsch)
Hi,
This looks fine to me but I will wait to see if there are other reviews
before applying.
Reviewed-by: Simon Horman <horms+renesas@verge.net.au>
^ permalink raw reply
* [PATCH v4 26/26] irqchip/gic-v3: Allow interrupts to be set as pseudo-NMI
From: Julien Thierry @ 2018-06-13 11:07 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1527241772-48007-27-git-send-email-julien.thierry@arm.com>
On 25/05/18 10:49, Julien Thierry wrote:
> Provide a way to set a GICv3 interrupt as pseudo-NMI. The interrupt
> must not be enabled when setting/clearing the NMI status of the interrupt.
>
> Signed-off-by: Julien Thierry <julien.thierry@arm.com>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Jason Cooper <jason@lakedaemon.net>
> Cc: Marc Zyngier <marc.zyngier@arm.com>
> ---
> drivers/irqchip/irq-gic-v3.c | 54 ++++++++++++++++++++++++++++++++++++++++++++
> include/linux/interrupt.h | 1 +
> 2 files changed, 55 insertions(+)
>
[...]
> diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
> index 5426627..02c794f 100644
> --- a/include/linux/interrupt.h
> +++ b/include/linux/interrupt.h
> @@ -419,6 +419,7 @@ enum irqchip_irq_state {
> IRQCHIP_STATE_ACTIVE, /* Is interrupt in progress? */
> IRQCHIP_STATE_MASKED, /* Is interrupt masked? */
> IRQCHIP_STATE_LINE_LEVEL, /* Is IRQ line high? */
> + IRQCHIP_STATE_NMI, /* Is IRQ an NMI? */
> };
After discussing with Thomas, NMI setting should not be exposed/managed
through the generic irq interface.
--
Julien Thierry
^ permalink raw reply
* [PATCH v4 24/26] irqchip/gic-v3: Add base support for pseudo-NMI
From: Julien Thierry @ 2018-06-13 11:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1527241772-48007-25-git-send-email-julien.thierry@arm.com>
On 25/05/18 10:49, Julien Thierry wrote:
> Provide a higher priority to be used for pseudo-NMIs. When such an
> interrupt is received, enter the NMI state and prevent other NMIs to
> be raised.
>
> When returning from a pseudo-NMI, skip preemption and tracing if the
> interrupted context has interrupts disabled.
>
> Signed-off-by: Julien Thierry <julien.thierry@arm.com>
> Cc: Russell King <linux@armlinux.org.uk>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Jason Cooper <jason@lakedaemon.net>
> Cc: Marc Zyngier <marc.zyngier@arm.com>
> ---
> arch/arm/include/asm/arch_gicv3.h | 6 ++++++
> arch/arm64/include/asm/arch_gicv3.h | 6 ++++++
> arch/arm64/kernel/entry.S | 43 +++++++++++++++++++++++++++++++++++++
> drivers/irqchip/irq-gic-v3.c | 41 +++++++++++++++++++++++++++++++++++
> 4 files changed, 96 insertions(+)
>
[...]
> diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
> index b144f73..4be5996 100644
> --- a/drivers/irqchip/irq-gic-v3.c
> +++ b/drivers/irqchip/irq-gic-v3.c
> @@ -371,6 +379,20 @@ static u64 gic_mpidr_to_affinity(unsigned long mpidr)
> return aff;
> }
>
> +static void do_handle_nmi(unsigned int hwirq, struct pt_regs *regs)
> +{
> + struct pt_regs *old_regs = set_irq_regs(regs);
> + unsigned int irq;
> +
> + nmi_enter();
RAS/SEA also enters NMI state and things will break if asynchronous
error occurs during a pseudo-NMI.
I'll have this fixed in the next version.
--
Julien Thierry
^ permalink raw reply
* [PATCH V5] ARM: shmobile: Rework the PMIC IRQ line quirk
From: Geert Uytterhoeven @ 2018-06-13 11:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180613110647.ygg66nu36pcf6kpn@verge.net.au>
Hi Simon,
On Wed, Jun 13, 2018 at 1:06 PM Simon Horman <horms@verge.net.au> wrote:
> On Mon, Jun 11, 2018 at 02:15:13PM +0200, Marek Vasut wrote:
> > Rather than hard-coding the quirk topology, which stopped scaling,
> > parse the information from DT. The code looks for all compatible
> > PMICs -- da9063 and da9210 -- and checks if their IRQ line is tied
> > to the same pin. If so, the code sends a matching sequence to the
> > PMIC to deassert the IRQ.
> >
> > Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
> > Cc: Geert Uytterhoeven <geert+renesas@glider.be>
> > Cc: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
> > Cc: Simon Horman <horms+renesas@verge.net.au>
> > Cc: Wolfram Sang <wsa+renesas@sang-engineering.com>
> > Cc: linux-renesas-soc at vger.kernel.org
> > Acked-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
> > Tested-by: Geert Uytterhoeven <geert+renesas@glider.be> (on Koelsch)
>
> This looks fine to me but I will wait to see if there are other reviews
> before applying.
>
> Reviewed-by: Simon Horman <horms+renesas@verge.net.au>
Note that applying it now will break gose, as its DTS doesn't describe all
regulators yet.
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* [PATCH V3] ARM: shmobile: Rework the PMIC IRQ line quirk
From: Geert Uytterhoeven @ 2018-06-13 11:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <3eda9da7-e26e-3e77-1040-9febe3b18abb@gmail.com>
Hi Marek,
On Mon, Jun 11, 2018 at 5:26 PM Marek Vasut <marek.vasut@gmail.com> wrote:
> On 06/11/2018 04:30 PM, Geert Uytterhoeven wrote:
> > On Mon, Jun 11, 2018 at 4:19 PM Marek Vasut <marek.vasut@gmail.com> wrote:
> >> On 06/11/2018 04:10 PM, Geert Uytterhoeven wrote:
> >>> On Mon, Jun 11, 2018 at 4:04 PM Marek Vasut <marek.vasut@gmail.com> wrote:
> >>>> On 06/11/2018 03:49 PM, Geert Uytterhoeven wrote:
> >>>>> On Mon, Jun 11, 2018 at 3:39 PM Marek Vasut <marek.vasut@gmail.com> wrote:
> >>>>>> On 06/11/2018 03:03 PM, Geert Uytterhoeven wrote:
> >>>>>>> On Mon, Jun 11, 2018 at 2:15 PM Marek Vasut <marek.vasut@gmail.com> wrote:
> >>>>>>>> On 06/11/2018 11:56 AM, Geert Uytterhoeven wrote:
> >>>>>>>>> On Mon, Jun 4, 2018 at 7:59 PM Marek Vasut <marek.vasut@gmail.com> wrote:
> >>>>>>>>>> Rather than hard-coding the quirk topology, which stopped scaling,
> >>>>>>>>>> parse the information from DT. The code looks for all compatible
> >>>>>>>>>> PMICs -- da9036 and da9210 -- and checks if their IRQ line is tied
> >>>>>>>>>> to the same pin. If so, the code sends a matching sequence to the
> >>>>>>>>>> PMIC to deassert the IRQ.
> >>>>>
> >>>>>>>>>> + ret = of_property_read_u32(np, "reg", &addr);
> >>>>>>>>>> + if (ret)
> >>>>>>>>>> + return ret;
> >>>>>>>>>
> >>>>>>>>> I think it's safer to skip this entry and continue, after calling
> >>>>>>>>> kfree(quirk), of course.
> >>>>>>>>>
> >>>>>>>>>> +
> >>>>>>>>>> + quirk->id = id;
> >>>>>>>>>> + quirk->i2c_msg.addr = addr;
> >>>>>>>>>> + quirk->shared = false;
> >>>>>>>>>> +
> >>>>>>>>>> + ret = of_irq_parse_one(np, 0, &quirk->irq_args);
> >>>>>>>>>> + if (ret)
> >>>>>>>>>> + return ret;
> >>>>>>>>>
> >>>>>>>>> kfree(quirk) and continue...
> >>>>>>>>
> >>>>>>>> I wonder if it shouldn't rather free the entire list and abort ?
> >>>>>>>
> >>>>>>> "Be strict when sending, be liberal when receiving."
> >>>>>>
> >>>>>> Meaning ? I think "the language barrier is protecting me" (TM)
> >>>>>
> >>>>> Do the best you can, given the buggy DT you received.
> >>>>> I.e. don't fail completely, just ignore the bad device node, and continue.
> >>>>
> >>>> But if you ignore node, you might as well ignore one which is shared and
> >>>> then the system crashes due to IRQ storm anyway. So hum, what can we do ?
> >>>
> >>> Correct. If it's a critical node, it will crash regardless.
> >>> If it's a non-critical node, you have the choice between aborting and crashing,
> >>> or ignoring and keeping the system alive. Your call.
> >>
> >> But wait, since we control which machines this code runs on , can't we
> >> assure they have valid DTs ? This situation with invalid DT starts to
> >> look a bit hypothetical to me.
> >
> > That assumes you keep the list of machines to check, and don't want to fix the
> > issue automatically when detected (on any R-Car Gen2 or RZ/G1 platform, so
> > you still need to check for r8a779[0-4] and r8a774[23457]).
>
> Yes, I want to keep a list of machines to check, to be _sure_ some
> machine doesn't randomly blow up.
Just checking for the presence of a "renesas,irqc" node should be sufficient.
Using that node would also get rid of the hardcoded IRQC_BASE address.
Note that the code assumes IRQ2. If another IRQ is used, that won't harm
much though (as in: if it didn't blow up before, it won't blow up now).
> > Anyway, as we care about booting old DTBs on new kernels (for a while), we
> > have a few more release cycles to bikeshed ;-)
>
> I was about to ask if this patch then makes any sense or not.
Sure. Less hard-coding is always better.
Especially if it means we can make it work on more machines automatically :-)
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* [PATCH 0/8] Add persistent clock support
From: Baolin Wang @ 2018-06-13 11:32 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
We will meet below issues when compensating the suspend time for the timekeeping.
1. We have too many different ways of dealing with persistent timekeeping
across architectures, so it is hard for one driver to be compatible with
different architectures. For example, we should register register_persistent_clock()
on arm architecture, but we should set x86_platform.get_wallclock() on x86
architecture, and we should implement the read_persistent_clock64() on arm64
architecture and so on.
2. On some platforms (such as Spreadtrum platform), we registered the high
resolution timer as one clocksource to update the OS time, but the high
resolution timer will be stopped when system goes into suspend state.
So we use another one always-on timer (but low resolution) to calculate
the suspend time to compensate the OS time. Though we can register the
always-on timer as one clocksource, we need re-calculate the mult/shift
with one larger conversion range to calculate the suspend time and need
update the clock in case of running over the always-on timer.
More duplicate code will be added if other platforms meet this case.
3. Now we have 3 sources that could be used to compensate the OS time:
Nonstop clocksource during suspend, persistent clock and rtc device,
which is complicated. Another hand is that the nonstop clocksource can
risk wrapping if the system suspend time is too long, so we need one
mechanism to wake up the system before the nonstop clocksource wrapping.
According to above issues, we can introduce one common persistent clock
framework to be compatible with different architectures, in future we will
remove the persistent clock implementation for each architecture. Also
this framework will implement common code to help drivers to register easily.
Moreover if we converted all SUSPEND_NONSTOP clocksource to register to
be one persistent clock, we can remove the SUSPEND_NONSTOP clocksource
accounting in timekeeping, which means we can only compensate the OS time
from persistent clock and RTC.
Will be appreciated for any comments. Thank you all.
Arnd posted some comments as below last time, but we did not get a general
consensus, so I post them again. Arnd said:
"I was planning to discuss this with Daniel and John during Linaro Connect,
but that didn't happen, so I'd like to bring up the bigger picture here again.
Today, we have a number of subsystem-type interfaces that deal with
time keeping in the wider sense (I might be missing some):
- clock source
- clock event
- sched clock
- real time clock
- ptp clock
- persistent clock
The first five have separate registration interfaces and may all refer
to different hardware blocks, or (more commonly) have some overlap
in the hardware. The fifth one is generalized by your series, without it
it's really architecture specific (as the other ones were one one point).
Are we happy with that structure in the long run? One of my earlier
comments on this series was that I thought it should be combined with
the clocksource registration, but upon talking to Baolin about it more,
I realized that this just follows the same structure that we have for the
others.
In theory, we could have a more abstract way of registering a clock
hardware that interfaces with any combination of the six subsystems
I mentioned above, with a superset of the subsystem specific structures
and a set of flags that indicate what a particular device is usable for.
Combining all six might be a bit too much (in particular rtc, though
it clearly overlaps the persistent-clk case), but what your general
ideas on where we should be heading? Is it worth reworking the
core kernel portion of the subsystems to simplify the individual
drivers?"
John also posted some important comments for this patch set, that I quite
agree with his points. John said:
"For context, these abstractions have grown out of the need for using
different hardware components for all of these. It was quite common
for x86 hardware to use the acpi_pm for clocksource, lapic/PIT for
clockevent, tsc for sched_clock and CMOS RTC for persistent clock.
While some of these could be backed by the same hardware, it wasn't
common. However, hardware with less restrictions have allowed in some
cases for these to be more unified, but I'm not sure if its particularly common.
Another part of the reason that we don't combine the above
abstractions, even when they are backed by the same hardware, is
because some of the fields used for freq conversion (mult/shift) have
different needs for the different types of accounting.
For instance, with a clocksource, we are very focused on avoiding
error to keep timekeeing accurate, thus we want to use as large a
shift (and thus mult) as possible (and do our shifting as late as
possible in our accounting). However, that then shrinks the amount of
time that can be accumulated in one go w/o causing an overflow.
Where as with sched_clock, we don't worry as much as about accuracy,
so we can use smaller shifts (and thus mults), and thus can go for
longer periods of time between accumulating without worrying.
Similarly for the persistent clock case we don't need need to worry as
much about accuracy, so we can can use smaller shifts, but we are not
in as much of a hot patch, so we can also"
Changes since RFC V1:
- Move the alarmtimer starting into alarmtimer.c.
- Export persistent_clock_start_alarmtimer().
- Add one memeber to indicate if the alarmtimer was initialized.
- Fix build issues.
Baolin Wang (8):
time: Add persistent clock support
clocksource: sprd: Add one persistent timer for Spreadtrum platform
arm: time: Remove the persistent clock support for ARM architecture
clocksource: arm_arch_timer: Register the persistent clock
clocksource: timer-ti-32k: Register the persistent clock
clocksource: time-pistachio: Register the persistent clock
x86: tsc: Register the persistent clock
time: timekeeping: Remove time compensating from nonstop clocksources
arch/arm/include/asm/mach/time.h | 4 -
arch/arm/kernel/time.c | 36 -------
arch/arm/plat-omap/Kconfig | 1 +
arch/arm/plat-omap/counter_32k.c | 44 ++------
arch/x86/Kconfig | 1 +
arch/x86/kernel/tsc.c | 21 ++++
drivers/clocksource/Kconfig | 4 +
drivers/clocksource/arm_arch_timer.c | 10 ++
drivers/clocksource/tegra20_timer.c | 12 ++-
drivers/clocksource/time-pistachio.c | 3 +
drivers/clocksource/timer-sprd.c | 80 +++++++++++++++
drivers/clocksource/timer-ti-32k.c | 4 +
include/linux/persistent_clock.h | 23 +++++
kernel/time/Kconfig | 4 +
kernel/time/Makefile | 1 +
kernel/time/alarmtimer.c | 4 +
kernel/time/persistent_clock.c | 184 ++++++++++++++++++++++++++++++++++
kernel/time/timekeeping.c | 19 +---
18 files changed, 360 insertions(+), 95 deletions(-)
create mode 100644 include/linux/persistent_clock.h
create mode 100644 kernel/time/persistent_clock.c
--
1.7.9.5
^ permalink raw reply
* [PATCH 1/8] time: Add persistent clock support
From: Baolin Wang @ 2018-06-13 11:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1528878545.git.baolin.wang@linaro.org>
On our Spreadtrum SC9860 platform, we registered the high resolution
ARM generic timer as one clocksource to update the OS time, but the
ARM generic timer will be stopped in suspend state. So we use one 64bit
always-on timer (but low resolution) of Spreadtrum to calculate the
suspend time to compensate the OS time. Though we can register the
always-on timer as one clocksource, we need re-calculate the
mult/shift with one larger conversion range to calculate the suspend
time.
But now we have too many different ways of dealing with persistent
timekeeping across architectures, and there will be many duplicate
code if we register one timer to be one persistent clock. Thus it
will be more helpful if we add one common framework for timer drivers
to be registered as one persistent clock and implement the common
read_persistent_clock64() to compensate the OS time.
Moreover we can register the clocksource with CLOCK_SOURCE_SUSPEND_NONSTOP
to be one persistent clock, then we can simplify the suspend/resume
accounting by removing CLOCK_SOURCE_SUSPEND_NONSTOP timing. After that
we can only compensate the OS time by persistent clock or RTC.
Signed-off-by: Baolin Wang <baolin.wang@linaro.org>
---
include/linux/persistent_clock.h | 23 +++++
kernel/time/Kconfig | 4 +
kernel/time/Makefile | 1 +
kernel/time/alarmtimer.c | 4 +
kernel/time/persistent_clock.c | 184 ++++++++++++++++++++++++++++++++++++++
5 files changed, 216 insertions(+)
create mode 100644 include/linux/persistent_clock.h
create mode 100644 kernel/time/persistent_clock.c
diff --git a/include/linux/persistent_clock.h b/include/linux/persistent_clock.h
new file mode 100644
index 0000000..7d42c1a
--- /dev/null
+++ b/include/linux/persistent_clock.h
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0
+#ifndef __PERSISTENT_CLOCK_H__
+#define __PERSISTENT_CLOCK_H__
+
+#ifdef CONFIG_PERSISTENT_CLOCK
+extern int persistent_clock_init_and_register(u64 (*read)(void),
+ u64 mask, u32 freq,
+ u64 maxsec);
+extern void persistent_clock_cleanup(void);
+extern void persistent_clock_start_alarmtimer(void);
+#else
+static inline int persistent_clock_init_and_register(u64 (*read)(void),
+ u64 mask, u32 freq,
+ u64 maxsec)
+{
+ return 0;
+}
+
+static inline void persistent_clock_cleanup(void) { }
+static inline void persistent_clock_start_alarmtimer(void) { }
+#endif
+
+#endif
diff --git a/kernel/time/Kconfig b/kernel/time/Kconfig
index 78eabc4..7188600 100644
--- a/kernel/time/Kconfig
+++ b/kernel/time/Kconfig
@@ -47,6 +47,10 @@ config GENERIC_CLOCKEVENTS_MIN_ADJUST
config GENERIC_CMOS_UPDATE
bool
+# Persistent clock support
+config PERSISTENT_CLOCK
+ bool
+
if GENERIC_CLOCKEVENTS
menu "Timers subsystem"
diff --git a/kernel/time/Makefile b/kernel/time/Makefile
index f1e46f3..f6d368f 100644
--- a/kernel/time/Makefile
+++ b/kernel/time/Makefile
@@ -18,3 +18,4 @@ obj-$(CONFIG_GENERIC_SCHED_CLOCK) += sched_clock.o
obj-$(CONFIG_TICK_ONESHOT) += tick-oneshot.o tick-sched.o
obj-$(CONFIG_DEBUG_FS) += timekeeping_debug.o
obj-$(CONFIG_TEST_UDELAY) += test_udelay.o
+obj-$(CONFIG_PERSISTENT_CLOCK) += persistent_clock.o
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c
index 639321b..1518fdb 100644
--- a/kernel/time/alarmtimer.c
+++ b/kernel/time/alarmtimer.c
@@ -29,6 +29,7 @@
#include <linux/freezer.h>
#include <linux/compat.h>
#include <linux/module.h>
+#include <linux/persistent_clock.h>
#include "posix-timers.h"
@@ -892,6 +893,9 @@ static int __init alarmtimer_init(void)
error = PTR_ERR(pdev);
goto out_drv;
}
+
+ /* Start one alarmtimer to update persistent clock */
+ persistent_clock_start_alarmtimer();
return 0;
out_drv:
diff --git a/kernel/time/persistent_clock.c b/kernel/time/persistent_clock.c
new file mode 100644
index 0000000..edaa659
--- /dev/null
+++ b/kernel/time/persistent_clock.c
@@ -0,0 +1,184 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 Linaro, Inc.
+ *
+ * Author: Baolin Wang <baolin.wang@linaro.org>
+ */
+
+#include <linux/alarmtimer.h>
+#include <linux/clocksource.h>
+#include <linux/persistent_clock.h>
+
+/**
+ * persistent_clock_read_data - data required to read persistent clock
+ * @read: Returns a cycle value from persistent clock.
+ * @last_cycles: Clock cycle value at last update.
+ * @last_ns: Time value (nanoseconds) at last update.
+ * @mask: Bitmask for two's complement subtraction of non 64bit clocks.
+ * @mult: Cycle to nanosecond multiplier.
+ * @shift: Cycle to nanosecond divisor.
+ */
+struct persistent_clock_read_data {
+ u64 (*read)(void);
+ u64 last_cycles;
+ u64 last_ns;
+ u64 mask;
+ u32 mult;
+ u32 shift;
+};
+
+/**
+ * persistent_clock - represent the persistent clock
+ * @read_data: Data required to read from persistent clock.
+ * @seq: Sequence counter for protecting updates.
+ * @freq: The frequency of the persistent clock.
+ * @wrap: Duration for persistent clock can run before wrapping.
+ * @alarm: Update timeout for persistent clock wrap.
+ * @alarm_inited: Indicate if the alarm has been initialized.
+ */
+struct persistent_clock {
+ struct persistent_clock_read_data read_data;
+ seqcount_t seq;
+ u32 freq;
+ ktime_t wrap;
+ struct alarm alarm;
+ bool alarm_inited;
+};
+
+static struct persistent_clock p;
+
+void read_persistent_clock64(struct timespec64 *ts)
+{
+ struct persistent_clock_read_data *read_data = &p.read_data;
+ unsigned long seq;
+ u64 delta, nsecs;
+
+ if (!read_data->read) {
+ ts->tv_sec = 0;
+ ts->tv_nsec = 0;
+ return;
+ }
+
+ do {
+ seq = read_seqcount_begin(&p.seq);
+ delta = (read_data->read() - read_data->last_cycles) &
+ read_data->mask;
+
+ nsecs = read_data->last_ns +
+ clocksource_cyc2ns(delta, read_data->mult,
+ read_data->shift);
+ *ts = ns_to_timespec64(nsecs);
+ } while (read_seqcount_retry(&p.seq, seq));
+}
+
+static void persistent_clock_update(void)
+{
+ struct persistent_clock_read_data *read_data = &p.read_data;
+ u64 cycles, delta;
+
+ write_seqcount_begin(&p.seq);
+
+ cycles = read_data->read();
+ delta = (cycles - read_data->last_cycles) & read_data->mask;
+ read_data->last_ns += clocksource_cyc2ns(delta, read_data->mult,
+ read_data->shift);
+ read_data->last_cycles = cycles;
+
+ write_seqcount_end(&p.seq);
+}
+
+static enum alarmtimer_restart persistent_clock_alarm_fired(struct alarm *alarm,
+ ktime_t now)
+{
+ persistent_clock_update();
+
+ alarm_forward(&p.alarm, now, p.wrap);
+ return ALARMTIMER_RESTART;
+}
+
+int persistent_clock_init_and_register(u64 (*read)(void), u64 mask,
+ u32 freq, u64 maxsec)
+{
+ struct persistent_clock_read_data *read_data = &p.read_data;
+ u64 wrap, res, secs = maxsec;
+
+ if (!read || !mask || !freq)
+ return -EINVAL;
+
+ if (!secs) {
+ /*
+ * If the timer driver did not specify the maximum conversion
+ * seconds of the persistent clock, then we calculate the
+ * conversion range with the persistent clock's bits and
+ * frequency.
+ */
+ secs = mask;
+ do_div(secs, freq);
+
+ /*
+ * Some persistent counter can be larger than 32bit, so we
+ * need limit the max suspend time to have a good conversion
+ * precision. So 24 hours may be enough usually.
+ */
+ if (secs > 86400)
+ secs = 86400;
+ }
+
+ /* Calculate the mult/shift to convert cycles to ns. */
+ clocks_calc_mult_shift(&read_data->mult, &read_data->shift, freq,
+ NSEC_PER_SEC, (u32)secs);
+
+ /* Calculate how many nanoseconds until we risk wrapping. */
+ wrap = clocks_calc_max_nsecs(read_data->mult, read_data->shift, 0,
+ mask, NULL);
+ p.wrap = ns_to_ktime(wrap);
+
+ p.freq = freq;
+ read_data->mask = mask;
+ read_data->read = read;
+
+ persistent_clock_update();
+
+ /* Calculate the ns resolution of this persistent clock. */
+ res = clocksource_cyc2ns(1ULL, read_data->mult, read_data->shift);
+
+ pr_info("persistent clock: mask %llu at %uHz, resolution %lluns, wraps every %lluns\n",
+ mask, freq, res, wrap);
+ return 0;
+}
+
+void persistent_clock_cleanup(void)
+{
+ p.read_data.read = NULL;
+
+ if (p.alarm_inited) {
+ alarm_cancel(&p.alarm);
+ p.alarm_inited = false;
+ }
+}
+
+void persistent_clock_start_alarmtimer(void)
+{
+ struct persistent_clock_read_data *read_data = &p.read_data;
+ ktime_t now;
+
+ /*
+ * If no persistent clock function has been provided or the alarmtimer
+ * has been initialized at that point, just return.
+ */
+ if (!read_data->read || p.alarm_inited)
+ return;
+
+ persistent_clock_update();
+
+ /*
+ * Since the persistent clock will not be stopped when system enters the
+ * suspend state, thus we need start one alarmtimer to wakeup the system
+ * to update the persistent clock before wrapping. We should start the
+ * update alarmtimer after the alarmtimer subsystem was initialized.
+ */
+ alarm_init(&p.alarm, ALARM_BOOTTIME, persistent_clock_alarm_fired);
+ now = ktime_get_boottime();
+ alarm_start(&p.alarm, ktime_add(now, p.wrap));
+ p.alarm_inited = true;
+}
--
1.7.9.5
^ permalink raw reply related
* [PATCH 2/8] clocksource: sprd: Add one persistent timer for Spreadtrum platform
From: Baolin Wang @ 2018-06-13 11:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1528878545.git.baolin.wang@linaro.org>
On Spreadtrum SC9860 platform, we need one persistent timer to calculate
the suspend time to compensate the OS time.
This patch registers one Spreadtrum AON timer as persistent timer, which
runs at 32bit and periodic mode.
Signed-off-by: Baolin Wang <baolin.wang@linaro.org>
---
drivers/clocksource/Kconfig | 1 +
drivers/clocksource/timer-sprd.c | 80 ++++++++++++++++++++++++++++++++++++++
2 files changed, 81 insertions(+)
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index dec0dd8..7f11c6c 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -455,6 +455,7 @@ config SPRD_TIMER
depends on (ARCH_SPRD || COMPILE_TEST)
default ARCH_SPRD
select TIMER_OF
+ select PERSISTENT_CLOCK
help
Enables support for the Spreadtrum timer driver.
diff --git a/drivers/clocksource/timer-sprd.c b/drivers/clocksource/timer-sprd.c
index ef9ebea..c6f657a 100644
--- a/drivers/clocksource/timer-sprd.c
+++ b/drivers/clocksource/timer-sprd.c
@@ -3,8 +3,11 @@
* Copyright (C) 2017 Spreadtrum Communications Inc.
*/
+#include <linux/clk.h>
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/of_address.h>
+#include <linux/persistent_clock.h>
#include "timer-of.h"
@@ -157,3 +160,80 @@ static int __init sprd_timer_init(struct device_node *np)
}
TIMER_OF_DECLARE(sc9860_timer, "sprd,sc9860-timer", sprd_timer_init);
+
+void __iomem *pbase;
+
+static u64 sprd_persistent_timer_read(void)
+{
+ return ~(u64)readl_relaxed(pbase + TIMER_VALUE_SHDW_LO) &
+ CLOCKSOURCE_MASK(32);
+}
+
+static void sprd_persistent_timer_disable(void)
+{
+ sprd_timer_disable(pbase);
+}
+
+static void sprd_persistent_timer_enable(void)
+{
+ sprd_timer_disable(pbase);
+ sprd_timer_update_counter(pbase, TIMER_VALUE_LO_MASK);
+ sprd_timer_enable(pbase, TIMER_CTL_PERIOD_MODE);
+}
+
+static int __init sprd_persistent_timer_init(struct device_node *np)
+{
+ struct clk *clk;
+ u32 freq;
+ int ret;
+
+ clk = of_clk_get(np, 0);
+ if (IS_ERR(clk)) {
+ pr_err("Can't get timer clock for %pOF\n", np);
+ return PTR_ERR(clk);
+ }
+
+ ret = clk_prepare_enable(clk);
+ if (ret) {
+ pr_err("Failed to enable clock for %pOF\n", np);
+ clk_put(clk);
+ return ret;
+ }
+
+ freq = clk_get_rate(clk);
+ if (!freq) {
+ pr_err("Failed to get clock rate for %pOF\n", np);
+ ret = -EINVAL;
+ goto clk_rate_err;
+ }
+
+ pbase = of_io_request_and_map(np, 0, of_node_full_name(np));
+ if (IS_ERR(pbase)) {
+ pr_err("Can't map timer registers for %pOF\n", np);
+ ret = PTR_ERR(pbase);
+ goto clk_rate_err;
+ }
+
+ sprd_persistent_timer_enable();
+
+ ret = persistent_clock_init_and_register(sprd_persistent_timer_read,
+ CLOCKSOURCE_MASK(32), freq, 0);
+ if (ret) {
+ pr_err("Failed to register persistent clock for %pOF\n", np);
+ goto persist_err;
+ }
+
+ return 0;
+
+persist_err:
+ sprd_persistent_timer_disable();
+ iounmap(pbase);
+clk_rate_err:
+ clk_disable_unprepare(clk);
+ clk_put(clk);
+
+ return ret;
+}
+
+TIMER_OF_DECLARE(sc9860_persistent_timer, "sprd,sc9860-persistent-timer",
+ sprd_persistent_timer_init);
--
1.7.9.5
^ permalink raw reply related
* [PATCH 3/8] arm: time: Remove the persistent clock support for ARM architecture
From: Baolin Wang @ 2018-06-13 11:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1528878545.git.baolin.wang@linaro.org>
We have introduced the persistent clock framework to support the OS time
compensating from persistent clock, and we will convert all drivers to
use common persistent clock framework instead of the persistent clock
support used only for the ARM architecture. So we can remove these code
with converting the Omap 32k counter and tegra20 timer.
Moreover there are no drivers will register read_boot_clock64(), so
remove it too.
Signed-off-by: Baolin Wang <baolin.wang@linaro.org>
---
arch/arm/include/asm/mach/time.h | 4 ----
arch/arm/kernel/time.c | 36 ----------------------------
arch/arm/plat-omap/Kconfig | 1 +
arch/arm/plat-omap/counter_32k.c | 44 ++++++-----------------------------
drivers/clocksource/tegra20_timer.c | 12 +++++++---
5 files changed, 17 insertions(+), 80 deletions(-)
diff --git a/arch/arm/include/asm/mach/time.h b/arch/arm/include/asm/mach/time.h
index 0f79e4d..3cbcafc 100644
--- a/arch/arm/include/asm/mach/time.h
+++ b/arch/arm/include/asm/mach/time.h
@@ -12,8 +12,4 @@
extern void timer_tick(void);
-typedef void (*clock_access_fn)(struct timespec64 *);
-extern int register_persistent_clock(clock_access_fn read_boot,
- clock_access_fn read_persistent);
-
#endif
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index cf2701c..713905c 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -76,42 +76,6 @@ void timer_tick(void)
}
#endif
-static void dummy_clock_access(struct timespec64 *ts)
-{
- ts->tv_sec = 0;
- ts->tv_nsec = 0;
-}
-
-static clock_access_fn __read_persistent_clock = dummy_clock_access;
-static clock_access_fn __read_boot_clock = dummy_clock_access;
-
-void read_persistent_clock64(struct timespec64 *ts)
-{
- __read_persistent_clock(ts);
-}
-
-void read_boot_clock64(struct timespec64 *ts)
-{
- __read_boot_clock(ts);
-}
-
-int __init register_persistent_clock(clock_access_fn read_boot,
- clock_access_fn read_persistent)
-{
- /* Only allow the clockaccess functions to be registered once */
- if (__read_persistent_clock == dummy_clock_access &&
- __read_boot_clock == dummy_clock_access) {
- if (read_boot)
- __read_boot_clock = read_boot;
- if (read_persistent)
- __read_persistent_clock = read_persistent;
-
- return 0;
- }
-
- return -EINVAL;
-}
-
void __init time_init(void)
{
if (machine_desc->init_time) {
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index c0a242c..073a80f 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -1,5 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
config ARCH_OMAP
+ select PERSISTENT_CLOCK
bool
if ARCH_OMAP
diff --git a/arch/arm/plat-omap/counter_32k.c b/arch/arm/plat-omap/counter_32k.c
index 2438b96..5d52f7c 100644
--- a/arch/arm/plat-omap/counter_32k.c
+++ b/arch/arm/plat-omap/counter_32k.c
@@ -19,8 +19,7 @@
#include <linux/io.h>
#include <linux/clocksource.h>
#include <linux/sched_clock.h>
-
-#include <asm/mach/time.h>
+#include <linux/persistent_clock.h>
#include <plat/counter-32k.h>
@@ -44,33 +43,6 @@ static u64 notrace omap_32k_read_sched_clock(void)
}
/**
- * omap_read_persistent_clock64 - Return time from a persistent clock.
- *
- * Reads the time from a source which isn't disabled during PM, the
- * 32k sync timer. Convert the cycles elapsed since last read into
- * nsecs and adds to a monotonically increasing timespec64.
- */
-static struct timespec64 persistent_ts;
-static cycles_t cycles;
-static unsigned int persistent_mult, persistent_shift;
-
-static void omap_read_persistent_clock64(struct timespec64 *ts)
-{
- unsigned long long nsecs;
- cycles_t last_cycles;
-
- last_cycles = cycles;
- cycles = sync32k_cnt_reg ? readl_relaxed(sync32k_cnt_reg) : 0;
-
- nsecs = clocksource_cyc2ns(cycles - last_cycles,
- persistent_mult, persistent_shift);
-
- timespec64_add_ns(&persistent_ts, nsecs);
-
- *ts = persistent_ts;
-}
-
-/**
* omap_init_clocksource_32k - setup and register counter 32k as a
* kernel clocksource
* @pbase: base addr of counter_32k module
@@ -95,13 +67,6 @@ int __init omap_init_clocksource_32k(void __iomem *vbase)
else
sync32k_cnt_reg = vbase + OMAP2_32KSYNCNT_CR_OFF_LOW;
- /*
- * 120000 rough estimate from the calculations in
- * __clocksource_update_freq_scale.
- */
- clocks_calc_mult_shift(&persistent_mult, &persistent_shift,
- 32768, NSEC_PER_SEC, 120000);
-
ret = clocksource_mmio_init(sync32k_cnt_reg, "32k_counter", 32768,
250, 32, clocksource_mmio_readl_up);
if (ret) {
@@ -110,7 +75,12 @@ int __init omap_init_clocksource_32k(void __iomem *vbase)
}
sched_clock_register(omap_32k_read_sched_clock, 32, 32768);
- register_persistent_clock(NULL, omap_read_persistent_clock64);
+ /*
+ * 120000 rough estimate from the calculations in
+ * __clocksource_update_freq_scale.
+ */
+ persistent_clock_init_and_register(omap_32k_read_sched_clock,
+ CLOCKSOURCE_MASK(32), 32768, 120000);
pr_info("OMAP clocksource: 32k_counter at 32768 Hz\n");
return 0;
diff --git a/drivers/clocksource/tegra20_timer.c b/drivers/clocksource/tegra20_timer.c
index c337a81..97a34cb 100644
--- a/drivers/clocksource/tegra20_timer.c
+++ b/drivers/clocksource/tegra20_timer.c
@@ -124,7 +124,7 @@ static u64 tegra_rtc_read_ms(void)
}
/*
- * tegra_read_persistent_clock64 - Return time from a persistent clock.
+ * read_persistent_clock64 - Return time from a persistent clock.
*
* Reads the time from a source which isn't disabled during PM, the
* 32k sync timer. Convert the cycles elapsed since last read into
@@ -133,10 +133,16 @@ static u64 tegra_rtc_read_ms(void)
* tegra_rtc driver could be executing to avoid race conditions
* on the RTC shadow register
*/
-static void tegra_read_persistent_clock64(struct timespec64 *ts)
+void read_persistent_clock64(struct timespec64 *ts)
{
u64 delta;
+ if (!rtc_base) {
+ ts->tv_sec = 0;
+ ts->tv_nsec = 0;
+ return;
+ }
+
last_persistent_ms = persistent_ms;
persistent_ms = tegra_rtc_read_ms();
delta = persistent_ms - last_persistent_ms;
@@ -259,6 +265,6 @@ static int __init tegra20_init_rtc(struct device_node *np)
else
clk_prepare_enable(clk);
- return register_persistent_clock(NULL, tegra_read_persistent_clock64);
+ return 0;
}
TIMER_OF_DECLARE(tegra20_rtc, "nvidia,tegra20-rtc", tegra20_init_rtc);
--
1.7.9.5
^ permalink raw reply related
* [PATCH 4/8] clocksource: arm_arch_timer: Register the persistent clock
From: Baolin Wang @ 2018-06-13 11:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1528878545.git.baolin.wang@linaro.org>
Register the persistent clock to compensate the suspend time for OS time,
if the ARM counter clocksource will not be stopped in suspend state.
Signed-off-by: Baolin Wang <baolin.wang@linaro.org>
---
drivers/clocksource/Kconfig | 1 +
drivers/clocksource/arm_arch_timer.c | 10 ++++++++++
2 files changed, 11 insertions(+)
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 7f11c6c..5e51fcf 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -308,6 +308,7 @@ config ARC_TIMERS_64BIT
config ARM_ARCH_TIMER
bool
+ select PERSISTENT_CLOCK
select TIMER_OF if OF
select TIMER_ACPI if ACPI
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 57cb2f0..671be63 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -32,6 +32,7 @@
#include <asm/virt.h>
#include <clocksource/arm_arch_timer.h>
+#include <linux/persistent_clock.h>
#undef pr_fmt
#define pr_fmt(fmt) "arch_timer: " fmt
@@ -950,6 +951,15 @@ static void __init arch_counter_register(unsigned type)
/* 56 bits minimum, so we assume worst case rollover */
sched_clock_register(arch_timer_read_counter, 56, arch_timer_rate);
+
+ /*
+ * Register the persistent clock if the clocksource will not be stopped
+ * in suspend state.
+ */
+ if (!arch_counter_suspend_stop)
+ persistent_clock_init_and_register(arch_timer_read_counter,
+ CLOCKSOURCE_MASK(56),
+ arch_timer_rate, 0);
}
static void arch_timer_stop(struct clock_event_device *clk)
--
1.7.9.5
^ permalink raw reply related
* [PATCH 5/8] clocksource: timer-ti-32k: Register the persistent clock
From: Baolin Wang @ 2018-06-13 11:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1528878545.git.baolin.wang@linaro.org>
Since the 32K counter is always available, then we can register the
persistent clock to compensate the suspend time for the OS time.
Signed-off-by: Baolin Wang <baolin.wang@linaro.org>
---
drivers/clocksource/Kconfig | 1 +
drivers/clocksource/timer-ti-32k.c | 4 ++++
2 files changed, 5 insertions(+)
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 5e51fcf..3cd136f 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -262,6 +262,7 @@ config CLKSRC_TI_32K
bool "Texas Instruments 32.768 Hz Clocksource" if COMPILE_TEST
depends on GENERIC_SCHED_CLOCK
select TIMER_OF if OF
+ select PERSISTENT_CLOCK
help
This option enables support for Texas Instruments 32.768 Hz clocksource
available on many OMAP-like platforms.
diff --git a/drivers/clocksource/timer-ti-32k.c b/drivers/clocksource/timer-ti-32k.c
index 880a861..353ff9d 100644
--- a/drivers/clocksource/timer-ti-32k.c
+++ b/drivers/clocksource/timer-ti-32k.c
@@ -41,6 +41,7 @@
#include <linux/clocksource.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/persistent_clock.h>
/*
* 32KHz clocksource ... always available, on pretty most chips except
@@ -120,6 +121,9 @@ static int __init ti_32k_timer_init(struct device_node *np)
}
sched_clock_register(omap_32k_read_sched_clock, 32, 32768);
+ persistent_clock_init_and_register(omap_32k_read_sched_clock,
+ CLOCKSOURCE_MASK(32), 32768, 0);
+
pr_info("OMAP clocksource: 32k_counter at 32768 Hz\n");
return 0;
--
1.7.9.5
^ permalink raw reply related
* [PATCH 6/8] clocksource: time-pistachio: Register the persistent clock
From: Baolin Wang @ 2018-06-13 11:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1528878545.git.baolin.wang@linaro.org>
Since the timer on pistachio platform is always available, we can
register it as one persistent clock to compensate the suspend time
for the OS time.
Signed-off-by: Baolin Wang <baolin.wang@linaro.org>
---
drivers/clocksource/Kconfig | 1 +
drivers/clocksource/time-pistachio.c | 3 +++
2 files changed, 4 insertions(+)
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 3cd136f..af552ba 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -255,6 +255,7 @@ config CLKSRC_PISTACHIO
bool "Clocksource for Pistachio SoC" if COMPILE_TEST
depends on HAS_IOMEM
select TIMER_OF
+ select PERSISTENT_CLOCK
help
Enables the clocksource for the Pistachio SoC.
diff --git a/drivers/clocksource/time-pistachio.c b/drivers/clocksource/time-pistachio.c
index a2dd85d..5c3eb71 100644
--- a/drivers/clocksource/time-pistachio.c
+++ b/drivers/clocksource/time-pistachio.c
@@ -20,6 +20,7 @@
#include <linux/mfd/syscon.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/persistent_clock.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/sched_clock.h>
@@ -212,6 +213,8 @@ static int __init pistachio_clksrc_of_init(struct device_node *node)
raw_spin_lock_init(&pcs_gpt.lock);
sched_clock_register(pistachio_read_sched_clock, 32, rate);
+ persistent_clock_init_and_register(pistachio_read_sched_clock,
+ CLOCKSOURCE_MASK(32), rate, 0);
return clocksource_register_hz(&pcs_gpt.cs, rate);
}
TIMER_OF_DECLARE(pistachio_gptimer, "img,pistachio-gptimer",
--
1.7.9.5
^ permalink raw reply related
* [PATCH 7/8] x86: tsc: Register the persistent clock
From: Baolin Wang @ 2018-06-13 11:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1528878545.git.baolin.wang@linaro.org>
Register the tsc as one persistent clock to compensate the suspend time
if the tsc clocksource is always available.
Signed-off-by: Baolin Wang <baolin.wang@linaro.org>
---
arch/x86/Kconfig | 1 +
arch/x86/kernel/tsc.c | 21 +++++++++++++++++++++
2 files changed, 22 insertions(+)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 297789a..549dd01 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -200,6 +200,7 @@ config X86
select USER_STACKTRACE_SUPPORT
select VIRT_TO_BUS
select X86_FEATURE_NAMES if PROC_FS
+ select PERSISTENT_CLOCK
config INSTRUCTION_DECODER
def_bool y
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index 74392d9..cb4f495 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -11,6 +11,7 @@
#include <linux/delay.h>
#include <linux/clocksource.h>
#include <linux/percpu.h>
+#include <linux/persistent_clock.h>
#include <linux/timex.h>
#include <linux/static_key.h>
@@ -1032,6 +1033,11 @@ static u64 read_tsc(struct clocksource *cs)
return (u64)rdtsc_ordered();
}
+static u64 notrace tsc_read_persistent_clock(void)
+{
+ return (u64)rdtsc_ordered();
+}
+
static void tsc_cs_mark_unstable(struct clocksource *cs)
{
if (tsc_unstable)
@@ -1300,6 +1306,14 @@ static void tsc_refine_calibration_work(struct work_struct *work)
if (boot_cpu_has(X86_FEATURE_ART))
art_related_clocksource = &clocksource_tsc;
clocksource_register_khz(&clocksource_tsc, tsc_khz);
+
+ if (clocksource_tsc.flags & CLOCK_SOURCE_SUSPEND_NONSTOP) {
+ persistent_clock_init_and_register(tsc_read_persistent_clock,
+ CLOCKSOURCE_MASK(64),
+ tsc_khz * 1000, 0);
+ persistent_clock_start_alarmtimer();
+ }
+
unreg:
clocksource_unregister(&clocksource_tsc_early);
}
@@ -1327,6 +1341,13 @@ static int __init init_tsc_clocksource(void)
if (boot_cpu_has(X86_FEATURE_ART))
art_related_clocksource = &clocksource_tsc;
clocksource_register_khz(&clocksource_tsc, tsc_khz);
+
+ if (clocksource_tsc.flags & CLOCK_SOURCE_SUSPEND_NONSTOP) {
+ persistent_clock_init_and_register(tsc_read_persistent_clock,
+ CLOCKSOURCE_MASK(64),
+ tsc_khz * 1000, 0);
+ persistent_clock_start_alarmtimer();
+ }
unreg:
clocksource_unregister(&clocksource_tsc_early);
return 0;
--
1.7.9.5
^ 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