soc: esp32: Define __start as a C function

The first stage bootloader, part of the ESP32 ROM, already sets up
a stack that's sufficient to execute C programs.  So, instead of
implementing __stack() in assembly, do it in C to simplify things
slightly.

This ESP32-specific initialization will perform the following:

  - Disable the watchdog timer that's enabled by the bootloader
  - Move exception handlers to IRAM
  - Disable normal interrupts
  - Disable the second CPU
  - Zero out the BSS segment

Things that might be performed in the future include setting up the
CPU frequency, memory protection regions, and enabling the flash
cache.

Signed-off-by: Leandro Pereira <leandro.pereira@intel.com>
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index 86c230a..4b11df9 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -77,6 +77,14 @@
 	This is always needed for the simulator. Real boards may already
 	implement this in boot ROM.
 
+config XTENSA_USE_CORE_CRT1
+	bool
+	prompt "Use crt1.S from core"
+	default y
+	help
+	SoC or boards might define their own __start by setting this setting
+	to false.
+
 menu "Specific core configuration"
 
 config IRQ_OFFLOAD_INTNUM
diff --git a/arch/xtensa/core/Makefile b/arch/xtensa/core/Makefile
index fdbbf55..6a5a23a 100644
--- a/arch/xtensa/core/Makefile
+++ b/arch/xtensa/core/Makefile
@@ -8,9 +8,10 @@
 # Use our own routines implmented in assembly
 obj-atomic=atomic.o
 endif
-obj-y = ${obj-atomic} cpu_idle.o fatal.o crt1.o \
+obj-y = ${obj-atomic} cpu_idle.o fatal.o \
 	swap.o thread.o xt_zephyr.o	xtensa_context.o xtensa_intr_asm.o \
 	xtensa_intr.o xtensa_vectors.o irq_manage.o
+obj-$(CONFIG_XTENSA_USE_CORE_CRT1) += crt1.o
 obj-$(CONFIG_IRQ_OFFLOAD) += irq_offload.o
 # Keep this last so that vague linking works
 obj-y += sw_isr_table.o
diff --git a/arch/xtensa/soc/esp32/Makefile b/arch/xtensa/soc/esp32/Makefile
index 5e8827d..550bff6 100644
--- a/arch/xtensa/soc/esp32/Makefile
+++ b/arch/xtensa/soc/esp32/Makefile
@@ -1 +1 @@
-obj- = soc.o
+obj-y = soc.o
diff --git a/arch/xtensa/soc/esp32/linker.ld b/arch/xtensa/soc/esp32/linker.ld
index 908ce9d..7d96571 100644
--- a/arch/xtensa/soc/esp32/linker.ld
+++ b/arch/xtensa/soc/esp32/linker.ld
@@ -191,10 +191,6 @@
     *(.dynamic)
     *(.gnu.version_d)
     . = ALIGN(4);               /* this table MUST be 4-byte aligned */
-    _bss_table_start = ABSOLUTE(.);
-    LONG(_bss_start)
-    LONG(_bss_end)
-    _bss_table_end = ABSOLUTE(.);
     _rodata_end = ABSOLUTE(.);
   } GROUP_LINK_IN(RAMABLE_REGION)
 
diff --git a/arch/xtensa/soc/esp32/soc.c b/arch/xtensa/soc/esp32/soc.c
new file mode 100644
index 0000000..d5890d9
--- /dev/null
+++ b/arch/xtensa/soc/esp32/soc.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <soc/dport_reg.h>
+#include <soc/rtc_cntl_reg.h>
+#include <soc/timer_group_reg.h>
+#include <string.h>
+#include <toolchain/gcc.h>
+#include <xtensa/config/core-isa.h>
+#include <xtensa/corebits.h>
+#include <zephyr/types.h>
+
+extern void _Cstart(void);
+
+/*
+ * This is written in C rather than assembly since, during the port bring up,
+ * Zephyr is being booted by the Espressif bootloader.  With it, the C stack
+ * is already set up.
+ */
+void __attribute__((section(".iram1"))) __start(void)
+{
+	volatile u32_t *wdt_rtc_reg = (u32_t *)RTC_CNTL_WDTCONFIG0_REG;
+	volatile u32_t *wdt_timg_reg = (u32_t *)TIMG_WDTCONFIG0_REG(0);
+	volatile u32_t *app_cpu_config_reg = (u32_t *)DPORT_APPCPU_CTRL_B_REG;
+	extern u32_t _init_start;
+	extern u32_t _bss_start;
+	extern u32_t _bss_end;
+
+	/* Move the exception vector table to IRAM. */
+	__asm__ __volatile__ (
+		"wsr %0, vecbase"
+		:
+		: "r"(&_init_start));
+
+	/* Zero out BSS.  Clobber _bss_start to avoid memset() elision. */
+	memset(&_bss_start, 0, (&_bss_end - &_bss_start) * sizeof(_bss_start));
+	__asm__ __volatile__ (
+		""
+		:
+		: "g"(&_bss_start)
+		: "memory");
+
+	/* The watchdog timer is enabled in the bootloader.  We're done booting,
+	 * so disable it.
+	 */
+	*wdt_rtc_reg &= ~RTC_CNTL_WDT_FLASHBOOT_MOD_EN;
+	*wdt_timg_reg &= ~TIMG_WDT_FLASHBOOT_MOD_EN;
+
+	/* Disable normal interrupts. */
+	__asm__ __volatile__ (
+		"wsr %0, PS"
+		:
+		: "r"(PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | PS_WOE));
+
+	/* Disable CPU1 while we figure out how to have SMP in Zephyr. */
+	*app_cpu_config_reg &= ~DPORT_APPCPU_CLKGATE_EN;
+
+	/* Start Zephyr */
+	_Cstart();
+
+	CODE_UNREACHABLE;
+}
diff --git a/boards/xtensa/esp32/esp32_defconfig b/boards/xtensa/esp32/esp32_defconfig
index 916064d..176534c 100644
--- a/boards/xtensa/esp32/esp32_defconfig
+++ b/boards/xtensa/esp32/esp32_defconfig
@@ -15,3 +15,5 @@
 CONFIG_UART_CONSOLE_ON_DEV_NAME="ROMUART"
 CONFIG_UART_CONSOLE=y
 CONFIG_UART_ESP32=y
+
+CONFIG_XTENSA_USE_CORE_CRT1=n