mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-10-26 10:57:38 +08:00
Add xe_sysctrl_is_oobmsm_fw_ready(), a convenience wrapper around xe_sysctrl_check_app_status() to check oCode application readiness. Signed-off-by: Anoop Vijay <anoop.c.vijay@intel.com> Reviewed-by: Michael J. Ruhl <michael.j.ruhl@intel.com> Reviewed-by: Umesh Nerlige Ramappa <umesh.nerlige.ramappa@intel.com> Signed-off-by: Umesh Nerlige Ramappa <umesh.nerlige.ramappa@intel.com> Link: https://patch.msgid.link/20260904134935.674507-6-anoop.c.vijay@intel.com
220 lines
5.8 KiB
C
220 lines
5.8 KiB
C
// SPDX-License-Identifier: MIT
|
|
/*
|
|
* Copyright © 2026 Intel Corporation
|
|
*/
|
|
|
|
#include <linux/device.h>
|
|
#include <linux/mutex.h>
|
|
|
|
#include <drm/drm_managed.h>
|
|
|
|
#include "regs/xe_irq_regs.h"
|
|
#include "regs/xe_sysctrl_regs.h"
|
|
#include "xe_device.h"
|
|
#include "xe_mmio.h"
|
|
#include "xe_pm.h"
|
|
#include "xe_printk.h"
|
|
#include "xe_soc_remapper.h"
|
|
#include "xe_sysctrl.h"
|
|
#include "xe_sysctrl_mailbox.h"
|
|
#include "xe_sysctrl_mailbox_types.h"
|
|
#include "xe_sysctrl_types.h"
|
|
|
|
/**
|
|
* DOC: System Controller (sysctrl)
|
|
*
|
|
* System Controller (sysctrl) is a firmware-managed entity on Intel dGPUs
|
|
* responsible for selected low-level platform management functions.
|
|
* Communication between driver and System Controller is performed
|
|
* via a mailbox interface, enabling command and response exchange.
|
|
*
|
|
* This module provides initialization and support code for interacting
|
|
* with System Controller through the mailbox interface.
|
|
*/
|
|
|
|
/* Application status flags reported in xe_sysctrl_app_status_resp.flags */
|
|
#define XE_SYSCTRL_APP_RESP_VALID BIT(0)
|
|
#define XE_SYSCTRL_APP_RESP_BOOTED BIT(1)
|
|
#define XE_SYSCTRL_APP_RESP_INITIALIZED BIT(2)
|
|
|
|
/*
|
|
* Known System Controller application identifiers, keyed by firmware
|
|
* application ID.
|
|
*/
|
|
enum xe_sysctrl_app_id {
|
|
XE_SYSCTRL_APP_OCODE = 0x0C,
|
|
XE_SYSCTRL_APP_DIAG = 0x0D,
|
|
};
|
|
|
|
static void sysctrl_fini(void *arg)
|
|
{
|
|
struct xe_device *xe = arg;
|
|
struct xe_sysctrl *sc = &xe->sc;
|
|
|
|
disable_work_sync(&sc->work);
|
|
xe->soc_remapper.set_sysctrl_region(xe, 0);
|
|
}
|
|
|
|
static void xe_sysctrl_work(struct work_struct *work)
|
|
{
|
|
struct xe_sysctrl *sc = container_of(work, struct xe_sysctrl, work);
|
|
struct xe_device *xe = sc_to_xe(sc);
|
|
|
|
guard(xe_pm_runtime)(xe);
|
|
xe_sysctrl_event(sc);
|
|
}
|
|
|
|
/**
|
|
* xe_sysctrl_init() - Initialize System Controller subsystem
|
|
* @xe: xe device instance
|
|
*
|
|
* Entry point for System Controller initialization, called from xe_device_probe.
|
|
* This function checks platform support and initializes the system controller.
|
|
*
|
|
* Return: 0 on success, error code on failure
|
|
*/
|
|
int xe_sysctrl_init(struct xe_device *xe)
|
|
{
|
|
struct xe_tile *tile = xe_device_get_root_tile(xe);
|
|
struct xe_sysctrl *sc = &xe->sc;
|
|
int ret;
|
|
|
|
if (!xe->info.has_soc_remapper_sysctrl)
|
|
return 0;
|
|
|
|
if (!xe->info.has_sysctrl)
|
|
return 0;
|
|
|
|
sc->mmio = devm_kzalloc(xe->drm.dev, sizeof(*sc->mmio), GFP_KERNEL);
|
|
if (!sc->mmio)
|
|
return -ENOMEM;
|
|
|
|
xe_mmio_init(sc->mmio, tile, tile->mmio.regs, tile->mmio.regs_size);
|
|
sc->mmio->adj_offset = SYSCTRL_BASE;
|
|
sc->mmio->adj_limit = U32_MAX;
|
|
|
|
ret = devm_mutex_init(xe->drm.dev, &sc->cmd_lock);
|
|
if (ret)
|
|
return ret;
|
|
|
|
ret = devm_mutex_init(xe->drm.dev, &sc->event_lock);
|
|
if (ret)
|
|
return ret;
|
|
|
|
xe->soc_remapper.set_sysctrl_region(xe, SYSCTRL_MAILBOX_INDEX);
|
|
INIT_WORK(&sc->work, xe_sysctrl_work);
|
|
|
|
return devm_add_action_or_reset(xe->drm.dev, sysctrl_fini, xe);
|
|
}
|
|
|
|
/**
|
|
* xe_sysctrl_irq_handler() - Handler for System Controller interrupts
|
|
* @xe: xe device instance
|
|
* @master_ctl: interrupt register
|
|
*
|
|
* Handle interrupts generated by System Controller.
|
|
*/
|
|
void xe_sysctrl_irq_handler(struct xe_device *xe, u32 master_ctl)
|
|
{
|
|
struct xe_sysctrl *sc = &xe->sc;
|
|
|
|
if (!xe->info.has_sysctrl || !sc->work.func)
|
|
return;
|
|
|
|
if (master_ctl & SYSCTRL_IRQ)
|
|
schedule_work(&sc->work);
|
|
}
|
|
|
|
/**
|
|
* xe_sysctrl_pm_resume() - System Controller resume handler
|
|
* @xe: xe device instance
|
|
*
|
|
* Invoked during system resume (S3/S4 to S0) and runtime resume from D3cold.
|
|
* Restores SoC remapper configuration.
|
|
*/
|
|
void xe_sysctrl_pm_resume(struct xe_device *xe)
|
|
{
|
|
if (!xe->info.has_soc_remapper_sysctrl)
|
|
return;
|
|
|
|
if (!xe->info.has_sysctrl)
|
|
return;
|
|
|
|
xe->soc_remapper.set_sysctrl_region(xe, SYSCTRL_MAILBOX_INDEX);
|
|
}
|
|
|
|
static enum xe_sysctrl_fw_status
|
|
xe_sysctrl_check_app_status(struct xe_device *xe, enum xe_sysctrl_app_id app_id)
|
|
{
|
|
struct xe_sysctrl_app_status_req req = {};
|
|
struct xe_sysctrl_app_status_resp resp = {};
|
|
struct xe_sysctrl_mailbox_command cmd = {};
|
|
size_t out_len = 0;
|
|
u32 flags;
|
|
int ret;
|
|
|
|
req.app_id = (u8)app_id;
|
|
|
|
xe_sysctrl_create_command(&cmd, XE_SYSCTRL_GROUP_CORE, XE_SYSCTRL_CMD_GET_APP_STATUS_BY_ID,
|
|
&req, sizeof(req), &resp, sizeof(resp));
|
|
|
|
ret = xe_sysctrl_send_command(&xe->sc, &cmd, &out_len);
|
|
if (ret)
|
|
return XE_SYSCTRL_FIRMWARE_COMM_FAILURE;
|
|
|
|
if (out_len != sizeof(resp)) {
|
|
xe_err(xe, "sysctrl: unexpected get app status response length %zu (expected %zu)\n",
|
|
out_len, sizeof(resp));
|
|
return XE_SYSCTRL_FIRMWARE_COMM_FAILURE;
|
|
}
|
|
|
|
flags = resp.flags;
|
|
|
|
if (!(flags & XE_SYSCTRL_APP_RESP_VALID))
|
|
return XE_SYSCTRL_FIRMWARE_APP_INVALID;
|
|
|
|
if (!(flags & XE_SYSCTRL_APP_RESP_BOOTED))
|
|
return XE_SYSCTRL_FIRMWARE_APP_NOT_LOADED;
|
|
|
|
if (!(flags & XE_SYSCTRL_APP_RESP_INITIALIZED))
|
|
return XE_SYSCTRL_FIRMWARE_APP_BOOTED;
|
|
|
|
return XE_SYSCTRL_FIRMWARE_APP_INITIALIZED;
|
|
}
|
|
|
|
/**
|
|
* xe_sysctrl_is_oobmsm_fw_ready() - Check if oCode firmware is fully initialized
|
|
* @xe: xe device instance
|
|
*
|
|
* Returns true if oCode firmware has reached the initialized state, indicating
|
|
* it is ready to handle requests.
|
|
*
|
|
* Callers must only invoke this on platforms where System Controller is
|
|
* present (xe->info.has_sysctrl).
|
|
*
|
|
* Return: true if oCode firmware is initialized, false otherwise
|
|
*/
|
|
bool xe_sysctrl_is_oobmsm_fw_ready(struct xe_device *xe)
|
|
{
|
|
return xe_sysctrl_check_app_status(xe, XE_SYSCTRL_APP_OCODE) ==
|
|
XE_SYSCTRL_FIRMWARE_APP_INITIALIZED;
|
|
}
|
|
|
|
/**
|
|
* xe_sysctrl_is_diag_fw_ready() - Check if diag firmware is fully initialized
|
|
* @xe: xe device instance
|
|
*
|
|
* Returns true if diag firmware has reached the initialized state, indicating
|
|
* it is ready to handle requests.
|
|
*
|
|
* Callers must only invoke this on platforms where System Controller is
|
|
* present (xe->info.has_sysctrl).
|
|
*
|
|
* Return: true if diag firmware is initialized, false otherwise
|
|
*/
|
|
bool xe_sysctrl_is_diag_fw_ready(struct xe_device *xe)
|
|
{
|
|
return xe_sysctrl_check_app_status(xe, XE_SYSCTRL_APP_DIAG) ==
|
|
XE_SYSCTRL_FIRMWARE_APP_INITIALIZED;
|
|
}
|