All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH v2 00/13] arm: add support for SoC S5P4418
@ 2020-03-28  9:43 Stefan Bosch
  2020-03-28  9:43 ` [RFC PATCH v2 01/13] arm: add mach-nexell (header files) Stefan Bosch
                   ` (12 more replies)
  0 siblings, 13 replies; 21+ messages in thread
From: Stefan Bosch @ 2020-03-28  9:43 UTC (permalink / raw)
  To: u-boot


This patch adds support for SAMSUNG's/NEXELL's ARM Cortex-A9 based
S5P4418 SoC, especially FriendlyARM's NanoPi2 and NanoPC-T2 boards.
It is based on the following FriendlyARM's U-Boot version:
https://github.com/friendlyarm/u-boot/tree/nanopi2-v2016.01.

Main changes in relation to nanopi2-v2016.01:
- Cosmetic changes due to patman warnings/errors.
- MMC and Video drivers changed to DM.
- Configs reworked (e.g. "CONFIG_..." moved from s5p4418_nanopi2.h
  to s5p4418_nanopi2_defconfig)
- SPL related files are not included.
- MACH_TYPE_S5P4418 is not defined/used anymore.
- arch/arm/mach-nexell/include/mach/boot0.h added to generate the NSIH
  (Nexell System Information Header), substitudes tools/nexell.
- board/s5p4418/ renamed to board/friendlyarm/
- Only the NanoPi2 and NanoPC-T2 boards are supported yet because I
  do only have the NanoPC-T2 board to test the code (this board uses
  the NanoPi2 code).
- USB is not supported yet.

The patch-series has been checked by buildman (all arm boards and two
m68k boards = M5235EVB):
  buildman --step 0 -b master arm
  buildman --step 0 -b master M5235EVB
There have been no new warnings or errors.

Changes in v2:
- arch/arm/mach-nexell/serial.c removed because this is for the UARTs
  of the S5P6818 SoC which is not supported yet. S5P4418 UARTs are
  different, here the (existing) PL011-code is used.
- line '... += spl/' in in arch/arm/mach-nexell/Makefile deleted, this
  change has already been stated in the commit message but was missing
  nethertheless.
- commit "i2c: mmc: add nexell driver (gpio, i2c, mmc, pwm)" splitted
  into separate commits for gpio, i2c, mmc, pwm.
- cosmetic: line "obj-$(CONFIG_NX_GPIO) += nx_gpio.o" in
  drivers/gpio/Makefile moved up.
- several Bugfixes in nx_i2c.c.
- the i2c-driver has been for s5p6818 only. Code extended approriately
  in order s5p4418 is also working.
- "probe_chip" added to the i2c-driver.
- doc/device-tree-bindings/i2c/nx_i2c.txt added.
- Since drivers/pwm/pwm-nexell.c is an adapted version of
  s5p-common/pwm.c an appropriately changed version of s5p-common/pwm.c
  is used now. Therefore arch/arm/mach-s5pc1xx/include/mach/pwm.h
  copied to arch/arm/mach-nexell/include/mach and s5p-common/Makefile
  changed appropriately.
- i2c: "nexell,s5pxx18-i2c"-driver is used now instead of "i2c-gpio".
  i2c0 and i2c1 added. I.e. dts files changed appropriately.
- dts: gmac-, ehci- and dwc2otg-entries removed because the appropriate
  functionality is not supported yet.
- s5p4418-pinctrl.dtsi removed because there is no pinctrl-driver
  available.
- "obj-$(CONFIG_ARCH_NEXELL) += s5p-common/" added to
  arch/arm/cpu/armv7/Makefile since s5p-common/pwm.c is used now instead
  of drivers/pwm/pwm-nexell.c.
- cosmetic: additional GPL license text removed, SPDX-License-Identifier
  is enough. Furthermore file path removed (two files).
- USB related configs removed because USB is not supported yet.
- CONFIG_CMD_MEMTEST moved from s5p4418_nanopi2.h to
  s5p4418_nanopi2_defconfig.
- MAINTAINERS: "F: drivers/pwm/pwm-nexell*" deleted because
  arch/arm/cpu/armv7/s5p-common/pwm.c is used now. Furthermore double
  line "F: drivers/video/nexell/" deleted.

Stefan Bosch (13):
  arm: add mach-nexell (header files)
  arm: add mach-nexell (all files except header files)
  gpio: add nexell driver
  i2c: add nexell driver
  mmc: add nexell driver
  pwm: add driver for nexell
  video: add nexell video driver (soc: displaytop)
  video: add nexell video driver (soc: mlc, mipi)
  video: add nexell video driver (soc: lvds, hdmi)
  video: add nexell video driver (soc: dpc, makefile)
  video: add nexell video driver (display/video driver)
  arm: add support for SoC s5p4418 (cpu) / nanopi2 board
  arm: add (default) config for nanopi2 board

 MAINTAINERS                                        |   16 +
 arch/arm/Kconfig                                   |    7 +
 arch/arm/Makefile                                  |    1 +
 arch/arm/cpu/armv7/Makefile                        |    2 +
 arch/arm/cpu/armv7/s5p-common/Makefile             |    4 +
 arch/arm/cpu/armv7/s5p-common/pwm.c                |   56 +
 arch/arm/cpu/armv7/s5p4418/Makefile                |    6 +
 arch/arm/cpu/armv7/s5p4418/cpu.c                   |  120 ++
 arch/arm/dts/Makefile                              |    3 +
 arch/arm/dts/s5p4418-nanopi2.dts                   |  108 ++
 arch/arm/dts/s5p4418.dtsi                          |  148 ++
 arch/arm/mach-nexell/Kconfig                       |   67 +
 arch/arm/mach-nexell/Makefile                      |   13 +
 arch/arm/mach-nexell/clock.c                       |  869 +++++++++
 arch/arm/mach-nexell/cmd_boot_linux.c              |  145 ++
 arch/arm/mach-nexell/config.mk                     |   11 +
 arch/arm/mach-nexell/include/mach/boot0.h          |   40 +
 arch/arm/mach-nexell/include/mach/clk.h            |   24 +
 arch/arm/mach-nexell/include/mach/display.h        |  273 +++
 arch/arm/mach-nexell/include/mach/display_dev.h    |   37 +
 arch/arm/mach-nexell/include/mach/ehci.h           |  106 ++
 arch/arm/mach-nexell/include/mach/gpio.h           |   17 +
 arch/arm/mach-nexell/include/mach/mipi_display.h   |  215 +++
 arch/arm/mach-nexell/include/mach/nexell.h         |  352 ++++
 arch/arm/mach-nexell/include/mach/nx_gpio.h        |  103 ++
 arch/arm/mach-nexell/include/mach/pwm.h            |   54 +
 arch/arm/mach-nexell/include/mach/reset.h          |   19 +
 arch/arm/mach-nexell/include/mach/sec_reg.h        |   15 +
 arch/arm/mach-nexell/include/mach/tieoff.h         |  423 +++++
 arch/arm/mach-nexell/nx_gpio.c                     |  352 ++++
 arch/arm/mach-nexell/nx_sec_reg.c                  |   82 +
 arch/arm/mach-nexell/reg-call.S                    |   23 +
 arch/arm/mach-nexell/reset.c                       |   33 +
 arch/arm/mach-nexell/tieoff.c                      |  109 ++
 arch/arm/mach-nexell/timer.c                       |  297 ++++
 board/friendlyarm/Kconfig                          |   39 +
 board/friendlyarm/nanopi2/Kconfig                  |   12 +
 board/friendlyarm/nanopi2/MAINTAINERS              |    7 +
 board/friendlyarm/nanopi2/Makefile                 |    6 +
 board/friendlyarm/nanopi2/board.c                  |  567 ++++++
 board/friendlyarm/nanopi2/hwrev.c                  |  108 ++
 board/friendlyarm/nanopi2/hwrev.h                  |   15 +
 board/friendlyarm/nanopi2/lcds.c                   |  697 ++++++++
 board/friendlyarm/nanopi2/nxp-fb.h                 |   94 +
 board/friendlyarm/nanopi2/onewire.c                |  309 ++++
 board/friendlyarm/nanopi2/onewire.h                |   15 +
 configs/s5p4418_nanopi2_defconfig                  |  148 ++
 doc/README.s5p4418                                 |   63 +
 doc/device-tree-bindings/i2c/nx_i2c.txt            |   28 +
 drivers/gpio/Kconfig                               |    9 +
 drivers/gpio/Makefile                              |    1 +
 drivers/gpio/nx_gpio.c                             |  252 +++
 drivers/i2c/Kconfig                                |    9 +
 drivers/i2c/Makefile                               |    1 +
 drivers/i2c/nx_i2c.c                               |  649 +++++++
 drivers/mmc/Kconfig                                |    6 +
 drivers/mmc/Makefile                               |    1 +
 drivers/mmc/nexell_dw_mmc_dm.c                     |  350 ++++
 drivers/video/Kconfig                              |   10 +
 drivers/video/Makefile                             |    1 +
 drivers/video/nexell/Kconfig                       |   27 +
 drivers/video/nexell/Makefile                      |   12 +
 drivers/video/nexell/s5pxx18_dp.c                  |  338 ++++
 drivers/video/nexell/s5pxx18_dp_hdmi.c             |  543 ++++++
 drivers/video/nexell/s5pxx18_dp_lvds.c             |  274 +++
 drivers/video/nexell/s5pxx18_dp_mipi.c             |  677 +++++++
 drivers/video/nexell/s5pxx18_dp_rgb.c              |   69 +
 drivers/video/nexell/soc/Makefile                  |   11 +
 drivers/video/nexell/soc/s5pxx18_soc_disptop.c     |  185 ++
 drivers/video/nexell/soc/s5pxx18_soc_disptop.h     |  385 ++++
 drivers/video/nexell/soc/s5pxx18_soc_disptop_clk.c |  309 ++++
 drivers/video/nexell/soc/s5pxx18_soc_disptop_clk.h |   59 +
 drivers/video/nexell/soc/s5pxx18_soc_disptype.h    |   23 +
 drivers/video/nexell/soc/s5pxx18_soc_dpc.c         | 1569 +++++++++++++++++
 drivers/video/nexell/soc/s5pxx18_soc_dpc.h         |  444 +++++
 drivers/video/nexell/soc/s5pxx18_soc_hdmi.c        |   50 +
 drivers/video/nexell/soc/s5pxx18_soc_hdmi.h        |  488 +++++
 drivers/video/nexell/soc/s5pxx18_soc_lvds.c        |  278 +++
 drivers/video/nexell/soc/s5pxx18_soc_lvds.h        |   83 +
 drivers/video/nexell/soc/s5pxx18_soc_mipi.c        |  580 ++++++
 drivers/video/nexell/soc/s5pxx18_soc_mipi.h        |  291 +++
 drivers/video/nexell/soc/s5pxx18_soc_mlc.c         | 1861 ++++++++++++++++++++
 drivers/video/nexell/soc/s5pxx18_soc_mlc.h         |  429 +++++
 drivers/video/nexell_display.c                     |  665 +++++++
 include/configs/s5p4418_nanopi2.h                  |  265 +++
 85 files changed, 17462 insertions(+)
 create mode 100644 arch/arm/cpu/armv7/s5p4418/Makefile
 create mode 100644 arch/arm/cpu/armv7/s5p4418/cpu.c
 create mode 100644 arch/arm/dts/s5p4418-nanopi2.dts
 create mode 100644 arch/arm/dts/s5p4418.dtsi
 create mode 100644 arch/arm/mach-nexell/Kconfig
 create mode 100644 arch/arm/mach-nexell/Makefile
 create mode 100644 arch/arm/mach-nexell/clock.c
 create mode 100644 arch/arm/mach-nexell/cmd_boot_linux.c
 create mode 100644 arch/arm/mach-nexell/config.mk
 create mode 100644 arch/arm/mach-nexell/include/mach/boot0.h
 create mode 100644 arch/arm/mach-nexell/include/mach/clk.h
 create mode 100644 arch/arm/mach-nexell/include/mach/display.h
 create mode 100644 arch/arm/mach-nexell/include/mach/display_dev.h
 create mode 100644 arch/arm/mach-nexell/include/mach/ehci.h
 create mode 100644 arch/arm/mach-nexell/include/mach/gpio.h
 create mode 100644 arch/arm/mach-nexell/include/mach/mipi_display.h
 create mode 100644 arch/arm/mach-nexell/include/mach/nexell.h
 create mode 100644 arch/arm/mach-nexell/include/mach/nx_gpio.h
 create mode 100644 arch/arm/mach-nexell/include/mach/pwm.h
 create mode 100644 arch/arm/mach-nexell/include/mach/reset.h
 create mode 100644 arch/arm/mach-nexell/include/mach/sec_reg.h
 create mode 100644 arch/arm/mach-nexell/include/mach/tieoff.h
 create mode 100644 arch/arm/mach-nexell/nx_gpio.c
 create mode 100644 arch/arm/mach-nexell/nx_sec_reg.c
 create mode 100644 arch/arm/mach-nexell/reg-call.S
 create mode 100644 arch/arm/mach-nexell/reset.c
 create mode 100644 arch/arm/mach-nexell/tieoff.c
 create mode 100644 arch/arm/mach-nexell/timer.c
 create mode 100644 board/friendlyarm/Kconfig
 create mode 100644 board/friendlyarm/nanopi2/Kconfig
 create mode 100644 board/friendlyarm/nanopi2/MAINTAINERS
 create mode 100644 board/friendlyarm/nanopi2/Makefile
 create mode 100644 board/friendlyarm/nanopi2/board.c
 create mode 100644 board/friendlyarm/nanopi2/hwrev.c
 create mode 100644 board/friendlyarm/nanopi2/hwrev.h
 create mode 100644 board/friendlyarm/nanopi2/lcds.c
 create mode 100644 board/friendlyarm/nanopi2/nxp-fb.h
 create mode 100644 board/friendlyarm/nanopi2/onewire.c
 create mode 100644 board/friendlyarm/nanopi2/onewire.h
 create mode 100644 configs/s5p4418_nanopi2_defconfig
 create mode 100644 doc/README.s5p4418
 create mode 100644 doc/device-tree-bindings/i2c/nx_i2c.txt
 create mode 100644 drivers/gpio/nx_gpio.c
 create mode 100644 drivers/i2c/nx_i2c.c
 create mode 100644 drivers/mmc/nexell_dw_mmc_dm.c
 create mode 100644 drivers/video/nexell/Kconfig
 create mode 100644 drivers/video/nexell/Makefile
 create mode 100644 drivers/video/nexell/s5pxx18_dp.c
 create mode 100644 drivers/video/nexell/s5pxx18_dp_hdmi.c
 create mode 100644 drivers/video/nexell/s5pxx18_dp_lvds.c
 create mode 100644 drivers/video/nexell/s5pxx18_dp_mipi.c
 create mode 100644 drivers/video/nexell/s5pxx18_dp_rgb.c
 create mode 100644 drivers/video/nexell/soc/Makefile
 create mode 100644 drivers/video/nexell/soc/s5pxx18_soc_disptop.c
 create mode 100644 drivers/video/nexell/soc/s5pxx18_soc_disptop.h
 create mode 100644 drivers/video/nexell/soc/s5pxx18_soc_disptop_clk.c
 create mode 100644 drivers/video/nexell/soc/s5pxx18_soc_disptop_clk.h
 create mode 100644 drivers/video/nexell/soc/s5pxx18_soc_disptype.h
 create mode 100644 drivers/video/nexell/soc/s5pxx18_soc_dpc.c
 create mode 100644 drivers/video/nexell/soc/s5pxx18_soc_dpc.h
 create mode 100644 drivers/video/nexell/soc/s5pxx18_soc_hdmi.c
 create mode 100644 drivers/video/nexell/soc/s5pxx18_soc_hdmi.h
 create mode 100644 drivers/video/nexell/soc/s5pxx18_soc_lvds.c
 create mode 100644 drivers/video/nexell/soc/s5pxx18_soc_lvds.h
 create mode 100644 drivers/video/nexell/soc/s5pxx18_soc_mipi.c
 create mode 100644 drivers/video/nexell/soc/s5pxx18_soc_mipi.h
 create mode 100644 drivers/video/nexell/soc/s5pxx18_soc_mlc.c
 create mode 100644 drivers/video/nexell/soc/s5pxx18_soc_mlc.h
 create mode 100644 drivers/video/nexell_display.c
 create mode 100644 include/configs/s5p4418_nanopi2.h

-- 
1.9.1

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [RFC PATCH v2 01/13] arm: add mach-nexell (header files)
  2020-03-28  9:43 [RFC PATCH v2 00/13] arm: add support for SoC S5P4418 Stefan Bosch
@ 2020-03-28  9:43 ` Stefan Bosch
  2020-03-28  9:43 ` [RFC PATCH v2 02/13] arm: add mach-nexell (all files except header files) Stefan Bosch
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 21+ messages in thread
From: Stefan Bosch @ 2020-03-28  9:43 UTC (permalink / raw)
  To: u-boot

Changes in relation to FriendlyARM's U-Boot nanopi2-v2016.01:
- DM_VIDEO support (display_dev.h).
- boot0.h added, handles NSIH --> tools/nexell obsolete.
- gpio.h: Include-path to errno.h changed.

Signed-off-by: Stefan Bosch <stefan_b@posteo.net>
---

Changes in v2:
- cosmetic: additional GPL license text removed, SPDX-License-Identifier
  is enough.

 arch/arm/mach-nexell/include/mach/boot0.h        |  40 +++
 arch/arm/mach-nexell/include/mach/clk.h          |  24 ++
 arch/arm/mach-nexell/include/mach/display.h      | 273 +++++++++++++++
 arch/arm/mach-nexell/include/mach/display_dev.h  |  37 ++
 arch/arm/mach-nexell/include/mach/ehci.h         | 106 ++++++
 arch/arm/mach-nexell/include/mach/gpio.h         |  17 +
 arch/arm/mach-nexell/include/mach/mipi_display.h | 215 ++++++++++++
 arch/arm/mach-nexell/include/mach/nexell.h       | 352 +++++++++++++++++++
 arch/arm/mach-nexell/include/mach/nx_gpio.h      | 103 ++++++
 arch/arm/mach-nexell/include/mach/reset.h        |  19 +
 arch/arm/mach-nexell/include/mach/sec_reg.h      |  15 +
 arch/arm/mach-nexell/include/mach/tieoff.h       | 423 +++++++++++++++++++++++
 12 files changed, 1624 insertions(+)
 create mode 100644 arch/arm/mach-nexell/include/mach/boot0.h
 create mode 100644 arch/arm/mach-nexell/include/mach/clk.h
 create mode 100644 arch/arm/mach-nexell/include/mach/display.h
 create mode 100644 arch/arm/mach-nexell/include/mach/display_dev.h
 create mode 100644 arch/arm/mach-nexell/include/mach/ehci.h
 create mode 100644 arch/arm/mach-nexell/include/mach/gpio.h
 create mode 100644 arch/arm/mach-nexell/include/mach/mipi_display.h
 create mode 100644 arch/arm/mach-nexell/include/mach/nexell.h
 create mode 100644 arch/arm/mach-nexell/include/mach/nx_gpio.h
 create mode 100644 arch/arm/mach-nexell/include/mach/reset.h
 create mode 100644 arch/arm/mach-nexell/include/mach/sec_reg.h
 create mode 100644 arch/arm/mach-nexell/include/mach/tieoff.h

diff --git a/arch/arm/mach-nexell/include/mach/boot0.h b/arch/arm/mach-nexell/include/mach/boot0.h
new file mode 100644
index 0000000..e05c07e
--- /dev/null
+++ b/arch/arm/mach-nexell/include/mach/boot0.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: GPL-2.0+
+ *
+ * NSIH (Nexell System Information Header) for FriendlyArm nanopi2 board
+ *
+ * The NSIH (first 512 Bytes of u-boot.bin) is necessary for the
+ * 2nd-Bootloader to get information like load address of U-Boot.
+ *
+ * 0x400 must be added to CONFIG_SYS_TEXT_BASE to have the actual load and
+ * start address because 2nd-Bootloader loads with an offset of 0x400
+ * (NSIH + 0x200 bytes are not loaded into RAM).
+ *
+ * It has been tested / is working with the following 2nd-Bootloader:
+ * "BL1 by Nexell V1.0.0-gd551e13 [Built on 2018-01-25 16:58:29]"
+ *
+ * (C) Copyright 2020 Stefan Bosch <stefan_b@posteo.net>
+ */
+
+#ifndef __BOOT0_H
+#define __BOOT0_H
+
+	ARM_VECTORS
+	.space	0x30
+	.word	(_end - _start) + 20 * 1024	/* 0x50: load size
+						 *       (bin + 20k for DTB) */
+	.space	0x4
+	.word	CONFIG_SYS_TEXT_BASE + 0x400	/* 0x58: load address */
+	.word	0x00000000
+	.word	CONFIG_SYS_TEXT_BASE + 0x400	/* 0x60: start address */
+	.space	0x198
+	.byte	'N'				/* 0x1FC: "NSIH" signature */
+	.byte	'S'
+	.byte	'I'
+	.byte	'H'
+
+	/* The NSIH + 0x200 bytes are omitted by the 2nd-Bootloader */
+	.space	0x200
+_start:
+	ARM_VECTORS
+
+#endif /* __BOOT0_H */
diff --git a/arch/arm/mach-nexell/include/mach/clk.h b/arch/arm/mach-nexell/include/mach/clk.h
new file mode 100644
index 0000000..cc5589a
--- /dev/null
+++ b/arch/arm/mach-nexell/include/mach/clk.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0+
+ *
+ * (C) Copyright 2016 Nexell
+ * Hyunseok, Jung <hsjung@nexell.co.kr>
+ */
+
+#ifndef __ASM_ARM_ARCH_CLK_H_
+#define __ASM_ARM_ARCH_CLK_H_
+
+struct clk {
+	unsigned long rate;
+};
+
+void clk_init(void);
+
+struct clk *clk_get(const char *id);
+void clk_put(struct clk *clk);
+unsigned long clk_get_rate(struct clk *clk);
+long clk_round_rate(struct clk *clk, unsigned long rate);
+int clk_set_rate(struct clk *clk, unsigned long rate);
+int clk_enable(struct clk *clk);
+void clk_disable(struct clk *clk);
+
+#endif
diff --git a/arch/arm/mach-nexell/include/mach/display.h b/arch/arm/mach-nexell/include/mach/display.h
new file mode 100644
index 0000000..b167e63
--- /dev/null
+++ b/arch/arm/mach-nexell/include/mach/display.h
@@ -0,0 +1,273 @@
+/* SPDX-License-Identifier: GPL-2.0+
+ *
+ * Copyright (C) 2016  Nexell Co., Ltd.
+ *
+ * Author: junghyun, kim <jhkim@nexell.co.kr>
+ */
+
+#ifndef _NX__DISPLAY_H_
+#define _NX__DISPLAY_H_
+
+#define	DP_PLANS_NUM	3
+
+/* the display output format. */
+#define	DPC_FORMAT_RGB555		0  /* RGB555 Format */
+#define	DPC_FORMAT_RGB565		1  /* RGB565 Format */
+#define	DPC_FORMAT_RGB666		2  /* RGB666 Format */
+#define	DPC_FORMAT_RGB888		3  /* RGB888 Format */
+#define	DPC_FORMAT_MRGB555A		4  /* MRGB555A Format */
+#define	DPC_FORMAT_MRGB555B		5  /* MRGB555B Format */
+#define	DPC_FORMAT_MRGB565		6  /* MRGB565 Format */
+#define	DPC_FORMAT_MRGB666		7  /* MRGB666 Format */
+#define	DPC_FORMAT_MRGB888A		8  /* MRGB888A Format */
+#define	DPC_FORMAT_MRGB888B		9  /* MRGB888B Format */
+#define	DPC_FORMAT_CCIR656		10 /* ITU-R BT.656 / 601(8-bit) */
+#define	DPC_FORMAT_CCIR601A		12 /* ITU-R BT.601A */
+#define	DPC_FORMAT_CCIR601B		13 /* ITU-R BT.601B */
+#define	DPC_FORMAT_4096COLOR	1  /* 4096 Color Format */
+#define	DPC_FORMAT_16GRAY		3  /* 16 Level Gray Format */
+
+/* layer pixel format. */
+#define	MLC_RGBFMT_R5G6B5		0x44320000	/* {R5,G6,B5 }. */
+#define	MLC_RGBFMT_B5G6R5		0xC4320000  /* {B5,G6,R5 }. */
+#define	MLC_RGBFMT_X1R5G5B5		0x43420000  /* {X1,R5,G5,B5}. */
+#define	MLC_RGBFMT_X1B5G5R5		0xC3420000  /* {X1,B5,G5,R5}. */
+#define	MLC_RGBFMT_X4R4G4B4		0x42110000  /* {X4,R4,G4,B4}. */
+#define	MLC_RGBFMT_X4B4G4R4		0xC2110000	/* {X4,B4,G4,R4}. */
+#define	MLC_RGBFMT_X8R3G3B2		0x41200000	/* {X8,R3,G3,B2}. */
+#define	MLC_RGBFMT_X8B3G3R2		0xC1200000	/* {X8,B3,G3,R2}. */
+#define	MLC_RGBFMT_A1R5G5B5		0x33420000	/* {A1,R5,G5,B5}. */
+#define	MLC_RGBFMT_A1B5G5R5		0xB3420000	/* {A1,B5,G5,R5}. */
+#define	MLC_RGBFMT_A4R4G4B4		0x22110000	/* {A4,R4,G4,B4}. */
+#define	MLC_RGBFMT_A4B4G4R4		0xA2110000	/* {A4,B4,G4,R4}. */
+#define	MLC_RGBFMT_A8R3G3B2		0x11200000	/* {A8,R3,G3,B2}. */
+#define	MLC_RGBFMT_A8B3G3R2		0x91200000	/* {A8,B3,G3,R2}. */
+#define	MLC_RGBFMT_R8G8B8		0x46530000	/* {R8,G8,B8 }. */
+#define	MLC_RGBFMT_B8G8R8		0xC6530000	/* {B8,G8,R8 }. */
+#define	MLC_RGBFMT_X8R8G8B8		0x46530000	/* {X8,R8,G8,B8}. */
+#define	MLC_RGBFMT_X8B8G8R8		0xC6530000	/* {X8,B8,G8,R8}. */
+#define	MLC_RGBFMT_A8R8G8B8		0x06530000	/* {A8,R8,G8,B8}. */
+#define	MLC_RGBFMT_A8B8G8R8		0x86530000	/* {A8,B8,G8,R8}.  */
+
+/* the data output order in case of ITU-R BT.656 / 601. */
+#define	DPC_YCORDER_CBYCRY		0
+#define	DPC_YCORDER_CRYCBY		1
+#define	DPC_YCORDER_YCBYCR		2
+#define	DPC_YCORDER_YCRYCB		3
+
+/* the PAD output clock. */
+#define	DPC_PADCLKSEL_VCLK		0	/* VCLK */
+#define	DPC_PADCLKSEL_VCLK2		1	/* VCLK2 */
+
+/* display sync info for DPC */
+struct dp_sync_info {
+	int interlace;
+	int h_active_len;
+	int h_sync_width;
+	int h_back_porch;
+	int h_front_porch;
+	int h_sync_invert;	/* default active low */
+	int v_active_len;
+	int v_sync_width;
+	int v_back_porch;
+	int v_front_porch;
+	int v_sync_invert;	/* default active low */
+	int pixel_clock_hz;	/* HZ */
+};
+
+/* syncgen control (DPC) */
+#define	DP_SYNC_DELAY_RGB_PVD		(1 << 0)
+#define	DP_SYNC_DELAY_HSYNC_CP1		(1 << 1)
+#define	DP_SYNC_DELAY_VSYNC_FRAM	(1 << 2)
+#define	DP_SYNC_DELAY_DE_CP			(1 << 3)
+
+struct dp_ctrl_info {
+	/* clock gen */
+	int clk_src_lv0;
+	int clk_div_lv0;
+	int clk_src_lv1;
+	int clk_div_lv1;
+	/* scan format */
+	int interlace;
+	/* syncgen format */
+	unsigned int out_format;
+	int invert_field;	/* 0:normal(Low odd), 1:invert (low even) */
+	int swap_RB;
+	unsigned int yc_order;	/* for CCIR output */
+	/* extern sync delay */
+	int delay_mask;		/* if 0, set defalut delays */
+	int d_rgb_pvd;		/* delay for RGB/PVD, 0~16, default  0 */
+	int d_hsync_cp1;	/* delay for HSYNC/CP1, 0~63, default 12 */
+	int d_vsync_fram;	/* delay for VSYNC/FRAM, 0~63, default 12 */
+	int d_de_cp2;		/* delay for DE/CP2, 0~63, default 12 */
+	/* sync offset */
+	int vs_start_offset;	/* start vsync offset, defatult 0 */
+	int vs_end_offset;	/* end vsync offset, default 0 */
+	int ev_start_offset;	/* start even vsync offset, default 0 */
+	int ev_end_offset;	/* end even vsync offset , default 0 */
+	/* pad clock seletor */
+	int vck_select;		/* 0=vclk0, 1=vclk2 */
+	int clk_inv_lv0;	/* OUTCLKINVn */
+	int clk_delay_lv0;	/* OUTCLKDELAYn */
+	int clk_inv_lv1;	/* OUTCLKINVn */
+	int clk_delay_lv1;	/* OUTCLKDELAYn */
+	int clk_sel_div1;	/* 0=clk1_inv, 1=clk1_div_2_ns */
+};
+
+/* multi layer control (MLC) */
+struct dp_plane_top {
+	int screen_width;
+	int screen_height;
+	int video_prior;	/* 0: video>RGBn, 1: RGB0>video>RGB1,
+				 *                2: RGB0 > RGB1 > video .. */
+	int interlace;
+	int plane_num;
+	unsigned int back_color;
+};
+
+struct dp_plane_info {
+	int layer;
+	unsigned int fb_base;
+	int left;
+	int top;
+	int width;
+	int height;
+	int pixel_byte;
+	unsigned int format;
+	int alpha_on;
+	int alpha_depth;
+	int tp_on;			/* transparency color enable */
+	unsigned int tp_color;
+	unsigned int mem_lock_size;	/* memory burst access (4,8,16) */
+	int video_layer;
+	int enable;
+};
+
+/*
+ * LCD device dependency struct
+ * RGB, LVDS, MiPi, HDMI
+ */
+enum {
+	DP_DEVICE_RESCONV = 0,
+	DP_DEVICE_RGBLCD = 1,
+	DP_DEVICE_HDMI = 2,
+	DP_DEVICE_MIPI = 3,
+	DP_DEVICE_LVDS = 4,
+	DP_DEVICE_CVBS = 5,
+	DP_DEVICE_DP0 = 6,
+	DP_DEVICE_DP1 = 7,
+	DP_DEVICE_END,
+};
+
+enum {
+	DP_CLOCK_RESCONV = 0,
+	DP_CLOCK_LCDIF = 1,
+	DP_CLOCK_MIPI = 2,
+	DP_CLOCK_LVDS = 3,
+	DP_CLOCK_HDMI = 4,
+	DP_CLOCK_END,
+};
+
+enum dp_lvds_format {
+	DP_LVDS_FORMAT_VESA = 0,
+	DP_LVDS_FORMAT_JEIDA = 1,
+	DP_LVDS_FORMAT_LOC = 2,
+};
+
+#define	DEF_VOLTAGE_LEVEL	(0x20)
+
+struct dp_lvds_dev {
+	enum dp_lvds_format lvds_format; /* 0:VESA, 1:JEIDA, 2: Location */
+	int pol_inv_hs;		/* hsync polarity invert for VESA, JEIDA */
+	int pol_inv_vs;		/* bsync polarity invert for VESA, JEIDA */
+	int pol_inv_de;		/* de polarity invert for VESA, JEIDA */
+	int pol_inv_ck;		/* input clock(pixel clock) polarity invert */
+	int voltage_level;
+	/* Location setting */
+	unsigned int loc_map[9];	/* Location Setting */
+	unsigned int loc_mask[2];	/* Location Setting, 0 ~ 34 */
+	unsigned int loc_pol[2];	/* Location Setting, 0 ~ 34 */
+};
+
+#include "mipi_display.h"
+
+struct dp_mipi_dev {
+	int lp_bitrate;	/* to lcd setup, low power bitrate (150, 100, 80 Mhz) */
+	int hs_bitrate; /* to lcd data, high speed bitrate (1000, ... Mhz) */
+	int lpm_trans;
+	int command_mode;
+	unsigned int hs_pllpms;
+	unsigned int hs_bandctl;
+	unsigned int lp_pllpms;
+	unsigned int lp_bandctl;
+	struct mipi_dsi_device dsi;
+};
+
+struct dp_rgb_dev {
+	int lcd_mpu_type;
+};
+
+struct dp_hdmi_dev {
+	int preset;
+};
+
+/* platform data for the driver model */
+struct nx_display_platdata {
+	int module;
+	struct dp_sync_info sync;
+	struct dp_ctrl_info ctrl;
+	struct dp_plane_top top;
+	struct dp_plane_info plane[DP_PLANS_NUM];
+	int dev_type;
+	void *device;
+};
+
+/* Lcd api */
+void nx_lvds_display(int module,
+		     struct dp_sync_info *sync, struct dp_ctrl_info *ctrl,
+		     struct dp_plane_top *top,
+		     struct dp_plane_info *planes,
+		     struct dp_lvds_dev *dev);
+
+void nx_rgb_display(int module,
+		    struct dp_sync_info *sync, struct dp_ctrl_info *ctrl,
+		    struct dp_plane_top *top, struct dp_plane_info *planes,
+		    struct dp_rgb_dev *dev);
+
+void nx_hdmi_display(int module,
+		     struct dp_sync_info *sync, struct dp_ctrl_info *ctrl,
+		     struct dp_plane_top *top,
+		     struct dp_plane_info *planes,
+		     struct dp_hdmi_dev *dev);
+
+void nx_mipi_display(int module,
+		     struct dp_sync_info *sync, struct dp_ctrl_info *ctrl,
+		     struct dp_plane_top *top,
+		     struct dp_plane_info *planes,
+		     struct dp_mipi_dev *dev);
+
+int nx_mipi_dsi_lcd_bind(struct mipi_dsi_device *dsi);
+
+/* disaply api */
+void dp_control_init(int module);
+int  dp_control_setup(int module, struct dp_sync_info *sync,
+		      struct dp_ctrl_info *ctrl);
+void dp_control_enable(int module, int on);
+
+void dp_plane_init(int module);
+int  dp_plane_screen_setup(int module, struct dp_plane_top *top);
+void dp_plane_screen_enable(int module, int on);
+
+int  dp_plane_layer_setup(int module, struct dp_plane_info *plane);
+void dp_plane_layer_enable(int module, struct dp_plane_info *plane, int on);
+
+int dp_plane_set_enable(int module, int layer, int on);
+int dp_plane_set_address(int module, int layer, unsigned int address);
+int dp_plane_wait_vsync(int module, int layer, int fps);
+
+#if defined CONFIG_SPL_BUILD ||	\
+	(!defined(CONFIG_DM) && !defined(CONFIG_OF_CONTROL))
+int nx_display_probe(struct nx_display_platdata *plat);
+#endif
+
+#endif
diff --git a/arch/arm/mach-nexell/include/mach/display_dev.h b/arch/arm/mach-nexell/include/mach/display_dev.h
new file mode 100644
index 0000000..77eb614
--- /dev/null
+++ b/arch/arm/mach-nexell/include/mach/display_dev.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0+
+ *
+ * Copyright (C) 2016  Nexell Co., Ltd.
+ *
+ * Author: junghyun, kim <jhkim@nexell.co.kr>
+ */
+
+#ifndef _NX__DISPLAY_DEV_H_
+#define _NX__DISPLAY_DEV_H_
+
+#if defined CONFIG_VIDEO || defined CONFIG_DM_VIDEO
+#include <video_fb.h>
+#elif defined CONFIG_LCD
+#include <lcd.h>
+#endif
+
+struct nx_display_dev {
+#if defined CONFIG_VIDEO || defined CONFIG_DM_VIDEO
+	GraphicDevice graphic_device;
+#elif defined CONFIG_LCD
+	vidinfo_t *panel_info;
+#endif
+	unsigned long base;
+	int module;
+	struct dp_sync_info sync;
+	struct dp_ctrl_info ctrl;
+	struct dp_plane_top top;
+	struct dp_plane_info planes[DP_PLANS_NUM];
+	int dev_type;
+	void *device;
+	struct dp_plane_info *fb_plane;
+	unsigned int depth;	/* byte per pixel */
+	unsigned int fb_addr;
+	unsigned int fb_size;
+};
+
+#endif
diff --git a/arch/arm/mach-nexell/include/mach/ehci.h b/arch/arm/mach-nexell/include/mach/ehci.h
new file mode 100644
index 0000000..545153b
--- /dev/null
+++ b/arch/arm/mach-nexell/include/mach/ehci.h
@@ -0,0 +1,106 @@
+/* SPDX-License-Identifier: GPL-2.0+
+ *
+ * NEXELL USB HOST EHCI Controller
+ *
+ * (C) Copyright 2016 Nexell
+ * Hyunseok, Jung <hsjung@nexell.co.kr>
+ */
+
+#ifndef __ASM_ARM_ARCH_EHCI_H__
+#define __ASM_ARM_ARCH_EHCI_H__
+
+/* Nexell USBHOST PHY registers */
+
+/* USBHOST Configuration 0 Register */
+#define NX_HOST_CON0				0x14
+#define NX_HOST_CON0_SS_WORD_IF			BIT(26)
+#define NX_HOST_CON0_SS_WORD_IF_ENB		BIT(25)
+#define NX_HOST_CON0_SS_WORD_IF_16 ( \
+	NX_HOST_CON0_SS_WORD_IF | \
+	NX_HOST_CON0_SS_WORD_IF_ENB)
+
+#define NX_HOST_CON0_HSIC_480M_FROM_OTG_PHY	BIT(24)
+#define NX_HOST_CON0_HSIC_FREE_CLOCK_ENB	BIT(23)
+#define NX_HOST_CON0_HSIC_CLK_MASK		(0x3 << 23)
+
+#define NX_HOST_CON0_N_HOST_HSIC_RESET_SYNC	BIT(22)
+#define NX_HOST_CON0_N_HOST_UTMI_RESET_SYNC	BIT(21)
+#define NX_HOST_CON0_N_HOST_PHY_RESET_SYNC	BIT(20)
+#define NX_HOST_CON0_UTMI_RESET_SYNC ( \
+	NX_HOST_CON0_N_HOST_HSIC_RESET_SYNC | \
+	NX_HOST_CON0_N_HOST_UTMI_RESET_SYNC | \
+	NX_HOST_CON0_N_HOST_PHY_RESET_SYNC)
+
+#define NX_HOST_CON0_N_AUXWELL_RESET_SYNC	BIT(19)
+#define NX_HOST_CON0_N_OHCI_RESET_SYNC		BIT(18)
+#define NX_HOST_CON0_N_RESET_SYNC		BIT(17)
+#define NX_HOST_CON0_AHB_RESET_SYNC ( \
+	NX_HOST_CON0_N_AUXWELL_RESET_SYNC | \
+	NX_HOST_CON0_N_OHCI_RESET_SYNC | \
+	NX_HOST_CON0_N_RESET_SYNC)
+
+#define NX_HOST_CON0_HSIC_EN_PORT1		(0x2 << 14)
+#define NX_HOST_CON0_HSIC_EN_MASK		(0x7 << 14)
+
+/* USBHOST Configuration 1 Register */
+#define NX_HOST_CON1				0x18
+
+/* USBHOST Configuration 2 Register */
+#define NX_HOST_CON2				0x1C
+#define NX_HOST_CON2_SS_ENA_INCRX_ALIGN		(0x1 << 28)
+#define NX_HOST_CON2_SS_ENA_INCR4		(0x1 << 27)
+#define NX_HOST_CON2_SS_ENA_INCR8		(0x1 << 26)
+#define NX_HOST_CON2_SS_ENA_INCR16		(0x1 << 25)
+#define NX_HOST_CON2_SS_DMA_BURST_MASK  \
+	(NX_HOST_CON2_SS_ENA_INCR16 | NX_HOST_CON2_SS_ENA_INCR8 | \
+	 NX_HOST_CON2_SS_ENA_INCR4 | NX_HOST_CON2_SS_ENA_INCRX_ALIGN)
+
+#define NX_HOST_CON2_EHCI_SS_ENABLE_DMA_BURST \
+	(NX_HOST_CON2_SS_ENA_INCR16 | NX_HOST_CON2_SS_ENA_INCR8 | \
+	 NX_HOST_CON2_SS_ENA_INCR4 | NX_HOST_CON2_SS_ENA_INCRX_ALIGN)
+
+#define NX_HOST_CON2_OHCI_SS_ENABLE_DMA_BURST \
+	(NX_HOST_CON2_SS_ENA_INCR4 | NX_HOST_CON2_SS_ENA_INCRX_ALIGN)
+
+#define NX_HOST_CON2_SS_FLADJ_VAL_0_OFFSET	(21)
+#define NX_HOST_CON2_SS_FLADJ_VAL_OFFSET	(3)
+#define NX_HOST_CON2_SS_FLADJ_VAL_NUM		(6)
+#define NX_HOST_CON2_SS_FLADJ_VAL_0_SEL		BIT(5)
+#define NX_HOST_CON2_SS_FLADJ_VAL_MAX		0x7
+
+/* USBHOST Configuration 3 Register */
+#define NX_HOST_CON3				0x20
+#define NX_HOST_CON3_POR			BIT(8)
+#define NX_HOST_CON3_POR_ENB			BIT(7)
+#define NX_HOST_CON3_POR_MASK			(0x3 << 7)
+
+/* USBHOST Configuration 4 Register */
+#define NX_HOST_CON4				0x24
+#define NX_HOST_CON4_WORDINTERFACE		BIT(9)
+#define NX_HOST_CON4_WORDINTERFACE_ENB		BIT(8)
+#define NX_HOST_CON4_WORDINTERFACE_16 ( \
+	NX_HOST_CON4_WORDINTERFACE | \
+	NX_HOST_CON4_WORDINTERFACE_ENB)
+
+/* USBHOST Configuration 5 Register */
+#define NX_HOST_CON5				0x28
+#define NX_HOST_CON5_HSIC_POR			BIT(19)
+#define NX_HOST_CON5_HSIC_POR_ENB		BIT(18)
+#define NX_HOST_CON5_HSIC_POR_MASK		(0x3 << 18)
+
+/* USBHOST Configuration 6 Register */
+#define NX_HOST_CON6				0x2C
+#define NX_HOST_CON6_HSIC_WORDINTERFACE		BIT(13)
+#define NX_HOST_CON6_HSIC_WORDINTERFACE_ENB	BIT(12)
+#define NX_HOST_CON6_HSIC_WORDINTERFACE_16 ( \
+	NX_HOST_CON6_HSIC_WORDINTERFACE | \
+	NX_HOST_CON6_HSIC_WORDINTERFACE_ENB)
+
+/* Register map for PHY control */
+struct nx_usb_phy {
+	unsigned int reserved;
+	unsigned int others[4];
+	unsigned int usbhost_con[7];
+};
+
+#endif /* __ASM_ARM_ARCH_EHCI_H__ */
diff --git a/arch/arm/mach-nexell/include/mach/gpio.h b/arch/arm/mach-nexell/include/mach/gpio.h
new file mode 100644
index 0000000..7167d3c
--- /dev/null
+++ b/arch/arm/mach-nexell/include/mach/gpio.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0+
+ *
+ * (C) Copyright 2016 Nexell
+ * DeokJin, Lee <truevirtue@nexell.co.kr>
+ */
+
+#ifndef __ASM_ARCH_NEXELL_GPIO_H
+#define __ASM_ARCH_NEXELL_GPIO_H
+
+#include <asm/io.h>
+#include <linux/errno.h>
+
+#define PIN_BASE		0
+
+#define MAX_GPIO_BANKS		5
+
+#endif /* __ASM_ARCH_NEXELL_GPIO_H */
diff --git a/arch/arm/mach-nexell/include/mach/mipi_display.h b/arch/arm/mach-nexell/include/mach/mipi_display.h
new file mode 100644
index 0000000..f3fdec6
--- /dev/null
+++ b/arch/arm/mach-nexell/include/mach/mipi_display.h
@@ -0,0 +1,215 @@
+/* SPDX-License-Identifier: GPL-2.0+
+ *
+ * Defines for Mobile Industry Processor Interface (MIPI(R))
+ * Display Working Group standards: DSI, DCS, DBI, DPI
+ *
+ * Copyright (C) 2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+ * Copyright (C) 2006 Nokia Corporation
+ * Author: Imre Deak <imre.deak@nokia.com>
+ */
+
+#ifndef MIPI_DISPLAY_H
+#define MIPI_DISPLAY_H
+
+/* MIPI DSI Processor-to-Peripheral transaction types */
+enum {
+	MIPI_DSI_V_SYNC_START				= 0x01,
+	MIPI_DSI_V_SYNC_END				= 0x11,
+	MIPI_DSI_H_SYNC_START				= 0x21,
+	MIPI_DSI_H_SYNC_END				= 0x31,
+
+	MIPI_DSI_COLOR_MODE_OFF				= 0x02,
+	MIPI_DSI_COLOR_MODE_ON				= 0x12,
+	MIPI_DSI_SHUTDOWN_PERIPHERAL			= 0x22,
+	MIPI_DSI_TURN_ON_PERIPHERAL			= 0x32,
+
+	MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM		= 0x03,
+	MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM		= 0x13,
+	MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM		= 0x23,
+
+	MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM		= 0x04,
+	MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM		= 0x14,
+	MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM		= 0x24,
+
+	MIPI_DSI_DCS_SHORT_WRITE			= 0x05,
+	MIPI_DSI_DCS_SHORT_WRITE_PARAM			= 0x15,
+
+	MIPI_DSI_DCS_READ				= 0x06,
+
+	MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE		= 0x37,
+
+	MIPI_DSI_END_OF_TRANSMISSION			= 0x08,
+
+	MIPI_DSI_NULL_PACKET				= 0x09,
+	MIPI_DSI_BLANKING_PACKET			= 0x19,
+	MIPI_DSI_GENERIC_LONG_WRITE			= 0x29,
+	MIPI_DSI_DCS_LONG_WRITE				= 0x39,
+
+	MIPI_DSI_LOOSELY_PACKED_PIXEL_STREAM_YCBCR20	= 0x0c,
+	MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR24		= 0x1c,
+	MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16		= 0x2c,
+
+	MIPI_DSI_PACKED_PIXEL_STREAM_30			= 0x0d,
+	MIPI_DSI_PACKED_PIXEL_STREAM_36			= 0x1d,
+	MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12		= 0x3d,
+
+	MIPI_DSI_PACKED_PIXEL_STREAM_16			= 0x0e,
+	MIPI_DSI_PACKED_PIXEL_STREAM_18			= 0x1e,
+	MIPI_DSI_PIXEL_STREAM_3BYTE_18			= 0x2e,
+	MIPI_DSI_PACKED_PIXEL_STREAM_24			= 0x3e,
+};
+
+/* MIPI DSI Peripheral-to-Processor transaction types */
+enum {
+	MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT	= 0x02,
+	MIPI_DSI_RX_END_OF_TRANSMISSION			= 0x08,
+	MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE	= 0x11,
+	MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE	= 0x12,
+	MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE		= 0x1a,
+	MIPI_DSI_RX_DCS_LONG_READ_RESPONSE		= 0x1c,
+	MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE	= 0x21,
+	MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE	= 0x22,
+};
+
+/* MIPI DCS commands */
+enum {
+	MIPI_DCS_NOP			= 0x00,
+	MIPI_DCS_SOFT_RESET		= 0x01,
+	MIPI_DCS_GET_DISPLAY_ID		= 0x04,
+	MIPI_DCS_GET_RED_CHANNEL	= 0x06,
+	MIPI_DCS_GET_GREEN_CHANNEL	= 0x07,
+	MIPI_DCS_GET_BLUE_CHANNEL	= 0x08,
+	MIPI_DCS_GET_DISPLAY_STATUS	= 0x09,
+	MIPI_DCS_GET_POWER_MODE		= 0x0A,
+	MIPI_DCS_GET_ADDRESS_MODE	= 0x0B,
+	MIPI_DCS_GET_PIXEL_FORMAT	= 0x0C,
+	MIPI_DCS_GET_DISPLAY_MODE	= 0x0D,
+	MIPI_DCS_GET_SIGNAL_MODE	= 0x0E,
+	MIPI_DCS_GET_DIAGNOSTIC_RESULT	= 0x0F,
+	MIPI_DCS_ENTER_SLEEP_MODE	= 0x10,
+	MIPI_DCS_EXIT_SLEEP_MODE	= 0x11,
+	MIPI_DCS_ENTER_PARTIAL_MODE	= 0x12,
+	MIPI_DCS_ENTER_NORMAL_MODE	= 0x13,
+	MIPI_DCS_EXIT_INVERT_MODE	= 0x20,
+	MIPI_DCS_ENTER_INVERT_MODE	= 0x21,
+	MIPI_DCS_SET_GAMMA_CURVE	= 0x26,
+	MIPI_DCS_SET_DISPLAY_OFF	= 0x28,
+	MIPI_DCS_SET_DISPLAY_ON		= 0x29,
+	MIPI_DCS_SET_COLUMN_ADDRESS	= 0x2A,
+	MIPI_DCS_SET_PAGE_ADDRESS	= 0x2B,
+	MIPI_DCS_WRITE_MEMORY_START	= 0x2C,
+	MIPI_DCS_WRITE_LUT		= 0x2D,
+	MIPI_DCS_READ_MEMORY_START	= 0x2E,
+	MIPI_DCS_SET_PARTIAL_AREA	= 0x30,
+	MIPI_DCS_SET_SCROLL_AREA	= 0x33,
+	MIPI_DCS_SET_TEAR_OFF		= 0x34,
+	MIPI_DCS_SET_TEAR_ON		= 0x35,
+	MIPI_DCS_SET_ADDRESS_MODE	= 0x36,
+	MIPI_DCS_SET_SCROLL_START	= 0x37,
+	MIPI_DCS_EXIT_IDLE_MODE		= 0x38,
+	MIPI_DCS_ENTER_IDLE_MODE	= 0x39,
+	MIPI_DCS_SET_PIXEL_FORMAT	= 0x3A,
+	MIPI_DCS_WRITE_MEMORY_CONTINUE	= 0x3C,
+	MIPI_DCS_READ_MEMORY_CONTINUE	= 0x3E,
+	MIPI_DCS_SET_TEAR_SCANLINE	= 0x44,
+	MIPI_DCS_GET_SCANLINE		= 0x45,
+	MIPI_DCS_READ_DDB_START		= 0xA1,
+	MIPI_DCS_READ_DDB_CONTINUE	= 0xA8,
+};
+
+/* MIPI DCS pixel formats */
+#define MIPI_DCS_PIXEL_FMT_24BIT	7
+#define MIPI_DCS_PIXEL_FMT_18BIT	6
+#define MIPI_DCS_PIXEL_FMT_16BIT	5
+#define MIPI_DCS_PIXEL_FMT_12BIT	3
+#define MIPI_DCS_PIXEL_FMT_8BIT		2
+#define MIPI_DCS_PIXEL_FMT_3BIT		1
+
+/* request ACK from peripheral */
+#define MIPI_DSI_MSG_REQ_ACK    BIT(0)
+/* use Low Power Mode to transmit message */
+#define MIPI_DSI_MSG_USE_LPM    BIT(1)
+
+/**
+ * struct mipi_dsi_msg - read/write DSI buffer
+ * @channel: virtual channel id
+ * @type: payload data type
+ * @flags: flags controlling this message transmission
+ * @tx_len: length of @tx_buf
+ * @tx_buf: data to be written
+ * @rx_len: length of @rx_buf
+ * @rx_buf: data to be read, or NULL
+ */
+struct mipi_dsi_msg {
+	u8 channel;	/* virtual channel id */
+	u8 type;	/* payload data type */
+	u16 flags;	/* flags controlling this message transmission */
+	size_t tx_len;
+	const void *tx_buf;
+	size_t rx_len;
+	void *rx_buf;
+};
+
+/* DSI mode flags */
+
+/* video mode */
+#define MIPI_DSI_MODE_VIDEO             BIT(0)
+/* video burst mode */
+#define MIPI_DSI_MODE_VIDEO_BURST       BIT(1)
+/* video pulse mode */
+#define MIPI_DSI_MODE_VIDEO_SYNC_PULSE  BIT(2)
+/* enable auto vertical count mode */
+#define MIPI_DSI_MODE_VIDEO_AUTO_VERT   BIT(3)
+/* enable hsync-end packets in vsync-pulse and v-porch area */
+#define MIPI_DSI_MODE_VIDEO_HSE         BIT(4)
+/* disable hfront-porch area */
+#define MIPI_DSI_MODE_VIDEO_HFP         BIT(5)
+/* disable hback-porch area */
+#define MIPI_DSI_MODE_VIDEO_HBP         BIT(6)
+/* disable hsync-active area */
+#define MIPI_DSI_MODE_VIDEO_HSA         BIT(7)
+/* flush display FIFO on vsync pulse */
+#define MIPI_DSI_MODE_VSYNC_FLUSH       BIT(8)
+/* disable EoT packets in HS mode */
+#define MIPI_DSI_MODE_EOT_PACKET        BIT(9)
+/* device supports non-continuous clock behavior (DSI spec 5.6.1) */
+#define MIPI_DSI_CLOCK_NON_CONTINUOUS   BIT(10)
+/* transmit data in low power */
+#define MIPI_DSI_MODE_LPM               BIT(11) /* DSI mode flags */
+
+enum mipi_dsi_pixel_format {
+	MIPI_DSI_FMT_RGB888,
+	MIPI_DSI_FMT_RGB666,
+	MIPI_DSI_FMT_RGB666_PACKED,
+	MIPI_DSI_FMT_RGB565,
+};
+
+/**
+ * struct mipi_dsi_device - DSI peripheral device
+ * @host: DSI host for this peripheral
+ * @dev: driver model device node for this peripheral
+ * @channel: virtual channel assigned to the peripheral
+ * @format: pixel format for video mode
+ * @lanes: number of active data lanes
+ * @mode_flags: DSI operation mode related flags
+ */
+struct mipi_dsi_device {
+	unsigned int channel;
+	unsigned int lanes;
+	enum mipi_dsi_pixel_format format;
+	unsigned long mode_flags;
+	struct mipi_panel_ops *ops;
+	ssize_t (*write_buffer)(struct mipi_dsi_device *dsi,
+				const void *data, size_t len);
+};
+
+struct mipi_panel_ops {
+	int (*init)(struct mipi_dsi_device *dsi, int width, int height);
+	int (*prepare)(struct mipi_dsi_device *dsi);
+	int (*unprepare)(struct mipi_dsi_device *dsi);
+	int (*enable)(struct mipi_dsi_device *dsi);
+	int (*disable)(struct mipi_dsi_device *dsi);
+	void *private_data;
+};
+
+#endif
diff --git a/arch/arm/mach-nexell/include/mach/nexell.h b/arch/arm/mach-nexell/include/mach/nexell.h
new file mode 100644
index 0000000..e42805f
--- /dev/null
+++ b/arch/arm/mach-nexell/include/mach/nexell.h
@@ -0,0 +1,352 @@
+/* SPDX-License-Identifier: GPL-2.0+
+ *
+ * (C) Copyright 2016 Nexell
+ * Hyunseok, Jung <hsjung@nexell.co.kr>
+ */
+
+#ifndef __NEXELL_H__
+#define __NEXELL_H__
+
+#define PHY_BASEADDR_DMA0		(0xC0000000)
+#define PHY_BASEADDR_DMA1		(0xC0001000)
+#if defined(CONFIG_ARCH_S5P4418)
+#define PHY_BASEADDR_INTC0		(0xC0002000)
+#define PHY_BASEADDR_INTC1		(0xC0003000)
+#elif defined(CONFIG_ARCH_S5P6818)
+#define PHY_BASEADDR_INTC		(0xC0008000)
+#endif
+#define PHY_BASEADDR_CLKPWR		(0xC0010000)
+#define PHY_BASEADDR_RTC		(0xC0010C00)
+#define PHY_BASEADDR_ALIVE		(0xC0010800)
+#define PHY_BASEADDR_RSTCON		(0xC0012000)
+#define PHY_BASEADDR_TIEOFF		(0xC0011000)
+#define PHY_BASEADDR_PDM		(0xC0014000)
+#define PHY_BASEADDR_CRYPTO		(0xC0015000)
+#define PHY_BASEADDR_TIMER		(0xC0017000)
+#define PHY_BASEADDR_PWM		(0xC0018000)
+#define PHY_BASEADDR_WDT		(0xC0019000)
+#define PHY_BASEADDR_GPIOA		(0xC001A000)
+#define PHY_BASEADDR_GPIOB		(0xC001B000)
+#define PHY_BASEADDR_GPIOC		(0xC001C000)
+#define PHY_BASEADDR_GPIOD		(0xC001D000)
+#define PHY_BASEADDR_GPIOE		(0xC001E000)
+#define PHY_BASEADDR_OHCI		(0xC0020000)
+#define PHY_BASEADDR_EHCI		(0xC0030000)
+#define PHY_BASEADDR_HSOTG		(0xC0040000)
+#define PHY_BASEADDR_ADC		(0xC0053000)
+#define PHY_BASEADDR_PPM		(0xC0054000)
+#define PHY_BASEADDR_I2S0		(0xC0055000)
+#define PHY_BASEADDR_I2S1		(0xC0056000)
+#define PHY_BASEADDR_I2S2		(0xC0057000)
+#define PHY_BASEADDR_AC97		(0xC0058000)
+#define PHY_BASEADDR_SPDIF_TX		(0xC0059000)
+#define PHY_BASEADDR_SPDIF_RX		(0xC005A000)
+#define PHY_BASEADDR_SSP0		(0xC005B000)
+#define PHY_BASEADDR_SSP1		(0xC005C000)
+#define PHY_BASEADDR_SSP2		(0xC005F000)
+#define PHY_BASEADDR_MPEGTSI		(0xC005D000)
+#define PHY_BASEADDR_GMAC		(0xC0060000)
+#define PHY_BASEADDR_VIP0		(0xC0063000)
+#define PHY_BASEADDR_VIP1		(0xC0064000)
+#if defined(CONFIG_ARCH_S5P6818)
+#define PHY_BASEADDR_VIP2		(0xC0099000)
+#endif
+#define PHY_BASEADDR_DEINTERLACE	(0xC0065000)
+#define PHY_BASEADDR_SCALER		(0xC0066000)
+#define PHY_BASEADDR_ECID		(0xC0067000)
+#define PHY_BASEADDR_SDMMC0		(0xC0062000)
+#define PHY_BASEADDR_SDMMC1		(0xC0068000)
+#define PHY_BASEADDR_SDMMC2		(0xC0069000)
+#define PHY_BASEADDR_MALI400		(0xC0070000)
+#define PHY_BASEADDR_CODA_APB0		(0xC0080000)
+#define PHY_BASEADDR_CODA_APB1		(0xC0081000)
+#define PHY_BASEADDR_CODA_APB2		(0xC0082000)
+#define PHY_BASEADDR_CODA_APB3		(0xC0083000)
+/* dma (O), modem(X), UART0_MODULE */
+#define PHY_BASEADDR_UART0		(0xC00A1000)
+/* dma (O), modem(O), pl01115_Uart_modem_MODULE */
+#define PHY_BASEADDR_UART1		(0xC00A0000)
+/* dma (O), modem(X), UART1_MODULE */
+#define PHY_BASEADDR_UART2		(0xC00A2000)
+/* dma (X), modem(X), pl01115_Uart_nodma0_MODULE */
+#define PHY_BASEADDR_UART3		(0xC00A3000)
+/* dma (X), modem(X), pl01115_Uart_nodma1_MODULE */
+#define PHY_BASEADDR_UART4		(0xC006D000)
+/* dma (X), modem(X), pl01115_Uart_nodma2_MODULE */
+#define PHY_BASEADDR_UART5		(0xC006F000)
+#define PHY_BASEADDR_I2C0		(0xC00A4000)
+#define PHY_BASEADDR_I2C1		(0xC00A5000)
+#define PHY_BASEADDR_I2C2		(0xC00A6000)
+#define PHY_BASEADDR_CAN0		(0xC00CE000)
+#define PHY_BASEADDR_CAN1		(0xC00CF000)
+#define PHY_BASEADDR_MIPI		(0xC00D0000)
+#define PHY_BASEADDR_DISPLAYTOP		(0xC0100000)
+
+#define PHY_BASEADDR_CLKGEN0		(0xC00BB000)	/* TIMER_1 */
+#define PHY_BASEADDR_CLKGEN1		(0xC00BC000)	/* TIMER_2 */
+#define PHY_BASEADDR_CLKGEN2		(0xC00BD000)	/* TIMER_3 */
+#define PHY_BASEADDR_CLKGEN3		(0xC00BE000)	/* PWM_1 */
+#define PHY_BASEADDR_CLKGEN4		(0xC00BF000)	/* PWM_2 */
+#define PHY_BASEADDR_CLKGEN5		(0xC00C0000)	/* PWM_3 */
+#define PHY_BASEADDR_CLKGEN6		(0xC00AE000)	/* I2C_0 */
+#define PHY_BASEADDR_CLKGEN7		(0xC00AF000)	/* I2C_1 */
+#define PHY_BASEADDR_CLKGEN8		(0xC00B0000)	/* I2C_2 */
+#define PHY_BASEADDR_CLKGEN9		(0xC00CA000)	/* MIPI */
+#define PHY_BASEADDR_CLKGEN10		(0xC00C8000)	/* GMAC */
+#define PHY_BASEADDR_CLKGEN11		(0xC00B8000)	/* SPDIF_TX */
+#define PHY_BASEADDR_CLKGEN12		(0xC00B7000)	/* MPEGTSI */
+#define PHY_BASEADDR_CLKGEN13		(0xC00BA000)	/* PWM_0 */
+#define PHY_BASEADDR_CLKGEN14		(0xC00B9000)	/* TIMER_0 */
+#define PHY_BASEADDR_CLKGEN15		(0xC00B2000)	/* I2S_0 */
+#define PHY_BASEADDR_CLKGEN16		(0xC00B3000)	/* I2S_1 */
+#define PHY_BASEADDR_CLKGEN17		(0xC00B4000)	/* I2S_2 */
+#define PHY_BASEADDR_CLKGEN18		(0xC00C5000)	/* SDHC_0 */
+#define PHY_BASEADDR_CLKGEN19		(0xC00CC000)	/* SDHC_1 */
+#define PHY_BASEADDR_CLKGEN20		(0xC00CD000)	/* SDHC_2 */
+#define PHY_BASEADDR_CLKGEN21		(0xC00C3000)	/* MALI */
+#define PHY_BASEADDR_CLKGEN22		(0xC00A9000)	/* UART_0 */
+#define PHY_BASEADDR_CLKGEN23		(0xC00AA000)	/* UART_2 */
+#define PHY_BASEADDR_CLKGEN24		(0xC00A8000)	/* UART_1 */
+#define PHY_BASEADDR_CLKGEN25		(0xC00AB000)	/* UART_3 */
+#define PHY_BASEADDR_CLKGEN26		(0xC006E000)	/* UART_4 */
+#define PHY_BASEADDR_CLKGEN27		(0xC00B1000)	/* UART_5 */
+#define PHY_BASEADDR_CLKGEN28		(0xC00B5000)	/* DEINTERLACE */
+#define PHY_BASEADDR_CLKGEN29		(0xC00C4000)	/* PPM */
+#define PHY_BASEADDR_CLKGEN30		(0xC00C1000)	/* VIP_0 */
+#define PHY_BASEADDR_CLKGEN31		(0xC00C2000)	/* VIP_1 */
+#define PHY_BASEADDR_CLKGEN32		(0xC006B000)	/* USB2HOST */
+#define PHY_BASEADDR_CLKGEN33		(0xC00C7000)	/* CODA */
+#define PHY_BASEADDR_CLKGEN34		(0xC00C6000)	/* CRYPTO */
+#define PHY_BASEADDR_CLKGEN35		(0xC00B6000)	/* SCALER */
+#define PHY_BASEADDR_CLKGEN36		(0xC00CB000)	/* PDM */
+#define PHY_BASEADDR_CLKGEN37		(0xC00AC000)	/* SPI0 */
+#define PHY_BASEADDR_CLKGEN38		(0xC00AD000)	/* SPI1 */
+#define PHY_BASEADDR_CLKGEN39		(0xC00A7000)	/* SPI2 */
+#if defined(CONFIG_ARCH_S5P6818)
+#define PHY_BASEADDR_CLKGEN40		(0xC009A000)
+#endif
+#define PHY_BASEADDR_DREX		(0xC00E0000)
+
+#define PHY_BASEADDR_CS_NAND		(0x2C000000)
+
+#define PHY_BASEADDR_SRAM		(0xFFFF0000)
+
+/*
+ * Nexell clock generator
+ */
+#define CLK_ID_TIMER_1			0
+#define CLK_ID_TIMER_2			1
+#define CLK_ID_TIMER_3			2
+#define CLK_ID_PWM_1			3
+#define CLK_ID_PWM_2			4
+#define CLK_ID_PWM_3			5
+#define CLK_ID_I2C_0			6
+#define CLK_ID_I2C_1			7
+#define CLK_ID_I2C_2			8
+#define CLK_ID_MIPI			9
+#define CLK_ID_GMAC			10	/* External Clock 1 */
+#define CLK_ID_SPDIF_TX			11
+#define CLK_ID_MPEGTSI			12
+#define CLK_ID_PWM_0			13
+#define CLK_ID_TIMER_0			14
+#define CLK_ID_I2S_0			15	/* External Clock 1 */
+#define CLK_ID_I2S_1			16	/* External Clock 1 */
+#define CLK_ID_I2S_2			17	/* External Clock 1 */
+#define CLK_ID_SDHC_0			18
+#define CLK_ID_SDHC_1			19
+#define CLK_ID_SDHC_2			20
+#define CLK_ID_MALI			21
+#define CLK_ID_UART_0			22	/* UART0_MODULE */
+#define CLK_ID_UART_2			23	/* UART1_MODULE */
+#define CLK_ID_UART_1			24	/* pl01115_Uart_modem_MODULE  */
+#define CLK_ID_UART_3			25	/* pl01115_Uart_nodma0_MODULE */
+#define CLK_ID_UART_4			26	/* pl01115_Uart_nodma1_MODULE */
+#define CLK_ID_UART_5			27	/* pl01115_Uart_nodma2_MODULE */
+#define CLK_ID_DIT			28
+#define CLK_ID_PPM			29
+#define CLK_ID_VIP_0			30	/* External Clock 1 */
+#define CLK_ID_VIP_1			31	/* External Clock 1, 2 */
+#define CLK_ID_USB2HOST			32	/* External Clock 2 */
+#define CLK_ID_CODA			33
+#define CLK_ID_CRYPTO			34
+#define CLK_ID_SCALER			35
+#define CLK_ID_PDM			36
+#define CLK_ID_SPI_0			37
+#define CLK_ID_SPI_1			38
+#define CLK_ID_SPI_2			39
+#define CLK_ID_MAX			39
+
+/*
+ * Nexell Reset control
+ */
+#define RESET_ID_AC97			0
+#define RESET_ID_CPU1			1
+#define RESET_ID_CPU2			2
+#define RESET_ID_CPU3			3
+#define RESET_ID_WD1			4
+#define RESET_ID_WD2			5
+#define RESET_ID_WD3			6
+#define RESET_ID_CRYPTO			7
+#define RESET_ID_DEINTERLACE		8
+#define RESET_ID_DISP_TOP		9
+#define RESET_ID_DISPLAY		10
+#define RESET_ID_RESCONV		11
+#define RESET_ID_LCDIF			12
+#define RESET_ID_HDMI			13
+#define RESET_ID_HDMI_VIDEO		14
+#define RESET_ID_HDMI_SPDIF		15
+#define RESET_ID_HDMI_TMDS		16
+#define RESET_ID_HDMI_PHY		17
+#define RESET_ID_LVDS			18
+#define RESET_ID_ECID			19
+#define RESET_ID_I2C0			20
+#define RESET_ID_I2C1			21
+#define RESET_ID_I2C2			22
+#define RESET_ID_I2S0			23
+#define RESET_ID_I2S1			24
+#define RESET_ID_I2S2			25
+#define RESET_ID_DREX_C			26
+#define RESET_ID_DREX_A			27
+#define RESET_ID_DREX			28
+#define RESET_ID_MIPI			29
+#define RESET_ID_MIPI_DSI		30
+#define RESET_ID_MIPI_CSI		31
+#define RESET_ID_MIPI_PHY_S		32
+#define RESET_ID_MIPI_PHY_M		33
+#define RESET_ID_MPEGTSI		34
+#define RESET_ID_PDM			35
+#define RESET_ID_TIMER			36
+#define RESET_ID_PWM			37
+#define RESET_ID_SCALER			38
+#define RESET_ID_SDMMC0			39
+#define RESET_ID_SDMMC1			40
+#define RESET_ID_SDMMC2			41
+#define RESET_ID_SPDIFRX		42
+#define RESET_ID_SPDIFTX		43
+#define RESET_ID_SSP0_P			44
+#define RESET_ID_SSP0			45
+#define RESET_ID_SSP1_P			46
+#define RESET_ID_SSP1			47
+#define RESET_ID_SSP2_P			48
+#define RESET_ID_SSP2			49
+#define RESET_ID_UART0			50	/* UART1 */
+#define RESET_ID_UART1			51	/* pl01115_Uart_modem	*/
+#define RESET_ID_UART2			52	/* UART1 */
+#define RESET_ID_UART3			53	/* pl01115_Uart_nodma0 */
+#define RESET_ID_UART4			54	/* pl01115_Uart_nodma1 */
+#define RESET_ID_UART5			55	/* pl01115_Uart_nodma2 */
+#define RESET_ID_USB20HOST		56
+#define RESET_ID_USB20OTG		57
+#define RESET_ID_WDT			58
+#define RESET_ID_WDT_POR		59
+#define RESET_ID_ADC			60
+#define RESET_ID_CODA_A			61
+#define RESET_ID_CODA_P			62
+#define RESET_ID_CODA_C			63
+#define RESET_ID_DWC_GMAC		64
+#define RESET_ID_MALI400		65
+#define RESET_ID_PPM			66
+#define RESET_ID_VIP1			67
+#define RESET_ID_VIP0			68
+#if defined(CONFIG_ARCH_S5P6818)
+#define RESET_ID_VIP2			69
+#endif
+
+/*
+ * device name
+ */
+#define DEV_NAME_UART			"nx-uart" /* pl0115 (amba-pl011.c) */
+#define DEV_NAME_FB			"nx-fb"
+#define DEV_NAME_DISP			"nx-disp"
+#define DEV_NAME_LCD			"nx-lcd"
+#define DEV_NAME_LVDS			"nx-lvds"
+#define DEV_NAME_HDMI			"nx-hdmi"
+#define DEV_NAME_RESCONV		"nx-resconv"
+#define DEV_NAME_MIPI			"nx-mipi"
+#define DEV_NAME_PCM			"nx-pcm"
+#define DEV_NAME_I2S			"nx-i2s"
+#define DEV_NAME_SPDIF_TX		"nx-spdif-tx"
+#define DEV_NAME_SPDIF_RX		"nx-spdif-rx"
+#define DEV_NAME_I2C			"nx-i2c"
+#define DEV_NAME_NAND			"nx-nand"
+#define DEV_NAME_KEYPAD			"nx-keypad"
+#define DEV_NAME_SDHC			"nx-sdhc"
+#define DEV_NAME_PWM			"nx-pwm"
+#define DEV_NAME_TIMER			"nx-timer"
+#define DEV_NAME_SOC_PWM		"nx-soc-pwm"
+#define DEV_NAME_GPIO			"nx-gpio"
+#define DEV_NAME_RTC			"nx-rtc"
+#define DEV_NAME_GMAC			"nx-gmac"
+#define DEV_NAME_MPEGTSI		"nx-mpegtsi"
+#define DEV_NAME_MALI			"nx-mali"
+#define DEV_NAME_DIT			"nx-deinterlace"
+#define DEV_NAME_PPM			"nx-ppm"
+#define DEV_NAME_VIP			"nx-vip"
+#define DEV_NAME_CODA			"nx-coda"
+#define DEV_NAME_USB2HOST		"nx-usb2h"
+#define DEV_NAME_CRYPTO			"nx-crypto"
+#define DEV_NAME_SCALER			"nx-scaler"
+#define DEV_NAME_PDM			"nx-pdm"
+#define DEV_NAME_SPI			"nx-spi"
+#define DEV_NAME_CPUFREQ		"nx-cpufreq"
+
+/*
+ * clock generator
+ */
+#define CORECLK_NAME_PLL0		"pll0"	/* cpu clock */
+#define CORECLK_NAME_PLL1		"pll1"
+#define CORECLK_NAME_PLL2		"pll2"
+#define CORECLK_NAME_PLL3		"pll3"
+#define CORECLK_NAME_FCLK		"fclk"
+#define CORECLK_NAME_MCLK		"mclk"
+#define CORECLK_NAME_BCLK		"bclk"
+#define CORECLK_NAME_PCLK		"pclk"
+#define CORECLK_NAME_HCLK		"hclk"
+
+#define CORECLK_ID_PLL0			0
+#define CORECLK_ID_PLL1			1
+#define CORECLK_ID_PLL2			2
+#define CORECLK_ID_PLL3			3
+#define CORECLK_ID_FCLK			4
+#define CORECLK_ID_MCLK			5
+#define CORECLK_ID_BCLK			6
+#define CORECLK_ID_PCLK			7
+#define CORECLK_ID_HCLK			8
+
+#define ALIVEPWRGATEREG			(PHY_BASEADDR_ALIVE + 0x0)
+
+#if defined(CONFIG_ARCH_S5P4418)
+#define	SCR_ARM_SECOND_BOOT		(0xC0010C1C)	 /* PWR scratch */
+#define	SCR_ARM_SECOND_BOOT_REG1	(0xc0010234) /* ToDo : Check Address */
+#elif defined(CONFIG_ARCH_S5P6818)
+#define	SCR_ARM_SECOND_BOOT		(0xc0010230)	 /* PWR scratch */
+#define	SCR_ARM_SECOND_BOOT_REG1	(0xc0010234) /* PWR scratch */
+#define	SCR_ARM_SECOND_BOOT_REG2	(0xc0010238) /* PWR scratch */
+#endif
+
+#define	SCR_ALIVE_BASE			(PHY_BASEADDR_ALIVE)
+#define	SCR_SIGNAGURE_RESET		(SCR_ALIVE_BASE + 0x068)
+#define	SCR_SIGNAGURE_SET		(SCR_ALIVE_BASE + 0x06C)
+#define	SCR_SIGNAGURE_READ		(SCR_ALIVE_BASE + 0x070)
+
+#define SYSRSTCONFIG			(0x23C)
+#define DEVICEBOOTINFO			(0x50)
+#define BOOTMODE_MASK			(0x7)
+#define BOOTMODE_SDMMC			5
+#define BOOTMODE_USB			6
+#define BOOTMODE_SDMMC_PORT_VAL(x)	((((x) >> 3) & 1) |	\
+					 (((x) >> 19 & 1) << 1))
+#define EMMC_PORT_NUM			2
+#define SD_PORT_NUM			0
+#define ID_REG_EC0				(0x54)
+#define WIRE0_MASK				(0x1)
+
+#ifndef __ASSEMBLY__
+
+#define NS_IN_HZ (1000000000UL)
+#define TO_PERIOD_NS(freq)	(NS_IN_HZ / (freq))
+#define TO_DUTY_NS(duty, freq)  (duty ? TO_PERIOD_NS(freq) / (100 / duty) : 0)
+
+#endif	/* __ASSEMBLY__ */
+
+#endif /* __NEXELL_H__ */
diff --git a/arch/arm/mach-nexell/include/mach/nx_gpio.h b/arch/arm/mach-nexell/include/mach/nx_gpio.h
new file mode 100644
index 0000000..91803d2
--- /dev/null
+++ b/arch/arm/mach-nexell/include/mach/nx_gpio.h
@@ -0,0 +1,103 @@
+/* SPDX-License-Identifier: GPL-2.0+
+ *
+ * (C) Copyright 2016 Nexell
+ * Youngbok, Park <ybpark@nexell.co.kr>
+ */
+
+#include <linux/types.h>
+#include <asm/io.h>
+
+#ifndef __nx_gpio_h__
+#define __nx_gpio_h__
+
+struct nx_gpio_register_set {
+	u32 gpioxout;
+	u32 gpioxoutenb;
+	u32 gpioxdetmode[2];
+	u32 gpioxintenb;
+	u32 gpioxdet;
+	u32 gpioxpad;
+	u32 gpioxpuenb;
+	u32 gpioxaltfn[2];
+	u32 gpioxdetmodeex;
+	u32 __reserved[4];
+	u32 gpioxdetenb;
+	u32 gpiox_slew;
+	u32 gpiox_slew_disable_default;
+	u32 gpiox_drv1;
+	u32 gpiox_drv1_disable_default;
+	u32 gpiox_drv0;
+	u32 gpiox_drv0_disable_default;
+	u32 gpiox_pullsel;
+	u32 gpiox_pullsel_disable_default;
+	u32 gpiox_pullenb;
+	u32 gpiox_pullenb_disable_default;
+	u32 gpiox_input_mux_select0;
+	u32 gpiox_input_mux_select1;
+	u8 __reserved1[0x1000 - 0x70];
+};
+
+enum {
+	nx_gpio_padfunc_0 = 0ul,
+	nx_gpio_padfunc_1 = 1ul,
+	nx_gpio_padfunc_2 = 2ul,
+	nx_gpio_padfunc_3 = 3ul
+};
+
+enum {
+	nx_gpio_drvstrength_0 = 0ul,
+	nx_gpio_drvstrength_1 = 1ul,
+	nx_gpio_drvstrength_2 = 2ul,
+	nx_gpio_drvstrength_3 = 3ul
+};
+
+enum {
+	nx_gpio_pull_down = 0ul,
+	nx_gpio_pull_up = 1ul,
+	nx_gpio_pull_off = 2ul
+};
+
+int nx_gpio_initialize(void);
+u32 nx_gpio_get_number_of_module(void);
+u32 nx_gpio_get_size_of_register_set(void);
+void nx_gpio_set_base_address(u32 module_index, void *base_address);
+void *nx_gpio_get_base_address(u32 module_index);
+int nx_gpio_open_module(u32 module_index);
+int nx_gpio_close_module(u32 module_index);
+int nx_gpio_check_busy(u32 module_index);
+void nx_gpio_set_detect_enable(u32 module_index, u32 bit_number,
+			       int detect_enb);
+void nx_gpio_set_pad_function(u32 module_index, u32 bit_number, u32 padfunc);
+void nx_gpio_set_pad_function32(u32 module_index, u32 msbvalue, u32 lsbvalue);
+int nx_gpio_get_pad_function(u32 module_index, u32 bit_number);
+void nx_gpio_set_output_enable(u32 module_index, u32 bit_number,
+			       int output_enb);
+int nx_gpio_get_detect_enable(u32 module_index, u32 bit_number);
+u32 nx_gpio_get_detect_enable32(u32 module_index);
+void nx_gpio_set_detect_enable(u32 module_index, u32 bit_number,
+			       int detect_enb);
+void nx_gpio_set_detect_enable32(u32 module_index, u32 enable_flag);
+int nx_gpio_get_output_enable(u32 module_index, u32 bit_number);
+void nx_gpio_set_output_enable32(u32 module_index, int output_enb);
+u32 nx_gpio_get_output_enable32(u32 module_index);
+void nx_gpio_set_output_value(u32 module_index, u32 bit_number, int value);
+int nx_gpio_get_output_value(u32 module_index, u32 bit_number);
+void nx_gpio_set_output_value32(u32 module_index, u32 value);
+u32 nx_gpio_get_output_value32(u32 module_index);
+int nx_gpio_get_input_value(u32 module_index, u32 bit_number);
+void nx_gpio_set_pull_select(u32 module_index, u32 bit_number, int enable);
+void nx_gpio_set_pull_select32(u32 module_index, u32 value);
+int nx_gpio_get_pull_select(u32 module_index, u32 bit_number);
+u32 nx_gpio_get_pull_select32(u32 module_index);
+void nx_gpio_set_pull_mode(u32 module_index, u32 bit_number, u32 mode);
+void nx_gpio_set_fast_slew(u32 module_index, u32 bit_number, int enable);
+void nx_gpio_set_drive_strength_disable_default(u32 module_index,
+						u32 bit_number, int enable);
+void nx_gpio_set_drive_strength_disable_default(u32 module_index,
+						u32 bit_number, int enable);
+void nx_gpio_set_drive_strength(u32 module_index, u32 bit_number,
+				u32 drvstrength);
+void nx_gpio_set_drive_strength_disable_default(u32 module_index,
+						u32 bit_number, int enable);
+u32 nx_gpio_get_drive_strength(u32 module_index, u32 bit_number);
+#endif
diff --git a/arch/arm/mach-nexell/include/mach/reset.h b/arch/arm/mach-nexell/include/mach/reset.h
new file mode 100644
index 0000000..e1301d4
--- /dev/null
+++ b/arch/arm/mach-nexell/include/mach/reset.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0+
+ *
+ * (C) Copyright 2016 Nexell
+ * Youngbok, Park <ybpark@nexell.co.kr>
+ */
+
+#ifndef __NEXELL_RESET__
+#define __NEXELL_RESET__
+
+#define NUMBER_OF_RESET_MODULE_PIN      69
+
+enum rstcon {
+	RSTCON_ASSERT	= 0UL,
+	RSTCON_NEGATE	= 1UL
+};
+
+void nx_rstcon_setrst(u32 rstindex, enum rstcon status);
+
+#endif /* __NEXELL_RESET__ */
diff --git a/arch/arm/mach-nexell/include/mach/sec_reg.h b/arch/arm/mach-nexell/include/mach/sec_reg.h
new file mode 100644
index 0000000..e3ae5ac
--- /dev/null
+++ b/arch/arm/mach-nexell/include/mach/sec_reg.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0+
+ *
+ * (C) Copyright 2016 Nexell
+ * Youngbok, Park <park@nexell.co.kr>
+ */
+
+#define NEXELL_L2C_SEC_ID	0
+#define NEXELL_MALI_SEC_ID	2
+#define NEXELL_MIPI_SEC_ID	4
+#define NEXELL_TOFF_SEC_ID	6
+
+int write_sec_reg_by_id(void __iomem *reg, int val, int id);
+int read_sec_reg_by_id(void __iomem *reg, int id);
+int read_sec_reg(void __iomem *reg);
+int write_sec_reg(void __iomem *reg, int val);
diff --git a/arch/arm/mach-nexell/include/mach/tieoff.h b/arch/arm/mach-nexell/include/mach/tieoff.h
new file mode 100644
index 0000000..70e9652
--- /dev/null
+++ b/arch/arm/mach-nexell/include/mach/tieoff.h
@@ -0,0 +1,423 @@
+/* SPDX-License-Identifier: GPL-2.0+
+ *
+ * (C) Copyright 2016 Nexell
+ * Youngbok, Park <park@nexell.co.kr>
+ */
+
+#ifndef _NEXELL_TIEOFF_H
+#define _NEXELL_TIEOFF_H
+
+void nx_tieoff_set(u32 tieoff_index, u32 tieoff_value);
+u32 nx_tieoff_get(u32 tieoff_index);
+
+#if defined(CONFIG_ARCH_S5P4418)
+#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_CLAMPCOREOUT	((1 << 16) | 0)
+#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_CLAMPCPU0	((1 << 16) | 1)
+#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_CLAMPCPU1	((1 << 16) | 2)
+#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_CLAMPCPU2	((1 << 16) | 3)
+#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_CLAMPCPU3	((1 << 16) | 4)
+#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_COREPWRDOWN	((1 << 16) | 5)
+#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_CPU0PWRDOWN	((1 << 16) | 6)
+#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_CPU1PWRDOWN	((1 << 16) | 7)
+#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_CPU2PWRDOWN	((1 << 16) | 8)
+#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_CPU3PWRDOWN	((1 << 16) | 9)
+#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_L2_CFGENDIAN	((1 << 16) | 10)
+#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_L1EMAS		((1 << 16) | 11)
+#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_L2RET1N_0	((1 << 16) | 12)
+#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_L2RET1N_1	((1 << 16) | 13)
+#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_L2PGEN_0	((1 << 16) | 14)
+#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_L2PGEN_1	((1 << 16) | 15)
+#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_CLAMPL2_0	((1 << 16) | 16)
+#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_CLAMPL2_1	((1 << 16) | 17)
+#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_VINITHI	((4 << 16) | 18)
+#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_L2EMA		((3 << 16) | 22)
+#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_TEINIT		((4 << 16) | 25)
+#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_L1EMAW		((2 << 16) | 29)
+#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_L2EMAW		((2 << 16) | 32)
+#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_L1EMA		((3 << 16) | 34)
+#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_CPUCLKOFF	((4 << 16) | 37)
+#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_PWRCTLI0	((2 << 16) | 41)
+#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_PWRCTLI1	((2 << 16) | 43)
+#define NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_PWRCTLI2	((2 << 16) | 45)
+#elif defined(CONFIG_ARCH_S5P6818)
+#define NX_TIEOFF_MMC_8BIT				((1 << 16) | 5)
+#endif
+#define NX_TIEOFF_AXISRAM0_i_TIE_ra2w_EMAA		((3 << 16) | 47)
+#define NX_TIEOFF_AXISRAM0_i_TIE_ra2w_EMAB		((3 << 16) | 50)
+#define NX_TIEOFF_AXISRAM0_i_TIE_ra2w_EMAWA		((2 << 16) | 53)
+#define NX_TIEOFF_AXISRAM0_i_TIE_ra2w_EMAWB		((2 << 16) | 55)
+#define NX_TIEOFF_AXISRAM0_i_nPowerDown			((1 << 16) | 57)
+#define NX_TIEOFF_AXISRAM0_i_nSleep			((1 << 16) | 58)
+#define NX_TIEOFF_CAN0_i_TIE_rf1_EMA			((3 << 16) | 59)
+#define NX_TIEOFF_CAN0_i_TIE_rf1_EMAW			((2 << 16) | 62)
+#define NX_TIEOFF_CAN0_i_nPowerDown			((1 << 16) | 64)
+#define NX_TIEOFF_CAN0_i_nSleep				((1 << 16) | 65)
+#define NX_TIEOFF_CAN1_i_TIE_rf1_EMA			((3 << 16) | 66)
+#define NX_TIEOFF_CAN1_i_TIE_rf1_EMAW			((2 << 16) | 69)
+#define NX_TIEOFF_CAN1_i_nPowerDown			((1 << 16) | 71)
+#define NX_TIEOFF_CAN1_i_nSleep				((1 << 16) | 72)
+#define NX_TIEOFF_DEINTERLACE0_i_NX_RF1_EMA		((3 << 16) | 73)
+#define NX_TIEOFF_DEINTERLACE0_i_NX_RF1_EMAW		((2 << 16) | 76)
+#define NX_TIEOFF_DEINTERLACE0_i_NX_RF2_EMAA		((3 << 16) | 78)
+#define NX_TIEOFF_DEINTERLACE0_i_NX_RF2_EMAB		((3 << 16) | 81)
+#define NX_TIEOFF_DEINTERLACE0_i_NX_RF2W_EMAA		((3 << 16) | 84)
+#define NX_TIEOFF_DEINTERLACE0_i_NX_RF2W_EMAB		((3 << 16) | 87)
+#define NX_TIEOFF_DISPLAYTOP0_i_ResConv_nPowerDown	((1 << 16) | 90)
+#define NX_TIEOFF_DISPLAYTOP0_i_ResConv_nSleep		((1 << 16) | 91)
+#define NX_TIEOFF_DISPLAYTOP0_i_HDMI_nPowerDown		((2 << 16) | 92)
+#define NX_TIEOFF_DISPLAYTOP0_i_HDMI_nSleep		((2 << 16) | 94)
+#define NX_TIEOFF_DISPLAYTOP0_i_HDMI_PHY_REFCLK_SEL	((1 << 16) | 96)
+#define NX_TIEOFF_DISPLAYTOP0_i_TIEOFF_SPSRAM_EMA	((3 << 16) | 97)
+#define NX_TIEOFF_DISPLAYTOP0_i_TIEOFF_SPSRAM_EMAW	((2 << 16) | 100)
+#define NX_TIEOFF_DISPLAYTOP0_i_TIEOFF_DPSRAM_1R1W_EMAA ((3 << 16) | 102)
+#define NX_TIEOFF_DISPLAYTOP0_i_TIEOFF_DPSRAM_1R1W_EMAB ((3 << 16) | 105)
+#define NX_TIEOFF_DISPLAYTOP0_i_TIEOFF_DPSRAM_EMAA	((3 << 16) | 108)
+#define NX_TIEOFF_DISPLAYTOP0_i_TIEOFF_DPSRAM_EMAB	((3 << 16) | 111)
+#define NX_TIEOFF_DISPLAYTOP0_i_TIEOFF_DPSRAM_EMAWA	((2 << 16) | 114)
+#define NX_TIEOFF_DISPLAYTOP0_i_TIEOFF_DPSRAM_EMAWB	((2 << 16) | 116)
+#define NX_TIEOFF_MCUSTOP0_i_vrom_EMA			((3 << 16) | 118)
+#define NX_TIEOFF_DREX0_CKE_INIT			((1 << 16) | 121)
+#define NX_TIEOFF_DREX0_CA_SWAP				((1 << 16) | 122)
+#define NX_TIEOFF_DREX0_CSYSREQ				((1 << 16) | 123)
+#define NX_TIEOFF_DREX0_PAUSE_REQ			((1 << 16) | 124)
+#define NX_TIEOFF_DREX0_PEREV_TRIGGER			((1 << 16) | 125)
+#define NX_TIEOFF_DREX0_CTRL_HCKE			((1 << 16) | 126)
+#define NX_TIEOFF_DREX0_DFI_RESET_N_P0			((1 << 16) | 127)
+#define NX_TIEOFF_DREX0_DFI_RESET_N_P1			((1 << 16) | 128)
+#define NX_TIEOFF_MIPI0_NX_DPSRAM_1R1W_EMAA		((3 << 16) | 129)
+#define NX_TIEOFF_MIPI0_NX_DPSRAM_1R1W_EMAB		((3 << 16) | 132)
+#define NX_TIEOFF_MIPI0_i_NX_NPOWERDOWN			((4 << 16) | 135)
+#define NX_TIEOFF_MIPI0_i_NX_NSLEEP			((4 << 16) | 139)
+#define NX_TIEOFF_SCALER0_i_NX_EMA			((3 << 16) | 143)
+#define NX_TIEOFF_SCALER0_i_NX_EMAW			((2 << 16) | 146)
+#define NX_TIEOFF_UART0_USESMC				((1 << 16) | 148)
+#define NX_TIEOFF_UART0_SMCTXENB			((1 << 16) | 149)
+#define NX_TIEOFF_UART0_SMCRXENB			((1 << 16) | 150)
+#define NX_TIEOFF_UART1_USESMC				((1 << 16) | 151)
+#define NX_TIEOFF_UART1_SMCTXENB			((1 << 16) | 152)
+#define NX_TIEOFF_UART1_SMCRXENB			((1 << 16) | 153)
+#define NX_TIEOFF_UART2_USESMC				((1 << 16) | 154)
+#define NX_TIEOFF_UART2_SMCTXENB			((1 << 16) | 155)
+#define NX_TIEOFF_UART2_SMCRXENB			((1 << 16) | 156)
+#define NX_TIEOFF_UART3_USESMC				((1 << 16) | 157)
+#define NX_TIEOFF_UART3_SMCTXENB			((1 << 16) | 158)
+#define NX_TIEOFF_UART3_SMCRXENB			((1 << 16) | 159)
+#define NX_TIEOFF_UART4_USESMC				((1 << 16) | 160)
+#define NX_TIEOFF_UART4_SMCTXENB			((1 << 16) | 161)
+#define NX_TIEOFF_UART4_SMCRXENB			((1 << 16) | 162)
+#define NX_TIEOFF_UART5_USESMC				((1 << 16) | 163)
+#define NX_TIEOFF_UART5_SMCTXENB			((1 << 16) | 164)
+#define NX_TIEOFF_UART5_SMCRXENB			((1 << 16) | 165)
+#define NX_TIEOFF_USB20HOST0_i_nPowerDown		((1 << 16) | 166)
+#define NX_TIEOFF_USB20HOST0_i_nSleep			((1 << 16) | 167)
+#define NX_TIEOFF_USB20HOST0_i_NX_RF1_EMA		((3 << 16) | 168)
+#define NX_TIEOFF_USB20HOST0_i_NX_RF1_EMAW		((2 << 16) | 171)
+#define NX_TIEOFF_USB20HOST0_sys_interrupt_i		((1 << 16) | 173)
+#define NX_TIEOFF_USB20HOST0_i_hsic_en			((3 << 16) | 174)
+#define NX_TIEOFF_USB20HOST0_i_nResetSync		((1 << 16) | 177)
+#define NX_TIEOFF_USB20HOST0_i_nResetSync_ohci		((1 << 16) | 178)
+#define NX_TIEOFF_USB20HOST0_i_nAuxWellResetSync	((1 << 16) | 179)
+#define NX_TIEOFF_USB20HOST0_i_nHostPhyResetSync	((1 << 16) | 180)
+#define NX_TIEOFF_USB20HOST0_i_nHostUtmiResetSync	((1 << 16) | 181)
+#define NX_TIEOFF_USB20HOST0_i_nHostHsicResetSync	((1 << 16) | 182)
+#define NX_TIEOFF_USB20HOST0_i_HSIC_FREE_CLOCK_ENB	((1 << 16) | 183)
+#define NX_TIEOFF_USB20HOST0_i_HSIC_480M_FROM_OTG_PHY	((1 << 16) | 184)
+#define NX_TIEOFF_USB20HOST0_ss_word_if_enb_i		((1 << 16) | 185)
+#define NX_TIEOFF_USB20HOST0_ss_word_if_i		((1 << 16) | 186)
+#define NX_TIEOFF_USB20HOST0_ss_utmi_backward_enb_i	((1 << 16) | 187)
+#define NX_TIEOFF_USB20HOST0_ss_resume_utmi_pls_dis_i	((1 << 16) | 188)
+#define NX_TIEOFF_USB20HOST0_phy_vstatus_0_i		((3 << 16) | 189)
+#define NX_TIEOFF_USB20HOST0_phy_vstatus_1_i		((3 << 16) | 192)
+#define NX_TIEOFF_USB20HOST0_phy_vstatus_2_i		((3 << 16) | 195)
+#define NX_TIEOFF_USB20HOST0_phy_vstatus_3_i		((3 << 16) | 198)
+#define NX_TIEOFF_USB20HOST0_phy_vstatus_4_i		((3 << 16) | 201)
+#define NX_TIEOFF_USB20HOST0_phy_vstatus_5_i		((3 << 16) | 204)
+#define NX_TIEOFF_USB20HOST0_phy_vstatus_6_i		((3 << 16) | 207)
+#define NX_TIEOFF_USB20HOST0_phy_vstatus_7_i		((3 << 16) | 210)
+#define NX_TIEOFF_USB20HOST0_ss_power_state_valid_i	((1 << 16) | 213)
+#define NX_TIEOFF_USB20HOST0_ss_nxt_power_state_valid_i ((1 << 16) | 214)
+#define NX_TIEOFF_USB20HOST0_ss_power_state_i		((2 << 16) | 215)
+#define NX_TIEOFF_USB20HOST0_ss_next_power_state_i	((2 << 16) | 217)
+#define NX_TIEOFF_USB20HOST0_app_prt_ovrcur_i		((3 << 16) | 219)
+#define NX_TIEOFF_USB20HOST0_ss_simulation_mode_i	((1 << 16) | 222)
+#define NX_TIEOFF_USB20HOST0_ss_fladj_val_host_i	((6 << 16) | 224)
+#define NX_TIEOFF_USB20HOST0_ss_fladj_val_5_i		((3 << 16) | 230)
+#define NX_TIEOFF_USB20HOST0_ss_fladj_val_4_i		((3 << 16) | 233)
+#define NX_TIEOFF_USB20HOST0_ss_fladj_val_3_i		((3 << 16) | 236)
+#define NX_TIEOFF_USB20HOST0_ss_fladj_val_2_i		((3 << 16) | 239)
+#define NX_TIEOFF_USB20HOST0_ss_fladj_val_1_i		((3 << 16) | 242)
+#define NX_TIEOFF_USB20HOST0_ss_fladj_val_0_i		((3 << 16) | 245)
+#define NX_TIEOFF_USB20HOST0_ss_autoppd_on_overcur_en_i ((1 << 16) | 248)
+#define NX_TIEOFF_USB20HOST0_ss_ena_incr16_i		((1 << 16) | 249)
+#define NX_TIEOFF_USB20HOST0_ss_ena_incr8_i		((1 << 16) | 250)
+#define NX_TIEOFF_USB20HOST0_ss_ena_incr4_i		((1 << 16) | 251)
+#define NX_TIEOFF_USB20HOST0_ss_ena_incrx_align_i	((1 << 16) | 252)
+#define NX_TIEOFF_USB20HOST0_i_ohci_0_cntsel_n		((1 << 16) | 253)
+#define NX_TIEOFF_USB20HOST0_ohci_0_app_irq1_i		((1 << 16) | 254)
+#define NX_TIEOFF_USB20HOST0_ohci_0_app_irq12_i		((1 << 16) | 255)
+#define NX_TIEOFF_USB20HOST0_ohci_0_app_io_hit_i	((1 << 16) | 256)
+#define NX_TIEOFF_USB20HOST0_ss_hubsetup_min_i		((1 << 16) | 257)
+#define NX_TIEOFF_USB20HOST0_app_start_clk_i		((1 << 16) | 258)
+#define NX_TIEOFF_USB20HOST0_ohci_susp_lgcy_i		((1 << 16) | 259)
+#define NX_TIEOFF_USB20HOST0_i_SIDDQ			((1 << 16) | 260)
+#define NX_TIEOFF_USB20HOST0_i_VATESTENB		((2 << 16) | 261)
+#define NX_TIEOFF_USB20HOST0_i_POR_ENB			((1 << 16) | 263)
+#define NX_TIEOFF_USB20HOST0_i_POR			((1 << 16) | 264)
+#define NX_TIEOFF_USB20HOST0_i_REFCLKSEL		((2 << 16) | 265)
+#define NX_TIEOFF_USB20HOST0_i_FSEL			((3 << 16) | 267)
+#define NX_TIEOFF_USB20HOST0_i_COMMONONN		((1 << 16) | 270)
+#define NX_TIEOFF_USB20HOST0_i_RESREQIN			((1 << 16) | 271)
+#define NX_TIEOFF_USB20HOST0_i_PORTRESET		((1 << 16) | 272)
+#define NX_TIEOFF_USB20HOST0_i_OTGDISABLE		((1 << 16) | 273)
+#define NX_TIEOFF_USB20HOST0_i_LOOPBACKENB		((1 << 16) | 274)
+#define NX_TIEOFF_USB20HOST0_i_IDPULLUPi		((1 << 16) | 275)
+#define NX_TIEOFF_USB20HOST0_i_DRVVBUS			((1 << 16) | 276)
+#define NX_TIEOFF_USB20HOST0_i_ADPCHRG			((1 << 16) | 277)
+#define NX_TIEOFF_USB20HOST0_i_ADPDISCHRG		((1 << 16) | 278)
+#define NX_TIEOFF_USB20HOST0_i_ADPPRBENB		((1 << 16) | 279)
+#define NX_TIEOFF_USB20HOST0_i_VBUSVLDEXT		((1 << 16) | 280)
+#define NX_TIEOFF_USB20HOST0_i_VBUSVLDEXTSEL		((1 << 16) | 281)
+#define NX_TIEOFF_USB20HOST0_i_DPPULLDOWN		((1 << 16) | 282)
+#define NX_TIEOFF_USB20HOST0_i_DMPULLDOWN		((1 << 16) | 283)
+#define NX_TIEOFF_USB20HOST0_i_SUSPENDM_ENB		((1 << 16) | 284)
+#define NX_TIEOFF_USB20HOST0_i_SUSPENDM			((1 << 16) | 285)
+#define NX_TIEOFF_USB20HOST0_i_SLEEPM_ENB		((1 << 16) | 286)
+#define NX_TIEOFF_USB20HOST0_i_SLEEPM			((1 << 16) | 287)
+#define NX_TIEOFF_USB20HOST0_i_OPMODE_ENB		((1 << 16) | 288)
+#define NX_TIEOFF_USB20HOST0_i_OPMODE			((2 << 16) | 289)
+#define NX_TIEOFF_USB20HOST0_i_TERMSEL_ENB		((1 << 16) | 291)
+#define NX_TIEOFF_USB20HOST0_i_TERMSEL			((1 << 16) | 292)
+#define NX_TIEOFF_USB20HOST0_i_XCVRSEL_ENB		((1 << 16) | 293)
+#define NX_TIEOFF_USB20HOST0_i_XCVRSEL			((2 << 16) | 294)
+#define NX_TIEOFF_USB20HOST0_i_WORDINTERFACE_ENB	((1 << 16) | 296)
+#define NX_TIEOFF_USB20HOST0_i_WORDINTERFACE		((1 << 16) | 297)
+#define NX_TIEOFF_USB20HOST0_i_TXBITSTUFFEN		((1 << 16) | 298)
+#define NX_TIEOFF_USB20HOST0_i_TXBITSTUFFENH		((1 << 16) | 299)
+#define NX_TIEOFF_USB20HOST0_i_BYPASSDPDATA		((1 << 16) | 300)
+#define NX_TIEOFF_USB20HOST0_i_BYPASSDMDATA		((1 << 16) | 301)
+#define NX_TIEOFF_USB20HOST0_i_BYPASSDPEN		((1 << 16) | 302)
+#define NX_TIEOFF_USB20HOST0_i_BYPASSDMEN		((1 << 16) | 303)
+#define NX_TIEOFF_USB20HOST0_i_BYPASSSEL		((1 << 16) | 304)
+#define NX_TIEOFF_USB20HOST0_i_COMPDISTUNE		((3 << 16) | 305)
+#define NX_TIEOFF_USB20HOST0_i_SQRXTUNE			((3 << 16) | 308)
+#define NX_TIEOFF_USB20HOST0_i_OTGTUNE			((3 << 16) | 311)
+#define NX_TIEOFF_USB20HOST0_i_TXHSXVTUNE		((2 << 16) | 314)
+#define NX_TIEOFF_USB20HOST0_i_TXFSLSTUNE		((4 << 16) | 316)
+#define NX_TIEOFF_USB20HOST0_i_TXVREFTUNE		((4 << 16) | 320)
+#define NX_TIEOFF_USB20HOST0_i_TXRISETUNE		((2 << 16) | 324)
+#define NX_TIEOFF_USB20HOST0_i_TXRESTUNE		((2 << 16) | 326)
+#define NX_TIEOFF_USB20HOST0_i_TXPREEMPAMPTUNE		((2 << 16) | 328)
+#define NX_TIEOFF_USB20HOST0_i_TXPREEMPPULSETUNE	((1 << 16) | 330)
+#define NX_TIEOFF_USB20HOST0_i_CHRGSEL			((1 << 16) | 331)
+#define NX_TIEOFF_USB20HOST0_i_VDATDETENB		((1 << 16) | 332)
+#define NX_TIEOFF_USB20HOST0_i_VDATSRCENB		((1 << 16) | 333)
+#define NX_TIEOFF_USB20HOST0_i_DCDENB			((1 << 16) | 334)
+#define NX_TIEOFF_USB20HOST0_i_ACAENB			((1 << 16) | 335)
+#define NX_TIEOFF_USB20HOST0_i_HSIC_MSTRXCVR		((1 << 16) | 336)
+#define NX_TIEOFF_USB20HOST0_i_HSIC_SIDDQ		((1 << 16) | 337)
+#define NX_TIEOFF_USB20HOST0_i_HSIC_POR_ENB		((1 << 16) | 338)
+#define NX_TIEOFF_USB20HOST0_i_HSIC_POR			((1 << 16) | 339)
+#define NX_TIEOFF_USB20HOST0_i_HSIC_REFCLKDIV		((7 << 16) | 340)
+#define NX_TIEOFF_USB20HOST0_i_HSIC_REFCLKSEL		((2 << 16) | 347)
+#define NX_TIEOFF_USB20HOST0_i_HSIC_COMMONONN		((1 << 16) | 349)
+#define NX_TIEOFF_USB20HOST0_i_HSIC_PORTRESET		((1 << 16) | 350)
+#define NX_TIEOFF_USB20HOST0_i_HSIC_LOOPBACKENB		((1 << 16) | 351)
+#define NX_TIEOFF_USB20HOST0_i_HSIC_DPPULLDOWN		((1 << 16) | 352)
+#define NX_TIEOFF_USB20HOST0_i_HSIC_DMPULLDOWN		((1 << 16) | 353)
+#define NX_TIEOFF_USB20HOST0_i_HSIC_SUSPENDM_ENB	((1 << 16) | 354)
+#define NX_TIEOFF_USB20HOST0_i_HSIC_SUSPENDM		((1 << 16) | 355)
+#define NX_TIEOFF_USB20HOST0_i_HSIC_SLEEPM_ENB		((1 << 16) | 356)
+#define NX_TIEOFF_USB20HOST0_i_HSIC_SLEEPM		((1 << 16) | 357)
+#define NX_TIEOFF_USB20HOST0_i_HSIC_MSTRXOPU		((1 << 16) | 358)
+#define NX_TIEOFF_USB20HOST0_i_HSIC_OPMODE_ENB		((1 << 16) | 359)
+#define NX_TIEOFF_USB20HOST0_i_HSIC_OPMODE		((2 << 16) | 360)
+#define NX_TIEOFF_USB20HOST0_i_HSIC_XCVRSELECT_ENB	((1 << 16) | 362)
+#define NX_TIEOFF_USB20HOST0_i_HSIC_XCVRSELECT		((1 << 16) | 363)
+#define NX_TIEOFF_USB20HOST0_i_HSIC_WORDINTERFACE_ENB	((1 << 16) | 364)
+#define NX_TIEOFF_USB20HOST0_i_HSIC_WORDINTERFACE	((1 << 16) | 365)
+#define NX_TIEOFF_USB20HOST0_i_HSIC_TXBITSTUFFEN	((1 << 16) | 366)
+#define NX_TIEOFF_USB20HOST0_i_HSIC_TXBITSTUFFENH	((1 << 16) | 367)
+#define NX_TIEOFF_USB20HOST0_i_HSIC_TXRPUTUNE		((2 << 16) | 368)
+#define NX_TIEOFF_USB20HOST0_i_HSIC_TXRPDTUNE		((2 << 16) | 370)
+#define NX_TIEOFF_USB20HOST0_i_HSIC_TXSRTUNE		((4 << 16) | 372)
+#define NX_TIEOFF_USB20OTG0_i_nPowerDown		((1 << 16) | 376)
+#define NX_TIEOFF_USB20OTG0_i_nSleep			((1 << 16) | 377)
+#define NX_TIEOFF_USB20OTG0_i_NX_RF1_EMA		((3 << 16) | 378)
+#define NX_TIEOFF_USB20OTG0_i_NX_RF1_EMAW		((2 << 16) | 381)
+#define NX_TIEOFF_USB20OTG0_i_ss_scaledown_mode		((2 << 16) | 384)
+#define NX_TIEOFF_USB20OTG0_i_gp_in			((16 << 16) | 386)
+#define NX_TIEOFF_USB20OTG0_i_sof_count			((14 << 16) | 402)
+#define NX_TIEOFF_USB20OTG0_i_sys_dma_done		((1 << 16) | 416)
+#define NX_TIEOFF_USB20OTG0_i_if_select_hsic		((1 << 16) | 417)
+#define NX_TIEOFF_USB20OTG0_i_nResetSync		((1 << 16) | 418)
+#define NX_TIEOFF_USB20OTG0_i_nUtmiResetSync		((1 << 16) | 419)
+#define NX_TIEOFF_USB20OTG0_i_SIDDQ			((1 << 16) | 420)
+#define NX_TIEOFF_USB20OTG0_i_VATESTENB			((2 << 16) | 421)
+#define NX_TIEOFF_USB20OTG0_i_POR_ENB			((1 << 16) | 423)
+#define NX_TIEOFF_USB20OTG0_i_POR			((1 << 16) | 424)
+#define NX_TIEOFF_USB20OTG0_i_REFCLKSEL			((2 << 16) | 425)
+#define NX_TIEOFF_USB20OTG0_i_FSEL			((3 << 16) | 427)
+#define NX_TIEOFF_USB20OTG0_i_COMMONONN			((1 << 16) | 430)
+#define NX_TIEOFF_USB20OTG0_i_RESREQIN			((1 << 16) | 431)
+#define NX_TIEOFF_USB20OTG0_i_PORTRESET			((1 << 16) | 432)
+#define NX_TIEOFF_USB20OTG0_i_OTGDISABLE		((1 << 16) | 433)
+#define NX_TIEOFF_USB20OTG0_i_LOOPBACKENB		((1 << 16) | 434)
+#define NX_TIEOFF_USB20OTG0_i_IDPULLUP			((1 << 16) | 435)
+#define NX_TIEOFF_USB20OTG0_i_DRVVBUS			((1 << 16) | 436)
+#define NX_TIEOFF_USB20OTG0_i_ADPCHRG			((1 << 16) | 437)
+#define NX_TIEOFF_USB20OTG0_i_ADPDISCHRG		((1 << 16) | 438)
+#define NX_TIEOFF_USB20OTG0_i_ADPPRBENB			((1 << 16) | 439)
+#define NX_TIEOFF_USB20OTG0_i_VBUSVLDEXT		((1 << 16) | 440)
+#define NX_TIEOFF_USB20OTG0_i_VBUSVLDEXTSEL		((1 << 16) | 441)
+#define NX_TIEOFF_USB20OTG0_i_DPPULLDOWN		((1 << 16) | 442)
+#define NX_TIEOFF_USB20OTG0_i_DMPULLDOWN		((1 << 16) | 443)
+#define NX_TIEOFF_USB20OTG0_i_SUSPENDM_ENB		((1 << 16) | 444)
+#define NX_TIEOFF_USB20OTG0_i_SUSPENDM			((1 << 16) | 445)
+#define NX_TIEOFF_USB20OTG0_i_SLEEPM_ENB		((1 << 16) | 446)
+#define NX_TIEOFF_USB20OTG0_i_SLEEPM			((1 << 16) | 447)
+#define NX_TIEOFF_USB20OTG0_i_OPMODE_ENB		((1 << 16) | 448)
+#define NX_TIEOFF_USB20OTG0_i_OPMODE			((2 << 16) | 449)
+#define NX_TIEOFF_USB20OTG0_i_TERMSEL_ENB		((1 << 16) | 451)
+#define NX_TIEOFF_USB20OTG0_i_TERMSEL			((1 << 16) | 452)
+#define NX_TIEOFF_USB20OTG0_i_XCVRSEL_ENB		((1 << 16) | 453)
+#define NX_TIEOFF_USB20OTG0_i_XCVRSEL			((2 << 16) | 454)
+#define NX_TIEOFF_USB20OTG0_i_WORDINTERFACE_ENB		((1 << 16) | 456)
+#define NX_TIEOFF_USB20OTG0_i_WORDINTERFACE		((1 << 16) | 457)
+#define NX_TIEOFF_USB20OTG0_i_TXBITSTUFFEN		((1 << 16) | 458)
+#define NX_TIEOFF_USB20OTG0_i_TXBITSTUFFENH		((1 << 16) | 459)
+#define NX_TIEOFF_USB20OTG0_i_BYPASSDPDATA		((1 << 16) | 460)
+#define NX_TIEOFF_USB20OTG0_i_BYPASSDMDATA		((1 << 16) | 461)
+#define NX_TIEOFF_USB20OTG0_i_BYPASSDPEN		((1 << 16) | 462)
+#define NX_TIEOFF_USB20OTG0_i_BYPASSDMEN		((1 << 16) | 463)
+#define NX_TIEOFF_USB20OTG0_i_BYPASSSEL			((1 << 16) | 464)
+#define NX_TIEOFF_USB20OTG0_i_COMPDISTUNE		((3 << 16) | 465)
+#define NX_TIEOFF_USB20OTG0_i_SQRXTUNE			((3 << 16) | 468)
+#define NX_TIEOFF_USB20OTG0_i_OTGTUNE			((3 << 16) | 471)
+#define NX_TIEOFF_USB20OTG0_i_TXHSXVTUNE		((2 << 16) | 474)
+#define NX_TIEOFF_USB20OTG0_i_TXFSLSTUNE		((4 << 16) | 476)
+#define NX_TIEOFF_USB20OTG0_i_TXVREFTUNE		((4 << 16) | 480)
+#define NX_TIEOFF_USB20OTG0_i_TXRISETUNE		((2 << 16) | 484)
+#define NX_TIEOFF_USB20OTG0_i_TXRESTUNE			((2 << 16) | 486)
+#define NX_TIEOFF_USB20OTG0_i_TXPREEMPAMPTUNE		((2 << 16) | 488)
+#define NX_TIEOFF_USB20OTG0_i_TXPREEMPPULSETUNE		((1 << 16) | 490)
+#define NX_TIEOFF_USB20OTG0_i_CHRGSEL			((1 << 16) | 491)
+#define NX_TIEOFF_USB20OTG0_i_VDATDETENB		((1 << 16) | 492)
+#define NX_TIEOFF_USB20OTG0_i_VDATSRCENB		((1 << 16) | 493)
+#define NX_TIEOFF_USB20OTG0_i_DCDENB			((1 << 16) | 494)
+#define NX_TIEOFF_USB20OTG0_i_ACAENB			((1 << 16) | 495)
+#define NX_TIEOFF_USB20OTG0_i_IDPULLUP_ENB		((1 << 16) | 496)
+#define NX_TIEOFF_USB20OTG0_i_DPPULLDOWN_ENB		((1 << 16) | 497)
+#define NX_TIEOFF_USB20OTG0_i_DMPULLDOWN_ENB		((1 << 16) | 498)
+#define NX_TIEOFF_USB20OTG0_i_DRVVBUS_ENB		((1 << 16) | 499)
+#define NX_TIEOFF_USB20OTG0_i_LPMClkMuxCntrl		((1 << 16) | 500)
+#define NX_TIEOFF_USB20OTG0_i_GLITCHLESSMUXCntrl	((1 << 16) | 501)
+#define NX_TIEOFF_CODA9600_i_nPWRDN00			((4 << 16) | 502)
+#define NX_TIEOFF_CODA9600_i_nSLEEP00			((4 << 16) | 506)
+#define NX_TIEOFF_CODA9600_i_nPWRDN01			((8 << 16) | 512)
+#define NX_TIEOFF_CODA9600_i_nSLEEP01			((8 << 16) | 520)
+#define NX_TIEOFF_CODA9600_i_nPWRDN02			((10 << 16) | 528)
+#define NX_TIEOFF_CODA9600_i_nSLEEP02			((10 << 16) | 544)
+#define NX_TIEOFF_CODA9600_i_nPWRDN03			((2 << 16) | 554)
+#define NX_TIEOFF_CODA9600_i_nSLEEP03			((2 << 16) | 556)
+#define NX_TIEOFF_CODA9600_i_nPWRDN04			((8 << 16) | 558)
+#define NX_TIEOFF_CODA9600_i_nSLEEP04			((8 << 16) | 566)
+#define NX_TIEOFF_CODA9600_i_nPWRDN05			((3 << 16) | 576)
+#define NX_TIEOFF_CODA9600_i_nSLEEP05			((3 << 16) | 579)
+#define NX_TIEOFF_CODA9600_i_nPWRDN06			((7 << 16) | 582)
+#define NX_TIEOFF_CODA9600_i_nSLEEP06			((7 << 16) | 589)
+#define NX_TIEOFF_CODA9600_i_nPWRDN07			((12 << 16) | 596)
+#define NX_TIEOFF_CODA9600_i_nSLEEP07			((12 << 16) | 608)
+#define NX_TIEOFF_CODA9600_i_nPWRDN08			((1 << 16) | 620)
+#define NX_TIEOFF_CODA9600_i_nSLEEP08			((1 << 16) | 621)
+#define NX_TIEOFF_CODA9600_i_nPWRDN09			((2 << 16) | 622)
+#define NX_TIEOFF_CODA9600_i_nSLEEP09			((2 << 16) | 624)
+#define NX_TIEOFF_CODA9600_i_nPWRDN10			((10 << 16) | 626)
+#define NX_TIEOFF_CODA9600_i_nSLEEP10			((10 << 16) | 640)
+#define NX_TIEOFF_CODA9600_i_nPWRDN11			((1 << 16) | 650)
+#define NX_TIEOFF_CODA9600_i_nSLEEP11			((1 << 16) | 651)
+#define NX_TIEOFF_CODA9600_i_TIE_rf2_EMAA		((3 << 16) | 652)
+#define NX_TIEOFF_CODA9600_i_TIE_rf2_EMAB		((3 << 16) | 655)
+#define NX_TIEOFF_CODA9600_i_TIE_rf2w_EMAA		((3 << 16) | 658)
+#define NX_TIEOFF_CODA9600_i_TIE_rf2w_EMAB		((3 << 16) | 661)
+#define NX_TIEOFF_CODA9600_i_TIE_ra2_EMAA		((3 << 16) | 664)
+#define NX_TIEOFF_CODA9600_i_TIE_ra2_EMAB		((3 << 16) | 667)
+#define NX_TIEOFF_CODA9600_i_TIE_ra2_EMAWA		((2 << 16) | 670)
+#define NX_TIEOFF_CODA9600_i_TIE_ra2_EMAWB		((2 << 16) | 672)
+#define NX_TIEOFF_CODA9600_i_TIE_ra2w_EMAA		((3 << 16) | 674)
+#define NX_TIEOFF_CODA9600_i_TIE_ra2w_EMAB		((3 << 16) | 677)
+#define NX_TIEOFF_CODA9600_i_TIE_ra2w_EMAWA		((2 << 16) | 680)
+#define NX_TIEOFF_CODA9600_i_TIE_ra2w_EMAWB		((2 << 16) | 682)
+#define NX_TIEOFF_CODA9600_i_TIE_rf1_EMA		((3 << 16) | 684)
+#define NX_TIEOFF_CODA9600_i_TIE_rf1_EMAW		((2 << 16) | 687)
+#define NX_TIEOFF_CODA9600_i_TIE_rf1w_EMA		((3 << 16) | 689)
+#define NX_TIEOFF_CODA9600_i_TIE_rf1w_EMAW		((2 << 16) | 692)
+#define NX_TIEOFF_DWC_GMAC0_sbd_flowctrl_i		((1 << 16) | 694)
+#define NX_TIEOFF_DWC_GMAC0_phy_intf_sel_i		((3 << 16) | 695)
+#define NX_TIEOFF_DWC_GMAC0_i_NX_RF2_EMAA		((3 << 16) | 698)
+#define NX_TIEOFF_DWC_GMAC0_i_NX_RF2_EMAB		((3 << 16) | 701)
+#define NX_TIEOFF_MALI4000_NX_DPSRAM_1R1W_EMAA		((3 << 16) | 704)
+#define NX_TIEOFF_MALI4000_NX_DPSRAM_1R1W_EMAB		((3 << 16) | 707)
+#define NX_TIEOFF_MALI4000_NX_SPSRAM_EMA		((3 << 16) | 710)
+#define NX_TIEOFF_MALI4000_NX_SPSRAM_EMAW		((2 << 16) | 713)
+#define NX_TIEOFF_MALI4000_NX_SPSRAM_BW_EMA		((3 << 16) | 715)
+#define NX_TIEOFF_MALI4000_NX_SPSRAM_BW_EMAW		((2 << 16) | 718)
+#define NX_TIEOFF_MALI4000_PWRDNBYPASS			((1 << 16) | 720)
+#define NX_TIEOFF_MALI4000_GP_NX_NPOWERDOWN		((15 << 16) | 721)
+#define NX_TIEOFF_MALI4000_GP_NX_NSLEEP			((15 << 16) | 736)
+#define NX_TIEOFF_MALI4000_L2_NX_NPOWERDOWN		((3 << 16) | 751)
+#define NX_TIEOFF_MALI4000_L2_NX_NSLEEP			((3 << 16) | 754)
+#define NX_TIEOFF_MALI4000_PP0_NX_NPOWERDOWN		((32 << 16) | 768)
+#define NX_TIEOFF_MALI4000_PP0_NX_NSLEEP		((32 << 16) | 800)
+#define NX_TIEOFF_MALI4000_PP1_NX_NPOWERDOWN		((32 << 16) | 832)
+#define NX_TIEOFF_MALI4000_PP1_NX_NSLEEP		((32 << 16) | 864)
+#define NX_TIEOFF_MALI4000_PP2_NX_NPOWERDOWN		((32 << 16) | 896)
+#define NX_TIEOFF_MALI4000_PP2_NX_NSLEEP		((32 << 16) | 928)
+#define NX_TIEOFF_MALI4000_PP3_NX_NPOWERDOWN		((32 << 16) | 960)
+#define NX_TIEOFF_MALI4000_PP3_NX_NSLEEP		((32 << 16) | 992)
+#define NX_TIEOFF_A3BM_AXI_PERI_BUS0_SYNCMODEREQm9	((1 << 16) | 1024)
+#define NX_TIEOFF_A3BM_AXI_PERI_BUS0_SYNCMODEREQm10	((1 << 16) | 1025)
+#define NX_TIEOFF_A3BM_AXI_PERI_BUS0_SYNCMODEREQm16	((1 << 16) | 1026)
+#define NX_TIEOFF_A3BM_AXI_TOP_MASTER_BUS0_REMAP	((2 << 16) | 1027)
+#if defined(CONFIG_ARCH_S5P6818)
+#define NX_TIEOFF_Inst_ARMTOP_SMPEN			((4 << 16) | 2816)
+#define NX_TIEOFF_Inst_ARMTOP_STANBYWFI			((4 << 16) | 2880)
+#define NX_TIEOFF_Inst_ARMTOP_STANBYWFIL2		((1 << 16) | 2884)
+#define NX_TIEOFF_Inst_ARMTOP_DBGNOPWRDWN		((4 << 16) | 2889)
+#define NX_TIEOFF_Inst_ARMTOP_DBGPWRUPREQ		((4 << 16) | 2893)
+#define NX_TIEOFF_Inst_ARMTOP_COREPWRDOWNPRE		((1 << 16) | 2901)
+#define NX_TIEOFF_Inst_ARMTOP_CPU0PWRDOWNPRE		((1 << 16) | 2902)
+#define NX_TIEOFF_Inst_ARMTOP_CPU1PWRDOWNPRE		((1 << 16) | 2903)
+#define NX_TIEOFF_Inst_ARMTOP_CPU2PWRDOWNPRE		((1 << 16) | 2904)
+#define NX_TIEOFF_Inst_ARMTOP_CPU3PWRDOWNPRE		((1 << 16) | 2905)
+#define NX_TIEOFF_Inst_ARMTOP_COREPWRDOWNALL		((1 << 16) | 2906)
+#define NX_TIEOFF_Inst_ARMTOP_CPU0PWRDOWNALL		((1 << 16) | 2907)
+#define NX_TIEOFF_Inst_ARMTOP_CPU1PWRDOWNALL		((1 << 16) | 2908)
+#define NX_TIEOFF_Inst_ARMTOP_CPU2PWRDOWNALL		((1 << 16) | 2909)
+#define NX_TIEOFF_Inst_ARMTOP_CPU3PWRDOWNALL		((1 << 16) | 2910)
+#define NX_TIEOFF_Inst_ARMTOP_CLAMPL2			((1 << 16) | 2920)
+#define NX_TIEOFF_Inst_ARMTOP_L2FLUSHREQ		((1 << 16) | 3018)
+#define NX_TIEOFF_Inst_ARMTOP_L2FLUSHDONE		((1 << 16) | 3019)
+#define NX_TIEOFF_Inst_ARMTOP_ACINACTM			((1 << 16) | 3023)
+#define NX_TIEOFF_Inst_ARMTOP_P1_SMPEN			((4 << 16) | 3360)
+#define NX_TIEOFF_Inst_ARMTOP_P1_STANBYWFI		((4 << 16) | 3424)
+#define NX_TIEOFF_Inst_ARMTOP_P1_STANBYWFIL2		((1 << 16) | 3428)
+#define NX_TIEOFF_Inst_ARMTOP_P1_DBGNOPWRDWN		((4 << 16) | 3442)
+#define NX_TIEOFF_Inst_ARMTOP_P1_DBGPWRUPREQ		((4 << 16) | 3443)
+#define NX_TIEOFF_Inst_ARMTOP_P1_DBGPWRDUP		((4 << 16) | 3444)
+#define NX_TIEOFF_Inst_ARMTOP_P1_COREPWRDOWNPRE		((1 << 16) | 3445)
+#define NX_TIEOFF_Inst_ARMTOP_P1_CPU0PWRDOWNPRE		((1 << 16) | 3446)
+#define NX_TIEOFF_Inst_ARMTOP_P1_CPU1PWRDOWNPRE		((1 << 16) | 3447)
+#define NX_TIEOFF_Inst_ARMTOP_P1_CPU2PWRDOWNPRE		((1 << 16) | 3448)
+#define NX_TIEOFF_Inst_ARMTOP_P1_CPU3PWRDOWNPRE		((1 << 16) | 3449)
+#define NX_TIEOFF_Inst_ARMTOP_P1_COREPWRDOWNALL		((1 << 16) | 3450)
+#define NX_TIEOFF_Inst_ARMTOP_P1_CPU0PWRDOWNALL		((1 << 16) | 3451)
+#define NX_TIEOFF_Inst_ARMTOP_P1_CPU1PWRDOWNALL		((1 << 16) | 3452)
+#define NX_TIEOFF_Inst_ARMTOP_P1_CPU2PWRDOWNALL		((1 << 16) | 3453)
+#define NX_TIEOFF_Inst_ARMTOP_P1_CPU3PWRDOWNALL		((1 << 16) | 3454)
+#define NX_TIEOFF_Inst_ARMTOP_P1_CLAMPL2		((1 << 16) | 3464)
+#define NX_TIEOFF_Inst_ARMTOP_P1_L2FLUSHREQ		((1 << 16) | 3562)
+#define NX_TIEOFF_Inst_ARMTOP_P1_L2FLUSHDONE		((1 << 16) | 3563)
+#define NX_TIEOFF_Inst_ARMTOP_P1_ACINACTM		((1 << 16) | 3567)
+#endif
+
+#endif /* _NEXELL_TIEOFF_H */
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [RFC PATCH v2 02/13] arm: add mach-nexell (all files except header files)
  2020-03-28  9:43 [RFC PATCH v2 00/13] arm: add support for SoC S5P4418 Stefan Bosch
  2020-03-28  9:43 ` [RFC PATCH v2 01/13] arm: add mach-nexell (header files) Stefan Bosch
@ 2020-03-28  9:43 ` Stefan Bosch
  2020-03-28  9:43 ` [RFC PATCH v2 03/13] gpio: add nexell driver Stefan Bosch
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 21+ messages in thread
From: Stefan Bosch @ 2020-03-28  9:43 UTC (permalink / raw)
  To: u-boot

Changes in relation to FriendlyARM's U-Boot nanopi2-v2016.01:
- SPL not supported yet --> no spl-directory in arch/arm/mach-nexell.
  Appropriate line in Makefile removed.
- clock.c: 'section(".data")' added to declaration of clk_periphs[] and
  core_hz.
- Kconfig: Changes to have a structure like in mach-bcm283x/Kconfig,
  e.g. "config ..." entries moved from other Kconfig.
- timer.c: 'section(".data")' added to declaration of timestamp and
  lastdec.
- arch/arm/mach-nexell/serial.c removed because this is for the UARTs
  of the S5P6818 SoC which is not supported yet. S5P4418 UARTs are
  different, here the (existing) PL011-code is used.

Signed-off-by: Stefan Bosch <stefan_b@posteo.net>
---

Changes in v2:
- arch/arm/mach-nexell/serial.c removed because this is for the UARTs
  of the S5P6818 SoC which is not supported yet. S5P4418 UARTs are
  different, here the (existing) PL011-code is used.
- line '... += spl/' in in arch/arm/mach-nexell/Makefile deleted, this
  change has already been stated in the commit message but was missing
  nethertheless.

 arch/arm/Kconfig                      |   7 +
 arch/arm/Makefile                     |   1 +
 arch/arm/mach-nexell/Kconfig          |  67 +++
 arch/arm/mach-nexell/Makefile         |  13 +
 arch/arm/mach-nexell/clock.c          | 869 ++++++++++++++++++++++++++++++++++
 arch/arm/mach-nexell/cmd_boot_linux.c | 145 ++++++
 arch/arm/mach-nexell/config.mk        |  11 +
 arch/arm/mach-nexell/nx_gpio.c        | 352 ++++++++++++++
 arch/arm/mach-nexell/nx_sec_reg.c     |  82 ++++
 arch/arm/mach-nexell/reg-call.S       |  23 +
 arch/arm/mach-nexell/reset.c          |  33 ++
 arch/arm/mach-nexell/tieoff.c         | 109 +++++
 arch/arm/mach-nexell/timer.c          | 297 ++++++++++++
 13 files changed, 2009 insertions(+)
 create mode 100644 arch/arm/mach-nexell/Kconfig
 create mode 100644 arch/arm/mach-nexell/Makefile
 create mode 100644 arch/arm/mach-nexell/clock.c
 create mode 100644 arch/arm/mach-nexell/cmd_boot_linux.c
 create mode 100644 arch/arm/mach-nexell/config.mk
 create mode 100644 arch/arm/mach-nexell/nx_gpio.c
 create mode 100644 arch/arm/mach-nexell/nx_sec_reg.c
 create mode 100644 arch/arm/mach-nexell/reg-call.S
 create mode 100644 arch/arm/mach-nexell/reset.c
 create mode 100644 arch/arm/mach-nexell/tieoff.c
 create mode 100644 arch/arm/mach-nexell/timer.c

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index a623ef5..469aa65 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -875,6 +875,11 @@ config ARCH_MX5
 	select CPU_V7A
 	imply MXC_GPIO
 
+config ARCH_NEXELL
+	bool "Nexell S5P4418/S5P6818 SoC"
+	select ENABLE_ARM_SOC_BOOT0_HOOK
+	select DM
+
 config ARCH_OWL
 	bool "Actions Semi OWL SoCs"
 	select ARM64
@@ -1797,6 +1802,8 @@ source "arch/arm/cpu/armv8/Kconfig"
 
 source "arch/arm/mach-imx/Kconfig"
 
+source "arch/arm/mach-nexell/Kconfig"
+
 source "board/bosch/shc/Kconfig"
 source "board/bosch/guardian/Kconfig"
 source "board/CarMediaLab/flea3/Kconfig"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 1e60a9f..5a390b8 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -67,6 +67,7 @@ machine-$(CONFIG_ARCH_MESON)		+= meson
 machine-$(CONFIG_ARCH_MVEBU)		+= mvebu
 # TODO: rename CONFIG_TEGRA -> CONFIG_ARCH_TEGRA
 # TODO: rename CONFIG_ORION5X -> CONFIG_ARCH_ORION5X
+machine-$(CONFIG_ARCH_NEXELL)		+= nexell
 machine-$(CONFIG_ORION5X)		+= orion5x
 machine-$(CONFIG_ARCH_OMAP2PLUS)	+= omap2
 machine-$(CONFIG_ARCH_OWL)		+= owl
diff --git a/arch/arm/mach-nexell/Kconfig b/arch/arm/mach-nexell/Kconfig
new file mode 100644
index 0000000..5368909
--- /dev/null
+++ b/arch/arm/mach-nexell/Kconfig
@@ -0,0 +1,67 @@
+if ARCH_NEXELL
+
+config NEXELL_COMMON
+	bool "Nexell common options"
+
+config NEXELL_ARMV7_COMMON
+	bool "Nexell 32-bit common options"
+	select CPU_V7A
+	select NEXELL_COMMON
+	#select SUPPORT_SPL
+
+config NEXELL_ARMV8_COMMON
+	bool "Nexell 64-bit common options"
+	select ARM64
+	select ARMV8_MULTIENTRY
+	select NEXELL_COMMON
+
+config ARCH_S5P4418
+	bool "Nexell S5P4418 SoC"
+	select NEXELL_ARMV7_COMMON
+	select OF_CONTROL
+	select OF_SEPARATE
+	select NX_GPIO
+	select PL011_SERIAL
+	select PL011_SERIAL_FLUSH_ON_INIT
+
+config ARCH_S5P6818
+	bool "Nexell S5P6818 SoC"
+	select NEXELL_ARMV8_COMMON
+
+menu "Nexell S5P4418/S5P6818"
+	#depends on ARCH_S5P4418
+	depends on ARCH_NEXELL
+
+choice
+	prompt "Nexell S5P4418/S5P6818 board select"
+	optional
+
+config TARGET_NANOPI2
+	bool "FriendlyARM NanoPi2 Board"
+	select ARCH_S5P4418
+
+endchoice
+
+config SYS_BOARD
+	default "nanopi2"
+
+config SYS_VENDOR
+	default "friendlyarm"
+
+config SYS_SOC
+	default "nexell"
+
+config SYS_CONFIG_NAME
+	default "s5p4418_nanopi2"
+
+endmenu
+
+config SYS_PLLFIN
+	int
+
+config TIMER_SYS_TICK_CH
+	int
+
+source "board/friendlyarm/Kconfig"
+
+endif
diff --git a/arch/arm/mach-nexell/Makefile b/arch/arm/mach-nexell/Makefile
new file mode 100644
index 0000000..10b3963
--- /dev/null
+++ b/arch/arm/mach-nexell/Makefile
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2016 Nexell
+# Hyunseok, Jung <hsjung@nexell.co.kr>
+
+obj-y				+= clock.o
+obj-y				+= timer.o
+obj-y				+= reset.o
+obj-y				+= nx_gpio.o
+obj-y				+= tieoff.o
+obj-$(CONFIG_ARCH_S5P4418)	+= reg-call.o
+obj-$(CONFIG_ARCH_S5P4418)	+= nx_sec_reg.o
+obj-$(CONFIG_CMD_BOOTL)		+= cmd_boot_linux.o
diff --git a/arch/arm/mach-nexell/clock.c b/arch/arm/mach-nexell/clock.c
new file mode 100644
index 0000000..a0ba2d8
--- /dev/null
+++ b/arch/arm/mach-nexell/clock.c
@@ -0,0 +1,869 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2016 Nexell
+ * Hyunseok, Jung <hsjung@nexell.co.kr>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <linux/err.h>
+#include <asm/io.h>
+#include <asm/arch/nexell.h>
+#include <asm/arch/clk.h>
+
+/*
+ * clock generator macros
+ */
+#define	I_PLL0_BIT		(0)
+#define	I_PLL1_BIT		(1)
+#define	I_PLL2_BIT		(2)
+#define	I_PLL3_BIT		(3)
+#define	I_EXT1_BIT		(4)
+#define	I_EXT2_BIT		(5)
+#define	I_CLKn_BIT		(7)
+#define	I_EXT1_BIT_FORCE	(8)
+#define	I_EXT2_BIT_FORCE	(9)
+
+#define	I_CLOCK_NUM		6 /* PLL0, PLL1, PLL2, PLL3, EXT1, EXT2 */
+
+#define I_EXECEPT_CLK		(0)
+#define	I_CLOCK_MASK		(((1 << I_CLOCK_NUM) - 1) & ~I_EXECEPT_CLK)
+
+#define	I_PLL0			(1 << I_PLL0_BIT)
+#define	I_PLL1			(1 << I_PLL1_BIT)
+#define	I_PLL2			(1 << I_PLL2_BIT)
+#define	I_PLL3			(1 << I_PLL3_BIT)
+#define	I_EXTCLK1		(1 << I_EXT1_BIT)
+#define	I_EXTCLK2		(1 << I_EXT2_BIT)
+#define	I_EXTCLK1_FORCE		(1 << I_EXT1_BIT_FORCE)
+#define	I_EXTCLK2_FORCE		(1 << I_EXT2_BIT_FORCE)
+
+#define	I_PLL_0_1		(I_PLL0    | I_PLL1)
+#define	I_PLL_0_2		(I_PLL_0_1 | I_PLL2)
+#define	I_PLL_0_3		(I_PLL_0_2 | I_PLL3)
+#define	I_CLKnOUT		(0)
+
+#define	I_PCLK			(1 << 16)
+#define	I_BCLK			(1 << 17)
+#define	I_GATE_PCLK		(1 << 20)
+#define	I_GATE_BCLK		(1 << 21)
+#define	I_PCLK_MASK		(I_GATE_PCLK | I_PCLK)
+#define	I_BCLK_MASK		(I_GATE_BCLK | I_BCLK)
+
+struct clk_dev_peri {
+	const char *dev_name;
+	void __iomem *base;
+	int dev_id;
+	int periph_id;
+	int clk_step;
+	u32 in_mask;
+	u32 in_mask1;
+	int div_src_0;
+	int div_val_0;
+	int invert_0;
+	int div_src_1;
+	int div_val_1;
+	int invert_1;
+	int in_extclk_1;
+	int in_extclk_2;
+};
+
+struct clk_dev {
+	struct clk  clk;
+	struct clk *link;
+	const char *name;
+	struct clk_dev_peri *peri;
+};
+
+struct clk_dev_map {
+	unsigned int con_enb;
+	unsigned int con_gen[4];
+};
+
+#define CLK_PERI_1S(name, devid, id, addr, mk)[id] = \
+	{ .dev_name = name, .dev_id = devid, .periph_id = id, .clk_step = 1, \
+	.base = (void *)addr, .in_mask = mk, }
+
+#define CLK_PERI_2S(name, devid, id, addr, mk, mk2)[id] = \
+	{ .dev_name = name, .dev_id = devid, .periph_id = id, .clk_step = 2, \
+	.base = (void *)addr, .in_mask = mk, .in_mask1 = mk2, }
+
+static const char * const clk_core[] = {
+	CORECLK_NAME_PLL0, CORECLK_NAME_PLL1, CORECLK_NAME_PLL2,
+	CORECLK_NAME_PLL3, CORECLK_NAME_FCLK, CORECLK_NAME_MCLK,
+	CORECLK_NAME_BCLK, CORECLK_NAME_PCLK, CORECLK_NAME_HCLK,
+};
+
+/*
+ * Section ".data" must be used because BSS is not available before relocation,
+ * in board_init_f(), respectively! I.e. global variables can not be used!
+ */
+static struct clk_dev_peri clk_periphs[]
+	__attribute__((section(".data"))) = {
+	CLK_PERI_1S(DEV_NAME_TIMER,	0,	CLK_ID_TIMER_0,
+		    PHY_BASEADDR_CLKGEN14, (I_PLL_0_2)),
+	CLK_PERI_1S(DEV_NAME_TIMER,	1,	CLK_ID_TIMER_1,
+		    PHY_BASEADDR_CLKGEN0, (I_PLL_0_2)),
+	CLK_PERI_1S(DEV_NAME_TIMER,	2,	CLK_ID_TIMER_2,
+		    PHY_BASEADDR_CLKGEN1, (I_PLL_0_2)),
+	CLK_PERI_1S(DEV_NAME_TIMER,	3,	CLK_ID_TIMER_3,
+		    PHY_BASEADDR_CLKGEN2, (I_PLL_0_2)),
+	CLK_PERI_1S(DEV_NAME_UART,	0,	CLK_ID_UART_0,
+		    PHY_BASEADDR_CLKGEN22, (I_PLL_0_2)),
+	CLK_PERI_1S(DEV_NAME_UART,	1,	CLK_ID_UART_1,
+		    PHY_BASEADDR_CLKGEN24, (I_PLL_0_2)),
+	CLK_PERI_1S(DEV_NAME_UART,	2,	CLK_ID_UART_2,
+		    PHY_BASEADDR_CLKGEN23, (I_PLL_0_2)),
+	CLK_PERI_1S(DEV_NAME_UART,	3,	CLK_ID_UART_3,
+		    PHY_BASEADDR_CLKGEN25, (I_PLL_0_2)),
+	CLK_PERI_1S(DEV_NAME_UART,	4,	CLK_ID_UART_4,
+		    PHY_BASEADDR_CLKGEN26, (I_PLL_0_2)),
+	CLK_PERI_1S(DEV_NAME_UART,	5,	CLK_ID_UART_5,
+		    PHY_BASEADDR_CLKGEN27, (I_PLL_0_2)),
+	CLK_PERI_1S(DEV_NAME_PWM,	0,	CLK_ID_PWM_0,
+		    PHY_BASEADDR_CLKGEN13, (I_PLL_0_2)),
+	CLK_PERI_1S(DEV_NAME_PWM,	1,	CLK_ID_PWM_1,
+		    PHY_BASEADDR_CLKGEN3, (I_PLL_0_2)),
+	CLK_PERI_1S(DEV_NAME_PWM,	2,	CLK_ID_PWM_2,
+		    PHY_BASEADDR_CLKGEN4, (I_PLL_0_2)),
+	CLK_PERI_1S(DEV_NAME_PWM,	3,	CLK_ID_PWM_3,
+		    PHY_BASEADDR_CLKGEN5, (I_PLL_0_2)),
+	CLK_PERI_1S(DEV_NAME_I2C,	0,	CLK_ID_I2C_0,
+		    PHY_BASEADDR_CLKGEN6, (I_GATE_PCLK)),
+	CLK_PERI_1S(DEV_NAME_I2C,	1,	CLK_ID_I2C_1,
+		    PHY_BASEADDR_CLKGEN7, (I_GATE_PCLK)),
+	CLK_PERI_1S(DEV_NAME_I2C,	2,	CLK_ID_I2C_2,
+		    PHY_BASEADDR_CLKGEN8, (I_GATE_PCLK)),
+	CLK_PERI_2S(DEV_NAME_GMAC,	0,	CLK_ID_GMAC,
+		    PHY_BASEADDR_CLKGEN10,
+		    (I_PLL_0_3 | I_EXTCLK1 | I_EXTCLK1_FORCE),
+		    (I_CLKnOUT)),
+	CLK_PERI_2S(DEV_NAME_I2S,	0,	CLK_ID_I2S_0,
+		    PHY_BASEADDR_CLKGEN15, (I_PLL_0_3 | I_EXTCLK1),
+		    (I_CLKnOUT)),
+	CLK_PERI_2S(DEV_NAME_I2S,	1,	CLK_ID_I2S_1,
+		    PHY_BASEADDR_CLKGEN16, (I_PLL_0_3 | I_EXTCLK1),
+		    (I_CLKnOUT)),
+	CLK_PERI_2S(DEV_NAME_I2S,	2,	CLK_ID_I2S_2,
+		    PHY_BASEADDR_CLKGEN17, (I_PLL_0_3 | I_EXTCLK1),
+		    (I_CLKnOUT)),
+	CLK_PERI_1S(DEV_NAME_SDHC,	0,	CLK_ID_SDHC_0,
+		    PHY_BASEADDR_CLKGEN18, (I_PLL_0_2 | I_GATE_PCLK)),
+	CLK_PERI_1S(DEV_NAME_SDHC,	1,	CLK_ID_SDHC_1,
+		    PHY_BASEADDR_CLKGEN19, (I_PLL_0_2 | I_GATE_PCLK)),
+	CLK_PERI_1S(DEV_NAME_SDHC,	2,	CLK_ID_SDHC_2,
+		    PHY_BASEADDR_CLKGEN20, (I_PLL_0_2 | I_GATE_PCLK)),
+	CLK_PERI_1S(DEV_NAME_SPI,	0,	CLK_ID_SPI_0,
+		    PHY_BASEADDR_CLKGEN37, (I_PLL_0_2)),
+	CLK_PERI_1S(DEV_NAME_SPI,	1,	CLK_ID_SPI_1,
+		    PHY_BASEADDR_CLKGEN38, (I_PLL_0_2)),
+	CLK_PERI_1S(DEV_NAME_SPI,	2,	CLK_ID_SPI_2,
+		    PHY_BASEADDR_CLKGEN39, (I_PLL_0_2)),
+};
+
+#define	CLK_PERI_NUM		((int)ARRAY_SIZE(clk_periphs))
+#define	CLK_CORE_NUM		((int)ARRAY_SIZE(clk_core))
+#define	CLK_DEVS_NUM		(CLK_CORE_NUM + CLK_PERI_NUM)
+#define	MAX_DIVIDER		((1 << 8) - 1)	/* 256, align 2 */
+
+static struct clk_dev		st_clk_devs[CLK_DEVS_NUM]
+				__attribute__((section(".data")));
+#define	clk_dev_get(n)		((struct clk_dev *)&st_clk_devs[n])
+#define	clk_container(p)	(container_of(p, struct clk_dev, clk))
+
+/*
+ * Core frequencys
+ */
+struct _core_hz_ {
+	unsigned long pll[4];					/* PLL */
+	unsigned long cpu_fclk, cpu_bclk;			/* cpu */
+	unsigned long mem_fclk, mem_dclk, mem_bclk, mem_pclk;	/* ddr */
+	unsigned long bus_bclk, bus_pclk;			/* bus */
+#if defined(CONFIG_ARCH_S5P6818)
+	unsigned long cci4_bclk, cci4_pclk;			/* cci */
+#endif
+	/* ip */
+	unsigned long g3d_bclk;
+	unsigned long coda_bclk, coda_pclk;
+#if defined(CONFIG_ARCH_S5P6818)
+	unsigned long disp_bclk, disp_pclk;
+	unsigned long hdmi_pclk;
+#endif
+};
+
+/*
+ * Section ".data" must be used because BSS is not available before relocation,
+ * in board_init_f(), respectively! I.e. global variables can not be used!
+ */
+/* core clock */
+static struct _core_hz_ core_hz __attribute__((section(".data")));
+
+#define	CORE_HZ_SIZE	(sizeof(core_hz) / 4)
+
+/*
+ * CLKGEN HW
+ */
+static inline void clk_dev_bclk(void *base, int on)
+{
+	struct clk_dev_map *reg = base;
+	unsigned int val = readl(&reg->con_enb) & ~(0x3);
+
+	val |= (on ? 3 : 0) & 0x3;	/* always BCLK */
+	writel(val, &reg->con_enb);
+}
+
+static inline void clk_dev_pclk(void *base, int on)
+{
+	struct clk_dev_map *reg = base;
+	unsigned int val = 0;
+
+	if (!on)
+		return;
+
+	val	 = readl(&reg->con_enb) & ~(1 << 3);
+	val |= (1 << 3);
+	writel(val, &reg->con_enb);
+}
+
+static inline void clk_dev_rate(void *base, int step, int src, int div)
+{
+	struct clk_dev_map *reg = base;
+	unsigned int val = 0;
+
+	val  = readl(&reg->con_gen[step << 1]);
+	val &= ~(0x07   << 2);
+	val |=  (src    << 2);	/* source */
+	val	&= ~(0xFF   << 5);
+	val	|=  (div - 1) << 5;	/* divider */
+	writel(val, &reg->con_gen[step << 1]);
+}
+
+static inline void clk_dev_inv(void *base, int step, int inv)
+{
+	struct clk_dev_map *reg = base;
+	unsigned int val = readl(&reg->con_gen[step << 1]) & ~(1 << 1);
+
+	val	|= (inv << 1);
+	writel(val, &reg->con_gen[step << 1]);
+}
+
+static inline void clk_dev_enb(void *base, int on)
+{
+	struct clk_dev_map *reg = base;
+	unsigned int val = readl(&reg->con_enb) & ~(1 << 2);
+
+	val	|= ((on ? 1 : 0) << 2);
+	writel(val, &reg->con_enb);
+}
+
+/*
+ * CORE FREQUENCY
+ *
+ * PLL0 [P,M,S]	-------	| | ----- [DIV0] --- CPU-G0
+ *			|M| ----- [DIV1] --- BCLK/PCLK
+ * PLL1 [P,M,S]	-------	| | ----- [DIV2] --- DDR
+ *			|U| ----- [DIV3] --- 3D
+ * PLL2 [P,M,S,K]-------| | ----- [DIV4] --- CODA
+ *			|X| ----- [DIV5] --- DISPLAY
+ * PLL3 [P,M,S,K]-------| | ----- [DIV6] --- HDMI
+ *			| | ----- [DIV7] --- CPU-G1
+ *			| | ----- [DIV8] --- CCI-400(FASTBUS)
+ *
+ */
+
+struct	nx_clkpwr_registerset {
+	u32 clkmodereg0;	/* 0x000 : Clock Mode Register0 */
+	u32 __reserved0;	/* 0x004 */
+	u32 pllsetreg[4];	/* 0x008 ~ 0x014 : PLL Setting Register */
+	u32 __reserved1[2];	/* 0x018 ~ 0x01C */
+	u32 dvoreg[9];		/* 0x020 ~ 0x040 : Divider Setting Register */
+	u32 __Reserved2;	/* 0x044 */
+	u32 pllsetreg_sscg[6];	/* 0x048 ~ 0x05C */
+	u32 __reserved3[8];		/* 0x060 ~ 0x07C */
+	u8 __reserved4[0x200 - 0x80];	/* padding (0x80 ~ 0x1FF) */
+	u32 gpiowakeupriseenb;	/* 0x200 : GPIO Rising Edge Detect En. Reg. */
+	u32 gpiowakeupfallenb;	/* 0x204 : GPIO Falling Edge Detect En. Reg. */
+	u32 gpiorstenb;		/* 0x208 : GPIO Reset Enable Register */
+	u32 gpiowakeupenb;	/* 0x20C : GPIO Wakeup Source Enable */
+	u32 gpiointenb;		/* 0x210 : Interrupt Enable Register */
+	u32 gpiointpend;	/* 0x214 : Interrupt Pend Register */
+	u32 resetstatus;	/* 0x218 : Reset Status Register */
+	u32 intenable;		/* 0x21C : Interrupt Enable Register */
+	u32 intpend;		/* 0x220 : Interrupt Pend Register */
+	u32 pwrcont;		/* 0x224 : Power Control Register */
+	u32 pwrmode;		/* 0x228 : Power Mode Register */
+	u32 __reserved5;	/* 0x22C : Reserved Region */
+	u32 scratch[3];		/* 0x230 ~ 0x238 : Scratch Register */
+	u32 sysrstconfig;	/* 0x23C : System Reset Configuration Reg. */
+	u8  __reserved6[0x2A0 - 0x240];	/* padding (0x240 ~ 0x29F) */
+	u32 cpupowerdownreq;	/* 0x2A0 : CPU Power Down Request Register */
+	u32 cpupoweronreq;	/* 0x2A4 : CPU Power On Request Register */
+	u32 cpuresetmode;	/* 0x2A8 : CPU Reset Mode Register */
+	u32 cpuwarmresetreq;	/* 0x2AC : CPU Warm Reset Request Register */
+	u32 __reserved7;	/* 0x2B0 */
+	u32 cpustatus;		/* 0x2B4 : CPU Status Register */
+	u8  __reserved8[0x400 - 0x2B8];	/* padding (0x2B8 ~ 0x33F) */
+};
+
+static struct nx_clkpwr_registerset * const clkpwr =
+	(struct nx_clkpwr_registerset *)PHY_BASEADDR_CLKPWR;
+
+#define	getquotient(v, d)	((v) / (d))
+
+#define	DIV_CPUG0	0
+#define	DIV_BUS		1
+#define	DIV_MEM		2
+#define	DIV_G3D		3
+#define	DIV_CODA	4
+#if defined(CONFIG_ARCH_S5P6818)
+#define	DIV_DISP	5
+#define	DIV_HDMI	6
+#define	DIV_CPUG1	7
+#define	DIV_CCI4	8
+#endif
+
+#define	DVO0		3
+#define	DVO1		9
+#define	DVO2		15
+#define	DVO3		21
+
+static unsigned int pll_rate(unsigned int plln, unsigned int xtal)
+{
+	unsigned int val, val1, nP, nM, nS, nK;
+	unsigned int temp = 0;
+
+	val   = clkpwr->pllsetreg[plln];
+	val1  = clkpwr->pllsetreg_sscg[plln];
+	xtal /= 1000;	/* Unit Khz */
+
+	nP = (val >> 18) & 0x03F;
+	nM = (val >>  8) & 0x3FF;
+	nS = (val >>  0) & 0x0FF;
+	nK = (val1 >> 16) & 0xFFFF;
+
+	if (plln > 1 && nK) {
+		temp = (unsigned int)(getquotient((getquotient((nK * 1000),
+			65536) * xtal), nP) >> nS);
+	}
+
+	temp = (unsigned int)((getquotient((nM * xtal), nP) >> nS) * 1000)
+	       + temp;
+	return temp;
+}
+
+static unsigned int pll_dvo(int dvo)
+{
+	unsigned int val;
+
+	val = (clkpwr->dvoreg[dvo] & 0x7);
+	return val;
+}
+
+static unsigned int pll_div(int dvo)
+{
+	unsigned int val = clkpwr->dvoreg[dvo];
+
+	return  ((((val >> DVO3) & 0x3F) + 1) << 24)  |
+			((((val >> DVO2) & 0x3F) + 1) << 16) |
+			((((val >> DVO1) & 0x3F) + 1) << 8)  |
+			((((val >> DVO0) & 0x3F) + 1) << 0);
+}
+
+#define	PLLN_RATE(n)	 (pll_rate(n, CONFIG_SYS_PLLFIN))	/* 0~ 3 */
+#define	CPU_FCLK_RATE(n) (pll_rate(pll_dvo(n), CONFIG_SYS_PLLFIN) / \
+			 ((pll_div(n) >> 0) & 0x3F))
+#define	CPU_BCLK_RATE(n) (pll_rate(pll_dvo(n), CONFIG_SYS_PLLFIN) / \
+			 ((pll_div(n) >> 0) & 0x3F) /               \
+			 ((pll_div(n) >> 8) & 0x3F))
+
+#define	MEM_FCLK_RATE()	 (pll_rate(pll_dvo(DIV_MEM), CONFIG_SYS_PLLFIN) / \
+			 ((pll_div(DIV_MEM) >> 0) & 0x3F) / \
+			 ((pll_div(DIV_MEM) >> 8) & 0x3F))
+
+#define	MEM_DCLK_RATE()	 (pll_rate(pll_dvo(DIV_MEM), CONFIG_SYS_PLLFIN) / \
+			 ((pll_div(DIV_MEM) >> 0) & 0x3F))
+
+#define	MEM_BCLK_RATE()	 (pll_rate(pll_dvo(DIV_MEM), CONFIG_SYS_PLLFIN) / \
+			 ((pll_div(DIV_MEM) >> 0) & 0x3F) / \
+			 ((pll_div(DIV_MEM) >> 8) & 0x3F) / \
+			 ((pll_div(DIV_MEM) >> 16) & 0x3F))
+#define	MEM_PCLK_RATE()	 (pll_rate(pll_dvo(DIV_MEM), CONFIG_SYS_PLLFIN) / \
+			 ((pll_div(DIV_MEM) >> 0) & 0x3F) / \
+			 ((pll_div(DIV_MEM) >> 8) & 0x3F) / \
+			 ((pll_div(DIV_MEM) >> 16) & 0x3F) / \
+			 ((pll_div(DIV_MEM) >> 24) & 0x3F))
+
+#define	BUS_BCLK_RATE()	 (pll_rate(pll_dvo(DIV_BUS), CONFIG_SYS_PLLFIN) / \
+			 ((pll_div(DIV_BUS) >> 0) & 0x3F))
+#define	BUS_PCLK_RATE()	 (pll_rate(pll_dvo(DIV_BUS), CONFIG_SYS_PLLFIN) / \
+			 ((pll_div(DIV_BUS) >> 0) & 0x3F) / \
+			 ((pll_div(DIV_BUS) >> 8) & 0x3F))
+
+#define	G3D_BCLK_RATE()	 (pll_rate(pll_dvo(DIV_G3D), CONFIG_SYS_PLLFIN) / \
+			 ((pll_div(DIV_G3D) >> 0) & 0x3F))
+
+#define	MPG_BCLK_RATE()	 (pll_rate(pll_dvo(DIV_CODA), CONFIG_SYS_PLLFIN) / \
+			 ((pll_div(DIV_CODA) >> 0) & 0x3F))
+#define	MPG_PCLK_RATE()	 (pll_rate(pll_dvo(DIV_CODA), CONFIG_SYS_PLLFIN) / \
+			 ((pll_div(DIV_CODA) >> 0) & 0x3F)	/ \
+			 ((pll_div(DIV_CODA) >> 8) & 0x3F))
+
+#if defined(CONFIG_ARCH_S5P6818)
+#define	DISP_BCLK_RATE() (pll_rate(pll_dvo(DIV_DISP), CONFIG_SYS_PLLFIN) / \
+			 ((pll_div(DIV_DISP) >> 0) & 0x3F))
+#define	DISP_PCLK_RATE() (pll_rate(pll_dvo(DIV_DISP), CONFIG_SYS_PLLFIN) / \
+			 ((pll_div(DIV_DISP) >> 0) & 0x3F)	/ \
+			 ((pll_div(DIV_DISP) >> 8) & 0x3F))
+
+#define	HDMI_PCLK_RATE() (pll_rate(pll_dvo(DIV_HDMI), CONFIG_SYS_PLLFIN) / \
+			 ((pll_div(DIV_HDMI) >> 0) & 0x3F))
+
+#define	CCI4_BCLK_RATE() (pll_rate(pll_dvo(DIV_CCI4), CONFIG_SYS_PLLFIN) / \
+			 ((pll_div(DIV_CCI4) >> 0) & 0x3F))
+#define	CCI4_PCLK_RATE() (pll_rate(pll_dvo(DIV_CCI4), CONFIG_SYS_PLLFIN) / \
+			 ((pll_div(DIV_CCI4) >> 0) & 0x3F)	/ \
+			 ((pll_div(DIV_CCI4) >> 8) & 0x3F))
+#endif
+
+static void core_update_rate(int type)
+{
+	switch (type) {
+	case  0:
+		core_hz.pll[0] = PLLN_RATE(0); break;
+	case  1:
+		core_hz.pll[1] = PLLN_RATE(1); break;
+	case  2:
+		core_hz.pll[2] = PLLN_RATE(2); break;
+	case  3:
+		core_hz.pll[3] = PLLN_RATE(3); break;
+	case  4:
+		core_hz.cpu_fclk = CPU_FCLK_RATE(DIV_CPUG0); break;
+	case  5:
+		core_hz.mem_fclk = MEM_FCLK_RATE(); break;
+	case  6:
+		core_hz.bus_bclk = BUS_BCLK_RATE(); break;
+	case  7:
+		core_hz.bus_pclk = BUS_PCLK_RATE(); break;
+	case  8:
+		core_hz.cpu_bclk = CPU_BCLK_RATE(DIV_CPUG0); break;
+	case  9:
+		core_hz.mem_dclk = MEM_DCLK_RATE(); break;
+	case 10:
+		core_hz.mem_bclk = MEM_BCLK_RATE(); break;
+	case 11:
+		core_hz.mem_pclk = MEM_PCLK_RATE(); break;
+	case 12:
+		core_hz.g3d_bclk = G3D_BCLK_RATE(); break;
+	case 13:
+		core_hz.coda_bclk = MPG_BCLK_RATE(); break;
+	case 14:
+		core_hz.coda_pclk = MPG_PCLK_RATE(); break;
+#if defined(CONFIG_ARCH_S5P6818)
+	case 15:
+		core_hz.disp_bclk = DISP_BCLK_RATE(); break;
+	case 16:
+		core_hz.disp_pclk = DISP_PCLK_RATE(); break;
+	case 17:
+		core_hz.hdmi_pclk = HDMI_PCLK_RATE(); break;
+	case 18:
+		core_hz.cci4_bclk = CCI4_BCLK_RATE(); break;
+	case 19:
+		core_hz.cci4_pclk = CCI4_PCLK_RATE(); break;
+#endif
+	};
+}
+
+static unsigned long core_get_rate(int type)
+{
+	unsigned long rate = 0;
+
+	switch (type) {
+	case  0:
+		rate = core_hz.pll[0];		break;
+	case  1:
+		rate = core_hz.pll[1];		break;
+	case  2:
+		rate = core_hz.pll[2];		break;
+	case  3:
+		rate = core_hz.pll[3];		break;
+	case  4:
+		rate = core_hz.cpu_fclk;	break;
+	case  5:
+		rate = core_hz.mem_fclk;	break;
+	case  6:
+		rate = core_hz.bus_bclk;	break;
+	case  7:
+		rate = core_hz.bus_pclk;	break;
+	case  8:
+		rate = core_hz.cpu_bclk;	break;
+	case  9:
+		rate = core_hz.mem_dclk;	break;
+	case 10:
+		rate = core_hz.mem_bclk;	break;
+	case 11:
+		rate = core_hz.mem_pclk;	break;
+	case 12:
+		rate = core_hz.g3d_bclk;	break;
+	case 13:
+		rate = core_hz.coda_bclk;	break;
+	case 14:
+		rate = core_hz.coda_pclk;	break;
+#if defined(CONFIG_ARCH_S5P6818)
+	case 15:
+		rate = core_hz.disp_bclk;	break;
+	case 16:
+		rate = core_hz.disp_pclk;	break;
+	case 17:
+		rate = core_hz.hdmi_pclk;	break;
+	case 18:
+		rate = core_hz.cci4_bclk;	break;
+	case 19:
+		rate = core_hz.cci4_pclk;	break;
+#endif
+	default:
+		printf("unknown core clock type %d ...\n", type);
+		break;
+	};
+	return rate;
+}
+
+static long core_set_rate(struct clk *clk, long rate)
+{
+	return clk->rate;
+}
+
+static void core_rate_init(void)
+{
+	int i;
+
+	for (i = 0; i < CORE_HZ_SIZE; i++)
+		core_update_rate(i);
+}
+
+/*
+ * Clock Interfaces
+ */
+static inline long clk_divide(long rate, long request,
+			      int align, int *divide)
+{
+	int div = (rate / request);
+	int max = MAX_DIVIDER & ~(align - 1);
+	int adv = (div & ~(align - 1)) + align;
+	long ret;
+
+	if (!div) {
+		if (divide)
+			*divide = 1;
+		return rate;
+	}
+
+	if (div != 1)
+		div &= ~(align - 1);
+
+	if (div != adv && abs(request - rate / div) > abs(request - rate / adv))
+		div = adv;
+
+	div = (div > max ? max : div);
+	if (divide)
+		*divide = div;
+
+	ret = rate / div;
+	return ret;
+}
+
+void clk_put(struct clk *clk)
+{
+}
+
+struct clk *clk_get(const char *id)
+{
+	struct clk_dev *cdev = clk_dev_get(0);
+	struct clk *clk = NULL;
+	const char *str = NULL, *c = NULL;
+	int i, devid;
+
+	if (id)
+		str = id;
+
+	for (i = 0; i < CLK_DEVS_NUM; i++, cdev++) {
+		if (!cdev->name)
+			continue;
+		if (!strncmp(cdev->name, str, strlen(cdev->name))) {
+			c = strrchr((const char *)str, (int)'.');
+			if (!c || !cdev->peri)
+				break;
+		devid = simple_strtoul(++c, NULL, 10);
+		if (cdev->peri->dev_id == devid)
+			break;
+		}
+	}
+	if (i < CLK_DEVS_NUM)
+		clk = &cdev->clk;
+	else
+		clk = &(clk_dev_get(7))->clk;	/* pclk */
+
+	return clk ? clk : ERR_PTR(-ENOENT);
+}
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	struct clk_dev *pll = NULL, *cdev = clk_container(clk);
+	struct clk_dev_peri *peri = cdev->peri;
+	unsigned long request = rate, rate_hz = 0;
+	unsigned int mask;
+	int step, div[2] = { 0, };
+	int i, n, clk2 = 0;
+	int start_src = 0, max_src = I_CLOCK_NUM;
+	short s1 = 0, s2 = 0, d1 = 0, d2 = 0;
+
+	if (!peri)
+		return core_set_rate(clk, rate);
+
+	step = peri->clk_step;
+	mask = peri->in_mask;
+	debug("clk: %s.%d request = %ld [input=0x%x]\n", peri->dev_name,
+	      peri->dev_id, rate, mask);
+
+	if (!(I_CLOCK_MASK & mask)) {
+		if (I_PCLK_MASK & mask)
+			return core_get_rate(CORECLK_ID_PCLK);
+		else if (I_BCLK_MASK & mask)
+			return core_get_rate(CORECLK_ID_BCLK);
+		else
+			return clk->rate;
+	}
+
+next:
+	if (peri->in_mask &  I_EXTCLK1_FORCE) {
+		start_src = 4; max_src = 5;
+	}
+	for (n = start_src ; max_src > n; n++) {
+		if (!(((mask & I_CLOCK_MASK) >> n) & 0x1))
+			continue;
+
+		if (n == I_EXT1_BIT) {
+			rate = peri->in_extclk_1;
+		} else if (n == I_EXT2_BIT) {
+			rate = peri->in_extclk_2;
+		} else {
+			pll  = clk_dev_get(n);
+			rate = pll->clk.rate;
+		}
+
+		if (!rate)
+			continue;
+
+		for (i = 0; step > i ; i++)
+			rate = clk_divide(rate, request, 2, &div[i]);
+
+		if (rate_hz && (abs(rate - request) > abs(rate_hz - request)))
+			continue;
+
+		debug("clk: %s.%d, pll.%d[%lu] request[%ld] calc[%ld]\n",
+		      peri->dev_name, peri->dev_id, n, pll->clk.rate,
+		      request, rate);
+
+		if (clk2) {
+			s1 = -1, d1 = -1;	/* not use */
+			s2 =  n, d2 = div[0];
+		} else {
+			s1 = n, d1 = div[0];
+			s2 = I_CLKn_BIT, d2 = div[1];
+		}
+		rate_hz = rate;
+	}
+
+	/* search 2th clock from input */
+	if (!clk2 && abs(rate_hz - request) &&
+	    peri->in_mask1 & ((1 << I_CLOCK_NUM) - 1)) {
+		clk2 = 1;
+		mask = peri->in_mask1;
+		step = 1;
+		goto next;
+	}
+	if (peri->in_mask &  I_EXTCLK1_FORCE) {
+		if (s1 == 0) {
+			s1 = 4; s2 = 7;
+			d1 = 1; d2 = 1;
+		}
+	}
+
+	peri->div_src_0 = s1, peri->div_val_0 = d1;
+	peri->div_src_1 = s2, peri->div_val_1 = d2;
+	clk->rate = rate_hz;
+
+	debug("clk: %s.%d, step[%d] src[%d,%d] %ld", peri->dev_name,
+	      peri->dev_id, peri->clk_step, peri->div_src_0, peri->div_src_1,
+	      rate);
+	debug("/(div0: %d * div1: %d) = %ld, %ld diff (%ld)\n",
+	      peri->div_val_0, peri->div_val_1, rate_hz, request,
+	      abs(rate_hz - request));
+
+	return clk->rate;
+}
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	struct clk_dev *cdev = clk_container(clk);
+
+	if (cdev->link)
+		clk = cdev->link;
+	return clk->rate;
+}
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	struct clk_dev *cdev = clk_container(clk);
+	struct clk_dev_peri *peri = cdev->peri;
+	int i;
+
+	if (!peri)
+		return core_set_rate(clk, rate);
+
+	clk_round_rate(clk, rate);
+
+	for (i = 0; peri->clk_step > i ; i++)	{
+		int s = (i == 0 ? peri->div_src_0 : peri->div_src_1);
+		int d = (i == 0 ? peri->div_val_0 : peri->div_val_1);
+
+		if (-1 == s)
+			continue;
+
+		clk_dev_rate(peri->base, i, s, d);
+
+		debug("clk: %s.%d (%p) set_rate [%d] src[%d] div[%d]\n",
+		      peri->dev_name, peri->dev_id, peri->base, i, s, d);
+	}
+
+	return clk->rate;
+}
+
+int clk_enable(struct clk *clk)
+{
+	struct clk_dev *cdev = clk_container(clk);
+	struct clk_dev_peri *peri = cdev->peri;
+	int i = 0, inv = 0;
+
+	if (!peri)
+		return 0;
+
+	debug("clk: %s.%d enable (BCLK=%s, PCLK=%s)\n", peri->dev_name,
+	      peri->dev_id, I_GATE_BCLK & peri->in_mask ? "ON" : "PASS",
+	      I_GATE_PCLK & peri->in_mask ? "ON" : "PASS");
+
+	if (!(I_CLOCK_MASK & peri->in_mask)) {
+		/* Gated BCLK/PCLK enable */
+		if (I_GATE_BCLK & peri->in_mask)
+			clk_dev_bclk(peri->base, 1);
+
+		if (I_GATE_PCLK & peri->in_mask)
+			clk_dev_pclk(peri->base, 1);
+
+		return 0;
+	}
+
+	/* invert */
+	inv = peri->invert_0;
+	for (; peri->clk_step > i; i++, inv = peri->invert_1)
+		clk_dev_inv(peri->base, i, inv);
+
+	/* Gated BCLK/PCLK enable */
+	if (I_GATE_BCLK & peri->in_mask)
+		clk_dev_bclk(peri->base, 1);
+
+	if (I_GATE_PCLK & peri->in_mask)
+		clk_dev_pclk(peri->base, 1);
+
+	/* restore clock rate */
+	for (i = 0; peri->clk_step > i ; i++)	{
+		int s = (i == 0 ? peri->div_src_0 : peri->div_src_1);
+		int d = (i == 0 ? peri->div_val_0 : peri->div_val_1);
+
+		if (s == -1)
+			continue;
+		clk_dev_rate(peri->base, i, s, d);
+	}
+
+	clk_dev_enb(peri->base, 1);
+
+	return 0;
+}
+
+void clk_disable(struct clk *clk)
+{
+	struct clk_dev *cdev = clk_container(clk);
+	struct clk_dev_peri *peri = cdev->peri;
+
+	if (!peri)
+		return;
+
+	debug("clk: %s.%d disable\n", peri->dev_name, peri->dev_id);
+
+	if (!(I_CLOCK_MASK & peri->in_mask)) {
+		/* Gated BCLK/PCLK disable */
+		if (I_GATE_BCLK & peri->in_mask)
+			clk_dev_bclk(peri->base, 0);
+
+		if (I_GATE_PCLK & peri->in_mask)
+			clk_dev_pclk(peri->base, 0);
+
+		return;
+	}
+
+	clk_dev_rate(peri->base, 0, 7, 256);	/* for power save */
+	clk_dev_enb(peri->base, 0);
+
+	/* Gated BCLK/PCLK disable */
+	if (I_GATE_BCLK & peri->in_mask)
+		clk_dev_bclk(peri->base, 0);
+
+	if (I_GATE_PCLK & peri->in_mask)
+		clk_dev_pclk(peri->base, 0);
+}
+
+/*
+ * Core clocks APIs
+ */
+void __init clk_init(void)
+{
+	struct clk_dev *cdev = st_clk_devs;
+	struct clk_dev_peri *peri = clk_periphs;
+	struct clk *clk = NULL;
+	int i = 0;
+
+	memset(cdev, 0, sizeof(st_clk_devs));
+	core_rate_init();
+
+	for (i = 0; (CLK_CORE_NUM + CLK_PERI_NUM) > i; i++, cdev++) {
+		if (i < CLK_CORE_NUM) {
+			cdev->name = clk_core[i];
+			clk = &cdev->clk;
+			clk->rate = core_get_rate(i);
+			continue;
+		}
+
+		peri = &clk_periphs[i - CLK_CORE_NUM];
+		peri->base = (void *)peri->base;
+
+		cdev->peri = peri;
+		cdev->name = peri->dev_name;
+
+		if (!(I_CLOCK_MASK & peri->in_mask)) {
+			if (I_BCLK_MASK & peri->in_mask)
+				cdev->clk.rate = core_get_rate(CORECLK_ID_BCLK);
+			if (I_PCLK_MASK & peri->in_mask)
+				cdev->clk.rate = core_get_rate(CORECLK_ID_PCLK);
+		}
+
+		/* prevent uart clock disable for low step debug message */
+		#ifndef CONFIG_DEBUG_NX_UART
+		if (peri->dev_name) {
+			#ifdef CONFIG_BACKLIGHT_PWM
+			if (!strcmp(peri->dev_name, DEV_NAME_PWM))
+				continue;
+			#endif
+		}
+		#endif
+	}
+	debug("CPU : Clock Generator= %d EA, ", CLK_DEVS_NUM);
+}
diff --git a/arch/arm/mach-nexell/cmd_boot_linux.c b/arch/arm/mach-nexell/cmd_boot_linux.c
new file mode 100644
index 0000000..f9d2a5c
--- /dev/null
+++ b/arch/arm/mach-nexell/cmd_boot_linux.c
@@ -0,0 +1,145 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2016 nexell
+ * jhkim <jhkim@nexell.co.kr>
+ */
+
+#include <common.h>
+#include <bootm.h>
+#include <command.h>
+#include <environment.h>
+#include <errno.h>
+#include <image.h>
+#include <fdt_support.h>
+
+#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_CLI_FRAMEWORK)
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static bootm_headers_t linux_images;
+
+static void boot_go_set_os(cmd_tbl_t *cmdtp, int flag, int argc,
+			   char * const argv[],
+			   bootm_headers_t *images)
+{
+	char * const img_addr = argv[0];
+
+	images->os.type = IH_TYPE_KERNEL;
+	images->os.comp = IH_COMP_NONE;
+	images->os.os = IH_OS_LINUX;
+	images->os.load = simple_strtoul(img_addr, NULL, 16);
+	images->ep = images->os.load;
+#if defined(CONFIG_ARM)
+	images->os.arch = IH_ARCH_ARM;
+#elif defined(CONFIG_ARM64)
+	images->os.arch = IH_ARCH_ARM64;
+#else
+	#error "Not support architecture ..."
+#endif
+
+#if !defined(CONFIG_OF_LIBFDT) && !defined(CONFIG_SPL_BUILD)
+	/* set DTB address for linux kernel */
+	if (argc > 2) {
+		unsigned long ft_addr;
+
+		ft_addr = simple_strtol(argv[2], NULL, 16);
+		images->ft_addr = (char *)ft_addr;
+
+		/*
+		 * if not defined IMAGE_ENABLE_OF_LIBFDT,
+		 * must be set to fdt address
+		 */
+		if (!IMAGE_ENABLE_OF_LIBFDT)
+			gd->bd->bi_boot_params = ft_addr;
+
+		debug("## set ft:%08lx and boot params:%08lx [control of:%s]"
+		      "...\n", ft_addr, gd->bd->bi_boot_params,
+		      IMAGE_ENABLE_OF_LIBFDT ? "on" : "off");
+	}
+#endif
+}
+
+#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_LMB)
+static void boot_start_lmb(bootm_headers_t *images)
+{
+	ulong		mem_start;
+	phys_size_t	mem_size;
+
+	lmb_init(&images->lmb);
+
+	mem_start = getenv_bootm_low();
+	mem_size = getenv_bootm_size();
+
+	lmb_add(&images->lmb, (phys_addr_t)mem_start, mem_size);
+
+	arch_lmb_reserve(&images->lmb);
+	board_lmb_reserve(&images->lmb);
+}
+#else
+#define lmb_reserve(lmb, base, size)
+static inline void boot_start_lmb(bootm_headers_t *images) { }
+#endif
+
+int do_boot_linux(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	boot_os_fn *boot_fn;
+	bootm_headers_t *images = &linux_images;
+	int flags;
+	int ret;
+
+	boot_start_lmb(images);
+
+	flags  = BOOTM_STATE_START;
+
+	argc--; argv++;
+	boot_go_set_os(cmdtp, flag, argc, argv, images);
+
+#if defined(CONFIG_OF_LIBFDT)
+	/* find flattened device tree */
+	ret = boot_get_fdt(flag, argc, argv, IH_ARCH_DEFAULT, images,
+			   &images->ft_addr, &images->ft_len);
+	if (ret) {
+		puts("Could not find a valid device tree\n");
+		return 1;
+	}
+	set_working_fdt_addr((ulong)images->ft_addr);
+#endif
+#if !defined(CONFIG_OF_LIBFDT)
+	flags |= BOOTM_STATE_OS_GO;
+#endif
+
+	boot_fn = do_bootm_linux;
+	ret = boot_fn(flags, argc, argv, images);
+
+	if (ret == BOOTM_ERR_UNIMPLEMENTED)
+		show_boot_progress(BOOTSTAGE_ID_DECOMP_UNIMPL);
+	else if (ret == BOOTM_ERR_RESET)
+		do_reset(cmdtp, flag, argc, argv);
+
+	return ret;
+}
+
+U_BOOT_CMD(bootl, CONFIG_SYS_MAXARGS, 1, do_boot_linux,
+	   "boot linux image from memory",
+	   "[addr [arg ...]]\n    - boot linux image stored in memory\n"
+	   "\tuse a '-' for the DTB address\n"
+);
+#endif
+
+#if defined(CONFIG_CMD_BOOTD) && !defined(CONFIG_CMD_BOOTM)
+int do_bootd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	return run_command(env_get("bootcmd"), flag);
+}
+
+U_BOOT_CMD(boot, 1, 1, do_bootd,
+	   "boot default, i.e., run 'bootcmd'",
+	   ""
+);
+
+/* keep old command name "bootd" for backward compatibility */
+U_BOOT_CMD(bootd, 1,	1,	do_bootd,
+	   "boot default, i.e., run 'bootcmd'",
+	   ""
+);
+#endif
diff --git a/arch/arm/mach-nexell/config.mk b/arch/arm/mach-nexell/config.mk
new file mode 100644
index 0000000..7b06626
--- /dev/null
+++ b/arch/arm/mach-nexell/config.mk
@@ -0,0 +1,11 @@
+#
+# (C) Copyright 2016 Nexell
+# junghyun kim<jhkim@nexell.co.kr>
+#
+# SPDX-License-Identifier:      GPL-2.0+
+#
+
+SOCDIR=CPUDIR/$(VENDOR)
+MACHDIR=$(patsubst %,arch/arm/mach-%,$(machine-y))
+
+LDPPFLAGS += -DMACHDIR=$(MACHDIR) -DSOCDIR=$(SOCDIR)
diff --git a/arch/arm/mach-nexell/nx_gpio.c b/arch/arm/mach-nexell/nx_gpio.c
new file mode 100644
index 0000000..dfba3a2
--- /dev/null
+++ b/arch/arm/mach-nexell/nx_gpio.c
@@ -0,0 +1,352 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2016 Nexell
+ * Youngbok, Park <ybpark@nexell.co.kr>
+ */
+
+/*
+ * FIXME : will be remove after support pinctrl
+ */
+#include <linux/types.h>
+#include <asm/io.h>
+#include <asm/arch/nexell.h>
+#include "asm/arch/nx_gpio.h"
+#define NUMBER_OF_GPIO_MODULE 5
+u32 __g_nx_gpio_valid_bit[NUMBER_OF_GPIO_MODULE] = {
+	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF};
+
+static struct {
+	struct nx_gpio_register_set *pregister;
+} __g_module_variables[NUMBER_OF_GPIO_MODULE] = {
+	{ (struct nx_gpio_register_set *)PHY_BASEADDR_GPIOA },
+	{ (struct nx_gpio_register_set *)PHY_BASEADDR_GPIOB },
+	{ (struct nx_gpio_register_set *)PHY_BASEADDR_GPIOC },
+	{ (struct nx_gpio_register_set *)PHY_BASEADDR_GPIOD },
+	{ (struct nx_gpio_register_set *)PHY_BASEADDR_GPIOE },
+};
+
+enum { nx_gpio_max_bit = 32 };
+
+void nx_gpio_set_bit(u32 *value, u32 bit, int enable)
+{
+	register u32 newvalue;
+
+	newvalue = *value;
+	newvalue &= ~(1ul << bit);
+	newvalue |= (u32)enable << bit;
+	writel(newvalue, value);
+}
+
+int nx_gpio_get_bit(u32 value, u32 bit)
+{
+	return (int)((value >> bit) & (1ul));
+}
+
+void nx_gpio_set_bit2(u32 *value, u32 bit, u32 bit_value)
+{
+	register u32 newvalue = *value;
+
+	newvalue = (u32)(newvalue & ~(3ul << (bit * 2)));
+	newvalue = (u32)(newvalue | (bit_value << (bit * 2)));
+
+	writel(newvalue, value);
+}
+
+u32 nx_gpio_get_bit2(u32 value, u32 bit)
+{
+	return (u32)((u32)(value >> (bit * 2)) & 3ul);
+}
+
+int nx_gpio_initialize(void)
+{
+	static int binit;
+	u32 i;
+
+	binit = 0;
+
+	if (binit == 0) {
+		for (i = 0; i < NUMBER_OF_GPIO_MODULE; i++)
+			__g_module_variables[i].pregister = NULL;
+		binit = true;
+	}
+	for (i = 0; i < NUMBER_OF_GPIO_MODULE; i++) {
+		__g_nx_gpio_valid_bit[i] = 0xFFFFFFFF;
+	};
+	return true;
+}
+
+u32 nx_gpio_get_number_of_module(void)
+{
+	return NUMBER_OF_GPIO_MODULE;
+}
+
+u32 nx_gpio_get_size_of_register_set(void)
+{
+	return sizeof(struct nx_gpio_register_set);
+}
+
+void nx_gpio_set_base_address(u32 module_index, void *base_address)
+{
+	__g_module_variables[module_index].pregister =
+		(struct nx_gpio_register_set *)base_address;
+}
+
+void *nx_gpio_get_base_address(u32 module_index)
+{
+	return (void *)__g_module_variables[module_index].pregister;
+}
+
+int nx_gpio_open_module(u32 module_index)
+{
+	register struct nx_gpio_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	writel(0xFFFFFFFF, &pregister->gpiox_slew_disable_default);
+	writel(0xFFFFFFFF, &pregister->gpiox_drv1_disable_default);
+	writel(0xFFFFFFFF, &pregister->gpiox_drv0_disable_default);
+	writel(0xFFFFFFFF, &pregister->gpiox_pullsel_disable_default);
+	writel(0xFFFFFFFF, &pregister->gpiox_pullenb_disable_default);
+	return true;
+}
+
+int nx_gpio_close_module(u32 module_index) { return true; }
+
+int nx_gpio_check_busy(u32 module_index) { return false; }
+
+void nx_gpio_set_pad_function(u32 module_index, u32 bit_number,
+			      u32 padfunc)
+{
+	register struct nx_gpio_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	nx_gpio_set_bit2(&pregister->gpioxaltfn[bit_number / 16],
+			 bit_number % 16, padfunc);
+}
+
+void nx_gpio_set_pad_function32(u32 module_index, u32 msbvalue, u32 lsbvalue)
+{
+	register struct nx_gpio_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	writel(lsbvalue, &pregister->gpioxaltfn[0]);
+	writel(msbvalue, &pregister->gpioxaltfn[1]);
+}
+
+int nx_gpio_get_pad_function(u32 module_index, u32 bit_number)
+{
+	register struct nx_gpio_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	return (int)nx_gpio_get_bit2
+		(readl(&pregister->gpioxaltfn[bit_number / 16]),
+		 bit_number % 16);
+}
+
+void nx_gpio_set_output_enable(u32 module_index, u32 bit_number,
+			       int output_enb)
+{
+	register struct nx_gpio_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	nx_gpio_set_bit(&pregister->gpioxoutenb, bit_number, output_enb);
+}
+
+int nx_gpio_get_detect_enable(u32 module_index, u32 bit_number)
+{
+	register struct nx_gpio_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	return nx_gpio_get_bit(readl(&pregister->gpioxdetenb), bit_number);
+}
+
+u32 nx_gpio_get_detect_enable32(u32 module_index)
+{
+	register struct nx_gpio_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	return readl(&pregister->gpioxdetenb);
+}
+
+void nx_gpio_set_detect_enable(u32 module_index, u32 bit_number,
+			       int detect_enb)
+{
+	register struct nx_gpio_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	nx_gpio_set_bit(&pregister->gpioxdetenb, bit_number, detect_enb);
+}
+
+void nx_gpio_set_detect_enable32(u32 module_index, u32 enable_flag)
+{
+	register struct nx_gpio_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	writel(enable_flag, &pregister->gpioxdetenb);
+}
+
+int nx_gpio_get_output_enable(u32 module_index, u32 bit_number)
+{
+	register struct nx_gpio_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	return nx_gpio_get_bit(readl(&pregister->gpioxoutenb), bit_number);
+}
+
+void nx_gpio_set_output_enable32(u32 module_index, int output_enb)
+{
+	register struct nx_gpio_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	if (output_enb)
+		writel(0xFFFFFFFF, &pregister->gpioxoutenb);
+	else
+		writel(0x0, &pregister->gpioxoutenb);
+}
+
+u32 nx_gpio_get_output_enable32(u32 module_index)
+{
+	register struct nx_gpio_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	return readl(&pregister->gpioxoutenb);
+}
+
+void nx_gpio_set_output_value(u32 module_index, u32 bit_number, int value)
+{
+	register struct nx_gpio_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	nx_gpio_set_bit(&pregister->gpioxout, bit_number, value);
+}
+
+int nx_gpio_get_output_value(u32 module_index, u32 bit_number)
+{
+	register struct nx_gpio_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	return nx_gpio_get_bit(readl(&pregister->gpioxout), bit_number);
+}
+
+void nx_gpio_set_output_value32(u32 module_index, u32 value)
+{
+	register struct nx_gpio_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	writel(value, &pregister->gpioxout);
+}
+
+u32 nx_gpio_get_output_value32(u32 module_index)
+{
+	register struct nx_gpio_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	return readl(&pregister->gpioxout);
+}
+
+int nx_gpio_get_input_value(u32 module_index, u32 bit_number)
+{
+	register struct nx_gpio_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	return nx_gpio_get_bit(readl(&pregister->gpioxpad), bit_number);
+}
+
+void nx_gpio_set_pull_select(u32 module_index, u32 bit_number, int enable)
+{
+	nx_gpio_set_bit(&__g_module_variables[module_index]
+			.pregister->gpiox_pullsel_disable_default,
+			bit_number, true);
+	nx_gpio_set_bit
+		(&__g_module_variables[module_index].pregister->gpiox_pullsel,
+		 bit_number, enable);
+}
+
+void nx_gpio_set_pull_select32(u32 module_index, u32 value)
+{
+	writel(value,
+	       &__g_module_variables[module_index].pregister->gpiox_pullsel);
+}
+
+int nx_gpio_get_pull_select(u32 module_index, u32 bit_number)
+{
+	return nx_gpio_get_bit
+		(__g_module_variables[module_index].pregister->gpiox_pullsel,
+		 bit_number);
+}
+
+u32 nx_gpio_get_pull_select32(u32 module_index)
+{
+	return __g_module_variables[module_index].pregister->gpiox_pullsel;
+}
+
+void nx_gpio_set_pull_mode(u32 module_index, u32 bit_number, u32 mode)
+{
+	nx_gpio_set_bit(&__g_module_variables[module_index]
+			.pregister->gpiox_pullsel_disable_default,
+			bit_number, true);
+	nx_gpio_set_bit(&__g_module_variables[module_index]
+			.pregister->gpiox_pullenb_disable_default,
+			bit_number, true);
+	if (mode == nx_gpio_pull_off) {
+		nx_gpio_set_bit
+		 (&__g_module_variables[module_index].pregister->gpiox_pullenb,
+		 bit_number, false);
+		nx_gpio_set_bit
+		 (&__g_module_variables[module_index].pregister->gpiox_pullsel,
+		 bit_number, false);
+	} else {
+		nx_gpio_set_bit
+		 (&__g_module_variables[module_index].pregister->gpiox_pullsel,
+		 bit_number, (mode & 1 ? true : false));
+		nx_gpio_set_bit
+		 (&__g_module_variables[module_index].pregister->gpiox_pullenb,
+		 bit_number, true);
+	}
+}
+
+void nx_gpio_set_fast_slew(u32 module_index, u32 bit_number,
+			   int enable)
+{
+	register struct nx_gpio_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	nx_gpio_set_bit(&pregister->gpiox_slew, bit_number,
+			(int)(!enable));
+}
+
+void nx_gpio_set_drive_strength(u32 module_index, u32 bit_number,
+				u32 drvstrength)
+{
+	register struct nx_gpio_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	nx_gpio_set_bit(&pregister->gpiox_drv1, bit_number,
+			(int)(((u32)drvstrength >> 0) & 0x1));
+	nx_gpio_set_bit(&pregister->gpiox_drv0, bit_number,
+			(int)(((u32)drvstrength >> 1) & 0x1));
+}
+
+void nx_gpio_set_drive_strength_disable_default(u32 module_index,
+						u32 bit_number, int enable)
+{
+	register struct nx_gpio_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	nx_gpio_set_bit(&pregister->gpiox_drv1_disable_default, bit_number,
+			(int)(enable));
+	nx_gpio_set_bit(&pregister->gpiox_drv0_disable_default, bit_number,
+			(int)(enable));
+}
+
+u32 nx_gpio_get_drive_strength(u32 module_index, u32 bit_number)
+{
+	register struct nx_gpio_register_set *pregister;
+	register u32 retvalue;
+
+	pregister = __g_module_variables[module_index].pregister;
+	retvalue =
+		nx_gpio_get_bit(readl(&pregister->gpiox_drv0), bit_number) << 1;
+	retvalue |=
+		nx_gpio_get_bit(readl(&pregister->gpiox_drv1), bit_number) << 0;
+	return retvalue;
+}
diff --git a/arch/arm/mach-nexell/nx_sec_reg.c b/arch/arm/mach-nexell/nx_sec_reg.c
new file mode 100644
index 0000000..3d3dd9f
--- /dev/null
+++ b/arch/arm/mach-nexell/nx_sec_reg.c
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2016 Nexell
+ * Youngbok, Park <park@nexell.co.kr>
+ */
+
+#include <linux/types.h>
+#include <asm/io.h>
+#include <asm/arch/nexell.h>
+#include <asm/arch/sec_reg.h>
+#include <linux/linkage.h>
+
+#define NEXELL_SMC_BASE			0x82000000
+
+#define NEXELL_SMC_FN(n)		(NEXELL_SMC_BASE +  (n))
+
+#define NEXELL_SMC_SEC_REG_WRITE	NEXELL_SMC_FN(0x0)
+#define NEXELL_SMC_SEC_REG_READ		NEXELL_SMC_FN(0x1)
+
+#define SECURE_ID_SHIFT			8
+
+#define SEC_4K_OFFSET			((4 * 1024) - 1)
+#define SEC_64K_OFFSET			((64 * 1024) - 1)
+
+asmlinkage int __invoke_nexell_fn_smc(u32, u32, u32, u32);
+
+int write_sec_reg_by_id(void __iomem *reg, int val, int id)
+{
+	int ret = 0;
+	u32 off = 0;
+
+	switch (id) {
+	case NEXELL_L2C_SEC_ID:
+	case NEXELL_MIPI_SEC_ID:
+	case NEXELL_TOFF_SEC_ID:
+		off = (u32)reg & SEC_4K_OFFSET;
+		break;
+	case NEXELL_MALI_SEC_ID:
+		off = (u32)reg & SEC_64K_OFFSET;
+		break;
+	}
+	ret = __invoke_nexell_fn_smc(NEXELL_SMC_SEC_REG_WRITE |
+			((1 << SECURE_ID_SHIFT) + id), off, val, 0);
+	return ret;
+}
+
+int read_sec_reg_by_id(void __iomem *reg, int id)
+{
+	int ret = 0;
+	u32 off = 0;
+
+	switch (id) {
+	case NEXELL_L2C_SEC_ID:
+	case NEXELL_MIPI_SEC_ID:
+	case NEXELL_TOFF_SEC_ID:
+		off = (u32)reg & SEC_4K_OFFSET;
+		break;
+	case NEXELL_MALI_SEC_ID:
+		off = (u32)reg & SEC_64K_OFFSET;
+		break;
+	}
+	ret = __invoke_nexell_fn_smc(NEXELL_SMC_SEC_REG_READ |
+			((1 << SECURE_ID_SHIFT) + id), off, 0, 0);
+	return ret;
+}
+
+int write_sec_reg(void __iomem *reg, int val)
+{
+	int ret = 0;
+
+	ret = __invoke_nexell_fn_smc(NEXELL_SMC_SEC_REG_WRITE,
+				     (u32)reg, val, 0);
+	return ret;
+}
+
+int read_sec_reg(void __iomem *reg)
+{
+	int ret = 0;
+
+	ret = __invoke_nexell_fn_smc(NEXELL_SMC_SEC_REG_READ, (u32)reg, 0, 0);
+	return ret;
+}
diff --git a/arch/arm/mach-nexell/reg-call.S b/arch/arm/mach-nexell/reg-call.S
new file mode 100644
index 0000000..5fdf515
--- /dev/null
+++ b/arch/arm/mach-nexell/reg-call.S
@@ -0,0 +1,23 @@
+#include <asm-offsets.h>
+#include <config.h>
+#include <linux/linkage.h>
+
+#define ___asm_opcode_identity32(x) ((x) & 0xFFFFFFFF)
+#define __opcode_to_mem_arm(x) ___opcode_identity32(x)
+#define ___asm_opcode_to_mem_arm(x) ___asm_opcode_identity32(x)
+
+#define ___opcode_identity32(x) ((u32)(x))
+#define ___inst_arm(x) .long x
+#define __inst_arm(x) ___inst_arm(___asm_opcode_to_mem_arm(x))
+
+#define __inst_arm_thumb32(arm_opcode, thumb_opcode) __inst_arm(arm_opcode)
+
+#define __SMC(imm4) __inst_arm_thumb32(                                 \
+        0xE1600070 | (((imm4) & 0xF) << 0),                             \
+        0xF7F08000 | (((imm4) & 0xF) << 16)                             \
+)
+
+ENTRY(__invoke_nexell_fn_smc)
+	__SMC(0)
+	bx      lr
+ENDPROC(__invoke_nexell_fn_smc)
diff --git a/arch/arm/mach-nexell/reset.c b/arch/arm/mach-nexell/reset.c
new file mode 100644
index 0000000..1f732a3
--- /dev/null
+++ b/arch/arm/mach-nexell/reset.c
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2016 Nexell
+ * Youngbok, Park <park@nexell.co.kr>
+ */
+
+/*
+ *FIXME : Not support device tree & reset control driver.
+ *        will remove after support device tree & reset control driver.
+ */
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/nexell.h>
+#include <asm/arch/reset.h>
+
+struct	nx_rstcon_registerset {
+	u32	regrst[(NUMBER_OF_RESET_MODULE_PIN + 31) >> 5];
+};
+
+static struct nx_rstcon_registerset *nx_rstcon =
+			(struct nx_rstcon_registerset *)PHY_BASEADDR_RSTCON;
+
+void nx_rstcon_setrst(u32 rstindex, enum rstcon status)
+{
+	u32 regnum, bitpos, curstat;
+
+	regnum		= rstindex >> 5;
+	curstat		= (u32)readl(&nx_rstcon->regrst[regnum]);
+	bitpos		= rstindex & 0x1f;
+	curstat		&= ~(1UL << bitpos);
+	curstat		|= (status & 0x01) << bitpos;
+	writel(curstat, &nx_rstcon->regrst[regnum]);
+}
diff --git a/arch/arm/mach-nexell/tieoff.c b/arch/arm/mach-nexell/tieoff.c
new file mode 100644
index 0000000..9a89517
--- /dev/null
+++ b/arch/arm/mach-nexell/tieoff.c
@@ -0,0 +1,109 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2016 Nexell
+ * Youngbok, Park <park@nexell.co.kr>
+ */
+
+#include <common.h>
+#include <asm/arch/nexell.h>
+#include <asm/arch/clk.h>
+#include <asm/arch/reset.h>
+#include <asm/arch/nx_gpio.h>
+#include <asm/arch/tieoff.h>
+#include <asm/arch/sec_reg.h>
+
+#define	NX_PIN_FN_SIZE	4
+#define TIEOFF_REG_NUM 33
+
+struct	nx_tieoff_registerset {
+	u32	tieoffreg[TIEOFF_REG_NUM];
+};
+
+static struct nx_tieoff_registerset *nx_tieoff = (void *)PHY_BASEADDR_TIEOFF;
+
+static int tieoff_readl(void __iomem *reg)
+{
+#ifdef CONFIG_ARCH_S5P4418
+		return read_sec_reg_by_id(reg, NEXELL_TOFF_SEC_ID);
+#else
+		return readl(reg);
+#endif
+}
+
+static int  tieoff_writetl(void __iomem *reg, int val)
+{
+#ifdef CONFIG_ARCH_S5P4418
+		return write_sec_reg_by_id(reg, val, NEXELL_TOFF_SEC_ID);
+#else
+		return writel(val, reg);
+#endif
+}
+
+void nx_tieoff_set(u32 tieoff_index, u32 tieoff_value)
+{
+	u32 regindex, mask;
+	u32 lsb, msb;
+	u32 regval;
+
+	u32 position;
+	u32 bitwidth;
+
+	position = tieoff_index & 0xffff;
+	bitwidth = (tieoff_index >> 16) & 0xffff;
+
+	regindex	= position >> 5;
+
+	lsb = position & 0x1F;
+	msb = lsb + bitwidth;
+
+	if (msb > 32) {
+		msb &= 0x1F;
+		mask   = ~(0xffffffff << lsb);
+		regval = tieoff_readl(&nx_tieoff->tieoffreg[regindex]) & mask;
+		regval |= ((tieoff_value & ((1UL << bitwidth) - 1)) << lsb);
+		tieoff_writetl(&nx_tieoff->tieoffreg[regindex], regval);
+
+		mask   = (0xffffffff << msb);
+		regval = tieoff_readl(&nx_tieoff->tieoffreg[regindex]) & mask;
+		regval |= ((tieoff_value & ((1UL << bitwidth) - 1)) >> msb);
+		tieoff_writetl(&nx_tieoff->tieoffreg[regindex + 1], regval);
+	} else	{
+		mask	= (0xffffffff << msb) | (~(0xffffffff << lsb));
+		regval = tieoff_readl(&nx_tieoff->tieoffreg[regindex]) & mask;
+		regval	|= ((tieoff_value & ((1UL << bitwidth) - 1)) << lsb);
+		tieoff_writetl(&nx_tieoff->tieoffreg[regindex], regval);
+	}
+}
+
+u32 nx_tieoff_get(u32 tieoff_index)
+{
+	u32 regindex, mask;
+	u32 lsb, msb;
+	u32 regval;
+
+	u32 position;
+	u32 bitwidth;
+
+	position = tieoff_index & 0xffff;
+	bitwidth = (tieoff_index >> 16) & 0xffff;
+
+	regindex = position / 32;
+	lsb = position % 32;
+	msb = lsb + bitwidth;
+
+	if (msb > 32) {
+		msb &= 0x1F;
+		mask   = 0xffffffff << lsb;
+		regval = tieoff_readl(&nx_tieoff->tieoffreg[regindex]) & mask;
+		regval >>= lsb;
+
+		mask   = ~(0xffffffff << msb);
+		regval |= ((tieoff_readl(&nx_tieoff->tieoffreg[regindex + 1])
+					& mask) << (32 - lsb));
+	} else	{
+		mask   = ~(0xffffffff << msb) & (0xffffffff << lsb);
+		regval = tieoff_readl(&nx_tieoff->tieoffreg[regindex]) & mask;
+		regval >>= lsb;
+	}
+	return regval;
+}
diff --git a/arch/arm/mach-nexell/timer.c b/arch/arm/mach-nexell/timer.c
new file mode 100644
index 0000000..f915684
--- /dev/null
+++ b/arch/arm/mach-nexell/timer.c
@@ -0,0 +1,297 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2016 Nexell
+ * Hyunseok, Jung <hsjung@nexell.co.kr>
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/nexell.h>
+#include <asm/arch/clk.h>
+#if defined(CONFIG_ARCH_S5P4418)
+#include <asm/arch/reset.h>
+#endif
+
+#if (CONFIG_TIMER_SYS_TICK_CH > 3)
+#error Not support timer channel. Please use "0~3" channels.
+#endif
+
+/* global variables to save timer count
+ *
+ * Section ".data" must be used because BSS is not available before relocation,
+ * in board_init_f(), respectively! I.e. global variables can not be used!
+ */
+static unsigned long timestamp __attribute__ ((section(".data")));
+static unsigned long lastdec __attribute__ ((section(".data")));
+static int	timerinit __attribute__ ((section(".data")));
+
+/* macro to hw timer tick config */
+static long	TIMER_FREQ  = 1000000;
+static long	TIMER_HZ    = 1000000 / CONFIG_SYS_HZ;
+static long	TIMER_COUNT = 0xFFFFFFFF;
+
+#define	REG_TCFG0			(0x00)
+#define	REG_TCFG1			(0x04)
+#define	REG_TCON			(0x08)
+#define	REG_TCNTB0			(0x0C)
+#define	REG_TCMPB0			(0x10)
+#define	REG_TCNT0			(0x14)
+#define	REG_CSTAT			(0x44)
+
+#define	TCON_BIT_AUTO			(1 << 3)
+#define	TCON_BIT_INVT			(1 << 2)
+#define	TCON_BIT_UP			(1 << 1)
+#define	TCON_BIT_RUN			(1 << 0)
+#define TCFG0_BIT_CH(ch)		((ch) == 0 || (ch) == 1 ? 0 : 8)
+#define TCFG1_BIT_CH(ch)		((ch) * 4)
+#define TCON_BIT_CH(ch)			((ch) ? (ch) * 4  + 4 : 0)
+#define TINT_CH(ch)			(ch)
+#define TINT_CSTAT_BIT_CH(ch)		((ch) + 5)
+#define	TINT_CSTAT_MASK			(0x1F)
+#define TIMER_TCNT_OFFS			(0xC)
+
+void reset_timer_masked(void);
+unsigned long get_timer_masked(void);
+
+/*
+ * Timer HW
+ */
+static inline void timer_clock(void __iomem *base, int ch, int mux, int scl)
+{
+	u32 val = readl(base + REG_TCFG0) & ~(0xFF << TCFG0_BIT_CH(ch));
+
+	writel(val | ((scl - 1) << TCFG0_BIT_CH(ch)), base + REG_TCFG0);
+	val = readl(base + REG_TCFG1) & ~(0xF << TCFG1_BIT_CH(ch));
+	writel(val | (mux << TCFG1_BIT_CH(ch)), base + REG_TCFG1);
+}
+
+static inline void timer_count(void __iomem *base, int ch, unsigned int cnt)
+{
+	writel((cnt - 1), base + REG_TCNTB0 + (TIMER_TCNT_OFFS * ch));
+	writel((cnt - 1), base + REG_TCMPB0 + (TIMER_TCNT_OFFS * ch));
+}
+
+static inline void timer_start(void __iomem *base, int ch)
+{
+	int on = 0;
+	u32 val = readl(base + REG_CSTAT) & ~(TINT_CSTAT_MASK << 5 | 0x1 << ch);
+
+	writel(val | (0x1 << TINT_CSTAT_BIT_CH(ch) | on << ch),
+	       base + REG_CSTAT);
+	val = readl(base + REG_TCON) & ~(0xE << TCON_BIT_CH(ch));
+	writel(val | (TCON_BIT_UP << TCON_BIT_CH(ch)), base + REG_TCON);
+
+	val &= ~(TCON_BIT_UP << TCON_BIT_CH(ch));
+	val |= ((TCON_BIT_AUTO | TCON_BIT_RUN) << TCON_BIT_CH(ch));
+	writel(val, base + REG_TCON);
+	dmb();
+}
+
+static inline void timer_stop(void __iomem *base, int ch)
+{
+	int on = 0;
+	u32 val = readl(base + REG_CSTAT) & ~(TINT_CSTAT_MASK << 5 | 0x1 << ch);
+
+	writel(val | (0x1 << TINT_CSTAT_BIT_CH(ch) | on << ch),
+	       base + REG_CSTAT);
+	val = readl(base + REG_TCON) & ~(TCON_BIT_RUN << TCON_BIT_CH(ch));
+	writel(val, base + REG_TCON);
+}
+
+static inline unsigned long timer_read(void __iomem *base, int ch)
+{
+	unsigned long ret;
+
+	ret = TIMER_COUNT - readl(base + REG_TCNT0 + (TIMER_TCNT_OFFS * ch));
+	return ret;
+}
+
+int timer_init(void)
+{
+	struct clk *clk = NULL;
+	char name[16] = "pclk";
+	int ch = CONFIG_TIMER_SYS_TICK_CH;
+	unsigned long rate, tclk = 0;
+	unsigned long mout, thz, cmp = -1UL;
+	int tcnt, tscl = 0, tmux = 0;
+	int mux = 0, scl = 0;
+	void __iomem *base = (void __iomem *)PHY_BASEADDR_TIMER;
+
+	if (timerinit)
+		return 0;
+
+	/* get with PCLK */
+	clk  = clk_get(name);
+	rate = clk_get_rate(clk);
+	for (mux = 0; mux < 5; mux++) {
+		mout = rate / (1 << mux), scl = mout / TIMER_FREQ,
+		thz = mout / scl;
+		if (!(mout % TIMER_FREQ) && 256 > scl) {
+			tclk = thz, tmux = mux, tscl = scl;
+			break;
+		}
+		if (scl > 256)
+			continue;
+		if (abs(thz - TIMER_FREQ) >= cmp)
+			continue;
+		tclk = thz, tmux = mux, tscl = scl;
+		cmp = abs(thz - TIMER_FREQ);
+	}
+	tcnt = tclk;	/* Timer Count := 1 Mhz counting */
+
+	TIMER_FREQ = tcnt;	/* Timer Count := 1 Mhz counting */
+	TIMER_HZ = TIMER_FREQ / CONFIG_SYS_HZ;
+	tcnt = TIMER_COUNT == 0xFFFFFFFF ? TIMER_COUNT + 1 : tcnt;
+
+	timer_stop(base, ch);
+	timer_clock(base, ch, tmux, tscl);
+	timer_count(base, ch, tcnt);
+	timer_start(base, ch);
+
+	reset_timer_masked();
+	timerinit = 1;
+
+	return 0;
+}
+
+void reset_timer(void)
+{
+	reset_timer_masked();
+}
+
+unsigned long get_timer(unsigned long base)
+{
+	long ret;
+	unsigned long time = get_timer_masked();
+	unsigned long hz = TIMER_HZ;
+
+	ret = time / hz - base;
+	return ret;
+}
+
+void set_timer(unsigned long t)
+{
+	timestamp = (unsigned long)t;
+}
+
+void reset_timer_masked(void)
+{
+	void __iomem *base = (void __iomem *)PHY_BASEADDR_TIMER;
+	int ch = CONFIG_TIMER_SYS_TICK_CH;
+
+	/* reset time */
+	/* capure current decrementer value time */
+	lastdec = timer_read(base, ch);
+	/* start "advancing" time stamp from 0 */
+	timestamp = 0;
+}
+
+unsigned long get_timer_masked(void)
+{
+	void __iomem *base = (void __iomem *)PHY_BASEADDR_TIMER;
+	int ch = CONFIG_TIMER_SYS_TICK_CH;
+
+	unsigned long now = timer_read(base, ch); /* current tick value */
+
+	if (now >= lastdec) {			  /* normal mode (non roll) */
+		/* move stamp fordward with absolute diff ticks */
+		timestamp += now - lastdec;
+	} else {
+		/* we have overflow of the count down timer */
+		/* nts = ts + ld + (TLV - now)
+		 * ts=old stamp, ld=time that passed before passing through -1
+		 * (TLV-now) amount of time after passing though -1
+		 * nts = new "advancing time stamp"...
+		 * it could also roll and cause problems.
+		 */
+		timestamp += now + TIMER_COUNT - lastdec;
+	}
+	/* save last */
+	lastdec = now;
+
+	debug("now=%lu, last=%lu, timestamp=%lu\n", now, lastdec, timestamp);
+	return (unsigned long)timestamp;
+}
+
+void __udelay(unsigned long usec)
+{
+	unsigned long tmo, tmp;
+
+	debug("+udelay=%ld\n", usec);
+
+	if (!timerinit)
+		timer_init();
+
+	/* if "big" number, spread normalization to seconds */
+	if (usec >= 1000) {
+		/* start to normalize for usec to ticks per sec */
+		tmo  = usec / 1000;
+		/* find number of "ticks" to wait to achieve target */
+		tmo *= TIMER_FREQ;
+		/* finish normalize. */
+		tmo /= 1000;
+	/* else small number, don't kill it prior to HZ multiply */
+	} else {
+		tmo = usec * TIMER_FREQ;
+		tmo /= (1000 * 1000);
+	}
+
+	tmp = get_timer_masked();	/* get current timestamp */
+	debug("A. tmo=%ld, tmp=%ld\n", tmo, tmp);
+
+	/* if setting this fordward will roll time stamp */
+	if (tmp > (tmo + tmp + 1))
+		/* reset "advancing" timestamp to 0, set lastdec value */
+		reset_timer_masked();
+	else
+		/* set advancing stamp wake up time */
+		tmo += tmp;
+
+	debug("B. tmo=%ld, tmp=%ld\n", tmo, tmp);
+
+	/* loop till event */
+	do {
+		tmp = get_timer_masked();
+	} while (tmo > tmp);
+	debug("-udelay=%ld\n", usec);
+}
+
+void udelay_masked(unsigned long usec)
+{
+	unsigned long tmo, endtime;
+	signed long diff;
+
+	/* if "big" number, spread normalization to seconds */
+	if (usec >= 1000) {
+		/* start to normalize for usec to ticks per sec */
+		tmo = usec / 1000;
+		/* find number of "ticks" to wait to achieve target */
+		tmo *= TIMER_FREQ;
+		/* finish normalize. */
+		tmo /= 1000;
+	} else { /* else small number, don't kill it prior to HZ multiply */
+		tmo = usec * TIMER_FREQ;
+		tmo /= (1000 * 1000);
+	}
+
+	endtime = get_timer_masked() + tmo;
+
+	do {
+		unsigned long now = get_timer_masked();
+
+		diff = endtime - now;
+	} while (diff >= 0);
+}
+
+unsigned long long get_ticks(void)
+{
+	return get_timer_masked();
+}
+
+#if defined(CONFIG_ARCH_S5P4418)
+ulong get_tbclk(void)
+{
+	ulong  tbclk = TIMER_FREQ;
+	return tbclk;
+}
+#endif
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [RFC PATCH v2 03/13] gpio: add nexell driver
  2020-03-28  9:43 [RFC PATCH v2 00/13] arm: add support for SoC S5P4418 Stefan Bosch
  2020-03-28  9:43 ` [RFC PATCH v2 01/13] arm: add mach-nexell (header files) Stefan Bosch
  2020-03-28  9:43 ` [RFC PATCH v2 02/13] arm: add mach-nexell (all files except header files) Stefan Bosch
@ 2020-03-28  9:43 ` Stefan Bosch
  2020-03-28  9:43 ` [RFC PATCH v2 04/13] i2c: " Stefan Bosch
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 21+ messages in thread
From: Stefan Bosch @ 2020-03-28  9:43 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Stefan Bosch <stefan_b@posteo.net>
---

Changes in v2:
- commit "i2c: mmc: add nexell driver (gpio, i2c, mmc, pwm)" splitted
  into separate commits for gpio, i2c, mmc, pwm.
- cosmetic: line "obj-$(CONFIG_NX_GPIO) += nx_gpio.o" in
  drivers/gpio/Makefile moved up.

 drivers/gpio/Kconfig   |   9 ++
 drivers/gpio/Makefile  |   1 +
 drivers/gpio/nx_gpio.c | 252 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 262 insertions(+)
 create mode 100644 drivers/gpio/nx_gpio.c

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 1de6f52..febda89 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -421,4 +421,13 @@ config MT7621_GPIO
 	help
 	  Say yes here to support MediaTek MT7621 compatible GPIOs.
 
+config NX_GPIO
+	bool "Nexell GPIO driver"
+	depends on DM_GPIO
+	help
+	  Support GPIO access on Nexell SoCs. The GPIOs are arranged into
+	  a number of banks (different for each SoC type) each with 32 GPIOs.
+	  The GPIOs for a device are defined in the device tree with one node
+	  for each bank.
+
 endmenu
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 449046b..cb20478 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -64,4 +64,5 @@ obj-$(CONFIG_$(SPL_)PCF8575_GPIO)	+= pcf8575_gpio.o
 obj-$(CONFIG_PM8916_GPIO)	+= pm8916_gpio.o
 obj-$(CONFIG_MT7621_GPIO)	+= mt7621_gpio.o
 obj-$(CONFIG_MSCC_SGPIO)	+= mscc_sgpio.o
+obj-$(CONFIG_NX_GPIO)		+= nx_gpio.o
 obj-$(CONFIG_SIFIVE_GPIO)	+= sifive-gpio.o
diff --git a/drivers/gpio/nx_gpio.c b/drivers/gpio/nx_gpio.c
new file mode 100644
index 0000000..86472f6
--- /dev/null
+++ b/drivers/gpio/nx_gpio.c
@@ -0,0 +1,252 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2016 Nexell
+ * DeokJin, Lee <truevirtue@nexell.co.kr>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <malloc.h>
+#include <fdtdec.h>
+#include <asm/io.h>
+#include <asm/gpio.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct nx_gpio_regs {
+	u32	data;		/* Data register */
+	u32	outputenb;	/* Output Enable register */
+	u32	detmode[2];	/* Detect Mode Register */
+	u32	intenb;		/* Interrupt Enable Register */
+	u32	det;		/* Event Detect Register */
+	u32	pad;		/* Pad Status Register */
+};
+
+struct nx_alive_gpio_regs {
+	u32	pwrgate;	/* Power Gating Register */
+	u32	reserved0[28];	/* Reserved0 */
+	u32	outputenb_reset;/* Alive GPIO Output Enable Reset Register */
+	u32	outputenb;	/* Alive GPIO Output Enable Register */
+	u32	outputenb_read; /* Alive GPIO Output Read Register */
+	u32	reserved1[3];	/* Reserved1 */
+	u32	pad_reset;	/* Alive GPIO Output Reset Register */
+	u32	data;		/* Alive GPIO Output Register */
+	u32	pad_read;	/* Alive GPIO Pad Read Register */
+	u32	reserved2[33];	/* Reserved2 */
+	u32	pad;		/* Alive GPIO Input Value Register */
+};
+
+struct nx_gpio_platdata {
+	void *regs;
+	int gpio_count;
+	const char *bank_name;
+};
+
+static int nx_alive_gpio_is_check(struct udevice *dev)
+{
+	struct nx_gpio_platdata *plat = dev_get_platdata(dev);
+	const char *bank_name = plat->bank_name;
+
+	if (!strcmp(bank_name, "gpio_alv"))
+		return 1;
+
+	return 0;
+}
+
+static int nx_alive_gpio_direction_input(struct udevice *dev, unsigned int pin)
+{
+	struct nx_gpio_platdata *plat = dev_get_platdata(dev);
+	struct nx_alive_gpio_regs *const regs = plat->regs;
+
+	setbits_le32(&regs->outputenb_reset, 1 << pin);
+
+	return 0;
+}
+
+static int nx_alive_gpio_direction_output(struct udevice *dev, unsigned int pin,
+					  int val)
+{
+	struct nx_gpio_platdata *plat = dev_get_platdata(dev);
+	struct nx_alive_gpio_regs *const regs = plat->regs;
+
+	if (val)
+		setbits_le32(&regs->data, 1 << pin);
+	else
+		setbits_le32(&regs->pad_reset, 1 << pin);
+
+	setbits_le32(&regs->outputenb, 1 << pin);
+
+	return 0;
+}
+
+static int nx_alive_gpio_get_value(struct udevice *dev, unsigned int pin)
+{
+	struct nx_gpio_platdata *plat = dev_get_platdata(dev);
+	struct nx_alive_gpio_regs *const regs = plat->regs;
+	unsigned int mask = 1UL << pin;
+	unsigned int value;
+
+	value = (readl(&regs->pad_read) & mask) >> pin;
+
+	return value;
+}
+
+static int nx_alive_gpio_set_value(struct udevice *dev, unsigned int pin,
+				   int val)
+{
+	struct nx_gpio_platdata *plat = dev_get_platdata(dev);
+	struct nx_alive_gpio_regs *const regs = plat->regs;
+
+	if (val)
+		setbits_le32(&regs->data, 1 << pin);
+	else
+		clrbits_le32(&regs->pad_reset, 1 << pin);
+
+	return 0;
+}
+
+static int nx_alive_gpio_get_function(struct udevice *dev, unsigned int pin)
+{
+	struct nx_gpio_platdata *plat = dev_get_platdata(dev);
+	struct nx_alive_gpio_regs *const regs = plat->regs;
+	unsigned int mask = (1UL << pin);
+	unsigned int output;
+
+	output = readl(&regs->outputenb_read) & mask;
+
+	if (output)
+		return GPIOF_OUTPUT;
+	else
+		return GPIOF_INPUT;
+}
+
+static int nx_gpio_direction_input(struct udevice *dev, unsigned int pin)
+{
+	struct nx_gpio_platdata *plat = dev_get_platdata(dev);
+	struct nx_gpio_regs *const regs = plat->regs;
+
+	if (nx_alive_gpio_is_check(dev))
+		return nx_alive_gpio_direction_input(dev, pin);
+
+	clrbits_le32(&regs->outputenb, 1 << pin);
+
+	return 0;
+}
+
+static int nx_gpio_direction_output(struct udevice *dev, unsigned int pin,
+				    int val)
+{
+	struct nx_gpio_platdata *plat = dev_get_platdata(dev);
+	struct nx_gpio_regs *const regs = plat->regs;
+
+	if (nx_alive_gpio_is_check(dev))
+		return nx_alive_gpio_direction_output(dev, pin, val);
+
+	if (val)
+		setbits_le32(&regs->data, 1 << pin);
+	else
+		clrbits_le32(&regs->data, 1 << pin);
+
+	setbits_le32(&regs->outputenb, 1 << pin);
+
+	return 0;
+}
+
+static int nx_gpio_get_value(struct udevice *dev, unsigned int pin)
+{
+	struct nx_gpio_platdata *plat = dev_get_platdata(dev);
+	struct nx_gpio_regs *const regs = plat->regs;
+	unsigned int mask = 1UL << pin;
+	unsigned int value;
+
+	if (nx_alive_gpio_is_check(dev))
+		return nx_alive_gpio_get_value(dev, pin);
+
+	value = (readl(&regs->pad) & mask) >> pin;
+
+	return value;
+}
+
+static int nx_gpio_set_value(struct udevice *dev, unsigned int pin, int val)
+{
+	struct nx_gpio_platdata *plat = dev_get_platdata(dev);
+	struct nx_gpio_regs *const regs = plat->regs;
+
+	if (nx_alive_gpio_is_check(dev))
+		return nx_alive_gpio_set_value(dev, pin, val);
+
+	if (val)
+		setbits_le32(&regs->data, 1 << pin);
+	else
+		clrbits_le32(&regs->data, 1 << pin);
+
+	return 0;
+}
+
+static int nx_gpio_get_function(struct udevice *dev, unsigned int pin)
+{
+	struct nx_gpio_platdata *plat = dev_get_platdata(dev);
+	struct nx_gpio_regs *const regs = plat->regs;
+	unsigned int mask = (1UL << pin);
+	unsigned int output;
+
+	if (nx_alive_gpio_is_check(dev))
+		return nx_alive_gpio_get_function(dev, pin);
+
+	output = readl(&regs->outputenb) & mask;
+
+	if (output)
+		return GPIOF_OUTPUT;
+	else
+		return GPIOF_INPUT;
+}
+
+static int nx_gpio_probe(struct udevice *dev)
+{
+	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+	struct nx_gpio_platdata *plat = dev_get_platdata(dev);
+
+	uc_priv->gpio_count = plat->gpio_count;
+	uc_priv->bank_name = plat->bank_name;
+
+	return 0;
+}
+
+static int nx_gpio_ofdata_to_platdata(struct udevice *dev)
+{
+	struct nx_gpio_platdata *plat = dev_get_platdata(dev);
+
+	plat->regs = map_physmem(devfdt_get_addr(dev),
+				 sizeof(struct nx_gpio_regs),
+				 MAP_NOCACHE);
+	plat->gpio_count = fdtdec_get_int(gd->fdt_blob, dev->node.of_offset,
+					  "nexell,gpio-bank-width", 32);
+	plat->bank_name = fdt_getprop(gd->fdt_blob, dev->node.of_offset,
+				      "gpio-bank-name", NULL);
+
+	return 0;
+}
+
+static const struct dm_gpio_ops nx_gpio_ops = {
+	.direction_input	= nx_gpio_direction_input,
+	.direction_output	= nx_gpio_direction_output,
+	.get_value		= nx_gpio_get_value,
+	.set_value		= nx_gpio_set_value,
+	.get_function		= nx_gpio_get_function,
+};
+
+static const struct udevice_id nx_gpio_ids[] = {
+	{ .compatible = "nexell,nexell-gpio" },
+	{ }
+};
+
+U_BOOT_DRIVER(nx_gpio) = {
+	.name		= "nx_gpio",
+	.id		= UCLASS_GPIO,
+	.of_match	= nx_gpio_ids,
+	.ops		= &nx_gpio_ops,
+	.ofdata_to_platdata = nx_gpio_ofdata_to_platdata,
+	.platdata_auto_alloc_size = sizeof(struct nx_gpio_platdata),
+	.probe		= nx_gpio_probe,
+};
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [RFC PATCH v2 04/13] i2c: add nexell driver
  2020-03-28  9:43 [RFC PATCH v2 00/13] arm: add support for SoC S5P4418 Stefan Bosch
                   ` (2 preceding siblings ...)
  2020-03-28  9:43 ` [RFC PATCH v2 03/13] gpio: add nexell driver Stefan Bosch
@ 2020-03-28  9:43 ` Stefan Bosch
  2020-04-08  4:08   ` Heiko Schocher
  2020-03-28  9:43 ` [RFC PATCH v2 05/13] mmc: " Stefan Bosch
                   ` (8 subsequent siblings)
  12 siblings, 1 reply; 21+ messages in thread
From: Stefan Bosch @ 2020-03-28  9:43 UTC (permalink / raw)
  To: u-boot

Changes in relation to FriendlyARM's U-Boot nanopi2-v2016.01:
- i2c/nx_i2c.c: Some adaptions mainly because of changes in
  "struct udevice".
- several Bugfixes in nx_i2c.c.
- the driver has been for s5p6818 only. Code extended appropriately
  in order s5p4418 is also working.
- "probe_chip" added.

Signed-off-by: Stefan Bosch <stefan_b@posteo.net>
---

Changes in v2:
- commit "i2c: mmc: add nexell driver (gpio, i2c, mmc, pwm)" splitted
  into separate commits for gpio, i2c, mmc, pwm.
- several Bugfixes in nx_i2c.c.
- the i2c-driver has been for s5p6818 only. Code extended approriately
  in order s5p4418 is also working.
- "probe_chip" added to the i2c-driver.
- doc/device-tree-bindings/i2c/nx_i2c.txt added.

 doc/device-tree-bindings/i2c/nx_i2c.txt |  28 ++
 drivers/i2c/Kconfig                     |   9 +
 drivers/i2c/Makefile                    |   1 +
 drivers/i2c/nx_i2c.c                    | 649 ++++++++++++++++++++++++++++++++
 4 files changed, 687 insertions(+)
 create mode 100644 doc/device-tree-bindings/i2c/nx_i2c.txt
 create mode 100644 drivers/i2c/nx_i2c.c

diff --git a/doc/device-tree-bindings/i2c/nx_i2c.txt b/doc/device-tree-bindings/i2c/nx_i2c.txt
new file mode 100644
index 0000000..9f3abe7
--- /dev/null
+++ b/doc/device-tree-bindings/i2c/nx_i2c.txt
@@ -0,0 +1,28 @@
+I2C controller embedded in Nexell's/Samsung's SoC S5P4418 and S5P6818
+
+Driver:
+- drivers/i2c/nx_i2c.c
+
+Required properties:
+- #address-cells = <1>;
+- #size-cells = <0>;
+- compatible = "nexell,s5pxx18-i2c";
+- reg = <i2c_base 0x100>;
+        Where i2c_base has to be the base address of the i2c-register set.
+        I2C0: 0xc00a4000
+        I2C1: 0xc00a5000
+        I2C2: 0xc00a6000
+
+Optional properties:
+- clock-frequency: Desired I2C bus frequency in Hz, default value is 100000.
+- i2c-sda-delay-ns (S5P6818 only): SDA delay in ns, default value is 0.
+- Child nodes conforming to i2c bus binding.
+
+Example:
+	i2c0:i2c at c00a4000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "nexell,s5pxx18-i2c";
+		reg = <0xc00a4000 0x100>;
+		clock-frequency = <400000>;
+	};
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index 03d2fed..2cd0ed3 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -317,6 +317,15 @@ config SYS_MXC_I2C8_SLAVE
 	 MXC I2C8 Slave
 endif
 
+config SYS_I2C_NEXELL
+	bool "Nexell I2C driver"
+	depends on DM_I2C
+	help
+	  Add support for the Nexell I2C driver. This is used with various
+	  Nexell parts such as S5Pxx18 series SoCs. All chips
+	  have several I2C ports and all are provided, controlled by the
+	  device tree.
+
 config SYS_I2C_OMAP24XX
 	bool "TI OMAP2+ I2C driver"
 	depends on ARCH_OMAP2PLUS || ARCH_K3
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index f5a471f..64b8ead 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_SYS_I2C_LPC32XX) += lpc32xx_i2c.o
 obj-$(CONFIG_SYS_I2C_MESON) += meson_i2c.o
 obj-$(CONFIG_SYS_I2C_MVTWSI) += mvtwsi.o
 obj-$(CONFIG_SYS_I2C_MXC) += mxc_i2c.o
+obj-$(CONFIG_SYS_I2C_NEXELL) += nx_i2c.o
 obj-$(CONFIG_SYS_I2C_OMAP24XX) += omap24xx_i2c.o
 obj-$(CONFIG_SYS_I2C_RCAR_I2C) += rcar_i2c.o
 obj-$(CONFIG_SYS_I2C_RCAR_IIC) += rcar_iic.o
diff --git a/drivers/i2c/nx_i2c.c b/drivers/i2c/nx_i2c.c
new file mode 100644
index 0000000..9bcf1f2
--- /dev/null
+++ b/drivers/i2c/nx_i2c.c
@@ -0,0 +1,649 @@
+#include <common.h>
+#include <errno.h>
+#include <dm.h>
+#include <i2c.h>
+#include <asm/arch/nexell.h>
+#include <asm/arch/reset.h>
+#include <asm/arch/clk.h>
+#include <asm/arch/nx_gpio.h>
+
+#define I2C_WRITE       0
+#define I2C_READ        1
+
+#define I2CSTAT_MTM     0xC0    /* Master Transmit Mode */
+#define I2CSTAT_MRM     0x80    /* Master Receive Mode */
+#define I2CSTAT_BSY     0x20    /* Read: Bus Busy */
+#define I2CSTAT_SS      0x20    /* Write: START (1) / STOP (0) */
+#define I2CSTAT_RXTXEN  0x10    /* Rx/Tx enable */
+#define I2CSTAT_ABT	0x08	/* Arbitration bit */
+#define I2CSTAT_NACK    0x01    /* Nack bit */
+#define I2CCON_IRCLR    0x100   /* Interrupt Clear bit  */
+#define I2CCON_ACKGEN   0x80    /* Acknowledge generation */
+#define I2CCON_IRENB	0x20	/* Interrupt Enable bit  */
+#define I2CCON_IRPND    0x10    /* Interrupt pending bit */
+
+#ifdef CONFIG_ARCH_S5P6818
+#define I2CLC_FILTER	0x04	/* SDA filter on */
+#else
+#define STOPCON_CLR	0x01	/* Clock Line Release */
+#define STOPCON_DLR	0x02	/* Data Line Release */
+#define STOPCON_NAG	0x04	/* not-ackn. generation and data shift cont. */
+#endif
+
+#define I2C_TIMEOUT_MS	10      /* 10 ms */
+
+#define I2C_M_NOSTOP	0x100
+
+#define MAX_I2C_NUM 3
+
+#define DEFAULT_SPEED   100000  /* default I2C speed [Hz] */
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct nx_i2c_regs {
+	uint     iiccon;
+	uint     iicstat;
+	uint     iicadd;
+	uint     iicds;
+#ifdef CONFIG_ARCH_S5P6818
+	/* S5P6818: Offset 0x10 is Line Control Register (SDA-delay, Filter) */
+	uint     iiclc;
+#else
+	/* S5P4418: Offset 0x10 is Stop Control Register */
+	uint     iicstopcon;
+#endif
+};
+
+struct nx_i2c_bus {
+	uint bus_num;
+	struct nx_i2c_regs *regs;
+	uint speed;
+	uint target_speed;
+#ifdef CONFIG_ARCH_S5P6818
+	uint sda_delay;
+#else
+	/* setup time for Stop condition [us] */
+	uint tsu_stop;
+#endif
+};
+
+/* s5pxx18 i2c must be reset before enabled */
+static void i2c_reset(int ch)
+{
+	int rst_id = RESET_ID_I2C0 + ch;
+
+	nx_rstcon_setrst(rst_id, 0);
+	nx_rstcon_setrst(rst_id, 1);
+}
+
+/* FIXME : this func will be removed after reset dm driver ported.
+ * set mmc pad alternative func.
+ */
+static void set_i2c_pad_func(uint bus_num)
+{
+	switch (bus_num) {
+	case 0:
+		nx_gpio_set_pad_function(3, 2, 1);
+		nx_gpio_set_pad_function(3, 3, 1);
+		break;
+	case 1:
+		nx_gpio_set_pad_function(3, 4, 1);
+		nx_gpio_set_pad_function(3, 5, 1);
+		break;
+	case 2:
+		nx_gpio_set_pad_function(3, 6, 1);
+		nx_gpio_set_pad_function(3, 7, 1);
+		break;
+	}
+}
+
+static uint i2c_get_clkrate(struct nx_i2c_bus *bus)
+{
+	struct clk *clk;
+	int index = bus->bus_num;
+	char name[50] = {0, };
+
+	sprintf(name, "%s.%d", DEV_NAME_I2C, index);
+	clk = clk_get((const char *)name);
+	if (!clk)
+		return -1;
+
+	return clk_get_rate(clk);
+}
+
+static uint i2c_set_clk(struct nx_i2c_bus *bus, uint enb)
+{
+	struct clk *clk;
+	char name[50];
+
+	sprintf(name, "%s.%d", DEV_NAME_I2C, bus->bus_num);
+	clk = clk_get((const char *)name);
+	if (!clk) {
+		debug("%s(): clk_get(%s) error!\n",
+		      __func__, (const char *)name);
+		return -EINVAL;
+	}
+
+	if (enb) {
+		clk_disable(clk);
+		clk_enable(clk);
+	} else {
+		clk_disable(clk);
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_ARCH_S5P6818
+/* Set SDA line delay, not available at S5P4418 */
+static int nx_i2c_set_sda_delay(struct nx_i2c_bus *bus)
+{
+	struct nx_i2c_regs *i2c = bus->regs;
+	uint pclk = 0;
+	uint t_pclk = 0;
+	uint delay = 0;
+
+	/* get input clock of the I2C-controller */
+	pclk = i2c_get_clkrate(bus);
+
+	if (bus->sda_delay) {
+		/* t_pclk = period time of one pclk [ns] */
+		t_pclk = DIV_ROUND_UP(1000, pclk / 1000000);
+		/* delay = number of pclks required for sda_delay [ns] */
+		delay = DIV_ROUND_UP(bus->sda_delay, t_pclk);
+		/* delay = register value (step of 5 clocks) */
+		delay = DIV_ROUND_UP(delay, 5);
+		/* max. possible register value = 3 */
+		if (delay > 3) {
+			delay = 3;
+			debug("%s(): sda-delay des.: %dns, sat. to max.: %dns (granularity: %dns)\n",
+			      __func__, bus->sda_delay, t_pclk * delay * 5,
+			      t_pclk * 5);
+		} else {
+			debug("%s(): sda-delay des.: %dns, act.: %dns (granularity: %dns)\n",
+			      __func__, bus->sda_delay, t_pclk * delay * 5,
+			      t_pclk * 5);
+		}
+
+		delay |= I2CLC_FILTER;
+	} else {
+		delay = 0;
+		debug("%s(): sda-delay = 0\n", __func__);
+	}
+
+	delay &= 0x7;
+	writel(delay, &i2c->iiclc);
+
+	return 0;
+}
+#endif
+
+static int nx_i2c_set_bus_speed(struct udevice *dev, uint speed)
+{
+	struct nx_i2c_bus *bus = dev_get_priv(dev);
+	struct nx_i2c_regs *i2c = bus->regs;
+	unsigned long pclk, pres = 16, div;
+
+	if (i2c_set_clk(bus, 1))
+		return -EINVAL;
+
+	/* get input clock of the I2C-controller */
+	pclk = i2c_get_clkrate(bus);
+
+	/* calculate prescaler and divisor values */
+	if ((pclk / pres / (16 + 1)) > speed)
+		/* set prescaler to 256 */
+		pres = 256;
+
+	div = 0;
+	/* actual divider = div + 1 */
+	while ((pclk / pres / (div + 1)) > speed)
+		div++;
+
+	if (div > 0xF) {
+		debug("%s(): pres==%ld, div==0x%lx is saturated to 0xF !)\n",
+		      __func__, pres, div);
+		div = 0xF;
+	} else {
+		debug("%s(): pres==%ld, div==0x%lx)\n", __func__, pres, div);
+	}
+
+	/* set prescaler, divisor according to pclk, also set ACKGEN, IRQ */
+	writel((div & 0x0F) | ((pres == 256) ? 0x40 : 0), &i2c->iiccon);
+
+	/* init to SLAVE REVEIVE and set slaveaddr */
+	writel(0, &i2c->iicstat);
+	writel(0x00, &i2c->iicadd);
+
+	/* program Master Transmit (and implicit STOP) */
+	writel(I2CSTAT_MTM | I2CSTAT_RXTXEN, &i2c->iicstat);
+
+	/* calculate actual I2C speed [Hz] */
+	bus->speed = pclk / ((div + 1) * pres);
+	debug("%s(): speed des.: %dHz, act.: %dHz\n",
+	      __func__, speed, bus->speed);
+
+#ifdef CONFIG_ARCH_S5P6818
+	nx_i2c_set_sda_delay(bus);
+#else
+	/* setup time for Stop condition [us], min. 4us @ 100kHz I2C-clock */
+	bus->tsu_stop = DIV_ROUND_UP(400, bus->speed / 1000);
+#endif
+	if (i2c_set_clk(bus, 0))
+		return -EINVAL;
+	return 0;
+}
+
+static void i2c_process_node(struct udevice *dev)
+{
+	struct nx_i2c_bus *bus = dev_get_priv(dev);
+	const void *blob = gd->fdt_blob;
+
+	int node;
+
+	node = dev->node.of_offset;
+
+	bus->target_speed = fdtdec_get_int(blob, node,
+					   "clock-frequency", DEFAULT_SPEED);
+
+#ifdef CONFIG_ARCH_S5P6818
+	bus->sda_delay = fdtdec_get_int(blob, node, "i2c-sda-delay-ns", 0);
+#endif
+}
+
+static int nx_i2c_probe(struct udevice *dev)
+{
+	struct nx_i2c_bus *bus = dev_get_priv(dev);
+	fdt_addr_t addr;
+
+	/* get regs = i2c base address */
+	addr = devfdt_get_addr(dev);
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
+	bus->regs = (struct nx_i2c_regs *)addr;
+
+	bus->bus_num = dev->seq;
+
+	/* i2c node parsing */
+	i2c_process_node(dev);
+	if (!bus->target_speed)
+		return -ENODEV;
+
+	/* reset */
+	i2c_reset(bus->bus_num);
+	/* gpio pad */
+	set_i2c_pad_func(bus->bus_num);
+	return 0;
+}
+
+/* i2c bus busy check */
+static int i2c_is_busy(struct nx_i2c_regs *i2c)
+{
+	ulong start_time;
+
+	start_time = get_timer(0);
+	while (readl(&i2c->iicstat) & I2CSTAT_BSY) {
+		if (get_timer(start_time) > I2C_TIMEOUT_MS) {
+			debug("Timeout\n");
+			return -EBUSY;
+		}
+	}
+	return 0;
+}
+
+/* irq enable/disable functions */
+static void i2c_enable_irq(struct nx_i2c_regs *i2c)
+{
+	unsigned int reg;
+
+	reg = readl(&i2c->iiccon);
+	reg |= I2CCON_IRENB;
+	writel(reg, &i2c->iiccon);
+}
+
+/* irq clear function */
+static void i2c_clear_irq(struct nx_i2c_regs *i2c)
+{
+	unsigned int reg;
+
+	reg = readl(&i2c->iiccon);
+	/* reset interrupt pending flag */
+	reg &= ~(I2CCON_IRPND);
+	/*
+	 * Interrupt must also be cleared!
+	 * Otherwise linux boot may hang after:
+	 *     [    0.436000] NetLabel:  unlabeled traffic allowed by default
+	 * Next would be:
+	 *     [    0.442000] clocksource: Switched to clocksource source timer
+	 */
+	reg |= I2CCON_IRCLR;
+	writel(reg, &i2c->iiccon);
+}
+
+/* ack enable functions */
+static void i2c_enable_ack(struct nx_i2c_regs *i2c)
+{
+	unsigned int reg;
+
+	reg = readl(&i2c->iiccon);
+	reg |= I2CCON_ACKGEN;
+	writel(reg, &i2c->iiccon);
+}
+
+static void i2c_send_stop(struct nx_i2c_bus *bus)
+{
+	struct nx_i2c_regs *i2c = bus->regs;
+#ifdef CONFIG_ARCH_S5P6818
+	unsigned int reg;
+
+	reg = readl(&i2c->iicstat);
+	reg |= I2CSTAT_MRM | I2CSTAT_RXTXEN;
+	reg &= (~I2CSTAT_SS);
+
+	writel(reg, &i2c->iicstat);
+	i2c_clear_irq(i2c);
+
+#else  /* S5P4418 */
+	writel(STOPCON_NAG, &i2c->iicstopcon);
+
+	i2c_clear_irq(i2c);
+
+	/*
+	 * Clock Line Release --> SDC changes from Low to High and
+	 * SDA from High to Low
+	 */
+	writel(STOPCON_CLR, &i2c->iicstopcon);
+
+	/* Hold SDA Low (Setup Time for Stop condition) */
+	udelay(bus->tsu_stop);
+
+	i2c_clear_irq(i2c);
+
+	/* Master Receive Mode Stop --> SDA becomes High */
+	writel(I2CSTAT_MRM, &i2c->iicstat);
+#endif
+}
+
+static int wait_for_xfer(struct nx_i2c_regs *i2c)
+{
+	unsigned long start_time = get_timer(0);
+
+	do {
+		if (readl(&i2c->iiccon) & I2CCON_IRPND)
+			/* return -EREMOTEIO if not Acknowledged, otherwise 0 */
+			return (readl(&i2c->iicstat) & I2CSTAT_NACK) ?
+				-EREMOTEIO : 0;
+	} while (get_timer(start_time) < I2C_TIMEOUT_MS);
+
+	return -ETIMEDOUT;
+}
+
+static int i2c_transfer(struct nx_i2c_regs *i2c,
+			uchar cmd_type,
+			uchar chip_addr,
+			uchar addr[],
+			uchar addr_len,
+			uchar data[],
+			unsigned short data_len,
+			uint seq)
+{
+	uint status;
+	int i = 0, result;
+
+	/* Note: data_len = 0 is supported for "probe_chip" */
+
+	i2c_enable_irq(i2c);
+	i2c_enable_ack(i2c);
+
+	/* Get the slave chip address going */
+	/* Enable Rx/Tx */
+	writel(I2CSTAT_RXTXEN, &i2c->iicstat);
+
+	writel(chip_addr, &i2c->iicds);
+	status = I2CSTAT_RXTXEN | I2CSTAT_SS;
+	if (cmd_type == I2C_WRITE || (addr && addr_len))
+		status |= I2CSTAT_MTM;
+	else
+		status |= I2CSTAT_MRM;
+
+	writel(status, &i2c->iicstat);
+	if (seq)
+		i2c_clear_irq(i2c);
+
+	/* Wait for chip address to transmit. */
+	result = wait_for_xfer(i2c);
+	if (result) {
+		debug("%s: transmitting chip address failed\n", __func__);
+		goto bailout;
+	}
+
+	/* If register address needs to be transmitted - do it now. */
+	if (addr && addr_len) {  /* register addr */
+		while ((i < addr_len) && !result) {
+			writel(addr[i++], &i2c->iicds);
+			i2c_clear_irq(i2c);
+			result = wait_for_xfer(i2c);
+		}
+
+		i = 0;
+		if (result) {
+			debug("%s: transmitting register address failed\n",
+			      __func__);
+			goto bailout;
+		}
+	}
+
+	switch (cmd_type) {
+	case I2C_WRITE:
+		while ((i < data_len) && !result) {
+			writel(data[i++], &i2c->iicds);
+			i2c_clear_irq(i2c);
+			result = wait_for_xfer(i2c);
+		}
+		break;
+	case I2C_READ:
+		if (addr && addr_len) {
+			/*
+			 * Register address has been sent, now send slave chip
+			 * address again to start the actual read transaction.
+			 */
+			writel(chip_addr, &i2c->iicds);
+
+			/* Generate a re-START. */
+			writel(I2CSTAT_MRM | I2CSTAT_RXTXEN |
+			       I2CSTAT_SS, &i2c->iicstat);
+			i2c_clear_irq(i2c);
+			result = wait_for_xfer(i2c);
+			if (result) {
+				debug("%s: I2C_READ: sending chip addr. failed\n",
+				      __func__);
+				goto bailout;
+			}
+		}
+
+		while ((i < data_len) && !result) {
+			/* disable ACK for final READ */
+			if (i == data_len - 1)
+				clrbits_le32(&i2c->iiccon, I2CCON_ACKGEN);
+
+			i2c_clear_irq(i2c);
+			result = wait_for_xfer(i2c);
+			data[i++] = readb(&i2c->iicds);
+		}
+
+		if (result == -EREMOTEIO)
+			 /* Not Acknowledged --> normal terminated read. */
+			result = 0;
+		else if (result == -ETIMEDOUT)
+			debug("%s: I2C_READ: time out\n", __func__);
+		else
+			debug("%s: I2C_READ: read not terminated with NACK\n",
+			      __func__);
+		break;
+
+	default:
+		debug("%s: bad call\n", __func__);
+		result = -EINVAL;
+		break;
+	}
+
+bailout:
+	return result;
+}
+
+static int nx_i2c_read(struct udevice *dev, uchar chip_addr, uint addr,
+		       uint alen, uchar *buffer, uint len, uint seq)
+{
+	struct nx_i2c_bus *i2c;
+	uchar xaddr[4];
+	int ret;
+
+	i2c = dev_get_priv(dev);
+	if (!i2c)
+		return -EFAULT;
+
+	if (alen > 4) {
+		debug("I2C read: addr len %d not supported\n", alen);
+		return -EADDRNOTAVAIL;
+	}
+
+	if (alen > 0)
+		xaddr[0] = (addr >> 24) & 0xFF;
+
+	if (alen > 0) {
+		xaddr[0] = (addr >> 24) & 0xFF;
+		xaddr[1] = (addr >> 16) & 0xFF;
+		xaddr[2] = (addr >> 8) & 0xFF;
+		xaddr[3] = addr & 0xFF;
+	}
+
+	ret = i2c_transfer(i2c->regs, I2C_READ, chip_addr << 1,
+			   &xaddr[4 - alen], alen, buffer, len, seq);
+
+	if (ret) {
+		debug("I2C read failed %d\n", ret);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int nx_i2c_write(struct udevice *dev, uchar chip_addr, uint addr,
+			uint alen, uchar *buffer, uint len, uint seq)
+{
+	struct nx_i2c_bus *i2c;
+	uchar xaddr[4];
+	int ret;
+
+	i2c = dev_get_priv(dev);
+	if (!i2c)
+		return -EFAULT;
+
+	if (alen > 4) {
+		debug("I2C write: addr len %d not supported\n", alen);
+		return -EINVAL;
+	}
+
+	if (alen > 0) {
+		xaddr[0] = (addr >> 24) & 0xFF;
+		xaddr[1] = (addr >> 16) & 0xFF;
+		xaddr[2] = (addr >> 8) & 0xFF;
+		xaddr[3] = addr & 0xFF;
+	}
+
+	ret = i2c_transfer(i2c->regs, I2C_WRITE, chip_addr << 1,
+			   &xaddr[4 - alen], alen, buffer, len, seq);
+	if (ret) {
+		debug("I2C write failed %d\n", ret);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int nx_i2c_xfer(struct udevice *dev, struct i2c_msg *msg, int nmsgs)
+{
+	struct nx_i2c_bus *bus = dev_get_priv(dev);
+	struct nx_i2c_regs *i2c = bus->regs;
+	int ret;
+	int i;
+
+	/* The power loss by the clock, only during on/off. */
+	ret = i2c_set_clk(bus, 1);
+
+	if (!ret)
+		/* Bus State(Busy) check  */
+		ret = i2c_is_busy(i2c);
+	if (!ret) {
+		for (i = 0; i < nmsgs; msg++, i++) {
+			if (msg->flags & I2C_M_RD) {
+				ret = nx_i2c_read(dev, msg->addr, 0, 0,
+						  msg->buf, msg->len, i);
+			} else {
+				ret = nx_i2c_write(dev, msg->addr, 0, 0,
+						   msg->buf, msg->len, i);
+			}
+
+			if (ret) {
+				debug("i2c_xfer: error sending\n");
+				ret = -EREMOTEIO;
+			}
+		}
+
+		i2c_send_stop(bus);
+		if (i2c_set_clk(bus, 0))
+			ret = -EINVAL;
+	}
+
+	return ret;
+};
+
+static int nx_i2c_probe_chip(struct udevice *dev, u32 chip_addr,
+			     u32 chip_flags)
+{
+	int ret;
+	struct nx_i2c_bus *bus = dev_get_priv(dev);
+
+	ret = i2c_set_clk(bus, 1);
+
+	if (!ret) {
+		/*
+		 * Send Chip Address only
+		 * --> I2C transfer with data length and address length = 0.
+		 * If there is a Slave, i2c_transfer() returns 0 (acknowledge
+		 * transfer).
+		 * I2C_WRITE must be used in order Master Transmit Mode is
+		 * selected. Otherwise (in Master Receive Mode, I2C_READ)
+		 * sending the stop condition below is not working (SDA does
+		 * not transit to High).
+		 */
+		ret = i2c_transfer(bus->regs, I2C_WRITE, (uchar)chip_addr << 1,
+				   NULL, 0, NULL, 0, 0);
+
+		i2c_send_stop(bus);
+		if (i2c_set_clk(bus, 0))
+			ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static const struct dm_i2c_ops nx_i2c_ops = {
+	.xfer		= nx_i2c_xfer,
+	.probe_chip	= nx_i2c_probe_chip,
+	.set_bus_speed	= nx_i2c_set_bus_speed,
+};
+
+static const struct udevice_id nx_i2c_ids[] = {
+	{ .compatible = "nexell,s5pxx18-i2c" },
+	{ }
+};
+
+U_BOOT_DRIVER(i2c_nexell) = {
+	.name		= "i2c_nexell",
+	.id		= UCLASS_I2C,
+	.of_match	= nx_i2c_ids,
+	.probe		= nx_i2c_probe,
+	.priv_auto_alloc_size	= sizeof(struct nx_i2c_bus),
+	.ops		= &nx_i2c_ops,
+};
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [RFC PATCH v2 05/13] mmc: add nexell driver
  2020-03-28  9:43 [RFC PATCH v2 00/13] arm: add support for SoC S5P4418 Stefan Bosch
                   ` (3 preceding siblings ...)
  2020-03-28  9:43 ` [RFC PATCH v2 04/13] i2c: " Stefan Bosch
@ 2020-03-28  9:43 ` Stefan Bosch
  2020-04-02 11:03   ` Jaehoon Chung
  2020-03-28  9:43 ` [RFC PATCH v2 06/13] pwm: add driver for nexell Stefan Bosch
                   ` (7 subsequent siblings)
  12 siblings, 1 reply; 21+ messages in thread
From: Stefan Bosch @ 2020-03-28  9:43 UTC (permalink / raw)
  To: u-boot

Changes in relation to FriendlyARM's U-Boot nanopi2-v2016.01:
- mmc: nexell_dw_mmc.c changed to nexell_dw_mmc_dm.c (switched to DM).

Signed-off-by: Stefan Bosch <stefan_b@posteo.net>
---

Changes in v2:
- commit "i2c: mmc: add nexell driver (gpio, i2c, mmc, pwm)" splitted
  into separate commits for gpio, i2c, mmc, pwm.

 drivers/mmc/Kconfig            |   6 +
 drivers/mmc/Makefile           |   1 +
 drivers/mmc/nexell_dw_mmc_dm.c | 350 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 357 insertions(+)
 create mode 100644 drivers/mmc/nexell_dw_mmc_dm.c

diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 2f0eedc..bb8e7c0 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -253,6 +253,12 @@ config MMC_DW_SNPS
 	  This selects support for Synopsys DesignWare Memory Card Interface driver
 	  extensions used in various Synopsys ARC devboards.
 
+config NEXELL_DWMMC
+	bool "Nexell SD/MMC controller support"
+	depends on ARCH_NEXELL
+	depends on MMC_DW
+	default y
+
 config MMC_MESON_GX
 	bool "Meson GX EMMC controller support"
 	depends on DM_MMC && BLK && ARCH_MESON
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 9c1f8e5..a7b5a7b 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_SH_MMCIF) += sh_mmcif.o
 obj-$(CONFIG_SH_SDHI) += sh_sdhi.o
 obj-$(CONFIG_STM32_SDMMC2) += stm32_sdmmc2.o
 obj-$(CONFIG_JZ47XX_MMC) += jz_mmc.o
+obj-$(CONFIG_NEXELL_DWMMC) += nexell_dw_mmc_dm.o
 
 # SDHCI
 obj-$(CONFIG_MMC_SDHCI)			+= sdhci.o
diff --git a/drivers/mmc/nexell_dw_mmc_dm.c b/drivers/mmc/nexell_dw_mmc_dm.c
new file mode 100644
index 0000000..b06b60d
--- /dev/null
+++ b/drivers/mmc/nexell_dw_mmc_dm.c
@@ -0,0 +1,350 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2016 Nexell
+ * Youngbok, Park <park@nexell.co.kr>
+ *
+ * (C) Copyright 2019 Stefan Bosch <stefan_b@posteo.net>
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <dt-structs.h>
+#include <dwmmc.h>
+#include <syscon.h>
+#include <asm/gpio.h>
+#include <asm/arch/nx_gpio.h>
+#include <asm/arch/reset.h>
+
+#define DWMCI_CLKSEL			0x09C
+#define DWMCI_SHIFT_0			0x0
+#define DWMCI_SHIFT_1			0x1
+#define DWMCI_SHIFT_2			0x2
+#define DWMCI_SHIFT_3			0x3
+#define DWMCI_SET_SAMPLE_CLK(x)	(x)
+#define DWMCI_SET_DRV_CLK(x)	((x) << 16)
+#define DWMCI_SET_DIV_RATIO(x)	((x) << 24)
+#define DWMCI_CLKCTRL			0x114
+#define NX_MMC_CLK_DELAY(x, y, a, b)	((((x) & 0xFF) << 0) |\
+					(((y) & 0x03) << 16) |\
+					(((a) & 0xFF) << 8)  |\
+					(((b) & 0x03) << 24))
+
+struct nexell_mmc_plat {
+	struct mmc_config cfg;
+	struct mmc mmc;
+};
+
+struct nexell_dwmmc_priv {
+	struct clk *clk;
+	struct dwmci_host host;
+	int fifo_size;
+	bool fifo_mode;
+	int frequency;
+	u32 min_freq;
+	u32 max_freq;
+	int d_delay;
+	int d_shift;
+	int s_delay;
+	int s_shift;
+
+};
+
+struct clk *clk_get(const char *id);
+
+static void set_pin_stat(int index, int bit, int value)
+{
+#if !defined(CONFIG_SPL_BUILD)
+	nx_gpio_set_pad_function(index, bit, value);
+#else
+#if defined(CONFIG_ARCH_S5P4418) ||	\
+	defined(CONFIG_ARCH_S5P6818)
+
+	unsigned long base[5] = {
+		PHY_BASEADDR_GPIOA, PHY_BASEADDR_GPIOB,
+		PHY_BASEADDR_GPIOC, PHY_BASEADDR_GPIOD,
+		PHY_BASEADDR_GPIOE,
+	};
+
+	dw_mmc_set_pin(base[index], bit, value);
+#endif
+#endif
+}
+
+static void nx_dw_mmc_set_pin(struct dwmci_host *host)
+{
+	debug("  %s(): dev_index == %d", __func__, host->dev_index);
+
+	switch (host->dev_index) {
+	case 0:
+		set_pin_stat(0, 29, 1);
+		set_pin_stat(0, 31, 1);
+		set_pin_stat(1, 1, 1);
+		set_pin_stat(1, 3, 1);
+		set_pin_stat(1, 5, 1);
+		set_pin_stat(1, 7, 1);
+		break;
+	case 1:
+		set_pin_stat(3, 22, 1);
+		set_pin_stat(3, 23, 1);
+		set_pin_stat(3, 24, 1);
+		set_pin_stat(3, 25, 1);
+		set_pin_stat(3, 26, 1);
+		set_pin_stat(3, 27, 1);
+		break;
+	case 2:
+		set_pin_stat(2, 18, 2);
+		set_pin_stat(2, 19, 2);
+		set_pin_stat(2, 20, 2);
+		set_pin_stat(2, 21, 2);
+		set_pin_stat(2, 22, 2);
+		set_pin_stat(2, 23, 2);
+		if (host->buswidth == 8) {
+			set_pin_stat(4, 21, 2);
+			set_pin_stat(4, 22, 2);
+			set_pin_stat(4, 23, 2);
+			set_pin_stat(4, 24, 2);
+		}
+		break;
+	default:
+		debug(" is invalid!");
+	}
+	debug("\n");
+}
+
+static void nx_dw_mmc_clksel(struct dwmci_host *host)
+{
+	u32 val;
+
+#ifdef CONFIG_BOOST_MMC
+	val = DWMCI_SET_SAMPLE_CLK(DWMCI_SHIFT_0) |
+	    DWMCI_SET_DRV_CLK(DWMCI_SHIFT_0) | DWMCI_SET_DIV_RATIO(1);
+#else
+	val = DWMCI_SET_SAMPLE_CLK(DWMCI_SHIFT_0) |
+	    DWMCI_SET_DRV_CLK(DWMCI_SHIFT_0) | DWMCI_SET_DIV_RATIO(3);
+#endif
+
+	dwmci_writel(host, DWMCI_CLKSEL, val);
+}
+
+static void nx_dw_mmc_reset(int ch)
+{
+	int rst_id = RESET_ID_SDMMC0 + ch;
+
+	nx_rstcon_setrst(rst_id, 0);
+	nx_rstcon_setrst(rst_id, 1);
+}
+
+static void nx_dw_mmc_clk_delay(struct udevice *dev)
+{
+	unsigned int delay;
+	struct nexell_dwmmc_priv *priv = dev_get_priv(dev);
+	struct dwmci_host *host = &priv->host;
+
+	delay = NX_MMC_CLK_DELAY(priv->d_delay,
+				 priv->d_shift, priv->s_delay, priv->s_shift);
+
+	writel(delay, (host->ioaddr + DWMCI_CLKCTRL));
+	debug("%s(): Values set: d_delay==%d, d_shift==%d, s_delay==%d, "
+	      "s_shift==%d\n", __func__, priv->d_delay, priv->d_shift,
+	      priv->s_delay, priv->s_shift);
+}
+
+static unsigned int nx_dw_mmc_get_clk(struct dwmci_host *host, uint freq)
+{
+	struct clk *clk;
+	struct udevice *dev = host->priv;
+	struct nexell_dwmmc_priv *priv = dev_get_priv(dev);
+
+	int index = host->dev_index;
+	char name[50] = { 0, };
+
+	clk = priv->clk;
+	if (!clk) {
+		sprintf(name, "%s.%d", DEV_NAME_SDHC, index);
+		clk = clk_get((const char *)name);
+		if (!clk)
+			return 0;
+		priv->clk = clk;
+	}
+
+	return clk_get_rate(clk) / 2;
+}
+
+static unsigned long nx_dw_mmc_set_clk(struct dwmci_host *host,
+				       unsigned int rate)
+{
+	struct clk *clk;
+	char name[50] = { 0, };
+	struct udevice *dev = host->priv;
+	struct nexell_dwmmc_priv *priv = dev_get_priv(dev);
+
+	int index = host->dev_index;
+
+	clk = priv->clk;
+	if (!clk) {
+		sprintf(name, "%s.%d", DEV_NAME_SDHC, index);
+		clk = clk_get((const char *)name);
+		if (!clk)
+			return 0;
+		priv->clk = clk;
+	}
+
+	clk_disable(clk);
+	rate = clk_set_rate(clk, rate);
+	clk_enable(clk);
+
+	return rate;
+}
+
+static int nexell_dwmmc_ofdata_to_platdata(struct udevice *dev)
+{
+	/* if (dev): *priv = dev->priv, else: *priv = NULL */
+	struct nexell_dwmmc_priv *priv = dev_get_priv(dev);
+	struct dwmci_host *host = &priv->host;
+	int val = -1;
+
+	debug("%s()\n", __func__);
+
+	host->name = dev->name;
+	host->ioaddr = dev_read_addr_ptr(dev);
+
+	val = dev_read_u32_default(dev, "nexell,bus-width", -1);
+	if (val < 0) {
+		debug("  'nexell,bus-width' missing/invalid!\n");
+		return -EINVAL;
+	}
+	host->buswidth = val;
+	host->get_mmc_clk = nx_dw_mmc_get_clk;
+	host->clksel = nx_dw_mmc_clksel;
+	host->priv = dev;
+
+	val = dev_read_u32_default(dev, "index", -1);
+	if (val < 0) {
+		debug("  'index' missing/invalid!\n");
+		return -EINVAL;
+	}
+	host->dev_index = val;
+
+	val = dev_read_u32_default(dev, "fifo-size", 0x20);
+	if (val <= 0) {
+		debug("  'fifo-size' missing/invalid!\n");
+		return -EINVAL;
+	}
+	priv->fifo_size = val;
+
+	priv->fifo_mode = dev_read_bool(dev, "fifo-mode");
+
+	val = dev_read_u32_default(dev, "frequency", -1);
+	if (val < 0) {
+		debug("  'frequency' missing/invalid!\n");
+		return -EINVAL;
+	}
+	priv->frequency = val;
+
+	val = dev_read_u32_default(dev, "max-frequency", -1);
+	if (val < 0) {
+		debug("  'max-frequency' missing/invalid!\n");
+		return -EINVAL;
+	}
+	priv->max_freq = val;
+	priv->min_freq = 400000;  /* 400 kHz */
+
+	val = dev_read_u32_default(dev, "nexell,drive_dly", -1);
+	if (val < 0) {
+		debug("  'nexell,drive_dly' missing/invalid!\n");
+		return -EINVAL;
+	}
+	priv->d_delay = val;
+
+	val = dev_read_u32_default(dev, "nexell,drive_shift", -1);
+	if (val < 0) {
+		debug("  'nexell,drive_shift' missing/invalid!\n");
+		return -EINVAL;
+	}
+	priv->d_shift = val;
+
+	val = dev_read_u32_default(dev, "nexell,sample_dly", -1);
+	if (val < 0) {
+		debug("  'nexell,sample_dly' missing/invalid!\n");
+		return -EINVAL;
+	}
+	priv->s_delay = val;
+
+	val = dev_read_u32_default(dev, "nexell,sample_shift", -1);
+	if (val < 0) {
+		debug("  'nexell,sample_shift' missing/invalid!\n");
+		return -EINVAL;
+	}
+	priv->s_shift = val;
+
+	debug("  index==%d, name==%s, ioaddr==0x%08x, buswidth==%d, "
+		  "fifo_size==%d, fifo_mode==%d, frequency==%d\n",
+		  host->dev_index, host->name, (u32)host->ioaddr,
+		  host->buswidth, priv->fifo_size, priv->fifo_mode,
+		  priv->frequency);
+	debug("  min_freq==%d, max_freq==%d, delay: "
+		  "0x%02x:0x%02x:0x%02x:0x%02x\n",
+		  priv->min_freq, priv->max_freq, priv->d_delay,
+		  priv->d_shift, priv->s_delay, priv->s_shift);
+
+	return 0;
+}
+
+static int nexell_dwmmc_probe(struct udevice *dev)
+{
+	struct nexell_mmc_plat *plat = dev_get_platdata(dev);
+	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+	struct nexell_dwmmc_priv *priv = dev_get_priv(dev);
+	struct dwmci_host *host = &priv->host;
+	struct udevice *pwr_dev __maybe_unused;
+
+	debug("%s():\n", __func__);
+
+	host->fifoth_val = MSIZE(0x2) |
+		RX_WMARK(priv->fifo_size / 2 - 1) |
+		TX_WMARK(priv->fifo_size / 2);
+
+	host->fifo_mode = priv->fifo_mode;
+
+	dwmci_setup_cfg(&plat->cfg, host, priv->max_freq, priv->min_freq);
+	host->mmc = &plat->mmc;
+	host->mmc->priv = &priv->host;
+	host->mmc->dev = dev;
+	upriv->mmc = host->mmc;
+
+	nx_dw_mmc_set_pin(host);
+
+	debug("  nx_dw_mmc_set_clk(host, frequency * 4 == %d)\n",
+	      priv->frequency * 4);
+	nx_dw_mmc_set_clk(host, priv->frequency * 4);
+
+	nx_dw_mmc_reset(host->dev_index);
+	nx_dw_mmc_clk_delay(dev);
+
+	return dwmci_probe(dev);
+}
+
+static int nexell_dwmmc_bind(struct udevice *dev)
+{
+	struct nexell_mmc_plat *plat = dev_get_platdata(dev);
+
+	return dwmci_bind(dev, &plat->mmc, &plat->cfg);
+}
+
+static const struct udevice_id nexell_dwmmc_ids[] = {
+	{ .compatible = "nexell,nexell-dwmmc" },
+	{ }
+};
+
+U_BOOT_DRIVER(nexell_dwmmc_drv) = {
+	.name		= "nexell_dwmmc",
+	.id		= UCLASS_MMC,
+	.of_match	= nexell_dwmmc_ids,
+	.ofdata_to_platdata = nexell_dwmmc_ofdata_to_platdata,
+	.ops		= &dm_dwmci_ops,
+	.bind		= nexell_dwmmc_bind,
+	.probe		= nexell_dwmmc_probe,
+	.priv_auto_alloc_size = sizeof(struct nexell_dwmmc_priv),
+	.platdata_auto_alloc_size = sizeof(struct nexell_mmc_plat),
+};
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [RFC PATCH v2 06/13] pwm: add driver for nexell
  2020-03-28  9:43 [RFC PATCH v2 00/13] arm: add support for SoC S5P4418 Stefan Bosch
                   ` (4 preceding siblings ...)
  2020-03-28  9:43 ` [RFC PATCH v2 05/13] mmc: " Stefan Bosch
@ 2020-03-28  9:43 ` Stefan Bosch
  2020-03-28  9:43 ` [RFC PATCH v2 07/13] video: add nexell video driver (soc: displaytop) Stefan Bosch
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 21+ messages in thread
From: Stefan Bosch @ 2020-03-28  9:43 UTC (permalink / raw)
  To: u-boot

Changes in relation to FriendlyARM's U-Boot nanopi2-v2016.01:
- Since drivers/pwm/pwm-nexell.c is an adapted version of
  s5p-common/pwm.c an appropriately changed version of s5p-common/pwm.c
  is used instead. Therefore arch/arm/mach-s5pc1xx/include/mach/pwm.h
  copied to arch/arm/mach-nexell/include/mach and s5p-common/Makefile
  changed appropriately.

Signed-off-by: Stefan Bosch <stefan_b@posteo.net>
---

Changes in v2:
- commit "i2c: mmc: add nexell driver (gpio, i2c, mmc, pwm)" splitted
  into separate commits for gpio, i2c, mmc, pwm.
- Since drivers/pwm/pwm-nexell.c is an adapted version of
  s5p-common/pwm.c an appropriately changed version of s5p-common/pwm.c
  is used now. Therefore arch/arm/mach-s5pc1xx/include/mach/pwm.h
  copied to arch/arm/mach-nexell/include/mach and s5p-common/Makefile
  changed appropriately.

 arch/arm/cpu/armv7/s5p-common/Makefile  |  4 +++
 arch/arm/cpu/armv7/s5p-common/pwm.c     | 56 +++++++++++++++++++++++++++++++++
 arch/arm/mach-nexell/include/mach/pwm.h | 54 +++++++++++++++++++++++++++++++
 3 files changed, 114 insertions(+)
 create mode 100644 arch/arm/mach-nexell/include/mach/pwm.h

diff --git a/arch/arm/cpu/armv7/s5p-common/Makefile b/arch/arm/cpu/armv7/s5p-common/Makefile
index 12cf804..3d4649b 100644
--- a/arch/arm/cpu/armv7/s5p-common/Makefile
+++ b/arch/arm/cpu/armv7/s5p-common/Makefile
@@ -3,9 +3,13 @@
 # Copyright (C) 2009 Samsung Electronics
 # Minkyu Kang <mk7.kang@samsung.com>
 
+ifdef CONFIG_ARCH_NEXELL
+obj-$(CONFIG_PWM_NX)	+= pwm.o
+else
 obj-y		+= cpu_info.o
 ifndef CONFIG_SPL_BUILD
 obj-y		+= timer.o
 obj-y		+= sromc.o
 obj-$(CONFIG_PWM)	+= pwm.o
 endif
+endif
diff --git a/arch/arm/cpu/armv7/s5p-common/pwm.c b/arch/arm/cpu/armv7/s5p-common/pwm.c
index 6b9e865..c4915af 100644
--- a/arch/arm/cpu/armv7/s5p-common/pwm.c
+++ b/arch/arm/cpu/armv7/s5p-common/pwm.c
@@ -15,7 +15,11 @@
 int pwm_enable(int pwm_id)
 {
 	const struct s5p_timer *pwm =
+#if defined(CONFIG_ARCH_NEXELL)
+			(struct s5p_timer *)PHY_BASEADDR_PWM;
+#else
 			(struct s5p_timer *)samsung_get_base_timer();
+#endif
 	unsigned long tcon;
 
 	tcon = readl(&pwm->tcon);
@@ -29,7 +33,11 @@ int pwm_enable(int pwm_id)
 void pwm_disable(int pwm_id)
 {
 	const struct s5p_timer *pwm =
+#if defined(CONFIG_ARCH_NEXELL)
+			(struct s5p_timer *)PHY_BASEADDR_PWM;
+#else
 			(struct s5p_timer *)samsung_get_base_timer();
+#endif
 	unsigned long tcon;
 
 	tcon = readl(&pwm->tcon);
@@ -43,14 +51,43 @@ static unsigned long pwm_calc_tin(int pwm_id, unsigned long freq)
 	unsigned long tin_parent_rate;
 	unsigned int div;
 
+#if defined(CONFIG_ARCH_NEXELL)
+	unsigned int pre_div;
+	const struct s5p_timer *pwm =
+		(struct s5p_timer *)PHY_BASEADDR_PWM;
+	unsigned int val;
+	struct clk *clk = clk_get(CORECLK_NAME_PCLK);
+
+	tin_parent_rate = clk_get_rate(clk);
+#else
 	tin_parent_rate = get_pwm_clk();
+#endif
+
+#if defined(CONFIG_ARCH_NEXELL)
+	writel(0, &pwm->tcfg0);
+	val = readl(&pwm->tcfg0);
+
+	if (pwm_id < 2)
+		div = ((val >> 0) & 0xff) + 1;
+	else
+		div = ((val >> 8) & 0xff) + 1;
+
+	writel(0, &pwm->tcfg1);
+	val = readl(&pwm->tcfg1);
+	val = (val >> MUX_DIV_SHIFT(pwm_id)) & 0xF;
+	pre_div = (1UL << val);
 
+	freq = tin_parent_rate / div / pre_div;
+
+	return freq;
+#else
 	for (div = 2; div <= 16; div *= 2) {
 		if ((tin_parent_rate / (div << 16)) < freq)
 			return tin_parent_rate / div;
 	}
 
 	return tin_parent_rate / 16;
+#endif
 }
 
 #define NS_IN_SEC 1000000000UL
@@ -58,7 +95,11 @@ static unsigned long pwm_calc_tin(int pwm_id, unsigned long freq)
 int pwm_config(int pwm_id, int duty_ns, int period_ns)
 {
 	const struct s5p_timer *pwm =
+#if defined(CONFIG_ARCH_NEXELL)
+			(struct s5p_timer *)PHY_BASEADDR_PWM;
+#else
 			(struct s5p_timer *)samsung_get_base_timer();
+#endif
 	unsigned int offset;
 	unsigned long tin_rate;
 	unsigned long tin_ns;
@@ -84,7 +125,13 @@ int pwm_config(int pwm_id, int duty_ns, int period_ns)
 	tin_rate = pwm_calc_tin(pwm_id, frequency);
 
 	tin_ns = NS_IN_SEC / tin_rate;
+
+#if defined(CONFIG_ARCH_NEXELL)
+	/* The counter starts at zero. */
+	tcnt = (period_ns / tin_ns) - 1;
+#else
 	tcnt = period_ns / tin_ns;
+#endif
 
 	/* Note, counters count down */
 	tcmp = duty_ns / tin_ns;
@@ -115,7 +162,11 @@ int pwm_init(int pwm_id, int div, int invert)
 {
 	u32 val;
 	const struct s5p_timer *pwm =
+#if defined(CONFIG_ARCH_NEXELL)
+			(struct s5p_timer *)PHY_BASEADDR_PWM;
+#else
 			(struct s5p_timer *)samsung_get_base_timer();
+#endif
 	unsigned long ticks_per_period;
 	unsigned int offset, prescaler;
 
@@ -148,7 +199,12 @@ int pwm_init(int pwm_id, int div, int invert)
 		ticks_per_period = -1UL;
 	} else {
 		const unsigned long pwm_hz = 1000;
+#if defined(CONFIG_ARCH_NEXELL)
+		struct clk *clk = clk_get(CORECLK_NAME_PCLK);
+		unsigned long timer_rate_hz = clk_get_rate(clk) /
+#else
 		unsigned long timer_rate_hz = get_pwm_clk() /
+#endif
 			((prescaler + 1) * (1 << div));
 
 		ticks_per_period = timer_rate_hz / pwm_hz;
diff --git a/arch/arm/mach-nexell/include/mach/pwm.h b/arch/arm/mach-nexell/include/mach/pwm.h
new file mode 100644
index 0000000..1a531be
--- /dev/null
+++ b/arch/arm/mach-nexell/include/mach/pwm.h
@@ -0,0 +1,54 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2009 Samsung Electronics
+ * Kyungmin Park <kyungmin.park@samsung.com>
+ * Minkyu Kang <mk7.kang@samsung.com>
+ */
+
+#ifndef __ASM_ARM_ARCH_PWM_H_
+#define __ASM_ARM_ARCH_PWM_H_
+
+#define PRESCALER_0		(8 - 1)		/* prescaler of timer 0, 1 */
+#define PRESCALER_1		(16 - 1)	/* prescaler of timer 2, 3, 4 */
+
+/* Divider MUX */
+#define MUX_DIV_1		0		/* 1/1 period */
+#define MUX_DIV_2		1		/* 1/2 period */
+#define MUX_DIV_4		2		/* 1/4 period */
+#define MUX_DIV_8		3		/* 1/8 period */
+#define MUX_DIV_16		4		/* 1/16 period */
+
+#define MUX_DIV_SHIFT(x)	(x * 4)
+
+#define TCON_OFFSET(x)		((x + 1) * (!!x) << 2)
+
+#define TCON_START(x)		(1 << TCON_OFFSET(x))
+#define TCON_UPDATE(x)		(1 << (TCON_OFFSET(x) + 1))
+#define TCON_INVERTER(x)	(1 << (TCON_OFFSET(x) + 2))
+#define TCON_AUTO_RELOAD(x)	(1 << (TCON_OFFSET(x) + 3))
+#define TCON4_AUTO_RELOAD	(1 << 22)
+
+#ifndef __ASSEMBLY__
+struct s5p_timer {
+	unsigned int	tcfg0;
+	unsigned int	tcfg1;
+	unsigned int	tcon;
+	unsigned int	tcntb0;
+	unsigned int	tcmpb0;
+	unsigned int	tcnto0;
+	unsigned int	tcntb1;
+	unsigned int	tcmpb1;
+	unsigned int	tcnto1;
+	unsigned int	tcntb2;
+	unsigned int	tcmpb2;
+	unsigned int	tcnto2;
+	unsigned int	tcntb3;
+	unsigned int	res1;
+	unsigned int	tcnto3;
+	unsigned int	tcntb4;
+	unsigned int	tcnto4;
+	unsigned int	tintcstat;
+};
+#endif	/* __ASSEMBLY__ */
+
+#endif
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [RFC PATCH v2 07/13] video: add nexell video driver (soc: displaytop)
  2020-03-28  9:43 [RFC PATCH v2 00/13] arm: add support for SoC S5P4418 Stefan Bosch
                   ` (5 preceding siblings ...)
  2020-03-28  9:43 ` [RFC PATCH v2 06/13] pwm: add driver for nexell Stefan Bosch
@ 2020-03-28  9:43 ` Stefan Bosch
  2020-03-28  9:43 ` [RFC PATCH v2 08/13] video: add nexell video driver (soc: mlc, mipi) Stefan Bosch
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 21+ messages in thread
From: Stefan Bosch @ 2020-03-28  9:43 UTC (permalink / raw)
  To: u-boot

Low level functions for DisplayTop (Display Topology).

Signed-off-by: Stefan Bosch <stefan_b@posteo.net>
---

Changes in v2: None

 drivers/video/nexell/soc/s5pxx18_soc_disptop.c     | 185 ++++++++++
 drivers/video/nexell/soc/s5pxx18_soc_disptop.h     | 385 +++++++++++++++++++++
 drivers/video/nexell/soc/s5pxx18_soc_disptop_clk.c | 309 +++++++++++++++++
 drivers/video/nexell/soc/s5pxx18_soc_disptop_clk.h |  59 ++++
 drivers/video/nexell/soc/s5pxx18_soc_disptype.h    |  23 ++
 5 files changed, 961 insertions(+)
 create mode 100644 drivers/video/nexell/soc/s5pxx18_soc_disptop.c
 create mode 100644 drivers/video/nexell/soc/s5pxx18_soc_disptop.h
 create mode 100644 drivers/video/nexell/soc/s5pxx18_soc_disptop_clk.c
 create mode 100644 drivers/video/nexell/soc/s5pxx18_soc_disptop_clk.h
 create mode 100644 drivers/video/nexell/soc/s5pxx18_soc_disptype.h

diff --git a/drivers/video/nexell/soc/s5pxx18_soc_disptop.c b/drivers/video/nexell/soc/s5pxx18_soc_disptop.c
new file mode 100644
index 0000000..626e53a
--- /dev/null
+++ b/drivers/video/nexell/soc/s5pxx18_soc_disptop.c
@@ -0,0 +1,185 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2016  Nexell Co., Ltd.
+ *
+ * Author: junghyun, kim <jhkim@nexell.co.kr>
+ */
+
+#include <linux/types.h>
+#include <linux/io.h>
+
+#include "s5pxx18_soc_disptop.h"
+
+static struct {
+	struct nx_disp_top_register_set *pregister;
+} __g_module_variables = { NULL, };
+
+int nx_disp_top_initialize(void)
+{
+	static int binit;
+	u32 i;
+
+	if (binit == 0) {
+		for (i = 0; i < NUMBER_OF_DISPTOP_MODULE; i++)
+			__g_module_variables.pregister = NULL;
+		binit = 1;
+	}
+	return 1;
+}
+
+u32 nx_disp_top_get_number_of_module(void)
+{
+	return NUMBER_OF_DISPTOP_MODULE;
+}
+
+u32 nx_disp_top_get_physical_address(void)
+{
+	static const u32 physical_addr[] = PHY_BASEADDR_DISPTOP_LIST;
+
+	return (u32)(physical_addr[0] + PHY_BASEADDR_DISPLAYTOP_MODULE_OFFSET);
+}
+
+u32 nx_disp_top_get_size_of_register_set(void)
+{
+	return sizeof(struct nx_disp_top_register_set);
+}
+
+void nx_disp_top_set_base_address(void *base_address)
+{
+	__g_module_variables.pregister =
+	    (struct nx_disp_top_register_set *)base_address;
+}
+
+void *nx_disp_top_get_base_address(void)
+{
+	return (void *)__g_module_variables.pregister;
+}
+
+void nx_disp_top_set_resconvmux(int benb, u32 sel)
+{
+	register struct nx_disp_top_register_set *pregister;
+	u32 regvalue;
+
+	pregister = __g_module_variables.pregister;
+	regvalue = (benb << 31) | (sel << 0);
+	writel((u32)regvalue, &pregister->resconv_mux_ctrl);
+}
+
+void nx_disp_top_set_hdmimux(int benb, u32 sel)
+{
+	register struct nx_disp_top_register_set *pregister;
+	u32 regvalue;
+
+	pregister = __g_module_variables.pregister;
+	regvalue = (benb << 31) | (sel << 0);
+	writel((u32)regvalue, &pregister->interconv_mux_ctrl);
+}
+
+void nx_disp_top_set_mipimux(int benb, u32 sel)
+{
+	register struct nx_disp_top_register_set *pregister;
+	u32 regvalue;
+
+	pregister = __g_module_variables.pregister;
+	regvalue = (benb << 31) | (sel << 0);
+	writel((u32)regvalue, &pregister->mipi_mux_ctrl);
+}
+
+void nx_disp_top_set_lvdsmux(int benb, u32 sel)
+{
+	register struct nx_disp_top_register_set *pregister;
+	u32 regvalue;
+
+	pregister = __g_module_variables.pregister;
+	regvalue = (benb << 31) | (sel << 0);
+	writel((u32)regvalue, &pregister->lvds_mux_ctrl);
+}
+
+void nx_disp_top_set_primary_mux(u32 sel)
+{
+	register struct nx_disp_top_register_set *pregister;
+
+	pregister = __g_module_variables.pregister;
+	writel((u32)sel, &pregister->tftmpu_mux);
+}
+
+void nx_disp_top_hdmi_set_vsync_start(u32 sel)
+{
+	register struct nx_disp_top_register_set *pregister;
+
+	pregister = __g_module_variables.pregister;
+	writel((u32)sel, &pregister->hdmisyncctrl0);
+}
+
+void nx_disp_top_hdmi_set_vsync_hsstart_end(u32 start, u32 end)
+{
+	register struct nx_disp_top_register_set *pregister;
+
+	pregister = __g_module_variables.pregister;
+	writel((u32)(end << 16) | (start << 0), &pregister->hdmisyncctrl3);
+}
+
+void nx_disp_top_hdmi_set_hactive_start(u32 sel)
+{
+	register struct nx_disp_top_register_set *pregister;
+
+	pregister = __g_module_variables.pregister;
+	writel((u32)sel, &pregister->hdmisyncctrl1);
+}
+
+void nx_disp_top_hdmi_set_hactive_end(u32 sel)
+{
+	register struct nx_disp_top_register_set *pregister;
+
+	pregister = __g_module_variables.pregister;
+	writel((u32)sel, &pregister->hdmisyncctrl2);
+}
+
+void nx_disp_top_set_hdmifield(u32 enable, u32 init_val, u32 vsynctoggle,
+			       u32 hsynctoggle, u32 vsyncclr, u32 hsyncclr,
+			       u32 field_use, u32 muxsel)
+{
+	register struct nx_disp_top_register_set *pregister;
+	u32 regvalue;
+
+	pregister = __g_module_variables.pregister;
+	regvalue = ((enable & 0x01) << 0) | ((init_val & 0x01) << 1) |
+		   ((vsynctoggle & 0x3fff) << 2) |
+		   ((hsynctoggle & 0x3fff) << 17);
+	writel(regvalue, &pregister->hdmifieldctrl);
+	regvalue = ((field_use & 0x01) << 31) | ((muxsel & 0x01) << 30) |
+		   ((hsyncclr) << 15) | ((vsyncclr) << 0);
+	writel(regvalue, &pregister->greg0);
+}
+
+void nx_disp_top_set_padclock(u32 mux_index, u32 padclk_cfg)
+{
+	register struct nx_disp_top_register_set *pregister;
+	u32 regvalue;
+
+	pregister = __g_module_variables.pregister;
+	regvalue = readl(&pregister->greg1);
+	if (padmux_secondary_mlc == mux_index) {
+		regvalue = regvalue & (~(0x7 << 3));
+		regvalue = regvalue | (padclk_cfg << 3);
+	} else if (padmux_resolution_conv == mux_index) {
+		regvalue = regvalue & (~(0x7 << 6));
+		regvalue = regvalue | (padclk_cfg << 6);
+	} else {
+		regvalue = regvalue & (~(0x7 << 0));
+		regvalue = regvalue | (padclk_cfg << 0);
+	}
+	writel(regvalue, &pregister->greg1);
+}
+
+void nx_disp_top_set_lcdif_enb(int enb)
+{
+	register struct nx_disp_top_register_set *pregister;
+	u32 regvalue;
+
+	pregister = __g_module_variables.pregister;
+	regvalue = readl(&pregister->greg1);
+	regvalue = regvalue & (~(0x1 << 9));
+	regvalue = regvalue | ((enb & 0x1) << 9);
+	writel(regvalue, &pregister->greg1);
+}
diff --git a/drivers/video/nexell/soc/s5pxx18_soc_disptop.h b/drivers/video/nexell/soc/s5pxx18_soc_disptop.h
new file mode 100644
index 0000000..c7bf504
--- /dev/null
+++ b/drivers/video/nexell/soc/s5pxx18_soc_disptop.h
@@ -0,0 +1,385 @@
+/* SPDX-License-Identifier: GPL-2.0+
+ *
+ * Copyright (C) 2016  Nexell Co., Ltd.
+ *
+ * Author: junghyun, kim <jhkim@nexell.co.kr>
+ */
+
+#ifndef _S5PXX18_SOC_DISPTOP_H_
+#define _S5PXX18_SOC_DISPTOP_H_
+
+#include "s5pxx18_soc_disptype.h"
+
+#define NUMBER_OF_DISPTOP_MODULE	1
+#define PHY_BASEADDR_DISPLAYTOP_MODULE 0xC0100000
+#define	PHY_BASEADDR_DISPTOP_LIST	\
+		{ PHY_BASEADDR_DISPLAYTOP_MODULE }
+
+#define HDMI_ADDR_OFFSET                                                       \
+	(((PHY_BASEADDR_DISPLAYTOP_MODULE / 0x00100000) % 2) ? 0x100000        \
+							     : 0x000000)
+#define OTHER_ADDR_OFFSET                                                      \
+	(((PHY_BASEADDR_DISPLAYTOP_MODULE / 0x00100000) % 2) ? 0x000000        \
+							     : 0x100000)
+#define PHY_BASEADDR_DISPLAYTOP_MODULE_OFFSET (OTHER_ADDR_OFFSET + 0x001000)
+#define PHY_BASEADDR_DUALDISPLAY_MODULE                                        \
+	(PHY_BASEADDR_DISPLAYTOP_MODULE + OTHER_ADDR_OFFSET + 0x002000)
+#define PHY_BASEADDR_RESCONV_MODULE                                            \
+	(PHY_BASEADDR_DISPLAYTOP_MODULE + OTHER_ADDR_OFFSET + 0x003000)
+#define PHY_BASEADDR_LCDINTERFACE_MODULE                                       \
+	(PHY_BASEADDR_DISPLAYTOP_MODULE + OTHER_ADDR_OFFSET + 0x004000)
+#define PHY_BASEADDR_HDMI_MODULE (PHY_BASEADDR_DISPLAYTOP_MODULE + 0x000000)
+#define PHY_BASEADDR_LVDS_MODULE                                               \
+	(PHY_BASEADDR_DISPLAYTOP_MODULE + OTHER_ADDR_OFFSET + 0x00a000)
+
+#define NUMBER_OF_DUALDISPLAY_MODULE 1
+#define INTNUM_OF_DUALDISPLAY_MODULE_PRIMIRQ                                   \
+	INTNUM_OF_DISPLAYTOP_MODULE_DUALDISPLAY_PRIMIRQ
+#define INTNUM_OF_DUALDISPLAY_MODULE_SECONDIRQ                                 \
+	INTNUM_OF_DISPLAYTOP_MODULE_DUALDISPLAY_SECONDIRQ
+#define RESETINDEX_OF_DUALDISPLAY_MODULE_I_NRST                                \
+	RESETINDEX_OF_DISPLAYTOP_MODULE_I_DUALDISPLAY_NRST
+#define PADINDEX_OF_DUALDISPLAY_O_NCS                                          \
+	PADINDEX_OF_DISPLAYTOP_O_DUAL_DISPLAY_PADPRIMVCLK
+#define PADINDEX_OF_DUALDISPLAY_O_NRD                                          \
+	PADINDEX_OF_DISPLAYTOP_O_DUAL_DISPLAY_PRIM_PADN_HSYNC
+#define PADINDEX_OF_DUALDISPLAY_O_RS                                           \
+	PADINDEX_OF_DISPLAYTOP_O_DUAL_DISPLAY_PRIM_PADN_VSYNC
+#define PADINDEX_OF_DUALDISPLAY_O_NWR                                          \
+	PADINDEX_OF_DISPLAYTOP_O_DUAL_DISPLAY_PRIM_PADDE
+#define PADINDEX_OF_DUALDISPLAY_PADPRIMVCLK                                    \
+	PADINDEX_OF_DISPLAYTOP_O_DUAL_DISPLAY_PADPRIMVCLK
+#define PADINDEX_OF_DUALDISPLAY_O_PRIM_PADN_HSYNC                              \
+	PADINDEX_OF_DISPLAYTOP_O_DUAL_DISPLAY_PRIM_PADN_HSYNC
+#define PADINDEX_OF_DUALDISPLAY_O_PRIM_PADN_VSYNC                              \
+	PADINDEX_OF_DISPLAYTOP_O_DUAL_DISPLAY_PRIM_PADN_VSYNC
+#define PADINDEX_OF_DUALDISPLAY_O_PRIM_PADDE                                   \
+	PADINDEX_OF_DISPLAYTOP_O_DUAL_DISPLAY_PRIM_PADDE
+#define PADINDEX_OF_DUALDISPLAY_PRIM_0_                                        \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_0_
+#define PADINDEX_OF_DUALDISPLAY_PRIM_1_                                        \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_1_
+#define PADINDEX_OF_DUALDISPLAY_PRIM_2_                                        \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_2_
+#define PADINDEX_OF_DUALDISPLAY_PRIM_3_                                        \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_3_
+#define PADINDEX_OF_DUALDISPLAY_PRIM_4_                                        \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_4_
+#define PADINDEX_OF_DUALDISPLAY_PRIM_5_                                        \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_5_
+#define PADINDEX_OF_DUALDISPLAY_PRIM_6_                                        \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_6_
+#define PADINDEX_OF_DUALDISPLAY_PRIM_7_                                        \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_7_
+#define PADINDEX_OF_DUALDISPLAY_PRIM_8_                                        \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_8_
+#define PADINDEX_OF_DUALDISPLAY_PRIM_9_                                        \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_9_
+#define PADINDEX_OF_DUALDISPLAY_PRIM_10_                                       \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_10_
+#define PADINDEX_OF_DUALDISPLAY_PRIM_11_                                       \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_11_
+#define PADINDEX_OF_DUALDISPLAY_PRIM_12_                                       \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_12_
+#define PADINDEX_OF_DUALDISPLAY_PRIM_13_                                       \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_13_
+#define PADINDEX_OF_DUALDISPLAY_PRIM_14_                                       \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_14_
+#define PADINDEX_OF_DUALDISPLAY_PRIM_15_                                       \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_15_
+#define PADINDEX_OF_DUALDISPLAY_PRIM_16_                                       \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_16_
+#define PADINDEX_OF_DUALDISPLAY_PRIM_17_                                       \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_17_
+#define PADINDEX_OF_DUALDISPLAY_PRIM_18_                                       \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_18_
+#define PADINDEX_OF_DUALDISPLAY_PRIM_19_                                       \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_19_
+#define PADINDEX_OF_DUALDISPLAY_PRIM_20_                                       \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_20_
+#define PADINDEX_OF_DUALDISPLAY_PRIM_21_                                       \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_21_
+#define PADINDEX_OF_DUALDISPLAY_PRIM_22_                                       \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_22_
+#define PADINDEX_OF_DUALDISPLAY_PRIM_23_                                       \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_23_
+#define PADINDEX_OF_DUALDISPLAY_PADSECONDVCLK                                  \
+	PADINDEX_OF_DISPLAYTOP_O_DUAL_DISPLAY_PADPRIMVCLK
+#define PADINDEX_OF_DUALDISPLAY_O_SECOND_PADN_HSYNC                            \
+	PADINDEX_OF_DISPLAYTOP_O_DUAL_DISPLAY_PRIM_PADN_HSYNC
+#define PADINDEX_OF_DUALDISPLAY_O_SECOND_PADN_VSYNC                            \
+	PADINDEX_OF_DISPLAYTOP_O_DUAL_DISPLAY_PRIM_PADN_VSYNC
+#define PADINDEX_OF_DUALDISPLAY_O_SECOND_PADDE                                 \
+	PADINDEX_OF_DISPLAYTOP_O_DUAL_DISPLAY_PRIM_PADDE
+#define PADINDEX_OF_DUALDISPLAY_SECOND_0_                                      \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_0_
+#define PADINDEX_OF_DUALDISPLAY_SECOND_1_                                      \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_1_
+#define PADINDEX_OF_DUALDISPLAY_SECOND_2_                                      \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_2_
+#define PADINDEX_OF_DUALDISPLAY_SECOND_3_                                      \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_3_
+#define PADINDEX_OF_DUALDISPLAY_SECOND_4_                                      \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_4_
+#define PADINDEX_OF_DUALDISPLAY_SECOND_5_                                      \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_5_
+#define PADINDEX_OF_DUALDISPLAY_SECOND_6_                                      \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_6_
+#define PADINDEX_OF_DUALDISPLAY_SECOND_7_                                      \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_7_
+#define PADINDEX_OF_DUALDISPLAY_SECOND_8_                                      \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_8_
+#define PADINDEX_OF_DUALDISPLAY_SECOND_9_                                      \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_9_
+#define PADINDEX_OF_DUALDISPLAY_SECOND_10_                                     \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_10_
+#define PADINDEX_OF_DUALDISPLAY_SECOND_11_                                     \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_11_
+#define PADINDEX_OF_DUALDISPLAY_SECOND_12_                                     \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_12_
+#define PADINDEX_OF_DUALDISPLAY_SECOND_13_                                     \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_13_
+#define PADINDEX_OF_DUALDISPLAY_SECOND_14_                                     \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_14_
+#define PADINDEX_OF_DUALDISPLAY_SECOND_15_                                     \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_15_
+#define PADINDEX_OF_DUALDISPLAY_SECOND_16_                                     \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_16_
+#define PADINDEX_OF_DUALDISPLAY_SECOND_17_                                     \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_17_
+#define PADINDEX_OF_DUALDISPLAY_SECOND_18_                                     \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_18_
+#define PADINDEX_OF_DUALDISPLAY_SECOND_19_                                     \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_19_
+#define PADINDEX_OF_DUALDISPLAY_SECOND_20_                                     \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_20_
+#define PADINDEX_OF_DUALDISPLAY_SECOND_21_                                     \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_21_
+#define PADINDEX_OF_DUALDISPLAY_SECOND_22_                                     \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_22_
+#define PADINDEX_OF_DUALDISPLAY_SECOND_23_                                     \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_23_
+
+#define NUMBER_OF_RESCONV_MODULE 1
+#define INTNUM_OF_RESCONV_MODULE INTNUM_OF_DISPLAYTOP_MODULE_RESCONV_IRQ
+#define RESETINDEX_OF_RESCONV_MODULE_I_NRST                                    \
+	RESETINDEX_OF_DISPLAYTOP_MODULE_I_RESCONV_NRST
+#define RESETINDEX_OF_RESCONV_MODULE RESETINDEX_OF_RESCONV_MODULE_I_NRST
+#define NUMBER_OF_LCDINTERFACE_MODULE 1
+#define RESETINDEX_OF_LCDINTERFACE_MODULE_I_NRST                               \
+	RESETINDEX_OF_DISPLAYTOP_MODULE_I_LCDIF_NRST
+#define PADINDEX_OF_LCDINTERFACE_O_VCLK                                        \
+	PADINDEX_OF_DISPLAYTOP_O_DUAL_DISPLAY_PADPRIMVCLK
+#define PADINDEX_OF_LCDINTERFACE_O_NHSYNC                                      \
+	PADINDEX_OF_DISPLAYTOP_O_DUAL_DISPLAY_PRIM_PADN_HSYNC
+#define PADINDEX_OF_LCDINTERFACE_O_NVSYNC                                      \
+	PADINDEX_OF_DISPLAYTOP_O_DUAL_DISPLAY_PRIM_PADN_VSYNC
+#define PADINDEX_OF_LCDINTERFACE_O_DE                                          \
+	PADINDEX_OF_DISPLAYTOP_O_DUAL_DISPLAY_PRIM_PADDE
+#define PADINDEX_OF_LCDINTERFACE_RGB24_0_                                      \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_0_
+#define PADINDEX_OF_LCDINTERFACE_RGB24_1_                                      \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_1_
+#define PADINDEX_OF_LCDINTERFACE_RGB24_2_                                      \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_2_
+#define PADINDEX_OF_LCDINTERFACE_RGB24_3_                                      \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_3_
+#define PADINDEX_OF_LCDINTERFACE_RGB24_4_                                      \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_4_
+#define PADINDEX_OF_LCDINTERFACE_RGB24_5_                                      \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_5_
+#define PADINDEX_OF_LCDINTERFACE_RGB24_6_                                      \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_6_
+#define PADINDEX_OF_LCDINTERFACE_RGB24_7_                                      \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_7_
+#define PADINDEX_OF_LCDINTERFACE_RGB24_8_                                      \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_8_
+#define PADINDEX_OF_LCDINTERFACE_RGB24_9_                                      \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_9_
+#define PADINDEX_OF_LCDINTERFACE_RGB24_10_                                     \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_10_
+#define PADINDEX_OF_LCDINTERFACE_RGB24_11_                                     \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_11_
+#define PADINDEX_OF_LCDINTERFACE_RGB24_12_                                     \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_12_
+#define PADINDEX_OF_LCDINTERFACE_RGB24_13_                                     \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_13_
+#define PADINDEX_OF_LCDINTERFACE_RGB24_14_                                     \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_14_
+#define PADINDEX_OF_LCDINTERFACE_RGB24_15_                                     \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_15_
+#define PADINDEX_OF_LCDINTERFACE_RGB24_16_                                     \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_16_
+#define PADINDEX_OF_LCDINTERFACE_RGB24_17_                                     \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_17_
+#define PADINDEX_OF_LCDINTERFACE_RGB24_18_                                     \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_18_
+#define PADINDEX_OF_LCDINTERFACE_RGB24_19_                                     \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_19_
+#define PADINDEX_OF_LCDINTERFACE_RGB24_20_                                     \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_20_
+#define PADINDEX_OF_LCDINTERFACE_RGB24_21_                                     \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_21_
+#define PADINDEX_OF_LCDINTERFACE_RGB24_22_                                     \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_22_
+#define PADINDEX_OF_LCDINTERFACE_RGB24_23_                                     \
+	PADINDEX_OF_DISPLAYTOP_DUAL_DISPLAY_PRIM_23_
+
+#define NUMBER_OF_HDMI_MODULE 1
+#define INTNUM_OF_HDMI_MODULE INTNUM_OF_DISPLAYTOP_MODULE_HDMI_IRQ
+#define RESETINDEX_OF_HDMI_MODULE_I_NRST                                       \
+	RESETINDEX_OF_DISPLAYTOP_MODULE_I_HDMI_NRST
+#define RESETINDEX_OF_HDMI_MODULE_I_NRST_VIDEO                                 \
+	RESETINDEX_OF_DISPLAYTOP_MODULE_I_HDMI_VIDEO_NRST
+#define RESETINDEX_OF_HDMI_MODULE_I_NRST_SPDIF                                 \
+	RESETINDEX_OF_DISPLAYTOP_MODULE_I_HDMI_SPDIF_NRST
+#define RESETINDEX_OF_HDMI_MODULE_I_NRST_TMDS                                  \
+	RESETINDEX_OF_DISPLAYTOP_MODULE_I_HDMI_TMDS_NRST
+#define RESETINDEX_OF_HDMI_MODULE_I_NRST_PHY                                   \
+	RESETINDEX_OF_DISPLAYTOP_MODULE_I_HDMI_PHY_NRST
+#define PADINDEX_OF_HDMI_I_PHY_CLKI PADINDEX_OF_DISPLAYTOP_I_HDMI_CLKI
+#define PADINDEX_OF_HDMI_O_PHY_CLKO PADINDEX_OF_DISPLAYTOP_O_HDMI_CLKO
+#define PADINDEX_OF_HDMI_IO_PHY_REXT PADINDEX_OF_DISPLAYTOP_IO_HDMI_REXT
+#define PADINDEX_OF_HDMI_O_PHY_TX0P PADINDEX_OF_DISPLAYTOP_O_HDMI_TX0P
+#define PADINDEX_OF_HDMI_O_PHY_TX0N PADINDEX_OF_DISPLAYTOP_O_HDMI_TX0N
+#define PADINDEX_OF_HDMI_O_PHY_TX1P PADINDEX_OF_DISPLAYTOP_O_HDMI_TX1P
+#define PADINDEX_OF_HDMI_O_PHY_TX1N PADINDEX_OF_DISPLAYTOP_O_HDMI_TX1N
+#define PADINDEX_OF_HDMI_O_PHY_TX2P PADINDEX_OF_DISPLAYTOP_O_HDMI_TX2P
+#define PADINDEX_OF_HDMI_O_PHY_TX2N PADINDEX_OF_DISPLAYTOP_O_HDMI_TX2N
+#define PADINDEX_OF_HDMI_O_PHY_TXCP PADINDEX_OF_DISPLAYTOP_O_HDMI_TXCP
+#define PADINDEX_OF_HDMI_O_PHY_TXCN PADINDEX_OF_DISPLAYTOP_O_HDMI_TXCN
+#define PADINDEX_OF_HDMI_I_HOTPLUG PADINDEX_OF_DISPLAYTOP_I_HDMI_HOTPLUG_5V
+#define PADINDEX_OF_HDMI_IO_PAD_CEC PADINDEX_OF_DISPLAYTOP_IO_HDMI_CEC
+#define NUMBER_OF_LVDS_MODULE 1
+
+#define RESETINDEX_OF_LVDS_MODULE_I_RESETN                                     \
+	RESETINDEX_OF_DISPLAYTOP_MODULE_I_LVDS_NRST
+#define RESETINDEX_OF_LVDS_MODULE RESETINDEX_OF_LVDS_MODULE_I_RESETN
+
+#define PADINDEX_OF_LVDS_TAP PADINDEX_OF_DISPLAYTOP_LVDS_TXP_A
+#define PADINDEX_OF_LVDS_TAN PADINDEX_OF_DISPLAYTOP_LVDS_TXN_A
+#define PADINDEX_OF_LVDS_TBP PADINDEX_OF_DISPLAYTOP_LVDS_TXP_B
+#define PADINDEX_OF_LVDS_TBN PADINDEX_OF_DISPLAYTOP_LVDS_TXN_B
+#define PADINDEX_OF_LVDS_TCP PADINDEX_OF_DISPLAYTOP_LVDS_TXP_C
+#define PADINDEX_OF_LVDS_TCN PADINDEX_OF_DISPLAYTOP_LVDS_TXN_C
+#define PADINDEX_OF_LVDS_TDP PADINDEX_OF_DISPLAYTOP_LVDS_TXP_D
+#define PADINDEX_OF_LVDS_TDN PADINDEX_OF_DISPLAYTOP_LVDS_TXN_D
+#define PADINDEX_OF_LVDS_TCLKP PADINDEX_OF_DISPLAYTOP_LVDS_TXP_CLK
+#define PADINDEX_OF_LVDS_TCLKN PADINDEX_OF_DISPLAYTOP_LVDS_TXN_CLK
+#define PADINDEX_OF_LVDS_ROUT PADINDEX_OF_DISPLAYTOP_LVDS_ROUT
+#define PADINDEX_OF_LVDS_TEP PADINDEX_OF_DISPLAYTOP_LVDS_TXN_E
+#define PADINDEX_OF_LVDS_TEN PADINDEX_OF_DISPLAYTOP_LVDS_TXN_E
+#define NUMBER_OF_DISPTOP_CLKGEN_MODULE 5
+
+enum disptop_clkgen_module_index {
+	res_conv_clkgen = 0,
+	lcdif_clkgen = 1,
+	to_mipi_clkgen = 2,
+	to_lvds_clkgen = 3,
+	hdmi_clkgen = 4,
+};
+
+enum disptop_res_conv_iclk_cclk {
+	res_conv_iclk = 0,
+	res_conv_cclk = 1,
+};
+
+enum disptop_res_conv_oclk {
+	res_conv_oclk = 1,
+};
+
+enum disptop_lcdif_clk {
+	lcdif_pixel_clkx_n = 0,
+	lcdif_pixel_clk = 1,
+};
+
+#define HDMI_SPDIF_CLKGEN 2
+#define HDMI_SPDIF_CLKOUT 0
+#define HDMI_I_VCLK_CLKOUT 0
+#define PHY_BASEADDR_DISPTOP_CLKGEN0_MODULE                                    \
+	(PHY_BASEADDR_DISPLAYTOP_MODULE + OTHER_ADDR_OFFSET + 0x006000)
+#define PHY_BASEADDR_DISPTOP_CLKGEN1_MODULE                                    \
+	(PHY_BASEADDR_DISPLAYTOP_MODULE + OTHER_ADDR_OFFSET + 0x007000)
+#define PHY_BASEADDR_DISPTOP_CLKGEN2_MODULE                                    \
+	(PHY_BASEADDR_DISPLAYTOP_MODULE + OTHER_ADDR_OFFSET + 0x005000)
+#define PHY_BASEADDR_DISPTOP_CLKGEN3_MODULE                                    \
+	(PHY_BASEADDR_DISPLAYTOP_MODULE + OTHER_ADDR_OFFSET + 0x008000)
+#define PHY_BASEADDR_DISPTOP_CLKGEN4_MODULE                                    \
+	(PHY_BASEADDR_DISPLAYTOP_MODULE + OTHER_ADDR_OFFSET + 0x009000)
+
+struct nx_disp_top_register_set {
+	u32 resconv_mux_ctrl;
+	u32 interconv_mux_ctrl;
+	u32 mipi_mux_ctrl;
+	u32 lvds_mux_ctrl;
+	u32 hdmifixctrl0;
+	u32 hdmisyncctrl0;
+	u32 hdmisyncctrl1;
+	u32 hdmisyncctrl2;
+	u32 hdmisyncctrl3;
+	u32 tftmpu_mux;
+	u32 hdmifieldctrl;
+	u32 greg0;
+	u32 greg1;
+	u32 greg2;
+	u32 greg3;
+	u32 greg4;
+	u32 greg5;
+};
+
+int nx_disp_top_initialize(void);
+u32 nx_disp_top_get_number_of_module(void);
+
+u32 nx_disp_top_get_physical_address(void);
+u32 nx_disp_top_get_size_of_register_set(void);
+void nx_disp_top_set_base_address(void *base_address);
+void *nx_disp_top_get_base_address(void);
+int nx_disp_top_open_module(void);
+int nx_disp_top_close_module(void);
+int nx_disp_top_check_busy(void);
+
+enum mux_index {
+	primary_mlc = 0,
+	secondary_mlc = 1,
+	resolution_conv = 2,
+};
+
+enum prim_pad_mux_index {
+	padmux_primary_mlc = 0,
+	padmux_primary_mpu = 1,
+	padmux_secondary_mlc = 2,
+	padmux_resolution_conv = 3,
+};
+
+void nx_disp_top_set_resconvmux(int benb, u32 sel);
+void nx_disp_top_set_hdmimux(int benb, u32 sel);
+void nx_disp_top_set_mipimux(int benb, u32 sel);
+void nx_disp_top_set_lvdsmux(int benb, u32 sel);
+void nx_disp_top_set_primary_mux(u32 sel);
+void nx_disp_top_hdmi_set_vsync_start(u32 sel);
+void nx_disp_top_hdmi_set_vsync_hsstart_end(u32 start, u32 end);
+void nx_disp_top_hdmi_set_hactive_start(u32 sel);
+void nx_disp_top_hdmi_set_hactive_end(u32 sel);
+
+void nx_disp_top_set_hdmifield(u32 enable, u32 init_val, u32 vsynctoggle,
+			       u32 hsynctoggle, u32 vsyncclr, u32 hsyncclr,
+			       u32 field_use, u32 muxsel);
+
+enum padclk_config {
+	padclk_clk = 0,
+	padclk_inv_clk = 1,
+	padclk_reserved_clk = 2,
+	padclk_reserved_inv_clk = 3,
+	padclk_clk_div2_0 = 4,
+	padclk_clk_div2_90 = 5,
+	padclk_clk_div2_180 = 6,
+	padclk_clk_div2_270 = 7,
+};
+
+void nx_disp_top_set_padclock(u32 mux_index, u32 padclk_cfg);
+void nx_disp_top_set_lcdif_enb(int enb);
+void nx_disp_top_set_hdmifield(u32 enable, u32 init_val, u32 vsynctoggle,
+			       u32 hsynctoggle, u32 vsyncclr, u32 hsyncclr,
+			       u32 field_use, u32 muxsel);
+
+#endif
diff --git a/drivers/video/nexell/soc/s5pxx18_soc_disptop_clk.c b/drivers/video/nexell/soc/s5pxx18_soc_disptop_clk.c
new file mode 100644
index 0000000..02361ba
--- /dev/null
+++ b/drivers/video/nexell/soc/s5pxx18_soc_disptop_clk.c
@@ -0,0 +1,309 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2016  Nexell Co., Ltd.
+ *
+ * Author: junghyun, kim <jhkim@nexell.co.kr>
+ */
+
+#include <linux/types.h>
+#include <linux/io.h>
+
+#include "s5pxx18_soc_disptop_clk.h"
+#include "s5pxx18_soc_disptop.h"
+
+static struct {
+	struct nx_disptop_clkgen_register_set *__g_pregister;
+} __g_module_variables[NUMBER_OF_DISPTOP_CLKGEN_MODULE] = {
+	{ NULL,},
+};
+
+int nx_disp_top_clkgen_initialize(void)
+{
+	static int binit;
+	u32 i;
+
+	if (binit == 0) {
+		for (i = 0; i < NUMBER_OF_DISPTOP_CLKGEN_MODULE; i++)
+			__g_module_variables[i].__g_pregister = NULL;
+		binit = 1;
+	}
+	return 1;
+}
+
+u32 nx_disp_top_clkgen_get_number_of_module(void)
+{
+	return NUMBER_OF_DISPTOP_CLKGEN_MODULE;
+}
+
+u32 nx_disp_top_clkgen_get_physical_address(u32 module_index)
+{
+	static const u32 physical_addr[] =
+		PHY_BASEADDR_DISPTOP_CLKGEN_LIST;
+
+	return (u32)physical_addr[module_index];
+}
+
+u32 nx_disp_top_clkgen_get_size_of_register_set(void)
+{
+	return sizeof(struct nx_disptop_clkgen_register_set);
+}
+
+void nx_disp_top_clkgen_set_base_address(u32 module_index, void *base_address)
+{
+	__g_module_variables[module_index].__g_pregister =
+	    (struct nx_disptop_clkgen_register_set *)base_address;
+}
+
+void *nx_disp_top_clkgen_get_base_address(u32 module_index)
+{
+	return (void *)__g_module_variables[module_index].__g_pregister;
+}
+
+void nx_disp_top_clkgen_set_clock_bclk_mode(u32 module_index,
+					    enum nx_bclkmode mode)
+{
+	register struct nx_disptop_clkgen_register_set *pregister;
+	register u32 regvalue;
+	u32 clkmode = 0;
+
+	pregister = __g_module_variables[module_index].__g_pregister;
+	switch (mode) {
+	case nx_bclkmode_disable:
+		clkmode = 0;
+	case nx_bclkmode_dynamic:
+		clkmode = 2;
+		break;
+	case nx_bclkmode_always:
+		clkmode = 3;
+		break;
+	default:
+		break;
+	}
+
+	regvalue = pregister->clkenb;
+	regvalue &= ~3ul;
+	regvalue |= (clkmode & 0x03);
+
+	writel(regvalue, &pregister->clkenb);
+}
+
+enum nx_bclkmode nx_disp_top_clkgen_get_clock_bclk_mode(u32 module_index)
+{
+	register struct nx_disptop_clkgen_register_set *pregister;
+	u32 mode = 0;
+
+	pregister = __g_module_variables[module_index].__g_pregister;
+	mode = (pregister->clkenb & 3ul);
+
+	switch (mode) {
+	case 0:
+		return nx_bclkmode_disable;
+	case 2:
+		return nx_bclkmode_dynamic;
+	case 3:
+		return nx_bclkmode_always;
+	default:
+		break;
+	}
+	return nx_bclkmode_disable;
+}
+
+void nx_disp_top_clkgen_set_clock_pclk_mode(u32 module_index,
+					    enum nx_pclkmode mode)
+{
+	register struct nx_disptop_clkgen_register_set *pregister;
+	register u32 regvalue;
+	const u32 pclkmode_pos = 3;
+	u32 clkmode = 0;
+
+	pregister = __g_module_variables[module_index].__g_pregister;
+	switch (mode) {
+	case nx_pclkmode_dynamic:
+		clkmode = 0;
+		break;
+	case nx_pclkmode_always:
+		clkmode = 1;
+		break;
+	default:
+		break;
+	}
+
+	regvalue = pregister->clkenb;
+	regvalue &= ~(1ul << pclkmode_pos);
+	regvalue |= (clkmode & 0x01) << pclkmode_pos;
+
+	writel(regvalue, &pregister->clkenb);
+}
+
+enum nx_pclkmode nx_disp_top_clkgen_get_clock_pclk_mode(u32 module_index)
+{
+	register struct nx_disptop_clkgen_register_set *pregister;
+	const u32 pclkmode_pos = 3;
+
+	pregister = __g_module_variables[module_index].__g_pregister;
+
+	if (pregister->clkenb & (1ul << pclkmode_pos))
+		return nx_pclkmode_always;
+
+	return nx_pclkmode_dynamic;
+}
+
+void nx_disp_top_clkgen_set_clock_source(u32 module_index, u32 index,
+					 u32 clk_src)
+{
+	register struct nx_disptop_clkgen_register_set *pregister;
+	register u32 read_value;
+
+	const u32 clksrcsel_pos = 2;
+	const u32 clksrcsel_mask = 0x07 << clksrcsel_pos;
+
+	pregister = __g_module_variables[module_index].__g_pregister;
+
+	read_value = pregister->CLKGEN[index << 1];
+	read_value &= ~clksrcsel_mask;
+	read_value |= clk_src << clksrcsel_pos;
+
+	writel(read_value, &pregister->CLKGEN[index << 1]);
+}
+
+u32 nx_disp_top_clkgen_get_clock_source(u32 module_index, u32 index)
+{
+	register struct nx_disptop_clkgen_register_set *pregister;
+	const u32 clksrcsel_pos = 2;
+	const u32 clksrcsel_mask = 0x07 << clksrcsel_pos;
+
+	pregister = __g_module_variables[module_index].__g_pregister;
+
+	return (pregister->CLKGEN[index << 1] &
+		clksrcsel_mask) >> clksrcsel_pos;
+}
+
+void nx_disp_top_clkgen_set_clock_divisor(u32 module_index, u32 index,
+					  u32 divisor)
+{
+	register struct nx_disptop_clkgen_register_set *pregister;
+	const u32 clkdiv_pos = 5;
+	const u32 clkdiv_mask = 0xff << clkdiv_pos;
+	register u32 read_value;
+
+	pregister = __g_module_variables[module_index].__g_pregister;
+
+	read_value = pregister->CLKGEN[index << 1];
+	read_value &= ~clkdiv_mask;
+	read_value |= (divisor - 1) << clkdiv_pos;
+	writel(read_value, &pregister->CLKGEN[index << 1]);
+}
+
+u32 nx_disp_top_clkgen_get_clock_divisor(u32 module_index, u32 index)
+{
+	register struct nx_disptop_clkgen_register_set *pregister;
+	const u32 clkdiv_pos = 5;
+	const u32 clkdiv_mask = 0xff << clkdiv_pos;
+
+	pregister = __g_module_variables[module_index].__g_pregister;
+
+	return ((pregister->CLKGEN[index << 1] &
+		 clkdiv_mask) >> clkdiv_pos) + 1;
+}
+
+void nx_disp_top_clkgen_set_clock_divisor_enable(u32 module_index, int enable)
+{
+	register struct nx_disptop_clkgen_register_set *pregister;
+	register u32 read_value;
+	const u32 clkgenenb_pos = 2;
+	const u32 clkgenenb_mask = 1ul << clkgenenb_pos;
+
+	pregister = __g_module_variables[module_index].__g_pregister;
+
+	read_value = pregister->clkenb;
+	read_value &= ~clkgenenb_mask;
+	read_value |= (u32)enable << clkgenenb_pos;
+
+	writel(read_value, &pregister->clkenb);
+}
+
+int nx_disp_top_clkgen_get_clock_divisor_enable(u32 module_index)
+{
+	register struct nx_disptop_clkgen_register_set *pregister;
+	const u32 clkgenenb_pos = 2;
+	const u32 clkgenenb_mask = 1ul << clkgenenb_pos;
+
+	pregister = __g_module_variables[module_index].__g_pregister;
+
+	return (int)((pregister->clkenb &
+		      clkgenenb_mask) >> clkgenenb_pos);
+}
+
+void nx_disp_top_clkgen_set_clock_out_inv(u32 module_index, u32 index,
+					  int out_clk_inv)
+{
+	register struct nx_disptop_clkgen_register_set *pregister;
+	register u32 read_value;
+	const u32 outclkinv_pos = 1;
+	const u32 outclkinv_mask = 1ul << outclkinv_pos;
+
+	pregister = __g_module_variables[module_index].__g_pregister;
+
+	read_value = pregister->CLKGEN[index << 1];
+	read_value &= ~outclkinv_mask;
+	read_value |= out_clk_inv << outclkinv_pos;
+
+	writel(read_value, &pregister->CLKGEN[index << 1]);
+}
+
+int nx_disp_top_clkgen_get_clock_out_inv(u32 module_index, u32 index)
+{
+	register struct nx_disptop_clkgen_register_set *pregister;
+	const u32 outclkinv_pos = 1;
+	const u32 outclkinv_mask = 1ul << outclkinv_pos;
+
+	pregister = __g_module_variables[module_index].__g_pregister;
+
+	return (int)((pregister->CLKGEN[index << 1] &
+		      outclkinv_mask) >> outclkinv_pos);
+}
+
+int nx_disp_top_clkgen_set_input_inv(u32 module_index,
+				     u32 index, int in_clk_inv)
+{
+	register struct nx_disptop_clkgen_register_set *pregister;
+	register u32 read_value;
+	const u32 inclkinv_pos = 4 + index;
+	const u32 inclkinv_mask = 1ul << inclkinv_pos;
+
+	pregister = __g_module_variables[module_index].__g_pregister;
+
+	read_value = pregister->clkenb;
+	read_value &= ~inclkinv_mask;
+	read_value |= in_clk_inv << inclkinv_pos;
+
+	writel(read_value, &pregister->clkenb);
+	return true;
+}
+
+int nx_disp_top_clkgen_get_input_inv(u32 module_index, u32 index)
+{
+	register struct nx_disptop_clkgen_register_set *pregister;
+	const u32 inclkinv_pos = 4 + index;
+	const u32 inclkinv_mask = 1ul << inclkinv_pos;
+
+	pregister = __g_module_variables[module_index].__g_pregister;
+
+	return (int)((pregister->clkenb &
+		      inclkinv_mask) >> inclkinv_pos);
+}
+
+void nx_disp_top_clkgen_set_clock_out_select(u32 module_index, u32 index,
+					     int bbypass)
+{
+	register struct nx_disptop_clkgen_register_set *pregister;
+	register u32 read_value;
+
+	pregister = __g_module_variables[module_index].__g_pregister;
+
+	read_value = pregister->CLKGEN[index << 1];
+	read_value = read_value & (~0x01);
+	read_value = read_value | bbypass;
+
+	writel(read_value, &pregister->CLKGEN[index << 1]);
+}
diff --git a/drivers/video/nexell/soc/s5pxx18_soc_disptop_clk.h b/drivers/video/nexell/soc/s5pxx18_soc_disptop_clk.h
new file mode 100644
index 0000000..d55fef7
--- /dev/null
+++ b/drivers/video/nexell/soc/s5pxx18_soc_disptop_clk.h
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: GPL-2.0+
+ *
+ * Copyright (C) 2016  Nexell Co., Ltd.
+ *
+ * Author: junghyun, kim <jhkim@nexell.co.kr>
+ */
+
+#ifndef _S5PXX18_SOC_DISPTOP_CLK_H_
+#define _S5PXX18_SOC_DISPTOP_CLK_H_
+
+#include "s5pxx18_soc_disptype.h"
+
+#define	PHY_BASEADDR_DISPTOP_CLKGEN_LIST	\
+		{ PHY_BASEADDR_DISPTOP_CLKGEN0_MODULE, \
+		  PHY_BASEADDR_DISPTOP_CLKGEN1_MODULE, \
+		  PHY_BASEADDR_DISPTOP_CLKGEN2_MODULE, \
+		  PHY_BASEADDR_DISPTOP_CLKGEN3_MODULE, \
+		  PHY_BASEADDR_DISPTOP_CLKGEN4_MODULE, \
+		}
+
+struct nx_disptop_clkgen_register_set {
+	u32 clkenb;
+	u32 CLKGEN[4];
+};
+
+int nx_disp_top_clkgen_initialize(void);
+u32 nx_disp_top_clkgen_get_number_of_module(void);
+u32 nx_disp_top_clkgen_get_physical_address(u32 module_index);
+u32 nx_disp_top_clkgen_get_size_of_register_set(void);
+void nx_disp_top_clkgen_set_base_address(u32 module_index,
+					 void *base_address);
+void *nx_disp_top_clkgen_get_base_address(u32 module_index);
+void nx_disp_top_clkgen_set_clock_pclk_mode(u32 module_index,
+					    enum nx_pclkmode mode);
+enum nx_pclkmode nx_disp_top_clkgen_get_clock_pclk_mode(u32 module_index);
+void nx_disp_top_clkgen_set_clock_source(u32 module_index, u32 index,
+					 u32 clk_src);
+u32 nx_disp_top_clkgen_get_clock_source(u32 module_index, u32 index);
+void nx_disp_top_clkgen_set_clock_divisor(u32 module_index, u32 index,
+					  u32 divisor);
+u32 nx_disp_top_clkgen_get_clock_divisor(u32 module_index, u32 index);
+void nx_disp_top_clkgen_set_clock_divisor_enable(u32 module_index,
+						 int enable);
+int nx_disp_top_clkgen_get_clock_divisor_enable(u32 module_index);
+void nx_disp_top_clkgen_set_clock_bclk_mode(u32 module_index,
+					    enum nx_bclkmode mode);
+enum nx_bclkmode nx_disp_top_clkgen_get_clock_bclk_mode(u32 module_index);
+
+void nx_disp_top_clkgen_set_clock_out_inv(u32 module_index, u32 index,
+					  int out_clk_inv);
+int nx_disp_top_clkgen_get_clock_out_inv(u32 module_index, u32 index);
+int nx_disp_top_clkgen_set_input_inv(u32 module_index, u32 index,
+				     int out_clk_inv);
+int nx_disp_top_clkgen_get_input_inv(u32 module_index, u32 index);
+
+void nx_disp_top_clkgen_set_clock_out_select(u32 module_index, u32 index,
+					     int bbypass);
+
+#endif
diff --git a/drivers/video/nexell/soc/s5pxx18_soc_disptype.h b/drivers/video/nexell/soc/s5pxx18_soc_disptype.h
new file mode 100644
index 0000000..b5df7a7
--- /dev/null
+++ b/drivers/video/nexell/soc/s5pxx18_soc_disptype.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0+
+ *
+ * Copyright (C) 2016  Nexell Co., Ltd.
+ *
+ * Author: junghyun, kim <jhkim@nexell.co.kr>
+ */
+
+#ifndef _S5PXX18_SOC_DISP_TYPE_H_
+#define _S5PXX18_SOC_DISP_TYPE_H_
+
+/* clock control types */
+enum nx_pclkmode {
+	nx_pclkmode_dynamic = 0UL,
+	nx_pclkmode_always	= 1UL
+};
+
+enum nx_bclkmode {
+	nx_bclkmode_disable	= 0UL,
+	nx_bclkmode_dynamic	= 2UL,
+	nx_bclkmode_always	= 3UL
+};
+
+#endif
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [RFC PATCH v2 08/13] video: add nexell video driver (soc: mlc, mipi)
  2020-03-28  9:43 [RFC PATCH v2 00/13] arm: add support for SoC S5P4418 Stefan Bosch
                   ` (6 preceding siblings ...)
  2020-03-28  9:43 ` [RFC PATCH v2 07/13] video: add nexell video driver (soc: displaytop) Stefan Bosch
@ 2020-03-28  9:43 ` Stefan Bosch
  2020-03-28  9:43 ` [RFC PATCH v2 09/13] video: add nexell video driver (soc: lvds, hdmi) Stefan Bosch
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 21+ messages in thread
From: Stefan Bosch @ 2020-03-28  9:43 UTC (permalink / raw)
  To: u-boot

Low level functions for MLC (Multi Layer Control) and MIPI (Mobile
Industry Processor Interface).

Signed-off-by: Stefan Bosch <stefan_b@posteo.net>
---

Changes in v2: None

 drivers/video/nexell/soc/s5pxx18_soc_mipi.c |  580 +++++++++
 drivers/video/nexell/soc/s5pxx18_soc_mipi.h |  291 +++++
 drivers/video/nexell/soc/s5pxx18_soc_mlc.c  | 1861 +++++++++++++++++++++++++++
 drivers/video/nexell/soc/s5pxx18_soc_mlc.h  |  429 ++++++
 4 files changed, 3161 insertions(+)
 create mode 100644 drivers/video/nexell/soc/s5pxx18_soc_mipi.c
 create mode 100644 drivers/video/nexell/soc/s5pxx18_soc_mipi.h
 create mode 100644 drivers/video/nexell/soc/s5pxx18_soc_mlc.c
 create mode 100644 drivers/video/nexell/soc/s5pxx18_soc_mlc.h

diff --git a/drivers/video/nexell/soc/s5pxx18_soc_mipi.c b/drivers/video/nexell/soc/s5pxx18_soc_mipi.c
new file mode 100644
index 0000000..1000ddb
--- /dev/null
+++ b/drivers/video/nexell/soc/s5pxx18_soc_mipi.c
@@ -0,0 +1,580 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2016  Nexell Co., Ltd.
+ *
+ * Author: junghyun, kim <jhkim@nexell.co.kr>
+ */
+
+#include <linux/types.h>
+#include <linux/io.h>
+
+#include "s5pxx18_soc_disptop.h"
+#include "s5pxx18_soc_mipi.h"
+
+static struct nx_mipi_register_set *__g_pregister[NUMBER_OF_MIPI_MODULE];
+
+int nx_mipi_smoke_test(u32 module_index)
+{
+	register struct nx_mipi_register_set *pregister;
+
+	pregister = __g_pregister[module_index];
+
+	if (pregister->csis_config_ch0 != 0x000000FC)
+		return false;
+
+	if (pregister->dsim_intmsk != 0xB337FFFF)
+		return false;
+
+	writel(0xDEADC0DE, &pregister->csis_dphyctrl);
+	writel(0xFFFFFFFF, &pregister->csis_ctrl2);
+	writel(0xDEADC0DE, &pregister->dsim_msync);
+
+	if (pregister->csis_dphyctrl != 0xDE80001E)
+		return false;
+
+	if ((pregister->csis_ctrl2 & (~1)) != 0xEEE00010)
+		return false;
+
+	if (pregister->dsim_msync != 0xDE80C0DE)
+		return false;
+
+	return true;
+}
+
+void nx_mipi_set_base_address(u32 module_index, void *base_address)
+{
+	__g_pregister[module_index] =
+	    (struct nx_mipi_register_set *)base_address;
+}
+
+void *nx_mipi_get_base_address(u32 module_index)
+{
+	return (void *)__g_pregister[module_index];
+}
+
+u32 nx_mipi_get_physical_address(u32 module_index)
+{
+	const u32 physical_addr[] = PHY_BASEADDR_MIPI_LIST;
+
+	return physical_addr[module_index];
+}
+
+#define __nx_mipi_valid_dsi_intmask__	\
+	(~((1 << 26) | (1 << 23) | (1 << 22) | (1 << 19)))
+
+void nx_mipi_set_interrupt_enable(u32 module_index, u32 int_num, int enable)
+{
+	register struct nx_mipi_register_set *pregister;
+	register u32 regvalue;
+
+	pregister = __g_pregister[module_index];
+	if (int_num < 32) {
+		regvalue = pregister->csis_intmsk;
+		regvalue &= ~(1ul << int_num);
+		regvalue |= (u32)enable << int_num;
+		writel(regvalue, &pregister->csis_intmsk);
+	} else {
+		regvalue = pregister->dsim_intmsk;
+		regvalue &= ~(1ul << (int_num - 32));
+		regvalue |= (u32)enable << (int_num - 32);
+		writel(regvalue, &pregister->dsim_intmsk);
+	}
+}
+
+int nx_mipi_get_interrupt_enable(u32 module_index, u32 int_num)
+{
+	if (int_num < 32)
+		return (int)((__g_pregister[module_index]->csis_intmsk >>
+			      int_num) & 0x01);
+	else
+		return (int)((__g_pregister[module_index]->dsim_intmsk >>
+			      (int_num - 32)) & 0x01);
+}
+
+int nx_mipi_get_interrupt_pending(u32 module_index, u32 int_num)
+{
+	register struct nx_mipi_register_set *pregister;
+	register u32 regvalue;
+	int ret;
+
+	pregister = __g_pregister[module_index];
+	if (int_num < 32) {
+		regvalue = pregister->csis_intmsk;
+		regvalue &= pregister->csis_intsrc;
+		ret = (int)((regvalue >> int_num) & 0x01);
+	} else {
+		regvalue = pregister->dsim_intmsk;
+		regvalue &= pregister->dsim_intsrc;
+		ret = (int)((regvalue >> (int_num - 32)) & 0x01);
+	}
+
+	return ret;
+}
+
+void nx_mipi_clear_interrupt_pending(u32 module_index, u32 int_num)
+{
+	register struct nx_mipi_register_set *pregister;
+
+	pregister = __g_pregister[module_index];
+	if (int_num < 32)
+		writel(1ul << int_num, &pregister->csis_intsrc);
+	else
+		writel(1ul << (int_num - 32), &pregister->dsim_intsrc);
+}
+
+void nx_mipi_set_interrupt_enable_all(u32 module_index, int enable)
+{
+	register struct nx_mipi_register_set *pregister;
+
+	pregister = __g_pregister[module_index];
+	if (enable)
+		writel(__nx_mipi_valid_dsi_intmask__, &pregister->dsim_intmsk);
+	else
+		writel(0, &pregister->dsim_intmsk);
+}
+
+int nx_mipi_get_interrupt_enable_all(u32 module_index)
+{
+	if (__g_pregister[module_index]->csis_intmsk)
+		return true;
+
+	if (__g_pregister[module_index]->dsim_intmsk)
+		return true;
+
+	return false;
+}
+
+int nx_mipi_get_interrupt_pending_all(u32 module_index)
+{
+	register struct nx_mipi_register_set *pregister;
+	register u32 regvalue;
+
+	pregister = __g_pregister[module_index];
+	regvalue = pregister->csis_intmsk;
+	regvalue &= pregister->csis_intsrc;
+
+	if (regvalue)
+		return true;
+
+	regvalue = pregister->dsim_intmsk;
+	regvalue &= pregister->dsim_intsrc;
+
+	if (regvalue)
+		return true;
+
+	return false;
+}
+
+void nx_mipi_clear_interrupt_pending_all(u32 module_index)
+{
+	register struct nx_mipi_register_set *pregister;
+
+	pregister = __g_pregister[module_index];
+	writel(__nx_mipi_valid_dsi_intmask__, &pregister->dsim_intsrc);
+}
+
+int32_t nx_mipi_get_interrupt_pending_number(u32 module_index)
+{
+	register struct nx_mipi_register_set *pregister;
+	register u32 regvalue;
+	int i;
+
+	pregister = __g_pregister[module_index];
+	regvalue = pregister->csis_intmsk;
+	regvalue &= pregister->csis_intsrc;
+	if (regvalue != 0) {
+		for (i = 0; i < 32; i++) {
+			if (regvalue & 1ul)
+				return i;
+			regvalue >>= 1;
+		}
+	}
+
+	regvalue = pregister->dsim_intmsk;
+	regvalue &= pregister->dsim_intsrc;
+	if (regvalue != 0) {
+		for (i = 0; i < 32; i++) {
+			if (regvalue & 1ul)
+				return i + 32;
+			regvalue >>= 1;
+		}
+	}
+	return -1;
+}
+
+#define writereg(regname, mask, value) \
+	regvalue = pregister->(regname);	\
+	regvalue = (regvalue & (~(mask))) | (value); \
+	writel(regvalue, &pregister->(regname))
+
+void nx_mipi_dsi_get_status(u32 module_index, u32 *pulps, u32 *pstop,
+			    u32 *pispllstable, u32 *pisinreset,
+			    u32 *pisbackward, u32 *pishsclockready)
+{
+	register struct nx_mipi_register_set *pregister;
+	register u32 regvalue;
+
+	pregister = __g_pregister[module_index];
+	regvalue = pregister->dsim_status;
+	if (pulps) {
+		*pulps = 0;
+		if (regvalue & (1 << 4))
+			*pulps |= (1 << 0);
+		if (regvalue & (1 << 5))
+			*pulps |= (1 << 1);
+		if (regvalue & (1 << 6))
+			*pulps |= (1 << 2);
+		if (regvalue & (1 << 7))
+			*pulps |= (1 << 3);
+		if (regvalue & (1 << 9))
+			*pulps |= (1 << 4);
+	}
+
+	if (pstop) {
+		*pstop = 0;
+		if (regvalue & (1 << 0))
+			*pstop |= (1 << 0);
+		if (regvalue & (1 << 1))
+			*pstop |= (1 << 1);
+		if (regvalue & (1 << 2))
+			*pstop |= (1 << 2);
+		if (regvalue & (1 << 3))
+			*pstop |= (1 << 3);
+		if (regvalue & (1 << 8))
+			*pstop |= (1 << 4);
+	}
+
+	if (pispllstable)
+		*pispllstable = (regvalue >> 31) & 1;
+
+	if (pisinreset)
+		*pisinreset = ((regvalue >> 20) & 1) ? 0 : 1;
+
+	if (pisbackward)
+		*pisbackward = (regvalue >> 16) & 1;
+
+	if (pishsclockready)
+		*pishsclockready = (regvalue >> 10) & 1;
+}
+
+void nx_mipi_dsi_software_reset(u32 module_index)
+{
+	register struct nx_mipi_register_set *pregister;
+
+	pregister = __g_pregister[module_index];
+
+	writel(0x00010001, &pregister->dsim_swrst);
+
+	while (0 != (readl(&pregister->dsim_status) & (1 << 20)))
+		;
+
+	writel(0x00000000, &pregister->dsim_swrst);
+}
+
+void nx_mipi_dsi_set_clock(u32 module_index, int enable_txhsclock,
+			   int use_external_clock, int enable_byte_clock,
+			   int enable_escclock_clock_lane,
+			   int enable_escclock_data_lane0,
+			   int enable_escclock_data_lane1,
+			   int enable_escclock_data_lane2,
+			   int enable_escclock_data_lane3,
+			   int enable_escprescaler, u32 escprescalervalue)
+{
+	register struct nx_mipi_register_set *pregister;
+	register u32 regvalue;
+
+	pregister = __g_pregister[module_index];
+	regvalue = 0;
+	regvalue |= (enable_txhsclock << 31);
+	regvalue |= (use_external_clock << 27);
+	regvalue |= (enable_byte_clock << 24);
+	regvalue |= (enable_escclock_clock_lane << 19);
+	regvalue |= (enable_escclock_data_lane0 << 20);
+	regvalue |= (enable_escclock_data_lane1 << 21);
+	regvalue |= (enable_escclock_data_lane2 << 22);
+	regvalue |= (enable_escclock_data_lane3 << 23);
+	regvalue |= (enable_escprescaler << 28);
+	regvalue |= escprescalervalue;
+
+	writel(regvalue, &pregister->dsim_clkctrl);
+}
+
+void nx_mipi_dsi_set_timeout(u32 module_index, u32 bta_tout, u32 lpdrtout)
+{
+	register struct nx_mipi_register_set *pregister;
+	register u32 regvalue;
+
+	pregister = __g_pregister[module_index];
+	regvalue = 0;
+	regvalue |= (bta_tout << 16);
+	regvalue |= (lpdrtout << 0);
+
+	writel(regvalue, &pregister->dsim_timeout);
+}
+
+void nx_mipi_dsi_set_config_video_mode(u32 module_index,
+				       int enable_auto_flush_main_display_fifo,
+				       int enable_auto_vertical_count,
+				       int enable_burst,
+				       enum nx_mipi_dsi_syncmode sync_mode,
+				       int enable_eo_tpacket,
+				       int enable_hsync_end_packet,
+				       int enable_hfp, int enable_hbp,
+				       int enable_hsa,
+				       u32 number_of_virtual_channel,
+				       enum nx_mipi_dsi_format format,
+				       u32 number_of_words_in_hfp,
+				       u32 number_of_words_in_hbp,
+				       u32 number_of_words_in_hsync,
+				       u32 number_of_lines_in_vfp,
+				       u32 number_of_lines_in_vbp,
+				       u32 number_of_lines_in_vsync,
+				       u32 number_of_lines_in_command_allow)
+{
+	register struct nx_mipi_register_set *pregister;
+	register u32 regvalue;
+	u32 newvalue;
+
+	pregister = __g_pregister[module_index];
+	newvalue = (1 << 25);
+	newvalue |= ((1 - enable_auto_flush_main_display_fifo) << 29);
+	newvalue |= (enable_auto_vertical_count << 24);
+	newvalue |= (enable_burst << 26);
+	newvalue |= (sync_mode << 27);
+	newvalue |= ((1 - enable_eo_tpacket) << 28);
+	newvalue |= (enable_hsync_end_packet << 23);
+	newvalue |= ((1 - enable_hfp) << 22);
+	newvalue |= ((1 - enable_hbp) << 21);
+	newvalue |= ((1 - enable_hsa) << 20);
+	newvalue |= (number_of_virtual_channel << 18);
+	newvalue |= (format << 12);
+
+	writereg(dsim_config, 0xFFFFFF00, newvalue);
+
+	newvalue = (number_of_lines_in_command_allow << 28);
+	newvalue |= (number_of_lines_in_vfp << 16);
+	newvalue |= (number_of_lines_in_vbp << 0);
+
+	writel(newvalue, &pregister->dsim_mvporch);
+
+	newvalue = (number_of_words_in_hfp << 16);
+	newvalue |= (number_of_words_in_hbp << 0);
+
+	writel(newvalue, &pregister->dsim_mhporch);
+
+	newvalue = (number_of_words_in_hsync << 0);
+	newvalue |= (number_of_lines_in_vsync << 22);
+
+	writel(newvalue, &pregister->dsim_msync);
+}
+
+void nx_mipi_dsi_set_config_command_mode(u32 module_index,
+					 int
+					 enable_auto_flush_main_display_fifo,
+					 int enable_eo_tpacket,
+					 u32 number_of_virtual_channel,
+					 enum nx_mipi_dsi_format format)
+{
+	register struct nx_mipi_register_set *pregister;
+	register u32 regvalue;
+	u32 newvalue;
+
+	pregister = __g_pregister[module_index];
+	newvalue = (0 << 25);
+	newvalue |= (enable_auto_flush_main_display_fifo << 29);
+	newvalue |= (enable_eo_tpacket << 28);
+	newvalue |= (number_of_virtual_channel << 18);
+	newvalue |= (format << 12);
+	writereg(dsim_config, 0xFFFFFF00, newvalue);
+}
+
+void nx_mipi_dsi_set_escape_mode(u32 module_index, u32 stop_state_count,
+				 int force_stop_state, int force_bta,
+				 enum nx_mipi_dsi_lpmode cmdin_lp,
+				 enum nx_mipi_dsi_lpmode txinlp)
+{
+	register struct nx_mipi_register_set *pregister;
+	register u32 regvalue;
+	u32 newvalue;
+
+	pregister = __g_pregister[module_index];
+	newvalue = (stop_state_count << 21);
+	newvalue |= (force_stop_state << 20);
+	newvalue |= (force_bta << 16);
+	newvalue |= (cmdin_lp << 7);
+	newvalue |= (txinlp << 6);
+	writereg(dsim_escmode, 0xFFFFFFC0, newvalue);
+}
+
+void nx_mipi_dsi_set_escape_lp(u32 module_index,
+			       enum nx_mipi_dsi_lpmode cmdin_lp,
+			       enum nx_mipi_dsi_lpmode txinlp)
+{
+	register struct nx_mipi_register_set *pregister;
+	register u32 regvalue;
+	u32 newvalue = 0;
+
+	pregister = __g_pregister[module_index];
+	newvalue |= (cmdin_lp << 7);
+	newvalue |= (txinlp << 6);
+	writereg(dsim_escmode, 0xC0, newvalue);
+}
+
+void nx_mipi_dsi_remote_reset_trigger(u32 module_index)
+{
+	register struct nx_mipi_register_set *pregister;
+	register u32 regvalue;
+	u32 newvalue;
+
+	pregister = __g_pregister[module_index];
+	newvalue = (1 << 4);
+	writereg(dsim_escmode, (1 << 4), newvalue);
+
+	while (readl(&pregister->dsim_escmode) & (1 << 4))
+		;
+}
+
+void nx_mipi_dsi_set_ulps(u32 module_index, int ulpsclocklane, int ulpsdatalane)
+{
+	register struct nx_mipi_register_set *pregister;
+	register u32 regvalue;
+
+	pregister = __g_pregister[module_index];
+	regvalue = pregister->dsim_escmode;
+
+	if (ulpsclocklane) {
+		regvalue &= ~(1 << 0);
+		regvalue |= (1 << 1);
+	} else {
+		regvalue |= (1 << 0);
+	}
+
+	if (ulpsdatalane) {
+		regvalue &= ~(1 << 2);
+		regvalue |= (1 << 3);
+	} else {
+		regvalue |= (1 << 2);
+	}
+
+	writel(regvalue, &pregister->dsim_escmode);
+
+	if (ulpsclocklane)
+		while ((1 << 9) ==
+		       (readl(&pregister->dsim_status) & (1 << 9)))
+			;
+	else
+		while (0 != (readl(&pregister->dsim_status) & (1 << 9)))
+			;
+
+	if (ulpsdatalane)
+		while ((15 << 4) ==
+		       (readl(&pregister->dsim_status) & (15 << 4)))
+			;
+	else
+		while (0 != (readl(&pregister->dsim_status) & (15 << 4)))
+			;
+
+	if (!ulpsclocklane)
+		regvalue &= (3 << 0);
+
+	if (!ulpsdatalane)
+		regvalue |= (3 << 2);
+
+	writel(regvalue, &pregister->dsim_escmode);
+}
+
+void nx_mipi_dsi_set_size(u32 module_index, u32 width, u32 height)
+{
+	register struct nx_mipi_register_set *pregister;
+	register u32 regvalue;
+	u32 newvalue;
+
+	pregister = __g_pregister[module_index];
+	newvalue = (height << 16);
+	newvalue |= (width << 0);
+	writereg(dsim_mdresol, 0x0FFFFFFF, newvalue);
+}
+
+void nx_mipi_dsi_set_enable(u32 module_index, int enable)
+{
+	register struct nx_mipi_register_set *pregister;
+	register u32 regvalue;
+
+	pregister = __g_pregister[module_index];
+	writereg(dsim_mdresol, (1 << 31), (enable << 31));
+}
+
+void nx_mipi_dsi_set_phy(u32 module_index, u32 number_of_data_lanes,
+			 int enable_clock_lane, int enable_data_lane0,
+			 int enable_data_lane1, int enable_data_lane2,
+			 int enable_data_lane3, int swap_clock_lane,
+			 int swap_data_lane)
+{
+	register struct nx_mipi_register_set *pregister;
+	register u32 regvalue;
+	u32 newvalue;
+
+	pregister = __g_pregister[module_index];
+	newvalue = (number_of_data_lanes << 5);
+	newvalue |= (enable_clock_lane << 0);
+	newvalue |= (enable_data_lane0 << 1);
+	newvalue |= (enable_data_lane1 << 2);
+	newvalue |= (enable_data_lane2 << 3);
+	newvalue |= (enable_data_lane3 << 4);
+	writereg(dsim_config, 0xFF, newvalue);
+	newvalue = (swap_clock_lane << 1);
+	newvalue |= (swap_data_lane << 0);
+	writereg(dsim_phyacchr1, 0x3, newvalue);
+}
+
+void nx_mipi_dsi_set_pll(u32 module_index, int enable, u32 pllstabletimer,
+			 u32 m_pllpms, u32 m_bandctl, u32 m_dphyctl,
+			 u32 b_dphyctl)
+{
+	register struct nx_mipi_register_set *pregister;
+	register u32 regvalue;
+	u32 newvalue;
+
+	pregister = __g_pregister[module_index];
+	if (!enable) {
+		newvalue = (enable << 23);
+		newvalue |= (m_pllpms << 1);
+		newvalue |= (m_bandctl << 24);
+		writereg(dsim_pllctrl, 0x0FFFFFFF, newvalue);
+	}
+
+	writel(m_dphyctl, &pregister->dsim_phyacchr);
+	writel(pllstabletimer, &pregister->dsim_plltmr);
+	writel((b_dphyctl << 9), &pregister->dsim_phyacchr1);
+
+	if (enable) {
+		newvalue = (enable << 23);
+		newvalue |= (m_pllpms << 1);
+		newvalue |= (m_bandctl << 24);
+		writereg(dsim_pllctrl, 0x0FFFFFFF, newvalue);
+	}
+}
+
+void nx_mipi_dsi_write_pkheader(u32 module_index, u32 data)
+{
+	register struct nx_mipi_register_set *pregister;
+
+	pregister = __g_pregister[module_index];
+	writel(data, &pregister->dsim_pkthdr);
+}
+
+void nx_mipi_dsi_write_payload(u32 module_index, u32 data)
+{
+	register struct nx_mipi_register_set *pregister;
+
+	pregister = __g_pregister[module_index];
+	writel(data, &pregister->dsim_payload);
+}
+
+u32 nx_mipi_dsi_read_fifo_status(u32 module_index)
+{
+	register struct nx_mipi_register_set *pregister;
+
+	pregister = __g_pregister[module_index];
+	return readl(&pregister->dsim_fifoctrl);
+}
diff --git a/drivers/video/nexell/soc/s5pxx18_soc_mipi.h b/drivers/video/nexell/soc/s5pxx18_soc_mipi.h
new file mode 100644
index 0000000..63751ca
--- /dev/null
+++ b/drivers/video/nexell/soc/s5pxx18_soc_mipi.h
@@ -0,0 +1,291 @@
+/* SPDX-License-Identifier: GPL-2.0+
+ *
+ * Copyright (C) 2016  Nexell Co., Ltd.
+ *
+ * Author: junghyun, kim <jhkim@nexell.co.kr>
+ */
+
+#ifndef _S5PXX18_SOC_MIPI_H_
+#define _S5PXX18_SOC_MIPI_H_
+
+#define NUMBER_OF_MIPI_MODULE 1
+#define PHY_BASEADDR_MIPI_MODULE	0xC00D0000
+#define	PHY_BASEADDR_MIPI_LIST	\
+		{ PHY_BASEADDR_MIPI_MODULE }
+
+#define nx_mipi_numberof_csi_channels 2
+
+struct nx_mipi_register_set {
+	u32 csis_control;
+	u32 csis_dphyctrl;
+	u32 csis_config_ch0;
+	u32 csis_dphysts;
+	u32 csis_intmsk;
+	u32 csis_intsrc;
+	u32 csis_ctrl2;
+	u32 csis_version;
+	u32 csis_dphyctrl_0;
+	u32 csis_dphyctrl_1;
+	u32 __reserved0;
+	u32 csis_resol_ch0;
+	u32 __reserved1;
+	u32 __reserved2;
+	u32 sdw_config_ch0;
+	u32 sdw_resol_ch0;
+	u32 csis_config_ch1;
+	u32 csis_resol_ch1;
+	u32 sdw_config_ch1;
+	u32 sdw_resol_ch1;
+	u32 csis_config_ch2;
+	u32 csis_resol_ch2;
+	u32 sdw_config_ch2;
+	u32 sdw_resol_ch2;
+	u32 csis_config_ch3;
+	u32 csis_resol_ch3;
+	u32 sdw_config_ch3;
+	u32 sdw_resol_3;
+	u32 __reserved3[(16 + 128) / 4];
+
+	u32 dsim_status;
+	u32 dsim_swrst;
+	u32 dsim_clkctrl;
+	u32 dsim_timeout;
+	u32 dsim_config;
+	u32 dsim_escmode;
+	u32 dsim_mdresol;
+	u32 dsim_mvporch;
+	u32 dsim_mhporch;
+	u32 dsim_msync;
+	u32 dsim_sdresol;
+	u32 dsim_intsrc;
+	u32 dsim_intmsk;
+	u32 dsim_pkthdr;
+	u32 dsim_payload;
+	u32 dsim_rxfifo;
+	u32 dsim_fifothld;
+	u32 dsim_fifoctrl;
+	u32 dsim_memacchr;
+	u32 dsim_pllctrl;
+	u32 dsim_plltmr;
+	u32 dsim_phyacchr;
+	u32 dsim_phyacchr1;
+
+	u32 __reserved4[(0x2000 - 0x015C) / 4];
+	u32 mipi_csis_pktdata[0x2000 / 4];
+};
+
+enum nx_mipi_dsi_syncmode {
+	nx_mipi_dsi_syncmode_event = 0,
+	nx_mipi_dsi_syncmode_pulse = 1,
+};
+
+enum nx_mipi_dsi_format {
+	nx_mipi_dsi_format_command3 = 0,
+	nx_mipi_dsi_format_command8 = 1,
+	nx_mipi_dsi_format_command12 = 2,
+	nx_mipi_dsi_format_command16 = 3,
+	nx_mipi_dsi_format_rgb565 = 4,
+	nx_mipi_dsi_format_rgb666_packed = 5,
+	nx_mipi_dsi_format_rgb666 = 6,
+	nx_mipi_dsi_format_rgb888 = 7
+};
+
+enum nx_mipi_dsi_lpmode {
+	nx_mipi_dsi_lpmode_hs = 0,
+	nx_mipi_dsi_lpmode_lp = 1
+};
+
+enum nx_mipi_phy_b_dphyctl {
+	nx_mipi_phy_b_dphyctl_m_txclkesc_20_mhz = 0x1F4,
+	nx_mipi_phy_b_dphyctl_m_txclkesc_19_mhz = 0x1DB,
+	nx_mipi_phy_b_dphyctl_m_txclkesc_18_mhz = 0x1C2,
+	nx_mipi_phy_b_dphyctl_m_txclkesc_17_mhz = 0x1A9,
+	nx_mipi_phy_b_dphyctl_m_txclkesc_16_mhz = 0x190,
+	nx_mipi_phy_b_dphyctl_m_txclkesc_15_mhz = 0x177,
+	nx_mipi_phy_b_dphyctl_m_txclkesc_14_mhz = 0x15E,
+	nx_mipi_phy_b_dphyctl_m_txclkesc_13_mhz = 0x145,
+	nx_mipi_phy_b_dphyctl_m_txclkesc_12_mhz = 0x12C,
+	nx_mipi_phy_b_dphyctl_m_txclkesc_11_mhz = 0x113,
+	nx_mipi_phy_b_dphyctl_m_txclkesc_10_mhz = 0x0FA,
+	nx_mipi_phy_b_dphyctl_m_txclkesc_9_mhz = 0x0E1,
+	nx_mipi_phy_b_dphyctl_m_txclkesc_8_mhz = 0x0C8,
+	nx_mipi_phy_b_dphyctl_m_txclkesc_7_mhz = 0x0AF,
+	nx_mipi_phy_b_dphyctl_m_txclkesc_6_mhz = 0x096,
+	nx_mipi_phy_b_dphyctl_m_txclkesc_5_mhz = 0x07D,
+	nx_mipi_phy_b_dphyctl_m_txclkesc_4_mhz = 0x064,
+	nx_mipi_phy_b_dphyctl_m_txclkesc_3_mhz = 0x04B,
+	nx_mipi_phy_b_dphyctl_m_txclkesc_2_mhz = 0x032,
+	nx_mipi_phy_b_dphyctl_m_txclkesc_1_mhz = 0x019,
+	nx_mipi_phy_b_dphyctl_m_txclkesc_0_10_mhz = 0x003,
+	nx_mipi_phy_b_dphyctl_m_txclkesc_0_01_mhz = 0x000
+};
+
+enum {
+	nx_mipi_rst = 0,
+	nx_mipi_rst_dsi_i,
+	nx_mipi_rst_csi_i,
+	nx_mipi_rst_phy_s,
+	nx_mipi_rst_phy_m
+};
+
+enum nx_mipi_int {
+	nx_mipi_int_csi_even_before = 31,
+	nx_mipi_int_csi_even_after = 30,
+	nx_mipi_int_csi_odd_before = 29,
+	nx_mipi_int_csi_odd_after = 28,
+	nx_mipi_int_csi_frame_start_ch3 = 27,
+	nx_mipi_int_csi_frame_start_ch2 = 26,
+	nx_mipi_int_csi_frame_start_ch1 = 25,
+	nx_mipi_int_csi_frame_start_ch0 = 24,
+	nx_mipi_int_csi_frame_end_ch3 = 23,
+	nx_mipi_int_csi_frame_end_ch2 = 22,
+	nx_mipi_int_csi_frame_end_ch1 = 21,
+	nx_mipi_int_csi_frame_end_ch0 = 20,
+	nx_mipi_int_csi_err_sot_hs_ch3 = 19,
+	nx_mipi_int_csi_err_sot_hs_ch2 = 18,
+	nx_mipi_int_csi_err_sot_hs_ch1 = 17,
+	nx_mipi_int_csi_err_sot_hs_ch0 = 16,
+	nx_mipi_int_csi_err_lost_fs_ch3 = 15,
+	nx_mipi_int_csi_err_lost_fs_ch2 = 14,
+	nx_mipi_int_csi_err_lost_fs_ch1 = 13,
+	nx_mipi_int_csi_err_lost_fs_ch0 = 12,
+	nx_mipi_int_csi_err_lost_fe_ch3 = 11,
+	nx_mipi_int_csi_err_lost_fe_ch2 = 10,
+	nx_mipi_int_csi_err_lost_fe_ch1 = 9,
+	nx_mipi_int_csi_err_lost_fe_ch0 = 8,
+	nx_mipi_int_csi_err_over_ch3 = 7,
+	nx_mipi_int_csi_err_over_ch2 = 6,
+	nx_mipi_int_csi_err_over_ch1 = 5,
+	nx_mipi_int_csi_err_over_ch0 = 4,
+
+	nx_mipi_int_csi_err_ecc = 2,
+	nx_mipi_int_csi_err_crc = 1,
+	nx_mipi_int_csi_err_id = 0,
+	nx_mipi_int_dsi_pll_stable = 32 + 31,
+	nx_mipi_int_dsi_sw_rst_release = 32 + 30,
+	nx_mipi_int_dsi_sfrplfifoempty = 32 + 29,
+	nx_mipi_int_dsi_sfrphfifoempty = 32 + 28,
+	nx_mipi_int_dsi_sync_override = 32 + 27,
+
+	nx_mipi_int_dsi_bus_turn_over = 32 + 25,
+	nx_mipi_int_dsi_frame_done = 32 + 24,
+
+	nx_mipi_int_dsi_lpdr_tout = 32 + 21,
+	nx_mipi_int_dsi_ta_tout = 32 + 20,
+
+	nx_mipi_int_dsi_rx_dat_done = 32 + 18,
+	nx_mipi_int_dsi_rx_te = 32 + 17,
+	nx_mipi_int_dsi_rx_ack = 32 + 16,
+	nx_mipi_int_dsi_err_rx_ecc = 32 + 15,
+	nx_mipi_int_dsi_err_rx_crc = 32 + 14,
+	nx_mipi_int_dsi_err_esc3 = 32 + 13,
+	nx_mipi_int_dsi_err_esc2 = 32 + 12,
+	nx_mipi_int_dsi_err_esc1 = 32 + 11,
+	nx_mipi_int_dsi_err_esc0 = 32 + 10,
+	nx_mipi_int_dsi_err_sync3 = 32 + 9,
+	nx_mipi_int_dsi_err_sync2 = 32 + 8,
+	nx_mipi_int_dsi_err_sync1 = 32 + 7,
+	nx_mipi_int_dsi_err_sync0 = 32 + 6,
+	nx_mipi_int_dsi_err_control3 = 32 + 5,
+	nx_mipi_int_dsi_err_control2 = 32 + 4,
+	nx_mipi_int_dsi_err_control1 = 32 + 3,
+	nx_mipi_int_dsi_err_control0 = 32 + 2,
+	nx_mipi_int_dsi_err_content_lp0 = 32 + 1,
+	nx_mipi_int_dsi_err_content_lp1 = 32 + 0,
+};
+
+#define DSI_TX_FIFO_SIZE	2048
+#define DSI_RX_FIFO_SIZE	256
+#define DSI_RX_FIFO_EMPTY	0x30800002
+
+void nx_mipi_dsi_get_status(u32 module_index, u32 *pulps, u32 *pstop,
+			    u32 *pispllstable, u32 *pisinreset,
+			    u32 *pisbackward, u32 *pishsclockready);
+
+void nx_mipi_dsi_software_reset(u32 module_index);
+
+void nx_mipi_dsi_set_clock(u32 module_index, int enable_txhsclock,
+			   int use_external_clock, int enable_byte_clock,
+			   int enable_escclock_clock_lane,
+			   int enable_escclock_data_lane0,
+			   int enable_escclock_data_lane1,
+			   int enable_escclock_data_lane2,
+			   int enable_escclock_data_lane3,
+			   int enable_escprescaler,
+			   u32 escprescalervalue);
+
+void nx_mipi_dsi_set_timeout(u32 module_index, u32 bta_tout,
+			     u32 lpdrtout);
+
+void nx_mipi_dsi_set_config_video_mode(u32 module_index,
+				       int enable_auto_flush_main_display_fifo,
+				       int enable_auto_vertical_count,
+				       int enable_burst,
+				       enum nx_mipi_dsi_syncmode
+				       sync_mode, int enable_eo_tpacket,
+				       int enable_hsync_end_packet,
+				       int enable_hfp, int enable_hbp,
+				       int enable_hsa,
+				       u32 number_of_virtual_channel,
+				       enum nx_mipi_dsi_format format,
+				       u32 number_of_words_in_hfp,
+				       u32 number_of_words_in_hbp,
+				       u32 number_of_words_in_hsync,
+				       u32 number_of_lines_in_vfp,
+				       u32 number_of_lines_in_vbp,
+				       u32 number_of_lines_in_vsync,
+				       u32 number_of_lines_in_command_allow);
+
+void nx_mipi_dsi_set_config_command_mode(u32 module_index,
+					 int enable_auto_flush_main_display_fifo,
+					 int enable_eo_tpacket,
+					 u32 number_of_virtual_channel,
+					 enum nx_mipi_dsi_format format);
+
+void nx_mipi_dsi_set_escape_mode(u32 module_index, u32 stop_state_count,
+				 int force_stop_state, int force_bta,
+				 enum nx_mipi_dsi_lpmode cmdin_lp,
+				 enum nx_mipi_dsi_lpmode txinlp);
+void nx_mipi_dsi_set_escape_lp(u32 module_index,
+			       enum nx_mipi_dsi_lpmode cmdin_lp,
+			       enum nx_mipi_dsi_lpmode txinlp);
+
+void nx_mipi_dsi_remote_reset_trigger(u32 module_index);
+void nx_mipi_dsi_set_ulps(u32 module_index, int ulpsclocklane,
+			  int ulpsdatalane);
+void nx_mipi_dsi_set_size(u32 module_index, u32 width, u32 height);
+void nx_mipi_dsi_set_enable(u32 module_index, int enable);
+void nx_mipi_dsi_set_phy(u32 module_index, u32 number_of_data_lanes,
+			 int enable_clock_lane, int enable_data_lane0,
+			 int enable_data_lane1, int enable_data_lane2,
+			 int enable_data_lane3, int swap_clock_lane,
+			 int swap_data_lane);
+
+void nx_mipi_dsi_set_pll(u32 module_index, int enable,
+			 u32 pllstabletimer, u32 m_pllpms, u32 m_bandctl,
+			 u32 m_dphyctl, u32 b_dphyctl);
+
+void nx_mipi_dsi_write_pkheader(u32 module_index, u32 data);
+void nx_mipi_dsi_write_payload(u32 module_index, u32 data);
+u32 nx_mipi_dsi_read_fifo(u32 module_index);
+u32 nx_mipi_dsi_read_fifo_status(u32 module_index);
+
+int nx_mipi_smoke_test(u32 module_index);
+void nx_mipi_set_base_address(u32 module_index, void *base_address);
+void *nx_mipi_get_base_address(u32 module_index);
+u32 nx_mipi_get_physical_address(u32 module_index);
+
+void nx_mipi_dsi_set_interrupt_enable_all(u32 module_index, int enable);
+void nx_mipi_dsi_set_interrupt_enable(u32 module_index,
+				      u32 int_num, int enable);
+int nx_mipi_dsi_get_interrupt_enable(u32 module_index, u32 int_num);
+int nx_mipi_dsi_get_interrupt_enable_all(u32 module_index);
+
+int nx_mipi_dsi_get_interrupt_pending(u32 module_index, u32 int_num);
+int nx_mipi_dsi_get_interrupt_pending_all(u32 module_index);
+int32_t nx_mipi_dsi_get_interrupt_pending_number(u32 module_index);
+
+void nx_mipi_dsi_clear_interrupt_pending(u32 module_index, u32 int_num);
+void nx_mipi_dsi_clear_interrupt_pending_all(u32 module_index);
+
+#endif
diff --git a/drivers/video/nexell/soc/s5pxx18_soc_mlc.c b/drivers/video/nexell/soc/s5pxx18_soc_mlc.c
new file mode 100644
index 0000000..c8cf833
--- /dev/null
+++ b/drivers/video/nexell/soc/s5pxx18_soc_mlc.c
@@ -0,0 +1,1861 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2016  Nexell Co., Ltd.
+ *
+ * Author: junghyun, kim <jhkim@nexell.co.kr>
+ */
+
+#include <linux/types.h>
+#include <linux/io.h>
+
+#include "s5pxx18_soc_mlc.h"
+
+static struct {
+	struct nx_mlc_register_set *pregister;
+} __g_module_variables[NUMBER_OF_MLC_MODULE] = { { NULL, },};
+
+int nx_mlc_initialize(void)
+{
+	static int binit;
+	u32 i;
+
+	if (binit == 0) {
+		for (i = 0; i < NUMBER_OF_MLC_MODULE; i++)
+			__g_module_variables[i].pregister = NULL;
+		binit = 1;
+	}
+	return 1;
+}
+
+u32 nx_mlc_get_physical_address(u32 module_index)
+{
+	const u32 physical_addr[] = PHY_BASEADDR_MLC_LIST;
+
+	return physical_addr[module_index];
+}
+
+void nx_mlc_set_base_address(u32 module_index, void *base_address)
+{
+	__g_module_variables[module_index].pregister =
+	    (struct nx_mlc_register_set *)base_address;
+}
+
+void *nx_mlc_get_base_address(u32 module_index)
+{
+	return (void *)__g_module_variables[module_index].pregister;
+}
+
+void nx_mlc_set_clock_pclk_mode(u32 module_index, enum nx_pclkmode mode)
+{
+	const u32 pclkmode_pos = 3;
+	u32 clkmode = 0;
+
+	register u32 regvalue;
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	switch (mode) {
+	case nx_pclkmode_dynamic:
+		clkmode = 0;
+		break;
+	case nx_pclkmode_always:
+		clkmode = 1;
+		break;
+	default:
+		break;
+	}
+	regvalue = pregister->mlcclkenb;
+	regvalue &= ~(1ul << pclkmode_pos);
+	regvalue |= (clkmode & 0x01) << pclkmode_pos;
+
+	writel(regvalue, &pregister->mlcclkenb);
+}
+
+enum nx_pclkmode nx_mlc_get_clock_pclk_mode(u32 module_index)
+{
+	const u32 pclkmode_pos = 3;
+
+	if (__g_module_variables[module_index].pregister->mlcclkenb &
+	    (1ul << pclkmode_pos)) {
+		return nx_pclkmode_always;
+	}
+	return nx_pclkmode_dynamic;
+}
+
+void nx_mlc_set_clock_bclk_mode(u32 module_index, enum nx_bclkmode mode)
+{
+	register u32 regvalue;
+	register struct nx_mlc_register_set *pregister;
+	u32 clkmode = 0;
+
+	pregister = __g_module_variables[module_index].pregister;
+	switch (mode) {
+	case nx_bclkmode_disable:
+		clkmode = 0;
+		break;
+	case nx_bclkmode_dynamic:
+		clkmode = 2;
+		break;
+	case nx_bclkmode_always:
+		clkmode = 3;
+		break;
+	default:
+		break;
+	}
+	regvalue = pregister->mlcclkenb;
+	regvalue &= ~(0x3);
+	regvalue |= clkmode & 0x3;
+
+	writel(regvalue, &pregister->mlcclkenb);
+}
+
+enum nx_bclkmode nx_mlc_get_clock_bclk_mode(u32 module_index)
+{
+	const u32 bclkmode = 3ul << 0;
+
+	switch (__g_module_variables[module_index].pregister->mlcclkenb &
+		bclkmode) {
+	case 0:
+		return nx_bclkmode_disable;
+	case 2:
+		return nx_bclkmode_dynamic;
+	case 3:
+		return nx_bclkmode_always;
+	}
+	return nx_bclkmode_disable;
+}
+
+void nx_mlc_set_top_power_mode(u32 module_index, int bpower)
+{
+	const u32 pixelbuffer_pwd_pos = 11;
+	const u32 pixelbuffer_pwd_mask = 1ul << pixelbuffer_pwd_pos;
+	const u32 dittyflag_mask = 1ul << 3;
+	register struct nx_mlc_register_set *pregister;
+	register u32 regvalue;
+
+	pregister = __g_module_variables[module_index].pregister;
+	regvalue = pregister->mlccontrolt;
+	regvalue &= ~(pixelbuffer_pwd_mask | dittyflag_mask);
+	regvalue |= (bpower << pixelbuffer_pwd_pos);
+
+	writel(regvalue, &pregister->mlccontrolt);
+}
+
+int nx_mlc_get_top_power_mode(u32 module_index)
+{
+	const u32 pixelbuffer_pwd_pos = 11;
+	const u32 pixelbuffer_pwd_mask = 1ul << pixelbuffer_pwd_pos;
+
+	return (int)((__g_module_variables[module_index].pregister->mlccontrolt
+		     & pixelbuffer_pwd_mask) >>
+		     pixelbuffer_pwd_pos);
+}
+
+void nx_mlc_set_top_sleep_mode(u32 module_index, int bsleep)
+{
+	const u32 pixelbuffer_sld_pos = 10;
+	const u32 pixelbuffer_sld_mask = 1ul << pixelbuffer_sld_pos;
+	const u32 dittyflag_mask = 1ul << 3;
+	register struct nx_mlc_register_set *pregister;
+	register u32 regvalue;
+
+	bsleep = (int)((u32)bsleep ^ 1);
+	pregister = __g_module_variables[module_index].pregister;
+	regvalue = pregister->mlccontrolt;
+	regvalue &= ~(pixelbuffer_sld_mask | dittyflag_mask);
+	regvalue |= (bsleep << pixelbuffer_sld_pos);
+
+	writel(regvalue, &pregister->mlccontrolt);
+}
+
+int nx_mlc_get_top_sleep_mode(u32 module_index)
+{
+	const u32 pixelbuffer_sld_pos = 11;
+	const u32 pixelbuffer_sld_mask = 1ul << pixelbuffer_sld_pos;
+
+	return (int)(((__g_module_variables[module_index].pregister->mlccontrolt
+		     & pixelbuffer_sld_mask) >>
+		     pixelbuffer_sld_pos) ^ 0x01);
+}
+
+void nx_mlc_set_top_dirty_flag(u32 module_index)
+{
+	const u32 dirtyflag = 1ul << 3;
+	register struct nx_mlc_register_set *pregister;
+	register u32 regvalue;
+
+	pregister = __g_module_variables[module_index].pregister;
+	regvalue = pregister->mlccontrolt;
+	regvalue |= dirtyflag;
+
+	writel(regvalue, &pregister->mlccontrolt);
+}
+
+int nx_mlc_get_top_dirty_flag(u32 module_index)
+{
+	const u32 dirtyflag_pos = 3;
+	const u32 dirtyflag_mask = 1ul << dirtyflag_pos;
+
+	return (int)((readl(&__g_module_variables[module_index]
+			    .pregister->mlccontrolt) &
+		      dirtyflag_mask) >> dirtyflag_pos);
+}
+
+void nx_mlc_set_mlc_enable(u32 module_index, int benb)
+{
+	const u32 mlcenb_pos = 1;
+	const u32 mlcenb_mask = 1ul << mlcenb_pos;
+	const u32 dirtyflag_pos = 3;
+	const u32 dirtyflag_mask = 1ul << dirtyflag_pos;
+	register u32 regvalue;
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	regvalue = pregister->mlccontrolt;
+	regvalue &= ~(mlcenb_mask | dirtyflag_mask);
+	regvalue |= (benb << mlcenb_pos);
+
+	writel(regvalue, &pregister->mlccontrolt);
+}
+
+int nx_mlc_get_mlc_enable(u32 module_index)
+{
+	const u32 mlcenb_pos = 1;
+	const u32 mlcenb_mask = 1ul << mlcenb_pos;
+
+	return (int)((__g_module_variables[module_index].pregister->mlccontrolt
+		     & mlcenb_mask) >> mlcenb_pos);
+}
+
+void nx_mlc_set_field_enable(u32 module_index, int benb)
+{
+	const u32 fieldenb_pos = 0;
+	const u32 fieldenb_mask = 1ul << fieldenb_pos;
+	const u32 dirtyflag_pos = 3;
+	const u32 dirtyflag_mask = 1ul << dirtyflag_pos;
+	register u32 regvalue;
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	regvalue = pregister->mlccontrolt;
+	regvalue &= ~(fieldenb_mask | dirtyflag_mask);
+	regvalue |= (benb << fieldenb_pos);
+
+	writel(regvalue, &pregister->mlccontrolt);
+}
+
+int nx_mlc_get_field_enable(u32 module_index)
+{
+	const u32 fieldenb_pos = 0;
+	const u32 fieldenb_mask = 1ul << fieldenb_pos;
+
+	return (int)(__g_module_variables[module_index].pregister->mlccontrolt &
+		     fieldenb_mask);
+}
+
+void nx_mlc_set_layer_priority(u32 module_index, enum nx_mlc_priority priority)
+{
+	const u32 priority_pos = 8;
+	const u32 priority_mask = 0x03 << priority_pos;
+	const u32 dirtyflag_pos = 3;
+	const u32 dirtyflag_mask = 1ul << dirtyflag_pos;
+	register struct nx_mlc_register_set *pregister;
+	register u32 regvalue;
+
+	pregister = __g_module_variables[module_index].pregister;
+	regvalue = pregister->mlccontrolt;
+	regvalue &= ~(priority_mask | dirtyflag_mask);
+	regvalue |= (priority << priority_pos);
+
+	writel(regvalue, &pregister->mlccontrolt);
+}
+
+void nx_mlc_set_screen_size(u32 module_index, u32 width, u32 height)
+{
+	register struct nx_mlc_register_set *pregister;
+	register u32 regvalue;
+
+	pregister = __g_module_variables[module_index].pregister;
+	regvalue = ((height - 1) << 16) | (width - 1);
+
+	writel(regvalue, &pregister->mlcscreensize);
+}
+
+void nx_mlc_get_screen_size(u32 module_index, u32 *pwidth, u32 *pheight)
+{
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+
+	if (pwidth)
+		*pwidth = (pregister->mlcscreensize & 0x0fff) + 1;
+
+	if (pheight)
+		*pheight = ((pregister->mlcscreensize >> 16) & 0x0fff) + 1;
+}
+
+void nx_mlc_set_background(u32 module_index, u32 color)
+{
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	writel(color, &pregister->mlcbgcolor);
+}
+
+void nx_mlc_set_dirty_flag(u32 module_index, u32 layer)
+{
+	register struct nx_mlc_register_set *pregister;
+	register u32 regvalue;
+	const u32 dirtyflg_mask = 1ul << 4;
+
+	pregister = __g_module_variables[module_index].pregister;
+	if (layer == 0 || layer == 1) {
+		regvalue = pregister->mlcrgblayer[layer].mlccontrol;
+		regvalue |= dirtyflg_mask;
+
+		writel(regvalue, &pregister->mlcrgblayer[layer].mlccontrol);
+	} else if (layer == 3) {
+		regvalue = pregister->mlcvideolayer.mlccontrol;
+		regvalue |= dirtyflg_mask;
+
+		writel(regvalue, &pregister->mlcvideolayer.mlccontrol);
+	}
+}
+
+int nx_mlc_get_dirty_flag(u32 module_index, u32 layer)
+{
+	const u32 dirtyflg_pos = 4;
+	const u32 dirtyflg_mask = 1ul << dirtyflg_pos;
+
+	if (layer == 0 || layer == 1) {
+		return (int)((__g_module_variables[module_index]
+			      .pregister->mlcrgblayer[layer]
+			      .mlccontrol & dirtyflg_mask) >> dirtyflg_pos);
+	} else if (layer == 2) {
+		return (int)((__g_module_variables[module_index]
+			      .pregister->mlcrgblayer2.mlccontrol &
+			      dirtyflg_mask) >> dirtyflg_pos);
+	} else if (layer == 3) {
+		return (int)((__g_module_variables[module_index]
+			      .pregister->mlcvideolayer.mlccontrol &
+			      dirtyflg_mask) >> dirtyflg_pos);
+	}
+	return 0;
+}
+
+void nx_mlc_set_layer_enable(u32 module_index, u32 layer, int benb)
+{
+	const u32 layerenb_pos = 5;
+	const u32 layerenb_mask = 0x01 << layerenb_pos;
+	const u32 dirtyflag_pos = 4;
+	const u32 dirtyflag_mask = 1ul << dirtyflag_pos;
+	register u32 regvalue;
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	if (layer == 0 || layer == 1) {
+		regvalue = pregister->mlcrgblayer[layer].mlccontrol;
+		regvalue &= ~(layerenb_mask | dirtyflag_mask);
+		regvalue |= (benb << layerenb_pos);
+
+		writel(regvalue, &pregister->mlcrgblayer[layer].mlccontrol);
+	} else if (layer == 3) {
+		regvalue = pregister->mlcvideolayer.mlccontrol;
+		regvalue &= ~(layerenb_mask | dirtyflag_mask);
+		regvalue |= (benb << layerenb_pos);
+
+		writel(regvalue, &pregister->mlcvideolayer.mlccontrol);
+	}
+}
+
+int nx_mlc_get_layer_enable(u32 module_index, u32 layer)
+{
+	const u32 layerenb_pos = 5;
+	const u32 layerenb_mask = 0x01 << layerenb_pos;
+
+	if (layer == 0 || layer == 1) {
+		return (int)((__g_module_variables[module_index]
+			      .pregister->mlcrgblayer[layer]
+			      .mlccontrol & layerenb_mask) >> layerenb_pos);
+	} else if (layer == 3) {
+		return (int)((__g_module_variables[module_index]
+			      .pregister->mlcvideolayer.mlccontrol &
+			      layerenb_mask) >> layerenb_pos);
+	}
+	return 0;
+}
+
+void nx_mlc_set_lock_size(u32 module_index, u32 layer, u32 locksize)
+{
+	const u32 locksize_mask = 3ul << 12;
+	const u32 dirtyflag_pos = 4;
+	const u32 dirtyflag_mask = 1ul << dirtyflag_pos;
+	register struct nx_mlc_register_set *pregister;
+	register u32 regvalue;
+
+	pregister = __g_module_variables[module_index].pregister;
+	locksize >>= 3;
+	if (layer == 0 || layer == 1) {
+		regvalue = pregister->mlcrgblayer[layer].mlccontrol;
+		regvalue &= ~(locksize_mask | dirtyflag_mask);
+		regvalue |= (locksize << 12);
+
+		writel(regvalue, &pregister->mlcrgblayer[layer].mlccontrol);
+	}
+}
+
+void nx_mlc_set_alpha_blending(u32 module_index, u32 layer, int benb, u32 alpha)
+{
+	const u32 blendenb_pos = 2;
+	const u32 blendenb_mask = 0x01 << blendenb_pos;
+	const u32 dirtyflag_pos = 4;
+	const u32 dirtyflag_mask = 1ul << dirtyflag_pos;
+	const u32 alpha_pos = 28;
+	const u32 alpha_mask = 0xf << alpha_pos;
+	register u32 regvalue;
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	if (layer == 0 || layer == 1) {
+		regvalue = pregister->mlcrgblayer[layer].mlccontrol;
+		regvalue &= ~(blendenb_mask | dirtyflag_mask);
+		regvalue |= (benb << blendenb_pos);
+
+		writel(regvalue, &pregister->mlcrgblayer[layer].mlccontrol);
+		regvalue = pregister->mlcrgblayer[layer].mlctpcolor;
+		regvalue &= ~alpha_mask;
+		regvalue |= alpha << alpha_pos;
+
+		writel(regvalue, &pregister->mlcrgblayer[layer].mlctpcolor);
+	} else if (layer == 3) {
+		regvalue = pregister->mlcvideolayer.mlccontrol;
+		regvalue &= ~(blendenb_mask | dirtyflag_mask);
+		regvalue |= (benb << blendenb_pos);
+
+		writel(regvalue, &pregister->mlcvideolayer.mlccontrol);
+
+		writel(alpha << alpha_pos,
+		       &pregister->mlcvideolayer.mlctpcolor);
+	}
+}
+
+void nx_mlc_set_transparency(u32 module_index, u32 layer, int benb, u32 color)
+{
+	const u32 tpenb_pos = 0;
+	const u32 tpenb_mask = 0x01 << tpenb_pos;
+	const u32 dirtyflag_pos = 4;
+	const u32 dirtyflag_mask = 1ul << dirtyflag_pos;
+	const u32 tpcolor_pos = 0;
+	const u32 tpcolor_mask = ((1 << 24) - 1) << tpcolor_pos;
+	register u32 regvalue;
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	if (layer == 0 || layer == 1) {
+		regvalue = pregister->mlcrgblayer[layer].mlccontrol;
+		regvalue &= ~(tpenb_mask | dirtyflag_mask);
+		regvalue |= (benb << tpenb_pos);
+
+		writel(regvalue, &pregister->mlcrgblayer[layer].mlccontrol);
+		regvalue = pregister->mlcrgblayer[layer].mlctpcolor;
+		regvalue &= ~tpcolor_mask;
+		regvalue |= (color & tpcolor_mask);
+
+		writel(regvalue, &pregister->mlcrgblayer[layer].mlctpcolor);
+	}
+}
+
+void nx_mlc_set_color_inversion(u32 module_index, u32 layer, int benb,
+				u32 color)
+{
+	const u32 invenb_pos = 1;
+	const u32 invenb_mask = 0x01 << invenb_pos;
+	const u32 dirtyflag_pos = 4;
+	const u32 dirtyflag_mask = 1ul << dirtyflag_pos;
+	const u32 invcolor_pos = 0;
+	const u32 invcolor_mask = ((1 << 24) - 1) << invcolor_pos;
+	register u32 regvalue;
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	if (layer == 0 || layer == 1) {
+		regvalue = pregister->mlcrgblayer[layer].mlccontrol;
+		regvalue &= ~(invenb_mask | dirtyflag_mask);
+		regvalue |= (benb << invenb_pos);
+
+		writel(regvalue, &pregister->mlcrgblayer[layer].mlccontrol);
+		regvalue = pregister->mlcrgblayer[layer].mlcinvcolor;
+		regvalue &= ~invcolor_mask;
+		regvalue |= (color & invcolor_mask);
+
+		writel(regvalue, &pregister->mlcrgblayer[layer].mlcinvcolor);
+	}
+}
+
+u32 nx_mlc_get_extended_color(u32 module_index, u32 color,
+			      enum nx_mlc_rgbfmt format)
+{
+	u32 rgb[3] = {
+		0,
+	};
+	u32 bw[3] = {
+		0,
+	};
+	u32 bp[3] = {
+		0,
+	};
+	u32 blank = 0;
+	u32 fill = 0;
+	u32 i = 0;
+
+	switch (format) {
+	case nx_mlc_rgbfmt_r5g6b5:
+		bw[0] = 5;
+		bw[1] = 6;
+		bw[2] = 5;
+		bp[0] = 11;
+		bp[1] = 5;
+		bp[2] = 0;
+		break;
+	case nx_mlc_rgbfmt_b5g6r5:
+		bw[0] = 5;
+		bw[1] = 6;
+		bw[2] = 5;
+		bp[0] = 0;
+		bp[1] = 5;
+		bp[2] = 11;
+		break;
+	case nx_mlc_rgbfmt_x1r5g5b5:
+	case nx_mlc_rgbfmt_a1r5g5b5:
+		bw[0] = 5;
+		bw[1] = 5;
+		bw[2] = 5;
+		bp[0] = 10;
+		bp[1] = 5;
+		bp[2] = 0;
+		break;
+	case nx_mlc_rgbfmt_x1b5g5r5:
+	case nx_mlc_rgbfmt_a1b5g5r5:
+		bw[0] = 5;
+		bw[1] = 5;
+		bw[2] = 5;
+		bp[0] = 0;
+		bp[1] = 5;
+		bp[2] = 10;
+		break;
+	case nx_mlc_rgbfmt_x4r4g4b4:
+	case nx_mlc_rgbfmt_a4r4g4b4:
+		bw[0] = 4;
+		bw[1] = 4;
+		bw[2] = 4;
+		bp[0] = 8;
+		bp[1] = 4;
+		bp[2] = 0;
+		break;
+	case nx_mlc_rgbfmt_x4b4g4r4:
+	case nx_mlc_rgbfmt_a4b4g4r4:
+		bw[0] = 4;
+		bw[1] = 4;
+		bw[2] = 4;
+		bp[0] = 0;
+		bp[1] = 4;
+		bp[2] = 8;
+		break;
+	case nx_mlc_rgbfmt_x8r3g3b2:
+	case nx_mlc_rgbfmt_a8r3g3b2:
+		bw[0] = 3;
+		bw[1] = 3;
+		bw[2] = 2;
+		bp[0] = 5;
+		bp[1] = 2;
+		bp[2] = 0;
+		break;
+	case nx_mlc_rgbfmt_x8b3g3r2:
+	case nx_mlc_rgbfmt_a8b3g3r2:
+		bw[0] = 2;
+		bw[1] = 3;
+		bw[2] = 3;
+		bp[0] = 0;
+		bp[1] = 2;
+		bp[2] = 5;
+		break;
+	case nx_mlc_rgbfmt_r8g8b8:
+	case nx_mlc_rgbfmt_a8r8g8b8:
+		bw[0] = 8;
+		bw[1] = 8;
+		bw[2] = 8;
+		bp[0] = 16;
+		bp[1] = 8;
+		bp[2] = 0;
+		break;
+	case nx_mlc_rgbfmt_b8g8r8:
+	case nx_mlc_rgbfmt_a8b8g8r8:
+		bw[0] = 8;
+		bw[1] = 8;
+		bw[2] = 8;
+		bp[0] = 0;
+		bp[1] = 8;
+		bp[2] = 16;
+		break;
+	default:
+		break;
+	}
+	for (i = 0; i < 3; i++) {
+		rgb[i] = (color >> bp[i]) & ((u32)(1 << bw[i]) - 1);
+		fill = bw[i];
+		blank = 8 - fill;
+		rgb[i] <<= blank;
+		while (blank > 0) {
+			rgb[i] |= (rgb[i] >> fill);
+			blank -= fill;
+			fill += fill;
+		}
+	}
+
+	return (rgb[0] << 16) | (rgb[1] << 8) | (rgb[2] << 0);
+}
+
+void nx_mlc_set_format_rgb(u32 module_index, u32 layer,
+			   enum nx_mlc_rgbfmt format)
+{
+	const u32 dirtyflag_pos = 4;
+	const u32 dirtyflag_mask = 1ul << dirtyflag_pos;
+	const u32 format_mask = 0xffff0000ul;
+	register u32 regvalue;
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	if (layer == 0 || layer == 1) {
+		regvalue = pregister->mlcrgblayer[layer].mlccontrol;
+		regvalue &= ~(format_mask | dirtyflag_mask);
+		regvalue |= (u32)format;
+
+		writel(regvalue, &pregister->mlcrgblayer[layer].mlccontrol);
+	}
+}
+
+void nx_mlc_set_format_yuv(u32 module_index, enum nx_mlc_yuvfmt format)
+{
+	const u32 format_mask = 0xffff0000ul;
+	register u32 temp;
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	temp = pregister->mlcvideolayer.mlccontrol;
+	temp &= ~format_mask;
+	temp |= (u32)format;
+
+	writel(temp, &pregister->mlcvideolayer.mlccontrol);
+}
+
+void nx_mlc_set_position(u32 module_index, u32 layer, s32 sx, s32 sy,
+			 s32 ex, s32 ey)
+{
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	if (layer == 0 || layer == 1) {
+		writel((((u32)sx & 0xffful) << 16) | ((u32)ex & 0xffful),
+		       &pregister->mlcrgblayer[layer].mlcleftright);
+
+		writel((((u32)sy & 0xffful) << 16) | ((u32)ey & 0xffful),
+		       &pregister->mlcrgblayer[layer].mlctopbottom);
+	} else if (layer == 2) {
+		writel((((u32)sx & 0xffful) << 16) | ((u32)ex & 0xffful),
+		       &pregister->mlcrgblayer2.mlcleftright);
+
+		writel((((u32)sy & 0xffful) << 16) | ((u32)ey & 0xffful),
+		       &pregister->mlcrgblayer2.mlctopbottom);
+	} else if (layer == 3) {
+		writel((((u32)sx & 0xffful) << 16) | ((u32)ex & 0xffful),
+		       &pregister->mlcvideolayer.mlcleftright);
+
+		writel((((u32)sy & 0xffful) << 16) | ((u32)ey & 0xffful),
+		       &pregister->mlcvideolayer.mlctopbottom);
+	}
+}
+
+void nx_mlc_set_dither_enable_when_using_gamma(u32 module_index, int benable)
+{
+	const u32 ditherenb_bitpos = 0;
+	const u32 ditherenb_mask = 1 << ditherenb_bitpos;
+	register struct nx_mlc_register_set *pregister;
+	register u32 read_value;
+
+	pregister = __g_module_variables[module_index].pregister;
+	read_value = pregister->mlcgammacont;
+	read_value &= ~ditherenb_mask;
+	read_value |= ((u32)benable << ditherenb_bitpos);
+
+	writel(read_value, &pregister->mlcgammacont);
+}
+
+int nx_mlc_get_dither_enable_when_using_gamma(u32 module_index)
+{
+	const u32 ditherenb_bitpos = 0;
+	const u32 ditherenb_mask = 1 << ditherenb_bitpos;
+
+	return (int)(__g_module_variables[module_index].pregister->mlcgammacont
+		     & ditherenb_mask);
+}
+
+void nx_mlc_set_gamma_priority(u32 module_index, int bvideolayer)
+{
+	const u32 alphaselect_bitpos = 5;
+	const u32 alphaselect_mask = 1 << alphaselect_bitpos;
+	register struct nx_mlc_register_set *pregister;
+	register u32 read_value;
+
+	pregister = __g_module_variables[module_index].pregister;
+	read_value = pregister->mlcgammacont;
+	read_value &= ~alphaselect_mask;
+	read_value |= ((u32)bvideolayer << alphaselect_bitpos);
+
+	writel(read_value, &pregister->mlcgammacont);
+}
+
+int nx_mlc_get_gamma_priority(u32 module_index)
+{
+	const u32 alphaselect_bitpos = 5;
+	const u32 alphaselect_mask = 1 << alphaselect_bitpos;
+
+	return (int)((__g_module_variables[module_index].pregister->mlcgammacont
+		     & alphaselect_mask) >> alphaselect_bitpos);
+}
+
+void nx_mlc_set_rgblayer_invalid_position(u32 module_index, u32 layer,
+					  u32 region, s32 sx, s32 sy,
+					  s32 ex, s32 ey, int benb)
+{
+	const u32 invalidenb_pos = 28;
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	if (layer == 0 || layer == 1) {
+		if (region == 0) {
+			writel(((benb << invalidenb_pos) |
+				((sx & 0x7ff) << 16) | (ex & 0x7ff)),
+			       &pregister->mlcrgblayer[layer]
+			       .mlcinvalidleftright0);
+
+			writel((((sy & 0x7ff) << 16) | (ey & 0x7ff)),
+			       &pregister->mlcrgblayer[layer]
+			       .mlcinvalidtopbottom0);
+		} else {
+			writel(((benb << invalidenb_pos) |
+				((sx & 0x7ff) << 16) | (ex & 0x7ff)),
+			       &pregister->mlcrgblayer[layer]
+			       .mlcinvalidleftright1);
+
+			writel((((sy & 0x7ff) << 16) | (ey & 0x7ff)),
+			       &pregister->mlcrgblayer[layer]
+			       .mlcinvalidtopbottom1);
+		}
+	}
+}
+
+void nx_mlc_set_rgblayer_stride(u32 module_index, u32 layer, s32 hstride,
+				s32 vstride)
+{
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	if (layer == 0 || layer == 1) {
+		writel(hstride, &pregister->mlcrgblayer[layer].mlchstride);
+		writel(vstride, &pregister->mlcrgblayer[layer].mlcvstride);
+	} else if (layer == 2) {
+		writel(hstride, &pregister->mlcrgblayer2.mlchstride);
+		writel(vstride, &pregister->mlcrgblayer2.mlcvstride);
+	}
+}
+
+void nx_mlc_set_rgblayer_address(u32 module_index, u32 layer, u32 addr)
+{
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	if (layer == 0 || layer == 1)
+		writel(addr, &pregister->mlcrgblayer[layer].mlcaddress);
+	else if (layer == 2)
+		writel(addr, &pregister->mlcrgblayer2.mlcaddress);
+}
+
+void nx_mlc_set_rgblayer_gama_table_power_mode(u32 module_index, int bred,
+					       int bgreen, int bblue)
+{
+	const u32 bgammatable_pwd_bitpos = 11;
+	const u32 ggammatable_pwd_bitpos = 9;
+	const u32 rgammatable_pwd_bitpos = 3;
+	const u32 bgammatable_pwd_mask = (1 << bgammatable_pwd_bitpos);
+	const u32 ggammatable_pwd_mask = (1 << ggammatable_pwd_bitpos);
+	const u32 rgammatable_pwd_mask = (1 << rgammatable_pwd_bitpos);
+	register u32 read_value;
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	read_value = pregister->mlcgammacont;
+	read_value &= ~(bgammatable_pwd_mask | ggammatable_pwd_mask |
+			rgammatable_pwd_mask);
+	read_value |= (((u32)bred << rgammatable_pwd_bitpos) |
+		       ((u32)bgreen << ggammatable_pwd_bitpos) |
+		       ((u32)bblue << bgammatable_pwd_bitpos));
+
+	writel(read_value, &pregister->mlcgammacont);
+}
+
+void nx_mlc_get_rgblayer_gama_table_power_mode(u32 module_index, int *pbred,
+					       int *pbgreen, int *pbblue)
+{
+	const u32 bgammatable_pwd_bitpos = 11;
+	const u32 ggammatable_pwd_bitpos = 9;
+	const u32 rgammatable_pwd_bitpos = 3;
+	const u32 bgammatable_pwd_mask = (1 << bgammatable_pwd_bitpos);
+	const u32 ggammatable_pwd_mask = (1 << ggammatable_pwd_bitpos);
+	const u32 rgammatable_pwd_mask = (1 << rgammatable_pwd_bitpos);
+	register u32 read_value;
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	read_value = pregister->mlcgammacont;
+	if (pbred)
+		*pbred = (read_value & rgammatable_pwd_mask) ? 1 : 0;
+
+	if (pbgreen)
+		*pbgreen = (read_value & ggammatable_pwd_mask) ? 1 : 0;
+
+	if (pbblue)
+		*pbblue = (read_value & bgammatable_pwd_mask) ? 1 : 0;
+}
+
+void nx_mlc_set_rgblayer_gama_table_sleep_mode(u32 module_index, int bred,
+					       int bgreen, int bblue)
+{
+	const u32 bgammatable_sld_bitpos = 10;
+	const u32 ggammatable_sld_bitpos = 8;
+	const u32 rgammatable_sld_bitpos = 2;
+	const u32 bgammatable_sld_mask = (1 << bgammatable_sld_bitpos);
+	const u32 ggammatable_sld_mask = (1 << ggammatable_sld_bitpos);
+	const u32 rgammatable_sld_mask = (1 << rgammatable_sld_bitpos);
+	register u32 read_value;
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	read_value = pregister->mlcgammacont;
+	if (bred)
+		read_value &= ~rgammatable_sld_mask;
+	else
+		read_value |= rgammatable_sld_mask;
+
+	if (bgreen)
+		read_value &= ~ggammatable_sld_mask;
+	else
+		read_value |= ggammatable_sld_mask;
+
+	if (bblue)
+		read_value &= ~bgammatable_sld_mask;
+	else
+		read_value |= bgammatable_sld_mask;
+
+	writel(read_value, &pregister->mlcgammacont);
+}
+
+void nx_mlc_get_rgblayer_gama_table_sleep_mode(u32 module_index, int *pbred,
+					       int *pbgreen, int *pbblue)
+{
+	const u32 bgammatable_sld_bitpos = 10;
+	const u32 ggammatable_sld_bitpos = 8;
+	const u32 rgammatable_sld_bitpos = 2;
+	const u32 bgammatable_sld_mask = (1 << bgammatable_sld_bitpos);
+	const u32 ggammatable_sld_mask = (1 << ggammatable_sld_bitpos);
+	const u32 rgammatable_sld_mask = (1 << rgammatable_sld_bitpos);
+	register u32 read_value;
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	read_value = pregister->mlcgammacont;
+
+	if (pbred)
+		*pbred = (read_value & rgammatable_sld_mask) ? 0 : 1;
+
+	if (pbgreen)
+		*pbgreen = (read_value & ggammatable_sld_mask) ? 0 : 1;
+
+	if (pbblue)
+		*pbblue = (read_value & bgammatable_sld_mask) ? 0 : 1;
+}
+
+void nx_mlc_set_rgblayer_rgamma_table(u32 module_index, u32 dwaddress,
+				      u32 dwdata)
+{
+	register struct nx_mlc_register_set *pregister;
+	const u32 tableaddr_bitpos = 24;
+
+	pregister = __g_module_variables[module_index].pregister;
+	writel(((dwaddress << tableaddr_bitpos) | dwdata),
+	       &pregister->mlcrgammatablewrite);
+}
+
+void nx_mlc_set_rgblayer_ggamma_table(u32 module_index, u32 dwaddress,
+				      u32 dwdata)
+{
+	register struct nx_mlc_register_set *pregister;
+	const u32 tableaddr_bitpos = 24;
+
+	pregister = __g_module_variables[module_index].pregister;
+	writel(((dwaddress << tableaddr_bitpos) | dwdata),
+	       &pregister->mlcggammatablewrite);
+}
+
+void nx_mlc_set_rgblayer_bgamma_table(u32 module_index, u32 dwaddress,
+				      u32 dwdata)
+{
+	register struct nx_mlc_register_set *pregister;
+	const u32 tableaddr_bitpos = 24;
+
+	pregister = __g_module_variables[module_index].pregister;
+	writel(((dwaddress << tableaddr_bitpos) | dwdata),
+	       &pregister->mlcbgammatablewrite);
+}
+
+void nx_mlc_set_rgblayer_gamma_enable(u32 module_index, int benable)
+{
+	const u32 rgbgammaemb_bitpos = 1;
+	const u32 rgbgammaemb_mask = 1 << rgbgammaemb_bitpos;
+	register u32 read_value;
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	read_value = pregister->mlcgammacont;
+	read_value &= ~rgbgammaemb_mask;
+	read_value |= (u32)benable << rgbgammaemb_bitpos;
+
+	writel(read_value, &pregister->mlcgammacont);
+}
+
+int nx_mlc_get_rgblayer_gamma_enable(u32 module_index)
+{
+	const u32 rgbgammaemb_bitpos = 1;
+	const u32 rgbgammaemb_mask = 1 << rgbgammaemb_bitpos;
+
+	return (int)((__g_module_variables[module_index].pregister->mlcgammacont
+		     & rgbgammaemb_mask) >> rgbgammaemb_bitpos);
+}
+
+void nx_mlc_set_video_layer_stride(u32 module_index, s32 lu_stride,
+				   s32 cb_stride, s32 cr_stride)
+{
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+
+	writel(lu_stride, &pregister->mlcvideolayer.mlcvstride);
+	writel(cb_stride, &pregister->mlcvideolayer.mlcvstridecb);
+	writel(cr_stride, &pregister->mlcvideolayer.mlcvstridecr);
+}
+
+void nx_mlc_set_video_layer_address(u32 module_index, u32 lu_addr, u32 cb_addr,
+				    u32 cr_addr)
+{
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	writel(lu_addr, &pregister->mlcvideolayer.mlcaddress);
+	writel(cb_addr, &pregister->mlcvideolayer.mlcaddresscb);
+	writel(cr_addr, &pregister->mlcvideolayer.mlcaddresscr);
+}
+
+void nx_mlc_set_video_layer_address_yuyv(u32 module_index, u32 addr,
+					 s32 stride)
+{
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	writel(addr, &pregister->mlcvideolayer.mlcaddress);
+	writel(stride, &pregister->mlcvideolayer.mlcvstride);
+}
+
+void nx_mlc_set_video_layer_scale_factor(u32 module_index, u32 hscale,
+					 u32 vscale, int bhlumaenb,
+					 int bhchromaenb, int bvlumaenb,
+					 int bvchromaenb)
+{
+	const u32 filter_luma_pos = 28;
+	const u32 filter_choma_pos = 29;
+	const u32 scale_mask = ((1 << 23) - 1);
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+
+	writel(((bhlumaenb << filter_luma_pos) |
+		(bhchromaenb << filter_choma_pos) | (hscale & scale_mask)),
+	       &pregister->mlcvideolayer.mlchscale);
+
+	writel(((bvlumaenb << filter_luma_pos) |
+		(bvchromaenb << filter_choma_pos) | (vscale & scale_mask)),
+	       &pregister->mlcvideolayer.mlcvscale);
+}
+
+void nx_mlc_set_video_layer_scale_filter(u32 module_index, int bhlumaenb,
+					 int bhchromaenb, int bvlumaenb,
+					 int bvchromaenb)
+{
+	const u32 filter_luma_pos = 28;
+	const u32 filter_choma_pos = 29;
+	const u32 scale_mask = ((1 << 23) - 1);
+	register struct nx_mlc_register_set *pregister;
+	register u32 read_value;
+
+	pregister = __g_module_variables[module_index].pregister;
+	read_value = pregister->mlcvideolayer.mlchscale;
+	read_value &= scale_mask;
+	read_value |=
+	    (bhlumaenb << filter_luma_pos) | (bhchromaenb << filter_choma_pos);
+
+	writel(read_value, &pregister->mlcvideolayer.mlchscale);
+	read_value = pregister->mlcvideolayer.mlcvscale;
+	read_value &= scale_mask;
+	read_value |=
+	    (bvlumaenb << filter_luma_pos) | (bvchromaenb << filter_choma_pos);
+
+	writel(read_value, &pregister->mlcvideolayer.mlcvscale);
+}
+
+void nx_mlc_get_video_layer_scale_filter(u32 module_index, int *bhlumaenb,
+					 int *bhchromaenb, int *bvlumaenb,
+					 int *bvchromaenb)
+{
+	const u32 filter_luma_pos = 28;
+	const u32 filter_choma_pos = 29;
+	const u32 filter_mask = 1ul;
+	register struct nx_mlc_register_set *pregister;
+	register u32 read_value;
+
+	pregister = __g_module_variables[module_index].pregister;
+	read_value = pregister->mlcvideolayer.mlchscale;
+	*bhlumaenb = (read_value >> filter_luma_pos) & filter_mask;
+	*bhchromaenb = (read_value >> filter_choma_pos) & filter_mask;
+	read_value = pregister->mlcvideolayer.mlcvscale;
+	*bvlumaenb = (read_value >> filter_luma_pos) & filter_mask;
+	*bvchromaenb = (read_value >> filter_choma_pos) & filter_mask;
+}
+
+void nx_mlc_set_video_layer_scale(u32 module_index, u32 sw, u32 sh, u32 dw,
+				  u32 dh, int bhlumaenb, int bhchromaenb,
+				  int bvlumaenb, int bvchromaenb)
+{
+	const u32 filter_luma_pos = 28;
+	const u32 filter_choma_pos = 29;
+	const u32 scale_mask = ((1 << 23) - 1);
+	register u32 hscale, vscale, cal_sh;
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+
+	if ((bhlumaenb || bhchromaenb) && dw > sw) {
+		sw--;
+		dw--;
+	}
+	hscale = (sw << 11) / dw;
+
+	if ((bvlumaenb || bvchromaenb) && dh > sh) {
+		sh--;
+		dh--;
+		vscale = (sh << 11) / dh;
+
+		cal_sh = ((vscale * dh) >> 11);
+		if (sh <= cal_sh)
+			vscale--;
+
+	} else {
+		vscale = (sh << 11) / dh;
+	}
+
+	writel(((bhlumaenb << filter_luma_pos) |
+		(bhchromaenb << filter_choma_pos) | (hscale & scale_mask)),
+	       &pregister->mlcvideolayer.mlchscale);
+
+	writel(((bvlumaenb << filter_luma_pos) |
+		(bvchromaenb << filter_choma_pos) | (vscale & scale_mask)),
+	       &pregister->mlcvideolayer.mlcvscale);
+}
+
+void nx_mlc_set_video_layer_luma_enhance(u32 module_index, u32 contrast,
+					 s32 brightness)
+{
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+
+	writel((((u32)brightness & 0xfful) << 8) | contrast,
+	       &pregister->mlcvideolayer.mlcluenh);
+}
+
+void nx_mlc_set_video_layer_chroma_enhance(u32 module_index, u32 quadrant,
+					   s32 cb_a, s32 cb_b,
+					   s32 cr_a, s32 cr_b)
+{
+	register struct nx_mlc_register_set *pregister;
+	register u32 temp;
+
+	pregister = __g_module_variables[module_index].pregister;
+	temp = (((u32)cr_b & 0xfful) << 24) | (((u32)cr_a & 0xfful) << 16) |
+	    (((u32)cb_b & 0xfful) << 8) | (((u32)cb_a & 0xfful) << 0);
+	if (quadrant > 0) {
+		writel(temp, &pregister->mlcvideolayer.mlcchenh[quadrant - 1]);
+	} else {
+		writel(temp, &pregister->mlcvideolayer.mlcchenh[0]);
+		writel(temp, &pregister->mlcvideolayer.mlcchenh[1]);
+		writel(temp, &pregister->mlcvideolayer.mlcchenh[2]);
+		writel(temp, &pregister->mlcvideolayer.mlcchenh[3]);
+	}
+}
+
+void nx_mlc_set_video_layer_line_buffer_power_mode(u32 module_index,
+						   int benable)
+{
+	const u32 linebuff_pwd_pos = 15;
+	const u32 linebuff_pwd_mask = 1ul << linebuff_pwd_pos;
+	const u32 dirtyflag_mask = 1ul << 4;
+	register u32 regvalue;
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	regvalue = pregister->mlcvideolayer.mlccontrol;
+	regvalue &= ~(linebuff_pwd_mask | dirtyflag_mask);
+	regvalue |= ((u32)benable << linebuff_pwd_pos);
+
+	writel(regvalue, &pregister->mlcvideolayer.mlccontrol);
+}
+
+int nx_mlc_get_video_layer_line_buffer_power_mode(u32 module_index)
+{
+	const u32 linebuff_pwd_pos = 15;
+	const u32 linebuff_pwd_mask = 1ul << linebuff_pwd_pos;
+
+	return (int)((__g_module_variables[module_index]
+		      .pregister->mlcvideolayer.mlccontrol &
+		      linebuff_pwd_mask) >> linebuff_pwd_pos);
+}
+
+void nx_mlc_set_video_layer_line_buffer_sleep_mode(u32 module_index,
+						   int benable)
+{
+	const u32 linebuff_slmd_pos = 14;
+	const u32 linebuff_slmd_mask = 1ul << linebuff_slmd_pos;
+	const u32 dirtyflag_mask = 1ul << 4;
+	register u32 regvalue;
+	register struct nx_mlc_register_set *pregister;
+
+	benable = (int)((u32)benable ^ 1);
+	pregister = __g_module_variables[module_index].pregister;
+	regvalue = pregister->mlcvideolayer.mlccontrol;
+	regvalue &= ~(linebuff_slmd_mask | dirtyflag_mask);
+	regvalue |= (benable << linebuff_slmd_pos);
+
+	writel(regvalue, &pregister->mlcvideolayer.mlccontrol);
+}
+
+int nx_mlc_get_video_layer_line_buffer_sleep_mode(u32 module_index)
+{
+	const u32 linebuff_slmd_pos = 14;
+	const u32 linebuff_slmd_mask = 1ul << linebuff_slmd_pos;
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	if (linebuff_slmd_mask & pregister->mlcvideolayer.mlccontrol)
+		return 0;
+	else
+		return 1;
+}
+
+void nx_mlc_set_video_layer_gama_table_power_mode(u32 module_index, int by,
+						  int bu, int bv)
+{
+	const u32 vgammatable_pwd_bitpos = 17;
+	const u32 ugammatable_pwd_bitpos = 15;
+	const u32 ygammatable_pwd_bitpos = 13;
+	const u32 vgammatable_pwd_mask = (1 << vgammatable_pwd_bitpos);
+	const u32 ugammatable_pwd_mask = (1 << ugammatable_pwd_bitpos);
+	const u32 ygammatable_pwd_mask = (1 << ygammatable_pwd_bitpos);
+	register u32 read_value;
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	read_value = pregister->mlcgammacont;
+	read_value &= ~(ygammatable_pwd_mask | ugammatable_pwd_mask |
+			vgammatable_pwd_mask);
+	read_value |= (((u32)by << ygammatable_pwd_bitpos) |
+		       ((u32)bu << ugammatable_pwd_bitpos) |
+		       ((u32)bv << vgammatable_pwd_bitpos));
+
+	writel(read_value, &pregister->mlcgammacont);
+}
+
+void nx_mlc_get_video_layer_gama_table_power_mode(u32 module_index, int *pby,
+						  int *pbu, int *pbv)
+{
+	const u32 vgammatable_pwd_bitpos = 17;
+	const u32 ugammatable_pwd_bitpos = 15;
+	const u32 ygammatable_pwd_bitpos = 13;
+	const u32 vgammatable_pwd_mask = (1 << vgammatable_pwd_bitpos);
+	const u32 ugammatable_pwd_mask = (1 << ugammatable_pwd_bitpos);
+	const u32 ygammatable_pwd_mask = (1 << ygammatable_pwd_bitpos);
+	register u32 read_value;
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	read_value = pregister->mlcgammacont;
+	if (pby)
+		*pby = (read_value & ygammatable_pwd_mask) ? 1 : 0;
+
+	if (pbu)
+		*pbu = (read_value & ugammatable_pwd_mask) ? 1 : 0;
+
+	if (pbv)
+		*pbv = (read_value & vgammatable_pwd_mask) ? 1 : 0;
+}
+
+void nx_mlc_set_video_layer_gama_table_sleep_mode(u32 module_index, int by,
+						  int bu, int bv)
+{
+	const u32 vgammatable_sld_bitpos = 16;
+	const u32 ugammatable_sld_bitpos = 14;
+	const u32 ygammatable_sld_bitpos = 12;
+	const u32 vgammatable_sld_mask = (1 << vgammatable_sld_bitpos);
+	const u32 ugammatable_sld_mask = (1 << ugammatable_sld_bitpos);
+	const u32 ygammatable_sld_mask = (1 << ygammatable_sld_bitpos);
+	register u32 read_value;
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	read_value = pregister->mlcgammacont;
+	if (by)
+		read_value &= ~ygammatable_sld_mask;
+	else
+		read_value |= ygammatable_sld_mask;
+
+	if (bu)
+		read_value &= ~ugammatable_sld_mask;
+	else
+		read_value |= ugammatable_sld_mask;
+
+	if (bv)
+		read_value &= ~vgammatable_sld_mask;
+	else
+		read_value |= vgammatable_sld_mask;
+
+	writel(read_value, &pregister->mlcgammacont);
+}
+
+void nx_mlc_get_video_layer_gama_table_sleep_mode(u32 module_index, int *pby,
+						  int *pbu, int *pbv)
+{
+	const u32 vgammatable_sld_bitpos = 16;
+	const u32 ugammatable_sld_bitpos = 14;
+	const u32 ygammatable_sld_bitpos = 12;
+	const u32 vgammatable_sld_mask = (1 << vgammatable_sld_bitpos);
+	const u32 ugammatable_sld_mask = (1 << ugammatable_sld_bitpos);
+	const u32 ygammatable_sld_mask = (1 << ygammatable_sld_bitpos);
+	register u32 read_value;
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	read_value = pregister->mlcgammacont;
+
+	if (pby)
+		*pby = (read_value & vgammatable_sld_mask) ? 0 : 1;
+
+	if (pbu)
+		*pbu = (read_value & ugammatable_sld_mask) ? 0 : 1;
+
+	if (pbv)
+		*pbv = (read_value & ygammatable_sld_mask) ? 0 : 1;
+}
+
+void nx_mlc_set_video_layer_gamma_enable(u32 module_index, int benable)
+{
+	const u32 yuvgammaemb_bitpos = 4;
+	const u32 yuvgammaemb_mask = 1 << yuvgammaemb_bitpos;
+	register u32 read_value;
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	read_value = pregister->mlcgammacont;
+	read_value &= ~yuvgammaemb_mask;
+	read_value |= (u32)benable << yuvgammaemb_bitpos;
+
+	writel(read_value, &pregister->mlcgammacont);
+}
+
+int nx_mlc_get_video_layer_gamma_enable(u32 module_index)
+{
+	const u32 yuvgammaemb_bitpos = 4;
+	const u32 yuvgammaemb_mask = 1 << yuvgammaemb_bitpos;
+
+	return (int)((__g_module_variables[module_index].pregister->mlcgammacont
+		     & yuvgammaemb_mask) >> yuvgammaemb_bitpos);
+}
+
+void nx_mlc_set_gamma_table_poweroff(u32 module_index, int enb)
+{
+	register struct nx_mlc_register_set *pregister;
+	u32 regvalue;
+
+	pregister = __g_module_variables[module_index].pregister;
+	if (enb == 1) {
+		regvalue = pregister->mlcgammacont;
+		regvalue = regvalue & 0xf3;
+		writel(regvalue, &pregister->mlcgammacont);
+	}
+}
+
+void nx_mlc_set_mlctop_control_parameter(u32 module_index, int field_enable,
+					 int mlcenable, u8 priority,
+					 enum g3daddrchangeallowed
+					 g3daddr_change_allowed)
+{
+	register u32 mlctopcontrolreg;
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	mlctopcontrolreg = (readl(&pregister->mlccontrolt)) & 0xfffffcfc;
+	mlctopcontrolreg = (u32)(mlctopcontrolreg |
+				  ((priority << 8) | ((mlcenable == 1) << 1) |
+				   (1 ==
+				    field_enable)) | (g3daddr_change_allowed <<
+						      12));
+	writel(mlctopcontrolreg, &pregister->mlccontrolt);
+}
+
+void nx_mlc_set_rgb0layer_control_parameter(u32 module_index, int layer_enable,
+					    int grp3denable, int tp_enable,
+					    u32 transparency_color,
+					    int inv_enable, u32 inverse_color,
+					    int blend_enable, u8 alpha_value,
+					    enum mlc_rgbfmt rbgformat,
+					    enum locksizesel lock_size_select)
+{
+	u32 layer_format;
+	u32 control_enb;
+	u32 alpha_argument;
+	u32 lock_size = (u32)(lock_size_select & 0x3);
+	u32 rgb0controlreg;
+	u32 regvalue;
+	register struct nx_mlc_register_set *pregister;
+
+	layer_format = nx_mlc_get_rgbformat(rbgformat);
+	pregister = __g_module_variables[module_index].pregister;
+	control_enb =
+	    (u32)((grp3denable << 8) | (layer_enable << 5) |
+		   (blend_enable << 2) | (inv_enable << 1) | tp_enable) & 0x127;
+	alpha_argument = (u32)(alpha_value & 0xf);
+
+	rgb0controlreg = readl(&pregister->mlcrgblayer[0].mlccontrol) & 0x10;
+	regvalue =
+	    (u32)(((layer_format << 16) | control_enb | (lock_size << 12)) |
+		   rgb0controlreg);
+	writel(regvalue, &pregister->mlcrgblayer[0].mlccontrol);
+
+	regvalue = (u32)((alpha_argument << 28) | transparency_color);
+	writel(regvalue, &pregister->mlcrgblayer[0].mlctpcolor);
+	regvalue = inverse_color;
+	writel(regvalue, &pregister->mlcrgblayer[0].mlcinvcolor);
+}
+
+u32 nx_mlc_get_rgbformat(enum mlc_rgbfmt rbgformat)
+{
+	u32 rgbformatvalue;
+	const u32 format_table[] = {
+		0x4432ul, 0x4342ul, 0x4211ul, 0x4120ul, 0x4003ul, 0x4554ul,
+		0x3342ul, 0x2211ul, 0x1120ul, 0x1003ul, 0x4653ul, 0x4653ul,
+		0x0653ul, 0x4ed3ul, 0x4f84ul, 0xc432ul, 0xc342ul, 0xc211ul,
+		0xc120ul, 0xb342ul, 0xa211ul, 0x9120ul, 0xc653ul, 0xc653ul,
+		0x8653ul, 0xced3ul, 0xcf84ul, 0x443aul
+	};
+
+	return rgbformatvalue = format_table[rbgformat];
+}
+
+void nx_mlc_set_rgb1layer_control_parameter(u32 module_index, int layer_enable,
+					    int grp3denable, int tp_enable,
+					    u32 transparency_color,
+					    int inv_enable, u32 inverse_color,
+					    int blend_enable, u8 alpha_value,
+					    enum mlc_rgbfmt rbgformat,
+					    enum locksizesel lock_size_select)
+{
+	u32 layer_format;
+	u32 control_enb;
+	u32 alpha_argument;
+	u32 lock_size = (u32)(lock_size_select & 0x3);
+	u32 rgb0controlreg;
+	u32 regvalue;
+	register struct nx_mlc_register_set *pregister;
+
+	layer_format = nx_mlc_get_rgbformat(rbgformat);
+	pregister = __g_module_variables[module_index].pregister;
+
+	rgb0controlreg = readl(&pregister->mlcrgblayer[1].mlccontrol) & 0x10;
+	control_enb =
+	    (u32)((grp3denable << 8) | (layer_enable << 5) |
+		   (blend_enable << 2) | (inv_enable << 1) | tp_enable) & 0x127;
+	alpha_argument = (u32)(alpha_value & 0xf);
+	regvalue =
+	    (u32)(((layer_format << 16) | control_enb | (lock_size << 12)) |
+		   rgb0controlreg);
+	writel(regvalue, &pregister->mlcrgblayer[1].mlccontrol);
+	regvalue = (u32)((alpha_argument << 28) | transparency_color);
+	writel(regvalue, &pregister->mlcrgblayer[1].mlctpcolor);
+	regvalue = inverse_color;
+	writel(regvalue, &pregister->mlcrgblayer[1].mlcinvcolor);
+}
+
+void nx_mlc_set_rgb2layer_control_parameter(u32 module_index, int layer_enable,
+					    int grp3denable, int tp_enable,
+					    u32 transparency_color,
+					    int inv_enable, u32 inverse_color,
+					    int blend_enable, u8 alpha_value,
+					    enum mlc_rgbfmt rbgformat,
+					    enum locksizesel lock_size_select)
+{
+	u32 layer_format;
+	u32 control_enb;
+	u32 alpha_argument;
+	u32 lock_size = (u32)(lock_size_select & 0x3);
+	u32 rgb0controlreg;
+	u32 regvalue;
+	register struct nx_mlc_register_set *pregister;
+
+	layer_format = nx_mlc_get_rgbformat(rbgformat);
+	pregister = __g_module_variables[module_index].pregister;
+
+	rgb0controlreg = readl(&pregister->mlcrgblayer2.mlccontrol) & 0x10;
+	control_enb =
+	    (u32)((grp3denable << 8) | (layer_enable << 5) |
+		   (blend_enable << 2) | (inv_enable << 1) | tp_enable) & 0x127;
+	alpha_argument = (u32)(alpha_value & 0xf);
+	regvalue =
+	    (u32)(((layer_format << 16) | control_enb | (lock_size << 12)) |
+		   rgb0controlreg);
+	writel(regvalue, &pregister->mlcrgblayer2.mlccontrol);
+	regvalue = (u32)((alpha_argument << 28) | transparency_color);
+	writel(regvalue, &pregister->mlcrgblayer2.mlctpcolor);
+	regvalue = inverse_color;
+	writel(regvalue, &pregister->mlcrgblayer2.mlcinvcolor);
+}
+
+void nx_mlc_set_video_layer_control_parameter(u32 module_index,
+					      int layer_enable, int tp_enable,
+					      u32 transparency_color,
+					      int inv_enable, u32 inverse_color,
+					      int blend_enable, u8 alpha_value,
+					      enum nx_mlc_yuvfmt yuvformat)
+{
+	u32 control_enb;
+	u32 alpha_argument;
+	u32 regvalue;
+	register struct nx_mlc_register_set *pregister;
+	u32 video_control_reg;
+
+	pregister = __g_module_variables[module_index].pregister;
+
+	video_control_reg = readl(&pregister->mlcvideolayer.mlccontrol);
+	control_enb =
+	    (u32)((yuvformat) | (layer_enable << 5) | (blend_enable << 2) |
+		   (inv_enable << 1) | tp_enable) & 0x30027;
+	alpha_argument = (u32)(alpha_value & 0xf);
+	regvalue = (u32)(control_enb | video_control_reg);
+	writel(regvalue, &pregister->mlcvideolayer.mlccontrol);
+	regvalue = (u32)((alpha_argument << 28) | transparency_color);
+	writel(regvalue, &pregister->mlcvideolayer.mlctpcolor);
+	regvalue = (u32)((alpha_argument << 28) | transparency_color);
+	writel(regvalue, &pregister->mlcvideolayer.mlcinvcolor);
+}
+
+void nx_mlc_set_srammode(u32 module_index, enum latyername layer_name,
+			 enum srammode sram_mode)
+{
+	u32 control_reg_value;
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	switch (layer_name) {
+	case topmlc:
+		control_reg_value = readl(&pregister->mlccontrolt);
+		writel((u32)(control_reg_value | (sram_mode << 10)),
+		       &pregister->mlccontrolt);
+		control_reg_value = 0;
+		break;
+	case rgb0:
+		control_reg_value =
+		    readl(&pregister->mlcrgblayer[0].mlccontrol);
+		writel((u32)(control_reg_value | (sram_mode << 14)),
+		       &pregister->mlcrgblayer[0].mlccontrol);
+		control_reg_value = 0;
+		break;
+	case rgb1:
+		control_reg_value =
+		    readl(&pregister->mlcrgblayer[1].mlccontrol);
+		writel((u32)(control_reg_value | (sram_mode << 14)),
+		       &pregister->mlcrgblayer[1].mlccontrol);
+		control_reg_value = 0;
+		break;
+	case rgb2:
+		control_reg_value = readl(&pregister->mlcrgblayer2.mlccontrol);
+		writel((u32)(control_reg_value | (sram_mode << 14)),
+		       &pregister->mlcrgblayer2.mlccontrol);
+		control_reg_value = 0;
+		break;
+	case video:
+		control_reg_value = readl(&pregister->mlcvideolayer.mlccontrol);
+		writel((u32)(control_reg_value | (sram_mode << 14)),
+		       &pregister->mlcvideolayer.mlccontrol);
+		control_reg_value = 0;
+		break;
+	default:
+		break;
+	}
+}
+
+void nx_mlc_set_layer_reg_finish(u32 module_index, enum latyername layer_name)
+{
+	u32 control_reg_value;
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+
+	switch (layer_name) {
+	case topmlc:
+		control_reg_value = readl(&pregister->mlccontrolt);
+		writel((u32)(control_reg_value | (1ul << 3)),
+		       &pregister->mlccontrolt);
+		control_reg_value = 0;
+		break;
+	case rgb0:
+		control_reg_value =
+		    readl(&pregister->mlcrgblayer[0].mlccontrol);
+		writel((u32)(control_reg_value | (1ul << 4)),
+		       &pregister->mlcrgblayer[0].mlccontrol);
+		control_reg_value = 0;
+		break;
+	case rgb1:
+		control_reg_value =
+		    readl(&pregister->mlcrgblayer[1].mlccontrol);
+		writel((u32)(control_reg_value | (1ul << 4)),
+		       &pregister->mlcrgblayer[1].mlccontrol);
+		control_reg_value = 0;
+		break;
+	case rgb2:
+		control_reg_value = readl(&pregister->mlcrgblayer2.mlccontrol);
+		writel((u32)(control_reg_value | (1ul << 4)),
+		       &pregister->mlcrgblayer2.mlccontrol);
+		control_reg_value = 0;
+		break;
+	case video:
+		control_reg_value = readl(&pregister->mlcvideolayer.mlccontrol);
+		writel((u32)(control_reg_value | (1ul << 4)),
+		       &pregister->mlcvideolayer.mlccontrol);
+		control_reg_value = 0;
+		break;
+	default:
+		break;
+	}
+}
+
+void nx_mlc_set_video_layer_coordinate(u32 module_index, int vfilterenable,
+				       int hfilterenable, int vfilterenable_c,
+				       int hfilterenable_c,
+				       u16 video_layer_with,
+				       u16 video_layer_height, s16 left,
+				       s16 right, s16 top,
+				       s16 bottom)
+{
+	s32 source_width, source_height;
+	s32 destination_width;
+	s32 destination_height;
+	s32 hscale, vscale;
+	s32 hfilterenb, vfilterenb;
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	writel((s32)(((left & 0x0fff) << 16) | (right & 0x0fff)),
+	       &pregister->mlcvideolayer.mlcleftright);
+	writel((s32)(((top & 0x0fff) << 16) | (bottom & 0x0fff)),
+	       &pregister->mlcvideolayer.mlctopbottom);
+	source_width = (s32)(video_layer_with - 1);
+	source_height = (s32)(video_layer_height - 1);
+	destination_width = (s32)(right - left);
+	destination_height = (s32)(bottom - top);
+
+	hscale =
+	    (s32)((source_width * (1ul << 11) + (destination_width / 2)) /
+		      destination_width);
+	vscale =
+	    (s32)((source_height * (1ul << 11) +
+		      (destination_height / 2)) / destination_height);
+
+	hfilterenb = (u32)(((hfilterenable_c << 29) | (hfilterenable) << 28)) &
+	    0x30000000;
+	vfilterenb = (u32)(((vfilterenable_c << 29) | (vfilterenable) << 28)) &
+	    0x30000000;
+	writel((u32)(hfilterenb | (hscale & 0x00ffffff)),
+	       &pregister->mlcvideolayer.mlchscale);
+	writel((u32)(vfilterenb | (vscale & 0x00ffffff)),
+	       &pregister->mlcvideolayer.mlcvscale);
+}
+
+void nx_mlc_set_video_layer_filter_scale(u32 module_index, u32 hscale,
+					 u32 vscale)
+{
+	register struct nx_mlc_register_set *pregister;
+	u32 mlchscale = 0;
+	u32 mlcvscale = 0;
+
+	pregister = __g_module_variables[module_index].pregister;
+	mlchscale = readl(&pregister->mlcvideolayer.mlchscale) & (~0x00ffffff);
+	mlcvscale = readl(&pregister->mlcvideolayer.mlcvscale) & (~0x00ffffff);
+
+	writel((u32)(mlchscale | (hscale & 0x00ffffff)),
+	       &pregister->mlcvideolayer.mlchscale);
+	writel((u32)(mlcvscale | (vscale & 0x00ffffff)),
+	       &pregister->mlcvideolayer.mlcvscale);
+}
+
+void nx_mlc_set_gamma_control_parameter(u32 module_index, int rgbgammaenb,
+					int yuvgammaenb, int yuvalphaarray,
+					int dither_enb)
+{
+	u32 register_data;
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	register_data = readl(&pregister->mlcgammacont);
+	register_data = (register_data & 0xf0c) |
+	    ((yuvalphaarray << 5) | (yuvgammaenb << 4) |
+	     (rgbgammaenb << 1) | (dither_enb << 0));
+	writel(register_data, &pregister->mlcgammacont);
+}
+
+void nx_mlc_set_layer_alpha256(u32 module_index, u32 layer, u32 alpha)
+{
+	u32 register_data;
+	register struct nx_mlc_register_set *pregister;
+
+	if (alpha < 0)
+		alpha = 0;
+	if (alpha > 255)
+		alpha = 255;
+
+	pregister = __g_module_variables[module_index].pregister;
+	if (layer == 0) {
+		register_data =
+		    readl(&pregister->mlcrgblayer[0].mlctpcolor) & 0x00ffffff;
+		register_data = register_data | (alpha << 24);
+		writel(register_data, &pregister->mlcrgblayer[0].mlctpcolor);
+	} else if (layer == 1) {
+		register_data =
+		    readl(&pregister->mlcrgblayer[1].mlctpcolor) & 0x00ffffff;
+		register_data = register_data | (alpha << 24);
+		writel(register_data, &pregister->mlcrgblayer[1].mlctpcolor);
+	} else if (layer == 2) {
+		register_data =
+		    readl(&pregister->mlcrgblayer[1].mlctpcolor) & 0x00ffffff;
+		register_data = register_data | (alpha << 24);
+		writel(register_data, &pregister->mlcrgblayer2.mlctpcolor);
+	} else {
+		register_data =
+		    readl(&pregister->mlcvideolayer.mlctpcolor) & 0x00ffffff;
+		register_data = register_data | (alpha << 24);
+		writel(register_data, &pregister->mlcvideolayer.mlctpcolor);
+	}
+}
+
+int nx_mlc_is_under_flow(u32 module_index)
+{
+	const u32 underflow_pend_pos = 31;
+	const u32 underflow_pend_mask = 1ul << underflow_pend_pos;
+
+	return (int)((__g_module_variables[module_index].pregister->mlccontrolt
+		     & underflow_pend_mask) >> underflow_pend_pos);
+}
+
+void nx_mlc_set_gamma_table(u32 module_index, int enb,
+			    struct nx_mlc_gamma_table_parameter *p_gammatable)
+{
+	register struct nx_mlc_register_set *pregister;
+	u32 i, regval = 0;
+
+	pregister = __g_module_variables[module_index].pregister;
+	if (enb == 1) {
+		regval = readl(&pregister->mlcgammacont);
+
+		regval = (1 << 11) | (1 << 9) | (1 << 3);
+		writel(regval, &pregister->mlcgammacont);
+
+		regval = regval | (1 << 10) | (1 << 8) | (1 << 2);
+		writel(regval, &pregister->mlcgammacont);
+
+		for (i = 0; i < 256; i++) {
+			nx_mlc_set_rgblayer_rgamma_table(module_index, i,
+						     p_gammatable->r_table[i]);
+			nx_mlc_set_rgblayer_ggamma_table(module_index, i,
+						     p_gammatable->g_table[i]);
+			nx_mlc_set_rgblayer_bgamma_table(module_index, i,
+						     p_gammatable->b_table[i]);
+		}
+
+		regval = regval | (p_gammatable->alphaselect << 5) |
+		    (p_gammatable->yuvgammaenb << 4 |
+		     p_gammatable->allgammaenb << 4) |
+		    (p_gammatable->rgbgammaenb << 1 |
+		     p_gammatable->allgammaenb << 1) |
+		    (p_gammatable->ditherenb << 1);
+		writel(regval, &pregister->mlcgammacont);
+	} else {
+		regval = regval & ~(1 << 10) & ~(1 << 8) & ~(1 << 2);
+		writel(regval, &pregister->mlcgammacont);
+
+		regval = regval & ~(1 << 11) & ~(1 << 9) & ~(1 << 3);
+		writel(regval, &pregister->mlcgammacont);
+	}
+}
+
+void nx_mlc_get_rgblayer_stride(u32 module_index, u32 layer, s32 *hstride,
+				s32 *vstride)
+{
+	unsigned int hs, vs;
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+
+	hs = readl(&pregister->mlcrgblayer[layer].mlchstride);
+	vs = readl(&pregister->mlcrgblayer[layer].mlcvstride);
+
+	if (hstride)
+		*(s32 *)hstride = hs;
+
+	if (vstride)
+		*(s32 *)vstride = vs;
+}
+
+void nx_mlc_get_rgblayer_address(u32 module_index, u32 layer,
+				 u32 *phys_address)
+{
+	u32 pa;
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	pa = readl(&pregister->mlcrgblayer[layer].mlcaddress);
+
+	if (phys_address)
+		*(u32 *)phys_address = pa;
+}
+
+void nx_mlc_get_position(u32 module_index, u32 layer, int *left, int *top,
+			 int *right, int *bottom)
+{
+	int lr, tb;
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+
+	lr = readl(&pregister->mlcrgblayer[layer].mlcleftright);
+	tb = readl(&pregister->mlcrgblayer[layer].mlctopbottom);
+
+	if (left)
+		*(int *)left = ((lr >> 16) & 0xFFUL);
+
+	if (top)
+		*(int *)top = ((tb >> 16) & 0xFFUL);
+
+	if (right)
+		*(int *)right = ((lr >> 0) & 0xFFUL);
+
+	if (bottom)
+		*(int *)bottom = ((tb >> 0) & 0xFFUL);
+}
+
+void nx_mlc_get_video_layer_address_yuyv(u32 module_index, u32 *address,
+					 u32 *stride)
+{
+	u32 a, s;
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	a = readl(&pregister->mlcvideolayer.mlcaddress);
+	s = readl(&pregister->mlcvideolayer.mlcvstride);
+
+	if (address)
+		*(u32 *)address = a;
+
+	if (stride)
+		*(u32 *)stride = s;
+}
+
+void nx_mlc_get_video_layer_address(u32 module_index, u32 *lu_address,
+				    u32 *cb_address, u32 *cr_address)
+{
+	u32 lua, cba, cra;
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+
+	lua = readl(&pregister->mlcvideolayer.mlcaddress);
+	cba = readl(&pregister->mlcvideolayer.mlcaddresscb);
+	cra = readl(&pregister->mlcvideolayer.mlcaddresscr);
+
+	if (lu_address)
+		*(u32 *)lu_address = lua;
+
+	if (cb_address)
+		*(u32 *)cb_address = cba;
+
+	if (cr_address)
+		*(u32 *)cr_address = cra;
+}
+
+void nx_mlc_get_video_layer_stride(u32 module_index, u32 *lu_stride,
+				   u32 *cb_stride, u32 *cr_stride)
+{
+	u32 lus, cbs, crs;
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+
+	lus = readl(&pregister->mlcvideolayer.mlcvstride);
+	cbs = readl(&pregister->mlcvideolayer.mlcvstridecb);
+	crs = readl(&pregister->mlcvideolayer.mlcvstridecr);
+
+	if (lu_stride)
+		*(u32 *)lu_stride = lus;
+
+	if (cb_stride)
+		*(u32 *)cb_stride = cbs;
+
+	if (cr_stride)
+		*(u32 *)cr_stride = crs;
+}
+
+void nx_mlc_get_video_position(u32 module_index, int *left, int *top,
+			       int *right, int *bottom)
+{
+	int lr, tb;
+	register struct nx_mlc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+
+	lr = readl(&pregister->mlcvideolayer.mlcleftright);
+	tb = readl(&pregister->mlcvideolayer.mlctopbottom);
+
+	if (left)
+		*(int *)left = ((lr >> 16) & 0xFFUL);
+
+	if (top)
+		*(int *)top = ((tb >> 16) & 0xFFUL);
+
+	if (right)
+		*(int *)right = ((lr >> 0) & 0xFFUL);
+
+	if (bottom)
+		*(int *)bottom = ((tb >> 0) & 0xFFUL);
+}
diff --git a/drivers/video/nexell/soc/s5pxx18_soc_mlc.h b/drivers/video/nexell/soc/s5pxx18_soc_mlc.h
new file mode 100644
index 0000000..77ceca6
--- /dev/null
+++ b/drivers/video/nexell/soc/s5pxx18_soc_mlc.h
@@ -0,0 +1,429 @@
+/* SPDX-License-Identifier: GPL-2.0+
+ *
+ * Copyright (C) 2016  Nexell Co., Ltd.
+ *
+ * Author: junghyun, kim <jhkim@nexell.co.kr>
+ */
+
+#ifndef _S5PXX18_SOC_MLC_H_
+#define _S5PXX18_SOC_MLC_H_
+
+#include "s5pxx18_soc_disptype.h"
+
+#define NUMBER_OF_MLC_MODULE 2
+#define PHY_BASEADDR_MLC0	0xC0102000
+#define PHY_BASEADDR_MLC1	0xC0102400
+
+#define	PHY_BASEADDR_MLC_LIST	\
+		{ PHY_BASEADDR_MLC0, PHY_BASEADDR_MLC1 }
+
+struct nx_mlc_register_set {
+	u32 mlccontrolt;
+	u32 mlcscreensize;
+	u32 mlcbgcolor;
+	struct {
+		u32 mlcleftright;
+		u32 mlctopbottom;
+		u32 mlcinvalidleftright0;
+		u32 mlcinvalidtopbottom0;
+		u32 mlcinvalidleftright1;
+		u32 mlcinvalidtopbottom1;
+		u32 mlccontrol;
+		s32 mlchstride;
+		s32 mlcvstride;
+		u32 mlctpcolor;
+		u32 mlcinvcolor;
+		u32 mlcaddress;
+		u32 __reserved0;
+	} mlcrgblayer[2];
+	struct {
+		u32 mlcleftright;
+		u32 mlctopbottom;
+		u32 mlccontrol;
+		u32 mlcvstride;
+		u32 mlctpcolor;
+
+		u32 mlcinvcolor;
+		u32 mlcaddress;
+		u32 mlcaddresscb;
+		u32 mlcaddresscr;
+		s32 mlcvstridecb;
+		s32 mlcvstridecr;
+		u32 mlchscale;
+		u32 mlcvscale;
+		u32 mlcluenh;
+		u32 mlcchenh[4];
+	} mlcvideolayer;
+	struct {
+		u32 mlcleftright;
+		u32 mlctopbottom;
+		u32 mlcinvalidleftright0;
+		u32 mlcinvalidtopbottom0;
+		u32 mlcinvalidleftright1;
+		u32 mlcinvalidtopbottom1;
+		u32 mlccontrol;
+		s32 mlchstride;
+		s32 mlcvstride;
+		u32 mlctpcolor;
+		u32 mlcinvcolor;
+		u32 mlcaddress;
+	} mlcrgblayer2;
+	u32 mlcpaletetable2;
+	u32 mlcgammacont;
+	u32 mlcrgammatablewrite;
+	u32 mlcggammatablewrite;
+	u32 mlcbgammatablewrite;
+	u32 yuvlayergammatable_red;
+	u32 yuvlayergammatable_green;
+	u32 yuvlayergammatable_blue;
+
+	u32 dimctrl;
+	u32 dimlut0;
+	u32 dimlut1;
+	u32 dimbusyflag;
+	u32 dimprdarrr0;
+	u32 dimprdarrr1;
+	u32 dimram0rddata;
+	u32 dimram1rddata;
+	u32 __reserved2[(0x3c0 - 0x12c) / 4];
+	u32 mlcclkenb;
+};
+
+enum nx_mlc_priority {
+	nx_mlc_priority_videofirst = 0ul,
+	nx_mlc_priority_videosecond = 1ul,
+	nx_mlc_priority_videothird = 2ul,
+	nx_mlc_priority_videofourth = 3ul
+};
+
+enum nx_mlc_rgbfmt {
+	nx_mlc_rgbfmt_r5g6b5 = 0x44320000ul,
+	nx_mlc_rgbfmt_b5g6r5 = 0xc4320000ul,
+	nx_mlc_rgbfmt_x1r5g5b5 = 0x43420000ul,
+	nx_mlc_rgbfmt_x1b5g5r5 = 0xc3420000ul,
+	nx_mlc_rgbfmt_x4r4g4b4 = 0x42110000ul,
+	nx_mlc_rgbfmt_x4b4g4r4 = 0xc2110000ul,
+	nx_mlc_rgbfmt_x8r3g3b2 = 0x41200000ul,
+	nx_mlc_rgbfmt_x8b3g3r2 = 0xc1200000ul,
+	nx_mlc_rgbfmt_a1r5g5b5 = 0x33420000ul,
+	nx_mlc_rgbfmt_a1b5g5r5 = 0xb3420000ul,
+	nx_mlc_rgbfmt_a4r4g4b4 = 0x22110000ul,
+	nx_mlc_rgbfmt_a4b4g4r4 = 0xa2110000ul,
+	nx_mlc_rgbfmt_a8r3g3b2 = 0x11200000ul,
+	nx_mlc_rgbfmt_a8b3g3r2 = 0x91200000ul,
+	nx_mlc_rgbfmt_r8g8b8 = 0x46530000ul,
+	nx_mlc_rgbfmt_b8g8r8 = 0xc6530000ul,
+	nx_mlc_rgbfmt_x8r8g8b8 = 0x46530000ul,
+	nx_mlc_rgbfmt_x8b8g8r8 = 0xc6530000ul,
+	nx_mlc_rgbfmt_a8r8g8b8 = 0x06530000ul,
+	nx_mlc_rgbfmt_a8b8g8r8 = 0x86530000ul
+};
+
+enum nx_mlc_yuvfmt {
+	nx_mlc_yuvfmt_420 = 0ul << 16,
+	nx_mlc_yuvfmt_422 = 1ul << 16,
+	nx_mlc_yuvfmt_444 = 3ul << 16,
+	nx_mlc_yuvfmt_yuyv = 2ul << 16,
+	nx_mlc_yuvfmt_422_cbcr = 4ul << 16,
+	nx_mlc_yuvfmt_420_cbcr = 5ul << 16,
+};
+
+#ifdef __arm
+#pragma diag_default 66
+#endif
+
+int nx_mlc_initialize(void);
+u32 nx_mlc_get_number_of_module(void);
+u32 nx_mlc_get_physical_address(u32 module_index);
+u32 nx_mlc_get_size_of_register_set(void);
+void nx_mlc_set_base_address(u32 module_index, void *base_address);
+void *nx_mlc_get_base_address(u32 module_index);
+int nx_mlc_open_module(u32 module_index);
+int nx_mlc_close_module(u32 module_index);
+int nx_mlc_check_busy(u32 module_index);
+int nx_mlc_can_power_down(u32 module_index);
+void nx_mlc_set_clock_pclk_mode(u32 module_index, enum nx_pclkmode mode);
+enum nx_pclkmode nx_mlc_get_clock_pclk_mode(u32 module_index);
+void nx_mlc_set_clock_bclk_mode(u32 module_index, enum nx_bclkmode mode);
+enum nx_bclkmode nx_mlc_get_clock_bclk_mode(u32 module_index);
+
+void nx_mlc_set_top_power_mode(u32 module_index, int bpower);
+int nx_mlc_get_top_power_mode(u32 module_index);
+void nx_mlc_set_top_sleep_mode(u32 module_index, int bsleep);
+int nx_mlc_get_top_sleep_mode(u32 module_index);
+void nx_mlc_set_top_dirty_flag(u32 module_index);
+int nx_mlc_get_top_dirty_flag(u32 module_index);
+void nx_mlc_set_mlc_enable(u32 module_index, int benb);
+int nx_mlc_get_mlc_enable(u32 module_index);
+void nx_mlc_set_field_enable(u32 module_index, int benb);
+int nx_mlc_get_field_enable(u32 module_index);
+void nx_mlc_set_layer_priority(u32 module_index,
+			       enum nx_mlc_priority priority);
+void nx_mlc_set_screen_size(u32 module_index, u32 width, u32 height);
+void nx_mlc_get_screen_size(u32 module_index, u32 *pwidth,
+			    u32 *pheight);
+void nx_mlc_set_background(u32 module_index, u32 color);
+
+void nx_mlc_set_dirty_flag(u32 module_index, u32 layer);
+int nx_mlc_get_dirty_flag(u32 module_index, u32 layer);
+void nx_mlc_set_layer_enable(u32 module_index, u32 layer, int benb);
+int nx_mlc_get_layer_enable(u32 module_index, u32 layer);
+void nx_mlc_set_lock_size(u32 module_index, u32 layer, u32 locksize);
+void nx_mlc_set_alpha_blending(u32 module_index, u32 layer, int benb,
+			       u32 alpha);
+void nx_mlc_set_transparency(u32 module_index, u32 layer, int benb,
+			     u32 color);
+void nx_mlc_set_color_inversion(u32 module_index, u32 layer, int benb,
+				u32 color);
+u32 nx_mlc_get_extended_color(u32 module_index, u32 color,
+			      enum nx_mlc_rgbfmt format);
+void nx_mlc_set_format_rgb(u32 module_index, u32 layer,
+			   enum nx_mlc_rgbfmt format);
+void nx_mlc_set_format_yuv(u32 module_index, enum nx_mlc_yuvfmt format);
+void nx_mlc_set_position(u32 module_index, u32 layer, s32 sx,
+			 s32 sy, s32 ex, s32 ey);
+void nx_mlc_set_dither_enable_when_using_gamma(u32 module_index,
+					       int benable);
+int nx_mlc_get_dither_enable_when_using_gamma(u32 module_index);
+void nx_mlc_set_gamma_priority(u32 module_index, int bvideolayer);
+int nx_mlc_get_gamma_priority(u32 module_index);
+
+void nx_mlc_set_rgblayer_invalid_position(u32 module_index, u32 layer,
+					  u32 region, s32 sx,
+					  s32 sy, s32 ex,
+					  s32 ey, int benb);
+void nx_mlc_set_rgblayer_stride(u32 module_index, u32 layer,
+				s32 hstride, s32 vstride);
+void nx_mlc_set_rgblayer_address(u32 module_index, u32 layer, u32 addr);
+void nx_mlc_set_rgblayer_gama_table_power_mode(u32 module_index,
+					       int bred, int bgreen,
+					       int bblue);
+void nx_mlc_get_rgblayer_gama_table_power_mode(u32 module_index,
+					       int *pbred, int *pbgreen,
+					       int *pbblue);
+void nx_mlc_set_rgblayer_gama_table_sleep_mode(u32 module_index,
+					       int bred, int bgreen,
+					       int bblue);
+void nx_mlc_get_rgblayer_gama_table_sleep_mode(u32 module_index,
+					       int *pbred, int *pbgreen,
+					       int *pbblue);
+void nx_mlc_set_rgblayer_rgamma_table(u32 module_index, u32 dwaddress,
+				      u32 dwdata);
+void nx_mlc_set_rgblayer_ggamma_table(u32 module_index, u32 dwaddress,
+				      u32 dwdata);
+void nx_mlc_set_rgblayer_bgamma_table(u32 module_index, u32 dwaddress,
+				      u32 dwdata);
+void nx_mlc_set_rgblayer_gamma_enable(u32 module_index, int benable);
+int nx_mlc_get_rgblayer_gamma_enable(u32 module_index);
+
+void nx_mlc_set_video_layer_stride(u32 module_index, s32 lu_stride,
+				   s32 cb_stride, s32 cr_stride);
+void nx_mlc_set_video_layer_address(u32 module_index, u32 lu_addr,
+				    u32 cb_addr, u32 cr_addr);
+void nx_mlc_set_video_layer_address_yuyv(u32 module_index, u32 addr,
+					 s32 stride);
+void nx_mlc_set_video_layer_scale_factor(u32 module_index, u32 hscale,
+					 u32 vscale, int bhlumaenb,
+					 int bhchromaenb, int bvlumaenb,
+					 int bvchromaenb);
+void nx_mlc_set_video_layer_scale_filter(u32 module_index, int bhlumaenb,
+					 int bhchromaenb, int bvlumaenb,
+					 int bvchromaenb);
+void nx_mlc_get_video_layer_scale_filter(u32 module_index,
+					 int *bhlumaenb,
+					 int *bhchromaenb,
+					 int *bvlumaenb,
+					 int *bvchromaenb);
+void nx_mlc_set_video_layer_scale(u32 module_index, u32 sw, u32 sh,
+				  u32 dw, u32 dh, int bhlumaenb,
+				  int bhchromaenb, int bvlumaenb,
+				  int bvchromaenb);
+void nx_mlc_set_video_layer_luma_enhance(u32 module_index, u32 contrast,
+					 s32 brightness);
+void nx_mlc_set_video_layer_chroma_enhance(u32 module_index,
+					   u32 quadrant, s32 cb_a,
+					   s32 cb_b, s32 cr_a,
+					   s32 cr_b);
+void nx_mlc_set_video_layer_line_buffer_power_mode(u32 module_index,
+						   int benable);
+int nx_mlc_get_video_layer_line_buffer_power_mode(u32 module_index);
+void nx_mlc_set_video_layer_line_buffer_sleep_mode(u32 module_index,
+						   int benable);
+int nx_mlc_get_video_layer_line_buffer_sleep_mode(u32 module_index);
+void nx_mlc_set_video_layer_gamma_enable(u32 module_index, int benable);
+int nx_mlc_get_video_layer_gamma_enable(u32 module_index);
+
+void nx_mlc_set_gamma_table_poweroff(u32 module_index, int enb);
+
+enum mlc_rgbfmt {
+	rgbfmt_r5g6b5 = 0,
+	rgbfmt_x1r5g5b5 = 1,
+	rgbfmt_x4r4g4b4 = 2,
+	rgbfmt_x8r3g3b2 = 3,
+	rgbfmt_x8l8 = 4,
+	rgbfmt_l16 = 5,
+	rgbfmt_a1r5g5b5 = 6,
+	rgbfmt_a4r4g4b4 = 7,
+	rgbfmt_a8r3g3b2 = 8,
+	rgbfmt_a8l8 = 9,
+	rgbfmt_r8g8b8 = 10,
+	rgbfmt_x8r8g8b8 = 11,
+	rgbfmt_a8r8g8b8 = 12,
+	rgbfmt_g8r8_g8b8 = 13,
+	rgbfmt_r8g8_b8g8 = 14,
+	rgbfmt_b5g6r5 = 15,
+	rgbfmt_x1b5g5r5 = 16,
+	rgbfmt_x4b4g4r4 = 17,
+	rgbfmt_x8b3g3r2 = 18,
+	rgbfmt_a1b5g5r5 = 19,
+	rgbfmt_a4b4g4r4 = 20,
+	rgbfmt_a8b3g3r2 = 21,
+	rgbfmt_b8g8r8 = 22,
+	rgbfmt_x8b8g8r8 = 23,
+	rgbfmt_a8b8g8r8 = 24,
+	rgbfmt_g8b8_g8r8 = 25,
+	rgbfmt_b8g8_r8g8 = 26,
+	rgbfmt_pataletb = 27
+};
+
+enum latyername {
+	topmlc = 0,
+	rgb0 = 1,
+	rgb1 = 2,
+	rgb2 = 3,
+	video = 4
+};
+
+enum srammode {
+	poweroff = 0,
+	sleepmode = 2,
+	run = 3
+};
+
+enum locksizesel {
+	locksize_4 = 0,
+	locksize_8 = 1,
+	locksize_16 = 2
+};
+
+enum g3daddrchangeallowed {
+	prim = 0,
+	secon = 1,
+	primorsecon = 2,
+	primandsecon = 3
+};
+
+void nx_mlc_set_mlctop_control_parameter(u32 module_index,
+					 int field_enable, int mlcenable,
+					 u8 priority,
+					 enum g3daddrchangeallowed
+					 g3daddr_change_allowed);
+void nx_mlc_set_rgb0layer_control_parameter(u32 module_index,
+					    int layer_enable,
+					    int grp3denable,
+					    int tp_enable,
+					    u32 transparency_color,
+					    int inv_enable,
+					    u32 inverse_color,
+					    int blend_enable,
+					    u8 alpha_value,
+					    enum mlc_rgbfmt rbgformat,
+					    enum locksizesel
+					    lock_size_select);
+
+u32 nx_mlc_get_rgbformat(enum mlc_rgbfmt rbgformat);
+void nx_mlc_set_rgb1layer_control_parameter(u32 module_index,
+					    int layer_enable,
+					    int grp3denable,
+					    int tp_enable,
+					    u32 transparency_color,
+					    int inv_enable,
+					    u32 inverse_color,
+					    int blend_enable,
+					    u8 alpha_value,
+					    enum mlc_rgbfmt rbgformat,
+					    enum locksizesel
+					    lock_size_select);
+
+void nx_mlc_set_rgb2layer_control_parameter(u32 module_index,
+					    int layer_enable,
+					    int grp3denable,
+					    int tp_enable,
+					    u32 transparency_color,
+					    int inv_enable,
+					    u32 inverse_color,
+					    int blend_enable,
+					    u8 alpha_value,
+					    enum mlc_rgbfmt rbgformat,
+					    enum locksizesel
+					    lock_size_select);
+
+void nx_mlc_set_video_layer_control_parameter(u32 module_index,
+					      int layer_enable,
+					      int tp_enable,
+					      u32 transparency_color,
+					      int inv_enable,
+					      u32 inverse_color,
+					      int blend_enable,
+					      u8 alpha_value,
+					      enum nx_mlc_yuvfmt
+					      yuvformat);
+
+void nx_mlc_set_srammode(u32 module_index, enum latyername layer_name,
+			 enum srammode sram_mode);
+
+void nx_mlc_set_layer_reg_finish(u32 module_index,
+				 enum latyername layer_name);
+
+void nx_mlc_set_video_layer_coordinate(u32 module_index,
+				       int vfilterenable,
+				       int hfilterenable,
+				       int vfilterenable_c,
+				       int hfilterenable_c,
+				       u16 video_layer_with,
+				       u16 video_layer_height,
+				       s16 left, s16 right,
+				       s16 top, s16 bottom);
+
+void nx_mlc_set_video_layer_filter_scale(u32 module_index, u32 hscale,
+					 u32 vscale);
+void nx_mlcsetgammasrammode(u32 module_index, enum srammode sram_mode);
+void nx_mlc_set_gamma_control_parameter(u32 module_index,
+					int rgbgammaenb, int yuvgammaenb,
+					int yuvalphaarray,
+					int dither_enb);
+
+void nx_mlc_set_layer_alpha256(u32 module_index, u32 layer, u32 alpha);
+int nx_mlc_is_under_flow(u32 module_index);
+
+struct nx_mlc_gamma_table_parameter {
+	u32 r_table[256];
+	u32 g_table[256];
+	u32 b_table[256];
+	u32 ditherenb;
+	u32 alphaselect;
+	u32 yuvgammaenb;
+	u32 rgbgammaenb;
+	u32 allgammaenb;
+};
+
+void nx_mlc_set_gamma_table(u32 module_index, int enb,
+			    struct nx_mlc_gamma_table_parameter *p_gammatable);
+void nx_mlc_get_rgblayer_stride(u32 module_index, u32 layer,
+				s32 *hstride, s32 *vstride);
+void nx_mlc_get_rgblayer_address(u32 module_index, u32 layer,
+				 u32 *phys_address);
+void nx_mlc_get_position(u32 module_index, u32 layer, int *left,
+			 int *top, int *right, int *bottom);
+void nx_mlc_get_video_layer_address_yuyv(u32 module_index, u32 *address,
+					 u32 *stride);
+void nx_mlc_get_video_layer_address(u32 module_index, u32 *lu_address,
+				    u32 *cb_address, u32 *cr_address);
+void nx_mlc_get_video_layer_stride(u32 module_index, u32 *lu_stride,
+				   u32 *cb_stride, u32 *cr_stride);
+void nx_mlc_get_video_layer_stride(u32 module_index, u32 *lu_stride,
+				   u32 *cb_stride, u32 *cr_stride);
+void nx_mlc_get_video_position(u32 module_index, int *left, int *top,
+			       int *right, int *bottom);
+
+#endif
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [RFC PATCH v2 09/13] video: add nexell video driver (soc: lvds, hdmi)
  2020-03-28  9:43 [RFC PATCH v2 00/13] arm: add support for SoC S5P4418 Stefan Bosch
                   ` (7 preceding siblings ...)
  2020-03-28  9:43 ` [RFC PATCH v2 08/13] video: add nexell video driver (soc: mlc, mipi) Stefan Bosch
@ 2020-03-28  9:43 ` Stefan Bosch
  2020-03-28  9:43 ` [RFC PATCH v2 10/13] video: add nexell video driver (soc: dpc, makefile) Stefan Bosch
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 21+ messages in thread
From: Stefan Bosch @ 2020-03-28  9:43 UTC (permalink / raw)
  To: u-boot

Low level functions for LVDS and HDMI display interfaces.

Signed-off-by: Stefan Bosch <stefan_b@posteo.net>
---

Changes in v2: None

 drivers/video/nexell/soc/s5pxx18_soc_hdmi.c |  50 +++
 drivers/video/nexell/soc/s5pxx18_soc_hdmi.h | 488 ++++++++++++++++++++++++++++
 drivers/video/nexell/soc/s5pxx18_soc_lvds.c | 278 ++++++++++++++++
 drivers/video/nexell/soc/s5pxx18_soc_lvds.h |  83 +++++
 4 files changed, 899 insertions(+)
 create mode 100644 drivers/video/nexell/soc/s5pxx18_soc_hdmi.c
 create mode 100644 drivers/video/nexell/soc/s5pxx18_soc_hdmi.h
 create mode 100644 drivers/video/nexell/soc/s5pxx18_soc_lvds.c
 create mode 100644 drivers/video/nexell/soc/s5pxx18_soc_lvds.h

diff --git a/drivers/video/nexell/soc/s5pxx18_soc_hdmi.c b/drivers/video/nexell/soc/s5pxx18_soc_hdmi.c
new file mode 100644
index 0000000..7b8be7e
--- /dev/null
+++ b/drivers/video/nexell/soc/s5pxx18_soc_hdmi.c
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2016  Nexell Co., Ltd.
+ *
+ * Author: junghyun, kim <jhkim@nexell.co.kr>
+ */
+
+#include <linux/types.h>
+#include <linux/io.h>
+
+#include "s5pxx18_soc_hdmi.h"
+
+static u32 *hdmi_base_addr;
+
+u32 nx_hdmi_get_reg(u32 module_index, u32 offset)
+{
+	u32 *reg_addr;
+	u32 regvalue;
+
+	reg_addr = hdmi_base_addr + (offset / sizeof(u32));
+	regvalue = readl((u32 *)reg_addr);
+
+	return regvalue;
+}
+
+void nx_hdmi_set_reg(u32 module_index, u32 offset, u32 regvalue)
+{
+	s64 offset_new = (s64)((int32_t)offset);
+	u32 *reg_addr;
+
+	reg_addr = hdmi_base_addr + (offset_new / sizeof(u32));
+	writel(regvalue, (u32 *)reg_addr);
+}
+
+void nx_hdmi_set_base_address(u32 module_index, void *base_address)
+{
+	hdmi_base_addr = (u32 *)base_address;
+}
+
+void *nx_hdmi_get_base_address(u32 module_index)
+{
+	return (u32 *)hdmi_base_addr;
+}
+
+u32 nx_hdmi_get_physical_address(u32 module_index)
+{
+	const u32 physical_addr[] = PHY_BASEADDR_HDMI_LIST;
+
+	return physical_addr[module_index];
+}
diff --git a/drivers/video/nexell/soc/s5pxx18_soc_hdmi.h b/drivers/video/nexell/soc/s5pxx18_soc_hdmi.h
new file mode 100644
index 0000000..a4c5ab5
--- /dev/null
+++ b/drivers/video/nexell/soc/s5pxx18_soc_hdmi.h
@@ -0,0 +1,488 @@
+/* SPDX-License-Identifier: GPL-2.0+
+ *
+ * Copyright (C) 2016  Nexell Co., Ltd.
+ *
+ * Author: junghyun, kim <jhkim@nexell.co.kr>
+ */
+
+#ifndef _S5PXX18_SOC_HDMI_H_
+#define _S5PXX18_SOC_HDMI_H_
+
+#include "s5pxx18_soc_disptop.h"
+
+#define PHY_BASEADDR_HDMI_PHY_MODULE	0xc00f0000
+#define PHY_BASEADDR_HDMI_LIST	\
+		{ PHY_BASEADDR_HDMI_MODULE }
+
+#define HDMI_LINK_INTC_CON_0		(HDMI_ADDR_OFFSET + 0x00000000)
+#define HDMI_LINK_INTC_FLAG_0		(HDMI_ADDR_OFFSET + 0x00000004)
+#define HDMI_LINK_AESKEY_VALID		(HDMI_ADDR_OFFSET + 0x00000008)
+#define HDMI_LINK_HPD				(HDMI_ADDR_OFFSET + 0x0000000C)
+#define HDMI_LINK_INTC_CON_1		(HDMI_ADDR_OFFSET + 0x00000010)
+#define HDMI_LINK_INTC_FLAG_1		(HDMI_ADDR_OFFSET + 0x00000014)
+#define HDMI_LINK_PHY_STATUS_0		(HDMI_ADDR_OFFSET + 0x00000020)
+#define HDMI_LINK_PHY_STATUS_CMU	(HDMI_ADDR_OFFSET + 0x00000024)
+#define HDMI_LINK_PHY_STATUS_PLL	(HDMI_ADDR_OFFSET + 0x00000028)
+#define HDMI_LINK_PHY_CON_0			(HDMI_ADDR_OFFSET + 0x00000030)
+#define HDMI_LINK_HPD_CTRL			(HDMI_ADDR_OFFSET + 0x00000040)
+#define HDMI_LINK_HPD_STATUS		(HDMI_ADDR_OFFSET + 0x00000044)
+#define HDMI_LINK_HPD_TH_x			(HDMI_ADDR_OFFSET + 0x00000050)
+
+#define HDMI_LINK_HDMI_CON_0		(HDMI_ADDR_OFFSET + 0x00010000)
+#define HDMI_LINK_HDMI_CON_1		(HDMI_ADDR_OFFSET + 0x00010004)
+#define HDMI_LINK_HDMI_CON_2		(HDMI_ADDR_OFFSET + 0x00010008)
+#define HDMI_LINK_STATUS			(HDMI_ADDR_OFFSET + 0x00010010)
+#define HDMI_LINK_STATUS_EN			(HDMI_ADDR_OFFSET + 0x00010020)
+
+#define HDMI_LINK_HDCP_SHA1_REN0	(HDMI_ADDR_OFFSET + 0x00010024)
+#define HDMI_LINK_HDCP_SHA1_REN1	(HDMI_ADDR_OFFSET + 0x00010028)
+
+#define HDMI_LINK_MODE_SEL			(HDMI_ADDR_OFFSET + 0x00010040)
+#define HDMI_LINK_ENC_EN			(HDMI_ADDR_OFFSET + 0x00010044)
+#define HDMI_LINK_HDMI_YMAX			(HDMI_ADDR_OFFSET + 0x00010060)
+#define HDMI_LINK_HDMI_YMIN			(HDMI_ADDR_OFFSET + 0x00010064)
+#define HDMI_LINK_HDMI_CMAX			(HDMI_ADDR_OFFSET + 0x00010068)
+#define HDMI_LINK_HDMI_CMIN			(HDMI_ADDR_OFFSET + 0x0001006C)
+#define HDMI_LINK_H_BLANK_0			(HDMI_ADDR_OFFSET + 0x000100A0)
+#define HDMI_LINK_H_BLANK_1			(HDMI_ADDR_OFFSET + 0x000100A4)
+#define HDMI_LINK_V2_BLANK_0		(HDMI_ADDR_OFFSET + 0x000100B0)
+#define HDMI_LINK_V2_BLANK_1		(HDMI_ADDR_OFFSET + 0x000100B4)
+#define HDMI_LINK_V1_BLANK_0		(HDMI_ADDR_OFFSET + 0x000100B8)
+#define HDMI_LINK_V1_BLANK_1		(HDMI_ADDR_OFFSET + 0x000100BC)
+#define HDMI_LINK_V_LINE_0			(HDMI_ADDR_OFFSET + 0x000100C0)
+#define HDMI_LINK_V_LINE_1			(HDMI_ADDR_OFFSET + 0x000100C4)
+#define HDMI_LINK_H_LINE_0			(HDMI_ADDR_OFFSET + 0x000100C8)
+#define HDMI_LINK_H_LINE_1			(HDMI_ADDR_OFFSET + 0x000100CC)
+#define HDMI_LINK_HSYNC_POL			(HDMI_ADDR_OFFSET + 0x000100E0)
+#define HDMI_LINK_VSYNC_POL			(HDMI_ADDR_OFFSET + 0x000100E4)
+#define HDMI_LINK_INT_PRO_MODE		(HDMI_ADDR_OFFSET + 0x000100E8)
+#define HDMI_LINK_SEND_START_0		(HDMI_ADDR_OFFSET + 0x000100F0)
+#define HDMI_LINK_SEND_START_1		(HDMI_ADDR_OFFSET + 0x000100F4)
+#define HDMI_LINK_SEND_END_0		(HDMI_ADDR_OFFSET + 0x00010100)
+#define HDMI_LINK_SEND_END_1		(HDMI_ADDR_OFFSET + 0x00010104)
+#define HDMI_LINK_SEND_END_2		(HDMI_ADDR_OFFSET + 0x00010108)
+#define HDMI_LINK_V_BLANK_F0_0		(HDMI_ADDR_OFFSET + 0x00010110)
+#define HDMI_LINK_V_BLANK_F0_1		(HDMI_ADDR_OFFSET + 0x00010114)
+#define HDMI_LINK_V_BLANK_F1_0		(HDMI_ADDR_OFFSET + 0x00010118)
+#define HDMI_LINK_V_BLANK_F1_1		(HDMI_ADDR_OFFSET + 0x0001011C)
+#define HDMI_LINK_H_SYNC_START_0	(HDMI_ADDR_OFFSET + 0x00010120)
+#define HDMI_LINK_H_SYNC_START_1	(HDMI_ADDR_OFFSET + 0x00010124)
+#define HDMI_LINK_H_SYNC_END_0		(HDMI_ADDR_OFFSET + 0x00010128)
+#define HDMI_LINK_H_SYNC_END_1		(HDMI_ADDR_OFFSET + 0x0001012C)
+#define HDMI_LINK_V_SYNC_LINE_BEF_2_0	(HDMI_ADDR_OFFSET + 0x00010130)
+#define HDMI_LINK_V_SYNC_LINE_BEF_2_1	(HDMI_ADDR_OFFSET + 0x00010134)
+#define HDMI_LINK_V_SYNC_LINE_BEF_1_0		(HDMI_ADDR_OFFSET + 0x00010138)
+#define HDMI_LINK_V_SYNC_LINE_BEF_1_1		(HDMI_ADDR_OFFSET + 0x0001013C)
+#define HDMI_LINK_V_SYNC_LINE_AFT_2_0		(HDMI_ADDR_OFFSET + 0x00010140)
+#define HDMI_LINK_V_SYNC_LINE_AFT_2_1		(HDMI_ADDR_OFFSET + 0x00010144)
+#define HDMI_LINK_V_SYNC_LINE_AFT_1_0		(HDMI_ADDR_OFFSET + 0x00010148)
+#define HDMI_LINK_V_SYNC_LINE_AFT_1_1		(HDMI_ADDR_OFFSET + 0x0001014C)
+#define HDMI_LINK_V_SYNC_LINE_AFT_PXL_2_0	(HDMI_ADDR_OFFSET + 0x00010150)
+#define HDMI_LINK_V_SYNC_LINE_AFT_PXL_2_1	(HDMI_ADDR_OFFSET + 0x00010154)
+#define HDMI_LINK_V_SYNC_LINE_AFT_PXL_1_0	(HDMI_ADDR_OFFSET + 0x00010158)
+#define HDMI_LINK_V_SYNC_LINE_AFT_PXL_1_1	(HDMI_ADDR_OFFSET + 0x0001015C)
+#define HDMI_LINK_V_BLANK_F2_0		(HDMI_ADDR_OFFSET + 0x00010160)
+#define HDMI_LINK_V_BLANK_F2_1		(HDMI_ADDR_OFFSET + 0x00010164)
+#define HDMI_LINK_V_BLANK_F3_0		(HDMI_ADDR_OFFSET + 0x00010168)
+#define HDMI_LINK_V_BLANK_F3_1		(HDMI_ADDR_OFFSET + 0x0001016C)
+#define HDMI_LINK_V_BLANK_F4_0		(HDMI_ADDR_OFFSET + 0x00010170)
+#define HDMI_LINK_V_BLANK_F4_1		(HDMI_ADDR_OFFSET + 0x00010174)
+#define HDMI_LINK_V_BLANK_F5_0		(HDMI_ADDR_OFFSET + 0x00010178)
+#define HDMI_LINK_V_BLANK_F5_1		(HDMI_ADDR_OFFSET + 0x0001017C)
+#define HDMI_LINK_V_SYNC_LINE_AFT_3_0		(HDMI_ADDR_OFFSET + 0x00010180)
+#define HDMI_LINK_V_SYNC_LINE_AFT_3_1		(HDMI_ADDR_OFFSET + 0x00010184)
+#define HDMI_LINK_V_SYNC_LINE_AFT_4_0		(HDMI_ADDR_OFFSET + 0x00010188)
+#define HDMI_LINK_V_SYNC_LINE_AFT_4_1		(HDMI_ADDR_OFFSET + 0x0001018C)
+#define HDMI_LINK_V_SYNC_LINE_AFT_5_0		(HDMI_ADDR_OFFSET + 0x00010190)
+#define HDMI_LINK_V_SYNC_LINE_AFT_5_1		(HDMI_ADDR_OFFSET + 0x00010194)
+#define HDMI_LINK_V_SYNC_LINE_AFT_6_0		(HDMI_ADDR_OFFSET + 0x00010198)
+#define HDMI_LINK_V_SYNC_LINE_AFT_6_1		(HDMI_ADDR_OFFSET + 0x0001019C)
+#define HDMI_LINK_V_SYNC_LINE_AFT_PXL_3_0	(HDMI_ADDR_OFFSET + 0x000101A0)
+#define HDMI_LINK_V_SYNC_LINE_AFT_PXL_3_1	(HDMI_ADDR_OFFSET + 0x000101A4)
+#define HDMI_LINK_V_SYNC_LINE_AFT_PXL_4_0	(HDMI_ADDR_OFFSET + 0x000101A8)
+#define HDMI_LINK_V_SYNC_LINE_AFT_PXL_4_1	(HDMI_ADDR_OFFSET + 0x000101AC)
+#define HDMI_LINK_V_SYNC_LINE_AFT_PXL_5_0	(HDMI_ADDR_OFFSET + 0x000101B0)
+#define HDMI_LINK_V_SYNC_LINE_AFT_PXL_5_1	(HDMI_ADDR_OFFSET + 0x000101B4)
+#define HDMI_LINK_V_SYNC_LINE_AFT_PXL_6_0	(HDMI_ADDR_OFFSET + 0x000101B8)
+#define HDMI_LINK_V_SYNC_LINE_AFT_PXL_6_1	(HDMI_ADDR_OFFSET + 0x000101BC)
+#define HDMI_LINK_VACT_SPACE1_0		(HDMI_ADDR_OFFSET + 0x000101C0)
+#define HDMI_LINK_VACT_SPACE1_1		(HDMI_ADDR_OFFSET + 0x000101C4)
+#define HDMI_LINK_VACT_SPACE2_0		(HDMI_ADDR_OFFSET + 0x000101C8)
+#define HDMI_LINK_VACT_SPACE2_1		(HDMI_ADDR_OFFSET + 0x000101CC)
+#define HDMI_LINK_VACT_SPACE3_0		(HDMI_ADDR_OFFSET + 0x000101D0)
+#define HDMI_LINK_VACT_SPACE3_1		(HDMI_ADDR_OFFSET + 0x000101D4)
+#define HDMI_LINK_VACT_SPACE4_0		(HDMI_ADDR_OFFSET + 0x000101D8)
+#define HDMI_LINK_VACT_SPACE4_1		(HDMI_ADDR_OFFSET + 0x000101DC)
+#define HDMI_LINK_VACT_SPACE5_0		(HDMI_ADDR_OFFSET + 0x000101E0)
+#define HDMI_LINK_VACT_SPACE5_1		(HDMI_ADDR_OFFSET + 0x000101E4)
+#define HDMI_LINK_VACT_SPACE6_0		(HDMI_ADDR_OFFSET + 0x000101E8)
+#define HDMI_LINK_VACT_SPACE6_1		(HDMI_ADDR_OFFSET + 0x000101EC)
+
+#define HDMI_LINK_CSC_MUX		(HDMI_ADDR_OFFSET + 0x000101F0)
+#define HDMI_LINK_SYNC_GEN_MUX	(HDMI_ADDR_OFFSET + 0x000101F4)
+
+#define HDMI_LINK_GCP_CON			(HDMI_ADDR_OFFSET + 0x00010200)
+#define HDMI_LINK_GCP_BYTE1			(HDMI_ADDR_OFFSET + 0x00010210)
+#define HDMI_LINK_GCP_BYTE2			(HDMI_ADDR_OFFSET + 0x00010214)
+#define HDMI_LINK_GCP_BYTE3			(HDMI_ADDR_OFFSET + 0x00010218)
+#define HDMI_LINK_ASP_CON			(HDMI_ADDR_OFFSET + 0x00010300)
+#define HDMI_LINK_ASP_SP_FLAT		(HDMI_ADDR_OFFSET + 0x00010304)
+#define HDMI_LINK_ASP_CHCFG0		(HDMI_ADDR_OFFSET + 0x00010310)
+#define HDMI_LINK_ASP_CHCFG1		(HDMI_ADDR_OFFSET + 0x00010314)
+#define HDMI_LINK_ASP_CHCFG2		(HDMI_ADDR_OFFSET + 0x00010318)
+#define HDMI_LINK_ASP_CHCFG3		(HDMI_ADDR_OFFSET + 0x0001031C)
+#define HDMI_LINK_ACR_CON			(HDMI_ADDR_OFFSET + 0x00010400)
+#define HDMI_LINK_ACR_MCTS0			(HDMI_ADDR_OFFSET + 0x00010410)
+#define HDMI_LINK_ACR_MCTS1			(HDMI_ADDR_OFFSET + 0x00010414)
+#define HDMI_LINK_ACR_MCTS2			(HDMI_ADDR_OFFSET + 0x00010418)
+#define HDMI_LINK_ACR_N0			(HDMI_ADDR_OFFSET + 0x00010430)
+#define HDMI_LINK_ACR_N1			(HDMI_ADDR_OFFSET + 0x00010434)
+#define HDMI_LINK_ACR_N2			(HDMI_ADDR_OFFSET + 0x00010438)
+#define HDMI_LINK_ACP_CON			(HDMI_ADDR_OFFSET + 0x00010500)
+#define HDMI_LINK_ACP_TYPE			(HDMI_ADDR_OFFSET + 0x00010514)
+#define HDMI_LINK_ACP_DATAX			(HDMI_ADDR_OFFSET + 0x00010520)
+#define HDMI_LINK_ISRC_CON			(HDMI_ADDR_OFFSET + 0x00010600)
+#define HDMI_LINK_ISRC1_HEADER1		(HDMI_ADDR_OFFSET + 0x00010614)
+#define HDMI_LINK_ISRC1_DATAX		(HDMI_ADDR_OFFSET + 0x00010620)
+#define HDMI_LINK_ISRC2_DATAX		(HDMI_ADDR_OFFSET + 0x000106A0)
+#define HDMI_LINK_AVI_CON			(HDMI_ADDR_OFFSET + 0x00010700)
+#define HDMI_LINK_AVI_HEADER0		(HDMI_ADDR_OFFSET + 0x00010710)
+#define HDMI_LINK_AVI_HEADER1		(HDMI_ADDR_OFFSET + 0x00010714)
+#define HDMI_LINK_AVI_HEADER2		(HDMI_ADDR_OFFSET + 0x00010718)
+#define HDMI_LINK_AVI_CHECK_SUM		(HDMI_ADDR_OFFSET + 0x0001071C)
+#define HDMI_LINK_AVI_BYTEX			(HDMI_ADDR_OFFSET + 0x00010720)
+#define HDMI_LINK_AVI_BYTE00		(HDMI_ADDR_OFFSET + 0x00010720)
+#define HDMI_LINK_AVI_BYTE01		(HDMI_ADDR_OFFSET + 0x00010724)
+#define HDMI_LINK_AVI_BYTE02		(HDMI_ADDR_OFFSET + 0x00010728)
+#define HDMI_LINK_AVI_BYTE03		(HDMI_ADDR_OFFSET + 0x0001073C)
+#define HDMI_LINK_AVI_BYTE04		(HDMI_ADDR_OFFSET + 0x00010730)
+#define HDMI_LINK_AVI_BYTE05		(HDMI_ADDR_OFFSET + 0x00010734)
+#define HDMI_LINK_AVI_BYTE06		(HDMI_ADDR_OFFSET + 0x00010738)
+#define HDMI_LINK_AVI_BYTE07		(HDMI_ADDR_OFFSET + 0x0001074C)
+#define HDMI_LINK_AVI_BYTE08		(HDMI_ADDR_OFFSET + 0x00010740)
+#define HDMI_LINK_AVI_BYTE09		(HDMI_ADDR_OFFSET + 0x00010744)
+#define HDMI_LINK_AVI_BYTE10		(HDMI_ADDR_OFFSET + 0x00010748)
+#define HDMI_LINK_AVI_BYTE11		(HDMI_ADDR_OFFSET + 0x0001074C)
+#define HDMI_LINK_AVI_BYTE12		(HDMI_ADDR_OFFSET + 0x00010750)
+#define HDMI_LINK_AUI_CON			(HDMI_ADDR_OFFSET + 0x00010800)
+#define HDMI_LINK_AUI_HEADER0		(HDMI_ADDR_OFFSET + 0x00010810)
+#define HDMI_LINK_AUI_HEADER1		(HDMI_ADDR_OFFSET + 0x00010814)
+#define HDMI_LINK_AUI_HEADER2		(HDMI_ADDR_OFFSET + 0x00010818)
+#define HDMI_LINK_AUI_CHECK_SUM		(HDMI_ADDR_OFFSET + 0x0001081C)
+#define HDMI_LINK_AUI_BYTEX			(HDMI_ADDR_OFFSET + 0x00010820)
+#define HDMI_LINK_MPG_CON			(HDMI_ADDR_OFFSET + 0x00010900)
+#define HDMI_LINK_MPG_CHECK_SUM		(HDMI_ADDR_OFFSET + 0x0001091C)
+#define HDMI_LINK_MPG_DATAX			(HDMI_ADDR_OFFSET + 0x00010920)
+#define HDMI_LINK_SPD_CON			(HDMI_ADDR_OFFSET + 0x00010A00)
+#define HDMI_LINK_SPD_HEADER0		(HDMI_ADDR_OFFSET + 0x00010A10)
+#define HDMI_LINK_SPD_HEADER1		(HDMI_ADDR_OFFSET + 0x00010A14)
+#define HDMI_LINK_SPD_HEADER2		(HDMI_ADDR_OFFSET + 0x00010A18)
+#define HDMI_LINK_SPD_DATAX			(HDMI_ADDR_OFFSET + 0x00010A20)
+#define HDMI_LINK_GAMUT_CON			(HDMI_ADDR_OFFSET + 0x00010B00)
+#define HDMI_LINK_GAMUT_HEADER0		(HDMI_ADDR_OFFSET + 0x00010B10)
+#define HDMI_LINK_GAMUT_HEADER1		(HDMI_ADDR_OFFSET + 0x00010B14)
+#define HDMI_LINK_GAMUT_HEADER2		(HDMI_ADDR_OFFSET + 0x00010B18)
+#define HDMI_LINK_GAMUT_METADATAX	(HDMI_ADDR_OFFSET + 0x00010B20)
+#define HDMI_LINK_VSI_CON			(HDMI_ADDR_OFFSET + 0x00010C00)
+#define HDMI_LINK_VSI_HEADER0		(HDMI_ADDR_OFFSET + 0x00010C10)
+#define HDMI_LINK_VSI_HEADER1		(HDMI_ADDR_OFFSET + 0x00010C14)
+#define HDMI_LINK_VSI_HEADER2		(HDMI_ADDR_OFFSET + 0x00010C18)
+#define HDMI_LINK_VSI_DATAX			(HDMI_ADDR_OFFSET + 0x00010C20)
+#define HDMI_LINK_VSI_DATA00		(HDMI_ADDR_OFFSET + 0x00010C20)
+#define HDMI_LINK_VSI_DATA01		(HDMI_ADDR_OFFSET + 0x00010C24)
+#define HDMI_LINK_VSI_DATA02		(HDMI_ADDR_OFFSET + 0x00010C28)
+#define HDMI_LINK_VSI_DATA03		(HDMI_ADDR_OFFSET + 0x00010C2C)
+#define HDMI_LINK_VSI_DATA04		(HDMI_ADDR_OFFSET + 0x00010C30)
+#define HDMI_LINK_VSI_DATA05		(HDMI_ADDR_OFFSET + 0x00010C34)
+#define HDMI_LINK_VSI_DATA06		(HDMI_ADDR_OFFSET + 0x00010C38)
+#define HDMI_LINK_VSI_DATA07		(HDMI_ADDR_OFFSET + 0x00010C3C)
+#define HDMI_LINK_VSI_DATA08		(HDMI_ADDR_OFFSET + 0x00010C40)
+#define HDMI_LINK_VSI_DATA09		(HDMI_ADDR_OFFSET + 0x00010C44)
+#define HDMI_LINK_VSI_DATA10		(HDMI_ADDR_OFFSET + 0x00010C48)
+#define HDMI_LINK_VSI_DATA11		(HDMI_ADDR_OFFSET + 0x00010c4c)
+#define HDMI_LINK_VSI_DATA12		(HDMI_ADDR_OFFSET + 0x00010C50)
+#define HDMI_LINK_VSI_DATA13		(HDMI_ADDR_OFFSET + 0x00010C54)
+#define HDMI_LINK_VSI_DATA14		(HDMI_ADDR_OFFSET + 0x00010C58)
+#define HDMI_LINK_VSI_DATA15		(HDMI_ADDR_OFFSET + 0x00010C5c)
+#define HDMI_LINK_VSI_DATA16		(HDMI_ADDR_OFFSET + 0x00010C60)
+#define HDMI_LINK_VSI_DATA17		(HDMI_ADDR_OFFSET + 0x00010C64)
+#define HDMI_LINK_VSI_DATA18		(HDMI_ADDR_OFFSET + 0x00010C68)
+#define HDMI_LINK_VSI_DATA19		(HDMI_ADDR_OFFSET + 0x00010C6c)
+#define HDMI_LINK_VSI_DATA20		(HDMI_ADDR_OFFSET + 0x00010C70)
+#define HDMI_LINK_VSI_DATA21		(HDMI_ADDR_OFFSET + 0x00010c74)
+#define HDMI_LINK_VSI_DATA22		(HDMI_ADDR_OFFSET + 0x00010C78)
+#define HDMI_LINK_VSI_DATA23		(HDMI_ADDR_OFFSET + 0x00010C7c)
+#define HDMI_LINK_VSI_DATA24		(HDMI_ADDR_OFFSET + 0x00010C80)
+#define HDMI_LINK_VSI_DATA25		(HDMI_ADDR_OFFSET + 0x00010C84)
+#define HDMI_LINK_VSI_DATA26		(HDMI_ADDR_OFFSET + 0x00010C88)
+#define HDMI_LINK_VSI_DATA27		(HDMI_ADDR_OFFSET + 0x00010C8C)
+#define HDMI_LINK_DC_CONTROL		(HDMI_ADDR_OFFSET + 0x00010D00)
+#define HDMI_LINK_VIDEO_PATTERN_GEN	(HDMI_ADDR_OFFSET + 0x00010D04)
+#define HDMI_LINK_AN_SEED_SEL		(HDMI_ADDR_OFFSET + 0x00010E48)
+#define HDMI_LINK_AN_SEED_0			(HDMI_ADDR_OFFSET + 0x00010E58)
+#define HDMI_LINK_AN_SEED_1			(HDMI_ADDR_OFFSET + 0x00010E5C)
+#define HDMI_LINK_AN_SEED_2			(HDMI_ADDR_OFFSET + 0x00010E60)
+#define HDMI_LINK_AN_SEED_3			(HDMI_ADDR_OFFSET + 0x00010E64)
+#define HDMI_LINK_HDCP_SHA1_X		(HDMI_ADDR_OFFSET + 0x00017000)
+
+#define HDMI_LINK_HDCP_SHA1_0_0	(HDMI_LINK_HDCP_SHA1_x   + 0x00)
+#define HDMI_LINK_HDCP_SHA1_0_1	(HDMI_LINK_HDCP_SHA1_0_0 + 0x04)
+#define HDMI_LINK_HDCP_SHA1_0_2	(HDMI_LINK_HDCP_SHA1_0_0 + 0x08)
+#define HDMI_LINK_HDCP_SHA1_0_3	(HDMI_LINK_HDCP_SHA1_0_0 + 0x0C)
+#define HDMI_LINK_HDCP_SHA1_1_0	(HDMI_LINK_HDCP_SHA1_x   + 0x10)
+#define HDMI_LINK_HDCP_SHA1_1_1	(HDMI_LINK_HDCP_SHA1_1_0 + 0x04)
+#define HDMI_LINK_HDCP_SHA1_1_2	(HDMI_LINK_HDCP_SHA1_1_0 + 0x08)
+#define HDMI_LINK_HDCP_SHA1_1_3	(HDMI_LINK_HDCP_SHA1_1_0 + 0x0C)
+#define HDMI_LINK_HDCP_SHA1_2_0	(HDMI_LINK_HDCP_SHA1_x   + 0x20)
+#define HDMI_LINK_HDCP_SHA1_2_1	(HDMI_LINK_HDCP_SHA1_2_0 + 0x04)
+#define HDMI_LINK_HDCP_SHA1_2_2	(HDMI_LINK_HDCP_SHA1_2_0 + 0x08)
+#define HDMI_LINK_HDCP_SHA1_2_3	(HDMI_LINK_HDCP_SHA1_2_0 + 0x0C)
+#define HDMI_LINK_HDCP_SHA1_3_0	(HDMI_LINK_HDCP_SHA1_x   + 0x30)
+#define HDMI_LINK_HDCP_SHA1_3_1	(HDMI_LINK_HDCP_SHA1_3_0 + 0x04)
+#define HDMI_LINK_HDCP_SHA1_3_2	(HDMI_LINK_HDCP_SHA1_3_0 + 0x08)
+#define HDMI_LINK_HDCP_SHA1_3_3	(HDMI_LINK_HDCP_SHA1_3_0 + 0x0C)
+#define HDMI_LINK_HDCP_SHA1_4_0	(HDMI_LINK_HDCP_SHA1_x   + 0x40)
+#define HDMI_LINK_HDCP_SHA1_4_1	(HDMI_LINK_HDCP_SHA1_4_0 + 0x04)
+#define HDMI_LINK_HDCP_SHA1_4_2	(HDMI_LINK_HDCP_SHA1_4_0 + 0x08)
+#define HDMI_LINK_HDCP_SHA1_4_3	(HDMI_LINK_HDCP_SHA1_4_0 + 0x0C)
+
+#define HDMI_LINK_HDCP_KSV_LIST_X	(HDMI_ADDR_OFFSET + 0x00017050)
+
+#define HDMI_LINK_HDCP_KSV_0_0	(HDMI_LINK_HDCP_KSV_LIST_X + 0x00)
+#define HDMI_LINK_HDCP_KSV_0_1	(HDMI_LINK_HDCP_KSV_LIST_X + 0x04)
+#define HDMI_LINK_HDCP_KSV_0_2	(HDMI_LINK_HDCP_KSV_LIST_X + 0x08)
+#define HDMI_LINK_HDCP_KSV_0_3	(HDMI_LINK_HDCP_KSV_LIST_X + 0x0C)
+#define HDMI_LINK_HDCP_KSV_1_0	(HDMI_LINK_HDCP_KSV_LIST_X + 0x10)
+#define HDMI_LINK_HDCP_KSV_1_1	(HDMI_LINK_HDCP_KSV_LIST_X + 0x14)
+
+#define HDMI_LINK_HDCP_KSV_LIST_0_0	(HDMI_LINK_HDCP_KSV_LIST_X + 0x00)
+#define HDMI_LINK_HDCP_KSV_LIST_0_1	(HDMI_LINK_HDCP_KSV_LIST_X + 0x04)
+#define HDMI_LINK_HDCP_KSV_LIST_0_2	(HDMI_LINK_HDCP_KSV_LIST_X + 0x08)
+#define HDMI_LINK_HDCP_KSV_LIST_0_3	(HDMI_LINK_HDCP_KSV_LIST_X + 0x0C)
+#define HDMI_LINK_HDCP_KSV_LIST_1_0	(HDMI_LINK_HDCP_KSV_LIST_X + 0x10)
+#define HDMI_LINK_HDCP_KSV_LIST_1_1	(HDMI_LINK_HDCP_KSV_LIST_X + 0x14)
+
+#define HDMI_LINK_HDCP_KSV_LIST_CON	(HDMI_ADDR_OFFSET + 0x00017064)
+#define HDMI_LINK_HDCP_SHA_RESULT	(HDMI_ADDR_OFFSET + 0x00017070)
+#define HDMI_LINK_HDCP_CTRL1		(HDMI_ADDR_OFFSET + 0x00017080)
+#define HDMI_LINK_HDCP_CTRL2		(HDMI_ADDR_OFFSET + 0x00017084)
+#define HDMI_LINK_HDCP_CHECK_RESULT	(HDMI_ADDR_OFFSET + 0x00017090)
+#define HDMI_LINK_HDCP_BKSV_X	(HDMI_ADDR_OFFSET + 0x000170A0)
+
+#define HDMI_LINK_HDCP_BKSV0_0	(HDMI_ADDR_OFFSET + 0x000170A0)
+#define HDMI_LINK_HDCP_BKSV0_1	(HDMI_ADDR_OFFSET + 0x000170A4)
+#define HDMI_LINK_HDCP_BKSV0_2	(HDMI_ADDR_OFFSET + 0x000170A8)
+#define HDMI_LINK_HDCP_BKSV0_3	(HDMI_ADDR_OFFSET + 0x000170AC)
+#define HDMI_LINK_HDCP_BKSV1	(HDMI_ADDR_OFFSET + 0x000170B0)
+
+#define HDMI_LINK_HDCP_AKSV_X		(HDMI_ADDR_OFFSET + 0x000170C0)
+#define HDMI_LINK_HDCP_AN_X			(HDMI_ADDR_OFFSET + 0x000170E0)
+#define HDMI_LINK_HDCP_BCAPS		(HDMI_ADDR_OFFSET + 0x00017100)
+#define HDMI_LINK_HDCP_BSTATUS_0	(HDMI_ADDR_OFFSET + 0x00017110)
+#define HDMI_LINK_HDCP_BSTATUS_1	(HDMI_ADDR_OFFSET + 0x00017114)
+#define HDMI_LINK_HDCP_RI_0			(HDMI_ADDR_OFFSET + 0x00017140)
+#define HDMI_LINK_HDCP_RI_1			(HDMI_ADDR_OFFSET + 0x00017144)
+
+#define HDMI_LINK_HDCP_OFFSET_TX_0	(HDMI_ADDR_OFFSET + 0x00017160)
+#define HDMI_LINK_HDCP_OFFSET_TX_1	(HDMI_ADDR_OFFSET + 0x00017164)
+#define HDMI_LINK_HDCP_OFFSET_TX_2	(HDMI_ADDR_OFFSET + 0x00017168)
+#define HDMI_LINK_HDCP_OFFSET_TX_3	(HDMI_ADDR_OFFSET + 0x0001716C)
+#define HDMI_LINK_HDCP_CYCLE_AA		(HDMI_ADDR_OFFSET + 0x00017170)
+
+#define HDMI_LINK_HDCP_I2C_INT		(HDMI_ADDR_OFFSET + 0x00017180)
+#define HDMI_LINK_HDCP_AN_INT		(HDMI_ADDR_OFFSET + 0x00017190)
+#define HDMI_LINK_HDCP_WATCHDOG_INT	(HDMI_ADDR_OFFSET + 0x000171A0)
+#define HDMI_LINK_HDCP_RI_INT		(HDMI_ADDR_OFFSET + 0x000171B0)
+#define HDMI_LINK_HDCP_RI_COMPARE_0	(HDMI_ADDR_OFFSET + 0x000171D0)
+#define HDMI_LINK_HDCP_RI_COMPARE_1	(HDMI_ADDR_OFFSET + 0x000171D4)
+
+#define HDMI_LINK_HDCP_RI_INT		(HDMI_ADDR_OFFSET + 0x000171B0)
+#define HDMI_LINK_HDCP_RI_COMPARE_0	(HDMI_ADDR_OFFSET + 0x000171D0)
+#define HDMI_LINK_HDCP_RI_COMPARE_1	(HDMI_ADDR_OFFSET + 0x000171D4)
+
+#define HDMI_LINK_HDCP_FRAME_COUNT	(HDMI_ADDR_OFFSET + 0x000171E0)
+#define HDMI_LINK_RGB_ROUND_EN		(HDMI_ADDR_OFFSET + 0x0001D500)
+#define HDMI_LINK_VACT_SPACE_R_0	(HDMI_ADDR_OFFSET + 0x0001D504)
+#define HDMI_LINK_VACT_SPACE_R_1	(HDMI_ADDR_OFFSET + 0x0001D508)
+#define HDMI_LINK_VACT_SPACE_G_0	(HDMI_ADDR_OFFSET + 0x0001D50C)
+#define HDMI_LINK_VACT_SPACE_G_1	(HDMI_ADDR_OFFSET + 0x0001D510)
+#define HDMI_LINK_VACT_SPACE_B_0	(HDMI_ADDR_OFFSET + 0x0001D514)
+#define HDMI_LINK_VACT_SPACE_B_1	(HDMI_ADDR_OFFSET + 0x0001D518)
+#define HDMI_LINK_BLUE_SCREEN_R_0	(HDMI_ADDR_OFFSET + 0x0001D520)
+#define HDMI_LINK_BLUE_SCREEN_R_1	(HDMI_ADDR_OFFSET + 0x0001D524)
+#define HDMI_LINK_BLUE_SCREEN_G_0	(HDMI_ADDR_OFFSET + 0x0001D528)
+#define HDMI_LINK_BLUE_SCREEN_G_1	(HDMI_ADDR_OFFSET + 0x0001D52C)
+#define HDMI_LINK_BLUE_SCREEN_B_0	(HDMI_ADDR_OFFSET + 0x0001D530)
+#define HDMI_LINK_BLUE_SCREEN_B_1	(HDMI_ADDR_OFFSET + 0x0001D534)
+#define HDMI_LINK_AES_START			(HDMI_ADDR_OFFSET +  0x00020000)
+#define HDMI_LINK_AES_DATA_SIZE_L	(HDMI_ADDR_OFFSET +  0x00020020)
+#define HDMI_LINK_AES_DATA_SIZE_H	(HDMI_ADDR_OFFSET +  0x00020024)
+#define HDMI_LINK_AES_DATA			(HDMI_ADDR_OFFSET +  0x00020040)
+#define HDMI_LINK_SPDIFIN_CLK_CTRL	(HDMI_ADDR_OFFSET + 0x00030000)
+#define HDMI_LINK_SPDIFIN_OP_CTRL          (HDMI_ADDR_OFFSET + 0x00030004)
+#define HDMI_LINK_SPDIFIN_IRQ_MASK         (HDMI_ADDR_OFFSET + 0x00030008)
+#define HDMI_LINK_SPDIFIN_IRQ_STATUS       (HDMI_ADDR_OFFSET + 0x0003000C)
+#define HDMI_LINK_SPDIFIN_CONFIG_1         (HDMI_ADDR_OFFSET + 0x00030010)
+#define HDMI_LINK_SPDIFIN_CONFIG_2         (HDMI_ADDR_OFFSET + 0x00030014)
+#define HDMI_LINK_SPDIFIN_USER_VALUE_1     (HDMI_ADDR_OFFSET + 0x00030020)
+#define HDMI_LINK_SPDIFIN_USER_VALUE_2     (HDMI_ADDR_OFFSET + 0x00030024)
+#define HDMI_LINK_SPDIFIN_USER_VALUE_3     (HDMI_ADDR_OFFSET + 0x00030028)
+#define HDMI_LINK_SPDIFIN_USER_VALUE_4     (HDMI_ADDR_OFFSET + 0x0003002C)
+#define HDMI_LINK_SPDIFIN_CH_STATUS_0_1    (HDMI_ADDR_OFFSET + 0x00030030)
+#define HDMI_LINK_SPDIFIN_CH_STATUS_0_2    (HDMI_ADDR_OFFSET + 0x00030034)
+#define HDMI_LINK_SPDIFIN_CH_STATUS_0_3    (HDMI_ADDR_OFFSET + 0x00030038)
+#define HDMI_LINK_SPDIFIN_CH_STATUS_0_4    (HDMI_ADDR_OFFSET + 0x0003003C)
+#define HDMI_LINK_SPDIFIN_CH_STATUS_1      (HDMI_ADDR_OFFSET + 0x00030040)
+#define HDMI_LINK_SPDIFIN_FRAME_PERIOD_1   (HDMI_ADDR_OFFSET + 0x00030048)
+#define HDMI_LINK_SPDIFIN_FRAME_PERIOD_2   (HDMI_ADDR_OFFSET + 0x0003004C)
+#define HDMI_LINK_SPDIFIN_PC_INFO_1        (HDMI_ADDR_OFFSET + 0x00030050)
+#define HDMI_LINK_SPDIFIN_PC_INFO_2        (HDMI_ADDR_OFFSET + 0x00030054)
+#define HDMI_LINK_SPDIFIN_PD_INFO_1        (HDMI_ADDR_OFFSET + 0x00030058)
+#define HDMI_LINK_SPDIFIN_PD_INFO_2        (HDMI_ADDR_OFFSET + 0x0003005C)
+#define HDMI_LINK_SPDIFIN_DATA_BUF_0_1     (HDMI_ADDR_OFFSET + 0x00030060)
+#define HDMI_LINK_SPDIFIN_DATA_BUF_0_2     (HDMI_ADDR_OFFSET + 0x00030064)
+#define HDMI_LINK_SPDIFIN_DATA_BUF_0_3     (HDMI_ADDR_OFFSET + 0x00030068)
+#define HDMI_LINK_SPDIFIN_USER_BUF_0       (HDMI_ADDR_OFFSET + 0x0003006C)
+#define HDMI_LINK_SPDIFIN_DATA_BUF_1_1     (HDMI_ADDR_OFFSET + 0x00030070)
+#define HDMI_LINK_SPDIFIN_DATA_BUF_1_2     (HDMI_ADDR_OFFSET + 0x00030074)
+#define HDMI_LINK_SPDIFIN_DATA_BUF_1_3     (HDMI_ADDR_OFFSET + 0x00030078)
+#define HDMI_LINK_SPDIFIN_USER_BUF_1       (HDMI_ADDR_OFFSET + 0x0003007C)
+#define HDMI_LINK_I2S_CLK_CON         (HDMI_ADDR_OFFSET + 0x00040000)
+#define HDMI_LINK_I2S_CON_1           (HDMI_ADDR_OFFSET + 0x00040004)
+#define HDMI_LINK_I2S_CON_2           (HDMI_ADDR_OFFSET + 0x00040008)
+#define HDMI_LINK_I2S_PIN_SEL_0       (HDMI_ADDR_OFFSET + 0x0004000C)
+#define HDMI_LINK_I2S_PIN_SEL_1       (HDMI_ADDR_OFFSET + 0x00040010)
+#define HDMI_LINK_I2S_PIN_SEL_2       (HDMI_ADDR_OFFSET + 0x00040014)
+#define HDMI_LINK_I2S_PIN_SEL_3       (HDMI_ADDR_OFFSET + 0x00040018)
+#define HDMI_LINK_I2S_DSD_CON         (HDMI_ADDR_OFFSET + 0x0004001C)
+#define HDMI_LINK_I2S_MUX_CON         (HDMI_ADDR_OFFSET + 0x00040020)
+#define HDMI_LINK_I2S_CH_ST_CON       (HDMI_ADDR_OFFSET + 0x00040024)
+#define HDMI_LINK_I2S_CH_ST_0         (HDMI_ADDR_OFFSET + 0x00040028)
+#define HDMI_LINK_I2S_CH_ST_1         (HDMI_ADDR_OFFSET + 0x0004002C)
+#define HDMI_LINK_I2S_CH_ST_2         (HDMI_ADDR_OFFSET + 0x00040030)
+#define HDMI_LINK_I2S_CH_ST_3         (HDMI_ADDR_OFFSET + 0x00040034)
+#define HDMI_LINK_I2S_CH_ST_4         (HDMI_ADDR_OFFSET + 0x00040038)
+#define HDMI_LINK_I2S_CH_ST_SH_0      (HDMI_ADDR_OFFSET + 0x0004003C)
+#define HDMI_LINK_I2S_CH_ST_SH_1      (HDMI_ADDR_OFFSET + 0x00040040)
+#define HDMI_LINK_I2S_CH_ST_SH_2      (HDMI_ADDR_OFFSET + 0x00040044)
+#define HDMI_LINK_I2S_CH_ST_SH_3      (HDMI_ADDR_OFFSET + 0x00040048)
+#define HDMI_LINK_I2S_CH_ST_SH_4      (HDMI_ADDR_OFFSET + 0x0004004C)
+#define HDMI_LINK_I2S_VD_DATA         (HDMI_ADDR_OFFSET + 0x00040050)
+#define HDMI_LINK_I2S_MUX_CH          (HDMI_ADDR_OFFSET + 0x00040054)
+#define HDMI_LINK_I2S_MUX_CUV         (HDMI_ADDR_OFFSET + 0x00040058)
+#define HDMI_LINK_I2S_CH0_L_0         (HDMI_ADDR_OFFSET + 0x00040064)
+#define HDMI_LINK_I2S_CH0_L_1         (HDMI_ADDR_OFFSET + 0x00040068)
+#define HDMI_LINK_I2S_CH0_L_2         (HDMI_ADDR_OFFSET + 0x0004006C)
+#define HDMI_LINK_I2S_CH0_R_0         (HDMI_ADDR_OFFSET + 0x00040074)
+#define HDMI_LINK_I2S_CH0_R_1         (HDMI_ADDR_OFFSET + 0x00040078)
+#define HDMI_LINK_I2S_CH0_R_2         (HDMI_ADDR_OFFSET + 0x0004007C)
+#define HDMI_LINK_I2S_CH0_R_3         (HDMI_ADDR_OFFSET + 0x00040080)
+#define HDMI_LINK_I2S_CH1_L_0         (HDMI_ADDR_OFFSET + 0x00040084)
+#define HDMI_LINK_I2S_CH1_L_1         (HDMI_ADDR_OFFSET + 0x00040088)
+#define HDMI_LINK_I2S_CH1_L_2         (HDMI_ADDR_OFFSET + 0x0004008C)
+#define HDMI_LINK_I2S_CH1_L_3         (HDMI_ADDR_OFFSET + 0x00040090)
+#define HDMI_LINK_I2S_CH1_R_0         (HDMI_ADDR_OFFSET + 0x00040094)
+#define HDMI_LINK_I2S_CH1_R_1         (HDMI_ADDR_OFFSET + 0x00040098)
+#define HDMI_LINK_I2S_CH1_R_2         (HDMI_ADDR_OFFSET + 0x0004009C)
+#define HDMI_LINK_I2S_CH1_R_3         (HDMI_ADDR_OFFSET + 0x000400A0)
+#define HDMI_LINK_I2S_CH2_L_0         (HDMI_ADDR_OFFSET + 0x000400A4)
+#define HDMI_LINK_I2S_CH2_L_1         (HDMI_ADDR_OFFSET + 0x000400A8)
+#define HDMI_LINK_I2S_CH2_L_2         (HDMI_ADDR_OFFSET + 0x000400AC)
+#define HDMI_LINK_I2S_CH2_L_3         (HDMI_ADDR_OFFSET + 0x000400B0)
+#define HDMI_LINK_I2S_CH2_R_0         (HDMI_ADDR_OFFSET + 0x000400B4)
+#define HDMI_LINK_I2S_CH2_R_1         (HDMI_ADDR_OFFSET + 0x000400B8)
+#define HDMI_LINK_I2S_CH2_R_2         (HDMI_ADDR_OFFSET + 0x000400BC)
+#define HDMI_LINK_I2S_CH2_R_3         (HDMI_ADDR_OFFSET + 0x000400C0)
+#define HDMI_LINK_I2S_CH3_L_0         (HDMI_ADDR_OFFSET + 0x000400C4)
+#define HDMI_LINK_I2S_CH3_L_1         (HDMI_ADDR_OFFSET + 0x000400C8)
+#define HDMI_LINK_I2S_CH3_L_2         (HDMI_ADDR_OFFSET + 0x000400CC)
+#define HDMI_LINK_I2S_CH3_R_0         (HDMI_ADDR_OFFSET + 0x000400D0)
+#define HDMI_LINK_I2S_CH3_R_1         (HDMI_ADDR_OFFSET + 0x000400D4)
+#define HDMI_LINK_I2S_CH3_R_2         (HDMI_ADDR_OFFSET + 0x000400D8)
+#define HDMI_LINK_I2S_CUV_L_R         (HDMI_ADDR_OFFSET + 0x000400DC)
+
+#define HDMI_CEC_TX_STATUS_0         (OTHER_ADDR_OFFSET + 0x00000000)
+#define HDMI_CEC_TX_STATUS_1         (OTHER_ADDR_OFFSET + 0x00000004)
+#define HDMI_CEC_RX_STATUS_0         (OTHER_ADDR_OFFSET + 0x00000008)
+#define HDMI_CEC_RX_STATUS_1         (OTHER_ADDR_OFFSET + 0x0000000C)
+#define HDMI_CEC_INTR_MASK           (OTHER_ADDR_OFFSET + 0x00000010)
+#define HDMI_CEC_INTR_CLEAR          (OTHER_ADDR_OFFSET + 0x00000014)
+#define HDMI_CEC_LOGIC_ADDR          (OTHER_ADDR_OFFSET + 0x00000020)
+#define HDMI_CEC_DIVISOR_0           (OTHER_ADDR_OFFSET + 0x00000030)
+#define HDMI_CEC_DIVISOR_1           (OTHER_ADDR_OFFSET + 0x00000034)
+#define HDMI_CEC_DIVISOR_2           (OTHER_ADDR_OFFSET + 0x00000038)
+#define HDMI_CEC_DIVISOR_3           (OTHER_ADDR_OFFSET + 0x0000003C)
+#define HDMI_CEC_TX_CTRL             (OTHER_ADDR_OFFSET + 0x00000040)
+#define HDMI_CEC_TX_BYTE_NUM         (OTHER_ADDR_OFFSET + 0x00000044)
+#define HDMI_CEC_TX_STATUS_2         (OTHER_ADDR_OFFSET + 0x00000060)
+#define HDMI_CEC_TX_STATUS_3         (OTHER_ADDR_OFFSET + 0x00000064)
+#define HDMI_CEC_TX_BUFFER_x         (OTHER_ADDR_OFFSET + 0x00000080)
+#define HDMI_CEC_TX_BUFFER00         (OTHER_ADDR_OFFSET + 0x00000080)
+#define HDMI_CEC_RX_CTRL             (OTHER_ADDR_OFFSET + 0x000000C0)
+#define HDMI_CEC_RX_STATUS_2         (OTHER_ADDR_OFFSET + 0x000000E0)
+#define HDMI_CEC_RX_STATUS_3         (OTHER_ADDR_OFFSET + 0x000000E4)
+#define HDMI_CEC_RX_BUFFER_x         (OTHER_ADDR_OFFSET + 0x00000100)
+#define HDMI_CEC_FILTER_CTRL         (OTHER_ADDR_OFFSET + 0x00000180)
+#define HDMI_CEC_FILTER_TH           (OTHER_ADDR_OFFSET + 0x00000184)
+
+#ifdef CONFIG_MACH_S5P6818
+#define HDMI_PHY_OFFSET             \
+	(PHY_BASEADDR_HDMI_PHY_MODULE - PHY_BASEADDR_HDMI_MODULE)
+#else
+#define HDMI_PHY_OFFSET			0x400
+#endif
+
+#define HDMI_PHY_REG00 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000000)
+#define HDMI_PHY_REG04 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000004)
+#define HDMI_PHY_REG08 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000008)
+#define HDMI_PHY_REG0C (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x0000000C)
+#define HDMI_PHY_REG10 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000010)
+#define HDMI_PHY_REG14 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000014)
+#define HDMI_PHY_REG18 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000018)
+#define HDMI_PHY_REG1C (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x0000001C)
+#define HDMI_PHY_REG20 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000020)
+#define HDMI_PHY_REG24 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000024)
+#define HDMI_PHY_REG28 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000028)
+#define HDMI_PHY_REG2C (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x0000002C)
+#define HDMI_PHY_REG30 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000030)
+#define HDMI_PHY_REG34 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000034)
+#define HDMI_PHY_REG38 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000038)
+#define HDMI_PHY_REG3C (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x0000003C)
+#define HDMI_PHY_REG40 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000040)
+#define HDMI_PHY_REG44 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000044)
+#define HDMI_PHY_REG48 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000048)
+#define HDMI_PHY_REG4C (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x0000004C)
+#define HDMI_PHY_REG50 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000050)
+#define HDMI_PHY_REG54 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000054)
+#define HDMI_PHY_REG58 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000058)
+#define HDMI_PHY_REG5C (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x0000005C)
+#define HDMI_PHY_REG60 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000060)
+#define HDMI_PHY_REG64 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000064)
+#define HDMI_PHY_REG68 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000068)
+#define HDMI_PHY_REG6C (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x0000006C)
+#define HDMI_PHY_REG70 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000070)
+#define HDMI_PHY_REG74 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000074)
+#define HDMI_PHY_REG78 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000078)
+#define HDMI_PHY_REG7C (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x0000007C)
+#define HDMI_PHY_REG80 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000080)
+#define HDMI_PHY_REG84 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000084)
+#define HDMI_PHY_REG88 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000088)
+#define HDMI_PHY_REG8C (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x0000008C)
+#define HDMI_PHY_REG90 (OTHER_ADDR_OFFSET + HDMI_PHY_OFFSET + 0x00000090)
+
+enum hdmi_reset {
+	i_nRST = 0,
+	i_nRST_VIDEO = 1,
+	i_nRST_SPDIF = 2,
+	i_nRST_TMDS = 3,
+	i_nRST_PHY = 4,
+};
+
+u32 nx_hdmi_get_reg(u32 module_index, u32 offset);
+void nx_hdmi_set_reg(u32 module_index, u32 offset, u32 regvalue);
+
+void nx_hdmi_set_base_address(u32 module_index, void *base_address);
+void *nx_hdmi_get_base_address(u32 module_index);
+u32 nx_hdmi_get_physical_address(u32 module_index);
+
+#endif
diff --git a/drivers/video/nexell/soc/s5pxx18_soc_lvds.c b/drivers/video/nexell/soc/s5pxx18_soc_lvds.c
new file mode 100644
index 0000000..18c101b
--- /dev/null
+++ b/drivers/video/nexell/soc/s5pxx18_soc_lvds.c
@@ -0,0 +1,278 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2016  Nexell Co., Ltd.
+ *
+ * Author: junghyun, kim <jhkim@nexell.co.kr>
+ */
+
+#include <linux/types.h>
+#include <linux/io.h>
+
+#include "s5pxx18_soc_disptop.h"
+#include "s5pxx18_soc_lvds.h"
+
+#ifndef pow
+static inline unsigned int pow(int a, int b)
+{
+	if (b == 0)
+		return 1;
+	else
+		return a * pow(a, b - 1);
+}
+#endif
+
+static struct nx_lvds_register_set *__g_pregister[NUMBER_OF_LVDS_MODULE];
+
+int nx_lvds_initialize(void)
+{
+	static int binit;
+	u32 i;
+
+	if (binit == 0) {
+		for (i = 0; i < NUMBER_OF_LVDS_MODULE; i++)
+			__g_pregister[i] = NULL;
+		binit = 1;
+	}
+
+	return 1;
+}
+
+u32 nx_lvds_get_number_of_module(void)
+{
+	return NUMBER_OF_LVDS_MODULE;
+}
+
+u32 nx_lvds_get_size_of_register_set(void)
+{
+	return sizeof(struct nx_lvds_register_set);
+}
+
+void nx_lvds_set_base_address(u32 module_index, void *base_address)
+{
+	__g_pregister[module_index] =
+	    (struct nx_lvds_register_set *)base_address;
+}
+
+void *nx_lvds_get_base_address(u32 module_index)
+{
+	return (void *)__g_pregister[module_index];
+}
+
+u32 nx_lvds_get_physical_address(u32 module_index)
+{
+	const u32 physical_addr[] = PHY_BASEADDR_LVDS_LIST;
+
+	return physical_addr[module_index];
+}
+
+int nx_lvds_open_module(u32 module_index)
+{
+	return true;
+}
+
+int nx_lvds_close_module(u32 module_index)
+{
+	return true;
+}
+
+int nx_lvds_check_busy(u32 module_index)
+{
+	return false;
+}
+
+void nx_lvds_set_lvdsctrl0(u32 module_index, u32 regvalue)
+{
+	register struct nx_lvds_register_set *pregister;
+
+	pregister = __g_pregister[module_index];
+	writel(regvalue, &pregister->lvdsctrl0);
+}
+
+void nx_lvds_set_lvdsctrl1(u32 module_index, u32 regvalue)
+{
+	register struct nx_lvds_register_set *pregister;
+
+	pregister = __g_pregister[module_index];
+	writel(regvalue, &pregister->lvdsctrl1);
+}
+
+void nx_lvds_set_lvdsctrl2(u32 module_index, u32 regvalue)
+{
+	register struct nx_lvds_register_set *pregister;
+
+	pregister = __g_pregister[module_index];
+	writel(regvalue, &pregister->lvdsctrl2);
+}
+
+void nx_lvds_set_lvdsctrl3(u32 module_index, u32 regvalue)
+{
+	register struct nx_lvds_register_set *pregister;
+
+	pregister = __g_pregister[module_index];
+	writel(regvalue, &pregister->lvdsctrl3);
+}
+
+void nx_lvds_set_lvdsctrl4(u32 module_index, u32 regvalue)
+{
+	register struct nx_lvds_register_set *pregister;
+
+	pregister = __g_pregister[module_index];
+	writel(regvalue, &pregister->lvdsctrl4);
+}
+
+void nx_lvds_set_lvdstmode0(u32 module_index, u32 regvalue)
+{
+	register struct nx_lvds_register_set *pregister;
+
+	pregister = __g_pregister[module_index];
+	writel(regvalue, &pregister->lvdstmode0);
+}
+
+void nx_lvds_set_lvdsloc0(u32 module_index, u32 regvalue)
+{
+	register struct nx_lvds_register_set *pregister;
+
+	pregister = __g_pregister[module_index];
+	writel(regvalue, &pregister->lvdsloc0);
+}
+
+void nx_lvds_set_lvdsloc1(u32 module_index, u32 regvalue)
+{
+	register struct nx_lvds_register_set *pregister;
+
+	pregister = __g_pregister[module_index];
+	writel(regvalue, &pregister->lvdsloc1);
+}
+
+void nx_lvds_set_lvdsloc2(u32 module_index, u32 regvalue)
+{
+	register struct nx_lvds_register_set *pregister;
+
+	pregister = __g_pregister[module_index];
+	writel(regvalue, &pregister->lvdsloc2);
+}
+
+void nx_lvds_set_lvdsloc3(u32 module_index, u32 regvalue)
+{
+	register struct nx_lvds_register_set *pregister;
+
+	pregister = __g_pregister[module_index];
+	writel(regvalue, &pregister->lvdsloc3);
+}
+
+void nx_lvds_set_lvdsloc4(u32 module_index, u32 regvalue)
+{
+	register struct nx_lvds_register_set *pregister;
+
+	pregister = __g_pregister[module_index];
+	writel(regvalue, &pregister->lvdsloc4);
+}
+
+void nx_lvds_set_lvdsloc5(u32 module_index, u32 regvalue)
+{
+	register struct nx_lvds_register_set *pregister;
+
+	pregister = __g_pregister[module_index];
+	writel(regvalue, &pregister->lvdsloc5);
+}
+
+void nx_lvds_set_lvdsloc6(u32 module_index, u32 regvalue)
+{
+	register struct nx_lvds_register_set *pregister;
+
+	pregister = __g_pregister[module_index];
+	writel(regvalue, &pregister->lvdsloc6);
+}
+
+void nx_lvds_set_lvdslocmask0(u32 module_index, u32 regvalue)
+{
+	register struct nx_lvds_register_set *pregister;
+
+	pregister = __g_pregister[module_index];
+	writel(regvalue, &pregister->lvdslocmask0);
+}
+
+void nx_lvds_set_lvdslocmask1(u32 module_index, u32 regvalue)
+{
+	register struct nx_lvds_register_set *pregister;
+
+	pregister = __g_pregister[module_index];
+	writel(regvalue, &pregister->lvdslocmask1);
+}
+
+void nx_lvds_set_lvdslocpol0(u32 module_index, u32 regvalue)
+{
+	register struct nx_lvds_register_set *pregister;
+
+	pregister = __g_pregister[module_index];
+	writel(regvalue, &pregister->lvdslocpol0);
+}
+
+void nx_lvds_set_lvdslocpol1(u32 module_index, u32 regvalue)
+{
+	register struct nx_lvds_register_set *pregister;
+
+	pregister = __g_pregister[module_index];
+	writel(regvalue, &pregister->lvdslocpol1);
+}
+
+void nx_lvds_set_lvdsdummy(u32 module_index, u32 regvalue)
+{
+	register struct nx_lvds_register_set *pregister;
+	u32 oldvalue;
+
+	pregister = __g_pregister[module_index];
+	oldvalue = readl(&pregister->lvdsctrl1) & 0x00ffffff;
+	writel(oldvalue | ((regvalue & 0xff) << 24), &pregister->lvdsctrl1);
+}
+
+u32 nx_lvds_get_lvdsdummy(u32 module_index)
+{
+	register struct nx_lvds_register_set *pregister;
+	u32 oldvalue;
+
+	pregister = __g_pregister[module_index];
+	oldvalue = readl(&pregister->lvdsctrl1);
+	oldvalue = oldvalue >> 24;
+	return oldvalue;
+}
+
+u32 nx_lvds_get_lvdsctrl0(u32 module_index)
+{
+	register struct nx_lvds_register_set *pregister;
+
+	pregister = __g_pregister[module_index];
+	return (u32)readl(&pregister->lvdsctrl0);
+}
+
+u32 nx_lvds_get_lvdsctrl1(u32 module_index)
+{
+	register struct nx_lvds_register_set *pregister;
+
+	pregister = __g_pregister[module_index];
+	return (u32)readl(&pregister->lvdsctrl1);
+}
+
+u32 nx_lvds_get_lvdsctrl2(u32 module_index)
+{
+	register struct nx_lvds_register_set *pregister;
+
+	pregister = __g_pregister[module_index];
+	return (u32)readl(&pregister->lvdsctrl2);
+}
+
+u32 nx_lvds_get_lvdsctrl3(u32 module_index)
+{
+	register struct nx_lvds_register_set *pregister;
+
+	pregister = __g_pregister[module_index];
+	return (u32)readl(&pregister->lvdsctrl3);
+}
+
+u32 nx_lvds_get_lvdsctrl4(u32 module_index)
+{
+	register struct nx_lvds_register_set *pregister;
+
+	pregister = __g_pregister[module_index];
+	return (u32)readl(&pregister->lvdsctrl4);
+}
diff --git a/drivers/video/nexell/soc/s5pxx18_soc_lvds.h b/drivers/video/nexell/soc/s5pxx18_soc_lvds.h
new file mode 100644
index 0000000..08f8e5c
--- /dev/null
+++ b/drivers/video/nexell/soc/s5pxx18_soc_lvds.h
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: GPL-2.0+
+ *
+ * Copyright (C) 2016  Nexell Co., Ltd.
+ *
+ * Author: junghyun, kim <jhkim@nexell.co.kr>
+ */
+
+#ifndef _S5PXX18_SOC_LVDS_H_
+#define _S5PXX18_SOC_LVDS_H_
+
+/*
+ * refter to s5pxx18_soc_disptop.h
+ *
+ * #define NUMBER_OF_LVDS_MODULE 1
+ * #define PHY_BASEADDR_LVDS_MODULE	0xC010A000
+ */
+#define	PHY_BASEADDR_LVDS_LIST	\
+		{ PHY_BASEADDR_LVDS_MODULE }
+
+struct nx_lvds_register_set {
+	u32 lvdsctrl0;
+	u32 lvdsctrl1;
+	u32 lvdsctrl2;
+	u32 lvdsctrl3;
+	u32 lvdsctrl4;
+	u32 _reserved0[3];
+	u32 lvdsloc0;
+	u32 lvdsloc1;
+	u32 lvdsloc2;
+	u32 lvdsloc3;
+	u32 lvdsloc4;
+	u32 lvdsloc5;
+	u32 lvdsloc6;
+	u32 _reserved1;
+	u32 lvdslocmask0;
+	u32 lvdslocmask1;
+	u32 lvdslocpol0;
+	u32 lvdslocpol1;
+	u32 lvdstmode0;
+	u32 lvdstmode1;
+	u32 _reserved2[2];
+};
+
+int nx_lvds_initialize(void);
+u32 nx_lvds_get_number_of_module(void);
+u32 nx_lvds_get_size_of_register_set(void);
+void nx_lvds_set_base_address(u32 module_index, void *base_address);
+void *nx_lvds_get_base_address(u32 module_index);
+u32 nx_lvds_get_physical_address(u32 module_index);
+int nx_lvds_open_module(u32 module_index);
+int nx_lvds_close_module(u32 module_index);
+int nx_lvds_check_busy(u32 module_index);
+
+void nx_lvds_set_lvdsctrl0(u32 module_index, u32 regvalue);
+void nx_lvds_set_lvdsctrl1(u32 module_index, u32 regvalue);
+void nx_lvds_set_lvdsctrl2(u32 module_index, u32 regvalue);
+void nx_lvds_set_lvdsctrl3(u32 module_index, u32 regvalue);
+void nx_lvds_set_lvdsctrl4(u32 module_index, u32 regvalue);
+u32 nx_lvds_get_lvdsctrl0(u32 module_index);
+u32 nx_lvds_get_lvdsctrl1(u32 module_index);
+u32 nx_lvds_get_lvdsctrl2(u32 module_index);
+u32 nx_lvds_get_lvdsctrl3(u32 module_index);
+u32 nx_lvds_get_lvdsctrl4(u32 module_index);
+
+void nx_lvds_set_lvdstmode0(u32 module_index, u32 regvalue);
+void nx_lvds_set_lvdsloc0(u32 module_index, u32 regvalue);
+void nx_lvds_set_lvdsloc1(u32 module_index, u32 regvalue);
+void nx_lvds_set_lvdsloc2(u32 module_index, u32 regvalue);
+void nx_lvds_set_lvdsloc3(u32 module_index, u32 regvalue);
+void nx_lvds_set_lvdsloc4(u32 module_index, u32 regvalue);
+void nx_lvds_set_lvdsloc5(u32 module_index, u32 regvalue);
+void nx_lvds_set_lvdsloc6(u32 module_index, u32 regvalue);
+void nx_lvds_set_lvdslocmask0(u32 module_index, u32 regvalue);
+void nx_lvds_set_lvdslocmask1(u32 module_index, u32 regvalue);
+void nx_lvds_set_lvdslocpol0(u32 module_index, u32 regvalue);
+void nx_lvds_set_lvdslocpol1(u32 module_index, u32 regvalue);
+
+void nx_lvds_set_lvdslocpol1(u32 module_index, u32 regvalue);
+
+void nx_lvds_set_lvdsdummy(u32 module_index, u32 regvalue);
+u32 nx_lvds_get_lvdsdummy(u32 module_index);
+
+#endif
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [RFC PATCH v2 10/13] video: add nexell video driver (soc: dpc, makefile)
  2020-03-28  9:43 [RFC PATCH v2 00/13] arm: add support for SoC S5P4418 Stefan Bosch
                   ` (8 preceding siblings ...)
  2020-03-28  9:43 ` [RFC PATCH v2 09/13] video: add nexell video driver (soc: lvds, hdmi) Stefan Bosch
@ 2020-03-28  9:43 ` Stefan Bosch
  2020-03-28  9:43 ` [RFC PATCH v2 11/13] video: add nexell video driver (display/video driver) Stefan Bosch
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 21+ messages in thread
From: Stefan Bosch @ 2020-03-28  9:43 UTC (permalink / raw)
  To: u-boot

Low level functions for DPC (Display Controller) and Makefile for all
nexell video low level functions.

Signed-off-by: Stefan Bosch <stefan_b@posteo.net>
---

Changes in v2: None

 drivers/video/nexell/soc/Makefile          |   11 +
 drivers/video/nexell/soc/s5pxx18_soc_dpc.c | 1569 ++++++++++++++++++++++++++++
 drivers/video/nexell/soc/s5pxx18_soc_dpc.h |  444 ++++++++
 3 files changed, 2024 insertions(+)
 create mode 100644 drivers/video/nexell/soc/Makefile
 create mode 100644 drivers/video/nexell/soc/s5pxx18_soc_dpc.c
 create mode 100644 drivers/video/nexell/soc/s5pxx18_soc_dpc.h

diff --git a/drivers/video/nexell/soc/Makefile b/drivers/video/nexell/soc/Makefile
new file mode 100644
index 0000000..a3036e5
--- /dev/null
+++ b/drivers/video/nexell/soc/Makefile
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2016 Nexell
+# Junghyun, kim<jhkim@nexell.co.kr>
+
+obj-$(CONFIG_VIDEO_NX) += s5pxx18_soc_dpc.o s5pxx18_soc_mlc.o \
+			  s5pxx18_soc_disptop.o s5pxx18_soc_disptop_clk.o
+
+obj-$(CONFIG_VIDEO_NX_LVDS) += s5pxx18_soc_lvds.o
+obj-$(CONFIG_VIDEO_NX_MIPI) += s5pxx18_soc_mipi.o
+obj-$(CONFIG_VIDEO_NX_HDMI) += s5pxx18_soc_hdmi.o
diff --git a/drivers/video/nexell/soc/s5pxx18_soc_dpc.c b/drivers/video/nexell/soc/s5pxx18_soc_dpc.c
new file mode 100644
index 0000000..fc15d6b
--- /dev/null
+++ b/drivers/video/nexell/soc/s5pxx18_soc_dpc.c
@@ -0,0 +1,1569 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2016  Nexell Co., Ltd.
+ *
+ * Author: junghyun, kim <jhkim@nexell.co.kr>
+ */
+
+#include <linux/types.h>
+#include <linux/io.h>
+
+#include "s5pxx18_soc_dpc.h"
+
+static struct {
+	struct nx_dpc_register_set *pregister;
+} __g_module_variables[NUMBER_OF_DPC_MODULE] = { { NULL,},};
+
+int nx_dpc_initialize(void)
+{
+	static int binit;
+	u32 i;
+
+	if (binit == 0) {
+		for (i = 0; i < NUMBER_OF_DPC_MODULE; i++)
+			__g_module_variables[i].pregister = NULL;
+		binit = 1;
+	}
+	return 1;
+}
+
+u32 nx_dpc_get_number_of_module(void)
+{
+	return NUMBER_OF_DPC_MODULE;
+}
+
+u32 nx_dpc_get_physical_address(u32 module_index)
+{
+	const u32 physical_addr[] = PHY_BASEADDR_DPC_LIST;
+
+	return physical_addr[module_index];
+}
+
+void nx_dpc_set_base_address(u32 module_index, void *base_address)
+{
+	__g_module_variables[module_index].pregister =
+	    (struct nx_dpc_register_set *)base_address;
+}
+
+void *nx_dpc_get_base_address(u32 module_index)
+{
+	return (void *)__g_module_variables[module_index].pregister;
+}
+
+void nx_dpc_set_interrupt_enable(u32 module_index, int32_t int_num, int enable)
+{
+	const u32 intenb_pos = 11;
+	const u32 intenb_mask = 1ul << intenb_pos;
+	const u32 intpend_pos = 10;
+	const u32 intpend_mask = 1ul << intpend_pos;
+
+	register u32 regvalue;
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	regvalue = pregister->dpcctrl0;
+	regvalue &= ~(intenb_mask | intpend_mask);
+	regvalue |= (u32)enable << intenb_pos;
+
+	writel(regvalue, &pregister->dpcctrl0);
+}
+
+int nx_dpc_get_interrupt_enable(u32 module_index, int32_t int_num)
+{
+	const u32 intenb_pos = 11;
+	const u32 intenb_mask = 1ul << intenb_pos;
+
+	return (int)((__g_module_variables[module_index].pregister->dpcctrl0 &
+		      intenb_mask) >> intenb_pos);
+}
+
+void nx_dpc_set_interrupt_enable32(u32 module_index, u32 enable_flag)
+{
+	const u32 intenb_pos = 11;
+	const u32 intenb_mask = 1 << intenb_pos;
+	const u32 intpend_pos = 10;
+	const u32 intpend_mask = 1 << intpend_pos;
+
+	register struct nx_dpc_register_set *pregister;
+	register u32 read_value;
+
+	pregister = __g_module_variables[module_index].pregister;
+	read_value = pregister->dpcctrl0 & ~(intpend_mask | intenb_mask);
+
+	writel((u32)(read_value | (enable_flag & 0x01) << intenb_pos),
+	       &pregister->dpcctrl0);
+}
+
+u32 nx_dpc_get_interrupt_enable32(u32 module_index)
+{
+	const u32 intenb_pos = 11;
+	const u32 intenb_mask = 1 << intenb_pos;
+
+	return (u32)((__g_module_variables[module_index].pregister->dpcctrl0 &
+		       intenb_mask) >> intenb_pos);
+}
+
+int nx_dpc_get_interrupt_pending(u32 module_index, int32_t int_num)
+{
+	const u32 intpend_pos = 10;
+	const u32 intpend_mask = 1ul << intpend_pos;
+
+	return (int)((__g_module_variables[module_index].pregister->dpcctrl0 &
+		      intpend_mask) >> intpend_pos);
+}
+
+u32 nx_dpc_get_interrupt_pending32(u32 module_index)
+{
+	const u32 intpend_pos = 10;
+	const u32 intpend_mask = 1 << intpend_pos;
+
+	return (u32)((__g_module_variables[module_index].pregister->dpcctrl0 &
+		       intpend_mask) >> intpend_pos);
+}
+
+void nx_dpc_clear_interrupt_pending(u32 module_index, int32_t int_num)
+{
+	const u32 intpend_pos = 10;
+	register struct nx_dpc_register_set *pregister;
+	register u32 regvalue;
+
+	pregister = __g_module_variables[module_index].pregister;
+	regvalue = pregister->dpcctrl0;
+	regvalue |= 1ul << intpend_pos;
+
+	writel(regvalue, &pregister->dpcctrl0);
+}
+
+void nx_dpc_clear_interrupt_pending32(u32 module_index, u32 pending_flag)
+{
+	const u32 intpend_pos = 10;
+	const u32 intpend_mask = 1 << intpend_pos;
+	register struct nx_dpc_register_set *pregister;
+	register u32 read_value;
+
+	pregister = __g_module_variables[module_index].pregister;
+	read_value = pregister->dpcctrl0 & ~intpend_mask;
+
+	writel((u32)(read_value | ((pending_flag & 0x01) << intpend_pos)),
+	       &pregister->dpcctrl0);
+}
+
+void nx_dpc_set_interrupt_enable_all(u32 module_index, int enable)
+{
+	const u32 intenb_pos = 11;
+	const u32 intenb_mask = 1ul << intenb_pos;
+	const u32 intpend_pos = 10;
+	const u32 intpend_mask = 1ul << intpend_pos;
+	register u32 regvalue;
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	regvalue = pregister->dpcctrl0;
+	regvalue &= ~(intenb_mask | intpend_mask);
+	regvalue |= (u32)enable << intenb_pos;
+
+	writel(regvalue, &pregister->dpcctrl0);
+}
+
+int nx_dpc_get_interrupt_enable_all(u32 module_index)
+{
+	const u32 intenb_pos = 11;
+	const u32 intenb_mask = 1ul << intenb_pos;
+
+	return (int)((__g_module_variables[module_index].pregister->dpcctrl0 &
+		      intenb_mask) >> intenb_pos);
+}
+
+int nx_dpc_get_interrupt_pending_all(u32 module_index)
+{
+	const u32 intpend_pos = 10;
+	const u32 intpend_mask = 1ul << intpend_pos;
+
+	return (int)((__g_module_variables[module_index].pregister->dpcctrl0 &
+		      intpend_mask) >> intpend_pos);
+}
+
+void nx_dpc_clear_interrupt_pending_all(u32 module_index)
+{
+	const u32 intpend_pos = 10;
+	register struct nx_dpc_register_set *pregister;
+	register u32 regvalue;
+
+	pregister = __g_module_variables[module_index].pregister;
+	regvalue = pregister->dpcctrl0;
+	regvalue |= 1ul << intpend_pos;
+
+	writel(regvalue, &pregister->dpcctrl0);
+}
+
+int32_t nx_dpc_get_interrupt_pending_number(u32 module_index)
+{
+	const u32 intenb_pos = 11;
+	const u32 intpend_pos = 10;
+	register struct nx_dpc_register_set *pregister;
+	register u32 pend;
+
+	pregister = __g_module_variables[module_index].pregister;
+	pend = ((pregister->dpcctrl0 >> intenb_pos) &&
+		(pregister->dpcctrl0 >> intpend_pos));
+
+	if (pend & 0x01)
+		return 0;
+
+	return -1;
+}
+
+void nx_dpc_set_clock_pclk_mode(u32 module_index, enum nx_pclkmode mode)
+{
+	const u32 pclkmode_pos = 3;
+	register u32 regvalue;
+	register struct nx_dpc_register_set *pregister;
+	u32 clkmode = 0;
+
+	pregister = __g_module_variables[module_index].pregister;
+	switch (mode) {
+	case nx_pclkmode_dynamic:
+		clkmode = 0;
+		break;
+	case nx_pclkmode_always:
+		clkmode = 1;
+		break;
+	default:
+		break;
+	}
+	regvalue = pregister->dpcclkenb;
+	regvalue &= ~(1ul << pclkmode_pos);
+	regvalue |= (clkmode & 0x01) << pclkmode_pos;
+
+	writel(regvalue, &pregister->dpcclkenb);
+}
+
+enum nx_pclkmode nx_dpc_get_clock_pclk_mode(u32 module_index)
+{
+	const u32 pclkmode_pos = 3;
+
+	if (__g_module_variables[module_index].pregister->dpcclkenb &
+	    (1ul << pclkmode_pos)) {
+		return nx_pclkmode_always;
+	}
+	return nx_pclkmode_dynamic;
+}
+
+void nx_dpc_set_clock_source(u32 module_index, u32 index, u32 clk_src)
+{
+	const u32 clksrcsel_pos = 2;
+	const u32 clksrcsel_mask = 0x07 << clksrcsel_pos;
+	register struct nx_dpc_register_set *pregister;
+	register u32 read_value;
+
+	pregister = __g_module_variables[module_index].pregister;
+	read_value = pregister->dpcclkgen[index][0];
+	read_value &= ~clksrcsel_mask;
+	read_value |= clk_src << clksrcsel_pos;
+
+	writel(read_value, &pregister->dpcclkgen[index][0]);
+}
+
+u32 nx_dpc_get_clock_source(u32 module_index, u32 index)
+{
+	const u32 clksrcsel_pos = 2;
+	const u32 clksrcsel_mask = 0x07 << clksrcsel_pos;
+
+	return (__g_module_variables[module_index]
+		.pregister->dpcclkgen[index][0] &
+		clksrcsel_mask) >> clksrcsel_pos;
+}
+
+void nx_dpc_set_clock_divisor(u32 module_index, u32 index, u32 divisor)
+{
+	const u32 clkdiv_pos = 5;
+	const u32 clkdiv_mask = ((1 << 8) - 1) << clkdiv_pos;
+	register struct nx_dpc_register_set *pregister;
+	register u32 read_value;
+
+	pregister = __g_module_variables[module_index].pregister;
+	read_value = pregister->dpcclkgen[index][0];
+	read_value &= ~clkdiv_mask;
+	read_value |= (divisor - 1) << clkdiv_pos;
+
+	writel(read_value, &pregister->dpcclkgen[index][0]);
+}
+
+u32 nx_dpc_get_clock_divisor(u32 module_index, u32 index)
+{
+	const u32 clkdiv_pos = 5;
+	const u32 clkdiv_mask = ((1 << 8) - 1) << clkdiv_pos;
+
+	return ((__g_module_variables[module_index]
+	       .pregister->dpcclkgen[index][0] &
+	       clkdiv_mask) >> clkdiv_pos) + 1;
+}
+
+void nx_dpc_set_clock_out_inv(u32 module_index, u32 index, int out_clk_inv)
+{
+	const u32 outclkinv_pos = 1;
+	const u32 outclkinv_mask = 1ul << outclkinv_pos;
+	register struct nx_dpc_register_set *pregister;
+	register u32 read_value;
+
+	pregister = __g_module_variables[module_index].pregister;
+	read_value = pregister->dpcclkgen[index][0];
+	read_value &= ~outclkinv_mask;
+	read_value |= out_clk_inv << outclkinv_pos;
+
+	writel(read_value, &pregister->dpcclkgen[index][0]);
+}
+
+int nx_dpc_get_clock_out_inv(u32 module_index, u32 index)
+{
+	const u32 outclkinv_pos = 1;
+	const u32 outclkinv_mask = 1ul << outclkinv_pos;
+
+	return (int)((__g_module_variables[module_index]
+		     .pregister->dpcclkgen[index][0] &
+		     outclkinv_mask) >> outclkinv_pos);
+}
+
+void nx_dpc_set_clock_out_select(u32 module_index, u32 index, int bbypass)
+{
+	const u32 outclksel_pos = 0;
+	const u32 outclksel_mask = 1ul << outclksel_pos;
+	register struct nx_dpc_register_set *pregister;
+	register u32 read_value;
+
+	pregister = __g_module_variables[module_index].pregister;
+	read_value = pregister->dpcclkgen[index][0];
+	read_value &= ~outclksel_mask;
+	if (bbypass == 0)
+		read_value |= outclksel_mask;
+
+	writel(read_value, &pregister->dpcclkgen[index][0]);
+}
+
+int nx_dpc_get_clock_out_select(u32 module_index, u32 index)
+{
+	const u32 outclksel_pos = 0;
+	const u32 outclksel_mask = 1ul << outclksel_pos;
+
+	if (__g_module_variables[module_index].pregister->dpcclkgen[index][0] &
+	    outclksel_mask) {
+		return 0;
+	} else {
+		return 1;
+	}
+}
+
+void nx_dpc_set_clock_polarity(u32 module_index, int bpolarity)
+{
+	const u32 clkpol_pos = 2;
+	const u32 clkpol_mask = 1ul << clkpol_pos;
+	register struct nx_dpc_register_set *pregister;
+	register u32 read_value;
+
+	pregister = __g_module_variables[module_index].pregister;
+	read_value = pregister->dpcctrl1;
+	read_value &= ~clkpol_mask;
+	if (bpolarity == 1)
+		read_value |= clkpol_mask;
+
+	writel(read_value, &pregister->dpcctrl1);
+}
+
+int nx_dpc_get_clock_polarity(u32 module_index)
+{
+	const u32 clkpol_pos = 2;
+	const u32 clkpol_mask = 1ul << clkpol_pos;
+
+	if (__g_module_variables[module_index].pregister->dpcctrl1 &
+	    clkpol_mask) {
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
+void nx_dpc_set_clock_out_enb(u32 module_index, u32 index, int out_clk_enb)
+{
+	const u32 outclkenb_pos = 15;
+	const u32 outclkenb_mask = 1ul << outclkenb_pos;
+	register struct nx_dpc_register_set *pregister;
+	register u32 read_value;
+
+	pregister = __g_module_variables[module_index].pregister;
+	read_value = pregister->dpcclkgen[index][0];
+	read_value &= ~outclkenb_mask;
+
+	if (out_clk_enb == 1)
+		read_value |= outclkenb_mask;
+
+	writel(read_value, &pregister->dpcclkgen[index][0]);
+}
+
+int nx_dpc_get_clock_out_enb(u32 module_index, u32 index)
+{
+	const u32 outclkenb_pos = 15;
+	const u32 outclkenb_mask = 1ul << outclkenb_pos;
+
+	if (__g_module_variables[module_index].pregister->dpcclkgen[index][0] &
+	    outclkenb_mask) {
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
+void nx_dpc_set_clock_out_delay(u32 module_index, u32 index, u32 delay)
+{
+	const u32 outclkdelay_pos = 0;
+	const u32 outclkdelay_mask = 0x1f << outclkdelay_pos;
+	register struct nx_dpc_register_set *pregister;
+	register u32 read_value;
+
+	pregister = __g_module_variables[module_index].pregister;
+	read_value = pregister->dpcclkgen[index][1];
+	read_value &= ~outclkdelay_mask;
+	read_value |= (u32)delay << outclkdelay_pos;
+
+	writel(read_value, &pregister->dpcclkgen[index][1]);
+}
+
+u32 nx_dpc_get_clock_out_delay(u32 module_index, u32 index)
+{
+	register struct nx_dpc_register_set *pregister;
+	const u32 outclkdelay_pos = 0;
+	const u32 outclkdelay_mask = 0x1f << outclkdelay_pos;
+
+	pregister = __g_module_variables[module_index].pregister;
+
+	return (u32)((pregister->dpcclkgen[index][1] & outclkdelay_mask) >>
+		     outclkdelay_pos);
+}
+
+void nx_dpc_set_clock_divisor_enable(u32 module_index, int enable)
+{
+	const u32 clkgenenb_pos = 2;
+	const u32 clkgenenb_mask = 1ul << clkgenenb_pos;
+	register struct nx_dpc_register_set *pregister;
+	register u32 read_value;
+
+	pregister = __g_module_variables[module_index].pregister;
+	read_value = pregister->dpcclkenb;
+	read_value &= ~clkgenenb_mask;
+	read_value |= (u32)enable << clkgenenb_pos;
+
+	writel(read_value, &pregister->dpcclkenb);
+}
+
+int nx_dpc_get_clock_divisor_enable(u32 module_index)
+{
+	const u32 clkgenenb_pos = 2;
+	const u32 clkgenenb_mask = 1ul << clkgenenb_pos;
+
+	return (int)((__g_module_variables[module_index].pregister->dpcclkenb &
+		     clkgenenb_mask) >> clkgenenb_pos);
+}
+
+void nx_dpc_set_dpc_enable(u32 module_index, int benb)
+{
+	const u32 intpend_pos = 10;
+	const u32 intpend_mask = 1ul << intpend_pos;
+	const u32 dpcenb_pos = 15;
+	const u32 dpcenb_mask = 1ul << dpcenb_pos;
+	register struct nx_dpc_register_set *pregister;
+	register u32 read_value;
+
+	pregister = __g_module_variables[module_index].pregister;
+	read_value = pregister->dpcctrl0;
+	read_value &= ~(intpend_mask | dpcenb_mask);
+	read_value |= (u32)benb << dpcenb_pos;
+
+	writel(read_value, &pregister->dpcctrl0);
+}
+
+int nx_dpc_get_dpc_enable(u32 module_index)
+{
+	const u32 dpcenb_pos = 15;
+	const u32 dpcenb_mask = 1ul << dpcenb_pos;
+
+	return (int)((__g_module_variables[module_index].pregister->dpcctrl0 &
+		      dpcenb_mask) >> dpcenb_pos);
+}
+
+void nx_dpc_set_delay(u32 module_index, u32 delay_rgb_pvd, u32 delay_hs_cp1,
+		      u32 delay_vs_fram, u32 delay_de_cp2)
+{
+	const u32 intpend_mask = 1u << 10;
+	const u32 delayrgb_pos = 4;
+	const u32 delayrgb_mask = 0xfu << delayrgb_pos;
+	register u32 temp;
+	const u32 delayde_pos = 0;
+	const u32 delayvs_pos = 8;
+	const u32 delayhs_pos = 0;
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	temp = pregister->dpcctrl0;
+	temp &= (u32)~(intpend_mask | delayrgb_mask);
+	temp = (u32)(temp | (delay_rgb_pvd << delayrgb_pos));
+
+	writel(temp, &pregister->dpcctrl0);
+
+	writel((u32)((delay_vs_fram << delayvs_pos) |
+		   (delay_hs_cp1 << delayhs_pos)), &pregister->dpcdelay0);
+
+	writel((u32)(delay_de_cp2 << delayde_pos), &pregister->dpcdelay1);
+}
+
+void nx_dpc_get_delay(u32 module_index, u32 *pdelayrgb_pvd, u32 *pdelayhs_cp1,
+		      u32 *pdelayvs_fram, u32 *pdelayde_cp2)
+{
+	const u32 delayrgb_pos = 4;
+	const u32 delayrgb_mask = 0xfu << delayrgb_pos;
+	const u32 delayde_pos = 0;
+	const u32 delayde_mask = 0x3fu << delayde_pos;
+	const u32 delayvs_pos = 8;
+	const u32 delayvs_mask = 0x3fu << delayvs_pos;
+	const u32 delayhs_pos = 0;
+	const u32 delayhs_mask = 0x3fu << delayhs_pos;
+	register u32 temp;
+
+	temp = __g_module_variables[module_index].pregister->dpcctrl0;
+	if (pdelayrgb_pvd)
+		*pdelayrgb_pvd = (u32)((temp & delayrgb_mask) >> delayrgb_pos);
+	temp = __g_module_variables[module_index].pregister->dpcdelay0;
+	if (pdelayhs_cp1)
+		*pdelayhs_cp1 = (u32)((temp & delayhs_mask) >> delayhs_pos);
+	if (pdelayvs_fram)
+		*pdelayvs_fram = (u32)((temp & delayvs_mask) >> delayvs_pos);
+	temp = __g_module_variables[module_index].pregister->dpcdelay1;
+	if (pdelayde_cp2)
+		*pdelayde_cp2 = (u32)((temp & delayde_mask) >> delayde_pos);
+}
+
+void nx_dpc_set_dither(u32 module_index, enum nx_dpc_dither dither_r,
+		       enum nx_dpc_dither dither_g, enum nx_dpc_dither dither_b)
+{
+	const u32 dither_mask = 0x3fu;
+	const u32 rdither_pos = 0;
+	const u32 gdither_pos = 2;
+	const u32 bdither_pos = 4;
+	register u32 temp;
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	temp = pregister->dpcctrl1;
+	temp &= (u32)~dither_mask;
+	temp = (u32)(temp |
+		     ((dither_b << bdither_pos) | (dither_g << gdither_pos) |
+		     (dither_r << rdither_pos)));
+
+	writel(temp, &pregister->dpcctrl1);
+}
+
+void nx_dpc_get_dither(u32 module_index, enum nx_dpc_dither *pditherr,
+		       enum nx_dpc_dither *pditherg,
+		       enum nx_dpc_dither *pditherb)
+{
+	const u32 rdither_pos = 0;
+	const u32 rdither_mask = 0x3u << rdither_pos;
+	const u32 gdither_pos = 2;
+	const u32 gdither_mask = 0x3u << gdither_pos;
+	const u32 bdither_pos = 4;
+	const u32 bdither_mask = 0x3u << bdither_pos;
+	register u32 temp;
+
+	temp = __g_module_variables[module_index].pregister->dpcctrl1;
+	if (pditherr)
+		*pditherr =
+		    (enum nx_dpc_dither)((temp & rdither_mask) >> rdither_pos);
+	if (pditherg)
+		*pditherg =
+		    (enum nx_dpc_dither)((temp & gdither_mask) >> gdither_pos);
+	if (pditherb)
+		*pditherb =
+		    (enum nx_dpc_dither)((temp & bdither_mask) >> bdither_pos);
+}
+
+void nx_dpc_set_mode(u32 module_index, enum nx_dpc_format format,
+		     int binterlace, int binvertfield, int brgbmode,
+		     int bswaprb, enum nx_dpc_ycorder ycorder, int bclipyc,
+		     int bembeddedsync, enum nx_dpc_padclk clock,
+		     int binvertclock, int bdualview)
+{
+	const u32 polfield_pos = 2;
+	const u32 seavenb_pos = 8;
+	const u32 scanmode_pos = 9;
+	const u32 intpend_pos = 10;
+	const u32 rgbmode_pos = 12;
+
+	const u32 dither_mask = 0x3f;
+	const u32 ycorder_pos = 6;
+	const u32 format_pos = 8;
+	const u32 ycrange_pos = 13;
+	const u32 swaprb_pos = 15;
+
+	const u32 padclksel_pos = 0;
+	const u32 padclksel_mask = 3u << padclksel_pos;
+	const u32 lcdtype_pos = 7;
+	const u32 lcdtype_mask = 3u << lcdtype_pos;
+	register struct nx_dpc_register_set *pregister;
+	register u32 temp;
+
+	pregister = __g_module_variables[module_index].pregister;
+	temp = pregister->dpcctrl0;
+	temp &= (u32)~(1u << intpend_pos);
+	if (binterlace)
+		temp |= (u32)(1u << scanmode_pos);
+	else
+		temp &= (u32)~(1u << scanmode_pos);
+	if (binvertfield)
+		temp |= (u32)(1u << polfield_pos);
+	else
+		temp &= (u32)~(1u << polfield_pos);
+	if (brgbmode)
+		temp |= (u32)(1u << rgbmode_pos);
+	else
+		temp &= (u32)~(1u << rgbmode_pos);
+	if (bembeddedsync)
+		temp |= (u32)(1u << seavenb_pos);
+	else
+		temp &= (u32)~(1u << seavenb_pos);
+
+	writel(temp, &pregister->dpcctrl0);
+	temp = pregister->dpcctrl1;
+	temp &= (u32)dither_mask;
+	temp = (u32)(temp | (ycorder << ycorder_pos));
+	if (format >= 16) {
+		register u32 temp1;
+
+		temp1 = pregister->dpcctrl2;
+		temp1 = temp1 | (1 << 4);
+		writel(temp1, &pregister->dpcctrl2);
+	} else {
+		register u32 temp1;
+
+		temp1 = pregister->dpcctrl2;
+		temp1 = temp1 & ~(1 << 4);
+		writel(temp1, &pregister->dpcctrl2);
+	}
+	temp = (u32)(temp | ((format & 0xf) << format_pos));
+	if (!bclipyc)
+		temp |= (u32)(1u << ycrange_pos);
+	if (bswaprb)
+		temp |= (u32)(1u << swaprb_pos);
+
+	writel(temp, &pregister->dpcctrl1);
+	temp = pregister->dpcctrl2;
+	temp &= (u32)~(padclksel_mask | lcdtype_mask);
+	temp = (u32)(temp | (clock << padclksel_pos));
+
+	writel(temp, &pregister->dpcctrl2);
+
+	nx_dpc_set_clock_out_inv(module_index, 0, binvertclock);
+	nx_dpc_set_clock_out_inv(module_index, 1, binvertclock);
+}
+
+void nx_dpc_get_mode(u32 module_index, enum nx_dpc_format *pformat,
+		     int *pbinterlace, int *pbinvertfield, int *pbrgbmode,
+		     int *pbswaprb, enum nx_dpc_ycorder *pycorder,
+		     int *pbclipyc, int *pbembeddedsync,
+		     enum nx_dpc_padclk *pclock, int *pbinvertclock,
+		     int *pbdualview)
+{
+	const u32 polfield = 1u << 2;
+	const u32 seavenb = 1u << 8;
+	const u32 scanmode = 1u << 9;
+	const u32 rgbmode = 1u << 12;
+
+	const u32 ycorder_pos = 6;
+	const u32 ycorder_mask = 0x3u << ycorder_pos;
+	const u32 format_pos = 8;
+	const u32 format_mask = 0xfu << format_pos;
+	const u32 ycrange = 1u << 13;
+	const u32 swaprb = 1u << 15;
+
+	const u32 padclksel_pos = 0;
+	const u32 padclksel_mask = 3u << padclksel_pos;
+	const u32 lcdtype_pos = 7;
+	const u32 lcdtype_mask = 3u << lcdtype_pos;
+	register u32 temp;
+
+	temp = __g_module_variables[module_index].pregister->dpcctrl0;
+	if (pbinterlace)
+		*pbinterlace = (temp & scanmode) ? 1 : 0;
+
+	if (pbinvertfield)
+		*pbinvertfield = (temp & polfield) ? 1 : 0;
+
+	if (pbrgbmode)
+		*pbrgbmode = (temp & rgbmode) ? 1 : 0;
+
+	if (pbembeddedsync)
+		*pbembeddedsync = (temp & seavenb) ? 1 : 0;
+
+	temp = __g_module_variables[module_index].pregister->dpcctrl1;
+
+	if (pycorder)
+		*pycorder =
+		    (enum nx_dpc_ycorder)((temp & ycorder_mask) >> ycorder_pos);
+
+	if (pformat)
+		*pformat =
+		    (enum nx_dpc_format)((temp & format_mask) >> format_pos);
+	if (pbclipyc)
+		*pbclipyc = (temp & ycrange) ? 0 : 1;
+	if (pbswaprb)
+		*pbswaprb = (temp & swaprb) ? 1 : 0;
+
+	temp = __g_module_variables[module_index].pregister->dpcctrl2;
+
+	if (pclock)
+		*pclock =
+		    (enum nx_dpc_padclk)((temp & padclksel_mask) >>
+					 padclksel_pos);
+
+	if (pbdualview)
+		*pbdualview = (2 == ((temp & lcdtype_mask) >> lcdtype_pos))
+		    ? 1 : 0;
+
+	if (pbinvertclock)
+		*pbinvertclock = nx_dpc_get_clock_out_inv(module_index, 1);
+}
+
+void nx_dpc_set_hsync(u32 module_index, u32 avwidth, u32 hsw, u32 hfp, u32 hbp,
+		      int binvhsync)
+{
+	const u32 intpend = 1u << 10;
+	const u32 polhsync = 1u << 0;
+	register u32 temp;
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+
+	writel((u32)(hsw + hbp + avwidth + hfp - 1), &pregister->dpchtotal);
+
+	writel((u32)(hsw - 1), &pregister->dpchswidth);
+
+	writel((u32)(hsw + hbp - 1), &pregister->dpchastart);
+
+	writel((u32)(hsw + hbp + avwidth - 1), &pregister->dpchaend);
+	temp = pregister->dpcctrl0;
+	temp &= ~intpend;
+	if (binvhsync)
+		temp |= (u32)polhsync;
+	else
+		temp &= (u32)~polhsync;
+
+	writel(temp, &pregister->dpcctrl0);
+}
+
+void nx_dpc_get_hsync(u32 module_index, u32 *pavwidth, u32 *phsw, u32 *phfp,
+		      u32 *phbp, int *pbinvhsync)
+{
+	const u32 polhsync = 1u << 0;
+	u32 htotal, hsw, hab, hae;
+	u32 avw, hfp, hbp;
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	htotal = (u32)pregister->dpchtotal + 1;
+	hsw = (u32)pregister->dpchswidth + 1;
+	hab = (u32)pregister->dpchastart + 1;
+	hae = (u32)pregister->dpchaend + 1;
+	hbp = hab - hsw;
+	avw = hae - hab;
+	hfp = htotal - hae;
+	if (pavwidth)
+		*pavwidth = avw;
+	if (phsw)
+		*phsw = hsw;
+	if (phfp)
+		*phfp = hfp;
+	if (phbp)
+		*phbp = hbp;
+	if (pbinvhsync)
+		*pbinvhsync = (pregister->dpcctrl0 & polhsync) ? 1 : 0;
+}
+
+void nx_dpc_set_vsync(u32 module_index, u32 avheight, u32 vsw, u32 vfp, u32 vbp,
+		      int binvvsync, u32 eavheight, u32 evsw, u32 evfp,
+		      u32 evbp)
+{
+	const u32 intpend = 1u << 10;
+	const u32 polvsync = 1u << 1;
+	register u32 temp;
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+
+	writel((u32)(vsw + vbp + avheight + vfp - 1), &pregister->dpcvtotal);
+
+	writel((u32)(vsw - 1), &pregister->dpcvswidth);
+
+	writel((u32)(vsw + vbp - 1), &pregister->dpcvastart);
+
+	writel((u32)(vsw + vbp + avheight - 1), &pregister->dpcvaend);
+
+	writel((u32)(evsw + evbp + eavheight + evfp - 1),
+	       &pregister->dpcevtotal);
+
+	writel((u32)(evsw - 1), &pregister->dpcevswidth);
+
+	writel((u32)(evsw + evbp - 1), &pregister->dpcevastart);
+
+	writel((u32)(evsw + evbp + eavheight - 1), &pregister->dpcevaend);
+	temp = pregister->dpcctrl0;
+	temp &= ~intpend;
+	if (binvvsync)
+		temp |= (u32)polvsync;
+	else
+		temp &= (u32)~polvsync;
+
+	writel(temp, &pregister->dpcctrl0);
+}
+
+void nx_dpc_get_vsync(u32 module_index, u32 *pavheight, u32 *pvsw, u32 *pvfp,
+		      u32 *pvbp, int *pbinvvsync, u32 *peavheight,
+		      u32 *pevsw, u32 *pevfp, u32 *pevbp)
+{
+	const u32 polvsync = 1u << 1;
+	u32 vtotal, vsw, vab, vae;
+	u32 avh, vfp, vbp;
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	vtotal = (u32)pregister->dpcvtotal + 1;
+	vsw = (u32)pregister->dpcvswidth + 1;
+	vab = (u32)pregister->dpcvastart + 1;
+	vae = (u32)pregister->dpcvaend + 1;
+	vbp = vab - vsw;
+	avh = vae - vab;
+	vfp = vtotal - vae;
+	if (pavheight)
+		*pavheight = avh;
+	if (pvsw)
+		*pvsw = vsw;
+	if (pvfp)
+		*pvfp = vfp;
+	if (pvbp)
+		*pvbp = vbp;
+	vtotal = (u32)pregister->dpcevtotal + 1;
+	vsw = (u32)pregister->dpcevswidth + 1;
+	vab = (u32)pregister->dpcevastart + 1;
+	vae = (u32)pregister->dpcevaend + 1;
+	vbp = vab - vsw;
+	avh = vae - vab;
+	vfp = vtotal - vae;
+	if (peavheight)
+		*peavheight = avh;
+	if (pevsw)
+		*pevsw = vsw;
+	if (pevfp)
+		*pevfp = vfp;
+	if (pevbp)
+		*pevbp = vbp;
+	if (pbinvvsync)
+		*pbinvvsync = (pregister->dpcctrl0 & polvsync) ? 1 : 0;
+}
+
+void nx_dpc_set_vsync_offset(u32 module_index, u32 vssoffset, u32 vseoffset,
+			     u32 evssoffset, u32 evseoffset)
+{
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+
+	writel((u32)vseoffset, &pregister->dpcvseoffset);
+
+	writel((u32)vssoffset, &pregister->dpcvssoffset);
+
+	writel((u32)evseoffset, &pregister->dpcevseoffset);
+
+	writel((u32)evssoffset, &pregister->dpcevssoffset);
+}
+
+void nx_dpc_get_vsync_offset(u32 module_index, u32 *pvssoffset,
+			     u32 *pvseoffset, u32 *pevssoffset,
+			     u32 *pevseoffset)
+{
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+
+	if (pvseoffset)
+		*pvseoffset = (u32)pregister->dpcvseoffset;
+
+	if (pvssoffset)
+		*pvssoffset = (u32)pregister->dpcvssoffset;
+
+	if (pevseoffset)
+		*pevseoffset = (u32)pregister->dpcevseoffset;
+
+	if (pevssoffset)
+		*pevssoffset = (u32)pregister->dpcevssoffset;
+}
+
+void nx_dpc_set_horizontal_up_scaler(u32 module_index, int benb,
+				     u32 sourcewidth, u32 destwidth)
+{
+	const u32 upscalel_pos = 8;
+	const u32 upscaleh_pos = 0;
+	const u32 upscaleh_mask = ((1 << 15) - 1) << upscaleh_pos;
+	const u32 upscalerenb_pos = 0;
+	register struct nx_dpc_register_set *pregister;
+	register u32 regvalue;
+	register u32 up_scale;
+
+	pregister = __g_module_variables[module_index].pregister;
+	up_scale = ((sourcewidth - 1) * (1 << 11)) / (destwidth - 1);
+	regvalue = 0;
+	regvalue |= (((u32)benb << upscalerenb_pos) |
+		     (up_scale & 0xff) << upscalel_pos);
+
+	writel(regvalue, &pregister->dpcupscalecon0);
+
+	writel((up_scale >> 0x08) & upscaleh_mask, &pregister->dpcupscalecon1);
+
+	writel(sourcewidth - 1, &pregister->dpcupscalecon2);
+}
+
+void nx_dpc_get_horizontal_up_scaler(u32 module_index, int *pbenb,
+				     u32 *psourcewidth, u32 *pdestwidth)
+{
+	const u32 upscalerenb_pos = 0;
+	const u32 upscalerenb_mask = 1u << upscalerenb_pos;
+	register struct nx_dpc_register_set *pregister;
+
+	u32 up_scale;
+	u32 destwidth, srcwidth;
+
+	pregister = __g_module_variables[module_index].pregister;
+	up_scale = ((u32)(pregister->dpcupscalecon1 & 0x7fff) << 8) |
+	    ((u32)(pregister->dpcupscalecon0 >> 8) & 0xff);
+	srcwidth = pregister->dpcupscalecon2;
+	destwidth = (srcwidth * (1 << 11)) / up_scale;
+	if (pbenb)
+		*pbenb = (pregister->dpcupscalecon0 & upscalerenb_mask);
+	if (psourcewidth)
+		*psourcewidth = srcwidth + 1;
+	if (pdestwidth)
+		*pdestwidth = destwidth + 1;
+}
+
+void nx_dpc_set_sync(u32 module_index, enum syncgenmode sync_gen_mode,
+		     u32 avwidth, u32 avheight, u32 hsw, u32 hfp, u32 hbp,
+		     u32 vsw, u32 vfp, u32 vbp, enum polarity field_polarity,
+		     enum polarity hsyncpolarity, enum polarity vsyncpolarity,
+		     u32 even_vsw, u32 even_vfp, u32 even_vbp, u32 vsetpixel,
+		     u32 vsclrpixel, u32 evenvsetpixel, u32 evenvsclrpixel)
+{
+	register struct nx_dpc_register_set *pregister;
+	u32 regvalue = 0;
+
+	pregister = __g_module_variables[module_index].pregister;
+
+	writel((u32)(hfp + hsw + hbp + avwidth - 1), &pregister->dpchtotal);
+	writel((u32)(hsw - 1), &pregister->dpchswidth);
+	writel((u32)(hsw + hbp - 1), &pregister->dpchastart);
+	writel((u32)(hsw + hbp + avwidth - 1), &pregister->dpchaend);
+	writel((u32)(vfp + vsw + vbp + avheight - 1), &pregister->dpcvtotal);
+	writel((u32)(vsw - 1), &pregister->dpcvswidth);
+	writel((u32)(vsw + vbp - 1), &pregister->dpcvastart);
+	writel((u32)(vsw + vbp + avheight - 1), &pregister->dpcvaend);
+	writel((u32)vsetpixel, &pregister->dpcvseoffset);
+	writel((u32)(hfp + hsw + hbp + avwidth - vsclrpixel - 1),
+	       &pregister->dpcvssoffset);
+	writel((u32)evenvsetpixel, &pregister->dpcevseoffset);
+	writel((u32)(hfp + hsw + hbp + avwidth - evenvsclrpixel - 1),
+	       &pregister->dpcevssoffset);
+	if (sync_gen_mode == 1) {
+		writel((u32)(even_vfp + even_vsw + even_vbp + avheight - 1),
+		       &pregister->dpcevtotal);
+		writel((u32)(even_vsw - 1), &pregister->dpcevswidth);
+		writel((u32)(even_vsw + even_vbp - 1),
+		       &pregister->dpcevastart);
+		writel((u32)(even_vsw + even_vbp + avheight - 1),
+		       &pregister->dpcevaend);
+	}
+	regvalue = readl(&pregister->dpcctrl0) & 0xfff0ul;
+	regvalue |= (((u32)field_polarity << 2) | ((u32)vsyncpolarity << 1) |
+		     ((u32)hsyncpolarity << 0));
+	writel((u32)regvalue, &pregister->dpcctrl0);
+}
+
+void nx_dpc_set_output_format(u32 module_index, enum outputformat output_format,
+			      u8 output_video_config)
+{
+	const u32 format_table[] = {
+		(0 << 0), (1 << 0), (2 << 0), (3 << 0), (4 << 0), (5 << 0),
+		(6 << 0), (7 << 0), (8 << 0), (9 << 0), (0 << 0) | (1 << 7),
+		(1 << 0) | (1 << 7), (2 << 0) | (1 << 7), (3 << 0) | (1 << 7),
+		(4 << 0) | (1 << 7), (5 << 0) | (1 << 7), (6 << 0) | (1 << 7),
+		(7 << 0) | (1 << 7), (8 << 0) | (1 << 7), (9 << 0) | (1 << 7),
+		(10 << 0), (11 << 0), (12 << 0), (13 << 0), (14 << 0), (15 << 0)
+	};
+	u32 regvalue;
+	u32 regvalue0;
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	regvalue = readl(&pregister->dpcctrl1) & 0x30fful;
+
+	regvalue |= (format_table[output_format] << 8);
+	writel((u32)regvalue, &pregister->dpcctrl1);
+	regvalue0 = (u32)(readl(&pregister->dpcctrl1) & 0xff3f);
+	regvalue0 = (u32)((output_video_config << 6) | regvalue0);
+	writel((u32)regvalue0, &pregister->dpcctrl1);
+}
+
+void nx_dpc_set_quantization_mode(u32 module_index, enum qmode rgb2yc,
+				  enum qmode yc2rgb)
+{
+	register struct nx_dpc_register_set *pregister;
+	u32 regvalue;
+
+	pregister = __g_module_variables[module_index].pregister;
+	regvalue = readl(&pregister->dpcctrl1) & 0x8ffful;
+	regvalue |= ((u32)rgb2yc << 13) | ((u32)yc2rgb << 12);
+	writel((u32)regvalue, &pregister->dpcctrl1);
+}
+
+void nx_dpc_set_enable(u32 module_index, int enable, int rgbmode,
+		       int use_ntscsync, int use_analog_output, int seavenable)
+{
+	u32 regvalue;
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	regvalue = readl(&pregister->dpcctrl0) & 0x0efful;
+	regvalue |= ((u32)enable << 15) | ((u32)use_ntscsync << 14) |
+	    ((u32)seavenable << 8) | ((u32)use_analog_output << 13) |
+	    ((u32)rgbmode << 12);
+	writel((u32)regvalue, &pregister->dpcctrl0);
+}
+
+void nx_dpc_set_out_video_clk_select(u32 module_index,
+				     enum outpadclksel out_pad_vclk_sel)
+{
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+
+	writel((u32)((readl(&pregister->dpcctrl2)) | (out_pad_vclk_sel & 0x3)),
+	       &pregister->dpcctrl2);
+}
+
+void nx_dpc_set_reg_flush(u32 module_index)
+{
+	u32 reg;
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	reg = readl(&pregister->dpcdataflush);
+	writel((u32)(reg | (1ul << 4)), &pregister->dpcdataflush);
+}
+
+void nx_dpc_set_sramon(u32 module_index)
+{
+	u32 reg;
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	reg = (u32)(readl(&pregister->dpcctrl2) & 0xf3ff);
+	writel((u32)(reg | (1ul << 10)), &pregister->dpcctrl2);
+	reg = (u32)(readl(&pregister->dpcctrl2) & 0xf7ff);
+	writel((u32)(reg | (1ul << 11)), &pregister->dpcctrl2);
+}
+
+void nx_dpc_set_sync_lcdtype(u32 module_index, int stnlcd, int dual_view_enb,
+			     int bit_widh, u8 cpcycle)
+{
+	u32 reg;
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+
+	reg = (u32)(readl(&pregister->dpcctrl2) & 0xc0f);
+	writel((u32)(reg | (cpcycle << 12) | (bit_widh << 9) |
+		      (dual_view_enb << 8) | (stnlcd << 7)),
+	       &pregister->dpcctrl2);
+}
+
+void nx_dpc_set_up_scale_control(u32 module_index, int up_scale_enb,
+				 int filter_enb, u32 hscale, u16 source_width)
+{
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	writel((u32)((hscale << 8) | ((u32)filter_enb << 1) | (up_scale_enb)),
+	       &pregister->dpcupscalecon0);
+	writel((u32)(hscale >> 8), &pregister->dpcupscalecon1);
+	writel(source_width, &pregister->dpcupscalecon2);
+}
+
+void nx_dpc_set_mputime(u32 module_index, u8 setup, u8 hold, u8 acc)
+{
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	writel((u32)((setup << 8) | (hold & 0xff)), &pregister->dpcmputime0);
+	writel((u32)(acc), &pregister->dpcmputime1);
+}
+
+void nx_dpc_set_index(u32 module_index, u32 index)
+{
+	u32 regvalue;
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	writel((u32)(index & 0xffff), &pregister->dpcmpuwrdatal);
+	writel((u32)((index >> 16) & 0xff), &pregister->dpcmpuindex);
+	if (index == 0x22) {
+		regvalue = readl(&pregister->dpcctrl2);
+		writel((regvalue | 0x10), &pregister->dpcctrl2);
+	}
+}
+
+void nx_dpc_set_data(u32 module_index, u32 data)
+{
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	writel((u32)(data & 0xffff), &pregister->dpcmpuwrdatal);
+	writel((u32)((data >> 16) & 0xff), &pregister->dpcmpudatah);
+}
+
+void nx_dpc_set_cmd_buffer_flush(u32 module_index)
+{
+	u32 reg;
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	reg = readl(&pregister->dpcdataflush);
+	writel((u32)(reg | (1 << 1)), &pregister->dpcdataflush);
+}
+
+void nx_dpc_set_cmd_buffer_clear(u32 module_index)
+{
+	u32 reg;
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	reg = readl(&pregister->dpcdataflush);
+	writel((u32)(reg | (1 << 0)), &pregister->dpcdataflush);
+}
+
+void nx_dpc_set_cmd_buffer_write(u32 module_index, u32 cmd_data)
+{
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	writel((u32)(cmd_data & 0xffff), &pregister->dpccmdbufferdatal);
+	writel((u32)(cmd_data >> 16), &pregister->dpccmdbufferdatah);
+}
+
+void nx_dpc_set(u32 module_index)
+{
+	u32 reg;
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	reg = readl(&pregister->dpcpolctrl);
+	writel((u32)(reg | 0x1), &pregister->dpcpolctrl);
+}
+
+u32 nx_dpc_get_data(u32 module_index)
+{
+	u32 reg = 0;
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	reg = readl(&pregister->dpcmpudatah);
+	reg = (reg << 16) | readl(&pregister->dpcmpurdatal);
+	return reg;
+}
+
+u32 nx_dpc_get_status(u32 module_index)
+{
+	u32 reg = 0;
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	reg = readl(&pregister->dpcmpustatus);
+	reg = (reg << 16) | readl(&pregister->dpcmpurdatal);
+	return reg;
+}
+
+void nx_dpc_rgbmask(u32 module_index, u32 rgbmask)
+{
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	writel((rgbmask >> 0) & 0xffff, &pregister->dpcrgbmask[0]);
+	writel((rgbmask >> 16) & 0x00ff, &pregister->dpcrgbmask[1]);
+}
+
+void nx_dpc_set_pad_location(u32 module_index, u32 index, u32 regvalue)
+{
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	writel(regvalue, &pregister->dpcpadposition[index]);
+}
+
+u32 nx_dpc_get_field_flag(u32 module_index)
+{
+	register struct nx_dpc_register_set *pregister;
+	u32 regvalue;
+
+	pregister = __g_module_variables[module_index].pregister;
+	regvalue = readl(&pregister->dpcrgbshift);
+
+	return (u32)((regvalue >> 5) & 0x01);
+}
+
+void nx_dpc_set_enable_with_interlace(u32 module_index, int enable, int rgbmode,
+				      int use_ntscsync, int use_analog_output,
+				      int seavenable)
+{
+	u32 regvalue;
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	regvalue = readl(&pregister->dpcctrl0) & 0x0eff;
+	regvalue = readl(&pregister->dpcctrl0) & 0x0eff;
+	regvalue |= ((u32)enable << 15) | ((u32)use_ntscsync << 14) |
+	    ((u32)seavenable << 8) | ((u32)use_analog_output << 13) |
+	    ((u32)rgbmode << 12);
+
+	regvalue |= (1 << 9);
+	writel((u16)regvalue, &pregister->dpcctrl0);
+}
+
+void nx_dpc_set_encoder_control_reg(u32 module_index, u32 param_a, u32 param_b,
+				    u32 param_c)
+{
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	writel(param_a, &pregister->ntsc_ecmda);
+	writel(param_b, &pregister->ntsc_ecmdb);
+	writel(param_c, &pregister->ntsc_ecmdc);
+}
+
+void nx_dpc_set_encoder_shcphase_control(u32 module_index, u32 chroma_param)
+{
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	writel(chroma_param, &pregister->ntsc_sch);
+}
+
+void nx_dpc_set_encoder_timing_config_reg(u32 module_index, u32 icntl)
+{
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	writel(icntl, &pregister->ntsc_icntl);
+}
+
+void nx_dpc_set_encoder_dacoutput_select(u32 module_index, u8 dacsel0,
+					 u8 dacsel1, u8 dacsel2, u8 dacsel3,
+					 u8 dacsel4, u8 dacsel5)
+{
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	writel(((dacsel1 & 0xf) << 4) | (dacsel0 & 0xf),
+	       &pregister->ntsc_dacsel10);
+	writel(((dacsel3 & 0xf) << 4) | (dacsel2 & 0xf),
+	       &pregister->ntsc_dacsel32);
+	writel(((dacsel5 & 0xf) << 4) | (dacsel4 & 0xf),
+	       &pregister->ntsc_dacsel54);
+}
+
+void nx_dpc_set_encoder_sync_location(u32 module_index, u16 hsoe, u16 hsob,
+				      u16 vsob, u16 vsoe, u8 vsost, int novrst)
+{
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	writel((u16)((((vsob & 0x100) >> 2) | ((hsob & 0x700) >> 5) |
+		       (hsoe & 0x700) >> 8)), &pregister->ntsc_hsvso);
+	writel((u16)(hsoe & 0xff), &pregister->ntsc_hsoe);
+	writel((u16)(hsob & 0xff), &pregister->ntsc_hsob);
+	writel((u16)(vsob & 0xff), &pregister->ntsc_vsob);
+	writel((u16)(((vsost & 0x3) << 6) | (novrst << 5) | (vsoe & 0x1f)),
+	       &pregister->ntsc_vsoe);
+}
+
+void nx_dpc_set_encoder_dacpower_enable(u32 module_index, u8 dacpd)
+{
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	writel(dacpd, &pregister->ntsc_dacpd);
+}
+
+void nx_dpc_set_ycorder(u32 module_index, enum nx_dpc_ycorder ycorder)
+{
+	const u16 ycorder_pos = 6;
+	register struct nx_dpc_register_set *pregister;
+	u32 temp;
+
+	pregister = __g_module_variables[module_index].pregister;
+	temp = pregister->dpcctrl1 & (~(0xf << ycorder_pos));
+	temp = (u16)(temp | (ycorder << ycorder_pos));
+	writel(temp, &pregister->dpcctrl1);
+}
+
+void nx_dpc_set_luma_gain(u32 module_index, u32 luma_gain)
+{
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	writel(luma_gain, &pregister->ntsc_cont);
+}
+
+void nx_dpc_set_encenable(u32 module_index, int benb)
+{
+	const u16 encmode = 1u << 14;
+	const u16 encrst = 1u << 13;
+	const u16 intpend = 1u << 10;
+	register struct nx_dpc_register_set *pregister;
+	register u16 temp;
+
+	pregister = __g_module_variables[module_index].pregister;
+	temp = readl(&pregister->dpcctrl0);
+	temp &= (u16)~intpend;
+	if (benb)
+		temp |= (u16)encrst;
+	else
+		temp &= (u16)~encrst;
+	writel((temp | encmode), &pregister->dpcctrl0);
+	writel(7, &pregister->ntsc_icntl);
+}
+
+int nx_dpc_get_encenable(u32 module_index)
+{
+	const u16 encrst = 1u << 13;
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	return (readl(&pregister->dpcctrl0) & encrst) ? 1 : 0;
+}
+
+void nx_dpc_set_video_encoder_power_down(u32 module_index, int benb)
+{
+	const u16 pwdenc = 1u << 7;
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	if (benb) {
+		writel(readl(&pregister->ntsc_ecmda) | (u16)pwdenc,
+		       &pregister->ntsc_ecmda);
+		writel(0, &pregister->ntsc_dacsel10);
+	} else {
+		writel(1, &pregister->ntsc_dacsel10);
+		writel(readl(&pregister->ntsc_ecmda) & (u16)~pwdenc,
+		       &pregister->ntsc_ecmda);
+	}
+}
+
+int nx_dpc_get_video_encoder_power_down(u32 module_index)
+{
+	const u16 pwdenc = 1u << 7;
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	return (readl(&pregister->ntsc_ecmda) & pwdenc) ? 1 : 0;
+}
+
+void nx_dpc_set_video_encoder_mode(u32 module_index, enum nx_dpc_vbs vbs,
+				   int bpedestal)
+{
+	register struct nx_dpc_register_set *pregister;
+
+#define phalt (1u << 0)
+#define ifmt (1u << 1)
+#define ped (1u << 3)
+#define fscsel_ntsc (0u << 4)
+#define fscsel_pal (1u << 4)
+#define fscsel_palm (2u << 4)
+#define fscsel_paln (3u << 4)
+#define fdrst (1u << 6)
+#define pwdenc (1u << 7)
+	register u16 temp;
+	static const u8 ntsc_ecmda_table[] = {
+		(u8)(fscsel_ntsc | fdrst), (u8)(ifmt | fscsel_ntsc),
+		(u8)(fscsel_pal), (u8)(fscsel_palm | phalt),
+		(u8)(ifmt | fscsel_paln | phalt),
+		(u8)(ifmt | fscsel_pal | phalt | fdrst),
+		(u8)(fscsel_pal | phalt),
+		(u8)(ifmt | fscsel_ntsc)
+	};
+	pregister = __g_module_variables[module_index].pregister;
+	temp = readl(&pregister->ntsc_ecmda);
+	temp &= (u16)pwdenc;
+	temp = (u16)(temp | (u16)ntsc_ecmda_table[vbs]);
+	if (bpedestal)
+		temp |= (u16)ped;
+	writel(temp, &pregister->ntsc_ecmda);
+#undef phalt
+#undef ifmt
+#undef ped
+#undef fscsel_ntsc
+#undef fscsel_pal
+#undef fscsel_palm
+#undef fscsel_paln
+#undef fdrst
+#undef pwdenc
+}
+
+void nx_dpc_set_video_encoder_schlock_control(u32 module_index, int bfreerun)
+{
+	const u16 fdrst = 1u << 6;
+	register struct nx_dpc_register_set *pregister;
+	register u16 temp;
+
+	pregister = __g_module_variables[module_index].pregister;
+	temp = readl(&pregister->ntsc_ecmda);
+	if (bfreerun)
+		temp |= (u16)fdrst;
+	else
+		temp &= (u16)~fdrst;
+	writel(temp, &pregister->ntsc_ecmda);
+}
+
+int nx_dpc_get_video_encoder_schlock_control(u32 module_index)
+{
+	const u16 fdrst = 1u << 6;
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	return (readl(&pregister->ntsc_ecmda) & fdrst) ? 1 : 0;
+}
+
+void nx_dpc_set_video_encoder_bandwidth(u32 module_index,
+					enum nx_dpc_bandwidth luma,
+					enum nx_dpc_bandwidth chroma)
+{
+	const u16 ybw_pos = 0;
+	const u16 cbw_pos = 2;
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	writel((u16)((chroma << cbw_pos) | (luma << ybw_pos)),
+	       &pregister->ntsc_ecmdb);
+}
+
+void nx_dpc_get_video_encoder_bandwidth(u32 module_index,
+					enum nx_dpc_bandwidth *pluma,
+					enum nx_dpc_bandwidth *pchroma)
+{
+	const u16 ybw_pos = 0;
+	const u16 ybw_mask = 3u << ybw_pos;
+	const u16 cbw_pos = 2;
+	const u16 cbw_mask = 3u << cbw_pos;
+	register struct nx_dpc_register_set *pregister;
+	register u16 temp;
+
+	pregister = __g_module_variables[module_index].pregister;
+	temp = readl(&pregister->ntsc_ecmdb);
+	if (pluma)
+		*pluma = (enum nx_dpc_bandwidth)((temp & ybw_mask) >> ybw_pos);
+	if (pchroma)
+		*pchroma =
+		    (enum nx_dpc_bandwidth)((temp & cbw_mask) >> cbw_pos);
+}
+
+void nx_dpc_set_video_encoder_color_control(u32 module_index, s8 sch,
+					    s8 hue, s8 sat, s8 crt,
+					    s8 brt)
+{
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	writel((u16)sch, &pregister->ntsc_sch);
+	writel((u16)hue, &pregister->ntsc_hue);
+	writel((u16)sat, &pregister->ntsc_sat);
+	writel((u16)crt, &pregister->ntsc_cont);
+	writel((u16)brt, &pregister->ntsc_bright);
+}
+
+void nx_dpc_get_video_encoder_color_control(u32 module_index, s8 *psch,
+					    s8 *phue, s8 *psat,
+					    s8 *pcrt, s8 *pbrt)
+{
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	if (psch)
+		*psch = (s8)readl(&pregister->ntsc_sch);
+	if (phue)
+		*phue = (s8)readl(&pregister->ntsc_hue);
+	if (psat)
+		*psat = (s8)readl(&pregister->ntsc_sat);
+	if (pcrt)
+		*pcrt = (s8)readl(&pregister->ntsc_cont);
+	if (pbrt)
+		*pbrt = (s8)readl(&pregister->ntsc_bright);
+}
+
+void nx_dpc_set_video_encoder_fscadjust(u32 module_index, int16_t adjust)
+{
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	writel((u16)(adjust >> 8), &pregister->ntsc_fsc_adjh);
+	writel((u16)(adjust & 0xff), &pregister->ntsc_fsc_adjl);
+}
+
+u16 nx_dpc_get_video_encoder_fscadjust(u32 module_index)
+{
+	register u32 temp;
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	temp = (u32)readl(&pregister->ntsc_fsc_adjh);
+	temp <<= 8;
+	temp |= (((u32)readl(&pregister->ntsc_fsc_adjl)) & 0xff);
+	return (u16)temp;
+}
+
+void nx_dpc_set_video_encoder_timing(u32 module_index, u32 hsos, u32 hsoe,
+				     u32 vsos, u32 vsoe)
+{
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	hsos -= 1;
+	hsoe -= 1;
+	writel((u16)((((vsos >> 8) & 1u) << 6) | (((hsos >> 8) & 7u) << 3) |
+		      (((hsoe >> 8) & 7u) << 0)), &pregister->ntsc_hsvso);
+	writel((u16)(hsos & 0xffu), &pregister->ntsc_hsob);
+	writel((u16)(hsoe & 0xffu), &pregister->ntsc_hsoe);
+	writel((u16)(vsos & 0xffu), &pregister->ntsc_vsob);
+	writel((u16)(vsoe & 0x1fu), &pregister->ntsc_vsoe);
+}
+
+void nx_dpc_get_video_encoder_timing(u32 module_index, u32 *phsos, u32 *phsoe,
+				     u32 *pvsos, u32 *pvsoe)
+{
+	register u16 hsvso;
+	register struct nx_dpc_register_set *pregister;
+
+	pregister = __g_module_variables[module_index].pregister;
+	hsvso = readl(&pregister->ntsc_hsvso);
+	if (phsos)
+		*phsos = (u32)((((hsvso >> 3) & 7u) << 8) |
+				(readl(&pregister->ntsc_hsob) & 0xffu)) + 1;
+	if (phsoe)
+		*phsoe = (u32)((((hsvso >> 0) & 7u) << 8) |
+				(readl(&pregister->ntsc_hsoe) & 0xffu)) + 1;
+	if (pvsos)
+		*pvsos = (u32)((((hsvso >> 6) & 1u) << 8) |
+				(readl(&pregister->ntsc_vsob) & 0xffu));
+	if (pvsoe)
+		*pvsoe = (u32)(readl(&pregister->ntsc_vsoe) & 0x1fu);
+}
diff --git a/drivers/video/nexell/soc/s5pxx18_soc_dpc.h b/drivers/video/nexell/soc/s5pxx18_soc_dpc.h
new file mode 100644
index 0000000..cfa53c3
--- /dev/null
+++ b/drivers/video/nexell/soc/s5pxx18_soc_dpc.h
@@ -0,0 +1,444 @@
+/* SPDX-License-Identifier: GPL-2.0+
+ *
+ * Copyright (C) 2016  Nexell Co., Ltd.
+ *
+ * Author: junghyun, kim <jhkim@nexell.co.kr>
+ */
+
+#ifndef _S5PXX18_SOC_DPC_H_
+#define _S5PXX18_SOC_DPC_H_
+
+#include "s5pxx18_soc_disptype.h"
+
+#define	IRQ_OFFSET	32
+#define IRQ_DPC_P    (IRQ_OFFSET + 33)
+#define IRQ_DPC_S   (IRQ_OFFSET + 34)
+
+#define NUMBER_OF_DPC_MODULE	2
+#define PHY_BASEADDR_DPC0	0xC0102800
+#define PHY_BASEADDR_DPC1	0xC0102C00
+
+#define	PHY_BASEADDR_DPC_LIST	\
+		{ PHY_BASEADDR_DPC0, PHY_BASEADDR_DPC1 }
+
+struct nx_dpc_register_set {
+	u32 ntsc_stata;
+	u32 ntsc_ecmda;
+	u32 ntsc_ecmdb;
+	u32 ntsc_glk;
+	u32 ntsc_sch;
+	u32 ntsc_hue;
+	u32 ntsc_sat;
+	u32 ntsc_cont;
+	u32 ntsc_bright;
+	u32 ntsc_fsc_adjh;
+	u32 ntsc_fsc_adjl;
+	u32 ntsc_ecmdc;
+	u32 ntsc_csdly;
+	u32 __ntsc_reserved_0_[3];
+	u32 ntsc_dacsel10;
+	u32 ntsc_dacsel32;
+	u32 ntsc_dacsel54;
+	u32 ntsc_daclp;
+	u32 ntsc_dacpd;
+	u32 __ntsc_reserved_1_[(0x20 - 0x15)];
+	u32 ntsc_icntl;
+	u32 ntsc_hvoffst;
+	u32 ntsc_hoffst;
+	u32 ntsc_voffset;
+	u32 ntsc_hsvso;
+	u32 ntsc_hsob;
+	u32 ntsc_hsoe;
+	u32 ntsc_vsob;
+	u32 ntsc_vsoe;
+	u32 __reserved[(0xf8 / 4) - 0x29];
+	u32 dpchtotal;
+	u32 dpchswidth;
+	u32 dpchastart;
+	u32 dpchaend;
+	u32 dpcvtotal;
+	u32 dpcvswidth;
+	u32 dpcvastart;
+	u32 dpcvaend;
+	u32 dpcctrl0;
+	u32 dpcctrl1;
+	u32 dpcevtotal;
+	u32 dpcevswidth;
+	u32 dpcevastart;
+	u32 dpcevaend;
+	u32 dpcctrl2;
+	u32 dpcvseoffset;
+	u32 dpcvssoffset;
+	u32 dpcevseoffset;
+	u32 dpcevssoffset;
+	u32 dpcdelay0;
+	u32 dpcupscalecon0;
+	u32 dpcupscalecon1;
+	u32 dpcupscalecon2;
+
+	u32 dpcrnumgencon0;
+	u32 dpcrnumgencon1;
+	u32 dpcrnumgencon2;
+	u32 dpcrndconformula_l;
+	u32 dpcrndconformula_h;
+	u32 dpcfdtaddr;
+	u32 dpcfrdithervalue;
+	u32 dpcfgdithervalue;
+	u32 dpcfbdithervalue;
+	u32 dpcdelay1;
+	u32 dpcmputime0;
+	u32 dpcmputime1;
+	u32 dpcmpuwrdatal;
+	u32 dpcmpuindex;
+	u32 dpcmpustatus;
+	u32 dpcmpudatah;
+	u32 dpcmpurdatal;
+	u32 dpcdummy12;
+	u32 dpccmdbufferdatal;
+	u32 dpccmdbufferdatah;
+	u32 dpcpolctrl;
+	u32 dpcpadposition[8];
+	u32 dpcrgbmask[2];
+	u32 dpcrgbshift;
+	u32 dpcdataflush;
+	u32 __reserved06[((0x3c0) - (2 * 0x0ec)) / 4];
+
+	u32 dpcclkenb;
+	u32 dpcclkgen[2][2];
+};
+
+enum {
+	nx_dpc_int_vsync = 0
+};
+
+enum nx_dpc_format {
+	nx_dpc_format_rgb555 = 0ul,
+	nx_dpc_format_rgb565 = 1ul,
+	nx_dpc_format_rgb666 = 2ul,
+	nx_dpc_format_rgb666b = 18ul,
+	nx_dpc_format_rgb888 = 3ul,
+	nx_dpc_format_mrgb555a = 4ul,
+	nx_dpc_format_mrgb555b = 5ul,
+	nx_dpc_format_mrgb565 = 6ul,
+	nx_dpc_format_mrgb666 = 7ul,
+	nx_dpc_format_mrgb888a = 8ul,
+	nx_dpc_format_mrgb888b = 9ul,
+	nx_dpc_format_ccir656 = 10ul,
+	nx_dpc_format_ccir601a = 12ul,
+	nx_dpc_format_ccir601b = 13ul,
+	nx_dpc_format_srgb888 = 14ul,
+	nx_dpc_format_srgbd8888 = 15ul,
+	nx_dpc_format_4096color = 1ul,
+	nx_dpc_format_16gray = 3ul
+};
+
+enum nx_dpc_ycorder {
+	nx_dpc_ycorder_cb_ycr_y = 0ul,
+	nx_dpc_ycorder_cr_ycb_y = 1ul,
+	nx_dpc_ycorder_ycbycr = 2ul,
+	nx_dpc_ycorder_ycrycb = 3ul
+};
+
+enum nx_dpc_padclk {
+	nx_dpc_padclk_vclk = 0ul,
+	nx_dpc_padclk_vclk2 = 1ul,
+	nx_dpc_padclk_vclk3 = 2ul
+};
+
+enum nx_dpc_dither {
+	nx_dpc_dither_bypass = 0ul,
+	nx_dpc_dither_4bit = 1ul,
+	nx_dpc_dither_5bit = 2ul,
+	nx_dpc_dither_6bit = 3ul
+};
+
+enum nx_dpc_vbs {
+	nx_dpc_vbs_ntsc_m = 0ul,
+	nx_dpc_vbs_ntsc_n = 1ul,
+	nx_dpc_vbs_ntsc_443 = 2ul,
+	nx_dpc_vbs_pal_m = 3ul,
+	nx_dpc_vbs_pal_n = 4ul,
+	nx_dpc_vbs_pal_bghi = 5ul,
+	nx_dpc_vbs_pseudo_pal = 6ul,
+	nx_dpc_vbs_pseudo_ntsc = 7ul
+};
+
+enum nx_dpc_bandwidth {
+	nx_dpc_bandwidth_low = 0ul,
+	nx_dpc_bandwidth_medium = 1ul,
+	nx_dpc_bandwidth_high = 2ul
+};
+
+int nx_dpc_initialize(void);
+u32 nx_dpc_get_number_of_module(void);
+u32 nx_dpc_get_physical_address(u32 module_index);
+u32 nx_dpc_get_size_of_register_set(void);
+void nx_dpc_set_base_address(u32 module_index, void *base_address);
+void *nx_dpc_get_base_address(u32 module_index);
+int nx_dpc_open_module(u32 module_index);
+int nx_dpc_close_module(u32 module_index);
+int nx_dpc_check_busy(u32 module_index);
+int nx_dpc_can_power_down(u32 module_index);
+int32_t nx_dpc_get_interrupt_number(u32 module_index);
+void nx_dpc_set_interrupt_enable(u32 module_index, int32_t int_num,
+				 int enable);
+int nx_dpc_get_interrupt_enable(u32 module_index, int32_t int_num);
+int nx_dpc_get_interrupt_pending(u32 module_index, int32_t int_num);
+void nx_dpc_clear_interrupt_pending(u32 module_index, int32_t int_num);
+void nx_dpc_set_interrupt_enable_all(u32 module_index, int enable);
+int nx_dpc_get_interrupt_enable_all(u32 module_index);
+int nx_dpc_get_interrupt_pending_all(u32 module_index);
+void nx_dpc_clear_interrupt_pending_all(u32 module_index);
+void nx_dpc_set_interrupt_enable32(u32 module_index, u32 enable_flag);
+u32 nx_dpc_get_interrupt_enable32(u32 module_index);
+u32 nx_dpc_get_interrupt_pending32(u32 module_index);
+void nx_dpc_clear_interrupt_pending32(u32 module_index,
+				      u32 pending_flag);
+int32_t nx_dpc_get_interrupt_pending_number(u32 module_index);
+void nx_dpc_set_clock_pclk_mode(u32 module_index, enum nx_pclkmode mode);
+enum nx_pclkmode nx_dpc_get_clock_pclk_mode(u32 module_index);
+void nx_dpc_set_clock_source(u32 module_index, u32 index, u32 clk_src);
+u32 nx_dpc_get_clock_source(u32 module_index, u32 index);
+void nx_dpc_set_clock_divisor(u32 module_index, u32 index, u32 divisor);
+u32 nx_dpc_get_clock_divisor(u32 module_index, u32 index);
+void nx_dpc_set_clock_out_inv(u32 module_index, u32 index,
+			      int out_clk_inv);
+int nx_dpc_get_clock_out_inv(u32 module_index, u32 index);
+void nx_dpc_set_clock_out_select(u32 module_index, u32 index,
+				 int bbypass);
+int nx_dpc_get_clock_out_select(u32 module_index, u32 index);
+void nx_dpc_set_clock_polarity(u32 module_index, int bpolarity);
+int nx_dpc_get_clock_polarity(u32 module_index);
+void nx_dpc_set_clock_out_enb(u32 module_index, u32 index,
+			      int out_clk_enb);
+int nx_dpc_get_clock_out_enb(u32 module_index, u32 index);
+void nx_dpc_set_clock_out_delay(u32 module_index, u32 index, u32 delay);
+u32 nx_dpc_get_clock_out_delay(u32 module_index, u32 index);
+void nx_dpc_set_clock_divisor_enable(u32 module_index, int enable);
+int nx_dpc_get_clock_divisor_enable(u32 module_index);
+
+void nx_dpc_set_dpc_enable(u32 module_index, int benb);
+int nx_dpc_get_dpc_enable(u32 module_index);
+void nx_dpc_set_delay(u32 module_index, u32 delay_rgb_pvd,
+		      u32 delay_hs_cp1, u32 delay_vs_fram,
+		      u32 delay_de_cp2);
+void nx_dpc_get_delay(u32 module_index, u32 *pdelayrgb_pvd,
+		      u32 *pdelayhs_cp1, u32 *pdelayvs_fram,
+		      u32 *pdelayde_cp2);
+void nx_dpc_set_dither(u32 module_index, enum nx_dpc_dither dither_r,
+		       enum nx_dpc_dither dither_g,
+		       enum nx_dpc_dither dither_b);
+void nx_dpc_get_dither(u32 module_index, enum nx_dpc_dither *pditherr,
+		       enum nx_dpc_dither *pditherg,
+		       enum nx_dpc_dither *pditherb);
+void nx_dpc_set_horizontal_up_scaler(u32 module_index, int benb,
+				     u32 sourcewidth, u32 destwidth);
+void nx_dpc_get_horizontal_up_scaler(u32 module_index, int *pbenb,
+				     u32 *psourcewidth,
+				     u32 *pdestwidth);
+
+void nx_dpc_set_mode(u32 module_index, enum nx_dpc_format format,
+		     int binterlace, int binvertfield, int brgbmode,
+		     int bswaprb, enum nx_dpc_ycorder ycorder,
+		     int bclipyc, int bembeddedsync,
+		     enum nx_dpc_padclk clock, int binvertclock,
+		     int bdualview);
+void nx_dpc_get_mode(u32 module_index, enum nx_dpc_format *pformat,
+		     int *pbinterlace, int *pbinvertfield,
+		     int *pbrgbmode, int *pbswaprb,
+		     enum nx_dpc_ycorder *pycorder, int *pbclipyc,
+		     int *pbembeddedsync, enum nx_dpc_padclk *pclock,
+		     int *pbinvertclock, int *pbdualview);
+void nx_dpc_set_hsync(u32 module_index, u32 avwidth, u32 hsw, u32 hfp,
+		      u32 hbp, int binvhsync);
+void nx_dpc_get_hsync(u32 module_index, u32 *pavwidth, u32 *phsw,
+		      u32 *phfp, u32 *phbp, int *pbinvhsync);
+void nx_dpc_set_vsync(u32 module_index, u32 avheight, u32 vsw, u32 vfp,
+		      u32 vbp, int binvvsync, u32 eavheight, u32 evsw,
+		      u32 evfp, u32 evbp);
+void nx_dpc_get_vsync(u32 module_index, u32 *pavheight, u32 *pvsw,
+		      u32 *pvfp, u32 *pvbp, int *pbinvvsync,
+		      u32 *peavheight, u32 *pevsw, u32 *pevfp,
+		      u32 *pevbp);
+void nx_dpc_set_vsync_offset(u32 module_index, u32 vssoffset,
+			     u32 vseoffset, u32 evssoffset,
+			     u32 evseoffset);
+void nx_dpc_get_vsync_offset(u32 module_index, u32 *pvssoffset,
+			     u32 *pvseoffset, u32 *pevssoffset,
+			     u32 *pevseoffset);
+
+u32 nx_dpc_enable_pad_tft(u32 module_index, u32 mode_index);
+u32 nx_dpc_enable_pad_i80(u32 module_index, u32 mode_index);
+
+enum syncgenmode {
+	progressive = 0,
+	interlace = 1
+};
+
+enum polarity {
+	polarity_activehigh = 0,
+	polarity_activelow = 1
+};
+
+enum outputformat {
+	outputformat_rgb555 = 0,
+	outputformat_rgb565 = 1,
+	outputformat_rgb666 = 2,
+	outputformat_rgb888 = 3,
+	outputformat_mrgb555a = 4,
+	outputformat_mrgb555b = 5,
+	outputformat_mrgb565 = 6,
+	outputformat_mrgb666 = 7,
+	outputformat_mrgb888a = 8,
+	outputformat_mrgb888b = 9,
+	outputformat_bgr555 = 10,
+	outputformat_bgr565 = 11,
+	outputformat_bgr666 = 12,
+	outputformat_bgr888 = 13,
+	outputformat_mbgr555a = 14,
+	outputformat_mbgr555b = 15,
+	outputformat_mbgr565 = 16,
+	outputformat_mbgr666 = 17,
+	outputformat_mbgr888a = 18,
+	outputformat_mbgr888b = 19,
+	outputformat_ccir656 = 20,
+	outputformat_ccir601_8 = 21,
+	outputformat_ccir601_16a = 22,
+	outputformat_ccir601_16b = 23,
+	outputformat_srgb888 = 24,
+	outputformat_srgbd8888 = 25
+};
+
+enum outpadclksel {
+	padvclk = 0,
+	padvclk2 = 1,
+	padvclk3 = 2
+};
+
+enum qmode {
+	qmode_220 = 0,
+	qmode_256 = 1
+};
+
+void nx_dpc_set_sync(u32 module_index, enum syncgenmode sync_gen_mode,
+		     u32 avwidth, u32 avheight, u32 hsw, u32 hfp,
+		     u32 hbp, u32 vsw, u32 vfp, u32 vbp,
+		     enum polarity field_polarity,
+		     enum polarity hsyncpolarity,
+		     enum polarity vsyncpolarity, u32 even_vsw,
+		     u32 even_vfp, u32 even_vbp, u32 vsetpixel,
+		     u32 vsclrpixel, u32 evenvsetpixel,
+		     u32 evenvsclrpixel);
+void nx_dpc_set_output_format(u32 module_index,
+			      enum outputformat output_format,
+			      u8 output_video_config);
+void nx_dpc_set_quantization_mode(u32 module_index, enum qmode rgb2yc,
+				  enum qmode yc2rgb);
+void nx_dpc_set_enable(u32 module_index, int enable, int rgbmode,
+		       int use_ntscsync, int use_analog_output,
+		       int seavenable);
+void nx_dpc_set_enable_with_interlace(u32 module_index, int enable,
+				      int rgbmode, int use_ntscsync,
+				      int use_analog_output,
+				      int seavenable);
+void nx_dpc_set_enable_with_interlace(u32 module_index, int enable,
+				      int rgbmode, int use_ntscsync,
+				      int use_analog_output,
+				      int seavenable);
+void nx_dpc_set_out_video_clk_select(u32 module_index,
+				     enum outpadclksel out_pad_vclk_sel);
+void nx_dpc_set_reg_flush(u32 module_index);
+void nx_dpc_set_sramon(u32 module_index);
+void nx_dpc_set_sync_lcdtype(u32 module_index, int stnlcd,
+			     int dual_view_enb, int bit_widh,
+			     u8 cpcycle);
+void nx_dpc_set_up_scale_control(u32 module_index, int up_scale_enb,
+				 int filter_enb, u32 hscale,
+				 u16 source_width);
+
+void nx_dpc_set_mputime(u32 module_index, u8 setup, u8 hold, u8 acc);
+void nx_dpc_set_index(u32 module_index, u32 index);
+void nx_dpc_set_data(u32 module_index, u32 data);
+void nx_dpc_set_cmd_buffer_flush(u32 module_index);
+void nx_dpc_set_cmd_buffer_clear(u32 module_index);
+void nx_dpc_set_cmd_buffer_write(u32 module_index, u32 cmd_data);
+void nx_dpc_set(u32 module_index);
+u32 nx_dpc_get_data(u32 module_index);
+u32 nx_dpc_get_status(u32 module_index);
+void nx_dpc_rgbmask(u32 module_index, u32 rgbmask);
+void nx_dpc_set_pad_location(u32 module_index, u32 index, u32 regvalue);
+u32 nx_dpc_get_field_flag(u32 module_index);
+
+void nx_dpc_set_sync_v(u32 module_index, u32 avheight, u32 vsw, u32 vfp,
+		       u32 vbp);
+
+int nx_dpc_init_reg_test(u32 module_index);
+void nx_dpc_set_encoder_control_reg(u32 module_index, u32 param_a,
+				    u32 param_b, u32 param_c);
+void nx_dpc_set_encoder_shcphase_control(u32 module_index,
+					 u32 chroma_param);
+void nx_dpc_set_encoder_timing_config_reg(u32 module_index, u32 inctl);
+void nx_dpc_set_encoder_dacoutput_select(u32 module_index, u8 dacsel0,
+					 u8 dacsel1, u8 dacsel2,
+					 u8 dacsel3, u8 dacsel4,
+					 u8 dacsel5);
+void nx_dpc_set_encoder_sync_location(u32 module_index, u16 hsoe,
+				      u16 hsob, u16 vsob, u16 vsoe,
+				      u8 vsost, int novrst);
+void nx_dpc_set_encoder_dacpower_enable(u32 module_index, u8 dacpd);
+void nx_dpc_set_ycorder(u32 module_index, enum nx_dpc_ycorder ycorder);
+void nx_dpc_set_luma_gain(u32 module_index, u32 luma_gain);
+
+void nx_dpc_set_secondary_dpcsync(u32 module_index, int benb);
+int nx_dpc_get_secondary_dpcsync(u32 module_index);
+void nx_dpc_set_encenable(u32 module_index, int benb);
+int nx_dpc_get_encenable(u32 module_index);
+void nx_dpc_set_video_encoder_power_down(u32 module_index, int benb);
+int nx_dpc_get_video_encoder_power_down(u32 module_index);
+void nx_dpc_set_video_encoder_mode(u32 module_index, enum nx_dpc_vbs vbs,
+				   int bpedestal);
+void nx_dpc_set_video_encoder_schlock_control(u32 module_index,
+					      int bfreerun);
+int nx_dpc_get_video_encoder_schlock_control(u32 module_index);
+void nx_dpc_set_video_encoder_bandwidth(u32 module_index,
+					enum nx_dpc_bandwidth luma,
+					enum nx_dpc_bandwidth chroma);
+void nx_dpc_get_video_encoder_bandwidth(u32 module_index,
+					enum nx_dpc_bandwidth *pluma,
+					enum nx_dpc_bandwidth *pchroma);
+void nx_dpc_set_video_encoder_color_control(u32 module_index, s8 sch,
+					    s8 hue, s8 sat,
+					    s8 crt, s8 brt);
+void nx_dpc_get_video_encoder_color_control(u32 module_index,
+					    s8 *psch, s8 *phue,
+					    s8 *psat, s8 *pcrt,
+					    s8 *pbrt);
+void nx_dpc_set_video_encoder_fscadjust(u32 module_index,
+					int16_t adjust);
+u16 nx_dpc_get_video_encoder_fscadjust(u32 module_index);
+void nx_dpc_set_video_encoder_timing(u32 module_index, u32 hsos,
+				     u32 hsoe, u32 vsos, u32 vsoe);
+void nx_dpc_get_video_encoder_timing(u32 module_index, u32 *phsos,
+				     u32 *phsoe, u32 *pvsos,
+				     u32 *pvsoe);
+void nx_dpc_set_sync_v(u32 module_index, u32 avheight, u32 vsw, u32 vfp,
+		       u32 vbp);
+
+int nx_dpc_init_reg_test(u32 module_index);
+void nx_dpc_set_encoder_control_reg(u32 module_index, u32 param_a,
+				    u32 param_b, u32 param_c);
+void nx_dpc_set_encoder_shcphase_control(u32 module_index,
+					 u32 chroma_param);
+void nx_dpc_set_encoder_timing_config_reg(u32 module_index, u32 inctl);
+void nx_dpc_set_encoder_dacoutput_select(u32 module_index, u8 dacsel0,
+					 u8 dacsel1, u8 dacsel2,
+					 u8 dacsel3, u8 dacsel4,
+					 u8 dacsel5);
+void nx_dpc_set_encoder_sync_location(u32 module_index, u16 hsoe,
+				      u16 hsob, u16 vsob, u16 vsoe,
+				      u8 vsost, int novrst);
+void nx_dpc_set_encoder_dacpower_enable(u32 module_index, u8 dacpd);
+void nx_dpc_set_ycorder(u32 module_index, enum nx_dpc_ycorder ycorder);
+void nx_dpc_set_luma_gain(u32 module_index, u32 luma_gain);
+
+#endif
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [RFC PATCH v2 11/13] video: add nexell video driver (display/video driver)
  2020-03-28  9:43 [RFC PATCH v2 00/13] arm: add support for SoC S5P4418 Stefan Bosch
                   ` (9 preceding siblings ...)
  2020-03-28  9:43 ` [RFC PATCH v2 10/13] video: add nexell video driver (soc: dpc, makefile) Stefan Bosch
@ 2020-03-28  9:43 ` Stefan Bosch
  2020-03-28  9:43 ` [RFC PATCH v2 12/13] arm: add support for SoC s5p4418 (cpu) / nanopi2 board Stefan Bosch
  2020-03-28  9:43 ` [RFC PATCH v2 13/13] arm: add (default) config for " Stefan Bosch
  12 siblings, 0 replies; 21+ messages in thread
From: Stefan Bosch @ 2020-03-28  9:43 UTC (permalink / raw)
  To: u-boot

Changes in relation to FriendlyARM's U-Boot nanopi2-v2016.01:
- nexell_display.c: Changed to DM, CONFIG_FB_ADDR can not be used
  anymore because framebuffer is allocated by video_reserve() in
  video-uclass.c. Therefore code changed appropriately.

Signed-off-by: Stefan Bosch <stefan_b@posteo.net>
---

Changes in v2: None

 drivers/video/Kconfig                  |  10 +
 drivers/video/Makefile                 |   1 +
 drivers/video/nexell/Kconfig           |  27 ++
 drivers/video/nexell/Makefile          |  12 +
 drivers/video/nexell/s5pxx18_dp.c      | 338 ++++++++++++++++
 drivers/video/nexell/s5pxx18_dp_hdmi.c | 543 ++++++++++++++++++++++++++
 drivers/video/nexell/s5pxx18_dp_lvds.c | 274 +++++++++++++
 drivers/video/nexell/s5pxx18_dp_mipi.c | 677 +++++++++++++++++++++++++++++++++
 drivers/video/nexell/s5pxx18_dp_rgb.c  |  69 ++++
 drivers/video/nexell_display.c         | 665 ++++++++++++++++++++++++++++++++
 10 files changed, 2616 insertions(+)
 create mode 100644 drivers/video/nexell/Kconfig
 create mode 100644 drivers/video/nexell/Makefile
 create mode 100644 drivers/video/nexell/s5pxx18_dp.c
 create mode 100644 drivers/video/nexell/s5pxx18_dp_hdmi.c
 create mode 100644 drivers/video/nexell/s5pxx18_dp_lvds.c
 create mode 100644 drivers/video/nexell/s5pxx18_dp_mipi.c
 create mode 100644 drivers/video/nexell/s5pxx18_dp_rgb.c
 create mode 100644 drivers/video/nexell_display.c

diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 50ab365..dd224ab 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -563,6 +563,16 @@ source "drivers/video/bridge/Kconfig"
 
 source "drivers/video/imx/Kconfig"
 
+config VIDEO_NX
+	bool "Enable video support on Nexell SoC"
+	depends on ARCH_S5P6818 || ARCH_S5P4418
+	help
+	   Nexell SoC supports many video output options including eDP and
+	   HDMI. This option enables this support which can be used on devices
+	   which have an eDP display connected.
+
+source "drivers/video/nexell/Kconfig"
+
 config VIDEO
 	bool "Enable legacy video support"
 	depends on !DM_VIDEO
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index df7119d..3bacc64 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -61,6 +61,7 @@ obj-${CONFIG_VIDEO_MIPI_DSI} += mipi_dsi.o
 obj-$(CONFIG_VIDEO_MVEBU) += mvebu_lcd.o
 obj-$(CONFIG_VIDEO_MX3) += mx3fb.o videomodes.o
 obj-$(CONFIG_VIDEO_MXS) += mxsfb.o videomodes.o
+obj-$(CONFIG_VIDEO_NX) += nexell_display.o videomodes.o nexell/
 obj-$(CONFIG_VIDEO_OMAP3) += omap3_dss.o
 obj-$(CONFIG_VIDEO_DSI_HOST_SANDBOX) += sandbox_dsi_host.o
 obj-$(CONFIG_VIDEO_SANDBOX_SDL) += sandbox_sdl.o
diff --git a/drivers/video/nexell/Kconfig b/drivers/video/nexell/Kconfig
new file mode 100644
index 0000000..54b8ccb
--- /dev/null
+++ b/drivers/video/nexell/Kconfig
@@ -0,0 +1,27 @@
+if VIDEO_NX
+
+menu "LCD select"
+
+config VIDEO_NX_RGB
+	bool "RGB LCD"
+	help
+	  Support for RGB lcd output.
+
+config VIDEO_NX_LVDS
+	bool "LVDS LCD"
+	help
+	  Support for LVDS lcd output.
+
+config VIDEO_NX_MIPI
+	bool "MiPi"
+	help
+	  Support for MiPi lcd output.
+
+config VIDEO_NX_HDMI
+	bool "HDMI"
+	help
+	  Support for hdmi output.
+
+endmenu
+
+endif
diff --git a/drivers/video/nexell/Makefile b/drivers/video/nexell/Makefile
new file mode 100644
index 0000000..111ab45
--- /dev/null
+++ b/drivers/video/nexell/Makefile
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2016 Nexell
+# Junghyun, kim<jhkim@nexell.co.kr>
+
+obj-$(CONFIG_VIDEO_NX) += s5pxx18_dp.o
+obj-$(CONFIG_VIDEO_NX) += soc/
+
+obj-$(CONFIG_VIDEO_NX_RGB)  += s5pxx18_dp_rgb.o
+obj-$(CONFIG_VIDEO_NX_LVDS) += s5pxx18_dp_lvds.o
+obj-$(CONFIG_VIDEO_NX_MIPI) += s5pxx18_dp_mipi.o
+obj-$(CONFIG_VIDEO_NX_HDMI) += s5pxx18_dp_hdmi.o
diff --git a/drivers/video/nexell/s5pxx18_dp.c b/drivers/video/nexell/s5pxx18_dp.c
new file mode 100644
index 0000000..c69b69c
--- /dev/null
+++ b/drivers/video/nexell/s5pxx18_dp.c
@@ -0,0 +1,338 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2016  Nexell Co., Ltd.
+ *
+ * Author: junghyun, kim <jhkim@nexell.co.kr>
+ */
+
+#include <config.h>
+#include <common.h>
+#include <errno.h>
+#include <asm/arch/reset.h>
+#include <asm/arch/nexell.h>
+#include <asm/arch/display.h>
+
+#include "soc/s5pxx18_soc_disptop.h"
+#include "soc/s5pxx18_soc_dpc.h"
+#include "soc/s5pxx18_soc_mlc.h"
+
+#define	MLC_LAYER_RGB_0		0	/* number of RGB layer 0 */
+#define	MLC_LAYER_RGB_1		1	/* number of RGB layer 1 */
+#define	MLC_LAYER_VIDEO		3	/* number of Video layer: 3 = VIDEO */
+
+#define	__io_address(a)	(void *)(uintptr_t)(a)
+
+void dp_control_init(int module)
+{
+	void *base;
+
+	/* top */
+	base = __io_address(nx_disp_top_get_physical_address());
+	nx_disp_top_set_base_address(base);
+
+	/* control */
+	base = __io_address(nx_dpc_get_physical_address(module));
+	nx_dpc_set_base_address(module, base);
+
+	/* top controller */
+	nx_rstcon_setrst(RESET_ID_DISP_TOP, RSTCON_ASSERT);
+	nx_rstcon_setrst(RESET_ID_DISP_TOP, RSTCON_NEGATE);
+
+	/* display controller */
+	nx_rstcon_setrst(RESET_ID_DISPLAY, RSTCON_ASSERT);
+	nx_rstcon_setrst(RESET_ID_DISPLAY, RSTCON_NEGATE);
+
+	nx_dpc_set_clock_pclk_mode(module, nx_pclkmode_always);
+}
+
+int dp_control_setup(int module,
+		     struct dp_sync_info *sync, struct dp_ctrl_info *ctrl)
+{
+	unsigned int out_format;
+	unsigned int delay_mask;
+	int rgb_pvd = 0, hsync_cp1 = 7, vsync_fram = 7, de_cp2 = 7;
+	int v_vso = 1, v_veo = 1, e_vso = 1, e_veo = 1;
+
+	int interlace = 0;
+	int invert_field;
+	int swap_rb;
+	unsigned int yc_order;
+	int vck_select;
+	int vclk_invert;
+	int emb_sync;
+
+	enum nx_dpc_dither r_dither, g_dither, b_dither;
+	int rgb_mode = 0;
+
+	if (NULL == sync || NULL == ctrl) {
+		debug("error, dp.%d not set sync or pad clock info !!!\n",
+		      module);
+		return -EINVAL;
+	}
+
+	out_format = ctrl->out_format;
+	delay_mask = ctrl->delay_mask;
+	interlace = sync->interlace;
+	invert_field = ctrl->invert_field;
+	swap_rb = ctrl->swap_RB;
+	yc_order = ctrl->yc_order;
+	vck_select = ctrl->vck_select;
+	vclk_invert = ctrl->clk_inv_lv0 | ctrl->clk_inv_lv1;
+	emb_sync = (out_format == DPC_FORMAT_CCIR656 ? 1 : 0);
+
+	/* set delay mask */
+	if (delay_mask & DP_SYNC_DELAY_RGB_PVD)
+		rgb_pvd = ctrl->d_rgb_pvd;
+	if (delay_mask & DP_SYNC_DELAY_HSYNC_CP1)
+		hsync_cp1 = ctrl->d_hsync_cp1;
+	if (delay_mask & DP_SYNC_DELAY_VSYNC_FRAM)
+		vsync_fram = ctrl->d_vsync_fram;
+	if (delay_mask & DP_SYNC_DELAY_DE_CP)
+		de_cp2 = ctrl->d_de_cp2;
+
+	if (ctrl->vs_start_offset != 0 ||
+	    ctrl->vs_end_offset != 0 ||
+	    ctrl->ev_start_offset != 0 || ctrl->ev_end_offset != 0) {
+		v_vso = ctrl->vs_start_offset;
+		v_veo = ctrl->vs_end_offset;
+		e_vso = ctrl->ev_start_offset;
+		e_veo = ctrl->ev_end_offset;
+	}
+
+	if (nx_dpc_format_rgb555 == out_format ||
+	    nx_dpc_format_mrgb555a == out_format ||
+	    nx_dpc_format_mrgb555b == out_format) {
+		r_dither = nx_dpc_dither_5bit;
+		g_dither = nx_dpc_dither_5bit;
+		b_dither = nx_dpc_dither_5bit;
+		rgb_mode = 1;
+	} else if (nx_dpc_format_rgb565 == out_format ||
+		       nx_dpc_format_mrgb565 == out_format) {
+		r_dither = nx_dpc_dither_5bit;
+		b_dither = nx_dpc_dither_5bit;
+		g_dither = nx_dpc_dither_6bit, rgb_mode = 1;
+	} else if ((nx_dpc_format_rgb666 == out_format) ||
+		   (nx_dpc_format_mrgb666 == out_format)) {
+		r_dither = nx_dpc_dither_6bit;
+		g_dither = nx_dpc_dither_6bit;
+		b_dither = nx_dpc_dither_6bit;
+		rgb_mode = 1;
+	} else {
+		r_dither = nx_dpc_dither_bypass;
+		g_dither = nx_dpc_dither_bypass;
+		b_dither = nx_dpc_dither_bypass;
+		rgb_mode = 1;
+	}
+
+	/* CLKGEN0/1 */
+	nx_dpc_set_clock_source(module, 0, ctrl->clk_src_lv0 == 3 ?
+				6 : ctrl->clk_src_lv0);
+	nx_dpc_set_clock_divisor(module, 0, ctrl->clk_div_lv0);
+	nx_dpc_set_clock_source(module, 1, ctrl->clk_src_lv1);
+	nx_dpc_set_clock_divisor(module, 1, ctrl->clk_div_lv1);
+	nx_dpc_set_clock_out_delay(module, 0, ctrl->clk_delay_lv0);
+	nx_dpc_set_clock_out_delay(module, 1, ctrl->clk_delay_lv1);
+
+	/* LCD out */
+	nx_dpc_set_mode(module, out_format, interlace, invert_field,
+			rgb_mode, swap_rb, yc_order, emb_sync, emb_sync,
+			vck_select, vclk_invert, 0);
+	nx_dpc_set_hsync(module, sync->h_active_len, sync->h_sync_width,
+			 sync->h_front_porch, sync->h_back_porch,
+			 sync->h_sync_invert);
+	nx_dpc_set_vsync(module, sync->v_active_len, sync->v_sync_width,
+			 sync->v_front_porch, sync->v_back_porch,
+			 sync->v_sync_invert, sync->v_active_len,
+			 sync->v_sync_width, sync->v_front_porch,
+			 sync->v_back_porch);
+	nx_dpc_set_vsync_offset(module, v_vso, v_veo, e_vso, e_veo);
+	nx_dpc_set_delay(module, rgb_pvd, hsync_cp1, vsync_fram, de_cp2);
+	nx_dpc_set_dither(module, r_dither, g_dither, b_dither);
+
+#ifdef CONFIG_MACH_S5P6818
+	/* Set TFT_CLKCTRL (offset : 1030h)
+	 * Field name : DPC0_CLKCTRL, DPC1_CLKCRL
+	 * Default value : clk_inv_lv0/1 = 0 : PADCLK_InvCLK
+	 * Invert case   : clk_inv_lv0/1 = 1 : PADCLK_CLK
+	 */
+	if (module == 0 && ctrl->clk_inv_lv0)
+		nx_disp_top_set_padclock(padmux_primary_mlc, padclk_clk);
+	if (module == 1 && ctrl->clk_inv_lv1)
+		nx_disp_top_set_padclock(padmux_secondary_mlc, padclk_clk);
+#endif
+
+	debug("%s: dp.%d x:%4d, hf:%3d, hb:%3d, hs:%3d, hi=%d\n",
+	      __func__, module, sync->h_active_len, sync->h_front_porch,
+	      sync->h_back_porch, sync->h_sync_width, sync->h_sync_invert);
+	debug("%s: dp.%d y:%4d, vf:%3d, vb:%3d, vs:%3d, vi=%d\n",
+	      __func__, module, sync->v_active_len, sync->v_front_porch,
+	      sync->v_back_porch, sync->v_sync_width, sync->h_sync_invert);
+	debug("%s: dp.%d ck.0:%d:%d:%d, ck.1:%d:%d:%d\n",
+	      __func__, module,
+	      ctrl->clk_src_lv0, ctrl->clk_div_lv0, ctrl->clk_inv_lv0,
+	      ctrl->clk_src_lv1, ctrl->clk_div_lv1, ctrl->clk_inv_lv1);
+	debug("%s: dp.%d vs:%d, ve:%d, es:%d, ee:%d\n",
+	      __func__, module, v_vso, v_veo, e_vso, e_veo);
+	debug("%s: dp.%d delay RGB:%d, hs:%d, vs:%d, de:%d, fmt:0x%x\n",
+	      __func__, module, rgb_pvd, hsync_cp1, vsync_fram, de_cp2,
+	      out_format);
+
+	return 0;
+}
+
+void dp_control_enable(int module, int on)
+{
+	debug("%s: dp.%d top %s\n", __func__, module, on ? "ON" : "OFF");
+
+	nx_dpc_set_dpc_enable(module, on);
+	nx_dpc_set_clock_divisor_enable(module, on);
+}
+
+void dp_plane_init(int module)
+{
+	void *base = __io_address(nx_mlc_get_physical_address(module));
+
+	nx_mlc_set_base_address(module, base);
+	nx_mlc_set_clock_pclk_mode(module, nx_pclkmode_always);
+	nx_mlc_set_clock_bclk_mode(module, nx_bclkmode_always);
+}
+
+int dp_plane_screen_setup(int module, struct dp_plane_top *top)
+{
+	int width = top->screen_width;
+	int height = top->screen_height;
+	int interlace = top->interlace;
+	int video_prior = top->video_prior;
+	unsigned int bg_color = top->back_color;
+
+	/* MLC TOP layer */
+	nx_mlc_set_screen_size(module, width, height);
+	nx_mlc_set_layer_priority(module, video_prior);
+	nx_mlc_set_background(module, bg_color);
+	nx_mlc_set_field_enable(module, interlace);
+	nx_mlc_set_rgblayer_gama_table_power_mode(module, 0, 0, 0);
+	nx_mlc_set_rgblayer_gama_table_sleep_mode(module, 1, 1, 1);
+	nx_mlc_set_rgblayer_gamma_enable(module, 0);
+	nx_mlc_set_dither_enable_when_using_gamma(module, 0);
+	nx_mlc_set_gamma_priority(module, 0);
+	nx_mlc_set_top_power_mode(module, 1);
+	nx_mlc_set_top_sleep_mode(module, 0);
+
+	debug("%s: dp.%d screen %dx%d, %s, priority:%d, bg:0x%x\n",
+	      __func__, module, width, height,
+	      interlace ? "Interlace" : "Progressive",
+	      video_prior, bg_color);
+
+	return 0;
+}
+
+void dp_plane_screen_enable(int module, int on)
+{
+	/* enable top screen */
+	nx_mlc_set_mlc_enable(module, on);
+	nx_mlc_set_top_dirty_flag(module);
+	debug("%s: dp.%d top %s\n", __func__, module, on ? "ON" : "OFF");
+}
+
+int dp_plane_layer_setup(int module, struct dp_plane_info *plane)
+{
+	int sx = plane->left;
+	int sy = plane->top;
+	int ex = sx + plane->width - 1;
+	int ey = sy + plane->height - 1;
+	int pixel_byte = plane->pixel_byte;
+	int mem_lock_size = 16;	/* fix mem lock size */
+	int layer = plane->layer;
+	unsigned int format = plane->format;
+
+	if (!plane->enable)
+		return -EINVAL;
+
+	/* MLC layer */
+	nx_mlc_set_lock_size(module, layer, mem_lock_size);
+	nx_mlc_set_alpha_blending(module, layer, 0, 15);
+	nx_mlc_set_transparency(module, layer, 0, 0);
+	nx_mlc_set_color_inversion(module, layer, 0, 0);
+	nx_mlc_set_rgblayer_invalid_position(module, layer, 0, 0, 0, 0, 0, 0);
+	nx_mlc_set_rgblayer_invalid_position(module, layer, 1, 0, 0, 0, 0, 0);
+	nx_mlc_set_format_rgb(module, layer, format);
+	nx_mlc_set_position(module, layer, sx, sy, ex, ey);
+	nx_mlc_set_rgblayer_stride(module, layer, pixel_byte,
+				   plane->width * pixel_byte);
+	nx_mlc_set_rgblayer_address(module, layer, plane->fb_base);
+
+	debug("%s: dp.%d.%d %d * %d, %dbpp, fmt:0x%x\n",
+	      __func__, module, layer, plane->width, plane->height,
+	      pixel_byte * 8, format);
+	debug("%s: b:0x%x, l:%d, t:%d, r:%d, b:%d, hs:%d, vs:%d\n",
+	      __func__, plane->fb_base, sx, sy, ex, ey,
+	      plane->width * pixel_byte, pixel_byte);
+
+	return 0;
+}
+
+int dp_plane_set_enable(int module, int layer, int on)
+{
+	int hl, hc;
+	int vl, vc;
+
+	debug("%s: dp.%d.%d %s:%s\n",
+	      __func__, module, layer,
+	      layer == MLC_LAYER_VIDEO ? "Video" : "RGB",
+	      on ? "ON" : "OFF");
+
+	if (layer != MLC_LAYER_VIDEO) {
+		nx_mlc_set_layer_enable(module, layer, on);
+		nx_mlc_set_dirty_flag(module, layer);
+		return 0;
+	}
+
+	/* video layer */
+	if (on) {
+		nx_mlc_set_video_layer_line_buffer_power_mode(module, 1);
+		nx_mlc_set_video_layer_line_buffer_sleep_mode(module, 0);
+		nx_mlc_set_layer_enable(module, layer, 1);
+		nx_mlc_set_dirty_flag(module, layer);
+	} else {
+		nx_mlc_set_layer_enable(module, layer, 0);
+		nx_mlc_set_dirty_flag(module, layer);
+		nx_mlc_get_video_layer_scale_filter(module,
+						    &hl, &hc, &vl, &vc);
+		if (hl || hc || vl || vc)
+			nx_mlc_set_video_layer_scale_filter(module, 0, 0, 0, 0);
+		nx_mlc_set_video_layer_line_buffer_power_mode(module, 0);
+		nx_mlc_set_video_layer_line_buffer_sleep_mode(module, 1);
+		nx_mlc_set_dirty_flag(module, layer);
+	}
+
+	return 0;
+}
+
+void dp_plane_layer_enable(int module,
+			   struct dp_plane_info *plane, int on)
+{
+	dp_plane_set_enable(module, plane->layer, on);
+}
+
+int dp_plane_set_address(int module, int layer, unsigned int address)
+{
+	nx_mlc_set_rgblayer_address(module, layer, address);
+	nx_mlc_set_dirty_flag(module, layer);
+
+	return 0;
+}
+
+int dp_plane_wait_vsync(int module, int layer, int fps)
+{
+	int cnt = 0;
+
+	if (fps == 0)
+		return (int)nx_mlc_get_dirty_flag(module, layer);
+
+	while (fps > cnt++) {
+		while (nx_mlc_get_dirty_flag(module, layer))
+			;
+		nx_mlc_set_dirty_flag(module, layer);
+	}
+	return 0;
+}
diff --git a/drivers/video/nexell/s5pxx18_dp_hdmi.c b/drivers/video/nexell/s5pxx18_dp_hdmi.c
new file mode 100644
index 0000000..5d72d1e
--- /dev/null
+++ b/drivers/video/nexell/s5pxx18_dp_hdmi.c
@@ -0,0 +1,543 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2016  Nexell Co., Ltd.
+ *
+ * Author: junghyun, kim <jhkim@nexell.co.kr>
+ */
+
+#include <config.h>
+#include <common.h>
+#include <errno.h>
+
+#include <asm/arch/nexell.h>
+#include <asm/arch/tieoff.h>
+#include <asm/arch/reset.h>
+#include <asm/arch/display.h>
+
+#include "soc/s5pxx18_soc_dpc.h"
+#include "soc/s5pxx18_soc_hdmi.h"
+#include "soc/s5pxx18_soc_disptop.h"
+#include "soc/s5pxx18_soc_disptop_clk.h"
+
+#define	__io_address(a)	(void *)(uintptr_t)(a)
+
+static const u8 hdmiphy_preset74_25[32] = {
+	0xd1, 0x1f, 0x10, 0x40, 0x40, 0xf8, 0xc8, 0x81,
+	0xe8, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80, 0x0a,
+	0x80, 0x09, 0x84, 0x05, 0x22, 0x24, 0x86, 0x54,
+	0xa5, 0x24, 0x01, 0x00, 0x00, 0x01, 0x10, 0x80,
+};
+
+static const u8 hdmiphy_preset148_5[32] = {
+	0xd1, 0x1f, 0x00, 0x40, 0x40, 0xf8, 0xc8, 0x81,
+	0xe8, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80, 0x0a,
+	0x80, 0x09, 0x84, 0x05, 0x22, 0x24, 0x86, 0x54,
+	0x4b, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80,
+};
+
+#define HDMIPHY_PRESET_TABLE_SIZE   (32)
+
+enum NXP_HDMI_PRESET {
+	NXP_HDMI_PRESET_720P = 0,	/* 1280 x 720 */
+	NXP_HDMI_PRESET_1080P,	/* 1920 x 1080 */
+	NXP_HDMI_PRESET_MAX
+};
+
+static void hdmi_reset(void)
+{
+	nx_rstcon_setrst(RESET_ID_HDMI_VIDEO, RSTCON_ASSERT);
+	nx_rstcon_setrst(RESET_ID_HDMI_SPDIF, RSTCON_ASSERT);
+	nx_rstcon_setrst(RESET_ID_HDMI_TMDS, RSTCON_ASSERT);
+	nx_rstcon_setrst(RESET_ID_HDMI_VIDEO, RSTCON_NEGATE);
+	nx_rstcon_setrst(RESET_ID_HDMI_SPDIF, RSTCON_NEGATE);
+	nx_rstcon_setrst(RESET_ID_HDMI_TMDS, RSTCON_NEGATE);
+}
+
+static int hdmi_phy_enable(int preset, int enable)
+{
+	const u8 *table = NULL;
+	int size = 0;
+	u32 addr, i = 0;
+
+	if (!enable)
+		return 0;
+
+	switch (preset) {
+	case NXP_HDMI_PRESET_720P:
+		table = hdmiphy_preset74_25;
+		size = 32;
+		break;
+	case NXP_HDMI_PRESET_1080P:
+		table = hdmiphy_preset148_5;
+		size = 31;
+		break;
+	default:
+		printf("hdmi: phy not support preset %d\n", preset);
+		return -EINVAL;
+	}
+
+	nx_hdmi_set_reg(0, HDMI_PHY_REG7C, (0 << 7));
+	nx_hdmi_set_reg(0, HDMI_PHY_REG7C, (0 << 7));
+	nx_hdmi_set_reg(0, HDMI_PHY_REG04, (0 << 4));
+	nx_hdmi_set_reg(0, HDMI_PHY_REG04, (0 << 4));
+	nx_hdmi_set_reg(0, HDMI_PHY_REG24, (1 << 7));
+	nx_hdmi_set_reg(0, HDMI_PHY_REG24, (1 << 7));
+
+	for (i = 0, addr = HDMI_PHY_REG04; size > i; i++, addr += 4) {
+		nx_hdmi_set_reg(0, addr, table[i]);
+		nx_hdmi_set_reg(0, addr, table[i]);
+	}
+
+	nx_hdmi_set_reg(0, HDMI_PHY_REG7C, 0x80);
+	nx_hdmi_set_reg(0, HDMI_PHY_REG7C, 0x80);
+	nx_hdmi_set_reg(0, HDMI_PHY_REG7C, (1 << 7));
+	nx_hdmi_set_reg(0, HDMI_PHY_REG7C, (1 << 7));
+	debug("%s: preset = %d\n", __func__, preset);
+
+	return 0;
+}
+
+static inline int hdmi_wait_phy_ready(void)
+{
+	int count = 500;
+
+	do {
+		u32 val = nx_hdmi_get_reg(0, HDMI_LINK_PHY_STATUS_0);
+
+		if (val & 0x01) {
+			printf("HDMI:  phy ready...\n");
+			return 1;
+		}
+		mdelay(10);
+	} while (count--);
+
+	return 0;
+}
+
+static inline int hdmi_get_vsync(int preset,
+				 struct dp_sync_info *sync,
+				 struct dp_ctrl_info *ctrl)
+{
+	switch (preset) {
+	case NXP_HDMI_PRESET_720P:	/* 720p: 1280x720 */
+		sync->h_active_len = 1280;
+		sync->h_sync_width = 40;
+		sync->h_back_porch = 220;
+		sync->h_front_porch = 110;
+		sync->h_sync_invert = 0;
+		sync->v_active_len = 720;
+		sync->v_sync_width = 5;
+		sync->v_back_porch = 20;
+		sync->v_front_porch = 5;
+		sync->v_sync_invert = 0;
+		break;
+
+	case NXP_HDMI_PRESET_1080P:	/* 1080p: 1920x1080 */
+		sync->h_active_len = 1920;
+		sync->h_sync_width = 44;
+		sync->h_back_porch = 148;
+		sync->h_front_porch = 88;
+		sync->h_sync_invert = 0;
+		sync->v_active_len = 1080;
+		sync->v_sync_width = 5;
+		sync->v_back_porch = 36;
+		sync->v_front_porch = 4;
+		sync->v_sync_invert = 0;
+		break;
+	default:
+		printf("HDMI: not support preset sync %d\n", preset);
+		return -EINVAL;
+	}
+
+	ctrl->clk_src_lv0 = 4;
+	ctrl->clk_div_lv0 = 1;
+	ctrl->clk_src_lv1 = 7;
+	ctrl->clk_div_lv1 = 1;
+
+	ctrl->out_format = outputformat_rgb888;
+	ctrl->delay_mask = (DP_SYNC_DELAY_RGB_PVD | DP_SYNC_DELAY_HSYNC_CP1 |
+			    DP_SYNC_DELAY_VSYNC_FRAM | DP_SYNC_DELAY_DE_CP);
+	ctrl->d_rgb_pvd = 0;
+	ctrl->d_hsync_cp1 = 0;
+	ctrl->d_vsync_fram = 0;
+	ctrl->d_de_cp2 = 7;
+
+	/* HFP + HSW + HBP + AVWidth-VSCLRPIXEL- 1; */
+	ctrl->vs_start_offset = (sync->h_front_porch + sync->h_sync_width +
+				 sync->h_back_porch + sync->h_active_len - 1);
+	ctrl->vs_end_offset = 0;
+
+	/* HFP + HSW + HBP + AVWidth-EVENVSCLRPIXEL- 1 */
+	ctrl->ev_start_offset = (sync->h_front_porch + sync->h_sync_width +
+				 sync->h_back_porch + sync->h_active_len - 1);
+	ctrl->ev_end_offset = 0;
+	debug("%s: preset: %d\n", __func__, preset);
+
+	return 0;
+}
+
+static void hdmi_clock(void)
+{
+	void *base =
+	    __io_address(nx_disp_top_clkgen_get_physical_address
+			 (to_mipi_clkgen));
+
+	nx_disp_top_clkgen_set_base_address(to_mipi_clkgen, base);
+	nx_disp_top_clkgen_set_clock_divisor_enable(to_mipi_clkgen, 0);
+	nx_disp_top_clkgen_set_clock_pclk_mode(to_mipi_clkgen,
+					       nx_pclkmode_always);
+	nx_disp_top_clkgen_set_clock_source(to_mipi_clkgen, HDMI_SPDIF_CLKOUT,
+					    2);
+	nx_disp_top_clkgen_set_clock_divisor(to_mipi_clkgen, HDMI_SPDIF_CLKOUT,
+					     2);
+	nx_disp_top_clkgen_set_clock_source(to_mipi_clkgen, 1, 7);
+	nx_disp_top_clkgen_set_clock_divisor_enable(to_mipi_clkgen, 1);
+
+	/* must initialize this !!! */
+	nx_disp_top_hdmi_set_vsync_hsstart_end(0, 0);
+	nx_disp_top_hdmi_set_vsync_start(0);
+	nx_disp_top_hdmi_set_hactive_start(0);
+	nx_disp_top_hdmi_set_hactive_end(0);
+}
+
+static void hdmi_vsync(struct dp_sync_info *sync)
+{
+	int width = sync->h_active_len;
+	int hsw = sync->h_sync_width;
+	int hbp = sync->h_back_porch;
+	int height = sync->v_active_len;
+	int vsw = sync->v_sync_width;
+	int vbp = sync->v_back_porch;
+
+	int v_sync_s = vsw + vbp + height - 1;
+	int h_active_s = hsw + hbp;
+	int h_active_e = width + hsw + hbp;
+	int v_sync_hs_se0 = hsw + hbp + 1;
+	int v_sync_hs_se1 = hsw + hbp + 2;
+
+	nx_disp_top_hdmi_set_vsync_start(v_sync_s);
+	nx_disp_top_hdmi_set_hactive_start(h_active_s);
+	nx_disp_top_hdmi_set_hactive_end(h_active_e);
+	nx_disp_top_hdmi_set_vsync_hsstart_end(v_sync_hs_se0, v_sync_hs_se1);
+}
+
+static int hdmi_prepare(struct dp_sync_info *sync)
+{
+	int width = sync->h_active_len;
+	int hsw = sync->h_sync_width;
+	int hfp = sync->h_front_porch;
+	int hbp = sync->h_back_porch;
+	int height = sync->v_active_len;
+	int vsw = sync->v_sync_width;
+	int vfp = sync->v_front_porch;
+	int vbp = sync->v_back_porch;
+
+	u32 h_blank, h_line, h_sync_start, h_sync_end;
+	u32 v_blank, v2_blank, v_line;
+	u32 v_sync_line_bef_1, v_sync_line_bef_2;
+
+	u32 fixed_ffff = 0xffff;
+
+	/* calculate sync variables */
+	h_blank = hfp + hsw + hbp;
+	v_blank = vfp + vsw + vbp;
+	v2_blank = height + vfp + vsw + vbp;
+	v_line = height + vfp + vsw + vbp;	/* total v */
+	h_line = width + hfp + hsw + hbp;	/* total h */
+	h_sync_start = hfp;
+	h_sync_end = hfp + hsw;
+	v_sync_line_bef_1 = vfp;
+	v_sync_line_bef_2 = vfp + vsw;
+
+	/* no blue screen mode, encoding order as it is */
+	nx_hdmi_set_reg(0, HDMI_LINK_HDMI_CON_0, (0 << 5) | (1 << 4));
+
+	/* set HDMI_LINK_BLUE_SCREEN_* to 0x0 */
+	nx_hdmi_set_reg(0, HDMI_LINK_BLUE_SCREEN_R_0, 0x5555);
+	nx_hdmi_set_reg(0, HDMI_LINK_BLUE_SCREEN_R_1, 0x5555);
+	nx_hdmi_set_reg(0, HDMI_LINK_BLUE_SCREEN_G_0, 0x5555);
+	nx_hdmi_set_reg(0, HDMI_LINK_BLUE_SCREEN_G_1, 0x5555);
+	nx_hdmi_set_reg(0, HDMI_LINK_BLUE_SCREEN_B_0, 0x5555);
+	nx_hdmi_set_reg(0, HDMI_LINK_BLUE_SCREEN_B_1, 0x5555);
+
+	/* set HDMI_CON_1 to 0x0 */
+	nx_hdmi_set_reg(0, HDMI_LINK_HDMI_CON_1, 0x0);
+	nx_hdmi_set_reg(0, HDMI_LINK_HDMI_CON_2, 0x0);
+
+	/* set interrupt : enable hpd_plug, hpd_unplug */
+	nx_hdmi_set_reg(0, HDMI_LINK_INTC_CON_0,
+			(1 << 6) | (1 << 3) | (1 << 2));
+
+	/* set STATUS_EN to 0x17 */
+	nx_hdmi_set_reg(0, HDMI_LINK_STATUS_EN, 0x17);
+
+	/* TODO set HDP to 0x0 : later check hpd */
+	nx_hdmi_set_reg(0, HDMI_LINK_HPD, 0x0);
+
+	/* set MODE_SEL to 0x02 */
+	nx_hdmi_set_reg(0, HDMI_LINK_MODE_SEL, 0x2);
+
+	/* set H_BLANK_*, V1_BLANK_*, V2_BLANK_*, V_LINE_*,
+	 * H_LINE_*, H_SYNC_START_*, H_SYNC_END_ *
+	 * V_SYNC_LINE_BEF_1_*, V_SYNC_LINE_BEF_2_*
+	 */
+	nx_hdmi_set_reg(0, HDMI_LINK_H_BLANK_0, h_blank % 256);
+	nx_hdmi_set_reg(0, HDMI_LINK_H_BLANK_1, h_blank >> 8);
+	nx_hdmi_set_reg(0, HDMI_LINK_V1_BLANK_0, v_blank % 256);
+	nx_hdmi_set_reg(0, HDMI_LINK_V1_BLANK_1, v_blank >> 8);
+	nx_hdmi_set_reg(0, HDMI_LINK_V2_BLANK_0, v2_blank % 256);
+	nx_hdmi_set_reg(0, HDMI_LINK_V2_BLANK_1, v2_blank >> 8);
+	nx_hdmi_set_reg(0, HDMI_LINK_V_LINE_0, v_line % 256);
+	nx_hdmi_set_reg(0, HDMI_LINK_V_LINE_1, v_line >> 8);
+	nx_hdmi_set_reg(0, HDMI_LINK_H_LINE_0, h_line % 256);
+	nx_hdmi_set_reg(0, HDMI_LINK_H_LINE_1, h_line >> 8);
+
+	if (width == 1280) {
+		nx_hdmi_set_reg(0, HDMI_LINK_HSYNC_POL, 0x1);
+		nx_hdmi_set_reg(0, HDMI_LINK_VSYNC_POL, 0x1);
+	} else {
+		nx_hdmi_set_reg(0, HDMI_LINK_HSYNC_POL, 0x0);
+		nx_hdmi_set_reg(0, HDMI_LINK_VSYNC_POL, 0x0);
+	}
+
+	nx_hdmi_set_reg(0, HDMI_LINK_INT_PRO_MODE, 0x0);
+
+	nx_hdmi_set_reg(0, HDMI_LINK_H_SYNC_START_0, (h_sync_start % 256) - 2);
+	nx_hdmi_set_reg(0, HDMI_LINK_H_SYNC_START_1, h_sync_start >> 8);
+	nx_hdmi_set_reg(0, HDMI_LINK_H_SYNC_END_0, (h_sync_end % 256) - 2);
+	nx_hdmi_set_reg(0, HDMI_LINK_H_SYNC_END_1, h_sync_end >> 8);
+	nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_BEF_1_0,
+			v_sync_line_bef_1 % 256);
+	nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_BEF_1_1,
+			v_sync_line_bef_1 >> 8);
+	nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_BEF_2_0,
+			v_sync_line_bef_2 % 256);
+	nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_BEF_2_1,
+			v_sync_line_bef_2 >> 8);
+
+	/* Set V_SYNC_LINE_AFT*, V_SYNC_LINE_AFT_PXL*, VACT_SPACE* */
+	nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_1_0, fixed_ffff % 256);
+	nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_1_1, fixed_ffff >> 8);
+	nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_2_0, fixed_ffff % 256);
+	nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_2_1, fixed_ffff >> 8);
+	nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_3_0, fixed_ffff % 256);
+	nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_3_1, fixed_ffff >> 8);
+	nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_4_0, fixed_ffff % 256);
+	nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_4_1, fixed_ffff >> 8);
+	nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_5_0, fixed_ffff % 256);
+	nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_5_1, fixed_ffff >> 8);
+	nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_6_0, fixed_ffff % 256);
+	nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_6_1, fixed_ffff >> 8);
+
+	nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_1_0, fixed_ffff % 256);
+	nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_1_1, fixed_ffff >> 8);
+	nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_2_0, fixed_ffff % 256);
+	nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_2_1, fixed_ffff >> 8);
+	nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_3_0, fixed_ffff % 256);
+	nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_3_1, fixed_ffff >> 8);
+	nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_4_0, fixed_ffff % 256);
+	nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_4_1, fixed_ffff >> 8);
+	nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_5_0, fixed_ffff % 256);
+	nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_5_1, fixed_ffff >> 8);
+	nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_6_0, fixed_ffff % 256);
+	nx_hdmi_set_reg(0, HDMI_LINK_V_SYNC_LINE_AFT_PXL_6_1, fixed_ffff >> 8);
+
+	nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE1_0, fixed_ffff % 256);
+	nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE1_1, fixed_ffff >> 8);
+	nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE2_0, fixed_ffff % 256);
+	nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE2_1, fixed_ffff >> 8);
+	nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE3_0, fixed_ffff % 256);
+	nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE3_1, fixed_ffff >> 8);
+	nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE4_0, fixed_ffff % 256);
+	nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE4_1, fixed_ffff >> 8);
+	nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE5_0, fixed_ffff % 256);
+	nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE5_1, fixed_ffff >> 8);
+	nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE6_0, fixed_ffff % 256);
+	nx_hdmi_set_reg(0, HDMI_LINK_VACT_SPACE6_1, fixed_ffff >> 8);
+
+	nx_hdmi_set_reg(0, HDMI_LINK_CSC_MUX, 0x0);
+	nx_hdmi_set_reg(0, HDMI_LINK_SYNC_GEN_MUX, 0x0);
+
+	nx_hdmi_set_reg(0, HDMI_LINK_SEND_START_0, 0xfd);
+	nx_hdmi_set_reg(0, HDMI_LINK_SEND_START_1, 0x01);
+	nx_hdmi_set_reg(0, HDMI_LINK_SEND_END_0, 0x0d);
+	nx_hdmi_set_reg(0, HDMI_LINK_SEND_END_1, 0x3a);
+	nx_hdmi_set_reg(0, HDMI_LINK_SEND_END_2, 0x08);
+
+	/* Set DC_CONTROL to 0x00 */
+	nx_hdmi_set_reg(0, HDMI_LINK_DC_CONTROL, 0x0);
+
+#if CONFIG_HDMI_PATTERN
+	nx_hdmi_set_reg(0, HDMI_LINK_VIDEO_PATTERN_GEN, 0x1);
+#else
+	nx_hdmi_set_reg(0, HDMI_LINK_VIDEO_PATTERN_GEN, 0x0);
+#endif
+
+	nx_hdmi_set_reg(0, HDMI_LINK_GCP_CON, 0x0a);
+	return 0;
+}
+
+static void hdmi_init(void)
+{
+	void *base;
+   /**
+    * [SEQ 2] set the HDMI CLKGEN's PCLKMODE to always enabled
+    */
+	base =
+	    __io_address(nx_disp_top_clkgen_get_physical_address(hdmi_clkgen));
+	nx_disp_top_clkgen_set_base_address(hdmi_clkgen, base);
+	nx_disp_top_clkgen_set_clock_pclk_mode(hdmi_clkgen, nx_pclkmode_always);
+
+	base = __io_address(nx_hdmi_get_physical_address(0));
+	nx_hdmi_set_base_address(0, base);
+
+    /**
+     * [SEQ 3] set the 0xC001100C[0] to 1
+     */
+	nx_tieoff_set(NX_TIEOFF_DISPLAYTOP0_i_HDMI_PHY_REFCLK_SEL, 1);
+
+    /**
+     * [SEQ 4] release the resets of HDMI.i_PHY_nRST and HDMI.i_nRST
+     */
+	nx_rstcon_setrst(RESET_ID_HDMI_PHY, RSTCON_ASSERT);
+	nx_rstcon_setrst(RESET_ID_HDMI, RSTCON_ASSERT);
+	nx_rstcon_setrst(RESET_ID_HDMI_PHY, RSTCON_NEGATE);
+	nx_rstcon_setrst(RESET_ID_HDMI, RSTCON_NEGATE);
+}
+
+void hdmi_enable(int input, int preset, struct dp_sync_info *sync, int enable)
+{
+	if (enable) {
+		nx_hdmi_set_reg(0, HDMI_LINK_HDMI_CON_0,
+				(nx_hdmi_get_reg(0, HDMI_LINK_HDMI_CON_0) |
+				 0x1));
+		hdmi_vsync(sync);
+	} else {
+		hdmi_phy_enable(preset, 0);
+	}
+}
+
+static int hdmi_setup(int input, int preset,
+		      struct dp_sync_info *sync, struct dp_ctrl_info *ctrl)
+{
+	u32 HDMI_SEL = 0;
+	int ret;
+
+	switch (input) {
+	case DP_DEVICE_DP0:
+		HDMI_SEL = primary_mlc;
+		break;
+	case DP_DEVICE_DP1:
+		HDMI_SEL = secondary_mlc;
+		break;
+	case DP_DEVICE_RESCONV:
+		HDMI_SEL = resolution_conv;
+		break;
+	default:
+		printf("HDMI: not support source device %d\n", input);
+		return -EINVAL;
+	}
+
+	/**
+	 * [SEQ 5] set up the HDMI PHY to specific video clock.
+	 */
+	ret = hdmi_phy_enable(preset, 1);
+	if (ret < 0)
+		return ret;
+
+	/**
+	 * [SEQ 6] I2S (or SPDIFTX) configuration for the source audio data
+	 * this is done in another user app  - ex> Android Audio HAL
+	 */
+
+	/**
+	 * [SEQ 7] Wait for ECID ready
+	 */
+
+	/**
+	 * [SEQ 8] release the resets of HDMI.i_VIDEO_nRST and HDMI.i_SPDIF_nRST
+	 * and HDMI.i_TMDS_nRST
+	 */
+	hdmi_reset();
+
+	/**
+	 * [SEQ 9] Wait for HDMI PHY ready (wait until 0xC0200020.[0], 1)
+	 */
+	if (hdmi_wait_phy_ready() == 0) {
+		printf("%s: failed to wait for hdmiphy ready\n", __func__);
+		hdmi_phy_enable(preset, 0);
+		return -EIO;
+	}
+	/* set mux */
+	nx_disp_top_set_hdmimux(1, HDMI_SEL);
+
+	/**
+	 * [SEC 10] Set the DPC CLKGEN's Source Clock to HDMI_CLK &
+	 * Set Sync Parameter
+	 */
+	hdmi_clock();
+	/* set hdmi link clk to clkgen  vs default is hdmi phy clk */
+
+	/**
+	 * [SEQ 11] Set up the HDMI Converter parameters
+	 */
+	hdmi_get_vsync(preset, sync, ctrl);
+	hdmi_prepare(sync);
+
+	return 0;
+}
+
+void nx_hdmi_display(int module,
+		     struct dp_sync_info *sync, struct dp_ctrl_info *ctrl,
+		     struct dp_plane_top *top, struct dp_plane_info *planes,
+		     struct dp_hdmi_dev *dev)
+{
+	struct dp_plane_info *plane = planes;
+	int input = module == 0 ? DP_DEVICE_DP0 : DP_DEVICE_DP1;
+	int count = top->plane_num;
+	int preset = dev->preset;
+	int i = 0;
+
+	debug("HDMI:  display.%d\n", module);
+
+	switch (preset) {
+	case 0:
+		top->screen_width = 1280;
+		top->screen_height = 720;
+		sync->h_active_len = 1280;
+		sync->v_active_len = 720;
+		break;
+	case 1:
+		top->screen_width = 1920;
+		top->screen_height = 1080;
+		sync->h_active_len = 1920;
+		sync->v_active_len = 1080;
+		break;
+	default:
+		printf("hdmi not support preset %d\n", preset);
+		return;
+	}
+
+	printf("HDMI:  display.%d, preset %d (%4d * %4d)\n",
+	       module, preset, top->screen_width, top->screen_height);
+
+	dp_control_init(module);
+	dp_plane_init(module);
+
+	hdmi_init();
+	hdmi_setup(input, preset, sync, ctrl);
+
+	dp_plane_screen_setup(module, top);
+	for (i = 0; count > i; i++, plane++) {
+		if (!plane->enable)
+			continue;
+		dp_plane_layer_setup(module, plane);
+		dp_plane_layer_enable(module, plane, 1);
+	}
+	dp_plane_screen_enable(module, 1);
+
+	dp_control_setup(module, sync, ctrl);
+	dp_control_enable(module, 1);
+
+	hdmi_enable(input, preset, sync, 1);
+}
diff --git a/drivers/video/nexell/s5pxx18_dp_lvds.c b/drivers/video/nexell/s5pxx18_dp_lvds.c
new file mode 100644
index 0000000..f8ea63f
--- /dev/null
+++ b/drivers/video/nexell/s5pxx18_dp_lvds.c
@@ -0,0 +1,274 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2016  Nexell Co., Ltd.
+ *
+ * Author: junghyun, kim <jhkim@nexell.co.kr>
+ */
+
+#include <config.h>
+#include <common.h>
+#include <errno.h>
+
+#include <asm/arch/nexell.h>
+#include <asm/arch/reset.h>
+#include <asm/arch/display.h>
+
+#include "soc/s5pxx18_soc_lvds.h"
+#include "soc/s5pxx18_soc_disptop.h"
+#include "soc/s5pxx18_soc_disptop_clk.h"
+
+#define	__io_address(a)	(void *)(uintptr_t)(a)
+
+static void lvds_phy_reset(void)
+{
+	nx_rstcon_setrst(RESET_ID_LVDS, RSTCON_ASSERT);
+	nx_rstcon_setrst(RESET_ID_LVDS, RSTCON_NEGATE);
+}
+
+static void lvds_init(void)
+{
+	int clkid = DP_CLOCK_LVDS;
+	int index = 0;
+	void *base;
+
+	base = __io_address(nx_disp_top_clkgen_get_physical_address(clkid));
+	nx_disp_top_clkgen_set_base_address(clkid, base);
+
+	nx_lvds_initialize();
+
+	for (index = 0; nx_lvds_get_number_of_module() > index; index++)
+		nx_lvds_set_base_address(index,
+		  (void *)__io_address(nx_lvds_get_physical_address(index)));
+
+	nx_disp_top_clkgen_set_clock_pclk_mode(clkid, nx_pclkmode_always);
+}
+
+static void lvds_enable(int enable)
+{
+	int clkid = DP_CLOCK_LVDS;
+	int on = (enable ? 1 : 0);
+
+	nx_disp_top_clkgen_set_clock_divisor_enable(clkid, on);
+}
+
+static int lvds_setup(int module, int input,
+		      struct dp_sync_info *sync, struct dp_ctrl_info *ctrl,
+		      struct dp_lvds_dev *dev)
+{
+	unsigned int val;
+	int clkid = DP_CLOCK_LVDS;
+	enum dp_lvds_format format = DP_LVDS_FORMAT_JEIDA;
+	u32 voltage = DEF_VOLTAGE_LEVEL;
+
+	if (dev) {
+		format = dev->lvds_format;
+		voltage = dev->voltage_level;
+	}
+
+	printf("LVDS:  ");
+	printf("%s, ", format == DP_LVDS_FORMAT_VESA ? "VESA" :
+		format == DP_LVDS_FORMAT_JEIDA ? "JEIDA" : "LOC");
+	printf("voltage LV:0x%x\n", voltage);
+
+	/*
+	 *-------- predefined type.
+	 * only change iTA to iTE in VESA mode
+	 * wire [34:0] loc_VideoIn =
+	 * {4'hf, 4'h0, i_VDEN, i_VSYNC, i_HSYNC, i_VD[23:0] };
+	 */
+	u32 VSYNC = 25;
+	u32 HSYNC = 24;
+	u32 VDEN  = 26; /* bit position */
+	u32 ONE   = 34;
+	u32 ZERO  = 27;
+
+	/*====================================================
+	 * current not use location mode
+	 *====================================================
+	 */
+	u32 LOC_A[7] = {ONE, ONE, ONE, ONE, ONE, ONE, ONE};
+	u32 LOC_B[7] = {ONE, ONE, ONE, ONE, ONE, ONE, ONE};
+	u32 LOC_C[7] = {VDEN, VSYNC, HSYNC, ONE, HSYNC, VSYNC, VDEN};
+	u32 LOC_D[7] = {ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO};
+	u32 LOC_E[7] = {ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO};
+
+	switch (input) {
+	case DP_DEVICE_DP0:
+		input = 0;
+		break;
+	case DP_DEVICE_DP1:
+		input = 1;
+		break;
+	case DP_DEVICE_RESCONV:
+		input = 2;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/*
+	 * select TOP MUX
+	 */
+	nx_disp_top_clkgen_set_clock_divisor_enable(clkid, 0);
+	nx_disp_top_clkgen_set_clock_source(clkid, 0, ctrl->clk_src_lv0);
+	nx_disp_top_clkgen_set_clock_divisor(clkid, 0, ctrl->clk_div_lv0);
+	nx_disp_top_clkgen_set_clock_source(clkid, 1, ctrl->clk_src_lv1);
+	nx_disp_top_clkgen_set_clock_divisor(clkid, 1, ctrl->clk_div_lv1);
+
+	/*
+	 * LVDS Control Pin Setting
+	 */
+	val = (0 << 30) |      /* CPU_I_VBLK_FLAG_SEL */
+	      (0 << 29) |      /* CPU_I_BVLK_FLAG */
+	      (1 << 28) |      /* SKINI_BST  */
+	      (1 << 27) |      /* DLYS_BST  */
+	      (0 << 26) |      /* I_AUTO_SEL */
+	      (format << 19) | /* JEiDA data packing */
+	      (0x1B << 13)   | /* I_LOCK_PPM_SET, PPM setting for PLL lock */
+	      (0x638 << 1);    /* I_DESKEW_CNT_SEL, period of de-skew region */
+	nx_lvds_set_lvdsctrl0(0, val);
+
+	val = (0 << 28) |   /* I_ATE_MODE, function mode */
+	      (0 << 27) |   /* I_TEST_CON_MODE, DA (test ctrl mode) */
+	      (0 << 24) |   /* I_TX4010X_DUMMY */
+	      (0 << 15) |   /* SKCCK 0 */
+	      (0 << 12) |   /* SKC4 (TX output skew control pin at ODD ch4) */
+	      (0 << 9)  |   /* SKC3 (TX output skew control pin at ODD ch3) */
+	      (0 << 6)  |   /* SKC2 (TX output skew control pin at ODD ch2) */
+	      (0 << 3)  |   /* SKC1 (TX output skew control pin at ODD ch1) */
+	      (0 << 0);     /* SKC0 (TX output skew control pin@ODD ch0) */
+	nx_lvds_set_lvdsctrl1(0, val);
+
+	val = (0 << 15)   | /* CK_POL_SEL, Input clock, bypass */
+	      (0 << 14)   | /* VSEL, VCO Freq. range. 0: Low(40MHz~90MHz),
+			     *                        1: High(90MHz~160MHz) */
+	      (0x1 << 12) | /* S (Post-scaler) */
+	      (0xA << 6)  | /* M (Main divider) */
+	      (0xA << 0);   /* P (Pre-divider) */
+
+	nx_lvds_set_lvdsctrl2(0, val);
+	val = (0x03 << 6) | /* SK_BIAS, Bias current ctrl pin */
+	      (0 << 5)    | /* SKEWINI, skew selection pin, 0: bypass,
+			     *                              1: skew enable */
+	      (0 << 4)    | /* SKEW_EN_H, skew block power down, 0: power down,
+			     *                                   1: operating */
+	      (1 << 3)    | /* CNTB_TDLY, delay control pin */
+	      (0 << 2)    | /* SEL_DATABF, input clock 1/2 division cont. pin */
+	      (0x3 << 0);   /* SKEW_REG_CUR, regulator bias current selection
+			     *               in SKEW block */
+
+	nx_lvds_set_lvdsctrl3(0, val);
+	val = (0 << 28)   | /* FLT_CNT, filter control pin for PLL */
+	      (0 << 27)   | /* VOD_ONLY_CNT, the pre-emphasis's pre-diriver
+			     *               control pin (VOD only) */
+	      (0 << 26)   | /* CNNCT_MODE_SEL, connectivity mode selection,
+			     *                 0:TX operating, 1:con check */
+	      (0 << 24)   | /* CNNCT_CNT, connectivity ctrl pin,
+			     *            0: tx operating, 1: con check */
+	      (0 << 23)   | /* VOD_HIGH_S, VOD control pin, 1: Vod only */
+	      (0 << 22)   | /* SRC_TRH, source termination resistor sel. pin */
+	      (voltage << 14) |
+	      (0x01 << 6) | /* CNT_PEN_H, TX driver pre-emphasis level cont. */
+	      (0x4 << 3)  | /* FC_CODE, vos control pin */
+	      (0 << 2)    | /* OUTCON, TX Driver state selectioin pin, 0:Hi-z,
+			     *                                         1:Low */
+	      (0 << 1)    | /* LOCK_CNT, Lock signal selection pin, enable */
+	      (0 << 0);     /* AUTO_DSK_SEL, auto deskew sel. pin, normal */
+	nx_lvds_set_lvdsctrl4(0, val);
+
+	val = (0 << 24) |   /* I_BIST_RESETB */
+	      (0 << 23) |   /* I_BIST_EN */
+	      (0 << 21) |   /* I_BIST_PAT_SEL */
+	      (0 << 14) |   /* I_BIST_USER_PATTERN */
+	      (0 << 13) |   /* I_BIST_FORCE_ERROR */
+	      (0 << 7)  |   /* I_BIST_SKEW_CTRL */
+	      (0 << 5)  |   /* I_BIST_CLK_INV */
+	      (0 << 3)  |   /* I_BIST_DATA_INV */
+	      (0 << 0);     /* I_BIST_CH_SEL */
+	nx_lvds_set_lvdstmode0(0, val);
+
+	/* user do not need to modify this codes. */
+	val = (LOC_A[4] << 24) | (LOC_A[3] << 18) | (LOC_A[2] << 12) |
+	      (LOC_A[1] << 6)  | (LOC_A[0] << 0);
+	nx_lvds_set_lvdsloc0(0, val);
+
+	val = (LOC_B[2] << 24) | (LOC_B[1] << 18) | (LOC_B[0] << 12) |
+	      (LOC_A[6] << 6)  | (LOC_A[5] << 0);
+	nx_lvds_set_lvdsloc1(0, val);
+
+	val = (LOC_C[0] << 24) | (LOC_B[6] << 18) | (LOC_B[5] << 12) |
+	      (LOC_B[4] << 6)  | (LOC_B[3] << 0);
+	nx_lvds_set_lvdsloc2(0, val);
+
+	val = (LOC_C[5] << 24) | (LOC_C[4] << 18) | (LOC_C[3] << 12) |
+	      (LOC_C[2] << 6)  | (LOC_C[1] << 0);
+	nx_lvds_set_lvdsloc3(0, val);
+
+	val = (LOC_D[3] << 24) | (LOC_D[2] << 18) | (LOC_D[1] << 12) |
+	      (LOC_D[0] << 6)  | (LOC_C[6] << 0);
+	nx_lvds_set_lvdsloc4(0, val);
+
+	val = (LOC_E[1] << 24) | (LOC_E[0] << 18) | (LOC_D[6] << 12) |
+	      (LOC_D[5] << 6)  | (LOC_D[4] << 0);
+	nx_lvds_set_lvdsloc5(0, val);
+
+	val = (LOC_E[6] << 24) | (LOC_E[5] << 18) | (LOC_E[4] << 12) |
+	      (LOC_E[3] << 6)  | (LOC_E[2] << 0);
+	nx_lvds_set_lvdsloc6(0, val);
+
+	nx_lvds_set_lvdslocmask0(0, 0xffffffff);
+	nx_lvds_set_lvdslocmask1(0, 0xffffffff);
+
+	nx_lvds_set_lvdslocpol0(0, (0 << 19) | (0 << 18));
+
+	/*
+	 * select TOP MUX
+	 */
+	nx_disp_top_set_lvdsmux(1, input);
+
+	/*
+	 * LVDS PHY Reset, make sure last.
+	 */
+	lvds_phy_reset();
+
+	return 0;
+}
+
+void nx_lvds_display(int module,
+		     struct dp_sync_info *sync, struct dp_ctrl_info *ctrl,
+		     struct dp_plane_top *top, struct dp_plane_info *planes,
+		     struct dp_lvds_dev *dev)
+{
+	struct dp_plane_info *plane = planes;
+	int input = module == 0 ? DP_DEVICE_DP0 : DP_DEVICE_DP1;
+	int count = top->plane_num;
+	int i = 0;
+
+	printf("LVDS:  dp.%d\n", module);
+
+	dp_control_init(module);
+	dp_plane_init(module);
+
+	lvds_init();
+
+	/* set plane */
+	dp_plane_screen_setup(module, top);
+
+	for (i = 0; count > i; i++, plane++) {
+		if (!plane->enable)
+			continue;
+		dp_plane_layer_setup(module, plane);
+		dp_plane_layer_enable(module, plane, 1);
+	}
+
+	dp_plane_screen_enable(module, 1);
+
+	/* set lvds */
+	lvds_setup(module, input, sync, ctrl, dev);
+
+	lvds_enable(1);
+
+	/* set dp control */
+	dp_control_setup(module, sync, ctrl);
+	dp_control_enable(module, 1);
+}
diff --git a/drivers/video/nexell/s5pxx18_dp_mipi.c b/drivers/video/nexell/s5pxx18_dp_mipi.c
new file mode 100644
index 0000000..670272b
--- /dev/null
+++ b/drivers/video/nexell/s5pxx18_dp_mipi.c
@@ -0,0 +1,677 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2016  Nexell Co., Ltd.
+ *
+ * Author: junghyun, kim <jhkim@nexell.co.kr>
+ */
+
+#include <config.h>
+#include <common.h>
+#include <errno.h>
+
+#include <asm/arch/nexell.h>
+#include <asm/arch/tieoff.h>
+#include <asm/arch/reset.h>
+#include <asm/arch/display.h>
+
+#include "soc/s5pxx18_soc_mipi.h"
+#include "soc/s5pxx18_soc_disptop.h"
+#include "soc/s5pxx18_soc_disptop_clk.h"
+
+#define	PLLPMS_1000MHZ		0x33E8
+#define	BANDCTL_1000MHZ		0xF
+#define PLLPMS_960MHZ       0x2280
+#define BANDCTL_960MHZ      0xF
+#define	PLLPMS_900MHZ		0x2258
+#define	BANDCTL_900MHZ		0xE
+#define	PLLPMS_840MHZ		0x2230
+#define	BANDCTL_840MHZ		0xD
+#define	PLLPMS_750MHZ		0x43E8
+#define	BANDCTL_750MHZ		0xC
+#define	PLLPMS_660MHZ		0x21B8
+#define	BANDCTL_660MHZ		0xB
+#define	PLLPMS_600MHZ		0x2190
+#define	BANDCTL_600MHZ		0xA
+#define	PLLPMS_540MHZ		0x2168
+#define	BANDCTL_540MHZ		0x9
+#define	PLLPMS_512MHZ		0x03200
+#define	BANDCTL_512MHZ		0x9
+#define	PLLPMS_480MHZ		0x2281
+#define	BANDCTL_480MHZ		0x8
+#define	PLLPMS_420MHZ		0x2231
+#define	BANDCTL_420MHZ		0x7
+#define	PLLPMS_402MHZ		0x2219
+#define	BANDCTL_402MHZ		0x7
+#define	PLLPMS_330MHZ		0x21B9
+#define	BANDCTL_330MHZ		0x6
+#define	PLLPMS_300MHZ		0x2191
+#define	BANDCTL_300MHZ		0x5
+#define	PLLPMS_210MHZ		0x2232
+#define	BANDCTL_210MHZ		0x4
+#define	PLLPMS_180MHZ		0x21E2
+#define	BANDCTL_180MHZ		0x3
+#define	PLLPMS_150MHZ		0x2192
+#define	BANDCTL_150MHZ		0x2
+#define	PLLPMS_100MHZ		0x3323
+#define	BANDCTL_100MHZ		0x1
+#define	PLLPMS_80MHZ		0x3283
+#define	BANDCTL_80MHZ		0x0
+
+#define	MIPI_INDEX		0
+#define MIPI_EXC_PRE_VALUE      1
+#define MIPI_DSI_IRQ_MASK       29
+
+#define	__io_address(a)	(void *)(uintptr_t)(a)
+
+struct mipi_xfer_msg {
+	u8 id, data[2];
+	u16 flags;
+	const u8 *tx_buf;
+	u16 tx_len;
+	u8 *rx_buf;
+	u16 rx_len;
+};
+
+static void mipi_reset(void)
+{
+	/* tieoff */
+	nx_tieoff_set(NX_TIEOFF_MIPI0_NX_DPSRAM_1R1W_EMAA, 3);
+	nx_tieoff_set(NX_TIEOFF_MIPI0_NX_DPSRAM_1R1W_EMAB, 3);
+
+	/* reset */
+	nx_rstcon_setrst(RESET_ID_MIPI, RSTCON_ASSERT);
+	nx_rstcon_setrst(RESET_ID_MIPI_DSI, RSTCON_ASSERT);
+	nx_rstcon_setrst(RESET_ID_MIPI_CSI, RSTCON_ASSERT);
+	nx_rstcon_setrst(RESET_ID_MIPI_PHY_S, RSTCON_ASSERT);
+	nx_rstcon_setrst(RESET_ID_MIPI_PHY_M, RSTCON_ASSERT);
+
+	nx_rstcon_setrst(RESET_ID_MIPI, RSTCON_NEGATE);
+	nx_rstcon_setrst(RESET_ID_MIPI_DSI, RSTCON_NEGATE);
+	nx_rstcon_setrst(RESET_ID_MIPI_PHY_S, RSTCON_NEGATE);
+	nx_rstcon_setrst(RESET_ID_MIPI_PHY_M, RSTCON_NEGATE);
+}
+
+static void mipi_init(void)
+{
+	int clkid = DP_CLOCK_MIPI;
+	void *base;
+
+	/*
+	 * neet to reset before open
+	 */
+	mipi_reset();
+
+	base = __io_address(nx_disp_top_clkgen_get_physical_address(clkid));
+	nx_disp_top_clkgen_set_base_address(clkid, base);
+	nx_disp_top_clkgen_set_clock_pclk_mode(clkid, nx_pclkmode_always);
+
+	base = __io_address(nx_mipi_get_physical_address(0));
+	nx_mipi_set_base_address(0, base);
+}
+
+static int mipi_get_phy_pll(int bitrate, unsigned int *pllpms,
+			    unsigned int *bandctl)
+{
+	unsigned int pms, ctl;
+
+	switch (bitrate) {
+	case 1000:
+		pms = PLLPMS_1000MHZ;
+		ctl = BANDCTL_1000MHZ;
+		break;
+	case 960:
+		pms = PLLPMS_960MHZ;
+		ctl = BANDCTL_960MHZ;
+		break;
+	case 900:
+		pms = PLLPMS_900MHZ;
+		ctl = BANDCTL_900MHZ;
+		break;
+	case 840:
+		pms = PLLPMS_840MHZ;
+		ctl = BANDCTL_840MHZ;
+		break;
+	case 750:
+		pms = PLLPMS_750MHZ;
+		ctl = BANDCTL_750MHZ;
+		break;
+	case 660:
+		pms = PLLPMS_660MHZ;
+		ctl = BANDCTL_660MHZ;
+		break;
+	case 600:
+		pms = PLLPMS_600MHZ;
+		ctl = BANDCTL_600MHZ;
+		break;
+	case 540:
+		pms = PLLPMS_540MHZ;
+		ctl = BANDCTL_540MHZ;
+		break;
+	case 512:
+		pms = PLLPMS_512MHZ;
+		ctl = BANDCTL_512MHZ;
+		break;
+	case 480:
+		pms = PLLPMS_480MHZ;
+		ctl = BANDCTL_480MHZ;
+		break;
+	case 420:
+		pms = PLLPMS_420MHZ;
+		ctl = BANDCTL_420MHZ;
+		break;
+	case 402:
+		pms = PLLPMS_402MHZ;
+		ctl = BANDCTL_402MHZ;
+		break;
+	case 330:
+		pms = PLLPMS_330MHZ;
+		ctl = BANDCTL_330MHZ;
+		break;
+	case 300:
+		pms = PLLPMS_300MHZ;
+		ctl = BANDCTL_300MHZ;
+		break;
+	case 210:
+		pms = PLLPMS_210MHZ;
+		ctl = BANDCTL_210MHZ;
+		break;
+	case 180:
+		pms = PLLPMS_180MHZ;
+		ctl = BANDCTL_180MHZ;
+		break;
+	case 150:
+		pms = PLLPMS_150MHZ;
+		ctl = BANDCTL_150MHZ;
+		break;
+	case 100:
+		pms = PLLPMS_100MHZ;
+		ctl = BANDCTL_100MHZ;
+		break;
+	case 80:
+		pms = PLLPMS_80MHZ;
+		ctl = BANDCTL_80MHZ;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	*pllpms = pms;
+	*bandctl = ctl;
+
+	return 0;
+}
+
+static int mipi_prepare(int module, int input,
+			struct dp_sync_info *sync, struct dp_ctrl_info *ctrl,
+			struct dp_mipi_dev *mipi)
+{
+	int index = MIPI_INDEX;
+	u32 esc_pre_value = MIPI_EXC_PRE_VALUE;
+	int lpm = mipi->lpm_trans;
+	int ret = 0;
+
+	ret = mipi_get_phy_pll(mipi->hs_bitrate,
+			       &mipi->hs_pllpms, &mipi->hs_bandctl);
+	if (ret < 0)
+		return ret;
+
+	ret = mipi_get_phy_pll(mipi->lp_bitrate,
+			       &mipi->lp_pllpms, &mipi->lp_bandctl);
+	if (ret < 0)
+		return ret;
+
+	debug("%s: mipi lp:%dmhz:0x%x:0x%x, hs:%dmhz:0x%x:0x%x, %s trans\n",
+	      __func__, mipi->lp_bitrate, mipi->lp_pllpms, mipi->lp_bandctl,
+	      mipi->hs_bitrate, mipi->hs_pllpms, mipi->hs_bandctl,
+	      lpm ? "low" : "high");
+
+	if (lpm)
+		nx_mipi_dsi_set_pll(index, 1, 0xFFFFFFFF,
+				    mipi->lp_pllpms, mipi->lp_bandctl, 0, 0);
+	else
+		nx_mipi_dsi_set_pll(index, 1, 0xFFFFFFFF,
+				    mipi->hs_pllpms, mipi->hs_bandctl, 0, 0);
+
+#ifdef CONFIG_ARCH_S5P4418
+	/*
+	 * disable the escape clock generating prescaler
+	 * before soft reset.
+	 */
+	nx_mipi_dsi_set_clock(index, 0, 0, 1, 1, 1, 0, 0, 0, 0, 10);
+	mdelay(1);
+#endif
+
+	nx_mipi_dsi_software_reset(index);
+	nx_mipi_dsi_set_clock(index, 0, 0, 1, 1, 1, 0, 0, 0, 1, esc_pre_value);
+	nx_mipi_dsi_set_phy(index, 0, 1, 1, 0, 0, 0, 0, 0);
+
+	if (lpm)
+		nx_mipi_dsi_set_escape_lp(index, nx_mipi_dsi_lpmode_lp,
+					  nx_mipi_dsi_lpmode_lp);
+	else
+		nx_mipi_dsi_set_escape_lp(index, nx_mipi_dsi_lpmode_hs,
+					  nx_mipi_dsi_lpmode_hs);
+	mdelay(20);
+
+	return 0;
+}
+
+static int mipi_enable(int module, int input,
+		       struct dp_sync_info *sync, struct dp_ctrl_info *ctrl,
+		       struct dp_mipi_dev *mipi)
+{
+	struct mipi_dsi_device *dsi = &mipi->dsi;
+	int clkid = DP_CLOCK_MIPI;
+	int index = MIPI_INDEX;
+	int width = sync->h_active_len;
+	int height = sync->v_active_len;
+	int HFP = sync->h_front_porch;
+	int HBP = sync->h_back_porch;
+	int HS = sync->h_sync_width;
+	int VFP = sync->v_front_porch;
+	int VBP = sync->v_back_porch;
+	int VS = sync->v_sync_width;
+	int en_prescaler = 1;
+	u32 esc_pre_value = MIPI_EXC_PRE_VALUE;
+
+	int txhsclock = 1;
+	int lpm = mipi->lpm_trans;
+	bool command_mode = mipi->command_mode;
+
+	enum nx_mipi_dsi_format dsi_format;
+	int data_len = dsi->lanes - 1;
+	bool burst = dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST ? true : false;
+	bool eot_enable = dsi->mode_flags & MIPI_DSI_MODE_EOT_PACKET ?
+	    false : true;
+
+	/*
+	 * disable the escape clock generating prescaler
+	 * before soft reset.
+	 */
+#ifdef CONFIG_ARCH_S5P4418
+	en_prescaler = 0;
+#endif
+
+	debug("%s: mode:%s, lanes.%d\n", __func__,
+	      command_mode ? "command" : "video", data_len + 1);
+
+	if (lpm)
+		nx_mipi_dsi_set_escape_lp(index,
+					  nx_mipi_dsi_lpmode_hs,
+					  nx_mipi_dsi_lpmode_hs);
+
+	nx_mipi_dsi_set_pll(index, 1, 0xFFFFFFFF,
+			    mipi->hs_pllpms, mipi->hs_bandctl, 0, 0);
+	mdelay(1);
+
+	nx_mipi_dsi_set_clock(index, 0, 0, 1, 1, 1, 0, 0, 0, en_prescaler, 10);
+	mdelay(1);
+
+	nx_mipi_dsi_software_reset(index);
+	nx_mipi_dsi_set_clock(index, txhsclock, 0, 1,
+			      1, 1, 0, 0, 0, 1, esc_pre_value);
+
+	switch (data_len) {
+	case 0:		/* 1 lane */
+		nx_mipi_dsi_set_phy(index, data_len, 1, 1, 0, 0, 0, 0, 0);
+		break;
+	case 1:		/* 2 lane */
+		nx_mipi_dsi_set_phy(index, data_len, 1, 1, 1, 0, 0, 0, 0);
+		break;
+	case 2:		/* 3 lane */
+		nx_mipi_dsi_set_phy(index, data_len, 1, 1, 1, 1, 0, 0, 0);
+		break;
+	case 3:		/* 3 lane */
+		nx_mipi_dsi_set_phy(index, data_len, 1, 1, 1, 1, 1, 0, 0);
+		break;
+	default:
+		printf("%s: not support data lanes %d\n",
+		       __func__, data_len + 1);
+		return -EINVAL;
+	}
+
+	switch (dsi->format) {
+	case MIPI_DSI_FMT_RGB565:
+		dsi_format = nx_mipi_dsi_format_rgb565;
+		break;
+	case MIPI_DSI_FMT_RGB666:
+		dsi_format = nx_mipi_dsi_format_rgb666;
+		break;
+	case MIPI_DSI_FMT_RGB666_PACKED:
+		dsi_format = nx_mipi_dsi_format_rgb666_packed;
+		break;
+	case MIPI_DSI_FMT_RGB888:
+		dsi_format = nx_mipi_dsi_format_rgb888;
+		break;
+	default:
+		printf("%s: not support format %d\n", __func__, dsi->format);
+		return -EINVAL;
+	}
+
+	nx_mipi_dsi_set_config_video_mode(index, 1, 0, burst,
+					  nx_mipi_dsi_syncmode_event,
+					  eot_enable, 1, 1, 1, 1, 0, dsi_format,
+					  HFP, HBP, HS, VFP, VBP, VS, 0);
+
+	nx_mipi_dsi_set_size(index, width, height);
+
+	/* set mux */
+	nx_disp_top_set_mipimux(1, module);
+
+	/*  0 is spdif, 1 is mipi vclk */
+	nx_disp_top_clkgen_set_clock_source(clkid, 1, ctrl->clk_src_lv0);
+	nx_disp_top_clkgen_set_clock_divisor(clkid, 1,
+					     ctrl->clk_div_lv1 *
+					     ctrl->clk_div_lv0);
+
+	/* SPDIF and MIPI */
+	nx_disp_top_clkgen_set_clock_divisor_enable(clkid, 1);
+
+	/* START: CLKGEN, MIPI is started in setup function */
+	nx_disp_top_clkgen_set_clock_divisor_enable(clkid, true);
+	nx_mipi_dsi_set_enable(index, true);
+
+	return 0;
+}
+
+static int nx_mipi_transfer_tx(struct mipi_dsi_device *dsi,
+			       struct mipi_xfer_msg *xfer)
+{
+	const u8 *txb;
+	int size, index = 0;
+	u32 data;
+
+	if (xfer->tx_len > DSI_TX_FIFO_SIZE)
+		printf("warn: tx %d size over fifo %d\n",
+		       (int)xfer->tx_len, DSI_TX_FIFO_SIZE);
+
+	/* write payload */
+	size = xfer->tx_len;
+	txb = xfer->tx_buf;
+
+	while (size >= 4) {
+		data = (txb[3] << 24) | (txb[2] << 16) |
+		    (txb[1] << 8) | (txb[0]);
+		nx_mipi_dsi_write_payload(index, data);
+		txb += 4, size -= 4;
+		data = 0;
+	}
+
+	switch (size) {
+	case 3:
+		data |= txb[2] << 16;
+	case 2:
+		data |= txb[1] << 8;
+	case 1:
+		data |= txb[0];
+		nx_mipi_dsi_write_payload(index, data);
+		break;
+	case 0:
+		break;		/* no payload */
+	}
+
+	/* write packet hdr */
+	data = (xfer->data[1] << 16) | (xfer->data[0] << 8) | xfer->id;
+
+	nx_mipi_dsi_write_pkheader(index, data);
+
+	return 0;
+}
+
+static int nx_mipi_transfer_done(struct mipi_dsi_device *dsi)
+{
+	int index = 0, count = 100;
+	u32 value;
+
+	do {
+		mdelay(1);
+		value = nx_mipi_dsi_read_fifo_status(index);
+		if (((1 << 22) & value))
+			break;
+	} while (count-- > 0);
+
+	if (count < 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int nx_mipi_transfer_rx(struct mipi_dsi_device *dsi,
+			       struct mipi_xfer_msg *xfer)
+{
+	u8 *rxb = xfer->rx_buf;
+	int index = 0, rx_len = 0;
+	u32 data, count = 0;
+	u16 size;
+	int err = -EINVAL;
+
+	nx_mipi_dsi_clear_interrupt_pending(index, 18);
+
+	while (1) {
+		/* Completes receiving data. */
+		if (nx_mipi_dsi_get_interrupt_pending(index, 18))
+			break;
+
+		mdelay(1);
+
+		if (count > 500) {
+			printf("%s: error recevice data\n", __func__);
+			err = -EINVAL;
+			goto clear_fifo;
+		} else {
+			count++;
+		}
+	}
+
+	data = nx_mipi_dsi_read_fifo(index);
+
+	switch (data & 0x3f) {
+	case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE:
+	case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE:
+		if (xfer->rx_len >= 2) {
+			rxb[1] = data >> 16;
+			rx_len++;
+		}
+
+		/* Fall through */
+	case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE:
+	case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE:
+		rxb[0] = data >> 8;
+		rx_len++;
+		xfer->rx_len = rx_len;
+		err = rx_len;
+		goto clear_fifo;
+
+	case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT:
+		printf("DSI Error Report: 0x%04x\n", (data >> 8) & 0xffff);
+		err = rx_len;
+		goto clear_fifo;
+	}
+
+	size = (data >> 8) & 0xffff;
+
+	if (size > xfer->rx_len)
+		size = xfer->rx_len;
+	else if (size < xfer->rx_len)
+		xfer->rx_len = size;
+
+	size = xfer->rx_len - rx_len;
+	rx_len += size;
+
+	/* Receive payload */
+	while (size >= 4) {
+		data = nx_mipi_dsi_read_fifo(index);
+		rxb[0] = (data >> 0) & 0xff;
+		rxb[1] = (data >> 8) & 0xff;
+		rxb[2] = (data >> 16) & 0xff;
+		rxb[3] = (data >> 24) & 0xff;
+		rxb += 4, size -= 4;
+	}
+
+	if (size) {
+		data = nx_mipi_dsi_read_fifo(index);
+		switch (size) {
+		case 3:
+			rxb[2] = (data >> 16) & 0xff;
+		case 2:
+			rxb[1] = (data >> 8) & 0xff;
+		case 1:
+			rxb[0] = data & 0xff;
+		}
+	}
+
+	if (rx_len == xfer->rx_len)
+		err = rx_len;
+
+clear_fifo:
+	size = DSI_RX_FIFO_SIZE / 4;
+	do {
+		data = nx_mipi_dsi_read_fifo(index);
+		if (data == DSI_RX_FIFO_EMPTY)
+			break;
+	} while (--size);
+
+	return err;
+}
+
+#define	IS_SHORT(t)	(9 > ((t) & 0x0f))
+
+static int nx_mipi_transfer(struct mipi_dsi_device *dsi,
+			    const struct mipi_dsi_msg *msg)
+{
+	struct mipi_xfer_msg xfer;
+	int err;
+
+	if (!msg->tx_len)
+		return -EINVAL;
+
+	/* set id */
+	xfer.id = msg->type | (msg->channel << 6);
+
+	/* short type msg */
+	if (IS_SHORT(msg->type)) {
+		const char *txb = msg->tx_buf;
+
+		if (msg->tx_len > 2)
+			return -EINVAL;
+
+		xfer.tx_len = 0;	/* no payload */
+		xfer.data[0] = txb[0];
+		xfer.data[1] = (msg->tx_len == 2) ? txb[1] : 0;
+		xfer.tx_buf = NULL;
+	} else {
+		xfer.tx_len = msg->tx_len;
+		xfer.data[0] = msg->tx_len & 0xff;
+		xfer.data[1] = msg->tx_len >> 8;
+		xfer.tx_buf = msg->tx_buf;
+	}
+
+	xfer.rx_len = msg->rx_len;
+	xfer.rx_buf = msg->rx_buf;
+	xfer.flags = msg->flags;
+
+	err = nx_mipi_transfer_tx(dsi, &xfer);
+
+	if (xfer.rx_len)
+		err = nx_mipi_transfer_rx(dsi, &xfer);
+
+	nx_mipi_transfer_done(dsi);
+
+	return err;
+}
+
+static ssize_t nx_mipi_write_buffer(struct mipi_dsi_device *dsi,
+				    const void *data, size_t len)
+{
+	struct mipi_dsi_msg msg = {
+		.channel = dsi->channel,
+		.tx_buf = data,
+		.tx_len = len
+	};
+
+	switch (len) {
+	case 0:
+		return -EINVAL;
+	case 1:
+		msg.type = MIPI_DSI_DCS_SHORT_WRITE;
+		break;
+	case 2:
+		msg.type = MIPI_DSI_DCS_SHORT_WRITE_PARAM;
+		break;
+	default:
+		msg.type = MIPI_DSI_DCS_LONG_WRITE;
+		break;
+	}
+
+	if (dsi->mode_flags & MIPI_DSI_MODE_LPM)
+		msg.flags |= MIPI_DSI_MSG_USE_LPM;
+
+	return nx_mipi_transfer(dsi, &msg);
+}
+
+__weak int nx_mipi_dsi_lcd_bind(struct mipi_dsi_device *dsi)
+{
+	return 0;
+}
+
+/*
+ * disply
+ * MIPI DSI Setting
+ *		(1) Initiallize MIPI(DSIM,DPHY,PLL)
+ *		(2) Initiallize LCD
+ *		(3) ReInitiallize MIPI(DSIM only)
+ *		(4) Turn on display(MLC,DPC,...)
+ */
+void nx_mipi_display(int module,
+		     struct dp_sync_info *sync, struct dp_ctrl_info *ctrl,
+		     struct dp_plane_top *top, struct dp_plane_info *planes,
+		     struct dp_mipi_dev *dev)
+{
+	struct dp_plane_info *plane = planes;
+	struct mipi_dsi_device *dsi = &dev->dsi;
+	int input = module == 0 ? DP_DEVICE_DP0 : DP_DEVICE_DP1;
+	int count = top->plane_num;
+	int i = 0, ret;
+
+	printf("MIPI: dp.%d\n", module);
+
+	/* map mipi-dsi write callback func */
+	dsi->write_buffer = nx_mipi_write_buffer;
+
+	ret = nx_mipi_dsi_lcd_bind(dsi);
+	if (ret) {
+		printf("Error: bind mipi-dsi lcd driver !\n");
+		return;
+	}
+
+	dp_control_init(module);
+	dp_plane_init(module);
+
+	mipi_init();
+
+	/* set plane */
+	dp_plane_screen_setup(module, top);
+
+	for (i = 0; count > i; i++, plane++) {
+		if (!plane->enable)
+			continue;
+		dp_plane_layer_setup(module, plane);
+		dp_plane_layer_enable(module, plane, 1);
+	}
+	dp_plane_screen_enable(module, 1);
+
+	/* set mipi */
+	mipi_prepare(module, input, sync, ctrl, dev);
+
+	if (dsi->ops && dsi->ops->prepare)
+		dsi->ops->prepare(dsi);
+
+	if (dsi->ops && dsi->ops->enable)
+		dsi->ops->enable(dsi);
+
+	mipi_enable(module, input, sync, ctrl, dev);
+
+	/* set dp control */
+	dp_control_setup(module, sync, ctrl);
+	dp_control_enable(module, 1);
+}
diff --git a/drivers/video/nexell/s5pxx18_dp_rgb.c b/drivers/video/nexell/s5pxx18_dp_rgb.c
new file mode 100644
index 0000000..44e8edb
--- /dev/null
+++ b/drivers/video/nexell/s5pxx18_dp_rgb.c
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2016  Nexell Co., Ltd.
+ *
+ * Author: junghyun, kim <jhkim@nexell.co.kr>
+ */
+
+#include <config.h>
+#include <common.h>
+#include <errno.h>
+
+#include <asm/arch/display.h>
+
+#include "soc/s5pxx18_soc_disptop.h"
+
+static int rgb_switch(int module, int input, struct dp_sync_info *sync,
+		      struct dp_rgb_dev *dev)
+{
+	int mpu = dev->lcd_mpu_type;
+	int rsc = 0, sel = 0;
+
+	switch (module) {
+	case 0:
+		sel = mpu ? 1 : 0;
+		break;
+	case 1:
+		sel = rsc ? 3 : 2;
+		break;
+	default:
+		printf("Fail, %s nuknown module %d\n", __func__, module);
+		return -1;
+	}
+
+	nx_disp_top_set_primary_mux(sel);
+	return 0;
+}
+
+void nx_rgb_display(int module,
+		    struct dp_sync_info *sync, struct dp_ctrl_info *ctrl,
+		    struct dp_plane_top *top, struct dp_plane_info *planes,
+		    struct dp_rgb_dev *dev)
+{
+	struct dp_plane_info *plane = planes;
+	int input = module == 0 ? DP_DEVICE_DP0 : DP_DEVICE_DP1;
+	int count = top->plane_num;
+	int i = 0;
+
+	printf("RGB:   dp.%d\n", module);
+
+	dp_control_init(module);
+	dp_plane_init(module);
+
+	/* set plane */
+	dp_plane_screen_setup(module, top);
+
+	for (i = 0; count > i; i++, plane++) {
+		if (!plane->enable)
+			continue;
+		dp_plane_layer_setup(module, plane);
+		dp_plane_layer_enable(module, plane, 1);
+	}
+
+	dp_plane_screen_enable(module, 1);
+
+	rgb_switch(module, input, sync, dev);
+
+	dp_control_setup(module, sync, ctrl);
+	dp_control_enable(module, 1);
+}
diff --git a/drivers/video/nexell_display.c b/drivers/video/nexell_display.c
new file mode 100644
index 0000000..640eb61
--- /dev/null
+++ b/drivers/video/nexell_display.c
@@ -0,0 +1,665 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2016  Nexell Co., Ltd.
+ *
+ * Author: junghyun, kim <jhkim@nexell.co.kr>
+ *
+ * Copyright (C) 2019  Stefan Bosch <stefan_b@posteo.net>
+ */
+
+#include <config.h>
+#include <common.h>
+#include <dm.h>
+#include <mapmem.h>
+#include <malloc.h>
+#include <linux/compat.h>
+#include <linux/err.h>
+#include <video.h>		/* For struct video_uc_platdata */
+#include <fdtdec.h>
+#include <fdt_support.h>
+#include <video_fb.h>
+#include <lcd.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include <asm/arch/display.h>
+#include <asm/arch/display_dev.h>
+#include "videomodes.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if !defined(CONFIG_DM) && !defined(CONFIG_OF_CONTROL)
+static struct nx_display_dev *dp_dev;
+#endif
+
+static char *const dp_dev_str[] = {
+	[DP_DEVICE_RESCONV] = "RESCONV",
+	[DP_DEVICE_RGBLCD] = "LCD",
+	[DP_DEVICE_HDMI] = "HDMI",
+	[DP_DEVICE_MIPI] = "MiPi",
+	[DP_DEVICE_LVDS] = "LVDS",
+	[DP_DEVICE_CVBS] = "TVOUT",
+	[DP_DEVICE_DP0] = "DP0",
+	[DP_DEVICE_DP1] = "DP1",
+};
+
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+static void nx_display_parse_dp_sync(const void *blob, int node,
+				     struct dp_sync_info *sync)
+{
+	sync->h_active_len = fdtdec_get_int(blob, node, "h_active_len", 0);
+	sync->h_sync_width = fdtdec_get_int(blob, node, "h_sync_width", 0);
+	sync->h_back_porch = fdtdec_get_int(blob, node, "h_back_porch", 0);
+	sync->h_front_porch = fdtdec_get_int(blob, node, "h_front_porch", 0);
+	sync->h_sync_invert = fdtdec_get_int(blob, node, "h_sync_invert", 0);
+	sync->v_active_len = fdtdec_get_int(blob, node, "v_active_len", 0);
+	sync->v_sync_width = fdtdec_get_int(blob, node, "v_sync_width", 0);
+	sync->v_back_porch = fdtdec_get_int(blob, node, "v_back_porch", 0);
+	sync->v_front_porch = fdtdec_get_int(blob, node, "v_front_porch", 0);
+	sync->v_sync_invert = fdtdec_get_int(blob, node, "v_sync_invert", 0);
+	sync->pixel_clock_hz = fdtdec_get_int(blob, node, "pixel_clock_hz", 0);
+
+	debug("DP: sync ->\n");
+	debug("ha:%d, hs:%d, hb:%d, hf:%d, hi:%d\n",
+	      sync->h_active_len, sync->h_sync_width,
+	      sync->h_back_porch, sync->h_front_porch, sync->h_sync_invert);
+	debug("va:%d, vs:%d, vb:%d, vf:%d, vi:%d\n",
+	      sync->v_active_len, sync->v_sync_width,
+	      sync->v_back_porch, sync->v_front_porch, sync->v_sync_invert);
+}
+
+static void nx_display_parse_dp_ctrl(const void *blob, int node,
+				     struct dp_ctrl_info *ctrl)
+{
+	/* clock gen */
+	ctrl->clk_src_lv0 = fdtdec_get_int(blob, node, "clk_src_lv0", 0);
+	ctrl->clk_div_lv0 = fdtdec_get_int(blob, node, "clk_div_lv0", 0);
+	ctrl->clk_src_lv1 = fdtdec_get_int(blob, node, "clk_src_lv1", 0);
+	ctrl->clk_div_lv1 = fdtdec_get_int(blob, node, "clk_div_lv1", 0);
+
+	/* scan format */
+	ctrl->interlace = fdtdec_get_int(blob, node, "interlace", 0);
+
+	/* syncgen format */
+	ctrl->out_format = fdtdec_get_int(blob, node, "out_format", 0);
+	ctrl->invert_field = fdtdec_get_int(blob, node, "invert_field", 0);
+	ctrl->swap_RB = fdtdec_get_int(blob, node, "swap_RB", 0);
+	ctrl->yc_order = fdtdec_get_int(blob, node, "yc_order", 0);
+
+	/* extern sync delay */
+	ctrl->delay_mask = fdtdec_get_int(blob, node, "delay_mask", 0);
+	ctrl->d_rgb_pvd = fdtdec_get_int(blob, node, "d_rgb_pvd", 0);
+	ctrl->d_hsync_cp1 = fdtdec_get_int(blob, node, "d_hsync_cp1", 0);
+	ctrl->d_vsync_fram = fdtdec_get_int(blob, node, "d_vsync_fram", 0);
+	ctrl->d_de_cp2 = fdtdec_get_int(blob, node, "d_de_cp2", 0);
+
+	/* extern sync delay */
+	ctrl->vs_start_offset =
+	    fdtdec_get_int(blob, node, "vs_start_offset", 0);
+	ctrl->vs_end_offset = fdtdec_get_int(blob, node, "vs_end_offset", 0);
+	ctrl->ev_start_offset =
+	    fdtdec_get_int(blob, node, "ev_start_offset", 0);
+	ctrl->ev_end_offset = fdtdec_get_int(blob, node, "ev_end_offset", 0);
+
+	/* pad clock seletor */
+	ctrl->vck_select = fdtdec_get_int(blob, node, "vck_select", 0);
+	ctrl->clk_inv_lv0 = fdtdec_get_int(blob, node, "clk_inv_lv0", 0);
+	ctrl->clk_delay_lv0 = fdtdec_get_int(blob, node, "clk_delay_lv0", 0);
+	ctrl->clk_inv_lv1 = fdtdec_get_int(blob, node, "clk_inv_lv1", 0);
+	ctrl->clk_delay_lv1 = fdtdec_get_int(blob, node, "clk_delay_lv1", 0);
+	ctrl->clk_sel_div1 = fdtdec_get_int(blob, node, "clk_sel_div1", 0);
+
+	debug("DP: ctrl [%s] ->\n",
+	      ctrl->interlace ? "Interlace" : " Progressive");
+	debug("cs0:%d, cd0:%d, cs1:%d, cd1:%d\n",
+	      ctrl->clk_src_lv0, ctrl->clk_div_lv0,
+	      ctrl->clk_src_lv1, ctrl->clk_div_lv1);
+	debug("fmt:0x%x, inv:%d, swap:%d, yb:0x%x\n",
+	      ctrl->out_format, ctrl->invert_field,
+	      ctrl->swap_RB, ctrl->yc_order);
+	debug("dm:0x%x, drp:%d, dhs:%d, dvs:%d, dde:0x%x\n",
+	      ctrl->delay_mask, ctrl->d_rgb_pvd,
+	      ctrl->d_hsync_cp1, ctrl->d_vsync_fram, ctrl->d_de_cp2);
+	debug("vss:%d, vse:%d, evs:%d, eve:%d\n",
+	      ctrl->vs_start_offset, ctrl->vs_end_offset,
+	      ctrl->ev_start_offset, ctrl->ev_end_offset);
+	debug("sel:%d, i0:%d, d0:%d, i1:%d, d1:%d, s1:%d\n",
+	      ctrl->vck_select, ctrl->clk_inv_lv0, ctrl->clk_delay_lv0,
+	      ctrl->clk_inv_lv1, ctrl->clk_delay_lv1, ctrl->clk_sel_div1);
+}
+
+static void nx_display_parse_dp_top_layer(const void *blob, int node,
+					  struct dp_plane_top *top)
+{
+	top->screen_width = fdtdec_get_int(blob, node, "screen_width", 0);
+	top->screen_height = fdtdec_get_int(blob, node, "screen_height", 0);
+	top->video_prior = fdtdec_get_int(blob, node, "video_prior", 0);
+	top->interlace = fdtdec_get_int(blob, node, "interlace", 0);
+	top->back_color = fdtdec_get_int(blob, node, "back_color", 0);
+	top->plane_num = DP_PLANS_NUM;
+
+	debug("DP: top [%s] ->\n",
+	      top->interlace ? "Interlace" : " Progressive");
+	debug("w:%d, h:%d, prior:%d, bg:0x%x\n",
+	      top->screen_width, top->screen_height,
+	      top->video_prior, top->back_color);
+}
+
+static void nx_display_parse_dp_layer(const void *blob, int node,
+				      struct dp_plane_info *plane)
+{
+	plane->left = fdtdec_get_int(blob, node, "left", 0);
+	plane->width = fdtdec_get_int(blob, node, "width", 0);
+	plane->top = fdtdec_get_int(blob, node, "top", 0);
+	plane->height = fdtdec_get_int(blob, node, "height", 0);
+	plane->pixel_byte = fdtdec_get_int(blob, node, "pixel_byte", 0);
+	plane->format = fdtdec_get_int(blob, node, "format", 0);
+	plane->alpha_on = fdtdec_get_int(blob, node, "alpha_on", 0);
+	plane->alpha_depth = fdtdec_get_int(blob, node, "alpha", 0);
+	plane->tp_on = fdtdec_get_int(blob, node, "tp_on", 0);
+	plane->tp_color = fdtdec_get_int(blob, node, "tp_color", 0);
+
+	/* enable layer */
+	if (plane->fb_base)
+		plane->enable = 1;
+	else
+		plane->enable = 0;
+
+	if (plane->fb_base == 0) {
+		printf("fail : dp plane.%d invalid fb base [0x%x] ->\n",
+		       plane->layer, plane->fb_base);
+		return;
+	}
+
+	debug("DP: plane.%d [0x%x] ->\n", plane->layer, plane->fb_base);
+	debug("f:0x%x, l:%d, t:%d, %d * %d, bpp:%d, a:%d(%d), t:%d(0x%x)\n",
+	      plane->format, plane->left, plane->top, plane->width,
+	      plane->height, plane->pixel_byte, plane->alpha_on,
+	      plane->alpha_depth, plane->tp_on, plane->tp_color);
+}
+
+static void nx_display_parse_dp_planes(const void *blob, int node,
+				       struct nx_display_dev *dp,
+				       struct video_uc_platdata *plat)
+{
+	const char *name;
+
+	for (node = fdt_first_subnode(blob, node);
+	     node > 0; node = fdt_next_subnode(blob, node)) {
+		name = fdt_get_name(blob, node, NULL);
+
+		if (strcmp(name, "layer_top") == 0)
+			nx_display_parse_dp_top_layer(blob, node, &dp->top);
+
+		/*
+		 * TODO: Is it sure that only one layer is used? Otherwise
+		 * fb_base must be different?
+		 */
+		if (strcmp(name, "layer_0") == 0) {
+			dp->planes[0].fb_base =
+			      (uint)map_sysmem(plat->base, plat->size);
+			debug("%s(): dp->planes[0].fb_base == 0x%x\n", __func__,
+			      (uint)dp->planes[0].fb_base);
+			nx_display_parse_dp_layer(blob, node, &dp->planes[0]);
+		}
+
+		if (strcmp(name, "layer_1") == 0) {
+			dp->planes[1].fb_base =
+			      (uint)map_sysmem(plat->base, plat->size);
+			debug("%s(): dp->planes[1].fb_base == 0x%x\n", __func__,
+			      (uint)dp->planes[1].fb_base);
+			nx_display_parse_dp_layer(blob, node, &dp->planes[1]);
+		}
+
+		if (strcmp(name, "layer_2") == 0) {
+			dp->planes[2].fb_base =
+			      (uint)map_sysmem(plat->base, plat->size);
+			debug("%s(): dp->planes[2].fb_base == 0x%x\n", __func__,
+			      (uint)dp->planes[2].fb_base);
+			nx_display_parse_dp_layer(blob, node, &dp->planes[2]);
+		}
+	}
+}
+
+static int nx_display_parse_dp_lvds(const void *blob, int node,
+				    struct nx_display_dev *dp)
+{
+	struct dp_lvds_dev *dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+
+	if (!dev) {
+		printf("failed to allocate display LVDS object.\n");
+		return -ENOMEM;
+	}
+
+	dp->device = dev;
+
+	dev->lvds_format = fdtdec_get_int(blob, node, "format", 0);
+	dev->pol_inv_hs = fdtdec_get_int(blob, node, "pol_inv_hs", 0);
+	dev->pol_inv_vs = fdtdec_get_int(blob, node, "pol_inv_vs", 0);
+	dev->pol_inv_de = fdtdec_get_int(blob, node, "pol_inv_de", 0);
+	dev->pol_inv_ck = fdtdec_get_int(blob, node, "pol_inv_ck", 0);
+	dev->voltage_level = fdtdec_get_int(blob, node, "voltage_level", 0);
+
+	if (!dev->voltage_level)
+		dev->voltage_level = DEF_VOLTAGE_LEVEL;
+
+	debug("DP: LVDS -> %s, voltage LV:0x%x\n",
+	      dev->lvds_format == DP_LVDS_FORMAT_VESA ? "VESA" :
+	      dev->lvds_format == DP_LVDS_FORMAT_JEIDA ? "JEIDA" : "LOC",
+	      dev->voltage_level);
+	debug("pol inv hs:%d, vs:%d, de:%d, ck:%d\n",
+	      dev->pol_inv_hs, dev->pol_inv_vs,
+	      dev->pol_inv_de, dev->pol_inv_ck);
+
+	return 0;
+}
+
+static int nx_display_parse_dp_rgb(const void *blob, int node,
+				   struct nx_display_dev *dp)
+{
+	struct dp_rgb_dev *dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+
+	if (!dev) {
+		printf("failed to allocate display RGB LCD object.\n");
+		return -ENOMEM;
+	}
+	dp->device = dev;
+
+	dev->lcd_mpu_type = fdtdec_get_int(blob, node, "lcd_mpu_type", 0);
+
+	debug("DP: RGB -> MPU[%s]\n", dev->lcd_mpu_type ? "O" : "X");
+	return 0;
+}
+
+static int nx_display_parse_dp_mipi(const void *blob, int node,
+				    struct nx_display_dev *dp)
+{
+	struct dp_mipi_dev *dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+
+	if (!dev) {
+		printf("failed to allocate display MiPi object.\n");
+		return -ENOMEM;
+	}
+	dp->device = dev;
+
+	dev->lp_bitrate = fdtdec_get_int(blob, node, "lp_bitrate", 0);
+	dev->hs_bitrate = fdtdec_get_int(blob, node, "hs_bitrate", 0);
+	dev->lpm_trans = 1;
+	dev->command_mode = 0;
+
+	debug("DP: MIPI ->\n");
+	debug("lp:%dmhz, hs:%dmhz\n", dev->lp_bitrate, dev->hs_bitrate);
+
+	return 0;
+}
+
+static int nx_display_parse_dp_hdmi(const void *blob, int node,
+				    struct nx_display_dev *dp)
+{
+	struct dp_hdmi_dev *dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+
+	if (!dev) {
+		printf("failed to allocate display HDMI object.\n");
+		return -ENOMEM;
+	}
+	dp->device = dev;
+
+	dev->preset = fdtdec_get_int(blob, node, "preset", 0);
+
+	debug("DP: HDMI -> %d\n", dev->preset);
+
+	return 0;
+}
+
+static int nx_display_parse_dp_lcds(const void *blob, int node,
+				    const char *type, struct nx_display_dev *dp)
+{
+	if (strcmp(type, "lvds") == 0) {
+		dp->dev_type = DP_DEVICE_LVDS;
+		return nx_display_parse_dp_lvds(blob, node, dp);
+	} else if (strcmp(type, "rgb") == 0) {
+		dp->dev_type = DP_DEVICE_RGBLCD;
+		return nx_display_parse_dp_rgb(blob, node, dp);
+	} else if (strcmp(type, "mipi") == 0) {
+		dp->dev_type = DP_DEVICE_MIPI;
+		return nx_display_parse_dp_mipi(blob, node, dp);
+	} else if (strcmp(type, "hdmi") == 0) {
+		dp->dev_type = DP_DEVICE_HDMI;
+		return nx_display_parse_dp_hdmi(blob, node, dp);
+	}
+
+	printf("%s: node %s unknown display type\n", __func__,
+	       fdt_get_name(blob, node, NULL));
+	return -EINVAL;
+
+	return 0;
+}
+
+#define	DT_SYNC		(1 << 0)
+#define	DT_CTRL		(1 << 1)
+#define	DT_PLANES	(1 << 2)
+#define	DT_DEVICE	(1 << 3)
+
+static int nx_display_parse_dt(const void *blob,
+			       struct nx_display_dev *dp, int node,
+			       struct video_uc_platdata *plat)
+{
+	const char *name, *dtype;
+	int ret = 0;
+	unsigned int dt_status = 0;
+
+	if (!node)
+		return -ENODEV;
+
+	dp->module = fdtdec_get_int(blob, node, "module", -1);
+	if (dp->module == -1)
+		dp->module = fdtdec_get_int(blob, node, "index", 0);
+
+	dtype = fdt_getprop(blob, node, "lcd-type", NULL);
+
+	for (node = fdt_first_subnode(blob, node);
+	     node > 0; node = fdt_next_subnode(blob, node)) {
+		name = fdt_get_name(blob, node, NULL);
+
+		if (strcmp("dp-sync", name) == 0) {
+			dt_status |= DT_SYNC;
+			nx_display_parse_dp_sync(blob, node, &dp->sync);
+		}
+
+		if (strcmp("dp-ctrl", name) == 0) {
+			dt_status |= DT_CTRL;
+			nx_display_parse_dp_ctrl(blob, node, &dp->ctrl);
+		}
+
+		if (strcmp("dp-planes", name) == 0) {
+			dt_status |= DT_PLANES;
+			nx_display_parse_dp_planes(blob, node, dp, plat);
+		}
+
+		if (strcmp("dp-device", name) == 0) {
+			dt_status |= DT_DEVICE;
+			ret = nx_display_parse_dp_lcds(blob, node, dtype, dp);
+		}
+	}
+
+	if (dt_status != (DT_SYNC | DT_CTRL | DT_PLANES | DT_DEVICE)) {
+		printf("Not enough DT config for display [0x%x]\n", dt_status);
+		return -ENODEV;
+	}
+
+	return ret;
+}
+#endif
+
+__weak int nx_display_fixup_dp(struct nx_display_dev *dp)
+{
+	return 0;
+}
+
+static struct nx_display_dev *nx_display_setup(void)
+{
+	struct nx_display_dev *dp;
+	int i, ret;
+	int node = 0;
+	struct video_uc_platdata *plat = NULL;
+
+	struct udevice *dev;
+
+	/* call driver probe */
+	debug("DT: uclass device call...\n");
+
+	ret = uclass_get_device(UCLASS_VIDEO, 0, &dev);
+	if (ret) {
+		debug("%s(): uclass_get_device(UCLASS_VIDEO, 0, &dev) != 0 --> return NULL\n",
+		      __func__);
+		return NULL;
+	}
+	plat = dev_get_uclass_platdata(dev);
+	if (!dev) {
+		debug("%s(): dev_get_uclass_platdata(dev) == NULL --> return NULL\n",
+		      __func__);
+		return NULL;
+	}
+	dp = dev_get_priv(dev);
+	if (!dp) {
+		debug("%s(): dev_get_priv(dev) == NULL --> return NULL\n",
+		      __func__);
+		return NULL;
+	}
+	node = dev->node.of_offset;
+
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+	ret = nx_display_parse_dt(gd->fdt_blob, dp, node, plat);
+	if (ret)
+		goto err_setup;
+#endif
+
+	nx_display_fixup_dp(dp);
+
+	for (i = 0; dp->top.plane_num > i; i++) {
+		dp->planes[i].layer = i;
+		if (dp->planes[i].enable && !dp->fb_plane) {
+			dp->fb_plane = &dp->planes[i];
+			dp->fb_addr = dp->fb_plane->fb_base;
+			dp->depth = dp->fb_plane->pixel_byte;
+		}
+	}
+
+	switch (dp->dev_type) {
+#ifdef CONFIG_VIDEO_NX_RGB
+	case DP_DEVICE_RGBLCD:
+		nx_rgb_display(dp->module,
+			       &dp->sync, &dp->ctrl, &dp->top,
+			       dp->planes, (struct dp_rgb_dev *)dp->device);
+		break;
+#endif
+#ifdef CONFIG_VIDEO_NX_LVDS
+	case DP_DEVICE_LVDS:
+		nx_lvds_display(dp->module,
+				&dp->sync, &dp->ctrl, &dp->top,
+				dp->planes, (struct dp_lvds_dev *)dp->device);
+		break;
+#endif
+#ifdef CONFIG_VIDEO_NX_MIPI
+	case DP_DEVICE_MIPI:
+		nx_mipi_display(dp->module,
+				&dp->sync, &dp->ctrl, &dp->top,
+				dp->planes, (struct dp_mipi_dev *)dp->device);
+		break;
+#endif
+#ifdef CONFIG_VIDEO_NX_HDMI
+	case DP_DEVICE_HDMI:
+		nx_hdmi_display(dp->module,
+				&dp->sync, &dp->ctrl, &dp->top,
+				dp->planes, (struct dp_hdmi_dev *)dp->device);
+		break;
+#endif
+	default:
+		printf("fail : not support lcd type %d !!!\n", dp->dev_type);
+		goto err_setup;
+	};
+
+	printf("LCD:   [%s] dp.%d.%d %dx%d %dbpp FB:0x%08x\n",
+	       dp_dev_str[dp->dev_type], dp->module, dp->fb_plane->layer,
+	       dp->fb_plane->width, dp->fb_plane->height, dp->depth * 8,
+	       dp->fb_addr);
+
+	return dp;
+
+err_setup:
+	kfree(dp);
+
+	return NULL;
+}
+
+#if defined CONFIG_LCD
+
+/* default lcd */
+struct vidinfo panel_info = {
+	.vl_col = 320, .vl_row = 240, .vl_bpix = 32,
+};
+
+void lcd_ctrl_init(void *lcdbase)
+{
+	vidinfo_t *pi = &panel_info;
+	struct nx_display_dev *dp;
+	int bpix;
+
+	dp = nx_display_setup();
+	if (!dp)
+		return NULL;
+
+	switch (dp->depth) {
+	case 2:
+		bpix = LCD_COLOR16;
+		break;
+	case 3:
+	case 4:
+		bpix = LCD_COLOR32;
+		break;
+	default:
+		printf("fail : not support LCD bit per pixel %d\n",
+		       dp->depth * 8);
+		return NULL;
+	}
+
+	dp->panel_info = pi;
+
+	/* set resolution with config */
+	pi->vl_bpix = bpix;
+	pi->vl_col = dp->fb_plane->width;
+	pi->vl_row = dp->fb_plane->height;
+	pi->priv = dp;
+	gd->fb_base = dp->fb_addr;
+}
+
+void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue)
+{
+}
+
+__weak void lcd_enable(void)
+{
+}
+#endif
+
+static int nx_display_dev_probe_uclass(struct udevice *dev)
+{
+	struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev);
+	struct video_priv *uc_priv = dev_get_uclass_priv(dev);
+	struct nx_display_platdata *plat = dev_get_platdata(dev);
+	static GraphicDevice *graphic_device;
+	char addr[64];
+
+	debug("%s()\n", __func__);
+
+	if (!dev)
+		return -EINVAL;
+
+	if (!uc_plat) {
+		debug("%s(): video_uc_platdata *plat == NULL --> return -EINVAL\n",
+		      __func__);
+		return -EINVAL;
+	}
+
+	if (!uc_priv) {
+		debug("%s(): video_priv *uc_priv == NULL --> return -EINVAL\n",
+		      __func__);
+		return -EINVAL;
+	}
+
+	if (!plat) {
+		debug("%s(): nx_display_platdata *plat == NULL --> return -EINVAL\n",
+		      __func__);
+		return -EINVAL;
+	}
+
+	struct nx_display_dev *dp;
+	unsigned int pp_index = 0;
+
+	dp = nx_display_setup();
+	if (!dp) {
+		debug("%s(): nx_display_setup() == 0 --> return -EINVAL\n",
+		      __func__);
+		return -EINVAL;
+	}
+
+	switch (dp->depth) {
+	case 2:
+		pp_index = GDF_16BIT_565RGB;
+		uc_priv->bpix = VIDEO_BPP16;
+		break;
+	case 3:
+		/* There is no VIDEO_BPP24 because these values are of
+		 * type video_log2_bpp
+		 */
+	case 4:
+		pp_index = GDF_32BIT_X888RGB;
+		uc_priv->bpix = VIDEO_BPP32;
+		break;
+	default:
+		printf("fail : not support LCD bit per pixel %d\n",
+		       dp->depth * 8);
+		return -EINVAL;
+	}
+
+	uc_priv->xsize = dp->fb_plane->width;
+	uc_priv->ysize = dp->fb_plane->height;
+	uc_priv->rot = 0;
+
+	graphic_device = &dp->graphic_device;
+	graphic_device->frameAdrs = dp->fb_addr;
+	graphic_device->gdfIndex = pp_index;
+	graphic_device->gdfBytesPP = dp->depth;
+	graphic_device->winSizeX = dp->fb_plane->width;
+	graphic_device->winSizeY = dp->fb_plane->height;
+	graphic_device->plnSizeX =
+	    graphic_device->winSizeX * graphic_device->gdfBytesPP;
+
+	/*
+	 * set environment variable "fb_addr" (frame buffer address), required
+	 * for splash image. Because drv_video_init() in common/stdio.c is only
+	 * called when CONFIG_VIDEO is set (and not if CONFIG_DM_VIDEO is set).
+	 */
+	sprintf(addr, "0x%x", dp->fb_addr);
+	debug("%s(): env_set(\"fb_addr\", %s) ...\n", __func__, addr);
+	env_set("fb_addr", addr);
+
+	return 0;
+}
+
+static int nx_display_bind(struct udevice *dev)
+{
+	struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
+
+	debug("%s()\n", __func__);
+
+	/* Datasheet S5p4418:
+	 *   Resolution up to 2048 x 1280, up to 12 Bit per color (HDMI)
+	 * Actual (max.) size is 0x1000000 because in U-Boot nanopi2-2016.01
+	 * "#define CONFIG_FB_ADDR  0x77000000" and next address is
+	 * "#define BMP_LOAD_ADDR  0x78000000"
+	 */
+	plat->size = 0x1000000;
+
+	return 0;
+}
+
+static int nx_display_probe(struct udevice *dev)
+{
+	return nx_display_dev_probe_uclass(dev);
+}
+
+static const struct udevice_id nx_display_ids[] = {
+	{.compatible = "nexell,nexell-display", },
+	{}
+};
+
+U_BOOT_DRIVER(nexell_display) = {
+	.name = "nexell-display",
+	.id = UCLASS_VIDEO,
+	.of_match = nx_display_ids,
+	.platdata_auto_alloc_size =
+	    sizeof(struct nx_display_platdata),
+	.bind = nx_display_bind,
+	.probe = nx_display_probe,
+	.priv_auto_alloc_size = sizeof(struct nx_display_dev),
+};
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [RFC PATCH v2 12/13] arm: add support for SoC s5p4418 (cpu) / nanopi2 board
  2020-03-28  9:43 [RFC PATCH v2 00/13] arm: add support for SoC S5P4418 Stefan Bosch
                   ` (10 preceding siblings ...)
  2020-03-28  9:43 ` [RFC PATCH v2 11/13] video: add nexell video driver (display/video driver) Stefan Bosch
@ 2020-03-28  9:43 ` Stefan Bosch
  2020-03-28  9:43 ` [RFC PATCH v2 13/13] arm: add (default) config for " Stefan Bosch
  12 siblings, 0 replies; 21+ messages in thread
From: Stefan Bosch @ 2020-03-28  9:43 UTC (permalink / raw)
  To: u-boot

Changes in relation to FriendlyARM's U-Boot nanopi2-v2016.01:
- SPL not supported yet --> no spl-dir in arch/arm/cpu/armv7/s5p4418/.
  Appropriate line in Makefile removed.
- cpu.c: '#include <cpu_func.h>' added.
- arch/arm/cpu/armv7/s5p4418/u-boot.lds removed, is not required
  anylonger.
- "obj-$(CONFIG_ARCH_NEXELL) += s5p-common/" added to
  arch/arm/cpu/armv7/Makefile since s5p-common/pwm.c is used instead
  of drivers/pwm/pwm-nexell.c.
- s5p4418.dtsi: '#include "../../../include/generated/autoconf.h"'
  removed, is not necessary, error at out-of-tree building.
  '#ifdef CONFIG_CPU_NXP4330'-blocks (2x) removed. Some minor changes
  regarding mmc. 'u-boot,dm-pre-reloc' added to dp0 because of added
  DM_VIDEO support.
- board/s5p4418/ renamed to board/friendlyarm/
- All s5p4418-boards except nanopi2 removed because there is no
  possibility to test the other boards.
- Kconfig: Changes to have a structure like mach-bcm283x (RaspberryPi),
  e.g. "config ..." entries moved from/to other Kconfig.
- "CONFIG_" removed from several s5p4418/nanopi2 specific defines
  because the appropriate values do not need to be configurable.
- nanopi2/board.c: All getenv(), getenv_ulong(), setenv() and saveenv()
  renamed to env_get(), env_get_ulong(), env_set() and env_save(),
  respectively. MACH_TYPE_S5P4418 is not defined anymore, therefore
  appropriate code removed (not necessary for DT-kernels).
- nanopi2/onewire.c: All crc8() renamed to crc8_ow() because crc8() is
  already defined in lib/crc8.c (with different parameters).
- dts: "nexell,s5pxx18-i2c" used instead of "i2c-gpio", i2c0 and
  i2c1 added. s5p4418-pinctrl.dtsi not included because there is
  no pinctrl-driver available. gmac-, ehci- and dwc2otg-entries
  removed because the appropriate functionality is not supported yet.

Signed-off-by: Stefan Bosch <stefan_b@posteo.net>
---

Changes in v2:
- i2c: "nexell,s5pxx18-i2c"-driver is used now instead of "i2c-gpio".
  i2c0 and i2c1 added. I.e. dts files changed appropriately.
- dts: gmac-, ehci- and dwc2otg-entries removed because the appropriate
  functionality is not supported yet.
- s5p4418-pinctrl.dtsi removed because there is no pinctrl-driver
  available.
- "obj-$(CONFIG_ARCH_NEXELL) += s5p-common/" added to
  arch/arm/cpu/armv7/Makefile since s5p-common/pwm.c is used now instead
  of drivers/pwm/pwm-nexell.c.
- cosmetic: additional GPL license text removed, SPDX-License-Identifier
  is enough. Furthermore file path removed (two files).

 arch/arm/cpu/armv7/Makefile           |   2 +
 arch/arm/cpu/armv7/s5p4418/Makefile   |   6 +
 arch/arm/cpu/armv7/s5p4418/cpu.c      | 120 ++++++
 arch/arm/dts/Makefile                 |   3 +
 arch/arm/dts/s5p4418-nanopi2.dts      | 108 ++++++
 arch/arm/dts/s5p4418.dtsi             | 148 ++++++++
 board/friendlyarm/Kconfig             |  39 ++
 board/friendlyarm/nanopi2/Kconfig     |  12 +
 board/friendlyarm/nanopi2/MAINTAINERS |   7 +
 board/friendlyarm/nanopi2/Makefile    |   6 +
 board/friendlyarm/nanopi2/board.c     | 567 +++++++++++++++++++++++++++
 board/friendlyarm/nanopi2/hwrev.c     | 108 ++++++
 board/friendlyarm/nanopi2/hwrev.h     |  15 +
 board/friendlyarm/nanopi2/lcds.c      | 697 ++++++++++++++++++++++++++++++++++
 board/friendlyarm/nanopi2/nxp-fb.h    |  94 +++++
 board/friendlyarm/nanopi2/onewire.c   | 309 +++++++++++++++
 board/friendlyarm/nanopi2/onewire.h   |  15 +
 17 files changed, 2256 insertions(+)
 create mode 100644 arch/arm/cpu/armv7/s5p4418/Makefile
 create mode 100644 arch/arm/cpu/armv7/s5p4418/cpu.c
 create mode 100644 arch/arm/dts/s5p4418-nanopi2.dts
 create mode 100644 arch/arm/dts/s5p4418.dtsi
 create mode 100644 board/friendlyarm/Kconfig
 create mode 100644 board/friendlyarm/nanopi2/Kconfig
 create mode 100644 board/friendlyarm/nanopi2/MAINTAINERS
 create mode 100644 board/friendlyarm/nanopi2/Makefile
 create mode 100644 board/friendlyarm/nanopi2/board.c
 create mode 100644 board/friendlyarm/nanopi2/hwrev.c
 create mode 100644 board/friendlyarm/nanopi2/hwrev.h
 create mode 100644 board/friendlyarm/nanopi2/lcds.c
 create mode 100644 board/friendlyarm/nanopi2/nxp-fb.h
 create mode 100644 board/friendlyarm/nanopi2/onewire.c
 create mode 100644 board/friendlyarm/nanopi2/onewire.h

diff --git a/arch/arm/cpu/armv7/Makefile b/arch/arm/cpu/armv7/Makefile
index 8c955d0..0e83e39 100644
--- a/arch/arm/cpu/armv7/Makefile
+++ b/arch/arm/cpu/armv7/Makefile
@@ -42,3 +42,5 @@ obj-$(CONFIG_RMOBILE) += rmobile/
 obj-$(if $(filter stv0991,$(SOC)),y) += stv0991/
 obj-$(CONFIG_ARCH_SUNXI) += sunxi/
 obj-$(CONFIG_VF610) += vf610/
+obj-$(CONFIG_ARCH_S5P4418) += s5p4418/
+obj-$(CONFIG_ARCH_NEXELL) += s5p-common/
diff --git a/arch/arm/cpu/armv7/s5p4418/Makefile b/arch/arm/cpu/armv7/s5p4418/Makefile
new file mode 100644
index 0000000..321b257
--- /dev/null
+++ b/arch/arm/cpu/armv7/s5p4418/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2016 Nexell
+# Hyunseok, Jung <hsjung@nexell.co.kr>
+
+obj-y += cpu.o
diff --git a/arch/arm/cpu/armv7/s5p4418/cpu.c b/arch/arm/cpu/armv7/s5p4418/cpu.c
new file mode 100644
index 0000000..79c284f
--- /dev/null
+++ b/arch/arm/cpu/armv7/s5p4418/cpu.c
@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2016 Nexell
+ * Hyunseok, Jung <hsjung@nexell.co.kr>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/system.h>
+#include <asm/cache.h>
+#include <asm/sections.h>
+#include <asm/io.h>
+#include <asm/arch/nexell.h>
+#include <asm/arch/clk.h>
+#include <asm/arch/reset.h>
+#include <asm/arch/tieoff.h>
+#include <cpu_func.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifndef	CONFIG_ARCH_CPU_INIT
+#error must be define the macro "CONFIG_ARCH_CPU_INIT"
+#endif
+
+void s_init(void)
+{
+}
+
+static void cpu_soc_init(void)
+{
+	/*
+	 * NOTE> ALIVE Power Gate must enable for Alive register access.
+	 *	     must be clear wfi jump address
+	 */
+	writel(1, ALIVEPWRGATEREG);
+	writel(0xFFFFFFFF, SCR_ARM_SECOND_BOOT);
+
+	/* write 0xf0 on alive scratchpad reg for boot success check */
+	writel(readl(SCR_SIGNAGURE_READ) | 0xF0, (SCR_SIGNAGURE_SET));
+
+	/* set l2 cache tieoff */
+	nx_tieoff_set(NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_L2RET1N_0, 1);
+	nx_tieoff_set(NX_TIEOFF_CORTEXA9MP_TOP_QUADL2C_L2RET1N_1, 1);
+}
+
+#ifdef CONFIG_PL011_SERIAL
+static void serial_device_init(void)
+{
+	char dev[10];
+	int id;
+
+	sprintf(dev, "nx-uart.%d", CONFIG_CONS_INDEX);
+	id = RESET_ID_UART0 + CONFIG_CONS_INDEX;
+
+	struct clk *clk = clk_get((const char *)dev);
+
+	/* reset control: Low active ___|---   */
+	nx_rstcon_setrst(id, RSTCON_ASSERT);
+	udelay(10);
+	nx_rstcon_setrst(id, RSTCON_NEGATE);
+	udelay(10);
+
+	/* set clock   */
+	clk_disable(clk);
+	clk_set_rate(clk, CONFIG_PL011_CLOCK);
+	clk_enable(clk);
+}
+#endif
+
+int arch_cpu_init(void)
+{
+	flush_dcache_all();
+	cpu_soc_init();
+	clk_init();
+
+#ifdef CONFIG_PL011_SERIAL
+	serial_device_init();
+#endif
+	return 0;
+}
+
+#if defined(CONFIG_DISPLAY_CPUINFO)
+int print_cpuinfo(void)
+{
+	return 0;
+}
+#endif
+
+void reset_cpu(ulong ignored)
+{
+	void *clkpwr_reg = (void *)PHY_BASEADDR_CLKPWR;
+	const u32 sw_rst_enb_bitpos = 3;
+	const u32 sw_rst_enb_mask = 1 << sw_rst_enb_bitpos;
+	const u32 sw_rst_bitpos = 12;
+	const u32 sw_rst_mask = 1 << sw_rst_bitpos;
+	int pwrcont = 0x224;
+	int pwrmode = 0x228;
+	u32 read_value;
+
+	read_value = readl((void *)(clkpwr_reg + pwrcont));
+
+	read_value &= ~sw_rst_enb_mask;
+	read_value |= 1 << sw_rst_enb_bitpos;
+
+	writel(read_value, (void *)(clkpwr_reg + pwrcont));
+	writel(sw_rst_mask, (void *)(clkpwr_reg + pwrmode));
+}
+
+void enable_caches(void)
+{
+	/* Enable D-cache. I-cache is already enabled in start.S */
+	dcache_enable();
+}
+
+#if defined(CONFIG_ARCH_MISC_INIT)
+int arch_misc_init(void)
+{
+	return 0;
+}
+#endif	/* CONFIG_ARCH_MISC_INIT */
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 04a8ccc..065b2d2 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -137,6 +137,9 @@ dtb-$(CONFIG_ROCKCHIP_RV1108) += \
 	rv1108-elgin-r1.dtb \
 	rv1108-evb.dtb
 
+dtb-$(CONFIG_ARCH_S5P4418) += \
+	s5p4418-nanopi2.dtb
+
 dtb-$(CONFIG_ARCH_MESON) += \
 	meson-gxbb-nanopi-k2.dtb \
 	meson-gxbb-odroidc2.dtb \
diff --git a/arch/arm/dts/s5p4418-nanopi2.dts b/arch/arm/dts/s5p4418-nanopi2.dts
new file mode 100644
index 0000000..f86282a
--- /dev/null
+++ b/arch/arm/dts/s5p4418-nanopi2.dts
@@ -0,0 +1,108 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2017 FriendlyElec Computer Tech. Co., Ltd.
+ * (http://www.friendlyarm.com)
+ *
+ * (C) Copyright 2016 Nexell
+ * Youngbok, Park <park@nexell.co.kr>
+ */
+
+/dts-v1/;
+#include "s5p4418.dtsi"
+
+/ {
+	model = "FriendlyElec boards based on Nexell s5p4418";
+	cpu-model = "S5p4418";
+
+	compatible = "friendlyelec,nanopi2",
+		     "nexell,s5p4418";
+
+	aliases {
+		mmc0 = "/mmc at c0069000";
+		mmc1 = "/mmc at c0062000";
+		i2c0 = "/i2c at c00a4000";
+		i2c1 = "/i2c at c00a5000";
+		i2c2 = "/i2c at c00a6000";
+	};
+
+	mmc0:mmc at c0062000 {
+		frequency = <50000000>;
+		nexell,drive_dly = <0x0>;
+		nexell,drive_shift = <0x03>;
+		nexell,sample_dly = <0x00>;
+		nexell,sample_shift = <0x02>;
+		status = "okay";
+	};
+
+	mmc2:mmc at c0069000 {
+		frequency = <50000000>;
+		nexell,drive_dly = <0x0>;
+		nexell,drive_shift = <0x03>;
+		nexell,sample_dly = <0x00>;
+		nexell,sample_shift = <0x02>;
+		nexell,bus-width = <4>;
+		index = <2>;
+		status = "okay";
+	};
+
+	/* NanoPi2: Header "CON2", NanoPC-T2: EEPROM (MAC-Addr.) and Audio */
+	i2c0:i2c at c00a4000 {
+		status ="okay";
+	};
+
+	/* NanoPi2: Header "CON2" and HDMI, NanoPC-T2: HDMI */
+	i2c1:i2c at c00a5000 {
+		status ="okay";
+	};
+
+	/* NanoPi2: LCD interface, NanoPC-T2: LCD, LVDS and MIPI interfaces */
+	i2c2:i2c at c00a6000 {
+		status ="okay";
+	};
+
+	dp0:dp at c0102800 {
+		status = "okay";
+		module = <0>;
+		lcd-type = "lvds";
+
+		dp-device {
+			format = <0>;	/* 0:VESA, 1:JEIDA */
+		};
+
+		dp-sync {
+			h_active_len = <1024>;
+			h_front_porch = <84>;
+			h_back_porch = <84>;
+			h_sync_width = <88>;
+			h_sync_invert = <0>;
+			v_active_len = <600>;
+			v_front_porch = <10>;
+			v_back_porch = <10>;
+			v_sync_width = <20>;
+			v_sync_invert = <0>;
+		};
+
+		dp-ctrl {
+			clk_src_lv0 = <3>;
+			clk_div_lv0 = <16>;
+			clk_src_lv1 = <7>;
+			clk_div_lv1 = <1>;
+			out_format = <2>;
+		};
+
+		dp-planes {
+			layer_top {
+				screen_width = <1024>;
+				screen_height = <600>;
+				back_color = <0x0>;
+			};
+
+			layer_1 {	/* RGB 1 */
+				width = <1024>;
+				height = <600>;
+				format = <0x06530000>;
+				pixel_byte = <4>;
+			};
+		};
+	};
+};
diff --git a/arch/arm/dts/s5p4418.dtsi b/arch/arm/dts/s5p4418.dtsi
new file mode 100644
index 0000000..d823e61
--- /dev/null
+++ b/arch/arm/dts/s5p4418.dtsi
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2016 Nexell
+ * Youngbok, Park <park@nexell.co.kr>
+ */
+
+#include "skeleton.dtsi"
+
+/ {
+	aliases {
+		mmc0 = &mmc0;
+		mmc1 = &mmc1;
+		mmc2 = &mmc2;
+		gmac = "/ethernet at c0060000";
+	};
+
+	mmc2:mmc at c0069000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "nexell,nexell-dwmmc";
+		reg = <0xc0069000 0x1000>;
+		nexell,bus-width = <4>;
+		index = <2>;
+		max-frequency = <50000000>;
+		status = "disabled";
+	};
+
+	mmc1:mmc at c0068000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "nexell,nexell-dwmmc";
+		reg = <0xc0068000 0x1000>;
+		nexell,bus-width = <4>;
+		index = <1>;
+		max-frequency = <50000000>;
+		status = "disabled";
+	};
+
+	mmc0:mmc at c0062000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "nexell,nexell-dwmmc";
+		reg = <0xc0062000 0x1000>;
+		nexell,bus-width = <4>;
+		index = <0>;
+		max-frequency = <50000000>;
+		status = "disabled";
+	};
+
+	i2c0:i2c at c00a4000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "nexell,s5pxx18-i2c";
+		reg = <0xc00a4000 0x100>;
+		//clock-frequency = <400000>;
+		sda-delay = <10>;
+		status ="disabled";
+	};
+
+	i2c1:i2c at c00a5000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "nexell,s5pxx18-i2c";
+		reg = <0xc00a5000 0x100>;
+		clock-frequency = <100000>;
+		status ="disabled";
+	};
+
+	i2c2:i2c at c00a6000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "nexell,s5pxx18-i2c";
+		reg = <0xc00a6000 0x100>;
+		clock-frequency = <100000>;
+		status ="disabled";
+	};
+
+	dp0:dp at c0102800 {
+		compatible = "nexell,nexell-display";
+		reg = <0xc0102800 0x100>;
+		index = <0>;
+		u-boot,dm-pre-reloc;
+		status = "disabled";
+	};
+
+	dp1:dp at c0102c00 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "nexell,nexell-display";
+		reg = <0xc0102c00 0x100>;
+		index = <1>;
+		status = "disabled";
+	};
+
+	gpio_a:gpio at c001a000 {
+		compatible = "nexell,nexell-gpio";
+		reg = <0xc001a000 0x00000010>;
+		altr,gpio-bank-width = <32>;
+		gpio-bank-name = "gpio_a";
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	gpio_b:gpio at c001b000 {
+		compatible = "nexell,nexell-gpio";
+		reg = <0xc001b000 0x00000010>;
+		altr,gpio-bank-width = <32>;
+		gpio-bank-name = "gpio_b";
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	gpio_c:gpio at c001c000 {
+		compatible = "nexell,nexell-gpio";
+		reg = <0xc001c000 0x00000010>;
+		nexell,gpio-bank-width = <32>;
+		gpio-bank-name = "gpio_c";
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	gpio_d:gpio at c001d000 {
+		compatible = "nexell,nexell-gpio";
+		reg = <0xc001d000 0x00000010>;
+		nexell,gpio-bank-width = <32>;
+		gpio-bank-name = "gpio_d";
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	gpio_e:gpio at c001e000 {
+		compatible = "nexell,nexell-gpio";
+		reg = <0xc001e000 0x00000010>;
+		nexell,gpio-bank-width = <32>;
+		gpio-bank-name = "gpio_e";
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	gpio_alv:gpio at c0010800 {
+		compatible = "nexell,nexell-gpio";
+		reg = <0xc0010800 0x00000010>;
+		nexell,gpio-bank-width = <32>;
+		gpio-bank-name = "gpio_alv";
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+};
diff --git a/board/friendlyarm/Kconfig b/board/friendlyarm/Kconfig
new file mode 100644
index 0000000..8f79640
--- /dev/null
+++ b/board/friendlyarm/Kconfig
@@ -0,0 +1,39 @@
+
+#config SYS_CONFIG_NAME
+#	string "Board header file"
+#	help
+#	  This option should contain the base name of board header file.
+#	  The header file include/configs/<CONFIG_SYS_CONFIG_NAME>.h
+#	  should be included from include/config.h.
+
+config S5P4418_ONEWIRE
+	bool "S5P4418_ONEWIRE"
+	#default y
+
+config PWM_NX
+	bool "PWM_NX"
+	#default y
+
+config SYS_RESERVE_MEM_SIZE
+	hex "SYS_RESERVE_MEM_SIZE"
+
+config ROOT_DEV
+	int "ROOT_DEV"
+	help
+	  Environment variable rootdev is set to this value if env. var. firstboot
+	  does not exist. Otherwise rootdev is set to the MMC boot device. rootdev
+	  determines (together with env. var. bootpart) where the OS (linux) is
+	  booted from.
+
+config BOOT_PART
+	int "BOOT_PART"
+	help
+	  Environment variable bootpart is set to this value. bootpart determines
+	  (together with env. var. rootdev) where the OS (linux) is booted from.
+
+config ROOT_PART
+	int "ROOT_PART"
+	help
+	  Environment variable rootpart is set to this value.
+
+source "board/friendlyarm/nanopi2/Kconfig"
diff --git a/board/friendlyarm/nanopi2/Kconfig b/board/friendlyarm/nanopi2/Kconfig
new file mode 100644
index 0000000..0f68422
--- /dev/null
+++ b/board/friendlyarm/nanopi2/Kconfig
@@ -0,0 +1,12 @@
+if TARGET_NANOPI2
+
+config SYS_BOARD
+	default "nanopi2"
+
+config SYS_VENDOR
+	default "friendlyarm"
+
+config SYS_CONFIG_NAME
+	default "s5p4418_nanopi2"
+
+endif
diff --git a/board/friendlyarm/nanopi2/MAINTAINERS b/board/friendlyarm/nanopi2/MAINTAINERS
new file mode 100644
index 0000000..c8e2ce7
--- /dev/null
+++ b/board/friendlyarm/nanopi2/MAINTAINERS
@@ -0,0 +1,7 @@
+NANOPI2 BOARD
+NANOPC-T2 BOARD
+M:  Stefan Bosch <stefan_b@posteo.net>
+S:  Maintained
+F:  board/s5p4418/nanopi2/
+F:  include/configs/s5p4418_nanopi2.h
+F:  configs/s5p4418_nanopi2_defconfig
diff --git a/board/friendlyarm/nanopi2/Makefile b/board/friendlyarm/nanopi2/Makefile
new file mode 100644
index 0000000..cd459f2
--- /dev/null
+++ b/board/friendlyarm/nanopi2/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2016 Nexell
+# Hyunseok, Jung <hsjung@nexell.co.kr>
+
+obj-y	:= board.o hwrev.o onewire.o lcds.o
diff --git a/board/friendlyarm/nanopi2/board.c b/board/friendlyarm/nanopi2/board.c
new file mode 100644
index 0000000..63094b5
--- /dev/null
+++ b/board/friendlyarm/nanopi2/board.c
@@ -0,0 +1,567 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) Guangzhou FriendlyARM Computer Tech. Co., Ltd.
+ * (http://www.friendlyarm.com)
+ */
+
+#include <config.h>
+#include <common.h>
+#ifdef CONFIG_PWM_NX
+#include <pwm.h>
+#endif
+#include <asm/io.h>
+
+#include <asm/arch/nexell.h>
+#include <asm/arch/nx_gpio.h>
+#include <asm/arch/display.h>
+#include <asm/arch/display_dev.h>
+
+#include <u-boot/md5.h>
+
+#include "hwrev.h"
+#include "onewire.h"
+#include "nxp-fb.h"
+
+#include <env_internal.h>	/* for env_save() */
+#include <asm/mach-types.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+enum gpio_group {
+	gpio_a, gpio_b, gpio_c, gpio_d, gpio_e,
+};
+
+#ifdef CONFIG_PWM_NX
+struct pwm_device {
+	int grp;
+	int bit;
+	int io_fn;
+};
+
+static inline void bd_pwm_config_gpio(int ch)
+{
+	struct pwm_device pwm_dev[] = {
+		[0] = { .grp = gpio_d, .bit = 1,  .io_fn = 0 },
+		[1] = { .grp = gpio_c, .bit = 13, .io_fn = 1 },
+		[2] = { .grp = gpio_c, .bit = 14, .io_fn = 1 },
+		[3] = { .grp = gpio_d, .bit = 0,  .io_fn = 0 },
+	};
+
+	int gp = pwm_dev[ch].grp;
+	int io = pwm_dev[ch].bit;
+
+	/* pwm backlight OFF: HIGH, ON: LOW */
+	nx_gpio_set_pad_function(gp, io, pwm_dev[ch].io_fn);
+	nx_gpio_set_output_value(gp, io, 1);
+	nx_gpio_set_output_enable(gp, io, 1);
+}
+#endif
+
+static void bd_backlight_off(void)
+{
+#ifdef CONFIG_S5P4418_ONEWIRE
+	onewire_set_backlight(0);
+
+#elif defined(BACKLIGHT_CH)
+	bd_pwm_config_gpio(BACKLIGHT_CH);
+#endif
+}
+
+static void bd_backlight_on(void)
+{
+#ifdef CONFIG_S5P4418_ONEWIRE
+	onewire_set_backlight(127);
+
+#elif defined(BACKLIGHT_CH)
+	/* pwm backlight ON: HIGH, ON: LOW */
+	pwm_init(BACKLIGHT_CH,
+		 BACKLIGHT_DIV, BACKLIGHT_INV);
+	pwm_config(BACKLIGHT_CH,
+		   TO_DUTY_NS(BACKLIGHT_DUTY, BACKLIGHT_HZ),
+		   TO_PERIOD_NS(BACKLIGHT_HZ));
+#endif
+}
+
+static void bd_lcd_config_gpio(void)
+{
+	int i;
+
+	for (i = 0; i < 28; i++) {
+		nx_gpio_set_pad_function(gpio_a, i, 1);
+		nx_gpio_set_drive_strength(gpio_a, i, 0);
+		nx_gpio_set_pull_mode(gpio_a, i, 2);
+	}
+
+	nx_gpio_set_drive_strength(gpio_a, 0, 1);
+}
+
+/* DEFAULT mmc dev for eMMC boot (dwmmc.2) */
+static int mmc_boot_dev = 0;
+
+int board_mmc_bootdev(void)
+{
+	return mmc_boot_dev;
+}
+
+/* call from common/env_mmc.c */
+int mmc_get_env_dev(void)
+{
+	return mmc_boot_dev;
+}
+
+#ifdef CONFIG_DISPLAY_BOARDINFO
+int checkboard(void)
+{
+	printf("Board: %s\n", get_board_name());
+
+	return 0;
+}
+#endif
+
+int nx_display_fixup_dp(struct nx_display_dev *dp)
+{
+	struct nxp_lcd *lcd = bd_get_lcd();
+	enum lcd_format fmt = bd_get_lcd_format();
+	struct nxp_lcd_timing *timing = &lcd->timing;
+	struct dp_sync_info *sync = &dp->sync;
+	struct dp_plane_info *plane = &dp->planes[0];
+	int i;
+	u32 clk = 800000000;
+	u32 div;
+
+	sync->h_active_len = lcd->width;
+	sync->h_sync_width = timing->h_sw;
+	sync->h_back_porch = timing->h_bp;
+	sync->h_front_porch = timing->h_fp;
+	sync->h_sync_invert = !lcd->polarity.inv_hsync;
+
+	sync->v_active_len = lcd->height;
+	sync->v_sync_width = timing->v_sw;
+	sync->v_back_porch = timing->v_bp;
+	sync->v_front_porch = timing->v_fp;
+	sync->v_sync_invert = !lcd->polarity.inv_vsync;
+
+	/* calculates pixel clock */
+	div  = timing->h_sw + timing->h_bp + timing->h_fp + lcd->width;
+	div *= timing->v_sw + timing->v_bp + timing->v_fp + lcd->height;
+	div *= lcd->freq ? : 60;
+	clk /= div;
+
+	dp->ctrl.clk_div_lv0 = clk;
+	dp->ctrl.clk_inv_lv0 = lcd->polarity.rise_vclk;
+
+	dp->top.screen_width = lcd->width;
+	dp->top.screen_height = lcd->height;
+
+	for (i = 0; i < dp->top.plane_num; i++, plane++) {
+		if (plane->enable) {
+			plane->width = lcd->width;
+			plane->height = lcd->height;
+		}
+	}
+
+	/* initialize display device type */
+	if (fmt == LCD_RGB) {
+		dp->dev_type = DP_DEVICE_RGBLCD;
+
+	} else if (fmt == LCD_HDMI) {
+		struct dp_hdmi_dev *dev = (struct dp_hdmi_dev *)dp->device;
+
+		dp->dev_type = DP_DEVICE_HDMI;
+		if (lcd->width == 1920 && lcd->height == 1080)
+			dev->preset = 1;
+		else
+			dev->preset = 0;
+
+	} else {
+		struct dp_lvds_dev *dev = (struct dp_lvds_dev *)dp->device;
+
+		dp->dev_type = DP_DEVICE_LVDS;
+		dev->lvds_format = (fmt & 0x3);
+	}
+
+	return 0;
+}
+
+/* --------------------------------------------------------------------------
+ * initialize board status.
+ */
+
+#define	MMC_BOOT_CH0		(0)
+#define	MMC_BOOT_CH1		(1 <<  3)
+#define	MMC_BOOT_CH2		(1 << 19)
+
+static void bd_bootdev_init(void)
+{
+	unsigned int rst = readl(PHY_BASEADDR_CLKPWR + SYSRSTCONFIG);
+
+	rst &= (1 << 19) | (1 << 3);
+	if (rst == MMC_BOOT_CH0) {
+		/* mmc dev 1 for SD boot */
+		mmc_boot_dev = 1;
+	}
+}
+
+static void bd_onewire_init(void)
+{
+	unsigned char lcd;
+	unsigned short fw_ver;
+
+	onewire_init();
+	onewire_get_info(&lcd, &fw_ver);
+}
+
+static void bd_lcd_init(void)
+{
+	struct nxp_lcd *cfg;
+	int id;
+	int ret;
+
+	id = onewire_get_lcd_id();
+	/* -1: onwire probe failed
+	 *  0: bad
+	 * >0: identified
+	 */
+
+	ret = bd_setup_lcd_by_id(id);
+	if (id <= 0 || ret != id) {
+		printf("Panel: N/A (%d)\n", id);
+		bd_setup_lcd_by_name("HDMI720P60");
+
+	} else {
+		printf("Panel: %s\n", bd_get_lcd_name());
+
+		cfg = bd_get_lcd();
+		if (cfg->gpio_init)
+			cfg->gpio_init();
+	}
+}
+
+static int mac_read_from_generic_eeprom(u8 *addr)
+{
+	return -1;
+}
+
+static void make_ether_addr(u8 *addr)
+{
+	u32 hash[20];
+
+#define ETHER_MAC_TAG  "ethmac"
+	memset(hash, 0, sizeof(hash));
+	memcpy(hash + 12, ETHER_MAC_TAG, sizeof(ETHER_MAC_TAG));
+
+	hash[4] = readl(PHY_BASEADDR_ECID + 0x00);
+	hash[5] = readl(PHY_BASEADDR_ECID + 0x04);
+	hash[6] = readl(PHY_BASEADDR_ECID + 0x08);
+	hash[7] = readl(PHY_BASEADDR_ECID + 0x0c);
+
+	md5((unsigned char *)&hash[4], 64, (unsigned char *)hash);
+
+	hash[0] ^= hash[2];
+	hash[1] ^= hash[3];
+
+	memcpy(addr, (char *)hash, 6);
+	addr[0] &= 0xfe;	/* clear multicast bit */
+	addr[0] |= 0x02;
+}
+
+static void set_ether_addr(void)
+{
+	unsigned char mac[6];
+	char ethaddr[20];
+	int ret;
+
+	if (env_get("ethaddr"))
+		return;
+
+	ret = mac_read_from_generic_eeprom(mac);
+	if (ret < 0)
+		make_ether_addr(mac);
+
+	sprintf(ethaddr, "%02x:%02x:%02x:%02x:%02x:%02x",
+		mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+	if (!ret)
+		printf("MAC:  [%s]\n", ethaddr);
+
+	env_set("ethaddr", ethaddr);
+}
+
+#ifdef CONFIG_REVISION_TAG
+static void set_board_rev(void)
+{
+	char info[64] = {0, };
+
+	snprintf(info, ARRAY_SIZE(info), "%02x", get_board_rev());
+	env_set("board_rev", info);
+}
+#endif
+
+static void set_dtb_name(void)
+{
+	char info[64] = {0, };
+
+	snprintf(info, ARRAY_SIZE(info),
+		 "s5p4418-nanopi2-rev%02x.dtb", get_board_rev());
+	env_set("dtb_name", info);
+}
+
+static void bd_update_env(void)
+{
+	char *lcdtype = env_get("lcdtype");
+	char *lcddpi = env_get("lcddpi");
+	char *bootargs = env_get("bootargs");
+	const char *name;
+	char *p = NULL;
+	int rootdev = board_mmc_bootdev();
+	int need_save = 0;
+
+#define CMDLINE_LCD		" lcd="
+	char cmdline[CONFIG_SYS_CBSIZE];
+	int n = 1;
+
+	if (rootdev != CONFIG_ROOT_DEV && !env_get("firstboot")) {
+		env_set_ulong("rootdev", rootdev);
+		env_set("firstboot", "0");
+		need_save = 1;
+	}
+
+	if (lcdtype) {
+		/* Setup again as user specified LCD in env */
+		bd_setup_lcd_by_name(lcdtype);
+	}
+
+	name = bd_get_lcd_name();
+
+	if (bootargs)
+		n = strlen(bootargs);	/* isn't 0 for NULL */
+	else
+		cmdline[0] = '\0';
+
+	if ((n + strlen(name) + sizeof(CMDLINE_LCD)) > sizeof(cmdline)) {
+		printf("Error: `bootargs' is too large (%d)\n", n);
+		goto __exit;
+	}
+
+	if (bootargs) {
+		p = strstr(bootargs, CMDLINE_LCD);
+		if (p) {
+			n = (p - bootargs);
+			p += strlen(CMDLINE_LCD);
+		}
+		strncpy(cmdline, bootargs, n);
+	}
+
+	/* add `lcd=NAME,NUMdpi' */
+	strncpy(cmdline + n, CMDLINE_LCD, strlen(CMDLINE_LCD));
+	n += strlen(CMDLINE_LCD);
+
+	strcpy(cmdline + n, name);
+	n += strlen(name);
+
+	if (lcddpi) {
+		n += sprintf(cmdline + n, ",%sdpi", lcddpi);
+	} else {
+		int dpi = bd_get_lcd_density();
+
+		if (dpi > 0 && dpi < 600)
+			n += sprintf(cmdline + n, ",%ddpi", dpi);
+	}
+
+	/* copy remaining of bootargs */
+	if (p) {
+		p = strstr(p, " ");
+		if (p) {
+			strcpy(cmdline + n, p);
+			n += strlen(p);
+		}
+	}
+
+	/* append `bootdev=2' */
+#define CMDLINE_BDEV	" bootdev="
+	if (rootdev > 0 && !strstr(cmdline, CMDLINE_BDEV))
+		n += sprintf(cmdline + n, "%s2", CMDLINE_BDEV);
+
+	/* finally, let's update uboot env & save it */
+	if (bootargs && strncmp(cmdline, bootargs, sizeof(cmdline))) {
+		env_set("bootargs", cmdline);
+		need_save = 1;
+	}
+
+__exit:
+	if (need_save)
+		env_save();
+}
+
+/* --------------------------------------------------------------------------
+ * call from u-boot
+ */
+
+int board_early_init_f(void)
+{
+	return 0;
+}
+
+int board_init(void)
+{
+	bd_hwrev_init();
+	bd_base_rev_init();
+
+	bd_bootdev_init();
+	bd_onewire_init();
+
+	bd_backlight_off();
+
+	bd_lcd_config_gpio();
+	bd_lcd_init();
+
+#ifdef CONFIG_SILENT_CONSOLE
+	gd->flags |= GD_FLG_SILENT;
+#endif
+
+	return 0;
+}
+
+#ifdef CONFIG_BOARD_LATE_INIT
+int board_late_init(void)
+{
+	bd_update_env();
+
+#ifdef CONFIG_REVISION_TAG
+	set_board_rev();
+#endif
+	set_dtb_name();
+
+	set_ether_addr();
+
+#ifdef CONFIG_SILENT_CONSOLE
+	gd->flags &= ~GD_FLG_SILENT;
+#endif
+
+	bd_backlight_on();
+	printf("\n");
+
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_SPLASH_SOURCE
+#include <splash.h>
+static struct splash_location splash_locations[] = {
+	{
+	.name = "mmc_fs",
+	.storage = SPLASH_STORAGE_MMC,
+	.flags = SPLASH_STORAGE_FS,
+	.devpart = __stringify(CONFIG_ROOT_DEV) ":"
+		   __stringify(CONFIG_BOOT_PART),
+	},
+};
+
+int splash_screen_prepare(void)
+{
+	int err;
+	char *env_cmd = env_get("load_splash");
+
+	debug("%s()\n", __func__);
+
+	if (env_cmd) {
+		err = run_command(env_cmd, 0);
+
+	} else {
+		char devpart[64] = { 0, };
+		int bootpart = env_get_ulong("bootpart", 0, CONFIG_BOOT_PART);
+		int rootdev;
+
+		if (env_get("firstboot"))
+			rootdev = env_get_ulong("rootdev", 0, CONFIG_ROOT_DEV);
+		else
+			rootdev = board_mmc_bootdev();
+
+		snprintf(devpart, ARRAY_SIZE(devpart), "%d:%d", rootdev,
+			 bootpart);
+		splash_locations[0].devpart = devpart;
+
+		err = splash_source_load(splash_locations,
+					 ARRAY_SIZE(splash_locations));
+	}
+
+	if (!err) {
+		char addr[64];
+
+		sprintf(addr, "0x%lx", gd->fb_base);
+		env_set("fb_addr", addr);
+	}
+
+	return err;
+}
+#endif
+
+/* u-boot dram initialize */
+int dram_init(void)
+{
+	gd->ram_size = CONFIG_SYS_SDRAM_SIZE;
+	return 0;
+}
+
+/* u-boot dram board specific */
+int dram_init_banksize(void)
+{
+#define SCR_USER_SIG6_READ		(SCR_ALIVE_BASE + 0x0F0)
+	unsigned int reg_val = readl(SCR_USER_SIG6_READ);
+
+	/* set global data memory */
+	gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x00000100;
+
+	gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
+	gd->bd->bi_dram[0].size  = CONFIG_SYS_SDRAM_SIZE;
+
+	/* Number of Row: 14 bits */
+	if ((reg_val >> 28) == 14)
+		gd->bd->bi_dram[0].size -= 0x20000000;
+
+	/* Number of Memory Chips */
+	if ((reg_val & 0x3) > 1) {
+		gd->bd->bi_dram[1].start = 0x80000000;
+		gd->bd->bi_dram[1].size  = 0x40000000;
+	}
+	return 0;
+}
+
+#if defined(CONFIG_OF_BOARD_SETUP)
+int ft_board_setup(void *blob, bd_t *bd)
+{
+	int nodeoff;
+	unsigned int rootdev;
+	unsigned int fb_addr;
+
+	if (board_mmc_bootdev() > 0) {
+		rootdev = fdt_getprop_u32_default(blob, "/board", "sdidx", 2);
+		if (rootdev) {
+			/* find or create "/chosen" node. */
+			nodeoff = fdt_find_or_add_subnode(blob, 0, "chosen");
+			if (nodeoff >= 0)
+				fdt_setprop_u32(blob, nodeoff, "linux,rootdev",
+						rootdev);
+		}
+	}
+
+	fb_addr = env_get_ulong("fb_addr", 0, 0);
+	if (fb_addr) {
+		nodeoff = fdt_path_offset(blob, "/reserved-memory");
+		if (nodeoff < 0)
+			return nodeoff;
+
+		nodeoff = fdt_add_subnode(blob, nodeoff, "display_reserved");
+		if (nodeoff >= 0) {
+			fdt32_t cells[2];
+
+			cells[0] = cpu_to_fdt32(fb_addr);
+			cells[1] = cpu_to_fdt32(0x800000);
+
+			fdt_setprop(blob, nodeoff, "reg", cells,
+				    sizeof(cells[0]) * 2);
+		}
+	}
+
+	return 0;
+}
+#endif
diff --git a/board/friendlyarm/nanopi2/hwrev.c b/board/friendlyarm/nanopi2/hwrev.c
new file mode 100644
index 0000000..ced9b26
--- /dev/null
+++ b/board/friendlyarm/nanopi2/hwrev.c
@@ -0,0 +1,108 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) Guangzhou FriendlyARM Computer Tech. Co., Ltd.
+ * (http://www.friendlyarm.com)
+ */
+
+#include <config.h>
+#include <common.h>
+#include <i2c.h>
+#include <asm/io.h>
+
+#include <asm/arch/nexell.h>
+#include <asm/arch/nx_gpio.h>
+
+/* Board revision list: <PCB3 | PCB2 | PCB1>
+ *  0b000 - NanoPi 2
+ *  0b001 - NanoPC-T2
+ *  0b010 - NanoPi S2
+ *  0b011 - Smart4418
+ *  0b100 - NanoPi Fire 2A
+ *  0b111 - NanoPi M2A
+ *
+ * Extented revision:
+ *  0b001 - Smart4418-SDK
+ */
+#define __IO_GRP		2	/* GPIO_C */
+#define __IO_PCB1			26
+#define __IO_PCB2			27
+#define __IO_PCB3			25
+
+static int pcb_rev = -1;
+static int base_rev	= 0;
+
+static void bd_hwrev_config_gpio(void)
+{
+	int gpios[3][2] = {
+		{ __IO_PCB1, 1 },
+		{ __IO_PCB2, 1 },
+		{ __IO_PCB3, 1 },
+	};
+	int i;
+
+	/* gpio input mode, pull-down */
+	for (i = 0; i < 3; i++) {
+		nx_gpio_set_pad_function(__IO_GRP, gpios[i][0], gpios[i][1]);
+		nx_gpio_set_output_enable(__IO_GRP, gpios[i][0], 0);
+		nx_gpio_set_pull_mode(__IO_GRP, gpios[i][0], 0);
+	}
+}
+
+void bd_hwrev_init(void)
+{
+	if (pcb_rev >= 0)
+		return;
+
+	bd_hwrev_config_gpio();
+
+	pcb_rev  = nx_gpio_get_input_value(__IO_GRP, __IO_PCB1);
+	pcb_rev |= nx_gpio_get_input_value(__IO_GRP, __IO_PCB2) << 1;
+	pcb_rev |= nx_gpio_get_input_value(__IO_GRP, __IO_PCB3) << 2;
+}
+
+/* Get extended revision for SmartXX18 */
+void bd_base_rev_init(void)
+{
+	struct udevice *dev;
+	u8 val = 0;
+
+	if (pcb_rev != 0x3)
+		return;
+
+#define PCA9536_I2C_BUS     2
+#define PCA9636_I2C_ADDR    0x41
+	if (i2c_get_chip_for_busnum
+				(PCA9536_I2C_BUS, PCA9636_I2C_ADDR, 1, &dev))
+		return;
+
+	if (!dm_i2c_read(dev, 0, &val, 1))
+		base_rev = (val & 0xf);
+}
+
+/* To override __weak symbols */
+u32 get_board_rev(void)
+{
+	return (base_rev << 8) | pcb_rev;
+}
+
+const char *get_board_name(void)
+{
+	bd_hwrev_init();
+
+	switch (pcb_rev) {
+	case 0:
+		return "NanoPi 2";
+	case 1:
+		return "NanoPC-T2";
+	case 2:
+		return "NanoPi S2";
+	case 3:
+		return "Smart4418";
+	case 4:
+		return "NanoPi Fire 2A";
+	case 7:
+		return "NanoPi M2A";
+	default:
+		return "s5p4418-X";
+	}
+}
diff --git a/board/friendlyarm/nanopi2/hwrev.h b/board/friendlyarm/nanopi2/hwrev.h
new file mode 100644
index 0000000..1b1a828
--- /dev/null
+++ b/board/friendlyarm/nanopi2/hwrev.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0+
+ *
+ * Copyright (C) Guangzhou FriendlyARM Computer Tech. Co., Ltd.
+ * (http://www.friendlyarm.com)
+ */
+
+#ifndef __BD_HW_REV_H__
+#define __BD_HW_REV_H__
+
+extern void bd_hwrev_init(void);
+extern void bd_base_rev_init(void);
+extern u32 get_board_rev(void);
+extern const char *get_board_name(void);
+
+#endif /* __BD_HW_REV_H__ */
diff --git a/board/friendlyarm/nanopi2/lcds.c b/board/friendlyarm/nanopi2/lcds.c
new file mode 100644
index 0000000..b3aee5c
--- /dev/null
+++ b/board/friendlyarm/nanopi2/lcds.c
@@ -0,0 +1,697 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2017 FriendlyARM (www.arm9.net)
+ */
+
+#include <config.h>
+#include <common.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <fdt_support.h>
+#include <asm/io.h>
+
+#include <asm/arch/nexell.h>
+#include <asm/arch/display.h>
+#include <asm/arch/nx_gpio.h>
+
+#include "nxp-fb.h"
+
+/*
+ * param @module_index for nx_gpio APIs and will be removed
+ * after support pinctrl
+ */
+#ifndef PAD_GPIO_A
+#define PAD_GPIO_A	0
+#endif
+
+static inline void common_gpio_init(void)
+{
+	/* PVCLK */
+	nx_gpio_set_fast_slew(PAD_GPIO_A, 0, 1);
+}
+
+static void s70_gpio_init(void)
+{
+	int i;
+
+	/* PVCLK */
+	nx_gpio_set_drive_strength(PAD_GPIO_A, 0, 1);
+
+	/* RGB24 */
+	for (i = 1; i < 25; i++)
+		nx_gpio_set_drive_strength(PAD_GPIO_A, i, 2);
+
+	/* HS/VS/DE */
+	for (; i < 28; i++)
+		nx_gpio_set_drive_strength(PAD_GPIO_A, i, 1);
+}
+
+static void s702_gpio_init(void)
+{
+	int i;
+
+	common_gpio_init();
+
+	nx_gpio_set_drive_strength(PAD_GPIO_A, 0, 2);
+
+	for (i = 1; i < 25; i++)
+		nx_gpio_set_drive_strength(PAD_GPIO_A, i, 0);
+
+	for (; i < 28; i++)
+		nx_gpio_set_drive_strength(PAD_GPIO_A, i, 1);
+}
+
+static void s430_gpio_init(void)
+{
+	int  i;
+
+	for (i = 0; i < 28; i++)
+		nx_gpio_set_drive_strength(PAD_GPIO_A, i, 1);
+}
+
+static void hd101_gpio_init(void)
+{
+	int i;
+
+	common_gpio_init();
+
+	nx_gpio_set_drive_strength(PAD_GPIO_A, 0, 2);
+
+	for (i = 1; i < 25; i++)
+		nx_gpio_set_drive_strength(PAD_GPIO_A, i, 1);
+
+	nx_gpio_set_drive_strength(PAD_GPIO_A, 27, 1);
+}
+
+static void hd700_gpio_init(void)
+{
+	hd101_gpio_init();
+}
+
+/* NXP display configs for supported LCD */
+
+static struct nxp_lcd wxga_hd700 = {
+	.width = 800,
+	.height = 1280,
+	.p_width = 94,
+	.p_height = 151,
+	.bpp = 24,
+	.freq = 60,
+
+	.timing = {
+		.h_fp = 20,
+		.h_bp = 20,
+		.h_sw = 24,
+		.v_fp =  4,
+		.v_fpe = 1,
+		.v_bp =  4,
+		.v_bpe = 1,
+		.v_sw =  8,
+	},
+	.polarity = {
+		.rise_vclk = 0,
+		.inv_hsync = 0,
+		.inv_vsync = 0,
+		.inv_vden = 0,
+	},
+	.gpio_init = hd700_gpio_init,
+};
+
+static struct nxp_lcd wvga_s70 = {
+	.width = 800,
+	.height = 480,
+	.p_width = 155,
+	.p_height = 93,
+	.bpp = 24,
+	.freq = 61,
+
+	.timing = {
+		.h_fp = 48,
+		.h_bp = 36,
+		.h_sw = 10,
+		.v_fp = 22,
+		.v_fpe = 1,
+		.v_bp = 15,
+		.v_bpe = 1,
+		.v_sw = 8,
+	},
+	.polarity = {
+		.rise_vclk = 0,
+		.inv_hsync = 1,
+		.inv_vsync = 1,
+		.inv_vden = 0,
+	},
+	.gpio_init = s70_gpio_init,
+};
+
+static struct nxp_lcd wvga_s702 = {
+	.width = 800,
+	.height = 480,
+	.p_width = 155,
+	.p_height = 93,
+	.bpp = 24,
+	.freq = 61,
+
+	.timing = {
+		.h_fp = 44,
+		.h_bp = 26,
+		.h_sw = 20,
+		.v_fp = 22,
+		.v_fpe = 1,
+		.v_bp = 15,
+		.v_bpe = 1,
+		.v_sw = 8,
+	},
+	.polarity = {
+		.rise_vclk = 1,
+		.inv_hsync = 1,
+		.inv_vsync = 1,
+		.inv_vden = 0,
+	},
+	.gpio_init = s702_gpio_init,
+};
+
+static struct nxp_lcd wvga_s70d = {
+	.width = 800,
+	.height = 480,
+	.p_width = 155,
+	.p_height = 93,
+	.bpp = 24,
+	.freq = 61,
+
+	.timing = {
+		.h_fp = 80,
+		.h_bp = 78,
+		.h_sw = 10,
+		.v_fp = 22,
+		.v_fpe = 1,
+		.v_bp = 24,
+		.v_bpe = 1,
+		.v_sw = 8,
+	},
+	.polarity = {
+		.rise_vclk = 0,
+		.inv_hsync = 1,
+		.inv_vsync = 1,
+		.inv_vden = 0,
+	},
+	.gpio_init = s702_gpio_init,
+};
+
+static struct nxp_lcd wvga_w50 = {
+	.width = 800,
+	.height = 480,
+	.p_width = 108,
+	.p_height = 64,
+	.bpp = 24,
+	.freq = 61,
+
+	.timing = {
+		.h_fp = 40,
+		.h_bp = 40,
+		.h_sw = 48,
+		.v_fp = 20,
+		.v_fpe = 1,
+		.v_bp = 20,
+		.v_bpe = 1,
+		.v_sw = 12,
+	},
+	.polarity = {
+		.rise_vclk = 0,
+		.inv_hsync = 1,
+		.inv_vsync = 1,
+		.inv_vden = 0,
+	},
+	.gpio_init = s70_gpio_init,
+};
+
+static struct nxp_lcd wvga_s430 = {
+	.width = 480,
+	.height = 800,
+	.p_width = 108,
+	.p_height = 64,
+	.bpp = 24,
+	.freq = 60,
+
+	.timing = {
+		.h_fp = 64,
+		.h_bp = 0,
+		.h_sw = 16,
+		.v_fp = 32,
+		.v_fpe = 1,
+		.v_bp = 0,
+		.v_bpe = 1,
+		.v_sw = 16,
+	},
+	.polarity = {
+		.rise_vclk = 1,
+		.inv_hsync = 1,
+		.inv_vsync = 1,
+		.inv_vden = 0,
+	},
+	.gpio_init = s430_gpio_init,
+};
+
+static struct nxp_lcd wsvga_w101 = {
+	.width = 1024,
+	.height = 600,
+	.p_width = 204,
+	.p_height = 120,
+	.bpp = 24,
+	.freq = 60,
+
+	.timing = {
+		.h_fp = 40,
+		.h_bp = 40,
+		.h_sw = 200,
+		.v_fp =  8,
+		.v_fpe = 1,
+		.v_bp =  8,
+		.v_bpe = 1,
+		.v_sw = 16,
+	},
+	.polarity = {
+		.rise_vclk = 1,
+		.inv_hsync = 1,
+		.inv_vsync = 1,
+		.inv_vden = 0,
+	},
+};
+
+static struct nxp_lcd wsvga_x710 = {
+	.width = 1024,
+	.height = 600,
+	.p_width = 154,
+	.p_height = 90,
+	.bpp = 24,
+	.freq = 61,
+
+	.timing = {
+		.h_fp = 84,
+		.h_bp = 84,
+		.h_sw = 88,
+		.v_fp = 10,
+		.v_fpe = 1,
+		.v_bp = 10,
+		.v_bpe = 1,
+		.v_sw = 20,
+	},
+	.polarity = {
+		.rise_vclk = 0,
+		.inv_hsync = 1,
+		.inv_vsync = 1,
+		.inv_vden = 0,
+	},
+	.gpio_init = hd101_gpio_init,
+};
+
+static struct nxp_lcd xga_a97 = {
+	.width = 1024,
+	.height = 768,
+	.p_width = 200,
+	.p_height = 150,
+	.bpp = 24,
+	.freq = 61,
+
+	.timing = {
+		.h_fp = 12,
+		.h_bp = 12,
+		.h_sw = 4,
+		.v_fp = 8,
+		.v_fpe = 1,
+		.v_bp = 8,
+		.v_bpe = 1,
+		.v_sw =  4,
+	},
+	.polarity = {
+		.rise_vclk = 0,
+		.inv_hsync = 1,
+		.inv_vsync = 1,
+		.inv_vden = 0,
+	},
+};
+
+static struct nxp_lcd xga_lq150 = {
+	.width = 1024,
+	.height = 768,
+	.p_width = 304,
+	.p_height = 228,
+	.bpp = 24,
+	.freq = 60,
+
+	.timing = {
+		.h_fp = 12,
+		.h_bp = 12,
+		.h_sw = 40,
+		.v_fp = 8,
+		.v_fpe = 1,
+		.v_bp = 8,
+		.v_bpe = 1,
+		.v_sw = 40,
+	},
+	.polarity = {
+		.rise_vclk = 0,
+		.inv_hsync = 1,
+		.inv_vsync = 1,
+		.inv_vden = 0,
+	},
+};
+
+static struct nxp_lcd vga_l80 = {
+	.width = 640,
+	.height = 480,
+	.p_width = 160,
+	.p_height = 120,
+	.bpp = 32,
+	.freq = 60,
+
+	.timing = {
+		.h_fp = 35,
+		.h_bp = 53,
+		.h_sw = 73,
+		.v_fp = 3,
+		.v_fpe = 1,
+		.v_bp = 29,
+		.v_bpe = 1,
+		.v_sw = 6,
+	},
+	.polarity = {
+		.rise_vclk = 0,
+		.inv_hsync = 1,
+		.inv_vsync = 1,
+		.inv_vden = 0,
+	},
+};
+
+static struct nxp_lcd wxga_bp101 = {
+	.width = 1280,
+	.height = 800,
+	.p_width = 218,
+	.p_height = 136,
+	.bpp = 24,
+	.freq = 60,
+
+	.timing = {
+		.h_fp = 20,
+		.h_bp = 20,
+		.h_sw = 24,
+		.v_fp =  4,
+		.v_fpe = 1,
+		.v_bp =  4,
+		.v_bpe = 1,
+		.v_sw =  8,
+	},
+	.polarity = {
+		.rise_vclk = 1,
+		.inv_hsync = 1,
+		.inv_vsync = 1,
+		.inv_vden = 0,
+	},
+};
+
+static struct nxp_lcd wxga_hd101 = {
+	.width = 1280,
+	.height = 800,
+	.p_width = 218,
+	.p_height = 136,
+	.bpp = 24,
+	.freq = 60,
+
+	.timing = {
+		.h_fp = 16,
+		.h_bp = 16,
+		.h_sw = 30,
+		.v_fp =  8,
+		.v_fpe = 1,
+		.v_bp =  8,
+		.v_bpe = 1,
+		.v_sw = 12,
+	},
+	.polarity = {
+		.rise_vclk = 1,
+		.inv_hsync = 0,
+		.inv_vsync = 0,
+		.inv_vden = 0,
+	},
+	.gpio_init = hd101_gpio_init,
+};
+
+static struct nxp_lcd hvga_h43 = {
+	.width = 480,
+	.height = 272,
+	.p_width = 96,
+	.p_height = 54,
+	.bpp = 32,
+	.freq = 65,
+
+	.timing = {
+		.h_fp =  5,
+		.h_bp = 40,
+		.h_sw =  2,
+		.v_fp =  8,
+		.v_fpe = 1,
+		.v_bp =  8,
+		.v_bpe = 1,
+		.v_sw =  2,
+	},
+	.polarity = {
+		.rise_vclk = 0,
+		.inv_hsync = 1,
+		.inv_vsync = 1,
+		.inv_vden = 0,
+	},
+};
+
+static struct nxp_lcd hvga_p43 = {
+	.width = 480,
+	.height = 272,
+	.p_width = 96,
+	.p_height = 54,
+	.bpp = 32,
+	.freq = 65,
+
+	.timing = {
+		.h_fp =  5,
+		.h_bp = 40,
+		.h_sw =  2,
+		.v_fp =  8,
+		.v_fpe = 1,
+		.v_bp =  9,
+		.v_bpe = 1,
+		.v_sw =  2,
+	},
+	.polarity = {
+		.rise_vclk = 1,
+		.inv_hsync = 1,
+		.inv_vsync = 1,
+		.inv_vden = 0,
+	},
+};
+
+static struct nxp_lcd qvga_w35 = {
+	.width = 320,
+	.height = 240,
+	.p_width = 70,
+	.p_height = 52,
+	.bpp = 16,
+	.freq = 65,
+
+	.timing = {
+		.h_fp =  4,
+		.h_bp = 70,
+		.h_sw =  4,
+		.v_fp =  4,
+		.v_fpe = 1,
+		.v_bp = 12,
+		.v_bpe = 1,
+		.v_sw =  4,
+	},
+	.polarity = {
+		.rise_vclk = 1,
+		.inv_hsync = 0,
+		.inv_vsync = 0,
+		.inv_vden = 0,
+	},
+};
+
+/* HDMI */
+static struct nxp_lcd hdmi_def = {
+	.width = 1920,
+	.height = 1080,
+	.p_width = 480,
+	.p_height = 320,
+	.bpp = 24,
+	.freq = 60,
+
+	.timing = {
+		.h_fp = 12,
+		.h_bp = 12,
+		.h_sw = 4,
+		.v_fp = 8,
+		.v_fpe = 1,
+		.v_bp = 8,
+		.v_bpe = 1,
+		.v_sw =  4,
+	},
+	.polarity = {
+		.rise_vclk = 0,
+		.inv_hsync = 1,
+		.inv_vsync = 1,
+		.inv_vden = 0,
+	},
+};
+
+static struct hdmi_config {
+	char *name;
+	int width;
+	int height;
+} bd_hdmi_config[] = {
+	{ "HDMI1080P60",	1920, 1080 },
+	{ "HDMI1080I60",	1920, 1080 },
+	{ "HDMI1080P30",	1920, 1080 },
+	{ "HDMI1080P50",	1920, 1080 },
+	{ "HDMI1080I50",	1920, 1080 },
+
+	{ "HDMI1080P60D",	 960,  536 },
+	{ "HDMI1080I60D",	 960,  536 },
+	{ "HDMI1080P30D",	 960,  536 },
+	{ "HDMI1080P50D",	 960,  536 },
+	{ "HDMI1080I50D",	 960,  536 },
+
+	{ "HDMI720P60",		1280,  720 },
+	{ "HDMI720P60D",	 640,  360 },
+	{ "HDMI720P50",		1280,  720 },
+	{ "HDMI720P50D",	 640,  360 },
+
+	{ "HDMI576P16X9",	 720,  576 },
+	{ "HDMI576P16X9D",	 720,  576 },
+	{ "HDMI576P4X3",	 720,  576 },
+	{ "HDMI576P4X3D",	 720,  576 },
+
+	{ "HDMI480P16X9",	 720,  480 },
+	{ "HDMI480P16X9D",	 720,  480 },
+	{ "HDMI480P4X3",	 720,  480 },
+	{ "HDMI480P4X3D",	 720,  480 },
+};
+
+/* Try to guess LCD panel by kernel command line, or
+ * using *HD101* as default
+ */
+static struct {
+	int id;
+	char *name;
+	struct nxp_lcd *lcd;
+	int dpi;
+	int ctp;
+	enum lcd_format fmt;
+} bd_lcd_config[] = {
+	{  25, "HD101",	 &wxga_hd101,   0, 1, LCD_RGB  },
+	{  32, "HD101B", &wxga_hd101,   0, 1, LCD_RGB  },
+	{  18, "HD700",	 &wxga_hd700, 213, 1, LCD_RGB  },
+	{  30, "HD702",	 &wxga_hd700, 213, 1, LCD_RGB  },
+	{  33, "H70",	 &wxga_hd700, 213, 0, LCD_VESA },
+	{   3, "S70",	 &wvga_s70,   128, 1, LCD_RGB  },
+	{  36, "S701",	 &wvga_s70,   128, 1, LCD_RGB  },
+	{  24, "S702",	 &wvga_s702,  128, 3, LCD_RGB  },
+	{  26, "S70D",	 &wvga_s70d,  128, 0, LCD_RGB  },
+	{  14, "H43",	 &hvga_h43,     0, 0, LCD_RGB  },
+	{  19, "P43",	 &hvga_p43,     0, 0, LCD_RGB  },
+	{   8, "W35",	 &qvga_w35,     0, 0, LCD_RGB  },
+	{  28, "X710",	 &wsvga_x710,   0, 1, LCD_RGB  },
+	{  31, "S430",	 &wvga_s430,  180, 1, LCD_RGB  },
+	{   4, "W50",	 &wvga_w50,     0, 0, LCD_RGB  },
+
+	/* TODO: Testing */
+	{  15, "W101",	 &wsvga_w101,   0, 1, LCD_RGB  },
+	{   5, "L80",	 &vga_l80,      0, 1, LCD_RGB  },
+	{  -1, "A97",	 &xga_a97,      0, 0, LCD_RGB  },
+	{  -1, "LQ150",	 &xga_lq150,    0, 1, LCD_RGB  },
+	{  -1, "BP101",	 &wxga_bp101,   0, 1, LCD_RGB  },
+	/* Pls keep it@last */
+	{ 128, "HDMI",	 &hdmi_def,     0, 0, LCD_HDMI },
+};
+
+static int lcd_idx = 0;
+
+int bd_setup_lcd_by_id(int id)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bd_lcd_config); i++) {
+		if (bd_lcd_config[i].id == id) {
+			lcd_idx = i;
+			break;
+		}
+	}
+
+	if (i >= ARRAY_SIZE(bd_lcd_config)) {
+		/* NOT found */
+		return -19;
+	}
+
+	return bd_lcd_config[i].id;
+}
+
+int bd_setup_lcd_by_name(char *str)
+{
+	char *delim;
+	int i;
+
+	delim = strchr(str, ',');
+	if (delim)
+		*delim++ = '\0';
+
+	if (!strncasecmp("HDMI", str, 4)) {
+		struct hdmi_config *cfg = &bd_hdmi_config[0];
+		struct nxp_lcd *lcd;
+
+		lcd_idx = ARRAY_SIZE(bd_lcd_config) - 1;
+		lcd = bd_lcd_config[lcd_idx].lcd;
+
+		for (i = 0; i < ARRAY_SIZE(bd_hdmi_config); i++, cfg++) {
+			if (!strcasecmp(cfg->name, str)) {
+				lcd->width = cfg->width;
+				lcd->height = cfg->height;
+				bd_lcd_config[lcd_idx].name = cfg->name;
+				goto __ret;
+			}
+		}
+	}
+
+	for (i = 0; i < ARRAY_SIZE(bd_lcd_config); i++) {
+		if (!strcasecmp(bd_lcd_config[i].name, str)) {
+			lcd_idx = i;
+			break;
+		}
+	}
+
+__ret:
+	return 0;
+}
+
+struct nxp_lcd *bd_get_lcd(void)
+{
+	return bd_lcd_config[lcd_idx].lcd;
+}
+
+const char *bd_get_lcd_name(void)
+{
+	return bd_lcd_config[lcd_idx].name;
+}
+
+enum lcd_format bd_get_lcd_format(void)
+{
+	return bd_lcd_config[lcd_idx].fmt;
+}
+
+int bd_get_lcd_density(void)
+{
+	return bd_lcd_config[lcd_idx].dpi;
+}
+
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+int bd_fixup_lcd_fdt(void *blob, struct nxp_lcd *lcd)
+{
+	return 0;
+}
+#endif
diff --git a/board/friendlyarm/nanopi2/nxp-fb.h b/board/friendlyarm/nanopi2/nxp-fb.h
new file mode 100644
index 0000000..d31a03d
--- /dev/null
+++ b/board/friendlyarm/nanopi2/nxp-fb.h
@@ -0,0 +1,94 @@
+/* SPDX-License-Identifier: GPL-2.0+
+ *
+ * Copyright (c) 2017 FriendlyARM (www.arm9.net)
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *              http://www.samsung.com/
+ *
+ * Header file for NXP Display Driver
+ */
+
+#ifndef __MACH_NXP_FB_H__
+#define __MACH_NXP_FB_H__
+
+/*
+ * struct nxp_lcd_polarity
+ * @rise_vclk:	if 1, video data is fetched@rising edge
+ * @inv_hsync:	if HSYNC polarity is inversed
+ * @inv_vsync:	if VSYNC polarity is inversed
+ * @inv_vden:	if VDEN polarity is inversed
+ */
+struct nxp_lcd_polarity {
+	int	rise_vclk;
+	int	inv_hsync;
+	int	inv_vsync;
+	int	inv_vden;
+};
+
+/*
+ * struct nxp_lcd_timing
+ * @h_fp:	horizontal front porch
+ * @h_bp:	horizontal back porch
+ * @h_sw:	horizontal sync width
+ * @v_fp:	vertical front porch
+ * @v_fpe:	vertical front porch for even field
+ * @v_bp:	vertical back porch
+ * @v_bpe:	vertical back porch for even field
+ */
+struct nxp_lcd_timing {
+	int	h_fp;
+	int	h_bp;
+	int	h_sw;
+	int	v_fp;
+	int	v_fpe;
+	int	v_bp;
+	int	v_bpe;
+	int	v_sw;
+};
+
+/*
+ * struct nxp_lcd
+ * @width:		horizontal resolution
+ * @height:		vertical resolution
+ * @p_width:	width of lcd in mm
+ * @p_height:	height of lcd in mm
+ * @bpp:		bits per pixel
+ * @freq:		vframe frequency
+ * @timing:		timing values
+ * @polarity:	polarity settings
+ * @gpio_init:	pointer to GPIO init function
+ *
+ */
+struct nxp_lcd {
+	int	width;
+	int	height;
+	int	p_width;
+	int	p_height;
+	int	bpp;
+	int	freq;
+	struct	nxp_lcd_timing timing;
+	struct	nxp_lcd_polarity polarity;
+	void	(*gpio_init)(void);
+};
+
+/**
+ * Public interfaces
+ */
+enum lcd_format {
+	LCD_VESA	= 0,
+	LCD_JEIDA	= 1,
+	LCD_LOC		= 2,
+
+	LCD_RGB		= 4,
+	LCD_HDMI	= 5,
+};
+
+extern int bd_setup_lcd_by_id(int id);
+extern int bd_setup_lcd_by_name(char *name);
+extern struct nxp_lcd *bd_get_lcd(void);
+extern const char *bd_get_lcd_name(void);
+extern int bd_get_lcd_density(void);
+extern enum lcd_format bd_get_lcd_format(void);
+extern int bd_fixup_lcd_fdt(void *blob, struct nxp_lcd *cfg);
+
+#endif /* __MACH_NXP_FB_H__ */
diff --git a/board/friendlyarm/nanopi2/onewire.c b/board/friendlyarm/nanopi2/onewire.c
new file mode 100644
index 0000000..2e8f380
--- /dev/null
+++ b/board/friendlyarm/nanopi2/onewire.c
@@ -0,0 +1,309 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) Guangzhou FriendlyARM Computer Tech. Co., Ltd.
+ * (http://www.friendlyarm.com)
+ */
+
+#include <config.h>
+#include <common.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <asm/arch/clk.h>
+#include <i2c.h>
+#ifdef CONFIG_PWM_NX
+#include <pwm.h>
+#endif
+
+#include <irq_func.h>
+
+#include <asm/arch/nexell.h>
+#include <asm/arch/nx_gpio.h>
+
+#ifndef NSEC_PER_SEC
+#define NSEC_PER_SEC	1000000000L
+#endif
+
+#define SAMPLE_BPS		9600
+#define SAMPLE_IN_US	101		/* (1000000 / BPS) */
+
+#define REQ_INFO		0x60U
+#define REQ_BL			0x80U
+
+#define BUS_I2C			0x18
+#define ONEWIRE_I2C_BUS		2
+#define ONEWIRE_I2C_ADDR	0x2f
+
+static int bus_type = -1;
+static int lcd_id = -1;
+static unsigned short lcd_fwrev = 0;
+static int current_brightness = -1;
+#ifdef CONFIG_DM_I2C
+static struct udevice *i2c_dev;
+#endif
+
+/* debug */
+#if (0)
+#define DBGOUT(msg...)	do { printf("onewire: " msg); } while (0)
+#else
+#define DBGOUT(msg...)	do {} while (0)
+#endif
+
+/* based on web page from http://lfh1986.blogspot.com */
+static unsigned char crc8_ow(unsigned int v, unsigned int len)
+{
+	unsigned char crc = 0xACU;
+
+	while (len--) {
+		if ((crc & 0x80U) != 0) {
+			crc <<= 1;
+			crc ^= 0x7U;
+		} else {
+			crc <<= 1;
+		}
+		if ((v & (1U << 31)) != 0)
+			crc ^= 0x7U;
+		v <<= 1;
+	}
+	return crc;
+}
+
+/* GPIO helpers */
+#define __IO_GRP		2	/* GPIOC15 */
+#define __IO_IDX		15
+
+static inline void set_pin_as_input(void)
+{
+	nx_gpio_set_output_enable(__IO_GRP, __IO_IDX, 0);
+}
+
+static inline void set_pin_as_output(void)
+{
+	nx_gpio_set_output_enable(__IO_GRP, __IO_IDX, 1);
+}
+
+static inline void set_pin_value(int v)
+{
+	nx_gpio_set_output_value(__IO_GRP, __IO_IDX, !!v);
+}
+
+static inline int get_pin_value(void)
+{
+	return nx_gpio_get_input_value(__IO_GRP, __IO_IDX);
+}
+
+/* Timer helpers */
+#define PWM_CH				3
+#define PWM_TCON			(PHY_BASEADDR_PWM + 0x08)
+#define PWM_TCON_START		(1 << 16)
+#define PWM_TINT_CSTAT		(PHY_BASEADDR_PWM + 0x44)
+
+static int onewire_init_timer(void)
+{
+	int period_ns = NSEC_PER_SEC / SAMPLE_BPS;
+
+	/* range: 1080~1970 */
+	period_ns -= 1525;
+
+	return pwm_config(PWM_CH, period_ns >> 1, period_ns);
+}
+
+static void wait_one_tick(void)
+{
+	unsigned int tcon;
+
+	tcon = readl(PWM_TCON);
+	tcon |= PWM_TCON_START;
+	writel(tcon, PWM_TCON);
+
+	while (1) {
+		if (readl(PWM_TINT_CSTAT) & (1 << (5 + PWM_CH)))
+			break;
+	}
+
+	writel((1 << (5 + PWM_CH)), PWM_TINT_CSTAT);
+
+	tcon &= ~PWM_TCON_START;
+	writel(tcon, PWM_TCON);
+}
+
+/* Session handler */
+static int onewire_session(unsigned char req, unsigned char res[])
+{
+	unsigned int Req;
+	unsigned int *Res;
+	int ints = disable_interrupts();
+	int i;
+	int ret;
+
+	Req = (req << 24) | (crc8_ow(req << 24, 8) << 16);
+	Res = (unsigned int *)res;
+
+	set_pin_value(1);
+	set_pin_as_output();
+	for (i = 0; i < 60; i++)
+		wait_one_tick();
+
+	set_pin_value(0);
+	for (i = 0; i < 2; i++)
+		wait_one_tick();
+
+	for (i = 0; i < 16; i++) {
+		int v = !!(Req & (1U << 31));
+
+		Req <<= 1;
+		set_pin_value(v);
+		wait_one_tick();
+	}
+
+	wait_one_tick();
+	set_pin_as_input();
+	wait_one_tick();
+	for (i = 0; i < 32; i++) {
+		(*Res) <<= 1;
+		(*Res) |= get_pin_value();
+		wait_one_tick();
+	}
+	set_pin_value(1);
+	set_pin_as_output();
+
+	if (ints)
+		enable_interrupts();
+
+	ret = crc8_ow(*Res, 24) == res[0];
+	DBGOUT("req = %02X, res = %02X%02X%02X%02X, ret = %d\n",
+	       req, res[3], res[2], res[1], res[0], ret);
+
+	return ret;
+}
+
+static int onewire_i2c_do_request(unsigned char req, unsigned char *buf)
+{
+	unsigned char tx[4];
+	int ret;
+
+	tx[0] = req;
+	tx[1] = crc8_ow(req << 24, 8);
+
+#ifdef CONFIG_DM_I2C
+	if (dm_i2c_write(i2c_dev, 0, tx, 2))
+		return -EIO;
+
+	if (!buf)
+		return 0;
+
+	if (dm_i2c_read(i2c_dev, 0, buf, 4))
+		return -EIO;
+#else
+	if (i2c_write(ONEWIRE_I2C_ADDR, 0, 0, tx, 2))
+		return -EIO;
+
+	if (!buf) /* NO READ */
+		return 0;
+
+	if (i2c_read(ONEWIRE_I2C_ADDR, 0, 0, buf, 4))
+		return -EIO;
+#endif
+
+	ret = crc8_ow((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8), 24);
+	DBGOUT("req = %02X, res = %02X%02X%02X%02X, ret = %02x\n",
+	       req, buf[0], buf[1], buf[2], buf[3], ret);
+
+	return (ret == buf[3]) ? 0 : -EIO;
+}
+
+static void onewire_i2c_init(void)
+{
+	unsigned char buf[4];
+	int ret;
+
+#ifdef CONFIG_DM_I2C
+	ret = i2c_get_chip_for_busnum(ONEWIRE_I2C_BUS,
+				      ONEWIRE_I2C_ADDR, 0, &i2c_dev);
+#else
+	i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+	i2c_set_bus_num(ONEWIRE_I2C_BUS);
+
+	ret = i2c_probe(ONEWIRE_I2C_ADDR);
+#endif
+	if (ret)
+		return;
+
+	ret = onewire_i2c_do_request(REQ_INFO, buf);
+	if (!ret) {
+		lcd_id = buf[0];
+		lcd_fwrev = buf[1] * 0x100 + buf[2];
+		bus_type = BUS_I2C;
+	}
+}
+
+void onewire_init(void)
+{
+	/* GPIO, Pull-off */
+	nx_gpio_set_pad_function(__IO_GRP, __IO_IDX, 1);
+	nx_gpio_set_pull_mode(__IO_GRP, __IO_IDX, 2);
+
+	onewire_init_timer();
+	onewire_i2c_init();
+}
+
+int onewire_get_info(unsigned char *lcd, unsigned short *fw_ver)
+{
+	unsigned char res[4];
+	int i;
+
+	if (bus_type == BUS_I2C && lcd_id > 0) {
+		*lcd = lcd_id;
+		*fw_ver = lcd_fwrev;
+		return 0;
+	}
+
+	for (i = 0; i < 3; i++) {
+		if (onewire_session(REQ_INFO, res)) {
+			*lcd = res[3];
+			*fw_ver = res[2] * 0x100 + res[1];
+			lcd_id = *lcd;
+			DBGOUT("lcd = %d, fw_ver = %x\n", *lcd, *fw_ver);
+			return 0;
+		}
+	}
+
+	/* LCD unknown or not connected */
+	*lcd = 0;
+	*fw_ver = -1;
+
+	return -1;
+}
+
+int onewire_get_lcd_id(void)
+{
+	return lcd_id;
+}
+
+int onewire_set_backlight(int brightness)
+{
+	unsigned char res[4];
+	int i;
+
+	if (brightness == current_brightness)
+		return 0;
+
+	if (brightness > 127)
+		brightness = 127;
+	else if (brightness < 0)
+		brightness = 0;
+
+	if (bus_type == BUS_I2C) {
+		onewire_i2c_do_request((REQ_BL | brightness), NULL);
+		current_brightness = brightness;
+		return 0;
+	}
+
+	for (i = 0; i < 3; i++) {
+		if (onewire_session((REQ_BL | brightness), res)) {
+			current_brightness = brightness;
+			return 0;
+		}
+	}
+
+	return -1;
+}
diff --git a/board/friendlyarm/nanopi2/onewire.h b/board/friendlyarm/nanopi2/onewire.h
new file mode 100644
index 0000000..9f6d7cf
--- /dev/null
+++ b/board/friendlyarm/nanopi2/onewire.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0+
+ *
+ * Copyright (C) Guangzhou FriendlyARM Computer Tech. Co., Ltd.
+ * (http://www.friendlyarm.com)
+ */
+
+#ifndef __ONE_WIRE_H__
+#define __ONE_WIRE_H__
+
+extern void onewire_init(void);
+extern int  onewire_get_info(unsigned char *lcd, unsigned short *fw_ver);
+extern int  onewire_get_lcd_id(void);
+extern int  onewire_set_backlight(int brightness);
+
+#endif /* __ONE_WIRE_H__ */
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [RFC PATCH v2 13/13] arm: add (default) config for nanopi2 board
  2020-03-28  9:43 [RFC PATCH v2 00/13] arm: add support for SoC S5P4418 Stefan Bosch
                   ` (11 preceding siblings ...)
  2020-03-28  9:43 ` [RFC PATCH v2 12/13] arm: add support for SoC s5p4418 (cpu) / nanopi2 board Stefan Bosch
@ 2020-03-28  9:43 ` Stefan Bosch
  12 siblings, 0 replies; 21+ messages in thread
From: Stefan Bosch @ 2020-03-28  9:43 UTC (permalink / raw)
  To: u-boot

Changes in relation to FriendlyARM's U-Boot nanopi2-v2016.01:
- Configuration changed, mainly several "CONFIG_..." moved from
  s5p4418_nanopi2.h to s5p4418_nanopi2_defconfig and USB related
  configs removed because USB is not supported yet.
- s5p4418_nanopi2.h: "CONFIG_" removed from several s5p4418/nanopi2
  specific defines because the appropriate values do not need to be
  configurable.


Signed-off-by: Stefan Bosch <stefan_b@posteo.net>
---

Changes in v2:
- USB related configs removed because USB is not supported yet.
- CONFIG_CMD_MEMTEST moved from s5p4418_nanopi2.h to
  s5p4418_nanopi2_defconfig.
- MAINTAINERS: "F: drivers/pwm/pwm-nexell*" deleted because
  arch/arm/cpu/armv7/s5p-common/pwm.c is used now. Furthermore double
  line "F: drivers/video/nexell/" deleted.

 MAINTAINERS                       |  16 +++
 configs/s5p4418_nanopi2_defconfig | 148 +++++++++++++++++++++
 doc/README.s5p4418                |  63 +++++++++
 include/configs/s5p4418_nanopi2.h | 265 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 492 insertions(+)
 create mode 100644 configs/s5p4418_nanopi2_defconfig
 create mode 100644 doc/README.s5p4418
 create mode 100644 include/configs/s5p4418_nanopi2.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 7d2729d..9d1acb7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -258,6 +258,22 @@ F:	arch/arm/mach-at91/
 F:	board/atmel/
 F:	drivers/misc/microchip_flexcom.c
 
+ARM NEXELL S5P4418
+M:	Stefan Bosch <stefan_b@posteo.net>
+S:	Maintained
+F:	arch/arm/cpu/armv7/s5p4418/
+F:	arch/arm/dts/s5p4418*
+F:	arch/arm/mach-nexell/
+F:	board/friendlyarm/
+F:	configs/s5p4418_nanopi2_defconfig
+F:	doc/README.s5p4418
+F:	drivers/gpio/nx_gpio.c
+F:	drivers/i2c/nx_i2c.c
+F:	drivers/mmc/nexell_dw_mmc_dm.c
+F:	drivers/video/nexell/
+F:	drivers/video/nexell_display.c
+F:	include/configs/s5p4418_nanopi2.h
+
 ARM OWL
 M:	Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
 S:	Maintained
diff --git a/configs/s5p4418_nanopi2_defconfig b/configs/s5p4418_nanopi2_defconfig
new file mode 100644
index 0000000..870a460
--- /dev/null
+++ b/configs/s5p4418_nanopi2_defconfig
@@ -0,0 +1,148 @@
+CONFIG_ARM=y
+CONFIG_ARCH_NEXELL=y
+CONFIG_ARCH_S5P4418=y
+CONFIG_TARGET_NANOPI2=y
+CONFIG_DM_I2C=y
+CONFIG_DM_GPIO=y
+CONFIG_DEFAULT_DEVICE_TREE="s5p4418-nanopi2"
+CONFIG_FIT=y
+
+# Must be set to 'n' (apparently "CONFIG_EFI_LOADER=y" per default)
+# otherwise boot errors "efi_runtime_relocate: Unknown relocation type 0"
+CONFIG_EFI_LOADER=n
+
+CONFIG_CMD_MEMTEST=y
+# CONFIG_CMD_IMLS is not set
+# CONFIG_CMD_FLASH is not set
+CONFIG_CMD_I2C=y
+# CONFIG_CMD_FPGA is not set
+CONFIG_CMD_GPIO=y
+# CONFIG_CMD_SETEXPR is not set
+# CONFIG_CMD_NET is not set
+
+# Default is CONFIG_NET=y, in this case:
+#   Loading Environment from MMC... ## Warning: Unknown environment variable type 'm'
+#   OK
+# CONFIG_CMD_NET=y must be set to avoid this Warning. But then:
+#   Net:   Net Initialization Skipped
+#   No ethernet found.
+# If CONFIG_NET=n is set additionally warning at "make s5p4418_nanopi2_defconfig":
+#    arch/../configs/s5p4418_nanopi2_defconfig:24:warning: override: reassigning to symbol CMD_NET
+#
+# --> CONFIG_NET=n set only
+CONFIG_NET=n
+
+# CONFIG_CMD_NFS is not set
+CONFIG_CMD_FDISK=y
+CONFIG_CMD_EXT4_IMG_WRITE=y
+CONFIG_CMD_SD_RECOVERY=y
+CONFIG_CMD_PMIC=y
+CONFIG_CMD_REGULATOR=y
+
+CONFIG_DM_I2C_GPIO=y
+CONFIG_SYS_I2C_NEXELL=y
+CONFIG_DM_PMIC=y
+CONFIG_DM_PMIC_AXP228=y
+CONFIG_DM_REGULATOR=y
+CONFIG_DM_REGULATOR_AXP228=y
+CONFIG_DM_PWM=n
+
+CONFIG_DISPLAY=y
+CONFIG_DM_VIDEO=y
+CONFIG_SYS_CONSOLE_BG_COL=0xff
+CONFIG_SYS_CONSOLE_FG_COL=0x00
+CONFIG_VIDEO_NX=y
+CONFIG_VIDEO_NX_RGB=y
+CONFIG_VIDEO_NX_LVDS=y
+
+CONFIG_VIDEO_NX_HDMI=y
+
+CONFIG_REGEX=y
+CONFIG_ERRNO_STR=y
+
+CONFIG_SYS_TEXT_BASE=0x74C00000
+CONFIG_SYS_RESERVE_MEM_SIZE=0x00400000
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_SYS_CACHELINE_SIZE=64
+
+## System initialize options (board_init_f)
+# board_init_f->init_sequence, call board_early_init_f
+CONFIG_BOARD_LATE_INIT=y
+# board_init_f->init_sequence, call print_cpuinfo
+CONFIG_DISPLAY_CPUINFO=y
+# board_init_f->init_sequence, call show_board_info
+CONFIG_DISPLAY_BOARDINFO=y
+# board_init_f, CONFIG_SYS_ICACHE_OFF
+CONFIG_SYS_DCACHE_OFF=y
+# board_init_r, call arch_misc_init
+CONFIG_ARCH_MISC_INIT=y
+
+CONFIG_BOOTDELAY=1
+CONFIG_ZERO_BOOTDELAY_CHECK=y
+
+## U-Boot Environments
+## refer to common/env_common.c
+
+# CONFIG_ENV_IS_IN_MMC must be set here and not in s5p4418_nanopi2.h
+# otherwise CONFIG_ENV_IS_NOWHERE is set by env/Kconfig and environment
+# (bootargs) are not loaded
+CONFIG_ENV_IS_IN_MMC=y
+CONFIG_ENV_OFFSET=0x2E0200
+CONFIG_ENV_SIZE=0x4000
+CONFIG_CMD_SAVEENV=y
+
+## Etc Command definition
+# image info
+CONFIG_CMD_IMI=y
+# add command line history
+CONFIG_CMDLINE_EDITING=y
+CONFIG_INITRD_TAG=y
+CONFIG_SUPPORT_RAW_INITRD=y
+CONFIG_REVISION_TAG=y
+CONFIG_CMD_BOOTZ=y
+
+## serial console configuration
+CONFIG_CONS_INDEX=0
+CONFIG_BAUDRATE=115200
+
+## SD/MMC
+CONFIG_BOUNCE_BUFFER=y
+CONFIG_GENERIC_MMC=y
+CONFIG_MMC=y
+CONFIG_MMC_DW=y
+CONFIG_NEXELL_DWMMC=y
+CONFIG_CMD_MMC=y
+CONFIG_DM_MMC=y
+
+CONFIG_DOS_PARTITION=y
+CONFIG_CMD_FAT=y
+CONFIG_FS_FAT=y
+CONFIG_FAT_WRITE=y
+
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_FS_EXT4=y
+CONFIG_EXT4_WRITE=y
+
+## OF_CONTROL
+CONFIG_FIT_BEST_MATCH=y
+CONFIG_OF_LIBFDT=y
+CONFIG_OF_BOARD_SETUP=y
+
+## BOOTCOMMAND
+CONFIG_ROOT_DEV=1
+CONFIG_BOOT_PART=1
+CONFIG_ROOT_PART=2
+
+## Misc.
+CONFIG_S5P4418_ONEWIRE=y
+CONFIG_PWM_NX=y
+
+# necessary for if-cmd
+CONFIG_HUSH_PARSER=y
+
+# set to 'n' to save memory
+CONFIG_SYS_LONGHELP=y
+
+# uncomment for debugging (trace) of MMC-CMDs
+#CONFIG_MMC_TRACE=y
diff --git a/doc/README.s5p4418 b/doc/README.s5p4418
new file mode 100644
index 0000000..ac724d0
--- /dev/null
+++ b/doc/README.s5p4418
@@ -0,0 +1,63 @@
+
+Summary
+=======
+
+This README is about U-Boot support for SAMSUNG's/NEXELL's ARM Cortex-A9 based
+S5P4418 SoC. It is based on FriendlyARM's U-Boot v2016.01 for the NanoPi2
+(and other) boards [1].
+
+Currently the following boards are supported:
+
+* FriendlyArm NanoPi2   [2]
+* FriendlyArm NanoPC-T2 [3]
+
+
+Build
+=====
+
+* NanoPi2 and NanoPC-T2
+
+make s5p4418_nanopi2_defconfig
+make
+
+
+Installation
+============
+
+- Download Official-ROMs-SDCard-20190718.7z from [4] (images files for android,
+  friendlyCore and LUbuntu)
+- Use s5p4418-sd-lubuntu-desktop-xenial-4.4-armhf-20190718.img to make a SD-card
+- Use dd in the directory where U-Boot has been built to update U-Boot:
+  (replace <SD-card> with the device used for the SD-card, e.g. sdc)
+  sudo dd seek=3841 if=u-boot.bin of=/dev/<SD-card>
+- Boot the board from this SD-card
+
+The source code for (the used?) LUbuntu 16.04 can be found at [5].
+
+
+Links
+=====
+
+[1] FriendlyArm U-boot v2016.01:
+
+https://github.com/friendlyarm/u-boot/tree/nanopi2-v2016.01
+
+
+[2] NanoPi2:
+
+http://wiki.friendlyarm.com/wiki/index.php/NanoPi_2
+
+
+[3] NanoPC-T2:
+
+http://wiki.friendlyarm.com/wiki/index.php/NanoPC-T2
+
+
+[4] FriendlyArm image files for NanoPi2:
+
+http://download.friendlyarm.com//NanoPi2
+
+
+[5] FriendlyArm LUbuntu 16.04 Source Code for NanoPi2:
+
+https://github.com/friendlyarm/linux/tree/nanopi2-v4.4.y
diff --git a/include/configs/s5p4418_nanopi2.h b/include/configs/s5p4418_nanopi2.h
new file mode 100644
index 0000000..a162eeb
--- /dev/null
+++ b/include/configs/s5p4418_nanopi2.h
@@ -0,0 +1,265 @@
+/* SPDX-License-Identifier: GPL-2.0+
+ *
+ * Copyright (C) Guangzhou FriendlyARM Computer Tech. Co., Ltd.
+ * (http://www.friendlyarm.com)
+ *
+ * (C) Copyright 2016 Nexell
+ * Hyejung Kwon <cjscld15@nexell.co.kr>
+ *
+ * Copyright (C) 2019  Stefan Bosch <stefan_b@posteo.net>
+ */
+
+#ifndef __CONFIG_H__
+#define __CONFIG_H__
+
+#include <linux/sizes.h>
+#include <asm/arch/nexell.h>
+
+/*-----------------------------------------------------------------------
+ *  System memory Configuration
+ */
+#define CONFIG_SYS_INIT_SP_ADDR		CONFIG_SYS_TEXT_BASE
+#define CONFIG_SYS_MONITOR_BASE		CONFIG_SYS_TEXT_BASE
+#define CONFIG_SYS_MEM_SIZE		0x40000000
+#define CONFIG_SYS_SDRAM_BASE		0x71000000
+
+/*
+ * "(CONFIG_SYS_MEM_SIZE - CONFIG_SYS_RESERVE_MEM_SIZE)" has been used in
+ * u-boot nanopi2-v2016.01.
+ * This is not working anymore because boot_fdt_add_mem_rsv_regions() in
+ * common/image-fdt.c has been extended:
+ * Also reserved-memory sections are marked as unusable.
+ *
+ * In friendlyArm Ubuntu 16.04 source arch/arm/boot/dts/s5p4418.dtsi:
+ *        reserved-memory {
+ *            #address-cells = <1>;
+ *            #size-cells = <1>;
+ *            ranges;
+ *
+ *            secure_memory at b0000000 {
+ *                reg = <0xB0000000 0x1000000>;
+ *                nop-map;
+ *            };
+ *        };
+ *
+ * arch_lmb_reserve() of arch/arm/lib/bootm.c:
+ *     "Allocate space for command line and board info - ... below the current
+ *      stack pointer."
+ *      --> Memory allocated would overlap with "secure_memory at b0000000"
+ *      --> lmb_add_region(rgn, base==0xb0000000, size==0x1000000) fails,
+ *      boot output:
+ *        ...
+ *        Kernel image @ 0x71080000 [ 0x000000 - 0x60e628 ]
+ *        ## Flattened Device Tree blob at 7a000000
+ *           Booting using the fdt blob at 0x7a000000
+ *        ERROR: reserving fdt memory region failed (addr=b0000000 size=1000000)
+ *           Using Device Tree in place at 7a000000, end 7a00fbf0
+ *
+ *        Starting kernel ...
+ *        ...
+ */
+#define CONFIG_SYS_SDRAM_SIZE		(0xb0000000 - CONFIG_SYS_SDRAM_BASE)
+
+#define CONFIG_SYS_MALLOC_LEN		(32 * 1024 * 1024)
+
+#define BMP_LOAD_ADDR			0x78000000
+
+/* kernel load address */
+#define CONFIG_SYS_LOAD_ADDR		0x71080000
+#define INITRD_START			0x79000000
+#define KERNEL_DTB_ADDR			0x7A000000
+
+/* memtest works on */
+#define CONFIG_SYS_MEMTEST_START	CONFIG_SYS_SDRAM_BASE
+#define CONFIG_SYS_MEMTEST_END		((ulong)CONFIG_SYS_SDRAM_BASE + \
+					 (ulong)CONFIG_SYS_SDRAM_SIZE)
+
+/*-----------------------------------------------------------------------
+ *  High Level System Configuration
+ */
+/* Not used: not need IRQ/FIQ stuff */
+#undef  CONFIG_USE_IRQ
+/* decrementer freq: 1ms ticks */
+#define CONFIG_SYS_HZ			1000
+
+/*-----------------------------------------------------------------------
+ *  System initialize options (board_init_f)
+ */
+/* board_init_f->init_sequence, call arch_cpu_init */
+#define CONFIG_ARCH_CPU_INIT
+
+/*-----------------------------------------------------------------------
+ * Miscellaneous configurable options
+ */
+#ifdef CONFIG_SYS_PROMPT
+#undef CONFIG_SYS_PROMPT
+/* Monitor Command Prompt */
+#define CONFIG_SYS_PROMPT		"nanopi2# "
+#endif
+
+/* Console I/O Buffer Size */
+#define CONFIG_SYS_CBSIZE		1024
+/* Print Buffer Size */
+#define CONFIG_SYS_PBSIZE		(CONFIG_SYS_CBSIZE +             \
+					 sizeof(CONFIG_SYS_PROMPT) + 16)
+/* max number of command args */
+#define CONFIG_SYS_MAXARGS		16
+/* Boot Argument Buffer Size */
+#define CONFIG_SYS_BARGSIZE		CONFIG_SYS_CBSIZE
+
+/*-----------------------------------------------------------------------
+ * allow to overwrite serial and ethaddr
+ */
+#define CONFIG_ENV_OVERWRITE
+
+#ifdef CONFIG_HUSH_PARSER
+#define CONFIG_SYS_PROMPT_HUSH_PS2	"> "
+#endif
+
+/*-----------------------------------------------------------------------
+ * Etc Command definition
+ */
+#define CONFIG_CMDLINE_TAG		/* use bootargs commandline */
+
+#undef CONFIG_BOOTM_NETBSD
+#undef CONFIG_BOOTM_RTEMS
+
+/*-----------------------------------------------------------------------
+ * serial console configuration
+ */
+#define CONFIG_PL011_CLOCK		50000000
+#define CONFIG_PL01x_PORTS		{(void *)PHY_BASEADDR_UART0, \
+					 (void *)PHY_BASEADDR_UART1, \
+					 (void *)PHY_BASEADDR_UART2, \
+					 (void *)PHY_BASEADDR_UART3}
+#define CONFIG_SYS_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, 115200 }
+
+/*-----------------------------------------------------------------------
+ * PLL
+ */
+#define CONFIG_SYS_PLLFIN		24000000UL
+
+/*-----------------------------------------------------------------------
+ * Timer
+ */
+#define CONFIG_TIMER_SYS_TICK_CH	0
+
+/*-----------------------------------------------------------------------
+ * BACKLIGHT
+ */
+#ifndef CONFIG_S5P4418_ONEWIRE
+/* fallback to pwm */
+#define BACKLIGHT_CH		0
+#define BACKLIGHT_DIV		0
+#define BACKLIGHT_INV		0
+#define BACKLIGHT_DUTY		50
+#define BACKLIGHT_HZ		1000
+#endif
+
+/*-----------------------------------------------------------------------
+ * SD/MMC
+ */
+#if defined(CONFIG_MMC)
+/* eMMC = 0, SD-card = 2 */
+#define CONFIG_SYS_MMC_DEV		2
+#define CONFIG_SYS_MMC_ENV_DEV		CONFIG_SYS_MMC_DEV
+
+#endif
+
+/*-----------------------------------------------------------------------
+ * Default environment organization
+ */
+#if !defined(CONFIG_ENV_IS_IN_MMC) && !defined(CONFIG_ENV_IS_IN_NAND) && \
+	!defined(CONFIG_ENV_IS_IN_FLASH) && !defined(CONFIG_ENV_IS_IN_EEPROM)
+	/* default: CONFIG_ENV_IS_NOWHERE */
+	#define CONFIG_ENV_IS_NOWHERE
+	#define CONFIG_ENV_OFFSET	1024
+	#define CONFIG_ENV_SIZE		(4 * 1024)	/* env size */
+	/* imls - list all images found in flash, default enable so disable */
+	#undef CONFIG_CMD_IMLS
+#endif
+
+/*-----------------------------------------------------------------------
+ * VIDEO
+ */
+
+#define CONFIG_VIDEO_LOGO
+
+#define CONFIG_SPLASH_SCREEN
+
+#ifdef CONFIG_VIDEO_LOGO
+#define CONFIG_CMD_BMP
+
+#ifdef CONFIG_DM_VIDEO
+#define CONFIG_BMP_24BPP
+#endif
+
+#ifdef CONFIG_SPLASH_SCREEN
+#define CONFIG_SPLASH_SOURCE		1
+#define CONFIG_SPLASH_SCREEN_ALIGN	1
+#define SPLASH_FILE			logo.bmp
+#endif
+#endif
+
+/*-----------------------------------------------------------------------
+ * ENV
+ */
+#define BLOADER_MMC						\
+	"ext4load mmc ${rootdev}:${bootpart} "
+
+#ifdef CONFIG_OF_BOARD_SETUP
+#define EXTRA_ENV_DTB_RESERVE					\
+	"dtb_reserve="						\
+	"if test -n \"$dtb_addr\"; then fdt addr $dtb_addr; fi\0"
+#else
+#define EXTRA_ENV_DTB_RESERVE					\
+	"dtb_reserve="						\
+	"if test -n \"$fb_addr\"; then "			\
+	  "fdt addr $dtb_addr;"					\
+	  "fdt resize;"						\
+	  "fdt mk /reserved-memory display_reserved;"		\
+	  "fdt set /reserved-memory/display_reserved "		\
+	    "reg <$fb_addr 0x800000>;"				\
+	"fi;\0"
+#endif
+
+#ifdef CONFIG_SPLASH_SCREEN
+#define EXTRA_ENV_BOOT_LOGO					\
+	"splashimage=" __stringify(BMP_LOAD_ADDR)"\0"		\
+	"splashfile=" __stringify(SPLASH_FILE)"\0"		\
+	"splashpos=m,m\0"					\
+	"fb_addr=\0"						\
+	EXTRA_ENV_DTB_RESERVE
+#else
+	#define EXTRA_ENV_BOOT_LOGO  EXTRA_ENV_DTB_RESERVE
+#endif
+
+#define CONFIG_EXTRA_ENV_SETTINGS				\
+	"fdt_high=0xffffffff\0"					\
+	"initrd_high=0xffffffff\0"				\
+	"rootdev=" __stringify(CONFIG_ROOT_DEV) "\0"		\
+	"rootpart=" __stringify(CONFIG_ROOT_PART) "\0"		\
+	"bootpart=" __stringify(CONFIG_BOOT_PART) "\0"		\
+	"kernel=zImage\0"					\
+	"loadaddr=" __stringify(CONFIG_SYS_LOAD_ADDR) "\0"	\
+	"dtb_name=s5p4418-nanopi2-rev01.dtb\0"			\
+	"dtb_addr=" __stringify(KERNEL_DTB_ADDR) "\0"		\
+	"initrd_name=ramdisk.img\0"				\
+	"initrd_addr=" __stringify(INITRD_START) "\0"		\
+	"initrd_size=0x600000\0"				\
+	"load_dtb="						\
+		BLOADER_MMC "${dtb_addr} ${dtb_name}; "		\
+		"run dtb_reserve\0"				\
+	"load_kernel="						\
+		BLOADER_MMC "${loadaddr} ${kernel}\0"		\
+	"load_initrd="						\
+		BLOADER_MMC "${initrd_addr} ${initrd_name}; "	\
+		"setenv initrd_size 0x${filesize}\0"		\
+	"mmcboot="						\
+		"run load_kernel; run load_initrd; run load_dtb; "	\
+		"bootz ${loadaddr} ${initrd_addr}:${initrd_size} "	\
+		  "${dtb_addr}\0"				\
+	"bootcmd=run mmcboot\0"					\
+	EXTRA_ENV_BOOT_LOGO
+
+#endif /* __CONFIG_H__ */
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [RFC PATCH v2 05/13] mmc: add nexell driver
  2020-03-28  9:43 ` [RFC PATCH v2 05/13] mmc: " Stefan Bosch
@ 2020-04-02 11:03   ` Jaehoon Chung
  2020-04-02 16:51     ` Stefan B.
  2020-04-09 17:33     ` Stefan B.
  0 siblings, 2 replies; 21+ messages in thread
From: Jaehoon Chung @ 2020-04-02 11:03 UTC (permalink / raw)
  To: u-boot

Hi,

On 3/28/20 6:43 PM, Stefan Bosch wrote:
> Changes in relation to FriendlyARM's U-Boot nanopi2-v2016.01:
> - mmc: nexell_dw_mmc.c changed to nexell_dw_mmc_dm.c (switched to DM).

It doesn't need to add postfix as _dm.

> 
> Signed-off-by: Stefan Bosch <stefan_b@posteo.net>
> ---
> 
> Changes in v2:
> - commit "i2c: mmc: add nexell driver (gpio, i2c, mmc, pwm)" splitted
>   into separate commits for gpio, i2c, mmc, pwm.
> 
>  drivers/mmc/Kconfig            |   6 +
>  drivers/mmc/Makefile           |   1 +
>  drivers/mmc/nexell_dw_mmc_dm.c | 350 +++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 357 insertions(+)
>  create mode 100644 drivers/mmc/nexell_dw_mmc_dm.c
> 
> diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
> index 2f0eedc..bb8e7c0 100644
> --- a/drivers/mmc/Kconfig
> +++ b/drivers/mmc/Kconfig
> @@ -253,6 +253,12 @@ config MMC_DW_SNPS
>  	  This selects support for Synopsys DesignWare Memory Card Interface driver
>  	  extensions used in various Synopsys ARC devboards.
>  
> +config NEXELL_DWMMC
> +	bool "Nexell SD/MMC controller support"
> +	depends on ARCH_NEXELL
> +	depends on MMC_DW
> +	default y

Not depends on DM_MMC?

> +
>  config MMC_MESON_GX
>  	bool "Meson GX EMMC controller support"
>  	depends on DM_MMC && BLK && ARCH_MESON
> diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
> index 9c1f8e5..a7b5a7b 100644
> --- a/drivers/mmc/Makefile
> +++ b/drivers/mmc/Makefile
> @@ -43,6 +43,7 @@ obj-$(CONFIG_SH_MMCIF) += sh_mmcif.o
>  obj-$(CONFIG_SH_SDHI) += sh_sdhi.o
>  obj-$(CONFIG_STM32_SDMMC2) += stm32_sdmmc2.o
>  obj-$(CONFIG_JZ47XX_MMC) += jz_mmc.o
> +obj-$(CONFIG_NEXELL_DWMMC) += nexell_dw_mmc_dm.o
>  
>  # SDHCI
>  obj-$(CONFIG_MMC_SDHCI)			+= sdhci.o
> diff --git a/drivers/mmc/nexell_dw_mmc_dm.c b/drivers/mmc/nexell_dw_mmc_dm.c
> new file mode 100644
> index 0000000..b06b60d
> --- /dev/null
> +++ b/drivers/mmc/nexell_dw_mmc_dm.c
> @@ -0,0 +1,350 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * (C) Copyright 2016 Nexell
> + * Youngbok, Park <park@nexell.co.kr>
> + *
> + * (C) Copyright 2019 Stefan Bosch <stefan_b@posteo.net>
> + */
> +
> +#include <common.h>
> +#include <clk.h>
> +#include <dm.h>
> +#include <dt-structs.h>
> +#include <dwmmc.h>
> +#include <syscon.h>
> +#include <asm/gpio.h>
> +#include <asm/arch/nx_gpio.h>
> +#include <asm/arch/reset.h>
> +
> +#define DWMCI_CLKSEL			0x09C
> +#define DWMCI_SHIFT_0			0x0
> +#define DWMCI_SHIFT_1			0x1
> +#define DWMCI_SHIFT_2			0x2
> +#define DWMCI_SHIFT_3			0x3
> +#define DWMCI_SET_SAMPLE_CLK(x)	(x)
> +#define DWMCI_SET_DRV_CLK(x)	((x) << 16)
> +#define DWMCI_SET_DIV_RATIO(x)	((x) << 24)
> +#define DWMCI_CLKCTRL			0x114
> +#define NX_MMC_CLK_DELAY(x, y, a, b)	((((x) & 0xFF) << 0) |\
> +					(((y) & 0x03) << 16) |\
> +					(((a) & 0xFF) << 8)  |\
> +					(((b) & 0x03) << 24))
> +
> +struct nexell_mmc_plat {
> +	struct mmc_config cfg;
> +	struct mmc mmc;
> +};
> +
> +struct nexell_dwmmc_priv {
> +	struct clk *clk;
> +	struct dwmci_host host;
> +	int fifo_size;
> +	bool fifo_mode;
> +	int frequency;
> +	u32 min_freq;
> +	u32 max_freq;
> +	int d_delay;
> +	int d_shift;
> +	int s_delay;
> +	int s_shift;
> +
> +};
> +
> +struct clk *clk_get(const char *id);
> +
> +static void set_pin_stat(int index, int bit, int value)
> +{
> +#if !defined(CONFIG_SPL_BUILD)
> +	nx_gpio_set_pad_function(index, bit, value);
> +#else
> +#if defined(CONFIG_ARCH_S5P4418) ||	\
> +	defined(CONFIG_ARCH_S5P6818)
> +
> +	unsigned long base[5] = {
> +		PHY_BASEADDR_GPIOA, PHY_BASEADDR_GPIOB,
> +		PHY_BASEADDR_GPIOC, PHY_BASEADDR_GPIOD,
> +		PHY_BASEADDR_GPIOE,
> +	};

I don't understand why gpio pin is set in mmc driver?
If nexell soc will change the gpio map and function value, does it needs to add other gpio control?

> +
> +	dw_mmc_set_pin(base[index], bit, value);
> +#endif
> +#endif
> +}
> +
> +static void nx_dw_mmc_set_pin(struct dwmci_host *host)
> +{
> +	debug("  %s(): dev_index == %d", __func__, host->dev_index);
> +
> +	switch (host->dev_index) {
> +	case 0:
> +		set_pin_stat(0, 29, 1);
> +		set_pin_stat(0, 31, 1);
> +		set_pin_stat(1, 1, 1);
> +		set_pin_stat(1, 3, 1);
> +		set_pin_stat(1, 5, 1);
> +		set_pin_stat(1, 7, 1);
> +		break;
> +	case 1:
> +		set_pin_stat(3, 22, 1);
> +		set_pin_stat(3, 23, 1);
> +		set_pin_stat(3, 24, 1);
> +		set_pin_stat(3, 25, 1);
> +		set_pin_stat(3, 26, 1);
> +		set_pin_stat(3, 27, 1);
> +		break;
> +	case 2:
> +		set_pin_stat(2, 18, 2);
> +		set_pin_stat(2, 19, 2);
> +		set_pin_stat(2, 20, 2);
> +		set_pin_stat(2, 21, 2);
> +		set_pin_stat(2, 22, 2);
> +		set_pin_stat(2, 23, 2);
> +		if (host->buswidth == 8) {
> +			set_pin_stat(4, 21, 2);
> +			set_pin_stat(4, 22, 2);
> +			set_pin_stat(4, 23, 2);
> +			set_pin_stat(4, 24, 2);
> +		}
> +		break;
> +	default:
> +		debug(" is invalid!");

Is invalid..then will not work fine? 

i don't check your patch fully.
Your patch doesn't control gpio with dt? 
Well, i don't agree this concept. it need to get opinion how to think about this.

> +	}
> +	debug("\n");
> +}
> +
> +static void nx_dw_mmc_clksel(struct dwmci_host *host)
> +{
> +	u32 val;
> +
> +#ifdef CONFIG_BOOST_MMC

What is BOOST_MMC?

> +	val = DWMCI_SET_SAMPLE_CLK(DWMCI_SHIFT_0) |
> +	    DWMCI_SET_DRV_CLK(DWMCI_SHIFT_0) | DWMCI_SET_DIV_RATIO(1);
> +#else
> +	val = DWMCI_SET_SAMPLE_CLK(DWMCI_SHIFT_0) |
> +	    DWMCI_SET_DRV_CLK(DWMCI_SHIFT_0) | DWMCI_SET_DIV_RATIO(3);
> +#endif
> +
> +	dwmci_writel(host, DWMCI_CLKSEL, val);
> +}
> +
> +static void nx_dw_mmc_reset(int ch)
> +{
> +	int rst_id = RESET_ID_SDMMC0 + ch;

RESET_ID_SDMMC0? 

> +
> +	nx_rstcon_setrst(rst_id, 0);
> +	nx_rstcon_setrst(rst_id, 1);
> +}
> +
> +static void nx_dw_mmc_clk_delay(struct udevice *dev)
> +{
> +	unsigned int delay;
> +	struct nexell_dwmmc_priv *priv = dev_get_priv(dev);
> +	struct dwmci_host *host = &priv->host;
> +
> +	delay = NX_MMC_CLK_DELAY(priv->d_delay,
> +				 priv->d_shift, priv->s_delay, priv->s_shift);
> +
> +	writel(delay, (host->ioaddr + DWMCI_CLKCTRL));
> +	debug("%s(): Values set: d_delay==%d, d_shift==%d, s_delay==%d, "
> +	      "s_shift==%d\n", __func__, priv->d_delay, priv->d_shift,
> +	      priv->s_delay, priv->s_shift);
> +}
> +
> +static unsigned int nx_dw_mmc_get_clk(struct dwmci_host *host, uint freq)
> +{
> +	struct clk *clk;
> +	struct udevice *dev = host->priv;
> +	struct nexell_dwmmc_priv *priv = dev_get_priv(dev);
> +
> +	int index = host->dev_index;
> +	char name[50] = { 0, };
> +
> +	clk = priv->clk;
> +	if (!clk) {
> +		sprintf(name, "%s.%d", DEV_NAME_SDHC, index);

DEV_NAME_SDHC ???

> +		clk = clk_get((const char *)name);
> +		if (!clk)
> +			return 0;
> +		priv->clk = clk;
> +	}
> +
> +	return clk_get_rate(clk) / 2;
> +}
> +
> +static unsigned long nx_dw_mmc_set_clk(struct dwmci_host *host,
> +				       unsigned int rate)
> +{
> +	struct clk *clk;
> +	char name[50] = { 0, };
> +	struct udevice *dev = host->priv;
> +	struct nexell_dwmmc_priv *priv = dev_get_priv(dev);
> +
> +	int index = host->dev_index;
> +
> +	clk = priv->clk;
> +	if (!clk) {
> +		sprintf(name, "%s.%d", DEV_NAME_SDHC, index);
> +		clk = clk_get((const char *)name);
> +		if (!clk)
> +			return 0;
> +		priv->clk = clk;
> +	}
> +
> +	clk_disable(clk);
> +	rate = clk_set_rate(clk, rate);
> +	clk_enable(clk);
> +
> +	return rate;
> +}
> +
> +static int nexell_dwmmc_ofdata_to_platdata(struct udevice *dev)
> +{
> +	/* if (dev): *priv = dev->priv, else: *priv = NULL */
> +	struct nexell_dwmmc_priv *priv = dev_get_priv(dev);
> +	struct dwmci_host *host = &priv->host;
> +	int val = -1;
> +
> +	debug("%s()\n", __func__);
> +
> +	host->name = dev->name;
> +	host->ioaddr = dev_read_addr_ptr(dev);
> +
> +	val = dev_read_u32_default(dev, "nexell,bus-width", -1);
> +	if (val < 0) {
> +		debug("  'nexell,bus-width' missing/invalid!\n");
> +		return -EINVAL;
> +	}
> +	host->buswidth = val;
> +	host->get_mmc_clk = nx_dw_mmc_get_clk;
> +	host->clksel = nx_dw_mmc_clksel;
> +	host->priv = dev;
> +
> +	val = dev_read_u32_default(dev, "index", -1);
> +	if (val < 0) {
> +		debug("  'index' missing/invalid!\n");
> +		return -EINVAL;
> +	}
> +	host->dev_index = val;
> +
> +	val = dev_read_u32_default(dev, "fifo-size", 0x20);
> +	if (val <= 0) {
> +		debug("  'fifo-size' missing/invalid!\n");
> +		return -EINVAL;
> +	}
> +	priv->fifo_size = val;
> +
> +	priv->fifo_mode = dev_read_bool(dev, "fifo-mode");
> +
> +	val = dev_read_u32_default(dev, "frequency", -1);
> +	if (val < 0) {
> +		debug("  'frequency' missing/invalid!\n");
> +		return -EINVAL;
> +	}
> +	priv->frequency = val;
> +
> +	val = dev_read_u32_default(dev, "max-frequency", -1);
> +	if (val < 0) {
> +		debug("  'max-frequency' missing/invalid!\n");
> +		return -EINVAL;
> +	}
> +	priv->max_freq = val;
> +	priv->min_freq = 400000;  /* 400 kHz */
> +
> +	val = dev_read_u32_default(dev, "nexell,drive_dly", -1);
> +	if (val < 0) {
> +		debug("  'nexell,drive_dly' missing/invalid!\n");
> +		return -EINVAL;
> +	}
> +	priv->d_delay = val;
> +
> +	val = dev_read_u32_default(dev, "nexell,drive_shift", -1);
> +	if (val < 0) {
> +		debug("  'nexell,drive_shift' missing/invalid!\n");
> +		return -EINVAL;
> +	}
> +	priv->d_shift = val;
> +
> +	val = dev_read_u32_default(dev, "nexell,sample_dly", -1);
> +	if (val < 0) {
> +		debug("  'nexell,sample_dly' missing/invalid!\n");
> +		return -EINVAL;
> +	}
> +	priv->s_delay = val;
> +
> +	val = dev_read_u32_default(dev, "nexell,sample_shift", -1);
> +	if (val < 0) {
> +		debug("  'nexell,sample_shift' missing/invalid!\n");
> +		return -EINVAL;
> +	}
> +	priv->s_shift = val;
> +
> +	debug("  index==%d, name==%s, ioaddr==0x%08x, buswidth==%d, "
> +		  "fifo_size==%d, fifo_mode==%d, frequency==%d\n",
> +		  host->dev_index, host->name, (u32)host->ioaddr,
> +		  host->buswidth, priv->fifo_size, priv->fifo_mode,
> +		  priv->frequency);
> +	debug("  min_freq==%d, max_freq==%d, delay: "
> +		  "0x%02x:0x%02x:0x%02x:0x%02x\n",
> +		  priv->min_freq, priv->max_freq, priv->d_delay,
> +		  priv->d_shift, priv->s_delay, priv->s_shift);

entirely not readable. not need to assign again with val.

priv->s_deley = dev_read_u32_default();


> +
> +	return 0;
> +}
> +
> +static int nexell_dwmmc_probe(struct udevice *dev)
> +{
> +	struct nexell_mmc_plat *plat = dev_get_platdata(dev);
> +	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
> +	struct nexell_dwmmc_priv *priv = dev_get_priv(dev);
> +	struct dwmci_host *host = &priv->host;
> +	struct udevice *pwr_dev __maybe_unused;
> +
> +	debug("%s():\n", __func__);

Don't add unnecessary debug code. it's meaningless even if it's enabled.

Well, i didn't check other patches..but i think that your patches seems to based on older u-boot version.

Best Regards,
Jaehoon Chung


> +
> +	host->fifoth_val = MSIZE(0x2) |
> +		RX_WMARK(priv->fifo_size / 2 - 1) |
> +		TX_WMARK(priv->fifo_size / 2);
> +
> +	host->fifo_mode = priv->fifo_mode;
> +
> +	dwmci_setup_cfg(&plat->cfg, host, priv->max_freq, priv->min_freq);
> +	host->mmc = &plat->mmc;
> +	host->mmc->priv = &priv->host;
> +	host->mmc->dev = dev;
> +	upriv->mmc = host->mmc;
> +
> +	nx_dw_mmc_set_pin(host);
> +
> +	debug("  nx_dw_mmc_set_clk(host, frequency * 4 == %d)\n",
> +	      priv->frequency * 4);
> +	nx_dw_mmc_set_clk(host, priv->frequency * 4);
> +
> +	nx_dw_mmc_reset(host->dev_index);
> +	nx_dw_mmc_clk_delay(dev);
> +
> +	return dwmci_probe(dev);
> +}
> +
> +static int nexell_dwmmc_bind(struct udevice *dev)
> +{
> +	struct nexell_mmc_plat *plat = dev_get_platdata(dev);
> +
> +	return dwmci_bind(dev, &plat->mmc, &plat->cfg);
> +}
> +
> +static const struct udevice_id nexell_dwmmc_ids[] = {
> +	{ .compatible = "nexell,nexell-dwmmc" },
> +	{ }
> +};
> +
> +U_BOOT_DRIVER(nexell_dwmmc_drv) = {
> +	.name		= "nexell_dwmmc",
> +	.id		= UCLASS_MMC,
> +	.of_match	= nexell_dwmmc_ids,
> +	.ofdata_to_platdata = nexell_dwmmc_ofdata_to_platdata,
> +	.ops		= &dm_dwmci_ops,
> +	.bind		= nexell_dwmmc_bind,
> +	.probe		= nexell_dwmmc_probe,
> +	.priv_auto_alloc_size = sizeof(struct nexell_dwmmc_priv),
> +	.platdata_auto_alloc_size = sizeof(struct nexell_mmc_plat),
> +};
> 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [RFC PATCH v2 05/13] mmc: add nexell driver
  2020-04-02 11:03   ` Jaehoon Chung
@ 2020-04-02 16:51     ` Stefan B.
  2020-04-09 17:33     ` Stefan B.
  1 sibling, 0 replies; 21+ messages in thread
From: Stefan B. @ 2020-04-02 16:51 UTC (permalink / raw)
  To: u-boot

Hi,

thanks a lot for your reply. As you already guessed I have ported the 
outdated U-Boot from FriendlyARM, see:
https://github.com/friendlyarm/u-boot/tree/nanopi2-v2016.01

The original MMC-driver has been nexell_dw_mmc.c, so I renamed it to 
nexell_dw_mmc_dm.c after changing to DM.

I will have a closer look at your suggestions and give you feedback ASAP.


Regards
Stefan Bosch


Am 02.04.20 um 13:03 schrieb Jaehoon Chung:
> Hi,
> 
> On 3/28/20 6:43 PM, Stefan Bosch wrote:
>> Changes in relation to FriendlyARM's U-Boot nanopi2-v2016.01:
>> - mmc: nexell_dw_mmc.c changed to nexell_dw_mmc_dm.c (switched to DM).
> 
> It doesn't need to add postfix as _dm.
> 
>>
>> Signed-off-by: Stefan Bosch <stefan_b@posteo.net>
>> ---
>>
>> Changes in v2:
>> - commit "i2c: mmc: add nexell driver (gpio, i2c, mmc, pwm)" splitted
>>    into separate commits for gpio, i2c, mmc, pwm.
>>
>>   drivers/mmc/Kconfig            |   6 +
>>   drivers/mmc/Makefile           |   1 +
>>   drivers/mmc/nexell_dw_mmc_dm.c | 350 +++++++++++++++++++++++++++++++++++++++++
>>   3 files changed, 357 insertions(+)
>>   create mode 100644 drivers/mmc/nexell_dw_mmc_dm.c
>>
>> diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
>> index 2f0eedc..bb8e7c0 100644
>> --- a/drivers/mmc/Kconfig
>> +++ b/drivers/mmc/Kconfig
>> @@ -253,6 +253,12 @@ config MMC_DW_SNPS
>>   	  This selects support for Synopsys DesignWare Memory Card Interface driver
>>   	  extensions used in various Synopsys ARC devboards.
>>   
>> +config NEXELL_DWMMC
>> +	bool "Nexell SD/MMC controller support"
>> +	depends on ARCH_NEXELL
>> +	depends on MMC_DW
>> +	default y
> 
> Not depends on DM_MMC?
> 
>> +
>>   config MMC_MESON_GX
>>   	bool "Meson GX EMMC controller support"
>>   	depends on DM_MMC && BLK && ARCH_MESON
>> diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
>> index 9c1f8e5..a7b5a7b 100644
>> --- a/drivers/mmc/Makefile
>> +++ b/drivers/mmc/Makefile
>> @@ -43,6 +43,7 @@ obj-$(CONFIG_SH_MMCIF) += sh_mmcif.o
>>   obj-$(CONFIG_SH_SDHI) += sh_sdhi.o
>>   obj-$(CONFIG_STM32_SDMMC2) += stm32_sdmmc2.o
>>   obj-$(CONFIG_JZ47XX_MMC) += jz_mmc.o
>> +obj-$(CONFIG_NEXELL_DWMMC) += nexell_dw_mmc_dm.o
>>   
>>   # SDHCI
>>   obj-$(CONFIG_MMC_SDHCI)			+= sdhci.o
>> diff --git a/drivers/mmc/nexell_dw_mmc_dm.c b/drivers/mmc/nexell_dw_mmc_dm.c
>> new file mode 100644
>> index 0000000..b06b60d
>> --- /dev/null
>> +++ b/drivers/mmc/nexell_dw_mmc_dm.c
>> @@ -0,0 +1,350 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +/*
>> + * (C) Copyright 2016 Nexell
>> + * Youngbok, Park <park@nexell.co.kr>
>> + *
>> + * (C) Copyright 2019 Stefan Bosch <stefan_b@posteo.net>
>> + */
>> +
>> +#include <common.h>
>> +#include <clk.h>
>> +#include <dm.h>
>> +#include <dt-structs.h>
>> +#include <dwmmc.h>
>> +#include <syscon.h>
>> +#include <asm/gpio.h>
>> +#include <asm/arch/nx_gpio.h>
>> +#include <asm/arch/reset.h>
>> +
>> +#define DWMCI_CLKSEL			0x09C
>> +#define DWMCI_SHIFT_0			0x0
>> +#define DWMCI_SHIFT_1			0x1
>> +#define DWMCI_SHIFT_2			0x2
>> +#define DWMCI_SHIFT_3			0x3
>> +#define DWMCI_SET_SAMPLE_CLK(x)	(x)
>> +#define DWMCI_SET_DRV_CLK(x)	((x) << 16)
>> +#define DWMCI_SET_DIV_RATIO(x)	((x) << 24)
>> +#define DWMCI_CLKCTRL			0x114
>> +#define NX_MMC_CLK_DELAY(x, y, a, b)	((((x) & 0xFF) << 0) |\
>> +					(((y) & 0x03) << 16) |\
>> +					(((a) & 0xFF) << 8)  |\
>> +					(((b) & 0x03) << 24))
>> +
>> +struct nexell_mmc_plat {
>> +	struct mmc_config cfg;
>> +	struct mmc mmc;
>> +};
>> +
>> +struct nexell_dwmmc_priv {
>> +	struct clk *clk;
>> +	struct dwmci_host host;
>> +	int fifo_size;
>> +	bool fifo_mode;
>> +	int frequency;
>> +	u32 min_freq;
>> +	u32 max_freq;
>> +	int d_delay;
>> +	int d_shift;
>> +	int s_delay;
>> +	int s_shift;
>> +
>> +};
>> +
>> +struct clk *clk_get(const char *id);
>> +
>> +static void set_pin_stat(int index, int bit, int value)
>> +{
>> +#if !defined(CONFIG_SPL_BUILD)
>> +	nx_gpio_set_pad_function(index, bit, value);
>> +#else
>> +#if defined(CONFIG_ARCH_S5P4418) ||	\
>> +	defined(CONFIG_ARCH_S5P6818)
>> +
>> +	unsigned long base[5] = {
>> +		PHY_BASEADDR_GPIOA, PHY_BASEADDR_GPIOB,
>> +		PHY_BASEADDR_GPIOC, PHY_BASEADDR_GPIOD,
>> +		PHY_BASEADDR_GPIOE,
>> +	};
> 
> I don't understand why gpio pin is set in mmc driver?
> If nexell soc will change the gpio map and function value, does it needs to add other gpio control?
> 
>> +
>> +	dw_mmc_set_pin(base[index], bit, value);
>> +#endif
>> +#endif
>> +}
>> +
>> +static void nx_dw_mmc_set_pin(struct dwmci_host *host)
>> +{
>> +	debug("  %s(): dev_index == %d", __func__, host->dev_index);
>> +
>> +	switch (host->dev_index) {
>> +	case 0:
>> +		set_pin_stat(0, 29, 1);
>> +		set_pin_stat(0, 31, 1);
>> +		set_pin_stat(1, 1, 1);
>> +		set_pin_stat(1, 3, 1);
>> +		set_pin_stat(1, 5, 1);
>> +		set_pin_stat(1, 7, 1);
>> +		break;
>> +	case 1:
>> +		set_pin_stat(3, 22, 1);
>> +		set_pin_stat(3, 23, 1);
>> +		set_pin_stat(3, 24, 1);
>> +		set_pin_stat(3, 25, 1);
>> +		set_pin_stat(3, 26, 1);
>> +		set_pin_stat(3, 27, 1);
>> +		break;
>> +	case 2:
>> +		set_pin_stat(2, 18, 2);
>> +		set_pin_stat(2, 19, 2);
>> +		set_pin_stat(2, 20, 2);
>> +		set_pin_stat(2, 21, 2);
>> +		set_pin_stat(2, 22, 2);
>> +		set_pin_stat(2, 23, 2);
>> +		if (host->buswidth == 8) {
>> +			set_pin_stat(4, 21, 2);
>> +			set_pin_stat(4, 22, 2);
>> +			set_pin_stat(4, 23, 2);
>> +			set_pin_stat(4, 24, 2);
>> +		}
>> +		break;
>> +	default:
>> +		debug(" is invalid!");
> 
> Is invalid..then will not work fine?
> 
> i don't check your patch fully.
> Your patch doesn't control gpio with dt?
> Well, i don't agree this concept. it need to get opinion how to think about this.
> 
>> +	}
>> +	debug("\n");
>> +}
>> +
>> +static void nx_dw_mmc_clksel(struct dwmci_host *host)
>> +{
>> +	u32 val;
>> +
>> +#ifdef CONFIG_BOOST_MMC
> 
> What is BOOST_MMC?
> 
>> +	val = DWMCI_SET_SAMPLE_CLK(DWMCI_SHIFT_0) |
>> +	    DWMCI_SET_DRV_CLK(DWMCI_SHIFT_0) | DWMCI_SET_DIV_RATIO(1);
>> +#else
>> +	val = DWMCI_SET_SAMPLE_CLK(DWMCI_SHIFT_0) |
>> +	    DWMCI_SET_DRV_CLK(DWMCI_SHIFT_0) | DWMCI_SET_DIV_RATIO(3);
>> +#endif
>> +
>> +	dwmci_writel(host, DWMCI_CLKSEL, val);
>> +}
>> +
>> +static void nx_dw_mmc_reset(int ch)
>> +{
>> +	int rst_id = RESET_ID_SDMMC0 + ch;
> 
> RESET_ID_SDMMC0?
> 
>> +
>> +	nx_rstcon_setrst(rst_id, 0);
>> +	nx_rstcon_setrst(rst_id, 1);
>> +}
>> +
>> +static void nx_dw_mmc_clk_delay(struct udevice *dev)
>> +{
>> +	unsigned int delay;
>> +	struct nexell_dwmmc_priv *priv = dev_get_priv(dev);
>> +	struct dwmci_host *host = &priv->host;
>> +
>> +	delay = NX_MMC_CLK_DELAY(priv->d_delay,
>> +				 priv->d_shift, priv->s_delay, priv->s_shift);
>> +
>> +	writel(delay, (host->ioaddr + DWMCI_CLKCTRL));
>> +	debug("%s(): Values set: d_delay==%d, d_shift==%d, s_delay==%d, "
>> +	      "s_shift==%d\n", __func__, priv->d_delay, priv->d_shift,
>> +	      priv->s_delay, priv->s_shift);
>> +}
>> +
>> +static unsigned int nx_dw_mmc_get_clk(struct dwmci_host *host, uint freq)
>> +{
>> +	struct clk *clk;
>> +	struct udevice *dev = host->priv;
>> +	struct nexell_dwmmc_priv *priv = dev_get_priv(dev);
>> +
>> +	int index = host->dev_index;
>> +	char name[50] = { 0, };
>> +
>> +	clk = priv->clk;
>> +	if (!clk) {
>> +		sprintf(name, "%s.%d", DEV_NAME_SDHC, index);
> 
> DEV_NAME_SDHC ???
> 
>> +		clk = clk_get((const char *)name);
>> +		if (!clk)
>> +			return 0;
>> +		priv->clk = clk;
>> +	}
>> +
>> +	return clk_get_rate(clk) / 2;
>> +}
>> +
>> +static unsigned long nx_dw_mmc_set_clk(struct dwmci_host *host,
>> +				       unsigned int rate)
>> +{
>> +	struct clk *clk;
>> +	char name[50] = { 0, };
>> +	struct udevice *dev = host->priv;
>> +	struct nexell_dwmmc_priv *priv = dev_get_priv(dev);
>> +
>> +	int index = host->dev_index;
>> +
>> +	clk = priv->clk;
>> +	if (!clk) {
>> +		sprintf(name, "%s.%d", DEV_NAME_SDHC, index);
>> +		clk = clk_get((const char *)name);
>> +		if (!clk)
>> +			return 0;
>> +		priv->clk = clk;
>> +	}
>> +
>> +	clk_disable(clk);
>> +	rate = clk_set_rate(clk, rate);
>> +	clk_enable(clk);
>> +
>> +	return rate;
>> +}
>> +
>> +static int nexell_dwmmc_ofdata_to_platdata(struct udevice *dev)
>> +{
>> +	/* if (dev): *priv = dev->priv, else: *priv = NULL */
>> +	struct nexell_dwmmc_priv *priv = dev_get_priv(dev);
>> +	struct dwmci_host *host = &priv->host;
>> +	int val = -1;
>> +
>> +	debug("%s()\n", __func__);
>> +
>> +	host->name = dev->name;
>> +	host->ioaddr = dev_read_addr_ptr(dev);
>> +
>> +	val = dev_read_u32_default(dev, "nexell,bus-width", -1);
>> +	if (val < 0) {
>> +		debug("  'nexell,bus-width' missing/invalid!\n");
>> +		return -EINVAL;
>> +	}
>> +	host->buswidth = val;
>> +	host->get_mmc_clk = nx_dw_mmc_get_clk;
>> +	host->clksel = nx_dw_mmc_clksel;
>> +	host->priv = dev;
>> +
>> +	val = dev_read_u32_default(dev, "index", -1);
>> +	if (val < 0) {
>> +		debug("  'index' missing/invalid!\n");
>> +		return -EINVAL;
>> +	}
>> +	host->dev_index = val;
>> +
>> +	val = dev_read_u32_default(dev, "fifo-size", 0x20);
>> +	if (val <= 0) {
>> +		debug("  'fifo-size' missing/invalid!\n");
>> +		return -EINVAL;
>> +	}
>> +	priv->fifo_size = val;
>> +
>> +	priv->fifo_mode = dev_read_bool(dev, "fifo-mode");
>> +
>> +	val = dev_read_u32_default(dev, "frequency", -1);
>> +	if (val < 0) {
>> +		debug("  'frequency' missing/invalid!\n");
>> +		return -EINVAL;
>> +	}
>> +	priv->frequency = val;
>> +
>> +	val = dev_read_u32_default(dev, "max-frequency", -1);
>> +	if (val < 0) {
>> +		debug("  'max-frequency' missing/invalid!\n");
>> +		return -EINVAL;
>> +	}
>> +	priv->max_freq = val;
>> +	priv->min_freq = 400000;  /* 400 kHz */
>> +
>> +	val = dev_read_u32_default(dev, "nexell,drive_dly", -1);
>> +	if (val < 0) {
>> +		debug("  'nexell,drive_dly' missing/invalid!\n");
>> +		return -EINVAL;
>> +	}
>> +	priv->d_delay = val;
>> +
>> +	val = dev_read_u32_default(dev, "nexell,drive_shift", -1);
>> +	if (val < 0) {
>> +		debug("  'nexell,drive_shift' missing/invalid!\n");
>> +		return -EINVAL;
>> +	}
>> +	priv->d_shift = val;
>> +
>> +	val = dev_read_u32_default(dev, "nexell,sample_dly", -1);
>> +	if (val < 0) {
>> +		debug("  'nexell,sample_dly' missing/invalid!\n");
>> +		return -EINVAL;
>> +	}
>> +	priv->s_delay = val;
>> +
>> +	val = dev_read_u32_default(dev, "nexell,sample_shift", -1);
>> +	if (val < 0) {
>> +		debug("  'nexell,sample_shift' missing/invalid!\n");
>> +		return -EINVAL;
>> +	}
>> +	priv->s_shift = val;
>> +
>> +	debug("  index==%d, name==%s, ioaddr==0x%08x, buswidth==%d, "
>> +		  "fifo_size==%d, fifo_mode==%d, frequency==%d\n",
>> +		  host->dev_index, host->name, (u32)host->ioaddr,
>> +		  host->buswidth, priv->fifo_size, priv->fifo_mode,
>> +		  priv->frequency);
>> +	debug("  min_freq==%d, max_freq==%d, delay: "
>> +		  "0x%02x:0x%02x:0x%02x:0x%02x\n",
>> +		  priv->min_freq, priv->max_freq, priv->d_delay,
>> +		  priv->d_shift, priv->s_delay, priv->s_shift);
> 
> entirely not readable. not need to assign again with val.
> 
> priv->s_deley = dev_read_u32_default();
> 
> 
>> +
>> +	return 0;
>> +}
>> +
>> +static int nexell_dwmmc_probe(struct udevice *dev)
>> +{
>> +	struct nexell_mmc_plat *plat = dev_get_platdata(dev);
>> +	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
>> +	struct nexell_dwmmc_priv *priv = dev_get_priv(dev);
>> +	struct dwmci_host *host = &priv->host;
>> +	struct udevice *pwr_dev __maybe_unused;
>> +
>> +	debug("%s():\n", __func__);
> 
> Don't add unnecessary debug code. it's meaningless even if it's enabled.
> 
> Well, i didn't check other patches..but i think that your patches seems to based on older u-boot version.
> 
> Best Regards,
> Jaehoon Chung
> 
> 
>> +
>> +	host->fifoth_val = MSIZE(0x2) |
>> +		RX_WMARK(priv->fifo_size / 2 - 1) |
>> +		TX_WMARK(priv->fifo_size / 2);
>> +
>> +	host->fifo_mode = priv->fifo_mode;
>> +
>> +	dwmci_setup_cfg(&plat->cfg, host, priv->max_freq, priv->min_freq);
>> +	host->mmc = &plat->mmc;
>> +	host->mmc->priv = &priv->host;
>> +	host->mmc->dev = dev;
>> +	upriv->mmc = host->mmc;
>> +
>> +	nx_dw_mmc_set_pin(host);
>> +
>> +	debug("  nx_dw_mmc_set_clk(host, frequency * 4 == %d)\n",
>> +	      priv->frequency * 4);
>> +	nx_dw_mmc_set_clk(host, priv->frequency * 4);
>> +
>> +	nx_dw_mmc_reset(host->dev_index);
>> +	nx_dw_mmc_clk_delay(dev);
>> +
>> +	return dwmci_probe(dev);
>> +}
>> +
>> +static int nexell_dwmmc_bind(struct udevice *dev)
>> +{
>> +	struct nexell_mmc_plat *plat = dev_get_platdata(dev);
>> +
>> +	return dwmci_bind(dev, &plat->mmc, &plat->cfg);
>> +}
>> +
>> +static const struct udevice_id nexell_dwmmc_ids[] = {
>> +	{ .compatible = "nexell,nexell-dwmmc" },
>> +	{ }
>> +};
>> +
>> +U_BOOT_DRIVER(nexell_dwmmc_drv) = {
>> +	.name		= "nexell_dwmmc",
>> +	.id		= UCLASS_MMC,
>> +	.of_match	= nexell_dwmmc_ids,
>> +	.ofdata_to_platdata = nexell_dwmmc_ofdata_to_platdata,
>> +	.ops		= &dm_dwmci_ops,
>> +	.bind		= nexell_dwmmc_bind,
>> +	.probe		= nexell_dwmmc_probe,
>> +	.priv_auto_alloc_size = sizeof(struct nexell_dwmmc_priv),
>> +	.platdata_auto_alloc_size = sizeof(struct nexell_mmc_plat),
>> +};
>>
> 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [RFC PATCH v2 04/13] i2c: add nexell driver
  2020-03-28  9:43 ` [RFC PATCH v2 04/13] i2c: " Stefan Bosch
@ 2020-04-08  4:08   ` Heiko Schocher
  2020-04-08 17:57     ` Stefan B.
  0 siblings, 1 reply; 21+ messages in thread
From: Heiko Schocher @ 2020-04-08  4:08 UTC (permalink / raw)
  To: u-boot

Hello Stefan,

Am 28.03.2020 um 10:43 schrieb Stefan Bosch:
> Changes in relation to FriendlyARM's U-Boot nanopi2-v2016.01:
> - i2c/nx_i2c.c: Some adaptions mainly because of changes in
>    "struct udevice".
> - several Bugfixes in nx_i2c.c.
> - the driver has been for s5p6818 only. Code extended appropriately
>    in order s5p4418 is also working.
> - "probe_chip" added.
> 
> Signed-off-by: Stefan Bosch <stefan_b@posteo.net>
> ---
> 
> Changes in v2:
> - commit "i2c: mmc: add nexell driver (gpio, i2c, mmc, pwm)" splitted
>    into separate commits for gpio, i2c, mmc, pwm.
> - several Bugfixes in nx_i2c.c.
> - the i2c-driver has been for s5p6818 only. Code extended approriately
>    in order s5p4418 is also working.
> - "probe_chip" added to the i2c-driver.
> - doc/device-tree-bindings/i2c/nx_i2c.txt added.
> 
>   doc/device-tree-bindings/i2c/nx_i2c.txt |  28 ++
>   drivers/i2c/Kconfig                     |   9 +
>   drivers/i2c/Makefile                    |   1 +
>   drivers/i2c/nx_i2c.c                    | 649 ++++++++++++++++++++++++++++++++
>   4 files changed, 687 insertions(+)
>   create mode 100644 doc/device-tree-bindings/i2c/nx_i2c.txt
>   create mode 100644 drivers/i2c/nx_i2c.c

I do not find this patch in patchwork ...

Thanks for splitting the big patch into several patches.

Reviewed-by: Heiko Schocher <hs@denx.de>

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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [RFC PATCH v2 04/13] i2c: add nexell driver
  2020-04-08  4:08   ` Heiko Schocher
@ 2020-04-08 17:57     ` Stefan B.
  2020-04-09  4:56       ` Heiko Schocher
  0 siblings, 1 reply; 21+ messages in thread
From: Stefan B. @ 2020-04-08 17:57 UTC (permalink / raw)
  To: u-boot

Hi Heiko,

I assume that patchwork does get the patch-series automatically when I 
send it to u-boot at lists.denx.de, or am I wrong? Perhaps it is in some 
pipeline?

At least the patch-series appeared in U-Boot Digest ("[RFC PATCH v2 
04/13] i2c: add nexell driver" is in Vol 142, Issue 58).


Regards
Stefan

Am 08.04.20 um 06:08 schrieb Heiko Schocher:
> Hello Stefan,
> 
> Am 28.03.2020 um 10:43 schrieb Stefan Bosch:
>> Changes in relation to FriendlyARM's U-Boot nanopi2-v2016.01:
>> - i2c/nx_i2c.c: Some adaptions mainly because of changes in
>> ?? "struct udevice".
>> - several Bugfixes in nx_i2c.c.
>> - the driver has been for s5p6818 only. Code extended appropriately
>> ?? in order s5p4418 is also working.
>> - "probe_chip" added.
>>
>> Signed-off-by: Stefan Bosch <stefan_b@posteo.net>
>> ---
>>
>> Changes in v2:
>> - commit "i2c: mmc: add nexell driver (gpio, i2c, mmc, pwm)" splitted
>> ?? into separate commits for gpio, i2c, mmc, pwm.
>> - several Bugfixes in nx_i2c.c.
>> - the i2c-driver has been for s5p6818 only. Code extended approriately
>> ?? in order s5p4418 is also working.
>> - "probe_chip" added to the i2c-driver.
>> - doc/device-tree-bindings/i2c/nx_i2c.txt added.
>>
>> ? doc/device-tree-bindings/i2c/nx_i2c.txt |? 28 ++
>> ? drivers/i2c/Kconfig???????????????????? |?? 9 +
>> ? drivers/i2c/Makefile??????????????????? |?? 1 +
>> ? drivers/i2c/nx_i2c.c??????????????????? | 649 
>> ++++++++++++++++++++++++++++++++
>> ? 4 files changed, 687 insertions(+)
>> ? create mode 100644 doc/device-tree-bindings/i2c/nx_i2c.txt
>> ? create mode 100644 drivers/i2c/nx_i2c.c
> 
> I do not find this patch in patchwork ...
> 
> Thanks for splitting the big patch into several patches.
> 
> Reviewed-by: Heiko Schocher <hs@denx.de>
> 
> bye,
> Heiko

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [RFC PATCH v2 04/13] i2c: add nexell driver
  2020-04-08 17:57     ` Stefan B.
@ 2020-04-09  4:56       ` Heiko Schocher
  0 siblings, 0 replies; 21+ messages in thread
From: Heiko Schocher @ 2020-04-09  4:56 UTC (permalink / raw)
  To: u-boot

Hello Stefan,

Am 08.04.2020 um 19:57 schrieb Stefan B.:
> Hi Heiko,
> 
> I assume that patchwork does get the patch-series automatically when I send it to 
> u-boot at lists.denx.de, or am I wrong? Perhaps it is in some pipeline?

normally, yes, patchwork gets the patch automatically...

> At least the patch-series appeared in U-Boot Digest ("[RFC PATCH v2 04/13] i2c: add nexell driver" 
> is in Vol 142, Issue 58).

bye,
Heiko
> 
> 
> Regards
> Stefan
> 
> Am 08.04.20 um 06:08 schrieb Heiko Schocher:
>> Hello Stefan,
>>
>> Am 28.03.2020 um 10:43 schrieb Stefan Bosch:
>>> Changes in relation to FriendlyARM's U-Boot nanopi2-v2016.01:
>>> - i2c/nx_i2c.c: Some adaptions mainly because of changes in
>>> ?? "struct udevice".
>>> - several Bugfixes in nx_i2c.c.
>>> - the driver has been for s5p6818 only. Code extended appropriately
>>> ?? in order s5p4418 is also working.
>>> - "probe_chip" added.
>>>
>>> Signed-off-by: Stefan Bosch <stefan_b@posteo.net>
>>> ---
>>>
>>> Changes in v2:
>>> - commit "i2c: mmc: add nexell driver (gpio, i2c, mmc, pwm)" splitted
>>> ?? into separate commits for gpio, i2c, mmc, pwm.
>>> - several Bugfixes in nx_i2c.c.
>>> - the i2c-driver has been for s5p6818 only. Code extended approriately
>>> ?? in order s5p4418 is also working.
>>> - "probe_chip" added to the i2c-driver.
>>> - doc/device-tree-bindings/i2c/nx_i2c.txt added.
>>>
>>> ? doc/device-tree-bindings/i2c/nx_i2c.txt |? 28 ++
>>> ? drivers/i2c/Kconfig???????????????????? |?? 9 +
>>> ? drivers/i2c/Makefile??????????????????? |?? 1 +
>>> ? drivers/i2c/nx_i2c.c??????????????????? | 649 ++++++++++++++++++++++++++++++++
>>> ? 4 files changed, 687 insertions(+)
>>> ? create mode 100644 doc/device-tree-bindings/i2c/nx_i2c.txt
>>> ? create mode 100644 drivers/i2c/nx_i2c.c
>>
>> I do not find this patch in patchwork ...
>>
>> Thanks for splitting the big patch into several patches.
>>
>> Reviewed-by: Heiko Schocher <hs@denx.de>
>>
>> bye,
>> Heiko
> 

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

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [RFC PATCH v2 05/13] mmc: add nexell driver
  2020-04-02 11:03   ` Jaehoon Chung
  2020-04-02 16:51     ` Stefan B.
@ 2020-04-09 17:33     ` Stefan B.
  2020-04-10  0:25       ` Jaehoon Chung
  1 sibling, 1 reply; 21+ messages in thread
From: Stefan B. @ 2020-04-09 17:33 UTC (permalink / raw)
  To: u-boot

Hi,

see below my answers to your questions.

Regards
Stefan Bosch


Hi,

thanks a lot for your reply. As you already guessed I have ported the 
outdated U-Boot from FriendlyARM, see:
https://github.com/friendlyarm/u-boot/tree/nanopi2-v2016.01

The original MMC-driver has been nexell_dw_mmc.c, so I renamed it to 
nexell_dw_mmc_dm.c after changing to DM.

I will have a closer look at your suggestions and give you feedback ASAP.


Regards
Stefan Bosch


Am 02.04.20 um 13:03 schrieb Jaehoon Chung:
> Hi,
> 
> On 3/28/20 6:43 PM, Stefan Bosch wrote:
>> Changes in relation to FriendlyARM's U-Boot nanopi2-v2016.01:
>> - mmc: nexell_dw_mmc.c changed to nexell_dw_mmc_dm.c (switched to DM).
> 
> It doesn't need to add postfix as _dm.
> 
Ok, I have renamed it to nexell_dw_mmc.c.

>>
>> Signed-off-by: Stefan Bosch <stefan_b@posteo.net>
>> ---
>>
>> Changes in v2:
>> - commit "i2c: mmc: add nexell driver (gpio, i2c, mmc, pwm)" splitted
>>    into separate commits for gpio, i2c, mmc, pwm.
>>
>>   drivers/mmc/Kconfig            |   6 +
>>   drivers/mmc/Makefile           |   1 +
>>   drivers/mmc/nexell_dw_mmc_dm.c | 350 +++++++++++++++++++++++++++++++++++++++++
>>   3 files changed, 357 insertions(+)
>>   create mode 100644 drivers/mmc/nexell_dw_mmc_dm.c
>>
>> diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
>> index 2f0eedc..bb8e7c0 100644
>> --- a/drivers/mmc/Kconfig
>> +++ b/drivers/mmc/Kconfig
>> @@ -253,6 +253,12 @@ config MMC_DW_SNPS
>>   	  This selects support for Synopsys DesignWare Memory Card Interface driver
>>   	  extensions used in various Synopsys ARC devboards.
>>   
>> +config NEXELL_DWMMC
>> +	bool "Nexell SD/MMC controller support"
>> +	depends on ARCH_NEXELL
>> +	depends on MMC_DW
>> +	default y
> 
> Not depends on DM_MMC?
> 
You are right, I have inserted "depends on DM_MMC". I missed this when 
changing to DM.

>> +
>>   config MMC_MESON_GX
>>   	bool "Meson GX EMMC controller support"
>>   	depends on DM_MMC && BLK && ARCH_MESON
>> diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
>> index 9c1f8e5..a7b5a7b 100644
>> --- a/drivers/mmc/Makefile
>> +++ b/drivers/mmc/Makefile
>> @@ -43,6 +43,7 @@ obj-$(CONFIG_SH_MMCIF) += sh_mmcif.o
>>   obj-$(CONFIG_SH_SDHI) += sh_sdhi.o
>>   obj-$(CONFIG_STM32_SDMMC2) += stm32_sdmmc2.o
>>   obj-$(CONFIG_JZ47XX_MMC) += jz_mmc.o
>> +obj-$(CONFIG_NEXELL_DWMMC) += nexell_dw_mmc_dm.o
>>   
>>   # SDHCI
>>   obj-$(CONFIG_MMC_SDHCI)			+= sdhci.o
>> diff --git a/drivers/mmc/nexell_dw_mmc_dm.c b/drivers/mmc/nexell_dw_mmc_dm.c
>> new file mode 100644
>> index 0000000..b06b60d
>> --- /dev/null
>> +++ b/drivers/mmc/nexell_dw_mmc_dm.c
>> @@ -0,0 +1,350 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +/*
>> + * (C) Copyright 2016 Nexell
>> + * Youngbok, Park <park@nexell.co.kr>
>> + *
>> + * (C) Copyright 2019 Stefan Bosch <stefan_b@posteo.net>
>> + */
>> +
>> +#include <common.h>
>> +#include <clk.h>
>> +#include <dm.h>
>> +#include <dt-structs.h>
>> +#include <dwmmc.h>
>> +#include <syscon.h>
>> +#include <asm/gpio.h>
>> +#include <asm/arch/nx_gpio.h>
>> +#include <asm/arch/reset.h>
>> +
>> +#define DWMCI_CLKSEL			0x09C
>> +#define DWMCI_SHIFT_0			0x0
>> +#define DWMCI_SHIFT_1			0x1
>> +#define DWMCI_SHIFT_2			0x2
>> +#define DWMCI_SHIFT_3			0x3
>> +#define DWMCI_SET_SAMPLE_CLK(x)	(x)
>> +#define DWMCI_SET_DRV_CLK(x)	((x) << 16)
>> +#define DWMCI_SET_DIV_RATIO(x)	((x) << 24)
>> +#define DWMCI_CLKCTRL			0x114
>> +#define NX_MMC_CLK_DELAY(x, y, a, b)	((((x) & 0xFF) << 0) |\
>> +					(((y) & 0x03) << 16) |\
>> +					(((a) & 0xFF) << 8)  |\
>> +					(((b) & 0x03) << 24))
>> +
>> +struct nexell_mmc_plat {
>> +	struct mmc_config cfg;
>> +	struct mmc mmc;
>> +};
>> +
>> +struct nexell_dwmmc_priv {
>> +	struct clk *clk;
>> +	struct dwmci_host host;
>> +	int fifo_size;
>> +	bool fifo_mode;
>> +	int frequency;
>> +	u32 min_freq;
>> +	u32 max_freq;
>> +	int d_delay;
>> +	int d_shift;
>> +	int s_delay;
>> +	int s_shift;
>> +
>> +};
>> +
>> +struct clk *clk_get(const char *id);
>> +
>> +static void set_pin_stat(int index, int bit, int value)
>> +{
>> +#if !defined(CONFIG_SPL_BUILD)
>> +	nx_gpio_set_pad_function(index, bit, value);
>> +#else
>> +#if defined(CONFIG_ARCH_S5P4418) ||	\
>> +	defined(CONFIG_ARCH_S5P6818)
>> +
>> +	unsigned long base[5] = {
>> +		PHY_BASEADDR_GPIOA, PHY_BASEADDR_GPIOB,
>> +		PHY_BASEADDR_GPIOC, PHY_BASEADDR_GPIOD,
>> +		PHY_BASEADDR_GPIOE,
>> +	};
> 
> I don't understand why gpio pin is set in mmc driver?
> If nexell soc will change the gpio map and function value, does it needs to add other gpio control?
> 
>> +
>> +	dw_mmc_set_pin(base[index], bit, value);
>> +#endif
>> +#endif
>> +}
>> +
>> +static void nx_dw_mmc_set_pin(struct dwmci_host *host)
>> +{
>> +	debug("  %s(): dev_index == %d", __func__, host->dev_index);
>> +
>> +	switch (host->dev_index) {
>> +	case 0:
>> +		set_pin_stat(0, 29, 1);
>> +		set_pin_stat(0, 31, 1);
>> +		set_pin_stat(1, 1, 1);
>> +		set_pin_stat(1, 3, 1);
>> +		set_pin_stat(1, 5, 1);
>> +		set_pin_stat(1, 7, 1);
>> +		break;
>> +	case 1:
>> +		set_pin_stat(3, 22, 1);
>> +		set_pin_stat(3, 23, 1);
>> +		set_pin_stat(3, 24, 1);
>> +		set_pin_stat(3, 25, 1);
>> +		set_pin_stat(3, 26, 1);
>> +		set_pin_stat(3, 27, 1);
>> +		break;
>> +	case 2:
>> +		set_pin_stat(2, 18, 2);
>> +		set_pin_stat(2, 19, 2);
>> +		set_pin_stat(2, 20, 2);
>> +		set_pin_stat(2, 21, 2);
>> +		set_pin_stat(2, 22, 2);
>> +		set_pin_stat(2, 23, 2);
>> +		if (host->buswidth == 8) {
>> +			set_pin_stat(4, 21, 2);
>> +			set_pin_stat(4, 22, 2);
>> +			set_pin_stat(4, 23, 2);
>> +			set_pin_stat(4, 24, 2);
>> +		}
>> +		break;
>> +	default:
>> +		debug(" is invalid!");
> 
> Is invalid..then will not work fine?
> 
> i don't check your patch fully.
> Your patch doesn't control gpio with dt?
> Well, i don't agree this concept. it need to get opinion how to think about this.
> 
Nexell has not implemented an pinctrl-driver, so the GPIOs are switched 
to MMC-function here.
I have removed the above "default", now I check for a valid dev_index in 
nexell_dwmmc_ofdata_to_platdata().

>> +	}
>> +	debug("\n");
>> +}
>> +
>> +static void nx_dw_mmc_clksel(struct dwmci_host *host)
>> +{
>> +	u32 val;
>> +
>> +#ifdef CONFIG_BOOST_MMC
> 
> What is BOOST_MMC?
> 
This influences what value is written to register offset 0x9C of the 
MMC-controller. Unfortunatelly, I can not give you more info because 
this register is indicated as "Reserved" in the S5P4418-datasheet I have 
access to (Revision 0.10 from October 2014).

>> +	val = DWMCI_SET_SAMPLE_CLK(DWMCI_SHIFT_0) |
>> +	    DWMCI_SET_DRV_CLK(DWMCI_SHIFT_0) | DWMCI_SET_DIV_RATIO(1);
>> +#else
>> +	val = DWMCI_SET_SAMPLE_CLK(DWMCI_SHIFT_0) |
>> +	    DWMCI_SET_DRV_CLK(DWMCI_SHIFT_0) | DWMCI_SET_DIV_RATIO(3);
>> +#endif
>> +
>> +	dwmci_writel(host, DWMCI_CLKSEL, val);
>> +}
>> +
>> +static void nx_dw_mmc_reset(int ch)
>> +{
>> +	int rst_id = RESET_ID_SDMMC0 + ch;
> 
> RESET_ID_SDMMC0?
> 
This is defined in arch/arm/include/asm/arch/nexell.h.

>> +
>> +	nx_rstcon_setrst(rst_id, 0);
>> +	nx_rstcon_setrst(rst_id, 1);
>> +}
>> +
>> +static void nx_dw_mmc_clk_delay(struct udevice *dev)
>> +{
>> +	unsigned int delay;
>> +	struct nexell_dwmmc_priv *priv = dev_get_priv(dev);
>> +	struct dwmci_host *host = &priv->host;
>> +
>> +	delay = NX_MMC_CLK_DELAY(priv->d_delay,
>> +				 priv->d_shift, priv->s_delay, priv->s_shift);
>> +
>> +	writel(delay, (host->ioaddr + DWMCI_CLKCTRL));
>> +	debug("%s(): Values set: d_delay==%d, d_shift==%d, s_delay==%d, "
>> +	      "s_shift==%d\n", __func__, priv->d_delay, priv->d_shift,
>> +	      priv->s_delay, priv->s_shift);
>> +}
>> +
>> +static unsigned int nx_dw_mmc_get_clk(struct dwmci_host *host, uint freq)
>> +{
>> +	struct clk *clk;
>> +	struct udevice *dev = host->priv;
>> +	struct nexell_dwmmc_priv *priv = dev_get_priv(dev);
>> +
>> +	int index = host->dev_index;
>> +	char name[50] = { 0, };
>> +
>> +	clk = priv->clk;
>> +	if (!clk) {
>> +		sprintf(name, "%s.%d", DEV_NAME_SDHC, index);
> 
> DEV_NAME_SDHC ???
> 
This is also defined in arch/arm/include/asm/arch/nexell.h: "nx-sdhc"

>> +		clk = clk_get((const char *)name);
>> +		if (!clk)
>> +			return 0;
>> +		priv->clk = clk;
>> +	}
>> +
>> +	return clk_get_rate(clk) / 2;
>> +}
>> +
>> +static unsigned long nx_dw_mmc_set_clk(struct dwmci_host *host,
>> +				       unsigned int rate)
>> +{
>> +	struct clk *clk;
>> +	char name[50] = { 0, };
>> +	struct udevice *dev = host->priv;
>> +	struct nexell_dwmmc_priv *priv = dev_get_priv(dev);
>> +
>> +	int index = host->dev_index;
>> +
>> +	clk = priv->clk;
>> +	if (!clk) {
>> +		sprintf(name, "%s.%d", DEV_NAME_SDHC, index);
>> +		clk = clk_get((const char *)name);
>> +		if (!clk)
>> +			return 0;
>> +		priv->clk = clk;
>> +	}
>> +
>> +	clk_disable(clk);
>> +	rate = clk_set_rate(clk, rate);
>> +	clk_enable(clk);
>> +
>> +	return rate;
>> +}
>> +
>> +static int nexell_dwmmc_ofdata_to_platdata(struct udevice *dev)
>> +{
>> +	/* if (dev): *priv = dev->priv, else: *priv = NULL */
>> +	struct nexell_dwmmc_priv *priv = dev_get_priv(dev);
>> +	struct dwmci_host *host = &priv->host;
>> +	int val = -1;
>> +
>> +	debug("%s()\n", __func__);
>> +
>> +	host->name = dev->name;
>> +	host->ioaddr = dev_read_addr_ptr(dev);
>> +
>> +	val = dev_read_u32_default(dev, "nexell,bus-width", -1);
>> +	if (val < 0) {
>> +		debug("  'nexell,bus-width' missing/invalid!\n");
>> +		return -EINVAL;
>> +	}
>> +	host->buswidth = val;
>> +	host->get_mmc_clk = nx_dw_mmc_get_clk;
>> +	host->clksel = nx_dw_mmc_clksel;
>> +	host->priv = dev;
>> +
>> +	val = dev_read_u32_default(dev, "index", -1);
>> +	if (val < 0) {
>> +		debug("  'index' missing/invalid!\n");
>> +		return -EINVAL;
>> +	}
>> +	host->dev_index = val;
>> +
>> +	val = dev_read_u32_default(dev, "fifo-size", 0x20);
>> +	if (val <= 0) {
>> +		debug("  'fifo-size' missing/invalid!\n");
>> +		return -EINVAL;
>> +	}
>> +	priv->fifo_size = val;
>> +
>> +	priv->fifo_mode = dev_read_bool(dev, "fifo-mode");
>> +
>> +	val = dev_read_u32_default(dev, "frequency", -1);
>> +	if (val < 0) {
>> +		debug("  'frequency' missing/invalid!\n");
>> +		return -EINVAL;
>> +	}
>> +	priv->frequency = val;
>> +
>> +	val = dev_read_u32_default(dev, "max-frequency", -1);
>> +	if (val < 0) {
>> +		debug("  'max-frequency' missing/invalid!\n");
>> +		return -EINVAL;
>> +	}
>> +	priv->max_freq = val;
>> +	priv->min_freq = 400000;  /* 400 kHz */
>> +
>> +	val = dev_read_u32_default(dev, "nexell,drive_dly", -1);
>> +	if (val < 0) {
>> +		debug("  'nexell,drive_dly' missing/invalid!\n");
>> +		return -EINVAL;
>> +	}
>> +	priv->d_delay = val;
>> +
>> +	val = dev_read_u32_default(dev, "nexell,drive_shift", -1);
>> +	if (val < 0) {
>> +		debug("  'nexell,drive_shift' missing/invalid!\n");
>> +		return -EINVAL;
>> +	}
>> +	priv->d_shift = val;
>> +
>> +	val = dev_read_u32_default(dev, "nexell,sample_dly", -1);
>> +	if (val < 0) {
>> +		debug("  'nexell,sample_dly' missing/invalid!\n");
>> +		return -EINVAL;
>> +	}
>> +	priv->s_delay = val;
>> +
>> +	val = dev_read_u32_default(dev, "nexell,sample_shift", -1);
>> +	if (val < 0) {
>> +		debug("  'nexell,sample_shift' missing/invalid!\n");
>> +		return -EINVAL;
>> +	}
>> +	priv->s_shift = val;
>> +
>> +	debug("  index==%d, name==%s, ioaddr==0x%08x, buswidth==%d, "
>> +		  "fifo_size==%d, fifo_mode==%d, frequency==%d\n",
>> +		  host->dev_index, host->name, (u32)host->ioaddr,
>> +		  host->buswidth, priv->fifo_size, priv->fifo_mode,
>> +		  priv->frequency);
>> +	debug("  min_freq==%d, max_freq==%d, delay: "
>> +		  "0x%02x:0x%02x:0x%02x:0x%02x\n",
>> +		  priv->min_freq, priv->max_freq, priv->d_delay,
>> +		  priv->d_shift, priv->s_delay, priv->s_shift);
> 
> entirely not readable. not need to assign again with val.
> 
> priv->s_deley = dev_read_u32_default();
> 
> 
I have reworked nexell_dwmmc_ofdata_to_platdata(), i.e. valid default 
values are used now (where possible) and the appropriate if-blocks have 
been removed.

>> +
>> +	return 0;
>> +}
>> +
>> +static int nexell_dwmmc_probe(struct udevice *dev)
>> +{
>> +	struct nexell_mmc_plat *plat = dev_get_platdata(dev);
>> +	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
>> +	struct nexell_dwmmc_priv *priv = dev_get_priv(dev);
>> +	struct dwmci_host *host = &priv->host;
>> +	struct udevice *pwr_dev __maybe_unused;
>> +
>> +	debug("%s():\n", __func__);
> 
> Don't add unnecessary debug code. it's meaningless even if it's enabled.
> 
Ok, I have removed this debug code.

> Well, i didn't check other patches..but i think that your patches seems to based on older u-boot version.
> 
> Best Regards,
> Jaehoon Chung
> 
> 
>> +
>> +	host->fifoth_val = MSIZE(0x2) |
>> +		RX_WMARK(priv->fifo_size / 2 - 1) |
>> +		TX_WMARK(priv->fifo_size / 2);
>> +
>> +	host->fifo_mode = priv->fifo_mode;
>> +
>> +	dwmci_setup_cfg(&plat->cfg, host, priv->max_freq, priv->min_freq);
>> +	host->mmc = &plat->mmc;
>> +	host->mmc->priv = &priv->host;
>> +	host->mmc->dev = dev;
>> +	upriv->mmc = host->mmc;
>> +
>> +	nx_dw_mmc_set_pin(host);
>> +
>> +	debug("  nx_dw_mmc_set_clk(host, frequency * 4 == %d)\n",
>> +	      priv->frequency * 4);
>> +	nx_dw_mmc_set_clk(host, priv->frequency * 4);
>> +
>> +	nx_dw_mmc_reset(host->dev_index);
>> +	nx_dw_mmc_clk_delay(dev);
>> +
>> +	return dwmci_probe(dev);
>> +}
>> +
>> +static int nexell_dwmmc_bind(struct udevice *dev)
>> +{
>> +	struct nexell_mmc_plat *plat = dev_get_platdata(dev);
>> +
>> +	return dwmci_bind(dev, &plat->mmc, &plat->cfg);
>> +}
>> +
>> +static const struct udevice_id nexell_dwmmc_ids[] = {
>> +	{ .compatible = "nexell,nexell-dwmmc" },
>> +	{ }
>> +};
>> +
>> +U_BOOT_DRIVER(nexell_dwmmc_drv) = {
>> +	.name		= "nexell_dwmmc",
>> +	.id		= UCLASS_MMC,
>> +	.of_match	= nexell_dwmmc_ids,
>> +	.ofdata_to_platdata = nexell_dwmmc_ofdata_to_platdata,
>> +	.ops		= &dm_dwmci_ops,
>> +	.bind		= nexell_dwmmc_bind,
>> +	.probe		= nexell_dwmmc_probe,
>> +	.priv_auto_alloc_size = sizeof(struct nexell_dwmmc_priv),
>> +	.platdata_auto_alloc_size = sizeof(struct nexell_mmc_plat),
>> +};
>>
> 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [RFC PATCH v2 05/13] mmc: add nexell driver
  2020-04-09 17:33     ` Stefan B.
@ 2020-04-10  0:25       ` Jaehoon Chung
  0 siblings, 0 replies; 21+ messages in thread
From: Jaehoon Chung @ 2020-04-10  0:25 UTC (permalink / raw)
  To: u-boot

Hi,

On 4/10/20 2:33 AM, Stefan B. wrote:
> Hi,
> 
> see below my answers to your questions.
> 
> Regards
> Stefan Bosch
> 
> 
> Hi,
> 
> thanks a lot for your reply. As you already guessed I have ported the outdated U-Boot from FriendlyARM, see:
> https://protect2.fireeye.com/url?k=00de144b-5d1421fc-00df9f04-0cc47a3003e8-6dd6a1886465f918&q=1&u=https%3A%2F%2Fgithub.com%2Ffriendlyarm%2Fu-boot%2Ftree%2Fnanopi2-v2016.01
> 
> The original MMC-driver has been nexell_dw_mmc.c, so I renamed it to nexell_dw_mmc_dm.c after changing to DM.
> 
> I will have a closer look at your suggestions and give you feedback ASAP.

I don't know that you had received reviews about other patches.
If you want to apply new chip, then i think you need to implement drivers based on DM. 

> 
> 
> Regards
> Stefan Bosch
> 
> 
> Am 02.04.20 um 13:03 schrieb Jaehoon Chung:
>> Hi,
>>
>> On 3/28/20 6:43 PM, Stefan Bosch wrote:
>>> Changes in relation to FriendlyARM's U-Boot nanopi2-v2016.01:
>>> - mmc: nexell_dw_mmc.c changed to nexell_dw_mmc_dm.c (switched to DM).
>>
>> It doesn't need to add postfix as _dm.
>>
> Ok, I have renamed it to nexell_dw_mmc.c.
> 
>>>
>>> Signed-off-by: Stefan Bosch <stefan_b@posteo.net>
>>> ---
>>>
>>> Changes in v2:
>>> - commit "i2c: mmc: add nexell driver (gpio, i2c, mmc, pwm)" splitted
>>> ?? into separate commits for gpio, i2c, mmc, pwm.
>>>
>>> ? drivers/mmc/Kconfig??????????? |?? 6 +
>>> ? drivers/mmc/Makefile?????????? |?? 1 +
>>> ? drivers/mmc/nexell_dw_mmc_dm.c | 350 +++++++++++++++++++++++++++++++++++++++++
>>> ? 3 files changed, 357 insertions(+)
>>> ? create mode 100644 drivers/mmc/nexell_dw_mmc_dm.c
>>>
>>> diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
>>> index 2f0eedc..bb8e7c0 100644
>>> --- a/drivers/mmc/Kconfig
>>> +++ b/drivers/mmc/Kconfig
>>> @@ -253,6 +253,12 @@ config MMC_DW_SNPS
>>> ??????? This selects support for Synopsys DesignWare Memory Card Interface driver
>>> ??????? extensions used in various Synopsys ARC devboards.
>>> ? +config NEXELL_DWMMC
>>> +??? bool "Nexell SD/MMC controller support"
>>> +??? depends on ARCH_NEXELL
>>> +??? depends on MMC_DW
>>> +??? default y
>>
>> Not depends on DM_MMC?
>>
> You are right, I have inserted "depends on DM_MMC". I missed this when changing to DM.
> 
>>> +
>>> ? config MMC_MESON_GX
>>> ????? bool "Meson GX EMMC controller support"
>>> ????? depends on DM_MMC && BLK && ARCH_MESON
>>> diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
>>> index 9c1f8e5..a7b5a7b 100644
>>> --- a/drivers/mmc/Makefile
>>> +++ b/drivers/mmc/Makefile
>>> @@ -43,6 +43,7 @@ obj-$(CONFIG_SH_MMCIF) += sh_mmcif.o
>>> ? obj-$(CONFIG_SH_SDHI) += sh_sdhi.o
>>> ? obj-$(CONFIG_STM32_SDMMC2) += stm32_sdmmc2.o
>>> ? obj-$(CONFIG_JZ47XX_MMC) += jz_mmc.o
>>> +obj-$(CONFIG_NEXELL_DWMMC) += nexell_dw_mmc_dm.o
>>> ? ? # SDHCI
>>> ? obj-$(CONFIG_MMC_SDHCI)??????????? += sdhci.o
>>> diff --git a/drivers/mmc/nexell_dw_mmc_dm.c b/drivers/mmc/nexell_dw_mmc_dm.c
>>> new file mode 100644
>>> index 0000000..b06b60d
>>> --- /dev/null
>>> +++ b/drivers/mmc/nexell_dw_mmc_dm.c
>>> @@ -0,0 +1,350 @@
>>> +// SPDX-License-Identifier: GPL-2.0+
>>> +/*
>>> + * (C) Copyright 2016 Nexell
>>> + * Youngbok, Park <park@nexell.co.kr>
>>> + *
>>> + * (C) Copyright 2019 Stefan Bosch <stefan_b@posteo.net>
>>> + */
>>> +
>>> +#include <common.h>
>>> +#include <clk.h>
>>> +#include <dm.h>
>>> +#include <dt-structs.h>
>>> +#include <dwmmc.h>
>>> +#include <syscon.h>
>>> +#include <asm/gpio.h>
>>> +#include <asm/arch/nx_gpio.h>
>>> +#include <asm/arch/reset.h>
>>> +
>>> +#define DWMCI_CLKSEL??????????? 0x09C
>>> +#define DWMCI_SHIFT_0??????????? 0x0
>>> +#define DWMCI_SHIFT_1??????????? 0x1
>>> +#define DWMCI_SHIFT_2??????????? 0x2
>>> +#define DWMCI_SHIFT_3??????????? 0x3
>>> +#define DWMCI_SET_SAMPLE_CLK(x)??? (x)
>>> +#define DWMCI_SET_DRV_CLK(x)??? ((x) << 16)
>>> +#define DWMCI_SET_DIV_RATIO(x)??? ((x) << 24)
>>> +#define DWMCI_CLKCTRL??????????? 0x114
>>> +#define NX_MMC_CLK_DELAY(x, y, a, b)??? ((((x) & 0xFF) << 0) |\
>>> +??????????????????? (((y) & 0x03) << 16) |\
>>> +??????????????????? (((a) & 0xFF) << 8)? |\
>>> +??????????????????? (((b) & 0x03) << 24))
>>> +
>>> +struct nexell_mmc_plat {
>>> +??? struct mmc_config cfg;
>>> +??? struct mmc mmc;
>>> +};
>>> +
>>> +struct nexell_dwmmc_priv {
>>> +??? struct clk *clk;
>>> +??? struct dwmci_host host;
>>> +??? int fifo_size;
>>> +??? bool fifo_mode;
>>> +??? int frequency;
>>> +??? u32 min_freq;
>>> +??? u32 max_freq;
>>> +??? int d_delay;
>>> +??? int d_shift;
>>> +??? int s_delay;
>>> +??? int s_shift;
>>> +
>>> +};
>>> +
>>> +struct clk *clk_get(const char *id);
>>> +
>>> +static void set_pin_stat(int index, int bit, int value)
>>> +{
>>> +#if !defined(CONFIG_SPL_BUILD)
>>> +??? nx_gpio_set_pad_function(index, bit, value);
>>> +#else
>>> +#if defined(CONFIG_ARCH_S5P4418) ||??? \
>>> +??? defined(CONFIG_ARCH_S5P6818)
>>> +
>>> +??? unsigned long base[5] = {
>>> +??????? PHY_BASEADDR_GPIOA, PHY_BASEADDR_GPIOB,
>>> +??????? PHY_BASEADDR_GPIOC, PHY_BASEADDR_GPIOD,
>>> +??????? PHY_BASEADDR_GPIOE,
>>> +??? };
>>
>> I don't understand why gpio pin is set in mmc driver?
>> If nexell soc will change the gpio map and function value, does it needs to add other gpio control?
>>
>>> +
>>> +??? dw_mmc_set_pin(base[index], bit, value);
>>> +#endif
>>> +#endif
>>> +}
>>> +
>>> +static void nx_dw_mmc_set_pin(struct dwmci_host *host)
>>> +{
>>> +??? debug("? %s(): dev_index == %d", __func__, host->dev_index);
>>> +
>>> +??? switch (host->dev_index) {
>>> +??? case 0:
>>> +??????? set_pin_stat(0, 29, 1);
>>> +??????? set_pin_stat(0, 31, 1);
>>> +??????? set_pin_stat(1, 1, 1);
>>> +??????? set_pin_stat(1, 3, 1);
>>> +??????? set_pin_stat(1, 5, 1);
>>> +??????? set_pin_stat(1, 7, 1);
>>> +??????? break;
>>> +??? case 1:
>>> +??????? set_pin_stat(3, 22, 1);
>>> +??????? set_pin_stat(3, 23, 1);
>>> +??????? set_pin_stat(3, 24, 1);
>>> +??????? set_pin_stat(3, 25, 1);
>>> +??????? set_pin_stat(3, 26, 1);
>>> +??????? set_pin_stat(3, 27, 1);
>>> +??????? break;
>>> +??? case 2:
>>> +??????? set_pin_stat(2, 18, 2);
>>> +??????? set_pin_stat(2, 19, 2);
>>> +??????? set_pin_stat(2, 20, 2);
>>> +??????? set_pin_stat(2, 21, 2);
>>> +??????? set_pin_stat(2, 22, 2);
>>> +??????? set_pin_stat(2, 23, 2);
>>> +??????? if (host->buswidth == 8) {
>>> +??????????? set_pin_stat(4, 21, 2);
>>> +??????????? set_pin_stat(4, 22, 2);
>>> +??????????? set_pin_stat(4, 23, 2);
>>> +??????????? set_pin_stat(4, 24, 2);
>>> +??????? }
>>> +??????? break;
>>> +??? default:
>>> +??????? debug(" is invalid!");
>>
>> Is invalid..then will not work fine?
>>
>> i don't check your patch fully.
>> Your patch doesn't control gpio with dt?
>> Well, i don't agree this concept. it need to get opinion how to think about this.
>>
> Nexell has not implemented an pinctrl-driver, so the GPIOs are switched to MMC-function here.
> I have removed the above "default", now I check for a valid dev_index in nexell_dwmmc_ofdata_to_platdata().

Then it needs to implement pinctrl driver.

> 
>>> +??? }
>>> +??? debug("\n");
>>> +}
>>> +
>>> +static void nx_dw_mmc_clksel(struct dwmci_host *host)
>>> +{
>>> +??? u32 val;
>>> +
>>> +#ifdef CONFIG_BOOST_MMC
>>
>> What is BOOST_MMC?
>>
> This influences what value is written to register offset 0x9C of the MMC-controller. Unfortunatelly, I can not give you more info because this register is indicated as "Reserved" in the S5P4418-datasheet I have access to (Revision 0.10 from October 2014).

I didn't find where BOOST_MMC config is defined.
And it can be used with device-tree property. As i know it's relevant to clk phase and timing.

> 
>>> +??? val = DWMCI_SET_SAMPLE_CLK(DWMCI_SHIFT_0) |
>>> +??????? DWMCI_SET_DRV_CLK(DWMCI_SHIFT_0) | DWMCI_SET_DIV_RATIO(1);
>>> +#else
>>> +??? val = DWMCI_SET_SAMPLE_CLK(DWMCI_SHIFT_0) |
>>> +??????? DWMCI_SET_DRV_CLK(DWMCI_SHIFT_0) | DWMCI_SET_DIV_RATIO(3);
>>> +#endif
>>> +
>>> +??? dwmci_writel(host, DWMCI_CLKSEL, val);
>>> +}
>>> +
>>> +static void nx_dw_mmc_reset(int ch)
>>> +{
>>> +??? int rst_id = RESET_ID_SDMMC0 + ch;
>>
>> RESET_ID_SDMMC0?
>>
> This is defined in arch/arm/include/asm/arch/nexell.h.
> 
>>> +
>>> +??? nx_rstcon_setrst(rst_id, 0);
>>> +??? nx_rstcon_setrst(rst_id, 1);
>>> +}
>>> +
>>> +static void nx_dw_mmc_clk_delay(struct udevice *dev)
>>> +{
>>> +??? unsigned int delay;
>>> +??? struct nexell_dwmmc_priv *priv = dev_get_priv(dev);
>>> +??? struct dwmci_host *host = &priv->host;
>>> +
>>> +??? delay = NX_MMC_CLK_DELAY(priv->d_delay,
>>> +???????????????? priv->d_shift, priv->s_delay, priv->s_shift);
>>> +
>>> +??? writel(delay, (host->ioaddr + DWMCI_CLKCTRL));
>>> +??? debug("%s(): Values set: d_delay==%d, d_shift==%d, s_delay==%d, "
>>> +????????? "s_shift==%d\n", __func__, priv->d_delay, priv->d_shift,
>>> +????????? priv->s_delay, priv->s_shift);
>>> +}
>>> +
>>> +static unsigned int nx_dw_mmc_get_clk(struct dwmci_host *host, uint freq)
>>> +{
>>> +??? struct clk *clk;
>>> +??? struct udevice *dev = host->priv;
>>> +??? struct nexell_dwmmc_priv *priv = dev_get_priv(dev);
>>> +
>>> +??? int index = host->dev_index;
>>> +??? char name[50] = { 0, };
>>> +
>>> +??? clk = priv->clk;
>>> +??? if (!clk) {
>>> +??????? sprintf(name, "%s.%d", DEV_NAME_SDHC, index);
>>
>> DEV_NAME_SDHC ???
>>
> This is also defined in arch/arm/include/asm/arch/nexell.h: "nx-sdhc"
> 
>>> +??????? clk = clk_get((const char *)name);
>>> +??????? if (!clk)
>>> +??????????? return 0;
>>> +??????? priv->clk = clk;
>>> +??? }
>>> +
>>> +??? return clk_get_rate(clk) / 2;
>>> +}
>>> +
>>> +static unsigned long nx_dw_mmc_set_clk(struct dwmci_host *host,
>>> +?????????????????????? unsigned int rate)
>>> +{
>>> +??? struct clk *clk;
>>> +??? char name[50] = { 0, };
>>> +??? struct udevice *dev = host->priv;
>>> +??? struct nexell_dwmmc_priv *priv = dev_get_priv(dev);
>>> +
>>> +??? int index = host->dev_index;
>>> +
>>> +??? clk = priv->clk;
>>> +??? if (!clk) {
>>> +??????? sprintf(name, "%s.%d", DEV_NAME_SDHC, index);
>>> +??????? clk = clk_get((const char *)name);
>>> +??????? if (!clk)
>>> +??????????? return 0;
>>> +??????? priv->clk = clk;
>>> +??? }
>>> +
>>> +??? clk_disable(clk);
>>> +??? rate = clk_set_rate(clk, rate);
>>> +??? clk_enable(clk);
>>> +
>>> +??? return rate;
>>> +}
>>> +
>>> +static int nexell_dwmmc_ofdata_to_platdata(struct udevice *dev)
>>> +{
>>> +??? /* if (dev): *priv = dev->priv, else: *priv = NULL */
>>> +??? struct nexell_dwmmc_priv *priv = dev_get_priv(dev);
>>> +??? struct dwmci_host *host = &priv->host;
>>> +??? int val = -1;
>>> +
>>> +??? debug("%s()\n", __func__);
>>> +
>>> +??? host->name = dev->name;
>>> +??? host->ioaddr = dev_read_addr_ptr(dev);
>>> +
>>> +??? val = dev_read_u32_default(dev, "nexell,bus-width", -1);
>>> +??? if (val < 0) {
>>> +??????? debug("? 'nexell,bus-width' missing/invalid!\n");
>>> +??????? return -EINVAL;
>>> +??? }
>>> +??? host->buswidth = val;
>>> +??? host->get_mmc_clk = nx_dw_mmc_get_clk;
>>> +??? host->clksel = nx_dw_mmc_clksel;
>>> +??? host->priv = dev;
>>> +
>>> +??? val = dev_read_u32_default(dev, "index", -1);
>>> +??? if (val < 0) {
>>> +??????? debug("? 'index' missing/invalid!\n");
>>> +??????? return -EINVAL;
>>> +??? }
>>> +??? host->dev_index = val;
>>> +
>>> +??? val = dev_read_u32_default(dev, "fifo-size", 0x20);
>>> +??? if (val <= 0) {
>>> +??????? debug("? 'fifo-size' missing/invalid!\n");
>>> +??????? return -EINVAL;
>>> +??? }
>>> +??? priv->fifo_size = val;
>>> +
>>> +??? priv->fifo_mode = dev_read_bool(dev, "fifo-mode");
>>> +
>>> +??? val = dev_read_u32_default(dev, "frequency", -1);
>>> +??? if (val < 0) {
>>> +??????? debug("? 'frequency' missing/invalid!\n");
>>> +??????? return -EINVAL;
>>> +??? }
>>> +??? priv->frequency = val;
>>> +
>>> +??? val = dev_read_u32_default(dev, "max-frequency", -1);
>>> +??? if (val < 0) {
>>> +??????? debug("? 'max-frequency' missing/invalid!\n");
>>> +??????? return -EINVAL;
>>> +??? }
>>> +??? priv->max_freq = val;
>>> +??? priv->min_freq = 400000;? /* 400 kHz */
>>> +
>>> +??? val = dev_read_u32_default(dev, "nexell,drive_dly", -1);
>>> +??? if (val < 0) {
>>> +??????? debug("? 'nexell,drive_dly' missing/invalid!\n");
>>> +??????? return -EINVAL;
>>> +??? }
>>> +??? priv->d_delay = val;
>>> +
>>> +??? val = dev_read_u32_default(dev, "nexell,drive_shift", -1);
>>> +??? if (val < 0) {
>>> +??????? debug("? 'nexell,drive_shift' missing/invalid!\n");
>>> +??????? return -EINVAL;
>>> +??? }
>>> +??? priv->d_shift = val;
>>> +
>>> +??? val = dev_read_u32_default(dev, "nexell,sample_dly", -1);
>>> +??? if (val < 0) {
>>> +??????? debug("? 'nexell,sample_dly' missing/invalid!\n");
>>> +??????? return -EINVAL;
>>> +??? }
>>> +??? priv->s_delay = val;
>>> +
>>> +??? val = dev_read_u32_default(dev, "nexell,sample_shift", -1);
>>> +??? if (val < 0) {
>>> +??????? debug("? 'nexell,sample_shift' missing/invalid!\n");
>>> +??????? return -EINVAL;
>>> +??? }
>>> +??? priv->s_shift = val;
>>> +
>>> +??? debug("? index==%d, name==%s, ioaddr==0x%08x, buswidth==%d, "
>>> +????????? "fifo_size==%d, fifo_mode==%d, frequency==%d\n",
>>> +????????? host->dev_index, host->name, (u32)host->ioaddr,
>>> +????????? host->buswidth, priv->fifo_size, priv->fifo_mode,
>>> +????????? priv->frequency);
>>> +??? debug("? min_freq==%d, max_freq==%d, delay: "
>>> +????????? "0x%02x:0x%02x:0x%02x:0x%02x\n",
>>> +????????? priv->min_freq, priv->max_freq, priv->d_delay,
>>> +????????? priv->d_shift, priv->s_delay, priv->s_shift);
>>
>> entirely not readable. not need to assign again with val.
>>
>> priv->s_deley = dev_read_u32_default();
>>
>>
> I have reworked nexell_dwmmc_ofdata_to_platdata(), i.e. valid default values are used now (where possible) and the appropriate if-blocks have been removed.
> 
>>> +
>>> +??? return 0;
>>> +}
>>> +
>>> +static int nexell_dwmmc_probe(struct udevice *dev)
>>> +{
>>> +??? struct nexell_mmc_plat *plat = dev_get_platdata(dev);
>>> +??? struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
>>> +??? struct nexell_dwmmc_priv *priv = dev_get_priv(dev);
>>> +??? struct dwmci_host *host = &priv->host;
>>> +??? struct udevice *pwr_dev __maybe_unused;
>>> +
>>> +??? debug("%s():\n", __func__);
>>
>> Don't add unnecessary debug code. it's meaningless even if it's enabled.
>>
> Ok, I have removed this debug code.
> 
>> Well, i didn't check other patches..but i think that your patches seems to based on older u-boot version.
>>
>> Best Regards,
>> Jaehoon Chung
>>
>>
>>> +
>>> +??? host->fifoth_val = MSIZE(0x2) |
>>> +??????? RX_WMARK(priv->fifo_size / 2 - 1) |
>>> +??????? TX_WMARK(priv->fifo_size / 2);
>>> +
>>> +??? host->fifo_mode = priv->fifo_mode;
>>> +
>>> +??? dwmci_setup_cfg(&plat->cfg, host, priv->max_freq, priv->min_freq);
>>> +??? host->mmc = &plat->mmc;
>>> +??? host->mmc->priv = &priv->host;
>>> +??? host->mmc->dev = dev;
>>> +??? upriv->mmc = host->mmc;
>>> +
>>> +??? nx_dw_mmc_set_pin(host);
>>> +
>>> +??? debug("? nx_dw_mmc_set_clk(host, frequency * 4 == %d)\n",
>>> +????????? priv->frequency * 4);
>>> +??? nx_dw_mmc_set_clk(host, priv->frequency * 4);
>>> +
>>> +??? nx_dw_mmc_reset(host->dev_index);
>>> +??? nx_dw_mmc_clk_delay(dev);
>>> +
>>> +??? return dwmci_probe(dev);
>>> +}
>>> +
>>> +static int nexell_dwmmc_bind(struct udevice *dev)
>>> +{
>>> +??? struct nexell_mmc_plat *plat = dev_get_platdata(dev);
>>> +
>>> +??? return dwmci_bind(dev, &plat->mmc, &plat->cfg);
>>> +}
>>> +
>>> +static const struct udevice_id nexell_dwmmc_ids[] = {
>>> +??? { .compatible = "nexell,nexell-dwmmc" },
>>> +??? { }
>>> +};
>>> +
>>> +U_BOOT_DRIVER(nexell_dwmmc_drv) = {
>>> +??? .name??????? = "nexell_dwmmc",
>>> +??? .id??????? = UCLASS_MMC,
>>> +??? .of_match??? = nexell_dwmmc_ids,
>>> +??? .ofdata_to_platdata = nexell_dwmmc_ofdata_to_platdata,
>>> +??? .ops??????? = &dm_dwmci_ops,
>>> +??? .bind??????? = nexell_dwmmc_bind,
>>> +??? .probe??????? = nexell_dwmmc_probe,
>>> +??? .priv_auto_alloc_size = sizeof(struct nexell_dwmmc_priv),
>>> +??? .platdata_auto_alloc_size = sizeof(struct nexell_mmc_plat),
>>> +};
>>>
>>
> 
> 

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2020-04-10  0:25 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-28  9:43 [RFC PATCH v2 00/13] arm: add support for SoC S5P4418 Stefan Bosch
2020-03-28  9:43 ` [RFC PATCH v2 01/13] arm: add mach-nexell (header files) Stefan Bosch
2020-03-28  9:43 ` [RFC PATCH v2 02/13] arm: add mach-nexell (all files except header files) Stefan Bosch
2020-03-28  9:43 ` [RFC PATCH v2 03/13] gpio: add nexell driver Stefan Bosch
2020-03-28  9:43 ` [RFC PATCH v2 04/13] i2c: " Stefan Bosch
2020-04-08  4:08   ` Heiko Schocher
2020-04-08 17:57     ` Stefan B.
2020-04-09  4:56       ` Heiko Schocher
2020-03-28  9:43 ` [RFC PATCH v2 05/13] mmc: " Stefan Bosch
2020-04-02 11:03   ` Jaehoon Chung
2020-04-02 16:51     ` Stefan B.
2020-04-09 17:33     ` Stefan B.
2020-04-10  0:25       ` Jaehoon Chung
2020-03-28  9:43 ` [RFC PATCH v2 06/13] pwm: add driver for nexell Stefan Bosch
2020-03-28  9:43 ` [RFC PATCH v2 07/13] video: add nexell video driver (soc: displaytop) Stefan Bosch
2020-03-28  9:43 ` [RFC PATCH v2 08/13] video: add nexell video driver (soc: mlc, mipi) Stefan Bosch
2020-03-28  9:43 ` [RFC PATCH v2 09/13] video: add nexell video driver (soc: lvds, hdmi) Stefan Bosch
2020-03-28  9:43 ` [RFC PATCH v2 10/13] video: add nexell video driver (soc: dpc, makefile) Stefan Bosch
2020-03-28  9:43 ` [RFC PATCH v2 11/13] video: add nexell video driver (display/video driver) Stefan Bosch
2020-03-28  9:43 ` [RFC PATCH v2 12/13] arm: add support for SoC s5p4418 (cpu) / nanopi2 board Stefan Bosch
2020-03-28  9:43 ` [RFC PATCH v2 13/13] arm: add (default) config for " Stefan Bosch

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.