xref: /dflybsd-src/sys/dev/drm/i915/intel_csr.c (revision 19c468b4dff0c9c2ceaa37f7e1e4cec69674b238)
1*19c468b4SFrançois Tigeot /*
2*19c468b4SFrançois Tigeot  * Copyright © 2014 Intel Corporation
3*19c468b4SFrançois Tigeot  *
4*19c468b4SFrançois Tigeot  * Permission is hereby granted, free of charge, to any person obtaining a
5*19c468b4SFrançois Tigeot  * copy of this software and associated documentation files (the "Software"),
6*19c468b4SFrançois Tigeot  * to deal in the Software without restriction, including without limitation
7*19c468b4SFrançois Tigeot  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*19c468b4SFrançois Tigeot  * and/or sell copies of the Software, and to permit persons to whom the
9*19c468b4SFrançois Tigeot  * Software is furnished to do so, subject to the following conditions:
10*19c468b4SFrançois Tigeot  *
11*19c468b4SFrançois Tigeot  * The above copyright notice and this permission notice (including the next
12*19c468b4SFrançois Tigeot  * paragraph) shall be included in all copies or substantial portions of the
13*19c468b4SFrançois Tigeot  * Software.
14*19c468b4SFrançois Tigeot  *
15*19c468b4SFrançois Tigeot  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*19c468b4SFrançois Tigeot  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*19c468b4SFrançois Tigeot  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*19c468b4SFrançois Tigeot  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*19c468b4SFrançois Tigeot  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*19c468b4SFrançois Tigeot  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21*19c468b4SFrançois Tigeot  * IN THE SOFTWARE.
22*19c468b4SFrançois Tigeot  *
23*19c468b4SFrançois Tigeot  */
24*19c468b4SFrançois Tigeot #include <linux/firmware.h>
25*19c468b4SFrançois Tigeot #include "i915_drv.h"
26*19c468b4SFrançois Tigeot #include "i915_reg.h"
27*19c468b4SFrançois Tigeot #include "intel_drv.h"
28*19c468b4SFrançois Tigeot 
29*19c468b4SFrançois Tigeot /**
30*19c468b4SFrançois Tigeot  * DOC: csr support for dmc
31*19c468b4SFrançois Tigeot  *
32*19c468b4SFrançois Tigeot  * Display Context Save and Restore (CSR) firmware support added from gen9
33*19c468b4SFrançois Tigeot  * onwards to drive newly added DMC (Display microcontroller) in display
34*19c468b4SFrançois Tigeot  * engine to save and restore the state of display engine when it enter into
35*19c468b4SFrançois Tigeot  * low-power state and comes back to normal.
36*19c468b4SFrançois Tigeot  *
37*19c468b4SFrançois Tigeot  * Firmware loading status will be one of the below states: FW_UNINITIALIZED,
38*19c468b4SFrançois Tigeot  * FW_LOADED, FW_FAILED.
39*19c468b4SFrançois Tigeot  *
40*19c468b4SFrançois Tigeot  * Once the firmware is written into the registers status will be moved from
41*19c468b4SFrançois Tigeot  * FW_UNINITIALIZED to FW_LOADED and for any erroneous condition status will
42*19c468b4SFrançois Tigeot  * be moved to FW_FAILED.
43*19c468b4SFrançois Tigeot  */
44*19c468b4SFrançois Tigeot 
45*19c468b4SFrançois Tigeot #define I915_CSR_SKL "i915/skl_dmc_ver1.bin"
46*19c468b4SFrançois Tigeot 
47*19c468b4SFrançois Tigeot MODULE_FIRMWARE(I915_CSR_SKL);
48*19c468b4SFrançois Tigeot 
49*19c468b4SFrançois Tigeot /*
50*19c468b4SFrançois Tigeot * SKL CSR registers for DC5 and DC6
51*19c468b4SFrançois Tigeot */
52*19c468b4SFrançois Tigeot #define CSR_PROGRAM_BASE		0x80000
53*19c468b4SFrançois Tigeot #define CSR_SSP_BASE_ADDR_GEN9		0x00002FC0
54*19c468b4SFrançois Tigeot #define CSR_HTP_ADDR_SKL		0x00500034
55*19c468b4SFrançois Tigeot #define CSR_SSP_BASE			0x8F074
56*19c468b4SFrançois Tigeot #define CSR_HTP_SKL			0x8F004
57*19c468b4SFrançois Tigeot #define CSR_LAST_WRITE			0x8F034
58*19c468b4SFrançois Tigeot #define CSR_LAST_WRITE_VALUE		0xc003b400
59*19c468b4SFrançois Tigeot /* MMIO address range for CSR program (0x80000 - 0x82FFF) */
60*19c468b4SFrançois Tigeot #define CSR_MAX_FW_SIZE			0x2FFF
61*19c468b4SFrançois Tigeot #define CSR_DEFAULT_FW_OFFSET		0xFFFFFFFF
62*19c468b4SFrançois Tigeot #define CSR_MMIO_START_RANGE	0x80000
63*19c468b4SFrançois Tigeot #define CSR_MMIO_END_RANGE		0x8FFFF
64*19c468b4SFrançois Tigeot 
65*19c468b4SFrançois Tigeot struct intel_css_header {
66*19c468b4SFrançois Tigeot 	/* 0x09 for DMC */
67*19c468b4SFrançois Tigeot 	uint32_t module_type;
68*19c468b4SFrançois Tigeot 
69*19c468b4SFrançois Tigeot 	/* Includes the DMC specific header in dwords */
70*19c468b4SFrançois Tigeot 	uint32_t header_len;
71*19c468b4SFrançois Tigeot 
72*19c468b4SFrançois Tigeot 	/* always value would be 0x10000 */
73*19c468b4SFrançois Tigeot 	uint32_t header_ver;
74*19c468b4SFrançois Tigeot 
75*19c468b4SFrançois Tigeot 	/* Not used */
76*19c468b4SFrançois Tigeot 	uint32_t module_id;
77*19c468b4SFrançois Tigeot 
78*19c468b4SFrançois Tigeot 	/* Not used */
79*19c468b4SFrançois Tigeot 	uint32_t module_vendor;
80*19c468b4SFrançois Tigeot 
81*19c468b4SFrançois Tigeot 	/* in YYYYMMDD format */
82*19c468b4SFrançois Tigeot 	uint32_t date;
83*19c468b4SFrançois Tigeot 
84*19c468b4SFrançois Tigeot 	/* Size in dwords (CSS_Headerlen + PackageHeaderLen + dmc FWsLen)/4 */
85*19c468b4SFrançois Tigeot 	uint32_t size;
86*19c468b4SFrançois Tigeot 
87*19c468b4SFrançois Tigeot 	/* Not used */
88*19c468b4SFrançois Tigeot 	uint32_t key_size;
89*19c468b4SFrançois Tigeot 
90*19c468b4SFrançois Tigeot 	/* Not used */
91*19c468b4SFrançois Tigeot 	uint32_t modulus_size;
92*19c468b4SFrançois Tigeot 
93*19c468b4SFrançois Tigeot 	/* Not used */
94*19c468b4SFrançois Tigeot 	uint32_t exponent_size;
95*19c468b4SFrançois Tigeot 
96*19c468b4SFrançois Tigeot 	/* Not used */
97*19c468b4SFrançois Tigeot 	uint32_t reserved1[12];
98*19c468b4SFrançois Tigeot 
99*19c468b4SFrançois Tigeot 	/* Major Minor */
100*19c468b4SFrançois Tigeot 	uint32_t version;
101*19c468b4SFrançois Tigeot 
102*19c468b4SFrançois Tigeot 	/* Not used */
103*19c468b4SFrançois Tigeot 	uint32_t reserved2[8];
104*19c468b4SFrançois Tigeot 
105*19c468b4SFrançois Tigeot 	/* Not used */
106*19c468b4SFrançois Tigeot 	uint32_t kernel_header_info;
107*19c468b4SFrançois Tigeot } __packed;
108*19c468b4SFrançois Tigeot 
109*19c468b4SFrançois Tigeot struct intel_fw_info {
110*19c468b4SFrançois Tigeot 	uint16_t reserved1;
111*19c468b4SFrançois Tigeot 
112*19c468b4SFrançois Tigeot 	/* Stepping (A, B, C, ..., *). * is a wildcard */
113*19c468b4SFrançois Tigeot 	char stepping;
114*19c468b4SFrançois Tigeot 
115*19c468b4SFrançois Tigeot 	/* Sub-stepping (0, 1, ..., *). * is a wildcard */
116*19c468b4SFrançois Tigeot 	char substepping;
117*19c468b4SFrançois Tigeot 
118*19c468b4SFrançois Tigeot 	uint32_t offset;
119*19c468b4SFrançois Tigeot 	uint32_t reserved2;
120*19c468b4SFrançois Tigeot } __packed;
121*19c468b4SFrançois Tigeot 
122*19c468b4SFrançois Tigeot struct intel_package_header {
123*19c468b4SFrançois Tigeot 	/* DMC container header length in dwords */
124*19c468b4SFrançois Tigeot 	unsigned char header_len;
125*19c468b4SFrançois Tigeot 
126*19c468b4SFrançois Tigeot 	/* always value would be 0x01 */
127*19c468b4SFrançois Tigeot 	unsigned char header_ver;
128*19c468b4SFrançois Tigeot 
129*19c468b4SFrançois Tigeot 	unsigned char reserved[10];
130*19c468b4SFrançois Tigeot 
131*19c468b4SFrançois Tigeot 	/* Number of valid entries in the FWInfo array below */
132*19c468b4SFrançois Tigeot 	uint32_t num_entries;
133*19c468b4SFrançois Tigeot 
134*19c468b4SFrançois Tigeot 	struct intel_fw_info fw_info[20];
135*19c468b4SFrançois Tigeot } __packed;
136*19c468b4SFrançois Tigeot 
137*19c468b4SFrançois Tigeot struct intel_dmc_header {
138*19c468b4SFrançois Tigeot 	/* always value would be 0x40403E3E */
139*19c468b4SFrançois Tigeot 	uint32_t signature;
140*19c468b4SFrançois Tigeot 
141*19c468b4SFrançois Tigeot 	/* DMC binary header length */
142*19c468b4SFrançois Tigeot 	unsigned char header_len;
143*19c468b4SFrançois Tigeot 
144*19c468b4SFrançois Tigeot 	/* 0x01 */
145*19c468b4SFrançois Tigeot 	unsigned char header_ver;
146*19c468b4SFrançois Tigeot 
147*19c468b4SFrançois Tigeot 	/* Reserved */
148*19c468b4SFrançois Tigeot 	uint16_t dmcc_ver;
149*19c468b4SFrançois Tigeot 
150*19c468b4SFrançois Tigeot 	/* Major, Minor */
151*19c468b4SFrançois Tigeot 	uint32_t	project;
152*19c468b4SFrançois Tigeot 
153*19c468b4SFrançois Tigeot 	/* Firmware program size (excluding header) in dwords */
154*19c468b4SFrançois Tigeot 	uint32_t	fw_size;
155*19c468b4SFrançois Tigeot 
156*19c468b4SFrançois Tigeot 	/* Major Minor version */
157*19c468b4SFrançois Tigeot 	uint32_t fw_version;
158*19c468b4SFrançois Tigeot 
159*19c468b4SFrançois Tigeot 	/* Number of valid MMIO cycles present. */
160*19c468b4SFrançois Tigeot 	uint32_t mmio_count;
161*19c468b4SFrançois Tigeot 
162*19c468b4SFrançois Tigeot 	/* MMIO address */
163*19c468b4SFrançois Tigeot 	uint32_t mmioaddr[8];
164*19c468b4SFrançois Tigeot 
165*19c468b4SFrançois Tigeot 	/* MMIO data */
166*19c468b4SFrançois Tigeot 	uint32_t mmiodata[8];
167*19c468b4SFrançois Tigeot 
168*19c468b4SFrançois Tigeot 	/* FW filename  */
169*19c468b4SFrançois Tigeot 	unsigned char dfile[32];
170*19c468b4SFrançois Tigeot 
171*19c468b4SFrançois Tigeot 	uint32_t reserved1[2];
172*19c468b4SFrançois Tigeot } __packed;
173*19c468b4SFrançois Tigeot 
174*19c468b4SFrançois Tigeot struct stepping_info {
175*19c468b4SFrançois Tigeot 	char stepping;
176*19c468b4SFrançois Tigeot 	char substepping;
177*19c468b4SFrançois Tigeot };
178*19c468b4SFrançois Tigeot 
179*19c468b4SFrançois Tigeot static const struct stepping_info skl_stepping_info[] = {
180*19c468b4SFrançois Tigeot 		{'A', '0'}, {'B', '0'}, {'C', '0'},
181*19c468b4SFrançois Tigeot 		{'D', '0'}, {'E', '0'}, {'F', '0'},
182*19c468b4SFrançois Tigeot 		{'G', '0'}, {'H', '0'}, {'I', '0'}
183*19c468b4SFrançois Tigeot };
184*19c468b4SFrançois Tigeot 
185*19c468b4SFrançois Tigeot #if 0
186*19c468b4SFrançois Tigeot static char intel_get_stepping(struct drm_device *dev)
187*19c468b4SFrançois Tigeot {
188*19c468b4SFrançois Tigeot 	if (IS_SKYLAKE(dev) && (dev->pdev->revision <
189*19c468b4SFrançois Tigeot 			ARRAY_SIZE(skl_stepping_info)))
190*19c468b4SFrançois Tigeot 		return skl_stepping_info[dev->pdev->revision].stepping;
191*19c468b4SFrançois Tigeot 	else
192*19c468b4SFrançois Tigeot 		return -ENODATA;
193*19c468b4SFrançois Tigeot }
194*19c468b4SFrançois Tigeot 
195*19c468b4SFrançois Tigeot static char intel_get_substepping(struct drm_device *dev)
196*19c468b4SFrançois Tigeot {
197*19c468b4SFrançois Tigeot 	if (IS_SKYLAKE(dev) && (dev->pdev->revision <
198*19c468b4SFrançois Tigeot 			ARRAY_SIZE(skl_stepping_info)))
199*19c468b4SFrançois Tigeot 		return skl_stepping_info[dev->pdev->revision].substepping;
200*19c468b4SFrançois Tigeot 	else
201*19c468b4SFrançois Tigeot 		return -ENODATA;
202*19c468b4SFrançois Tigeot }
203*19c468b4SFrançois Tigeot #endif
204*19c468b4SFrançois Tigeot 
205*19c468b4SFrançois Tigeot /**
206*19c468b4SFrançois Tigeot  * intel_csr_load_status_get() - to get firmware loading status.
207*19c468b4SFrançois Tigeot  * @dev_priv: i915 device.
208*19c468b4SFrançois Tigeot  *
209*19c468b4SFrançois Tigeot  * This function helps to get the firmware loading status.
210*19c468b4SFrançois Tigeot  *
211*19c468b4SFrançois Tigeot  * Return: Firmware loading status.
212*19c468b4SFrançois Tigeot  */
213*19c468b4SFrançois Tigeot enum csr_state intel_csr_load_status_get(struct drm_i915_private *dev_priv)
214*19c468b4SFrançois Tigeot {
215*19c468b4SFrançois Tigeot 	enum csr_state state;
216*19c468b4SFrançois Tigeot 
217*19c468b4SFrançois Tigeot 	mutex_lock(&dev_priv->csr_lock);
218*19c468b4SFrançois Tigeot 	state = dev_priv->csr.state;
219*19c468b4SFrançois Tigeot 	mutex_unlock(&dev_priv->csr_lock);
220*19c468b4SFrançois Tigeot 
221*19c468b4SFrançois Tigeot 	return state;
222*19c468b4SFrançois Tigeot }
223*19c468b4SFrançois Tigeot 
224*19c468b4SFrançois Tigeot /**
225*19c468b4SFrançois Tigeot  * intel_csr_load_status_set() - help to set firmware loading status.
226*19c468b4SFrançois Tigeot  * @dev_priv: i915 device.
227*19c468b4SFrançois Tigeot  * @state: enumeration of firmware loading status.
228*19c468b4SFrançois Tigeot  *
229*19c468b4SFrançois Tigeot  * Set the firmware loading status.
230*19c468b4SFrançois Tigeot  */
231*19c468b4SFrançois Tigeot void intel_csr_load_status_set(struct drm_i915_private *dev_priv,
232*19c468b4SFrançois Tigeot 			enum csr_state state)
233*19c468b4SFrançois Tigeot {
234*19c468b4SFrançois Tigeot 	mutex_lock(&dev_priv->csr_lock);
235*19c468b4SFrançois Tigeot 	dev_priv->csr.state = state;
236*19c468b4SFrançois Tigeot 	mutex_unlock(&dev_priv->csr_lock);
237*19c468b4SFrançois Tigeot }
238*19c468b4SFrançois Tigeot 
239*19c468b4SFrançois Tigeot /**
240*19c468b4SFrançois Tigeot  * intel_csr_load_program() - write the firmware from memory to register.
241*19c468b4SFrançois Tigeot  * @dev: drm device.
242*19c468b4SFrançois Tigeot  *
243*19c468b4SFrançois Tigeot  * CSR firmware is read from a .bin file and kept in internal memory one time.
244*19c468b4SFrançois Tigeot  * Everytime display comes back from low power state this function is called to
245*19c468b4SFrançois Tigeot  * copy the firmware from internal memory to registers.
246*19c468b4SFrançois Tigeot  */
247*19c468b4SFrançois Tigeot void intel_csr_load_program(struct drm_device *dev)
248*19c468b4SFrançois Tigeot {
249*19c468b4SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
250*19c468b4SFrançois Tigeot 	__be32 *payload = dev_priv->csr.dmc_payload;
251*19c468b4SFrançois Tigeot 	uint32_t i, fw_size;
252*19c468b4SFrançois Tigeot 
253*19c468b4SFrançois Tigeot 	if (!IS_GEN9(dev)) {
254*19c468b4SFrançois Tigeot 		DRM_ERROR("No CSR support available for this platform\n");
255*19c468b4SFrançois Tigeot 		return;
256*19c468b4SFrançois Tigeot 	}
257*19c468b4SFrançois Tigeot 
258*19c468b4SFrançois Tigeot 	mutex_lock(&dev_priv->csr_lock);
259*19c468b4SFrançois Tigeot 	fw_size = dev_priv->csr.dmc_fw_size;
260*19c468b4SFrançois Tigeot 	for (i = 0; i < fw_size; i++)
261*19c468b4SFrançois Tigeot 		I915_WRITE(CSR_PROGRAM_BASE + i * 4,
262*19c468b4SFrançois Tigeot 			(u32 __force)payload[i]);
263*19c468b4SFrançois Tigeot 
264*19c468b4SFrançois Tigeot 	for (i = 0; i < dev_priv->csr.mmio_count; i++) {
265*19c468b4SFrançois Tigeot 		I915_WRITE(dev_priv->csr.mmioaddr[i],
266*19c468b4SFrançois Tigeot 			dev_priv->csr.mmiodata[i]);
267*19c468b4SFrançois Tigeot 	}
268*19c468b4SFrançois Tigeot 
269*19c468b4SFrançois Tigeot 	dev_priv->csr.state = FW_LOADED;
270*19c468b4SFrançois Tigeot 	mutex_unlock(&dev_priv->csr_lock);
271*19c468b4SFrançois Tigeot }
272*19c468b4SFrançois Tigeot 
273*19c468b4SFrançois Tigeot #if 0
274*19c468b4SFrançois Tigeot static void finish_csr_load(const struct firmware *fw, void *context)
275*19c468b4SFrançois Tigeot {
276*19c468b4SFrançois Tigeot 	struct drm_i915_private *dev_priv = context;
277*19c468b4SFrançois Tigeot 	struct drm_device *dev = dev_priv->dev;
278*19c468b4SFrançois Tigeot 	struct intel_css_header *css_header;
279*19c468b4SFrançois Tigeot 	struct intel_package_header *package_header;
280*19c468b4SFrançois Tigeot 	struct intel_dmc_header *dmc_header;
281*19c468b4SFrançois Tigeot 	struct intel_csr *csr = &dev_priv->csr;
282*19c468b4SFrançois Tigeot 	char stepping = intel_get_stepping(dev);
283*19c468b4SFrançois Tigeot 	char substepping = intel_get_substepping(dev);
284*19c468b4SFrançois Tigeot 	uint32_t dmc_offset = CSR_DEFAULT_FW_OFFSET, readcount = 0, nbytes;
285*19c468b4SFrançois Tigeot 	uint32_t i;
286*19c468b4SFrançois Tigeot 	__be32 *dmc_payload;
287*19c468b4SFrançois Tigeot 	bool fw_loaded = false;
288*19c468b4SFrançois Tigeot 
289*19c468b4SFrançois Tigeot 	if (!fw) {
290*19c468b4SFrançois Tigeot 		i915_firmware_load_error_print(csr->fw_path, 0);
291*19c468b4SFrançois Tigeot 		goto out;
292*19c468b4SFrançois Tigeot 	}
293*19c468b4SFrançois Tigeot 
294*19c468b4SFrançois Tigeot 	if ((stepping == -ENODATA) || (substepping == -ENODATA)) {
295*19c468b4SFrançois Tigeot 		DRM_ERROR("Unknown stepping info, firmware loading failed\n");
296*19c468b4SFrançois Tigeot 		goto out;
297*19c468b4SFrançois Tigeot 	}
298*19c468b4SFrançois Tigeot 
299*19c468b4SFrançois Tigeot 	/* Extract CSS Header information*/
300*19c468b4SFrançois Tigeot 	css_header = (struct intel_css_header *)fw->data;
301*19c468b4SFrançois Tigeot 	if (sizeof(struct intel_css_header) !=
302*19c468b4SFrançois Tigeot 		(css_header->header_len * 4)) {
303*19c468b4SFrançois Tigeot 		DRM_ERROR("Firmware has wrong CSS header length %u bytes\n",
304*19c468b4SFrançois Tigeot 			(css_header->header_len * 4));
305*19c468b4SFrançois Tigeot 		goto out;
306*19c468b4SFrançois Tigeot 	}
307*19c468b4SFrançois Tigeot 	readcount += sizeof(struct intel_css_header);
308*19c468b4SFrançois Tigeot 
309*19c468b4SFrançois Tigeot 	/* Extract Package Header information*/
310*19c468b4SFrançois Tigeot 	package_header = (struct intel_package_header *)
311*19c468b4SFrançois Tigeot 					&fw->data[readcount];
312*19c468b4SFrançois Tigeot 	if (sizeof(struct intel_package_header) !=
313*19c468b4SFrançois Tigeot 		(package_header->header_len * 4)) {
314*19c468b4SFrançois Tigeot 		DRM_ERROR("Firmware has wrong package header length %u bytes\n",
315*19c468b4SFrançois Tigeot 			(package_header->header_len * 4));
316*19c468b4SFrançois Tigeot 		goto out;
317*19c468b4SFrançois Tigeot 	}
318*19c468b4SFrançois Tigeot 	readcount += sizeof(struct intel_package_header);
319*19c468b4SFrançois Tigeot 
320*19c468b4SFrançois Tigeot 	/* Search for dmc_offset to find firware binary. */
321*19c468b4SFrançois Tigeot 	for (i = 0; i < package_header->num_entries; i++) {
322*19c468b4SFrançois Tigeot 		if (package_header->fw_info[i].substepping == '*' &&
323*19c468b4SFrançois Tigeot 			stepping == package_header->fw_info[i].stepping) {
324*19c468b4SFrançois Tigeot 			dmc_offset = package_header->fw_info[i].offset;
325*19c468b4SFrançois Tigeot 			break;
326*19c468b4SFrançois Tigeot 		} else if (stepping == package_header->fw_info[i].stepping &&
327*19c468b4SFrançois Tigeot 			substepping == package_header->fw_info[i].substepping) {
328*19c468b4SFrançois Tigeot 			dmc_offset = package_header->fw_info[i].offset;
329*19c468b4SFrançois Tigeot 			break;
330*19c468b4SFrançois Tigeot 		} else if (package_header->fw_info[i].stepping == '*' &&
331*19c468b4SFrançois Tigeot 			package_header->fw_info[i].substepping == '*')
332*19c468b4SFrançois Tigeot 			dmc_offset = package_header->fw_info[i].offset;
333*19c468b4SFrançois Tigeot 	}
334*19c468b4SFrançois Tigeot 	if (dmc_offset == CSR_DEFAULT_FW_OFFSET) {
335*19c468b4SFrançois Tigeot 		DRM_ERROR("Firmware not supported for %c stepping\n", stepping);
336*19c468b4SFrançois Tigeot 		goto out;
337*19c468b4SFrançois Tigeot 	}
338*19c468b4SFrançois Tigeot 	readcount += dmc_offset;
339*19c468b4SFrançois Tigeot 
340*19c468b4SFrançois Tigeot 	/* Extract dmc_header information. */
341*19c468b4SFrançois Tigeot 	dmc_header = (struct intel_dmc_header *)&fw->data[readcount];
342*19c468b4SFrançois Tigeot 	if (sizeof(struct intel_dmc_header) != (dmc_header->header_len)) {
343*19c468b4SFrançois Tigeot 		DRM_ERROR("Firmware has wrong dmc header length %u bytes\n",
344*19c468b4SFrançois Tigeot 				(dmc_header->header_len));
345*19c468b4SFrançois Tigeot 		goto out;
346*19c468b4SFrançois Tigeot 	}
347*19c468b4SFrançois Tigeot 	readcount += sizeof(struct intel_dmc_header);
348*19c468b4SFrançois Tigeot 
349*19c468b4SFrançois Tigeot 	/* Cache the dmc header info. */
350*19c468b4SFrançois Tigeot 	if (dmc_header->mmio_count > ARRAY_SIZE(csr->mmioaddr)) {
351*19c468b4SFrançois Tigeot 		DRM_ERROR("Firmware has wrong mmio count %u\n",
352*19c468b4SFrançois Tigeot 						dmc_header->mmio_count);
353*19c468b4SFrançois Tigeot 		goto out;
354*19c468b4SFrançois Tigeot 	}
355*19c468b4SFrançois Tigeot 	csr->mmio_count = dmc_header->mmio_count;
356*19c468b4SFrançois Tigeot 	for (i = 0; i < dmc_header->mmio_count; i++) {
357*19c468b4SFrançois Tigeot 		if (dmc_header->mmioaddr[i] < CSR_MMIO_START_RANGE &&
358*19c468b4SFrançois Tigeot 			dmc_header->mmioaddr[i] > CSR_MMIO_END_RANGE) {
359*19c468b4SFrançois Tigeot 			DRM_ERROR(" Firmware has wrong mmio address 0x%x\n",
360*19c468b4SFrançois Tigeot 						dmc_header->mmioaddr[i]);
361*19c468b4SFrançois Tigeot 			goto out;
362*19c468b4SFrançois Tigeot 		}
363*19c468b4SFrançois Tigeot 		csr->mmioaddr[i] = dmc_header->mmioaddr[i];
364*19c468b4SFrançois Tigeot 		csr->mmiodata[i] = dmc_header->mmiodata[i];
365*19c468b4SFrançois Tigeot 	}
366*19c468b4SFrançois Tigeot 
367*19c468b4SFrançois Tigeot 	/* fw_size is in dwords, so multiplied by 4 to convert into bytes. */
368*19c468b4SFrançois Tigeot 	nbytes = dmc_header->fw_size * 4;
369*19c468b4SFrançois Tigeot 	if (nbytes > CSR_MAX_FW_SIZE) {
370*19c468b4SFrançois Tigeot 		DRM_ERROR("CSR firmware too big (%u) bytes\n", nbytes);
371*19c468b4SFrançois Tigeot 		goto out;
372*19c468b4SFrançois Tigeot 	}
373*19c468b4SFrançois Tigeot 	csr->dmc_fw_size = dmc_header->fw_size;
374*19c468b4SFrançois Tigeot 
375*19c468b4SFrançois Tigeot 	csr->dmc_payload = kmalloc(nbytes, M_DRM, M_WAITOK);
376*19c468b4SFrançois Tigeot 	if (!csr->dmc_payload) {
377*19c468b4SFrançois Tigeot 		DRM_ERROR("Memory allocation failed for dmc payload\n");
378*19c468b4SFrançois Tigeot 		goto out;
379*19c468b4SFrançois Tigeot 	}
380*19c468b4SFrançois Tigeot 
381*19c468b4SFrançois Tigeot 	dmc_payload = csr->dmc_payload;
382*19c468b4SFrançois Tigeot 	for (i = 0; i < dmc_header->fw_size; i++) {
383*19c468b4SFrançois Tigeot 		uint32_t *tmp = (u32 *)&fw->data[readcount + i * 4];
384*19c468b4SFrançois Tigeot 		/*
385*19c468b4SFrançois Tigeot 		 * The firmware payload is an array of 32 bit words stored in
386*19c468b4SFrançois Tigeot 		 * little-endian format in the firmware image and programmed
387*19c468b4SFrançois Tigeot 		 * as 32 bit big-endian format to memory.
388*19c468b4SFrançois Tigeot 		 */
389*19c468b4SFrançois Tigeot 		dmc_payload[i] = cpu_to_be32(*tmp);
390*19c468b4SFrançois Tigeot 	}
391*19c468b4SFrançois Tigeot 
392*19c468b4SFrançois Tigeot 	/* load csr program during system boot, as needed for DC states */
393*19c468b4SFrançois Tigeot 	intel_csr_load_program(dev);
394*19c468b4SFrançois Tigeot 	fw_loaded = true;
395*19c468b4SFrançois Tigeot 
396*19c468b4SFrançois Tigeot out:
397*19c468b4SFrançois Tigeot 	if (fw_loaded)
398*19c468b4SFrançois Tigeot 		intel_runtime_pm_put(dev_priv);
399*19c468b4SFrançois Tigeot 	else
400*19c468b4SFrançois Tigeot 		intel_csr_load_status_set(dev_priv, FW_FAILED);
401*19c468b4SFrançois Tigeot 
402*19c468b4SFrançois Tigeot 	release_firmware(fw);
403*19c468b4SFrançois Tigeot }
404*19c468b4SFrançois Tigeot #endif
405*19c468b4SFrançois Tigeot 
406*19c468b4SFrançois Tigeot /**
407*19c468b4SFrançois Tigeot  * intel_csr_ucode_init() - initialize the firmware loading.
408*19c468b4SFrançois Tigeot  * @dev: drm device.
409*19c468b4SFrançois Tigeot  *
410*19c468b4SFrançois Tigeot  * This function is called at the time of loading the display driver to read
411*19c468b4SFrançois Tigeot  * firmware from a .bin file and copied into a internal memory.
412*19c468b4SFrançois Tigeot  */
413*19c468b4SFrançois Tigeot void intel_csr_ucode_init(struct drm_device *dev)
414*19c468b4SFrançois Tigeot {
415*19c468b4SFrançois Tigeot #if 0
416*19c468b4SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
417*19c468b4SFrançois Tigeot 	struct intel_csr *csr = &dev_priv->csr;
418*19c468b4SFrançois Tigeot 	int ret;
419*19c468b4SFrançois Tigeot 
420*19c468b4SFrançois Tigeot 	if (!HAS_CSR(dev))
421*19c468b4SFrançois Tigeot 		return;
422*19c468b4SFrançois Tigeot 
423*19c468b4SFrançois Tigeot 	if (IS_SKYLAKE(dev))
424*19c468b4SFrançois Tigeot 		csr->fw_path = I915_CSR_SKL;
425*19c468b4SFrançois Tigeot 	else {
426*19c468b4SFrançois Tigeot 		DRM_ERROR("Unexpected: no known CSR firmware for platform\n");
427*19c468b4SFrançois Tigeot 		intel_csr_load_status_set(dev_priv, FW_FAILED);
428*19c468b4SFrançois Tigeot 		return;
429*19c468b4SFrançois Tigeot 	}
430*19c468b4SFrançois Tigeot 
431*19c468b4SFrançois Tigeot 	/*
432*19c468b4SFrançois Tigeot 	 * Obtain a runtime pm reference, until CSR is loaded,
433*19c468b4SFrançois Tigeot 	 * to avoid entering runtime-suspend.
434*19c468b4SFrançois Tigeot 	 */
435*19c468b4SFrançois Tigeot 	intel_runtime_pm_get(dev_priv);
436*19c468b4SFrançois Tigeot 
437*19c468b4SFrançois Tigeot 	/* CSR supported for platform, load firmware */
438*19c468b4SFrançois Tigeot 	ret = request_firmware_nowait(THIS_MODULE, true, csr->fw_path,
439*19c468b4SFrançois Tigeot 				&dev_priv->dev->pdev->dev,
440*19c468b4SFrançois Tigeot 				GFP_KERNEL, dev_priv,
441*19c468b4SFrançois Tigeot 				finish_csr_load);
442*19c468b4SFrançois Tigeot 	if (ret) {
443*19c468b4SFrançois Tigeot 		i915_firmware_load_error_print(csr->fw_path, ret);
444*19c468b4SFrançois Tigeot 		intel_csr_load_status_set(dev_priv, FW_FAILED);
445*19c468b4SFrançois Tigeot 	}
446*19c468b4SFrançois Tigeot #endif
447*19c468b4SFrançois Tigeot }
448*19c468b4SFrançois Tigeot 
449*19c468b4SFrançois Tigeot /**
450*19c468b4SFrançois Tigeot  * intel_csr_ucode_fini() - unload the CSR firmware.
451*19c468b4SFrançois Tigeot  * @dev: drm device.
452*19c468b4SFrançois Tigeot  *
453*19c468b4SFrançois Tigeot  * Firmmware unloading includes freeing the internal momory and reset the
454*19c468b4SFrançois Tigeot  * firmware loading status.
455*19c468b4SFrançois Tigeot  */
456*19c468b4SFrançois Tigeot void intel_csr_ucode_fini(struct drm_device *dev)
457*19c468b4SFrançois Tigeot {
458*19c468b4SFrançois Tigeot #if 0
459*19c468b4SFrançois Tigeot 	struct drm_i915_private *dev_priv = dev->dev_private;
460*19c468b4SFrançois Tigeot 
461*19c468b4SFrançois Tigeot 	if (!HAS_CSR(dev))
462*19c468b4SFrançois Tigeot 		return;
463*19c468b4SFrançois Tigeot 
464*19c468b4SFrançois Tigeot 	intel_csr_load_status_set(dev_priv, FW_FAILED);
465*19c468b4SFrançois Tigeot 	kfree(dev_priv->csr.dmc_payload);
466*19c468b4SFrançois Tigeot #endif
467*19c468b4SFrançois Tigeot }
468*19c468b4SFrançois Tigeot 
469*19c468b4SFrançois Tigeot void assert_csr_loaded(struct drm_i915_private *dev_priv)
470*19c468b4SFrançois Tigeot {
471*19c468b4SFrançois Tigeot 	WARN((intel_csr_load_status_get(dev_priv) != FW_LOADED), "CSR is not loaded.\n");
472*19c468b4SFrançois Tigeot 	WARN(!I915_READ(CSR_PROGRAM_BASE),
473*19c468b4SFrançois Tigeot 				"CSR program storage start is NULL\n");
474*19c468b4SFrançois Tigeot 	WARN(!I915_READ(CSR_SSP_BASE), "CSR SSP Base Not fine\n");
475*19c468b4SFrançois Tigeot 	WARN(!I915_READ(CSR_HTP_SKL), "CSR HTP Not fine\n");
476*19c468b4SFrançois Tigeot }
477