Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 3/4] clk/soc: mediatek: mt6779: Bind clock driver from platform device
From: matthias.bgg @ 2020-05-18 11:31 UTC (permalink / raw)
  To: Rob Herring, Matthias Brugger, Michael Turquette, Stephen Boyd
  Cc: Kate Stewart, devicetree, Greg Kroah-Hartman, linux-kernel,
	linux-mediatek, linux-arm-kernel, mtk01761, Thomas Gleixner,
	linux-clk, Allison Randal
In-Reply-To: <20200518113156.25009-1-matthias.bgg@kernel.org>

From: Matthias Brugger <matthias.bgg@gmail.com>

The mmsys driver is now the top level entry point for the multimedia
system (mmsys), we bind the clock driver by creating a platform device.
We also bind the MediaTek DRM driver which is not yet implement and
therefor will errror out for now.

Signed-off-by: Matthias Brugger <matthias.bgg@gmail.com>
---

 drivers/clk/mediatek/clk-mt6779-mm.c | 9 ++-------
 drivers/soc/mediatek/mtk-mmsys.c     | 8 ++++++++
 2 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/drivers/clk/mediatek/clk-mt6779-mm.c b/drivers/clk/mediatek/clk-mt6779-mm.c
index fb5fbb8e3e41..059c1a41ac7a 100644
--- a/drivers/clk/mediatek/clk-mt6779-mm.c
+++ b/drivers/clk/mediatek/clk-mt6779-mm.c
@@ -84,15 +84,11 @@ static const struct mtk_gate mm_clks[] = {
 	GATE_MM1(CLK_MM_DISP_OVL_FBDC, "mm_disp_ovl_fbdc", "mm_sel", 16),
 };
 
-static const struct of_device_id of_match_clk_mt6779_mm[] = {
-	{ .compatible = "mediatek,mt6779-mmsys", },
-	{}
-};
-
 static int clk_mt6779_mm_probe(struct platform_device *pdev)
 {
+	struct device *dev = &pdev->dev;
+	struct device_node *node = dev->parent->of_node;
 	struct clk_onecell_data *clk_data;
-	struct device_node *node = pdev->dev.of_node;
 
 	clk_data = mtk_alloc_clk_data(CLK_MM_NR_CLK);
 
@@ -106,7 +102,6 @@ static struct platform_driver clk_mt6779_mm_drv = {
 	.probe = clk_mt6779_mm_probe,
 	.driver = {
 		.name = "clk-mt6779-mm",
-		.of_match_table = of_match_clk_mt6779_mm,
 	},
 };
 
diff --git a/drivers/soc/mediatek/mtk-mmsys.c b/drivers/soc/mediatek/mtk-mmsys.c
index fee64c8d3020..dc15808cf3a3 100644
--- a/drivers/soc/mediatek/mtk-mmsys.c
+++ b/drivers/soc/mediatek/mtk-mmsys.c
@@ -88,6 +88,10 @@ static const struct mtk_mmsys_driver_data mt2712_mmsys_driver_data = {
 	.clk_driver = "clk-mt2712-mm",
 };
 
+static const struct mtk_mmsys_driver_data mt6779_mmsys_driver_data = {
+	.clk_driver = "clk-mt6779-mm",
+};
+
 static const struct mtk_mmsys_driver_data mt6797_mmsys_driver_data = {
 	.clk_driver = "clk-mt6797-mm",
 };
@@ -343,6 +347,10 @@ static const struct of_device_id of_match_mtk_mmsys[] = {
 		.compatible = "mediatek,mt2712-mmsys",
 		.data = &mt2712_mmsys_driver_data,
 	},
+	{
+		.compatible = "mediatek,mt6779-mmsys",
+		.data = &mt6779_mmsys_driver_data,
+	},
 	{
 		.compatible = "mediatek,mt6797-mmsys",
 		.data = &mt6797_mmsys_driver_data,
-- 
2.26.2


_______________________________________________
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/4] clk/soc: mediatek: mt6797: Bind clock driver from platform device
From: matthias.bgg @ 2020-05-18 11:31 UTC (permalink / raw)
  To: Rob Herring, Matthias Brugger, Michael Turquette, Stephen Boyd
  Cc: Kate Stewart, devicetree, Greg Kroah-Hartman, linux-kernel,
	Richard Fontana, linux-mediatek, linux-arm-kernel, mtk01761,
	Thomas Gleixner, linux-clk, Allison Randal
In-Reply-To: <20200518113156.25009-1-matthias.bgg@kernel.org>

From: Matthias Brugger <matthias.bgg@gmail.com>

The mmsys driver is now the top level entry point for the multimedia
system (mmsys), we bind the clock driver by creating a platform device.
We also bind the MediaTek DRM driver which is not yet implement and
therefor will errror out for now.

Signed-off-by: Matthias Brugger <matthias.bgg@gmail.com>
---

 drivers/clk/mediatek/clk-mt6797-mm.c | 9 ++-------
 drivers/soc/mediatek/mtk-mmsys.c     | 8 ++++++++
 2 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/drivers/clk/mediatek/clk-mt6797-mm.c b/drivers/clk/mediatek/clk-mt6797-mm.c
index 8f05653b387d..01fdce287247 100644
--- a/drivers/clk/mediatek/clk-mt6797-mm.c
+++ b/drivers/clk/mediatek/clk-mt6797-mm.c
@@ -92,16 +92,12 @@ static const struct mtk_gate mm_clks[] = {
 		 "clk26m", 3),
 };
 
-static const struct of_device_id of_match_clk_mt6797_mm[] = {
-	{ .compatible = "mediatek,mt6797-mmsys", },
-	{}
-};
-
 static int clk_mt6797_mm_probe(struct platform_device *pdev)
 {
+	struct device *dev = &pdev->dev;
+	struct device_node *node = dev->parent->of_node;
 	struct clk_onecell_data *clk_data;
 	int r;
-	struct device_node *node = pdev->dev.of_node;
 
 	clk_data = mtk_alloc_clk_data(CLK_MM_NR);
 
@@ -121,7 +117,6 @@ static struct platform_driver clk_mt6797_mm_drv = {
 	.probe = clk_mt6797_mm_probe,
 	.driver = {
 		.name = "clk-mt6797-mm",
-		.of_match_table = of_match_clk_mt6797_mm,
 	},
 };
 
diff --git a/drivers/soc/mediatek/mtk-mmsys.c b/drivers/soc/mediatek/mtk-mmsys.c
index 783c3dd008b2..fee64c8d3020 100644
--- a/drivers/soc/mediatek/mtk-mmsys.c
+++ b/drivers/soc/mediatek/mtk-mmsys.c
@@ -88,6 +88,10 @@ static const struct mtk_mmsys_driver_data mt2712_mmsys_driver_data = {
 	.clk_driver = "clk-mt2712-mm",
 };
 
+static const struct mtk_mmsys_driver_data mt6797_mmsys_driver_data = {
+	.clk_driver = "clk-mt6797-mm",
+};
+
 static const struct mtk_mmsys_driver_data mt8173_mmsys_driver_data = {
 	.clk_driver = "clk-mt8173-mm",
 };
@@ -339,6 +343,10 @@ static const struct of_device_id of_match_mtk_mmsys[] = {
 		.compatible = "mediatek,mt2712-mmsys",
 		.data = &mt2712_mmsys_driver_data,
 	},
+	{
+		.compatible = "mediatek,mt6797-mmsys",
+		.data = &mt6797_mmsys_driver_data,
+	},
 	{
 		.compatible = "mediatek,mt8173-mmsys",
 		.data = &mt8173_mmsys_driver_data,
-- 
2.26.2


_______________________________________________
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/4] clk/soc: mediatek: mt8183: Bind clock driver from platform device
From: matthias.bgg @ 2020-05-18 11:31 UTC (permalink / raw)
  To: Rob Herring, Matthias Brugger, Michael Turquette, Stephen Boyd
  Cc: Kate Stewart, devicetree, Greg Kroah-Hartman, linux-kernel,
	linux-mediatek, linux-arm-kernel, mtk01761, Thomas Gleixner,
	linux-clk, Allison Randal

From: Matthias Brugger <matthias.bgg@gmail.com>

The mmsys driver is now the top level entry point for the multimedia
system (mmsys), we bind the clock driver by creating a platform device.
We also bind the MediaTek DRM driver which is not yet implement and
therefor will errror out for now.

Signed-off-by: Matthias Brugger <matthias.bgg@gmail.com>
---

 drivers/clk/mediatek/clk-mt8183-mm.c | 9 ++-------
 drivers/soc/mediatek/mtk-mmsys.c     | 8 ++++++++
 2 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/drivers/clk/mediatek/clk-mt8183-mm.c b/drivers/clk/mediatek/clk-mt8183-mm.c
index 720c696b506d..9d60e09619c1 100644
--- a/drivers/clk/mediatek/clk-mt8183-mm.c
+++ b/drivers/clk/mediatek/clk-mt8183-mm.c
@@ -84,8 +84,9 @@ static const struct mtk_gate mm_clks[] = {
 
 static int clk_mt8183_mm_probe(struct platform_device *pdev)
 {
+	struct device *dev = &pdev->dev;
+	struct device_node *node = dev->parent->of_node;
 	struct clk_onecell_data *clk_data;
-	struct device_node *node = pdev->dev.of_node;
 
 	clk_data = mtk_alloc_clk_data(CLK_MM_NR_CLK);
 
@@ -95,16 +96,10 @@ static int clk_mt8183_mm_probe(struct platform_device *pdev)
 	return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
 }
 
-static const struct of_device_id of_match_clk_mt8183_mm[] = {
-	{ .compatible = "mediatek,mt8183-mmsys", },
-	{}
-};
-
 static struct platform_driver clk_mt8183_mm_drv = {
 	.probe = clk_mt8183_mm_probe,
 	.driver = {
 		.name = "clk-mt8183-mm",
-		.of_match_table = of_match_clk_mt8183_mm,
 	},
 };
 
diff --git a/drivers/soc/mediatek/mtk-mmsys.c b/drivers/soc/mediatek/mtk-mmsys.c
index cacafe23c823..783c3dd008b2 100644
--- a/drivers/soc/mediatek/mtk-mmsys.c
+++ b/drivers/soc/mediatek/mtk-mmsys.c
@@ -92,6 +92,10 @@ static const struct mtk_mmsys_driver_data mt8173_mmsys_driver_data = {
 	.clk_driver = "clk-mt8173-mm",
 };
 
+static const struct mtk_mmsys_driver_data mt8183_mmsys_driver_data = {
+	.clk_driver = "clk-mt8183-mm",
+};
+
 static unsigned int mtk_mmsys_ddp_mout_en(enum mtk_ddp_comp_id cur,
 					  enum mtk_ddp_comp_id next,
 					  unsigned int *addr)
@@ -339,6 +343,10 @@ static const struct of_device_id of_match_mtk_mmsys[] = {
 		.compatible = "mediatek,mt8173-mmsys",
 		.data = &mt8173_mmsys_driver_data,
 	},
+	{
+		.compatible = "mediatek,mt8183-mmsys",
+		.data = &mt8183_mmsys_driver_data,
+	},
 	{ }
 };
 
-- 
2.26.2


_______________________________________________
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 v3 00/20] dts/dt-bindings: Fix Arm Ltd. ARMv8 "boards"
From: Sudeep Holla @ 2020-05-18 11:31 UTC (permalink / raw)
  To: Andre Przywara
  Cc: Mark Rutland, Rob Herring, Lorenzo Pieralisi, devicetree,
	Marc Zyngier, Liviu Dudau, Sudeep Holla, linux-arm-kernel
In-Reply-To: <20200513103016.130417-1-andre.przywara@arm.com>

On Wed, 13 May 2020 11:29:56 +0100, Andre Przywara wrote:
> A few updates compared to v2. The most important is to fix the
> interrupt-maps, triggered by changing the number of address-cells in
> the GIC node. For this I split the former patch 07/17 into two (09/20
> and 10/20), one for the foundation model, the other for Juno.
> Also I fixed a dtc complaint about device nodes without reg properties
> being inside simple-bus nodes, those are the new patches 04-06/20.
> Will took patch 01/17 from v2 already, so I removed this from this
> series.
> The rest of the patches stayed the same.
> -----------------------------------
> 
> [...]

Hi Andre,

Patch 12/20 was missing your Signed-off tags, re-applied adding the same.

Applied to scmi-vexpress-juno (for-next/juno), thanks!

[02/20] arm64: dts: fvp/juno: Fix node address fields
        https://git.kernel.org/sudeep.holla/c/bb5cce12ac
[03/20] arm64: dts: fvp: Move fixed devices out of bus node
        https://git.kernel.org/sudeep.holla/c/849bfc3dfc
[04/20] arm64: dts: vexpress: Move fixed devices out of bus node
        https://git.kernel.org/sudeep.holla/c/d9258898ad
[05/20] arm64: dts: fvp: Move fixed clocks out of bus node
        https://git.kernel.org/sudeep.holla/c/feebdc3f79
[06/20] arm64: dts: juno: Move fixed devices out of bus node
        https://git.kernel.org/sudeep.holla/c/948204a1bf
[07/20] arm64: dts: juno: Fix mem-timer
        https://git.kernel.org/sudeep.holla/c/0e529dae51
[08/20] arm64: dts: fvp: Fix GIC compatible names
        https://git.kernel.org/sudeep.holla/c/336edacfb9
[09/20] arm64: dts: juno: Fix GIC child nodes
        https://git.kernel.org/sudeep.holla/c/a78aee9e43
[10/20] arm64: dts: fvp: Fix GIC child nodes
        https://git.kernel.org/sudeep.holla/c/78631aecc5
[11/20] arm64: dts: fvp: Fix ITS node names and #msi-cells
        https://git.kernel.org/sudeep.holla/c/fac959c93f
[12/20] arm64: dts: juno: Use proper DT node name for USB
        https://git.kernel.org/sudeep.holla/c/a66ab61b2c
[13/20] arm64: dts: fvp/juno: Fix serial node names
        https://git.kernel.org/sudeep.holla/c/1d33445a19
[14/20] arm64: dts: fvp: Fix SMMU DT node
        https://git.kernel.org/sudeep.holla/c/386270bad0
[15/20] arm64: dts: fvp/juno: Fix bus node names
        https://git.kernel.org/sudeep.holla/c/48db29f2c9
[16/20] arm64: dts: juno: Fix GPU interrupt order
        https://git.kernel.org/sudeep.holla/c/90280c4dc0
[17/20] arm64: dts: vexpress: Fix VExpress LED names
        https://git.kernel.org/sudeep.holla/c/dc6e874179
[18/20] arm64: dts: juno: Fix SCPI shared mem node name
        https://git.kernel.org/sudeep.holla/c/267c673233

--
Regards,
Sudeep


_______________________________________________
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 v4 24/26] arm64: mte: Introduce early param to disable MTE support
From: Will Deacon @ 2020-05-18 11:31 UTC (permalink / raw)
  To: Vladimir Murzin
  Cc: linux-arch, Szabolcs Nagy, Catalin Marinas, Kevin Brodsky,
	linux-mm, Andrey Konovalov, Vincenzo Frascino,
	Peter Collingbourne, Dave P Martin, linux-arm-kernel
In-Reply-To: <a2ad6cbf-2632-3cda-eb49-74ddfbed2cec@arm.com>

On Mon, May 18, 2020 at 12:26:30PM +0100, Vladimir Murzin wrote:
> On 5/15/20 6:16 PM, Catalin Marinas wrote:
> > For performance analysis it may be desirable to disable MTE altogether
> > via an early param. Introduce arm64.mte_disable and, if true, filter out
> > the sanitised ID_AA64PFR1_EL1.MTE field to avoid exposing the HWCAP to
> > user.
> > 
> > Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
> > Cc: Will Deacon <will@kernel.org>
> > ---
> > 
> > Notes:
> >     New in v4.
> > 
> >  Documentation/admin-guide/kernel-parameters.txt |  4 ++++
> >  arch/arm64/kernel/cpufeature.c                  | 11 +++++++++++
> >  2 files changed, 15 insertions(+)
> > 
> > diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> > index f2a93c8679e8..7436e7462b85 100644
> > --- a/Documentation/admin-guide/kernel-parameters.txt
> > +++ b/Documentation/admin-guide/kernel-parameters.txt
> > @@ -373,6 +373,10 @@
> >  	arcrimi=	[HW,NET] ARCnet - "RIM I" (entirely mem-mapped) cards
> >  			Format: <io>,<irq>,<nodeID>
> >  
> > +	arm64.mte_disable=
> > +			[ARM64] Disable Linux support for the Memory
> > +			Tagging Extension (both user and in-kernel).
> > +
> 
> Should it really to take parameter (on/off/true/false)? It may lead to expectation
> that arm64.mte_disable=false should enable MT and, yes, double negatives make it
> look ugly, so if we do need parameter, can it be arm64.mte=on/off/true/false?

I don't think "performance analysis" is a good justification for this
parameter tbh. We don't tend to add these options for other architectural
features, and I don't see why MTE is any different in this regard.

Will

_______________________________________________
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 v3 2/4] kasan: record and print the free track
From: Walter Wu @ 2020-05-18 11:27 UTC (permalink / raw)
  To: Dmitry Vyukov
  Cc: wsd_upstream, linux-mediatek, LKML, kasan-dev, Linux-MM,
	Alexander Potapenko, Matthias Brugger, Andrey Ryabinin, Linux ARM
In-Reply-To: <CACT4Y+YVF2cLdg6qaK+3NcU3kLz2Pys6NWxLAYfity5n5cjirA@mail.gmail.com>

On Mon, 2020-05-18 at 12:18 +0200, Dmitry Vyukov wrote:
> On Mon, May 18, 2020 at 8:27 AM Walter Wu <walter-zh.wu@mediatek.com> wrote:
> >
> > Move free track from slub alloc meta-data to slub free meta-data in
> > order to make struct kasan_free_meta size is 16 bytes. It is a good
> > size because it is the minimal redzone size and a good number of
> > alignment.
> >
> > For free track in generic KASAN, we do the modification in struct
> > kasan_alloc_meta and kasan_free_meta:
> > - remove free track from kasan_alloc_meta.
> > - add free track into kasan_free_meta.
> >
> > [1]https://bugzilla.kernel.org/show_bug.cgi?id=198437
> >
> > Signed-off-by: Walter Wu <walter-zh.wu@mediatek.com>
> > Suggested-by: Dmitry Vyukov <dvyukov@google.com>
> > Cc: Andrey Ryabinin <aryabinin@virtuozzo.com>
> > Cc: Dmitry Vyukov <dvyukov@google.com>
> > Cc: Alexander Potapenko <glider@google.com>
> > ---
> >  mm/kasan/common.c  | 33 ++++++++++-----------------------
> >  mm/kasan/generic.c | 18 ++++++++++++++++++
> >  mm/kasan/kasan.h   |  7 +++++++
> >  mm/kasan/report.c  | 20 --------------------
> >  mm/kasan/tags.c    | 37 +++++++++++++++++++++++++++++++++++++
> >  5 files changed, 72 insertions(+), 43 deletions(-)
> >
> > diff --git a/mm/kasan/common.c b/mm/kasan/common.c
> > index 8bc618289bb1..6500bc2bb70c 100644
> > --- a/mm/kasan/common.c
> > +++ b/mm/kasan/common.c
> > @@ -51,7 +51,7 @@ depot_stack_handle_t kasan_save_stack(gfp_t flags)
> >         return stack_depot_save(entries, nr_entries, flags);
> >  }
> >
> > -static inline void set_track(struct kasan_track *track, gfp_t flags)
> > +void kasan_set_track(struct kasan_track *track, gfp_t flags)
> >  {
> >         track->pid = current->pid;
> >         track->stack = kasan_save_stack(flags);
> > @@ -249,9 +249,7 @@ void kasan_cache_create(struct kmem_cache *cache, unsigned int *size,
> >         *size += sizeof(struct kasan_alloc_meta);
> >
> >         /* Add free meta. */
> > -       if (IS_ENABLED(CONFIG_KASAN_GENERIC) &&
> > -           (cache->flags & SLAB_TYPESAFE_BY_RCU || cache->ctor ||
> > -            cache->object_size < sizeof(struct kasan_free_meta))) {
> > +       if (IS_ENABLED(CONFIG_KASAN_GENERIC)) {
> 
> Why do we need to increase object size unconditionally?
> We only store info in free track when the object is free, so I would
> assume we still can generally overlap free track and the object
> itself. We store free track at the same time we use the quarantine
> link, and the quarantine link was overlapped with the object just
> fine.
> With this change we indeed increase object size, which we do not want
> in general.
> 

If it doesn't add free meta, but we always store free track into the
object, Is it safe?

> 
> >                 cache->kasan_info.free_meta_offset = *size;
> >                 *size += sizeof(struct kasan_free_meta);
> >         }
> > @@ -299,24 +297,6 @@ struct kasan_free_meta *get_free_info(struct kmem_cache *cache,
> >         return (void *)object + cache->kasan_info.free_meta_offset;
> >  }
> >
> > -
> > -static void kasan_set_free_info(struct kmem_cache *cache,
> > -               void *object, u8 tag)
> > -{
> > -       struct kasan_alloc_meta *alloc_meta;
> > -       u8 idx = 0;
> > -
> > -       alloc_meta = get_alloc_info(cache, object);
> > -
> > -#ifdef CONFIG_KASAN_SW_TAGS_IDENTIFY
> > -       idx = alloc_meta->free_track_idx;
> > -       alloc_meta->free_pointer_tag[idx] = tag;
> > -       alloc_meta->free_track_idx = (idx + 1) % KASAN_NR_FREE_STACKS;
> > -#endif
> > -
> > -       set_track(&alloc_meta->free_track[idx], GFP_NOWAIT);
> > -}
> > -
> >  void kasan_poison_slab(struct page *page)
> >  {
> >         unsigned long i;
> > @@ -396,6 +376,13 @@ void * __must_check kasan_init_slab_obj(struct kmem_cache *cache,
> >         alloc_info = get_alloc_info(cache, object);
> >         __memset(alloc_info, 0, sizeof(*alloc_info));
> >
> > +       if (IS_ENABLED(CONFIG_KASAN_GENERIC)) {
> > +               struct kasan_free_meta *free_info;
> > +
> > +               free_info = get_free_info(cache, object);
> > +               __memset(free_info, 0, sizeof(*free_info));
> 
> If we overlap free track with object, this will not be needed as well, right?
> 

Should we not consider those objects which have adding free meta? If
they exist, then we should init their meta data when object re-allocate.

struct kasan_free_meta {
    struct qlist_node quarantine_link;
    struct kasan_track free_track;
};


> > +       }
> > +
> >         if (IS_ENABLED(CONFIG_KASAN_SW_TAGS))
> >                 object = set_tag(object,
> >                                 assign_tag(cache, object, true, false));
> > @@ -492,7 +479,7 @@ static void *__kasan_kmalloc(struct kmem_cache *cache, const void *object,
> >                 KASAN_KMALLOC_REDZONE);
> >
> >         if (cache->flags & SLAB_KASAN)
> > -               set_track(&get_alloc_info(cache, object)->alloc_track, flags);
> > +               kasan_set_track(&get_alloc_info(cache, object)->alloc_track, flags);
> >
> >         return set_tag(object, tag);
> >  }
> > diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c
> > index 78d8e0a75a8a..988bc095b738 100644
> > --- a/mm/kasan/generic.c
> > +++ b/mm/kasan/generic.c
> > @@ -345,3 +345,21 @@ void kasan_record_aux_stack(void *addr)
> >                 alloc_info->rcu_stack[1] = alloc_info->rcu_stack[0];
> >         alloc_info->rcu_stack[0] = kasan_save_stack(GFP_NOWAIT);
> >  }
> > +
> > +void kasan_set_free_info(struct kmem_cache *cache,
> > +                               void *object, u8 tag)
> > +{
> > +       struct kasan_free_meta *free_meta;
> > +
> > +       free_meta = get_free_info(cache, object);
> > +       kasan_set_track(&free_meta->free_track, GFP_NOWAIT);
> > +}
> > +
> > +struct kasan_track *kasan_get_free_track(struct kmem_cache *cache,
> > +                               void *object, u8 tag)
> > +{
> > +       struct kasan_free_meta *free_meta;
> > +
> > +       free_meta = get_free_info(cache, object);
> > +       return &free_meta->free_track;
> > +}
> > diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
> > index 870c5dd07756..87ee3626b8b0 100644
> > --- a/mm/kasan/kasan.h
> > +++ b/mm/kasan/kasan.h
> > @@ -127,6 +127,9 @@ struct kasan_free_meta {
> >          * Otherwise it might be used for the allocator freelist.
> >          */
> >         struct qlist_node quarantine_link;
> > +#ifdef CONFIG_KASAN_GENERIC
> > +       struct kasan_track free_track;
> > +#endif
> >  };
> >
> >  struct kasan_alloc_meta *get_alloc_info(struct kmem_cache *cache,
> > @@ -168,6 +171,10 @@ void kasan_report_invalid_free(void *object, unsigned long ip);
> >  struct page *kasan_addr_to_page(const void *addr);
> >
> >  depot_stack_handle_t kasan_save_stack(gfp_t flags);
> > +void kasan_set_track(struct kasan_track *track, gfp_t flags);
> > +void kasan_set_free_info(struct kmem_cache *cache, void *object, u8 tag);
> > +struct kasan_track *kasan_get_free_track(struct kmem_cache *cache,
> > +                               void *object, u8 tag);
> >
> >  #if defined(CONFIG_KASAN_GENERIC) && \
> >         (defined(CONFIG_SLAB) || defined(CONFIG_SLUB))
> > diff --git a/mm/kasan/report.c b/mm/kasan/report.c
> > index 5ee66cf7e27c..7e9f9f6d5e85 100644
> > --- a/mm/kasan/report.c
> > +++ b/mm/kasan/report.c
> > @@ -159,26 +159,6 @@ static void describe_object_addr(struct kmem_cache *cache, void *object,
> >                 (void *)(object_addr + cache->object_size));
> >  }
> >
> > -static struct kasan_track *kasan_get_free_track(struct kmem_cache *cache,
> > -               void *object, u8 tag)
> > -{
> > -       struct kasan_alloc_meta *alloc_meta;
> > -       int i = 0;
> > -
> > -       alloc_meta = get_alloc_info(cache, object);
> > -
> > -#ifdef CONFIG_KASAN_SW_TAGS_IDENTIFY
> > -       for (i = 0; i < KASAN_NR_FREE_STACKS; i++) {
> > -               if (alloc_meta->free_pointer_tag[i] == tag)
> > -                       break;
> > -       }
> > -       if (i == KASAN_NR_FREE_STACKS)
> > -               i = alloc_meta->free_track_idx;
> > -#endif
> > -
> > -       return &alloc_meta->free_track[i];
> > -}
> > -
> >  #ifdef CONFIG_KASAN_GENERIC
> >  static void print_stack(depot_stack_handle_t stack)
> >  {
> > diff --git a/mm/kasan/tags.c b/mm/kasan/tags.c
> > index 25b7734e7013..201dee5d6ae0 100644
> > --- a/mm/kasan/tags.c
> > +++ b/mm/kasan/tags.c
> > @@ -162,3 +162,40 @@ void __hwasan_tag_memory(unsigned long addr, u8 tag, unsigned long size)
> >         kasan_poison_shadow((void *)addr, size, tag);
> >  }
> >  EXPORT_SYMBOL(__hwasan_tag_memory);
> > +
> > +void kasan_set_free_info(struct kmem_cache *cache,
> > +                               void *object, u8 tag)
> > +{
> > +       struct kasan_alloc_meta *alloc_meta;
> > +       u8 idx = 0;
> > +
> > +       alloc_meta = get_alloc_info(cache, object);
> > +
> > +#ifdef CONFIG_KASAN_SW_TAGS_IDENTIFY
> > +       idx = alloc_meta->free_track_idx;
> > +       alloc_meta->free_pointer_tag[idx] = tag;
> > +       alloc_meta->free_track_idx = (idx + 1) % KASAN_NR_FREE_STACKS;
> > +#endif
> > +
> > +       kasan_set_track(&alloc_meta->free_track[idx], GFP_NOWAIT);
> > +}
> > +
> > +struct kasan_track *kasan_get_free_track(struct kmem_cache *cache,
> > +                               void *object, u8 tag)
> > +{
> > +       struct kasan_alloc_meta *alloc_meta;
> > +       int i = 0;
> > +
> > +       alloc_meta = get_alloc_info(cache, object);
> > +
> > +#ifdef CONFIG_KASAN_SW_TAGS_IDENTIFY
> > +       for (i = 0; i < KASAN_NR_FREE_STACKS; i++) {
> > +               if (alloc_meta->free_pointer_tag[i] == tag)
> > +                       break;
> > +       }
> > +       if (i == KASAN_NR_FREE_STACKS)
> > +               i = alloc_meta->free_track_idx;
> > +#endif
> > +
> > +       return &alloc_meta->free_track[i];
> > +}
> > --
> > 2.18.0

_______________________________________________
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 v4 24/26] arm64: mte: Introduce early param to disable MTE support
From: Vladimir Murzin @ 2020-05-18 11:26 UTC (permalink / raw)
  To: Catalin Marinas, linux-arm-kernel
  Cc: linux-arch, Will Deacon, Szabolcs Nagy, Andrey Konovalov,
	Kevin Brodsky, linux-mm, Vincenzo Frascino, Peter Collingbourne,
	Dave P Martin
In-Reply-To: <20200515171612.1020-25-catalin.marinas@arm.com>

On 5/15/20 6:16 PM, Catalin Marinas wrote:
> For performance analysis it may be desirable to disable MTE altogether
> via an early param. Introduce arm64.mte_disable and, if true, filter out
> the sanitised ID_AA64PFR1_EL1.MTE field to avoid exposing the HWCAP to
> user.
> 
> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Will Deacon <will@kernel.org>
> ---
> 
> Notes:
>     New in v4.
> 
>  Documentation/admin-guide/kernel-parameters.txt |  4 ++++
>  arch/arm64/kernel/cpufeature.c                  | 11 +++++++++++
>  2 files changed, 15 insertions(+)
> 
> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> index f2a93c8679e8..7436e7462b85 100644
> --- a/Documentation/admin-guide/kernel-parameters.txt
> +++ b/Documentation/admin-guide/kernel-parameters.txt
> @@ -373,6 +373,10 @@
>  	arcrimi=	[HW,NET] ARCnet - "RIM I" (entirely mem-mapped) cards
>  			Format: <io>,<irq>,<nodeID>
>  
> +	arm64.mte_disable=
> +			[ARM64] Disable Linux support for the Memory
> +			Tagging Extension (both user and in-kernel).
> +

Should it really to take parameter (on/off/true/false)? It may lead to expectation
that arm64.mte_disable=false should enable MT and, yes, double negatives make it
look ugly, so if we do need parameter, can it be arm64.mte=on/off/true/false?

Cheers
Vladimir

_______________________________________________
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/2] mmc: host: meson-mx-sdhc: fix manual RX FIFO flushing
From: Ulf Hansson @ 2020-05-18 11:23 UTC (permalink / raw)
  To: Martin Blumenstingl
  Cc: open list:ARM/Amlogic Meson..., linux-mmc@vger.kernel.org,
	Linux Kernel Mailing List, Linux ARM, Thomas Graichen
In-Reply-To: <20200517222907.1277787-1-martin.blumenstingl@googlemail.com>

On Mon, 18 May 2020 at 00:29, Martin Blumenstingl
<martin.blumenstingl@googlemail.com> wrote:
>
> For Meson8 and Meson8b SoCs the vendor driver follows the following
> pattern:
> - for eMMC and SD cards in .set_pdma it sets:
>   pdma->rxfifo_manual_flush = 1;
> - for SDIO cards in .set_pdma it sets:
>   pdma->rxfifo_manual_flush = 0;
> - before syncing the DMA read buffer is sets:
>   pdma->rxfifo_manual_flush |= 0x02;
>
> Set the second bit of MESON_SDHC_PDMA_RXFIFO_MANUAL_FLUSH without
> clearing the first bit before syncing the DMA read buffer. This fixes a
> problem where Meson8 and Meson8b SoCs would read random garbage from SD
> cards. It is not clear why it worked for eMMC cards. This manifested in
> the following errors when plugging in an SD card:
>   unrecognised SCR structure version <random number>
>
> Fixes: 53ded1b676d199 ("mmc: host: meson-mx-sdhc: new driver for the Amlogic Meson SDHC host")
> Cc: Thomas Graichen <thomas.graichen@gmail.com>
> Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>

Applied for next, thanks!

Kind regards
Uffe


> ---
>  drivers/mmc/host/meson-mx-sdhc.c | 11 +++++++++--
>  1 file changed, 9 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/mmc/host/meson-mx-sdhc.c b/drivers/mmc/host/meson-mx-sdhc.c
> index 5c00958d7754..53e3f6a4245a 100644
> --- a/drivers/mmc/host/meson-mx-sdhc.c
> +++ b/drivers/mmc/host/meson-mx-sdhc.c
> @@ -586,10 +586,17 @@ static irqreturn_t meson_mx_sdhc_irq_thread(int irq, void *irq_data)
>                     cmd->data->flags & MMC_DATA_READ) {
>                         meson_mx_sdhc_wait_cmd_ready(host->mmc);
>
> +                       /*
> +                        * If MESON_SDHC_PDMA_RXFIFO_MANUAL_FLUSH was
> +                        * previously 0x1 then it has to be set to 0x3. If it
> +                        * was 0x0 before then it has to be set to 0x2. Without
> +                        * this reading SD cards sometimes transfers garbage,
> +                        * which results in cards not being detected due to:
> +                        *   unrecognised SCR structure version <random number>
> +                        */
>                         val = FIELD_PREP(MESON_SDHC_PDMA_RXFIFO_MANUAL_FLUSH,
>                                          2);
> -                       regmap_update_bits(host->regmap, MESON_SDHC_PDMA,
> -                                          MESON_SDHC_PDMA_RXFIFO_MANUAL_FLUSH,
> +                       regmap_update_bits(host->regmap, MESON_SDHC_PDMA, val,
>                                            val);
>                 }
>
> --
> 2.26.2
>

_______________________________________________
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 2/2] mmc: host: meson-mx-sdhc: don't use literal 0 to initialize structs
From: Ulf Hansson @ 2020-05-18 11:23 UTC (permalink / raw)
  To: Martin Blumenstingl
  Cc: open list:ARM/Amlogic Meson..., linux-mmc@vger.kernel.org,
	Linux Kernel Mailing List, Linux ARM, kbuild test robot
In-Reply-To: <20200517222907.1277787-2-martin.blumenstingl@googlemail.com>

On Mon, 18 May 2020 at 00:29, Martin Blumenstingl
<martin.blumenstingl@googlemail.com> wrote:
>
> Kbuild test robot reports the following warning in lines 56 and 87 of
> drivers/mmc/host/meson-mx-sdhc-clkc.c:
>   Using plain integer as NULL pointer
>
> Drop the integer value from the struct initialization to fix that
> warning. This will still ensure that the compiler will zero out the
> struct so it's in a well-defined state.
>
> Fixes: 53ded1b676d199 ("mmc: host: meson-mx-sdhc: new driver for the Amlogic Meson SDHC host")
> Reported-by: kbuild test robot <lkp@intel.com>
> Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>

Applied for next, thanks!

Kind regards
Uffe


> ---
>  drivers/mmc/host/meson-mx-sdhc-clkc.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/mmc/host/meson-mx-sdhc-clkc.c b/drivers/mmc/host/meson-mx-sdhc-clkc.c
> index ab0d6c68a078..e1f29b279123 100644
> --- a/drivers/mmc/host/meson-mx-sdhc-clkc.c
> +++ b/drivers/mmc/host/meson-mx-sdhc-clkc.c
> @@ -53,7 +53,7 @@ static int meson_mx_sdhc_clk_hw_register(struct device *dev,
>                                          const struct clk_ops *ops,
>                                          struct clk_hw *hw)
>  {
> -       struct clk_init_data init = { 0 };
> +       struct clk_init_data init = { };
>         char clk_name[32];
>
>         snprintf(clk_name, sizeof(clk_name), "%s#%s", dev_name(dev),
> @@ -84,7 +84,7 @@ static int meson_mx_sdhc_gate_clk_hw_register(struct device *dev,
>  int meson_mx_sdhc_register_clkc(struct device *dev, void __iomem *base,
>                                 struct clk_bulk_data *clk_bulk_data)
>  {
> -       struct clk_parent_data div_parent = { 0 };
> +       struct clk_parent_data div_parent = { };
>         struct meson_mx_sdhc_clkc *clkc_data;
>         int ret;
>
> --
> 2.26.2
>

_______________________________________________
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] mmc: host: meson-mx-sdhc: fix building with CONFIG_MMC_MESON_MX_SDHC=m
From: Ulf Hansson @ 2020-05-18 11:23 UTC (permalink / raw)
  To: Martin Blumenstingl
  Cc: open list:ARM/Amlogic Meson..., linux-mmc@vger.kernel.org,
	Linux Kernel Mailing List, Linux ARM, Stephen Rothwell
In-Reply-To: <20200518060811.1499962-1-martin.blumenstingl@googlemail.com>

On Mon, 18 May 2020 at 08:08, Martin Blumenstingl
<martin.blumenstingl@googlemail.com> wrote:
>
> For an x86_64 allmodconfig build Stephen reports that building
> meson-mx-sdhc-clkc.o warns that MODULE_LICENSE is missing and when
> linking meson_mx_sdhc_register_clkc cannot be found.
>
> Compile the MMC controller driver together with the build-in clock
> controller driver into one module rather than using two separate
> modules to fix these issues.
>
> Fixes: 53ded1b676d199 ("mmc: host: meson-mx-sdhc: new driver for the Amlogic Meson SDHC host")
> Reported-by: Stephen Rothwell <sfr@canb.auug.org.au>
> Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>

Applied for next, thanks!

Kind regards
Uffe


> ---
>  drivers/mmc/host/Makefile                                 | 3 ++-
>  drivers/mmc/host/{meson-mx-sdhc.c => meson-mx-sdhc-mmc.c} | 0
>  2 files changed, 2 insertions(+), 1 deletion(-)
>  rename drivers/mmc/host/{meson-mx-sdhc.c => meson-mx-sdhc-mmc.c} (100%)
>
> diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
> index 8bcb420e071c..8f459259181e 100644
> --- a/drivers/mmc/host/Makefile
> +++ b/drivers/mmc/host/Makefile
> @@ -68,7 +68,8 @@ obj-$(CONFIG_MMC_VUB300)      += vub300.o
>  obj-$(CONFIG_MMC_USHC)         += ushc.o
>  obj-$(CONFIG_MMC_WMT)          += wmt-sdmmc.o
>  obj-$(CONFIG_MMC_MESON_GX)     += meson-gx-mmc.o
> -obj-$(CONFIG_MMC_MESON_MX_SDHC)        += meson-mx-sdhc-clkc.o meson-mx-sdhc.o
> +meson-mx-sdhc-objs             := meson-mx-sdhc-clkc.o meson-mx-sdhc-mmc.o
> +obj-$(CONFIG_MMC_MESON_MX_SDHC)        += meson-mx-sdhc.o
>  obj-$(CONFIG_MMC_MESON_MX_SDIO)        += meson-mx-sdio.o
>  obj-$(CONFIG_MMC_MOXART)       += moxart-mmc.o
>  obj-$(CONFIG_MMC_SUNXI)                += sunxi-mmc.o
> diff --git a/drivers/mmc/host/meson-mx-sdhc.c b/drivers/mmc/host/meson-mx-sdhc-mmc.c
> similarity index 100%
> rename from drivers/mmc/host/meson-mx-sdhc.c
> rename to drivers/mmc/host/meson-mx-sdhc-mmc.c
> --
> 2.26.2
>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* [PATCH] drm/mediatek: Delete not used of_device_get_match_data
From: matthias.bgg @ 2020-05-18 11:22 UTC (permalink / raw)
  To: chunkuang.hu, p.zabel, airlied, daniel
  Cc: linux-kernel, dri-devel, Matthias Brugger, linux-mediatek,
	matthias.bgg, enric.balletbo, linux-arm-kernel

From: Matthias Brugger <matthias.bgg@gmail.com>

The driver will be loaded by via a platform device. So we
will need to get the device_node from the parent device.
Depending on this we will set the driver data.
As all this is done later already, just delete the call to
of_device_get_match_data.

Signed-off-by: Matthias Brugger <matthias.bgg@gmail.com>
---
 drivers/gpu/drm/mediatek/mtk_drm_drv.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index e2bb0d19ef99..63ec92ba0e92 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -447,7 +447,6 @@ static int mtk_drm_probe(struct platform_device *pdev)
 	if (!private)
 		return -ENOMEM;
 
-	private->data = of_device_get_match_data(dev);
 	private->mmsys_dev = dev->parent;
 	if (!private->mmsys_dev) {
 		dev_err(dev, "Failed to get MMSYS device\n");
-- 
2.26.2


_______________________________________________
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/3] arm64: perf: Add support for Perf NMI interrupts
From: Alexandru Elisei @ 2020-05-18 11:17 UTC (permalink / raw)
  To: Mark Rutland, Lecopzer Chen
  Cc: Sumit Garg, Jian-Lin Chen, Will Deacon, alexander.shishkin,
	Catalin Marinas, yj.chiang, Linux Kernel Mailing List, acme,
	Peter Zijlstra, mingo, linux-mediatek, linux-arm-kernel,
	matthias.bgg, namhyung, jolsa, julien.thierry.kdev
In-Reply-To: <20200518104524.GA1224@C02TD0UTHF1T.local>

Hi,

On 5/18/20 11:45 AM, Mark Rutland wrote:
> Hi all,
>
> On Mon, May 18, 2020 at 02:26:00PM +0800, Lecopzer Chen wrote:
>> HI Sumit,
>>
>> Thanks for your information.
>>
>> I've already implemented IPI (same as you did [1], little difference
>> in detail), hardlockup detector and perf in last year(2019) for
>> debuggability.
>> And now we tend to upstream to reduce kernel maintaining effort.
>> I'm glad if someone in ARM can do this work :)
>>
>> Hi Julien,
>>
>> Does any Arm maintainers can proceed this action?
> Alexandru (Cc'd) has been rebasing and reworking Julien's patches, which
> is my preferred approach.
>
> I understand that's not quite ready for posting since he's investigating
> some of the nastier subtleties (e.g. mutual exclusion with the NMI), but
> maybe we can put the work-in-progress patches somewhere in the mean
> time.
>
> Alexandru, do you have an idea of what needs to be done, and/or when you
> expect you could post that?

I'm currently working on rebasing the patches on top of 5.7-rc5, when I have
something usable I'll post a link (should be a couple of days). After that I will
address the review comments, and I plan to do a thorough testing because I'm not
100% confident that some of the assumptions around the locks that were removed are
correct. My guess is this will take a few weeks.

Thanks,
Alex
>
> Thanks,
> Mark.
>
>> This is really useful in debugging.
>> Thank you!!
>>
>>
>>
>> [1] https://lkml.org/lkml/2020/4/24/328
>>
>>
>> Lecopzer
>>
>> Sumit Garg <sumit.garg@linaro.org> 於 2020年5月18日 週一 下午1:46寫道:
>>> + Julien
>>>
>>> Hi Lecopzer,
>>>
>>> On Sat, 16 May 2020 at 18:20, Lecopzer Chen <lecopzer@gmail.com> wrote:
>>>> These series implement Perf NMI funxtionality and depends on
>>>> Pseudo NMI [1] which has been upstreamed.
>>>>
>>>> In arm64 with GICv3, Pseudo NMI was implemented for NMI-like interruts.
>>>> That can be extended to Perf NMI which is the prerequisite for hard-lockup
>>>> detector which had already a standard interface inside Linux.
>>>>
>>>> Thus the first step we need to implement perf NMI interface and make sure
>>>> it works fine.
>>>>
>>> This is something that is already implemented via Julien's patch-set
>>> [1]. Its v4 has been floating since July, 2019 and I couldn't find any
>>> major blocking comments but not sure why things haven't progressed
>>> further.
>>>
>>> Maybe Julien or Arm maintainers can provide updates on existing
>>> patch-set [1] and how we should proceed further with this interesting
>>> feature.
>>>
>>> And regarding hard-lockup detection, I have been able to enable it
>>> based on perf NMI events using Julien's perf patch-set [1]. Have a
>>> look at the patch here [2].
>>>
>>> [1] https://patchwork.kernel.org/cover/11047407/
>>> [2] http://lists.infradead.org/pipermail/linux-arm-kernel/2020-May/732227.html
>>>
>>> -Sumit
>>>
>>>> Perf NMI has been test by dd if=/dev/urandom of=/dev/null like the link [2]
>>>> did.
>>>>
>>>> [1] https://lkml.org/lkml/2019/1/31/535
>>>> [2] https://www.linaro.org/blog/debugging-arm-kernels-using-nmifiq
>>>>
>>>>
>>>> Lecopzer Chen (3):
>>>>   arm_pmu: Add support for perf NMI interrupts registration
>>>>   arm64: perf: Support NMI context for perf event ISR
>>>>   arm64: Kconfig: Add support for the Perf NMI
>>>>
>>>>  arch/arm64/Kconfig             | 10 +++++++
>>>>  arch/arm64/kernel/perf_event.c | 36 ++++++++++++++++++------
>>>>  drivers/perf/arm_pmu.c         | 51 ++++++++++++++++++++++++++++++----
>>>>  include/linux/perf/arm_pmu.h   |  6 ++++
>>>>  4 files changed, 88 insertions(+), 15 deletions(-)
>>>>
>>>> --
>>>> 2.25.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 v4 00/14] Add PCIe support to TI's J721E SoC
From: Kishon Vijay Abraham I @ 2020-05-18 11:14 UTC (permalink / raw)
  To: Bjorn Helgaas, Rob Herring, Lorenzo Pieralisi, Arnd Bergmann,
	Tom Joseph
  Cc: devicetree, Greg Kroah-Hartman, linux-kernel, linux-pci,
	linux-omap, linux-arm-kernel
In-Reply-To: <20200506151429.12255-1-kishon@ti.com>

Hi Lorenzo, RobH

On 5/6/2020 8:44 PM, Kishon Vijay Abraham I wrote:
> TI's J721E SoC uses Cadence PCIe core to implement both RC mode
> and EP mode.
> 
> The high level features are:
>   *) Supports Legacy, MSI and MSI-X interrupt
>   *) Supports upto GEN4 speed mode
>   *) Supports SR-IOV
>   *) Supports multiple physical function
>   *) Ability to route all transactions via SMMU
> 
> This patch series
>   *) Add support in Cadence PCIe core to be used for TI's J721E SoC
>   *) Add a driver for J721E PCIe wrapper

Do you have any other comments on this series? I'm hoping this gets merged for 5.8.

Thanks
Kishon

> 
> v1 of the series can be found @ [1]
> v2 of the series can be found @ [2]
> v3 of the series can be found @ [5]
> 
> Changes from v3:
> 1) Changed the order of files in MAINTAINTERS file to fix Joe's comments
> 2) Fixed indentation and added Reviewed-by: Rob Herring <robh@kernel.org>
> 3) Cleaned up computing msix_tbl
> 4) Fixed RobH's comment on J721E driver
> 
> Changes from v2:
> 1) Converting Cadence binding to YAML schema was done as a 
>    separate series [3] & [4]. [3] is merged and [4] is
>    pending.
> 2) Included MSI-X support in this series
> 3) Added link down interrupt handling (only error message)
> 4) Rebased to latest 5.7-rc1
> 5) Adapted TI J721E binding to [3] & [4] 
> 
> Changes from v1:
> 1) Added DT schemas cdns-pcie-host.yaml, cdns-pcie-ep.yaml and
>    cdns-pcie.yaml for Cadence PCIe core and included it in
>    TI's PCIe DT schema.
> 2) Added cpu_addr_fixup() for Cadence Platform driver.
> 3) Fixed subject/description/renamed functions as commented by
>    Andrew Murray.
> 
> [1] -> http://lore.kernel.org/r/20191209092147.22901-1-kishon@ti.com
> [2] -> http://lore.kernel.org/r/20200106102058.19183-1-kishon@ti.com
> [3] -> http://lore.kernel.org/r/20200305103017.16706-1-kishon@ti.com
> [4] -> http://lore.kernel.org/r/20200417114322.31111-1-kishon@ti.com
> [5] -> http://lore.kernel.org/r/20200417125753.13021-1-kishon@ti.com
> 
> Alan Douglas (1):
>   PCI: cadence: Add MSI-X support to Endpoint driver
> 
> Kishon Vijay Abraham I (13):
>   PCI: cadence: Fix cdns_pcie_{host|ep}_setup() error path
>   linux/kernel.h: Add PTR_ALIGN_DOWN macro
>   PCI: cadence: Add support to use custom read and write accessors
>   PCI: cadence: Add support to start link and verify link status
>   PCI: cadence: Add read/write accessors to perform only 32-bit accesses
>   PCI: cadence: Allow pci_host_bridge to have custom pci_ops
>   PCI: cadence: Add new *ops* for CPU addr fixup
>   PCI: cadence: Fix updating Vendor ID and Subsystem Vendor ID register
>   dt-bindings: PCI: Add host mode dt-bindings for TI's J721E SoC
>   dt-bindings: PCI: Add EP mode dt-bindings for TI's J721E SoC
>   PCI: j721e: Add TI J721E PCIe driver
>   misc: pci_endpoint_test: Add J721E in pci_device_id table
>   MAINTAINERS: Add Kishon Vijay Abraham I for TI J721E SoC PCIe
> 
>  .../bindings/pci/ti,j721e-pci-ep.yaml         |  89 ++++
>  .../bindings/pci/ti,j721e-pci-host.yaml       | 113 ++++
>  MAINTAINERS                                   |   4 +-
>  drivers/misc/pci_endpoint_test.c              |   9 +
>  drivers/pci/controller/cadence/Kconfig        |  23 +
>  drivers/pci/controller/cadence/Makefile       |   1 +
>  drivers/pci/controller/cadence/pci-j721e.c    | 492 ++++++++++++++++++
>  .../pci/controller/cadence/pcie-cadence-ep.c  | 125 ++++-
>  .../controller/cadence/pcie-cadence-host.c    |  59 ++-
>  .../controller/cadence/pcie-cadence-plat.c    |  13 +
>  drivers/pci/controller/cadence/pcie-cadence.c |  48 +-
>  drivers/pci/controller/cadence/pcie-cadence.h | 158 +++++-
>  include/linux/kernel.h                        |   1 +
>  13 files changed, 1093 insertions(+), 42 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/pci/ti,j721e-pci-ep.yaml
>  create mode 100644 Documentation/devicetree/bindings/pci/ti,j721e-pci-host.yaml
>  create mode 100644 drivers/pci/controller/cadence/pci-j721e.c
> 

_______________________________________________
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 v3 4/4] PCI: cadence: Use "dma-ranges" instead of "cdns,no-bar-match-nbits" property
From: Kishon Vijay Abraham I @ 2020-05-18 11:12 UTC (permalink / raw)
  To: Bjorn Helgaas, Rob Herring, Lorenzo Pieralisi, Robin Murphy,
	Tom Joseph
  Cc: linux-pci, linux-kernel, linux-arm-kernel, devicetree
In-Reply-To: <20200508130646.23939-5-kishon@ti.com>

Hi RobH, Robin,

On 5/8/2020 6:36 PM, Kishon Vijay Abraham I wrote:
> Cadence PCIe core driver (host mode) uses "cdns,no-bar-match-nbits"
> property to configure the number of bits passed through from PCIe
> address to internal address in Inbound Address Translation register.
> This only used the NO MATCH BAR.
> 
> However standard PCI dt-binding already defines "dma-ranges" to
> describe the address ranges accessible by PCIe controller. Add support
> in Cadence PCIe host driver to parse dma-ranges and configure the
> inbound regions for BAR0, BAR1 and NO MATCH BAR. Cadence IP specifies
> maximum size for BAR0 as 256GB, maximum size for BAR1 as 2 GB, so if
> the dma-ranges specifies a size larger than the maximum allowed, the
> driver will split and configure the BARs.
> 
> Legacy device tree binding compatibility is maintained by retaining
> support for "cdns,no-bar-match-nbits".

Do you have any comments for this patch?

Tom,

where you able to test this in Cadence platform?

Thanks
Kishon

> 
> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
> ---
>  .../controller/cadence/pcie-cadence-host.c    | 141 ++++++++++++++++--
>  drivers/pci/controller/cadence/pcie-cadence.h |  17 ++-
>  2 files changed, 141 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/pci/controller/cadence/pcie-cadence-host.c b/drivers/pci/controller/cadence/pcie-cadence-host.c
> index 6ecebb79057a..2485ecd8434d 100644
> --- a/drivers/pci/controller/cadence/pcie-cadence-host.c
> +++ b/drivers/pci/controller/cadence/pcie-cadence-host.c
> @@ -11,6 +11,12 @@
>  
>  #include "pcie-cadence.h"
>  
> +static u64 cdns_rp_bar_max_size[] = {
> +	[RP_BAR0] = _ULL(128 * SZ_2G),
> +	[RP_BAR1] = SZ_2G,
> +	[RP_NO_BAR] = SZ_64T,
> +};
> +
>  void __iomem *cdns_pci_map_bus(struct pci_bus *bus, unsigned int devfn,
>  			       int where)
>  {
> @@ -106,6 +112,117 @@ static int cdns_pcie_host_init_root_port(struct cdns_pcie_rc *rc)
>  	return 0;
>  }
>  
> +static void cdns_pcie_host_bar_ib_config(struct cdns_pcie_rc *rc,
> +					 enum cdns_pcie_rp_bar bar,
> +					 u64 cpu_addr, u32 aperture)
> +{
> +	struct cdns_pcie *pcie = &rc->pcie;
> +	u32 addr0, addr1;
> +
> +	addr0 = CDNS_PCIE_AT_IB_RP_BAR_ADDR0_NBITS(aperture) |
> +		(lower_32_bits(cpu_addr) & GENMASK(31, 8));
> +	addr1 = upper_32_bits(cpu_addr);
> +	cdns_pcie_writel(pcie, CDNS_PCIE_AT_IB_RP_BAR_ADDR0(bar), addr0);
> +	cdns_pcie_writel(pcie, CDNS_PCIE_AT_IB_RP_BAR_ADDR1(bar), addr1);
> +}
> +
> +static int cdns_pcie_host_bar_config(struct cdns_pcie_rc *rc,
> +				     struct resource_entry *entry,
> +				     enum cdns_pcie_rp_bar *index)
> +{
> +	u64 cpu_addr, pci_addr, size, winsize;
> +	struct cdns_pcie *pcie = &rc->pcie;
> +	struct device *dev = pcie->dev;
> +	enum cdns_pcie_rp_bar bar;
> +	unsigned long flags;
> +	u32 aperture;
> +	u32 value;
> +
> +	cpu_addr = entry->res->start;
> +	flags = entry->res->flags;
> +	pci_addr = entry->res->start - entry->offset;
> +	size = resource_size(entry->res);
> +	bar = *index;
> +
> +	if (entry->offset) {
> +		dev_err(dev, "Cannot map PCI addr: %llx to CPU addr: %llx\n",
> +			pci_addr, cpu_addr);
> +		return -EINVAL;
> +	}
> +
> +	value = cdns_pcie_readl(pcie, CDNS_PCIE_LM_RC_BAR_CFG);
> +	while (size > 0) {
> +		if (bar > RP_NO_BAR) {
> +			dev_err(dev, "Failed to map inbound regions!\n");
> +			return -EINVAL;
> +		}
> +
> +		winsize = size;
> +		if (size > cdns_rp_bar_max_size[bar])
> +			winsize = cdns_rp_bar_max_size[bar];
> +
> +		aperture = ilog2(winsize);
> +
> +		cdns_pcie_host_bar_ib_config(rc, bar, cpu_addr, aperture);
> +
> +		if (bar == RP_NO_BAR)
> +			break;
> +
> +		if (winsize + cpu_addr >= SZ_4G) {
> +			if (!(flags & IORESOURCE_PREFETCH))
> +				value |= LM_RC_BAR_CFG_CTRL_MEM_64BITS(bar);
> +			value |= LM_RC_BAR_CFG_CTRL_PREF_MEM_64BITS(bar);
> +		} else {
> +			if (!(flags & IORESOURCE_PREFETCH))
> +				value |= LM_RC_BAR_CFG_CTRL_MEM_32BITS(bar);
> +			value |= LM_RC_BAR_CFG_CTRL_PREF_MEM_32BITS(bar);
> +		}
> +
> +		value |= LM_RC_BAR_CFG_APERTURE(bar, aperture);
> +
> +		size -= winsize;
> +		cpu_addr += winsize;
> +		bar++;
> +	}
> +	cdns_pcie_writel(pcie, CDNS_PCIE_LM_RC_BAR_CFG, value);
> +	*index = bar;
> +
> +	return 0;
> +}
> +
> +static int cdns_pcie_host_map_dma_ranges(struct cdns_pcie_rc *rc)
> +{
> +	enum cdns_pcie_rp_bar bar = RP_BAR0;
> +	struct cdns_pcie *pcie = &rc->pcie;
> +	struct device *dev = pcie->dev;
> +	struct device_node *np = dev->of_node;
> +	struct pci_host_bridge *bridge;
> +	struct resource_entry *entry;
> +	u32 no_bar_nbits = 32;
> +	int err;
> +
> +	bridge = pci_host_bridge_from_priv(rc);
> +	if (!bridge)
> +		return -ENOMEM;
> +
> +	if (list_empty(&bridge->dma_ranges)) {
> +		of_property_read_u32(np, "cdns,no-bar-match-nbits",
> +				     &no_bar_nbits);
> +		cdns_pcie_host_bar_ib_config(rc, RP_NO_BAR, 0x0, no_bar_nbits);
> +		return 0;
> +	}
> +
> +	resource_list_for_each_entry(entry, &bridge->dma_ranges) {
> +		err = cdns_pcie_host_bar_config(rc, entry, &bar);
> +		if (err) {
> +			dev_err(dev, "Fail to configure IB using dma-ranges\n");
> +			return err;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
>  static int cdns_pcie_host_init_address_translation(struct cdns_pcie_rc *rc)
>  {
>  	struct cdns_pcie *pcie = &rc->pcie;
> @@ -160,16 +277,9 @@ static int cdns_pcie_host_init_address_translation(struct cdns_pcie_rc *rc)
>  		r++;
>  	}
>  
> -	/*
> -	 * Set Root Port no BAR match Inbound Translation registers:
> -	 * needed for MSI and DMA.
> -	 * Root Port BAR0 and BAR1 are disabled, hence no need to set their
> -	 * inbound translation registers.
> -	 */
> -	addr0 = CDNS_PCIE_AT_IB_RP_BAR_ADDR0_NBITS(rc->no_bar_nbits);
> -	addr1 = 0;
> -	cdns_pcie_writel(pcie, CDNS_PCIE_AT_IB_RP_BAR_ADDR0(RP_NO_BAR), addr0);
> -	cdns_pcie_writel(pcie, CDNS_PCIE_AT_IB_RP_BAR_ADDR1(RP_NO_BAR), addr1);
> +	err = cdns_pcie_host_map_dma_ranges(rc);
> +	if (err)
> +		return err;
>  
>  	return 0;
>  }
> @@ -179,10 +289,16 @@ static int cdns_pcie_host_init(struct device *dev,
>  			       struct cdns_pcie_rc *rc)
>  {
>  	struct resource *bus_range = NULL;
> +	struct pci_host_bridge *bridge;
>  	int err;
>  
> +	bridge = pci_host_bridge_from_priv(rc);
> +	if (!bridge)
> +		return -ENOMEM;
> +
>  	/* Parse our PCI ranges and request their resources */
> -	err = pci_parse_request_of_pci_ranges(dev, resources, NULL, &bus_range);
> +	err = pci_parse_request_of_pci_ranges(dev, resources,
> +					      &bridge->dma_ranges, &bus_range);
>  	if (err)
>  		return err;
>  
> @@ -239,9 +355,6 @@ int cdns_pcie_host_setup(struct cdns_pcie_rc *rc)
>  	pcie = &rc->pcie;
>  	pcie->is_rc = true;
>  
> -	rc->no_bar_nbits = 32;
> -	of_property_read_u32(np, "cdns,no-bar-match-nbits", &rc->no_bar_nbits);
> -
>  	rc->vendor_id = 0xffff;
>  	of_property_read_u32(np, "vendor-id", &rc->vendor_id);
>  
> diff --git a/drivers/pci/controller/cadence/pcie-cadence.h b/drivers/pci/controller/cadence/pcie-cadence.h
> index f349f5828a58..336237a7025c 100644
> --- a/drivers/pci/controller/cadence/pcie-cadence.h
> +++ b/drivers/pci/controller/cadence/pcie-cadence.h
> @@ -92,6 +92,20 @@
>  #define  CDNS_PCIE_LM_BAR_CFG_CTRL_MEM_64BITS		0x6
>  #define  CDNS_PCIE_LM_BAR_CFG_CTRL_PREFETCH_MEM_64BITS	0x7
>  
> +#define LM_RC_BAR_CFG_CTRL_DISABLED(bar)		\
> +		(CDNS_PCIE_LM_BAR_CFG_CTRL_DISABLED << (((bar) * 8) + 6))
> +#define LM_RC_BAR_CFG_CTRL_IO_32BITS(bar)		\
> +		(CDNS_PCIE_LM_BAR_CFG_CTRL_IO_32BITS << (((bar) * 8) + 6))
> +#define LM_RC_BAR_CFG_CTRL_MEM_32BITS(bar)		\
> +		(CDNS_PCIE_LM_BAR_CFG_CTRL_MEM_32BITS << (((bar) * 8) + 6))
> +#define LM_RC_BAR_CFG_CTRL_PREF_MEM_32BITS(bar)	\
> +	(CDNS_PCIE_LM_BAR_CFG_CTRL_PREFETCH_MEM_32BITS << (((bar) * 8) + 6))
> +#define LM_RC_BAR_CFG_CTRL_MEM_64BITS(bar)		\
> +		(CDNS_PCIE_LM_BAR_CFG_CTRL_MEM_64BITS << (((bar) * 8) + 6))
> +#define LM_RC_BAR_CFG_CTRL_PREF_MEM_64BITS(bar)	\
> +	(CDNS_PCIE_LM_BAR_CFG_CTRL_PREFETCH_MEM_64BITS << (((bar) * 8) + 6))
> +#define LM_RC_BAR_CFG_APERTURE(bar, aperture)		\
> +					(((aperture) - 2) << ((bar) * 8))
>  
>  /*
>   * Endpoint Function Registers (PCI configuration space for endpoint functions)
> @@ -266,8 +280,6 @@ struct cdns_pcie {
>   * @bus_range: first/last buses behind the PCIe host controller
>   * @cfg_base: IO mapped window to access the PCI configuration space of a
>   *            single function at a time
> - * @no_bar_nbits: Number of bits to keep for inbound (PCIe -> CPU) address
> - *                translation (nbits sets into the "no BAR match" register)
>   * @vendor_id: PCI vendor ID
>   * @device_id: PCI device ID
>   */
> @@ -276,7 +288,6 @@ struct cdns_pcie_rc {
>  	struct resource		*cfg_res;
>  	struct resource		*bus_range;
>  	void __iomem		*cfg_base;
> -	u32			no_bar_nbits;
>  	u32			vendor_id;
>  	u32			device_id;
>  };
> 

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* [PATCH v4 8/8] drm/panel: Add ilitek ili9341 panel driver
From: dillon.minfei @ 2020-05-18 11:09 UTC (permalink / raw)
  To: robh+dt, p.zabel, mcoquelin.stm32, broonie, devicetree,
	alexandre.torgue, thierry.reding, sam, airlied, daniel,
	mturquette, sboyd
  Cc: linux-kernel, dri-devel, linux-stm32, linux-spi, dillon min,
	linux-clk, linux-arm-kernel
In-Reply-To: <1589800165-3271-1-git-send-email-dillon.minfei@gmail.com>

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=y, Size: 42888 bytes --]

From: dillon min <dillon.minfei@gmail.com>

This driver combine tiny/ili9341.c mipi_dbi_interface driver
with mipi_dpi_interface driver, can support ili9341 with serial
mode or parallel rgb interface mode by register configuration.

Signed-off-by: dillon min <dillon.minfei@gmail.com>
---

Changes since V3:

accoding to Linus Walleij's suggestion.
1 add more comments to driver.
2 reduce magic number usage in the driver.
3 move panel configuration from common place to system configuration.
4 reuse MIPI_DCS_* as more as possible.
---
 drivers/gpu/drm/panel/Kconfig                |   12 +
 drivers/gpu/drm/panel/Makefile               |    1 +
 drivers/gpu/drm/panel/panel-ilitek-ili9341.c | 1301 ++++++++++++++++++++++++++
 3 files changed, 1314 insertions(+)
 create mode 100644 drivers/gpu/drm/panel/panel-ilitek-ili9341.c

diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index a1723c1..c938bee 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -95,6 +95,18 @@ config DRM_PANEL_ILITEK_IL9322
 	  Say Y here if you want to enable support for Ilitek IL9322
 	  QVGA (320x240) RGB, YUV and ITU-T BT.656 panels.
 
+config DRM_PANEL_ILITEK_ILI9341
+	tristate "Ilitek ILI9341 240x320 QVGA panels"
+	depends on OF && SPI
+	depends on DRM_KMS_HELPER
+	depends on DRM_KMS_CMA_HELPER
+	depends on BACKLIGHT_CLASS_DEVICE
+	select DRM_MIPI_DBI
+	help
+	  Say Y here if you want to enable support for Ilitek IL9341
+	  QVGA (240x320) RGB panels. support serial & parallel rgb
+	  interface.
+
 config DRM_PANEL_ILITEK_ILI9881C
 	tristate "Ilitek ILI9881C-based panels"
 	depends on OF
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index 96a883c..16947d7 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_DRM_PANEL_ELIDA_KD35T133) += panel-elida-kd35t133.o
 obj-$(CONFIG_DRM_PANEL_FEIXIN_K101_IM2BA02) += panel-feixin-k101-im2ba02.o
 obj-$(CONFIG_DRM_PANEL_FEIYANG_FY07024DI26A30D) += panel-feiyang-fy07024di26a30d.o
 obj-$(CONFIG_DRM_PANEL_ILITEK_IL9322) += panel-ilitek-ili9322.o
+obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9341) += panel-ilitek-ili9341.o
 obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9881C) += panel-ilitek-ili9881c.o
 obj-$(CONFIG_DRM_PANEL_INNOLUX_P079ZCA) += panel-innolux-p079zca.o
 obj-$(CONFIG_DRM_PANEL_JDI_LT070ME05000) += panel-jdi-lt070me05000.o
diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9341.c b/drivers/gpu/drm/panel/panel-ilitek-ili9341.c
new file mode 100644
index 0000000..dd6f860
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-ilitek-ili9341.c
@@ -0,0 +1,1301 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Ilitek ILI9341 TFT LCD drm_panel driver.
+ *
+ * This panel can be configured to support:
+ * - 16-bit parallel RGB interface
+ * - 18-bit parallel RGB interface
+ * - 4-line serial spi interface
+ *
+ * Copyright (C) 2020 Dillon Min <dillon.minfei@gmail.com>
+ * Derived from drivers/drm/gpu/panel/panel-ilitek-ili9322.c
+ */
+
+#include <linux/bitops.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/spi/spi.h>
+#include <linux/delay.h>
+#include <video/mipi_display.h>
+#include <drm/drm_mipi_dbi.h>
+#include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_atomic_helper.h>
+
+#include <drm/drm_drv.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_print.h>
+
+#define ILI9341_RGB_INTERFACE  0xb0   /* RGB Interface Signal Control */
+#define ILI9341_FRC            0xb1   /* Frame Rate Control register */
+#define ILI9341_DFC            0xb6   /* Display Function Control register */
+#define ILI9341_POWER1         0xc0   /* Power Control 1 register */
+#define ILI9341_POWER2         0xc1   /* Power Control 2 register */
+#define ILI9341_VCOM1          0xc5   /* VCOM Control 1 register */
+#define ILI9341_VCOM2          0xc7   /* VCOM Control 2 register */
+#define ILI9341_POWERA         0xcb   /* Power control A register */
+#define ILI9341_POWERB         0xcf   /* Power control B register */
+#define ILI9341_PGAMMA         0xe0   /* Positive Gamma Correction register */
+#define ILI9341_NGAMMA         0xe1   /* Negative Gamma Correction register */
+#define ILI9341_DTCA           0xe8   /* Driver timing control A */
+#define ILI9341_DTCB           0xea   /* Driver timing control B */
+#define ILI9341_POWER_SEQ      0xed   /* Power on sequence register */
+#define ILI9341_3GAMMA_EN      0xf2   /* 3 Gamma enable register */
+#define ILI9341_INTERFACE      0xf6   /* Interface control register */
+#define ILI9341_PRC            0xf7   /* Pump ratio control register */
+#define ILI9341_ETMOD	       0xb7   /* Entry mode set */
+
+#define ILI9341_MADCTL_BGR	BIT(3)
+#define ILI9341_MADCTL_MV	BIT(5)
+#define ILI9341_MADCTL_MX	BIT(6)
+#define ILI9341_MADCTL_MY	BIT(7)
+
+
+#define ILI9341_POWER_B_LEN	3
+#define ILI9341_POWER_SEQ_LEN	4
+#define ILI9341_DTCA_LEN	3
+#define ILI9341_DTCB_LEN	2
+#define ILI9341_POWER_A_LEN	5
+#define ILI9341_DFC_1_LEN	2
+#define ILI9341_FRC_LEN		2
+#define ILI9341_VCOM_1_LEN	2
+#define ILI9341_DFC_2_LEN	4
+#define ILI9341_COLUMN_ADDR_LEN	4
+#define ILI9341_PAGE_ADDR_LEN	4
+#define ILI9341_INTERFACE_LEN	3
+#define ILI9341_PGAMMA_LEN	15
+#define ILI9341_NGAMMA_LEN	15
+#define ILI9341_CA_LEN		3
+
+#define ILI9341_PIXEL_DPI_16_BITS	(BIT(6)|BIT(4))
+#define ILI9341_PIXEL_DPI_18_BITS	(BIT(6)|BIT(5))
+#define ILI9341_GAMMA_CURVE_1		BIT(0)
+#define ILI9341_IF_WE_MODE		BIT(0)
+#define ILI9341_IF_BIG_ENDIAN		0x00
+#define ILI9341_IF_DM_RGB		BIT(2)
+#define ILI9341_IF_DM_INTERNAL		0x00
+#define ILI9341_IF_DM_VSYNC		BIT(3)
+#define ILI9341_IF_RM_RGB		BIT(1)
+#define ILI9341_IF_RIM_RGB		0x00
+
+#define ILI9341_COLUMN_ADDR		0x00ef
+#define ILI9341_PAGE_ADDR		0x013f
+
+#define ILI9341_RGB_EPL			BIT(0)
+#define ILI9341_RGB_DPL			BIT(1)
+#define ILI9341_RGB_HSPL		BIT(2)
+#define ILI9341_RGB_VSPL		BIT(3)
+#define ILI9341_RGB_DE_MODE		BIT(6)
+#define ILI9341_RGB_DISP_PATH_MEM	BIT(7)
+
+#define ILI9341_DBI_VCOMH_4P6V		0x23
+#define ILI9341_DBI_PWR_2_DEFAULT	0x10
+#define ILI9341_DBI_PRC_NORMAL		0x20
+#define ILI9341_DBI_VCOM_1_VMH_4P25V	0x3e
+#define ILI9341_DBI_VCOM_1_VML_1P5V	0x28
+#define ILI9341_DBI_VCOM_2_DEC_58	0x86
+#define ILI9341_DBI_FRC_DIVA		0x00
+#define ILI9341_DBI_FRC_RTNA		0x1b
+#define ILI9341_DBI_EMS_GAS		BIT(0)
+#define ILI9341_DBI_EMS_DTS		BIT(1)
+#define ILI9341_DBI_EMS_GON		BIT(2)
+/**
+ * ili9341_command - ili9341 command with optional parameter(s)
+ * @ili: struct ili9341
+ * @cmd: Command
+ * @seq...: Optional parameter(s)
+ *
+ * Send command to the controller.
+ *
+ * Returns:
+ * Zero on success, negative error code on failure.
+ */
+#define ili9341_command(ili, cmd, seq...) \
+({ \
+	u8 d[] = { seq }; \
+	_ili9341_command(ili, cmd, d, ARRAY_SIZE(d)); \
+})
+
+/**
+ * struct ili9341_config - the system specific ILI9341 configuration
+ * @max_spi_speed: 10000000
+ */
+struct ili9341_config {
+	u32 max_spi_speed;
+
+	const struct drm_display_mode mode;
+	/* TODO: need comments for this register */
+	u8 ca[ILI9341_CA_LEN];
+	/* TODO: need comments for this register */
+	u8 power_b[ILI9341_POWER_B_LEN];
+	/* TODO: need comments for this register */
+	u8 power_seq[ILI9341_POWER_SEQ_LEN];
+	/* TODO: need comments for this register */
+	u8 dtca[ILI9341_DTCA_LEN];
+	/* TODO: need comments for this register */
+	u8 dtcb[ILI9341_DTCB_LEN];
+	/* TODO: need comments for this register */
+	u8 power_a[ILI9341_POWER_A_LEN];
+	/*
+	 * Frame Rate Control (In Normal Mode/Full Colors) (B1h)
+	 *
+	 * Formula to calculate frame frequency:
+	 * Frame Rate=fosc/(Clocks per line x Division ratio x
+	 * (Lines+VBP+VFP))
+	 *
+	 * Sets the division ratio for internal clocks of Normal mode at MCU
+	 * interface.
+	 *
+	 * fosc : internal oscillator frequency
+	 * Clocks per line : RTNA setting
+	 * Division ratio : DIVA setting
+	 * Lines : total driving line number
+	 * VBP : back porch line number
+	 * VFP : front porch line number
+	 *
+	 * RTNA [4:0] Frame Rate (Hz)   RTNA [4:0] Frame Rate (Hz)
+	 * 1 0 0 0 0  119		1 1 0 0 0  79
+	 * 1 0 0 0 1  112		1 1 0 0 1  76
+	 * 1 0 0 1 0  106		1 1 0 1 0  73
+	 * 1 0 0 1 1  100		1 1 0 1 1  70(default)
+	 * 1 0 1 0 0  95		1 1 1 0 0  68
+	 * 1 0 1 0 1  90		1 1 1 0 1  65
+	 * 1 0 1 1 0  86		1 1 1 0 1  63
+	 * 1 0 1 1 1  83		1 1 1 1 1  61
+	 *
+	 * DIVA [1:0] : division ratio for internal clocks when Normal mode.
+	 *
+	 * DIVA [1:0] Division Ratio
+	 * 0 0 fosc
+	 * 0 1 fosc / 2
+	 * 1 0 fosc / 4
+	 * 1 1 fosc / 8
+	 *
+	 */
+	u8 frc[ILI9341_FRC_LEN];
+	/* TODO: need comments for this register */
+	u8 prc;
+	/*
+	 * B6h DISCTRL (Display Function Control)
+	 *               D/CX RDX WRX D17-8 D7  D6 D5 D4 D3   D2  D1  D0  HEX
+	 * Command       0    1   M   XX    1   0  1  1  0    1   1   0   B6h
+	 * 1st Parameter 1    1   M   XX    0   0  0  0  PTG[1:0] PT[1:0] 0A
+	 * 2nd Parameter 1    1   M   XX    REV GS SS SM ISC[3:0]         82
+	 * 3rd Parameter 1    1   M   XX    0   0  NL[5:0]                27
+	 * 4th Parameter 1    1   M   XX    0   0  PCDIV[5:0]             XX
+	 *
+	 * PTG [1:0]: Set the scan mode in non-display area.
+	 * PTG1 | PTG0 | Gate outputs in   | Source outputs in  | VCOM output
+	 *               non-display area  | non-display area   |
+	 * 1      0      Interval scan       Set with the PT[2:0] bits
+	 *
+	 * PT [1:0]: Determine source/VCOM output in a non-display area in the
+	 * partial display mode.
+	 * 1    0    AGND       AGND       AGND         AGND
+	 *
+	 * REV: Select whether the liquid crystal type is normally white type
+	 * or normally black type.
+	 * REV   Liquid crystal type
+	 * 0     Normally black
+	 * 1     Normally white
+	 *
+	 * SS: Select the shift direction of outputs from the source driver.
+	 * SS    Source Output Scan Direction
+	 * 0     S1 -> S720
+	 * 1     S720 -> S1
+	 *
+	 * GS: Sets the direction of scan by the gate driver in the range
+	 * determined by SCN [4:0] and NL [4:0]. The scan direction
+	 * determined by GS = 0 can be reversed by setting GS = 1.
+	 *
+	 * GS     Gate Output Scan Direction
+	 * 0      G1 -> G320
+	 * 1      G320 -> G1
+	 */
+	u8 dfc_1[ILI9341_DFC_1_LEN];
+	/*
+	 * Power Control 1 (C0h)
+	 * VRH [5:0]: Set the GVDD level, which is a reference level for the
+	 * VCOM level and the grayscale voltage level.
+	 *
+	 * VRH[5:0]    GVDD			VRH[5:0]	GVDD
+	 * 0 0 0 0 0 0 Setting prohibited	1 0 0 0 0 0	4.45 V
+	 * 0 0 0 0 0 1 Setting prohibited	1 0 0 0 0 1	4.50 V
+	 * 0 0 0 0 1 0 Setting prohibited	1 0 0 0 1 0	4.55 V
+	 * 0 0 0 0 1 1 3.00 V			1 0 0 0 1 1	4.60 V
+	 * 0 0 0 1 0 0 3.05 V			1 0 0 1 0 0	4.65 V
+	 * 0 0 0 1 0 1 3.10 V			1 0 0 1 0 1	4.70 V
+	 * 0 0 0 1 1 0 3.15 V			1 0 0 1 1 0	4.75 V
+	 * 0 0 0 1 1 1 3.20 V			1 0 0 1 1 1	4.80 V
+	 * 0 0 1 0 0 0 3.25 V			1 0 1 0 0 0	4.85 V
+	 * 0 0 1 0 0 1 3.30 V			1 0 1 0 0 1	4.90 V
+	 * 0 0 1 0 1 0 3.35 V			1 0 1 0 1 0	4.95 V
+	 * 0 0 1 0 1 1 3.40 V			1 0 1 0 1 1	5.00 V
+	 * 0 0 1 1 0 0 3.45 V			1 0 1 1 0 0	5.05 V
+	 * 0 0 1 1 0 1 3.50 V			1 0 1 1 0 1	5.10 V
+	 * 0 0 1 1 1 0 3.55 V			1 0 1 1 1 0	5.15 V
+	 * 0 0 1 1 1 1 3.60 V			1 0 1 1 1 1	5.20 V
+	 * 0 1 0 0 0 0 3.65 V			1 1 0 0 0 0	5.25 V
+	 * 0 1 0 0 0 1 3.70 V			1 1 0 0 0 1	5.30 V
+	 * 0 1 0 0 1 0 3.75 V			1 1 0 0 1 0	5.35 V
+	 * 0 1 0 0 1 1 3.80 V			1 1 0 0 1 1	5.40 V
+	 * 0 1 0 1 0 0 3.85 V			1 1 0 1 0 0	5.45 V
+	 * 0 1 0 1 0 1 3.90 V			1 1 0 1 0 1	5.50 V
+	 * 0 1 0 1 1 0 3.95 V			1 1 0 1 1 0	5.55 V
+	 * 0 1 0 1 1 1 4.00 V			1 1 0 1 1 1	5.60 V
+	 * 0 1 1 0 0 0 4.05 V			1 1 1 0 0 0	5.65 V
+	 * 0 1 1 0 0 1 4.10 V			1 1 1 0 0 1	5.70 V
+	 * 0 1 1 0 1 0 4.15 V			1 1 1 0 1 0	5.75 V
+	 * 0 1 1 0 1 1 4.20 V			1 1 1 0 1 1	5.80 V
+	 * 0 1 1 1 0 0 4.25 V			1 1 1 1 0 0	5.85 V
+	 * 0 1 1 1 0 1 4.30 V			1 1 1 1 0 1	5.90 V
+	 * 0 1 1 1 1 0 4.35 V			1 1 1 1 1 0	5.95 V
+	 * 0 1 1 1 1 1 4.40 V			1 1 1 1 1 1	6.00 V
+	 */
+	u8 power_1;
+	/*
+	 * Power Control 2 (C1h)
+	 *
+	 * BT [2:0]: Sets the factor used in the step-up circuits.
+	 * Select the optimal step-up factor for the operating voltage. To
+	 * reduce power consumption, set a smaller factor.
+	 *
+	 * BT[2:0]   AVDD     VGH      VGL
+	 * 0 0 0     VCI x 2  VCI x 7  VCI x 4
+	 * 0 0 1                       VCI x 3
+	 * 0 1 0              VCI x 6  VCI x 4
+	 * 0 1 1		       VCI x 3
+	 *
+	 */
+	u8 power_2;
+	/*
+	 * VCOM Control 1(C5h)
+	 *
+	 * VMH [6:0] : Set the VCOMH voltage
+	 *
+	 * VMH[6:0] VCOMH(V) VMH[6:0] VCOMH(V) VMH[6:0] VCOMH(V) VMH[6:0] VCOMH
+	 * 0000000  2.700    0100000  3.500    1000000  4.300    1100000  5.100
+	 * 0000001  2.725    0100001  3.525    1000001  4.325    1100001  5.125
+	 * 0000010  2.750    0100010  3.550    1000010  4.350    1100010  5.150
+	 * 0000011  2.775    0100011  3.575    1000011  4.375    1100011  5.175
+	 * 0000100  2.800    0100100  3.600    1000100  4.400    1100100  5.200
+	 * 0000101  2.825    0100101  3.625    1000101  4.425    1100101  5.225
+	 * 0000110  2.850    0100110  3.650    1000110  4.450    1100110  5.250
+	 * 0000111  2.875    0100111  3.675    1000111  4.475 	 1100111  5.275
+	 * 0001000  2.900    0101000  3.700    1001000  4.500 	 1101000  5.300
+	 * 0001001  2.925    0101001  3.725    1001001  4.525 	 1101001  5.325
+	 * 0001010  2.950    0101010  3.750    1001010  4.550 	 1101010  5.350
+	 * 0001011  2.975    0101011  3.775    1001011  4.575 	 1101011  5.375
+	 * 0001100  3.000    0101100  3.800    1001100  4.600 	 1101100  5.400
+	 * 0001101  3.025    0101101  3.825    1001101  4.625 	 1101101  5.425
+	 * 0001110  3.050    0101110  3.850    1001110  4.650 	 1101110  5.450
+	 * 0001111  3.075    0101111  3.875    1001111  4.675 	 1101111  5.475
+	 * 0010000  3.100    0110000  3.900    1010000  4.700 	 1110000  5.500
+	 * 0010001  3.125    0110001  3.925    1010001  4.725 	 1110001  5.525
+	 * 0010010  3.150    0110010  3.950    1010010  4.750 	 1110010  5.550
+	 * 0010011  3.175    0110011  3.975    1010011  4.775 	 1110011  5.575
+	 * 0010100  3.200    0110100  4.000    1010100  4.800 	 1110100  5.600
+	 * 0010101  3.225    0110101  4.025    1010101  4.825 	 1110101  5.625
+	 * 0010110  3.250    0110110  4.050    1010110  4.850 	 1110110  5.650
+	 * 0010111  3.275    0110111  4.075    1010111  4.875 	 1110111  5.675
+	 * 0011000  3.300    0111000  4.100    1011000  4.900 	 1111000  5.700
+	 * 0011001  3.325    0111001  4.125    1011001  4.925 	 1111001  5.725
+	 * 0011010  3.350    0111010  4.150    1011010  4.950 	 1111010  5.750
+	 * 0011011  3.375    0111011  4.175    1011011  4.975 	 1111011  5.775
+	 * 0011100  3.400    0111100  4.200    1011100  5.000 	 1111100  5.800
+	 * 0011101  3.425    0111101  4.225    1011101  5.025 	 1111101  5.825
+	 * 0011110  3.450    0111110  4.250    1011110  5.050 	 1111110  5.850
+	 * 0011111  3.475    0111111  4.275    1011111  5.075    1111111  5.875
+	 *
+	 * VML[6:0] : Set the VCOML voltage
+	 *
+	 * VML[6:0] VCOML(V) VML[6:0] VCOML(V) VML[6:0] VCOML(V) VML[6:0] VCOML
+	 * 0000000 -2.500 0100000 -1.700 1000000 -0.900 1100000 -0.100
+	 * 0000001 -2.475 0100001 -1.675 1000001 -0.875 1100001 -0.075
+	 * 0000010 -2.450 0100010 -1.650 1000010 -0.850 1100010 -0.050
+	 * 0000011 -2.425 0100011 -1.625 1000011 -0.825 1100011 -0.025
+	 * 0000100 -2.400 0100100 -1.600 1000100 -0.800 1100100 0
+	 * 0000101 -2.375 0100101 -1.575 1000101 -0.775 1100101 Reserved
+	 * 0000110 -2.350 0100110 -1.550 1000110 -0.750 1100110 Reserved
+	 * 0000111 -2.325 0100111 -1.525 1000111 -0.725 1100111 Reserved
+	 * 0001000 -2.300 0101000 -1.500 1001000 -0.700 1101000 Reserved
+	 * 0001001 -2.275 0101001 -1.475 1001001 -0.675 1101001 Reserved
+	 * 0001010 -2.250 0101010 -1.450 1001010 -0.650 1101010 Reserved
+	 * 0001011 -2.225 0101011 -1.425 1001011 -0.625 1101011 Reserved
+	 * 0001100 -2.200 0101100 -1.400 1001100 -0.600 1101100 Reserved
+	 * 0001101 -2.175 0101101 -1.375 1001101 -0.575 1101101 Reserved
+	 * 0001110 -2.150 0101110 -1.350 1001110 -0.550 1101110 Reserved
+	 * 0001111 -2.125 0101111 -1.325 1001111 -0.525 1101111 Reserved
+	 * 0010000 -2.100 0110000 -1.300 1010000 -0.500 1110000 Reserved
+	 * 0010001 -2.075 0110001 -1.275 1010001 -0.475 1110001 Reserved
+	 * 0010010 -2.050 0110010 -1.250 1010010 -0.450 1110010 Reserved
+	 * 0010011 -2.025 0110011 -1.225 1010011 -0.425 1110011 Reserved
+	 * 0010100 -2.000 0110100 -1.200 1010100 -0.400 1110100 Reserved
+	 * 0010101 -1.975 0110101 -1.175 1010101 -0.375 1110101 Reserved
+	 * 0010110 -1.950 0110110 -1.150 1010110 -0.350 1110110 Reserved
+	 * 0010111 -1.925 0110111 -1.125 1010111 -0.325 1110111 Reserved
+	 * 0011000 -1.900 0111000 -1.100 1011000 -0.300 1111000 Reserved
+	 * 0011001 -1.875 0111001 -1.075 1011001 -0.275 1111001 Reserved
+	 * 0011010 -1.850 0111010 -1.050 1011010 -0.250 1111010 Reserved
+	 * 0011011 -1.825 0111011 -1.025 1011011 -0.225 1111011 Reserved
+	 * 0011100 -1.800 0111100 -1.000 1011100 -0.200 1111100 Reserved
+	 * 0011101 -1.775 0111101 -0.975 1011101 -0.175 1111101 Reserved
+	 * 0011110 -1.750 0111110 -0.950 1011110 -0.150 1111110 Reserved
+	 * 0011111 -1.725 0111111 -0.925 1011111 -0.125 1111111 Reserved
+	 */
+	u8 vcom_1[ILI9341_VCOM_1_LEN];
+	/*
+	 * VCOM Control 2(C7h)
+	 *
+	 * C7h		VMCTRL1 (VCOM Control 1)
+	 *		D/CX RDX WRX D17-8 D7  D6  D5 D4 D3 D2 D1 D0 HEX
+	 * Command 	0    1   M   XX    1   1   0  0  0  1  1  1  C7h
+	 * Parameter 	1    1   M   XX    nVM VMF[6:0]              C0
+	 *
+	 * nVM: nVM equals to “0” after power on reset and VCOM offset
+	 * equals to program MTP value. When nVM set to “1”, setting
+	 * of VMF [6:0] becomes valid and VCOMH/VCOML can be adjusted.
+	 *
+	 * VMF [6:0]: Set the VCOM offset voltage.
+	 */
+	u8 vcom_2;
+	/*
+	 * Memory Access Control (36h)
+	 *
+	 * 36h 		MADCTL (Memory Access Control)
+	 * 		D/CX RDX WRX D17-8 D7 D6 D5 D4 D3  D2 D1 D0 HEX
+	 * Command 	0    1   M   XX    0  0  1  1  0   1  1  0  36h
+	 * Parameter 	1    1   M   XX    MY MX MV ML BGR MH 0  0  00
+	 *
+	 * This command defines read/write scanning direction of frame memory.
+	 * This command makes no change on the other driver status.
+	 *
+	 * Bit  Name 			 Description
+	 * MY   Row Address Order
+	 * MX   Column Address Order
+	 * MV 	Row / Column Exchange 	 These 3 bits control MCU to memory
+	 * 				 write/read direction.
+	 * ML 	Vertical Refresh Order 	 LCD vertical refresh direction control.
+	 * BGR 	RGB-BGR Order		 Color selector switch control
+	 *                               (0=RGB color filter panel, 1=BGR
+	 *                               color filter panel)
+	 * MH 	Horizontal Refresh ORDER LCD horizontal refreshing
+	 * direction control.
+	 *
+	 * Note: When BGR bit is changed, the new setting is active
+	 * immediately without update the content in Frame Memory again.
+	 *
+	 */
+	u8 address_mode;
+	/* TODO: need comments for this register */
+	u8 g3amma_en;
+	/* RGB Interface Signal Control (B0h)
+	 *
+	 * B0h 		IFMODE (Interface Mode Control)
+	 * 		D/CX RDX WRX D17-8 D7 	       D6     D5     D4 D3   D2   D1  D0  HEX
+	 * Command 	0    1   M   XX    1 	       0      1      1  0    0    0   0   B0h
+	 * Parameter 	1    1   M   XX    ByPass_MODE RCM[1] RCM[0] 0  VSPL HSPL DPL EPL 40
+	 *
+	 * Sets the operation status of the display interface. The setting
+	 * becomes effective as soon as the command is received.
+	 * EPL: DE polarity (“0”= High enable for RGB interface, “1”= Low
+	 * enable for RGB interface)
+	 *
+	 * DPL: DOTCLK polarity set (“0”= data fetched at the rising time,
+	 * “1”= data fetched at the falling time)
+	 *
+	 * HSPL: HSYNC polarity (“0”= Low level sync clock, “1”= High
+	 * level sync clock)
+	 *
+	 * VSPL: VSYNC polarity (“0”= Low level sync clock, “1”= High
+	 * level sync clock)
+	 *
+	 * RCM [1:0]: RGB interface selection (refer to the RGB interface
+	 * section).
+	 *
+	 * ByPass_MODE: Select display data path whether Memory or Direct to
+	 * Shift register when RGB Interface is used.
+	 *
+	 * ByPass_MODE 	Display Data Path
+	 * 0 		Direct to Shift Register (default)
+	 * 1 		Memory
+	 */
+	u8 rgb_interface;
+	/* refer to dfc_1 */
+	u8 dfc_2[ILI9341_DFC_2_LEN];
+	/*
+	 * Column Address Set (2Ah)
+	 * This command is used to define area of frame memory where MCU can
+	 * access. This command makes no change on the
+	 * other driver status. The values of SC [15:0] and EC [15:0] are
+	 * referred when RAMWR command comes. Each value
+	 * represents one column line in the Frame Memory.
+	 */
+	u8 column_addr[ILI9341_COLUMN_ADDR_LEN];
+	/*
+	 * Page Address Set (2Bh)
+	 * This command is used to define area of frame memory where MCU can
+	 * access. This command makes no change on the
+	 * other driver status. The values of SP [15:0] and EP [15:0] are
+	 * referred when RAMWR command comes. Each value
+	 * represents one Page line in the Frame Memory.
+	 */
+	u8 page_addr[ILI9341_PAGE_ADDR_LEN];
+	/*
+	 * Interface Control (F6h)
+	 *
+	 * F6h 		IFCTL (16bits Data Format Selection)
+	 * 	        D/CX RDX WRX D17-8 D7   D6   D5     D4     D3      D2     D1     D0      HEX
+	 * Command      0    1   M   XX    1    1    1      1      0       1      1      0       F6h
+	 * 1stParameter 1    1   M   XX    MY   MX   MV
+	 * 				   _EOR _EOR _EOR   0      BGR_EOR 0      0      WE MODE 01
+	 * 2ndParameter 1    1   M   XX    0    0    EPF[1] EPF[0] 0       0      MDT[1] MDT[0]  00
+	 * 3rdParameter 1    1   M   XX    0    0    ENDIAN 0      DM[1]   DM[0]  RM     RIM     00
+	 *
+	 */
+	u8 interface[ILI9341_INTERFACE_LEN];
+	/*
+	 * This command sets the pixel format for the RGB image data used by
+	 * the interface. DPI [2:0] is the pixel format select of RGB
+	 * interface and DBI [2:0] is the pixel format of MCU interface. If a
+	 * particular interface, either RGB interface or MCU interface, is
+	 * not used then the corresponding bits in the parameter are ignored.
+	 * The pixel format is shown in the table below.
+	 *
+	 * DPI[2:0] 	RGB Interface Format 	DBI[2:0] MCU Interface Format
+	 * 0 0 0 	Reserved 		0 0 0 	 Reserved
+	 * 0 0 1 	Reserved 		0 0 1 	 Reserved
+	 * 0 1 0 	Reserved 		0 1 0 	 Reserved
+	 * 0 1 1 	Reserved 		0 1 1 	 Reserved
+	 * 1 0 0 	Reserved 		1 0 0  	 Reserved
+	 * 1 0 1 	16 bits / pixel 	1 0 1    16 bits / pixel
+	 * 1 1 0 	18 bits / pixel 	1 1 0 	 18 bits / pixel
+	 * 1 1 1 	Reserved 		1 1 1 	 Reserved
+	 *
+	 */
+	u8 pixel_format;
+	/*
+	 * This command is used to select the desired Gamma curve for the
+	 * current display. A maximum of 4 fixed gamma curves can
+	 * be selected. The curve is selected by setting the appropriate bit
+	 * in the parameter as described in the Table:
+	 *
+	 * GC [7:0] 	Curve Selected
+	 * 01h 		Gamma curve 1 (G2.2)
+	 * 02h 		---
+	 * 04h 		---
+	 * 08h 		---
+	 */
+	u8 gamma_curve;
+	/*
+	 * Positive Gamma Correction (E0h)
+	 *
+	 * Set the gray scale voltage to adjust the gamma characteristics of
+	 * the TFT panel.
+	 */
+	u8 pgamma[ILI9341_PGAMMA_LEN];
+	/*
+	 * Negative Gamma Correction (E1h)
+	 *
+	 * Set the gray scale voltage to adjust the gamma characteristics of
+	 * the TFT panel.
+	 */
+	u8 ngamma[ILI9341_NGAMMA_LEN];
+};
+
+struct ili9341 {
+	struct device *dev;
+	const struct ili9341_config *conf;
+	struct drm_panel panel;
+	struct gpio_desc *reset_gpio;
+	struct gpio_desc *dc_gpio;
+	u32 max_spi_speed;
+	struct regulator *vcc;
+};
+
+/*
+ * The Stm32f429-disco board has a panel ili9341 connected to ltdc controller
+ */
+static const struct ili9341_config ili9341_stm32f429_disco_data = {
+	.max_spi_speed = 10000000,
+	.mode = {
+		.clock = 6100,
+		.hdisplay = 240,
+		.hsync_start = 240 + 10,/* hfp 10 */
+		.hsync_end = 240 + 10 + 10,/* hsync 10 */
+		.htotal = 240 + 10 + 10 + 20,/* hbp 20 */
+		.vdisplay = 320,
+		.vsync_start = 320 + 4,/* vfp 4 */
+		.vsync_end = 320 + 4 + 2,/* vsync 2 */
+		.vtotal = 320 + 4 + 2 + 2,/* vbp 2 */
+		.vrefresh = 60,
+		.flags = 0,
+		.width_mm = 65,
+		.height_mm = 50,
+		.type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+	},
+	/* TODO: need comments for this register */
+	.ca = {0xc3, 0x08, 0x50},
+	/* TODO: need comments for this register */
+	.power_b = {0x00, 0xc1, 0x30},
+	/* TODO: need comments for this register */
+	.power_seq = {0x64, 0x03, 0x12, 0x81},
+	/* TODO: need comments for this register */
+	.dtca = {0x85, 0x00, 0x78},
+	/* TODO: need comments for this register */
+	.power_a = {0x39, 0x2c, 0x00, 0x34, 0x02},
+	/* TODO: need comments for this register */
+	.prc = 0x20,
+	/* TODO: need comments for this register */
+	.dtcb = {0x00, 0x00},
+	/* 0x00 fosc, 0x1b 70hz */
+	.frc = {0x00, 0x1b},
+	/* 0x0a Interval scan, AGND AGND AGND AGND
+	 * 0xa2 Normally white, G1 -> G320, S720 -> S1,
+	 *	Scan Cycle 5 frames,85ms
+	 */
+	.dfc_1 = {0x0a, 0xa2},
+	/* 0x10 3.65v */
+	.power_1 = 0x10,
+	/* 0x10 AVDD=vci*2, VGH=vci*7, VGL=-vci*4 */
+	.power_2 = 0x10,
+	/* 0x45 VCOMH 4.425v, 0x15 VCOML -1.975*/
+	.vcom_1 = {0x45, 0x15},
+	/* 0x90 offset voltage, VMH-48, VML-48 */
+	.vcom_2 = 0x90,
+	/* 0xc8 Row Address Order, Column Address Order
+	 * 	BGR 1
+	 */
+	.address_mode = 0xc8,
+	.g3amma_en = 0x00,
+	/* 0xc2
+	 * Display Data Path: Memory
+	 * RGB: DE mode
+	 * DOTCLK polarity set (data fetched at the falling time)
+	 */
+	.rgb_interface = ILI9341_RGB_DISP_PATH_MEM |
+			ILI9341_RGB_DE_MODE |
+			ILI9341_RGB_DPL,
+	/*
+	 * 0x0a
+	 * Gate outputs in non-display area: Interval scan
+	 * Determine source/VCOM output in a non-display area in the partial
+	 * display mode: AGND AGND AGND AGND
+	 *
+	 * 0xa7
+	 * Scan Cycle: 15 frames
+	 * fFLM = 60Hz: 255ms
+	 * Liquid crystal type: Normally white
+	 * Gate Output Scan Direction: G1 -> G320
+	 * Source Output Scan Direction: S720 -> S1
+	 *
+	 * 0x27
+	 * LCD Driver Line: 320 lines
+	 *
+	 * 0x04
+	 * PCDIV: 4
+	 */
+	.dfc_2 = {0x0a, 0xa7, 0x27, 0x04},
+	/* column address: 240 */
+	.column_addr = {0x00, 0x00, (ILI9341_COLUMN_ADDR >> 4) & 0xff,
+				ILI9341_COLUMN_ADDR & 0xff},
+	/* page address: 320 */
+	.page_addr = {0x00, 0x00, (ILI9341_PAGE_ADDR >> 4) & 0xff,
+				ILI9341_PAGE_ADDR & 0xff},
+	/* Memory write control: When the transfer number of data exceeds
+	 * (EC-SC+1)*(EP-SP+1), the column and page number will be
+	 * reset, and the exceeding data will be written into the following
+	 * column and page.
+	 * Display Operation Mode: RGB Interface Mode
+	 * Interface for RAM Access: RGB interface
+	 * 16- bit RGB interface (1 transfer/pixel)
+	 */
+	.interface = {ILI9341_IF_WE_MODE, 0x00,
+			ILI9341_IF_DM_RGB | ILI9341_IF_RM_RGB},
+	/* DPI: 16 bits / pixel */
+	.pixel_format = ILI9341_PIXEL_DPI_16_BITS,
+	/* Curve Selected: Gamma curve 1 (G2.2) */
+	.gamma_curve = ILI9341_GAMMA_CURVE_1,
+	.pgamma = {0x0f, 0x29, 0x24, 0x0c, 0x0e,
+			0x09, 0x4e, 0x78, 0x3c, 0x09,
+			0x13, 0x05, 0x17, 0x11, 0x00},
+	.ngamma = {0x00, 0x16, 0x1b, 0x04, 0x11,
+			0x07, 0x31, 0x33, 0x42, 0x05,
+			0x0c, 0x0a, 0x28, 0x2f, 0x0f},
+};
+static inline struct ili9341 *panel_to_ili9341(struct drm_panel *panel)
+{
+	return container_of(panel, struct ili9341, panel);
+}
+
+int ili9341_spi_transfer(struct spi_device *spi, u32 speed_hz,
+			  u8 bpw, const void *buf, size_t len)
+{
+	size_t max_chunk = spi_max_transfer_size(spi);
+	struct spi_transfer tr = {
+		.bits_per_word = bpw,
+		.speed_hz = speed_hz,
+		.len = len,
+	};
+	struct spi_message m;
+	size_t chunk;
+	int ret;
+
+	spi_message_init_with_transfers(&m, &tr, 1);
+
+	while (len) {
+		chunk = min(len, max_chunk);
+
+		tr.tx_buf = buf;
+		tr.len = chunk;
+		buf += chunk;
+		len -= chunk;
+
+		ret = spi_sync(spi, &m);
+		if (ret) {
+			dev_err(&spi->dev, "spi_sync error: %d\n", ret);
+			return ret;
+		}
+	}
+	return 0;
+}
+
+static int _ili9341_command(struct ili9341 *ili, u8 cmd, const void *data,
+				    size_t count)
+{
+	struct spi_device *spi = to_spi_device(ili->dev);
+	int ret = 0;
+
+	gpiod_set_value_cansleep(ili->dc_gpio, 0);
+
+	ret = ili9341_spi_transfer(spi, ili->max_spi_speed, 8,
+					(const void *)&cmd, 1);
+	if (ret || data == NULL || count == 0)
+		return ret;
+
+	gpiod_set_value_cansleep(ili->dc_gpio, 1);
+
+	return ili9341_spi_transfer(spi, ili->max_spi_speed, 8,
+		data, count);
+}
+
+static int ili9341_dpi_init(struct ili9341 *ili)
+{
+	int ret;
+	ret = _ili9341_command(ili, 0xca,
+			ili->conf->ca,
+			ILI9341_CA_LEN);
+	if (ret)
+		return ret;
+
+	ret = _ili9341_command(ili, ILI9341_POWERB,
+			ili->conf->power_b,
+			ILI9341_POWER_B_LEN);
+	if (ret)
+		return ret;
+
+	ret = _ili9341_command(ili, ILI9341_POWER_SEQ,
+			ili->conf->power_seq,
+			ILI9341_POWER_SEQ_LEN);
+	if (ret)
+		return ret;
+
+	ret = _ili9341_command(ili, ILI9341_DTCA,
+			ili->conf->dtca,
+			ILI9341_DTCA_LEN);
+	if (ret)
+		return ret;
+
+	ret = _ili9341_command(ili, ILI9341_POWERA,
+			ili->conf->power_a,
+			ILI9341_POWER_A_LEN);
+	if (ret)
+		return ret;
+
+	ret = _ili9341_command(ili, ILI9341_PRC,
+			&ili->conf->prc,
+			1);
+	if (ret)
+		return ret;
+
+	ret = _ili9341_command(ili, ILI9341_DTCB,
+			ili->conf->dtcb,
+			ILI9341_DTCB_LEN);
+	if (ret)
+		return ret;
+
+	ret = _ili9341_command(ili, ILI9341_FRC,
+			ili->conf->frc,
+			ILI9341_FRC_LEN);
+	if (ret)
+		return ret;
+
+	ret = _ili9341_command(ili, ILI9341_DFC,
+			ili->conf->dfc_1,
+			ILI9341_DFC_1_LEN);
+	if (ret)
+		return ret;
+
+	ret = _ili9341_command(ili, ILI9341_POWER1,
+			&ili->conf->power_1,
+			1);
+	if (ret)
+		return ret;
+
+	ret = _ili9341_command(ili, ILI9341_POWER2,
+			&ili->conf->power_2,
+			1);
+	if (ret)
+		return ret;
+
+	ret = _ili9341_command(ili, ILI9341_VCOM1,
+			ili->conf->vcom_1,
+			ILI9341_VCOM_1_LEN);
+	if (ret)
+		return ret;
+
+	ret = _ili9341_command(ili, ILI9341_VCOM2,
+			&ili->conf->vcom_2,
+			1);
+	if (ret)
+		return ret;
+
+	ret = _ili9341_command(ili, MIPI_DCS_SET_ADDRESS_MODE,
+			&ili->conf->address_mode,
+			1);
+	if (ret)
+		return ret;
+
+	ret = _ili9341_command(ili, ILI9341_3GAMMA_EN,
+			&ili->conf->g3amma_en,
+			1);
+	if (ret)
+		return ret;
+
+	ret = _ili9341_command(ili, ILI9341_RGB_INTERFACE,
+			&ili->conf->rgb_interface,
+			1);
+	if (ret)
+		return ret;
+
+	ret = _ili9341_command(ili, ILI9341_DFC,
+			ili->conf->dfc_2,
+			ILI9341_DFC_2_LEN);
+	if (ret)
+		return ret;
+
+	ret = _ili9341_command(ili, MIPI_DCS_SET_COLUMN_ADDRESS,
+			ili->conf->column_addr,
+			ILI9341_COLUMN_ADDR_LEN);
+	if (ret)
+		return ret;
+
+	ret = _ili9341_command(ili, MIPI_DCS_SET_PAGE_ADDRESS,
+			ili->conf->page_addr,
+			ILI9341_PAGE_ADDR_LEN);
+	if (ret)
+		return ret;
+
+	ret = _ili9341_command(ili, ILI9341_INTERFACE,
+			ili->conf->interface,
+			ILI9341_INTERFACE_LEN);
+	if (ret)
+		return ret;
+
+	ret = _ili9341_command(ili, MIPI_DCS_SET_PIXEL_FORMAT,
+			&ili->conf->pixel_format,
+			1);
+	if (ret)
+		return ret;
+
+	ret = ili9341_command(ili, MIPI_DCS_WRITE_MEMORY_START);
+	if (ret)
+		return ret;
+
+	msleep(200);
+	ret = _ili9341_command(ili, MIPI_DCS_SET_GAMMA_CURVE,
+			&ili->conf->gamma_curve,
+			1);
+	if (ret)
+		return ret;
+
+	ret = _ili9341_command(ili, ILI9341_PGAMMA,
+			ili->conf->pgamma,
+			ILI9341_PGAMMA_LEN);
+	if (ret)
+		return ret;
+
+	ret = _ili9341_command(ili, ILI9341_NGAMMA,
+			ili->conf->ngamma,
+			ILI9341_NGAMMA_LEN);
+	if (ret)
+		return ret;
+
+	ret = ili9341_command(ili, MIPI_DCS_EXIT_SLEEP_MODE);
+	if (ret)
+		return ret;
+
+	msleep(200);
+	ret = ili9341_command(ili, MIPI_DCS_SET_DISPLAY_ON);
+	if (ret)
+		return ret;
+
+	ret = ili9341_command(ili, MIPI_DCS_WRITE_MEMORY_START);
+	if (ret)
+		return ret;
+
+
+	dev_info(ili->dev, "initialized display rgb interface\n");
+
+	return 0;
+}
+
+static int ili9341_dpi_power_on(struct ili9341 *ili)
+{
+	int ret = 0;
+
+	/* Assert RESET */
+	gpiod_set_value(ili->reset_gpio, 1);
+
+	/* Enable power */
+	if (!IS_ERR(ili->vcc)) {
+		ret = regulator_enable(ili->vcc);
+		if (ret < 0) {
+			dev_err(ili->dev, "unable to enable vcc\n");
+			return ret;
+		}
+	}
+	msleep(20);
+
+	/* De-assert RESET */
+	gpiod_set_value(ili->reset_gpio, 0);
+	msleep(10);
+
+	return 0;
+}
+
+static int ili9341_dpi_power_off(struct ili9341 *ili)
+{
+	/* Assert RESET */
+	gpiod_set_value(ili->reset_gpio, 1);
+
+	/* Disable power */
+	if (!IS_ERR(ili->vcc))
+		return regulator_disable(ili->vcc);
+
+	return 0;
+}
+
+static int ili9341_dpi_disable(struct drm_panel *panel)
+{
+	struct ili9341 *ili = panel_to_ili9341(panel);
+
+	ili9341_command(ili, MIPI_DCS_SET_DISPLAY_OFF);
+
+	return 0;
+}
+
+static int ili9341_dpi_unprepare(struct drm_panel *panel)
+{
+	struct ili9341 *ili = panel_to_ili9341(panel);
+
+	return ili9341_dpi_power_off(ili);
+}
+
+static int ili9341_dpi_prepare(struct drm_panel *panel)
+{
+	struct ili9341 *ili = panel_to_ili9341(panel);
+	int ret;
+
+	ret = ili9341_dpi_power_on(ili);
+	if (ret < 0)
+		return ret;
+
+	ret = ili9341_dpi_init(ili);
+	if (ret < 0)
+		ili9341_dpi_unprepare(panel);
+
+	return ret;
+}
+
+static int ili9341_dpi_enable(struct drm_panel *panel)
+{
+	struct ili9341 *ili = panel_to_ili9341(panel);
+
+	ili9341_command(ili, MIPI_DCS_SET_DISPLAY_ON);
+
+	return 0;
+}
+
+static int ili9341_dpi_get_modes(struct drm_panel *panel,
+				struct drm_connector *connector)
+{
+	struct ili9341 *ili = panel_to_ili9341(panel);
+	struct drm_device *drm = connector->dev;
+	struct drm_display_mode *mode;
+	struct drm_display_info *info;
+
+	info = &connector->display_info;
+	info->width_mm = ili->conf->mode.width_mm;
+	info->height_mm = ili->conf->mode.height_mm;
+
+	if (ili->conf->rgb_interface & ILI9341_RGB_DPL)
+		info->bus_flags |= DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE;
+	else
+		info->bus_flags |= DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE;
+
+	if (ili->conf->rgb_interface & ILI9341_RGB_EPL)
+		info->bus_flags |= DRM_BUS_FLAG_DE_HIGH;
+	else
+		info->bus_flags |= DRM_BUS_FLAG_DE_LOW;
+
+	mode = drm_mode_duplicate(drm, &ili->conf->mode);
+	if (!mode) {
+		DRM_ERROR("bad mode or failed to add mode\n");
+		return -EINVAL;
+	}
+	drm_mode_set_name(mode);
+
+	/* Set up the polarity */
+	if (ili->conf->rgb_interface & ILI9341_RGB_HSPL)
+		mode->flags |= DRM_MODE_FLAG_PHSYNC;
+	else
+		mode->flags |= DRM_MODE_FLAG_NHSYNC;
+
+	if (ili->conf->rgb_interface & ILI9341_RGB_VSPL)
+		mode->flags |= DRM_MODE_FLAG_PVSYNC;
+	else
+		mode->flags |= DRM_MODE_FLAG_NVSYNC;
+
+	drm_mode_probed_add(connector, mode);
+
+	return 1; /* Number of modes */
+}
+
+static const struct drm_panel_funcs ili9341_dpi_funcs = {
+	.disable = ili9341_dpi_disable,
+	.unprepare = ili9341_dpi_unprepare,
+	.prepare = ili9341_dpi_prepare,
+	.enable = ili9341_dpi_enable,
+	.get_modes = ili9341_dpi_get_modes,
+};
+
+static int ili9341_dpi_probe(struct spi_device *spi)
+{
+	int ret;
+	struct device *dev = &spi->dev;
+	struct ili9341 *ili;
+
+	ili = devm_kzalloc(dev, sizeof(struct ili9341), GFP_KERNEL);
+	if (!ili)
+		return -ENOMEM;
+
+	spi_set_drvdata(spi, ili);
+
+	ili->dev = dev;
+	/*
+	 * Every new incarnation of this display must have a unique
+	 * data entry for the system in this driver.
+	 */
+	ili->conf = of_device_get_match_data(dev);
+	if (!ili->conf) {
+		dev_err(dev, "missing device configuration\n");
+		return -ENODEV;
+	}
+
+	ili->vcc = devm_regulator_get_optional(dev, "vcc");
+	if (IS_ERR(ili->vcc))
+		dev_err(dev, "get optional vcc failed\n");
+
+	ili->reset_gpio = devm_gpiod_get_optional(dev, "reset",
+		GPIOD_OUT_HIGH);
+	if (IS_ERR(ili->reset_gpio)) {
+		dev_err(dev, "failed to get RESET GPIO\n");
+		return PTR_ERR(ili->reset_gpio);
+	}
+
+	ili->dc_gpio = devm_gpiod_get(dev, "dc", GPIOD_OUT_LOW);
+	if (IS_ERR(ili->dc_gpio)) {
+		dev_err(dev, "failed to get DC GPIO\n");
+		return PTR_ERR(ili->dc_gpio);
+	}
+
+	spi->bits_per_word = 8;
+	ret = spi_setup(spi);
+	if (ret < 0) {
+		dev_err(dev, "spi setup failed.\n");
+		return ret;
+	}
+
+	ili->max_spi_speed = ili->conf->max_spi_speed;
+
+	drm_panel_init(&ili->panel, dev, &ili9341_dpi_funcs,
+		       DRM_MODE_CONNECTOR_DPI);
+
+	return drm_panel_add(&ili->panel);
+}
+
+
+
+static void ili9341_dbi_enable(struct drm_simple_display_pipe *pipe,
+			     struct drm_crtc_state *crtc_state,
+			     struct drm_plane_state *plane_state)
+{
+	struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev);
+	struct mipi_dbi *dbi = &dbidev->dbi;
+	u8 addr_mode;
+	int ret, idx;
+
+	if (!drm_dev_enter(pipe->crtc.dev, &idx))
+		return;
+
+	DRM_DEBUG_KMS("\n");
+
+	ret = mipi_dbi_poweron_conditional_reset(dbidev);
+	if (ret < 0)
+		goto out_exit;
+	if (ret == 1)
+		goto out_enable;
+
+	mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_OFF);
+
+	mipi_dbi_command(dbi, ILI9341_POWERB, 0x00, 0xc1, 0x30);
+	mipi_dbi_command(dbi, ILI9341_POWER_SEQ, 0x64, 0x03, 0x12, 0x81);
+	mipi_dbi_command(dbi, ILI9341_DTCA, 0x85, 0x00, 0x78);
+	mipi_dbi_command(dbi, ILI9341_POWERA, 0x39, 0x2c, 0x00, 0x34, 0x02);
+	mipi_dbi_command(dbi, ILI9341_PRC, ILI9341_DBI_PRC_NORMAL);
+	mipi_dbi_command(dbi, ILI9341_DTCB, 0x00, 0x00);
+
+	/* Power Control */
+	mipi_dbi_command(dbi, ILI9341_POWER1, ILI9341_DBI_VCOMH_4P6V);
+	mipi_dbi_command(dbi, ILI9341_POWER2, ILI9341_DBI_PWR_2_DEFAULT);
+	/* VCOM */
+	mipi_dbi_command(dbi, ILI9341_VCOM1, ILI9341_DBI_VCOM_1_VMH_4P25V,
+						ILI9341_DBI_VCOM_1_VML_1P5V);
+	mipi_dbi_command(dbi, ILI9341_VCOM2, ILI9341_DBI_VCOM_2_DEC_58);
+
+	/* Memory Access Control */
+	mipi_dbi_command(dbi, MIPI_DCS_SET_PIXEL_FORMAT,
+				MIPI_DCS_PIXEL_FMT_16BIT);
+
+	/* Frame Rate */
+	mipi_dbi_command(dbi, ILI9341_FRC, ILI9341_DBI_FRC_DIVA & 0x03,
+						ILI9341_DBI_FRC_RTNA & 0x1f);
+
+	/* Gamma */
+	mipi_dbi_command(dbi, ILI9341_3GAMMA_EN, 0x00);
+	mipi_dbi_command(dbi, MIPI_DCS_SET_GAMMA_CURVE, ILI9341_GAMMA_CURVE_1);
+	mipi_dbi_command(dbi, ILI9341_PGAMMA,
+			 0x0f, 0x31, 0x2b, 0x0c, 0x0e, 0x08, 0x4e, 0xf1,
+			 0x37, 0x07, 0x10, 0x03, 0x0e, 0x09, 0x00);
+	mipi_dbi_command(dbi, ILI9341_NGAMMA,
+			 0x00, 0x0e, 0x14, 0x03, 0x11, 0x07, 0x31, 0xc1,
+			 0x48, 0x08, 0x0f, 0x0c, 0x31, 0x36, 0x0f);
+
+	/* DDRAM */
+	mipi_dbi_command(dbi, ILI9341_ETMOD, ILI9341_DBI_EMS_GAS |
+						ILI9341_DBI_EMS_DTS |
+						ILI9341_DBI_EMS_GON);
+
+	/* Display */
+	mipi_dbi_command(dbi, ILI9341_DFC, 0x08, 0x82, 0x27, 0x00);
+	mipi_dbi_command(dbi, MIPI_DCS_EXIT_SLEEP_MODE);
+	msleep(100);
+
+	mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_ON);
+	msleep(100);
+
+out_enable:
+	switch (dbidev->rotation) {
+	default:
+		addr_mode = ILI9341_MADCTL_MX;
+		break;
+	case 90:
+		addr_mode = ILI9341_MADCTL_MV;
+		break;
+	case 180:
+		addr_mode = ILI9341_MADCTL_MY;
+		break;
+	case 270:
+		addr_mode = ILI9341_MADCTL_MV | ILI9341_MADCTL_MY |
+			    ILI9341_MADCTL_MX;
+		break;
+	}
+	addr_mode |= ILI9341_MADCTL_BGR;
+	mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode);
+	mipi_dbi_enable_flush(dbidev, crtc_state, plane_state);
+	DRM_DEBUG_KMS("initialized display serial interface\n");
+out_exit:
+	drm_dev_exit(idx);
+}
+
+static const struct drm_simple_display_pipe_funcs ili9341_dbi_funcs = {
+	.enable = ili9341_dbi_enable,
+	.disable = mipi_dbi_pipe_disable,
+	.update = mipi_dbi_pipe_update,
+	.prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb,
+};
+
+static const struct drm_display_mode ili9341_dbi_mode = {
+	DRM_SIMPLE_MODE(240, 320, 37, 49),
+};
+
+DEFINE_DRM_GEM_CMA_FOPS(ili9341_dbi_fops);
+
+static struct drm_driver ili9341_dbi_driver = {
+	.driver_features	= DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
+	.fops			= &ili9341_dbi_fops,
+	.release		= mipi_dbi_release,
+	DRM_GEM_CMA_VMAP_DRIVER_OPS,
+	.debugfs_init		= mipi_dbi_debugfs_init,
+	.name			= "ili9341",
+	.desc			= "Ilitek ILI9341",
+	.date			= "20180514",
+	.major			= 1,
+	.minor			= 0,
+};
+static int ili9341_dbi_probe(struct spi_device *spi)
+{
+	struct mipi_dbi_dev *dbidev;
+	struct drm_device *drm;
+	struct mipi_dbi *dbi;
+	struct gpio_desc *dc;
+	struct device *dev = &spi->dev;
+	u32 rotation = 0;
+	int ret;
+
+	dbidev = kzalloc(sizeof(*dbidev), GFP_KERNEL);
+	if (!dbidev)
+		return -ENOMEM;
+
+	dbi = &dbidev->dbi;
+	drm = &dbidev->drm;
+	ret = devm_drm_dev_init(dev, drm, &ili9341_dbi_driver);
+	if (ret) {
+		kfree(dbidev);
+		return ret;
+	}
+
+	drm_mode_config_init(drm);
+
+	dbi->reset = devm_gpiod_get_optional(dev, "reset",
+					GPIOD_OUT_HIGH);
+	if (IS_ERR(dbi->reset)) {
+		DRM_DEV_ERROR(dev, "Failed to get gpio 'reset'\n");
+		return PTR_ERR(dbi->reset);
+	}
+
+	dc = devm_gpiod_get_optional(dev, "dc", GPIOD_OUT_LOW);
+	if (IS_ERR(dc)) {
+		DRM_DEV_ERROR(dev, "Failed to get gpio 'dc'\n");
+		return PTR_ERR(dc);
+	}
+
+	dbidev->regulator = devm_regulator_get_optional(dev, "vcc");
+	if (IS_ERR(dbidev->regulator))
+		dev_err(dev, "get optional vcc failed\n");
+
+	dbidev->backlight = devm_of_find_backlight(dev);
+	if (IS_ERR(dbidev->backlight))
+		return PTR_ERR(dbidev->backlight);
+
+	device_property_read_u32(dev, "rotation", &rotation);
+
+	ret = mipi_dbi_spi_init(spi, dbi, dc);
+	if (ret)
+		return ret;
+
+	ret = mipi_dbi_dev_init(dbidev, &ili9341_dbi_funcs,
+					&ili9341_dbi_mode, rotation);
+	if (ret)
+		return ret;
+
+	drm_mode_config_reset(drm);
+
+	ret = drm_dev_register(drm, 0);
+	if (ret)
+		return ret;
+
+	spi_set_drvdata(spi, drm);
+
+	drm_fbdev_generic_setup(drm, 0);
+
+	return 0;
+}
+static int ili9341_probe(struct spi_device *spi)
+{
+	const struct spi_device_id *id = spi_get_device_id(spi);
+
+	if (!strcmp(id->name, "sf-tc240t-9370-t"))
+		return ili9341_dpi_probe(spi);
+	else if (!strcmp(id->name, "yx240qv29"))
+		return ili9341_dbi_probe(spi);
+
+	return -1;
+}
+
+static int ili9341_remove(struct spi_device *spi)
+{
+	const struct spi_device_id *id = spi_get_device_id(spi);
+	struct ili9341 *ili = spi_get_drvdata(spi);
+	struct drm_device *drm = spi_get_drvdata(spi);
+
+	if (!strcmp(id->name, "sf-tc240t-9370-t")) {
+		ili9341_dpi_power_off(ili);
+		drm_panel_remove(&ili->panel);
+	} else if (!strcmp(id->name, "yx240qv29")) {
+		drm_dev_unplug(drm);
+		drm_atomic_helper_shutdown(drm);
+	}
+	return 0;
+}
+
+static void ili9341_shutdown(struct spi_device *spi)
+{
+	const struct spi_device_id *id = spi_get_device_id(spi);
+
+	if (!strcmp(id->name, "yx240qv29"))
+		drm_atomic_helper_shutdown(spi_get_drvdata(spi));
+}
+
+static const struct of_device_id ili9341_of_match[] = {
+	{
+		.compatible = "st,sf-tc240t-9370-t",
+		.data = &ili9341_stm32f429_disco_data,
+	},
+	{
+		/* porting from tiny/ili9341.c
+		 * for original mipi dbi compitable
+		 */
+		.compatible = "adafruit,yx240qv29",
+		.data = NULL,
+	},
+};
+MODULE_DEVICE_TABLE(of, ili9341_of_match);
+
+static const struct spi_device_id ili9341_id[] = {
+	{ "yx240qv29", 0 },
+	{ "sf-tc240t-9370-t", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(spi, ili9341_id);
+
+static struct spi_driver ili9341_driver = {
+	.probe = ili9341_probe,
+	.remove = ili9341_remove,
+	.shutdown = ili9341_shutdown,
+	.id_table = ili9341_id,
+	.driver = {
+		.name = "panel-ilitek-ili9341",
+		.of_match_table = ili9341_of_match,
+	},
+};
+module_spi_driver(ili9341_driver);
+
+MODULE_AUTHOR("Dillon Min <dillon.minfei@gmail.com>");
+MODULE_DESCRIPTION("ILI9341 LCD panel driver");
+MODULE_LICENSE("GPL v2");
-- 
2.7.4



[-- 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 related

* [PATCH v4 7/8] clk: stm32: Fix stm32f429's ltdc driver hang in set clock rate.
From: dillon.minfei @ 2020-05-18 11:09 UTC (permalink / raw)
  To: robh+dt, p.zabel, mcoquelin.stm32, broonie, devicetree,
	alexandre.torgue, thierry.reding, sam, airlied, daniel,
	mturquette, sboyd
  Cc: linux-kernel, dri-devel, linux-stm32, linux-spi, dillon min,
	linux-clk, linux-arm-kernel
In-Reply-To: <1589800165-3271-1-git-send-email-dillon.minfei@gmail.com>

From: dillon min <dillon.minfei@gmail.com>

fix duplicated ltdc clock register to 'clk_core' case ltdc's clock
turn off by clk_disable_unused()

ltdc set clock rate crashed:
   'post_div_data[]''s pll_num is PLL_I2S, PLL_SAI (number is 1,2). but,
    as pll_num is offset of 'clks[]' input to clk_register_pll_div(), which
    is FCLK, CLK_LSI, defined in 'include/dt-bindings/clock/stm32fx-clock.h'
    so, this is a null object at the register time.
    then, in ltdc's clock is_enabled(), enable(), will call to_clk_gate().
    will return a null object, cause kernel crashed.
    need change pll_num to PLL_VCO_I2S, PLL_VCO_SAI for 'post_div_data[]'

duplicated ltdc clock
   'stm32f429_gates[]' has a member 'ltdc' register to 'clk_core', but no
    upper driver use it, ltdc driver use the lcd-tft defined in
   'stm32f429_aux_clk[]'. after system startup, as stm32f429_gates[]'s ltdc
   enable_count is zero, so turn off by clk_disable_unused()

Signed-off-by: dillon min <dillon.minfei@gmail.com>
---
Hi Stephen Boyd:

thanks for reviewing, this patch fix the wrong use of clk ignore unused.

thanks.

Changes since V3:
1 drop last wrong changes about 'CLK_IGNORE_UNUSED' patch
2 fix PLL_SAI mismatch with PLL_VCO_SAI
 drivers/clk/clk-stm32f4.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/clk-stm32f4.c b/drivers/clk/clk-stm32f4.c
index 18117ce..fa62e99 100644
--- a/drivers/clk/clk-stm32f4.c
+++ b/drivers/clk/clk-stm32f4.c
@@ -129,7 +129,6 @@ static const struct stm32f4_gate_data stm32f429_gates[] __initconst = {
 	{ STM32F4_RCC_APB2ENR, 20,	"spi5",		"apb2_div" },
 	{ STM32F4_RCC_APB2ENR, 21,	"spi6",		"apb2_div" },
 	{ STM32F4_RCC_APB2ENR, 22,	"sai1",		"apb2_div" },
-	{ STM32F4_RCC_APB2ENR, 26,	"ltdc",		"apb2_div" },
 };
 
 static const struct stm32f4_gate_data stm32f469_gates[] __initconst = {
@@ -557,13 +556,13 @@ static const struct clk_div_table post_divr_table[] = {
 
 #define MAX_POST_DIV 3
 static const struct stm32f4_pll_post_div_data  post_div_data[MAX_POST_DIV] = {
-	{ CLK_I2SQ_PDIV, PLL_I2S, "plli2s-q-div", "plli2s-q",
+	{ CLK_I2SQ_PDIV, PLL_VCO_I2S, "plli2s-q-div", "plli2s-q",
 		CLK_SET_RATE_PARENT, STM32F4_RCC_DCKCFGR, 0, 5, 0, NULL},
 
-	{ CLK_SAIQ_PDIV, PLL_SAI, "pllsai-q-div", "pllsai-q",
+	{ CLK_SAIQ_PDIV, PLL_VCO_SAI, "pllsai-q-div", "pllsai-q",
 		CLK_SET_RATE_PARENT, STM32F4_RCC_DCKCFGR, 8, 5, 0, NULL },
 
-	{ NO_IDX, PLL_SAI, "pllsai-r-div", "pllsai-r", CLK_SET_RATE_PARENT,
+	{ NO_IDX, PLL_VCO_SAI, "pllsai-r-div", "pllsai-r", CLK_SET_RATE_PARENT,
 		STM32F4_RCC_DCKCFGR, 16, 2, 0, post_divr_table },
 };
 
-- 
2.7.4


_______________________________________________
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 v4 6/8] ARM: dts: stm32: enable ltdc binding with ili9341 on stm32429-disco board
From: dillon.minfei @ 2020-05-18 11:09 UTC (permalink / raw)
  To: robh+dt, p.zabel, mcoquelin.stm32, broonie, devicetree,
	alexandre.torgue, thierry.reding, sam, airlied, daniel,
	mturquette, sboyd
  Cc: linux-kernel, dri-devel, linux-stm32, linux-spi, dillon min,
	linux-clk, linux-arm-kernel
In-Reply-To: <1589800165-3271-1-git-send-email-dillon.minfei@gmail.com>

From: dillon min <dillon.minfei@gmail.com>

Enable the ltdc & ili9341 on stm32429-disco board.

Signed-off-by: dillon min <dillon.minfei@gmail.com>
---
 arch/arm/boot/dts/stm32f429-disco.dts | 48 +++++++++++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/arch/arm/boot/dts/stm32f429-disco.dts b/arch/arm/boot/dts/stm32f429-disco.dts
index 30c0f67..365d16f 100644
--- a/arch/arm/boot/dts/stm32f429-disco.dts
+++ b/arch/arm/boot/dts/stm32f429-disco.dts
@@ -49,6 +49,8 @@
 #include "stm32f429.dtsi"
 #include "stm32f429-pinctrl.dtsi"
 #include <dt-bindings/input/input.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/gpio/gpio.h>
 
 / {
 	model = "STMicroelectronics STM32F429i-DISCO board";
@@ -127,3 +129,49 @@
 	pinctrl-names = "default";
 	status = "okay";
 };
+
+&ltdc {
+	status = "okay";
+	pinctrl-0 = <&ltdc_pins_f429_disco>;
+	pinctrl-names = "default";
+
+	port {
+		ltdc_out_rgb: endpoint {
+			remote-endpoint = <&panel_in_rgb>;
+		};
+	};
+};
+
+&spi5 {
+	status = "okay";
+	pinctrl-0 = <&spi5_pins>;
+	pinctrl-names = "default";
+	#address-cells = <1>;
+	#size-cells = <0>;
+	cs-gpios = <&gpioc 1 GPIO_ACTIVE_LOW>, <&gpioc 2 GPIO_ACTIVE_LOW>;
+
+	l3gd20: l3gd20@0 {
+		compatible = "st,l3gd20-gyro";
+		spi-max-frequency = <10000000>;
+		st,drdy-int-pin = <2>;
+		interrupt-parent = <&gpioa>;
+		interrupts = <1 IRQ_TYPE_EDGE_RISING>,
+				<2 IRQ_TYPE_EDGE_RISING>;
+		reg = <0>;
+		status = "okay";
+	};
+
+	display: display@1{
+		/* Connect panel-ilitek-9341 to ltdc */
+		compatible = "st,sf-tc240t-9370-t";
+		reg = <1>;
+		spi-3wire;
+		spi-max-frequency = <10000000>;
+		dc-gpios = <&gpiod 13 0>;
+		port {
+			panel_in_rgb: endpoint {
+			remote-endpoint = <&ltdc_out_rgb>;
+			};
+		};
+	};
+};
-- 
2.7.4


_______________________________________________
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 v4 5/8] dt-bindings: display: panel: Add ilitek ili9341 panel bindings
From: dillon.minfei @ 2020-05-18 11:09 UTC (permalink / raw)
  To: robh+dt, p.zabel, mcoquelin.stm32, broonie, devicetree,
	alexandre.torgue, thierry.reding, sam, airlied, daniel,
	mturquette, sboyd
  Cc: linux-kernel, dri-devel, linux-stm32, linux-spi, dillon min,
	linux-clk, linux-arm-kernel
In-Reply-To: <1589800165-3271-1-git-send-email-dillon.minfei@gmail.com>

From: dillon min <dillon.minfei@gmail.com>

Add documentation for "ilitek,ili9341" panel.

Signed-off-by: dillon min <dillon.minfei@gmail.com>
---
 .../bindings/display/panel/ilitek,ili9341.yaml     | 69 ++++++++++++++++++++++
 1 file changed, 69 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/panel/ilitek,ili9341.yaml

diff --git a/Documentation/devicetree/bindings/display/panel/ilitek,ili9341.yaml b/Documentation/devicetree/bindings/display/panel/ilitek,ili9341.yaml
new file mode 100644
index 0000000..2172f88
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/ilitek,ili9341.yaml
@@ -0,0 +1,69 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/ilitek,ili9341.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Ilitek-9341 Display Panel
+
+maintainers:
+  - Dillon Min <dillon.minfei@gmail.com>
+
+description: |
+  Ilitek ILI9341 TFT panel driver with SPI control bus
+  This is a driver for 320x240 TFT panels, accepting a rgb input
+  streams with 16 bits or 18 bits.
+
+allOf:
+  - $ref: panel-common.yaml#
+
+properties:
+  compatible:
+    items:
+      - enum:
+          # ili9341 240*320 Color on stm32f429-disco board
+        - st,sf-tc240t-9370-t
+      - const: ilitek,ili9341
+
+  reg: true
+
+  dc-gpios:
+    maxItems: 1
+    description: Display data/command selection (D/CX)
+
+  spi-3wire: true
+
+  spi-max-frequency:
+    const: 10000000
+
+  port: true
+
+additionalProperties: false
+
+required:
+  - compatible
+  - reg
+  - dc-gpios
+  - port
+
+examples:
+  - |+
+    spi {
+        #address-cells = <1>;
+        #size-cells = <0>;
+        panel: display@0 {
+                 compatible = "st,sf-tc240t-9370-t",
+                              "ilitek,ili9341";
+                 reg = <0>;
+                 spi-3wire;
+                 spi-max-frequency = <10000000>;
+                 dc-gpios = <&gpiod 13 0>;
+                 port {
+                         panel_in: endpoint {
+                           remote-endpoint = <&display_out>;
+                      };
+                 };
+             };
+        };
+...
+
-- 
2.7.4


_______________________________________________
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 v4 4/8] ARM: dts: stm32: Add pin map for ltdc on stm32f429-disco board
From: dillon.minfei @ 2020-05-18 11:09 UTC (permalink / raw)
  To: robh+dt, p.zabel, mcoquelin.stm32, broonie, devicetree,
	alexandre.torgue, thierry.reding, sam, airlied, daniel,
	mturquette, sboyd
  Cc: linux-kernel, dri-devel, linux-stm32, linux-spi, dillon min,
	linux-clk, linux-arm-kernel
In-Reply-To: <1589800165-3271-1-git-send-email-dillon.minfei@gmail.com>

From: dillon min <dillon.minfei@gmail.com>

This patch adds the pin configuration for ltdc controller
on stm32f429-disco board.

Signed-off-by: dillon min <dillon.minfei@gmail.com>
---
 arch/arm/boot/dts/stm32f4-pinctrl.dtsi | 50 ++++++++++++++++++++++++++++++++++
 1 file changed, 50 insertions(+)

diff --git a/arch/arm/boot/dts/stm32f4-pinctrl.dtsi b/arch/arm/boot/dts/stm32f4-pinctrl.dtsi
index 54c1b27..0eb107f 100644
--- a/arch/arm/boot/dts/stm32f4-pinctrl.dtsi
+++ b/arch/arm/boot/dts/stm32f4-pinctrl.dtsi
@@ -316,6 +316,56 @@
 				};
 			};
 
+			ltdc_pins_f429_disco: ltdc-1 {
+				pins {
+					pinmux = <STM32_PINMUX('C', 6,  AF14)>,
+						/* LCD_HSYNC */
+						 <STM32_PINMUX('A', 4,  AF14)>,
+						 /* LCD_VSYNC */
+						 <STM32_PINMUX('G', 7,  AF14)>,
+						 /* LCD_CLK */
+						 <STM32_PINMUX('C', 10, AF14)>,
+						 /* LCD_R2 */
+						 <STM32_PINMUX('B', 0,  AF9)>,
+						 /* LCD_R3 */
+						 <STM32_PINMUX('A', 11, AF14)>,
+						 /* LCD_R4 */
+						 <STM32_PINMUX('A', 12, AF14)>,
+						 /* LCD_R5 */
+						 <STM32_PINMUX('B', 1,  AF9)>,
+						 /* LCD_R6*/
+						 <STM32_PINMUX('G', 6,  AF14)>,
+						 /* LCD_R7 */
+						 <STM32_PINMUX('A', 6,  AF14)>,
+						 /* LCD_G2 */
+						 <STM32_PINMUX('G', 10, AF9)>,
+						 /* LCD_G3 */
+						 <STM32_PINMUX('B', 10, AF14)>,
+						 /* LCD_G4 */
+						 <STM32_PINMUX('D', 6,  AF14)>,
+						 /* LCD_B2 */
+						 <STM32_PINMUX('G', 11, AF14)>,
+						 /* LCD_B3*/
+						 <STM32_PINMUX('B', 11, AF14)>,
+						 /* LCD_G5 */
+						 <STM32_PINMUX('C', 7,  AF14)>,
+						 /* LCD_G6 */
+						 <STM32_PINMUX('D', 3,  AF14)>,
+						 /* LCD_G7 */
+						 <STM32_PINMUX('G', 12, AF9)>,
+						 /* LCD_B4 */
+						 <STM32_PINMUX('A', 3,  AF14)>,
+						 /* LCD_B5 */
+						 <STM32_PINMUX('B', 8,  AF14)>,
+						 /* LCD_B6 */
+						 <STM32_PINMUX('B', 9,  AF14)>,
+						 /* LCD_B7 */
+						 <STM32_PINMUX('F', 10, AF14)>;
+						 /* LCD_DE */
+					slew-rate = <2>;
+				};
+			};
+
 			spi5_pins: spi5-0 {
 				pins1 {
 					pinmux = <STM32_PINMUX('F', 7, AF5)>,
-- 
2.7.4


_______________________________________________
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 v4 3/8] spi: stm32: Add 'SPI_SIMPLEX_RX', 'SPI_3WIRE_RX' support for stm32f4
From: dillon.minfei @ 2020-05-18 11:09 UTC (permalink / raw)
  To: robh+dt, p.zabel, mcoquelin.stm32, broonie, devicetree,
	alexandre.torgue, thierry.reding, sam, airlied, daniel,
	mturquette, sboyd
  Cc: linux-kernel, dri-devel, linux-stm32, linux-spi, dillon min,
	linux-clk, linux-arm-kernel
In-Reply-To: <1589800165-3271-1-git-send-email-dillon.minfei@gmail.com>

From: dillon min <dillon.minfei@gmail.com>

in l3gd20 driver startup, there is a setup failed error return from
stm32 spi driver

    "
    [    2.687630] st-gyro-spi spi0.0: supply vdd not found, using dummy
    regulator
    [    2.696869] st-gyro-spi spi0.0: supply vddio not found, using dummy
    regulator
    [    2.706707] spi_stm32 40015000.spi: SPI transfer setup failed
    [    2.713741] st-gyro-spi spi0.0: SPI transfer failed: -22
    [    2.721096] spi_master spi0: failed to transfer one message from queue
    [    2.729268] iio iio:device0: failed to read Who-Am-I register.
    [    2.737504] st-gyro-spi: probe of spi0.0 failed with error -22
    "

after debug into spi-stm32 driver, st-gyro-spi split two steps to read
l3gd20 id

first: send command to l3gd20 with read id command in tx_buf, rx_buf
is null.
second: read id with tx_buf is null, rx_buf not null.

so, for second step, stm32 driver recongise this process is 'SPI_SIMPLE_RX'
from stm32_spi_communication_type(), but there is no related process for this
type in stm32f4_spi_set_mode(), then we get error from
stm32_spi_transfer_one_setup().

we can use two method to fix this bug.
1, use stm32 spi's "In unidirectional receive-only mode (BIDIMODE=0 and
RXONLY=1)". but as our code running in sdram, the read latency is too large
to get so many receive overrun error in interrupts handler.

2, use stm32 spi's "In full-duplex (BIDIMODE=0 and RXONLY=0)", as tx_buf is
null, we must add dummy data sent out before read data.
so, add stm32f4_spi_tx_dummy() to handle this situation.

Signed-off-by: dillon min <dillon.minfei@gmail.com>
---
 drivers/spi/spi-stm32.c | 30 ++++++++++++++++++++++++++----
 1 file changed, 26 insertions(+), 4 deletions(-)

diff --git a/drivers/spi/spi-stm32.c b/drivers/spi/spi-stm32.c
index 44ac6eb3..72d9387 100644
--- a/drivers/spi/spi-stm32.c
+++ b/drivers/spi/spi-stm32.c
@@ -388,6 +388,14 @@ static int stm32h7_spi_get_fifo_size(struct stm32_spi *spi)
 	return count;
 }
 
+static void stm32f4_spi_tx_dummy(struct stm32_spi *spi)
+{
+	if (spi->cur_bpw == 16)
+		writew_relaxed(0x5555, spi->base + STM32F4_SPI_DR);
+	else
+		writeb_relaxed(0x55, spi->base + STM32F4_SPI_DR);
+}
+
 /**
  * stm32f4_spi_get_bpw_mask - Return bits per word mask
  * @spi: pointer to the spi controller data structure
@@ -811,7 +819,9 @@ static irqreturn_t stm32f4_spi_irq_event(int irq, void *dev_id)
 		mask |= STM32F4_SPI_SR_TXE;
 	}
 
-	if (!spi->cur_usedma && spi->cur_comm == SPI_FULL_DUPLEX) {
+	if (!spi->cur_usedma && (spi->cur_comm == SPI_FULL_DUPLEX ||
+				spi->cur_comm == SPI_SIMPLEX_RX ||
+				spi->cur_comm == SPI_3WIRE_RX)) {
 		/* TXE flag is set and is handled when RXNE flag occurs */
 		sr &= ~STM32F4_SPI_SR_TXE;
 		mask |= STM32F4_SPI_SR_RXNE | STM32F4_SPI_SR_OVR;
@@ -850,8 +860,10 @@ static irqreturn_t stm32f4_spi_irq_event(int irq, void *dev_id)
 		stm32f4_spi_read_rx(spi);
 		if (spi->rx_len == 0)
 			end = true;
-		else /* Load data for discontinuous mode */
+		else if (spi->tx_buf)/* Load data for discontinuous mode */
 			stm32f4_spi_write_tx(spi);
+		else if (spi->cur_comm == SPI_SIMPLEX_RX)
+			stm32f4_spi_tx_dummy(spi);
 	}
 
 end_irq:
@@ -1151,7 +1163,9 @@ static int stm32f4_spi_transfer_one_irq(struct stm32_spi *spi)
 	/* Enable the interrupts relative to the current communication mode */
 	if (spi->cur_comm == SPI_SIMPLEX_TX || spi->cur_comm == SPI_3WIRE_TX) {
 		cr2 |= STM32F4_SPI_CR2_TXEIE;
-	} else if (spi->cur_comm == SPI_FULL_DUPLEX) {
+	} else if (spi->cur_comm == SPI_FULL_DUPLEX ||
+				spi->cur_comm == SPI_SIMPLEX_RX ||
+				spi->cur_comm == SPI_3WIRE_RX) {
 		/* In transmit-only mode, the OVR flag is set in the SR register
 		 * since the received data are never read. Therefore set OVR
 		 * interrupt only when rx buffer is available.
@@ -1170,6 +1184,8 @@ static int stm32f4_spi_transfer_one_irq(struct stm32_spi *spi)
 	/* starting data transfer when buffer is loaded */
 	if (spi->tx_buf)
 		stm32f4_spi_write_tx(spi);
+	else if (spi->cur_comm == SPI_SIMPLEX_RX)
+		stm32f4_spi_tx_dummy(spi);
 
 	spin_unlock_irqrestore(&spi->lock, flags);
 
@@ -1462,10 +1478,16 @@ static int stm32f4_spi_set_mode(struct stm32_spi *spi, unsigned int comm_type)
 		stm32_spi_set_bits(spi, STM32F4_SPI_CR1,
 					STM32F4_SPI_CR1_BIDIMODE |
 					STM32F4_SPI_CR1_BIDIOE);
-	} else if (comm_type == SPI_FULL_DUPLEX) {
+	} else if (comm_type == SPI_FULL_DUPLEX ||
+				comm_type == SPI_SIMPLEX_RX) {
 		stm32_spi_clr_bits(spi, STM32F4_SPI_CR1,
 					STM32F4_SPI_CR1_BIDIMODE |
 					STM32F4_SPI_CR1_BIDIOE);
+	} else if (comm_type == SPI_3WIRE_RX) {
+		stm32_spi_set_bits(spi, STM32F4_SPI_CR1,
+					STM32F4_SPI_CR1_BIDIMODE);
+		stm32_spi_clr_bits(spi, STM32F4_SPI_CR1,
+					STM32F4_SPI_CR1_BIDIOE);
 	} else {
 		return -EINVAL;
 	}
-- 
2.7.4


_______________________________________________
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 v4 2/8] ARM: dts: stm32: enable l3gd20 on stm32429-disco board
From: dillon.minfei @ 2020-05-18 11:09 UTC (permalink / raw)
  To: robh+dt, p.zabel, mcoquelin.stm32, broonie, devicetree,
	alexandre.torgue, thierry.reding, sam, airlied, daniel,
	mturquette, sboyd
  Cc: linux-kernel, dri-devel, linux-stm32, linux-spi, dillon min,
	linux-clk, linux-arm-kernel
In-Reply-To: <1589800165-3271-1-git-send-email-dillon.minfei@gmail.com>

From: dillon min <dillon.minfei@gmail.com>

L3gd20, st mems motion sensor, 3-axis digital output gyroscope,
connect to stm32f429 via spi5

Signed-off-by: dillon min <dillon.minfei@gmail.com>
---
 arch/arm/boot/dts/stm32f4-pinctrl.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/arm/boot/dts/stm32f4-pinctrl.dtsi b/arch/arm/boot/dts/stm32f4-pinctrl.dtsi
index 392fa14..54c1b27 100644
--- a/arch/arm/boot/dts/stm32f4-pinctrl.dtsi
+++ b/arch/arm/boot/dts/stm32f4-pinctrl.dtsi
@@ -316,6 +316,23 @@
 				};
 			};
 
+			spi5_pins: spi5-0 {
+				pins1 {
+					pinmux = <STM32_PINMUX('F', 7, AF5)>,
+						/* SPI5_CLK */
+						 <STM32_PINMUX('F', 9, AF5)>;
+						/* SPI5_MOSI */
+					bias-disable;
+					drive-push-pull;
+					slew-rate = <0>;
+				};
+				pins2 {
+					pinmux = <STM32_PINMUX('F', 8, AF5)>;
+						/* SPI5_MISO */
+					bias-disable;
+				};
+			};
+
 			dcmi_pins: dcmi-0 {
 				pins {
 					pinmux = <STM32_PINMUX('A', 4, AF13)>, /* DCMI_HSYNC */
-- 
2.7.4


_______________________________________________
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 v4 1/8] ARM: dts: stm32: Add dma config for spi5
From: dillon.minfei @ 2020-05-18 11:09 UTC (permalink / raw)
  To: robh+dt, p.zabel, mcoquelin.stm32, broonie, devicetree,
	alexandre.torgue, thierry.reding, sam, airlied, daniel,
	mturquette, sboyd
  Cc: linux-kernel, dri-devel, linux-stm32, linux-spi, dillon min,
	linux-clk, linux-arm-kernel
In-Reply-To: <1589800165-3271-1-git-send-email-dillon.minfei@gmail.com>

From: dillon min <dillon.minfei@gmail.com>

Enable spi5's dma configuration. for graphics data output to
ilitek ili9341 panel via mipi dbi interface

Signed-off-by: dillon min <dillon.minfei@gmail.com>
---
 arch/arm/boot/dts/stm32f429.dtsi | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/boot/dts/stm32f429.dtsi b/arch/arm/boot/dts/stm32f429.dtsi
index d777069..5820b11 100644
--- a/arch/arm/boot/dts/stm32f429.dtsi
+++ b/arch/arm/boot/dts/stm32f429.dtsi
@@ -660,6 +660,9 @@
 			reg = <0x40015000 0x400>;
 			interrupts = <85>;
 			clocks = <&rcc 0 STM32F4_APB2_CLOCK(SPI5)>;
+			dmas = <&dma2 3 2 0x400 0x0>,
+				<&dma2 4 2 0x400 0x0>;
+			dma-names = "rx", "tx";
 			status = "disabled";
 		};
 
-- 
2.7.4


_______________________________________________
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 v4 0/8] Enable ili9341 and l3gd20 on stm32f429-disco
From: dillon.minfei @ 2020-05-18 11:09 UTC (permalink / raw)
  To: robh+dt, p.zabel, mcoquelin.stm32, broonie, devicetree,
	alexandre.torgue, thierry.reding, sam, airlied, daniel,
	mturquette, sboyd
  Cc: linux-kernel, dri-devel, linux-stm32, linux-spi, dillon min,
	linux-clk, linux-arm-kernel

From: dillon min <dillon.minfei@gmail.com>

According to alexandre torgue's suggestion, combine ili9341 and
l3gd20's modification on stm32f429-disco board to one patchset.

Changes:

ili9341:

V4:
1 update ili9341 panel driver according to Linus's suggestion
2 drop V1's No.5 patch, sumbit new changes for clk-stm32f4
3 merge l3gd20's change to this patchset

V3:
1 merge original tiny/ili9341.c driver to panel/panel-ilitek-ili9341.c
  to support serial spi & parallel rgb interface in one driver.
2 update ilitek,ili9341.yaml dts binding documentation.
3 update stm32f429-disco dts binding

V2:
1 verify ilitek,ili9341.yaml with make O=../linux-stm32
   dt_binding_check
   DT_SCHEMA_FILES=Documentation/devicetree/bindings/display/panel/
   ilitek,ili9341.yaml

V1:
1 add ili9341 drm panel driver
2 add ltdc, spi5 controller for stm32f429-disco
3 add ltdc, spi5 pin map for stm32f429-disco
4 add docs about ili9341
5 fix ltdc driver loading hang in clk set rate bug


L3gd20:

V3:
1, merge stm32f429-disco dtbs binding with ili9341 part

V2:
1, insert blank line at stm32f420-disco.dts line 143
2, add more description for l3gd20 in commit message

V1:
1, enable spi5 controller on stm32f429-disco (dts)
2, add spi5 pinmap for stm32f429-disco  (dts)
3, add SPI_SIMPLEX_RX, SPI_3WIRE_RX support for stm32f4

dillon min (8):
  ARM: dts: stm32: Add dma config for spi5
  ARM: dts: stm32: enable l3gd20 on stm32429-disco board
  spi: stm32: Add 'SPI_SIMPLEX_RX', 'SPI_3WIRE_RX' support for stm32f4
  ARM: dts: stm32: Add pin map for ltdc on stm32f429-disco board
  dt-bindings: display: panel: Add ilitek ili9341 panel bindings
  ARM: dts: stm32: enable ltdc binding with ili9341 on stm32429-disco
    board
  clk: stm32: Fix stm32f429's ltdc driver hang in set clock rate.
  drm/panel: Add ilitek ili9341 panel driver

 .../bindings/display/panel/ilitek,ili9341.yaml     |   69 ++
 arch/arm/boot/dts/stm32f4-pinctrl.dtsi             |   67 +
 arch/arm/boot/dts/stm32f429-disco.dts              |   48 +
 arch/arm/boot/dts/stm32f429.dtsi                   |    3 +
 drivers/clk/clk-stm32f4.c                          |    7 +-
 drivers/gpu/drm/panel/Kconfig                      |   12 +
 drivers/gpu/drm/panel/Makefile                     |    1 +
 drivers/gpu/drm/panel/panel-ilitek-ili9341.c       | 1301 ++++++++++++++++++++
 drivers/spi/spi-stm32.c                            |   30 +-
 9 files changed, 1530 insertions(+), 8 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/display/panel/ilitek,ili9341.yaml
 create mode 100644 drivers/gpu/drm/panel/panel-ilitek-ili9341.c

-- 
2.7.4


_______________________________________________
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/4] dt-bindings: i2c-stm32: add SMBus Alert bindings
From: Alain Volmat @ 2020-05-18 10:53 UTC (permalink / raw)
  To: Rob Herring, wsa@kernel.org
  Cc: mark.rutland@arm.com, devicetree@vger.kernel.org,
	Alexandre TORGUE, linux-kernel@vger.kernel.org,
	Pierre Yves MORDRET, linux-i2c@vger.kernel.org,
	mcoquelin.stm32@gmail.com, Fabrice GASNIER,
	linux-stm32@st-md-mailman.stormreply.com,
	linux-arm-kernel@lists.infradead.org
In-Reply-To: <20200513054231.GA16558@gnbcxd0016.gnb.st.com>

Gentle Reminder, as I wrote in my previous responce, smbus_alert interrupt
refers to an host and not a client. And since we do not have a dedicated
irq for smbus_alert, I propose to add this st, binding to enable the
smbus_alert mechanism.

On Wed, May 13, 2020 at 07:42:31AM +0200, Alain Volmat wrote:
> Hello Rob,
> 
> On Wed, May 13, 2020 at 02:19:32AM +0000, Rob Herring wrote:
> > On Tue, May 05, 2020 at 07:51:10AM +0200, Alain Volmat wrote:
> > > Add a new binding of the i2c-stm32f7 driver to enable the handling
> > > of the SMBUS-Alert
> > > 
> > > Signed-off-by: Alain Volmat <alain.volmat@st.com>
> > > ---
> > >  Documentation/devicetree/bindings/i2c/st,stm32-i2c.yaml | 4 ++++
> > >  1 file changed, 4 insertions(+)
> > > 
> > > diff --git a/Documentation/devicetree/bindings/i2c/st,stm32-i2c.yaml b/Documentation/devicetree/bindings/i2c/st,stm32-i2c.yaml
> > > index b50a2f420b36..04c0882c3661 100644
> > > --- a/Documentation/devicetree/bindings/i2c/st,stm32-i2c.yaml
> > > +++ b/Documentation/devicetree/bindings/i2c/st,stm32-i2c.yaml
> > > @@ -36,6 +36,10 @@ allOf:
> > >                  minItems: 3
> > >                  maxItems: 3
> > >  
> > > +        st,smbus-alert:
> > > +          description: Enable the SMBus Alert feature
> > > +          $ref: /schemas/types.yaml#/definitions/flag
> > > +
> > 
> > We already have smbus_alert interrupt. Can't you just check for this in 
> > the slave nodes and enable if found?
> 
> My understanding reading the code (smbalert_probe within i2c-smbus.c, of_i2c_setup_smbus_alert called when
> registering an adapter within i2c-core-smbus.c) is that smbus_alert refers to an interrupt on the
> adapter side. That is an interrupt that would be triggered when the adapter is receiving an smbus_alert
> message.
> In our case (stm32f7), we do not have specific interrupt for that purpose. The interrupt triggered when
> an SMBUS Alert is received (by the adapter) is the same interrupt as for other reasons and we check
> within the irq handler within stm32f7 the reason before calling i2c_handle_smbus_alert if the status
> register indicated an SMBUS Alert.
> So my understanding is that we cannot rely on the mechanism of naming an interrupt smbus_alert.
> Did I misunderstood something ?
> 
> > 
> > >    - if:
> > >        properties:
> > >          compatible:
> > > -- 
> > > 2.17.1
> > > 

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCHv2 0/7] Support inhibiting input devices
From: Andrzej Pietrasiewicz @ 2020-05-18 10:48 UTC (permalink / raw)
  To: Hans de Goede, linux-input, linux-acpi, linux-iio,
	linux-arm-kernel, linux-samsung-soc, linux-tegra, patches,
	ibm-acpi-devel, platform-driver-x86
  Cc: Nick Dyer, Benjamin Tissoires, Laxman Dewangan,
	Peter Meerwald-Stadler, kernel, Fabio Estevam, Lars-Peter Clausen,
	Krzysztof Kozlowski, Jonathan Hunter, Kukjin Kim, NXP Linux Team,
	Sylvain Lemieux, Len Brown, Peter Hutterer, Michael Hennerich,
	Sascha Hauer, Henrique de Moraes Holschuh, Vladimir Zapolskiy,
	Barry Song, Ferruh Yigit, Dmitry Torokhov, Rafael J . Wysocki,
	Thierry Reding, Sangwon Jee, Pengutronix Kernel Team,
	Hartmut Knaack, Shawn Guo, Jonathan Cameron
In-Reply-To: <842b95bb-8391-5806-fe65-be64b02de122@redhat.com>

Hi Hans,

W dniu 15.05.2020 o 20:19, Hans de Goede pisze:
> Hi Andrezj,
> 
> On 5/15/20 6:49 PM, Andrzej Pietrasiewicz wrote:
>> Userspace might want to implement a policy to temporarily disregard input
>> from certain devices, including not treating them as wakeup sources.
>>
>> An example use case is a laptop, whose keyboard can be folded under the
>> screen to create tablet-like experience. The user then must hold the laptop
>> in such a way that it is difficult to avoid pressing the keyboard keys. It
>> is therefore desirable to temporarily disregard input from the keyboard,
>> until it is folded back. This obviously is a policy which should be kept
>> out of the kernel, but the kernel must provide suitable means to implement
>> such a policy.
> 
> Actually libinput already binds together (inside libinput) SW_TABLET_MODE
> generating evdev nodes and e.g. internal keyboards on devices with 360°
> hinges for this reason. libinput simply closes the /dev/input/event#
> node when folded and re-opens it when the keyboard should become active
> again. Thus not only suppresses events but allows e.g. touchpads to
> enter runtime suspend mode which saves power. Typically closing the
> /dev/input/event# node will also disable the device as wakeup source.
> 
> So I wonder what this series actually adds for functionality for
> userspace which can not already be achieved this way?
> 
> I also noticed that you keep the device open (do not call the
> input_device's close callback) when inhibited and just throw away

I'm not sure if I understand you correctly, it is called:

+static inline void input_stop(struct input_dev *dev)
+{
+	if (dev->poller)
+		input_dev_poller_stop(dev->poller);
+	if (dev->close)
+		dev->close(dev);
                 ^^^^^^^^^^^^^^^^
+static int input_inhibit(struct input_dev *dev)
+{
+	int ret = 0;
+
+	mutex_lock(&dev->mutex);
+
+	if (dev->inhibited)
+		goto out;
+
+	if (dev->users) {
+		if (dev->inhibit) {
+			ret = dev->inhibit(dev);
+			if (ret)
+				goto out;
+		}
+		input_stop(dev);
                 ^^^^^^^^^^^^^^^^

It will not be called when dev->users is zero, but if it is zero,
then nobody has opened the device yet so there is nothing to close.

Andrzej

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox