Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/8] binding-doc: power: pwrseq-generic: add binding doc for generic power sequence library
From: Peter Chen @ 2017-01-03  6:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1483425211-14473-1-git-send-email-peter.chen@nxp.com>

Add binding doc for generic power sequence library.

Signed-off-by: Peter Chen <peter.chen@nxp.com>
Acked-by: Philipp Zabel <p.zabel@pengutronix.de>
Acked-by: Rob Herring <robh@kernel.org>
---
 .../bindings/power/pwrseq/pwrseq-generic.txt       | 48 ++++++++++++++++++++++
 1 file changed, 48 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/power/pwrseq/pwrseq-generic.txt

diff --git a/Documentation/devicetree/bindings/power/pwrseq/pwrseq-generic.txt b/Documentation/devicetree/bindings/power/pwrseq/pwrseq-generic.txt
new file mode 100644
index 0000000..ebf0d47
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/pwrseq/pwrseq-generic.txt
@@ -0,0 +1,48 @@
+The generic power sequence library
+
+Some hard-wired devices (eg USB/MMC) need to do power sequence before
+the device can be enumerated on the bus, the typical power sequence
+like: enable USB PHY clock, toggle reset pin, etc. But current
+Linux device driver lacks of such code to do it, it may cause some
+hard-wired devices works abnormal or can't be recognized by
+controller at all. The power sequence will be done before this device
+can be found at the bus.
+
+The power sequence properties is under the device node.
+
+Optional properties:
+- clocks: the input clocks for device.
+- reset-gpios: Should specify the GPIO for reset.
+- reset-duration-us: the duration in microsecond for assert reset signal.
+
+Below is the example of USB power sequence properties on USB device
+nodes which have two level USB hubs.
+
+&usbotg1 {
+	vbus-supply = <&reg_usb_otg1_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usb_otg1_id>;
+	status = "okay";
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+	genesys: hub at 1 {
+		compatible = "usb5e3,608";
+		reg = <1>;
+
+		clocks = <&clks IMX6SX_CLK_CKO>;
+		reset-gpios = <&gpio4 5 GPIO_ACTIVE_LOW>; /* hub reset pin */
+		reset-duration-us = <10>;
+
+		#address-cells = <1>;
+		#size-cells = <0>;
+		asix: ethernet at 1 {
+			compatible = "usbb95,1708";
+			reg = <1>;
+
+			clocks = <&clks IMX6SX_CLK_IPG>;
+			reset-gpios = <&gpio4 6 GPIO_ACTIVE_LOW>; /* ethernet_rst */
+			reset-duration-us = <15>;
+		};
+	};
+};
-- 
2.7.4

^ permalink raw reply related

* [PATCH 0/8] power: add power sequence library
From: Peter Chen @ 2017-01-03  6:33 UTC (permalink / raw)
  To: linux-arm-kernel

Hi all,

This is a follow-up for my last power sequence framework patch set [1].
According to Rob Herring and Ulf Hansson's comments[2]. The kinds of
power sequence instances will be added at postcore_initcall, the match
criteria is compatible string first, if the compatible string is not
matched between dts and library, it will try to use generic power sequence.
	 
The host driver just needs to call of_pwrseq_on/of_pwrseq_off
if only one power sequence instance is needed, for more power sequences
are used, using of_pwrseq_on_list/of_pwrseq_off_list instead (eg, USB hub driver).

In future, if there are special power sequence requirements, the special
power sequence library can be created.

This patch set is tested on i.mx6 sabresx evk using a dts change, I use
two hot-plug devices to simulate this use case, the related binding
change is updated at patch [1/6], The udoo board changes were tested
using my last power sequence patch set.[3]

Except for hard-wired MMC and USB devices, I find the USB ULPI PHY also
need to power on itself before it can be found by ULPI bus.

[1] http://www.spinics.net/lists/linux-usb/msg142755.html
[2] http://www.spinics.net/lists/linux-usb/msg143106.html
[3] http://www.spinics.net/lists/linux-usb/msg142815.html

Changes for v11:
- Fix warning: (USB) selects POWER_SEQUENCE which has unmet direct dependencies (OF)
- Delete redundant copyright statement.
- Change pr_warn to pr_debug at wrseq_find_available_instance
- Refine kerneldoc
- %s/ENONET/ENOENT 
- Allocate pwrseq list node before than carry out power sequence on 
- Add mutex_lock/mutex_lock for pwrseq node browse at pwrseq_find_available_instance
- Add pwrseq_suspend/resume for API both single instance and list 
- Add .pwrseq_suspend/resume for pwrseq_generic.c
- Add pwrseq_suspend_list and pwrseq_resume_list for USB hub suspend
  and resume routine

Changes for v10:
- Improve the kernel-doc for power sequence core, including exported APIs and
  main structure. [Patch 2/8]
- Change Kconfig, and let the user choose power sequence. [Patch 2/8]
- Delete EXPORT_SYMBOL and change related APIs as local, these APIs do not
  be intended to export currently. [Patch 2/8]
- Selete POWER_SEQUENCE at USB core's Kconfig. [Patch 4/8]

Changes for v9:
- Add Vaibhav Hiremath's reviewed-by [Patch 4/8]
- Rebase to v4.9-rc1

Changes for v8:
- Allocate one extra pwrseq instance if pwrseq_get has succeed, it can avoid
  preallocate instances problem which the number of instance is decided at
  compile time, thanks for Heiko Stuebner's suggestion [Patch 2/8]
- Delete pwrseq_compatible_sample.c which is the demo purpose to show compatible
  match method. [Patch 2/8]
- Add Maciej S. Szmigiero's tested-by. [Patch 7/8]

Changes for v7:
- Create kinds of power sequence instance at postcore_initcall, and match
  the instance with node using compatible string, the beneit of this is
  the host driver doesn't need to consider which pwrseq instance needs
  to be used, and pwrseq core will match it, however, it eats some memories
  if less power sequence instances are used. [Patch 2/8]
- Add pwrseq_compatible_sample.c to test match pwrseq using device_id. [Patch 2/8]
- Fix the comments Vaibhav Hiremath adds for error path for clock and do not
  use device_node for parameters at pwrseq_on. [Patch 2/8]
- Simplify the caller to use power sequence, follows Alan's commnets [Patch 4/8]
- Tested three pwrseq instances together using both specific compatible string and
  generic libraries.

Changes for v6:
- Add Matthias Kaehlcke's Reviewed-by and Tested-by. (patch [2/6])
- Change chipidea core of_node assignment for coming user. (patch [5/6])
- Applies Joshua Clayton's three dts changes for two boards,
  the USB device's reg has only #address-cells, but without #size-cells.

Changes for v5:
- Delete pwrseq_register/pwrseq_unregister, which is useless currently
- Fix the linker error when the pwrseq user is compiled as module

Changes for v4:
- Create the patch on next-20160722 
- Fix the of_node is not NULL after chipidea driver is unbinded [Patch 5/6]
- Using more friendly wait method for reset gpio [Patch 2/6]
- Support multiple input clocks [Patch 2/6]
- Add Rob Herring's ack for DT changes
- Add Joshua Clayton's Tested-by

Changes for v3:
- Delete "power-sequence" property at binding-doc, and change related code
  at both library and user code.
- Change binding-doc example node name with Rob's comments
- of_get_named_gpio_flags only gets the gpio, but without setting gpio flags,
  add additional code request gpio with proper gpio flags
- Add Philipp Zabel's Ack and MAINTAINER's entry

Changes for v2:
- Delete "pwrseq" prefix and clock-names for properties at dt binding
- Should use structure not but its pointer for kzalloc
- Since chipidea core has no of_node, let core's of_node equals glue
  layer's at core's probe

Joshua Clayton (2):
  ARM: dts: imx6qdl: Enable usb node children with <reg>
  ARM: dts: imx6q-evi: Fix onboard hub reset line

Peter Chen (6):
  binding-doc: power: pwrseq-generic: add binding doc for generic power
    sequence library
  power: add power sequence library
  binding-doc: usb: usb-device: add optional properties for power
    sequence
  usb: core: add power sequence handling for USB devices
  usb: chipidea: let chipidea core device of_node equal's glue layer
    device of_node
  ARM: dts: imx6qdl-udoo.dtsi: fix onboard USB HUB property

 .../bindings/power/pwrseq/pwrseq-generic.txt       |  48 +++
 .../devicetree/bindings/usb/usb-device.txt         |  10 +-
 MAINTAINERS                                        |   9 +
 arch/arm/boot/dts/imx6q-evi.dts                    |  25 +-
 arch/arm/boot/dts/imx6qdl-udoo.dtsi                |  26 +-
 arch/arm/boot/dts/imx6qdl.dtsi                     |   6 +
 drivers/power/Kconfig                              |   1 +
 drivers/power/Makefile                             |   1 +
 drivers/power/pwrseq/Kconfig                       |  20 ++
 drivers/power/pwrseq/Makefile                      |   2 +
 drivers/power/pwrseq/core.c                        | 335 +++++++++++++++++++++
 drivers/power/pwrseq/pwrseq_generic.c              | 224 ++++++++++++++
 drivers/usb/Kconfig                                |   1 +
 drivers/usb/chipidea/core.c                        |  27 +-
 drivers/usb/core/hub.c                             |  48 ++-
 drivers/usb/core/hub.h                             |   1 +
 include/linux/power/pwrseq.h                       |  81 +++++
 17 files changed, 823 insertions(+), 42 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/power/pwrseq/pwrseq-generic.txt
 create mode 100644 drivers/power/pwrseq/Kconfig
 create mode 100644 drivers/power/pwrseq/Makefile
 create mode 100644 drivers/power/pwrseq/core.c
 create mode 100644 drivers/power/pwrseq/pwrseq_generic.c
 create mode 100644 include/linux/power/pwrseq.h

-- 
2.7.4

^ permalink raw reply

* [PATCH v2] drm/mediatek: Support UYVY and YUYV format for overlay
From: Daniel Kurtz @ 2017-01-03  6:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1483079183-38637-1-git-send-email-bibby.hsieh@mediatek.com>

On Fri, Dec 30, 2016 at 2:26 PM, Bibby Hsieh <bibby.hsieh@mediatek.com> wrote:
>
> MT8173 overlay can support UYVY and YUYV format,
> we add the format in DRM driver.
>
> Signed-off-by: Bibby Hsieh <bibby.hsieh@mediatek.com>
> Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
> ---
>  drivers/gpu/drm/mediatek/mtk_disp_ovl.c  | 21 +++++++++++++++++++++
>  drivers/gpu/drm/mediatek/mtk_drm_plane.c |  2 ++
>  2 files changed, 23 insertions(+)
>
> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> index c703102..de05845 100644
> --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
> @@ -40,10 +40,13 @@
>  #define        OVL_RDMA_MEM_GMC        0x40402020
>
>  #define OVL_CON_BYTE_SWAP      BIT(24)
> +#define OVL_CON_MTX_YUV_TO_RGB (6 << 16)
>  #define OVL_CON_CLRFMT_RGB565  (0 << 12)
>  #define OVL_CON_CLRFMT_RGB888  (1 << 12)
>  #define OVL_CON_CLRFMT_RGBA8888        (2 << 12)
>  #define OVL_CON_CLRFMT_ARGB8888        (3 << 12)
> +#define OVL_CON_CLRFMT_UYVY    (4 << 12)
> +#define OVL_CON_CLRFMT_YUYV    (5 << 12)

Why not just add " | OVL_CON_MTX_YUV_TO_RGB" here in the definition of
these two constants, instead of adding a helper function?

>  #define        OVL_CON_AEN             BIT(8)
>  #define        OVL_CON_ALPHA           0xff
>
> @@ -162,6 +165,21 @@ static unsigned int ovl_fmt_convert(unsigned int fmt)
>         case DRM_FORMAT_XBGR8888:
>         case DRM_FORMAT_ABGR8888:
>                 return OVL_CON_CLRFMT_RGBA8888 | OVL_CON_BYTE_SWAP;
> +       case DRM_FORMAT_UYVY:
> +               return OVL_CON_CLRFMT_UYVY;
> +       case DRM_FORMAT_YUYV:
> +               return OVL_CON_CLRFMT_YUYV;
> +       }
> +}
> +
> +static bool ovl_yuv_space(unsigned int fmt)
> +{
> +       switch (fmt) {
> +       case DRM_FORMAT_UYVY:
> +       case DRM_FORMAT_YUYV:
> +               return true;
> +       default:
> +               return false;
>         }
>  }
>
> @@ -183,6 +201,9 @@ static void mtk_ovl_layer_config(struct mtk_ddp_comp *comp, unsigned int idx,
>         if (idx != 0)
>                 con |= OVL_CON_AEN | OVL_CON_ALPHA;
>
> +       if (ovl_yuv_space(fmt))
> +               con |= OVL_CON_MTX_YUV_TO_RGB;
> +
>         writel_relaxed(con, comp->regs + DISP_REG_OVL_CON(idx));
>         writel_relaxed(pitch, comp->regs + DISP_REG_OVL_PITCH(idx));
>         writel_relaxed(src_size, comp->regs + DISP_REG_OVL_SRC_SIZE(idx));
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_plane.c b/drivers/gpu/drm/mediatek/mtk_drm_plane.c
> index c461a23..8c02d1d 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_plane.c
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_plane.c
> @@ -28,6 +28,8 @@
>         DRM_FORMAT_XRGB8888,
>         DRM_FORMAT_ARGB8888,
>         DRM_FORMAT_RGB565,
> +       DRM_FORMAT_UYVY,
> +       DRM_FORMAT_YUYV,
>  };
>
>  static void mtk_plane_reset(struct drm_plane *plane)
> --
> 1.9.1
>

^ permalink raw reply

* [PATCH 1/2] arm64:dt:ls1046a: Add TMU device tree support for LS1046A
From: Shawn Guo @ 2017-01-03  6:26 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <AM4PR0401MB1843C415E2CF7D58BD5A1064EB6E0@AM4PR0401MB1843.eurprd04.prod.outlook.com>

On Tue, Jan 03, 2017 at 03:49:33AM +0000, Troy Jia wrote:
> > > @@ -279,6 +282,82 @@
> > >  			clocks = <&sysclk>;
> > >  		};
> > >
> > > +		tmu: tmu at 1f00000 {
> > > +			compatible = "fsl,qoriq-tmu";
> > > +			reg = <0x0 0x1f00000 0x0 0x10000>;
> > > +			interrupts = <0 33 0x4>;
> > > +			fsl,tmu-range = <0xb0000 0x9002a 0x6004c 0x30062>;
> > > +			fsl,tmu-calibration = <0x00000000 0x00000026
> > > +					       0x00000001 0x0000002d
> > > +					       0x00000002 0x00000032
> > > +					       0x00000003 0x00000039
> > > +					       0x00000004 0x0000003f
> > > +					       0x00000005 0x00000046
> > > +					       0x00000006 0x0000004d
> > > +					       0x00000007 0x00000054
> > > +					       0x00000008 0x0000005a
> > > +					       0x00000009 0x00000061
> > > +					       0x0000000a 0x0000006a
> > > +					       0x0000000b 0x00000071
> > > +
> > 
> > Instead of a newline, can we have a single line comment here to tell how these
> > calibration data is grouped?
> 
> Each group represent one temperature range. It's a good idea to add comment here.
> Could I just add one comment like below to clarify all four groups?
> /* Each calibration data group represent one temperature range. There are four ranges in total */

Probably the following form?

	/* Calibration data group 1 */
	...
	/* Calibration data group 2 */
	...
	/* Calibration data group 3 */
	...
	/* Calibration data group 4 */
	...


> 
> > 
> > > +					       0x00010000 0x00000025
> > > +					       0x00010001 0x0000002c
> > > +					       0x00010002 0x00000035
> > > +					       0x00010003 0x0000003d
> > > +					       0x00010004 0x00000045
> > > +					       0x00010005 0x0000004e
> > > +					       0x00010006 0x00000057
> > > +					       0x00010007 0x00000061
> > > +					       0x00010008 0x0000006b
> > > +					       0x00010009 0x00000076
> > > +
> > > +					       0x00020000 0x00000029
> > > +					       0x00020001 0x00000033
> > > +					       0x00020002 0x0000003d
> > > +					       0x00020003 0x00000049
> > > +					       0x00020004 0x00000056
> > > +					       0x00020005 0x00000061
> > > +					       0x00020006 0x0000006d
> > > +
> > > +					       0x00030000 0x00000021
> > > +					       0x00030001 0x0000002a
> > > +					       0x00030002 0x0000003c
> > > +					       0x00030003 0x0000004e>;
> > > +			big-endian;
> > > +			#thermal-sensor-cells = <1>;
> > > +		};
> > > +
> > > +		thermal-zones {
> > > +			cpu_thermal: cpu-thermal {
> > > +				polling-delay-passive = <1000>;
> > > +				polling-delay = <5000>;
> > > +
> > 
> > We usually do not have newline between properties but nodes, or between
> > property list and child node.
> 
> I just follow the style of thermal binding of
> Documentation/devicetree/bindings/thermal/thermal.txt.

Different subsystem or binding examples use different style, but when we
put things together in the platform dts, we would like to have them in a
unified style.

Shawn

^ permalink raw reply

* [RFC, PATCHv2 29/29] mm, x86: introduce RLIMIT_VADDR
From: Andy Lutomirski @ 2017-01-03  6:08 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <2736959.3MfCab47fD@wuerfel>

On Mon, Jan 2, 2017 at 12:44 AM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Tuesday, December 27, 2016 4:54:13 AM CET Kirill A. Shutemov wrote:
>> As with other resources you can set the limit lower than current usage.
>> It would affect only future virtual address space allocations.

I still don't buy all these use cases:

>>
>> Use-cases for new rlimit:
>>
>>   - Bumping the soft limit to RLIM_INFINITY, allows current process all
>>     its children to use addresses above 47-bits.

OK, I get this, but only as a workaround for programs that make
assumptions about the address space and don't use some mechanism (to
be designed?) to work correctly in spite of a larger address space.

>>
>>   - Bumping the soft limit to RLIM_INFINITY after fork(2), but before
>>     exec(2) allows the child to use addresses above 47-bits.

Ditto.

>>
>>   - Lowering the hard limit to 47-bits would prevent current process all
>>     its children to use addresses above 47-bits, unless a process has
>>     CAP_SYS_RESOURCES.

I've tried and I can't imagine any reason to do this.

>>
>>   - It?s also can be handy to lower hard or soft limit to arbitrary
>>     address. User-mode emulation in QEMU may lower the limit to 32-bit
>>     to emulate 32-bit machine on 64-bit host.

I don't understand.  QEMU user-mode emulation intercepts all syscalls.
What QEMU would *actually* want is a way to say "allocate me some
memory with the high N bits clear".  mmap-via-int80 on x86 should be
fixed to do this, but a new syscall with an explicit parameter would
work, as would a prctl changing the current limit.

>>
>> TODO:
>>   - port to non-x86;
>>
>> Not-yet-signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
>> Cc: linux-api at vger.kernel.org
>
> This seems to nicely address the same problem on arm64, which has
> run into the same issue due to the various page table formats
> that can currently be chosen at compile time.

On further reflection, I think this has very little to do with paging
formats except insofar as paging formats make us notice the problem.
The issue is that user code wants to be able to assume an upper limit
on an address, and it gets an upper limit right now that depends on
architecture due to paging formats.  But someone really might want to
write a *portable* 64-bit program that allocates memory with the high
16 bits clear.  So let's add such a mechanism directly.

As a thought experiment, what if x86_64 simply never allocated "high"
(above 2^47-1) addresses unless a new mmap-with-explicit-limit syscall
were used?  Old glibc would continue working.  Old VMs would work.
New programs that want to use ginormous mappings would have to use the
new syscall.  This would be totally stateless and would have no issues
with CRIU.

If necessary, we could also have a prctl that changes a
"personality-like" limit that is in effect when the old mmap was used.
I say "personality-like" because it would reset under exactly the same
conditions that personality resets itself.

Thoughts?

^ permalink raw reply

* [PATCH v2 2/2] ARM: dts: imx6q: Add mccmon6 board support
From: Lukasz Majewski @ 2017-01-03  6:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170103020650.GM20956@dragon>

Hi Shawn,

Thank you for your comments.

> On Tue, Jan 03, 2017 at 12:43:38AM +0100, Lukasz Majewski wrote:
> > From: Lukasz Majewski <l.majewski@majess.pl>
> > 
> > This patch provides support for Liebherr's Monitor 6 board
> > (abverrated as mccmon6) to Linux kernel.
> > 
> > Signed-off-by: Lukasz Majewski <lukma@denx.de>
> > ---
> > Changes for v2:
> > - Reorganize the dts file according to Valdimir Zapolskiy's comments
> > 
> > ---
> > MCCMON6 board support depends on following patches:
> > 
> > 1. "video: backlight: pwm_bl: Initialize fb_bl_on[x] and use_count
> > during pwm_backlight_probe()"
> > http://patchwork.ozlabs.org/patch/708844/
> > 
> > 2. "pwm: imx: Provide atomic operation for IMX PWM driver"
> > 	http://patchwork.ozlabs.org/patch/708847/ -
> > http://patchwork.ozlabs.org/patch/708843/ ---
> >  arch/arm/boot/dts/Makefile          |   1 +
> >  arch/arm/boot/dts/imx6q-mccmon6.dts | 477
> > ++++++++++++++++++++++++++++++++++++ 2 files changed, 478
> > insertions(+) create mode 100644 arch/arm/boot/dts/imx6q-mccmon6.dts
> > 
> > diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
> > index c558ba7..0aa8e89 100644
> > --- a/arch/arm/boot/dts/Makefile
> > +++ b/arch/arm/boot/dts/Makefile
> > @@ -383,6 +383,7 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
> >  	imx6q-hummingboard.dtb \
> >  	imx6q-icore-rqs.dtb \
> >  	imx6q-marsboard.dtb \
> > +	imx6q-mccmon6.dtb \
> >  	imx6q-nitrogen6x.dtb \
> >  	imx6q-nitrogen6_max.dtb \
> >  	imx6q-novena.dtb \
> > diff --git a/arch/arm/boot/dts/imx6q-mccmon6.dts
> > b/arch/arm/boot/dts/imx6q-mccmon6.dts new file mode 100644
> > index 0000000..7128dc2
> > --- /dev/null
> > +++ b/arch/arm/boot/dts/imx6q-mccmon6.dts
> > @@ -0,0 +1,477 @@
> > +/*
> > + * Copyright 2016-2017
> > + * Lukasz Majewski, DENX Software Engineering, lukma at denx.de
> > + *
> > + * This program is free software; you can redistribute it and/or
> > modify
> > + * it under the terms of the GNU General Public License version 2
> > as
> > + * published by the Free Software Foundation.
> > + *
> > + */
> 
> You might want to GPL/X11 dual licence for non-Linux device tree
> users. There are a plenty of examples in arch/arm/boot/dts.  But note
> the following correction.
> 
> https://patchwork.kernel.org/patch/9475057/

For this board GPLv2 is enough. Is the above description correct or do
I need to add something?

> 
> > +
> > +/dts-v1/;
> > +
> > +#include "imx6q.dtsi"
> > +
> > +#include <dt-bindings/gpio/gpio.h>
> > +#include <dt-bindings/pwm/pwm.h>
> > +
> > +/ {
> > +	model = "Liebherr (LWN) monitor6 i.MX6 Quad Board";
> > +	compatible = "lwn,mccmon6", "fsl,imx6q";
> > +
> > +	memory {
> > +		reg = <0x10000000 0x80000000>;
> > +	};
> > +
> > +	backlight_lvds: backlight {
> > +		compatible = "pwm-backlight";
> > +		pinctrl-names = "default";
> > +		pinctrl-0 = <&pinctrl_backlight>;
> > +		pwms = <&pwm2 0 5000000 PWM_POLARITY_INVERTED>;
> > +		brightness-levels = <  0   1   2   3   4   5   6
> > 7   8   9
> > +				      10  11  12  13  14  15  16
> > 17  18  19
> > +				      20  21  22  23  24  25  26
> > 27  28  29
> > +				      30  31  32  33  34  35  36
> > 37  38  39
> > +				      40  41  42  43  44  45  46
> > 47  48  49
> > +				      50  51  52  53  54  55  56
> > 57  58  59
> > +				      60  61  62  63  64  65  66
> > 67  68  69
> > +				      70  71  72  73  74  75  76
> > 77  78  79
> > +				      80  81  82  83  84  85  86
> > 87  88  89
> > +				      90  91  92  93  94  95  96
> > 97  98  99
> > +				     100 101 102 103 104 105 106
> > 107 108 109
> > +				     110 111 112 113 114 115 116
> > 117 118 119
> > +				     120 121 122 123 124 125 126
> > 127 128 129
> > +				     130 131 132 133 134 135 136
> > 137 138 139
> > +				     140 141 142 143 144 145 146
> > 147 148 149
> > +				     150 151 152 153 154 155 156
> > 157 158 159
> > +				     160 161 162 163 164 165 166
> > 167 168 169
> > +				     170 171 172 173 174 175 176
> > 177 178 179
> > +				     180 181 182 183 184 185 186
> > 187 188 189
> > +				     190 191 192 193 194 195 196
> > 197 198 199
> > +				     200 201 202 203 204 205 206
> > 207 208 209
> > +				     210 211 212 213 214 215 216
> > 217 218 219
> > +				     220 221 222 223 224 225 226
> > 227 228 229
> > +				     230 231 232 233 234 235 236
> > 237 238 239
> > +				     240 241 242 243 244 245 246
> > 247 248 249
> > +				     250 251 252 253 254 255>;
> > +		default-brightness-level = <50>;
> > +		enable-gpios = <&gpio1 2 GPIO_ACTIVE_LOW>;
> > +	};
> > +
> > +	reg_lvds: regulator-lvds {
> > +		compatible = "regulator-fixed";
> > +		regulator-name = "lvds_ppen";
> > +		regulator-min-microvolt = <3300000>;
> > +		regulator-max-microvolt = <3300000>;
> > +		regulator-boot-on;
> > +		pinctrl-names = "default";
> > +		pinctrl-0 = <&pinctrl_reg_lvds>;
> > +		gpio = <&gpio1 19 GPIO_ACTIVE_HIGH>;
> > +		enable-active-high;
> > +	};
> > +
> > +	panel-lvds0 {
> > +		compatible = "innolux,g121x1-l03";
> > +		backlight = <&backlight_lvds>;
> > +		power-supply = <&reg_lvds>;
> > +
> > +		port {
> > +			panel_in_lvds0: endpoint {
> > +				remote-endpoint = <&lvds0_out>;
> > +			};
> > +		};
> > +	};
> > +};
> > +
> > +&iomuxc {
> 
> Considering the data amount of this node, we generally put it at the
> bottom of the file to improve the readability of the rest.

But then it will not be alphabetically ordered :-).

I can put it on the end - no problem.

> 
> > +	pinctrl-names = "default";
> > +
> > +	imx6q-mccmon6 {
> 
> This container node can now be dropped completely to save one level of
> indentation.

Ok, I will remove imx6q-mccmon6 container node completely.

> 
> > +		pinctrl_backlight: dispgrp {
> > +			fsl,pins = <
> > +				/* BLEN_OUT */
> > +				MX6QDL_PAD_GPIO_2__GPIO1_IO02
> > 0x1b0b0
> > +			>;
> > +		};
> > +
> > +		pinctrl_ecspi3: ecspi3grp {
> > +			fsl,pins = <
> > +
> > MX6QDL_PAD_DISP0_DAT2__ECSPI3_MISO	0x100b1
> > +
> > MX6QDL_PAD_DISP0_DAT1__ECSPI3_MOSI	0x100b1
> > +
> > MX6QDL_PAD_DISP0_DAT0__ECSPI3_SCLK	0x100b1
> > +			>;
> > +		};
> > +
> > +		pinctrl_ecspi3_cs: ecspi3cs {
> 
> ecspi3csgrp, if we follow the naming scheme used in other nodes.
> 
> > +			fsl,pins = <
> > +				MX6QDL_PAD_DISP0_DAT3__GPIO4_IO24
> > 0x80000000
> > +			>;
> > +		};
> > +
> > +		pinctrl_ecspi3_flwp: ecspi3flwp {
> 
> Ditto
> 
> > +			fsl,pins = <
> > +				MX6QDL_PAD_DISP0_DAT6__GPIO4_IO27
> > 0x80000000
> > +			>;
> > +		};
> > +
> > +		pinctrl_enet: enetgrp {
> > +			fsl,pins = <
> > +
> > MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
> > +
> > MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
> > +
> > MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x1b0b0
> > +
> > MX6QDL_PAD_RGMII_TD0__RGMII_TD0		0x1b0b0
> > +
> > MX6QDL_PAD_RGMII_TD1__RGMII_TD1		0x1b0b0
> > +
> > MX6QDL_PAD_RGMII_TD2__RGMII_TD2		0x1b0b0
> > +
> > MX6QDL_PAD_RGMII_TD3__RGMII_TD3		0x1b0b0
> > +
> > MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL	0x1b0b0
> > +
> > MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK	0x1b0b0
> > +
> > MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b0b0
> > +
> > MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x1b0b0
> > +
> > MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x1b0b0
> > +
> > MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b0b0
> > +
> > MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b0b0
> > +
> > MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x1b0b0
> > +				MX6QDL_PAD_GPIO_16__ENET_REF_CLK
> > 0x4001b0a8
> > +
> > MX6QDL_PAD_GPIO_6__ENET_IRQ		0x000b1
> > +
> > MX6QDL_PAD_ENET_RXD0__GPIO1_IO27        0x1b0b0
> > +			>;
> > +		};
> > +
> > +		pinctrl_i2c1: i2c1grp {
> > +			fsl,pins = <
> > +
> > MX6QDL_PAD_CSI0_DAT9__I2C1_SCL	0x4001b8b1
> > +
> > MX6QDL_PAD_CSI0_DAT8__I2C1_SDA	0x4001b8b1
> > +			>;
> > +		};
> > +
> > +		pinctrl_i2c2: i2c2grp {
> > +			fsl,pins = <
> > +
> > MX6QDL_PAD_KEY_COL3__I2C2_SCL	0x4001b8b1
> > +
> > MX6QDL_PAD_KEY_ROW3__I2C2_SDA	0x4001b8b1
> > +			>;
> > +		};
> > +
> > +		pinctrl_pwm2: pwm2grp {
> > +			fsl,pins = <
> > +				MX6QDL_PAD_GPIO_1__PWM2_OUT
> > 0x1b0b1
> > +			>;
> > +		};
> > +
> > +		pinctrl_reg_lvds: req_lvds_grp {
> 
> reglvdsgrp
> 
> > +			fsl,pins = <
> > +				/* LVDS_PPEN_OUT */
> > +
> > MX6QDL_PAD_SD1_DAT2__GPIO1_IO19         0x1b0b0
> > +			>;
> > +		};
> > +
> > +		pinctrl_uart1: uart1grp {
> > +			fsl,pins = <
> > +
> > MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA	0x1b0b1
> > +
> > MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA	0x1b0b1
> > +			>;
> > +		};
> > +
> > +		pinctrl_uart4: uart4grp {
> > +			fsl,pins = <
> > +
> > MX6QDL_PAD_KEY_COL0__UART4_TX_DATA	0x1b0b1
> > +
> > MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA	0x1b0b1
> > +
> > MX6QDL_PAD_CSI0_DAT16__UART4_RTS_B	0x1b0b1
> > +
> > MX6QDL_PAD_CSI0_DAT17__UART4_CTS_B	0x1b0b1
> > +			>;
> > +		};
> > +
> > +		pinctrl_usdhc2: usdhc2grp {
> > +			fsl,pins = <
> > +
> > MX6QDL_PAD_SD2_CMD__SD2_CMD		0x17059
> > +
> > MX6QDL_PAD_SD2_CLK__SD2_CLK		0x10059
> > +
> > MX6QDL_PAD_SD2_DAT0__SD2_DATA0		0x17059
> > +
> > MX6QDL_PAD_SD2_DAT1__SD2_DATA1		0x17059
> > +
> > MX6QDL_PAD_SD2_DAT2__SD2_DATA2		0x17059
> > +
> > MX6QDL_PAD_SD2_DAT3__SD2_DATA3		0x17059
> > +
> > MX6QDL_PAD_GPIO_4__GPIO1_IO04           0x1b0b1
> > +			>;
> > +		};
> > +
> > +		pinctrl_usdhc3: usdhc3grp {
> > +			fsl,pins = <
> > +
> > MX6QDL_PAD_SD3_CMD__SD3_CMD		0x17059
> > +
> > MX6QDL_PAD_SD3_CLK__SD3_CLK		0x10059
> > +
> > MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x17059
> > +
> > MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x17059
> > +
> > MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x17059
> > +
> > MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x17059
> > +
> > MX6QDL_PAD_SD3_DAT4__SD3_DATA4		0x17059
> > +
> > MX6QDL_PAD_SD3_DAT5__SD3_DATA5		0x17059
> > +
> > MX6QDL_PAD_SD3_DAT6__SD3_DATA6		0x17059
> > +
> > MX6QDL_PAD_SD3_DAT7__SD3_DATA7		0x17059
> > +
> > MX6QDL_PAD_SD3_RST__SD3_RESET		0x17059
> > +			>;
> > +		};
> > +
> > +		pinctrl_weim_cs0: weimcs0grp {
> > +			fsl,pins = <
> > +
> > MX6QDL_PAD_EIM_CS0__EIM_CS0_B		0xb0b1
> > +			>;
> > +		};
> > +
> > +		pinctrl_weim_nor: weimnorgrp {
> > +			fsl,pins = <
> > +
> > MX6QDL_PAD_EIM_OE__EIM_OE_B		0xb0b1
> > +
> > MX6QDL_PAD_EIM_RW__EIM_RW		0xb0b1
> > +
> > MX6QDL_PAD_EIM_WAIT__EIM_WAIT_B	0xb060
> > +
> > MX6QDL_PAD_EIM_D16__EIM_DATA16		0x1b0b0
> > +
> > MX6QDL_PAD_EIM_D17__EIM_DATA17		0x1b0b0
> > +
> > MX6QDL_PAD_EIM_D18__EIM_DATA18		0x1b0b0
> > +
> > MX6QDL_PAD_EIM_D19__EIM_DATA19		0x1b0b0
> > +
> > MX6QDL_PAD_EIM_D20__EIM_DATA20		0x1b0b0
> > +
> > MX6QDL_PAD_EIM_D21__EIM_DATA21		0x1b0b0
> > +
> > MX6QDL_PAD_EIM_D22__EIM_DATA22		0x1b0b0
> > +
> > MX6QDL_PAD_EIM_D23__EIM_DATA23		0x1b0b0
> > +
> > MX6QDL_PAD_EIM_D24__EIM_DATA24		0x1b0b0
> > +
> > MX6QDL_PAD_EIM_D25__EIM_DATA25		0x1b0b0
> > +
> > MX6QDL_PAD_EIM_D26__EIM_DATA26		0x1b0b0
> > +
> > MX6QDL_PAD_EIM_D27__EIM_DATA27		0x1b0b0
> > +
> > MX6QDL_PAD_EIM_D28__EIM_DATA28		0x1b0b0
> > +
> > MX6QDL_PAD_EIM_D29__EIM_DATA29		0x1b0b0
> > +
> > MX6QDL_PAD_EIM_D30__EIM_DATA30		0x1b0b0
> > +
> > MX6QDL_PAD_EIM_D31__EIM_DATA31		0x1b0b0
> > +
> > MX6QDL_PAD_EIM_A23__EIM_ADDR23		0xb0b1
> > +
> > MX6QDL_PAD_EIM_A22__EIM_ADDR22		0xb0b1
> > +
> > MX6QDL_PAD_EIM_A21__EIM_ADDR21		0xb0b1
> > +
> > MX6QDL_PAD_EIM_A20__EIM_ADDR20		0xb0b1
> > +
> > MX6QDL_PAD_EIM_A19__EIM_ADDR19		0xb0b1
> > +
> > MX6QDL_PAD_EIM_A18__EIM_ADDR18		0xb0b1
> > +
> > MX6QDL_PAD_EIM_A17__EIM_ADDR17		0xb0b1
> > +
> > MX6QDL_PAD_EIM_A16__EIM_ADDR16		0xb0b1
> > +
> > MX6QDL_PAD_EIM_DA15__EIM_AD15		0xb0b1
> > +
> > MX6QDL_PAD_EIM_DA14__EIM_AD14		0xb0b1
> > +
> > MX6QDL_PAD_EIM_DA13__EIM_AD13		0xb0b1
> > +
> > MX6QDL_PAD_EIM_DA12__EIM_AD12		0xb0b1
> > +
> > MX6QDL_PAD_EIM_DA11__EIM_AD11		0xb0b1
> > +
> > MX6QDL_PAD_EIM_DA10__EIM_AD10		0xb0b1
> > +
> > MX6QDL_PAD_EIM_DA9__EIM_AD09		0xb0b1
> > +
> > MX6QDL_PAD_EIM_DA8__EIM_AD08		0xb0b1
> > +
> > MX6QDL_PAD_EIM_DA7__EIM_AD07		0xb0b1
> > +
> > MX6QDL_PAD_EIM_DA6__EIM_AD06		0xb0b1
> > +
> > MX6QDL_PAD_EIM_DA5__EIM_AD05		0xb0b1
> > +
> > MX6QDL_PAD_EIM_DA4__EIM_AD04		0xb0b1
> > +
> > MX6QDL_PAD_EIM_DA3__EIM_AD03		0xb0b1
> > +
> > MX6QDL_PAD_EIM_DA2__EIM_AD02		0xb0b1
> > +
> > MX6QDL_PAD_EIM_DA1__EIM_AD01		0xb0b1
> > +
> > MX6QDL_PAD_EIM_DA0__EIM_AD00		0xb0b1
> > +			>;
> > +		};
> > +	};
> > +};
> > +
> > +&ecspi3 {
> > +	cs-gpios = <&gpio4 24 0>;
> 
> GPIO_ACTIVE_HIGH?

No, on our HW it is GPIO_ACTIVE_LOW

> 
> > +	pinctrl-names = "default";
> > +	pinctrl-0 = <&pinctrl_ecspi3 &pinctrl_ecspi3_cs
> > &pinctrl_ecspi3_flwp>;
> > +	status = "okay";
> > +
> > +	flash: s25sl032p at 0 {
> 
> Node name should be as generic as possible, while label name can be
> specific.  That said, 's25sl032p: flash at 0' should be better.

OK.

> 
> > +		#address-cells = <1>;
> > +		#size-cells = <1>;
> > +		compatible = "spansion,s25sl032p", "jedec,spi-nor";
> 
> "spansion,s25sl032p" doesn't seem to be documented.  Can it be
> dropped?

This memory is jedec compatible and uses "jedec,spi-nor", so
"spansion,s25sl032p" can be dropped

> 
> > +		spi-max-frequency = <40000000>;
> > +		reg = <0>;
> > +	};
> > +};
> > +
> > +&fec {
> > +	pinctrl-names = "default";
> > +	pinctrl-0 = <&pinctrl_enet>;
> > +	phy-mode = "rgmii";
> > +	phy-reset-gpios = <&gpio1 27 0>;
> 
> GPIO_ACTIVE_xxx?  But you probably need GPIO_ACTIVE_LOW.

Yes.

> 
> > +	interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>,
> > +			      <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>;
> > +	status = "okay";
> > +};
> > +
> > +&i2c1 {
> > +	clock-frequency = <100000>;
> > +	pinctrl-names = "default";
> > +	pinctrl-0 = <&pinctrl_i2c1>;
> > +	status = "okay";
> > +};
> > +
> > +&i2c2 {
> > +	clock-frequency = <100000>;
> > +	pinctrl-names = "default";
> > +	pinctrl-0 = <&pinctrl_i2c2>;
> > +	status = "okay";
> > +
> > +	pmic: pfuze100 at 08 {
> 
> pfuze100: pmic at 08
> 
> > +		compatible = "fsl,pfuze100";
> > +		reg = <0x08>;
> > +
> > +		regulators {
> > +			sw1a_reg: sw1ab {
> > +				regulator-min-microvolt = <300000>;
> > +				regulator-max-microvolt =
> > <1875000>;
> > +				regulator-boot-on;
> > +				regulator-always-on;
> > +				regulator-ramp-delay = <6250>;
> > +			};
> > +
> > +			sw1c_reg: sw1c {
> > +				regulator-min-microvolt = <300000>;
> > +				regulator-max-microvolt =
> > <1875000>;
> > +				regulator-boot-on;
> > +				regulator-always-on;
> > +				regulator-ramp-delay = <6250>;
> > +			};
> > +
> > +			sw2_reg: sw2 {
> > +				regulator-min-microvolt = <800000>;
> > +				regulator-max-microvolt =
> > <3950000>;
> > +				regulator-boot-on;
> > +				regulator-always-on;
> > +			};
> > +
> > +			sw3a_reg: sw3a {
> > +				regulator-min-microvolt = <400000>;
> > +				regulator-max-microvolt =
> > <1975000>;
> > +				regulator-boot-on;
> > +				regulator-always-on;
> > +			};
> > +
> > +			sw3b_reg: sw3b {
> > +				regulator-min-microvolt = <400000>;
> > +				regulator-max-microvolt =
> > <1975000>;
> > +				regulator-boot-on;
> > +				regulator-always-on;
> > +			};
> > +
> > +			sw4_reg: sw4 {
> > +				regulator-min-microvolt = <800000>;
> > +				regulator-max-microvolt =
> > <3300000>;
> > +			};
> > +
> > +			swbst_reg: swbst {
> > +				regulator-min-microvolt =
> > <5000000>;
> > +				regulator-max-microvolt =
> > <5150000>;
> > +			};
> > +
> > +			snvs_reg: vsnvs {
> > +				regulator-min-microvolt =
> > <1000000>;
> > +				regulator-max-microvolt =
> > <3000000>;
> > +				regulator-boot-on;
> > +				regulator-always-on;
> > +			};
> > +
> > +			vref_reg: vrefddr {
> > +				regulator-boot-on;
> > +				regulator-always-on;
> > +			};
> > +
> > +			vgen1_reg: vgen1 {
> > +				regulator-min-microvolt = <800000>;
> > +				regulator-max-microvolt =
> > <1550000>;
> > +			};
> > +
> > +			vgen2_reg: vgen2 {
> > +				regulator-min-microvolt = <800000>;
> > +				regulator-max-microvolt =
> > <1550000>;
> > +			};
> > +
> > +			vgen3_reg: vgen3 {
> > +				regulator-min-microvolt =
> > <1800000>;
> > +				regulator-max-microvolt =
> > <3300000>;
> > +			};
> > +
> > +			vgen4_reg: vgen4 {
> > +				regulator-min-microvolt =
> > <1800000>;
> > +				regulator-max-microvolt =
> > <3300000>;
> > +				regulator-always-on;
> > +			};
> > +
> > +			vgen5_reg: vgen5 {
> > +				regulator-min-microvolt =
> > <1800000>;
> > +				regulator-max-microvolt =
> > <3300000>;
> > +				regulator-always-on;
> > +			};
> > +
> > +			vgen6_reg: vgen6 {
> > +				regulator-min-microvolt =
> > <1800000>;
> > +				regulator-max-microvolt =
> > <3300000>;
> > +				regulator-always-on;
> > +			};
> > +		};
> > +	};
> > +};
> > +
> > +&ldb {
> > +	status = "okay";
> > +
> > +	lvds0: lvds-channel at 0 {
> > +		fsl,data-mapping = "spwg";
> > +		fsl,data-width = <24>;
> > +		status = "okay";
> > +
> > +		port at 4 {
> > +			reg = <4>;
> > +
> > +			lvds0_out: endpoint {
> > +				remote-endpoint =
> > <&panel_in_lvds0>;
> > +			};
> > +		};
> > +	};
> > +};
> > +
> > +&pwm2 {
> > +	#pwm-cells = <3>;
> > +	pinctrl-names = "default";
> > +	pinctrl-0 = <&pinctrl_pwm2>;
> > +	status = "okay";
> > +};
> > +
> > +&uart1 {
> > +	pinctrl-names = "default";
> > +	pinctrl-0 = <&pinctrl_uart1>;
> > +	status = "okay";
> > +};
> > +
> > +&uart4 {
> > +	pinctrl-names = "default";
> > +	pinctrl-0 = <&pinctrl_uart4>;
> > +	uart-has-rtscts;
> > +	status = "okay";
> > +};
> > +
> > +&usdhc2 {
> > +	pinctrl-names = "default";
> > +	pinctrl-0 = <&pinctrl_usdhc2>;
> > +	cd-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
> > +	bus-width = <4>;
> > +	status = "okay";
> > +};
> > +
> > +&usdhc3 {
> > +	pinctrl-names = "default";
> > +	pinctrl-0 = <&pinctrl_usdhc3>;
> > +	bus-width = <8>;
> > +	non-removable;
> > +	status = "okay";
> > +};
> > +
> > +&weim {
> > +	pinctrl-names = "default";
> > +	pinctrl-0 = <&pinctrl_weim_nor &pinctrl_weim_cs0>;
> > +	#address-cells = <2>;
> > +	#size-cells = <1>;
> 
> These two properties can be saved from board dts since commit
> 1be81ea58607 ("ARM: dts: imx6: Add imx-weim parameters to dtsi's").

Ok, I will remove them.

> 
> Shawn
> 
> > +	ranges = <0 0 0x08000000 0x08000000>;
> > +	status = "okay";
> > +
> > +	nor at 0,0 {
> > +		compatible = "cfi-flash";
> > +		reg = <0 0 0x02000000>;
> > +		#address-cells = <1>;
> > +		#size-cells = <1>;
> > +		bank-width = <2>;
> > +		use-advanced-sector-protection;
> > +		fsl,weim-cs-timing = <0x00620081 0x00000001
> > 0x1c022000
> > +				0x0000c000 0x1404a38e 0x00000000>;
> > +	};
> > +};
> > -- 
> > 2.1.4
> > 


Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de

^ permalink raw reply

* [PATCH] ARM: dts: imx: Remove unexistant property
From: Shawn Guo @ 2017-01-03  5:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1483123378-20138-1-git-send-email-festevam@gmail.com>

On Fri, Dec 30, 2016 at 04:42:58PM -0200, Fabio Estevam wrote:
> From: Fabio Estevam <fabio.estevam@nxp.com>
> 
> Property 'anatop-enable-bit' does not exist, so just remove it.
> 
> Signed-off-by: Fabio Estevam <fabio.estevam@nxp.com>

Applied, thanks.

^ permalink raw reply

* [PATCH v2 3/3] phy: rockchip-inno-usb2: Set EXTCON_USB when EXTCON_CHG_USB_SDP was set
From: Baolin Wang @ 2017-01-03  5:54 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <23666cc1a5ff123ece5bdbb9821d1eab280d0927.1482307697.git.baolin.wang@linaro.org>

Hi Kison and Heiko,

On 21 December 2016 at 16:12, Baolin Wang <baolin.wang@linaro.org> wrote:
> According to the documentation, we should set the EXTCON_USB when
> one SDP charger connector was reported.
>
> Signed-off-by: Baolin Wang <baolin.wang@linaro.org>
> Reviewed-by: Chanwoo Choi <cw00.choi@samsung.com>

Could you apply this patch if there are no other comments? Thanks.

-- 
Baolin.wang
Best Regards

^ permalink raw reply

* [PATCH v2 1/6] ARM: mach-mx31_3ds: Remove camera support
From: Shawn Guo @ 2017-01-03  5:53 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1483097613-21481-1-git-send-email-festevam@gmail.com>

On Fri, Dec 30, 2016 at 09:33:28AM -0200, Fabio Estevam wrote:
> From: Fabio Estevam <fabio.estevam@nxp.com>
> 
> Since commit c93cc61475ebbe6e66 ("[media] staging/media: remove deprecated
> mx3 driver") the mx3 camera driver has been removed, so remove the camera
> support from the board file as well.
> 
> Signed-off-by: Fabio Estevam <fabio.estevam@nxp.com>

Applied all, thanks.

^ permalink raw reply

* [PATCH v2 2/4] ARM: davinci_all_defconfig: enable video capture as modules
From: Sekhar Nori @ 2017-01-03  5:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161207193137.27947-3-khilman@baylibre.com>

On Thursday 08 December 2016 01:01 AM, Kevin Hilman wrote:
> Enable media support and V4L2 capture, along with video decoders used
> on da850 platforms.
> 
> Tested on da850-lcdk.
> 
> Signed-off-by: Kevin Hilman <khilman@baylibre.com>

Applied to v4.11/defconfig

Thanks,
Sekhar

^ permalink raw reply

* [PATCH v7 3/5] drm: bridge: add support for TI ths8135
From: Sekhar Nori @ 2017-01-03  5:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <da6d299e-be36-7564-f57f-ba5e3601cafc@codeaurora.org>

On Tuesday 03 January 2017 10:56 AM, Archit Taneja wrote:
> Hi Sekhar,
> 
> On 1/2/2017 4:38 PM, Sekhar Nori wrote:
>> Hi Archit,
>>
>> On Wednesday 14 December 2016 10:35 AM, Archit Taneja wrote:
>>>
>>>
>>> On 12/13/2016 03:39 PM, Bartosz Golaszewski wrote:
>>>> THS8135 is a configurable video DAC, but no configuration is actually
>>>> necessary to make it work.
>>>>
>>>> For now use the dumb-vga-dac driver to support it.
>>>
>>> Queued to drm-misc-next
>>
>> This patch and 2/5 are not in v4.10 kernel. Did you mean to queue them
>> to v4.10?
> 
> These missed out on 4.10 because the drm related pull requests were
> already sent by then. These 2 patches are queued for 4.11.

Alright, thanks for the update.

Regards,
Sekhar

^ permalink raw reply

* [PATCH v2.1 1/4] ARM: dts: davinci: da850: VPIF: add node and muxing
From: Sekhar Nori @ 2017-01-03  5:35 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161208001418.4469-1-khilman@baylibre.com>

Hi Kevin,

On Thursday 08 December 2016 05:44 AM, Kevin Hilman wrote:
> Add VPIF node an pins to da850 and enable on boards.  VPIF has two input
> channels described using the standard DT ports and enpoints.
> 
> Signed-off-by: Kevin Hilman <khilman@baylibre.com>
> ---
> v2 -> v2.1: moved ports from SoC .dtsi to board .dts files.
> 
>  arch/arm/boot/dts/da850-evm.dts  | 20 ++++++++++++++++++++
>  arch/arm/boot/dts/da850-lcdk.dts | 13 +++++++++++++
>  arch/arm/boot/dts/da850.dtsi     | 27 ++++++++++++++++++++++++++-
>  3 files changed, 59 insertions(+), 1 deletion(-)

Can you split this patch to keep the SoC addition separate from board
updates. Separating support addition for EVM and LCDK will be good also.

> diff --git a/arch/arm/boot/dts/da850.dtsi b/arch/arm/boot/dts/da850.dtsi
> index f79e1b91c680..5f0b40510b2b 100644
> --- a/arch/arm/boot/dts/da850.dtsi
> +++ b/arch/arm/boot/dts/da850.dtsi

> @@ -399,7 +410,21 @@
>  				<&edma0 0 1>;
>  			dma-names = "tx", "rx";
>  		};
> +
> +		vpif: video at 217000 {
> +			compatible = "ti,da850-vpif";
> +			reg = <0x217000 0x1000>;
> +			interrupts = <92>;
> +			status = "disabled";
> +
> +			/* VPIF capture port */
> +			port {
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +			};
> +		};

Can you add this node just above mmc1? I am trying to keep the nodes
sorted in the order of unit address instead of new ones getting added at
the end. Unfortunately, it was not strictly enforced and we have many
breakages. But lets add the new ones where they will eventually end up.

Thanks,
Sekhar

^ permalink raw reply

* [PATCH v7 3/5] drm: bridge: add support for TI ths8135
From: Archit Taneja @ 2017-01-03  5:26 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <0b47c27e-cda4-b5f6-ff3c-da74c40ed204@ti.com>

Hi Sekhar,

On 1/2/2017 4:38 PM, Sekhar Nori wrote:
> Hi Archit,
>
> On Wednesday 14 December 2016 10:35 AM, Archit Taneja wrote:
>>
>>
>> On 12/13/2016 03:39 PM, Bartosz Golaszewski wrote:
>>> THS8135 is a configurable video DAC, but no configuration is actually
>>> necessary to make it work.
>>>
>>> For now use the dumb-vga-dac driver to support it.
>>
>> Queued to drm-misc-next
>
> This patch and 2/5 are not in v4.10 kernel. Did you mean to queue them
> to v4.10?

These missed out on 4.10 because the drm related pull requests were
already sent by then. These 2 patches are queued for 4.11.

Thanks,
Archit

>
> Thanks,
> Sekhar
>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply

* [PATCH v3 2/3] DT: bingdings: power: reset: add linkstation-reset doc
From: Florian Fainelli @ 2017-01-03  5:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161227070611.14852-3-rogershimizu@gmail.com>



On 12/26/2016 11:06 PM, Roger Shimizu wrote:
> Add linkstation-reset doc to describe the newly added
> POWER_RESET_LINKSTATION driver, which controls magic command
> sending to UART1 to power-off Buffalo Linkstation / KuroBox
> and their variants.
> 
> To: Sebastian Reichel <sre@kernel.org>
> To: Rob Herring <robh+dt@kernel.org>
> To: Mark Rutland <mark.rutland@arm.com>
> Cc: Andrew Lunn <andrew@lunn.ch>
> Cc: Ryan Tandy <ryan@nardis.ca>
> Cc: linux-pm at vger.kernel.org
> Cc: devicetree at vger.kernel.org
> Cc: linux-arm-kernel at lists.infradead.org
> 
> Signed-off-by: Roger Shimizu <rogershimizu@gmail.com>
> ---
>  .../bindings/power/reset/linkstation-reset.txt     | 26 ++++++++++++++++++++++
>  1 file changed, 26 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/power/reset/linkstation-reset.txt
> 
> diff --git a/Documentation/devicetree/bindings/power/reset/linkstation-reset.txt b/Documentation/devicetree/bindings/power/reset/linkstation-reset.txt
> new file mode 100644
> index 000000000000..815e340318f3
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/power/reset/linkstation-reset.txt
> @@ -0,0 +1,26 @@
> +* Buffalo Linkstation Reset Driver
> +
> +Power of some Buffalo Linkstation or KuroBox Pro is managed by
> +micro-controller, which connects to UART1. After being fed from UART1
> +by a few magic numbers, the so-called power-off command,
> +the micro-controller will turn power off the device.
> +
> +This is very similar to QNAP or Synology NAS devices, which is
> +described in qnap-poweroff.txt, however the command is much simpler,
> +only 1-byte long and without checksums.
> +
> +This driver adds a handler to pm_power_off which is called to turn the
> +power off.

This is a driver implementation detail, so does not really belong in the
DT here.

> +
> +Required Properties:
> +- compatible: Should be "linkstation,power-off"
> +- reg: Address and length of the register set for UART1

Humm, should we instead have a phandle to the uart1 node?

> +- clocks: tclk clock
> +
> +Example:
> +
> +	reset {
> +		compatible = "linkstation,power-off";
> +		reg = <0x12100 0x100>;
> +		clocks = <&core_clk 0>;
> +	};
> 

-- 
Florian

^ permalink raw reply

* [PATCH v3 1/3] power: reset: add linkstation-reset driver
From: Florian Fainelli @ 2017-01-03  5:19 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161227070611.14852-2-rogershimizu@gmail.com>

Hi Roger,

On 12/26/2016 11:06 PM, Roger Shimizu wrote:
> Buffalo Linkstation / KuroBox and their variants need magic command
> sending to UART1 to power-off.
> 
> Power driver linkstation-reset implements the magic command and I/O
> routine, which come from files listed below:
>   - arch/arm/mach-orion5x/kurobox_pro-setup.c
>   - arch/arm/mach-orion5x/terastation_pro2-setup.c

Interestingly, I submitted a patch doing nearly the same thing recently
after hacking on a Buffalo Terastation Pro II two days after yours
without seeing yours:

https://lkml.org/lkml/2016/12/28/273

Some comments below.

> +
> +static void __iomem *base;
> +static unsigned long tclk;
> +static const struct reset_cfg *cfg;

How about avoiding the singletons here and pass this down from the
platform driver's private data after we (see below) also make use of a
reboot notifier?

> +
> +static void linkstation_reset(void)
> +{
> +	const unsigned divisor = ((tclk + (8 * cfg->baud)) / (16 * cfg->baud));
> +	int i;
> +
> +	pr_err("%s: triggering power-off...\n", __func__);
> +
> +	/* hijack UART1 and reset into sane state */
> +	writel(0x83, UART1_REG(LCR));
> +	writel(divisor & 0xff, UART1_REG(DLL));
> +	writel((divisor >> 8) & 0xff, UART1_REG(DLM));
> +	writel(cfg->magic[0], UART1_REG(LCR));
> +	writel(cfg->magic[1], UART1_REG(IER));
> +	writel(cfg->magic[2], UART1_REG(FCR));
> +	writel(cfg->magic[3], UART1_REG(MCR));
> +
> +	/* send the power-off command to PIC */
> +	for(i = 0; cfg->cmd[i][0] > 0; i ++) {
> +		/* [0] is size of the command; command starts from [1] */
> +		uart1_micon_send(base, &(cfg->cmd[i][1]), cfg->cmd[i][0]);
> +	}
> +}
> +
> +static int linkstation_reset_probe(struct platform_device *pdev)
> +{
> +	struct device_node *np = pdev->dev.of_node;
> +	struct resource *res;
> +	struct clk *clk;
> +	char symname[KSYM_NAME_LEN];
> +
> +	const struct of_device_id *match =
> +		of_match_node(linkstation_reset_of_match_table, np);
> +	cfg = match->data;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!res) {
> +		dev_err(&pdev->dev, "Missing resource");
> +		return -EINVAL;
> +	}
> +
> +	base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
> +	if (!base) {
> +		dev_err(&pdev->dev, "Unable to map resource");
> +		return -EINVAL;
> +	}
> +
> +	/* We need to know tclk in order to calculate the UART divisor */
> +	clk = devm_clk_get(&pdev->dev, NULL);
> +	if (IS_ERR(clk)) {
> +		dev_err(&pdev->dev, "Clk missing");
> +		return PTR_ERR(clk);
> +	}
> +
> +	tclk = clk_get_rate(clk);

Does this work with the Terastation II which has not been converted to
DT yet? Is tclk available through the CLK API there?

> +
> +	/* Check that nothing else has already setup a handler */
> +	if (pm_power_off) {
> +		lookup_symbol_name((ulong)pm_power_off, symname);
> +		dev_err(&pdev->dev,
> +			"pm_power_off already claimed %p %s",
> +			pm_power_off, symname);
> +		return -EBUSY;
> +	}
> +	pm_power_off = linkstation_reset;

That seems a bit complicated, why not just assume that there will be
either this driver used, or not at all?

Also, you are supposed to register a reboot notifier to which you can
pass private context:

https://lkml.org/lkml/2016/12/28/275

As indicated in my patch series, the UART1-attached micro controller
does a lot more things that just providing reboot, which is why I chose
to move this code to a MFD driver, as the starting point before adding
support for LEDs, FAN, PWM, beeper which would be other types of devices.

Is adding support for other peripherals on your TODO as well?

Thanks!
-- 
Florian

^ permalink raw reply

* [RFC PATCH net-next v4 1/2] macb: Add 1588 support in Cadence GEM.
From: Harini Katakam @ 2017-01-03  5:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170102161359.GD3609@localhost.localdomain>

Hi Richard,

On Mon, Jan 2, 2017 at 9:43 PM, Richard Cochran
<richardcochran@gmail.com> wrote:
> On Mon, Jan 02, 2017 at 03:47:07PM +0100, Nicolas Ferre wrote:
>> Le 02/01/2017 ? 12:31, Richard Cochran a ?crit :
>> > This Cadence IP core is a complete disaster.
>>
>> Well, it evolved and propose several options to different SoC
>> integrators. This is not something unusual...
>> I suspect as well that some other network adapters have the same
>> weakness concerning PTP timestamp in single register as the early
>> revisions of this IP.
>
> It appears that this core can neither latch the time on read or write,
> or even latch time stamps.  I have worked with many different PTP HW
> implementations, even early ones like on the ixp4xx, and it is no
> exaggeration to say that this one is uniquely broken.
>
>> I suspect that Rafal tend to jump too quickly to the latest IP revisions
>> and add more options to this series: let's not try to pour too much
>> things into this code right now.
>
> Why can't you check the IP version in the driver?

There is an IP revision register but it would be probably be better
to rely on "caps" from the compatibility strings - to cover SoC
specific implementations. Also, when this extended BD is
added (with timestamp), additional words will need to be added
statically which will be consistent with Andrei's CONFIG_
checks.

>
> And is it really true that the registers don't latch the time stamps,
> as Rafal said?  If so, then we cannot accept the non-descriptor driver
> version, since it cannot possibly work correctly.
>

AFAIK, the two sets of registers only hold the timestamp till the next
event (or peer event) packet comes in.
I understand that it is not accurate - it is an initial version.

Regards,
Harini

^ permalink raw reply

* [PATCH RESEND] dmaengine: stm32-dma: Rework starting transfer management
From: Vinod Koul @ 2017-01-03  3:57 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1483349607-16870-1-git-send-email-cedric.madianga@gmail.com>

On Mon, Jan 02, 2017 at 10:33:27AM +0100, M'boumba Cedric Madianga wrote:
> This patch reworks the way to manage transfer starting.
> Now, starting DMA is only allowed when the channel is not busy.
> Then, stm32_dma_start_transfer is declared as void.
> At least, after each transfer completion, we start the next transfer if a
> new descriptor as been queued in the issued list during an ongoing
> transfer.

ah sorry, i missed to push topic/stm32-dma. can you rebase onnthis and
resend again. Btw this fails as as well..

-- 
~Vinod

^ permalink raw reply

* [PATCH v2 2/2] mfd: axp20x: Fix AXP806 access errors on cold boot
From: Chen-Yu Tsai @ 2017-01-03  3:54 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161214174053.qsm6umlgtdivevwt@sirena.org.uk>

On Thu, Dec 15, 2016 at 1:40 AM, Mark Brown <broonie@kernel.org> wrote:
> On Wed, Dec 14, 2016 at 09:52:31PM +0800, Chen-Yu Tsai wrote:
>
>> What this patch does is make sure the registers match, to guarantee
>> access, and then reinitialize the regmap cache to get rid of any
>> stale data.
>
> So what you're saying is that previous writes may have been ignored?

Sorry for the late reply.

Yes, any previous reads and writes may have been ignored. I'm not sure
if regmap cache prefetches any registers. Last I checked it didn't.

>> > If the chip has been reset then you'd want to reset the cache too.  I've
>> > no idea if that's needed here or not though, it depends what happens to
>> > the global state of the chip when this reconfiguration happens.
>
>> It is not a reset in the general sense. I suppose a better way would
>> be to do an explicit write to the register first, then initialize
>> the regmap. I'd have to export the write function from the RSB bus
>> driver first though.
>
> Surely just doing a write immediately after initializing the regmap
> would have the same effect?  That'd ensure that the hardware has the
> desired value before there are any other writes.  But I might be missing
> something here.

So I just tested this. Dropping both the regcache_sync_region() and
regmap_reinit_cache() is ok.

I'll send a revised patch.

ChenYu

^ permalink raw reply

* [PATCH 2/2] arm64:dt:ls1012a: Add TMU device tree support for LS1012A
From: Troy Jia @ 2017-01-03  3:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170102062553.GB20956@dragon>



> -----Original Message-----
> From: Shawn Guo [mailto:shawnguo at kernel.org]
> Sent: Monday, January 02, 2017 2:26 PM
> To: Troy Jia <hongtao.jia@nxp.com>
> Cc: rui.zhang at intel.com; edubezval at gmail.com; robh+dt at kernel.org; Scott Wood
> <scott.wood@nxp.com>; devicetree at vger.kernel.org; linux-
> kernel at vger.kernel.org; linux-arm-kernel at lists.infradead.org
> Subject: Re: [PATCH 2/2] arm64:dt:ls1012a: Add TMU device tree support for
> LS1012A
> 
> On Thu, Dec 08, 2016 at 11:28:26AM +0800, Jia Hongtao wrote:
> > Also add nodes and properties for thermal management support.
> >
> > Signed-off-by: Jia Hongtao <hongtao.jia@nxp.com>
> > ---
> > Depend on patch "[v3] arm64: Add DTS support for FSL's LS1012A SoC".
> > https://patchwork.kernel.org/patch/9462399/
> 
> Please send me the patch only after the dependent one is already accepted.
> 

I will hold the patch until the platform support is accepted.
Thanks.
-Hongtao.

^ permalink raw reply

* [PATCH 1/2] arm64:dt:ls1046a: Add TMU device tree support for LS1046A
From: Troy Jia @ 2017-01-03  3:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170102062433.GA20956@dragon>

Add Yuantian who is the owner of this patch set since next week.

> -----Original Message-----
> From: Shawn Guo [mailto:shawnguo at kernel.org]
> Sent: Monday, January 02, 2017 2:25 PM
> To: Troy Jia <hongtao.jia@nxp.com>
> Cc: rui.zhang at intel.com; edubezval at gmail.com; robh+dt at kernel.org; Scott Wood
> <scott.wood@nxp.com>; devicetree at vger.kernel.org; linux-
> kernel at vger.kernel.org; linux-arm-kernel at lists.infradead.org
> Subject: Re: [PATCH 1/2] arm64:dt:ls1046a: Add TMU device tree support for
> LS1046A
> 
> On Thu, Dec 08, 2016 at 11:28:25AM +0800, Jia Hongtao wrote:
> > Also add nodes and properties for thermal management support.
> >
> > Signed-off-by: Jia Hongtao <hongtao.jia@nxp.com>
> 
> "arm64: dts: ls1046a: ..." for subject prefix please.  Also, since we have ls1046a in
> prefix, the 'for LS1046A' is not needed.

Thanks. I will fix it.

> 
> > ---
> >  arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi | 79
> > ++++++++++++++++++++++++++
> >  1 file changed, 79 insertions(+)
> >
> > diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
> > b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
> > index 38806ca..40604e9 100644
> > --- a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
> > +++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
> > @@ -45,6 +45,8 @@
> >   */
> >
> >  #include <dt-bindings/interrupt-controller/arm-gic.h>
> > +#include <dt-bindings/thermal/thermal.h>
> > +
> 
> Unneeded newline.

Got it.

> 
> >
> >  / {
> >  	compatible = "fsl,ls1046a";
> > @@ -67,6 +69,7 @@
> >  			clocks = <&clockgen 1 0>;
> >  			next-level-cache = <&l2>;
> >  			cpu-idle-states = <&CPU_PH20>;
> > +			#cooling-cells = <2>;
> >  		};
> >
> >  		cpu1: cpu at 1 {
> > @@ -279,6 +282,82 @@
> >  			clocks = <&sysclk>;
> >  		};
> >
> > +		tmu: tmu at 1f00000 {
> > +			compatible = "fsl,qoriq-tmu";
> > +			reg = <0x0 0x1f00000 0x0 0x10000>;
> > +			interrupts = <0 33 0x4>;
> > +			fsl,tmu-range = <0xb0000 0x9002a 0x6004c 0x30062>;
> > +			fsl,tmu-calibration = <0x00000000 0x00000026
> > +					       0x00000001 0x0000002d
> > +					       0x00000002 0x00000032
> > +					       0x00000003 0x00000039
> > +					       0x00000004 0x0000003f
> > +					       0x00000005 0x00000046
> > +					       0x00000006 0x0000004d
> > +					       0x00000007 0x00000054
> > +					       0x00000008 0x0000005a
> > +					       0x00000009 0x00000061
> > +					       0x0000000a 0x0000006a
> > +					       0x0000000b 0x00000071
> > +
> 
> Instead of a newline, can we have a single line comment here to tell how these
> calibration data is grouped?

Each group represent one temperature range. It's a good idea to add comment here.
Could I just add one comment like below to clarify all four groups?
/* Each calibration data group represent one temperature range. There are four ranges in total */

> 
> > +					       0x00010000 0x00000025
> > +					       0x00010001 0x0000002c
> > +					       0x00010002 0x00000035
> > +					       0x00010003 0x0000003d
> > +					       0x00010004 0x00000045
> > +					       0x00010005 0x0000004e
> > +					       0x00010006 0x00000057
> > +					       0x00010007 0x00000061
> > +					       0x00010008 0x0000006b
> > +					       0x00010009 0x00000076
> > +
> > +					       0x00020000 0x00000029
> > +					       0x00020001 0x00000033
> > +					       0x00020002 0x0000003d
> > +					       0x00020003 0x00000049
> > +					       0x00020004 0x00000056
> > +					       0x00020005 0x00000061
> > +					       0x00020006 0x0000006d
> > +
> > +					       0x00030000 0x00000021
> > +					       0x00030001 0x0000002a
> > +					       0x00030002 0x0000003c
> > +					       0x00030003 0x0000004e>;
> > +			big-endian;
> > +			#thermal-sensor-cells = <1>;
> > +		};
> > +
> > +		thermal-zones {
> > +			cpu_thermal: cpu-thermal {
> > +				polling-delay-passive = <1000>;
> > +				polling-delay = <5000>;
> > +
> 
> We usually do not have newline between properties but nodes, or between
> property list and child node.

I just follow the style of thermal binding of
Documentation/devicetree/bindings/thermal/thermal.txt.

> 
> > +				thermal-sensors = <&tmu 3>;
> > +
> > +				trips {
> > +					cpu_alert: cpu-alert {
> > +						temperature = <85000>;
> > +						hysteresis = <2000>;
> > +						type = "passive";
> > +					};
> 
> Have a newline here.

Also follow the thermal binding.

-Hongtao.

> 
> > +					cpu_crit: cpu-crit {
> > +						temperature = <95000>;
> > +						hysteresis = <2000>;
> > +						type = "critical";
> > +					};
> > +				};
> > +
> > +				cooling-maps {
> > +					map0 {
> > +						trip = <&cpu_alert>;
> > +						cooling-device =
> > +							<&cpu0
> THERMAL_NO_LIMIT
> > +							THERMAL_NO_LIMIT>;
> > +					};
> > +				};
> > +			};
> > +		};
> > +
> >  		dspi: dspi at 2100000 {
> >  			compatible = "fsl,ls1021a-v1.0-dspi";
> >  			#address-cells = <1>;
> > --
> > 2.1.0.27.g96db324
> >
> >
> > _______________________________________________
> > linux-arm-kernel mailing list
> > linux-arm-kernel at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* [PATCH] dmaengine: pl330: Fix runtime PM support for terminated transfers
From: Vinod Koul @ 2017-01-03  3:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1481884751-21411-1-git-send-email-m.szyprowski@samsung.com>

On Fri, Dec 16, 2016 at 11:39:11AM +0100, Marek Szyprowski wrote:
> PL330 DMA engine driver is leaking a runtime reference after any terminated
> DMA transactions. This patch fixes this issue by tracking runtime PM state
> of the device and making additional call to pm_runtime_put() in terminate_all
> callback if needed.

Applied now

-- 
~Vinod

^ permalink raw reply

* [PATCH] MAINTAINERS: dmaengine: Update + Hand over the at_hdmac driver to Ludovic
From: Vinod Koul @ 2017-01-03  3:43 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170102164208.6038-1-nicolas.ferre@atmel.com>

On Mon, Jan 02, 2017 at 05:42:08PM +0100, Nicolas Ferre wrote:
> Hand over the Microchip / Atmel DMA driver handled by at_hdmac driver
> to Ludovic who is responsible for the newer at_xdmac driver as well.
> Also update the entry name and position to follow company changes.

Applied now

-- 
~Vinod

^ permalink raw reply

* [PATCH v19 4/4] soc: mediatek: Add Mediatek CMDQ helper
From: HS Liao @ 2017-01-03  3:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1483412751-28690-1-git-send-email-hs.liao@mediatek.com>

Add Mediatek CMDQ helper to create CMDQ packet and assemble GCE op code.

Signed-off-by: HS Liao <hs.liao@mediatek.com>
---
 drivers/soc/mediatek/Kconfig           |  12 ++
 drivers/soc/mediatek/Makefile          |   1 +
 drivers/soc/mediatek/mtk-cmdq-helper.c | 310 +++++++++++++++++++++++++++++++++
 include/linux/soc/mediatek/mtk-cmdq.h  | 174 ++++++++++++++++++
 4 files changed, 497 insertions(+)
 create mode 100644 drivers/soc/mediatek/mtk-cmdq-helper.c
 create mode 100644 include/linux/soc/mediatek/mtk-cmdq.h

diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig
index 609bb34..2f145d8 100644
--- a/drivers/soc/mediatek/Kconfig
+++ b/drivers/soc/mediatek/Kconfig
@@ -1,6 +1,18 @@
 #
 # MediaTek SoC drivers
 #
+config MTK_CMDQ
+	bool "MediaTek CMDQ Support"
+	depends on ARM64 && ( ARCH_MEDIATEK || COMPILE_TEST )
+	select MAILBOX
+	select MTK_CMDQ_MBOX
+	select MTK_INFRACFG
+	help
+	  Say yes here to add support for the MediaTek Command Queue (CMDQ)
+	  driver. The CMDQ is used to help read/write registers with critical
+	  time limitation, such as updating display configuration during the
+	  vblank.
+
 config MTK_INFRACFG
 	bool "MediaTek INFRACFG Support"
 	depends on ARCH_MEDIATEK || COMPILE_TEST
diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile
index 12998b0..64ce5ee 100644
--- a/drivers/soc/mediatek/Makefile
+++ b/drivers/soc/mediatek/Makefile
@@ -1,3 +1,4 @@
+obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq-helper.o
 obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o
 obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o
 obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o
diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c
new file mode 100644
index 0000000..7809e65
--- /dev/null
+++ b/drivers/soc/mediatek/mtk-cmdq-helper.c
@@ -0,0 +1,310 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/completion.h>
+#include <linux/errno.h>
+#include <linux/of_address.h>
+#include <linux/soc/mediatek/mtk-cmdq.h>
+
+#define CMDQ_SUBSYS_SHIFT	16
+#define CMDQ_ARG_A_WRITE_MASK	0xffff
+#define CMDQ_WRITE_ENABLE_MASK	BIT(0)
+#define CMDQ_EOC_IRQ_EN		BIT(0)
+#define CMDQ_EOC_CMD		((u64)((CMDQ_CODE_EOC << CMDQ_OP_CODE_SHIFT)) \
+				<< 32 | CMDQ_EOC_IRQ_EN)
+
+struct cmdq_subsys {
+	u32	base;
+	int	id;
+};
+
+static const struct cmdq_subsys gce_subsys[] = {
+	{0x1400, 1},
+	{0x1401, 2},
+	{0x1402, 3},
+};
+
+static int cmdq_subsys_base_to_id(u32 base)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(gce_subsys); i++)
+		if (gce_subsys[i].base == base)
+			return gce_subsys[i].id;
+	return -EFAULT;
+}
+
+static int cmdq_pkt_realloc_cmd_buffer(struct cmdq_pkt *pkt, size_t size)
+{
+	void *new_buf;
+
+	new_buf = krealloc(pkt->va_base, size, GFP_KERNEL | __GFP_ZERO);
+	if (!new_buf)
+		return -ENOMEM;
+	pkt->va_base = new_buf;
+	pkt->buf_size = size;
+	return 0;
+}
+
+struct cmdq_base *cmdq_register_device(struct device *dev)
+{
+	struct cmdq_base *cmdq_base;
+	struct resource res;
+	int subsys;
+	u32 base;
+
+	if (of_address_to_resource(dev->of_node, 0, &res))
+		return NULL;
+	base = (u32)res.start;
+
+	subsys = cmdq_subsys_base_to_id(base >> 16);
+	if (subsys < 0)
+		return NULL;
+
+	cmdq_base = devm_kmalloc(dev, sizeof(*cmdq_base), GFP_KERNEL);
+	if (!cmdq_base)
+		return NULL;
+	cmdq_base->subsys = subsys;
+	cmdq_base->base = base;
+
+	return cmdq_base;
+}
+EXPORT_SYMBOL(cmdq_register_device);
+
+struct cmdq_client *cmdq_mbox_create(struct device *dev, int index)
+{
+	struct cmdq_client *client;
+
+	client = kzalloc(sizeof(*client), GFP_KERNEL);
+	client->client.dev = dev;
+	client->client.tx_block = false;
+	client->chan = mbox_request_channel(&client->client, index);
+	return client;
+}
+EXPORT_SYMBOL(cmdq_mbox_create);
+
+void cmdq_mbox_destroy(struct cmdq_client *client)
+{
+	mbox_free_channel(client->chan);
+	kfree(client);
+}
+EXPORT_SYMBOL(cmdq_mbox_destroy);
+
+int cmdq_pkt_create(struct cmdq_pkt **pkt_ptr)
+{
+	struct cmdq_pkt *pkt;
+	int err;
+
+	pkt = kzalloc(sizeof(*pkt), GFP_KERNEL);
+	if (!pkt)
+		return -ENOMEM;
+	err = cmdq_pkt_realloc_cmd_buffer(pkt, PAGE_SIZE);
+	if (err < 0) {
+		kfree(pkt);
+		return err;
+	}
+	*pkt_ptr = pkt;
+	return 0;
+}
+EXPORT_SYMBOL(cmdq_pkt_create);
+
+void cmdq_pkt_destroy(struct cmdq_pkt *pkt)
+{
+	kfree(pkt->va_base);
+	kfree(pkt);
+}
+EXPORT_SYMBOL(cmdq_pkt_destroy);
+
+static bool cmdq_pkt_is_finalized(struct cmdq_pkt *pkt)
+{
+	u64 *expect_eoc;
+
+	if (pkt->cmd_buf_size < CMDQ_INST_SIZE << 1)
+		return false;
+
+	expect_eoc = pkt->va_base + pkt->cmd_buf_size - (CMDQ_INST_SIZE << 1);
+	if (*expect_eoc == CMDQ_EOC_CMD)
+		return true;
+
+	return false;
+}
+
+static int cmdq_pkt_append_command(struct cmdq_pkt *pkt, enum cmdq_code code,
+				   u32 arg_a, u32 arg_b)
+{
+	u64 *cmd_ptr;
+	int err;
+
+	if (WARN_ON(cmdq_pkt_is_finalized(pkt)))
+		return -EBUSY;
+	if (unlikely(pkt->cmd_buf_size + CMDQ_INST_SIZE > pkt->buf_size)) {
+		err = cmdq_pkt_realloc_cmd_buffer(pkt, pkt->buf_size << 1);
+		if (err < 0)
+			return err;
+	}
+	cmd_ptr = pkt->va_base + pkt->cmd_buf_size;
+	(*cmd_ptr) = (u64)((code << CMDQ_OP_CODE_SHIFT) | arg_a) << 32 | arg_b;
+	pkt->cmd_buf_size += CMDQ_INST_SIZE;
+	return 0;
+}
+
+int cmdq_pkt_write(struct cmdq_pkt *pkt, u32 value, struct cmdq_base *base,
+		   u32 offset)
+{
+	u32 arg_a = ((base->base + offset) & CMDQ_ARG_A_WRITE_MASK) |
+		    (base->subsys << CMDQ_SUBSYS_SHIFT);
+	return cmdq_pkt_append_command(pkt, CMDQ_CODE_WRITE, arg_a, value);
+}
+EXPORT_SYMBOL(cmdq_pkt_write);
+
+int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u32 value,
+			struct cmdq_base *base, u32 offset, u32 mask)
+{
+	u32 offset_mask = offset;
+	int err;
+
+	if (mask != 0xffffffff) {
+		err = cmdq_pkt_append_command(pkt, CMDQ_CODE_MASK, 0, ~mask);
+		if (err < 0)
+			return err;
+		offset_mask |= CMDQ_WRITE_ENABLE_MASK;
+	}
+	return cmdq_pkt_write(pkt, value, base, offset_mask);
+}
+EXPORT_SYMBOL(cmdq_pkt_write_mask);
+
+static const u32 cmdq_event_value[CMDQ_MAX_EVENT] = {
+	/* Display start of frame(SOF) events */
+	[CMDQ_EVENT_DISP_OVL0_SOF] = 11,
+	[CMDQ_EVENT_DISP_OVL1_SOF] = 12,
+	[CMDQ_EVENT_DISP_RDMA0_SOF] = 13,
+	[CMDQ_EVENT_DISP_RDMA1_SOF] = 14,
+	[CMDQ_EVENT_DISP_RDMA2_SOF] = 15,
+	[CMDQ_EVENT_DISP_WDMA0_SOF] = 16,
+	[CMDQ_EVENT_DISP_WDMA1_SOF] = 17,
+	/* Display end of frame(EOF) events */
+	[CMDQ_EVENT_DISP_OVL0_EOF] = 39,
+	[CMDQ_EVENT_DISP_OVL1_EOF] = 40,
+	[CMDQ_EVENT_DISP_RDMA0_EOF] = 41,
+	[CMDQ_EVENT_DISP_RDMA1_EOF] = 42,
+	[CMDQ_EVENT_DISP_RDMA2_EOF] = 43,
+	[CMDQ_EVENT_DISP_WDMA0_EOF] = 44,
+	[CMDQ_EVENT_DISP_WDMA1_EOF] = 45,
+	/* Mutex end of frame(EOF) events */
+	[CMDQ_EVENT_MUTEX0_STREAM_EOF] = 53,
+	[CMDQ_EVENT_MUTEX1_STREAM_EOF] = 54,
+	[CMDQ_EVENT_MUTEX2_STREAM_EOF] = 55,
+	[CMDQ_EVENT_MUTEX3_STREAM_EOF] = 56,
+	[CMDQ_EVENT_MUTEX4_STREAM_EOF] = 57,
+	/* Display underrun events */
+	[CMDQ_EVENT_DISP_RDMA0_UNDERRUN] = 63,
+	[CMDQ_EVENT_DISP_RDMA1_UNDERRUN] = 64,
+	[CMDQ_EVENT_DISP_RDMA2_UNDERRUN] = 65,
+};
+
+int cmdq_pkt_wfe(struct cmdq_pkt *pkt, enum cmdq_event event)
+{
+	u32 arg_b;
+
+	if (event >= CMDQ_MAX_EVENT || event < 0)
+		return -EINVAL;
+
+	/*
+	 * WFE arg_b
+	 * bit 0-11: wait value
+	 * bit 15: 1 - wait, 0 - no wait
+	 * bit 16-27: update value
+	 * bit 31: 1 - update, 0 - no update
+	 */
+	arg_b = CMDQ_WFE_UPDATE | CMDQ_WFE_WAIT | CMDQ_WFE_WAIT_VALUE;
+	return cmdq_pkt_append_command(pkt, CMDQ_CODE_WFE,
+			cmdq_event_value[event], arg_b);
+}
+EXPORT_SYMBOL(cmdq_pkt_wfe);
+
+int cmdq_pkt_clear_event(struct cmdq_pkt *pkt, enum cmdq_event event)
+{
+	if (event >= CMDQ_MAX_EVENT || event < 0)
+		return -EINVAL;
+
+	return cmdq_pkt_append_command(pkt, CMDQ_CODE_WFE,
+			cmdq_event_value[event], CMDQ_WFE_UPDATE);
+}
+EXPORT_SYMBOL(cmdq_pkt_clear_event);
+
+static int cmdq_pkt_finalize(struct cmdq_pkt *pkt)
+{
+	int err;
+
+	if (cmdq_pkt_is_finalized(pkt))
+		return 0;
+
+	/* insert EOC and generate IRQ for each command iteration */
+	err = cmdq_pkt_append_command(pkt, CMDQ_CODE_EOC, 0, CMDQ_EOC_IRQ_EN);
+	if (err < 0)
+		return err;
+
+	/* JUMP to end */
+	err = cmdq_pkt_append_command(pkt, CMDQ_CODE_JUMP, 0, CMDQ_JUMP_PASS);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+int cmdq_pkt_flush_async(struct cmdq_client *client, struct cmdq_pkt *pkt,
+			 cmdq_async_flush_cb cb, void *data)
+{
+	int err;
+
+	err = cmdq_pkt_finalize(pkt);
+	if (err < 0)
+		return err;
+
+	pkt->cb.cb = cb;
+	pkt->cb.data = data;
+
+	mbox_send_message(client->chan, pkt);
+	/* We can send next packet immediately, so just call txdone. */
+	mbox_client_txdone(client->chan, 0);
+
+	return 0;
+}
+EXPORT_SYMBOL(cmdq_pkt_flush_async);
+
+struct cmdq_flush_completion {
+	struct completion cmplt;
+	bool err;
+};
+
+static void cmdq_pkt_flush_cb(struct cmdq_cb_data data)
+{
+	struct cmdq_flush_completion *cmplt = data.data;
+
+	cmplt->err = data.err;
+	complete(&cmplt->cmplt);
+}
+
+int cmdq_pkt_flush(struct cmdq_client *client, struct cmdq_pkt *pkt)
+{
+	struct cmdq_flush_completion cmplt;
+	int err;
+
+	init_completion(&cmplt.cmplt);
+	err = cmdq_pkt_flush_async(client, pkt, cmdq_pkt_flush_cb, &cmplt);
+	if (err < 0)
+		return err;
+	wait_for_completion(&cmplt.cmplt);
+	return cmplt.err ? -EFAULT : 0;
+}
+EXPORT_SYMBOL(cmdq_pkt_flush);
diff --git a/include/linux/soc/mediatek/mtk-cmdq.h b/include/linux/soc/mediatek/mtk-cmdq.h
new file mode 100644
index 0000000..5b35d73
--- /dev/null
+++ b/include/linux/soc/mediatek/mtk-cmdq.h
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MTK_CMDQ_H__
+#define __MTK_CMDQ_H__
+
+#include <linux/mailbox_client.h>
+#include <linux/mailbox/mtk-cmdq-mailbox.h>
+
+/* display events in command queue(CMDQ) */
+enum cmdq_event {
+	/* Display start of frame(SOF) events */
+	CMDQ_EVENT_DISP_OVL0_SOF,
+	CMDQ_EVENT_DISP_OVL1_SOF,
+	CMDQ_EVENT_DISP_RDMA0_SOF,
+	CMDQ_EVENT_DISP_RDMA1_SOF,
+	CMDQ_EVENT_DISP_RDMA2_SOF,
+	CMDQ_EVENT_DISP_WDMA0_SOF,
+	CMDQ_EVENT_DISP_WDMA1_SOF,
+	/* Display end of frame(EOF) events */
+	CMDQ_EVENT_DISP_OVL0_EOF,
+	CMDQ_EVENT_DISP_OVL1_EOF,
+	CMDQ_EVENT_DISP_RDMA0_EOF,
+	CMDQ_EVENT_DISP_RDMA1_EOF,
+	CMDQ_EVENT_DISP_RDMA2_EOF,
+	CMDQ_EVENT_DISP_WDMA0_EOF,
+	CMDQ_EVENT_DISP_WDMA1_EOF,
+	/* Mutex end of frame(EOF) events */
+	CMDQ_EVENT_MUTEX0_STREAM_EOF,
+	CMDQ_EVENT_MUTEX1_STREAM_EOF,
+	CMDQ_EVENT_MUTEX2_STREAM_EOF,
+	CMDQ_EVENT_MUTEX3_STREAM_EOF,
+	CMDQ_EVENT_MUTEX4_STREAM_EOF,
+	/* Display underrun events */
+	CMDQ_EVENT_DISP_RDMA0_UNDERRUN,
+	CMDQ_EVENT_DISP_RDMA1_UNDERRUN,
+	CMDQ_EVENT_DISP_RDMA2_UNDERRUN,
+	/* Keep this at the end */
+	CMDQ_MAX_EVENT,
+};
+
+struct cmdq_pkt;
+
+struct cmdq_base {
+	int	subsys;
+	u32	base;
+};
+
+struct cmdq_client {
+	struct mbox_client client;
+	struct mbox_chan *chan;
+};
+
+/**
+ * cmdq_register_device() - register device which needs CMDQ
+ * @dev:	device for CMDQ to access its registers
+ *
+ * Return: cmdq_base pointer or NULL for failed
+ */
+struct cmdq_base *cmdq_register_device(struct device *dev);
+
+/**
+ * cmdq_mbox_create() - create CMDQ mailbox client and channel
+ * @dev:	device of CMDQ mailbox client
+ * @index:	index of CMDQ mailbox channel
+ *
+ * Return: CMDQ mailbox client pointer
+ */
+struct cmdq_client *cmdq_mbox_create(struct device *dev, int index);
+
+/**
+ * cmdq_mbox_destroy() - destroy CMDQ mailbox client and channel
+ * @client:	the CMDQ mailbox client
+ */
+void cmdq_mbox_destroy(struct cmdq_client *client);
+
+/**
+ * cmdq_pkt_create() - create a CMDQ packet
+ * @pkt_ptr:	CMDQ packet pointer to retrieve cmdq_pkt
+ *
+ * Return: 0 for success; else the error code is returned
+ */
+int cmdq_pkt_create(struct cmdq_pkt **pkt_ptr);
+
+/**
+ * cmdq_pkt_destroy() - destroy the CMDQ packet
+ * @pkt:	the CMDQ packet
+ */
+void cmdq_pkt_destroy(struct cmdq_pkt *pkt);
+
+/**
+ * cmdq_pkt_write() - append write command to the CMDQ packet
+ * @pkt:	the CMDQ packet
+ * @value:	the specified target register value
+ * @base:	the CMDQ base
+ * @offset:	register offset from module base
+ *
+ * Return: 0 for success; else the error code is returned
+ */
+int cmdq_pkt_write(struct cmdq_pkt *pkt, u32 value,
+		   struct cmdq_base *base, u32 offset);
+
+/**
+ * cmdq_pkt_write_mask() - append write command with mask to the CMDQ packet
+ * @pkt:	the CMDQ packet
+ * @value:	the specified target register value
+ * @base:	the CMDQ base
+ * @offset:	register offset from module base
+ * @mask:	the specified target register mask
+ *
+ * Return: 0 for success; else the error code is returned
+ */
+int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u32 value,
+			struct cmdq_base *base, u32 offset, u32 mask);
+
+/**
+ * cmdq_pkt_wfe() - append wait for event command to the CMDQ packet
+ * @pkt:	the CMDQ packet
+ * @event:	the desired event type to "wait and CLEAR"
+ *
+ * Return: 0 for success; else the error code is returned
+ */
+int cmdq_pkt_wfe(struct cmdq_pkt *pkt, enum cmdq_event event);
+
+/**
+ * cmdq_pkt_clear_event() - append clear event command to the CMDQ packet
+ * @pkt:	the CMDQ packet
+ * @event:	the desired event to be cleared
+ *
+ * Return: 0 for success; else the error code is returned
+ */
+int cmdq_pkt_clear_event(struct cmdq_pkt *pkt, enum cmdq_event event);
+
+/**
+ * cmdq_pkt_flush() - trigger CMDQ to execute the CMDQ packet
+ * @client:	the CMDQ mailbox client
+ * @pkt:	the CMDQ packet
+ *
+ * Return: 0 for success; else the error code is returned
+ *
+ * Trigger CMDQ to execute the CMDQ packet. Note that this is a
+ * synchronous flush function. When the function returned, the recorded
+ * commands have been done.
+ */
+int cmdq_pkt_flush(struct cmdq_client *client, struct cmdq_pkt *pkt);
+
+/**
+ * cmdq_pkt_flush_async() - trigger CMDQ to asynchronously execute the CMDQ
+ *                          packet and call back at the end of done packet
+ * @client:	the CMDQ mailbox client
+ * @pkt:	the CMDQ packet
+ * @cb:		called at the end of done packet
+ * @data:	this data will pass back to cb
+ *
+ * Return: 0 for success; else the error code is returned
+ *
+ * Trigger CMDQ to asynchronously execute the CMDQ packet and call back
+ * at the end of done packet. Note that this is an ASYNC function. When the
+ * function returned, it may or may not be finished.
+ */
+int cmdq_pkt_flush_async(struct cmdq_client *client, struct cmdq_pkt *pkt,
+			 cmdq_async_flush_cb cb, void *data);
+
+#endif	/* __MTK_CMDQ_H__ */
-- 
1.9.1

^ permalink raw reply related

* [PATCH v19 3/4] arm64: dts: mt8173: Add GCE node
From: HS Liao @ 2017-01-03  3:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1483412751-28690-1-git-send-email-hs.liao@mediatek.com>

This patch adds the device node of the GCE hardware for CMDQ module.

Signed-off-by: HS Liao <hs.liao@mediatek.com>
---
 arch/arm64/boot/dts/mediatek/mt8173.dtsi | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
index 12e7027..9f93447 100644
--- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
@@ -422,6 +422,16 @@
 			status = "disabled";
 		};
 
+		gce: gce at 10212000 {
+			compatible = "mediatek,mt8173-gce";
+			reg = <0 0x10212000 0 0x1000>;
+			interrupts = <GIC_SPI 135 IRQ_TYPE_LEVEL_LOW>;
+			clocks = <&infracfg CLK_INFRA_GCE>;
+			clock-names = "gce";
+
+			#mbox-cells = <2>;
+		};
+
 		mipi_tx0: mipi-dphy at 10215000 {
 			compatible = "mediatek,mt8173-mipi-tx";
 			reg = <0 0x10215000 0 0x1000>;
-- 
1.9.1

^ permalink raw reply related

* [PATCH v19 2/4] mailbox: mediatek: Add Mediatek CMDQ driver
From: HS Liao @ 2017-01-03  3:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1483412751-28690-1-git-send-email-hs.liao@mediatek.com>

This patch is first version of Mediatek Command Queue(CMDQ) driver. The
CMDQ is used to help write registers with critical time limitation,
such as updating display configuration during the vblank. It controls
Global Command Engine (GCE) hardware to achieve this requirement.
Currently, CMDQ only supports display related hardwares, but we expect
it can be extended to other hardwares for future requirements.

Signed-off-by: HS Liao <hs.liao@mediatek.com>
Signed-off-by: CK Hu <ck.hu@mediatek.com>
---
 drivers/mailbox/Kconfig                  |  10 +
 drivers/mailbox/Makefile                 |   2 +
 drivers/mailbox/mtk-cmdq-mailbox.c       | 596 +++++++++++++++++++++++++++++++
 include/linux/mailbox/mtk-cmdq-mailbox.h |  75 ++++
 4 files changed, 683 insertions(+)
 create mode 100644 drivers/mailbox/mtk-cmdq-mailbox.c
 create mode 100644 include/linux/mailbox/mtk-cmdq-mailbox.h

diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
index ceff415..9108dd4 100644
--- a/drivers/mailbox/Kconfig
+++ b/drivers/mailbox/Kconfig
@@ -152,4 +152,14 @@ config BCM_PDC_MBOX
 	  Mailbox implementation for the Broadcom PDC ring manager,
 	  which provides access to various offload engines on Broadcom
 	  SoCs. Say Y here if you want to use the Broadcom PDC.
+
+config MTK_CMDQ_MBOX
+	bool "MediaTek CMDQ Mailbox Support"
+	depends on ARM64 && ( ARCH_MEDIATEK || COMPILE_TEST )
+	select MTK_INFRACFG
+	help
+	  Say yes here to add support for the MediaTek Command Queue (CMDQ)
+	  mailbox driver. The CMDQ is used to help read/write registers with
+	  critical time limitation, such as updating display configuration
+	  during the vblank.
 endif
diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
index 7dde4f6..fad8965 100644
--- a/drivers/mailbox/Makefile
+++ b/drivers/mailbox/Makefile
@@ -31,3 +31,5 @@ obj-$(CONFIG_HI6220_MBOX)	+= hi6220-mailbox.o
 obj-$(CONFIG_BCM_PDC_MBOX)	+= bcm-pdc-mailbox.o
 
 obj-$(CONFIG_TEGRA_HSP_MBOX)	+= tegra-hsp.o
+
+obj-$(CONFIG_MTK_CMDQ_MBOX)	+= mtk-cmdq-mailbox.o
diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c
new file mode 100644
index 0000000..747bcd3
--- /dev/null
+++ b/drivers/mailbox/mtk-cmdq-mailbox.c
@@ -0,0 +1,596 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/mailbox_controller.h>
+#include <linux/mailbox/mtk-cmdq-mailbox.h>
+#include <linux/timer.h>
+
+#define CMDQ_THR_MAX_COUNT		3 /* main, sub, general(misc) */
+#define CMDQ_OP_CODE_MASK		(0xff << CMDQ_OP_CODE_SHIFT)
+#define CMDQ_TIMEOUT_MS			1000
+#define CMDQ_IRQ_MASK			0xffff
+#define CMDQ_NUM_CMD(t)			(t->cmd_buf_size / CMDQ_INST_SIZE)
+
+#define CMDQ_CURR_IRQ_STATUS		0x10
+#define CMDQ_THR_SLOT_CYCLES		0x30
+
+#define CMDQ_THR_BASE			0x100
+#define CMDQ_THR_SIZE			0x80
+#define CMDQ_THR_WARM_RESET		0x00
+#define CMDQ_THR_ENABLE_TASK		0x04
+#define CMDQ_THR_SUSPEND_TASK		0x08
+#define CMDQ_THR_CURR_STATUS		0x0c
+#define CMDQ_THR_IRQ_STATUS		0x10
+#define CMDQ_THR_IRQ_ENABLE		0x14
+#define CMDQ_THR_CURR_ADDR		0x20
+#define CMDQ_THR_END_ADDR		0x24
+#define CMDQ_THR_WAIT_TOKEN		0x30
+
+#define CMDQ_THR_ENABLED		0x1
+#define CMDQ_THR_DISABLED		0x0
+#define CMDQ_THR_SUSPEND		0x1
+#define CMDQ_THR_RESUME			0x0
+#define CMDQ_THR_STATUS_SUSPENDED	BIT(1)
+#define CMDQ_THR_DO_WARM_RESET		BIT(0)
+#define CMDQ_THR_ACTIVE_SLOT_CYCLES	0x3200
+#define CMDQ_THR_IRQ_DONE		0x1
+#define CMDQ_THR_IRQ_ERROR		0x12
+#define CMDQ_THR_IRQ_EN			(CMDQ_THR_IRQ_ERROR | CMDQ_THR_IRQ_DONE)
+#define CMDQ_THR_IS_WAITING		BIT(31)
+
+#define CMDQ_JUMP_BY_OFFSET		0x10000000
+#define CMDQ_JUMP_BY_PA			0x10000001
+
+struct cmdq_thread {
+	struct mbox_chan	*chan;
+	void __iomem		*base;
+	struct list_head	task_busy_list;
+	struct timer_list	timeout;
+	bool			atomic_exec;
+};
+
+struct cmdq_task {
+	struct cmdq		*cmdq;
+	struct list_head	list_entry;
+	dma_addr_t		pa_base;
+	struct cmdq_thread	*thread;
+	struct cmdq_pkt		*pkt; /* the packet sent from mailbox client */
+};
+
+struct cmdq {
+	struct mbox_controller	mbox;
+	void __iomem		*base;
+	u32			irq;
+	struct cmdq_thread	thread[CMDQ_THR_MAX_COUNT];
+	struct clk		*clock;
+	bool			suspended;
+};
+
+static int cmdq_thread_suspend(struct cmdq *cmdq, struct cmdq_thread *thread)
+{
+	u32 status;
+
+	writel(CMDQ_THR_SUSPEND, thread->base + CMDQ_THR_SUSPEND_TASK);
+
+	/* If already disabled, treat as suspended successful. */
+	if (!(readl(thread->base + CMDQ_THR_ENABLE_TASK) & CMDQ_THR_ENABLED))
+		return 0;
+
+	if (readl_poll_timeout_atomic(thread->base + CMDQ_THR_CURR_STATUS,
+			status, status & CMDQ_THR_STATUS_SUSPENDED, 0, 10)) {
+		dev_err(cmdq->mbox.dev, "suspend GCE thread 0x%x failed\n",
+			(u32)(thread->base - cmdq->base));
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static void cmdq_thread_resume(struct cmdq_thread *thread)
+{
+	writel(CMDQ_THR_RESUME, thread->base + CMDQ_THR_SUSPEND_TASK);
+}
+
+static int cmdq_thread_reset(struct cmdq *cmdq, struct cmdq_thread *thread)
+{
+	u32 warm_reset;
+
+	writel(CMDQ_THR_DO_WARM_RESET, thread->base + CMDQ_THR_WARM_RESET);
+	if (readl_poll_timeout_atomic(thread->base + CMDQ_THR_WARM_RESET,
+			warm_reset, !(warm_reset & CMDQ_THR_DO_WARM_RESET),
+			0, 10)) {
+		dev_err(cmdq->mbox.dev, "reset GCE thread 0x%x failed\n",
+			(u32)(thread->base - cmdq->base));
+		return -EFAULT;
+	}
+	writel(CMDQ_THR_ACTIVE_SLOT_CYCLES, cmdq->base + CMDQ_THR_SLOT_CYCLES);
+	return 0;
+}
+
+static void cmdq_thread_disable(struct cmdq *cmdq, struct cmdq_thread *thread)
+{
+	cmdq_thread_reset(cmdq, thread);
+	writel(CMDQ_THR_DISABLED, thread->base + CMDQ_THR_ENABLE_TASK);
+}
+
+/* notify GCE to re-fetch commands by setting GCE thread PC */
+static void cmdq_thread_invalidate_fetched_data(struct cmdq_thread *thread)
+{
+	writel(readl(thread->base + CMDQ_THR_CURR_ADDR),
+	       thread->base + CMDQ_THR_CURR_ADDR);
+}
+
+static void cmdq_task_insert_into_thread(struct cmdq_task *task)
+{
+	struct device *dev = task->cmdq->mbox.dev;
+	struct cmdq_thread *thread = task->thread;
+	struct cmdq_task *prev_task = list_last_entry(
+			&thread->task_busy_list, typeof(*task), list_entry);
+	u64 *prev_task_base = prev_task->pkt->va_base;
+
+	/* let previous task jump to this task */
+	dma_sync_single_for_cpu(dev, prev_task->pa_base,
+				prev_task->pkt->cmd_buf_size, DMA_TO_DEVICE);
+	prev_task_base[CMDQ_NUM_CMD(prev_task->pkt) - 1] =
+		(u64)CMDQ_JUMP_BY_PA << 32 | task->pa_base;
+	dma_sync_single_for_device(dev, prev_task->pa_base,
+				   prev_task->pkt->cmd_buf_size, DMA_TO_DEVICE);
+
+	cmdq_thread_invalidate_fetched_data(thread);
+}
+
+static bool cmdq_command_is_wfe(u64 cmd)
+{
+	u64 wfe_option = CMDQ_WFE_UPDATE | CMDQ_WFE_WAIT | CMDQ_WFE_WAIT_VALUE;
+	u64 wfe_op = (u64)(CMDQ_CODE_WFE << CMDQ_OP_CODE_SHIFT) << 32;
+	u64 wfe_mask = (u64)CMDQ_OP_CODE_MASK << 32 | 0xffffffff;
+
+	return ((cmd & wfe_mask) == (wfe_op | wfe_option));
+}
+
+/* we assume tasks in the same display GCE thread are waiting the same event. */
+static void cmdq_task_remove_wfe(struct cmdq_task *task)
+{
+	struct device *dev = task->cmdq->mbox.dev;
+	u64 *base = task->pkt->va_base;
+	int i;
+
+	dma_sync_single_for_cpu(dev, task->pa_base, task->pkt->cmd_buf_size,
+				DMA_TO_DEVICE);
+	for (i = 0; i < CMDQ_NUM_CMD(task->pkt); i++)
+		if (cmdq_command_is_wfe(base[i]))
+			base[i] = (u64)CMDQ_JUMP_BY_OFFSET << 32 |
+				  CMDQ_JUMP_PASS;
+	dma_sync_single_for_device(dev, task->pa_base, task->pkt->cmd_buf_size,
+				   DMA_TO_DEVICE);
+}
+
+static bool cmdq_thread_is_in_wfe(struct cmdq_thread *thread)
+{
+	return readl(thread->base + CMDQ_THR_WAIT_TOKEN) & CMDQ_THR_IS_WAITING;
+}
+
+static void cmdq_thread_wait_end(struct cmdq_thread *thread,
+				 unsigned long end_pa)
+{
+	struct device *dev = thread->chan->mbox->dev;
+	unsigned long curr_pa;
+
+	if (readl_poll_timeout_atomic(thread->base + CMDQ_THR_CURR_ADDR,
+			curr_pa, curr_pa == end_pa, 1, 20))
+		dev_err(dev, "GCE thread cannot run to end.\n");
+}
+
+static void cmdq_task_exec(struct cmdq_pkt *pkt, struct cmdq_thread *thread)
+{
+	struct cmdq *cmdq;
+	struct cmdq_task *task;
+	unsigned long curr_pa, end_pa;
+
+	cmdq = dev_get_drvdata(thread->chan->mbox->dev);
+
+	/* Client should not flush new tasks if suspended. */
+	WARN_ON(cmdq->suspended);
+
+	task = kzalloc(sizeof(*task), GFP_ATOMIC);
+	task->cmdq = cmdq;
+	INIT_LIST_HEAD(&task->list_entry);
+	task->pa_base = dma_map_single(cmdq->mbox.dev, pkt->va_base,
+				       pkt->cmd_buf_size, DMA_TO_DEVICE);
+	task->thread = thread;
+	task->pkt = pkt;
+
+	if (list_empty(&thread->task_busy_list)) {
+		WARN_ON(clk_enable(cmdq->clock) < 0);
+		WARN_ON(cmdq_thread_reset(cmdq, thread) < 0);
+
+		writel(task->pa_base, thread->base + CMDQ_THR_CURR_ADDR);
+		writel(task->pa_base + pkt->cmd_buf_size,
+		       thread->base + CMDQ_THR_END_ADDR);
+		writel(CMDQ_THR_IRQ_EN, thread->base + CMDQ_THR_IRQ_ENABLE);
+		writel(CMDQ_THR_ENABLED, thread->base + CMDQ_THR_ENABLE_TASK);
+
+		mod_timer(&thread->timeout,
+			  jiffies + msecs_to_jiffies(CMDQ_TIMEOUT_MS));
+	} else {
+		WARN_ON(cmdq_thread_suspend(cmdq, thread) < 0);
+		curr_pa = readl(thread->base + CMDQ_THR_CURR_ADDR);
+		end_pa = readl(thread->base + CMDQ_THR_END_ADDR);
+
+		/*
+		 * Atomic execution should remove the following wfe, i.e. only
+		 * wait event at first task, and prevent to pause when running.
+		 */
+		if (thread->atomic_exec) {
+			/* GCE is executing if command is not WFE */
+			if (!cmdq_thread_is_in_wfe(thread)) {
+				cmdq_thread_resume(thread);
+				cmdq_thread_wait_end(thread, end_pa);
+				WARN_ON(cmdq_thread_suspend(cmdq, thread) < 0);
+				/* set to this task directly */
+				writel(task->pa_base,
+				       thread->base + CMDQ_THR_CURR_ADDR);
+			} else {
+				cmdq_task_insert_into_thread(task);
+				cmdq_task_remove_wfe(task);
+				smp_mb(); /* modify jump before enable thread */
+			}
+		} else {
+			/* check boundary */
+			if (curr_pa == end_pa - CMDQ_INST_SIZE ||
+			    curr_pa == end_pa) {
+				/* set to this task directly */
+				writel(task->pa_base,
+				       thread->base + CMDQ_THR_CURR_ADDR);
+			} else {
+				cmdq_task_insert_into_thread(task);
+				smp_mb(); /* modify jump before enable thread */
+			}
+		}
+		writel(task->pa_base + pkt->cmd_buf_size,
+		       thread->base + CMDQ_THR_END_ADDR);
+		cmdq_thread_resume(thread);
+	}
+	list_move_tail(&task->list_entry, &thread->task_busy_list);
+}
+
+static void cmdq_task_exec_done(struct cmdq_task *task, bool err)
+{
+	struct device *dev = task->cmdq->mbox.dev;
+	struct cmdq_cb_data cmdq_cb_data;
+
+	dma_unmap_single(dev, task->pa_base, task->pkt->cmd_buf_size,
+			 DMA_TO_DEVICE);
+	if (task->pkt->cb.cb) {
+		cmdq_cb_data.err = err;
+		cmdq_cb_data.data = task->pkt->cb.data;
+		task->pkt->cb.cb(cmdq_cb_data);
+	}
+	list_del(&task->list_entry);
+}
+
+static void cmdq_task_handle_error(struct cmdq_task *task)
+{
+	struct cmdq_thread *thread = task->thread;
+	struct cmdq_task *next_task;
+
+	dev_err(task->cmdq->mbox.dev, "task 0x%p error\n", task);
+	WARN_ON(cmdq_thread_suspend(task->cmdq, thread) < 0);
+	next_task = list_first_entry_or_null(&thread->task_busy_list,
+			struct cmdq_task, list_entry);
+	if (next_task)
+		writel(next_task->pa_base, thread->base + CMDQ_THR_CURR_ADDR);
+	cmdq_thread_resume(thread);
+}
+
+static void cmdq_thread_irq_handler(struct cmdq *cmdq,
+				    struct cmdq_thread *thread)
+{
+	struct cmdq_task *task, *tmp, *curr_task = NULL;
+	u32 curr_pa, irq_flag, task_end_pa;
+	bool err;
+
+	irq_flag = readl(thread->base + CMDQ_THR_IRQ_STATUS);
+	writel(~irq_flag, thread->base + CMDQ_THR_IRQ_STATUS);
+
+	/*
+	 * When ISR call this function, another CPU core could run
+	 * "release task" right before we acquire the spin lock, and thus
+	 * reset / disable this GCE thread, so we need to check the enable
+	 * bit of this GCE thread.
+	 */
+	if (!(readl(thread->base + CMDQ_THR_ENABLE_TASK) & CMDQ_THR_ENABLED))
+		return;
+
+	if (irq_flag & CMDQ_THR_IRQ_ERROR)
+		err = true;
+	else if (irq_flag & CMDQ_THR_IRQ_DONE)
+		err = false;
+	else
+		return;
+
+	curr_pa = readl(thread->base + CMDQ_THR_CURR_ADDR);
+
+	list_for_each_entry_safe(task, tmp, &thread->task_busy_list,
+				 list_entry) {
+		task_end_pa = task->pa_base + task->pkt->cmd_buf_size;
+		if (curr_pa >= task->pa_base && curr_pa < task_end_pa)
+			curr_task = task;
+
+		if (!curr_task || curr_pa == task_end_pa - CMDQ_INST_SIZE) {
+			cmdq_task_exec_done(task, false);
+			kfree(task);
+		} else if (err) {
+			cmdq_task_exec_done(task, true);
+			cmdq_task_handle_error(curr_task);
+			kfree(task);
+		}
+
+		if (curr_task)
+			break;
+	}
+
+	if (list_empty(&thread->task_busy_list)) {
+		cmdq_thread_disable(cmdq, thread);
+		clk_disable(cmdq->clock);
+	} else {
+		mod_timer(&thread->timeout,
+			  jiffies + msecs_to_jiffies(CMDQ_TIMEOUT_MS));
+	}
+}
+
+static irqreturn_t cmdq_irq_handler(int irq, void *dev)
+{
+	struct cmdq *cmdq = dev;
+	unsigned long irq_status, flags = 0L;
+	int bit;
+
+	irq_status = readl(cmdq->base + CMDQ_CURR_IRQ_STATUS) & CMDQ_IRQ_MASK;
+	if (!(irq_status ^ CMDQ_IRQ_MASK))
+		return IRQ_NONE;
+
+	for_each_clear_bit(bit, &irq_status, fls(CMDQ_IRQ_MASK)) {
+		struct cmdq_thread *thread = &cmdq->thread[bit];
+
+		spin_lock_irqsave(&thread->chan->lock, flags);
+		cmdq_thread_irq_handler(cmdq, thread);
+		spin_unlock_irqrestore(&thread->chan->lock, flags);
+	}
+	return IRQ_HANDLED;
+}
+
+static void cmdq_thread_handle_timeout(unsigned long data)
+{
+	struct cmdq_thread *thread = (struct cmdq_thread *)data;
+	struct cmdq *cmdq = container_of(thread->chan->mbox, struct cmdq, mbox);
+	struct cmdq_task *task, *tmp;
+	unsigned long flags;
+
+	spin_lock_irqsave(&thread->chan->lock, flags);
+	WARN_ON(cmdq_thread_suspend(cmdq, thread) < 0);
+
+	/*
+	 * Although IRQ is disabled, GCE continues to execute.
+	 * It may have pending IRQ before GCE thread is suspended,
+	 * so check this condition again.
+	 */
+	cmdq_thread_irq_handler(cmdq, thread);
+
+	if (list_empty(&thread->task_busy_list)) {
+		cmdq_thread_resume(thread);
+		spin_unlock_irqrestore(&thread->chan->lock, flags);
+		return;
+	}
+
+	dev_err(cmdq->mbox.dev, "timeout\n");
+	list_for_each_entry_safe(task, tmp, &thread->task_busy_list,
+				 list_entry) {
+		cmdq_task_exec_done(task, true);
+		kfree(task);
+	}
+
+	cmdq_thread_resume(thread);
+	cmdq_thread_disable(cmdq, thread);
+	clk_disable(cmdq->clock);
+	spin_unlock_irqrestore(&thread->chan->lock, flags);
+}
+
+static int cmdq_suspend(struct device *dev)
+{
+	struct cmdq *cmdq = dev_get_drvdata(dev);
+	struct cmdq_thread *thread;
+	int i;
+	bool task_running = false;
+
+	cmdq->suspended = true;
+
+	for (i = 0; i < ARRAY_SIZE(cmdq->thread); i++) {
+		thread = &cmdq->thread[i];
+		if (!list_empty(&thread->task_busy_list)) {
+			task_running = true;
+			break;
+		}
+	}
+
+	if (task_running)
+		dev_warn(dev, "exist running task(s) in suspend\n");
+
+	clk_unprepare(cmdq->clock);
+	return 0;
+}
+
+static int cmdq_resume(struct device *dev)
+{
+	struct cmdq *cmdq = dev_get_drvdata(dev);
+
+	WARN_ON(clk_prepare(cmdq->clock) < 0);
+	cmdq->suspended = false;
+	return 0;
+}
+
+static int cmdq_remove(struct platform_device *pdev)
+{
+	struct cmdq *cmdq = platform_get_drvdata(pdev);
+
+	mbox_controller_unregister(&cmdq->mbox);
+	clk_unprepare(cmdq->clock);
+	return 0;
+}
+
+static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data)
+{
+	cmdq_task_exec(data, chan->con_priv);
+	return 0;
+}
+
+static int cmdq_mbox_startup(struct mbox_chan *chan)
+{
+	return 0;
+}
+
+static void cmdq_mbox_shutdown(struct mbox_chan *chan)
+{
+}
+
+static bool cmdq_mbox_last_tx_done(struct mbox_chan *chan)
+{
+	return true;
+}
+
+static const struct mbox_chan_ops cmdq_mbox_chan_ops = {
+	.send_data = cmdq_mbox_send_data,
+	.startup = cmdq_mbox_startup,
+	.shutdown = cmdq_mbox_shutdown,
+	.last_tx_done = cmdq_mbox_last_tx_done,
+};
+
+static struct mbox_chan *cmdq_xlate(struct mbox_controller *mbox,
+		const struct of_phandle_args *sp)
+{
+	int ind = sp->args[0];
+	struct cmdq_thread *thread;
+
+	if (ind >= mbox->num_chans)
+		return ERR_PTR(-EINVAL);
+
+	thread = mbox->chans[ind].con_priv;
+	thread->atomic_exec = (sp->args[1] != 0);
+	thread->chan = &mbox->chans[ind];
+
+	return &mbox->chans[ind];
+}
+
+static int cmdq_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	struct cmdq *cmdq;
+	int err, i;
+
+	cmdq = devm_kzalloc(dev, sizeof(*cmdq), GFP_KERNEL);
+	if (!cmdq)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	cmdq->base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(cmdq->base)) {
+		dev_err(dev, "failed to ioremap gce\n");
+		return PTR_ERR(cmdq->base);
+	}
+
+	cmdq->irq = platform_get_irq(pdev, 0);
+	if (!cmdq->irq) {
+		dev_err(dev, "failed to get irq\n");
+		return -EINVAL;
+	}
+	err = devm_request_irq(dev, cmdq->irq, cmdq_irq_handler, IRQF_SHARED,
+			       "mtk_cmdq", cmdq);
+	if (err < 0) {
+		dev_err(dev, "failed to register ISR (%d)\n", err);
+		return err;
+	}
+
+	dev_dbg(dev, "cmdq device: addr:0x%p, va:0x%p, irq:%d\n",
+		dev, cmdq->base, cmdq->irq);
+
+	cmdq->clock = devm_clk_get(dev, "gce");
+	if (IS_ERR(cmdq->clock)) {
+		dev_err(dev, "failed to get gce clk\n");
+		return PTR_ERR(cmdq->clock);
+	}
+
+	cmdq->mbox.dev = dev;
+	cmdq->mbox.chans = devm_kcalloc(dev, CMDQ_THR_MAX_COUNT,
+					sizeof(*cmdq->mbox.chans), GFP_KERNEL);
+	if (!cmdq->mbox.chans)
+		return -ENOMEM;
+
+	cmdq->mbox.num_chans = CMDQ_THR_MAX_COUNT;
+	cmdq->mbox.ops = &cmdq_mbox_chan_ops;
+	cmdq->mbox.of_xlate = cmdq_xlate;
+
+	/* make use of TXDONE_BY_ACK */
+	cmdq->mbox.txdone_irq = false;
+	cmdq->mbox.txdone_poll = false;
+
+	for (i = 0; i < ARRAY_SIZE(cmdq->thread); i++) {
+		cmdq->thread[i].base = cmdq->base + CMDQ_THR_BASE +
+				CMDQ_THR_SIZE * i;
+		INIT_LIST_HEAD(&cmdq->thread[i].task_busy_list);
+		init_timer(&cmdq->thread[i].timeout);
+		cmdq->thread[i].timeout.function = cmdq_thread_handle_timeout;
+		cmdq->thread[i].timeout.data = (unsigned long)&cmdq->thread[i];
+		cmdq->mbox.chans[i].con_priv = &cmdq->thread[i];
+	}
+
+	err = mbox_controller_register(&cmdq->mbox);
+	if (err < 0) {
+		dev_err(dev, "failed to register mailbox: %d\n", err);
+		return err;
+	}
+
+	platform_set_drvdata(pdev, cmdq);
+	WARN_ON(clk_prepare(cmdq->clock) < 0);
+
+	return 0;
+}
+
+static const struct dev_pm_ops cmdq_pm_ops = {
+	.suspend = cmdq_suspend,
+	.resume = cmdq_resume,
+};
+
+static const struct of_device_id cmdq_of_ids[] = {
+	{.compatible = "mediatek,mt8173-gce",},
+	{}
+};
+
+static struct platform_driver cmdq_drv = {
+	.probe = cmdq_probe,
+	.remove = cmdq_remove,
+	.driver = {
+		.name = "mtk_cmdq",
+		.pm = &cmdq_pm_ops,
+		.of_match_table = cmdq_of_ids,
+	}
+};
+
+builtin_platform_driver(cmdq_drv);
diff --git a/include/linux/mailbox/mtk-cmdq-mailbox.h b/include/linux/mailbox/mtk-cmdq-mailbox.h
new file mode 100644
index 0000000..3433c64
--- /dev/null
+++ b/include/linux/mailbox/mtk-cmdq-mailbox.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MTK_CMDQ_MAILBOX_H__
+#define __MTK_CMDQ_MAILBOX_H__
+
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#define CMDQ_INST_SIZE			8 /* instruction is 64-bit */
+#define CMDQ_OP_CODE_SHIFT		24
+#define CMDQ_JUMP_PASS			CMDQ_INST_SIZE
+
+#define CMDQ_WFE_UPDATE			BIT(31)
+#define CMDQ_WFE_WAIT			BIT(15)
+#define CMDQ_WFE_WAIT_VALUE		0x1
+
+/*
+ * CMDQ_CODE_MASK:
+ *   set write mask
+ *   format: op mask
+ * CMDQ_CODE_WRITE:
+ *   write value into target register
+ *   format: op subsys address value
+ * CMDQ_CODE_JUMP:
+ *   jump by offset
+ *   format: op offset
+ * CMDQ_CODE_WFE:
+ *   wait for event and clear
+ *   it is just clear if no wait
+ *   format: [wait]  op event update:1 to_wait:1 wait:1
+ *           [clear] op event update:1 to_wait:0 wait:0
+ * CMDQ_CODE_EOC:
+ *   end of command
+ *   format: op irq_flag
+ */
+enum cmdq_code {
+	CMDQ_CODE_MASK = 0x02,
+	CMDQ_CODE_WRITE = 0x04,
+	CMDQ_CODE_JUMP = 0x10,
+	CMDQ_CODE_WFE = 0x20,
+	CMDQ_CODE_EOC = 0x40,
+};
+
+struct cmdq_cb_data {
+	bool	err;
+	void	*data;
+};
+
+typedef void (*cmdq_async_flush_cb)(struct cmdq_cb_data data);
+
+struct cmdq_task_cb {
+	cmdq_async_flush_cb	cb;
+	void			*data;
+};
+
+struct cmdq_pkt {
+	void			*va_base;
+	size_t			cmd_buf_size; /* command occupied size */
+	size_t			buf_size; /* real buffer size */
+	struct cmdq_task_cb	cb;
+};
+
+#endif /* __MTK_CMDQ_MAILBOX_H__ */
-- 
1.9.1

^ 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