* [PATCH v2 0/3] dmaengine: xilinx_dma: Bug fixes
From: Kedareswara rao Appana @ 2016-12-23 8:52 UTC (permalink / raw)
To: linux-arm-kernel
This patch series fixes below bugs in DMA and VDMA IP's
---> Do not start VDMA until frame buffer is processed by the h/w Fix
---> bug in Multi frame sotres handling in VDMA Fix issues w.r.to multi
---> frame descriptors submit with AXI DMA S2MM(recv) Side.
Kedareswara rao Appana (3):
dmaengine: xilinx_dma: Check for channel idle state before submitting
dma descriptor
dmaeninge: xilinx_dma: Fix bug in multiple frame stores scenario in
vdma
dmaengine: xilinx_dma: Fix race condition in the driver for multiple
descriptor scenario
drivers/dma/xilinx/xilinx_dma.c | 241 ++++++++++++++++++++++------------------
1 file changed, 130 insertions(+), 111 deletions(-)
--
2.1.2
^ permalink raw reply
* [PATCH 1/3] dmaengine: xilinx_dma: Check for channel idle state before submitting dma descriptor
From: Appana Durga Kedareswara Rao @ 2016-12-23 8:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <2156938.MvgiZll4tB@avalon>
Hi Laurent Pinchart,
Sorry for the delay in the reply.
Thanks for the review...
>
> Hi Kedar,
>
> On Monday 19 Dec 2016 15:39:43 Appana Durga Kedareswara Rao wrote:
> > Hi Laurent Pinchart,
> >
> > Thanks for the review...
> >
> > > > + if (!chan->idle)
> > > > + return;
> > >
> > > Don't you need to perform the same check for the DMA and CDMA channels
> ?
> > > If so, shouldn't this be moved to common code ?
> >
> > Will fix it in v2...
> >
> > > There's another problem (not strictly introduced by this patch) I
> > > wanted to mention. The append_desc_queue() function, called from
> > > your tx_submit handler, appends descriptors to the pending_list. The
> > > DMA engine API states that a transfer submitted by tx_submit will
> > > not be executed until
> > > .issue_pending() is called. However, if a transfer is in progress at
> > > tx_submit time, I believe that the IRQ handler, at transfer
> > > completion, will start the next transfer from the pending_list even
> > > if
> > > .issue_pending() hasn't been called for it.
> > >
> > > > if (list_empty(&chan->pending_list))
> > > > return;
> >
> > If user submits more than h/w limit then that case only driver will
> > process The descriptors from the pending_list for other cases the
> > pending_list will be Empty so driver just returns from there.
>
> I understand that, but that's not the problem. Your .tx_submit() handler calls
> append_desc_queue() which adds the tx descriptor to the pending_list. If a
> transfer is in progress at that time, I believe the transfer completion IRQ handler
> will take the next descriptor from the pending_list and process it, even though
> issue_pending() hasn't been called for it.
>
Thanks for the explanation...
Agree will keep this my to-do list...
Regards,
Kedar.
^ permalink raw reply
* [PATCH v1] watchdog: imx2: fix hang-up on boot for i.MX21, i.MX27 and i.MX31 SoCs
From: Uwe Kleine-König @ 2016-12-23 8:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <bedae3d8-3057-36e4-1d89-ec41f9f1a25b@mleia.com>
Hello,
On Fri, Dec 23, 2016 at 10:20:20AM +0200, Vladimir Zapolskiy wrote:
> On 12/23/2016 03:55 AM, Guenter Roeck wrote:
> > What is the ultimate conclusion of this exchange ?
> >
> > Are we going to get another version of the patch, or did everyone agree that
> > the patch is good as it is and does not require further changes ?
> >
>
> I can not imagine a different fix.
my preferred fix would be:
- add an imx35 compatible to all newer dtsi
- update the driver to only write the wmcr on imx35 compatible devices
adding only imx35.
Compared to Vladimir's change this undoes 5fe65ce7ccbb ("watchdog:
imx2_wdt: Disable power down counter on boot") on the newer generation
SoCs until their dtb is updated. 5fe65ce7ccbb fixed a problem in 2014
for these newer SoCs which wasn't urgent enough to be fixed earlier, so
I'd say this isn't a big problem and in return the drivers and device
trees stay simpler.
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-K?nig |
Industrial Linux Solutions | http://www.pengutronix.de/ |
^ permalink raw reply
* [PATCH v1] watchdog: imx2: fix hang-up on boot for i.MX21, i.MX27 and i.MX31 SoCs
From: Vladimir Zapolskiy @ 2016-12-23 8:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <fe9b03bf-9c37-862f-b3aa-0f9b5a4dfefb@roeck-us.net>
On 12/23/2016 03:55 AM, Guenter Roeck wrote:
> On 12/11/2016 03:21 AM, Vladimir Zapolskiy wrote:
>> On 12/11/2016 12:26 PM, Uwe Kleine-K?nig wrote:
>>> Hello Vladimir,
>>>
>>> On Sun, Dec 11, 2016 at 12:01:08PM +0200, Vladimir Zapolskiy wrote:
>>>> On 12/11/2016 11:35 AM, Uwe Kleine-K?nig wrote:
>>>>> On Sun, Dec 11, 2016 at 03:06:48AM +0200, Vladimir Zapolskiy wrote:
>>>>>> Power down counter enable/disable bit switch is located in WMCR
>>>>>> register, but watchdog controllers found on legacy i.MX21, i.MX27 and
>>>>>> i.MX31 SoCs don't have this register. As a result of writing data to
>>>>>> the non-existing register on driver probe the SoC hangs up, to fix the
>>>>>> problem add more OF compatible strings and on this basis get
>>>>>> information about availability of the WMCR register.
>>>>>>
>>>>>> Fixes: 5fe65ce7ccbb ("watchdog: imx2_wdt: Disable power down counter on boot")
>>>>>> Signed-off-by: Vladimir Zapolskiy <vz@mleia.com>
>>>>>> ---
>>>>
>
>
> What is the ultimate conclusion of this exchange ?
>
> Are we going to get another version of the patch, or did everyone agree that
> the patch is good as it is and does not require further changes ?
>
I can not imagine a different fix.
--
With best wishes,
Vladimir
^ permalink raw reply
* [PATCH v3] mm: pmd dirty emulation in page fault handler
From: Minchan Kim @ 2016-12-23 7:53 UTC (permalink / raw)
To: linux-arm-kernel
Andreas reported [1] made a test in jemalloc hang in THP mode in arm64.
http://lkml.kernel.org/r/mvmmvfy37g1.fsf at hawking.suse.de
The problem is page fault handler supports only accessed flag emulation
for THP page of SW-dirty/accessed architecture.
This patch enables dirty-bit emulation for those architectures.
Without it, MADV_FREE makes application hang by repeated fault forever.
[1] b8d3c4c3009d, mm/huge_memory.c: don't split THP page when MADV_FREE syscall is called
Cc: Jason Evans <je@fb.com>
Cc: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: linux-arch at vger.kernel.org
Cc: linux-arm-kernel at lists.infradead.org
Cc: <stable@vger.kernel.org> [4.5+]
Fixes: b8d3c4c3009d ("mm/huge_memory.c: don't split THP page when MADV_FREE syscall is called")
Reported-and-Tested-by: Andreas Schwab <schwab@suse.de>
Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Signed-off-by: Minchan Kim <minchan@kernel.org>
---
* from v2
* Add acked-by/tested-by
* from v1
* Remove __handle_mm_fault part - Kirill
mm/huge_memory.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 10eedbf..29ec8a4 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -883,15 +883,17 @@ void huge_pmd_set_accessed(struct vm_fault *vmf, pmd_t orig_pmd)
{
pmd_t entry;
unsigned long haddr;
+ bool write = vmf->flags & FAULT_FLAG_WRITE;
vmf->ptl = pmd_lock(vmf->vma->vm_mm, vmf->pmd);
if (unlikely(!pmd_same(*vmf->pmd, orig_pmd)))
goto unlock;
entry = pmd_mkyoung(orig_pmd);
+ if (write)
+ entry = pmd_mkdirty(entry);
haddr = vmf->address & HPAGE_PMD_MASK;
- if (pmdp_set_access_flags(vmf->vma, haddr, vmf->pmd, entry,
- vmf->flags & FAULT_FLAG_WRITE))
+ if (pmdp_set_access_flags(vmf->vma, haddr, vmf->pmd, entry, write))
update_mmu_cache_pmd(vmf->vma, vmf->address, vmf->pmd);
unlock:
--
2.7.4
^ permalink raw reply related
* [PATCH V5 1/3] ARM64 LPC: Indirect ISA port IO introduced
From: Ming Lei @ 2016-12-23 7:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <585C815B.4030000@hisilicon.com>
On Fri, Dec 23, 2016 at 9:43 AM, zhichang.yuan
<yuanzhichang@hisilicon.com> wrote:
> Hi?Ming,
>
>
> On 2016/12/22 16:15, Ming Lei wrote:
>> Hi Guys,
>>
>> On Tue, Nov 8, 2016 at 11:47 AM, zhichang.yuan
>> <yuanzhichang@hisilicon.com> wrote:
>>> For arm64, there is no I/O space as other architectural platforms, such as
>>> X86. Most I/O accesses are achieved based on MMIO. But for some arm64 SoCs,
>>> such as Hip06, when accessing some legacy ISA devices connected to LPC, those
>>> known port addresses are used to control the corresponding target devices, for
>>> example, 0x2f8 is for UART, 0xe4 is for ipmi-bt. It is different from the
>>> normal MMIO mode in using.
>>>
>>> To drive these devices, this patch introduces a method named indirect-IO.
>>> In this method the in/out pair in arch/arm64/include/asm/io.h will be
>>> redefined. When upper layer drivers call in/out with those known legacy port
>>> addresses to access the peripherals, the hooking functions corrresponding to
>>> those target peripherals will be called. Through this way, those upper layer
>>> drivers which depend on in/out can run on Hip06 without any changes.
>>>
>>> Cc: Catalin Marinas <catalin.marinas@arm.com>
>>> Cc: Will Deacon <will.deacon@arm.com>
>>> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
>>> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
>>> ---
>>> arch/arm64/Kconfig | 6 +++
>>> arch/arm64/include/asm/extio.h | 94 ++++++++++++++++++++++++++++++++++++++++++
>>> arch/arm64/include/asm/io.h | 29 +++++++++++++
>>> arch/arm64/kernel/Makefile | 1 +
>>> arch/arm64/kernel/extio.c | 27 ++++++++++++
>>> 5 files changed, 157 insertions(+)
>>
>> When I applied these three patches against current linus tree and
>> enable CONFIG_HISILICON_LPC, the following build failure[1] is
>> triggered when running 'make modules'.
>>
>
> Thanks for your report!
>
> This patch has compilation issue on some architectures, sorry for the inconvenience caused by this!
> The ongoing v6 will solve these issues.
> I will trace this failure and provide a fix if you can not wait for the next version.
>
> Could you send me your .config in private? I don't want to bother all the hacker in the mail-list.
>
Sure, please see the config in attachment.
>
> Thanks,
> Zhichang
>
>>
>> Thanks,
>> Ming
>>
>> [1] 'make modules' failure log
>>
>> Building modules, stage 2.
>> MODPOST 2260 modules
>> ERROR: "inb" [drivers/watchdog/wdt_pci.ko] undefined!
>> ERROR: "outb" [drivers/watchdog/wdt_pci.ko] undefined!
>> ERROR: "outb" [drivers/watchdog/pcwd_pci.ko] undefined!
>> ERROR: "inb" [drivers/watchdog/pcwd_pci.ko] undefined!
>> ERROR: "outw" [drivers/video/vgastate.ko] undefined!
>> ERROR: "outb" [drivers/video/vgastate.ko] undefined!
>> ERROR: "inb" [drivers/video/vgastate.ko] undefined!
>> ERROR: "outw" [drivers/video/fbdev/vt8623fb.ko] undefined!
>> ERROR: "inb" [drivers/video/fbdev/vt8623fb.ko] undefined!
>> ERROR: "outb" [drivers/video/fbdev/vt8623fb.ko] undefined!
>> ERROR: "outw" [drivers/video/fbdev/tridentfb.ko] undefined!
>> ERROR: "inb" [drivers/video/fbdev/tridentfb.ko] undefined!
>> ERROR: "outb" [drivers/video/fbdev/tridentfb.ko] undefined!
>> ERROR: "inb" [drivers/video/fbdev/tdfxfb.ko] undefined!
>> .....
>> ERROR: "inb" [drivers/ata/pata_cmd64x.ko] undefined!
>> ERROR: "inb" [drivers/ata/pata_artop.ko] undefined!
>> scripts/Makefile.modpost:91: recipe for target '__modpost' failed
>> make[1]: *** [__modpost] Error 1
>> Makefile:1196: recipe for target 'modules' failed
>> make: *** [modules] Error 2
>>
>>
>>> create mode 100644 arch/arm64/include/asm/extio.h
>>> create mode 100644 arch/arm64/kernel/extio.c
>>>
>>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>>> index 969ef88..b44070b 100644
>>> --- a/arch/arm64/Kconfig
>>> +++ b/arch/arm64/Kconfig
>>> @@ -163,6 +163,12 @@ config ARCH_MMAP_RND_COMPAT_BITS_MIN
>>> config ARCH_MMAP_RND_COMPAT_BITS_MAX
>>> default 16
>>>
>>> +config ARM64_INDIRECT_PIO
>>> + bool "access peripherals with legacy I/O port"
>>> + help
>>> + Support special accessors for ISA I/O devices. This is needed for
>>> + SoCs that do not support standard read/write for the ISA range.
>>> +
>>> config NO_IOPORT_MAP
>>> def_bool y if !PCI
>>>
>>> diff --git a/arch/arm64/include/asm/extio.h b/arch/arm64/include/asm/extio.h
>>> new file mode 100644
>>> index 0000000..6ae0787
>>> --- /dev/null
>>> +++ b/arch/arm64/include/asm/extio.h
>>> @@ -0,0 +1,94 @@
>>> +/*
>>> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
>>> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License version 2 as
>>> + * published by the Free Software Foundation.
>>> + *
>>> + * This program is distributed in the hope that it will be useful,
>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>>> + * GNU General Public License for more details.
>>> + *
>>> + * You should have received a copy of the GNU General Public License
>>> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
>>> + */
>>> +
>>> +#ifndef __LINUX_EXTIO_H
>>> +#define __LINUX_EXTIO_H
>>> +
>>> +struct extio_ops {
>>> + unsigned long start;/* inclusive, sys io addr */
>>> + unsigned long end;/* inclusive, sys io addr */
>>> +
>>> + u64 (*pfin)(void *devobj, unsigned long ptaddr, size_t dlen);
>>> + void (*pfout)(void *devobj, unsigned long ptaddr, u32 outval,
>>> + size_t dlen);
>>> + u64 (*pfins)(void *devobj, unsigned long ptaddr, void *inbuf,
>>> + size_t dlen, unsigned int count);
>>> + void (*pfouts)(void *devobj, unsigned long ptaddr,
>>> + const void *outbuf, size_t dlen,
>>> + unsigned int count);
>>> + void *devpara;
>>> +};
>>> +
>>> +extern struct extio_ops *arm64_extio_ops;
>>> +
>>> +#define DECLARE_EXTIO(bw, type) \
>>> +extern type in##bw(unsigned long addr); \
>>> +extern void out##bw(type value, unsigned long addr); \
>>> +extern void ins##bw(unsigned long addr, void *buffer, unsigned int count);\
>>> +extern void outs##bw(unsigned long addr, const void *buffer, unsigned int count);
>>> +
>>> +#define BUILD_EXTIO(bw, type) \
>>> +type in##bw(unsigned long addr) \
>>> +{ \
>>> + if (!arm64_extio_ops || arm64_extio_ops->start > addr || \
>>> + arm64_extio_ops->end < addr) \
>>> + return read##bw(PCI_IOBASE + addr); \
>>> + return arm64_extio_ops->pfin ? \
>>> + arm64_extio_ops->pfin(arm64_extio_ops->devpara, \
>>> + addr, sizeof(type)) : -1; \
>>> +} \
>>> + \
>>> +void out##bw(type value, unsigned long addr) \
>>> +{ \
>>> + if (!arm64_extio_ops || arm64_extio_ops->start > addr || \
>>> + arm64_extio_ops->end < addr) \
>>> + write##bw(value, PCI_IOBASE + addr); \
>>> + else \
>>> + if (arm64_extio_ops->pfout) \
>>> + arm64_extio_ops->pfout(arm64_extio_ops->devpara,\
>>> + addr, value, sizeof(type)); \
>>> +} \
>>> + \
>>> +void ins##bw(unsigned long addr, void *buffer, unsigned int count) \
>>> +{ \
>>> + if (!arm64_extio_ops || arm64_extio_ops->start > addr || \
>>> + arm64_extio_ops->end < addr) \
>>> + reads##bw(PCI_IOBASE + addr, buffer, count); \
>>> + else \
>>> + if (arm64_extio_ops->pfins) \
>>> + arm64_extio_ops->pfins(arm64_extio_ops->devpara,\
>>> + addr, buffer, sizeof(type), count); \
>>> +} \
>>> + \
>>> +void outs##bw(unsigned long addr, const void *buffer, unsigned int count) \
>>> +{ \
>>> + if (!arm64_extio_ops || arm64_extio_ops->start > addr || \
>>> + arm64_extio_ops->end < addr) \
>>> + writes##bw(PCI_IOBASE + addr, buffer, count); \
>>> + else \
>>> + if (arm64_extio_ops->pfouts) \
>>> + arm64_extio_ops->pfouts(arm64_extio_ops->devpara,\
>>> + addr, buffer, sizeof(type), count); \
>>> +}
>>> +
>>> +static inline void arm64_set_extops(struct extio_ops *ops)
>>> +{
>>> + if (ops)
>>> + WRITE_ONCE(arm64_extio_ops, ops);
>>> +}
>>> +
>>> +#endif /* __LINUX_EXTIO_H*/
>>> diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
>>> index 0bba427..136735d 100644
>>> --- a/arch/arm64/include/asm/io.h
>>> +++ b/arch/arm64/include/asm/io.h
>>> @@ -31,6 +31,7 @@
>>> #include <asm/early_ioremap.h>
>>> #include <asm/alternative.h>
>>> #include <asm/cpufeature.h>
>>> +#include <asm/extio.h>
>>>
>>> #include <xen/xen.h>
>>>
>>> @@ -149,6 +150,34 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
>>> #define IO_SPACE_LIMIT (PCI_IO_SIZE - 1)
>>> #define PCI_IOBASE ((void __iomem *)PCI_IO_START)
>>>
>>> +
>>> +/*
>>> + * redefine the in(s)b/out(s)b for indirect-IO.
>>> + */
>>> +#ifdef CONFIG_ARM64_INDIRECT_PIO
>>> +#define inb inb
>>> +#define outb outb
>>> +#define insb insb
>>> +#define outsb outsb
>>> +/* external declaration */
>>> +DECLARE_EXTIO(b, u8)
>>> +
>>> +#define inw inw
>>> +#define outw outw
>>> +#define insw insw
>>> +#define outsw outsw
>>> +
>>> +DECLARE_EXTIO(w, u16)
>>> +
>>> +#define inl inl
>>> +#define outl outl
>>> +#define insl insl
>>> +#define outsl outsl
>>> +
>>> +DECLARE_EXTIO(l, u32)
>>> +#endif
>>> +
>>> +
>>> /*
>>> * String version of I/O memory access operations.
>>> */
>>> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
>>> index 7d66bba..60e0482 100644
>>> --- a/arch/arm64/kernel/Makefile
>>> +++ b/arch/arm64/kernel/Makefile
>>> @@ -31,6 +31,7 @@ arm64-obj-$(CONFIG_COMPAT) += sys32.o kuser32.o signal32.o \
>>> sys_compat.o entry32.o
>>> arm64-obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o entry-ftrace.o
>>> arm64-obj-$(CONFIG_MODULES) += arm64ksyms.o module.o
>>> +arm64-obj-$(CONFIG_ARM64_INDIRECT_PIO) += extio.o
>>> arm64-obj-$(CONFIG_ARM64_MODULE_PLTS) += module-plts.o
>>> arm64-obj-$(CONFIG_PERF_EVENTS) += perf_regs.o perf_callchain.o
>>> arm64-obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o
>>> diff --git a/arch/arm64/kernel/extio.c b/arch/arm64/kernel/extio.c
>>> new file mode 100644
>>> index 0000000..647b3fa
>>> --- /dev/null
>>> +++ b/arch/arm64/kernel/extio.c
>>> @@ -0,0 +1,27 @@
>>> +/*
>>> + * Copyright (C) 2016 Hisilicon Limited, All Rights Reserved.
>>> + * Author: Zhichang Yuan <yuanzhichang@hisilicon.com>
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License version 2 as
>>> + * published by the Free Software Foundation.
>>> + *
>>> + * This program is distributed in the hope that it will be useful,
>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>>> + * GNU General Public License for more details.
>>> + *
>>> + * You should have received a copy of the GNU General Public License
>>> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
>>> + */
>>> +
>>> +#include <linux/io.h>
>>> +
>>> +struct extio_ops *arm64_extio_ops;
>>> +
>>> +
>>> +BUILD_EXTIO(b, u8)
>>> +
>>> +BUILD_EXTIO(w, u16)
>>> +
>>> +BUILD_EXTIO(l, u32)
>>> --
>>> 1.9.1
>>>
>>
>>
>>
>
Thanks,
Ming Lei
-------------- next part --------------
A non-text attachment was scrubbed...
Name: config.tar.gz
Type: application/x-gzip
Size: 37193 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161223/4f3c2eff/attachment-0001.bin>
^ permalink raw reply
* [PATCH] serial: 8250: use initializer instead of memset to clear local struct
From: Greg Kroah-Hartman @ 2016-12-23 7:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1482463308-28968-1-git-send-email-yamada.masahiro@socionext.com>
On Fri, Dec 23, 2016 at 12:21:48PM +0900, Masahiro Yamada wrote:
> Leave the way of zero-out to the compiler's decision; the compiler
> may know a more optimized way than calling memset().
But no, it doesn't, it will leave "blank" areas in the structure with
bad data in it, which is why we do memset. See the tree-wide fixups we
made about a year ago for this very issue. Are you sure none of these
structures get copied to userspace?
> It may end up with memset() for big structures like this after all,
> but the code will be cleaner at least.
Please leave it as-is, unless you see a measured speedup.
thanks,
greg k-h
^ permalink raw reply
* [PATCH v5 6/6] arm64: arch_timer: acpi: add hisi timer errata data
From: Ding Tianhong @ 2016-12-23 7:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1482476669-15596-1-git-send-email-dingtianhong@huawei.com>
From: Hanjun Guo <hanjun.guo@linaro.org>
Add hisi timer specific erratum fixes.
v3: add hisilicon erratum 161601 for ACPI mode.
v4: update some data structures.
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: Ding Tianhong <dingtianhong@huawei.com>
---
drivers/clocksource/arm_arch_timer.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 212bfa5..7b15d2a 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -1089,10 +1089,28 @@ struct gtdt_arch_timer_fixup {
void *context;
};
+#ifdef CONFIG_HISILICON_ERRATUM_161601
+static void __init erratum_workaround_enable(void *context)
+{
+ u64 erratum = (u64) context;
+
+ if (erratum & HISILICON_161601) {
+ timer_unstable_counter_workaround = &arch_timer_hisi_161601;
+ static_branch_enable(&arch_timer_read_ool_enabled);
+ pr_info("Enabling workaround for HISILICON ERRATUM 161601\n");
+ }
+}
+#endif
+
/* note: this needs to be updated according to the doc of OEM ID
* and TABLE ID for different board.
*/
struct gtdt_arch_timer_fixup arch_timer_quirks[] __initdata = {
+#ifdef CONFIG_HISILICON_ERRATUM_161601
+ {"HISI", "hip05", 0, &erratum_workaround_enable, (void *) HISILICON_161601},
+ {"HISI", "hip06", 0, &erratum_workaround_enable, (void *) HISILICON_161601},
+ {"HISI", "hip07", 0, &erratum_workaround_enable, (void *) HISILICON_161601},
+#endif
};
void __init arch_timer_acpi_quirks_handler(char *oem_id,
--
1.9.0
^ permalink raw reply related
* [PATCH v5 5/6] arm64: arch_timer: apci: Introduce a generic aquirk framework for erratum
From: Ding Tianhong @ 2016-12-23 7:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1482476669-15596-1-git-send-email-dingtianhong@huawei.com>
From: Hanjun Guo <hanjun.guo@linaro.org>
Introduce a general quirk framework for each timer erratum in ACPI,
which use the oem information in GTDT table for platform specific erratums.
The struct gtdt_arch_timer_fixup is introduced to record the oem
information to match the quirk and handle the erratum.
v3: Introduce a generic aquick framework for erratum in ACPI mode.
v4: rename the quirk handler parameter to make it more generic, and
avoid break loop when handling the quirk becasue it need to
support multi quirks handler.
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: Ding Tianhong <dingtianhong@huawei.com>
---
drivers/clocksource/arm_arch_timer.c | 36 ++++++++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 9a82496..212bfa5 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -1079,6 +1079,39 @@ static int __init arch_timer_mem_init(struct device_node *np)
arch_timer_mem_init);
#ifdef CONFIG_ACPI
+struct gtdt_arch_timer_fixup {
+ char oem_id[ACPI_OEM_ID_SIZE];
+ char oem_table_id[ACPI_OEM_TABLE_ID_SIZE];
+ u32 oem_revision;
+
+ /* quirk handler for arch timer erratum */
+ void (*handler)(void *context);
+ void *context;
+};
+
+/* note: this needs to be updated according to the doc of OEM ID
+ * and TABLE ID for different board.
+ */
+struct gtdt_arch_timer_fixup arch_timer_quirks[] __initdata = {
+};
+
+void __init arch_timer_acpi_quirks_handler(char *oem_id,
+ char *oem_table_id,
+ u32 oem_revision)
+{
+ struct gtdt_arch_timer_fixup *quirks = arch_timer_quirks;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(arch_timer_quirks); i++, quirks++) {
+ if (!memcmp(quirks->oem_id, oem_id, ACPI_OEM_ID_SIZE) &&
+ !memcmp(quirks->oem_table_id, oem_table_id, ACPI_OEM_TABLE_ID_SIZE) &&
+ quirks->oem_revision == oem_revision) {
+ if (quirks->handler && quirks->context)
+ quirks->handler(quirks->context);
+ }
+ }
+}
+
static int __init map_generic_timer_interrupt(u32 interrupt, u32 flags)
{
int trigger, polarity;
@@ -1105,6 +1138,9 @@ static int __init arch_timer_acpi_init(struct acpi_table_header *table)
return -EINVAL;
}
+ arch_timer_acpi_quirks_handler(table->oem_id, table->oem_table_id,
+ table->oem_revision);
+
gtdt = container_of(table, struct acpi_table_gtdt, header);
arch_timers_present |= ARCH_CP15_TIMER;
--
1.9.0
^ permalink raw reply related
* [PATCH v5 4/6] arm64: arch timer: Add timer erratum property for Hip05-d02 and Hip06-d03
From: Ding Tianhong @ 2016-12-23 7:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1482476669-15596-1-git-send-email-dingtianhong@huawei.com>
Enable workaround for hisilicon erratum 161601 on Hip05-d02 and Hip06-d03 board.
Signed-off-by: Ding Tianhong <dingtianhong@huawei.com>
---
arch/arm64/boot/dts/hisilicon/hip05.dtsi | 1 +
arch/arm64/boot/dts/hisilicon/hip06.dtsi | 1 +
2 files changed, 2 insertions(+)
diff --git a/arch/arm64/boot/dts/hisilicon/hip05.dtsi b/arch/arm64/boot/dts/hisilicon/hip05.dtsi
index 4b472a3..a8e9969 100644
--- a/arch/arm64/boot/dts/hisilicon/hip05.dtsi
+++ b/arch/arm64/boot/dts/hisilicon/hip05.dtsi
@@ -281,6 +281,7 @@
<GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
<GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
<GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+ hisilicon,erratum-161601;
};
pmu {
diff --git a/arch/arm64/boot/dts/hisilicon/hip06.dtsi b/arch/arm64/boot/dts/hisilicon/hip06.dtsi
index a049b64..344e0f0 100644
--- a/arch/arm64/boot/dts/hisilicon/hip06.dtsi
+++ b/arch/arm64/boot/dts/hisilicon/hip06.dtsi
@@ -260,6 +260,7 @@
<GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
<GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
<GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+ hisilicon,erratum-161601;
};
pmu {
--
1.9.0
^ permalink raw reply related
* [PATCH v5 3/6] arm64: arch_timer: Work around Erratum Hisilicon-161601
From: Ding Tianhong @ 2016-12-23 7:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1482476669-15596-1-git-send-email-dingtianhong@huawei.com>
Erratum Hisilicon-161601 says that the ARM generic timer counter "has the
potential to contain an erroneous value when the timer value changes".
Accesses to TVAL (both read and write) are also affected due to the implicit counter
read. Accesses to CVAL are not affected.
The workaround is to reread the system count registers until the value of the second
read is larger than the first one by less than 32, the system counter can be guaranteed
not to return wrong value twice by back-to-back read and the error value is always larger
than the correct one by 32. Writes to TVAL are replaced with an equivalent write to CVAL.
The workaround is enabled if the hisilicon,erratum-161601 property is found in
the timer node in the device tree. This can be overridden with the
clocksource.arm_arch_timer.hisilicon-161601 boot parameter, which allows KVM
users to enable the workaround until a mechanism is implemented to
automatically communicate this information.
Fix some description for fsl erratum a008585.
v2: Significant rework based on feedback, including seperate the fsl erratum a008585
to another patch, update the erratum name and remove unwanted code.
v3: Significant rework based on feedback, including fix some alignment problem, make the
#define __hisi_161601_read_reg to be private to the .c file instead of being globally
visible, add more accurate annotation and modify a bit of logical format to enable
arch_timer_read_ool_enabled, remove the kernel commandline parameter
clocksource.arm_arch_timer.hisilicon-161601.
v5: Theoretically the erratum should not occur more than twice in succession when reading
the system counter, but it is possible that some interrupts may lead to more than twice
read errors, triggering the warning, so setting the number of retries to 50 which is far
beyond the number of iterations the loop has been observed to take.
Signed-off-by: Ding Tianhong <dingtianhong@huawei.com>
---
Documentation/arm64/silicon-errata.txt | 1 +
arch/arm64/include/asm/arch_timer.h | 2 +-
drivers/clocksource/Kconfig | 9 +++++
drivers/clocksource/arm_arch_timer.c | 70 +++++++++++++++++++++++++++++++---
4 files changed, 76 insertions(+), 6 deletions(-)
diff --git a/Documentation/arm64/silicon-errata.txt b/Documentation/arm64/silicon-errata.txt
index 405da11..1c1a95f 100644
--- a/Documentation/arm64/silicon-errata.txt
+++ b/Documentation/arm64/silicon-errata.txt
@@ -63,3 +63,4 @@ stable kernels.
| Cavium | ThunderX SMMUv2 | #27704 | N/A |
| | | | |
| Freescale/NXP | LS2080A/LS1043A | A-008585 | FSL_ERRATUM_A008585 |
+| Hisilicon | Hip0{5,6,7} | #161601 | HISILICON_ERRATUM_161601|
diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h
index f882c7c..ebf4cde 100644
--- a/arch/arm64/include/asm/arch_timer.h
+++ b/arch/arm64/include/asm/arch_timer.h
@@ -29,7 +29,7 @@
#include <clocksource/arm_arch_timer.h>
-#if IS_ENABLED(CONFIG_FSL_ERRATUM_A008585)
+#if IS_ENABLED(CONFIG_FSL_ERRATUM_A008585) || IS_ENABLED(CONFIG_HISILICON_ERRATUM_161601)
extern struct static_key_false arch_timer_read_ool_enabled;
#define needs_unstable_timer_counter_workaround() \
static_branch_unlikely(&arch_timer_read_ool_enabled)
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 4866f7a..162d820 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -335,6 +335,15 @@ config FSL_ERRATUM_A008585
value"). The workaround will only be active if the
fsl,erratum-a008585 property is found in the timer node.
+config HISILICON_ERRATUM_161601
+ bool "Workaround for Hisilicon Erratum 161601"
+ default y
+ depends on ARM_ARCH_TIMER && ARM64
+ help
+ This option enables a workaround for Hisilicon Erratum
+ 161601. The workaround will be active if the hisilicon,erratum-161601
+ property is found in the timer node.
+
config ARM_GLOBAL_TIMER
bool "Support for the ARM global timer" if COMPILE_TEST
select CLKSRC_OF if OF
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index e7406ad..9a82496 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -95,15 +95,18 @@ static int __init early_evtstrm_cfg(char *buf)
* Architected system timer support.
*/
-#ifdef CONFIG_FSL_ERRATUM_A008585
+#if CONFIG_FSL_ERRATUM_A008585 || IS_ENABLED(CONFIG_HISILICON_ERRATUM_161601)
struct arch_timer_erratum_workaround *timer_unstable_counter_workaround = NULL;
EXPORT_SYMBOL_GPL(timer_unstable_counter_workaround);
#define FSL_A008585 0x0001
+#define HISILICON_161601 0x0002
DEFINE_STATIC_KEY_FALSE(arch_timer_read_ool_enabled);
EXPORT_SYMBOL_GPL(arch_timer_read_ool_enabled);
+#endif
+#ifdef CONFIG_FSL_ERRATUM_A008585
/*
* The number of retries is an arbitrary value well beyond the highest number
* of iterations the loop has been observed to take.
@@ -145,6 +148,54 @@ static u64 fsl_a008585_read_cntvct_el0(void)
};
#endif /* CONFIG_FSL_ERRATUM_A008585 */
+#ifdef CONFIG_HISILICON_ERRATUM_161601
+/*
+ * Verify whether the value of the second read is larger than the first by
+ * less than 32 is the only way to confirm the value is correct, so clear the
+ * lower 5 bits to check whether the difference is greater than 32 or not.
+ * Theoretically the erratum should not occur more than twice in succession
+ * when reading the system counter, but it is possible that some interrupts
+ * may lead to more than twice read errors, triggering the warning, so setting
+ * the number of retries far beyond the number of iterations the loop has been
+ * observed to take.
+ */
+#define __hisi_161601_read_reg(reg) ({ \
+ u64 _old, _new; \
+ int _retries = 50; \
+ \
+ do { \
+ _old = read_sysreg(reg); \
+ _new = read_sysreg(reg); \
+ _retries--; \
+ } while (unlikely((_new - _old) >> 5) && _retries); \
+ \
+ WARN_ON_ONCE(!_retries); \
+ _new; \
+})
+
+static u32 hisi_161601_read_cntp_tval_el0(void)
+{
+ return __hisi_161601_read_reg(cntp_tval_el0);
+}
+
+static u32 hisi_161601_read_cntv_tval_el0(void)
+{
+ return __hisi_161601_read_reg(cntv_tval_el0);
+}
+
+static u64 hisi_161601_read_cntvct_el0(void)
+{
+ return __hisi_161601_read_reg(cntvct_el0);
+}
+
+static struct arch_timer_erratum_workaround arch_timer_hisi_161601 = {
+ .erratum = HISILICON_161601,
+ .read_cntp_tval_el0 = hisi_161601_read_cntp_tval_el0,
+ .read_cntv_tval_el0 = hisi_161601_read_cntv_tval_el0,
+ .read_cntvct_el0 = hisi_161601_read_cntvct_el0,
+};
+#endif /* CONFIG_HISILICON_ERRATUM_161601 */
+
static __always_inline
void arch_timer_reg_write(int access, enum arch_timer_reg reg, u32 val,
struct clock_event_device *clk)
@@ -294,7 +345,7 @@ static __always_inline void set_next_event(const int access, unsigned long evt,
arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk);
}
-#ifdef CONFIG_FSL_ERRATUM_A008585
+#if IS_ENABLED(CONFIG_FSL_ERRATUM_A008585) || IS_ENABLED(CONFIG_HISILICON_ERRATUM_161601)
static __always_inline void erratum_set_next_event_generic(const int access,
unsigned long evt, struct clock_event_device *clk)
{
@@ -358,7 +409,7 @@ static int arch_timer_set_next_event_phys_mem(unsigned long evt,
static void erratum_workaround_set_sne(struct clock_event_device *clk)
{
-#ifdef CONFIG_FSL_ERRATUM_A008585
+#if IS_ENABLED(CONFIG_FSL_ERRATUM_A008585) || IS_ENABLED(CONFIG_HISILICON_ERRATUM_161601)
if (!static_branch_unlikely(&arch_timer_read_ool_enabled))
return;
@@ -618,7 +669,7 @@ static void __init arch_counter_register(unsigned type)
clocksource_counter.archdata.vdso_direct = true;
-#ifdef CONFIG_FSL_ERRATUM_A008585
+#if IS_ENABLED(CONFIG_FSL_ERRATUM_A008585) || IS_ENABLED(CONFIG_HISILICON_ERRATUM_161601)
/*
* Don't use the vdso fastpath if errata require using
* the out-of-line counter accessor.
@@ -909,10 +960,19 @@ static int __init arch_timer_of_init(struct device_node *np)
#ifdef CONFIG_FSL_ERRATUM_A008585
if (!timer_unstable_counter_workaround && of_property_read_bool(np, "fsl,erratum-a008585"))
timer_unstable_counter_workaround = &arch_timer_fsl_a008585;
+#endif
+
+#ifdef CONFIG_HISILICON_ERRATUM_161601
+ if (!timer_unstable_counter_workaround && of_property_read_bool(np, "hisilicon,erratum-161601"))
+ timer_unstable_counter_workaround = &arch_timer_hisi_161601;
+#endif
+#if IS_ENABLED(CONFIG_FSL_ERRATUM_A008585) || IS_ENABLED(CONFIG_HISILICON_ERRATUM_161601)
if (timer_unstable_counter_workaround) {
static_branch_enable(&arch_timer_read_ool_enabled);
- pr_info("Enabling workaround for FSL erratum A-008585\n");
+ pr_info("Enabling workaround for %s\n",
+ timer_unstable_counter_workaround->erratum == FSL_A008585 ?
+ "FSL ERRATUM A-008585" : "HISILICON ERRATUM 161601");
}
#endif
--
1.9.0
^ permalink raw reply related
* [PATCH v5 2/6] arm64: arch_timer: Introduce a generic erratum handing mechanism for fsl-a008585
From: Ding Tianhong @ 2016-12-23 7:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1482476669-15596-1-git-send-email-dingtianhong@huawei.com>
The workaround for hisilicon,161601 will check the return value of the system counter
by different way, in order to distinguish with the fsl-a008585 workaround, introduce
a new generic erratum handing mechanism for fsl-a008585 and rename some functions.
v2: Introducing a new generic erratum handling mechanism for fsl erratum a008585.
v3: Introducing the erratum_workaround_set_sne generic function for fsl erratum a008585
and make the #define __fsl_a008585_read_reg to be private to the .c file instead of
being globally visible. After discussion with Marc and Will, a consensus decision was
made to remove the commandline parameter for enabling fsl,erratum-a008585 erratum,
and make some generic name more specific, export timer_unstable_counter_workaround
for module access.
v5: Adapt the new documentation for kernel-parameters.txt.
Signed-off-by: Ding Tianhong <dingtianhong@huawei.com>
---
Documentation/admin-guide/kernel-parameters.txt | 9 ---
arch/arm64/include/asm/arch_timer.h | 36 ++++--------
drivers/clocksource/arm_arch_timer.c | 78 +++++++++++++++----------
3 files changed, 58 insertions(+), 65 deletions(-)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 21e2d88..76437ad 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -539,15 +539,6 @@
loops can be debugged more effectively on production
systems.
- clocksource.arm_arch_timer.fsl-a008585=
- [ARM64]
- Format: <bool>
- Enable/disable the workaround of Freescale/NXP
- erratum A-008585. This can be useful for KVM
- guests, if the guest device tree doesn't show the
- erratum. If unspecified, the workaround is
- enabled based on the device tree.
-
clearcpuid=BITNUM [X86]
Disable CPUID feature X for the kernel. See
arch/x86/include/asm/cpufeatures.h for the valid bit
diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h
index eaa5bbe..f882c7c 100644
--- a/arch/arm64/include/asm/arch_timer.h
+++ b/arch/arm64/include/asm/arch_timer.h
@@ -31,39 +31,27 @@
#if IS_ENABLED(CONFIG_FSL_ERRATUM_A008585)
extern struct static_key_false arch_timer_read_ool_enabled;
-#define needs_fsl_a008585_workaround() \
+#define needs_unstable_timer_counter_workaround() \
static_branch_unlikely(&arch_timer_read_ool_enabled)
#else
-#define needs_fsl_a008585_workaround() false
+#define needs_unstable_timer_counter_workaround() false
#endif
-u32 __fsl_a008585_read_cntp_tval_el0(void);
-u32 __fsl_a008585_read_cntv_tval_el0(void);
-u64 __fsl_a008585_read_cntvct_el0(void);
-/*
- * The number of retries is an arbitrary value well beyond the highest number
- * of iterations the loop has been observed to take.
- */
-#define __fsl_a008585_read_reg(reg) ({ \
- u64 _old, _new; \
- int _retries = 200; \
- \
- do { \
- _old = read_sysreg(reg); \
- _new = read_sysreg(reg); \
- _retries--; \
- } while (unlikely(_old != _new) && _retries); \
- \
- WARN_ON_ONCE(!_retries); \
- _new; \
-})
+struct arch_timer_erratum_workaround {
+ int erratum; /* Indicate the Erratum ID */
+ u32 (*read_cntp_tval_el0)(void);
+ u32 (*read_cntv_tval_el0)(void);
+ u64 (*read_cntvct_el0)(void);
+};
+
+extern struct arch_timer_erratum_workaround *timer_unstable_counter_workaround;
#define arch_timer_reg_read_stable(reg) \
({ \
u64 _val; \
- if (needs_fsl_a008585_workaround()) \
- _val = __fsl_a008585_read_##reg(); \
+ if (needs_unstable_timer_counter_workaround()) \
+ _val = timer_unstable_counter_workaround->read_##reg();\
else \
_val = read_sysreg(reg); \
_val; \
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 02fef68..e7406ad 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -96,40 +96,53 @@ static int __init early_evtstrm_cfg(char *buf)
*/
#ifdef CONFIG_FSL_ERRATUM_A008585
-DEFINE_STATIC_KEY_FALSE(arch_timer_read_ool_enabled);
-EXPORT_SYMBOL_GPL(arch_timer_read_ool_enabled);
-
-static int fsl_a008585_enable = -1;
+struct arch_timer_erratum_workaround *timer_unstable_counter_workaround = NULL;
+EXPORT_SYMBOL_GPL(timer_unstable_counter_workaround);
-static int __init early_fsl_a008585_cfg(char *buf)
-{
- int ret;
- bool val;
+#define FSL_A008585 0x0001
- ret = strtobool(buf, &val);
- if (ret)
- return ret;
-
- fsl_a008585_enable = val;
- return 0;
-}
-early_param("clocksource.arm_arch_timer.fsl-a008585", early_fsl_a008585_cfg);
+DEFINE_STATIC_KEY_FALSE(arch_timer_read_ool_enabled);
+EXPORT_SYMBOL_GPL(arch_timer_read_ool_enabled);
-u32 __fsl_a008585_read_cntp_tval_el0(void)
+/*
+ * The number of retries is an arbitrary value well beyond the highest number
+ * of iterations the loop has been observed to take.
+ */
+#define __fsl_a008585_read_reg(reg) ({ \
+ u64 _old, _new; \
+ int _retries = 200; \
+ \
+ do { \
+ _old = read_sysreg(reg); \
+ _new = read_sysreg(reg); \
+ _retries--; \
+ } while (unlikely(_old != _new) && _retries); \
+ \
+ WARN_ON_ONCE(!_retries); \
+ _new; \
+})
+
+static u32 fsl_a008585_read_cntp_tval_el0(void)
{
return __fsl_a008585_read_reg(cntp_tval_el0);
}
-u32 __fsl_a008585_read_cntv_tval_el0(void)
+static u32 fsl_a008585_read_cntv_tval_el0(void)
{
return __fsl_a008585_read_reg(cntv_tval_el0);
}
-u64 __fsl_a008585_read_cntvct_el0(void)
+static u64 fsl_a008585_read_cntvct_el0(void)
{
return __fsl_a008585_read_reg(cntvct_el0);
}
-EXPORT_SYMBOL(__fsl_a008585_read_cntvct_el0);
+
+static struct arch_timer_erratum_workaround arch_timer_fsl_a008585 = {
+ .erratum = FSL_A008585,
+ .read_cntp_tval_el0 = fsl_a008585_read_cntp_tval_el0,
+ .read_cntv_tval_el0 = fsl_a008585_read_cntv_tval_el0,
+ .read_cntvct_el0 = fsl_a008585_read_cntvct_el0,
+};
#endif /* CONFIG_FSL_ERRATUM_A008585 */
static __always_inline
@@ -282,7 +295,7 @@ static __always_inline void set_next_event(const int access, unsigned long evt,
}
#ifdef CONFIG_FSL_ERRATUM_A008585
-static __always_inline void fsl_a008585_set_next_event(const int access,
+static __always_inline void erratum_set_next_event_generic(const int access,
unsigned long evt, struct clock_event_device *clk)
{
unsigned long ctrl;
@@ -300,17 +313,17 @@ static __always_inline void fsl_a008585_set_next_event(const int access,
arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk);
}
-static int fsl_a008585_set_next_event_virt(unsigned long evt,
+static int erratum_set_next_event_virt(unsigned long evt,
struct clock_event_device *clk)
{
- fsl_a008585_set_next_event(ARCH_TIMER_VIRT_ACCESS, evt, clk);
+ erratum_set_next_event_generic(ARCH_TIMER_VIRT_ACCESS, evt, clk);
return 0;
}
-static int fsl_a008585_set_next_event_phys(unsigned long evt,
+static int erratum_set_next_event_phys(unsigned long evt,
struct clock_event_device *clk)
{
- fsl_a008585_set_next_event(ARCH_TIMER_PHYS_ACCESS, evt, clk);
+ erratum_set_next_event_generic(ARCH_TIMER_PHYS_ACCESS, evt, clk);
return 0;
}
#endif /* CONFIG_FSL_ERRATUM_A008585 */
@@ -343,16 +356,16 @@ static int arch_timer_set_next_event_phys_mem(unsigned long evt,
return 0;
}
-static void fsl_a008585_set_sne(struct clock_event_device *clk)
+static void erratum_workaround_set_sne(struct clock_event_device *clk)
{
#ifdef CONFIG_FSL_ERRATUM_A008585
if (!static_branch_unlikely(&arch_timer_read_ool_enabled))
return;
if (arch_timer_uses_ppi == VIRT_PPI)
- clk->set_next_event = fsl_a008585_set_next_event_virt;
+ clk->set_next_event = erratum_set_next_event_virt;
else
- clk->set_next_event = fsl_a008585_set_next_event_phys;
+ clk->set_next_event = erratum_set_next_event_phys;
#endif
}
@@ -385,7 +398,7 @@ static void __arch_timer_setup(unsigned type,
BUG();
}
- fsl_a008585_set_sne(clk);
+ erratum_workaround_set_sne(clk);
} else {
clk->features |= CLOCK_EVT_FEAT_DYNIRQ;
clk->name = "arch_mem_timer";
@@ -894,9 +907,10 @@ static int __init arch_timer_of_init(struct device_node *np)
arch_timer_c3stop = !of_property_read_bool(np, "always-on");
#ifdef CONFIG_FSL_ERRATUM_A008585
- if (fsl_a008585_enable < 0)
- fsl_a008585_enable = of_property_read_bool(np, "fsl,erratum-a008585");
- if (fsl_a008585_enable) {
+ if (!timer_unstable_counter_workaround && of_property_read_bool(np, "fsl,erratum-a008585"))
+ timer_unstable_counter_workaround = &arch_timer_fsl_a008585;
+
+ if (timer_unstable_counter_workaround) {
static_branch_enable(&arch_timer_read_ool_enabled);
pr_info("Enabling workaround for FSL erratum A-008585\n");
}
--
1.9.0
^ permalink raw reply related
* [PATCH v5 1/6] arm64: arch_timer: Add device tree binding for hisilicon-161601 erratum
From: Ding Tianhong @ 2016-12-23 7:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1482476669-15596-1-git-send-email-dingtianhong@huawei.com>
This erratum describes a bug in logic outside the core, so MIDR can't be
used to identify its presence, and reading an SoC-specific revision
register from common arch timer code would be awkward. So, describe it
in the device tree.
v2: Use the new erratum name and update the description.
Signed-off-by: Ding Tianhong <dingtianhong@huawei.com>
Acked-by: Rob Herring <robh@kernel.org>
---
Documentation/devicetree/bindings/arm/arch_timer.txt | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/Documentation/devicetree/bindings/arm/arch_timer.txt b/Documentation/devicetree/bindings/arm/arch_timer.txt
index ad440a2..935f142 100644
--- a/Documentation/devicetree/bindings/arm/arch_timer.txt
+++ b/Documentation/devicetree/bindings/arm/arch_timer.txt
@@ -31,6 +31,14 @@ to deliver its interrupts via SPIs.
This also affects writes to the tval register, due to the implicit
counter read.
+- hisilicon,erratum-161601 : A boolean property. Indicates the presence of
+ erratum 161601, which says that reading the counter is unreliable unless
+ reading twice on the register and the value of the second read is larger
+ than the first by less than 32. If the verification is unsuccessful, then
+ discard the value of this read and repeat this procedure until the verification
+ is successful. This also affects writes to the tval register, due to the
+ implicit counter read.
+
** Optional properties:
- arm,cpu-registers-not-fw-configured : Firmware does not initialize
--
1.9.0
^ permalink raw reply related
* [PATCH v5 0/6] arm64: arch_timer: Add workaround for hisilicon-161601 erratum
From: Ding Tianhong @ 2016-12-23 7:04 UTC (permalink / raw)
To: linux-arm-kernel
Erratum Hisilicon-161601 says that the ARM generic timer counter "has the
potential to contain an erroneous value when the timer value changes".
Accesses to TVAL (both read and write) are also affected due to the implicit counter
read. Accesses to CVAL are not affected.
The workaround is to reread the system count registers until the value of the second
read is larger than the first one by less than 32, the system counter can be guaranteed
not to return wrong value twice by back-to-back read and the error value is always larger
than the correct one by 32. Writes to TVAL are replaced with an equivalent write to CVAL.
v2: Introducing a new generic erratum handling mechanism for fsl,a008585 and hisilicon,161601.
Significant rework based on feedback, including seperate the fsl erratum a008585
to another patch, update the erratum name and remove unwanted code.
v3: Introducing the erratum_workaround_set_sne generic function for fsl erratum a008585
and make the #define __fsl_a008585_read_reg to be private to the .c file instead of
being globally visible. After discussion with Marc and Will, a consensus decision was
made to remove the commandline parameter for enabling fsl,erratum-a008585 erratum,
and make some generic name more specific, export timer_unstable_counter_workaround
for module access.
Significant rework based on feedback, including fix some alignment problem, make the
#define __hisi_161601_read_reg to be private to the .c file instead of being globally
visible, add more accurate annotation and modify a bit of logical format to enable
arch_timer_read_ool_enabled, remove the kernel commandline parameter
clocksource.arm_arch_timer.hisilicon-161601.
Introduce a generic aquick framework for erratum in ACPI mode.
v4: rename the quirk handler parameter to make it more generic, and
avoid break loop when handling the quirk becasue it need to
support multi quirks handler.
update some data structures for acpi mode.
v5: Adapt the new kernel-parameters.txt for latest kernel version.
Set the retries of reread system counter to 50, because it is possible
that some interrupts may lead to more than twice read errors and break the loop,
it will trigger the warning, so we set the number of retries far beyond the number of
iterations the loop has been observed to take.
Ding Tianhong (4):
arm64: arch_timer: Add device tree binding for hisilicon-161601
erratum
arm64: arch_timer: Introduce a generic erratum handing mechanism for
fsl-a008585
arm64: arch_timer: Work around Erratum Hisilicon-161601
arm64: arch timer: Add timer erratum property for Hip05-d02 and
Hip06-d03
Hanjun Guo (2):
arm64: arch_timer: apci: Introduce a generic aquirk framework for
erratum
arm64: arch_timer: acpi: add hisi timer errata data
Documentation/arm64/silicon-errata.txt | 1 +
.../devicetree/bindings/arm/arch_timer.txt | 8 +
Documentation/kernel-parameters.txt | 9 -
arch/arm64/boot/dts/hisilicon/hip05.dtsi | 1 +
arch/arm64/boot/dts/hisilicon/hip06.dtsi | 1 +
arch/arm64/include/asm/arch_timer.h | 38 ++--
drivers/clocksource/Kconfig | 9 +
drivers/clocksource/arm_arch_timer.c | 197 +++++++++++++++++----
8 files changed, 194 insertions(+), 70 deletions(-)
--
1.9.0
^ permalink raw reply
* [PATCH v1 3/3] soc: rockchip: power-domain: Modify power domain driver for rk3328
From: Elaine Zhang @ 2016-12-23 3:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1482464872-12954-1-git-send-email-zhangqing@rock-chips.com>
This driver is modified to support RK3328 SoC.
RK3328 SoC is only support idle.
add DOMAIN_M type, for support regs have write_enable bit.
Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
---
drivers/soc/rockchip/pm_domains.c | 63 +++++++++++++++++++++++++++++++++++----
1 file changed, 57 insertions(+), 6 deletions(-)
diff --git a/drivers/soc/rockchip/pm_domains.c b/drivers/soc/rockchip/pm_domains.c
index 1c78c42416c6..796c46a6cbe7 100644
--- a/drivers/soc/rockchip/pm_domains.c
+++ b/drivers/soc/rockchip/pm_domains.c
@@ -19,6 +19,7 @@
#include <linux/regmap.h>
#include <linux/mfd/syscon.h>
#include <dt-bindings/power/rk3288-power.h>
+#include <dt-bindings/power/rk3328-power.h>
#include <dt-bindings/power/rk3368-power.h>
#include <dt-bindings/power/rk3399-power.h>
@@ -29,6 +30,8 @@ struct rockchip_domain_info {
int idle_mask;
int ack_mask;
bool active_wakeup;
+ int pwr_w_mask;
+ int req_w_mask;
};
struct rockchip_pmu_info {
@@ -87,9 +90,24 @@ struct rockchip_pmu {
.active_wakeup = wakeup, \
}
+#define DOMAIN_M(pwr, status, req, idle, ack, wakeup) \
+{ \
+ .pwr_w_mask = (pwr >= 0) ? BIT(pwr + 16) : 0, \
+ .pwr_mask = (pwr >= 0) ? BIT(pwr) : 0, \
+ .status_mask = (status >= 0) ? BIT(status) : 0, \
+ .req_w_mask = (req >= 0) ? BIT(req + 16) : 0, \
+ .req_mask = (req >= 0) ? BIT(req) : 0, \
+ .idle_mask = (idle >= 0) ? BIT(idle) : 0, \
+ .ack_mask = (ack >= 0) ? BIT(ack) : 0, \
+ .active_wakeup = wakeup, \
+}
+
#define DOMAIN_RK3288(pwr, status, req, wakeup) \
DOMAIN(pwr, status, req, req, (req) + 16, wakeup)
+#define DOMAIN_RK3328(pwr, status, req, wakeup) \
+ DOMAIN_M(pwr, pwr, req, (req) + 10, req, wakeup)
+
#define DOMAIN_RK3368(pwr, status, req, wakeup) \
DOMAIN(pwr, status, req, (req) + 16, req, wakeup)
@@ -127,9 +145,13 @@ static int rockchip_pmu_set_idle_request(struct rockchip_pm_domain *pd,
if (pd_info->req_mask == 0)
return 0;
-
- regmap_update_bits(pmu->regmap, pmu->info->req_offset,
- pd_info->req_mask, idle ? -1U : 0);
+ else if (pd_info->req_w_mask)
+ regmap_write(pmu->regmap, pmu->info->req_offset,
+ idle ? (pd_info->req_mask | pd_info->req_w_mask) :
+ pd_info->req_w_mask);
+ else
+ regmap_update_bits(pmu->regmap, pmu->info->req_offset,
+ pd_info->req_mask, idle ? -1U : 0);
dsb(sy);
@@ -230,9 +252,13 @@ static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd,
if (pd->info->pwr_mask == 0)
return;
-
- regmap_update_bits(pmu->regmap, pmu->info->pwr_offset,
- pd->info->pwr_mask, on ? 0 : -1U);
+ else if (pd->info->pwr_w_mask)
+ regmap_write(pmu->regmap, pmu->info->pwr_offset,
+ on ? pd->info->pwr_mask :
+ (pd->info->pwr_mask | pd->info->pwr_w_mask));
+ else
+ regmap_update_bits(pmu->regmap, pmu->info->pwr_offset,
+ pd->info->pwr_mask, on ? 0 : -1U);
dsb(sy);
@@ -692,6 +718,18 @@ static int rockchip_pm_domain_probe(struct platform_device *pdev)
[RK3288_PD_GPU] = DOMAIN_RK3288(9, 9, 2, false),
};
+static const struct rockchip_domain_info rk3328_pm_domains[] = {
+ [RK3328_PD_CORE] = DOMAIN_RK3328(-1, 0, 0, false),
+ [RK3328_PD_GPU] = DOMAIN_RK3328(-1, 1, 1, false),
+ [RK3328_PD_BUS] = DOMAIN_RK3328(-1, 2, 2, true),
+ [RK3328_PD_MSCH] = DOMAIN_RK3328(-1, 3, 3, true),
+ [RK3328_PD_PERI] = DOMAIN_RK3328(-1, 4, 4, true),
+ [RK3328_PD_VIDEO] = DOMAIN_RK3328(-1, 5, 5, false),
+ [RK3328_PD_HEVC] = DOMAIN_RK3328(-1, 6, 6, false),
+ [RK3328_PD_VIO] = DOMAIN_RK3328(-1, 8, 8, false),
+ [RK3328_PD_VPU] = DOMAIN_RK3328(-1, 9, 9, false),
+};
+
static const struct rockchip_domain_info rk3368_pm_domains[] = {
[RK3368_PD_PERI] = DOMAIN_RK3368(13, 12, 6, true),
[RK3368_PD_VIO] = DOMAIN_RK3368(15, 14, 8, false),
@@ -747,6 +785,15 @@ static int rockchip_pm_domain_probe(struct platform_device *pdev)
.domain_info = rk3288_pm_domains,
};
+static const struct rockchip_pmu_info rk3328_pmu = {
+ .req_offset = 0x414,
+ .idle_offset = 0x484,
+ .ack_offset = 0x484,
+
+ .num_domains = ARRAY_SIZE(rk3328_pm_domains),
+ .domain_info = rk3328_pm_domains,
+};
+
static const struct rockchip_pmu_info rk3368_pmu = {
.pwr_offset = 0x0c,
.status_offset = 0x10,
@@ -783,6 +830,10 @@ static int rockchip_pm_domain_probe(struct platform_device *pdev)
.data = (void *)&rk3288_pmu,
},
{
+ .compatible = "rockchip,rk3328-power-controller",
+ .data = (void *)&rk3328_pmu,
+ },
+ {
.compatible = "rockchip,rk3368-power-controller",
.data = (void *)&rk3368_pmu,
},
--
1.9.1
^ permalink raw reply related
* [PATCH v1 2/3] dt-bindings: add binding for rk3328 power domains
From: Elaine Zhang @ 2016-12-23 3:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1482464872-12954-1-git-send-email-zhangqing@rock-chips.com>
Add binding documentation for the power domains
found on Rockchip RK3328 SoCs.
But RK3328 SoC just support idle, not support pd.
Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
---
Documentation/devicetree/bindings/soc/rockchip/power_domain.txt | 3 +++
1 file changed, 3 insertions(+)
diff --git a/Documentation/devicetree/bindings/soc/rockchip/power_domain.txt b/Documentation/devicetree/bindings/soc/rockchip/power_domain.txt
index f909ce06afc4..01bfb6745fbd 100644
--- a/Documentation/devicetree/bindings/soc/rockchip/power_domain.txt
+++ b/Documentation/devicetree/bindings/soc/rockchip/power_domain.txt
@@ -6,6 +6,7 @@ powered up/down by software based on different application scenes to save power.
Required properties for power domain controller:
- compatible: Should be one of the following.
"rockchip,rk3288-power-controller" - for RK3288 SoCs.
+ "rockchip,rk3328-power-controller" - for RK3328 SoCs.
"rockchip,rk3368-power-controller" - for RK3368 SoCs.
"rockchip,rk3399-power-controller" - for RK3399 SoCs.
- #power-domain-cells: Number of cells in a power-domain specifier.
@@ -16,6 +17,7 @@ Required properties for power domain controller:
Required properties for power domain sub nodes:
- reg: index of the power domain, should use macros in:
"include/dt-bindings/power/rk3288-power.h" - for RK3288 type power domain.
+ "include/dt-bindings/power/rk3328-power.h" - for RK3328 type power domain.
"include/dt-bindings/power/rk3368-power.h" - for RK3368 type power domain.
"include/dt-bindings/power/rk3399-power.h" - for RK3399 type power domain.
- clocks (optional): phandles to clocks which need to be enabled while power domain
@@ -90,6 +92,7 @@ containing a phandle to the power device node and an index specifying which
power domain to use.
The index should use macros in:
"include/dt-bindings/power/rk3288-power.h" - for rk3288 type power domain.
+ "include/dt-bindings/power/rk3328-power.h" - for rk3328 type power domain.
"include/dt-bindings/power/rk3368-power.h" - for rk3368 type power domain.
"include/dt-bindings/power/rk3399-power.h" - for rk3399 type power domain.
--
1.9.1
^ permalink raw reply related
* [PATCH v1 1/3] dt/bindings: power: add RK3328 SoCs header for idle-request
From: Elaine Zhang @ 2016-12-23 3:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1482464872-12954-1-git-send-email-zhangqing@rock-chips.com>
According to a description from TRM, add all the idle request.
Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
---
include/dt-bindings/power/rk3328-power.h | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
create mode 100644 include/dt-bindings/power/rk3328-power.h
diff --git a/include/dt-bindings/power/rk3328-power.h b/include/dt-bindings/power/rk3328-power.h
new file mode 100644
index 000000000000..10c3c3715334
--- /dev/null
+++ b/include/dt-bindings/power/rk3328-power.h
@@ -0,0 +1,18 @@
+#ifndef __DT_BINDINGS_POWER_RK3328_POWER_H__
+#define __DT_BINDINGS_POWER_RK3328_POWER_H__
+
+/**
+ * RK3328 idle id Summary.
+ */
+#define RK3328_PD_CORE 0
+#define RK3328_PD_GPU 1
+#define RK3328_PD_BUS 2
+#define RK3328_PD_MSCH 3
+#define RK3328_PD_PERI 4
+#define RK3328_PD_VIDEO 5
+#define RK3328_PD_HEVC 6
+#define RK3328_PD_SYS 7
+#define RK3328_PD_VPU 8
+#define RK3328_PD_VIO 9
+
+#endif
--
1.9.1
^ permalink raw reply related
* [PATCH v1 0/3] soc: rockchip: power-domain: support RK3328 SoC
From: Elaine Zhang @ 2016-12-23 3:47 UTC (permalink / raw)
To: linux-arm-kernel
Elaine Zhang (3):
dt/bindings: power: add RK3328 SoCs header for idle-request
dt-bindings: add binding for rk3328 power domains
soc: rockchip: power-domain: Modify power domain driver for rk3328
.../bindings/soc/rockchip/power_domain.txt | 3 ++
drivers/soc/rockchip/pm_domains.c | 63 +++++++++++++++++++---
include/dt-bindings/power/rk3328-power.h | 18 +++++++
3 files changed, 78 insertions(+), 6 deletions(-)
create mode 100644 include/dt-bindings/power/rk3328-power.h
--
1.9.1
^ permalink raw reply
* [PATCH] serial: 8250: use initializer instead of memset to clear local struct
From: Masahiro Yamada @ 2016-12-23 3:21 UTC (permalink / raw)
To: linux-arm-kernel
Leave the way of zero-out to the compiler's decision; the compiler
may know a more optimized way than calling memset().
It may end up with memset() for big structures like this after all,
but the code will be cleaner at least.
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
---
drivers/tty/serial/8250/8250_acorn.c | 3 +--
drivers/tty/serial/8250/8250_core.c | 4 +---
drivers/tty/serial/8250/8250_em.c | 3 +--
drivers/tty/serial/8250/8250_gsc.c | 3 +--
drivers/tty/serial/8250/8250_hp300.c | 11 +++--------
drivers/tty/serial/8250/8250_lpc18xx.c | 4 +---
drivers/tty/serial/8250/8250_lpss.c | 4 +---
drivers/tty/serial/8250/8250_mid.c | 4 +---
drivers/tty/serial/8250/8250_moxa.c | 4 +---
drivers/tty/serial/8250/8250_of.c | 4 ++--
drivers/tty/serial/8250/8250_omap.c | 3 +--
drivers/tty/serial/8250/8250_pci.c | 3 +--
drivers/tty/serial/8250/8250_pnp.c | 3 +--
drivers/tty/serial/8250/8250_uniphier.c | 4 +---
drivers/tty/serial/8250/serial_cs.c | 3 +--
15 files changed, 18 insertions(+), 42 deletions(-)
diff --git a/drivers/tty/serial/8250/8250_acorn.c b/drivers/tty/serial/8250/8250_acorn.c
index 402dfdd..f49acafc 100644
--- a/drivers/tty/serial/8250/8250_acorn.c
+++ b/drivers/tty/serial/8250/8250_acorn.c
@@ -43,7 +43,7 @@ serial_card_probe(struct expansion_card *ec, const struct ecard_id *id)
{
struct serial_card_info *info;
struct serial_card_type *type = id->data;
- struct uart_8250_port uart;
+ struct uart_8250_port uart = {};
unsigned long bus_addr;
unsigned int i;
@@ -62,7 +62,6 @@ serial_card_probe(struct expansion_card *ec, const struct ecard_id *id)
ecard_set_drvdata(ec, info);
- memset(&uart, 0, sizeof(struct uart_8250_port));
uart.port.irq = ec->irq;
uart.port.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
uart.port.uartclk = type->uartclk;
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 61569a7..27c18c9 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -804,11 +804,9 @@ EXPORT_SYMBOL(serial8250_resume_port);
static int serial8250_probe(struct platform_device *dev)
{
struct plat_serial8250_port *p = dev_get_platdata(&dev->dev);
- struct uart_8250_port uart;
+ struct uart_8250_port uart = {};
int ret, i, irqflag = 0;
- memset(&uart, 0, sizeof(uart));
-
if (share_irqs)
irqflag = IRQF_SHARED;
diff --git a/drivers/tty/serial/8250/8250_em.c b/drivers/tty/serial/8250/8250_em.c
index 0b63812..5deabaf 100644
--- a/drivers/tty/serial/8250/8250_em.c
+++ b/drivers/tty/serial/8250/8250_em.c
@@ -92,7 +92,7 @@ static int serial8250_em_probe(struct platform_device *pdev)
struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
struct serial8250_em_priv *priv;
- struct uart_8250_port up;
+ struct uart_8250_port up = {};
int ret;
if (!regs || !irq) {
@@ -110,7 +110,6 @@ static int serial8250_em_probe(struct platform_device *pdev)
return PTR_ERR(priv->sclk);
}
- memset(&up, 0, sizeof(up));
up.port.mapbase = regs->start;
up.port.irq = irq->start;
up.port.type = PORT_UNKNOWN;
diff --git a/drivers/tty/serial/8250/8250_gsc.c b/drivers/tty/serial/8250/8250_gsc.c
index b1e6ae9..5366e97 100644
--- a/drivers/tty/serial/8250/8250_gsc.c
+++ b/drivers/tty/serial/8250/8250_gsc.c
@@ -26,7 +26,7 @@
static int __init serial_init_chip(struct parisc_device *dev)
{
- struct uart_8250_port uart;
+ struct uart_8250_port uart = {};
unsigned long address;
int err;
@@ -53,7 +53,6 @@ static int __init serial_init_chip(struct parisc_device *dev)
if (dev->id.sversion != 0x8d)
address += 0x800;
- memset(&uart, 0, sizeof(uart));
uart.port.iotype = UPIO_MEM;
/* 7.272727MHz on Lasi. Assumed the same for Dino, Wax and Timi. */
uart.port.uartclk = (dev->id.sversion != 0xad) ?
diff --git a/drivers/tty/serial/8250/8250_hp300.c b/drivers/tty/serial/8250/8250_hp300.c
index 38166db..6fd6414 100644
--- a/drivers/tty/serial/8250/8250_hp300.c
+++ b/drivers/tty/serial/8250/8250_hp300.c
@@ -90,9 +90,7 @@ extern int hp300_uart_scode;
int __init hp300_setup_serial_console(void)
{
int scode;
- struct uart_port port;
-
- memset(&port, 0, sizeof(port));
+ struct uart_port port = {};
if (hp300_uart_scode < 0 || hp300_uart_scode > DIO_SCMAX)
return 0;
@@ -156,7 +154,7 @@ int __init hp300_setup_serial_console(void)
static int hpdca_init_one(struct dio_dev *d,
const struct dio_device_id *ent)
{
- struct uart_8250_port uart;
+ struct uart_8250_port uart = {};
int line;
#ifdef CONFIG_SERIAL_8250_CONSOLE
@@ -165,7 +163,6 @@ static int hpdca_init_one(struct dio_dev *d,
return 0;
}
#endif
- memset(&uart, 0, sizeof(uart));
/* Memory mapped I/O */
uart.port.iotype = UPIO_MEM;
@@ -205,7 +202,7 @@ static int __init hp300_8250_init(void)
#ifdef CONFIG_HPAPCI
int line;
unsigned long base;
- struct uart_8250_port uart;
+ struct uart_8250_port uart = {};
struct hp300_port *port;
int i;
#endif
@@ -243,8 +240,6 @@ static int __init hp300_8250_init(void)
if (!port)
return -ENOMEM;
- memset(&uart, 0, sizeof(uart));
-
base = (FRODO_BASE + FRODO_APCI_OFFSET(i));
/* Memory mapped I/O */
diff --git a/drivers/tty/serial/8250/8250_lpc18xx.c b/drivers/tty/serial/8250/8250_lpc18xx.c
index 99cd478..e00115b 100644
--- a/drivers/tty/serial/8250/8250_lpc18xx.c
+++ b/drivers/tty/serial/8250/8250_lpc18xx.c
@@ -105,7 +105,7 @@ static void lpc18xx_uart_serial_out(struct uart_port *p, int offset, int value)
static int lpc18xx_serial_probe(struct platform_device *pdev)
{
struct lpc18xx_uart_data *data;
- struct uart_8250_port uart;
+ struct uart_8250_port uart = {};
struct resource *res;
int irq, ret;
@@ -121,8 +121,6 @@ static int lpc18xx_serial_probe(struct platform_device *pdev)
return -EINVAL;
}
- memset(&uart, 0, sizeof(uart));
-
uart.port.membase = devm_ioremap(&pdev->dev, res->start,
resource_size(res));
if (!uart.port.membase)
diff --git a/drivers/tty/serial/8250/8250_lpss.c b/drivers/tty/serial/8250/8250_lpss.c
index 58cbb30..cba46dd 100644
--- a/drivers/tty/serial/8250/8250_lpss.c
+++ b/drivers/tty/serial/8250/8250_lpss.c
@@ -275,7 +275,7 @@ static int lpss8250_dma_setup(struct lpss8250 *lpss, struct uart_8250_port *port
static int lpss8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
- struct uart_8250_port uart;
+ struct uart_8250_port uart = {};
struct lpss8250 *lpss;
int ret;
@@ -289,8 +289,6 @@ static int lpss8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
lpss->board = (struct lpss8250_board *)id->driver_data;
- memset(&uart, 0, sizeof(struct uart_8250_port));
-
uart.port.dev = &pdev->dev;
uart.port.irq = pdev->irq;
uart.port.private_data = lpss;
diff --git a/drivers/tty/serial/8250/8250_mid.c b/drivers/tty/serial/8250/8250_mid.c
index ac013edf..8dd68c9 100644
--- a/drivers/tty/serial/8250/8250_mid.c
+++ b/drivers/tty/serial/8250/8250_mid.c
@@ -241,7 +241,7 @@ static int mid8250_dma_setup(struct mid8250 *mid, struct uart_8250_port *port)
static int mid8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
- struct uart_8250_port uart;
+ struct uart_8250_port uart = {};
struct mid8250 *mid;
unsigned int bar;
int ret;
@@ -259,8 +259,6 @@ static int mid8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
mid->board = (struct mid8250_board *)id->driver_data;
bar = FL_GET_BASE(mid->board->flags);
- memset(&uart, 0, sizeof(struct uart_8250_port));
-
uart.port.dev = &pdev->dev;
uart.port.irq = pdev->irq;
uart.port.private_data = mid;
diff --git a/drivers/tty/serial/8250/8250_moxa.c b/drivers/tty/serial/8250/8250_moxa.c
index 26eb539..fe5179b 100644
--- a/drivers/tty/serial/8250/8250_moxa.c
+++ b/drivers/tty/serial/8250/8250_moxa.c
@@ -49,7 +49,7 @@ static struct moxa8250_board moxa8250_boards[] = {
static int moxa8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
- struct uart_8250_port uart;
+ struct uart_8250_port uart = {};
struct moxa8250_board *brd;
void __iomem *ioaddr;
resource_size_t baseaddr;
@@ -69,8 +69,6 @@ static int moxa8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (!brd)
return -ENOMEM;
- memset(&uart, 0, sizeof(struct uart_8250_port));
-
uart.port.dev = &pdev->dev;
uart.port.irq = pdev->irq;
uart.port.uartclk = MOXA_BASE_BAUD * 16;
diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c
index d25ab1c..1fae126 100644
--- a/drivers/tty/serial/8250/8250_of.c
+++ b/drivers/tty/serial/8250/8250_of.c
@@ -196,8 +196,8 @@ static int of_platform_serial_probe(struct platform_device *ofdev)
case PORT_8250 ... PORT_MAX_8250:
{
u32 tx_threshold;
- struct uart_8250_port port8250;
- memset(&port8250, 0, sizeof(port8250));
+ struct uart_8250_port port8250 = {};
+
port8250.port = port;
if (port.fifosize)
diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
index 61ad6c3..ac88bf9 100644
--- a/drivers/tty/serial/8250/8250_omap.c
+++ b/drivers/tty/serial/8250/8250_omap.c
@@ -1093,7 +1093,7 @@ static int omap8250_probe(struct platform_device *pdev)
struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
struct omap8250_priv *priv;
- struct uart_8250_port up;
+ struct uart_8250_port up = {};
int ret;
void __iomem *membase;
@@ -1111,7 +1111,6 @@ static int omap8250_probe(struct platform_device *pdev)
if (!membase)
return -ENODEV;
- memset(&up, 0, sizeof(up));
up.port.dev = &pdev->dev;
up.port.mapbase = regs->start;
up.port.membase = membase;
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index aa0166b..5e45704 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -3834,7 +3834,7 @@ serial_pci_matches(const struct pciserial_board *board,
struct serial_private *
pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board)
{
- struct uart_8250_port uart;
+ struct uart_8250_port uart = {};
struct serial_private *priv;
struct pci_serial_quirk *quirk;
int rc, nr_ports, i;
@@ -3874,7 +3874,6 @@ pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board)
priv->dev = dev;
priv->quirk = quirk;
- memset(&uart, 0, sizeof(uart));
uart.port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
uart.port.uartclk = board->base_baud * 16;
uart.port.irq = get_pci_irq(dev, board);
diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c
index 34f05ed..0891a6f 100644
--- a/drivers/tty/serial/8250/8250_pnp.c
+++ b/drivers/tty/serial/8250/8250_pnp.c
@@ -439,7 +439,7 @@ static int serial_pnp_guess_board(struct pnp_dev *dev)
static int
serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
{
- struct uart_8250_port uart, *port;
+ struct uart_8250_port uart = {}, *port;
int ret, line, flags = dev_id->driver_data;
if (flags & UNKNOWN_DEV) {
@@ -448,7 +448,6 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
return ret;
}
- memset(&uart, 0, sizeof(uart));
if (pnp_irq_valid(dev, 0))
uart.port.irq = pnp_irq(dev, 0);
if ((flags & CIR_PORT) && pnp_port_valid(dev, 2)) {
diff --git a/drivers/tty/serial/8250/8250_uniphier.c b/drivers/tty/serial/8250/8250_uniphier.c
index 746680e..d7cfdfd 100644
--- a/drivers/tty/serial/8250/8250_uniphier.c
+++ b/drivers/tty/serial/8250/8250_uniphier.c
@@ -196,7 +196,7 @@ static int uniphier_of_serial_setup(struct device *dev, struct uart_port *port,
static int uniphier_uart_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- struct uart_8250_port up;
+ struct uart_8250_port up = {};
struct uniphier8250_priv *priv;
struct resource *regs;
void __iomem *membase;
@@ -223,8 +223,6 @@ static int uniphier_uart_probe(struct platform_device *pdev)
if (!priv)
return -ENOMEM;
- memset(&up, 0, sizeof(up));
-
ret = uniphier_of_serial_setup(dev, &up.port, priv);
if (ret < 0)
return ret;
diff --git a/drivers/tty/serial/8250/serial_cs.c b/drivers/tty/serial/8250/serial_cs.c
index 933c268..348f897 100644
--- a/drivers/tty/serial/8250/serial_cs.c
+++ b/drivers/tty/serial/8250/serial_cs.c
@@ -342,10 +342,9 @@ static void serial_detach(struct pcmcia_device *link)
static int setup_serial(struct pcmcia_device *handle, struct serial_info *info,
unsigned int iobase, int irq)
{
- struct uart_8250_port uart;
+ struct uart_8250_port uart = {};
int line;
- memset(&uart, 0, sizeof(uart));
uart.port.iobase = iobase;
uart.port.irq = irq;
uart.port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ;
--
2.7.4
^ permalink raw reply related
* [PATCH] arm64: dts: uniphier: add eMMC controller node for LD11/LD20
From: Masahiro Yamada @ 2016-12-23 3:18 UTC (permalink / raw)
To: linux-arm-kernel
Add Cadence's eMMC controller node for LD11/LD20.
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
---
arch/arm/boot/dts/uniphier-pinctrl.dtsi | 5 +++++
arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi | 12 ++++++++++++
arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi | 12 ++++++++++++
3 files changed, 29 insertions(+)
diff --git a/arch/arm/boot/dts/uniphier-pinctrl.dtsi b/arch/arm/boot/dts/uniphier-pinctrl.dtsi
index 10a7110..be353af15 100644
--- a/arch/arm/boot/dts/uniphier-pinctrl.dtsi
+++ b/arch/arm/boot/dts/uniphier-pinctrl.dtsi
@@ -43,6 +43,11 @@
*/
&pinctrl {
+ pinctrl_emmc: emmc_grp {
+ groups = "emmc", "emmc_dat8";
+ function = "emmc";
+ };
+
pinctrl_i2c0: i2c0_grp {
groups = "i2c0";
function = "i2c0";
diff --git a/arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi b/arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi
index 43b6583..e1e45b4 100644
--- a/arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi
+++ b/arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi
@@ -300,6 +300,18 @@
};
};
+ emmc: sdhc at 5a000000 {
+ compatible = "socionext,uniphier-sd4hc", "cdns,sd4hc";
+ reg = <0x5a000000 0x400>;
+ interrupts = <0 78 4>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_emmc>;
+ clocks = <&sys_clk 4>;
+ bus-width = <8>;
+ mmc-ddr-1_8v;
+ mmc-hs200-1_8v;
+ };
+
usb0: usb at 5a800100 {
compatible = "socionext,uniphier-ehci", "generic-ehci";
status = "disabled";
diff --git a/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi b/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi
index fcaecc6..1e61a04 100644
--- a/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi
+++ b/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi
@@ -374,6 +374,18 @@
};
};
+ emmc: sdhc at 5a000000 {
+ compatible = "socionext,uniphier-sd4hc", "cdns,sd4hc";
+ reg = <0x5a000000 0x400>;
+ interrupts = <0 78 4>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_emmc>;
+ clocks = <&sys_clk 4>;
+ bus-width = <8>;
+ mmc-ddr-1_8v;
+ mmc-hs200-1_8v;
+ };
+
soc-glue at 5f800000 {
compatible = "socionext,uniphier-ld20-soc-glue",
"simple-mfd", "syscon";
--
2.7.4
^ permalink raw reply related
* [PATCH v3 2/3] USB3/DWC3: Add property "snps, incr-burst-type-adjustment" for INCR burst type
From: Jerry Huang @ 2016-12-23 2:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161222184514.hfd4g7ifrz5cv627@rob-hp-laptop>
Hi, Rob,
> -----Original Message-----
> From: Rob Herring [mailto:robh at kernel.org]
> Sent: Friday, December 23, 2016 2:45 AM
> To: Jerry Huang <jerry.huang@nxp.com>
> Cc: balbi at kernel.org; mark.rutland at arm.com; catalin.marinas at arm.com;
> will.deacon at arm.com; linux at armlinux.org.uk; devicetree at vger.kernel.org;
> linux-usb at vger.kernel.org; linux-kernel at vger.kernel.org; linux-arm-
> kernel at lists.infradead.org
> Subject: Re: [PATCH v3 2/3] USB3/DWC3: Add property "snps, incr-burst-
> type-adjustment" for INCR burst type
>
> On Mon, Dec 19, 2016 at 05:25:53PM +0800, Changming Huang wrote:
> > New property "snps,incr-burst-type-adjustment = <x>, <y>" for USB3.0
> DWC3.
> > Field "x": 1/0 - undefined length INCR burst type enable or not; Field
> > "y": INCR4/INCR8/INCR16/INCR32/INCR64/INCR128/INCR256 burst type.
> >
> > While enabling undefined length INCR burst type and INCR16 burst type,
> > get better write performance on NXP Layerscape platform:
> > around 3% improvement (from 364MB/s to 375MB/s).
> >
> > Signed-off-by: Changming Huang <jerry.huang@nxp.com>
> > ---
> > Changes in v3:
> > - add new property for INCR burst in usb node.
> >
> > Documentation/devicetree/bindings/usb/dwc3.txt | 5 +++++
> > arch/arm/boot/dts/ls1021a.dtsi | 1 +
> > arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi | 3 +++
> > arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi | 2 ++
> > 4 files changed, 11 insertions(+)
> >
> > diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt
> > b/Documentation/devicetree/bindings/usb/dwc3.txt
> > index e3e6983..8c405a3 100644
> > --- a/Documentation/devicetree/bindings/usb/dwc3.txt
> > +++ b/Documentation/devicetree/bindings/usb/dwc3.txt
> > @@ -55,6 +55,10 @@ Optional properties:
> > fladj_30mhz_sdbnd signal is invalid or incorrect.
> >
> > - <DEPRECATED> tx-fifo-resize: determines if the FIFO *has* to be
> reallocated.
> > + - snps,incr-burst-type-adjustment: Value for INCR burst type of
> GSBUSCFG0
> > + register, undefined length INCR burst type enable and INCRx type.
> > + First field is for undefined length INCR burst type enable or not.
> > + Second field is for largest INCRx type enabled.
>
> Why do you need the first field? Is the 2nd field used if the 1st is 0?
> If not, then just use the presence of the property to enable or not.
The first field is one switch.
When it is 1, means undefined length INCR burst type enabled, we can use any length less than or equal to the largest-enabled burst length of INCR4/8/16/32/64/128/256.
When it is zero, means INCRx burst mode enabled, we can use one fixed burst length of 1/4/8/16/32/64/128/256 byte.
So, the 2nd field is used if the 1st is 0, we need to select one largest burst length the USB controller can support.
If we don't want to change the value of this register (use the default value), we don't need to add this property to usb node.
^ permalink raw reply
* [PATCH 3/3] dmaengine: pl330: Don't require irq-safe runtime PM
From: Krzysztof Kozlowski @ 2016-12-23 2:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1482408689-21971-4-git-send-email-m.szyprowski@samsung.com>
On Thu, Dec 22, 2016 at 01:11:29PM +0100, Marek Szyprowski wrote:
> This patch replaces irq-safe runtime pm with non-irq-safe version.
>
> Till now non-irq-safe runtime PM implementation was only possible by calling
> pm_runtime_get/put functions from alloc/free_chan_resources. All other DMA
> engine API functions cannot be called from a context, which allows sleeping.
> Such implementation in practice resulted in keeping PL330 DMA controller
> device active almost all the time, because most of the slave device drivers
> (DMA engine clients) acquired DMA channel in their probe() function and
> released it during driver removal.
I think that is not accurate (unless something changed recently and I
missed it)... The runtime PM in pl330 was infact suspending device when
the queue was empty. It was working during the regular work of DMA and
slave devices.
Maybe your recent fix changed this?
> This patch provides a new approach.
Please say why this approach is better because the previous one - was
suspending the dma channel when not used. Otherwise, it would make no
sense of implement the irq-safe runtime PM at the beginning!
Of course, a change from irq-safe to non-irq-safe is a good reason to
implement changes. But that was not mentioned in the first paragraph at
all.
> The main assumption for it is an
> observation that there can be only one slave device using each DMA channel.
Wait, observation, real requirement or assumption?
Later in the code I see adding such requirement.
> Using recently introduced device dependencies (links) infrastructure one can
> ensure proper runtime PM state of PL330 DMA controller. In this approach in
> pl330_alloc_chan_resources() function a new dependency is being created
> between PL330 DMA controller device (as supplier) and given slave device
> (as consumer). This way PL330 DMA controller device runtime active counter
> is increased when the slave device is resumed and decreased the same time
> when given slave device is put to suspend. This way it has been ensured to
> keep PL330 DMA controller runtime active if there is an active used of any
> of its DMA channels. Slave device pointer is initially stored in per-channel
> data in of_dma_xlate callback. This is similar to what has been already
> implemented in Exynos IOMMU driver in commit 2f5f44f205cc958b
> ("iommu/exynos: Use device dependency links to control runtime pm").
Sounds convincing... Interesting approach!
My doubts are:
1. What with more then one slave device? (assumption?)
2. If slave device does not implement runtime PM, then pl330 will be
active all the time?
3. If slave device implements runtime PM in a way that it's enabled in
probe and released in remove, then pl330 will be active all the time?
>
> If one requests memory-to-memory chanel, runtime active counter is
> increased unconditionally. This might be a drawback of this approach, but
> PL330 is not really used for memory-to-memory operations due to poor
> performance in such operations compared to CPU.
>
> Introducing non-irq-safe runtime power management finally allows to turn
> audio power domain off on Exynos5 SoCs.
... and actually any domain which contained pl330 device so this is nice
benefit!
>
> Removal of irq-safe runtime pm is based on the revert of the following
> commits:
> 1. "dmaengine: pl330: fix runtime pm support" commit <no stable id yet>
> 2. "dmaengine: pl330: Fix hang on dmaengine_terminate_all on certain boards"
> commit 81cc6edc08705ac0146fe6ac14a0982a31ce6f3d
> 3. "ARM: 8202/1: dmaengine: pl330: Add runtime Power Management support v12"
> commit ae43b3289186480f81c78bb63d788a85a3631f47
>
> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
> ---
> drivers/dma/pl330.c | 133 +++++++++++++++++++++++++++-------------------------
> 1 file changed, 70 insertions(+), 63 deletions(-)
>
> diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
> index 3c80e71..2cffbb4 100644
> --- a/drivers/dma/pl330.c
> +++ b/drivers/dma/pl330.c
> @@ -268,9 +268,6 @@ enum pl330_byteswap {
>
> #define NR_DEFAULT_DESC 16
>
> -/* Delay for runtime PM autosuspend, ms */
> -#define PL330_AUTOSUSPEND_DELAY 20
> -
> /* Populated by the PL330 core driver for DMA API driver's info */
> struct pl330_config {
> u32 periph_id;
> @@ -449,7 +446,8 @@ struct dma_pl330_chan {
> bool cyclic;
>
> /* for runtime pm tracking */
> - bool active;
> + struct device *slave;
> + struct device_link *slave_link;
> };
>
> struct pl330_dmac {
> @@ -2015,7 +2013,6 @@ static void pl330_tasklet(unsigned long data)
> struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data;
> struct dma_pl330_desc *desc, *_dt;
> unsigned long flags;
> - bool power_down = false;
>
> spin_lock_irqsave(&pch->lock, flags);
>
> @@ -2030,18 +2027,10 @@ static void pl330_tasklet(unsigned long data)
> /* Try to submit a req imm. next to the last completed cookie */
> fill_queue(pch);
>
> - if (list_empty(&pch->work_list)) {
> - spin_lock(&pch->thread->dmac->lock);
> - _stop(pch->thread);
> - spin_unlock(&pch->thread->dmac->lock);
> - power_down = true;
> - pch->active = false;
> - } else {
> - /* Make sure the PL330 Channel thread is active */
> - spin_lock(&pch->thread->dmac->lock);
> - _start(pch->thread);
> - spin_unlock(&pch->thread->dmac->lock);
> - }
> + /* Make sure the PL330 Channel thread is active */
> + spin_lock(&pch->thread->dmac->lock);
> + _start(pch->thread);
> + spin_unlock(&pch->thread->dmac->lock);
>
> while (!list_empty(&pch->completed_list)) {
> struct dmaengine_desc_callback cb;
> @@ -2054,13 +2043,6 @@ static void pl330_tasklet(unsigned long data)
> if (pch->cyclic) {
> desc->status = PREP;
> list_move_tail(&desc->node, &pch->work_list);
> - if (power_down) {
> - pch->active = true;
> - spin_lock(&pch->thread->dmac->lock);
> - _start(pch->thread);
> - spin_unlock(&pch->thread->dmac->lock);
> - power_down = false;
> - }
> } else {
> desc->status = FREE;
> list_move_tail(&desc->node, &pch->dmac->desc_pool);
> @@ -2075,12 +2057,6 @@ static void pl330_tasklet(unsigned long data)
> }
> }
> spin_unlock_irqrestore(&pch->lock, flags);
> -
> - /* If work list empty, power down */
> - if (power_down) {
> - pm_runtime_mark_last_busy(pch->dmac->ddma.dev);
> - pm_runtime_put_autosuspend(pch->dmac->ddma.dev);
> - }
> }
>
> bool pl330_filter(struct dma_chan *chan, void *param)
> @@ -2113,14 +2089,63 @@ static struct dma_chan *of_dma_pl330_xlate(struct of_phandle_args *dma_spec,
> if (chan_id >= pl330->num_peripherals)
> return NULL;
>
> + if (!pl330->peripherals[chan_id].slave)
> + pl330->peripherals[chan_id].slave = slave;
> + else if (pl330->peripherals[chan_id].slave != slave) {
> + dev_err(pl330->ddma.dev,
> + "Can't use same channel with multiple slave devices!\n");
> + return NULL;
> + }
This could be nicely split into separate patch.
Best regards,
Krzysztof
> +
> return dma_get_slave_channel(&pl330->peripherals[chan_id].chan);
> }
>
> +static int pl330_add_slave_link(struct pl330_dmac *pl330,
> + struct dma_pl330_chan *pch)
> +{
> + struct device_link *link;
> + int i;
> +
> + if (pch->slave_link)
> + return 0;
> +
> + link = device_link_add(pch->slave, pl330->ddma.dev,
> + DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE);
> + if (!link)
> + return -ENODEV;
> +
> + for (i = 0; i < pl330->num_peripherals; i++)
> + if (pl330->peripherals[i].slave == pch->slave)
> + pl330->peripherals[i].slave_link = link;
> + return 0;
> +}
> +
> +static void pl330_del_slave_link(struct pl330_dmac *pl330,
> + struct dma_pl330_chan *pch)
> +{
> + struct device_link *link = pch->slave_link;
> + int i, count = 0;
> +
> + for (i = 0; i < pl330->num_peripherals; i++)
> + if (pl330->peripherals[i].slave == pch->slave &&
> + pl330->peripherals[i].thread)
> + count++;
> +
> + if (count > 0)
> + return;
> +
> + device_link_del(link);
> + for (i = 0; i < pl330->num_peripherals; i++)
> + if (pl330->peripherals[i].slave == pch->slave)
> + pch->slave_link = NULL;
> +}
> +
> static int pl330_alloc_chan_resources(struct dma_chan *chan)
> {
> struct dma_pl330_chan *pch = to_pchan(chan);
> struct pl330_dmac *pl330 = pch->dmac;
> unsigned long flags;
> + int ret = 0;
>
> spin_lock_irqsave(&pch->lock, flags);
>
> @@ -2137,6 +2162,14 @@ static int pl330_alloc_chan_resources(struct dma_chan *chan)
>
> spin_unlock_irqrestore(&pch->lock, flags);
>
> + if (pch->slave)
> + ret = pl330_add_slave_link(pl330, pch);
> + else
> + ret = pm_runtime_get_sync(pl330->ddma.dev);
> +
> + if (ret < 0)
> + return ret;
> +
> return 1;
> }
>
> @@ -2171,9 +2204,7 @@ static int pl330_terminate_all(struct dma_chan *chan)
> unsigned long flags;
> struct pl330_dmac *pl330 = pch->dmac;
> LIST_HEAD(list);
> - bool power_down = false;
>
> - pm_runtime_get_sync(pl330->ddma.dev);
> spin_lock_irqsave(&pch->lock, flags);
> spin_lock(&pl330->lock);
> _stop(pch->thread);
> @@ -2182,8 +2213,6 @@ static int pl330_terminate_all(struct dma_chan *chan)
> pch->thread->req[0].desc = NULL;
> pch->thread->req[1].desc = NULL;
> pch->thread->req_running = -1;
> - power_down = pch->active;
> - pch->active = false;
>
> /* Mark all desc done */
> list_for_each_entry(desc, &pch->submitted_list, node) {
> @@ -2200,10 +2229,6 @@ static int pl330_terminate_all(struct dma_chan *chan)
> list_splice_tail_init(&pch->work_list, &pl330->desc_pool);
> list_splice_tail_init(&pch->completed_list, &pl330->desc_pool);
> spin_unlock_irqrestore(&pch->lock, flags);
> - pm_runtime_mark_last_busy(pl330->ddma.dev);
> - if (power_down)
> - pm_runtime_put_autosuspend(pl330->ddma.dev);
> - pm_runtime_put_autosuspend(pl330->ddma.dev);
>
> return 0;
> }
> @@ -2221,7 +2246,6 @@ static int pl330_pause(struct dma_chan *chan)
> struct pl330_dmac *pl330 = pch->dmac;
> unsigned long flags;
>
> - pm_runtime_get_sync(pl330->ddma.dev);
> spin_lock_irqsave(&pch->lock, flags);
>
> spin_lock(&pl330->lock);
> @@ -2229,8 +2253,6 @@ static int pl330_pause(struct dma_chan *chan)
> spin_unlock(&pl330->lock);
>
> spin_unlock_irqrestore(&pch->lock, flags);
> - pm_runtime_mark_last_busy(pl330->ddma.dev);
> - pm_runtime_put_autosuspend(pl330->ddma.dev);
>
> return 0;
> }
> @@ -2238,11 +2260,11 @@ static int pl330_pause(struct dma_chan *chan)
> static void pl330_free_chan_resources(struct dma_chan *chan)
> {
> struct dma_pl330_chan *pch = to_pchan(chan);
> + struct pl330_dmac *pl330 = pch->dmac;
> unsigned long flags;
>
> tasklet_kill(&pch->task);
>
> - pm_runtime_get_sync(pch->dmac->ddma.dev);
> spin_lock_irqsave(&pch->lock, flags);
>
> pl330_release_channel(pch->thread);
> @@ -2252,19 +2274,20 @@ static void pl330_free_chan_resources(struct dma_chan *chan)
> list_splice_tail_init(&pch->work_list, &pch->dmac->desc_pool);
>
> spin_unlock_irqrestore(&pch->lock, flags);
> - pm_runtime_mark_last_busy(pch->dmac->ddma.dev);
> - pm_runtime_put_autosuspend(pch->dmac->ddma.dev);
> +
> + if (pch->slave)
> + pl330_del_slave_link(pl330, pch);
> + else
> + pm_runtime_put(pl330->ddma.dev);
> }
>
> static int pl330_get_current_xferred_count(struct dma_pl330_chan *pch,
> struct dma_pl330_desc *desc)
> {
> struct pl330_thread *thrd = pch->thread;
> - struct pl330_dmac *pl330 = pch->dmac;
> void __iomem *regs = thrd->dmac->base;
> u32 val, addr;
>
> - pm_runtime_get_sync(pl330->ddma.dev);
> val = addr = 0;
> if (desc->rqcfg.src_inc) {
> val = readl(regs + SA(thrd->id));
> @@ -2273,8 +2296,6 @@ static int pl330_get_current_xferred_count(struct dma_pl330_chan *pch,
> val = readl(regs + DA(thrd->id));
> addr = desc->px.dst_addr;
> }
> - pm_runtime_mark_last_busy(pch->dmac->ddma.dev);
> - pm_runtime_put_autosuspend(pl330->ddma.dev);
>
> /* If DMAMOV hasn't finished yet, SAR/DAR can be zero */
> if (!val)
> @@ -2360,16 +2381,6 @@ static void pl330_issue_pending(struct dma_chan *chan)
> unsigned long flags;
>
> spin_lock_irqsave(&pch->lock, flags);
> - if (list_empty(&pch->work_list)) {
> - /*
> - * Warn on nothing pending. Empty submitted_list may
> - * break our pm_runtime usage counter as it is
> - * updated on work_list emptiness status.
> - */
> - WARN_ON(list_empty(&pch->submitted_list));
> - pch->active = true;
> - pm_runtime_get_sync(pch->dmac->ddma.dev);
> - }
> list_splice_tail_init(&pch->submitted_list, &pch->work_list);
> spin_unlock_irqrestore(&pch->lock, flags);
>
> @@ -2987,11 +2998,7 @@ static int __maybe_unused pl330_resume(struct device *dev)
> pcfg->data_buf_dep, pcfg->data_bus_width / 8, pcfg->num_chan,
> pcfg->num_peri, pcfg->num_events);
>
> - pm_runtime_irq_safe(&adev->dev);
> - pm_runtime_use_autosuspend(&adev->dev);
> - pm_runtime_set_autosuspend_delay(&adev->dev, PL330_AUTOSUSPEND_DELAY);
> - pm_runtime_mark_last_busy(&adev->dev);
> - pm_runtime_put_autosuspend(&adev->dev);
> + pm_runtime_put(&adev->dev);
>
> return 0;
> probe_err3:
> --
> 1.9.1
>
^ permalink raw reply
* [PATCH 2/2] clk: hi3660: Clock driver support for Hisilicon hi3660 SoC
From: zhangfei @ 2016-12-23 2:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161222205112.GD8288@codeaurora.org>
Hi, Stephen
On 2016?12?23? 04:51, Stephen Boyd wrote:
> On 12/22, zhangfei wrote:
>> On 2016?12?22? 07:25, Stephen Boyd wrote:
>>> On 12/15, Zhangfei Gao wrote:
>>>> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
>>>> +
>>>> + switch (type) {
>>>> + case HI3660_CRGCTRL:
>>>> + hi3660_clk_crgctrl_init(np);
>>>> + break;
>>>> + case HI3660_PCTRL:
>>>> + hi3660_clk_pctrl_init(np);
>>>> + break;
>>>> + case HI3660_PMUCTRL:
>>>> + hi3660_clk_pmuctrl_init(np);
>>>> + break;
>>>> + case HI3660_SCTRL:
>>>> + hi3660_clk_sctrl_init(np);
>>>> + break;
>>>> + case HI3660_IOMCU:
>>>> + hi3660_clk_iomcu_init(np);
>>>> + break;
>>> This "multi-device" driver design is sort of odd. Why not have
>>> different files and struct drivers for the different devices in
>>> the system that are clock controllers? I don't really understand
>>> why we're controlling the devices with one struct driver
>>> instance. Is something shared between the devices?
>> Do you mean put in different .c / drivers?
> Yes.
>
>> They have to be put in the same file, since the parent / child
>> relate to each other.
> We handle clk parent/child relationships through strings. So why
> does that mean we need to put these in the same file with the
> same struct driver?
Yes, you are right.
But we still prefer to put in the same file for as a hi3660-clock driver,
since it is easy to maintain.
There may too many files if each chip split to small pieces,
there may many chips for hisilicon in the futures.
And some clocks has less entries, like hi3660_pmu_gate_clks only have
one entry.
Also put in one file is easy to find parent/child relation, so easier to
find bugs.
After all, they just put in different region for privilege control, no
other special reason.
What do you think.
Thanks
>
>> They are for the same chip, but some put in different region for
>> privilege control.
> Ok.
>
^ permalink raw reply
* [PATCH] dmaengine: pl330: Fix runtime PM support for terminated transfers
From: Krzysztof Kozlowski @ 2016-12-23 2:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1481884751-21411-1-git-send-email-m.szyprowski@samsung.com>
On Fri, Dec 16, 2016 at 11:39:11AM +0100, Marek Szyprowski wrote:
> PL330 DMA engine driver is leaking a runtime reference after any terminated
> DMA transactions. This patch fixes this issue by tracking runtime PM state
> of the device and making additional call to pm_runtime_put() in terminate_all
> callback if needed.
>
> Fixes: ae43b3289186 ("ARM: 8202/1: dmaengine: pl330: Add runtime Power Management support v12")
> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
> ---
> drivers/dma/pl330.c | 11 +++++++++++
> 1 file changed, 11 insertions(+)
>
> diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
> index 030fe05ed43b..9f3dbc8c63d2 100644
> --- a/drivers/dma/pl330.c
> +++ b/drivers/dma/pl330.c
> @@ -448,6 +448,9 @@ struct dma_pl330_chan {
>
> /* for cyclic capability */
> bool cyclic;
> +
> + /* for runtime pm tracking */
> + bool active;
> };
>
> struct pl330_dmac {
> @@ -2031,6 +2034,7 @@ static void pl330_tasklet(unsigned long data)
> _stop(pch->thread);
> spin_unlock(&pch->thread->dmac->lock);
> power_down = true;
> + pch->active = false;
> } else {
> /* Make sure the PL330 Channel thread is active */
> spin_lock(&pch->thread->dmac->lock);
> @@ -2050,6 +2054,7 @@ static void pl330_tasklet(unsigned long data)
> desc->status = PREP;
> list_move_tail(&desc->node, &pch->work_list);
> if (power_down) {
> + pch->active = true;
It's been a while since I was playign with the driver so I don't
remember everything... but I can't get the logic behind this.
The device is marked as inactive and scheduled to power down. But you
mark chanel as active.
Maybe it is correct but for me it is unreadable.
I understand that you wanted to mark the device as active at some point,
in case transfer was terminated?
Best regards,
Krzysztof
> spin_lock(&pch->thread->dmac->lock);
> _start(pch->thread);
> spin_unlock(&pch->thread->dmac->lock);
> @@ -2164,6 +2169,7 @@ static int pl330_terminate_all(struct dma_chan *chan)
> unsigned long flags;
> struct pl330_dmac *pl330 = pch->dmac;
> LIST_HEAD(list);
> + bool power_down = false;
>
> pm_runtime_get_sync(pl330->ddma.dev);
> spin_lock_irqsave(&pch->lock, flags);
> @@ -2174,6 +2180,8 @@ static int pl330_terminate_all(struct dma_chan *chan)
> pch->thread->req[0].desc = NULL;
> pch->thread->req[1].desc = NULL;
> pch->thread->req_running = -1;
> + power_down = pch->active;
> + pch->active = false;
>
> /* Mark all desc done */
> list_for_each_entry(desc, &pch->submitted_list, node) {
> @@ -2191,6 +2199,8 @@ static int pl330_terminate_all(struct dma_chan *chan)
> list_splice_tail_init(&pch->completed_list, &pl330->desc_pool);
> spin_unlock_irqrestore(&pch->lock, flags);
> pm_runtime_mark_last_busy(pl330->ddma.dev);
> + if (power_down)
> + pm_runtime_put_autosuspend(pl330->ddma.dev);
> pm_runtime_put_autosuspend(pl330->ddma.dev);
>
> return 0;
> @@ -2350,6 +2360,7 @@ static void pl330_issue_pending(struct dma_chan *chan)
> * updated on work_list emptiness status.
> */
> WARN_ON(list_empty(&pch->submitted_list));
> + pch->active = true;
> pm_runtime_get_sync(pch->dmac->ddma.dev);
> }
> list_splice_tail_init(&pch->submitted_list, &pch->work_list);
> --
> 1.9.1
>
^ permalink raw reply
* [PATCH v1] watchdog: imx2: fix hang-up on boot for i.MX21, i.MX27 and i.MX31 SoCs
From: Guenter Roeck @ 2016-12-23 1:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <2fc2558d-fe05-14a7-745e-f71d2178bad6@mleia.com>
On 12/11/2016 03:21 AM, Vladimir Zapolskiy wrote:
> On 12/11/2016 12:26 PM, Uwe Kleine-K?nig wrote:
>> Hello Vladimir,
>>
>> On Sun, Dec 11, 2016 at 12:01:08PM +0200, Vladimir Zapolskiy wrote:
>>> On 12/11/2016 11:35 AM, Uwe Kleine-K?nig wrote:
>>>> On Sun, Dec 11, 2016 at 03:06:48AM +0200, Vladimir Zapolskiy wrote:
>>>>> Power down counter enable/disable bit switch is located in WMCR
>>>>> register, but watchdog controllers found on legacy i.MX21, i.MX27 and
>>>>> i.MX31 SoCs don't have this register. As a result of writing data to
>>>>> the non-existing register on driver probe the SoC hangs up, to fix the
>>>>> problem add more OF compatible strings and on this basis get
>>>>> information about availability of the WMCR register.
>>>>>
>>>>> Fixes: 5fe65ce7ccbb ("watchdog: imx2_wdt: Disable power down counter on boot")
>>>>> Signed-off-by: Vladimir Zapolskiy <vz@mleia.com>
>>>>> ---
>>>
What is the ultimate conclusion of this exchange ?
Are we going to get another version of the patch, or did everyone agree that
the patch is good as it is and does not require further changes ?
Guenter
>>> [snip]
>>>
>>>>>
>>>>> static const struct of_device_id imx2_wdt_dt_ids[] = {
>>>>> - { .compatible = "fsl,imx21-wdt", },
>>>>> + { .compatible = "fsl,imx21-wdt", .data = IMX2_WDT_NO_WMCR },
>>>>> + { .compatible = "fsl,imx25-wdt", },
>>>>> + { .compatible = "fsl,imx27-wdt", .data = IMX2_WDT_NO_WMCR },
>>>>> + { .compatible = "fsl,imx31-wdt", .data = IMX2_WDT_NO_WMCR },
>>>>> + { .compatible = "fsl,imx35-wdt", },
>>>>> + { .compatible = "fsl,imx50-wdt", },
>>>>> + { .compatible = "fsl,imx51-wdt", },
>>>>> + { .compatible = "fsl,imx53-wdt", },
>>>>> + { .compatible = "fsl,imx6q-wdt", },
>>>>> + { .compatible = "fsl,imx6sl-wdt", },
>>>>> + { .compatible = "fsl,imx6sx-wdt", },
>>>>> + { .compatible = "fsl,imx6ul-wdt", },
>>>>> + { .compatible = "fsl,imx7d-wdt", },
>>>>> + { .compatible = "fsl,vf610-wdt", },
>>>>
>>>> Up to now we only had fsl,imx21-wdt, now it seems that iMX31, i.MX27 and
>>>> i.MX21 form a group of equal watchdog IPs and the others form another
>>>> group, right?
>>>>
>>>> So conceptually we should differenciate between
>>>>
>>>> fsl,imx21-wdt (which is used on i.MX21, i.MX27 and i.MX31)
>>>> fsl,imx35-wdt (which is used on all others)
>>>>
>>>
>>> The problem is that "fsl,imx35-wdt" is not used on all others in the
>>> existing DTS, i.e. in the old firmware, which shall be compatible with
>>> new changes.
>>
>> So old i.MX53 has
>>
>> compatible = "fsl,imx53-wdt", "fsl,imx21-wdt";
>>
>> . With the change to the driver it's like using the watchdog driver in
>> it's pre-5fe65ce7ccbb4-state on it. If this is bad, we must indeed make
>> fsl,imx53-wdt known to the driver. If not, just adding a single new
>> compatible to the driver is just fine.
>
> The change under discussion preserves the current runtime behaviour for
> i.MX53 and its friends, the watchdog power down counter in WMCR is
> disabled on boot (you may want to confirm it by testing though), another
> question is if it is wanted for e.g. i.MX53 right from the beginning.
>
> To keep the runtime compatibility of a newer kernel with old DTBs such
> a long list of device compatibles has to be inserted.
>
>>
>> If you want to call it imx25 or imx35 doesn't matter much. The reason I
>> picked imx35 is that this one was already picked before for cspi. This
>> suggests that i.MX35 is older than i.MX25 and so this is the canonical
>> choice.
>
> Accepted, from the Wikipedia both i.MX25 and i.MX35 are released in 2009,
> which one is the first I don't know for sure, I supposed it could be
> i.MX25 as a SoC with a weaker core.
>
>>
>>> $ grep -H 'fsl,imx.*-wdt' arch/arm/boot/dts/*.dtsi
>>> arch/arm/boot/dts/imx25.dtsi: compatible = "fsl,imx25-wdt", "fsl,imx21-wdt";
>>> arch/arm/boot/dts/imx27.dtsi: compatible = "fsl,imx27-wdt", "fsl,imx21-wdt";
>>> arch/arm/boot/dts/imx35.dtsi: compatible = "fsl,imx35-wdt", "fsl,imx21-wdt";
>>> arch/arm/boot/dts/imx50.dtsi: compatible = "fsl,imx50-wdt", "fsl,imx21-wdt";
>>> arch/arm/boot/dts/imx51.dtsi: compatible = "fsl,imx51-wdt", "fsl,imx21-wdt";
>>> arch/arm/boot/dts/imx51.dtsi: compatible = "fsl,imx51-wdt", "fsl,imx21-wdt";
>>> arch/arm/boot/dts/imx53.dtsi: compatible = "fsl,imx53-wdt", "fsl,imx21-wdt";
>>> arch/arm/boot/dts/imx53.dtsi: compatible = "fsl,imx53-wdt", "fsl,imx21-wdt";
>>> arch/arm/boot/dts/imx6qdl.dtsi: compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt";
>>> arch/arm/boot/dts/imx6qdl.dtsi: compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt";
>>> arch/arm/boot/dts/imx6sl.dtsi: compatible = "fsl,imx6sl-wdt", "fsl,imx21-wdt";
>>> arch/arm/boot/dts/imx6sl.dtsi: compatible = "fsl,imx6sl-wdt", "fsl,imx21-wdt";
>>> arch/arm/boot/dts/imx6sx.dtsi: compatible = "fsl,imx6sx-wdt", "fsl,imx21-wdt";
>>> arch/arm/boot/dts/imx6sx.dtsi: compatible = "fsl,imx6sx-wdt", "fsl,imx21-wdt";
>>> arch/arm/boot/dts/imx6sx.dtsi: compatible = "fsl,imx6sx-wdt", "fsl,imx21-wdt";
>>> arch/arm/boot/dts/imx6ul.dtsi: compatible = "fsl,imx6ul-wdt", "fsl,imx21-wdt";
>>> arch/arm/boot/dts/imx6ul.dtsi: compatible = "fsl,imx6ul-wdt", "fsl,imx21-wdt";
>>> arch/arm/boot/dts/imx7s.dtsi: compatible = "fsl,imx7d-wdt", "fsl,imx21-wdt";
>>> arch/arm/boot/dts/imx7s.dtsi: compatible = "fsl,imx7d-wdt", "fsl,imx21-wdt";
>>> arch/arm/boot/dts/imx7s.dtsi: compatible = "fsl,imx7d-wdt", "fsl,imx21-wdt";
>>> arch/arm/boot/dts/imx7s.dtsi: compatible = "fsl,imx7d-wdt", "fsl,imx21-wdt";
>>> arch/arm/boot/dts/ls1021a.dtsi: compatible = "fsl,imx21-wdt";
>>> arch/arm/boot/dts/vfxxx.dtsi: compatible = "fsl,vf610-wdt", "fsl,imx21-wdt";
>>>
>>> I don't see a confirmation of the fact that "fsl,imx35-wdt" is the best
>>> selection, hence definitely "fsl,imx25-wdt" overscores it.
>>
>> I stated my reason to pick imx35 over imx25 above. Why do yo prefer
>> imx25?
>
> As you said right now and until it is added into DTS files "fsl,imx25-wdt" and
> "fsl,imx35-wdt" are equal as a compatible representation of WMCR-aware watchdogs.
>
> I may be wrong, if I assume that i.MX25 is released before i.MX35 (looks like
> they are released in parallel), but "imx25" precedes in alphanumerically sorted
> list of SoC names.
>
>>>> A reason to add e.g. fsl,imx6sl-wdt is that dtbs in the wild use
>>>>
>>>> "fsl,imx6sl-wdt", "fsl,imx21-wdt"
>>>>
>>>> . But then I wonder if
>>>>
>>>> 5fe65ce7ccbb ("watchdog: imx2_wdt: Disable power down counter on boot")
>>>>
>>>> is that important to justify to add these all.
>>>
>>> About this comment I don't know, you may have better insight about the original
>>> change. By the way, in barebox you may want to fix the same hang-up, because
>>> you touch WMCR unconditionally.
>>
>> Sure.
>>
>>>> Independant of this I'd like to have all dtsi for the newer SoCs changed
>>>> to get
>>>>
>>>> "fsl,imx6sl-wdt", "fsl,imx35-wdt"
>>>>
>>>> and if you really want to add all these compatibles, add a comment that
>>>> these are really fsl,imx35-wdt and were added to work around broken
>>>> dtbs.
>>>
>>> No objections, but
>>>
>>> 1) I'd like to see "fsl,imx25-wdt" as a new common compatible, and that's
>>> what have been proposed and shared in RFC 2/2.
>>
>> Yeah, I missed that other patch (which was not part of this series).
>>
>>> 2) Please remind me, why do you ask to drop "fsl,imx21-wdt" from the list?
>>>
>>> compatible = "fsl,imx6sx-wdt", "fsl,imx25-wdt", "fsl,imx21-wdt";
>>>
>>> The list of compatibles above is valid (from the most specific on the left
>>> to the most generic on the right), and that compatible property is rightly
>>> handled in the driver with this change applied. I don't see a need to
>>> drop "fsl,imx21-wdt".
>>
>> If the wdt in the i.MX6SX can be operated by the watchdog driver in it's
>> imx21 mode, you should keep the imx21 entry. If not, you shouldn't.
>
> The DTS description shall be rather independent from any particular software
> implementation, someone may want to reuse the same DTB in bootloaders and OS
> kernels of different versions. Assuming that I have a bootloader/kernel
> with a pure i.MX21 watchdog driver and run it on i.MX6SX, I'd prefer to match
> "fsl,imx21-wdt" compatible.
>
> --
> With best wishes,
> Vladimir
> --
> To unsubscribe from this list: send the line "unsubscribe linux-watchdog" 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
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