summaryrefslogtreecommitdiff
path: root/src/portable/synopsys/dwc2/dwc2_info.py
blob: 55bec3d2335022ac880d2b28af3edaec63f96e05 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
import click
import ctypes
import pandas as pd

# hex value for register: guid, gsnpsid, ghwcfg1, ghwcfg2, ghwcfg3, ghwcfg4
dwc2_reg_list = ['guid', 'gsnpsid', 'ghwcfg1', 'ghwcfg2', 'ghwcfg3', 'ghwcfg4']
dwc2_reg_value = {
    'BCM2711 (Pi4)': [0x2708A000, 0x4F54280A, 0, 0x228DDD50, 0xFF000E8, 0x1FF00020],
    'EFM32GG FullSpeed': [0, 0x4F54330A, 0, 0x228F5910, 0x1F204E8, 0x1BF08030],
    'ESP32-S2': [0, 0x4F54400A, 0, 0x224DD930, 0xC804B5, 0xD3F0A030],
    'STM32F407 Fullspeed': [0x1200, 0x4F54281A, 0, 0x229DCD20, 0x20001E8, 0xFF08030],
    'STM32F407 Highspeed': [0x1100, 0x4F54281A, 0, 0x229ED590, 0x3F403E8, 0x17F00030],
    'STM32F411 Fullspeed': [0x1200, 0x4F54281A, 0, 0x229DCD20, 0x20001E8, 0xFF08030],
    'STM32F412 Fullspeed': [0x2000, 0x4F54320A, 0, 0x229ED520, 0x200D1E8, 0x17F08030],
    'STM32F429 Fullspeed': [0x1200, 0x4F54281A, 0, 0x229DCD20, 0x20001E8, 0xFF08030],
    'STM32F429 Highspeed': [0x1100, 0x4F54281A, 0, 0x229ED590, 0x3F403E8, 0x17F00030],
    'STM32F723 Fullspeed': [0x3000, 0x4F54330A, 0, 0x229ED520, 0x200D1E8, 0x17F08030],
    'STM32F723 HighSpeed': [0x3100, 0x4F54330A, 0, 0x229FE1D0, 0x3EED2E8, 0x23F00030],
    'STM32F767 Fullspeed': [0x2000, 0x4F54320A, 0, 0x229ED520, 0x200D1E8, 0x17F08030],
    'STM32H743 Highspeed': [0x2300, 0x4F54330A, 0, 0x229FE190, 0x3B8D2E8, 0xE3F00030], # both HS cores
    'STM32L476 Fullspeed': [0x2000, 0x4F54310A, 0, 0x229ED520, 0x200D1E8, 0x17F08030],
    'STM32U5A5 Highspeed': [0x00005000, 0x4F54411A, 0x00000000, 0x228FE052, 0x03B882E8, 0xE2103E30],
    'GD32VF103 Fullspeed': [0x1000, 0, 0, 0, 0, 0],
    'XMC4500': [0xAEC000, 0x4F54292A, 0, 0x228F5930, 0x27A01E5, 0xDBF08030]
}

# Combine dwc2_info with dwc2_reg_list
# dwc2_info = {
#     'BCM2711 (Pi4)': {
#         'guid': 0x2708A000,
#         'gsnpsid': 0x4F54280A,
#         'ghwcfg1': 0,
#         'ghwcfg2': 0x228DDD50,
#         'ghwcfg3': 0xFF000E8,
#         'ghwcfg4': 0x1FF00020
#     },
dwc2_info = {key: {field: value for field, value in zip(dwc2_reg_list, values)} for key, values in dwc2_reg_value.items()}


class GHWCFG2(ctypes.LittleEndianStructure):
    _fields_ = [
        ("op_mode", ctypes.c_uint32, 3),
        ("arch", ctypes.c_uint32, 2),
        ("point2point", ctypes.c_uint32, 1),
        ("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),
        ("nperiod_tx_q_depth", ctypes.c_uint32, 2),
        ("host_period_tx_q_depth", ctypes.c_uint32, 2),
        ("dev_token_q_depth", ctypes.c_uint32, 5),
        ("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),
        ("total_fifo_size", ctypes.c_uint32, 16)
    ]


class GHWCFG4(ctypes.LittleEndianStructure):
    _fields_ = [
        ("num_dev_period_in_ep", ctypes.c_uint32, 4),
        ("power_optimized", ctypes.c_uint32, 1),
        ("ahb_freq_min", ctypes.c_uint32, 1),
        ("hibernation", ctypes.c_uint32, 1),
        ("reserved7", ctypes.c_uint32, 3),
        ("service_interval_mode", ctypes.c_uint32, 1),
        ("ipg_isoc_en", ctypes.c_uint32, 1),
        ("acg_enable", ctypes.c_uint32, 1),
        ("reserved13", ctypes.c_uint32, 1),
        ("utmi_phy_data_width", ctypes.c_uint32, 2),
        ("dev_ctrl_ep_num", ctypes.c_uint32, 4),
        ("iddg_filter_enabled", ctypes.c_uint32, 1),
        ("vbus_valid_filter_enabled", ctypes.c_uint32, 1),
        ("a_valid_filter_enabled", ctypes.c_uint32, 1),
        ("b_valid_filter_enabled", ctypes.c_uint32, 1),
        ("dedicated_fifos", ctypes.c_uint32, 1),
        ("num_dev_in_eps", ctypes.c_uint32, 4),
        ("dma_desc_enable", ctypes.c_uint32, 1),
        ("dma_dynamic", ctypes.c_uint32, 1)
    ]


@click.group()
def cli():
    pass


@cli.command()
@click.argument('mcus', nargs=-1)
@click.option('-a', '--all', is_flag=True, help='Print all bit-field values')
def info(mcus, all):
    """Print DWC2 register values for given MCU(s)"""
    if len(mcus) == 0:
        mcus = dwc2_info

    for mcu in mcus:
        for entry in dwc2_info:
            if mcu.lower() in entry.lower():
                print(f"## {entry}")
                for r_name, r_value in dwc2_info[entry].items():
                    print(f"{r_name} = 0x{r_value:08X}")
                    # Print bit-field values
                    if all and r_name.upper() in globals():
                        class_name = globals()[r_name.upper()]
                        ghwcfg = class_name.from_buffer_copy(r_value.to_bytes(4, byteorder='little'))
                        for field_name, field_type, _ in class_name._fields_:
                            print(f"  {field_name} = {getattr(ghwcfg, field_name)}")


@cli.command()
def render_md():
    """Render dwc2_info to Markdown table"""
    # Create an empty list to hold the dictionaries
    dwc2_info_list = []

    # Iterate over the dwc2_info dictionary and extract fields
    for device, reg_values in dwc2_info.items():
        entry_dict = {"Device": device}
        for r_name, r_value in reg_values.items():
            entry_dict[r_name] = f"0x{r_value:08X}"

            if r_name == 'gsnpsid':
                # Get dwc2 specs version
                major = ((r_value >> 8) >> 4) & 0x0F
                minor = (r_value >> 4) & 0xFF
                patch = chr((r_value & 0x0F) + ord('a') - 0xA)
                entry_dict[f' - specs version'] = f"{major:X}.{minor:02X}{patch}"
            elif r_name.upper() in globals():
                # Get bit-field values which exist as ctypes structures
                class_name = globals()[r_name.upper()]
                ghwcfg = class_name.from_buffer_copy(r_value.to_bytes(4, byteorder='little'))
                for field_name, field_type, _ in class_name._fields_:
                    entry_dict[f' - {field_name}'] = getattr(ghwcfg, field_name)

        dwc2_info_list.append(entry_dict)

    # Create a Pandas DataFrame from the list of dictionaries
    df = pd.DataFrame(dwc2_info_list).set_index('Device')

    # 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())
        md_file.write('\n')


if __name__ == '__main__':
    cli()