summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/xe/xe_sysctrl.c
blob: 1db20be8158b56c19e2db656e570de7ac041e64b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// 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_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);
}