arc: Add support for IoT development kit
authorAlexey Brodkin <abrodkin@synopsys.com>
Wed, 24 Jan 2018 18:37:14 +0000 (21:37 +0300)
committerAlexey Brodkin <abrodkin@synopsys.com>
Fri, 5 Oct 2018 13:57:00 +0000 (16:57 +0300)
The DesignWare ARC IoT Development Kit is a versatile platform
that includes the necessary hardware and software to accelerate
software development and debugging of sensor fusion,
voice recognition and face detection designs.

More information is avaialble here [1] and here [2].

The board is based on real silicon with
ARC EM9D-based Data Fusion IP Subsystem.

It sports a rich set of I/O including
 * DW USB OTG
 * DW MobileStorage (used for micro SD-card)
 * GPIO
 * multiple serial interface including DW APB UART
 * ADC, PWM and eFlash, SRAM and SPI Flash memory
 * Real-Time Clock (RTC)
 * Bluetooth module with worldwide regulatory compliance
   (FCC, IC, CE, ETSI, TELEC)
 * On-board 9-axis sensor (gyro, accelerometer and compass)

Extensible with Arduino, Pmod, mikroBUS connectors and a 2x18
extension header.

One of the most interesting features for developers is built-in
Digilent USB JTAG probe so only micro-USB cable is needed!

[1] https://www.synopsys.com/dw/ipdir.php?ds=arc_iot_development_kit
[2] https://www.synopsys.com/dw/doc.php/ds/cc/iot_dev_kit.pdf

Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
arch/arc/Kconfig
arch/arc/dts/Makefile
arch/arc/dts/iot_devkit.dts [new file with mode: 0644]
board/synopsys/iot_devkit/Kconfig [new file with mode: 0644]
board/synopsys/iot_devkit/MAINTAINERS [new file with mode: 0644]
board/synopsys/iot_devkit/Makefile [new file with mode: 0644]
board/synopsys/iot_devkit/config.mk [new file with mode: 0644]
board/synopsys/iot_devkit/iot_devkit.c [new file with mode: 0644]
board/synopsys/iot_devkit/u-boot.lds [new file with mode: 0644]
configs/iot_devkit_defconfig [new file with mode: 0644]
include/configs/iot_devkit.h [new file with mode: 0644]

index d59aa3ae291e021b783f0a178f7ed8d2995ee791..b24593e137b31907df4f8d744f4912b0b05e328d 100644 (file)
@@ -157,6 +157,10 @@ config TARGET_EMDK
 config TARGET_HSDK
        bool "Support Synpsys HS DevelopmentKit board"
 
+config TARGET_IOT_DEVKIT
+       bool "Synopsys Brite IoT Development kit"
+       select CPU_ARCEM6
+
 endchoice
 
 source "board/abilis/tb100/Kconfig"
@@ -164,5 +168,6 @@ source "board/synopsys/Kconfig"
 source "board/synopsys/axs10x/Kconfig"
 source "board/synopsys/emdk/Kconfig"
 source "board/synopsys/hsdk/Kconfig"
+source "board/synopsys/iot_devkit/Kconfig"
 
 endmenu
index 491a4f40bbc759864ba1547aa779696e6c59c0da..17e1405c0c4833b48d57f4f9a975e2453d42150c 100644 (file)
@@ -6,6 +6,7 @@ dtb-$(CONFIG_TARGET_NSIM) +=  nsim.dtb
 dtb-$(CONFIG_TARGET_TB100) +=  abilis_tb100.dtb
 dtb-$(CONFIG_TARGET_EMDK) +=  emdk.dtb
 dtb-$(CONFIG_TARGET_HSDK) +=  hsdk.dtb
+dtb-$(CONFIG_TARGET_IOT_DEVKIT) +=  iot_devkit.dtb
 
 targets += $(dtb-y)
 
diff --git a/arch/arc/dts/iot_devkit.dts b/arch/arc/dts/iot_devkit.dts
new file mode 100644 (file)
index 0000000..ebf5a95
--- /dev/null
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Synopsys, Inc. All rights reserved.
+ */
+/dts-v1/;
+
+#include "skeleton.dtsi"
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       aliases {
+               console = &uart0;
+       };
+
+       cpu_card {
+               core_clk: core_clk {
+                       #clock-cells = <0>;
+                       compatible = "fixed-clock";
+                       clock-frequency = <144000000>;
+                       u-boot,dm-pre-reloc;
+               };
+       };
+
+       uart0: serial0@80014000 {
+               compatible = "snps,dw-apb-uart";
+               clock-frequency = <16000000>;
+               reg = <0x80014000 0x1000>;
+               reg-shift = <2>;
+               reg-io-width = <4>;
+       };
+
+       usb: usb@f0040000 {
+               compatible = "snps,dwc2";
+               reg = <0xf0040000 0x10000>;
+               phys = <&usbphy>;
+               phy-names = "usb2-phy";
+       };
+
+       usbphy: phy {
+               compatible = "nop-phy";
+               #phy-cells = <0>;
+       };
+};
diff --git a/board/synopsys/iot_devkit/Kconfig b/board/synopsys/iot_devkit/Kconfig
new file mode 100644 (file)
index 0000000..ad956b2
--- /dev/null
@@ -0,0 +1,12 @@
+if TARGET_IOT_DEVKIT
+
+config SYS_BOARD
+       default "iot_devkit"
+
+config SYS_VENDOR
+       default "synopsys"
+
+config SYS_CONFIG_NAME
+       default "iot_devkit"
+
+endif
diff --git a/board/synopsys/iot_devkit/MAINTAINERS b/board/synopsys/iot_devkit/MAINTAINERS
new file mode 100644 (file)
index 0000000..06457cf
--- /dev/null
@@ -0,0 +1,5 @@
+IOT DEVKIT BOARD
+M:     Alexey Brodkin <abrodkin@synopsys.com>
+S:     Maintained
+F:     board/synopsys/iot_devkit/
+F:     configs/iot_devkit_defconfig
diff --git a/board/synopsys/iot_devkit/Makefile b/board/synopsys/iot_devkit/Makefile
new file mode 100644 (file)
index 0000000..1616024
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# Copyright (C) 2018 Synopsys, Inc. All rights reserved.
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+obj-y  += iot_devkit.o
diff --git a/board/synopsys/iot_devkit/config.mk b/board/synopsys/iot_devkit/config.mk
new file mode 100644 (file)
index 0000000..1207335
--- /dev/null
@@ -0,0 +1,2 @@
+PLATFORM_CPPFLAGS += -mlittle-endian -mcode-density -mdiv-rem -mswap -mnorm -mmpy-option=6 -mbarrel-shifter
+LDSCRIPT = $(srctree)/board/synopsys/iot_devkit/u-boot.lds
diff --git a/board/synopsys/iot_devkit/iot_devkit.c b/board/synopsys/iot_devkit/iot_devkit.c
new file mode 100644 (file)
index 0000000..c185d5c
--- /dev/null
@@ -0,0 +1,168 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Synopsys, Inc. All rights reserved.
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <dwmmc.h>
+#include <linux/libfdt.h>
+#include <fdtdec.h>
+
+#include <asm/arcregs.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define SYSCON_BASE    0xf000a000
+#define AHBCKDIV       (void *)(SYSCON_BASE + 0x04)
+#define APBCKDIV       (void *)(SYSCON_BASE + 0x08)
+#define APBCKEN                (void *)(SYSCON_BASE + 0x0C)
+#define CLKSEL         (void *)(SYSCON_BASE + 0x24)
+#define CLKSTAT                (void *)(SYSCON_BASE + 0x28)
+#define PLLCON         (void *)(SYSCON_BASE + 0x2C)
+#define APBCKSEL       (void *)(SYSCON_BASE + 0x30)
+#define AHBCKEN                (void *)(SYSCON_BASE + 0x34)
+#define USBPHY_PLL     (void *)(SYSCON_BASE + 0x78)
+#define USBCFG         (void *)(SYSCON_BASE + 0x7c)
+
+#define PLL_MASK_0     0xffcfffff
+#define PLL_MASK_1     0xffcfff00
+#define PLL_MASK_2     0xfbcfff00
+
+#define CLKSEL_DEFAULT 0x5a690000
+
+static int set_cpu_freq(unsigned int clk)
+{
+       clk /= 1000000;
+
+       /* Set clk to ext Xtal (LSN value 0) */
+       writel(CLKSEL_DEFAULT, CLKSEL);
+
+       switch (clk) {
+       case 16:
+               /* Bypass mode */
+               return 0;
+
+       case 50:
+               writel(readl(PLLCON) & PLL_MASK_0, PLLCON);
+               /* pll_off=1, M=25, N=1, OD=3, PLL_OUT_CLK=50M */
+               writel((readl(PLLCON) & PLL_MASK_1) | 0x300191, PLLCON);
+               /* pll_off=0, M=25, N=1, OD=3, PLL_OUT_CLK=50M */
+               writel((readl(PLLCON) & PLL_MASK_2) | 0x300191, PLLCON);
+               break;
+
+       case 72:
+               writel(readl(PLLCON) & PLL_MASK_0, PLLCON);
+               /* pll_off=1, M=18, N=1, OD=2, PLL_OUT_CLK=72M */
+               writel((readl(PLLCON) & PLL_MASK_1) | 0x200121, PLLCON);
+               /* pll_off=0, M=18, N=1, OD=2, PLL_OUT_CLK=72M */
+               writel((readl(PLLCON) & PLL_MASK_2) | 0x200121, PLLCON);
+               break;
+
+       case 100:
+               writel(readl(PLLCON) & PLL_MASK_0, PLLCON);
+               /* pll_off=1,M=25, N=1, OD=2, PLL_OUT_CLK=100M */
+               writel((readl(PLLCON) & PLL_MASK_1) | 0x200191, PLLCON);
+               /* pll_off=0,M=25, N=1, OD=2, PLL_OUT_CLK=100M */
+               writel((readl(PLLCON) & PLL_MASK_2) | 0x200191, PLLCON);
+               break;
+
+       case 144:
+               writel(readl(PLLCON) & PLL_MASK_0, PLLCON);
+               /* pll_off=1, M=18, N=1, OD=1, PLL_OUT_CLK=144M */
+               writel((readl(PLLCON) & PLL_MASK_1) | 0x100121, PLLCON);
+               /* pll_off=0, M=18, N=1, OD=1, PLL_OUT_CLK=144M */
+               writel((readl(PLLCON) & PLL_MASK_2) | 0x100121, PLLCON);
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       while (!(readl(CLKSTAT) & 0x4))
+               ;
+
+       /* Set clk from PLL on bus (LSN = 1) */
+       writel(CLKSEL_DEFAULT | BIT(0), CLKSEL);
+
+       return 0;
+}
+
+extern u8 __rom_end[];
+extern u8 __ram_start[];
+extern u8 __ram_end[];
+
+/*
+ * Use mach_cpu_init() for .data section copy as board_early_init_f() will be
+ * too late: initf_dm() will use a value of "av_" variable from not yet
+ * initialized (by copy) area.
+ */
+int mach_cpu_init(void)
+{
+       int offset, freq;
+
+       /* Don't relocate U-Boot */
+       gd->flags |= GD_FLG_SKIP_RELOC;
+
+       /* Copy data from ROM to RAM */
+       u8 *src = __rom_end;
+       u8 *dst = __ram_start;
+
+       while (dst < __ram_end)
+               *dst++ = *src++;
+
+       /* Enable debug uart */
+#define DEBUG_UART_BASE                0x80014000
+#define DEBUG_UART_DLF_OFFSET  0xc0
+       write_aux_reg(DEBUG_UART_BASE + DEBUG_UART_DLF_OFFSET, 1);
+
+       offset = fdt_path_offset(gd->fdt_blob, "/cpu_card/core_clk");
+       if (offset < 0)
+               return offset;
+
+       freq = fdtdec_get_int(gd->fdt_blob, offset, "clock-frequency", 0);
+       if (!freq)
+               return -EINVAL;
+
+       /* If CPU freq > 100 MHz, divide eFLASH clock by 2 */
+       if (freq > 100000000) {
+               u32 reg = readl(AHBCKDIV);
+
+               reg &= ~(0xF << 8);
+               reg |= 2 << 8;
+               writel(reg, AHBCKDIV);
+       }
+
+       return set_cpu_freq(freq);
+}
+
+#define ARC_PERIPHERAL_BASE    0xF0000000
+#define SDIO_BASE              (ARC_PERIPHERAL_BASE + 0xB000)
+
+int board_mmc_init(bd_t *bis)
+{
+       struct dwmci_host *host = NULL;
+
+       host = malloc(sizeof(struct dwmci_host));
+       if (!host) {
+               printf("dwmci_host malloc fail!\n");
+               return -ENOMEM;
+       }
+
+       memset(host, 0, sizeof(struct dwmci_host));
+       host->name = "Synopsys Mobile storage";
+       host->ioaddr = (void *)SDIO_BASE;
+       host->buswidth = 4;
+       host->dev_index = 0;
+       host->bus_hz = 50000000;
+
+       add_dwmci(host, host->bus_hz / 2, 400000);
+
+       return 0;
+}
+
+int checkboard(void)
+{
+       puts("Board: Synopsys IoT Development Kit\n");
+       return 0;
+};
diff --git a/board/synopsys/iot_devkit/u-boot.lds b/board/synopsys/iot_devkit/u-boot.lds
new file mode 100644 (file)
index 0000000..d083168
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2018 Synopsys, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <config.h>
+
+MEMORY {
+       ROM : ORIGIN = ROM_BASE, LENGTH = ROM_SIZE
+       RAM : ORIGIN = RAM_DATA_BASE, LENGTH = RAM_DATA_SIZE
+}
+
+OUTPUT_FORMAT("elf32-littlearc", "elf32-littlearc", "elf32-littlearc")
+OUTPUT_ARCH(arc)
+ENTRY(_start)
+SECTIONS
+{
+       . = CONFIG_SYS_MONITOR_BASE;
+       __image_copy_start = .;
+       .ivt :
+       {
+               __ivt_start = .;
+               KEEP(*(.ivt));
+               __ivt_end = .;
+       } > ROM
+
+       . = ALIGN(1024);
+       .text : {
+               __text_start = .;
+               arch/arc/lib/start.o (.text*)
+               *(.text*)
+               __text_end = .;
+       } > ROM
+
+       . = ALIGN(4);
+       .rodata : {
+               *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
+       } > ROM
+
+       . = ALIGN(4);
+       .u_boot_list : {
+               KEEP(*(SORT(.u_boot_list*)));
+
+               /* Mark RAM's LMA */
+               . = ALIGN(4);
+               __rom_end = .;
+       } > ROM
+
+       .data : {
+               /* Mark RAM's VMA */
+               . = ALIGN(4);
+
+               /*
+                * Everything between __ram_start and __ram_start will be
+                * copied from ROM to RAM in board_early_init_f().
+                */
+               __ram_start = .;
+
+               *(.data*)
+
+               __ram_end = .;
+       } > RAM AT > ROM
+
+       .bss : {
+               . = ALIGN(1024);
+               __bss_start = .;
+               *(.bss*)
+               __bss_end = .;
+       } > RAM
+
+       /* Keep relocation-related symbols to make linker happy */
+       __rel_dyn_start = .;
+       __rel_dyn_end = .;
+       __image_copy_end = .;
+       __init_end = .;
+}
diff --git a/configs/iot_devkit_defconfig b/configs/iot_devkit_defconfig
new file mode 100644 (file)
index 0000000..1f0f9c3
--- /dev/null
@@ -0,0 +1,38 @@
+CONFIG_ARC=y
+CONFIG_ISA_ARCV2=y
+CONFIG_CPU_ARCEM6=y
+CONFIG_SYS_ICACHE_OFF=y
+CONFIG_SYS_DCACHE_OFF=y
+CONFIG_TARGET_IOT_DEVKIT=y
+CONFIG_SYS_TEXT_BASE=0x20000000
+CONFIG_SYS_CLK_FREQ=16000000
+# CONFIG_ARCH_FIXUP_FDT_MEMORY is not set
+CONFIG_SYS_PROMPT="IoTDK# "
+# CONFIG_CMD_BOOTD is not set
+# CONFIG_CMD_BOOTM is not set
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_XIMG is not set
+# CONFIG_CMD_FLASH is not set
+# CONFIG_CMD_LOADB is not set
+# CONFIG_CMD_LOADS is not set
+CONFIG_CMD_MMC=y
+CONFIG_CMD_USB=y
+# CONFIG_CMD_NET is not set
+CONFIG_CMD_FAT=y
+CONFIG_OF_CONTROL=y
+CONFIG_OF_EMBED=y
+CONFIG_DEFAULT_DEVICE_TREE="iot_devkit"
+CONFIG_ENV_IS_IN_FAT=y
+CONFIG_ENV_FAT_INTERFACE="mmc"
+CONFIG_ENV_FAT_DEVICE_AND_PART="0:1"
+CONFIG_DM=y
+CONFIG_MMC=y
+CONFIG_MMC_DW=y
+CONFIG_DM_SERIAL=y
+CONFIG_SYS_NS16550=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_DWC2=y
+CONFIG_USB_DWC2_BUFFER_SIZE=16
+CONFIG_USB_STORAGE=y
+CONFIG_FS_FAT_MAX_CLUSTSIZE=4096
diff --git a/include/configs/iot_devkit.h b/include/configs/iot_devkit.h
new file mode 100644 (file)
index 0000000..4ffe114
--- /dev/null
@@ -0,0 +1,84 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2018 Synopsys, Inc. All rights reserved.
+ */
+
+#ifndef _CONFIG_IOT_DEVKIT_H_
+#define _CONFIG_IOT_DEVKIT_H_
+
+#include <linux/sizes.h>
+
+/*
+ *                         MEMORY MAP
+ *
+ * eFlash: 0x0000_0000 - 0x0008_0000 (512K)
+ *   ICCM: 0x2000_0000 - 0x2004_0000 (256K)
+ *   SRAM: 0x3000_0000 - 0x3002_0000 (128K)
+ *   DCCM: 0x8000_0000 - 0x8002_0000 (128K)
+ *     Note: only data goes here, as IFQ cannot fetch instructions from DCCM
+ *
+ *
+ *                         RAM PARTITIONING
+ *
+ *   +-----------+----------+---------------------+-------------+
+ *   | <-- Stack |  .data   | Malloc              | Environment |
+ *   +-----------+----------+---------------------+-------------+
+ *   :           :          :                     :\___________/
+ *   :           :          :                     :      |
+ *   :           :          :                     :     CONFIG_ENV_SIZE
+ *   :           :           \____________________/
+ *   :           :                     |
+ *   :           :                    CONFIG_SYS_MALLOC_LEN
+ *   :           :
+ *   :          Specified explicitly by CONFIG_SYS_INIT_SP_ADDR
+ *   :
+ *  Specified explicitly by CONFIG_SYS_SDRAM_BASE
+ *
+ *  NOTES:
+ *    - Stack starts from CONFIG_SYS_INIT_SP_ADDR and grows down,
+ *      i.e. towards CONFIG_SYS_SDRAM_BASE but nothing stops it from crossing
+ *      that CONFIG_SYS_SDRAM_BASE in which case data won't be really saved on
+ *      stack any longer and values popped from stack will contain garbage
+ *      leading to unexpected behavior, typically but not limited to:
+ *        - "Returning" back to bogus caller function
+ *        - Reading data from weird addresses
+ */
+
+#define CONFIG_SYS_MONITOR_BASE                CONFIG_SYS_TEXT_BASE
+
+#define SRAM_BASE                      0x30000000
+#define SRAM_SIZE                      SZ_128K
+
+#define DCCM_BASE                      0x80000000
+#define DCCM_SIZE                      SZ_128K
+
+#define CONFIG_SYS_SDRAM_BASE          DCCM_BASE
+#define CONFIG_SYS_SDRAM_SIZE          DCCM_SIZE
+
+#define CONFIG_SYS_INIT_SP_ADDR                (CONFIG_SYS_SDRAM_BASE + SZ_32K)
+
+#define CONFIG_SYS_MALLOC_LEN          SZ_64K
+#define CONFIG_SYS_BOOTM_LEN           SZ_128K
+#define CONFIG_SYS_LOAD_ADDR           SRAM_BASE
+
+#define ROM_BASE                       CONFIG_SYS_MONITOR_BASE
+#define ROM_SIZE                       SZ_256K
+
+#define RAM_DATA_BASE                  CONFIG_SYS_INIT_SP_ADDR
+#define RAM_DATA_SIZE                  CONFIG_SYS_SDRAM_SIZE - \
+                                       (CONFIG_SYS_INIT_SP_ADDR - \
+                                       CONFIG_SYS_SDRAM_BASE) - \
+                                       CONFIG_SYS_MALLOC_LEN - \
+                                       CONFIG_ENV_SIZE
+
+/* Required by DW MMC driver */
+#define CONFIG_BOUNCE_BUFFER
+
+/*
+ * Environment
+ */
+#define CONFIG_ENV_SIZE                        SZ_4K
+#define CONFIG_BOOTFILE                        "app.bin"
+#define CONFIG_LOADADDR                        CONFIG_SYS_LOAD_ADDR
+
+#endif /* _CONFIG_IOT_DEVKIT_H_ */