* Re: [PATCH V2 05/13] clk: bcm2835: Add BCM2711_CLOCK_EMMC2 support
From: Matthias Brugger @ 2019-09-12 17:24 UTC (permalink / raw)
To: Stefan Wahren, Eric Anholt, Florian Fainelli, Ray Jui,
Scott Branden, Wolfram Sang, Rob Herring, Mark Rutland,
Michael Turquette, Stephen Boyd
Cc: devicetree, bcm-kernel-feedback-list, linux-i2c, linux-clk,
linux-arm-kernel, linux-rpi-kernel
In-Reply-To: <1565713248-4906-6-git-send-email-wahrenst@gmx.net>
On 13/08/2019 18:20, Stefan Wahren wrote:
> The new BCM2711 supports an additional clock for the emmc2 block.
> So add a new compatible and register this clock only for BCM2711.
>
> Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
> Reviewed-by: Matthias Brugger <mbrugger@suse.com>
> Acked-by: Eric Anholt <eric@anholt.net>
> ---
> drivers/clk/bcm/clk-bcm2835.c | 20 +++++++++++++++++++-
> 1 file changed, 19 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
> index 21cd952..fdf672a 100644
> --- a/drivers/clk/bcm/clk-bcm2835.c
> +++ b/drivers/clk/bcm/clk-bcm2835.c
> @@ -114,6 +114,8 @@
> #define CM_AVEODIV 0x1bc
> #define CM_EMMCCTL 0x1c0
> #define CM_EMMCDIV 0x1c4
> +#define CM_EMMC2CTL 0x1d0
> +#define CM_EMMC2DIV 0x1d4
>
> /* General bits for the CM_*CTL regs */
> # define CM_ENABLE BIT(4)
> @@ -290,7 +292,8 @@
> #define BCM2835_MAX_FB_RATE 1750000000u
>
> #define SOC_BCM2835 BIT(0)
> -#define SOC_ALL (SOC_BCM2835)
> +#define SOC_BCM2711 BIT(1)
> +#define SOC_ALL (SOC_BCM2835 | SOC_BCM2711)
>
> /*
> * Names of clocks used within the driver that need to be replaced
> @@ -2003,6 +2006,16 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
> .frac_bits = 8,
> .tcnt_mux = 39),
>
> + /* EMMC2 clock (only available for BCM2711) */
> + [BCM2711_CLOCK_EMMC2] = REGISTER_PER_CLK(
> + SOC_BCM2711,
> + .name = "emmc2",
> + .ctl_reg = CM_EMMC2CTL,
> + .div_reg = CM_EMMC2DIV,
> + .int_bits = 4,
> + .frac_bits = 8,
> + .tcnt_mux = 42),
> +
> /* General purpose (GPIO) clocks */
> [BCM2835_CLOCK_GP0] = REGISTER_PER_CLK(
> SOC_ALL,
> @@ -2238,8 +2251,13 @@ static const struct cprman_plat_data cprman_bcm2835_plat_data = {
> .soc = SOC_BCM2835,
> };
>
> +static const struct cprman_plat_data cprman_bcm2711_plat_data = {
> + .soc = SOC_BCM2711,
> +};
> +
> static const struct of_device_id bcm2835_clk_of_match[] = {
> { .compatible = "brcm,bcm2835-cprman", .data = &cprman_bcm2835_plat_data },
> + { .compatible = "brcm,bcm2711-cprman", .data = &cprman_bcm2711_plat_data },
Because the RPi4 FW uses bcm2838-cprman as compatible, we will need to add this
here as well.
Regards,
Matthias
> {}
> };
> MODULE_DEVICE_TABLE(of, bcm2835_clk_of_match);
> --
> 2.7.4
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v5 0/4] Raspberry Pi 4 DMA addressing support
From: Florian Fainelli @ 2019-09-12 17:27 UTC (permalink / raw)
To: Matthias Brugger, Matthias Brugger, Stefan Wahren,
catalin.marinas, marc.zyngier, robh+dt, linux-mm,
linux-arm-kernel, linux-riscv, hch, Nicolas Saenz Julienne
Cc: robin.murphy, linux-kernel, linux-rpi-kernel, phill, will,
m.szyprowski
In-Reply-To: <09f82f88-a13a-b441-b723-7bb061a2f1e3@gmail.com>
On 9/12/19 10:18 AM, Matthias Brugger wrote:
>
>
> On 10/09/2019 11:27, Matthias Brugger wrote:
>>
>>
>> On 09/09/2019 21:33, Stefan Wahren wrote:
>>> Hi Nicolas,
>>>
>>> Am 09.09.19 um 11:58 schrieb Nicolas Saenz Julienne:
>>>> Hi all,
>>>> this series attempts to address some issues we found while bringing up
>>>> the new Raspberry Pi 4 in arm64 and it's intended to serve as a follow
>>>> up of these discussions:
>>>> v4: https://lkml.org/lkml/2019/9/6/352
>>>> v3: https://lkml.org/lkml/2019/9/2/589
>>>> v2: https://lkml.org/lkml/2019/8/20/767
>>>> v1: https://lkml.org/lkml/2019/7/31/922
>>>> RFC: https://lkml.org/lkml/2019/7/17/476
>>>>
>>>> The new Raspberry Pi 4 has up to 4GB of memory but most peripherals can
>>>> only address the first GB: their DMA address range is
>>>> 0xc0000000-0xfc000000 which is aliased to the first GB of physical
>>>> memory 0x00000000-0x3c000000. Note that only some peripherals have these
>>>> limitations: the PCIe, V3D, GENET, and 40-bit DMA channels have a wider
>>>> view of the address space by virtue of being hooked up trough a second
>>>> interconnect.
>>>>
>>>> Part of this is solved on arm32 by setting up the machine specific
>>>> '.dma_zone_size = SZ_1G', which takes care of reserving the coherent
>>>> memory area at the right spot. That said no buffer bouncing (needed for
>>>> dma streaming) is available at the moment, but that's a story for
>>>> another series.
>>>>
>>>> Unfortunately there is no such thing as 'dma_zone_size' in arm64. Only
>>>> ZONE_DMA32 is created which is interpreted by dma-direct and the arm64
>>>> arch code as if all peripherals where be able to address the first 4GB
>>>> of memory.
>>>>
>>>> In the light of this, the series implements the following changes:
>>>>
>>>> - Create both DMA zones in arm64, ZONE_DMA will contain the first 1G
>>>> area and ZONE_DMA32 the rest of the 32 bit addressable memory. So far
>>>> the RPi4 is the only arm64 device with such DMA addressing limitations
>>>> so this hardcoded solution was deemed preferable.
>>>>
>>>> - Properly set ARCH_ZONE_DMA_BITS.
>>>>
>>>> - Reserve the CMA area in a place suitable for all peripherals.
>>>>
>>>> This series has been tested on multiple devices both by checking the
>>>> zones setup matches the expectations and by double-checking physical
>>>> addresses on pages allocated on the three relevant areas GFP_DMA,
>>>> GFP_DMA32, GFP_KERNEL:
>>>>
>>>> - On an RPi4 with variations on the ram memory size. But also forcing
>>>> the situation where all three memory zones are nonempty by setting a 3G
>>>> ZONE_DMA32 ceiling on a 4G setup. Both with and without NUMA support.
>>>>
>>> i like to test this series on Raspberry Pi 4 and i have some questions
>>> to get arm64 running:
>>>
>>> Do you use U-Boot? Which tree?
>>
>> If you want to use U-Boot, try v2019.10-rc4, it should have everything you need
>> to boot your kernel.
>>
>
> Ok, here is a thing. In the linux kernel we now use bcm2711 as SoC name, but the
> RPi4 devicetree provided by the FW uses mostly bcm2838. U-Boot in its default
> config uses the devicetree provided by the FW, mostly because this way you don't
> have to do anything to find out how many RAM you really have. Secondly because
> this will allow us, in the near future, to have one U-boot binary for both RPi3
> and RPi4 (and as a side effect one binary for RPi1 and RPi2).
Fairly sure we had the conversation a few weeks ago about whether to
chose bcm2711 or bcm2838 for the compatible string. In all cases, the
actual HW this designates is the same, but there was a consistency
argument that 2838, is numerically + 1 than its predecessor and might be
how the RPi would be announced, even if the chip silkscreen says 2711.
If we start adding 2711, does that mean we should also add 2708/09/10 to
existing 2835/36/37 compatible strings or has that ship sailed?
--
Florian
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v9 0/8] stg mail -e --version=v9 \
From: Alexander Duyck @ 2019-09-12 17:48 UTC (permalink / raw)
To: Mel Gorman, Michal Hocko
Cc: Yang Zhang, Pankaj Gupta, kvm list, David Hildenbrand,
Catalin Marinas, Alexander Duyck, lcapitulino, linux-mm, will,
Andrea Arcangeli, virtio-dev, Michael S. Tsirkin, Matthew Wilcox,
Wang, Wei W, Mel Gorman, ying.huang, Rik van Riel,
Vlastimil Babka, Dan Williams, linux-arm-kernel, Oscar Salvador,
Nitesh Narayan Lal, Konrad Rzeszutek Wilk, Dave Hansen, LKML,
Paolo Bonzini, Andrew Morton, Fengguang Wu, Kirill A. Shutemov
In-Reply-To: <20190912163525.GV2739@techsingularity.net>
On Thu, 2019-09-12 at 17:35 +0100, Mel Gorman wrote:
> On Thu, Sep 12, 2019 at 11:19:25AM +0200, Michal Hocko wrote:
> > On Wed 11-09-19 08:12:03, Alexander Duyck wrote:
> > > On Wed, Sep 11, 2019 at 4:36 AM Michal Hocko <mhocko@kernel.org> wrote:
> > > > On Tue 10-09-19 14:23:40, Alexander Duyck wrote:
> > > > [...]
> > > > > We don't put any limitations on the allocator other then that it needs to
> > > > > clean up the metadata on allocation, and that it cannot allocate a page
> > > > > that is in the process of being reported since we pulled it from the
> > > > > free_list. If the page is a "Reported" page then it decrements the
> > > > > reported_pages count for the free_area and makes sure the page doesn't
> > > > > exist in the "Boundary" array pointer value, if it does it moves the
> > > > > "Boundary" since it is pulling the page.
> > > >
> > > > This is still a non-trivial limitation on the page allocation from an
> > > > external code IMHO. I cannot give any explicit reason why an ordering on
> > > > the free list might matter (well except for page shuffling which uses it
> > > > to make physical memory pattern allocation more random) but the
> > > > architecture seems hacky and dubious to be honest. It shoulds like the
> > > > whole interface has been developed around a very particular and single
> > > > purpose optimization.
> > >
> > > How is this any different then the code that moves a page that will
> > > likely be merged to the tail though?
> >
> > I guess you are referring to the page shuffling. If that is the case
> > then this is an integral part of the allocator for a reason and it is
> > very well obvious in the code including the consequences. I do not
> > really like an idea of hiding similar constrains behind a generic
> > looking feature which is completely detached from the allocator and so
> > any future change of the allocator might subtly break it.
> >
>
> It's not just that, compaction pokes into the free_area information as
> well and directly takes pages from the free list without going through
> the page allocator itself. It assumes that a free page is a free page
> and only takes the zone and migratetype into account.
Pulling pages out at random isn't an issue as long as the boundary pointer
gets pushed back. However the list tumbling with the
move_freelist_head/tail would be much more problematic for me since it is
essentially shuffling the list and will cause reported pages to be
shuffled in with non-reported ones.
> > > In our case the "Reported" page is likely going to be much more
> > > expensive to allocate and use then a standard page because it will be
> > > faulted back in. In such a case wouldn't it make sense for us to want
> > > to keep the pages that don't require faults ahead of those pages in
> > > the free_list so that they are more likely to be allocated?
> >
> > OK, I was suspecting this would pop out. And this is exactly why I
> > didn't like an idea of an external code imposing a non obvious constrains
> > to the allocator. You simply cannot count with any ordering with the
> > page allocator.
>
> Indeed not. It can be arbitrary and compaction can interfere with the
> ordering as well. While in theory that could be addressed by always
> going through an interface maintained by the page allocator, it would be
> tricky to test the virtio case in particular.
>
> > We used to distinguish cache hot/cold pages in the past
> > and pushed pages to the specific end of the free list but that has been
> > removed.
>
> That was always best effort too, not a hard guarantee. It was eventually
> removed as the cost of figuring out the ordering exceeded the benefit.
>
> > There are other potential changes like that possible. Shuffling
> > is a good recent example.
> >
> > Anyway I am not a maintainer of this code. I would really like to hear
> > opinions from Mel and Vlastimil here (now CCed - the thread starts
> > http://lkml.kernel.org/r/20190907172225.10910.34302.stgit@localhost.localdomain.
>
> I worry that poking too much into the internal state of the allocator
> will be fragile long-term. There is the arch alloc/free hooks but they
> are typically about protections only and does not interfere with the
> internal state of the allocator. Compaction pokes in as well but once
> the page is off the free list, the page allocator no longer cares so
> again there is on interference with the internal state. If the state is
> interefered with externally, it becomes unclear what happens if things
> like page merging is deferred in a way the allocator cannot control as
> high-order allocation requests may fail for example. For THP, it would
> not matter but failed allocation reports when pages are on the freelist,
> but unsuitable for allocation because of the reported state, would be
> hard to debug. Similarly, latency issues due to a reported page being
> picked for allocation but requiring communication with the hypervisor
> will be difficult to debug and atomic allocations may fail entirely.
> Finally, if merging was broken for reported/unreported pages, it could
> be a long time before such bugs were fixed.
We weren't preventing allocations off of the list other then when the
pages were actually off the list and being reported. So a reported page
could still be allocated normally.
As far as state there were only two things that were really being tracked
with the Reported flag. Basically when we cleared it we needed to make
sure the boundary pointer for the freelist was checked so we could push it
back if needed, and the count for the reported pages was decremented. All
the page->index was providing was an index into the boundary array so we
could find the pointer for that specific free_list.
> That's a lot of caveats to optimise communication about unused free
> pages to the allocator. I didn't read the patches particularly carefully
> but it was not clear why a best effort was not made to track free pages
> and if the metadata maintenance for that fills then do exhaustive
> searches for remaining pages. It might be difficult to stabilise that as
> the metadata may overflow again while the exhaustive search takes place.
> Much would depend on the frequency that pages are entering/leaving
> reported state.
What I was trying to avoid is having to perform an exhaustive walk of the
free_list. I was using boundary as an iterator. Since we have to hold the
zone->lock while pulling pages I wanted to keep the critical section as
small and fast as possible.
It seems like you were somewhat accomplishing that in the compaction code
by using the move_freelist_head/tail calls to basically roll over the list
as you are working through it. Maybe I will look to see just how expensive
it would be to do something similar as that would at least partially
reduce the cost.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH 1/6] dt-bindings: bus: sunxi: Add H3 MBUS compatible
From: Jernej Skrabec @ 2019-09-12 17:51 UTC (permalink / raw)
To: mripard, wens
Cc: mark.rutland, devicetree, linux-kernel, hverkuil, linux-sunxi,
robh+dt, mchehab, linux-arm-kernel, linux-media
In-Reply-To: <20190912175132.411-1-jernej.skrabec@siol.net>
Allwinner H3 SoC also contains MBUS controller.
Add compatible for it.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
Documentation/devicetree/bindings/arm/sunxi/sunxi-mbus.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/arm/sunxi/sunxi-mbus.txt b/Documentation/devicetree/bindings/arm/sunxi/sunxi-mbus.txt
index 1464a4713553..2005bb486705 100644
--- a/Documentation/devicetree/bindings/arm/sunxi/sunxi-mbus.txt
+++ b/Documentation/devicetree/bindings/arm/sunxi/sunxi-mbus.txt
@@ -8,6 +8,7 @@ bus.
Required properties:
- compatible: Must be one of:
- allwinner,sun5i-a13-mbus
+ - allwinner,sun8i-h3-mbus
- reg: Offset and length of the register set for the controller
- clocks: phandle to the clock driving the controller
- dma-ranges: See section 2.3.9 of the DeviceTree Specification
--
2.23.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 0/6] media: Introduce Allwinner H3 deinterlace driver
From: Jernej Skrabec @ 2019-09-12 17:51 UTC (permalink / raw)
To: mripard, wens
Cc: mark.rutland, devicetree, linux-kernel, hverkuil, linux-sunxi,
robh+dt, mchehab, linux-arm-kernel, linux-media
Starting with H3, Allwinner began to include standalone deinterlace
core in multimedia oriented SoCs. This patch series introduces support
for it. Note that new SoCs, like H6, have radically different (updated)
deinterlace core, which will need a new driver.
v4l2-compliance report:
v4l2-compliance SHA: dece02f862f38d8f866230ca9f1015cb93ddfac4, 32 bits
Compliance test for sun8i-di device /dev/video0:
Driver Info:
Driver name : sun8i-di
Card type : sun8i-di
Bus info : platform:sun8i-di
Driver version : 5.3.0
Capabilities : 0x84208000
Video Memory-to-Memory
Streaming
Extended Pix Format
Device Capabilities
Device Caps : 0x04208000
Video Memory-to-Memory
Streaming
Extended Pix Format
Required ioctls:
test VIDIOC_QUERYCAP: OK
Allow for multiple opens:
test second /dev/video0 open: OK
test VIDIOC_QUERYCAP: OK
test VIDIOC_G/S_PRIORITY: OK
test for unlimited opens: OK
Debug ioctls:
test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
test VIDIOC_LOG_STATUS: OK (Not Supported)
Input ioctls:
test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
test VIDIOC_ENUMAUDIO: OK (Not Supported)
test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
test VIDIOC_G/S_AUDIO: OK (Not Supported)
Inputs: 0 Audio Inputs: 0 Tuners: 0
Output ioctls:
test VIDIOC_G/S_MODULATOR: OK (Not Supported)
test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
test VIDIOC_ENUMAUDOUT: OK (Not Supported)
test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
test VIDIOC_G/S_AUDOUT: OK (Not Supported)
Outputs: 0 Audio Outputs: 0 Modulators: 0
Input/Output configuration ioctls:
test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
test VIDIOC_G/S_EDID: OK (Not Supported)
Control ioctls:
test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK (Not Supported)
test VIDIOC_QUERYCTRL: OK (Not Supported)
test VIDIOC_G/S_CTRL: OK (Not Supported)
test VIDIOC_G/S/TRY_EXT_CTRLS: OK (Not Supported)
test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK (Not Supported)
test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
Standard Controls: 0 Private Controls: 0
Format ioctls:
test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
test VIDIOC_G/S_PARM: OK (Not Supported)
test VIDIOC_G_FBUF: OK (Not Supported)
test VIDIOC_G_FMT: OK
test VIDIOC_TRY_FMT: OK
test VIDIOC_S_FMT: OK
test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
test Cropping: OK (Not Supported)
test Composing: OK (Not Supported)
test Scaling: OK
Codec ioctls:
test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
test VIDIOC_G_ENC_INDEX: OK (Not Supported)
test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
Buffer ioctls:
test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
test VIDIOC_EXPBUF: OK
test Requests: OK (Not Supported)
Total for sun8i-di device /dev/video0: 44, Succeeded: 44, Failed: 0, Warnings: 0
Please take a look.
Best regards,
Jernej
Jernej Skrabec (6):
dt-bindings: bus: sunxi: Add H3 MBUS compatible
clk: sunxi-ng: h3: Export MBUS clock
ARM: dts: sunxi: h3/h5: Add MBUS controller node
dt-bindings: media: Add Allwinner H3 Deinterlace binding
media: sun4i: Add H3 deinterlace driver
dts: arm: sun8i: h3: Enable deinterlace unit
.../bindings/arm/sunxi/sunxi-mbus.txt | 1 +
.../media/allwinner,sun8i-h3-deinterlace.yaml | 76 ++
MAINTAINERS | 7 +
arch/arm/boot/dts/sun8i-h3.dtsi | 13 +
arch/arm/boot/dts/sunxi-h3-h5.dtsi | 9 +
drivers/clk/sunxi-ng/ccu-sun8i-h3.h | 4 -
drivers/media/platform/sunxi/Kconfig | 1 +
drivers/media/platform/sunxi/Makefile | 1 +
drivers/media/platform/sunxi/sun8i-di/Kconfig | 10 +
.../media/platform/sunxi/sun8i-di/Makefile | 2 +
.../media/platform/sunxi/sun8i-di/sun8i-di.c | 969 ++++++++++++++++++
.../media/platform/sunxi/sun8i-di/sun8i-di.h | 238 +++++
include/dt-bindings/clock/sun8i-h3-ccu.h | 2 +-
13 files changed, 1328 insertions(+), 5 deletions(-)
create mode 100644 Documentation/devicetree/bindings/media/allwinner,sun8i-h3-deinterlace.yaml
create mode 100644 drivers/media/platform/sunxi/sun8i-di/Kconfig
create mode 100644 drivers/media/platform/sunxi/sun8i-di/Makefile
create mode 100644 drivers/media/platform/sunxi/sun8i-di/sun8i-di.c
create mode 100644 drivers/media/platform/sunxi/sun8i-di/sun8i-di.h
--
2.23.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH 2/6] clk: sunxi-ng: h3: Export MBUS clock
From: Jernej Skrabec @ 2019-09-12 17:51 UTC (permalink / raw)
To: mripard, wens
Cc: mark.rutland, devicetree, linux-kernel, hverkuil, linux-sunxi,
robh+dt, mchehab, linux-arm-kernel, linux-media
In-Reply-To: <20190912175132.411-1-jernej.skrabec@siol.net>
MBUS clock will be referenced in MBUS controller node.
Export it.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
drivers/clk/sunxi-ng/ccu-sun8i-h3.h | 4 ----
include/dt-bindings/clock/sun8i-h3-ccu.h | 2 +-
2 files changed, 1 insertion(+), 5 deletions(-)
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.h b/drivers/clk/sunxi-ng/ccu-sun8i-h3.h
index b6e2680ef354..d8c38447e11b 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-h3.h
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-h3.h
@@ -48,10 +48,6 @@
/* Some more module clocks are exported */
-#define CLK_MBUS 113
-
-/* And the GPU module clock is exported */
-
#define CLK_NUMBER_H3 (CLK_GPU + 1)
#define CLK_NUMBER_H5 (CLK_BUS_SCR1 + 1)
diff --git a/include/dt-bindings/clock/sun8i-h3-ccu.h b/include/dt-bindings/clock/sun8i-h3-ccu.h
index c5f7e9a70968..30d2d15373a2 100644
--- a/include/dt-bindings/clock/sun8i-h3-ccu.h
+++ b/include/dt-bindings/clock/sun8i-h3-ccu.h
@@ -143,7 +143,7 @@
#define CLK_AVS 110
#define CLK_HDMI 111
#define CLK_HDMI_DDC 112
-
+#define CLK_MBUS 113
#define CLK_GPU 114
/* New clocks imported in H5 */
--
2.23.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 3/6] ARM: dts: sunxi: h3/h5: Add MBUS controller node
From: Jernej Skrabec @ 2019-09-12 17:51 UTC (permalink / raw)
To: mripard, wens
Cc: mark.rutland, devicetree, linux-kernel, hverkuil, linux-sunxi,
robh+dt, mchehab, linux-arm-kernel, linux-media
In-Reply-To: <20190912175132.411-1-jernej.skrabec@siol.net>
Both, H3 and H5, contain MBUS, which is the bus used by DMA devices to
access system memory.
MBUS controller is responsible for arbitration between channels based
on set priority and can do some other things as well, like report
bandwidth used. It also maps RAM region to different address than CPU.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
arch/arm/boot/dts/sunxi-h3-h5.dtsi | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
index eba190b3f9de..ef1d03812636 100644
--- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi
+++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
@@ -109,6 +109,7 @@
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
+ dma-ranges;
ranges;
display_clocks: clock@1000000 {
@@ -538,6 +539,14 @@
};
};
+ mbus: dram-controller@1c62000 {
+ compatible = "allwinner,sun8i-h3-mbus";
+ reg = <0x01c62000 0x1000>;
+ clocks = <&ccu 113>;
+ dma-ranges = <0x00000000 0x40000000 0xc0000000>;
+ #interconnect-cells = <1>;
+ };
+
spi0: spi@1c68000 {
compatible = "allwinner,sun8i-h3-spi";
reg = <0x01c68000 0x1000>;
--
2.23.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 4/6] dt-bindings: media: Add Allwinner H3 Deinterlace binding
From: Jernej Skrabec @ 2019-09-12 17:51 UTC (permalink / raw)
To: mripard, wens
Cc: mark.rutland, devicetree, linux-kernel, hverkuil, linux-sunxi,
robh+dt, mchehab, linux-arm-kernel, linux-media
In-Reply-To: <20190912175132.411-1-jernej.skrabec@siol.net>
Allwinner H3 Deinterlace core is used for deinterlacing interlaced video
content. Core can also be found on some later SoCs, like H5 and R40.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
.../media/allwinner,sun8i-h3-deinterlace.yaml | 76 +++++++++++++++++++
1 file changed, 76 insertions(+)
create mode 100644 Documentation/devicetree/bindings/media/allwinner,sun8i-h3-deinterlace.yaml
diff --git a/Documentation/devicetree/bindings/media/allwinner,sun8i-h3-deinterlace.yaml b/Documentation/devicetree/bindings/media/allwinner,sun8i-h3-deinterlace.yaml
new file mode 100644
index 000000000000..31c0ac427442
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/allwinner,sun8i-h3-deinterlace.yaml
@@ -0,0 +1,76 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/arm/allwinner,sun8i-h3-deinterlace.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Allwinner H3 Deinterlace Device Tree Bindings
+
+maintainers:
+ - Chen-Yu Tsai <wens@csie.org>
+ - Maxime Ripard <maxime.ripard@bootlin.com>
+
+description: |-
+ The Allwinner H3 and later has a deinterlace core used for
+ deinterlacing interlaced video content.
+
+properties:
+ compatible:
+ const: allwinner,sun8i-h3-deinterlace
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: Deinterlace interface clock
+ - description: Deinterlace module clock
+ - description: Deinterlace DRAM clock
+
+ clock-names:
+ items:
+ - const: bus
+ - const: mod
+ - const: ram
+
+ resets:
+ maxItems: 1
+
+ interconnects:
+ maxItems: 1
+
+ interconnect-names:
+ items:
+ - const: dma-mem
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - clocks
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/clock/sun8i-h3-ccu.h>
+ #include <dt-bindings/reset/sun8i-h3-ccu.h>
+
+ deinterlace: deinterlace@1400000 {
+ compatible = "allwinner,sun8i-h3-deinterlace";
+ reg = <0x01400000 0x20000>;
+ clocks = <&ccu CLK_BUS_DEINTERLACE>,
+ <&ccu CLK_DEINTERLACE>,
+ <&ccu CLK_DRAM_DEINTERLACE>;
+ clock-names = "bus", "mod", "ram";
+ resets = <&ccu RST_BUS_DEINTERLACE>;
+ interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
+ interconnects = <&mbus 9>;
+ interconnect-names = "dma-mem";
+ };
+
+...
--
2.23.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 6/6] dts: arm: sun8i: h3: Enable deinterlace unit
From: Jernej Skrabec @ 2019-09-12 17:51 UTC (permalink / raw)
To: mripard, wens
Cc: mark.rutland, devicetree, linux-kernel, hverkuil, linux-sunxi,
robh+dt, mchehab, linux-arm-kernel, linux-media
In-Reply-To: <20190912175132.411-1-jernej.skrabec@siol.net>
Allwinner H3 SoC contains deinterlace unit, which can be used in
combination with VPU unit to decode and process interlaced videos.
Add a node for it.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
arch/arm/boot/dts/sun8i-h3.dtsi | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi
index e37c30e811d3..7a59c57d2114 100644
--- a/arch/arm/boot/dts/sun8i-h3.dtsi
+++ b/arch/arm/boot/dts/sun8i-h3.dtsi
@@ -120,6 +120,19 @@
};
soc {
+ deinterlace: deinterlace@1400000 {
+ compatible = "allwinner,sun8i-h3-deinterlace";
+ reg = <0x01400000 0x20000>;
+ clocks = <&ccu CLK_BUS_DEINTERLACE>,
+ <&ccu CLK_DEINTERLACE>,
+ <&ccu CLK_DRAM_DEINTERLACE>;
+ clock-names = "bus", "mod", "ram";
+ resets = <&ccu RST_BUS_DEINTERLACE>;
+ interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
+ interconnects = <&mbus 9>;
+ interconnect-names = "dma-mem";
+ };
+
syscon: system-control@1c00000 {
compatible = "allwinner,sun8i-h3-system-control";
reg = <0x01c00000 0x1000>;
--
2.23.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 5/6] media: sun4i: Add H3 deinterlace driver
From: Jernej Skrabec @ 2019-09-12 17:51 UTC (permalink / raw)
To: mripard, wens
Cc: mark.rutland, devicetree, linux-kernel, hverkuil, linux-sunxi,
robh+dt, mchehab, linux-arm-kernel, linux-media
In-Reply-To: <20190912175132.411-1-jernej.skrabec@siol.net>
Allwinner H3 SoC contains deinterlace unit, which has several modes of
operation - bypass, weave, bob and mixed (advanced) mode. I don't know
how mixed mode works, but according to Allwinner it gives best results,
so they use it exclusively. Currently this mode is also hardcoded here.
For each interleaved frame queued, this driver produces 2 deinterlaced
frames. Deinterlaced frames are based on 2 consequtive output buffers,
except for the first 2, where same output buffer is given to peripheral
as current and previous.
There is no documentation for this core, so register layout and fixed
values were taken from BSP driver.
I'm not sure if maximum size of the image unit is capable to process is
governed by size of "flag" buffers, frequency or it really is some HW
limitation. Currently driver can process full HD image in ~15ms (7.5ms
for each capture buffer), which allows to process 1920x1080@60i video
smoothly in real time.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
---
MAINTAINERS | 7 +
drivers/media/platform/sunxi/Kconfig | 1 +
drivers/media/platform/sunxi/Makefile | 1 +
drivers/media/platform/sunxi/sun8i-di/Kconfig | 10 +
.../media/platform/sunxi/sun8i-di/Makefile | 2 +
.../media/platform/sunxi/sun8i-di/sun8i-di.c | 969 ++++++++++++++++++
.../media/platform/sunxi/sun8i-di/sun8i-di.h | 238 +++++
7 files changed, 1228 insertions(+)
create mode 100644 drivers/media/platform/sunxi/sun8i-di/Kconfig
create mode 100644 drivers/media/platform/sunxi/sun8i-di/Makefile
create mode 100644 drivers/media/platform/sunxi/sun8i-di/sun8i-di.c
create mode 100644 drivers/media/platform/sunxi/sun8i-di/sun8i-di.h
diff --git a/MAINTAINERS b/MAINTAINERS
index ee4e873c0f9a..3b0c24c0b5ac 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4621,6 +4621,13 @@ M: "Maciej W. Rozycki" <macro@linux-mips.org>
S: Maintained
F: drivers/net/fddi/defxx.*
+DEINTERLACE DRIVERS FOR ALLWINNER H3
+M: Jernej Skrabec <jernej.skrabec@siol.net>
+L: linux-media@vger.kernel.org
+T: git git://linuxtv.org/media_tree.git
+S: Maintained
+F: drivers/media/platform/sunxi/sun8i-di/
+
DELL SMBIOS DRIVER
M: Pali Rohár <pali.rohar@gmail.com>
M: Mario Limonciello <mario.limonciello@dell.com>
diff --git a/drivers/media/platform/sunxi/Kconfig b/drivers/media/platform/sunxi/Kconfig
index 71808e93ac2e..d7a5621bf327 100644
--- a/drivers/media/platform/sunxi/Kconfig
+++ b/drivers/media/platform/sunxi/Kconfig
@@ -1,2 +1,3 @@
source "drivers/media/platform/sunxi/sun4i-csi/Kconfig"
source "drivers/media/platform/sunxi/sun6i-csi/Kconfig"
+source "drivers/media/platform/sunxi/sun8i-di/Kconfig"
diff --git a/drivers/media/platform/sunxi/Makefile b/drivers/media/platform/sunxi/Makefile
index a05127529006..3878cb4efdc2 100644
--- a/drivers/media/platform/sunxi/Makefile
+++ b/drivers/media/platform/sunxi/Makefile
@@ -1,2 +1,3 @@
obj-y += sun4i-csi/
obj-y += sun6i-csi/
+obj-y += sun8i-di/
diff --git a/drivers/media/platform/sunxi/sun8i-di/Kconfig b/drivers/media/platform/sunxi/sun8i-di/Kconfig
new file mode 100644
index 000000000000..88eef15514f9
--- /dev/null
+++ b/drivers/media/platform/sunxi/sun8i-di/Kconfig
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: GPL-2.0-only
+config VIDEO_SUN8I_DEINTERLACE
+ tristate "Allwinner Deinterlace driver"
+ depends on VIDEO_DEV && VIDEO_V4L2
+ depends on HAS_DMA
+ depends on OF
+ select VIDEOBUF2_DMA_CONTIG
+ select V4L2_MEM2MEM_DEV
+ help
+ Support for the Allwinner Deinterlace unit found on some SoCs.
diff --git a/drivers/media/platform/sunxi/sun8i-di/Makefile b/drivers/media/platform/sunxi/sun8i-di/Makefile
new file mode 100644
index 000000000000..109f7e5442b7
--- /dev/null
+++ b/drivers/media/platform/sunxi/sun8i-di/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_VIDEO_SUN8I_DEINTERLACE) += sun8i-di.o
diff --git a/drivers/media/platform/sunxi/sun8i-di/sun8i-di.c b/drivers/media/platform/sunxi/sun8i-di/sun8i-di.c
new file mode 100644
index 000000000000..9bd1920999b5
--- /dev/null
+++ b/drivers/media/platform/sunxi/sun8i-di/sun8i-di.c
@@ -0,0 +1,969 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Allwinner sun8i deinterlace driver
+ *
+ * Copyright (C) 2019 Jernej Skrabec <jernej.skrabec@siol.net>
+ *
+ * Based on vim2m driver.
+ */
+
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "sun8i-di.h"
+
+#define FLAG_SIZE (DEINTERLACE_MAX_WIDTH * DEINTERLACE_MAX_HEIGHT / 4)
+
+static u32 deinterlace_formats[] = {
+ V4L2_PIX_FMT_NV12,
+ V4L2_PIX_FMT_NV21,
+};
+
+static void deinterlace_device_run(void *priv)
+{
+ struct deinterlace_ctx *ctx = priv;
+ struct deinterlace_dev *dev = ctx->dev;
+ u32 size, stride, width, height, val;
+ struct vb2_v4l2_buffer *src, *dst;
+ unsigned int hstep, vstep;
+ dma_addr_t addr;
+
+ src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+ dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+
+ v4l2_m2m_buf_copy_metadata(src, dst, true);
+
+ regmap_write(dev->regmap, DEINTERLACE_MOD_ENABLE,
+ DEINTERLACE_MOD_ENABLE_EN);
+
+ if (ctx->field) {
+ regmap_write(dev->regmap, DEINTERLACE_TILE_FLAG0,
+ ctx->flag1_buf_dma);
+ regmap_write(dev->regmap, DEINTERLACE_TILE_FLAG1,
+ ctx->flag2_buf_dma);
+ } else {
+ regmap_write(dev->regmap, DEINTERLACE_TILE_FLAG0,
+ ctx->flag2_buf_dma);
+ regmap_write(dev->regmap, DEINTERLACE_TILE_FLAG1,
+ ctx->flag1_buf_dma);
+ }
+ regmap_write(dev->regmap, DEINTERLACE_FLAG_LINE_STRIDE, 0x200);
+
+ width = ctx->src_fmt.width;
+ height = ctx->src_fmt.height;
+ stride = ctx->src_fmt.bytesperline;
+ size = stride * height;
+
+ addr = vb2_dma_contig_plane_dma_addr(&src->vb2_buf, 0);
+ regmap_write(dev->regmap, DEINTERLACE_BUF_ADDR0, addr);
+ regmap_write(dev->regmap, DEINTERLACE_BUF_ADDR1, addr + size);
+ regmap_write(dev->regmap, DEINTERLACE_BUF_ADDR2, 0);
+
+ regmap_write(dev->regmap, DEINTERLACE_LINE_STRIDE0, stride);
+ regmap_write(dev->regmap, DEINTERLACE_LINE_STRIDE1, stride);
+
+ regmap_write(dev->regmap, DEINTERLACE_CH0_IN_SIZE,
+ DEINTERLACE_SIZE(width, height));
+ regmap_write(dev->regmap, DEINTERLACE_CH1_IN_SIZE,
+ DEINTERLACE_SIZE(width / 2, height / 2));
+
+ val = DEINTERLACE_IN_FMT_FMT(DEINTERLACE_IN_FMT_YUV420) |
+ DEINTERLACE_IN_FMT_MOD(DEINTERLACE_MODE_UV_COMBINED);
+ switch (ctx->src_fmt.pixelformat) {
+ case V4L2_PIX_FMT_NV12:
+ val |= DEINTERLACE_IN_FMT_PS(DEINTERLACE_PS_UVUV);
+ break;
+ case V4L2_PIX_FMT_NV21:
+ val |= DEINTERLACE_IN_FMT_PS(DEINTERLACE_PS_VUVU);
+ break;
+ }
+ regmap_write(dev->regmap, DEINTERLACE_IN_FMT, val);
+
+ if (ctx->prev)
+ addr = vb2_dma_contig_plane_dma_addr(&ctx->prev->vb2_buf, 0);
+
+ regmap_write(dev->regmap, DEINTERLACE_PRELUMA, addr);
+ regmap_write(dev->regmap, DEINTERLACE_PRECHROMA, addr + size);
+
+ val = DEINTERLACE_OUT_FMT_FMT(DEINTERLACE_OUT_FMT_YUV420SP);
+ switch (ctx->src_fmt.pixelformat) {
+ case V4L2_PIX_FMT_NV12:
+ val |= DEINTERLACE_OUT_FMT_PS(DEINTERLACE_PS_UVUV);
+ break;
+ case V4L2_PIX_FMT_NV21:
+ val |= DEINTERLACE_OUT_FMT_PS(DEINTERLACE_PS_VUVU);
+ break;
+ }
+ regmap_write(dev->regmap, DEINTERLACE_OUT_FMT, val);
+
+ width = ctx->dst_fmt.width;
+ height = ctx->dst_fmt.height;
+ stride = ctx->dst_fmt.bytesperline;
+ size = stride * height;
+
+ regmap_write(dev->regmap, DEINTERLACE_CH0_OUT_SIZE,
+ DEINTERLACE_SIZE(width, height));
+ regmap_write(dev->regmap, DEINTERLACE_CH1_OUT_SIZE,
+ DEINTERLACE_SIZE(width / 2, height / 2));
+
+ regmap_write(dev->regmap, DEINTERLACE_WB_LINE_STRIDE0, stride);
+ regmap_write(dev->regmap, DEINTERLACE_WB_LINE_STRIDE1, stride);
+
+ addr = vb2_dma_contig_plane_dma_addr(&dst->vb2_buf, 0);
+ regmap_write(dev->regmap, DEINTERLACE_WB_ADDR0, addr);
+ regmap_write(dev->regmap, DEINTERLACE_WB_ADDR1, addr + size);
+ regmap_write(dev->regmap, DEINTERLACE_WB_ADDR2, 0);
+
+ hstep = (ctx->src_fmt.width << 16) / ctx->dst_fmt.width;
+ vstep = (ctx->src_fmt.height << 16) / ctx->dst_fmt.height;
+ regmap_write(dev->regmap, DEINTERLACE_CH0_HORZ_FACT, hstep);
+ regmap_write(dev->regmap, DEINTERLACE_CH0_VERT_FACT, vstep);
+ regmap_write(dev->regmap, DEINTERLACE_CH1_HORZ_FACT, hstep);
+ regmap_write(dev->regmap, DEINTERLACE_CH1_VERT_FACT, vstep);
+
+ regmap_update_bits(dev->regmap, DEINTERLACE_FIELD_CTRL,
+ DEINTERLACE_FIELD_CTRL_FIELD_CNT_MSK,
+ DEINTERLACE_FIELD_CTRL_FIELD_CNT(ctx->field));
+
+ regmap_update_bits(dev->regmap, DEINTERLACE_FRM_CTRL,
+ DEINTERLACE_FRM_CTRL_START,
+ DEINTERLACE_FRM_CTRL_START);
+
+ regmap_update_bits(dev->regmap, DEINTERLACE_FRM_CTRL,
+ DEINTERLACE_FRM_CTRL_REG_READY,
+ DEINTERLACE_FRM_CTRL_REG_READY);
+
+ regmap_update_bits(dev->regmap, DEINTERLACE_INT_ENABLE,
+ DEINTERLACE_INT_ENABLE_WB_EN,
+ DEINTERLACE_INT_ENABLE_WB_EN);
+
+ regmap_update_bits(dev->regmap, DEINTERLACE_FRM_CTRL,
+ DEINTERLACE_FRM_CTRL_WB_EN,
+ DEINTERLACE_FRM_CTRL_WB_EN);
+}
+
+static int deinterlace_job_ready(void *priv)
+{
+ struct deinterlace_ctx *ctx = priv;
+
+ return v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) >= 1 &&
+ v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx) >= 2;
+}
+
+static void deinterlace_job_abort(void *priv)
+{
+ struct deinterlace_ctx *ctx = priv;
+
+ /* Will cancel the transaction in the next interrupt handler */
+ ctx->aborting = 1;
+}
+
+static irqreturn_t deinterlace_irq(int irq, void *data)
+{
+ struct deinterlace_dev *dev = data;
+ struct vb2_v4l2_buffer *src, *dst;
+ enum vb2_buffer_state state;
+ struct deinterlace_ctx *ctx;
+ unsigned int val;
+
+ ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev);
+ if (!ctx) {
+ v4l2_err(&dev->v4l2_dev,
+ "Instance released before the end of transaction\n");
+ return IRQ_NONE;
+ }
+
+ regmap_read(dev->regmap, DEINTERLACE_INT_STATUS, &val);
+ if (!(val & DEINTERLACE_INT_STATUS_WRITEBACK))
+ return IRQ_NONE;
+
+ regmap_write(dev->regmap, DEINTERLACE_INT_ENABLE, 0);
+ regmap_update_bits(dev->regmap, DEINTERLACE_INT_STATUS,
+ DEINTERLACE_INT_STATUS_WRITEBACK,
+ DEINTERLACE_INT_STATUS_WRITEBACK);
+ regmap_write(dev->regmap, DEINTERLACE_MOD_ENABLE, 0);
+ regmap_update_bits(dev->regmap, DEINTERLACE_FRM_CTRL,
+ DEINTERLACE_FRM_CTRL_START, 0);
+
+ regmap_read(dev->regmap, DEINTERLACE_STATUS, &val);
+ if (val & DEINTERLACE_STATUS_WB_ERROR)
+ state = VB2_BUF_STATE_ERROR;
+ else
+ state = VB2_BUF_STATE_DONE;
+
+ dst = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+ v4l2_m2m_buf_done(dst, state);
+
+ if (ctx->field != ctx->first_field || ctx->aborting) {
+ ctx->field = ctx->first_field;
+
+ src = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+ if (ctx->prev)
+ v4l2_m2m_buf_done(ctx->prev, state);
+ ctx->prev = src;
+
+ v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
+ } else {
+ ctx->field = !ctx->first_field;
+ deinterlace_device_run(ctx);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static void deinterlace_init(struct deinterlace_dev *dev)
+{
+ u32 val;
+ int i;
+
+ regmap_write(dev->regmap, DEINTERLACE_BYPASS,
+ DEINTERLACE_BYPASS_CSC);
+ regmap_write(dev->regmap, DEINTERLACE_WB_LINE_STRIDE_CTRL,
+ DEINTERLACE_WB_LINE_STRIDE_CTRL_EN);
+ regmap_update_bits(dev->regmap,
+ DEINTERLACE_FRM_CTRL,
+ DEINTERLACE_FRM_CTRL_OUT_CTRL,
+ DEINTERLACE_FRM_CTRL_OUT_CTRL);
+ regmap_write(dev->regmap, DEINTERLACE_AGTH_SEL,
+ DEINTERLACE_AGTH_SEL_LINEBUF);
+
+ val = DEINTERLACE_CTRL_EN |
+ DEINTERLACE_CTRL_MODE_MIXED |
+ DEINTERLACE_CTRL_DIAG_INTP_EN |
+ DEINTERLACE_CTRL_TEMP_DIFF_EN;
+ regmap_write(dev->regmap, DEINTERLACE_CTRL, val);
+
+ regmap_update_bits(dev->regmap, DEINTERLACE_LUMA_TH,
+ DEINTERLACE_LUMA_TH_MIN_LUMA_MSK,
+ DEINTERLACE_LUMA_TH_MIN_LUMA(4));
+
+ regmap_update_bits(dev->regmap, DEINTERLACE_SPAT_COMP,
+ DEINTERLACE_SPAT_COMP_TH2_MSK,
+ DEINTERLACE_SPAT_COMP_TH2(5));
+
+ regmap_update_bits(dev->regmap, DEINTERLACE_TEMP_DIFF,
+ DEINTERLACE_TEMP_DIFF_AMBIGUITY_TH_MSK,
+ DEINTERLACE_TEMP_DIFF_AMBIGUITY_TH(5));
+
+ val = DEINTERLACE_DIAG_INTP_TH0(60) |
+ DEINTERLACE_DIAG_INTP_TH1(0) |
+ DEINTERLACE_DIAG_INTP_TH3(30);
+ regmap_write(dev->regmap, DEINTERLACE_DIAG_INTP, val);
+
+ regmap_update_bits(dev->regmap, DEINTERLACE_CHROMA_DIFF,
+ DEINTERLACE_CHROMA_DIFF_TH_MSK,
+ DEINTERLACE_CHROMA_DIFF_TH(5));
+
+ /* neutral filter coefficients */
+ regmap_update_bits(dev->regmap, DEINTERLACE_FRM_CTRL,
+ DEINTERLACE_FRM_CTRL_COEF_CTRL,
+ DEINTERLACE_FRM_CTRL_COEF_CTRL);
+ regmap_read_poll_timeout(dev->regmap, DEINTERLACE_STATUS, val,
+ (val & DEINTERLACE_STATUS_COEF_STATUS), 2, 40);
+
+ for (i = 0; i < 32; i++) {
+ regmap_write(dev->regmap, DEINTERLACE_CH0_HORZ_COEF0 + i * 4,
+ DEINTERLACE_IDENTITY_COEF);
+ regmap_write(dev->regmap, DEINTERLACE_CH0_VERT_COEF + i * 4,
+ DEINTERLACE_IDENTITY_COEF);
+ regmap_write(dev->regmap, DEINTERLACE_CH1_HORZ_COEF0 + i * 4,
+ DEINTERLACE_IDENTITY_COEF);
+ regmap_write(dev->regmap, DEINTERLACE_CH1_VERT_COEF + i * 4,
+ DEINTERLACE_IDENTITY_COEF);
+ }
+
+ regmap_update_bits(dev->regmap, DEINTERLACE_FRM_CTRL,
+ DEINTERLACE_FRM_CTRL_COEF_CTRL, 0);
+}
+
+static inline struct deinterlace_ctx *deinterlace_file2ctx(struct file *file)
+{
+ return container_of(file->private_data, struct deinterlace_ctx, fh);
+}
+
+static bool deinterlace_check_format(u32 pixelformat)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(deinterlace_formats); i++)
+ if (deinterlace_formats[i] == pixelformat)
+ return true;
+
+ return false;
+}
+
+static void deinterlace_prepare_format(struct v4l2_pix_format *pix_fmt)
+{
+ unsigned int height = pix_fmt->height;
+ unsigned int width = pix_fmt->width;
+ unsigned int bytesperline;
+ unsigned int sizeimage;
+
+ width = clamp(width, DEINTERLACE_MIN_WIDTH,
+ DEINTERLACE_MAX_WIDTH);
+ height = clamp(height, DEINTERLACE_MIN_HEIGHT,
+ DEINTERLACE_MAX_HEIGHT);
+
+ bytesperline = ALIGN(width, 2);
+ /* luma */
+ sizeimage = bytesperline * height;
+ /* chroma */
+ sizeimage += bytesperline * height / 2;
+
+ pix_fmt->width = width;
+ pix_fmt->height = height;
+ pix_fmt->bytesperline = bytesperline;
+ pix_fmt->sizeimage = sizeimage;
+}
+
+static int deinterlace_querycap(struct file *file, void *priv,
+ struct v4l2_capability *cap)
+{
+ strscpy(cap->driver, DEINTERLACE_NAME, sizeof(cap->driver));
+ strscpy(cap->card, DEINTERLACE_NAME, sizeof(cap->card));
+ snprintf(cap->bus_info, sizeof(cap->bus_info),
+ "platform:%s", DEINTERLACE_NAME);
+
+ return 0;
+}
+
+static int deinterlace_enum_fmt(struct file *file, void *priv,
+ struct v4l2_fmtdesc *f)
+{
+ if (f->index < ARRAY_SIZE(deinterlace_formats)) {
+ f->pixelformat = deinterlace_formats[f->index];
+
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int deinterlace_enum_framesizes(struct file *file, void *priv,
+ struct v4l2_frmsizeenum *fsize)
+{
+ if (fsize->index != 0)
+ return -EINVAL;
+
+ if (!deinterlace_check_format(fsize->pixel_format))
+ return -EINVAL;
+
+ fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
+ fsize->stepwise.min_width = DEINTERLACE_MIN_WIDTH;
+ fsize->stepwise.min_height = DEINTERLACE_MIN_HEIGHT;
+ fsize->stepwise.max_width = DEINTERLACE_MAX_WIDTH;
+ fsize->stepwise.max_height = DEINTERLACE_MAX_HEIGHT;
+ fsize->stepwise.step_width = 2;
+ fsize->stepwise.step_height = 1;
+
+ return 0;
+}
+
+static int deinterlace_g_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct deinterlace_ctx *ctx = deinterlace_file2ctx(file);
+
+ f->fmt.pix = ctx->dst_fmt;
+
+ return 0;
+}
+
+static int deinterlace_g_fmt_vid_out(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct deinterlace_ctx *ctx = deinterlace_file2ctx(file);
+
+ f->fmt.pix = ctx->src_fmt;
+
+ return 0;
+}
+
+static int deinterlace_try_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ if (!deinterlace_check_format(f->fmt.pix.pixelformat))
+ f->fmt.pix.pixelformat = deinterlace_formats[0];
+
+ if (f->fmt.pix.field != V4L2_FIELD_NONE)
+ f->fmt.pix.field = V4L2_FIELD_NONE;
+
+ deinterlace_prepare_format(&f->fmt.pix);
+
+ return 0;
+}
+
+static int deinterlace_try_fmt_vid_out(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ if (!deinterlace_check_format(f->fmt.pix.pixelformat))
+ f->fmt.pix.pixelformat = deinterlace_formats[0];
+
+ if (f->fmt.pix.field != V4L2_FIELD_INTERLACED_TB &&
+ f->fmt.pix.field != V4L2_FIELD_INTERLACED_BT &&
+ f->fmt.pix.field != V4L2_FIELD_INTERLACED)
+ f->fmt.pix.field = V4L2_FIELD_INTERLACED;
+
+ deinterlace_prepare_format(&f->fmt.pix);
+
+ return 0;
+}
+
+static int deinterlace_s_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct deinterlace_ctx *ctx = deinterlace_file2ctx(file);
+ struct vb2_queue *vq;
+ int ret;
+
+ vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
+ if (vb2_is_busy(vq))
+ return -EBUSY;
+
+ ret = deinterlace_try_fmt_vid_cap(file, priv, f);
+ if (ret)
+ return ret;
+
+ ctx->dst_fmt = f->fmt.pix;
+
+ return 0;
+}
+
+static int deinterlace_s_fmt_vid_out(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct deinterlace_ctx *ctx = deinterlace_file2ctx(file);
+ struct vb2_queue *vq;
+ int ret;
+
+ vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
+ if (vb2_is_busy(vq))
+ return -EBUSY;
+
+ ret = deinterlace_try_fmt_vid_out(file, priv, f);
+ if (ret)
+ return ret;
+
+ ctx->src_fmt = f->fmt.pix;
+
+ /* Propagate colorspace information to capture. */
+ ctx->dst_fmt.colorspace = f->fmt.pix.colorspace;
+ ctx->dst_fmt.xfer_func = f->fmt.pix.xfer_func;
+ ctx->dst_fmt.ycbcr_enc = f->fmt.pix.ycbcr_enc;
+ ctx->dst_fmt.quantization = f->fmt.pix.quantization;
+
+ return 0;
+}
+
+const struct v4l2_ioctl_ops deinterlace_ioctl_ops = {
+ .vidioc_querycap = deinterlace_querycap,
+
+ .vidioc_enum_framesizes = deinterlace_enum_framesizes,
+
+ .vidioc_enum_fmt_vid_cap = deinterlace_enum_fmt,
+ .vidioc_g_fmt_vid_cap = deinterlace_g_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = deinterlace_try_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = deinterlace_s_fmt_vid_cap,
+
+ .vidioc_enum_fmt_vid_out = deinterlace_enum_fmt,
+ .vidioc_g_fmt_vid_out = deinterlace_g_fmt_vid_out,
+ .vidioc_try_fmt_vid_out = deinterlace_try_fmt_vid_out,
+ .vidioc_s_fmt_vid_out = deinterlace_s_fmt_vid_out,
+
+ .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
+ .vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
+ .vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
+ .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
+ .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,
+ .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,
+ .vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
+
+ .vidioc_streamon = v4l2_m2m_ioctl_streamon,
+ .vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
+};
+
+static int deinterlace_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
+ unsigned int *nplanes, unsigned int sizes[],
+ struct device *alloc_devs[])
+{
+ struct deinterlace_ctx *ctx = vb2_get_drv_priv(vq);
+ struct v4l2_pix_format *pix_fmt;
+
+ if (V4L2_TYPE_IS_OUTPUT(vq->type))
+ pix_fmt = &ctx->src_fmt;
+ else
+ pix_fmt = &ctx->dst_fmt;
+
+ if (*nplanes) {
+ if (sizes[0] < pix_fmt->sizeimage)
+ return -EINVAL;
+ } else {
+ sizes[0] = pix_fmt->sizeimage;
+ *nplanes = 1;
+ }
+
+ return 0;
+}
+
+static int deinterlace_buf_prepare(struct vb2_buffer *vb)
+{
+ struct vb2_queue *vq = vb->vb2_queue;
+ struct deinterlace_ctx *ctx = vb2_get_drv_priv(vq);
+ struct v4l2_pix_format *pix_fmt;
+
+ if (V4L2_TYPE_IS_OUTPUT(vq->type))
+ pix_fmt = &ctx->src_fmt;
+ else
+ pix_fmt = &ctx->dst_fmt;
+
+ if (vb2_plane_size(vb, 0) < pix_fmt->sizeimage)
+ return -EINVAL;
+
+ vb2_set_plane_payload(vb, 0, pix_fmt->sizeimage);
+
+ return 0;
+}
+
+static void deinterlace_buf_queue(struct vb2_buffer *vb)
+{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct deinterlace_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+
+ v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
+}
+
+static void deinterlace_queue_cleanup(struct vb2_queue *vq, u32 state)
+{
+ struct deinterlace_ctx *ctx = vb2_get_drv_priv(vq);
+ struct vb2_v4l2_buffer *vbuf;
+
+ do {
+ if (V4L2_TYPE_IS_OUTPUT(vq->type))
+ vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+ else
+ vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+
+ if (vbuf)
+ v4l2_m2m_buf_done(vbuf, state);
+ } while (vbuf);
+
+ if (V4L2_TYPE_IS_OUTPUT(vq->type) && ctx->prev)
+ v4l2_m2m_buf_done(ctx->prev, state);
+}
+
+static int deinterlace_start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+ struct deinterlace_ctx *ctx = vb2_get_drv_priv(vq);
+ struct device *dev = ctx->dev->dev;
+
+ if (V4L2_TYPE_IS_OUTPUT(vq->type)) {
+ ctx->first_field =
+ ctx->src_fmt.field == V4L2_FIELD_INTERLACED_BT;
+ ctx->field = ctx->first_field;
+
+ ctx->prev = NULL;
+ ctx->aborting = 0;
+
+ ctx->flag1_buf = dma_alloc_coherent(dev, FLAG_SIZE,
+ &ctx->flag1_buf_dma,
+ GFP_KERNEL);
+ if (!ctx->flag1_buf)
+ goto err_no_mem1;
+
+ ctx->flag2_buf = dma_alloc_coherent(dev, FLAG_SIZE,
+ &ctx->flag2_buf_dma,
+ GFP_KERNEL);
+ if (!ctx->flag2_buf)
+ goto err_no_mem2;
+ }
+
+ return 0;
+
+err_no_mem2:
+ dma_free_coherent(dev, FLAG_SIZE, ctx->flag1_buf,
+ ctx->flag1_buf_dma);
+err_no_mem1:
+ deinterlace_queue_cleanup(vq, VB2_BUF_STATE_QUEUED);
+
+ return -ENOMEM;
+}
+
+static void deinterlace_stop_streaming(struct vb2_queue *vq)
+{
+ struct deinterlace_ctx *ctx = vb2_get_drv_priv(vq);
+
+ if (V4L2_TYPE_IS_OUTPUT(vq->type)) {
+ struct device *dev = ctx->dev->dev;
+
+ dma_free_coherent(dev, FLAG_SIZE, ctx->flag1_buf,
+ ctx->flag1_buf_dma);
+ dma_free_coherent(dev, FLAG_SIZE, ctx->flag2_buf,
+ ctx->flag2_buf_dma);
+ }
+
+ deinterlace_queue_cleanup(vq, VB2_BUF_STATE_ERROR);
+}
+
+static const struct vb2_ops deinterlace_qops = {
+ .queue_setup = deinterlace_queue_setup,
+ .buf_prepare = deinterlace_buf_prepare,
+ .buf_queue = deinterlace_buf_queue,
+ .start_streaming = deinterlace_start_streaming,
+ .stop_streaming = deinterlace_stop_streaming,
+ .wait_prepare = vb2_ops_wait_prepare,
+ .wait_finish = vb2_ops_wait_finish,
+};
+
+static int deinterlace_queue_init(void *priv, struct vb2_queue *src_vq,
+ struct vb2_queue *dst_vq)
+{
+ struct deinterlace_ctx *ctx = priv;
+ int ret;
+
+ src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
+ src_vq->drv_priv = ctx;
+ src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+ src_vq->min_buffers_needed = 1;
+ src_vq->ops = &deinterlace_qops;
+ src_vq->mem_ops = &vb2_dma_contig_memops;
+ src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+ src_vq->lock = &ctx->dev->dev_mutex;
+ src_vq->dev = ctx->dev->dev;
+
+ ret = vb2_queue_init(src_vq);
+ if (ret)
+ return ret;
+
+ dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
+ dst_vq->drv_priv = ctx;
+ dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+ dst_vq->min_buffers_needed = 2;
+ dst_vq->ops = &deinterlace_qops;
+ dst_vq->mem_ops = &vb2_dma_contig_memops;
+ dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+ dst_vq->lock = &ctx->dev->dev_mutex;
+ dst_vq->dev = ctx->dev->dev;
+
+ ret = vb2_queue_init(dst_vq);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int deinterlace_open(struct file *file)
+{
+ struct deinterlace_dev *dev = video_drvdata(file);
+ struct deinterlace_ctx *ctx = NULL;
+ int ret;
+
+ if (mutex_lock_interruptible(&dev->dev_mutex))
+ return -ERESTARTSYS;
+
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+ if (!ctx) {
+ mutex_unlock(&dev->dev_mutex);
+ return -ENOMEM;
+ }
+
+ /* default output format */
+ ctx->src_fmt.pixelformat = deinterlace_formats[0];
+ ctx->src_fmt.field = V4L2_FIELD_INTERLACED;
+ ctx->src_fmt.width = 640;
+ ctx->src_fmt.height = 480;
+ deinterlace_prepare_format(&ctx->src_fmt);
+
+ /* default capture format */
+ ctx->dst_fmt.pixelformat = deinterlace_formats[0];
+ ctx->dst_fmt.field = V4L2_FIELD_NONE;
+ ctx->dst_fmt.width = 640;
+ ctx->dst_fmt.height = 480;
+ deinterlace_prepare_format(&ctx->dst_fmt);
+
+ v4l2_fh_init(&ctx->fh, video_devdata(file));
+ file->private_data = &ctx->fh;
+ ctx->dev = dev;
+
+ ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx,
+ &deinterlace_queue_init);
+ if (IS_ERR(ctx->fh.m2m_ctx)) {
+ ret = PTR_ERR(ctx->fh.m2m_ctx);
+ goto err_free;
+ }
+
+ v4l2_fh_add(&ctx->fh);
+
+ mutex_unlock(&dev->dev_mutex);
+
+ return 0;
+
+err_free:
+ kfree(ctx);
+ mutex_unlock(&dev->dev_mutex);
+
+ return ret;
+}
+
+static int deinterlace_release(struct file *file)
+{
+ struct deinterlace_dev *dev = video_drvdata(file);
+ struct deinterlace_ctx *ctx = container_of(file->private_data,
+ struct deinterlace_ctx, fh);
+
+ mutex_lock(&dev->dev_mutex);
+
+ v4l2_fh_del(&ctx->fh);
+ v4l2_fh_exit(&ctx->fh);
+ v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
+
+ kfree(ctx);
+
+ mutex_unlock(&dev->dev_mutex);
+
+ return 0;
+}
+
+static const struct v4l2_file_operations deinterlace_fops = {
+ .owner = THIS_MODULE,
+ .open = deinterlace_open,
+ .release = deinterlace_release,
+ .poll = v4l2_m2m_fop_poll,
+ .unlocked_ioctl = video_ioctl2,
+ .mmap = v4l2_m2m_fop_mmap,
+};
+
+static const struct video_device deinterlace_video_device = {
+ .name = DEINTERLACE_NAME,
+ .vfl_dir = VFL_DIR_M2M,
+ .fops = &deinterlace_fops,
+ .ioctl_ops = &deinterlace_ioctl_ops,
+ .minor = -1,
+ .release = video_device_release_empty,
+ .device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING,
+};
+
+static const struct v4l2_m2m_ops deinterlace_m2m_ops = {
+ .device_run = deinterlace_device_run,
+ .job_ready = deinterlace_job_ready,
+ .job_abort = deinterlace_job_abort,
+};
+
+static const struct regmap_config deinterlace_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+ .max_register = 0x97f,
+};
+
+static int deinterlace_probe(struct platform_device *pdev)
+{
+ struct deinterlace_dev *dev;
+ struct video_device *vfd;
+ struct resource *res;
+ int irq, ret;
+
+ dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return -ENOMEM;
+
+ dev->vfd = deinterlace_video_device;
+ dev->dev = &pdev->dev;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq <= 0) {
+ dev_err(dev->dev, "Failed to get IRQ\n");
+
+ return irq;
+ }
+
+ ret = devm_request_irq(dev->dev, irq, deinterlace_irq,
+ 0, dev_name(dev->dev), dev);
+ if (ret) {
+ dev_err(dev->dev, "Failed to request IRQ\n");
+
+ return ret;
+ }
+
+ ret = of_dma_configure(dev->dev, dev->dev->of_node, true);
+ if (ret)
+ return ret;
+
+ dev->bus_clk = devm_clk_get(dev->dev, "bus");
+ if (IS_ERR(dev->bus_clk)) {
+ dev_err(dev->dev, "Failed to get bus clock\n");
+
+ return PTR_ERR(dev->bus_clk);
+ }
+
+ dev->mod_clk = devm_clk_get(dev->dev, "mod");
+ if (IS_ERR(dev->mod_clk)) {
+ dev_err(dev->dev, "Failed to get mod clock\n");
+
+ return PTR_ERR(dev->mod_clk);
+ }
+
+ dev->ram_clk = devm_clk_get(dev->dev, "ram");
+ if (IS_ERR(dev->ram_clk)) {
+ dev_err(dev->dev, "Failed to get ram clock\n");
+
+ return PTR_ERR(dev->ram_clk);
+ }
+
+ dev->rstc = devm_reset_control_get(dev->dev, NULL);
+ if (IS_ERR(dev->rstc)) {
+ dev_err(dev->dev, "Failed to get reset control\n");
+
+ return PTR_ERR(dev->rstc);
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ dev->base = devm_ioremap_resource(dev->dev, res);
+ if (IS_ERR(dev->base)) {
+ dev_err(dev->dev, "Failed to map registers\n");
+
+ return PTR_ERR(dev->base);
+ }
+
+ dev->regmap = devm_regmap_init_mmio(dev->dev, dev->base,
+ &deinterlace_regmap_config);
+ if (IS_ERR(dev->regmap)) {
+ dev_err(dev->dev, "Couldn't create deinterlace regmap\n");
+
+ return PTR_ERR(dev->regmap);
+ }
+
+ ret = clk_prepare_enable(dev->bus_clk);
+ if (ret) {
+ dev_err(dev->dev, "Failed to enable bus clock\n");
+
+ return ret;
+ }
+
+ clk_set_rate(dev->mod_clk, 300000000);
+
+ ret = clk_prepare_enable(dev->mod_clk);
+ if (ret) {
+ dev_err(dev->dev, "Failed to enable mod clock\n");
+
+ goto err_bus_clk;
+ }
+
+ ret = clk_prepare_enable(dev->ram_clk);
+ if (ret) {
+ dev_err(dev->dev, "Failed to enable ram clock\n");
+
+ goto err_mod_clk;
+ }
+
+ ret = reset_control_reset(dev->rstc);
+ if (ret) {
+ dev_err(dev->dev, "Failed to apply reset\n");
+
+ goto err_ram_clk;
+ }
+
+ mutex_init(&dev->dev_mutex);
+
+ ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
+ if (ret) {
+ dev_err(dev->dev, "Failed to register V4L2 device\n");
+
+ goto err_rstc;
+ }
+
+ vfd = &dev->vfd;
+ vfd->lock = &dev->dev_mutex;
+ vfd->v4l2_dev = &dev->v4l2_dev;
+
+ snprintf(vfd->name, sizeof(vfd->name), "%s",
+ deinterlace_video_device.name);
+ video_set_drvdata(vfd, dev);
+
+ ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
+ if (ret) {
+ v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
+
+ goto err_v4l2;
+ }
+
+ v4l2_info(&dev->v4l2_dev,
+ "Device registered as /dev/video%d\n", vfd->num);
+
+ dev->m2m_dev = v4l2_m2m_init(&deinterlace_m2m_ops);
+ if (IS_ERR(dev->m2m_dev)) {
+ v4l2_err(&dev->v4l2_dev,
+ "Failed to initialize V4L2 M2M device\n");
+ ret = PTR_ERR(dev->m2m_dev);
+
+ goto err_video;
+ }
+
+ platform_set_drvdata(pdev, dev);
+
+ deinterlace_init(dev);
+
+ return 0;
+
+err_video:
+ video_unregister_device(&dev->vfd);
+err_v4l2:
+ v4l2_device_unregister(&dev->v4l2_dev);
+err_rstc:
+ reset_control_assert(dev->rstc);
+err_ram_clk:
+ clk_disable_unprepare(dev->ram_clk);
+err_mod_clk:
+ clk_disable_unprepare(dev->mod_clk);
+err_bus_clk:
+ clk_disable_unprepare(dev->bus_clk);
+
+ return ret;
+}
+
+static int deinterlace_remove(struct platform_device *pdev)
+{
+ struct deinterlace_dev *dev = platform_get_drvdata(pdev);
+
+ v4l2_m2m_release(dev->m2m_dev);
+ video_unregister_device(&dev->vfd);
+ v4l2_device_unregister(&dev->v4l2_dev);
+
+ reset_control_assert(dev->rstc);
+
+ clk_disable_unprepare(dev->ram_clk);
+ clk_disable_unprepare(dev->mod_clk);
+ clk_disable_unprepare(dev->bus_clk);
+
+ return 0;
+}
+
+static const struct of_device_id deinterlace_dt_match[] = {
+ { .compatible = "allwinner,sun8i-h3-deinterlace" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, deinterlace_dt_match);
+
+static struct platform_driver deinterlace_driver = {
+ .probe = deinterlace_probe,
+ .remove = deinterlace_remove,
+ .driver = {
+ .name = DEINTERLACE_NAME,
+ .of_match_table = of_match_ptr(deinterlace_dt_match),
+ },
+};
+module_platform_driver(deinterlace_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Jernej Skrabec <jernej.skrabec@siol.net>");
+MODULE_DESCRIPTION("Allwinner Deinterlace driver");
diff --git a/drivers/media/platform/sunxi/sun8i-di/sun8i-di.h b/drivers/media/platform/sunxi/sun8i-di/sun8i-di.h
new file mode 100644
index 000000000000..d4c02fc1ee19
--- /dev/null
+++ b/drivers/media/platform/sunxi/sun8i-di/sun8i-di.h
@@ -0,0 +1,238 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Allwinner Deinterlace driver
+ *
+ * Copyright (C) 2019 Jernej Skrabec <jernej.skrabec@siol.net>
+ */
+
+#ifndef _SUN8I_DEINTERLACE_H_
+#define _SUN8I_DEINTERLACE_H_
+
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/videobuf2-v4l2.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include <linux/platform_device.h>
+
+#define DEINTERLACE_NAME "sun8i-di"
+
+#define DEINTERLACE_MOD_ENABLE 0x00
+#define DEINTERLACE_MOD_ENABLE_EN BIT(0)
+
+#define DEINTERLACE_FRM_CTRL 0x04
+#define DEINTERLACE_FRM_CTRL_REG_READY BIT(0)
+#define DEINTERLACE_FRM_CTRL_WB_EN BIT(2)
+#define DEINTERLACE_FRM_CTRL_OUT_CTRL BIT(11)
+#define DEINTERLACE_FRM_CTRL_START BIT(16)
+#define DEINTERLACE_FRM_CTRL_COEF_CTRL BIT(23)
+
+#define DEINTERLACE_BYPASS 0x08
+#define DEINTERLACE_BYPASS_CSC BIT(1)
+
+#define DEINTERLACE_AGTH_SEL 0x0c
+#define DEINTERLACE_AGTH_SEL_LINEBUF BIT(8)
+
+#define DEINTERLACE_LINT_CTRL 0x10
+#define DEINTERLACE_TRD_PRELUMA 0x1c
+#define DEINTERLACE_BUF_ADDR0 0x20
+#define DEINTERLACE_BUF_ADDR1 0x24
+#define DEINTERLACE_BUF_ADDR2 0x28
+
+#define DEINTERLACE_FIELD_CTRL 0x2c
+#define DEINTERLACE_FIELD_CTRL_FIELD_CNT(v) ((v) & 0xff)
+#define DEINTERLACE_FIELD_CTRL_FIELD_CNT_MSK (0xff)
+
+#define DEINTERLACE_TB_OFFSET0 0x30
+#define DEINTERLACE_TB_OFFSET1 0x34
+#define DEINTERLACE_TB_OFFSET2 0x38
+#define DEINTERLACE_TRD_PRECHROMA 0x3c
+#define DEINTERLACE_LINE_STRIDE0 0x40
+#define DEINTERLACE_LINE_STRIDE1 0x44
+#define DEINTERLACE_LINE_STRIDE2 0x48
+
+#define DEINTERLACE_IN_FMT 0x4c
+#define DEINTERLACE_IN_FMT_PS(v) ((v) & 3)
+#define DEINTERLACE_IN_FMT_FMT(v) (((v) & 7) << 4)
+#define DEINTERLACE_IN_FMT_MOD(v) (((v) & 7) << 8)
+
+#define DEINTERLACE_WB_ADDR0 0x50
+#define DEINTERLACE_WB_ADDR1 0x54
+#define DEINTERLACE_WB_ADDR2 0x58
+
+#define DEINTERLACE_OUT_FMT 0x5c
+#define DEINTERLACE_OUT_FMT_FMT(v) ((v) & 0xf)
+#define DEINTERLACE_OUT_FMT_PS(v) (((v) & 3) << 5)
+
+#define DEINTERLACE_INT_ENABLE 0x60
+#define DEINTERLACE_INT_ENABLE_WB_EN BIT(7)
+
+#define DEINTERLACE_INT_STATUS 0x64
+#define DEINTERLACE_INT_STATUS_WRITEBACK BIT(7)
+
+#define DEINTERLACE_STATUS 0x68
+#define DEINTERLACE_STATUS_COEF_STATUS BIT(11)
+#define DEINTERLACE_STATUS_WB_ERROR BIT(12)
+
+#define DEINTERLACE_CSC_COEF 0x70 /* 12 registers */
+
+#define DEINTERLACE_CTRL 0xa0
+#define DEINTERLACE_CTRL_EN BIT(0)
+#define DEINTERLACE_CTRL_FLAG_OUT_EN BIT(8)
+#define DEINTERLACE_CTRL_MODE_PASSTROUGH (0 << 16)
+#define DEINTERLACE_CTRL_MODE_WEAVE (1 << 16)
+#define DEINTERLACE_CTRL_MODE_BOB (2 << 16)
+#define DEINTERLACE_CTRL_MODE_MIXED (3 << 16)
+#define DEINTERLACE_CTRL_DIAG_INTP_EN BIT(24)
+#define DEINTERLACE_CTRL_TEMP_DIFF_EN BIT(25)
+
+#define DEINTERLACE_DIAG_INTP 0xa4
+#define DEINTERLACE_DIAG_INTP_TH0(v) ((v) & 0x7f)
+#define DEINTERLACE_DIAG_INTP_TH0_MSK (0x7f)
+#define DEINTERLACE_DIAG_INTP_TH1(v) (((v) & 0x7f) << 8)
+#define DEINTERLACE_DIAG_INTP_TH1_MSK (0x7f << 8)
+#define DEINTERLACE_DIAG_INTP_TH3(v) (((v) & 0xff) << 24)
+#define DEINTERLACE_DIAG_INTP_TH3_MSK (0xff << 24)
+
+#define DEINTERLACE_TEMP_DIFF 0xa8
+#define DEINTERLACE_TEMP_DIFF_SAD_CENTRAL_TH(v) ((v) & 0x7f)
+#define DEINTERLACE_TEMP_DIFF_SAD_CENTRAL_TH_MSK (0x7f)
+#define DEINTERLACE_TEMP_DIFF_AMBIGUITY_TH(v) (((v) & 0x7f) << 8)
+#define DEINTERLACE_TEMP_DIFF_AMBIGUITY_TH_MSK (0x7f << 8)
+#define DEINTERLACE_TEMP_DIFF_DIRECT_DITHER_TH(v) (((v) & 0x7ff) << 16)
+#define DEINTERLACE_TEMP_DIFF_DIRECT_DITHER_TH_MSK (0x7ff << 16)
+
+#define DEINTERLACE_LUMA_TH 0xac
+#define DEINTERLACE_LUMA_TH_MIN_LUMA(v) ((v) & 0xff)
+#define DEINTERLACE_LUMA_TH_MIN_LUMA_MSK (0xff)
+#define DEINTERLACE_LUMA_TH_MAX_LUMA(v) (((v) & 0xff) << 8)
+#define DEINTERLACE_LUMA_TH_MAX_LUMA_MSK (0xff << 8)
+#define DEINTERLACE_LUMA_TH_AVG_LUMA_SHIFT(v) (((v) & 0xff) << 16)
+#define DEINTERLACE_LUMA_TH_AVG_LUMA_SHIFT_MSK (0xff << 16)
+#define DEINTERLACE_LUMA_TH_PIXEL_STATIC(v) (((v) & 3) << 24)
+#define DEINTERLACE_LUMA_TH_PIXEL_STATIC_MSK (3 << 24)
+
+#define DEINTERLACE_SPAT_COMP 0xb0
+#define DEINTERLACE_SPAT_COMP_TH2(v) ((v) & 0xff)
+#define DEINTERLACE_SPAT_COMP_TH2_MSK (0xff)
+#define DEINTERLACE_SPAT_COMP_TH3(v) (((v) & 0xff) << 16)
+#define DEINTERLACE_SPAT_COMP_TH3_MSK (0xff << 16)
+
+#define DEINTERLACE_CHROMA_DIFF 0xb4
+#define DEINTERLACE_CHROMA_DIFF_TH(v) ((v) & 0xff)
+#define DEINTERLACE_CHROMA_DIFF_TH_MSK (0xff)
+#define DEINTERLACE_CHROMA_DIFF_LUMA(v) (((v) & 0x3f) << 16)
+#define DEINTERLACE_CHROMA_DIFF_LUMA_MSK (0x3f << 16)
+#define DEINTERLACE_CHROMA_DIFF_CHROMA(v) (((v) & 0x3f) << 24)
+#define DEINTERLACE_CHROMA_DIFF_CHROMA_MSK (0x3f << 24)
+
+#define DEINTERLACE_PRELUMA 0xb8
+#define DEINTERLACE_PRECHROMA 0xbc
+#define DEINTERLACE_TILE_FLAG0 0xc0
+#define DEINTERLACE_TILE_FLAG1 0xc4
+#define DEINTERLACE_FLAG_LINE_STRIDE 0xc8
+#define DEINTERLACE_FLAG_SEQ 0xcc
+
+#define DEINTERLACE_WB_LINE_STRIDE_CTRL 0xd0
+#define DEINTERLACE_WB_LINE_STRIDE_CTRL_EN BIT(0)
+
+#define DEINTERLACE_WB_LINE_STRIDE0 0xd4
+#define DEINTERLACE_WB_LINE_STRIDE1 0xd8
+#define DEINTERLACE_WB_LINE_STRIDE2 0xdc
+#define DEINTERLACE_TRD_CTRL 0xe0
+#define DEINTERLACE_TRD_BUF_ADDR0 0xe4
+#define DEINTERLACE_TRD_BUF_ADDR1 0xe8
+#define DEINTERLACE_TRD_BUF_ADDR2 0xec
+#define DEINTERLACE_TRD_TB_OFF0 0xf0
+#define DEINTERLACE_TRD_TB_OFF1 0xf4
+#define DEINTERLACE_TRD_TB_OFF2 0xf8
+#define DEINTERLACE_TRD_WB_STRIDE 0xfc
+#define DEINTERLACE_CH0_IN_SIZE 0x100
+#define DEINTERLACE_CH0_OUT_SIZE 0x104
+#define DEINTERLACE_CH0_HORZ_FACT 0x108
+#define DEINTERLACE_CH0_VERT_FACT 0x10c
+#define DEINTERLACE_CH0_HORZ_PHASE 0x110
+#define DEINTERLACE_CH0_VERT_PHASE0 0x114
+#define DEINTERLACE_CH0_VERT_PHASE1 0x118
+#define DEINTERLACE_CH0_HORZ_TAP0 0x120
+#define DEINTERLACE_CH0_HORZ_TAP1 0x124
+#define DEINTERLACE_CH0_VERT_TAP 0x128
+#define DEINTERLACE_CH1_IN_SIZE 0x200
+#define DEINTERLACE_CH1_OUT_SIZE 0x204
+#define DEINTERLACE_CH1_HORZ_FACT 0x208
+#define DEINTERLACE_CH1_VERT_FACT 0x20c
+#define DEINTERLACE_CH1_HORZ_PHASE 0x210
+#define DEINTERLACE_CH1_VERT_PHASE0 0x214
+#define DEINTERLACE_CH1_VERT_PHASE1 0x218
+#define DEINTERLACE_CH1_HORZ_TAP0 0x220
+#define DEINTERLACE_CH1_HORZ_TAP1 0x224
+#define DEINTERLACE_CH1_VERT_TAP 0x228
+#define DEINTERLACE_CH0_HORZ_COEF0 0x400 /* 32 registers */
+#define DEINTERLACE_CH0_HORZ_COEF1 0x480 /* 32 registers */
+#define DEINTERLACE_CH0_VERT_COEF 0x500 /* 32 registers */
+#define DEINTERLACE_CH1_HORZ_COEF0 0x600 /* 32 registers */
+#define DEINTERLACE_CH1_HORZ_COEF1 0x680 /* 32 registers */
+#define DEINTERLACE_CH1_VERT_COEF 0x700 /* 32 registers */
+#define DEINTERLACE_CH3_HORZ_COEF0 0x800 /* 32 registers */
+#define DEINTERLACE_CH3_HORZ_COEF1 0x880 /* 32 registers */
+#define DEINTERLACE_CH3_VERT_COEF 0x900 /* 32 registers */
+
+#define DEINTERLACE_MIN_WIDTH 2U
+#define DEINTERLACE_MIN_HEIGHT 2U
+#define DEINTERLACE_MAX_WIDTH 2048U
+#define DEINTERLACE_MAX_HEIGHT 1100U
+
+#define DEINTERLACE_MODE_UV_COMBINED 2
+
+#define DEINTERLACE_IN_FMT_YUV420 2
+
+#define DEINTERLACE_OUT_FMT_YUV420SP 13
+
+#define DEINTERLACE_PS_UVUV 0
+#define DEINTERLACE_PS_VUVU 1
+
+#define DEINTERLACE_IDENTITY_COEF 0x4000
+
+#define DEINTERLACE_SIZE(w, h) (((h) - 1) << 16 | ((w) - 1))
+
+struct deinterlace_ctx {
+ struct v4l2_fh fh;
+ struct deinterlace_dev *dev;
+
+ struct v4l2_pix_format src_fmt;
+ struct v4l2_pix_format dst_fmt;
+
+ void *flag1_buf;
+ dma_addr_t flag1_buf_dma;
+
+ void *flag2_buf;
+ dma_addr_t flag2_buf_dma;
+
+ struct vb2_v4l2_buffer *prev;
+
+ unsigned int first_field;
+ unsigned int field;
+
+ int aborting;
+};
+
+struct deinterlace_dev {
+ struct v4l2_device v4l2_dev;
+ struct video_device vfd;
+ struct device *dev;
+ struct v4l2_m2m_dev *m2m_dev;
+
+ /* Device file mutex */
+ struct mutex dev_mutex;
+
+ void __iomem *base;
+ struct regmap *regmap;
+
+ struct clk *bus_clk;
+ struct clk *mod_clk;
+ struct clk *ram_clk;
+
+ struct reset_control *rstc;
+};
+
+#endif
--
2.23.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* Re: [PATCH 0/4] Fix UART DMA freezes for iMX6
From: Fabio Estevam @ 2019-09-12 18:23 UTC (permalink / raw)
To: Philipp Puschmann, Robin Gong, Fugang Duan
Cc: linux-serial, Greg Kroah-Hartman, Sascha Hauer, linux-kernel,
Vinod, NXP Linux Team, Sascha Hauer, Jiri Slaby, dmaengine,
Dan Williams, Shawn Guo,
moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
In-Reply-To: <20190911144943.21554-1-philipp.puschmann@emlix.com>
Hi Philipp,
Thanks for submitting these fixes.
On Wed, Sep 11, 2019 at 11:50 AM Philipp Puschmann
<philipp.puschmann@emlix.com> wrote:
>
> For some years and since many kernel versions there are reports that
> RX UART DMA channel stops working at one point. So far the usual workaround was
> to disable RX DMA. This patches try to fix the underlying problem.
>
> When a running sdma script does not find any usable destination buffer to put
> its data into it just leads to stopping the channel being scheduled again. As
> solution we we manually retrigger the sdma script for this channel and by this
> dissolve the freeze.
>
> While this seems to work fine so far a further patch in this series increases
> the number of RX DMA periods for UART to reduce use cases running into such
> a situation.
>
> This patch series was tested with the current kernel and backported to
> kernel 4.15 with a special use case using a WL1837MOD via UART and provoking
> the hanging of UART RX DMA within seconds after starting a test application.
> It resulted in well known
> "Bluetooth: hci0: command 0x0408 tx timeout"
> errors and complete stop of UART data reception. Our Bluetooth traffic consists
> of many independent small packets, mostly only a few bytes, causing high usage
> of periods.
>
>
> Philipp Puschmann (4):
> dmaengine: imx-sdma: fix buffer ownership
> dmaengine: imx-sdma: fix dma freezes
> serial: imx: adapt rx buffer and dma periods
> dmaengine: imx-sdma: drop redundant variable
I have some suggestions:
1. Please split this in two series: one for dmaengine and other one for serial
2. Please add Fixes tag when appropriate, so that the fixes can be
backported to stable kernels.
3. Please Cc Robin and Andy
Thanks
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH V2 05/13] clk: bcm2835: Add BCM2711_CLOCK_EMMC2 support
From: Eric Anholt @ 2019-09-12 18:52 UTC (permalink / raw)
To: Matthias Brugger, Stefan Wahren, Florian Fainelli, Ray Jui,
Scott Branden, Wolfram Sang, Rob Herring, Mark Rutland,
Michael Turquette, Stephen Boyd
Cc: devicetree, bcm-kernel-feedback-list, linux-i2c, linux-clk,
linux-arm-kernel, linux-rpi-kernel
In-Reply-To: <d89bbc4b-b6bc-0d4e-86d1-6be11876ce00@gmail.com>
[-- Attachment #1.1: Type: text/plain, Size: 2565 bytes --]
Matthias Brugger <matthias.bgg@gmail.com> writes:
> On 13/08/2019 18:20, Stefan Wahren wrote:
>> The new BCM2711 supports an additional clock for the emmc2 block.
>> So add a new compatible and register this clock only for BCM2711.
>>
>> Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
>> Reviewed-by: Matthias Brugger <mbrugger@suse.com>
>> Acked-by: Eric Anholt <eric@anholt.net>
>> ---
>> drivers/clk/bcm/clk-bcm2835.c | 20 +++++++++++++++++++-
>> 1 file changed, 19 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
>> index 21cd952..fdf672a 100644
>> --- a/drivers/clk/bcm/clk-bcm2835.c
>> +++ b/drivers/clk/bcm/clk-bcm2835.c
>> @@ -114,6 +114,8 @@
>> #define CM_AVEODIV 0x1bc
>> #define CM_EMMCCTL 0x1c0
>> #define CM_EMMCDIV 0x1c4
>> +#define CM_EMMC2CTL 0x1d0
>> +#define CM_EMMC2DIV 0x1d4
>>
>> /* General bits for the CM_*CTL regs */
>> # define CM_ENABLE BIT(4)
>> @@ -290,7 +292,8 @@
>> #define BCM2835_MAX_FB_RATE 1750000000u
>>
>> #define SOC_BCM2835 BIT(0)
>> -#define SOC_ALL (SOC_BCM2835)
>> +#define SOC_BCM2711 BIT(1)
>> +#define SOC_ALL (SOC_BCM2835 | SOC_BCM2711)
>>
>> /*
>> * Names of clocks used within the driver that need to be replaced
>> @@ -2003,6 +2006,16 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
>> .frac_bits = 8,
>> .tcnt_mux = 39),
>>
>> + /* EMMC2 clock (only available for BCM2711) */
>> + [BCM2711_CLOCK_EMMC2] = REGISTER_PER_CLK(
>> + SOC_BCM2711,
>> + .name = "emmc2",
>> + .ctl_reg = CM_EMMC2CTL,
>> + .div_reg = CM_EMMC2DIV,
>> + .int_bits = 4,
>> + .frac_bits = 8,
>> + .tcnt_mux = 42),
>> +
>> /* General purpose (GPIO) clocks */
>> [BCM2835_CLOCK_GP0] = REGISTER_PER_CLK(
>> SOC_ALL,
>> @@ -2238,8 +2251,13 @@ static const struct cprman_plat_data cprman_bcm2835_plat_data = {
>> .soc = SOC_BCM2835,
>> };
>>
>> +static const struct cprman_plat_data cprman_bcm2711_plat_data = {
>> + .soc = SOC_BCM2711,
>> +};
>> +
>> static const struct of_device_id bcm2835_clk_of_match[] = {
>> { .compatible = "brcm,bcm2835-cprman", .data = &cprman_bcm2835_plat_data },
>> + { .compatible = "brcm,bcm2711-cprman", .data = &cprman_bcm2711_plat_data },
>
> Because the RPi4 FW uses bcm2838-cprman as compatible, we will need to add this
> here as well.
Upstream has not committed to backwards compat with Pi's firmware. That
makes the ABI requirement we get held to for upstream's DT absurd, but
that's the state of things.
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]
[-- Attachment #2: Type: text/plain, Size: 176 bytes --]
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 1/3] OMAP3: PM: Set/clear T2 bit for Smartreflex on TWL
From: Adam Ford @ 2019-09-12 18:59 UTC (permalink / raw)
To: André Roth
Cc: Nishanth Menon, Kevin Hilman, Tony Lindgren, H. Nikolaus Schaller,
Shweta Gulati, Thara Gopinath, Linux-OMAP, arm-soc
In-Reply-To: <20190801012823.28730-2-neolynx@gmail.com>
On Wed, Jul 31, 2019 at 8:29 PM André Roth <neolynx@gmail.com> wrote:
>
> From: Thara Gopinath <thara@ti.com>
>
> Voltage control on TWL can be done using VMODE/I2C1/I2C_SR.
> Since almost all platforms use I2C_SR on omap3, omap3_twl_init by
> default expects that OMAP's I2C_SR is plugged in to TWL's I2C
> and calls omap3_twl_set_sr_bit. On platforms where I2C_SR is not connected,
> the board files are expected to call omap3_twl_set_sr_bit(false) to
> ensure that I2C_SR path is not set for voltage control and prevent
> the default behavior of omap3_twl_init.
>
> Signed-off-by: Nishanth Menon <nm@ti.com>
> Signed-off-by: Thara Gopinath <thara@ti.com>
> Signed-off-by: Shweta Gulati <shweta.gulati@ti.com>
> Cc: linux-arm-kernel@lists.infradead.org
> Signed-off-by: Kevin Hilman <khilman@ti.com>
Tony,
Is there a status update on this series? It's been several months,
and I haven't seen any feedback on it, nor does it appear to be in any
of your branches that I can see.
adam
> ---
> arch/arm/mach-omap2/omap_twl.c | 60 ++++++++++++++++++++++++++++++++++
> 1 file changed, 60 insertions(+)
>
> diff --git a/arch/arm/mach-omap2/omap_twl.c b/arch/arm/mach-omap2/omap_twl.c
> index 6787f1e72c6b..1dae906128c2 100644
> --- a/arch/arm/mach-omap2/omap_twl.c
> +++ b/arch/arm/mach-omap2/omap_twl.c
> @@ -43,8 +43,15 @@
>
> static bool is_offset_valid;
> static u8 smps_offset;
> +/*
> + * Flag to ensure Smartreflex bit in TWL
> + * being cleared in board file is not overwritten.
> + */
> +static bool __initdata twl_sr_enable_autoinit;
>
> +#define TWL4030_DCDC_GLOBAL_CFG 0x06
> #define REG_SMPS_OFFSET 0xE0
> +#define SMARTREFLEX_ENABLE BIT(3)
>
> static unsigned long twl4030_vsel_to_uv(const u8 vsel)
> {
> @@ -241,6 +248,18 @@ int __init omap3_twl_init(void)
> if (!cpu_is_omap34xx())
> return -ENODEV;
>
> + /*
> + * The smartreflex bit on twl4030 specifies if the setting of voltage
> + * is done over the I2C_SR path. Since this setting is independent of
> + * the actual usage of smartreflex AVS module, we enable TWL SR bit
> + * by default irrespective of whether smartreflex AVS module is enabled
> + * on the OMAP side or not. This is because without this bit enabled,
> + * the voltage scaling through vp forceupdate/bypass mechanism of
> + * voltage scaling will not function on TWL over I2C_SR.
> + */
> + if (!twl_sr_enable_autoinit)
> + omap3_twl_set_sr_bit(true);
> +
> voltdm = voltdm_lookup("mpu_iva");
> omap_voltage_register_pmic(voltdm, &omap3_mpu_pmic);
>
> @@ -249,3 +268,44 @@ int __init omap3_twl_init(void)
>
> return 0;
> }
> +
> +/**
> + * omap3_twl_set_sr_bit() - Set/Clear SR bit on TWL
> + * @enable: enable SR mode in twl or not
> + *
> + * If 'enable' is true, enables Smartreflex bit on TWL 4030 to make sure
> + * voltage scaling through OMAP SR works. Else, the smartreflex bit
> + * on twl4030 is cleared as there are platforms which use OMAP3 and T2 but
> + * use Synchronized Scaling Hardware Strategy (ENABLE_VMODE=1) and Direct
> + * Strategy Software Scaling Mode (ENABLE_VMODE=0), for setting the voltages,
> + * in those scenarios this bit is to be cleared (enable = false).
> + *
> + * Returns 0 on sucess, error is returned if I2C read/write fails.
> + */
> +int __init omap3_twl_set_sr_bit(bool enable)
> +{
> + u8 temp;
> + int ret;
> + if (twl_sr_enable_autoinit)
> + pr_warning("%s: unexpected multiple calls\n", __func__);
> +
> + ret = twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &temp,
> + TWL4030_DCDC_GLOBAL_CFG);
> + if (ret)
> + goto err;
> +
> + if (enable)
> + temp |= SMARTREFLEX_ENABLE;
> + else
> + temp &= ~SMARTREFLEX_ENABLE;
> +
> + ret = twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, temp,
> + TWL4030_DCDC_GLOBAL_CFG);
> + if (!ret) {
> + twl_sr_enable_autoinit = true;
> + return 0;
> + }
> +err:
> + pr_err("%s: Error access to TWL4030 (%d)\n", __func__, ret);
> + return ret;
> +}
> --
> 2.17.1
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v5 0/4] Raspberry Pi 4 DMA addressing support
From: Stefan Wahren @ 2019-09-12 19:32 UTC (permalink / raw)
To: Matthias Brugger, Matthias Brugger, Stefan Wahren,
catalin.marinas, marc.zyngier, robh+dt, linux-mm,
linux-arm-kernel, linux-riscv, hch, Nicolas Saenz Julienne
Cc: f.fainelli, robin.murphy, linux-kernel, linux-rpi-kernel, phill,
will, m.szyprowski
In-Reply-To: <09f82f88-a13a-b441-b723-7bb061a2f1e3@gmail.com>
Am 12.09.19 um 19:18 schrieb Matthias Brugger:
>
> On 10/09/2019 11:27, Matthias Brugger wrote:
>>
>> On 09/09/2019 21:33, Stefan Wahren wrote:
>>> Hi Nicolas,
>>>
>>> Am 09.09.19 um 11:58 schrieb Nicolas Saenz Julienne:
>>>> Hi all,
>>>> this series attempts to address some issues we found while bringing up
>>>> the new Raspberry Pi 4 in arm64 and it's intended to serve as a follow
>>>> up of these discussions:
>>>> v4: https://lkml.org/lkml/2019/9/6/352
>>>> v3: https://lkml.org/lkml/2019/9/2/589
>>>> v2: https://lkml.org/lkml/2019/8/20/767
>>>> v1: https://lkml.org/lkml/2019/7/31/922
>>>> RFC: https://lkml.org/lkml/2019/7/17/476
>>>>
>>>> The new Raspberry Pi 4 has up to 4GB of memory but most peripherals can
>>>> only address the first GB: their DMA address range is
>>>> 0xc0000000-0xfc000000 which is aliased to the first GB of physical
>>>> memory 0x00000000-0x3c000000. Note that only some peripherals have these
>>>> limitations: the PCIe, V3D, GENET, and 40-bit DMA channels have a wider
>>>> view of the address space by virtue of being hooked up trough a second
>>>> interconnect.
>>>>
>>>> Part of this is solved on arm32 by setting up the machine specific
>>>> '.dma_zone_size = SZ_1G', which takes care of reserving the coherent
>>>> memory area at the right spot. That said no buffer bouncing (needed for
>>>> dma streaming) is available at the moment, but that's a story for
>>>> another series.
>>>>
>>>> Unfortunately there is no such thing as 'dma_zone_size' in arm64. Only
>>>> ZONE_DMA32 is created which is interpreted by dma-direct and the arm64
>>>> arch code as if all peripherals where be able to address the first 4GB
>>>> of memory.
>>>>
>>>> In the light of this, the series implements the following changes:
>>>>
>>>> - Create both DMA zones in arm64, ZONE_DMA will contain the first 1G
>>>> area and ZONE_DMA32 the rest of the 32 bit addressable memory. So far
>>>> the RPi4 is the only arm64 device with such DMA addressing limitations
>>>> so this hardcoded solution was deemed preferable.
>>>>
>>>> - Properly set ARCH_ZONE_DMA_BITS.
>>>>
>>>> - Reserve the CMA area in a place suitable for all peripherals.
>>>>
>>>> This series has been tested on multiple devices both by checking the
>>>> zones setup matches the expectations and by double-checking physical
>>>> addresses on pages allocated on the three relevant areas GFP_DMA,
>>>> GFP_DMA32, GFP_KERNEL:
>>>>
>>>> - On an RPi4 with variations on the ram memory size. But also forcing
>>>> the situation where all three memory zones are nonempty by setting a 3G
>>>> ZONE_DMA32 ceiling on a 4G setup. Both with and without NUMA support.
>>>>
>>> i like to test this series on Raspberry Pi 4 and i have some questions
>>> to get arm64 running:
>>>
>>> Do you use U-Boot? Which tree?
>> If you want to use U-Boot, try v2019.10-rc4, it should have everything you need
>> to boot your kernel.
>>
> Ok, here is a thing. In the linux kernel we now use bcm2711 as SoC name, but the
> RPi4 devicetree provided by the FW uses mostly bcm2838.
Do you mean the DTB provided at runtime?
You mean the merged U-Boot changes, doesn't work with my Raspberry Pi
series?
> U-Boot in its default
> config uses the devicetree provided by the FW, mostly because this way you don't
> have to do anything to find out how many RAM you really have. Secondly because
> this will allow us, in the near future, to have one U-boot binary for both RPi3
> and RPi4 (and as a side effect one binary for RPi1 and RPi2).
>
> Anyway, I found at least, that the following compatibles need to be added:
>
> "brcm,bcm2838-cprman"
> "brcm,bcm2838-gpio"
>
> Without at least the cprman driver update, you won't see anything.
>
> "brcm,bcm2838-rng200" is also a candidate.
>
> I also suppose we will need to add "brcm,bcm2838" to
> arch/arm/mach-bcm/bcm2711.c, but I haven't verified this.
How about changing this in the downstream kernel? Which is much easier.
>
> Regards,
> Matthias
>
>> Regards,
>> Matthias
>>
>>> Are there any config.txt tweaks necessary?
>>>
>>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel@lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH 3/3] ARM: dts: at91: sama5d2: set the sdmmc gclk frequency
From: Ludovic Desroches @ 2019-09-12 20:09 UTC (permalink / raw)
To: linux-arm-kernel, devicetree, linux-mmc
Cc: mark.rutland, ulf.hansson, linux-kernel, ludovic.desroches,
robh+dt, adrian.hunter, claudiu.beznea
In-Reply-To: <20190912200908.31318-1-ludovic.desroches@microchip.com>
Set the frequency of the generated clock used by sdmmc devices in order
to not rely on the configuration done by previous components.
Signed-off-by: Ludovic Desroches <ludovic.desroches@microchip.com>
---
arch/arm/boot/dts/sama5d2.dtsi | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi
index 2e2c1a7b1d1d..8d79ff75e3cd 100644
--- a/arch/arm/boot/dts/sama5d2.dtsi
+++ b/arch/arm/boot/dts/sama5d2.dtsi
@@ -300,6 +300,8 @@
interrupts = <31 IRQ_TYPE_LEVEL_HIGH 0>;
clocks = <&pmc PMC_TYPE_PERIPHERAL 31>, <&pmc PMC_TYPE_GCK 31>, <&pmc PMC_TYPE_CORE PMC_MAIN>;
clock-names = "hclock", "multclk", "baseclk";
+ assigned-clocks = <&pmc PMC_TYPE_GCK 31>;
+ assigned-clock-rates = <480000000>;
status = "disabled";
};
@@ -309,6 +311,8 @@
interrupts = <32 IRQ_TYPE_LEVEL_HIGH 0>;
clocks = <&pmc PMC_TYPE_PERIPHERAL 32>, <&pmc PMC_TYPE_GCK 32>, <&pmc PMC_TYPE_CORE PMC_MAIN>;
clock-names = "hclock", "multclk", "baseclk";
+ assigned-clocks = <&pmc PMC_TYPE_GCK 32>;
+ assigned-clock-rates = <480000000>;
status = "disabled";
};
--
2.23.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 1/3] dt-bindings: sdhci-of-at91: new compatible string and update properties
From: Ludovic Desroches @ 2019-09-12 20:09 UTC (permalink / raw)
To: linux-arm-kernel, devicetree, linux-mmc
Cc: mark.rutland, ulf.hansson, linux-kernel, ludovic.desroches,
robh+dt, adrian.hunter, claudiu.beznea
There is a new compatible string for the SAM9X60 sdhci device. It involves
an update of the properties about the clocks stuff.
Signed-off-by: Ludovic Desroches <ludovic.desroches@microchip.com>
---
.../devicetree/bindings/mmc/sdhci-atmel.txt | 25 ++++++++++++++++---
1 file changed, 22 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-atmel.txt b/Documentation/devicetree/bindings/mmc/sdhci-atmel.txt
index 1b662d7171a0..364ceea330b6 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-atmel.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-atmel.txt
@@ -5,12 +5,19 @@ Documentation/devicetree/bindings/mmc/mmc.txt and the properties used by the
sdhci-of-at91 driver.
Required properties:
-- compatible: Must be "atmel,sama5d2-sdhci".
+- compatible: Must be "atmel,sama5d2-sdhci" or "microchip,sam9x60-sdhci".
- clocks: Phandlers to the clocks.
-- clock-names: Must be "hclock", "multclk", "baseclk";
+- clock-names: Must be "hclock", "multclk", "baseclk" for
+ "atmel,sama5d2-sdhci".
+ Must be "hclock", "multclk" for "microchip,sam9x60-sdhci".
+Optional properties:
+- assigned-clocks: The same with "multclk".
+- assigned-clock-rates The rate of "multclk" in order to not rely on the
+ gck configuration set by previous components.
-Example:
+
+Examples:
sdmmc0: sdio-host@a0000000 {
compatible = "atmel,sama5d2-sdhci";
@@ -18,4 +25,16 @@ sdmmc0: sdio-host@a0000000 {
interrupts = <31 IRQ_TYPE_LEVEL_HIGH 0>;
clocks = <&sdmmc0_hclk>, <&sdmmc0_gclk>, <&main>;
clock-names = "hclock", "multclk", "baseclk";
+ assigned-clocks = <&sdmmc0_gclk>;
+ assigned-clock-rates = <480000000>;
+};
+
+sdmmc0: sdio-host@80000000 {
+ compatible = "microchip,sam9x60-sdhci";
+ reg = <0x80000000 0x300>;
+ interrupts = <12 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&pmc PMC_TYPE_PERIPHERAL 12>, <&pmc PMC_TYPE_GCK 12>;
+ clock-names = "hclock", "multclk";
+ assigned-clocks = <&pmc PMC_TYPE_GCK 12>;
+ assigned-clock-rates = <100000000>;
};
--
2.23.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 2/3] mmc: sdhci-of-at91: rework clocks management to support SAM9x60 device
From: Ludovic Desroches @ 2019-09-12 20:09 UTC (permalink / raw)
To: linux-arm-kernel, devicetree, linux-mmc
Cc: mark.rutland, ulf.hansson, linux-kernel, ludovic.desroches,
robh+dt, adrian.hunter, claudiu.beznea
In-Reply-To: <20190912200908.31318-1-ludovic.desroches@microchip.com>
In the SAM9x60 SoC, there are only two clocks instead of three for the
SDHCI device. The base clk is no longer provided, it is generated
internally from the mult clk.
The values of the base clk and mul in the capabilities registers may not
reflect the reality as the mult clk is a programmable clock which can take
several rates. As we can't trust those values, take them from the clock
tree and update the capabilities according to.
As we can have the same pitfall, in some cases, with the SAMA5D2 Soc,
stop relying on capabilities too.
Signed-off-by: Ludovic Desroches <ludovic.desroches@microchip.com>
---
drivers/mmc/host/sdhci-of-at91.c | 104 +++++++++++++++++--------------
1 file changed, 57 insertions(+), 47 deletions(-)
diff --git a/drivers/mmc/host/sdhci-of-at91.c b/drivers/mmc/host/sdhci-of-at91.c
index e7d1920729fb..a9c126f14d85 100644
--- a/drivers/mmc/host/sdhci-of-at91.c
+++ b/drivers/mmc/host/sdhci-of-at91.c
@@ -30,7 +30,14 @@
#define SDHCI_AT91_PRESET_COMMON_CONF 0x400 /* drv type B, programmable clock mode */
+struct sdhci_at91_soc_data {
+ const struct sdhci_pltfm_data *pdata;
+ bool baseclk_is_generated_internally;
+ unsigned int divider_for_baseclk;
+};
+
struct sdhci_at91_priv {
+ const struct sdhci_at91_soc_data *soc_data;
struct clk *hclock;
struct clk *gck;
struct clk *mainck;
@@ -130,12 +137,24 @@ static const struct sdhci_ops sdhci_at91_sama5d2_ops = {
.set_power = sdhci_at91_set_power,
};
-static const struct sdhci_pltfm_data soc_data_sama5d2 = {
+static const struct sdhci_pltfm_data sdhci_sama5d2_pdata = {
.ops = &sdhci_at91_sama5d2_ops,
};
+static const struct sdhci_at91_soc_data soc_data_sama5d2 = {
+ .pdata = &sdhci_sama5d2_pdata,
+ .baseclk_is_generated_internally = false,
+};
+
+static const struct sdhci_at91_soc_data soc_data_sam9x60 = {
+ .pdata = &sdhci_sama5d2_pdata,
+ .baseclk_is_generated_internally = true,
+ .divider_for_baseclk = 2,
+};
+
static const struct of_device_id sdhci_at91_dt_match[] = {
{ .compatible = "atmel,sama5d2-sdhci", .data = &soc_data_sama5d2 },
+ { .compatible = "microchip,sam9x60-sdhci", .data = &soc_data_sam9x60 },
{}
};
MODULE_DEVICE_TABLE(of, sdhci_at91_dt_match);
@@ -145,50 +164,36 @@ static int sdhci_at91_set_clks_presets(struct device *dev)
struct sdhci_host *host = dev_get_drvdata(dev);
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_at91_priv *priv = sdhci_pltfm_priv(pltfm_host);
- int ret;
unsigned int caps0, caps1;
unsigned int clk_base, clk_mul;
- unsigned int gck_rate, real_gck_rate;
+ unsigned int gck_rate, clk_base_rate;
unsigned int preset_div;
- /*
- * The mult clock is provided by as a generated clock by the PMC
- * controller. In order to set the rate of gck, we have to get the
- * base clock rate and the clock mult from capabilities.
- */
clk_prepare_enable(priv->hclock);
caps0 = readl(host->ioaddr + SDHCI_CAPABILITIES);
caps1 = readl(host->ioaddr + SDHCI_CAPABILITIES_1);
- clk_base = (caps0 & SDHCI_CLOCK_V3_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT;
- clk_mul = (caps1 & SDHCI_CLOCK_MUL_MASK) >> SDHCI_CLOCK_MUL_SHIFT;
- gck_rate = clk_base * 1000000 * (clk_mul + 1);
- ret = clk_set_rate(priv->gck, gck_rate);
- if (ret < 0) {
- dev_err(dev, "failed to set gck");
- clk_disable_unprepare(priv->hclock);
- return ret;
- }
- /*
- * We need to check if we have the requested rate for gck because in
- * some cases this rate could be not supported. If it happens, the rate
- * is the closest one gck can provide. We have to update the value
- * of clk mul.
- */
- real_gck_rate = clk_get_rate(priv->gck);
- if (real_gck_rate != gck_rate) {
- clk_mul = real_gck_rate / (clk_base * 1000000) - 1;
- caps1 &= (~SDHCI_CLOCK_MUL_MASK);
- caps1 |= ((clk_mul << SDHCI_CLOCK_MUL_SHIFT) &
- SDHCI_CLOCK_MUL_MASK);
- /* Set capabilities in r/w mode. */
- writel(SDMMC_CACR_KEY | SDMMC_CACR_CAPWREN,
- host->ioaddr + SDMMC_CACR);
- writel(caps1, host->ioaddr + SDHCI_CAPABILITIES_1);
- /* Set capabilities in ro mode. */
- writel(0, host->ioaddr + SDMMC_CACR);
- dev_info(dev, "update clk mul to %u as gck rate is %u Hz\n",
- clk_mul, real_gck_rate);
- }
+
+ gck_rate = clk_get_rate(priv->gck);
+ if (priv->soc_data->baseclk_is_generated_internally)
+ clk_base_rate = gck_rate / priv->soc_data->divider_for_baseclk;
+ else
+ clk_base_rate = clk_get_rate(priv->mainck);
+
+ clk_base = clk_base_rate / 1000000;
+ clk_mul = gck_rate / clk_base_rate - 1;
+
+ caps0 &= (~SDHCI_CLOCK_V3_BASE_MASK);
+ caps0 |= ((clk_base << SDHCI_CLOCK_BASE_SHIFT) & SDHCI_CLOCK_V3_BASE_MASK);
+ caps1 &= (~SDHCI_CLOCK_MUL_MASK);
+ caps1 |= ((clk_mul << SDHCI_CLOCK_MUL_SHIFT) & SDHCI_CLOCK_MUL_MASK);
+ /* Set capabilities in r/w mode. */
+ writel(SDMMC_CACR_KEY | SDMMC_CACR_CAPWREN, host->ioaddr + SDMMC_CACR);
+ writel(caps1, host->ioaddr + SDHCI_CAPABILITIES_1);
+ /* Set capabilities in ro mode. */
+ writel(0, host->ioaddr + SDMMC_CACR);
+
+ dev_info(dev, "update clk mul to %u as gck rate is %u Hz and clk base is %u Hz\n",
+ clk_mul, gck_rate, clk_base_rate);
/*
* We have to set preset values because it depends on the clk_mul
@@ -196,19 +201,19 @@ static int sdhci_at91_set_clks_presets(struct device *dev)
* maximum sd clock value is 120 MHz instead of 208 MHz. For that
* reason, we need to use presets to support SDR104.
*/
- preset_div = DIV_ROUND_UP(real_gck_rate, 24000000) - 1;
+ preset_div = DIV_ROUND_UP(gck_rate, 24000000) - 1;
writew(SDHCI_AT91_PRESET_COMMON_CONF | preset_div,
host->ioaddr + SDHCI_PRESET_FOR_SDR12);
- preset_div = DIV_ROUND_UP(real_gck_rate, 50000000) - 1;
+ preset_div = DIV_ROUND_UP(gck_rate, 50000000) - 1;
writew(SDHCI_AT91_PRESET_COMMON_CONF | preset_div,
host->ioaddr + SDHCI_PRESET_FOR_SDR25);
- preset_div = DIV_ROUND_UP(real_gck_rate, 100000000) - 1;
+ preset_div = DIV_ROUND_UP(gck_rate, 100000000) - 1;
writew(SDHCI_AT91_PRESET_COMMON_CONF | preset_div,
host->ioaddr + SDHCI_PRESET_FOR_SDR50);
- preset_div = DIV_ROUND_UP(real_gck_rate, 120000000) - 1;
+ preset_div = DIV_ROUND_UP(gck_rate, 120000000) - 1;
writew(SDHCI_AT91_PRESET_COMMON_CONF | preset_div,
host->ioaddr + SDHCI_PRESET_FOR_SDR104);
- preset_div = DIV_ROUND_UP(real_gck_rate, 50000000) - 1;
+ preset_div = DIV_ROUND_UP(gck_rate, 50000000) - 1;
writew(SDHCI_AT91_PRESET_COMMON_CONF | preset_div,
host->ioaddr + SDHCI_PRESET_FOR_DDR50);
@@ -303,7 +308,7 @@ static const struct dev_pm_ops sdhci_at91_dev_pm_ops = {
static int sdhci_at91_probe(struct platform_device *pdev)
{
const struct of_device_id *match;
- const struct sdhci_pltfm_data *soc_data;
+ const struct sdhci_at91_soc_data *soc_data;
struct sdhci_host *host;
struct sdhci_pltfm_host *pltfm_host;
struct sdhci_at91_priv *priv;
@@ -314,17 +319,22 @@ static int sdhci_at91_probe(struct platform_device *pdev)
return -EINVAL;
soc_data = match->data;
- host = sdhci_pltfm_init(pdev, soc_data, sizeof(*priv));
+ host = sdhci_pltfm_init(pdev, soc_data->pdata, sizeof(*priv));
if (IS_ERR(host))
return PTR_ERR(host);
pltfm_host = sdhci_priv(host);
priv = sdhci_pltfm_priv(pltfm_host);
+ priv->soc_data = soc_data;
priv->mainck = devm_clk_get(&pdev->dev, "baseclk");
if (IS_ERR(priv->mainck)) {
- dev_err(&pdev->dev, "failed to get baseclk\n");
- return PTR_ERR(priv->mainck);
+ if (soc_data->baseclk_is_generated_internally) {
+ priv->mainck = NULL;
+ } else {
+ dev_err(&pdev->dev, "failed to get baseclk\n");
+ return PTR_ERR(priv->mainck);
+ }
}
priv->hclock = devm_clk_get(&pdev->dev, "hclock");
--
2.23.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* Re: [PATCHv5 10/10] ARM: OMAP2+: pdata-quirks: add PRM data for reset support
From: Tero Kristo @ 2019-09-12 20:09 UTC (permalink / raw)
To: Tony Lindgren
Cc: devicetree, linux-omap, robh+dt, p.zabel, ssantosh,
linux-arm-kernel
In-Reply-To: <20190912170953.GT52127@atomide.com>
On 12/09/2019 20:09, Tony Lindgren wrote:
> * Tero Kristo <t-kristo@ti.com> [190912 11:40]:
>> @@ -565,6 +566,12 @@ void omap_pcs_legacy_init(int irq, void (*rearm)(void))
>> pcs_pdata.rearm = rearm;
>> }
>>
>> +static struct ti_prm_platform_data ti_prm_pdata = {
>> + .clkdm_deny_idle = clkdm_deny_idle,
>> + .clkdm_allow_idle = clkdm_allow_idle,
>> + .clkdm_lookup = clkdm_lookup,
>> +};
>> +
>> /*
>> * GPIOs for TWL are initialized by the I2C bus and need custom
>> * handing until DSS has device tree bindings.
>> @@ -664,6 +671,11 @@ static struct of_dev_auxdata omap_auxdata_lookup[] = {
>> /* Common auxdata */
>> OF_DEV_AUXDATA("ti,sysc", 0, NULL, &ti_sysc_pdata),
>> OF_DEV_AUXDATA("pinctrl-single", 0, NULL, &pcs_pdata),
>> + OF_DEV_AUXDATA("ti,omap4-prm-inst", 0, NULL, &ti_prm_pdata),
>> + OF_DEV_AUXDATA("ti,omap5-prm-inst", 0, NULL, &ti_prm_pdata),
>> + OF_DEV_AUXDATA("ti,dra7-prm-inst", 0, NULL, &ti_prm_pdata),
>> + OF_DEV_AUXDATA("ti,am3-prm-inst", 0, NULL, &ti_prm_pdata),
>> + OF_DEV_AUXDATA("ti,am4-prm-inst", 0, NULL, &ti_prm_pdata),
>> { /* sentinel */ },
>> };
>
> Hmm I think I already commented on this.. Just one entry please:
>
> OF_DEV_AUXDATA("ti,omap-prm-inst", 0, NULL, &ti_prm_pdata),
>
> As the auxdata is the same for all of them. Note that all the
> dts files need to have also the generic compatible
> "ti,omap-prm-inst" after the SoC specific one.
Ok that should be fine, sorry for missing it out. I can update this in
the next rev, just need to update the dt binding also.
-Tero
--
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH V7 3/3] arm64/mm: Enable memory hot remove
From: Catalin Marinas @ 2019-09-12 20:15 UTC (permalink / raw)
To: Anshuman Khandual
Cc: mark.rutland, mhocko, david, linux-mm, arunks, cpandya, ira.weiny,
will, steven.price, valentin.schneider, suzuki.poulose,
Robin.Murphy, broonie, cai, ard.biesheuvel, dan.j.williams,
linux-arm-kernel, osalvador, steve.capper, logang, linux-kernel,
akpm, mgorman
In-Reply-To: <1567503958-25831-4-git-send-email-anshuman.khandual@arm.com>
Hi Anshuman,
Thanks for the details on the need for removing the page tables and
vmemmap backing. Some comments on the code below.
On Tue, Sep 03, 2019 at 03:15:58PM +0530, Anshuman Khandual wrote:
> --- a/arch/arm64/mm/mmu.c
> +++ b/arch/arm64/mm/mmu.c
> @@ -60,6 +60,14 @@ static pud_t bm_pud[PTRS_PER_PUD] __page_aligned_bss __maybe_unused;
>
> static DEFINE_SPINLOCK(swapper_pgdir_lock);
>
> +/*
> + * This represents if vmalloc and vmemmap address range overlap with
> + * each other on an intermediate level kernel page table entry which
> + * in turn helps in deciding whether empty kernel page table pages
> + * if any can be freed during memory hotplug operation.
> + */
> +static bool vmalloc_vmemmap_overlap;
I'd say just move the static find_vmalloc_vmemmap_overlap() function
here, the compiler should be sufficiently smart enough to figure out
that it's just a build-time constant.
> @@ -770,6 +1022,28 @@ int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node,
> void vmemmap_free(unsigned long start, unsigned long end,
> struct vmem_altmap *altmap)
> {
> +#ifdef CONFIG_MEMORY_HOTPLUG
> + /*
> + * FIXME: We should have called remove_pagetable(start, end, true).
> + * vmemmap and vmalloc virtual range might share intermediate kernel
> + * page table entries. Removing vmemmap range page table pages here
> + * can potentially conflict with a concurrent vmalloc() allocation.
> + *
> + * This is primarily because vmalloc() does not take init_mm ptl for
> + * the entire page table walk and it's modification. Instead it just
> + * takes the lock while allocating and installing page table pages
> + * via [p4d|pud|pmd|pte]_alloc(). A concurrently vanishing page table
> + * entry via memory hot remove can cause vmalloc() kernel page table
> + * walk pointers to be invalid on the fly which can cause corruption
> + * or worst, a crash.
> + *
> + * So free_empty_tables() gets called where vmalloc and vmemmap range
> + * do not overlap at any intermediate level kernel page table entry.
> + */
> + unmap_hotplug_range(start, end, true);
> + if (!vmalloc_vmemmap_overlap)
> + free_empty_tables(start, end);
> +#endif
> }
So, I see the risk with overlapping and I guess for some kernel
configurations (PAGE_SIZE == 64K) we may not be able to avoid it. If we
can, that's great, otherwise could we rewrite the above functions to
handle floor and ceiling similar to free_pgd_range()? (I wonder how this
function works if you called it on init_mm and kernel address range). By
having the vmemmap start/end information it avoids freeing partially
filled page table pages.
Another question: could we do the page table and the actual vmemmap
pages freeing in a single pass (sorry if this has been discussed
before)?
> @@ -1048,10 +1322,18 @@ int p4d_free_pud_page(p4d_t *p4d, unsigned long addr)
> }
>
> #ifdef CONFIG_MEMORY_HOTPLUG
> +static void __remove_pgd_mapping(pgd_t *pgdir, unsigned long start, u64 size)
> +{
> + unsigned long end = start + size;
> +
> + WARN_ON(pgdir != init_mm.pgd);
> + remove_pagetable(start, end, false);
> +}
I think the point I've made previously still stands: you only call
remove_pagetable() with sparse_vmap == false in this patch. Just remove
the extra argument and call unmap_hotplug_range() with sparse_vmap ==
false directly in remove_pagetable().
--
Catalin
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 3/6] ARM: dts: sunxi: h3/h5: Add MBUS controller node
From: Maxime Ripard @ 2019-09-12 20:20 UTC (permalink / raw)
To: Jernej Skrabec
Cc: mark.rutland, devicetree, linux-sunxi, linux-kernel, hverkuil,
wens, robh+dt, mchehab, linux-arm-kernel, linux-media
In-Reply-To: <20190912175132.411-4-jernej.skrabec@siol.net>
Hi,
On Thu, Sep 12, 2019 at 07:51:29PM +0200, Jernej Skrabec wrote:
> Both, H3 and H5, contain MBUS, which is the bus used by DMA devices to
> access system memory.
>
> MBUS controller is responsible for arbitration between channels based
> on set priority and can do some other things as well, like report
> bandwidth used. It also maps RAM region to different address than CPU.
>
> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> ---
> arch/arm/boot/dts/sunxi-h3-h5.dtsi | 9 +++++++++
> 1 file changed, 9 insertions(+)
>
> diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
> index eba190b3f9de..ef1d03812636 100644
> --- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi
> +++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
> @@ -109,6 +109,7 @@
> compatible = "simple-bus";
> #address-cells = <1>;
> #size-cells = <1>;
> + dma-ranges;
> ranges;
>
> display_clocks: clock@1000000 {
> @@ -538,6 +539,14 @@
> };
> };
>
> + mbus: dram-controller@1c62000 {
> + compatible = "allwinner,sun8i-h3-mbus";
> + reg = <0x01c62000 0x1000>;
> + clocks = <&ccu 113>;
> + dma-ranges = <0x00000000 0x40000000 0xc0000000>;
> + #interconnect-cells = <1>;
> + };
> +
If that's easy enough to access, can you also add the references in
the devices that are already there? (CSI and DE comes to my mind, but
there might be others).
Thanks!
Maxime
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 4/6] dt-bindings: media: Add Allwinner H3 Deinterlace binding
From: Maxime Ripard @ 2019-09-12 20:22 UTC (permalink / raw)
To: Jernej Skrabec
Cc: mark.rutland, devicetree, linux-sunxi, linux-kernel, hverkuil,
wens, robh+dt, mchehab, linux-arm-kernel, linux-media
In-Reply-To: <20190912175132.411-5-jernej.skrabec@siol.net>
Hi,
On Thu, Sep 12, 2019 at 07:51:30PM +0200, Jernej Skrabec wrote:
> Allwinner H3 Deinterlace core is used for deinterlacing interlaced video
> content. Core can also be found on some later SoCs, like H5 and R40.
>
> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> ---
> .../media/allwinner,sun8i-h3-deinterlace.yaml | 76 +++++++++++++++++++
> 1 file changed, 76 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/media/allwinner,sun8i-h3-deinterlace.yaml
>
> diff --git a/Documentation/devicetree/bindings/media/allwinner,sun8i-h3-deinterlace.yaml b/Documentation/devicetree/bindings/media/allwinner,sun8i-h3-deinterlace.yaml
> new file mode 100644
> index 000000000000..31c0ac427442
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/media/allwinner,sun8i-h3-deinterlace.yaml
> @@ -0,0 +1,76 @@
> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/arm/allwinner,sun8i-h3-deinterlace.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Allwinner H3 Deinterlace Device Tree Bindings
> +
> +maintainers:
> + - Chen-Yu Tsai <wens@csie.org>
> + - Maxime Ripard <maxime.ripard@bootlin.com>
mripard@kernel.org please
> +
> +description: |-
> + The Allwinner H3 and later has a deinterlace core used for
> + deinterlacing interlaced video content.
> +
> +properties:
> + compatible:
> + const: allwinner,sun8i-h3-deinterlace
> +
> + reg:
> + maxItems: 1
> +
> + interrupts:
> + maxItems: 1
> +
> + clocks:
> + items:
> + - description: Deinterlace interface clock
> + - description: Deinterlace module clock
> + - description: Deinterlace DRAM clock
> +
> + clock-names:
> + items:
> + - const: bus
> + - const: mod
> + - const: ram
> +
> + resets:
> + maxItems: 1
> +
> + interconnects:
> + maxItems: 1
> +
> + interconnect-names:
> + items:
> + - const: dma-mem
You can define it as:
interconnect-names:
const: dma-mem
There's no need for the items here.
Maxime
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 3/9] dt-bindings: crypto: Add DT bindings documentation for sun8i-ce Crypto Engine
From: Chen-Yu Tsai @ 2019-09-12 20:26 UTC (permalink / raw)
To: Maxime Ripard
Cc: Mark Rutland, devicetree, Herbert Xu, Russell King, linux-kernel,
linux-sunxi, Rob Herring, Corentin Labbe, linux-crypto,
David Miller, linux-arm-kernel
In-Reply-To: <20190912093737.s6iu63sdncij2qib@localhost.localdomain>
On Thu, Sep 12, 2019 at 10:37 AM Maxime Ripard <mripard@kernel.org> wrote:
>
> Hi Corentin,
>
> On Wed, Sep 11, 2019 at 08:31:58PM +0200, Corentin Labbe wrote:
> > On Sat, Sep 07, 2019 at 07:01:16AM +0300, Maxime Ripard wrote:
> > > On Fri, Sep 06, 2019 at 08:45:45PM +0200, Corentin Labbe wrote:
> > > > This patch adds documentation for Device-Tree bindings for the
> > > > Crypto Engine cryptographic accelerator driver.
> > > >
> > > > Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
> > > > ---
> > > > .../bindings/crypto/allwinner,sun8i-ce.yaml | 84 +++++++++++++++++++
> > > > 1 file changed, 84 insertions(+)
> > > > create mode 100644 Documentation/devicetree/bindings/crypto/allwinner,sun8i-ce.yaml
> > > >
> > > > diff --git a/Documentation/devicetree/bindings/crypto/allwinner,sun8i-ce.yaml b/Documentation/devicetree/bindings/crypto/allwinner,sun8i-ce.yaml
> > [...]
> > > > +else:
> > > > + clocks:
> > > > + items:
> > > > + - description: Bus clock
> > > > + - description: Module clock
> > > > +
> > > > + clock-names:
> > > > + items:
> > > > + - const: ahb
> > > > + - const: mod
> > > > +
> > > > + resets:
> > > > + maxItems: 1
> > > > +
> > > > + reset-names:
> > > > + const: ahb
> > >
> > > This prevents the usage of the additionalProperties property, which
> > > you should really use.
> > >
> > > What you can do instead is moving the clocks and clock-names
> > > description under properties, with a minItems of 2 and a maxItems of
> > > 3. Then you can restrict the length of that property to either 2 or 3
> > > depending on the case here.
> > >
> >
> > Hello
> >
> > I fail to do this.
> > I do the following (keeped only clock stuff)
> > properties:
> >
> > clocks:
> > items:
> > - description: Bus clock
> > - description: Module clock
> > - description: MBus clock
>
> Add minItems: 2 and maxItems: 3 at the same level than items
>
> >
> > clock-names:
> > items:
> > - const: ahb
> > - const: mod
> > - const: mbus
>
> And here as well
>
> Something I missed earlier though was that we've tried to unify as
> much as possible the ahb / apb / axi clocks around the bus name, it
> would be great if you could do it.
I think we also want to standardize "mbus" as "dram"?
ChenYu
> >
> > if:
> > properties:
> > compatible:
> > items:
> > const: allwinner,sun50i-h6-crypto
> > then:
> > properties:
> > clocks:
> > minItems: 3
> > maxItems: 3
> > clock-names:
> > minItems: 3
> > maxItems: 3
>
> You don't need to duplicate the min and maxItems here
>
> Maxime
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 5/6] media: sun4i: Add H3 deinterlace driver
From: Maxime Ripard @ 2019-09-12 20:26 UTC (permalink / raw)
To: Jernej Skrabec
Cc: mark.rutland, devicetree, linux-sunxi, linux-kernel, hverkuil,
wens, robh+dt, mchehab, linux-arm-kernel, linux-media
In-Reply-To: <20190912175132.411-6-jernej.skrabec@siol.net>
Hi,
On Thu, Sep 12, 2019 at 07:51:31PM +0200, Jernej Skrabec wrote:
> + dev->regmap = devm_regmap_init_mmio(dev->dev, dev->base,
> + &deinterlace_regmap_config);
> + if (IS_ERR(dev->regmap)) {
> + dev_err(dev->dev, "Couldn't create deinterlace regmap\n");
> +
> + return PTR_ERR(dev->regmap);
> + }
> +
> + ret = clk_prepare_enable(dev->bus_clk);
> + if (ret) {
> + dev_err(dev->dev, "Failed to enable bus clock\n");
> +
> + return ret;
> + }
Do you need to keep the bus clock enabled all the time? Usually, for
the SoCs that have a reset line, you only need it to read / write to
the registers, not to have the controller actually running.
If you don't, then regmap_init_mmio_clk will take care of that for
you.
> + clk_set_rate(dev->mod_clk, 300000000);
> +
> + ret = clk_prepare_enable(dev->mod_clk);
> + if (ret) {
> + dev_err(dev->dev, "Failed to enable mod clock\n");
> +
> + goto err_bus_clk;
> + }
> +
> + ret = clk_prepare_enable(dev->ram_clk);
> + if (ret) {
> + dev_err(dev->dev, "Failed to enable ram clock\n");
> +
> + goto err_mod_clk;
> + }
> +
> + ret = reset_control_reset(dev->rstc);
> + if (ret) {
> + dev_err(dev->dev, "Failed to apply reset\n");
> +
> + goto err_ram_clk;
> + }
This could be moved to a runtime_pm hook, with get_sync called in the
open. That way you won't leave the device powered on if it's unused.
> +struct deinterlace_dev {
> + struct v4l2_device v4l2_dev;
> + struct video_device vfd;
> + struct device *dev;
> + struct v4l2_m2m_dev *m2m_dev;
> +
> + /* Device file mutex */
> + struct mutex dev_mutex;
> +
> + void __iomem *base;
> + struct regmap *regmap;
Do you need to store the base address in that structure if you're
using the regmap?
Maxime
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 3/6] ARM: dts: sunxi: h3/h5: Add MBUS controller node
From: Jernej Škrabec @ 2019-09-12 20:28 UTC (permalink / raw)
To: Maxime Ripard
Cc: mark.rutland, devicetree, linux-sunxi, linux-kernel, hverkuil,
wens, robh+dt, mchehab, linux-arm-kernel, linux-media
In-Reply-To: <20190912202057.czb6nzgssg442isi@localhost.localdomain>
Dne četrtek, 12. september 2019 ob 22:20:57 CEST je Maxime Ripard napisal(a):
> Hi,
>
> On Thu, Sep 12, 2019 at 07:51:29PM +0200, Jernej Skrabec wrote:
> > Both, H3 and H5, contain MBUS, which is the bus used by DMA devices to
> > access system memory.
> >
> > MBUS controller is responsible for arbitration between channels based
> > on set priority and can do some other things as well, like report
> > bandwidth used. It also maps RAM region to different address than CPU.
> >
> > Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> > ---
> >
> > arch/arm/boot/dts/sunxi-h3-h5.dtsi | 9 +++++++++
> > 1 file changed, 9 insertions(+)
> >
> > diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi
> > b/arch/arm/boot/dts/sunxi-h3-h5.dtsi index eba190b3f9de..ef1d03812636
> > 100644
> > --- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi
> > +++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
> > @@ -109,6 +109,7 @@
> >
> > compatible = "simple-bus";
> > #address-cells = <1>;
> > #size-cells = <1>;
> >
> > + dma-ranges;
> >
> > ranges;
> >
> > display_clocks: clock@1000000 {
> >
> > @@ -538,6 +539,14 @@
> >
> > };
> >
> > };
> >
> > + mbus: dram-controller@1c62000 {
> > + compatible = "allwinner,sun8i-h3-mbus";
> > + reg = <0x01c62000 0x1000>;
> > + clocks = <&ccu 113>;
> > + dma-ranges = <0x00000000 0x40000000
0xc0000000>;
> > + #interconnect-cells = <1>;
> > + };
> > +
>
> If that's easy enough to access, can you also add the references in
> the devices that are already there? (CSI and DE comes to my mind, but
> there might be others).
Strangely, DE2 doesn't use this offset. That was tested on OrangePi Plus2E,
which has 2 GiB of RAM and subtracting this offset causes corrupted image.
But I can add this properties to CSI too. However, wouldn't that need CSI DT
binding expansion with those properties? othetwise DT check will fail.
Best regards,
Jernej
>
> Thanks!
> Maxime
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH] ARM: dts: imx6: Extend support for Phytec phycore i.MX6ULL SoM
From: Parthiban Nallathambi @ 2019-09-12 20:29 UTC (permalink / raw)
To: robh+dt, mark.rutland, shawnguo, s.hauer, kernel, festevam,
linux-imx
Cc: devicetree, Parthiban Nallathambi, linux-kernel, linux-arm-kernel
Extend Phycore i.MX6UL SoM for i.MX6ULL with on board eMMC. Phycore
i.MX6ULL is deployed with same carrier board Segin as the pins are
compatible with UL version.
Signed-off-by: Parthiban Nallathambi <pn@denx.de>
---
arch/arm/boot/dts/imx6ul-phytec-pcl063.dtsi | 26 +++++++++++++++++--
.../dts/imx6ul-phytec-phyboard-segin-full.dts | 5 ++++
arch/arm/boot/dts/imx6ull-phytec-pcl063.dtsi | 24 +++++++++++++++++
3 files changed, 53 insertions(+), 2 deletions(-)
create mode 100644 arch/arm/boot/dts/imx6ull-phytec-pcl063.dtsi
diff --git a/arch/arm/boot/dts/imx6ul-phytec-pcl063.dtsi b/arch/arm/boot/dts/imx6ul-phytec-pcl063.dtsi
index fc2997449b49..822a178ce438 100644
--- a/arch/arm/boot/dts/imx6ul-phytec-pcl063.dtsi
+++ b/arch/arm/boot/dts/imx6ul-phytec-pcl063.dtsi
@@ -7,7 +7,6 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/pwm/pwm.h>
-#include "imx6ul.dtsi"
/ {
model = "Phytec phyCORE i.MX6 UltraLite";
@@ -65,7 +64,7 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_gpmi_nand>;
nand-on-flash-bbt;
- status = "okay";
+ status = "disabled";
};
&i2c1 {
@@ -90,6 +89,15 @@
status = "okay";
};
+&usdhc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc2>;
+ bus-width = <8>;
+ no-1-8-v;
+ non-removable;
+ status = "disabled";
+};
+
&iomuxc {
pinctrl_enet1: enet1grp {
fsl,pins = <
@@ -145,4 +153,18 @@
>;
};
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6UL_PAD_NAND_WE_B__USDHC2_CMD 0x170f9
+ MX6UL_PAD_NAND_RE_B__USDHC2_CLK 0x100f9
+ MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x170f9
+ MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x170f9
+ MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x170f9
+ MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x170f9
+ MX6UL_PAD_NAND_DATA04__USDHC2_DATA4 0x170f9
+ MX6UL_PAD_NAND_DATA05__USDHC2_DATA5 0x170f9
+ MX6UL_PAD_NAND_DATA06__USDHC2_DATA6 0x170f9
+ MX6UL_PAD_NAND_DATA07__USDHC2_DATA7 0x170f9
+ >;
+ };
};
diff --git a/arch/arm/boot/dts/imx6ul-phytec-phyboard-segin-full.dts b/arch/arm/boot/dts/imx6ul-phytec-phyboard-segin-full.dts
index b6a1407a9d44..76f2447f2657 100644
--- a/arch/arm/boot/dts/imx6ul-phytec-phyboard-segin-full.dts
+++ b/arch/arm/boot/dts/imx6ul-phytec-phyboard-segin-full.dts
@@ -5,6 +5,7 @@
*/
/dts-v1/;
+#include "imx6ul.dtsi"
#include "imx6ul-phytec-pcl063.dtsi"
#include "imx6ul-phytec-phyboard-segin.dtsi"
#include "imx6ul-phytec-peb-eval-01.dtsi"
@@ -37,6 +38,10 @@
status = "okay";
};
+&gpmi {
+ status = "okay";
+};
+
&i2c_rtc {
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6ull-phytec-pcl063.dtsi b/arch/arm/boot/dts/imx6ull-phytec-pcl063.dtsi
new file mode 100644
index 000000000000..3f749d9f09a5
--- /dev/null
+++ b/arch/arm/boot/dts/imx6ull-phytec-pcl063.dtsi
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2018 PHYTEC Messtechnik GmbH
+ * Author: Stefan Riedmueller <s.riedmueller@phytec.de>
+ */
+
+#include "imx6ul-phytec-pcl063.dtsi"
+
+/ {
+ model = "PHYTEC phyCORE-i.MX 6ULL";
+ compatible = "phytec,imx6ull-pcl063", "fsl,imx6ull";
+};
+
+&iomuxc {
+ /delete-node/ gpioledssomgrp;
+};
+
+&iomuxc_snvs {
+ pinctrl_gpioleds_som: gpioledssomgrp {
+ fsl,pins = <
+ MX6ULL_PAD_SNVS_TAMPER4__GPIO5_IO04 0x0b0b0
+ >;
+ };
+};
--
2.21.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox