Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 2/3] ARM: dts: bcm2711: Update SPI nodes compatible strings
From: Florian Fainelli @ 2020-06-04  3:46 UTC (permalink / raw)
  To: linux-kernel
  Cc: moderated list:BROADCOM BCM2711/BCM2835 ARM ARCHITECTURE,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Florian Fainelli, Scott Branden, lukas, Ray Jui, Rob Herring,
	open list:SPI SUBSYSTEM, Mark Brown,
	maintainer:BROADCOM BCM281XX/BCM11XXX/BCM216XX ARM ARCHITE...,
	moderated list:BROADCOM BCM2711/BCM2835 ARM ARCHITECTURE,
	Martin Sperl, Nicolas Saenz Julienne
In-Reply-To: <20200604034655.15930-1-f.fainelli@gmail.com>

The BCM2711 SoC features 5 SPI controllers which all share the same
interrupt line, the SPI driver needs to support interrupt sharing,
therefore use the chip specific compatible string to help with that.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 arch/arm/boot/dts/bcm2711.dtsi | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boot/dts/bcm2711.dtsi b/arch/arm/boot/dts/bcm2711.dtsi
index a91cf68e3c4c..9a9ea67fbc2d 100644
--- a/arch/arm/boot/dts/bcm2711.dtsi
+++ b/arch/arm/boot/dts/bcm2711.dtsi
@@ -152,7 +152,7 @@
 		};
 
 		spi3: spi@7e204600 {
-			compatible = "brcm,bcm2835-spi";
+			compatible = "brcm,bcm2711-spi", "brcm,bcm2835-spi";
 			reg = <0x7e204600 0x0200>;
 			interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clocks BCM2835_CLOCK_VPU>;
@@ -162,7 +162,7 @@
 		};
 
 		spi4: spi@7e204800 {
-			compatible = "brcm,bcm2835-spi";
+			compatible = "brcm,bcm2711-spi", "brcm,bcm2835-spi";
 			reg = <0x7e204800 0x0200>;
 			interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clocks BCM2835_CLOCK_VPU>;
@@ -172,7 +172,7 @@
 		};
 
 		spi5: spi@7e204a00 {
-			compatible = "brcm,bcm2835-spi";
+			compatible = "brcm,bcm2711-spi", "brcm,bcm2835-spi";
 			reg = <0x7e204a00 0x0200>;
 			interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clocks BCM2835_CLOCK_VPU>;
@@ -182,7 +182,7 @@
 		};
 
 		spi6: spi@7e204c00 {
-			compatible = "brcm,bcm2835-spi";
+			compatible = "brcm,bcm2711-spi", "brcm,bcm2835-spi";
 			reg = <0x7e204c00 0x0200>;
 			interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clocks BCM2835_CLOCK_VPU>;
-- 
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 related

* [PATCH 3/3] spi: bcm2835: Enable shared interrupt support
From: Florian Fainelli @ 2020-06-04  3:46 UTC (permalink / raw)
  To: linux-kernel
  Cc: moderated list:BROADCOM BCM2711/BCM2835 ARM ARCHITECTURE,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Florian Fainelli, Scott Branden, lukas, Ray Jui, Rob Herring,
	open list:SPI SUBSYSTEM, Mark Brown,
	maintainer:BROADCOM BCM281XX/BCM11XXX/BCM216XX ARM ARCHITE...,
	moderated list:BROADCOM BCM2711/BCM2835 ARM ARCHITECTURE,
	Martin Sperl, Nicolas Saenz Julienne
In-Reply-To: <20200604034655.15930-1-f.fainelli@gmail.com>

The SPI controller found in the BCM2711 and BCM7211 SoCs is instantiated
5 times, with all instances sharing the same interrupt line. We
specifically match the two compatible strings here to determine whether
it is necessary to request the interrupt with the IRQF_SHARED flag and
to use an appropriate interrupt handler capable of returning IRQ_NONE.

For the BCM2835 case which is deemed performance critical, there is no
overhead since a dedicated handler that does not assume sharing is used.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 drivers/spi/spi-bcm2835.c | 48 +++++++++++++++++++++++++++++++--------
 1 file changed, 38 insertions(+), 10 deletions(-)

diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c
index 237bd306c268..2e73ec70ee80 100644
--- a/drivers/spi/spi-bcm2835.c
+++ b/drivers/spi/spi-bcm2835.c
@@ -361,11 +361,10 @@ static void bcm2835_spi_reset_hw(struct spi_controller *ctlr)
 	bcm2835_wr(bs, BCM2835_SPI_DLEN, 0);
 }
 
-static irqreturn_t bcm2835_spi_interrupt(int irq, void *dev_id)
+static inline irqreturn_t bcm2835_spi_interrupt_common(struct spi_controller *ctlr,
+						       u32 cs)
 {
-	struct spi_controller *ctlr = dev_id;
 	struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr);
-	u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS);
 
 	/*
 	 * An interrupt is signaled either if DONE is set (TX FIFO empty)
@@ -394,6 +393,27 @@ static irqreturn_t bcm2835_spi_interrupt(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
+static irqreturn_t bcm2835_spi_interrupt(int irq, void *dev_id)
+{
+	struct spi_controller *ctlr = dev_id;
+	struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr);
+	u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS);
+
+	return bcm2835_spi_interrupt_common(ctlr, cs);
+}
+
+static irqreturn_t bcm2835_spi_sh_interrupt(int irq, void *dev_id)
+{
+	struct spi_controller *ctlr = dev_id;
+	struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr);
+	u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS);
+
+	if (!(cs & BCM2835_SPI_CS_INTR))
+		return IRQ_NONE;
+
+	return bcm2835_spi_interrupt_common(ctlr, cs);
+}
+
 static int bcm2835_spi_transfer_one_irq(struct spi_controller *ctlr,
 					struct spi_device *spi,
 					struct spi_transfer *tfr,
@@ -1287,12 +1307,26 @@ static int bcm2835_spi_setup(struct spi_device *spi)
 	return 0;
 }
 
+static const struct of_device_id bcm2835_spi_match[] = {
+	{ .compatible = "brcm,bcm2835-spi", .data = &bcm2835_spi_interrupt },
+	{ .compatible = "brcm,bcm2711-spi", .data = &bcm2835_spi_sh_interrupt },
+	{ .compatible = "brcm,bcm7211-spi", .data = &bcm2835_spi_sh_interrupt },
+	{}
+};
+MODULE_DEVICE_TABLE(of, bcm2835_spi_match);
+
 static int bcm2835_spi_probe(struct platform_device *pdev)
 {
+	irqreturn_t (*bcm2835_spi_isr_func)(int, void *);
 	struct spi_controller *ctlr;
+	unsigned long flags = 0;
 	struct bcm2835_spi *bs;
 	int err;
 
+	bcm2835_spi_isr_func = of_device_get_match_data(&pdev->dev);
+	if (bcm2835_spi_isr_func == &bcm2835_spi_sh_interrupt)
+		flags = IRQF_SHARED;
+
 	ctlr = spi_alloc_master(&pdev->dev, ALIGN(sizeof(*bs),
 						  dma_get_cache_alignment()));
 	if (!ctlr)
@@ -1344,7 +1378,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
 	bcm2835_wr(bs, BCM2835_SPI_CS,
 		   BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX);
 
-	err = devm_request_irq(&pdev->dev, bs->irq, bcm2835_spi_interrupt, 0,
+	err = devm_request_irq(&pdev->dev, bs->irq, bcm2835_spi_isr_func, flags,
 			       dev_name(&pdev->dev), ctlr);
 	if (err) {
 		dev_err(&pdev->dev, "could not request IRQ: %d\n", err);
@@ -1400,12 +1434,6 @@ static void bcm2835_spi_shutdown(struct platform_device *pdev)
 		dev_err(&pdev->dev, "failed to shutdown\n");
 }
 
-static const struct of_device_id bcm2835_spi_match[] = {
-	{ .compatible = "brcm,bcm2835-spi", },
-	{}
-};
-MODULE_DEVICE_TABLE(of, bcm2835_spi_match);
-
 static struct platform_driver bcm2835_spi_driver = {
 	.driver		= {
 		.name		= DRV_NAME,
-- 
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 related

* Re: [PATCH V2] dt-bindings: clock: Convert imx7ulp clock to json-schema
From: Stephen Boyd @ 2020-06-04  4:40 UTC (permalink / raw)
  To: Anson Huang, aisheng.dong, devicetree, festevam, kernel,
	linux-arm-kernel, linux-clk, linux-kernel, mturquette, robh+dt,
	s.hauer, shawnguo
  Cc: Linux-imx
In-Reply-To: <1591234387-15059-1-git-send-email-Anson.Huang@nxp.com>

Quoting Anson Huang (2020-06-03 18:33:07)
> Convert the i.MX7ULP clock binding to DT schema format using json-schema,
> the original binding doc is actually for two clock modules(SCG and PCC),
> so split it to two binding docs, and the MPLL(mipi PLL) is NOT supposed
> to be in clock module, so remove it from binding doc as well.
> 
> Signed-off-by: Anson Huang <Anson.Huang@nxp.com>
> ---

Reviewed-by: Stephen Boyd <sboyd@kernel.org>

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

^ permalink raw reply

* [PATCH] soc: amlogic: meson-gx-socinfo: Fix S905X3 ID
From: Christian Hewitt @ 2020-06-04  4:48 UTC (permalink / raw)
  To: Rob Herring, Mark Rutland, Kevin Hilman, devicetree,
	linux-arm-kernel, linux-amlogic, linux-kernel
  Cc: Christian Hewitt

The current value is taken from Amlogic's 4.9 bsp kernel which appears
to use the wrong ID. For comparison, here's before/after:

[    0.152237] soc soc0: Amlogic Meson SM1 (Unknown) Revision 2b:c (10:2) Detected
[    0.152463] soc soc0: Amlogic Meson SM1 (S905X3) Revision 2b:c (10:2) Detected

Fixes c9cc9bec36d0 ("soc: amlogic: meson-gx-socinfo: Add SM1 and S905X3 IDs")
Signed-off-by: Christian Hewitt <christianshewitt@gmail.com>
---
 drivers/soc/amlogic/meson-gx-socinfo.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/soc/amlogic/meson-gx-socinfo.c b/drivers/soc/amlogic/meson-gx-socinfo.c
index 01fc0d20a70d..c38a1e4db28b 100644
--- a/drivers/soc/amlogic/meson-gx-socinfo.c
+++ b/drivers/soc/amlogic/meson-gx-socinfo.c
@@ -68,7 +68,7 @@ static const struct meson_gx_package_id {
 	{ "S905X2", 0x28, 0x40, 0xf0 },
 	{ "S922X", 0x29, 0x40, 0xf0 },
 	{ "A311D", 0x29, 0x10, 0xf0 },
-	{ "S905X3", 0x2b, 0x5, 0xf },
+	{ "S905X3", 0x2b, 0x10, 0xf0 },
 	{ "S905D3", 0x2b, 0xb0, 0xf0 },
 	{ "A113L", 0x2c, 0x0, 0xf8 },
 };
-- 
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 related

* RE: [EXT] Re: [PATCH v6 2/2] arm64/crash_core: Export TCR_EL1.T1SZ in vmcoreinfo
From: Kamlakant Patel @ 2020-06-04  4:49 UTC (permalink / raw)
  To: Bhupesh Sharma
  Cc: Mark Rutland, Kazuhito Hagio, Ganapatrao Kulkarni, Steve Capper,
	Catalin Marinas, x86@kernel.org, kexec@lists.infradead.org,
	linux-kernel@vger.kernel.org, Ard Biesheuvel, James Morse,
	Dave Anderson, bhupesh.linux@gmail.com, Will Deacon,
	linux-arm-kernel@lists.infradead.org
In-Reply-To: <CACi5LpOyQ+MAg9rh=cgLprBGTZ3kvtVP1ShNKG-2AV1Tu14EgQ@mail.gmail.com>

Hi Bhupesh,

> -----Original Message-----
> From: Bhupesh Sharma <bhsharma@redhat.com>
> Sent: Thursday, June 4, 2020 2:05 AM
> To: Kamlakant Patel <kamlakantp@marvell.com>
> Cc: linux-arm-kernel@lists.infradead.org; x86@kernel.org; Mark Rutland
> <mark.rutland@arm.com>; Kazuhito Hagio <k-hagio@ab.jp.nec.com>; Steve
> Capper <steve.capper@arm.com>; Catalin Marinas
> <catalin.marinas@arm.com>; Ard Biesheuvel <ard.biesheuvel@linaro.org>;
> kexec@lists.infradead.org; linux-kernel@vger.kernel.org; James Morse
> <james.morse@arm.com>; Dave Anderson <anderson@redhat.com>;
> bhupesh.linux@gmail.com; Will Deacon <will@kernel.org>; Ganapatrao Kulkarni
> <gkulkarni@marvell.com>
> Subject: [EXT] Re: [PATCH v6 2/2] arm64/crash_core: Export TCR_EL1.T1SZ in
> vmcoreinfo
> 
> External Email
> 
> ----------------------------------------------------------------------
> Hi Kamlakant,
> 
> Many thanks for having a look at the patchset.
> 
> On Wed, Jun 3, 2020 at 4:50 PM Kamlakant Patel <kamlakantp@marvell.com>
> wrote:
> >
> > Hi Bhupesh,
> >
> > > -----Original Message-----
> > > From: kexec <kexec-bounces@lists.infradead.org> On Behalf Of Bhupesh
> > > Sharma
> > > Sent: Thursday, May 14, 2020 12:23 AM
> > > To: linux-arm-kernel@lists.infradead.org; x86@kernel.org
> > > Cc: Mark Rutland <mark.rutland@arm.com>; Kazuhito Hagio <k-
> > > hagio@ab.jp.nec.com>; Steve Capper <steve.capper@arm.com>; Catalin
> > > Marinas <catalin.marinas@arm.com>; bhsharma@redhat.com; Ard
> > > Biesheuvel <ard.biesheuvel@linaro.org>; kexec@lists.infradead.org;
> > > linux- kernel@vger.kernel.org; James Morse <james.morse@arm.com>;
> > > Dave Anderson <anderson@redhat.com>; bhupesh.linux@gmail.com; Will
> > > Deacon <will@kernel.org>
> > > Subject: [PATCH v6 2/2] arm64/crash_core: Export TCR_EL1.T1SZ in
> > > vmcoreinfo
> > >
> > > vabits_actual variable on arm64 indicates the actual VA space size,
> > > and allows a single binary to support both 48-bit and 52-bit VA spaces.
> > >
> > > If the ARMv8.2-LVA optional feature is present, and we are running
> > > with a 64KB page size; then it is possible to use 52-bits of address
> > > space for both userspace and kernel addresses. However, any kernel
> > > binary that supports 52-bit must also be able to fall back to 48-bit
> > > at early boot time if the hardware feature is not present.
> > >
> > > Since TCR_EL1.T1SZ indicates the size offset of the memory region
> > > addressed by
> > > TTBR1_EL1 (and hence can be used for determining the vabits_actual
> > > value) it makes more sense to export the same in vmcoreinfo rather
> > > than vabits_actual variable, as the name of the variable can change
> > > in future kernel versions, but the architectural constructs like
> > > TCR_EL1.T1SZ can be used better to indicate intended specific fields to user-
> space.
> > >
> > > User-space utilities like makedumpfile and crash-utility, need to
> > > read this value from vmcoreinfo for determining if a virtual address lies in the
> linear map range.
> > >
> > > While at it also add documentation for TCR_EL1.T1SZ variable being
> > > added to vmcoreinfo.
> > >
> > > It indicates the size offset of the memory region addressed by
> > > TTBR1_EL1
> > >
> > > Cc: James Morse <james.morse@arm.com>
> > > Cc: Mark Rutland <mark.rutland@arm.com>
> > > Cc: Will Deacon <will@kernel.org>
> > > Cc: Steve Capper <steve.capper@arm.com>
> > > Cc: Catalin Marinas <catalin.marinas@arm.com>
> > > Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> > > Cc: Dave Anderson <anderson@redhat.com>
> > > Cc: Kazuhito Hagio <k-hagio@ab.jp.nec.com>
> > > Cc: linux-arm-kernel@lists.infradead.org
> > > Cc: linux-kernel@vger.kernel.org
> > > Cc: kexec@lists.infradead.org
> > > Tested-by: John Donnelly <john.p.donnelly@oracle.com>
> > > Signed-off-by: Bhupesh Sharma <bhsharma@redhat.com>
> > > ---
> > >  Documentation/admin-guide/kdump/vmcoreinfo.rst | 11 +++++++++++
> > >  arch/arm64/include/asm/pgtable-hwdef.h         |  1 +
> > >  arch/arm64/kernel/crash_core.c                 | 10 ++++++++++
> > >  3 files changed, 22 insertions(+)
> > >
> > > diff --git a/Documentation/admin-guide/kdump/vmcoreinfo.rst
> > > b/Documentation/admin-guide/kdump/vmcoreinfo.rst
> > > index 2a632020f809..2baad0bfb09d 100644
> > > --- a/Documentation/admin-guide/kdump/vmcoreinfo.rst
> > > +++ b/Documentation/admin-guide/kdump/vmcoreinfo.rst
> > > @@ -404,6 +404,17 @@ KERNELPACMASK
> > >  The mask to extract the Pointer Authentication Code from a kernel
> > > virtual address.
> > >
> > > +TCR_EL1.T1SZ
> > > +------------
> > > +
> > > +Indicates the size offset of the memory region addressed by TTBR1_EL1.
> > > +The region size is 2^(64-T1SZ) bytes.
> > > +
> > > +TTBR1_EL1 is the table base address register specified by ARMv8-A
> > > +architecture which is used to lookup the page-tables for the
> > > +Virtual addresses in the higher VA range (refer to ARMv8 ARM
> > > +document for more details).
> > > +
> > >  arm
> > >  ===
> > >
> > > diff --git a/arch/arm64/include/asm/pgtable-hwdef.h
> > > b/arch/arm64/include/asm/pgtable-hwdef.h
> > > index 6bf5e650da78..a1861af97ac9 100644
> > > --- a/arch/arm64/include/asm/pgtable-hwdef.h
> > > +++ b/arch/arm64/include/asm/pgtable-hwdef.h
> > > @@ -216,6 +216,7 @@
> > >  #define TCR_TxSZ(x)          (TCR_T0SZ(x) | TCR_T1SZ(x))
> > >  #define TCR_TxSZ_WIDTH               6
> > >  #define TCR_T0SZ_MASK                (((UL(1) << TCR_TxSZ_WIDTH) - 1) <<
> > > TCR_T0SZ_OFFSET)
> > > +#define TCR_T1SZ_MASK                (((UL(1) << TCR_TxSZ_WIDTH) - 1) <<
> > > TCR_T1SZ_OFFSET)
> > >
> > >  #define TCR_EPD0_SHIFT               7
> > >  #define TCR_EPD0_MASK                (UL(1) << TCR_EPD0_SHIFT)
> > > diff --git a/arch/arm64/kernel/crash_core.c
> > > b/arch/arm64/kernel/crash_core.c index 1f646b07e3e9..314391a156ee
> > > 100644
> > > --- a/arch/arm64/kernel/crash_core.c
> > > +++ b/arch/arm64/kernel/crash_core.c
> > > @@ -7,6 +7,14 @@
> > >  #include <linux/crash_core.h>
> > >  #include <asm/cpufeature.h>
> > >  #include <asm/memory.h>
> > > +#include <asm/pgtable-hwdef.h>
> > > +
> > > +static inline u64 get_tcr_el1_t1sz(void);
> > > +
> > > +static inline u64 get_tcr_el1_t1sz(void) {
> > > +     return (read_sysreg(tcr_el1) & TCR_T1SZ_MASK) >>
> > > +TCR_T1SZ_OFFSET; }
> > >
> > >  void arch_crash_save_vmcoreinfo(void)  { @@ -16,6 +24,8 @@ void
> > > arch_crash_save_vmcoreinfo(void)
> > >                                               kimage_voffset);
> > >       vmcoreinfo_append_str("NUMBER(PHYS_OFFSET)=0x%llx\n",
> > >                                               PHYS_OFFSET);
> > > +     vmcoreinfo_append_str("NUMBER(TCR_EL1_T1SZ)=0x%llx\n",
> > > +                                             get_tcr_el1_t1sz());
> > I tested this patch on top of upstream kernel v5.7 and I am getting "crash:
> cannot determine VA_BITS_ACTUAL" error with crash tool.
> > I looked into crash-utility source and it is expecting tcr_el1_t1sz not
> TCR_EL1_T1SZ.
> > Could you please check.
> 
> Indeed. As per James comments on the v5 (see [1]) where he suggested
> converting ttcr_el1_t1sz into TCR_EL1_T1SZ, I made the change in v6
> accordingly.
> 
> This time I haven't sent out the v6 userspace changes
> (makedumpfile/crash-utility) upstream first, since we are waiting for kernel
> changes to be accepted first, as we have seen in the past that while the
> userspace patches have been accepted, the kernel patches required a respin
> cycle, thus leading to inconsistencies, as you also pointed out with crash-utility.
> 
> If you want, for your local testing, I can share my github branch where I have
> kept the crash-utility v6 patchset ready. Please let me know.
> 
> [1]. https://urldefense.proofpoint.com/v2/url?u=https-
> 3A__lore.kernel.org_linuxppc-2Ddev_63d6e63c-2D7218-2Dd2dd-2D8767-
> 2D4464be83603f-
> 40arm.com_&d=DwIBaQ&c=nKjWec2b6R0mOyPaz7xtfQ&r=XecQZQJWhG6-
> mN8sWxffFOgUXg4irGP3Sjuy6RxdacQ&m=ijR8vEafG_QGTKYX2oI-
> SvfFsY4pPou6tvtrnxRoloo&s=zJmo3qbm2XfnKbrUqJPNN5o6PJqER9OzltwgS4aTa
> -k&e=
Thanks for clarifying.
I made userspace changes accordingly and tested and it works fine. We will be wait for your userspace patch.

Tested-by: Kamlakant Patel <kamlakantp@marvell.com>

Thanks,
Kamlakant Patel
> 
> Thanks,
> Bhupesh
> 
> 
> >
> > Thanks,
> > Kamlakant Patel
> > >       vmcoreinfo_append_str("KERNELOFFSET=%lx\n", kaslr_offset());
> > >       vmcoreinfo_append_str("NUMBER(KERNELPACMASK)=0x%llx\n",
> > >
> > >       system_supports_address_auth() ?
> > > --
> > > 2.7.4
> > >
> > >
> > > _______________________________________________
> > > kexec mailing list
> > > kexec@lists.infradead.org
> > > https://urldefense.proofpoint.com/v2/url?u=http-
> > > 3A__lists.infradead.org_mailman_listinfo_kexec&d=DwICAg&c=nKjWec2b6R
> > > 0m
> > > OyPaz7xtfQ&r=XecQZQJWhG6-
> > >
> mN8sWxffFOgUXg4irGP3Sjuy6RxdacQ&m=oeLdIVaWScimdfEc4dNhRI0tT24IgzG
> > > 7LkpAE5P11JQ&s=LLjHpz349DuDtORX4xywCxzbGUOagoq4JXosStycqI4&e=
> >

_______________________________________________
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] drm/sun4i: hdmi ddc clk: Fix size of m divider
From: Chen-Yu Tsai @ 2020-06-04  5:19 UTC (permalink / raw)
  To: Maxime Ripard, Jernej Škrabec
  Cc: David Airlie, linux-kernel, dri-devel, Daniel Vetter,
	linux-arm-kernel
In-Reply-To: <20200422092300.444wcaurdwyrorow@gilmour.lan>

On Wed, Apr 22, 2020 at 5:23 PM Maxime Ripard <maxime@cerno.tech> wrote:
>
> Hi,
>
> On Wed, Apr 15, 2020 at 07:52:28PM +0200, Jernej Škrabec wrote:
> > Dne sreda, 15. april 2020 ob 12:42:14 CEST je Maxime Ripard napisal(a):
> > > On Mon, Apr 13, 2020 at 06:09:08PM +0200, Jernej Škrabec wrote:
> > > > Dne ponedeljek, 13. april 2020 ob 16:12:39 CEST je Chen-Yu Tsai
> > napisal(a):
> > > > > On Mon, Apr 13, 2020 at 6:11 PM Chen-Yu Tsai <wens@csie.org> wrote:
> > > > > > On Mon, Apr 13, 2020 at 5:55 PM Jernej Skrabec
> > > > > > <jernej.skrabec@siol.net>
> > > >
> > > > wrote:
> > > > > > > m divider in DDC clock register is 4 bits wide. Fix that.
> > > > > > >
> > > > > > > Fixes: 9c5681011a0c ("drm/sun4i: Add HDMI support")
> > > > > > > Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> > > > > >
> > > > > > Reviewed-by: Chen-Yu Tsai <wens@csie.org>
> > > > >
> > > > > Cc stable?
> > > >
> > > > I don't think it's necessary:
> > > > 1. It doesn't change much (anything?) for me when reading EDID. I don't
> > > > think it's super important to have precise DDC clock in order to properly
> > > > read EDID. 2. No matter if it has "Cc stable" tag or not, it will be
> > > > eventually picked for stable due to fixes tag.
> > > >
> > > > This was only small observation when I was researching EDID readout issue
> > > > on A20 board, but sadly, I wasn't able to figure out why reading it
> > > > sometimes fails. I noticed similar issue on SoCs with DE2 (most
> > > > prominently on OrangePi PC2 - H5), but there was easy workaround - I just
> > > > disabled video driver in U- Boot. However, if A20 display driver gets
> > > > disabled in U-Boot, it totally breaks video output on my TV when Linux
> > > > boots (no output). I guess there is more fundamental problem with clocks
> > > > than just field size. I think we should add more constraints in clock
> > > > driver, like preset some clock parents and not allow to change parents
> > > > when setting rate, but carefully, so simplefb doesn't break. Such
> > > > constraints should also solve problems with dual head setups.
> > > I disagree here. Doing all sorts of special case just doesn't scale,
> > > and we'll never have the special cases sorted out on all the boards
> > > (and it's a nightmare to maintain).
> > >
> > > Especially since it's basically putting a blanket over the actual
> > > issue and looking the other way. If there's something wrong with how
> > > we deal with (re)parenting, we should fix that. It impacts more than
> > > just DRM, and all the SoCs.
> >
> > I agree with you that automatic solution would be best, but I just don't see
> > it how it would be done.
>
> > Dual head display pipeline is pretty complex for clock driver to get it right
> > on it's own. There are different possible setups and some of them are hot
> > pluggable, like HDMI.
>
> Do you have an actual scenario that is broken right now?
>
> > And there are also SoC specific quirks, like A64, where for some reason, MIPI
> > DPHY and HDMI PHY share same clock parent - PLL_VIDEO0. Technically, MIPI DPHY
> > can be clocked from PLL_PERIPH0 (fixed to 600 MHz), but that's not really
> > helpful. I'm not even sure if there is any good solution to this - certainly
> > HDMI and MIPI can't claim exclusivity and somehow best common rate must be
> > found for PLL_VIDEO0, if that's even possible.
>
> IIRC the DSI DPHY needs a clock running at 297MHz, which is pretty much what the
> HDMI PHY should need too (or 148.5, but that's pretty easy to generate from
> 297). So which problem do we have there?
>
> > I was sure that HDMI PHY on A64 can be clocked from PLL_VIDEO1, which would
> > solve main issue, but to date, I didn't find any way to do that.
> >
> > That's pretty off topic, so I hope original patch can be merged as-is.
>
> It does, sorry
>
> Acked-by: Maxime Ripard <maxime@cerno.tech>

Looks like this hasn't landed yet.

ChenYu

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

^ permalink raw reply

* Re: dmaengine: stm32-mdma: call pm_runtime_put if pm_runtime_get_sync fails
From: Markus Elfring @ 2020-06-04  5:43 UTC (permalink / raw)
  To: Geert Uytterhoeven, Navid Emamdoost, dmaengine, linux-arm-kernel,
	linux-stm32
  Cc: Maxime Coquelin, Alexandre Torgue, kernel-janitors, Kangjie Lu,
	linux-kernel, Vinod Koul, Navid Emamdoost, Qiushi Wu,
	Stephen McCamant, Dan Williams
In-Reply-To: <CAMuHMdU3wMT_pnh4NE9W9Su6qip_oObgd6OiRCwfuvouqjXKHA@mail.gmail.com>

>>> Calling pm_runtime_get_sync increments the counter even in case of
>>> failure, causing incorrect ref count. Call pm_runtime_put if
>>> pm_runtime_get_sync fails.
>>
>> Is it appropriate to copy a sentence from the change description
>> into the patch subject?
>>
>> How do you think about a wording variant like the following?
>>
>>    The PM runtime reference counter is generally incremented by a call of
>>    the function “pm_runtime_get_sync”.
>>    Thus call the function “pm_runtime_put” also in two error cases
>>    to keep the reference counting consistent.
>
> IMHO the important part is "even in case of failure", which you dropped.
> Missing that point was the root cause of the issue being fixed.
> Hence I prefer the original description, FWIW.

Would you like to comment any more of the presented patch review concerns?

Can it make sense to combine any adjustments into a single patch
according to the discussed software transformation pattern?
https://lore.kernel.org/patchwork/project/lkml/list/?submitter=26544&state=*&q=engine%3A+stm32&archive=both

Regards,
Markus

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

^ permalink raw reply

* Re: [RFC] dt-bindings: mailbox: add doorbell support to ARM MHU
From: Viresh Kumar @ 2020-06-04  5:59 UTC (permalink / raw)
  To: Sudeep Holla
  Cc: Rob Herring, Arnd Bergmann, devicetree, Jassi Brar, linux-kernel,
	Bjorn Andersson, Frank Rowand, linux-arm-kernel
In-Reply-To: <20200603181743.GC23722@bogus>

On 03-06-20, 19:17, Sudeep Holla wrote:
> I just realised that we have the timing info in the traces and you will
> observe the sensor readings take something in order of 100us to 500-600us
> or even more based on which sensor is being read. While we have 100us
> timeout for cpufreq opp set.

Which timeout from opp core are you talking about ?

-- 
viresh

_______________________________________________
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] arch/{mips,sparc,microblaze,powerpc}: Don't enable pagefault/preempt twice
From: Mike Rapoport @ 2020-06-04  6:18 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Peter Zijlstra, Benjamin Herrenschmidt, Dave Hansen, dri-devel,
	linux-mips, James E.J. Bottomley, Max Filippov, Paul Mackerras,
	H. Peter Anvin, sparclinux, Ira Weiny, Dan Williams, Helge Deller,
	x86, linux-csky, Christoph Hellwig, Ingo Molnar, linux-snps-arc,
	linux-xtensa, Borislav Petkov, Al Viro, Andy Lutomirski,
	Thomas Gleixner, linux-arm-kernel, Chris Zankel,
	Thomas Bogendoerfer, linux-parisc, linux-kernel, Christian Koenig,
	Andrew Morton, linuxppc-dev, David S. Miller
In-Reply-To: <3538c8ad-674e-d310-d870-4ef6888092ed@roeck-us.net>

On Wed, Jun 03, 2020 at 04:44:17PM -0700, Guenter Roeck wrote:
> On 6/3/20 2:14 PM, Ira Weiny wrote:
> > On Wed, Jun 03, 2020 at 01:57:36PM -0700, Andrew Morton wrote:
> >> On Thu, 21 May 2020 10:42:50 -0700 Ira Weiny <ira.weiny@intel.com> wrote:
> >>
> >>>>>
> >>>>> Actually it occurs to me that the patch consolidating kmap_prot is odd for
> >>>>> sparc 32 bit...
> >>>>>
> >>>>> Its a long shot but could you try reverting this patch?
> >>>>>
> >>>>> 4ea7d2419e3f kmap: consolidate kmap_prot definitions
> >>>>>
> >>>>
> >>>> That is not easy to revert, unfortunately, due to several follow-up patches.
> >>>
> >>> I have gotten your sparc tests to run and they all pass...
> >>>
> >>> 08:10:34 > ../linux-build-test/rootfs/sparc/run-qemu-sparc.sh 
> >>> Build reference: v5.7-rc4-17-g852b6f2edc0f
> >>>
> >>> Building sparc32:SPARCClassic:nosmp:scsi:hd ... running ......... passed
> >>> Building sparc32:SPARCbook:nosmp:scsi:cd ... running ......... passed
> >>> Building sparc32:LX:nosmp:noapc:scsi:hd ... running ......... passed
> >>> Building sparc32:SS-4:nosmp:initrd ... running ......... passed
> >>> Building sparc32:SS-5:nosmp:scsi:hd ... running ......... passed
> >>> Building sparc32:SS-10:nosmp:scsi:cd ... running ......... passed
> >>> Building sparc32:SS-20:nosmp:scsi:hd ... running ......... passed
> >>> Building sparc32:SS-600MP:nosmp:scsi:hd ... running ......... passed
> >>> Building sparc32:Voyager:nosmp:noapc:scsi:hd ... running ......... passed
> >>> Building sparc32:SS-4:smp:scsi:hd ... running ......... passed
> >>> Building sparc32:SS-5:smp:scsi:cd ... running ......... passed
> >>> Building sparc32:SS-10:smp:scsi:hd ... running ......... passed
> >>> Building sparc32:SS-20:smp:scsi:hd ... running ......... passed
> >>> Building sparc32:SS-600MP:smp:scsi:hd ... running ......... passed
> >>> Building sparc32:Voyager:smp:noapc:scsi:hd ... running ......... passed
> >>>
> >>> Is there another test I need to run?
> >>
> >> This all petered out, but as I understand it, this patchset still might
> >> have issues on various architectures.
> >>
> >> Can folks please provide an update on the testing status?
> > 
> > I believe the tests were failing for Guenter due to another patch set...[1]
> > 
> > My tests with just this series are working.
> > 
> >>From my understanding the other failures were unrelated.[2]
> > 
> > 	<quote Mike Rapoport>
> > 	I've checked the patch above on top of the mmots which already has
> > 	Ira's patches and it booted fine. I've used sparc32_defconfig to build
> > 	the kernel and qemu-system-sparc with default machine and CPU.
> > 	</quote>
> > 
> > Mike, am I wrong?  Do you think the kmap() patches are still causing issues?

sparc32 UP and microblaze work for me with next-20200603, but I didn't
test other architectures. 
 
> For my part, all I can say is that -next is in pretty bad shape right now.
> The summary of my tests says:
> 
> Build results:
> 	total: 151 pass: 130 fail: 21
> Qemu test results:
> 	total: 430 pass: 375 fail: 55
> 
> sparc32 smp images in next-20200603 still crash for me with a spinlock
> recursion.

I think this is because Will's fixes [1] are not yet in -next.

> s390 images hang early in boot. Several others (alpha, arm64,
> various ppc) don't even compile. I can run some more bisects over time,
> but this is becoming a full-time job :-(.
> 
> Guenter

[1] https://lore.kernel.org/lkml/20200526173302.377-1-will@kernel.org
-- 
Sincerely yours,
Mike.

_______________________________________________
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] arch/{mips,sparc,microblaze,powerpc}: Don't enable pagefault/preempt twice
From: Ira Weiny @ 2020-06-04  6:22 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Peter Zijlstra, Benjamin Herrenschmidt, Dave Hansen, dri-devel,
	linux-mips, James E.J. Bottomley, Max Filippov, Paul Mackerras,
	H. Peter Anvin, sparclinux, Dan Williams, Helge Deller, x86,
	linux-csky, Christoph Hellwig, Ingo Molnar, linux-snps-arc,
	linux-xtensa, Borislav Petkov, Al Viro, Andy Lutomirski,
	Thomas Gleixner, linux-arm-kernel, Chris Zankel,
	Thomas Bogendoerfer, linux-parisc, linux-kernel, Christian Koenig,
	Andrew Morton, linuxppc-dev, David S. Miller, Mike Rapoport
In-Reply-To: <3538c8ad-674e-d310-d870-4ef6888092ed@roeck-us.net>

On Wed, Jun 03, 2020 at 04:44:17PM -0700, Guenter Roeck wrote:
> On 6/3/20 2:14 PM, Ira Weiny wrote:
> > On Wed, Jun 03, 2020 at 01:57:36PM -0700, Andrew Morton wrote:
> >> On Thu, 21 May 2020 10:42:50 -0700 Ira Weiny <ira.weiny@intel.com> wrote:
> >>

...

> >>
> >> This all petered out, but as I understand it, this patchset still might
> >> have issues on various architectures.
> >>
> >> Can folks please provide an update on the testing status?
> > 
> > I believe the tests were failing for Guenter due to another patch set...[1]
> > 
> > My tests with just this series are working.
> > 
> >>From my understanding the other failures were unrelated.[2]
> > 
> > 	<quote Mike Rapoport>
> > 	I've checked the patch above on top of the mmots which already has
> > 	Ira's patches and it booted fine. I've used sparc32_defconfig to build
> > 	the kernel and qemu-system-sparc with default machine and CPU.
> > 	</quote>
> > 
> > Mike, am I wrong?  Do you think the kmap() patches are still causing issues?
> > 
> 
> For my part, all I can say is that -next is in pretty bad shape right now.
> The summary of my tests says:
> 
> Build results:
> 	total: 151 pass: 130 fail: 21
> Qemu test results:
> 	total: 430 pass: 375 fail: 55
> 
> sparc32 smp images in next-20200603 still crash for me with a spinlock
> recursion. s390 images hang early in boot. Several others (alpha, arm64,
> various ppc) don't even compile. I can run some more bisects over time,
> but this is becoming a full-time job :-(.
> 

I'm not sure what the process here is.  I just applied my series[1] on
Linus' Master branch[2] and ran sparc32 and s290 from your tests.

sparc32: (passes)

21:43:49 > /home/iweiny/dev/linux-build-test/rootfs/sparc/run-qemu-sparc.sh 
Build reference: v5.7-7188-g67a7a97e8a0f

Building sparc32:SPARCClassic:nosmp:scsi:hd ... running ......... passed
Building sparc32:SPARCbook:nosmp:scsi:cd ... running ......... passed
Building sparc32:LX:nosmp:noapc:scsi:hd ... running ......... passed
Building sparc32:SS-4:nosmp:initrd ... running ......... passed
Building sparc32:SS-5:nosmp:scsi:hd ... running ......... passed
Building sparc32:SS-10:nosmp:scsi:cd ... running ......... passed
Building sparc32:SS-20:nosmp:scsi:hd ... running ......... passed
Building sparc32:SS-600MP:nosmp:scsi:hd ... running ......... passed
Building sparc32:Voyager:nosmp:noapc:scsi:hd ... running ...... .... passed
Building sparc32:SS-4:smp:scsi:hd ... running ......... passed
Building sparc32:SS-5:smp:scsi:cd ... running ......... passed
Building sparc32:SS-10:smp:scsi:hd ... running ......... passed
Building sparc32:SS-20:smp:scsi:hd ... running ......... passed
Building sparc32:SS-600MP:smp:scsi:hd ... running ......... passed
Building sparc32:Voyager:smp:noapc:scsi:hd ... running ......... passed


s390: (does not compile)

<stdin>:1511:2: warning: #warning syscall clone3 not implemented [-Wcpp]
In file included from ./arch/sparc/include/asm/bug.h:6:0,
                 from ./include/linux/bug.h:5,
                 from ./include/linux/mmdebug.h:5,
                 from ./include/linux/mm.h:9,
                 from mm/huge_memory.c:8:
mm/huge_memory.c: In function 'hugepage_init':
./include/linux/compiler.h:403:38: error: call to '__compiletime_assert_127' declared with attribute error: BUILD_BUG_ON failed: ((13 + (13-3))-13) >= 9
  _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
                                      ^
./include/linux/compiler.h:384:4: note: in definition of macro '__compiletime_assert'
    prefix ## suffix();    \
    ^~~~~~
./include/linux/compiler.h:403:2: note: in expansion of macro '_compiletime_assert'
  _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
  ^~~~~~~~~~~~~~~~~~~
./include/linux/build_bug.h:39:37: note: in expansion of macro 'compiletime_assert'
 #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg)
                                     ^~~~~~~~~~~~~~~~~~
./include/linux/build_bug.h:50:2: note: in expansion of macro 'BUILD_BUG_ON_MSG'
  BUILD_BUG_ON_MSG(condition, "BUILD_BUG_ON failed: " #condition)
  ^~~~~~~~~~~~~~~~
./include/linux/bug.h:24:4: note: in expansion of macro 'BUILD_BUG_ON'
    BUILD_BUG_ON(cond);             \
    ^~~~~~~~~~~~
mm/huge_memory.c:403:2: note: in expansion of macro 'MAYBE_BUILD_BUG_ON'
  MAYBE_BUILD_BUG_ON(HPAGE_PMD_ORDER >= MAX_ORDER);
  ^~~~~~~~~~~~~~~~~~
make[1]: *** [scripts/Makefile.build:267: mm/huge_memory.o] Error 1
make[1]: *** Waiting for unfinished jobs....
make: *** [Makefile:1735: mm] Error 2
make: *** Waiting for unfinished jobs....
------------


The s390 error is the same on Linus' master and linux-next.  So whatever is
causing that has slipped into mainline and/or is something I've broken in the
test scripts.


With linux-next on sparc I too see the spinlock issue; something like:

...
Starting syslogd: BUG: spinlock recursion on CPU#0, S01syslogd/139
 lock: 0xf53ef350, .magic: dead4ead, .owner: S01syslogd/139, .owner_cpu: 0
CPU: 0 PID: 139 Comm: S01syslogd Not tainted 5.7.0-next-20200603 #1
[f0067d00 : 
do_raw_spin_lock+0xa8/0xd8 ] 
[f00d598c : 
copy_page_range+0x328/0x804 ] 
[f0025c34 : 
dup_mm+0x334/0x434 ] 
[f0027198 : 
copy_process+0x1248/0x12d4 ] 
[f00273b8 : 
_do_fork+0x54/0x30c ] 
[f00276e4 : 
do_fork+0x5c/0x6c ] 
[f000de44 : 
sparc_do_fork+0x18/0x38 ] 
[f000b7f4 : 
do_syscall+0x34/0x40 ] 
[5010cd4c : 
0x5010cd4c ] 

qemu-system-sparc: terminating on signal 15 from pid 2000056 (/bin/bash)
...


FWIW I don't see any of this being an issue with the kmap() code but I agree
things could be cleaner.  How can we back linux-next off a bit?  I'm not an
expert here with how linux-next works.

For example I just picked the latest patch from me within the linux-next tree:

  2e483306d5a8 arch/{mips,sparc,microblaze,powerpc}: don't enable pagefault/preempt twice

And built from there it looks good for sparc.

23:01:31 > /home/iweiny/dev/linux-build-test/rootfs/sparc/run-qemu-sparc.sh 
Build reference: v5.7-719-g2e483306d5a8

Building sparc32:SPARCClassic:nosmp:scsi:hd ... running .......... passed
Building sparc32:SPARCbook:nosmp:scsi:cd ... running .......... passed
Building sparc32:LX:nosmp:noapc:scsi:hd ... running .......... passed
Building sparc32:SS-4:nosmp:initrd ... running .......... passed
Building sparc32:SS-5:nosmp:scsi:hd ... running .......... passed
Building sparc32:SS-10:nosmp:scsi:cd ... running .......... passed
Building sparc32:SS-20:nosmp:scsi:hd ... running .......... passed
Building sparc32:SS-600MP:nosmp:scsi:hd ... running ......... passed
Building sparc32:Voyager:nosmp:noapc:scsi:hd ... running ......... passed
Building sparc32:SS-4:smp:scsi:hd ... running ......^[[1;2D... passed
Building sparc32:SS-5:smp:scsi:cd ... running ......... passed
Building sparc32:SS-10:smp:scsi:hd ... running ......... passed
Building sparc32:SS-20:smp:scsi:hd ... running ......... passed
Building sparc32:SS-600MP:smp:scsi:hd ... running ......... passed
Building sparc32:Voyager:smp:noapc:scsi:hd ... running ......... passed


I'm going to bisect between there and HEAD.


Ira


[1]

67a7a97e8a0f arch/{mips,sparc,microblaze,powerpc}: Don't enable pagefault/preempt twice
4a3dd9ec36d8 kmap: Consolidate kmap_prot definitions
a3b39b1668ac sparc: Remove unnecessary includes
452195c6e8a8 parisc/kmap: Remove duplicate kmap code
317e4af1da94 kmap: Remove kmap_atomic_to_page()
e11e52415a4d drm: Remove drm specific kmap_atomic code
afd4911f0cfb arch/kmap: Define kmap_atomic_prot() for all arch's
2a5524d63341 arch/kmap: Don't hard code kmap_prot values
c94bbaab0296 arch/kmap: Ensure kmap_prot visibility
6f29a6b66d3b arch/kunmap_atomic: Consolidate duplicate code
0c7122ef07d1 arch/kmap_atomic: Consolidate duplicate code
63b8bbf47723 {x86,powerpc,microblaze}/kmap: Move preempt disable
23b3175de76f arch/kunmap: Remove duplicate kunmap implementations
9514dd54fda8 arch/kmap: Remove redundant arch specific kmaps
e92e53c0080b arch/xtensa: Move kmap build bug out of the way
cab1afa4f6ac arch/kmap: Remove BUG_ON()

[2] cb8e59cc8720 (linus/master, linus-master) Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next

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

^ permalink raw reply

* [PATCH] leds: mt6360: Add LED driver for MT6360
From: Gene Chen @ 2020-06-04  6:26 UTC (permalink / raw)
  To: jacek.anaszewski, pavel, matthias.bgg
  Cc: gene_chen, linux-kernel, cy_huang, benjamin.chao, linux-mediatek,
	dmurphy, linux-leds, Wilma.Wu, linux-arm-kernel, shufan_lee

From: Gene Chen <gene_chen@richtek.com>

Add MT6360 LED driver include 2-channel Flash LED with torch/strobe mode,
and 3-channel RGB LED support Register/Flash/Breath Mode

Signed-off-by: Gene Chen <gene_chen@richtek.com>
base-commit: 098c4adf249c198519a4abebe482b1e6b8c50e47
---
 drivers/leds/Kconfig       |   11 +
 drivers/leds/Makefile      |    1 +
 drivers/leds/leds-mt6360.c | 1061 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/mfd/mt6360.h |    6 +-
 4 files changed, 1078 insertions(+), 1 deletion(-)
 create mode 100644 drivers/leds/leds-mt6360.c

diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index c664d84..c47be91 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -229,6 +229,17 @@ config LEDS_MT6323
 	  This option enables support for on-chip LED drivers found on
 	  Mediatek MT6323 PMIC.
 
+config LEDS_MT6360
+	tristate "LED Support for Mediatek MT6360 PMIC"
+	depends on LEDS_CLASS_FLASH && OF
+	depends on V4L2_FLASH_LED_CLASS || !V4L2_FLASH_LED_CLASS
+	depends on MFD_MT6360
+	help
+	  This option enables support for dual Flash LED drivers found on
+	  Mediatek MT6360 PMIC.
+	  Support Torch and Strobe mode independently current source.
+	  Include Low-VF and short protection.
+
 config LEDS_S3C24XX
 	tristate "LED Support for Samsung S3C24XX GPIO LEDs"
 	depends on LEDS_CLASS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 45235d5..2883b4d 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -63,6 +63,7 @@ obj-$(CONFIG_LEDS_MIKROTIK_RB532)	+= leds-rb532.o
 obj-$(CONFIG_LEDS_MLXCPLD)		+= leds-mlxcpld.o
 obj-$(CONFIG_LEDS_MLXREG)		+= leds-mlxreg.o
 obj-$(CONFIG_LEDS_MT6323)		+= leds-mt6323.o
+obj-$(CONFIG_LEDS_MT6360)		+= leds-mt6360.o
 obj-$(CONFIG_LEDS_NET48XX)		+= leds-net48xx.o
 obj-$(CONFIG_LEDS_NETXBIG)		+= leds-netxbig.o
 obj-$(CONFIG_LEDS_NIC78BX)		+= leds-nic78bx.o
diff --git a/drivers/leds/leds-mt6360.c b/drivers/leds/leds-mt6360.c
new file mode 100644
index 0000000..3e62547
--- /dev/null
+++ b/drivers/leds/leds-mt6360.c
@@ -0,0 +1,1061 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2020 MediaTek Inc.
+ *
+ * Author: Gene Chen <gene_chen@richtek.com>
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/regmap.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/of.h>
+#include <linux/led-class-flash.h>
+#include <media/v4l2-flash-led-class.h>
+
+#include <linux/mfd/mt6360.h>
+
+enum {
+	MT6360_LED_ISINK1 = 0,
+	MT6360_LED_ISINK2,
+	MT6360_LED_ISINK3,
+	MT6360_LED_ISINK4,
+	MT6360_LED_MAX,
+};
+
+enum {
+	MT6360_LEDMODE_PWM = 0,
+	MT6360_LEDMODE_BREATH,
+	MT6360_LEDMODE_CC,
+	MT6360_LEDMODE_MAX,
+};
+
+enum {
+	MT6360_FLED_CH1 = 0,
+	MT6360_FLED_CH2,
+	MT6360_FLED_MAX,
+};
+
+/* ILED setting/reg */
+#define MT6360_SINKCUR_MAX1	(0x0d)
+#define MT6360_SINKCUR_MAX2	(0x0d)
+#define MT6360_SINKCUR_MAX3	(0x0d)
+#define MT6360_SINKCUR_MAX4	(0x1f)
+#define MT6360_CURRSEL_REG1	(MT6360_PMU_RGB1_ISNK)
+#define MT6360_CURRSEL_REG2	(MT6360_PMU_RGB2_ISNK)
+#define MT6360_CURRSEL_REG3	(MT6360_PMU_RGB3_ISNK)
+#define MT6360_CURRSEL_REG4	(MT6360_PMU_RGB_ML_ISNK)
+#define MT6360_CURRSEL_MASK1	(0x0f)
+#define MT6360_CURRSEL_MASK2	(0x0f)
+#define MT6360_CURRSEL_MASK3	(0x0f)
+#define MT6360_CURRSEL_MASK4	(0x1f)
+#define MT6360_LEDMODE_REG1	(MT6360_PMU_RGB1_ISNK)
+#define MT6360_LEDMODE_REG2	(MT6360_PMU_RGB2_ISNK)
+#define MT6360_LEDMODE_REG3	(MT6360_PMU_RGB3_ISNK)
+#define MT6360_LEDMODE_REG4	(0)
+#define MT6360_LEDMODE_MASK1	(0xc0)
+#define MT6360_LEDMODE_MASK2	(0xc0)
+#define MT6360_LEDMODE_MASK3	(0xc0)
+#define MT6360_LEDMODE_MASK4	(0)
+#define MT6360_PWMDUTY_REG1	(MT6360_PMU_RGB1_DIM)
+#define MT6360_PWMDUTY_REG2	(MT6360_PMU_RGB2_DIM)
+#define MT6360_PWMDUTY_REG3	(MT6360_PMU_RGB3_DIM)
+#define MT6360_PWMDUTY_REG4	(0)
+#define MT6360_PWMDUTY_MASK1	(0xff)
+#define MT6360_PWMDUTY_MASK2	(0xff)
+#define MT6360_PWMDUTY_MASK3	(0xff)
+#define MT6360_PWMDUTY_MASK4	(0)
+#define MT6360_PWMFREQ_REG1	(MT6360_PMU_RGB12_Freq)
+#define MT6360_PWMFREQ_REG2	(MT6360_PMU_RGB12_Freq)
+#define MT6360_PWMFREQ_REG3	(MT6360_PMU_RGB34_Freq)
+#define MT6360_PWMFREQ_REG4	(0)
+#define MT6360_PWMFREQ_MASK1	(0xe0)
+#define MT6360_PWMFREQ_MASK2	(0x1c)
+#define MT6360_PWMFREQ_MASK3	(0xe0)
+#define MT6360_PWMFREQ_MASK4	(0)
+#define MT6360_BREATH_REGBASE1	(MT6360_PMU_RGB1_Tr)
+#define MT6360_BREATH_REGBASE2	(MT6360_PMU_RGB2_Tr)
+#define MT6360_BREATH_REGBASE3	(MT6360_PMU_RGB3_Tr)
+#define MT6360_BREATH_REGBASE4	(0)
+#define MT6360_LEDEN_MASK1	(0x80)
+#define MT6360_LEDEN_MASK2	(0x40)
+#define MT6360_LEDEN_MASK3	(0x20)
+#define MT6360_LEDEN_MASK4	(0x10)
+#define MT6360_LEDEN_REG	(MT6360_PMU_RGB_EN)
+#define MT6360_LEDALLEN_MASK	(0xf0)
+
+#define MT6360_CHRIND_MASK	(0x08)
+
+/* pattern order -> toff, tr1, tr2, ton, tf1, tf2 */
+#define MT6360_BRPATTERN_NUM	(6)
+#define MT6360_BREATHREG_NUM	(3)
+
+/* FLED setting */
+#define MT6360_CSENABLE_REG1	(MT6360_PMU_FLED_EN)
+#define MT6360_CSENABLE_MASK1	(0x02)
+#define MT6360_CSENABLE_REG2	(MT6360_PMU_FLED_EN)
+#define MT6360_CSENABLE_MASK2	(0x01)
+#define MT6360_TORBRIGHT_MAX1	(0x1f)
+#define MT6360_TORBRIGHT_MAX2	(0x1f)
+#define MT6360_TORBRIGHT_REG1	(MT6360_PMU_FLED1_TOR_CTRL)
+#define MT6360_TORBRIGHT_MASK1	(0x1f)
+#define MT6360_STRBRIGHT_REG1	(MT6360_PMU_FLED1_STRB_CTRL2)
+#define MT6360_STRBRIGHT_MASK1	(0x7f)
+#define MT6360_TORBRIGHT_REG2	(MT6360_PMU_FLED2_TOR_CTRL)
+#define MT6360_TORBRIGHT_MASK2	(0x1f)
+#define MT6360_STRBRIGHT_REG2	(MT6360_PMU_FLED2_STRB_CTRL2)
+#define MT6360_STRBRIGHT_MASK2	(0x7f)
+#define MT6360_TORENABLE_REG1	(MT6360_PMU_FLED_EN)
+#define MT6360_TORENABLE_MASK1	(0x08)
+#define MT6360_TORENABLE_REG2	(MT6360_PMU_FLED_EN)
+#define MT6360_TORENABLE_MASK2	(0x08)
+#define MT6360_STRBENABLE_REG1	(MT6360_PMU_FLED_EN)
+#define MT6360_STRBENABLE_MASK1 (0x06)
+#define MT6360_STRBENABLE_REG2	(MT6360_PMU_FLED_EN)
+#define MT6360_STRBENABLE_MASK2 (0x04)
+#define MT6360_STRBTIMEOUT_REG	(MT6360_PMU_FLED_STRB_CTRL)
+#define MT6360_STRBTIMEOUT_MASK	(0x7f)
+#define MT6360_TORCHCUR_MIN	(25000)
+#define MT6360_TORCHCUR_STEP	(12500)
+#define MT6360_TORCHCUR_MAX	(400000)
+#define MT6360_STROBECUR_MIN	(50000)
+#define MT6360_STROBECUR_STEP	(12500)
+#define MT6360_STROBECUR_MAX	(1500000)
+#define MT6360_STRBTIMEOUT_MIN	(64000)
+#define MT6360_STRBTIMEOUT_STEP	(32000)
+#define MT6360_STRBTIMEOUT_MAX	(2432000)
+
+#define MT6360_MASK_ULTRA_STROBE	(0x80)
+#define MT6360_SHIFT_ULTRA_STROBE	(7)
+
+#define MT6360_FLEDSUPPORT_FAULTS	(LED_FAULT_UNDER_VOLTAGE |\
+					 LED_FAULT_SHORT_CIRCUIT |\
+					 LED_FAULT_INPUT_VOLTAGE |\
+					 LED_FAULT_TIMEOUT)
+
+struct mt6360_led_platform_data {
+	u32 rgbon_sync;
+	u32 fled1_ultraistrb;
+	u32 fled2_ultraistrb;
+};
+
+struct breath_element_cfg {
+	/* base, step in ms */
+	unsigned int base;
+	unsigned int step;
+	unsigned int maxval;
+	unsigned int reg_offset;
+	unsigned int reg_mask;
+};
+
+struct mt6360_led_classdev {
+	struct led_classdev cdev;
+	int index;
+	struct device_node *np;
+	unsigned int currsel_reg;
+	unsigned int currsel_mask;
+	unsigned int enable_mask;
+	unsigned int mode_reg;
+	unsigned int mode_mask;
+	unsigned int pwmduty_reg;
+	unsigned int pwmduty_mask;
+	unsigned int pwmfreq_reg;
+	unsigned int pwmfreq_mask;
+	unsigned int breath_regbase;
+};
+
+struct mt6360_fled_classdev {
+	struct led_classdev_flash fl_cdev;
+	int index;
+	struct v4l2_flash *v4l2_flash;
+	struct device_node *np;
+	unsigned int cs_enable_reg;
+	unsigned int cs_enable_mask;
+	unsigned int torch_bright_reg;
+	unsigned int torch_bright_mask;
+	unsigned int torch_enable_reg;
+	unsigned int torch_enable_mask;
+	unsigned int strobe_bright_reg;
+	unsigned int strobe_bright_mask;
+	unsigned int strobe_enable_reg;
+	unsigned int strobe_enable_mask;
+	unsigned int strobe_external_reg;
+	unsigned int strobe_external_mask;
+	u32 faults;
+};
+
+struct mt6360_led_data {
+	struct device *dev;
+	struct mt6360_led_platform_data *pdata;
+	struct regmap *regmap;
+	struct mt6360_led_classdev mtled_cdev[MT6360_LED_MAX];
+	struct mt6360_fled_classdev mtfled_cdev[MT6360_FLED_MAX];
+	unsigned long fl_torch_flags;
+	unsigned long fl_strobe_flags;
+};
+
+static const struct mt6360_led_platform_data def_platform_data = {
+	.rgbon_sync = 0,
+	.fled1_ultraistrb = 1,
+	.fled2_ultraistrb = 1,
+};
+
+static int mt6360_led_brightness_set(struct led_classdev *cdev,
+				      enum led_brightness brightness)
+{
+	struct mt6360_led_classdev *mtled_cdev =
+					     (struct mt6360_led_classdev *)cdev;
+	struct mt6360_led_data *mld = dev_get_drvdata(cdev->dev->parent);
+	int shift, sync_regval = 0, ret;
+
+	/* if isink1 user control, set chrind function to sw mode */
+	if (mtled_cdev->index == MT6360_LED_ISINK1) {
+		ret = regmap_update_bits(mld->regmap,
+				   MT6360_PMU_RGB_EN, MT6360_CHRIND_MASK, 0xff);
+		if (ret < 0)
+			dev_err(cdev->dev, "disable chrind func fail\n");
+	}
+	if (brightness == LED_OFF) {
+		ret = regmap_update_bits(mld->regmap,
+				  MT6360_LEDEN_REG, mtled_cdev->enable_mask, 0);
+		if (ret < 0)
+			return ret;
+		if (mtled_cdev->mode_reg == 0)
+			goto out_bright_set;
+		/* if off, force config to cc_mode */
+		shift = ffs(mtled_cdev->mode_mask) - 1;
+		ret = regmap_update_bits(mld->regmap, mtled_cdev->mode_reg,
+			     mtled_cdev->mode_mask, MT6360_LEDMODE_CC << shift);
+		if (ret < 0)
+			dev_err(cdev->dev, "config cc mode fail\n");
+		goto out_bright_set;
+	}
+	shift = ffs(mtled_cdev->currsel_mask) - 1;
+	brightness -= 1;
+	ret = regmap_update_bits(mld->regmap, mtled_cdev->currsel_reg,
+				 mtled_cdev->currsel_mask, brightness << shift);
+	if (ret < 0)
+		return ret;
+	if (mld->pdata->rgbon_sync) {
+		ret = regmap_read(mld->regmap, MT6360_LEDEN_REG,  &sync_regval);
+		if (ret < 0)
+			goto out_bright_set;
+		ret = regmap_update_bits(mld->regmap,
+				     MT6360_LEDEN_REG, MT6360_LEDALLEN_MASK, 0);
+		if (ret < 0)
+			goto out_bright_set;
+		sync_regval |= mtled_cdev->enable_mask;
+		ret = regmap_update_bits(mld->regmap, MT6360_LEDEN_REG,
+					 MT6360_LEDALLEN_MASK, sync_regval);
+	} else {
+		ret = regmap_update_bits(mld->regmap, MT6360_LEDEN_REG,
+					 mtled_cdev->enable_mask, 0xff);
+	}
+out_bright_set:
+	return ret;
+}
+
+static enum led_brightness mt6360_led_brightness_get(struct led_classdev *cdev)
+{
+	struct mt6360_led_classdev *mtled_cdev =
+					     (struct mt6360_led_classdev *)cdev;
+	struct mt6360_led_data *mld = dev_get_drvdata(cdev->dev->parent);
+	unsigned int regval = 0;
+	int shift = ffs(mtled_cdev->currsel_mask) - 1, ret;
+
+	ret = regmap_read(mld->regmap, MT6360_LEDEN_REG, &regval);
+	if (ret < 0) {
+		dev_err(cdev->dev, "%s: get enable fail\n", __func__);
+		return LED_OFF;
+	}
+	if (!(regval & mtled_cdev->enable_mask))
+		return LED_OFF;
+	ret = regmap_read(mld->regmap, mtled_cdev->currsel_reg, &regval);
+	if (ret < 0) {
+		dev_err(cdev->dev, "%s: get isink fail\n", __func__);
+		return LED_OFF;
+	}
+	regval &= mtled_cdev->currsel_mask;
+	regval >>= shift;
+	return (regval + 1);
+}
+
+static const unsigned int dim_freqs[] = {
+	4, 8, 250, 500, 1000, 2000, 4000, 8000,
+};
+
+static int mt6360_led_blink_set(struct led_classdev *cdev,
+			     unsigned long *delay_on,  unsigned long *delay_off)
+{
+	struct mt6360_led_classdev *mtled_cdev =
+					     (struct mt6360_led_classdev *)cdev;
+	struct mt6360_led_data *mld = dev_get_drvdata(cdev->dev->parent);
+	int freq, duty, shift, sum, ret;
+
+	if (mtled_cdev->mode_reg == 0)
+		return -ENOTSUPP;
+	if (*delay_on == 0 && *delay_off == 0)
+		*delay_on = *delay_off = 500;
+	sum = *delay_on + *delay_off;
+	for (freq = 0; freq < ARRAY_SIZE(dim_freqs); freq++) {
+		if (sum <= dim_freqs[freq])
+			break;
+	}
+	if (freq == ARRAY_SIZE(dim_freqs)) {
+		dev_err(cdev->dev, "exceed pwm frequency max\n");
+		return -EINVAL;
+	}
+	/* invert */
+	freq = ARRAY_SIZE(dim_freqs) - 1 - freq;
+	shift = ffs(mtled_cdev->pwmfreq_mask) - 1;
+	ret = regmap_update_bits(mld->regmap, mtled_cdev->pwmfreq_reg,
+				 mtled_cdev->pwmfreq_mask, freq << shift);
+	if (ret < 0) {
+		dev_err(cdev->dev, "Failed to set pwmfreq\n");
+		return ret;
+	}
+	duty = 255 * (*delay_on) / sum;
+	shift = ffs(mtled_cdev->pwmduty_mask) - 1;
+	ret = regmap_update_bits(mld->regmap, mtled_cdev->pwmduty_reg,
+				 mtled_cdev->pwmduty_mask, duty << shift);
+	if (ret < 0) {
+		dev_err(cdev->dev, "Failed to set pwmduty\n");
+		return ret;
+	}
+	shift = ffs(mtled_cdev->mode_mask) - 1;
+	ret = regmap_update_bits(mld->regmap, mtled_cdev->mode_reg,
+			    mtled_cdev->mode_mask, MT6360_LEDMODE_PWM << shift);
+	return ret;
+}
+
+#define MT6360_LED_DESC(_id)  {						\
+	.cdev = {							\
+		.name = "mt6360_isink" #_id,				\
+		.max_brightness = MT6360_SINKCUR_MAX##_id,		\
+		.brightness_set_blocking = mt6360_led_brightness_set,	\
+		.brightness_get = mt6360_led_brightness_get,		\
+		.blink_set = mt6360_led_blink_set,			\
+	},								\
+	.index = MT6360_LED_ISINK##_id,					\
+	.currsel_reg = MT6360_CURRSEL_REG##_id,				\
+	.currsel_mask = MT6360_CURRSEL_MASK##_id,			\
+	.enable_mask = MT6360_LEDEN_MASK##_id,				\
+	.mode_reg = MT6360_LEDMODE_REG##_id,				\
+	.mode_mask = MT6360_LEDMODE_MASK##_id,				\
+	.pwmduty_reg = MT6360_PWMDUTY_REG##_id,				\
+	.pwmduty_mask = MT6360_PWMDUTY_MASK##_id,			\
+	.pwmfreq_reg = MT6360_PWMFREQ_REG##_id,				\
+	.pwmfreq_mask = MT6360_PWMFREQ_MASK##_id,			\
+	.breath_regbase = MT6360_BREATH_REGBASE##_id,			\
+}
+
+/* ISINK 1/2/3 for RGBLED, ISINK4 for MoonLight */
+static const struct mt6360_led_classdev def_led_classdev[MT6360_LED_MAX] = {
+	MT6360_LED_DESC(1),
+	MT6360_LED_DESC(2),
+	MT6360_LED_DESC(3),
+	MT6360_LED_DESC(4),
+};
+
+static inline bool mt6360_fled_check_flags_if_any(unsigned long *flags)
+{
+	return (*flags) ? true : false;
+}
+
+static int mt6360_fled_strobe_brightness_set(
+			   struct led_classdev_flash *fled_cdev, u32 brightness)
+{
+	struct led_classdev *led_cdev = &fled_cdev->led_cdev;
+	struct mt6360_led_data *mld = dev_get_drvdata(led_cdev->dev->parent);
+	struct led_flash_setting *fs = &fled_cdev->brightness;
+	struct mt6360_fled_classdev *mtfled_cdev = (void *)fled_cdev;
+	int shift;
+	u32 val;
+
+	val = brightness;
+	val = (val - fs->min) / fs->step;
+	shift = ffs(mtfled_cdev->strobe_bright_mask) - 1;
+	return regmap_update_bits(mld->regmap, mtfled_cdev->strobe_bright_reg,
+				 mtfled_cdev->strobe_bright_mask, val << shift);
+}
+
+static int mt6360_fled_strobe_brightness_get(
+			  struct led_classdev_flash *fled_cdev, u32 *brightness)
+{
+	struct led_classdev *led_cdev = &fled_cdev->led_cdev;
+	struct mt6360_led_data *mld = dev_get_drvdata(led_cdev->dev->parent);
+	struct led_flash_setting *fs = &fled_cdev->brightness;
+	struct mt6360_fled_classdev *mtfled_cdev = (void *)fled_cdev;
+	int shift, ret;
+	u32 regval = 0;
+
+	ret = regmap_read(mld->regmap, mtfled_cdev->strobe_bright_reg, &regval);
+	if (ret < 0)
+		return ret;
+	regval &= mtfled_cdev->strobe_bright_mask;
+	shift = ffs(mtfled_cdev->strobe_bright_mask) - 1;
+	regval >>= shift;
+	/* convert to microamp value */
+	*brightness = regval * fs->step + fs->min;
+	return 0;
+}
+
+static int mt6360_fled_strobe_set(
+			       struct led_classdev_flash *fled_cdev, bool state)
+{
+	struct led_classdev *led_cdev = &fled_cdev->led_cdev;
+	struct mt6360_led_data *mld = dev_get_drvdata(led_cdev->dev->parent);
+	struct mt6360_fled_classdev *mtfled_cdev = (void *)fled_cdev;
+	int id = mtfled_cdev->index, ret;
+
+	if (!(state ^ test_bit(id, &mld->fl_strobe_flags)))
+		return 0;
+	if (mt6360_fled_check_flags_if_any(&mld->fl_torch_flags)) {
+		dev_err(led_cdev->dev,
+			"Disable all leds torch [%lu]\n", mld->fl_torch_flags);
+		return -EINVAL;
+	}
+	ret = regmap_update_bits(mld->regmap, mtfled_cdev->cs_enable_reg,
+				 mtfled_cdev->cs_enable_mask, state ? 0xff : 0);
+	if (ret < 0) {
+		dev_err(led_cdev->dev, "Fail to set cs enable [%d]\n", state);
+		goto out_strobe_set;
+	}
+	ret = regmap_update_bits(mld->regmap, mtfled_cdev->strobe_enable_reg,
+			     mtfled_cdev->strobe_enable_mask, state ? 0xff : 0);
+	if (ret < 0) {
+		dev_err(led_cdev->dev, "Fail to set strb enable [%d]\n", state);
+		goto out_strobe_set;
+	}
+	if (state) {
+		if (!mt6360_fled_check_flags_if_any(&mld->fl_strobe_flags))
+			usleep_range(5000, 6000);
+		set_bit(id, &mld->fl_strobe_flags);
+		mtfled_cdev->faults = 0;
+	} else {
+		clear_bit(id, &mld->fl_strobe_flags);
+		if (!mt6360_fled_check_flags_if_any(&mld->fl_strobe_flags))
+			usleep_range(400, 500);
+	}
+out_strobe_set:
+	return ret;
+}
+
+static int mt6360_fled_strobe_get(
+			      struct led_classdev_flash *fled_cdev, bool *state)
+{
+	struct led_classdev *led_cdev = &fled_cdev->led_cdev;
+	struct mt6360_led_data *mld = dev_get_drvdata(led_cdev->dev->parent);
+	struct mt6360_fled_classdev *mtfled_cdev = (void *)fled_cdev;
+	int id = mtfled_cdev->index;
+
+	*state = test_bit(id, &mld->fl_strobe_flags) ? true : false;
+	return 0;
+}
+
+static int mt6360_fled_strobe_timeout_set(
+			      struct led_classdev_flash *fled_cdev, u32 timeout)
+{
+	struct led_classdev *led_cdev = &fled_cdev->led_cdev;
+	struct mt6360_led_data *mld = dev_get_drvdata(led_cdev->dev->parent);
+	struct led_flash_setting *ts = &fled_cdev->timeout;
+	int shift, ret;
+	u32 regval;
+
+	regval = (timeout - ts->min) / ts->step;
+	shift = ffs(MT6360_STRBTIMEOUT_MASK) - 1;
+	ret = regmap_update_bits(mld->regmap, MT6360_STRBTIMEOUT_REG,
+				 MT6360_STRBTIMEOUT_MASK, regval << shift);
+	return ret;
+}
+
+static int mt6360_fled_strobe_fault_get(
+			       struct led_classdev_flash *fled_cdev, u32 *fault)
+{
+	struct mt6360_fled_classdev *mtfled_cdev = (void *)fled_cdev;
+
+	*fault = mtfled_cdev->faults;
+	return 0;
+}
+
+static const struct led_flash_ops mt6360_fled_ops = {
+	.flash_brightness_set = mt6360_fled_strobe_brightness_set,
+	.flash_brightness_get = mt6360_fled_strobe_brightness_get,
+	.strobe_set = mt6360_fled_strobe_set,
+	.strobe_get = mt6360_fled_strobe_get,
+	.timeout_set = mt6360_fled_strobe_timeout_set,
+	.fault_get = mt6360_fled_strobe_fault_get,
+};
+
+static int mt6360_fled_brightness_set(struct led_classdev *led_cdev,
+				      enum led_brightness brightness)
+{
+	struct led_classdev_flash *lcf = lcdev_to_flcdev(led_cdev);
+	struct mt6360_led_data *mld = dev_get_drvdata(led_cdev->dev->parent);
+	struct mt6360_fled_classdev *mtfled_cdev = (void *)lcf;
+	int id = mtfled_cdev->index, shift, keep, ret;
+
+	if (mt6360_fled_check_flags_if_any(&mld->fl_strobe_flags)) {
+		dev_err(led_cdev->dev,
+		       "Disable all leds strobe [%lu]\n", mld->fl_strobe_flags);
+		return -EINVAL;
+	}
+	if (brightness == LED_OFF) {
+		clear_bit(id, &mld->fl_torch_flags);
+		keep = mt6360_fled_check_flags_if_any(&mld->fl_torch_flags);
+		ret = regmap_update_bits(mld->regmap,
+					 mtfled_cdev->torch_enable_reg,
+					 mtfled_cdev->torch_enable_mask,
+					 keep ? 0xff : 0);
+		if (ret < 0) {
+			dev_err(led_cdev->dev, "Fail to set torch disable\n");
+			goto out_bright_set;
+		}
+		ret = regmap_update_bits(mld->regmap,
+					 mtfled_cdev->cs_enable_reg,
+					 mtfled_cdev->cs_enable_mask, 0);
+		if (ret < 0)
+			dev_err(led_cdev->dev, "Fail to set torch disable\n");
+		goto out_bright_set;
+	}
+	shift = ffs(mtfled_cdev->torch_bright_mask) - 1;
+	brightness -= 1;
+	ret = regmap_update_bits(mld->regmap, mtfled_cdev->torch_bright_reg,
+			   mtfled_cdev->torch_bright_mask, brightness << shift);
+	if (ret < 0) {
+		dev_err(led_cdev->dev,
+			"Fail to set torch bright [%d]\n", brightness);
+		goto out_bright_set;
+	}
+	ret = regmap_update_bits(mld->regmap, mtfled_cdev->cs_enable_reg,
+				 mtfled_cdev->cs_enable_mask, 0xff);
+	if (ret < 0) {
+		dev_err(led_cdev->dev, "Fail to set cs enable\n");
+		goto out_bright_set;
+	}
+	ret = regmap_update_bits(mld->regmap, mtfled_cdev->torch_enable_reg,
+				 mtfled_cdev->torch_enable_mask, 0xff);
+	set_bit(id, &mld->fl_torch_flags);
+out_bright_set:
+	return ret;
+}
+
+static enum led_brightness mt6360_fled_brightness_get(
+						  struct led_classdev *led_cdev)
+{
+	struct led_classdev_flash *lcf = lcdev_to_flcdev(led_cdev);
+	struct mt6360_led_data *mld = dev_get_drvdata(led_cdev->dev->parent);
+	struct mt6360_fled_classdev *mtfled_cdev = (void *)lcf;
+	int id = mtfled_cdev->index, shift, ret;
+	u32 regval = 0;
+
+	if (!test_bit(id, &mld->fl_torch_flags))
+		return LED_OFF;
+	ret = regmap_read(mld->regmap, mtfled_cdev->torch_bright_reg, &regval);
+	if (ret < 0) {
+		dev_err(led_cdev->dev, "%s: Fail to get torb reg\n", __func__);
+		return LED_OFF;
+	}
+	shift = ffs(mtfled_cdev->torch_bright_mask) - 1;
+	regval &= mtfled_cdev->torch_bright_mask;
+	regval >>= shift;
+	return (regval + 1);
+}
+
+#define MT6360_FLED_DESC(_id)  {					\
+	.fl_cdev = {							\
+	 .led_cdev = {							\
+		.name = "mt6360_fled_ch" #_id,				\
+		.max_brightness = MT6360_TORBRIGHT_MAX##_id,		\
+		.brightness_set_blocking =  mt6360_fled_brightness_set,	\
+		.brightness_get = mt6360_fled_brightness_get,		\
+		.flags = LED_DEV_CAP_FLASH,				\
+	 },								\
+	 .brightness = {						\
+		.min = MT6360_STROBECUR_MIN,				\
+		.step = MT6360_STROBECUR_STEP,				\
+		.max = MT6360_STROBECUR_MAX,				\
+		.val = MT6360_STROBECUR_MIN,				\
+	 },								\
+	 .timeout = {							\
+		.min = MT6360_STRBTIMEOUT_MIN,				\
+		.step = MT6360_STRBTIMEOUT_STEP,			\
+		.max = MT6360_STRBTIMEOUT_MAX,				\
+		.val = MT6360_STRBTIMEOUT_MIN,				\
+	 },								\
+	 .ops = &mt6360_fled_ops,					\
+	},								\
+	.index = MT6360_FLED_CH##_id,					\
+	.cs_enable_reg = MT6360_CSENABLE_REG##_id,			\
+	.cs_enable_mask = MT6360_CSENABLE_MASK##_id,			\
+	.torch_bright_reg = MT6360_TORBRIGHT_REG##_id,			\
+	.torch_bright_mask = MT6360_TORBRIGHT_MASK##_id,		\
+	.torch_enable_reg = MT6360_TORENABLE_REG##_id,			\
+	.torch_enable_mask = MT6360_TORENABLE_MASK##_id,		\
+	.strobe_bright_reg = MT6360_STRBRIGHT_REG##_id,			\
+	.strobe_bright_mask = MT6360_STRBRIGHT_MASK##_id,		\
+	.strobe_enable_reg = MT6360_STRBENABLE_REG##_id,		\
+	.strobe_enable_mask = MT6360_STRBENABLE_MASK##_id,		\
+}
+
+static const struct mt6360_fled_classdev def_fled_classdev[MT6360_FLED_MAX] = {
+	MT6360_FLED_DESC(1),
+	MT6360_FLED_DESC(2),
+};
+
+#if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
+static int mt6360_fled_external_strobe_set(
+				     struct v4l2_flash *v4l2_flash, bool enable)
+{
+	struct led_classdev_flash *lcf = v4l2_flash->fled_cdev;
+	struct led_classdev *led_cdev = &lcf->led_cdev;
+	struct mt6360_led_data *mld = dev_get_drvdata(led_cdev->dev->parent);
+	struct mt6360_fled_classdev *mtfled_cdev = (void *)lcf;
+	int id = mtfled_cdev->index, ret;
+
+	if (!(enable ^ test_bit(id, &mld->fl_strobe_flags)))
+		return 0;
+	if (mt6360_fled_check_flags_if_any(&mld->fl_torch_flags)) {
+		dev_err(led_cdev->dev,
+			"Disable all leds torch [%lu]\n", mld->fl_torch_flags);
+		return -EINVAL;
+	}
+	ret = regmap_update_bits(mld->regmap, mtfled_cdev->cs_enable_reg,
+			  mtfled_cdev->cs_enable_mask, enable ? 0xff : 0);
+	if (enable) {
+		set_bit(id, &mld->fl_strobe_flags);
+		mtfled_cdev->faults = 0;
+	} else
+		clear_bit(id, &mld->fl_strobe_flags);
+	return ret;
+}
+
+static const struct v4l2_flash_ops v4l2_flash_ops = {
+	.external_strobe_set = mt6360_fled_external_strobe_set,
+};
+
+static void mt6360_init_v4l2_flash_config(
+				       struct mt6360_fled_classdev *mtfled_cdev,
+				       struct v4l2_flash_config *config)
+{
+	struct led_flash_setting *torch_intensity = &config->intensity;
+	struct led_classdev *led_cdev = &(mtfled_cdev->fl_cdev.led_cdev);
+	s32 val;
+
+	snprintf(config->dev_name, sizeof(config->dev_name),
+		 "%s", mtfled_cdev->fl_cdev.led_cdev.name);
+	torch_intensity->min = MT6360_TORCHCUR_MIN;
+	torch_intensity->step = MT6360_TORCHCUR_STEP;
+	val = MT6360_TORCHCUR_MIN;
+	val += ((led_cdev->max_brightness - 1) * MT6360_TORCHCUR_STEP);
+	torch_intensity->val = torch_intensity->max = val;
+	config->flash_faults |= MT6360_FLEDSUPPORT_FAULTS;
+	config->has_external_strobe = 1;
+}
+#else
+static const struct v4l2_flash_ops v4l2_flash_ops;
+
+static void mt6360_init_v4l2_flash_config(
+				       struct mt6360_fled_classdev *mtfled_cdev,
+				       struct v4l2_flash_config *config)
+{
+}
+#endif /* IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS) */
+
+static irqreturn_t mt6360_pmu_fled_lvf_evt_handler(int irq, void *data)
+{
+	struct mt6360_led_data *mld = data;
+
+	dev_err(mld->dev, "%s\n", __func__);
+	mld->mtfled_cdev[MT6360_FLED_CH1].faults |= LED_FAULT_UNDER_VOLTAGE;
+	mld->mtfled_cdev[MT6360_FLED_CH2].faults |= LED_FAULT_UNDER_VOLTAGE;
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t mt6360_pmu_fled2_short_evt_handler(int irq, void *data)
+{
+	struct mt6360_led_data *mld = data;
+
+	dev_err(mld->dev, "%s\n", __func__);
+	mld->mtfled_cdev[MT6360_FLED_CH2].faults |= LED_FAULT_SHORT_CIRCUIT;
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t mt6360_pmu_fled1_short_evt_handler(int irq, void *data)
+{
+	struct mt6360_led_data *mld = data;
+
+	dev_err(mld->dev, "%s\n", __func__);
+	mld->mtfled_cdev[MT6360_FLED_CH1].faults |= LED_FAULT_SHORT_CIRCUIT;
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t mt6360_pmu_fled2_strb_to_evt_handler(int irq, void *data)
+{
+	struct mt6360_led_data *mld = data;
+
+	mld->mtfled_cdev[MT6360_FLED_CH2].faults |= LED_FAULT_TIMEOUT;
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t mt6360_pmu_fled1_strb_to_evt_handler(int irq, void *data)
+{
+	struct mt6360_led_data *mld = data;
+
+	mld->mtfled_cdev[MT6360_FLED_CH1].faults |= LED_FAULT_TIMEOUT;
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t mt6360_pmu_fled_chg_vinovp_evt_handler(int irq, void *data)
+{
+	struct mt6360_led_data *mld = data;
+
+	dev_warn(mld->dev, "%s\n", __func__);
+	mld->mtfled_cdev[MT6360_FLED_CH1].faults |= LED_FAULT_INPUT_VOLTAGE;
+	mld->mtfled_cdev[MT6360_FLED_CH2].faults |= LED_FAULT_INPUT_VOLTAGE;
+	return IRQ_HANDLED;
+}
+
+static struct mt6360_pmu_irq_desc mt6360_pmu_fled_irq_desc[] = {
+	{ "fled_chg_vinovp_evt",  mt6360_pmu_fled_chg_vinovp_evt_handler },
+	{ "fled_lvf_evt", mt6360_pmu_fled_lvf_evt_handler },
+	{ "fled2_short_evt", mt6360_pmu_fled2_short_evt_handler },
+	{ "fled1_short_evt", mt6360_pmu_fled1_short_evt_handler },
+	{ "fled2_strb_to_evt", mt6360_pmu_fled2_strb_to_evt_handler },
+	{ "fled1_strb_to_evt", mt6360_pmu_fled1_strb_to_evt_handler },
+};
+
+static int mt6360_fled_irq_register(struct platform_device *pdev)
+{
+	struct mt6360_pmu_irq_desc *irq_desc;
+	int i, irq, ret;
+
+	for (i = 0; i < ARRAY_SIZE(mt6360_pmu_fled_irq_desc); i++) {
+		irq_desc = mt6360_pmu_fled_irq_desc + i;
+		if (unlikely(!irq_desc->name))
+			continue;
+		irq = platform_get_irq_byname(pdev, irq_desc->name);
+		if (irq < 0)
+			continue;
+		ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+						irq_desc->irq_handler,
+						IRQF_TRIGGER_FALLING,
+						irq_desc->name,
+						platform_get_drvdata(pdev));
+		if (ret < 0) {
+			dev_err(&pdev->dev,
+				"request %s irq fail\n", irq_desc->name);
+			return ret;
+		}
+	}
+	return 0;
+}
+
+static int mt6360_iled_parse_dt(struct device *dev,
+				struct mt6360_led_data *mld)
+{
+	struct device_node *iled_np, *child;
+	struct mt6360_led_classdev *mtled_cdev;
+	u32 val;
+	int ret;
+
+	if (!dev->of_node)
+		return 0;
+	iled_np = of_find_node_by_name(dev->of_node, "iled");
+	if (!iled_np)
+		return 0;
+	for_each_available_child_of_node(iled_np, child) {
+		ret = of_property_read_u32(child, "reg", &val);
+		if (ret) {
+			dev_err(dev, "Fail to read reg property\n");
+			continue;
+		}
+		if (val >= MT6360_LED_MAX) {
+			dev_err(dev, "Invalid iled reg [%u]\n", val);
+			ret = -EINVAL;
+			goto out_iled_dt;
+		}
+		mtled_cdev = mld->mtled_cdev + val;
+
+		of_property_read_string(child,
+					"label", &(mtled_cdev->cdev.name));
+		of_property_read_string(child, "linux,default-trigger",
+					&(mtled_cdev->cdev.default_trigger));
+		mtled_cdev->np = child;
+	}
+	return 0;
+out_iled_dt:
+	of_node_put(child);
+	return ret;
+}
+
+static int mt6360_fled_parse_dt(struct device *dev,
+				struct mt6360_led_data *mld)
+{
+	struct device_node *fled_np, *child;
+	struct mt6360_fled_classdev *mtfled_cdev;
+	struct led_classdev *led_cdev;
+	struct led_flash_setting *fs;
+	u32 val;
+	int ret;
+
+	if (!dev->of_node)
+		return 0;
+	fled_np = of_find_node_by_name(dev->of_node, "fled");
+	if (!fled_np)
+		return 0;
+	for_each_available_child_of_node(fled_np, child) {
+		ret = of_property_read_u32(child, "reg", &val);
+		if (ret) {
+			dev_err(dev, "Fail to read reg property\n");
+			continue;
+		}
+		if (val >= MT6360_FLED_MAX) {
+			dev_err(dev, "Invalid fled reg [%u]\n", val);
+			ret = -EINVAL;
+			goto out_fled_dt;
+		}
+		mtfled_cdev = mld->mtfled_cdev + val;
+
+		of_property_read_string(child, "label",
+					&(mtfled_cdev->fl_cdev.led_cdev.name));
+		ret = of_property_read_u32(child, "led-max-microamp", &val);
+		if (ret) {
+			dev_warn(dev, "led-max-microamp property missing\n");
+			val = MT6360_TORCHCUR_MIN;
+		}
+		if (val < MT6360_TORCHCUR_MIN)
+			val = MT6360_TORCHCUR_MIN;
+		val = (val - MT6360_TORCHCUR_MIN) / MT6360_TORCHCUR_STEP + 1;
+		led_cdev = &(mtfled_cdev->fl_cdev.led_cdev);
+		led_cdev->max_brightness = min(led_cdev->max_brightness, val);
+		ret = of_property_read_u32(child, "flash-max-microamp", &val);
+		if (ret) {
+			dev_warn(dev, "flash-max-microamp property missing\n");
+			val = MT6360_STROBECUR_MIN;
+		}
+		if (val < MT6360_STROBECUR_MIN)
+			val = MT6360_STROBECUR_MIN;
+		fs = &(mtfled_cdev->fl_cdev.brightness);
+		fs->val = fs->max = min(fs->max, val);
+		ret = of_property_read_u32(child, "flash-max-timeout", &val);
+		if (ret) {
+			dev_warn(dev, "flash-max-timeout property missing\n");
+			val = MT6360_STRBTIMEOUT_MIN;
+		}
+		if (val < MT6360_STRBTIMEOUT_MIN)
+			val = MT6360_STRBTIMEOUT_MIN;
+		fs = &(mtfled_cdev->fl_cdev.timeout);
+		fs->val = fs->max = min(fs->max, val);
+		mtfled_cdev->np = child;
+	}
+	return 0;
+out_fled_dt:
+	of_node_put(child);
+	return ret;
+}
+
+static void mt6360_led_parse_dt_data(struct device *dev,
+				     struct mt6360_led_platform_data *pdata)
+{
+	struct device_node *np = dev->of_node;
+	int i, ret;
+	const struct {
+		const char *name;
+		u32 *val_ptr;
+	} u32_opts[] = {
+		{ "rgbon_sync", &pdata->rgbon_sync },
+		{ "fled1_ultraistrb", &pdata->fled1_ultraistrb },
+		{ "fled2_ultraistrb", &pdata->fled2_ultraistrb },
+	};
+
+	memcpy(pdata, &def_platform_data, sizeof(*pdata));
+	for (i = 0; i < ARRAY_SIZE(u32_opts); i++) {
+		ret = of_property_read_u32(np, u32_opts[i].name,
+					   u32_opts[i].val_ptr);
+		if (ret)
+			dev_err(dev, "error reading '%s'\n", u32_opts[i].name);
+	}
+}
+
+static int mt6360_led_apply_pdata(struct mt6360_led_data *mld,
+				   struct mt6360_led_platform_data *pdata)
+{
+	int i, ret;
+	const struct {
+		u32 *val_ptr;
+		u8 reg;
+		u8 mask;
+		u8 shift;
+	} sel_props[] = {
+		{
+			&pdata->fled1_ultraistrb, MT6360_PMU_FLED1_STRB_CTRL2,
+			MT6360_MASK_ULTRA_STROBE, MT6360_SHIFT_ULTRA_STROBE,
+		},
+		{
+			&pdata->fled2_ultraistrb, MT6360_PMU_FLED2_STRB_CTRL2,
+			MT6360_MASK_ULTRA_STROBE, MT6360_SHIFT_ULTRA_STROBE,
+		},
+	};
+
+	for (i = 0; i < ARRAY_SIZE(sel_props); i++) {
+		ret = regmap_update_bits(mld->regmap,
+					 sel_props[i].reg,
+					 sel_props[i].mask,
+					 *sel_props[i].val_ptr <<
+						sel_props[i].shift);
+		if (ret < 0)
+			return ret;
+	}
+	return 0;
+}
+
+static int mt6360_led_probe(struct platform_device *pdev)
+{
+	struct mt6360_led_platform_data *pdata = dev_get_platdata(&pdev->dev);
+	struct mt6360_led_data *mld;
+	struct mt6360_led_classdev *mtled_cdev;
+	struct mt6360_fled_classdev *mtfled_cdev;
+	struct v4l2_flash_config v4l2_config;
+	int i, ret;
+
+	mld = devm_kzalloc(&pdev->dev, sizeof(*mld), GFP_KERNEL);
+	if (!mld)
+		return -ENOMEM;
+
+	if (pdev->dev.of_node) {
+		pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+		if (!pdata)
+			return -ENOMEM;
+		mt6360_led_parse_dt_data(&pdev->dev, pdata);
+	}
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "no platform data specified\n");
+		return -EINVAL;
+	}
+
+	mld->dev = &pdev->dev;
+	mld->pdata = pdata;
+	platform_set_drvdata(pdev, mld);
+
+	mld->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+	if (!mld->regmap) {
+		dev_err(&pdev->dev, "Failed to get parent regmap\n");
+		return -ENODEV;
+	}
+
+	ret = mt6360_led_apply_pdata(mld, pdata);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "apply pdata fail\n");
+		return ret;
+	}
+
+	memcpy(mld->mtled_cdev, def_led_classdev, sizeof(def_led_classdev));
+	ret = mt6360_iled_parse_dt(&pdev->dev, mld);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Failed to parse iled dt\n");
+		return ret;
+	}
+
+	for (i = 0; i < MT6360_LED_MAX; i++) {
+		mtled_cdev = mld->mtled_cdev + i;
+		ret = devm_led_classdev_register(&pdev->dev,
+						 &(mtled_cdev->cdev));
+		if (ret < 0) {
+			dev_err(&pdev->dev, "Failed to register led[%d]\n", i);
+			return ret;
+		}
+		mtled_cdev->cdev.dev->of_node = mtled_cdev->np;
+	}
+
+	memcpy(mld->mtfled_cdev, def_fled_classdev, sizeof(def_fled_classdev));
+	ret = mt6360_fled_parse_dt(&pdev->dev, mld);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Fail to parse fled dt\n");
+		return ret;
+	}
+
+	for (i = 0; i < MT6360_FLED_MAX; i++) {
+		mtfled_cdev = mld->mtfled_cdev + i;
+		ret = led_classdev_flash_register(&pdev->dev,
+						  &mtfled_cdev->fl_cdev);
+		if (ret < 0) {
+			dev_err(&pdev->dev, "Failed to register fled[%d]\n", i);
+			goto out_fled_cdev;
+		}
+	}
+
+	for (i = 0; i < MT6360_FLED_MAX; i++) {
+		mtfled_cdev = mld->mtfled_cdev + i;
+		memset(&v4l2_config, 0, sizeof(v4l2_config));
+		mt6360_init_v4l2_flash_config(mtfled_cdev, &v4l2_config);
+		mtfled_cdev->v4l2_flash = v4l2_flash_init(&pdev->dev,
+					      of_fwnode_handle(mtfled_cdev->np),
+					      &mtfled_cdev->fl_cdev,
+					      &v4l2_flash_ops, &v4l2_config);
+		if (IS_ERR(mtfled_cdev->v4l2_flash)) {
+			dev_err(&pdev->dev, "Failed to register v4l2_sd\n");
+			ret = PTR_ERR(mtfled_cdev->v4l2_flash);
+			goto out_v4l2_sd;
+		}
+	}
+
+	ret = mt6360_fled_irq_register(pdev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Failed to register irqs\n");
+		goto out_v4l2_sd;
+	}
+
+	return 0;
+out_v4l2_sd:
+	while (--i >= 0) {
+		mtfled_cdev = mld->mtfled_cdev + i;
+		v4l2_flash_release(mtfled_cdev->v4l2_flash);
+	}
+	i = MT6360_FLED_MAX;
+out_fled_cdev:
+	while (--i >= 0) {
+		mtfled_cdev = mld->mtfled_cdev + i;
+		led_classdev_flash_unregister(&mtfled_cdev->fl_cdev);
+	}
+	return ret;
+}
+
+static int mt6360_led_remove(struct platform_device *pdev)
+{
+	struct mt6360_led_data *mld = platform_get_drvdata(pdev);
+	struct mt6360_fled_classdev *mtfled_cdev;
+	int i;
+
+	for (i = 0; i < MT6360_FLED_MAX; i++) {
+		mtfled_cdev = mld->mtfled_cdev + i;
+		v4l2_flash_release(mtfled_cdev->v4l2_flash);
+		led_classdev_flash_unregister(&mtfled_cdev->fl_cdev);
+	}
+
+	return 0;
+}
+
+static const struct of_device_id __maybe_unused mt6360_led_of_id[] = {
+	{ .compatible = "mediatek,mt6360_led", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, mt6360_led_of_id);
+
+static struct platform_driver mt6360_led_driver = {
+	.driver = {
+		.name = "mt6360_led",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(mt6360_led_of_id),
+	},
+	.probe = mt6360_led_probe,
+	.remove = mt6360_led_remove,
+};
+module_platform_driver(mt6360_led_driver);
+
+MODULE_AUTHOR("Gene Chen <gene_chen@richtek.com>");
+MODULE_DESCRIPTION("MT6360 Led Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/mfd/mt6360.h b/include/linux/mfd/mt6360.h
index ea13040..2b81ab5 100644
--- a/include/linux/mfd/mt6360.h
+++ b/include/linux/mfd/mt6360.h
@@ -29,6 +29,11 @@ struct mt6360_pmu_data {
 	unsigned int chip_rev;
 };
 
+struct mt6360_pmu_irq_desc {
+	const char *name;
+	irq_handler_t irq_handler;
+};
+
 /* PMU register defininition */
 #define MT6360_PMU_DEV_INFO			(0x00)
 #define MT6360_PMU_CORE_CTRL1			(0x01)
@@ -236,5 +241,4 @@ struct mt6360_pmu_data {
 #define CHIP_VEN_MASK				(0xF0)
 #define CHIP_VEN_MT6360				(0x50)
 #define CHIP_REV_MASK				(0x0F)
-
 #endif /* __MT6360_H__ */
-- 
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

* Re: [PATCH] arch/{mips,sparc,microblaze,powerpc}: Don't enable pagefault/preempt twice
From: Mike Rapoport @ 2020-06-04  6:37 UTC (permalink / raw)
  To: Ira Weiny
  Cc: Peter Zijlstra, Benjamin Herrenschmidt, Dave Hansen, dri-devel,
	linux-mips, James E.J. Bottomley, Max Filippov, Paul Mackerras,
	H. Peter Anvin, sparclinux, Dan Williams, Helge Deller, x86,
	linux-csky, Christoph Hellwig, Ingo Molnar, linux-snps-arc,
	Guenter Roeck, linux-xtensa, Borislav Petkov, Al Viro,
	Andy Lutomirski, Thomas Gleixner, linux-arm-kernel, Chris Zankel,
	Thomas Bogendoerfer, linux-parisc, linux-kernel, Christian Koenig,
	Andrew Morton, linuxppc-dev, David S. Miller
In-Reply-To: <20200604062226.GA1740345@iweiny-DESK2.sc.intel.com>

On Wed, Jun 03, 2020 at 11:22:26PM -0700, Ira Weiny wrote:
> On Wed, Jun 03, 2020 at 04:44:17PM -0700, Guenter Roeck wrote:
> 
> With linux-next on sparc I too see the spinlock issue; something like:
> 
> ...
> Starting syslogd: BUG: spinlock recursion on CPU#0, S01syslogd/139
>  lock: 0xf53ef350, .magic: dead4ead, .owner: S01syslogd/139, .owner_cpu: 0
> CPU: 0 PID: 139 Comm: S01syslogd Not tainted 5.7.0-next-20200603 #1
> [f0067d00 : 
> do_raw_spin_lock+0xa8/0xd8 ] 
> [f00d598c : 
> copy_page_range+0x328/0x804 ] 
> [f0025c34 : 
> dup_mm+0x334/0x434 ] 
> [f0027198 : 
> copy_process+0x1248/0x12d4 ] 
> [f00273b8 : 
> _do_fork+0x54/0x30c ] 
> [f00276e4 : 
> do_fork+0x5c/0x6c ] 
> [f000de44 : 
> sparc_do_fork+0x18/0x38 ] 
> [f000b7f4 : 
> do_syscall+0x34/0x40 ] 
> [5010cd4c : 
> 0x5010cd4c ] 
> 
> 
> I'm going to bisect between there and HEAD.

The sparc issue should be fixed by 

https://lore.kernel.org/lkml/20200526173302.377-1-will@kernel.org
 
> Ira

-- 
Sincerely yours,
Mike.

_______________________________________________
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] arch/{mips,sparc,microblaze,powerpc}: Don't enable pagefault/preempt twice
From: Ira Weiny @ 2020-06-04  6:43 UTC (permalink / raw)
  To: Mike Rapoport
  Cc: Peter Zijlstra, Benjamin Herrenschmidt, Dave Hansen, dri-devel,
	linux-mips, James E.J. Bottomley, Max Filippov, Paul Mackerras,
	H. Peter Anvin, sparclinux, Dan Williams, Helge Deller, x86,
	linux-csky, Christoph Hellwig, Ingo Molnar, linux-snps-arc,
	Guenter Roeck, linux-xtensa, Borislav Petkov, Al Viro,
	Andy Lutomirski, Thomas Gleixner, linux-arm-kernel, Chris Zankel,
	Thomas Bogendoerfer, linux-parisc, linux-kernel, Christian Koenig,
	Andrew Morton, linuxppc-dev, David S. Miller
In-Reply-To: <20200604061805.GA202650@kernel.org>

On Thu, Jun 04, 2020 at 09:18:05AM +0300, Mike Rapoport wrote:
> On Wed, Jun 03, 2020 at 04:44:17PM -0700, Guenter Roeck wrote:
> > On 6/3/20 2:14 PM, Ira Weiny wrote:
> > > On Wed, Jun 03, 2020 at 01:57:36PM -0700, Andrew Morton wrote:
> > >> On Thu, 21 May 2020 10:42:50 -0700 Ira Weiny <ira.weiny@intel.com> wrote:
> > >>
> > >>>>>
> > >>>>> Actually it occurs to me that the patch consolidating kmap_prot is odd for
> > >>>>> sparc 32 bit...
> > >>>>>
> > >>>>> Its a long shot but could you try reverting this patch?
> > >>>>>
> > >>>>> 4ea7d2419e3f kmap: consolidate kmap_prot definitions
> > >>>>>
> > >>>>
> > >>>> That is not easy to revert, unfortunately, due to several follow-up patches.
> > >>>
> > >>> I have gotten your sparc tests to run and they all pass...
> > >>>
> > >>> 08:10:34 > ../linux-build-test/rootfs/sparc/run-qemu-sparc.sh 
> > >>> Build reference: v5.7-rc4-17-g852b6f2edc0f
> > >>>
> > >>> Building sparc32:SPARCClassic:nosmp:scsi:hd ... running ......... passed
> > >>> Building sparc32:SPARCbook:nosmp:scsi:cd ... running ......... passed
> > >>> Building sparc32:LX:nosmp:noapc:scsi:hd ... running ......... passed
> > >>> Building sparc32:SS-4:nosmp:initrd ... running ......... passed
> > >>> Building sparc32:SS-5:nosmp:scsi:hd ... running ......... passed
> > >>> Building sparc32:SS-10:nosmp:scsi:cd ... running ......... passed
> > >>> Building sparc32:SS-20:nosmp:scsi:hd ... running ......... passed
> > >>> Building sparc32:SS-600MP:nosmp:scsi:hd ... running ......... passed
> > >>> Building sparc32:Voyager:nosmp:noapc:scsi:hd ... running ......... passed
> > >>> Building sparc32:SS-4:smp:scsi:hd ... running ......... passed
> > >>> Building sparc32:SS-5:smp:scsi:cd ... running ......... passed
> > >>> Building sparc32:SS-10:smp:scsi:hd ... running ......... passed
> > >>> Building sparc32:SS-20:smp:scsi:hd ... running ......... passed
> > >>> Building sparc32:SS-600MP:smp:scsi:hd ... running ......... passed
> > >>> Building sparc32:Voyager:smp:noapc:scsi:hd ... running ......... passed
> > >>>
> > >>> Is there another test I need to run?
> > >>
> > >> This all petered out, but as I understand it, this patchset still might
> > >> have issues on various architectures.
> > >>
> > >> Can folks please provide an update on the testing status?
> > > 
> > > I believe the tests were failing for Guenter due to another patch set...[1]
> > > 
> > > My tests with just this series are working.
> > > 
> > >>From my understanding the other failures were unrelated.[2]
> > > 
> > > 	<quote Mike Rapoport>
> > > 	I've checked the patch above on top of the mmots which already has
> > > 	Ira's patches and it booted fine. I've used sparc32_defconfig to build
> > > 	the kernel and qemu-system-sparc with default machine and CPU.
> > > 	</quote>
> > > 
> > > Mike, am I wrong?  Do you think the kmap() patches are still causing issues?
> 
> sparc32 UP and microblaze work for me with next-20200603, but I didn't
> test other architectures. 
>  
> > For my part, all I can say is that -next is in pretty bad shape right now.
> > The summary of my tests says:
> > 
> > Build results:
> > 	total: 151 pass: 130 fail: 21
> > Qemu test results:
> > 	total: 430 pass: 375 fail: 55
> > 
> > sparc32 smp images in next-20200603 still crash for me with a spinlock
> > recursion.
> 
> I think this is because Will's fixes [1] are not yet in -next.
> 
> > s390 images hang early in boot. Several others (alpha, arm64,
> > various ppc) don't even compile. I can run some more bisects over time,
> > but this is becoming a full-time job :-(.
> > 
> > Guenter
> 
> [1] https://lore.kernel.org/lkml/20200526173302.377-1-will@kernel.org

I abandoned the bisect and tested with this fix.[1]  It passes.  Guenter, on
the original thread we had microblaze and ppc working with my fix.

https://lore.kernel.org/lkml/20200519194215.GA71941@roeck-us.net/

Sounds like the current failures above are from something much newer in the
tree.

Ira

[1]
23:26:24 > /home/iweiny/dev/linux-build-test/rootfs/sparc/run-qemu-sparc.sh 
Build reference: next-20200603-3-gf5afe92a2135

Building sparc32:SPARCClassic:nosmp:scsi:hd ... running ......... passed
Building sparc32:SPARCbook:nosmp:scsi:cd ... running ......... passed
Building sparc32:LX:nosmp:noapc:scsi:hd ... running ......... passed
Building sparc32:SS-4:nosmp:initrd ... running ......... passed
Building sparc32:SS-5:nosmp:scsi:hd ... running ......... passed
Building sparc32:SS-10:nosmp:scsi:cd ... running ......... passed
Building sparc32:SS-20:nosmp:scsi:hd ... running ......... passed
Building sparc32:SS-600MP:nosmp:scsi:hd ... running ......... passed
Building sparc32:Voyager:nosmp:noapc:scsi:hd ... running ......... passed
Building sparc32:SS-4:smp:scsi:hd ... running ......... passed
Building sparc32:SS-5:smp:scsi:cd ... running ......... passed
Building sparc32:SS-10:smp:scsi:hd ... running ......... passed
Building sparc32:SS-20:smp:scsi:hd ... running ......... passed
Building sparc32:SS-600MP:smp:scsi:hd ... running ......... passed
Building sparc32:Voyager:smp:noapc:scsi:hd ... running ......... passed


> -- 
> Sincerely yours,
> Mike.

_______________________________________________
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] arch/{mips,sparc,microblaze,powerpc}: Don't enable pagefault/preempt twice
From: Ira Weiny @ 2020-06-04  6:44 UTC (permalink / raw)
  To: Mike Rapoport
  Cc: Peter Zijlstra, Benjamin Herrenschmidt, Dave Hansen, dri-devel,
	linux-mips, James E.J. Bottomley, Max Filippov, Paul Mackerras,
	H. Peter Anvin, sparclinux, Dan Williams, Helge Deller, x86,
	linux-csky, Christoph Hellwig, Ingo Molnar, linux-snps-arc,
	Guenter Roeck, linux-xtensa, Borislav Petkov, Al Viro,
	Andy Lutomirski, Thomas Gleixner, linux-arm-kernel, Chris Zankel,
	Thomas Bogendoerfer, linux-parisc, linux-kernel, Christian Koenig,
	Andrew Morton, linuxppc-dev, David S. Miller
In-Reply-To: <20200604063745.GB202650@kernel.org>

On Thu, Jun 04, 2020 at 09:37:45AM +0300, Mike Rapoport wrote:
> On Wed, Jun 03, 2020 at 11:22:26PM -0700, Ira Weiny wrote:
> > On Wed, Jun 03, 2020 at 04:44:17PM -0700, Guenter Roeck wrote:
> > 
> > With linux-next on sparc I too see the spinlock issue; something like:
> > 
> > ...
> > Starting syslogd: BUG: spinlock recursion on CPU#0, S01syslogd/139
> >  lock: 0xf53ef350, .magic: dead4ead, .owner: S01syslogd/139, .owner_cpu: 0
> > CPU: 0 PID: 139 Comm: S01syslogd Not tainted 5.7.0-next-20200603 #1
> > [f0067d00 : 
> > do_raw_spin_lock+0xa8/0xd8 ] 
> > [f00d598c : 
> > copy_page_range+0x328/0x804 ] 
> > [f0025c34 : 
> > dup_mm+0x334/0x434 ] 
> > [f0027198 : 
> > copy_process+0x1248/0x12d4 ] 
> > [f00273b8 : 
> > _do_fork+0x54/0x30c ] 
> > [f00276e4 : 
> > do_fork+0x5c/0x6c ] 
> > [f000de44 : 
> > sparc_do_fork+0x18/0x38 ] 
> > [f000b7f4 : 
> > do_syscall+0x34/0x40 ] 
> > [5010cd4c : 
> > 0x5010cd4c ] 
> > 
> > 
> > I'm going to bisect between there and HEAD.
> 
> The sparc issue should be fixed by 
> 
> https://lore.kernel.org/lkml/20200526173302.377-1-will@kernel.org

Saw your other email.  And yes they are!

Thanks!
Ira

>  
> > Ira
> 
> -- 
> Sincerely yours,
> Mike.

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

^ permalink raw reply

* [PATCH] dt-bindings: input: Convert imx keypad to json-schema
From: Anson Huang @ 2020-06-04  6:43 UTC (permalink / raw)
  To: dmitry.torokhov, robh+dt, shawnguo, s.hauer, kernel, festevam,
	gnuiyl, linux-input, devicetree, linux-arm-kernel, linux-kernel
  Cc: Linux-imx

Convert the i.MX KEYPAD binding to DT schema format using json-schema

Signed-off-by: Anson Huang <Anson.Huang@nxp.com>
---
 .../devicetree/bindings/input/imx-keypad.txt       | 53 -------------
 .../devicetree/bindings/input/imx-keypad.yaml      | 89 ++++++++++++++++++++++
 2 files changed, 89 insertions(+), 53 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/input/imx-keypad.txt
 create mode 100644 Documentation/devicetree/bindings/input/imx-keypad.yaml

diff --git a/Documentation/devicetree/bindings/input/imx-keypad.txt b/Documentation/devicetree/bindings/input/imx-keypad.txt
deleted file mode 100644
index 2ebaf7d..0000000
--- a/Documentation/devicetree/bindings/input/imx-keypad.txt
+++ /dev/null
@@ -1,53 +0,0 @@
-* Freescale i.MX Keypad Port(KPP) device tree bindings
-
-The KPP is designed to interface with a keypad matrix with 2-point contact
-or 3-point contact keys. The KPP is designed to simplify the software task
-of scanning a keypad matrix. The KPP is capable of detecting, debouncing,
-and decoding one or multiple keys pressed simultaneously on a keypad.
-
-Required SoC Specific Properties:
-- compatible: Should be "fsl,<soc>-kpp".
-
-- reg: Physical base address of the KPP and length of memory mapped
-  region.
-
-- interrupts: The KPP interrupt number to the CPU(s).
-
-- clocks: The clock provided by the SoC to the KPP. Some SoCs use dummy
-clock(The clock for the KPP is provided by the SoCs automatically).
-
-Required Board Specific Properties:
-- pinctrl-names: The definition can be found at
-pinctrl/pinctrl-bindings.txt.
-
-- pinctrl-0: The definition can be found at
-pinctrl/pinctrl-bindings.txt.
-
-- linux,keymap: The definition can be found at
-bindings/input/matrix-keymap.txt.
-
-Example:
-kpp: kpp@73f94000 {
-	compatible = "fsl,imx51-kpp", "fsl,imx21-kpp";
-	reg = <0x73f94000 0x4000>;
-	interrupts = <60>;
-	clocks = <&clks 0>;
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_kpp_1>;
-	linux,keymap = <0x00000067	/* KEY_UP */
-			0x0001006c	/* KEY_DOWN */
-			0x00020072	/* KEY_VOLUMEDOWN */
-			0x00030066	/* KEY_HOME */
-			0x0100006a	/* KEY_RIGHT */
-			0x01010069	/* KEY_LEFT */
-			0x0102001c	/* KEY_ENTER */
-			0x01030073	/* KEY_VOLUMEUP */
-			0x02000040	/* KEY_F6 */
-			0x02010042	/* KEY_F8 */
-			0x02020043	/* KEY_F9 */
-			0x02030044	/* KEY_F10 */
-			0x0300003b	/* KEY_F1 */
-			0x0301003c	/* KEY_F2 */
-			0x0302003d	/* KEY_F3 */
-			0x03030074>;	/* KEY_POWER */
-};
diff --git a/Documentation/devicetree/bindings/input/imx-keypad.yaml b/Documentation/devicetree/bindings/input/imx-keypad.yaml
new file mode 100644
index 0000000..a1350cd
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/imx-keypad.yaml
@@ -0,0 +1,89 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/imx-keypad.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Freescale i.MX Keypad Port(KPP) device tree bindings
+
+maintainers:
+  - Liu Ying <gnuiyl@gmail.com>
+
+description: |
+  The KPP is designed to interface with a keypad matrix with 2-point contact
+  or 3-point contact keys. The KPP is designed to simplify the software task
+  of scanning a keypad matrix. The KPP is capable of detecting, debouncing,
+  and decoding one or multiple keys pressed simultaneously on a keypad.
+
+properties:
+  compatible:
+    oneOf:
+      - const: fsl,imx21-kpp
+      - items:
+          - enum:
+            - fsl,imx25-kpp
+            - fsl,imx27-kpp
+            - fsl,imx31-kpp
+            - fsl,imx35-kpp
+            - fsl,imx51-kpp
+            - fsl,imx53-kpp
+            - fsl,imx50-kpp
+            - fsl,imx6q-kpp
+            - fsl,imx6sx-kpp
+            - fsl,imx6sl-kpp
+            - fsl,imx6sll-kpp
+            - fsl,imx6ul-kpp
+            - fsl,imx7d-kpp
+          - const: fsl,imx21-kpp
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  linux,keymap:
+    $ref: '/schemas/types.yaml#/definitions/uint32-array'
+    description: |
+      An array of packed 1-cell entries containing the equivalent of row,
+      column and linux key-code. The 32-bit big endian cell is packed as:
+      row << 24 | column << 16 | key-code
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+  - linux,keymap
+
+additionalProperties: false
+
+examples:
+  - |
+    keypad@73f94000 {
+        compatible = "fsl,imx51-kpp", "fsl,imx21-kpp";
+        reg = <0x73f94000 0x4000>;
+        interrupts = <60>;
+        clocks = <&clks 0>;
+        pinctrl-names = "default";
+        pinctrl-0 = <&pinctrl_kpp_1>;
+        linux,keymap = <0x00000067	/* KEY_UP */
+                        0x0001006c	/* KEY_DOWN */
+                        0x00020072	/* KEY_VOLUMEDOWN */
+                        0x00030066	/* KEY_HOME */
+                        0x0100006a	/* KEY_RIGHT */
+                        0x01010069	/* KEY_LEFT */
+                        0x0102001c	/* KEY_ENTER */
+                        0x01030073	/* KEY_VOLUMEUP */
+                        0x02000040	/* KEY_F6 */
+                        0x02010042	/* KEY_F8 */
+                        0x02020043	/* KEY_F9 */
+                        0x02030044	/* KEY_F10 */
+                        0x0300003b	/* KEY_F1 */
+                        0x0301003c	/* KEY_F2 */
+                        0x0302003d	/* KEY_F3 */
+                        0x03030074>;	/* KEY_POWER */
+    };
-- 
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] regulator: mt6360: Add support for MT6360 regulator
From: Gene Chen @ 2020-06-04  7:06 UTC (permalink / raw)
  To: matthias.bgg
  Cc: gene_chen, lgirdwood, linux-kernel, cy_huang, benjamin.chao,
	broonie, linux-mediatek, Wilma.Wu, linux-arm-kernel, shufan_lee

From: Gene Chen <gene_chen@richtek.com>

Add MT6360 regulator driver include 2-channel buck and
6-channel ldo

Signed-off-by: Gene Chen <gene_chen@richtek.com>
base-commit: 098c4adf249c198519a4abebe482b1e6b8c50e47
---
 drivers/regulator/Kconfig            |  10 +
 drivers/regulator/Makefile           |   1 +
 drivers/regulator/mt6360-regulator.c | 571 +++++++++++++++++++++++++++++++++++
 include/linux/mfd/mt6360.h           |   5 +
 4 files changed, 587 insertions(+)
 create mode 100644 drivers/regulator/mt6360-regulator.c

diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index f4b72cb..05a3b14 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -680,6 +680,16 @@ config REGULATOR_MT6358
 	  This driver supports the control of different power rails of device
 	  through regulator interface.
 
+config REGULATOR_MT6360
+	tristate "MT6360 SubPMIC Regulator"
+	depends on MFD_MT6360
+	select CRC8
+	help
+	  Say Y here to enable MT6360 regulator support.
+	  This is support MT6360 PMIC/LDO part include
+	  2-channel buck with Thermal Shutdown and Overlord Protection
+	  6-channel High PSRR and Low Dropout LDO.
+
 config REGULATOR_MT6380
 	tristate "MediaTek MT6380 PMIC"
 	depends on MTK_PMIC_WRAP
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 6610ee0..1137af0 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -85,6 +85,7 @@ obj-$(CONFIG_REGULATOR_MPQ7920) += mpq7920.o
 obj-$(CONFIG_REGULATOR_MT6311) += mt6311-regulator.o
 obj-$(CONFIG_REGULATOR_MT6323)	+= mt6323-regulator.o
 obj-$(CONFIG_REGULATOR_MT6358)	+= mt6358-regulator.o
+obj-$(CONFIG_REGULATOR_MT6360) += mt6360-regulator.o
 obj-$(CONFIG_REGULATOR_MT6380)	+= mt6380-regulator.o
 obj-$(CONFIG_REGULATOR_MT6397)	+= mt6397-regulator.o
 obj-$(CONFIG_REGULATOR_QCOM_RPM) += qcom_rpm-regulator.o
diff --git a/drivers/regulator/mt6360-regulator.c b/drivers/regulator/mt6360-regulator.c
new file mode 100644
index 0000000..f0d878b
--- /dev/null
+++ b/drivers/regulator/mt6360-regulator.c
@@ -0,0 +1,571 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2020 MediaTek Inc.
+ *
+ * Author: Gene Chen <gene_chen@richtek.com>
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
+#include <linux/crc8.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+
+#include <linux/mfd/mt6360.h>
+
+enum {
+	MT6360_PMIC_BUCK1 = 0,
+	MT6360_PMIC_BUCK2,
+	MT6360_PMIC_LDO6,
+	MT6360_PMIC_LDO7,
+};
+
+enum {
+	MT6360_LDO_LDO1 = 0,
+	MT6360_LDO_LDO2,
+	MT6360_LDO_LDO3,
+	MT6360_LDO_LDO5,
+};
+
+#define MT6360_MAX_REGULATOR		(4)
+
+/* PMIC register defininition */
+#define MT6360_PMIC_BUCK1_VOSEL		(0x10)
+#define MT6360_PMIC_BUCK1_EN_CTRL2	(0x17)
+#define MT6360_PMIC_BUCK2_VOSEL		(0x20)
+#define MT6360_PMIC_BUCK2_EN_CTRL2	(0x27)
+#define MT6360_PMIC_LDO7_EN_CTRL2	(0x31)
+#define MT6360_PMIC_LDO7_CTRL3		(0x35)
+#define MT6360_PMIC_LDO6_EN_CTRL2	(0x37)
+#define MT6360_PMIC_LDO6_CTRL3		(0x3B)
+#define MT6360_PMIC_REGMAX		(0x3C)
+
+/* LDO register defininition */
+#define MT6360_LDO_LDO3_EN_CTRL2	(0x05)
+#define MT6360_LDO_LDO3_CTRL3		(0x09)
+#define MT6360_LDO_LDO5_EN_CTRL2	(0x0B)
+#define MT6360_LDO_LDO5_CTRL0		(0x0C)
+#define MT6360_LDO_LDO5_CTRL3		(0x0F)
+#define MT6360_LDO_LDO2_EN_CTRL2	(0x11)
+#define MT6360_LDO_LDO2_CTRL3		(0x15)
+#define MT6360_LDO_LDO1_EN_CTRL2	(0x17)
+#define MT6360_LDO_LDO1_CTRL3		(0x1B)
+#define MT6360_LDO_REGMAX		(0x1C)
+
+#define MT6360_OPMODE_LP		(2)
+#define MT6360_OPMODE_ULP		(3)
+#define MT6360_OPMODE_NORMAL		(0)
+
+struct mt6360_regulator_desc {
+	const struct regulator_desc desc;
+	unsigned int control_reg;
+	unsigned int mode_set_mask;
+	unsigned int mode_get_mask;
+};
+
+struct mt6360_regulator_devdata {
+	int i2c_idx;
+	const struct regmap_config *regmap_config;
+	const struct mt6360_regulator_desc *reg_descs;
+	int num_reg_descs;
+	const struct mt6360_pmu_irq_desc *irq_descs;
+	int num_irq_descs;
+};
+
+struct mt6360_regulator_data {
+	struct i2c_client *i2c;
+	struct device *dev;
+	struct regulator_dev *rdev[MT6360_MAX_REGULATOR];
+	struct regmap *regmap;
+	unsigned int chip_rev;
+	u8 crc8_table[CRC8_TABLE_SIZE];
+};
+
+#define MT6360_REGU_IRQH(_name, _rid, _event) \
+static irqreturn_t mt6360_pmu_##_name##_handler(int irq, void *data) \
+{ \
+	struct mt6360_regulator_data *mrd = data; \
+	dev_warn(mrd->dev, "%s\n", __func__); \
+	regulator_notifier_call_chain(mrd->rdev[_rid], _event, NULL); \
+	return IRQ_HANDLED; \
+}
+
+#define MT6360_REGU_IRQ(_name) { #_name, mt6360_pmu_##_name##_handler }
+
+/* PMIC irqs */
+MT6360_REGU_IRQH(buck1_pgb_evt, MT6360_PMIC_BUCK1, REGULATOR_EVENT_FAIL)
+MT6360_REGU_IRQH(buck1_oc_evt, MT6360_PMIC_BUCK1, REGULATOR_EVENT_OVER_CURRENT)
+MT6360_REGU_IRQH(buck1_ov_evt,
+		 MT6360_PMIC_BUCK1, REGULATOR_EVENT_REGULATION_OUT)
+MT6360_REGU_IRQH(buck1_uv_evt, MT6360_PMIC_BUCK1, REGULATOR_EVENT_UNDER_VOLTAGE)
+MT6360_REGU_IRQH(buck2_pgb_evt, MT6360_PMIC_BUCK2, REGULATOR_EVENT_FAIL)
+MT6360_REGU_IRQH(buck2_oc_evt, MT6360_PMIC_BUCK2, REGULATOR_EVENT_OVER_CURRENT)
+MT6360_REGU_IRQH(buck2_ov_evt,
+		 MT6360_PMIC_BUCK2, REGULATOR_EVENT_REGULATION_OUT)
+MT6360_REGU_IRQH(buck2_uv_evt, MT6360_PMIC_BUCK2, REGULATOR_EVENT_UNDER_VOLTAGE)
+MT6360_REGU_IRQH(ldo6_oc_evt, MT6360_PMIC_LDO6, REGULATOR_EVENT_OVER_CURRENT)
+MT6360_REGU_IRQH(ldo7_oc_evt, MT6360_PMIC_LDO7, REGULATOR_EVENT_OVER_CURRENT)
+MT6360_REGU_IRQH(ldo6_pgb_evt, MT6360_PMIC_LDO6, REGULATOR_EVENT_FAIL)
+MT6360_REGU_IRQH(ldo7_pgb_evt, MT6360_PMIC_LDO7, REGULATOR_EVENT_FAIL)
+
+/* LDO irqs */
+MT6360_REGU_IRQH(ldo1_oc_evt, MT6360_LDO_LDO1, REGULATOR_EVENT_OVER_CURRENT)
+MT6360_REGU_IRQH(ldo2_oc_evt, MT6360_LDO_LDO2, REGULATOR_EVENT_OVER_CURRENT)
+MT6360_REGU_IRQH(ldo3_oc_evt, MT6360_LDO_LDO3, REGULATOR_EVENT_OVER_CURRENT)
+MT6360_REGU_IRQH(ldo5_oc_evt, MT6360_LDO_LDO5, REGULATOR_EVENT_OVER_CURRENT)
+MT6360_REGU_IRQH(ldo1_pgb_evt, MT6360_LDO_LDO1, REGULATOR_EVENT_FAIL)
+MT6360_REGU_IRQH(ldo2_pgb_evt, MT6360_LDO_LDO2, REGULATOR_EVENT_FAIL)
+MT6360_REGU_IRQH(ldo3_pgb_evt, MT6360_LDO_LDO3, REGULATOR_EVENT_FAIL)
+MT6360_REGU_IRQH(ldo5_pgb_evt, MT6360_LDO_LDO5, REGULATOR_EVENT_FAIL)
+
+static const struct mt6360_pmu_irq_desc mt6360_pmic_irq_descs[] = {
+	MT6360_REGU_IRQ(buck1_pgb_evt),
+	MT6360_REGU_IRQ(buck1_oc_evt),
+	MT6360_REGU_IRQ(buck1_ov_evt),
+	MT6360_REGU_IRQ(buck1_uv_evt),
+	MT6360_REGU_IRQ(buck2_pgb_evt),
+	MT6360_REGU_IRQ(buck2_oc_evt),
+	MT6360_REGU_IRQ(buck2_ov_evt),
+	MT6360_REGU_IRQ(buck2_uv_evt),
+	MT6360_REGU_IRQ(ldo6_oc_evt),
+	MT6360_REGU_IRQ(ldo7_oc_evt),
+	MT6360_REGU_IRQ(ldo6_pgb_evt),
+	MT6360_REGU_IRQ(ldo7_pgb_evt),
+};
+
+static const struct mt6360_pmu_irq_desc mt6360_ldo_irq_descs[] = {
+	MT6360_REGU_IRQ(ldo1_oc_evt),
+	MT6360_REGU_IRQ(ldo2_oc_evt),
+	MT6360_REGU_IRQ(ldo3_oc_evt),
+	MT6360_REGU_IRQ(ldo5_oc_evt),
+	MT6360_REGU_IRQ(ldo1_pgb_evt),
+	MT6360_REGU_IRQ(ldo2_pgb_evt),
+	MT6360_REGU_IRQ(ldo3_pgb_evt),
+	MT6360_REGU_IRQ(ldo5_pgb_evt),
+};
+
+static int mt6360_regulator_irq_register(struct platform_device *pdev,
+				       struct mt6360_regulator_devdata *devdata)
+{
+	const struct mt6360_pmu_irq_desc *irq_desc;
+	int i, irq, ret;
+
+	for (i = 0; i < devdata->num_irq_descs; i++) {
+		irq_desc = devdata->irq_descs + i;
+		if (unlikely(!irq_desc->name))
+			continue;
+		irq = platform_get_irq_byname(pdev, irq_desc->name);
+		if (irq < 0)
+			continue;
+		ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+						irq_desc->irq_handler,
+						IRQF_TRIGGER_FALLING,
+						irq_desc->name,
+						platform_get_drvdata(pdev));
+		if (ret < 0) {
+			dev_err(&pdev->dev,
+				"request %s irq fail\n", irq_desc->name);
+			return ret;
+		}
+	}
+	return 0;
+}
+
+static int mt6360_regulator_set_mode(
+				  struct regulator_dev *rdev, unsigned int mode)
+{
+	const struct mt6360_regulator_desc *desc =
+			       (const struct mt6360_regulator_desc *)rdev->desc;
+	int shift = ffs(desc->mode_set_mask) - 1, ret;
+	unsigned int val;
+
+	if (!mode)
+		return -EINVAL;
+	switch (1 << (ffs(mode) - 1)) {
+	case REGULATOR_MODE_NORMAL:
+		val = MT6360_OPMODE_NORMAL;
+		break;
+	case REGULATOR_MODE_STANDBY:
+		val = MT6360_OPMODE_ULP;
+		break;
+	case REGULATOR_MODE_IDLE:
+		val = MT6360_OPMODE_LP;
+		break;
+	default:
+		return -ENOTSUPP;
+	}
+	ret = regmap_update_bits(rdev->regmap, desc->control_reg,
+				 desc->mode_set_mask, val << shift);
+	if (ret < 0) {
+		dev_err(&rdev->dev, "%s: fail (%d)\n", __func__, ret);
+		return ret;
+	}
+	return 0;
+}
+
+static unsigned int mt6360_regulator_get_mode(struct regulator_dev *rdev)
+{
+	const struct mt6360_regulator_desc *desc =
+			       (const struct mt6360_regulator_desc *)rdev->desc;
+	int shift = ffs(desc->mode_get_mask) - 1, ret;
+	unsigned int val = 0;
+
+	ret = regmap_read(rdev->regmap, desc->control_reg, &val);
+	if (ret < 0)
+		return ret;
+	val &= desc->mode_get_mask;
+	val >>= shift;
+	switch (val) {
+	case MT6360_OPMODE_LP:
+		ret = REGULATOR_MODE_IDLE;
+		break;
+	case MT6360_OPMODE_ULP:
+		ret = REGULATOR_MODE_STANDBY;
+		break;
+	case MT6360_OPMODE_NORMAL:
+		ret = REGULATOR_MODE_NORMAL;
+		break;
+	default:
+		ret = 0;
+	}
+	return ret;
+}
+
+static unsigned int mt6360_regulator_of_map_mode(unsigned int hw_mode)
+{
+	unsigned int trans_mode = 0;
+
+	switch (hw_mode) {
+	case MT6360_OPMODE_NORMAL:
+		trans_mode = REGULATOR_MODE_NORMAL;
+		break;
+	case MT6360_OPMODE_LP:
+		trans_mode = REGULATOR_MODE_IDLE;
+		break;
+	case MT6360_OPMODE_ULP:
+		trans_mode = REGULATOR_MODE_STANDBY;
+		break;
+	}
+	return trans_mode;
+}
+
+static const struct regulator_ops mt6360_pmic_regulator_ops = {
+	.list_voltage = regulator_list_voltage_linear,
+	.enable = regulator_enable_regmap,
+	.disable = regulator_disable_regmap,
+	.is_enabled = regulator_is_enabled_regmap,
+	.set_voltage_sel = regulator_set_voltage_sel_regmap,
+	.get_voltage_sel = regulator_get_voltage_sel_regmap,
+	.set_mode = mt6360_regulator_set_mode,
+	.get_mode = mt6360_regulator_get_mode,
+};
+
+#define MT6360_PMIC_DESC(_name, _min, _stp, _cnt, _vreg, _vmask, \
+			 _enreg, _enmask, _ctrlreg, _modesmask, _modegmask) \
+{									\
+	.desc = {							\
+		.name = #_name,						\
+		.id =  MT6360_PMIC_##_name,				\
+		.owner = THIS_MODULE,					\
+		.ops = &mt6360_pmic_regulator_ops,			\
+		.of_match = of_match_ptr(#_name),			\
+		.min_uV = _min,						\
+		.uV_step = _stp,					\
+		.n_voltages = _cnt,					\
+		.type = REGULATOR_VOLTAGE,				\
+		.vsel_reg = _vreg,					\
+		.vsel_mask = _vmask,					\
+		.enable_reg = _enreg,					\
+		.enable_mask = _enmask,					\
+		.of_map_mode = mt6360_regulator_of_map_mode,		\
+	},								\
+	.control_reg = _ctrlreg,					\
+	.mode_set_mask = _modesmask,					\
+	.mode_get_mask = _modegmask,					\
+}
+
+static const struct mt6360_regulator_desc mt6360_pmic_descs[] =  {
+	MT6360_PMIC_DESC(BUCK1, 300000, 5000, 201, MT6360_PMIC_BUCK1_VOSEL,
+			 0xff, MT6360_PMIC_BUCK1_EN_CTRL2, 0x40,
+			 MT6360_PMIC_BUCK1_EN_CTRL2, 0x30, 0x03),
+	MT6360_PMIC_DESC(BUCK2, 300000, 5000, 201, MT6360_PMIC_BUCK2_VOSEL,
+			 0xff, MT6360_PMIC_BUCK2_EN_CTRL2, 0x40,
+			 MT6360_PMIC_BUCK2_EN_CTRL2, 0x30, 0x03),
+	MT6360_PMIC_DESC(LDO6, 500000, 10000, 161, MT6360_PMIC_LDO6_CTRL3,
+			 0xff, MT6360_PMIC_LDO6_EN_CTRL2, 0x40,
+			 MT6360_PMIC_LDO6_EN_CTRL2, 0x30, 0x03),
+	MT6360_PMIC_DESC(LDO7, 500000, 10000, 161, MT6360_PMIC_LDO7_CTRL3,
+			 0xff, MT6360_PMIC_LDO7_EN_CTRL2, 0x40,
+			 MT6360_PMIC_LDO7_EN_CTRL2, 0x30, 0x03),
+};
+
+static const struct regulator_ops mt6360_ldo_regulator_ops = {
+	.list_voltage = regulator_list_voltage_linear_range,
+	.enable = regulator_enable_regmap,
+	.disable = regulator_disable_regmap,
+	.is_enabled = regulator_is_enabled_regmap,
+	.set_voltage_sel = regulator_set_voltage_sel_regmap,
+	.get_voltage_sel = regulator_get_voltage_sel_regmap,
+	.set_mode = mt6360_regulator_set_mode,
+	.get_mode = mt6360_regulator_get_mode,
+};
+
+static const struct regulator_linear_range ldo_volt_ranges1[] = {
+	REGULATOR_LINEAR_RANGE(1200000, 0x00, 0x09, 10000),
+	REGULATOR_LINEAR_RANGE(1300000, 0x0a, 0x10, 0),
+	REGULATOR_LINEAR_RANGE(1310000, 0x11, 0x19, 10000),
+	REGULATOR_LINEAR_RANGE(1400000, 0x1a, 0x1f, 0),
+	REGULATOR_LINEAR_RANGE(1500000, 0x20, 0x29, 10000),
+	REGULATOR_LINEAR_RANGE(1600000, 0x2a, 0x2f, 0),
+	REGULATOR_LINEAR_RANGE(1700000, 0x30, 0x39, 10000),
+	REGULATOR_LINEAR_RANGE(1800000, 0x3a, 0x40, 0),
+	REGULATOR_LINEAR_RANGE(1810000, 0x41, 0x49, 10000),
+	REGULATOR_LINEAR_RANGE(1900000, 0x4a, 0x4f, 0),
+	REGULATOR_LINEAR_RANGE(2000000, 0x50, 0x59, 10000),
+	REGULATOR_LINEAR_RANGE(2100000, 0x5a, 0x60, 0),
+	REGULATOR_LINEAR_RANGE(2110000, 0x61, 0x69, 10000),
+	REGULATOR_LINEAR_RANGE(2200000, 0x6a, 0x70, 0),
+	REGULATOR_LINEAR_RANGE(2210000, 0x71, 0x79, 10000),
+	REGULATOR_LINEAR_RANGE(2300000, 0x7a, 0x7f, 0),
+	REGULATOR_LINEAR_RANGE(2700000, 0x80, 0x89, 10000),
+	REGULATOR_LINEAR_RANGE(2800000, 0x8a, 0x90, 0),
+	REGULATOR_LINEAR_RANGE(2810000, 0x91, 0x99, 10000),
+	REGULATOR_LINEAR_RANGE(2900000, 0x9a, 0xa0, 0),
+	REGULATOR_LINEAR_RANGE(2910000, 0xa1, 0xa9, 10000),
+	REGULATOR_LINEAR_RANGE(3000000, 0xaa, 0xb0, 0),
+	REGULATOR_LINEAR_RANGE(3010000, 0xb1, 0xb9, 10000),
+	REGULATOR_LINEAR_RANGE(3100000, 0xba, 0xc0, 0),
+	REGULATOR_LINEAR_RANGE(3110000, 0xc1, 0xc9, 10000),
+	REGULATOR_LINEAR_RANGE(3200000, 0xca, 0xcf, 0),
+	REGULATOR_LINEAR_RANGE(3300000, 0xd0, 0xd9, 10000),
+	REGULATOR_LINEAR_RANGE(3400000, 0xda, 0xe0, 0),
+	REGULATOR_LINEAR_RANGE(3410000, 0xe1, 0xe9, 10000),
+	REGULATOR_LINEAR_RANGE(3500000, 0xea, 0xf0, 0),
+	REGULATOR_LINEAR_RANGE(3510000, 0xf1, 0xf9, 10000),
+	REGULATOR_LINEAR_RANGE(3600000, 0xfa, 0xff, 0),
+};
+
+static const struct regulator_linear_range ldo_volt_ranges2[] = {
+	REGULATOR_LINEAR_RANGE(2700000, 0x00, 0x09, 10000),
+	REGULATOR_LINEAR_RANGE(2800000, 0x0a, 0x10, 0),
+	REGULATOR_LINEAR_RANGE(2810000, 0x11, 0x19, 10000),
+	REGULATOR_LINEAR_RANGE(2900000, 0x1a, 0x20, 0),
+	REGULATOR_LINEAR_RANGE(2910000, 0x21, 0x29, 10000),
+	REGULATOR_LINEAR_RANGE(3000000, 0x2a, 0x30, 0),
+	REGULATOR_LINEAR_RANGE(3010000, 0x31, 0x39, 10000),
+	REGULATOR_LINEAR_RANGE(3100000, 0x3a, 0x40, 0),
+	REGULATOR_LINEAR_RANGE(3110000, 0x41, 0x49, 10000),
+	REGULATOR_LINEAR_RANGE(3200000, 0x4a, 0x4f, 0),
+	REGULATOR_LINEAR_RANGE(3300000, 0x50, 0x59, 10000),
+	REGULATOR_LINEAR_RANGE(3400000, 0x5a, 0x60, 0),
+	REGULATOR_LINEAR_RANGE(3410000, 0x61, 0x69, 10000),
+	REGULATOR_LINEAR_RANGE(3500000, 0x6a, 0x70, 0),
+	REGULATOR_LINEAR_RANGE(3510000, 0x71, 0x79, 10000),
+	REGULATOR_LINEAR_RANGE(3600000, 0x7a, 0x7f, 0),
+};
+
+#define MT6360_LDO_DESC(_name, _vranges, _vcnt, _vreg, _vmask, _enreg, \
+		      _enmask, _ctrlreg, _modesmask, _modegmask, _offon_delay) \
+{									\
+	.desc = {							\
+		.name = #_name,						\
+		.id =  MT6360_LDO_##_name,				\
+		.owner = THIS_MODULE,					\
+		.ops = &mt6360_ldo_regulator_ops,			\
+		.of_match = of_match_ptr(#_name),			\
+		.linear_ranges = _vranges,				\
+		.n_linear_ranges = ARRAY_SIZE(_vranges),		\
+		.n_voltages = _vcnt,					\
+		.type = REGULATOR_VOLTAGE,				\
+		.vsel_reg = _vreg,					\
+		.vsel_mask = _vmask,					\
+		.enable_reg = _enreg,					\
+		.enable_mask = _enmask,					\
+		.off_on_delay = _offon_delay,				\
+		.of_map_mode = mt6360_regulator_of_map_mode,		\
+	},								\
+	.control_reg = _ctrlreg,					\
+	.mode_set_mask = _modesmask,					\
+	.mode_get_mask = _modegmask,					\
+}
+
+static const struct mt6360_regulator_desc mt6360_ldo_descs[] =  {
+	MT6360_LDO_DESC(LDO1, ldo_volt_ranges1, 256, MT6360_LDO_LDO1_CTRL3,
+			0xff, MT6360_LDO_LDO1_EN_CTRL2, 0x40,
+			MT6360_LDO_LDO1_EN_CTRL2, 0x30, 0x03, 0),
+	MT6360_LDO_DESC(LDO2, ldo_volt_ranges1, 256, MT6360_LDO_LDO2_CTRL3,
+			0xff, MT6360_LDO_LDO2_EN_CTRL2, 0x40,
+			MT6360_LDO_LDO2_EN_CTRL2, 0x30, 0x03, 0),
+	MT6360_LDO_DESC(LDO3, ldo_volt_ranges1, 256, MT6360_LDO_LDO3_CTRL3,
+			0xff, MT6360_LDO_LDO3_EN_CTRL2, 0x40,
+			MT6360_LDO_LDO3_EN_CTRL2, 0x30, 0x03, 100),
+	MT6360_LDO_DESC(LDO5, ldo_volt_ranges2, 128, MT6360_LDO_LDO5_CTRL3,
+			0xff, MT6360_LDO_LDO5_EN_CTRL2, 0x40,
+			MT6360_LDO_LDO5_EN_CTRL2, 0x30, 0x03, 100),
+};
+
+static int mt6360_regulator_reg_write(void *context,
+				      unsigned int reg, unsigned int val)
+{
+	struct mt6360_regulator_data *mrd = context;
+	u8 chunk[4] = {0};
+
+	/* chunk 0 ->i2c addr, 1 -> reg_addr, 2 -> reg_val 3-> crc8 */
+	chunk[0] = (mrd->i2c->addr & 0x7f) << 1;
+	chunk[1] = reg & 0x3f;
+	chunk[2] = (u8)val;
+	chunk[3] = crc8(mrd->crc8_table, chunk, 3, 0);
+	/* also dummy one byte */
+	return i2c_smbus_write_i2c_block_data(mrd->i2c, chunk[1], 3, chunk + 2);
+}
+
+static int mt6360_regulator_reg_read(void *context,
+				     unsigned int reg, unsigned int *val)
+{
+	struct mt6360_regulator_data *mrd = context;
+	u8 chunk[5] = {0};
+	int ret;
+
+	/* chunk 0->i2c addr, 1->reg_addr, 2->reg_val, 3->crc8, 4->crck */
+	chunk[0] = ((mrd->i2c->addr & 0x7f) << 1) + 1;
+	chunk[1] = reg & 0x3f;
+	ret =  i2c_smbus_read_i2c_block_data(mrd->i2c, chunk[1], 2, chunk + 2);
+	if (ret < 0)
+		return ret;
+	chunk[4] = crc8(mrd->crc8_table, chunk, 3, 0);
+	if (chunk[3] != chunk[4])
+		return -EINVAL;
+	*val = chunk[2];
+	return 0;
+}
+
+static const struct regmap_config mt6360_pmic_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.reg_read = mt6360_regulator_reg_read,
+	.reg_write = mt6360_regulator_reg_write,
+	.max_register = MT6360_PMIC_REGMAX,
+	.use_single_read = true,
+	.use_single_write = true,
+};
+
+static const struct regmap_config mt6360_ldo_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.reg_read = mt6360_regulator_reg_read,
+	.reg_write = mt6360_regulator_reg_write,
+	.max_register = MT6360_LDO_REGMAX,
+	.use_single_read = true,
+	.use_single_write = true,
+};
+
+static const struct mt6360_regulator_devdata mt6360_pmic_devdata = {
+	.i2c_idx = MT6360_SLAVE_PMIC,
+	.regmap_config = &mt6360_pmic_regmap_config,
+	.reg_descs = mt6360_pmic_descs,
+	.num_reg_descs = ARRAY_SIZE(mt6360_pmic_descs),
+	.irq_descs = mt6360_pmic_irq_descs,
+	.num_irq_descs = ARRAY_SIZE(mt6360_pmic_irq_descs),
+};
+
+static const struct mt6360_regulator_devdata mt6360_ldo_devdata = {
+	.i2c_idx = MT6360_SLAVE_LDO,
+	.regmap_config = &mt6360_ldo_regmap_config,
+	.reg_descs = mt6360_ldo_descs,
+	.num_reg_descs = ARRAY_SIZE(mt6360_ldo_descs),
+	.irq_descs = mt6360_ldo_irq_descs,
+	.num_irq_descs = ARRAY_SIZE(mt6360_ldo_irq_descs),
+};
+
+static const struct of_device_id __maybe_unused mt6360_regulator_of_id[] = {
+	{
+		.compatible = "mediatek,mt6360_pmic",
+		.data = (void *)&mt6360_pmic_devdata,
+	},
+	{
+		.compatible = "mediatek,mt6360_ldo",
+		.data = (void *)&mt6360_ldo_devdata,
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, mt6360_regulator_of_id);
+
+static int mt6360_regulator_probe(struct platform_device *pdev)
+{
+	struct mt6360_pmu_data *pmu_data = dev_get_drvdata(pdev->dev.parent);
+	struct mt6360_regulator_devdata *devdata;
+	struct mt6360_regulator_data *mrd;
+	struct regulator_config config = {};
+	const struct of_device_id *match;
+	const struct platform_device_id *id;
+	int i, ret;
+
+	mrd = devm_kzalloc(&pdev->dev, sizeof(*mrd), GFP_KERNEL);
+	if (!mrd)
+		return -ENOMEM;
+
+	if (pdev->dev.of_node) {
+		match = of_match_device(
+			      of_match_ptr(mt6360_regulator_of_id), &pdev->dev);
+		if (!match) {
+			dev_err(&pdev->dev, "no match device id\n");
+			return -EINVAL;
+		}
+		devdata = (struct mt6360_regulator_devdata *)match->data;
+	} else {
+		id = platform_get_device_id(pdev);
+		devdata = (struct mt6360_regulator_devdata *)id->driver_data;
+	}
+
+	mrd->i2c = pmu_data->i2c[devdata->i2c_idx];
+	mrd->dev = &pdev->dev;
+	mrd->chip_rev = pmu_data->chip_rev;
+	crc8_populate_msb(mrd->crc8_table, 0x7);
+	platform_set_drvdata(pdev, mrd);
+
+	mrd->regmap = devm_regmap_init(&(mrd->i2c->dev),
+				       NULL, mrd, devdata->regmap_config);
+	if (IS_ERR(mrd->regmap)) {
+		dev_err(&pdev->dev, "Failed to register regmap\n");
+		return PTR_ERR(mrd->regmap);
+	}
+
+	config.dev = &pdev->dev;
+	config.driver_data = mrd;
+	config.regmap = mrd->regmap;
+
+	for (i = 0; i < devdata->num_reg_descs; i++) {
+		mrd->rdev[i] = devm_regulator_register(&pdev->dev,
+					&(devdata->reg_descs[i].desc), &config);
+		if (IS_ERR(mrd->rdev[i])) {
+			dev_err(&pdev->dev,
+				"Failed to register  %d regulaotr\n", i);
+			return PTR_ERR(mrd->rdev[i]);
+		}
+	}
+
+	ret = mt6360_regulator_irq_register(pdev, devdata);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Failed to register irqs\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static struct platform_driver mt6360_regulator_driver = {
+	.driver = {
+		.name = "mt6360_regulator",
+		.of_match_table = of_match_ptr(mt6360_regulator_of_id),
+	},
+	.probe = mt6360_regulator_probe,
+};
+module_platform_driver(mt6360_regulator_driver);
+
+MODULE_AUTHOR("Gene Chen <gene_chen@richtek.com>");
+MODULE_DESCRIPTION("MT6360 Regulator Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/mfd/mt6360.h b/include/linux/mfd/mt6360.h
index ea13040..495dfa8 100644
--- a/include/linux/mfd/mt6360.h
+++ b/include/linux/mfd/mt6360.h
@@ -29,6 +29,11 @@ struct mt6360_pmu_data {
 	unsigned int chip_rev;
 };
 
+struct mt6360_pmu_irq_desc {
+	const char *name;
+	irq_handler_t irq_handler;
+};
+
 /* PMU register defininition */
 #define MT6360_PMU_DEV_INFO			(0x00)
 #define MT6360_PMU_CORE_CTRL1			(0x01)
-- 
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

* Re: [PATCH v8 0/5] support reserving crashkernel above 4G on arm64 kdump
From: Will Deacon @ 2020-06-04  7:14 UTC (permalink / raw)
  To: Bhupesh Sharma
  Cc: John Donnelly, Prabhakar Kushwaha, Arnd Bergmann, Baoquan He,
	Devicetree List, chenzhou, Catalin Marinas,
	Linux Doc Mailing List, kexec mailing list,
	Linux Kernel Mailing List, Rob Herring, Simon Horman, James Morse,
	linux-arm-kernel, guohanjun, Thomas Gleixner, Prabhakar Kushwaha,
	RuiRui Yang, Ingo Molnar, nsaenzjulienne
In-Reply-To: <CACi5LpN-+NRnaDoWWWidbzma8BNzmofA5FQBV=cPF1Mc84FpFg@mail.gmail.com>

On Thu, Jun 04, 2020 at 01:17:06AM +0530, Bhupesh Sharma wrote:
> On Wed, Jun 3, 2020 at 9:03 PM John Donnelly <john.p.donnelly@oracle.com> wrote:
> > > On Jun 3, 2020, at 8:20 AM, chenzhou <chenzhou10@huawei.com> wrote:
> > > On 2020/6/3 19:47, Prabhakar Kushwaha wrote:
> > >>>> diff --git a/kernel/crash_core.c b/kernel/crash_core.c
> > >>>> index 7f9e5a6dc48c..bd67b90d35bd 100644
> > >>>> --- a/kernel/crash_core.c
> > >>>> +++ b/kernel/crash_core.c
> > >>>> @@ -354,7 +354,7 @@ int __init reserve_crashkernel_low(void)
> > >>>>                       return 0;
> > >>>>       }
> > >>>>
> > >>>> -       low_base = memblock_find_in_range(0, 1ULL << 32, low_size, CRASH_ALIGN);
> > >>>> +       low_base = memblock_find_in_range(0,0xc0000000, low_size, CRASH_ALIGN);
> > >>>>       if (!low_base) {
> > >>>>               pr_err("Cannot reserve %ldMB crashkernel low memory,
> > >>>> please try smaller size.\n",
> > >>>>                      (unsigned long)(low_size >> 20));
> > >>>>
> > >>>>
> > >>>    I suspect  0xc0000000  would need to be a CONFIG item  and not hard-coded.
> > >>>
> > >> if you consider this as valid change,  can you please incorporate as
> > >> part of your patch-set.
> > >
> > > After commit 1a8e1cef7 ("arm64: use both ZONE_DMA and
> > > ZONE_DMA32"),the 0-4G memory is splited to DMA [mem
> > > 0x0000000000000000-0x000000003fffffff] and DMA32 [mem
> > > 0x0000000040000000-0x00000000ffffffff] on arm64.
> > >
> > > From the above discussion, on your platform, the low crashkernel fall
> > > in DMA32 region, but your environment needs to access DMA region, so
> > > there is the call trace.
> > >
> > > I have a question, why do you choose 0xc0000000 here?
> > >
> > > Besides, this is common code, we also need to consider about x86.
> > >
> >
> >  + nsaenzjulienne@suse.de
> >
> >   Exactly .  This is why it needs to be a CONFIG option for  Raspberry
> >   ..,  or device tree option.
> >
> >
> >   We could revert 1a8e1cef7 since it broke  Arm kdump too.
> 
> Well, unfortunately the patch for commit 1a8e1cef7603 ("arm64: use
> both ZONE_DMA and ZONE_DMA32") was not Cc'ed to the kexec mailing
> list, thus we couldn't get many eyes on it for a thorough review from
> kexec/kdump p-o-v.
> 
> Also we historically never had distinction in common arch code on the
> basis of the intended end use-case: embedded, server or automotive, so
> I am not sure introducing a Raspberry specific CONFIG option would be
> a good idea.

Right, we need a fix that works for everybody, since we try hard for a
single Image that works for all platforms.

What I don't really understand is why, with Chen's patches applied, we can't
just keep the crashkernel out of the DMA zones altogether when no base is
specified. I guess I'll just look out for your patch!

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 v6 2/2] arm64/crash_core: Export TCR_EL1.T1SZ in vmcoreinfo
From: Will Deacon @ 2020-06-04  7:19 UTC (permalink / raw)
  To: Bhupesh Sharma
  Cc: Mark Rutland, Kazuhito Hagio, Ganapatrao Kulkarni, Steve Capper,
	Catalin Marinas, x86@kernel.org, kexec@lists.infradead.org,
	linux-kernel@vger.kernel.org, Ard Biesheuvel, Kamlakant Patel,
	James Morse, Dave Anderson, bhupesh.linux@gmail.com,
	linux-arm-kernel@lists.infradead.org
In-Reply-To: <CACi5LpOyQ+MAg9rh=cgLprBGTZ3kvtVP1ShNKG-2AV1Tu14EgQ@mail.gmail.com>

On Thu, Jun 04, 2020 at 02:04:58AM +0530, Bhupesh Sharma wrote:
> On Wed, Jun 3, 2020 at 4:50 PM Kamlakant Patel <kamlakantp@marvell.com> wrote:
> > > diff --git a/arch/arm64/kernel/crash_core.c b/arch/arm64/kernel/crash_core.c
> > > index 1f646b07e3e9..314391a156ee 100644
> > > --- a/arch/arm64/kernel/crash_core.c
> > > +++ b/arch/arm64/kernel/crash_core.c
> > > @@ -7,6 +7,14 @@
> > >  #include <linux/crash_core.h>
> > >  #include <asm/cpufeature.h>
> > >  #include <asm/memory.h>
> > > +#include <asm/pgtable-hwdef.h>
> > > +
> > > +static inline u64 get_tcr_el1_t1sz(void);
> > > +
> > > +static inline u64 get_tcr_el1_t1sz(void) {
> > > +     return (read_sysreg(tcr_el1) & TCR_T1SZ_MASK) >> TCR_T1SZ_OFFSET; }
> > >
> > >  void arch_crash_save_vmcoreinfo(void)
> > >  {
> > > @@ -16,6 +24,8 @@ void arch_crash_save_vmcoreinfo(void)
> > >                                               kimage_voffset);
> > >       vmcoreinfo_append_str("NUMBER(PHYS_OFFSET)=0x%llx\n",
> > >                                               PHYS_OFFSET);
> > > +     vmcoreinfo_append_str("NUMBER(TCR_EL1_T1SZ)=0x%llx\n",
> > > +                                             get_tcr_el1_t1sz());
> > I tested this patch on top of upstream kernel v5.7 and I am getting "crash: cannot determine VA_BITS_ACTUAL" error with crash tool.
> > I looked into crash-utility source and it is expecting tcr_el1_t1sz not TCR_EL1_T1SZ.
> > Could you please check.
> 
> Indeed. As per James comments on the v5 (see [1]) where he suggested
> converting ttcr_el1_t1sz into TCR_EL1_T1SZ, I made the change in v6
> accordingly.
> 
> This time I haven't sent out the v6 userspace changes
> (makedumpfile/crash-utility) upstream first, since we are waiting for
> kernel changes to be accepted first, as we have seen in the past that
> while the userspace patches have been accepted, the kernel patches
> required a respin cycle, thus leading to inconsistencies, as you also
> pointed out with crash-utility.

Yes, and that';s the right way to do it. Userspace can't rely on the
stability of a kernel interface if it's no in the upstream kernel!

So doing with the ALL CAPS names is the right thing to do.

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 2/2] coresight: tmc: Add shutdown callback for TMC ETR/ETF
From: Sai Prakash Ranjan @ 2020-06-04  7:27 UTC (permalink / raw)
  To: Mathieu Poirier, Robin Murphy, Will Deacon
  Cc: Suzuki K Poulose, linux-arm-msm, Coresight ML,
	Linux Kernel Mailing List, Stephen Boyd, linux-arm-kernel,
	Mike Leach
In-Reply-To: <20200603174426.GA23165@xps15>

Hi Mathieu,

+Will

On 2020-06-03 23:14, Mathieu Poirier wrote:
> On Wed, Jun 03, 2020 at 02:34:10PM +0100, Robin Murphy wrote:
>> On 2020-06-03 14:22, Mike Leach wrote:
>> > Hi Sai,
>> >
>> > On Wed, 3 Jun 2020 at 13:14, Sai Prakash Ranjan
>> > <saiprakash.ranjan@codeaurora.org> wrote:
>> > >
>> > > Hi Mike,
>> > >
>> > > On 2020-06-03 16:57, Mike Leach wrote:
>> > > > Hi,
>> > > >
>> > > > On Wed, 3 Jun 2020 at 11:24, Sai Prakash Ranjan
>> > > > <saiprakash.ranjan@codeaurora.org> wrote:
>> > > > >
>> > > > > Hi Mike,
>> > > > >
>> > > > > Thanks again for looking at this.
>> > > > >
>> > > > > On 2020-06-03 03:42, Mike Leach wrote:
>> > > > > [...]
>> > > > >
>> > > > > > >
>> > > > > > > SMMU/IOMMU won't be able to do much here as it is the client's
>> > > > > > > responsiblity to
>> > > > > > > properly shutdown and SMMU device link just makes sure that
>> > > > > > > SMMU(supplier) shutdown is
>> > > > > > > called only after its consumers shutdown callbacks are called.
>> > > > > >
>> > > > > > I think this use case can be handled slightly differently than the
>> > > > > > general requirements for modular CoreSight drivers.
>> > > > > >
>> > > > > > What is needed here is a way of stopping the underlying ETR hardware
>> > > > > > from issuing data to the SMMU, until the entire device has been shut
>> > > > > > down, in a way that does not remove the driver, breaking existing
>> > > > > > references and causing a system crash.
>> > > > > >
>> > > > > > We could introduce a new mode to the ETR driver - e.g.
>> > > > > > CS_MODE_SHUTDOWN.
>> > > > > >
>> > > > > > At the end of the block tmc_shutdown(struct amba_device *adev), set
>> > > > > > drvdata->mode to CS_MODE_SHUTDOWN & remove the coresight_unregister().
>> > > > > > This new mode can be used to  prevent the underlying hardware from
>> > > > > > being able to restart until the device is re-powered.
>> > > > > >
>> > > > > > This mode can be detected in the code that enables / disables the ETR
>> > > > > > and handled appropriately (updates to tmc_enable_etr_sink and
>> > > > > > tmc_disable_etr_sink).
>> > > > > > This mode will persist until the device is re-started - but because we
>> > > > > > are on the device shutdown path this is not an issue.
>> > > > > >
>> > > > > > This should leave the CoreSight infrastructure stable until the
>> > > > > > drivers are shut down normally as part of the device power down
>> > > > > > process.
>> > > > > >
>> > > > >
>> > > > > Sounds good to me, but if the coresight_unregister() is the trouble
>> > > > > point
>> > > > > causing these crashes, then can't we just remove that from
>> > > > > tmc_shutdown()
>> > > > > callback? This would be like maintaining the same behaviour as now
>> > > > > where
>> > > > > on reboot/shutdown we basically don't do anything except for disabling
>> > > > > ETR.
>> > > >
>> > > > No - the new mode prevents race conditions where the thread shutting
>> > > > down the SMMU does the ETR shutdown, but then another thread happens
>> > > > to be trying to start trace and restarts the ETR.
>> > > > It also prevents the condition Mathieu discussed where a thread might
>> > > > be attempting to shutdown trace - this could try to disable the
>> > > > hardware again re-releasing resources/ re-flushing and waiting for
>> > > > stop.
>> > > >
>> > >
>> > > I do not think there will a race between SMMU shutdown and ETR shutdown.
>> > > Driver core takes care of calling SMMU shutdown after its consumer
>> > > shutdown callbacks via device link, otherwise there would already be
>> > > bugs in all other client drivers.
>> > >
>> >
>> > I am not saying there could be a race between tmc_shutdowm and
>> > Smmu_shutdown - there may be a case if the coresight_disable_path
>> > sequence is running and gets to the point of disabling the ETR after
>> > the SMMU callback has disabled it.
>> 
>> I'm confused now - there is no "SMMU callback", we're talking about 
>> the
>> system-wide cleanup from kernel_shutdown_prepare() or
>> kernel_restart_prepare(). As far as I'm aware userspace should be long 
>> gone
>> by that point, so although trace may have been left running, the 
>> chance of
>> racing against other driver operations seems pretty unlikely.
> 
> Robin has a point - user space is long gone at this time.  As such the 
> first
> question to ask is what kind of CS session was running at the time the 
> system
> was shutting down.  Was it a perf session of a sysfs session?
> 
> I'm guessing it was a sysfs session because user space has been blown 
> away a
> while back and part of that process should have killed all perf 
> sessions.

I was enabling trace via sysfs.

> 
> If I am correct then simply switching off the ETR HW in the shutdown() 
> amba bus
> callback should be fine - otherwise Mike's approach is mandatory.  
> There is
> also the exchange between Robin and Sai about removing the SMMU 
> shutdown
> callback, but that thread is still incomplete.
> 

If Robin is hinting at removing SMMU shutdown callback, then I think 
adding
all these shutdown callbacks to all clients of SMMU can be avoided. Git 
blaming
the thing shows it was added to avoid some kexec memory corruption.

Thanks,
Sai

-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a 
member
of Code Aurora Forum, hosted by The Linux Foundation

_______________________________________________
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: Dmitry Torokhov @ 2020-06-04  7:28 UTC (permalink / raw)
  To: Hans de Goede
  Cc: Nick Dyer, linux-iio, Benjamin Tissoires, platform-driver-x86,
	ibm-acpi-devel, Laxman Dewangan, Peter Meerwald-Stadler, kernel,
	Fabio Estevam, linux-samsung-soc, Krzysztof Kozlowski,
	Jonathan Hunter, linux-acpi, Kukjin Kim, NXP Linux Team,
	linux-input, Len Brown, Peter Hutterer, Michael Hennerich,
	Sascha Hauer, Sylvain Lemieux, Henrique de Moraes Holschuh,
	Vladimir Zapolskiy, Lars-Peter Clausen, linux-tegra,
	linux-arm-kernel, Barry Song, Ferruh Yigit, patches,
	Rafael J . Wysocki, Andrzej Pietrasiewicz, Thierry Reding,
	Sangwon Jee, Pengutronix Kernel Team, Hartmut Knaack, Shawn Guo,
	Jonathan Cameron
In-Reply-To: <01b902dd-8841-e697-5ba7-96fa6b73c1cd@redhat.com>

Hi Hans, Andrzej,

On Wed, Jun 03, 2020 at 09:37:10PM +0200, Hans de Goede wrote:
> Hi,
> 
> On 6/3/20 7:54 PM, Andrzej Pietrasiewicz wrote:
> > W dniu 03.06.2020 o 19:38, Hans de Goede pisze:
> > > Hi,
> > > 
> > > On 6/3/20 3:07 PM, Andrzej Pietrasiewicz wrote:
> > > > Hi Hans, hi Dmitry,
> > > 
> > > <snip>
> > > 
> > > > I'm taking one step back and looking at the ->open() and ->close()
> > > > driver callbacks. They are called from input_open_device() and
> > > > input_close_device(), respectively:
> > > > 
> > > > input_open_device():
> > > > "This function should be called by input handlers when they
> > > > want to start receive events from given input device."
> > > > 
> > > > ->open() callback:
> > > > "this method is called when the very first user calls
> > > > input_open_device(). The driver must prepare the device to start
> > > > generating events (start polling thread, request an IRQ, submit
> > > > URB, etc.)"
> > > > 
> > > > input_close_device():
> > > > "This function should be called by input handlers when they
> > > > want to stop receive events from given input device."
> > > > 
> > > > ->close() callback:
> > > > "this method is called when the very last user calls
> > > > input_close_device()"
> > > > 
> > > > It seems to me that the callback names do not reflect their
> > > > purpose: their meaning is not to "open" or to "close" but to
> > > > give drivers a chance to control when they start or stop
> > > > providing events to the input core.
> > > > 
> > > > What would you say about changing the callbacks' names?
> > > > I'd envsion: ->provide_events() instead of ->open() and
> > > > ->stop_events() instead of ->close(). Of course drivers can
> > > > exploit the fact of knowing that nobody wants any events
> > > > from them and do whatever they consider appropriate, for
> > > > example go into a low power mode - but the latter is beyond
> > > > the scope of the input subsystem and is driver-specific.
> > > 
> > > I don't have much of an opinion on changing the names,
> > > to me open/close have always means start/stop receiving
> > > events. This follows the everything is a file philosophy,
> > > e.g. you can also not really "open" a serial port,
> > > yet opening /dev/ttyS0 will activate the receive IRQ
> > > of the UART, etc. So maybe we just need to make the
> > > docs clearer rather then do the rename?  Doing the
> > > rename is certainly going to cause a lot of churn.
> > 
> > Right, I can see now that the suggestion to change names is
> > too far fetched. (I feel that release() would be better
> > than close(), though). But it exposes the message I wanted to
> > pass.

release() usually means that the object is destroyedm, i.e this action,
unlike close() is irrevocable.

Let's leave the names as is, and adjust kerneldoc comments as needed.

> > 
> > > 
> > > Anyways as said, I don't have much of an opinion,
> > > so I'll leave commenting (more) on this to Dmitry.
> > > 
> > > > With such a naming change in mind let's consider inhibiting.
> > > > We want to be able to control when to disregard events from
> > > > a given device. It makes sense to do it at device level, otherwise
> > > > such an operation would have to be invoked in all associated
> > > > handlers (those that have an open handle associating them with
> > > > the device in question). But of course we can do better than
> > > > merely ignoring the events received: we can tell the drivers
> > > > that we don't want any events from them, and later, at uninhibit
> > > > time, tell them to start providing the events again. Conceptually,
> > > > the two operations (provide or don't provide envents) are exactly
> > > > the same thing we want to be happening at input_open_device() and
> > > > input_close_device() time. To me, changing the names of
> > > > ->open() and ->close() exposes this fact very well.
> > > > 
> > > > Consequently, ->inhibit() and ->uninhibit() won't be needed,
> > > > and drivers which already implement ->provide_events() (formerly
> > > > ->open()) and ->stop_events() (formerly ->close()) will receive
> > > > full inhibit/uninhibit support for free (subject to how well they
> > > > implement ->provide_events()/->stop_events()). Unless we can come
> > > > up with what the drivers might be doing on top of ->stop_events()
> > > > and ->provide_events() when inhibiting/uninhibiting, but it seems
> > > > to me we can't. Can we?
> > > 
> > > Right. I'm happy that you've come to see that both on open/close
> > > and on inhibit/uninhibit we want to "start receiving events" and
> > > "stop receiving events", so that we only need one set of callbacks.
> > > 
> > 
> > Yeah, that's my conclusion - at least on a conceptual level.
> > 
> > That said, what I can imagine is an existing driver (e.g. elan_i2c)
> > which does not implement neither open() nor close(), but does have
> > suspend() and resume(). Then it is maybe a bit easier to add inhibit()
> > and uninhibit() /they would be similar to suspend and resume/ instead
> > of open() and close(): If only open() and close() are possible, then
> > the probe function needs to be extended to "close" the device before it
> > gets registered, because from the moment it is registered it might be
> > opened right away.
> 
> The probe only needs to "close" it if for some reason it
> starts directly sending events in most cases the driver
> must actively do something to get it to send events.
> 
> So in most cases this should be pretty straight forward,
> as for having to do some init / power-on during probe
> and then power-off at the end of the probe. Yes sometimes
> something like that might be necessary.
> 
> Looking at your suggested elan_i2c changes I think they
> look fine. I have the feeling that with some refactoring
> they can be made a bit cleaner (I did not look a the
> changes in too much detail) but overall I think they
> look ok.
> 
> Note you may also want to look at using the runtime
> suspend framework for this, doing a pm_runtime_get_sync()
> in open() and then letting (runtime) suspend do the power
> off if you set a reasonable timeout for autosuspend after
> the last user is gone then that will also avoid an
> unnecessary suspend / resume cycle between probe()
> exiting and the first open() call and this avoids the
> need to do a poweroff() at the end of probe(), the
> runtime-pm framework will autosuspend the device after
> the timeout expires.

Yes, plugging into runtime PM would be nice, as as it currently stands
the driver will be broken with regard to trying access sysfs for
firmware update/calibration/etc if device happens to be inhibited.

The version of the driver in Chrome OS tree is similarly broken, but
because we control both kernel and the rest of the stack we know that we
do not poke at sysfs when device is inhibited. It will not be acceptable
for mainline (and that is one of reasons why elan_i2c does not have
open/close methods at the moment).

Thanks.

-- 
Dmitry

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

^ permalink raw reply

* [PATCH v9 01/18] media: platform: Improve subscribe event flow for bug fixing
From: Xia Jiang @ 2020-06-04  7:26 UTC (permalink / raw)
  To: Hans Verkuil, Mauro Carvalho Chehab, Rob Herring,
	Matthias Brugger, Rick Chang
  Cc: maoguang.meng, devicetree, mojahsu, srv_heupstream, linux-kernel,
	Tomasz Figa, senozhatsky, sj.huang, drinkcat, linux-mediatek,
	Xia Jiang, linux-media, linux-arm-kernel, Marek Szyprowski
In-Reply-To: <20200604072708.9468-1-xia.jiang@mediatek.com>

Let v4l2_ctrl_subscribe_event() do the job for other types except
V4L2_EVENT_SOURCE_CHANGE.

Reviewed-by: Tomasz Figa <tfiga@chromium.org>
Signed-off-by: Xia Jiang <xia.jiang@mediatek.com>
---
v9: no changes
---
 drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
index f82a81a3bdee..4ad4a4b30a0e 100644
--- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
+++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
@@ -446,9 +446,9 @@ static int mtk_jpeg_subscribe_event(struct v4l2_fh *fh,
 	switch (sub->type) {
 	case V4L2_EVENT_SOURCE_CHANGE:
 		return v4l2_src_change_event_subscribe(fh, sub);
-	default:
-		return -EINVAL;
 	}
+
+	return v4l2_ctrl_subscribe_event(fh, sub);
 }
 
 static int mtk_jpeg_g_selection(struct file *file, void *priv,
-- 
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 related

* [PATCH v9 08/18] media: platform: Cancel the last frame handling flow
From: Xia Jiang @ 2020-06-04  7:26 UTC (permalink / raw)
  To: Hans Verkuil, Mauro Carvalho Chehab, Rob Herring,
	Matthias Brugger, Rick Chang
  Cc: maoguang.meng, devicetree, mojahsu, srv_heupstream, linux-kernel,
	Tomasz Figa, senozhatsky, sj.huang, drinkcat, linux-mediatek,
	Xia Jiang, linux-media, linux-arm-kernel, Marek Szyprowski
In-Reply-To: <20200604072708.9468-1-xia.jiang@mediatek.com>

There is no need to queue an empty buffer for signaling a last frame,
because all frames are separate from each other in JPEG.

Signed-off-by: Xia Jiang <xia.jiang@mediatek.com>
---
v9: new patch
---
 .../media/platform/mtk-jpeg/mtk_jpeg_core.c   | 21 +------------------
 1 file changed, 1 insertion(+), 20 deletions(-)

diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
index 49bdbf1c435f..bb4ebce881ee 100644
--- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
+++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
@@ -55,15 +55,9 @@ static struct mtk_jpeg_fmt mtk_jpeg_formats[] = {
 
 #define MTK_JPEG_NUM_FORMATS ARRAY_SIZE(mtk_jpeg_formats)
 
-enum {
-	MTK_JPEG_BUF_FLAGS_INIT			= 0,
-	MTK_JPEG_BUF_FLAGS_LAST_FRAME		= 1,
-};
-
 struct mtk_jpeg_src_buf {
 	struct vb2_v4l2_buffer b;
 	struct list_head list;
-	int flags;
 	struct mtk_jpeg_dec_param dec_param;
 };
 
@@ -520,8 +514,6 @@ static int mtk_jpeg_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
 
 	vb = vb2_get_buffer(vq, buf->index);
 	jpeg_src_buf = mtk_jpeg_vb2_to_srcbuf(vb);
-	jpeg_src_buf->flags = (buf->m.planes[0].bytesused == 0) ?
-		MTK_JPEG_BUF_FLAGS_LAST_FRAME : MTK_JPEG_BUF_FLAGS_INIT;
 end:
 	return v4l2_m2m_qbuf(file, fh->m2m_ctx, buf);
 }
@@ -676,10 +668,6 @@ static void mtk_jpeg_buf_queue(struct vb2_buffer *vb)
 	param = &jpeg_src_buf->dec_param;
 	memset(param, 0, sizeof(*param));
 
-	if (jpeg_src_buf->flags & MTK_JPEG_BUF_FLAGS_LAST_FRAME) {
-		v4l2_dbg(1, debug, &jpeg->v4l2_dev, "Got eos\n");
-		goto end;
-	}
 	header_valid = mtk_jpeg_parse(param, (u8 *)vb2_plane_vaddr(vb, 0),
 				      vb2_get_plane_payload(vb, 0));
 	if (!header_valid) {
@@ -792,19 +780,12 @@ static void mtk_jpeg_device_run(void *priv)
 	struct mtk_jpeg_src_buf *jpeg_src_buf;
 	struct mtk_jpeg_bs bs;
 	struct mtk_jpeg_fb fb;
-	int i, ret;
+	int ret;
 
 	src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
 	dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
 	jpeg_src_buf = mtk_jpeg_vb2_to_srcbuf(&src_buf->vb2_buf);
 
-	if (jpeg_src_buf->flags & MTK_JPEG_BUF_FLAGS_LAST_FRAME) {
-		for (i = 0; i < dst_buf->vb2_buf.num_planes; i++)
-			vb2_set_plane_payload(&dst_buf->vb2_buf, i, 0);
-		buf_state = VB2_BUF_STATE_DONE;
-		goto dec_end;
-	}
-
 	if (mtk_jpeg_check_resolution_change(ctx, &jpeg_src_buf->dec_param)) {
 		mtk_jpeg_queue_src_chg_event(ctx);
 		ctx->state = MTK_JPEG_SOURCE_CHANGE;
-- 
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 related

* [PATCH v9 11/18] media: platform: Use generic rounding helpers
From: Xia Jiang @ 2020-06-04  7:27 UTC (permalink / raw)
  To: Hans Verkuil, Mauro Carvalho Chehab, Rob Herring,
	Matthias Brugger, Rick Chang
  Cc: maoguang.meng, devicetree, mojahsu, srv_heupstream, linux-kernel,
	Tomasz Figa, senozhatsky, sj.huang, drinkcat, linux-mediatek,
	Xia Jiang, linux-media, linux-arm-kernel, Marek Szyprowski
In-Reply-To: <20200604072708.9468-1-xia.jiang@mediatek.com>

Use clamp() to replace mtk_jpeg_bound_align_image() and round() to
replace mtk_jpeg_align().

Reviewed-by: Tomasz Figa <tfiga@chromium.org>
Signed-off-by: Xia Jiang <xia.jiang@mediatek.com>
---
v9: change the patch title description
---
 .../media/platform/mtk-jpeg/mtk_jpeg_core.c   | 41 +++++--------------
 drivers/media/platform/mtk-jpeg/mtk_jpeg_hw.c |  8 ++--
 drivers/media/platform/mtk-jpeg/mtk_jpeg_hw.h |  5 ---
 3 files changed, 15 insertions(+), 39 deletions(-)

diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
index bd1cc58324c6..c9c0357b2d6c 100644
--- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
+++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
@@ -151,25 +151,6 @@ static struct mtk_jpeg_fmt *mtk_jpeg_find_format(struct mtk_jpeg_ctx *ctx,
 	return NULL;
 }
 
-static void mtk_jpeg_bound_align_image(u32 *w, unsigned int wmin,
-				       unsigned int wmax, unsigned int walign,
-				       u32 *h, unsigned int hmin,
-				       unsigned int hmax, unsigned int halign)
-{
-	int width, height, w_step, h_step;
-
-	width = *w;
-	height = *h;
-	w_step = 1 << walign;
-	h_step = 1 << halign;
-
-	v4l_bound_align_image(w, wmin, wmax, walign, h, hmin, hmax, halign, 0);
-	if (*w < width && (*w + w_step) <= wmax)
-		*w += w_step;
-	if (*h < height && (*h + h_step) <= hmax)
-		*h += h_step;
-}
-
 static void mtk_jpeg_adjust_fmt_mplane(struct mtk_jpeg_ctx *ctx,
 				       struct v4l2_format *f)
 {
@@ -211,24 +192,24 @@ static int mtk_jpeg_try_fmt_mplane(struct v4l2_format *f,
 	if (q_type == MTK_JPEG_FMT_TYPE_OUTPUT) {
 		struct v4l2_plane_pix_format *pfmt = &pix_mp->plane_fmt[0];
 
-		mtk_jpeg_bound_align_image(&pix_mp->width, MTK_JPEG_MIN_WIDTH,
-					   MTK_JPEG_MAX_WIDTH, 0,
-					   &pix_mp->height, MTK_JPEG_MIN_HEIGHT,
-					   MTK_JPEG_MAX_HEIGHT, 0);
+		pix_mp->height = clamp(pix_mp->height, MTK_JPEG_MIN_HEIGHT,
+				       MTK_JPEG_MAX_HEIGHT);
+		pix_mp->width = clamp(pix_mp->width, MTK_JPEG_MIN_WIDTH,
+				      MTK_JPEG_MAX_WIDTH);
 
 		pfmt->bytesperline = 0;
 		/* Source size must be aligned to 128 */
-		pfmt->sizeimage = mtk_jpeg_align(pfmt->sizeimage, 128);
+		pfmt->sizeimage = round_up(pfmt->sizeimage, 128);
 		if (pfmt->sizeimage == 0)
 			pfmt->sizeimage = MTK_JPEG_DEFAULT_SIZEIMAGE;
 		goto end;
 	}
 
 	/* type is MTK_JPEG_FMT_TYPE_CAPTURE */
-	mtk_jpeg_bound_align_image(&pix_mp->width, MTK_JPEG_MIN_WIDTH,
-				   MTK_JPEG_MAX_WIDTH, fmt->h_align,
-				   &pix_mp->height, MTK_JPEG_MIN_HEIGHT,
-				   MTK_JPEG_MAX_HEIGHT, fmt->v_align);
+	pix_mp->height = clamp(round_up(pix_mp->height, fmt->v_align),
+			       MTK_JPEG_MIN_HEIGHT, MTK_JPEG_MAX_HEIGHT);
+	pix_mp->width = clamp(round_up(pix_mp->width, fmt->h_align),
+			      MTK_JPEG_MIN_WIDTH, MTK_JPEG_MAX_WIDTH);
 
 	for (i = 0; i < fmt->colplanes; i++) {
 		struct v4l2_plane_pix_format *pfmt = &pix_mp->plane_fmt[i];
@@ -734,8 +715,8 @@ static void mtk_jpeg_set_dec_src(struct mtk_jpeg_ctx *ctx,
 {
 	bs->str_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0);
 	bs->end_addr = bs->str_addr +
-			 mtk_jpeg_align(vb2_get_plane_payload(src_buf, 0), 16);
-	bs->size = mtk_jpeg_align(vb2_plane_size(src_buf, 0), 128);
+		       round_up(vb2_get_plane_payload(src_buf, 0), 16);
+	bs->size = round_up(vb2_plane_size(src_buf, 0), 128);
 }
 
 static int mtk_jpeg_set_dec_dst(struct mtk_jpeg_ctx *ctx,
diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_hw.c b/drivers/media/platform/mtk-jpeg/mtk_jpeg_hw.c
index ddf0dfa78e20..68abcfd7494d 100644
--- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_hw.c
+++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_hw.c
@@ -153,10 +153,10 @@ static int mtk_jpeg_calc_dst_size(struct mtk_jpeg_dec_param *param)
 				param->sampling_w[i];
 		/* output format is 420/422 */
 		param->comp_w[i] = padding_w >> brz_w[i];
-		param->comp_w[i] = mtk_jpeg_align(param->comp_w[i],
-						  MTK_JPEG_DCTSIZE);
-		param->img_stride[i] = i ? mtk_jpeg_align(param->comp_w[i], 16)
-					: mtk_jpeg_align(param->comp_w[i], 32);
+		param->comp_w[i] = round_up(param->comp_w[i],
+					    MTK_JPEG_DCTSIZE);
+		param->img_stride[i] = i ? round_up(param->comp_w[i], 16)
+					: round_up(param->comp_w[i], 32);
 		ds_row_h[i] = (MTK_JPEG_DCTSIZE * param->sampling_h[i]);
 	}
 	param->dec_w = param->img_stride[0];
diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_hw.h b/drivers/media/platform/mtk-jpeg/mtk_jpeg_hw.h
index 9c6584eaad99..7b0687f8f4b6 100644
--- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_hw.h
+++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_hw.h
@@ -54,11 +54,6 @@ struct mtk_jpeg_dec_param {
 	u8 uv_brz_w;
 };
 
-static inline u32 mtk_jpeg_align(u32 val, u32 align)
-{
-	return (val + align - 1) & ~(align - 1);
-}
-
 struct mtk_jpeg_bs {
 	dma_addr_t	str_addr;
 	dma_addr_t	end_addr;
-- 
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 related

* [PATCH v9 10/18] media: platform: Stylistic changes for improving code quality
From: Xia Jiang @ 2020-06-04  7:27 UTC (permalink / raw)
  To: Hans Verkuil, Mauro Carvalho Chehab, Rob Herring,
	Matthias Brugger, Rick Chang
  Cc: maoguang.meng, devicetree, mojahsu, srv_heupstream, linux-kernel,
	Tomasz Figa, senozhatsky, sj.huang, drinkcat, linux-mediatek,
	Xia Jiang, linux-media, linux-arm-kernel, Marek Szyprowski
In-Reply-To: <20200604072708.9468-1-xia.jiang@mediatek.com>

Change register offset hex numerals from uppercase to lowercase.
Change data type of max/min width/height from integer to unsigned
integer.

Signed-off-by: Xia Jiang <xia.jiang@mediatek.com>
---
v9: move changing data type of max/min width/height to this patch
---
 .../media/platform/mtk-jpeg/mtk_jpeg_core.h    |  8 ++++----
 drivers/media/platform/mtk-jpeg/mtk_jpeg_reg.h | 18 +++++++++---------
 2 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h
index 999bd1427809..28e9b30ad5c3 100644
--- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h
+++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h
@@ -21,10 +21,10 @@
 #define MTK_JPEG_FMT_TYPE_OUTPUT	1
 #define MTK_JPEG_FMT_TYPE_CAPTURE	2
 
-#define MTK_JPEG_MIN_WIDTH	32
-#define MTK_JPEG_MIN_HEIGHT	32
-#define MTK_JPEG_MAX_WIDTH	8192
-#define MTK_JPEG_MAX_HEIGHT	8192
+#define MTK_JPEG_MIN_WIDTH	32U
+#define MTK_JPEG_MIN_HEIGHT	32U
+#define MTK_JPEG_MAX_WIDTH	8192U
+#define MTK_JPEG_MAX_HEIGHT	8192U
 
 #define MTK_JPEG_DEFAULT_SIZEIMAGE	(1 * 1024 * 1024)
 
diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_reg.h b/drivers/media/platform/mtk-jpeg/mtk_jpeg_reg.h
index 94db04e9cdb6..2945da842dfa 100644
--- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_reg.h
+++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_reg.h
@@ -20,29 +20,29 @@
 #define BIT_INQST_MASK_ALLIRQ		0x37
 
 #define JPGDEC_REG_RESET		0x0090
-#define JPGDEC_REG_BRZ_FACTOR		0x00F8
-#define JPGDEC_REG_DU_NUM		0x00FC
+#define JPGDEC_REG_BRZ_FACTOR		0x00f8
+#define JPGDEC_REG_DU_NUM		0x00fc
 #define JPGDEC_REG_DEST_ADDR0_Y		0x0140
 #define JPGDEC_REG_DEST_ADDR0_U		0x0144
 #define JPGDEC_REG_DEST_ADDR0_V		0x0148
-#define JPGDEC_REG_DEST_ADDR1_Y		0x014C
+#define JPGDEC_REG_DEST_ADDR1_Y		0x014c
 #define JPGDEC_REG_DEST_ADDR1_U		0x0150
 #define JPGDEC_REG_DEST_ADDR1_V		0x0154
 #define JPGDEC_REG_STRIDE_Y		0x0158
-#define JPGDEC_REG_STRIDE_UV		0x015C
+#define JPGDEC_REG_STRIDE_UV		0x015c
 #define JPGDEC_REG_IMG_STRIDE_Y		0x0160
 #define JPGDEC_REG_IMG_STRIDE_UV	0x0164
-#define JPGDEC_REG_WDMA_CTRL		0x016C
+#define JPGDEC_REG_WDMA_CTRL		0x016c
 #define JPGDEC_REG_PAUSE_MCU_NUM	0x0170
-#define JPGDEC_REG_OPERATION_MODE	0x017C
+#define JPGDEC_REG_OPERATION_MODE	0x017c
 #define JPGDEC_REG_FILE_ADDR		0x0200
-#define JPGDEC_REG_COMP_ID		0x020C
+#define JPGDEC_REG_COMP_ID		0x020c
 #define JPGDEC_REG_TOTAL_MCU_NUM	0x0210
 #define JPGDEC_REG_COMP0_DATA_UNIT_NUM	0x0224
-#define JPGDEC_REG_DU_CTRL		0x023C
+#define JPGDEC_REG_DU_CTRL		0x023c
 #define JPGDEC_REG_TRIG			0x0240
 #define JPGDEC_REG_FILE_BRP		0x0248
-#define JPGDEC_REG_FILE_TOTAL_SIZE	0x024C
+#define JPGDEC_REG_FILE_TOTAL_SIZE	0x024c
 #define JPGDEC_REG_QT_ID		0x0270
 #define JPGDEC_REG_INTERRUPT_STATUS	0x0274
 #define JPGDEC_REG_STATUS		0x0278
-- 
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 related

* [PATCH v9 17/18] media: platform: Rename existing functions/defines/variables
From: Xia Jiang @ 2020-06-04  7:27 UTC (permalink / raw)
  To: Hans Verkuil, Mauro Carvalho Chehab, Rob Herring,
	Matthias Brugger, Rick Chang
  Cc: maoguang.meng, devicetree, mojahsu, srv_heupstream, linux-kernel,
	Tomasz Figa, senozhatsky, sj.huang, drinkcat, linux-mediatek,
	Xia Jiang, linux-media, linux-arm-kernel, Marek Szyprowski
In-Reply-To: <20200604072708.9468-1-xia.jiang@mediatek.com>

Rename existing funcitons/defines/variables with a  _dec prefix and
without dec_ prefix to prepare for the addition of the jpeg encoder
feature.

Signed-off-by: Xia Jiang <xia.jiang@mediatek.com>
---
v9: new patch
---
 .../media/platform/mtk-jpeg/mtk_jpeg_core.c   | 196 +++++++++---------
 .../media/platform/mtk-jpeg/mtk_jpeg_core.h   |   8 +-
 .../media/platform/mtk-jpeg/mtk_jpeg_dec_hw.h |   7 +-
 3 files changed, 107 insertions(+), 104 deletions(-)

diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
index e0e522a502e1..8d5a78c775a6 100644
--- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
+++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
@@ -27,7 +27,7 @@
 #include "mtk_jpeg_core.h"
 #include "mtk_jpeg_dec_parse.h"
 
-static struct mtk_jpeg_fmt mtk_jpeg_formats[] = {
+static struct mtk_jpeg_fmt mtk_jpeg_dec_formats[] = {
 	{
 		.fourcc		= V4L2_PIX_FMT_JPEG,
 		.colplanes	= 1,
@@ -53,7 +53,7 @@ static struct mtk_jpeg_fmt mtk_jpeg_formats[] = {
 	},
 };
 
-#define MTK_JPEG_NUM_FORMATS ARRAY_SIZE(mtk_jpeg_formats)
+#define MTK_JPEG_DEC_NUM_FORMATS ARRAY_SIZE(mtk_jpeg_dec_formats)
 
 struct mtk_jpeg_src_buf {
 	struct vb2_v4l2_buffer b;
@@ -75,12 +75,12 @@ static inline struct mtk_jpeg_src_buf *mtk_jpeg_vb2_to_srcbuf(
 	return container_of(to_vb2_v4l2_buffer(vb), struct mtk_jpeg_src_buf, b);
 }
 
-static int mtk_jpeg_querycap(struct file *file, void *priv,
+static int mtk_jpeg_dec_querycap(struct file *file, void *priv,
 			     struct v4l2_capability *cap)
 {
 	struct mtk_jpeg_dev *jpeg = video_drvdata(file);
 
-	strscpy(cap->driver, MTK_JPEG_NAME " decoder", sizeof(cap->driver));
+	strscpy(cap->driver, MTK_JPEG_NAME, sizeof(cap->driver));
 	strscpy(cap->card, MTK_JPEG_NAME " decoder", sizeof(cap->card));
 	snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
 		 dev_name(jpeg->dev));
@@ -109,22 +109,23 @@ static int mtk_jpeg_enum_fmt(struct mtk_jpeg_fmt *mtk_jpeg_formats, int n,
 	return 0;
 }
 
-static int mtk_jpeg_enum_fmt_vid_cap(struct file *file, void *priv,
-				     struct v4l2_fmtdesc *f)
+static int mtk_jpeg_dec_enum_fmt_vid_cap(struct file *file, void *priv,
+					 struct v4l2_fmtdesc *f)
 {
-	return mtk_jpeg_enum_fmt(mtk_jpeg_formats, MTK_JPEG_NUM_FORMATS, f,
+	return mtk_jpeg_enum_fmt(mtk_jpeg_dec_formats,
+				 MTK_JPEG_DEC_NUM_FORMATS, f,
 				 MTK_JPEG_FMT_FLAG_DEC_CAPTURE);
 }
 
-static int mtk_jpeg_enum_fmt_vid_out(struct file *file, void *priv,
-				     struct v4l2_fmtdesc *f)
+static int mtk_jpeg_dec_enum_fmt_vid_out(struct file *file, void *priv,
+					 struct v4l2_fmtdesc *f)
 {
-	return mtk_jpeg_enum_fmt(mtk_jpeg_formats, MTK_JPEG_NUM_FORMATS, f,
-				 MTK_JPEG_FMT_FLAG_DEC_OUTPUT);
+	return mtk_jpeg_enum_fmt(mtk_jpeg_dec_formats, MTK_JPEG_DEC_NUM_FORMATS,
+				 f, MTK_JPEG_FMT_FLAG_DEC_OUTPUT);
 }
 
-static struct mtk_jpeg_q_data *mtk_jpeg_get_q_data(struct mtk_jpeg_ctx *ctx,
-						   enum v4l2_buf_type type)
+static struct mtk_jpeg_q_data *
+mtk_jpeg_get_q_data(struct mtk_jpeg_ctx *ctx, enum v4l2_buf_type type)
 {
 	if (V4L2_TYPE_IS_OUTPUT(type))
 		return &ctx->out_q;
@@ -141,8 +142,8 @@ static struct mtk_jpeg_fmt *mtk_jpeg_find_format(struct mtk_jpeg_ctx *ctx,
 		   MTK_JPEG_FMT_FLAG_DEC_OUTPUT :
 		   MTK_JPEG_FMT_FLAG_DEC_CAPTURE;
 
-	for (k = 0; k < MTK_JPEG_NUM_FORMATS; k++) {
-		struct mtk_jpeg_fmt *fmt = &mtk_jpeg_formats[k];
+	for (k = 0; k < MTK_JPEG_DEC_NUM_FORMATS; k++) {
+		struct mtk_jpeg_fmt *fmt = &mtk_jpeg_dec_formats[k];
 
 		if (fmt->fourcc == pixelformat && fmt->flags & fmt_flag)
 			return fmt;
@@ -270,8 +271,8 @@ static int mtk_jpeg_g_fmt_vid_mplane(struct file *file, void *priv,
 	return 0;
 }
 
-static int mtk_jpeg_try_fmt_vid_cap_mplane(struct file *file, void *priv,
-					   struct v4l2_format *f)
+static int mtk_jpeg_dec_try_fmt_vid_cap_mplane(struct file *file, void *priv,
+					       struct v4l2_format *f)
 {
 	struct mtk_jpeg_ctx *ctx = mtk_jpeg_fh_to_ctx(priv);
 	struct mtk_jpeg_fmt *fmt;
@@ -291,8 +292,8 @@ static int mtk_jpeg_try_fmt_vid_cap_mplane(struct file *file, void *priv,
 	return mtk_jpeg_try_fmt_mplane(f, fmt, ctx, MTK_JPEG_FMT_TYPE_CAPTURE);
 }
 
-static int mtk_jpeg_try_fmt_vid_out_mplane(struct file *file, void *priv,
-					   struct v4l2_format *f)
+static int mtk_jpeg_dec_try_fmt_vid_out_mplane(struct file *file, void *priv,
+					       struct v4l2_format *f)
 {
 	struct mtk_jpeg_ctx *ctx = mtk_jpeg_fh_to_ctx(priv);
 	struct mtk_jpeg_fmt *fmt;
@@ -364,24 +365,24 @@ static int mtk_jpeg_s_fmt_mplane(struct mtk_jpeg_ctx *ctx,
 	return 0;
 }
 
-static int mtk_jpeg_s_fmt_vid_out_mplane(struct file *file, void *priv,
-					 struct v4l2_format *f)
+static int mtk_jpeg_dec_s_fmt_vid_out_mplane(struct file *file, void *priv,
+					     struct v4l2_format *f)
 {
 	int ret;
 
-	ret = mtk_jpeg_try_fmt_vid_out_mplane(file, priv, f);
+	ret = mtk_jpeg_dec_try_fmt_vid_out_mplane(file, priv, f);
 	if (ret)
 		return ret;
 
 	return mtk_jpeg_s_fmt_mplane(mtk_jpeg_fh_to_ctx(priv), f);
 }
 
-static int mtk_jpeg_s_fmt_vid_cap_mplane(struct file *file, void *priv,
-					 struct v4l2_format *f)
+static int mtk_jpeg_dec_s_fmt_vid_cap_mplane(struct file *file, void *priv,
+					     struct v4l2_format *f)
 {
 	int ret;
 
-	ret = mtk_jpeg_try_fmt_vid_cap_mplane(file, priv, f);
+	ret = mtk_jpeg_dec_try_fmt_vid_cap_mplane(file, priv, f);
 	if (ret)
 		return ret;
 
@@ -410,8 +411,8 @@ static int mtk_jpeg_subscribe_event(struct v4l2_fh *fh,
 	return v4l2_ctrl_subscribe_event(fh, sub);
 }
 
-static int mtk_jpeg_g_selection(struct file *file, void *priv,
-				struct v4l2_selection *s)
+static int mtk_jpeg_dec_g_selection(struct file *file, void *priv,
+				    struct v4l2_selection *s)
 {
 	struct mtk_jpeg_ctx *ctx = mtk_jpeg_fh_to_ctx(priv);
 
@@ -439,8 +440,8 @@ static int mtk_jpeg_g_selection(struct file *file, void *priv,
 	return 0;
 }
 
-static int mtk_jpeg_s_selection(struct file *file, void *priv,
-				struct v4l2_selection *s)
+static int mtk_jpeg_dec_s_selection(struct file *file, void *priv,
+				    struct v4l2_selection *s)
 {
 	struct mtk_jpeg_ctx *ctx = mtk_jpeg_fh_to_ctx(priv);
 
@@ -483,20 +484,20 @@ static int mtk_jpeg_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
 	return v4l2_m2m_qbuf(file, fh->m2m_ctx, buf);
 }
 
-static const struct v4l2_ioctl_ops mtk_jpeg_ioctl_ops = {
-	.vidioc_querycap                = mtk_jpeg_querycap,
-	.vidioc_enum_fmt_vid_cap	= mtk_jpeg_enum_fmt_vid_cap,
-	.vidioc_enum_fmt_vid_out	= mtk_jpeg_enum_fmt_vid_out,
-	.vidioc_try_fmt_vid_cap_mplane	= mtk_jpeg_try_fmt_vid_cap_mplane,
-	.vidioc_try_fmt_vid_out_mplane	= mtk_jpeg_try_fmt_vid_out_mplane,
+static const struct v4l2_ioctl_ops mtk_jpeg_dec_ioctl_ops = {
+	.vidioc_querycap                = mtk_jpeg_dec_querycap,
+	.vidioc_enum_fmt_vid_cap	= mtk_jpeg_dec_enum_fmt_vid_cap,
+	.vidioc_enum_fmt_vid_out	= mtk_jpeg_dec_enum_fmt_vid_out,
+	.vidioc_try_fmt_vid_cap_mplane	= mtk_jpeg_dec_try_fmt_vid_cap_mplane,
+	.vidioc_try_fmt_vid_out_mplane	= mtk_jpeg_dec_try_fmt_vid_out_mplane,
 	.vidioc_g_fmt_vid_cap_mplane    = mtk_jpeg_g_fmt_vid_mplane,
 	.vidioc_g_fmt_vid_out_mplane    = mtk_jpeg_g_fmt_vid_mplane,
-	.vidioc_s_fmt_vid_cap_mplane    = mtk_jpeg_s_fmt_vid_cap_mplane,
-	.vidioc_s_fmt_vid_out_mplane    = mtk_jpeg_s_fmt_vid_out_mplane,
+	.vidioc_s_fmt_vid_cap_mplane    = mtk_jpeg_dec_s_fmt_vid_cap_mplane,
+	.vidioc_s_fmt_vid_out_mplane    = mtk_jpeg_dec_s_fmt_vid_out_mplane,
 	.vidioc_qbuf                    = mtk_jpeg_qbuf,
 	.vidioc_subscribe_event         = mtk_jpeg_subscribe_event,
-	.vidioc_g_selection		= mtk_jpeg_g_selection,
-	.vidioc_s_selection		= mtk_jpeg_s_selection,
+	.vidioc_g_selection		= mtk_jpeg_dec_g_selection,
+	.vidioc_s_selection		= mtk_jpeg_dec_s_selection,
 
 	.vidioc_create_bufs		= v4l2_m2m_ioctl_create_bufs,
 	.vidioc_prepare_buf		= v4l2_m2m_ioctl_prepare_buf,
@@ -615,7 +616,7 @@ static void mtk_jpeg_set_queue_data(struct mtk_jpeg_ctx *ctx,
 		 param->dec_w, param->dec_h);
 }
 
-static void mtk_jpeg_buf_queue(struct vb2_buffer *vb)
+static void mtk_jpeg_dec_buf_queue(struct vb2_buffer *vb)
 {
 	struct mtk_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
 	struct mtk_jpeg_dec_param *param;
@@ -663,7 +664,7 @@ static struct vb2_v4l2_buffer *mtk_jpeg_buf_remove(struct mtk_jpeg_ctx *ctx,
 		return v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
 }
 
-static void mtk_jpeg_stop_streaming(struct vb2_queue *q)
+static void mtk_jpeg_dec_stop_streaming(struct vb2_queue *q)
 {
 	struct mtk_jpeg_ctx *ctx = vb2_get_drv_priv(q);
 	struct vb2_v4l2_buffer *vb;
@@ -689,13 +690,13 @@ static void mtk_jpeg_stop_streaming(struct vb2_queue *q)
 		v4l2_m2m_buf_done(vb, VB2_BUF_STATE_ERROR);
 }
 
-static const struct vb2_ops mtk_jpeg_qops = {
+static const struct vb2_ops mtk_jpeg_dec_qops = {
 	.queue_setup        = mtk_jpeg_queue_setup,
 	.buf_prepare        = mtk_jpeg_buf_prepare,
-	.buf_queue          = mtk_jpeg_buf_queue,
+	.buf_queue          = mtk_jpeg_dec_buf_queue,
 	.wait_prepare       = vb2_ops_wait_prepare,
 	.wait_finish        = vb2_ops_wait_finish,
-	.stop_streaming     = mtk_jpeg_stop_streaming,
+	.stop_streaming     = mtk_jpeg_dec_stop_streaming,
 };
 
 static void mtk_jpeg_set_dec_src(struct mtk_jpeg_ctx *ctx,
@@ -735,7 +736,7 @@ static int mtk_jpeg_set_dec_dst(struct mtk_jpeg_ctx *ctx,
 	return 0;
 }
 
-static void mtk_jpeg_device_run(void *priv)
+static void mtk_jpeg_dec_device_run(void *priv)
 {
 	struct mtk_jpeg_ctx *ctx = priv;
 	struct mtk_jpeg_dev *jpeg = ctx->jpeg;
@@ -763,15 +764,16 @@ static void mtk_jpeg_device_run(void *priv)
 		goto dec_end;
 
 	mtk_jpeg_set_dec_src(ctx, &src_buf->vb2_buf, &bs);
-	if (mtk_jpeg_set_dec_dst(ctx, &jpeg_src_buf->dec_param, &dst_buf->vb2_buf, &fb))
+	if (mtk_jpeg_set_dec_dst(ctx, &jpeg_src_buf->dec_param,
+				 &dst_buf->vb2_buf, &fb))
 		goto dec_end;
 
 	spin_lock_irqsave(&jpeg->hw_lock, flags);
-	mtk_jpeg_dec_reset(jpeg->dec_reg_base);
-	mtk_jpeg_dec_set_config(jpeg->dec_reg_base,
+	mtk_jpeg_dec_reset(jpeg->reg_base);
+	mtk_jpeg_dec_set_config(jpeg->reg_base,
 				&jpeg_src_buf->dec_param, &bs, &fb);
 
-	mtk_jpeg_dec_start(jpeg->dec_reg_base);
+	mtk_jpeg_dec_start(jpeg->reg_base);
 	spin_unlock_irqrestore(&jpeg->hw_lock, flags);
 	return;
 
@@ -783,19 +785,19 @@ static void mtk_jpeg_device_run(void *priv)
 	v4l2_m2m_job_finish(jpeg->m2m_dev, ctx->fh.m2m_ctx);
 }
 
-static int mtk_jpeg_job_ready(void *priv)
+static int mtk_jpeg_dec_job_ready(void *priv)
 {
 	struct mtk_jpeg_ctx *ctx = priv;
 
 	return (ctx->state == MTK_JPEG_RUNNING) ? 1 : 0;
 }
 
-static const struct v4l2_m2m_ops mtk_jpeg_m2m_ops = {
-	.device_run = mtk_jpeg_device_run,
-	.job_ready  = mtk_jpeg_job_ready,
+static const struct v4l2_m2m_ops mtk_jpeg_dec_m2m_ops = {
+	.device_run = mtk_jpeg_dec_device_run,
+	.job_ready  = mtk_jpeg_dec_job_ready,
 };
 
-static int mtk_jpeg_queue_init(void *priv, struct vb2_queue *src_vq,
+static int mtk_jpeg_dec_queue_init(void *priv, struct vb2_queue *src_vq,
 			       struct vb2_queue *dst_vq)
 {
 	struct mtk_jpeg_ctx *ctx = priv;
@@ -805,7 +807,7 @@ static int mtk_jpeg_queue_init(void *priv, struct vb2_queue *src_vq,
 	src_vq->io_modes = VB2_DMABUF | VB2_MMAP;
 	src_vq->drv_priv = ctx;
 	src_vq->buf_struct_size = sizeof(struct mtk_jpeg_src_buf);
-	src_vq->ops = &mtk_jpeg_qops;
+	src_vq->ops = &mtk_jpeg_dec_qops;
 	src_vq->mem_ops = &vb2_dma_contig_memops;
 	src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
 	src_vq->lock = &ctx->jpeg->lock;
@@ -818,7 +820,7 @@ static int mtk_jpeg_queue_init(void *priv, struct vb2_queue *src_vq,
 	dst_vq->io_modes = VB2_DMABUF | VB2_MMAP;
 	dst_vq->drv_priv = ctx;
 	dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
-	dst_vq->ops = &mtk_jpeg_qops;
+	dst_vq->ops = &mtk_jpeg_dec_qops;
 	dst_vq->mem_ops = &vb2_dma_contig_memops;
 	dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
 	dst_vq->lock = &ctx->jpeg->lock;
@@ -857,7 +859,7 @@ static irqreturn_t mtk_jpeg_dec_irq(int irq, void *priv)
 	u32 dec_ret;
 	int i;
 
-	dec_ret = mtk_jpeg_dec_get_int_status(jpeg->dec_reg_base);
+	dec_ret = mtk_jpeg_dec_get_int_status(jpeg->reg_base);
 	dec_irq_ret = mtk_jpeg_dec_enum_result(dec_ret);
 	ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
 	if (!ctx) {
@@ -870,7 +872,7 @@ static irqreturn_t mtk_jpeg_dec_irq(int irq, void *priv)
 	jpeg_src_buf = mtk_jpeg_vb2_to_srcbuf(&src_buf->vb2_buf);
 
 	if (dec_irq_ret >= MTK_JPEG_DEC_RESULT_UNDERFLOW)
-		mtk_jpeg_dec_reset(jpeg->dec_reg_base);
+		mtk_jpeg_dec_reset(jpeg->reg_base);
 
 	if (dec_irq_ret != MTK_JPEG_DEC_RESULT_EOF_DONE) {
 		dev_err(jpeg->dev, "decode failed\n");
@@ -891,7 +893,7 @@ static irqreturn_t mtk_jpeg_dec_irq(int irq, void *priv)
 	return IRQ_HANDLED;
 }
 
-static void mtk_jpeg_set_default_params(struct mtk_jpeg_ctx *ctx)
+static void mtk_jpeg_set_dec_default_params(struct mtk_jpeg_ctx *ctx)
 {
 	struct mtk_jpeg_q_data *q = &ctx->out_q;
 	int i;
@@ -923,7 +925,7 @@ static void mtk_jpeg_set_default_params(struct mtk_jpeg_ctx *ctx)
 	}
 }
 
-static int mtk_jpeg_open(struct file *file)
+static int mtk_jpeg_dec_open(struct file *file)
 {
 	struct mtk_jpeg_dev *jpeg = video_drvdata(file);
 	struct video_device *vfd = video_devdata(file);
@@ -945,13 +947,13 @@ static int mtk_jpeg_open(struct file *file)
 
 	ctx->jpeg = jpeg;
 	ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(jpeg->m2m_dev, ctx,
-					    mtk_jpeg_queue_init);
+					    mtk_jpeg_dec_queue_init);
 	if (IS_ERR(ctx->fh.m2m_ctx)) {
 		ret = PTR_ERR(ctx->fh.m2m_ctx);
 		goto error;
 	}
 
-	mtk_jpeg_set_default_params(ctx);
+	mtk_jpeg_set_dec_default_params(ctx);
 	mutex_unlock(&jpeg->lock);
 	return 0;
 
@@ -978,9 +980,9 @@ static int mtk_jpeg_release(struct file *file)
 	return 0;
 }
 
-static const struct v4l2_file_operations mtk_jpeg_fops = {
+static const struct v4l2_file_operations mtk_jpeg_dec_fops = {
 	.owner          = THIS_MODULE,
-	.open           = mtk_jpeg_open,
+	.open           = mtk_jpeg_dec_open,
 	.release        = mtk_jpeg_release,
 	.poll           = v4l2_m2m_fop_poll,
 	.unlocked_ioctl = video_ioctl2,
@@ -1016,7 +1018,7 @@ static int mtk_jpeg_probe(struct platform_device *pdev)
 {
 	struct mtk_jpeg_dev *jpeg;
 	struct resource *res;
-	int dec_irq;
+	int jpeg_irq;
 	int ret;
 
 	jpeg = devm_kzalloc(&pdev->dev, sizeof(*jpeg), GFP_KERNEL);
@@ -1028,23 +1030,23 @@ static int mtk_jpeg_probe(struct platform_device *pdev)
 	jpeg->dev = &pdev->dev;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	jpeg->dec_reg_base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(jpeg->dec_reg_base)) {
-		ret = PTR_ERR(jpeg->dec_reg_base);
+	jpeg->reg_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(jpeg->reg_base)) {
+		ret = PTR_ERR(jpeg->reg_base);
 		return ret;
 	}
 
-	dec_irq = platform_get_irq(pdev, 0);
-	if (dec_irq < 0) {
-		dev_err(&pdev->dev, "Failed to get dec_irq %d.\n", dec_irq);
-		return dec_irq;
+	jpeg_irq = platform_get_irq(pdev, 0);
+	if (jpeg_irq < 0) {
+		dev_err(&pdev->dev, "Failed to get jpeg_irq %d.\n", jpeg_irq);
+		return jpeg_irq;
 	}
 
-	ret = devm_request_irq(&pdev->dev, dec_irq, mtk_jpeg_dec_irq, 0,
+	ret = devm_request_irq(&pdev->dev, jpeg_irq, mtk_jpeg_dec_irq, 0,
 			       pdev->name, jpeg);
 	if (ret) {
-		dev_err(&pdev->dev, "Failed to request dec_irq %d (%d)\n",
-			dec_irq, ret);
+		dev_err(&pdev->dev, "Failed to request jpeg_irq %d (%d)\n",
+			jpeg_irq, ret);
 		goto err_req_irq;
 	}
 
@@ -1061,40 +1063,40 @@ static int mtk_jpeg_probe(struct platform_device *pdev)
 		goto err_dev_register;
 	}
 
-	jpeg->m2m_dev = v4l2_m2m_init(&mtk_jpeg_m2m_ops);
+	jpeg->m2m_dev = v4l2_m2m_init(&mtk_jpeg_dec_m2m_ops);
 	if (IS_ERR(jpeg->m2m_dev)) {
 		v4l2_err(&jpeg->v4l2_dev, "Failed to init mem2mem device\n");
 		ret = PTR_ERR(jpeg->m2m_dev);
 		goto err_m2m_init;
 	}
 
-	jpeg->dec_vdev = video_device_alloc();
-	if (!jpeg->dec_vdev) {
+	jpeg->vdev = video_device_alloc();
+	if (!jpeg->vdev) {
 		ret = -ENOMEM;
-		goto err_dec_vdev_alloc;
+		goto err_vfd_jpeg_alloc;
 	}
-	snprintf(jpeg->dec_vdev->name, sizeof(jpeg->dec_vdev->name),
+	snprintf(jpeg->vdev->name, sizeof(jpeg->vdev->name),
 		 "%s-dec", MTK_JPEG_NAME);
-	jpeg->dec_vdev->fops = &mtk_jpeg_fops;
-	jpeg->dec_vdev->ioctl_ops = &mtk_jpeg_ioctl_ops;
-	jpeg->dec_vdev->minor = -1;
-	jpeg->dec_vdev->release = video_device_release;
-	jpeg->dec_vdev->lock = &jpeg->lock;
-	jpeg->dec_vdev->v4l2_dev = &jpeg->v4l2_dev;
-	jpeg->dec_vdev->vfl_dir = VFL_DIR_M2M;
-	jpeg->dec_vdev->device_caps = V4L2_CAP_STREAMING |
+	jpeg->vdev->fops = &mtk_jpeg_dec_fops;
+	jpeg->vdev->ioctl_ops = &mtk_jpeg_dec_ioctl_ops;
+	jpeg->vdev->minor = -1;
+	jpeg->vdev->release = video_device_release;
+	jpeg->vdev->lock = &jpeg->lock;
+	jpeg->vdev->v4l2_dev = &jpeg->v4l2_dev;
+	jpeg->vdev->vfl_dir = VFL_DIR_M2M;
+	jpeg->vdev->device_caps = V4L2_CAP_STREAMING |
 				      V4L2_CAP_VIDEO_M2M_MPLANE;
 
-	ret = video_register_device(jpeg->dec_vdev, VFL_TYPE_VIDEO, -1);
+	ret = video_register_device(jpeg->vdev, VFL_TYPE_VIDEO, -1);
 	if (ret) {
 		v4l2_err(&jpeg->v4l2_dev, "Failed to register video device\n");
-		goto err_dec_vdev_register;
+		goto err_vfd_jpeg_register;
 	}
 
-	video_set_drvdata(jpeg->dec_vdev, jpeg);
+	video_set_drvdata(jpeg->vdev, jpeg);
 	v4l2_info(&jpeg->v4l2_dev,
 		  "decoder device registered as /dev/video%d (%d,%d)\n",
-		  jpeg->dec_vdev->num, VIDEO_MAJOR, jpeg->dec_vdev->minor);
+		  jpeg->vdev->num, VIDEO_MAJOR, jpeg->vdev->minor);
 
 	platform_set_drvdata(pdev, jpeg);
 
@@ -1102,10 +1104,10 @@ static int mtk_jpeg_probe(struct platform_device *pdev)
 
 	return 0;
 
-err_dec_vdev_register:
-	video_device_release(jpeg->dec_vdev);
+err_vfd_jpeg_register:
+	video_device_release(jpeg->vdev);
 
-err_dec_vdev_alloc:
+err_vfd_jpeg_alloc:
 	v4l2_m2m_release(jpeg->m2m_dev);
 
 err_m2m_init:
@@ -1125,8 +1127,8 @@ static int mtk_jpeg_remove(struct platform_device *pdev)
 	struct mtk_jpeg_dev *jpeg = platform_get_drvdata(pdev);
 
 	pm_runtime_disable(&pdev->dev);
-	video_unregister_device(jpeg->dec_vdev);
-	video_device_release(jpeg->dec_vdev);
+	video_unregister_device(jpeg->vdev);
+	video_device_release(jpeg->vdev);
 	v4l2_m2m_release(jpeg->m2m_dev);
 	v4l2_device_unregister(&jpeg->v4l2_dev);
 
diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h
index 5fcdf6950782..0b59e48495d5 100644
--- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h
+++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.h
@@ -51,8 +51,8 @@ enum mtk_jpeg_ctx_state {
  * @v4l2_dev:		v4l2 device for mem2mem mode
  * @m2m_dev:		v4l2 mem2mem device data
  * @alloc_ctx:		videobuf2 memory allocator's context
- * @dec_vdev:		video device node for decoder mem2mem mode
- * @dec_reg_base:	JPEG registers mapping
+ * @vdev:		video device node for jpeg mem2mem mode
+ * @reg_base:		JPEG registers mapping
  * @clk_jdec:		JPEG hw working clock
  * @clk_jdec_smi:	JPEG SMI bus clock
  * @larb:		SMI device
@@ -65,8 +65,8 @@ struct mtk_jpeg_dev {
 	struct v4l2_device	v4l2_dev;
 	struct v4l2_m2m_dev	*m2m_dev;
 	void			*alloc_ctx;
-	struct video_device	*dec_vdev;
-	void __iomem		*dec_reg_base;
+	struct video_device	*vdev;
+	void __iomem		*reg_base;
 	struct clk		*clk_jdec;
 	struct clk		*clk_jdec_smi;
 	struct device		*larb;
diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_dec_hw.h b/drivers/media/platform/mtk-jpeg/mtk_jpeg_dec_hw.h
index 1cc37dbfc8e7..ce263db5f30a 100644
--- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_dec_hw.h
+++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_dec_hw.h
@@ -3,10 +3,11 @@
  * Copyright (c) 2016 MediaTek Inc.
  * Author: Ming Hsiu Tsai <minghsiu.tsai@mediatek.com>
  *         Rick Chang <rick.chang@mediatek.com>
+ *         Xia Jiang <xia.jiang@mediatek.com>
  */
 
-#ifndef _MTK_JPEG_HW_H
-#define _MTK_JPEG_HW_H
+#ifndef _MTK_JPEG_DEC_HW_H
+#define _MTK_JPEG_DEC_HW_H
 
 #include <media/videobuf2-core.h>
 
@@ -75,4 +76,4 @@ void mtk_jpeg_dec_set_config(void __iomem *base,
 void mtk_jpeg_dec_reset(void __iomem *dec_reg_base);
 void mtk_jpeg_dec_start(void __iomem *dec_reg_base);
 
-#endif /* _MTK_JPEG_HW_H */
+#endif /* _MTK_JPEG_DEC_HW_H */
-- 
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 related


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