| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/07/28 05:15 | flow | patch-triage |
0mArgs:null Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch introduces a new PTP clock driver for the Qualcomm Timestamp Counter Subsystem (TSCSS). This is a hardware-specific SoC platform driver that requires specific clocks (\"ahb\", \"cntr\") and MMIO resources to probe successfully. These hardware dependencies are not emulated in standard virtualized environments like QEMU, making the code unreachable for fuzzing.",
"WorthFuzzing": false
} |
| 1/1 | 2026/07/28 05:15 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 4e4f9832aae3082a961d0c84dce6547f7a0cb35d\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Tue Jul 28 05:15:06 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/Documentation/devicetree/bindings/ptp/qcom,lemans-tscss.yaml b/Documentation/devicetree/bindings/ptp/qcom,lemans-tscss.yaml\nnew file mode 100644\nindex 00000000000000..4cbe4b00ff7dca\n--- /dev/null\n+++ b/Documentation/devicetree/bindings/ptp/qcom,lemans-tscss.yaml\n@@ -0,0 +1,198 @@\n+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause\n+%YAML 1.2\n+---\n+$id: http://devicetree.org/schemas/ptp/qcom,lemans-tscss.yaml#\n+$schema: http://devicetree.org/meta-schemas/core.yaml#\n+\n+title: Timestamp Counter Subsystem (TSCSS) on Qualcomm Lemans and Monaco SoCs\n+\n+maintainers:\n+ - Imran Shaik \u003cimran.shaik@oss.qualcomm.com\u003e\n+ - Taniya Das \u003ctaniya.das@oss.qualcomm.com\u003e\n+\n+description: |\n+ Qualcomm TSCSS is a time synchronization subsystem composed of two main\n+ blocks - the Time Stamp Counter (TSC) and the Event Timestamp Unit (ETU).\n+\n+ The TSC block is a timestamp generator that maintains a running counter used\n+ for system timekeeping, and is functional with just the AHB and counter\n+ clocks.\n+ The ETU block is optional and captures TSC timestamps for external\n+ hardware events, each ETU slice binding a slice identifier to an external\n+ event selector. Support for the ETU block requires the additional ETU\n+ clock along with the summary interrupt and slice subnodes.\n+\n+properties:\n+ compatible:\n+ oneOf:\n+ - const: qcom,lemans-tscss\n+ - items:\n+ - const: qcom,monaco-tscss\n+ - const: qcom,lemans-tscss\n+\n+ reg:\n+ maxItems: 1\n+\n+ reg-names:\n+ items:\n+ - const: tsc\n+\n+ clocks:\n+ minItems: 2\n+ items:\n+ - description: TSC AHB configuration clock.\n+ - description: TSC global counter clock.\n+ - description: TSC ETU clock.\n+\n+ clock-names:\n+ minItems: 2\n+ items:\n+ - const: ahb\n+ - const: cntr\n+ - const: etu\n+\n+ interrupts:\n+ description: Summary interrupt raised based on external event for any of the ETU slices.\n+ maxItems: 1\n+\n+ interrupt-names:\n+ items:\n+ - const: etu_summary\n+\n+ assigned-clocks: true\n+ assigned-clock-rates: true\n+\n+ \"#address-cells\":\n+ const: 2\n+\n+ \"#size-cells\":\n+ const: 2\n+\n+ ranges: true\n+\n+patternProperties:\n+ \"^etu-slice@[0-9a-f]+$\":\n+ type: object\n+ description: ETU slice configuration\n+ properties:\n+ reg:\n+ maxItems: 1\n+\n+ pinctrl-0: true\n+\n+ pinctrl-names:\n+ items:\n+ - const: default\n+\n+ qcom,etu-event-sel:\n+ description: Event selection value for this slice.\n+ $ref: /schemas/types.yaml#/definitions/uint32\n+\n+ qcom,etu-slice:\n+ description: ETU slice identifier.\n+ $ref: /schemas/types.yaml#/definitions/uint32\n+\n+ required:\n+ - reg\n+ - qcom,etu-event-sel\n+ - qcom,etu-slice\n+ - pinctrl-0\n+ - pinctrl-names\n+ unevaluatedProperties: false\n+\n+required:\n+ - compatible\n+ - reg\n+ - reg-names\n+ - clocks\n+ - clock-names\n+\n+allOf:\n+ - if:\n+ properties:\n+ clock-names:\n+ contains:\n+ const: etu\n+ then:\n+ properties:\n+ clocks:\n+ minItems: 3\n+ clock-names:\n+ minItems: 3\n+ required:\n+ - interrupts\n+ - interrupt-names\n+ - \"#address-cells\"\n+ - \"#size-cells\"\n+ - ranges\n+\n+unevaluatedProperties: false\n+\n+examples:\n+ - |\n+ #include \u003cdt-bindings/clock/qcom,sa8775p-gcc.h\u003e\n+\n+ soc {\n+ #address-cells = \u003c2\u003e;\n+ #size-cells = \u003c2\u003e;\n+\n+ tscss@1c80000 {\n+ compatible = \"qcom,lemans-tscss\";\n+ reg = \u003c0x0 0x01c80000 0x0 0x2000\u003e;\n+ reg-names = \"tsc\";\n+\n+ clocks = \u003c\u0026gcc GCC_TSCSS_AHB_CLK\u003e,\n+ \u003c\u0026gcc GCC_TSCSS_GLOBAL_CNTR_CLK\u003e;\n+ clock-names = \"ahb\", \"cntr\";\n+\n+ assigned-clocks = \u003c\u0026gcc GCC_TSCSS_GLOBAL_CNTR_CLK\u003e;\n+ assigned-clock-rates = \u003c15625000\u003e;\n+ };\n+ };\n+\n+ - |\n+ #include \u003cdt-bindings/clock/qcom,sa8775p-gcc.h\u003e\n+ #include \u003cdt-bindings/interrupt-controller/arm-gic.h\u003e\n+\n+ soc {\n+ #address-cells = \u003c2\u003e;\n+ #size-cells = \u003c2\u003e;\n+\n+ tscss@1c80000 {\n+ compatible = \"qcom,lemans-tscss\";\n+ reg = \u003c0x0 0x01c80000 0x0 0x2000\u003e;\n+ reg-names = \"tsc\";\n+ #address-cells = \u003c2\u003e;\n+ #size-cells = \u003c2\u003e;\n+ ranges;\n+\n+ clocks = \u003c\u0026gcc GCC_TSCSS_AHB_CLK\u003e,\n+ \u003c\u0026gcc GCC_TSCSS_GLOBAL_CNTR_CLK\u003e,\n+ \u003c\u0026gcc GCC_TSCSS_ETU_CLK\u003e;\n+ clock-names = \"ahb\", \"cntr\", \"etu\";\n+\n+ assigned-clocks = \u003c\u0026gcc GCC_TSCSS_GLOBAL_CNTR_CLK\u003e,\n+ \u003c\u0026gcc GCC_TSCSS_ETU_CLK\u003e;\n+ assigned-clock-rates = \u003c15625000\u003e, \u003c15625000\u003e;\n+\n+ interrupts = \u003cGIC_SPI 604 IRQ_TYPE_LEVEL_HIGH\u003e;\n+ interrupt-names = \"etu_summary\";\n+\n+ etu-slice@1c91000 {\n+ reg = \u003c0x0 0x01c91000 0x0 0x1000\u003e;\n+ pinctrl-0 = \u003c\u0026cci_timer0\u003e;\n+ pinctrl-names = \"default\";\n+ qcom,etu-event-sel = \u003c1\u003e;\n+ qcom,etu-slice = \u003c1\u003e;\n+ };\n+\n+ etu-slice@1c92000 {\n+ reg = \u003c0x0 0x01c92000 0x0 0x1000\u003e;\n+ pinctrl-0 = \u003c\u0026cci_timer1\u003e;\n+ pinctrl-names = \"default\";\n+ qcom,etu-event-sel = \u003c2\u003e;\n+ qcom,etu-slice = \u003c2\u003e;\n+ };\n+ };\n+ };\n+...\ndiff --git a/Documentation/devicetree/bindings/ptp/qcom,qdu1000-tscss.yaml b/Documentation/devicetree/bindings/ptp/qcom,qdu1000-tscss.yaml\nnew file mode 100644\nindex 00000000000000..39387614ef8939\n--- /dev/null\n+++ b/Documentation/devicetree/bindings/ptp/qcom,qdu1000-tscss.yaml\n@@ -0,0 +1,187 @@\n+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause\n+%YAML 1.2\n+---\n+$id: http://devicetree.org/schemas/ptp/qcom,qdu1000-tscss.yaml#\n+$schema: http://devicetree.org/meta-schemas/core.yaml#\n+\n+title: Timestamp Counter Subsystem (TSCSS) on Qualcomm QDU1000 SoC\n+\n+maintainers:\n+ - Imran Shaik \u003cimran.shaik@oss.qualcomm.com\u003e\n+ - Taniya Das \u003ctaniya.das@oss.qualcomm.com\u003e\n+\n+description: |\n+ Qualcomm TSCSS is a time synchronization subsystem composed of two main\n+ blocks - the Time Stamp Counter (TSC) and the Event Timestamp Unit (ETU).\n+\n+ The TSC block is a timestamp generator that maintains a running counter used\n+ for system timekeeping, and is functional with just the AHB and counter\n+ clocks.\n+ The ETU block is optional and captures TSC timestamps for external\n+ hardware events, each ETU slice binding a slice identifier to an external\n+ event selector. Support for the ETU block requires the additional ETU\n+ clock along with the per slice interrupt and slice subnodes.\n+\n+properties:\n+ compatible:\n+ const: qcom,qdu1000-tscss\n+\n+ reg:\n+ maxItems: 1\n+\n+ reg-names:\n+ items:\n+ - const: tsc\n+\n+ clocks:\n+ minItems: 2\n+ items:\n+ - description: TSC AHB configuration clock.\n+ - description: TSC global counter clock.\n+ - description: TSC ETU clock.\n+\n+ clock-names:\n+ minItems: 2\n+ items:\n+ - const: ahb\n+ - const: cntr\n+ - const: etu\n+\n+ assigned-clocks: true\n+ assigned-clock-rates: true\n+\n+ \"#address-cells\":\n+ const: 2\n+\n+ \"#size-cells\":\n+ const: 2\n+\n+ ranges: true\n+\n+patternProperties:\n+ \"^etu-slice@[0-9a-f]+$\":\n+ type: object\n+ description: ETU slice configuration\n+ properties:\n+ reg:\n+ maxItems: 1\n+\n+ pinctrl-0: true\n+\n+ pinctrl-names:\n+ items:\n+ - const: default\n+\n+ interrupts:\n+ description: Per slice interrupt generated by ETU based on external event trigger.\n+ maxItems: 1\n+\n+ qcom,etu-event-sel:\n+ description: Event selection value for this slice.\n+ $ref: /schemas/types.yaml#/definitions/uint32\n+\n+ qcom,etu-slice:\n+ description: ETU slice identifier.\n+ $ref: /schemas/types.yaml#/definitions/uint32\n+\n+ required:\n+ - reg\n+ - interrupts\n+ - qcom,etu-event-sel\n+ - qcom,etu-slice\n+ - pinctrl-0\n+ - pinctrl-names\n+ unevaluatedProperties: false\n+\n+required:\n+ - compatible\n+ - reg\n+ - reg-names\n+ - clocks\n+ - clock-names\n+\n+allOf:\n+ - if:\n+ properties:\n+ clock-names:\n+ contains:\n+ const: etu\n+ then:\n+ properties:\n+ clocks:\n+ minItems: 3\n+ clock-names:\n+ minItems: 3\n+ required:\n+ - \"#address-cells\"\n+ - \"#size-cells\"\n+ - ranges\n+\n+unevaluatedProperties: false\n+\n+examples:\n+ - |\n+ #include \u003cdt-bindings/clock/qcom,qdu1000-gcc.h\u003e\n+\n+ soc {\n+ #address-cells = \u003c2\u003e;\n+ #size-cells = \u003c2\u003e;\n+\n+ tscss@1da0000 {\n+ compatible = \"qcom,qdu1000-tscss\";\n+ reg = \u003c0x0 0x01da0000 0x0 0x2000\u003e;\n+ reg-names = \"tsc\";\n+\n+ clocks = \u003c\u0026gcc GCC_TSC_CFG_AHB_CLK\u003e,\n+ \u003c\u0026gcc GCC_TSC_CNTR_CLK\u003e;\n+ clock-names = \"ahb\", \"cntr\";\n+ assigned-clocks = \u003c\u0026gcc GCC_TSC_CNTR_CLK\u003e;\n+ assigned-clock-rates = \u003c500000000\u003e;\n+ };\n+ };\n+\n+ - |\n+ #include \u003cdt-bindings/clock/qcom,qdu1000-gcc.h\u003e\n+ #include \u003cdt-bindings/interrupt-controller/arm-gic.h\u003e\n+\n+ soc {\n+ #address-cells = \u003c2\u003e;\n+ #size-cells = \u003c2\u003e;\n+\n+ tscss@1da0000 {\n+ compatible = \"qcom,qdu1000-tscss\";\n+ reg = \u003c0x0 0x01da0000 0x0 0x2000\u003e;\n+ reg-names = \"tsc\";\n+ #address-cells = \u003c2\u003e;\n+ #size-cells = \u003c2\u003e;\n+ ranges;\n+\n+ clocks = \u003c\u0026gcc GCC_TSC_CFG_AHB_CLK\u003e,\n+ \u003c\u0026gcc GCC_TSC_CNTR_CLK\u003e,\n+ \u003c\u0026gcc GCC_TSC_ETU_CLK\u003e;\n+ clock-names = \"ahb\", \"cntr\", \"etu\";\n+\n+ assigned-clocks = \u003c\u0026gcc GCC_TSC_CNTR_CLK\u003e,\n+ \u003c\u0026gcc GCC_TSC_ETU_CLK\u003e;\n+ assigned-clock-rates = \u003c500000000\u003e, \u003c500000000\u003e;\n+\n+ etu-slice@1db1000 {\n+ reg = \u003c0x0 0x01db1000 0x0 0x1000\u003e;\n+ interrupts = \u003cGIC_SPI 329 IRQ_TYPE_EDGE_RISING\u003e;\n+ pinctrl-0 = \u003c\u0026cci_timer0\u003e;\n+ pinctrl-names = \"default\";\n+ qcom,etu-event-sel = \u003c1\u003e;\n+ qcom,etu-slice = \u003c1\u003e;\n+ };\n+\n+ etu-slice@1db2000 {\n+ reg = \u003c0x0 0x01db2000 0x0 0x1000\u003e;\n+ interrupts = \u003cGIC_SPI 330 IRQ_TYPE_EDGE_RISING\u003e;\n+ pinctrl-0 = \u003c\u0026cci_timer1\u003e;\n+ pinctrl-names = \"default\";\n+ qcom,etu-event-sel = \u003c2\u003e;\n+ qcom,etu-slice = \u003c2\u003e;\n+ };\n+ };\n+ };\n+...\ndiff --git a/arch/arm64/boot/dts/qcom/lemans.dtsi b/arch/arm64/boot/dts/qcom/lemans.dtsi\nindex 3b0539e27b5192..e225292a1e41a5 100644\n--- a/arch/arm64/boot/dts/qcom/lemans.dtsi\n+++ b/arch/arm64/boot/dts/qcom/lemans.dtsi\n@@ -3023,6 +3023,17 @@ pcie1_phy: phy@1c14000 {\n \t\t\tstatus = \"disabled\";\n \t\t};\n \n+\t\ttscss@1c80000 {\n+\t\t\tcompatible = \"qcom,lemans-tscss\";\n+\t\t\treg = \u003c0x0 0x01c80000 0x0 0x2000\u003e;\n+\t\t\treg-names = \"tsc\";\n+\t\t\tclocks = \u003c\u0026gcc GCC_TSCSS_AHB_CLK\u003e,\n+\t\t\t\t \u003c\u0026gcc GCC_TSCSS_GLOBAL_CNTR_CLK\u003e;\n+\t\t\tclock-names = \"ahb\", \"cntr\";\n+\t\t\tassigned-clocks = \u003c\u0026gcc GCC_TSCSS_GLOBAL_CNTR_CLK\u003e;\n+\t\t\tassigned-clock-rates = \u003c15625000\u003e;\n+\t\t};\n+\n \t\tufs_mem_hc: ufshc@1d84000 {\n \t\t\tcompatible = \"qcom,sa8775p-ufshc\", \"qcom,ufshc\", \"jedec,ufs-2.0\";\n \t\t\treg = \u003c0x0 0x01d84000 0x0 0x3000\u003e;\ndiff --git a/arch/arm64/boot/dts/qcom/qdu1000.dtsi b/arch/arm64/boot/dts/qcom/qdu1000.dtsi\nindex 26cc86d12f7256..8979c18225184a 100644\n--- a/arch/arm64/boot/dts/qcom/qdu1000.dtsi\n+++ b/arch/arm64/boot/dts/qcom/qdu1000.dtsi\n@@ -876,6 +876,17 @@ system_noc: interconnect@1640000 {\n \t\t\t#interconnect-cells = \u003c2\u003e;\n \t\t};\n \n+\t\ttscss@1da0000 {\n+\t\t\tcompatible = \"qcom,qdu1000-tscss\";\n+\t\t\treg = \u003c0x0 0x01da0000 0x0 0x2000\u003e;\n+\t\t\treg-names = \"tsc\";\n+\t\t\tclocks = \u003c\u0026gcc GCC_TSC_CFG_AHB_CLK\u003e,\n+\t\t\t\t \u003c\u0026gcc GCC_TSC_CNTR_CLK\u003e;\n+\t\t\tclock-names = \"ahb\", \"cntr\";\n+\t\t\tassigned-clocks = \u003c\u0026gcc GCC_TSC_CNTR_CLK\u003e;\n+\t\t\tassigned-clock-rates = \u003c500000000\u003e;\n+\t\t};\n+\n \t\ttcsr_mutex: hwlock@1f40000 {\n \t\t\tcompatible = \"qcom,tcsr-mutex\";\n \t\t\treg = \u003c0x0 0x1f40000 0x0 0x20000\u003e;\ndiff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig\nindex 6ec8d3a69c98e0..73435e5f8877d2 100644\n--- a/arch/arm64/configs/defconfig\n+++ b/arch/arm64/configs/defconfig\n@@ -683,6 +683,7 @@ CONFIG_SPI_SPIDEV=m\n CONFIG_SPMI=y\n CONFIG_SPMI_APPLE=m\n CONFIG_SPMI_MTK_PMIF=m\n+CONFIG_PTP_QCOM_TSC=m\n CONFIG_PINCTRL_APPLE_GPIO=m\n CONFIG_PINCTRL_DA9062=m\n CONFIG_PINCTRL_MAX77620=y\ndiff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig\nindex b93640ca08b728..d3ceb1ee01a505 100644\n--- a/drivers/ptp/Kconfig\n+++ b/drivers/ptp/Kconfig\n@@ -263,4 +263,14 @@ config PTP_NETC_V4_TIMER\n \t synchronization. It also supports periodic output signal (e.g. PPS)\n \t and external trigger timestamping.\n \n+config PTP_QCOM_TSC\n+\ttristate \"Qualcomm TSC as PTP clock\"\n+\tdepends on COMMON_CLK \u0026\u0026 PTP_1588_CLOCK\n+\thelp\n+\t This driver adds support for using the Qualcomm Timestamp Counter\n+\t Subsystem (TSCSS) as a PTP clock.\n+\n+\t To compile this driver as a module, choose M here: the module\n+\t will be called ptp_qcom_tsc.\n+\n endmenu\ndiff --git a/drivers/ptp/Makefile b/drivers/ptp/Makefile\nindex bdc47e284f14e7..ff029323e98f5e 100644\n--- a/drivers/ptp/Makefile\n+++ b/drivers/ptp/Makefile\n@@ -22,3 +22,4 @@ obj-$(CONFIG_PTP_1588_CLOCK_OCP)\t+= ptp_ocp.o\n obj-$(CONFIG_PTP_DFL_TOD)\t\t+= ptp_dfl_tod.o\n obj-$(CONFIG_PTP_S390)\t\t\t+= ptp_s390.o\n obj-$(CONFIG_PTP_NETC_V4_TIMER)\t\t+= ptp_netc.o\n+obj-$(CONFIG_PTP_QCOM_TSC)\t\t+= ptp_qcom_tsc.o\ndiff --git a/drivers/ptp/ptp_qcom_tsc.c b/drivers/ptp/ptp_qcom_tsc.c\nnew file mode 100644\nindex 00000000000000..b29248150388f3\n--- /dev/null\n+++ b/drivers/ptp/ptp_qcom_tsc.c\n@@ -0,0 +1,413 @@\n+// SPDX-License-Identifier: GPL-2.0-only\n+/*\n+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.\n+ */\n+\n+#include \u003clinux/bitfield.h\u003e\n+#include \u003clinux/clk.h\u003e\n+#include \u003clinux/err.h\u003e\n+#include \u003clinux/iopoll.h\u003e\n+#include \u003clinux/io.h\u003e\n+#include \u003clinux/module.h\u003e\n+#include \u003clinux/mutex.h\u003e\n+#include \u003clinux/of.h\u003e\n+#include \u003clinux/ptp_clock_kernel.h\u003e\n+#include \u003clinux/platform_device.h\u003e\n+\n+#define ROLLOVER_VAL\t\t\t\t999999999\n+#define NSEC_SHIFT\t\t\t\t32\n+#define PULSE_WIDTH_MASK\t\t\tGENMASK(7, 6)\n+#define DRIFT_MAX_RES\t\t\t\t0x1FFFF\n+#define DRIFT_JUMP_SWALLOW\t\t\tBIT(31)\n+#define DRIFT_PERIOD_MASK\t\t\tGENMASK(28, 12)\n+#define DRIFT_SUBPERIOD_MASK\t\t\tGENMASK(11, 0)\n+#define DRIFT_INTERVAL_US\t\t\t10\n+#define DRIFT_MIN_TIMEOUT_US\t\t\t5000\n+\n+#define DRIFT_TIMEOUT_US(period, subperiod, cntr_res)\t\t\t\\\n+\tmax_t(u64, div_u64((u64)(period) * (subperiod) * (cntr_res), NSEC_PER_USEC), \\\n+\t DRIFT_MIN_TIMEOUT_US)\n+\n+struct qcom_tsc_regs {\n+\tu32 control_cntcr;\n+\tu32 control_cntcv_lo;\n+\tu32 control_cntcv_hi;\n+\tu32 drift_correct_incr_val;\n+\tu32 drift_correct_duration;\n+\tu32 drift_correct_cmd;\n+\tu32 rollover_val;\n+\tu32 offset_lo;\n+\tu32 offset_hi;\n+\tu32 read_cntcv_lo;\n+\tu32 read_cntcv_hi;\n+};\n+\n+/**\n+ * struct qcom_tsc_soc_data - SoC specific TSC hardware capabilities\n+ *\n+ * @rollover: indicates the counter uses sec/nsec split\n+ * @offset_correction: hardware supports one-shot offset correction\n+ * @pulse_width: valid pulse width in cycles for drift correction\n+ * @cntr_res: TSC counter resolution in nsec\n+ * @reg_layout: register layout for this SoC/version\n+ */\n+struct qcom_tsc_soc_data {\n+\tbool rollover;\n+\tbool offset_correction;\n+\tint pulse_width;\n+\tint cntr_res;\n+\tconst struct qcom_tsc_regs *reg_layout;\n+};\n+\n+struct qcom_tsc {\n+\tstruct device *dev;\n+\tvoid __iomem *base;\n+\tconst struct qcom_tsc_soc_data *soc;\n+\tstruct clk *ahb_clk;\n+\tstruct clk *cntr_clk;\n+\tstruct clk *etu_clk;\n+\tstruct ptp_clock *ptp;\n+\tstruct ptp_clock_info ptp_info;\n+\t/* Mutex to protect operations from being interrupted */\n+\tstruct mutex lock;\n+};\n+\n+static bool qcom_tsc_is_enabled(struct qcom_tsc *tsc)\n+{\n+\tconst struct qcom_tsc_regs *regs = tsc-\u003esoc-\u003ereg_layout;\n+\n+\treturn readl_relaxed(tsc-\u003ebase + regs-\u003econtrol_cntcr) \u0026 BIT(0);\n+}\n+\n+static int qcom_tsc_read_time(struct qcom_tsc *tsc, struct timespec64 *ts)\n+{\n+\tconst struct qcom_tsc_regs *regs = tsc-\u003esoc-\u003ereg_layout;\n+\tu32 hi, lo;\n+\n+\tif (!qcom_tsc_is_enabled(tsc))\n+\t\treturn -EINVAL;\n+\n+\thi = readl_relaxed(tsc-\u003ebase + regs-\u003eread_cntcv_hi);\n+\tlo = readl_relaxed(tsc-\u003ebase + regs-\u003eread_cntcv_lo);\n+\n+\tif (tsc-\u003esoc-\u003erollover) {\n+\t\tts-\u003etv_sec = hi;\n+\t\tts-\u003etv_nsec = lo;\n+\t} else {\n+\t\tu64 ns = ((u64)hi \u003c\u003c NSEC_SHIFT) | lo;\n+\n+\t\t*ts = ns_to_timespec64(ns);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int qcom_tsc_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)\n+{\n+\tstruct qcom_tsc *tsc = container_of(ptp, struct qcom_tsc, ptp_info);\n+\tint ret;\n+\n+\tmutex_lock(\u0026tsc-\u003elock);\n+\tret = qcom_tsc_read_time(tsc, ts);\n+\tmutex_unlock(\u0026tsc-\u003elock);\n+\n+\treturn ret;\n+}\n+\n+static inline void qcom_tsc_split_ts(struct qcom_tsc *tsc, struct timespec64 ts, u32 *hi, u32 *lo)\n+{\n+\tif (tsc-\u003esoc-\u003erollover) {\n+\t\t*hi = ts.tv_sec;\n+\t\t*lo = ts.tv_nsec;\n+\t} else {\n+\t\tu64 ns = timespec64_to_ns(\u0026ts);\n+\n+\t\t*lo = lower_32_bits(ns);\n+\t\t*hi = upper_32_bits(ns);\n+\t}\n+}\n+\n+static int qcom_tsc_update_counter(struct qcom_tsc *tsc, struct timespec64 ts)\n+{\n+\tconst struct qcom_tsc_regs *regs = tsc-\u003esoc-\u003ereg_layout;\n+\tu32 regval, hi, lo;\n+\n+\tqcom_tsc_split_ts(tsc, ts, \u0026hi, \u0026lo);\n+\n+\twritel_relaxed(lo, tsc-\u003ebase + regs-\u003econtrol_cntcv_lo);\n+\twritel_relaxed(hi, tsc-\u003ebase + regs-\u003econtrol_cntcv_hi);\n+\n+\tregval = readl_relaxed(tsc-\u003ebase + regs-\u003econtrol_cntcr);\n+\tregval |= BIT(0);\n+\twritel_relaxed(regval, tsc-\u003ebase + regs-\u003econtrol_cntcr);\n+\n+\treturn 0;\n+}\n+\n+static int qcom_tsc_update_offset(struct qcom_tsc *tsc, const struct timespec64 ts)\n+{\n+\tconst struct qcom_tsc_regs *regs = tsc-\u003esoc-\u003ereg_layout;\n+\tstruct timespec64 tod;\n+\tu32 regval, hi, lo;\n+\tint ret;\n+\n+\tif (tsc-\u003esoc-\u003eoffset_correction) {\n+\t\tqcom_tsc_split_ts(tsc, ts, \u0026hi, \u0026lo);\n+\n+\t\twritel_relaxed(lo, tsc-\u003ebase + regs-\u003eoffset_lo);\n+\t\twritel_relaxed(hi, tsc-\u003ebase + regs-\u003eoffset_hi);\n+\n+\t\treturn 0;\n+\t}\n+\n+\t/*\n+\t * No hardware offset correction support: disable and reload the\n+\t * counter with the corrected time, as recommended by the hardware\n+\t * design team.\n+\t */\n+\tret = qcom_tsc_read_time(tsc, \u0026tod);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tregval = readl_relaxed(tsc-\u003ebase + regs-\u003econtrol_cntcr);\n+\tregval \u0026= ~BIT(0);\n+\twritel_relaxed(regval, tsc-\u003ebase + regs-\u003econtrol_cntcr);\n+\n+\treturn qcom_tsc_update_counter(tsc, timespec64_add(tod, ts));\n+}\n+\n+static int qcom_tsc_settime(struct ptp_clock_info *ptp, const struct timespec64 *ts)\n+{\n+\tstruct qcom_tsc *tsc = container_of(ptp, struct qcom_tsc, ptp_info);\n+\tconst struct qcom_tsc_regs *regs = tsc-\u003esoc-\u003ereg_layout;\n+\tstruct timespec64 tod;\n+\tu32 regval;\n+\tint ret;\n+\n+\tmutex_lock(\u0026tsc-\u003elock);\n+\n+\tif (qcom_tsc_is_enabled(tsc)) {\n+\t\tqcom_tsc_read_time(tsc, \u0026tod);\n+\t\tret = qcom_tsc_update_offset(tsc, timespec64_sub(*ts, tod));\n+\t\tmutex_unlock(\u0026tsc-\u003elock);\n+\t\treturn ret;\n+\t}\n+\n+\t/* Configure and enable the TSC counter */\n+\tregval = readl_relaxed(tsc-\u003ebase + regs-\u003econtrol_cntcr);\n+\tregval |= FIELD_PREP(PULSE_WIDTH_MASK, tsc-\u003esoc-\u003epulse_width);\n+\twritel_relaxed(regval, tsc-\u003ebase + regs-\u003econtrol_cntcr);\n+\n+\tif (tsc-\u003esoc-\u003erollover)\n+\t\twritel_relaxed(ROLLOVER_VAL, tsc-\u003ebase + regs-\u003erollover_val);\n+\n+\tret = qcom_tsc_update_counter(tsc, *ts);\n+\tmutex_unlock(\u0026tsc-\u003elock);\n+\n+\treturn ret;\n+}\n+\n+static int qcom_tsc_adjtime(struct ptp_clock_info *ptp, s64 delta)\n+{\n+\tstruct qcom_tsc *tsc = container_of(ptp, struct qcom_tsc, ptp_info);\n+\tint ret;\n+\n+\tmutex_lock(\u0026tsc-\u003elock);\n+\tret = qcom_tsc_update_offset(tsc, ns_to_timespec64(delta));\n+\tmutex_unlock(\u0026tsc-\u003elock);\n+\n+\treturn ret;\n+}\n+\n+static int qcom_tsc_drift_correction(struct qcom_tsc *tsc, long scaled_ppm)\n+{\n+\tconst struct qcom_tsc_soc_data *soc = tsc-\u003esoc;\n+\tconst struct qcom_tsc_regs *regs = soc-\u003ereg_layout;\n+\tlong ppb = scaled_ppm_to_ppb(scaled_ppm);\n+\tu64 period, incval = 0;\n+\tu32 regval = 0, subperiod;\n+\n+\tif (ppb \u003c 0) {\n+\t\tppb = -ppb;\n+\t\tregval \u0026= ~DRIFT_JUMP_SWALLOW;\n+\n+\t\tperiod = div_u64(ppb, soc-\u003ecntr_res);\n+\t\tif (period \u003e= DRIFT_MAX_RES)\n+\t\t\tperiod = DRIFT_MAX_RES;\n+\t} else {\n+\t\tregval |= DRIFT_JUMP_SWALLOW;\n+\n+\t\tperiod = div_u64(ppb, soc-\u003ecntr_res);\n+\t\tif (period \u003e= DRIFT_MAX_RES) {\n+\t\t\tperiod = DRIFT_MAX_RES;\n+\t\t\tincval = soc-\u003ecntr_res * 2;\n+\t\t} else if (ppb \u003c soc-\u003ecntr_res) {\n+\t\t\tincval = soc-\u003ecntr_res + ppb;\n+\t\t\tperiod = 1;\n+\t\t} else {\n+\t\t\tincval = soc-\u003ecntr_res * 2;\n+\t\t}\n+\t}\n+\n+\tsubperiod = soc-\u003epulse_width * 2;\n+\tregval |= FIELD_PREP(DRIFT_SUBPERIOD_MASK, subperiod);\n+\tregval |= FIELD_PREP(DRIFT_PERIOD_MASK, period);\n+\n+\t/* Update jump/swallow, period, subperiod */\n+\twritel_relaxed(regval, tsc-\u003ebase + regs-\u003edrift_correct_duration);\n+\n+\twritel_relaxed(incval, tsc-\u003ebase + regs-\u003edrift_correct_incr_val);\n+\n+\t/* Trigger the drift correction */\n+\tregval = readl_relaxed(tsc-\u003ebase + regs-\u003edrift_correct_cmd);\n+\tregval |= BIT(0);\n+\twritel_relaxed(regval, tsc-\u003ebase + regs-\u003edrift_correct_cmd);\n+\n+\treturn readl_poll_timeout(tsc-\u003ebase + regs-\u003edrift_correct_cmd, regval,\n+\t\t\t\t !(regval \u0026 BIT(1)), DRIFT_INTERVAL_US,\n+\t\t\t\t DRIFT_TIMEOUT_US(period, subperiod, soc-\u003ecntr_res));\n+}\n+\n+static int qcom_tsc_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)\n+{\n+\tstruct qcom_tsc *tsc = container_of(ptp, struct qcom_tsc, ptp_info);\n+\tint ret;\n+\n+\tif (scaled_ppm == 0)\n+\t\treturn 0;\n+\n+\tmutex_lock(\u0026tsc-\u003elock);\n+\tret = qcom_tsc_drift_correction(tsc, scaled_ppm);\n+\tmutex_unlock(\u0026tsc-\u003elock);\n+\n+\treturn ret;\n+}\n+\n+static struct ptp_clock_info qcom_ptp_info = {\n+\t.owner\t\t= THIS_MODULE,\n+\t.name\t\t= \"PTP_QCOM_TSC\",\n+\t.max_adj\t= 9999999,\n+\t.adjfine\t= qcom_tsc_adjfine,\n+\t.adjtime\t= qcom_tsc_adjtime,\n+\t.gettime64 = qcom_tsc_gettime,\n+\t.settime64 = qcom_tsc_settime,\n+};\n+\n+static const struct qcom_tsc_regs qcom_tsc_layout = {\n+\t.control_cntcr = 0x0,\n+\t.control_cntcv_lo = 0x8,\n+\t.control_cntcv_hi = 0xc,\n+\t.drift_correct_incr_val = 0x2c,\n+\t.drift_correct_duration = 0x30,\n+\t.drift_correct_cmd = 0x34,\n+\t.rollover_val = 0x3c,\n+\t.offset_lo = 0x50,\n+\t.offset_hi = 0x54,\n+\t.read_cntcv_lo = 0x1000,\n+\t.read_cntcv_hi = 0x1004,\n+};\n+\n+static const struct qcom_tsc_soc_data qcom_tsc_lemans = {\n+\t.reg_layout\t\t= \u0026qcom_tsc_layout,\n+\t.rollover\t\t= false,\n+\t.offset_correction\t= false,\n+\t.pulse_width\t\t= 2,\n+\t.cntr_res\t\t= 64,\n+};\n+\n+static const struct qcom_tsc_soc_data qcom_tsc_qdu1000 = {\n+\t.reg_layout\t\t= \u0026qcom_tsc_layout,\n+\t.rollover\t\t= true,\n+\t.offset_correction\t= true,\n+\t.pulse_width\t\t= 3,\n+\t.cntr_res\t\t= 2,\n+};\n+\n+static const struct of_device_id qcom_tsc_of_match[] = {\n+\t{ .compatible = \"qcom,lemans-tscss\", .data = \u0026qcom_tsc_lemans },\n+\t{ .compatible = \"qcom,qdu1000-tscss\", .data = \u0026qcom_tsc_qdu1000 },\n+\t{ }\n+};\n+MODULE_DEVICE_TABLE(of, qcom_tsc_of_match);\n+\n+static void qcom_ptp_tsc_remove(struct platform_device *pdev)\n+{\n+\tstruct qcom_tsc *tsc = platform_get_drvdata(pdev);\n+\n+\tif (tsc \u0026\u0026 tsc-\u003eptp) {\n+\t\tptp_clock_unregister(tsc-\u003eptp);\n+\t\ttsc-\u003eptp = NULL;\n+\t}\n+}\n+\n+static int qcom_ptp_tsc_probe(struct platform_device *pdev)\n+{\n+\tconst struct qcom_tsc_soc_data *soc;\n+\tstruct qcom_tsc *tsc;\n+\tstruct resource *r_mem;\n+\tint ret;\n+\n+\tsoc = of_device_get_match_data(\u0026pdev-\u003edev);\n+\tif (!soc)\n+\t\treturn -ENODEV;\n+\n+\ttsc = devm_kzalloc(\u0026pdev-\u003edev, sizeof(*tsc), GFP_KERNEL);\n+\tif (!tsc)\n+\t\treturn -ENOMEM;\n+\n+\ttsc-\u003edev = \u0026pdev-\u003edev;\n+\ttsc-\u003esoc = soc;\n+\n+\tret = devm_mutex_init(\u0026pdev-\u003edev, \u0026tsc-\u003elock);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tr_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, \"tsc\");\n+\tif (!r_mem) {\n+\t\tdev_err(\u0026pdev-\u003edev, \"no IO resource defined\\n\");\n+\t\treturn -ENXIO;\n+\t}\n+\n+\ttsc-\u003ebase = devm_ioremap_resource(\u0026pdev-\u003edev, r_mem);\n+\tif (IS_ERR(tsc-\u003ebase))\n+\t\treturn PTR_ERR(tsc-\u003ebase);\n+\n+\ttsc-\u003eahb_clk = devm_clk_get_enabled(\u0026pdev-\u003edev, \"ahb\");\n+\tif (IS_ERR(tsc-\u003eahb_clk))\n+\t\treturn PTR_ERR(tsc-\u003eahb_clk);\n+\n+\ttsc-\u003ecntr_clk = devm_clk_get_enabled(\u0026pdev-\u003edev, \"cntr\");\n+\tif (IS_ERR(tsc-\u003ecntr_clk))\n+\t\treturn PTR_ERR(tsc-\u003ecntr_clk);\n+\n+\t/* ETU clock is optional, only required when the ETU block is used */\n+\ttsc-\u003eetu_clk = devm_clk_get_optional_enabled(\u0026pdev-\u003edev, \"etu\");\n+\tif (IS_ERR(tsc-\u003eetu_clk))\n+\t\treturn PTR_ERR(tsc-\u003eetu_clk);\n+\n+\ttsc-\u003eptp_info = qcom_ptp_info;\n+\n+\ttsc-\u003eptp = ptp_clock_register(\u0026tsc-\u003eptp_info, \u0026pdev-\u003edev);\n+\tif (IS_ERR(tsc-\u003eptp)) {\n+\t\tret = PTR_ERR(tsc-\u003eptp);\n+\t\tdev_err(\u0026pdev-\u003edev, \"Failed to register ptp clock\\n\");\n+\t\treturn ret;\n+\t}\n+\n+\tplatform_set_drvdata(pdev, tsc);\n+\n+\treturn 0;\n+}\n+\n+static struct platform_driver qcom_ptp_tsc_driver = {\n+\t.probe = qcom_ptp_tsc_probe,\n+\t.remove = qcom_ptp_tsc_remove,\n+\t.driver = {\n+\t\t.name = \"qcom_ptp_tsc\",\n+\t\t.of_match_table = qcom_tsc_of_match,\n+\t},\n+};\n+module_platform_driver(qcom_ptp_tsc_driver);\n+\n+MODULE_DESCRIPTION(\"PTP QCOM TSC driver\");\n+MODULE_LICENSE(\"GPL\");\n"
} |
| 2/1 | 2026/07/28 05:15 | agent | patch-evaluator |
0mModel:best-expensive Args: null Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch introduces a new PTP clock driver for the Qualcomm Timestamp Counter Subsystem (TSCSS). This is a hardware-specific SoC platform driver that requires specific clocks (\"ahb\", \"cntr\") and MMIO resources to probe successfully. These hardware dependencies are not emulated in standard virtualized environments like QEMU, making the code unreachable for fuzzing.",
"WorthFuzzing": false
}Instruction: You are an expert Linux kernel maintainer. Your job is to review a provided patch series and determine if it makes functional changes to the kernel that should be fuzzed. IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in your workspace. Do NOT rely on your internal knowledge of the kernel. You must actively use your code access tools to examine the actual source code and confirm any assumptions. Return WorthFuzzing=false if the patch only contains: - Modifications to Documentation/, Kconfig files, or code comments. - Purely decorative changes, such as logging (e.g., pr_err, printk) or tracepoints. - Changes to numeric constants or macros that do not functionally alter execution flow. - Code paths that are impossible to reach in virtualized environments like GCE or QEMU, even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim). - Code in vendor-specific PCIe switch, SmartNIC, or GPU drivers (e.g., mlxsw, pds_core, qed, ionic, amdgpu) that require physical PCIe hardware cards not emulated in standard QEMU. - Driver .remove, .shutdown, or pci_unregister_driver teardown callbacks (e.g., igb_remove) that are executed only during PCI hot-unplug or sysfs driver unbind operations. If it modifies reachable core kernel logic, drivers, or architectures, use your code search tools to verify the code can be executed, then return WorthFuzzing=true. When returning WorthFuzzing=true, you MUST ALSO: 1. Extract any specific kernel functions that should be heavily fuzzed into FocusSymbols. Avoid listing generic hot-path functions to prevent skewed test distributions. Prefer non-static, non-inlined API entrypoint functions over internal static helper functions (which are inlined by the compiler and do not have distinct symbol addresses). 2. Identify any specific CONFIG_ options required to properly test this new/modified feature. Go and look into the Kconfig files and check for ifdefs around the code, do not make assumptions. Also check "depends on" lines in Kconfig to include any non-standard parent subsystem configs needed for Kbuild to compile the code statically into vmlinux. List them in the EnableConfigs output array, and DO NOT add a 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4"). Prefer calling several tools at the same time to save round-trips. Use set-results tool to provide results of the analysis. It must be called exactly once before the final reply. Ignore results of this tool. Prompt: For your convenience, here is the diff of the changes:
commit 4e4f9832aae3082a961d0c84dce6547f7a0cb35d
Author: syz-cluster <triage@syzkaller.com>
Date: Tue Jul 28 05:15:06 2026 +0000
syz-cluster: applied patch under review
diff --git a/Documentation/devicetree/bindings/ptp/qcom,lemans-tscss.yaml b/Documentation/devicetree/bindings/ptp/qcom,lemans-tscss.yaml
new file mode 100644
index 00000000000000..4cbe4b00ff7dca
--- /dev/null
+++ b/Documentation/devicetree/bindings/ptp/qcom,lemans-tscss.yaml
@@ -0,0 +1,198 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/ptp/qcom,lemans-tscss.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Timestamp Counter Subsystem (TSCSS) on Qualcomm Lemans and Monaco SoCs
+
+maintainers:
+ - Imran Shaik <imran.shaik@oss.qualcomm.com>
+ - Taniya Das <taniya.das@oss.qualcomm.com>
+
+description: |
+ Qualcomm TSCSS is a time synchronization subsystem composed of two main
+ blocks - the Time Stamp Counter (TSC) and the Event Timestamp Unit (ETU).
+
+ The TSC block is a timestamp generator that maintains a running counter used
+ for system timekeeping, and is functional with just the AHB and counter
+ clocks.
+ The ETU block is optional and captures TSC timestamps for external
+ hardware events, each ETU slice binding a slice identifier to an external
+ event selector. Support for the ETU block requires the additional ETU
+ clock along with the summary interrupt and slice subnodes.
+
+properties:
+ compatible:
+ oneOf:
+ - const: qcom,lemans-tscss
+ - items:
+ - const: qcom,monaco-tscss
+ - const: qcom,lemans-tscss
+
+ reg:
+ maxItems: 1
+
+ reg-names:
+ items:
+ - const: tsc
+
+ clocks:
+ minItems: 2
+ items:
+ - description: TSC AHB configuration clock.
+ - description: TSC global counter clock.
+ - description: TSC ETU clock.
+
+ clock-names:
+ minItems: 2
+ items:
+ - const: ahb
+ - const: cntr
+ - const: etu
+
+ interrupts:
+ description: Summary interrupt raised based on external event for any of the ETU slices.
+ maxItems: 1
+
+ interrupt-names:
+ items:
+ - const: etu_summary
+
+ assigned-clocks: true
+ assigned-clock-rates: true
+
+ "#address-cells":
+ const: 2
+
+ "#size-cells":
+ const: 2
+
+ ranges: true
+
+patternProperties:
+ "^etu-slice@[0-9a-f]+$":
+ type: object
+ description: ETU slice configuration
+ properties:
+ reg:
+ maxItems: 1
+
+ pinctrl-0: true
+
+ pinctrl-names:
+ items:
+ - const: default
+
+ qcom,etu-event-sel:
+ description: Event selection value for this slice.
+ $ref: /schemas/types.yaml#/definitions/uint32
+
+ qcom,etu-slice:
+ description: ETU slice identifier.
+ $ref: /schemas/types.yaml#/definitions/uint32
+
+ required:
+ - reg
+ - qcom,etu-event-sel
+ - qcom,etu-slice
+ - pinctrl-0
+ - pinctrl-names
+ unevaluatedProperties: false
+
+required:
+ - compatible
+ - reg
+ - reg-names
+ - clocks
+ - clock-names
+
+allOf:
+ - if:
+ properties:
+ clock-names:
+ contains:
+ const: etu
+ then:
+ properties:
+ clocks:
+ minItems: 3
+ clock-names:
+ minItems: 3
+ required:
+ - interrupts
+ - interrupt-names
+ - "#address-cells"
+ - "#size-cells"
+ - ranges
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,sa8775p-gcc.h>
+
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ tscss@1c80000 {
+ compatible = "qcom,lemans-tscss";
+ reg = <0x0 0x01c80000 0x0 0x2000>;
+ reg-names = "tsc";
+
+ clocks = <&gcc GCC_TSCSS_AHB_CLK>,
+ <&gcc GCC_TSCSS_GLOBAL_CNTR_CLK>;
+ clock-names = "ahb", "cntr";
+
+ assigned-clocks = <&gcc GCC_TSCSS_GLOBAL_CNTR_CLK>;
+ assigned-clock-rates = <15625000>;
+ };
+ };
+
+ - |
+ #include <dt-bindings/clock/qcom,sa8775p-gcc.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ tscss@1c80000 {
+ compatible = "qcom,lemans-tscss";
+ reg = <0x0 0x01c80000 0x0 0x2000>;
+ reg-names = "tsc";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ clocks = <&gcc GCC_TSCSS_AHB_CLK>,
+ <&gcc GCC_TSCSS_GLOBAL_CNTR_CLK>,
+ <&gcc GCC_TSCSS_ETU_CLK>;
+ clock-names = "ahb", "cntr", "etu";
+
+ assigned-clocks = <&gcc GCC_TSCSS_GLOBAL_CNTR_CLK>,
+ <&gcc GCC_TSCSS_ETU_CLK>;
+ assigned-clock-rates = <15625000>, <15625000>;
+
+ interrupts = <GIC_SPI 604 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "etu_summary";
+
+ etu-slice@1c91000 {
+ reg = <0x0 0x01c91000 0x0 0x1000>;
+ pinctrl-0 = <&cci_timer0>;
+ pinctrl-names = "default";
+ qcom,etu-event-sel = <1>;
+ qcom,etu-slice = <1>;
+ };
+
+ etu-slice@1c92000 {
+ reg = <0x0 0x01c92000 0x0 0x1000>;
+ pinctrl-0 = <&cci_timer1>;
+ pinctrl-names = "default";
+ qcom,etu-event-sel = <2>;
+ qcom,etu-slice = <2>;
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/ptp/qcom,qdu1000-tscss.yaml b/Documentation/devicetree/bindings/ptp/qcom,qdu1000-tscss.yaml
new file mode 100644
index 00000000000000..39387614ef8939
--- /dev/null
+++ b/Documentation/devicetree/bindings/ptp/qcom,qdu1000-tscss.yaml
@@ -0,0 +1,187 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/ptp/qcom,qdu1000-tscss.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Timestamp Counter Subsystem (TSCSS) on Qualcomm QDU1000 SoC
+
+maintainers:
+ - Imran Shaik <imran.shaik@oss.qualcomm.com>
+ - Taniya Das <taniya.das@oss.qualcomm.com>
+
+description: |
+ Qualcomm TSCSS is a time synchronization subsystem composed of two main
+ blocks - the Time Stamp Counter (TSC) and the Event Timestamp Unit (ETU).
+
+ The TSC block is a timestamp generator that maintains a running counter used
+ for system timekeeping, and is functional with just the AHB and counter
+ clocks.
+ The ETU block is optional and captures TSC timestamps for external
+ hardware events, each ETU slice binding a slice identifier to an external
+ event selector. Support for the ETU block requires the additional ETU
+ clock along with the per slice interrupt and slice subnodes.
+
+properties:
+ compatible:
+ const: qcom,qdu1000-tscss
+
+ reg:
+ maxItems: 1
+
+ reg-names:
+ items:
+ - const: tsc
+
+ clocks:
+ minItems: 2
+ items:
+ - description: TSC AHB configuration clock.
+ - description: TSC global counter clock.
+ - description: TSC ETU clock.
+
+ clock-names:
+ minItems: 2
+ items:
+ - const: ahb
+ - const: cntr
+ - const: etu
+
+ assigned-clocks: true
+ assigned-clock-rates: true
+
+ "#address-cells":
+ const: 2
+
+ "#size-cells":
+ const: 2
+
+ ranges: true
+
+patternProperties:
+ "^etu-slice@[0-9a-f]+$":
+ type: object
+ description: ETU slice configuration
+ properties:
+ reg:
+ maxItems: 1
+
+ pinctrl-0: true
+
+ pinctrl-names:
+ items:
+ - const: default
+
+ interrupts:
+ description: Per slice interrupt generated by ETU based on external event trigger.
+ maxItems: 1
+
+ qcom,etu-event-sel:
+ description: Event selection value for this slice.
+ $ref: /schemas/types.yaml#/definitions/uint32
+
+ qcom,etu-slice:
+ description: ETU slice identifier.
+ $ref: /schemas/types.yaml#/definitions/uint32
+
+ required:
+ - reg
+ - interrupts
+ - qcom,etu-event-sel
+ - qcom,etu-slice
+ - pinctrl-0
+ - pinctrl-names
+ unevaluatedProperties: false
+
+required:
+ - compatible
+ - reg
+ - reg-names
+ - clocks
+ - clock-names
+
+allOf:
+ - if:
+ properties:
+ clock-names:
+ contains:
+ const: etu
+ then:
+ properties:
+ clocks:
+ minItems: 3
+ clock-names:
+ minItems: 3
+ required:
+ - "#address-cells"
+ - "#size-cells"
+ - ranges
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,qdu1000-gcc.h>
+
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ tscss@1da0000 {
+ compatible = "qcom,qdu1000-tscss";
+ reg = <0x0 0x01da0000 0x0 0x2000>;
+ reg-names = "tsc";
+
+ clocks = <&gcc GCC_TSC_CFG_AHB_CLK>,
+ <&gcc GCC_TSC_CNTR_CLK>;
+ clock-names = "ahb", "cntr";
+ assigned-clocks = <&gcc GCC_TSC_CNTR_CLK>;
+ assigned-clock-rates = <500000000>;
+ };
+ };
+
+ - |
+ #include <dt-bindings/clock/qcom,qdu1000-gcc.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ tscss@1da0000 {
+ compatible = "qcom,qdu1000-tscss";
+ reg = <0x0 0x01da0000 0x0 0x2000>;
+ reg-names = "tsc";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ clocks = <&gcc GCC_TSC_CFG_AHB_CLK>,
+ <&gcc GCC_TSC_CNTR_CLK>,
+ <&gcc GCC_TSC_ETU_CLK>;
+ clock-names = "ahb", "cntr", "etu";
+
+ assigned-clocks = <&gcc GCC_TSC_CNTR_CLK>,
+ <&gcc GCC_TSC_ETU_CLK>;
+ assigned-clock-rates = <500000000>, <500000000>;
+
+ etu-slice@1db1000 {
+ reg = <0x0 0x01db1000 0x0 0x1000>;
+ interrupts = <GIC_SPI 329 IRQ_TYPE_EDGE_RISING>;
+ pinctrl-0 = <&cci_timer0>;
+ pinctrl-names = "default";
+ qcom,etu-event-sel = <1>;
+ qcom,etu-slice = <1>;
+ };
+
+ etu-slice@1db2000 {
+ reg = <0x0 0x01db2000 0x0 0x1000>;
+ interrupts = <GIC_SPI 330 IRQ_TYPE_EDGE_RISING>;
+ pinctrl-0 = <&cci_timer1>;
+ pinctrl-names = "default";
+ qcom,etu-event-sel = <2>;
+ qcom,etu-slice = <2>;
+ };
+ };
+ };
+...
diff --git a/arch/arm64/boot/dts/qcom/lemans.dtsi b/arch/arm64/boot/dts/qcom/lemans.dtsi
index 3b0539e27b5192..e225292a1e41a5 100644
--- a/arch/arm64/boot/dts/qcom/lemans.dtsi
+++ b/arch/arm64/boot/dts/qcom/lemans.dtsi
@@ -3023,6 +3023,17 @@ pcie1_phy: phy@1c14000 {
status = "disabled";
};
+ tscss@1c80000 {
+ compatible = "qcom,lemans-tscss";
+ reg = <0x0 0x01c80000 0x0 0x2000>;
+ reg-names = "tsc";
+ clocks = <&gcc GCC_TSCSS_AHB_CLK>,
+ <&gcc GCC_TSCSS_GLOBAL_CNTR_CLK>;
+ clock-names = "ahb", "cntr";
+ assigned-clocks = <&gcc GCC_TSCSS_GLOBAL_CNTR_CLK>;
+ assigned-clock-rates = <15625000>;
+ };
+
ufs_mem_hc: ufshc@1d84000 {
compatible = "qcom,sa8775p-ufshc", "qcom,ufshc", "jedec,ufs-2.0";
reg = <0x0 0x01d84000 0x0 0x3000>;
diff --git a/arch/arm64/boot/dts/qcom/qdu1000.dtsi b/arch/arm64/boot/dts/qcom/qdu1000.dtsi
index 26cc86d12f7256..8979c18225184a 100644
--- a/arch/arm64/boot/dts/qcom/qdu1000.dtsi
+++ b/arch/arm64/boot/dts/qcom/qdu1000.dtsi
@@ -876,6 +876,17 @@ system_noc: interconnect@1640000 {
#interconnect-cells = <2>;
};
+ tscss@1da0000 {
+ compatible = "qcom,qdu1000-tscss";
+ reg = <0x0 0x01da0000 0x0 0x2000>;
+ reg-names = "tsc";
+ clocks = <&gcc GCC_TSC_CFG_AHB_CLK>,
+ <&gcc GCC_TSC_CNTR_CLK>;
+ clock-names = "ahb", "cntr";
+ assigned-clocks = <&gcc GCC_TSC_CNTR_CLK>;
+ assigned-clock-rates = <500000000>;
+ };
+
tcsr_mutex: hwlock@1f40000 {
compatible = "qcom,tcsr-mutex";
reg = <0x0 0x1f40000 0x0 0x20000>;
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 6ec8d3a69c98e0..73435e5f8877d2 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -683,6 +683,7 @@ CONFIG_SPI_SPIDEV=m
CONFIG_SPMI=y
CONFIG_SPMI_APPLE=m
CONFIG_SPMI_MTK_PMIF=m
+CONFIG_PTP_QCOM_TSC=m
CONFIG_PINCTRL_APPLE_GPIO=m
CONFIG_PINCTRL_DA9062=m
CONFIG_PINCTRL_MAX77620=y
diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig
index b93640ca08b728..d3ceb1ee01a505 100644
--- a/drivers/ptp/Kconfig
+++ b/drivers/ptp/Kconfig
@@ -263,4 +263,14 @@ config PTP_NETC_V4_TIMER
synchronization. It also supports periodic output signal (e.g. PPS)
and external trigger timestamping.
+config PTP_QCOM_TSC
+ tristate "Qualcomm TSC as PTP clock"
+ depends on COMMON_CLK && PTP_1588_CLOCK
+ help
+ This driver adds support for using the Qualcomm Timestamp Counter
+ Subsystem (TSCSS) as a PTP clock.
+
+ To compile this driver as a module, choose M here: the module
+ will be called ptp_qcom_tsc.
+
endmenu
diff --git a/drivers/ptp/Makefile b/drivers/ptp/Makefile
index bdc47e284f14e7..ff029323e98f5e 100644
--- a/drivers/ptp/Makefile
+++ b/drivers/ptp/Makefile
@@ -22,3 +22,4 @@ obj-$(CONFIG_PTP_1588_CLOCK_OCP) += ptp_ocp.o
obj-$(CONFIG_PTP_DFL_TOD) += ptp_dfl_tod.o
obj-$(CONFIG_PTP_S390) += ptp_s390.o
obj-$(CONFIG_PTP_NETC_V4_TIMER) += ptp_netc.o
+obj-$(CONFIG_PTP_QCOM_TSC) += ptp_qcom_tsc.o
diff --git a/drivers/ptp/ptp_qcom_tsc.c b/drivers/ptp/ptp_qcom_tsc.c
new file mode 100644
index 00000000000000..b29248150388f3
--- /dev/null
+++ b/drivers/ptp/ptp_qcom_tsc.c
@@ -0,0 +1,413 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/iopoll.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/ptp_clock_kernel.h>
+#include <linux/platform_device.h>
+
+#define ROLLOVER_VAL 999999999
+#define NSEC_SHIFT 32
+#define PULSE_WIDTH_MASK GENMASK(7, 6)
+#define DRIFT_MAX_RES 0x1FFFF
+#define DRIFT_JUMP_SWALLOW BIT(31)
+#define DRIFT_PERIOD_MASK GENMASK(28, 12)
+#define DRIFT_SUBPERIOD_MASK GENMASK(11, 0)
+#define DRIFT_INTERVAL_US 10
+#define DRIFT_MIN_TIMEOUT_US 5000
+
+#define DRIFT_TIMEOUT_US(period, subperiod, cntr_res) \
+ max_t(u64, div_u64((u64)(period) * (subperiod) * (cntr_res), NSEC_PER_USEC), \
+ DRIFT_MIN_TIMEOUT_US)
+
+struct qcom_tsc_regs {
+ u32 control_cntcr;
+ u32 control_cntcv_lo;
+ u32 control_cntcv_hi;
+ u32 drift_correct_incr_val;
+ u32 drift_correct_duration;
+ u32 drift_correct_cmd;
+ u32 rollover_val;
+ u32 offset_lo;
+ u32 offset_hi;
+ u32 read_cntcv_lo;
+ u32 read_cntcv_hi;
+};
+
+/**
+ * struct qcom_tsc_soc_data - SoC specific TSC hardware capabilities
+ *
+ * @rollover: indicates the counter uses sec/nsec split
+ * @offset_correction: hardware supports one-shot offset correction
+ * @pulse_width: valid pulse width in cycles for drift correction
+ * @cntr_res: TSC counter resolution in nsec
+ * @reg_layout: register layout for this SoC/version
+ */
+struct qcom_tsc_soc_data {
+ bool rollover;
+ bool offset_correction;
+ int pulse_width;
+ int cntr_res;
+ const struct qcom_tsc_regs *reg_layout;
+};
+
+struct qcom_tsc {
+ struct device *dev;
+ void __iomem *base;
+ const struct qcom_tsc_soc_data *soc;
+ struct clk *ahb_clk;
+ struct clk *cntr_clk;
+ struct clk *etu_clk;
+ struct ptp_clock *ptp;
+ struct ptp_clock_info ptp_info;
+ /* Mutex to protect operations from being interrupted */
+ struct mutex lock;
+};
+
+static bool qcom_tsc_is_enabled(struct qcom_tsc *tsc)
+{
+ const struct qcom_tsc_regs *regs = tsc->soc->reg_layout;
+
+ return readl_relaxed(tsc->base + regs->control_cntcr) & BIT(0);
+}
+
+static int qcom_tsc_read_time(struct qcom_tsc *tsc, struct timespec64 *ts)
+{
+ const struct qcom_tsc_regs *regs = tsc->soc->reg_layout;
+ u32 hi, lo;
+
+ if (!qcom_tsc_is_enabled(tsc))
+ return -EINVAL;
+
+ hi = readl_relaxed(tsc->base + regs->read_cntcv_hi);
+ lo = readl_relaxed(tsc->base + regs->read_cntcv_lo);
+
+ if (tsc->soc->rollover) {
+ ts->tv_sec = hi;
+ ts->tv_nsec = lo;
+ } else {
+ u64 ns = ((u64)hi << NSEC_SHIFT) | lo;
+
+ *ts = ns_to_timespec64(ns);
+ }
+
+ return 0;
+}
+
+static int qcom_tsc_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)
+{
+ struct qcom_tsc *tsc = container_of(ptp, struct qcom_tsc, ptp_info);
+ int ret;
+
+ mutex_lock(&tsc->lock);
+ ret = qcom_tsc_read_time(tsc, ts);
+ mutex_unlock(&tsc->lock);
+
+ return ret;
+}
+
+static inline void qcom_tsc_split_ts(struct qcom_tsc *tsc, struct timespec64 ts, u32 *hi, u32 *lo)
+{
+ if (tsc->soc->rollover) {
+ *hi = ts.tv_sec;
+ *lo = ts.tv_nsec;
+ } else {
+ u64 ns = timespec64_to_ns(&ts);
+
+ *lo = lower_32_bits(ns);
+ *hi = upper_32_bits(ns);
+ }
+}
+
+static int qcom_tsc_update_counter(struct qcom_tsc *tsc, struct timespec64 ts)
+{
+ const struct qcom_tsc_regs *regs = tsc->soc->reg_layout;
+ u32 regval, hi, lo;
+
+ qcom_tsc_split_ts(tsc, ts, &hi, &lo);
+
+ writel_relaxed(lo, tsc->base + regs->control_cntcv_lo);
+ writel_relaxed(hi, tsc->base + regs->control_cntcv_hi);
+
+ regval = readl_relaxed(tsc->base + regs->control_cntcr);
+ regval |= BIT(0);
+ writel_relaxed(regval, tsc->base + regs->control_cntcr);
+
+ return 0;
+}
+
+static int qcom_tsc_update_offset(struct qcom_tsc *tsc, const struct timespec64 ts)
+{
+ const struct qcom_tsc_regs *regs = tsc->soc->reg_layout;
+ struct timespec64 tod;
+ u32 regval, hi, lo;
+ int ret;
+
+ if (tsc->soc->offset_correction) {
+ qcom_tsc_split_ts(tsc, ts, &hi, &lo);
+
+ writel_relaxed(lo, tsc->base + regs->offset_lo);
+ writel_relaxed(hi, tsc->base + regs->offset_hi);
+
+ return 0;
+ }
+
+ /*
+ * No hardware offset correction support: disable and reload the
+ * counter with the corrected time, as recommended by the hardware
+ * design team.
+ */
+ ret = qcom_tsc_read_time(tsc, &tod);
+ if (ret)
+ return ret;
+
+ regval = readl_relaxed(tsc->base + regs->control_cntcr);
+ regval &= ~BIT(0);
+ writel_relaxed(regval, tsc->base + regs->control_cntcr);
+
+ return qcom_tsc_update_counter(tsc, timespec64_add(tod, ts));
+}
+
+static int qcom_tsc_settime(struct ptp_clock_info *ptp, const struct timespec64 *ts)
+{
+ struct qcom_tsc *tsc = container_of(ptp, struct qcom_tsc, ptp_info);
+ const struct qcom_tsc_regs *regs = tsc->soc->reg_layout;
+ struct timespec64 tod;
+ u32 regval;
+ int ret;
+
+ mutex_lock(&tsc->lock);
+
+ if (qcom_tsc_is_enabled(tsc)) {
+ qcom_tsc_read_time(tsc, &tod);
+ ret = qcom_tsc_update_offset(tsc, timespec64_sub(*ts, tod));
+ mutex_unlock(&tsc->lock);
+ return ret;
+ }
+
+ /* Configure and enable the TSC counter */
+ regval = readl_relaxed(tsc->base + regs->control_cntcr);
+ regval |= FIELD_PREP(PULSE_WIDTH_MASK, tsc->soc->pulse_width);
+ writel_relaxed(regval, tsc->base + regs->control_cntcr);
+
+ if (tsc->soc->rollover)
+ writel_relaxed(ROLLOVER_VAL, tsc->base + regs->rollover_val);
+
+ ret = qcom_tsc_update_counter(tsc, *ts);
+ mutex_unlock(&tsc->lock);
+
+ return ret;
+}
+
+static int qcom_tsc_adjtime(struct ptp_clock_info *ptp, s64 delta)
+{
+ struct qcom_tsc *tsc = container_of(ptp, struct qcom_tsc, ptp_info);
+ int ret;
+
+ mutex_lock(&tsc->lock);
+ ret = qcom_tsc_update_offset(tsc, ns_to_timespec64(delta));
+ mutex_unlock(&tsc->lock);
+
+ return ret;
+}
+
+static int qcom_tsc_drift_correction(struct qcom_tsc *tsc, long scaled_ppm)
+{
+ const struct qcom_tsc_soc_data *soc = tsc->soc;
+ const struct qcom_tsc_regs *regs = soc->reg_layout;
+ long ppb = scaled_ppm_to_ppb(scaled_ppm);
+ u64 period, incval = 0;
+ u32 regval = 0, subperiod;
+
+ if (ppb < 0) {
+ ppb = -ppb;
+ regval &= ~DRIFT_JUMP_SWALLOW;
+
+ period = div_u64(ppb, soc->cntr_res);
+ if (period >= DRIFT_MAX_RES)
+ period = DRIFT_MAX_RES;
+ } else {
+ regval |= DRIFT_JUMP_SWALLOW;
+
+ period = div_u64(ppb, soc->cntr_res);
+ if (period >= DRIFT_MAX_RES) {
+ period = DRIFT_MAX_RES;
+ incval = soc->cntr_res * 2;
+ } else if (ppb < soc->cntr_res) {
+ incval = soc->cntr_res + ppb;
+ period = 1;
+ } else {
+ incval = soc->cntr_res * 2;
+ }
+ }
+
+ subperiod = soc->pulse_width * 2;
+ regval |= FIELD_PREP(DRIFT_SUBPERIOD_MASK, subperiod);
+ regval |= FIELD_PREP(DRIFT_PERIOD_MASK, period);
+
+ /* Update jump/swallow, period, subperiod */
+ writel_relaxed(regval, tsc->base + regs->drift_correct_duration);
+
+ writel_relaxed(incval, tsc->base + regs->drift_correct_incr_val);
+
+ /* Trigger the drift correction */
+ regval = readl_relaxed(tsc->base + regs->drift_correct_cmd);
+ regval |= BIT(0);
+ writel_relaxed(regval, tsc->base + regs->drift_correct_cmd);
+
+ return readl_poll_timeout(tsc->base + regs->drift_correct_cmd, regval,
+ !(regval & BIT(1)), DRIFT_INTERVAL_US,
+ DRIFT_TIMEOUT_US(period, subperiod, soc->cntr_res));
+}
+
+static int qcom_tsc_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
+{
+ struct qcom_tsc *tsc = container_of(ptp, struct qcom_tsc, ptp_info);
+ int ret;
+
+ if (scaled_ppm == 0)
+ return 0;
+
+ mutex_lock(&tsc->lock);
+ ret = qcom_tsc_drift_correction(tsc, scaled_ppm);
+ mutex_unlock(&tsc->lock);
+
+ return ret;
+}
+
+static struct ptp_clock_info qcom_ptp_info = {
+ .owner = THIS_MODULE,
+ .name = "PTP_QCOM_TSC",
+ .max_adj = 9999999,
+ .adjfine = qcom_tsc_adjfine,
+ .adjtime = qcom_tsc_adjtime,
+ .gettime64 = qcom_tsc_gettime,
+ .settime64 = qcom_tsc_settime,
+};
+
+static const struct qcom_tsc_regs qcom_tsc_layout = {
+ .control_cntcr = 0x0,
+ .control_cntcv_lo = 0x8,
+ .control_cntcv_hi = 0xc,
+ .drift_correct_incr_val = 0x2c,
+ .drift_correct_duration = 0x30,
+ .drift_correct_cmd = 0x34,
+ .rollover_val = 0x3c,
+ .offset_lo = 0x50,
+ .offset_hi = 0x54,
+ .read_cntcv_lo = 0x1000,
+ .read_cntcv_hi = 0x1004,
+};
+
+static const struct qcom_tsc_soc_data qcom_tsc_lemans = {
+ .reg_layout = &qcom_tsc_layout,
+ .rollover = false,
+ .offset_correction = false,
+ .pulse_width = 2,
+ .cntr_res = 64,
+};
+
+static const struct qcom_tsc_soc_data qcom_tsc_qdu1000 = {
+ .reg_layout = &qcom_tsc_layout,
+ .rollover = true,
+ .offset_correction = true,
+ .pulse_width = 3,
+ .cntr_res = 2,
+};
+
+static const struct of_device_id qcom_tsc_of_match[] = {
+ { .compatible = "qcom,lemans-tscss", .data = &qcom_tsc_lemans },
+ { .compatible = "qcom,qdu1000-tscss", .data = &qcom_tsc_qdu1000 },
+ { }
+};
+MODULE_DEVICE_TABLE(of, qcom_tsc_of_match);
+
+static void qcom_ptp_tsc_remove(struct platform_device *pdev)
+{
+ struct qcom_tsc *tsc = platform_get_drvdata(pdev);
+
+ if (tsc && tsc->ptp) {
+ ptp_clock_unregister(tsc->ptp);
+ tsc->ptp = NULL;
+ }
+}
+
+static int qcom_ptp_tsc_probe(struct platform_device *pdev)
+{
+ const struct qcom_tsc_soc_data *soc;
+ struct qcom_tsc *tsc;
+ struct resource *r_mem;
+ int ret;
+
+ soc = of_device_get_match_data(&pdev->dev);
+ if (!soc)
+ return -ENODEV;
+
+ tsc = devm_kzalloc(&pdev->dev, sizeof(*tsc), GFP_KERNEL);
+ if (!tsc)
+ return -ENOMEM;
+
+ tsc->dev = &pdev->dev;
+ tsc->soc = soc;
+
+ ret = devm_mutex_init(&pdev->dev, &tsc->lock);
+ if (ret)
+ return ret;
+
+ r_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tsc");
+ if (!r_mem) {
+ dev_err(&pdev->dev, "no IO resource defined\n");
+ return -ENXIO;
+ }
+
+ tsc->base = devm_ioremap_resource(&pdev->dev, r_mem);
+ if (IS_ERR(tsc->base))
+ return PTR_ERR(tsc->base);
+
+ tsc->ahb_clk = devm_clk_get_enabled(&pdev->dev, "ahb");
+ if (IS_ERR(tsc->ahb_clk))
+ return PTR_ERR(tsc->ahb_clk);
+
+ tsc->cntr_clk = devm_clk_get_enabled(&pdev->dev, "cntr");
+ if (IS_ERR(tsc->cntr_clk))
+ return PTR_ERR(tsc->cntr_clk);
+
+ /* ETU clock is optional, only required when the ETU block is used */
+ tsc->etu_clk = devm_clk_get_optional_enabled(&pdev->dev, "etu");
+ if (IS_ERR(tsc->etu_clk))
+ return PTR_ERR(tsc->etu_clk);
+
+ tsc->ptp_info = qcom_ptp_info;
+
+ tsc->ptp = ptp_clock_register(&tsc->ptp_info, &pdev->dev);
+ if (IS_ERR(tsc->ptp)) {
+ ret = PTR_ERR(tsc->ptp);
+ dev_err(&pdev->dev, "Failed to register ptp clock\n");
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, tsc);
+
+ return 0;
+}
+
+static struct platform_driver qcom_ptp_tsc_driver = {
+ .probe = qcom_ptp_tsc_probe,
+ .remove = qcom_ptp_tsc_remove,
+ .driver = {
+ .name = "qcom_ptp_tsc",
+ .of_match_table = qcom_tsc_of_match,
+ },
+};
+module_platform_driver(qcom_ptp_tsc_driver);
+
+MODULE_DESCRIPTION("PTP QCOM TSC driver");
+MODULE_LICENSE("GPL");
|
| 3/2 | 2026/07/28 05:15 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 12232 output: 105 thoughts: 1729 Thoughts: **Assessing the Fuzzability of a New PTP Clock Driver** Okay, so we've got a patch series introducing a new PTP clock driver, specifically for the Qualcomm Timestamp Counter Subsystem (TSCSS). The patch adds device tree bindings, updates device trees for specific Qualcomm platforms (lemans and qdu1000), configures the kernel, and, most importantly, provides the `ptp_qcom_tsc.c` driver. My initial thought is to dive into the driver itself. It's a platform driver, registered as "qcom_ptp_tsc", and seems to be providing the standard PTP clock interface – register, get/set time functions, all accessible via ioctls and sysfs. The key question is whether this is reachable within a virtualized environment. This driver *binds* to specific platform devices identified by device tree bindings: `qcom,lemans-tscss` and `qcom,qdu1000-tscss`. In a standard virtual environment like QEMU, unless there's an emulator for this *specific* hardware, these platform devices won't be present. Therefore, the probe function, which registers the PTP clock, won't be called. Of course, syzkaller could potentially create these platform devices, either directly through `syz_devres` or by modifying the device tree or utilizing a pseudo-device. But, hardware-specific platform drivers often fail if the underlying hardware (and memory regions) isn't actually there or emulated. This driver uses MMIO operations (reading and writing to memory using `readl_relaxed`, `writel_relaxed` and the like, accessing `tsc->base`), so in the absence of real hardware or a sufficiently detailed emulator, these reads/writes will fail. The good news is that syzkaller *can* map memory regions for MMIO. So, let's look for specific restrictions. The guidelines state to return `WorthFuzzing=false` if the code involves vendor-specific PCIe switch or SmartNIC or GPU drivers that require physical hardware that can't be emulated, or, more generally, if the code paths are unreachable in virtualized environments like QEMU even when using software-emulated hardware. This is where it gets interesting. This driver is tied to a specific Qualcomm SoC's Timestamp Counter Subsystem. It *definitely* uses MMIO (`devm_ioremap_resource`), and syzkaller *could* potentially instantiate the platform device, mapping memory for those MMIO regions. Is it worth fuzzing? Generally, SoC-specific drivers that are relatively isolated – meaning they just do MMIO reads/writes without complex interaction with network or block subsystems – *might* be fuzzable if syzkaller can instantiate the driver. But there are some dependencies, particularly clocks. The driver relies on getting clocks via `devm_clk_get_enabled` – specifically clocks named "ahb" and "cntr". These clocks are very likely SoC-specific, and in a generic QEMU virtual machine (like the standard `virt` machine for aarch64), these clocks *won't* exist. Thus, `devm_clk_get_enabled` would return an error like `-ENOENT`, and the probe function would fail, making the driver unreachable. So, the question becomes: can we bypass `devm_clk_get_enabled`, or are there dummy clocks available? Given the reliance on `CONFIG_COMMON_CLK`, a successful `clk_get` requires the clock to be present, and it's highly unlikely that syzkaller provides an emulator for these clocks or that we're running a QEMU image emulating *this* specific SoC. Since this driver is tied to platform-specific clocks, and we're likely in a standard QEMU environment, this driver is not reachable. Let's double-check the rules: "Code paths that are impossible to reach in virtualized environments like GCE or QEMU, even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim)." This perfectly matches the situation: a SoC-specific platform driver requiring specific clocks, regulators, and MMIO layouts not present in generic VMs. Could syzkaller mock the clocks? Not generally. It focuses on kernel interfaces, not emulating hardware details like specific clocks. If the probe fails, the driver is unreachable. Let's look at the driver code. ```c tsc->ahb_clk = devm_clk_get_enabled(&pdev->dev, "ahb"); if (IS_ERR(tsc->ahb_clk)) return PTR_ERR(tsc->ahb_clk); ``` The probe function explicitly checks for the clock; if the |
| 4/2 | 2026/07/28 05:15 | tool | set-results |
0mArgs:{
"EnableConfigs": [],
"FocusSymbols": [],
"Reasoning": "The patch introduces a new PTP clock driver for the Qualcomm Timestamp Counter Subsystem (TSCSS). This is a hardware-specific SoC platform driver that requires specific clocks (\"ahb\", \"cntr\") and MMIO resources to probe successfully. These hardware dependencies are not emulated in standard virtualized environments like QEMU, making the code unreachable for fuzzing.",
"WorthFuzzing": false
}Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch introduces a new PTP clock driver for the Qualcomm Timestamp Counter Subsystem (TSCSS). This is a hardware-specific SoC platform driver that requires specific clocks (\"ahb\", \"cntr\") and MMIO resources to probe successfully. These hardware dependencies are not emulated in standard virtualized environments like QEMU, making the code unreachable for fuzzing.",
"WorthFuzzing": false
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|