Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 2/2] kbuild: add __cc-ifversion and compiler-specific variants
From: Sami Tolvanen @ 2017-11-30 23:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171130233827.130069-1-samitolvanen@google.com>

This change adds macros for testing both compiler name and
version. Current cc-version, cc-ifversion etc. macros that test
gcc version are left unchanged to prevent compatibility issues
with existing tests.

Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
---
 scripts/Kbuild.include | 41 ++++++++++++++++++++++++++++++++++-------
 1 file changed, 34 insertions(+), 7 deletions(-)

diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
index 065324a8046f..eb2cf2780f6e 100644
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -215,6 +215,37 @@ cc-disable-warning = $(call try-run-cached,\
 # Expands to either gcc or clang
 cc-name = $(call shell-cached,$(CC) -v 2>&1 | grep -q "clang version" && echo clang || echo gcc)
 
+# __cc-version
+# Returns compiler version
+__cc-version = $(call shell-cached,$(CONFIG_SHELL) $(srctree)/scripts/$(cc-name)-version.sh $(CC))
+
+# __cc-fullversion
+# Returns full compiler version
+__cc-fullversion = $(call shell-cached,$(CONFIG_SHELL) \
+	$(srctree)/scripts/$(cc-name)-version.sh -p $(CC))
+
+# __cc-ifversion
+# Matches compiler name and version
+# Usage:  EXTRA_CFLAGS += $(call cc-if-name-version, gcc, -lt, 0402, -O1)
+__cc-ifversion = $(shell [ $(cc-name) = $(1) ] && [ $(__cc-version) $(2) $(3) ] && echo $(4) || echo $(5))
+
+# __cc-if-fullversion
+# Matches compiler name and full version
+# Usage:  EXTRA_CFLAGS += $(call cc-if-name-fullversion, gcc, -lt, 040502, -O1)
+__cc-if-fullversion = $(shell [ $(cc-name) = $(1) ] && [ $(__cc-fullversion) $(2) $(3) ] && echo $(4) || echo $(5))
+
+# gcc-ifversion
+gcc-ifversion = $(call __cc-ifversion, gcc, $(1), $(2), $(3), $(4))
+
+# gcc-if-fullversion
+gcc-if-fullversion = (call __cc-if-fullversion, gcc, $(1), $(2), $(3), $(4))
+
+# clang-ifversion
+clang-ifversion =  $(call __cc-ifversion, clang, $(1), $(2), $(3), $(4))
+
+# clang-if-fullversion
+clang-if-fullversion = (call __cc-if-fullversion, clang, $(1), $(2), $(3), $(4))
+
 # cc-version
 cc-version = $(call shell-cached,$(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh $(CC))
 
@@ -222,13 +253,9 @@ cc-version = $(call shell-cached,$(CONFIG_SHELL) $(srctree)/scripts/gcc-version.
 cc-fullversion = $(call shell-cached,$(CONFIG_SHELL) \
 	$(srctree)/scripts/gcc-version.sh -p $(CC))
 
-# cc-ifversion
-# Usage:  EXTRA_CFLAGS += $(call cc-ifversion, -lt, 0402, -O1)
-cc-ifversion = $(shell [ $(cc-version) $(1) $(2) ] && echo $(3) || echo $(4))
-
-# cc-if-fullversion
-# Usage:  EXTRA_CFLAGS += $(call cc-if-fullversion, -lt, 040502, -O1)
-cc-if-fullversion = $(shell [ $(cc-fullversion) $(1) $(2) ] && echo $(3) || echo $(4))
+# backward compatibility
+cc-ifversion = $(gcc-ifversion)
+cc-if-fullversion = $(gcc-if-fullversion)
 
 # cc-ldoption
 # Usage: ldflags += $(call cc-ldoption, -Wl$(comma)--hash-style=both)
-- 
2.15.0.531.g2ccb3012c9-goog

^ permalink raw reply related

* [PATCH v2 1/2] kbuild: add clang-version.sh
From: Sami Tolvanen @ 2017-11-30 23:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171130233827.130069-1-samitolvanen@google.com>

Based on gcc-version.sh, clang-version.sh prints out the correct
version of clang.

Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
Tested-by: Nick Desaulniers <ndesaulniers@google.com>
---
 scripts/clang-version.sh | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)
 create mode 100755 scripts/clang-version.sh

diff --git a/scripts/clang-version.sh b/scripts/clang-version.sh
new file mode 100755
index 000000000000..9780efa56980
--- /dev/null
+++ b/scripts/clang-version.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+#
+# clang-version [-p] clang-command
+#
+# Prints the compiler version of `clang-command' in a canonical 4-digit form
+# such as `0500' for clang-5.0 etc.
+#
+# With the -p option, prints the patchlevel as well, for example `050001' for
+# clang-5.0.1 etc.
+#
+
+if [ "$1" = "-p" ] ; then
+	with_patchlevel=1;
+	shift;
+fi
+
+compiler="$*"
+
+if [ ${#compiler} -eq 0 ]; then
+	echo "Error: No compiler specified."
+	printf "Usage:\n\t$0 <clang-command>\n"
+	exit 1
+fi
+
+MAJOR=$(echo __clang_major__ | $compiler -E -x c - | tail -n 1)
+MINOR=$(echo __clang_minor__ | $compiler -E -x c - | tail -n 1)
+if [ "x$with_patchlevel" != "x" ] ; then
+	PATCHLEVEL=$(echo __clang_patchlevel__ | $compiler -E -x c - | tail -n 1)
+	printf "%02d%02d%02d\\n" $MAJOR $MINOR $PATCHLEVEL
+else
+	printf "%02d%02d\\n" $MAJOR $MINOR
+fi
-- 
2.15.0.531.g2ccb3012c9-goog

^ permalink raw reply related

* [PATCH v2 0/2] Add version macros for clang
From: Sami Tolvanen @ 2017-11-30 23:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171129000011.55235-1-samitolvanen@google.com>

This patch set adds macros for checking clang version.

Changes from v1:
  - fixed a comment in clang-version.sh
  - renamed macros to __cc-ifversion and __cc-if-fullversion
  - fixed a bug with non-bash shells
  - dropped the arm64 patch as unnecessary

Sami Tolvanen (2):
  kbuild: add clang-version.sh
  kbuild: add __cc-ifversion and compiler-specific variants

 scripts/Kbuild.include   | 41 ++++++++++++++++++++++++++++++++++-------
 scripts/clang-version.sh | 33 +++++++++++++++++++++++++++++++++
 2 files changed, 67 insertions(+), 7 deletions(-)
 create mode 100755 scripts/clang-version.sh

-- 
2.15.0.531.g2ccb3012c9-goog

^ permalink raw reply

* [GIT PULL] Amlogic fixes for v4.15-rc
From: Kevin Hilman @ 2017-11-30 23:28 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <7hefofpdcs.fsf@baylibre.com>

On Thu, Nov 30, 2017 at 3:15 PM, Kevin Hilman <khilman@baylibre.com> wrote:
> Arnd, Olof,
>
> A handful of minor v4.15 fixes for Amlogic family SoCs.  They're mostly
> DT, but some trivial non-DT stuff mixed in.  Let me know if you prefer
> those in separate pulls, and I will do so.

Oops, please ignore.  Tagged the wrong branch... re-spinning...

Kevin

^ permalink raw reply

* [PATCH v3 8/9] pwm: pwm-omap-dmtimer: Adapt driver to utilize dmtimer pdata ops
From: Grygorii Strashko @ 2017-11-30 23:19 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <e632a727-1067-7767-1646-f49ec0f8c2ec@ti.com>



On 11/30/2017 03:36 AM, Keerthy wrote:
> 
> 
> On Tuesday 28 November 2017 11:57 PM, Strashko, Grygorii wrote:
>>
>>
>> On 11/15/2017 10:23 PM, Keerthy wrote:
>>> Adapt driver to utilize dmtimer pdata ops instead of pdata-quirks.
>>>
>>> Signed-off-by: Keerthy <j-keerthy@ti.com>
>>> ---
>>>
>>> Changes in v3:
>>>
>>>     * Used of_find_platdata_by_node function to fetch platform
>>>       data for timer node.
>>>
>>>    drivers/pwm/pwm-omap-dmtimer.c | 39 ++++++++++++++++++++++-----------------
>>>    1 file changed, 22 insertions(+), 17 deletions(-)
>>>
>>> diff --git a/drivers/pwm/pwm-omap-dmtimer.c b/drivers/pwm/pwm-omap-dmtimer.c
>>> index 5ad42f3..2caf46b 100644
>>> --- a/drivers/pwm/pwm-omap-dmtimer.c
>>> +++ b/drivers/pwm/pwm-omap-dmtimer.c
>>> @@ -23,6 +23,7 @@
>>>    #include <linux/mutex.h>
>>>    #include <linux/of.h>
>>>    #include <linux/of_platform.h>
>>> +#include <linux/platform_data/dmtimer-omap.h>
>>>    #include <linux/platform_data/pwm_omap_dmtimer.h>
>>>    #include <linux/platform_device.h>
>>>    #include <linux/pm_runtime.h>
>>> @@ -37,7 +38,7 @@ struct pwm_omap_dmtimer_chip {
>>>    	struct pwm_chip chip;
>>>    	struct mutex mutex;
>>>    	pwm_omap_dmtimer *dm_timer;
>>> -	struct pwm_omap_dmtimer_pdata *pdata;
>>> +	struct omap_dm_timer_ops *pdata;
>>>    	struct platform_device *dm_timer_pdev;
>>>    };
>>>    
>>> @@ -242,19 +243,33 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev)
>>>    {
>>>    	struct device_node *np = pdev->dev.of_node;
>>>    	struct device_node *timer;
>>> +	struct platform_device *timer_pdev;
>>>    	struct pwm_omap_dmtimer_chip *omap;
>>> -	struct pwm_omap_dmtimer_pdata *pdata;
>>> +	struct dmtimer_platform_data *timer_pdata;
>>> +	struct omap_dm_timer_ops *pdata;
>>>    	pwm_omap_dmtimer *dm_timer;
>>>    	u32 v;
>>>    	int status;
>>>    
>>> -	pdata = dev_get_platdata(&pdev->dev);
>>> -	if (!pdata) {
>>> -		dev_err(&pdev->dev, "Missing dmtimer platform data\n");
>>> +	timer = of_parse_phandle(np, "ti,timers", 0);
>>> +	if (!timer)
>>> +		return -ENODEV;
>>> +
>>> +	timer_pdev = of_find_device_by_node(timer);
>>> +	if (!timer_pdev) {
>>> +		dev_err(&pdev->dev, "Unable to find Timer pdev\n");
>>> +		return -ENODEV;
>>> +	}
>>> +
>>> +	timer_pdata = of_find_platdata_by_node(timer);
>>> +	if (!timer_pdata) {
>>> +		dev_err(&pdev->dev, "dmtimer pdata structure NULL\n");
>>>    		return -EINVAL;
>>>    	}
>>
>> Huh. I think It might be better if you add smth. like
>>
>> struct omap_dm_timer *dm_timer = of_omap_dm_timer_get(parent_np, "ti,timers", idx);
>>
>> struct omap_dm_timer_ops *pdata = omap_dm_timer_get_ops(dm_timer);
>>
>> so all DT and platdata implementation details will be hidden.
> 
> Grygorii,
> 
> This driver is already fetching:
> 
> omap->dm_timer_pdev = of_find_device_by_node(timer);
> 
> It stores dm_timer_pdev in struct pwm_omap_dmtimer_chip.
> So we already need:
> timer = of_parse_phandle(np, "ti,timers", 0);
> and
> omap->dm_timer_pdev = of_find_device_by_node(timer);
> 
> So why not just do:
> 
> struct omap_dm_timer_ops *pdata =
> omap_dm_timer_get_ops(omap->dm_timer_pdev);

if you dont want to do additional optimizations as part of migration
might be
dev_get_platdata(&omap->dm_timer_pdev->dev);

would be enough.

But, again, PWM driver don't need to know so many details about
DM timer implementation and internal structure as consumer.

-- 
regards,
-grygorii

^ permalink raw reply

* [GIT PULL] Amlogic fixes for v4.15-rc
From: Kevin Hilman @ 2017-11-30 23:15 UTC (permalink / raw)
  To: linux-arm-kernel

Arnd, Olof,

A handful of minor v4.15 fixes for Amlogic family SoCs.  They're mostly
DT, but some trivial non-DT stuff mixed in.  Let me know if you prefer
those in separate pulls, and I will do so.

Thanks,

Kevin


The following changes since commit 4fbd8d194f06c8a3fd2af1ce560ddb31f7ec8323:

  Linux 4.15-rc1 (2017-11-26 16:01:47 -0800)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-amlogic.git tags/amlogic-fixes

for you to fetch changes up to 1142a3a457d007910df95acc7983d4d7be49645a:

  meson-gx-socinfo: Fix package id parsing (2017-11-29 15:58:00 -0800)

----------------------------------------------------------------
Amlogic fixes for v4.15-rc
- GPIO interrupt fixes
- new nodes for drivers merged late (VPU domains)
- socinfo fix for GX series
- fix typo

----------------------------------------------------------------
Arnaud Patard (1):
      meson-gx-socinfo: Fix package id parsing

Colin Ian King (1):
      ARM: meson: fix spelling mistake: "Couln't" -> "Couldn't"

Martin Blumenstingl (2):
      ARM: dts: meson: correct the sort order for the the gpio_intc node
      ARM: dts: meson: fix the memory region of the GPIO interrupt controller

Neil Armstrong (4):
      ARM64: dts: meson-gx: add VPU power domain
      ARM64: dts: meson-gx: Add HDMI_5V regulator on selected boards
      ARM64: dts: meson-gx: grow reset controller memory zone
      ARM64: dts: odroid-c2: Add HDMI and CEC Nodes

 arch/arm/boot/dts/meson.dtsi                                 | 18 +++++++++---------
 arch/arm/mach-meson/platsmp.c                                |  2 +-
 arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi          | 12 ++++++++++++
 arch/arm64/boot/dts/amlogic/meson-gx.dtsi                    | 13 ++++++++++++-
 arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts          | 30 ++++++++++++++++++++++++++++++
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi                  | 43 +++++++++++++++++++++++++++++++++++++++++++
 arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts         |  1 +
 arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts   |  1 +
 arch/arm64/boot/dts/amlogic/meson-gxl-s905x-libretech-cc.dts | 12 ++++++++++++
 arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dts         |  1 +
 arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dtsi        | 11 +++++++++++
 arch/arm64/boot/dts/amlogic/meson-gxl.dtsi                   | 43 +++++++++++++++++++++++++++++++++++++++++++
 arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts        | 12 ++++++++++++
 drivers/soc/amlogic/meson-gx-socinfo.c                       |  4 ++--
 14 files changed, 190 insertions(+), 13 deletions(-)

^ permalink raw reply

* [PATCH v6 2/2] memory: ti-emif-sram: introduce relocatable suspend/resume handlers
From: Dave Gerlach @ 2017-11-30 22:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1512082568-5012-1-git-send-email-d-gerlach@ti.com>

Certain SoCs like Texas Instruments AM335x and AM437x require parts
of the EMIF PM code to run late in the suspend sequence from SRAM,
such as saving and restoring the EMIF context and placing the memory
into self-refresh.

One requirement for these SoCs to suspend and enter its lowest power
mode, called DeepSleep0, is that the PER power domain must be shut off.
Because the EMIF (DDR Controller) resides within this power domain, it
will lose context during a suspend operation, so we must save it so we
can restore once we resume. However, we cannot execute this code from
external memory, as it is not available at this point, so the code must
be executed late in the suspend path from SRAM.

This patch introduces a ti-emif-sram driver that includes several
functions written in ARM ASM that are relocatable so the PM SRAM
code can use them. It also allocates a region of writable SRAM to
be used by the code running in the executable region of SRAM to save
and restore the EMIF context. It can export a table containing the
absolute addresses of the available PM functions so that other SRAM
code can branch to them. This code is required for suspend/resume on
AM335x and AM437x to work.

In addition to this, to be able to share data structures between C and
the ti-emif-sram-pm assembly code, we can automatically generate all of
the C struct member offsets and sizes as macros by processing
emif-asm-offsets.c into assembly code and then extracting the relevant
data as is done for the generated platform asm-offsets.h files.

Acked-by: Tony Lindgren <tony@atomide.com>
Acked-by: Russell King <rmk+kernel@armlinux.org.uk>
Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
---
 drivers/memory/Kconfig              |  10 ++
 drivers/memory/Makefile             |   8 +
 drivers/memory/Makefile.asm-offsets |   5 +
 drivers/memory/emif-asm-offsets.c   |  92 ++++++++++
 drivers/memory/emif.h               |  17 ++
 drivers/memory/ti-emif-pm.c         | 325 +++++++++++++++++++++++++++++++++++
 drivers/memory/ti-emif-sram-pm.S    | 334 ++++++++++++++++++++++++++++++++++++
 include/linux/ti-emif-sram.h        |  69 ++++++++
 8 files changed, 860 insertions(+)
 create mode 100644 drivers/memory/Makefile.asm-offsets
 create mode 100644 drivers/memory/emif-asm-offsets.c
 create mode 100644 drivers/memory/ti-emif-pm.c
 create mode 100644 drivers/memory/ti-emif-sram-pm.S
 create mode 100644 include/linux/ti-emif-sram.h

diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
index ffc350258041..19a0e83f260d 100644
--- a/drivers/memory/Kconfig
+++ b/drivers/memory/Kconfig
@@ -84,6 +84,16 @@ config OMAP_GPMC_DEBUG
 	  bootloader or else the GPMC timings won't be identical with the
 	  bootloader timings.
 
+config TI_EMIF_SRAM
+	tristate "Texas Instruments EMIF SRAM driver"
+	depends on (SOC_AM33XX || SOC_AM43XX) && SRAM
+	help
+	  This driver is for the EMIF module available on Texas Instruments
+	  AM33XX and AM43XX SoCs and is required for PM. Certain parts of
+	  the EMIF PM code must run from on-chip SRAM late in the suspend
+	  sequence so this driver provides several relocatable PM functions
+	  for the SoC PM code to use.
+
 config MVEBU_DEVBUS
 	bool "Marvell EBU Device Bus Controller"
 	default y
diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
index 929a601d4cd1..66f55240830e 100644
--- a/drivers/memory/Makefile
+++ b/drivers/memory/Makefile
@@ -23,3 +23,11 @@ obj-$(CONFIG_DA8XX_DDRCTL)	+= da8xx-ddrctl.o
 
 obj-$(CONFIG_SAMSUNG_MC)	+= samsung/
 obj-$(CONFIG_TEGRA_MC)		+= tegra/
+obj-$(CONFIG_TI_EMIF_SRAM)	+= ti-emif-sram.o
+ti-emif-sram-objs		:= ti-emif-pm.o ti-emif-sram-pm.o
+
+AFLAGS_ti-emif-sram-pm.o	:=-Wa,-march=armv7-a
+
+include drivers/memory/Makefile.asm-offsets
+
+drivers/memory/ti-emif-sram-pm.o: include/generated/ti-emif-asm-offsets.h
diff --git a/drivers/memory/Makefile.asm-offsets b/drivers/memory/Makefile.asm-offsets
new file mode 100644
index 000000000000..843ff60ccb5a
--- /dev/null
+++ b/drivers/memory/Makefile.asm-offsets
@@ -0,0 +1,5 @@
+drivers/memory/emif-asm-offsets.s: drivers/memory/emif-asm-offsets.c
+	$(call if_changed_dep,cc_s_c)
+
+include/generated/ti-emif-asm-offsets.h: drivers/memory/emif-asm-offsets.s FORCE
+	$(call filechk,offsets,__TI_EMIF_ASM_OFFSETS_H__)
diff --git a/drivers/memory/emif-asm-offsets.c b/drivers/memory/emif-asm-offsets.c
new file mode 100644
index 000000000000..71a89d5d3efd
--- /dev/null
+++ b/drivers/memory/emif-asm-offsets.c
@@ -0,0 +1,92 @@
+/*
+ * TI AM33XX EMIF PM Assembly Offsets
+ *
+ * Copyright (C) 2016-2017 Texas Instruments Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/ti-emif-sram.h>
+
+int main(void)
+{
+	DEFINE(EMIF_SDCFG_VAL_OFFSET,
+	       offsetof(struct emif_regs_amx3, emif_sdcfg_val));
+	DEFINE(EMIF_TIMING1_VAL_OFFSET,
+	       offsetof(struct emif_regs_amx3, emif_timing1_val));
+	DEFINE(EMIF_TIMING2_VAL_OFFSET,
+	       offsetof(struct emif_regs_amx3, emif_timing2_val));
+	DEFINE(EMIF_TIMING3_VAL_OFFSET,
+	       offsetof(struct emif_regs_amx3, emif_timing3_val));
+	DEFINE(EMIF_REF_CTRL_VAL_OFFSET,
+	       offsetof(struct emif_regs_amx3, emif_ref_ctrl_val));
+	DEFINE(EMIF_ZQCFG_VAL_OFFSET,
+	       offsetof(struct emif_regs_amx3, emif_zqcfg_val));
+	DEFINE(EMIF_PMCR_VAL_OFFSET,
+	       offsetof(struct emif_regs_amx3, emif_pmcr_val));
+	DEFINE(EMIF_PMCR_SHDW_VAL_OFFSET,
+	       offsetof(struct emif_regs_amx3, emif_pmcr_shdw_val));
+	DEFINE(EMIF_RD_WR_LEVEL_RAMP_CTRL_OFFSET,
+	       offsetof(struct emif_regs_amx3, emif_rd_wr_level_ramp_ctrl));
+	DEFINE(EMIF_RD_WR_EXEC_THRESH_OFFSET,
+	       offsetof(struct emif_regs_amx3, emif_rd_wr_exec_thresh));
+	DEFINE(EMIF_COS_CONFIG_OFFSET,
+	       offsetof(struct emif_regs_amx3, emif_cos_config));
+	DEFINE(EMIF_PRIORITY_TO_COS_MAPPING_OFFSET,
+	       offsetof(struct emif_regs_amx3, emif_priority_to_cos_mapping));
+	DEFINE(EMIF_CONNECT_ID_SERV_1_MAP_OFFSET,
+	       offsetof(struct emif_regs_amx3, emif_connect_id_serv_1_map));
+	DEFINE(EMIF_CONNECT_ID_SERV_2_MAP_OFFSET,
+	       offsetof(struct emif_regs_amx3, emif_connect_id_serv_2_map));
+	DEFINE(EMIF_OCP_CONFIG_VAL_OFFSET,
+	       offsetof(struct emif_regs_amx3, emif_ocp_config_val));
+	DEFINE(EMIF_LPDDR2_NVM_TIM_OFFSET,
+	       offsetof(struct emif_regs_amx3, emif_lpddr2_nvm_tim));
+	DEFINE(EMIF_LPDDR2_NVM_TIM_SHDW_OFFSET,
+	       offsetof(struct emif_regs_amx3, emif_lpddr2_nvm_tim_shdw));
+	DEFINE(EMIF_DLL_CALIB_CTRL_VAL_OFFSET,
+	       offsetof(struct emif_regs_amx3, emif_dll_calib_ctrl_val));
+	DEFINE(EMIF_DLL_CALIB_CTRL_VAL_SHDW_OFFSET,
+	       offsetof(struct emif_regs_amx3, emif_dll_calib_ctrl_val_shdw));
+	DEFINE(EMIF_DDR_PHY_CTLR_1_OFFSET,
+	       offsetof(struct emif_regs_amx3, emif_ddr_phy_ctlr_1));
+	DEFINE(EMIF_EXT_PHY_CTRL_VALS_OFFSET,
+	       offsetof(struct emif_regs_amx3, emif_ext_phy_ctrl_vals));
+	DEFINE(EMIF_REGS_AMX3_SIZE, sizeof(struct emif_regs_amx3));
+
+	BLANK();
+
+	DEFINE(EMIF_PM_BASE_ADDR_VIRT_OFFSET,
+	       offsetof(struct ti_emif_pm_data, ti_emif_base_addr_virt));
+	DEFINE(EMIF_PM_BASE_ADDR_PHYS_OFFSET,
+	       offsetof(struct ti_emif_pm_data, ti_emif_base_addr_phys));
+	DEFINE(EMIF_PM_CONFIG_OFFSET,
+	       offsetof(struct ti_emif_pm_data, ti_emif_sram_config));
+	DEFINE(EMIF_PM_REGS_VIRT_OFFSET,
+	       offsetof(struct ti_emif_pm_data, regs_virt));
+	DEFINE(EMIF_PM_REGS_PHYS_OFFSET,
+	       offsetof(struct ti_emif_pm_data, regs_phys));
+	DEFINE(EMIF_PM_DATA_SIZE, sizeof(struct ti_emif_pm_data));
+
+	BLANK();
+
+	DEFINE(EMIF_PM_SAVE_CONTEXT_OFFSET,
+	       offsetof(struct ti_emif_pm_functions, save_context));
+	DEFINE(EMIF_PM_RESTORE_CONTEXT_OFFSET,
+	       offsetof(struct ti_emif_pm_functions, restore_context));
+	DEFINE(EMIF_PM_ENTER_SR_OFFSET,
+	       offsetof(struct ti_emif_pm_functions, enter_sr));
+	DEFINE(EMIF_PM_EXIT_SR_OFFSET,
+	       offsetof(struct ti_emif_pm_functions, exit_sr));
+	DEFINE(EMIF_PM_ABORT_SR_OFFSET,
+	       offsetof(struct ti_emif_pm_functions, abort_sr));
+	DEFINE(EMIF_PM_FUNCTIONS_SIZE, sizeof(struct ti_emif_pm_functions));
+
+	return 0;
+}
diff --git a/drivers/memory/emif.h b/drivers/memory/emif.h
index bfe08bae961a..9e9f8037955d 100644
--- a/drivers/memory/emif.h
+++ b/drivers/memory/emif.h
@@ -555,6 +555,9 @@
 #define READ_LATENCY_SHDW_SHIFT				0
 #define READ_LATENCY_SHDW_MASK				(0x1f << 0)
 
+#define EMIF_SRAM_AM33_REG_LAYOUT			0x00000000
+#define EMIF_SRAM_AM43_REG_LAYOUT			0x00000001
+
 #ifndef __ASSEMBLY__
 /*
  * Structure containing shadow of important registers in EMIF
@@ -585,5 +588,19 @@ struct emif_regs {
 	u32 ext_phy_ctrl_3_shdw;
 	u32 ext_phy_ctrl_4_shdw;
 };
+
+struct ti_emif_pm_functions;
+
+extern unsigned int ti_emif_sram;
+extern unsigned int ti_emif_sram_sz;
+extern struct ti_emif_pm_data ti_emif_pm_sram_data;
+extern struct emif_regs_amx3 ti_emif_regs_amx3;
+
+void ti_emif_save_context(void);
+void ti_emif_restore_context(void);
+void ti_emif_enter_sr(void);
+void ti_emif_exit_sr(void);
+void ti_emif_abort_sr(void);
+
 #endif /* __ASSEMBLY__ */
 #endif /* __EMIF_H */
diff --git a/drivers/memory/ti-emif-pm.c b/drivers/memory/ti-emif-pm.c
new file mode 100644
index 000000000000..4ea1514fb9b2
--- /dev/null
+++ b/drivers/memory/ti-emif-pm.c
@@ -0,0 +1,325 @@
+/*
+ * TI AM33XX SRAM EMIF Driver
+ *
+ * Copyright (C) 2016-2017 Texas Instruments Inc.
+ *	Dave Gerlach
+ *
+ * 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/err.h>
+#include <linux/genalloc.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/sram.h>
+#include <linux/ti-emif-sram.h>
+
+#include "emif.h"
+
+#define TI_EMIF_SRAM_SYMBOL_OFFSET(sym) ((unsigned long)(sym) - \
+					 (unsigned long)&ti_emif_sram)
+
+#define EMIF_POWER_MGMT_WAIT_SELF_REFRESH_8192_CYCLES		0x00a0
+
+struct ti_emif_data {
+	phys_addr_t ti_emif_sram_phys;
+	phys_addr_t ti_emif_sram_data_phys;
+	unsigned long ti_emif_sram_virt;
+	unsigned long ti_emif_sram_data_virt;
+	struct gen_pool *sram_pool_code;
+	struct gen_pool	*sram_pool_data;
+	struct ti_emif_pm_data pm_data;
+	struct ti_emif_pm_functions pm_functions;
+};
+
+static struct ti_emif_data *emif_instance;
+
+static u32 sram_suspend_address(struct ti_emif_data *emif_data,
+				unsigned long addr)
+{
+	return (emif_data->ti_emif_sram_virt +
+		TI_EMIF_SRAM_SYMBOL_OFFSET(addr));
+}
+
+static phys_addr_t sram_resume_address(struct ti_emif_data *emif_data,
+				       unsigned long addr)
+{
+	return ((unsigned long)emif_data->ti_emif_sram_phys +
+		TI_EMIF_SRAM_SYMBOL_OFFSET(addr));
+}
+
+static void ti_emif_free_sram(struct ti_emif_data *emif_data)
+{
+	gen_pool_free(emif_data->sram_pool_code, emif_data->ti_emif_sram_virt,
+		      ti_emif_sram_sz);
+	gen_pool_free(emif_data->sram_pool_data,
+		      emif_data->ti_emif_sram_data_virt,
+		      sizeof(struct emif_regs_amx3));
+}
+
+static int ti_emif_alloc_sram(struct device *dev,
+			      struct ti_emif_data *emif_data)
+{
+	struct device_node *np = dev->of_node;
+	int ret;
+
+	emif_data->sram_pool_code = of_gen_pool_get(np, "sram", 0);
+	if (!emif_data->sram_pool_code) {
+		dev_err(dev, "Unable to get sram pool for ocmcram code\n");
+		return -ENODEV;
+	}
+
+	emif_data->ti_emif_sram_virt =
+			gen_pool_alloc(emif_data->sram_pool_code,
+				       ti_emif_sram_sz);
+	if (!emif_data->ti_emif_sram_virt) {
+		dev_err(dev, "Unable to allocate code memory from ocmcram\n");
+		return -ENOMEM;
+	}
+
+	/* Save physical address to calculate resume offset during pm init */
+	emif_data->ti_emif_sram_phys =
+			gen_pool_virt_to_phys(emif_data->sram_pool_code,
+					      emif_data->ti_emif_sram_virt);
+
+	/* Get sram pool for data section and allocate space */
+	emif_data->sram_pool_data = of_gen_pool_get(np, "sram", 1);
+	if (!emif_data->sram_pool_data) {
+		dev_err(dev, "Unable to get sram pool for ocmcram data\n");
+		ret = -ENODEV;
+		goto err_free_sram_code;
+	}
+
+	emif_data->ti_emif_sram_data_virt =
+				gen_pool_alloc(emif_data->sram_pool_data,
+					       sizeof(struct emif_regs_amx3));
+	if (!emif_data->ti_emif_sram_data_virt) {
+		dev_err(dev, "Unable to allocate data memory from ocmcram\n");
+		ret = -ENOMEM;
+		goto err_free_sram_code;
+	}
+
+	/* Save physical address to calculate resume offset during pm init */
+	emif_data->ti_emif_sram_data_phys =
+		gen_pool_virt_to_phys(emif_data->sram_pool_data,
+				      emif_data->ti_emif_sram_data_virt);
+	/*
+	 * These functions are called during suspend path while MMU is
+	 * still on so add virtual base to offset for absolute address
+	 */
+	emif_data->pm_functions.save_context =
+		sram_suspend_address(emif_data,
+				     (unsigned long)ti_emif_save_context);
+	emif_data->pm_functions.enter_sr =
+		sram_suspend_address(emif_data,
+				     (unsigned long)ti_emif_enter_sr);
+	emif_data->pm_functions.abort_sr =
+		sram_suspend_address(emif_data,
+				     (unsigned long)ti_emif_abort_sr);
+
+	/*
+	 * These are called during resume path when MMU is not enabled
+	 * so physical address is used instead
+	 */
+	emif_data->pm_functions.restore_context =
+		sram_resume_address(emif_data,
+				    (unsigned long)ti_emif_restore_context);
+	emif_data->pm_functions.exit_sr =
+		sram_resume_address(emif_data,
+				    (unsigned long)ti_emif_exit_sr);
+
+	emif_data->pm_data.regs_virt =
+		(struct emif_regs_amx3 *)emif_data->ti_emif_sram_data_virt;
+	emif_data->pm_data.regs_phys = emif_data->ti_emif_sram_data_phys;
+
+	return 0;
+
+err_free_sram_code:
+	gen_pool_free(emif_data->sram_pool_code, emif_data->ti_emif_sram_virt,
+		      ti_emif_sram_sz);
+	return ret;
+}
+
+static int ti_emif_push_sram(struct device *dev, struct ti_emif_data *emif_data)
+{
+	void *copy_addr;
+	u32 data_addr;
+
+	copy_addr = sram_exec_copy(emif_data->sram_pool_code,
+				   (void *)emif_data->ti_emif_sram_virt,
+				   &ti_emif_sram, ti_emif_sram_sz);
+	if (!copy_addr) {
+		dev_err(dev, "Cannot copy emif code to sram\n");
+		return -ENODEV;
+	}
+
+	data_addr = sram_suspend_address(emif_data,
+					 (unsigned long)&ti_emif_pm_sram_data);
+	copy_addr = sram_exec_copy(emif_data->sram_pool_code,
+				   (void *)data_addr,
+				   &emif_data->pm_data,
+				   sizeof(emif_data->pm_data));
+	if (!copy_addr) {
+		dev_err(dev, "Cannot copy emif data to code sram\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+/*
+ * Due to Usage Note 3.1.2 "DDR3: JEDEC Compliance for Maximum
+ * Self-Refresh Command Limit" found in AM335x Silicon Errata
+ * (Document SPRZ360F Revised November 2013) we must configure
+ * the self refresh delay timer to 0xA (8192 cycles) to avoid
+ * generating too many refresh command from the EMIF.
+ */
+static void ti_emif_configure_sr_delay(struct ti_emif_data *emif_data)
+{
+	writel(EMIF_POWER_MGMT_WAIT_SELF_REFRESH_8192_CYCLES,
+	       (emif_data->pm_data.ti_emif_base_addr_virt +
+		EMIF_POWER_MANAGEMENT_CONTROL));
+
+	writel(EMIF_POWER_MGMT_WAIT_SELF_REFRESH_8192_CYCLES,
+	       (emif_data->pm_data.ti_emif_base_addr_virt +
+		EMIF_POWER_MANAGEMENT_CTRL_SHDW));
+}
+
+/**
+ * ti_emif_copy_pm_function_table - copy mapping of pm funcs in sram
+ * @sram_pool: pointer to struct gen_pool where dst resides
+ * @dst: void * to address that table should be copied
+ *
+ * Returns 0 if success other error code if table is not available
+ */
+int ti_emif_copy_pm_function_table(struct gen_pool *sram_pool, void *dst)
+{
+	void *copy_addr;
+
+	if (!emif_instance)
+		return -ENODEV;
+
+	copy_addr = sram_exec_copy(sram_pool, dst,
+				   &emif_instance->pm_functions,
+				   sizeof(emif_instance->pm_functions));
+	if (!copy_addr)
+		return -ENODEV;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ti_emif_copy_pm_function_table);
+
+/**
+ * ti_emif_get_mem_type - return type for memory type in use
+ *
+ * Returns memory type value read from EMIF or error code if fails
+ */
+int ti_emif_get_mem_type(void)
+{
+	unsigned long temp;
+
+	if (!emif_instance)
+		return -ENODEV;
+
+	temp = readl(emif_instance->pm_data.ti_emif_base_addr_virt +
+		     EMIF_SDRAM_CONFIG);
+
+	temp = (temp & SDRAM_TYPE_MASK) >> SDRAM_TYPE_SHIFT;
+	return temp;
+}
+EXPORT_SYMBOL_GPL(ti_emif_get_mem_type);
+
+static const struct of_device_id ti_emif_of_match[] = {
+	{ .compatible = "ti,emif-am3352", .data =
+					(void *)EMIF_SRAM_AM33_REG_LAYOUT, },
+	{ .compatible = "ti,emif-am4372", .data =
+					(void *)EMIF_SRAM_AM43_REG_LAYOUT, },
+	{},
+};
+MODULE_DEVICE_TABLE(of, ti_emif_of_match);
+
+static int ti_emif_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct resource *res;
+	struct device *dev = &pdev->dev;
+	const struct of_device_id *match;
+	struct ti_emif_data *emif_data;
+
+	emif_data = devm_kzalloc(dev, sizeof(*emif_data), GFP_KERNEL);
+	if (!emif_data)
+		return -ENOMEM;
+
+	match = of_match_device(ti_emif_of_match, &pdev->dev);
+	if (!match)
+		return -ENODEV;
+
+	emif_data->pm_data.ti_emif_sram_config = (unsigned long)match->data;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	emif_data->pm_data.ti_emif_base_addr_virt = devm_ioremap_resource(dev,
+									  res);
+	if (IS_ERR(emif_data->pm_data.ti_emif_base_addr_virt)) {
+		dev_err(dev, "could not ioremap emif mem\n");
+		ret = PTR_ERR(emif_data->pm_data.ti_emif_base_addr_virt);
+		return ret;
+	}
+
+	emif_data->pm_data.ti_emif_base_addr_phys = res->start;
+
+	ti_emif_configure_sr_delay(emif_data);
+
+	ret = ti_emif_alloc_sram(dev, emif_data);
+	if (ret)
+		return ret;
+
+	ret = ti_emif_push_sram(dev, emif_data);
+	if (ret)
+		goto fail_free_sram;
+
+	emif_instance = emif_data;
+
+	return 0;
+
+fail_free_sram:
+	ti_emif_free_sram(emif_data);
+
+	return ret;
+}
+
+static int ti_emif_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct ti_emif_data *emif_data = emif_instance;
+
+	emif_instance = NULL;
+
+	ti_emif_free_sram(emif_data);
+
+	return 0;
+}
+
+static struct platform_driver ti_emif_driver = {
+	.probe = ti_emif_probe,
+	.remove = ti_emif_remove,
+	.driver = {
+		.name = KBUILD_MODNAME,
+		.of_match_table = of_match_ptr(ti_emif_of_match),
+	},
+};
+module_platform_driver(ti_emif_driver);
+
+MODULE_AUTHOR("Dave Gerlach <d-gerlach@ti.com>");
+MODULE_DESCRIPTION("Texas Instruments SRAM EMIF driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/memory/ti-emif-sram-pm.S b/drivers/memory/ti-emif-sram-pm.S
new file mode 100644
index 000000000000..a5369181e5c2
--- /dev/null
+++ b/drivers/memory/ti-emif-sram-pm.S
@@ -0,0 +1,334 @@
+/*
+ * Low level PM code for TI EMIF
+ *
+ * Copyright (C) 2016-2017 Texas Instruments Incorporated - http://www.ti.com/
+ *	Dave Gerlach
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <generated/ti-emif-asm-offsets.h>
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/memory.h>
+
+#include "emif.h"
+
+#define EMIF_POWER_MGMT_WAIT_SELF_REFRESH_8192_CYCLES	0x00a0
+#define EMIF_POWER_MGMT_SR_TIMER_MASK			0x00f0
+#define EMIF_POWER_MGMT_SELF_REFRESH_MODE		0x0200
+#define EMIF_POWER_MGMT_SELF_REFRESH_MODE_MASK		0x0700
+
+#define EMIF_SDCFG_TYPE_DDR2				0x2 << SDRAM_TYPE_SHIFT
+#define EMIF_STATUS_READY				0x4
+
+#define AM43XX_EMIF_PHY_CTRL_REG_COUNT                  0x120
+
+#define EMIF_AM437X_REGISTERS				0x1
+
+	.arm
+	.align 3
+
+ENTRY(ti_emif_sram)
+
+/*
+ * void ti_emif_save_context(void)
+ *
+ * Used during suspend to save the context of all required EMIF registers
+ * to local memory if the EMIF is going to lose context during the sleep
+ * transition. Operates on the VIRTUAL address of the EMIF.
+ */
+ENTRY(ti_emif_save_context)
+	stmfd   sp!, {r4 - r11, lr}     @ save registers on stack
+
+	adr	r4, ti_emif_pm_sram_data
+	ldr	r0, [r4, #EMIF_PM_BASE_ADDR_VIRT_OFFSET]
+	ldr	r2, [r4, #EMIF_PM_REGS_VIRT_OFFSET]
+
+	/* Save EMIF configuration */
+	ldr	r1, [r0, #EMIF_SDRAM_CONFIG]
+	str	r1, [r2, #EMIF_SDCFG_VAL_OFFSET]
+
+	ldr	r1, [r0, #EMIF_SDRAM_REFRESH_CONTROL]
+	str	r1, [r2, #EMIF_REF_CTRL_VAL_OFFSET]
+
+	ldr	r1, [r0, #EMIF_SDRAM_TIMING_1]
+	str     r1, [r2, #EMIF_TIMING1_VAL_OFFSET]
+
+	ldr	r1, [r0, #EMIF_SDRAM_TIMING_2]
+	str     r1, [r2, #EMIF_TIMING2_VAL_OFFSET]
+
+	ldr	r1, [r0, #EMIF_SDRAM_TIMING_3]
+	str     r1, [r2, #EMIF_TIMING3_VAL_OFFSET]
+
+	ldr	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
+	str     r1, [r2, #EMIF_PMCR_VAL_OFFSET]
+
+	ldr	r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
+	str     r1, [r2, #EMIF_PMCR_SHDW_VAL_OFFSET]
+
+	ldr	r1, [r0, #EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG]
+	str     r1, [r2, #EMIF_ZQCFG_VAL_OFFSET]
+
+	ldr	r1, [r0, #EMIF_DDR_PHY_CTRL_1]
+	str     r1, [r2, #EMIF_DDR_PHY_CTLR_1_OFFSET]
+
+	ldr	r1, [r0, #EMIF_COS_CONFIG]
+	str     r1, [r2, #EMIF_COS_CONFIG_OFFSET]
+
+	ldr	r1, [r0, #EMIF_PRIORITY_TO_CLASS_OF_SERVICE_MAPPING]
+	str     r1, [r2, #EMIF_PRIORITY_TO_COS_MAPPING_OFFSET]
+
+	ldr	r1, [r0, #EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_1_MAPPING]
+	str     r1, [r2, #EMIF_CONNECT_ID_SERV_1_MAP_OFFSET]
+
+	ldr	r1, [r0, #EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_2_MAPPING]
+	str     r1, [r2, #EMIF_CONNECT_ID_SERV_2_MAP_OFFSET]
+
+	ldr	r1, [r0, #EMIF_OCP_CONFIG]
+	str     r1, [r2, #EMIF_OCP_CONFIG_VAL_OFFSET]
+
+	ldr	r5, [r4, #EMIF_PM_CONFIG_OFFSET]
+	cmp	r5, #EMIF_SRAM_AM43_REG_LAYOUT
+	bne	emif_skip_save_extra_regs
+
+	ldr	r1, [r0, #EMIF_READ_WRITE_LEVELING_RAMP_CONTROL]
+	str     r1, [r2, #EMIF_RD_WR_LEVEL_RAMP_CTRL_OFFSET]
+
+	ldr	r1, [r0, #EMIF_READ_WRITE_EXECUTION_THRESHOLD]
+	str     r1, [r2, #EMIF_RD_WR_EXEC_THRESH_OFFSET]
+
+	ldr	r1, [r0, #EMIF_LPDDR2_NVM_TIMING]
+	str     r1, [r2, #EMIF_LPDDR2_NVM_TIM_OFFSET]
+
+	ldr	r1, [r0, #EMIF_LPDDR2_NVM_TIMING_SHDW]
+	str     r1, [r2, #EMIF_LPDDR2_NVM_TIM_SHDW_OFFSET]
+
+	ldr	r1, [r0, #EMIF_DLL_CALIB_CTRL]
+	str     r1, [r2, #EMIF_DLL_CALIB_CTRL_VAL_OFFSET]
+
+	ldr	r1, [r0, #EMIF_DLL_CALIB_CTRL_SHDW]
+	str     r1, [r2, #EMIF_DLL_CALIB_CTRL_VAL_SHDW_OFFSET]
+
+	/* Loop and save entire block of emif phy regs */
+	mov	r5, #0x0
+	add	r4, r2, #EMIF_EXT_PHY_CTRL_VALS_OFFSET
+	add	r3, r0, #EMIF_EXT_PHY_CTRL_1
+ddr_phy_ctrl_save:
+	ldr	r1, [r3, r5]
+	str	r1, [r4, r5]
+	add	r5, r5, #0x4
+	cmp	r5, #AM43XX_EMIF_PHY_CTRL_REG_COUNT
+	bne	ddr_phy_ctrl_save
+
+emif_skip_save_extra_regs:
+	ldmfd	sp!, {r4 - r11, pc}	@ restore regs and return
+ENDPROC(ti_emif_save_context)
+
+/*
+ * void ti_emif_restore_context(void)
+ *
+ * Used during resume to restore the context of all required EMIF registers
+ * from local memory after the EMIF has lost context during a sleep transition.
+ * Operates on the PHYSICAL address of the EMIF.
+ */
+ENTRY(ti_emif_restore_context)
+	adr	r4, ti_emif_pm_sram_data
+	ldr	r0, [r4, #EMIF_PM_BASE_ADDR_PHYS_OFFSET]
+	ldr	r2, [r4, #EMIF_PM_REGS_PHYS_OFFSET]
+
+	/* Config EMIF Timings */
+	ldr     r1, [r2, #EMIF_DDR_PHY_CTLR_1_OFFSET]
+	str	r1, [r0, #EMIF_DDR_PHY_CTRL_1]
+	str	r1, [r0, #EMIF_DDR_PHY_CTRL_1_SHDW]
+
+	ldr     r1, [r2, #EMIF_TIMING1_VAL_OFFSET]
+	str	r1, [r0, #EMIF_SDRAM_TIMING_1]
+	str	r1, [r0, #EMIF_SDRAM_TIMING_1_SHDW]
+
+	ldr     r1, [r2, #EMIF_TIMING2_VAL_OFFSET]
+	str	r1, [r0, #EMIF_SDRAM_TIMING_2]
+	str	r1, [r0, #EMIF_SDRAM_TIMING_2_SHDW]
+
+	ldr     r1, [r2, #EMIF_TIMING3_VAL_OFFSET]
+	str	r1, [r0, #EMIF_SDRAM_TIMING_3]
+	str	r1, [r0, #EMIF_SDRAM_TIMING_3_SHDW]
+
+	ldr     r1, [r2, #EMIF_REF_CTRL_VAL_OFFSET]
+	str	r1, [r0, #EMIF_SDRAM_REFRESH_CONTROL]
+	str	r1, [r0, #EMIF_SDRAM_REFRESH_CTRL_SHDW]
+
+	ldr     r1, [r2, #EMIF_PMCR_VAL_OFFSET]
+	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
+
+	ldr     r1, [r2, #EMIF_PMCR_SHDW_VAL_OFFSET]
+	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
+
+	ldr     r1, [r2, #EMIF_COS_CONFIG_OFFSET]
+	str	r1, [r0, #EMIF_COS_CONFIG]
+
+	ldr     r1, [r2, #EMIF_PRIORITY_TO_COS_MAPPING_OFFSET]
+	str	r1, [r0, #EMIF_PRIORITY_TO_CLASS_OF_SERVICE_MAPPING]
+
+	ldr	r1, [r2, #EMIF_CONNECT_ID_SERV_1_MAP_OFFSET]
+	str	r1, [r0, #EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_1_MAPPING]
+
+	ldr     r1, [r2, #EMIF_CONNECT_ID_SERV_2_MAP_OFFSET]
+	str	r1, [r0, #EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_2_MAPPING]
+
+	ldr     r1, [r2, #EMIF_OCP_CONFIG_VAL_OFFSET]
+	str	r1, [r0, #EMIF_OCP_CONFIG]
+
+	ldr	r5, [r4, #EMIF_PM_CONFIG_OFFSET]
+	cmp	r5, #EMIF_SRAM_AM43_REG_LAYOUT
+	bne	emif_skip_restore_extra_regs
+
+	ldr     r1, [r2, #EMIF_RD_WR_LEVEL_RAMP_CTRL_OFFSET]
+	str	r1, [r0, #EMIF_READ_WRITE_LEVELING_RAMP_CONTROL]
+
+	ldr     r1, [r2, #EMIF_RD_WR_EXEC_THRESH_OFFSET]
+	str	r1, [r0, #EMIF_READ_WRITE_EXECUTION_THRESHOLD]
+
+	ldr     r1, [r2, #EMIF_LPDDR2_NVM_TIM_OFFSET]
+	str	r1, [r0, #EMIF_LPDDR2_NVM_TIMING]
+
+	ldr     r1, [r2, #EMIF_LPDDR2_NVM_TIM_SHDW_OFFSET]
+	str	r1, [r0, #EMIF_LPDDR2_NVM_TIMING_SHDW]
+
+	ldr     r1, [r2, #EMIF_DLL_CALIB_CTRL_VAL_OFFSET]
+	str	r1, [r0, #EMIF_DLL_CALIB_CTRL]
+
+	ldr     r1, [r2, #EMIF_DLL_CALIB_CTRL_VAL_SHDW_OFFSET]
+	str	r1, [r0, #EMIF_DLL_CALIB_CTRL_SHDW]
+
+	ldr     r1, [r2, #EMIF_ZQCFG_VAL_OFFSET]
+	str	r1, [r0, #EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG]
+
+	/* Loop and restore entire block of emif phy regs */
+	mov	r5, #0x0
+	/* Load ti_emif_regs_amx3 + EMIF_EXT_PHY_CTRL_VALS_OFFSET for address
+	 * to phy register save space
+	 */
+	add	r3, r2, #EMIF_EXT_PHY_CTRL_VALS_OFFSET
+	add	r4, r0, #EMIF_EXT_PHY_CTRL_1
+ddr_phy_ctrl_restore:
+	ldr	r1, [r3, r5]
+	str	r1, [r4, r5]
+	add	r5, r5, #0x4
+	cmp	r5, #AM43XX_EMIF_PHY_CTRL_REG_COUNT
+	bne	ddr_phy_ctrl_restore
+
+emif_skip_restore_extra_regs:
+	/*
+	 * Output impedence calib needed only for DDR3
+	 * but since the initial state of this will be
+	 * disabled for DDR2 no harm in restoring the
+	 * old configuration
+	 */
+	ldr     r1, [r2, #EMIF_ZQCFG_VAL_OFFSET]
+	str	r1, [r0, #EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG]
+
+	/* Write to sdcfg last for DDR2 only */
+	ldr	r1, [r2, #EMIF_SDCFG_VAL_OFFSET]
+	and	r2, r1, #SDRAM_TYPE_MASK
+	cmp	r2, #EMIF_SDCFG_TYPE_DDR2
+	streq	r1, [r0, #EMIF_SDRAM_CONFIG]
+
+	mov	pc, lr
+ENDPROC(ti_emif_restore_context)
+
+/*
+ * void ti_emif_enter_sr(void)
+ *
+ * Programs the EMIF to tell the SDRAM to enter into self-refresh
+ * mode during a sleep transition. Operates on the VIRTUAL address
+ * of the EMIF.
+ */
+ENTRY(ti_emif_enter_sr)
+	stmfd   sp!, {r4 - r11, lr}     @ save registers on stack
+
+	adr	r4, ti_emif_pm_sram_data
+	ldr	r0, [r4, #EMIF_PM_BASE_ADDR_VIRT_OFFSET]
+	ldr	r2, [r4, #EMIF_PM_REGS_VIRT_OFFSET]
+
+	ldr	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
+	bic	r1, r1, #EMIF_POWER_MGMT_SELF_REFRESH_MODE_MASK
+	orr	r1, r1, #EMIF_POWER_MGMT_SELF_REFRESH_MODE
+	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
+
+	ldmfd	sp!, {r4 - r11, pc}	@ restore regs and return
+ENDPROC(ti_emif_enter_sr)
+
+/*
+ * void ti_emif_exit_sr(void)
+ *
+ * Programs the EMIF to tell the SDRAM to exit self-refresh mode
+ * after a sleep transition. Operates on the PHYSICAL address of
+ * the EMIF.
+ */
+ENTRY(ti_emif_exit_sr)
+	adr	r4, ti_emif_pm_sram_data
+	ldr	r0, [r4, #EMIF_PM_BASE_ADDR_PHYS_OFFSET]
+	ldr	r2, [r4, #EMIF_PM_REGS_PHYS_OFFSET]
+
+	/*
+	 * Toggle EMIF to exit refresh mode:
+	 * if EMIF lost context, PWR_MGT_CTRL is currently 0, writing disable
+	 *   (0x0), wont do diddly squat! so do a toggle from SR(0x2) to disable
+	 *   (0x0) here.
+	 * *If* EMIF did not lose context, nothing broken as we write the same
+	 *   value(0x2) to reg before we write a disable (0x0).
+	 */
+	ldr	r1, [r2, #EMIF_PMCR_VAL_OFFSET]
+	bic	r1, r1, #EMIF_POWER_MGMT_SELF_REFRESH_MODE_MASK
+	orr	r1, r1, #EMIF_POWER_MGMT_SELF_REFRESH_MODE
+	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
+	bic	r1, r1, #EMIF_POWER_MGMT_SELF_REFRESH_MODE_MASK
+	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
+
+        /* Wait for EMIF to become ready */
+1:	ldr     r1, [r0, #EMIF_STATUS]
+	tst     r1, #EMIF_STATUS_READY
+	beq     1b
+
+	mov	pc, lr
+ENDPROC(ti_emif_exit_sr)
+
+/*
+ * void ti_emif_abort_sr(void)
+ *
+ * Disables self-refresh after a failed transition to a low-power
+ * state so the kernel can jump back to DDR and follow abort path.
+ * Operates on the VIRTUAL address of the EMIF.
+ */
+ENTRY(ti_emif_abort_sr)
+	stmfd   sp!, {r4 - r11, lr}     @ save registers on stack
+
+	adr	r4, ti_emif_pm_sram_data
+	ldr	r0, [r4, #EMIF_PM_BASE_ADDR_VIRT_OFFSET]
+	ldr	r2, [r4, #EMIF_PM_REGS_VIRT_OFFSET]
+
+	ldr	r1, [r2, #EMIF_PMCR_VAL_OFFSET]
+	bic	r1, r1, #EMIF_POWER_MGMT_SELF_REFRESH_MODE_MASK
+	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
+
+	/* Wait for EMIF to become ready */
+1:	ldr     r1, [r0, #EMIF_STATUS]
+	tst     r1, #EMIF_STATUS_READY
+	beq     1b
+
+	ldmfd	sp!, {r4 - r11, pc}	@ restore regs and return
+ENDPROC(ti_emif_abort_sr)
+
+	.align 3
+ENTRY(ti_emif_pm_sram_data)
+	.space EMIF_PM_DATA_SIZE
+ENTRY(ti_emif_sram_sz)
+        .word   . - ti_emif_save_context
diff --git a/include/linux/ti-emif-sram.h b/include/linux/ti-emif-sram.h
new file mode 100644
index 000000000000..45bc6b376492
--- /dev/null
+++ b/include/linux/ti-emif-sram.h
@@ -0,0 +1,69 @@
+/*
+ * TI AM33XX EMIF Routines
+ *
+ * Copyright (C) 2016-2017 Texas Instruments Inc.
+ *	Dave Gerlach
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef __LINUX_TI_EMIF_H
+#define __LINUX_TI_EMIF_H
+
+#include <linux/kbuild.h>
+#include <linux/types.h>
+#ifndef __ASSEMBLY__
+
+struct emif_regs_amx3 {
+	u32 emif_sdcfg_val;
+	u32 emif_timing1_val;
+	u32 emif_timing2_val;
+	u32 emif_timing3_val;
+	u32 emif_ref_ctrl_val;
+	u32 emif_zqcfg_val;
+	u32 emif_pmcr_val;
+	u32 emif_pmcr_shdw_val;
+	u32 emif_rd_wr_level_ramp_ctrl;
+	u32 emif_rd_wr_exec_thresh;
+	u32 emif_cos_config;
+	u32 emif_priority_to_cos_mapping;
+	u32 emif_connect_id_serv_1_map;
+	u32 emif_connect_id_serv_2_map;
+	u32 emif_ocp_config_val;
+	u32 emif_lpddr2_nvm_tim;
+	u32 emif_lpddr2_nvm_tim_shdw;
+	u32 emif_dll_calib_ctrl_val;
+	u32 emif_dll_calib_ctrl_val_shdw;
+	u32 emif_ddr_phy_ctlr_1;
+	u32 emif_ext_phy_ctrl_vals[120];
+};
+
+struct ti_emif_pm_data {
+	void __iomem *ti_emif_base_addr_virt;
+	phys_addr_t ti_emif_base_addr_phys;
+	unsigned long ti_emif_sram_config;
+	struct emif_regs_amx3 *regs_virt;
+	phys_addr_t regs_phys;
+} __packed __aligned(8);
+
+struct ti_emif_pm_functions {
+	u32 save_context;
+	u32 restore_context;
+	u32 enter_sr;
+	u32 exit_sr;
+	u32 abort_sr;
+} __packed __aligned(8);
+
+struct gen_pool;
+
+int ti_emif_copy_pm_function_table(struct gen_pool *sram_pool, void *dst);
+int ti_emif_get_mem_type(void);
+
+#endif
+#endif /* __LINUX_TI_EMIF_H */
-- 
2.15.0

^ permalink raw reply related

* [PATCH v6 1/2] Documentation: dt: Update ti,emif bindings
From: Dave Gerlach @ 2017-11-30 22:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1512082568-5012-1-git-send-email-d-gerlach@ti.com>

Update the Texas Instruments EMIF binding document to include the device
tree bindings for ti,emif-am3352 and ti,emif-am4372 which are used by
the ti-emif-sram driver to provide low-level PM functionality.

Acked-by: Rob Herring <robh@kernel.org>
Acked-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
---
 .../devicetree/bindings/memory-controllers/ti/emif.txt  | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/memory-controllers/ti/emif.txt b/Documentation/devicetree/bindings/memory-controllers/ti/emif.txt
index fd823d6091b2..29a99871e808 100644
--- a/Documentation/devicetree/bindings/memory-controllers/ti/emif.txt
+++ b/Documentation/devicetree/bindings/memory-controllers/ti/emif.txt
@@ -23,6 +23,13 @@ Required properties:
   the value shall be "emif<n>" where <n> is the number of the EMIF
   instance with base 1.
 
+Required only for "ti,emif-am3352" and "ti,emif-am4372":
+- sram			: Phandles for generic sram driver nodes,
+  first should be type 'protect-exec' for the driver to use to copy
+  and run PM functions, second should be regular pool to be used for
+  data region for code. See Documentation/devicetree/bindings/sram/sram.txt
+  for more details.
+
 Optional properties:
 - cs1-used		: Have this property if CS1 of this EMIF
   instance has a memory part attached to it. If there is a memory
@@ -44,7 +51,7 @@ Optional properties:
 - hw-caps-temp-alert	: Have this property if the controller
   has capability for generating SDRAM temperature alerts
 
-Example:
+-Examples:
 
 emif1: emif at 0x4c000000 {
 	compatible	= "ti,emif-4d";
@@ -56,3 +63,11 @@ emif1: emif at 0x4c000000 {
 	hw-caps-ll-interface;
 	hw-caps-temp-alert;
 };
+
+/* From am33xx.dtsi */
+emif: emif at 4c000000 {
+        compatible = "ti,emif-am3352";
+        reg =   <0x4C000000 0x1000>;
+        sram = <&pm_sram_code
+                &pm_sram_data>;
+};
-- 
2.15.0

^ permalink raw reply related

* [PATCH v6 0/2] memory: Introduce ti-emif-sram driver
From: Dave Gerlach @ 2017-11-30 22:56 UTC (permalink / raw)
  To: linux-arm-kernel

This is a resend of v5 of this series found here [1]. It introduces
relocatable PM handlers for the emif that are copied to sram and
run from there during low power mode entry.

The patches still have the previous ACKs but have a small change to
accomodate a change made by Tony in commit cd57dc5a2099 ("ARM: dts:
Add missing hwmod related nodes for am33xx"). If there are objections
to this let me know ASAP.

Now that a hwmod is present for the am335x EMIF, on probe fail the call to
pm_runtime_put_sync causes the board to hang. In fact, this emif driver should
never alter the PM state of the hardware at all through normal kernel calls, it
is the job of the suspend handlers that are added, that is the whole point of
this driver. Because of this, I have dropped all runtime pm calls, as any
change to the PM state while the kernel is running is dangerous as we may shut
of the memory controller. It makes the most sense just to drop runtime PM from
the driver entirely. Besides that patch is unchanged.

This code is required for low-power modes to work on AM335x and AM437x and a
forthcoming PM series for those platforms will depend on this series. After
both this and the PM series are reviewed I will send the necessary device tree
changes for both, but in the meantime all remaining patches for am335x and
am437x PM can be found here [2].

Regards,
Dave

[1] https://www.spinics.net/lists/arm-kernel/msg611537.html
[2] https://github.com/dgerlach/linux-pm/tree/upstream/v4.15/amx3-suspend-v6

Dave Gerlach (2):
  Documentation: dt: Update ti,emif bindings
  memory: ti-emif-sram: introduce relocatable suspend/resume handlers

 .../bindings/memory-controllers/ti/emif.txt        |  17 +-
 drivers/memory/Kconfig                             |  10 +
 drivers/memory/Makefile                            |   8 +
 drivers/memory/Makefile.asm-offsets                |   5 +
 drivers/memory/emif-asm-offsets.c                  |  92 ++++++
 drivers/memory/emif.h                              |  17 ++
 drivers/memory/ti-emif-pm.c                        | 325 ++++++++++++++++++++
 drivers/memory/ti-emif-sram-pm.S                   | 334 +++++++++++++++++++++
 include/linux/ti-emif-sram.h                       |  69 +++++
 9 files changed, 876 insertions(+), 1 deletion(-)
 create mode 100644 drivers/memory/Makefile.asm-offsets
 create mode 100644 drivers/memory/emif-asm-offsets.c
 create mode 100644 drivers/memory/ti-emif-pm.c
 create mode 100644 drivers/memory/ti-emif-sram-pm.S
 create mode 100644 include/linux/ti-emif-sram.h

-- 
2.15.0

^ permalink raw reply

* [PATCH 5/5] mtd: nand: add ->exec_op() implementation
From: Miquel RAYNAL @ 2017-11-30 22:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171130215025.67f74437@bbrezillon>

> > diff --git a/drivers/mtd/nand/nand_base.c
> > b/drivers/mtd/nand/nand_base.c index 52965a8aeb2c..46bf31aff909
> > 100644 --- a/drivers/mtd/nand/nand_base.c
> > +++ b/drivers/mtd/nand/nand_base.c
> > @@ -689,6 +689,59 @@ static void nand_wait_status_ready(struct
> > mtd_info *mtd, unsigned long timeo) };
> >  
> >  /**
> > + * nand_soft_waitrdy - Read the status waiting for it to be ready
> > + * @chip: NAND chip structure
> > + * @timeout_ms: Timeout in ms
> > + *
> > + * Poll the status using ->exec_op() until it is ready unless it
> > takes too
> > + * much time.
> > + *
> > + * This helper is intended to be used by drivers without R/B pin
> > available to
> > + * poll for the chip status until ready and may be called at any
> > time in the
> > + * middle of any set of instruction. The READ_STATUS just need to
> > ask a single
> > + * time for it and then any read will return the status. Once the
> > READ_STATUS
> > + * cycles are done, the function will send a READ0 command to
> > cancel the
> > + * "READ_STATUS state" and let the normal flow of operation to
> > continue.
> > + *
> > + * This helper *cannot* send a WAITRDY command or ->exec_op()
> > implementations  
> 
> 					  ^ instruction
> 
> > + * using it will enter an infinite loop.  
> 
> Hm, not sure why this would be the case, but okay. Maybe you should
> move this comment outside the kernel doc header, since this is an
> implementation detail, not something the caller/user should be aware
> of.

Right.

> 
> There's another important aspect to mention here: this function can
> only be called from an ->exec_op() implementation if this
> implementation is re-entrant.

I do not agree with this statement: this function can be called from an
->exec_op() implementation even if it is not reentrant as long as it
does not send a WAITRDY instruction itself. No?

Or maybe you wanted to point that the entire ->exec_op()
implementation must be reentrant in order to use this function in it?

> 
> > + *
> > + * Return 0 if the NAND chip is ready, a negative error otherwise.
> > + */
> > +int nand_soft_waitrdy(struct nand_chip *chip, unsigned long
> > timeout_ms) +{
> > +	u8 status = 0;
> > +	int ret;
> > +
> > +	if (!chip->exec_op)
> > +		return -ENOTSUPP;
> > +
> > +	ret = nand_status_op(chip, NULL);
> > +	if (ret)
> > +		return ret;
> > +
> > +	timeout_ms = jiffies + msecs_to_jiffies(timeout_ms);
> > +	do {
> > +		ret = nand_read_data_op(chip, &status,
> > sizeof(status), true);
> > +		if (ret)
> > +			break;
> > +
> > +		if (status & NAND_STATUS_READY)
> > +			break;
> > +
> > +		udelay(100);  
> 
> Sounds a bit high, especially for a read page which takes around 20us.

Well, this value is arbitrary but greping for NAND_OP_WAIT_RDY tells us
the different timeouts with which this function is usually called, to
get an idea of the possible wait periods: tR, tBERS, tFEAT, tPROG, tRST.

While a tR_max is 200us, a tRST_max is 250000us. That is why I choose
100us as period, which I found somehow well tuned for every timeout. But
if you think most of the time the delay will be smaller, I will update
the value to repeat the operation every 20us.

> 
> > +	} while	(time_before(jiffies, timeout_ms));
> > +
> > +	nand_exit_status_op(chip);
> > +
> > +	if (ret)
> > +		return ret;
> > +
> > +	return status & NAND_STATUS_READY ? 0 : -ETIMEDOUT;
> > +};
> > +EXPORT_SYMBOL_GPL(nand_soft_waitrdy);
> > +

^ permalink raw reply

* [PATCH v3 4/4] DTS: Pandora: fix panel compatibility string
From: Sebastian Reichel @ 2017-11-30 22:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171130152430.GM28152@atomide.com>

Hi,

On Thu, Nov 30, 2017 at 07:24:30AM -0800, Tony Lindgren wrote:
> * H. Nikolaus Schaller <hns@goldelico.com> [171128 18:35]:
> > Hi,
> > 
> > > Am 28.11.2017 um 17:18 schrieb Tony Lindgren <tony@atomide.com>:
> > > 
> > > * H. Nikolaus Schaller <hns@goldelico.com> [171128 16:17]:
> > >> Hi Tony,
> > >> 
> > >>> Am 28.11.2017 um 17:04 schrieb Tony Lindgren <tony@atomide.com>:
> > >>> 
> > >>> * H. Nikolaus Schaller <hns@goldelico.com> [171128 15:52]:
> > >>>> We can remove the unnecessary "omapdss," prefix because
> > >>>> the omapdrm driver takes care of it when matching with
> > >>>> the driver table.
> > >>> 
> > >>> So is this needed as a fix or is this another clean-up?
> > >>> 
> > >>> So is this is really needed as a fix?
> > >> 
> > >> Hm. How do you differentiate between "fix" and "cleanup"?
> > >> Maybe it is more a wording than a content issue...
> > >> 
> > >> For me it is a "fix" because it is semantically wrong to have
> > >> a prefix where it is not needed. And "fixing" it changes the
> > >> compiler output by 8 bytes.
> > > 
> > > How about let's call it a "typo fix" then? :)
> > 
> > Well, it is not really a typo.
> 
> Well what if the stable people pick it into earlier stable series
> based on the word fix in the subject? That has happened before.
> 
> I suggest you update the dts patches to use wording like
> "update compatible to use new naming" or something similar.

Patch 4/4 is a Fix and should be applied to stable trees. "omapdss,"
prefix was never supposed to be in the DTS files, is not supposed to
be in there now and will break some time in the future.

Explanation: The early init of omapdss adds the prefix at runtime,
so that the binding can use generic properties and the kernel can
use omapdss specific drivers until the generic ones can be used.

-- Sebastian
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20171130/f6407f70/attachment.sig>

^ permalink raw reply

* [PATCH 1/5] mtd: nand: use usual return values for the ->erase() hook
From: Miquel RAYNAL @ 2017-11-30 22:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171130215113.458d616f@bbrezillon>

> > diff --git a/drivers/mtd/nand/nand_base.c
> > b/drivers/mtd/nand/nand_base.c index 630048f5abdc..4d1f2bda6095
> > 100644 --- a/drivers/mtd/nand/nand_base.c
> > +++ b/drivers/mtd/nand/nand_base.c
> > @@ -3077,7 +3077,7 @@ int nand_erase_nand(struct mtd_info *mtd,
> > struct erase_info *instr, status = chip->erase(mtd, page &
> > chip->pagemask); 
> >  		/* See if block erase succeeded */
> > -		if (status & NAND_STATUS_FAIL) {
> > +		if (status) {
> >  			pr_debug("%s: failed erase, page 0x%08x\n",
> >  					__func__, page);
> >  			instr->state = MTD_ERASE_FAILED;  
> 
> You forgot to patch single_erase() accordingly.

Right, sorry about that, I will fix that.

Thanks,
Miqu?l

^ permalink raw reply

* [PATCH RFC 2/2] arm64: allwinner: a64: Add Brava Keller initial support
From: Philippe Ombredanne @ 2017-11-30 21:36 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1512067334-12761-2-git-send-email-jagan@amarulasolutions.com>

Jagan,

On Thu, Nov 30, 2017 at 7:42 PM, Jagan Teki <jagannadh.teki@gmail.com> wrote:
[]
> diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-brava-keller.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-brava-keller.dts
> new file mode 100644
> index 0000000..f5303a3
> --- /dev/null
> +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-brava-keller.dts
> @@ -0,0 +1,244 @@
> +/*
> + * Copyright (C) 2017 Jagan Teki <jagan@amarulasolutions.com>
> + *
> + * This file is dual-licensed: you can use it either under the terms
> + * of the GPL or the X11 license, at your option. Note that this dual
> + * licensing only applies to this file, and not this project as a
> + * whole.
> + *
> + *  a) This library is free software; you can redistribute it and/or
> + *     modify it under the terms of the GNU General Public License as
> + *     published by the Free Software Foundation; either version 2 of the
> + *     License, or (at your option) any later version.
> + *
> + *     This library 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.
> + *
> + * Or, alternatively,
> + *
> + *  b) Permission is hereby granted, free of charge, to any person
> + *     obtaining a copy of this software and associated documentation
> + *     files (the "Software"), to deal in the Software without
> + *     restriction, including without limitation the rights to use,
> + *     copy, modify, merge, publish, distribute, sublicense, and/or
> + *     sell copies of the Software, and to permit persons to whom the
> + *     Software is furnished to do so, subject to the following
> + *     conditions:
> + *
> + *     The above copyright notice and this permission notice shall be
> + *     included in all copies or substantial portions of the Software.
> + *
> + *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> + *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
> + *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> + *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
> + *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
> + *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> + *     OTHER DEALINGS IN THE SOFTWARE.
> + */

Rather than this long boilerplate, you might want to use the SPDX ids,
as started by Greg and documented by Thomas.
Noe that Linus wants the // comment style for the license line, and
since there is only two line left here I suggest using it for both
lines.
You can check also the recent doc patch posted by Thomas (tglx) and
comments from Linus and Greg.

So I guess you could use this:

> +// Copyright (C) 2017 Jagan Teki <jagan@amarulasolutions.com>
> +// SPDX-License-Indentifier: (GPL-2.0+ OR MIT)

NB: what you call X11 is has the MIT license id in the SPDX license list.

So you could replace 32 lines by only two lines :) it'[s neat right?

And this would also help as we have tagged already ~15K files, so it
would help to use this for new files so the amount of cleanup work
still left does not increase. Thank you for your kind consideration!

-- 
Cordially
Philippe Ombredanne

^ permalink raw reply

* [PATCH v2 2/2] ARM: dts: at91: disable the nxp,se97b SMBUS timeout on the TSE-850
From: Guenter Roeck @ 2017-11-30 21:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <acaea4f3-d273-444a-4df4-e6d1b35c876d@axentia.se>

On Thu, Nov 30, 2017 at 07:46:09PM +0100, Peter Rosin wrote:
> On 2017-11-30 18:26, Alexandre Belloni wrote:
> > On 30/11/2017 at 09:16:38 -0800, Guenter Roeck wrote:
> >> On Wed, Nov 29, 2017 at 09:56:29PM +0100, Alexandre Belloni wrote:
> >>> On 29/11/2017 at 12:53:11 -0800, Guenter Roeck wrote:
> >>>> On Mon, Nov 27, 2017 at 05:31:01PM +0100, Peter Rosin wrote:
> >>>>> The I2C adapter driver is sometimes slow, causing the SCL line to
> >>>>> be stuck low for more than the stipulated SMBUS timeout of 25-35 ms.
> >>>>> This causes the client device to give up which in turn causes silent
> >>>>> corruption of data. So, disable the SMBUS timeout in the client device.
> >>>>>
> >>>>> Signed-off-by: Peter Rosin <peda@axentia.se>
> >>>>
> >>>> Acked-by: Guenter Roeck <linux@roeck-us.net>
> >>>>
> >>>> I assume this will be sent upstream through an arm tree.
> >>>>
> >>>
> >>> Yes, I'm applying it right now.
> >>>
> >> Are you going to apply the patch for 4.15, or queue it up for 4.16 ?
> >> I have been arguing with myself if this is a feature or a bug fix.
> >> So far I queued the driver change up for 4.16, but I am open to
> >> applying it to 4.15. Any thoughts ?
> >>
> > 
> > I was wondering that myself. I'm open to have it as a fix in 4.15. Or
> > maybe Peter can send the series to stable if he needs it in 4.14.
> > 
> > Peter, what do you think/want?
> 
> TL;DR Either way is fine.
> 
> I think it's a bugfix; it fixes real problems where the application
> misbehave due to faulty content when reading from an eeprom. I'm
> expecting to make a new release for the hw in question RSN and these
> are the only local patches. So, it would be nice if they made it to
> 4.14.x before my release happens. However, it's not like it's difficult
> to rebase the patches should that backport not happen or take too long.
> 
Good enough for me. I'll send it as a fix for v4.15, with Cc: stable.

Guenter

> The badness started to happen much more frequently due to some timing
> difference affecting the i2c bus driver, but in theory it's a problem
> that has been there from the start. I have just not noticed it before...
> 
> Cheers,
> Peter
> --
> To unsubscribe from this list: send the line "unsubscribe linux-hwmon" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH 1/5] mtd: nand: use usual return values for the ->erase() hook
From: Boris Brezillon @ 2017-11-30 20:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171130170132.27522-2-miquel.raynal@free-electrons.com>

On Thu, 30 Nov 2017 18:01:28 +0100
Miquel Raynal <miquel.raynal@free-electrons.com> wrote:

> Avoid using specific defined values for checking returned status of the
> ->erase() hook. Instead, use usual negative error values on failure,  
> zero otherwise.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@free-electrons.com>
> ---
>  drivers/mtd/nand/denali.c    | 2 +-
>  drivers/mtd/nand/docg4.c     | 7 ++++++-
>  drivers/mtd/nand/nand_base.c | 2 +-
>  3 files changed, 8 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
> index 34008a02ddb0..3e19861a46c6 100644
> --- a/drivers/mtd/nand/denali.c
> +++ b/drivers/mtd/nand/denali.c
> @@ -951,7 +951,7 @@ static int denali_erase(struct mtd_info *mtd, int page)
>  	irq_status = denali_wait_for_irq(denali,
>  					 INTR__ERASE_COMP | INTR__ERASE_FAIL);
>  
> -	return irq_status & INTR__ERASE_COMP ? 0 : NAND_STATUS_FAIL;
> +	return irq_status & INTR__ERASE_COMP ? 0 : -EIO;
>  }
>  
>  static int denali_setup_data_interface(struct mtd_info *mtd, int chipnr,
> diff --git a/drivers/mtd/nand/docg4.c b/drivers/mtd/nand/docg4.c
> index 2436cbc71662..45c01b4b34c7 100644
> --- a/drivers/mtd/nand/docg4.c
> +++ b/drivers/mtd/nand/docg4.c
> @@ -900,6 +900,7 @@ static int docg4_erase_block(struct mtd_info *mtd, int page)
>  	struct docg4_priv *doc = nand_get_controller_data(nand);
>  	void __iomem *docptr = doc->virtadr;
>  	uint16_t g4_page;
> +	int status;
>  
>  	dev_dbg(doc->dev, "%s: page %04x\n", __func__, page);
>  
> @@ -939,7 +940,11 @@ static int docg4_erase_block(struct mtd_info *mtd, int page)
>  	poll_status(doc);
>  	write_nop(docptr);
>  
> -	return nand->waitfunc(mtd, nand);
> +	status = nand->waitfunc(mtd, nand);
> +	if (status < 0)
> +		return status;
> +
> +	return status & NAND_STATUS_FAIL ? -EIO : 0;
>  }
>  
>  static int write_page(struct mtd_info *mtd, struct nand_chip *nand,
> diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
> index 630048f5abdc..4d1f2bda6095 100644
> --- a/drivers/mtd/nand/nand_base.c
> +++ b/drivers/mtd/nand/nand_base.c
> @@ -3077,7 +3077,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
>  		status = chip->erase(mtd, page & chip->pagemask);
>  
>  		/* See if block erase succeeded */
> -		if (status & NAND_STATUS_FAIL) {
> +		if (status) {
>  			pr_debug("%s: failed erase, page 0x%08x\n",
>  					__func__, page);
>  			instr->state = MTD_ERASE_FAILED;

You forgot to patch single_erase() accordingly.

^ permalink raw reply

* [PATCH 5/5] mtd: nand: add ->exec_op() implementation
From: Boris Brezillon @ 2017-11-30 20:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171130170132.27522-6-miquel.raynal@free-electrons.com>

On Thu, 30 Nov 2017 18:01:32 +0100
Miquel Raynal <miquel.raynal@free-electrons.com> wrote:

> Introduce a new interface to instruct NAND controllers to send specific
> NAND operations. The new interface takes the form of a single method
> called ->exec_op(). This method is designed to replace ->cmd_ctrl(),
> ->cmdfunc() and ->read/write_byte/word/buf() hooks.  
> 
> ->exec_op() is passed a set of instructions describing the operation  
> to execute. Each instruction has a type (ADDR, CMD, DATA, WAITRDY)
> and delay. The type is directly matching the description of NAND
> operations in various NAND datasheet and standards (ONFI, JEDEC), the
> delay is here to help simple controllers wait enough time between each
> instruction. Advanced controllers with integrated timings control can
> ignore these delays.
> 
> Advanced controllers (that are not limited to independent ADDR, CMD and
> DATA cycles) may use the parser added by this commit to get the best
> matching hook, if any. The instructions may be split by the parser in
> order to comply with the controller constraints filled in an array of
> supported patterns.
> 
> For instance, if a controller driver declares supporting up to 4 address
> cycles and then writes up to 512 bytes within one pattern (both are
> optional in this pattern):
>         NAND_OP_PARSER_PAT_ADDR_ELEM(true, 4)
>         NAND_OP_PARSER_PAT_DATA_OUT_ELEM(true, 512)
> It means that if the matching operation is made of 5 address cycles
> followed by 1024 bytes to write, then the controller will be asked to:
>         - send 4 address cycles (the first four cycles),
>         - send 1 address cycle (the last one) +
>           write 512 bytes (the first half),
>         - write 512 bytes again (the second half).
> 
> Various other helpers are also added to ease NAND controller drivers
> writing.
> 
> This new interface should really ease the support of new vendor specific
> operations, and at least report whether the command is supported or not
> by a given controller, which was not possible before.
> 
> Suggested-by: Boris Brezillon <boris.brezillon@free-electrons.com>
> Signed-off-by: Miquel Raynal <miquel.raynal@free-electrons.com>
> ---
>  drivers/mtd/nand/nand_base.c  | 1037 +++++++++++++++++++++++++++++++++++++++--
>  drivers/mtd/nand/nand_hynix.c |    9 +
>  include/linux/mtd/rawnand.h   |  391 +++++++++++++++-
>  3 files changed, 1397 insertions(+), 40 deletions(-)
> 
> diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
> index 52965a8aeb2c..46bf31aff909 100644
> --- a/drivers/mtd/nand/nand_base.c
> +++ b/drivers/mtd/nand/nand_base.c
> @@ -689,6 +689,59 @@ static void nand_wait_status_ready(struct mtd_info *mtd, unsigned long timeo)
>  };
>  
>  /**
> + * nand_soft_waitrdy - Read the status waiting for it to be ready
> + * @chip: NAND chip structure
> + * @timeout_ms: Timeout in ms
> + *
> + * Poll the status using ->exec_op() until it is ready unless it takes too
> + * much time.
> + *
> + * This helper is intended to be used by drivers without R/B pin available to
> + * poll for the chip status until ready and may be called at any time in the
> + * middle of any set of instruction. The READ_STATUS just need to ask a single
> + * time for it and then any read will return the status. Once the READ_STATUS
> + * cycles are done, the function will send a READ0 command to cancel the
> + * "READ_STATUS state" and let the normal flow of operation to continue.
> + *
> + * This helper *cannot* send a WAITRDY command or ->exec_op() implementations

					  ^ instruction

> + * using it will enter an infinite loop.

Hm, not sure why this would be the case, but okay. Maybe you should
move this comment outside the kernel doc header, since this is an
implementation detail, not something the caller/user should be aware of.

There's another important aspect to mention here: this function can only
be called from an ->exec_op() implementation if this implementation is
re-entrant.

> + *
> + * Return 0 if the NAND chip is ready, a negative error otherwise.
> + */
> +int nand_soft_waitrdy(struct nand_chip *chip, unsigned long timeout_ms)
> +{
> +	u8 status = 0;
> +	int ret;
> +
> +	if (!chip->exec_op)
> +		return -ENOTSUPP;
> +
> +	ret = nand_status_op(chip, NULL);
> +	if (ret)
> +		return ret;
> +
> +	timeout_ms = jiffies + msecs_to_jiffies(timeout_ms);
> +	do {
> +		ret = nand_read_data_op(chip, &status, sizeof(status), true);
> +		if (ret)
> +			break;
> +
> +		if (status & NAND_STATUS_READY)
> +			break;
> +
> +		udelay(100);

Sounds a bit high, especially for a read page which takes around 20us.

> +	} while	(time_before(jiffies, timeout_ms));
> +
> +	nand_exit_status_op(chip);
> +
> +	if (ret)
> +		return ret;
> +
> +	return status & NAND_STATUS_READY ? 0 : -ETIMEDOUT;
> +};
> +EXPORT_SYMBOL_GPL(nand_soft_waitrdy);
> +
> +/**
>   * nand_command - [DEFAULT] Send command to NAND device
>   * @mtd: MTD device structure
>   * @command: the command to be sent
> @@ -1238,6 +1291,134 @@ static int nand_init_data_interface(struct nand_chip *chip)
>  }
>  
>  /**
> + * nand_fill_column_cycles - fill the column fields on an address array
> + * @chip: The NAND chip
> + * @addrs: Array of address cycles to fill
> + * @offset_in_page: The offset in the page
> + *
> + * Fills the first or the two first bytes of the @addrs field depending
> + * on the NAND bus width and the page size.
> + */
> +static int nand_fill_column_cycles(struct nand_chip *chip, u8 *addrs,
> +				   unsigned int offset_in_page)
> +{
> +	struct mtd_info *mtd = nand_to_mtd(chip);
> +
> +	/* Make sure the offset is less than the actual page size. */
> +	if (offset_in_page > mtd->writesize + mtd->oobsize)
> +		return -EINVAL;
> +
> +	/*
> +	 * On small page NANDs, there's a dedicated command to access the OOB
> +	 * area, and the column address is relative to the start of the OOB
> +	 * area, not the start of the page. Asjust the address accordingly.
> +	 */
> +	if (mtd->writesize <= 512 && offset_in_page >= mtd->writesize)
> +		offset_in_page -= mtd->writesize;
> +
> +	/*
> +	 * The offset in page is expressed in bytes, if the NAND bus is 16-bit
> +	 * wide, then it must be divided by 2.
> +	 */
> +	if (chip->options & NAND_BUSWIDTH_16) {
> +		if (WARN_ON(offset_in_page % 2))
> +			return -EINVAL;
> +
> +		offset_in_page /= 2;
> +	}
> +
> +	addrs[0] = offset_in_page;
> +
> +	/* Small pages use 1 cycle for the columns, while large page need 2 */

								^ pages

> +	if (mtd->writesize <= 512)
> +		return 1;
> +
> +	addrs[1] = offset_in_page >> 8;
> +
> +	return 2;
> +}
> +
> +static int nand_sp_exec_read_page_op(struct nand_chip *chip, unsigned int page,
> +				     unsigned int offset_in_page, void *buf,
> +				     unsigned int len)
> +{
> +	struct mtd_info *mtd = nand_to_mtd(chip);
> +	const struct nand_sdr_timings *sdr =
> +		nand_get_sdr_timings(&chip->data_interface);
> +	u8 addrs[4];
> +	struct nand_op_instr instrs[] = {
> +		NAND_OP_CMD(NAND_CMD_READ0, 0),
> +		NAND_OP_ADDR(3, addrs, PSEC_TO_NSEC(sdr->tWB_max)),
> +		NAND_OP_WAIT_RDY(PSEC_TO_MSEC(sdr->tR_max),
> +				 PSEC_TO_NSEC(sdr->tRR_min)),
> +		NAND_OP_DATA_IN(len, buf, 0),
> +	};
> +	struct nand_operation op = NAND_OPERATION(instrs);
> +	int ret;
> +
> +	/* Drop the DATA_OUT instruction if len is set to 0. */

		    ^ DATA_IN

> +	if (!len)
> +		op.ninstrs--;
> +
> +	if (offset_in_page >= mtd->writesize)
> +		instrs[0].ctx.cmd.opcode = NAND_CMD_READOOB;
> +	else if (offset_in_page >= 256 &&
> +		 !(chip->options & NAND_BUSWIDTH_16))
> +		instrs[0].ctx.cmd.opcode = NAND_CMD_READ1;
> +
> +	ret = nand_fill_column_cycles(chip, addrs, offset_in_page);
> +	if (ret < 0)
> +		return ret;
> +
> +	addrs[1] = page;
> +	addrs[2] = page >> 8;
> +
> +	if (chip->options & NAND_ROW_ADDR_3) {
> +		addrs[3] = page >> 16;
> +		instrs[1].ctx.addr.naddrs++;
> +	}
> +
> +	return nand_exec_op(chip, &op);
> +}

[...]

> @@ -1363,6 +1609,81 @@ int nand_read_oob_op(struct nand_chip *chip, unsigned int page,
>  }
>  EXPORT_SYMBOL_GPL(nand_read_oob_op);
>  
> +static int nand_exec_prog_page_op(struct nand_chip *chip, unsigned int page,
> +				  unsigned int offset_in_page, const void *buf,
> +				  unsigned int len, bool prog)
> +{
> +	struct mtd_info *mtd = nand_to_mtd(chip);
> +	const struct nand_sdr_timings *sdr =
> +		nand_get_sdr_timings(&chip->data_interface);
> +	u8 addrs[5] = {};
> +	struct nand_op_instr instrs[] = {
> +		/*
> +		 * The first instruction will be dropped if we're dealing
> +		 * with a large page NAND and adjusted if we're dealing
> +		 * with a small page NAND and the page offset is > 255.
> +		 */
> +		NAND_OP_CMD(NAND_CMD_READ0, 0),
> +		NAND_OP_CMD(NAND_CMD_SEQIN, 0),
> +		NAND_OP_ADDR(0, addrs, PSEC_TO_NSEC(sdr->tADL_min)),
> +		NAND_OP_DATA_OUT(len, buf, 0),
> +		NAND_OP_CMD(NAND_CMD_PAGEPROG, PSEC_TO_NSEC(sdr->tWB_max)),
> +		NAND_OP_WAIT_RDY(PSEC_TO_MSEC(sdr->tPROG_max), 0),
> +	};
> +	struct nand_operation op = NAND_OPERATION(instrs);
> +	int naddrs = nand_fill_column_cycles(chip, addrs, offset_in_page);
> +	int ret;
> +	u8 status;
> +
> +	if (naddrs < 0)
> +		return naddrs;
> +
> +	addrs[naddrs++] = page;
> +	addrs[naddrs++] = page >> 8;
> +	if (chip->options & NAND_ROW_ADDR_3)
> +		addrs[naddrs++] = page >> 16;
> +
> +	instrs[2].ctx.addr.naddrs = naddrs;
> +
> +	/* Drop the lasts instructions if we're not programming the page. */

		    ^ last two

> +	if (!prog) {
> +		op.ninstrs -= 2;
> +		/* Also drop the DATA_OUT instruction if empty. */
> +		if (!len)
> +			op.ninstrs--;
> +	}
> +
> +	if (mtd->writesize <= 512) {
> +		/*
> +		 * Small pages need some more tweaking: we have to adjust the
> +		 * first instruction depending on the page offset we're trying
> +		 * to access.
> +		 */
> +		if (offset_in_page >= mtd->writesize)
> +			instrs[0].ctx.cmd.opcode = NAND_CMD_READOOB;
> +		else if (offset_in_page >= 256 &&
> +			 !(chip->options & NAND_BUSWIDTH_16))
> +			instrs[0].ctx.cmd.opcode = NAND_CMD_READ1;
> +	} else {
> +		/*
> +		 * Drop the first command if we're dealing with a large page
> +		 * NAND.
> +		 */
> +		op.instrs++;
> +		op.ninstrs--;
> +	}
> +
> +	ret = nand_exec_op(chip, &op);
> +	if (!prog || ret)
> +		return ret;
> +
> +	ret = nand_status_op(chip, &status);
> +	if (ret)
> +		return ret;
> +
> +	return status;
> +}
> +

^ permalink raw reply

* [PATCH] dt-bindings: pinctrl: uniphier: add UniPhier pinctrl binding
From: Rob Herring @ 2017-11-30 20:24 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAK7LNAQYBe=x8sOBTrz8zE+5JEhOu+3eQKd8fbSAxi9Zuy18jQ@mail.gmail.com>

On Tue, Nov 28, 2017 at 9:44 PM, Masahiro Yamada
<yamada.masahiro@socionext.com> wrote:
> Hi Rob,
>
>
> 2017-11-29 0:27 GMT+09:00 Rob Herring <robh@kernel.org>:
>> On Tue, Nov 28, 2017 at 04:49:45PM +0900, Masahiro Yamada wrote:
>>> The driver has been in the tree for a while, but its binding document
>>> is missing.  Hence, here it is.
>>>
>>> Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
>>> ---
>>>
>>>  .../pinctrl/socionext,uniphier-pinctrl.txt         | 27 ++++++++++++++++++++++
>>>  MAINTAINERS                                        |  1 +
>>>  2 files changed, 28 insertions(+)
>>>  create mode 100644 Documentation/devicetree/bindings/pinctrl/socionext,uniphier-pinctrl.txt
>>>
>>> diff --git a/Documentation/devicetree/bindings/pinctrl/socionext,uniphier-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/socionext,uniphier-pinctrl.txt
>>> new file mode 100644
>>> index 0000000..8173b12
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/pinctrl/socionext,uniphier-pinctrl.txt
>>> @@ -0,0 +1,27 @@
>>> +UniPhier SoCs pin controller
>>> +
>>> +Required properties:
>>> +- compatible: should be one of the following:
>>> +    "socionext,uniphier-ld4-pinctrl"  - for LD4 SoC
>>> +    "socionext,uniphier-pro4-pinctrl" - for Pro4 SoC
>>> +    "socionext,uniphier-sld8-pinctrl" - for sLD8 SoC
>>> +    "socionext,uniphier-pro5-pinctrl" - for Pro5 SoC
>>> +    "socionext,uniphier-pxs2-pinctrl" - for PXs2 SoC
>>> +    "socionext,uniphier-ld6b-pinctrl" - for LD6b SoC
>>> +    "socionext,uniphier-ld11-pinctrl" - for LD11 SoC
>>> +    "socionext,uniphier-ld20-pinctrl" - for LD20 SoC
>>> +    "socionext,uniphier-pxs3-pinctrl" - for PXs3 SoC
>>> +
>>> +Note:
>>> +The UniPhier pinctrl should be a subnode of a "syscon" compatible node.
>>> +
>>> +Example:
>>> +     soc-glue at 5f800000 {
>>> +             compatible = "socionext,uniphier-pro4-soc-glue",
>>> +                          "simple-mfd", "syscon";
>>> +             reg = <0x5f800000 0x2000>;
>>> +
>>> +             pinctrl: pinctrl {
>>> +                     compatible = "socionext,uniphier-pro4-pinctrl";
>>
>> There's not a contiguous register range that can be put here?
>
>
> Right.
>
> I saw SATA PHY registers are inserted among the pinctrl registers.

Okay,

Acked-by: Rob Herring <robh@kernel.org>

> Hardware engineers often make crazy design.

If there's 2 ways to do things, they will find a 3rd way.

Rob

^ permalink raw reply

* [PATCH 8/8] PCIe: imx6: imx7d: add support for phy refclk source
From: tyler at opensourcefoundries.com @ 2017-11-30 20:14 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171130201434.14122-1-tyler@opensourcefoundries.com>

From: Tyler Baker <tyler@opensourcefoundries.com>

In the i.MX7D the PCIe PHY can use either externel oscillator or
internal PLL as a reference clock source.
Add support for the PHY Reference Clock source including
device tree property phy-ref-clk.
External oscillator is used as a default reference clock source.

Signed-off-by: Tyler Baker <tyler@opensourcefoundries.com>
Signed-off-by: Ilya Ledvich <ilya@compulab.co.il>
---
 drivers/pci/dwc/pci-imx6.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/dwc/pci-imx6.c b/drivers/pci/dwc/pci-imx6.c
index b734835..e935db4 100644
--- a/drivers/pci/dwc/pci-imx6.c
+++ b/drivers/pci/dwc/pci-imx6.c
@@ -45,6 +45,7 @@ enum imx6_pcie_variants {
 struct imx6_pcie {
 	struct dw_pcie		*pci;
 	int			reset_gpio;
+	u32			phy_refclk;
 	bool			gpio_active_high;
 	struct clk		*pcie_bus;
 	struct clk		*pcie_phy;
@@ -474,7 +475,7 @@ static void imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie)
 	switch (imx6_pcie->variant) {
 	case IMX7D:
 		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
-				   IMX7D_GPR12_PCIE_PHY_REFCLK_SEL, 0);
+				   BIT(5), imx6_pcie->phy_refclk ? BIT(5) : 0);
 		break;
 	case IMX6SX:
 		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
@@ -733,6 +734,11 @@ static int imx6_pcie_probe(struct platform_device *pdev)
 	if (IS_ERR(pci->dbi_base))
 		return PTR_ERR(pci->dbi_base);
 
+	/* Fetch PHY Reference Clock */
+	if (of_property_read_u32(node, "phy-ref-clk", &imx6_pcie->phy_refclk))
+		imx6_pcie->phy_refclk = 0;
+	pr_info("%s: phy_refclk = %d\n", __func__, imx6_pcie->phy_refclk);
+
 	/* Fetch GPIOs */
 	imx6_pcie->reset_gpio = of_get_named_gpio(node, "reset-gpio", 0);
 	imx6_pcie->gpio_active_high = of_property_read_bool(node,
-- 
2.9.3

^ permalink raw reply related

* [PATCH 7/8] ARM: dts: imx7s: add usb hsic phy domain
From: tyler at opensourcefoundries.com @ 2017-11-30 20:14 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171130201434.14122-1-tyler@opensourcefoundries.com>

From: Tyler Baker <tyler@opensourcefoundries.com>

The GPCv2 driver should control the MIPI, PCIe,
and USB HSIC PHY regulators. Add the USB HSIC
power domain to the GPC node.

Signed-off-by: Tyler Baker <tyler@opensourcefoundries.com>
---
 arch/arm/boot/dts/imx7s.dtsi | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/imx7s.dtsi b/arch/arm/boot/dts/imx7s.dtsi
index 151ab34..9626a3e 100644
--- a/arch/arm/boot/dts/imx7s.dtsi
+++ b/arch/arm/boot/dts/imx7s.dtsi
@@ -602,6 +602,12 @@
 						reg = <IMX7_POWER_DOMAIN_PCIE_PHY>;
 						power-supply = <&reg_1p0d>;
 					};
+					pgc_usb_hsic_phy: pgc-usb-hsic-phy-domain {
+						#power-domain-cells = <0>;
+
+						reg = <IMX7_POWER_DOMAIN_USB_HSIC_PHY>;
+						power-supply = <&reg_1p2>;
+					};
 				};
 			};
 		};
-- 
2.9.3

^ permalink raw reply related

* [PATCH 6/8] ARM: dts: imx7d-sbc-iot: enable PCIe peripheral
From: tyler at opensourcefoundries.com @ 2017-11-30 20:14 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171130201434.14122-1-tyler@opensourcefoundries.com>

From: Tyler Baker <tyler@opensourcefoundries.com>

Add a PCIe device tree node to enable PCIe support.

Signed-off-by: Tyler Baker <tyler@opensourcefoundries.com>
---
 arch/arm/boot/dts/imx7d-sbc-iot-imx7.dts | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/arch/arm/boot/dts/imx7d-sbc-iot-imx7.dts b/arch/arm/boot/dts/imx7d-sbc-iot-imx7.dts
index 50dfdd3..7b21366 100644
--- a/arch/arm/boot/dts/imx7d-sbc-iot-imx7.dts
+++ b/arch/arm/boot/dts/imx7d-sbc-iot-imx7.dts
@@ -127,6 +127,12 @@
 		>;
 	};
 
+	pinctrl_pcie: pciegrp {
+		fsl,pins = <
+			MX7D_PAD_EPDC_BDR1__GPIO2_IO29		0x34 /* PCIe RST */
+		>;
+	};
+
 	pinctrl_uart2: uart2grp {
 		fsl,pins = <
 			MX7D_PAD_LCD_ENABLE__UART2_DCE_TX	0x79 /* P7-12 */
@@ -201,6 +207,14 @@
 	};
 };
 
+&pcie {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pcie>;
+	reset-gpio = <&gpio2 29 GPIO_ACTIVE_LOW>;
+	phy-ref-clk = <1>;
+	status = "okay";
+};
+
 &uart2 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_uart2>;
-- 
2.9.3

^ permalink raw reply related

* [PATCH 5/8] ARM: dts: imx7s: add node and supplies for vdd1p2
From: tyler at opensourcefoundries.com @ 2017-11-30 20:14 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171130201434.14122-1-tyler@opensourcefoundries.com>

From: Tyler Baker <tyler@opensourcefoundries.com>

Add the regulator nodes and supplies for vdd1p2. This regulator is
used to power the GPC and USB HSIC PHY.

Signed-off-by: Tyler Baker <tyler@opensourcefoundries.com>
---
 arch/arm/boot/dts/imx7s.dtsi | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/imx7s.dtsi b/arch/arm/boot/dts/imx7s.dtsi
index 7b85659..151ab34 100644
--- a/arch/arm/boot/dts/imx7s.dtsi
+++ b/arch/arm/boot/dts/imx7s.dtsi
@@ -522,6 +522,20 @@
 					anatop-max-voltage = <1200000>;
 					anatop-enable-bit = <0>;
 				};
+
+				reg_1p2: regulator-vdd1p2 at 220 {
+					compatible = "fsl,anatop-regulator";
+					regulator-name = "vdd1p2";
+					regulator-min-microvolt = <1100000>;
+					regulator-max-microvolt = <1300000>;
+					anatop-reg-offset = <0x220>;
+					anatop-vol-bit-shift = <8>;
+					anatop-vol-bit-width = <5>;
+					anatop-min-bit-val = <8>;
+					anatop-min-voltage = <1100000>;
+					anatop-max-voltage = <1300000>;
+					anatop-enable-bit = <0>;
+				};
 			};
 
 			snvs: snvs at 30370000 {
@@ -578,7 +592,7 @@
 				#interrupt-cells = <3>;
 				interrupt-parent = <&intc>;
 				#power-domain-cells = <1>;
-
+				vcc-supply = <&reg_1p2>;
 				pgc {
 					#address-cells = <1>;
 					#size-cells = <0>;
@@ -961,6 +975,7 @@
 				compatible = "usb-nop-xceiv";
 				clocks = <&clks IMX7D_USB_HSIC_ROOT_CLK>;
 				clock-names = "main_clk";
+				vcc-supply = <&reg_1p2>;
 			};
 
 			usdhc1: usdhc at 30b40000 {
-- 
2.9.3

^ permalink raw reply related

* [PATCH 4/8] ARM: dts: imx7s: add dma support
From: tyler at opensourcefoundries.com @ 2017-11-30 20:14 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171130201434.14122-1-tyler@opensourcefoundries.com>

From: Tyler Baker <tyler@opensourcefoundries.com>

Enable dma on all SPI and UART interfaces.

Signed-off-by: Tyler Baker <tyler@opensourcefoundries.com>
---
 arch/arm/boot/dts/imx7s.dtsi | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/imx7s.dtsi b/arch/arm/boot/dts/imx7s.dtsi
index 82ad26e..7b85659 100644
--- a/arch/arm/boot/dts/imx7s.dtsi
+++ b/arch/arm/boot/dts/imx7s.dtsi
@@ -700,6 +700,8 @@
 				clocks = <&clks IMX7D_ECSPI1_ROOT_CLK>,
 					<&clks IMX7D_ECSPI1_ROOT_CLK>;
 				clock-names = "ipg", "per";
+				dmas = <&sdma 0 7 1>, <&sdma 1 7 2>;
+				dma-names = "rx", "tx";
 				status = "disabled";
 			};
 
@@ -712,6 +714,8 @@
 				clocks = <&clks IMX7D_ECSPI2_ROOT_CLK>,
 					<&clks IMX7D_ECSPI2_ROOT_CLK>;
 				clock-names = "ipg", "per";
+				dmas = <&sdma 2 7 1>, <&sdma 3 7 2>;
+				dma-names = "rx", "tx";
 				status = "disabled";
 			};
 
@@ -724,6 +728,8 @@
 				clocks = <&clks IMX7D_ECSPI3_ROOT_CLK>,
 					<&clks IMX7D_ECSPI3_ROOT_CLK>;
 				clock-names = "ipg", "per";
+				dmas = <&sdma 4 7 1>, <&sdma 5 7 2>;
+				dma-names = "rx", "tx";
 				status = "disabled";
 			};
 
-- 
2.9.3

^ permalink raw reply related

* [PATCH 3/8] ARM: dts: imx7d-cl-som: add nodes for usbh, and usbotg2
From: tyler at opensourcefoundries.com @ 2017-11-30 20:14 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171130201434.14122-1-tyler@opensourcefoundries.com>

From: Tyler Baker <tyler@opensourcefoundries.com>

Add device tree nodes for the USB hub, and USB OTG. i2c2 on this
platform supports low state retention power state so lets use it.

Signed-off-by: Tyler Baker <tyler@opensourcefoundries.com>
---
 arch/arm/boot/dts/imx7d-cl-som-imx7.dts | 36 +++++++++++++++++++++++++--------
 1 file changed, 28 insertions(+), 8 deletions(-)

diff --git a/arch/arm/boot/dts/imx7d-cl-som-imx7.dts b/arch/arm/boot/dts/imx7d-cl-som-imx7.dts
index ae45af1..a9f690b 100644
--- a/arch/arm/boot/dts/imx7d-cl-som-imx7.dts
+++ b/arch/arm/boot/dts/imx7d-cl-som-imx7.dts
@@ -30,6 +30,16 @@
 		gpio = <&gpio1 5 GPIO_ACTIVE_HIGH>;
 		enable-active-high;
 	};
+
+	reg_usbh_nreset: regulator at 4 {
+		compatible = "regulator-fixed";
+		regulator-name = "usb_host_nreset";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		gpio = <&pca9555 6 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+		regulator-always-on;
+	};
 };
 
 &cpu0 {
@@ -199,6 +209,16 @@
 	status = "okay";
 };
 
+&usbotg2 {
+	dr_mode = "host";
+	status = "okay";
+};
+
+&usbh {
+	vbus-supply = <&reg_usbh_nreset>;
+	status = "okay";
+};
+
 &usdhc3 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_usdhc3>;
@@ -247,13 +267,6 @@
 		>;
 	};
 
-	pinctrl_i2c2: i2c2grp {
-		fsl,pins = <
-			MX7D_PAD_I2C2_SDA__I2C2_SDA		0x4000007f
-			MX7D_PAD_I2C2_SCL__I2C2_SCL		0x4000007f
-		>;
-	};
-
 	pinctrl_uart1: uart1grp {
 		fsl,pins = <
 			MX7D_PAD_UART1_TX_DATA__UART1_DCE_TX	0x79
@@ -284,4 +297,11 @@
 			MX7D_PAD_LPSR_GPIO1_IO05__GPIO1_IO5	0x14 /* OTG PWREN */
 		>;
 	};
-};
\ No newline at end of file
+
+	pinctrl_i2c2: i2c2grp {
+		fsl,pins = <
+			MX7D_PAD_LPSR_GPIO1_IO07__I2C2_SDA		0x4000000f
+			MX7D_PAD_LPSR_GPIO1_IO06__I2C2_SCL		0x4000000f
+		>;
+	};
+};
-- 
2.9.3

^ permalink raw reply related

* [PATCH 2/8] ARM: dts: imx7: build imx7d-sbc-iot-imx7 dtb
From: tyler at opensourcefoundries.com @ 2017-11-30 20:14 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171130201434.14122-1-tyler@opensourcefoundries.com>

From: Tyler Baker <tyler@opensourcefoundries.com>

Build the imx7d-sbc-iot-imx7 device tree blob.

Signed-off-by: Tyler Baker <tyler@opensourcefoundries.com>
---
 arch/arm/boot/dts/Makefile | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index d0381e9..0334137 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -515,6 +515,7 @@ dtb-$(CONFIG_SOC_IMX7D) += \
 	imx7d-nitrogen7.dtb \
 	imx7d-pico.dtb \
 	imx7d-sbc-imx7.dtb \
+	imx7d-sbc-iot-imx7.dtb \
 	imx7d-sdb.dtb \
 	imx7d-sdb-sht11.dtb \
 	imx7s-colibri-eval-v3.dtb \
-- 
2.9.3

^ permalink raw reply related

* [PATCH 1/8] ARM: dts: imx7d-sbc-iot: add initial iot gateway dts
From: tyler at opensourcefoundries.com @ 2017-11-30 20:14 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171130201434.14122-1-tyler@opensourcefoundries.com>

From: Tyler Baker <tyler@opensourcefoundries.com>

The Compulab IoT Gateway is based on an NXP i.MX7D, dual core
Cortex-A7 clocking at 1GHz. It supports up to 2GB of DDR3,
and 32GB of eMMC flash. Onboard, there are two gigabit
ethernet controllers, 4 x USB2, RS485, and CAN.

This platform is based on the imx7d-cl-som-imx7 module but
includes a baseboard with additional peripherals
which is what this device tree is meant to describe.

This work has been derrived from the Compulab Linux sources
based on v4.1.

Signed-off-by: Tyler Baker <tyler@opensourcefoundries.com>
Signed-off-by: Ilya Ledvich <ilya@compulab.co.il>
---
 arch/arm/boot/dts/imx7d-sbc-iot-imx7.dts | 238 +++++++++++++++++++++++++++++++
 1 file changed, 238 insertions(+)
 create mode 100644 arch/arm/boot/dts/imx7d-sbc-iot-imx7.dts

diff --git a/arch/arm/boot/dts/imx7d-sbc-iot-imx7.dts b/arch/arm/boot/dts/imx7d-sbc-iot-imx7.dts
new file mode 100644
index 0000000..50dfdd3
--- /dev/null
+++ b/arch/arm/boot/dts/imx7d-sbc-iot-imx7.dts
@@ -0,0 +1,238 @@
+/*
+ * Support for CompuLab SBC-IOT-iMX7 Single Board Computer
+ *
+ * Copyright (C) 2017 CompuLab Ltd. - http://www.compulab.co.il/
+ * Author: Ilya Ledvich <ilya@compulab.co.il>
+ *
+ * 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.
+ */
+
+#include "imx7d-cl-som-imx7.dts"
+
+/ {
+	model = "CompuLab SBC-IOT-iMX7";
+	compatible = "compulab,sbc-iot-imx7", "compulab,cl-som-imx7", "fsl,imx7d";
+
+	aliases {
+		lcdif = &lcdif;
+	};
+};
+
+&ecspi3 {
+	fsl,spi-num-chipselects = <1>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi3 &pinctrl_ecspi3_cs>;
+	cs-gpios = <&gpio4 11 0>;
+	status = "okay";
+};
+
+&i2c3 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	status = "okay";
+};
+
+&i2c4 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c4>;
+	status = "okay";
+
+	eeprom_iot at 54 {
+		compatible = "atmel,24c08";
+		reg = <0x54>;
+		pagesize = <16>;
+	};
+
+	dvicape at 39 {
+		compatible = "sil164_simple";
+		reg = <0x39>;
+	};
+};
+
+&iomuxc {
+	pinctrl_xpen: xpengrp {
+		fsl,pins = <
+			MX7D_PAD_LCD_DATA13__GPIO3_IO18		0x34 /* P7-4 - gpio82 */
+			MX7D_PAD_LCD_DATA12__GPIO3_IO17		0x34 /* P7-5 - gpio81 */
+		>;
+	};
+
+	pinctrl_ecspi3: ecspi3grp {
+		fsl,pins = <
+			MX7D_PAD_I2C1_SDA__ECSPI3_MOSI		0xf /* P7-8 */
+			MX7D_PAD_I2C1_SCL__ECSPI3_MISO		0xf /* P7-7 */
+			MX7D_PAD_I2C2_SCL__ECSPI3_SCLK		0xf /* P7-6 */
+		>;
+	};
+
+	pinctrl_ecspi3_cs: ecspi3_cs_grp {
+		fsl,pins = <
+			MX7D_PAD_I2C2_SDA__GPIO4_IO11		0x34 /* P7-9 */
+		>;
+	};
+
+	pinctrl_i2c3: i2c3grp {
+		fsl,pins = <
+			MX7D_PAD_GPIO1_IO09__I2C3_SDA		0x4000000f /* P7-3 */
+			MX7D_PAD_GPIO1_IO08__I2C3_SCL		0x4000000f /* P7-2 */
+		>;
+	};
+
+	pinctrl_i2c4: i2c4grp {
+		fsl,pins = <
+			MX7D_PAD_GPIO1_IO11__I2C4_SDA		0x4000000f
+			MX7D_PAD_GPIO1_IO10__I2C4_SCL		0x4000000f
+		>;
+	};
+
+	pinctrl_lcdif_dat: lcdifdatgrp {
+		fsl,pins = <
+			MX7D_PAD_LCD_DATA00__LCD_DATA0		0x79
+			MX7D_PAD_LCD_DATA01__LCD_DATA1		0x79
+			MX7D_PAD_LCD_DATA02__LCD_DATA2		0x79
+			MX7D_PAD_LCD_DATA03__LCD_DATA3		0x79
+			MX7D_PAD_EPDC_DATA04__LCD_DATA4		0x79
+			MX7D_PAD_EPDC_DATA05__LCD_DATA5		0x79
+			MX7D_PAD_EPDC_DATA06__LCD_DATA6		0x79
+			MX7D_PAD_EPDC_DATA07__LCD_DATA7		0x79
+			MX7D_PAD_EPDC_DATA08__LCD_DATA8		0x79
+			MX7D_PAD_EPDC_DATA09__LCD_DATA9		0x79
+			MX7D_PAD_EPDC_DATA10__LCD_DATA10	0x79
+			MX7D_PAD_EPDC_DATA11__LCD_DATA11	0x79
+			MX7D_PAD_EPDC_DATA12__LCD_DATA12	0x79
+			MX7D_PAD_EPDC_DATA13__LCD_DATA13	0x79
+			MX7D_PAD_EPDC_DATA14__LCD_DATA14	0x79
+			MX7D_PAD_EPDC_DATA15__LCD_DATA15	0x79
+			MX7D_PAD_LCD_DATA16__LCD_DATA16		0x79
+			MX7D_PAD_LCD_DATA17__LCD_DATA17		0x79
+			MX7D_PAD_LCD_DATA18__LCD_DATA18		0x79
+			MX7D_PAD_LCD_DATA19__LCD_DATA19		0x79
+			MX7D_PAD_LCD_DATA20__LCD_DATA20		0x79
+			MX7D_PAD_LCD_DATA21__LCD_DATA21		0x79
+			MX7D_PAD_LCD_DATA22__LCD_DATA22		0x79
+			MX7D_PAD_LCD_DATA23__LCD_DATA23		0x79
+		>;
+	};
+
+	pinctrl_lcdif_ctrl: lcdifctrlgrp {
+		fsl,pins = <
+			MX7D_PAD_EPDC_DATA00__LCD_CLK		0x79
+			MX7D_PAD_EPDC_DATA01__LCD_ENABLE	0x79
+			MX7D_PAD_EPDC_DATA02__LCD_VSYNC		0x79
+			MX7D_PAD_EPDC_DATA03__LCD_HSYNC		0x79
+		>;
+	};
+
+	pinctrl_uart2: uart2grp {
+		fsl,pins = <
+			MX7D_PAD_LCD_ENABLE__UART2_DCE_TX	0x79 /* P7-12 */
+			MX7D_PAD_LCD_CLK__UART2_DCE_RX		0x79 /* P7-13 */
+			MX7D_PAD_LCD_VSYNC__UART2_DCE_CTS	0x79 /* P7-11 */
+			MX7D_PAD_LCD_HSYNC__UART2_DCE_RTS	0x79 /* P7-10 */
+		>;
+	};
+
+	pinctrl_uart5: uart5grp {
+		fsl,pins = <
+			MX7D_PAD_I2C4_SDA__UART5_DCE_TX		0x79 /* RS232-TX */
+			MX7D_PAD_I2C4_SCL__UART5_DCE_RX		0x79 /* RS232-RX */
+			MX7D_PAD_I2C3_SDA__UART5_DCE_RTS	0x79 /* RS232-RTS */
+			MX7D_PAD_I2C3_SCL__UART5_DCE_CTS	0x79 /* RS232-CTS */
+		>;
+	};
+
+	pinctrl_uart7: uart7grp {
+		fsl,pins = <
+			MX7D_PAD_ECSPI2_MOSI__UART7_DCE_TX	0x79 /* R485-TX */
+			MX7D_PAD_ECSPI2_SCLK__UART7_DCE_RX	0x79 /* R485-RX */
+			MX7D_PAD_ECSPI2_SS0__UART7_DCE_CTS	0x79 /* R485-CTS */
+			MX7D_PAD_ECSPI2_MISO__UART7_DCE_RTS	0x79 /* R485-TTS */
+		>;
+	};
+
+	pinctrl_usdhc1: usdhc1grp {
+		fsl,pins = <
+			MX7D_PAD_SD1_CMD__SD1_CMD		0x59
+			MX7D_PAD_SD1_CLK__SD1_CLK		0x19
+			MX7D_PAD_SD1_DATA0__SD1_DATA0		0x59
+			MX7D_PAD_SD1_DATA1__SD1_DATA1		0x59
+			MX7D_PAD_SD1_DATA2__SD1_DATA2		0x59
+			MX7D_PAD_SD1_DATA3__SD1_DATA3		0x59
+			MX7D_PAD_SD1_CD_B__GPIO5_IO0		0x59 /* CD */
+		>;
+	};
+};
+
+&lcdif {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_lcdif_dat
+		     &pinctrl_lcdif_ctrl>;
+	display = <&display0>;
+	status = "okay";
+
+	display0: display {
+		bits-per-pixel = <24>;
+		bus-width = <24>;
+
+		display-timings {
+			native-mode = <&timing0>;
+			timing0: dvi {
+				/* 1024x768p60 */
+				clock-frequency = <65000000>;
+				hactive = <1024>;
+				hfront-porch = <40>;
+				hback-porch = <220>;
+				hsync-len = <60>;
+				vactive = <768>;
+				vfront-porch = <7>;
+				vback-porch = <21>;
+				vsync-len = <10>;
+
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+		};
+	};
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	assigned-clocks = <&clks IMX7D_UART2_ROOT_SRC>;
+	assigned-clock-parents = <&clks IMX7D_OSC_24M_CLK>;
+	fsl,uart-has-rtscts;
+	status = "okay";
+};
+
+&uart5 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart5>;
+	assigned-clocks = <&clks IMX7D_UART5_ROOT_SRC>;
+	assigned-clock-parents = <&clks IMX7D_PLL_SYS_MAIN_240M_CLK>;
+	fsl,uart-has-rtscts;
+	status = "okay";
+};
+
+&uart7 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart7>;
+	assigned-clocks = <&clks IMX7D_UART7_ROOT_SRC>;
+	assigned-clock-parents = <&clks IMX7D_PLL_SYS_MAIN_240M_CLK>;
+	fsl,uart-has-rtscts;
+	status = "okay";
+};
+
+&usdhc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc1>;
+	cd-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>;
+	wp-gpios = <&gpio5 1 GPIO_ACTIVE_HIGH>;
+	enable-sdio-wakeup;
+	status = "okay";
+};
-- 
2.9.3

^ 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