2024-09-17 12:17:12 -07:00
|
|
|
#!/usr/bin/env python3
|
2024-10-04 22:12:38 +07:00
|
|
|
|
2023-10-30 22:21:58 +07:00
|
|
|
import ctypes
|
2024-10-04 22:12:38 +07:00
|
|
|
import argparse
|
|
|
|
import click
|
2023-10-30 22:21:58 +07:00
|
|
|
import pandas as pd
|
|
|
|
|
|
|
|
# hex value for register: guid, gsnpsid, ghwcfg1, ghwcfg2, ghwcfg3, ghwcfg4
|
2024-09-18 17:59:04 +07:00
|
|
|
# Note: FS is FullSpeed, HS is HighSpeed
|
2024-10-04 22:12:38 +07:00
|
|
|
dwc2_reg_list = ['GUID', 'GSNPSID', 'GHWCFG1', 'GHWCFG2', 'GHWCFG3', 'GHWCFG4']
|
2023-10-30 22:21:58 +07:00
|
|
|
dwc2_reg_value = {
|
|
|
|
'BCM2711 (Pi4)': [0x2708A000, 0x4F54280A, 0, 0x228DDD50, 0xFF000E8, 0x1FF00020],
|
2024-09-18 17:59:04 +07:00
|
|
|
'EFM32GG FS': [0, 0x4F54330A, 0, 0x228F5910, 0x1F204E8, 0x1BF08030],
|
|
|
|
'ESP32-S2/S3': [0, 0x4F54400A, 0, 0x224DD930, 0xC804B5, 0xD3F0A030],
|
2024-09-25 20:36:16 +07:00
|
|
|
'ESP32-P4': [0, 0x4F54400A, 0, 0x215FFFD0, 0x03805EB5, 0xDFF1A030],
|
2024-10-04 22:12:38 +07:00
|
|
|
'ST F407/411/429 FS': [0x1200, 0x4F54281A, 0, 0x229DCD20, 0x20001E8, 0xFF08030],
|
|
|
|
'ST F407/429 HS': [0x1100, 0x4F54281A, 0, 0x229ED590, 0x3F403E8, 0x17F00030],
|
|
|
|
'ST F412/767 FS': [0x2000, 0x4F54320A, 0, 0x229ED520, 0x200D1E8, 0x17F08030],
|
|
|
|
'ST F723 FS': [0x3000, 0x4F54330A, 0, 0x229ED520, 0x200D1E8, 0x17F08030],
|
|
|
|
'ST F723 HS': [0x3100, 0x4F54330A, 0, 0x229FE1D0, 0x3EED2E8, 0x23F00030],
|
|
|
|
'ST F769': [0x2100, 0x4F54320A, 0, 0x229FE190, 0x03EED2E8, 0x23F00030],
|
|
|
|
'ST H743 HS': [0x2300, 0x4F54330A, 0, 0x229FE190, 0x3B8D2E8, 0xE3F00030], # both HS cores
|
|
|
|
'ST L476 FS': [0x2000, 0x4F54310A, 0, 0x229ED520, 0x200D1E8, 0x17F08030],
|
|
|
|
'ST U5A5 HS': [0x5000, 0x4F54411A, 0, 0x228FE052, 0x03B882E8, 0xE2103E30],
|
2024-09-18 17:59:04 +07:00
|
|
|
'GD32VF103 FS': [0x1000, 0, 0, 0, 0, 0],
|
2023-10-30 22:21:58 +07:00
|
|
|
'XMC4500': [0xAEC000, 0x4F54292A, 0, 0x228F5930, 0x27A01E5, 0xDBF08030]
|
|
|
|
}
|
|
|
|
|
|
|
|
# Combine dwc2_info with dwc2_reg_list
|
|
|
|
# dwc2_info = {
|
|
|
|
# 'BCM2711 (Pi4)': {
|
2024-10-04 22:12:38 +07:00
|
|
|
# 'GUID': 0x2708A000,
|
|
|
|
# 'GSNPSID': 0x4F54280A,
|
|
|
|
# 'GHWCFG1': 0,
|
|
|
|
# 'GHWCFG2': 0x228DDD50,
|
|
|
|
# 'GHWCFG3': 0xFF000E8,
|
|
|
|
# 'GHWCFG4': 0x1FF00020
|
2023-10-30 22:21:58 +07:00
|
|
|
# },
|
|
|
|
dwc2_info = {key: {field: value for field, value in zip(dwc2_reg_list, values)} for key, values in dwc2_reg_value.items()}
|
|
|
|
|
2023-11-22 17:36:52 +07:00
|
|
|
|
2023-10-30 22:21:58 +07:00
|
|
|
class GHWCFG2(ctypes.LittleEndianStructure):
|
|
|
|
_fields_ = [
|
|
|
|
("op_mode", ctypes.c_uint32, 3),
|
|
|
|
("arch", ctypes.c_uint32, 2),
|
2024-10-04 22:12:38 +07:00
|
|
|
("p2p (hub support)", ctypes.c_uint32, 1),
|
2023-10-30 22:21:58 +07:00
|
|
|
("hs_phy_type", ctypes.c_uint32, 2),
|
|
|
|
("fs_phy_type", ctypes.c_uint32, 2),
|
|
|
|
("num_dev_ep", ctypes.c_uint32, 4),
|
|
|
|
("num_host_ch", ctypes.c_uint32, 4),
|
|
|
|
("period_channel_support", ctypes.c_uint32, 1),
|
|
|
|
("enable_dynamic_fifo", ctypes.c_uint32, 1),
|
|
|
|
("mul_cpu_int", ctypes.c_uint32, 1),
|
|
|
|
("reserved21", ctypes.c_uint32, 1),
|
2024-09-24 22:35:07 +07:00
|
|
|
("nptx_q_depth", ctypes.c_uint32, 2),
|
|
|
|
("ptx_q_depth", ctypes.c_uint32, 2),
|
|
|
|
("token_q_depth", ctypes.c_uint32, 5),
|
2023-10-30 22:21:58 +07:00
|
|
|
("otg_enable_ic_usb", ctypes.c_uint32, 1)
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
class GHWCFG3(ctypes.LittleEndianStructure):
|
|
|
|
_fields_ = [
|
|
|
|
("xfer_size_width", ctypes.c_uint32, 4),
|
|
|
|
("packet_size_width", ctypes.c_uint32, 3),
|
|
|
|
("otg_enable", ctypes.c_uint32, 1),
|
|
|
|
("i2c_enable", ctypes.c_uint32, 1),
|
|
|
|
("vendor_ctrl_itf", ctypes.c_uint32, 1),
|
|
|
|
("optional_feature_removed", ctypes.c_uint32, 1),
|
|
|
|
("synch_reset", ctypes.c_uint32, 1),
|
|
|
|
("otg_adp_support", ctypes.c_uint32, 1),
|
|
|
|
("otg_enable_hsic", ctypes.c_uint32, 1),
|
|
|
|
("battery_charger_support", ctypes.c_uint32, 1),
|
|
|
|
("lpm_mode", ctypes.c_uint32, 1),
|
2024-09-24 22:35:07 +07:00
|
|
|
("dfifo_depth", ctypes.c_uint32, 16)
|
2023-10-30 22:21:58 +07:00
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
class GHWCFG4(ctypes.LittleEndianStructure):
|
|
|
|
_fields_ = [
|
|
|
|
("num_dev_period_in_ep", ctypes.c_uint32, 4),
|
2024-09-24 22:35:07 +07:00
|
|
|
("partial_powerdown", ctypes.c_uint32, 1),
|
2023-10-30 22:21:58 +07:00
|
|
|
("ahb_freq_min", ctypes.c_uint32, 1),
|
|
|
|
("hibernation", ctypes.c_uint32, 1),
|
2024-09-24 22:35:07 +07:00
|
|
|
("extended_hibernation", ctypes.c_uint32, 1),
|
|
|
|
("reserved8", ctypes.c_uint32, 1),
|
|
|
|
("enhanced_lpm_support1", ctypes.c_uint32, 1),
|
|
|
|
("service_interval_flow", ctypes.c_uint32, 1),
|
|
|
|
("ipg_isoc_support", ctypes.c_uint32, 1),
|
|
|
|
("acg_support", ctypes.c_uint32, 1),
|
|
|
|
("enhanced_lpm_support", ctypes.c_uint32, 1),
|
|
|
|
("phy_data_width", ctypes.c_uint32, 2),
|
|
|
|
("ctrl_ep_num", ctypes.c_uint32, 4),
|
|
|
|
("iddg_filter", ctypes.c_uint32, 1),
|
|
|
|
("vbus_valid_filter", ctypes.c_uint32, 1),
|
|
|
|
("a_valid_filter", ctypes.c_uint32, 1),
|
|
|
|
("b_valid_filter", ctypes.c_uint32, 1),
|
|
|
|
("session_end_filter", ctypes.c_uint32, 1),
|
2023-10-30 22:21:58 +07:00
|
|
|
("dedicated_fifos", ctypes.c_uint32, 1),
|
|
|
|
("num_dev_in_eps", ctypes.c_uint32, 4),
|
|
|
|
("dma_desc_enable", ctypes.c_uint32, 1),
|
2024-09-24 22:35:07 +07:00
|
|
|
("dma_desc_dynamic", ctypes.c_uint32, 1)
|
2023-10-30 22:21:58 +07:00
|
|
|
]
|
|
|
|
|
2024-10-04 22:12:38 +07:00
|
|
|
# mapping for specific fields in GHWCFG2
|
|
|
|
GHWCFG2_field = {
|
|
|
|
'op_mode': {
|
|
|
|
0: "HNP SRP",
|
|
|
|
1: "SRP",
|
|
|
|
2: "noHNP noSRP",
|
|
|
|
3: "SRP Device",
|
|
|
|
4: "noOTG Device",
|
|
|
|
5: "SRP Host",
|
|
|
|
6: "noOTG Host"
|
|
|
|
},
|
|
|
|
'arch': {
|
|
|
|
0: "Slave only",
|
|
|
|
1: "DMA external",
|
|
|
|
2: "DMA internal"
|
|
|
|
},
|
|
|
|
'hs_phy_type': {
|
|
|
|
0: "N/A",
|
|
|
|
1: "UTMI+",
|
|
|
|
2: "ULPI",
|
|
|
|
3: "UTMI+/ULPI"
|
|
|
|
},
|
|
|
|
'fs_phy_type': {
|
|
|
|
0: "N/A",
|
|
|
|
1: "Dedicated",
|
|
|
|
2: "Shared UTMI+",
|
|
|
|
3: "Shared ULPI"
|
|
|
|
}
|
|
|
|
}
|
2023-10-30 22:21:58 +07:00
|
|
|
|
2024-10-04 22:12:38 +07:00
|
|
|
# mapping for specific fields in GHWCFG4
|
|
|
|
GHWCFG4_field = {
|
|
|
|
'phy_data_width': {
|
|
|
|
0: "8 bit",
|
|
|
|
1: "16 bit",
|
|
|
|
2: "8/16 bit",
|
|
|
|
3: "Reserved"
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
def main():
|
|
|
|
"""Render dwc2_info to Markdown table"""
|
2023-10-30 22:21:58 +07:00
|
|
|
|
2024-10-04 22:12:38 +07:00
|
|
|
parser = argparse.ArgumentParser()
|
|
|
|
args = parser.parse_args()
|
2023-10-30 22:21:58 +07:00
|
|
|
|
|
|
|
# Create an empty list to hold the dictionaries
|
2024-10-04 22:12:38 +07:00
|
|
|
md_table = []
|
2023-10-30 22:21:58 +07:00
|
|
|
|
2023-11-22 17:36:52 +07:00
|
|
|
# Iterate over the dwc2_info dictionary and extract fields
|
2023-10-30 22:21:58 +07:00
|
|
|
for device, reg_values in dwc2_info.items():
|
2024-10-04 22:12:38 +07:00
|
|
|
md_item = {"Device": device}
|
2023-10-30 22:21:58 +07:00
|
|
|
for r_name, r_value in reg_values.items():
|
2024-10-04 22:12:38 +07:00
|
|
|
md_item[r_name] = f"0x{r_value:08X}"
|
2023-11-22 17:36:52 +07:00
|
|
|
|
2024-10-04 22:12:38 +07:00
|
|
|
if r_name == 'GSNPSID':
|
2023-11-22 17:36:52 +07:00
|
|
|
# Get dwc2 specs version
|
|
|
|
major = ((r_value >> 8) >> 4) & 0x0F
|
|
|
|
minor = (r_value >> 4) & 0xFF
|
|
|
|
patch = chr((r_value & 0x0F) + ord('a') - 0xA)
|
2024-10-04 22:12:38 +07:00
|
|
|
md_item[f' - specs version'] = f"{major:X}.{minor:02X}{patch}"
|
|
|
|
elif r_name in globals():
|
2023-11-22 17:36:52 +07:00
|
|
|
# Get bit-field values which exist as ctypes structures
|
2024-10-04 22:12:38 +07:00
|
|
|
class_hdl = globals()[r_name]
|
|
|
|
ghwcfg = class_hdl.from_buffer_copy(r_value.to_bytes(4, byteorder='little'))
|
|
|
|
for field_name, field_type, _ in class_hdl._fields_:
|
|
|
|
field_value = getattr(ghwcfg, field_name)
|
|
|
|
if class_hdl == GHWCFG2 and field_name in GHWCFG2_field:
|
|
|
|
field_value = GHWCFG2_field[field_name].get(field_value, f"Unknown ({field_value})")
|
|
|
|
if class_hdl == GHWCFG4 and field_name in GHWCFG4_field:
|
|
|
|
field_value = GHWCFG4_field[field_name].get(field_value, f"Unknown ({field_value})")
|
|
|
|
|
|
|
|
md_item[f' - {field_name}'] = field_value
|
2023-10-30 22:21:58 +07:00
|
|
|
|
2024-10-04 22:12:38 +07:00
|
|
|
md_table.append(md_item)
|
2023-10-30 22:21:58 +07:00
|
|
|
|
|
|
|
# Create a Pandas DataFrame from the list of dictionaries
|
2024-10-04 22:12:38 +07:00
|
|
|
df = pd.DataFrame(md_table).set_index('Device')
|
2023-10-30 22:21:58 +07:00
|
|
|
|
|
|
|
# Transpose the DataFrame to switch rows and columns
|
|
|
|
df = df.T
|
|
|
|
#print(df)
|
|
|
|
|
|
|
|
# Write the Markdown table to a file
|
|
|
|
with open('dwc2_info.md', 'w') as md_file:
|
|
|
|
md_file.write(df.to_markdown())
|
2023-11-19 16:19:11 +01:00
|
|
|
md_file.write('\n')
|
2023-10-30 22:21:58 +07:00
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
2024-10-04 22:12:38 +07:00
|
|
|
main()
|