tsens-dbg.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. /* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  2. *
  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 <asm/arch_timer.h>
  14. #include <linux/platform_device.h>
  15. #include "tsens.h"
  16. #include "tsens-mtc.h"
  17. /* debug defines */
  18. #define TSENS_DBG_BUS_ID_0 0
  19. #define TSENS_DBG_BUS_ID_1 1
  20. #define TSENS_DBG_BUS_ID_2 2
  21. #define TSENS_DBG_BUS_ID_15 15
  22. #define TSENS_DEBUG_LOOP_COUNT_ID_0 2
  23. #define TSENS_DEBUG_LOOP_COUNT 5
  24. #define TSENS_DEBUG_STATUS_REG_START 10
  25. #define TSENS_DEBUG_OFFSET_RANGE 16
  26. #define TSENS_DEBUG_OFFSET_WORD1 0x4
  27. #define TSENS_DEBUG_OFFSET_WORD2 0x8
  28. #define TSENS_DEBUG_OFFSET_WORD3 0xc
  29. #define TSENS_DEBUG_OFFSET_ROW 0x10
  30. #define TSENS_DEBUG_DECIDEGC -950
  31. #define TSENS_DEBUG_CYCLE_MS 64
  32. #define TSENS_DEBUG_POLL_MS 200
  33. #define TSENS_DEBUG_BUS_ID2_MIN_CYCLE 50
  34. #define TSENS_DEBUG_BUS_ID2_MAX_CYCLE 51
  35. #define TSENS_DEBUG_ID_MASK_1_4 0xffffffe1
  36. #define DEBUG_SIZE 10
  37. #define TSENS_DEBUG_CONTROL(n) ((n) + 0x130)
  38. #define TSENS_DEBUG_DATA(n) ((n) + 0x134)
  39. struct tsens_dbg_func {
  40. int (*dbg_func)(struct tsens_device *, u32, u32, int *);
  41. };
  42. static ssize_t
  43. zonemask_show(struct device *dev, struct device_attribute *attr, char *buf)
  44. {
  45. struct tsens_device *tmdev = NULL;
  46. tmdev = tsens_controller_is_present();
  47. if (!tmdev) {
  48. pr_err("No TSENS controller present\n");
  49. return -EPROBE_DEFER;
  50. }
  51. return snprintf(buf, PAGE_SIZE,
  52. "Zone =%d th1=%d th2=%d\n", tmdev->mtcsys.zone_mtc,
  53. tmdev->mtcsys.th1, tmdev->mtcsys.th2);
  54. }
  55. static ssize_t
  56. zonemask_store(struct device *dev, struct device_attribute *attr,
  57. const char *buf, size_t count)
  58. {
  59. int ret;
  60. struct tsens_device *tmdev = NULL;
  61. tmdev = tsens_controller_is_present();
  62. if (!tmdev) {
  63. pr_err("No TSENS controller present\n");
  64. return -EPROBE_DEFER;
  65. }
  66. ret = sscanf(buf, "%d %d %d", &tmdev->mtcsys.zone_mtc,
  67. &tmdev->mtcsys.th1, &tmdev->mtcsys.th2);
  68. if (ret != TSENS_ZONEMASK_PARAMS) {
  69. pr_err("Invalid command line arguments\n");
  70. count = -EINVAL;
  71. } else {
  72. pr_debug("store zone_mtc=%d th1=%d th2=%d\n",
  73. tmdev->mtcsys.zone_mtc,
  74. tmdev->mtcsys.th1, tmdev->mtcsys.th2);
  75. ret = tsens_set_mtc_zone_sw_mask(tmdev->mtcsys.zone_mtc,
  76. tmdev->mtcsys.th1, tmdev->mtcsys.th2);
  77. if (ret < 0) {
  78. pr_err("Invalid command line arguments\n");
  79. count = -EINVAL;
  80. }
  81. }
  82. return count;
  83. }
  84. static ssize_t
  85. zonelog_show(struct device *dev, struct device_attribute *attr, char *buf)
  86. {
  87. int ret, zlog[TSENS_MTC_ZONE_LOG_SIZE];
  88. struct tsens_device *tmdev = NULL;
  89. tmdev = tsens_controller_is_present();
  90. if (!tmdev) {
  91. pr_err("No TSENS controller present\n");
  92. return -EPROBE_DEFER;
  93. }
  94. ret = tsens_get_mtc_zone_log(tmdev->mtcsys.zone_log, zlog);
  95. if (ret < 0) {
  96. pr_err("Invalid command line arguments\n");
  97. return -EINVAL;
  98. }
  99. return snprintf(buf, PAGE_SIZE,
  100. "Log[0]=%d\nLog[1]=%d\nLog[2]=%d\nLog[3]=%d\nLog[4]=%d\nLog[5]=%d\n",
  101. zlog[0], zlog[1], zlog[2], zlog[3], zlog[4], zlog[5]);
  102. }
  103. static ssize_t
  104. zonelog_store(struct device *dev, struct device_attribute *attr,
  105. const char *buf, size_t count)
  106. {
  107. int ret;
  108. struct tsens_device *tmdev = NULL;
  109. tmdev = tsens_controller_is_present();
  110. if (!tmdev) {
  111. pr_err("No TSENS controller present\n");
  112. return -EPROBE_DEFER;
  113. }
  114. ret = kstrtou32(buf, 0, &tmdev->mtcsys.zone_log);
  115. if (ret < 0) {
  116. pr_err("Invalid command line arguments\n");
  117. return -EINVAL;
  118. }
  119. return count;
  120. }
  121. static ssize_t
  122. zonehist_show(struct device *dev, struct device_attribute *attr, char *buf)
  123. {
  124. int ret, zhist[TSENS_MTC_ZONE_HISTORY_SIZE];
  125. struct tsens_device *tmdev = NULL;
  126. tmdev = tsens_controller_is_present();
  127. if (!tmdev) {
  128. pr_err("No TSENS controller present\n");
  129. return -EPROBE_DEFER;
  130. }
  131. ret = tsens_get_mtc_zone_history(tmdev->mtcsys.zone_hist, zhist);
  132. if (ret < 0) {
  133. pr_err("Invalid command line arguments\n");
  134. return -EINVAL;
  135. }
  136. return snprintf(buf, PAGE_SIZE,
  137. "Cool = %d\nYellow = %d\nRed = %d\n",
  138. zhist[0], zhist[1], zhist[2]);
  139. }
  140. static ssize_t
  141. zonehist_store(struct device *dev, struct device_attribute *attr,
  142. const char *buf, size_t count)
  143. {
  144. int ret;
  145. struct tsens_device *tmdev = NULL;
  146. tmdev = tsens_controller_is_present();
  147. if (!tmdev) {
  148. pr_err("No TSENS controller present\n");
  149. return -EPROBE_DEFER;
  150. }
  151. ret = kstrtou32(buf, 0, &tmdev->mtcsys.zone_hist);
  152. if (ret < 0) {
  153. pr_err("Invalid command line arguments\n");
  154. return -EINVAL;
  155. }
  156. return count;
  157. }
  158. static struct device_attribute tsens_mtc_dev_attr[] = {
  159. __ATTR(zonemask, 0644, zonemask_show, zonemask_store),
  160. __ATTR(zonelog, 0644, zonelog_show, zonelog_store),
  161. __ATTR(zonehist, 0644, zonehist_show, zonehist_store),
  162. };
  163. static struct device_attribute tsens_mtc_dev_attr_V14[] = {
  164. __ATTR(zonemask, 0644, zonemask_show, zonemask_store),
  165. __ATTR(zonelog, 0644, zonelog_show, zonelog_store),
  166. };
  167. static int tsens_dbg_mtc_data(struct tsens_device *data,
  168. u32 id, u32 dbg_type, int *val)
  169. {
  170. int result = 0, i;
  171. struct tsens_device *tmdev = NULL;
  172. struct device_attribute *attr_ptr = NULL;
  173. u32 ver_major;
  174. u32 ver_minor;
  175. u32 num_elem;
  176. tmdev = data;
  177. ver_major = tmdev->ctrl_data->ver_major;
  178. ver_minor = tmdev->ctrl_data->ver_minor;
  179. if (ver_major == 1 && ver_minor == 4) {
  180. attr_ptr = tsens_mtc_dev_attr_V14;
  181. num_elem = ARRAY_SIZE(tsens_mtc_dev_attr_V14);
  182. } else {
  183. attr_ptr = tsens_mtc_dev_attr;
  184. num_elem = ARRAY_SIZE(tsens_mtc_dev_attr);
  185. }
  186. for (i = 0; i < num_elem; i++) {
  187. result = device_create_file(&tmdev->pdev->dev, &attr_ptr[i]);
  188. if (result < 0)
  189. goto error;
  190. }
  191. return result;
  192. error:
  193. for (i--; i >= 0; i--)
  194. device_remove_file(&tmdev->pdev->dev, &attr_ptr[i]);
  195. return result;
  196. }
  197. static int tsens_dbg_log_temp_reads(struct tsens_device *data, u32 id,
  198. u32 dbg_type, int *temp)
  199. {
  200. struct tsens_sensor *sensor;
  201. struct tsens_device *tmdev = NULL;
  202. u32 idx = 0;
  203. if (!data)
  204. return -EINVAL;
  205. pr_debug("%d %d\n", id, dbg_type);
  206. tmdev = data;
  207. sensor = &tmdev->sensor[id];
  208. idx = tmdev->tsens_dbg.sensor_dbg_info[sensor->hw_id].idx;
  209. tmdev->tsens_dbg.sensor_dbg_info[sensor->hw_id].temp[idx%10] = *temp;
  210. tmdev->tsens_dbg.sensor_dbg_info[sensor->hw_id].time_stmp[idx%10] =
  211. sched_clock();
  212. idx++;
  213. tmdev->tsens_dbg.sensor_dbg_info[sensor->hw_id].idx = idx;
  214. return 0;
  215. }
  216. static int tsens_dbg_log_interrupt_timestamp(struct tsens_device *data,
  217. u32 id, u32 dbg_type, int *val)
  218. {
  219. struct tsens_device *tmdev = NULL;
  220. u32 idx = 0;
  221. if (!data)
  222. return -EINVAL;
  223. pr_debug("%d %d\n", id, dbg_type);
  224. tmdev = data;
  225. /* debug */
  226. idx = tmdev->tsens_dbg.irq_idx;
  227. tmdev->tsens_dbg.irq_time_stmp[idx%10] =
  228. sched_clock();
  229. tmdev->tsens_dbg.irq_idx++;
  230. return 0;
  231. }
  232. static int tsens_dbg_log_bus_id_data(struct tsens_device *data,
  233. u32 id, u32 dbg_type, int *val)
  234. {
  235. struct tsens_device *tmdev = NULL;
  236. u32 loop = 0, i = 0;
  237. uint32_t r1, r2, r3, r4, offset = 0;
  238. unsigned int debug_dump;
  239. unsigned int debug_id = 0, cntrl_id = 0;
  240. void __iomem *srot_addr;
  241. void __iomem *controller_id_addr;
  242. void __iomem *debug_id_addr;
  243. void __iomem *debug_data_addr;
  244. if (!data)
  245. return -EINVAL;
  246. pr_debug("%d %d\n", id, dbg_type);
  247. tmdev = data;
  248. controller_id_addr = TSENS_CONTROLLER_ID(tmdev->tsens_tm_addr);
  249. debug_id_addr = TSENS_DEBUG_CONTROL(tmdev->tsens_tm_addr);
  250. debug_data_addr = TSENS_DEBUG_DATA(tmdev->tsens_tm_addr);
  251. srot_addr = TSENS_CTRL_ADDR(tmdev->tsens_srot_addr);
  252. cntrl_id = readl_relaxed(controller_id_addr);
  253. pr_err("Controller_id: 0x%x\n", cntrl_id);
  254. loop = 0;
  255. i = 0;
  256. debug_id = readl_relaxed(debug_id_addr);
  257. writel_relaxed((debug_id | (i << 1) | 1),
  258. TSENS_DEBUG_CONTROL(tmdev->tsens_tm_addr));
  259. while (loop < TSENS_DEBUG_LOOP_COUNT_ID_0) {
  260. debug_dump = readl_relaxed(debug_data_addr);
  261. r1 = readl_relaxed(debug_data_addr);
  262. r2 = readl_relaxed(debug_data_addr);
  263. r3 = readl_relaxed(debug_data_addr);
  264. r4 = readl_relaxed(debug_data_addr);
  265. pr_err("cntrl:%d, bus-id:%d value:0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n",
  266. cntrl_id, i, debug_dump, r1, r2, r3, r4);
  267. loop++;
  268. }
  269. for (i = TSENS_DBG_BUS_ID_1; i <= TSENS_DBG_BUS_ID_15; i++) {
  270. loop = 0;
  271. debug_id = readl_relaxed(debug_id_addr);
  272. debug_id = debug_id & TSENS_DEBUG_ID_MASK_1_4;
  273. writel_relaxed((debug_id | (i << 1) | 1),
  274. TSENS_DEBUG_CONTROL(tmdev->tsens_tm_addr));
  275. while (loop < TSENS_DEBUG_LOOP_COUNT) {
  276. debug_dump = readl_relaxed(debug_data_addr);
  277. pr_err("cntrl:%d, bus-id:%d with value: 0x%x\n",
  278. cntrl_id, i, debug_dump);
  279. if (i == TSENS_DBG_BUS_ID_2)
  280. usleep_range(
  281. TSENS_DEBUG_BUS_ID2_MIN_CYCLE,
  282. TSENS_DEBUG_BUS_ID2_MAX_CYCLE);
  283. loop++;
  284. }
  285. }
  286. pr_err("Start of TSENS TM dump\n");
  287. for (i = 0; i < TSENS_DEBUG_OFFSET_RANGE; i++) {
  288. r1 = readl_relaxed(controller_id_addr + offset);
  289. r2 = readl_relaxed(controller_id_addr + (offset +
  290. TSENS_DEBUG_OFFSET_WORD1));
  291. r3 = readl_relaxed(controller_id_addr + (offset +
  292. TSENS_DEBUG_OFFSET_WORD2));
  293. r4 = readl_relaxed(controller_id_addr + (offset +
  294. TSENS_DEBUG_OFFSET_WORD3));
  295. pr_err("ctrl:%d:0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
  296. cntrl_id, offset, r1, r2, r3, r4);
  297. offset += TSENS_DEBUG_OFFSET_ROW;
  298. }
  299. offset = 0;
  300. pr_err("Start of TSENS SROT dump\n");
  301. for (i = 0; i < TSENS_DEBUG_OFFSET_RANGE; i++) {
  302. r1 = readl_relaxed(srot_addr + offset);
  303. r2 = readl_relaxed(srot_addr + (offset +
  304. TSENS_DEBUG_OFFSET_WORD1));
  305. r3 = readl_relaxed(srot_addr + (offset +
  306. TSENS_DEBUG_OFFSET_WORD2));
  307. r4 = readl_relaxed(srot_addr + (offset +
  308. TSENS_DEBUG_OFFSET_WORD3));
  309. pr_err("ctrl:%d:0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
  310. cntrl_id, offset, r1, r2, r3, r4);
  311. offset += TSENS_DEBUG_OFFSET_ROW;
  312. }
  313. loop = 0;
  314. while (loop < TSENS_DEBUG_LOOP_COUNT) {
  315. offset = TSENS_DEBUG_OFFSET_ROW *
  316. TSENS_DEBUG_STATUS_REG_START;
  317. pr_err("Start of TSENS TM dump %d\n", loop);
  318. /* Limited dump of the registers for the temperature */
  319. for (i = 0; i < TSENS_DEBUG_LOOP_COUNT; i++) {
  320. r1 = readl_relaxed(controller_id_addr + offset);
  321. r2 = readl_relaxed(controller_id_addr +
  322. (offset + TSENS_DEBUG_OFFSET_WORD1));
  323. r3 = readl_relaxed(controller_id_addr +
  324. (offset + TSENS_DEBUG_OFFSET_WORD2));
  325. r4 = readl_relaxed(controller_id_addr +
  326. (offset + TSENS_DEBUG_OFFSET_WORD3));
  327. pr_err("ctrl:%d:0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
  328. cntrl_id, offset, r1, r2, r3, r4);
  329. offset += TSENS_DEBUG_OFFSET_ROW;
  330. }
  331. loop++;
  332. }
  333. return 0;
  334. }
  335. static struct tsens_dbg_func dbg_arr[] = {
  336. [TSENS_DBG_LOG_TEMP_READS] = {tsens_dbg_log_temp_reads},
  337. [TSENS_DBG_LOG_INTERRUPT_TIMESTAMP] = {
  338. tsens_dbg_log_interrupt_timestamp},
  339. [TSENS_DBG_LOG_BUS_ID_DATA] = {tsens_dbg_log_bus_id_data},
  340. [TSENS_DBG_MTC_DATA] = {tsens_dbg_mtc_data},
  341. };
  342. int tsens2xxx_dbg(struct tsens_device *data, u32 id, u32 dbg_type, int *val)
  343. {
  344. if (dbg_type >= TSENS_DBG_LOG_MAX)
  345. return -EINVAL;
  346. dbg_arr[dbg_type].dbg_func(data, id, dbg_type, val);
  347. return 0;
  348. }
  349. EXPORT_SYMBOL(tsens2xxx_dbg);