summaryrefslogtreecommitdiff
path: root/drivers/soc/xilinx/xlnx_event_manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/soc/xilinx/xlnx_event_manager.c')
-rw-r--r--drivers/soc/xilinx/xlnx_event_manager.c58
1 files changed, 36 insertions, 22 deletions
diff --git a/drivers/soc/xilinx/xlnx_event_manager.c b/drivers/soc/xilinx/xlnx_event_manager.c
index f9d9b82b562d..6fdf4d14b7e7 100644
--- a/drivers/soc/xilinx/xlnx_event_manager.c
+++ b/drivers/soc/xilinx/xlnx_event_manager.c
@@ -3,6 +3,7 @@
* Xilinx Event Management Driver
*
* Copyright (C) 2021 Xilinx, Inc.
+ * Copyright (C) 2024 Advanced Micro Devices, Inc.
*
* Abhyuday Godhasara <abhyuday.godhasara@xilinx.com>
*/
@@ -19,7 +20,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
-static DEFINE_PER_CPU_READ_MOSTLY(int, cpu_number1);
+static DEFINE_PER_CPU_READ_MOSTLY(int, dummy_cpu_number);
static int virq_sgi;
static int event_manager_availability = -EACCES;
@@ -35,7 +36,6 @@ static int event_manager_availability = -EACCES;
#define MAX_BITS (32U) /* Number of bits available for error mask */
-#define FIRMWARE_VERSION_MASK (0xFFFFU)
#define REGISTER_NOTIFIER_FIRMWARE_VERSION (2U)
static DEFINE_HASHTABLE(reg_driver_map, REGISTERED_DRIVER_MAX_ORDER);
@@ -77,11 +77,26 @@ struct registered_event_data {
static bool xlnx_is_error_event(const u32 node_id)
{
- if (node_id == EVENT_ERROR_PMC_ERR1 ||
- node_id == EVENT_ERROR_PMC_ERR2 ||
- node_id == EVENT_ERROR_PSM_ERR1 ||
- node_id == EVENT_ERROR_PSM_ERR2)
- return true;
+ u32 pm_family_code;
+
+ zynqmp_pm_get_family_info(&pm_family_code);
+
+ if (pm_family_code == PM_VERSAL_FAMILY_CODE) {
+ if (node_id == VERSAL_EVENT_ERROR_PMC_ERR1 ||
+ node_id == VERSAL_EVENT_ERROR_PMC_ERR2 ||
+ node_id == VERSAL_EVENT_ERROR_PSM_ERR1 ||
+ node_id == VERSAL_EVENT_ERROR_PSM_ERR2)
+ return true;
+ } else if (pm_family_code == PM_VERSAL_NET_FAMILY_CODE) {
+ if (node_id == VERSAL_NET_EVENT_ERROR_PMC_ERR1 ||
+ node_id == VERSAL_NET_EVENT_ERROR_PMC_ERR2 ||
+ node_id == VERSAL_NET_EVENT_ERROR_PMC_ERR3 ||
+ node_id == VERSAL_NET_EVENT_ERROR_PSM_ERR1 ||
+ node_id == VERSAL_NET_EVENT_ERROR_PSM_ERR2 ||
+ node_id == VERSAL_NET_EVENT_ERROR_PSM_ERR3 ||
+ node_id == VERSAL_NET_EVENT_ERROR_PSM_ERR4)
+ return true;
+ }
return false;
}
@@ -173,8 +188,10 @@ static int xlnx_add_cb_for_suspend(event_cb_func_t cb_fun, void *data)
INIT_LIST_HEAD(&eve_data->cb_list_head);
cb_data = kmalloc(sizeof(*cb_data), GFP_KERNEL);
- if (!cb_data)
+ if (!cb_data) {
+ kfree(eve_data);
return -ENOMEM;
+ }
cb_data->eve_cb = cb_fun;
cb_data->agent_data = data;
@@ -477,13 +494,13 @@ static void xlnx_call_notify_cb_handler(const u32 *payload)
}
}
if (!is_callback_found)
- pr_warn("Didn't find any registered callback for 0x%x 0x%x\n",
+ pr_warn("Unhandled SGI node 0x%x event 0x%x. Expected with Xen hypervisor\n",
payload[1], payload[2]);
}
static void xlnx_get_event_callback_data(u32 *buf)
{
- zynqmp_pm_invoke_fn(GET_CALLBACK_DATA, 0, 0, 0, 0, buf);
+ zynqmp_pm_invoke_fn(GET_CALLBACK_DATA, buf, 0);
}
static irqreturn_t xlnx_event_handler(int irq, void *dev_id)
@@ -555,7 +572,6 @@ static void xlnx_disable_percpu_irq(void *data)
static int xlnx_event_init_sgi(struct platform_device *pdev)
{
int ret = 0;
- int cpu = smp_processor_id();
/*
* IRQ related structures are used for the following:
* for each SGI interrupt ensure its mapped by GIC IRQ domain
@@ -592,9 +608,9 @@ static int xlnx_event_init_sgi(struct platform_device *pdev)
sgi_fwspec.param[0] = sgi_num;
virq_sgi = irq_create_fwspec_mapping(&sgi_fwspec);
- per_cpu(cpu_number1, cpu) = cpu;
ret = request_percpu_irq(virq_sgi, xlnx_event_handler, "xlnx_event_mgmt",
- &cpu_number1);
+ &dummy_cpu_number);
+
WARN_ON(ret);
if (ret) {
irq_dispose_mapping(virq_sgi);
@@ -609,16 +625,12 @@ static int xlnx_event_init_sgi(struct platform_device *pdev)
static void xlnx_event_cleanup_sgi(struct platform_device *pdev)
{
- int cpu = smp_processor_id();
-
- per_cpu(cpu_number1, cpu) = cpu;
-
cpuhp_remove_state(CPUHP_AP_ONLINE_DYN);
on_each_cpu(xlnx_disable_percpu_irq, NULL, 1);
irq_clear_status_flags(virq_sgi, IRQ_PER_CPU);
- free_percpu_irq(virq_sgi, &cpu_number1);
+ free_percpu_irq(virq_sgi, &dummy_cpu_number);
irq_dispose_mapping(virq_sgi);
}
@@ -653,7 +665,11 @@ static int xlnx_event_manager_probe(struct platform_device *pdev)
ret = zynqmp_pm_register_sgi(sgi_num, 0);
if (ret) {
- dev_err(&pdev->dev, "SGI %d Registration over TF-A failed with %d\n", sgi_num, ret);
+ if (ret == -EOPNOTSUPP)
+ dev_err(&pdev->dev, "SGI registration not supported by TF-A or Xen\n");
+ else
+ dev_err(&pdev->dev, "SGI %d registration failed, err %d\n", sgi_num, ret);
+
xlnx_event_cleanup_sgi(pdev);
return ret;
}
@@ -666,7 +682,7 @@ static int xlnx_event_manager_probe(struct platform_device *pdev)
return ret;
}
-static int xlnx_event_manager_remove(struct platform_device *pdev)
+static void xlnx_event_manager_remove(struct platform_device *pdev)
{
int i;
struct registered_event_data *eve_data;
@@ -691,8 +707,6 @@ static int xlnx_event_manager_remove(struct platform_device *pdev)
xlnx_event_cleanup_sgi(pdev);
event_manager_availability = -EACCES;
-
- return ret;
}
static struct platform_driver xlnx_event_manager_driver = {