xref: /openbmc/linux/drivers/gpu/drm/msm/adreno/adreno_gpu.h (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
1caab277bSThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */
27198e6b0SRob Clark /*
37198e6b0SRob Clark  * Copyright (C) 2013 Red Hat
47198e6b0SRob Clark  * Author: Rob Clark <robdclark@gmail.com>
57198e6b0SRob Clark  *
6e812744cSSharat Masetty  * Copyright (c) 2014,2017, 2019 The Linux Foundation. All rights reserved.
77198e6b0SRob Clark  */
87198e6b0SRob Clark 
97198e6b0SRob Clark #ifndef __ADRENO_GPU_H__
107198e6b0SRob Clark #define __ADRENO_GPU_H__
117198e6b0SRob Clark 
127198e6b0SRob Clark #include <linux/firmware.h>
13983674e2SJordan Crouse #include <linux/iopoll.h>
147198e6b0SRob Clark 
157198e6b0SRob Clark #include "msm_gpu.h"
167198e6b0SRob Clark 
177198e6b0SRob Clark #include "adreno_common.xml.h"
187198e6b0SRob Clark #include "adreno_pm4.xml.h"
197198e6b0SRob Clark 
206f7cd6e4SRob Clark extern bool snapshot_debugbus;
213f7759e7SIskren Chernev extern bool allow_vram_carveout;
226f7cd6e4SRob Clark 
23c5e3548cSJordan Crouse enum {
24c5e3548cSJordan Crouse 	ADRENO_FW_PM4 = 0,
254b565ca5SJordan Crouse 	ADRENO_FW_SQE = 0, /* a6xx */
26c5e3548cSJordan Crouse 	ADRENO_FW_PFP = 1,
274b565ca5SJordan Crouse 	ADRENO_FW_GMU = 1, /* a6xx */
28c5e3548cSJordan Crouse 	ADRENO_FW_GPMU = 2,
29c5e3548cSJordan Crouse 	ADRENO_FW_MAX,
30c5e3548cSJordan Crouse };
31c5e3548cSJordan Crouse 
3267133dc0SRob Clark /**
3367133dc0SRob Clark  * @enum adreno_family: identify generation and possibly sub-generation
3467133dc0SRob Clark  *
3567133dc0SRob Clark  * In some cases there are distinct sub-generations within a major revision
3667133dc0SRob Clark  * so it helps to be able to group the GPU devices by generation and if
3767133dc0SRob Clark  * necessary sub-generation.
3867133dc0SRob Clark  */
3967133dc0SRob Clark enum adreno_family {
4067133dc0SRob Clark 	ADRENO_2XX_GEN1,  /* a20x */
4167133dc0SRob Clark 	ADRENO_2XX_GEN2,  /* a22x */
4267133dc0SRob Clark 	ADRENO_3XX,
4367133dc0SRob Clark 	ADRENO_4XX,
4467133dc0SRob Clark 	ADRENO_5XX,
4567133dc0SRob Clark 	ADRENO_6XX_GEN1,  /* a630 family */
4667133dc0SRob Clark 	ADRENO_6XX_GEN2,  /* a640 family */
4767133dc0SRob Clark 	ADRENO_6XX_GEN3,  /* a650 family */
4867133dc0SRob Clark 	ADRENO_6XX_GEN4,  /* a660 family */
4967133dc0SRob Clark };
5067133dc0SRob Clark 
5113ef096eSKonrad Dybcio #define ADRENO_QUIRK_TWO_PASS_USE_WFI		BIT(0)
5213ef096eSKonrad Dybcio #define ADRENO_QUIRK_FAULT_DETECT_MASK		BIT(1)
5313ef096eSKonrad Dybcio #define ADRENO_QUIRK_LMLOADKILL_DISABLE		BIT(2)
54459f9e26SRob Clark #define ADRENO_QUIRK_HAS_HW_APRIV		BIT(3)
55155668efSRob Clark #define ADRENO_QUIRK_HAS_CACHED_COHERENT	BIT(4)
56b5f103abSJordan Crouse 
578825f596SRob Clark /* Helper for formating the chip_id in the way that userspace tools like
588825f596SRob Clark  * crashdec expect.
598825f596SRob Clark  */
608825f596SRob Clark #define ADRENO_CHIPID_FMT "u.%u.%u.%u"
61*90b593ceSRob Clark #define ADRENO_CHIPID_ARGS(_c) \
62*90b593ceSRob Clark 	(((_c) >> 24) & 0xff), \
63*90b593ceSRob Clark 	(((_c) >> 16) & 0xff), \
64*90b593ceSRob Clark 	(((_c) >> 8)  & 0xff), \
65*90b593ceSRob Clark 	((_c) & 0xff)
668825f596SRob Clark 
677198e6b0SRob Clark struct adreno_gpu_funcs {
687198e6b0SRob Clark 	struct msm_gpu_funcs base;
696c77d1abSRob Clark 	int (*get_timestamp)(struct msm_gpu *gpu, uint64_t *value);
707198e6b0SRob Clark };
717198e6b0SRob Clark 
72b1c53a2aSJonathan Marek struct adreno_reglist {
73b1c53a2aSJonathan Marek 	u32 offset;
74b1c53a2aSJonathan Marek 	u32 value;
75b1c53a2aSJonathan Marek };
76b1c53a2aSJonathan Marek 
77e7fc9398SKonrad Dybcio extern const struct adreno_reglist a612_hwcg[], a615_hwcg[], a630_hwcg[], a640_hwcg[], a650_hwcg[];
78e7fc9398SKonrad Dybcio extern const struct adreno_reglist a660_hwcg[], a690_hwcg[];
79b1c53a2aSJonathan Marek 
80c928a05eSRob Clark struct adreno_speedbin {
81c928a05eSRob Clark 	uint16_t fuse;
82c928a05eSRob Clark 	uint16_t speedbin;
83c928a05eSRob Clark };
84c928a05eSRob Clark 
85e2550b7aSRob Clark struct adreno_info {
86f30a648dSRob Clark 	const char *machine;
87*90b593ceSRob Clark 	/**
88*90b593ceSRob Clark 	 * @chipids: Table of matching chip-ids
89*90b593ceSRob Clark 	 *
90*90b593ceSRob Clark 	 * Terminated with 0 sentinal
91*90b593ceSRob Clark 	 */
92*90b593ceSRob Clark 	uint32_t *chip_ids;
9367133dc0SRob Clark 	enum adreno_family family;
94e2550b7aSRob Clark 	uint32_t revn;
95c5e3548cSJordan Crouse 	const char *fw[ADRENO_FW_MAX];
96e2550b7aSRob Clark 	uint32_t gmem;
9713ef096eSKonrad Dybcio 	u64 quirks;
98e2550b7aSRob Clark 	struct msm_gpu *(*init)(struct drm_device *dev);
997c65817eSJordan Crouse 	const char *zapfw;
10064709686SJordan Crouse 	u32 inactive_period;
101b1c53a2aSJonathan Marek 	const struct adreno_reglist *hwcg;
10236bbfdb8SRob Clark 	u64 address_space_size;
103c928a05eSRob Clark 	/**
104c928a05eSRob Clark 	 * @speedbins: Optional table of fuse to speedbin mappings
105c928a05eSRob Clark 	 *
106c928a05eSRob Clark 	 * Consists of pairs of fuse, index mappings, terminated with
107c928a05eSRob Clark 	 * {SHRT_MAX, 0} sentinal.
108c928a05eSRob Clark 	 */
109c928a05eSRob Clark 	struct adreno_speedbin *speedbins;
110e2550b7aSRob Clark };
111e2550b7aSRob Clark 
112*90b593ceSRob Clark #define ADRENO_CHIP_IDS(tbl...) (uint32_t[]) { tbl, 0 }
113*90b593ceSRob Clark 
114c928a05eSRob Clark /*
115c928a05eSRob Clark  * Helper to build a speedbin table, ie. the table:
116c928a05eSRob Clark  *      fuse | speedbin
117c928a05eSRob Clark  *      -----+---------
118c928a05eSRob Clark  *        0  |   0
119c928a05eSRob Clark  *       169 |   1
120c928a05eSRob Clark  *       174 |   2
121c928a05eSRob Clark  *
122c928a05eSRob Clark  * would be declared as:
123c928a05eSRob Clark  *
124c928a05eSRob Clark  *     .speedbins = ADRENO_SPEEDBINS(
125c928a05eSRob Clark  *                      { 0,   0 },
126c928a05eSRob Clark  *                      { 169, 1 },
127c928a05eSRob Clark  *                      { 174, 2 },
128c928a05eSRob Clark  *     ),
129c928a05eSRob Clark  */
130c928a05eSRob Clark #define ADRENO_SPEEDBINS(tbl...) (struct adreno_speedbin[]) { tbl {SHRT_MAX, 0} }
131c928a05eSRob Clark 
1327198e6b0SRob Clark struct adreno_gpu {
1337198e6b0SRob Clark 	struct msm_gpu base;
1347198e6b0SRob Clark 	const struct adreno_info *info;
135*90b593ceSRob Clark 	uint32_t chip_id;
136afab9d91SAkhil P Oommen 	uint16_t speedbin;
1377198e6b0SRob Clark 	const struct adreno_gpu_funcs *funcs;
1387198e6b0SRob Clark 
1393bcefb04SRob Clark 	/* interesting register offsets to dump: */
1403bcefb04SRob Clark 	const unsigned int *registers;
1413bcefb04SRob Clark 
1422c41ef1bSRob Clark 	/*
1432c41ef1bSRob Clark 	 * Are we loading fw from legacy path?  Prior to addition
1442c41ef1bSRob Clark 	 * of gpu firmware to linux-firmware, the fw files were
1452c41ef1bSRob Clark 	 * placed in toplevel firmware directory, following qcom's
1462c41ef1bSRob Clark 	 * android kernel.  But linux-firmware preferred they be
1472c41ef1bSRob Clark 	 * placed in a 'qcom' subdirectory.
1482c41ef1bSRob Clark 	 *
1492c41ef1bSRob Clark 	 * For backwards compatibility, we try first to load from
1502c41ef1bSRob Clark 	 * the new path, using request_firmware_direct() to avoid
1512c41ef1bSRob Clark 	 * any potential timeout waiting for usermode helper, then
1522c41ef1bSRob Clark 	 * fall back to the old path (with direct load).  And
1532c41ef1bSRob Clark 	 * finally fall back to request_firmware() with the new
1542c41ef1bSRob Clark 	 * path to allow the usermode helper.
1552c41ef1bSRob Clark 	 */
1562c41ef1bSRob Clark 	enum {
1572c41ef1bSRob Clark 		FW_LOCATION_UNKNOWN = 0,
1582c41ef1bSRob Clark 		FW_LOCATION_NEW,       /* /lib/firmware/qcom/$fwfile */
1592c41ef1bSRob Clark 		FW_LOCATION_LEGACY,    /* /lib/firmware/$fwfile */
1602c41ef1bSRob Clark 		FW_LOCATION_HELPER,
1612c41ef1bSRob Clark 	} fwloc;
1622c41ef1bSRob Clark 
1637198e6b0SRob Clark 	/* firmware: */
164c5e3548cSJordan Crouse 	const struct firmware *fw[ADRENO_FW_MAX];
1657198e6b0SRob Clark 
16691b74e97SAravind Ganesan 	/*
16791b74e97SAravind Ganesan 	 * Register offsets are different between some GPUs.
16891b74e97SAravind Ganesan 	 * GPU specific offsets will be exported by GPU specific
16991b74e97SAravind Ganesan 	 * code (a3xx_gpu.c) and stored in this common location.
17091b74e97SAravind Ganesan 	 */
17191b74e97SAravind Ganesan 	const unsigned int *reg_offsets;
1725a903a44SKonrad Dybcio 	bool gmu_is_wrapper;
1737198e6b0SRob Clark };
1747198e6b0SRob Clark #define to_adreno_gpu(x) container_of(x, struct adreno_gpu, base)
1757198e6b0SRob Clark 
17626c0b26dSBrian Masney struct adreno_ocmem {
17726c0b26dSBrian Masney 	struct ocmem *ocmem;
17826c0b26dSBrian Masney 	unsigned long base;
17926c0b26dSBrian Masney 	void *hdl;
18026c0b26dSBrian Masney };
18126c0b26dSBrian Masney 
1827198e6b0SRob Clark /* platform config data (ie. from DT, or pdata) */
1837198e6b0SRob Clark struct adreno_platform_config {
184*90b593ceSRob Clark 	uint32_t chip_id;
18547bd37f9SRob Clark 	const struct adreno_info *info;
1867198e6b0SRob Clark };
1877198e6b0SRob Clark 
1880963756fSRob Clark #define ADRENO_IDLE_TIMEOUT msecs_to_jiffies(1000)
1890963756fSRob Clark 
1900963756fSRob Clark #define spin_until(X) ({                                   \
1910963756fSRob Clark 	int __ret = -ETIMEDOUT;                            \
1920963756fSRob Clark 	unsigned long __t = jiffies + ADRENO_IDLE_TIMEOUT; \
1930963756fSRob Clark 	do {                                               \
1940963756fSRob Clark 		if (X) {                                   \
1950963756fSRob Clark 			__ret = 0;                         \
1960963756fSRob Clark 			break;                             \
1970963756fSRob Clark 		}                                          \
1980963756fSRob Clark 	} while (time_before(jiffies, __t));               \
1990963756fSRob Clark 	__ret;                                             \
2000963756fSRob Clark })
2010963756fSRob Clark 
adreno_patchid(const struct adreno_gpu * gpu)202*90b593ceSRob Clark static inline uint8_t adreno_patchid(const struct adreno_gpu *gpu)
203*90b593ceSRob Clark {
204*90b593ceSRob Clark 	/* It is probably ok to assume legacy "adreno_rev" format
205*90b593ceSRob Clark 	 * for all a6xx devices, but probably best to limit this
206*90b593ceSRob Clark 	 * to older things.
207*90b593ceSRob Clark 	 */
208*90b593ceSRob Clark 	WARN_ON_ONCE(gpu->info->family >= ADRENO_6XX_GEN1);
209*90b593ceSRob Clark 	return gpu->chip_id & 0xff;
210*90b593ceSRob Clark }
21127514ce2SAkhil P Oommen 
adreno_is_revn(const struct adreno_gpu * gpu,uint32_t revn)212cc943f43SDmitry Baryshkov static inline bool adreno_is_revn(const struct adreno_gpu *gpu, uint32_t revn)
213cc943f43SDmitry Baryshkov {
214f4f1c707SRob Clark 	if (WARN_ON_ONCE(!gpu->info))
215f4f1c707SRob Clark 		return false;
216f4f1c707SRob Clark 	return gpu->info->revn == revn;
217cc943f43SDmitry Baryshkov }
218cc943f43SDmitry Baryshkov 
adreno_has_gmu_wrapper(const struct adreno_gpu * gpu)2195a903a44SKonrad Dybcio static inline bool adreno_has_gmu_wrapper(const struct adreno_gpu *gpu)
2205a903a44SKonrad Dybcio {
2215a903a44SKonrad Dybcio 	return gpu->gmu_is_wrapper;
2225a903a44SKonrad Dybcio }
2235a903a44SKonrad Dybcio 
adreno_is_a2xx(const struct adreno_gpu * gpu)2241b90e8f8SDmitry Baryshkov static inline bool adreno_is_a2xx(const struct adreno_gpu *gpu)
22521af872cSJonathan Marek {
226f4f1c707SRob Clark 	if (WARN_ON_ONCE(!gpu->info))
227f4f1c707SRob Clark 		return false;
22867133dc0SRob Clark 	return gpu->info->family <= ADRENO_2XX_GEN2;
22921af872cSJonathan Marek }
23021af872cSJonathan Marek 
adreno_is_a20x(const struct adreno_gpu * gpu)2311b90e8f8SDmitry Baryshkov static inline bool adreno_is_a20x(const struct adreno_gpu *gpu)
23221af872cSJonathan Marek {
233f4f1c707SRob Clark 	if (WARN_ON_ONCE(!gpu->info))
234f4f1c707SRob Clark 		return false;
23567133dc0SRob Clark 	return gpu->info->family == ADRENO_2XX_GEN1;
23621af872cSJonathan Marek }
23721af872cSJonathan Marek 
adreno_is_a225(const struct adreno_gpu * gpu)2381b90e8f8SDmitry Baryshkov static inline bool adreno_is_a225(const struct adreno_gpu *gpu)
23921af872cSJonathan Marek {
240cc943f43SDmitry Baryshkov 	return adreno_is_revn(gpu, 225);
24121af872cSJonathan Marek }
2427198e6b0SRob Clark 
adreno_is_a305(const struct adreno_gpu * gpu)2431b90e8f8SDmitry Baryshkov static inline bool adreno_is_a305(const struct adreno_gpu *gpu)
2447198e6b0SRob Clark {
245cc943f43SDmitry Baryshkov 	return adreno_is_revn(gpu, 305);
2467198e6b0SRob Clark }
2477198e6b0SRob Clark 
adreno_is_a306(const struct adreno_gpu * gpu)2481b90e8f8SDmitry Baryshkov static inline bool adreno_is_a306(const struct adreno_gpu *gpu)
249de558cd2SRob Clark {
250de558cd2SRob Clark 	/* yes, 307, because a305c is 306 */
251cc943f43SDmitry Baryshkov 	return adreno_is_revn(gpu, 307);
252de558cd2SRob Clark }
253de558cd2SRob Clark 
adreno_is_a320(const struct adreno_gpu * gpu)2541b90e8f8SDmitry Baryshkov static inline bool adreno_is_a320(const struct adreno_gpu *gpu)
2557198e6b0SRob Clark {
256cc943f43SDmitry Baryshkov 	return adreno_is_revn(gpu, 320);
2577198e6b0SRob Clark }
2587198e6b0SRob Clark 
adreno_is_a330(const struct adreno_gpu * gpu)2591b90e8f8SDmitry Baryshkov static inline bool adreno_is_a330(const struct adreno_gpu *gpu)
2607198e6b0SRob Clark {
261cc943f43SDmitry Baryshkov 	return adreno_is_revn(gpu, 330);
2627198e6b0SRob Clark }
2637198e6b0SRob Clark 
adreno_is_a330v2(const struct adreno_gpu * gpu)2641b90e8f8SDmitry Baryshkov static inline bool adreno_is_a330v2(const struct adreno_gpu *gpu)
26555459968SRob Clark {
266*90b593ceSRob Clark 	return adreno_is_a330(gpu) && (adreno_patchid(gpu) > 0);
26755459968SRob Clark }
26855459968SRob Clark 
adreno_is_a405(const struct adreno_gpu * gpu)2691b90e8f8SDmitry Baryshkov static inline int adreno_is_a405(const struct adreno_gpu *gpu)
270dc0fa5ebSShawn Guo {
271cc943f43SDmitry Baryshkov 	return adreno_is_revn(gpu, 405);
272dc0fa5ebSShawn Guo }
273dc0fa5ebSShawn Guo 
adreno_is_a420(const struct adreno_gpu * gpu)2741b90e8f8SDmitry Baryshkov static inline int adreno_is_a420(const struct adreno_gpu *gpu)
27523bd62fdSAravind Ganesan {
276cc943f43SDmitry Baryshkov 	return adreno_is_revn(gpu, 420);
27723bd62fdSAravind Ganesan }
27823bd62fdSAravind Ganesan 
adreno_is_a430(const struct adreno_gpu * gpu)2791b90e8f8SDmitry Baryshkov static inline int adreno_is_a430(const struct adreno_gpu *gpu)
280357ff00bSCraig Stout {
281cc943f43SDmitry Baryshkov 	return adreno_is_revn(gpu, 430);
282357ff00bSCraig Stout }
283357ff00bSCraig Stout 
adreno_is_a506(const struct adreno_gpu * gpu)2841b90e8f8SDmitry Baryshkov static inline int adreno_is_a506(const struct adreno_gpu *gpu)
2856bf78053SVladimir Lypak {
286cc943f43SDmitry Baryshkov 	return adreno_is_revn(gpu, 506);
2876bf78053SVladimir Lypak }
2886bf78053SVladimir Lypak 
adreno_is_a508(const struct adreno_gpu * gpu)2891b90e8f8SDmitry Baryshkov static inline int adreno_is_a508(const struct adreno_gpu *gpu)
2901d832ab3SAngeloGioacchino Del Regno {
291cc943f43SDmitry Baryshkov 	return adreno_is_revn(gpu, 508);
2921d832ab3SAngeloGioacchino Del Regno }
2931d832ab3SAngeloGioacchino Del Regno 
adreno_is_a509(const struct adreno_gpu * gpu)2941b90e8f8SDmitry Baryshkov static inline int adreno_is_a509(const struct adreno_gpu *gpu)
2951d832ab3SAngeloGioacchino Del Regno {
296cc943f43SDmitry Baryshkov 	return adreno_is_revn(gpu, 509);
2971d832ab3SAngeloGioacchino Del Regno }
2981d832ab3SAngeloGioacchino Del Regno 
adreno_is_a510(const struct adreno_gpu * gpu)2991b90e8f8SDmitry Baryshkov static inline int adreno_is_a510(const struct adreno_gpu *gpu)
300e20c9284SAngeloGioacchino Del Regno {
301cc943f43SDmitry Baryshkov 	return adreno_is_revn(gpu, 510);
302e20c9284SAngeloGioacchino Del Regno }
303e20c9284SAngeloGioacchino Del Regno 
adreno_is_a512(const struct adreno_gpu * gpu)3041b90e8f8SDmitry Baryshkov static inline int adreno_is_a512(const struct adreno_gpu *gpu)
3051d832ab3SAngeloGioacchino Del Regno {
306cc943f43SDmitry Baryshkov 	return adreno_is_revn(gpu, 512);
3071d832ab3SAngeloGioacchino Del Regno }
3081d832ab3SAngeloGioacchino Del Regno 
adreno_is_a530(const struct adreno_gpu * gpu)3091b90e8f8SDmitry Baryshkov static inline int adreno_is_a530(const struct adreno_gpu *gpu)
310b5f103abSJordan Crouse {
311cc943f43SDmitry Baryshkov 	return adreno_is_revn(gpu, 530);
312b5f103abSJordan Crouse }
313b5f103abSJordan Crouse 
adreno_is_a540(const struct adreno_gpu * gpu)3141b90e8f8SDmitry Baryshkov static inline int adreno_is_a540(const struct adreno_gpu *gpu)
315370063eeSJeffrey Hugo {
316cc943f43SDmitry Baryshkov 	return adreno_is_revn(gpu, 540);
317370063eeSJeffrey Hugo }
318370063eeSJeffrey Hugo 
adreno_is_a610(const struct adreno_gpu * gpu)319e7fc9398SKonrad Dybcio static inline int adreno_is_a610(const struct adreno_gpu *gpu)
320e7fc9398SKonrad Dybcio {
321e7fc9398SKonrad Dybcio 	return adreno_is_revn(gpu, 610);
322e7fc9398SKonrad Dybcio }
323e7fc9398SKonrad Dybcio 
adreno_is_a618(const struct adreno_gpu * gpu)3241b90e8f8SDmitry Baryshkov static inline int adreno_is_a618(const struct adreno_gpu *gpu)
325e812744cSSharat Masetty {
326cc943f43SDmitry Baryshkov 	return adreno_is_revn(gpu, 618);
327e812744cSSharat Masetty }
328e812744cSSharat Masetty 
adreno_is_a619(const struct adreno_gpu * gpu)3291b90e8f8SDmitry Baryshkov static inline int adreno_is_a619(const struct adreno_gpu *gpu)
330b7616b5cSKonrad Dybcio {
331cc943f43SDmitry Baryshkov 	return adreno_is_revn(gpu, 619);
332b7616b5cSKonrad Dybcio }
333b7616b5cSKonrad Dybcio 
adreno_is_a619_holi(const struct adreno_gpu * gpu)3348296ff0aSKonrad Dybcio static inline int adreno_is_a619_holi(const struct adreno_gpu *gpu)
3358296ff0aSKonrad Dybcio {
3368296ff0aSKonrad Dybcio 	return adreno_is_a619(gpu) && adreno_has_gmu_wrapper(gpu);
3378296ff0aSKonrad Dybcio }
3388296ff0aSKonrad Dybcio 
adreno_is_a630(const struct adreno_gpu * gpu)3391b90e8f8SDmitry Baryshkov static inline int adreno_is_a630(const struct adreno_gpu *gpu)
340e812744cSSharat Masetty {
341cc943f43SDmitry Baryshkov 	return adreno_is_revn(gpu, 630);
342e812744cSSharat Masetty }
343e812744cSSharat Masetty 
adreno_is_a640(const struct adreno_gpu * gpu)344b3bcd583SKonrad Dybcio static inline int adreno_is_a640(const struct adreno_gpu *gpu)
345a83366efSJonathan Marek {
346b3bcd583SKonrad Dybcio 	return adreno_is_revn(gpu, 640);
347a83366efSJonathan Marek }
348a83366efSJonathan Marek 
adreno_is_a650(const struct adreno_gpu * gpu)3491b90e8f8SDmitry Baryshkov static inline int adreno_is_a650(const struct adreno_gpu *gpu)
350a83366efSJonathan Marek {
351cc943f43SDmitry Baryshkov 	return adreno_is_revn(gpu, 650);
352a83366efSJonathan Marek }
353a83366efSJonathan Marek 
adreno_is_7c3(const struct adreno_gpu * gpu)3541b90e8f8SDmitry Baryshkov static inline int adreno_is_7c3(const struct adreno_gpu *gpu)
355192f4ee3SAkhil P Oommen {
356*90b593ceSRob Clark 	return gpu->info->chip_ids[0] == 0x06030500;
357192f4ee3SAkhil P Oommen }
358192f4ee3SAkhil P Oommen 
adreno_is_a660(const struct adreno_gpu * gpu)3591b90e8f8SDmitry Baryshkov static inline int adreno_is_a660(const struct adreno_gpu *gpu)
360f6d62d09SJonathan Marek {
361cc943f43SDmitry Baryshkov 	return adreno_is_revn(gpu, 660);
362f6d62d09SJonathan Marek }
363f6d62d09SJonathan Marek 
adreno_is_a680(const struct adreno_gpu * gpu)364b3bcd583SKonrad Dybcio static inline int adreno_is_a680(const struct adreno_gpu *gpu)
365b3bcd583SKonrad Dybcio {
366b3bcd583SKonrad Dybcio 	return adreno_is_revn(gpu, 680);
367b3bcd583SKonrad Dybcio }
368b3bcd583SKonrad Dybcio 
adreno_is_a690(const struct adreno_gpu * gpu)369b263325bSDmitry Baryshkov static inline int adreno_is_a690(const struct adreno_gpu *gpu)
3705e7665b5SBjorn Andersson {
371*90b593ceSRob Clark 	return gpu->info->chip_ids[0] == 0x06090000;
37275a5227cSRob Clark }
3735e7665b5SBjorn Andersson 
37475a5227cSRob Clark /* check for a615, a616, a618, a619 or any a630 derivatives */
adreno_is_a630_family(const struct adreno_gpu * gpu)37575a5227cSRob Clark static inline int adreno_is_a630_family(const struct adreno_gpu *gpu)
376b7616b5cSKonrad Dybcio {
37767133dc0SRob Clark 	if (WARN_ON_ONCE(!gpu->info))
37867133dc0SRob Clark 		return false;
37967133dc0SRob Clark 	return gpu->info->family == ADRENO_6XX_GEN1;
380b7616b5cSKonrad Dybcio }
381b7616b5cSKonrad Dybcio 
adreno_is_a660_family(const struct adreno_gpu * gpu)3821b90e8f8SDmitry Baryshkov static inline int adreno_is_a660_family(const struct adreno_gpu *gpu)
383192f4ee3SAkhil P Oommen {
38467133dc0SRob Clark 	if (WARN_ON_ONCE(!gpu->info))
38567133dc0SRob Clark 		return false;
38667133dc0SRob Clark 	return gpu->info->family == ADRENO_6XX_GEN4;
387192f4ee3SAkhil P Oommen }
388192f4ee3SAkhil P Oommen 
389f6d62d09SJonathan Marek /* check for a650, a660, or any derivatives */
adreno_is_a650_family(const struct adreno_gpu * gpu)3901b90e8f8SDmitry Baryshkov static inline int adreno_is_a650_family(const struct adreno_gpu *gpu)
391f6d62d09SJonathan Marek {
39267133dc0SRob Clark 	if (WARN_ON_ONCE(!gpu->info))
39367133dc0SRob Clark 		return false;
39467133dc0SRob Clark 	return gpu->info->family >= ADRENO_6XX_GEN3;
395f6d62d09SJonathan Marek }
396f6d62d09SJonathan Marek 
adreno_is_a640_family(const struct adreno_gpu * gpu)397b3bcd583SKonrad Dybcio static inline int adreno_is_a640_family(const struct adreno_gpu *gpu)
398b3bcd583SKonrad Dybcio {
39967133dc0SRob Clark 	if (WARN_ON_ONCE(!gpu->info))
40067133dc0SRob Clark 		return false;
40167133dc0SRob Clark 	return gpu->info->family == ADRENO_6XX_GEN2;
402b3bcd583SKonrad Dybcio }
403b3bcd583SKonrad Dybcio 
40436bbfdb8SRob Clark u64 adreno_private_address_space_size(struct msm_gpu *gpu);
405f98f915bSRob Clark int adreno_get_param(struct msm_gpu *gpu, struct msm_file_private *ctx,
4064bfba716SRob Clark 		     uint32_t param, uint64_t *value, uint32_t *len);
407f7ddbf55SRob Clark int adreno_set_param(struct msm_gpu *gpu, struct msm_file_private *ctx,
4084bfba716SRob Clark 		     uint32_t param, uint64_t value, uint32_t len);
409e8f3de96SRob Clark const struct firmware *adreno_request_fw(struct adreno_gpu *adreno_gpu,
410e8f3de96SRob Clark 		const char *fwname);
4119de43e79SJordan Crouse struct drm_gem_object *adreno_fw_create_bo(struct msm_gpu *gpu,
4129de43e79SJordan Crouse 		const struct firmware *fw, u64 *iova);
4137198e6b0SRob Clark int adreno_hw_init(struct msm_gpu *gpu);
414bd6f82d8SRob Clark void adreno_recover(struct msm_gpu *gpu);
4152fb7487aSJordan Crouse void adreno_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring, u32 reg);
416f97decacSJordan Crouse bool adreno_idle(struct msm_gpu *gpu, struct msm_ringbuffer *ring);
417c0fec7f5SJordan Crouse #if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEV_COREDUMP)
4184f776f45SJordan Crouse void adreno_show(struct msm_gpu *gpu, struct msm_gpu_state *state,
419c0fec7f5SJordan Crouse 		struct drm_printer *p);
4207198e6b0SRob Clark #endif
42126716185SRob Clark void adreno_dump_info(struct msm_gpu *gpu);
4225b6ef08eSRob Clark void adreno_dump(struct msm_gpu *gpu);
423f97decacSJordan Crouse void adreno_wait_ring(struct msm_ringbuffer *ring, uint32_t ndwords);
424f97decacSJordan Crouse struct msm_ringbuffer *adreno_active_ring(struct msm_gpu *gpu);
4257198e6b0SRob Clark 
42626c0b26dSBrian Masney int adreno_gpu_ocmem_init(struct device *dev, struct adreno_gpu *adreno_gpu,
42726c0b26dSBrian Masney 			  struct adreno_ocmem *ocmem);
42826c0b26dSBrian Masney void adreno_gpu_ocmem_cleanup(struct adreno_ocmem *ocmem);
42926c0b26dSBrian Masney 
4307198e6b0SRob Clark int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
431f97decacSJordan Crouse 		struct adreno_gpu *gpu, const struct adreno_gpu_funcs *funcs,
432f97decacSJordan Crouse 		int nr_rings);
4337198e6b0SRob Clark void adreno_gpu_cleanup(struct adreno_gpu *gpu);
4342c087a33SJordan Crouse int adreno_load_fw(struct adreno_gpu *adreno_gpu);
4357198e6b0SRob Clark 
43650f8d218SJordan Crouse void adreno_gpu_state_destroy(struct msm_gpu_state *state);
43750f8d218SJordan Crouse 
43850f8d218SJordan Crouse int adreno_gpu_state_get(struct msm_gpu *gpu, struct msm_gpu_state *state);
439c0fec7f5SJordan Crouse int adreno_gpu_state_put(struct msm_gpu_state *state);
440518380cbSAkhil P Oommen void adreno_show_object(struct drm_printer *p, void **ptr, int len,
441518380cbSAkhil P Oommen 		bool *encoded);
442e00e473dSJordan Crouse 
443a9e2559cSJordan Crouse /*
444ccac7ce3SJordan Crouse  * Common helper function to initialize the default address space for arm-smmu
445ccac7ce3SJordan Crouse  * attached targets
446ccac7ce3SJordan Crouse  */
447ccac7ce3SJordan Crouse struct msm_gem_address_space *
448822ff993SDmitry Baryshkov adreno_create_address_space(struct msm_gpu *gpu,
449ccac7ce3SJordan Crouse 			    struct platform_device *pdev);
450ccac7ce3SJordan Crouse 
451822ff993SDmitry Baryshkov struct msm_gem_address_space *
452822ff993SDmitry Baryshkov adreno_iommu_create_address_space(struct msm_gpu *gpu,
453822ff993SDmitry Baryshkov 				  struct platform_device *pdev,
454822ff993SDmitry Baryshkov 				  unsigned long quirks);
455822ff993SDmitry Baryshkov 
456f62ad0f6SDmitry Baryshkov int adreno_fault_handler(struct msm_gpu *gpu, unsigned long iova, int flags,
457f62ad0f6SDmitry Baryshkov 			 struct adreno_smmu_fault_info *info, const char *block,
458f62ad0f6SDmitry Baryshkov 			 u32 scratch[4]);
459f62ad0f6SDmitry Baryshkov 
460afab9d91SAkhil P Oommen int adreno_read_speedbin(struct device *dev, u32 *speedbin);
461afab9d91SAkhil P Oommen 
462ccac7ce3SJordan Crouse /*
463a9e2559cSJordan Crouse  * For a5xx and a6xx targets load the zap shader that is used to pull the GPU
464a9e2559cSJordan Crouse  * out of secure mode
465a9e2559cSJordan Crouse  */
466a9e2559cSJordan Crouse int adreno_zap_shader_load(struct msm_gpu *gpu, u32 pasid);
467a9e2559cSJordan Crouse 
4687198e6b0SRob Clark /* ringbuffer helpers (the parts that are adreno specific) */
4697198e6b0SRob Clark 
4707198e6b0SRob Clark static inline void
OUT_PKT0(struct msm_ringbuffer * ring,uint16_t regindx,uint16_t cnt)4717198e6b0SRob Clark OUT_PKT0(struct msm_ringbuffer *ring, uint16_t regindx, uint16_t cnt)
4727198e6b0SRob Clark {
473f97decacSJordan Crouse 	adreno_wait_ring(ring, cnt+1);
4747198e6b0SRob Clark 	OUT_RING(ring, CP_TYPE0_PKT | ((cnt-1) << 16) | (regindx & 0x7FFF));
4757198e6b0SRob Clark }
4767198e6b0SRob Clark 
4777198e6b0SRob Clark /* no-op packet: */
4787198e6b0SRob Clark static inline void
OUT_PKT2(struct msm_ringbuffer * ring)4797198e6b0SRob Clark OUT_PKT2(struct msm_ringbuffer *ring)
4807198e6b0SRob Clark {
481f97decacSJordan Crouse 	adreno_wait_ring(ring, 1);
4827198e6b0SRob Clark 	OUT_RING(ring, CP_TYPE2_PKT);
4837198e6b0SRob Clark }
4847198e6b0SRob Clark 
4857198e6b0SRob Clark static inline void
OUT_PKT3(struct msm_ringbuffer * ring,uint8_t opcode,uint16_t cnt)4867198e6b0SRob Clark OUT_PKT3(struct msm_ringbuffer *ring, uint8_t opcode, uint16_t cnt)
4877198e6b0SRob Clark {
488f97decacSJordan Crouse 	adreno_wait_ring(ring, cnt+1);
4897198e6b0SRob Clark 	OUT_RING(ring, CP_TYPE3_PKT | ((cnt-1) << 16) | ((opcode & 0xFF) << 8));
4907198e6b0SRob Clark }
4917198e6b0SRob Clark 
PM4_PARITY(u32 val)49205b9401bSJordan Crouse static inline u32 PM4_PARITY(u32 val)
49305b9401bSJordan Crouse {
49405b9401bSJordan Crouse 	return (0x9669 >> (0xF & (val ^
49505b9401bSJordan Crouse 		(val >> 4) ^ (val >> 8) ^ (val >> 12) ^
49605b9401bSJordan Crouse 		(val >> 16) ^ ((val) >> 20) ^ (val >> 24) ^
49705b9401bSJordan Crouse 		(val >> 28)))) & 1;
49805b9401bSJordan Crouse }
49905b9401bSJordan Crouse 
50005b9401bSJordan Crouse /* Maximum number of values that can be executed for one opcode */
50105b9401bSJordan Crouse #define TYPE4_MAX_PAYLOAD 127
50205b9401bSJordan Crouse 
50305b9401bSJordan Crouse #define PKT4(_reg, _cnt) \
50405b9401bSJordan Crouse 	(CP_TYPE4_PKT | ((_cnt) << 0) | (PM4_PARITY((_cnt)) << 7) | \
50505b9401bSJordan Crouse 	 (((_reg) & 0x3FFFF) << 8) | (PM4_PARITY((_reg)) << 27))
50605b9401bSJordan Crouse 
50705b9401bSJordan Crouse static inline void
OUT_PKT4(struct msm_ringbuffer * ring,uint16_t regindx,uint16_t cnt)50805b9401bSJordan Crouse OUT_PKT4(struct msm_ringbuffer *ring, uint16_t regindx, uint16_t cnt)
50905b9401bSJordan Crouse {
510f97decacSJordan Crouse 	adreno_wait_ring(ring, cnt + 1);
51105b9401bSJordan Crouse 	OUT_RING(ring, PKT4(regindx, cnt));
51205b9401bSJordan Crouse }
51305b9401bSJordan Crouse 
51405b9401bSJordan Crouse static inline void
OUT_PKT7(struct msm_ringbuffer * ring,uint8_t opcode,uint16_t cnt)51505b9401bSJordan Crouse OUT_PKT7(struct msm_ringbuffer *ring, uint8_t opcode, uint16_t cnt)
51605b9401bSJordan Crouse {
517f97decacSJordan Crouse 	adreno_wait_ring(ring, cnt + 1);
51805b9401bSJordan Crouse 	OUT_RING(ring, CP_TYPE7_PKT | (cnt << 0) | (PM4_PARITY(cnt) << 15) |
51905b9401bSJordan Crouse 		((opcode & 0x7F) << 16) | (PM4_PARITY(opcode) << 23));
52005b9401bSJordan Crouse }
52105b9401bSJordan Crouse 
52221af872cSJonathan Marek struct msm_gpu *a2xx_gpu_init(struct drm_device *dev);
523a5725ab0SBaoyou Xie struct msm_gpu *a3xx_gpu_init(struct drm_device *dev);
524a5725ab0SBaoyou Xie struct msm_gpu *a4xx_gpu_init(struct drm_device *dev);
525b5f103abSJordan Crouse struct msm_gpu *a5xx_gpu_init(struct drm_device *dev);
5264b565ca5SJordan Crouse struct msm_gpu *a6xx_gpu_init(struct drm_device *dev);
527a5725ab0SBaoyou Xie 
get_wptr(struct msm_ringbuffer * ring)528b1fc2839SJordan Crouse static inline uint32_t get_wptr(struct msm_ringbuffer *ring)
529b1fc2839SJordan Crouse {
530b1fc2839SJordan Crouse 	return (ring->cur - ring->start) % (MSM_GPU_RINGBUFFER_SZ >> 2);
531b1fc2839SJordan Crouse }
532b1fc2839SJordan Crouse 
533b5f103abSJordan Crouse /*
534b5f103abSJordan Crouse  * Given a register and a count, return a value to program into
535b5f103abSJordan Crouse  * REG_CP_PROTECT_REG(n) - this will block both reads and writes for _len
536b5f103abSJordan Crouse  * registers starting at _reg.
537b5f103abSJordan Crouse  *
538b5f103abSJordan Crouse  * The register base needs to be a multiple of the length. If it is not, the
539b5f103abSJordan Crouse  * hardware will quietly mask off the bits for you and shift the size. For
540b5f103abSJordan Crouse  * example, if you intend the protection to start at 0x07 for a length of 4
541b5f103abSJordan Crouse  * (0x07-0x0A) the hardware will actually protect (0x04-0x07) which might
542b5f103abSJordan Crouse  * expose registers you intended to protect!
543b5f103abSJordan Crouse  */
544b5f103abSJordan Crouse #define ADRENO_PROTECT_RW(_reg, _len) \
545b5f103abSJordan Crouse 	((1 << 30) | (1 << 29) | \
546b5f103abSJordan Crouse 	((ilog2((_len)) & 0x1F) << 24) | (((_reg) << 2) & 0xFFFFF))
547b5f103abSJordan Crouse 
548b5f103abSJordan Crouse /*
549b5f103abSJordan Crouse  * Same as above, but allow reads over the range. For areas of mixed use (such
550b5f103abSJordan Crouse  * as performance counters) this allows us to protect a much larger range with a
551b5f103abSJordan Crouse  * single register
552b5f103abSJordan Crouse  */
553b5f103abSJordan Crouse #define ADRENO_PROTECT_RDONLY(_reg, _len) \
554b5f103abSJordan Crouse 	((1 << 29) \
555b5f103abSJordan Crouse 	((ilog2((_len)) & 0x1F) << 24) | (((_reg) << 2) & 0xFFFFF))
556b5f103abSJordan Crouse 
557983674e2SJordan Crouse 
558983674e2SJordan Crouse #define gpu_poll_timeout(gpu, addr, val, cond, interval, timeout) \
559983674e2SJordan Crouse 	readl_poll_timeout((gpu)->mmio + ((addr) << 2), val, cond, \
560983674e2SJordan Crouse 		interval, timeout)
561983674e2SJordan Crouse 
5627198e6b0SRob Clark #endif /* __ADRENO_GPU_H__ */
563