1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright(c) 2019-2022, Intel Corporation. All rights reserved.
5 * Intel Management Engine Interface (Intel MEI) Linux driver
8 #include <linux/module.h>
9 #include <linux/mei_aux.h>
10 #include <linux/device.h>
11 #include <linux/irqreturn.h>
12 #include <linux/jiffies.h>
13 #include <linux/ktime.h>
14 #include <linux/delay.h>
15 #include <linux/pm_runtime.h>
16 #include <linux/kthread.h>
20 #include "hw-me-regs.h"
22 #include "mei-trace.h"
24 #define MEI_GSC_RPM_TIMEOUT 500
26 static int mei_gsc_read_hfs(const struct mei_device
*dev
, int where
, u32
*val
)
28 struct mei_me_hw
*hw
= to_me_hw(dev
);
30 *val
= ioread32(hw
->mem_addr
+ where
+ 0xC00);
35 static void mei_gsc_set_ext_op_mem(const struct mei_me_hw
*hw
, struct resource
*mem
)
37 u32 low
= lower_32_bits(mem
->start
);
38 u32 hi
= upper_32_bits(mem
->start
);
39 u32 limit
= (resource_size(mem
) / SZ_4K
) | GSC_EXT_OP_MEM_VALID
;
41 iowrite32(low
, hw
->mem_addr
+ H_GSC_EXT_OP_MEM_BASE_ADDR_LO_REG
);
42 iowrite32(hi
, hw
->mem_addr
+ H_GSC_EXT_OP_MEM_BASE_ADDR_HI_REG
);
43 iowrite32(limit
, hw
->mem_addr
+ H_GSC_EXT_OP_MEM_LIMIT_REG
);
46 static int mei_gsc_probe(struct auxiliary_device
*aux_dev
,
47 const struct auxiliary_device_id
*aux_dev_id
)
49 struct mei_aux_device
*adev
= auxiliary_dev_to_mei_aux_dev(aux_dev
);
50 struct mei_device
*dev
;
52 struct device
*device
;
53 const struct mei_cfg
*cfg
;
56 cfg
= mei_me_get_cfg(aux_dev_id
->driver_data
);
60 device
= &aux_dev
->dev
;
62 dev
= mei_me_dev_init(device
, cfg
, adev
->slow_firmware
);
69 hw
->mem_addr
= devm_ioremap_resource(device
, &adev
->bar
);
70 if (IS_ERR(hw
->mem_addr
)) {
71 ret
= PTR_ERR(hw
->mem_addr
);
76 hw
->read_fws
= mei_gsc_read_hfs
;
78 dev_set_drvdata(device
, dev
);
80 if (adev
->ext_op_mem
.start
) {
81 mei_gsc_set_ext_op_mem(hw
, &adev
->ext_op_mem
);
82 dev
->pxp_mode
= MEI_DEV_PXP_INIT
;
86 if (mei_me_hw_use_polling(hw
)) {
87 mei_disable_interrupts(dev
);
88 mei_clear_interrupts(dev
);
89 init_waitqueue_head(&hw
->wait_active
);
90 hw
->is_active
= true; /* start in active mode for initialization */
91 hw
->polling_thread
= kthread_run(mei_me_polling_thread
, dev
,
92 "kmegscirqd/%s", dev_name(device
));
93 if (IS_ERR(hw
->polling_thread
)) {
94 ret
= PTR_ERR(hw
->polling_thread
);
95 dev_err(device
, "unable to create kernel thread: %d\n", ret
);
99 ret
= devm_request_threaded_irq(device
, hw
->irq
,
100 mei_me_irq_quick_handler
,
101 mei_me_irq_thread_handler
,
102 IRQF_ONESHOT
, KBUILD_MODNAME
, dev
);
104 dev_err(device
, "irq register failed %d\n", ret
);
109 pm_runtime_get_noresume(device
);
110 pm_runtime_set_active(device
);
111 pm_runtime_enable(device
);
113 /* Continue to char device setup in spite of firmware handshake failure.
114 * In order to provide access to the firmware status registers to the user
118 dev_warn(device
, "init hw failure.\n");
120 pm_runtime_set_autosuspend_delay(device
, MEI_GSC_RPM_TIMEOUT
);
121 pm_runtime_use_autosuspend(device
);
123 ret
= mei_register(dev
, device
);
127 pm_runtime_put_noidle(device
);
132 if (!mei_me_hw_use_polling(hw
))
133 devm_free_irq(device
, hw
->irq
, dev
);
136 dev_err(device
, "probe failed: %d\n", ret
);
137 dev_set_drvdata(device
, NULL
);
141 static void mei_gsc_remove(struct auxiliary_device
*aux_dev
)
143 struct mei_device
*dev
;
144 struct mei_me_hw
*hw
;
146 dev
= dev_get_drvdata(&aux_dev
->dev
);
152 if (mei_me_hw_use_polling(hw
))
153 kthread_stop(hw
->polling_thread
);
157 pm_runtime_disable(&aux_dev
->dev
);
159 mei_disable_interrupts(dev
);
160 if (!mei_me_hw_use_polling(hw
))
161 devm_free_irq(&aux_dev
->dev
, hw
->irq
, dev
);
164 static int __maybe_unused
mei_gsc_pm_suspend(struct device
*device
)
166 struct mei_device
*dev
= dev_get_drvdata(device
);
170 mei_disable_interrupts(dev
);
175 static int __maybe_unused
mei_gsc_pm_resume(struct device
*device
)
177 struct mei_device
*dev
= dev_get_drvdata(device
);
178 struct auxiliary_device
*aux_dev
;
179 struct mei_aux_device
*adev
;
181 struct mei_me_hw
*hw
;
184 aux_dev
= to_auxiliary_dev(device
);
185 adev
= auxiliary_dev_to_mei_aux_dev(aux_dev
);
186 if (adev
->ext_op_mem
.start
) {
187 mei_gsc_set_ext_op_mem(hw
, &adev
->ext_op_mem
);
188 dev
->pxp_mode
= MEI_DEV_PXP_INIT
;
191 err
= mei_restart(dev
);
195 /* Start timer if stopped in suspend */
196 schedule_delayed_work(&dev
->timer_work
, HZ
);
201 static int __maybe_unused
mei_gsc_pm_runtime_idle(struct device
*device
)
203 struct mei_device
*dev
= dev_get_drvdata(device
);
205 if (mei_write_is_idle(dev
))
206 pm_runtime_autosuspend(device
);
211 static int __maybe_unused
mei_gsc_pm_runtime_suspend(struct device
*device
)
213 struct mei_device
*dev
= dev_get_drvdata(device
);
214 struct mei_me_hw
*hw
;
217 mutex_lock(&dev
->device_lock
);
219 if (mei_write_is_idle(dev
)) {
221 hw
->pg_state
= MEI_PG_ON
;
223 if (mei_me_hw_use_polling(hw
))
224 hw
->is_active
= false;
230 mutex_unlock(&dev
->device_lock
);
235 static int __maybe_unused
mei_gsc_pm_runtime_resume(struct device
*device
)
237 struct mei_device
*dev
= dev_get_drvdata(device
);
238 struct mei_me_hw
*hw
;
241 mutex_lock(&dev
->device_lock
);
244 hw
->pg_state
= MEI_PG_OFF
;
246 if (mei_me_hw_use_polling(hw
)) {
247 hw
->is_active
= true;
248 wake_up(&hw
->wait_active
);
251 mutex_unlock(&dev
->device_lock
);
253 irq_ret
= mei_me_irq_thread_handler(1, dev
);
254 if (irq_ret
!= IRQ_HANDLED
)
255 dev_err(dev
->dev
, "thread handler fail %d\n", irq_ret
);
260 static const struct dev_pm_ops mei_gsc_pm_ops
= {
261 SET_SYSTEM_SLEEP_PM_OPS(mei_gsc_pm_suspend
,
263 SET_RUNTIME_PM_OPS(mei_gsc_pm_runtime_suspend
,
264 mei_gsc_pm_runtime_resume
,
265 mei_gsc_pm_runtime_idle
)
268 static const struct auxiliary_device_id mei_gsc_id_table
[] = {
270 .name
= "i915.mei-gsc",
271 .driver_data
= MEI_ME_GSC_CFG
,
275 .name
= "i915.mei-gscfi",
276 .driver_data
= MEI_ME_GSCFI_CFG
,
279 .name
= "xe.mei-gscfi",
280 .driver_data
= MEI_ME_GSCFI_CFG
,
286 MODULE_DEVICE_TABLE(auxiliary
, mei_gsc_id_table
);
288 static struct auxiliary_driver mei_gsc_driver
= {
289 .probe
= mei_gsc_probe
,
290 .remove
= mei_gsc_remove
,
292 /* auxiliary_driver_register() sets .name to be the modname */
293 .pm
= &mei_gsc_pm_ops
,
295 .id_table
= mei_gsc_id_table
297 module_auxiliary_driver(mei_gsc_driver
);
299 MODULE_AUTHOR("Intel Corporation");
300 MODULE_ALIAS("auxiliary:i915.mei-gsc");
301 MODULE_ALIAS("auxiliary:i915.mei-gscfi");
302 MODULE_ALIAS("auxiliary:xe.mei-gscfi");
303 MODULE_DESCRIPTION("Intel(R) Graphics System Controller");
304 MODULE_LICENSE("GPL");