Linux Audio

Check our new training course

Loading...
v6.13.7
  1// SPDX-License-Identifier: MIT
  2/*
  3 * Copyright(c) 2023, Intel Corporation. All rights reserved.
  4 */
  5
  6#include <linux/irq.h>
  7#include <linux/mei_aux.h>
  8#include <linux/pci.h>
  9#include <linux/sizes.h>
 10
 11#include "xe_device_types.h"
 12#include "xe_drv.h"
 13#include "xe_heci_gsc.h"
 14#include "xe_platform_types.h"
 15
 16#define GSC_BAR_LENGTH  0x00000FFC
 17
 18#define DG1_GSC_HECI2_BASE			0x259000
 19#define PVC_GSC_HECI2_BASE			0x285000
 20#define DG2_GSC_HECI2_BASE			0x374000
 21
 22static void heci_gsc_irq_mask(struct irq_data *d)
 23{
 24	/* generic irq handling */
 25}
 26
 27static void heci_gsc_irq_unmask(struct irq_data *d)
 28{
 29	/* generic irq handling */
 30}
 31
 32static const struct irq_chip heci_gsc_irq_chip = {
 33	.name = "gsc_irq_chip",
 34	.irq_mask = heci_gsc_irq_mask,
 35	.irq_unmask = heci_gsc_irq_unmask,
 36};
 37
 38static int heci_gsc_irq_init(int irq)
 39{
 40	irq_set_chip_and_handler_name(irq, &heci_gsc_irq_chip,
 41				      handle_simple_irq, "heci_gsc_irq_handler");
 42
 43	return irq_set_chip_data(irq, NULL);
 44}
 45
 46/**
 47 * struct heci_gsc_def - graphics security controller heci interface definitions
 48 *
 49 * @name: name of the heci device
 50 * @bar: address of the mmio bar
 51 * @bar_size: size of the mmio bar
 52 * @use_polling: indication of using polling mode for the device
 53 * @slow_firmware: indication of whether the device is slow (needs longer timeouts)
 54 */
 55struct heci_gsc_def {
 56	const char *name;
 57	unsigned long bar;
 58	size_t bar_size;
 59	bool use_polling;
 60	bool slow_firmware;
 61};
 62
 63/* gsc resources and definitions */
 64static const struct heci_gsc_def heci_gsc_def_dg1 = {
 65	.name = "mei-gscfi",
 66	.bar = DG1_GSC_HECI2_BASE,
 67	.bar_size = GSC_BAR_LENGTH,
 68};
 69
 70static const struct heci_gsc_def heci_gsc_def_dg2 = {
 71	.name = "mei-gscfi",
 72	.bar = DG2_GSC_HECI2_BASE,
 73	.bar_size = GSC_BAR_LENGTH,
 74};
 75
 76static const struct heci_gsc_def heci_gsc_def_pvc = {
 77	.name = "mei-gscfi",
 78	.bar = PVC_GSC_HECI2_BASE,
 79	.bar_size = GSC_BAR_LENGTH,
 80	.slow_firmware = true,
 81};
 82
 83static void heci_gsc_release_dev(struct device *dev)
 84{
 85	struct auxiliary_device *aux_dev = to_auxiliary_dev(dev);
 86	struct mei_aux_device *adev = auxiliary_dev_to_mei_aux_dev(aux_dev);
 87
 88	kfree(adev);
 89}
 90
 91void xe_heci_gsc_fini(struct xe_device *xe)
 92{
 93	struct xe_heci_gsc *heci_gsc = &xe->heci_gsc;
 94
 95	if (!HAS_HECI_GSCFI(xe) && !HAS_HECI_CSCFI(xe))
 96		return;
 97
 98	if (heci_gsc->adev) {
 99		struct auxiliary_device *aux_dev = &heci_gsc->adev->aux_dev;
100
101		auxiliary_device_delete(aux_dev);
102		auxiliary_device_uninit(aux_dev);
103		heci_gsc->adev = NULL;
104	}
105
106	if (heci_gsc->irq >= 0)
107		irq_free_desc(heci_gsc->irq);
108	heci_gsc->irq = -1;
109}
110
111static int heci_gsc_irq_setup(struct xe_device *xe)
112{
113	struct xe_heci_gsc *heci_gsc = &xe->heci_gsc;
114	int ret;
115
116	heci_gsc->irq = irq_alloc_desc(0);
117	if (heci_gsc->irq < 0) {
118		drm_err(&xe->drm, "gsc irq error %d\n", heci_gsc->irq);
119		return heci_gsc->irq;
120	}
121
122	ret = heci_gsc_irq_init(heci_gsc->irq);
123	if (ret < 0)
124		drm_err(&xe->drm, "gsc irq init failed %d\n", ret);
125
126	return ret;
127}
128
129static int heci_gsc_add_device(struct xe_device *xe, const struct heci_gsc_def *def)
130{
131	struct xe_heci_gsc *heci_gsc = &xe->heci_gsc;
132	struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
133	struct auxiliary_device *aux_dev;
134	struct mei_aux_device *adev;
135	int ret;
136
137	adev = kzalloc(sizeof(*adev), GFP_KERNEL);
138	if (!adev)
139		return -ENOMEM;
140	adev->irq = heci_gsc->irq;
141	adev->bar.parent = &pdev->resource[0];
142	adev->bar.start = def->bar + pdev->resource[0].start;
143	adev->bar.end = adev->bar.start + def->bar_size - 1;
144	adev->bar.flags = IORESOURCE_MEM;
145	adev->bar.desc = IORES_DESC_NONE;
146	adev->slow_firmware = def->slow_firmware;
147
148	aux_dev = &adev->aux_dev;
149	aux_dev->name = def->name;
150	aux_dev->id = (pci_domain_nr(pdev->bus) << 16) |
151		      PCI_DEVID(pdev->bus->number, pdev->devfn);
152	aux_dev->dev.parent = &pdev->dev;
153	aux_dev->dev.release = heci_gsc_release_dev;
154
155	ret = auxiliary_device_init(aux_dev);
156	if (ret < 0) {
157		drm_err(&xe->drm, "gsc aux init failed %d\n", ret);
158		kfree(adev);
159		return ret;
160	}
161
162	heci_gsc->adev = adev; /* needed by the notifier */
163	ret = auxiliary_device_add(aux_dev);
164	if (ret < 0) {
165		drm_err(&xe->drm, "gsc aux add failed %d\n", ret);
166		heci_gsc->adev = NULL;
167
168		/* adev will be freed with the put_device() and .release sequence */
169		auxiliary_device_uninit(aux_dev);
170	}
171	return ret;
172}
173
174void xe_heci_gsc_init(struct xe_device *xe)
175{
176	struct xe_heci_gsc *heci_gsc = &xe->heci_gsc;
177	const struct heci_gsc_def *def;
178	int ret;
179
180	if (!HAS_HECI_GSCFI(xe) && !HAS_HECI_CSCFI(xe))
181		return;
182
183	heci_gsc->irq = -1;
184
185	if (xe->info.platform == XE_BATTLEMAGE) {
186		def = &heci_gsc_def_dg2;
187	} else if (xe->info.platform == XE_PVC) {
188		def = &heci_gsc_def_pvc;
189	} else if (xe->info.platform == XE_DG2) {
190		def = &heci_gsc_def_dg2;
191	} else if (xe->info.platform == XE_DG1) {
192		def = &heci_gsc_def_dg1;
193	} else {
194		drm_warn_once(&xe->drm, "Unknown platform\n");
195		return;
196	}
197
198	if (!def->name) {
199		drm_warn_once(&xe->drm, "HECI is not implemented!\n");
200		return;
201	}
202
203	if (!def->use_polling) {
204		ret = heci_gsc_irq_setup(xe);
205		if (ret)
206			goto fail;
207	}
208
209	ret = heci_gsc_add_device(xe, def);
210	if (ret)
211		goto fail;
212
213	return;
214fail:
215	xe_heci_gsc_fini(xe);
216}
217
218void xe_heci_gsc_irq_handler(struct xe_device *xe, u32 iir)
219{
220	int ret;
221
222	if ((iir & GSC_IRQ_INTF(1)) == 0)
223		return;
224
225	if (!HAS_HECI_GSCFI(xe)) {
226		drm_warn_once(&xe->drm, "GSC irq: not supported");
227		return;
228	}
229
230	if (xe->heci_gsc.irq < 0)
231		return;
232
233	ret = generic_handle_irq(xe->heci_gsc.irq);
234	if (ret)
235		drm_err_ratelimited(&xe->drm, "error handling GSC irq: %d\n", ret);
236}
237
238void xe_heci_csc_irq_handler(struct xe_device *xe, u32 iir)
239{
240	int ret;
241
242	if ((iir & CSC_IRQ_INTF(1)) == 0)
243		return;
244
245	if (!HAS_HECI_CSCFI(xe)) {
246		drm_warn_once(&xe->drm, "CSC irq: not supported");
247		return;
248	}
249
250	if (xe->heci_gsc.irq < 0)
251		return;
252
253	ret = generic_handle_irq(xe->heci_gsc.irq);
254	if (ret)
255		drm_err_ratelimited(&xe->drm, "error handling GSC irq: %d\n", ret);
256}
v6.9.4
  1// SPDX-License-Identifier: MIT
  2/*
  3 * Copyright(c) 2023, Intel Corporation. All rights reserved.
  4 */
  5
  6#include <linux/irq.h>
  7#include <linux/mei_aux.h>
  8#include <linux/pci.h>
  9#include <linux/sizes.h>
 10
 11#include "xe_device_types.h"
 12#include "xe_drv.h"
 13#include "xe_heci_gsc.h"
 14#include "xe_platform_types.h"
 15
 16#define GSC_BAR_LENGTH  0x00000FFC
 17
 18#define DG1_GSC_HECI2_BASE			0x259000
 19#define PVC_GSC_HECI2_BASE			0x285000
 20#define DG2_GSC_HECI2_BASE			0x374000
 21
 22static void heci_gsc_irq_mask(struct irq_data *d)
 23{
 24	/* generic irq handling */
 25}
 26
 27static void heci_gsc_irq_unmask(struct irq_data *d)
 28{
 29	/* generic irq handling */
 30}
 31
 32static const struct irq_chip heci_gsc_irq_chip = {
 33	.name = "gsc_irq_chip",
 34	.irq_mask = heci_gsc_irq_mask,
 35	.irq_unmask = heci_gsc_irq_unmask,
 36};
 37
 38static int heci_gsc_irq_init(int irq)
 39{
 40	irq_set_chip_and_handler_name(irq, &heci_gsc_irq_chip,
 41				      handle_simple_irq, "heci_gsc_irq_handler");
 42
 43	return irq_set_chip_data(irq, NULL);
 44}
 45
 46/**
 47 * struct heci_gsc_def - graphics security controller heci interface definitions
 48 *
 49 * @name: name of the heci device
 50 * @bar: address of the mmio bar
 51 * @bar_size: size of the mmio bar
 52 * @use_polling: indication of using polling mode for the device
 53 * @slow_firmware: indication of whether the device is slow (needs longer timeouts)
 54 */
 55struct heci_gsc_def {
 56	const char *name;
 57	unsigned long bar;
 58	size_t bar_size;
 59	bool use_polling;
 60	bool slow_firmware;
 61};
 62
 63/* gsc resources and definitions */
 64static const struct heci_gsc_def heci_gsc_def_dg1 = {
 65	.name = "mei-gscfi",
 66	.bar = DG1_GSC_HECI2_BASE,
 67	.bar_size = GSC_BAR_LENGTH,
 68};
 69
 70static const struct heci_gsc_def heci_gsc_def_dg2 = {
 71	.name = "mei-gscfi",
 72	.bar = DG2_GSC_HECI2_BASE,
 73	.bar_size = GSC_BAR_LENGTH,
 74};
 75
 76static const struct heci_gsc_def heci_gsc_def_pvc = {
 77	.name = "mei-gscfi",
 78	.bar = PVC_GSC_HECI2_BASE,
 79	.bar_size = GSC_BAR_LENGTH,
 80	.slow_firmware = true,
 81};
 82
 83static void heci_gsc_release_dev(struct device *dev)
 84{
 85	struct auxiliary_device *aux_dev = to_auxiliary_dev(dev);
 86	struct mei_aux_device *adev = auxiliary_dev_to_mei_aux_dev(aux_dev);
 87
 88	kfree(adev);
 89}
 90
 91void xe_heci_gsc_fini(struct xe_device *xe)
 92{
 93	struct xe_heci_gsc *heci_gsc = &xe->heci_gsc;
 94
 95	if (!HAS_HECI_GSCFI(xe))
 96		return;
 97
 98	if (heci_gsc->adev) {
 99		struct auxiliary_device *aux_dev = &heci_gsc->adev->aux_dev;
100
101		auxiliary_device_delete(aux_dev);
102		auxiliary_device_uninit(aux_dev);
103		heci_gsc->adev = NULL;
104	}
105
106	if (heci_gsc->irq >= 0)
107		irq_free_desc(heci_gsc->irq);
108	heci_gsc->irq = -1;
109}
110
111static int heci_gsc_irq_setup(struct xe_device *xe)
112{
113	struct xe_heci_gsc *heci_gsc = &xe->heci_gsc;
114	int ret;
115
116	heci_gsc->irq = irq_alloc_desc(0);
117	if (heci_gsc->irq < 0) {
118		drm_err(&xe->drm, "gsc irq error %d\n", heci_gsc->irq);
119		return heci_gsc->irq;
120	}
121
122	ret = heci_gsc_irq_init(heci_gsc->irq);
123	if (ret < 0)
124		drm_err(&xe->drm, "gsc irq init failed %d\n", ret);
125
126	return ret;
127}
128
129static int heci_gsc_add_device(struct xe_device *xe, const struct heci_gsc_def *def)
130{
131	struct xe_heci_gsc *heci_gsc = &xe->heci_gsc;
132	struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
133	struct auxiliary_device *aux_dev;
134	struct mei_aux_device *adev;
135	int ret;
136
137	adev = kzalloc(sizeof(*adev), GFP_KERNEL);
138	if (!adev)
139		return -ENOMEM;
140	adev->irq = heci_gsc->irq;
141	adev->bar.parent = &pdev->resource[0];
142	adev->bar.start = def->bar + pdev->resource[0].start;
143	adev->bar.end = adev->bar.start + def->bar_size - 1;
144	adev->bar.flags = IORESOURCE_MEM;
145	adev->bar.desc = IORES_DESC_NONE;
146	adev->slow_firmware = def->slow_firmware;
147
148	aux_dev = &adev->aux_dev;
149	aux_dev->name = def->name;
150	aux_dev->id = (pci_domain_nr(pdev->bus) << 16) |
151		      PCI_DEVID(pdev->bus->number, pdev->devfn);
152	aux_dev->dev.parent = &pdev->dev;
153	aux_dev->dev.release = heci_gsc_release_dev;
154
155	ret = auxiliary_device_init(aux_dev);
156	if (ret < 0) {
157		drm_err(&xe->drm, "gsc aux init failed %d\n", ret);
158		kfree(adev);
159		return ret;
160	}
161
162	heci_gsc->adev = adev; /* needed by the notifier */
163	ret = auxiliary_device_add(aux_dev);
164	if (ret < 0) {
165		drm_err(&xe->drm, "gsc aux add failed %d\n", ret);
166		heci_gsc->adev = NULL;
167
168		/* adev will be freed with the put_device() and .release sequence */
169		auxiliary_device_uninit(aux_dev);
170	}
171	return ret;
172}
173
174void xe_heci_gsc_init(struct xe_device *xe)
175{
176	struct xe_heci_gsc *heci_gsc = &xe->heci_gsc;
177	const struct heci_gsc_def *def;
178	int ret;
179
180	if (!HAS_HECI_GSCFI(xe))
181		return;
182
183	heci_gsc->irq = -1;
184
185	if (xe->info.platform == XE_PVC) {
 
 
186		def = &heci_gsc_def_pvc;
187	} else if (xe->info.platform == XE_DG2) {
188		def = &heci_gsc_def_dg2;
189	} else if (xe->info.platform == XE_DG1) {
190		def = &heci_gsc_def_dg1;
191	} else {
192		drm_warn_once(&xe->drm, "Unknown platform\n");
193		return;
194	}
195
196	if (!def->name) {
197		drm_warn_once(&xe->drm, "HECI is not implemented!\n");
198		return;
199	}
200
201	if (!def->use_polling) {
202		ret = heci_gsc_irq_setup(xe);
203		if (ret)
204			goto fail;
205	}
206
207	ret = heci_gsc_add_device(xe, def);
208	if (ret)
209		goto fail;
210
211	return;
212fail:
213	xe_heci_gsc_fini(xe);
214}
215
216void xe_heci_gsc_irq_handler(struct xe_device *xe, u32 iir)
217{
218	int ret;
219
220	if ((iir & GSC_IRQ_INTF(1)) == 0)
221		return;
222
223	if (!HAS_HECI_GSCFI(xe)) {
224		drm_warn_once(&xe->drm, "GSC irq: not supported");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
225		return;
226	}
227
228	if (xe->heci_gsc.irq < 0)
229		return;
230
231	ret = generic_handle_irq(xe->heci_gsc.irq);
232	if (ret)
233		drm_err_ratelimited(&xe->drm, "error handling GSC irq: %d\n", ret);
234}