1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2026 Intel Corporation 4 */ 5 6 #include <linux/device.h> 7 #include <linux/mutex.h> 8 9 #include <drm/drm_managed.h> 10 11 #include "regs/xe_irq_regs.h" 12 #include "regs/xe_sysctrl_regs.h" 13 #include "xe_device.h" 14 #include "xe_mmio.h" 15 #include "xe_pm.h" 16 #include "xe_soc_remapper.h" 17 #include "xe_sysctrl.h" 18 #include "xe_sysctrl_mailbox.h" 19 #include "xe_sysctrl_types.h" 20 21 /** 22 * DOC: System Controller (sysctrl) 23 * 24 * System Controller (sysctrl) is a firmware-managed entity on Intel dGPUs 25 * responsible for selected low-level platform management functions. 26 * Communication between driver and System Controller is performed 27 * via a mailbox interface, enabling command and response exchange. 28 * 29 * This module provides initialization and support code for interacting 30 * with System Controller through the mailbox interface. 31 */ 32 static void sysctrl_fini(void *arg) 33 { 34 struct xe_device *xe = arg; 35 struct xe_sysctrl *sc = &xe->sc; 36 37 disable_work_sync(&sc->work); 38 xe->soc_remapper.set_sysctrl_region(xe, 0); 39 } 40 41 static void xe_sysctrl_work(struct work_struct *work) 42 { 43 struct xe_sysctrl *sc = container_of(work, struct xe_sysctrl, work); 44 struct xe_device *xe = sc_to_xe(sc); 45 46 guard(xe_pm_runtime)(xe); 47 xe_sysctrl_event(sc); 48 } 49 50 /** 51 * xe_sysctrl_init() - Initialize System Controller subsystem 52 * @xe: xe device instance 53 * 54 * Entry point for System Controller initialization, called from xe_device_probe. 55 * This function checks platform support and initializes the system controller. 56 * 57 * Return: 0 on success, error code on failure 58 */ 59 int xe_sysctrl_init(struct xe_device *xe) 60 { 61 struct xe_tile *tile = xe_device_get_root_tile(xe); 62 struct xe_sysctrl *sc = &xe->sc; 63 int ret; 64 65 if (!xe->info.has_soc_remapper_sysctrl) 66 return 0; 67 68 if (!xe->info.has_sysctrl) 69 return 0; 70 71 sc->mmio = devm_kzalloc(xe->drm.dev, sizeof(*sc->mmio), GFP_KERNEL); 72 if (!sc->mmio) 73 return -ENOMEM; 74 75 xe_mmio_init(sc->mmio, tile, tile->mmio.regs, tile->mmio.regs_size); 76 sc->mmio->adj_offset = SYSCTRL_BASE; 77 sc->mmio->adj_limit = U32_MAX; 78 79 ret = devm_mutex_init(xe->drm.dev, &sc->cmd_lock); 80 if (ret) 81 return ret; 82 83 ret = devm_mutex_init(xe->drm.dev, &sc->event_lock); 84 if (ret) 85 return ret; 86 87 xe->soc_remapper.set_sysctrl_region(xe, SYSCTRL_MAILBOX_INDEX); 88 xe_sysctrl_mailbox_init(sc); 89 INIT_WORK(&sc->work, xe_sysctrl_work); 90 91 return devm_add_action_or_reset(xe->drm.dev, sysctrl_fini, xe); 92 } 93 94 /** 95 * xe_sysctrl_irq_handler() - Handler for System Controller interrupts 96 * @xe: xe device instance 97 * @master_ctl: interrupt register 98 * 99 * Handle interrupts generated by System Controller. 100 */ 101 void xe_sysctrl_irq_handler(struct xe_device *xe, u32 master_ctl) 102 { 103 struct xe_sysctrl *sc = &xe->sc; 104 105 if (!xe->info.has_sysctrl || !sc->work.func) 106 return; 107 108 if (master_ctl & SYSCTRL_IRQ) 109 schedule_work(&sc->work); 110 } 111 112 /** 113 * xe_sysctrl_pm_resume() - System Controller resume handler 114 * @xe: xe device instance 115 * 116 * Invoked during system resume (S3/S4 to S0) and runtime resume from D3cold. 117 * Restores SoC remapper configuration and reinitializes mailbox interface. 118 */ 119 void xe_sysctrl_pm_resume(struct xe_device *xe) 120 { 121 struct xe_sysctrl *sc = &xe->sc; 122 123 if (!xe->info.has_soc_remapper_sysctrl) 124 return; 125 126 if (!xe->info.has_sysctrl) 127 return; 128 129 xe->soc_remapper.set_sysctrl_region(xe, SYSCTRL_MAILBOX_INDEX); 130 131 xe_sysctrl_mailbox_init(sc); 132 } 133