2 * Copyright (c) 2017 Samsung Electronics Co., Ltd.
3 * http://www.samsung.com
5 * IPs Traffic Monitor(ITMON) Driver for Samsung Exynos9610 SOC
6 * By Hosung Kim (hosung0.kim@samsung.com)
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
13 #include <linux/module.h>
14 #include <linux/platform_device.h>
15 #include <linux/slab.h>
17 #include <linux/interrupt.h>
18 #include <linux/of_irq.h>
19 #include <linux/bitops.h>
20 #include <soc/samsung/exynos-pmu.h>
21 #include <soc/samsung/exynos-itmon.h>
22 #if defined(CONFIG_SEC_MODEM_IF)
23 #include <soc/samsung/exynos-modem-ctrl.h>
27 #define OFFSET_TMOUT_REG (0x2000)
28 #define OFFSET_REQ_R (0x0)
29 #define OFFSET_REQ_W (0x20)
30 #define OFFSET_RESP_R (0x40)
31 #define OFFSET_RESP_W (0x60)
32 #define OFFSET_ERR_REPT (0x20)
33 #define OFFSET_HW_ASSERT (0x100)
34 #define OFFSET_NUM (0x4)
36 #define REG_INT_MASK (0x0)
37 #define REG_INT_CLR (0x4)
38 #define REG_INT_INFO (0x8)
39 #define REG_EXT_INFO_0 (0x10)
40 #define REG_EXT_INFO_1 (0x14)
41 #define REG_EXT_INFO_2 (0x18)
43 #define REG_DBG_CTL (0x10)
44 #define REG_TMOUT_INIT_VAL (0x14)
45 #define REG_TMOUT_FRZ_EN (0x18)
46 #define REG_TMOUT_BUF_WR_OFFSET (0x20)
48 #define REG_TMOUT_BUF_STATUS (0x1C)
49 #define REG_TMOUT_BUF_POINT_ADDR (0x20)
50 #define REG_TMOUT_BUF_ID (0x24)
51 #define REG_TMOUT_BUF_PAYLOAD (0x28)
52 #define REG_TMOUT_BUF_PAYLOAD_SRAM1 (0x30)
53 #define REG_TMOUT_BUF_PAYLOAD_SRAM2 (0x34)
54 #define REG_TMOUT_BUF_PAYLOAD_SRAM3 (0x38)
56 #define REG_HWA_CTL (0x4)
57 #define REG_HWA_INT (0x8)
58 #define REG_HWA_INT_ID (0xC)
59 #define REG_HWA_START_ADDR_LOW (0x10)
60 #define REG_HWA_END_ADDR_LOW (0x14)
61 #define REG_HWA_START_END_ADDR_UPPER (0x18)
63 #define RD_RESP_INT_ENABLE (1 << 0)
64 #define WR_RESP_INT_ENABLE (1 << 1)
65 #define ARLEN_RLAST_INT_ENABLE (1 << 2)
66 #define AWLEN_WLAST_INT_ENABLE (1 << 3)
67 #define INTEND_ACCESS_INT_ENABLE (1 << 4)
69 #define BIT_HWA_ERR_OCCURRED(x) (((x) & (0x1 << 0)) >> 0)
70 #define BIT_HWA_ERR_CODE(x) (((x) & (0xF << 1)) >> 28)
72 #define BIT_ERR_CODE(x) (((x) & (0xF << 28)) >> 28)
73 #define BIT_ERR_OCCURRED(x) (((x) & (0x1 << 27)) >> 27)
74 #define BIT_ERR_VALID(x) (((x) & (0x1 << 26)) >> 26)
75 #define BIT_AXID(x) (((x) & (0xFFFF)))
76 #define BIT_AXUSER(x) (((x) & (0xFFFF << 16)) >> 16)
77 #define BIT_AXBURST(x) (((x) & (0x3)))
78 #define BIT_AXPROT(x) (((x) & (0x3 << 2)) >> 2)
79 #define BIT_AXLEN(x) (((x) & (0xF << 16)) >> 16)
80 #define BIT_AXSIZE(x) (((x) & (0x7 << 28)) >> 28)
88 #define ERRCODE_SLVERR (0)
89 #define ERRCODE_DECERR (1)
90 #define ERRCODE_UNSUPORTED (2)
91 #define ERRCODE_POWER_DOWN (3)
92 #define ERRCODE_UNKNOWN_4 (4)
93 #define ERRCODE_UNKNOWN_5 (5)
94 #define ERRCODE_TMOUT (6)
98 #define BUS_PATH_TYPE (2)
100 #define TRANS_TYPE_WRITE (0)
101 #define TRANS_TYPE_READ (1)
102 #define TRANS_TYPE_NUM (2)
104 #define FROM_PERI (0)
108 #define CP_COMMON_STR "CP_"
110 #define TMOUT (0xFFFFF)
111 #define TMOUT_TEST (0x1)
113 #define PANIC_ALLOWED_THRESHOLD (0x2)
114 #define INVALID_REMAPPING (0x08000000)
115 #define BAAW_RETURN (0x08000000)
117 static bool initial_multi_irq_enable
= false;
118 static struct itmon_dev
*g_itmon
= NULL
;
120 struct itmon_rpathinfo
{
125 unsigned int shift_bits
;
128 struct itmon_masterinfo
{
135 struct itmon_nodegroup
;
137 struct itmon_traceinfo
{
141 unsigned long target_addr
;
142 unsigned int errcode
;
151 struct itmon_tracedata
{
152 unsigned int int_info
;
153 unsigned int ext_info_0
;
154 unsigned int ext_info_1
;
155 unsigned int ext_info_2
;
156 unsigned int hwa_ctl
;
157 unsigned int hwa_info
;
158 unsigned int hwa_int_id
;
164 struct itmon_nodeinfo
{
167 unsigned int phy_regs
;
169 unsigned int time_val
;
171 bool tmout_frz_enabled
;
173 bool hw_assert_enabled
;
175 struct itmon_tracedata tracedata
;
176 struct itmon_nodegroup
*group
;
177 struct list_head list
;
180 static const char *itmon_pathtype
[] = {
181 "DATA Path transaction (0x2000_0000 ~ 0xf_ffff_ffff)",
182 "PERI(SFR) Path transaction (0x0 ~ 0x1fff_ffff)",
185 /* Error Code Description */
186 static const char *itmon_errcode
[] = {
187 "Error Detect by the Slave(SLVERR)",
188 "Decode error(DECERR)",
189 "Unsupported transaction error",
190 "Power Down access error",
191 "Unsupported transaction",
192 "Unsupported transaction",
193 "Timeout error - response timeout in timeout value",
197 static const char *itmon_nodestring
[] = {
204 struct itmon_nodegroup
{
207 unsigned int phy_regs
;
209 struct itmon_nodeinfo
*nodeinfo
;
210 unsigned int nodesize
;
211 unsigned int bus_type
;
214 struct itmon_platdata
{
215 const struct itmon_rpathinfo
*rpathinfo
;
216 const struct itmon_masterinfo
*masterinfo
;
217 struct itmon_nodegroup
*nodegroup
;
218 struct itmon_traceinfo traceinfo
[BUS_PATH_TYPE
];
219 struct list_head tracelist
[BUS_PATH_TYPE
];
220 unsigned int err_cnt
;
222 bool crash_in_progress
;
223 unsigned int sysfs_tmout_val
;
228 static struct itmon_rpathinfo rpathinfo
[] = {
230 {0, "MFC0", "S_CCI", GENMASK(3, 0), 0},
231 {1, "MFC1", "S_CCI", GENMASK(3, 0), 0},
232 {2, "VIPX2", "S_CCI", GENMASK(3, 0), 0},
233 {3, "DIT", "S_CCI", GENMASK(3, 0), 0},
234 {4, "G2D", "S_CCI", GENMASK(3, 0), 0},
235 {5, "FSYS", "S_CCI", GENMASK(3, 0), 0},
236 {6, "USB", "S_CCI", GENMASK(3, 0), 0},
237 {7, "ISP0", "S_CCI", GENMASK(3, 0), 0},
238 {8, "ISP1", "S_CCI", GENMASK(3, 0), 0},
239 {9, "CAM", "S_CCI", GENMASK(3, 0), 0},
240 {10, "DPU", "S_CCI", GENMASK(3, 0), 0},
241 {11, "VIPX1", "S_CCI", GENMASK(3, 0), 0},
243 {0, "CP_1", "S_NRT", GENMASK(3, 0), 0},
244 {1, "ISP0", "S_NRT", GENMASK(3, 0), 0},
245 {2, "ISP1", "S_NRT", GENMASK(3, 0), 0},
246 {3, "VIPX1", "S_NRT", GENMASK(3, 0), 0},
247 {4, "VIPX2", "S_NRT", GENMASK(3, 0), 0},
248 {5, "MFC0", "S_NRT", GENMASK(3, 0), 0},
249 {6, "MFC1", "S_NRT", GENMASK(3, 0), 0},
250 {7, "G2D", "S_NRT", GENMASK(3, 0), 0},
251 {8, "FSYS", "S_NRT", GENMASK(3, 0), 0},
252 {9, "USB", "S_NRT", GENMASK(3, 0), 0},
253 {10, "COREX", "S_NRT", GENMASK(3, 0), 0},
254 {11, "GNSS", "S_NRT", GENMASK(3, 0), 0},
255 {12, "WLBT", "S_NRT", GENMASK(3, 0), 0},
256 {13, "DIT", "S_NRT", GENMASK(3, 0), 0},
257 {14, "CSSYS", "S_NRT", GENMASK(3, 0), 0},
259 {0, "CAM", "RT_MEM", GENMASK(3, 0), 0},
260 {1, "DPU", "RT_MEM", GENMASK(3, 0), 0},
261 {2, "ABOX", "RT_MEM", GENMASK(3, 0), 0},
262 {3, "CP_1", "RT_MEM", GENMASK(3, 0), 0},
263 {4, "WLBT", "RT_MEM", GENMASK(3, 0), 0},
264 {5, "GNSS", "RT_MEM", GENMASK(3, 0), 0},
265 {6, "VIPX1", "RT_MEM", GENMASK(3, 0), 0},
266 {7, "VIPX2", "RT_MEM", GENMASK(3, 0), 0},
267 {8, "ISP0", "RT_MEM", GENMASK(3, 0), 0},
268 {9, "ISP1", "RT_MEM", GENMASK(3, 0), 0},
270 {0, "CP_0", "CP_MEM", GENMASK(3, 0), 0},
271 {1, "ABOX", "CP_MEM", GENMASK(3, 0), 0},
272 {2, "CP_1", "CP_MEM", GENMASK(3, 0), 0},
273 {3, "WLBT", "CP_MEM", GENMASK(3, 0), 0},
274 {4, "DIT", "CP_MEM", GENMASK(3, 0), 0},
277 {0, "G3D", "PERI", GENMASK(4, 0), 0},
278 {1, "MFC0", "PERI", GENMASK(4, 0), 0},
279 {2, "ISP1", "PERI", GENMASK(4, 0), 0},
280 {3, "CAM", "PERI", GENMASK(4, 0), 0},
281 {4, "DPU", "PERI", GENMASK(4, 0), 0},
282 {5, "ABOX", "PERI", GENMASK(4, 0), 0},
283 {6, "WLBT", "PERI", GENMASK(4, 0), 0},
284 {7, "CP_0", "PERI", GENMASK(4, 0), 0},
285 {8, "CP_1", "PERI", GENMASK(4, 0), 0},
286 {9, "VIPX1", "PERI", GENMASK(4, 0), 0},
287 {10, "VIPX2", "PERI", GENMASK(4, 0), 0},
288 {11, "DIT", "PERI", GENMASK(4, 0), 0},
289 {12, "MFC1", "PERI", GENMASK(4, 0), 0},
290 {13, "G2D", "PERI", GENMASK(4, 0), 0},
291 {14, "FSYS", "PERI", GENMASK(4, 0), 0},
292 {15, "USB", "PERI", GENMASK(4, 0), 0},
293 {16, "COREX", "PERI", GENMASK(4, 0), 0},
294 {17, "GNSS", "PERI", GENMASK(4, 0), 0},
295 {18, "CSSYS", "PERI", GENMASK(4, 0), 0},
296 {19, "ISP0", "PERI", GENMASK(4, 0), 0},
299 /* XIU ID Information */
300 static struct itmon_masterinfo masterinfo
[] = {
302 {"CAM", 0, "PAF-STAT", GENMASK(2, 1)},
303 {"CAM", BIT(1), "3AA", GENMASK(2, 1)},
306 {"DPU", 0, "IDMA0", 0},
307 {"ABOX", 0, "SPUS_SPUM", GENMASK(1, 1)},
308 {"ABOX", BIT(1), "ABOX_CA7", GENMASK(1, 1)},
311 {"VIPX1", 0, "SDMA", GENMASK(1, 1)},
312 {"VIPX1", BIT(1), "CM7", GENMASK(1, 1)},
315 {"VIPX2", 0, "SDMA", 0},
318 {"ISP0", 0, "FIMC-ISP", GENMASK(2, 1)},
319 {"ISP0", BIT(1), "VRA", GENMASK(2, 1)},
320 {"ISP0", BIT(2), "GDC", GENMASK(2, 1)},
321 {"ISP1", 0, "MC_SCALER", 0},
324 {"FSYS", 0, "UFS", GENMASK(1, 0)},
325 {"FSYS", BIT(0), "MMC_CARD", GENMASK(1, 0)},
326 {"FSYS", BIT(1), "SSS", GENMASK(1, 0)},
327 {"FSYS", BIT(1) | BIT(0), "RTIC", GENMASK(1, 0)},
330 {"USB", 0, "USB", 0},
333 {"COREX", 0, "APM", GENMASK(1, 0)},
336 {"COREX", BIT(0), "CM4_SHUB_CD", GENMASK(3, 0)},
337 {"COREX", BIT(0) | BIT(2), "CM4_SHUB_P", GENMASK(3, 0)},
338 {"COREX", BIT(0) | BIT(3), "PDMA_SHUB", GENMASK(3, 0)},
341 {"COREX", BIT(1), "PDMA", GENMASK(1, 0)},
342 {"COREX", BIT(0) | BIT(1), "SPDMA", GENMASK(1, 0)},
343 {"SIREX", 0, "SIREX", 0},
344 {"DIT", 0, "DIT", 0},
346 /* BLK_G3D - Unique ID */
350 {"MFC0", 0, "MFC0", 0},
351 {"MFC1", 0, "MFC1", GENMASK(1, 1)},
352 {"MFC1", BIT(1), "WFD", GENMASK(1, 1)},
355 {"G2D", 0, "JPEG", GENMASK(2, 1)},
356 {"G2D", BIT(1), "MSCL", GENMASK(2, 1)},
357 {"G2D", BIT(2), "G2D", GENMASK(2, 1)},
360 {"CP_0", 0, "UCPUM", GENMASK(5, 0)},
361 {"CP_0", BIT(0), "DMA0", GENMASK(5, 0)},
362 {"CP_0", BIT(0) | BIT(3), "DMA1", GENMASK(5, 0)},
363 {"CP_0", BIT(0) | BIT(4), "DMA2", GENMASK(5, 0)},
364 {"CP_0", BIT(0) | BIT(2), "LCPUMtoL2", GENMASK(5, 0)},
365 {"CP_0", BIT(2), "LMAC", GENMASK(5, 0)},
366 {"CP_0", BIT(1), "CSXAP", GENMASK(5, 0)},
367 {"CP_0", BIT(0) | BIT(1), "DATAMOVER", GENMASK(5, 0)},
368 {"CP_0", BIT(0) | BIT(1) | BIT(4), "BAYES", GENMASK(5, 0)},
369 {"CP_0", BIT(0) | BIT(1) | BIT(3), "LOGGER", GENMASK(5, 0)},
370 {"CP_0", BIT(1) | BIT(2), "HARQMOVER", GENMASK(5, 0)},
373 {"CP_1", 0, "UCPUM", GENMASK(5, 0)},
374 {"CP_1", BIT(0), "DMA0", GENMASK(5, 0)},
375 {"CP_1", BIT(0) | BIT(3), "DMA1", GENMASK(5, 0)},
376 {"CP_1", BIT(0) | BIT(4), "DMA2", GENMASK(5, 0)},
377 {"CP_1", BIT(0) | BIT(2), "LCPUMtoL2", GENMASK(5, 0)},
378 {"CP_1", BIT(2), "LMAC", GENMASK(5, 0)},
379 {"CP_1", BIT(1), "CSXAP", GENMASK(5, 0)},
380 {"CP_1", BIT(0) | BIT(1), "DATAMOVER", GENMASK(5, 0)},
381 {"CP_1", BIT(0) | BIT(1) | BIT(4), "BAYES", GENMASK(5, 0)},
382 {"CP_1", BIT(0) | BIT(1) | BIT(3), "LOGGER", GENMASK(5, 0)},
383 {"CP_1", BIT(1) | BIT(2), "HARQMOVER", GENMASK(5, 0)},
386 {"WLBT", 0, "CR7", GENMASK(2, 0)},
387 {"WLBT", BIT(0), "XDMA", GENMASK(2, 0)},
388 {"WLBT", BIT(1), "ENC_DMA0", GENMASK(2, 0)},
389 {"WLBT", BIT(0) | BIT(1), "ENC_DMA0", GENMASK(2, 0)},
390 {"WLBT", BIT(2), "BTLC", GENMASK(2, 0)},
393 {"GNSS", 0, "CM7F_S0", GENMASK(2, 0)},
394 {"GNSS", BIT(0), "CM7F_S1_AHB", GENMASK(2, 0)},
395 {"GNSS", BIT(1), "XDMA0", GENMASK(2, 0)},
396 {"GNSS", BIT(0) | BIT(1), "XDMA1", GENMASK(1, 0)},
399 /* data_path is sorted by INT_VEC_DEBUG_INTERRUPT_VECTOR_TABLE bits */
400 static struct itmon_nodeinfo data_path
[] = {
401 {M_NODE
, "ABOX", 0x12403000, NULL
, 0, false, false, true, true, false},
402 {M_NODE
, "CAM", 0x12423000, NULL
, 0, false, false, true, true, false},
403 {M_NODE
, "COREX", 0x12413000, NULL
, 0, false, false, true, true, false},
404 {M_NODE
, "CSSYS", 0x12433000, NULL
, 0, false, false, true, true, false},
405 {M_NODE
, "DIT", 0x12453000, NULL
, 0, false, false, true, true, false},
406 {M_NODE
, "DPU", 0x12443000, NULL
, 0, false, false, true, true, false},
407 {M_NODE
, "FSYS", 0x12463000, NULL
, 0, false, false, true, true, false},
408 {M_NODE
, "G2D", 0x12473000, NULL
, 0, false, false, true, true, false},
409 {M_NODE
, "G3D", 0x12483000, NULL
, 0, false, false, true, true, false},
410 {M_NODE
, "GNSS", 0x12493000, NULL
, 0, false, false, true, true, false},
411 {M_NODE
, "ISP0", 0x124A3000, NULL
, 0, false, false, true, true, false},
412 {M_NODE
, "ISP1", 0x124B3000, NULL
, 0, false, false, true, true, false},
413 {M_NODE
, "MFC0", 0x124C3000, NULL
, 0, false, false, true, true, false},
414 {M_NODE
, "MFC1", 0x124D3000, NULL
, 0, false, false, true, true, false},
415 {M_NODE
, "CP_0", 0x124E3000, NULL
, 0, false, false, true, true, false},
416 {M_NODE
, "CP_1", 0x124F3000, NULL
, 0, false, false, true, true, false},
417 {M_NODE
, "USB", 0x12513000, NULL
, 0, false, false, true, true, false},
418 {M_NODE
, "VIPX1", 0x12523000, NULL
, 0, false, false, true, true, false},
419 {M_NODE
, "VIPX2", 0x12533000, NULL
, 0, false, false, true, true, false},
420 {M_NODE
, "WLBT", 0x12503000, NULL
, 0, false, false, true, true, false},
421 {S_NODE
, "CP_MEM0", 0x12583000, NULL
, TMOUT
, true, false, true, true, false},
422 {S_NODE
, "CP_MEM1", 0x12593000, NULL
, TMOUT
, true, false, true, true, false},
423 {S_NODE
, "PERI", 0x125B3000, NULL
, TMOUT
, true, false, true, true, false},
424 {S_NODE
, "RT_MEM0", 0x12563000, NULL
, TMOUT
, true, false, true, true, false},
425 {S_NODE
, "RT_MEM1", 0x12573000, NULL
, TMOUT
, true, false, true, true, false},
426 {S_NODE
, "S_CCI", 0x125A3000, NULL
, TMOUT
, true, false, true, true, false},
427 {S_NODE
, "S_NRT0", 0x12543000, NULL
, TMOUT
, true, false, true, true, false},
428 {S_NODE
, "S_NRT1", 0x12553000, NULL
, TMOUT
, true, false, true, true, false},
431 /* peri_path is sorted by INT_VEC_DEBUG_INTERRUPT_VECTOR_TABLE bits */
432 static struct itmon_nodeinfo trex_d_nrt
[] = {
433 {M_NODE
, "M_NRT0", 0x12A13000, NULL
, 0, false, false, true, true, false},
434 {M_NODE
, "M_NRT1", 0x12A23000, NULL
, 0, false, false, true, true, false},
435 {M_NODE
, "SIREX", 0x12A03000, NULL
, 0, false, false, true, true, false},
436 {M_NODE
, "NRT_MEM0", 0x12A33000, NULL
, 0, false, false, true, true, false},
437 {M_NODE
, "NRT_MEM1", 0x12A43000, NULL
, 0, false, false, true, true, false},
440 /* peri_path is sorted by INT_VEC_DEBUG_INTERRUPT_VECTOR_TABLE bits */
441 static struct itmon_nodeinfo peri_path
[] = {
442 {M_NODE
, "CPU_TO_SFR", 0x12803000, NULL
, 0, false, false, true, true, false},
443 {M_NODE
, "PERI_TO_SFR", 0x12813000, NULL
, 0, false, false, true, true, false},
444 {S_NODE
, "APMP", 0x12833000, NULL
, TMOUT
, true, false, true, true, false},
445 {S_NODE
, "CAMP", 0x12843000, NULL
, TMOUT
, true, false, true, true, false},
446 {S_NODE
, "COREP_SFR", 0x12893000, NULL
, TMOUT
, true, false, true, true, false},
447 {S_NODE
, "COREP_TREX", 0x12883000, NULL
, TMOUT
, true, false, true, true, false},
448 {S_NODE
, "CPU_CL0P", 0x12853000, NULL
, TMOUT
, true, false, true, true, false},
449 {S_NODE
, "CPU_CL1P", 0x12863000, NULL
, TMOUT
, true, false, true, true, false},
450 {S_NODE
, "CSSYS", 0x12873000, NULL
, TMOUT
, true, false, true, true, false},
451 {S_NODE
, "DISPAUDP", 0x128A3000, NULL
, TMOUT
, true, false, true, true, false},
452 {S_NODE
, "FSYSP", 0x128B3000, NULL
, TMOUT
, true, false, true, true, false},
453 {S_NODE
, "G2DP", 0x128C3000, NULL
, TMOUT
, true, false, true, true, false},
454 {S_NODE
, "G3DP", 0x128D3000, NULL
, TMOUT
, true, false, true, true, false},
455 {S_NODE
, "GICP", 0x128E3000, NULL
, TMOUT
, true, false, true, true, false},
456 {S_NODE
, "GNSSP", 0x128F3000, NULL
, TMOUT
, true, false, true, true, false},
457 {S_NODE
, "ISPP", 0x12903000, NULL
, TMOUT
, true, false, true, true, false},
458 {S_NODE
, "MFCP", 0x12913000, NULL
, TMOUT
, true, false, true, true, false},
459 {S_NODE
, "MIF0P", 0x12923000, NULL
, TMOUT
, true, false, true, true, false},
460 {S_NODE
, "MIF1P", 0x12933000, NULL
, TMOUT
, true, false, true, true, false},
461 {S_NODE
, "CP_P", 0x12943000, NULL
, TMOUT
, true, false, true, true, false},
462 {S_NODE
, "PERIP", 0x12953000, NULL
, TMOUT
, true, false, true, true, false},
463 {S_NODE
, "SHUBP", 0x12963000, NULL
, TMOUT
, true, false, true, true, false},
464 {S_NODE
, "SIREXP", 0x12973000, NULL
, TMOUT
, true, false, true, true, false},
465 {S_NODE
, "USBP", 0x12983000, NULL
, TMOUT
, true, false, true, true, false},
466 {S_NODE
, "VIPX1P", 0x129A3000, NULL
, TMOUT
, true, false, true, true, false},
467 {S_NODE
, "VIPX2P", 0x129B3000, NULL
, TMOUT
, true, false, true, true, false},
468 {S_NODE
, "WLBTP", 0x12993000, NULL
, TMOUT
, true, false, true, true, false},
471 static struct itmon_nodegroup nodegroup
[] = {
472 {306, "TREX_D_CORE", 0x127F3000, NULL
, data_path
, ARRAY_SIZE(data_path
), BUS_DATA
},
473 {320, "TREX_D_NRT", 0x12BF3000, NULL
, trex_d_nrt
, ARRAY_SIZE(trex_d_nrt
), BUS_DATA
},
474 {307, "TREX_P_CORE", 0x129F3000, NULL
, peri_path
, ARRAY_SIZE(peri_path
), BUS_PERI
},
479 struct itmon_platdata
*pdata
;
480 struct of_device_id
*match
;
484 spinlock_t ctrl_lock
;
485 struct itmon_notifier notifier_info
;
488 struct itmon_panic_block
{
489 struct notifier_block nb_panic_block
;
490 struct itmon_dev
*pdev
;
493 /* declare notifier_list */
494 ATOMIC_NOTIFIER_HEAD(itmon_notifier_list
);
496 static const struct of_device_id itmon_dt_match
[] = {
497 {.compatible
= "samsung,exynos-itmon",
501 MODULE_DEVICE_TABLE(of
, itmon_dt_match
);
503 #define EXYNOS_PMU_BURNIN_CTRL 0x0A08
504 #define BIT_ENABLE_DBGSEL_WDTRESET BIT(25)
505 #ifdef CONFIG_S3C2410_WATCHDOG
506 extern int s3c2410wdt_set_emergency_reset(unsigned int timeout
, int index
);
508 #define s3c2410wdt_set_emergency_reset(a, b) do { } while (0)
510 static void itmon_switch_scandump(void)
515 ret
= exynos_pmu_read(EXYNOS_PMU_BURNIN_CTRL
, &val
);
516 ret
= exynos_pmu_write(EXYNOS_PMU_BURNIN_CTRL
, val
| BIT_ENABLE_DBGSEL_WDTRESET
);
517 s3c2410wdt_set_emergency_reset(5, 0);
520 static struct itmon_rpathinfo
*itmon_get_rpathinfo(struct itmon_dev
*itmon
,
524 struct itmon_platdata
*pdata
= itmon
->pdata
;
525 struct itmon_rpathinfo
*rpath
= NULL
;
531 for (i
= 0; i
< ARRAY_SIZE(rpathinfo
); i
++) {
532 if (pdata
->rpathinfo
[i
].id
== (id
& pdata
->rpathinfo
[i
].bits
)) {
533 if (dest_name
&& !strncmp(pdata
->rpathinfo
[i
].dest_name
,
535 strlen(pdata
->rpathinfo
[i
].dest_name
))) {
536 rpath
= (struct itmon_rpathinfo
*)&pdata
->rpathinfo
[i
];
544 static struct itmon_masterinfo
*itmon_get_masterinfo(struct itmon_dev
*itmon
,
548 struct itmon_platdata
*pdata
= itmon
->pdata
;
549 struct itmon_masterinfo
*master
= NULL
;
556 for (i
= 0; i
< ARRAY_SIZE(masterinfo
); i
++) {
557 if (!strncmp(pdata
->masterinfo
[i
].port_name
, port_name
, strlen(port_name
))) {
558 val
= user
& pdata
->masterinfo
[i
].bits
;
559 if (val
== pdata
->masterinfo
[i
].user
) {
560 master
= (struct itmon_masterinfo
*)&pdata
->masterinfo
[i
];
568 static void itmon_init(struct itmon_dev
*itmon
, bool enabled
)
570 struct itmon_platdata
*pdata
= itmon
->pdata
;
571 struct itmon_nodeinfo
*node
;
575 for (i
= 0; i
< ARRAY_SIZE(nodegroup
); i
++) {
576 node
= pdata
->nodegroup
[i
].nodeinfo
;
577 for (j
= 0; j
< pdata
->nodegroup
[i
].nodesize
; j
++) {
578 if (node
[j
].type
== S_NODE
&& node
[j
].tmout_enabled
) {
579 offset
= OFFSET_TMOUT_REG
;
580 /* Enable Timeout setting */
581 __raw_writel(enabled
, node
[j
].regs
+ offset
+ REG_DBG_CTL
);
582 /* set tmout interval value */
583 __raw_writel(node
[j
].time_val
,
584 node
[j
].regs
+ offset
+ REG_TMOUT_INIT_VAL
);
585 pr_debug("Exynos ITMON - %s timeout enabled\n", node
[j
].name
);
586 if (node
[j
].tmout_frz_enabled
) {
587 /* Enable freezing */
588 __raw_writel(enabled
,
589 node
[j
].regs
+ offset
+ REG_TMOUT_FRZ_EN
);
592 if (node
[j
].err_enabled
) {
593 /* clear previous interrupt of req_read */
594 offset
= OFFSET_REQ_R
;
595 if (!pdata
->probed
|| !node
->retention
)
596 __raw_writel(1, node
[j
].regs
+ offset
+ REG_INT_CLR
);
597 /* enable interrupt */
598 __raw_writel(enabled
, node
[j
].regs
+ offset
+ REG_INT_MASK
);
600 /* clear previous interrupt of req_write */
601 offset
= OFFSET_REQ_W
;
602 if (pdata
->probed
|| !node
->retention
)
603 __raw_writel(1, node
[j
].regs
+ offset
+ REG_INT_CLR
);
604 /* enable interrupt */
605 __raw_writel(enabled
, node
[j
].regs
+ offset
+ REG_INT_MASK
);
607 /* clear previous interrupt of response_read */
608 offset
= OFFSET_RESP_R
;
609 if (!pdata
->probed
|| !node
->retention
)
610 __raw_writel(1, node
[j
].regs
+ offset
+ REG_INT_CLR
);
611 /* enable interrupt */
612 __raw_writel(enabled
, node
[j
].regs
+ offset
+ REG_INT_MASK
);
614 /* clear previous interrupt of response_write */
615 offset
= OFFSET_RESP_W
;
616 if (!pdata
->probed
|| !node
->retention
)
617 __raw_writel(1, node
[j
].regs
+ offset
+ REG_INT_CLR
);
618 /* enable interrupt */
619 __raw_writel(enabled
, node
[j
].regs
+ offset
+ REG_INT_MASK
);
620 pr_debug("Exynos ITMON - %s error reporting enabled\n", node
[j
].name
);
622 if (node
[j
].hw_assert_enabled
) {
623 offset
= OFFSET_HW_ASSERT
;
624 __raw_writel(RD_RESP_INT_ENABLE
| WR_RESP_INT_ENABLE
|
625 ARLEN_RLAST_INT_ENABLE
| AWLEN_WLAST_INT_ENABLE
,
626 node
[j
].regs
+ offset
+ REG_HWA_CTL
);
632 void itmon_enable(bool enabled
)
635 itmon_init(g_itmon
, enabled
);
638 void itmon_set_errcnt(int cnt
)
640 struct itmon_platdata
*pdata
;
643 pdata
= g_itmon
->pdata
;
644 pdata
->err_cnt
= cnt
;
648 static void itmon_post_handler_to_notifier(struct itmon_dev
*itmon
,
649 unsigned int trans_type
)
651 struct itmon_platdata
*pdata
= itmon
->pdata
;
652 struct itmon_traceinfo
*traceinfo
= &pdata
->traceinfo
[trans_type
];
654 /* After treatment by port */
655 if (!traceinfo
->port
|| strlen(traceinfo
->port
) < 1)
658 itmon
->notifier_info
.port
= traceinfo
->port
;
659 itmon
->notifier_info
.master
= traceinfo
->master
;
660 itmon
->notifier_info
.dest
= traceinfo
->dest
;
661 itmon
->notifier_info
.read
= traceinfo
->read
;
662 itmon
->notifier_info
.target_addr
= traceinfo
->target_addr
;
663 itmon
->notifier_info
.errcode
= traceinfo
->errcode
;
665 /* call notifier_call_chain of itmon */
666 atomic_notifier_call_chain(&itmon_notifier_list
, 0, &itmon
->notifier_info
);
669 static void itmon_post_handler_by_master(struct itmon_dev
*itmon
,
670 unsigned int trans_type
)
672 struct itmon_platdata
*pdata
= itmon
->pdata
;
673 struct itmon_traceinfo
*traceinfo
= &pdata
->traceinfo
[trans_type
];
675 /* After treatment by port */
676 if (!traceinfo
->port
|| strlen(traceinfo
->port
) < 1)
679 if (!strncmp(traceinfo
->port
, "CPU", strlen("CPU"))) {
680 /* if master is CPU, then we expect any exception */
681 if (pdata
->err_cnt
> PANIC_ALLOWED_THRESHOLD
) {
683 itmon_init(itmon
, false);
684 pr_info("ITMON is turn-off when CPU transaction is detected repeatly\n");
686 pr_info("ITMON skips CPU transaction detected\n");
688 } else if (!strncmp(traceinfo
->port
, CP_COMMON_STR
, strlen(CP_COMMON_STR
))) {
689 /* if master is DSP and operation is read, we don't care this */
690 if (traceinfo
->master
&& traceinfo
->target_addr
== INVALID_REMAPPING
&&
691 !strncmp(traceinfo
->master
, "CR4MtoL2", strlen(traceinfo
->master
))) {
693 pr_info("ITMON skips CP's DSP(CR4MtoL2) detected\n");
695 /* Disable busmon all interrupts */
696 itmon_init(itmon
, false);
697 #if defined(CONFIG_SEC_MODEM_IF)
698 pdata
->crash_in_progress
= true;
699 modem_force_crash_exit_ext();
705 void itmon_report_timeout(struct itmon_dev
*itmon
,
706 struct itmon_nodeinfo
*node
,
707 unsigned int trans_type
)
709 unsigned int info
, axid
, valid
, timeout
, payload
;
711 char *master_name
, *port_name
;
712 struct itmon_rpathinfo
*port
;
713 struct itmon_masterinfo
*master
;
714 int i
, num
= (trans_type
== TRANS_TYPE_READ
? SZ_128
: SZ_64
);
715 int fz_offset
= (trans_type
== TRANS_TYPE_READ
? 0 : REG_TMOUT_BUF_WR_OFFSET
);
717 pr_info("\n TIMEOUT_BUFFER Information\n\n");
718 pr_info(" > NUM| BLOCK| MASTER| VALID| TIMEOUT| ID| ADDRESS| INFO|\n");
720 for (i
= 0; i
< num
; i
++) {
721 writel(i
, node
->regs
+ OFFSET_TMOUT_REG
+
722 REG_TMOUT_BUF_POINT_ADDR
+ fz_offset
);
723 axid
= readl(node
->regs
+ OFFSET_TMOUT_REG
+
724 REG_TMOUT_BUF_ID
+ fz_offset
);
725 payload
= readl(node
->regs
+ OFFSET_TMOUT_REG
+
726 REG_TMOUT_BUF_PAYLOAD
+ fz_offset
);
727 addr
= (((unsigned long)readl(node
->regs
+ OFFSET_TMOUT_REG
+
728 REG_TMOUT_BUF_PAYLOAD_SRAM1
+ fz_offset
) &
729 GENMASK(15, 0)) << 32ULL);
730 addr
|= (readl(node
->regs
+ OFFSET_TMOUT_REG
+
731 REG_TMOUT_BUF_PAYLOAD_SRAM2
+ fz_offset
));
732 info
= readl(node
->regs
+ OFFSET_TMOUT_REG
+
733 REG_TMOUT_BUF_PAYLOAD_SRAM3
+ fz_offset
);
735 valid
= payload
& BIT(0);
736 timeout
= (payload
& GENMASK(19, 16)) >> 16;
738 port
= (struct itmon_rpathinfo
*)
739 itmon_get_rpathinfo(itmon
, axid
, node
->name
);
741 port_name
= port
->port_name
;
742 master
= (struct itmon_masterinfo
*)
743 itmon_get_masterinfo(itmon
, port_name
,
744 axid
>> port
->shift_bits
);
746 master_name
= master
->master_name
;
748 master_name
= "Unknown";
750 port_name
= "Unknown";
751 master_name
= "Unknown";
753 pr_info(" > %03d|%8s|%8s|%8u|%8x|%08x|%010zx|%08x|\n",
754 i
, port_name
, master_name
, valid
, timeout
, axid
, addr
, info
);
756 pr_info("--------------------------------------------------------------------------\n");
759 static unsigned int power(unsigned int param
, unsigned int num
)
763 return param
* (power(param
, num
- 1));
766 static void itmon_report_traceinfo(struct itmon_dev
*itmon
,
767 struct itmon_nodeinfo
*node
,
768 unsigned int trans_type
)
770 struct itmon_platdata
*pdata
= itmon
->pdata
;
771 struct itmon_traceinfo
*traceinfo
= &pdata
->traceinfo
[trans_type
];
772 struct itmon_nodegroup
*group
= NULL
;
774 if (!traceinfo
->dirty
)
777 pr_info("--------------------------------------------------------------------------\n"
778 " Transaction Information\n\n"
779 " > Master : %s %s\n"
781 " > Target Address : 0x%lX %s\n"
783 " > Error code : %s\n",
784 traceinfo
->port
, traceinfo
->master
? traceinfo
->master
: "",
785 traceinfo
->dest
? traceinfo
->dest
: "Unknown",
786 traceinfo
->target_addr
,
787 (unsigned int)traceinfo
->target_addr
== INVALID_REMAPPING
?
788 "(BAAW Remapped address)" : "",
789 trans_type
== TRANS_TYPE_READ
? "READ" : "WRITE",
790 itmon_errcode
[traceinfo
->errcode
]);
793 struct itmon_tracedata
*tracedata
= &node
->tracedata
;
795 pr_info(" > Size : %u bytes x %u burst => %u bytes\n"
796 " > Burst Type : %u (0:FIXED, 1:INCR, 2:WRAP)\n"
798 " > Protection : %s\n",
799 power(BIT_AXSIZE(tracedata
->ext_info_1
), 2), BIT_AXLEN(tracedata
->ext_info_1
) + 1,
800 power(BIT_AXSIZE(tracedata
->ext_info_1
), 2) * (BIT_AXLEN(tracedata
->ext_info_1
) + 1),
801 BIT_AXBURST(tracedata
->ext_info_2
),
802 (BIT_AXPROT(tracedata
->ext_info_2
) & 0x1) ? "Privileged access" : "Unprivileged access",
803 (BIT_AXPROT(tracedata
->ext_info_2
) & 0x2) ? "Non-secure access" : "Secure access");
806 pr_info(" > Path Type : %s\n"
807 "--------------------------------------------------------------------------\n",
808 itmon_pathtype
[group
->bus_type
]);
811 pr_info("--------------------------------------------------------------------------\n");
815 static void itmon_report_pathinfo(struct itmon_dev
*itmon
,
816 struct itmon_nodeinfo
*node
,
817 unsigned int trans_type
)
819 struct itmon_platdata
*pdata
= itmon
->pdata
;
820 struct itmon_tracedata
*tracedata
= &node
->tracedata
;
821 struct itmon_traceinfo
*traceinfo
= &pdata
->traceinfo
[trans_type
];
823 if (!traceinfo
->path_dirty
) {
824 pr_info("--------------------------------------------------------------------------\n"
825 " ITMON Report (%s)\n"
826 "--------------------------------------------------------------------------\n"
827 " PATH Information\n",
828 trans_type
== TRANS_TYPE_READ
? "READ" : "WRITE");
829 traceinfo
->path_dirty
= true;
831 switch (node
->type
) {
833 pr_info(" > %14s, %8s(0x%08X)\n",
834 node
->name
, "M_NODE", node
->phy_regs
+ tracedata
->offset
);
837 pr_info(" > %14s, %8s(0x%08X)\n",
838 node
->name
, "T_S_NODE", node
->phy_regs
+ tracedata
->offset
);
841 pr_info(" > %14s, %8s(0x%08X)\n",
842 node
->name
, "T_M_NODE", node
->phy_regs
+ tracedata
->offset
);
845 pr_info(" > %14s, %8s(0x%08X)\n",
846 node
->name
, "S_NODE", node
->phy_regs
+ tracedata
->offset
);
851 static void itmon_report_tracedata(struct itmon_dev
*itmon
,
852 struct itmon_nodeinfo
*node
,
853 unsigned int trans_type
)
855 struct itmon_platdata
*pdata
= itmon
->pdata
;
856 struct itmon_tracedata
*tracedata
= &node
->tracedata
;
857 struct itmon_traceinfo
*traceinfo
= &pdata
->traceinfo
[trans_type
];
858 struct itmon_masterinfo
*master
;
859 struct itmon_rpathinfo
*port
;
860 unsigned int errcode
, axid
;
862 errcode
= BIT_ERR_CODE(tracedata
->int_info
);
863 axid
= BIT_AXID(tracedata
->int_info
);
865 switch (node
->type
) {
867 /* In this case, we can get information from M_NODE
868 * Fill traceinfo->port / target_addr / read / master */
869 if (BIT_ERR_VALID(tracedata
->int_info
) && tracedata
->ext_info_2
) {
870 /* If only detecting M_NODE only(DECERR) */
871 traceinfo
->port
= node
->name
;
872 master
= (struct itmon_masterinfo
*)
873 itmon_get_masterinfo(itmon
, node
->name
, axid
);
875 traceinfo
->master
= master
->master_name
;
877 traceinfo
->master
= NULL
;
879 traceinfo
->target_addr
=
880 (((unsigned long)node
->tracedata
.ext_info_1
881 & GENMASK(3, 0)) << 32ULL);
882 traceinfo
->target_addr
|= node
->tracedata
.ext_info_0
;
883 traceinfo
->read
= tracedata
->read
;
884 traceinfo
->errcode
= errcode
;
885 traceinfo
->dirty
= true;
887 traceinfo
->master
= NULL
;
888 traceinfo
->target_addr
= 0;
889 traceinfo
->read
= tracedata
->read
;
890 traceinfo
->port
= node
->name
;
891 traceinfo
->errcode
= errcode
;
892 traceinfo
->dirty
= true;
894 itmon_report_pathinfo(itmon
, node
, trans_type
);
898 * In DECERR case, the follow information was already filled in M_NODE.
900 port
= (struct itmon_rpathinfo
*) itmon_get_rpathinfo(itmon
, axid
, node
->name
);
903 struct itmon_nodeinfo
*m_node
, *next_m_node
;
904 struct itmon_tracedata
*m_tracedata
;
907 traceinfo
->port
= port
->port_name
;
908 list_for_each_entry_safe(m_node
, next_m_node
,
909 &pdata
->tracelist
[trans_type
], list
) {
910 if (m_node
&& m_node
->name
&& port
->port_name
&& m_node
->type
== M_NODE
&&
911 strncmp(m_node
->name
, port
->port_name
,
912 strlen(port
->port_name
)) == 0) {
913 m_tracedata
= &m_node
->tracedata
;
914 m_axid
= BIT_AXID(m_tracedata
->int_info
);
915 master
= (struct itmon_masterinfo
*)
916 itmon_get_masterinfo(itmon
, traceinfo
->port
, m_axid
);
918 traceinfo
->master
= master
->master_name
;
924 if (!traceinfo
->port
)
925 traceinfo
->port
= "Unknown";
926 if (!traceinfo
->master
)
927 traceinfo
->master
= "Unknown";
929 traceinfo
->target_addr
=
930 (((unsigned long)node
->tracedata
.ext_info_1
931 & GENMASK(3, 0)) << 32ULL);
932 traceinfo
->target_addr
|= node
->tracedata
.ext_info_0
;
933 traceinfo
->errcode
= errcode
;
934 traceinfo
->dest
= node
->name
;
935 traceinfo
->dirty
= true;
936 traceinfo
->snode_dirty
= true;
937 itmon_report_pathinfo(itmon
, node
, trans_type
);
938 itmon_report_traceinfo(itmon
, node
, trans_type
);
941 pr_info("Unknown Error - offset:%u\n", tracedata
->offset
);
946 static void itmon_report_hwa_rawdata(struct itmon_dev
*itmon
,
947 struct itmon_nodeinfo
*node
)
949 unsigned int hwa_ctl
, hwa_info
, hwa_int_id
;
951 hwa_ctl
= __raw_readl(node
->regs
+ OFFSET_HW_ASSERT
+ REG_HWA_CTL
);
952 hwa_info
= __raw_readl(node
->regs
+ OFFSET_HW_ASSERT
+ REG_HWA_INT
);
953 hwa_int_id
= __raw_readl(node
->regs
+ OFFSET_HW_ASSERT
+ REG_HWA_INT_ID
);
955 /* Output Raw register information */
956 pr_info("--------------------------------------------------------------------------\n"
957 " HWA Raw Register Information(ITMON information)\n\n");
958 pr_info(" > %s(%s, 0x%08X)\n"
959 " > REG(0x104~0x10C) : 0x%08X, 0x%08X, 0x%08X\n",
960 node
->name
, itmon_nodestring
[node
->type
],
967 static void itmon_report_rawdata(struct itmon_dev
*itmon
,
968 struct itmon_nodeinfo
*node
,
969 unsigned int trans_type
)
971 struct itmon_platdata
*pdata
= itmon
->pdata
;
972 struct itmon_traceinfo
*traceinfo
= &pdata
->traceinfo
[trans_type
];
973 struct itmon_tracedata
*tracedata
= &node
->tracedata
;
975 /* Output Raw register information */
976 pr_info(" > %s(%s, 0x%08X)\n"
977 " > REG(0x08~0x18) : 0x%08X, 0x%08X, 0x%08X, 0x%08X\n"
978 " > REG(0x104~0x10C) : 0x%08X, 0x%08X, 0x%08X\n",
979 node
->name
, itmon_nodestring
[node
->type
],
980 node
->phy_regs
+ tracedata
->offset
,
982 tracedata
->ext_info_0
,
983 tracedata
->ext_info_1
,
984 tracedata
->ext_info_2
,
987 tracedata
->hwa_int_id
);
989 /* If node is to DREX S_NODE, Outputing timeout freezing result */
990 if (node
->type
== S_NODE
&& traceinfo
->errcode
== ERRCODE_TMOUT
)
991 itmon_report_timeout(itmon
, node
, trans_type
);
994 static void itmon_route_tracedata(struct itmon_dev
*itmon
)
996 struct itmon_platdata
*pdata
= itmon
->pdata
;
997 struct itmon_traceinfo
*traceinfo
;
998 struct itmon_nodeinfo
*node
, *next_node
;
999 unsigned int trans_type
;
1002 /* To call function is sorted by declaration */
1003 for (trans_type
= 0; trans_type
< TRANS_TYPE_NUM
; trans_type
++) {
1004 for (i
= M_NODE
; i
< NODE_TYPE
; i
++) {
1005 list_for_each_entry(node
, &pdata
->tracelist
[trans_type
], list
) {
1006 if (i
== node
->type
)
1007 itmon_report_tracedata(itmon
, node
, trans_type
);
1010 /* If there is no S_NODE information, check one more */
1011 traceinfo
= &pdata
->traceinfo
[trans_type
];
1012 if (!traceinfo
->snode_dirty
)
1013 itmon_report_traceinfo(itmon
, NULL
, trans_type
);
1016 if (pdata
->traceinfo
[TRANS_TYPE_READ
].dirty
||
1017 pdata
->traceinfo
[TRANS_TYPE_WRITE
].dirty
)
1018 pr_info(" Raw Register Information(ITMON Internal Information)\n\n");
1020 for (trans_type
= 0; trans_type
< TRANS_TYPE_NUM
; trans_type
++) {
1021 for (i
= M_NODE
; i
< NODE_TYPE
; i
++) {
1022 list_for_each_entry_safe(node
, next_node
, &pdata
->tracelist
[trans_type
], list
) {
1023 if (i
== node
->type
) {
1024 itmon_report_rawdata(itmon
, node
, trans_type
);
1026 list_del(&node
->list
);
1033 if (pdata
->traceinfo
[TRANS_TYPE_READ
].dirty
||
1034 pdata
->traceinfo
[TRANS_TYPE_WRITE
].dirty
)
1035 pr_info("--------------------------------------------------------------------------\n");
1037 for (trans_type
= 0; trans_type
< TRANS_TYPE_NUM
; trans_type
++) {
1038 itmon_post_handler_to_notifier(itmon
, trans_type
);
1039 itmon_post_handler_by_master(itmon
, trans_type
);
1043 static void itmon_trace_data(struct itmon_dev
*itmon
,
1044 struct itmon_nodegroup
*group
,
1045 struct itmon_nodeinfo
*node
,
1046 unsigned int offset
)
1048 struct itmon_platdata
*pdata
= itmon
->pdata
;
1049 struct itmon_nodeinfo
*new_node
= NULL
;
1050 unsigned int int_info
, info0
, info1
, info2
;
1051 unsigned int hwa_ctl
, hwa_info
, hwa_int_id
;
1052 bool read
= TRANS_TYPE_WRITE
;
1055 int_info
= __raw_readl(node
->regs
+ offset
+ REG_INT_INFO
);
1056 info0
= __raw_readl(node
->regs
+ offset
+ REG_EXT_INFO_0
);
1057 info1
= __raw_readl(node
->regs
+ offset
+ REG_EXT_INFO_1
);
1058 info2
= __raw_readl(node
->regs
+ offset
+ REG_EXT_INFO_2
);
1060 hwa_ctl
= __raw_readl(node
->regs
+ OFFSET_HW_ASSERT
+ REG_HWA_CTL
);
1061 hwa_info
= __raw_readl(node
->regs
+ OFFSET_HW_ASSERT
+ REG_HWA_INT
);
1062 hwa_int_id
= __raw_readl(node
->regs
+ OFFSET_HW_ASSERT
+ REG_HWA_INT_ID
);
1066 read
= TRANS_TYPE_READ
;
1070 /* Only S-Node is able to make log to registers */
1073 read
= TRANS_TYPE_READ
;
1077 /* Only NOT S-Node is able to make log to registers */
1080 pr_info("Unknown Error - node:%s offset:%u\n", node
->name
, offset
);
1084 new_node
= kmalloc(sizeof(struct itmon_nodeinfo
), GFP_ATOMIC
);
1086 /* Fill detected node information to tracedata's list */
1087 memcpy(new_node
, node
, sizeof(struct itmon_nodeinfo
));
1088 new_node
->tracedata
.int_info
= int_info
;
1089 new_node
->tracedata
.ext_info_0
= info0
;
1090 new_node
->tracedata
.ext_info_1
= info1
;
1091 new_node
->tracedata
.ext_info_2
= info2
;
1092 new_node
->tracedata
.hwa_ctl
= hwa_ctl
;
1093 new_node
->tracedata
.hwa_info
= hwa_info
;
1094 new_node
->tracedata
.hwa_int_id
= hwa_int_id
;
1096 new_node
->tracedata
.offset
= offset
;
1097 new_node
->tracedata
.read
= read
;
1098 new_node
->group
= group
;
1099 if (BIT_ERR_VALID(int_info
))
1100 node
->tracedata
.logging
= true;
1102 node
->tracedata
.logging
= false;
1104 list_add(&new_node
->list
, &pdata
->tracelist
[read
]);
1106 pr_info("failed to kmalloc for %s node %x offset\n",
1107 node
->name
, offset
);
1111 static int itmon_search_node(struct itmon_dev
*itmon
, struct itmon_nodegroup
*group
, bool clear
)
1113 struct itmon_platdata
*pdata
= itmon
->pdata
;
1114 struct itmon_nodeinfo
*node
= NULL
;
1115 unsigned int val
, offset
;
1116 unsigned long vec
, flags
, bit
= 0;
1119 spin_lock_irqsave(&itmon
->ctrl_lock
, flags
);
1120 memset(pdata
->traceinfo
, 0, sizeof(struct itmon_traceinfo
) * 2);
1122 /* Processing only this group and select detected node */
1123 vec
= (unsigned long)__raw_readl(group
->regs
);
1124 node
= group
->nodeinfo
;
1128 for_each_set_bit(bit
, &vec
, group
->nodesize
) {
1130 for (i
= 0; i
< OFFSET_NUM
; i
++) {
1131 offset
= i
* OFFSET_ERR_REPT
;
1132 /* Check Request information */
1133 val
= __raw_readl(node
[bit
].regs
+ offset
+ REG_INT_INFO
);
1134 if (BIT_ERR_OCCURRED(val
)) {
1135 /* This node occurs the error */
1136 itmon_trace_data(itmon
, group
, &node
[bit
], offset
);
1138 __raw_writel(1, node
[bit
].regs
1139 + offset
+ REG_INT_CLR
);
1143 /* Check H/W assertion */
1144 if (node
[bit
].hw_assert_enabled
) {
1145 val
= __raw_readl(node
[bit
].regs
+ OFFSET_HW_ASSERT
+
1147 if (BIT_HWA_ERR_OCCURRED(val
)) {
1148 itmon_report_hwa_rawdata(itmon
, &node
[bit
]);
1150 pdata
->err_cnt
= PANIC_ALLOWED_THRESHOLD
+ 1;
1156 /* Processing all group & nodes */
1157 for (i
= 0; i
< ARRAY_SIZE(nodegroup
); i
++) {
1158 group
= &nodegroup
[i
];
1159 if (group
->phy_regs
)
1160 vec
= (unsigned long)__raw_readl(group
->regs
);
1162 vec
= GENMASK(group
->nodesize
, 0);
1164 node
= group
->nodeinfo
;
1167 for_each_set_bit(bit
, &vec
, group
->nodesize
) {
1168 for (j
= 0; j
< OFFSET_NUM
; j
++) {
1169 offset
= j
* OFFSET_ERR_REPT
;
1170 /* Check Request information */
1171 val
= __raw_readl(node
[bit
].regs
+ offset
+ REG_INT_INFO
);
1172 if (BIT_ERR_OCCURRED(val
)) {
1173 /* This node occurs the error */
1174 itmon_trace_data(itmon
, group
, &node
[bit
], offset
);
1176 __raw_writel(1, node
[bit
].regs
1177 + offset
+ REG_INT_CLR
);
1181 /* Check H/W assertion */
1182 if (node
[bit
].hw_assert_enabled
) {
1183 val
= __raw_readl(node
[bit
].regs
+ OFFSET_HW_ASSERT
+
1185 if (BIT_HWA_ERR_OCCURRED(val
)) {
1186 itmon_report_hwa_rawdata(itmon
, &node
[bit
]);
1188 pdata
->err_cnt
= PANIC_ALLOWED_THRESHOLD
+ 1;
1195 itmon_route_tracedata(itmon
);
1197 spin_unlock_irqrestore(&itmon
->ctrl_lock
, flags
);
1201 static irqreturn_t
itmon_irq_handler(int irq
, void *data
)
1203 struct itmon_dev
*itmon
= (struct itmon_dev
*)data
;
1204 struct itmon_platdata
*pdata
= itmon
->pdata
;
1205 struct itmon_nodegroup
*group
= NULL
;
1209 /* Search itmon group */
1210 for (i
= 0; i
< ARRAY_SIZE(nodegroup
); i
++) {
1211 if (irq
== nodegroup
[i
].irq
) {
1212 group
= &pdata
->nodegroup
[i
];
1213 if (group
->phy_regs
!= 0) {
1214 pr_info("\nITMON Detected: %d irq, %s group, 0x%x vec, err_cnt:%u\n",
1215 irq
, group
->name
, __raw_readl(group
->regs
), pdata
->err_cnt
);
1217 pr_info("\nITMON Detected: %d irq, %s group, err_cnt:%u\n",
1218 irq
, group
->name
, pdata
->err_cnt
);
1224 ret
= itmon_search_node(itmon
, NULL
, true);
1226 pr_info("ITMON could not detect any error\n");
1228 if (pdata
->sysfs_scandump
) {
1229 itmon_switch_scandump();
1232 if (pdata
->err_cnt
++ > PANIC_ALLOWED_THRESHOLD
)
1233 pdata
->panic_allowed
= true;
1236 if (pdata
->panic_allowed
)
1237 panic("ITMON occurs panic, Transaction is invalid from IPs");
1242 void itmon_notifier_chain_register(struct notifier_block
*block
)
1244 atomic_notifier_chain_register(&itmon_notifier_list
, block
);
1247 static struct bus_type itmon_subsys
= {
1249 .dev_name
= "itmon",
1252 static ssize_t
itmon_timeout_fix_val_show(struct device
*dev
,
1253 struct device_attribute
*attr
, char *buf
)
1256 struct itmon_platdata
*pdata
= g_itmon
->pdata
;
1258 n
= scnprintf(buf
+ n
, 24, "set timeout val: 0x%x\n", pdata
->sysfs_tmout_val
);
1263 static ssize_t
itmon_timeout_fix_val_store(struct device
*dev
,
1264 struct device_attribute
*attr
, const char *buf
, size_t count
)
1266 unsigned long val
= simple_strtoul(buf
, NULL
, 0);
1267 struct itmon_platdata
*pdata
= g_itmon
->pdata
;
1269 if (val
> 0 && val
<= 0xFFFFF)
1270 pdata
->sysfs_tmout_val
= val
;
1275 static ssize_t
itmon_scandump_show(struct device
*dev
,
1276 struct device_attribute
*attr
, char *buf
)
1279 struct itmon_platdata
*pdata
= g_itmon
->pdata
;
1281 n
= scnprintf(buf
+ n
, 30, "scandump mode is %sable : %d\n",
1282 pdata
->sysfs_scandump
== 1 ? "en" : "dis",
1283 pdata
->sysfs_scandump
);
1288 static ssize_t
itmon_scandump_store(struct device
*dev
,
1289 struct device_attribute
*attr
, const char *buf
, size_t count
)
1291 unsigned long val
= simple_strtoul(buf
, NULL
, 0);
1292 struct itmon_platdata
*pdata
= g_itmon
->pdata
;
1294 if (val
> 0 && val
<= 0xFFFFF) {
1295 pdata
= g_itmon
->pdata
;
1296 pdata
->sysfs_scandump
= val
;
1302 static ssize_t
itmon_timeout_show(struct device
*dev
,
1303 struct device_attribute
*attr
, char *buf
)
1305 unsigned long i
, offset
;
1307 unsigned long vec
, bit
= 0;
1308 struct itmon_nodegroup
*group
= NULL
;
1309 struct itmon_nodeinfo
*node
;
1311 /* Processing all group & nodes */
1312 offset
= OFFSET_TMOUT_REG
;
1313 for (i
= 0; i
< ARRAY_SIZE(nodegroup
); i
++) {
1314 group
= &nodegroup
[i
];
1315 node
= group
->nodeinfo
;
1316 vec
= GENMASK(group
->nodesize
, 0);
1318 for_each_set_bit(bit
, &vec
, group
->nodesize
) {
1319 if (node
[bit
].type
== S_NODE
) {
1320 n
+= scnprintf(buf
+ n
, 60, "%-12s : 0x%08X, timeout : %x\n",
1321 node
[bit
].name
, node
[bit
].phy_regs
,
1322 __raw_readl(node
[bit
].regs
+ offset
+ REG_DBG_CTL
));
1329 static ssize_t
itmon_timeout_val_show(struct device
*dev
,
1330 struct device_attribute
*attr
, char *buf
)
1332 unsigned long i
, offset
;
1334 unsigned long vec
, bit
= 0;
1335 struct itmon_nodegroup
*group
= NULL
;
1336 struct itmon_nodeinfo
*node
;
1338 /* Processing all group & nodes */
1339 offset
= OFFSET_TMOUT_REG
;
1340 for (i
= 0; i
< ARRAY_SIZE(nodegroup
); i
++) {
1341 group
= &nodegroup
[i
];
1342 node
= group
->nodeinfo
;
1343 vec
= GENMASK(group
->nodesize
, 0);
1345 for_each_set_bit(bit
, &vec
, group
->nodesize
) {
1346 if (node
[bit
].type
== S_NODE
) {
1347 n
+= scnprintf(buf
+ n
, 60, "%-12s : 0x%08X, timeout : 0x%x\n",
1348 node
[bit
].name
, node
[bit
].phy_regs
,
1349 __raw_readl(node
[bit
].regs
+ offset
+ REG_TMOUT_INIT_VAL
));
1356 static ssize_t
itmon_timeout_freeze_show(struct device
*dev
,
1357 struct device_attribute
*attr
, char *buf
)
1359 unsigned long i
, offset
;
1361 unsigned long vec
, bit
= 0;
1362 struct itmon_nodegroup
*group
= NULL
;
1363 struct itmon_nodeinfo
*node
;
1365 /* Processing all group & nodes */
1366 offset
= OFFSET_TMOUT_REG
;
1367 for (i
= 0; i
< ARRAY_SIZE(nodegroup
); i
++) {
1368 group
= &nodegroup
[i
];
1369 node
= group
->nodeinfo
;
1370 vec
= GENMASK(group
->nodesize
, 0);
1372 for_each_set_bit(bit
, &vec
, group
->nodesize
) {
1373 if (node
[bit
].type
== S_NODE
) {
1374 n
+= scnprintf(buf
+ n
, 60, "%-12s : 0x%08X, timeout_freeze : %x\n",
1375 node
[bit
].name
, node
[bit
].phy_regs
,
1376 __raw_readl(node
[bit
].regs
+ offset
+ REG_TMOUT_FRZ_EN
));
1383 static ssize_t
itmon_timeout_store(struct device
*dev
,
1384 struct device_attribute
*attr
,
1385 const char *buf
, size_t count
)
1388 unsigned int val
, offset
, i
;
1389 unsigned long vec
, bit
= 0;
1390 struct itmon_nodegroup
*group
= NULL
;
1391 struct itmon_nodeinfo
*node
;
1393 name
= (char *)kstrndup(buf
, count
, GFP_KERNEL
);
1397 name
[count
- 1] = '\0';
1398 offset
= OFFSET_TMOUT_REG
;
1399 for (i
= 0; i
< ARRAY_SIZE(nodegroup
); i
++) {
1400 group
= &nodegroup
[i
];
1401 node
= group
->nodeinfo
;
1402 vec
= GENMASK(group
->nodesize
, 0);
1404 for_each_set_bit(bit
, &vec
, group
->nodesize
) {
1405 if (node
[bit
].type
== S_NODE
&&
1406 !strncmp(name
, node
[bit
].name
, strlen(name
))) {
1407 val
= __raw_readl(node
[bit
].regs
+ offset
+ REG_DBG_CTL
);
1412 __raw_writel(val
, node
[bit
].regs
+ offset
+ REG_DBG_CTL
);
1413 node
[bit
].tmout_enabled
= val
;
1421 static ssize_t
itmon_timeout_val_store(struct device
*dev
,
1422 struct device_attribute
*attr
,
1423 const char *buf
, size_t count
)
1426 unsigned int offset
, i
;
1427 unsigned long vec
, bit
= 0;
1428 struct itmon_nodegroup
*group
= NULL
;
1429 struct itmon_nodeinfo
*node
;
1430 struct itmon_platdata
*pdata
= g_itmon
->pdata
;
1432 name
= (char *)kstrndup(buf
, count
, GFP_KERNEL
);
1436 name
[count
- 1] = '\0';
1437 offset
= OFFSET_TMOUT_REG
;
1438 for (i
= 0; i
< ARRAY_SIZE(nodegroup
); i
++) {
1439 group
= &nodegroup
[i
];
1440 node
= group
->nodeinfo
;
1441 vec
= GENMASK(group
->nodesize
, 0);
1443 for_each_set_bit(bit
, &vec
, group
->nodesize
) {
1444 if (node
[bit
].type
== S_NODE
&&
1445 !strncmp(name
, node
[bit
].name
, strlen(name
))) {
1446 __raw_writel(pdata
->sysfs_tmout_val
,
1447 node
[bit
].regs
+ offset
+ REG_TMOUT_INIT_VAL
);
1448 node
[bit
].time_val
= pdata
->sysfs_tmout_val
;
1456 static ssize_t
itmon_timeout_freeze_store(struct device
*dev
,
1457 struct device_attribute
*attr
,
1458 const char *buf
, size_t count
)
1461 unsigned int val
, offset
, i
;
1462 unsigned long vec
, bit
= 0;
1463 struct itmon_nodegroup
*group
= NULL
;
1464 struct itmon_nodeinfo
*node
;
1466 name
= (char *)kstrndup(buf
, count
, GFP_KERNEL
);
1470 name
[count
- 1] = '\0';
1471 offset
= OFFSET_TMOUT_REG
;
1472 for (i
= 0; i
< ARRAY_SIZE(nodegroup
); i
++) {
1473 group
= &nodegroup
[i
];
1474 node
= group
->nodeinfo
;
1475 vec
= GENMASK(group
->nodesize
, 0);
1477 for_each_set_bit(bit
, &vec
, group
->nodesize
) {
1478 if (node
[bit
].type
== S_NODE
&&
1479 !strncmp(name
, node
[bit
].name
, strlen(name
))) {
1480 val
= __raw_readl(node
[bit
].regs
+ offset
+ REG_TMOUT_FRZ_EN
);
1485 __raw_writel(val
, node
[bit
].regs
+ offset
+ REG_TMOUT_FRZ_EN
);
1486 node
[bit
].tmout_frz_enabled
= val
;
1494 static struct device_attribute itmon_timeout_attr
=
1495 __ATTR(timeout_en
, 0644, itmon_timeout_show
, itmon_timeout_store
);
1496 static struct device_attribute itmon_timeout_fix_attr
=
1497 __ATTR(set_val
, 0644, itmon_timeout_fix_val_show
, itmon_timeout_fix_val_store
);
1498 static struct device_attribute itmon_scandump_attr
=
1499 __ATTR(scandump_en
, 0644, itmon_scandump_show
, itmon_scandump_store
);
1500 static struct device_attribute itmon_timeout_val_attr
=
1501 __ATTR(timeout_val
, 0644, itmon_timeout_val_show
, itmon_timeout_val_store
);
1502 static struct device_attribute itmon_timeout_freeze_attr
=
1503 __ATTR(timeout_freeze
, 0644, itmon_timeout_freeze_show
, itmon_timeout_freeze_store
);
1505 static struct attribute
*itmon_sysfs_attrs
[] = {
1506 &itmon_timeout_attr
.attr
,
1507 &itmon_timeout_fix_attr
.attr
,
1508 &itmon_timeout_val_attr
.attr
,
1509 &itmon_timeout_freeze_attr
.attr
,
1510 &itmon_scandump_attr
.attr
,
1514 static struct attribute_group itmon_sysfs_group
= {
1515 .attrs
= itmon_sysfs_attrs
,
1518 static const struct attribute_group
*itmon_sysfs_groups
[] = {
1523 static int __init
itmon_sysfs_init(void)
1527 ret
= subsys_system_register(&itmon_subsys
, itmon_sysfs_groups
);
1529 pr_err("fail to register exynos-snapshop subsys\n");
1533 late_initcall(itmon_sysfs_init
);
1535 static int itmon_logging_panic_handler(struct notifier_block
*nb
,
1536 unsigned long l
, void *buf
)
1538 struct itmon_panic_block
*itmon_panic
= (struct itmon_panic_block
*)nb
;
1539 struct itmon_dev
*itmon
= itmon_panic
->pdev
;
1540 struct itmon_platdata
*pdata
= itmon
->pdata
;
1543 if (!IS_ERR_OR_NULL(itmon
)) {
1544 /* Check error has been logged */
1545 ret
= itmon_search_node(itmon
, NULL
, false);
1547 pr_info("No found error in %s\n", __func__
);
1549 pr_info("Found errors in %s\n", __func__
);
1550 if (pdata
->sysfs_scandump
) {
1551 itmon_switch_scandump();
1559 static int itmon_probe(struct platform_device
*pdev
)
1561 struct itmon_dev
*itmon
;
1562 struct itmon_panic_block
*itmon_panic
= NULL
;
1563 struct itmon_platdata
*pdata
;
1564 struct itmon_nodeinfo
*node
;
1565 unsigned int irq_option
= 0, irq
;
1569 itmon
= devm_kzalloc(&pdev
->dev
, sizeof(struct itmon_dev
), GFP_KERNEL
);
1571 dev_err(&pdev
->dev
, "failed to allocate memory for driver's "
1575 itmon
->dev
= &pdev
->dev
;
1577 spin_lock_init(&itmon
->ctrl_lock
);
1579 pdata
= devm_kzalloc(&pdev
->dev
, sizeof(struct itmon_platdata
), GFP_KERNEL
);
1581 dev_err(&pdev
->dev
, "failed to allocate memory for driver's "
1585 itmon
->pdata
= pdata
;
1586 itmon
->pdata
->masterinfo
= masterinfo
;
1587 itmon
->pdata
->rpathinfo
= rpathinfo
;
1588 itmon
->pdata
->nodegroup
= nodegroup
;
1590 for (i
= 0; i
< ARRAY_SIZE(nodegroup
); i
++) {
1591 dev_name
= nodegroup
[i
].name
;
1592 node
= nodegroup
[i
].nodeinfo
;
1594 if (nodegroup
[i
].phy_regs
) {
1595 nodegroup
[i
].regs
= devm_ioremap_nocache(&pdev
->dev
,
1596 nodegroup
[i
].phy_regs
, SZ_16K
);
1597 if (nodegroup
[i
].regs
== NULL
) {
1598 dev_err(&pdev
->dev
, "failed to claim register region - %s\n",
1604 if (initial_multi_irq_enable
)
1605 irq_option
= IRQF_GIC_MULTI_TARGET
;
1607 irq
= irq_of_parse_and_map(pdev
->dev
.of_node
, i
);
1608 nodegroup
[i
].irq
= irq
;
1610 ret
= devm_request_irq(&pdev
->dev
, irq
,
1611 itmon_irq_handler
, irq_option
, dev_name
, itmon
);
1613 dev_err(&pdev
->dev
, "failed to request irq - %s\n", dev_name
);
1616 dev_err(&pdev
->dev
, "success to register request irq%u - %s\n", irq
, dev_name
);
1619 for (j
= 0; j
< nodegroup
[i
].nodesize
; j
++) {
1620 node
[j
].regs
= devm_ioremap_nocache(&pdev
->dev
, node
[j
].phy_regs
, SZ_16K
);
1621 if (node
[j
].regs
== NULL
) {
1622 dev_err(&pdev
->dev
, "failed to claim register region - %s\n",
1629 itmon_panic
= devm_kzalloc(&pdev
->dev
, sizeof(struct itmon_panic_block
),
1633 dev_err(&pdev
->dev
, "failed to allocate memory for driver's "
1634 "panic handler data\n");
1636 itmon_panic
->nb_panic_block
.notifier_call
= itmon_logging_panic_handler
;
1637 itmon_panic
->pdev
= itmon
;
1638 atomic_notifier_chain_register(&panic_notifier_list
,
1639 &itmon_panic
->nb_panic_block
);
1642 platform_set_drvdata(pdev
, itmon
);
1644 INIT_LIST_HEAD(&pdata
->tracelist
[BUS_DATA
]);
1645 INIT_LIST_HEAD(&pdata
->tracelist
[BUS_PERI
]);
1647 pdata
->crash_in_progress
= false;
1648 itmon_init(itmon
, true);
1651 pdata
->probed
= true;
1653 dev_info(&pdev
->dev
, "success to probe Exynos ITMON driver\n");
1658 static int itmon_remove(struct platform_device
*pdev
)
1660 platform_set_drvdata(pdev
, NULL
);
1664 #ifdef CONFIG_PM_SLEEP
1665 static int itmon_suspend(struct device
*dev
)
1670 static int itmon_resume(struct device
*dev
)
1672 struct platform_device
*pdev
= to_platform_device(dev
);
1673 struct itmon_dev
*itmon
= platform_get_drvdata(pdev
);
1674 struct itmon_platdata
*pdata
= itmon
->pdata
;
1676 /* re-enable ITMON if cp-crash progress is not starting */
1677 if (!pdata
->crash_in_progress
)
1678 itmon_init(itmon
, true);
1683 static SIMPLE_DEV_PM_OPS(itmon_pm_ops
, itmon_suspend
, itmon_resume
);
1684 #define ITMON_PM (itmon_pm_ops)
1686 #define ITM_ONPM NULL
1689 static struct platform_driver exynos_itmon_driver
= {
1690 .probe
= itmon_probe
,
1691 .remove
= itmon_remove
,
1693 .name
= "exynos-itmon",
1694 .of_match_table
= itmon_dt_match
,
1695 .pm
= &itmon_pm_ops
,
1699 module_platform_driver(exynos_itmon_driver
);
1701 MODULE_DESCRIPTION("Samsung Exynos ITMON DRIVER");
1702 MODULE_AUTHOR("Hosung Kim <hosung0.kim@samsung.com");
1703 MODULE_LICENSE("GPL v2");
1704 MODULE_ALIAS("platform:exynos-itmon");