Hi Daniel,

On 09.08.2018 15:28, Daniel Schwierzeck wrote:
Am Do., 9. Aug. 2018 um 12:46 Uhr schrieb Stefan Roese <s...@denx.de>:

Hi Daniel,

On 07.08.2018 17:44, Daniel Schwierzeck wrote:
2018-08-06 17:11 GMT+02:00 Stefan Roese <s...@denx.de>:
This patch adds basic support for the MediaTek MT7620/88 SoCs. Parts of
the code is copied from the MediaTek GitHub repository:

https://github.com/MediaTek-Labs/linkit-smart-uboot.git

Support for the LinkIt Smart 7688 module and the Gardena Smart Gateway
both based on the MT7688 will be added in further patches.

Signed-off-by: Stefan Roese <s...@denx.de>
Cc: Daniel Schwierzeck <daniel.schwierz...@gmail.com>
---
   arch/mips/Kconfig                     |  15 ++
   arch/mips/Makefile                    |   1 +
   arch/mips/mach-mt7620/Kconfig         | 130 ++++++++++
   arch/mips/mach-mt7620/Makefile        |   8 +
   arch/mips/mach-mt7620/cpu.c           |  66 +++++
   arch/mips/mach-mt7620/ddr_calibrate.c | 331 +++++++++++++++++++++++++
   arch/mips/mach-mt7620/lowlevel_init.S | 337 ++++++++++++++++++++++++++
   arch/mips/mach-mt7620/mt76xx.h        |  39 +++
   8 files changed, 927 insertions(+)
   create mode 100644 arch/mips/mach-mt7620/Kconfig
   create mode 100644 arch/mips/mach-mt7620/Makefile
   create mode 100644 arch/mips/mach-mt7620/cpu.c
   create mode 100644 arch/mips/mach-mt7620/ddr_calibrate.c
   create mode 100644 arch/mips/mach-mt7620/lowlevel_init.S
   create mode 100644 arch/mips/mach-mt7620/mt76xx.h

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 31b622ff51..af791c320d 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -87,6 +87,20 @@ config ARCH_BMIPS
          select SYSRESET
          imply CMD_DM

+config ARCH_MT7620
+       bool "Support MT7620/7688 SoCs"
+       select SUPPORTS_LITTLE_ENDIAN
+       select SUPPORTS_CPU_MIPS32_R1
+       select SUPPORTS_CPU_MIPS32_R2
+       select ROM_EXCEPTION_VECTORS
+       select MIPS_TUNE_4KC

MT7620 has a MIPS 24kc core, thus you could optimize for that

Okay.

+       select OF_CONTROL
+       select DM
+       select DM_SERIAL
+       select DM_SPI
+       select DM_SPI_FLASH
+       select DISPLAY_CPUINFO
+

could you sort this in alphabetic order?

Okay, will do in v2.

There were some patches recently
which did the sorting tree wide. Also drop the SPI options until you add a
SPI driver.

The SPI driver is also on the list:

http://patchwork.ozlabs.org/patch/954365/

ok, I didn't received this one. But since SPI is not strictly
required, you should prefer "imply" instead of a hard "select".

I've not seen an MT76xx board without SPI NOR flash, but this is
okay, I will turn this option into an "imply" instead in v2.


   config MACH_PIC32
          bool "Support Microchip PIC32"
          select DM
@@ -141,6 +155,7 @@ source "board/qemu-mips/Kconfig"
   source "arch/mips/mach-ath79/Kconfig"
   source "arch/mips/mach-bmips/Kconfig"
   source "arch/mips/mach-pic32/Kconfig"
+source "arch/mips/mach-mt7620/Kconfig"

   if MIPS

diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 5deec9a202..cc8ea5d7d4 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -15,6 +15,7 @@ machine-$(CONFIG_SOC_AU1X00) += au1x00
   machine-$(CONFIG_ARCH_ATH79) += ath79
   machine-$(CONFIG_ARCH_BMIPS) += bmips
   machine-$(CONFIG_MACH_PIC32) += pic32
+machine-$(CONFIG_ARCH_MT7620) += mt7620

   machdirs := $(patsubst %,arch/mips/mach-%/,$(machine-y))
   libs-y += $(machdirs)
diff --git a/arch/mips/mach-mt7620/Kconfig b/arch/mips/mach-mt7620/Kconfig
new file mode 100644
index 0000000000..40e15b8a31
--- /dev/null
+++ b/arch/mips/mach-mt7620/Kconfig
@@ -0,0 +1,130 @@
+menu "MediaTek MIPS platforms"
+       depends on ARCH_MT7620
+
+config SYS_MALLOC_F_LEN
+       default 0x1000
+
+config SYS_SOC
+       default "mt7620" if SOC_MT7620
+
+choice
+       prompt "MediaTek MIPS SoC select"
+
+config SOC_MT7620
+       bool "MT7620/8"
+       select MIPS_L1_CACHE_SHIFT_5
+       help
+         This supports MediaTek MIPS MT7620 family.
+
+endchoice
+
+choice
+       prompt "Board select"
+
+config BOARD_LINKIT_SMART_7688
+       bool "LinkIt Smart 7688"
+       depends on SOC_MT7620
+       select SUPPORTS_BOOT_RAM
+       help
+         Seeed LinkIt Smart 7688 boards have a MT7688 SoC with 128 MiB of RAM
+         and 32 MiB of flash (SPI).
+         Between its different peripherals there's an integrated switch with 4
+         ethernet ports, 1 USB port, 1 UART, GPIO buttons and LEDs, and
+         a MT7688 (PCIe).

could you add this part with patch 3/4?

Ah, yes. This slipped in too early.

+
+endchoice
+
+choice
+       prompt "Boot mode"
+
+config BOOT_RAM
+       bool "RAM boot"
+       depends on SUPPORTS_BOOT_RAM
+       select SKIP_LOWLEVEL_INIT
+       help
+         This builds an image that is linked to a RAM address. It can be used
+         for booting from CFE via TFTP using an ELF image, but it can also be
+         booted from RAM by other bootloaders using a BIN image.
+
+config BOOT_ROM
+       bool "ROM boot"
+       depends on SUPPORTS_BOOT_RAM
+       help
+         This builds an image that is linked to a ROM address. It can be
+         used as main bootloader image which is programmed onto the onboard
+         flash storage (SPI NOR).
+
+endchoice
+
+choice
+       prompt "DDR2 size"
+
+config ONBOARD_DDR2_SIZE_256MBIT
+       bool "256MBit (32MByte) total size"
+       depends on BOOT_ROM
+       help
+         Use 256MBit (32MByte) of DDR total size
+
+config ONBOARD_DDR2_SIZE_512MBIT
+       bool "512MBit (64MByte) total size"
+       depends on BOOT_ROM
+       help
+         Use 512MBit (64MByte) of DDR total size
+
+config ONBOARD_DDR2_SIZE_1024MBIT
+       bool "1024MBit (128MByte) total size"
+       depends on BOOT_ROM
+       help
+         Use 1024MBit (128MByte) of DDR total size
+
+config ONBOARD_DDR2_SIZE_2048MBIT
+       bool "2048MBit (256MByte) total size"
+       depends on BOOT_ROM
+       help
+         Use 2048MBit (256MByte) of DDR total size
+
+endchoice
+
+choice
+       prompt "DDR2 chip width"
+
+config ONBOARD_DDR2_CHIP_WIDTH_8BIT
+       bool "8bit DDR chip width"
+       depends on BOOT_ROM
+       help
+         Use DDR chips with 8bit width
+
+config ONBOARD_DDR2_CHIP_WIDTH_16BIT
+       bool "16bit DDR chip width"
+       depends on BOOT_ROM
+       help
+         Use DDR chips with 16bit width
+
+endchoice
+
+choice
+       prompt "DDR2 bus width"
+
+config ONBOARD_DDR2_BUS_WIDTH_16BIT
+       bool "16bit DDR bus width"
+       depends on BOOT_ROM
+       help
+         Use 16bit DDR bus width
+
+config ONBOARD_DDR2_BUS_WIDTH_32BIT
+       bool "32bit DDR bus width"
+       depends on BOOT_ROM
+       help
+         Use 32bit DDR bus width
+
+endchoice
+
+config SUPPORTS_BOOT_RAM
+       bool
+
+config SKIP_LOWLEVEL_INIT
+       bool

this is a legacy config option, thus you have to define it in your
board config header file.
MIPS shouldn't add a Kconfig symbol for that. This have to be migrated
to Kconfig tree-wide.

Will move to config header for now.

+
+source "board/seeed/linkit-smart-7688/Kconfig"

could you add this part with patch 3/4?

Sure.

+
+endmenu
diff --git a/arch/mips/mach-mt7620/Makefile b/arch/mips/mach-mt7620/Makefile
new file mode 100644
index 0000000000..1f3e65e8a5
--- /dev/null
+++ b/arch/mips/mach-mt7620/Makefile
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj-y += cpu.o
+
+ifndef CONFIG_SKIP_LOWLEVEL_INIT
+obj-y += ddr_calibrate.o
+obj-y += lowlevel_init.o
+endif
diff --git a/arch/mips/mach-mt7620/cpu.c b/arch/mips/mach-mt7620/cpu.c
new file mode 100644
index 0000000000..0b22956499
--- /dev/null
+++ b/arch/mips/mach-mt7620/cpu.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Stefan Roese <s...@denx.de>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <ram.h>
+#include <asm/io.h>
+#include <linux/io.h>
+#include <linux/sizes.h>
+#include "mt76xx.h"
+
+#define STR_LEN                        6
+
+#ifdef CONFIG_BOOT_ROM
+int mach_cpu_init(void)
+{
+       void (*ptr)(void);
+
+       /*
+        * DDR calibration routine needs to be called very early. This
+        * function also configures the clock to run at full speed.
+        */
+       ptr = (void *)CKSEG0ADDR(ddr_calibrate);
+       (*ptr)();

what is the purpose of forcing the function symbol to KSEG0?

Its copied from the original MediaTek code. I just tested it without
forcing the execution into KSEG0 and the DDR calibration is extremely
slow then, taking a few minutes to complete.

I have to admit that I am not 100% sure, if the caches are configured
100% correctly / optimally for this SoC. Perhaps you (or someone else)
has some improvements here.

I guess the BootROM does some XiP magic with the SPI flash controller
and runs in the uncached KSEG1 segment.
That would explain why the pre-relocation code runs so slowly. But
this shift from KSEG1 to KSEG0 could be done
generically in start.S after the cache initialization is complete. I
will have a look at it.

That would be great. Please let me know if you need some help with
testing etc.


+
+       return 0;
+}
+#endif
+
+int print_cpuinfo(void)
+{
+       static const char * const boot_str[] = { "PLL (3-Byte SPI Addr)",
+                                                "PLL (4-Byte SPI Addr)",
+                                                "XTAL (3-Byte SPI Addr)",
+                                                "XTAL (4-Byte SPI Addr)" };
+       char *chr = (char *)MT76XX_CHIPID;
+       char buf[STR_LEN + 1];
+       u32 val;
+
+       snprintf(buf, STR_LEN + 1, "%s", chr);
+       val = readl((void *)MT76XX_CHIP_REV_ID);
+       printf("CPU:   %-*s Rev %ld.%ld - ", STR_LEN, buf,
+              (val & GENMASK(11, 8)) >> 8, val & GENMASK(3, 0));
+
+       val = (readl((void *)MT76XX_SYSCFG0) & GENMASK(3, 1)) >> 1;
+       printf("Boot from %s\n", boot_str[val]);

could you try to create a CPU driver like on BMIPS?

Do you really think this is necessary just for printing some SoC
information here?

according to the datasheet those registers are in the memory space of
the system controller block. Thus you should create at least a syscon
driver. Also the device tree you're going to add references this
syscon device.

Yes, this would be a plus, to get rid of the base address definition
in the header and use the DT here. I'll take a look...


+
+       return 0;
+}
+
+void _machine_restart(void)
+{
+       writel(0x01, (void *)MT76XX_RSTCTL);
+
+       while (1)
+               ;       /* NOP */

could you try to create a reset controller driver? Then you could also
use the generic syscon-reboot driver.

Yes, I also thought about this. Will do in v2.

+}
+
+int dram_init(void)
+{
+       gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE, SZ_256M);

shouldn't you return the real configured DRAM size here?

I always like using get_ram_size() as it automatically detects the
RAM size. This might be different (smaller) than the one configured,
if HW problems with the DDR interface exist.

We might think about printing a warning, if the detected size does not
match the configured one.

+
+       return 0;
+}
diff --git a/arch/mips/mach-mt7620/ddr_calibrate.c 
b/arch/mips/mach-mt7620/ddr_calibrate.c
new file mode 100644
index 0000000000..6fd136674e
--- /dev/null
+++ b/arch/mips/mach-mt7620/ddr_calibrate.c
@@ -0,0 +1,331 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Stefan Roese <s...@denx.de>
+ *
+ * This code is mostly based on the code extracted from this MediaTek
+ * github repository:
+ *
+ * https://github.com/MediaTek-Labs/linkit-smart-uboot.git
+ *
+ * I was not able to find a specific license or other developers
+ * copyrights here, so I can't add them here.
+ *
+ * Most functions in this file are copied from the MediaTek U-Boot
+ * repository. Without any documentation, it was impossible to really
+ * implement this differently. So its mostly a cleaned-up version of
+ * the original code, with only support for the MT7628 / MT7688 SoC.
+ */
+
+#include <common.h>
+#include <linux/io.h>
+#include <asm/cacheops.h>
+#include <asm/io.h>
+#include "mt76xx.h"
+
+#define NUM_OF_CACHELINE       64
+#define MIN_START              6
+#define MIN_FINE_START         0xf
+#define MAX_START              7
+#define MAX_FINE_START         0x0
+
+#define CPU_FRAC_DIV           1
+
+#if defined(CONFIG_ONBOARD_DDR2_SIZE_256MBIT)
+#define DRAM_BUTTOM 0x02000000
+#endif
+#if defined(CONFIG_ONBOARD_DDR2_SIZE_512MBIT)
+#define DRAM_BUTTOM 0x04000000
+#endif
+#if defined(CONFIG_ONBOARD_DDR2_SIZE_1024MBIT)
+#define DRAM_BUTTOM 0x08000000
+#endif
+#if defined(CONFIG_ONBOARD_DDR2_SIZE_2048MBIT)
+#define DRAM_BUTTOM 0x10000000
+#endif
+
+static inline void cal_memcpy(void *src, void *dst, u32 size)
+{
+       u8 *psrc = (u8 *)src;
+       u8 *pdst = (u8 *)dst;
+       int i;
+
+       for (i = 0; i < size; i++, psrc++, pdst++)
+               *pdst = *psrc;
+}
+
+static inline void cal_memset(void *src, u8 pat, u32 size)
+{
+       u8 *psrc = (u8 *)src;
+       int i;
+
+       for (i = 0; i < size; i++, psrc++)
+               *psrc = pat;
+}
+
+#define pref_op(hint, addr)                                            \
+       __asm__ __volatile__(                                           \
+               ".set   push\n"                                         \
+               ".set   noreorder\n"                                    \
+               "pref   %0, %1\n"                                       \
+               ".set   pop\n"                                          \
+               :                                                       \
+               : "i" (hint), "R" (*(u8 *)(addr)))
+
+#define cache_op(op, addr)                                             \
+       __asm__ __volatile__(                                           \
+               ".set   push\n"                                         \
+               ".set   noreorder\n"                                    \
+               ".set   mips3\n"                                        \
+               "cache  %0, %1\n"                                       \
+               ".set   pop\n"                                          \
+               :                                                       \
+               : "i" (op), "R" (*(u8 *)(addr)))

cache_op() is already available in arch/mips/include/asm/cacheops.h.

Hmm, Where exactly?

sorry, I meant mips_cache()

Not needed anymore when moved to using the generic invalidate
dcache function.


Maybe you could add pref_op in the same way to that file.

Could make sense, but please see above. Again, I'm still pretty new to
MIPS and especially the caches.

I noticed prefetch() is already defined in
arch/mips/include/asm/processor.h. You could utilize it if you add a
boolean Kconfig option CONFIG_CPU_HAS_PREFETCH in arch/mips/Kconfig
and select it for MT7620.

Yes. But which implementation is the correct one for this SoC?

#define PREF(hint, addr)                                \
                .set    push;                           \
                .set    arch=r5000;                     \
                pref    hint, addr;                     \
                .set    pop

#define PREFE(hint, addr)                               \
                .set    push;                           \
                .set    mips0;                          \
                .set    eva;                            \
                prefe   hint, addr;                     \
                .set    pop

#define PREFX(hint, addr)                               \
                .set    push;                           \
                .set    arch=r5000;                     \
                prefx   hint, addr;                     \
                .set    pop

Thanks,
Stefan
_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

Reply via email to