summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAurora zuma automerger <aurora-zuma-automerger@google.com>2023-03-16 06:57:53 +0000
committerCopybara-Service <copybara-worker@google.com>2023-03-20 20:47:52 -0700
commit2ad1089b18c3ff61ee3423c36347b0c3b95cdfa2 (patch)
treea465c2534bbf106ddeef6308de5a59d8c4a812b1
parent1bece40209e7b86b40b77aa80665c484052e0ee0 (diff)
downloadzuma-2ad1089b18c3ff61ee3423c36347b0c3b95cdfa2.tar.gz
gxp: [Copybara Auto Merge] Merge branch 'zuma' into 'android14-gs-pixel-5.15'
gxp: Add GXP device in /sys/class Bug: 271952597 gxp: Add functions gxp_common_platform_[init|exit] Bug: 271952597 (repeat) gxp: set a value to KCI mbox on HW wdg handling Bug: 270655971 GitOrigin-RevId: 515179bb221ab807e3f5384fbad9eb3a74324dc8 Change-Id: Id7a3dd217af58bbda6801b8e76871b3f94cf5491
-rw-r--r--callisto-platform.c9
-rw-r--r--callisto/mailbox-regs.h1
-rw-r--r--gxp-common-platform.c99
-rw-r--r--gxp-internal.h5
-rw-r--r--gxp-mailbox-driver.c5
-rw-r--r--gxp-mailbox-driver.h2
-rw-r--r--gxp-mailbox.h3
-rw-r--r--gxp-mcu-firmware.c6
8 files changed, 115 insertions, 15 deletions
diff --git a/callisto-platform.c b/callisto-platform.c
index 8ccd526..838f066 100644
--- a/callisto-platform.c
+++ b/callisto-platform.c
@@ -118,14 +118,19 @@ static struct platform_driver gxp_platform_driver = {
static int __init gxp_platform_init(void)
{
- gxp_common_platform_reg_sscd();
+ int ret;
+
+ ret = gxp_common_platform_init();
+ if (ret)
+ return ret;
+
return platform_driver_register(&gxp_platform_driver);
}
static void __exit gxp_platform_exit(void)
{
platform_driver_unregister(&gxp_platform_driver);
- gxp_common_platform_unreg_sscd();
+ gxp_common_platform_exit();
}
MODULE_DESCRIPTION("Google GXP platform driver");
diff --git a/callisto/mailbox-regs.h b/callisto/mailbox-regs.h
index 6baefed..89880c3 100644
--- a/callisto/mailbox-regs.h
+++ b/callisto/mailbox-regs.h
@@ -26,5 +26,6 @@
#define MBOX_DATA_DESCRIPTOR_ADDR_OFFSET 0x04
#define MBOX_DATA_CMD_TAIL_RESP_HEAD_OFFSET 0x08
#define MBOX_DATA_CMD_HEAD_RESP_TAIL_OFFSET 0x0C
+#define MBOX_DATA_CONTROL_OFFSET 0x30
#endif /* __CALLISTO_MAILBOX_REGS_H__ */
diff --git a/gxp-common-platform.c b/gxp-common-platform.c
index 5767377..37c1654 100644
--- a/gxp-common-platform.c
+++ b/gxp-common-platform.c
@@ -10,11 +10,11 @@
#endif
#include <linux/bitops.h>
+#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/file.h>
#include <linux/fs.h>
-#include <linux/miscdevice.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
@@ -59,7 +59,12 @@
#include "gxp-dci.h"
#endif
+/* We will only have one gxp device */
+#define GXP_DEV_COUNT 1
+
static struct gxp_dev *gxp_debug_pointer;
+static struct class *gxp_class;
+static dev_t gxp_base_devno;
/* Caller needs to hold client->semaphore for reading */
static bool check_client_has_available_vd_wakelock(struct gxp_client *client,
@@ -142,8 +147,8 @@ static const uint aur_memory_state_array[MEMORY_POWER_STATE_MAX + 1] = {
static int gxp_open(struct inode *inode, struct file *file)
{
struct gxp_client *client;
- struct gxp_dev *gxp = container_of(file->private_data, struct gxp_dev,
- misc_dev);
+ struct gxp_dev *gxp =
+ container_of(inode->i_cdev, struct gxp_dev, char_dev);
int ret = 0;
/* If this is the first call to open(), load the firmware files */
@@ -1912,6 +1917,71 @@ static void gxp_put_gsa_dev(struct gxp_dev *gxp)
put_device(gxp->gsa_dev);
}
+static int gxp_device_add(struct gxp_dev *gxp)
+{
+ int ret;
+ struct device *dev;
+
+ dev_dbg(gxp->dev, "adding interface: %s", GXP_NAME);
+
+ gxp->char_dev_no = MKDEV(MAJOR(gxp_base_devno), 0);
+ cdev_init(&gxp->char_dev, &gxp_fops);
+ ret = cdev_add(&gxp->char_dev, gxp->char_dev_no, 1);
+ if (ret) {
+ dev_err(gxp->dev, "error %d adding cdev for dev %d:%d\n", ret,
+ MAJOR(gxp->char_dev_no), MINOR(gxp->char_dev_no));
+ return ret;
+ }
+
+ /*
+ * We only need char_dev_no for device_destroy, no need to record the
+ * returned dev.
+ */
+ dev = device_create(gxp_class, gxp->dev, gxp->char_dev_no, gxp, "%s",
+ GXP_NAME);
+ if (IS_ERR(dev)) {
+ ret = PTR_ERR(dev);
+ dev_err(gxp->dev, "failed to create char device: %d\n", ret);
+ cdev_del(&gxp->char_dev);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void gxp_device_remove(struct gxp_dev *gxp)
+{
+ device_destroy(gxp_class, gxp->char_dev_no);
+ cdev_del(&gxp->char_dev);
+}
+
+static __init int gxp_fs_init(void)
+{
+ int ret;
+
+ gxp_class = class_create(THIS_MODULE, GXP_NAME);
+ if (IS_ERR(gxp_class)) {
+ pr_err(GXP_NAME " error creating gxp class: %ld\n",
+ PTR_ERR(gxp_class));
+ return PTR_ERR(gxp_class);
+ }
+
+ ret = alloc_chrdev_region(&gxp_base_devno, 0, GXP_DEV_COUNT, GXP_NAME);
+ if (ret) {
+ pr_err(GXP_NAME " char device registration failed: %d\n", ret);
+ class_destroy(gxp_class);
+ return ret;
+ }
+ pr_debug(GXP_NAME " registered major=%d\n", MAJOR(gxp_base_devno));
+ return 0;
+}
+
+static __exit void gxp_fs_exit(void)
+{
+ unregister_chrdev_region(gxp_base_devno, GXP_DEV_COUNT);
+ class_destroy(gxp_class);
+}
+
static int gxp_common_platform_probe(struct platform_device *pdev, struct gxp_dev *gxp)
{
struct device *dev = &pdev->dev;
@@ -2054,14 +2124,9 @@ static int gxp_common_platform_probe(struct platform_device *pdev, struct gxp_de
*/
gxp_fw_data_populate_system_config(gxp);
- gxp->misc_dev.minor = MISC_DYNAMIC_MINOR;
- gxp->misc_dev.name = GXP_NAME;
- gxp->misc_dev.fops = &gxp_fops;
- ret = misc_register(&gxp->misc_dev);
- if (ret) {
- dev_err(dev, "Failed to register misc device: %d", ret);
+ ret = gxp_device_add(gxp);
+ if (ret)
goto err_before_remove;
- }
gxp_create_debugfs(gxp);
gxp_debug_pointer = gxp;
@@ -2112,7 +2177,7 @@ static int gxp_common_platform_remove(struct platform_device *pdev)
*/
gxp_thermal_exit(gxp);
gxp_remove_debugdir(gxp);
- misc_deregister(&gxp->misc_dev);
+ gxp_device_remove(gxp);
if (gxp->before_remove)
gxp->before_remove(gxp);
gxp_core_telemetry_exit(gxp);
@@ -2133,6 +2198,18 @@ static int gxp_common_platform_remove(struct platform_device *pdev)
return 0;
}
+static int __init gxp_common_platform_init(void)
+{
+ gxp_common_platform_reg_sscd();
+ return gxp_fs_init();
+}
+
+static void __exit gxp_common_platform_exit(void)
+{
+ gxp_fs_exit();
+ gxp_common_platform_unreg_sscd();
+}
+
#if IS_ENABLED(CONFIG_PM_SLEEP)
static int gxp_platform_suspend(struct device *dev)
diff --git a/gxp-internal.h b/gxp-internal.h
index c1a5bf0..ba4cf7b 100644
--- a/gxp-internal.h
+++ b/gxp-internal.h
@@ -8,6 +8,7 @@
#define __GXP_INTERNAL_H__
#include <linux/atomic.h>
+#include <linux/cdev.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/firmware.h>
@@ -15,7 +16,6 @@
#include <linux/io.h>
#include <linux/iommu.h>
#include <linux/list.h>
-#include <linux/miscdevice.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/of_address.h>
@@ -74,7 +74,8 @@ struct gxp_power_states;
struct gxp_dev {
struct device *dev; /* platform bus device */
- struct miscdevice misc_dev; /* misc device structure */
+ struct cdev char_dev; /* char device structure */
+ dev_t char_dev_no;
struct dentry *d_entry; /* debugfs dir for this device */
struct gxp_mapped_resource regs; /* ioremapped CSRs */
struct gxp_mapped_resource lpm_regs; /* ioremapped LPM CSRs, may be equal to @regs */
diff --git a/gxp-mailbox-driver.c b/gxp-mailbox-driver.c
index 40fdba1..8d610c3 100644
--- a/gxp-mailbox-driver.c
+++ b/gxp-mailbox-driver.c
@@ -301,6 +301,11 @@ void gxp_mailbox_set_resp_queue_head(struct gxp_mailbox *mailbox, u32 value)
gxp_mailbox_write_resp_queue_head(mailbox, value);
}
+void gxp_mailbox_set_control(struct gxp_mailbox *mailbox, u32 val)
+{
+ data_write(mailbox, MBOX_DATA_CONTROL_OFFSET, val);
+}
+
int gxp_mailbox_inc_cmd_queue_tail_nolock(struct gxp_mailbox *mailbox, u32 inc,
u32 wrap_bit)
{
diff --git a/gxp-mailbox-driver.h b/gxp-mailbox-driver.h
index 30292d2..4eaf36b 100644
--- a/gxp-mailbox-driver.h
+++ b/gxp-mailbox-driver.h
@@ -75,6 +75,8 @@ void gxp_mailbox_set_cmd_queue_tail(struct gxp_mailbox *mailbox, u32 value);
/* Sets mailbox->resp_queue_head and corresponding CSR on device. */
void gxp_mailbox_set_resp_queue_head(struct gxp_mailbox *mailbox, u32 value);
+void gxp_mailbox_set_control(struct gxp_mailbox *mailbox, u32 val);
+
/*
* Increases the command queue tail by @inc.
*
diff --git a/gxp-mailbox.h b/gxp-mailbox.h
index cf72fbe..887578e 100644
--- a/gxp-mailbox.h
+++ b/gxp-mailbox.h
@@ -20,6 +20,9 @@
#include <gcip/gcip-mailbox.h>
#endif
+/* Pre-agreed values can be passed to gxp_mailbox_set_control(). */
+#define GXP_MBOX_CONTROL_MAGIC_POWER_DOWN (0xcafebabeu)
+
/*
* Offset from the host mailbox interface to the device interface that needs to
* be mapped.
diff --git a/gxp-mcu-firmware.c b/gxp-mcu-firmware.c
index bae6853..6c39e52 100644
--- a/gxp-mcu-firmware.c
+++ b/gxp-mcu-firmware.c
@@ -29,7 +29,9 @@
#include "gxp-internal.h"
#include "gxp-kci.h"
#include "gxp-lpm.h"
+#include "gxp-mailbox-driver.h"
#include "gxp-mcu-firmware.h"
+#include "gxp-mcu-platform.h"
#include "gxp-mcu.h"
#include "gxp-pm.h"
@@ -583,6 +585,10 @@ void gxp_mcu_firmware_crash_handler(struct gxp_dev *gxp,
* fall into the WFI mode. We have to trigger the doorbell to let the MCU do that.
*/
if (crash_type == GCIP_FW_CRASH_HW_WDG_TIMEOUT) {
+ struct gxp_mcu *mcu = &to_mcu_dev(gxp)->mcu;
+
+ gxp_mailbox_set_control(mcu->kci.mbx,
+ GXP_MBOX_CONTROL_MAGIC_POWER_DOWN);
gxp_doorbell_enable_for_core(
gxp, CORE_WAKEUP_DOORBELL(GXP_MCU_CORE_ID),
GXP_MCU_CORE_ID);