orizon_tilt.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. /* ===========================================================================
  2. * orizon_tilt.c
  3. * Copyright (C) 2009-2010 Bookeen - All rights reserved
  4. * ===========================================================================
  5. */
  6. /* TODO: Verify if all this includes are necessary */
  7. #include <linux/kernel.h>
  8. #include <linux/module.h>
  9. #include <asm/atomic.h>
  10. #include <asm/io.h>
  11. #include <asm/arch/irqs.h>
  12. #include <asm/arch/gpio.h>
  13. #include <linux/delay.h>
  14. #include <linux/interrupt.h>
  15. #include <linux/irq.h>
  16. #include <linux/jiffies.h>
  17. #include <linux/proc_fs.h>
  18. #include <linux/kthread.h>
  19. #include <linux/mutex.h>
  20. #include <linux/spinlock.h>
  21. #include <cybook.h>
  22. #include <linux/cyevent.h>
  23. //#define DEBUG_MESSAGES
  24. //#define DEBUG_TRACEFUNC
  25. //#define DBG_IRQ
  26. #define MODULE_NAME "CYB_TILT"
  27. #undef MSG
  28. #undef DBG
  29. #ifdef DEBUG_MESSAGES
  30. #ifdef DEBUG_TRACEFUNC
  31. static int _dbg_FunctionLevel = 0;
  32. #define MSG(str) {\
  33. int i;\
  34. printk(KERN_ALERT "+");\
  35. for (i = 0; i < _dbg_FunctionLevel; i++)\
  36. printk("-");\
  37. printk("||" str "\n");\
  38. }
  39. #define DBG(str, ...) {\
  40. int i;\
  41. printk(KERN_ALERT "+");\
  42. for (i = 0; i < _dbg_FunctionLevel; i++)\
  43. printk("-");\
  44. printk("||" str "\n", __VA_ARGS__);\
  45. }
  46. #define FUNC_IN() {\
  47. int i;\
  48. _dbg_FunctionLevel++;\
  49. printk(KERN_ALERT "+");\
  50. for (i = 0; i < _dbg_FunctionLevel; i++)\
  51. printk("-");\
  52. printk(">> %s() >>\n", __func__);\
  53. }
  54. #define FUNC_OUT() {\
  55. int i;\
  56. printk(KERN_ALERT "+");\
  57. for (i = 0; i < _dbg_FunctionLevel; i++)\
  58. printk("-");\
  59. printk("<< %s() <<\n", __func__);\
  60. _dbg_FunctionLevel--;\
  61. }
  62. #define FUNC_OUTR(val) {\
  63. int i;\
  64. printk(KERN_ALERT "+");\
  65. for (i = 0; i < _dbg_FunctionLevel; i++)\
  66. printk("-");\
  67. printk("<< %s() = %d <<\n", __func__, val);\
  68. _dbg_FunctionLevel--;\
  69. }
  70. #else /* DEBUG_TRACEFUNC */
  71. #define MSG(str) do {\
  72. printk(KERN_ALERT MODULE_NAME ": " str "\n");\
  73. } while(0)
  74. #define DBG(str, ...) do {\
  75. printk(KERN_ALERT MODULE_NAME ": " str "\n", __VA_ARGS__);\
  76. } while(0)
  77. #define FUNC_IN() do {\
  78. } while(0)
  79. #define FUNC_OUT() do {\
  80. } while(0)
  81. #define FUNC_OUTR(val) do {\
  82. printk(KERN_ALERT MODULE_NAME ": %s() return %d\n", __func__, val);\
  83. } while(0)
  84. #endif /* DEBUG_TRACEFUNC */
  85. #else /* DEBUG_MESSAGES */
  86. #define MSG(str)
  87. #define DBG(str, ...)
  88. #define FUNC_IN()
  89. #define FUNC_OUT()
  90. #define FUNC_OUTR(val)
  91. #endif /* DEBUG_MESSAGES */
  92. #define GPROCFS_ROOTFOLDER "cybook"
  93. #define GPROCFS_MODULEFOLDER "gsensor"
  94. #define GPROCFS_IOFILE "io"
  95. #define TRUE (1==1)
  96. #define FALSE (1==0)
  97. static struct proc_dir_entry *rootDir,
  98. *ioProcEntry;
  99. atomic_t OrizonTilt_Status;
  100. atomic_t OrizonTilt_IrqSet;
  101. static volatile short OrizonTilt_CurrentDirection = 270;
  102. static int SensorsInt[2];
  103. static DEFINE_SPINLOCK(suspendLock);
  104. static unsigned char OrizonTilt_finishedWork = 0;
  105. /*============================================================================*/
  106. /*============================= Prototypes ===================================*/
  107. /*============================================================================*/
  108. /********************************* PM *****************************************/
  109. static int orizontilt_suspend(struct device *dev, pm_message_t state);
  110. static int orizontilt_resume (struct device *dev);
  111. /************************* Data collection Functions **************************/
  112. /********************** Interrupt Related functions ***************************/
  113. static void orizontilt_setMode(int mode);
  114. static int orizontilt_initIrq(void);
  115. static void orizontilt_deinitIrq(void);
  116. static irqreturn_t orizontilt_interrupt(int irq, void *dev_id);
  117. /****************************** ProcFs functions ******************************/
  118. static int orizontilt_procReadIo (char *page, char **start, off_t off, int count,
  119. int *eof, void *data);
  120. static int orizontilt_procWriteIo (struct file *file, const char *buffer,
  121. unsigned long count, void *data);
  122. /****************************** Module functions ******************************/
  123. static int __init orizontilt_init(void);
  124. static void __exit orizontilt_exit(void);
  125. /*============================= End of prototypes ============================*/
  126. /******************************************************************************/
  127. /********************** Interrupt Related functions ***************************/
  128. /******************************************************************************/
  129. static int orizontilt_initIrq(void)
  130. {
  131. int ret = 0;
  132. FUNC_IN();
  133. if ( atomic_read(&OrizonTilt_IrqSet) != TRUE )
  134. {
  135. MSG("I will enable IRQ\n");
  136. set_irq_type(IRQ_EINT11, IRQT_BOTHEDGE);
  137. set_irq_type(IRQ_EINT12, IRQT_BOTHEDGE);
  138. s3c2410_gpio_pullup(S3C2410_GPG3, 0);
  139. s3c2410_gpio_pullup(S3C2410_GPG4, 0);
  140. if(request_irq(IRQ_EINT11, orizontilt_interrupt, SA_INTERRUPT, "TILT-SENSOR[1]", &SensorsInt[0]))
  141. {
  142. ret = -1;
  143. goto exit;
  144. }
  145. if(request_irq(IRQ_EINT12, orizontilt_interrupt, SA_INTERRUPT, "TILT-SENSOR[2]", &SensorsInt[1]))
  146. {
  147. ret = -1;
  148. goto exit;
  149. }
  150. atomic_set(&OrizonTilt_IrqSet, TRUE);
  151. }
  152. exit:
  153. FUNC_OUTR(ret);
  154. return ret;
  155. }
  156. static void orizontilt_deinitIrq(void)
  157. {
  158. FUNC_IN();
  159. /* Set the orizontilt to standby mode */
  160. if ( atomic_read(&OrizonTilt_IrqSet) == TRUE )
  161. {
  162. disable_irq_wake(IRQ_EINT11);
  163. disable_irq_wake(IRQ_EINT12);
  164. free_irq(IRQ_EINT11, NULL);
  165. free_irq(IRQ_EINT12, NULL);
  166. atomic_set(&OrizonTilt_IrqSet, FALSE);
  167. }
  168. FUNC_OUT();
  169. }
  170. static irqreturn_t orizontilt_interrupt(int irq, void *dev_id)
  171. {
  172. irqreturn_t ret = IRQ_HANDLED;
  173. unsigned long tmpReg;
  174. unsigned long calcTilt;
  175. CyEvent_t event = NEW_CYEVENT(CYEVENT_TYPE_ORIENTATION);
  176. FUNC_IN();
  177. spin_lock(&suspendLock);
  178. OrizonTilt_finishedWork = 1;
  179. spin_unlock(&suspendLock);
  180. /* Do it here */
  181. MSG("Will read gpios...");
  182. tmpReg = (__raw_readl(S3C2410_GPGDAT) >> 3) & 0x3;
  183. DBG("Got reg: %lu", tmpReg);
  184. calcTilt = 0;
  185. switch(tmpReg)
  186. {
  187. case 0x00: /* 90 */
  188. calcTilt = 90;
  189. break;
  190. case 0x02: /* 0 */
  191. calcTilt = 0;
  192. break;
  193. case 0x01: /* 180 */
  194. calcTilt = 180;
  195. break;
  196. case 0x03: /* 270 */
  197. calcTilt = 270;
  198. break;
  199. }
  200. DBG("New Orientation is: %lu", calcTilt);
  201. if (calcTilt != OrizonTilt_CurrentDirection)
  202. {
  203. MSG("Different from old one, push new event!");
  204. OrizonTilt_CurrentDirection = calcTilt;
  205. event.data.orientation = calcTilt / 90;
  206. CyEvent_PushOrUpdateUniqueEvent(&event, false);
  207. }
  208. spin_lock(&suspendLock);
  209. OrizonTilt_finishedWork = 0;
  210. spin_unlock(&suspendLock);
  211. FUNC_OUT();
  212. exit:
  213. FUNC_OUTR((int)ret);
  214. return ret;
  215. }
  216. static void orizontilt_setMode(int mode)
  217. {
  218. switch(mode)
  219. {
  220. case G_SENSOR_ON:
  221. orizontilt_initIrq();
  222. enable_irq_wake(IRQ_EINT11);
  223. enable_irq_wake(IRQ_EINT12);
  224. /* Switch TILT on */
  225. gpio_direction_output(S3C2410_GPC3, 1);
  226. atomic_set(&OrizonTilt_Status, CYGSENSOR_STATUS_ENABLED);
  227. break;
  228. case G_SENSOR_OFF:
  229. atomic_set(&OrizonTilt_Status, CYGSENSOR_STATUS_DISABLED);
  230. /* Switch TILT off */
  231. gpio_direction_output(S3C2410_GPC3, 0);
  232. orizontilt_deinitIrq();
  233. disable_irq_wake(IRQ_EINT11);
  234. disable_irq_wake(IRQ_EINT12);
  235. break;
  236. }
  237. }
  238. /******************************************************************************/
  239. /****************************** ProcFs functions ******************************/
  240. /******************************************************************************/
  241. static int orizontilt_procReadIo (char *page, char **start, off_t off, int count,
  242. int *eof, void *data)
  243. {
  244. int len;
  245. char tmp = 0;
  246. /* We are a tilt and need no calibration */
  247. tmp |= (1 << 6);
  248. if ( atomic_read(&OrizonTilt_Status) != CYGSENSOR_STATUS_ENABLED )
  249. tmp |= (1 << 4);
  250. switch (OrizonTilt_CurrentDirection)
  251. {
  252. case 270:
  253. tmp++;
  254. case 180:
  255. tmp++;
  256. case 90:
  257. tmp++;
  258. default:
  259. break;
  260. }
  261. len = sprintf (page, "%02X", tmp);
  262. DBG("io readed value: %02X", tmp);
  263. FUNC_OUTR(len);
  264. return len;
  265. }
  266. static int orizontilt_procWriteIo (struct file *file, const char *buffer,
  267. unsigned long count, void *data)
  268. {
  269. char cmd;
  270. FUNC_IN();
  271. /* in case of... */
  272. if ( count < 1 )
  273. return 0;
  274. cmd = buffer[0];
  275. switch(cmd)
  276. {
  277. case G_SENSOR_ON:
  278. case G_SENSOR_OFF:
  279. orizontilt_setMode(cmd);
  280. break;
  281. default:
  282. printk(KERN_ERR "ProcIO: Unknown command '%c'\n",cmd);
  283. break;
  284. }
  285. FUNC_OUTR((int)count);
  286. return count;
  287. }
  288. /******************************************************************************/
  289. /****************************** Module functions ******************************/
  290. /******************************************************************************/
  291. static int __init orizontilt_init(void)
  292. {
  293. FUNC_IN();
  294. //printk(KERN_ERR "Platform is Cybook %d\n", platform_type);
  295. SensorsInt[0] = 1;
  296. SensorsInt[1] = 2;
  297. if (GET_CAPABILITY(PLAT_CAP_GSENSOR) == PLAT_CAP_GTILT)
  298. {
  299. atomic_set(&OrizonTilt_Status, CYGSENSOR_STATUS_UNKNOWN);
  300. atomic_set(&OrizonTilt_IrqSet, FALSE);
  301. rootDir = proc_mkdir(GPROCFS_ROOTFOLDER, NULL);
  302. rootDir = proc_mkdir(GPROCFS_MODULEFOLDER, proc_root_driver);
  303. ioProcEntry = create_proc_entry(GPROCFS_IOFILE, 0644, rootDir);
  304. ioProcEntry->read_proc = orizontilt_procReadIo;
  305. ioProcEntry->write_proc = orizontilt_procWriteIo;
  306. ioProcEntry->owner = THIS_MODULE;
  307. }
  308. FUNC_OUT();
  309. return 0;
  310. }
  311. // ---------------------------------------------------------------------------
  312. static void __exit orizontilt_exit(void)
  313. {
  314. FUNC_IN();
  315. if (GET_CAPABILITY(PLAT_CAP_GSENSOR) == PLAT_CAP_GTILT)
  316. {
  317. orizontilt_setMode(G_SENSOR_OFF);
  318. remove_proc_entry(GPROCFS_IOFILE, rootDir);
  319. remove_proc_entry(GPROCFS_MODULEFOLDER, proc_root_driver);
  320. }
  321. FUNC_OUT();
  322. }
  323. // ---------------------------------------------------------------------------
  324. module_init(orizontilt_init);
  325. module_exit(orizontilt_exit);
  326. // ---------------------------------------------------------------------------
  327. MODULE_LICENSE("GPL");
  328. MODULE_AUTHOR("Bookeen <developers@bookeen.com>");
  329. MODULE_VERSION("1.1");
  330. MODULE_DESCRIPTION("Orizon Tilt Sensor driver");
  331. // ===========================================================================