summaryrefslogtreecommitdiff
path: root/src/soc/ti/am335x
diff options
context:
space:
mode:
Diffstat (limited to 'src/soc/ti/am335x')
-rw-r--r--src/soc/ti/am335x/Kconfig18
-rw-r--r--src/soc/ti/am335x/Makefile.inc56
-rw-r--r--src/soc/ti/am335x/bootblock.c16
-rw-r--r--src/soc/ti/am335x/bootblock_media.c13
-rw-r--r--src/soc/ti/am335x/cbmem.c9
-rw-r--r--src/soc/ti/am335x/clock.h222
-rw-r--r--src/soc/ti/am335x/dmtimer.c12
-rw-r--r--src/soc/ti/am335x/dmtimer.h13
-rw-r--r--src/soc/ti/am335x/gpio.c77
-rw-r--r--src/soc/ti/am335x/gpio.h58
-rw-r--r--src/soc/ti/am335x/header.c57
-rw-r--r--src/soc/ti/am335x/header.h50
-rw-r--r--src/soc/ti/am335x/header.ld8
-rw-r--r--src/soc/ti/am335x/memlayout.ld28
-rw-r--r--src/soc/ti/am335x/monotonic_timer.c40
-rw-r--r--src/soc/ti/am335x/nand.c9
-rw-r--r--src/soc/ti/am335x/pinmux.c171
-rw-r--r--src/soc/ti/am335x/pinmux.h250
-rw-r--r--src/soc/ti/am335x/soc.c7
-rw-r--r--src/soc/ti/am335x/uart.c185
-rw-r--r--src/soc/ti/am335x/uart.h163
21 files changed, 1462 insertions, 0 deletions
diff --git a/src/soc/ti/am335x/Kconfig b/src/soc/ti/am335x/Kconfig
new file mode 100644
index 0000000000..533a0de628
--- /dev/null
+++ b/src/soc/ti/am335x/Kconfig
@@ -0,0 +1,18 @@
+config SOC_TI_AM335X
+ select ARCH_BOOTBLOCK_ARMV7
+ select ARCH_VERSTAGE_ARMV7
+ select ARCH_ROMSTAGE_ARMV7
+ select ARCH_RAMSTAGE_ARMV7
+ select HAVE_UART_SPECIAL
+ select UART_OVERRIDE_REFCLK
+ select BOOT_DEVICE_NOT_SPI_FLASH
+ bool
+ default n
+
+if SOC_TI_AM335X
+
+config MEMLAYOUT_LD_FILE
+ string
+ default "src/soc/ti/am335x/memlayout.ld"
+
+endif
diff --git a/src/soc/ti/am335x/Makefile.inc b/src/soc/ti/am335x/Makefile.inc
new file mode 100644
index 0000000000..2865338217
--- /dev/null
+++ b/src/soc/ti/am335x/Makefile.inc
@@ -0,0 +1,56 @@
+ifeq ($(CONFIG_SOC_TI_AM335X),y)
+bootblock-y += bootblock.c
+bootblock-y += bootblock_media.c
+bootblock-y += dmtimer.c
+bootblock-y += gpio.c
+bootblock-y += pinmux.c
+bootblock-y += monotonic_timer.c
+
+romstage-y += nand.c
+romstage-y += cbmem.c
+romstage-y += dmtimer.c
+romstage-y += monotonic_timer.c
+
+ramstage-y += dmtimer.c
+ramstage-y += monotonic_timer.c
+ramstage-y += nand.c
+ramstage-y += soc.c
+
+bootblock-y += uart.c
+romstage-y += uart.c
+ramstage-y += uart.c
+
+$(call add-class,omap-header)
+$(eval $(call create_class_compiler,omap-header,arm))
+
+omap-header-generic-ccopts += -D__COREBOOT_ARM_ARCH__=7
+
+real-target: $(obj)/MLO
+
+header_ld := $(call src-to-obj,omap-header,$(dir)/header.ld)
+
+get_header_size= \
+ $(eval omap_header_info=$(shell $(CBFSTOOL) $(1) print | grep $(2))) \
+ $(shell echo $$(($(word 2,$(omap_header_info)) + \
+ $(word 4,$(omap_header_info)))))
+
+$(obj)/omap-header.bin: $$(omap-header-objs) $(obj)/coreboot.rom
+ @printf " CC $(subst $(obj)/,,$(@))\n"
+ $(CC_omap-header) -nostdlib -nostartfiles -static -include $(obj)/config.h \
+ -Wl,--defsym,header_load_size=$(strip \
+ $(call get_header_size,$(obj)/coreboot.rom, \
+ $(CONFIG_CBFS_PREFIX)/romstage \
+ ) \
+ ) \
+ -o $@.tmp $< -T $(header_ld)
+ $(OBJCOPY_omap-header) --only-section=".header" -O binary $@.tmp $@
+
+$(obj)/MLO: $(obj)/coreboot.rom $(obj)/omap-header.bin
+ @printf " HEADER $(subst $(obj)/,,$(@))\n"
+ $(Q)cat $(obj)/omap-header.bin $(obj)/coreboot.rom > $@
+
+omap-header-y += header.c
+
+omap-header-srcs += $(CONFIG_MEMLAYOUT_LD_FILE)
+omap-header-y += header.ld
+endif
diff --git a/src/soc/ti/am335x/bootblock.c b/src/soc/ti/am335x/bootblock.c
new file mode 100644
index 0000000000..985e1a1a0b
--- /dev/null
+++ b/src/soc/ti/am335x/bootblock.c
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <types.h>
+
+#include <arch/cache.h>
+#include <bootblock_common.h>
+
+void bootblock_soc_init(void)
+{
+ uint32_t sctlr;
+
+ /* enable dcache */
+ sctlr = read_sctlr();
+ sctlr |= SCTLR_C;
+ write_sctlr(sctlr);
+}
diff --git a/src/soc/ti/am335x/bootblock_media.c b/src/soc/ti/am335x/bootblock_media.c
new file mode 100644
index 0000000000..050e0b77da
--- /dev/null
+++ b/src/soc/ti/am335x/bootblock_media.c
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <boot_device.h>
+#include <symbols.h>
+
+/* FIXME: No idea how big the internal SRAM actually is. */
+static const struct mem_region_device boot_dev =
+ MEM_REGION_DEV_RO_INIT(_dram, CONFIG_ROM_SIZE);
+
+const struct region_device *boot_device_ro(void)
+{
+ return &boot_dev.rdev;
+}
diff --git a/src/soc/ti/am335x/cbmem.c b/src/soc/ti/am335x/cbmem.c
new file mode 100644
index 0000000000..3765874ebe
--- /dev/null
+++ b/src/soc/ti/am335x/cbmem.c
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <cbmem.h>
+#include <symbols.h>
+
+void *cbmem_top_chipset(void)
+{
+ return _dram + (CONFIG_DRAM_SIZE_MB << 20);
+}
diff --git a/src/soc/ti/am335x/clock.h b/src/soc/ti/am335x/clock.h
new file mode 100644
index 0000000000..38b4ece249
--- /dev/null
+++ b/src/soc/ti/am335x/clock.h
@@ -0,0 +1,222 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef __SOC_TI_AM335X_CLOCK_H__
+#define __SOC_TI_AM335X_CLOCK_H__
+
+#include <stdint.h>
+
+enum {
+ CM_ST_NO_SLEEP = 0x0,
+ CM_ST_SW_SLEEP = 0x1,
+ CM_ST_SW_WKUP = 0x2
+};
+
+enum {
+ CM_MODULEMODE_DISABLED = 0x0,
+ CM_MODULEMODE_ENABLED = 0x2
+};
+
+enum {
+ CM_FCLK_DIS = 0x0 << 18,
+ CM_FCLK_EN = 0x1 << 18
+};
+
+/* Clock module peripheral registers */
+struct am335x_cm_per_regs {
+ uint32_t l4ls_st; // 0x0
+ uint32_t l3s_st; // 0x4
+ uint8_t _rsv0[4]; // 0x8-0xb
+ uint32_t l3_st; // 0xc
+ uint8_t _rsv1[4]; // 0x10-0x13
+ uint32_t cpgmac0; // 0x14
+ uint32_t lcdc; // 0x18
+ uint32_t usb0; // 0x1c
+ uint8_t _rsv2[4]; // 0x20-0x23
+ uint32_t tptc0; // 0x24
+ uint32_t emif; // 0x28
+ uint32_t ocmcram; // 0x2c
+ uint32_t gpmc; // 0x30
+ uint32_t mcasp0; // 0x34
+ uint32_t uart5; // 0x38
+ uint32_t mmc0; // 0x3c
+ uint32_t elm; // 0x40
+ uint32_t i2c2; // 0x44
+ uint32_t i2c1; // 0x48
+ uint32_t spi0; // 0x4c
+ uint32_t spi1; // 0x50
+ uint8_t _rsv3[0xc]; // 0x54-0x5f
+ uint32_t l4ls; // 0x60
+ uint8_t _rsv4[4]; // 0x64-0x67
+ uint32_t mcasp1; // 0x68
+ uint32_t uart1; // 0x6c
+ uint32_t uart2; // 0x70
+ uint32_t uart3; // 0x74
+ uint32_t uart4; // 0x78
+ uint32_t timer7; // 0x7c
+ uint32_t timer2; // 0x80
+ uint32_t timer3; // 0x84
+ uint32_t timer4; // 0x88
+ uint8_t _rsv5[0x20]; // 0x90-0xab
+ uint32_t gpio1; // 0xac
+ uint32_t gpio2; // 0xb0
+ uint32_t gpio3; // 0xb4
+ uint8_t _rsv6[4]; // 0xb8-0xbb
+ uint32_t tpcc; // 0xbc
+ uint32_t dcan0; // 0xc0
+ uint32_t dcan1; // 0xc4
+ uint8_t _rsv7[4]; // 0xc8-0xcb
+ uint32_t epwmss1; // 0xcc
+ uint8_t _rsv8[4]; // 0xd0-0xd3
+ uint32_t epwmss0; // 0xd4
+ uint32_t epwmss2; // 0xd8
+ uint32_t l3_instr; // 0xdc
+ uint32_t l3; // 0xe0
+ uint32_t ieee5000; // 0xe4
+ uint32_t pru_icss; // 0xe8
+ uint32_t timer5; // 0xec
+ uint32_t timer6; // 0xf0
+ uint32_t mmc1; // 0xf4
+ uint32_t mmc2; // 0xf8
+ uint32_t tptc1; // 0xfc
+ uint32_t tptc2; // 0x100
+ uint8_t _rsv9[8]; // 0x104-0x10b
+ uint32_t spinlock; // 0x10c
+ uint32_t mailbox0; // 0x110
+ uint8_t _rsv10[8]; // 0x114-0x11b
+ uint32_t l4hs_st; // 0x11c
+ uint32_t l4hs; // 0x120
+ uint8_t _rsv11[8]; // 0x124-0x12b
+ uint32_t ocpwp_l3_st; // 0x12c
+ uint32_t ocpwp; // 0x130
+ uint8_t _rsv12[0xb]; // 0x134-0x13f
+ uint32_t pru_icss_st; // 0x140
+ uint32_t cpsw_st; // 0x144
+ uint32_t lcdc_st; // 0x148
+ uint32_t clkdiv32k; // 0x14c
+ uint32_t clk_24mhz_st; // 0x150
+} __packed;
+static struct am335x_cm_per_regs * const am335x_cm_per = (void *)0x44e00000;
+
+/* Clock module wakeup registers */
+struct am335x_cm_wkup_regs {
+ uint32_t wkup_st; // 0x0
+ uint32_t wkup_control; // 0x4
+ uint32_t wkup_gpio0; // 0x8
+ uint32_t wkup_l4wkup; // 0xc
+ uint32_t wkup_timer0; // 0x10
+ uint32_t wkup_debugss; // 0x14
+ uint32_t l3_aon_st; // 0x18
+ uint32_t autoidle_dpll_mpu; // 0x1c
+ uint32_t idlest_dpll_mpu; // 0x20
+ uint32_t ssc_deltamstep_dpll_mpu; // 0x24
+ uint32_t ssc_modfreqdiv_dpll_mpu; // 0x28
+ uint32_t clksel_dpll_mpu; // 0x2c
+ uint32_t autoidle_dpll_ddr; // 0x30
+ uint32_t idlest_dpll_ddr; // 0x34
+ uint32_t ssc_deltamstep_dpll_ddr; // 0x38
+ uint32_t ssc_modfreqdiv_dpll_ddr; // 0x3c
+ uint32_t clksel_dpll_ddr; // 0x40
+ uint32_t autoidle_dpll_disp; // 0x44
+ uint32_t idlest_dpll_disp; // 0x48
+ uint32_t ssc_deltamstep_dpll_disp; // 0x4c
+ uint32_t ssc_modfreqdiv_dpll_disp; // 0x50
+ uint32_t clksel_dpll_disp; // 0x54
+ uint32_t autoidle_dpll_core; // 0x58
+ uint32_t idlest_dpll_core; // 0x5c
+ uint32_t ssc_deltamstep_dpll_core; // 0x60
+ uint32_t ssc_modfreqdiv_dpll_core; // 0x64
+ uint32_t clksel_dpll_core; // 0x68
+ uint32_t autoidle_dpll_per; // 0x6c
+ uint32_t idlest_dpll_per; // 0x70
+ uint32_t ssc_deltamstep_dpll_per; // 0x74
+ uint32_t ssc_modfreqdiv_dpll_per; // 0x78
+ uint32_t clkdcoldo_dpll_per; // 0x7c
+ uint32_t div_m4_dpll_core; // 0x80
+ uint32_t div_m5_dpll_core; // 0x84
+ uint32_t clkmode_dpll_mpu; // 0x88
+ uint32_t clkmode_dpll_per; // 0x8c
+ uint32_t clkmode_dpll_core; // 0x90
+ uint32_t clkmode_dpll_ddr; // 0x94
+ uint32_t clkmode_dpll_disp; // 0x98
+ uint32_t clksel_dpll_periph; // 0x9c
+ uint32_t div_m2_dpll_ddr; // 0xa0
+ uint32_t div_m2_dpll_disp; // 0xa4
+ uint32_t div_m2_dpll_mpu; // 0xa8
+ uint32_t div_m2_dpll_per; // 0xac
+ uint32_t wkup_wkup_m3; // 0xb0
+ uint32_t wkup_uart0; // 0xb4
+ uint32_t wkup_i2c0; // 0xb8
+ uint32_t wkup_adc_tsc; // 0xbc
+ uint32_t wkup_smartreflex0; // 0xc0
+ uint32_t wkup_timer1; // 0xc4
+ uint32_t wkup_smartreflex1; // 0xc8
+ uint32_t l4_wkup_aon_st; // 0xcc
+ uint8_t _rsv0[4]; // 0xd0-0xd3
+ uint32_t wkup_wdt1; // 0xd4
+ uint32_t div_m6_dpll_core; // 0xd8
+} __packed;
+static struct am335x_cm_wkup_regs * const am335x_cm_wkup = (void *)0x44e00400;
+
+/* Clock module pll registers */
+struct am335x_cm_dpll_regs {
+ uint8_t _rsv0[4]; // 0x0-0x3
+ uint32_t clksel_timer7_clk; // 0x4
+ uint32_t clksel_timer2_clk; // 0x8
+ uint32_t clksel_timer3_clk; // 0xc
+ uint32_t clksel_timer4_clk; // 0x10
+ uint32_t cm_mac_clksel; // 0x14
+ uint32_t clksel_timer5_clk; // 0x18
+ uint32_t clksel_timer6_clk; // 0x1c
+ uint32_t cm_cpts_rft_clksel; // 0x20
+ uint8_t _rsv1[4]; // 0x24-0x27
+ uint32_t clksel_timer1ms_clk; // 0x28
+ uint32_t clksel_gfx_fclk; // 0x2c
+ uint32_t clksel_pru_icss_ocp_clk; // 0x30
+ uint32_t clksel_lcdc_pixel_clk; // 0x34
+ uint32_t clksel_wdt1_clk; // 0x38
+ uint32_t clksel_gpio0_dbclk; // 0x3c
+} __packed;
+static struct am335x_cm_dpll_regs * const am335x_cm_dpll = (void *)0x44e00500;
+
+/* Clock module mpu registers */
+struct am335x_cm_mpu_regs {
+ uint32_t st; // 0x0
+ uint32_t mpu; // 0x4
+} __packed;
+static struct am335x_cm_mpu_regs * const am335x_cm_mpu = (void *)0x44e00600;
+
+/* Clock module device registers */
+struct am335x_cm_device_regs {
+ uint32_t cm_clkout_ctrl; // 0x0
+} __packed;
+static struct am335x_cm_device_regs * const am335x_cm_device =
+ (void *)0x44e00700;
+
+/* Clock module RTC registers */
+struct am335x_cm_rtc_regs {
+ uint32_t rtc; // 0x0
+ uint32_t st; // 0x4
+} __packed;
+static struct am335x_cm_rtc_regs * const am335x_cm_rtc = (void *)0x44e00800;
+
+/* Clock module graphics controller registers */
+struct am335x_cm_gfx_regs {
+ uint32_t l3_st; // 0x0
+ uint32_t gfx; // 0x4
+ uint8_t _rsv0[4]; // 0x8-0xb
+ uint32_t l4ls_gfx_st; // 0xc
+ uint32_t mmucfg; // 0x10
+ uint32_t mmudata; // 0x14
+} __packed;
+static struct am335x_cm_gfx_regs * const am335x_cm_gfx = (void *)0x44e00900;
+
+/* Clock module efuse registers */
+struct am335x_cm_cefuse_regs {
+ uint32_t st; // 0x0
+ uint8_t _rsv0[0x1c]; // 0x4-0x1f
+ uint32_t cefuse; // 0x20
+} __packed;
+static struct am335x_cm_cefuse_regs * const am335x_cm_cefuse =
+ (void *)0x44e00a00;
+
+#endif /* __SOC_TI_AM335X_CLOCK_H__ */
diff --git a/src/soc/ti/am335x/dmtimer.c b/src/soc/ti/am335x/dmtimer.c
new file mode 100644
index 0000000000..b3aa7a18ba
--- /dev/null
+++ b/src/soc/ti/am335x/dmtimer.c
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include "dmtimer.h"
+
+void dmtimer_start(int num)
+{
+}
+
+uint64_t dmtimer_raw_value(int num)
+{
+ return 0;
+}
diff --git a/src/soc/ti/am335x/dmtimer.h b/src/soc/ti/am335x/dmtimer.h
new file mode 100644
index 0000000000..ad8515fbba
--- /dev/null
+++ b/src/soc/ti/am335x/dmtimer.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __SOC_TI_AM335X_DMTIMER_H__
+#define __SOC_TI_AM335X_DMTIMER_H__
+
+#include <stdint.h>
+
+#define OSC_HZ 24000000
+
+void dmtimer_start(int num);
+uint64_t dmtimer_raw_value(int num);
+
+#endif
diff --git a/src/soc/ti/am335x/gpio.c b/src/soc/ti/am335x/gpio.c
new file mode 100644
index 0000000000..d3d3581f86
--- /dev/null
+++ b/src/soc/ti/am335x/gpio.c
@@ -0,0 +1,77 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include <device/mmio.h>
+#include <console/console.h>
+#include <soc/ti/am335x/gpio.h>
+#include <stdint.h>
+
+static struct am335x_gpio_regs *gpio_regs_and_bit(unsigned int gpio,
+ uint32_t *bit)
+{
+ unsigned int bank = gpio / AM335X_GPIO_BITS_PER_BANK;
+
+ if (bank >= ARRAY_SIZE(am335x_gpio_banks)) {
+ printk(BIOS_ERR, "Bad gpio index %d.\n", gpio);
+ return NULL;
+ }
+ *bit = 1 << (gpio % 32);
+ return am335x_gpio_banks[bank];
+}
+
+void am335x_disable_gpio_irqs(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(am335x_gpio_banks); i++)
+ write32(&am335x_gpio_banks[i]->irqstatus_clr_0, 0xffffffff);
+}
+
+int gpio_direction_input(unsigned int gpio)
+{
+ uint32_t bit;
+ struct am335x_gpio_regs *regs = gpio_regs_and_bit(gpio, &bit);
+
+ if (!regs)
+ return -1;
+ setbits32(&regs->oe, bit);
+ return 0;
+}
+
+int gpio_direction_output(unsigned int gpio, int value)
+{
+ uint32_t bit;
+ struct am335x_gpio_regs *regs = gpio_regs_and_bit(gpio, &bit);
+
+ if (!regs)
+ return -1;
+ if (value)
+ write32(&regs->setdataout, bit);
+ else
+ write32(&regs->cleardataout, bit);
+ clrbits32(&regs->oe, bit);
+ return 0;
+}
+
+int gpio_get_value(unsigned int gpio)
+{
+ uint32_t bit;
+ struct am335x_gpio_regs *regs = gpio_regs_and_bit(gpio, &bit);
+
+ if (!regs)
+ return -1;
+ return (read32(&regs->datain) & bit) ? 1 : 0;
+}
+
+int gpio_set_value(unsigned int gpio, int value)
+{
+ uint32_t bit;
+ struct am335x_gpio_regs *regs = gpio_regs_and_bit(gpio, &bit);
+
+ if (!regs)
+ return -1;
+ if (value)
+ write32(&regs->setdataout, bit);
+ else
+ write32(&regs->cleardataout, bit);
+ return 0;
+}
diff --git a/src/soc/ti/am335x/gpio.h b/src/soc/ti/am335x/gpio.h
new file mode 100644
index 0000000000..0877a6258c
--- /dev/null
+++ b/src/soc/ti/am335x/gpio.h
@@ -0,0 +1,58 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef __SOC_TI_AM335X_GPIO_H__
+#define __SOC_TI_AM335X_GPIO_H__
+
+#include <stdint.h>
+
+enum {
+ AM335X_GPIO_BITS_PER_BANK = 32
+};
+
+struct am335x_gpio_regs {
+ uint32_t revision; // 0x0
+ uint8_t _rsv0[0xc]; // 0x4-0xf
+ uint32_t sysconfig; // 0x10
+ uint8_t _rsv1[0xc]; // 0x14-0x1f
+ uint32_t eoi; // 0x20
+ uint32_t irqstatus_raw_0; // 0x24
+ uint32_t irqstatus_raw_1; // 0x28
+ uint32_t irqstatus_0; // 0x2c
+ uint32_t irqstatus_1; // 0x30
+ uint32_t irqstatus_set_0; // 0x34
+ uint32_t irqstatus_set_1; // 0x38
+ uint32_t irqstatus_clr_0; // 0x3c
+ uint32_t irqstatus_clk_1; // 0x40
+ uint32_t irqwaken_0; // 0x44
+ uint32_t irqwaken_1; // 0x48
+ uint8_t _rsv2[0xc8]; // 0x4c-0x113
+ uint32_t sysstatus; // 0x114
+ uint8_t _rsv3[0x18]; // 0x118-0x12f
+ uint32_t ctrl; // 0x130
+ uint32_t oe; // 0x134
+ uint32_t datain; // 0x138
+ uint32_t dataout; // 0x13c
+ uint32_t leveldetect0; // 0x140
+ uint32_t leveldetect1; // 0x144
+ uint32_t risingdetect; // 0x148
+ uint32_t fallingdetect; // 0x14c
+ uint32_t debouncenable; // 0x150
+ uint32_t debouncingtime; // 0x154
+ uint8_t _rsv4[0x38]; // 0x158-0x18f
+ uint32_t cleardataout; // 0x190
+ uint32_t setdataout; // 0x194
+} __packed;
+
+static struct am335x_gpio_regs * const am335x_gpio_banks[] = {
+ (void *)0x44e07000, (void *)0x4804c000,
+ (void *)0x481ac000, (void *)0x481ae000
+};
+
+void am335x_disable_gpio_irqs(void);
+
+int gpio_direction_input(unsigned int gpio);
+int gpio_direction_output(unsigned int gpio, int value);
+int gpio_get_value(unsigned int gpio);
+int gpio_set_value(unsigned int gpio, int value);
+
+#endif /* __SOC_TI_AM335X_CLOCK_H__ */
diff --git a/src/soc/ti/am335x/header.c b/src/soc/ti/am335x/header.c
new file mode 100644
index 0000000000..9edfdd062b
--- /dev/null
+++ b/src/soc/ti/am335x/header.c
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include <stdint.h>
+#include <symbols.h>
+
+#include "header.h"
+
+struct config_headers {
+ // The table of contents.
+ struct configuration_header_toc_item toc_chsettings;
+ struct configuration_header_toc_item toc_end;
+
+ // An inert instance of chsettings.
+ struct configuration_header_settings chsettings;
+} __packed;
+
+struct omap_image_headers {
+ union {
+ struct config_headers config_headers;
+ uint8_t bytes[512];
+ };
+ struct gp_device_header image_header;
+};
+
+// A symbol which defines how much of the image the iROM should load.
+extern char header_load_size;
+
+struct omap_image_headers headers __attribute__((section(".header"))) = {
+ .config_headers = {
+ .toc_chsettings = {
+ .start = offsetof(struct omap_image_headers,
+ config_headers.chsettings),
+ .size = sizeof(struct configuration_header_settings),
+ .reserved = { 0, 0, 0 },
+ .filename = "CHSETTINGS\0"
+ },
+ .toc_end = {
+ .start = 0xffffffff,
+ .size = 0xffffffff,
+ .reserved = { 0xffffffff, 0xffffffff, 0xffffffff },
+ .filename = { 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff }
+ },
+ .chsettings = {
+ .key = 0xc0c0c0c1,
+ .valid = 0,
+ .version = 1,
+ .reserved = 0,
+ .flags = 0
+ }
+ },
+ .image_header = {
+ .size = (uintptr_t)&header_load_size,
+ .destination = (uintptr_t)_dram
+ }
+};
diff --git a/src/soc/ti/am335x/header.h b/src/soc/ti/am335x/header.h
new file mode 100644
index 0000000000..a0a54ad0f3
--- /dev/null
+++ b/src/soc/ti/am335x/header.h
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef __SOC_TI_AM335X_HEADER_H
+#define __SOC_TI_AM335X_HEADER_H
+
+#include <stdint.h>
+
+struct configuration_header_toc_item {
+ // Offset from the start address of the TOC to the actual address of
+ // a section.
+ uint32_t start;
+
+ // Size of a section.
+ uint32_t size;
+
+ // Reserved.
+ uint32_t reserved[3];
+
+ // 12-character name of a section, including the zero (\0) terminator.
+ char filename[12];
+} __packed;
+
+struct configuration_header_settings {
+ // Key used for section verification.
+ uint32_t key;
+
+ // Enables or disables the section.
+ // 00h: Disable.
+ // Other: Enable.
+ uint8_t valid;
+
+ // Configuration header version.
+ uint8_t version;
+
+ // Reserved.
+ uint16_t reserved;
+
+ // Flags. It's not clear what this is used for.
+ uint32_t flags;
+} __packed;
+
+struct gp_device_header {
+ // Size of the image.
+ uint32_t size;
+
+ // Address to store the image/code entry point.
+ uint32_t destination;
+} __packed;
+
+#endif
diff --git a/src/soc/ti/am335x/header.ld b/src/soc/ti/am335x/header.ld
new file mode 100644
index 0000000000..84e01362b1
--- /dev/null
+++ b/src/soc/ti/am335x/header.ld
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+/* We use ELF as output format. So that we can debug the code in some form. */
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+
+#define OMAP_HEADER 1
+#include "memlayout.ld"
diff --git a/src/soc/ti/am335x/memlayout.ld b/src/soc/ti/am335x/memlayout.ld
new file mode 100644
index 0000000000..78528e63b7
--- /dev/null
+++ b/src/soc/ti/am335x/memlayout.ld
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <memlayout.h>
+
+#include <arch/header.ld>
+
+SECTIONS
+{
+ DRAM_START(0x40000000)
+ BOOTBLOCK(0x402f0400, 20K)
+ ROMSTAGE(0x402f5400, 88K)
+ FMAP_CACHE(0x4030b400, 2K)
+ STACK(0x4030be00, 4K)
+ RAMSTAGE(0x80200000, 192K)
+
+ /* TODO: Implement MMU support and move TTB to a better location. */
+ TTB(0x81000000, 16K)
+
+#ifdef OMAP_HEADER
+ .header : {
+ *(.header);
+ } : to_load
+
+ /DISCARD/ : {
+ *(*)
+ }
+#endif
+}
diff --git a/src/soc/ti/am335x/monotonic_timer.c b/src/soc/ti/am335x/monotonic_timer.c
new file mode 100644
index 0000000000..b57258b6c8
--- /dev/null
+++ b/src/soc/ti/am335x/monotonic_timer.c
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <stdint.h>
+#include <delay.h>
+#include <timer.h>
+
+#include "dmtimer.h"
+
+static struct monotonic_counter {
+ int initialized;
+ struct mono_time time;
+ uint64_t last_value;
+} mono_counter;
+
+static const uint32_t clocks_per_usec = OSC_HZ/1000000;
+
+void timer_monotonic_get(struct mono_time *mt)
+{
+ uint64_t current_tick;
+ uint64_t usecs_elapsed;
+
+ if (!mono_counter.initialized) {
+ init_timer();
+ mono_counter.last_value = dmtimer_raw_value(0);
+ mono_counter.initialized = 1;
+ }
+
+ current_tick = dmtimer_raw_value(0);
+ usecs_elapsed = (current_tick - mono_counter.last_value) /
+ clocks_per_usec;
+
+ /* Update current time and tick values only if a full tick occurred. */
+ if (usecs_elapsed) {
+ mono_time_add_usecs(&mono_counter.time, usecs_elapsed);
+ mono_counter.last_value = current_tick;
+ }
+
+ /* Save result. */
+ *mt = mono_counter.time;
+}
diff --git a/src/soc/ti/am335x/nand.c b/src/soc/ti/am335x/nand.c
new file mode 100644
index 0000000000..a7029a02d6
--- /dev/null
+++ b/src/soc/ti/am335x/nand.c
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <boot_device.h>
+
+const struct region_device *boot_device_ro(void)
+{
+ /* FIXME: add support for reading coreboot from NAND */
+ return NULL;
+}
diff --git a/src/soc/ti/am335x/pinmux.c b/src/soc/ti/am335x/pinmux.c
new file mode 100644
index 0000000000..8cf888405f
--- /dev/null
+++ b/src/soc/ti/am335x/pinmux.c
@@ -0,0 +1,171 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "pinmux.h"
+
+#include <device/mmio.h>
+
+static struct am335x_pinmux_regs *regs =
+ (struct am335x_pinmux_regs *)(uintptr_t)AM335X_PINMUX_REG_ADDR;
+
+void am335x_pinmux_uart0(void)
+{
+ write32(&regs->uart0_rxd, MODE(0) | PULLUP_EN | RXACTIVE);
+ write32(&regs->uart0_txd, MODE(0) | PULLUDEN);
+}
+
+void am335x_pinmux_uart1(void)
+{
+ write32(&regs->uart1_rxd, MODE(0) | PULLUP_EN | RXACTIVE);
+ write32(&regs->uart1_txd, MODE(0) | PULLUDEN);
+}
+
+void am335x_pinmux_uart2(void)
+{
+ // UART2_RXD
+ write32(&regs->spi0_sclk, MODE(1) | PULLUP_EN | RXACTIVE);
+ // UART2_TXD
+ write32(&regs->spi0_d0, MODE(1) | PULLUDEN);
+}
+
+void am335x_pinmux_uart3(void)
+{
+ // UART3_RXD
+ write32(&regs->spi0_cs1, MODE(1) | PULLUP_EN | RXACTIVE);
+ // UART3_TXD
+ write32(&regs->ecap0_in_pwm0_out, MODE(1) | PULLUDEN);
+}
+
+void am335x_pinmux_uart4(void)
+{
+ // UART4_RXD
+ write32(&regs->gpmc_wait0, MODE(6) | PULLUP_EN | RXACTIVE);
+ // UART4_TXD
+ write32(&regs->gpmc_wpn, MODE(6) | PULLUDEN);
+}
+
+void am335x_pinmux_uart5(void)
+{
+ // UART5_RXD
+ write32(&regs->lcd_data9, MODE(4) | PULLUP_EN | RXACTIVE);
+ // UART5_TXD
+ write32(&regs->lcd_data8, MODE(4) | PULLUDEN);
+}
+
+void am335x_pinmux_mmc0(int cd, int sk_evm)
+{
+ write32(&regs->mmc0_dat0, MODE(0) | RXACTIVE | PULLUP_EN);
+ write32(&regs->mmc0_dat1, MODE(0) | RXACTIVE | PULLUP_EN);
+ write32(&regs->mmc0_dat2, MODE(0) | RXACTIVE | PULLUP_EN);
+ write32(&regs->mmc0_dat3, MODE(0) | RXACTIVE | PULLUP_EN);
+ write32(&regs->mmc0_clk, MODE(0) | RXACTIVE | PULLUP_EN);
+ write32(&regs->mmc0_cmd, MODE(0) | RXACTIVE | PULLUP_EN);
+ if (!sk_evm) {
+ // MMC0_WP
+ write32(&regs->mcasp0_aclkr, MODE(4) | RXACTIVE);
+ }
+ if (cd) {
+ // MMC0_CD
+ write32(&regs->spi0_cs1, MODE(5) | RXACTIVE | PULLUP_EN);
+ }
+}
+
+void am335x_pinmux_mmc1(void)
+{
+ // MMC1_DAT0
+ write32(&regs->gpmc_ad0, MODE(1) | RXACTIVE | PULLUP_EN);
+ // MMC1_DAT1
+ write32(&regs->gpmc_ad1, MODE(1) | RXACTIVE | PULLUP_EN);
+ // MMC1_DAT2
+ write32(&regs->gpmc_ad2, MODE(1) | RXACTIVE | PULLUP_EN);
+ // MMC1_DAT3
+ write32(&regs->gpmc_ad3, MODE(1) | RXACTIVE | PULLUP_EN);
+ // MMC1_CLK
+ write32(&regs->gpmc_csn1, MODE(2) | RXACTIVE | PULLUP_EN);
+ // MMC1_CMD
+ write32(&regs->gpmc_csn2, MODE(2) | RXACTIVE | PULLUP_EN);
+ // MMC1_WP
+ write32(&regs->gpmc_csn0, MODE(7) | RXACTIVE | PULLUP_EN);
+ // MMC1_CD
+ write32(&regs->gpmc_advn_ale, MODE(7) | RXACTIVE | PULLUP_EN);
+}
+
+void am335x_pinmux_i2c0(void)
+{
+ write32(&regs->i2c0_sda, MODE(0) | RXACTIVE | PULLUDEN | SLEWCTRL);
+ write32(&regs->i2c0_scl, MODE(0) | RXACTIVE | PULLUDEN | SLEWCTRL);
+}
+
+void am335x_pinmux_i2c1(void)
+{
+ // I2C_DATA
+ write32(&regs->spi0_d1, MODE(2) | RXACTIVE | PULLUDEN | SLEWCTRL);
+ // I2C_SCLK
+ write32(&regs->spi0_cs0, MODE(2) | RXACTIVE | PULLUDEN | SLEWCTRL);
+}
+
+void am335x_pinmux_spi0(void)
+{
+ write32(&regs->spi0_sclk, MODE(0) | RXACTIVE | PULLUDEN);
+ write32(&regs->spi0_d0, MODE(0) | RXACTIVE | PULLUDEN | PULLUP_EN);
+ write32(&regs->spi0_d1, MODE(0) | RXACTIVE | PULLUDEN);
+ write32(&regs->spi0_cs0, MODE(0) | RXACTIVE | PULLUDEN | PULLUP_EN);
+}
+
+void am335x_pinmux_gpio0_7(void)
+{
+ write32(&regs->ecap0_in_pwm0_out, MODE(7) | PULLUDEN);
+}
+
+void am335x_pinmux_rgmii1(void)
+{
+ write32(&regs->mii1_txen, MODE(2));
+ write32(&regs->mii1_rxdv, MODE(2) | RXACTIVE);
+ write32(&regs->mii1_txd0, MODE(2));
+ write32(&regs->mii1_txd1, MODE(2));
+ write32(&regs->mii1_txd2, MODE(2));
+ write32(&regs->mii1_txd3, MODE(2));
+ write32(&regs->mii1_txclk, MODE(2));
+ write32(&regs->mii1_rxclk, MODE(2) | RXACTIVE);
+ write32(&regs->mii1_rxd0, MODE(2) | RXACTIVE);
+ write32(&regs->mii1_rxd1, MODE(2) | RXACTIVE);
+ write32(&regs->mii1_rxd2, MODE(2) | RXACTIVE);
+ write32(&regs->mii1_rxd3, MODE(2) | RXACTIVE);
+}
+
+void am335x_pinmux_mii1(void)
+{
+ write32(&regs->mii1_rxerr, MODE(0) | RXACTIVE);
+ write32(&regs->mii1_txen, MODE(0));
+ write32(&regs->mii1_rxdv, MODE(0) | RXACTIVE);
+ write32(&regs->mii1_txd0, MODE(0));
+ write32(&regs->mii1_txd1, MODE(0));
+ write32(&regs->mii1_txd2, MODE(0));
+ write32(&regs->mii1_txd3, MODE(0));
+ write32(&regs->mii1_txclk, MODE(0) | RXACTIVE);
+ write32(&regs->mii1_rxclk, MODE(0) | RXACTIVE);
+ write32(&regs->mii1_rxd0, MODE(0) | RXACTIVE);
+ write32(&regs->mii1_rxd1, MODE(0) | RXACTIVE);
+ write32(&regs->mii1_rxd2, MODE(0) | RXACTIVE);
+ write32(&regs->mii1_rxd3, MODE(0) | RXACTIVE);
+ write32(&regs->mdio_data, MODE(0) | RXACTIVE | PULLUP_EN);
+ write32(&regs->mdio_clk, MODE(0) | PULLUP_EN);
+}
+
+void am335x_pinmux_nand(void)
+{
+ write32(&regs->gpmc_ad0, MODE(0) | PULLUP_EN | RXACTIVE);
+ write32(&regs->gpmc_ad1, MODE(0) | PULLUP_EN | RXACTIVE);
+ write32(&regs->gpmc_ad2, MODE(0) | PULLUP_EN | RXACTIVE);
+ write32(&regs->gpmc_ad3, MODE(0) | PULLUP_EN | RXACTIVE);
+ write32(&regs->gpmc_ad4, MODE(0) | PULLUP_EN | RXACTIVE);
+ write32(&regs->gpmc_ad5, MODE(0) | PULLUP_EN | RXACTIVE);
+ write32(&regs->gpmc_ad6, MODE(0) | PULLUP_EN | RXACTIVE);
+ write32(&regs->gpmc_ad7, MODE(0) | PULLUP_EN | RXACTIVE);
+ write32(&regs->gpmc_wait0, MODE(0) | RXACTIVE | PULLUP_EN);
+ write32(&regs->gpmc_wpn, MODE(7) | PULLUP_EN | RXACTIVE);
+ write32(&regs->gpmc_csn0, MODE(0) | PULLUDEN);
+ write32(&regs->gpmc_advn_ale, MODE(0) | PULLUDEN);
+ write32(&regs->gpmc_oen_ren, MODE(0) | PULLUDEN);
+ write32(&regs->gpmc_wen, MODE(0) | PULLUDEN);
+ write32(&regs->gpmc_be0n_cle, MODE(0) | PULLUDEN);
+}
diff --git a/src/soc/ti/am335x/pinmux.h b/src/soc/ti/am335x/pinmux.h
new file mode 100644
index 0000000000..c46d03dbc9
--- /dev/null
+++ b/src/soc/ti/am335x/pinmux.h
@@ -0,0 +1,250 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef __SOC_TI_AM335X_PINMUX_H
+#define __SOC_TI_AM335X_PINMUX_H
+
+#include <stdint.h>
+
+// PAD Control Fields
+#define SLEWCTRL (0x1 << 6)
+#define RXACTIVE (0x1 << 5)
+#define PULLDOWN_EN (0x0 << 4) // Pull down
+#define PULLUP_EN (0x1 << 4) // Pull up
+#define PULLUDEN (0x0 << 3) // Pull up enabled
+#define PULLUDDIS (0x1 << 3) // Pull up disabled
+#define MODE(val) val
+
+void am335x_pinmux_uart0(void);
+void am335x_pinmux_uart1(void);
+void am335x_pinmux_uart2(void);
+void am335x_pinmux_uart3(void);
+void am335x_pinmux_uart4(void);
+void am335x_pinmux_uart5(void);
+
+void am335x_pinmux_mmc0(int cd, int sk_evm);
+void am335x_pinmux_mmc1(void);
+
+void am335x_pinmux_i2c0(void);
+void am335x_pinmux_i2c1(void);
+
+void am335x_pinmux_spi0(void);
+
+void am335x_pinmux_gpio0_7(void);
+
+void am335x_pinmux_rgmii1(void);
+void am335x_pinmux_mii1(void);
+
+void am335x_pinmux_nand(void);
+
+#define AM335X_PINMUX_REG_ADDR 0x44e10800
+
+struct am335x_pinmux_regs {
+ uint32_t gpmc_ad0;
+ uint32_t gpmc_ad1;
+ uint32_t gpmc_ad2;
+ uint32_t gpmc_ad3;
+ uint32_t gpmc_ad4;
+ uint32_t gpmc_ad5;
+ uint32_t gpmc_ad6;
+ uint32_t gpmc_ad7;
+ uint32_t gpmc_ad8;
+ uint32_t gpmc_ad9;
+ uint32_t gpmc_ad10;
+ uint32_t gpmc_ad11;
+ uint32_t gpmc_ad12;
+ uint32_t gpmc_ad13;
+ uint32_t gpmc_ad14;
+ uint32_t gpmc_ad15;
+ uint32_t gpmc_a0;
+ uint32_t gpmc_a1;
+ uint32_t gpmc_a2;
+ uint32_t gpmc_a3;
+ uint32_t gpmc_a4;
+ uint32_t gpmc_a5;
+ uint32_t gpmc_a6;
+ uint32_t gpmc_a7;
+ uint32_t gpmc_a8;
+ uint32_t gpmc_a9;
+ uint32_t gpmc_a10;
+ uint32_t gpmc_a11;
+ uint32_t gpmc_wait0;
+ uint32_t gpmc_wpn;
+ uint32_t gpmc_be1n;
+ uint32_t gpmc_csn0;
+ uint32_t gpmc_csn1;
+ uint32_t gpmc_csn2;
+ uint32_t gpmc_csn3;
+ uint32_t gpmc_clk;
+ uint32_t gpmc_advn_ale;
+ uint32_t gpmc_oen_ren;
+ uint32_t gpmc_wen;
+ uint32_t gpmc_be0n_cle;
+ uint32_t lcd_data0;
+ uint32_t lcd_data1;
+ uint32_t lcd_data2;
+ uint32_t lcd_data3;
+ uint32_t lcd_data4;
+ uint32_t lcd_data5;
+ uint32_t lcd_data6;
+ uint32_t lcd_data7;
+ uint32_t lcd_data8;
+ uint32_t lcd_data9;
+ uint32_t lcd_data10;
+ uint32_t lcd_data11;
+ uint32_t lcd_data12;
+ uint32_t lcd_data13;
+ uint32_t lcd_data14;
+ uint32_t lcd_data15;
+ uint32_t lcd_vsync;
+ uint32_t lcd_hsync;
+ uint32_t lcd_pclk;
+ uint32_t lcd_ac_bias_en;
+ uint32_t mmc0_dat3;
+ uint32_t mmc0_dat2;
+ uint32_t mmc0_dat1;
+ uint32_t mmc0_dat0;
+ uint32_t mmc0_clk;
+ uint32_t mmc0_cmd;
+ uint32_t mii1_col;
+ uint32_t mii1_crs;
+ uint32_t mii1_rxerr;
+ uint32_t mii1_txen;
+ uint32_t mii1_rxdv;
+ uint32_t mii1_txd3;
+ uint32_t mii1_txd2;
+ uint32_t mii1_txd1;
+ uint32_t mii1_txd0;
+ uint32_t mii1_txclk;
+ uint32_t mii1_rxclk;
+ uint32_t mii1_rxd3;
+ uint32_t mii1_rxd2;
+ uint32_t mii1_rxd1;
+ uint32_t mii1_rxd0;
+ uint32_t rmii1_refclk;
+ uint32_t mdio_data;
+ uint32_t mdio_clk;
+ uint32_t spi0_sclk;
+ uint32_t spi0_d0;
+ uint32_t spi0_d1;
+ uint32_t spi0_cs0;
+ uint32_t spi0_cs1;
+ uint32_t ecap0_in_pwm0_out;
+ uint32_t uart0_ctsn;
+ uint32_t uart0_rtsn;
+ uint32_t uart0_rxd;
+ uint32_t uart0_txd;
+ uint32_t uart1_ctsn;
+ uint32_t uart1_rtsn;
+ uint32_t uart1_rxd;
+ uint32_t uart1_txd;
+ uint32_t i2c0_sda;
+ uint32_t i2c0_scl;
+ uint32_t mcasp0_aclkx;
+ uint32_t mcasp0_fsx;
+ uint32_t mcasp0_axr0;
+ uint32_t mcasp0_ahclkr;
+ uint32_t mcasp0_aclkr;
+ uint32_t mcasp0_fsr;
+ uint32_t mcasp0_axr1;
+ uint32_t mcasp0_ahclkx;
+ uint32_t xdma_event_intr0;
+ uint32_t xdma_event_intr1;
+ uint32_t nresetin_out;
+ uint32_t porz;
+ uint32_t nnmi;
+ uint32_t osc0_in;
+ uint32_t osc0_out;
+ uint32_t rsvd1;
+ uint32_t tms;
+ uint32_t tdi;
+ uint32_t tdo;
+ uint32_t tck;
+ uint32_t ntrst;
+ uint32_t emu0;
+ uint32_t emu1;
+ uint32_t osc1_in;
+ uint32_t osc1_out;
+ uint32_t pmic_power_en;
+ uint32_t rtc_porz;
+ uint32_t rsvd2;
+ uint32_t ext_wakeup;
+ uint32_t enz_kaldo_1p8v;
+ uint32_t usb0_dm;
+ uint32_t usb0_dp;
+ uint32_t usb0_ce;
+ uint32_t usb0_id;
+ uint32_t usb0_vbus;
+ uint32_t usb0_drvvbus;
+ uint32_t usb1_dm;
+ uint32_t usb1_dp;
+ uint32_t usb1_ce;
+ uint32_t usb1_id;
+ uint32_t usb1_vbus;
+ uint32_t usb1_drvvbus;
+ uint32_t ddr_resetn;
+ uint32_t ddr_csn0;
+ uint32_t ddr_cke;
+ uint32_t ddr_ck;
+ uint32_t ddr_nck;
+ uint32_t ddr_casn;
+ uint32_t ddr_rasn;
+ uint32_t ddr_wen;
+ uint32_t ddr_ba0;
+ uint32_t ddr_ba1;
+ uint32_t ddr_ba2;
+ uint32_t ddr_a0;
+ uint32_t ddr_a1;
+ uint32_t ddr_a2;
+ uint32_t ddr_a3;
+ uint32_t ddr_a4;
+ uint32_t ddr_a5;
+ uint32_t ddr_a6;
+ uint32_t ddr_a7;
+ uint32_t ddr_a8;
+ uint32_t ddr_a9;
+ uint32_t ddr_a10;
+ uint32_t ddr_a11;
+ uint32_t ddr_a12;
+ uint32_t ddr_a13;
+ uint32_t ddr_a14;
+ uint32_t ddr_a15;
+ uint32_t ddr_odt;
+ uint32_t ddr_d0;
+ uint32_t ddr_d1;
+ uint32_t ddr_d2;
+ uint32_t ddr_d3;
+ uint32_t ddr_d4;
+ uint32_t ddr_d5;
+ uint32_t ddr_d6;
+ uint32_t ddr_d7;
+ uint32_t ddr_d8;
+ uint32_t ddr_d9;
+ uint32_t ddr_d10;
+ uint32_t ddr_d11;
+ uint32_t ddr_d12;
+ uint32_t ddr_d13;
+ uint32_t ddr_d14;
+ uint32_t ddr_d15;
+ uint32_t ddr_dqm0;
+ uint32_t ddr_dqm1;
+ uint32_t ddr_dqs0;
+ uint32_t ddr_dqsn0;
+ uint32_t ddr_dqs1;
+ uint32_t ddr_dqsn1;
+ uint32_t ddr_vref;
+ uint32_t ddr_vtp;
+ uint32_t ddr_strben0;
+ uint32_t ddr_strben1;
+ uint32_t ain7;
+ uint32_t ain6;
+ uint32_t ain5;
+ uint32_t ain4;
+ uint32_t ain3;
+ uint32_t ain2;
+ uint32_t ain1;
+ uint32_t ain0;
+ uint32_t vrefp;
+ uint32_t vrefn;
+};
+
+#endif
diff --git a/src/soc/ti/am335x/soc.c b/src/soc/ti/am335x/soc.c
new file mode 100644
index 0000000000..0362ed9c0c
--- /dev/null
+++ b/src/soc/ti/am335x/soc.c
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <device/device.h>
+
+struct chip_operations soc_ti_am335x_ops = {
+ CHIP_NAME("TI AM335X")
+};
diff --git a/src/soc/ti/am335x/uart.c b/src/soc/ti/am335x/uart.c
new file mode 100644
index 0000000000..90095d47d9
--- /dev/null
+++ b/src/soc/ti/am335x/uart.c
@@ -0,0 +1,185 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include <types.h>
+#include <console/uart.h>
+#include <device/mmio.h>
+#include <boot/coreboot_tables.h>
+#include <soc/ti/am335x/uart.h>
+
+#define EFR_ENHANCED_EN (1 << 4)
+#define FCR_FIFO_EN (1 << 0)
+#define MCR_TCR_TLR (1 << 6)
+#define SYSC_SOFTRESET (1 << 1)
+#define SYSS_RESETDONE (1 << 0)
+
+#define LSR_RXFIFOE (1 << 0)
+#define LSR_TXFIFOE (1 << 5)
+
+/*
+ * Initialise the serial port with the given baudrate divisor. The settings
+ * are always 8 data bits, no parity, 1 stop bit, no start bits.
+ */
+static void am335x_uart_init(struct am335x_uart *uart, uint16_t div)
+{
+ uint16_t lcr_orig, efr_orig, mcr_orig;
+
+ /* reset the UART */
+ write16(&uart->sysc, uart->sysc | SYSC_SOFTRESET);
+ while (!(read16(&uart->syss) & SYSS_RESETDONE))
+ ;
+
+ /* 1. switch to register config mode B */
+ lcr_orig = read16(&uart->lcr);
+ write16(&uart->lcr, 0xbf);
+
+ /*
+ * 2. Set EFR ENHANCED_EN bit. To access this bit, registers must
+ * be in TCR_TLR submode, meaning EFR[4] = 1 and MCR[6] = 1.
+ */
+ efr_orig = read16(&uart->efr);
+ write16(&uart->efr, efr_orig | EFR_ENHANCED_EN);
+
+ /* 3. Switch to register config mode A */
+ write16(&uart->lcr, 0x80);
+
+ /* 4. Enable register submode TCR_TLR to access the UARTi.UART_TLR */
+ mcr_orig = read16(&uart->mcr);
+ write16(&uart->mcr, mcr_orig | MCR_TCR_TLR);
+
+ /* 5. Enable the FIFO. For now we'll ignore FIFO triggers and DMA */
+ write16(&uart->fcr, FCR_FIFO_EN);
+
+ /* 6. Switch to configuration mode B */
+ write16(&uart->lcr, 0xbf);
+ /* Skip steps 7 and 8 (setting up FIFO triggers for DMA) */
+
+ /* 9. Restore original EFR value */
+ write16(&uart->efr, efr_orig);
+
+ /* 10. Switch to config mode A */
+ write16(&uart->lcr, 0x80);
+
+ /* 11. Restore original MCR value */
+ write16(&uart->mcr, mcr_orig);
+
+ /* 12. Restore original LCR value */
+ write16(&uart->lcr, lcr_orig);
+
+ /* Protocol, baud rate and interrupt settings */
+
+ /* 1. Disable UART access to DLL and DLH registers */
+ write16(&uart->mdr1, read16(&uart->mdr1) | 0x7);
+
+ /* 2. Switch to config mode B */
+ write16(&uart->lcr, 0xbf);
+
+ /* 3. Enable access to IER[7:4] */
+ write16(&uart->efr, efr_orig | EFR_ENHANCED_EN);
+
+ /* 4. Switch to operational mode */
+ write16(&uart->lcr, 0x0);
+
+ /* 5. Clear IER */
+ write16(&uart->ier, 0x0);
+
+ /* 6. Switch to config mode B */
+ write16(&uart->lcr, 0xbf);
+
+ /* 7. Set dll and dlh to the desired values (table 19-25) */
+ write16(&uart->dlh, (div >> 8));
+ write16(&uart->dll, (div & 0xff));
+
+ /* 8. Switch to operational mode to access ier */
+ write16(&uart->lcr, 0x0);
+
+ /* 9. Clear ier to disable all interrupts */
+ write16(&uart->ier, 0x0);
+
+ /* 10. Switch to config mode B */
+ write16(&uart->lcr, 0xbf);
+
+ /* 11. Restore efr */
+ write16(&uart->efr, efr_orig);
+
+ /* 12. Set protocol formatting 8n1 (8 bit data, no parity, 1 stop bit) */
+ write16(&uart->lcr, 0x3);
+
+ /* 13. Load the new UART mode */
+ write16(&uart->mdr1, 0x0);
+}
+
+/*
+ * Read a single byte from the serial port. Returns 1 on success, 0
+ * otherwise. When the function is successful, the character read is
+ * written into its argument c.
+ */
+static unsigned char am335x_uart_rx_byte(struct am335x_uart *uart)
+{
+ while (!(read16(&uart->lsr) & LSR_RXFIFOE));
+
+ return read8(&uart->rhr);
+}
+
+/*
+ * Output a single byte to the serial port.
+ */
+static void am335x_uart_tx_byte(struct am335x_uart *uart, unsigned char data)
+{
+ while (!(read16(&uart->lsr) & LSR_TXFIFOE));
+
+ return write8(&uart->thr, data);
+}
+
+unsigned int uart_platform_refclk(void)
+{
+ return 48000000;
+}
+
+uintptr_t uart_platform_base(int idx)
+{
+ const unsigned int bases[] = {
+ 0x44e09000, 0x48022000, 0x48024000,
+ 0x481a6000, 0x481a8000, 0x481aa000
+ };
+ if (idx < ARRAY_SIZE(bases))
+ return bases[idx];
+ return 0;
+}
+
+void uart_init(int idx)
+{
+ struct am335x_uart *uart = uart_platform_baseptr(idx);
+ uint16_t div = (uint16_t) uart_baudrate_divisor(
+ get_uart_baudrate(), uart_platform_refclk(), 16);
+ am335x_uart_init(uart, div);
+}
+
+unsigned char uart_rx_byte(int idx)
+{
+ struct am335x_uart *uart = uart_platform_baseptr(idx);
+ return am335x_uart_rx_byte(uart);
+}
+
+void uart_tx_byte(int idx, unsigned char data)
+{
+ struct am335x_uart *uart = uart_platform_baseptr(idx);
+ am335x_uart_tx_byte(uart, data);
+}
+
+void uart_tx_flush(int idx)
+{
+}
+
+void uart_fill_lb(void *data)
+{
+ struct lb_serial serial;
+ serial.type = LB_SERIAL_TYPE_MEMORY_MAPPED;
+ serial.baseaddr = uart_platform_base(CONFIG_UART_FOR_CONSOLE);
+ serial.baud = get_uart_baudrate();
+ serial.regwidth = 2;
+ serial.input_hertz = uart_platform_refclk();
+ serial.uart_pci_addr = CONFIG_UART_PCI_ADDR;
+ lb_add_serial(&serial, data);
+
+ lb_add_console(LB_TAG_CONSOLE_SERIAL8250MEM, data);
+}
diff --git a/src/soc/ti/am335x/uart.h b/src/soc/ti/am335x/uart.h
new file mode 100644
index 0000000000..664d57d42b
--- /dev/null
+++ b/src/soc/ti/am335x/uart.h
@@ -0,0 +1,163 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef AM335X_UART_H
+#define AM335X_UART_H
+
+#include <stdint.h>
+
+#define AM335X_UART0_BASE 0x44e09000
+#define AM335X_UART1_BASE 0x48020000
+#define AM335X_UART2_BASE 0x48024000
+#define AM335X_UART3_BASE 0x481A6000
+#define AM335X_UART4_BASE 0x481A8000
+#define AM335X_UART5_BASE 0x481AA000
+
+/*
+ * The meaning of some AM335x UART register offsets changes depending on read
+ * or write operation as well as various modes. See section 19.3.7.1.2 for
+ * register access submode description and 19.5.1 for register descriptions.
+ */
+struct am335x_uart {
+ union {
+ /* operational mode */
+ uint16_t rhr; /* receiver holding (read) */
+ uint16_t thr; /* transmit holding (write) */
+ /* config mode A and B */
+ uint16_t dll; /* divisor latches low */
+ };
+ uint8_t rsvd_0x02[2];
+ union {
+ /* operational mode */
+ uint16_t ier; /* interrupt enable */
+ /* config mode A and B */
+ uint16_t dlh; /* divisor latches high */
+ };
+ uint8_t rsvd_0x06[2];
+ union {
+ /* operational mode, config mode A */
+ uint16_t iir; /* interrupt ID (read) */
+ uint16_t fcr; /* FIFO control (write) */
+ /* config mode B */
+ uint16_t efr;
+ };
+ uint8_t rsvd_0x0a[2];
+ uint16_t lcr; /* line control */
+ uint8_t rsvd_0x0e[2];
+
+ /* 0x10 */
+ union {
+ /* operational mode, config mode A */
+ uint16_t mcr; /* modem control */
+ /* config mode B */
+ uint16_t xon1; /* XON1 character (UART mode) */
+ uint16_t addr1; /* address 1 (IrDA mode) */
+ };
+ uint8_t rsvd_0x12[2];
+ union {
+ /* operational mode, config mode A */
+ uint16_t lsr; /* line status, read-only */
+ /* config mode B */
+ uint16_t xon2; /* XON2 character (UART mode) */
+ uint16_t addr2; /* IrDA mode (IrDA mode) */
+ };
+ uint8_t rsvd_0x16[2];
+
+ /*
+ * Bytes 0x18 and 0x1c depend on submode TCR_TLR. When EFR[4] = 1 and
+ * MCR[6] = 1, transmission control register and trigger level register
+ * will be read/written. If not, the modem status register and the
+ * scratchpad register will be affected by read/write.
+ */
+ union {
+ /* operational mode and config mode A */
+ uint16_t msr; /* modem status */
+ /* config mode B */
+ uint16_t xoff1; /* xoff1 character (UART MODE) */
+ /* submode TCR_TLR */
+ uint16_t tcr; /* transmission control */
+ };
+ uint8_t rsvd_0x1a[2];
+ union {
+ uint16_t spr; /* scratchpad */
+ /* config mode B */
+ uint16_t xoff2; /* xoff2 character (UART mode) */
+ /* submode TCR_TLR */
+ uint16_t tlr; /* trigger level */
+ };
+ uint8_t rsvd_0x1e[2];
+
+ /* 0x20 */
+ uint16_t mdr1; /* mode definition 1 */
+ uint8_t rsvd_0x22[2];
+ uint16_t mdr2; /* mode definition 2 */
+ uint8_t rsvd_0x26[2];
+ union {
+ uint16_t sflsr; /* status FIFO line status reg (read) */
+ uint16_t txfll; /* transmit frame length low (write) */
+ };
+ uint8_t rsvd_0x2a[2];
+ union {
+ uint16_t resume; /* resume halted operation (read) */
+ uint16_t txflh; /* transmit frame length high (write) */
+ };
+ uint8_t rsvd_0x2e[2];
+
+ /* 0x30 */
+ union {
+ uint16_t sfregl; /* status FIFO low (read) */
+ uint16_t rxfll; /* received frame length low (write) */
+ };
+ uint8_t rsvd_0x32[2];
+ union {
+ uint16_t sfregh; /* status FIFO high (read) */
+ uint16_t rxflh; /* received frame length high (write) */
+ };
+ uint8_t rsvd_0x36[2];
+ uint16_t blr; /* BOF control */
+ uint8_t rsvd_0x3a[2];
+ uint16_t acreg; /* auxiliary control */
+ uint8_t rsvd_0x3e[2];
+
+ /* 0x40 */
+ uint16_t scr; /* supplementary control */
+ uint8_t rsvd_0x42[2];
+ uint16_t ssr; /* supplementary status */
+ uint8_t rsvd_0x46[2];
+
+ uint16_t eblr; /* BOF length (operational mode only) */
+ uint8_t rsvd_0x4a[6];
+
+ /* 0x50 */
+ uint16_t mvr; /* module version (read-only) */
+ uint8_t rsvd_0x52[2];
+ uint16_t sysc; /* system config */
+ uint8_t rsvd_0x56[2];
+ uint16_t syss; /* system status (read-only) */
+ uint8_t rsvd_0x5a[2];
+ uint16_t wer; /* wake-up enable */
+ uint8_t rsvd_0x5e[2];
+
+ /* 0x60 */
+ uint16_t cfps; /* carrier prescale frequency */
+ uint8_t rsvd_0x62[2];
+ uint16_t rxfifo_lvl; /* received FIFO level */
+ uint8_t rsvd_0x66[2];
+ uint16_t txfifo_lvl; /* transmit FIFO level */
+ uint8_t rsvd_0x6a[2];
+ uint16_t ier2; /* RX/TX FIFO empty interrupt enable */
+ uint8_t rsvd_0x6e[2];
+
+ /* 0x70 */
+ uint16_t isr2; /* RX/TX FIFO empty interrupt status */
+ uint8_t rsvd_0x72[2];
+ uint16_t freq_sel; /* frequency select */
+ uint8_t rsvd_0x76[10];
+
+ /* 0x80 */
+ uint16_t mdr3; /* mode definition register 3 */
+ uint8_t rsvd_0x82[2];
+ uint16_t txdma; /* TX DMA threshold */
+
+} __packed;
+
+#endif /* AM335X_UART_H */