mt_gpio_core.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702
  1. /******************************************************************************
  2. * mt_gpio.c - MTKLinux GPIO Device Driver
  3. *
  4. * Copyright 2008-2009 MediaTek Co.,Ltd.
  5. *
  6. * DESCRIPTION:
  7. * This file provid the other drivers GPIO relative functions
  8. *
  9. ******************************************************************************/
  10. #include <linux/init.h>
  11. #include <linux/module.h>
  12. #include <linux/kernel.h>
  13. #include <generated/autoconf.h>
  14. #include <linux/platform_device.h>
  15. #include <linux/fs.h>
  16. #include <linux/ioctl.h>
  17. #include <linux/types.h>
  18. #include <linux/device.h>
  19. #include <linux/slab.h>
  20. #include <linux/spinlock.h>
  21. #include <linux/cdev.h>
  22. #include <asm/uaccess.h>
  23. #include <asm/io.h>
  24. #include <asm/atomic.h>
  25. #include <linux/miscdevice.h>
  26. #include "mt-plat/mtgpio.h"
  27. #include <linux/types.h>
  28. #include <mt-plat/mt_gpio.h>
  29. #include <mt-plat/mt_gpio_core.h>
  30. #include <mach/gpio_const.h>
  31. /***********************/
  32. struct mt_gpio_ops {
  33. /* char name[MT_GPIO_MAX_NAME]; */
  34. int (*set_dir)(unsigned long pin, unsigned long dir);
  35. int (*get_dir)(unsigned long pin);
  36. int (*set_pull_enable)(unsigned long pin, unsigned long enable);
  37. int (*get_pull_enable)(unsigned long pin);
  38. int (*set_smt)(unsigned long pin, unsigned long enable);
  39. int (*get_smt)(unsigned long pin);
  40. int (*set_ies)(unsigned long pin, unsigned long enable);
  41. int (*get_ies)(unsigned long pin);
  42. int (*set_pull_select)(unsigned long pin, unsigned long select);
  43. int (*get_pull_select)(unsigned long pin);
  44. int (*set_inversion)(unsigned long pin, unsigned long enable);
  45. int (*get_inversion)(unsigned long pin);
  46. int (*set_out)(unsigned long pin, unsigned long output);
  47. int (*get_out)(unsigned long pin);
  48. int (*get_in)(unsigned long pin);
  49. int (*set_mode)(unsigned long pin, unsigned long mode);
  50. int (*get_mode)(unsigned long pin);
  51. };
  52. /*---------------------------------------------------------------------------*/
  53. static struct mt_gpio_ops mt_base_ops = {
  54. .set_dir = mt_set_gpio_dir_base,
  55. .get_dir = mt_get_gpio_dir_base,
  56. .set_pull_enable = mt_set_gpio_pull_enable_base,
  57. .get_pull_enable = mt_get_gpio_pull_enable_base,
  58. .set_smt = mt_set_gpio_smt_base,
  59. .get_smt = mt_get_gpio_smt_base,
  60. .set_ies = mt_set_gpio_ies_base,
  61. .get_ies = mt_get_gpio_ies_base,
  62. .set_pull_select = mt_set_gpio_pull_select_base,
  63. .get_pull_select = mt_get_gpio_pull_select_base,
  64. .set_inversion = mt_set_gpio_inversion_base,
  65. .get_inversion = mt_get_gpio_inversion_base,
  66. .set_out = mt_set_gpio_out_base,
  67. .get_out = mt_get_gpio_out_base,
  68. .get_in = mt_get_gpio_in_base,
  69. .set_mode = mt_set_gpio_mode_base,
  70. .get_mode = mt_get_gpio_mode_base,
  71. };
  72. static struct mt_gpio_ops mt_ext_ops = {
  73. .set_dir = mt_set_gpio_dir_ext,
  74. .get_dir = mt_get_gpio_dir_ext,
  75. .set_pull_enable = mt_set_gpio_pull_enable_ext,
  76. .get_pull_enable = mt_get_gpio_pull_enable_ext,
  77. .set_smt = mt_set_gpio_smt_ext,
  78. .get_smt = mt_get_gpio_smt_ext,
  79. .set_ies = mt_set_gpio_ies_ext,
  80. .get_ies = mt_get_gpio_ies_ext,
  81. .set_pull_select = mt_set_gpio_pull_select_ext,
  82. .get_pull_select = mt_get_gpio_pull_select_ext,
  83. .set_inversion = mt_set_gpio_inversion_ext,
  84. .get_inversion = mt_get_gpio_inversion_ext,
  85. .set_out = mt_set_gpio_out_ext,
  86. .get_out = mt_get_gpio_out_ext,
  87. .get_in = mt_get_gpio_in_ext,
  88. .set_mode = mt_set_gpio_mode_ext,
  89. .get_mode = mt_get_gpio_mode_ext,
  90. };
  91. DEFINE_SPINLOCK(mt_gpio_lock);
  92. struct mt_gpio_obj_t {
  93. atomic_t ref;
  94. dev_t devno;
  95. struct class *cls;
  96. struct device *dev;
  97. struct cdev chrdev;
  98. /* spinlock_t lock; */
  99. struct miscdevice *misc;
  100. struct mt_gpio_ops *base_ops;
  101. struct mt_gpio_ops *ext_ops;
  102. };
  103. static struct mt_gpio_obj_t mt_gpio_obj = {
  104. .ref = ATOMIC_INIT(0),
  105. .cls = NULL,
  106. .dev = NULL,
  107. .base_ops = &mt_base_ops,
  108. .ext_ops = &mt_ext_ops,
  109. /* .lock = __SPIN_LOCK_UNLOCKED(die.lock), */
  110. };
  111. static struct mt_gpio_obj_t *mt_gpio = &mt_gpio_obj;
  112. #define MT_GPIO_OPS_SET(pin, operation, arg) \
  113. ({ unsigned long flags;\
  114. u32 retval = 0;\
  115. mt_gpio_pin_decrypt(&pin);\
  116. spin_lock_irqsave(&mt_gpio_lock, flags);\
  117. if (MT_BASE == MT_GPIO_PLACE(pin)) {\
  118. if ((mt_gpio->base_ops == NULL) || (mt_gpio->base_ops->operation == NULL)) {\
  119. GPIOERR("base access error, null point %d\n", (int)pin);\
  120. retval = -ERACCESS;\
  121. } else{\
  122. retval = mt_gpio->base_ops->operation(pin, arg);\
  123. if (retval < 0) \
  124. GPIOERR("base operation fail %d\n", (int)retval);\
  125. } \
  126. } \
  127. else if (MT_EXT == MT_GPIO_PLACE(pin)) {\
  128. if ((mt_gpio->ext_ops == NULL) || (mt_gpio->ext_ops->operation == NULL)) {\
  129. GPIOERR("extension access error, null point %d\n", (int)pin);\
  130. retval = -ERWRAPPER;\
  131. } else{\
  132. retval = mt_gpio->ext_ops->operation(pin, arg);\
  133. if (retval < 0) \
  134. GPIOERR("ext operation fail %d\n", (int)retval);\
  135. } \
  136. } \
  137. else{\
  138. GPIOERR("Parameter error: %d\n", (int)pin);\
  139. retval = -ERINVAL;\
  140. } \
  141. spin_unlock_irqrestore(&mt_gpio_lock, flags);\
  142. retval; })
  143. /* GPIOLOG("%s(%d)\n","operation",pin); */
  144. #define MT_GPIO_OPS_GET(pin, operation) \
  145. ({ u32 retval = 0;\
  146. mt_gpio_pin_decrypt(&pin);\
  147. if (MT_BASE == MT_GPIO_PLACE(pin)) {\
  148. if ((mt_gpio->base_ops == NULL) || (mt_gpio->base_ops->operation == NULL)) {\
  149. GPIOERR("base access error, null point %d\n", (int)pin);\
  150. retval = -ERACCESS;\
  151. } else{\
  152. retval = mt_gpio->base_ops->operation(pin);\
  153. if (retval < 0) \
  154. GPIOERR("base operation fail %d\n", (int)retval);\
  155. } \
  156. } \
  157. else if (MT_EXT == MT_GPIO_PLACE(pin)) {\
  158. if ((mt_gpio->ext_ops == NULL) || (mt_gpio->ext_ops->operation == NULL)) {\
  159. GPIOERR("extension access error, null point %d\n", (int)pin);\
  160. retval = -ERWRAPPER;\
  161. } else{\
  162. retval = mt_gpio->ext_ops->operation(pin);\
  163. if (retval < 0) \
  164. GPIOERR("ext operation fail %d\n", (int)retval);\
  165. } \
  166. } \
  167. else{\
  168. GPIOERR("Parameter pin number error: %d\n", (int)pin);\
  169. retval = -ERINVAL;\
  170. };\
  171. retval; })
  172. #if (defined(MACH_FPGA) && !defined(GPIO_FPGA_SIMULATION))
  173. S32 mt_set_gpio_dir(u32 pin, u32 dir) {return RSUCCESS; }
  174. S32 mt_get_gpio_dir(u32 pin) {return GPIO_DIR_UNSUPPORTED; }
  175. S32 mt_set_gpio_pull_enable(u32 pin, u32 enable) {return RSUCCESS; }
  176. S32 mt_get_gpio_pull_enable(u32 pin) {return GPIO_PULL_EN_UNSUPPORTED; }
  177. S32 mt_set_gpio_pull_select(u32 pin, u32 select) {return RSUCCESS; }
  178. S32 mt_get_gpio_pull_select(u32 pin) {return GPIO_PULL_UNSUPPORTED; }
  179. S32 mt_set_gpio_smt(u32 pin, u32 enable) {return RSUCCESS; }
  180. S32 mt_get_gpio_smt(u32 pin) {return GPIO_SMT_UNSUPPORTED; }
  181. S32 mt_set_gpio_ies(u32 pin, u32 enable) {return RSUCCESS; }
  182. S32 mt_get_gpio_ies(u32 pin) {return GPIO_IES_UNSUPPORTED; }
  183. S32 mt_set_gpio_out(u32 pin, u32 output) {return RSUCCESS; }
  184. S32 mt_get_gpio_out(u32 pin) {return GPIO_OUT_UNSUPPORTED; }
  185. S32 mt_get_gpio_in(u32 pin) {return GPIO_IN_UNSUPPORTED; }
  186. S32 mt_set_gpio_mode(u32 pin, u32 mode) {return RSUCCESS; }
  187. S32 mt_get_gpio_mode(u32 pin) {return GPIO_MODE_UNSUPPORTED; }
  188. #else
  189. int mt_set_gpio_dir(unsigned long pin, unsigned long dir)
  190. {
  191. /* int ret=0; */
  192. if (dir >= GPIO_DIR_MAX) {
  193. GPIOERR("Parameter dir error: %d\n", (int)dir);
  194. return -ERINVAL;
  195. }
  196. return MT_GPIO_OPS_SET(pin, set_dir, dir);
  197. }
  198. EXPORT_SYMBOL(mt_set_gpio_dir);
  199. /*---------------------------------------------------------------------------*/
  200. int mt_get_gpio_dir(unsigned long pin)
  201. {
  202. return MT_GPIO_OPS_GET(pin, get_dir);
  203. }
  204. EXPORT_SYMBOL(mt_get_gpio_dir);
  205. /*---------------------------------------------------------------------------*/
  206. int mt_set_gpio_pull_enable(unsigned long pin, unsigned long enable)
  207. {
  208. if (enable >= GPIO_PULL_EN_MAX) {
  209. GPIOERR("Parameter enable error: %d\n", (int)enable);
  210. return -ERINVAL;
  211. }
  212. return MT_GPIO_OPS_SET(pin, set_pull_enable, enable);
  213. }
  214. EXPORT_SYMBOL(mt_set_gpio_pull_enable);
  215. /*---------------------------------------------------------------------------*/
  216. int mt_get_gpio_pull_enable(unsigned long pin)
  217. {
  218. return MT_GPIO_OPS_GET(pin, get_pull_enable);
  219. }
  220. EXPORT_SYMBOL(mt_get_gpio_pull_enable);
  221. /*---------------------------------------------------------------------------*/
  222. int mt_set_gpio_smt(unsigned long pin, unsigned long enable)
  223. {
  224. if (enable >= GPIO_SMT_MAX) {
  225. GPIOERR("Parameter enable error: %d\n", (int)enable);
  226. return -ERINVAL;
  227. }
  228. return MT_GPIO_OPS_SET(pin, set_smt, enable);
  229. }
  230. EXPORT_SYMBOL(mt_set_gpio_smt);
  231. /*---------------------------------------------------------------------------*/
  232. int mt_get_gpio_smt(unsigned long pin)
  233. {
  234. return MT_GPIO_OPS_GET(pin, get_smt);
  235. }
  236. EXPORT_SYMBOL(mt_get_gpio_smt);
  237. /*---------------------------------------------------------------------------*/
  238. int mt_set_gpio_ies(unsigned long pin, unsigned long enable)
  239. {
  240. if (enable >= GPIO_IES_MAX) {
  241. GPIOERR("Parameter enable error: %d\n", (int)enable);
  242. return -ERINVAL;
  243. }
  244. return MT_GPIO_OPS_SET(pin, set_ies, enable);
  245. }
  246. EXPORT_SYMBOL(mt_set_gpio_ies);
  247. /*---------------------------------------------------------------------------*/
  248. int mt_get_gpio_ies(unsigned long pin)
  249. {
  250. return MT_GPIO_OPS_GET(pin, get_ies);
  251. }
  252. EXPORT_SYMBOL(mt_get_gpio_ies);
  253. /*---------------------------------------------------------------------------*/
  254. int mt_set_gpio_pull_select(unsigned long pin, unsigned long select)
  255. {
  256. if (select >= GPIO_PULL_MAX) {
  257. GPIOERR("Parameter select error: %d\n", (int)select);
  258. return -ERINVAL;
  259. }
  260. return MT_GPIO_OPS_SET(pin, set_pull_select, select);
  261. }
  262. EXPORT_SYMBOL(mt_get_gpio_pull_select);
  263. /*---------------------------------------------------------------------------*/
  264. int mt_get_gpio_pull_select(unsigned long pin)
  265. {
  266. return MT_GPIO_OPS_GET(pin, get_pull_select);
  267. }
  268. EXPORT_SYMBOL(mt_set_gpio_pull_select);
  269. /*---------------------------------------------------------------------------*/
  270. int mt_set_gpio_inversion(unsigned long pin, unsigned long enable)
  271. {
  272. if (enable >= GPIO_DATA_INV_MAX) {
  273. GPIOERR("Parameter enable error: %d\n", (int)enable);
  274. return -ERINVAL;
  275. }
  276. return MT_GPIO_OPS_SET(pin, set_inversion, enable);
  277. }
  278. EXPORT_SYMBOL(mt_set_gpio_inversion);
  279. /*---------------------------------------------------------------------------*/
  280. int mt_get_gpio_inversion(unsigned long pin)
  281. {
  282. return MT_GPIO_OPS_GET(pin, get_inversion);
  283. }
  284. EXPORT_SYMBOL(mt_get_gpio_inversion);
  285. /*---------------------------------------------------------------------------*/
  286. int mt_set_gpio_out(unsigned long pin, unsigned long output)
  287. {
  288. if (output >= GPIO_OUT_MAX) {
  289. GPIOERR("Parameter output error: %d\n", (int)output);
  290. return -ERINVAL;
  291. }
  292. return MT_GPIO_OPS_SET(pin, set_out, output);
  293. }
  294. EXPORT_SYMBOL(mt_set_gpio_out);
  295. /*---------------------------------------------------------------------------*/
  296. int mt_get_gpio_out(unsigned long pin)
  297. {
  298. return MT_GPIO_OPS_GET(pin, get_out);
  299. }
  300. EXPORT_SYMBOL(mt_get_gpio_out);
  301. /*---------------------------------------------------------------------------*/
  302. int mt_get_gpio_in(unsigned long pin)
  303. {
  304. return MT_GPIO_OPS_GET(pin, get_in);
  305. }
  306. EXPORT_SYMBOL(mt_get_gpio_in);
  307. /*---------------------------------------------------------------------------*/
  308. int mt_set_gpio_mode(unsigned long pin, unsigned long mode)
  309. {
  310. if (mode >= GPIO_MODE_MAX) {
  311. GPIOERR("Parameter mode error: %d\n", (int)mode);
  312. return -ERINVAL;
  313. }
  314. return MT_GPIO_OPS_SET(pin, set_mode, mode);
  315. }
  316. EXPORT_SYMBOL(mt_set_gpio_mode);
  317. /*---------------------------------------------------------------------------*/
  318. int mt_get_gpio_mode(unsigned long pin)
  319. {
  320. return MT_GPIO_OPS_GET(pin, get_mode);
  321. }
  322. EXPORT_SYMBOL(mt_get_gpio_mode);
  323. #endif
  324. /*****************************************************************************/
  325. /* File operation */
  326. /*****************************************************************************/
  327. static int mt_gpio_open(struct inode *inode, struct file *file)
  328. {
  329. struct mt_gpio_obj_t *obj = mt_gpio;
  330. GPIOFUC();
  331. if (obj == NULL) {
  332. GPIOERR("NULL pointer");
  333. return -EFAULT;
  334. }
  335. atomic_inc(&obj->ref);
  336. file->private_data = obj;
  337. return nonseekable_open(inode, file);
  338. }
  339. /*---------------------------------------------------------------------------*/
  340. static int mt_gpio_release(struct inode *inode, struct file *file)
  341. {
  342. struct mt_gpio_obj_t *obj = mt_gpio;
  343. GPIOFUC();
  344. if (obj == NULL) {
  345. GPIOERR("NULL pointer");
  346. return -EFAULT;
  347. }
  348. atomic_dec(&obj->ref);
  349. return RSUCCESS;
  350. }
  351. /*---------------------------------------------------------------------------*/
  352. static long mt_gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  353. {
  354. struct mt_gpio_obj_t *obj = mt_gpio;
  355. long res;
  356. unsigned long pin;
  357. GPIOFUC();
  358. if (obj == NULL) {
  359. GPIOERR("NULL pointer");
  360. return -EFAULT;
  361. }
  362. switch (cmd) {
  363. case GPIO_IOCQMODE:
  364. {
  365. pin = (unsigned long)arg;
  366. res = GIO_INVALID_OBJ(obj) ? (-EACCES) : mt_get_gpio_mode(pin);
  367. break;
  368. }
  369. case GPIO_IOCTMODE0:
  370. {
  371. pin = (unsigned long)arg;
  372. res =
  373. GIO_INVALID_OBJ(obj) ? (-EACCES) : mt_set_gpio_mode(pin, GPIO_MODE_00);
  374. break;
  375. }
  376. case GPIO_IOCTMODE1:
  377. {
  378. pin = (unsigned long)arg;
  379. res =
  380. GIO_INVALID_OBJ(obj) ? (-EACCES) : mt_set_gpio_mode(pin, GPIO_MODE_01);
  381. break;
  382. }
  383. case GPIO_IOCTMODE2:
  384. {
  385. pin = (unsigned long)arg;
  386. res =
  387. GIO_INVALID_OBJ(obj) ? (-EACCES) : mt_set_gpio_mode(pin, GPIO_MODE_02);
  388. break;
  389. }
  390. case GPIO_IOCTMODE3:
  391. {
  392. pin = (unsigned long)arg;
  393. res =
  394. GIO_INVALID_OBJ(obj) ? (-EACCES) : mt_set_gpio_mode(pin, GPIO_MODE_03);
  395. break;
  396. }
  397. case GPIO_IOCQDIR:
  398. {
  399. pin = (unsigned long)arg;
  400. res = GIO_INVALID_OBJ(obj) ? (-EACCES) : mt_get_gpio_dir(pin);
  401. break;
  402. }
  403. case GPIO_IOCSDIRIN:
  404. {
  405. pin = (unsigned long)arg;
  406. res = GIO_INVALID_OBJ(obj) ? (-EACCES) : mt_set_gpio_dir(pin, GPIO_DIR_IN);
  407. break;
  408. }
  409. case GPIO_IOCSDIROUT:
  410. {
  411. pin = (unsigned long)arg;
  412. res = GIO_INVALID_OBJ(obj) ? (-EACCES) : mt_set_gpio_dir(pin, GPIO_DIR_OUT);
  413. break;
  414. }
  415. case GPIO_IOCQPULLEN:
  416. {
  417. pin = (unsigned long)arg;
  418. res = GIO_INVALID_OBJ(obj) ? (-EACCES) : mt_get_gpio_pull_enable(pin);
  419. break;
  420. }
  421. case GPIO_IOCSPULLENABLE:
  422. {
  423. pin = (unsigned long)arg;
  424. res = GIO_INVALID_OBJ(obj) ? (-EACCES) : mt_set_gpio_pull_enable(pin, true);
  425. break;
  426. }
  427. case GPIO_IOCSPULLDISABLE:
  428. {
  429. pin = (unsigned long)arg;
  430. res =
  431. GIO_INVALID_OBJ(obj) ? (-EACCES) : mt_set_gpio_pull_enable(pin, false);
  432. break;
  433. }
  434. case GPIO_IOCQPULL:
  435. {
  436. pin = (unsigned long)arg;
  437. res = GIO_INVALID_OBJ(obj) ? (-EACCES) : mt_get_gpio_pull_select(pin);
  438. break;
  439. }
  440. case GPIO_IOCSPULLDOWN:
  441. {
  442. pin = (unsigned long)arg;
  443. res =
  444. GIO_INVALID_OBJ(obj) ? (-EACCES) : mt_set_gpio_pull_select(pin,
  445. GPIO_PULL_DOWN);
  446. break;
  447. }
  448. case GPIO_IOCSPULLUP:
  449. {
  450. pin = (unsigned long)arg;
  451. res =
  452. GIO_INVALID_OBJ(obj) ? (-EACCES) : mt_set_gpio_pull_select(pin,
  453. GPIO_PULL_UP);
  454. break;
  455. }
  456. case GPIO_IOCQINV:
  457. {
  458. pin = (unsigned long)arg;
  459. res = GIO_INVALID_OBJ(obj) ? (-EACCES) : mt_get_gpio_inversion(pin);
  460. break;
  461. }
  462. case GPIO_IOCSINVENABLE:
  463. {
  464. pin = (unsigned long)arg;
  465. res = GIO_INVALID_OBJ(obj) ? (-EACCES) : mt_set_gpio_inversion(pin, true);
  466. break;
  467. }
  468. case GPIO_IOCSINVDISABLE:
  469. {
  470. pin = (unsigned long)arg;
  471. res = GIO_INVALID_OBJ(obj) ? (-EACCES) : mt_set_gpio_inversion(pin, false);
  472. break;
  473. }
  474. case GPIO_IOCQDATAIN:
  475. {
  476. pin = (unsigned long)arg;
  477. res = GIO_INVALID_OBJ(obj) ? (-EFAULT) : mt_get_gpio_in(pin);
  478. break;
  479. }
  480. case GPIO_IOCQDATAOUT:
  481. {
  482. pin = (unsigned long)arg;
  483. res = GIO_INVALID_OBJ(obj) ? (-EACCES) : mt_get_gpio_out(pin);
  484. break;
  485. }
  486. case GPIO_IOCSDATALOW:
  487. {
  488. pin = (unsigned long)arg;
  489. res =
  490. GIO_INVALID_OBJ(obj) ? (-EACCES) : mt_set_gpio_out(pin, GPIO_OUT_ZERO);
  491. break;
  492. }
  493. case GPIO_IOCSDATAHIGH:
  494. {
  495. pin = (unsigned long)arg;
  496. res = GIO_INVALID_OBJ(obj) ? (-EACCES) : mt_set_gpio_out(pin, GPIO_OUT_ONE);
  497. break;
  498. }
  499. default:
  500. {
  501. res = -EPERM;
  502. break;
  503. }
  504. }
  505. if (res == -EACCES)
  506. GPIOERR(" cmd = 0x%8X, invalid pointer\n", cmd);
  507. else if (res < 0)
  508. GPIOERR(" cmd = 0x%8X, err = %ld\n", cmd, res);
  509. return res;
  510. }
  511. /*---------------------------------------------------------------------------*/
  512. static const struct file_operations mt_gpio_fops = {
  513. .owner = THIS_MODULE,
  514. .unlocked_ioctl = mt_gpio_ioctl,
  515. #ifdef CONFIG_COMPAT
  516. .compat_ioctl = mt_gpio_ioctl,
  517. #endif
  518. .open = mt_gpio_open,
  519. .release = mt_gpio_release,
  520. };
  521. /*----------------------------------------------------------------------------*/
  522. static struct miscdevice mt_gpio_device = {
  523. .minor = MISC_DYNAMIC_MINOR,
  524. .name = "mtgpio",
  525. .fops = &mt_gpio_fops,
  526. };
  527. /*---------------------------------------------------------------------------*/
  528. static int mt_gpio_probe(struct platform_device *dev)
  529. {
  530. int err;
  531. struct miscdevice *misc = &mt_gpio_device;
  532. #ifdef CONFIG_OF
  533. if (dev->dev.of_node) {
  534. /* Setup IO addresses */
  535. get_gpio_vbase(dev->dev.of_node);
  536. }
  537. get_io_cfg_vbase();
  538. #endif
  539. #ifdef CONFIG_MD32_SUPPORT
  540. md32_gpio_handle_init();
  541. #endif
  542. /* printk(KERN_ALERT"[GPIO]%5d,<%s> gpio devices probe\n", __LINE__, __func__); */
  543. GPIOLOG("Registering GPIO device\n");
  544. if (!mt_gpio)
  545. GPIO_RETERR(-EACCES, "");
  546. mt_gpio->misc = misc;
  547. err = misc_register(misc);
  548. if (err)
  549. GPIOERR("register gpio\n");
  550. err = mt_gpio_create_attr(misc->this_device);
  551. if (err)
  552. GPIOERR("create attribute\n");
  553. dev_set_drvdata(misc->this_device, mt_gpio);
  554. return err;
  555. }
  556. /*---------------------------------------------------------------------------*/
  557. static int mt_gpio_remove(struct platform_device *dev)
  558. {
  559. struct mt_gpio_obj_t *obj = platform_get_drvdata(dev);
  560. int err;
  561. err = mt_gpio_delete_attr(obj->misc->this_device);
  562. if (err)
  563. GPIOERR("delete attr\n");
  564. err = misc_deregister(obj->misc);
  565. if (err)
  566. GPIOERR("deregister gpio\n");
  567. return err;
  568. }
  569. /*---------------------------------------------------------------------------*/
  570. #ifdef CONFIG_PM
  571. /*---------------------------------------------------------------------------*/
  572. static int mtk_gpio_suspend(struct platform_device *pdev, pm_message_t state)
  573. {
  574. int ret = 0;
  575. mt_gpio_suspend();
  576. return ret;
  577. }
  578. /*---------------------------------------------------------------------------*/
  579. static int mtk_gpio_resume(struct platform_device *pdev)
  580. {
  581. int ret = 0;
  582. mt_gpio_resume();
  583. return ret;
  584. }
  585. /*---------------------------------------------------------------------------*/
  586. #endif /*CONFIG_PM */
  587. /*---------------------------------------------------------------------------*/
  588. /*---------------------------------------------------------------------------*/
  589. #ifdef CONFIG_OF
  590. static const struct of_device_id apgpio_of_ids[] = {
  591. {.compatible = "mediatek,gpio",},
  592. {}
  593. };
  594. #endif
  595. static struct platform_driver gpio_driver = {
  596. .probe = mt_gpio_probe,
  597. .remove = mt_gpio_remove,
  598. #ifdef CONFIG_PM
  599. .suspend = mtk_gpio_suspend,
  600. .resume = mtk_gpio_resume,
  601. #endif
  602. .driver = {
  603. .name = GPIO_DEVICE,
  604. #ifdef CONFIG_OF
  605. .of_match_table = apgpio_of_ids,
  606. #endif
  607. },
  608. };
  609. #ifdef CONFIG_OF
  610. struct device_node *get_gpio_np(void)
  611. {
  612. struct device_node *np_gpio;
  613. gpio_vbase.gpio_regs = NULL;
  614. np_gpio = of_find_compatible_node(NULL, NULL, apgpio_of_ids[0].compatible);
  615. if (np_gpio == NULL) {
  616. GPIOERR("GPIO device node is NULL\n");
  617. return NULL;
  618. }
  619. return np_gpio;
  620. }
  621. #endif
  622. /*---------------------------------------------------------------------------*/
  623. /*---------------------------------------------------------------------------*/
  624. static int __init mt_gpio_init(void)
  625. {
  626. int ret = 0;
  627. GPIOLOG("version: %s\n", VERSION);
  628. ret = platform_driver_register(&gpio_driver);
  629. return ret;
  630. }
  631. /*---------------------------------------------------------------------------*/
  632. static void __exit mt_gpio_exit(void)
  633. {
  634. platform_driver_unregister(&gpio_driver);
  635. }
  636. /* void gpio_dump_regs(void) */
  637. /* { */
  638. /* return; */
  639. /* } */
  640. /*---------------------------------------------------------------------------*/
  641. subsys_initcall(mt_gpio_init);
  642. module_exit(mt_gpio_exit);
  643. MODULE_AUTHOR("mediatek ");
  644. MODULE_DESCRIPTION("MT General Purpose Driver (GPIO) Revision");
  645. MODULE_LICENSE("GPL");
  646. /*---------------------------------------------------------------------------*/