build/patch/u-boot/v2023.07/board_khadas-vim3/khadas-kbi.patch

1119 lines
28 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ricardo Pardini <ricardo@pardini.net>
Date: Sat, 24 Jun 2023 14:29:42 +0200
Subject: Khadas KBI cmd
Taken from
- https://raw.githubusercontent.com/khadas/khadas-uboot/master/packages/u-boot-mainline/patches/v2021.07-rc1/0002-Edge-add-kbi-support-WiP.patch
- https://raw.githubusercontent.com/khadas/khadas-uboot/master/packages/u-boot-mainline/patches/v2021.07-rc1/0003-VIMs-add-kbi-cmd-support.patch
- made it 'default y' so no need to change defconfig
---
cmd/Kconfig | 7 +
cmd/Makefile | 2 +
cmd/kbi.c | 1065 ++++++++++
3 files changed, 1074 insertions(+)
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 365371fb51..baa4143b88 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -2847,4 +2847,11 @@ config CMD_MESON
default y
help
Enable useful commands for the Meson Soc family developed by Amlogic Inc.
+
+config CMD_KHADAS_KBI
+ bool "Khadas Bootloader Instructions"
+ default y
+ help
+ Khadas Bootloader Instructions
+
endmenu
diff --git a/cmd/Makefile b/cmd/Makefile
index 6c37521b4e..54a93980f7 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -218,6 +218,8 @@ obj-$(CONFIG_CMD_REGULATOR) += regulator.o
obj-$(CONFIG_CMD_BLOB) += blob.o
+obj-$(CONFIG_CMD_KHADAS_KBI) += kbi.o
+
# Android Verified Boot 2.0
obj-$(CONFIG_CMD_AVB) += avb.o
diff --git a/cmd/kbi.c b/cmd/kbi.c
new file mode 100644
index 0000000000..d38611ca90
--- /dev/null
+++ b/cmd/kbi.c
@@ -0,0 +1,1065 @@
+#include <common.h>
+#include <bootretry.h>
+#include <cli.h>
+#include <command.h>
+#include <dm.h>
+#include <edid.h>
+#include <env.h>
+#include <errno.h>
+#include <i2c.h>
+#include <adc.h>
+#include <malloc.h>
+#include <asm/byteorder.h>
+#include <linux/compiler.h>
+#include <asm/u-boot.h>
+
+#define CHIP_ADDR 0x18
+#define CHIP_ADDR_CHAR "0x18"
+#define I2C_SPEED 100000
+#if defined (CONFIG_ARCH_ROCKCHIP)
+ #define MCU_I2C_BUS_NUM 8
+#else
+ #if defined (CONFIG_MESON_GXM) || defined (CONFIG_MESON_GXL)
+ #define MCU_I2C_BUS_NUM 1
+ #elif defined (CONFIG_MESON_G12A)
+ #define MCU_I2C_BUS_NUM 0
+ #endif
+#endif
+
+#define REG_PASSWD_VENDOR 0x00
+#define REG_MAC 0x06
+#define REG_USID 0x0c
+#define REG_VERSION 0x12
+
+#define REG_BOOT_MODE 0x20
+#define REG_BOOT_EN_WOL 0x21
+#define REG_BOOT_EN_RTC 0x22
+#define REG_BOOT_EN_IR 0x24
+#define REG_BOOT_EN_DCIN 0x25
+#define REG_BOOT_EN_KEY 0x26
+#define REG_BOOT_EN_GPIO 0x23
+#define REG_LED_SYSTEM_ON_MODE 0x28
+#define REG_LED_SYSTEM_OFF_MODE 0x29
+#define REG_ADC 0x2a
+#define REG_MAC_SWITCH 0x2d
+
+#if defined(CONFIG_MESON_G12A)
+#define REG_PORT_MODE 0x33
+#endif
+
+#define REG_PASSWD_CUSTOM 0x40
+
+#define REG_POWER_OFF 0x80
+#define REG_PASSWD_CHECK_STATE 0x81
+#define REG_PASSWD_CHECK_VENDOR 0x82
+#define REG_PASSWD_CHECK_CUSTOM 0x83
+#define REG_POWER_STATE 0x86
+
+#define BOOT_EN_WOL 0
+#define BOOT_EN_RTC 1
+#define BOOT_EN_IR 2
+#define BOOT_EN_DCIN 3
+#define BOOT_EN_KEY 4
+#define BOOT_EN_GPIO 5
+
+#define LED_OFF_MODE 0
+#define LED_ON_MODE 1
+#define LED_BREATHE_MODE 2
+#define LED_HEARTBEAT_MODE 3
+
+#define LED_SYSTEM_OFF 0
+#define LED_SYSTEM_ON 1
+
+#define BOOT_MODE_SPI 0
+#define BOOT_MODE_EMMC 1
+
+#define FORCERESET_WOL 0
+#define FORCERESET_GPIO 1
+
+#define VERSION_LENGHT 2
+#define USID_LENGHT 6
+#define MAC_LENGHT 6
+#define ADC_LENGHT 2
+#define PASSWD_CUSTOM_LENGHT 6
+#define PASSWD_VENDOR_LENGHT 6
+
+#if defined (CONFIG_ARCH_ROCKCHIP)
+ // Board Detect
+ #define BOARD_DETECT_ADC_DEVIATION 10
+ #define BOARD_DETECT_ADC_VALUE_EDGE 1024
+ #define BOARD_DETECT_ADC_VALUE_EDGEV 204
+ #define BOARD_DETECT_ADC_VALUE_CAPTAIN 170
+
+ #define BOARD_TYPE_EDGE 1 /* Single Edge Board */
+ #define BOARD_TYPE_EDGEV 2 /* Single Edge V Board */
+ #define BOARD_TYPE_CAPTAIN 3 /* Edge with Captain */
+ #define BOARD_TYPE_UNKNOW 0 /* Unknow board */
+#else
+ #define HW_VERSION_ADC_VALUE_TOLERANCE 0x28
+ #define HW_VERSION_ADC_VAL_VIM1_V12 0x7FE
+ #define HW_VERSION_ADC_VAL_VIM1_V14 0xA1E
+ #define HW_VERSION_ADC_VAL_VIM2_V12 0x805
+ #define HW_VERSION_ADC_VAL_VIM2_V14 0xA20
+ #define HW_VERSION_ADC_VAL_VIM3_V11 0x200
+ #define HW_VERSION_ADC_VAL_VIM3_V12 0x288
+ #define HW_VERSION_UNKNOW 0x00
+ #define HW_VERSION_VIM1_V12 0x12
+ #define HW_VERSION_VIM1_V14 0x14
+ #define HW_VERSION_VIM2_V12 0x22
+ #define HW_VERSION_VIM2_V14 0x24
+ #define HW_VERSION_VIM3_V11 0x31
+ #define HW_VERSION_VIM3_V12 0x32
+#endif
+
+static char* LED_MODE_STR[] = { "off", "on", "breathe", "heartbeat"};
+
+#ifdef CONFIG_DM_I2C
+static struct udevice *i2c_cur_bus;
+
+static int cmd_i2c_set_bus_num(unsigned int busnum)
+{
+ struct udevice *bus;
+ int ret;
+
+ ret = uclass_get_device_by_seq(UCLASS_I2C, busnum, &bus);
+ if (ret) {
+ printf("%s: No bus %d\n", __func__, busnum);
+ return ret;
+ }
+ i2c_cur_bus = bus;
+
+ return 0;
+}
+
+static int i2c_get_cur_bus(struct udevice **busp)
+{
+ if (!i2c_cur_bus) {
+ if (cmd_i2c_set_bus_num(MCU_I2C_BUS_NUM)) {
+ printf("Default I2C bus %d not found\n",
+ MCU_I2C_BUS_NUM);
+ return -ENODEV;
+ }
+ }
+
+ if (!i2c_cur_bus) {
+ puts("No I2C bus selected\n");
+ return -ENODEV;
+ }
+ *busp = i2c_cur_bus;
+
+ return 0;
+}
+
+static int i2c_get_cur_bus_chip(uint chip_addr, struct udevice **devp)
+{
+ struct udevice *bus;
+ int ret;
+
+ ret = i2c_get_cur_bus(&bus);
+ if (ret)
+ return ret;
+
+ return i2c_get_chip(bus, chip_addr, 1, devp);
+}
+#endif
+
+static int kbi_i2c_read(uint reg)
+{
+ int ret;
+ char val[64];
+ uchar linebuf[1];
+ uchar chip;
+#ifdef CONFIG_DM_I2C
+ struct udevice *dev;
+#endif
+
+
+ chip = simple_strtoul(CHIP_ADDR_CHAR, NULL, 16);
+
+#ifdef CONFIG_DM_I2C
+ ret = i2c_get_cur_bus_chip(chip, &dev);
+ if (!ret)
+ ret = dm_i2c_read(dev, reg, (uint8_t *)linebuf, 1);
+#else
+ ret = i2c_read(chip, reg, 1, linebuf, 1);
+#endif
+
+ if (ret)
+ printf("Error reading the chip: %d\n",ret);
+ else {
+ sprintf(val, "%d", linebuf[0]);
+ ret = simple_strtoul(val, NULL, 10);
+
+ }
+ return ret;
+}
+
+static void kbi_i2c_read_block(uint start_reg, int count, char val[])
+{
+ uint addr;
+ int nbytes;
+ int ret;
+ uchar chip;
+#ifdef CONFIG_DM_I2C
+ struct udevice *dev;
+#endif
+
+ chip = simple_strtoul(CHIP_ADDR_CHAR, NULL, 16);
+
+ nbytes = count;
+ addr = start_reg;
+ do {
+ unsigned char linebuf[1];
+#ifdef CONFIG_DM_I2C
+ ret = i2c_get_cur_bus_chip(chip, &dev);
+ if (!ret)
+ ret = dm_i2c_read(dev, addr, (uint8_t *)linebuf, 1);
+#else
+ ret = i2c_read(chip, addr, 1, linebuf, 1);
+#endif
+ if (ret)
+ printf("Error reading the chip: %d\n",ret);
+ else
+ val[count-nbytes] = linebuf[0];
+
+ addr++;
+ nbytes--;
+
+ } while (nbytes > 0);
+}
+
+static void get_version(void)
+{
+ char version[VERSION_LENGHT] = {};
+ int i;
+
+ kbi_i2c_read_block(REG_VERSION, VERSION_LENGHT, version);
+ printf("version: ");
+ for (i=0; i< VERSION_LENGHT; i++) {
+ printf("%02x ",version[i]);
+ }
+ printf("\n");
+}
+
+static void get_mac(void)
+{
+ char mac[64];
+ char mac_addr[MAC_LENGHT] = {0};
+ int i, mode;
+
+ mode = kbi_i2c_read(REG_MAC_SWITCH);
+
+ if (mode == 1) {
+ kbi_i2c_read_block(REG_MAC, MAC_LENGHT, mac_addr);
+ } else {
+ ;;
+// int ret;
+// ret = vendor_storage_init();
+// if (ret) {
+// printf("KBI: vendor_storage_init failed %d\n", ret);
+// return;
+// }
+
+// ret = vendor_storage_read(VENDOR_LAN_MAC_ID, mac_addr, MAC_LENGHT);
+// if (MAC_LENGHT == ret && !is_zero_ethaddr((const u8 *)mac_addr)) {
+// debug("read mac from vendor successfully!\n");
+// } else {
+// kbi_i2c_read_block(REG_MAC, MAC_LENGHT, mac_addr);
+// }
+
+ }
+ printf("mac address: ");
+ for (i=0; i<MAC_LENGHT; i++) {
+ if (i == (MAC_LENGHT-1))
+ printf("%02x",mac_addr[i]);
+ else
+ printf("%02x:",mac_addr[i]);
+ }
+ printf("\n");
+ sprintf(mac, "%02x:%02x:%02x:%02x:%02x:%02x",mac_addr[0],mac_addr[1],mac_addr[2],mac_addr[3],mac_addr[4],mac_addr[5]);
+ env_set("eth_mac", mac);
+}
+
+#if defined (CONFIG_ARCH_ROCKCHIP)
+static const char *board_type_to_string(char board_type)
+{
+ switch (board_type) {
+ case BOARD_TYPE_EDGEV:
+ return "Edge-V";
+ case BOARD_TYPE_EDGE:
+ return "Edge";
+ case BOARD_TYPE_CAPTAIN:
+ return "Captain";
+ default:
+ return "UnknowBorad";
+ }
+}
+#else
+static const char *hw_version_str(int hw_ver)
+{
+ switch (hw_ver) {
+ case HW_VERSION_VIM1_V12:
+ return "VIM1.V12";
+ case HW_VERSION_VIM1_V14:
+ return "VIM1.V14";
+ case HW_VERSION_VIM2_V12:
+ return "VIM2.V12";
+ case HW_VERSION_VIM2_V14:
+ return "VIM2.V14";
+ case HW_VERSION_VIM3_V11:
+ return "VIM3.V11";
+ case HW_VERSION_VIM3_V12:
+ return "VIM3.V12";
+ default:
+ return "Unknow";
+ }
+}
+#endif
+
+#if defined (CONFIG_ARCH_ROCKCHIP)
+static char detect_board(void)
+{
+ int ret;
+ unsigned int val;
+ char board_type = -1;
+ char str[4] = {0};
+
+ ret = adc_channel_single_shot("saradc@ff100000", 0, &val);
+ if (ret) {
+ printf("%s adc_channel_single_shot fail! ret=%d\n", __func__, ret);
+ return -1;
+ }
+
+ debug("%s SARADC: %d\n", __func__, val);
+
+ if (val >= (BOARD_DETECT_ADC_VALUE_EDGEV - BOARD_DETECT_ADC_DEVIATION) && val <= (BOARD_DETECT_ADC_VALUE_EDGEV + BOARD_DETECT_ADC_DEVIATION)) {
+ board_type = BOARD_TYPE_EDGEV;
+ } else if (val >= (BOARD_DETECT_ADC_VALUE_CAPTAIN - BOARD_DETECT_ADC_DEVIATION) && val <= (BOARD_DETECT_ADC_VALUE_CAPTAIN + BOARD_DETECT_ADC_DEVIATION)) {
+ board_type = BOARD_TYPE_CAPTAIN;
+ } else if (val >= (BOARD_DETECT_ADC_VALUE_EDGE - BOARD_DETECT_ADC_DEVIATION) && val <= (BOARD_DETECT_ADC_VALUE_EDGE + BOARD_DETECT_ADC_DEVIATION)) {
+ board_type = BOARD_TYPE_EDGE;
+ } else {
+ board_type = BOARD_TYPE_UNKNOW;
+ }
+
+ printf("board type = %s (%d)\n", board_type_to_string(board_type), board_type);
+
+ sprintf(str, "%d", board_type);
+ env_set("board_type", str);
+ env_set("board_type_name", board_type_to_string(board_type));
+
+ return board_type;
+}
+#else
+static int get_hw_version(void)
+{
+ unsigned int val = 0;
+ int hw_ver = 0;
+
+#if defined (CONFIG_MESON_GXM)
+ int ret = adc_channel_single_shot("adc@8680", 1, &val);
+ if (ret) {
+ printf("%s adc_channel_single_shot fail! ret=%ud\n", __func__, ret);
+ return -1;
+ }
+
+ debug("%s SARADC: %ud\n", __func__, val);
+
+ if ((val >= HW_VERSION_ADC_VAL_VIM2_V12 - HW_VERSION_ADC_VALUE_TOLERANCE) && (val <= HW_VERSION_ADC_VAL_VIM2_V12 + HW_VERSION_ADC_VALUE_TOLERANCE)) {
+ hw_ver = HW_VERSION_VIM2_V12;
+ } else if ((val >= HW_VERSION_ADC_VAL_VIM2_V14 - HW_VERSION_ADC_VALUE_TOLERANCE) && (val <= HW_VERSION_ADC_VAL_VIM2_V14 + HW_VERSION_ADC_VALUE_TOLERANCE)) {
+ hw_ver = HW_VERSION_VIM2_V14;
+ } else {
+ hw_ver = HW_VERSION_UNKNOW;
+ }
+#elif defined (CONFIG_MESON_GXL)
+ int ret = adc_channel_single_shot("adc@8680", 1, &val);
+ if (ret) {
+ printf("%s adc_channel_single_shot fail! ret=%ud\n", __func__, ret);
+ return -1;
+ }
+
+ debug("%s SARADC: %ud\n", __func__, val);
+
+ if ((val >= HW_VERSION_ADC_VAL_VIM1_V14 - HW_VERSION_ADC_VALUE_TOLERANCE) && (val <= HW_VERSION_ADC_VAL_VIM1_V14 + HW_VERSION_ADC_VALUE_TOLERANCE)) {
+ hw_ver = HW_VERSION_VIM1_V14;
+ } else if ((val >= HW_VERSION_ADC_VAL_VIM1_V12 - HW_VERSION_ADC_VALUE_TOLERANCE) && (val <= HW_VERSION_ADC_VAL_VIM1_V12 + HW_VERSION_ADC_VALUE_TOLERANCE)) {
+ hw_ver = HW_VERSION_VIM1_V12;
+ } else {
+ hw_ver = HW_VERSION_UNKNOW;
+ }
+#elif defined (CONFIG_MESON_G12A)
+// if ((val >= HW_VERSION_ADC_VAL_VIM3_V11 - HW_VERSION_ADC_VALUE_TOLERANCE) && (val <= HW_VERSION_ADC_VAL_VIM3_V11 + HW_VERSION_ADC_VALUE_TOLERANCE)) {
+// hw_ver = HW_VERSION_VIM3_V11;
+// } else if ((val >= HW_VERSION_ADC_VAL_VIM3_V12 - HW_VERSION_ADC_VALUE_TOLERANCE) && (val <= HW_VERSION_ADC_VAL_VIM3_V12 + HW_VERSION_ADC_VALUE_TOLERANCE)) {
+// hw_ver = HW_VERSION_VIM3_V12;
+// } else {
+// hw_ver = HW_VERSION_UNKNOW;
+// }
+ // force set to V12
+ hw_ver = HW_VERSION_VIM3_V12;
+#endif
+ printf("saradc: 0x%x, hw_ver: 0x%x (%s)\n", val, hw_ver, hw_version_str(hw_ver));
+
+ env_set("hwver", hw_version_str(hw_ver));
+
+ return 0;
+}
+#endif
+
+static void get_usid(void)
+{
+ char serial[64];
+ char usid[USID_LENGHT] = {};
+ int i;
+#ifdef CONFIG_USID_FROM_ETH_MAC
+ int mode;
+ mode = kbi_i2c_read(REG_MAC_SWITCH);
+
+ if (mode == 1) {
+ kbi_i2c_read_block(REG_MAC, MAC_LENGHT, usid);
+ } else {
+ run_command("efuse mac", 0);
+ char *s = getenv("eth_mac");
+ if ((s != NULL) && (strcmp(s, "00:00:00:00:00:00") != 0)) {
+ for (i = 0; i < 6 && s[0] != '\0' && s[1] != '\0'; i++) {
+ usid[i] = chartonum(s[0]) << 4 | chartonum(s[1]);
+ s +=3;
+ }
+ } else {
+ kbi_i2c_read_block(REG_MAC, MAC_LENGHT, usid);
+ }
+ }
+#else
+ kbi_i2c_read_block(REG_USID, USID_LENGHT, usid);
+#endif
+ printf("usid: ");
+ for (i=0; i< USID_LENGHT; i++) {
+ printf("%x",usid[i]);
+ }
+ printf("\n");
+ sprintf(serial, "%02x%02x%02x%02x%02x%02x",usid[0],usid[1],usid[2],usid[3],usid[4],usid[5]);
+ env_set("usid", serial);
+}
+
+static void get_adc(void)
+{
+ char adc[ADC_LENGHT] = {};
+ kbi_i2c_read_block(REG_ADC, ADC_LENGHT, adc);
+ printf("adc: 0x%x\n",(adc[0] << 8) | adc[1]);
+
+}
+
+
+static void get_power_state(void)
+{
+ int val;
+ val = kbi_i2c_read(REG_POWER_STATE);
+ if (val == 0) {
+ printf("normal power on\n");
+ env_set("power_state","0");
+ } else if (val == 1) {
+ printf("abort power off\n");
+ env_set("power_state","1");
+ } else if (val == 2) {
+ printf("normal power off\n");
+ env_set("power_state","2");
+ } else {
+ printf("state err\n");
+ env_set("power_state","f");
+ }
+}
+
+static void set_poweroff(void)
+{
+ char cmd[64];
+ sprintf(cmd, "i2c mw 0x18 0x80 0x1");
+ run_command(cmd, 0);
+}
+
+static void set_bootmode(int mode)
+{
+ char cmd[64];
+ sprintf(cmd, "i2c mw %x %x %d 1",CHIP_ADDR, REG_BOOT_MODE, mode);
+ run_command(cmd, 0);
+
+}
+
+static void get_bootmode(void)
+{
+ int mode;
+ mode = kbi_i2c_read(REG_BOOT_MODE);
+
+ if (mode == BOOT_MODE_EMMC) {
+ printf("bootmode: emmc\n");
+ } else if (mode == BOOT_MODE_SPI) {
+ printf("bootmode: spi\n");
+ } else {
+ printf("bootmode err: %d\n",mode);
+ }
+}
+
+static void get_rtc(void)
+{
+ int enable;
+ enable = kbi_i2c_read(REG_BOOT_EN_RTC);
+ printf("boot rtc: %s\n", enable==1 ? "enable" : "disable" );
+}
+
+static void set_rtc(int enable)
+{
+ char cmd[64];
+ sprintf(cmd, "i2c mw %x %x %d 1",CHIP_ADDR, REG_BOOT_EN_RTC, enable);
+ run_command(cmd, 0);
+
+}
+
+static void get_dcin(void)
+{
+ int enable;
+ enable = kbi_i2c_read(REG_BOOT_EN_DCIN);
+ printf("boot dcin: %s\n", enable==1 ? "enable" : "disable" );
+}
+
+static void set_dcin(int enable)
+{
+ char cmd[64];
+ sprintf(cmd, "i2c mw %x %x %d 1",CHIP_ADDR, REG_BOOT_EN_DCIN, enable);
+ run_command(cmd, 0);
+}
+
+static void get_ir(void)
+{
+ int enable;
+ enable = kbi_i2c_read(REG_BOOT_EN_IR);
+ printf("boot ir: %s\n", enable==1 ? "enable" : "disable" );
+}
+
+static void set_ir(int enable)
+{
+ char cmd[64];
+ sprintf(cmd, "i2c mw %x %x %d 1",CHIP_ADDR, REG_BOOT_EN_IR, enable);
+ run_command(cmd, 0);
+}
+
+#if defined(CONFIG_MESON_G12A)
+static void get_port_mode(void)
+{
+ int mode;
+ mode = kbi_i2c_read(REG_PORT_MODE);
+ printf("port mode is %s\n", mode==0 ? "usb3.0" : "pcie");
+ env_set("port_mode", mode==0 ? "0" : "1");
+}
+
+static void set_port_mode(int mode)
+{
+ char cmd[64];
+ if ((mode < 0) && (mode > 1)) {
+ printf("the mode is invalid, you can set 0 and 1");
+ return;
+ }
+ sprintf(cmd, "i2c mw %x %x %d 1",CHIP_ADDR, REG_PORT_MODE, mode);
+ printf("set port mode to :%s\n", mode==0 ? "usb3.0" : "pcie");
+ run_command(cmd, 0);
+ env_set("port_mode", mode==0 ? "0" : "1");
+}
+#endif
+
+static void get_switch_mac(void)
+{
+ int mode;
+ mode = kbi_i2c_read(REG_MAC_SWITCH);
+ printf("switch mac from %d\n", mode);
+ env_set("switch_mac", mode==1 ? "1" : "0");
+}
+
+static void set_switch_mac(int mode)
+{
+ char cmd[64];
+ sprintf(cmd, "i2c mw %x %x %d 1",CHIP_ADDR, REG_MAC_SWITCH, mode);
+ printf("set_switch_mac :%d\n", mode);
+ run_command(cmd, 0);
+ env_set("switch_mac", mode==1 ? "1" : "0");
+}
+
+static void get_key(void)
+{
+ int enable;
+ enable = kbi_i2c_read(REG_BOOT_EN_KEY);
+ printf("boot key: %s\n", enable==1 ? "enable" : "disable" );
+}
+static void set_key(int enable)
+{
+ char cmd[64];
+ sprintf(cmd, "i2c mw %x %x %d 1",CHIP_ADDR, REG_BOOT_EN_KEY, enable);
+ run_command(cmd, 0);
+}
+
+/*
+static int get_forcereset_gpio(bool is_print)
+{
+ int enable;
+ enable = kbi_i2c_read(REG_BOOT_EN_GPIO);
+ if (is_print)
+ printf("gpio forcereset: %s\n", enable&0x02 ? "enable" : "disable" );
+ return enable;
+}
+*/
+
+static int get_gpio(bool is_print)
+{
+ int enable;
+ enable = kbi_i2c_read(REG_BOOT_EN_GPIO);
+ if (is_print)
+ printf("boot gpio: %s\n", enable&0x01 ? "enable" : "disable" );
+ return enable;
+}
+
+static void set_gpio(int enable)
+{
+ char cmd[64];
+ sprintf(cmd, "i2c mw %x %x %d 1",CHIP_ADDR, REG_BOOT_EN_GPIO, enable);
+ run_command(cmd, 0);
+}
+
+static void get_boot_enable(int type)
+{
+ if (type == BOOT_EN_RTC)
+ get_rtc();
+ else if (type == BOOT_EN_IR)
+ get_ir();
+ else if (type == BOOT_EN_DCIN)
+ get_dcin();
+ else if (type == BOOT_EN_KEY)
+ get_key();
+ else
+ get_gpio(true);
+}
+
+static void set_boot_enable(int type, int enable)
+{
+ int state = 0;
+ if (type == BOOT_EN_RTC)
+ set_rtc(enable);
+ else if (type == BOOT_EN_IR)
+ set_ir(enable);
+ else if (type == BOOT_EN_DCIN)
+ set_dcin(enable);
+ else if (type == BOOT_EN_KEY)
+ set_key(enable);
+ else {
+ state = get_gpio(false);
+ set_gpio(enable|(state&0x02));
+ }
+}
+
+static void get_blue_led_mode(int type)
+{
+ int mode;
+ if (type == LED_SYSTEM_OFF) {
+ mode = kbi_i2c_read(REG_LED_SYSTEM_OFF_MODE);
+ if ((mode >= 0) && (mode <=3) )
+ printf("led mode: %s [systemoff]\n",LED_MODE_STR[mode]);
+ else
+ printf("read led mode err\n");
+ }
+ else {
+ mode = kbi_i2c_read(REG_LED_SYSTEM_ON_MODE);
+ if ((mode >= LED_OFF_MODE) && (mode <= LED_HEARTBEAT_MODE))
+ printf("led mode: %s [systemon]\n",LED_MODE_STR[mode]);
+ else
+ printf("read led mode err\n");
+ }
+}
+
+static int set_blue_led_mode(int type, int mode)
+{
+ char cmd[64];
+ if (type == LED_SYSTEM_OFF) {
+ sprintf(cmd, "i2c mw %x %x %d 1",CHIP_ADDR, REG_LED_SYSTEM_OFF_MODE, mode);
+ } else if (type == LED_SYSTEM_ON) {
+ sprintf(cmd, "i2c mw %x %x %d 1",CHIP_ADDR, REG_LED_SYSTEM_ON_MODE, mode);
+ } else {
+ return CMD_RET_USAGE;
+ }
+
+ run_command(cmd, 0);
+ return 0;
+}
+
+static int do_kbi_init(struct cmd_tbl * cmdtp, int flag, int argc, char * const argv[])
+{
+ char cmd[64];
+ sprintf(cmd, "i2c dev %d", MCU_I2C_BUS_NUM);
+ run_command(cmd, 0);
+ return 0;
+}
+
+static int do_kbi_resetflag(struct cmd_tbl * cmdtp, int flag, int argc, char * const argv[])
+{
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ if (strcmp(argv[1], "1") == 0) {
+ run_command("i2c mw 0x18 0x87 1 1", 0);
+ } else if (strcmp(argv[1], "0") == 0) {
+ run_command("i2c mw 0x18 0x87 0 1", 0);
+ } else {
+ return CMD_RET_USAGE;
+ }
+ return 0;
+}
+
+static int do_kbi_version(struct cmd_tbl * cmdtp, int flag, int argc, char * const argv[])
+{
+ get_version();
+ return 0;
+
+}
+
+static int do_kbi_usid(struct cmd_tbl * cmdtp, int flag, int argc, char * const argv[])
+{
+ get_usid();
+ return 0;
+}
+
+static int do_kbi_adc(struct cmd_tbl * cmdtp, int flag, int argc, char * const argv[])
+{
+ get_adc();
+ return 0;
+}
+
+static int do_kbi_powerstate(struct cmd_tbl * cmdtp, int flag, int argc, char * const argv[])
+{
+ get_power_state();
+ return 0;
+
+}
+
+static int do_kbi_ethmac(struct cmd_tbl * cmdtp, int flag, int argc, char * const argv[])
+{
+ get_mac();
+ return 0;
+}
+
+#if defined (CONFIG_ARCH_ROCKCHIP)
+static int do_kbi_boarddetect(struct cmd_tbl * cmdtp, int flag, int argc, char * const argv[])
+{
+ detect_board();
+ return 0;
+}
+#else
+static int do_kbi_hwver(struct cmd_tbl * cmdtp, int flag, int argc, char * const argv[])
+{
+ return get_hw_version();
+}
+#endif
+
+static int do_kbi_switchmac(struct cmd_tbl * cmdtp, int flag, int argc, char * const argv[])
+{
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ if (strcmp(argv[1], "w") == 0) {
+ if (argc < 3)
+ return CMD_RET_USAGE;
+
+ if (strcmp(argv[2], "0") == 0) {
+ set_switch_mac(0);
+ } else if (strcmp(argv[2], "1") == 0) {
+ set_switch_mac(1);
+ } else {
+ return CMD_RET_USAGE;
+ }
+ } else if (strcmp(argv[1], "r") == 0) {
+ get_switch_mac();
+ } else {
+ return CMD_RET_USAGE;
+ }
+ return 0;
+}
+
+#if defined (CONFIG_MESON_G12A)
+static int do_kbi_portmode(struct cmd_tbl * cmdtp, int flag, int argc, char * const argv[])
+{
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ if (strcmp(argv[1], "w") == 0) {
+ if (argc < 3)
+ return CMD_RET_USAGE;
+
+ if (strcmp(argv[2], "0") == 0) {
+ set_port_mode(0);
+ } else if (strcmp(argv[2], "1") == 0) {
+ set_port_mode(1);
+ } else {
+ return CMD_RET_USAGE;
+ }
+ } else if (strcmp(argv[1], "r") == 0) {
+ get_port_mode();
+ } else {
+ return CMD_RET_USAGE;
+ }
+ return 0;
+}
+#endif
+
+static int do_kbi_led(struct cmd_tbl * cmdtp, int flag, int argc, char * const argv[])
+{
+ int ret = 0;
+ if (argc < 3)
+ return CMD_RET_USAGE;
+
+ if (strcmp(argv[1], "systemoff") ==0) {
+ if (strcmp(argv[2], "r") == 0) {
+ get_blue_led_mode(LED_SYSTEM_OFF);
+ } else if (strcmp(argv[2], "w") == 0) {
+ if (argc < 4)
+ return CMD_RET_USAGE;
+ if (strcmp(argv[3], "breathe") == 0) {
+ ret = set_blue_led_mode(LED_SYSTEM_OFF, LED_BREATHE_MODE);
+ } else if (strcmp(argv[3], "heartbeat") == 0) {
+ ret = set_blue_led_mode(LED_SYSTEM_OFF, LED_HEARTBEAT_MODE);
+ } else if (strcmp(argv[3], "on") == 0) {
+ ret = set_blue_led_mode(LED_SYSTEM_OFF, LED_ON_MODE);
+ } else if (strcmp(argv[3], "off") == 0) {
+ ret = set_blue_led_mode(LED_SYSTEM_OFF, LED_OFF_MODE);
+ } else {
+ ret = CMD_RET_USAGE;
+ }
+ }
+ } else if (strcmp(argv[1], "systemon") ==0) {
+
+ if (strcmp(argv[2], "r") == 0) {
+ get_blue_led_mode(LED_SYSTEM_ON);
+ } else if (strcmp(argv[2], "w") == 0) {
+ if (argc <4)
+ return CMD_RET_USAGE;
+ if (strcmp(argv[3], "breathe") == 0) {
+ ret = set_blue_led_mode(LED_SYSTEM_ON, LED_BREATHE_MODE);
+ } else if (strcmp(argv[3], "heartbeat") == 0) {
+ ret = set_blue_led_mode(LED_SYSTEM_ON, LED_HEARTBEAT_MODE);
+ } else if (strcmp(argv[3], "on") == 0) {
+ ret = set_blue_led_mode(LED_SYSTEM_ON, LED_ON_MODE);
+ } else if (strcmp(argv[3], "off") == 0) {
+ ret = set_blue_led_mode(LED_SYSTEM_ON, LED_OFF_MODE);
+ } else {
+ ret = CMD_RET_USAGE;
+ }
+ }
+
+ } else {
+ return CMD_RET_USAGE;
+ }
+ return ret;
+}
+
+static int do_kbi_poweroff(struct cmd_tbl * cmdtp, int flag, int argc, char * const argv[])
+{
+ printf("System poweroff\n");
+ set_poweroff();
+ return 0;
+}
+
+static int do_kbi_trigger(struct cmd_tbl * cmdtp, int flag, int argc, char * const argv[])
+{
+ if (argc < 3)
+ return CMD_RET_USAGE;
+
+ if (strcmp(argv[2], "r") == 0) {
+
+ if (strcmp(argv[1], "rtc") == 0)
+ get_boot_enable(BOOT_EN_RTC);
+ else if (strcmp(argv[1], "ir") == 0)
+ get_boot_enable(BOOT_EN_IR);
+ else if (strcmp(argv[1], "dcin") == 0)
+ get_boot_enable(BOOT_EN_DCIN);
+ else if (strcmp(argv[1], "key") == 0)
+ get_boot_enable(BOOT_EN_KEY);
+ else if (strcmp(argv[1], "gpio") == 0)
+ get_boot_enable(BOOT_EN_GPIO);
+ else
+ return CMD_RET_USAGE;
+ } else if (strcmp(argv[2], "w") == 0) {
+ if (argc < 4)
+ return CMD_RET_USAGE;
+ if ((strcmp(argv[3], "1") != 0) && (strcmp(argv[3], "0") != 0))
+ return CMD_RET_USAGE;
+
+ if (strcmp(argv[1], "rtc") == 0) {
+
+ if (strcmp(argv[3], "1") == 0)
+ set_boot_enable(BOOT_EN_RTC, 1);
+ else
+ set_boot_enable(BOOT_EN_RTC, 0);
+
+ } else if (strcmp(argv[1], "ir") == 0) {
+
+ if (strcmp(argv[3], "1") == 0)
+ set_boot_enable(BOOT_EN_IR, 1);
+ else
+ set_boot_enable(BOOT_EN_IR, 0);
+
+ } else if (strcmp(argv[1], "dcin") == 0) {
+
+ if (strcmp(argv[3], "1") == 0)
+ set_boot_enable(BOOT_EN_DCIN, 1);
+ else
+ set_boot_enable(BOOT_EN_DCIN, 0);
+
+ } else if (strcmp(argv[1], "key") == 0) {
+
+ if (strcmp(argv[3], "1") == 0)
+ set_boot_enable(BOOT_EN_KEY, 1);
+ else
+ set_boot_enable(BOOT_EN_KEY, 0);
+
+ } else if (strcmp(argv[1], "gpio") == 0) {
+
+ if (strcmp(argv[3], "1") == 0)
+ set_boot_enable(BOOT_EN_GPIO, 1);
+ else
+ set_boot_enable(BOOT_EN_GPIO, 0);
+
+ } else {
+ return CMD_RET_USAGE;
+
+ }
+ } else {
+
+ return CMD_RET_USAGE;
+ }
+
+ return 0;
+}
+
+
+static int do_kbi_bootmode(struct cmd_tbl * cmdtp, int flag, int argc, char * const argv[])
+{
+ if (argc < 2)
+ return CMD_RET_USAGE;
+ if (strcmp(argv[1], "w") == 0) {
+ if (argc < 3)
+ return CMD_RET_USAGE;
+ if (strcmp(argv[2], "emmc") == 0) {
+ set_bootmode(BOOT_MODE_EMMC);
+ } else if (strcmp(argv[2], "spi") == 0) {
+ set_bootmode(BOOT_MODE_SPI);
+ } else {
+ return CMD_RET_USAGE;
+ }
+ } else if (strcmp(argv[1], "r") == 0) {
+
+ get_bootmode();
+
+ } else {
+ return CMD_RET_USAGE;
+ }
+
+ return 0;
+}
+static struct cmd_tbl cmd_kbi_sub[] = {
+ U_BOOT_CMD_MKENT(init, 1, 1, do_kbi_init, "", ""),
+ U_BOOT_CMD_MKENT(resetflag, 2, 1, do_kbi_resetflag, "", ""),
+ U_BOOT_CMD_MKENT(usid, 1, 1, do_kbi_usid, "", ""),
+ U_BOOT_CMD_MKENT(version, 1, 1, do_kbi_version, "", ""),
+ U_BOOT_CMD_MKENT(adc, 1, 1, do_kbi_adc, "", ""),
+ U_BOOT_CMD_MKENT(powerstate, 1, 1, do_kbi_powerstate, "", ""),
+ U_BOOT_CMD_MKENT(ethmac, 1, 1, do_kbi_ethmac, "", ""),
+#if defined (CONFIG_ARCH_ROCKCHIP)
+ U_BOOT_CMD_MKENT(boarddetect, 1, 1, do_kbi_boarddetect, "", ""),
+#else
+ U_BOOT_CMD_MKENT(hwver, 1, 1, do_kbi_hwver, "", ""),
+#endif
+ U_BOOT_CMD_MKENT(poweroff, 1, 1, do_kbi_poweroff, "", ""),
+ U_BOOT_CMD_MKENT(switchmac, 3, 1, do_kbi_switchmac, "", ""),
+ U_BOOT_CMD_MKENT(led, 4, 1, do_kbi_led, "", ""),
+ U_BOOT_CMD_MKENT(trigger, 4, 1, do_kbi_trigger, "", ""),
+ U_BOOT_CMD_MKENT(bootmode, 3, 1, do_kbi_bootmode, "", ""),
+#if defined(CONFIG_MESON_G12A)
+ U_BOOT_CMD_MKENT(portmode, 1, 1, do_kbi_portmode, "", ""),
+#endif
+};
+
+static int do_kbi(struct cmd_tbl * cmdtp, int flag, int argc, char * const argv[])
+{
+ struct cmd_tbl *c;
+
+#if defined (CONFIG_MESON_GXL)
+ int hw_ver = 0;
+ unsigned int val = 0;
+ int ret = 0;
+
+ ret = adc_channel_single_shot("adc@8680", 1, &val);
+ if (ret) {
+ printf("%s adc_channel_single_shot fail! ret=%d\n", __func__, ret);
+ return -1;
+ }
+
+ if ((val >= HW_VERSION_ADC_VAL_VIM1_V14 - HW_VERSION_ADC_VALUE_TOLERANCE) && (val <= HW_VERSION_ADC_VAL_VIM1_V14 + HW_VERSION_ADC_VALUE_TOLERANCE)) {
+ hw_ver = HW_VERSION_VIM1_V14;
+ } else if ((val >= HW_VERSION_ADC_VAL_VIM1_V12 - HW_VERSION_ADC_VALUE_TOLERANCE) && (val <= HW_VERSION_ADC_VAL_VIM1_V12 + HW_VERSION_ADC_VALUE_TOLERANCE)) {
+ hw_ver = HW_VERSION_VIM1_V12;
+ } else {
+ hw_ver = HW_VERSION_UNKNOW;
+ }
+ if ((hw_ver == HW_VERSION_UNKNOW) || (hw_ver == HW_VERSION_VIM1_V12)) {
+ printf("The Board don't support KBI interface\n");
+ env_set("hwver", hw_version_str(hw_ver));
+ return CMD_RET_FAILURE;
+ }
+#endif
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ /* Strip off leading 'kbi' command argument */
+ argc--;
+ argv++;
+
+ c = find_cmd_tbl(argv[0], &cmd_kbi_sub[0], ARRAY_SIZE(cmd_kbi_sub));
+
+ if (c)
+ return c->cmd(cmdtp, flag, argc, argv);
+ else
+ return CMD_RET_USAGE;
+
+}
+static char kbi_help_text[] =
+ "[function] [mode] [write|read] <value>\n"
+ "\n"
+ "kbi version - read version information\n"
+ "kbi usid - read usid information\n"
+ "kbi adc - read adc value\n"
+ "kbi powerstate - read power on state\n"
+ "kbi poweroff - power off device\n"
+ "kbi ethmac - read ethernet mac address\n"
+#if defined (CONFIG_ARCH_ROCKCHIP)
+ "kbi boarddetect - detect board type\n"
+#else
+ "kbi hwver - read board hardware version\n"
+#endif
+ "\n"
+ "kbi led [systemoff|systemon] w <off|on|breathe|heartbeat> - set blue led mode\n"
+ "kbi led [systemoff|systemon] r - read blue led mode\n"
+ "\n"
+ "kbi bootmode w <emmc|spi> - set bootmode to emmc or spi\n"
+ "kbi bootmode r - read current bootmode\n"
+ "\n"
+#if defined(CONFIG_MESON_G12A)
+ "kbi portmode w <0|1> - set port as usb3.0 or pcie\n"
+ "kbi portmode r - read current port mode\n"
+ "\n"
+#endif
+ "kbi trigger [rtc|ir|dcin|key|gpio] w <0|1> - disable/enable boot trigger\n"
+ "kbi trigger [rtc|ir|dcin|key|gpio] r - read mode of a boot trigger";
+
+
+U_BOOT_CMD(
+ kbi, 6, 1, do_kbi,
+ "Khadas Bootloader Instructions sub-system",
+ kbi_help_text
+);
--
Armbian