1100-gpio.patch 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. --- /dev/null
  2. +++ b/drivers/char/gemini_gpio_dev.c
  3. @@ -0,0 +1,356 @@
  4. +/*
  5. + * GPIO driver for Gemini board
  6. + * Provides /dev/gpio
  7. + */
  8. +
  9. +#include <linux/version.h>
  10. +#include <linux/kernel.h>
  11. +#include <linux/module.h>
  12. +#include <linux/init.h>
  13. +#include <linux/proc_fs.h>
  14. +#include <linux/fcntl.h>
  15. +#include <linux/miscdevice.h>
  16. +#include <asm/uaccess.h> /* copy_to_user, copy_from_user */
  17. +
  18. +#include <asm/hardware.h>
  19. +#include <asm/io.h>
  20. +#include <asm/arch/sl2312.h>
  21. +#include <asm/arch/irqs.h>
  22. +#include <asm/arch/gemini_gpio.h>
  23. +
  24. +#define GEMINI_GPIO_BASE1 IO_ADDRESS(SL2312_GPIO_BASE)
  25. +#define GEMINI_GPIO_BASE2 IO_ADDRESS(SL2312_GPIO_BASE1)
  26. +
  27. +#define GPIO_SET 2
  28. +#define MAX_GPIO_LINE 32*GPIO_SET
  29. +
  30. +wait_queue_head_t gemini_gpio_wait[MAX_GPIO_LINE];
  31. +
  32. +enum GPIO_REG
  33. +{
  34. + GPIO_DATA_OUT = 0x00,
  35. + GPIO_DATA_IN = 0x04,
  36. + GPIO_PIN_DIR = 0x08,
  37. + GPIO_BY_PASS = 0x0C,
  38. + GPIO_DATA_SET = 0x10,
  39. + GPIO_DATA_CLEAR = 0x14,
  40. + GPIO_PULL_ENABLE = 0x18,
  41. + GPIO_PULL_TYPE = 0x1C,
  42. + GPIO_INT_ENABLE = 0x20,
  43. + GPIO_INT_RAW_STATUS = 0x24,
  44. + GPIO_INT_MASK_STATUS = 0x28,
  45. + GPIO_INT_MASK = 0x2C,
  46. + GPIO_INT_CLEAR = 0x30,
  47. + GPIO_INT_TRIG = 0x34,
  48. + GPIO_INT_BOTH = 0x38,
  49. + GPIO_INT_POLAR = 0x3C
  50. +};
  51. +
  52. +unsigned int regist_gpio_int0=0,regist_gpio_int1=0;
  53. +
  54. +/* defines a specific GPIO bit number and state */
  55. +struct gpio_bit {
  56. + unsigned char bit;
  57. + unsigned char state;
  58. +};
  59. +
  60. +#define GPIO_MAJOR 10
  61. +#define GPIO_MINOR 127
  62. +
  63. +/*
  64. + * ioctl calls that are permitted to the /dev/gpio interface
  65. + */
  66. +#define GPIO_GET_BIT 0x0000001
  67. +#define GPIO_SET_BIT 0x0000002
  68. +#define GPIO_GET_CONFIG 0x0000003
  69. +#define GPIO_SET_CONFIG 0x0000004
  70. +
  71. +//#define GPIO_CONFIG_OUT 1
  72. +//#define GPIO_CONFIG_IN 2
  73. +
  74. +
  75. +
  76. +#define DEVICE_NAME "gpio"
  77. +
  78. +//#define DEBUG
  79. +
  80. +/*
  81. + * GPIO interface
  82. + */
  83. +
  84. +/* /dev/gpio */
  85. +static int gpio_ioctl(struct inode *inode, struct file *file,
  86. + unsigned int cmd, unsigned long arg);
  87. +
  88. +/* /proc/driver/gpio */
  89. +static int gpio_read_proc(char *page, char **start, off_t off,
  90. + int count, int *eof, void *data);
  91. +
  92. +static unsigned char gpio_status; /* bitmapped status byte. */
  93. +
  94. +/* functions for set/get gpio lines on storlink cpu */
  95. +
  96. +void gpio_line_get(unsigned char pin, u32 * data)
  97. +{
  98. + unsigned int set = pin >>5; // each GPIO set has 32 pins
  99. + unsigned int status,addr;
  100. +
  101. + addr = (set ? GEMINI_GPIO_BASE2:GEMINI_GPIO_BASE1) + GPIO_DATA_IN;
  102. + status = readl(addr);
  103. +#ifdef DEBUG
  104. + printk("status = %08X, pin = %d, set = %d\n", status, pin, set);
  105. +#endif
  106. + if (set)
  107. + *data = (status&(1<<(pin-32)))?1:0;
  108. + else
  109. + *data = (status&(1<<pin))?1:0;
  110. +}
  111. +
  112. +void gpio_line_set(unsigned char pin, u32 high)
  113. +{
  114. + unsigned char set = pin >>5; // each GPIO set has 32 pins
  115. + unsigned int status=0,addr;
  116. +
  117. + addr = (set ? GEMINI_GPIO_BASE2:GEMINI_GPIO_BASE1)+(high?GPIO_DATA_SET:GPIO_DATA_CLEAR);
  118. +
  119. + status &= ~(1 << (pin %32));
  120. + status |= (1 << (pin % 32));
  121. + writel(status,addr);
  122. +}
  123. +
  124. +/*
  125. + * pin = [0..63]
  126. + * mode =
  127. + * 1 -- OUT
  128. + * 2 -- IN
  129. + */
  130. +void gpio_line_config(unsigned char pin, unsigned char mode)
  131. +{
  132. + unsigned char set = pin >>5; // each GPIO set has 32 pins
  133. + unsigned int status,addr;
  134. +
  135. + addr = (set ? GEMINI_GPIO_BASE2:GEMINI_GPIO_BASE1)+GPIO_PIN_DIR;
  136. + status = readl(addr);
  137. +
  138. + status &= ~(1 << (pin %32));
  139. + if (mode == 1)
  140. + status |= (1 << (pin % 32)); /* PinDir: 0 - input, 1 - output */
  141. +
  142. + writel(status,addr);
  143. +#if 0
  144. + /* enable pullup-high if mode is input */
  145. +
  146. + addr = (set ? GEMINI_GPIO_BASE2:GEMINI_GPIO_BASE1)+GPIO_PULL_ENABLE;
  147. + status = readl(addr);
  148. +
  149. + status &= ~(1 << (pin %32));
  150. + if (mode == 2) /* input */
  151. + status |= (1 << (pin % 32)); /* PullEnable: 0 - disable, 1 - enable */
  152. +
  153. + writel(status,addr);
  154. +
  155. + addr = (set ? GEMINI_GPIO_BASE2:GEMINI_GPIO_BASE1)+GPIO_PULL_TYPE;
  156. + status = readl(addr);
  157. +
  158. + status &= ~(1 << (pin %32));
  159. + if (mode == 2) /* input */
  160. + status |= (1 << (pin % 32)); /* PullType: 0 - low, 1 - high */
  161. +
  162. + writel(status,addr);
  163. +#endif
  164. +}
  165. +
  166. +#define GPIO_IS_OPEN 0x01 /* means /dev/gpio is in use */
  167. +
  168. +/*
  169. + * Now all the various file operations that we export.
  170. + */
  171. +static int gpio_ioctl(struct inode *inode, struct file *file,
  172. + unsigned int cmd, unsigned long arg)
  173. +{
  174. + struct gpio_bit bit;
  175. + u32 val;
  176. +
  177. + if (copy_from_user(&bit, (struct gpio_bit *)arg,
  178. + sizeof(bit)))
  179. + return -EFAULT;
  180. +
  181. + switch (cmd) {
  182. +
  183. + case GPIO_GET_BIT:
  184. + gpio_line_get(bit.bit, &val);
  185. + bit.state = val;
  186. + return copy_to_user((void *)arg, &bit, sizeof(bit)) ? -EFAULT : 0;
  187. + case GPIO_SET_BIT:
  188. + val = bit.state;
  189. + gpio_line_set(bit.bit, val);
  190. + return 0;
  191. + case GPIO_GET_CONFIG:
  192. + // gpio_line_config(bit.bit, bit.state);
  193. + return copy_to_user((void *)arg, &bit, sizeof(bit)) ? -EFAULT : 0;
  194. + case GPIO_SET_CONFIG:
  195. + val = bit.state;
  196. + gpio_line_config(bit.bit, bit.state);
  197. + return 0;
  198. + }
  199. + return -EINVAL;
  200. +}
  201. +
  202. +
  203. +static int gpio_open(struct inode *inode, struct file *file)
  204. +{
  205. + if (gpio_status & GPIO_IS_OPEN)
  206. + return -EBUSY;
  207. +
  208. + gpio_status |= GPIO_IS_OPEN;
  209. + return 0;
  210. +}
  211. +
  212. +
  213. +static int gpio_release(struct inode *inode, struct file *file)
  214. +{
  215. + /*
  216. + * Turn off all interrupts once the device is no longer
  217. + * in use and clear the data.
  218. + */
  219. +
  220. + gpio_status &= ~GPIO_IS_OPEN;
  221. + return 0;
  222. +}
  223. +
  224. +
  225. +/*
  226. + * The various file operations we support.
  227. + */
  228. +
  229. +static struct file_operations gpio_fops = {
  230. + .owner = THIS_MODULE,
  231. + .ioctl = gpio_ioctl,
  232. + .open = gpio_open,
  233. + .release = gpio_release,
  234. +};
  235. +
  236. +static struct miscdevice gpio_dev =
  237. +{
  238. + .minor = GPIO_MINOR,
  239. + .name = "gpio",
  240. + .fops = &gpio_fops,
  241. +};
  242. +
  243. +
  244. +
  245. +
  246. +#ifdef CONFIG_PROC_FS
  247. +static struct proc_dir_entry *dir;
  248. +
  249. +/*
  250. + * Info exported via "/proc/driver/gpio".
  251. + */
  252. +static int gpio_get_status(char *buf)
  253. +{
  254. + char *p = buf;
  255. + u32 val = 0;
  256. + int i;
  257. + int bit;
  258. +#ifdef DEBUG
  259. + u32 addr;
  260. +
  261. + for (i = 0; i < 0x20; i+=4 ) {
  262. + addr = IO_ADDRESS(SL2312_GPIO_BASE) + i;
  263. + val = readl(addr);
  264. + p+=sprintf(p, "GPIO0: 0x%02X: %08X\n", i, val );
  265. + }
  266. + for (i = 0; i < 0x20; i+=4 ) {
  267. + addr = IO_ADDRESS(SL2312_GPIO_BASE1) + i;
  268. + val = readl(addr);
  269. + p+=sprintf(p, "GPIO1: 0x%02X: %08X\n", i, val );
  270. + }
  271. +#endif
  272. +
  273. + for (i = 0; i < 32; i++) {
  274. + gpio_line_get(i, &bit);
  275. + if (bit)
  276. + val |= (1 << i);
  277. + }
  278. + p += sprintf(p, "gpio0\t: 0x%08x\n", val);
  279. +
  280. + val = 0;
  281. + for (i = 32; i < 64; i++) {
  282. + gpio_line_get(i, &bit);
  283. + if (bit)
  284. + val |= (1 << i);
  285. + }
  286. + p += sprintf(p, "gpio1\t: 0x%08x\n", val);
  287. +
  288. + return p - buf;
  289. +}
  290. +
  291. +
  292. +/* /proc/driver/gpio read op
  293. + */
  294. +static int gpio_read_proc(char *page, char **start, off_t off,
  295. + int count, int *eof, void *data)
  296. +{
  297. + int len = gpio_get_status (page);
  298. +
  299. + if (len <= off+count)
  300. + *eof = 1;
  301. + *start = page + off;
  302. + len -= off;
  303. + if ( len > count )
  304. + len = count;
  305. + if ( len < 0 )
  306. + len = 0;
  307. + return len;
  308. +}
  309. +#endif /* CONFIG_PROC_FS */
  310. +
  311. +
  312. +static int __init gpio_init_module(void)
  313. +{
  314. + int retval;
  315. +#ifdef CONFIG_PROC_FS
  316. + struct proc_dir_entry *res;
  317. +#endif
  318. +
  319. + /* register /dev/gpio file ops */
  320. + //retval = register_chrdev(GPIO_MAJOR, DEVICE_NAME, &gpio_fops);
  321. + retval = misc_register(&gpio_dev);
  322. + if(retval < 0)
  323. + return retval;
  324. +
  325. +#ifdef CONFIG_PROC_FS
  326. + dir = proc_mkdir("driver/gpio", NULL);
  327. + if (!dir) {
  328. + misc_deregister(&gpio_dev);
  329. + return -ENOMEM;
  330. + }
  331. + /* register /proc/driver/gpio */
  332. + res = create_proc_entry("info", 0644, dir);
  333. + if (res) {
  334. + res->read_proc= gpio_read_proc;
  335. + } else {
  336. + misc_deregister(&gpio_dev);
  337. + return -ENOMEM;
  338. + }
  339. +#endif
  340. +
  341. + printk("%s: GPIO driver loaded\n", __FILE__);
  342. +
  343. + return 0;
  344. +}
  345. +
  346. +static void __exit gpio_cleanup_module(void)
  347. +{
  348. + remove_proc_entry ("info", dir);
  349. + misc_deregister(&gpio_dev);
  350. +
  351. + printk("%s: GPIO driver unloaded\n", __FILE__);
  352. +}
  353. +
  354. +module_init(gpio_init_module);
  355. +module_exit(gpio_cleanup_module);
  356. +
  357. +MODULE_AUTHOR("Jonas Majauskas");
  358. +MODULE_LICENSE("GPL");
  359. +
  360. --- a/drivers/char/Kconfig
  361. +++ b/drivers/char/Kconfig
  362. @@ -1064,5 +1064,12 @@
  363. source "drivers/s390/char/Kconfig"
  364. +config GEMINI_GPIO_DEV
  365. + tristate "GPIO driver for Gemini board (provides /dev/gpio)"
  366. + depends on ARCH_SL2312
  367. + default n
  368. + help
  369. + GPIO driver for Gemini boards - SL3512, SL3516.
  370. +
  371. endmenu
  372. --- a/drivers/char/Makefile
  373. +++ b/drivers/char/Makefile
  374. @@ -115,6 +115,7 @@
  375. obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o
  376. obj-$(CONFIG_TCG_TPM) += tpm/
  377. +obj-$(CONFIG_GEMINI_GPIO_DEV) += gemini_gpio_dev.o
  378. obj-$(CONFIG_PS3_FLASH) += ps3flash.o