tegra20.c 20 KB

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