// SPDX-License-Identifier: MIT /* * Copyright © 2026 Intel Corporation */ #include #include #include #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_soc_remapper.h" #include "xe_sysctrl.h" #include "xe_sysctrl_mailbox.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. */ 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); xe_sysctrl_mailbox_init(sc); 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 and reinitializes mailbox interface. */ void xe_sysctrl_pm_resume(struct xe_device *xe) { struct xe_sysctrl *sc = &xe->sc; if (!xe->info.has_soc_remapper_sysctrl) return; if (!xe->info.has_sysctrl) return; xe->soc_remapper.set_sysctrl_region(xe, SYSCTRL_MAILBOX_INDEX); xe_sysctrl_mailbox_init(sc); }