blob: 24f16c61bc9fc73ce1231a406a7f38a36605d0f8 [file] [log] [blame]
Dhaval Patel6fe7f672017-02-10 12:40:46 -08001/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
Ben Chan78647cd2016-06-26 22:02:47 -04002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/bitops.h>
14#include <linux/slab.h>
15
16#include "sde_kms.h"
17#include "sde_hw_interrupts.h"
Clarence Ipc475b082016-06-26 09:27:23 -040018#include "sde_hw_util.h"
Ben Chan78647cd2016-06-26 22:02:47 -040019#include "sde_hw_mdss.h"
20
21/**
22 * Register offsets in MDSS register file for the interrupt registers
23 * w.r.t. to the MDSS base
24 */
25#define HW_INTR_STATUS 0x0010
26#define MDP_SSPP_TOP0_OFF 0x1000
27#define MDP_INTF_0_OFF 0x6B000
28#define MDP_INTF_1_OFF 0x6B800
29#define MDP_INTF_2_OFF 0x6C000
30#define MDP_INTF_3_OFF 0x6C800
31#define MDP_INTF_4_OFF 0x6D000
Gopikrishnaiah Anandan5154c712017-02-27 17:48:24 -080032#define MDP_AD4_0_OFF 0x7D000
33#define MDP_AD4_1_OFF 0x7E000
Lloyd Atkinson74bada42017-04-18 11:37:55 -070034#define MDP_AD4_INTR_EN_OFF 0x41c
35#define MDP_AD4_INTR_CLEAR_OFF 0x424
36#define MDP_AD4_INTR_STATUS_OFF 0x420
Ben Chan78647cd2016-06-26 22:02:47 -040037
38/**
39 * WB interrupt status bit definitions
40 */
41#define SDE_INTR_WB_0_DONE BIT(0)
42#define SDE_INTR_WB_1_DONE BIT(1)
43#define SDE_INTR_WB_2_DONE BIT(4)
44
45/**
46 * WDOG timer interrupt status bit definitions
47 */
48#define SDE_INTR_WD_TIMER_0_DONE BIT(2)
49#define SDE_INTR_WD_TIMER_1_DONE BIT(3)
50#define SDE_INTR_WD_TIMER_2_DONE BIT(5)
51#define SDE_INTR_WD_TIMER_3_DONE BIT(6)
52#define SDE_INTR_WD_TIMER_4_DONE BIT(7)
53
54/**
55 * Pingpong interrupt status bit definitions
56 */
57#define SDE_INTR_PING_PONG_0_DONE BIT(8)
58#define SDE_INTR_PING_PONG_1_DONE BIT(9)
59#define SDE_INTR_PING_PONG_2_DONE BIT(10)
60#define SDE_INTR_PING_PONG_3_DONE BIT(11)
61#define SDE_INTR_PING_PONG_0_RD_PTR BIT(12)
62#define SDE_INTR_PING_PONG_1_RD_PTR BIT(13)
63#define SDE_INTR_PING_PONG_2_RD_PTR BIT(14)
64#define SDE_INTR_PING_PONG_3_RD_PTR BIT(15)
65#define SDE_INTR_PING_PONG_0_WR_PTR BIT(16)
66#define SDE_INTR_PING_PONG_1_WR_PTR BIT(17)
67#define SDE_INTR_PING_PONG_2_WR_PTR BIT(18)
68#define SDE_INTR_PING_PONG_3_WR_PTR BIT(19)
69#define SDE_INTR_PING_PONG_0_AUTOREFRESH_DONE BIT(20)
70#define SDE_INTR_PING_PONG_1_AUTOREFRESH_DONE BIT(21)
71#define SDE_INTR_PING_PONG_2_AUTOREFRESH_DONE BIT(22)
72#define SDE_INTR_PING_PONG_3_AUTOREFRESH_DONE BIT(23)
73
74/**
75 * Interface interrupt status bit definitions
76 */
77#define SDE_INTR_INTF_0_UNDERRUN BIT(24)
78#define SDE_INTR_INTF_1_UNDERRUN BIT(26)
79#define SDE_INTR_INTF_2_UNDERRUN BIT(28)
80#define SDE_INTR_INTF_3_UNDERRUN BIT(30)
81#define SDE_INTR_INTF_0_VSYNC BIT(25)
82#define SDE_INTR_INTF_1_VSYNC BIT(27)
83#define SDE_INTR_INTF_2_VSYNC BIT(29)
84#define SDE_INTR_INTF_3_VSYNC BIT(31)
85
86/**
87 * Pingpong Secondary interrupt status bit definitions
88 */
89#define SDE_INTR_PING_PONG_S0_AUTOREFRESH_DONE BIT(0)
Lloyd Atkinson74bada42017-04-18 11:37:55 -070090#define SDE_INTR_PING_PONG_S0_WR_PTR BIT(4)
Ben Chan78647cd2016-06-26 22:02:47 -040091#define SDE_INTR_PING_PONG_S0_RD_PTR BIT(8)
92#define SDE_INTR_PING_PONG_S0_TEAR_DETECTED BIT(22)
93#define SDE_INTR_PING_PONG_S0_TE_DETECTED BIT(28)
94
95/**
96 * Pingpong TEAR detection interrupt status bit definitions
97 */
98#define SDE_INTR_PING_PONG_0_TEAR_DETECTED BIT(16)
99#define SDE_INTR_PING_PONG_1_TEAR_DETECTED BIT(17)
100#define SDE_INTR_PING_PONG_2_TEAR_DETECTED BIT(18)
101#define SDE_INTR_PING_PONG_3_TEAR_DETECTED BIT(19)
102
103/**
104 * Pingpong TE detection interrupt status bit definitions
105 */
106#define SDE_INTR_PING_PONG_0_TE_DETECTED BIT(24)
107#define SDE_INTR_PING_PONG_1_TE_DETECTED BIT(25)
108#define SDE_INTR_PING_PONG_2_TE_DETECTED BIT(26)
109#define SDE_INTR_PING_PONG_3_TE_DETECTED BIT(27)
110
111/**
Dhaval Patel55396cc2017-05-01 23:45:59 -0700112 * Ctl start interrupt status bit definitions
113 */
114#define SDE_INTR_CTL_0_START BIT(9)
115#define SDE_INTR_CTL_1_START BIT(10)
116#define SDE_INTR_CTL_2_START BIT(11)
117#define SDE_INTR_CTL_3_START BIT(12)
118#define SDE_INTR_CTL_4_START BIT(13)
119
120/**
Ben Chan78647cd2016-06-26 22:02:47 -0400121 * Concurrent WB overflow interrupt status bit definitions
122 */
123#define SDE_INTR_CWB_2_OVERFLOW BIT(14)
124#define SDE_INTR_CWB_3_OVERFLOW BIT(15)
125
126/**
127 * Histogram VIG done interrupt status bit definitions
128 */
129#define SDE_INTR_HIST_VIG_0_DONE BIT(0)
130#define SDE_INTR_HIST_VIG_1_DONE BIT(4)
131#define SDE_INTR_HIST_VIG_2_DONE BIT(8)
132#define SDE_INTR_HIST_VIG_3_DONE BIT(10)
133
134/**
135 * Histogram VIG reset Sequence done interrupt status bit definitions
136 */
137#define SDE_INTR_HIST_VIG_0_RSTSEQ_DONE BIT(1)
138#define SDE_INTR_HIST_VIG_1_RSTSEQ_DONE BIT(5)
139#define SDE_INTR_HIST_VIG_2_RSTSEQ_DONE BIT(9)
140#define SDE_INTR_HIST_VIG_3_RSTSEQ_DONE BIT(11)
141
142/**
143 * Histogram DSPP done interrupt status bit definitions
144 */
145#define SDE_INTR_HIST_DSPP_0_DONE BIT(12)
146#define SDE_INTR_HIST_DSPP_1_DONE BIT(16)
147#define SDE_INTR_HIST_DSPP_2_DONE BIT(20)
148#define SDE_INTR_HIST_DSPP_3_DONE BIT(22)
149
150/**
151 * Histogram DSPP reset Sequence done interrupt status bit definitions
152 */
153#define SDE_INTR_HIST_DSPP_0_RSTSEQ_DONE BIT(13)
154#define SDE_INTR_HIST_DSPP_1_RSTSEQ_DONE BIT(17)
155#define SDE_INTR_HIST_DSPP_2_RSTSEQ_DONE BIT(21)
156#define SDE_INTR_HIST_DSPP_3_RSTSEQ_DONE BIT(23)
157
158/**
159 * INTF interrupt status bit definitions
160 */
161#define SDE_INTR_VIDEO_INTO_STATIC BIT(0)
162#define SDE_INTR_VIDEO_OUTOF_STATIC BIT(1)
163#define SDE_INTR_DSICMD_0_INTO_STATIC BIT(2)
164#define SDE_INTR_DSICMD_0_OUTOF_STATIC BIT(3)
165#define SDE_INTR_DSICMD_1_INTO_STATIC BIT(4)
166#define SDE_INTR_DSICMD_1_OUTOF_STATIC BIT(5)
167#define SDE_INTR_DSICMD_2_INTO_STATIC BIT(6)
168#define SDE_INTR_DSICMD_2_OUTOF_STATIC BIT(7)
169#define SDE_INTR_PROG_LINE BIT(8)
170
171/**
Gopikrishnaiah Anandan5154c712017-02-27 17:48:24 -0800172 * AD4 interrupt status bit definitions
173 */
174#define SDE_INTR_BRIGHTPR_UPDATED BIT(4)
175#define SDE_INTR_DARKENH_UPDATED BIT(3)
176#define SDE_INTR_STREN_OUTROI_UPDATED BIT(2)
177#define SDE_INTR_STREN_INROI_UPDATED BIT(1)
178#define SDE_INTR_BACKLIGHT_UPDATED BIT(0)
179/**
Ben Chan78647cd2016-06-26 22:02:47 -0400180 * struct sde_intr_reg - array of SDE register sets
181 * @clr_off: offset to CLEAR reg
182 * @en_off: offset to ENABLE reg
183 * @status_off: offset to STATUS reg
184 */
185struct sde_intr_reg {
186 u32 clr_off;
187 u32 en_off;
188 u32 status_off;
189};
190
191/**
192 * struct sde_irq_type - maps each irq with i/f
193 * @intr_type: type of interrupt listed in sde_intr_type
194 * @instance_idx: instance index of the associated HW block in SDE
195 * @irq_mask: corresponding bit in the interrupt status reg
196 * @reg_idx: which reg set to use
197 */
198struct sde_irq_type {
199 u32 intr_type;
200 u32 instance_idx;
201 u32 irq_mask;
202 u32 reg_idx;
203};
204
205/**
206 * List of SDE interrupt registers
207 */
208static const struct sde_intr_reg sde_intr_set[] = {
209 {
210 MDP_SSPP_TOP0_OFF+INTR_CLEAR,
211 MDP_SSPP_TOP0_OFF+INTR_EN,
212 MDP_SSPP_TOP0_OFF+INTR_STATUS
213 },
214 {
215 MDP_SSPP_TOP0_OFF+INTR2_CLEAR,
216 MDP_SSPP_TOP0_OFF+INTR2_EN,
217 MDP_SSPP_TOP0_OFF+INTR2_STATUS
218 },
219 {
220 MDP_SSPP_TOP0_OFF+HIST_INTR_CLEAR,
221 MDP_SSPP_TOP0_OFF+HIST_INTR_EN,
222 MDP_SSPP_TOP0_OFF+HIST_INTR_STATUS
223 },
224 {
225 MDP_INTF_0_OFF+INTF_INTR_CLEAR,
226 MDP_INTF_0_OFF+INTF_INTR_EN,
227 MDP_INTF_0_OFF+INTF_INTR_STATUS
228 },
229 {
230 MDP_INTF_1_OFF+INTF_INTR_CLEAR,
231 MDP_INTF_1_OFF+INTF_INTR_EN,
232 MDP_INTF_1_OFF+INTF_INTR_STATUS
233 },
234 {
235 MDP_INTF_2_OFF+INTF_INTR_CLEAR,
236 MDP_INTF_2_OFF+INTF_INTR_EN,
237 MDP_INTF_2_OFF+INTF_INTR_STATUS
238 },
239 {
240 MDP_INTF_3_OFF+INTF_INTR_CLEAR,
241 MDP_INTF_3_OFF+INTF_INTR_EN,
242 MDP_INTF_3_OFF+INTF_INTR_STATUS
243 },
244 {
245 MDP_INTF_4_OFF+INTF_INTR_CLEAR,
246 MDP_INTF_4_OFF+INTF_INTR_EN,
247 MDP_INTF_4_OFF+INTF_INTR_STATUS
Gopikrishnaiah Anandan5154c712017-02-27 17:48:24 -0800248 },
249 {
250 MDP_AD4_0_OFF + MDP_AD4_INTR_CLEAR_OFF,
251 MDP_AD4_0_OFF + MDP_AD4_INTR_EN_OFF,
252 MDP_AD4_0_OFF + MDP_AD4_INTR_STATUS_OFF,
253 },
254 {
255 MDP_AD4_1_OFF + MDP_AD4_INTR_CLEAR_OFF,
256 MDP_AD4_1_OFF + MDP_AD4_INTR_EN_OFF,
257 MDP_AD4_1_OFF + MDP_AD4_INTR_STATUS_OFF,
Ben Chan78647cd2016-06-26 22:02:47 -0400258 }
259};
260
261/**
262 * IRQ mapping table - use for lookup an irq_idx in this table that have
263 * a matching interface type and instance index.
264 */
265static const struct sde_irq_type sde_irq_map[] = {
266 /* BEGIN MAP_RANGE: 0-31, INTR */
267 /* irq_idx: 0-3 */
268 { SDE_IRQ_TYPE_WB_ROT_COMP, WB_0, SDE_INTR_WB_0_DONE, 0},
269 { SDE_IRQ_TYPE_WB_ROT_COMP, WB_1, SDE_INTR_WB_1_DONE, 0},
270 { SDE_IRQ_TYPE_WD_TIMER, WD_TIMER_0, SDE_INTR_WD_TIMER_0_DONE, 0},
271 { SDE_IRQ_TYPE_WD_TIMER, WD_TIMER_1, SDE_INTR_WD_TIMER_1_DONE, 0},
272 /* irq_idx: 4-7 */
273 { SDE_IRQ_TYPE_WB_WFD_COMP, WB_2, SDE_INTR_WB_2_DONE, 0},
274 { SDE_IRQ_TYPE_WD_TIMER, WD_TIMER_2, SDE_INTR_WD_TIMER_2_DONE, 0},
275 { SDE_IRQ_TYPE_WD_TIMER, WD_TIMER_3, SDE_INTR_WD_TIMER_3_DONE, 0},
276 { SDE_IRQ_TYPE_WD_TIMER, WD_TIMER_4, SDE_INTR_WD_TIMER_4_DONE, 0},
277 /* irq_idx: 8-11 */
278 { SDE_IRQ_TYPE_PING_PONG_COMP, PINGPONG_0,
279 SDE_INTR_PING_PONG_0_DONE, 0},
280 { SDE_IRQ_TYPE_PING_PONG_COMP, PINGPONG_1,
281 SDE_INTR_PING_PONG_1_DONE, 0},
282 { SDE_IRQ_TYPE_PING_PONG_COMP, PINGPONG_2,
283 SDE_INTR_PING_PONG_2_DONE, 0},
284 { SDE_IRQ_TYPE_PING_PONG_COMP, PINGPONG_3,
285 SDE_INTR_PING_PONG_3_DONE, 0},
286 /* irq_idx: 12-15 */
287 { SDE_IRQ_TYPE_PING_PONG_RD_PTR, PINGPONG_0,
288 SDE_INTR_PING_PONG_0_RD_PTR, 0},
289 { SDE_IRQ_TYPE_PING_PONG_RD_PTR, PINGPONG_1,
290 SDE_INTR_PING_PONG_1_RD_PTR, 0},
291 { SDE_IRQ_TYPE_PING_PONG_RD_PTR, PINGPONG_2,
292 SDE_INTR_PING_PONG_2_RD_PTR, 0},
293 { SDE_IRQ_TYPE_PING_PONG_RD_PTR, PINGPONG_3,
294 SDE_INTR_PING_PONG_3_RD_PTR, 0},
295 /* irq_idx: 16-19 */
296 { SDE_IRQ_TYPE_PING_PONG_WR_PTR, PINGPONG_0,
297 SDE_INTR_PING_PONG_0_WR_PTR, 0},
298 { SDE_IRQ_TYPE_PING_PONG_WR_PTR, PINGPONG_1,
299 SDE_INTR_PING_PONG_1_WR_PTR, 0},
300 { SDE_IRQ_TYPE_PING_PONG_WR_PTR, PINGPONG_2,
301 SDE_INTR_PING_PONG_2_WR_PTR, 0},
302 { SDE_IRQ_TYPE_PING_PONG_WR_PTR, PINGPONG_3,
303 SDE_INTR_PING_PONG_3_WR_PTR, 0},
304 /* irq_idx: 20-23 */
305 { SDE_IRQ_TYPE_PING_PONG_AUTO_REF, PINGPONG_0,
306 SDE_INTR_PING_PONG_0_AUTOREFRESH_DONE, 0},
307 { SDE_IRQ_TYPE_PING_PONG_AUTO_REF, PINGPONG_1,
308 SDE_INTR_PING_PONG_1_AUTOREFRESH_DONE, 0},
309 { SDE_IRQ_TYPE_PING_PONG_AUTO_REF, PINGPONG_2,
310 SDE_INTR_PING_PONG_2_AUTOREFRESH_DONE, 0},
311 { SDE_IRQ_TYPE_PING_PONG_AUTO_REF, PINGPONG_3,
312 SDE_INTR_PING_PONG_3_AUTOREFRESH_DONE, 0},
313 /* irq_idx: 24-27 */
314 { SDE_IRQ_TYPE_INTF_UNDER_RUN, INTF_0, SDE_INTR_INTF_0_UNDERRUN, 0},
315 { SDE_IRQ_TYPE_INTF_VSYNC, INTF_0, SDE_INTR_INTF_0_VSYNC, 0},
316 { SDE_IRQ_TYPE_INTF_UNDER_RUN, INTF_1, SDE_INTR_INTF_1_UNDERRUN, 0},
317 { SDE_IRQ_TYPE_INTF_VSYNC, INTF_1, SDE_INTR_INTF_1_VSYNC, 0},
318 /* irq_idx: 28-31 */
319 { SDE_IRQ_TYPE_INTF_UNDER_RUN, INTF_2, SDE_INTR_INTF_2_UNDERRUN, 0},
320 { SDE_IRQ_TYPE_INTF_VSYNC, INTF_2, SDE_INTR_INTF_2_VSYNC, 0},
321 { SDE_IRQ_TYPE_INTF_UNDER_RUN, INTF_3, SDE_INTR_INTF_3_UNDERRUN, 0},
322 { SDE_IRQ_TYPE_INTF_VSYNC, INTF_3, SDE_INTR_INTF_3_VSYNC, 0},
323
324 /* BEGIN MAP_RANGE: 32-64, INTR2 */
325 /* irq_idx: 32-35 */
326 { SDE_IRQ_TYPE_PING_PONG_AUTO_REF, PINGPONG_S0,
327 SDE_INTR_PING_PONG_S0_AUTOREFRESH_DONE, 1},
328 { SDE_IRQ_TYPE_RESERVED, 0, 0, 1},
329 { SDE_IRQ_TYPE_RESERVED, 0, 0, 1},
330 { SDE_IRQ_TYPE_RESERVED, 0, 0, 1},
331 /* irq_idx: 36-39 */
332 { SDE_IRQ_TYPE_PING_PONG_WR_PTR, PINGPONG_S0,
333 SDE_INTR_PING_PONG_S0_WR_PTR, 1},
334 { SDE_IRQ_TYPE_RESERVED, 0, 0, 1},
335 { SDE_IRQ_TYPE_RESERVED, 0, 0, 1},
336 { SDE_IRQ_TYPE_RESERVED, 0, 0, 1},
Dhaval Patel55396cc2017-05-01 23:45:59 -0700337 /* irq_idx: 40 */
Ben Chan78647cd2016-06-26 22:02:47 -0400338 { SDE_IRQ_TYPE_PING_PONG_RD_PTR, PINGPONG_S0,
339 SDE_INTR_PING_PONG_S0_RD_PTR, 1},
Dhaval Patel55396cc2017-05-01 23:45:59 -0700340 /* irq_idx: 41-45 */
341 { SDE_IRQ_TYPE_CTL_START, CTL_0,
342 SDE_INTR_CTL_0_START, 1},
343 { SDE_IRQ_TYPE_CTL_START, CTL_1,
344 SDE_INTR_CTL_1_START, 1},
345 { SDE_IRQ_TYPE_CTL_START, CTL_2,
346 SDE_INTR_CTL_2_START, 1},
347 { SDE_IRQ_TYPE_CTL_START, CTL_3,
348 SDE_INTR_CTL_3_START, 1},
349 { SDE_IRQ_TYPE_CTL_START, CTL_4,
350 SDE_INTR_CTL_4_START, 1},
351 /* irq_idx: 46-47 */
Ben Chan78647cd2016-06-26 22:02:47 -0400352 { SDE_IRQ_TYPE_CWB_OVERFLOW, CWB_2, SDE_INTR_CWB_2_OVERFLOW, 1},
353 { SDE_IRQ_TYPE_CWB_OVERFLOW, CWB_3, SDE_INTR_CWB_3_OVERFLOW, 1},
354 /* irq_idx: 48-51 */
355 { SDE_IRQ_TYPE_PING_PONG_TEAR_CHECK, PINGPONG_0,
356 SDE_INTR_PING_PONG_0_TEAR_DETECTED, 1},
357 { SDE_IRQ_TYPE_PING_PONG_TEAR_CHECK, PINGPONG_1,
358 SDE_INTR_PING_PONG_1_TEAR_DETECTED, 1},
359 { SDE_IRQ_TYPE_PING_PONG_TEAR_CHECK, PINGPONG_2,
360 SDE_INTR_PING_PONG_2_TEAR_DETECTED, 1},
361 { SDE_IRQ_TYPE_PING_PONG_TEAR_CHECK, PINGPONG_3,
362 SDE_INTR_PING_PONG_3_TEAR_DETECTED, 1},
363 /* irq_idx: 52-55 */
364 { SDE_IRQ_TYPE_RESERVED, 0, 0, 1},
365 { SDE_IRQ_TYPE_RESERVED, 0, 0, 1},
366 { SDE_IRQ_TYPE_PING_PONG_TEAR_CHECK, PINGPONG_S0,
367 SDE_INTR_PING_PONG_S0_TEAR_DETECTED, 1},
368 { SDE_IRQ_TYPE_RESERVED, 0, 0, 1},
369 /* irq_idx: 56-59 */
370 { SDE_IRQ_TYPE_PING_PONG_TE_CHECK, PINGPONG_0,
371 SDE_INTR_PING_PONG_0_TE_DETECTED, 1},
372 { SDE_IRQ_TYPE_PING_PONG_TE_CHECK, PINGPONG_1,
373 SDE_INTR_PING_PONG_1_TE_DETECTED, 1},
374 { SDE_IRQ_TYPE_PING_PONG_TE_CHECK, PINGPONG_2,
375 SDE_INTR_PING_PONG_2_TE_DETECTED, 1},
376 { SDE_IRQ_TYPE_PING_PONG_TE_CHECK, PINGPONG_3,
377 SDE_INTR_PING_PONG_3_TE_DETECTED, 1},
378 /* irq_idx: 60-63 */
379 { SDE_IRQ_TYPE_PING_PONG_TE_CHECK, PINGPONG_S0,
380 SDE_INTR_PING_PONG_S0_TE_DETECTED, 1},
381 { SDE_IRQ_TYPE_RESERVED, 0, 0, 1},
382 { SDE_IRQ_TYPE_RESERVED, 0, 0, 1},
383 { SDE_IRQ_TYPE_RESERVED, 0, 0, 1},
384
385 /* BEGIN MAP_RANGE: 64-95 HIST */
386 /* irq_idx: 64-67 */
387 { SDE_IRQ_TYPE_HIST_VIG_DONE, SSPP_VIG0, SDE_INTR_HIST_VIG_0_DONE, 2},
388 { SDE_IRQ_TYPE_HIST_VIG_RSTSEQ, SSPP_VIG0,
389 SDE_INTR_HIST_VIG_0_RSTSEQ_DONE, 2},
390 { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
391 { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
392 /* irq_idx: 68-71 */
393 { SDE_IRQ_TYPE_HIST_VIG_DONE, SSPP_VIG1, SDE_INTR_HIST_VIG_1_DONE, 2},
394 { SDE_IRQ_TYPE_HIST_VIG_RSTSEQ, SSPP_VIG1,
395 SDE_INTR_HIST_VIG_1_RSTSEQ_DONE, 2},
396 { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
397 { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
398 /* irq_idx: 68-71 */
399 { SDE_IRQ_TYPE_HIST_VIG_DONE, SSPP_VIG2, SDE_INTR_HIST_VIG_2_DONE, 2},
400 { SDE_IRQ_TYPE_HIST_VIG_RSTSEQ, SSPP_VIG2,
401 SDE_INTR_HIST_VIG_2_RSTSEQ_DONE, 2},
402 { SDE_IRQ_TYPE_HIST_VIG_DONE, SSPP_VIG3, SDE_INTR_HIST_VIG_3_DONE, 2},
403 { SDE_IRQ_TYPE_HIST_VIG_RSTSEQ, SSPP_VIG3,
404 SDE_INTR_HIST_VIG_3_RSTSEQ_DONE, 2},
405 /* irq_idx: 72-75 */
406 { SDE_IRQ_TYPE_HIST_DSPP_DONE, DSPP_0, SDE_INTR_HIST_DSPP_0_DONE, 2},
407 { SDE_IRQ_TYPE_HIST_DSPP_RSTSEQ, DSPP_0,
408 SDE_INTR_HIST_DSPP_0_RSTSEQ_DONE, 2},
409 { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
410 { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
411 /* irq_idx: 76-79 */
412 { SDE_IRQ_TYPE_HIST_DSPP_DONE, DSPP_1, SDE_INTR_HIST_DSPP_1_DONE, 2},
413 { SDE_IRQ_TYPE_HIST_DSPP_RSTSEQ, DSPP_1,
414 SDE_INTR_HIST_DSPP_1_RSTSEQ_DONE, 2},
415 { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
416 { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
417 /* irq_idx: 80-83 */
418 { SDE_IRQ_TYPE_HIST_DSPP_DONE, DSPP_2, SDE_INTR_HIST_DSPP_2_DONE, 2},
419 { SDE_IRQ_TYPE_HIST_DSPP_RSTSEQ, DSPP_2,
420 SDE_INTR_HIST_DSPP_2_RSTSEQ_DONE, 2},
421 { SDE_IRQ_TYPE_HIST_DSPP_DONE, DSPP_3, SDE_INTR_HIST_DSPP_3_DONE, 2},
422 { SDE_IRQ_TYPE_HIST_DSPP_RSTSEQ, DSPP_3,
423 SDE_INTR_HIST_DSPP_3_RSTSEQ_DONE, 2},
424 /* irq_idx: 84-87 */
425 { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
426 { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
427 { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
428 { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
429 /* irq_idx: 88-91 */
430 { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
431 { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
432 { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
433 { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
434 /* irq_idx: 92-95 */
435 { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
436 { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
437 { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
438 { SDE_IRQ_TYPE_RESERVED, 0, 0, 2},
439
440 /* BEGIN MAP_RANGE: 96-127 INTF_0_INTR */
441 /* irq_idx: 96-99 */
442 { SDE_IRQ_TYPE_SFI_VIDEO_IN, INTF_0,
443 SDE_INTR_VIDEO_INTO_STATIC, 3},
444 { SDE_IRQ_TYPE_SFI_VIDEO_OUT, INTF_0,
445 SDE_INTR_VIDEO_OUTOF_STATIC, 3},
446 { SDE_IRQ_TYPE_SFI_CMD_0_IN, INTF_0,
447 SDE_INTR_DSICMD_0_INTO_STATIC, 3},
448 { SDE_IRQ_TYPE_SFI_CMD_0_OUT, INTF_0,
449 SDE_INTR_DSICMD_0_OUTOF_STATIC, 3},
450 /* irq_idx: 100-103 */
451 { SDE_IRQ_TYPE_SFI_CMD_1_IN, INTF_0,
452 SDE_INTR_DSICMD_1_INTO_STATIC, 3},
453 { SDE_IRQ_TYPE_SFI_CMD_1_OUT, INTF_0,
454 SDE_INTR_DSICMD_1_OUTOF_STATIC, 3},
455 { SDE_IRQ_TYPE_SFI_CMD_2_IN, INTF_0,
456 SDE_INTR_DSICMD_2_INTO_STATIC, 3},
457 { SDE_IRQ_TYPE_SFI_CMD_2_OUT, INTF_0,
458 SDE_INTR_DSICMD_2_OUTOF_STATIC, 3},
459 /* irq_idx: 104-107 */
460 { SDE_IRQ_TYPE_PROG_LINE, INTF_0, SDE_INTR_PROG_LINE, 3},
461 { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
462 { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
463 { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
464 /* irq_idx: 108-111 */
465 { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
466 { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
467 { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
468 { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
469 /* irq_idx: 112-115 */
470 { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
471 { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
472 { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
473 { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
474 /* irq_idx: 116-119 */
475 { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
476 { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
477 { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
478 { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
479 /* irq_idx: 120-123 */
480 { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
481 { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
482 { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
483 { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
484 /* irq_idx: 124-127 */
485 { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
486 { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
487 { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
488 { SDE_IRQ_TYPE_RESERVED, 0, 0, 3},
489
490 /* BEGIN MAP_RANGE: 128-159 INTF_1_INTR */
491 /* irq_idx: 128-131 */
492 { SDE_IRQ_TYPE_SFI_VIDEO_IN, INTF_1,
493 SDE_INTR_VIDEO_INTO_STATIC, 4},
494 { SDE_IRQ_TYPE_SFI_VIDEO_OUT, INTF_1,
495 SDE_INTR_VIDEO_OUTOF_STATIC, 4},
496 { SDE_IRQ_TYPE_SFI_CMD_0_IN, INTF_1,
497 SDE_INTR_DSICMD_0_INTO_STATIC, 4},
498 { SDE_IRQ_TYPE_SFI_CMD_0_OUT, INTF_1,
499 SDE_INTR_DSICMD_0_OUTOF_STATIC, 4},
500 /* irq_idx: 132-135 */
501 { SDE_IRQ_TYPE_SFI_CMD_1_IN, INTF_1,
502 SDE_INTR_DSICMD_1_INTO_STATIC, 4},
503 { SDE_IRQ_TYPE_SFI_CMD_1_OUT, INTF_1,
504 SDE_INTR_DSICMD_1_OUTOF_STATIC, 4},
505 { SDE_IRQ_TYPE_SFI_CMD_2_IN, INTF_1,
506 SDE_INTR_DSICMD_2_INTO_STATIC, 4},
507 { SDE_IRQ_TYPE_SFI_CMD_2_OUT, INTF_1,
508 SDE_INTR_DSICMD_2_OUTOF_STATIC, 4},
509 /* irq_idx: 136-139 */
510 { SDE_IRQ_TYPE_PROG_LINE, INTF_1, SDE_INTR_PROG_LINE, 4},
511 { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
512 { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
513 { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
514 /* irq_idx: 140-143 */
515 { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
516 { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
517 { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
518 { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
519 /* irq_idx: 144-147 */
520 { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
521 { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
522 { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
523 { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
524 /* irq_idx: 148-151 */
525 { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
526 { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
527 { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
528 { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
529 /* irq_idx: 152-155 */
530 { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
531 { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
532 { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
533 { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
534 /* irq_idx: 156-159 */
535 { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
536 { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
537 { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
538 { SDE_IRQ_TYPE_RESERVED, 0, 0, 4},
539
540 /* BEGIN MAP_RANGE: 160-191 INTF_2_INTR */
541 /* irq_idx: 160-163 */
542 { SDE_IRQ_TYPE_SFI_VIDEO_IN, INTF_2,
543 SDE_INTR_VIDEO_INTO_STATIC, 5},
544 { SDE_IRQ_TYPE_SFI_VIDEO_OUT, INTF_2,
545 SDE_INTR_VIDEO_OUTOF_STATIC, 5},
546 { SDE_IRQ_TYPE_SFI_CMD_0_IN, INTF_2,
547 SDE_INTR_DSICMD_0_INTO_STATIC, 5},
548 { SDE_IRQ_TYPE_SFI_CMD_0_OUT, INTF_2,
549 SDE_INTR_DSICMD_0_OUTOF_STATIC, 5},
550 /* irq_idx: 164-167 */
551 { SDE_IRQ_TYPE_SFI_CMD_1_IN, INTF_2,
552 SDE_INTR_DSICMD_1_INTO_STATIC, 5},
553 { SDE_IRQ_TYPE_SFI_CMD_1_OUT, INTF_2,
554 SDE_INTR_DSICMD_1_OUTOF_STATIC, 5},
555 { SDE_IRQ_TYPE_SFI_CMD_2_IN, INTF_2,
556 SDE_INTR_DSICMD_2_INTO_STATIC, 5},
557 { SDE_IRQ_TYPE_SFI_CMD_2_OUT, INTF_2,
558 SDE_INTR_DSICMD_2_OUTOF_STATIC, 5},
559 /* irq_idx: 168-171 */
560 { SDE_IRQ_TYPE_PROG_LINE, INTF_2, SDE_INTR_PROG_LINE, 5},
561 { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
562 { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
563 { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
564 /* irq_idx: 172-175 */
565 { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
566 { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
567 { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
568 { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
569 /* irq_idx: 176-179 */
570 { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
571 { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
572 { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
573 { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
574 /* irq_idx: 180-183 */
575 { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
576 { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
577 { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
578 { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
579 /* irq_idx: 184-187 */
580 { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
581 { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
582 { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
583 { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
584 /* irq_idx: 188-191 */
585 { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
586 { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
587 { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
588 { SDE_IRQ_TYPE_RESERVED, 0, 0, 5},
589
590 /* BEGIN MAP_RANGE: 192-223 INTF_3_INTR */
591 /* irq_idx: 192-195 */
592 { SDE_IRQ_TYPE_SFI_VIDEO_IN, INTF_3,
593 SDE_INTR_VIDEO_INTO_STATIC, 6},
594 { SDE_IRQ_TYPE_SFI_VIDEO_OUT, INTF_3,
595 SDE_INTR_VIDEO_OUTOF_STATIC, 6},
596 { SDE_IRQ_TYPE_SFI_CMD_0_IN, INTF_3,
597 SDE_INTR_DSICMD_0_INTO_STATIC, 6},
598 { SDE_IRQ_TYPE_SFI_CMD_0_OUT, INTF_3,
599 SDE_INTR_DSICMD_0_OUTOF_STATIC, 6},
600 /* irq_idx: 196-199 */
601 { SDE_IRQ_TYPE_SFI_CMD_1_IN, INTF_3,
602 SDE_INTR_DSICMD_1_INTO_STATIC, 6},
603 { SDE_IRQ_TYPE_SFI_CMD_1_OUT, INTF_3,
604 SDE_INTR_DSICMD_1_OUTOF_STATIC, 6},
605 { SDE_IRQ_TYPE_SFI_CMD_2_IN, INTF_3,
606 SDE_INTR_DSICMD_2_INTO_STATIC, 6},
607 { SDE_IRQ_TYPE_SFI_CMD_2_OUT, INTF_3,
608 SDE_INTR_DSICMD_2_OUTOF_STATIC, 6},
609 /* irq_idx: 200-203 */
610 { SDE_IRQ_TYPE_PROG_LINE, INTF_3, SDE_INTR_PROG_LINE, 6},
611 { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
612 { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
613 { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
614 /* irq_idx: 204-207 */
615 { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
616 { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
617 { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
618 { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
619 /* irq_idx: 208-211 */
620 { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
621 { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
622 { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
623 { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
624 /* irq_idx: 212-215 */
625 { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
626 { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
627 { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
628 { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
629 /* irq_idx: 216-219 */
630 { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
631 { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
632 { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
633 { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
634 /* irq_idx: 220-223 */
635 { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
636 { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
637 { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
638 { SDE_IRQ_TYPE_RESERVED, 0, 0, 6},
639
640 /* BEGIN MAP_RANGE: 224-255 INTF_4_INTR */
641 /* irq_idx: 224-227 */
642 { SDE_IRQ_TYPE_SFI_VIDEO_IN, INTF_4,
643 SDE_INTR_VIDEO_INTO_STATIC, 7},
644 { SDE_IRQ_TYPE_SFI_VIDEO_OUT, INTF_4,
645 SDE_INTR_VIDEO_OUTOF_STATIC, 7},
646 { SDE_IRQ_TYPE_SFI_CMD_0_IN, INTF_4,
647 SDE_INTR_DSICMD_0_INTO_STATIC, 7},
648 { SDE_IRQ_TYPE_SFI_CMD_0_OUT, INTF_4,
649 SDE_INTR_DSICMD_0_OUTOF_STATIC, 7},
650 /* irq_idx: 228-231 */
651 { SDE_IRQ_TYPE_SFI_CMD_1_IN, INTF_4,
652 SDE_INTR_DSICMD_1_INTO_STATIC, 7},
653 { SDE_IRQ_TYPE_SFI_CMD_1_OUT, INTF_4,
654 SDE_INTR_DSICMD_1_OUTOF_STATIC, 7},
655 { SDE_IRQ_TYPE_SFI_CMD_2_IN, INTF_4,
656 SDE_INTR_DSICMD_2_INTO_STATIC, 7},
657 { SDE_IRQ_TYPE_SFI_CMD_2_OUT, INTF_4,
658 SDE_INTR_DSICMD_2_OUTOF_STATIC, 7},
659 /* irq_idx: 232-235 */
660 { SDE_IRQ_TYPE_PROG_LINE, INTF_4, SDE_INTR_PROG_LINE, 7},
661 { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
662 { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
663 { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
664 /* irq_idx: 236-239 */
665 { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
666 { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
667 { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
668 { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
669 /* irq_idx: 240-243 */
670 { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
671 { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
672 { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
673 { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
674 /* irq_idx: 244-247 */
675 { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
676 { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
677 { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
678 { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
679 /* irq_idx: 248-251 */
680 { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
681 { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
682 { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
683 { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
684 /* irq_idx: 252-255 */
685 { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
686 { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
687 { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
688 { SDE_IRQ_TYPE_RESERVED, 0, 0, 7},
Gopikrishnaiah Anandan5154c712017-02-27 17:48:24 -0800689
690 /* irq_idx: 256-257 */
691 { SDE_IRQ_TYPE_AD4_BL_DONE, DSPP_0, SDE_INTR_BACKLIGHT_UPDATED, 8},
692 { SDE_IRQ_TYPE_AD4_BL_DONE, DSPP_1, SDE_INTR_BACKLIGHT_UPDATED, 9}
Ben Chan78647cd2016-06-26 22:02:47 -0400693};
694
695static int sde_hw_intr_irqidx_lookup(enum sde_intr_type intr_type,
696 u32 instance_idx)
697{
698 int i;
699
700 for (i = 0; i < ARRAY_SIZE(sde_irq_map); i++) {
701 if (intr_type == sde_irq_map[i].intr_type &&
702 instance_idx == sde_irq_map[i].instance_idx)
703 return i;
704 }
705
706 pr_debug("IRQ lookup fail!! intr_type=%d, instance_idx=%d\n",
707 intr_type, instance_idx);
708 return -EINVAL;
709}
710
711static void sde_hw_intr_set_mask(struct sde_hw_intr *intr, uint32_t reg_off,
712 uint32_t mask)
713{
Lloyd Atkinson3693f9a2017-04-18 12:34:31 -0700714 if (!intr)
715 return;
716
Ben Chan78647cd2016-06-26 22:02:47 -0400717 SDE_REG_WRITE(&intr->hw, reg_off, mask);
718}
719
720static void sde_hw_intr_dispatch_irq(struct sde_hw_intr *intr,
721 void (*cbfunc)(void *, int),
722 void *arg)
723{
724 int reg_idx;
725 int irq_idx;
726 int start_idx;
727 int end_idx;
728 u32 irq_status;
729 unsigned long irq_flags;
730
Lloyd Atkinson3693f9a2017-04-18 12:34:31 -0700731 if (!intr)
732 return;
733
Ben Chan78647cd2016-06-26 22:02:47 -0400734 /*
735 * The dispatcher will save the IRQ status before calling here.
736 * Now need to go through each IRQ status and find matching
737 * irq lookup index.
738 */
739 spin_lock_irqsave(&intr->status_lock, irq_flags);
740 for (reg_idx = 0; reg_idx < ARRAY_SIZE(sde_intr_set); reg_idx++) {
741 irq_status = intr->save_irq_status[reg_idx];
742
743 /*
744 * Each Interrupt register has a range of 32 indexes, and
745 * that is static for sde_irq_map.
746 */
747 start_idx = reg_idx * 32;
748 end_idx = start_idx + 32;
749
Lloyd Atkinson3693f9a2017-04-18 12:34:31 -0700750 if (start_idx >= ARRAY_SIZE(sde_irq_map) ||
751 end_idx > ARRAY_SIZE(sde_irq_map))
752 continue;
753
Ben Chan78647cd2016-06-26 22:02:47 -0400754 /*
755 * Search through matching intr status from irq map.
756 * start_idx and end_idx defined the search range in
757 * the sde_irq_map.
758 */
759 for (irq_idx = start_idx;
760 (irq_idx < end_idx) && irq_status;
761 irq_idx++)
762 if ((irq_status & sde_irq_map[irq_idx].irq_mask) &&
763 (sde_irq_map[irq_idx].reg_idx == reg_idx)) {
764 /*
765 * Once a match on irq mask, perform a callback
766 * to the given cbfunc. cbfunc will take care
767 * the interrupt status clearing. If cbfunc is
768 * not provided, then the interrupt clearing
769 * is here.
770 */
771 if (cbfunc)
772 cbfunc(arg, irq_idx);
773 else
774 intr->ops.clear_interrupt_status(
775 intr, irq_idx);
776
777 /*
778 * When callback finish, clear the irq_status
779 * with the matching mask. Once irq_status
780 * is all cleared, the search can be stopped.
781 */
782 irq_status &= ~sde_irq_map[irq_idx].irq_mask;
783 }
784 }
785 spin_unlock_irqrestore(&intr->status_lock, irq_flags);
786}
787
788static int sde_hw_intr_enable_irq(struct sde_hw_intr *intr, int irq_idx)
789{
790 int reg_idx;
791 unsigned long irq_flags;
792 const struct sde_intr_reg *reg;
793 const struct sde_irq_type *irq;
794 const char *dbgstr = NULL;
795 uint32_t cache_irq_mask;
796
Lloyd Atkinson3693f9a2017-04-18 12:34:31 -0700797 if (!intr)
798 return -EINVAL;
799
Ben Chan78647cd2016-06-26 22:02:47 -0400800 if (irq_idx < 0 || irq_idx >= ARRAY_SIZE(sde_irq_map)) {
801 pr_err("invalid IRQ index: [%d]\n", irq_idx);
802 return -EINVAL;
803 }
804
805 irq = &sde_irq_map[irq_idx];
806 reg_idx = irq->reg_idx;
807 reg = &sde_intr_set[reg_idx];
808
809 spin_lock_irqsave(&intr->mask_lock, irq_flags);
810 cache_irq_mask = intr->cache_irq_mask[reg_idx];
811 if (cache_irq_mask & irq->irq_mask) {
812 dbgstr = "SDE IRQ already set:";
813 } else {
814 dbgstr = "SDE IRQ enabled:";
815
816 cache_irq_mask |= irq->irq_mask;
817 /* Cleaning any pending interrupt */
818 SDE_REG_WRITE(&intr->hw, reg->clr_off, irq->irq_mask);
819 /* Enabling interrupts with the new mask */
820 SDE_REG_WRITE(&intr->hw, reg->en_off, cache_irq_mask);
821
822 intr->cache_irq_mask[reg_idx] = cache_irq_mask;
823 }
824 spin_unlock_irqrestore(&intr->mask_lock, irq_flags);
825
826 pr_debug("%s MASK:0x%.8x, CACHE-MASK:0x%.8x\n", dbgstr,
827 irq->irq_mask, cache_irq_mask);
828
829 return 0;
830}
831
832static int sde_hw_intr_disable_irq(struct sde_hw_intr *intr, int irq_idx)
833{
834 int reg_idx;
835 unsigned long irq_flags;
836 const struct sde_intr_reg *reg;
837 const struct sde_irq_type *irq;
838 const char *dbgstr = NULL;
839 uint32_t cache_irq_mask;
840
Lloyd Atkinson3693f9a2017-04-18 12:34:31 -0700841 if (!intr)
842 return -EINVAL;
843
Ben Chan78647cd2016-06-26 22:02:47 -0400844 if (irq_idx < 0 || irq_idx >= ARRAY_SIZE(sde_irq_map)) {
845 pr_err("invalid IRQ index: [%d]\n", irq_idx);
846 return -EINVAL;
847 }
848
849 irq = &sde_irq_map[irq_idx];
850 reg_idx = irq->reg_idx;
851 reg = &sde_intr_set[reg_idx];
852
853 spin_lock_irqsave(&intr->mask_lock, irq_flags);
854 cache_irq_mask = intr->cache_irq_mask[reg_idx];
855 if ((cache_irq_mask & irq->irq_mask) == 0) {
856 dbgstr = "SDE IRQ is already cleared:";
857 } else {
858 dbgstr = "SDE IRQ mask disable:";
859
860 cache_irq_mask &= ~irq->irq_mask;
861 /* Disable interrupts based on the new mask */
862 SDE_REG_WRITE(&intr->hw, reg->en_off, cache_irq_mask);
863 /* Cleaning any pending interrupt */
864 SDE_REG_WRITE(&intr->hw, reg->clr_off, irq->irq_mask);
865
866 intr->cache_irq_mask[reg_idx] = cache_irq_mask;
867 }
868 spin_unlock_irqrestore(&intr->mask_lock, irq_flags);
869
870 pr_debug("%s MASK:0x%.8x, CACHE-MASK:0x%.8x\n", dbgstr,
871 irq->irq_mask, cache_irq_mask);
872
873 return 0;
874}
875
876static int sde_hw_intr_clear_irqs(struct sde_hw_intr *intr)
877{
Dhaval Patel88739332017-04-11 11:08:04 -0700878 int i;
879
Lloyd Atkinson3693f9a2017-04-18 12:34:31 -0700880 if (!intr)
881 return -EINVAL;
882
Dhaval Patel88739332017-04-11 11:08:04 -0700883 for (i = 0; i < ARRAY_SIZE(sde_intr_set); i++)
884 SDE_REG_WRITE(&intr->hw, sde_intr_set[i].clr_off, 0xffffffff);
885
Ben Chan78647cd2016-06-26 22:02:47 -0400886 return 0;
887}
888
889static int sde_hw_intr_disable_irqs(struct sde_hw_intr *intr)
890{
Dhaval Patel88739332017-04-11 11:08:04 -0700891 int i;
892
Lloyd Atkinson3693f9a2017-04-18 12:34:31 -0700893 if (!intr)
894 return -EINVAL;
895
Dhaval Patel88739332017-04-11 11:08:04 -0700896 for (i = 0; i < ARRAY_SIZE(sde_intr_set); i++)
897 SDE_REG_WRITE(&intr->hw, sde_intr_set[i].en_off, 0x00000000);
898
Ben Chan78647cd2016-06-26 22:02:47 -0400899 return 0;
900}
901
902static int sde_hw_intr_get_valid_interrupts(struct sde_hw_intr *intr,
903 uint32_t *mask)
904{
Lloyd Atkinson3693f9a2017-04-18 12:34:31 -0700905 if (!intr || !mask)
906 return -EINVAL;
907
Ben Chan78647cd2016-06-26 22:02:47 -0400908 *mask = IRQ_SOURCE_MDP | IRQ_SOURCE_DSI0 | IRQ_SOURCE_DSI1
909 | IRQ_SOURCE_HDMI | IRQ_SOURCE_EDP;
Lloyd Atkinson3693f9a2017-04-18 12:34:31 -0700910
Ben Chan78647cd2016-06-26 22:02:47 -0400911 return 0;
912}
913
914static int sde_hw_intr_get_interrupt_sources(struct sde_hw_intr *intr,
915 uint32_t *sources)
916{
Lloyd Atkinson3693f9a2017-04-18 12:34:31 -0700917 if (!intr || !sources)
918 return -EINVAL;
919
Ben Chan78647cd2016-06-26 22:02:47 -0400920 *sources = SDE_REG_READ(&intr->hw, HW_INTR_STATUS);
Lloyd Atkinson3693f9a2017-04-18 12:34:31 -0700921
Ben Chan78647cd2016-06-26 22:02:47 -0400922 return 0;
923}
924
925static void sde_hw_intr_get_interrupt_statuses(struct sde_hw_intr *intr)
926{
927 int i;
928 u32 enable_mask;
929 unsigned long irq_flags;
930
Lloyd Atkinson3693f9a2017-04-18 12:34:31 -0700931 if (!intr)
932 return;
933
Ben Chan78647cd2016-06-26 22:02:47 -0400934 spin_lock_irqsave(&intr->status_lock, irq_flags);
935 for (i = 0; i < ARRAY_SIZE(sde_intr_set); i++) {
936 /* Read interrupt status */
937 intr->save_irq_status[i] = SDE_REG_READ(&intr->hw,
938 sde_intr_set[i].status_off);
939
940 /* Read enable mask */
941 enable_mask = SDE_REG_READ(&intr->hw, sde_intr_set[i].en_off);
942
943 /* and clear the interrupt */
944 if (intr->save_irq_status[i])
945 SDE_REG_WRITE(&intr->hw, sde_intr_set[i].clr_off,
946 intr->save_irq_status[i]);
947
948 /* Finally update IRQ status based on enable mask */
949 intr->save_irq_status[i] &= enable_mask;
950 }
951 spin_unlock_irqrestore(&intr->status_lock, irq_flags);
952}
953
954static void sde_hw_intr_clear_interrupt_status(struct sde_hw_intr *intr,
955 int irq_idx)
956{
957 int reg_idx;
958 unsigned long irq_flags;
959
Lloyd Atkinson3693f9a2017-04-18 12:34:31 -0700960 if (!intr)
961 return;
962
Ben Chan78647cd2016-06-26 22:02:47 -0400963 spin_lock_irqsave(&intr->mask_lock, irq_flags);
964
965 reg_idx = sde_irq_map[irq_idx].reg_idx;
966 SDE_REG_WRITE(&intr->hw, sde_intr_set[reg_idx].clr_off,
967 sde_irq_map[irq_idx].irq_mask);
968
969 spin_unlock_irqrestore(&intr->mask_lock, irq_flags);
970}
971
Alan Kwong2fad18c2016-07-29 02:10:37 -0400972static u32 sde_hw_intr_get_interrupt_status(struct sde_hw_intr *intr,
973 int irq_idx, bool clear)
974{
975 int reg_idx;
976 unsigned long irq_flags;
977 u32 intr_status;
978
Lloyd Atkinson3693f9a2017-04-18 12:34:31 -0700979 if (!intr)
980 return 0;
981
Alan Kwong2fad18c2016-07-29 02:10:37 -0400982 spin_lock_irqsave(&intr->mask_lock, irq_flags);
983
984 reg_idx = sde_irq_map[irq_idx].reg_idx;
985 intr_status = SDE_REG_READ(&intr->hw,
986 sde_intr_set[reg_idx].status_off) &
987 sde_irq_map[irq_idx].irq_mask;
988 if (intr_status && clear)
989 SDE_REG_WRITE(&intr->hw, sde_intr_set[irq_idx].clr_off,
990 intr_status);
991
992 spin_unlock_irqrestore(&intr->mask_lock, irq_flags);
993
994 return intr_status;
995}
Ben Chan78647cd2016-06-26 22:02:47 -0400996
997static void __setup_intr_ops(struct sde_hw_intr_ops *ops)
998{
999 ops->set_mask = sde_hw_intr_set_mask;
1000 ops->irq_idx_lookup = sde_hw_intr_irqidx_lookup;
1001 ops->enable_irq = sde_hw_intr_enable_irq;
1002 ops->disable_irq = sde_hw_intr_disable_irq;
1003 ops->dispatch_irqs = sde_hw_intr_dispatch_irq;
1004 ops->clear_all_irqs = sde_hw_intr_clear_irqs;
1005 ops->disable_all_irqs = sde_hw_intr_disable_irqs;
1006 ops->get_valid_interrupts = sde_hw_intr_get_valid_interrupts;
1007 ops->get_interrupt_sources = sde_hw_intr_get_interrupt_sources;
1008 ops->get_interrupt_statuses = sde_hw_intr_get_interrupt_statuses;
1009 ops->clear_interrupt_status = sde_hw_intr_clear_interrupt_status;
Alan Kwong2fad18c2016-07-29 02:10:37 -04001010 ops->get_interrupt_status = sde_hw_intr_get_interrupt_status;
Ben Chan78647cd2016-06-26 22:02:47 -04001011}
1012
1013static struct sde_mdss_base_cfg *__intr_offset(struct sde_mdss_cfg *m,
1014 void __iomem *addr, struct sde_hw_blk_reg_map *hw)
1015{
Lloyd Atkinson3693f9a2017-04-18 12:34:31 -07001016 if (!m || !addr || !hw || m->mdp_count == 0)
Ben Chan78647cd2016-06-26 22:02:47 -04001017 return NULL;
1018
1019 hw->base_off = addr;
1020 hw->blk_off = m->mdss[0].base;
1021 hw->hwversion = m->hwversion;
1022 return &m->mdss[0];
1023}
1024
1025struct sde_hw_intr *sde_hw_intr_init(void __iomem *addr,
1026 struct sde_mdss_cfg *m)
1027{
Lloyd Atkinson3693f9a2017-04-18 12:34:31 -07001028 struct sde_hw_intr *intr;
Ben Chan78647cd2016-06-26 22:02:47 -04001029 struct sde_mdss_base_cfg *cfg;
1030
Lloyd Atkinson3693f9a2017-04-18 12:34:31 -07001031 if (!addr || !m)
1032 return ERR_PTR(-EINVAL);
1033
1034 intr = kzalloc(sizeof(*intr), GFP_KERNEL);
Ben Chan78647cd2016-06-26 22:02:47 -04001035 if (!intr)
1036 return ERR_PTR(-ENOMEM);
1037
1038 cfg = __intr_offset(m, addr, &intr->hw);
1039 if (!cfg) {
1040 kfree(intr);
1041 return ERR_PTR(-EINVAL);
1042 }
1043 __setup_intr_ops(&intr->ops);
1044
1045 intr->irq_idx_tbl_size = ARRAY_SIZE(sde_irq_map);
1046
1047 intr->cache_irq_mask = kcalloc(ARRAY_SIZE(sde_intr_set), sizeof(u32),
1048 GFP_KERNEL);
1049 if (intr->cache_irq_mask == NULL) {
1050 kfree(intr);
1051 return ERR_PTR(-ENOMEM);
1052 }
1053
1054 intr->save_irq_status = kcalloc(ARRAY_SIZE(sde_intr_set), sizeof(u32),
1055 GFP_KERNEL);
1056 if (intr->save_irq_status == NULL) {
1057 kfree(intr->cache_irq_mask);
1058 kfree(intr);
1059 return ERR_PTR(-ENOMEM);
1060 }
1061
1062 spin_lock_init(&intr->mask_lock);
1063 spin_lock_init(&intr->status_lock);
1064
1065 return intr;
1066}
1067
1068void sde_hw_intr_destroy(struct sde_hw_intr *intr)
1069{
1070 if (intr) {
1071 kfree(intr->cache_irq_mask);
1072 kfree(intr->save_irq_status);
1073 kfree(intr);
1074 }
1075}
1076