All of lore.kernel.org
 help / color / mirror / Atom feed
From: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH 1/4] mips: Add basic MediaTek MT7620/88 support
Date: Thu, 9 Aug 2018 15:28:55 +0200	[thread overview]
Message-ID: <CACUy__UVb++4hCh8iS1Os=QFa0JtRGrLFfM4wJuv42X_87Lnmg@mail.gmail.com> (raw)
In-Reply-To: <9dbedfcf-c4d7-1be6-d55e-ba880502e5df@denx.de>

Am Do., 9. Aug. 2018 um 12:46 Uhr schrieb Stefan Roese <sr@denx.de>:
>
> Hi Daniel,
>
> On 07.08.2018 17:44, Daniel Schwierzeck wrote:
> > 2018-08-06 17:11 GMT+02:00 Stefan Roese <sr@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 <sr@denx.de>
> >> Cc: Daniel Schwierzeck <daniel.schwierzeck@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".

>
> >>   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 <sr@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.

>
> >> +
> >> +       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.

>
> >> +
> >> +       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 <sr@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()

>
> > 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.

>
> >> +
> >> +static inline void cal_invalidate_dcache_range(u32 start_addr, u32 stop)
> >> +{
> >> +       u32 lsize = CONFIG_SYS_CACHELINE_SIZE;
> >> +       u32 addr = start_addr & ~(lsize - 1);
> >> +       u32 aend = (stop - 1) & ~(lsize - 1);
> >> +
> >> +       while (1) {
> >> +               cache_op(HIT_INVALIDATE_D, addr);
> >> +               if (addr == aend)
> >> +                       break;
> >> +               addr += lsize;
> >> +       }
> >> +}
> >
> > you should use the generic MIPS implementation instead
>
> Yes, makes sense.
>
> Thanks,
> Stefan



--
- Daniel

  reply	other threads:[~2018-08-09 13:28 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-08-06 15:11 [U-Boot] [PATCH 1/4] mips: Add basic MediaTek MT7620/88 support Stefan Roese
2018-08-06 15:11 ` [U-Boot] [PATCH 2/4] mips: Add arch/mips/include/asm/atomic.h Stefan Roese
2018-08-07 14:51   ` Daniel Schwierzeck
2018-08-09  9:27     ` Stefan Roese
2018-08-09 10:20       ` Daniel Schwierzeck
2018-08-06 15:11 ` [U-Boot] [PATCH 3/4] mips: Add LinkIt Smart 7688 support Stefan Roese
2018-08-06 15:11 ` [U-Boot] [PATCH 4/4] mips: Add Gardena Smart-Gateway board support Stefan Roese
2018-08-07 15:44 ` [U-Boot] [PATCH 1/4] mips: Add basic MediaTek MT7620/88 support Daniel Schwierzeck
2018-08-09 10:46   ` Stefan Roese
2018-08-09 13:28     ` Daniel Schwierzeck [this message]
2018-08-09 14:22       ` Stefan Roese
2018-08-11 22:52         ` Daniel Schwierzeck
2018-08-15  6:22           ` Stefan Roese

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CACUy__UVb++4hCh8iS1Os=QFa0JtRGrLFfM4wJuv42X_87Lnmg@mail.gmail.com' \
    --to=daniel.schwierzeck@gmail.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.