From d4e7cb5ebda61bcbb194859a3ea3d4b8da27db57 Mon Sep 17 00:00:00 2001
From: Robert Nelson <robertcnelson@gmail.com>
Date: Thu, 21 Oct 2021 16:04:55 -0500
Subject: [PATCH] U-Boot-BeagleBone-Cape-Manager

Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
---
 board/ti/am335x/board.c           | 466 ++++++++++++++++++++++++++++++
 board/ti/am335x/hash-string.h     |  59 ++++
 include/configs/ti_armv7_common.h | 153 ++++++++++
 include/environment/ti/mmc.h      |  20 ++
 4 files changed, 698 insertions(+)
 create mode 100644 board/ti/am335x/hash-string.h

diff --git a/board/ti/am335x/board.c b/board/ti/am335x/board.c
index af0c386e..e69ef49d 100644
--- a/board/ti/am335x/board.c
+++ b/board/ti/am335x/board.c
@@ -47,6 +47,7 @@
 #include "../common/board_detect.h"
 #include "../common/cape_detect.h"
 #include "board.h"
+#include "hash-string.h"
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -90,6 +91,463 @@ void do_board_detect(void)
 }
 #endif
 
+#define CAPE_EEPROM_BUS_NUM 2
+#define CAPE_EEPROM_ADDR0	0x54
+#define CAPE_EEPROM_ADDR1	0x55
+#define CAPE_EEPROM_ADDR2	0x56
+#define CAPE_EEPROM_ADDR3	0x57
+
+#define CAPE_EEPROM_ADDR_LEN 0x10
+
+#define NOT_POP		0x0
+#define PINS_TAKEN	0x0
+
+#define UNK_BASE_DTB	0x0
+#define BB_BASE_DTB	0x1
+#define BBB_BASE_DTB	0x2
+#define BBGW_BASE_DTB	0x3
+#define BBBL_BASE_DTB	0x4
+#define BBE_BASE_DTB	0x5
+#define BBEL_BASE_DTB	0x6
+
+#define BBB_EMMC	0x1
+
+#define BBB_TDA998X_AUDIO	0x1
+#define BBB_TDA998X_NAUDIO	0x2
+#define BBB_ADV7511_AUDIO	0x3
+#define BBB_ADV7511_NAUDIO	0x4
+
+#define BBBW_WL1835	0x1
+#define BBGW_WL1835	0x2
+#define BBGG_WL1835	0x3
+
+#define M_BBG1	0x01
+#define M_OS00	0x02
+#define M_OS01	0x03
+#define M_BBGG	0x04
+
+static int probe_cape_eeprom(struct am335x_cape_eeprom_id *cape_header)
+{
+	int ret;
+	struct udevice *dev;
+	unsigned char addr;
+	/* /lib/firmware/BB-CAPE-DISP-CT4-00A0.dtbo */
+	/* 14 + 16 + 1 + 4 + 5 = 40 */
+	char hash_cape_overlay[40];
+	char cape_overlay[26];
+	char process_cape_part_number[16];
+	char process_cape_version[4];
+	char end_part_number;
+	char cape_overlay_pass_to_kernel[18];
+
+	//Don't forget about the BeagleBone Classic (White)
+	char base_dtb=UNK_BASE_DTB;
+	char virtual_emmc=NOT_POP;
+	char virtual_video=NOT_POP;
+	char virtual_audio=NOT_POP;
+	char virtual_wireless=NOT_POP;
+	char model=NOT_POP;
+
+	char *name = NULL;
+
+	if (board_is_bone_lt()) {
+		puts("BeagleBone Black:\n");
+		base_dtb=BBB_BASE_DTB;
+		virtual_emmc=BBB_EMMC;
+		virtual_video=BBB_TDA998X_AUDIO;
+		virtual_audio=BBB_TDA998X_AUDIO;
+		virtual_wireless=NOT_POP;
+		name = "A335BNLT";
+
+		if (!strncmp(board_ti_get_rev(), "BLA", 3)) {
+			puts("Model: BeagleBoard.org BeagleBone Blue:\n");
+			/* Special case */
+			base_dtb=BBBL_BASE_DTB;
+			virtual_emmc=NOT_POP;
+			virtual_video=NOT_POP;
+			virtual_audio=NOT_POP;
+			virtual_wireless=NOT_POP;
+			name = "BBBL";
+		}
+		if (!strncmp(board_ti_get_rev(), "BW", 2)) {
+			puts("Model: BeagleBoard.org BeagleBone Black Wireless:\n");
+			virtual_wireless=BBBW_WL1835;
+			name = "BBBW";
+		}
+		if (!strncmp(board_ti_get_rev(), "BBG", 3)) {
+			/* catches again in board_is_bbg1() */
+			//puts("Model: SeeedStudio BeagleBone Green:\n");
+			virtual_video=NOT_POP;
+			virtual_audio=NOT_POP;
+			name = "BBG1";
+			model=M_BBG1;
+		}
+		if (!strncmp(board_ti_get_rev(), "GW1", 3)) {
+			puts("Model: SeeedStudio BeagleBone Green Wireless:\n");
+			base_dtb=BBGW_BASE_DTB;
+			virtual_video=NOT_POP;
+			virtual_audio=NOT_POP;
+			virtual_wireless=BBGW_WL1835;
+		}
+		if (!strncmp(board_ti_get_rev(), "GG1", 3)) {
+			puts("Model: SeeedStudio BeagleBone Green Gateway:\n");
+			virtual_video=NOT_POP;
+			virtual_audio=NOT_POP;
+			virtual_wireless=BBGG_WL1835;
+			model=M_BBGG;
+		}
+		if (!strncmp(board_ti_get_rev(), "AIA", 3)) {
+			puts("Model: Arrow BeagleBone Black Industrial:\n");
+			virtual_video=BBB_ADV7511_AUDIO;
+			virtual_audio=BBB_ADV7511_AUDIO;
+		}
+		if (!strncmp(board_ti_get_rev(), "EIA", 3)) {
+			puts("Model: BeagleBone Black Industrial:\n");
+		}
+		if (!strncmp(board_ti_get_rev(), "SE", 2)) {
+			char subtype_id = board_ti_get_config()[1];
+			if (subtype_id == 'L') {
+				name = "BBELITE";
+				base_dtb=BBEL_BASE_DTB;
+			} else {
+				name = "BBEN";
+				base_dtb=BBE_BASE_DTB;
+			}
+		}
+		if (!strncmp(board_ti_get_rev(), "ME0", 3)) {
+			puts("Model: MENTOREL BeagleBone uSomIQ:\n");
+			virtual_video=NOT_POP;
+			virtual_audio=NOT_POP;
+		}
+		if (!strncmp(board_ti_get_rev(), "NAD", 3)) {
+			puts("Model: Neuromeka BeagleBone Air:\n");
+		}
+		if (!strncmp(board_ti_get_rev(), "OS0", 3)) {
+			unsigned char rev = board_ti_get_rev()[3];
+			puts("Model: Octavo Systems OSD3358-SM-RED:\n");
+			switch (rev) {
+			case 0x31: /* 1 */
+				name = "OS01";
+				model=M_OS01;
+				break;
+			default: /* 0 */
+				name = "OS00";
+				model=M_OS00;
+				break;
+			}
+		}
+	}
+
+	if (board_is_bone()) {
+		puts("Model: BeagleBone:\n");
+		base_dtb=BB_BASE_DTB;
+		virtual_emmc=NOT_POP;
+		virtual_video=NOT_POP;
+		virtual_audio=NOT_POP;
+		virtual_wireless=NOT_POP;
+		name = "A335BONE";
+	}
+
+	if (board_is_bbg1()) {
+		puts("Model: SeeedStudio BeagleBone Green:\n");
+		base_dtb=BBB_BASE_DTB;
+		virtual_emmc=BBB_EMMC;
+		virtual_video=NOT_POP;
+		virtual_audio=NOT_POP;
+		virtual_wireless=NOT_POP;
+		name = "BBG1";
+		model=M_BBG1;
+	}
+
+	set_board_info_env(name);
+
+	strlcpy(cape_overlay_pass_to_kernel, "", 1);
+
+	for ( addr = CAPE_EEPROM_ADDR0; addr <= CAPE_EEPROM_ADDR3; addr++ ) {
+		ret = i2c_get_chip_for_busnum(CAPE_EEPROM_BUS_NUM, addr, 1, &dev);
+		if (ret) {
+			printf("BeagleBone Cape EEPROM: no EEPROM at address: 0x%x\n", addr);
+		} else {
+			printf("BeagleBone Cape EEPROM: found EEPROM at address: 0x%x\n", addr);
+
+			ret = i2c_set_chip_offset_len(dev, 2);
+			if (ret) {
+				printf("BeagleBone Cape EEPROM: i2c_set_chip_offset_len failure\n");
+			}
+
+			ret = dm_i2c_read(dev, 0, (uchar *)cape_header, sizeof(struct am335x_cape_eeprom_id));
+			if (ret) {
+				printf("BeagleBone Cape EEPROM: Cannot read eeprom params\n");
+			}
+
+			if (cape_header->header == 0xEE3355AA) {
+				strlcpy(hash_cape_overlay, "/lib/firmware/", 14 + 1);
+				strlcpy(cape_overlay, "", 2);
+				strlcpy(cape_overlay_pass_to_kernel, "", 2);
+				strlcpy(process_cape_part_number, "...............", 16 + 1);
+				strlcpy(process_cape_version, "...", 4 + 1);
+
+				strlcpy(process_cape_part_number, cape_header->part_number, 16 + 1);
+				printf("BeagleBone Cape EEPROM: debug part_number field:[%s]\n", process_cape_part_number);
+
+				//FIXME: some capes end with '.'
+				if ( process_cape_part_number[15] == 0x2E ) {
+					puts("debug: fixup, extra . in eeprom field\n");
+					process_cape_part_number[15] = 0x00;
+					if ( process_cape_part_number[14] == 0x2E ) {
+						process_cape_part_number[14] = 0x00;
+					}
+				}
+
+				//Find ending 0x00 or 0xFF
+				puts("BeagleBone Cape EEPROM: debug part_number field HEX:[");
+				end_part_number=16;
+				for ( int i=0; i <= 16; i++ ) {
+					if (( process_cape_part_number[i] == 0x00 ) || ( process_cape_part_number[i] == 0xFF )) {
+						end_part_number=i;
+						i=17;
+					} else {
+						printf("%x", process_cape_part_number[i]);
+					}
+				}
+				puts("]\n");
+
+				strncat(cape_overlay_pass_to_kernel, process_cape_part_number, end_part_number);
+				strncat(cape_overlay_pass_to_kernel, ",", 1);
+				//printf("debug: %s\n", cape_overlay_pass_to_kernel);
+
+				strncat(hash_cape_overlay, process_cape_part_number, end_part_number);
+				strncat(cape_overlay, process_cape_part_number, end_part_number);
+				//printf("debug: %s %s\n", hash_cape_overlay, cape_overlay);
+
+				strncat(hash_cape_overlay, "-", 1);
+				strncat(cape_overlay, "-", 1);
+				//printf("debug: %s %s\n", hash_cape_overlay, cape_overlay);
+
+				strlcpy(process_cape_version, cape_header->version, 4 + 1);
+				//printf("debug: version field:[%s]\n", process_cape_version);
+
+				//Find invalid 0xFF -> 0x30 BBAI FAN Cape...
+				puts("BeagleBone Cape EEPROM: debug version field HEX:[");
+				for ( int i=0; i <= 3; i++ ) {
+					printf("%x", process_cape_version[i]);
+					if ( process_cape_version[i] == 0xFF ) {
+						process_cape_version[i] = 0x30;
+					}
+				}
+				puts("]\n");
+
+				strncat(hash_cape_overlay, process_cape_version, 4);
+				strncat(cape_overlay, process_cape_version, 4);
+				//printf("debug: %s %s\n", hash_cape_overlay, cape_overlay);
+
+				strncat(hash_cape_overlay, ".dtbo", 5);
+				strncat(cape_overlay, ".dtbo", 5);
+				//printf("debug: %s %s\n", hash_cape_overlay, cape_overlay);
+
+				unsigned long cape_overlay_hash = hash_string(hash_cape_overlay);
+
+				printf("BeagleBone Cape EEPROM: 0x%x: %s [0x%lx]\n", addr, cape_overlay, cape_overlay_hash);
+
+				switch(cape_overlay_hash) {
+					case 0x3c766f: /* /lib/firmware/BB-CAPE-DISP-CT4-00A0.dtbo */
+						virtual_video=PINS_TAKEN;
+						break;
+					case 0x24f51cf: /* /lib/firmware/BB-BONE-CAM-VVDN-00A0.dtbo */
+						virtual_emmc=PINS_TAKEN;
+						break;
+					case 0x4b0c13f: /* /lib/firmware/NL-AB-BBCL-00B0.dtbo */
+						virtual_video=PINS_TAKEN;
+						break;
+					case 0x74e7bbf: /* /lib/firmware/bb-justboom-dac-00A0.dtbo */
+						virtual_audio=PINS_TAKEN;
+						break;
+					case 0x93b574f: /* /lib/firmware/BB-GREEN-HDMI-00A0.dtbo */
+						virtual_video=PINS_TAKEN;
+						break;
+					case 0x9dcd73f: /* /lib/firmware/BB-BONE-NH10C-01-00A0.dtbo */
+						virtual_video=PINS_TAKEN;
+						break;
+					case 0xb1b7bbf: /* /lib/firmware/bb-justboom-amp-00A0.dtbo */
+						virtual_audio=PINS_TAKEN;
+						break;
+					//d15bb
+					case 0xd15b80f: /* /lib/firmware/DLPDLCR2000-00A0.dtbo */
+						virtual_video=PINS_TAKEN;
+						break;
+					case 0xd4c9eff: /* /lib/firmware/bb-justboom-digi-00A0.dtbo */
+						virtual_audio=PINS_TAKEN;
+						break;
+					case 0xe05061f: /* /lib/firmware/BBORG_DISPLAY70-00A2.dtbo */
+						virtual_video=PINS_TAKEN;
+						break;
+					case 0xe3f55df: /* /lib/firmware/BB-BONE-NH7C-01-A0.dtbo */
+						virtual_video=PINS_TAKEN;
+						break;
+					case 0xfc93c8f: /* /lib/firmware/BB-BONE-LCD7-01-00A3.dtbo */
+						virtual_video=PINS_TAKEN;
+						break;
+					//fe131
+					case 0xfe1313f: /* /lib/firmware/BB-BONE-4D5R-01-00A1.dtbo */
+						virtual_video=PINS_TAKEN;
+						break;
+					//fe132
+					case 0xfe1323f: /* /lib/firmware/BB-BONE-4D4R-01-00A1.dtbo */
+						virtual_video=PINS_TAKEN;
+						break;
+					case 0xfe1327f: /* /lib/firmware/BB-BONE-4D4N-01-00A1.dtbo */
+						virtual_video=PINS_TAKEN;
+						break;
+					case 0xfe132cf: /* /lib/firmware/BB-BONE-4D4C-01-00A1.dtbo */
+						virtual_video=PINS_TAKEN;
+						break;
+					//fe133
+					case 0xfe1337f: /* /lib/firmware/BB-BONE-4D7N-01-00A1.dtbo */
+						virtual_video=PINS_TAKEN;
+						break;
+					case 0xfe133cf: /* /lib/firmware/BB-BONE-4D7C-01-00A1.dtbo */
+						virtual_video=PINS_TAKEN;
+						break;
+					//fe135
+					case 0xfe1357f: /* /lib/firmware/BB-BONE-4D5N-01-00A1.dtbo */
+						virtual_video=PINS_TAKEN;
+						break;
+					case 0xfe135cf: /* /lib/firmware/BB-BONE-4D5C-01-00A1.dtbo */
+						virtual_video=PINS_TAKEN;
+						break;
+					//fe137
+					case 0xfe1373f: /* /lib/firmware/BB-BONE-4D7R-01-00A1.dtbo */
+						virtual_video=PINS_TAKEN;
+						break;
+					case 0xfe93c1f: /* /lib/firmware/BB-BONE-LCD4-01-00A1.dtbo */
+						virtual_video=PINS_TAKEN;
+						break;
+					case 0xfe93c2f: /* /lib/firmware/BB-BONE-LCD5-01-00A1.dtbo */
+						virtual_video=PINS_TAKEN;
+						break;
+				}
+
+				switch(addr) {
+					case CAPE_EEPROM_ADDR0:
+						env_set("uboot_overlay_addr0", cape_overlay);
+						env_set("uboot_detected_capes_addr0", cape_overlay_pass_to_kernel);
+						break;
+					case CAPE_EEPROM_ADDR1:
+						env_set("uboot_overlay_addr1", cape_overlay);
+						env_set("uboot_detected_capes_addr1", cape_overlay_pass_to_kernel);
+						break;
+					case CAPE_EEPROM_ADDR2:
+						env_set("uboot_overlay_addr2", cape_overlay);
+						env_set("uboot_detected_capes_addr2", cape_overlay_pass_to_kernel);
+						break;
+					case CAPE_EEPROM_ADDR3:
+						env_set("uboot_overlay_addr3", cape_overlay);
+						env_set("uboot_detected_capes_addr3", cape_overlay_pass_to_kernel);
+						break;
+				}
+				env_set("uboot_detected_capes", "1");
+			} else {
+				printf("BeagleBone Cape EEPROM: EEPROM contents not valid (or blank) on address: 0x%x\n", addr);
+			}
+		}
+	}//for
+
+	switch(base_dtb) {
+		case BB_BASE_DTB:
+			env_set("uboot_base_dtb_univ", "am335x-bone-uboot-univ.dtb");
+			env_set("uboot_base_dtb", "am335x-bone.dtb");
+			break;
+		case BBB_BASE_DTB:
+			env_set("uboot_base_dtb_univ", "am335x-boneblack-uboot-univ.dtb");
+			env_set("uboot_base_dtb", "am335x-boneblack-uboot.dtb");
+			break;
+		case BBGW_BASE_DTB:
+			//gpio-hogs and cape-universal dont mesh very well on bootup...
+			env_set("uboot_base_dtb_univ", "am335x-bonegreen-wireless-uboot-univ.dtb");
+			env_set("uboot_base_dtb", "am335x-boneblack-uboot.dtb");
+			break;
+		case BBE_BASE_DTB:
+			env_set("uboot_base_dtb_univ", "am335x-sancloud-bbe-uboot-univ.dtb");
+			env_set("uboot_base_dtb", "am335x-sancloud-bbe-uboot.dtb");
+			break;
+		case BBEL_BASE_DTB:
+			env_set("uboot_base_dtb_univ", "am335x-sancloud-bbe-lite-uboot-univ.dtb");
+			env_set("uboot_base_dtb", "am335x-sancloud-bbe-lite-uboot.dtb");
+			break;
+		case BBBL_BASE_DTB:
+			env_set("uboot_base_dtb_univ", "am335x-boneblue.dtb");
+			break;
+	}
+
+	if (virtual_emmc == BBB_EMMC) {
+		env_set("uboot_emmc", "BB-BONE-eMMC1-01-00A0.dtbo");
+	}
+
+	switch(virtual_video) {
+		case BBB_TDA998X_AUDIO:
+			if (virtual_audio == PINS_TAKEN) {
+				env_set("uboot_video", "BB-NHDMI-TDA998x-00A0.dtbo");
+				env_set("uboot_video_naudio", "BB-NHDMI-TDA998x-00A0.dtbo");
+			} else {
+				env_set("uboot_video", "BB-HDMI-TDA998x-00A0.dtbo");
+				env_set("uboot_video_naudio", "BB-NHDMI-TDA998x-00A0.dtbo");
+			}
+			break;
+		case BBB_TDA998X_NAUDIO:
+			env_set("uboot_video", "BB-NHDMI-TDA998x-00A0.dtbo");
+			env_set("uboot_video_naudio", "BB-NHDMI-TDA998x-00A0.dtbo");
+			break;
+		case BBB_ADV7511_AUDIO:
+			if (virtual_audio == PINS_TAKEN) {
+				env_set("uboot_video", "BB-NHDMI-ADV7511-00A0.dtbo");
+				env_set("uboot_video_naudio", "BB-NHDMI-ADV7511-00A0.dtbo");
+			} else {
+				env_set("uboot_video", "BB-HDMI-ADV7511-00A0.dtbo");
+				env_set("uboot_video_naudio", "BB-NHDMI-ADV7511-00A0.dtbo");
+			}
+			break;
+		case BBB_ADV7511_NAUDIO:
+			env_set("uboot_video", "BB-NHDMI-ADV7511-00A0.dtbo");
+			env_set("uboot_video_naudio", "BB-NHDMI-ADV7511-00A0.dtbo");
+			break;
+	}
+
+	switch(virtual_wireless) {
+		case BBBW_WL1835:
+			env_set("uboot_wireless", "BB-BBBW-WL1835-00A0.dtbo");
+			break;
+		case BBGW_WL1835:
+			env_set("uboot_wireless", "BB-BBGW-WL1835-00A0.dtbo");
+			break;
+		case BBGG_WL1835:
+			env_set("uboot_wireless", "BB-BBGG-WL1835-00A0.dtbo");
+			break;
+	}
+
+	switch(model) {
+		case M_BBG1:
+			env_set("uboot_model", "M-BB-BBG-00A0.dtbo");
+			break;
+		case M_OS00:
+			env_set("uboot_model", "M-BB-OSD3358-SM-RED-00A0.dtbo");
+			break;
+		case M_OS01:
+			env_set("uboot_model", "M-BB-OSD3358-SM-RED-00A1.dtbo");
+			break;
+		case M_BBGG:
+			env_set("uboot_model", "M-BB-BBGG-00A0.dtbo");
+			break;
+	}
+	return 0;
+}
+
+void do_cape_detect(void)
+{
+	struct am335x_cape_eeprom_id cape_header;
+
+	probe_cape_eeprom(&cape_header);
+}
+
 #ifndef CONFIG_DM_SERIAL
 struct serial_device *default_serial_console(void)
 {
@@ -976,6 +1434,14 @@ int board_late_init(void)
 	/* Just probe the potentially supported cdce913 device */
 	uclass_get_device_by_name(UCLASS_CLK, "cdce913@65", &dev);
 
+#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
+#ifdef CONFIG_TI_I2C_BOARD_DETECT
+	if (!board_is_pb() && !board_is_beaglelogic()) {
+		do_cape_detect();
+	}
+#endif
+#endif
+
 	return 0;
 }
 #endif
diff --git a/board/ti/am335x/hash-string.h b/board/ti/am335x/hash-string.h
new file mode 100644
index 00000000..b267a877
--- /dev/null
+++ b/board/ti/am335x/hash-string.h
@@ -0,0 +1,59 @@
+/* Description of GNU message catalog format: string hashing function.
+   Copyright (C) 1995, 1997, 1998, 2000, 2001 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Library General Public License as published
+   by the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+/* @@ end of prolog @@ */
+
+#ifndef PARAMS
+# if __STDC__ || defined __GNUC__ || defined __SUNPRO_C || defined __cplusplus || __PROTOTYPES
+#  define PARAMS(Args) Args
+# else
+#  define PARAMS(Args) ()
+# endif
+#endif
+
+/* We assume to have `unsigned long int' value with at least 32 bits.  */
+#define HASHWORDBITS 32
+
+
+/* Defines the so called `hashpjw' function by P.J. Weinberger
+   [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools,
+   1986, 1987 Bell Telephone Laboratories, Inc.]  */
+static unsigned long int hash_string PARAMS ((const char *__str_param));
+
+static inline unsigned long int
+hash_string (str_param)
+     const char *str_param;
+{
+  unsigned long int hval, g;
+  const char *str = str_param;
+
+  /* Compute the hash value for the given string.  */
+  hval = 0;
+  while (*str != '\0')
+    {
+      hval <<= 4;
+      hval += (unsigned long int) *str++;
+      g = hval & ((unsigned long int) 0xf << (HASHWORDBITS - 4));
+      if (g != 0)
+	{
+	  hval ^= g >> (HASHWORDBITS - 8);
+	  hval ^= g;
+	}
+    }
+  return hval;
+}
diff --git a/include/configs/ti_armv7_common.h b/include/configs/ti_armv7_common.h
index 78c3d195..1c63c8e6 100644
--- a/include/configs/ti_armv7_common.h
+++ b/include/configs/ti_armv7_common.h
@@ -269,6 +269,40 @@
 			"echo loading ${bootdir}/${bootfile} ...; "\
 			"run loadimage;" \
 			"setenv fdtdir /boot/dtbs/${uname_r}; " \
+			"echo debug: [enable_uboot_overlays=${enable_uboot_overlays}] ... ;" \
+			"if test -n ${enable_uboot_overlays}; then " \
+				"echo debug: [enable_uboot_cape_universal=${enable_uboot_cape_universal}] ... ;" \
+				"if test -n ${enable_uboot_cape_universal}; then " \
+					"echo debug: [uboot_base_dtb_univ=${uboot_base_dtb_univ}] ... ;" \
+					"if test -n ${uboot_base_dtb_univ}; then " \
+						"echo uboot_overlays: [uboot_base_dtb=${uboot_base_dtb_univ}] ... ;" \
+						"if test -e ${devtype} ${bootpart} ${fdtdir}/${uboot_base_dtb_univ}; then " \
+							"setenv fdtfile ${uboot_base_dtb_univ};" \
+							"echo uboot_overlays: Switching too: dtb=${fdtfile} ...;" \
+							"setenv cape_uboot bone_capemgr.uboot_capemgr_enabled=1; " \
+						"else " \
+							"echo debug: unable to find [${uboot_base_dtb_univ}] using [${uboot_base_dtb}] instead ... ;" \
+							"echo debug: [uboot_base_dtb_univ=${uboot_base_dtb}] ... ;" \
+							"if test -n ${uboot_base_dtb}; then " \
+								"echo uboot_overlays: [uboot_base_dtb=${uboot_base_dtb}] ... ;" \
+								"if test -e ${devtype} ${bootpart} ${fdtdir}/${uboot_base_dtb}; then " \
+									"setenv fdtfile ${uboot_base_dtb};" \
+									"echo uboot_overlays: Switching too: dtb=${fdtfile} ...;" \
+								"fi;" \
+							"fi;" \
+						"fi;" \
+					"fi;" \
+				"else " \
+					"echo debug: [uboot_base_dtb_univ=${uboot_base_dtb}] ... ;" \
+					"if test -n ${uboot_base_dtb}; then " \
+						"echo uboot_overlays: [uboot_base_dtb=${uboot_base_dtb}] ... ;" \
+						"if test -e ${devtype} ${bootpart} ${fdtdir}/${uboot_base_dtb}; then " \
+							"setenv fdtfile ${uboot_base_dtb};" \
+							"echo uboot_overlays: Switching too: dtb=${fdtfile} ...;" \
+						"fi;" \
+					"fi;" \
+				"fi;" \
+			"fi;" \
 			"if test -e ${devtype} ${bootpart} ${fdtdir}/${fdtfile}; then " \
 				"run loadfdt;" \
 			"else " \
@@ -309,6 +343,125 @@
 					"fi;" \
 				"fi;" \
 			"fi; " \
+			"if test -n ${enable_uboot_overlays}; then " \
+				"extension scan;" \
+				"setenv fdt_buffer 0x60000;" \
+				"if test -n ${uboot_fdt_buffer}; then " \
+					"setenv fdt_buffer ${uboot_fdt_buffer};" \
+				"fi;" \
+				"echo uboot_overlays: [fdt_buffer=${fdt_buffer}] ... ;" \
+				"if test -n ${uboot_silicon}; then " \
+					"setenv uboot_overlay ${uboot_silicon}; " \
+					"run virtualloadoverlay;" \
+				"fi;" \
+				"if test -n ${uboot_model}; then " \
+					"setenv uboot_overlay ${uboot_model}; " \
+					"run virtualloadoverlay;" \
+				"fi;" \
+				"if test -n ${disable_uboot_overlay_adc}; then " \
+					"echo uboot_overlays: uboot loading of [BB-ADC-00A0.dtbo] disabled by /boot/uEnv.txt [disable_uboot_overlay_adc=1]...;" \
+				"else " \
+					"setenv uboot_overlay BB-ADC-00A0.dtbo; " \
+					"run virtualloadoverlay;" \
+				"fi;" \
+				"if test -n ${uboot_overlay_addr0}; then " \
+					"if test -n ${disable_uboot_overlay_addr0}; then " \
+						"echo uboot_overlays: uboot loading of [${uboot_overlay_addr0}] disabled by /boot/uEnv.txt [disable_uboot_overlay_addr0=1]...;" \
+					"else " \
+						"setenv uboot_overlay ${uboot_overlay_addr0}; " \
+						"run virtualloadoverlay;" \
+					"fi;" \
+				"fi;" \
+				"if test -n ${uboot_overlay_addr1}; then " \
+					"if test -n ${disable_uboot_overlay_addr1}; then " \
+						"echo uboot_overlays: uboot loading of [${uboot_overlay_addr1}] disabled by /boot/uEnv.txt [disable_uboot_overlay_addr1=1]...;" \
+					"else " \
+						"setenv uboot_overlay ${uboot_overlay_addr1}; " \
+						"run virtualloadoverlay;" \
+					"fi;" \
+				"fi;" \
+				"if test -n ${uboot_overlay_addr2}; then " \
+					"if test -n ${disable_uboot_overlay_addr2}; then " \
+						"echo uboot_overlays: uboot loading of [${uboot_overlay_addr2}] disabled by /boot/uEnv.txt [disable_uboot_overlay_addr2=1]...;" \
+					"else " \
+						"setenv uboot_overlay ${uboot_overlay_addr2}; " \
+						"run virtualloadoverlay;" \
+					"fi;" \
+				"fi;" \
+				"if test -n ${uboot_overlay_addr3}; then " \
+					"if test -n ${disable_uboot_overlay_addr3}; then " \
+						"echo uboot_overlays: uboot loading of [${uboot_overlay_addr3}] disabled by /boot/uEnv.txt [disable_uboot_overlay_addr3=1]...;" \
+					"else " \
+						"setenv uboot_overlay ${uboot_overlay_addr3}; " \
+						"run virtualloadoverlay;" \
+					"fi;" \
+				"fi;" \
+				"if test -n ${uboot_overlay_addr4}; then " \
+					"setenv uboot_overlay ${uboot_overlay_addr4}; " \
+					"run virtualloadoverlay;" \
+				"fi;" \
+				"if test -n ${uboot_overlay_addr5}; then " \
+					"setenv uboot_overlay ${uboot_overlay_addr5}; " \
+					"run virtualloadoverlay;" \
+				"fi;" \
+				"if test -n ${uboot_overlay_addr6}; then " \
+					"setenv uboot_overlay ${uboot_overlay_addr6}; " \
+					"run virtualloadoverlay;" \
+				"fi;" \
+				"if test -n ${uboot_overlay_addr7}; then " \
+					"setenv uboot_overlay ${uboot_overlay_addr7}; " \
+					"run virtualloadoverlay;" \
+				"fi;" \
+				"if test -n ${uboot_emmc}; then " \
+					"if test -n ${disable_uboot_overlay_emmc}; then " \
+						"echo uboot_overlays: uboot loading of [${uboot_emmc}] disabled by /boot/uEnv.txt [disable_uboot_overlay_emmc=1]...;" \
+					"else " \
+						"setenv uboot_overlay ${uboot_emmc}; " \
+						"run virtualloadoverlay;" \
+					"fi;" \
+				"fi;" \
+				"if test -n ${uboot_video}; then " \
+					"if test -n ${disable_uboot_overlay_video}; then " \
+						"echo uboot_overlays: uboot loading of [${uboot_video}] disabled by /boot/uEnv.txt [disable_uboot_overlay_video=1]...;" \
+					"else " \
+						"if test -n ${disable_uboot_overlay_audio}; then " \
+							"echo uboot_overlays: uboot loading of [${uboot_video}] disabled by /boot/uEnv.txt [disable_uboot_overlay_audio=1]...;" \
+							"setenv uboot_overlay ${uboot_video_naudio}; " \
+							"run virtualloadoverlay;" \
+						"else " \
+							"setenv uboot_overlay ${uboot_video}; " \
+							"run virtualloadoverlay;" \
+						"fi;" \
+					"fi;" \
+				"fi;" \
+				"if test -n ${uboot_wireless}; then " \
+					"if test -n ${disable_uboot_overlay_wireless}; then " \
+						"echo uboot_overlays: uboot loading of [${uboot_wireless}] disabled by /boot/uEnv.txt [disable_uboot_overlay_wireless=1]...;" \
+					"else " \
+						"setenv uboot_overlay ${uboot_wireless}; " \
+						"run virtualloadoverlay;" \
+					"fi;" \
+				"fi;" \
+				"if test -n ${uboot_overlay_pru}; then " \
+					"setenv uboot_overlay ${uboot_overlay_pru}; " \
+					"run virtualloadoverlay;" \
+				"fi;" \
+				"if test -n ${uboot_overlay_pru_add}; then " \
+					"setenv uboot_overlay ${uboot_overlay_pru_add}; " \
+					"run virtualloadoverlay;" \
+				"fi;" \
+				"if test -n ${dtb_overlay}; then " \
+					"setenv uboot_overlay ${dtb_overlay}; " \
+					"echo uboot_overlays: [dtb_overlay=${uboot_overlay}] ... ;" \
+					"run virtualloadoverlay;" \
+				"fi;" \
+			"else " \
+				"echo uboot_overlays: add [enable_uboot_overlays=1] to /boot/uEnv.txt to enable...;" \
+			"fi;" \
+			"if test -n ${uboot_detected_capes}; then " \
+				"echo uboot_overlays: [uboot_detected_capes=${uboot_detected_capes_addr0}${uboot_detected_capes_addr1}${uboot_detected_capes_addr2}${uboot_detected_capes_addr3}] ... ;" \
+				"setenv uboot_detected_capes uboot_detected_capes=${uboot_detected_capes_addr0}${uboot_detected_capes_addr1}${uboot_detected_capes_addr2}${uboot_detected_capes_addr3}; " \
+			"fi;" \
 			"setenv rdfile initrd.img-${uname_r}; " \
 			"if test -e ${devtype} ${bootpart} ${bootdir}/${rdfile}; then " \
 				"echo loading ${bootdir}/${rdfile} ...; "\
diff --git a/include/environment/ti/mmc.h b/include/environment/ti/mmc.h
index b671c048..030f53fb 100644
--- a/include/environment/ti/mmc.h
+++ b/include/environment/ti/mmc.h
@@ -58,6 +58,26 @@
 	"loadimage=load ${devtype} ${bootpart} ${loadaddr} ${bootdir}/${bootfile}\0" \
 	"loadrd=load ${devtype} ${bootpart} ${rdaddr} ${bootdir}/${rdfile}; setenv rdsize ${filesize}\0" \
 	"loadfdt=echo loading ${fdtdir}/${fdtfile} ...; load ${devtype} ${bootpart} ${fdtaddr} ${fdtdir}/${fdtfile}\0" \
+	"loadoverlay=echo uboot_overlays: loading ${actual_uboot_overlay} ...; " \
+		"load ${devtype} ${bootpart} ${rdaddr} ${actual_uboot_overlay}; " \
+		"fdt addr ${fdtaddr}; fdt resize ${fdt_buffer}; " \
+		"fdt apply ${rdaddr}; fdt resize ${fdt_buffer};\0" \
+	"virtualloadoverlay=if test -e ${devtype} ${bootpart} ${fdtdir}/overlays/${uboot_overlay}; then " \
+				"setenv actual_uboot_overlay ${fdtdir}/overlays/${uboot_overlay}; " \
+				"run loadoverlay;" \
+			"else " \
+				"if test -e ${devtype} ${bootpart} /lib/firmware/${uboot_overlay}; then " \
+					"setenv actual_uboot_overlay /lib/firmware/${uboot_overlay}; " \
+					"run loadoverlay;" \
+				"else " \
+					"if test -e ${devtype} ${bootpart} ${uboot_overlay}; then " \
+						"setenv actual_uboot_overlay ${uboot_overlay}; " \
+						"run loadoverlay;" \
+					"else " \
+						"echo uboot_overlays: unable to find [${devtype} ${bootpart} ${uboot_overlay}]...;" \
+					"fi;" \
+				"fi;" \
+			"fi;\0" \
 	"failumsboot=echo; echo FAILSAFE: U-Boot UMS (USB Mass Storage) enabled, media now available over the usb slave port ...; " \
 		"ums 0 ${devtype} 1;\0" \
 	"envboot=mmc dev ${mmcdev}; " \
-- 
2.25.1

