cmdq_device.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546
  1. #include "cmdq_device.h"
  2. #include "cmdq_core.h"
  3. #include "cmdq_virtual.h"
  4. #ifndef CMDQ_OF_SUPPORT
  5. #include <mach/mt_irq.h>
  6. #endif
  7. /* device tree */
  8. #include <linux/of.h>
  9. #include <linux/of_irq.h>
  10. #include <linux/of_address.h>
  11. #include <linux/io.h>
  12. typedef struct CmdqDeviceStruct {
  13. struct device *pDev;
  14. #ifdef CMDQ_USE_CCF
  15. struct clk *clk_gce;
  16. #endif /* defined(CMDQ_USE_CCF) */
  17. long regBaseVA; /* considering 64 bit kernel, use long */
  18. long regBasePA;
  19. uint32_t irqId;
  20. uint32_t irqSecId;
  21. } CmdqDeviceStruct;
  22. static CmdqDeviceStruct gCmdqDev;
  23. static long gMMSYS_CONFIG_Base_VA;
  24. static long gAPXGPT2Count;
  25. struct device *cmdq_dev_get(void)
  26. {
  27. return gCmdqDev.pDev;
  28. }
  29. uint32_t cmdq_dev_get_irq_id(void)
  30. {
  31. return gCmdqDev.irqId;
  32. }
  33. uint32_t cmdq_dev_get_irq_secure_id(void)
  34. {
  35. return gCmdqDev.irqSecId;
  36. }
  37. long cmdq_dev_get_module_base_VA_GCE(void)
  38. {
  39. return gCmdqDev.regBaseVA;
  40. }
  41. long cmdq_dev_get_module_base_PA_GCE(void)
  42. {
  43. return gCmdqDev.regBasePA;
  44. }
  45. long cmdq_dev_get_module_base_VA_MMSYS_CONFIG(void)
  46. {
  47. return gMMSYS_CONFIG_Base_VA;
  48. }
  49. long cmdq_dev_get_APXGPT2_count(void)
  50. {
  51. return gAPXGPT2Count;
  52. }
  53. void cmdq_dev_init_module_base_VA(void)
  54. {
  55. gMMSYS_CONFIG_Base_VA = 0;
  56. #ifdef CMDQ_OF_SUPPORT
  57. gMMSYS_CONFIG_Base_VA = cmdq_dev_alloc_module_base_VA_by_name("mediatek,mmsys_config");
  58. if (0 == gMMSYS_CONFIG_Base_VA)
  59. gMMSYS_CONFIG_Base_VA = cmdq_dev_alloc_module_base_VA_by_name("mediatek,MMSYS_CONFIG");
  60. #endif
  61. cmdq_mdp_get_func()->initModuleBaseVA();
  62. }
  63. void cmdq_dev_deinit_module_base_VA(void)
  64. {
  65. #ifdef CMDQ_OF_SUPPORT
  66. cmdq_dev_free_module_base_VA(cmdq_dev_get_module_base_VA_MMSYS_CONFIG());
  67. #else
  68. /* do nothing, registers' IOMAP will be destroyed by platform */
  69. #endif
  70. cmdq_mdp_get_func()->deinitModuleBaseVA();
  71. }
  72. long cmdq_dev_alloc_module_base_VA_by_name(const char *name)
  73. {
  74. unsigned long VA;
  75. struct device_node *node = NULL;
  76. node = of_find_compatible_node(NULL, NULL, name);
  77. VA = (unsigned long)of_iomap(node, 0);
  78. CMDQ_LOG("DEV: VA(%s): 0x%lx\n", name, VA);
  79. return VA;
  80. }
  81. void cmdq_dev_free_module_base_VA(const long VA)
  82. {
  83. iounmap((void *)VA);
  84. }
  85. long cmdq_dev_get_gce_node_PA(struct device_node *node, int index)
  86. {
  87. struct resource res;
  88. int status;
  89. long regBasePA = 0L;
  90. do {
  91. status = of_address_to_resource(node, index, &res);
  92. if (status < 0)
  93. break;
  94. regBasePA = (0L | res.start);
  95. } while (0);
  96. return regBasePA;
  97. }
  98. #ifndef CMDQ_USE_CCF
  99. #define IMP_ENABLE_HW_CLOCK(FN_NAME, HW_NAME) \
  100. uint32_t cmdq_dev_enable_clock_##FN_NAME(bool enable) \
  101. { \
  102. return cmdq_dev_enable_mtk_clock(enable, MT_CG_DISP0_##HW_NAME, "CMDQ_MDP_"#HW_NAME); \
  103. }
  104. uint32_t cmdq_dev_enable_mtk_clock(bool enable, cgCLKID gateId, char *name)
  105. {
  106. if (enable)
  107. enable_clock(gateId, name);
  108. else
  109. disable_clock(gateId, name);
  110. return 0;
  111. }
  112. bool cmdq_dev_mtk_clock_is_enable(cgCLKID gateId)
  113. {
  114. return clock_is_on(gateId);
  115. }
  116. IMP_ENABLE_HW_CLOCK(SMI_COMMON, SMI_COMMON);
  117. #else
  118. typedef struct CmdqModuleClock {
  119. struct clk *clk_SMI_COMMON;
  120. struct clk *clk_SMI_LARB0;
  121. struct clk *clk_MTCMOS_DIS;
  122. } CmdqModuleClock;
  123. static CmdqModuleClock gCmdqModuleClock;
  124. #define IMP_ENABLE_HW_CLOCK(FN_NAME, HW_NAME) \
  125. uint32_t cmdq_dev_enable_clock_##FN_NAME(bool enable) \
  126. { \
  127. return cmdq_dev_enable_device_clock(enable, gCmdqModuleClock.clk_##HW_NAME, #HW_NAME "-clk"); \
  128. }
  129. void cmdq_dev_get_module_clock_by_dev(struct device *dev, const char *clkName,
  130. struct clk **clk_module)
  131. {
  132. *clk_module = devm_clk_get(dev, clkName);
  133. if (IS_ERR(*clk_module)) {
  134. /* error status print */
  135. CMDQ_ERR("DEV: cannot get module clock: %s\n", clkName);
  136. } else {
  137. /* message print */
  138. CMDQ_MSG("DEV: get module clock: %s\n", clkName);
  139. }
  140. }
  141. void cmdq_dev_get_module_clock_by_name(const char *name, const char *clkName,
  142. struct clk **clk_module)
  143. {
  144. struct device_node *node = NULL;
  145. node = of_find_compatible_node(NULL, NULL, name);
  146. *clk_module = of_clk_get_by_name(node, clkName);
  147. if (IS_ERR(*clk_module)) {
  148. /* error status print */
  149. CMDQ_ERR("DEV: byName: cannot get module clock: %s\n", clkName);
  150. } else {
  151. /* message print */
  152. CMDQ_MSG("DEV: byName: get module clock: %s\n", clkName);
  153. }
  154. }
  155. uint32_t cmdq_dev_enable_device_clock(bool enable, struct clk *clk_module, const char *clkName)
  156. {
  157. int result = 0;
  158. if (IS_ERR(clk_module))
  159. return PTR_ERR(clk_module);
  160. if (enable) {
  161. result = clk_prepare_enable(clk_module);
  162. CMDQ_MSG("enable clock with module: %s, result: %d\n", clkName, result);
  163. } else {
  164. clk_disable_unprepare(clk_module);
  165. CMDQ_MSG("disable clock with module: %s\n", clkName);
  166. }
  167. return result;
  168. }
  169. bool cmdq_dev_device_clock_is_enable(struct clk *clk_module)
  170. {
  171. return true;
  172. }
  173. /* special handle for MTCMOS */
  174. uint32_t cmdq_dev_enable_clock_SMI_COMMON(bool enable)
  175. {
  176. if (enable) {
  177. cmdq_dev_enable_device_clock(enable, gCmdqModuleClock.clk_MTCMOS_DIS,
  178. "MTCMOS_DIS-clk");
  179. cmdq_dev_enable_device_clock(enable, gCmdqModuleClock.clk_SMI_COMMON,
  180. "SMI_COMMON-clk");
  181. } else {
  182. cmdq_dev_enable_device_clock(enable, gCmdqModuleClock.clk_SMI_COMMON,
  183. "SMI_COMMON-clk");
  184. cmdq_dev_enable_device_clock(enable, gCmdqModuleClock.clk_MTCMOS_DIS,
  185. "MTCMOS_DIS-clk");
  186. }
  187. return 0;
  188. }
  189. #endif /* !defined(CMDQ_USE_CCF) */
  190. IMP_ENABLE_HW_CLOCK(SMI_LARB0, SMI_LARB0);
  191. #ifdef CMDQ_USE_LEGACY
  192. IMP_ENABLE_HW_CLOCK(MUTEX_32K, MUTEX_32K);
  193. #endif
  194. #undef IMP_ENABLE_HW_CLOCK
  195. /* Common Clock Framework */
  196. void cmdq_dev_init_module_clk(void)
  197. {
  198. #if defined(CMDQ_OF_SUPPORT) && defined(CMDQ_USE_CCF)
  199. cmdq_dev_get_module_clock_by_name("mediatek,smi_common", "smi-common",
  200. &gCmdqModuleClock.clk_SMI_COMMON);
  201. cmdq_dev_get_module_clock_by_name("mediatek,smi_common", "smi-larb0",
  202. &gCmdqModuleClock.clk_SMI_LARB0);
  203. cmdq_dev_get_module_clock_by_name("mediatek,smi_common", "mtcmos-dis",
  204. &gCmdqModuleClock.clk_MTCMOS_DIS);
  205. #endif
  206. cmdq_mdp_get_func()->initModuleCLK();
  207. }
  208. void cmdq_dev_enable_gce_clock(bool enable)
  209. {
  210. #ifndef CMDQ_USE_CCF
  211. cmdq_dev_enable_mtk_clock(enable, MT_CG_INFRA_GCE, "mtk_cmdq");
  212. #else
  213. cmdq_dev_enable_device_clock(enable, gCmdqDev.clk_gce, "gce-clk");
  214. #endif
  215. }
  216. bool cmdq_dev_gce_clock_is_enable(void)
  217. {
  218. #ifndef CMDQ_USE_CCF
  219. return cmdq_dev_mtk_clock_is_enable(MT_CG_INFRA_GCE);
  220. #else
  221. return cmdq_dev_device_clock_is_enable(gCmdqDev.clk_gce);
  222. #endif
  223. }
  224. void cmdq_dev_get_module_PA(const char *name, int index, long *startPA, long *endPA)
  225. {
  226. int status;
  227. struct device_node *node = NULL;
  228. struct resource res;
  229. do {
  230. node = of_find_compatible_node(NULL, NULL, name);
  231. if (NULL == node)
  232. break;
  233. status = of_address_to_resource(node, index, &res);
  234. if (status < 0)
  235. break;
  236. *startPA = res.start;
  237. *endPA = res.end;
  238. CMDQ_MSG("DEV: PA(%s): start = 0x%lx, end = 0x%lx\n", name, *startPA, *endPA);
  239. } while (0);
  240. }
  241. /* Get MDP base address to user space */
  242. void cmdq_dev_init_MDP_PA(struct device_node *node)
  243. {
  244. #ifdef CMDQ_OF_SUPPORT
  245. int status;
  246. uint32_t gceDispMutex[2] = {0, 0};
  247. uint32_t *pMDPBaseAddress = cmdq_core_get_whole_DTS_Data()->MDPBaseAddress;
  248. do {
  249. status = of_property_read_u32_array(node, "disp_mutex_reg", gceDispMutex, ARRAY_SIZE(gceDispMutex));
  250. if (status < 0)
  251. break;
  252. pMDPBaseAddress[CMDQ_MDP_PA_BASE_MM_MUTEX] = gceDispMutex[0];
  253. } while (0);
  254. #endif
  255. }
  256. #ifdef CMDQ_OF_SUPPORT
  257. void cmdq_dev_get_subsys_by_name(struct device_node *node, CMDQ_SUBSYS_ENUM subsys,
  258. const char *grp_name, const char *dts_name)
  259. {
  260. int status;
  261. uint32_t gceSubsys[3] = { 0, 0, 0 };
  262. SubsysStruct *gceSubsysStruct = NULL;
  263. do {
  264. if (subsys < 0 || subsys >= CMDQ_SUBSYS_MAX_COUNT)
  265. break;
  266. gceSubsysStruct = cmdq_core_get_whole_DTS_Data()->subsys;
  267. status = of_property_read_u32_array(node, dts_name, gceSubsys, ARRAY_SIZE(gceSubsys));
  268. if (status < 0) {
  269. gceSubsysStruct[subsys].subsysID = -1;
  270. break;
  271. }
  272. gceSubsysStruct[subsys].msb = gceSubsys[0];
  273. gceSubsysStruct[subsys].subsysID = gceSubsys[1];
  274. gceSubsysStruct[subsys].mask = gceSubsys[2];
  275. strncpy(gceSubsysStruct[subsys].grpName, grp_name, CMDQ_SUBSYS_GRPNAME_MAX-1);
  276. } while (0);
  277. }
  278. void cmdq_dev_test_subsys_correctness_impl(CMDQ_SUBSYS_ENUM subsys)
  279. {
  280. SubsysStruct *gceSubsysStruct = NULL;
  281. if (subsys >= 0 && subsys < CMDQ_SUBSYS_MAX_COUNT) {
  282. gceSubsysStruct = cmdq_core_get_whole_DTS_Data()->subsys;
  283. if (gceSubsysStruct[subsys].subsysID != -1) {
  284. /* print subsys information from device tree */
  285. CMDQ_LOG("(%s), msb: 0x%08x, %d, 0x%08x\n",
  286. gceSubsysStruct[subsys].grpName, gceSubsysStruct[subsys].msb,
  287. gceSubsysStruct[subsys].subsysID, gceSubsysStruct[subsys].mask);
  288. }
  289. }
  290. }
  291. #endif
  292. void cmdq_dev_init_subsys(struct device_node *node)
  293. {
  294. #ifdef CMDQ_OF_SUPPORT
  295. #undef DECLARE_CMDQ_SUBSYS
  296. #define DECLARE_CMDQ_SUBSYS(name, val, grp, dts_name) \
  297. { \
  298. cmdq_dev_get_subsys_by_name(node, val, #grp, #dts_name); \
  299. }
  300. #include "cmdq_subsys_common.h"
  301. #undef DECLARE_CMDQ_SUBSYS
  302. #endif
  303. }
  304. #ifdef CMDQ_OF_SUPPORT
  305. void cmdq_dev_get_event_value_by_name(struct device_node *node, CMDQ_EVENT_ENUM event, const char *dts_name)
  306. {
  307. int status;
  308. uint32_t event_value;
  309. do {
  310. if (event < 0 || event >= CMDQ_MAX_HW_EVENT_COUNT)
  311. break;
  312. status = of_property_read_u32(node, dts_name, &event_value);
  313. if (status < 0)
  314. break;
  315. cmdq_core_set_event_table(event, event_value);
  316. } while (0);
  317. }
  318. void cmdq_dev_test_event_correctness_impl(CMDQ_EVENT_ENUM event, const char *event_name)
  319. {
  320. int32_t eventValue = cmdq_core_get_event_value(event);
  321. if (eventValue >= 0 && eventValue < CMDQ_SYNC_TOKEN_MAX) {
  322. /* print event name from device tree */
  323. CMDQ_LOG("%s = %d\n", event_name, eventValue);
  324. }
  325. }
  326. #endif
  327. void cmdq_dev_init_event_table(struct device_node *node)
  328. {
  329. #ifdef CMDQ_OF_SUPPORT
  330. #undef DECLARE_CMDQ_EVENT
  331. #define DECLARE_CMDQ_EVENT(name, val, dts_name) \
  332. { \
  333. cmdq_dev_get_event_value_by_name(node, val, #dts_name); \
  334. }
  335. #include "cmdq_event_common.h"
  336. #undef DECLARE_CMDQ_EVENT
  337. #endif
  338. }
  339. void cmdq_dev_test_dts_correctness(void)
  340. {
  341. #ifdef CMDQ_OF_SUPPORT
  342. #undef DECLARE_CMDQ_EVENT
  343. #define DECLARE_CMDQ_EVENT(name, val, dts_name) \
  344. { \
  345. cmdq_dev_test_event_correctness_impl(val, #name); \
  346. }
  347. #include "cmdq_event_common.h"
  348. #undef DECLARE_CMDQ_EVENT
  349. #undef DECLARE_CMDQ_SUBSYS
  350. #define DECLARE_CMDQ_SUBSYS(name, val, grp, dts_name) \
  351. { \
  352. cmdq_dev_test_subsys_correctness_impl(val); \
  353. }
  354. #include "cmdq_subsys_common.h"
  355. #undef DECLARE_CMDQ_SUBSYS
  356. CMDQ_LOG("APXGPT2_Count = 0x%08lx\n", gAPXGPT2Count);
  357. #endif
  358. }
  359. void cmdq_dev_get_dts_setting(cmdq_dts_setting *dts_setting)
  360. {
  361. int status;
  362. do {
  363. status = of_property_read_u32(gCmdqDev.pDev->of_node,
  364. "max_prefetch_cnt", &dts_setting->prefetch_thread_count);
  365. if (status < 0)
  366. break;
  367. status = of_property_read_u32_array(gCmdqDev.pDev->of_node, "prefetch_size",
  368. dts_setting->prefetch_size, dts_setting->prefetch_thread_count);
  369. if (status < 0)
  370. break;
  371. } while (0);
  372. }
  373. void cmdq_dev_init_resource(CMDQ_DEV_INIT_RESOURCE_CB init_cb)
  374. {
  375. int status, index;
  376. uint32_t count;
  377. do {
  378. status = of_property_read_u32(gCmdqDev.pDev->of_node,
  379. "sram_share_cnt", &count);
  380. if (status < 0)
  381. break;
  382. for (index = 0; index < count; index++) {
  383. uint32_t engine, event;
  384. status = of_property_read_u32_index(gCmdqDev.pDev->of_node, "sram_share_engine",
  385. index, &engine);
  386. if (status < 0)
  387. break;
  388. status = of_property_read_u32_index(gCmdqDev.pDev->of_node, "sram_share_event",
  389. index, &event);
  390. if (status < 0)
  391. break;
  392. if (init_cb != NULL)
  393. init_cb(engine, event);
  394. }
  395. } while (0);
  396. }
  397. void cmdq_dev_init_device_tree(struct device_node *node)
  398. {
  399. int status;
  400. uint32_t apxgpt2_count_value = 0;
  401. gAPXGPT2Count = 0;
  402. cmdq_core_init_DTS_data();
  403. #ifdef CMDQ_OF_SUPPORT
  404. /* init GCE subsys */
  405. cmdq_dev_init_subsys(node);
  406. /* init event table */
  407. cmdq_dev_init_event_table(node);
  408. /* init MDP PA address */
  409. cmdq_dev_init_MDP_PA(node);
  410. do {
  411. status = of_property_read_u32(node, "apxgpt2_count", &apxgpt2_count_value);
  412. if (status < 0)
  413. break;
  414. gAPXGPT2Count = apxgpt2_count_value;
  415. } while (0);
  416. #endif
  417. }
  418. void cmdq_dev_init(struct platform_device *pDevice)
  419. {
  420. struct device_node *node = pDevice->dev.of_node;
  421. /* init cmdq device dependent data */
  422. do {
  423. memset(&gCmdqDev, 0x0, sizeof(CmdqDeviceStruct));
  424. gCmdqDev.pDev = &pDevice->dev;
  425. #ifdef CMDQ_OF_SUPPORT
  426. gCmdqDev.regBaseVA = (unsigned long)of_iomap(node, 0);
  427. gCmdqDev.regBasePA = cmdq_dev_get_gce_node_PA(node, 0);
  428. gCmdqDev.irqId = irq_of_parse_and_map(node, 0);
  429. gCmdqDev.irqSecId = irq_of_parse_and_map(node, 1);
  430. #ifdef CMDQ_USE_CCF
  431. gCmdqDev.clk_gce = devm_clk_get(&pDevice->dev, "GCE");
  432. #endif /* defined(CMDQ_USE_CCF) */
  433. #endif
  434. CMDQ_LOG
  435. ("[CMDQ] platform_dev: dev: %p, PA: %lx, VA: %lx, irqId: %d, irqSecId:%d\n",
  436. gCmdqDev.pDev, gCmdqDev.regBasePA, gCmdqDev.regBaseVA, gCmdqDev.irqId,
  437. gCmdqDev.irqSecId);
  438. } while (0);
  439. /* init module VA */
  440. cmdq_dev_init_module_base_VA();
  441. /* init module clock */
  442. cmdq_dev_init_module_clk();
  443. /* init module PA for instruction count */
  444. cmdq_get_func()->initModulePAStat();
  445. /* init load HW information from device tree */
  446. cmdq_dev_init_device_tree(node);
  447. }
  448. void cmdq_dev_deinit(void)
  449. {
  450. cmdq_dev_deinit_module_base_VA();
  451. /* deinit cmdq device dependent data */
  452. do {
  453. #ifdef CMDQ_OF_SUPPORT
  454. cmdq_dev_free_module_base_VA(cmdq_dev_get_module_base_VA_GCE());
  455. gCmdqDev.regBaseVA = 0;
  456. #else
  457. /* do nothing */
  458. #endif
  459. } while (0);
  460. }