diff --git a/cmake/vif.cmake b/cmake/vif.cmake index 611cabe349a..f26351fc97b 100644 --- a/cmake/vif.cmake +++ b/cmake/vif.cmake @@ -4,14 +4,49 @@ # Generates USB-C VIF policies in XML format from device tree. set(gen_vif_script ${ZEPHYR_BASE}/scripts/generate_usb_vif/generate_vif.py) set(dts_compatible usb-c-connector) -set(vif_xml ${PROJECT_BINARY_DIR}/vif.xml) +set(vif_xml vif.xml) +set(board_vif_xml ${BOARD}_${vif_xml}) +set(vif_out ${PROJECT_BINARY_DIR}/${vif_xml}) + set(cmd_gen_vif ${PYTHON_EXECUTABLE} ${gen_vif_script} --edt-pickle ${EDT_PICKLE} --compatible ${dts_compatible} - --vif-out ${vif_xml} - --board ${BOARD} + --vif-out ${vif_out} ) +if (CONFIG_GENVIF_INPUT_VIF_XML_PATH) + if (IS_ABSOLUTE ${CONFIG_GENVIF_INPUT_VIF_XML_PATH}) + if (EXISTS ${CONFIG_GENVIF_INPUT_VIF_XML_PATH}) + set(vif_source_xml ${CONFIG_GENVIF_INPUT_VIF_XML_PATH}) + endif () + elseif (EXISTS ${APPLICATION_CONFIG_DIR}/${CONFIG_GENVIF_INPUT_VIF_XML_PATH}) + set(vif_source_xml ${APPLICATION_CONFIG_DIR}/${CONFIG_GENVIF_INPUT_VIF_XML_PATH}) + endif () +else () + if (EXISTS ${APPLICATION_CONFIG_DIR}/boards/${board_vif_xml}) + set(vif_source_xml ${APPLICATION_CONFIG_DIR}/boards/${board_vif_xml}) + elseif (EXISTS ${APPLICATION_CONFIG_DIR}/${vif_xml}) + set(vif_source_xml ${APPLICATION_CONFIG_DIR}/${vif_xml}) + elseif (EXISTS ${BOARD_DIR}/${vif_xml}) + set(vif_source_xml ${BOARD_DIR}/${vif_xml}) + endif () +endif () + +if (DEFINED vif_source_xml) + list(APPEND cmd_gen_vif --vif-source-xml ${vif_source_xml}) +else () + if (CONFIG_GENVIF_INPUT_VIF_XML_PATH) + message(FATAL_ERROR "Incorrect VIF source XML file path. To fix specify" + " correct XML file path at 'CONFIG_GENVIF_INPUT_VIF_XML_PATH'.") + else () + message(FATAL_ERROR "No VIF source XML file found. To fix, create" + " '${board_vif_xml}' in 'boards' directory of application" + " directory, or create '${vif_xml}' file in application" + " directory or board directory, or supply a custom XML VIF path" + " using 'CONFIG_GENVIF_INPUT_VIF_XML_PATH'.") + endif () +endif () + add_custom_command( OUTPUT ${vif_xml} DEPENDS ${EDT_PICKLE} diff --git a/dts/bindings/usb-c/usb-c-connector.yaml b/dts/bindings/usb-c/usb-c-connector.yaml index d5a9499e991..1984486b7e6 100644 --- a/dts/bindings/usb-c/usb-c-connector.yaml +++ b/dts/bindings/usb-c/usb-c-connector.yaml @@ -9,6 +9,34 @@ description: | This is based on Linux, documentation: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/connector/usb-connector.yaml?h=v5.19&id=3d7cb6b04c3f3115719235cc6866b10326de34cd + Example: + + USB-C connector attached to a STM32 UCPD typec port controller, which has + power delivery support and enables SINK. + + vbus1: vbus { + compatible = "zephyr,usb-c-vbus-adc"; + io-channels = <&adc2 8>; + output-ohms = <49900>; + full-ohms = <(330000 + 49900)>; + }; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port1: usb-c-port@1 { + compatible = "usb-c-connector"; + reg = <1>; + tcpc = <&ucpd1>; + vbus = <&vbus1>; + power-role = "SINK"; + sink-pdos = ; + op-sink-microwatt = <10000000>; + }; + }; + + compatible: "usb-c-connector" include: base.yaml @@ -136,32 +164,3 @@ properties: description: | Minimum power, in microwatts, needed by the sink. A Capability Mismatch is sent to the Source if the power can't be met. - - # EXAMPLE: - # - # USB-C connector attached to a STM32 UCPD typec port controller, which has - # power delivery support and enables SINK. - # - # #include - # - # vbus1: vbus { - # compatible = "zephyr,usb-c-vbus-adc"; - # io-channels = <&adc2 8>; - # output-ohms = <49900>; - # full-ohms = <(330000 + 49900)>; - # }; - # - # ports { - # #address-cells = <1>; - # #size-cells = <0>; - # port1: usb-c-port@1 { - # compatible = "usb-c-connector"; - # reg = <1>; - # tcpc = <&ucpd1>; - # vbus = <&vbus1>; - # power-role = "SINK"; - # sink-pdos = ; - # op-sink-microwatt = <10000000>; - # }; - # }; diff --git a/samples/subsys/usb_c/sink/vif.xml b/samples/subsys/usb_c/sink/vif.xml new file mode 100644 index 00000000000..d064e4efc49 --- /dev/null +++ b/samples/subsys/usb_c/sink/vif.xml @@ -0,0 +1,9 @@ + + + Zephyr + Sink + 1 + 0 + Port Product + End Product + diff --git a/scripts/generate_usb_vif/constants.py b/scripts/generate_usb_vif/constants.py deleted file mode 100644 index 1c9b4659cc3..00000000000 --- a/scripts/generate_usb_vif/constants.py +++ /dev/null @@ -1,97 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright (c) 2022 The Chromium OS Authors -# SPDX-License-Identifier: Apache-2.0 - -"""This file contains all constants defined to be used by all other scripts -in this folder i.e, generate_usb_vif""" - -XML_ENCODING = "utf-8" -XML_ELEMENT_NAME_PREFIX = "vif" -XML_ROOT_ELEMENT_NAME = "VIF" -XML_NAMESPACE_ATTRIBUTES = { - "xmlns:opt": "http://compliance.usb.org/cv/VendorInfoFile/Schemas/Current/VendorInfoFileOptionalContent.xsd", - "xmlns:xsi": "http://www.w3.org/2001/XMLSchema", - "xmlns:vif": "http://compliance.usb.org/cv/VendorInfoFile/Schemas/Current/VendorInfoFile.xsd", -} - -NAME = "name" -VALUE = "value" -TEXT = "text" -ATTRIBUTES = "attributes" -CHILD = "child" -COMPONENT = "Component" -TRUE = "true" -FALSE = "false" - -SINK_PDOS = "sink-pdos" -SINK_PDO = "SnkPDO" -SINK_PDO_SUPPLY_TYPE = "Snk_PDO_Supply_Type" -SINK_PDO_VOLTAGE = "Snk_PDO_Voltage" -SINK_PDO_OP_CURRENT = "Snk_PDO_Op_Current" -SINK_PDO_MIN_VOLTAGE = "Snk_PDO_Min_Voltage" -SINK_PDO_MAX_VOLTAGE = "Snk_PDO_Max_Voltage" -SINK_PDO_OP_POWER = "Snk_PDO_Op_Power" -PD_POWER_AS_SINK = "PD_Power_As_Sink" -NUM_SINK_PDOS = "Num_Snk_PDOs" -MODEL_PART_NUMBER = "Model_Part_Number" -EPR_SUPPORTED_AS_SINK = "EPR_Supported_As_Snk" -NO_USB_SUSPEND_MAY_BE_SET = "No_USB_Suspend_May_Be_Set" -HIGHER_CAPABILITY_SET = "Higher_Capability_Set" -FR_SWAP_REQD_TYPE_C_CURRENT_AS_INITIAL_SOURCE = "FR_Swap_Reqd_Type_C_Current_As_Initial_Source" - -VIF_SPEC_ELEMENTS = { - "VIF_Specification": { - TEXT: "3.19", - }, - "VIF_App": { - CHILD: { - "Vendor": { - TEXT: "USB-IF", - }, - "Name": { - TEXT: "VIF Editor", - }, - "Version": { - TEXT: "3.2.4.0", - } - } - }, - "VIF_Product_Type": { - TEXT: "Port Product", - ATTRIBUTES: { - "value": "0", - }, - }, - "Certification_Type": { - TEXT: "End Product", - ATTRIBUTES: { - "value": "0", - }, - } -} - -VIF_ELEMENTS = ["VIF_Specification", "VIF_App", "Vendor", "Name", "Version", - "Vendor_Name", "VIF_Product_Type", "Certification_Type", - MODEL_PART_NUMBER, COMPONENT, SINK_PDOS, SINK_PDO, - SINK_PDO_SUPPLY_TYPE, SINK_PDO_VOLTAGE, SINK_PDO_OP_CURRENT, - SINK_PDO_MIN_VOLTAGE, SINK_PDO_MAX_VOLTAGE, SINK_PDO_OP_POWER, - PD_POWER_AS_SINK, PD_POWER_AS_SINK, NUM_SINK_PDOS, - EPR_SUPPORTED_AS_SINK, NO_USB_SUSPEND_MAY_BE_SET, - HIGHER_CAPABILITY_SET, ] - -DT_VIF_ELEMENTS = { - SINK_PDOS: "SnkPdoList", -} - -PDO_TYPE_FIXED = 0 -PDO_TYPE_BATTERY = 1 -PDO_TYPE_VARIABLE = 2 -PDO_TYPE_AUGUMENTED = 3 - -PDO_TYPES = { - PDO_TYPE_FIXED: "Fixed", - PDO_TYPE_BATTERY: "Battery", - PDO_TYPE_VARIABLE: "Variable", - PDO_TYPE_AUGUMENTED: "Augmented", -} diff --git a/scripts/generate_usb_vif/constants/dt_constants.py b/scripts/generate_usb_vif/constants/dt_constants.py new file mode 100644 index 00000000000..9ddf4879ac4 --- /dev/null +++ b/scripts/generate_usb_vif/constants/dt_constants.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2022 The Chromium OS Authors +# SPDX-License-Identifier: Apache-2.0 + +"""This file contains device tree constants defined to be used by generate_vif.py""" + +SINK_PDOS = "sink-pdos" +PD_DISABLE = "pd-disable" +POWER_ROLE = "power-role" + +DT_VIF_ELEMENTS = { + SINK_PDOS: "SnkPdoList", +} diff --git a/scripts/generate_usb_vif/constants/other_constants.py b/scripts/generate_usb_vif/constants/other_constants.py new file mode 100644 index 00000000000..5c8eb3f9bea --- /dev/null +++ b/scripts/generate_usb_vif/constants/other_constants.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2022 The Chromium OS Authors +# SPDX-License-Identifier: Apache-2.0 + +"""This file contains generic constants defined to be used by generate_vif.py""" + +NAME = "name" +VALUE = "value" +TEXT = "text" +ATTRIBUTES = "attributes" +CHILD = "child" +TRUE = "true" +FALSE = "false" + +PD_PORT_TYPE_VALUES = { + "sink": ("0", "Consumer Only"), + "source": ("3", "Provider Only"), + "dual": ("4", "DRP"), +} + +TYPE_C_STATE_MACHINE_VALUES = { + "sink": ("1", "SNK"), + "source": ("0", "SRC"), + "dual": ("2", "DRP"), +} + +FR_SWAP_REQD_TYPE_C_CURRENT_AS_INITIAL_SOURCE_VALUES = { + 0: "FR_Swap not supported", + 1: "Default USB Power", + 2: "1.5A @ 5V", + 3: "3A @ 5V", +} diff --git a/scripts/generate_usb_vif/constants/pdo_constants.py b/scripts/generate_usb_vif/constants/pdo_constants.py new file mode 100644 index 00000000000..e35db765bd7 --- /dev/null +++ b/scripts/generate_usb_vif/constants/pdo_constants.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2022 The Chromium OS Authors +# SPDX-License-Identifier: Apache-2.0 + +"""This file contains PDO constants defined to be used by generate_vif.py""" + +# PDO +PDO_TYPE_FIXED = 0 +PDO_TYPE_BATTERY = 1 +PDO_TYPE_VARIABLE = 2 +PDO_TYPE_AUGUMENTED = 3 + +PDO_TYPES = { + PDO_TYPE_FIXED: "Fixed", + PDO_TYPE_BATTERY: "Battery", + PDO_TYPE_VARIABLE: "Variable", + PDO_TYPE_AUGUMENTED: "Augmented", +} diff --git a/scripts/generate_usb_vif/constants/vif_element_constants.py b/scripts/generate_usb_vif/constants/vif_element_constants.py new file mode 100644 index 00000000000..055deeb41f6 --- /dev/null +++ b/scripts/generate_usb_vif/constants/vif_element_constants.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2022 The Chromium OS Authors +# SPDX-License-Identifier: Apache-2.0 + +"""This file contains VIF element constants defined to be used by generate_vif.py""" + +VENDOR_NAME = "Vendor_Name" +MODEL_PART_NUMBER = "Model_Part_Number" +PRODUCT_REVISION = "Product_Revision" +TID = "TID" +VIF_PRODUCT_TYPE = "VIF_Product_Type" +CERTIFICATION_TYPE = "Certification_Type" +COMPONENT = "Component" + +USB_PD_SUPPORT = "USB_PD_Support" +PD_PORT_TYPE = "PD_Port_Type" +TYPE_C_STATE_MACHINE = "Type_C_State_Machine" +SINK_PDO = "SnkPDO" +SINK_PDO_SUPPLY_TYPE = "Snk_PDO_Supply_Type" +SINK_PDO_VOLTAGE = "Snk_PDO_Voltage" +SINK_PDO_OP_CURRENT = "Snk_PDO_Op_Current" +SINK_PDO_OP_POWER = "Snk_PDO_Op_Power" +SINK_PDO_MIN_VOLTAGE = "Snk_PDO_Min_Voltage" +SINK_PDO_MAX_VOLTAGE = "Snk_PDO_Max_Voltage" +PD_POWER_AS_SINK = "PD_Power_As_Sink" +HIGHER_CAPABILITY_SET = "Higher_Capability_Set" +FR_SWAP_REQD_TYPE_C_CURRENT_AS_INITIAL_SOURCE = "FR_Swap_Reqd_Type_C_Current_As_Initial_Source" +NUM_SNK_PDOS = "Num_Snk_PDOs" diff --git a/scripts/generate_usb_vif/constants/xml_constants.py b/scripts/generate_usb_vif/constants/xml_constants.py new file mode 100644 index 00000000000..2aeeefe9cd5 --- /dev/null +++ b/scripts/generate_usb_vif/constants/xml_constants.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2022 The Chromium OS Authors +# SPDX-License-Identifier: Apache-2.0 + +"""This file contains XML constants defined to be used by generate_vif.py""" + +from constants import other_constants +from constants import vif_element_constants + +XML_ENCODING = "utf-8" +XML_ELEMENT_NAME_PREFIX = "vif" +XML_ROOT_ELEMENT_NAME = "VIF" +XML_VIF_NAMESPACE = "http://usb.org/VendorInfoFile.xsd" +XML_NAMESPACE_ATTRIBUTES = { + "xmlns:vif": XML_VIF_NAMESPACE, +} + +VIF_SPEC_ELEMENTS = { + "VIF_Specification": { + other_constants.TEXT: "3.19", + }, + "VIF_App": { + other_constants.CHILD: { + "Description": { + other_constants.TEXT: "This VIF XML file is generated by the Zephyr GenVIF script", + } + } + }, +} + +VIF_SPEC_ELEMENTS_FROM_SOURCE_XML = {vif_element_constants.VENDOR_NAME, + vif_element_constants.MODEL_PART_NUMBER, + vif_element_constants.PRODUCT_REVISION, + vif_element_constants.TID, + vif_element_constants.VIF_PRODUCT_TYPE, + vif_element_constants.CERTIFICATION_TYPE, } diff --git a/scripts/generate_usb_vif/generate_vif.py b/scripts/generate_usb_vif/generate_vif.py index 2b181d380ee..182c6949ebc 100644 --- a/scripts/generate_usb_vif/generate_vif.py +++ b/scripts/generate_usb_vif/generate_vif.py @@ -13,44 +13,32 @@ import pickle import sys import xml.etree.ElementTree as ET -import constants +from constants import dt_constants +from constants import other_constants +from constants import pdo_constants +from constants import vif_element_constants +from constants import xml_constants SCRIPTS_DIR = os.path.join(os.path.dirname(__file__), "..") sys.path.insert(0, os.path.join(SCRIPTS_DIR, 'dts', 'python-devicetree', 'src')) -def main(): - global edtlib - args = parse_args() - with open(args.edt_pickle, 'rb') as f: - edt = pickle.load(f) - edtlib = inspect.getmodule(edt) - - xml_root = get_root() - add_elements_to_xml(xml_root, constants.VIF_SPEC_ELEMENTS) - add_element_to_xml(xml_root, constants.MODEL_PART_NUMBER, args.board) - for node in edt.compat2nodes[args.compatible]: - xml_ele = add_element_to_xml(xml_root, constants.COMPONENT) - parse_and_add_node_to_xml(xml_ele, node) - tree = ET.ElementTree(xml_root) - tree.write(args.vif_out, xml_declaration=True, - encoding=constants.XML_ENCODING) - - -def is_vif_element(name): - if name in constants.VIF_ELEMENTS: - return True - return False +def get_value_attribute(data): + if not isinstance(data, str): + data = str(data) + return {other_constants.VALUE: data} def get_vif_element_name(name): - return constants.XML_ELEMENT_NAME_PREFIX + ":" + constants.DT_VIF_ELEMENTS.get( + return xml_constants.XML_ELEMENT_NAME_PREFIX + ":" + dt_constants.DT_VIF_ELEMENTS.get( name, name) def get_root(): - xml_root = ET.Element(get_vif_element_name(constants.XML_ROOT_ELEMENT_NAME)) - add_attributes_to_xml_element(xml_root, constants.XML_NAMESPACE_ATTRIBUTES) + xml_root = ET.Element( + get_vif_element_name(xml_constants.XML_ROOT_ELEMENT_NAME)) + add_attributes_to_xml_element(xml_root, + xml_constants.XML_NAMESPACE_ATTRIBUTES) return xml_root @@ -60,23 +48,33 @@ def add_attributes_to_xml_element(xml_ele, attributes): def add_element_to_xml(xml_ele, name, text=None, attributes=None): - if is_vif_element(name): - new_xml_ele = ET.SubElement(xml_ele, get_vif_element_name(name)) - if text: - new_xml_ele.text = str(text) - if attributes: - add_attributes_to_xml_element(new_xml_ele, attributes) - return new_xml_ele - return xml_ele + new_xml_ele = ET.SubElement(xml_ele, get_vif_element_name(name)) + if text: + new_xml_ele.text = str(text) + if attributes: + add_attributes_to_xml_element(new_xml_ele, attributes) + return new_xml_ele def add_elements_to_xml(xml_ele, elements): for element_name in elements: - text = elements[element_name].get(constants.TEXT, None) - attributes = elements[element_name].get(constants.ATTRIBUTES, None) - new_xml_ele = add_element_to_xml(xml_ele, element_name, text, attributes) - if constants.CHILD in elements[element_name]: - add_elements_to_xml(new_xml_ele, elements[element_name][constants.CHILD]) + text = elements[element_name].get(other_constants.TEXT, None) + attributes = elements[element_name].get(other_constants.ATTRIBUTES, + None) + new_xml_ele = add_element_to_xml(xml_ele, element_name, text, + attributes) + if other_constants.CHILD in elements[element_name]: + add_elements_to_xml(new_xml_ele, + elements[element_name][other_constants.CHILD]) + + +def add_vif_spec_from_source_to_xml(xml_ele, source_xml_ele): + prefix = '{' + xml_constants.XML_VIF_NAMESPACE + '}' + for child in source_xml_ele: + element_name = child.tag[len(prefix):] + if element_name in xml_constants.VIF_SPEC_ELEMENTS_FROM_SOURCE_XML: + add_element_to_xml(xml_ele, element_name, child.text, + child.attrib) def is_simple_datatype(value): @@ -91,66 +89,54 @@ def get_pdo_type(pdo_value): def get_xml_bool_value(value): if value: - return constants.TRUE - return constants.FALSE + return other_constants.TRUE + return other_constants.FALSE -def parse_and_add_sink_pdos_to_xml(xml_ele, sink_pdos): - new_xml_ele = add_element_to_xml(xml_ele, constants.SINK_PDOS) - pdos_info = dict() - snk_max_power = 0 - for pdo_value in sink_pdos: - power_mv = parse_and_add_sink_pdo_to_xml(new_xml_ele, pdo_value, pdos_info) - if power_mv > snk_max_power: - snk_max_power = power_mv - add_element_to_xml(xml_ele, constants.NUM_SINK_PDOS, None, - {constants.VALUE: str(len(sink_pdos))}) - add_element_to_xml(xml_ele, constants.EPR_SUPPORTED_AS_SINK, - attributes={constants.VALUE: constants.FALSE}) - add_element_to_xml(xml_ele, constants.NO_USB_SUSPEND_MAY_BE_SET, - attributes={constants.VALUE: constants.TRUE}) - add_element_to_xml(xml_ele, constants.HIGHER_CAPABILITY_SET, attributes={ - constants.VALUE: get_xml_bool_value(pdos_info.get(constants.HIGHER_CAPABILITY_SET, 0))}) - add_element_to_xml(xml_ele, constants.FR_SWAP_REQD_TYPE_C_CURRENT_AS_INITIAL_SOURCE, - "FR_Swap not supported", attributes={constants.VALUE: str( - pdos_info.get(constants.FR_SWAP_REQD_TYPE_C_CURRENT_AS_INITIAL_SOURCE, 0))}) - add_element_to_xml(xml_ele, constants.PD_POWER_AS_SINK, f'{snk_max_power} mW', - {constants.VALUE: str(snk_max_power)}) - - -def parse_and_add_sink_pdo_to_xml(xml_ele, pdo_value, pdos_info): +def parse_and_add_sink_pdo_to_xml(xml_ele, pdo_value, pdo_info): power_mw = 0 - xml_ele = add_element_to_xml(xml_ele, constants.SINK_PDO) + xml_ele = add_element_to_xml(xml_ele, vif_element_constants.SINK_PDO) pdo_type = get_pdo_type(pdo_value) - if pdo_type == constants.PDO_TYPE_FIXED: + + if pdo_type == pdo_constants.PDO_TYPE_FIXED: + # As per USB PD specification Revision 3.1, Version 1.6, Table 6-16 Fixed supply PDO - Sink current = pdo_value & 0x3ff current_ma = current * 10 voltage = (pdo_value >> 10) & 0x3ff voltage_mv = voltage * 50 power_mw = (current_ma * voltage_mv) // 1000 - pdos_info[constants.HIGHER_CAPABILITY_SET] = pdo_value & (1 << 28) - pdos_info[constants.FR_SWAP_REQD_TYPE_C_CURRENT_AS_INITIAL_SOURCE] = pdo_value & (3 << 23) - add_element_to_xml(xml_ele, constants.SINK_PDO_VOLTAGE, f'{voltage_mv} mV', - {constants.VALUE: str(voltage)}) - add_element_to_xml(xml_ele, constants.SINK_PDO_OP_CURRENT, + + if pdo_value & (1 << 28): + pdo_info[vif_element_constants.HIGHER_CAPABILITY_SET] = True + pdo_info[ + vif_element_constants.FR_SWAP_REQD_TYPE_C_CURRENT_AS_INITIAL_SOURCE] = pdo_value & ( + 3 << 23) + add_element_to_xml(xml_ele, vif_element_constants.SINK_PDO_VOLTAGE, + f'{voltage_mv} mV', + get_value_attribute(voltage)) + add_element_to_xml(xml_ele, vif_element_constants.SINK_PDO_OP_CURRENT, f'{current_ma} mA', - {constants.VALUE: str(current)}) - elif pdo_type == constants.PDO_TYPE_BATTERY: + get_value_attribute(current)) + elif pdo_type == pdo_constants.PDO_TYPE_BATTERY: + # As per USB PD specification Revision 3.1, Version 1.6, Table 6-18 Battery supply PDO - Sink max_voltage = (pdo_value >> 20) & 0x3ff max_voltage_mv = max_voltage * 50 min_voltage = (pdo_value >> 10) & 0x3ff min_voltage_mv = min_voltage * 50 power = pdo_value & 0x3ff power_mw = power * 250 - add_element_to_xml(xml_ele, constants.SINK_PDO_MIN_VOLTAGE, + + add_element_to_xml(xml_ele, vif_element_constants.SINK_PDO_MIN_VOLTAGE, f'{min_voltage_mv} mV', - {constants.VALUE: str(min_voltage)}) - add_element_to_xml(xml_ele, constants.SINK_PDO_MAX_VOLTAGE, + get_value_attribute(min_voltage)) + add_element_to_xml(xml_ele, vif_element_constants.SINK_PDO_MAX_VOLTAGE, f'{max_voltage_mv} mV', - {constants.VALUE: str(max_voltage)}) - add_element_to_xml(xml_ele, constants.SINK_PDO_OP_POWER, f'{power_mw} mW', - {constants.VALUE: str(power)}) - elif pdo_type == constants.PDO_TYPE_VARIABLE: + get_value_attribute(max_voltage)) + add_element_to_xml(xml_ele, vif_element_constants.SINK_PDO_OP_POWER, + f'{power_mw} mW', + get_value_attribute(power)) + elif pdo_type == pdo_constants.PDO_TYPE_VARIABLE: + # As per USB PD specification Revision 3.1, Version 1.6, Table 6-17 Variable supply (non-Battery) PDO - Sink max_voltage = (pdo_value >> 20) & 0x3ff max_voltage_mv = max_voltage * 50 min_voltage = (pdo_value >> 10) & 0x3ff @@ -158,16 +144,18 @@ def parse_and_add_sink_pdo_to_xml(xml_ele, pdo_value, pdos_info): current = pdo_value & 0x3ff current_ma = current * 10 power_mw = (current_ma * max_voltage_mv) // 1000 - add_element_to_xml(xml_ele, constants.SINK_PDO_MIN_VOLTAGE, + + add_element_to_xml(xml_ele, vif_element_constants.SINK_PDO_MIN_VOLTAGE, f'{min_voltage_mv} mV', - {constants.VALUE: str(min_voltage)}) - add_element_to_xml(xml_ele, constants.SINK_PDO_MAX_VOLTAGE, + get_value_attribute(min_voltage)) + add_element_to_xml(xml_ele, vif_element_constants.SINK_PDO_MAX_VOLTAGE, f'{max_voltage_mv} mV', - {constants.VALUE: str(max_voltage)}) - add_element_to_xml(xml_ele, constants.SINK_PDO_OP_CURRENT, + get_value_attribute(max_voltage)) + add_element_to_xml(xml_ele, vif_element_constants.SINK_PDO_OP_CURRENT, f'{current_ma} mA', - {constants.VALUE: str(current)}) - elif pdo_type == constants.PDO_TYPE_AUGUMENTED: + get_value_attribute(current)) + elif pdo_type == pdo_constants.PDO_TYPE_AUGUMENTED: + # As per USB PD specification Revision 3.1, Version 1.6, Table 6-19 Programmable Power supply APDO - Sink pps = (pdo_value >> 28) & 0x03 if pps: raise ValueError(f'ERROR: Invalid PDO_TYPE {pdo_value}') @@ -178,72 +166,81 @@ def parse_and_add_sink_pdo_to_xml(xml_ele, pdo_value, pdos_info): pps_current = pdo_value & 0x7f pps_current_ma = pps_current * 50 power_mw = (pps_current_ma * pps_max_voltage_mv) // 1000 - add_element_to_xml(xml_ele, constants.SINK_PDO_MIN_VOLTAGE, + + add_element_to_xml(xml_ele, vif_element_constants.SINK_PDO_MIN_VOLTAGE, f'{pps_min_voltage_mv} mV', - {constants.VALUE: str(pps_min_voltage)}) - add_element_to_xml(xml_ele, constants.SINK_PDO_MAX_VOLTAGE, + get_value_attribute(pps_min_voltage)) + add_element_to_xml(xml_ele, vif_element_constants.SINK_PDO_MAX_VOLTAGE, f'{pps_max_voltage_mv} mV', - {constants.VALUE: str(pps_max_voltage)}) - add_element_to_xml(xml_ele, constants.SINK_PDO_OP_CURRENT, + get_value_attribute(pps_max_voltage)) + add_element_to_xml(xml_ele, vif_element_constants.SINK_PDO_OP_CURRENT, f'{pps_current_ma} mA', - {constants.VALUE: str(pps_current)}) + get_value_attribute(pps_current)) else: raise ValueError(f'ERROR: Invalid PDO_TYPE {pdo_value}') - add_element_to_xml(xml_ele, constants.SINK_PDO_SUPPLY_TYPE, - constants.PDO_TYPES[pdo_type], {constants.VALUE: str(pdo_type)}) + + add_element_to_xml(xml_ele, vif_element_constants.SINK_PDO_SUPPLY_TYPE, + pdo_constants.PDO_TYPES[pdo_type], + get_value_attribute(pdo_type)) return power_mw -def parse_and_add_controller_and_data_to_xml(xml_ele, cad): - xml_ele = add_element_to_xml(xml_ele, cad.basename) - for name in cad.data: - add_element_to_xml(xml_ele, name, str(cad.data[name])) - parse_and_add_node_to_xml(xml_ele, cad.controller) +def parse_and_add_sink_pdos_to_xml(xml_ele, sink_pdos): + new_xml_ele = add_element_to_xml(xml_ele, dt_constants.SINK_PDOS) + snk_max_power = 0 + pdo_info = dict() + + for pdo_value in sink_pdos: + power_mv = parse_and_add_sink_pdo_to_xml(new_xml_ele, pdo_value, + pdo_info) + if power_mv > snk_max_power: + snk_max_power = power_mv + + add_element_to_xml(xml_ele, vif_element_constants.PD_POWER_AS_SINK, + f'{snk_max_power} mW', + get_value_attribute(snk_max_power)) + add_element_to_xml(xml_ele, vif_element_constants.HIGHER_CAPABILITY_SET, + None, get_value_attribute(get_xml_bool_value( + vif_element_constants.HIGHER_CAPABILITY_SET in + pdo_info))) + fr_swap_required_type_c_current_as_initial_source = pdo_info[ + vif_element_constants.FR_SWAP_REQD_TYPE_C_CURRENT_AS_INITIAL_SOURCE] + add_element_to_xml(xml_ele, + vif_element_constants.FR_SWAP_REQD_TYPE_C_CURRENT_AS_INITIAL_SOURCE, + other_constants.FR_SWAP_REQD_TYPE_C_CURRENT_AS_INITIAL_SOURCE_VALUES[ + fr_swap_required_type_c_current_as_initial_source], + get_value_attribute( + fr_swap_required_type_c_current_as_initial_source)) + add_element_to_xml(xml_ele, vif_element_constants.NUM_SNK_PDOS, None, + get_value_attribute(len(sink_pdos))) -def parse_and_add_array_to_xml(xml_ele, prop): - for member in prop.val: - if is_simple_datatype(member): - add_element_to_xml(xml_ele, prop.name, str(member)) - elif isinstance(member, list): - new_xml_ele = add_element_to_xml(xml_ele, prop.name) - parse_and_add_array_to_xml(new_xml_ele, member) - elif isinstance(member, edtlib.Node): - new_xml_ele = add_element_to_xml(xml_ele, prop.name) - parse_and_add_node_to_xml(new_xml_ele, member) - elif isinstance(member, edtlib.ControllerAndData): - new_xml_ele = add_element_to_xml(xml_ele, prop.name) - parse_and_add_controller_and_data_to_xml(new_xml_ele, member) - else: - ValueError( - f'Noticed undefined type : {str(type(member))}, with value {str(member)}') +def parse_and_add_component_to_xml(xml_ele, node): + add_element_to_xml(xml_ele, vif_element_constants.USB_PD_SUPPORT, None, + get_value_attribute(get_xml_bool_value( + not node.props[dt_constants.PD_DISABLE].val))) + + if not node.props[dt_constants.PD_DISABLE].val: + power_role = node.props[dt_constants.POWER_ROLE].val + add_element_to_xml(xml_ele, vif_element_constants.PD_PORT_TYPE, + other_constants.PD_PORT_TYPE_VALUES[power_role][1], + get_value_attribute( + other_constants.PD_PORT_TYPE_VALUES[ + power_role][0])) + add_element_to_xml(xml_ele, vif_element_constants.TYPE_C_STATE_MACHINE, + other_constants.TYPE_C_STATE_MACHINE_VALUES[ + power_role][1], + get_value_attribute( + other_constants.TYPE_C_STATE_MACHINE_VALUES[ + power_role][0])) + + if dt_constants.SINK_PDOS in node.props: + parse_and_add_sink_pdos_to_xml(xml_ele, + node.props[dt_constants.SINK_PDOS].val) -def parse_and_add_node_to_xml(xml_ele, node): - if not isinstance(node, edtlib.Node): - return - xml_ele = add_element_to_xml(xml_ele, node.name) - for prop in node.props: - if is_simple_datatype(node.props[prop].val): - add_element_to_xml(xml_ele, node.props[prop].name, - str(node.props[prop].val)) - elif node.props[prop].name == constants.SINK_PDOS: - parse_and_add_sink_pdos_to_xml(xml_ele, node.props[prop].val) - elif isinstance(node.props[prop].val, list): - parse_and_add_array_to_xml(xml_ele, node.props[prop]) - elif isinstance(node.props[prop].val, edtlib.Node): - new_xml_ele = add_element_to_xml(xml_ele, node.props[prop].name) - parse_and_add_node_to_xml(new_xml_ele, node.props[prop].val) - elif isinstance(node.props[prop].val, edtlib.ControllerAndData): - new_xml_ele = add_element_to_xml(xml_ele, node.props[prop].name) - parse_and_add_controller_and_data_to_xml(new_xml_ele, node.props[prop].val) - else: - ValueError( - f'Noticed undefined type : {str(type(node.props[prop].val))}, ' - f'with value {str(node.props[prop].val)}') - for child in node.children: - new_xml_ele = add_element_to_xml(xml_ele, child) - parse_and_add_node_to_xml(new_xml_ele, node.children[child]) +def get_source_xml_root(source_xml_file): + return ET.parse(source_xml_file).getroot() def parse_args(): @@ -254,9 +251,32 @@ def parse_args(): help="device tree compatible to be parsed") parser.add_argument("--vif-out", required=True, help="path to write VIF policies to") - parser.add_argument("--board", required=True, help="board name") + parser.add_argument("--vif-source-xml", required=True, + help="XML file containing high level VIF specifications") return parser.parse_args() +def main(): + global edtlib + + args = parse_args() + with open(args.edt_pickle, 'rb') as f: + edt = pickle.load(f) + edtlib = inspect.getmodule(edt) + + xml_root = get_root() + source_xml_root = get_source_xml_root(args.vif_source_xml) + add_elements_to_xml(xml_root, xml_constants.VIF_SPEC_ELEMENTS) + add_vif_spec_from_source_to_xml(xml_root, source_xml_root) + + for node in edt.compat2nodes[args.compatible]: + xml_ele = add_element_to_xml(xml_root, vif_element_constants.COMPONENT) + parse_and_add_component_to_xml(xml_ele, node) + + tree = ET.ElementTree(xml_root) + tree.write(args.vif_out, xml_declaration=True, + encoding=xml_constants.XML_ENCODING) + + if __name__ == "__main__": main() diff --git a/subsys/usb/usb_c/Kconfig b/subsys/usb/usb_c/Kconfig index e07c28a8063..57be78f6819 100644 --- a/subsys/usb/usb_c/Kconfig +++ b/subsys/usb/usb_c/Kconfig @@ -39,6 +39,13 @@ config BUILD_OUTPUT_VIF help Generate XML file containing VIF policies during project build. +config GENVIF_INPUT_VIF_XML_PATH + string "Path to input VIF file" + depends on BUILD_OUTPUT_VIF + help + Absolute path or relative path (w.r.to the application source + directory) of the GenVIF input VIF XML file. + choice USBC_CSM_TYPE prompt "USB-C Connection State Machine" default USBC_CSM_SINK_ONLY