From: Rouven Czerwinski <r.czerwinski@pengutronix.de>
Date: Tue, 15 Jun 2021 21:18:38 +0200
Subject: [PATCH] ARM: stm32mp: add Linux Automation TAC board
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Add support for the Linux Automation GmbH Test Automation
Controller (TAC). The board boots from eMMC, but requires USB loading if
no previous barebox has been put into the eMMC boot partition.

Signed-off-by: Leonard Göhrs <l.goehrs@pengutronix.de>
Signed-off-by: Rouven Czerwinski <r.czerwinski@pengutronix.de>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Upstream-Status: Pending
---
 arch/arm/boards/Makefile                  |   1 +
 arch/arm/boards/lxa-tac/Makefile          |   2 +
 arch/arm/boards/lxa-tac/board.c           |  49 +++++++++++
 arch/arm/boards/lxa-tac/lowlevel.c        |  77 +++++++++++++++++
 arch/arm/dts/Makefile                     |   2 +
 arch/arm/dts/stm32mp153c-lxa-tac-gen3.dts |  38 ++++++++
 arch/arm/dts/stm32mp157c-lxa-tac-gen1.dts |   7 ++
 arch/arm/dts/stm32mp157c-lxa-tac-gen2.dts |  38 ++++++++
 arch/arm/dts/stm32mp15xc-lxa-tac.dtsi     | 138 ++++++++++++++++++++++++++++++
 arch/arm/mach-stm32mp/Kconfig             |   5 ++
 images/Makefile.stm32mp                   |   4 +
 11 files changed, 361 insertions(+)
 create mode 100644 arch/arm/boards/lxa-tac/Makefile
 create mode 100644 arch/arm/boards/lxa-tac/board.c
 create mode 100644 arch/arm/boards/lxa-tac/lowlevel.c
 create mode 100644 arch/arm/dts/stm32mp153c-lxa-tac-gen3.dts
 create mode 100644 arch/arm/dts/stm32mp157c-lxa-tac-gen1.dts
 create mode 100644 arch/arm/dts/stm32mp157c-lxa-tac-gen2.dts
 create mode 100644 arch/arm/dts/stm32mp15xc-lxa-tac.dtsi

diff --git a/arch/arm/boards/Makefile b/arch/arm/boards/Makefile
index e0dc27cb3d21..e36fd78aa3f1 100644
--- a/arch/arm/boards/Makefile
+++ b/arch/arm/boards/Makefile
@@ -122,6 +122,7 @@ obj-$(CONFIG_MACH_SOLIDRUN_MICROSOM)		+= solidrun-microsom/
 obj-$(CONFIG_MACH_STM32MP15XX_DKX)		+= stm32mp15xx-dkx/
 obj-$(CONFIG_MACH_STM32MP13XX_DK)		+= stm32mp13xx-dk/
 obj-$(CONFIG_MACH_LXA_MC1)			+= lxa-mc1/
+obj-$(CONFIG_MACH_LXA_TAC)			+= lxa-tac/
 obj-$(CONFIG_MACH_STM32MP15X_EV1)		+= stm32mp15x-ev1/
 obj-$(CONFIG_MACH_TECHNEXION_PICO_HOBBIT)	+= technexion-pico-hobbit/
 obj-$(CONFIG_MACH_TECHNEXION_WANDBOARD)		+= technexion-wandboard/
diff --git a/arch/arm/boards/lxa-tac/Makefile b/arch/arm/boards/lxa-tac/Makefile
new file mode 100644
index 000000000000..092c31d6b28d
--- /dev/null
+++ b/arch/arm/boards/lxa-tac/Makefile
@@ -0,0 +1,2 @@
+lwl-y += lowlevel.o
+obj-y += board.o
diff --git a/arch/arm/boards/lxa-tac/board.c b/arch/arm/boards/lxa-tac/board.c
new file mode 100644
index 000000000000..d124452d09c3
--- /dev/null
+++ b/arch/arm/boards/lxa-tac/board.c
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-2.0+
+#include <common.h>
+#include <linux/sizes.h>
+#include <init.h>
+#include <asm/memory.h>
+#include <mach/stm32mp/bbu.h>
+#include <bootsource.h>
+#include <deep-probe.h>
+#include <of.h>
+#include <tlv/tlv.h>
+#include <boards/lxa/tlv.h>
+
+static int tac_probe(struct device *dev)
+{
+	struct tlv_device *tlvdev;
+	int ret;
+
+	barebox_set_hostname("lxatac");
+
+	stm32mp_bbu_mmc_fip_register("mmc", "/dev/mmc1", BBU_HANDLER_FLAG_DEFAULT);
+
+	ret = lxa_tlv_v1_register();
+	if (ret)
+		return ret;
+
+	tlvdev = tlv_ensure_probed_by_alias("factory-data");
+	if (!IS_ERR_OR_NULL(tlvdev)) {
+		printf("tlvdev = %p\n", tlvdev);
+		dev_info(dev, "HW release: %s\n",
+			 dev_get_param(&tlvdev->dev, "device-hardware-release"));
+	}
+
+	return 0;
+}
+
+static const struct of_device_id tac_of_match[] = {
+	{ .compatible = "lxa,stm32mp157c-tac-gen1" },
+	{ .compatible = "lxa,stm32mp157c-tac-gen2" },
+	{ .compatible = "lxa,stm32mp153c-tac-gen3" },
+	{ /* sentinel */ },
+};
+BAREBOX_DEEP_PROBE_ENABLE(tac_of_match);
+
+static struct driver tac_board_driver = {
+	.name = "board-lxa-tac",
+	.probe = tac_probe,
+	.of_compatible = tac_of_match,
+};
+late_platform_driver(tac_board_driver);
diff --git a/arch/arm/boards/lxa-tac/lowlevel.c b/arch/arm/boards/lxa-tac/lowlevel.c
new file mode 100644
index 000000000000..75e13417c209
--- /dev/null
+++ b/arch/arm/boards/lxa-tac/lowlevel.c
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: GPL-2.0+
+#include <common.h>
+#include <debug_ll.h>
+#include <mach/stm32mp/entry.h>
+#include <soc/stm32/gpio.h>
+
+extern char __dtb_z_stm32mp157c_lxa_tac_gen1_start[];
+extern char __dtb_z_stm32mp157c_lxa_tac_gen2_start[];
+extern char __dtb_z_stm32mp153c_lxa_tac_gen3_start[];
+
+/*
+ * Major board generation is set via traces in copper
+ * Minor board generation can be changed via resistors.
+ * The revision is available on GPIOs:
+ * [PZ0, PZ1, PZ2, PZ3, PZ6, PZ7]
+ */
+#define BOARD_GEN(major, minor) (major << 2 | minor)
+#define BOARD_GEN1 BOARD_GEN(0, 0)
+#define BOARD_GEN2 BOARD_GEN(1, 0)
+#define BOARD_GEN3 BOARD_GEN(2, 0)
+
+#define RCC_MP_AHB5ENSETR ((void *)0x50000210)
+#define GPIOZ_BASE ((void *)0x54004000)
+
+static const int board_rev_pins[] = {0, 1, 2, 3, 6, 7};
+
+static u32 get_board_rev(void)
+{
+	u32 board_rev = 0;
+	size_t i;
+
+	/* Enable GPIOZ bank */
+	setbits_le32(RCC_MP_AHB5ENSETR, BIT(0));
+
+	for (i = 0; i < ARRAY_SIZE(board_rev_pins); i++) {
+		int pin = board_rev_pins[i];
+
+		__stm32_pmx_gpio_input(GPIOZ_BASE, pin);
+		board_rev |= __stm32_pmx_gpio_get(GPIOZ_BASE, pin) << i;
+	}
+
+	return board_rev;
+}
+
+static void noinline select_fdt_and_start(void *fdt)
+{
+	putc_ll('>');
+
+	switch (get_board_rev()) {
+	case BOARD_GEN1:
+		fdt = __dtb_z_stm32mp157c_lxa_tac_gen1_start +
+			get_runtime_offset();
+		break;
+	case BOARD_GEN2:
+		fdt = __dtb_z_stm32mp157c_lxa_tac_gen2_start +
+			get_runtime_offset();
+		break;
+	case BOARD_GEN3:
+		fdt = __dtb_z_stm32mp153c_lxa_tac_gen3_start +
+			get_runtime_offset();
+		break;
+	}
+
+	stm32mp1_barebox_entry(fdt);
+}
+
+ENTRY_FUNCTION(start_stm32mp15xc_lxa_tac, r0, r1, r2)
+{
+	stm32mp_cpu_lowlevel_init();
+
+	/*
+	 * stm32mp_cpu_lowlevel_init sets up a stack. Do the remaining
+	 * init in a non-naked function. Register r2 points to the fdt
+	 * from the FIT image which can be used as a default.
+	 */
+	select_fdt_and_start((void *)r2);
+}
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 3b3236b4165f..bcdc8d607c35 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -149,6 +149,8 @@ lwl-$(CONFIG_MACH_STM32MP15XX_DKX) += stm32mp157c-dk2.dtb.o stm32mp157a-dk1.dtb.
 					stm32mp157c-dk2-scmi.dtb.o stm32mp157a-dk1-scmi.dtb.o
 lwl-$(CONFIG_MACH_STM32MP13XX_DK) += stm32mp135f-dk.dtb.o
 lwl-$(CONFIG_MACH_LXA_MC1) += stm32mp157c-lxa-mc1.dtb.o stm32mp157c-lxa-mc1-scmi.dtb.o
+lwl-$(CONFIG_MACH_LXA_TAC) += stm32mp157c-lxa-tac-gen1.dtb.o stm32mp157c-lxa-tac-gen2.dtb.o \
+				stm32mp153c-lxa-tac-gen3.dtb.o
 lwl-$(CONFIG_MACH_STM32MP15X_EV1) += stm32mp157c-ev1.dtb.o stm32mp157c-ev1-scmi.dtb.o
 lwl-$(CONFIG_MACH_SCB9328) += imx1-scb9328.dtb.o
 lwl-$(CONFIG_MACH_TECHNEXION_WANDBOARD) += imx6q-wandboard.dtb.o imx6dl-wandboard.dtb.o
diff --git a/arch/arm/dts/stm32mp153c-lxa-tac-gen3.dts b/arch/arm/dts/stm32mp153c-lxa-tac-gen3.dts
new file mode 100644
index 000000000000..ab46e11d396d
--- /dev/null
+++ b/arch/arm/dts/stm32mp153c-lxa-tac-gen3.dts
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (C) 2024 Leonard Göhrs, Pengutronix
+ */
+
+#include <arm/st/stm32mp153c-lxa-tac-gen3.dts>
+#include "stm32mp15xc-lxa-tac.dtsi"
+
+/ {
+	led-controller-pwm {
+		compatible = "pwm-leds";
+
+		led-status-red {
+			label = "pwm:red:status";
+			pwms = <&led_pwm 0 1000000 0>;
+			active-low;
+			max-brightness = <255>;
+		};
+
+		led-status-green {
+			label = "pwm:green:status";
+			pwms = <&led_pwm 2 1000000 0>;
+			active-low;
+			max-brightness = <255>;
+		};
+
+		led-status-blue {
+			label = "pwm:blue:status";
+			pwms = <&led_pwm 1 1000000 0>;
+			active-low;
+			max-brightness = <255>;
+		};
+	};
+
+	led-controller-1 {
+		status = "disabled";
+	};
+};
diff --git a/arch/arm/dts/stm32mp157c-lxa-tac-gen1.dts b/arch/arm/dts/stm32mp157c-lxa-tac-gen1.dts
new file mode 100644
index 000000000000..47b764f13242
--- /dev/null
+++ b/arch/arm/dts/stm32mp157c-lxa-tac-gen1.dts
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (C) 2023 Leonard Göhrs, Pengutronix
+ */
+
+#include <arm/st/stm32mp157c-lxa-tac-gen1.dts>
+#include "stm32mp15xc-lxa-tac.dtsi"
diff --git a/arch/arm/dts/stm32mp157c-lxa-tac-gen2.dts b/arch/arm/dts/stm32mp157c-lxa-tac-gen2.dts
new file mode 100644
index 000000000000..f5261203f8ef
--- /dev/null
+++ b/arch/arm/dts/stm32mp157c-lxa-tac-gen2.dts
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (C) 2023 Leonard Göhrs, Pengutronix
+ */
+
+#include <arm/st/stm32mp157c-lxa-tac-gen2.dts>
+#include "stm32mp15xc-lxa-tac.dtsi"
+
+/ {
+	led-controller-pwm {
+		compatible = "pwm-leds";
+
+		led-status-red {
+			label = "pwm:red:status";
+			pwms = <&led_pwm 0 1000000 0>;
+			active-low;
+			max-brightness = <255>;
+		};
+
+		led-status-green {
+			label = "pwm:green:status";
+			pwms = <&led_pwm 2 1000000 0>;
+			active-low;
+			max-brightness = <255>;
+		};
+
+		led-status-blue {
+			label = "pwm:blue:status";
+			pwms = <&led_pwm 1 1000000 0>;
+			active-low;
+			max-brightness = <255>;
+		};
+	};
+
+	led-controller-1 {
+		status = "disabled";
+	};
+};
diff --git a/arch/arm/dts/stm32mp15xc-lxa-tac.dtsi b/arch/arm/dts/stm32mp15xc-lxa-tac.dtsi
new file mode 100644
index 000000000000..33f83e035457
--- /dev/null
+++ b/arch/arm/dts/stm32mp15xc-lxa-tac.dtsi
@@ -0,0 +1,138 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (C) 2020 Ahmad Fatoum, Pengutronix
+ */
+
+#include "stm32mp151.dtsi"
+
+/ {
+	chosen {
+		environment {
+			compatible = "barebox,environment";
+			device-path = &environment_emmc;
+		};
+	};
+
+	aliases {
+		state = &state_emmc;
+		baseboard-factory-data = &baseboard_factory_data;
+		powerboard-factory-data = &powerboard_factory_data;
+	};
+
+	baseboard_factory_data: baseboard-factory-data {
+		compatible = "lxa,tlv-baseboard-v1";
+		backend = <&baseboard_tlv_backend>;
+	};
+
+	powerboard_factory_data: powerboard-factory-data {
+		compatible = "lxa,tlv-powerboard-v1";
+		backend = <&powerboard_tlv_backend>;
+	};
+
+	reserved-memory {
+		ramoops {
+			compatible = "ramoops";
+			/* Everything else will be fixed up at runtime */
+		};
+	};
+
+	state_emmc: state {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "barebox,state";
+		magic = <0xfee2ea9b>;
+		backend-type = "raw";
+		backend = <&backend_state_emmc>;
+		backend-stridesize = <0x1000>;
+
+		bootstate {
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			system0 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+
+				remaining_attempts@0 {
+					reg = <0x0 0x4>;
+					type = "uint32";
+					default = <3>;
+				};
+
+				priority@4 {
+					reg = <0x4 0x4>;
+					type = "uint32";
+					default = <20>;
+				};
+			};
+
+			system1 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+
+				remaining_attempts@8 {
+					reg = <0x8 0x4>;
+					type = "uint32";
+					default = <0>;
+				};
+
+				priority@c {
+					reg = <0xc 0x4>;
+					type = "uint32";
+					default = <0>;
+				};
+			};
+
+			last_chosen@10 {
+				reg = <0x10 0x4>;
+				type = "uint32";
+			};
+		};
+	};
+};
+
+&baseboard_eeprom {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	baseboard_tlv_backend: factory-data@0 {
+		reg = <0 0x400>;
+		label = "tlv";
+	};
+};
+
+&powerboard_eeprom {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	powerboard_tlv_backend: factory-data@0 {
+		reg = <0 0x100>;
+		label = "tlv";
+	};
+};
+
+&sdmmc2 {
+	partitions {
+		compatible = "fixed-partitions";
+		#address-cells = <2>;
+		#size-cells = <2>;
+
+		environment_emmc: partition@80000 {
+			label = "barebox-environment";
+			reg = <0 0x80000 0 0x40000>;
+		};
+
+		backend_state_emmc: partition@c0000 {
+			label = "barebox-state";
+			reg = <0 0xc0000 0 0x40000>;
+		};
+	};
+};
+
+&usbh_ehci {
+	status = "disabled";
+};
+
+&usbh_ohci {
+	status = "okay";
+};
diff --git a/arch/arm/mach-stm32mp/Kconfig b/arch/arm/mach-stm32mp/Kconfig
index 5d60c7996786..ddf2451a49c5 100644
--- a/arch/arm/mach-stm32mp/Kconfig
+++ b/arch/arm/mach-stm32mp/Kconfig
@@ -29,6 +29,11 @@ config MACH_LXA_MC1
 	select ARCH_STM32MP157
 	bool "Linux Automation MC-1 board"
 
+config MACH_LXA_TAC
+	select ARCH_STM32MP157
+	bool "Linux Automation TAC board"
+	select BOARD_LXA
+
 config MACH_SEEED_ODYSSEY
 	select ARCH_STM32MP157
 	bool "Seeed Studio Odyssey"
diff --git a/images/Makefile.stm32mp b/images/Makefile.stm32mp
index cb01eb2555e8..9be7a14d0f14 100644
--- a/images/Makefile.stm32mp
+++ b/images/Makefile.stm32mp
@@ -35,6 +35,10 @@ $(call build_stm32mp_image, CONFIG_MACH_STM32MP15X_EV1, start_stm32mp15x_ev1, st
 
 $(call build_stm32mp_image, CONFIG_MACH_LXA_MC1, start_stm32mp157c_lxa_mc1, stm32mp157c-lxa-mc1)
 
+pblb-$(CONFIG_MACH_LXA_TAC) += start_stm32mp15xc_lxa_tac
+FILE_barebox-stm32mp15xc-lxa-tac.img  = start_stm32mp15xc_lxa_tac.pblb
+image-$(CONFIG_MACH_LXA_TAC) += barebox-stm32mp15xc-lxa-tac.img
+
 $(call build_stm32mp_image, CONFIG_MACH_PROTONIC_STM32MP1, start_prtt1a, prtt1a)
 $(call build_stm32mp_image, CONFIG_MACH_PROTONIC_STM32MP1, start_prtt1s, prtt1s)
 $(call build_stm32mp_image, CONFIG_MACH_PROTONIC_STM32MP1, start_prtt1c, prtt1c)
