Board bring-up part 4: Wrap it up

Posted by Marcus Folkesson on Saturday, August 17, 2024

Board bring-up part 4: Wrap it up

I'm currently working with a board bring up for a custom hardware based on a OMAPL138 from Texas Instruments. It is fun to work with "real" bring-ups. Most of my customers use System On Modules (SoM:s) these days. You get a lot for free with those modules but a lot of the fun is stripped away.

This post is not intended to be guide, it is more of a follow-me-through-my-work-post divided into three parts.

The first step is to get a bootloader to startup properly - which is also as far as I will take it in this series.

We are going to use U-boot [1] as bootloader for this project and I will use the TMDSLCDK138 [2] implementation as a reference during my bring-up, which is a evaluation kit for the OMAP-L138 CPU.

I will also be sharing lots of code snippets and it may not be obvious where they belong. In part4, I will summary all the changes I made.

About this part

This part will present all changes I made to the U-boot repository in order to support my new board.

I have removed all references to the actual customer and replaced with MFOC so as not to reveal anything I shouldn't.

File structure

In order to implement support for a new board you have to create a few file and modify others.

Here is a summary of the files I've created and modified:

 1$ git show --stat
 2commit 81a7026fe6981ef2a76f463aab688c672c53a7d8 (HEAD -> mfoc)
 3Author: Marcus Folkesson <marcus.folkesson@gmail.com>
 4Date:   Mon Aug 19 12:51:14 2024 +0200
 5
 6    board: davinci: mfoc: initial support
 7
 8    Initial support for the MFOC platform.
 9
10    Signed-off-by: Marcus Folkesson <marcus.folkesson@gmail.com>
11
12 arch/arm/dts/da850-mfoc.dts            | 185 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13 arch/arm/mach-davinci/Kconfig          |   7 +++++
14 board/davinci/mfoc/Kconfig             |  17 +++++++++++
15 board/davinci/mfoc/Makefile            |   5 ++++
16 board/davinci/mfoc/mfoc.c              | 295 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
17 board/davinci/mfoc/u-boot-spl-mfoc.lds |  65 ++++++++++++++++++++++++++++++++++++++++++
18 configs/mfoc_defconfig                 | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
19 include/configs/mfoc.h                 | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
20 8 files changed, 802 insertions(+), 5 deletions(-)
  • arch/arm/dts/da850-mfoc.dts: (NEW) Device tree used by U-Boot
  • arch/arm/mach-davinci/Kconfig: (MODIFIED) Add new target and source board/davinci/mfoc/Kconfig
  • board/davinci/mfoc/Kconfig: (NEW) Add KConfig options for our new board
  • board/davinci/mfoc/Makefile: (NEW) Make rules for our new board
  • board/davinci/mfoc/mfoc.c: (NEW) Our new board
  • board/davinci/mfoc/u-boot-spl-mfoc.lds: (NEW) Linker script for the SPL
  • configs/mfoc_defconfig: (NEW) Default (KConfig) configuration for the MFOC board
  • include/configs/mfoc.h: (NEW) Board specific configurations

arch/arm/dts/da850-mfoc.dts

The complete device-tree.

/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (c) 2024 MFOC
 *
 * Licensed under GPLv2.
 */
/dts-v1/;
#include "da850.dtsi"
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>

/ {
	model = "MFOC";
	compatible = "ti,da850-lcdk", "ti,da850", "ti,da850-mfoc";

	aliases {
		serial1 = &serial1;
		ethernet0 = &eth0;
	};

	chosen {
		stdout-path = &serial1;
	};

	memory@c0000000 {
		/* 128 MB MDDR2 SDRAM @ 0xc0000000 */
		reg = <0xc0000000 0x08000000>;
	};

	reserved-memory {
		#address-cells = <1>;
		#size-cells = <1>;
		ranges;

		dsp_memory_region: dsp-memory@c3000000 {
			compatible = "shared-dma-pool";
			reg = <0xc3000000 0x1000000>;
			reusable;
			status = "okay";
		};
	};
};


&ref_clk {
	clock-frequency = <24000000>;
};

&pmx_core {
	status = "okay";

	mcasp0_pins: pinmux_mcasp0_pins {
		pinctrl-single,bits = <
			/* AHCLKX AFSX ACLKX */
			0x00 0x00101010 0x00f0f0f0
			/* ARX13 ARX14 */
			0x04 0x00000110 0x00000ff0
		>;
	};

	nand_pins: nand_pins {
		pinctrl-single,bits = <
			/* EMA_WAIT[0], EMA_OE, EMA_WE, EMA_CS[3] */
			0x1c 0x10110010  0xf0ff00f0
			/*
			 * EMA_D[0], EMA_D[1], EMA_D[2],
			 * EMA_D[3], EMA_D[4], EMA_D[5],
			 * EMA_D[6], EMA_D[7]
			 */
			0x24 0x11111111  0xffffffff
			/*
			 * EMA_D[8],  EMA_D[9],  EMA_D[10],
			 * EMA_D[11], EMA_D[12], EMA_D[13],
			 * EMA_D[14], EMA_D[15]
			 */
			0x20 0x11111111  0xffffffff
			/* EMA_A[1], EMA_A[2] */
			0x30 0x01100000  0x0ff00000
		>;
	};
};

&serial1 {
	pinctrl-names = "default";
	pinctrl-0 = <&serial1_rxtx_pins>;
	status = "okay";
};

&serial2 {
	pinctrl-names = "default";
	pinctrl-0 = <&serial2_rxtx_pins>;
	status = "okay";
};


&wdt {
	status = "okay";
};

&rtc0 {
	status = "okay";
};

&gpio {
	status = "okay";
};

&mdio {
	pinctrl-names = "default";
	pinctrl-0 = <&mdio_pins>;
	bus_freq = <2200000>;
	status = "okay";
};

&eth0 {
	pinctrl-names = "default";
	pinctrl-0 = <&mii_pins>;
	status = "okay";
};

&aemif {
	pinctrl-names = "default";
	pinctrl-0 = <&nand_pins>;
	status = "okay";
	cs3 {
		#address-cells = <2>;
		#size-cells = <1>;
		clock-ranges;
		ranges;

		ti,cs-chipselect = <3>;

		nand@2000000,0 {
			compatible = "ti,davinci-nand";
			#address-cells = <1>;
			#size-cells = <1>;
			reg = <0 0x02000000 0x02000000
			       1 0x00000000 0x00008000>;

			ti,davinci-chipselect = <1>;
			ti,davinci-mask-ale = <0>;
			ti,davinci-mask-cle = <0>;
			ti,davinci-mask-chipsel = <0>;

			ti,davinci-nand-buswidth = <8>;
			ti,davinci-ecc-mode = "hw";
			ti,davinci-ecc-bits = <4>;
			ti,davinci-nand-use-bbt;

			partitions {
				compatible = "fixed-partitions";
				#address-cells = <1>;
				#size-cells = <1>;

				partition@0 {
					label = "u-boot env";
					reg = <0 0x020000>;
				};
				partition@20000 {
					/* The LCDK defaults to booting from this partition */
					label = "u-boot";
					reg = <0x020000 0x080000>;
				};
				partition@a0000 {
					label = "free space";
					reg = <0x0a0000 0>;
				};
			};
		};
	};
};

&prictrl {
	status = "okay";
};

&memctrl {
	status = "okay";
};


&dsp {
	memory-region = <&dsp_memory_region>;
	status = "okay";
};

arch/arm/mach-davinci/Kconfig

Create a new target, TARGET_MFOC, and source the Kconfig file located in board/davinci/mfoc.

 1diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig
 2index 25c5db4991..93ea114a94 100644
 3--- a/arch/arm/mach-davinci/Kconfig
 4+++ b/arch/arm/mach-davinci/Kconfig
 5@@ -4,6 +4,12 @@ choice
 6        prompt "DaVinci board select"
 7        optional
 8
 9+config TARGET_MFOC
10+       bool "MFOC"
11+       select SOC_DA8XX
12+       select SUPPORT_SPL
13+       select SPL_BOARD_INIT
14+
15 config TARGET_DA850EVM
16        bool "DA850 EVM board"
17        select MACH_DAVINCI_DA850_EVM
18@@ -132,6 +138,7 @@ config SYS_DA850_PLL1_PLLDIV3
19 endif
20
21 source "board/davinci/da8xxevm/Kconfig"
22+source "board/davinci/mfoc/Kconfig"
23 source "board/lego/ev3/Kconfig"
24
25 endif

board/davinci/mfoc/Kconfig

There was a time when U-boot instead of Kconfig had a database, boards.cfg, which contained information about CPU, SoC, Vendor, etc. for all supported boards.

Now these fields are split between a few Kconfig entries and the MAINTAINERS file. The fields translates as follow:

Status      ->  "S:" entry of MAINTAINERS
Arch        ->  CONFIG_SYS_ARCH defined by Kconfig
CPU         ->  CONFIG_SYS_CPU defined by Kconfig
SoC         ->  CONFIG_SYS_SOC defined by Kconfig
Vendor      ->  CONFIG_SYS_VENDOR defined by Kconfig
Board       ->  CONFIG_SYS_BOARD defined by Kconfig
Target      ->  File name of defconfig (configs/<target>_defconfig)
Maintainers ->  "M:" entry of MAINTAINERS

This is what my Kconfig file looks like:

 1diff --git a/board/davinci/mfoc/Kconfig b/board/davinci/mfoc/Kconfig
 2new file mode 100644
 3index 0000000000..762a1ba95d
 4--- /dev/null
 5+++ b/board/davinci/mfoc/Kconfig
 6@@ -0,0 +1,17 @@
 7+if TARGET_MFOC
 8+
 9+config SYS_BOARD
10+       default "MFOC"
11+
12+config SYS_VENDOR
13+       default "davinci"
14+
15+config SYS_CONFIG_NAME
16+       default "MFOC"
17+
18+config NAND_6BYTES_OOB_FREE_10BYTES_ECC
19+       def_bool y
20+
21+endif

It is important to define at least SYS_BOARD, SYS_VENDOR and SYS_CONFIG_NAME as those are used by the build system.

CONFIG_SYS_BOARD and CONFIG_SYS_VENDOR are used to compile board/<vendor>/common/* and board/<vendor>/<board>.

CONFIG_SYS_CONFIG_NAME="target" is used to include include/configs/<target>.h.

board/davinci/mfoc/Makefile

1# SPDX-License-Identifier: GPL-2.0+
2#
3# (C) Copyright 2024 MFOC
4
5obj-$(CONFIG_TARGET_MFOC)       += mfoc.o

board/davinci/mfoc/mfoc.c

  1// SPDX-License-Identifier: GPL-2.0+
  2/*
  3 * Copyright (C) 2024 MFOC
  4 *
  5 * Based on omapl138_lcdk.c. Original Copyrights follow:
  6 *
  7 * Copyright (C) 2009 Nick Thompson, GE Fanuc, Ltd. <nick.thompson@gefanuc.com>
  8 * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
  9 */
 10
 11#include <common.h>
 12#include <env.h>
 13#include <i2c.h>
 14#include <init.h>
 15#include <net.h>
 16#include <asm/arch/hardware.h>
 17#include <asm/global_data.h>
 18#include <asm/ti-common/davinci_nand.h>
 19#include <asm/io.h>
 20#include <ns16550.h>
 21#include <dm/platdata.h>
 22#include <linux/errno.h>
 23#include <asm/mach-types.h>
 24#include <asm/arch/davinci_misc.h>
 25#include <linux/mtd/rawnand.h>
 26#include <nand.h>
 27
 28DECLARE_GLOBAL_DATA_PTR;
 29
 30#define pinmux(x)	(&davinci_syscfg_regs->pinmux[x])
 31
 32/* UART pin muxer settings */
 33static const struct pinmux_config uart_pins[] = {
 34	{ pinmux(0), 4, 6 },
 35	{ pinmux(0), 4, 7 },
 36	{ pinmux(4), 2, 4 },
 37	{ pinmux(4), 2, 5 },
 38	{ pinmux(4), 2, 6 },
 39	{ pinmux(4), 2, 7 },
 40    { pinmux(11), 8, 6 }
 41};
 42
 43#ifdef CONFIG_DRIVER_TI_EMAC
 44static const struct pinmux_config emac_pins[] = {
 45	{ pinmux(2), 8, 1 },
 46	{ pinmux(2), 8, 2 },
 47	{ pinmux(2), 8, 3 },
 48	{ pinmux(2), 8, 4 },
 49	{ pinmux(2), 8, 5 },
 50	{ pinmux(2), 8, 6 },
 51	{ pinmux(2), 8, 7 },
 52	{ pinmux(3), 8, 0 },
 53	{ pinmux(3), 8, 1 },
 54	{ pinmux(3), 8, 2 },
 55	{ pinmux(3), 8, 3 },
 56	{ pinmux(3), 8, 4 },
 57	{ pinmux(3), 8, 5 },
 58	{ pinmux(3), 8, 6 },
 59	{ pinmux(3), 8, 7 },
 60	{ pinmux(4), 8, 0 },
 61	{ pinmux(4), 8, 1 }
 62};
 63#endif /* CONFIG_DRIVER_TI_EMAC */
 64
 65/* I2C pin muxer settings */
 66static const struct pinmux_config i2c_pins[] = {
 67	{ pinmux(4), 2, 2 },
 68	{ pinmux(4), 2, 3 }
 69};
 70
 71#ifdef CONFIG_NAND_DAVINCI
 72const struct pinmux_config nand_pins[] = {
 73	{ pinmux(7), 1, 1 },
 74	{ pinmux(7), 1, 2 },
 75	{ pinmux(7), 1, 4 },
 76	{ pinmux(7), 1, 5 },
 77	{ pinmux(8), 1, 0 },
 78	{ pinmux(8), 1, 1 },
 79	{ pinmux(8), 1, 2 },
 80	{ pinmux(8), 1, 3 },
 81	{ pinmux(8), 1, 4 },
 82	{ pinmux(8), 1, 5 },
 83	{ pinmux(8), 1, 6 },
 84	{ pinmux(8), 1, 7 },
 85	{ pinmux(9), 1, 0 },
 86	{ pinmux(9), 1, 1 },
 87	{ pinmux(9), 1, 2 },
 88	{ pinmux(9), 1, 3 },
 89	{ pinmux(9), 1, 4 },
 90	{ pinmux(9), 1, 5 },
 91	{ pinmux(9), 1, 6 },
 92	{ pinmux(9), 1, 7 },
 93	{ pinmux(12), 1, 5 },
 94	{ pinmux(12), 1, 6 }
 95};
 96
 97#endif
 98
 99#ifdef CONFIG_DRIVER_TI_EMAC_USE_RMII
100#define HAS_RMII 1
101#else
102#define HAS_RMII 0
103#endif
104
105const struct pinmux_resource pinmuxes[] = {
106	PINMUX_ITEM(uart_pins),
107	PINMUX_ITEM(i2c_pins),
108	PINMUX_ITEM(nand_pins),
109};
110
111const int pinmuxes_size = ARRAY_SIZE(pinmuxes);
112
113
114const struct pinmux_config gpio_pins[] = {
115    { pinmux(6), 8, 1 },
116    { pinmux(11), 8, 6 }
117};
118
119const struct lpsc_resource lpsc[] = {
120	{ DAVINCI_LPSC_AEMIF },	/* NAND, NOR */
121    { DAVINCI_LPSC_SPI1 },	/*[> Serial Flash <] */
122    { DAVINCI_LPSC_EMAC },	/*[> image download <] */
123    { DAVINCI_LPSC_UART1 },/*	[> console <] */
124    { DAVINCI_LPSC_UART2 },/*	[> console <] */
125    { DAVINCI_LPSC_GPIO },
126};
127
128const int lpsc_size = ARRAY_SIZE(lpsc);
129
130#ifndef CFG_DA850_EVM_MAX_CPU_CLK
131#define CFG_DA850_EVM_MAX_CPU_CLK	456000000
132#endif
133
134int board_early_init_f(void)
135{
136    unsigned int temp;
137
138    davinci_configure_pin_mux_items(pinmuxes, ARRAY_SIZE(pinmuxes));
139
140	/*
141	 * Power on required peripherals
142	 * ARM does not have access by default to PSC0 and PSC1
143	 * assuming here that the DSP bootloader has set the IOPU
144	 * such that PSC access is available to ARM
145	 */
146	if (da8xx_configure_lpsc_items(lpsc, ARRAY_SIZE(lpsc)))
147		return 1;
148
149	return 0;
150}
151
152int board_init(void)
153{
154	irq_init();
155
156	/* arch number of the board */
157	gd->bd->bi_arch_number = MACH_TYPE_OMAPL138_LCDK;
158
159	/* address of boot parameters */
160	gd->bd->bi_boot_params = LINUX_BOOT_PARAM_ADDR;
161
162
163	/* setup the SUSPSRC for ARM to control emulation suspend */
164	writel(readl(&davinci_syscfg_regs->suspsrc) &
165	       ~(DAVINCI_SYSCFG_SUSPSRC_EMAC | DAVINCI_SYSCFG_SUSPSRC_I2C |
166		 DAVINCI_SYSCFG_SUSPSRC_SPI1 | DAVINCI_SYSCFG_SUSPSRC_TIMER0 |
167		 DAVINCI_SYSCFG_SUSPSRC_UART1 | DAVINCI_SYSCFG_SUSPSRC_UART2),
168	       &davinci_syscfg_regs->suspsrc);
169
170	/* configure pinmux settings */
171	if (davinci_configure_pin_mux_items(pinmuxes, ARRAY_SIZE(pinmuxes)))
172		return 1;
173
174#ifdef CONFIG_DRIVER_TI_EMAC
175	if (davinci_configure_pin_mux(emac_pins, ARRAY_SIZE(emac_pins)) != 0)
176		return 1;
177	davinci_emac_mii_mode_sel(HAS_RMII);
178#endif /* CONFIG_DRIVER_TI_EMAC */
179
180	return 0;
181}
182
183#define CFG_MAC_ADDR_SPI_BUS	0
184#define CFG_MAC_ADDR_SPI_CS	0
185#define CFG_MAC_ADDR_SPI_MAX_HZ	CONFIG_SF_DEFAULT_SPEED
186#define CFG_MAC_ADDR_SPI_MODE	SPI_MODE_3
187
188#define CFG_MAC_ADDR_OFFSET	(flash->size - SZ_64K)
189
190void dsp_lpsc_on(unsigned domain, unsigned int id)
191{
192	dv_reg_p mdstat, mdctl, ptstat, ptcmd;
193	struct davinci_psc_regs *psc_regs;
194
195	psc_regs = davinci_psc0_regs;
196	mdstat = &psc_regs->psc0.mdstat[id];
197	mdctl = &psc_regs->psc0.mdctl[id];
198	ptstat = &psc_regs->ptstat;
199	ptcmd = &psc_regs->ptcmd;
200
201	while (*ptstat & (0x1 << domain))
202		;
203
204	if ((*mdstat & 0x1f) == 0x03)
205		return;                 /* Already on and enabled */
206
207	*mdctl |= 0x03;
208
209	*ptcmd = 0x1 << domain;
210
211	while (*ptstat & (0x1 << domain))
212		;
213	while ((*mdstat & 0x1f) != 0x03)
214		;		/* Probably an overkill... */
215}
216
217static void dspwake(void)
218{
219	unsigned *resetvect = (unsigned *)DAVINCI_L3CBARAM_BASE;
220
221	/* if the device is ARM only, return */
222	if ((REG(CHIP_REV_ID_REG) & 0x3f) == 0x10)
223		return;
224
225	if (!strcmp(env_get("dspwake"), "no"))
226		return;
227
228	*resetvect++ = 0x1E000; /* DSP Idle */
229	/* clear out the next 10 words as NOP */
230	memset(resetvect, 0, sizeof(unsigned) * 10);
231
232	/* setup the DSP reset vector */
233	REG(HOST1CFG) = DAVINCI_L3CBARAM_BASE;
234
235	dsp_lpsc_on(1, DAVINCI_LPSC_GEM);
236	REG(PSC0_MDCTL + (15 * 4)) |= 0x100;
237}
238
239#ifdef CONFIG_DRIVER_TI_EMAC_USE_RMII
240/**
241 * rmii_hw_init
242 *
243 */
244int rmii_hw_init(void)
245{
246	return 0;
247}
248#endif /* CONFIG_DRIVER_TI_EMAC_USE_RMII */
249
250int misc_init_r(void)
251{
252#ifdef CONFIG_DRIVER_TI_EMAC_USE_RMII
253	/* Select RMII fucntion through the expander */
254	if (rmii_hw_init())
255		printf("RMII hardware init failed!!!\n");
256#endif
257
258	dspwake();
259
260	return 0;
261}
262
263static const struct ns16550_plat serial_pdata = {
264	.base = DAVINCI_UART1_BASE,
265	.reg_shift = 2,
266	.clock = 228000000,
267	.fcr = UART_FCR_DEFVAL,
268};
269
270U_BOOT_DRVINFO(omapl138_uart) = {
271	.name = "ns16550_serial",
272	.plat = &serial_pdata,
273};
274
275#ifdef CONFIG_SPL_BUILD
276void spl_board_init(void)
277{
278    davinci_configure_pin_mux_items(pinmuxes, ARRAY_SIZE(pinmuxes));
279    da8xx_configure_lpsc_items(lpsc, ARRAY_SIZE(lpsc));
280
281    /* Setup proper NAND timing already in the SPL */
282    writel((DAVINCI_ABCR_WSETUP(2) |
283                DAVINCI_ABCR_WSTROBE(1) |
284                DAVINCI_ABCR_WHOLD(1) |
285                DAVINCI_ABCR_RSETUP(1) |
286                DAVINCI_ABCR_RSTROBE(3) |
287                DAVINCI_ABCR_RHOLD(2) |
288                DAVINCI_ABCR_TA(3) |
289                DAVINCI_ABCR_ASIZE_8BIT),
290            &davinci_emif_regs->ab2cr);
291}
292#endif

board/davinci/mfoc/u-boot-spl-mfoc.lds

 1/* SPDX-License-Identifier: GPL-2.0+ */
 2/*
 3 * (C) Copyright 2002
 4 * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
 5 *
 6 * (C) Copyright 2008
 7 * Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de>
 8 */
 9
10MEMORY { .sram : ORIGIN = IMAGE_TEXT_BASE,\
11		LENGTH = CONFIG_SPL_MAX_FOOTPRINT }
12
13MEMORY { .sdram : ORIGIN = CONFIG_SPL_BSS_START_ADDR, \
14                LENGTH = 0x1080000 }
15
16OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
17OUTPUT_ARCH(arm)
18ENTRY(_start)
19SECTIONS
20{
21	. = 0x00000000;
22
23	. = ALIGN(4);
24	.text      :
25	{
26	__start = .;
27	  *(.vectors)
28	  arch/arm/cpu/arm926ejs/start.o	(.text*)
29	  *(.text*)
30	} >.sram
31
32	. = ALIGN(4);
33	.rodata : { *(SORT_BY_ALIGNMENT(.rodata*)) } >.sram
34
35	. = ALIGN(4);
36	.data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram
37
38	. = ALIGN(4);
39	__u_boot_list : { KEEP(*(SORT(__u_boot_list*))); } >.sram
40
41	. = ALIGN(4);
42	.rel.dyn : {
43		__rel_dyn_start = .;
44		*(.rel*)
45		__rel_dyn_end = .;
46	} >.sram
47
48	__image_copy_end = .;
49
50	.end :
51	{
52		*(.__end)
53	}
54
55	_image_binary_end = .;
56
57	.bss :
58	{
59		. = ALIGN(4);
60		__bss_start = .;
61		*(.bss*)
62		. = ALIGN(4);
63		__bss_end = .;
64	} >.sram
65}

configs/mfoc_defconfig

CONFIG_ARM=y
CONFIG_SKIP_LOWLEVEL_INIT_ONLY=y
CONFIG_SPL_SKIP_LOWLEVEL_INIT_ONLY=y
CONFIG_SYS_THUMB_BUILD=y
CONFIG_ARCH_DAVINCI=y
CONFIG_TEXT_BASE=0xc1080000
CONFIG_SYS_MALLOC_LEN=0x110000
CONFIG_SYS_MALLOC_F_LEN=0x800
CONFIG_TARGET_MFOC=y
CONFIG_SYS_DA850_PLL0_POSTDIV=0
CONFIG_SYS_DA850_PLL1_PLLDIV3=0x8003
CONFIG_TI_COMMON_CMD_OPTIONS=y
CONFIG_SPL_LIBCOMMON_SUPPORT=y
CONFIG_SPL_LIBGENERIC_SUPPORT=y
CONFIG_NR_DRAM_BANKS=1
CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0xc0000f20
CONFIG_ENV_SIZE=0x10000
CONFIG_ENV_OFFSET=0x0
CONFIG_DM_GPIO=y
CONFIG_DEFAULT_DEVICE_TREE="da850-mfoc"
CONFIG_SPL_TEXT_BASE=0x80000000
CONFIG_SPL_SERIAL=y
CONFIG_SPL_STACK=0x8001ff00
CONFIG_SPL=y
CONFIG_SPL_LIBDISK_SUPPORT=y
CONFIG_SYS_LOAD_ADDR=0xc0700000
CONFIG_SPL_PAYLOAD="u-boot.img"
CONFIG_SYS_MONITOR_LEN=1048576
CONFIG_DYNAMIC_SYS_CLK_FREQ=y
CONFIG_BOOTDELAY=3
CONFIG_USE_BOOTCOMMAND=y
CONFIG_BOOTCOMMAND="run envboot; run mmcboot; "
CONFIG_LOGLEVEL=3
# CONFIG_DISPLAY_CPUINFO is not set
CONFIG_BOARD_EARLY_INIT_F=y
CONFIG_CLOCKS=y
CONFIG_MISC_INIT_R=y
CONFIG_SPL_PAD_TO=0x8000
CONFIG_SPL_FOOTPRINT_LIMIT=y
CONFIG_SPL_MAX_FOOTPRINT=0x8000
CONFIG_SPL_SHOW_ERRORS=y
CONFIG_SPL_SYS_MALLOC_SIMPLE=y
# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set
CONFIG_SYS_SPL_MALLOC=y
CONFIG_HAS_CUSTOM_SPL_MALLOC_START=y
CONFIG_CUSTOM_SYS_SPL_MALLOC_ADDR=0xc0f70000
CONFIG_SYS_SPL_MALLOC_SIZE=0x110000
# CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR is not set
CONFIG_SPL_NAND_SUPPORT=y
CONFIG_SPL_NAND_RAW_ONLY=y
CONFIG_SPL_NAND_DRIVERS=y
CONFIG_SPL_NAND_ECC=y
CONFIG_SPL_NAND_SIMPLE=y
CONFIG_SPL_NAND_BASE=y
CONFIG_SPL_NAND_IDENT=y
CONFIG_SPL_RAM_SUPPORT=y
CONFIG_HUSH_PARSER=y
# CONFIG_SYS_LONGHELP is not set
# CONFIG_CMD_ENV_EXISTS is not set
CONFIG_CRC32_VERIFY=y
# CONFIG_CMD_EEPROM is not set
CONFIG_CMD_MX_CYCLIC=y
CONFIG_CMD_DM=y
# CONFIG_CMD_FLASH is not set
CONFIG_CMD_NAND=y
# CONFIG_CMD_PINMUX is not set
# CONFIG_CMD_SETEXPR is not set
CONFIG_BOOTP_DNS2=y
CONFIG_CMD_MTDPARTS=y
CONFIG_CMD_DIAG=y
CONFIG_CMD_UBI=y
CONFIG_OF_CONTROL=y
CONFIG_ENV_IS_IN_NAND=y
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_USE_BOOTFILE=y
CONFIG_BOOTFILE="zImage"
CONFIG_VERSION_VARIABLE=y
CONFIG_NET_RETRY_COUNT=10
CONFIG_BOOTP_SEND_HOSTNAME=y
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_SPL_DM=y
CONFIG_SPL_DM_SEQ_ALIAS=y
CONFIG_DA8XX_GPIO=y
CONFIG_DM_I2C=y
CONFIG_SYS_I2C_DAVINCI=y
CONFIG_MTD=y
CONFIG_DM_MTD=y
CONFIG_MTD_RAW_NAND=y
CONFIG_SYS_NAND_USE_FLASH_BBT=y
CONFIG_NAND_DAVINCI=y
CONFIG_SYS_NAND_BLOCK_SIZE=0x20000
CONFIG_SYS_NAND_PAGE_COUNT=0x40
CONFIG_SYS_NAND_PAGE_SIZE=0x800
CONFIG_SYS_NAND_OOBSIZE=0x40
CONFIG_SYS_NAND_U_BOOT_LOCATIONS=y
CONFIG_SYS_NAND_U_BOOT_OFFS=0x100000
CONFIG_SYS_NAND_U_BOOT_OFFS_REDUND=0x28000
CONFIG_SYS_NAND_HW_ECC_OOBFIRST=y
CONFIG_MII=y
CONFIG_DRIVER_TI_EMAC=y
CONFIG_PHY=y
CONFIG_PHY_DA8XX_USB=y
CONFIG_PINCTRL=y
CONFIG_PINCTRL_SINGLE=y
CONFIG_SPECIFY_CONSOLE_INDEX=y
CONFIG_DM_SERIAL=y
CONFIG_SYS_NS16550=y
CONFIG_USB=y
# CONFIG_SPL_DM_USB is not set
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_OHCI_DA8XX=y
CONFIG_USB_MUSB_HOST=y
CONFIG_USB_MUSB_DA8XX=y
CONFIG_USB_MUSB_PIO_ONLY=y
CONFIG_USB_STORAGE=y
# CONFIG_FAT_WRITE is not set
CONFIG_SPL_OF_LIBFDT=y

include/configs/mfoc.h

 1/* SPDX-License-Identifier: GPL-2.0 */
 2/*
 3 * Copyright (C) 2024 MFOC
 4 *
 5 * Based on davinci_dvevm.h. Original Copyrights follow:
 6 *
 7 * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net>
 8 */
 9
10#ifndef __CONFIG_H
11#define __CONFIG_H
12/*
13 * SoC Configuration
14 */
15#define CFG_SYS_OSCIN_FREQ		24000000
16#define CFG_SYS_TIMERBASE		DAVINCI_TIMER0_BASE
17#define CFG_SYS_HZ_CLOCK		clk_get(DAVINCI_AUXCLK_CLKID)
18
19/*
20 * Memory Info
21 */
22#define PHYS_SDRAM_1		DAVINCI_DDR_EMIF_DATA_BASE /* DDR Start */
23#define PHYS_SDRAM_1_SIZE	(128 << 20) /* SDRAM size 128MB */
24#define CFG_MAX_RAM_BANK_SIZE (512 << 20) /* max size from SPRS586*/
25
26#define CFG_SYS_DA850_SYSCFG_SUSPSRC (	\
27	DAVINCI_SYSCFG_SUSPSRC_TIMER0 |		\
28	DAVINCI_SYSCFG_SUSPSRC_SPI1 |		\
29	DAVINCI_SYSCFG_SUSPSRC_UART1 |		\
30	DAVINCI_SYSCFG_SUSPSRC_EMAC |		\
31	DAVINCI_SYSCFG_SUSPSRC_I2C)
32
33/*
34 * PLL configuration
35 */
36
37/* Requires CONFIG_SYS_DA850_PLL0_POSTDIV=0, set in Kconfig */
38#define CFG_SYS_DA850_PLL0_PLLM     18
39#define CFG_SYS_DA850_PLL1_PLLM     21
40
41/*
42 * DDR2 memory configuration
43 */
44#define CFG_SYS_DA850_DDR2_DDRPHYCR (0x000000c4)
45#define CFG_SYS_DA850_DDR2_SDBCR (0x02074622)
46
47/* SDBCR2 is only used if IBANK_POS bit in SDBCR is set */
48#define CFG_SYS_DA850_DDR2_SDBCR2 0
49#define CFG_SYS_DA850_DDR2_SDTIMR (0x129129c8)
50#define CFG_SYS_DA850_DDR2_SDTIMR2 (0x380f7000)
51#define CFG_SYS_DA850_DDR2_SDRCR    0x0000040d
52#define CFG_SYS_DA850_DDR2_PBBPR    0x30
53
54/*
55 * Serial Driver info
56 */
57#define CFG_SYS_NS16550_CLK	clk_get(DAVINCI_UART2_CLKID)
58
59#define CFG_SYS_SPI_BASE		DAVINCI_SPI1_BASE
60#define CFG_SYS_SPI_CLK		clk_get(DAVINCI_SPI1_CLKID)
61
62/*
63 * Flash & Environment
64 */
65#ifdef CONFIG_MTD_RAW_NAND
66#define CFG_SYS_NAND_CS		3
67#define CFG_SYS_NAND_BASE		DAVINCI_ASYNC_EMIF_DATA_CE3_BASE
68#define CFG_SYS_NAND_MASK_CLE	0x10
69#define CFG_SYS_NAND_MASK_ALE	0x8
70#define CFG_SYS_NAND_U_BOOT_SIZE	SZ_512K
71#define CFG_SYS_NAND_U_BOOT_DST	0xc1080000
72#define CFG_SYS_NAND_U_BOOT_START	CFG_SYS_NAND_U_BOOT_DST
73#define CFG_SYS_NAND_ECCPOS		{				\
74				6, 7, 8, 9, 10, 11, 12, 13, 14, 15,	\
75				22, 23, 24, 25, 26, 27, 28, 29, 30, 31, \
76				38, 39, 40, 41, 42, 43, 44, 45, 46, 47, \
77				54, 55, 56, 57, 58, 59, 60, 61, 62, 63 }
78#define CFG_SYS_NAND_ECCSIZE		512
79#define CFG_SYS_NAND_ECCBYTES	10
80#endif
81
82/*
83 * U-Boot general configuration
84 */
85
86/*
87 * Linux Information
88 */
89#define LINUX_BOOT_PARAM_ADDR	(PHYS_SDRAM_1 + 0x100)
90
91#define CFG_EXTRA_ENV_SETTINGS \
92	"console=ttyS1,115200n8\0"
93
94/* additions for new relocation code, must added to all boards */
95#define CFG_SYS_SDRAM_BASE		0xc0000000
96
97#include <asm/arch/hardware.h>
98
99#endif /* __CONFIG_H */

Wrap it up

Last check

Run checkpatch and fix all warnings/errors before create a merge request.

1$ ./scripts/checkpatch.pl  --git HEAD
2# Fix all warnings and errors
3$ git commit -a --amend

And we are ready to push!

Summary

It's easy to underestimate the work and time required to start from scratch with a board. There are usually few opportunities to be able to debug in a good way, slow program loading (changing DIP switches, power-cycling the board, etc.) which means that each iteration takes time.

If you encounter an unexpected problem (the configuration of the SDRAM in my case) it can easily drag on for a long time.

But it is also among the assignments I find the most fun!

/media/omapl138-starting-kernel.png