uwb: add sscd functionality to qm35 driver

Bug: 272537946
Change-Id: I0432ce8eae65103e3eae46b69ae0836b1aabd859
Signed-off-by: Hasan Awais <hasanawais@google.com>
(cherry picked from commit 52a00971ebd06b321fb9b040227bc53fa689606c)
diff --git a/BUILD.bazel b/BUILD.bazel
index 79dc4bc..47ced9b 100644
--- a/BUILD.bazel
+++ b/BUILD.bazel
@@ -8,7 +8,9 @@
         "**/*.c",
         "**/*.h",
         "Kbuild",
-    ]),
+    ]) + [
+        "//private/google-modules/soc/gs:gs_soc_headers",
+    ],
     outs = [
         "qm35.ko",
     ],
@@ -17,4 +19,7 @@
         "//private/devices/google:__subpackages__",
         "//private/google-modules/soc/gs:__pkg__",
     ],
+    deps = [
+        "//private/google-modules/soc/gs:gs_soc_module",
+    ],
 )
diff --git a/Kbuild b/Kbuild
index 7e16ab7..3e4f197 100644
--- a/Kbuild
+++ b/Kbuild
@@ -4,6 +4,7 @@
 
 qm35-y := \
 	qm35-spi.o \
+	qm35-sscd.o \
 	qm35_rb.o \
 	qmrom_spi.o \
 	libqmrom/src/qmrom_common.o \
diff --git a/Makefile b/Makefile
index fae1a30..1734d94 100644
--- a/Makefile
+++ b/Makefile
@@ -8,5 +8,8 @@
 
 KBUILD_OPTIONS += CONFIG_QM35_SPI=m
 
+include $(KERNEL_SRC)/../private/google-modules/soc/gs/Makefile.include
+
 modules modules_install clean:
-	$(MAKE) -C $(KERNEL_SRC) M=$(M) INSTALL_MOD_STRIP=1 $(KBUILD_OPTIONS) $(@)
+	$(MAKE) -C $(KERNEL_SRC) M=$(M) INSTALL_MOD_STRIP=1 \
+	$(KBUILD_OPTIONS) KBUILD_EXTRA_SYMBOLS="$(EXTRA_SYMBOLS)" $(@)
diff --git a/hsspi_coredump.c b/hsspi_coredump.c
index 0172ef4..ec7cc25 100644
--- a/hsspi_coredump.c
+++ b/hsspi_coredump.c
@@ -28,6 +28,7 @@
 
 #include "qm35.h"
 #include "hsspi_coredump.h"
+#include "qm35-sscd.h"
 
 #define COREDUMP_HEADER_NTF 0x00
 #define COREDUMP_BODY_NTF 0x01
@@ -206,6 +207,9 @@
 	struct coredump_layer *layer =
 		container_of(hlayer, struct coredump_layer, hlayer);
 
+	struct qm35_ctx *qm35_hdl =
+		container_of(layer, struct qm35_ctx, coredump_layer);
+
 	if (status)
 		goto out;
 
@@ -252,6 +256,9 @@
 			if (crc == layer->coredump_crc)
 				layer->coredump_status = COREDUMP_RCV_ACK;
 
+			if (qm35_hdl->sscd)
+				report_coredump(qm35_hdl);
+
 			coredump_send_rcv_status(layer, layer->coredump_status);
 
 			break;
diff --git a/qm35-spi.c b/qm35-spi.c
index c39f944..0928d8c 100644
--- a/qm35-spi.c
+++ b/qm35-spi.c
@@ -53,6 +53,7 @@
 #include <fwupdater.h>
 
 #include "qm35.h"
+#include "qm35-sscd.h"
 #include "uci_ioctls.h"
 #include "hsspi.h"
 #include "hsspi_uci.h"
@@ -1011,6 +1012,11 @@
 		goto log_layer_unregister;
 	}
 
+	dev_dbg(&spi->dev, "SSCD device init\n");
+	ret = register_coredump(spi, qm35_ctx);
+	if (ret)
+		goto sscd_unregister;
+
 	dev_info(&spi->dev, "Registered: [%s] misc device\n", uci_misc->name);
 
 	dev_info(&spi->dev, "QM35 spi driver version " DRV_VERSION " probed\n");
@@ -1032,6 +1038,8 @@
 	uci_layer_deinit(&qm35_ctx->uci_layer);
 hsspi_deinit:
 	hsspi_deinit(&qm35_ctx->hsspi);
+sscd_unregister:
+	unregister_coredump(qm35_ctx->sscd);
 poweroff:
 	qm35_regulators_set(qm35_ctx, false);
 	return ret;
diff --git a/qm35-sscd.c b/qm35-sscd.c
new file mode 100644
index 0000000..b02647e
--- /dev/null
+++ b/qm35-sscd.c
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include "qm35-sscd.h"
+
+#define NAME "uwb"
+
+void release_coredump(struct device *dev)
+{
+}
+
+int report_coredump(struct qm35_ctx *qm35_ctx)
+{
+	struct coredump_layer *layer = &qm35_ctx->coredump_layer;
+	struct sscd_platform_data *sscd_pdata = &qm35_ctx->sscd->sscd_pdata;
+	struct sscd_info *sscd_info = &qm35_ctx->sscd->sscd_info;
+
+	if (!layer || !sscd_pdata || !sscd_info || !sscd_pdata->sscd_report)
+		return 1;
+
+	sscd_info->seg_count = 0;
+	sscd_info->name = NAME;
+	sscd_info->segs[0].addr = layer->coredump_data;
+	sscd_info->segs[0].size = layer->coredump_size;
+	sscd_info->seg_count = 1;
+
+	return sscd_pdata->sscd_report(&qm35_ctx->sscd->sscd_dev,
+					sscd_info->segs, sscd_info->seg_count, 0,
+					"qm35 coredump");
+}
+
+int register_coredump(struct spi_device *spi, struct qm35_ctx *qm35_ctx)
+{
+	struct sscd_desc *sscd;
+	sscd = devm_kzalloc(&spi->dev, sizeof(*sscd), GFP_KERNEL);
+	if (!sscd)
+		return -ENOMEM;
+
+	sscd->sscd_dev.name = NAME;
+	sscd->sscd_dev.driver_override = SSCD_NAME;
+	sscd->sscd_dev.id = -1;
+	sscd->sscd_dev.dev.platform_data = &sscd->sscd_pdata;
+	sscd->sscd_dev.dev.release = release_coredump;
+
+	qm35_ctx->sscd = sscd;
+	return platform_device_register(&qm35_ctx->sscd->sscd_dev);
+}
+
+void unregister_coredump(struct sscd_desc *sscd)
+{
+	platform_device_unregister(&sscd->sscd_dev);
+}
diff --git a/qm35-sscd.h b/qm35-sscd.h
new file mode 100644
index 0000000..8c90eb0
--- /dev/null
+++ b/qm35-sscd.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __QM35_SSCD__
+#define __QM35_SSCD__
+
+#include <linux/platform_data/sscoredump.h>
+#include "qm35.h"
+#include "hsspi_coredump.h"
+
+#define QM35_COREDUMP_SEGMENTS 1
+
+struct sscd_info {
+	char *name;
+	struct sscd_segment segs[QM35_COREDUMP_SEGMENTS];
+	u16 seg_count;
+};
+
+struct sscd_desc {
+	struct sscd_info sscd_info;
+	struct sscd_platform_data sscd_pdata;
+	struct platform_device sscd_dev;
+};
+
+int report_coredump(struct qm35_ctx *qm35_ctx);
+int register_coredump(struct spi_device *spi, struct qm35_ctx *qm35_ctx);
+void unregister_coredump(struct sscd_desc *sscd);
+
+#endif /* __QM35_SSCD__ */
diff --git a/qm35.h b/qm35.h
index 7bc3d70..81f4240 100644
--- a/qm35.h
+++ b/qm35.h
@@ -61,6 +61,7 @@
 	struct regulator *vdd4;
 	bool regulators_enabled;
 	bool log_qm_traces;
+	struct sscd_desc *sscd;
 
 	/* qmrom support */
 	struct wait_queue_head qmrom_wq_ready;