support lt6911d

This commit is contained in:
916BGAI
2026-06-09 18:00:32 +08:00
parent 3de4a18eb4
commit 208998c13a
7 changed files with 382 additions and 102 deletions

View File

@@ -1,5 +1,5 @@
#!/bin/sh
# kvmhwd Rev2.1
# kvmhwd Rev2.2
start_usb_dev(){
. /etc/profile
@@ -23,6 +23,11 @@ start_usb_dev(){
else
echo 0x1009 > idProduct
fi
echo 0xEF > bDeviceClass
echo 0x02 > bDeviceSubClass
echo 0x01 > bDeviceProtocol
mkdir strings/0x409
echo '0123456789ABCDEF' > strings/0x409/serialnumber
echo 'sipeed' > strings/0x409/manufacturer
@@ -37,15 +42,30 @@ start_usb_dev(){
if [ -e /boot/usb.ncm ]
then
mkdir functions/ncm.usb0
echo WINNCM > functions/ncm.usb0/os_desc/interface.ncm/compatible_id
ln -s functions/ncm.usb0 configs/c.1/
else
if [ -e /boot/usb.rndis0 ]
then
mkdir functions/rndis.usb0
echo e0 > functions/rndis.usb0/class
echo 01 > functions/rndis.usb0/subclass
echo 03 > functions/rndis.usb0/protocol
echo RNDIS > functions/rndis.usb0/os_desc/interface.rndis/compatible_id
echo 5162001 > functions/rndis.usb0/os_desc/interface.rndis/sub_compatible_id
ln -s functions/rndis.usb0 configs/c.1/
fi
fi
if [ -e /boot/usb.ncm ] || [ -e /boot/usb.rndis0 ]
then
# Microsoft OS 2.0 Descriptor
echo 1 > os_desc/use
echo 0xCD > os_desc/b_vendor_code
echo MSFT100 > os_desc/qw_sign
ln -s configs/c.1 os_desc
fi
if [ ! -e /boot/disable_hid ]
then
# keyboard

View File

@@ -1,5 +1,5 @@
#!/bin/sh
# kvmhwd Rev2.4
# kvmhwd Rev2.5
Alpha_OLED_RST_Pin=371
Beta_OLED_RST_Pin=502
@@ -146,19 +146,7 @@ kvm_hw_detect(){
insmod /mnt/system/ko/i2c-algo-bit.ko
insmod /mnt/system/ko/i2c-gpio.ko
kvm_tmp=$(i2cdetect -ry 4 0x2c 0x2c | grep 2c)
if [ -n "$kvm_tmp" ]
then
echo "c" > /etc/kvm/hdmi_version
else
kvm_tmp1=$(i2cdetect -ry 4 0x2b 0x2b | grep 2b)
if [ -n "$kvm_tmp1" ]
then
echo "ux" > /etc/kvm/hdmi_version
else
echo "ue" > /etc/kvm/hdmi_version
fi
fi
kvm_hdmi_version_detect
kvm_tmp=$(i2cdetect -ry 5 0x3c 0x3c | grep 3c)
if [ -n "$kvm_tmp" ]
@@ -199,20 +187,19 @@ kvm_hw_init(){
fi
}
kvm_hdmi_version_detect(){
hdmi_tmp=$(i2cdetect -ry 4 0x2c 0x2c | grep 2c)
if [ -n "$hdmi_tmp" ]
then
echo "c" > /etc/kvm/hdmi_version
else
hdmi_tmp1=$(i2cdetect -ry 4 0x2b 0x2b | grep 2b)
if [ -n "$hdmi_tmp1" ]
then
echo "ux" > /etc/kvm/hdmi_version
kvm_hdmi_version_detect()
{
if i2cdetect -ry 4 0x2c 0x2c | grep -qw "2c"; then
echo "c" > /etc/kvm/hdmi_version
elif i2cdetect -ry 4 0x2b 0x2b | grep -qw "2b"; then
if i2cdetect -ry 4 0x44 0x44 | grep -qw "44"; then
echo "ux" > /etc/kvm/hdmi_version
else
echo "d" > /etc/kvm/hdmi_version
fi
else
echo "ue" > /etc/kvm/hdmi_version
echo "ue" > /etc/kvm/hdmi_version
fi
fi
}
case "$1" in

View File

@@ -495,6 +495,11 @@ uint8_t chack_ion()
void lt6911_enable()
{
uint8_t buf[2];
if(kvmv_cfg.hdmi_version == 3){
return;
}
buf[0] = 0xff;
buf[1] = 0x80;
LT6911_i2c.writeto(LT6911_ADDR, buf, 2);
@@ -503,7 +508,7 @@ void lt6911_enable()
buf[1] = 0x01;
LT6911_i2c.writeto(LT6911_ADDR, buf, 2);
if(kvmv_cfg.hdmi_version != 0){
if(kvmv_cfg.hdmi_version == 1){
// disable watchdog
buf[0] = 0x10;
buf[1] = 0x00;
@@ -514,6 +519,11 @@ void lt6911_enable()
void lt6911_disable()
{
uint8_t buf[2];
if(kvmv_cfg.hdmi_version == 3){
return;
}
buf[0] = 0xff;
buf[1] = 0x80;
LT6911_i2c.writeto(LT6911_ADDR, buf, 2);
@@ -629,6 +639,38 @@ uint8_t lt6911_get_hdmi_res()
if(revbuf[0] == 0x55) return 1;
else if(revbuf[0] == 0x88) return 0;
else return 0;
} else if (kvmv_cfg.hdmi_version == 3){
// LT6911D
buf[0] = 0xff;
buf[1] = 0xe0;
LT6911_i2c.writeto(LT6911_ADDR, buf, 2);
// Hactive
buf[0] = 0x8c;
LT6911_i2c.writeto(LT6911_ADDR, buf, 1);
maix::Bytes *dat0 = LT6911_i2c.readfrom(LT6911_ADDR, 2);
// Vactive
buf[0] = 0x8e;
LT6911_i2c.writeto(LT6911_ADDR, buf, 1);
maix::Bytes *dat1 = LT6911_i2c.readfrom(LT6911_ADDR, 2);
revbuf[0] = (uint8_t)dat0->data[0];
revbuf[1] = (uint8_t)dat0->data[1];
revbuf[2] = (uint8_t)dat1->data[0];
revbuf[3] = (uint8_t)dat1->data[1];
Hactive = ((revbuf[0] << 8)|revbuf[1]) * 2;
Vactive = (revbuf[2] << 8)|revbuf[3];
debug("[hdmi]HDMI-D res modification event\n");
debug("[hdmi]new res: %d * %d\n", Hactive, Vactive);
delete dat0;
delete dat1;
if(Hactive != 0 || Vactive != 0) return 1;
else return 0;
} else {
return 0;
}
@@ -738,6 +780,33 @@ uint8_t lt6911_get_csi_res(uint16_t *p_width, uint16_t *p_height)
Vactive = (revbuf[0] << 8)|revbuf[1];
Hactive = (revbuf[2] << 8)|revbuf[3];
} else if(kvmv_cfg.hdmi_version == 3) {
// LT6911D
debug("[hdmi]D get csi res\n");
buf[0] = 0xff;
buf[1] = 0xe0;
LT6911_i2c.writeto(LT6911_ADDR, buf, 2);
// Vactive
buf[0] = 0x8e;
LT6911_i2c.writeto(LT6911_ADDR, buf, 1);
maix::Bytes *dat0 = LT6911_i2c.readfrom(LT6911_ADDR, 2);
// Hactive
buf[0] = 0x8c;
LT6911_i2c.writeto(LT6911_ADDR, buf, 1);
maix::Bytes *dat1 = LT6911_i2c.readfrom(LT6911_ADDR, 2);
revbuf[0] = (uint8_t)dat0->data[0];
revbuf[1] = (uint8_t)dat0->data[1];
revbuf[2] = (uint8_t)dat1->data[0];
revbuf[3] = (uint8_t)dat1->data[1];
delete dat0;
delete dat1;
Vactive = (revbuf[0] << 8)|revbuf[1];
Hactive = ((revbuf[2] << 8)|revbuf[3]) * 2;
} else {
return UNKNOWN_RES;
}
@@ -1048,6 +1117,10 @@ void get_hdmi_version()
kvmv_cfg.hdmi_version = 1;
debug("[hdmi]Incomplete version number, set to 'ux'\n");
}
} else if(RW_Data[0] == 'd'){
// 6911d
kvmv_cfg.hdmi_version = 3;
debug("[hdmi]HDMI-D exist!\n");
} else {
// 6911c
kvmv_cfg.hdmi_version = 0;
@@ -1171,6 +1244,31 @@ void* vi_subsystem_detection(void * arg)
}
lt6911_disable();
}
} else if (kvmv_cfg.hdmi_version == 3){
// LT6911D
debug("[hdmi] D int\n");
if(falling_times != 0){
debug("[hdmi] D int && \n");
lt6911_enable();
if(lt6911_get_hdmi_res()){
// hdmi get res
debug("[hdmi] D HDMI cable insertion!\n");
kvmv_cfg.hdmi_cable_state = 1;
kvmv_cfg.hdmi_res_type = lt6911_get_csi_res(&kvmv_cfg.vi_width, &kvmv_cfg.vi_height);
if (kvmv_cfg.hdmi_res_type == NEW_RES) kvmv_cfg.reopen_cam_flag = 1;
else if (kvmv_cfg.hdmi_res_type == UNKNOWN_RES){
/* Move HDMI resolution modification directly
to mode1 to solve deadlock problem */
auto_change_mode = 1;
set_hdmi_mode(1);
}
} else {
// HDMI res = 0*0/x*0
debug("[hdmi] D HDMI cable unplugged!\n");
kvmv_cfg.hdmi_cable_state = 0;
}
lt6911_disable();
}
} else {
debug("[hdmi] Chip not supported for reading \n");
}

View File

@@ -17,7 +17,7 @@ uint8_t get_hdmi_version()
fread(RW_Data, sizeof(char), 2, fp);
fclose(fp);
if(RW_Data[0] == 'u'){
// 6911uxc
// 6911uxc / 6911uxe
if(RW_Data[1] == 'e'){
return 2;
} else if(RW_Data[1] == 'x') {
@@ -25,6 +25,9 @@ uint8_t get_hdmi_version()
} else {
return 1;
}
} else if(RW_Data[0] == 'd'){
// 6911d
return 3;
} else {
// 6911c
return 0;
@@ -139,6 +142,7 @@ void new_app_init(void)
fclose(fp);
if(RW_Data[0] == 'c') hdmi_ver = 1;
else if(RW_Data[0] == 'u') hdmi_ver = 2;
else if(RW_Data[0] == 'd') hdmi_ver = 2;
}
// system("/etc/init.d/S03usbdev stop_start");

View File

@@ -487,6 +487,158 @@ int lt6911c_edid_read(uint8_t *edid_data, uint16_t edid_size)
return 0;
}
int lt6911d_str_read(uint8_t *str)
{
fprintf(stdout, "Reading LT6911D version data...\n");
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0xEE, 0x01) != 0) return -1;
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5E, 0xDF) != 0) return -1;
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x58, 0x00) != 0) return -1;
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x59, 0x50) != 0) return -1;
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x10) != 0) return -1;
usleep(1000);
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x00) != 0) return -1;
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x58, 0x21) != 0) return -1;
if (i2c_write_byte(LT6911D_DATA_OFFSET, 0x03, 0xBF) != 0) return -1;
usleep(1000);
if (i2c_write_byte(LT6911D_DATA_OFFSET, 0x03, 0xFF) != 0) return -1;
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x04) != 0) return -1;
usleep(1000);
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x00) != 0) return -1;
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5E, 0x5F) != 0) return -1;
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x20) != 0) return -1;
usleep(1000);
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x00) != 0) return -1;
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5B, 0x00) != 0) return -1;
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5C, 0x81) != 0) return -1;
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5D, 0x00) != 0) return -1;
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x10) != 0) return -1;
usleep(1000);
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x00) != 0) return -1;
if (i2c_read_bytes(LT6911D_MANAGE_OFFSET, 0x5F, str, LT6911D_WR_SIZE) != 0) return -1;
usleep(10000);
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x08) != 0) return -1;
usleep(1000);
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x00) != 0) return -1;
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x58, 0x00) != 0) return -1;
return 0;
}
int lt6911d_edid_write(uint8_t *edid_data, uint16_t edid_size)
{
uint8_t i;
uint8_t wr_count = edid_size / LT6911D_WR_SIZE + 1;
uint8_t version_str[LT6911D_WR_SIZE] = {0};
if (lt6911d_str_read(version_str) != 0) {
fprintf(stderr, "Failed to read LT6911D version data\n");
return -1;
}
fprintf(stdout, "Writing EDID....\n");
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0xEE, 0x01) != 0) return -1;
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5E, 0xDF) != 0) return -1;
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x58, 0x00) != 0) return -1;
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x59, 0x50) != 0) return -1;
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x10) != 0) return -1;
usleep(1000);
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x00) != 0) return -1;
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x58, 0x21) != 0) return -1;
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x04) != 0) return -1;
usleep(1000);
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x00) != 0) return -1;
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5B, 0x00) != 0) return -1;
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5C, 0x80) != 0) return -1;
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5D, 0x00) != 0) return -1;
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x01) != 0) return -1;
usleep(1000);
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x00) != 0) return -1;
usleep(600000);
for (i = 0; i < wr_count; i++) {
if (i2c_write_byte(LT6911D_DATA_OFFSET, 0x03, 0xBF) != 0) return -1;
usleep(1000);
if (i2c_write_byte(LT6911D_DATA_OFFSET, 0x03, 0xFF) != 0) return -1;
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x04) != 0) return -1;
usleep(1000);
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x00) != 0) return -1;
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5E, 0xDF) != 0) return -1;
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x20) != 0) return -1;
usleep(1000);
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x00) != 0) return -1;
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x58, 0x21) != 0) return -1;
if (i != wr_count - 1) {
if (i2c_write_bytes(LT6911D_MANAGE_OFFSET, 0x59, edid_data + (LT6911D_WR_SIZE * i), LT6911D_WR_SIZE) != 0) return -1;
} else {
if (i2c_write_bytes(LT6911D_MANAGE_OFFSET, 0x59, version_str, LT6911D_WR_SIZE) != 0) return -1;
}
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5B, 0x00) != 0) return -1;
if (i != wr_count - 1) {
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5C, 0x80) != 0) return -1;
} else {
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5C, 0x81) != 0) return -1;
}
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5D, 0x00 + (LT6911D_WR_SIZE * i)) != 0) return -1;
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x10) != 0) return -1;
usleep(5000);
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x00) != 0) return -1;
usleep(10000);
}
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x08) != 0) return -1;
usleep(1000);
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x00) != 0) return -1;
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x58, 0x00) != 0) return -1;
fprintf(stdout, "EDID write completed\n");
return 0;
}
int lt6911d_edid_read(uint8_t *edid_data, uint16_t edid_size)
{
uint8_t i;
uint8_t wr_count = edid_size / LT6911D_WR_SIZE;
fprintf(stdout, "Reading EDID...\n");
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0xEE, 0x01) != 0) return -1;
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5E, 0xDF) != 0) return -1;
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x58, 0x00) != 0) return -1;
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x59, 0x50) != 0) return -1;
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x10) != 0) return -1;
usleep(1000);
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x00) != 0) return -1;
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x58, 0x21) != 0) return -1;
for (i = 0; i < wr_count; i++) {
if (i2c_write_byte(LT6911D_DATA_OFFSET, 0x03, 0xBF) != 0) return -1;
usleep(1000);
if (i2c_write_byte(LT6911D_DATA_OFFSET, 0x03, 0xFF) != 0) return -1;
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x04) != 0) return -1;
usleep(1000);
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x00) != 0) return -1;
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5E, 0x5F) != 0) return -1;
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x20) != 0) return -1;
usleep(1000);
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x00) != 0) return -1;
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5B, 0x00) != 0) return -1;
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5C, 0x80) != 0) return -1;
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5D, 0x00 + (LT6911D_WR_SIZE * i)) != 0) return -1;
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x10) != 0) return -1;
usleep(1000);
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x00) != 0) return -1;
if (i2c_read_bytes(LT6911D_MANAGE_OFFSET, 0x5F, edid_data + (LT6911D_WR_SIZE * i), LT6911D_WR_SIZE) != 0) return -1;
usleep(10000);
}
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x08) != 0) return -1;
usleep(1000);
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x5A, 0x00) != 0) return -1;
if (i2c_write_byte(LT6911D_MANAGE_OFFSET, 0x58, 0x00) != 0) return -1;
return 0;
}
// =======================================================================================================
int lt6911_edid_config(chip_version_t chip_version, uint8_t *edid_data, uint16_t edid_size)
@@ -523,6 +675,12 @@ int lt6911_edid_config(chip_version_t chip_version, uint8_t *edid_data, uint16_t
close(client);
return -1;
}
} else if (chip_version == CHIP_LT6911D) {
if (lt6911d_edid_write(edid_data, edid_size) != 0) {
fprintf(stderr, "Failed to write EDID data to LT6911D\n");
close(client);
return -1;
}
} else {
fprintf(stderr, "Unknown chip version\n");
close(client);
@@ -545,6 +703,12 @@ int lt6911_edid_config(chip_version_t chip_version, uint8_t *edid_data, uint16_t
close(client);
return -1;
}
} else if (chip_version == CHIP_LT6911D) {
if (lt6911d_edid_read(edid_read_data, EDID_BUFFER_SIZE) != 0) {
fprintf(stderr, "Failed to read EDID data from LT6911D\n");
close(client);
return -1;
}
} else {
fprintf(stderr, "Unknown chip version\n");
close(client);
@@ -686,6 +850,9 @@ int main(int argc, char *argv[]) {
} else if (strcmp(chip_version_str, "ux") == 0) {
fprintf(stdout, "Chip Version: LT6911UXC\n");
chip_version = CHIP_LT6911UXC;
} else if (strcmp(chip_version_str, "d") == 0) {
fprintf(stdout, "Chip Version: LT6911D\n");
chip_version = CHIP_LT6911D;
} else if (strcmp(chip_version_str, "ue") == 0) {
fprintf(stderr, "Chip Version Error: UE version's edid can't be updated\n");
return 1;

View File

@@ -17,10 +17,13 @@
#define LT6911C_HDMI_INFO_OFFSET 0xD2 // LT6911C HDMI信息寄存器偏移地址
#define LT6911C_AUDIO_INFO_OFFSET 0xD1 // LT6911C 音频信息寄存器偏移地址
#define LT6911C_CSI_INFO_OFFSET 0xC2 // LT6911C CSI信息寄存器偏移地址
#define LT6911D_MANAGE_OFFSET 0xE0 // LT6911D 管理寄存器偏移地址
#define LT6911D_DATA_OFFSET 0xE1 // LT6911D 数据寄存器偏移地址
#define EDID_BUFFER_SIZE 256 // 最大支持的字节数
#define LT6911UXC_WR_SIZE 32 // LT6911UXC单次读写最大字节数
#define LT6911C_WR_SIZE 16 // LT6911C单次读写最大字节数
#define LT6911D_WR_SIZE 32 // LT6911D单次读写最大字节数
#define VERSION_PATH "/etc/kvm/hdmi_version"
#define PRODUCT_PATH "/etc/kvm/hw"
@@ -28,6 +31,7 @@
typedef enum {
CHIP_LT6911UXC = 0,
CHIP_LT6911C,
CHIP_LT6911D,
CHIP_UNKNOWN
} chip_version_t;