mjc_kernel_driver.c 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179
  1. #include <linux/init.h>
  2. #include <linux/module.h>
  3. #include <linux/kdev_t.h>
  4. #include <linux/cdev.h>
  5. #include <linux/sched.h>
  6. #include <linux/mm.h>
  7. #include <linux/fs.h>
  8. #include <linux/platform_device.h>
  9. #include <linux/printk.h>
  10. #include <linux/slab.h>
  11. #include <linux/interrupt.h>
  12. #include <asm/uaccess.h>
  13. /* #include <linux/earlysuspend.h> */
  14. #include <mach/irqs.h>
  15. #include <asm/io.h>
  16. #include <m4u.h>
  17. #include <m4u_port.h>
  18. #include <linux/of.h>
  19. #include <linux/of_irq.h>
  20. #include <linux/of_address.h>
  21. #include <mt-plat/sync_write.h>
  22. #ifdef CONFIG_MTK_CLKMGR
  23. #include "mach/mt_clkmgr.h"
  24. #else
  25. #include "linux/clk.h"
  26. #endif
  27. #include "mjc_kernel_driver.h"
  28. #include "mjc_kernel_compat_driver.h"
  29. /* LOG */
  30. #define MJC_ASSERT(x) {if (!(x)) pr_error("MJC assert fail, file:%s, line:%d", __FILE__, __LINE__); }
  31. #define MTK_MJC_DBG
  32. #ifdef MTK_MJC_DBG
  33. #define MJCDBG(string, args...) pr_debug("MJC [pid=%d]"string, current->tgid, ##args)
  34. #else
  35. #define MJCDBG(string, args...)
  36. #endif
  37. #define MTK_MJC_MSG
  38. #ifdef MTK_MJC_MSG
  39. #define MJCMSG(string, args...) pr_debug("MJC [pid=%d]"string, current->tgid, ##args)
  40. #else
  41. #define MJCMSG(string, args...)
  42. #endif
  43. #ifdef CONFIG_FPGA_EARLY_PORTING
  44. #define enable_clock(...)
  45. #define disable_clock(...)
  46. #endif
  47. #define MJC_WriteReg32(addr, data) mt_reg_sync_writel(data, addr)
  48. #define MJC_Reg32(addr) (*(volatile unsigned int *)(addr))
  49. /* Define */
  50. #define MJC_DEVNAME "MJC"
  51. #define MTK_MJC_DEV_MAJOR_NUMBER 168
  52. #define MJC_FORCE_REG_NUM 100
  53. /* variable */
  54. static DEFINE_SPINLOCK(ContextLock);
  55. static DEFINE_SPINLOCK(HWLock);
  56. static MJC_CONTEXT_T grContext; /* spinlock : ContextLock */
  57. static MJC_CONTEXT_T grHWLockContext; /* spinlock : HWLock */
  58. static dev_t mjc_devno = MKDEV(MTK_MJC_DEV_MAJOR_NUMBER, 0);
  59. static struct cdev *g_mjc_cdev;
  60. static struct class *pMjcClass;
  61. static struct device *mjcDevice;
  62. #ifndef CONFIG_MTK_CLKMGR
  63. static struct clk *clk_MM_SMI_COMMON; /* SMI common larb */
  64. static struct clk *clk_MM_LARB4_AXI_ASIF_MM_CLOCK; /* SMI larb4 axi_asif_mm */
  65. static struct clk *clk_MM_LARB4_AXI_ASIF_MJC_CLOCK; /* SMI larb4_axi_asif_mjc */
  66. static struct clk *clk_MJC_SMI_LARB; /* SMI MJC larb */
  67. static struct clk *clk_MJC_TOP_CLK_0;
  68. static struct clk *clk_MJC_TOP_CLK_1;
  69. static struct clk *clk_MJC_TOP_CLK_2;
  70. static struct clk *clk_MJC_LARB4_ASIF;
  71. #endif
  72. unsigned long gulRegister, gu1PaReg, gu1PaSize, gulCGRegister;
  73. int gi4IrqID;
  74. MJC_WRITE_REG_T gfWriteReg[MJC_FORCE_REG_NUM];
  75. /*****************************************************************************
  76. * FUNCTION
  77. * _mjc_CreateEvent
  78. * DESCRIPTION
  79. *
  80. * PARAMETERS
  81. * None.
  82. * RETURNS
  83. * None.
  84. ****************************************************************************/
  85. static int _mjc_CreateEvent(MJC_EVENT_T *a_prParam)
  86. {
  87. wait_queue_head_t *prWaitQueue;
  88. unsigned char *pu1Flag;
  89. prWaitQueue = kmalloc(sizeof(wait_queue_head_t), GFP_ATOMIC);
  90. pu1Flag = kmalloc(sizeof(unsigned char), GFP_ATOMIC);
  91. if (prWaitQueue != 0) {
  92. init_waitqueue_head(prWaitQueue);
  93. a_prParam->pvWaitQueue = (void *)prWaitQueue;
  94. } else {
  95. MJCMSG("[Error]_mjc_CreateEvent() Event wait Queue failed to create\n");
  96. }
  97. if (pu1Flag != 0) {
  98. a_prParam->pvFlag = (void *)pu1Flag;
  99. *((unsigned char *)a_prParam->pvFlag) = 0;
  100. } else {
  101. MJCMSG("[Error]_mjc_CreateEvent() Event flag failed to create\n");
  102. }
  103. return 0;
  104. }
  105. /*****************************************************************************
  106. * FUNCTION
  107. * _mjc_CloseEvent
  108. * DESCRIPTION
  109. *
  110. * PARAMETERS
  111. * None.
  112. * RETURNS
  113. * None.
  114. ****************************************************************************/
  115. static int _mjc_CloseEvent(MJC_EVENT_T *a_prParam)
  116. {
  117. wait_queue_head_t *prWaitQueue;
  118. unsigned char *pu1Flag;
  119. prWaitQueue = (wait_queue_head_t *) a_prParam->pvWaitQueue;
  120. pu1Flag = (unsigned char *)a_prParam->pvFlag;
  121. kfree(prWaitQueue);
  122. kfree(pu1Flag);
  123. a_prParam->pvWaitQueue = 0;
  124. a_prParam->pvFlag = 0;
  125. return 0;
  126. }
  127. /*****************************************************************************
  128. * FUNCTION
  129. * _mjc_WaitEvent
  130. * DESCRIPTION
  131. *
  132. * PARAMETERS
  133. * None.
  134. * RETURNS
  135. * None.
  136. ****************************************************************************/
  137. static int _mjc_WaitEvent(MJC_EVENT_T *a_prParam)
  138. {
  139. wait_queue_head_t *prWaitQueue;
  140. long timeout_jiff;
  141. int i4Status;
  142. prWaitQueue = (wait_queue_head_t *) a_prParam->pvWaitQueue;
  143. timeout_jiff = (a_prParam->u4TimeoutMs) * HZ / 1000;
  144. /* MJCDBG("_mjc_WaitEv(),a_prParam->u4TimeoutMs=%d, timeout = %ld\n",a_prParam->u4TimeoutMs,timeout_jiff); */
  145. if (0 ==
  146. wait_event_interruptible_timeout(*prWaitQueue, *((unsigned char *)a_prParam->pvFlag)
  147. /*g_mflexvideo_interrupt_handler */
  148. , timeout_jiff)) {
  149. i4Status = 1; /* timeout */
  150. } else {
  151. i4Status = 0;
  152. }
  153. *((unsigned char *)a_prParam->pvFlag) = 0;
  154. return i4Status;
  155. }
  156. /*****************************************************************************
  157. * FUNCTION
  158. * _mjc_WaitEvent
  159. * DESCRIPTION
  160. *
  161. * PARAMETERS
  162. * None.
  163. * RETURNS
  164. * None.
  165. ****************************************************************************/
  166. static int _mjc_SetEvent(MJC_EVENT_T *a_prParam)
  167. {
  168. wait_queue_head_t *prWaitQueue;
  169. /* MJCDBG("[MFV]eVideoSetEvent\n"); */
  170. prWaitQueue = (wait_queue_head_t *) a_prParam->pvWaitQueue;
  171. if (a_prParam->pvFlag != NULL)
  172. *((unsigned char *)a_prParam->pvFlag) = 1;
  173. else
  174. MJCMSG("[Error] _mjc_SetEvent() Event flag should not be null\n");
  175. if (prWaitQueue != NULL)
  176. wake_up_interruptible(prWaitQueue);
  177. else
  178. MJCMSG("[[Error] _mjc_SetEvent() Wait Queue should not be null\n");
  179. return 0;
  180. }
  181. /*****************************************************************************
  182. * FUNCTION
  183. * _mjc_WaitEvent
  184. * DESCRIPTION
  185. *
  186. * PARAMETERS
  187. * None.
  188. * RETURNS
  189. * None.
  190. ****************************************************************************/
  191. static void _mjc_m4uConfigPort(void)
  192. {
  193. int u4Status;
  194. M4U_PORT_STRUCT rM4uPort;
  195. rM4uPort.Virtuality = 1;
  196. rM4uPort.Security = 0;
  197. rM4uPort.Distance = 0;
  198. rM4uPort.Direction = 0;
  199. rM4uPort.domain = 3;
  200. rM4uPort.ePortID = M4U_PORT_MJC_MV_RD;
  201. u4Status = m4u_config_port(&rM4uPort);
  202. if (u4Status != 0) {
  203. MJCMSG("[ERROR] m4u_config_port(%d) fail!! status = %d\n", rM4uPort.ePortID,
  204. u4Status);
  205. }
  206. rM4uPort.ePortID = M4U_PORT_MJC_MV_WR;
  207. u4Status = m4u_config_port(&rM4uPort);
  208. if (u4Status != 0) {
  209. MJCMSG("[ERROR] m4u_config_port(%d) fail!! status = %d\n", rM4uPort.ePortID,
  210. u4Status);
  211. }
  212. rM4uPort.ePortID = M4U_PORT_MJC_DMA_RD;
  213. u4Status = m4u_config_port(&rM4uPort);
  214. if (u4Status != 0) {
  215. MJCMSG("[ERROR] m4u_config_port(%d) fail!! status = %d\n", rM4uPort.ePortID,
  216. u4Status);
  217. }
  218. rM4uPort.ePortID = M4U_PORT_MJC_DMA_WR;
  219. u4Status = m4u_config_port(&rM4uPort);
  220. if (u4Status != 0) {
  221. MJCMSG("[ERROR] m4u_config_port(%d) fail!! status = %d\n", rM4uPort.ePortID,
  222. u4Status);
  223. }
  224. }
  225. /*****************************************************************************
  226. * FUNCTION
  227. * mjc_fault_callback
  228. * DESCRIPTION
  229. *
  230. * PARAMETERS
  231. * None.
  232. * RETURNS
  233. * None.
  234. ****************************************************************************/
  235. m4u_callback_ret_t mjc_m4u_fault_callback(int port, unsigned int mva, void *data)
  236. {
  237. MJCMSG("[ERROR] mjc faut call port=%d, mva=0x%x, data=%lx\n", port, mva, (long)data);
  238. MJCMSG("Sys Basic: 0x%x, Status: 0x%x, FS00: 0x%x, RDMA00: 0x%x, RDMA01: 0x%x\n",
  239. MJC_Reg32(gulRegister + 0x4),
  240. MJC_Reg32(gulRegister + 0x70), MJC_Reg32(gulRegister + 0xc00),
  241. MJC_Reg32(gulRegister + 0x100), MJC_Reg32(gulRegister + 0x104));
  242. MJCMSG("ACT FB Address (0x%x,0x%x,0x%x), (0x%x,0x%x,0x%x), (0x%x)\n",
  243. MJC_Reg32(gulRegister + 0xc4c), MJC_Reg32(gulRegister + 0xc50),
  244. MJC_Reg32(gulRegister + 0xc54), MJC_Reg32(gulRegister + 0xc58),
  245. MJC_Reg32(gulRegister + 0xc5c), MJC_Reg32(gulRegister + 0xc60),
  246. MJC_Reg32(gulRegister + 0xc64));
  247. MJCMSG("PLB FB Address (0x%x,0x%x,0x%x), (0x%x,0x%x,0x%x), (0x%x)\n",
  248. MJC_Reg32(gulRegister + 0xc68), MJC_Reg32(gulRegister + 0xc6c),
  249. MJC_Reg32(gulRegister + 0xc70), MJC_Reg32(gulRegister + 0xc74),
  250. MJC_Reg32(gulRegister + 0xc78), MJC_Reg32(gulRegister + 0xc7c),
  251. MJC_Reg32(gulRegister + 0xc80));
  252. MJCMSG("WD Address (0x%x,0x%x)\n",
  253. MJC_Reg32(gulRegister + 0xc3c), MJC_Reg32(gulRegister + 0xc40));
  254. MJCMSG("MV Address BI(0x%x,0x%x), TD(0x%x,0x%x), CUR(0x%x,0x%x), PV(0x%x)\n",
  255. MJC_Reg32(gulRegister + 0xc1c), MJC_Reg32(gulRegister + 0xc20),
  256. MJC_Reg32(gulRegister + 0xc30), MJC_Reg32(gulRegister + 0xc34),
  257. MJC_Reg32(gulRegister + 0xc24), MJC_Reg32(gulRegister + 0xc28),
  258. MJC_Reg32(gulRegister + 0xc2c));
  259. /* MJCMSG("Lab=0x%x, CG=0x%x\n", ioread32((void *)0xf4000100), ioread32((void *)0xf7000000)); */
  260. return M4U_CALLBACK_HANDLED;
  261. }
  262. /*****************************************************************************
  263. * FUNCTION
  264. * mjc_open
  265. * DESCRIPTION
  266. *
  267. * PARAMETERS
  268. * None.
  269. * RETURNS
  270. * None.
  271. ****************************************************************************/
  272. static int mjc_open(struct inode *pInode, struct file *pFile)
  273. {
  274. unsigned long ulFlags;
  275. int ret = 0;
  276. #ifdef CONFIG_FPGA_EARLY_PORTING
  277. struct device_node *node = NULL;
  278. #endif
  279. MJCDBG("mjc_open() pid = %d\n", current->pid);
  280. #ifdef CONFIG_MTK_CLKMGR
  281. /* Gary todo: enable clock */
  282. enable_clock(MT_CG_DISP0_SMI_COMMON, "mjc");
  283. enable_clock(MT_CG_DISP0_LARB4_AXI_ASIF_MM, "mjc");
  284. enable_clock(MT_CG_DISP0_LARB4_AXI_ASIF_MJC, "mjc");
  285. enable_clock(MT_CG_MJC_SMI_LARB, "mjc");
  286. enable_clock(MT_CG_MJC_TOP_GROUP0, "mjc");
  287. enable_clock(MT_CG_MJC_TOP_GROUP1, "mjc");
  288. enable_clock(MT_CG_MJC_TOP_GROUP2, "mjc");
  289. enable_clock(MT_CG_MJC_LARB4_AXI_ASIF, "mjc");
  290. #else
  291. ret = clk_prepare_enable(clk_MM_SMI_COMMON);
  292. if (ret) {
  293. /* print error log & error handling */
  294. MJCMSG("[ERROR] mjc_open() clk_MM_SMI_COMMON is not enabled, ret = %d\n", ret);
  295. }
  296. ret = clk_prepare_enable(clk_MM_LARB4_AXI_ASIF_MM_CLOCK);
  297. if (ret) {
  298. /* print error log & error handling */
  299. MJCMSG("[ERROR] mjc_open() clk_MM_LARB4_AXI_ASIF_MM_CLOCK is not enabled, ret = %d\n", ret);
  300. }
  301. ret = clk_prepare_enable(clk_MM_LARB4_AXI_ASIF_MJC_CLOCK);
  302. if (ret) {
  303. /* print error log & error handling */
  304. MJCMSG("[ERROR] mjc_open() clk_MM_LARB4_AXI_ASIF_MJC_CLOCK is not enabled, ret = %d\n", ret);
  305. }
  306. ret = clk_prepare_enable(clk_MJC_SMI_LARB);
  307. if (ret) {
  308. /* print error log & error handling */
  309. MJCMSG("[ERROR] mjc_open() clk_MJC_SMI_LARB is not enabled, ret = %d\n", ret);
  310. }
  311. ret = clk_prepare_enable(clk_MJC_TOP_CLK_0);
  312. if (ret) {
  313. /* print error log & error handling */
  314. MJCMSG("[ERROR] mjc_open() clk_MJC_TOP_CLK_0 is not enabled, ret = %d\n", ret);
  315. }
  316. ret = clk_prepare_enable(clk_MJC_TOP_CLK_1);
  317. if (ret) {
  318. /* print error log & error handling */
  319. MJCMSG("[ERROR] mjc_open() clk_MJC_TOP_CLK_1 is not enabled, ret = %d\n", ret);
  320. }
  321. ret = clk_prepare_enable(clk_MJC_TOP_CLK_2);
  322. if (ret) {
  323. /* print error log & error handling */
  324. MJCMSG("[ERROR] mjc_open() clk_MJC_TOP_CLK_2 is not enabled, ret = %d\n", ret);
  325. }
  326. ret = clk_prepare_enable(clk_MJC_LARB4_ASIF);
  327. if (ret) {
  328. /* print error log & error handling */
  329. MJCMSG("[ERROR] mjc_open() clk_MJC_LARB4_ASIF is not enabled, ret = %d\n", ret);
  330. }
  331. #endif
  332. #ifdef CONFIG_FPGA_EARLY_PORTING
  333. node = of_find_compatible_node(NULL, NULL, "mediatek,-mjc_config-v1");
  334. gulCGRegister = (unsigned long)of_iomap(node, 0);
  335. MJC_WriteReg32((gulCGRegister+8), 0xffffffff);
  336. #endif
  337. spin_lock_irqsave(&ContextLock, ulFlags);
  338. grContext.rEvent.u4TimeoutMs = 0xFFFFFFFF;
  339. spin_unlock_irqrestore(&ContextLock, ulFlags);
  340. spin_lock_irqsave(&HWLock, ulFlags);
  341. grHWLockContext.rEvent.u4TimeoutMs = 0xFFFFFFFF;
  342. spin_unlock_irqrestore(&HWLock, ulFlags);
  343. _mjc_m4uConfigPort();
  344. m4u_register_fault_callback(M4U_PORT_MJC_MV_RD, mjc_m4u_fault_callback, (void *)0);
  345. m4u_register_fault_callback(M4U_PORT_MJC_MV_WR, mjc_m4u_fault_callback, (void *)0);
  346. m4u_register_fault_callback(M4U_PORT_MJC_DMA_RD, mjc_m4u_fault_callback, (void *)0);
  347. m4u_register_fault_callback(M4U_PORT_MJC_DMA_WR, mjc_m4u_fault_callback, (void *)0);
  348. MJCDBG("Mapping register: 0x%lx, PA:0x%lx, Size:0x%lx, Irq ID:%d\n", gulRegister, gu1PaReg,
  349. gu1PaSize, gi4IrqID);
  350. return 0;
  351. }
  352. /*****************************************************************************
  353. * FUNCTION
  354. * mjc_release
  355. * DESCRIPTION
  356. *
  357. * PARAMETERS
  358. * None.
  359. * RETURNS
  360. * None.
  361. ****************************************************************************/
  362. static int mjc_release(struct inode *pInode, struct file *pFile)
  363. {
  364. MJCDBG("mjc_release() pid = %d\n", current->pid);
  365. m4u_unregister_fault_callback(M4U_PORT_MJC_MV_RD);
  366. m4u_unregister_fault_callback(M4U_PORT_MJC_MV_WR);
  367. m4u_unregister_fault_callback(M4U_PORT_MJC_DMA_RD);
  368. m4u_unregister_fault_callback(M4U_PORT_MJC_DMA_WR);
  369. #ifdef CONFIG_MTK_CLKMGR
  370. /* Gary todo: disable clock */
  371. disable_clock(MT_CG_MJC_SMI_LARB, "mjc");
  372. disable_clock(MT_CG_MJC_TOP_GROUP0, "mjc");
  373. disable_clock(MT_CG_MJC_TOP_GROUP1, "mjc");
  374. disable_clock(MT_CG_MJC_TOP_GROUP2, "mjc");
  375. disable_clock(MT_CG_DISP0_SMI_COMMON, "mjc");
  376. disable_clock(MT_CG_DISP0_LARB4_AXI_ASIF_MJC, "mjc");
  377. disable_clock(MT_CG_DISP0_LARB4_AXI_ASIF_MM, "mjc");
  378. disable_clock(MT_CG_MJC_LARB4_AXI_ASIF, "mjc");
  379. #else
  380. clk_disable_unprepare(clk_MM_SMI_COMMON);
  381. clk_disable_unprepare(clk_MM_LARB4_AXI_ASIF_MM_CLOCK);
  382. clk_disable_unprepare(clk_MM_LARB4_AXI_ASIF_MJC_CLOCK);
  383. clk_disable_unprepare(clk_MJC_SMI_LARB);
  384. clk_disable_unprepare(clk_MJC_TOP_CLK_0);
  385. clk_disable_unprepare(clk_MJC_TOP_CLK_1);
  386. clk_disable_unprepare(clk_MJC_TOP_CLK_2);
  387. clk_disable_unprepare(clk_MJC_LARB4_ASIF);
  388. #endif
  389. return 0;
  390. }
  391. /*****************************************************************************
  392. * FUNCTION
  393. * mjc_ioctl
  394. * DESCRIPTION
  395. *
  396. * PARAMETERS
  397. * None.
  398. * RETURNS
  399. * None.
  400. ****************************************************************************/
  401. static long mjc_ioctl(struct file *pfile, unsigned int u4cmd, unsigned long u4arg)
  402. {
  403. int ret = 0;
  404. int u4FirstUse;
  405. unsigned long ulAdd;
  406. unsigned long ulFlags;
  407. unsigned int u4efuse;
  408. #ifdef CONFIG_MTK_SEGMENT_TEST
  409. unsigned int u4TestValue;
  410. #endif
  411. MJC_IOCTL_LOCK_HW_T rLockHW;
  412. MJC_IOCTL_ISR_T rIsr;
  413. MJC_READ_REG_T rReadReg;
  414. MJC_WRITE_REG_T rWriteReg;
  415. MJC_IOCTL_SRC_CLK_T rSrcClk;
  416. MJC_IOCTL_EFUSE_INFO_T rEFuseInfo;
  417. MJC_IOCTL_REG_INFO_T rRegInfo;
  418. int cnt = 0;
  419. MJCDBG("mjc_ioctl() command:%u\n", u4cmd);
  420. switch (u4cmd) {
  421. case MJC_LOCKHW:
  422. {
  423. MJCDBG("+ mjc_ioctl() MJC_LOCKHW + tid = %d\n", current->pid);
  424. if (copy_from_user
  425. (&rLockHW, (void __user *)u4arg, sizeof(MJC_IOCTL_LOCK_HW_T))) {
  426. MJCMSG("[ERROR] mjc_ioctl() MJC_LOCKHW copy_from_user fail\n");
  427. return -1;
  428. }
  429. if (sizeof(MJC_IOCTL_LOCK_HW_T) != rLockHW.u4StructSize) {
  430. MJCMSG
  431. ("[ERROR] mjc_ioctl() MJC_LOCKHW context size mismatch (user:%d, kernel:%zu)\n",
  432. rLockHW.u4StructSize, sizeof(MJC_IOCTL_LOCK_HW_T));
  433. return -1;
  434. }
  435. spin_lock_irqsave(&HWLock, ulFlags);
  436. if (grHWLockContext.rEvent.u4TimeoutMs == 0xFFFFFFFF) {
  437. grHWLockContext.rEvent.u4TimeoutMs = 1;
  438. u4FirstUse = 1;
  439. } else {
  440. u4FirstUse = 0;
  441. }
  442. spin_unlock_irqrestore(&HWLock, ulFlags);
  443. /* MJCDBG("mjc_ioctl() MJC_LOCKHW start + tid = %d (%d)\n", current->pid,
  444. grHWLockContext.rEvent.u4TimeoutMs); */
  445. if (u4FirstUse == 1) {
  446. _mjc_WaitEvent(&(grHWLockContext.rEvent));
  447. spin_lock_irqsave(&HWLock, ulFlags);
  448. grHWLockContext.rEvent.u4TimeoutMs = 1000;
  449. spin_unlock_irqrestore(&HWLock, ulFlags);
  450. } else {
  451. ret = _mjc_WaitEvent(&(grHWLockContext.rEvent));
  452. }
  453. /* MJCDBG("mjc_ioctl() MJC_LOCKHW end + tid = %d (%d)\n", current->pid,
  454. grHWLockContext.rEvent.u4TimeoutMs); */
  455. if (ret == 1) {
  456. MJCMSG("[ERROR] mjc_ioctl() MJC_LOCKHW HW has been usaged\n");
  457. return -1;
  458. }
  459. /* Gary todo */
  460. enable_irq(gi4IrqID);
  461. MJCDBG("- mjc_ioctl() MJC_LOCKHW + tid = %d\n", current->pid);
  462. }
  463. break;
  464. case MJC_WAITISR:
  465. {
  466. MJCDBG("mjc_ioctl() MJC_WAITISR + tid = %d\n", current->pid);
  467. if (copy_from_user(&rIsr, (void __user *)u4arg, sizeof(MJC_IOCTL_ISR_T))) {
  468. MJCMSG("[ERROR] mjc_ioctl() MJC_WAITISR copy_from_user fail\n");
  469. return -1;
  470. }
  471. if (sizeof(MJC_IOCTL_ISR_T) != rIsr.u4StructSize) {
  472. MJCMSG
  473. ("[ERROR] mjc_ioctl() MJC_WAITISR context size mismatch (user:%d, kernel:%zu)\n",
  474. rIsr.u4StructSize, sizeof(MJC_IOCTL_ISR_T));
  475. return -1;
  476. }
  477. MJCDBG(" isrevent timeout setting (%x, %x)\n", grContext.rEvent.u4TimeoutMs,
  478. rIsr.u4TimeoutMs);
  479. spin_lock_irqsave(&ContextLock, ulFlags);
  480. grContext.rEvent.u4TimeoutMs = rIsr.u4TimeoutMs;
  481. spin_unlock_irqrestore(&ContextLock, ulFlags);
  482. /* MJCDBG(" new isrevent timeout =%x\n", grContext.rEvent.u4TimeoutMs); */
  483. ret = _mjc_WaitEvent(&(grContext.rEvent));
  484. MJCDBG("mjc_ioctl() waitdone MJC_WAITISR TID:%d, ret:%d\n", current->pid,
  485. ret);
  486. if (ret != 0) {
  487. MJCMSG("[ERROR] mjc_ioctl() MJC_WAITISR TimeOut\n");
  488. spin_lock_irqsave(&HWLock, ulFlags);
  489. _mjc_SetEvent(&(grHWLockContext.rEvent));
  490. spin_unlock_irqrestore(&HWLock, ulFlags);
  491. disable_irq_nosync(gi4IrqID);
  492. return -2;
  493. }
  494. }
  495. break;
  496. case MJC_READ_REG:
  497. {
  498. MJCDBG("mjc_ioctl() MJC_READ_REG + tid = %d\n", current->pid);
  499. if (copy_from_user(&rReadReg, (void __user *)u4arg, sizeof(MJC_READ_REG_T))) {
  500. MJCMSG("[ERROR] mjc_ioctl() MJC_READ_REG copy_from_user failed\n");
  501. return -1;
  502. }
  503. if (rReadReg.reg > (gu1PaReg + gu1PaSize) || rReadReg.reg < gu1PaReg) {
  504. MJCMSG
  505. ("[ERROR] MJC_READ_REG, addr invalid, addr min=0x%lx, max=0x%lx, addr=0x%lx\n",
  506. gu1PaReg, (gu1PaReg + gu1PaSize), rReadReg.reg);
  507. return -1;
  508. }
  509. ulAdd = gulRegister + (rReadReg.reg & 0xfff);
  510. rReadReg.val = MJC_Reg32(ulAdd) & rReadReg.mask;
  511. MJCDBG("read 0x%lx (0x%lx)= 0x%x (0x%x)\n", rReadReg.reg, ulAdd,
  512. rReadReg.val, rReadReg.mask);
  513. if (copy_to_user((void __user *)u4arg, &rReadReg, sizeof(MJC_READ_REG_T))) {
  514. MJCMSG("[ERROR] mjc_ioctl() MJC_READ_REG, copy_to_user failed\n");
  515. return -1;
  516. }
  517. }
  518. break;
  519. case MJC_WRITE_REG:
  520. {
  521. MJCDBG("mjc_ioctl() MJC_WRITE_REG + tid = %d\n", current->pid);
  522. if (copy_from_user
  523. (&rWriteReg, (void __user *)u4arg, sizeof(MJC_WRITE_REG_T))) {
  524. MJCMSG("[ERROR] mjc_ioctl() MJC_WRITE_REG copy_from_user failed\n");
  525. return -1;
  526. }
  527. MJCDBG("write 0x%lx = 0x%x (0x%x)\n", rWriteReg.reg, rWriteReg.val,
  528. rWriteReg.mask);
  529. if (rWriteReg.reg > (gu1PaReg + gu1PaSize) || rWriteReg.reg < gu1PaReg) {
  530. MJCMSG
  531. ("[ERROR] MJC_WRITE_REG, addr invalid, addr min=0x%lx, max=0x%lx, addr=0x%lx\n",
  532. gu1PaReg, (gu1PaReg + gu1PaSize), rWriteReg.reg);
  533. return -1;
  534. }
  535. for (cnt = 0; cnt < MJC_FORCE_REG_NUM; cnt++) {
  536. if (gfWriteReg[cnt].reg == 0
  537. || gfWriteReg[cnt].reg == rWriteReg.reg) {
  538. gfWriteReg[cnt].reg = rWriteReg.reg;
  539. gfWriteReg[cnt].val = rWriteReg.val;
  540. gfWriteReg[cnt].mask = rWriteReg.mask;
  541. break;
  542. }
  543. }
  544. ulAdd = gulRegister + (rWriteReg.reg & 0xfff);
  545. MJC_WriteReg32(ulAdd,
  546. ((MJC_Reg32(ulAdd) & ~rWriteReg.mask) |
  547. (rWriteReg.val & rWriteReg.mask)));
  548. }
  549. break;
  550. case MJC_WRITE_REG_TBL:
  551. {
  552. MJCDBG("mjc_ioctl() MJC_WRITE_REG_TBL + tid = %d\n", current->pid);
  553. for (cnt = 0; cnt < MJC_FORCE_REG_NUM; cnt++) {
  554. if (gfWriteReg[cnt].reg == 0)
  555. break;
  556. MJCMSG("s(%lx %x)\n", gfWriteReg[cnt].reg, gfWriteReg[cnt].val);
  557. ulAdd = gulRegister + (gfWriteReg[cnt].reg & 0xfff);
  558. MJC_WriteReg32(ulAdd,
  559. ((MJC_Reg32(ulAdd) & ~gfWriteReg[cnt].mask) |
  560. (gfWriteReg[cnt].val & gfWriteReg[cnt].mask)));
  561. }
  562. }
  563. break;
  564. case MJC_CLEAR_REG_TBL:
  565. {
  566. MJCDBG("mjc_ioctl() MJC_CLEAR_REG_TBL + tid = %d\n", current->pid);
  567. for (cnt = 0; cnt < MJC_FORCE_REG_NUM; cnt++) {
  568. gfWriteReg[cnt].reg = 0;
  569. gfWriteReg[cnt].val = 0;
  570. gfWriteReg[cnt].mask = 0;
  571. }
  572. }
  573. break;
  574. case MJC_SOURCE_CLK:
  575. {
  576. MJCDBG("mjc_ioctl() MJC_SOURCE_CLK + tid = %d\n", current->pid);
  577. if (copy_from_user
  578. (&rSrcClk, (void __user *)u4arg, sizeof(MJC_IOCTL_SRC_CLK_T))) {
  579. MJCMSG("[ERROR] mjc_ioctl() MJC_SOURCE_CLK copy_from_user fail\n");
  580. return -1;
  581. }
  582. if (sizeof(MJC_IOCTL_SRC_CLK_T) != rSrcClk.u4StructSize) {
  583. MJCMSG
  584. ("[ERROR] mjc_ioctl() MJC_SOURCE_CLK context size mismatch (user:%d, kernel:%zu)\n",
  585. rSrcClk.u4StructSize, sizeof(MJC_IOCTL_SRC_CLK_T));
  586. return -1;
  587. }
  588. MJCDBG(" frame rate =%d\n", rSrcClk.u2OutputFramerate);
  589. if (rSrcClk.u2OutputFramerate == 600) { /* frame rate 60 case */
  590. /* clkmux_sel(MT_MUX_MJC, 7, "mjc"); SYSPLL_D5 (218.4) */
  591. } else if (rSrcClk.u2OutputFramerate == 1200) { /* frame rate 120 case */
  592. /* clkmux_sel(MT_MUX_MJC, 1, "mjc"); UNIVPLL_D3 (416) */
  593. } else {
  594. MJCMSG("[ERROR] mjc_ioctl() MJC_SOURCE_CLK fail frame rate : %d\n",
  595. rSrcClk.u2OutputFramerate);
  596. return -1;
  597. }
  598. }
  599. break;
  600. case MJC_EFUSE_INFO:
  601. {
  602. MJCDBG("mjc_ioctl() MJC_EFUSE_INFO + tid = %d\n", current->pid);
  603. if (copy_from_user
  604. (&rEFuseInfo, (void __user *)u4arg, sizeof(MJC_IOCTL_SRC_CLK_T))) {
  605. MJCMSG("[ERROR] mjc_ioctl() MJC_EFUSE_INFO copy_from_user fail\n");
  606. return -1;
  607. }
  608. if (sizeof(MJC_IOCTL_SRC_CLK_T) != rEFuseInfo.u4StructSize) {
  609. MJCMSG
  610. ("[ERROR] mjc_ioctl() MJC_EFUSE_INFO context size mismatch (user:%d, kernel:%ld)\n",
  611. rEFuseInfo.u4StructSize, sizeof(MJC_IOCTL_SRC_CLK_T));
  612. return -1;
  613. }
  614. MJCDBG(" EFUSE_MJC_IDX =%d, EFUSE_MJC_BIT =%d\n",
  615. rEFuseInfo.u1EFuseIndex, rEFuseInfo.u4EFuseBit);
  616. #ifndef CONFIG_MTK_SEGMENT_TEST
  617. u4efuse = get_devinfo_with_index(rEFuseInfo.u1EFuseIndex);
  618. if ((u4efuse & rEFuseInfo.u4EFuseBit) != 0) {
  619. MJCMSG("[ERROR] mjc efuse no support %d\n", u4efuse);
  620. return -1;
  621. }
  622. #else
  623. u4TestValue = MJC_Reg32((gulRegister + 4));
  624. MJCDBG("Pre-Read: 0x%x\n", u4TestValue);
  625. MJC_WriteReg32((gulRegister + 4), 0x123456);
  626. MJC_WriteReg32((gulRegister + 4), 0x123456);
  627. u4TestValue = MJC_Reg32((gulRegister + 4));
  628. MJCDBG("Read: 0x%x\n", u4TestValue);
  629. if (u4TestValue == 0x123456) {
  630. MJCMSG("[MJC efuse] HW enable\n");
  631. } else {
  632. MJCMSG("[MJC efuse] HW disable\n");
  633. return -1;
  634. }
  635. #endif
  636. }
  637. break;
  638. case MJC_REG_INFO:
  639. {
  640. MJCDBG("mjc_ioctl() MJC_REG_INFO + tid = %d\n", current->pid);
  641. if (copy_from_user
  642. (&rRegInfo, (void __user *)u4arg, sizeof(MJC_IOCTL_REG_INFO_T))) {
  643. MJCMSG("[ERROR] mjc_ioctl() MJC_REG_INFO copy_from_user fail\n");
  644. return -1;
  645. }
  646. if (sizeof(MJC_IOCTL_REG_INFO_T) != rRegInfo.u4StructSize) {
  647. MJCMSG
  648. ("[ERROR] mjc_ioctl() MJC_REG_INFO context size mismatch (user:%d, kernel:%zu)\n",
  649. rRegInfo.u4StructSize, sizeof(MJC_IOCTL_REG_INFO_T));
  650. return -1;
  651. }
  652. rRegInfo.ulRegPAddress = gu1PaReg;
  653. rRegInfo.ulRegPSize = gu1PaSize;
  654. MJCDBG(" PA = 0x%lx, PS = 0x%lx\n", rRegInfo.ulRegPAddress,
  655. rRegInfo.ulRegPSize);
  656. if (copy_to_user
  657. ((void __user *)u4arg, &rRegInfo, sizeof(MJC_IOCTL_REG_INFO_T))) {
  658. MJCMSG("[ERROR] mjc_ioctl() MJC_REG_INFO copy_to_user fail\n");
  659. return -1;
  660. }
  661. }
  662. break;
  663. default:
  664. MJCMSG("[ERROR] mjc_ioctl() No such command 0x%x!!\n", u4cmd);
  665. break;
  666. }
  667. return 0;
  668. }
  669. /*****************************************************************************
  670. * FUNCTION
  671. * mjc_mmap
  672. * DESCRIPTION
  673. *
  674. * PARAMETERS
  675. * None.
  676. * RETURNS
  677. * None.
  678. ****************************************************************************/
  679. static int mjc_mmap(struct file *pFile, struct vm_area_struct *pVma)
  680. {
  681. unsigned long ulLength;
  682. unsigned long ulAddr;
  683. MJCDBG("mjc_mmap\n");
  684. MJCMSG("start = 0x%lx, pgoff= 0x%lx vm_end= 0x%lx\n",
  685. pVma->vm_start, pVma->vm_pgoff, pVma->vm_end);
  686. pVma->vm_page_prot = pgprot_noncached(pVma->vm_page_prot);
  687. ulLength = pVma->vm_end - pVma->vm_start;
  688. ulAddr = pVma->vm_pgoff << PAGE_SHIFT;
  689. if ((ulLength > gu1PaSize) || (ulAddr < gu1PaReg) || (ulAddr > gu1PaReg + gu1PaSize)) {
  690. MJCMSG("[ERROR] mmap region error: Length(0x%lx), pfn(0x%lx)\n", ulLength, ulAddr);
  691. return -EAGAIN;
  692. }
  693. if (remap_pfn_range(pVma, pVma->vm_start, pVma->vm_pgoff, ulLength, pVma->vm_page_prot)) {
  694. MJCMSG("[ERROR] MMAP failed!!\n");
  695. return -EAGAIN;
  696. }
  697. return 0;
  698. }
  699. static const struct file_operations g_mjc_fops = {
  700. .owner = THIS_MODULE,
  701. .open = mjc_open,
  702. .release = mjc_release,
  703. .unlocked_ioctl = mjc_ioctl,
  704. .mmap = mjc_mmap,
  705. #if IS_ENABLED(CONFIG_COMPAT)
  706. .compat_ioctl = compat_mjc_ioctl
  707. #endif
  708. };
  709. /*****************************************************************************
  710. * FUNCTION
  711. * mjc_probe
  712. * DESCRIPTION
  713. * 1. Register MJC Device Number.
  714. * 2. Allocate and Initial MJC cdev struct.
  715. * 3. Add MJC device to kernel. (call cdev_add)
  716. * 4. register MJC interrupt
  717. * PARAMETERS
  718. * None.
  719. * RETURNS
  720. * None.
  721. ****************************************************************************/
  722. static irqreturn_t mjc_intr_dlr(int irq, void *dev_id)
  723. {
  724. unsigned long ulFlags;
  725. MJCDBG("mjc_intr_dlr()");
  726. spin_lock_irqsave(&ContextLock, ulFlags);
  727. _mjc_SetEvent(&(grContext.rEvent));
  728. spin_unlock_irqrestore(&ContextLock, ulFlags);
  729. spin_lock_irqsave(&HWLock, ulFlags);
  730. _mjc_SetEvent(&(grHWLockContext.rEvent));
  731. spin_unlock_irqrestore(&HWLock, ulFlags);
  732. /* Gary todo */
  733. disable_irq_nosync(gi4IrqID);
  734. return IRQ_HANDLED;
  735. }
  736. /*****************************************************************************
  737. * FUNCTION
  738. * mjc_probe
  739. * DESCRIPTION
  740. * 1. Register MJC Device Number.
  741. * 2. Allocate and Initial MJC cdev struct.
  742. * 3. Add MJC device to kernel. (call cdev_add)
  743. * 4. register MJC interrupt
  744. * PARAMETERS
  745. * None.
  746. * RETURNS
  747. * None.
  748. ****************************************************************************/
  749. static int mjc_probe(struct platform_device *pDev)
  750. {
  751. struct device_node *node = pDev->dev.of_node;
  752. struct resource res;
  753. int ret;
  754. unsigned long ulFlags;
  755. MJCDBG("mjc_probe()");
  756. ret = register_chrdev_region(mjc_devno, 1, MJC_DEVNAME);
  757. if (ret) {
  758. /*can not get Major number to register device */
  759. MJCMSG("[ERROR] Can't Get Major number for MJC Device\n");
  760. }
  761. g_mjc_cdev = cdev_alloc();
  762. g_mjc_cdev->owner = THIS_MODULE;
  763. g_mjc_cdev->ops = &g_mjc_fops;
  764. ret = cdev_add(g_mjc_cdev, mjc_devno, 1);
  765. /* create /dev/mjc automatically */
  766. pMjcClass = class_create(THIS_MODULE, MJC_DEVNAME);
  767. if (IS_ERR(pMjcClass)) {
  768. ret = PTR_ERR(pMjcClass);
  769. MJCMSG("Unable to create class, err = %d", ret);
  770. return ret;
  771. }
  772. mjcDevice = device_create(pMjcClass, NULL, mjc_devno, NULL, MJC_DEVNAME);
  773. gulRegister = (unsigned long)of_iomap(node, 0);
  774. gi4IrqID = irq_of_parse_and_map(node, 0);
  775. of_address_to_resource(node, 0, &res);
  776. gu1PaReg = res.start;
  777. gu1PaSize = resource_size(&res);
  778. spin_lock_irqsave(&ContextLock, ulFlags);
  779. grContext.rEvent.u4TimeoutMs = 0xFFFFFFFF;
  780. _mjc_CreateEvent(&(grContext.rEvent));
  781. spin_unlock_irqrestore(&ContextLock, ulFlags);
  782. spin_lock_irqsave(&HWLock, ulFlags);
  783. grHWLockContext.rEvent.u4TimeoutMs = 0xFFFFFFFF;
  784. _mjc_CreateEvent(&(grHWLockContext.rEvent));
  785. spin_unlock_irqrestore(&HWLock, ulFlags);
  786. /* register interrupt */
  787. /* level and low */
  788. /* Gary todo: */
  789. if (request_irq(gi4IrqID, (irq_handler_t) mjc_intr_dlr, IRQF_TRIGGER_NONE, MJC_DEVNAME, NULL)
  790. < 0) {
  791. MJCMSG("[ERROR] mjc_probe() error to request dec irq\n");
  792. } else {
  793. MJCDBG("mjc_probe() success to request dec irq\n");
  794. }
  795. disable_irq(gi4IrqID);
  796. #ifndef CONFIG_MTK_CLKMGR
  797. clk_MM_SMI_COMMON = devm_clk_get(&pDev->dev, "smi-common");
  798. if (IS_ERR(clk_MM_SMI_COMMON)) {
  799. MJCMSG("[ERROR] Unable to devm_clk_get MM_SMI_COMMON\n");
  800. return PTR_ERR(clk_MM_SMI_COMMON);
  801. }
  802. clk_MM_LARB4_AXI_ASIF_MM_CLOCK = devm_clk_get(&pDev->dev, "larb4-axi-asif-mm");
  803. if (IS_ERR(clk_MM_LARB4_AXI_ASIF_MM_CLOCK)) {
  804. MJCMSG("[ERROR] Unable to devm_clk_get MM_LARB4_AXI_ASIF_MM_CLOCK\n");
  805. return PTR_ERR(clk_MM_LARB4_AXI_ASIF_MM_CLOCK);
  806. }
  807. clk_MM_LARB4_AXI_ASIF_MJC_CLOCK = devm_clk_get(&pDev->dev, "larb4-axi-asif-mjc");
  808. if (IS_ERR(clk_MM_LARB4_AXI_ASIF_MJC_CLOCK)) {
  809. MJCMSG("[ERROR] Unable to devm_clk_get MM_LARB4_AXI_ASIF_MJC_CLOCK\n");
  810. return PTR_ERR(clk_MM_LARB4_AXI_ASIF_MJC_CLOCK);
  811. }
  812. clk_MJC_SMI_LARB = devm_clk_get(&pDev->dev, "mjc-smi-larb");
  813. if (IS_ERR(clk_MJC_SMI_LARB)) {
  814. MJCMSG("[ERROR] Unable to devm_clk_get MJC_SMI_LARB\n");
  815. return PTR_ERR(clk_MJC_SMI_LARB);
  816. }
  817. clk_MJC_TOP_CLK_0 = devm_clk_get(&pDev->dev, "top-clk-0");
  818. if (IS_ERR(clk_MJC_TOP_CLK_0)) {
  819. MJCMSG("[ERROR] Unable to devm_clk_get MJC_TOP_CLK_0\n");
  820. return PTR_ERR(clk_MJC_TOP_CLK_0);
  821. }
  822. clk_MJC_TOP_CLK_1 = devm_clk_get(&pDev->dev, "top-clk-1");
  823. if (IS_ERR(clk_MJC_TOP_CLK_1)) {
  824. MJCMSG("[ERROR] Unable to devm_clk_get MJC_TOP_CLK_1\n");
  825. return PTR_ERR(clk_MJC_TOP_CLK_1);
  826. }
  827. clk_MJC_TOP_CLK_2 = devm_clk_get(&pDev->dev, "top-clk-2");
  828. if (IS_ERR(clk_MJC_TOP_CLK_2)) {
  829. MJCMSG("[ERROR] Unable to devm_clk_get MJC_TOP_CLK_2\n");
  830. return PTR_ERR(clk_MJC_TOP_CLK_2);
  831. }
  832. clk_MJC_LARB4_ASIF = devm_clk_get(&pDev->dev, "larb4-asif");
  833. if (IS_ERR(clk_MJC_LARB4_ASIF)) {
  834. MJCMSG("[ERROR] Unable to devm_clk_get MJC_LARB4_ASIF\n");
  835. return PTR_ERR(clk_MJC_LARB4_ASIF);
  836. }
  837. #endif
  838. return 0;
  839. }
  840. /*****************************************************************************
  841. * FUNCTION
  842. * mjc_remove
  843. * DESCRIPTION
  844. * 1. Remove mjc device.
  845. * 2. Un-register mjc Device Number.
  846. * 3. Free IRQ
  847. * PARAMETERS
  848. * param1 : [IN] struct platform_device *pdev
  849. * No used in this function.
  850. * RETURNS
  851. * Type: Integer. always zero.
  852. ****************************************************************************/
  853. static int mjc_remove(struct platform_device *pdev)
  854. {
  855. unsigned long ulFlags;
  856. MJCDBG("mjc_remove()\n");
  857. cdev_del(g_mjc_cdev);
  858. unregister_chrdev_region(mjc_devno, 1);
  859. /* Release IRQ */
  860. /* Gary todo: */
  861. free_irq(gi4IrqID, NULL);
  862. /* memory allocated in probe function don't free. */
  863. spin_lock_irqsave(&ContextLock, ulFlags);
  864. _mjc_CloseEvent(&(grContext.rEvent));
  865. spin_unlock_irqrestore(&ContextLock, ulFlags);
  866. spin_lock_irqsave(&HWLock, ulFlags);
  867. _mjc_CloseEvent(&(grHWLockContext.rEvent));
  868. spin_unlock_irqrestore(&HWLock, ulFlags);
  869. return 0;
  870. }
  871. static int mjc_suspend(struct platform_device *pdev, pm_message_t mesg)
  872. {
  873. MJCMSG("mjc_early_suspend, tid = %d\n", current->pid);
  874. MJCDBG("mjc_early_suspend - tid = %d\n", current->pid);
  875. return 0;
  876. }
  877. static int mjc_resume(struct platform_device *pdev)
  878. {
  879. MJCMSG("mjc_late_resume, tid = %d\n", current->pid);
  880. MJCDBG("mjc_late_resume - tid = %d\n", current->pid);
  881. return 0;
  882. }
  883. /*---------------------------------------------------------------------------*/
  884. #ifdef CONFIG_PM
  885. /*---------------------------------------------------------------------------*/
  886. int mjc_pm_suspend(struct device *device)
  887. {
  888. struct platform_device *pdev = to_platform_device(device);
  889. MJCDBG("calling %s()\n", __func__);
  890. BUG_ON(pdev == NULL);
  891. return mjc_suspend(pdev, PMSG_SUSPEND);
  892. }
  893. int mjc_pm_resume(struct device *device)
  894. {
  895. struct platform_device *pdev = to_platform_device(device);
  896. MJCDBG("calling %s()\n", __func__);
  897. BUG_ON(pdev == NULL);
  898. return mjc_resume(pdev);
  899. }
  900. static int mjc_pm_restore_noirq(struct device *device)
  901. {
  902. /* IRQF_TRIGGER_LOW */
  903. /* Gary todo */
  904. irq_set_irq_type(gi4IrqID, IRQF_TRIGGER_LOW);
  905. return 0;
  906. }
  907. const struct dev_pm_ops mjc_pm_ops = {
  908. .suspend = mjc_pm_suspend,
  909. .resume = mjc_pm_resume,
  910. .freeze = mjc_pm_suspend,
  911. .thaw = mjc_pm_resume,
  912. .poweroff = mjc_pm_suspend,
  913. .restore = mjc_pm_resume,
  914. .restore_noirq = mjc_pm_restore_noirq
  915. };
  916. /*---------------------------------------------------------------------------*/
  917. #endif /*CONFIG_PM */
  918. /*---------------------------------------------------------------------------*/
  919. static const struct of_device_id mjc_of_ids[] = {
  920. {.compatible = "mediatek,mjc_top-v1",},
  921. {}
  922. };
  923. static struct platform_driver mjcDrv = {
  924. .probe = mjc_probe,
  925. .remove = mjc_remove,
  926. .suspend = mjc_suspend,
  927. .resume = mjc_resume,
  928. .driver = {
  929. .name = MJC_DEVNAME,
  930. .of_match_table = mjc_of_ids,
  931. #ifdef CONFIG_PM
  932. .pm = &mjc_pm_ops,
  933. #endif
  934. .owner = THIS_MODULE,
  935. }
  936. };
  937. /*****************************************************************************
  938. * FUNCTION
  939. * mjc_driver_init
  940. * DESCRIPTION
  941. *
  942. * PARAMETERS
  943. * None.
  944. * RETURNS
  945. * Type: Integer. zero mean success and others mean fail.
  946. ****************************************************************************/
  947. static int __init mjc_driver_init(void)
  948. {
  949. int cnt;
  950. MJCDBG("mjc_driver_init()");
  951. if (platform_driver_register(&mjcDrv)) {
  952. MJCMSG("failed to register MAU driver");
  953. return -ENODEV;
  954. }
  955. /* clear force write register table for NCSTool tuning */
  956. for (cnt = 0; cnt < MJC_FORCE_REG_NUM; cnt++) {
  957. gfWriteReg[cnt].reg = 0;
  958. gfWriteReg[cnt].val = 0;
  959. gfWriteReg[cnt].mask = 0;
  960. }
  961. return 0;
  962. }
  963. /*****************************************************************************
  964. * FUNCTION
  965. * mjc_driver_exit
  966. * DESCRIPTION
  967. *
  968. * PARAMETERS
  969. * None.
  970. * RETURNS
  971. * None.
  972. ****************************************************************************/
  973. static void __exit mjc_driver_exit(void)
  974. {
  975. MJCDBG("mjc_driver_exit()");
  976. platform_driver_unregister(&mjcDrv);
  977. }
  978. module_init(mjc_driver_init);
  979. module_exit(mjc_driver_exit);
  980. MODULE_AUTHOR("Gary Huang <gary.huang@mediatek.com>");
  981. MODULE_DESCRIPTION("MTK MJC Driver");
  982. MODULE_LICENSE("GPL");