Discussion:
[U-Boot] [PATCH 0/6] Add support for MIPS Creator CI20
Ezequiel Garcia
2018-12-10 20:35:56 UTC
Permalink
As the subject says, this series adds support for CI20.

Most of the work was done by Paul Burton, and then by Marek Vasut.
I've just rescued the work from the dark wastelands of Mordor,
did some cleaning here and there and submitted.

Patches 1, 2, and 4 are completely untouched. I've picked them
from Marek's tree.

For the MMC driver (patch 3) there is some cleanup, and some
fixes for proper DM migration.

Finally, patches 5 and 6 have been changed a bit: I've cleaned
up the devicetree, the board support files and the defconfig.

This is based on top of today's master (7ff485c68b7e) and has
been tested by SD-card booting both U-Boot and Linux. Booting
Linux via TFTP was also tested.

Please note that I've added Paul's SOB to all the patches
he authored, to make the authorship chain more clear.

Reviews and tests are welcome. Bikesheds not so much! ;-)

Thanks!

Paul Burton (6):
misc: Add JZ47xx efuse driver
gpio: Add JZ47xx GPIO driver
mmc: Add JZ47xx SD/MMC controller driver
mips: Add SPL header
mips: jz47xx: Add JZ4780 SoC support
mips: jz47xx: Add Creator CI20 platform

arch/mips/Kconfig | 7 +
arch/mips/Makefile | 1 +
arch/mips/dts/Makefile | 1 +
arch/mips/dts/ci20.dts | 120 ++++
arch/mips/dts/jz4780.dtsi | 162 ++++++
arch/mips/include/asm/spl.h | 35 ++
arch/mips/mach-jz47xx/Kconfig | 26 +
arch/mips/mach-jz47xx/Makefile | 7 +
arch/mips/mach-jz47xx/include/mach/jz4780.h | 104 ++++
.../mach-jz47xx/include/mach/jz4780_dram.h | 457 +++++++++++++++
arch/mips/mach-jz47xx/jz4780/Makefile | 5 +
arch/mips/mach-jz47xx/jz4780/jz4780.c | 142 +++++
arch/mips/mach-jz47xx/jz4780/pll.c | 528 ++++++++++++++++++
arch/mips/mach-jz47xx/jz4780/sdram.c | 271 +++++++++
arch/mips/mach-jz47xx/jz4780/timer.c | 238 ++++++++
arch/mips/mach-jz47xx/jz4780/u-boot-spl.lds | 52 ++
arch/mips/mach-jz47xx/start.S | 99 ++++
board/imgtec/ci20/Kconfig | 15 +
board/imgtec/ci20/Makefile | 5 +
board/imgtec/ci20/README | 10 +
board/imgtec/ci20/ci20.c | 365 ++++++++++++
configs/ci20_defconfig | 47 ++
drivers/gpio/Kconfig | 7 +
drivers/gpio/Makefile | 1 +
drivers/gpio/gpio-jz47xx.c | 78 +++
drivers/misc/Kconfig | 6 +
drivers/misc/Makefile | 1 +
drivers/misc/jz4780_efuse.c | 100 ++++
drivers/mmc/Kconfig | 6 +
drivers/mmc/Makefile | 1 +
drivers/mmc/jz_mmc. | 0
drivers/mmc/jz_mmc.c | 491 ++++++++++++++++
include/configs/ci20.h | 74 +++
include/dt-bindings/clock/jz4780-cgu.h | 88 +++
34 files changed, 3550 insertions(+)
create mode 100644 arch/mips/dts/ci20.dts
create mode 100644 arch/mips/dts/jz4780.dtsi
create mode 100644 arch/mips/include/asm/spl.h
create mode 100644 arch/mips/mach-jz47xx/Kconfig
create mode 100644 arch/mips/mach-jz47xx/Makefile
create mode 100644 arch/mips/mach-jz47xx/include/mach/jz4780.h
create mode 100644 arch/mips/mach-jz47xx/include/mach/jz4780_dram.h
create mode 100644 arch/mips/mach-jz47xx/jz4780/Makefile
create mode 100644 arch/mips/mach-jz47xx/jz4780/jz4780.c
create mode 100644 arch/mips/mach-jz47xx/jz4780/pll.c
create mode 100644 arch/mips/mach-jz47xx/jz4780/sdram.c
create mode 100644 arch/mips/mach-jz47xx/jz4780/timer.c
create mode 100644 arch/mips/mach-jz47xx/jz4780/u-boot-spl.lds
create mode 100644 arch/mips/mach-jz47xx/start.S
create mode 100644 board/imgtec/ci20/Kconfig
create mode 100644 board/imgtec/ci20/Makefile
create mode 100644 board/imgtec/ci20/README
create mode 100644 board/imgtec/ci20/ci20.c
create mode 100644 configs/ci20_defconfig
create mode 100644 drivers/gpio/gpio-jz47xx.c
create mode 100644 drivers/misc/jz4780_efuse.c
create mode 100644 drivers/mmc/jz_mmc.
create mode 100644 drivers/mmc/jz_mmc.c
create mode 100644 include/configs/ci20.h
create mode 100644 include/dt-bindings/clock/jz4780-cgu.h
--
2.20.0.rc2
Ezequiel Garcia
2018-12-10 20:35:57 UTC
Permalink
From: Paul Burton <***@imgtec.com>

Add driver for the efuse block in the JZ47xx SOC.

Cc: Daniel Schwierzeck <***@gmail.com>
Signed-off-by: Paul Burton <***@imgtec.com>
Signed-off-by: Marek Vasut <***@gmail.com>
---
drivers/misc/Kconfig | 6 +++
drivers/misc/Makefile | 1 +
drivers/misc/jz4780_efuse.c | 100 ++++++++++++++++++++++++++++++++++++
3 files changed, 107 insertions(+)
create mode 100644 drivers/misc/jz4780_efuse.c

diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 48febc47d263..704c8dd1955f 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -120,6 +120,12 @@ config FSL_SEC_MON
Security Monitor can be transitioned on any security failures,
like software violations or hardware security violations.

+config JZ4780_EFUSE
+ bool "Ingenic JZ4780 eFUSE support"
+ depends on ARCH_JZ47XX
+ help
+ This selects support for the eFUSE on Ingenic JZ4780 SoCs.
+
config MXC_OCOTP
bool "Enable MXC OCOTP Driver"
help
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 302d44159274..6bdf5054f475 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -62,3 +62,4 @@ obj-$(CONFIG_TEGRA_CAR) += tegra_car.o
obj-$(CONFIG_TWL4030_LED) += twl4030_led.o
obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress_config.o
obj-$(CONFIG_WINBOND_W83627) += winbond_w83627.o
+obj-$(CONFIG_JZ4780_EFUSE) += jz4780_efuse.o
diff --git a/drivers/misc/jz4780_efuse.c b/drivers/misc/jz4780_efuse.c
new file mode 100644
index 000000000000..78383f343dce
--- /dev/null
+++ b/drivers/misc/jz4780_efuse.c
@@ -0,0 +1,100 @@
+/*
+ * JZ4780 EFUSE driver
+ *
+ * Copyright (c) 2014 Imagination Technologies
+ * Author: Alex Smith <***@imgtec.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/unaligned.h>
+#include <errno.h>
+#include <mach/jz4780.h>
+
+#define EFUSE_EFUCTRL 0xd0
+#define EFUSE_EFUCFG 0xd4
+#define EFUSE_EFUSTATE 0xd8
+#define EFUSE_EFUDATA(n) (0xdc + ((n) * 4))
+
+#define EFUSE_EFUCTRL_RD_EN BIT(0)
+#define EFUSE_EFUCTRL_LEN_BIT 16
+#define EFUSE_EFUCTRL_LEN_MASK 0x1f
+#define EFUSE_EFUCTRL_ADDR_BIT 21
+#define EFUSE_EFUCTRL_ADDR_MASK 0x1ff
+#define EFUSE_EFUCTRL_CS BIT(30)
+
+#define EFUSE_EFUCFG_RD_STROBE_BIT 16
+#define EFUSE_EFUCFG_RD_STROBE_MASK 0xf
+#define EFUSE_EFUCFG_RD_ADJ_BIT 20
+#define EFUSE_EFUCFG_RD_ADJ_MASK 0xf
+
+#define EFUSE_EFUSTATE_RD_DONE BIT(0)
+
+static void jz4780_efuse_read_chunk(size_t addr, size_t count, u8 *buf)
+{
+ void __iomem *regs = (void __iomem *)NEMC_BASE;
+ size_t i;
+ u32 val;
+
+ val = EFUSE_EFUCTRL_RD_EN |
+ ((count - 1) << EFUSE_EFUCTRL_LEN_BIT) |
+ (addr << EFUSE_EFUCTRL_ADDR_BIT) |
+ ((addr > 0x200) ? EFUSE_EFUCTRL_CS : 0);
+ writel(val, regs + EFUSE_EFUCTRL);
+ /* FIXME -- wait_bit() */
+ while (!(readl(regs + EFUSE_EFUSTATE) & EFUSE_EFUSTATE_RD_DONE))
+ ;
+
+ if ((count % 4) == 0) {
+ for (i = 0; i < count / 4; i++) {
+ val = readl(regs + EFUSE_EFUDATA(i));
+ put_unaligned(val, (u32 *)(buf + (i * 4)));
+ }
+ } else {
+ val = readl(regs + EFUSE_EFUDATA(0));
+ if (count > 2)
+ buf[2] = (val >> 16) & 0xff;
+ if (count > 1)
+ buf[1] = (val >> 8) & 0xff;
+ buf[0] = val & 0xff;
+ }
+}
+
+static inline int jz4780_efuse_chunk_size(size_t count)
+{
+ if (count >= 32)
+ return 32;
+ else if ((count / 4) > 0)
+ return (count / 4) * 4;
+ else
+ return count % 4;
+}
+
+void jz4780_efuse_read(size_t addr, size_t count, u8 *buf)
+{
+ size_t chunk;
+
+ while (count > 0) {
+ chunk = jz4780_efuse_chunk_size(count);
+ jz4780_efuse_read_chunk(addr, chunk, buf);
+ addr += chunk;
+ buf += chunk;
+ count -= chunk;
+ }
+}
+
+void jz4780_efuse_init(u32 ahb2_rate)
+{
+ void __iomem *regs = (void __iomem *)NEMC_BASE;
+ u32 rd_adj, rd_strobe, tmp;
+
+ rd_adj = (((6500 * (ahb2_rate / 1000000)) / 1000000) + 0xf) / 2;
+ tmp = (((35000 * (ahb2_rate / 1000000)) / 1000000) - 4) - rd_adj;
+ rd_strobe = ((tmp + 0xf) / 2 < 7) ? 7 : (tmp + 0xf) / 2;
+
+ tmp = (rd_adj << EFUSE_EFUCFG_RD_ADJ_BIT) |
+ (rd_strobe << EFUSE_EFUCFG_RD_STROBE_BIT);
+ writel(tmp, regs + EFUSE_EFUCFG);
+}
--
2.20.0.rc2
Marek Vasut
2018-12-10 20:56:53 UTC
Permalink
Post by Ezequiel Garcia
Add driver for the efuse block in the JZ47xx SOC.
[...]
Post by Ezequiel Garcia
+static void jz4780_efuse_read_chunk(size_t addr, size_t count, u8 *buf)
+{
+ void __iomem *regs = (void __iomem *)NEMC_BASE;
+ size_t i;
+ u32 val;
+
+ val = EFUSE_EFUCTRL_RD_EN |
+ ((count - 1) << EFUSE_EFUCTRL_LEN_BIT) |
+ (addr << EFUSE_EFUCTRL_ADDR_BIT) |
+ ((addr > 0x200) ? EFUSE_EFUCTRL_CS : 0);
+ writel(val, regs + EFUSE_EFUCTRL);
+ /* FIXME -- wait_bit() */
+ while (!(readl(regs + EFUSE_EFUSTATE) & EFUSE_EFUSTATE_RD_DONE))
+ ;
Does wait_for_bit_le32() fit into the SPL if you use it here ?
Post by Ezequiel Garcia
+ if ((count % 4) == 0) {
+ for (i = 0; i < count / 4; i++) {
+ val = readl(regs + EFUSE_EFUDATA(i));
+ put_unaligned(val, (u32 *)(buf + (i * 4)));
+ }
I thought we had something like ioread*_rep(), but I guess not.
Post by Ezequiel Garcia
+ } else {
+ val = readl(regs + EFUSE_EFUDATA(0));
+ if (count > 2)
+ buf[2] = (val >> 16) & 0xff;
+ if (count > 1)
+ buf[1] = (val >> 8) & 0xff;
+ buf[0] = val & 0xff;
+ }
+}
+
+static inline int jz4780_efuse_chunk_size(size_t count)
+{
+ if (count >= 32)
+ return 32;
+ else if ((count / 4) > 0)
+ return (count / 4) * 4;
+ else
+ return count % 4;
+}
+
+void jz4780_efuse_read(size_t addr, size_t count, u8 *buf)
+{
+ size_t chunk;
+
+ while (count > 0) {
+ chunk = jz4780_efuse_chunk_size(count);
+ jz4780_efuse_read_chunk(addr, chunk, buf);
+ addr += chunk;
+ buf += chunk;
+ count -= chunk;
+ }
+}
+
+void jz4780_efuse_init(u32 ahb2_rate)
+{
+ void __iomem *regs = (void __iomem *)NEMC_BASE;
+ u32 rd_adj, rd_strobe, tmp;
+
+ rd_adj = (((6500 * (ahb2_rate / 1000000)) / 1000000) + 0xf) / 2;
+ tmp = (((35000 * (ahb2_rate / 1000000)) / 1000000) - 4) - rd_adj;
+ rd_strobe = ((tmp + 0xf) / 2 < 7) ? 7 : (tmp + 0xf) / 2;
Can you turn those magic numbers into macros ? Or if they really come
from the datasheet, well ... at least add a comment.
Post by Ezequiel Garcia
+ tmp = (rd_adj << EFUSE_EFUCFG_RD_ADJ_BIT) |
+ (rd_strobe << EFUSE_EFUCFG_RD_STROBE_BIT);
+ writel(tmp, regs + EFUSE_EFUCFG);
+}
--
Best regards,
Marek Vasut
Ezequiel Garcia
2018-12-10 22:02:07 UTC
Permalink
Post by Marek Vasut
Post by Ezequiel Garcia
Add driver for the efuse block in the JZ47xx SOC.
[...]
Post by Ezequiel Garcia
+static void jz4780_efuse_read_chunk(size_t addr, size_t count, u8 *buf)
+{
+ void __iomem *regs = (void __iomem *)NEMC_BASE;
+ size_t i;
+ u32 val;
+
+ val = EFUSE_EFUCTRL_RD_EN |
+ ((count - 1) << EFUSE_EFUCTRL_LEN_BIT) |
+ (addr << EFUSE_EFUCTRL_ADDR_BIT) |
+ ((addr > 0x200) ? EFUSE_EFUCTRL_CS : 0);
+ writel(val, regs + EFUSE_EFUCTRL);
+ /* FIXME -- wait_bit() */
+ while (!(readl(regs + EFUSE_EFUSTATE) & EFUSE_EFUSTATE_RD_DONE))
+ ;
Does wait_for_bit_le32() fit into the SPL if you use it here ?
I literally haven't looked at these (working) drivers. Let's see..

...hm, to be honest, I'm more worried about these infinite loops
than about fancy API uses. An infinite loop in the MMC driver caused
a freeze during driver-model porting, so these are more serious threats.

Will try to address the unbounded loop and take a stab at using
wait_for_bit_le32.

Thanks for the review!
Eze
Marek Vasut
2018-12-10 22:03:27 UTC
Permalink
Post by Ezequiel Garcia
Post by Marek Vasut
Post by Ezequiel Garcia
Add driver for the efuse block in the JZ47xx SOC.
[...]
Post by Ezequiel Garcia
+static void jz4780_efuse_read_chunk(size_t addr, size_t count, u8 *buf)
+{
+ void __iomem *regs = (void __iomem *)NEMC_BASE;
+ size_t i;
+ u32 val;
+
+ val = EFUSE_EFUCTRL_RD_EN |
+ ((count - 1) << EFUSE_EFUCTRL_LEN_BIT) |
+ (addr << EFUSE_EFUCTRL_ADDR_BIT) |
+ ((addr > 0x200) ? EFUSE_EFUCTRL_CS : 0);
+ writel(val, regs + EFUSE_EFUCTRL);
+ /* FIXME -- wait_bit() */
+ while (!(readl(regs + EFUSE_EFUSTATE) & EFUSE_EFUSTATE_RD_DONE))
+ ;
Does wait_for_bit_le32() fit into the SPL if you use it here ?
I literally haven't looked at these (working) drivers. Let's see..
...hm, to be honest, I'm more worried about these infinite loops
than about fancy API uses. An infinite loop in the MMC driver caused
a freeze during driver-model porting, so these are more serious threats.
Will try to address the unbounded loop and take a stab at using
wait_for_bit_le32.
Right, that should fix the infinite loop problem.
--
Best regards,
Marek Vasut
Ezequiel Garcia
2018-12-10 20:35:58 UTC
Permalink
From: Paul Burton <***@imgtec.com>

Add primitive GPIO controller driver for the JZ47xx SoC.

Cc: Daniel Schwierzeck <***@gmail.com>
Signed-off-by: Paul Burton <***@imgtec.com>
Signed-off-by: Marek Vasut <***@gmail.com>
---
drivers/gpio/Kconfig | 7 ++++
drivers/gpio/Makefile | 1 +
drivers/gpio/gpio-jz47xx.c | 78 ++++++++++++++++++++++++++++++++++++++
3 files changed, 86 insertions(+)
create mode 100644 drivers/gpio/gpio-jz47xx.c

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 35344e57c6c6..46c161c99ce9 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -322,4 +322,11 @@ config MT7621_GPIO
help
Say yes here to support MediaTek MT7621 compatible GPIOs.

+config JZ47XX_GPIO
+ bool "Ingenic JZ47xx GPIO driver"
+ depends on ARCH_JZ47XX
+ default y
+ help
+ Supports GPIO access on Ingenic JZ47xx SoCs.
+
endmenu
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 7ed9a4ec4221..92310e9ba934 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -59,3 +59,4 @@ obj-$(CONFIG_MSM_GPIO) += msm_gpio.o
obj-$(CONFIG_$(SPL_)PCF8575_GPIO) += pcf8575_gpio.o
obj-$(CONFIG_PM8916_GPIO) += pm8916_gpio.o
obj-$(CONFIG_MT7621_GPIO) += mt7621_gpio.o
+obj-$(CONFIG_JZ47XX_GPIO) += gpio-jz47xx.o
diff --git a/drivers/gpio/gpio-jz47xx.c b/drivers/gpio/gpio-jz47xx.c
new file mode 100644
index 000000000000..565108192306
--- /dev/null
+++ b/drivers/gpio/gpio-jz47xx.c
@@ -0,0 +1,78 @@
+/*
+ * Ingenic JZ47xx GPIO
+ *
+ * Copyright (C) 2018 Marek Vasut <***@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <errno.h>
+#include <mach/jz4780.h>
+
+int gpio_get_value(unsigned gpio)
+{
+ void __iomem *gpio_regs = (void __iomem *)GPIO_BASE;
+ int port = gpio / 32;
+ int pin = gpio % 32;
+
+ return readl(gpio_regs + GPIO_PXPIN(port)) & BIT(pin);
+}
+
+int gpio_set_value(unsigned gpio, int value)
+{
+ void __iomem *gpio_regs = (void __iomem *)GPIO_BASE;
+ int port = gpio / 32;
+ int pin = gpio % 32;
+
+ if (value)
+ writel(BIT(pin), gpio_regs + GPIO_PXPAT0S(port));
+ else
+ writel(BIT(pin), gpio_regs + GPIO_PXPAT0C(port));
+
+ return 0;
+}
+
+int gpio_direction_input(unsigned gpio)
+{
+ void __iomem *gpio_regs = (void __iomem *)GPIO_BASE;
+ int port = gpio / 32;
+ int pin = gpio % 32;
+
+ writel(BIT(pin), gpio_regs + GPIO_PXINTC(port));
+ writel(BIT(pin), gpio_regs + GPIO_PXMASKS(port));
+ writel(BIT(pin), gpio_regs + GPIO_PXPAT1S(port));
+
+ return 0;
+}
+
+int gpio_direction_output(unsigned gpio, int value)
+{
+ void __iomem *gpio_regs = (void __iomem *)GPIO_BASE;
+ int port = gpio / 32;
+ int pin = gpio % 32;
+
+ writel(BIT(pin), gpio_regs + GPIO_PXINTC(port));
+ writel(BIT(pin), gpio_regs + GPIO_PXMASKS(port));
+ writel(BIT(pin), gpio_regs + GPIO_PXPAT1C(port));
+
+ gpio_set_value(gpio, value);
+
+ return 0;
+}
+
+int gpio_request(unsigned gpio, const char *label)
+{
+ int port = gpio / 32;
+
+ if (port >= 6)
+ return -EINVAL;
+
+ return 0;
+}
+
+int gpio_free(unsigned gpio)
+{
+ return 0;
+}
--
2.20.0.rc2
Ezequiel Garcia
2018-12-10 20:36:01 UTC
Permalink
From: Paul Burton <***@imgtec.com>

Add initial support for the Ingenic JZ47xx MIPS SoC.

Cc: Daniel Schwierzeck <***@gmail.com>
Signed-off-by: Paul Burton <***@imgtec.com>
Signed-off-by: Marek Vasut <***@gmail.com>
Signed-off-by: Ezequiel Garcia <***@collabora.com>
---
arch/mips/Kconfig | 7 +
arch/mips/Makefile | 1 +
arch/mips/dts/jz4780.dtsi | 162 ++++++
arch/mips/mach-jz47xx/Kconfig | 15 +
arch/mips/mach-jz47xx/Makefile | 7 +
arch/mips/mach-jz47xx/include/mach/jz4780.h | 104 ++++
.../mach-jz47xx/include/mach/jz4780_dram.h | 457 +++++++++++++++
arch/mips/mach-jz47xx/jz4780/Makefile | 5 +
arch/mips/mach-jz47xx/jz4780/jz4780.c | 142 +++++
arch/mips/mach-jz47xx/jz4780/pll.c | 528 ++++++++++++++++++
arch/mips/mach-jz47xx/jz4780/sdram.c | 271 +++++++++
arch/mips/mach-jz47xx/jz4780/timer.c | 238 ++++++++
arch/mips/mach-jz47xx/jz4780/u-boot-spl.lds | 52 ++
arch/mips/mach-jz47xx/start.S | 99 ++++
include/dt-bindings/clock/jz4780-cgu.h | 88 +++
15 files changed, 2176 insertions(+)
create mode 100644 arch/mips/dts/jz4780.dtsi
create mode 100644 arch/mips/mach-jz47xx/Kconfig
create mode 100644 arch/mips/mach-jz47xx/Makefile
create mode 100644 arch/mips/mach-jz47xx/include/mach/jz4780.h
create mode 100644 arch/mips/mach-jz47xx/include/mach/jz4780_dram.h
create mode 100644 arch/mips/mach-jz47xx/jz4780/Makefile
create mode 100644 arch/mips/mach-jz47xx/jz4780/jz4780.c
create mode 100644 arch/mips/mach-jz47xx/jz4780/pll.c
create mode 100644 arch/mips/mach-jz47xx/jz4780/sdram.c
create mode 100644 arch/mips/mach-jz47xx/jz4780/timer.c
create mode 100644 arch/mips/mach-jz47xx/jz4780/u-boot-spl.lds
create mode 100644 arch/mips/mach-jz47xx/start.S
create mode 100644 include/dt-bindings/clock/jz4780-cgu.h

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 1b1b1d7d0031..44b25460b8cc 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -88,6 +88,12 @@ config ARCH_MT7620
select SUPPORTS_LITTLE_ENDIAN
select SYSRESET

+config ARCH_JZ47XX
+ bool "Support Ingenic JZ47xx"
+ select SUPPORT_SPL
+ select OF_CONTROL
+ select DM
+
config MACH_PIC32
bool "Support Microchip PIC32"
select DM
@@ -139,6 +145,7 @@ source "board/micronas/vct/Kconfig"
source "board/qemu-mips/Kconfig"
source "arch/mips/mach-ath79/Kconfig"
source "arch/mips/mach-bmips/Kconfig"
+source "arch/mips/mach-jz47xx/Kconfig"
source "arch/mips/mach-pic32/Kconfig"
source "arch/mips/mach-mt7620/Kconfig"

diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 802244a06e5d..a294e9b1e8b9 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -13,6 +13,7 @@ libs-y += arch/mips/lib/

machine-$(CONFIG_ARCH_ATH79) += ath79
machine-$(CONFIG_ARCH_BMIPS) += bmips
+machine-$(CONFIG_ARCH_JZ47XX) += jz47xx
machine-$(CONFIG_MACH_PIC32) += pic32
machine-$(CONFIG_ARCH_MT7620) += mt7620

diff --git a/arch/mips/dts/jz4780.dtsi b/arch/mips/dts/jz4780.dtsi
new file mode 100644
index 000000000000..e34f8d359036
--- /dev/null
+++ b/arch/mips/dts/jz4780.dtsi
@@ -0,0 +1,162 @@
+#include <dt-bindings/clock/jz4780-cgu.h>
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "ingenic,jz4780";
+
+ cpuintc: interrupt-controller {
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ compatible = "mti,cpu-interrupt-controller";
+ };
+
+ intc: interrupt-***@10001000 {
+ compatible = "ingenic,jz4780-intc";
+ reg = <0x10001000 0x50>;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ interrupt-parent = <&cpuintc>;
+ interrupts = <2>;
+ };
+
+ ext: ext {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ };
+
+ rtc: rtc {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ };
+
+ cgu: jz4780-***@10000000 {
+ compatible = "ingenic,jz4780-cgu";
+ reg = <0x10000000 0x100>;
+
+ clocks = <&ext>, <&rtc>;
+ clock-names = "ext", "rtc";
+
+ #clock-cells = <1>;
+ };
+
+ mmc0: ***@13450000 {
+ compatible = "ingenic,jz4780-mmc";
+ reg = <0x13450000 0x1000>;
+
+ status = "disabled";
+
+ clocks = <&cgu JZ4780_CLK_MSC0>;
+ clock-names = "mmc";
+ };
+
+ mmc1: ***@13460000 {
+ compatible = "ingenic,jz4780-mmc";
+ reg = <0x13460000 0x1000>;
+
+ clocks = <&cgu JZ4780_CLK_MSC1>;
+ clock-names = "mmc";
+
+ status = "disabled";
+ };
+
+ uart0: ***@10030000 {
+ compatible = "ingenic,jz4780-uart";
+ reg = <0x10030000 0x100>;
+ reg-shift = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <51>;
+
+ clocks = <&ext>, <&cgu JZ4780_CLK_UART0>;
+ clock-names = "baud", "module";
+
+ status = "disabled";
+ };
+
+ uart1: ***@10031000 {
+ compatible = "ingenic,jz4780-uart";
+ reg = <0x10031000 0x100>;
+ reg-shift = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <50>;
+
+ clocks = <&ext>, <&cgu JZ4780_CLK_UART1>;
+ clock-names = "baud", "module";
+
+ status = "disabled";
+ };
+
+ uart2: ***@10032000 {
+ compatible = "ingenic,jz4780-uart";
+ reg = <0x10032000 0x100>;
+ reg-shift = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <49>;
+
+ clocks = <&ext>, <&cgu JZ4780_CLK_UART2>;
+ clock-names = "baud", "module";
+
+ status = "disabled";
+ };
+
+ uart3: ***@10033000 {
+ compatible = "ingenic,jz4780-uart";
+ reg = <0x10033000 0x100>;
+ reg-shift = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <48>;
+
+ clocks = <&ext>, <&cgu JZ4780_CLK_UART3>;
+ clock-names = "baud", "module";
+
+ status = "disabled";
+ };
+
+ uart4: ***@10034000 {
+ compatible = "ingenic,jz4780-uart";
+ reg = <0x10034000 0x100>;
+ reg-shift = <2>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <34>;
+
+ clocks = <&ext>, <&cgu JZ4780_CLK_UART4>;
+ clock-names = "baud", "module";
+
+ status = "disabled";
+ };
+
+ nemc: ***@13410000 {
+ compatible = "ingenic,jz4780-nemc";
+ reg = <0x13410000 0x10000>;
+ #address-cells = <2>;
+ #size-cells = <1>;
+ ranges = <1 0 0x1b000000 0x1000000
+ 2 0 0x1a000000 0x1000000
+ 3 0 0x19000000 0x1000000
+ 4 0 0x18000000 0x1000000
+ 5 0 0x17000000 0x1000000
+ 6 0 0x16000000 0x1000000>;
+
+ clocks = <&cgu JZ4780_CLK_NEMC>;
+
+ status = "disabled";
+ };
+
+ bch: ***@134d0000 {
+ compatible = "ingenic,jz4780-bch";
+ reg = <0x134d0000 0x10000>;
+
+ clocks = <&cgu JZ4780_CLK_BCH>;
+
+ status = "disabled";
+ };
+};
diff --git a/arch/mips/mach-jz47xx/Kconfig b/arch/mips/mach-jz47xx/Kconfig
new file mode 100644
index 000000000000..cd6944cfc252
--- /dev/null
+++ b/arch/mips/mach-jz47xx/Kconfig
@@ -0,0 +1,15 @@
+menu "Ingenic JZ47xx platforms"
+ depends on ARCH_JZ47XX
+
+config SYS_SOC
+ default "jz47xx"
+
+config SOC_JZ4780
+ bool
+ select SUPPORTS_LITTLE_ENDIAN
+ select SUPPORTS_CPU_MIPS32_R1
+ select SUPPORTS_CPU_MIPS32_R2
+ help
+ Support for Ingenic JZ4780 family SoCs.
+
+endmenu
diff --git a/arch/mips/mach-jz47xx/Makefile b/arch/mips/mach-jz47xx/Makefile
new file mode 100644
index 000000000000..5eee9acf559d
--- /dev/null
+++ b/arch/mips/mach-jz47xx/Makefile
@@ -0,0 +1,7 @@
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+extra-$(CONFIG_SPL_BUILD) := start.o
+
+obj-$(CONFIG_SOC_JZ4780) += jz4780/
diff --git a/arch/mips/mach-jz47xx/include/mach/jz4780.h b/arch/mips/mach-jz47xx/include/mach/jz4780.h
new file mode 100644
index 000000000000..86a6cc44d7c7
--- /dev/null
+++ b/arch/mips/mach-jz47xx/include/mach/jz4780.h
@@ -0,0 +1,104 @@
+/*
+ * JZ4780 definitions
+ *
+ * Copyright (c) 2013 Imagination Technologies
+ * Author: Paul Burton <***@imgtec.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef __JZ4780_H__
+#define __JZ4780_H__
+
+/* AHB0 BUS Devices */
+#define DDRC_BASE 0xb3010000
+
+/* AHB2 BUS Devices */
+#define NEMC_BASE 0xb3410000
+#define BCH_BASE 0xb34d0000
+
+/* APB BUS Devices */
+#define CPM_BASE 0xb0000000
+#define TCU_BASE 0xb0002000
+#define WDT_BASE 0xb0002000
+#define GPIO_BASE 0xb0010000
+#define UART0_BASE 0xb0030000
+#define UART1_BASE 0xb0031000
+#define UART2_BASE 0xb0032000
+#define UART3_BASE 0xb0033000
+#define MSC0_BASE 0xb3450000
+#define MSC1_BASE 0xb3460000
+#define MSC2_BASE 0xb3470000
+
+/*
+ * GPIO
+ */
+/* n = 0,1,2,3,4,5 */
+#define GPIO_PXPIN(n) (0x00 + (n) * 0x100)
+#define GPIO_PXINT(n) (0x10 + (n) * 0x100)
+#define GPIO_PXINTS(n) (0x14 + (n) * 0x100)
+#define GPIO_PXINTC(n) (0x18 + (n) * 0x100)
+#define GPIO_PXMASK(n) (0x20 + (n) * 0x100)
+#define GPIO_PXMASKS(n) (0x24 + (n) * 0x100)
+#define GPIO_PXMASKC(n) (0x28 + (n) * 0x100)
+#define GPIO_PXPAT1(n) (0x30 + (n) * 0x100)
+#define GPIO_PXPAT1S(n) (0x34 + (n) * 0x100)
+#define GPIO_PXPAT1C(n) (0x38 + (n) * 0x100)
+#define GPIO_PXPAT0(n) (0x40 + (n) * 0x100)
+#define GPIO_PXPAT0S(n) (0x44 + (n) * 0x100)
+#define GPIO_PXPAT0C(n) (0x48 + (n) * 0x100)
+#define GPIO_PXFLG(n) (0x50 + (n) * 0x100)
+#define GPIO_PXFLGC(n) (0x54 + (n) * 0x100)
+#define GPIO_PXOEN(n) (0x60 + (n) * 0x100)
+#define GPIO_PXOENS(n) (0x64 + (n) * 0x100)
+#define GPIO_PXOENC(n) (0x68 + (n) * 0x100)
+#define GPIO_PXPEN(n) (0x70 + (n) * 0x100)
+#define GPIO_PXPENS(n) (0x74 + (n) * 0x100)
+#define GPIO_PXPENC(n) (0x78 + (n) * 0x100)
+#define GPIO_PXDS(n) (0x80 + (n) * 0x100)
+#define GPIO_PXDSS(n) (0x84 + (n) * 0x100)
+#define GPIO_PXDSC(n) (0x88 + (n) * 0x100)
+
+/* PLL setup */
+#define JZ4780_SYS_EXTAL 48000000
+#define JZ4780_SYS_MEM_SPEED (CONFIG_SYS_MHZ * 1000000)
+#define JZ4780_SYS_MEM_DIV 3
+#define JZ4780_SYS_AUDIO_SPEED (768 * 1000000)
+
+#define JZ4780_APLL_M 1
+#define JZ4780_APLL_N 1
+#define JZ4780_APLL_OD 1
+
+#define JZ4780_MPLL_M (JZ4780_SYS_MEM_SPEED / JZ4780_SYS_EXTAL * 2)
+#define JZ4780_MPLL_N 2
+#define JZ4780_MPLL_OD 1
+
+#define JZ4780_EPLL_M (JZ4780_SYS_AUDIO_SPEED * 2 / JZ4780_SYS_EXTAL)
+#define JZ4780_EPLL_N 1
+#define JZ4780_EPLL_OD 2
+
+#define JZ4780_VPLL_M ((888 * 1000000) * 2 / JZ4780_SYS_EXTAL)
+#define JZ4780_VPLL_N 1
+#define JZ4780_VPLL_OD 2
+
+#ifndef __ASSEMBLY__
+
+u32 sdram_size(int bank);
+
+const u32 jz4780_clk_get_efuse_clk(void);
+void jz4780_clk_ungate_ethernet(void);
+void jz4780_clk_ungate_mmc(void);
+void jz4780_clk_ungate_uart(const unsigned int uart);
+
+void jz4780_efuse_read(size_t addr, size_t count, u8 *buf);
+void jz4780_efuse_init(u32 ahb2_rate);
+
+void jz4780_tcu_wdt_start(void);
+
+#ifdef CONFIG_SPL_BUILD
+int jz_mmc_init(void __iomem *base);
+#endif
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __JZ4780_H__ */
diff --git a/arch/mips/mach-jz47xx/include/mach/jz4780_dram.h b/arch/mips/mach-jz47xx/include/mach/jz4780_dram.h
new file mode 100644
index 000000000000..0bcc2157693e
--- /dev/null
+++ b/arch/mips/mach-jz47xx/include/mach/jz4780_dram.h
@@ -0,0 +1,457 @@
+/*
+ * JZ4780 DDR initialization - parameters definitions
+ *
+ * Copyright (c) 2015 Imagination Technologies
+ * Author: Matt Redfearn <matt.redfearn.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef __JZ4780_DRAM_H__
+#define __JZ4780_DRAM_H__
+
+/*
+ * DDR
+ */
+#define DDRC_ST 0x0
+#define DDRC_CFG 0x4
+#define DDRC_CTRL 0x8
+#define DDRC_LMR 0xc
+#define DDRC_REFCNT 0x18
+#define DDRC_DQS 0x1c
+#define DDRC_DQS_ADJ 0x20
+#define DDRC_MMAP0 0x24
+#define DDRC_MMAP1 0x28
+#define DDRC_MDELAY 0x2c
+#define DDRC_CKEL 0x30
+#define DDRC_PMEMCTRL0 0x54
+#define DDRC_PMEMCTRL1 0x50
+#define DDRC_PMEMCTRL2 0x58
+#define DDRC_PMEMCTRL3 0x5c
+
+#define DDRC_TIMING(n) (0x60 + 4 * (n))
+#define DDRC_REMMAP(n) (0x9c + 4 * (n))
+
+/*
+ * DDR PHY
+ */
+#define DDR_MEM_PHY_BASE 0x20000000
+#define DDR_PHY_OFFSET 0x1000
+
+#define DDRP_PIR 0x4
+#define DDRP_PGCR 0x8
+#define DDRP_PGSR 0xc
+
+#define DDRP_PTR0 0x18
+#define DDRP_PTR1 0x1c
+#define DDRP_PTR2 0x20
+
+#define DDRP_ACIOCR 0x24
+#define DDRP_DXCCR 0x28
+#define DDRP_DSGCR 0x2c
+#define DDRP_DCR 0x30
+
+#define DDRP_DTPR0 0x34
+#define DDRP_DTPR1 0x38
+#define DDRP_DTPR2 0x3c
+#define DDRP_MR0 0x40
+#define DDRP_MR1 0x44
+#define DDRP_MR2 0x48
+#define DDRP_MR3 0x4c
+
+#define DDRP_ODTCR 0x50
+#define DDRP_DTAR 0x54
+#define DDRP_DTDR0 0x58
+#define DDRP_DTDR1 0x5c
+
+#define DDRP_DCUAR 0xc0
+#define DDRP_DCUDR 0xc4
+#define DDRP_DCURR 0xc8
+#define DDRP_DCULR 0xcc
+#define DDRP_DCUGCR 0xd0
+#define DDRP_DCUTPR 0xd4
+#define DDRP_DCUSR0 0xd8
+#define DDRP_DCUSR1 0xdc
+
+#define DDRP_ZQXCR0(n) (0x180 + ((n) * 0x10))
+#define DDRP_ZQXCR1(n) (0x184 + ((n) * 0x10))
+#define DDRP_ZQXSR0(n) (0x188 + ((n) * 0x10))
+#define DDRP_ZQXSR1(n) (0x18c + ((n) * 0x10))
+
+#define DDRP_DXGCR(n) (0x1c0 + ((n) * 0x40))
+#define DDRP_DXGSR0(n) (0x1c4 + ((n) * 0x40))
+#define DDRP_DXGSR1(n) (0x1c8 + ((n) * 0x40))
+#define DDRP_DXDQSTR(n) (0x1d4 + ((n) * 0x40))
+
+/* DDRC Status Register */
+#define DDRC_ST_ENDIAN BIT(7)
+#define DDRC_ST_DPDN BIT(5)
+#define DDRC_ST_PDN BIT(4)
+#define DDRC_ST_AREF BIT(3)
+#define DDRC_ST_SREF BIT(2)
+#define DDRC_ST_CKE1 BIT(1)
+#define DDRC_ST_CKE0 BIT(0)
+
+/* DDRC Configure Register */
+#define DDRC_CFG_ROW1_BIT 27
+#define DDRC_CFG_ROW1_MASK (0x7 << DDRC_CFG_ROW1_BIT)
+#define DDRC_CFG_COL1_BIT 24
+#define DDRC_CFG_COL1_MASK (0x7 << DDRC_CFG_COL1_BIT)
+#define DDRC_CFG_BA1 BIT(23)
+#define DDRC_CFG_IMBA BIT(22)
+#define DDRC_CFG_BL_8 BIT(21)
+
+#define DDRC_CFG_TYPE_BIT 17
+#define DDRC_CFG_TYPE_MASK (0x7 << DDRC_CFG_TYPE_BIT)
+#define DDRC_CFG_TYPE_DDR1 (2 << DDRC_CFG_TYPE_BIT)
+#define DDRC_CFG_TYPE_MDDR (3 << DDRC_CFG_TYPE_BIT)
+#define DDRC_CFG_TYPE_DDR2 (4 << DDRC_CFG_TYPE_BIT)
+#define DDRC_CFG_TYPE_LPDDR2 (5 << DDRC_CFG_TYPE_BIT)
+#define DDRC_CFG_TYPE_DDR3 (6 << DDRC_CFG_TYPE_BIT)
+
+#define DDRC_CFG_ODT_EN BIT(16)
+
+#define DDRC_CFG_MPRT BIT(15)
+
+#define DDRC_CFG_ROW_BIT 11
+#define DDRC_CFG_ROW_MASK (0x7 << DDRC_CFG_ROW_BIT)
+#define DDRC_CFG_ROW_12 (0 << DDRC_CFG_ROW_BIT)
+#define DDRC_CFG_ROW_13 (1 << DDRC_CFG_ROW_BIT)
+#define DDRC_CFG_ROW_14 (2 << DDRC_CFG_ROW_BIT)
+
+#define DDRC_CFG_COL_BIT 8
+#define DDRC_CFG_COL_MASK (0x7 << DDRC_CFG_COL_BIT)
+#define DDRC_CFG_COL_8 (0 << DDRC_CFG_COL_BIT)
+#define DDRC_CFG_COL_9 (1 << DDRC_CFG_COL_BIT)
+#define DDRC_CFG_COL_10 (2 << DDRC_CFG_COL_BIT)
+#define DDRC_CFG_COL_11 (3 << DDRC_CFG_COL_BIT)
+
+#define DDRC_CFG_CS1EN BIT(7)
+#define DDRC_CFG_CS0EN BIT(6)
+#define DDRC_CFG_CL_BIT 2
+#define DDRC_CFG_CL_MASK (0xf << DDRC_CFG_CL_BIT)
+#define DDRC_CFG_CL_3 (0 << DDRC_CFG_CL_BIT)
+#define DDRC_CFG_CL_4 (1 << DDRC_CFG_CL_BIT)
+#define DDRC_CFG_CL_5 (2 << DDRC_CFG_CL_BIT)
+#define DDRC_CFG_CL_6 (3 << DDRC_CFG_CL_BIT)
+
+#define DDRC_CFG_BA BIT(1)
+#define DDRC_CFG_DW BIT(0)
+
+/* DDRC Control Register */
+#define DDRC_CTRL_DFI_RST BIT(23)
+#define DDRC_CTRL_DLL_RST BIT(22)
+#define DDRC_CTRL_CTL_RST BIT(21)
+#define DDRC_CTRL_CFG_RST BIT(20)
+#define DDRC_CTRL_ACTPD BIT(15)
+#define DDRC_CTRL_PDT_BIT 12
+#define DDRC_CTRL_PDT_MASK (0x7 << DDRC_CTRL_PDT_BIT)
+#define DDRC_CTRL_PDT_DIS (0 << DDRC_CTRL_PDT_BIT)
+#define DDRC_CTRL_PDT_8 (1 << DDRC_CTRL_PDT_BIT)
+#define DDRC_CTRL_PDT_16 (2 << DDRC_CTRL_PDT_BIT)
+#define DDRC_CTRL_PDT_32 (3 << DDRC_CTRL_PDT_BIT)
+#define DDRC_CTRL_PDT_64 (4 << DDRC_CTRL_PDT_BIT)
+#define DDRC_CTRL_PDT_128 (5 << DDRC_CTRL_PDT_BIT)
+
+#define DDRC_CTRL_PRET_BIT 8
+#define DDRC_CTRL_PRET_MASK (0x7 << DDRC_CTRL_PRET_BIT)
+#define DDRC_CTRL_PRET_DIS (0 << DDRC_CTRL_PRET_BIT)
+#define DDRC_CTRL_PRET_8 (1 << DDRC_CTRL_PRET_BIT)
+#define DDRC_CTRL_PRET_16 (2 << DDRC_CTRL_PRET_BIT)
+#define DDRC_CTRL_PRET_32 (3 << DDRC_CTRL_PRET_BIT)
+#define DDRC_CTRL_PRET_64 (4 << DDRC_CTRL_PRET_BIT)
+#define DDRC_CTRL_PRET_128 (5 << DDRC_CTRL_PRET_BIT)
+
+#define DDRC_CTRL_DPD BIT(6)
+#define DDRC_CTRL_SR BIT(5)
+#define DDRC_CTRL_UNALIGN BIT(4)
+#define DDRC_CTRL_ALH BIT(3)
+#define DDRC_CTRL_RDC BIT(2)
+#define DDRC_CTRL_CKE BIT(1)
+#define DDRC_CTRL_RESET BIT(0)
+
+/* DDRC Load-Mode-Register */
+#define DDRC_LMR_DDR_ADDR_BIT 16
+#define DDRC_LMR_DDR_ADDR_MASK (0x3fff << DDRC_LMR_DDR_ADDR_BIT)
+
+#define DDRC_LMR_BA_BIT 8
+#define DDRC_LMR_BA_MASK (0x7 << DDRC_LMR_BA_BIT)
+/* For DDR2 */
+#define DDRC_LMR_BA_MRS (0 << DDRC_LMR_BA_BIT)
+#define DDRC_LMR_BA_EMRS1 (1 << DDRC_LMR_BA_BIT)
+#define DDRC_LMR_BA_EMRS2 (2 << DDRC_LMR_BA_BIT)
+#define DDRC_LMR_BA_EMRS3 (3 << DDRC_LMR_BA_BIT)
+/* For mobile DDR */
+#define DDRC_LMR_BA_M_MRS (0 << DDRC_LMR_BA_BIT)
+#define DDRC_LMR_BA_M_EMRS (2 << DDRC_LMR_BA_BIT)
+#define DDRC_LMR_BA_M_SR (1 << DDRC_LMR_BA_BIT)
+/* For Normal DDR1 */
+#define DDRC_LMR_BA_N_MRS (0 << DDRC_LMR_BA_BIT)
+#define DDRC_LMR_BA_N_EMRS (1 << DDRC_LMR_BA_BIT)
+
+#define DDRC_LMR_CMD_BIT 4
+#define DDRC_LMR_CMD_MASK (0x3 << DDRC_LMR_CMD_BIT)
+#define DDRC_LMR_CMD_PREC (0 << DDRC_LMR_CMD_BIT)
+#define DDRC_LMR_CMD_AUREF (1 << DDRC_LMR_CMD_BIT)
+#define DDRC_LMR_CMD_LMR (2 << DDRC_LMR_CMD_BIT)
+
+#define DDRC_LMR_START BIT(0)
+
+/* DDRC Timing Config Register 1 */
+#define DDRC_TIMING1_TRTP_BIT 24
+#define DDRC_TIMING1_TRTP_MASK (0x3f << DDRC_TIMING1_TRTP_BIT)
+#define DDRC_TIMING1_TWTR_BIT 16
+#define DDRC_TIMING1_TWTR_MASK (0x3f << DDRC_TIMING1_TWTR_BIT)
+#define DDRC_TIMING1_TWTR_1 (0 << DDRC_TIMING1_TWTR_BIT)
+#define DDRC_TIMING1_TWTR_2 (1 << DDRC_TIMING1_TWTR_BIT)
+#define DDRC_TIMING1_TWTR_3 (2 << DDRC_TIMING1_TWTR_BIT)
+#define DDRC_TIMING1_TWTR_4 (3 << DDRC_TIMING1_TWTR_BIT)
+#define DDRC_TIMING1_TWR_BIT 8
+#define DDRC_TIMING1_TWR_MASK (0x3f << DDRC_TIMING1_TWR_BIT)
+#define DDRC_TIMING1_TWR_1 (0 << DDRC_TIMING1_TWR_BIT)
+#define DDRC_TIMING1_TWR_2 (1 << DDRC_TIMING1_TWR_BIT)
+#define DDRC_TIMING1_TWR_3 (2 << DDRC_TIMING1_TWR_BIT)
+#define DDRC_TIMING1_TWR_4 (3 << DDRC_TIMING1_TWR_BIT)
+#define DDRC_TIMING1_TWR_5 (4 << DDRC_TIMING1_TWR_BIT)
+#define DDRC_TIMING1_TWR_6 (5 << DDRC_TIMING1_TWR_BIT)
+#define DDRC_TIMING1_TWL_BIT 0
+#define DDRC_TIMING1_TWL_MASK (0x3f << DDRC_TIMING1_TWL_BIT)
+
+/* DDRC Timing Config Register 2 */
+#define DDRC_TIMING2_TCCD_BIT 24
+#define DDRC_TIMING2_TCCD_MASK (0x3f << DDRC_TIMING2_TCCD_BIT)
+#define DDRC_TIMING2_TRAS_BIT 16
+#define DDRC_TIMING2_TRAS_MASK (0x3f << DDRC_TIMING2_TRAS_BIT)
+#define DDRC_TIMING2_TRCD_BIT 8
+#define DDRC_TIMING2_TRCD_MASK (0x3f << DDRC_TIMING2_TRCD_BIT)
+#define DDRC_TIMING2_TRL_BIT 0
+#define DDRC_TIMING2_TRL_MASK (0x3f << DDRC_TIMING2_TRL_BIT)
+
+/* DDRC Timing Config Register 3 */
+#define DDRC_TIMING3_ONUM 27
+#define DDRC_TIMING3_TCKSRE_BIT 24
+#define DDRC_TIMING3_TCKSRE_MASK (0x3f << DDRC_TIMING3_TCKSRE_BIT)
+#define DDRC_TIMING3_TRP_BIT 16
+#define DDRC_TIMING3_TRP_MASK (0x3f << DDRC_TIMING3_TRP_BIT)
+#define DDRC_TIMING3_TRRD_BIT 8
+#define DDRC_TIMING3_TRRD_MASK (0x3f << DDRC_TIMING3_TRRD_BIT)
+#define DDRC_TIMING3_TRRD_DISABLE (0 << DDRC_TIMING3_TRRD_BIT)
+#define DDRC_TIMING3_TRRD_2 (1 << DDRC_TIMING3_TRRD_BIT)
+#define DDRC_TIMING3_TRRD_3 (2 << DDRC_TIMING3_TRRD_BIT)
+#define DDRC_TIMING3_TRRD_4 (3 << DDRC_TIMING3_TRRD_BIT)
+#define DDRC_TIMING3_TRC_BIT 0
+#define DDRC_TIMING3_TRC_MASK (0x3f << DDRC_TIMING3_TRC_BIT)
+
+/* DDRC Timing Config Register 4 */
+#define DDRC_TIMING4_TRFC_BIT 24
+#define DDRC_TIMING4_TRFC_MASK (0x3f << DDRC_TIMING4_TRFC_BIT)
+#define DDRC_TIMING4_TEXTRW_BIT 21
+#define DDRC_TIMING4_TEXTRW_MASK (0x7 << DDRC_TIMING4_TEXTRW_BIT)
+#define DDRC_TIMING4_TRWCOV_BIT 19
+#define DDRC_TIMING4_TRWCOV_MASK (0x3 << DDRC_TIMING4_TRWCOV_BIT)
+#define DDRC_TIMING4_TCKE_BIT 16
+#define DDRC_TIMING4_TCKE_MASK (0x7 << DDRC_TIMING4_TCKE_BIT)
+#define DDRC_TIMING4_TMINSR_BIT 8
+#define DDRC_TIMING4_TMINSR_MASK (0xf << DDRC_TIMING4_TMINSR_BIT)
+#define DDRC_TIMING4_TXP_BIT 4
+#define DDRC_TIMING4_TXP_MASK (0x7 << DDRC_TIMING4_TXP_BIT)
+#define DDRC_TIMING4_TMRD_BIT 0
+#define DDRC_TIMING4_TMRD_MASK (0x3 << DDRC_TIMING4_TMRD_BIT)
+
+/* DDRC Timing Config Register 5 */
+#define DDRC_TIMING5_TCTLUPD_BIT 24
+#define DDRC_TIMING4_TCTLUPD_MASK (0x3f << DDRC_TIMING5_TCTLUDP_BIT)
+#define DDRC_TIMING5_TRTW_BIT 16
+#define DDRC_TIMING5_TRTW_MASK (0x3f << DDRC_TIMING5_TRTW_BIT)
+#define DDRC_TIMING5_TRDLAT_BIT 8
+#define DDRC_TIMING5_TRDLAT_MASK (0x3f << DDRC_TIMING5_TRDLAT_BIT)
+#define DDRC_TIMING5_TWDLAT_BIT 0
+#define DDRC_TIMING5_TWDLAT_MASK (0x3f << DDRC_TIMING5_TWDLAT_BIT)
+
+/* DDRC Timing Config Register 6 */
+#define DDRC_TIMING6_TXSRD_BIT 24
+#define DDRC_TIMING6_TXSRD_MASK (0x3f << DDRC_TIMING6_TXSRD_BIT)
+#define DDRC_TIMING6_TFAW_BIT 16
+#define DDRC_TIMING6_TFAW_MASK (0x3f << DDRC_TIMING6_TFAW_BIT)
+#define DDRC_TIMING6_TCFGW_BIT 8
+#define DDRC_TIMING6_TCFGW_MASK (0x3f << DDRC_TIMING6_TCFGW_BIT)
+#define DDRC_TIMING6_TCFGR_BIT 0
+#define DDRC_TIMING6_TCFGR_MASK (0x3f << DDRC_TIMING6_TCFGR_BIT)
+
+/* DDRC Auto-Refresh Counter */
+#define DDRC_REFCNT_CON_BIT 16
+#define DDRC_REFCNT_CON_MASK (0xff << DDRC_REFCNT_CON_BIT)
+#define DDRC_REFCNT_CNT_BIT 8
+#define DDRC_REFCNT_CNT_MASK (0xff << DDRC_REFCNT_CNT_BIT)
+#define DDRC_REFCNT_CLKDIV_BIT 1
+#define DDRC_REFCNT_CLKDIV_MASK (0x7 << DDRC_REFCNT_CLKDIV_BIT)
+#define DDRC_REFCNT_REF_EN BIT(0)
+
+/* DDRC DQS Delay Control Register */
+#define DDRC_DQS_ERROR BIT(29)
+#define DDRC_DQS_READY BIT(28)
+#define DDRC_DQS_AUTO BIT(23)
+#define DDRC_DQS_DET BIT(24)
+#define DDRC_DQS_SRDET BIT(25)
+#define DDRC_DQS_CLKD_BIT 16
+#define DDRC_DQS_CLKD_MASK (0x3f << DDRC_DQS_CLKD_BIT)
+#define DDRC_DQS_WDQS_BIT 8
+#define DDRC_DQS_WDQS_MASK (0x3f << DDRC_DQS_WDQS_BIT)
+#define DDRC_DQS_RDQS_BIT 0
+#define DDRC_DQS_RDQS_MASK (0x3f << DDRC_DQS_RDQS_BIT)
+
+/* DDRC DQS Delay Adjust Register */
+#define DDRC_DQS_ADJWDQS_BIT 8
+#define DDRC_DQS_ADJWDQS_MASK (0x1f << DDRC_DQS_ADJWDQS_BIT)
+#define DDRC_DQS_ADJRDQS_BIT 0
+#define DDRC_DQS_ADJRDQS_MASK (0x1f << DDRC_DQS_ADJRDQS_BIT)
+
+/* DDRC Memory Map Config Register */
+#define DDRC_MMAP_BASE_BIT 8
+#define DDRC_MMAP_BASE_MASK (0xff << DDRC_MMAP_BASE_BIT)
+#define DDRC_MMAP_MASK_BIT 0
+#define DDRC_MMAP_MASK_MASK (0xff << DDRC_MMAP_MASK_BIT)
+
+#define DDRC_MMAP0_BASE (0x20 << DDRC_MMAP_BASE_BIT)
+#define DDRC_MMAP1_BASE_64M (0x24 << DDRC_MMAP_BASE_BIT)
+#define DDRC_MMAP1_BASE_128M (0x28 << DDRC_MMAP_BASE_BIT)
+#define DDRC_MMAP1_BASE_256M (0x30 << DDRC_MMAP_BASE_BIT)
+
+#define DDRC_MMAP_MASK_64_64 (0xfc << DDRC_MMAP_MASK_BIT)
+#define DDRC_MMAP_MASK_128_128 (0xf8 << DDRC_MMAP_MASK_BIT)
+#define DDRC_MMAP_MASK_256_256 (0xf0 << DDRC_MMAP_MASK_BIT)
+
+/* DDRP PHY Initialization Register */
+#define DDRP_PIR_INIT BIT(0)
+#define DDRP_PIR_DLLSRST BIT(1)
+#define DDRP_PIR_DLLLOCK BIT(2)
+#define DDRP_PIR_ZCAL BIT(3)
+#define DDRP_PIR_ITMSRST BIT(4)
+#define DDRP_PIR_DRAMRST BIT(5)
+#define DDRP_PIR_DRAMINT BIT(6)
+#define DDRP_PIR_QSTRN BIT(7)
+#define DDRP_PIR_EYETRN BIT(8)
+#define DDRP_PIR_DLLBYP BIT(17)
+/* DDRP PHY General Configurate Register */
+#define DDRP_PGCR_ITMDMD BIT(0)
+#define DDRP_PGCR_DQSCFG BIT(1)
+#define DDRP_PGCR_DFTCMP BIT(2)
+#define DDRP_PGCR_DFTLMT_BIT 3
+#define DDRP_PGCR_DTOSEL_BIT 5
+#define DDRP_PGCR_CKEN_BIT 9
+#define DDRP_PGCR_CKDV_BIT 12
+#define DDRP_PGCR_CKINV BIT(14)
+#define DDRP_PGCR_RANKEN_BIT 18
+#define DDRP_PGCR_ZCKSEL_32 (2 << 22)
+#define DDRP_PGCR_PDDISDX BIT(24)
+/* DDRP PHY General Status Register */
+#define DDRP_PGSR_IDONE BIT(0)
+#define DDRP_PGSR_DLDONE BIT(1)
+#define DDRP_PGSR_ZCDONE BIT(2)
+#define DDRP_PGSR_DIDONE BIT(3)
+#define DDRP_PGSR_DTDONE BIT(4)
+#define DDRP_PGSR_DTERR BIT(5)
+#define DDRP_PGSR_DTIERR BIT(6)
+#define DDRP_PGSR_DFTEERR BIT(7)
+/* DDRP DRAM Configuration Register */
+#define DDRP_DCR_TYPE_BIT 0
+#define DDRP_DCR_TYPE_MASK (0x7 << DDRP_DCR_TYPE_BIT)
+#define DDRP_DCR_TYPE_MDDR (0 << DDRP_DCR_TYPE_BIT)
+#define DDRP_DCR_TYPE_DDR (1 << DDRP_DCR_TYPE_BIT)
+#define DDRP_DCR_TYPE_DDR2 (2 << DDRP_DCR_TYPE_BIT)
+#define DDRP_DCR_TYPE_DDR3 (3 << DDRP_DCR_TYPE_BIT)
+#define DDRP_DCR_TYPE_LPDDR2 (4 << DDRP_DCR_TYPE_BIT)
+#define DDRP_DCR_DDR8BNK_BIT 3
+#define DDRP_DCR_DDR8BNK_MASK (1 << DDRP_DCR_DDR8BNK_BIT)
+#define DDRP_DCR_DDR8BNK (1 << DDRP_DCR_DDR8BNK_BIT)
+#define DDRP_DCR_DDR8BNK_DIS (0 << DDRP_DCR_DDR8BNK_BIT)
+
+#define DRP_DTRP1_RTODT BIT(11)
+
+#define DDRP_DXGCR_DXEN BIT(0)
+
+#define DDRP_ZQXCR_ZDEN_BIT 28
+#define DDRP_ZQXCR_ZDEN (1 << DDRP_ZQXCR_ZDEN_BIT)
+#define DDRP_ZQXCR_PULLUP_IMPE_BIT 5
+#define DDRP_ZQXCR_PULLDOWN_IMPE_BIT 0
+
+/* DDR3 Mode Register Set */
+#define DDR3_MR0_BL_BIT 0
+#define DDR3_MR0_BL_MASK (3 << DDR3_MR0_BL_BIT)
+#define DDR3_MR0_BL_8 (0 << DDR3_MR0_BL_BIT)
+#define DDR3_MR0_BL_fly (1 << DDR3_MR0_BL_BIT)
+#define DDR3_MR0_BL_4 (2 << DDR3_MR0_BL_BIT)
+#define DDR3_MR0_BT_BIT 3
+#define DDR3_MR0_BT_MASK (1 << DDR3_MR0_BT_BIT)
+#define DDR3_MR0_BT_SEQ (0 << DDR3_MR0_BT_BIT)
+#define DDR3_MR0_BT_INTER (1 << DDR3_MR0_BT_BIT)
+#define DDR3_MR0_WR_BIT 9
+
+#define DDR3_MR1_DLL_DISABLE 1
+#define DDR3_MR1_DIC_6 (0 << 5 | 0 << 1)
+#define DDR3_MR1_DIC_7 (0 << 5 | BIT(1))
+#define DDR3_MR1_RTT_DIS (0 << 9 | 0 << 6 | 0 << 2)
+#define DDR3_MR1_RTT_4 (0 << 9 | 0 << 6 | BIT(2))
+#define DDR3_MR1_RTT_2 (0 << 9 | BIT(6) | 0 << 2)
+#define DDR3_MR1_RTT_6 (0 << 9 | BIT(6) | BIT(2))
+#define DDR3_MR1_RTT_12 (BIT(9) | 0 << 6 | 0 << 2)
+#define DDR3_MR1_RTT_8 (BIT(9) | 0 << 6 | BIT(2))
+
+#define DDR3_MR2_CWL_BIT 3
+
+/* Paramters common to all RAM devices used */
+
+/* Chip Select */
+/* CSEN : whether a ddr chip exists 0 - un-used, 1 - used */
+#define DDR_CS0EN 1
+/* CSEN : whether a ddr chip exists 0 - un-used, 1 - used */
+#define DDR_CS1EN 0
+
+/* ROW : 12 to 18 row address, 1G only 512MB */
+#define DDR_ROW 15
+/* COL : 8 to 14 column address */
+#define DDR_COL 10
+/* Banks each chip: 0-4bank, 1-8bank */
+#define DDR_BANK8 1
+/* 0 - 16-bit data width, 1 - 32-bit data width */
+#define DDR_DW32 1
+
+/* Refresh period: 64ms / 32768 = 1.95 us , 2 ^ 15 = 32768 */
+#define DDR_tREFI 7800
+/* Clock Divider */
+#define DDR_CLK_DIV 1
+
+/* DDR3 Burst length: 0 - 8 burst, 2 - 4 burst , 1 - 4 or 8 (on the fly) */
+#define DDR_BL 8
+
+/* CAS latency: 5 to 14, tCK */
+#define DDR_CL 6
+/* DDR3 only: CAS Write Latency, 5 to 8 */
+#define DDR_tCWL (DDR_CL - 1)
+
+/* Structure representing per-RAM type configuration */
+
+struct jz4780_ddr_config {
+ u32 timing[6]; /* Timing1..6 register value */
+
+ /* DDR PHY control */
+ u16 mr0; /* Mode Register 0 */
+ u16 mr1; /* Mode Register 1 */
+
+ u32 ptr0; /* PHY Timing Register 0 */
+ u32 ptr1; /* PHY Timing Register 1 */
+ u32 ptr2; /* PHY Timing Register 1 */
+
+ u32 dtpr0; /* DRAM Timing Parameters Register 0 */
+ u32 dtpr1; /* DRAM Timing Parameters Register 1 */
+ u32 dtpr2; /* DRAM Timing Parameters Register 2 */
+
+ u8 pullup; /* PHY pullup impedance */
+ u8 pulldn; /* PHY pulldown impedance */
+};
+
+void pll_init(void);
+void sdram_init(void);
+
+#endif /* __JZ4780_DRAM_H__ */
+
diff --git a/arch/mips/mach-jz47xx/jz4780/Makefile b/arch/mips/mach-jz47xx/jz4780/Makefile
new file mode 100644
index 000000000000..683eea65c2f1
--- /dev/null
+++ b/arch/mips/mach-jz47xx/jz4780/Makefile
@@ -0,0 +1,5 @@
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-y := jz4780.o pll.o sdram.o timer.o
diff --git a/arch/mips/mach-jz47xx/jz4780/jz4780.c b/arch/mips/mach-jz47xx/jz4780/jz4780.c
new file mode 100644
index 000000000000..bbc4eaa53bbb
--- /dev/null
+++ b/arch/mips/mach-jz47xx/jz4780/jz4780.c
@@ -0,0 +1,142 @@
+/*
+ * JZ4780 common routines
+ *
+ * Copyright (c) 2013 Imagination Technologies
+ * Author: Paul Burton <***@imgtec.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <config.h>
+#include <common.h>
+#include <asm/io.h>
+#include <mach/jz4780.h>
+#include <mach/jz4780_dram.h>
+#include <mmc.h>
+#include <spl.h>
+
+#ifdef CONFIG_SPL_BUILD
+/* Pointer to the global data structure for SPL */
+DECLARE_GLOBAL_DATA_PTR;
+gd_t gdata __attribute__ ((section(".bss")));
+
+void board_init_f(ulong dummy)
+{
+ typedef void __noreturn (*image_entry_noargs_t)(void);
+ struct mmc *mmc;
+ unsigned long count;
+ struct image_header *header;
+ int ret;
+
+ /* Set global data pointer */
+ gd = &gdata;
+
+ timer_init();
+ pll_init();
+ sdram_init();
+ enable_caches();
+
+ /* Clear the BSS */
+ memset(__bss_start, 0, (char *)&__bss_end - __bss_start);
+
+ gd->flags |= GD_FLG_SPL_INIT;
+
+ ret = mmc_initialize(NULL);
+ if (ret)
+ hang();
+
+ mmc = find_mmc_device(BOOT_DEVICE_MMC1);
+ if (ret)
+ hang();
+
+ ret = mmc_init(mmc);
+ if (ret)
+ hang();
+
+ header = (struct image_header *)(CONFIG_SYS_TEXT_BASE -
+ sizeof(struct image_header));
+
+ count = blk_dread(mmc_get_blk_desc(mmc),
+ CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR,
+ 0x800, header);
+ if (count == 0)
+ hang();
+
+ image_entry_noargs_t image_entry =
+ (image_entry_noargs_t)CONFIG_SYS_TEXT_BASE;
+
+ image_entry();
+
+ hang();
+}
+#endif /* CONFIG_SPL_BUILD */
+
+ulong board_get_usable_ram_top(ulong total_size)
+{
+ return CONFIG_SYS_SDRAM_BASE + (256 * 1024 * 1024);
+}
+
+int print_cpuinfo(void)
+{
+ printf("CPU: Ingenic JZ4780\n");
+ return 0;
+}
+
+/* WDT */
+#define WDT_TDR 0x00
+#define WDT_TCER 0x04
+#define WDT_TCNT 0x08
+#define WDT_TCSR 0x0C
+
+/* Register definition */
+#define WDT_TCSR_PRESCALE_BIT 3
+#define WDT_TCSR_PRESCALE_MASK (0x7 << WDT_TCSR_PRESCALE_BIT)
+ #define WDT_TCSR_PRESCALE1 (0x0 << WDT_TCSR_PRESCALE_BIT)
+ #define WDT_TCSR_PRESCALE4 (0x1 << WDT_TCSR_PRESCALE_BIT)
+ #define WDT_TCSR_PRESCALE16 (0x2 << WDT_TCSR_PRESCALE_BIT)
+ #define WDT_TCSR_PRESCALE64 (0x3 << WDT_TCSR_PRESCALE_BIT)
+ #define WDT_TCSR_PRESCALE256 (0x4 << WDT_TCSR_PRESCALE_BIT)
+ #define WDT_TCSR_PRESCALE1024 (0x5 << WDT_TCSR_PRESCALE_BIT)
+#define WDT_TCSR_EXT_EN BIT(2)
+#define WDT_TCSR_RTC_EN BIT(1)
+#define WDT_TCSR_PCK_EN BIT(0)
+
+#define WDT_TCER_TCEN BIT(0)
+
+void _machine_restart(void)
+{
+ void __iomem *wdt_regs = (void __iomem *)WDT_BASE;
+
+ mdelay(100);
+
+ /*
+ * Select the EXTAL as the timer clock input, and make each
+ * WDT clock tick equal 4 ticks of the system clock.
+ */
+ writew(WDT_TCSR_PRESCALE4 | WDT_TCSR_EXT_EN, wdt_regs + WDT_TCSR);
+
+ /* Reset the WDT counter to zero. */
+ writew(0, wdt_regs + WDT_TCNT);
+
+ /*
+ * Reset after 4ms
+ *
+ * 1 sec CONFIG_SYS_EXTAL ticks
+ * 4ms * ------- * ---------------------- = Number of WDT clock ticks
+ * 1000 ms 1 sec
+ *
+ * As noted above the number of system clock ticks have been
+ * effectively multiplied by 4. All that's left here for the
+ * computation of WDT clock ticks is to divide by 1000
+ * (one thousand).
+ */
+ writew(JZ4780_SYS_EXTAL / 1000, wdt_regs + WDT_TDR);
+
+ jz4780_tcu_wdt_start();
+
+ /* WDT start */
+ writeb(WDT_TCER_TCEN, wdt_regs + WDT_TCER);
+
+ for (;;)
+ ;
+}
diff --git a/arch/mips/mach-jz47xx/jz4780/pll.c b/arch/mips/mach-jz47xx/jz4780/pll.c
new file mode 100644
index 000000000000..52071f8538cb
--- /dev/null
+++ b/arch/mips/mach-jz47xx/jz4780/pll.c
@@ -0,0 +1,528 @@
+/*
+ * JZ4780 PLL setup
+ *
+ * Copyright (c) 2013 Imagination Technologies
+ * Author: Paul Burton <***@imgtec.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <config.h>
+#include <common.h>
+#include <asm/io.h>
+#include <mach/jz4780.h>
+
+#define CPM_CPCCR 0x00
+#define CPM_LCR 0x04
+#define CPM_RSR 0x08
+#define CPM_CPPCR 0x0c
+#define CPM_CPAPCR 0x10
+#define CPM_CPMPCR 0x14
+#define CPM_CPEPCR 0x18
+#define CPM_CPVPCR 0x1c
+#define CPM_CLKGR0 0x20
+#define CPM_OPCR 0x24
+#define CPM_CLKGR1 0x28
+#define CPM_DDCDR 0x2c
+#define CPM_VPUCDR 0x30
+#define CPM_CPSPR 0x34
+#define CPM_CPSPPR 0x38
+#define CPM_USBPCR 0x3c
+#define CPM_USBRDT 0x40
+#define CPM_USBVBFIL 0x44
+#define CPM_USBPCR1 0x48
+#define CPM_USBCDR 0x50
+#define CPM_LPCDR 0x54
+#define CPM_I2SCDR 0x60
+#define CPM_LPCDR1 0x64
+#define CPM_MSCCDR 0x68
+#define CPM_UHCCDR 0x6c
+#define CPM_SSICDR 0x74
+#define CPM_CIMCDR 0x7c
+#define CPM_PCMCDR 0x84
+#define CPM_GPUCDR 0x88
+#define CPM_HDMICDR 0x8c
+#define CPM_I2S1CDR 0xa0
+#define CPM_MSCCDR1 0xa4
+#define CPM_MSCCDR2 0xa8
+#define CPM_BCHCDR 0xac
+#define CPM_SPCR0 0xb8
+#define CPM_SPCR1 0xbc
+#define CPM_CPCSR 0xd4
+#define CPM_PSWCST(n) ((0x4 * (n)) + 0x90)
+
+/* Clock control register */
+#define CPM_CPCCR_SEL_SRC_BIT 30
+#define CPM_CPCCR_SEL_SRC_MASK (0x3 << CPM_CPCCR_SEL_SRC_BIT)
+#define CPM_SRC_SEL_STOP 0
+#define CPM_SRC_SEL_APLL 1
+#define CPM_SRC_SEL_EXCLK 2
+#define CPM_SRC_SEL_RTCLK 3
+#define CPM_CPCCR_SEL_CPLL_BIT 28
+#define CPM_CPCCR_SEL_CPLL_MASK (0x3 << CPM_CPCCR_SEL_CPLL_BIT)
+#define CPM_CPCCR_SEL_H0PLL_BIT 26
+#define CPM_CPCCR_SEL_H0PLL_MASK (0x3 << CPM_CPCCR_SEL_H0PLL_BIT)
+#define CPM_CPCCR_SEL_H2PLL_BIT 24
+#define CPM_CPCCR_SEL_H2PLL_MASK (0x3 << CPM_CPCCR_SEL_H2PLL_BIT)
+#define CPM_PLL_SEL_STOP 0
+#define CPM_PLL_SEL_SRC 1
+#define CPM_PLL_SEL_MPLL 2
+#define CPM_PLL_SEL_EPLL 3
+#define CPM_CPCCR_CE_CPU (0x1 << 22)
+#define CPM_CPCCR_CE_AHB0 (0x1 << 21)
+#define CPM_CPCCR_CE_AHB2 (0x1 << 20)
+#define CPM_CPCCR_PDIV_BIT 16
+#define CPM_CPCCR_PDIV_MASK (0xf << CPM_CPCCR_PDIV_BIT)
+#define CPM_CPCCR_H2DIV_BIT 12
+#define CPM_CPCCR_H2DIV_MASK (0xf << CPM_CPCCR_H2DIV_BIT)
+#define CPM_CPCCR_H0DIV_BIT 8
+#define CPM_CPCCR_H0DIV_MASK (0x0f << CPM_CPCCR_H0DIV_BIT)
+#define CPM_CPCCR_L2DIV_BIT 4
+#define CPM_CPCCR_L2DIV_MASK (0x0f << CPM_CPCCR_L2DIV_BIT)
+#define CPM_CPCCR_CDIV_BIT 0
+#define CPM_CPCCR_CDIV_MASK (0x0f << CPM_CPCCR_CDIV_BIT)
+
+/* Clock Status register */
+#define CPM_CPCSR_H2DIV_BUSY BIT(2)
+#define CPM_CPCSR_H0DIV_BUSY BIT(1)
+#define CPM_CPCSR_CDIV_BUSY BIT(0)
+
+/* PLL control register */
+#define CPM_CPPCR_PLLST_BIT 0
+#define CPM_CPPCR_PLLST_MASK (0xff << CPM_CPPCR_PLLST_BIT)
+
+/* XPLL control register */
+#define CPM_CPXPCR_XPLLM_BIT 19
+#define CPM_CPXPCR_XPLLM_MASK (0x1fff << CPM_CPXPCR_XPLLM_BIT)
+#define CPM_CPXPCR_XPLLN_BIT 13
+#define CPM_CPXPCR_XPLLN_MASK (0x3f << CPM_CPXPCR_XPLLN_BIT)
+#define CPM_CPXPCR_XPLLOD_BIT 9
+#define CPM_CPXPCR_XPLLOD_MASK (0xf << CPM_CPXPCR_XPLLOD_BIT)
+#define CPM_CPXPCR_XLOCK BIT(6)
+#define CPM_CPXPCR_XPLL_ON BIT(4)
+#define CPM_CPXPCR_XF_MODE BIT(3)
+#define CPM_CPXPCR_XPLLBP BIT(1)
+#define CPM_CPXPCR_XPLLEN BIT(0)
+
+/* CPM scratch protected register */
+#define CPM_CPSPPR_BIT 0
+#define CPM_CPSPPR_MASK (0xffff << CPM_CPSPPR_BIT)
+
+/* USB parameter control register */
+#define CPM_USBPCR_USB_MODE BIT(31) /* 1: OTG, 0: UDC*/
+#define CPM_USBPCR_AVLD_REG BIT(30)
+#define CPM_USBPCR_IDPULLUP_MASK_BIT 28
+#define CPM_USBPCR_IDPULLUP_MASK_MASK (0x02 << IDPULLUP_MASK_BIT)
+#define CPM_USBPCR_INCR_MASK BIT(27)
+#define CPM_USBPCR_CLK12_EN BIT(26)
+#define CPM_USBPCR_COMMONONN BIT(25)
+#define CPM_USBPCR_VBUSVLDEXT BIT(24)
+#define CPM_USBPCR_VBUSVLDEXTSEL BIT(23)
+#define CPM_USBPCR_POR BIT(22)
+#define CPM_USBPCR_SIDDQ BIT(21)
+#define CPM_USBPCR_OTG_DISABLE BIT(20)
+#define CPM_USBPCR_COMPDISTUNE_BIT 17
+#define CPM_USBPCR_COMPDISTUNE_MASK (0x07 << COMPDISTUNE_BIT)
+#define CPM_USBPCR_OTGTUNE_BIT 14
+#define CPM_USBPCR_OTGTUNE_MASK (0x07 << OTGTUNE_BIT)
+#define CPM_USBPCR_SQRXTUNE_BIT 11
+#define CPM_USBPCR_SQRXTUNE_MASK (0x7x << SQRXTUNE_BIT)
+#define CPM_USBPCR_TXFSLSTUNE_BIT 7
+#define CPM_USBPCR_TXFSLSTUNE_MASK (0x0f << TXFSLSTUNE_BIT)
+#define CPM_USBPCR_TXPREEMPHTUNE BIT(6)
+#define CPM_USBPCR_TXRISETUNE_BIT 4
+#define CPM_USBPCR_TXRISETUNE_MASK (0x03 << TXRISETUNE_BIT)
+#define CPM_USBPCR_TXVREFTUNE_BIT 0
+#define CPM_USBPCR_TXVREFTUNE_MASK (0x0f << TXVREFTUNE_BIT)
+
+/* DDR memory clock divider register */
+#define CPM_DDRCDR_DCS_BIT 30
+#define CPM_DDRCDR_DCS_MASK (0x3 << CPM_DDRCDR_DCS_BIT)
+#define CPM_DDRCDR_DCS_STOP (0x0 << CPM_DDRCDR_DCS_BIT)
+#define CPM_DDRCDR_DCS_SRC (0x1 << CPM_DDRCDR_DCS_BIT)
+#define CPM_DDRCDR_DCS_MPLL (0x2 << CPM_DDRCDR_DCS_BIT)
+#define CPM_DDRCDR_CE_DDR BIT(29)
+#define CPM_DDRCDR_DDR_BUSY BIT(28)
+#define CPM_DDRCDR_DDR_STOP BIT(27)
+#define CPM_DDRCDR_DDRDIV_BIT 0
+#define CPM_DDRCDR_DDRDIV_MASK (0xf << CPM_DDRCDR_DDRDIV_BIT)
+
+/* USB reset detect timer register */
+#define CPM_USBRDT_VBFIL_LD_EN BIT(25)
+#define CPM_USBRDT_IDDIG_EN BIT(24)
+#define CPM_USBRDT_IDDIG_REG BIT(23)
+#define CPM_USBRDT_USBRDT_BIT 0
+#define CPM_USBRDT_USBRDT_MASK (0x7fffff << CPM_USBRDT_USBRDT_BIT)
+
+/* USB OTG PHY clock divider register */
+#define CPM_USBCDR_UCS BIT(31)
+#define CPM_USBCDR_UPCS BIT(30)
+#define CPM_USBCDR_CEUSB BIT(29)
+#define CPM_USBCDR_USB_BUSY BIT(28)
+#define CPM_USBCDR_OTGDIV_BIT 0
+#define CPM_USBCDR_OTGDIV_MASK (0xff << CPM_USBCDR_OTGDIV_BIT)
+
+/* I2S device clock divider register */
+#define CPM_I2SCDR_I2CS BIT(31)
+#define CPM_I2SCDR_I2PCS BIT(30)
+#define CPM_I2SCDR_I2SDIV_BIT 0
+#define CPM_I2SCDR_I2SDIV_MASK (0x1ff << CPM_I2SCDR_I2SDIV_BIT)
+
+/* LCD0 pix clock divider register */
+#define CPM_LPCDR_LPCS_BIT 30
+#define CPM_LPCDR_LPCS_MASK (0x3 << CPM_LPCDR_LPCS_BIT)
+#define CPM_LPCDR_CELCD BIT(28)
+#define CPM_LPCDR_LCD_BUSY BIT(27)
+#define CPM_LPCDR_LCD_STOP BIT(26)
+#define CPM_LPCDR_PIXDIV_BIT 0
+#define CPM_LPCDR_PIXDIV_MASK (0xff << CPM_LPCDR_PIXDIV_BIT)
+
+/* MSC clock divider register */
+#define CPM_MSCCDR_MPCS_BIT 30
+#define CPM_MSCCDR_MPCS_MASK (3 << CPM_MSCCDR_MPCS_BIT)
+#define CPM_MSCCDR_MPCS_STOP (0x0 << CPM_MSCCDR_MPCS_BIT)
+#define CPM_MSCCDR_MPCS_SRC (0x1 << CPM_MSCCDR_MPCS_BIT)
+#define CPM_MSCCDR_MPCS_MPLL (0x2 << CPM_MSCCDR_MPCS_BIT)
+#define CPM_MSCCDR_CE BIT(29)
+#define CPM_MSCCDR_MSC_BUSY BIT(28)
+#define CPM_MSCCDR_MSC_STOP BIT(27)
+#define CPM_MSCCDR_MSC_CLK0_SEL BIT(15)
+#define CPM_MSCCDR_MSCDIV_BIT 0
+#define CPM_MSCCDR_MSCDIV_MASK (0xff << CPM_MSCCDR_MSCDIV_BIT)
+
+/* UHC 48M clock divider register */
+#define CPM_UHCCDR_UHCS_BIT 30
+#define CPM_UHCCDR_UHCS_MASK (0x3 << CPM_UHCCDR_UHCS_BIT)
+#define CPM_UHCCDR_UHCS_SRC (0x0 << CPM_UHCCDR_UHCS_BIT)
+#define CPM_UHCCDR_UHCS_MPLL (0x1 << CPM_UHCCDR_UHCS_BIT)
+#define CPM_UHCCDR_UHCS_EPLL (0x2 << CPM_UHCCDR_UHCS_BIT)
+#define CPM_UHCCDR_UHCS_OTG (0x3 << CPM_UHCCDR_UHCS_BIT)
+#define CPM_UHCCDR_CE_UHC BIT(29)
+#define CPM_UHCCDR_UHC_BUSY BIT(28)
+#define CPM_UHCCDR_UHC_STOP BIT(27)
+#define CPM_UHCCDR_UHCDIV_BIT 0
+#define CPM_UHCCDR_UHCDIV_MASK (0xff << CPM_UHCCDR_UHCDIV_BIT)
+
+/* SSI clock divider register */
+#define CPM_SSICDR_SCS BIT(31)
+#define CPM_SSICDR_SSIDIV_BIT 0
+#define CPM_SSICDR_SSIDIV_MASK (0x3f << CPM_SSICDR_SSIDIV_BIT)
+
+/* CIM MCLK clock divider register */
+#define CPM_CIMCDR_CIMDIV_BIT 0
+#define CPM_CIMCDR_CIMDIV_MASK (0xff << CPM_CIMCDR_CIMDIV_BIT)
+
+/* GPS clock divider register */
+#define CPM_GPSCDR_GPCS BIT(31)
+#define CPM_GPSCDR_GPSDIV_BIT 0
+#define CPM_GSPCDR_GPSDIV_MASK (0xf << CPM_GPSCDR_GPSDIV_BIT)
+
+/* PCM device clock divider register */
+#define CPM_PCMCDR_PCMS BIT(31)
+#define CPM_PCMCDR_PCMPCS BIT(30)
+#define CPM_PCMCDR_PCMDIV_BIT 0
+#define CPM_PCMCDR_PCMDIV_MASK (0x1ff << CPM_PCMCDR_PCMDIV_BIT)
+
+/* GPU clock divider register */
+#define CPM_GPUCDR_GPCS BIT(31)
+#define CPM_GPUCDR_GPUDIV_BIT 0
+#define CPM_GPUCDR_GPUDIV_MASK (0x7 << CPM_GPUCDR_GPUDIV_BIT)
+
+/* HDMI clock divider register */
+#define CPM_HDMICDR_HPCS_BIT 30
+#define CPM_HDMICDR_HPCS_MASK (0x3 << CPM_HDMICDR_HPCS_BIT)
+#define CPM_HDMICDR_CEHDMI BIT(29)
+#define CPM_HDMICDR_HDMI_BUSY BIT(28)
+#define CPM_HDMICDR_HDMI_STOP BIT(26)
+#define CPM_HDMICDR_HDMIDIV_BIT 0
+#define CPM_HDMICDR_HDMIDIV_MASK (0xff << CPM_HDMICDR_HDMIDIV_BIT)
+
+/* Low Power Control Register */
+#define CPM_LCR_PD_SCPU BIT(31)
+#define CPM_LCR_PD_VPU BIT(30)
+#define CPM_LCR_PD_GPU BIT(29)
+#define CPM_LCR_PD_GPS BIT(28)
+#define CPM_LCR_SCPUS BIT(27)
+#define CPM_LCR_VPUS BIT(26)
+#define CPM_LCR_GPUS BIT(25)
+#define CPM_LCR_GPSS BIT(24)
+#define CPM_LCR_GPU_IDLE BIT(20)
+#define CPM_LCR_PST_BIT 8
+#define CPM_LCR_PST_MASK (0xfff << CPM_LCR_PST_BIT)
+#define CPM_LCR_DOZE_DUTY_BIT 3
+#define CPM_LCR_DOZE_DUTY_MASK (0x1f << CPM_LCR_DOZE_DUTY_BIT)
+#define CPM_LCR_DOZE_ON BIT(2)
+#define CPM_LCR_LPM_BIT 0
+#define CPM_LCR_LPM_MASK (0x3 << CPM_LCR_LPM_BIT)
+#define CPM_LCR_LPM_IDLE (0x0 << CPM_LCR_LPM_BIT)
+#define CPM_LCR_LPM_SLEEP (0x1 << CPM_LCR_LPM_BIT)
+
+/* Clock Gate Register0 */
+#define CPM_CLKGR0_DDR1 BIT(31)
+#define CPM_CLKGR0_DDR0 BIT(30)
+#define CPM_CLKGR0_IPU BIT(29)
+#define CPM_CLKGR0_LCD1 BIT(28)
+#define CPM_CLKGR0_LCD BIT(27)
+#define CPM_CLKGR0_CIM BIT(26)
+#define CPM_CLKGR0_I2C2 BIT(25)
+#define CPM_CLKGR0_UHC BIT(24)
+#define CPM_CLKGR0_MAC BIT(23)
+#define CPM_CLKGR0_GPS BIT(22)
+#define CPM_CLKGR0_PDMAC BIT(21)
+#define CPM_CLKGR0_SSI2 BIT(20)
+#define CPM_CLKGR0_SSI1 BIT(19)
+#define CPM_CLKGR0_UART3 BIT(18)
+#define CPM_CLKGR0_UART2 BIT(17)
+#define CPM_CLKGR0_UART1 BIT(16)
+#define CPM_CLKGR0_UART0 BIT(15)
+#define CPM_CLKGR0_SADC BIT(14)
+#define CPM_CLKGR0_KBC BIT(13)
+#define CPM_CLKGR0_MSC2 BIT(12)
+#define CPM_CLKGR0_MSC1 BIT(11)
+#define CPM_CLKGR0_OWI BIT(10)
+#define CPM_CLKGR0_TSSI BIT(9)
+#define CPM_CLKGR0_AIC BIT(8)
+#define CPM_CLKGR0_SCC BIT(7)
+#define CPM_CLKGR0_I2C1 BIT(6)
+#define CPM_CLKGR0_I2C0 BIT(5)
+#define CPM_CLKGR0_SSI0 BIT(4)
+#define CPM_CLKGR0_MSC0 BIT(3)
+#define CPM_CLKGR0_OTG BIT(2)
+#define CPM_CLKGR0_BCH BIT(1)
+#define CPM_CLKGR0_NEMC BIT(0)
+
+/* Clock Gate Register1 */
+#define CPM_CLKGR1_P1 BIT(15)
+#define CPM_CLKGR1_X2D BIT(14)
+#define CPM_CLKGR1_DES BIT(13)
+#define CPM_CLKGR1_I2C4 BIT(12)
+#define CPM_CLKGR1_AHB BIT(11)
+#define CPM_CLKGR1_UART4 BIT(10)
+#define CPM_CLKGR1_HDMI BIT(9)
+#define CPM_CLKGR1_OTG1 BIT(8)
+#define CPM_CLKGR1_GPVLC BIT(7)
+#define CPM_CLKGR1_AIC1 BIT(6)
+#define CPM_CLKGR1_COMPRES BIT(5)
+#define CPM_CLKGR1_GPU BIT(4)
+#define CPM_CLKGR1_PCM BIT(3)
+#define CPM_CLKGR1_VPU BIT(2)
+#define CPM_CLKGR1_TSSI1 BIT(1)
+#define CPM_CLKGR1_I2C3 BIT(0)
+
+/* Oscillator and Power Control Register */
+#define CPM_OPCR_O1ST_BIT 8
+#define CPM_OPCR_O1ST_MASK (0xff << CPM_OPCR_O1ST_BIT)
+#define CPM_OPCR_SPENDN BIT(7)
+#define CPM_OPCR_GPSEN BIT(6)
+#define CPM_OPCR_SPENDH BIT(5)
+#define CPM_OPCR_O1SE BIT(4)
+#define CPM_OPCR_ERCS BIT(2) /* 0: select EXCLK/512 clock, 1: RTCLK clock */
+#define CPM_OPCR_USBM BIT(0) /* 0: select EXCLK/512 clock, 1: RTCLK clock */
+
+/* Reset Status Register */
+#define CPM_RSR_P0R BIT(2)
+#define CPM_RSR_WR BIT(1)
+#define CPM_RSR_PR BIT(0)
+
+/* BCH clock divider register */
+#define CPM_BCHCDR_BPCS_BIT 30
+#define CPM_BCHCDR_BPCS_MASK (0x3 << CPM_BCHCDR_BPCS_BIT)
+#define CPM_BCHCDR_BPCS_STOP (0X0 << CPM_BCHCDR_BPCS_BIT)
+#define CPM_BCHCDR_BPCS_SRC_CLK (0x1 << CPM_BCHCDR_BPCS_BIT)
+#define CPM_BCHCDR_BPCS_MPLL (0x2 << CPM_BCHCDR_BPCS_BIT)
+#define CPM_BCHCDR_BPCS_EPLL (0x3 << CPM_BCHCDR_BPCS_BIT)
+#define CPM_BCHCDR_CE_BCH BIT(29)
+#define CPM_BCHCDR_BCH_BUSY BIT(28)
+#define CPM_BCHCDR_BCH_STOP BIT(27)
+#define CPM_BCHCDR_BCHCDR_BIT 0
+#define CPM_BCHCDR_BCHCDR_MASK (0x7 << CPM_BCHCDR_BCHCDR_BIT)
+
+/* CPM scratch pad protected register(CPSPPR) */
+#define CPSPPR_CPSPR_WRITABLE 0x00005a5a
+#define RECOVERY_SIGNATURE 0x1a1a /* means "RECY" */
+#define RECOVERY_SIGNATURE_SEC 0x800 /* means "RECY" */
+
+#define REBOOT_SIGNATURE 0x3535 /* means reboot */
+
+/* XPLL control register */
+#define XLOCK (1 << 6)
+#define XPLL_ON (1 << 4)
+#define XF_MODE (1 << 3)
+#define XPLLBP (1 << 1)
+#define XPLLEN (1 << 0)
+
+enum PLLS {
+ EXTCLK = 0,
+ APLL,
+ MPLL,
+ EPLL,
+ VPLL,
+};
+
+#define M_N_OD(m,n,od) \
+ ((((m) - 1) << 19) | (((n) - 1) << 13) | (((od) - 1) << 9))
+
+struct cgu_pll_select {
+ u8 reg;
+ u8 pll;
+ u8 pll_shift;
+};
+
+static void pll_init_one(int pll, int m, int n, int od)
+{
+ void __iomem *cpm_regs = (void __iomem *)CPM_BASE;
+ void __iomem *pll_reg = cpm_regs + CPM_CPAPCR + ((pll - 1) * 4);
+
+ setbits_le32(pll_reg, M_N_OD(m, n, od) | XPLLEN);
+
+ /* FIXME */
+ while (!(readl(pll_reg) & XPLL_ON))
+ ;
+}
+
+static void cpu_mux_select(int pll)
+{
+ void __iomem *cpm_regs = (void __iomem *)CPM_BASE;
+ u32 clk_ctrl;
+ unsigned int selectplls[] = {
+ CPM_PLL_SEL_STOP,
+ CPM_PLL_SEL_SRC,
+ CPM_PLL_SEL_MPLL,
+ CPM_PLL_SEL_EPLL
+ };
+
+ /* Init CPU, L2CACHE, AHB0, AHB2, APB clock */
+ clk_ctrl = CPM_CPCCR_CE_CPU | CPM_CPCCR_CE_AHB0 | CPM_CPCCR_CE_AHB2 |
+ ((6 - 1) << CPM_CPCCR_H2DIV_BIT) |
+ ((3 - 1) << CPM_CPCCR_H0DIV_BIT) |
+ ((2 - 1) << CPM_CPCCR_L2DIV_BIT) |
+ ((1 - 1) << CPM_CPCCR_CDIV_BIT);
+
+ if (CONFIG_SYS_MHZ >= 1000)
+ clk_ctrl |= (12 - 1) << CPM_CPCCR_PDIV_BIT;
+ else
+ clk_ctrl |= (6 - 1) << CPM_CPCCR_PDIV_BIT;
+
+ clrsetbits_le32(cpm_regs + CPM_CPCCR, 0x00ffffff, clk_ctrl);
+
+ while (readl(cpm_regs + CPM_CPCSR) & (CPM_CPCSR_CDIV_BUSY |
+ CPM_CPCSR_H0DIV_BUSY | CPM_CPCSR_H2DIV_BUSY))
+ ;
+
+ clk_ctrl = (selectplls[pll] << CPM_CPCCR_SEL_CPLL_BIT) |
+ (selectplls[MPLL] << CPM_CPCCR_SEL_H0PLL_BIT) |
+ (selectplls[MPLL] << CPM_CPCCR_SEL_H2PLL_BIT);
+ if (pll == APLL)
+ clk_ctrl |= CPM_PLL_SEL_SRC << CPM_CPCCR_SEL_SRC_BIT;
+ else
+ clk_ctrl |= CPM_SRC_SEL_EXCLK << CPM_CPCCR_SEL_SRC_BIT;
+
+ clrsetbits_le32(cpm_regs + CPM_CPCCR, 0xff << 24, clk_ctrl);
+}
+
+static void ddr_mux_select(int pll)
+{
+ void __iomem *cpm_regs = (void __iomem *)CPM_BASE;
+ int selectplls[] = { CPM_DDRCDR_DCS_STOP,
+ CPM_DDRCDR_DCS_SRC,
+ CPM_DDRCDR_DCS_MPLL};
+
+ writel(selectplls[pll] | CPM_DDRCDR_CE_DDR | (JZ4780_SYS_MEM_DIV - 1),
+ cpm_regs + CPM_DDCDR);
+
+ while (readl(cpm_regs + CPM_DDCDR) & CPM_DDRCDR_DDR_BUSY)
+ ;
+
+ clrbits_le32(cpm_regs + CPM_CLKGR0, CPM_CLKGR0_DDR0);
+
+ mdelay(200);
+}
+
+static void cgu_mux_init(struct cgu_pll_select *cgu, unsigned int num)
+{
+ void __iomem *cpm_regs = (void __iomem *)CPM_BASE;
+ unsigned int selectplls[] = {0, 1, 2, 3, 2, 6};
+ int i;
+
+ for (i = 0; i < num; i++)
+ writel(selectplls[cgu[i].pll] << cgu[i].pll_shift,
+ cpm_regs + cgu[i].reg);
+}
+
+void pll_init(void)
+{
+ void __iomem *cpm_regs = (void __iomem *)CPM_BASE;
+ struct cgu_pll_select cgu_mux[] = {
+ { CPM_MSCCDR, MPLL, 30 },
+ { CPM_LPCDR, VPLL, 30 },
+ { CPM_LPCDR1, VPLL, 30 },
+ { CPM_GPUCDR, MPLL, 30 },
+ { CPM_HDMICDR, VPLL, 30 },
+ { CPM_I2SCDR, EPLL, 30 },
+ { CPM_BCHCDR, MPLL, 30 },
+ { CPM_VPUCDR, 0x1, 30 },
+ { CPM_UHCCDR, 0x3, 30 },
+ { CPM_CIMCDR, 0x1, 31 },
+ { CPM_PCMCDR, 0x5, 29 },
+ { CPM_SSICDR, 0x3, 30 },
+ };
+
+ /* PLL stable time set to default -- 1ms */
+ clrsetbits_le32(cpm_regs + CPM_CPPCR, 0xfffff, (16 << 8) | 0x20);
+
+ pll_init_one(APLL, JZ4780_APLL_M, JZ4780_APLL_N, JZ4780_APLL_OD);
+ pll_init_one(MPLL, JZ4780_MPLL_M, JZ4780_MPLL_N, JZ4780_MPLL_OD);
+ pll_init_one(VPLL, JZ4780_VPLL_M, JZ4780_VPLL_N, JZ4780_VPLL_OD);
+ pll_init_one(EPLL, JZ4780_EPLL_M, JZ4780_EPLL_N, JZ4780_EPLL_OD);
+
+ cpu_mux_select(MPLL);
+ ddr_mux_select(MPLL);
+ cgu_mux_init(cgu_mux, ARRAY_SIZE(cgu_mux));
+}
+
+const u32 jz4780_clk_get_efuse_clk(void)
+{
+ void __iomem *cpm_regs = (void __iomem *)CPM_BASE;
+ u32 cpccr = readl(cpm_regs + CPM_CPCCR);
+ u32 ahb2_div = ((cpccr & CPM_CPCCR_H2DIV_MASK) >>
+ CPM_CPCCR_H2DIV_BIT) + 1;
+ return JZ4780_SYS_MEM_SPEED / ahb2_div;
+}
+
+void jz4780_clk_ungate_ethernet(void)
+{
+ void __iomem *cpm_regs = (void __iomem *)CPM_BASE;
+ clrbits_le32(cpm_regs + CPM_CLKGR0, CPM_CLKGR0_MAC);
+ clrbits_le32(cpm_regs + CPM_CLKGR0, CPM_CLKGR0_NEMC);
+}
+
+void jz4780_clk_ungate_mmc(void)
+{
+ void __iomem *cpm_regs = (void __iomem *)CPM_BASE;
+ u32 msc_cdr = JZ4780_SYS_MEM_SPEED / 24000000 / 2 - 1;
+ msc_cdr |= CPM_MSCCDR_MPCS_MPLL | CPM_MSCCDR_CE;
+ writel(msc_cdr, cpm_regs + CPM_MSCCDR);
+ writel(msc_cdr, cpm_regs + CPM_MSCCDR1);
+ writel(msc_cdr, cpm_regs + CPM_MSCCDR2);
+
+ /* The wait_for_bit() won't fit, thus unbounded loop here. */
+ while (readl(cpm_regs + CPM_MSCCDR1) & CPM_MSCCDR_MSC_BUSY)
+ ;
+}
+
+void jz4780_clk_ungate_uart(const unsigned int uart)
+{
+ void __iomem *cpm_regs = (void __iomem *)CPM_BASE;
+ if (uart == 0)
+ clrbits_le32(cpm_regs + CPM_CLKGR0, CPM_CLKGR0_UART0);
+ else if (uart == 1)
+ clrbits_le32(cpm_regs + CPM_CLKGR0, CPM_CLKGR0_UART1);
+ else if (uart == 2)
+ clrbits_le32(cpm_regs + CPM_CLKGR0, CPM_CLKGR0_UART2);
+ else if (uart == 3)
+ clrbits_le32(cpm_regs + CPM_CLKGR0, CPM_CLKGR0_UART3);
+ else if (uart == 4)
+ clrbits_le32(cpm_regs + CPM_CLKGR1, CPM_CLKGR1_UART4);
+ else
+ printf("%s[%i]: Invalid UART %d\n", __func__, __LINE__, uart);
+}
diff --git a/arch/mips/mach-jz47xx/jz4780/sdram.c b/arch/mips/mach-jz47xx/jz4780/sdram.c
new file mode 100644
index 000000000000..8cc3ffc85173
--- /dev/null
+++ b/arch/mips/mach-jz47xx/jz4780/sdram.c
@@ -0,0 +1,271 @@
+/*
+ * JZ4780 DDR initialization
+ *
+ * Copyright (c) 2013 Imagination Technologies
+ * Author: Paul Burton <***@imgtec.com>
+ *
+ * Based on spl/common/{jz4780_ddr,jz_ddr3_init}.c from X-Boot
+ * Copyright (c) 2006-2013 Ingenic Semiconductor
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <mach/jz4780.h>
+#include <mach/jz4780_dram.h>
+
+static const u32 get_mem_clk(void)
+{
+ const u32 mpll_out = ((u64)JZ4780_SYS_EXTAL * JZ4780_MPLL_M) /
+ (JZ4780_MPLL_N * JZ4780_MPLL_OD);
+ return mpll_out / JZ4780_SYS_MEM_DIV;
+}
+
+u32 sdram_size(int cs)
+{
+ u32 dw = DDR_DW32 ? 4 : 2;
+ u32 banks = DDR_BANK8 ? 8 : 4;
+ u32 size = 0;
+
+ if ((cs == 0) && DDR_CS0EN) {
+ size = (1 << (DDR_ROW + DDR_COL)) * dw * banks;
+ if (DDR_CS1EN && (size > 0x20000000))
+ size = 0x20000000;
+ } else if ((cs == 1) && DDR_CS1EN) {
+ size = (1 << (DDR_ROW + DDR_COL)) * dw * banks;
+ }
+
+ return size;
+}
+
+static void ddr_cfg_init(void)
+{
+ void __iomem *ddr_ctl_regs = (void __iomem *)DDRC_BASE;
+ u32 ddrc_cfg, tmp;
+
+ tmp = DDR_CL;
+ if (tmp)
+ tmp--;
+ if (tmp > 4)
+ tmp = 4;
+
+ ddrc_cfg = DDRC_CFG_TYPE_DDR3 | DDRC_CFG_IMBA |
+ DDR_DW32 | DDRC_CFG_MPRT | ((tmp | 0x8) << 2) |
+ ((DDR_ROW - 12) << 11) | ((DDR_COL - 8) << 8) |
+ (DDR_CS0EN << 6) | (DDR_BANK8 << 1) |
+ ((DDR_ROW - 12) << 27) | ((DDR_COL - 8) << 24) |
+ (DDR_CS1EN << 7) | (DDR_BANK8 << 23);
+
+ if (DDR_BL > 4)
+ ddrc_cfg |= BIT(21);
+
+ writel(ddrc_cfg, ddr_ctl_regs + DDRC_CFG);
+}
+
+static void ddr_phy_init(const struct jz4780_ddr_config *ddr_config)
+{
+ void __iomem *ddr_ctl_regs = (void __iomem *)DDRC_BASE;
+ void __iomem *ddr_phy_regs = ddr_ctl_regs + DDR_PHY_OFFSET;
+ unsigned int count = 0, i;
+ u32 reg, mask;
+
+ writel(DDRP_DCR_TYPE_DDR3 | (DDR_BANK8 << 3), ddr_phy_regs + DDRP_DCR);
+
+ writel(ddr_config->mr0, ddr_phy_regs + DDRP_MR0);
+ writel(ddr_config->mr1, ddr_phy_regs + DDRP_MR1);
+ writel(0, ddr_phy_regs + DDRP_ODTCR);
+ writel(0, ddr_phy_regs + DDRP_MR2);
+
+ writel(ddr_config->ptr0, ddr_phy_regs + DDRP_PTR0);
+ writel(ddr_config->ptr1, ddr_phy_regs + DDRP_PTR1);
+ writel(ddr_config->ptr2, ddr_phy_regs + DDRP_PTR2);
+
+ writel(ddr_config->dtpr0, ddr_phy_regs + DDRP_DTPR0);
+ writel(ddr_config->dtpr1, ddr_phy_regs + DDRP_DTPR1);
+ writel(ddr_config->dtpr2, ddr_phy_regs + DDRP_DTPR2);
+
+ writel(DDRP_PGCR_DQSCFG | (7 << DDRP_PGCR_CKEN_BIT) |
+ (2 << DDRP_PGCR_CKDV_BIT) |
+ (DDR_CS0EN | (DDR_CS1EN << 1)) << DDRP_PGCR_RANKEN_BIT |
+ DDRP_PGCR_ZCKSEL_32 | DDRP_PGCR_PDDISDX,
+ ddr_phy_regs + DDRP_PGCR);
+
+ for (i = 0; i < 8; i++)
+ clrbits_le32(ddr_phy_regs + DDRP_DXGCR(i), 0x3 << 9);
+
+ count = 0;
+ mask = DDRP_PGSR_IDONE | DDRP_PGSR_DLDONE | DDRP_PGSR_ZCDONE;
+ for (;;) {
+ reg = readl(ddr_phy_regs + DDRP_PGSR);
+ if ((reg == mask) || (reg == 0x1f))
+ break;
+ if (count++ == 10000)
+ hang();
+ }
+
+ /* DQS extension and early set to 1 */
+ clrsetbits_le32(ddr_phy_regs + DDRP_DSGCR, 0x7E << 4, 0x12 << 4);
+
+ /* 500 pull up and 500 pull down */
+ clrsetbits_le32(ddr_phy_regs + DDRP_DXCCR, 0xFF << 4, 0xC4 << 4);
+
+ /* Initialise phy */
+ writel(DDRP_PIR_INIT | DDRP_PIR_DRAMINT | DDRP_PIR_DRAMRST,
+ ddr_phy_regs + DDRP_PIR);
+
+ count = 0;
+ mask |= DDRP_PGSR_DIDONE;
+ for (;;) {
+ reg = readl(ddr_phy_regs + DDRP_PGSR);
+ if ((reg == mask) || (reg == 0x1f))
+ break;
+ if (count++ == 20000)
+ hang();
+ }
+
+ writel(DDRP_PIR_INIT | DDRP_PIR_QSTRN, ddr_phy_regs + DDRP_PIR);
+
+ count = 0;
+ mask |= DDRP_PGSR_DTDONE;
+ for (;;) {
+ reg = readl(ddr_phy_regs + DDRP_PGSR);
+ if (reg == mask)
+ break;
+ if (count++ != 50000)
+ continue;
+ reg &= DDRP_PGSR_DTDONE | DDRP_PGSR_DTERR | DDRP_PGSR_DTIERR;
+ if (reg)
+ hang();
+ count = 0;
+ }
+
+ /* Override impedance */
+ clrsetbits_le32(ddr_phy_regs + DDRP_ZQXCR0(0), 0x3ff,
+ ((ddr_config->pullup & 0x1f) << DDRP_ZQXCR_PULLUP_IMPE_BIT) |
+ ((ddr_config->pulldn & 0x1f) << DDRP_ZQXCR_PULLDOWN_IMPE_BIT) |
+ DDRP_ZQXCR_ZDEN);
+}
+
+#define JZBIT(bit) ((bit % 4) * 8)
+#define JZMASK(bit) (0x1f << JZBIT(bit))
+
+static void remap_swap(int a, int b)
+{
+ void __iomem *ddr_ctl_regs = (void __iomem *)DDRC_BASE;
+ u32 remmap[2], tmp[2];
+
+ remmap[0] = readl(ddr_ctl_regs + DDRC_REMMAP(a / 4));
+ remmap[1] = readl(ddr_ctl_regs + DDRC_REMMAP(b / 4));
+
+ tmp[0] = (remmap[0] & JZMASK(a)) >> JZBIT(a);
+ tmp[1] = (remmap[1] & JZMASK(b)) >> JZBIT(b);
+
+ remmap[0] &= ~JZMASK(a);
+ remmap[1] &= ~JZMASK(b);
+
+ writel(remmap[0] | (tmp[1] << JZBIT(a)),
+ ddr_ctl_regs + DDRC_REMMAP(a / 4));
+ writel(remmap[1] | (tmp[0] << JZBIT(b)),
+ ddr_ctl_regs + DDRC_REMMAP(b / 4));
+}
+
+static void mem_remap(void)
+{
+ u32 start = (DDR_ROW + DDR_COL + (DDR_DW32 ? 4 : 2) / 2) - 12;
+ u32 num = DDR_BANK8 ? 3 : 2;
+
+ if (DDR_CS0EN && DDR_CS1EN)
+ num++;
+
+ for (; num > 0; num--)
+ remap_swap(0 + num - 1, start + num - 1);
+}
+
+/* Fetch DRAM config from board file */
+__weak const struct jz4780_ddr_config *jz4780_get_ddr_config(void)
+{
+ return NULL;
+}
+
+void sdram_init(void)
+{
+ const struct jz4780_ddr_config *ddr_config = jz4780_get_ddr_config();
+ void __iomem *ddr_ctl_regs = (void __iomem *)DDRC_BASE;
+ void __iomem *ddr_phy_regs = ddr_ctl_regs + DDR_PHY_OFFSET;
+ void __iomem *cpm_regs = (void __iomem *)CPM_BASE;
+ u32 mem_clk, tmp, i;
+ u32 mem_base0, mem_base1;
+ u32 mem_mask0, mem_mask1;
+ u32 mem_size0, mem_size1;
+
+ if (!ddr_config)
+ hang();
+
+ /* Reset DLL in DDR PHY */
+ writel(0x3, cpm_regs + 0xd0);
+ mdelay(400);
+ writel(0x1, cpm_regs + 0xd0);
+ mdelay(400);
+
+ /* Enter reset */
+ writel(0xf << 20, ddr_ctl_regs + DDRC_CTRL);
+
+ mem_clk = get_mem_clk();
+
+ tmp = 1000000000 / mem_clk;
+ if (1000000000 % mem_clk)
+ tmp++;
+ tmp = DDR_tREFI / tmp;
+ tmp = tmp / (16 * (1 << DDR_CLK_DIV)) - 1;
+ if (tmp > 0xff)
+ tmp = 0xff;
+ if (tmp < 1)
+ tmp = 1;
+
+ writel(0x0, ddr_ctl_regs + DDRC_CTRL);
+
+ writel(0x150000, ddr_phy_regs + DDRP_DTAR);
+ ddr_phy_init(ddr_config);
+
+ writel(DDRC_CTRL_CKE | DDRC_CTRL_ALH, ddr_ctl_regs + DDRC_CTRL);
+ writel(0x0, ddr_ctl_regs + DDRC_CTRL);
+
+ ddr_cfg_init();
+
+ for (i = 0; i < 6; i++)
+ writel(ddr_config->timing[i], ddr_ctl_regs + DDRC_TIMING(i));
+
+ mem_size0 = sdram_size(0);
+ mem_size1 = sdram_size(1);
+
+ if (!mem_size1 && mem_size0 > 0x20000000) {
+ mem_base0 = 0x0;
+ mem_mask0 = ~(((mem_size0 * 2) >> 24) - 1) & DDRC_MMAP_MASK_MASK;
+ } else {
+ mem_base0 = (DDR_MEM_PHY_BASE >> 24) & 0xff;
+ mem_mask0 = ~((mem_size0 >> 24) - 1) & DDRC_MMAP_MASK_MASK;
+ }
+
+ if (mem_size1) {
+ mem_mask1 = ~((mem_size1 >> 24) - 1) & DDRC_MMAP_MASK_MASK;
+ mem_base1 = ((DDR_MEM_PHY_BASE + mem_size0) >> 24) & 0xff;
+ } else {
+ mem_mask1 = 0;
+ mem_base1 = 0xff;
+ }
+
+ writel(mem_base0 << DDRC_MMAP_BASE_BIT | mem_mask0,
+ ddr_ctl_regs + DDRC_MMAP0);
+ writel(mem_base1 << DDRC_MMAP_BASE_BIT | mem_mask1,
+ ddr_ctl_regs + DDRC_MMAP1);
+ writel(DDRC_CTRL_CKE | DDRC_CTRL_ALH, ddr_ctl_regs + DDRC_CTRL);
+ writel((DDR_CLK_DIV << 1) | DDRC_REFCNT_REF_EN |
+ (tmp << DDRC_REFCNT_CON_BIT),
+ ddr_ctl_regs + DDRC_REFCNT);
+ writel((1 << 15) | (4 << 12) | (1 << 11) | (1 << 8) | (0 << 6) |
+ (1 << 4) | (1 << 3) | (1 << 2) | (1 << 1),
+ ddr_ctl_regs + DDRC_CTRL);
+ mem_remap();
+ clrbits_le32(ddr_ctl_regs + DDRC_ST, 0x40);
+}
diff --git a/arch/mips/mach-jz47xx/jz4780/timer.c b/arch/mips/mach-jz47xx/jz4780/timer.c
new file mode 100644
index 000000000000..a9fc2cb38e51
--- /dev/null
+++ b/arch/mips/mach-jz47xx/jz4780/timer.c
@@ -0,0 +1,238 @@
+/*
+ * JZ4780 timer
+ *
+ * Copyright (c) 2013 Imagination Technologies
+ * Author: Paul Burton <***@imgtec.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <config.h>
+#include <common.h>
+#include <div64.h>
+#include <asm/io.h>
+#include <asm/mipsregs.h>
+#include <mach/jz4780.h>
+
+#define TCU_TSR 0x1C /* Timer Stop Register */
+#define TCU_TSSR 0x2C /* Timer Stop Set Register */
+#define TCU_TSCR 0x3C /* Timer Stop Clear Register */
+#define TCU_TER 0x10 /* Timer Counter Enable Register */
+#define TCU_TESR 0x14 /* Timer Counter Enable Set Register */
+#define TCU_TECR 0x18 /* Timer Counter Enable Clear Register */
+#define TCU_TFR 0x20 /* Timer Flag Register */
+#define TCU_TFSR 0x24 /* Timer Flag Set Register */
+#define TCU_TFCR 0x28 /* Timer Flag Clear Register */
+#define TCU_TMR 0x30 /* Timer Mask Register */
+#define TCU_TMSR 0x34 /* Timer Mask Set Register */
+#define TCU_TMCR 0x38 /* Timer Mask Clear Register */
+/* n = 0,1,2,3,4,5 */
+#define TCU_TDFR(n) (0x40 + (n) * 0x10) /* Timer Data Full Reg */
+#define TCU_TDHR(n) (0x44 + (n) * 0x10) /* Timer Data Half Reg */
+#define TCU_TCNT(n) (0x48 + (n) * 0x10) /* Timer Counter Reg */
+#define TCU_TCSR(n) (0x4C + (n) * 0x10) /* Timer Control Reg */
+
+#define TCU_OSTCNTL 0xe4
+#define TCU_OSTCNTH 0xe8
+#define TCU_OSTCSR 0xec
+#define TCU_OSTCNTHBUF 0xfc
+
+/* Register definitions */
+#define TCU_TCSR_PWM_SD BIT(9)
+#define TCU_TCSR_PWM_INITL_HIGH BIT(8)
+#define TCU_TCSR_PWM_EN BIT(7)
+#define TCU_TCSR_PRESCALE_BIT 3
+#define TCU_TCSR_PRESCALE_MASK (0x7 << TCU_TCSR_PRESCALE_BIT)
+#define TCU_TCSR_PRESCALE1 (0x0 << TCU_TCSR_PRESCALE_BIT)
+#define TCU_TCSR_PRESCALE4 (0x1 << TCU_TCSR_PRESCALE_BIT)
+#define TCU_TCSR_PRESCALE16 (0x2 << TCU_TCSR_PRESCALE_BIT)
+#define TCU_TCSR_PRESCALE64 (0x3 << TCU_TCSR_PRESCALE_BIT)
+#define TCU_TCSR_PRESCALE256 (0x4 << TCU_TCSR_PRESCALE_BIT)
+#define TCU_TCSR_PRESCALE1024 (0x5 << TCU_TCSR_PRESCALE_BIT)
+#define TCU_TCSR_EXT_EN BIT(2)
+#define TCU_TCSR_RTC_EN BIT(1)
+#define TCU_TCSR_PCK_EN BIT(0)
+
+#define TCU_TER_TCEN5 BIT(5)
+#define TCU_TER_TCEN4 BIT(4)
+#define TCU_TER_TCEN3 BIT(3)
+#define TCU_TER_TCEN2 BIT(2)
+#define TCU_TER_TCEN1 BIT(1)
+#define TCU_TER_TCEN0 BIT(0)
+
+#define TCU_TESR_TCST5 BIT(5)
+#define TCU_TESR_TCST4 BIT(4)
+#define TCU_TESR_TCST3 BIT(3)
+#define TCU_TESR_TCST2 BIT(2)
+#define TCU_TESR_TCST1 BIT(1)
+#define TCU_TESR_TCST0 BIT(0)
+
+#define TCU_TECR_TCCL5 BIT(5)
+#define TCU_TECR_TCCL4 BIT(4)
+#define TCU_TECR_TCCL3 BIT(3)
+#define TCU_TECR_TCCL2 BIT(2)
+#define TCU_TECR_TCCL1 BIT(1)
+#define TCU_TECR_TCCL0 BIT(0)
+
+#define TCU_TFR_HFLAG5 BIT(21)
+#define TCU_TFR_HFLAG4 BIT(20)
+#define TCU_TFR_HFLAG3 BIT(19)
+#define TCU_TFR_HFLAG2 BIT(18)
+#define TCU_TFR_HFLAG1 BIT(17)
+#define TCU_TFR_HFLAG0 BIT(16)
+#define TCU_TFR_FFLAG5 BIT(5)
+#define TCU_TFR_FFLAG4 BIT(4)
+#define TCU_TFR_FFLAG3 BIT(3)
+#define TCU_TFR_FFLAG2 BIT(2)
+#define TCU_TFR_FFLAG1 BIT(1)
+#define TCU_TFR_FFLAG0 BIT(0)
+
+#define TCU_TFSR_HFLAG5 BIT(21)
+#define TCU_TFSR_HFLAG4 BIT(20)
+#define TCU_TFSR_HFLAG3 BIT(19)
+#define TCU_TFSR_HFLAG2 BIT(18)
+#define TCU_TFSR_HFLAG1 BIT(17)
+#define TCU_TFSR_HFLAG0 BIT(16)
+#define TCU_TFSR_FFLAG5 BIT(5)
+#define TCU_TFSR_FFLAG4 BIT(4)
+#define TCU_TFSR_FFLAG3 BIT(3)
+#define TCU_TFSR_FFLAG2 BIT(2)
+#define TCU_TFSR_FFLAG1 BIT(1)
+#define TCU_TFSR_FFLAG0 BIT(0)
+
+#define TCU_TFCR_HFLAG5 BIT(21)
+#define TCU_TFCR_HFLAG4 BIT(20)
+#define TCU_TFCR_HFLAG3 BIT(19)
+#define TCU_TFCR_HFLAG2 BIT(18)
+#define TCU_TFCR_HFLAG1 BIT(17)
+#define TCU_TFCR_HFLAG0 BIT(16)
+#define TCU_TFCR_FFLAG5 BIT(5)
+#define TCU_TFCR_FFLAG4 BIT(4)
+#define TCU_TFCR_FFLAG3 BIT(3)
+#define TCU_TFCR_FFLAG2 BIT(2)
+#define TCU_TFCR_FFLAG1 BIT(1)
+#define TCU_TFCR_FFLAG0 BIT(0)
+
+#define TCU_TMR_HMASK5 BIT(21)
+#define TCU_TMR_HMASK4 BIT(20)
+#define TCU_TMR_HMASK3 BIT(19)
+#define TCU_TMR_HMASK2 BIT(18)
+#define TCU_TMR_HMASK1 BIT(17)
+#define TCU_TMR_HMASK0 BIT(16)
+#define TCU_TMR_FMASK5 BIT(5)
+#define TCU_TMR_FMASK4 BIT(4)
+#define TCU_TMR_FMASK3 BIT(3)
+#define TCU_TMR_FMASK2 BIT(2)
+#define TCU_TMR_FMASK1 BIT(1)
+#define TCU_TMR_FMASK0 BIT(0)
+
+#define TCU_TMSR_HMST5 BIT(21)
+#define TCU_TMSR_HMST4 BIT(20)
+#define TCU_TMSR_HMST3 BIT(19)
+#define TCU_TMSR_HMST2 BIT(18)
+#define TCU_TMSR_HMST1 BIT(17)
+#define TCU_TMSR_HMST0 BIT(16)
+#define TCU_TMSR_FMST5 BIT(5)
+#define TCU_TMSR_FMST4 BIT(4)
+#define TCU_TMSR_FMST3 BIT(3)
+#define TCU_TMSR_FMST2 BIT(2)
+#define TCU_TMSR_FMST1 BIT(1)
+#define TCU_TMSR_FMST0 BIT(0)
+
+#define TCU_TMCR_HMCL5 BIT(21)
+#define TCU_TMCR_HMCL4 BIT(20)
+#define TCU_TMCR_HMCL3 BIT(19)
+#define TCU_TMCR_HMCL2 BIT(18)
+#define TCU_TMCR_HMCL1 BIT(17)
+#define TCU_TMCR_HMCL0 BIT(16)
+#define TCU_TMCR_FMCL5 BIT(5)
+#define TCU_TMCR_FMCL4 BIT(4)
+#define TCU_TMCR_FMCL3 BIT(3)
+#define TCU_TMCR_FMCL2 BIT(2)
+#define TCU_TMCR_FMCL1 BIT(1)
+#define TCU_TMCR_FMCL0 BIT(0)
+
+#define TCU_TSR_WDTS BIT(16)
+#define TCU_TSR_STOP5 BIT(5)
+#define TCU_TSR_STOP4 BIT(4)
+#define TCU_TSR_STOP3 BIT(3)
+#define TCU_TSR_STOP2 BIT(2)
+#define TCU_TSR_STOP1 BIT(1)
+#define TCU_TSR_STOP0 BIT(0)
+
+#define TCU_TSSR_WDTSS BIT(16)
+#define TCU_TSSR_STPS5 BIT(5)
+#define TCU_TSSR_STPS4 BIT(4)
+#define TCU_TSSR_STPS3 BIT(3)
+#define TCU_TSSR_STPS2 BIT(2)
+#define TCU_TSSR_STPS1 BIT(1)
+#define TCU_TSSR_STPS0 BIT(0)
+
+#define TCU_TSSR_WDTSC BIT(16)
+#define TCU_TSSR_STPC5 BIT(5)
+#define TCU_TSSR_STPC4 BIT(4)
+#define TCU_TSSR_STPC3 BIT(3)
+#define TCU_TSSR_STPC2 BIT(2)
+#define TCU_TSSR_STPC1 BIT(1)
+#define TCU_TSSR_STPC0 BIT(0)
+
+#define TER_OSTEN BIT(15)
+
+#define OSTCSR_CNT_MD BIT(15)
+#define OSTCSR_SD BIT(9)
+#define OSTCSR_PRESCALE_16 (0x2 << 3)
+#define OSTCSR_EXT_EN BIT(2)
+
+int timer_init(void)
+{
+ void __iomem *regs = (void __iomem *)TCU_BASE;
+
+ writel(OSTCSR_SD, regs + TCU_OSTCSR);
+ reset_timer();
+ writel(OSTCSR_CNT_MD | OSTCSR_EXT_EN | OSTCSR_PRESCALE_16,
+ regs + TCU_OSTCSR);
+ writew(TER_OSTEN, regs + TCU_TESR);
+ return 0;
+}
+
+void reset_timer(void)
+{
+ void __iomem *regs = (void __iomem *)TCU_BASE;
+
+ writel(0, regs + TCU_OSTCNTH);
+ writel(0, regs + TCU_OSTCNTL);
+}
+
+static u64 get_timer64(void)
+{
+ void __iomem *regs = (void __iomem *)TCU_BASE;
+ u32 low = readl(regs + TCU_OSTCNTL);
+ u32 high = readl(regs + TCU_OSTCNTHBUF);
+ return ((u64)high << 32) | low;
+}
+
+ulong get_timer(ulong base)
+{
+ return lldiv(get_timer64(), 3000) - base;
+}
+
+void __udelay(unsigned long usec)
+{
+ /* OST count increments at 3MHz */
+ u64 end = get_timer64() + ((u64)usec * 3);
+ while (get_timer64() < end)
+ ;
+}
+
+unsigned long long get_ticks(void)
+{
+ return get_timer64();
+}
+
+void jz4780_tcu_wdt_start(void)
+{
+ void __iomem *tcu_regs = (void __iomem *)TCU_BASE;
+
+ /* Enable WDT clock */
+ writel(TCU_TSSR_WDTSC, tcu_regs + TCU_TSCR);
+}
diff --git a/arch/mips/mach-jz47xx/jz4780/u-boot-spl.lds b/arch/mips/mach-jz47xx/jz4780/u-boot-spl.lds
new file mode 100644
index 000000000000..f6d2d2d9117a
--- /dev/null
+++ b/arch/mips/mach-jz47xx/jz4780/u-boot-spl.lds
@@ -0,0 +1,52 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+MEMORY { .sram : ORIGIN = CONFIG_SPL_TEXT_BASE,\
+ LENGTH = CONFIG_SPL_MAX_SIZE }
+MEMORY { .sdram : ORIGIN = CONFIG_SPL_BSS_START_ADDR, \
+ LENGTH = CONFIG_SPL_BSS_MAX_SIZE }
+
+OUTPUT_ARCH(mips)
+ENTRY(_start)
+SECTIONS
+{
+ .text :
+ {
+ __image_copy_start = .;
+ arch/mips/mach-jz47xx/start.o (.text*)
+ *(.text*)
+ } >.sram
+
+ . = ALIGN(4);
+ .rodata : { *(SORT_BY_ALIGNMENT(.rodata*)) } >.sram
+
+ . = ALIGN(4);
+ .data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram
+
+ . = ALIGN(4);
+ __image_copy_end = .;
+
+ .bss : {
+ . = ALIGN(4);
+ __bss_start = .;
+ *(.sbss.*)
+ *(.bss.*)
+ *(COMMON)
+ . = ALIGN(4);
+ __bss_end = .;
+ } >.sdram
+
+ /DISCARD/ : {
+ *(.dynbss)
+ *(.dynstr)
+ *(.dynamic)
+ *(.interp)
+ *(.hash)
+ *(.gnu.*)
+ *(.plt)
+ *(.got.plt)
+ *(.rel.plt)
+ *(.rel.dyn)
+ }
+}
diff --git a/arch/mips/mach-jz47xx/start.S b/arch/mips/mach-jz47xx/start.S
new file mode 100644
index 000000000000..9f70596d3302
--- /dev/null
+++ b/arch/mips/mach-jz47xx/start.S
@@ -0,0 +1,99 @@
+/*
+ * Startup Code for MIPS32 XBURST CPU-core
+ *
+ * Copyright (c) 2010 Xiangfu Liu <***@sharism.cc>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <config.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/cacheops.h>
+#include <asm/cache.h>
+#include <mach/jz4780.h>
+
+ .set noreorder
+
+ .globl _start
+ .text
+_start:
+#ifdef CONFIG_SPL_BUILD
+
+ /* magic value ("MSPL") */
+ .word 0x4d53504c
+
+ /* Invalidate BTB */
+ mfc0 t0, CP0_CONFIG, 7
+ nop
+ ori t0, 2
+ mtc0 t0, CP0_CONFIG, 7
+ nop
+
+ /*
+ * CU0=UM=EXL=IE=0, BEV=ERL=1, IP2~7=1
+ */
+ li t0, 0x0040FC04
+ mtc0 t0, CP0_STATUS
+
+ /* CAUSE register */
+ /* IV=1, use the specical interrupt vector (0x200) */
+ li t1, 0x00800000
+ mtc0 t1, CP0_CAUSE
+
+#ifdef CONFIG_SOC_JZ4780
+ /* enable bridge radical mode */
+ la t0, CPM_BASE
+ lw t1, 0x24(t0)
+ ori t1, t1, 0x22
+ sw t1, 0x24(t0)
+#endif
+
+ /* Set up stack */
+ li sp, CONFIG_SPL_STACK
+
+ b board_init_f
+ nop
+
+#ifdef CONFIG_SOC_JZ4780
+
+ .globl enable_caches
+ .ent enable_caches
+enable_caches:
+ mtc0 zero, CP0_TAGLO
+ mtc0 zero, CP0_TAGHI
+
+ li t0, KSEG0
+ addu t1, t0, CONFIG_SYS_DCACHE_SIZE
+1:
+ cache INDEX_STORE_TAG_D, 0(t0)
+ bne t0, t1, 1b
+ addiu t0, t0, CONFIG_SYS_CACHELINE_SIZE
+
+ li t0, KSEG0
+ addu t1, t0, CONFIG_SYS_ICACHE_SIZE
+2:
+ cache INDEX_STORE_TAG_I, 0(t0)
+ bne t0, t1, 2b
+ addiu t0, t0, CONFIG_SYS_CACHELINE_SIZE
+
+ /* Invalidate BTB */
+ mfc0 t0, CP0_CONFIG, 7
+ nop
+ ori t0, 2
+ mtc0 t0, CP0_CONFIG, 7
+ nop
+
+ /* Enable caches */
+ li t0, CONF_CM_CACHABLE_NONCOHERENT
+ mtc0 t0, CP0_CONFIG
+ nop
+
+ jr ra
+ nop
+
+ .end enable_caches
+
+#endif /* CONFIG_SOC_JZ4780 */
+#endif /* !CONFIG_SPL_BUILD */
diff --git a/include/dt-bindings/clock/jz4780-cgu.h b/include/dt-bindings/clock/jz4780-cgu.h
new file mode 100644
index 000000000000..467165e3cfee
--- /dev/null
+++ b/include/dt-bindings/clock/jz4780-cgu.h
@@ -0,0 +1,88 @@
+/*
+ * This header provides clock numbers for the ingenic,jz4780-cgu DT binding.
+ *
+ * They are roughly ordered as:
+ * - external clocks
+ * - PLLs
+ * - muxes/dividers in the order they appear in the jz4780 programmers manual
+ * - gates in order of their bit in the CLKGR* registers
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_JZ4780_CGU_H__
+#define __DT_BINDINGS_CLOCK_JZ4780_CGU_H__
+
+#define JZ4780_CLK_EXCLK 0
+#define JZ4780_CLK_RTCLK 1
+#define JZ4780_CLK_APLL 2
+#define JZ4780_CLK_MPLL 3
+#define JZ4780_CLK_EPLL 4
+#define JZ4780_CLK_VPLL 5
+#define JZ4780_CLK_OTGPHY 6
+#define JZ4780_CLK_SCLKA 7
+#define JZ4780_CLK_CPUMUX 8
+#define JZ4780_CLK_CPU 9
+#define JZ4780_CLK_L2CACHE 10
+#define JZ4780_CLK_AHB0 11
+#define JZ4780_CLK_AHB2PMUX 12
+#define JZ4780_CLK_AHB2 13
+#define JZ4780_CLK_PCLK 14
+#define JZ4780_CLK_DDR 15
+#define JZ4780_CLK_VPU 16
+#define JZ4780_CLK_I2SPLL 17
+#define JZ4780_CLK_I2S 18
+#define JZ4780_CLK_LCD0PIXCLK 19
+#define JZ4780_CLK_LCD1PIXCLK 20
+#define JZ4780_CLK_MSCMUX 21
+#define JZ4780_CLK_MSC0 22
+#define JZ4780_CLK_MSC1 23
+#define JZ4780_CLK_MSC2 24
+#define JZ4780_CLK_UHC 25
+#define JZ4780_CLK_SSIPLL 26
+#define JZ4780_CLK_SSI 27
+#define JZ4780_CLK_CIMMCLK 28
+#define JZ4780_CLK_PCMPLL 29
+#define JZ4780_CLK_PCM 30
+#define JZ4780_CLK_GPU 31
+#define JZ4780_CLK_HDMI 32
+#define JZ4780_CLK_BCH 33
+#define JZ4780_CLK_NEMC 34
+#define JZ4780_CLK_OTG0 35
+#define JZ4780_CLK_SSI0 36
+#define JZ4780_CLK_SMB0 37
+#define JZ4780_CLK_SMB1 38
+#define JZ4780_CLK_SCC 39
+#define JZ4780_CLK_AIC 40
+#define JZ4780_CLK_TSSI0 41
+#define JZ4780_CLK_OWI 42
+#define JZ4780_CLK_KBC 43
+#define JZ4780_CLK_SADC 44
+#define JZ4780_CLK_UART0 45
+#define JZ4780_CLK_UART1 46
+#define JZ4780_CLK_UART2 47
+#define JZ4780_CLK_UART3 48
+#define JZ4780_CLK_SSI1 49
+#define JZ4780_CLK_SSI2 50
+#define JZ4780_CLK_PDMA 51
+#define JZ4780_CLK_GPS 52
+#define JZ4780_CLK_MAC 53
+#define JZ4780_CLK_SMB2 54
+#define JZ4780_CLK_CIM 55
+#define JZ4780_CLK_LCD 56
+#define JZ4780_CLK_TVE 57
+#define JZ4780_CLK_IPU 58
+#define JZ4780_CLK_DDR0 59
+#define JZ4780_CLK_DDR1 60
+#define JZ4780_CLK_SMB3 61
+#define JZ4780_CLK_TSSI1 62
+#define JZ4780_CLK_COMPRESS 63
+#define JZ4780_CLK_AIC1 64
+#define JZ4780_CLK_GPVLC 65
+#define JZ4780_CLK_OTG1 66
+#define JZ4780_CLK_UART4 67
+#define JZ4780_CLK_AHBMON 68
+#define JZ4780_CLK_SMB4 69
+#define JZ4780_CLK_DES 70
+#define JZ4780_CLK_X2D 71
+#define JZ4780_CLK_CORE1 72
+
+#endif /* __DT_BINDINGS_CLOCK_JZ4780_CGU_H__ */
--
2.20.0.rc2
Ezequiel Garcia
2018-12-10 20:35:59 UTC
Permalink
From: Paul Burton <***@imgtec.com>

Add driver for the JZ47xx MSC controller.

Cc: Daniel Schwierzeck <***@gmail.com>
Signed-off-by: Paul Burton <***@imgtec.com>
Signed-off-by: Marek Vasut <***@gmail.com>
Signed-off-by: Ezequiel Garcia <***@collabora.com>
---
drivers/mmc/Kconfig | 6 +
drivers/mmc/Makefile | 1 +
drivers/mmc/jz_mmc. | 0
drivers/mmc/jz_mmc.c | 491 +++++++++++++++++++++++++++++++++++++++++++
4 files changed, 498 insertions(+)
create mode 100644 drivers/mmc/jz_mmc.
create mode 100644 drivers/mmc/jz_mmc.c

diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index fbd13964a084..496b2cba6405 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -332,6 +332,12 @@ config MMC_BCM2835

If unsure, say N.

+config JZ47XX_MMC
+ bool "Ingenic JZ47xx SD/MMC Host Controller support"
+ depends on ARCH_JZ47XX
+ help
+ This selects support for the SD Card Controller on Ingenic JZ47xx SoCs.
+
config MMC_SANDBOX
bool "Sandbox MMC support"
depends on SANDBOX
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 801a26d82192..7892c468f05c 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -40,6 +40,7 @@ obj-$(CONFIG_MMC_SANDBOX) += sandbox_mmc.o
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

# SDHCI
obj-$(CONFIG_MMC_SDHCI) += sdhci.o
diff --git a/drivers/mmc/jz_mmc. b/drivers/mmc/jz_mmc.
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/drivers/mmc/jz_mmc.c b/drivers/mmc/jz_mmc.c
new file mode 100644
index 000000000000..18c1810ff42c
--- /dev/null
+++ b/drivers/mmc/jz_mmc.c
@@ -0,0 +1,491 @@
+/*
+ * Ingenic JZ MMC driver
+ *
+ * Copyright (c) 2013 Imagination Technologies
+ * Author: Paul Burton <***@imgtec.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <mmc.h>
+#include <asm/io.h>
+#include <asm/unaligned.h>
+#include <errno.h>
+#include <mach/jz4780.h>
+
+/* Registers */
+#define MSC_STRPCL 0x000
+#define MSC_STAT 0x004
+#define MSC_CLKRT 0x008
+#define MSC_CMDAT 0x00c
+#define MSC_RESTO 0x010
+#define MSC_RDTO 0x014
+#define MSC_BLKLEN 0x018
+#define MSC_NOB 0x01c
+#define MSC_SNOB 0x020
+#define MSC_IMASK 0x024
+#define MSC_IREG 0x028
+#define MSC_CMD 0x02c
+#define MSC_ARG 0x030
+#define MSC_RES 0x034
+#define MSC_RXFIFO 0x038
+#define MSC_TXFIFO 0x03c
+#define MSC_LPM 0x040
+#define MSC_DMAC 0x044
+#define MSC_DMANDA 0x048
+#define MSC_DMADA 0x04c
+#define MSC_DMALEN 0x050
+#define MSC_DMACMD 0x054
+#define MSC_CTRL2 0x058
+#define MSC_RTCNT 0x05c
+#define MSC_DBG 0x0fc
+
+/* MSC Clock and Control Register (MSC_STRPCL) */
+#define MSC_STRPCL_EXIT_MULTIPLE BIT(7)
+#define MSC_STRPCL_EXIT_TRANSFER BIT(6)
+#define MSC_STRPCL_START_READWAIT BIT(5)
+#define MSC_STRPCL_STOP_READWAIT BIT(4)
+#define MSC_STRPCL_RESET BIT(3)
+#define MSC_STRPCL_START_OP BIT(2)
+#define MSC_STRPCL_CLOCK_CONTROL_STOP BIT(0)
+#define MSC_STRPCL_CLOCK_CONTROL_START BIT(1)
+
+/* MSC Status Register (MSC_STAT) */
+#define MSC_STAT_AUTO_CMD_DONE BIT(31)
+#define MSC_STAT_IS_RESETTING BIT(15)
+#define MSC_STAT_SDIO_INT_ACTIVE BIT(14)
+#define MSC_STAT_PRG_DONE BIT(13)
+#define MSC_STAT_DATA_TRAN_DONE BIT(12)
+#define MSC_STAT_END_CMD_RES BIT(11)
+#define MSC_STAT_DATA_FIFO_AFULL BIT(10)
+#define MSC_STAT_IS_READWAIT BIT(9)
+#define MSC_STAT_CLK_EN BIT(8)
+#define MSC_STAT_DATA_FIFO_FULL BIT(7)
+#define MSC_STAT_DATA_FIFO_EMPTY BIT(6)
+#define MSC_STAT_CRC_RES_ERR BIT(5)
+#define MSC_STAT_CRC_READ_ERROR BIT(4)
+#define MSC_STAT_CRC_WRITE_ERROR BIT(2)
+#define MSC_STAT_CRC_WRITE_ERROR_NOSTS BIT(4)
+#define MSC_STAT_TIME_OUT_RES BIT(1)
+#define MSC_STAT_TIME_OUT_READ BIT(0)
+
+/* MSC Bus Clock Control Register (MSC_CLKRT) */
+#define MSC_CLKRT_CLK_RATE_MASK 0x7
+
+/* MSC Command Sequence Control Register (MSC_CMDAT) */
+#define MSC_CMDAT_IO_ABORT BIT(11)
+#define MSC_CMDAT_BUS_WIDTH_1BIT (0x0 << 9)
+#define MSC_CMDAT_BUS_WIDTH_4BIT (0x2 << 9)
+#define MSC_CMDAT_DMA_EN BIT(8)
+#define MSC_CMDAT_INIT BIT(7)
+#define MSC_CMDAT_BUSY BIT(6)
+#define MSC_CMDAT_STREAM_BLOCK BIT(5)
+#define MSC_CMDAT_WRITE BIT(4)
+#define MSC_CMDAT_DATA_EN BIT(3)
+#define MSC_CMDAT_RESPONSE_MASK (0x7 << 0)
+#define MSC_CMDAT_RESPONSE_NONE (0x0 << 0) /* No response */
+#define MSC_CMDAT_RESPONSE_R1 (0x1 << 0) /* Format R1 and R1b */
+#define MSC_CMDAT_RESPONSE_R2 (0x2 << 0) /* Format R2 */
+#define MSC_CMDAT_RESPONSE_R3 (0x3 << 0) /* Format R3 */
+#define MSC_CMDAT_RESPONSE_R4 (0x4 << 0) /* Format R4 */
+#define MSC_CMDAT_RESPONSE_R5 (0x5 << 0) /* Format R5 */
+#define MSC_CMDAT_RESPONSE_R6 (0x6 << 0) /* Format R6 */
+
+/* MSC Interrupts Mask Register (MSC_IMASK) */
+#define MSC_IMASK_TIME_OUT_RES BIT(9)
+#define MSC_IMASK_TIME_OUT_READ BIT(8)
+#define MSC_IMASK_SDIO BIT(7)
+#define MSC_IMASK_TXFIFO_WR_REQ BIT(6)
+#define MSC_IMASK_RXFIFO_RD_REQ BIT(5)
+#define MSC_IMASK_END_CMD_RES BIT(2)
+#define MSC_IMASK_PRG_DONE BIT(1)
+#define MSC_IMASK_DATA_TRAN_DONE BIT(0)
+
+/* MSC Interrupts Status Register (MSC_IREG) */
+#define MSC_IREG_TIME_OUT_RES BIT(9)
+#define MSC_IREG_TIME_OUT_READ BIT(8)
+#define MSC_IREG_SDIO BIT(7)
+#define MSC_IREG_TXFIFO_WR_REQ BIT(6)
+#define MSC_IREG_RXFIFO_RD_REQ BIT(5)
+#define MSC_IREG_END_CMD_RES BIT(2)
+#define MSC_IREG_PRG_DONE BIT(1)
+#define MSC_IREG_DATA_TRAN_DONE BIT(0)
+
+struct jz_mmc_plat {
+ struct mmc_config cfg;
+ struct mmc mmc;
+};
+
+struct jz_mmc_priv {
+ void __iomem *regs;
+ u32 flags;
+/* priv flags */
+#define JZ_MMC_BUS_WIDTH_MASK 0x3
+#define JZ_MMC_BUS_WIDTH_1 0x0
+#define JZ_MMC_BUS_WIDTH_4 0x2
+#define JZ_MMC_BUS_WIDTH_8 0x3
+#define JZ_MMC_SENT_INIT BIT(2)
+};
+
+static int jz_mmc_clock_rate(void)
+{
+ return 24000000;
+}
+
+static int jz_mmc_send_cmd(struct mmc *mmc, struct jz_mmc_priv *priv,
+ struct mmc_cmd *cmd, struct mmc_data *data)
+{
+ u32 stat, mask, cmdat = 0;
+
+ /* stop the clock */
+ writel(MSC_STRPCL_CLOCK_CONTROL_STOP, priv->regs + MSC_STRPCL);
+ while (readl(priv->regs + MSC_STAT) & MSC_STAT_CLK_EN)
+ ;
+
+ writel(0, priv->regs + MSC_DMAC);
+
+ /* setup command */
+ writel(cmd->cmdidx, priv->regs + MSC_CMD);
+ writel(cmd->cmdarg, priv->regs + MSC_ARG);
+
+ if (data) {
+ /* setup data */
+ cmdat |= MSC_CMDAT_DATA_EN;
+ if (data->flags & MMC_DATA_WRITE)
+ cmdat |= MSC_CMDAT_WRITE;
+
+ writel(data->blocks, priv->regs + MSC_NOB);
+ writel(data->blocksize, priv->regs + MSC_BLKLEN);
+ } else {
+ writel(0, priv->regs + MSC_NOB);
+ writel(0, priv->regs + MSC_BLKLEN);
+ }
+
+ /* setup response */
+ switch (cmd->resp_type) {
+ case MMC_RSP_NONE:
+ break;
+ case MMC_RSP_R1:
+ case MMC_RSP_R1b:
+ cmdat |= MSC_CMDAT_RESPONSE_R1;
+ break;
+ case MMC_RSP_R2:
+ cmdat |= MSC_CMDAT_RESPONSE_R2;
+ break;
+ case MMC_RSP_R3:
+ cmdat |= MSC_CMDAT_RESPONSE_R3;
+ break;
+ default:
+ break;
+ }
+
+ if (cmd->resp_type & MMC_RSP_BUSY)
+ cmdat |= MSC_CMDAT_BUSY;
+
+ /* set init for the first command only */
+ if (!(priv->flags & JZ_MMC_SENT_INIT)) {
+ cmdat |= MSC_CMDAT_INIT;
+ priv->flags |= JZ_MMC_SENT_INIT;
+ }
+
+ cmdat |= (priv->flags & JZ_MMC_BUS_WIDTH_MASK) << 9;
+
+ /* write the data setup */
+ writel(cmdat, priv->regs + MSC_CMDAT);
+
+ /* unmask interrupts */
+ mask = 0xffffffff & ~(MSC_IMASK_END_CMD_RES | MSC_IMASK_TIME_OUT_RES);
+ if (data) {
+ mask &= ~MSC_IMASK_DATA_TRAN_DONE;
+ if (data->flags & MMC_DATA_WRITE) {
+ mask &= ~MSC_IMASK_TXFIFO_WR_REQ;
+ } else {
+ mask &= ~(MSC_IMASK_RXFIFO_RD_REQ |
+ MSC_IMASK_TIME_OUT_READ);
+ }
+ }
+ writel(mask, priv->regs + MSC_IMASK);
+
+ /* clear interrupts */
+ writel(0xffffffff, priv->regs + MSC_IREG);
+
+ /* start the command (& the clock) */
+ writel(MSC_STRPCL_START_OP | MSC_STRPCL_CLOCK_CONTROL_START,
+ priv->regs + MSC_STRPCL);
+
+ /* wait for completion */
+ for (;;) {
+ stat = readl(priv->regs + MSC_IREG);
+ stat &= MSC_IREG_END_CMD_RES | MSC_IREG_TIME_OUT_RES;
+ if (stat)
+ break;
+ mdelay(1);
+ }
+ writel(stat, priv->regs + MSC_IREG);
+ if (stat & MSC_IREG_TIME_OUT_RES)
+ return -ETIMEDOUT;
+
+ if (cmd->resp_type & MMC_RSP_PRESENT) {
+ /* read the response */
+ if (cmd->resp_type & MMC_RSP_136) {
+ u16 a, b, c, i;
+
+ a = readw(priv->regs + MSC_RES);
+ for (i = 0; i < 4; i++) {
+ b = readw(priv->regs + MSC_RES);
+ c = readw(priv->regs + MSC_RES);
+ cmd->response[i] =
+ (a << 24) | (b << 8) | (c >> 8);
+ a = c;
+ }
+ } else {
+ cmd->response[0] = readw(priv->regs + MSC_RES) << 24;
+ cmd->response[0] |= readw(priv->regs + MSC_RES) << 8;
+ cmd->response[0] |= readw(priv->regs + MSC_RES) & 0xff;
+ }
+ }
+
+ if (data && (data->flags & MMC_DATA_WRITE)) {
+ /* write the data */
+ int sz = DIV_ROUND_UP(data->blocks * data->blocksize, 4);
+ const void *buf = data->src;
+
+ while (sz--) {
+ u32 val = get_unaligned_le32(buf);
+
+ while (!(readl(priv->regs + MSC_IREG) &
+ MSC_IREG_TXFIFO_WR_REQ))
+ ;
+ writel(val, priv->regs + MSC_TXFIFO);
+ buf += 4;
+ }
+ } else if (data && (data->flags & MMC_DATA_READ)) {
+ /* read the data */
+ int sz = data->blocks * data->blocksize;
+ void *buf = data->dest;
+
+ do {
+ stat = readl(priv->regs + MSC_STAT);
+
+ if (stat & MSC_STAT_TIME_OUT_READ)
+ return -ETIMEDOUT;
+ if (stat & MSC_STAT_CRC_READ_ERROR)
+ return -EINVAL;
+ if (stat & MSC_STAT_DATA_FIFO_EMPTY) {
+ udelay(10);
+ continue;
+ }
+ do {
+ u32 val = readl(priv->regs + MSC_RXFIFO);
+
+ if (sz == 1)
+ *(u8 *)buf = (u8)val;
+ else if (sz == 2)
+ put_unaligned_le16(val, buf);
+ else if (sz >= 4)
+ put_unaligned_le32(val, buf);
+ buf += 4;
+ sz -= 4;
+ stat = readl(priv->regs + MSC_STAT);
+ } while (!(stat & MSC_STAT_DATA_FIFO_EMPTY));
+ } while (!(stat & MSC_STAT_DATA_TRAN_DONE));
+ }
+
+ return 0;
+}
+
+static int jz_mmc_set_ios(struct mmc *mmc, struct jz_mmc_priv *priv)
+{
+ u32 real_rate = jz_mmc_clock_rate();
+ u8 clk_div = 0;
+
+ /* calculate clock divide */
+ while ((real_rate > mmc->clock) && (clk_div < 7)) {
+ real_rate >>= 1;
+ clk_div++;
+ }
+ writel(clk_div & MSC_CLKRT_CLK_RATE_MASK, priv->regs + MSC_CLKRT);
+
+ /* set the bus width for the next command */
+ priv->flags &= ~JZ_MMC_BUS_WIDTH_MASK;
+ if (mmc->bus_width == 8)
+ priv->flags |= JZ_MMC_BUS_WIDTH_8;
+ else if (mmc->bus_width == 4)
+ priv->flags |= JZ_MMC_BUS_WIDTH_4;
+ else
+ priv->flags |= JZ_MMC_BUS_WIDTH_1;
+
+ return 0;
+}
+
+static int jz_mmc_core_init(struct mmc *mmc)
+{
+ struct jz_mmc_priv *priv = mmc->priv;
+ unsigned int timeout = 1000;
+ u32 status;
+
+ /* Reset */
+ writel(MSC_STRPCL_RESET, priv->regs + MSC_STRPCL);
+ udelay(10);
+ do {
+ status = readl(priv->regs + MSC_STAT);
+ } while (status & MSC_STAT_IS_RESETTING && --timeout);
+
+ if (!timeout) {
+ printf("jz_mmc: timeout on reset\n");
+ return -ETIMEDOUT;
+ }
+
+ /* Maximum timeouts */
+ writel(0xffff, priv->regs + MSC_RESTO);
+ writel(0xffffffff, priv->regs + MSC_RDTO);
+
+ /* Enable low power mode */
+ writel(0x1, priv->regs + MSC_LPM);
+
+ return 0;
+}
+
+#if !CONFIG_IS_ENABLED(DM_MMC)
+
+static int jz_mmc_legacy_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
+ struct mmc_data *data)
+{
+ struct jz_mmc_priv *priv = mmc->priv;
+
+ return jz_mmc_send_cmd(mmc, priv, cmd, data);
+}
+
+static int jz_mmc_legacy_set_ios(struct mmc *mmc)
+{
+ struct jz_mmc_priv *priv = mmc->priv;
+
+ return jz_mmc_set_ios(mmc, priv);
+};
+
+static const struct mmc_ops jz_msc_ops = {
+ .send_cmd = jz_mmc_legacy_send_cmd,
+ .set_ios = jz_mmc_legacy_set_ios,
+ .init = jz_mmc_core_init,
+};
+
+static struct jz_mmc_priv jz_mmc_priv_static;
+static struct jz_mmc_plat jz_mmc_plat_static = {
+ .cfg = {
+ .name = "MSC",
+ .ops = &jz_msc_ops,
+
+ .voltages = MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30 |
+ MMC_VDD_30_31 | MMC_VDD_31_32 | MMC_VDD_32_33 |
+ MMC_VDD_33_34 | MMC_VDD_34_35 | MMC_VDD_35_36,
+ .host_caps = MMC_MODE_4BIT | MMC_MODE_HS_52MHz | MMC_MODE_HS,
+
+ .f_min = 375000,
+ .f_max = 48000000,
+ .b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT,
+ },
+};
+
+int jz_mmc_init(void __iomem *base)
+{
+ struct mmc *mmc;
+
+ jz_mmc_priv_static.regs = base;
+
+ mmc = mmc_create(&jz_mmc_plat_static.cfg, &jz_mmc_priv_static);
+
+ return mmc ? 0 : -ENODEV;
+}
+
+#else /* CONFIG_DM_MMC */
+
+#include <dm.h>
+DECLARE_GLOBAL_DATA_PTR;
+
+static int jz_mmc_dm_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
+ struct mmc_data *data)
+{
+ struct jz_mmc_priv *priv = dev_get_priv(dev);
+ struct mmc *mmc = mmc_get_mmc_dev(dev);
+
+ return jz_mmc_send_cmd(mmc, priv, cmd, data);
+}
+
+static int jz_mmc_dm_set_ios(struct udevice *dev)
+{
+ struct jz_mmc_priv *priv = dev_get_priv(dev);
+ struct mmc *mmc = mmc_get_mmc_dev(dev);
+
+ return jz_mmc_set_ios(mmc, priv);
+};
+
+static const struct dm_mmc_ops jz_msc_ops = {
+ .send_cmd = jz_mmc_dm_send_cmd,
+ .set_ios = jz_mmc_dm_set_ios,
+};
+
+static int jz_mmc_ofdata_to_platdata(struct udevice *dev)
+{
+ struct jz_mmc_priv *priv = dev_get_priv(dev);
+ struct jz_mmc_plat *plat = dev_get_platdata(dev);
+ struct mmc_config *cfg;
+ int ret;
+
+ priv->regs = map_physmem(devfdt_get_addr(dev), 0x100, MAP_NOCACHE);
+ cfg = &plat->cfg;
+
+ cfg->name = "MSC";
+ cfg->host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS;
+
+ ret = mmc_of_parse(dev, cfg);
+ if (ret < 0) {
+ dev_err(dev, "failed to parse host caps\n");
+ return ret;
+ }
+
+ cfg->f_min = 400000;
+ cfg->f_max = 52000000;
+
+ cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
+ cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
+
+ return 0;
+}
+
+static int jz_mmc_bind(struct udevice *dev)
+{
+ struct jz_mmc_plat *plat = dev_get_platdata(dev);
+
+ return mmc_bind(dev, &plat->mmc, &plat->cfg);
+}
+
+static int jz_mmc_probe(struct udevice *dev)
+{
+ struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+ struct jz_mmc_priv *priv = dev_get_priv(dev);
+ struct jz_mmc_plat *plat = dev_get_platdata(dev);
+
+ plat->mmc.priv = priv;
+ upriv->mmc = &plat->mmc;
+ return jz_mmc_core_init(&plat->mmc);
+}
+
+static const struct udevice_id jz_mmc_ids[] = {
+ { .compatible = "ingenic,jz4780-mmc" },
+ { }
+};
+
+U_BOOT_DRIVER(jz_mmc_drv) = {
+ .name = "jz_mmc",
+ .id = UCLASS_MMC,
+ .of_match = jz_mmc_ids,
+ .ofdata_to_platdata = jz_mmc_ofdata_to_platdata,
+ .bind = jz_mmc_bind,
+ .probe = jz_mmc_probe,
+ .priv_auto_alloc_size = sizeof(struct jz_mmc_priv),
+ .platdata_auto_alloc_size = sizeof(struct jz_mmc_plat),
+ .ops = &jz_msc_ops,
+};
+#endif /* CONFIG_DM_MMC */
--
2.20.0.rc2
Ezequiel Garcia
2018-12-10 20:36:02 UTC
Permalink
From: Paul Burton <***@imgtec.com>

Add support for the Creator CI20 platform based on the JZ4780 SoC.

Cc: Daniel Schwierzeck <***@gmail.com>
Signed-off-by: Paul Burton <***@imgtec.com>
Signed-off-by: Marek Vasut <***@gmail.com>
Signed-off-by: Ezequiel Garcia <***@collabora.com>
---
arch/mips/dts/Makefile | 1 +
arch/mips/dts/ci20.dts | 120 +++++++++++
arch/mips/mach-jz47xx/Kconfig | 11 +
board/imgtec/ci20/Kconfig | 15 ++
board/imgtec/ci20/Makefile | 5 +
board/imgtec/ci20/README | 10 +
board/imgtec/ci20/ci20.c | 365 ++++++++++++++++++++++++++++++++++
configs/ci20_defconfig | 47 +++++
include/configs/ci20.h | 74 +++++++
9 files changed, 648 insertions(+)
create mode 100644 arch/mips/dts/ci20.dts
create mode 100644 board/imgtec/ci20/Kconfig
create mode 100644 board/imgtec/ci20/Makefile
create mode 100644 board/imgtec/ci20/README
create mode 100644 board/imgtec/ci20/ci20.c
create mode 100644 configs/ci20_defconfig
create mode 100644 include/configs/ci20.h

diff --git a/arch/mips/dts/Makefile b/arch/mips/dts/Makefile
index b447141f8717..647d2bf0d53b 100644
--- a/arch/mips/dts/Makefile
+++ b/arch/mips/dts/Makefile
@@ -16,6 +16,7 @@ dtb-$(CONFIG_BOARD_NETGEAR_CG3100D) += netgear,cg3100d.dtb
dtb-$(CONFIG_BOARD_NETGEAR_DGND3700V2) += netgear,dgnd3700v2.dtb
dtb-$(CONFIG_BOARD_SAGEM_FAST1704) += sagem,***@st1704.dtb
dtb-$(CONFIG_BOARD_TPLINK_WDR4300) += tplink_wdr4300.dtb
+dtb-$(CONFIG_TARGET_JZ4780_CI20) += ci20.dtb

targets += $(dtb-y)

diff --git a/arch/mips/dts/ci20.dts b/arch/mips/dts/ci20.dts
new file mode 100644
index 000000000000..934d9e96d24d
--- /dev/null
+++ b/arch/mips/dts/ci20.dts
@@ -0,0 +1,120 @@
+/dts-v1/;
+
+#include "jz4780.dtsi"
+
+/ {
+ compatible = "img,ci20", "ingenic,jz4780";
+
+ aliases {
+ serial0 = &uart0;
+ serial1 = &uart1;
+ serial3 = &uart3;
+ serial4 = &uart4;
+ };
+
+ chosen {
+ stdout-path = "serial4:115200n8";
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x0 0x10000000
+ 0x30000000 0x30000000>;
+ };
+};
+
+&ext {
+ clock-frequency = <48000000>;
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&uart1 {
+ status = "okay";
+};
+
+&uart3 {
+ status = "okay";
+};
+
+&uart4 {
+ status = "okay";
+};
+
+&nemc {
+ status = "okay";
+
+ nandc: nand-***@1 {
+ compatible = "ingenic,jz4780-nand";
+ reg = <1 0 0x1000000>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ingenic,bch-controller = <&bch>;
+
+ ingenic,nemc-tAS = <10>;
+ ingenic,nemc-tAH = <5>;
+ ingenic,nemc-tBP = <10>;
+ ingenic,nemc-tAW = <15>;
+ ingenic,nemc-tSTRV = <100>;
+
+ ***@1 {
+ reg = <1>;
+
+ nand-ecc-step-size = <1024>;
+ nand-ecc-strength = <24>;
+ nand-ecc-mode = "hw";
+ nand-on-flash-bbt;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ ***@0 {
+ label = "u-boot-spl";
+ reg = <0x0 0x0 0x0 0x800000>;
+ };
+
+ ***@0x800000 {
+ label = "u-boot";
+ reg = <0x0 0x800000 0x0 0x200000>;
+ };
+
+ ***@0xa00000 {
+ label = "u-boot-env";
+ reg = <0x0 0xa00000 0x0 0x200000>;
+ };
+
+ ***@0xc00000 {
+ label = "boot";
+ reg = <0x0 0xc00000 0x0 0x4000000>;
+ };
+
+ ***@0x8c00000 {
+ label = "system";
+ reg = <0x0 0x4c00000 0x1 0xfb400000>;
+ };
+ };
+ };
+ };
+};
+
+&bch {
+ status = "okay";
+};
+
+&mmc0 {
+ bus-width = <4>;
+ max-frequency = <50000000>;
+ status = "okay";
+};
+
+&mmc1 {
+ bus-width = <4>;
+ max-frequency = <50000000>;
+ status = "okay";
+};
diff --git a/arch/mips/mach-jz47xx/Kconfig b/arch/mips/mach-jz47xx/Kconfig
index cd6944cfc252..dcaac0162866 100644
--- a/arch/mips/mach-jz47xx/Kconfig
+++ b/arch/mips/mach-jz47xx/Kconfig
@@ -12,4 +12,15 @@ config SOC_JZ4780
help
Support for Ingenic JZ4780 family SoCs.

+choice
+ prompt "Board select"
+
+config TARGET_JZ4780_CI20
+ bool "Creator CI20 Reference Board"
+ select SOC_JZ4780
+
+endchoice
+
+source "board/imgtec/ci20/Kconfig"
+
endmenu
diff --git a/board/imgtec/ci20/Kconfig b/board/imgtec/ci20/Kconfig
new file mode 100644
index 000000000000..82bf65d64f1e
--- /dev/null
+++ b/board/imgtec/ci20/Kconfig
@@ -0,0 +1,15 @@
+if TARGET_JZ4780_CI20
+
+config SYS_BOARD
+ default "ci20"
+
+config SYS_VENDOR
+ default "imgtec"
+
+config SYS_CONFIG_NAME
+ default "ci20"
+
+config SYS_TEXT_BASE
+ default 0x80000000
+
+endif
diff --git a/board/imgtec/ci20/Makefile b/board/imgtec/ci20/Makefile
new file mode 100644
index 000000000000..8c00081e660b
--- /dev/null
+++ b/board/imgtec/ci20/Makefile
@@ -0,0 +1,5 @@
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-y := ci20.o
diff --git a/board/imgtec/ci20/README b/board/imgtec/ci20/README
new file mode 100644
index 000000000000..c757d41c7640
--- /dev/null
+++ b/board/imgtec/ci20/README
@@ -0,0 +1,10 @@
+CI20 U-Boot
+
+Installation to an SD card:
+ Repartition your card with an MBR such that the first partition starts at an
+ offset of no less than 270KB. Then install U-Boot SPL & the full U-Boot image
+ to the card like so:
+
+ dd if=spl/u-boot-spl.bin of=/dev/sdX obs=512 seek=1
+ dd if=u-boot.img of=/dev/sdX obs=1K seek=14
+ sync
diff --git a/board/imgtec/ci20/ci20.c b/board/imgtec/ci20/ci20.c
new file mode 100644
index 000000000000..8e5b11e2679a
--- /dev/null
+++ b/board/imgtec/ci20/ci20.c
@@ -0,0 +1,365 @@
+/*
+ * CI20 setup code
+ *
+ * Copyright (c) 2013 Imagination Technologies
+ * Author: Paul Burton <***@imgtec.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <environment.h>
+#include <net.h>
+#include <netdev.h>
+#include <asm/io.h>
+#include <asm/gpio.h>
+#include <mach/jz4780.h>
+#include <mach/jz4780_dram.h>
+
+#define JZ_GPIO(bank, pin) ((32 * (bank)) + (pin))
+
+#define CONFIG_JTAG
+
+struct ci20_otp {
+ u32 serial_number;
+ u32 date;
+ u8 manufacturer[2];
+ u8 mac[6];
+} __packed;
+
+static void ci20_mux_eth(void)
+{
+ void __iomem *gpio_regs = (void __iomem *)GPIO_BASE;
+
+#ifdef CONFIG_NAND
+ /* setup pins (some already setup for NAND) */
+ writel(0x04030000, gpio_regs + GPIO_PXINTC(0));
+ writel(0x04030000, gpio_regs + GPIO_PXMASKC(0));
+ writel(0x04030000, gpio_regs + GPIO_PXPAT1C(0));
+ writel(0x04030000, gpio_regs + GPIO_PXPAT0C(0));
+ writel(0x04030000, gpio_regs + GPIO_PXPENS(0));
+#else
+ /* setup pins (as above +NAND CS +RD/WE +SDx +SAx) */
+ writel(0x0dff00ff, gpio_regs + GPIO_PXINTC(0));
+ writel(0x0dff00ff, gpio_regs + GPIO_PXMASKC(0));
+ writel(0x0dff00ff, gpio_regs + GPIO_PXPAT1C(0));
+ writel(0x0dff00ff, gpio_regs + GPIO_PXPAT0C(0));
+ writel(0x0dff00ff, gpio_regs + GPIO_PXPENS(0));
+ writel(0x00000003, gpio_regs + GPIO_PXINTC(1));
+ writel(0x00000003, gpio_regs + GPIO_PXMASKC(1));
+ writel(0x00000003, gpio_regs + GPIO_PXPAT1C(1));
+ writel(0x00000003, gpio_regs + GPIO_PXPAT0C(1));
+ writel(0x00000003, gpio_regs + GPIO_PXPENS(1));
+#endif
+}
+
+static void ci20_mux_jtag(void)
+{
+#ifdef CONFIG_JTAG
+ void __iomem *gpio_regs = (void __iomem *)GPIO_BASE;
+
+ /* enable JTAG */
+ writel(3 << 30, gpio_regs + GPIO_PXINTC(0));
+ writel(3 << 30, gpio_regs + GPIO_PXMASKC(0));
+ writel(3 << 30, gpio_regs + GPIO_PXPAT1C(0));
+ writel(3 << 30, gpio_regs + GPIO_PXPAT0C(0));
+#endif
+}
+
+static void ci20_mux_mmc(void)
+{
+ void __iomem *gpio_regs = (void __iomem *)GPIO_BASE;
+
+ /* setup MSC1 pins */
+ writel(0x30f00000, gpio_regs + GPIO_PXINTC(4));
+ writel(0x30f00000, gpio_regs + GPIO_PXMASKC(4));
+ writel(0x30f00000, gpio_regs + GPIO_PXPAT1C(4));
+ writel(0x30f00000, gpio_regs + GPIO_PXPAT0C(4));
+ writel(0x30f00000, gpio_regs + GPIO_PXPENC(4));
+ jz4780_clk_ungate_mmc();
+}
+
+static void ci20_mux_nand(void)
+{
+ void __iomem *gpio_regs = (void __iomem *)GPIO_BASE;
+
+ /* setup pins */
+ writel(0x002c00ff, gpio_regs + GPIO_PXINTC(0));
+ writel(0x002c00ff, gpio_regs + GPIO_PXMASKC(0));
+ writel(0x002c00ff, gpio_regs + GPIO_PXPAT1C(0));
+ writel(0x002c00ff, gpio_regs + GPIO_PXPAT0C(0));
+ writel(0x002c00ff, gpio_regs + GPIO_PXPENS(0));
+ writel(0x00000003, gpio_regs + GPIO_PXINTC(1));
+ writel(0x00000003, gpio_regs + GPIO_PXMASKC(1));
+ writel(0x00000003, gpio_regs + GPIO_PXPAT1C(1));
+ writel(0x00000003, gpio_regs + GPIO_PXPAT0C(1));
+ writel(0x00000003, gpio_regs + GPIO_PXPENS(1));
+
+ /* FRB0_N */
+ gpio_direction_input(32 * 0 + 20);
+ writel(20, gpio_regs + GPIO_PXPENS(0));
+
+ /* disable write protect */
+ gpio_direction_output(JZ_GPIO(5, 22), 1);
+}
+
+static void ci20_mux_uart(void)
+{
+ void __iomem *gpio_regs = (void __iomem *)GPIO_BASE;
+
+ /* UART0 */
+ writel(0x9, gpio_regs + GPIO_PXINTC(5));
+ writel(0x9, gpio_regs + GPIO_PXMASKC(5));
+ writel(0x9, gpio_regs + GPIO_PXPAT1C(5));
+ writel(0x9, gpio_regs + GPIO_PXPAT0C(5));
+ writel(0x9, gpio_regs + GPIO_PXPENC(5));
+ jz4780_clk_ungate_uart(0);
+
+ /* UART 1 and 2 */
+ jz4780_clk_ungate_uart(1);
+ jz4780_clk_ungate_uart(2);
+
+#ifndef CONFIG_JTAG
+ /* UART3 */
+ writel(1 << 12, gpio_regs + GPIO_PXINTC(3));
+ writel(1 << 12, gpio_regs + GPIO_PXMASKS(3));
+ writel(1 << 12, gpio_regs + GPIO_PXPAT1S(3));
+ writel(1 << 12, gpio_regs + GPIO_PXPAT0C(3));
+ writel(3 << 30, gpio_regs + GPIO_PXINTC(0));
+ writel(3 << 30, gpio_regs + GPIO_PXMASKC(0));
+ writel(3 << 30, gpio_regs + GPIO_PXPAT1C(0));
+ writel(1 << 30, gpio_regs + GPIO_PXPAT0C(0));
+ writel(1 << 31, gpio_regs + GPIO_PXPAT0S(0));
+ jz4780_clk_ungate_uart(3);
+#endif
+
+ /* UART4 */
+ writel(0x100400, gpio_regs + GPIO_PXINTC(2));
+ writel(0x100400, gpio_regs + GPIO_PXMASKC(2));
+ writel(0x100400, gpio_regs + GPIO_PXPAT1S(2));
+ writel(0x100400, gpio_regs + GPIO_PXPAT0C(2));
+ writel(0x100400, gpio_regs + GPIO_PXPENC(2));
+ jz4780_clk_ungate_uart(4);
+}
+
+int board_early_init_f(void)
+{
+ ci20_mux_jtag();
+ ci20_mux_uart();
+
+ ci20_mux_eth();
+ ci20_mux_mmc();
+ ci20_mux_nand();
+
+ /* SYS_POWER_IND high (LED blue, VBUS on) */
+ gpio_direction_output(JZ_GPIO(5, 15), 1);
+
+ /* LEDs off */
+ gpio_direction_output(JZ_GPIO(2, 0), 0);
+ gpio_direction_output(JZ_GPIO(2, 1), 0);
+ gpio_direction_output(JZ_GPIO(2, 2), 0);
+ gpio_direction_output(JZ_GPIO(2, 3), 0);
+
+ return 0;
+}
+
+#ifndef CONFIG_SPL_BUILD
+int misc_init_r(void)
+{
+ const u32 efuse_clk = jz4780_clk_get_efuse_clk();
+ struct ci20_otp otp;
+ char manufacturer[3];
+
+ /* Read the board OTP data */
+ jz4780_efuse_init(efuse_clk);
+ jz4780_efuse_read(0x18, 16, (u8 *)&otp);
+
+ /* Set MAC address */
+ if (!is_valid_ethaddr(otp.mac)) {
+ /* no MAC assigned, generate one from the unique chip ID */
+ jz4780_efuse_read(0x8, 4, &otp.mac[0]);
+ jz4780_efuse_read(0x12, 2, &otp.mac[4]);
+ otp.mac[0] = (otp.mac[0] | 0x02) & ~0x01;
+ }
+ eth_env_set_enetaddr("ethaddr", otp.mac);
+
+ /* Put other board information into the environment */
+ env_set_ulong("serial#", otp.serial_number);
+ env_set_ulong("board_date", otp.date);
+ manufacturer[0] = otp.manufacturer[0];
+ manufacturer[1] = otp.manufacturer[1];
+ manufacturer[2] = 0;
+ env_set("board_mfr", manufacturer);
+
+ return 0;
+}
+
+#ifdef CONFIG_DRIVER_DM9000
+int board_eth_init(bd_t *bis)
+{
+ /* Enable clock */
+ jz4780_clk_ungate_ethernet();
+
+ /* Enable power (PB25) */
+ gpio_direction_output(JZ_GPIO(1, 25), 1);
+
+ /* Reset (PF12) */
+ mdelay(10);
+ gpio_direction_output(JZ_GPIO(5, 12), 0);
+ mdelay(10);
+ gpio_direction_output(JZ_GPIO(5, 12), 1);
+ mdelay(10);
+
+ return dm9000_initialize(bis);
+}
+#endif /* CONFIG_DRIVER_DM9000 */
+#endif
+
+static u8 ci20_revision(void)
+{
+ void __iomem *gpio_regs = (void __iomem *)GPIO_BASE;
+ int val;
+
+ gpio_direction_input(82);
+ gpio_direction_input(83);
+
+ /* Enable pullups */
+ writel(BIT(18) | BIT(19), gpio_regs + GPIO_PXPENC(2));
+
+ /* Read PC18/19 for version */
+ val = (!!gpio_get_value(82)) | ((!!gpio_get_value(83)) << 1);
+
+ if (val == 3) /* Rev 1 boards had no pulldowns - giving 3 */
+ return 1;
+ if (val == 1) /* Rev 2 boards pulldown port C bit 18 giving 1 */
+ return 2;
+
+ return 0;
+}
+
+int dram_init(void)
+{
+ gd->ram_size = sdram_size(0) + sdram_size(1);
+ return 0;
+}
+
+/* U-Boot common routines */
+int checkboard(void)
+{
+ printf("Board: Creator CI20 (rev.%d)\n", ci20_revision());
+ return 0;
+}
+
+#ifdef CONFIG_SPL_BUILD
+
+#if defined(CONFIG_SPL_MMC_SUPPORT)
+int board_mmc_init(bd_t *bd)
+{
+ ci20_mux_mmc();
+ return jz_mmc_init((void __iomem *)MSC0_BASE);
+}
+#endif
+
+static const struct jz4780_ddr_config K4B2G0846Q_48_config = {
+ .timing = {
+ (4 << DDRC_TIMING1_TRTP_BIT) | (13 << DDRC_TIMING1_TWTR_BIT) |
+ (6 << DDRC_TIMING1_TWR_BIT) | (5 << DDRC_TIMING1_TWL_BIT),
+
+
+ (4 << DDRC_TIMING2_TCCD_BIT) | (15 << DDRC_TIMING2_TRAS_BIT) |
+ (6 << DDRC_TIMING2_TRCD_BIT) | (6 << DDRC_TIMING2_TRL_BIT),
+
+ (4 << DDRC_TIMING3_ONUM) | (7 << DDRC_TIMING3_TCKSRE_BIT) |
+ (6 << DDRC_TIMING3_TRP_BIT) | (4 << DDRC_TIMING3_TRRD_BIT) |
+ (21 << DDRC_TIMING3_TRC_BIT),
+
+ (31 << DDRC_TIMING4_TRFC_BIT) | (1 << DDRC_TIMING4_TRWCOV_BIT) |
+ (4 << DDRC_TIMING4_TCKE_BIT) | (9 << DDRC_TIMING4_TMINSR_BIT) |
+ (8 << DDRC_TIMING4_TXP_BIT) | (3 << DDRC_TIMING4_TMRD_BIT),
+
+ (8 << DDRC_TIMING5_TRTW_BIT) | (4 << DDRC_TIMING5_TRDLAT_BIT) |
+ (4 << DDRC_TIMING5_TWDLAT_BIT),
+
+ (25 << DDRC_TIMING6_TXSRD_BIT) | (12 << DDRC_TIMING6_TFAW_BIT) |
+ (2 << DDRC_TIMING6_TCFGW_BIT) | (2 << DDRC_TIMING6_TCFGR_BIT),
+ },
+
+ /* PHY */
+ /* Mode Register 0 */
+ .mr0 = 0x420,
+#ifdef SDRAM_DISABLE_DLL
+ .mr1 = (DDR3_MR1_DIC_7 | DDR3_MR1_RTT_DIS | DDR3_MR1_DLL_DISABLE),
+#else
+ .mr1 = (DDR3_MR1_DIC_7 | DDR3_MR1_RTT_DIS),
+#endif
+
+ .ptr0 = 0x002000d4,
+ .ptr1 = 0x02230d40,
+ .ptr2 = 0x04013880,
+
+ .dtpr0 = 0x2a8f6690,
+ .dtpr1 = 0x00400860,
+ .dtpr2 = 0x10042a00,
+
+ .pullup = 0x0b,
+ .pulldn = 0x0b,
+};
+
+static const struct jz4780_ddr_config H5TQ2G83CFR_48_config = {
+ .timing = {
+ (4 << DDRC_TIMING1_TRTP_BIT) | (13 << DDRC_TIMING1_TWTR_BIT) |
+ (6 << DDRC_TIMING1_TWR_BIT) | (5 << DDRC_TIMING1_TWL_BIT),
+
+ (4 << DDRC_TIMING2_TCCD_BIT) | (16 << DDRC_TIMING2_TRAS_BIT) |
+ (6 << DDRC_TIMING2_TRCD_BIT) | (6 << DDRC_TIMING2_TRL_BIT),
+
+ (4 << DDRC_TIMING3_ONUM) | (7 << DDRC_TIMING3_TCKSRE_BIT) |
+ (6 << DDRC_TIMING3_TRP_BIT) | (4 << DDRC_TIMING3_TRRD_BIT) |
+ (22 << DDRC_TIMING3_TRC_BIT),
+
+ (42 << DDRC_TIMING4_TRFC_BIT) | (1 << DDRC_TIMING4_TRWCOV_BIT) |
+ (4 << DDRC_TIMING4_TCKE_BIT) | (7 << DDRC_TIMING4_TMINSR_BIT) |
+ (3 << DDRC_TIMING4_TXP_BIT) | (3 << DDRC_TIMING4_TMRD_BIT),
+
+ (8 << DDRC_TIMING5_TRTW_BIT) | (4 << DDRC_TIMING5_TRDLAT_BIT) |
+ (4 << DDRC_TIMING5_TWDLAT_BIT),
+
+ (25 << DDRC_TIMING6_TXSRD_BIT) | (20 << DDRC_TIMING6_TFAW_BIT) |
+ (2 << DDRC_TIMING6_TCFGW_BIT) | (2 << DDRC_TIMING6_TCFGR_BIT),
+ },
+
+ /* PHY */
+ /* Mode Register 0 */
+ .mr0 = 0x420,
+#ifdef SDRAM_DISABLE_DLL
+ .mr1 = (DDR3_MR1_DIC_7 | DDR3_MR1_RTT_DIS | DDR3_MR1_DLL_DISABLE),
+#else
+ .mr1 = (DDR3_MR1_DIC_7 | DDR3_MR1_RTT_DIS),
+#endif
+
+ .ptr0 = 0x002000d4,
+ .ptr1 = 0x02d30d40,
+ .ptr2 = 0x04013880,
+
+ .dtpr0 = 0x2c906690,
+ .dtpr1 = 0x005608a0,
+ .dtpr2 = 0x10042a00,
+
+ .pullup = 0x0e,
+ .pulldn = 0x0e,
+};
+
+#if (CONFIG_SYS_MHZ != 1200)
+#error No DDR configuration for CPU speed
+#endif
+
+const struct jz4780_ddr_config *jz4780_get_ddr_config(void)
+{
+ const int board_revision = ci20_revision();
+
+ if (board_revision == 2)
+ return &K4B2G0846Q_48_config;
+ else /* Fall back to H5TQ2G83CFR RAM */
+ return &H5TQ2G83CFR_48_config;
+}
+#endif
diff --git a/configs/ci20_defconfig b/configs/ci20_defconfig
new file mode 100644
index 000000000000..df1a1846667e
--- /dev/null
+++ b/configs/ci20_defconfig
@@ -0,0 +1,47 @@
+CONFIG_MIPS=y
+CONFIG_SPL_LDSCRIPT="arch/mips/mach-jz47xx/jz4780/u-boot-spl.lds"
+CONFIG_SYS_TEXT_BASE=0x80010000
+CONFIG_SPL_GPIO_SUPPORT=y
+CONFIG_SPL_LIBGENERIC_SUPPORT=y
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_SPL_MMC_SUPPORT=y
+CONFIG_SPL=y
+CONFIG_ARCH_JZ47XX=y
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_FIT=y
+CONFIG_USE_BOOTARGS=y
+CONFIG_BOOTARGS="console=ttyS4,115200 rw rootwait root=/dev/mmcblk0p1"
+CONFIG_USE_BOOTCOMMAND=y
+CONFIG_BOOTCOMMAND="ext4load mmc 0:1 0x88000000 /boot/uImage; bootm 0x88000000"
+CONFIG_DISPLAY_CPUINFO=y
+CONFIG_BOARD_EARLY_INIT_F=y
+# CONFIG_SPL_BANNER_PRINT is not set
+# CONFIG_TPL_BANNER_PRINT is not set
+CONFIG_HUSH_PARSER=y
+# CONFIG_CMD_FLASH is not set
+CONFIG_CMD_MMC=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_FAT=y
+# CONFIG_SPL_DOS_PARTITION is not set
+CONFIG_OF_EMBED=y
+CONFIG_DEFAULT_DEVICE_TREE="ci20"
+CONFIG_ENV_IS_IN_MMC=y
+# CONFIG_DM_WARN is not set
+# CONFIG_DM_DEVICE_REMOVE is not set
+CONFIG_JZ4780_EFUSE=y
+CONFIG_MMC=y
+CONFIG_MMC_BROKEN_CD=y
+CONFIG_DM_MMC=y
+# CONFIG_MMC_HW_PARTITIONING is not set
+CONFIG_MMC_IO_VOLTAGE=y
+CONFIG_MMC_UHS_SUPPORT=y
+CONFIG_MMC_HS400_SUPPORT=y
+# CONFIG_MMC_VERBOSE is not set
+CONFIG_SPL_MMC_TINY=y
+CONFIG_JZ47XX_MMC=y
+CONFIG_DM_SERIAL=y
+CONFIG_SYS_NS16550=y
+CONFIG_USE_TINY_PRINTF=y
+CONFIG_SPL_TINY_MEMSET=y
+CONFIG_LZO=y
diff --git a/include/configs/ci20.h b/include/configs/ci20.h
new file mode 100644
index 000000000000..e600f9dfe0c0
--- /dev/null
+++ b/include/configs/ci20.h
@@ -0,0 +1,74 @@
+/*
+ * CI20 configuration
+ *
+ * Copyright (c) 2013 Imagination Technologies
+ * Author: Paul Burton <***@imgtec.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef __CONFIG_CI20_H__
+#define __CONFIG_CI20_H__
+
+#define CONFIG_SKIP_LOWLEVEL_INIT
+#define CONFIG_MISC_INIT_R
+
+/* Ingenic JZ4780 clock configuration. */
+#define CONFIG_SYS_HZ 1000
+#define CONFIG_SYS_MHZ 1200
+#define CONFIG_SYS_MIPS_TIMER_FREQ (CONFIG_SYS_MHZ * 1000000)
+
+/* Memory configuration */
+#define CONFIG_SYS_MONITOR_LEN (512 * 1024)
+#define CONFIG_SYS_MALLOC_LEN (64 * 1024 * 1024)
+#define CONFIG_SYS_BOOTPARAMS_LEN (128 * 1024)
+
+#define CONFIG_SYS_SDRAM_BASE 0x80000000 /* cached (KSEG0) address */
+#define CONFIG_SYS_INIT_SP_OFFSET 0x400000
+#define CONFIG_SYS_LOAD_ADDR 0x81000000
+#define CONFIG_LOADADDR CONFIG_SYS_LOAD_ADDR
+#define CONFIG_SYS_MEMTEST_START 0x80000000
+#define CONFIG_SYS_MEMTEST_END 0x88000000
+
+#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE
+
+/* NS16550-ish UARTs */
+#define CONFIG_SYS_NS16550_CLK 48000000
+#define CONFIG_SYS_CONSOLE_IS_IN_ENV
+
+/* Ethernet: davicom DM9000 */
+#define CONFIG_DRIVER_DM9000 1
+#define CONFIG_DM9000_BASE 0xb6000000
+#define DM9000_IO CONFIG_DM9000_BASE
+#define DM9000_DATA (CONFIG_DM9000_BASE + 2)
+
+/* Environment */
+#define CONFIG_SYS_MMC_ENV_DEV 0
+#define CONFIG_ENV_SIZE (32 << 10)
+#define CONFIG_ENV_OFFSET ((14 + 512) << 10)
+#define CONFIG_ENV_OVERWRITE
+
+/* Command line configuration. */
+#define CONFIG_SYS_CBSIZE 1024 /* Console I/O buffer size */
+#define CONFIG_SYS_MAXARGS 32 /* Max number of command args */
+#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE
+ /* Boot argument buffer size */
+#define CONFIG_VERSION_VARIABLE /* U-BOOT version */
+
+/* Miscellaneous configuration options */
+#define CONFIG_SYS_BOOTM_LEN (64 << 20)
+
+/* SPL */
+#define CONFIG_SPL_STACK 0xf4008000 /* only max. 2KB spare! */
+
+#define CONFIG_SPL_TEXT_BASE 0xf4000a00
+#define CONFIG_SPL_MAX_SIZE ((14 * 1024) - 0xa00)
+
+#define CONFIG_SPL_BSS_START_ADDR 0xf4004000
+#define CONFIG_SPL_BSS_MAX_SIZE 0x00002000 /* 512KB, arbitrary */
+
+#define CONFIG_SPL_START_S_PATH "arch/mips/mach-jz47xx"
+
+#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR 0x1c /* 14 KiB offset */
+
+#endif /* __CONFIG_CI20_H__ */
--
2.20.0.rc2
Ezequiel Garcia
2018-12-10 20:36:00 UTC
Permalink
From: Paul Burton <***@imgtec.com>

Add header with SPL boot mode and type definitions.

Cc: Daniel Schwierzeck <***@gmail.com>
Signed-off-by: Paul Burton <***@imgtec.com>
Signed-off-by: Marek Vasut <***@gmail.com>
---
arch/mips/include/asm/spl.h | 35 +++++++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
create mode 100644 arch/mips/include/asm/spl.h

diff --git a/arch/mips/include/asm/spl.h b/arch/mips/include/asm/spl.h
new file mode 100644
index 000000000000..01baab606606
--- /dev/null
+++ b/arch/mips/include/asm/spl.h
@@ -0,0 +1,35 @@
+/*
+ * (C) Copyright 2012
+ * Texas Instruments, <www.ti.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+#ifndef _ASM_SPL_H_
+#define _ASM_SPL_H_
+
+enum {
+ BOOT_DEVICE_RAM,
+ BOOT_DEVICE_MMC1,
+ BOOT_DEVICE_MMC2,
+ BOOT_DEVICE_MMC2_2,
+ BOOT_DEVICE_NAND,
+ BOOT_DEVICE_ONENAND,
+ BOOT_DEVICE_NOR,
+ BOOT_DEVICE_UART,
+ BOOT_DEVICE_SPI,
+ BOOT_DEVICE_USB,
+ BOOT_DEVICE_SATA,
+ BOOT_DEVICE_I2C,
+ BOOT_DEVICE_BOARD,
+ BOOT_DEVICE_NONE
+};
+
+/* Linker symbols. */
+extern char __bss_start[];
+extern ulong __bss_end;
+
+#ifndef CONFIG_DM
+extern gd_t gdata;
+#endif
+
+#endif
--
2.20.0.rc2
Marek Vasut
2018-12-10 20:58:55 UTC
Permalink
Post by Ezequiel Garcia
As the subject says, this series adds support for CI20.
Most of the work was done by Paul Burton, and then by Marek Vasut.
I've just rescued the work from the dark wastelands of Mordor,
did some cleaning here and there and submitted.
Patches 1, 2, and 4 are completely untouched. I've picked them
from Marek's tree.
For the MMC driver (patch 3) there is some cleanup, and some
fixes for proper DM migration.
Finally, patches 5 and 6 have been changed a bit: I've cleaned
up the devicetree, the board support files and the defconfig.
This is based on top of today's master (7ff485c68b7e) and has
been tested by SD-card booting both U-Boot and Linux. Booting
Linux via TFTP was also tested.
Please note that I've added Paul's SOB to all the patches
he authored, to make the authorship chain more clear.
Reviews and tests are welcome. Bikesheds not so much! ;-)
The platform is awfully size constrained, so it'd be nice to have it in
to keep the general bloat in check.

Except for minor nits in 1/6,
Reviewed-by: Marek Vasut <***@denx.de>
--
Best regards,
Marek Vasut
Andreas Färber
2018-12-10 21:00:11 UTC
Permalink
Hi Ezequiel,
Post by Ezequiel Garcia
Please note that I've added Paul's SOB to all the patches
he authored, to make the authorship chain more clear.
That's only permitted if Paul agreed to that beforehand - did he?
Never add other people's Signed-off-by if their patches didn't have it!

https://www.kernel.org/doc/html/latest/process/submitting-patches.html#sign-your-work-the-developer-s-certificate-of-origin

As far as the authorship chain goes, you re-did all my forward-porting,
that I'm not being credited with Signed-off-by in MMC/SoC/defconfig
patches or verbally anywhere?

Also this is surely not a v1 patch! Marek had posted CI20 before, so
this should be v2 (doesn't look like I posted mine as v2, it didn't
fully build yet) and thus your next iteration should be v3 please.

Further, it would be very helpful - given the history of this patchset -
to indicate which toolchain and version you used for building this.

Regards,
Andreas
--
SUSE Linux GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
Ezequiel Garcia
2018-12-10 21:31:29 UTC
Permalink
Post by Andreas Färber
Hi Ezequiel,
Post by Ezequiel Garcia
Please note that I've added Paul's SOB to all the patches
he authored, to make the authorship chain more clear.
That's only permitted if Paul agreed to that beforehand - did he?
Never add other people's Signed-off-by if their patches didn't have it!
Fair enough. Let's hope Paul is OK with this. I wasn't really comfortable
not having Paul's SOB, given he authored all the patches.

Paul, do we have green light?
Post by Andreas Färber
https://www.kernel.org/doc/html/latest/process/submitting-patches.html#sign-your-work-the-developer-s-certificate-of-origin
As far as the authorship chain goes, you re-did all my forward-porting,
that I'm not being credited with Signed-off-by in MMC/SoC/defconfig
patches or verbally anywhere?
Oh, sorry, but I haven't used anything from your work. This series
is entirely based on https://github.com/marex/u-boot-mips/tree/ci20-v2018.xx.

Basically, I've cherry-picked the commits that weren't already available
in upstream, adding my SOB to those patches that I've modified.

Like I mentioned in the cover letter, most of the work has been done
by Paul Burton and Marek, so they deserve all the credit.

I'm just cleaning and submitting.
Post by Andreas Färber
Also this is surely not a v1 patch! Marek had posted CI20 before, so
this should be v2 (doesn't look like I posted mine as v2, it didn't
fully build yet) and thus your next iteration should be v3 please.
Well, I couldn't find Marek's cover letter, and I've decided to start from scratch.

Two years have passed, we have a new try at getting this merged so I think
it deserves it's own set of integers.
Post by Andreas Färber
Further, it would be very helpful - given the history of this patchset -
to indicate which toolchain and version you used for building this.
I've used gcc version 5.3.0 (Sourcery CodeBench Lite 2016.05-8),
installed via Buildroot. Wasn't really paying attention to the toolchain.

I'll test with a recent gcc and post the results.

Thanks,
Eze
Andreas Färber
2018-12-10 21:39:16 UTC
Permalink
Post by Ezequiel Garcia
Post by Andreas Färber
Also this is surely not a v1 patch! Marek had posted CI20 before, so
this should be v2 (doesn't look like I posted mine as v2, it didn't
fully build yet) and thus your next iteration should be v3 please.
Well, I couldn't find Marek's cover letter, and I've decided to start from scratch.
That's OK, you did mention your changes in the cover letter.
Post by Ezequiel Garcia
Two years have passed, we have a new try at getting this merged so I think
it deserves it's own set of integers.
The patches need to be distinguishable in Patchwork and inboxes if the
subjects remained the same, no matter how much time passed.

Thanks,
Andreas
--
SUSE Linux GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
Paul Burton
2018-12-10 22:57:14 UTC
Permalink
Hi Ezequiel,
Post by Ezequiel Garcia
Post by Andreas Färber
Post by Ezequiel Garcia
Please note that I've added Paul's SOB to all the patches
he authored, to make the authorship chain more clear.
That's only permitted if Paul agreed to that beforehand - did he?
Never add other people's Signed-off-by if their patches didn't have it!
Fair enough. Let's hope Paul is OK with this. I wasn't really comfortable
not having Paul's SOB, given he authored all the patches.
Paul, do we have green light?
I'm OK with it in this instance, though please feel free to take
authorship if you make significant changes. I've not had the time to do
this work myself but I certainly don't want to stand in the way of
others :)

It's worth noting though that ***@imgtec.com is no longer a
valid email address, so it might be worth updating to
***@mips.com wherever my email address appears.

Thanks,
Paul
Tom Rini
2018-12-10 23:41:33 UTC
Permalink
[snip]
Post by Ezequiel Garcia
Post by Andreas Färber
Further, it would be very helpful - given the history of this patchset -
to indicate which toolchain and version you used for building this.
I've used gcc version 5.3.0 (Sourcery CodeBench Lite 2016.05-8),
installed via Buildroot. Wasn't really paying attention to the toolchain.
I'll test with a recent gcc and post the results.
Just to chime in on this part for now, to be clear, it needs to work
with the default toolchain buildman uses, which is currently the gcc-7.3
kernel.org ones and buildman will fetch one for you.
--
Tom
Ezequiel Garcia
2018-12-11 00:27:53 UTC
Permalink
Post by Tom Rini
[snip]
Post by Ezequiel Garcia
Post by Andreas Färber
Further, it would be very helpful - given the history of this patchset -
to indicate which toolchain and version you used for building this.
I've used gcc version 5.3.0 (Sourcery CodeBench Lite 2016.05-8),
installed via Buildroot. Wasn't really paying attention to the toolchain.
I'll test with a recent gcc and post the results.
Just to chime in on this part for now, to be clear, it needs to work
with the default toolchain buildman uses, which is currently the gcc-7.3
kernel.org ones and buildman will fetch one for you.
Done!

$ strings u-boot | grep GCC
mips-linux-gcc (GCC) 7.3.0
GCC: (GNU) 7.3.0
$ strings spl/u-boot-spl | grep GCC
GCC: (GNU) 7.3.0

U-Boot 2019.01-rc1-00226-g208679cb9307 (Dec 10 2018 - 21:19:57 -0300)

CPU: Ingenic JZ4780
Board: Creator CI20 (rev.1)
DRAM: 1 GiB
MMC: MSC: 0, MSC: 1
Loading Environment from MMC... OK
In: ***@10034000
Out: ***@10034000
Err: ***@10034000
Net: dm9000
Hit any key to stop autoboot: 0
=>

Regards,
Eze
Tom Rini
2018-12-11 00:46:29 UTC
Permalink
Post by Ezequiel Garcia
Post by Tom Rini
[snip]
Post by Ezequiel Garcia
Post by Andreas Färber
Further, it would be very helpful - given the history of this patchset -
to indicate which toolchain and version you used for building this.
I've used gcc version 5.3.0 (Sourcery CodeBench Lite 2016.05-8),
installed via Buildroot. Wasn't really paying attention to the toolchain.
I'll test with a recent gcc and post the results.
Just to chime in on this part for now, to be clear, it needs to work
with the default toolchain buildman uses, which is currently the gcc-7.3
kernel.org ones and buildman will fetch one for you.
Done!
$ strings u-boot | grep GCC
mips-linux-gcc (GCC) 7.3.0
GCC: (GNU) 7.3.0
$ strings spl/u-boot-spl | grep GCC
GCC: (GNU) 7.3.0
U-Boot 2019.01-rc1-00226-g208679cb9307 (Dec 10 2018 - 21:19:57 -0300)
CPU: Ingenic JZ4780
Board: Creator CI20 (rev.1)
DRAM: 1 GiB
MMC: MSC: 0, MSC: 1
Loading Environment from MMC... OK
Net: dm9000
Hit any key to stop autoboot: 0
=>
Yay!
--
Tom
Tom Rini
2018-12-11 00:48:08 UTC
Permalink
Post by Ezequiel Garcia
As the subject says, this series adds support for CI20.
Most of the work was done by Paul Burton, and then by Marek Vasut.
I've just rescued the work from the dark wastelands of Mordor,
did some cleaning here and there and submitted.
Patches 1, 2, and 4 are completely untouched. I've picked them
from Marek's tree.
For the MMC driver (patch 3) there is some cleanup, and some
fixes for proper DM migration.
Finally, patches 5 and 6 have been changed a bit: I've cleaned
up the devicetree, the board support files and the defconfig.
This is based on top of today's master (7ff485c68b7e) and has
been tested by SD-card booting both U-Boot and Linux. Booting
Linux via TFTP was also tested.
Please note that I've added Paul's SOB to all the patches
he authored, to make the authorship chain more clear.
Reviews and tests are welcome. Bikesheds not so much! ;-)
There's some stuff that's been noted that needs fixing and a v5 (I
think, really) posted with those addressed. But if there's nothing
else, it would be good to finally get this platform in and I would be
open to seeing it come in still at this point in the merge window.
Thanks all!
--
Tom
Ezequiel Garcia
2018-12-11 00:54:43 UTC
Permalink
Post by Tom Rini
Post by Ezequiel Garcia
As the subject says, this series adds support for CI20.
Most of the work was done by Paul Burton, and then by Marek Vasut.
I've just rescued the work from the dark wastelands of Mordor,
did some cleaning here and there and submitted.
Patches 1, 2, and 4 are completely untouched. I've picked them
from Marek's tree.
For the MMC driver (patch 3) there is some cleanup, and some
fixes for proper DM migration.
Finally, patches 5 and 6 have been changed a bit: I've cleaned
up the devicetree, the board support files and the defconfig.
This is based on top of today's master (7ff485c68b7e) and has
been tested by SD-card booting both U-Boot and Linux. Booting
Linux via TFTP was also tested.
Please note that I've added Paul's SOB to all the patches
he authored, to make the authorship chain more clear.
Reviews and tests are welcome. Bikesheds not so much! ;-)
There's some stuff that's been noted that needs fixing and a v5 (I
think, really) posted with those addressed. But if there's nothing
else, it would be good to finally get this platform in and I would be
open to seeing it come in still at this point in the merge window.
Thanks all!
I think that if we are worried about those infinite loops in the drivers,
and stuff along that severity level, it won't hurt to fix them as
follow-up patches.

Thanks,
Eze

Loading...