Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature/starfive regmaps #19

Open
wants to merge 38 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
d2cfca8
generate_svd: be more general with DTS fields
rmsyn Aug 24, 2023
a90e437
README: include DTS flattening instructions
rmsyn Sep 10, 2023
d615f3d
regmaps: add StarFive JH7110 PWM regmap
rmsyn Sep 11, 2023
3324ea9
logging: add logging messages
rmsyn Sep 13, 2023
03af5fc
scripts: add StarFive JH7110 SYSCRG definitions
rmsyn Sep 15, 2023
5d03cc7
scripts: add StarFive JH7110 STGCRG definitions
rmsyn Sep 19, 2023
ae530c1
scripts: add StarFive JH7110 TRNG definitions
rmsyn Sep 20, 2023
8e4bbdd
scripts: add StarFive JH7110 AONCRG definitions
rmsyn Sep 21, 2023
7f1b156
scripts: add StarFive JH7110 SYS SYSCON definitions
rmsyn Sep 22, 2023
d16bd7c
scripts: add StarFive JH7110 STG SYSCON definitions
rmsyn Sep 24, 2023
da17d81
scripts: add StarFive JH7110 AON SYSCON definitions
rmsyn Sep 27, 2023
28fa133
scripts: add StarFive JH7110 SYS IOMUX CFG definitions
rmsyn Sep 27, 2023
c132d3b
scripts: add StarFive JH7110 AON IOMUX CFG definitions
rmsyn Sep 28, 2023
4682d55
scripts: add StarFive JH7110 PMU definitions
rmsyn Oct 2, 2023
82fea28
scripts: add Synopsys Designware I2C definitions
rmsyn Oct 7, 2023
89fcbb8
scripts: add ARM PL022 SPI definitions
rmsyn Oct 8, 2023
1bd948f
fixup: scripts: add default `resetValue`
rmsyn Oct 20, 2023
9d4ec48
fixup: simplify peripheral naming
rmsyn Oct 21, 2023
4e2d880
fixup: sys_pinctrl: improve SYS GPIO register naming
rmsyn Oct 22, 2023
2048488
scripts: add Cadence QSPI-NOR registers
rmsyn Oct 25, 2023
ccd79e4
scripts: add DW_apb_uart register definitions
rmsyn Nov 11, 2023
51a9ad0
fixup: regmaps: use `generate_register` for stg_syscon
rmsyn Dec 3, 2023
f357712
fixup: scripts: make PLIC registers resettable
rmsyn Dec 5, 2023
d6f0413
fixup: rename `sys_syscon` registers
rmsyn Dec 8, 2023
846364c
fixup: aon_syscon: rename registers using generate_register
rmsyn Dec 9, 2023
e01c0cb
fixup: trng: use `generate_register` help function
rmsyn Dec 9, 2023
65216a6
fixup: starfive_common: use `generate_register`
rmsyn Dec 9, 2023
abd71f4
fixup: aon_iomux: simplify names, increase code re-use
rmsyn Dec 10, 2023
1f9c2d1
feature: scripts: add `generate_interrupt` function
rmsyn Dec 10, 2023
8627c01
fixup: sys_pinctrl: simplify names, fix offsets
rmsyn Dec 10, 2023
d9f6516
fixup: sys_syscon: simplify naming
rmsyn Dec 17, 2023
8cafe9e
fixup: syscrg: more naming simplification
rmsyn Dec 17, 2023
b59efd7
fixup: clint: add fields for reset
rmsyn Dec 18, 2023
9bbf046
fixup: clint: add register fields
rmsyn Dec 18, 2023
a2ecfd3
fixup: stg_syscon: more naming changes
rmsyn Dec 19, 2023
97f8114
fixup: reset: naming changes for reset fields
rmsyn Dec 19, 2023
954ea4e
fixup/sys_pinctrl: change `gpo_dout` naming to match `gpo_doen`
rmsyn Jan 3, 2024
7e79375
feature: scripts: add JH7110 DMC peripherals
rmsyn Jan 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,22 @@
# cmsis-svd-generator
Generates CMSIS-SVD xml files from DTS info and Register templates in the regmaps directory.

# Generating a compatible DTS file

Many DTS files are multi-level, and have both C and DSTI includes.

To flatten the DTS file, one can run the C preprocessor and device tree compiler:

```bash
# run CPP to handle any C-style includes

cpp -nostdinc -I include -I arch -undef -x assembler-with-cpp /path/to/input.dts > processed.dts

# run DTC to handle any DTSI includes

dtc -I dts -O dts -o output.dts processed.dts

# finally, run generate-svd.py

./generate-svd.py -o output.svd -d output.dts
```
191 changes: 184 additions & 7 deletions generate_svd.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,31 @@
"""

import argparse
import logging
import os
import sys
import inspect
import pydevicetree
from scripts.arm_pl022 import generate_registers_arm_pl022
from scripts.cdns_qspi_nor import generate_registers_cdns_qspi
from scripts.riscv_clint0_control import generate_registers_riscv_clint0
from scripts.sifive_clic0_control import generate_registers_sifive_clic0
from scripts.riscv_plic0_control import generate_registers_riscv_plic0
from scripts.snps_designware_i2c import generate_registers_snps_designware_i2c
from scripts.snps_dw_apb_uart import generate_registers_snps_dw_apb_uart
from scripts.starfive_common import generate_interrupt
from scripts.starfive_jh7110_dmc_ctrl import generate_registers_starfive_jh7110_dmc_ctrl
from scripts.starfive_jh7110_dmc_phy import generate_registers_starfive_jh7110_dmc_phy
from scripts.starfive_jh7110_pmu import generate_registers_starfive_jh7110_pmu
from scripts.starfive_jh7110_stgcrg import generate_registers_starfive_jh7110_stgcrg
from scripts.starfive_jh7110_syscrg import generate_registers_starfive_jh7110_syscrg
from scripts.starfive_jh7110_aoncrg import generate_registers_starfive_jh7110_aoncrg
from scripts.starfive_jh7110_aon_pinctrl import generate_registers_starfive_jh7110_aon_iomux_cfg
from scripts.starfive_jh7110_aon_syscon import generate_registers_starfive_jh7110_aon_syscon
from scripts.starfive_jh7110_stg_syscon import generate_registers_starfive_jh7110_stg_syscon
from scripts.starfive_jh7110_sys_pinctrl import generate_registers_starfive_jh7110_sys_iomux_cfg
from scripts.starfive_jh7110_sys_syscon import generate_registers_starfive_jh7110_sys_syscon
from scripts.starfive_jh7110_trng import generate_registers_starfive_jh7110_trng

def parse_arguments(argv):
"""Parse the arguments into a dictionary with argparse"""
Expand All @@ -24,6 +42,10 @@ def parse_arguments(argv):
arg_parser.add_argument("-o", "--output", required=True,
type=argparse.FileType('w'),
help="The path of the CMSIS SVD file to output")
arg_parser.add_argument("-l", "--log", required=False,
default="WARN",
type=str,
help="The path of the CMSIS SVD file to output")

return arg_parser.parse_args(argv)

Expand Down Expand Up @@ -63,58 +85,204 @@ def generate_peripherals(dts):
idx[compatible] = 0

for peripheral in soc.child_nodes():
if peripheral.get_field("compatible") is not None and \
peripheral.get_field("reg-names") is not None:
if peripheral.get_field("compatible") is not None:
reg = peripheral.get_fields("reg")

if reg is None:
reg_cells = 0
else:
reg_cells = len(peripheral.get_fields("reg").values)

exp_reg_cells = peripheral.address_cells() + peripheral.size_cells()

if peripheral.get_fields("reg") is not None and reg_cells % exp_reg_cells != 0:
logging.debug("Unexpected number of reg cells {}, expected {}".format(reg_cells, exp_reg_cells))
continue

compatibles = peripheral.get_fields("compatible")
reg_names = peripheral.get_fields("reg-names")

reg_names = {}
if peripheral.get_field("reg-names") is not None:
reg_names = peripheral.get_fields("reg-names")
else:
reg_names = {""}

for comp in compatibles:
for reg in reg_names:
if len(reg) == 0:
rn = ""
else:
rn = "_" + reg

regmap_root = os.path.abspath(os.path.dirname(sys.argv[0]))
regmap_name = get_name_as_id(comp) + "_" + reg + ".svd"
regmap_name = get_name_as_id(comp) + rn + ".svd"
regmap_path = os.path.join(regmap_root, "regmaps", regmap_name)
script_name = get_name_as_id(comp) + "_" + reg + ".py"
script_name = get_name_as_id(comp) + rn + ".py"
script_path = os.path.join(regmap_root, "scripts", script_name)

logging.debug("Compatible: {}".format(comp))
logging.debug(" Regmap path: {}".format(regmap_path))
logging.debug(" Script path: {}".format(script_path))

if "clint" in comp and not os.path.exists(script_path):
regmap_path = ""
script_path = os.path.join(regmap_root, "scripts", "riscv_clint0_control.py")
elif "plic" in comp and not os.path.exists(script_path):
regmap_path = ""
script_path = os.path.join(regmap_root, "scripts", "riscv_plic0_control.py")
elif "clic" in comp and not os.path.exists(script_path):
regmap_path = ""
script_path = os.path.join(regmap_root, "scripts", "sifive_clic0_control.py")

if os.path.exists(regmap_path):
ext = str(idx[comp])
logging.info("Regmap path: {}".format(regmap_path))
txt += generate_peripheral(dts, peripheral, comp, ext, reg, regmap_path)
idx[comp] += 1
elif os.path.exists(script_path):
ext = str(idx[comp])
logging.info("Script path: {}".format(script_path))
txt += generate_peripheral(dts, peripheral, comp, ext, reg, script_path)
idx[comp] += 1
else:
ext = str(idx[comp])
txt += generate_peripheral(dts, peripheral, comp, ext, reg, "")
idx[comp] += 1

return txt

#pylint: disable=too-many-arguments
def generate_peripheral(dts, peripheral, comp, ext, reg, regmap_path):
"""Generate xml string for peripheral"""
reg_dict = peripheral.get_reg()

if reg_dict is None:
logging.debug("No peripheral found for {}".format(peripheral))
return ""

reg_pair = reg_dict.get_by_name(reg)

addr_cells = peripheral.address_cells()
size_cells = peripheral.size_cells()
group_size = addr_cells + size_cells

if reg_pair is None and len(reg_dict.values) == group_size:
# no reg-names field was present, so parse according to the spec
reg_pair = [reg_dict.values[addr_cells - 1], reg_dict.values[group_size - 1]]
elif reg_pair is None:
logging.debug("Malformed DTS entry: {}".format(peripheral))
# malformed DTS, give up
return ""

reg_desc = comp + """,""" + reg
print("Emitting registers for '" + peripheral.name + "' soc peripheral node")
logging.info("Emitting registers for '" + peripheral.name + "' soc peripheral node")

if regmap_path.endswith("arm_pl022.py"):
name = "spi{}".format(ext)
elif regmap_path.endswith("cdns_qspi_nor.py"):
name = "qspi".format(ext)
elif regmap_path.endswith("riscv_clint0_control.py"):
name = "clint"
elif regmap_path.endswith("riscv_plic0_control.py"):
name = "plic"
elif regmap_path.endswith("sifive_clic0_control.py"):
name = "clic"
elif regmap_path.endswith("snps_dw_apb_uart.py"):
name = "uart{}".format(ext)
elif regmap_path.endswith("snps_designware_i2c.py"):
name = "i2c{}".format(ext)
elif regmap_path.endswith("starfive_jh7110_pmu.py"):
name = "pmu"
elif regmap_path.endswith("starfive_jh7110_syscrg.py"):
name = "syscrg"
elif regmap_path.endswith("starfive_jh7110_stgcrg.py"):
name = "stgcrg"
elif regmap_path.endswith("starfive_jh7110_aoncrg.py"):
name = "aoncrg"
elif regmap_path.endswith("starfive_jh7110_aon_pinctrl.py"):
name = "aon_pinctrl"
elif regmap_path.endswith("starfive_jh7110_aon_syscon.py"):
name = "aon_syscon"
elif regmap_path.endswith("starfive_jh7110_stg_syscon.py"):
name = "stg_syscon"
elif regmap_path.endswith("starfive_jh7110_sys_pinctrl.py"):
name = "sys_pinctrl"
elif regmap_path.endswith("starfive_jh7110_sys_syscon.py"):
name = "sys_syscon"
elif regmap_path.endswith("starfive_jh7110_pwm.py") or regmap_path.endswith("starfive_jh7110_pwm.svd"):
name = "pwm"
elif regmap_path.endswith("starfive_jh7110_trng.py"):
name = "trng"
elif regmap_path.endswith("starfive_jh7110_dmc_ctrl.py"):
name = "dmc_ctrl"
elif regmap_path.endswith("starfive_jh7110_dmc_phy.py"):
name = "dmc_phy"
else:
name = "{}_{}".format(get_name_as_id(comp), ext)

return """\
<peripheral>
<name>""" + get_name_as_id(comp) + """_""" + ext + """</name>
<name>""" + name + """</name>
<description>From """ + reg_desc + """ peripheral generator</description>
<baseAddress>""" + "0x{:X}".format(reg_pair[0]) + """</baseAddress>
<addressBlock>
<offset>0</offset>
<size>""" + "0x{:X}".format(reg_pair[1]) + """</size>
<usage>registers</usage>
</addressBlock>
""" + generate_interrupt("jh7110", name) + """\
""" + generate_registers(dts, peripheral, regmap_path) + """\
</peripheral>
"""

def generate_registers(dts, peripheral, regmap_path):
if regmap_path == "":
logging.debug("No regmap file found for {}".format(peripheral))
logging.debug("\tRegmap path: {}".format(regmap_path))
# FIXME: instead of just giving up here, attempt to parse register data from the DTS
return ""

"""Generate xml string for registers from regmap file or generator code"""
if regmap_path.endswith("arm_pl022.py"):
return generate_registers_arm_pl022(dts, peripheral)
if regmap_path.endswith("cdns_qspi_nor.py"):
return generate_registers_cdns_qspi(dts, peripheral)
if regmap_path.endswith("riscv_clint0_control.py"):
return generate_registers_riscv_clint0(dts)
if regmap_path.endswith("sifive_clic0_control.py"):
return generate_registers_sifive_clic0(dts, peripheral)
if regmap_path.endswith("riscv_plic0_control.py"):
return generate_registers_riscv_plic0(dts, peripheral)
if regmap_path.endswith("snps_designware_i2c.py"):
return generate_registers_snps_designware_i2c(dts, peripheral)
if regmap_path.endswith("snps_dw_apb_uart.py"):
return generate_registers_snps_dw_apb_uart(dts, peripheral)
if regmap_path.endswith("starfive_jh7110_dmc_ctrl.py"):
return generate_registers_starfive_jh7110_dmc_ctrl(dts, peripheral)
if regmap_path.endswith("starfive_jh7110_dmc_phy.py"):
return generate_registers_starfive_jh7110_dmc_phy(dts, peripheral)
if regmap_path.endswith("starfive_jh7110_pmu.py"):
return generate_registers_starfive_jh7110_pmu(dts, peripheral)
if regmap_path.endswith("starfive_jh7110_syscrg.py"):
return generate_registers_starfive_jh7110_syscrg(dts, peripheral)
if regmap_path.endswith("starfive_jh7110_stgcrg.py"):
return generate_registers_starfive_jh7110_stgcrg(dts, peripheral)
if regmap_path.endswith("starfive_jh7110_aoncrg.py"):
return generate_registers_starfive_jh7110_aoncrg(dts, peripheral)
if regmap_path.endswith("starfive_jh7110_aon_pinctrl.py"):
return generate_registers_starfive_jh7110_aon_iomux_cfg(dts, peripheral)
if regmap_path.endswith("starfive_jh7110_aon_syscon.py"):
return generate_registers_starfive_jh7110_aon_syscon(dts, peripheral)
if regmap_path.endswith("starfive_jh7110_stg_syscon.py"):
return generate_registers_starfive_jh7110_stg_syscon(dts, peripheral)
if regmap_path.endswith("starfive_jh7110_sys_pinctrl.py"):
return generate_registers_starfive_jh7110_sys_iomux_cfg(dts, peripheral)
if regmap_path.endswith("starfive_jh7110_sys_syscon.py"):
return generate_registers_starfive_jh7110_sys_syscon(dts, peripheral)
if regmap_path.endswith("starfive_jh7110_trng.py"):
return generate_registers_starfive_jh7110_trng(dts, peripheral)

logging.debug("Reading registers from regmap file: {}".format(regmap_path))

regmap_file = open(regmap_path, "r")
txt = ""
Expand All @@ -128,7 +296,16 @@ def get_name_as_id(name):

def main(argv):
"""Parse arguments, extract data, and render clean cmsis svd xml to file"""


parsed_args = parse_arguments(argv)

# set the logging level from the command line
numeric_level = getattr(logging, parsed_args.log.upper(), None)
if not isinstance(numeric_level, int):
raise ValueError('Invalid log level: %s' % parsed_args.log)
logging.basicConfig(level=numeric_level)

dts = pydevicetree.Devicetree.parseFile(parsed_args.dts, followIncludes=True)
text = generate_device(dts)
output = inspect.cleandoc(text)
Expand Down
102 changes: 102 additions & 0 deletions regmaps/starfive_jh7110_pwm.svd
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<registers>
<register>
<name>cntr</name>
<description>PTC counter register</description>
<addressOffset>0x0</addressOffset>
<fields>
<field>
<name>cntr</name>
<description>PWM PTC counter</description>
<bitRange>[31:0]</bitRange>
<access>read-write</access>
</field>
</fields>
</register>
<register>
<name>hrc</name>
<description>PTC duty-cycle register</description>
<addressOffset>0x4</addressOffset>
<fields>
<field>
<name>hrc</name>
<description>PWM PTC duty-cycle value</description>
<bitRange>[31:0]</bitRange>
<access>read-write</access>
</field>
</fields>
</register>
<register>
<name>lrc</name>
<description>PTC period register</description>
<addressOffset>0x8</addressOffset>
<fields>
<field>
<name>lrc</name>
<description>PWM PTC period value</description>
<bitRange>[31:0]</bitRange>
<access>read-write</access>
</field>
</fields>
</register>
<register>
<name>ctrl</name>
<description>PTC control register</description>
<addressOffset>0xc</addressOffset>
<fields>
<field>
<name>en</name>
<description>PWM PTC enable</description>
<bitRange>[0:0]</bitRange>
<access>read-write</access>
</field>
<field>
<name>eclk</name>
<description>PWM PTC enable clock</description>
<bitRange>[1:1]</bitRange>
<access>read-write</access>
</field>
<field>
<name>nec</name>
<description>PWM PTC nec</description>
<bitRange>[2:2]</bitRange>
<access>read-write</access>
</field>
<field>
<name>oe</name>
<description>PWM PTC oe</description>
<bitRange>[3:3]</bitRange>
<access>read-write</access>
</field>
<field>
<name>single</name>
<description>PWM PTC single</description>
<bitRange>[4:4]</bitRange>
<access>read-write</access>
</field>
<field>
<name>inte</name>
<description>PWM PTC interrupt enable</description>
<bitRange>[5:5]</bitRange>
<access>read-write</access>
</field>
<field>
<name>int</name>
<description>PWM PTC interrupt</description>
<bitRange>[6:6]</bitRange>
<access>read-write</access>
</field>
<field>
<name>cntrrst</name>
<description>PWM PTC counter reset</description>
<bitRange>[7:7]</bitRange>
<access>read-write</access>
</field>
<field>
<name>capte</name>
<description>PWM PTC capte</description>
<bitRange>[8:8]</bitRange>
<access>read-write</access>
</field>
</fields>
</register>
</registers>
Loading