linux-usb.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 0/4] usb: typec: tps6598x: Add IRQ flag and register tracing
@ 2021-02-15 11:46 Guido Günther
  2021-02-15 11:46 ` [PATCH v3 1/4] usb: typec: tps6598x: Add trace event for IRQ events Guido Günther
                   ` (3 more replies)
  0 siblings, 4 replies; 9+ messages in thread
From: Guido Günther @ 2021-02-15 11:46 UTC (permalink / raw)
  To: Heikki Krogerus, Greg Kroah-Hartman, linux-kernel, linux-usb


This series adds tracing events for the chips IRQ and registers that are useful
to figure out the current data and power status. This came about since
diagnosing why a certain usb-c hub or dp-alt-mode adapter fails is hard with
the information in /sys/class/typec alone since this does not have a timeline
of events (and we don't want every typec user having to also buy a PD
analyzer). With this series debugging these kinds of things starts to become
fun:

   # echo 1 > /sys/kernel/debug/tracing/events/tps6598x/enable
   # cat /sys/kernel/debug/tracing/trace_pipe
   irq/79-0-003f-526     [003] ....   512.717871: tps6598x_irq: event1=PLUG_EVENT|DATA_STATUS_UPDATE|STATUS_UPDATE, event2=
   irq/79-0-003f-526     [003] ....   512.722408: tps6598x_status: conn: conn-Ra, pp_5v0: off, pp_hv: off, pp_ext: off, pp_cable: off, pwr-src: vin-3p3, vbus: vSafe0V, usb-host: no, legacy: no, flags: PLUG_PRESENT|PORTROLE|DATAROLE
   irq/79-0-003f-526     [003] ....   512.727127: tps6598x_data_status: DATA_CONNECTION|USB2_CONNECTION|USB3_CONNECTION
   irq/79-0-003f-526     [003] ....   512.769571: tps6598x_irq: event1=PP_SWITCH_CHANGED|STATUS_UPDATE, event2=
   irq/79-0-003f-526     [003] ....   512.773380: tps6598x_status: conn: conn-Ra, pp_5v0: out, pp_hv: off, pp_ext: off, pp_cable: in, pwr-src: vin-3p3, vbus: vSafe0V, usb-host: no, legacy: no, flags: PLUG_PRESENT|PORTROLE|DATAROLE|VCONN
   irq/79-0-003f-526     [003] ....   512.872450: tps6598x_irq: event1=POWER_STATUS_UPDATE|PD_STATUS_UPDATE, event2=
   irq/79-0-003f-526     [003] ....   512.876311: tps6598x_status: conn: conn-Ra, pp_5v0: out, pp_hv: off, pp_ext: off, pp_cable: in, pwr-src: vin-3p3, vbus: vSafe0V, usb-host: no, legacy: no, flags: PLUG_PRESENT|PORTROLE|DATAROLE|VCONN
   irq/79-0-003f-526     [003] ....   512.880237: tps6598x_power_status: conn: 1, pwr-role: source, typec: usb, bc: sdp
   irq/79-0-003f-526     [003] ....   513.072682: tps6598x_irq: event1=STATUS_UPDATE, event2=
   irq/79-0-003f-526     [003] ....   513.076390: tps6598x_status: conn: conn-Ra, pp_5v0: out, pp_hv: off, pp_ext: off, pp_cable: in, pwr-src: vin-3p3, vbus: vSafe5V, usb-host: no, legacy: no, flags: PLUG_PRESENT|PORTROLE|DATAROLE|VCONN
   irq/79-0-003f-526     [003] ....   513.090676: tps6598x_irq: event1=ERROR_CANNOT_PROVIDE_PWR, event2=
   irq/79-0-003f-526     [003] ....   513.094368: tps6598x_status: conn: conn-Ra, pp_5v0: out, pp_hv: off, pp_ext: off, pp_cable: in, pwr-src: vin-3p3, vbus: vSafe5V, usb-host: no, legacy: no, flags: PLUG_PRESENT|PORTROLE|DATAROLE|VCONN
   irq/79-0-003f-526     [003] ....   513.109606: tps6598x_irq: event1=NEW_CONTRACT_AS_PROVIDER|POWER_STATUS_UPDATE|STATUS_UPDATE|SRC_TRANSITION, event2=
   irq/79-0-003f-526     [003] ....   513.113777: tps6598x_status: conn: conn-Ra, pp_5v0: out, pp_hv: off, pp_ext: off, pp_cable: in, pwr-src: vin-3p3, vbus: pd, usb-host: no, legacy: no, flags: PLUG_PRESENT|PORTROLE|DATAROLE|VCONN
   irq/79-0-003f-526     [003] ....   513.117475: tps6598x_power_status: conn: 1, pwr-role: source, typec: pd, bc: sdp
   irq/79-0-003f-526     [003] ....   513.137469: tps6598x_irq: event1=VDM_RECEIVED, event2=
   irq/79-0-003f-526     [003] ....   513.141570: tps6598x_status: conn: conn-Ra, pp_5v0: out, pp_hv: off, pp_ext: off, pp_cable: in, pwr-src: vin-3p3, vbus: pd, usb-host: no, legacy: no, flags: PLUG_PRESENT|PORTROLE|DATAROLE|VCONN
   irq/79-0-003f-526     [003] ....   513.281926: tps6598x_irq: event1=VDM_RECEIVED, event2=
   irq/79-0-003f-526     [003] ....   513.285638: tps6598x_status: conn: conn-Ra, pp_5v0: out, pp_hv: off, pp_ext: off, pp_cable: in, pwr-src: vin-3p3, vbus: pd, usb-host: no, legacy: no, flags: PLUG_PRESENT|PORTROLE|DATAROLE|VCONN
   irq/79-0-003f-526     [003] ....   513.300515: tps6598x_irq: event1=VDM_RECEIVED|DATA_STATUS_UPDATE, event2=
   irq/79-0-003f-526     [003] ....   513.304226: tps6598x_status: conn: conn-Ra, pp_5v0: out, pp_hv: off, pp_ext: off, pp_cable: in, pwr-src: vin-3p3, vbus: pd, usb-host: no, legacy: no, flags: PLUG_PRESENT|PORTROLE|DATAROLE|VCONN
   irq/79-0-003f-526     [003] ....   513.308302: tps6598x_data_status: DATA_CONNECTION|USB2_CONNECTION|USB3_CONNECTION|DP_CONNECTION, DP pinout D

It should not impose any problems for firmwares that don't have IRQs for the
registers enabled. The trace will then just be missing those events.

Patch is against next-20210210.

changes from v1:
- Fix issues on 32bit arches and missing include spotted by kbuild
  (build testes on mips)
  https://lore.kernel.org/linux-usb/202102120644.IXu75GmJ-lkp@intel.com/
  https://lore.kernel.org/linux-usb/202102120159.Lyh8AGhQ-lkp@intel.com/

changes from v2:
- Reduce macro expansion size by using a custom FIELD_GET. This
  avoids a sparse warning.
  https://lore.kernel.org/linux-usb/20210213031237.GP219708@shao2-debian/

Guido Günther (4):
  usb: typec: tps6598x: Add trace event for IRQ events
  usb: typec: tps6598x: Add trace event for status register
  usb: typec: tps6598x: Add trace event for power status register
  usb: typec: tps6598x: Add trace event for data status

 drivers/usb/typec/Makefile         |   3 +
 drivers/usb/typec/tps6598x.c       |  66 ++++---
 drivers/usb/typec/tps6598x.h       | 189 +++++++++++++++++++
 drivers/usb/typec/tps6598x_trace.h | 283 +++++++++++++++++++++++++++++
 4 files changed, 515 insertions(+), 26 deletions(-)
 create mode 100644 drivers/usb/typec/tps6598x.h
 create mode 100644 drivers/usb/typec/tps6598x_trace.h

-- 
2.30.0


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v3 1/4] usb: typec: tps6598x: Add trace event for IRQ events
  2021-02-15 11:46 [PATCH v3 0/4] usb: typec: tps6598x: Add IRQ flag and register tracing Guido Günther
@ 2021-02-15 11:46 ` Guido Günther
  2021-03-01 15:09   ` Heikki Krogerus
  2021-02-15 11:46 ` [PATCH v3 2/4] usb: typec: tps6598x: Add trace event for status register Guido Günther
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 9+ messages in thread
From: Guido Günther @ 2021-02-15 11:46 UTC (permalink / raw)
  To: Heikki Krogerus, Greg Kroah-Hartman, linux-kernel, linux-usb

Allow to get irq event information via the tracing framework.  This
allows to inspect USB-C negotiation at runtime.

Signed-off-by: Guido Günther <agx@sigxcpu.org>
---
 drivers/usb/typec/Makefile         |  3 +
 drivers/usb/typec/tps6598x.c       |  9 ++-
 drivers/usb/typec/tps6598x.h       | 64 ++++++++++++++++++++
 drivers/usb/typec/tps6598x_trace.h | 97 ++++++++++++++++++++++++++++++
 4 files changed, 170 insertions(+), 3 deletions(-)
 create mode 100644 drivers/usb/typec/tps6598x.h
 create mode 100644 drivers/usb/typec/tps6598x_trace.h

diff --git a/drivers/usb/typec/Makefile b/drivers/usb/typec/Makefile
index d03b48c4b864..27aa12129190 100644
--- a/drivers/usb/typec/Makefile
+++ b/drivers/usb/typec/Makefile
@@ -1,4 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
+# define_trace.h needs to know how to find our header
+CFLAGS_tps6598x.o		:= -I$(src)
+
 obj-$(CONFIG_TYPEC)		+= typec.o
 typec-y				:= class.o mux.o bus.o
 obj-$(CONFIG_TYPEC)		+= altmodes/
diff --git a/drivers/usb/typec/tps6598x.c b/drivers/usb/typec/tps6598x.c
index 6e6ef6317523..bc34b35e909f 100644
--- a/drivers/usb/typec/tps6598x.c
+++ b/drivers/usb/typec/tps6598x.c
@@ -6,6 +6,8 @@
  * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com>
  */
 
+#include "tps6598x.h"
+
 #include <linux/i2c.h>
 #include <linux/acpi.h>
 #include <linux/module.h>
@@ -15,6 +17,9 @@
 #include <linux/usb/typec.h>
 #include <linux/usb/role.h>
 
+#define CREATE_TRACE_POINTS
+#include "tps6598x_trace.h"
+
 /* Register offsets */
 #define TPS_REG_VID			0x00
 #define TPS_REG_MODE			0x03
@@ -32,9 +37,6 @@
 #define TPS_REG_POWER_STATUS		0x3f
 #define TPS_REG_RX_IDENTITY_SOP		0x48
 
-/* TPS_REG_INT_* bits */
-#define TPS_REG_INT_PLUG_EVENT		BIT(3)
-
 /* TPS_REG_STATUS bits */
 #define TPS_STATUS_PLUG_PRESENT		BIT(0)
 #define TPS_STATUS_ORIENTATION		BIT(4)
@@ -428,6 +430,7 @@ static irqreturn_t tps6598x_interrupt(int irq, void *data)
 		dev_err(tps->dev, "%s: failed to read events\n", __func__);
 		goto err_unlock;
 	}
+	trace_tps6598x_irq(event1, event2);
 
 	ret = tps6598x_read32(tps, TPS_REG_STATUS, &status);
 	if (ret) {
diff --git a/drivers/usb/typec/tps6598x.h b/drivers/usb/typec/tps6598x.h
new file mode 100644
index 000000000000..b83b8a6a1504
--- /dev/null
+++ b/drivers/usb/typec/tps6598x.h
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Driver for TI TPS6598x USB Power Delivery controller family
+ *
+ * Copyright (C) 2017, Intel Corporation
+ * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+ */
+
+#include <linux/bits.h>
+#include <linux/bitfield.h>
+
+#ifndef __TPS6598X_H__
+#define __TPS6598X_H__
+
+
+/* TPS_REG_INT_* bits */
+#define TPS_REG_INT_USER_VID_ALT_MODE_OTHER_VDM		BIT_ULL(27+32)
+#define TPS_REG_INT_USER_VID_ALT_MODE_ATTN_VDM		BIT_ULL(26+32)
+#define TPS_REG_INT_USER_VID_ALT_MODE_EXIT		BIT_ULL(25+32)
+#define TPS_REG_INT_USER_VID_ALT_MODE_ENTERED		BIT_ULL(24+32)
+#define TPS_REG_INT_EXIT_MODES_COMPLETE			BIT_ULL(20+32)
+#define TPS_REG_INT_DISCOVER_MODES_COMPLETE		BIT_ULL(19+32)
+#define TPS_REG_INT_VDM_MSG_SENT			BIT_ULL(18+32)
+#define TPS_REG_INT_VDM_ENTERED_MODE			BIT_ULL(17+32)
+#define TPS_REG_INT_ERROR_UNABLE_TO_SOURCE		BIT_ULL(14+32)
+#define TPS_REG_INT_SRC_TRANSITION			BIT_ULL(10+32)
+#define TPS_REG_INT_ERROR_DISCHARGE_FAILED		BIT_ULL(9+32)
+#define TPS_REG_INT_ERROR_MESSAGE_DATA			BIT_ULL(7+32)
+#define TPS_REG_INT_ERROR_PROTOCOL_ERROR		BIT_ULL(6+32)
+#define TPS_REG_INT_ERROR_MISSING_GET_CAP_MESSAGE	BIT_ULL(4+32)
+#define TPS_REG_INT_ERROR_POWER_EVENT_OCCURRED		BIT_ULL(3+32)
+#define TPS_REG_INT_ERROR_CAN_PROVIDE_PWR_LATER		BIT_ULL(2+32)
+#define TPS_REG_INT_ERROR_CANNOT_PROVIDE_PWR		BIT_ULL(1+32)
+#define TPS_REG_INT_ERROR_DEVICE_INCOMPATIBLE		BIT_ULL(0+32)
+#define TPS_REG_INT_CMD2_COMPLETE			BIT(31)
+#define TPS_REG_INT_CMD1_COMPLETE			BIT(30)
+#define TPS_REG_INT_ADC_HIGH_THRESHOLD			BIT(29)
+#define TPS_REG_INT_ADC_LOW_THRESHOLD			BIT(28)
+#define TPS_REG_INT_PD_STATUS_UPDATE			BIT(27)
+#define TPS_REG_INT_STATUS_UPDATE			BIT(26)
+#define TPS_REG_INT_DATA_STATUS_UPDATE			BIT(25)
+#define TPS_REG_INT_POWER_STATUS_UPDATE			BIT(24)
+#define TPS_REG_INT_PP_SWITCH_CHANGED			BIT(23)
+#define TPS_REG_INT_HIGH_VOLTAGE_WARNING		BIT(22)
+#define TPS_REG_INT_USB_HOST_PRESENT_NO_LONGER		BIT(21)
+#define TPS_REG_INT_USB_HOST_PRESENT			BIT(20)
+#define TPS_REG_INT_GOTO_MIN_RECEIVED			BIT(19)
+#define TPS_REG_INT_PR_SWAP_REQUESTED			BIT(17)
+#define TPS_REG_INT_SINK_CAP_MESSAGE_READY		BIT(15)
+#define TPS_REG_INT_SOURCE_CAP_MESSAGE_READY		BIT(14)
+#define TPS_REG_INT_NEW_CONTRACT_AS_PROVIDER		BIT(13)
+#define TPS_REG_INT_NEW_CONTRACT_AS_CONSUMER		BIT(12)
+#define TPS_REG_INT_VDM_RECEIVED			BIT(11)
+#define TPS_REG_INT_ATTENTION_RECEIVED			BIT(10)
+#define TPS_REG_INT_OVERCURRENT				BIT(9)
+#define TPS_REG_INT_BIST				BIT(8)
+#define TPS_REG_INT_RDO_RECEIVED_FROM_SINK		BIT(7)
+#define TPS_REG_INT_DR_SWAP_COMPLETE			BIT(5)
+#define TPS_REG_INT_PR_SWAP_COMPLETE			BIT(4)
+#define TPS_REG_INT_PLUG_EVENT				BIT(3)
+#define TPS_REG_INT_HARD_RESET				BIT(1)
+#define TPS_REG_INT_PD_SOFT_RESET			BIT(0)
+
+#endif /* __TPS6598X_H__ */
diff --git a/drivers/usb/typec/tps6598x_trace.h b/drivers/usb/typec/tps6598x_trace.h
new file mode 100644
index 000000000000..4ec96e3b2c3e
--- /dev/null
+++ b/drivers/usb/typec/tps6598x_trace.h
@@ -0,0 +1,97 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Driver for TI TPS6598x USB Power Delivery controller family
+ *
+ * Copyright (C) 2020 Purism SPC
+ * Author: Guido Günther <agx@sigxcpu.org>
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM tps6598x
+
+#if !defined(_TPS6598x_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ)
+#define _TPS6598X_TRACE_H_
+
+#include "tps6598x.h"
+
+#include <linux/stringify.h>
+#include <linux/types.h>
+#include <linux/tracepoint.h>
+
+#define show_irq_flags(flags) \
+	__print_flags_u64(flags, "|", \
+		{ TPS_REG_INT_PD_SOFT_RESET,			"PD_SOFT_RESET" }, \
+		{ TPS_REG_INT_HARD_RESET,			"HARD_RESET" }, \
+		{ TPS_REG_INT_PLUG_EVENT,			"PLUG_EVENT" }, \
+		{ TPS_REG_INT_PR_SWAP_COMPLETE,			"PR_SWAP_COMPLETE" }, \
+		{ TPS_REG_INT_DR_SWAP_COMPLETE,			"DR_SWAP_COMPLETE" }, \
+		{ TPS_REG_INT_RDO_RECEIVED_FROM_SINK,		"RDO_RECEIVED_FROM_SINK" }, \
+		{ TPS_REG_INT_BIST,				"BIST" }, \
+		{ TPS_REG_INT_OVERCURRENT,			"OVERCURRENT" }, \
+		{ TPS_REG_INT_ATTENTION_RECEIVED,		"ATTENTION_RECEIVED" }, \
+		{ TPS_REG_INT_VDM_RECEIVED,			"VDM_RECEIVED" }, \
+		{ TPS_REG_INT_NEW_CONTRACT_AS_CONSUMER,		"NEW_CONTRACT_AS_CONSUMER" }, \
+		{ TPS_REG_INT_NEW_CONTRACT_AS_PROVIDER,		"NEW_CONTRACT_AS_PROVIDER" }, \
+		{ TPS_REG_INT_SOURCE_CAP_MESSAGE_READY,		"SOURCE_CAP_MESSAGE_READY" }, \
+		{ TPS_REG_INT_SINK_CAP_MESSAGE_READY,		"SINK_CAP_MESSAGE_READY" }, \
+		{ TPS_REG_INT_PR_SWAP_REQUESTED,		"PR_SWAP_REQUESTED" }, \
+		{ TPS_REG_INT_GOTO_MIN_RECEIVED,		"GOTO_MIN_RECEIVED" }, \
+		{ TPS_REG_INT_USB_HOST_PRESENT,			"USB_HOST_PRESENT" }, \
+		{ TPS_REG_INT_USB_HOST_PRESENT_NO_LONGER,	"USB_HOST_PRESENT_NO_LONGER" }, \
+		{ TPS_REG_INT_HIGH_VOLTAGE_WARNING,		"HIGH_VOLTAGE_WARNING" }, \
+		{ TPS_REG_INT_PP_SWITCH_CHANGED,		"PP_SWITCH_CHANGED" }, \
+		{ TPS_REG_INT_POWER_STATUS_UPDATE,		"POWER_STATUS_UPDATE" }, \
+		{ TPS_REG_INT_DATA_STATUS_UPDATE,		"DATA_STATUS_UPDATE" }, \
+		{ TPS_REG_INT_STATUS_UPDATE,			"STATUS_UPDATE" }, \
+		{ TPS_REG_INT_PD_STATUS_UPDATE,			"PD_STATUS_UPDATE" }, \
+		{ TPS_REG_INT_ADC_LOW_THRESHOLD,		"ADC_LOW_THRESHOLD" }, \
+		{ TPS_REG_INT_ADC_HIGH_THRESHOLD,		"ADC_HIGH_THRESHOLD" }, \
+		{ TPS_REG_INT_CMD1_COMPLETE,			"CMD1_COMPLETE" }, \
+		{ TPS_REG_INT_CMD2_COMPLETE,			"CMD2_COMPLETE" }, \
+		{ TPS_REG_INT_ERROR_DEVICE_INCOMPATIBLE,	"ERROR_DEVICE_INCOMPATIBLE" }, \
+		{ TPS_REG_INT_ERROR_CANNOT_PROVIDE_PWR,		"ERROR_CANNOT_PROVIDE_PWR" }, \
+		{ TPS_REG_INT_ERROR_CAN_PROVIDE_PWR_LATER,	"ERROR_CAN_PROVIDE_PWR_LATER" }, \
+		{ TPS_REG_INT_ERROR_POWER_EVENT_OCCURRED,	"ERROR_POWER_EVENT_OCCURRED" }, \
+		{ TPS_REG_INT_ERROR_MISSING_GET_CAP_MESSAGE,	"ERROR_MISSING_GET_CAP_MESSAGE" }, \
+		{ TPS_REG_INT_ERROR_PROTOCOL_ERROR,		"ERROR_PROTOCOL_ERROR" }, \
+		{ TPS_REG_INT_ERROR_MESSAGE_DATA,		"ERROR_MESSAGE_DATA" }, \
+		{ TPS_REG_INT_ERROR_DISCHARGE_FAILED,		"ERROR_DISCHARGE_FAILED" }, \
+		{ TPS_REG_INT_SRC_TRANSITION,			"SRC_TRANSITION" }, \
+		{ TPS_REG_INT_ERROR_UNABLE_TO_SOURCE,		"ERROR_UNABLE_TO_SOURCE" }, \
+		{ TPS_REG_INT_VDM_ENTERED_MODE,			"VDM_ENTERED_MODE" }, \
+		{ TPS_REG_INT_VDM_MSG_SENT,			"VDM_MSG_SENT" }, \
+		{ TPS_REG_INT_DISCOVER_MODES_COMPLETE,		"DISCOVER_MODES_COMPLETE" }, \
+		{ TPS_REG_INT_EXIT_MODES_COMPLETE,		"EXIT_MODES_COMPLETE" }, \
+		{ TPS_REG_INT_USER_VID_ALT_MODE_ENTERED,	"USER_VID_ALT_MODE_ENTERED" }, \
+		{ TPS_REG_INT_USER_VID_ALT_MODE_EXIT,		"USER_VID_ALT_MODE_EXIT" }, \
+		{ TPS_REG_INT_USER_VID_ALT_MODE_ATTN_VDM,	"USER_VID_ALT_MODE_ATTN_VDM" }, \
+		{ TPS_REG_INT_USER_VID_ALT_MODE_OTHER_VDM,	"USER_VID_ALT_MODE_OTHER_VDM" })
+
+TRACE_EVENT(tps6598x_irq,
+	    TP_PROTO(u64 event1,
+		     u64 event2),
+	    TP_ARGS(event1, event2),
+
+	    TP_STRUCT__entry(
+			     __field(u64, event1)
+			     __field(u64, event2)
+			     ),
+
+	    TP_fast_assign(
+			   __entry->event1 = event1;
+			   __entry->event2 = event2;
+			   ),
+
+	    TP_printk("event1=%s, event2=%s",
+		      show_irq_flags(__entry->event1),
+		      show_irq_flags(__entry->event2))
+);
+
+#endif /* _TPS6598X_TRACE_H_ */
+
+/* This part must be outside protection */
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_FILE tps6598x_trace
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#include <trace/define_trace.h>
-- 
2.30.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v3 2/4] usb: typec: tps6598x: Add trace event for status register
  2021-02-15 11:46 [PATCH v3 0/4] usb: typec: tps6598x: Add IRQ flag and register tracing Guido Günther
  2021-02-15 11:46 ` [PATCH v3 1/4] usb: typec: tps6598x: Add trace event for IRQ events Guido Günther
@ 2021-02-15 11:46 ` Guido Günther
  2021-03-01 15:10   ` Heikki Krogerus
  2021-02-15 11:46 ` [PATCH v3 3/4] usb: typec: tps6598x: Add trace event for power " Guido Günther
  2021-02-15 11:46 ` [PATCH v3 4/4] usb: typec: tps6598x: Add trace event for data status Guido Günther
  3 siblings, 1 reply; 9+ messages in thread
From: Guido Günther @ 2021-02-15 11:46 UTC (permalink / raw)
  To: Heikki Krogerus, Greg Kroah-Hartman, linux-kernel, linux-usb

This allows to trace status information which helps to debug problems
with role switching, etc.

We don't use the generic FIELD_GET() to reduce the macro size since we
otherwise trip up sparse.

Signed-off-by: Guido Günther <agx@sigxcpu.org>
---
 drivers/usb/typec/tps6598x.c       | 26 ++++-----
 drivers/usb/typec/tps6598x.h       | 68 +++++++++++++++++++++
 drivers/usb/typec/tps6598x_trace.h | 94 ++++++++++++++++++++++++++++++
 3 files changed, 173 insertions(+), 15 deletions(-)

diff --git a/drivers/usb/typec/tps6598x.c b/drivers/usb/typec/tps6598x.c
index bc34b35e909f..559aa175f948 100644
--- a/drivers/usb/typec/tps6598x.c
+++ b/drivers/usb/typec/tps6598x.c
@@ -37,13 +37,6 @@
 #define TPS_REG_POWER_STATUS		0x3f
 #define TPS_REG_RX_IDENTITY_SOP		0x48
 
-/* TPS_REG_STATUS bits */
-#define TPS_STATUS_PLUG_PRESENT		BIT(0)
-#define TPS_STATUS_ORIENTATION		BIT(4)
-#define TPS_STATUS_PORTROLE(s)		(!!((s) & BIT(5)))
-#define TPS_STATUS_DATAROLE(s)		(!!((s) & BIT(6)))
-#define TPS_STATUS_VCONN(s)		(!!((s) & BIT(7)))
-
 /* TPS_REG_SYSTEM_CONF bits */
 #define TPS_SYSCONF_PORTINFO(c)		((c) & 7)
 
@@ -258,9 +251,9 @@ static int tps6598x_connect(struct tps6598x *tps, u32 status)
 	}
 
 	typec_set_pwr_opmode(tps->port, mode);
-	typec_set_pwr_role(tps->port, TPS_STATUS_PORTROLE(status));
-	typec_set_vconn_role(tps->port, TPS_STATUS_VCONN(status));
-	tps6598x_set_data_role(tps, TPS_STATUS_DATAROLE(status), true);
+	typec_set_pwr_role(tps->port, TPS_STATUS_TO_TYPEC_PORTROLE(status));
+	typec_set_vconn_role(tps->port, TPS_STATUS_TO_TYPEC_VCONN(status));
+	tps6598x_set_data_role(tps, TPS_STATUS_TO_TYPEC_DATAROLE(status), true);
 
 	tps->partner = typec_register_partner(tps->port, &desc);
 	if (IS_ERR(tps->partner))
@@ -280,9 +273,10 @@ static void tps6598x_disconnect(struct tps6598x *tps, u32 status)
 		typec_unregister_partner(tps->partner);
 	tps->partner = NULL;
 	typec_set_pwr_opmode(tps->port, TYPEC_PWR_MODE_USB);
-	typec_set_pwr_role(tps->port, TPS_STATUS_PORTROLE(status));
-	typec_set_vconn_role(tps->port, TPS_STATUS_VCONN(status));
-	tps6598x_set_data_role(tps, TPS_STATUS_DATAROLE(status), false);
+	typec_set_pwr_role(tps->port, TPS_STATUS_TO_TYPEC_PORTROLE(status));
+	typec_set_vconn_role(tps->port, TPS_STATUS_TO_TYPEC_VCONN(status));
+	tps6598x_set_data_role(tps, TPS_STATUS_TO_TYPEC_DATAROLE(status), false);
+
 	power_supply_changed(tps->psy);
 }
 
@@ -366,7 +360,7 @@ static int tps6598x_dr_set(struct typec_port *port, enum typec_data_role role)
 	if (ret)
 		goto out_unlock;
 
-	if (role != TPS_STATUS_DATAROLE(status)) {
+	if (role != TPS_STATUS_TO_TYPEC_DATAROLE(status)) {
 		ret = -EPROTO;
 		goto out_unlock;
 	}
@@ -396,7 +390,7 @@ static int tps6598x_pr_set(struct typec_port *port, enum typec_role role)
 	if (ret)
 		goto out_unlock;
 
-	if (role != TPS_STATUS_PORTROLE(status)) {
+	if (role != TPS_STATUS_TO_TYPEC_PORTROLE(status)) {
 		ret = -EPROTO;
 		goto out_unlock;
 	}
@@ -437,6 +431,7 @@ static irqreturn_t tps6598x_interrupt(int irq, void *data)
 		dev_err(tps->dev, "%s: failed to read status\n", __func__);
 		goto err_clear_ints;
 	}
+	trace_tps6598x_status(status);
 
 	/* Handle plug insert or removal */
 	if ((event1 | event2) & TPS_REG_INT_PLUG_EVENT) {
@@ -612,6 +607,7 @@ static int tps6598x_probe(struct i2c_client *client)
 	ret = tps6598x_read32(tps, TPS_REG_STATUS, &status);
 	if (ret < 0)
 		return ret;
+	trace_tps6598x_status(status);
 
 	ret = tps6598x_read32(tps, TPS_REG_SYSTEM_CONF, &conf);
 	if (ret < 0)
diff --git a/drivers/usb/typec/tps6598x.h b/drivers/usb/typec/tps6598x.h
index b83b8a6a1504..621fb336c15d 100644
--- a/drivers/usb/typec/tps6598x.h
+++ b/drivers/usb/typec/tps6598x.h
@@ -12,6 +12,74 @@
 #ifndef __TPS6598X_H__
 #define __TPS6598X_H__
 
+#define TPS_FIELD_GET(_mask, _reg) ((typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask)))
+
+/* TPS_REG_STATUS bits */
+#define TPS_STATUS_PLUG_PRESENT		BIT(0)
+#define TPS_STATUS_PLUG_UPSIDE_DOWN	BIT(4)
+#define TPS_STATUS_PORTROLE		BIT(5)
+#define TPS_STATUS_TO_TYPEC_PORTROLE(s) (!!((s) & TPS_STATUS_PORTROLE))
+#define TPS_STATUS_DATAROLE		BIT(6)
+#define TPS_STATUS_TO_TYPEC_DATAROLE(s)	(!!((s) & TPS_STATUS_DATAROLE))
+#define TPS_STATUS_VCONN		BIT(7)
+#define TPS_STATUS_TO_TYPEC_VCONN(s)	(!!((s) & TPS_STATUS_VCONN))
+#define TPS_STATUS_OVERCURRENT		BIT(16)
+#define TPS_STATUS_GOTO_MIN_ACTIVE	BIT(26)
+#define TPS_STATUS_BIST			BIT(27)
+#define TPS_STATUS_HIGH_VOLAGE_WARNING	BIT(28)
+#define TPS_STATUS_HIGH_LOW_VOLTAGE_WARNING BIT(29)
+
+#define TPS_STATUS_CONN_STATE_MASK		GENMASK(3, 1)
+#define TPS_STATUS_CONN_STATE(x)		TPS_FIELD_GET(TPS_STATUS_CONN_STATE_MASK, (x))
+#define TPS_STATUS_PP_5V0_SWITCH_MASK		GENMASK(9, 8)
+#define TPS_STATUS_PP_5V0_SWITCH(x)		TPS_FIELD_GET(TPS_STATUS_PP_5V0_SWITCH_MASK, (x))
+#define TPS_STATUS_PP_HV_SWITCH_MASK		GENMASK(11, 10)
+#define TPS_STATUS_PP_HV_SWITCH(x)		TPS_FIELD_GET(TPS_STATUS_PP_HV_SWITCH_MASK, (x))
+#define TPS_STATUS_PP_EXT_SWITCH_MASK		GENMASK(13, 12)
+#define TPS_STATUS_PP_EXT_SWITCH(x)		TPS_FIELD_GET(TPS_STATUS_PP_EXT_SWITCH_MASK, (x))
+#define TPS_STATUS_PP_CABLE_SWITCH_MASK		GENMASK(15, 14)
+#define TPS_STATUS_PP_CABLE_SWITCH(x)		TPS_FIELD_GET(TPS_STATUS_PP_CABLE_SWITCH_MASK, (x))
+#define TPS_STATUS_POWER_SOURCE_MASK		GENMASK(19, 18)
+#define TPS_STATUS_POWER_SOURCE(x)		TPS_FIELD_GET(TPS_STATUS_POWER_SOURCE_MASK, (x))
+#define TPS_STATUS_VBUS_STATUS_MASK		GENMASK(21, 20)
+#define TPS_STATUS_VBUS_STATUS(x)		TPS_FIELD_GET(TPS_STATUS_VBUS_STATUS_MASK, (x))
+#define TPS_STATUS_USB_HOST_PRESENT_MASK	GENMASK(23, 22)
+#define TPS_STATUS_USB_HOST_PRESENT(x)		TPS_FIELD_GET(TPS_STATUS_USB_HOST_PRESENT_MASK, (x))
+#define TPS_STATUS_LEGACY_MASK			GENMASK(25, 24)
+#define TPS_STATUS_LEGACY(x)			TPS_FIELD_GET(TPS_STATUS_LEGACY_MASK, (x))
+
+#define TPS_STATUS_CONN_STATE_NO_CONN		0
+#define TPS_STATUS_CONN_STATE_DISABLED		1
+#define TPS_STATUS_CONN_STATE_AUDIO_CONN	2
+#define TPS_STATUS_CONN_STATE_DEBUG_CONN	3
+#define TPS_STATUS_CONN_STATE_NO_CONN_R_A	4
+#define TPS_STATUS_CONN_STATE_RESERVED		5
+#define TPS_STATUS_CONN_STATE_CONN_NO_R_A	6
+#define TPS_STATUS_CONN_STATE_CONN_WITH_R_A	7
+
+#define TPS_STATUS_PP_SWITCH_STATE_DISABLED	0
+#define TPS_STATUS_PP_SWITCH_STATE_FAULT	1
+#define TPS_STATUS_PP_SWITCH_STATE_OUT		2
+#define TPS_STATUS_PP_SWITCH_STATE_IN		3
+
+#define TPS_STATUS_POWER_SOURCE_UNKNOWN		0
+#define TPS_STATUS_POWER_SOURCE_VIN_3P3		1
+#define TPS_STATUS_POWER_SOURCE_DEAD_BAT	2
+#define TPS_STATUS_POWER_SOURCE_VBUS		3
+
+#define TPS_STATUS_VBUS_STATUS_VSAFE0V		0
+#define TPS_STATUS_VBUS_STATUS_VSAFE5V		1
+#define TPS_STATUS_VBUS_STATUS_PD		2
+#define TPS_STATUS_VBUS_STATUS_FAULT		3
+
+#define TPS_STATUS_USB_HOST_PRESENT_NO		0
+#define TPS_STATUS_USB_HOST_PRESENT_PD_NO_USB	1
+#define TPS_STATUS_USB_HOST_PRESENT_NO_PD	2
+#define TPS_STATUS_USB_HOST_PRESENT_PD_USB	3
+
+#define TPS_STATUS_LEGACY_NO			0
+#define TPS_STATUS_LEGACY_SINK			1
+#define TPS_STATUS_LEGACY_SOURCE		2
 
 /* TPS_REG_INT_* bits */
 #define TPS_REG_INT_USER_VID_ALT_MODE_OTHER_VDM		BIT_ULL(27+32)
diff --git a/drivers/usb/typec/tps6598x_trace.h b/drivers/usb/typec/tps6598x_trace.h
index 4ec96e3b2c3e..e0677b9c5c53 100644
--- a/drivers/usb/typec/tps6598x_trace.h
+++ b/drivers/usb/typec/tps6598x_trace.h
@@ -67,6 +67,73 @@
 		{ TPS_REG_INT_USER_VID_ALT_MODE_ATTN_VDM,	"USER_VID_ALT_MODE_ATTN_VDM" }, \
 		{ TPS_REG_INT_USER_VID_ALT_MODE_OTHER_VDM,	"USER_VID_ALT_MODE_OTHER_VDM" })
 
+#define TPS6598X_STATUS_FLAGS_MASK (GENMASK(31, 0) ^ (TPS_STATUS_CONN_STATE_MASK | \
+						      TPS_STATUS_PP_5V0_SWITCH_MASK | \
+						      TPS_STATUS_PP_HV_SWITCH_MASK | \
+						      TPS_STATUS_PP_EXT_SWITCH_MASK | \
+						      TPS_STATUS_PP_CABLE_SWITCH_MASK | \
+						      TPS_STATUS_POWER_SOURCE_MASK | \
+						      TPS_STATUS_VBUS_STATUS_MASK | \
+						      TPS_STATUS_USB_HOST_PRESENT_MASK | \
+						      TPS_STATUS_LEGACY_MASK))
+
+#define show_status_conn_state(status) \
+	__print_symbolic(TPS_STATUS_CONN_STATE((status)), \
+		{ TPS_STATUS_CONN_STATE_CONN_WITH_R_A,	"conn-Ra"  }, \
+		{ TPS_STATUS_CONN_STATE_CONN_NO_R_A,	"conn-no-Ra" }, \
+		{ TPS_STATUS_CONN_STATE_NO_CONN_R_A,	"no-conn-Ra" },	\
+		{ TPS_STATUS_CONN_STATE_DEBUG_CONN,	"debug"	 }, \
+		{ TPS_STATUS_CONN_STATE_AUDIO_CONN,	"audio"	 }, \
+		{ TPS_STATUS_CONN_STATE_DISABLED,	"disabled" }, \
+		{ TPS_STATUS_CONN_STATE_NO_CONN,	"no-conn" })
+
+#define show_status_pp_switch_state(status) \
+	__print_symbolic(status, \
+		{ TPS_STATUS_PP_SWITCH_STATE_IN,	"in" }, \
+		{ TPS_STATUS_PP_SWITCH_STATE_OUT,	"out" }, \
+		{ TPS_STATUS_PP_SWITCH_STATE_FAULT,	"fault" }, \
+		{ TPS_STATUS_PP_SWITCH_STATE_DISABLED,	"off" })
+
+#define show_status_power_sources(status) \
+	__print_symbolic(TPS_STATUS_POWER_SOURCE(status), \
+		{ TPS_STATUS_POWER_SOURCE_VBUS,		"vbus" }, \
+		{ TPS_STATUS_POWER_SOURCE_VIN_3P3,	"vin-3p3" }, \
+		{ TPS_STATUS_POWER_SOURCE_DEAD_BAT,	"dead-battery" }, \
+		{ TPS_STATUS_POWER_SOURCE_UNKNOWN,	"unknown" })
+
+#define show_status_vbus_status(status) \
+	__print_symbolic(TPS_STATUS_VBUS_STATUS(status), \
+		{ TPS_STATUS_VBUS_STATUS_VSAFE0V,	"vSafe0V" }, \
+		{ TPS_STATUS_VBUS_STATUS_VSAFE5V,	"vSafe5V" }, \
+		{ TPS_STATUS_VBUS_STATUS_PD,		"pd" }, \
+		{ TPS_STATUS_VBUS_STATUS_FAULT,		"fault" })
+
+#define show_status_usb_host_present(status) \
+	__print_symbolic(TPS_STATUS_USB_HOST_PRESENT(status), \
+		{ TPS_STATUS_USB_HOST_PRESENT_PD_USB,	 "pd-usb" }, \
+		{ TPS_STATUS_USB_HOST_PRESENT_NO_PD,	 "no-pd" }, \
+		{ TPS_STATUS_USB_HOST_PRESENT_PD_NO_USB, "pd-no-usb" }, \
+		{ TPS_STATUS_USB_HOST_PRESENT_NO,	 "no" })
+
+#define show_status_legacy(status) \
+	__print_symbolic(TPS_STATUS_LEGACY(status),	     \
+		{ TPS_STATUS_LEGACY_SOURCE,		 "source" }, \
+		{ TPS_STATUS_LEGACY_SINK,		 "sink" }, \
+		{ TPS_STATUS_LEGACY_NO,			 "no" })
+
+#define show_status_flags(flags) \
+	__print_flags((flags & TPS6598X_STATUS_FLAGS_MASK), "|", \
+		      { TPS_STATUS_PLUG_PRESENT,	"PLUG_PRESENT" }, \
+		      { TPS_STATUS_PLUG_UPSIDE_DOWN,	"UPSIDE_DOWN" }, \
+		      { TPS_STATUS_PORTROLE,		"PORTROLE" }, \
+		      { TPS_STATUS_DATAROLE,		"DATAROLE" }, \
+		      { TPS_STATUS_VCONN,		"VCONN" }, \
+		      { TPS_STATUS_OVERCURRENT,		"OVERCURRENT" }, \
+		      { TPS_STATUS_GOTO_MIN_ACTIVE,	"GOTO_MIN_ACTIVE" }, \
+		      { TPS_STATUS_BIST,		"BIST" }, \
+		      { TPS_STATUS_HIGH_VOLAGE_WARNING,	"HIGH_VOLAGE_WARNING" }, \
+		      { TPS_STATUS_HIGH_LOW_VOLTAGE_WARNING, "HIGH_LOW_VOLTAGE_WARNING" })
+
 TRACE_EVENT(tps6598x_irq,
 	    TP_PROTO(u64 event1,
 		     u64 event2),
@@ -87,6 +154,33 @@ TRACE_EVENT(tps6598x_irq,
 		      show_irq_flags(__entry->event2))
 );
 
+TRACE_EVENT(tps6598x_status,
+	    TP_PROTO(u32 status),
+	    TP_ARGS(status),
+
+	    TP_STRUCT__entry(
+			     __field(u32, status)
+			     ),
+
+	    TP_fast_assign(
+			   __entry->status = status;
+			   ),
+
+	    TP_printk("conn: %s, pp_5v0: %s, pp_hv: %s, pp_ext: %s, pp_cable: %s, "
+		      "pwr-src: %s, vbus: %s, usb-host: %s, legacy: %s, flags: %s",
+		      show_status_conn_state(__entry->status),
+		      show_status_pp_switch_state(TPS_STATUS_PP_5V0_SWITCH(__entry->status)),
+		      show_status_pp_switch_state(TPS_STATUS_PP_HV_SWITCH(__entry->status)),
+		      show_status_pp_switch_state(TPS_STATUS_PP_EXT_SWITCH(__entry->status)),
+		      show_status_pp_switch_state(TPS_STATUS_PP_CABLE_SWITCH(__entry->status)),
+		      show_status_power_sources(__entry->status),
+		      show_status_vbus_status(__entry->status),
+		      show_status_usb_host_present(__entry->status),
+		      show_status_legacy(__entry->status),
+		      show_status_flags(__entry->status)
+		    )
+);
+
 #endif /* _TPS6598X_TRACE_H_ */
 
 /* This part must be outside protection */
-- 
2.30.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v3 3/4] usb: typec: tps6598x: Add trace event for power status register
  2021-02-15 11:46 [PATCH v3 0/4] usb: typec: tps6598x: Add IRQ flag and register tracing Guido Günther
  2021-02-15 11:46 ` [PATCH v3 1/4] usb: typec: tps6598x: Add trace event for IRQ events Guido Günther
  2021-02-15 11:46 ` [PATCH v3 2/4] usb: typec: tps6598x: Add trace event for status register Guido Günther
@ 2021-02-15 11:46 ` Guido Günther
  2021-03-01 15:11   ` Heikki Krogerus
  2021-02-15 11:46 ` [PATCH v3 4/4] usb: typec: tps6598x: Add trace event for data status Guido Günther
  3 siblings, 1 reply; 9+ messages in thread
From: Guido Günther @ 2021-02-15 11:46 UTC (permalink / raw)
  To: Heikki Krogerus, Greg Kroah-Hartman, linux-kernel, linux-usb

Together with the PD status register this is vital for debugging power
negotiations at runtime.

Signed-off-by: Guido Günther <agx@sigxcpu.org>
---
 drivers/usb/typec/tps6598x.c       | 19 +++++++++------
 drivers/usb/typec/tps6598x.h       | 19 +++++++++++++++
 drivers/usb/typec/tps6598x_trace.h | 38 ++++++++++++++++++++++++++++++
 3 files changed, 69 insertions(+), 7 deletions(-)

diff --git a/drivers/usb/typec/tps6598x.c b/drivers/usb/typec/tps6598x.c
index 559aa175f948..3e6ad3ba7fc8 100644
--- a/drivers/usb/typec/tps6598x.c
+++ b/drivers/usb/typec/tps6598x.c
@@ -50,11 +50,6 @@ enum {
 	TPS_PORTINFO_SOURCE,
 };
 
-/* TPS_REG_POWER_STATUS bits */
-#define TPS_POWER_STATUS_CONNECTION	BIT(0)
-#define TPS_POWER_STATUS_SOURCESINK	BIT(1)
-#define TPS_POWER_STATUS_PWROPMODE(p)	(((p) & GENMASK(3, 2)) >> 2)
-
 /* TPS_REG_RX_IDENTITY_SOP */
 struct tps6598x_rx_identity_reg {
 	u8 status;
@@ -414,6 +409,7 @@ static irqreturn_t tps6598x_interrupt(int irq, void *data)
 	u64 event1;
 	u64 event2;
 	u32 status;
+	u16 pwr_status;
 	int ret;
 
 	mutex_lock(&tps->lock);
@@ -433,6 +429,15 @@ static irqreturn_t tps6598x_interrupt(int irq, void *data)
 	}
 	trace_tps6598x_status(status);
 
+	if ((event1 | event2) & TPS_REG_INT_POWER_STATUS_UPDATE) {
+		ret = tps6598x_read16(tps, TPS_REG_POWER_STATUS, &pwr_status);
+		if (ret < 0) {
+			dev_err(tps->dev, "failed to read power status: %d\n", ret);
+			goto err_clear_ints;
+		}
+		trace_tps6598x_power_status(pwr_status);
+	}
+
 	/* Handle plug insert or removal */
 	if ((event1 | event2) & TPS_REG_INT_PLUG_EVENT) {
 		if (status & TPS_STATUS_PLUG_PRESENT) {
@@ -497,8 +502,8 @@ static int tps6598x_psy_get_online(struct tps6598x *tps,
 	if (ret < 0)
 		return ret;
 
-	if ((pwr_status & TPS_POWER_STATUS_CONNECTION) &&
-	    (pwr_status & TPS_POWER_STATUS_SOURCESINK)) {
+	if (TPS_POWER_STATUS_CONNECTION(pwr_status) &&
+	    TPS_POWER_STATUS_SOURCESINK(pwr_status)) {
 		val->intval = 1;
 	} else {
 		val->intval = 0;
diff --git a/drivers/usb/typec/tps6598x.h b/drivers/usb/typec/tps6598x.h
index 621fb336c15d..9a34c020f3e5 100644
--- a/drivers/usb/typec/tps6598x.h
+++ b/drivers/usb/typec/tps6598x.h
@@ -129,4 +129,23 @@
 #define TPS_REG_INT_HARD_RESET				BIT(1)
 #define TPS_REG_INT_PD_SOFT_RESET			BIT(0)
 
+/* TPS_REG_POWER_STATUS bits */
+#define TPS_POWER_STATUS_CONNECTION(x)  TPS_FIELD_GET(BIT(0), (x))
+#define TPS_POWER_STATUS_SOURCESINK(x)	TPS_FIELD_GET(BIT(1), (x))
+#define TPS_POWER_STATUS_BC12_DET(x)	TPS_FIELD_GET(BIT(2), (x))
+
+#define TPS_POWER_STATUS_TYPEC_CURRENT_MASK GENMASK(3, 2)
+#define TPS_POWER_STATUS_PWROPMODE(p)	    TPS_FIELD_GET(TPS_POWER_STATUS_TYPEC_CURRENT_MASK, (p))
+#define TPS_POWER_STATUS_BC12_STATUS_MASK   GENMASK(6, 5)
+#define TPS_POWER_STATUS_BC12_STATUS(p)	    TPS_FIELD_GET(TPS_POWER_STATUS_BC12_STATUS_MASK, (p))
+
+#define TPS_POWER_STATUS_TYPEC_CURRENT_USB     0
+#define TPS_POWER_STATUS_TYPEC_CURRENT_1A5     1
+#define TPS_POWER_STATUS_TYPEC_CURRENT_3A0     2
+#define TPS_POWER_STATUS_TYPEC_CURRENT_PD      3
+
+#define TPS_POWER_STATUS_BC12_STATUS_SDP 0
+#define TPS_POWER_STATUS_BC12_STATUS_CDP 2
+#define TPS_POWER_STATUS_BC12_STATUS_DCP 3
+
 #endif /* __TPS6598X_H__ */
diff --git a/drivers/usb/typec/tps6598x_trace.h b/drivers/usb/typec/tps6598x_trace.h
index e0677b9c5c53..78a5a6ca337b 100644
--- a/drivers/usb/typec/tps6598x_trace.h
+++ b/drivers/usb/typec/tps6598x_trace.h
@@ -134,6 +134,24 @@
 		      { TPS_STATUS_HIGH_VOLAGE_WARNING,	"HIGH_VOLAGE_WARNING" }, \
 		      { TPS_STATUS_HIGH_LOW_VOLTAGE_WARNING, "HIGH_LOW_VOLTAGE_WARNING" })
 
+#define show_power_status_source_sink(power_status) \
+	__print_symbolic(TPS_POWER_STATUS_SOURCESINK(power_status), \
+		{ 1, "sink" }, \
+		{ 0, "source" })
+
+#define show_power_status_typec_status(power_status) \
+	__print_symbolic(TPS_POWER_STATUS_PWROPMODE(power_status), \
+		{ TPS_POWER_STATUS_TYPEC_CURRENT_PD,  "pd" }, \
+		{ TPS_POWER_STATUS_TYPEC_CURRENT_3A0, "3.0A" }, \
+		{ TPS_POWER_STATUS_TYPEC_CURRENT_1A5, "1.5A" }, \
+		{ TPS_POWER_STATUS_TYPEC_CURRENT_USB, "usb" })
+
+#define show_power_status_bc12_status(power_status) \
+	__print_symbolic(TPS_POWER_STATUS_BC12_STATUS(power_status), \
+		{ TPS_POWER_STATUS_BC12_STATUS_DCP, "dcp" }, \
+		{ TPS_POWER_STATUS_BC12_STATUS_CDP, "cdp" }, \
+		{ TPS_POWER_STATUS_BC12_STATUS_SDP, "sdp" })
+
 TRACE_EVENT(tps6598x_irq,
 	    TP_PROTO(u64 event1,
 		     u64 event2),
@@ -181,6 +199,26 @@ TRACE_EVENT(tps6598x_status,
 		    )
 );
 
+TRACE_EVENT(tps6598x_power_status,
+	    TP_PROTO(u16 power_status),
+	    TP_ARGS(power_status),
+
+	    TP_STRUCT__entry(
+			     __field(u16, power_status)
+			     ),
+
+	    TP_fast_assign(
+			   __entry->power_status = power_status;
+			   ),
+
+	    TP_printk("conn: %d, pwr-role: %s, typec: %s, bc: %s",
+		      !!TPS_POWER_STATUS_CONNECTION(__entry->power_status),
+		      show_power_status_source_sink(__entry->power_status),
+		      show_power_status_typec_status(__entry->power_status),
+		      show_power_status_bc12_status(__entry->power_status)
+		    )
+);
+
 #endif /* _TPS6598X_TRACE_H_ */
 
 /* This part must be outside protection */
-- 
2.30.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v3 4/4] usb: typec: tps6598x: Add trace event for data status
  2021-02-15 11:46 [PATCH v3 0/4] usb: typec: tps6598x: Add IRQ flag and register tracing Guido Günther
                   ` (2 preceding siblings ...)
  2021-02-15 11:46 ` [PATCH v3 3/4] usb: typec: tps6598x: Add trace event for power " Guido Günther
@ 2021-02-15 11:46 ` Guido Günther
  2021-03-01 15:12   ` Heikki Krogerus
  3 siblings, 1 reply; 9+ messages in thread
From: Guido Günther @ 2021-02-15 11:46 UTC (permalink / raw)
  To: Heikki Krogerus, Greg Kroah-Hartman, linux-kernel, linux-usb

This is useful to debug DP negotiation and pin assignment even
when the firmware does all the work.

Signed-off-by: Guido Günther <agx@sigxcpu.org>
---
 drivers/usb/typec/tps6598x.c       | 12 ++++++-
 drivers/usb/typec/tps6598x.h       | 38 +++++++++++++++++++++
 drivers/usb/typec/tps6598x_trace.h | 54 ++++++++++++++++++++++++++++++
 3 files changed, 103 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/typec/tps6598x.c b/drivers/usb/typec/tps6598x.c
index 3e6ad3ba7fc8..a4ec8e56c2b9 100644
--- a/drivers/usb/typec/tps6598x.c
+++ b/drivers/usb/typec/tps6598x.c
@@ -36,6 +36,7 @@
 #define TPS_REG_CTRL_CONF		0x29
 #define TPS_REG_POWER_STATUS		0x3f
 #define TPS_REG_RX_IDENTITY_SOP		0x48
+#define TPS_REG_DATA_STATUS		0x5f
 
 /* TPS_REG_SYSTEM_CONF bits */
 #define TPS_SYSCONF_PORTINFO(c)		((c) & 7)
@@ -408,7 +409,7 @@ static irqreturn_t tps6598x_interrupt(int irq, void *data)
 	struct tps6598x *tps = data;
 	u64 event1;
 	u64 event2;
-	u32 status;
+	u32 status, data_status;
 	u16 pwr_status;
 	int ret;
 
@@ -438,6 +439,15 @@ static irqreturn_t tps6598x_interrupt(int irq, void *data)
 		trace_tps6598x_power_status(pwr_status);
 	}
 
+	if ((event1 | event2) & TPS_REG_INT_DATA_STATUS_UPDATE) {
+		ret = tps6598x_read32(tps, TPS_REG_DATA_STATUS, &data_status);
+		if (ret < 0) {
+			dev_err(tps->dev, "failed to read data status: %d\n", ret);
+			goto err_clear_ints;
+		}
+		trace_tps6598x_data_status(data_status);
+	}
+
 	/* Handle plug insert or removal */
 	if ((event1 | event2) & TPS_REG_INT_PLUG_EVENT) {
 		if (status & TPS_STATUS_PLUG_PRESENT) {
diff --git a/drivers/usb/typec/tps6598x.h b/drivers/usb/typec/tps6598x.h
index 9a34c020f3e5..003a577be216 100644
--- a/drivers/usb/typec/tps6598x.h
+++ b/drivers/usb/typec/tps6598x.h
@@ -148,4 +148,42 @@
 #define TPS_POWER_STATUS_BC12_STATUS_CDP 2
 #define TPS_POWER_STATUS_BC12_STATUS_DCP 3
 
+/* TPS_REG_DATA_STATUS bits */
+#define TPS_DATA_STATUS_DATA_CONNECTION	     BIT(0)
+#define TPS_DATA_STATUS_UPSIDE_DOWN	     BIT(1)
+#define TPS_DATA_STATUS_ACTIVE_CABLE	     BIT(2)
+#define TPS_DATA_STATUS_USB2_CONNECTION	     BIT(4)
+#define TPS_DATA_STATUS_USB3_CONNECTION	     BIT(5)
+#define TPS_DATA_STATUS_USB3_GEN2	     BIT(6)
+#define TPS_DATA_STATUS_USB_DATA_ROLE	     BIT(7)
+#define TPS_DATA_STATUS_DP_CONNECTION	     BIT(8)
+#define TPS_DATA_STATUS_DP_SINK		     BIT(9)
+#define TPS_DATA_STATUS_TBT_CONNECTION	     BIT(16)
+#define TPS_DATA_STATUS_TBT_TYPE	     BIT(17)
+#define TPS_DATA_STATUS_OPTICAL_CABLE	     BIT(18)
+#define TPS_DATA_STATUS_ACTIVE_LINK_TRAIN    BIT(20)
+#define TPS_DATA_STATUS_FORCE_LSX	     BIT(23)
+#define TPS_DATA_STATUS_POWER_MISMATCH	     BIT(24)
+
+#define TPS_DATA_STATUS_DP_PIN_ASSIGNMENT_MASK GENMASK(11, 10)
+#define TPS_DATA_STATUS_DP_PIN_ASSIGNMENT(x) \
+	TPS_FIELD_GET(TPS_DATA_STATUS_DP_PIN_ASSIGNMENT_MASK, (x))
+#define TPS_DATA_STATUS_TBT_CABLE_SPEED_MASK   GENMASK(27, 25)
+#define TPS_DATA_STATUS_TBT_CABLE_SPEED \
+	TPS_FIELD_GET(TPS_DATA_STATUS_TBT_CABLE_SPEED_MASK, (x))
+#define TPS_DATA_STATUS_TBT_CABLE_GEN_MASK     GENMASK(29, 28)
+#define TPS_DATA_STATUS_TBT_CABLE_GEN \
+	TPS_FIELD_GET(TPS_DATA_STATUS_TBT_CABLE_GEN_MASK, (x))
+
+/* Map data status to DP spec assignments */
+#define TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT(x) \
+	((TPS_DATA_STATUS_DP_PIN_ASSIGNMENT(x) << 1) | \
+		TPS_FIELD_GET(TPS_DATA_STATUS_USB3_CONNECTION, (x)))
+#define TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT_E    0
+#define TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT_F    BIT(0)
+#define TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT_C    BIT(1)
+#define TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT_D    (BIT(1) | BIT(0))
+#define TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT_A    BIT(2)
+#define TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT_B    (BIT(2) | BIT(1))
+
 #endif /* __TPS6598X_H__ */
diff --git a/drivers/usb/typec/tps6598x_trace.h b/drivers/usb/typec/tps6598x_trace.h
index 78a5a6ca337b..38bfb2f04e46 100644
--- a/drivers/usb/typec/tps6598x_trace.h
+++ b/drivers/usb/typec/tps6598x_trace.h
@@ -152,6 +152,41 @@
 		{ TPS_POWER_STATUS_BC12_STATUS_CDP, "cdp" }, \
 		{ TPS_POWER_STATUS_BC12_STATUS_SDP, "sdp" })
 
+#define TPS_DATA_STATUS_FLAGS_MASK (GENMASK(31, 0) ^ (TPS_DATA_STATUS_DP_PIN_ASSIGNMENT_MASK | \
+						      TPS_DATA_STATUS_TBT_CABLE_SPEED_MASK | \
+						      TPS_DATA_STATUS_TBT_CABLE_GEN_MASK))
+
+#define show_data_status_flags(data_status) \
+	__print_flags(data_status & TPS_DATA_STATUS_FLAGS_MASK, "|", \
+		{ TPS_DATA_STATUS_DATA_CONNECTION,	"DATA_CONNECTION" }, \
+		{ TPS_DATA_STATUS_UPSIDE_DOWN,		"DATA_UPSIDE_DOWN" }, \
+		{ TPS_DATA_STATUS_ACTIVE_CABLE,		"ACTIVE_CABLE" }, \
+		{ TPS_DATA_STATUS_USB2_CONNECTION,	"USB2_CONNECTION" }, \
+		{ TPS_DATA_STATUS_USB3_CONNECTION,	"USB3_CONNECTION" }, \
+		{ TPS_DATA_STATUS_USB3_GEN2,		"USB3_GEN2" }, \
+		{ TPS_DATA_STATUS_USB_DATA_ROLE,	"USB_DATA_ROLE" }, \
+		{ TPS_DATA_STATUS_DP_CONNECTION,	"DP_CONNECTION" }, \
+		{ TPS_DATA_STATUS_DP_SINK,		"DP_SINK" }, \
+		{ TPS_DATA_STATUS_TBT_CONNECTION,	"TBT_CONNECTION" }, \
+		{ TPS_DATA_STATUS_TBT_TYPE,		"TBT_TYPE" }, \
+		{ TPS_DATA_STATUS_OPTICAL_CABLE,	"OPTICAL_CABLE" }, \
+		{ TPS_DATA_STATUS_ACTIVE_LINK_TRAIN,	"ACTIVE_LINK_TRAIN" }, \
+		{ TPS_DATA_STATUS_FORCE_LSX,		"FORCE_LSX" }, \
+		{ TPS_DATA_STATUS_POWER_MISMATCH,	"POWER_MISMATCH" })
+
+#define show_data_status_dp_pin_assignment(data_status) \
+	__print_symbolic(TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT(data_status), \
+		{ TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT_E, "E" }, \
+		{ TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT_F, "F" }, \
+		{ TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT_C, "C" }, \
+		{ TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT_D, "D" }, \
+		{ TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT_A, "A" }, \
+		{ TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT_B, "B" })
+
+#define maybe_show_data_status_dp_pin_assignment(data_status) \
+	(data_status & TPS_DATA_STATUS_DP_CONNECTION ? \
+	 show_data_status_dp_pin_assignment(data_status) : "")
+
 TRACE_EVENT(tps6598x_irq,
 	    TP_PROTO(u64 event1,
 		     u64 event2),
@@ -219,6 +254,25 @@ TRACE_EVENT(tps6598x_power_status,
 		    )
 );
 
+TRACE_EVENT(tps6598x_data_status,
+	    TP_PROTO(u32 data_status),
+	    TP_ARGS(data_status),
+
+	    TP_STRUCT__entry(
+			     __field(u32, data_status)
+			     ),
+
+	    TP_fast_assign(
+			   __entry->data_status = data_status;
+			   ),
+
+	    TP_printk("%s%s%s",
+		      show_data_status_flags(__entry->data_status),
+		      __entry->data_status & TPS_DATA_STATUS_DP_CONNECTION ? ", DP pinout " : "",
+		      maybe_show_data_status_dp_pin_assignment(__entry->data_status)
+		    )
+);
+
 #endif /* _TPS6598X_TRACE_H_ */
 
 /* This part must be outside protection */
-- 
2.30.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH v3 1/4] usb: typec: tps6598x: Add trace event for IRQ events
  2021-02-15 11:46 ` [PATCH v3 1/4] usb: typec: tps6598x: Add trace event for IRQ events Guido Günther
@ 2021-03-01 15:09   ` Heikki Krogerus
  0 siblings, 0 replies; 9+ messages in thread
From: Heikki Krogerus @ 2021-03-01 15:09 UTC (permalink / raw)
  To: Guido Günther; +Cc: Greg Kroah-Hartman, linux-kernel, linux-usb

On Mon, Feb 15, 2021 at 12:46:42PM +0100, Guido Günther wrote:
> Allow to get irq event information via the tracing framework.  This
> allows to inspect USB-C negotiation at runtime.
> 
> Signed-off-by: Guido Günther <agx@sigxcpu.org>

Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>

> ---
>  drivers/usb/typec/Makefile         |  3 +
>  drivers/usb/typec/tps6598x.c       |  9 ++-
>  drivers/usb/typec/tps6598x.h       | 64 ++++++++++++++++++++
>  drivers/usb/typec/tps6598x_trace.h | 97 ++++++++++++++++++++++++++++++
>  4 files changed, 170 insertions(+), 3 deletions(-)
>  create mode 100644 drivers/usb/typec/tps6598x.h
>  create mode 100644 drivers/usb/typec/tps6598x_trace.h
> 
> diff --git a/drivers/usb/typec/Makefile b/drivers/usb/typec/Makefile
> index d03b48c4b864..27aa12129190 100644
> --- a/drivers/usb/typec/Makefile
> +++ b/drivers/usb/typec/Makefile
> @@ -1,4 +1,7 @@
>  # SPDX-License-Identifier: GPL-2.0
> +# define_trace.h needs to know how to find our header
> +CFLAGS_tps6598x.o		:= -I$(src)
> +
>  obj-$(CONFIG_TYPEC)		+= typec.o
>  typec-y				:= class.o mux.o bus.o
>  obj-$(CONFIG_TYPEC)		+= altmodes/
> diff --git a/drivers/usb/typec/tps6598x.c b/drivers/usb/typec/tps6598x.c
> index 6e6ef6317523..bc34b35e909f 100644
> --- a/drivers/usb/typec/tps6598x.c
> +++ b/drivers/usb/typec/tps6598x.c
> @@ -6,6 +6,8 @@
>   * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com>
>   */
>  
> +#include "tps6598x.h"
> +
>  #include <linux/i2c.h>
>  #include <linux/acpi.h>
>  #include <linux/module.h>
> @@ -15,6 +17,9 @@
>  #include <linux/usb/typec.h>
>  #include <linux/usb/role.h>
>  
> +#define CREATE_TRACE_POINTS
> +#include "tps6598x_trace.h"
> +
>  /* Register offsets */
>  #define TPS_REG_VID			0x00
>  #define TPS_REG_MODE			0x03
> @@ -32,9 +37,6 @@
>  #define TPS_REG_POWER_STATUS		0x3f
>  #define TPS_REG_RX_IDENTITY_SOP		0x48
>  
> -/* TPS_REG_INT_* bits */
> -#define TPS_REG_INT_PLUG_EVENT		BIT(3)
> -
>  /* TPS_REG_STATUS bits */
>  #define TPS_STATUS_PLUG_PRESENT		BIT(0)
>  #define TPS_STATUS_ORIENTATION		BIT(4)
> @@ -428,6 +430,7 @@ static irqreturn_t tps6598x_interrupt(int irq, void *data)
>  		dev_err(tps->dev, "%s: failed to read events\n", __func__);
>  		goto err_unlock;
>  	}
> +	trace_tps6598x_irq(event1, event2);
>  
>  	ret = tps6598x_read32(tps, TPS_REG_STATUS, &status);
>  	if (ret) {
> diff --git a/drivers/usb/typec/tps6598x.h b/drivers/usb/typec/tps6598x.h
> new file mode 100644
> index 000000000000..b83b8a6a1504
> --- /dev/null
> +++ b/drivers/usb/typec/tps6598x.h
> @@ -0,0 +1,64 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Driver for TI TPS6598x USB Power Delivery controller family
> + *
> + * Copyright (C) 2017, Intel Corporation
> + * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> + */
> +
> +#include <linux/bits.h>
> +#include <linux/bitfield.h>
> +
> +#ifndef __TPS6598X_H__
> +#define __TPS6598X_H__
> +
> +
> +/* TPS_REG_INT_* bits */
> +#define TPS_REG_INT_USER_VID_ALT_MODE_OTHER_VDM		BIT_ULL(27+32)
> +#define TPS_REG_INT_USER_VID_ALT_MODE_ATTN_VDM		BIT_ULL(26+32)
> +#define TPS_REG_INT_USER_VID_ALT_MODE_EXIT		BIT_ULL(25+32)
> +#define TPS_REG_INT_USER_VID_ALT_MODE_ENTERED		BIT_ULL(24+32)
> +#define TPS_REG_INT_EXIT_MODES_COMPLETE			BIT_ULL(20+32)
> +#define TPS_REG_INT_DISCOVER_MODES_COMPLETE		BIT_ULL(19+32)
> +#define TPS_REG_INT_VDM_MSG_SENT			BIT_ULL(18+32)
> +#define TPS_REG_INT_VDM_ENTERED_MODE			BIT_ULL(17+32)
> +#define TPS_REG_INT_ERROR_UNABLE_TO_SOURCE		BIT_ULL(14+32)
> +#define TPS_REG_INT_SRC_TRANSITION			BIT_ULL(10+32)
> +#define TPS_REG_INT_ERROR_DISCHARGE_FAILED		BIT_ULL(9+32)
> +#define TPS_REG_INT_ERROR_MESSAGE_DATA			BIT_ULL(7+32)
> +#define TPS_REG_INT_ERROR_PROTOCOL_ERROR		BIT_ULL(6+32)
> +#define TPS_REG_INT_ERROR_MISSING_GET_CAP_MESSAGE	BIT_ULL(4+32)
> +#define TPS_REG_INT_ERROR_POWER_EVENT_OCCURRED		BIT_ULL(3+32)
> +#define TPS_REG_INT_ERROR_CAN_PROVIDE_PWR_LATER		BIT_ULL(2+32)
> +#define TPS_REG_INT_ERROR_CANNOT_PROVIDE_PWR		BIT_ULL(1+32)
> +#define TPS_REG_INT_ERROR_DEVICE_INCOMPATIBLE		BIT_ULL(0+32)
> +#define TPS_REG_INT_CMD2_COMPLETE			BIT(31)
> +#define TPS_REG_INT_CMD1_COMPLETE			BIT(30)
> +#define TPS_REG_INT_ADC_HIGH_THRESHOLD			BIT(29)
> +#define TPS_REG_INT_ADC_LOW_THRESHOLD			BIT(28)
> +#define TPS_REG_INT_PD_STATUS_UPDATE			BIT(27)
> +#define TPS_REG_INT_STATUS_UPDATE			BIT(26)
> +#define TPS_REG_INT_DATA_STATUS_UPDATE			BIT(25)
> +#define TPS_REG_INT_POWER_STATUS_UPDATE			BIT(24)
> +#define TPS_REG_INT_PP_SWITCH_CHANGED			BIT(23)
> +#define TPS_REG_INT_HIGH_VOLTAGE_WARNING		BIT(22)
> +#define TPS_REG_INT_USB_HOST_PRESENT_NO_LONGER		BIT(21)
> +#define TPS_REG_INT_USB_HOST_PRESENT			BIT(20)
> +#define TPS_REG_INT_GOTO_MIN_RECEIVED			BIT(19)
> +#define TPS_REG_INT_PR_SWAP_REQUESTED			BIT(17)
> +#define TPS_REG_INT_SINK_CAP_MESSAGE_READY		BIT(15)
> +#define TPS_REG_INT_SOURCE_CAP_MESSAGE_READY		BIT(14)
> +#define TPS_REG_INT_NEW_CONTRACT_AS_PROVIDER		BIT(13)
> +#define TPS_REG_INT_NEW_CONTRACT_AS_CONSUMER		BIT(12)
> +#define TPS_REG_INT_VDM_RECEIVED			BIT(11)
> +#define TPS_REG_INT_ATTENTION_RECEIVED			BIT(10)
> +#define TPS_REG_INT_OVERCURRENT				BIT(9)
> +#define TPS_REG_INT_BIST				BIT(8)
> +#define TPS_REG_INT_RDO_RECEIVED_FROM_SINK		BIT(7)
> +#define TPS_REG_INT_DR_SWAP_COMPLETE			BIT(5)
> +#define TPS_REG_INT_PR_SWAP_COMPLETE			BIT(4)
> +#define TPS_REG_INT_PLUG_EVENT				BIT(3)
> +#define TPS_REG_INT_HARD_RESET				BIT(1)
> +#define TPS_REG_INT_PD_SOFT_RESET			BIT(0)
> +
> +#endif /* __TPS6598X_H__ */
> diff --git a/drivers/usb/typec/tps6598x_trace.h b/drivers/usb/typec/tps6598x_trace.h
> new file mode 100644
> index 000000000000..4ec96e3b2c3e
> --- /dev/null
> +++ b/drivers/usb/typec/tps6598x_trace.h
> @@ -0,0 +1,97 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Driver for TI TPS6598x USB Power Delivery controller family
> + *
> + * Copyright (C) 2020 Purism SPC
> + * Author: Guido Günther <agx@sigxcpu.org>
> + */
> +
> +#undef TRACE_SYSTEM
> +#define TRACE_SYSTEM tps6598x
> +
> +#if !defined(_TPS6598x_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ)
> +#define _TPS6598X_TRACE_H_
> +
> +#include "tps6598x.h"
> +
> +#include <linux/stringify.h>
> +#include <linux/types.h>
> +#include <linux/tracepoint.h>
> +
> +#define show_irq_flags(flags) \
> +	__print_flags_u64(flags, "|", \
> +		{ TPS_REG_INT_PD_SOFT_RESET,			"PD_SOFT_RESET" }, \
> +		{ TPS_REG_INT_HARD_RESET,			"HARD_RESET" }, \
> +		{ TPS_REG_INT_PLUG_EVENT,			"PLUG_EVENT" }, \
> +		{ TPS_REG_INT_PR_SWAP_COMPLETE,			"PR_SWAP_COMPLETE" }, \
> +		{ TPS_REG_INT_DR_SWAP_COMPLETE,			"DR_SWAP_COMPLETE" }, \
> +		{ TPS_REG_INT_RDO_RECEIVED_FROM_SINK,		"RDO_RECEIVED_FROM_SINK" }, \
> +		{ TPS_REG_INT_BIST,				"BIST" }, \
> +		{ TPS_REG_INT_OVERCURRENT,			"OVERCURRENT" }, \
> +		{ TPS_REG_INT_ATTENTION_RECEIVED,		"ATTENTION_RECEIVED" }, \
> +		{ TPS_REG_INT_VDM_RECEIVED,			"VDM_RECEIVED" }, \
> +		{ TPS_REG_INT_NEW_CONTRACT_AS_CONSUMER,		"NEW_CONTRACT_AS_CONSUMER" }, \
> +		{ TPS_REG_INT_NEW_CONTRACT_AS_PROVIDER,		"NEW_CONTRACT_AS_PROVIDER" }, \
> +		{ TPS_REG_INT_SOURCE_CAP_MESSAGE_READY,		"SOURCE_CAP_MESSAGE_READY" }, \
> +		{ TPS_REG_INT_SINK_CAP_MESSAGE_READY,		"SINK_CAP_MESSAGE_READY" }, \
> +		{ TPS_REG_INT_PR_SWAP_REQUESTED,		"PR_SWAP_REQUESTED" }, \
> +		{ TPS_REG_INT_GOTO_MIN_RECEIVED,		"GOTO_MIN_RECEIVED" }, \
> +		{ TPS_REG_INT_USB_HOST_PRESENT,			"USB_HOST_PRESENT" }, \
> +		{ TPS_REG_INT_USB_HOST_PRESENT_NO_LONGER,	"USB_HOST_PRESENT_NO_LONGER" }, \
> +		{ TPS_REG_INT_HIGH_VOLTAGE_WARNING,		"HIGH_VOLTAGE_WARNING" }, \
> +		{ TPS_REG_INT_PP_SWITCH_CHANGED,		"PP_SWITCH_CHANGED" }, \
> +		{ TPS_REG_INT_POWER_STATUS_UPDATE,		"POWER_STATUS_UPDATE" }, \
> +		{ TPS_REG_INT_DATA_STATUS_UPDATE,		"DATA_STATUS_UPDATE" }, \
> +		{ TPS_REG_INT_STATUS_UPDATE,			"STATUS_UPDATE" }, \
> +		{ TPS_REG_INT_PD_STATUS_UPDATE,			"PD_STATUS_UPDATE" }, \
> +		{ TPS_REG_INT_ADC_LOW_THRESHOLD,		"ADC_LOW_THRESHOLD" }, \
> +		{ TPS_REG_INT_ADC_HIGH_THRESHOLD,		"ADC_HIGH_THRESHOLD" }, \
> +		{ TPS_REG_INT_CMD1_COMPLETE,			"CMD1_COMPLETE" }, \
> +		{ TPS_REG_INT_CMD2_COMPLETE,			"CMD2_COMPLETE" }, \
> +		{ TPS_REG_INT_ERROR_DEVICE_INCOMPATIBLE,	"ERROR_DEVICE_INCOMPATIBLE" }, \
> +		{ TPS_REG_INT_ERROR_CANNOT_PROVIDE_PWR,		"ERROR_CANNOT_PROVIDE_PWR" }, \
> +		{ TPS_REG_INT_ERROR_CAN_PROVIDE_PWR_LATER,	"ERROR_CAN_PROVIDE_PWR_LATER" }, \
> +		{ TPS_REG_INT_ERROR_POWER_EVENT_OCCURRED,	"ERROR_POWER_EVENT_OCCURRED" }, \
> +		{ TPS_REG_INT_ERROR_MISSING_GET_CAP_MESSAGE,	"ERROR_MISSING_GET_CAP_MESSAGE" }, \
> +		{ TPS_REG_INT_ERROR_PROTOCOL_ERROR,		"ERROR_PROTOCOL_ERROR" }, \
> +		{ TPS_REG_INT_ERROR_MESSAGE_DATA,		"ERROR_MESSAGE_DATA" }, \
> +		{ TPS_REG_INT_ERROR_DISCHARGE_FAILED,		"ERROR_DISCHARGE_FAILED" }, \
> +		{ TPS_REG_INT_SRC_TRANSITION,			"SRC_TRANSITION" }, \
> +		{ TPS_REG_INT_ERROR_UNABLE_TO_SOURCE,		"ERROR_UNABLE_TO_SOURCE" }, \
> +		{ TPS_REG_INT_VDM_ENTERED_MODE,			"VDM_ENTERED_MODE" }, \
> +		{ TPS_REG_INT_VDM_MSG_SENT,			"VDM_MSG_SENT" }, \
> +		{ TPS_REG_INT_DISCOVER_MODES_COMPLETE,		"DISCOVER_MODES_COMPLETE" }, \
> +		{ TPS_REG_INT_EXIT_MODES_COMPLETE,		"EXIT_MODES_COMPLETE" }, \
> +		{ TPS_REG_INT_USER_VID_ALT_MODE_ENTERED,	"USER_VID_ALT_MODE_ENTERED" }, \
> +		{ TPS_REG_INT_USER_VID_ALT_MODE_EXIT,		"USER_VID_ALT_MODE_EXIT" }, \
> +		{ TPS_REG_INT_USER_VID_ALT_MODE_ATTN_VDM,	"USER_VID_ALT_MODE_ATTN_VDM" }, \
> +		{ TPS_REG_INT_USER_VID_ALT_MODE_OTHER_VDM,	"USER_VID_ALT_MODE_OTHER_VDM" })
> +
> +TRACE_EVENT(tps6598x_irq,
> +	    TP_PROTO(u64 event1,
> +		     u64 event2),
> +	    TP_ARGS(event1, event2),
> +
> +	    TP_STRUCT__entry(
> +			     __field(u64, event1)
> +			     __field(u64, event2)
> +			     ),
> +
> +	    TP_fast_assign(
> +			   __entry->event1 = event1;
> +			   __entry->event2 = event2;
> +			   ),
> +
> +	    TP_printk("event1=%s, event2=%s",
> +		      show_irq_flags(__entry->event1),
> +		      show_irq_flags(__entry->event2))
> +);
> +
> +#endif /* _TPS6598X_TRACE_H_ */
> +
> +/* This part must be outside protection */
> +#undef TRACE_INCLUDE_PATH
> +#define TRACE_INCLUDE_FILE tps6598x_trace
> +#undef TRACE_INCLUDE_PATH
> +#define TRACE_INCLUDE_PATH .
> +#include <trace/define_trace.h>
> -- 
> 2.30.0

thanks,

-- 
heikki

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v3 2/4] usb: typec: tps6598x: Add trace event for status register
  2021-02-15 11:46 ` [PATCH v3 2/4] usb: typec: tps6598x: Add trace event for status register Guido Günther
@ 2021-03-01 15:10   ` Heikki Krogerus
  0 siblings, 0 replies; 9+ messages in thread
From: Heikki Krogerus @ 2021-03-01 15:10 UTC (permalink / raw)
  To: Guido Günther; +Cc: Greg Kroah-Hartman, linux-kernel, linux-usb

On Mon, Feb 15, 2021 at 12:46:43PM +0100, Guido Günther wrote:
> This allows to trace status information which helps to debug problems
> with role switching, etc.
> 
> We don't use the generic FIELD_GET() to reduce the macro size since we
> otherwise trip up sparse.
> 
> Signed-off-by: Guido Günther <agx@sigxcpu.org>

Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>

> ---
>  drivers/usb/typec/tps6598x.c       | 26 ++++-----
>  drivers/usb/typec/tps6598x.h       | 68 +++++++++++++++++++++
>  drivers/usb/typec/tps6598x_trace.h | 94 ++++++++++++++++++++++++++++++
>  3 files changed, 173 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/usb/typec/tps6598x.c b/drivers/usb/typec/tps6598x.c
> index bc34b35e909f..559aa175f948 100644
> --- a/drivers/usb/typec/tps6598x.c
> +++ b/drivers/usb/typec/tps6598x.c
> @@ -37,13 +37,6 @@
>  #define TPS_REG_POWER_STATUS		0x3f
>  #define TPS_REG_RX_IDENTITY_SOP		0x48
>  
> -/* TPS_REG_STATUS bits */
> -#define TPS_STATUS_PLUG_PRESENT		BIT(0)
> -#define TPS_STATUS_ORIENTATION		BIT(4)
> -#define TPS_STATUS_PORTROLE(s)		(!!((s) & BIT(5)))
> -#define TPS_STATUS_DATAROLE(s)		(!!((s) & BIT(6)))
> -#define TPS_STATUS_VCONN(s)		(!!((s) & BIT(7)))
> -
>  /* TPS_REG_SYSTEM_CONF bits */
>  #define TPS_SYSCONF_PORTINFO(c)		((c) & 7)
>  
> @@ -258,9 +251,9 @@ static int tps6598x_connect(struct tps6598x *tps, u32 status)
>  	}
>  
>  	typec_set_pwr_opmode(tps->port, mode);
> -	typec_set_pwr_role(tps->port, TPS_STATUS_PORTROLE(status));
> -	typec_set_vconn_role(tps->port, TPS_STATUS_VCONN(status));
> -	tps6598x_set_data_role(tps, TPS_STATUS_DATAROLE(status), true);
> +	typec_set_pwr_role(tps->port, TPS_STATUS_TO_TYPEC_PORTROLE(status));
> +	typec_set_vconn_role(tps->port, TPS_STATUS_TO_TYPEC_VCONN(status));
> +	tps6598x_set_data_role(tps, TPS_STATUS_TO_TYPEC_DATAROLE(status), true);
>  
>  	tps->partner = typec_register_partner(tps->port, &desc);
>  	if (IS_ERR(tps->partner))
> @@ -280,9 +273,10 @@ static void tps6598x_disconnect(struct tps6598x *tps, u32 status)
>  		typec_unregister_partner(tps->partner);
>  	tps->partner = NULL;
>  	typec_set_pwr_opmode(tps->port, TYPEC_PWR_MODE_USB);
> -	typec_set_pwr_role(tps->port, TPS_STATUS_PORTROLE(status));
> -	typec_set_vconn_role(tps->port, TPS_STATUS_VCONN(status));
> -	tps6598x_set_data_role(tps, TPS_STATUS_DATAROLE(status), false);
> +	typec_set_pwr_role(tps->port, TPS_STATUS_TO_TYPEC_PORTROLE(status));
> +	typec_set_vconn_role(tps->port, TPS_STATUS_TO_TYPEC_VCONN(status));
> +	tps6598x_set_data_role(tps, TPS_STATUS_TO_TYPEC_DATAROLE(status), false);
> +
>  	power_supply_changed(tps->psy);
>  }
>  
> @@ -366,7 +360,7 @@ static int tps6598x_dr_set(struct typec_port *port, enum typec_data_role role)
>  	if (ret)
>  		goto out_unlock;
>  
> -	if (role != TPS_STATUS_DATAROLE(status)) {
> +	if (role != TPS_STATUS_TO_TYPEC_DATAROLE(status)) {
>  		ret = -EPROTO;
>  		goto out_unlock;
>  	}
> @@ -396,7 +390,7 @@ static int tps6598x_pr_set(struct typec_port *port, enum typec_role role)
>  	if (ret)
>  		goto out_unlock;
>  
> -	if (role != TPS_STATUS_PORTROLE(status)) {
> +	if (role != TPS_STATUS_TO_TYPEC_PORTROLE(status)) {
>  		ret = -EPROTO;
>  		goto out_unlock;
>  	}
> @@ -437,6 +431,7 @@ static irqreturn_t tps6598x_interrupt(int irq, void *data)
>  		dev_err(tps->dev, "%s: failed to read status\n", __func__);
>  		goto err_clear_ints;
>  	}
> +	trace_tps6598x_status(status);
>  
>  	/* Handle plug insert or removal */
>  	if ((event1 | event2) & TPS_REG_INT_PLUG_EVENT) {
> @@ -612,6 +607,7 @@ static int tps6598x_probe(struct i2c_client *client)
>  	ret = tps6598x_read32(tps, TPS_REG_STATUS, &status);
>  	if (ret < 0)
>  		return ret;
> +	trace_tps6598x_status(status);
>  
>  	ret = tps6598x_read32(tps, TPS_REG_SYSTEM_CONF, &conf);
>  	if (ret < 0)
> diff --git a/drivers/usb/typec/tps6598x.h b/drivers/usb/typec/tps6598x.h
> index b83b8a6a1504..621fb336c15d 100644
> --- a/drivers/usb/typec/tps6598x.h
> +++ b/drivers/usb/typec/tps6598x.h
> @@ -12,6 +12,74 @@
>  #ifndef __TPS6598X_H__
>  #define __TPS6598X_H__
>  
> +#define TPS_FIELD_GET(_mask, _reg) ((typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask)))
> +
> +/* TPS_REG_STATUS bits */
> +#define TPS_STATUS_PLUG_PRESENT		BIT(0)
> +#define TPS_STATUS_PLUG_UPSIDE_DOWN	BIT(4)
> +#define TPS_STATUS_PORTROLE		BIT(5)
> +#define TPS_STATUS_TO_TYPEC_PORTROLE(s) (!!((s) & TPS_STATUS_PORTROLE))
> +#define TPS_STATUS_DATAROLE		BIT(6)
> +#define TPS_STATUS_TO_TYPEC_DATAROLE(s)	(!!((s) & TPS_STATUS_DATAROLE))
> +#define TPS_STATUS_VCONN		BIT(7)
> +#define TPS_STATUS_TO_TYPEC_VCONN(s)	(!!((s) & TPS_STATUS_VCONN))
> +#define TPS_STATUS_OVERCURRENT		BIT(16)
> +#define TPS_STATUS_GOTO_MIN_ACTIVE	BIT(26)
> +#define TPS_STATUS_BIST			BIT(27)
> +#define TPS_STATUS_HIGH_VOLAGE_WARNING	BIT(28)
> +#define TPS_STATUS_HIGH_LOW_VOLTAGE_WARNING BIT(29)
> +
> +#define TPS_STATUS_CONN_STATE_MASK		GENMASK(3, 1)
> +#define TPS_STATUS_CONN_STATE(x)		TPS_FIELD_GET(TPS_STATUS_CONN_STATE_MASK, (x))
> +#define TPS_STATUS_PP_5V0_SWITCH_MASK		GENMASK(9, 8)
> +#define TPS_STATUS_PP_5V0_SWITCH(x)		TPS_FIELD_GET(TPS_STATUS_PP_5V0_SWITCH_MASK, (x))
> +#define TPS_STATUS_PP_HV_SWITCH_MASK		GENMASK(11, 10)
> +#define TPS_STATUS_PP_HV_SWITCH(x)		TPS_FIELD_GET(TPS_STATUS_PP_HV_SWITCH_MASK, (x))
> +#define TPS_STATUS_PP_EXT_SWITCH_MASK		GENMASK(13, 12)
> +#define TPS_STATUS_PP_EXT_SWITCH(x)		TPS_FIELD_GET(TPS_STATUS_PP_EXT_SWITCH_MASK, (x))
> +#define TPS_STATUS_PP_CABLE_SWITCH_MASK		GENMASK(15, 14)
> +#define TPS_STATUS_PP_CABLE_SWITCH(x)		TPS_FIELD_GET(TPS_STATUS_PP_CABLE_SWITCH_MASK, (x))
> +#define TPS_STATUS_POWER_SOURCE_MASK		GENMASK(19, 18)
> +#define TPS_STATUS_POWER_SOURCE(x)		TPS_FIELD_GET(TPS_STATUS_POWER_SOURCE_MASK, (x))
> +#define TPS_STATUS_VBUS_STATUS_MASK		GENMASK(21, 20)
> +#define TPS_STATUS_VBUS_STATUS(x)		TPS_FIELD_GET(TPS_STATUS_VBUS_STATUS_MASK, (x))
> +#define TPS_STATUS_USB_HOST_PRESENT_MASK	GENMASK(23, 22)
> +#define TPS_STATUS_USB_HOST_PRESENT(x)		TPS_FIELD_GET(TPS_STATUS_USB_HOST_PRESENT_MASK, (x))
> +#define TPS_STATUS_LEGACY_MASK			GENMASK(25, 24)
> +#define TPS_STATUS_LEGACY(x)			TPS_FIELD_GET(TPS_STATUS_LEGACY_MASK, (x))
> +
> +#define TPS_STATUS_CONN_STATE_NO_CONN		0
> +#define TPS_STATUS_CONN_STATE_DISABLED		1
> +#define TPS_STATUS_CONN_STATE_AUDIO_CONN	2
> +#define TPS_STATUS_CONN_STATE_DEBUG_CONN	3
> +#define TPS_STATUS_CONN_STATE_NO_CONN_R_A	4
> +#define TPS_STATUS_CONN_STATE_RESERVED		5
> +#define TPS_STATUS_CONN_STATE_CONN_NO_R_A	6
> +#define TPS_STATUS_CONN_STATE_CONN_WITH_R_A	7
> +
> +#define TPS_STATUS_PP_SWITCH_STATE_DISABLED	0
> +#define TPS_STATUS_PP_SWITCH_STATE_FAULT	1
> +#define TPS_STATUS_PP_SWITCH_STATE_OUT		2
> +#define TPS_STATUS_PP_SWITCH_STATE_IN		3
> +
> +#define TPS_STATUS_POWER_SOURCE_UNKNOWN		0
> +#define TPS_STATUS_POWER_SOURCE_VIN_3P3		1
> +#define TPS_STATUS_POWER_SOURCE_DEAD_BAT	2
> +#define TPS_STATUS_POWER_SOURCE_VBUS		3
> +
> +#define TPS_STATUS_VBUS_STATUS_VSAFE0V		0
> +#define TPS_STATUS_VBUS_STATUS_VSAFE5V		1
> +#define TPS_STATUS_VBUS_STATUS_PD		2
> +#define TPS_STATUS_VBUS_STATUS_FAULT		3
> +
> +#define TPS_STATUS_USB_HOST_PRESENT_NO		0
> +#define TPS_STATUS_USB_HOST_PRESENT_PD_NO_USB	1
> +#define TPS_STATUS_USB_HOST_PRESENT_NO_PD	2
> +#define TPS_STATUS_USB_HOST_PRESENT_PD_USB	3
> +
> +#define TPS_STATUS_LEGACY_NO			0
> +#define TPS_STATUS_LEGACY_SINK			1
> +#define TPS_STATUS_LEGACY_SOURCE		2
>  
>  /* TPS_REG_INT_* bits */
>  #define TPS_REG_INT_USER_VID_ALT_MODE_OTHER_VDM		BIT_ULL(27+32)
> diff --git a/drivers/usb/typec/tps6598x_trace.h b/drivers/usb/typec/tps6598x_trace.h
> index 4ec96e3b2c3e..e0677b9c5c53 100644
> --- a/drivers/usb/typec/tps6598x_trace.h
> +++ b/drivers/usb/typec/tps6598x_trace.h
> @@ -67,6 +67,73 @@
>  		{ TPS_REG_INT_USER_VID_ALT_MODE_ATTN_VDM,	"USER_VID_ALT_MODE_ATTN_VDM" }, \
>  		{ TPS_REG_INT_USER_VID_ALT_MODE_OTHER_VDM,	"USER_VID_ALT_MODE_OTHER_VDM" })
>  
> +#define TPS6598X_STATUS_FLAGS_MASK (GENMASK(31, 0) ^ (TPS_STATUS_CONN_STATE_MASK | \
> +						      TPS_STATUS_PP_5V0_SWITCH_MASK | \
> +						      TPS_STATUS_PP_HV_SWITCH_MASK | \
> +						      TPS_STATUS_PP_EXT_SWITCH_MASK | \
> +						      TPS_STATUS_PP_CABLE_SWITCH_MASK | \
> +						      TPS_STATUS_POWER_SOURCE_MASK | \
> +						      TPS_STATUS_VBUS_STATUS_MASK | \
> +						      TPS_STATUS_USB_HOST_PRESENT_MASK | \
> +						      TPS_STATUS_LEGACY_MASK))
> +
> +#define show_status_conn_state(status) \
> +	__print_symbolic(TPS_STATUS_CONN_STATE((status)), \
> +		{ TPS_STATUS_CONN_STATE_CONN_WITH_R_A,	"conn-Ra"  }, \
> +		{ TPS_STATUS_CONN_STATE_CONN_NO_R_A,	"conn-no-Ra" }, \
> +		{ TPS_STATUS_CONN_STATE_NO_CONN_R_A,	"no-conn-Ra" },	\
> +		{ TPS_STATUS_CONN_STATE_DEBUG_CONN,	"debug"	 }, \
> +		{ TPS_STATUS_CONN_STATE_AUDIO_CONN,	"audio"	 }, \
> +		{ TPS_STATUS_CONN_STATE_DISABLED,	"disabled" }, \
> +		{ TPS_STATUS_CONN_STATE_NO_CONN,	"no-conn" })
> +
> +#define show_status_pp_switch_state(status) \
> +	__print_symbolic(status, \
> +		{ TPS_STATUS_PP_SWITCH_STATE_IN,	"in" }, \
> +		{ TPS_STATUS_PP_SWITCH_STATE_OUT,	"out" }, \
> +		{ TPS_STATUS_PP_SWITCH_STATE_FAULT,	"fault" }, \
> +		{ TPS_STATUS_PP_SWITCH_STATE_DISABLED,	"off" })
> +
> +#define show_status_power_sources(status) \
> +	__print_symbolic(TPS_STATUS_POWER_SOURCE(status), \
> +		{ TPS_STATUS_POWER_SOURCE_VBUS,		"vbus" }, \
> +		{ TPS_STATUS_POWER_SOURCE_VIN_3P3,	"vin-3p3" }, \
> +		{ TPS_STATUS_POWER_SOURCE_DEAD_BAT,	"dead-battery" }, \
> +		{ TPS_STATUS_POWER_SOURCE_UNKNOWN,	"unknown" })
> +
> +#define show_status_vbus_status(status) \
> +	__print_symbolic(TPS_STATUS_VBUS_STATUS(status), \
> +		{ TPS_STATUS_VBUS_STATUS_VSAFE0V,	"vSafe0V" }, \
> +		{ TPS_STATUS_VBUS_STATUS_VSAFE5V,	"vSafe5V" }, \
> +		{ TPS_STATUS_VBUS_STATUS_PD,		"pd" }, \
> +		{ TPS_STATUS_VBUS_STATUS_FAULT,		"fault" })
> +
> +#define show_status_usb_host_present(status) \
> +	__print_symbolic(TPS_STATUS_USB_HOST_PRESENT(status), \
> +		{ TPS_STATUS_USB_HOST_PRESENT_PD_USB,	 "pd-usb" }, \
> +		{ TPS_STATUS_USB_HOST_PRESENT_NO_PD,	 "no-pd" }, \
> +		{ TPS_STATUS_USB_HOST_PRESENT_PD_NO_USB, "pd-no-usb" }, \
> +		{ TPS_STATUS_USB_HOST_PRESENT_NO,	 "no" })
> +
> +#define show_status_legacy(status) \
> +	__print_symbolic(TPS_STATUS_LEGACY(status),	     \
> +		{ TPS_STATUS_LEGACY_SOURCE,		 "source" }, \
> +		{ TPS_STATUS_LEGACY_SINK,		 "sink" }, \
> +		{ TPS_STATUS_LEGACY_NO,			 "no" })
> +
> +#define show_status_flags(flags) \
> +	__print_flags((flags & TPS6598X_STATUS_FLAGS_MASK), "|", \
> +		      { TPS_STATUS_PLUG_PRESENT,	"PLUG_PRESENT" }, \
> +		      { TPS_STATUS_PLUG_UPSIDE_DOWN,	"UPSIDE_DOWN" }, \
> +		      { TPS_STATUS_PORTROLE,		"PORTROLE" }, \
> +		      { TPS_STATUS_DATAROLE,		"DATAROLE" }, \
> +		      { TPS_STATUS_VCONN,		"VCONN" }, \
> +		      { TPS_STATUS_OVERCURRENT,		"OVERCURRENT" }, \
> +		      { TPS_STATUS_GOTO_MIN_ACTIVE,	"GOTO_MIN_ACTIVE" }, \
> +		      { TPS_STATUS_BIST,		"BIST" }, \
> +		      { TPS_STATUS_HIGH_VOLAGE_WARNING,	"HIGH_VOLAGE_WARNING" }, \
> +		      { TPS_STATUS_HIGH_LOW_VOLTAGE_WARNING, "HIGH_LOW_VOLTAGE_WARNING" })
> +
>  TRACE_EVENT(tps6598x_irq,
>  	    TP_PROTO(u64 event1,
>  		     u64 event2),
> @@ -87,6 +154,33 @@ TRACE_EVENT(tps6598x_irq,
>  		      show_irq_flags(__entry->event2))
>  );
>  
> +TRACE_EVENT(tps6598x_status,
> +	    TP_PROTO(u32 status),
> +	    TP_ARGS(status),
> +
> +	    TP_STRUCT__entry(
> +			     __field(u32, status)
> +			     ),
> +
> +	    TP_fast_assign(
> +			   __entry->status = status;
> +			   ),
> +
> +	    TP_printk("conn: %s, pp_5v0: %s, pp_hv: %s, pp_ext: %s, pp_cable: %s, "
> +		      "pwr-src: %s, vbus: %s, usb-host: %s, legacy: %s, flags: %s",
> +		      show_status_conn_state(__entry->status),
> +		      show_status_pp_switch_state(TPS_STATUS_PP_5V0_SWITCH(__entry->status)),
> +		      show_status_pp_switch_state(TPS_STATUS_PP_HV_SWITCH(__entry->status)),
> +		      show_status_pp_switch_state(TPS_STATUS_PP_EXT_SWITCH(__entry->status)),
> +		      show_status_pp_switch_state(TPS_STATUS_PP_CABLE_SWITCH(__entry->status)),
> +		      show_status_power_sources(__entry->status),
> +		      show_status_vbus_status(__entry->status),
> +		      show_status_usb_host_present(__entry->status),
> +		      show_status_legacy(__entry->status),
> +		      show_status_flags(__entry->status)
> +		    )
> +);
> +
>  #endif /* _TPS6598X_TRACE_H_ */
>  
>  /* This part must be outside protection */
> -- 
> 2.30.0

thanks,

-- 
heikki

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v3 3/4] usb: typec: tps6598x: Add trace event for power status register
  2021-02-15 11:46 ` [PATCH v3 3/4] usb: typec: tps6598x: Add trace event for power " Guido Günther
@ 2021-03-01 15:11   ` Heikki Krogerus
  0 siblings, 0 replies; 9+ messages in thread
From: Heikki Krogerus @ 2021-03-01 15:11 UTC (permalink / raw)
  To: Guido Günther; +Cc: Greg Kroah-Hartman, linux-kernel, linux-usb

On Mon, Feb 15, 2021 at 12:46:44PM +0100, Guido Günther wrote:
> Together with the PD status register this is vital for debugging power
> negotiations at runtime.
> 
> Signed-off-by: Guido Günther <agx@sigxcpu.org>

Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>

> ---
>  drivers/usb/typec/tps6598x.c       | 19 +++++++++------
>  drivers/usb/typec/tps6598x.h       | 19 +++++++++++++++
>  drivers/usb/typec/tps6598x_trace.h | 38 ++++++++++++++++++++++++++++++
>  3 files changed, 69 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/usb/typec/tps6598x.c b/drivers/usb/typec/tps6598x.c
> index 559aa175f948..3e6ad3ba7fc8 100644
> --- a/drivers/usb/typec/tps6598x.c
> +++ b/drivers/usb/typec/tps6598x.c
> @@ -50,11 +50,6 @@ enum {
>  	TPS_PORTINFO_SOURCE,
>  };
>  
> -/* TPS_REG_POWER_STATUS bits */
> -#define TPS_POWER_STATUS_CONNECTION	BIT(0)
> -#define TPS_POWER_STATUS_SOURCESINK	BIT(1)
> -#define TPS_POWER_STATUS_PWROPMODE(p)	(((p) & GENMASK(3, 2)) >> 2)
> -
>  /* TPS_REG_RX_IDENTITY_SOP */
>  struct tps6598x_rx_identity_reg {
>  	u8 status;
> @@ -414,6 +409,7 @@ static irqreturn_t tps6598x_interrupt(int irq, void *data)
>  	u64 event1;
>  	u64 event2;
>  	u32 status;
> +	u16 pwr_status;
>  	int ret;
>  
>  	mutex_lock(&tps->lock);
> @@ -433,6 +429,15 @@ static irqreturn_t tps6598x_interrupt(int irq, void *data)
>  	}
>  	trace_tps6598x_status(status);
>  
> +	if ((event1 | event2) & TPS_REG_INT_POWER_STATUS_UPDATE) {
> +		ret = tps6598x_read16(tps, TPS_REG_POWER_STATUS, &pwr_status);
> +		if (ret < 0) {
> +			dev_err(tps->dev, "failed to read power status: %d\n", ret);
> +			goto err_clear_ints;
> +		}
> +		trace_tps6598x_power_status(pwr_status);
> +	}
> +
>  	/* Handle plug insert or removal */
>  	if ((event1 | event2) & TPS_REG_INT_PLUG_EVENT) {
>  		if (status & TPS_STATUS_PLUG_PRESENT) {
> @@ -497,8 +502,8 @@ static int tps6598x_psy_get_online(struct tps6598x *tps,
>  	if (ret < 0)
>  		return ret;
>  
> -	if ((pwr_status & TPS_POWER_STATUS_CONNECTION) &&
> -	    (pwr_status & TPS_POWER_STATUS_SOURCESINK)) {
> +	if (TPS_POWER_STATUS_CONNECTION(pwr_status) &&
> +	    TPS_POWER_STATUS_SOURCESINK(pwr_status)) {
>  		val->intval = 1;
>  	} else {
>  		val->intval = 0;
> diff --git a/drivers/usb/typec/tps6598x.h b/drivers/usb/typec/tps6598x.h
> index 621fb336c15d..9a34c020f3e5 100644
> --- a/drivers/usb/typec/tps6598x.h
> +++ b/drivers/usb/typec/tps6598x.h
> @@ -129,4 +129,23 @@
>  #define TPS_REG_INT_HARD_RESET				BIT(1)
>  #define TPS_REG_INT_PD_SOFT_RESET			BIT(0)
>  
> +/* TPS_REG_POWER_STATUS bits */
> +#define TPS_POWER_STATUS_CONNECTION(x)  TPS_FIELD_GET(BIT(0), (x))
> +#define TPS_POWER_STATUS_SOURCESINK(x)	TPS_FIELD_GET(BIT(1), (x))
> +#define TPS_POWER_STATUS_BC12_DET(x)	TPS_FIELD_GET(BIT(2), (x))
> +
> +#define TPS_POWER_STATUS_TYPEC_CURRENT_MASK GENMASK(3, 2)
> +#define TPS_POWER_STATUS_PWROPMODE(p)	    TPS_FIELD_GET(TPS_POWER_STATUS_TYPEC_CURRENT_MASK, (p))
> +#define TPS_POWER_STATUS_BC12_STATUS_MASK   GENMASK(6, 5)
> +#define TPS_POWER_STATUS_BC12_STATUS(p)	    TPS_FIELD_GET(TPS_POWER_STATUS_BC12_STATUS_MASK, (p))
> +
> +#define TPS_POWER_STATUS_TYPEC_CURRENT_USB     0
> +#define TPS_POWER_STATUS_TYPEC_CURRENT_1A5     1
> +#define TPS_POWER_STATUS_TYPEC_CURRENT_3A0     2
> +#define TPS_POWER_STATUS_TYPEC_CURRENT_PD      3
> +
> +#define TPS_POWER_STATUS_BC12_STATUS_SDP 0
> +#define TPS_POWER_STATUS_BC12_STATUS_CDP 2
> +#define TPS_POWER_STATUS_BC12_STATUS_DCP 3
> +
>  #endif /* __TPS6598X_H__ */
> diff --git a/drivers/usb/typec/tps6598x_trace.h b/drivers/usb/typec/tps6598x_trace.h
> index e0677b9c5c53..78a5a6ca337b 100644
> --- a/drivers/usb/typec/tps6598x_trace.h
> +++ b/drivers/usb/typec/tps6598x_trace.h
> @@ -134,6 +134,24 @@
>  		      { TPS_STATUS_HIGH_VOLAGE_WARNING,	"HIGH_VOLAGE_WARNING" }, \
>  		      { TPS_STATUS_HIGH_LOW_VOLTAGE_WARNING, "HIGH_LOW_VOLTAGE_WARNING" })
>  
> +#define show_power_status_source_sink(power_status) \
> +	__print_symbolic(TPS_POWER_STATUS_SOURCESINK(power_status), \
> +		{ 1, "sink" }, \
> +		{ 0, "source" })
> +
> +#define show_power_status_typec_status(power_status) \
> +	__print_symbolic(TPS_POWER_STATUS_PWROPMODE(power_status), \
> +		{ TPS_POWER_STATUS_TYPEC_CURRENT_PD,  "pd" }, \
> +		{ TPS_POWER_STATUS_TYPEC_CURRENT_3A0, "3.0A" }, \
> +		{ TPS_POWER_STATUS_TYPEC_CURRENT_1A5, "1.5A" }, \
> +		{ TPS_POWER_STATUS_TYPEC_CURRENT_USB, "usb" })
> +
> +#define show_power_status_bc12_status(power_status) \
> +	__print_symbolic(TPS_POWER_STATUS_BC12_STATUS(power_status), \
> +		{ TPS_POWER_STATUS_BC12_STATUS_DCP, "dcp" }, \
> +		{ TPS_POWER_STATUS_BC12_STATUS_CDP, "cdp" }, \
> +		{ TPS_POWER_STATUS_BC12_STATUS_SDP, "sdp" })
> +
>  TRACE_EVENT(tps6598x_irq,
>  	    TP_PROTO(u64 event1,
>  		     u64 event2),
> @@ -181,6 +199,26 @@ TRACE_EVENT(tps6598x_status,
>  		    )
>  );
>  
> +TRACE_EVENT(tps6598x_power_status,
> +	    TP_PROTO(u16 power_status),
> +	    TP_ARGS(power_status),
> +
> +	    TP_STRUCT__entry(
> +			     __field(u16, power_status)
> +			     ),
> +
> +	    TP_fast_assign(
> +			   __entry->power_status = power_status;
> +			   ),
> +
> +	    TP_printk("conn: %d, pwr-role: %s, typec: %s, bc: %s",
> +		      !!TPS_POWER_STATUS_CONNECTION(__entry->power_status),
> +		      show_power_status_source_sink(__entry->power_status),
> +		      show_power_status_typec_status(__entry->power_status),
> +		      show_power_status_bc12_status(__entry->power_status)
> +		    )
> +);
> +
>  #endif /* _TPS6598X_TRACE_H_ */
>  
>  /* This part must be outside protection */
> -- 
> 2.30.0

thanks,

-- 
heikki

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v3 4/4] usb: typec: tps6598x: Add trace event for data status
  2021-02-15 11:46 ` [PATCH v3 4/4] usb: typec: tps6598x: Add trace event for data status Guido Günther
@ 2021-03-01 15:12   ` Heikki Krogerus
  0 siblings, 0 replies; 9+ messages in thread
From: Heikki Krogerus @ 2021-03-01 15:12 UTC (permalink / raw)
  To: Guido Günther; +Cc: Greg Kroah-Hartman, linux-kernel, linux-usb

On Mon, Feb 15, 2021 at 12:46:45PM +0100, Guido Günther wrote:
> This is useful to debug DP negotiation and pin assignment even
> when the firmware does all the work.
> 
> Signed-off-by: Guido Günther <agx@sigxcpu.org>

Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>

> ---
>  drivers/usb/typec/tps6598x.c       | 12 ++++++-
>  drivers/usb/typec/tps6598x.h       | 38 +++++++++++++++++++++
>  drivers/usb/typec/tps6598x_trace.h | 54 ++++++++++++++++++++++++++++++
>  3 files changed, 103 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/usb/typec/tps6598x.c b/drivers/usb/typec/tps6598x.c
> index 3e6ad3ba7fc8..a4ec8e56c2b9 100644
> --- a/drivers/usb/typec/tps6598x.c
> +++ b/drivers/usb/typec/tps6598x.c
> @@ -36,6 +36,7 @@
>  #define TPS_REG_CTRL_CONF		0x29
>  #define TPS_REG_POWER_STATUS		0x3f
>  #define TPS_REG_RX_IDENTITY_SOP		0x48
> +#define TPS_REG_DATA_STATUS		0x5f
>  
>  /* TPS_REG_SYSTEM_CONF bits */
>  #define TPS_SYSCONF_PORTINFO(c)		((c) & 7)
> @@ -408,7 +409,7 @@ static irqreturn_t tps6598x_interrupt(int irq, void *data)
>  	struct tps6598x *tps = data;
>  	u64 event1;
>  	u64 event2;
> -	u32 status;
> +	u32 status, data_status;
>  	u16 pwr_status;
>  	int ret;
>  
> @@ -438,6 +439,15 @@ static irqreturn_t tps6598x_interrupt(int irq, void *data)
>  		trace_tps6598x_power_status(pwr_status);
>  	}
>  
> +	if ((event1 | event2) & TPS_REG_INT_DATA_STATUS_UPDATE) {
> +		ret = tps6598x_read32(tps, TPS_REG_DATA_STATUS, &data_status);
> +		if (ret < 0) {
> +			dev_err(tps->dev, "failed to read data status: %d\n", ret);
> +			goto err_clear_ints;
> +		}
> +		trace_tps6598x_data_status(data_status);
> +	}
> +
>  	/* Handle plug insert or removal */
>  	if ((event1 | event2) & TPS_REG_INT_PLUG_EVENT) {
>  		if (status & TPS_STATUS_PLUG_PRESENT) {
> diff --git a/drivers/usb/typec/tps6598x.h b/drivers/usb/typec/tps6598x.h
> index 9a34c020f3e5..003a577be216 100644
> --- a/drivers/usb/typec/tps6598x.h
> +++ b/drivers/usb/typec/tps6598x.h
> @@ -148,4 +148,42 @@
>  #define TPS_POWER_STATUS_BC12_STATUS_CDP 2
>  #define TPS_POWER_STATUS_BC12_STATUS_DCP 3
>  
> +/* TPS_REG_DATA_STATUS bits */
> +#define TPS_DATA_STATUS_DATA_CONNECTION	     BIT(0)
> +#define TPS_DATA_STATUS_UPSIDE_DOWN	     BIT(1)
> +#define TPS_DATA_STATUS_ACTIVE_CABLE	     BIT(2)
> +#define TPS_DATA_STATUS_USB2_CONNECTION	     BIT(4)
> +#define TPS_DATA_STATUS_USB3_CONNECTION	     BIT(5)
> +#define TPS_DATA_STATUS_USB3_GEN2	     BIT(6)
> +#define TPS_DATA_STATUS_USB_DATA_ROLE	     BIT(7)
> +#define TPS_DATA_STATUS_DP_CONNECTION	     BIT(8)
> +#define TPS_DATA_STATUS_DP_SINK		     BIT(9)
> +#define TPS_DATA_STATUS_TBT_CONNECTION	     BIT(16)
> +#define TPS_DATA_STATUS_TBT_TYPE	     BIT(17)
> +#define TPS_DATA_STATUS_OPTICAL_CABLE	     BIT(18)
> +#define TPS_DATA_STATUS_ACTIVE_LINK_TRAIN    BIT(20)
> +#define TPS_DATA_STATUS_FORCE_LSX	     BIT(23)
> +#define TPS_DATA_STATUS_POWER_MISMATCH	     BIT(24)
> +
> +#define TPS_DATA_STATUS_DP_PIN_ASSIGNMENT_MASK GENMASK(11, 10)
> +#define TPS_DATA_STATUS_DP_PIN_ASSIGNMENT(x) \
> +	TPS_FIELD_GET(TPS_DATA_STATUS_DP_PIN_ASSIGNMENT_MASK, (x))
> +#define TPS_DATA_STATUS_TBT_CABLE_SPEED_MASK   GENMASK(27, 25)
> +#define TPS_DATA_STATUS_TBT_CABLE_SPEED \
> +	TPS_FIELD_GET(TPS_DATA_STATUS_TBT_CABLE_SPEED_MASK, (x))
> +#define TPS_DATA_STATUS_TBT_CABLE_GEN_MASK     GENMASK(29, 28)
> +#define TPS_DATA_STATUS_TBT_CABLE_GEN \
> +	TPS_FIELD_GET(TPS_DATA_STATUS_TBT_CABLE_GEN_MASK, (x))
> +
> +/* Map data status to DP spec assignments */
> +#define TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT(x) \
> +	((TPS_DATA_STATUS_DP_PIN_ASSIGNMENT(x) << 1) | \
> +		TPS_FIELD_GET(TPS_DATA_STATUS_USB3_CONNECTION, (x)))
> +#define TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT_E    0
> +#define TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT_F    BIT(0)
> +#define TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT_C    BIT(1)
> +#define TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT_D    (BIT(1) | BIT(0))
> +#define TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT_A    BIT(2)
> +#define TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT_B    (BIT(2) | BIT(1))
> +
>  #endif /* __TPS6598X_H__ */
> diff --git a/drivers/usb/typec/tps6598x_trace.h b/drivers/usb/typec/tps6598x_trace.h
> index 78a5a6ca337b..38bfb2f04e46 100644
> --- a/drivers/usb/typec/tps6598x_trace.h
> +++ b/drivers/usb/typec/tps6598x_trace.h
> @@ -152,6 +152,41 @@
>  		{ TPS_POWER_STATUS_BC12_STATUS_CDP, "cdp" }, \
>  		{ TPS_POWER_STATUS_BC12_STATUS_SDP, "sdp" })
>  
> +#define TPS_DATA_STATUS_FLAGS_MASK (GENMASK(31, 0) ^ (TPS_DATA_STATUS_DP_PIN_ASSIGNMENT_MASK | \
> +						      TPS_DATA_STATUS_TBT_CABLE_SPEED_MASK | \
> +						      TPS_DATA_STATUS_TBT_CABLE_GEN_MASK))
> +
> +#define show_data_status_flags(data_status) \
> +	__print_flags(data_status & TPS_DATA_STATUS_FLAGS_MASK, "|", \
> +		{ TPS_DATA_STATUS_DATA_CONNECTION,	"DATA_CONNECTION" }, \
> +		{ TPS_DATA_STATUS_UPSIDE_DOWN,		"DATA_UPSIDE_DOWN" }, \
> +		{ TPS_DATA_STATUS_ACTIVE_CABLE,		"ACTIVE_CABLE" }, \
> +		{ TPS_DATA_STATUS_USB2_CONNECTION,	"USB2_CONNECTION" }, \
> +		{ TPS_DATA_STATUS_USB3_CONNECTION,	"USB3_CONNECTION" }, \
> +		{ TPS_DATA_STATUS_USB3_GEN2,		"USB3_GEN2" }, \
> +		{ TPS_DATA_STATUS_USB_DATA_ROLE,	"USB_DATA_ROLE" }, \
> +		{ TPS_DATA_STATUS_DP_CONNECTION,	"DP_CONNECTION" }, \
> +		{ TPS_DATA_STATUS_DP_SINK,		"DP_SINK" }, \
> +		{ TPS_DATA_STATUS_TBT_CONNECTION,	"TBT_CONNECTION" }, \
> +		{ TPS_DATA_STATUS_TBT_TYPE,		"TBT_TYPE" }, \
> +		{ TPS_DATA_STATUS_OPTICAL_CABLE,	"OPTICAL_CABLE" }, \
> +		{ TPS_DATA_STATUS_ACTIVE_LINK_TRAIN,	"ACTIVE_LINK_TRAIN" }, \
> +		{ TPS_DATA_STATUS_FORCE_LSX,		"FORCE_LSX" }, \
> +		{ TPS_DATA_STATUS_POWER_MISMATCH,	"POWER_MISMATCH" })
> +
> +#define show_data_status_dp_pin_assignment(data_status) \
> +	__print_symbolic(TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT(data_status), \
> +		{ TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT_E, "E" }, \
> +		{ TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT_F, "F" }, \
> +		{ TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT_C, "C" }, \
> +		{ TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT_D, "D" }, \
> +		{ TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT_A, "A" }, \
> +		{ TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT_B, "B" })
> +
> +#define maybe_show_data_status_dp_pin_assignment(data_status) \
> +	(data_status & TPS_DATA_STATUS_DP_CONNECTION ? \
> +	 show_data_status_dp_pin_assignment(data_status) : "")
> +
>  TRACE_EVENT(tps6598x_irq,
>  	    TP_PROTO(u64 event1,
>  		     u64 event2),
> @@ -219,6 +254,25 @@ TRACE_EVENT(tps6598x_power_status,
>  		    )
>  );
>  
> +TRACE_EVENT(tps6598x_data_status,
> +	    TP_PROTO(u32 data_status),
> +	    TP_ARGS(data_status),
> +
> +	    TP_STRUCT__entry(
> +			     __field(u32, data_status)
> +			     ),
> +
> +	    TP_fast_assign(
> +			   __entry->data_status = data_status;
> +			   ),
> +
> +	    TP_printk("%s%s%s",
> +		      show_data_status_flags(__entry->data_status),
> +		      __entry->data_status & TPS_DATA_STATUS_DP_CONNECTION ? ", DP pinout " : "",
> +		      maybe_show_data_status_dp_pin_assignment(__entry->data_status)
> +		    )
> +);
> +
>  #endif /* _TPS6598X_TRACE_H_ */
>  
>  /* This part must be outside protection */
> -- 
> 2.30.0

thanks,

-- 
heikki

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2021-03-01 15:16 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-02-15 11:46 [PATCH v3 0/4] usb: typec: tps6598x: Add IRQ flag and register tracing Guido Günther
2021-02-15 11:46 ` [PATCH v3 1/4] usb: typec: tps6598x: Add trace event for IRQ events Guido Günther
2021-03-01 15:09   ` Heikki Krogerus
2021-02-15 11:46 ` [PATCH v3 2/4] usb: typec: tps6598x: Add trace event for status register Guido Günther
2021-03-01 15:10   ` Heikki Krogerus
2021-02-15 11:46 ` [PATCH v3 3/4] usb: typec: tps6598x: Add trace event for power " Guido Günther
2021-03-01 15:11   ` Heikki Krogerus
2021-02-15 11:46 ` [PATCH v3 4/4] usb: typec: tps6598x: Add trace event for data status Guido Günther
2021-03-01 15:12   ` Heikki Krogerus

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).