exynos-ppmu.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  1. /*
  2. * exynos_ppmu.c - EXYNOS PPMU (Platform Performance Monitoring Unit) support
  3. *
  4. * Copyright (c) 2014-2015 Samsung Electronics Co., Ltd.
  5. * Author : Chanwoo Choi <cw00.choi@samsung.com>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License version 2 as
  9. * published by the Free Software Foundation.
  10. *
  11. * This driver is based on drivers/devfreq/exynos/exynos_ppmu.c
  12. */
  13. #include <linux/clk.h>
  14. #include <linux/io.h>
  15. #include <linux/kernel.h>
  16. #include <linux/module.h>
  17. #include <linux/of_address.h>
  18. #include <linux/platform_device.h>
  19. #include <linux/suspend.h>
  20. #include <linux/devfreq-event.h>
  21. #include "exynos-ppmu.h"
  22. struct exynos_ppmu_data {
  23. void __iomem *base;
  24. struct clk *clk;
  25. };
  26. struct exynos_ppmu {
  27. struct devfreq_event_dev **edev;
  28. struct devfreq_event_desc *desc;
  29. unsigned int num_events;
  30. struct device *dev;
  31. struct exynos_ppmu_data ppmu;
  32. };
  33. #define PPMU_EVENT(name) \
  34. { "ppmu-event0-"#name, PPMU_PMNCNT0 }, \
  35. { "ppmu-event1-"#name, PPMU_PMNCNT1 }, \
  36. { "ppmu-event2-"#name, PPMU_PMNCNT2 }, \
  37. { "ppmu-event3-"#name, PPMU_PMNCNT3 }
  38. struct __exynos_ppmu_events {
  39. char *name;
  40. int id;
  41. } ppmu_events[] = {
  42. /* For Exynos3250, Exynos4 and Exynos5260 */
  43. PPMU_EVENT(g3d),
  44. PPMU_EVENT(fsys),
  45. /* For Exynos4 SoCs and Exynos3250 */
  46. PPMU_EVENT(dmc0),
  47. PPMU_EVENT(dmc1),
  48. PPMU_EVENT(cpu),
  49. PPMU_EVENT(rightbus),
  50. PPMU_EVENT(leftbus),
  51. PPMU_EVENT(lcd0),
  52. PPMU_EVENT(camif),
  53. /* Only for Exynos3250 and Exynos5260 */
  54. PPMU_EVENT(mfc),
  55. /* Only for Exynos4 SoCs */
  56. PPMU_EVENT(mfc-left),
  57. PPMU_EVENT(mfc-right),
  58. /* Only for Exynos5260 SoCs */
  59. PPMU_EVENT(drex0-s0),
  60. PPMU_EVENT(drex0-s1),
  61. PPMU_EVENT(drex1-s0),
  62. PPMU_EVENT(drex1-s1),
  63. PPMU_EVENT(eagle),
  64. PPMU_EVENT(kfc),
  65. PPMU_EVENT(isp),
  66. PPMU_EVENT(fimc),
  67. PPMU_EVENT(gscl),
  68. PPMU_EVENT(mscl),
  69. PPMU_EVENT(fimd0x),
  70. PPMU_EVENT(fimd1x),
  71. /* Only for Exynos5433 SoCs */
  72. PPMU_EVENT(d0-cpu),
  73. PPMU_EVENT(d0-general),
  74. PPMU_EVENT(d0-rt),
  75. PPMU_EVENT(d1-cpu),
  76. PPMU_EVENT(d1-general),
  77. PPMU_EVENT(d1-rt),
  78. };
  79. static int exynos_ppmu_find_ppmu_id(struct devfreq_event_dev *edev)
  80. {
  81. int i;
  82. for (i = 0; i < ARRAY_SIZE(ppmu_events); i++)
  83. if (!strcmp(edev->desc->name, ppmu_events[i].name))
  84. return ppmu_events[i].id;
  85. return -EINVAL;
  86. }
  87. /*
  88. * The devfreq-event ops structure for PPMU v1.1
  89. */
  90. static int exynos_ppmu_disable(struct devfreq_event_dev *edev)
  91. {
  92. struct exynos_ppmu *info = devfreq_event_get_drvdata(edev);
  93. u32 pmnc;
  94. /* Disable all counters */
  95. __raw_writel(PPMU_CCNT_MASK |
  96. PPMU_PMCNT0_MASK |
  97. PPMU_PMCNT1_MASK |
  98. PPMU_PMCNT2_MASK |
  99. PPMU_PMCNT3_MASK,
  100. info->ppmu.base + PPMU_CNTENC);
  101. /* Disable PPMU */
  102. pmnc = __raw_readl(info->ppmu.base + PPMU_PMNC);
  103. pmnc &= ~PPMU_PMNC_ENABLE_MASK;
  104. __raw_writel(pmnc, info->ppmu.base + PPMU_PMNC);
  105. return 0;
  106. }
  107. static int exynos_ppmu_set_event(struct devfreq_event_dev *edev)
  108. {
  109. struct exynos_ppmu *info = devfreq_event_get_drvdata(edev);
  110. int id = exynos_ppmu_find_ppmu_id(edev);
  111. u32 pmnc, cntens;
  112. if (id < 0)
  113. return id;
  114. /* Enable specific counter */
  115. cntens = __raw_readl(info->ppmu.base + PPMU_CNTENS);
  116. cntens |= (PPMU_CCNT_MASK | (PPMU_ENABLE << id));
  117. __raw_writel(cntens, info->ppmu.base + PPMU_CNTENS);
  118. /* Set the event of Read/Write data count */
  119. __raw_writel(PPMU_RO_DATA_CNT | PPMU_WO_DATA_CNT,
  120. info->ppmu.base + PPMU_BEVTxSEL(id));
  121. /* Reset cycle counter/performance counter and enable PPMU */
  122. pmnc = __raw_readl(info->ppmu.base + PPMU_PMNC);
  123. pmnc &= ~(PPMU_PMNC_ENABLE_MASK
  124. | PPMU_PMNC_COUNTER_RESET_MASK
  125. | PPMU_PMNC_CC_RESET_MASK);
  126. pmnc |= (PPMU_ENABLE << PPMU_PMNC_ENABLE_SHIFT);
  127. pmnc |= (PPMU_ENABLE << PPMU_PMNC_COUNTER_RESET_SHIFT);
  128. pmnc |= (PPMU_ENABLE << PPMU_PMNC_CC_RESET_SHIFT);
  129. __raw_writel(pmnc, info->ppmu.base + PPMU_PMNC);
  130. return 0;
  131. }
  132. static int exynos_ppmu_get_event(struct devfreq_event_dev *edev,
  133. struct devfreq_event_data *edata)
  134. {
  135. struct exynos_ppmu *info = devfreq_event_get_drvdata(edev);
  136. int id = exynos_ppmu_find_ppmu_id(edev);
  137. u32 pmnc, cntenc;
  138. if (id < 0)
  139. return -EINVAL;
  140. /* Disable PPMU */
  141. pmnc = __raw_readl(info->ppmu.base + PPMU_PMNC);
  142. pmnc &= ~PPMU_PMNC_ENABLE_MASK;
  143. __raw_writel(pmnc, info->ppmu.base + PPMU_PMNC);
  144. /* Read cycle count */
  145. edata->total_count = __raw_readl(info->ppmu.base + PPMU_CCNT);
  146. /* Read performance count */
  147. switch (id) {
  148. case PPMU_PMNCNT0:
  149. case PPMU_PMNCNT1:
  150. case PPMU_PMNCNT2:
  151. edata->load_count
  152. = __raw_readl(info->ppmu.base + PPMU_PMNCT(id));
  153. break;
  154. case PPMU_PMNCNT3:
  155. edata->load_count =
  156. ((__raw_readl(info->ppmu.base + PPMU_PMCNT3_HIGH) << 8)
  157. | __raw_readl(info->ppmu.base + PPMU_PMCNT3_LOW));
  158. break;
  159. default:
  160. return -EINVAL;
  161. }
  162. /* Disable specific counter */
  163. cntenc = __raw_readl(info->ppmu.base + PPMU_CNTENC);
  164. cntenc |= (PPMU_CCNT_MASK | (PPMU_ENABLE << id));
  165. __raw_writel(cntenc, info->ppmu.base + PPMU_CNTENC);
  166. dev_dbg(&edev->dev, "%s (event: %ld/%ld)\n", edev->desc->name,
  167. edata->load_count, edata->total_count);
  168. return 0;
  169. }
  170. static const struct devfreq_event_ops exynos_ppmu_ops = {
  171. .disable = exynos_ppmu_disable,
  172. .set_event = exynos_ppmu_set_event,
  173. .get_event = exynos_ppmu_get_event,
  174. };
  175. /*
  176. * The devfreq-event ops structure for PPMU v2.0
  177. */
  178. static int exynos_ppmu_v2_disable(struct devfreq_event_dev *edev)
  179. {
  180. struct exynos_ppmu *info = devfreq_event_get_drvdata(edev);
  181. u32 pmnc, clear;
  182. /* Disable all counters */
  183. clear = (PPMU_CCNT_MASK | PPMU_PMCNT0_MASK | PPMU_PMCNT1_MASK
  184. | PPMU_PMCNT2_MASK | PPMU_PMCNT3_MASK);
  185. __raw_writel(clear, info->ppmu.base + PPMU_V2_FLAG);
  186. __raw_writel(clear, info->ppmu.base + PPMU_V2_INTENC);
  187. __raw_writel(clear, info->ppmu.base + PPMU_V2_CNTENC);
  188. __raw_writel(clear, info->ppmu.base + PPMU_V2_CNT_RESET);
  189. __raw_writel(0x0, info->ppmu.base + PPMU_V2_CIG_CFG0);
  190. __raw_writel(0x0, info->ppmu.base + PPMU_V2_CIG_CFG1);
  191. __raw_writel(0x0, info->ppmu.base + PPMU_V2_CIG_CFG2);
  192. __raw_writel(0x0, info->ppmu.base + PPMU_V2_CIG_RESULT);
  193. __raw_writel(0x0, info->ppmu.base + PPMU_V2_CNT_AUTO);
  194. __raw_writel(0x0, info->ppmu.base + PPMU_V2_CH_EV0_TYPE);
  195. __raw_writel(0x0, info->ppmu.base + PPMU_V2_CH_EV1_TYPE);
  196. __raw_writel(0x0, info->ppmu.base + PPMU_V2_CH_EV2_TYPE);
  197. __raw_writel(0x0, info->ppmu.base + PPMU_V2_CH_EV3_TYPE);
  198. __raw_writel(0x0, info->ppmu.base + PPMU_V2_SM_ID_V);
  199. __raw_writel(0x0, info->ppmu.base + PPMU_V2_SM_ID_A);
  200. __raw_writel(0x0, info->ppmu.base + PPMU_V2_SM_OTHERS_V);
  201. __raw_writel(0x0, info->ppmu.base + PPMU_V2_SM_OTHERS_A);
  202. __raw_writel(0x0, info->ppmu.base + PPMU_V2_INTERRUPT_RESET);
  203. /* Disable PPMU */
  204. pmnc = __raw_readl(info->ppmu.base + PPMU_V2_PMNC);
  205. pmnc &= ~PPMU_PMNC_ENABLE_MASK;
  206. __raw_writel(pmnc, info->ppmu.base + PPMU_V2_PMNC);
  207. return 0;
  208. }
  209. static int exynos_ppmu_v2_set_event(struct devfreq_event_dev *edev)
  210. {
  211. struct exynos_ppmu *info = devfreq_event_get_drvdata(edev);
  212. int id = exynos_ppmu_find_ppmu_id(edev);
  213. u32 pmnc, cntens;
  214. /* Enable all counters */
  215. cntens = __raw_readl(info->ppmu.base + PPMU_V2_CNTENS);
  216. cntens |= (PPMU_CCNT_MASK | (PPMU_ENABLE << id));
  217. __raw_writel(cntens, info->ppmu.base + PPMU_V2_CNTENS);
  218. /* Set the event of Read/Write data count */
  219. switch (id) {
  220. case PPMU_PMNCNT0:
  221. case PPMU_PMNCNT1:
  222. case PPMU_PMNCNT2:
  223. __raw_writel(PPMU_V2_RO_DATA_CNT | PPMU_V2_WO_DATA_CNT,
  224. info->ppmu.base + PPMU_V2_CH_EVx_TYPE(id));
  225. break;
  226. case PPMU_PMNCNT3:
  227. __raw_writel(PPMU_V2_EVT3_RW_DATA_CNT,
  228. info->ppmu.base + PPMU_V2_CH_EVx_TYPE(id));
  229. break;
  230. }
  231. /* Reset cycle counter/performance counter and enable PPMU */
  232. pmnc = __raw_readl(info->ppmu.base + PPMU_V2_PMNC);
  233. pmnc &= ~(PPMU_PMNC_ENABLE_MASK
  234. | PPMU_PMNC_COUNTER_RESET_MASK
  235. | PPMU_PMNC_CC_RESET_MASK
  236. | PPMU_PMNC_CC_DIVIDER_MASK
  237. | PPMU_V2_PMNC_START_MODE_MASK);
  238. pmnc |= (PPMU_ENABLE << PPMU_PMNC_ENABLE_SHIFT);
  239. pmnc |= (PPMU_ENABLE << PPMU_PMNC_COUNTER_RESET_SHIFT);
  240. pmnc |= (PPMU_ENABLE << PPMU_PMNC_CC_RESET_SHIFT);
  241. pmnc |= (PPMU_V2_MODE_MANUAL << PPMU_V2_PMNC_START_MODE_SHIFT);
  242. __raw_writel(pmnc, info->ppmu.base + PPMU_V2_PMNC);
  243. return 0;
  244. }
  245. static int exynos_ppmu_v2_get_event(struct devfreq_event_dev *edev,
  246. struct devfreq_event_data *edata)
  247. {
  248. struct exynos_ppmu *info = devfreq_event_get_drvdata(edev);
  249. int id = exynos_ppmu_find_ppmu_id(edev);
  250. u32 pmnc, cntenc;
  251. u32 pmcnt_high, pmcnt_low;
  252. u64 load_count = 0;
  253. /* Disable PPMU */
  254. pmnc = __raw_readl(info->ppmu.base + PPMU_V2_PMNC);
  255. pmnc &= ~PPMU_PMNC_ENABLE_MASK;
  256. __raw_writel(pmnc, info->ppmu.base + PPMU_V2_PMNC);
  257. /* Read cycle count and performance count */
  258. edata->total_count = __raw_readl(info->ppmu.base + PPMU_V2_CCNT);
  259. switch (id) {
  260. case PPMU_PMNCNT0:
  261. case PPMU_PMNCNT1:
  262. case PPMU_PMNCNT2:
  263. load_count = __raw_readl(info->ppmu.base + PPMU_V2_PMNCT(id));
  264. break;
  265. case PPMU_PMNCNT3:
  266. pmcnt_high = __raw_readl(info->ppmu.base + PPMU_V2_PMCNT3_HIGH);
  267. pmcnt_low = __raw_readl(info->ppmu.base + PPMU_V2_PMCNT3_LOW);
  268. load_count = ((u64)((pmcnt_high & 0xff)) << 32)
  269. + (u64)pmcnt_low;
  270. break;
  271. }
  272. edata->load_count = load_count;
  273. /* Disable all counters */
  274. cntenc = __raw_readl(info->ppmu.base + PPMU_V2_CNTENC);
  275. cntenc |= (PPMU_CCNT_MASK | (PPMU_ENABLE << id));
  276. __raw_writel(cntenc, info->ppmu.base + PPMU_V2_CNTENC);
  277. dev_dbg(&edev->dev, "%25s (load: %ld / %ld)\n", edev->desc->name,
  278. edata->load_count, edata->total_count);
  279. return 0;
  280. }
  281. static const struct devfreq_event_ops exynos_ppmu_v2_ops = {
  282. .disable = exynos_ppmu_v2_disable,
  283. .set_event = exynos_ppmu_v2_set_event,
  284. .get_event = exynos_ppmu_v2_get_event,
  285. };
  286. static const struct of_device_id exynos_ppmu_id_match[] = {
  287. {
  288. .compatible = "samsung,exynos-ppmu",
  289. .data = (void *)&exynos_ppmu_ops,
  290. }, {
  291. .compatible = "samsung,exynos-ppmu-v2",
  292. .data = (void *)&exynos_ppmu_v2_ops,
  293. },
  294. { /* sentinel */ },
  295. };
  296. MODULE_DEVICE_TABLE(of, exynos_ppmu_id_match);
  297. static struct devfreq_event_ops *exynos_bus_get_ops(struct device_node *np)
  298. {
  299. const struct of_device_id *match;
  300. match = of_match_node(exynos_ppmu_id_match, np);
  301. return (struct devfreq_event_ops *)match->data;
  302. }
  303. static int of_get_devfreq_events(struct device_node *np,
  304. struct exynos_ppmu *info)
  305. {
  306. struct devfreq_event_desc *desc;
  307. struct devfreq_event_ops *event_ops;
  308. struct device *dev = info->dev;
  309. struct device_node *events_np, *node;
  310. int i, j, count;
  311. events_np = of_get_child_by_name(np, "events");
  312. if (!events_np) {
  313. dev_err(dev,
  314. "failed to get child node of devfreq-event devices\n");
  315. return -EINVAL;
  316. }
  317. event_ops = exynos_bus_get_ops(np);
  318. count = of_get_child_count(events_np);
  319. desc = devm_kzalloc(dev, sizeof(*desc) * count, GFP_KERNEL);
  320. if (!desc)
  321. return -ENOMEM;
  322. info->num_events = count;
  323. j = 0;
  324. for_each_child_of_node(events_np, node) {
  325. for (i = 0; i < ARRAY_SIZE(ppmu_events); i++) {
  326. if (!ppmu_events[i].name)
  327. continue;
  328. if (!of_node_cmp(node->name, ppmu_events[i].name))
  329. break;
  330. }
  331. if (i == ARRAY_SIZE(ppmu_events)) {
  332. dev_warn(dev,
  333. "don't know how to configure events : %s\n",
  334. node->name);
  335. continue;
  336. }
  337. desc[j].ops = event_ops;
  338. desc[j].driver_data = info;
  339. of_property_read_string(node, "event-name", &desc[j].name);
  340. j++;
  341. }
  342. info->desc = desc;
  343. of_node_put(events_np);
  344. return 0;
  345. }
  346. static int exynos_ppmu_parse_dt(struct exynos_ppmu *info)
  347. {
  348. struct device *dev = info->dev;
  349. struct device_node *np = dev->of_node;
  350. int ret = 0;
  351. if (!np) {
  352. dev_err(dev, "failed to find devicetree node\n");
  353. return -EINVAL;
  354. }
  355. /* Maps the memory mapped IO to control PPMU register */
  356. info->ppmu.base = of_iomap(np, 0);
  357. if (IS_ERR_OR_NULL(info->ppmu.base)) {
  358. dev_err(dev, "failed to map memory region\n");
  359. return -ENOMEM;
  360. }
  361. info->ppmu.clk = devm_clk_get(dev, "ppmu");
  362. if (IS_ERR(info->ppmu.clk)) {
  363. info->ppmu.clk = NULL;
  364. dev_warn(dev, "cannot get PPMU clock\n");
  365. }
  366. ret = of_get_devfreq_events(np, info);
  367. if (ret < 0) {
  368. dev_err(dev, "failed to parse exynos ppmu dt node\n");
  369. goto err;
  370. }
  371. return 0;
  372. err:
  373. iounmap(info->ppmu.base);
  374. return ret;
  375. }
  376. static int exynos_ppmu_probe(struct platform_device *pdev)
  377. {
  378. struct exynos_ppmu *info;
  379. struct devfreq_event_dev **edev;
  380. struct devfreq_event_desc *desc;
  381. int i, ret = 0, size;
  382. info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
  383. if (!info)
  384. return -ENOMEM;
  385. info->dev = &pdev->dev;
  386. /* Parse dt data to get resource */
  387. ret = exynos_ppmu_parse_dt(info);
  388. if (ret < 0) {
  389. dev_err(&pdev->dev,
  390. "failed to parse devicetree for resource\n");
  391. return ret;
  392. }
  393. desc = info->desc;
  394. size = sizeof(struct devfreq_event_dev *) * info->num_events;
  395. info->edev = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
  396. if (!info->edev) {
  397. dev_err(&pdev->dev,
  398. "failed to allocate memory devfreq-event devices\n");
  399. ret = -ENOMEM;
  400. goto err;
  401. }
  402. edev = info->edev;
  403. platform_set_drvdata(pdev, info);
  404. for (i = 0; i < info->num_events; i++) {
  405. edev[i] = devm_devfreq_event_add_edev(&pdev->dev, &desc[i]);
  406. if (IS_ERR(edev[i])) {
  407. ret = PTR_ERR(edev[i]);
  408. dev_err(&pdev->dev,
  409. "failed to add devfreq-event device\n");
  410. goto err;
  411. }
  412. }
  413. clk_prepare_enable(info->ppmu.clk);
  414. return 0;
  415. err:
  416. iounmap(info->ppmu.base);
  417. return ret;
  418. }
  419. static int exynos_ppmu_remove(struct platform_device *pdev)
  420. {
  421. struct exynos_ppmu *info = platform_get_drvdata(pdev);
  422. clk_disable_unprepare(info->ppmu.clk);
  423. iounmap(info->ppmu.base);
  424. return 0;
  425. }
  426. static struct platform_driver exynos_ppmu_driver = {
  427. .probe = exynos_ppmu_probe,
  428. .remove = exynos_ppmu_remove,
  429. .driver = {
  430. .name = "exynos-ppmu",
  431. .of_match_table = exynos_ppmu_id_match,
  432. },
  433. };
  434. module_platform_driver(exynos_ppmu_driver);
  435. MODULE_DESCRIPTION("Exynos PPMU(Platform Performance Monitoring Unit) driver");
  436. MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
  437. MODULE_LICENSE("GPL");