tegra20.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
  4. */
  5. #include <linux/bitfield.h>
  6. #include <linux/delay.h>
  7. #include <linux/device.h>
  8. #include <linux/mutex.h>
  9. #include <linux/of.h>
  10. #include <linux/slab.h>
  11. #include <linux/string.h>
  12. #include <dt-bindings/memory/tegra20-mc.h>
  13. #include "mc.h"
  14. #define MC_STAT_CONTROL 0x90
  15. #define MC_STAT_EMC_CLOCK_LIMIT 0xa0
  16. #define MC_STAT_EMC_CLOCKS 0xa4
  17. #define MC_STAT_EMC_CONTROL_0 0xa8
  18. #define MC_STAT_EMC_CONTROL_1 0xac
  19. #define MC_STAT_EMC_COUNT_0 0xb8
  20. #define MC_STAT_EMC_COUNT_1 0xbc
  21. #define MC_STAT_CONTROL_CLIENT_ID GENMASK(13, 8)
  22. #define MC_STAT_CONTROL_EVENT GENMASK(23, 16)
  23. #define MC_STAT_CONTROL_PRI_EVENT GENMASK(25, 24)
  24. #define MC_STAT_CONTROL_FILTER_CLIENT_ENABLE GENMASK(26, 26)
  25. #define MC_STAT_CONTROL_FILTER_PRI GENMASK(29, 28)
  26. #define MC_STAT_CONTROL_PRI_EVENT_HP 0
  27. #define MC_STAT_CONTROL_PRI_EVENT_TM 1
  28. #define MC_STAT_CONTROL_PRI_EVENT_BW 2
  29. #define MC_STAT_CONTROL_FILTER_PRI_DISABLE 0
  30. #define MC_STAT_CONTROL_FILTER_PRI_NO 1
  31. #define MC_STAT_CONTROL_FILTER_PRI_YES 2
  32. #define MC_STAT_CONTROL_EVENT_QUALIFIED 0
  33. #define MC_STAT_CONTROL_EVENT_ANY_READ 1
  34. #define MC_STAT_CONTROL_EVENT_ANY_WRITE 2
  35. #define MC_STAT_CONTROL_EVENT_RD_WR_CHANGE 3
  36. #define MC_STAT_CONTROL_EVENT_SUCCESSIVE 4
  37. #define MC_STAT_CONTROL_EVENT_ARB_BANK_AA 5
  38. #define MC_STAT_CONTROL_EVENT_ARB_BANK_BB 6
  39. #define MC_STAT_CONTROL_EVENT_PAGE_MISS 7
  40. #define MC_STAT_CONTROL_EVENT_AUTO_PRECHARGE 8
  41. #define EMC_GATHER_RST (0 << 8)
  42. #define EMC_GATHER_CLEAR (1 << 8)
  43. #define EMC_GATHER_DISABLE (2 << 8)
  44. #define EMC_GATHER_ENABLE (3 << 8)
  45. #define MC_STAT_SAMPLE_TIME_USEC 16000
  46. /* we store collected statistics as a fixed point values */
  47. #define MC_FX_FRAC_SCALE 100
  48. static DEFINE_MUTEX(tegra20_mc_stat_lock);
  49. struct tegra20_mc_stat_gather {
  50. unsigned int pri_filter;
  51. unsigned int pri_event;
  52. unsigned int result;
  53. unsigned int client;
  54. unsigned int event;
  55. bool client_enb;
  56. };
  57. struct tegra20_mc_stat {
  58. struct tegra20_mc_stat_gather gather0;
  59. struct tegra20_mc_stat_gather gather1;
  60. unsigned int sample_time_usec;
  61. const struct tegra_mc *mc;
  62. };
  63. struct tegra20_mc_client_stat {
  64. unsigned int events;
  65. unsigned int arb_high_prio;
  66. unsigned int arb_timeout;
  67. unsigned int arb_bandwidth;
  68. unsigned int rd_wr_change;
  69. unsigned int successive;
  70. unsigned int page_miss;
  71. unsigned int auto_precharge;
  72. unsigned int arb_bank_aa;
  73. unsigned int arb_bank_bb;
  74. };
  75. static const struct tegra_mc_client tegra20_mc_clients[] = {
  76. {
  77. .id = 0x00,
  78. .name = "display0a",
  79. }, {
  80. .id = 0x01,
  81. .name = "display0ab",
  82. }, {
  83. .id = 0x02,
  84. .name = "display0b",
  85. }, {
  86. .id = 0x03,
  87. .name = "display0bb",
  88. }, {
  89. .id = 0x04,
  90. .name = "display0c",
  91. }, {
  92. .id = 0x05,
  93. .name = "display0cb",
  94. }, {
  95. .id = 0x06,
  96. .name = "display1b",
  97. }, {
  98. .id = 0x07,
  99. .name = "display1bb",
  100. }, {
  101. .id = 0x08,
  102. .name = "eppup",
  103. }, {
  104. .id = 0x09,
  105. .name = "g2pr",
  106. }, {
  107. .id = 0x0a,
  108. .name = "g2sr",
  109. }, {
  110. .id = 0x0b,
  111. .name = "mpeunifbr",
  112. }, {
  113. .id = 0x0c,
  114. .name = "viruv",
  115. }, {
  116. .id = 0x0d,
  117. .name = "avpcarm7r",
  118. }, {
  119. .id = 0x0e,
  120. .name = "displayhc",
  121. }, {
  122. .id = 0x0f,
  123. .name = "displayhcb",
  124. }, {
  125. .id = 0x10,
  126. .name = "fdcdrd",
  127. }, {
  128. .id = 0x11,
  129. .name = "g2dr",
  130. }, {
  131. .id = 0x12,
  132. .name = "host1xdmar",
  133. }, {
  134. .id = 0x13,
  135. .name = "host1xr",
  136. }, {
  137. .id = 0x14,
  138. .name = "idxsrd",
  139. }, {
  140. .id = 0x15,
  141. .name = "mpcorer",
  142. }, {
  143. .id = 0x16,
  144. .name = "mpe_ipred",
  145. }, {
  146. .id = 0x17,
  147. .name = "mpeamemrd",
  148. }, {
  149. .id = 0x18,
  150. .name = "mpecsrd",
  151. }, {
  152. .id = 0x19,
  153. .name = "ppcsahbdmar",
  154. }, {
  155. .id = 0x1a,
  156. .name = "ppcsahbslvr",
  157. }, {
  158. .id = 0x1b,
  159. .name = "texsrd",
  160. }, {
  161. .id = 0x1c,
  162. .name = "vdebsevr",
  163. }, {
  164. .id = 0x1d,
  165. .name = "vdember",
  166. }, {
  167. .id = 0x1e,
  168. .name = "vdemcer",
  169. }, {
  170. .id = 0x1f,
  171. .name = "vdetper",
  172. }, {
  173. .id = 0x20,
  174. .name = "eppu",
  175. }, {
  176. .id = 0x21,
  177. .name = "eppv",
  178. }, {
  179. .id = 0x22,
  180. .name = "eppy",
  181. }, {
  182. .id = 0x23,
  183. .name = "mpeunifbw",
  184. }, {
  185. .id = 0x24,
  186. .name = "viwsb",
  187. }, {
  188. .id = 0x25,
  189. .name = "viwu",
  190. }, {
  191. .id = 0x26,
  192. .name = "viwv",
  193. }, {
  194. .id = 0x27,
  195. .name = "viwy",
  196. }, {
  197. .id = 0x28,
  198. .name = "g2dw",
  199. }, {
  200. .id = 0x29,
  201. .name = "avpcarm7w",
  202. }, {
  203. .id = 0x2a,
  204. .name = "fdcdwr",
  205. }, {
  206. .id = 0x2b,
  207. .name = "host1xw",
  208. }, {
  209. .id = 0x2c,
  210. .name = "ispw",
  211. }, {
  212. .id = 0x2d,
  213. .name = "mpcorew",
  214. }, {
  215. .id = 0x2e,
  216. .name = "mpecswr",
  217. }, {
  218. .id = 0x2f,
  219. .name = "ppcsahbdmaw",
  220. }, {
  221. .id = 0x30,
  222. .name = "ppcsahbslvw",
  223. }, {
  224. .id = 0x31,
  225. .name = "vdebsevw",
  226. }, {
  227. .id = 0x32,
  228. .name = "vdembew",
  229. }, {
  230. .id = 0x33,
  231. .name = "vdetpmw",
  232. },
  233. };
  234. #define TEGRA20_MC_RESET(_name, _control, _status, _reset, _bit) \
  235. { \
  236. .name = #_name, \
  237. .id = TEGRA20_MC_RESET_##_name, \
  238. .control = _control, \
  239. .status = _status, \
  240. .reset = _reset, \
  241. .bit = _bit, \
  242. }
  243. static const struct tegra_mc_reset tegra20_mc_resets[] = {
  244. TEGRA20_MC_RESET(AVPC, 0x100, 0x140, 0x104, 0),
  245. TEGRA20_MC_RESET(DC, 0x100, 0x144, 0x104, 1),
  246. TEGRA20_MC_RESET(DCB, 0x100, 0x148, 0x104, 2),
  247. TEGRA20_MC_RESET(EPP, 0x100, 0x14c, 0x104, 3),
  248. TEGRA20_MC_RESET(2D, 0x100, 0x150, 0x104, 4),
  249. TEGRA20_MC_RESET(HC, 0x100, 0x154, 0x104, 5),
  250. TEGRA20_MC_RESET(ISP, 0x100, 0x158, 0x104, 6),
  251. TEGRA20_MC_RESET(MPCORE, 0x100, 0x15c, 0x104, 7),
  252. TEGRA20_MC_RESET(MPEA, 0x100, 0x160, 0x104, 8),
  253. TEGRA20_MC_RESET(MPEB, 0x100, 0x164, 0x104, 9),
  254. TEGRA20_MC_RESET(MPEC, 0x100, 0x168, 0x104, 10),
  255. TEGRA20_MC_RESET(3D, 0x100, 0x16c, 0x104, 11),
  256. TEGRA20_MC_RESET(PPCS, 0x100, 0x170, 0x104, 12),
  257. TEGRA20_MC_RESET(VDE, 0x100, 0x174, 0x104, 13),
  258. TEGRA20_MC_RESET(VI, 0x100, 0x178, 0x104, 14),
  259. };
  260. static int tegra20_mc_hotreset_assert(struct tegra_mc *mc,
  261. const struct tegra_mc_reset *rst)
  262. {
  263. unsigned long flags;
  264. u32 value;
  265. spin_lock_irqsave(&mc->lock, flags);
  266. value = mc_readl(mc, rst->reset);
  267. mc_writel(mc, value & ~BIT(rst->bit), rst->reset);
  268. spin_unlock_irqrestore(&mc->lock, flags);
  269. return 0;
  270. }
  271. static int tegra20_mc_hotreset_deassert(struct tegra_mc *mc,
  272. const struct tegra_mc_reset *rst)
  273. {
  274. unsigned long flags;
  275. u32 value;
  276. spin_lock_irqsave(&mc->lock, flags);
  277. value = mc_readl(mc, rst->reset);
  278. mc_writel(mc, value | BIT(rst->bit), rst->reset);
  279. spin_unlock_irqrestore(&mc->lock, flags);
  280. return 0;
  281. }
  282. static int tegra20_mc_block_dma(struct tegra_mc *mc,
  283. const struct tegra_mc_reset *rst)
  284. {
  285. unsigned long flags;
  286. u32 value;
  287. spin_lock_irqsave(&mc->lock, flags);
  288. value = mc_readl(mc, rst->control) & ~BIT(rst->bit);
  289. mc_writel(mc, value, rst->control);
  290. spin_unlock_irqrestore(&mc->lock, flags);
  291. return 0;
  292. }
  293. static bool tegra20_mc_dma_idling(struct tegra_mc *mc,
  294. const struct tegra_mc_reset *rst)
  295. {
  296. return mc_readl(mc, rst->status) == 0;
  297. }
  298. static int tegra20_mc_reset_status(struct tegra_mc *mc,
  299. const struct tegra_mc_reset *rst)
  300. {
  301. return (mc_readl(mc, rst->reset) & BIT(rst->bit)) == 0;
  302. }
  303. static int tegra20_mc_unblock_dma(struct tegra_mc *mc,
  304. const struct tegra_mc_reset *rst)
  305. {
  306. unsigned long flags;
  307. u32 value;
  308. spin_lock_irqsave(&mc->lock, flags);
  309. value = mc_readl(mc, rst->control) | BIT(rst->bit);
  310. mc_writel(mc, value, rst->control);
  311. spin_unlock_irqrestore(&mc->lock, flags);
  312. return 0;
  313. }
  314. static const struct tegra_mc_reset_ops tegra20_mc_reset_ops = {
  315. .hotreset_assert = tegra20_mc_hotreset_assert,
  316. .hotreset_deassert = tegra20_mc_hotreset_deassert,
  317. .block_dma = tegra20_mc_block_dma,
  318. .dma_idling = tegra20_mc_dma_idling,
  319. .unblock_dma = tegra20_mc_unblock_dma,
  320. .reset_status = tegra20_mc_reset_status,
  321. };
  322. static int tegra20_mc_icc_set(struct icc_node *src, struct icc_node *dst)
  323. {
  324. /*
  325. * It should be possible to tune arbitration knobs here, but the
  326. * default values are known to work well on all devices. Hence
  327. * nothing to do here so far.
  328. */
  329. return 0;
  330. }
  331. static int tegra20_mc_icc_aggreate(struct icc_node *node, u32 tag, u32 avg_bw,
  332. u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
  333. {
  334. /*
  335. * ISO clients need to reserve extra bandwidth up-front because
  336. * there could be high bandwidth pressure during initial filling
  337. * of the client's FIFO buffers. Secondly, we need to take into
  338. * account impurities of the memory subsystem.
  339. */
  340. if (tag & TEGRA_MC_ICC_TAG_ISO)
  341. peak_bw = tegra_mc_scale_percents(peak_bw, 300);
  342. *agg_avg += avg_bw;
  343. *agg_peak = max(*agg_peak, peak_bw);
  344. return 0;
  345. }
  346. static struct icc_node_data *
  347. tegra20_mc_of_icc_xlate_extended(const struct of_phandle_args *spec, void *data)
  348. {
  349. struct tegra_mc *mc = icc_provider_to_tegra_mc(data);
  350. unsigned int i, idx = spec->args[0];
  351. struct icc_node_data *ndata;
  352. struct icc_node *node;
  353. list_for_each_entry(node, &mc->provider.nodes, node_list) {
  354. if (node->id != idx)
  355. continue;
  356. ndata = kzalloc(sizeof(*ndata), GFP_KERNEL);
  357. if (!ndata)
  358. return ERR_PTR(-ENOMEM);
  359. ndata->node = node;
  360. /* these clients are isochronous by default */
  361. if (strstarts(node->name, "display") ||
  362. strstarts(node->name, "vi"))
  363. ndata->tag = TEGRA_MC_ICC_TAG_ISO;
  364. else
  365. ndata->tag = TEGRA_MC_ICC_TAG_DEFAULT;
  366. return ndata;
  367. }
  368. for (i = 0; i < mc->soc->num_clients; i++) {
  369. if (mc->soc->clients[i].id == idx)
  370. return ERR_PTR(-EPROBE_DEFER);
  371. }
  372. dev_err(mc->dev, "invalid ICC client ID %u\n", idx);
  373. return ERR_PTR(-EINVAL);
  374. }
  375. static const struct tegra_mc_icc_ops tegra20_mc_icc_ops = {
  376. .xlate_extended = tegra20_mc_of_icc_xlate_extended,
  377. .aggregate = tegra20_mc_icc_aggreate,
  378. .set = tegra20_mc_icc_set,
  379. };
  380. static u32 tegra20_mc_stat_gather_control(const struct tegra20_mc_stat_gather *g)
  381. {
  382. u32 control;
  383. control = FIELD_PREP(MC_STAT_CONTROL_EVENT, g->event);
  384. control |= FIELD_PREP(MC_STAT_CONTROL_CLIENT_ID, g->client);
  385. control |= FIELD_PREP(MC_STAT_CONTROL_PRI_EVENT, g->pri_event);
  386. control |= FIELD_PREP(MC_STAT_CONTROL_FILTER_PRI, g->pri_filter);
  387. control |= FIELD_PREP(MC_STAT_CONTROL_FILTER_CLIENT_ENABLE, g->client_enb);
  388. return control;
  389. }
  390. static void tegra20_mc_stat_gather(struct tegra20_mc_stat *stat)
  391. {
  392. u32 clocks, count0, count1, control_0, control_1;
  393. const struct tegra_mc *mc = stat->mc;
  394. control_0 = tegra20_mc_stat_gather_control(&stat->gather0);
  395. control_1 = tegra20_mc_stat_gather_control(&stat->gather1);
  396. /*
  397. * Reset statistic gathers state, select statistics collection mode
  398. * and set clocks counter saturation limit to maximum.
  399. */
  400. mc_writel(mc, 0x00000000, MC_STAT_CONTROL);
  401. mc_writel(mc, control_0, MC_STAT_EMC_CONTROL_0);
  402. mc_writel(mc, control_1, MC_STAT_EMC_CONTROL_1);
  403. mc_writel(mc, 0xffffffff, MC_STAT_EMC_CLOCK_LIMIT);
  404. mc_writel(mc, EMC_GATHER_ENABLE, MC_STAT_CONTROL);
  405. fsleep(stat->sample_time_usec);
  406. mc_writel(mc, EMC_GATHER_DISABLE, MC_STAT_CONTROL);
  407. count0 = mc_readl(mc, MC_STAT_EMC_COUNT_0);
  408. count1 = mc_readl(mc, MC_STAT_EMC_COUNT_1);
  409. clocks = mc_readl(mc, MC_STAT_EMC_CLOCKS);
  410. clocks = max(clocks / 100 / MC_FX_FRAC_SCALE, 1u);
  411. stat->gather0.result = DIV_ROUND_UP(count0, clocks);
  412. stat->gather1.result = DIV_ROUND_UP(count1, clocks);
  413. }
  414. static void tegra20_mc_stat_events(const struct tegra_mc *mc,
  415. const struct tegra_mc_client *client0,
  416. const struct tegra_mc_client *client1,
  417. unsigned int pri_filter,
  418. unsigned int pri_event,
  419. unsigned int event,
  420. unsigned int *result0,
  421. unsigned int *result1)
  422. {
  423. struct tegra20_mc_stat stat = {};
  424. stat.gather0.client = client0 ? client0->id : 0;
  425. stat.gather0.pri_filter = pri_filter;
  426. stat.gather0.client_enb = !!client0;
  427. stat.gather0.pri_event = pri_event;
  428. stat.gather0.event = event;
  429. stat.gather1.client = client1 ? client1->id : 0;
  430. stat.gather1.pri_filter = pri_filter;
  431. stat.gather1.client_enb = !!client1;
  432. stat.gather1.pri_event = pri_event;
  433. stat.gather1.event = event;
  434. stat.sample_time_usec = MC_STAT_SAMPLE_TIME_USEC;
  435. stat.mc = mc;
  436. tegra20_mc_stat_gather(&stat);
  437. *result0 = stat.gather0.result;
  438. *result1 = stat.gather1.result;
  439. }
  440. static void tegra20_mc_collect_stats(const struct tegra_mc *mc,
  441. struct tegra20_mc_client_stat *stats)
  442. {
  443. const struct tegra_mc_client *client0, *client1;
  444. unsigned int i;
  445. /* collect memory controller utilization percent for each client */
  446. for (i = 0; i < mc->soc->num_clients; i += 2) {
  447. client0 = &mc->soc->clients[i];
  448. client1 = &mc->soc->clients[i + 1];
  449. if (i + 1 == mc->soc->num_clients)
  450. client1 = NULL;
  451. tegra20_mc_stat_events(mc, client0, client1,
  452. MC_STAT_CONTROL_FILTER_PRI_DISABLE,
  453. MC_STAT_CONTROL_PRI_EVENT_HP,
  454. MC_STAT_CONTROL_EVENT_QUALIFIED,
  455. &stats[i + 0].events,
  456. &stats[i + 1].events);
  457. }
  458. /* collect more info from active clients */
  459. for (i = 0; i < mc->soc->num_clients; i++) {
  460. unsigned int clienta, clientb = mc->soc->num_clients;
  461. for (client0 = NULL; i < mc->soc->num_clients; i++) {
  462. if (stats[i].events) {
  463. client0 = &mc->soc->clients[i];
  464. clienta = i++;
  465. break;
  466. }
  467. }
  468. for (client1 = NULL; i < mc->soc->num_clients; i++) {
  469. if (stats[i].events) {
  470. client1 = &mc->soc->clients[i];
  471. clientb = i;
  472. break;
  473. }
  474. }
  475. if (!client0 && !client1)
  476. break;
  477. tegra20_mc_stat_events(mc, client0, client1,
  478. MC_STAT_CONTROL_FILTER_PRI_YES,
  479. MC_STAT_CONTROL_PRI_EVENT_HP,
  480. MC_STAT_CONTROL_EVENT_QUALIFIED,
  481. &stats[clienta].arb_high_prio,
  482. &stats[clientb].arb_high_prio);
  483. tegra20_mc_stat_events(mc, client0, client1,
  484. MC_STAT_CONTROL_FILTER_PRI_YES,
  485. MC_STAT_CONTROL_PRI_EVENT_TM,
  486. MC_STAT_CONTROL_EVENT_QUALIFIED,
  487. &stats[clienta].arb_timeout,
  488. &stats[clientb].arb_timeout);
  489. tegra20_mc_stat_events(mc, client0, client1,
  490. MC_STAT_CONTROL_FILTER_PRI_YES,
  491. MC_STAT_CONTROL_PRI_EVENT_BW,
  492. MC_STAT_CONTROL_EVENT_QUALIFIED,
  493. &stats[clienta].arb_bandwidth,
  494. &stats[clientb].arb_bandwidth);
  495. tegra20_mc_stat_events(mc, client0, client1,
  496. MC_STAT_CONTROL_FILTER_PRI_DISABLE,
  497. MC_STAT_CONTROL_PRI_EVENT_HP,
  498. MC_STAT_CONTROL_EVENT_RD_WR_CHANGE,
  499. &stats[clienta].rd_wr_change,
  500. &stats[clientb].rd_wr_change);
  501. tegra20_mc_stat_events(mc, client0, client1,
  502. MC_STAT_CONTROL_FILTER_PRI_DISABLE,
  503. MC_STAT_CONTROL_PRI_EVENT_HP,
  504. MC_STAT_CONTROL_EVENT_SUCCESSIVE,
  505. &stats[clienta].successive,
  506. &stats[clientb].successive);
  507. tegra20_mc_stat_events(mc, client0, client1,
  508. MC_STAT_CONTROL_FILTER_PRI_DISABLE,
  509. MC_STAT_CONTROL_PRI_EVENT_HP,
  510. MC_STAT_CONTROL_EVENT_PAGE_MISS,
  511. &stats[clienta].page_miss,
  512. &stats[clientb].page_miss);
  513. }
  514. }
  515. static void tegra20_mc_printf_percents(struct seq_file *s,
  516. const char *fmt,
  517. unsigned int percents_fx)
  518. {
  519. char percents_str[8];
  520. snprintf(percents_str, ARRAY_SIZE(percents_str), "%3u.%02u%%",
  521. percents_fx / MC_FX_FRAC_SCALE, percents_fx % MC_FX_FRAC_SCALE);
  522. seq_printf(s, fmt, percents_str);
  523. }
  524. static int tegra20_mc_stats_show(struct seq_file *s, void *unused)
  525. {
  526. const struct tegra_mc *mc = dev_get_drvdata(s->private);
  527. struct tegra20_mc_client_stat *stats;
  528. unsigned int i;
  529. stats = kcalloc(mc->soc->num_clients + 1, sizeof(*stats), GFP_KERNEL);
  530. if (!stats)
  531. return -ENOMEM;
  532. mutex_lock(&tegra20_mc_stat_lock);
  533. tegra20_mc_collect_stats(mc, stats);
  534. mutex_unlock(&tegra20_mc_stat_lock);
  535. seq_puts(s, "Memory client Events Timeout High priority Bandwidth ARB RW change Successive Page miss\n");
  536. seq_puts(s, "-----------------------------------------------------------------------------------------------------\n");
  537. for (i = 0; i < mc->soc->num_clients; i++) {
  538. seq_printf(s, "%-14s ", mc->soc->clients[i].name);
  539. /* An event is generated when client performs R/W request. */
  540. tegra20_mc_printf_percents(s, "%-9s", stats[i].events);
  541. /*
  542. * An event is generated based on the timeout (TM) signal
  543. * accompanying a request for arbitration.
  544. */
  545. tegra20_mc_printf_percents(s, "%-10s", stats[i].arb_timeout);
  546. /*
  547. * An event is generated based on the high-priority (HP) signal
  548. * accompanying a request for arbitration.
  549. */
  550. tegra20_mc_printf_percents(s, "%-16s", stats[i].arb_high_prio);
  551. /*
  552. * An event is generated based on the bandwidth (BW) signal
  553. * accompanying a request for arbitration.
  554. */
  555. tegra20_mc_printf_percents(s, "%-16s", stats[i].arb_bandwidth);
  556. /*
  557. * An event is generated when the memory controller switches
  558. * between making a read request to making a write request.
  559. */
  560. tegra20_mc_printf_percents(s, "%-12s", stats[i].rd_wr_change);
  561. /*
  562. * An even generated when the chosen client has wins arbitration
  563. * when it was also the winner at the previous request. If a
  564. * client makes N requests in a row that are honored, SUCCESSIVE
  565. * will be counted (N-1) times. Large values for this event
  566. * imply that if we were patient enough, all of those requests
  567. * could have been coalesced.
  568. */
  569. tegra20_mc_printf_percents(s, "%-13s", stats[i].successive);
  570. /*
  571. * An event is generated when the memory controller detects a
  572. * page miss for the current request.
  573. */
  574. tegra20_mc_printf_percents(s, "%-12s\n", stats[i].page_miss);
  575. }
  576. kfree(stats);
  577. return 0;
  578. }
  579. static int tegra20_mc_probe(struct tegra_mc *mc)
  580. {
  581. debugfs_create_devm_seqfile(mc->dev, "stats", mc->debugfs.root,
  582. tegra20_mc_stats_show);
  583. return 0;
  584. }
  585. static irqreturn_t tegra20_mc_handle_irq(int irq, void *data)
  586. {
  587. struct tegra_mc *mc = data;
  588. unsigned long status;
  589. unsigned int bit;
  590. /* mask all interrupts to avoid flooding */
  591. status = mc_readl(mc, MC_INTSTATUS) & mc->soc->intmask;
  592. if (!status)
  593. return IRQ_NONE;
  594. for_each_set_bit(bit, &status, 32) {
  595. const char *error = tegra_mc_status_names[bit];
  596. const char *direction = "read", *secure = "";
  597. const char *client, *desc;
  598. phys_addr_t addr;
  599. u32 value, reg;
  600. u8 id, type;
  601. switch (BIT(bit)) {
  602. case MC_INT_DECERR_EMEM:
  603. reg = MC_DECERR_EMEM_OTHERS_STATUS;
  604. value = mc_readl(mc, reg);
  605. id = value & mc->soc->client_id_mask;
  606. desc = tegra_mc_error_names[2];
  607. if (value & BIT(31))
  608. direction = "write";
  609. break;
  610. case MC_INT_INVALID_GART_PAGE:
  611. reg = MC_GART_ERROR_REQ;
  612. value = mc_readl(mc, reg);
  613. id = (value >> 1) & mc->soc->client_id_mask;
  614. desc = tegra_mc_error_names[2];
  615. if (value & BIT(0))
  616. direction = "write";
  617. break;
  618. case MC_INT_SECURITY_VIOLATION:
  619. reg = MC_SECURITY_VIOLATION_STATUS;
  620. value = mc_readl(mc, reg);
  621. id = value & mc->soc->client_id_mask;
  622. type = (value & BIT(30)) ? 4 : 3;
  623. desc = tegra_mc_error_names[type];
  624. secure = "secure ";
  625. if (value & BIT(31))
  626. direction = "write";
  627. break;
  628. default:
  629. continue;
  630. }
  631. client = mc->soc->clients[id].name;
  632. addr = mc_readl(mc, reg + sizeof(u32));
  633. dev_err_ratelimited(mc->dev, "%s: %s%s @%pa: %s (%s)\n",
  634. client, secure, direction, &addr, error,
  635. desc);
  636. }
  637. /* clear interrupts */
  638. mc_writel(mc, status, MC_INTSTATUS);
  639. return IRQ_HANDLED;
  640. }
  641. static const struct tegra_mc_ops tegra20_mc_ops = {
  642. .probe = tegra20_mc_probe,
  643. .handle_irq = tegra20_mc_handle_irq,
  644. };
  645. const struct tegra_mc_soc tegra20_mc_soc = {
  646. .clients = tegra20_mc_clients,
  647. .num_clients = ARRAY_SIZE(tegra20_mc_clients),
  648. .num_address_bits = 32,
  649. .client_id_mask = 0x3f,
  650. .intmask = MC_INT_SECURITY_VIOLATION | MC_INT_INVALID_GART_PAGE |
  651. MC_INT_DECERR_EMEM,
  652. .reset_ops = &tegra20_mc_reset_ops,
  653. .resets = tegra20_mc_resets,
  654. .num_resets = ARRAY_SIZE(tegra20_mc_resets),
  655. .icc_ops = &tegra20_mc_icc_ops,
  656. .ops = &tegra20_mc_ops,
  657. };