PageRenderTime 55ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/recipes/linux/linux-2.6.21/proc-gpio.patch

https://github.com/Martix/Eonos
Patch | 328 lines | 326 code | 2 blank | 0 comment | 0 complexity | 1d9eb4ce223c237dccbd84f4f55ab105 MD5 | raw file
  1. Index: linux-2.6.21gum/arch/arm/Kconfig
  2. ===================================================================
  3. --- linux-2.6.21gum.orig/arch/arm/Kconfig
  4. +++ linux-2.6.21gum/arch/arm/Kconfig
  5. @@ -505,6 +505,8 @@ config PCI_HOST_VIA82C505
  6. depends on PCI && ARCH_SHARK
  7. default y
  8. +source "drivers/gpio/Kconfig"
  9. +
  10. source "drivers/pci/Kconfig"
  11. source "drivers/pcmcia/Kconfig"
  12. Index: linux-2.6.21gum/drivers/Makefile
  13. ===================================================================
  14. --- linux-2.6.21gum.orig/drivers/Makefile
  15. +++ linux-2.6.21gum/drivers/Makefile
  16. @@ -81,3 +81,4 @@ obj-$(CONFIG_GENERIC_TIME) += clocksourc
  17. obj-$(CONFIG_DMA_ENGINE) += dma/
  18. obj-$(CONFIG_HID) += hid/
  19. obj-$(CONFIG_PPC_PS3) += ps3/
  20. +obj-$(CONFIG_PROC_GPIO) += gpio/
  21. Index: linux-2.6.21gum/drivers/gpio/Kconfig
  22. ===================================================================
  23. --- /dev/null
  24. +++ linux-2.6.21gum/drivers/gpio/Kconfig
  25. @@ -0,0 +1,12 @@
  26. +config PROC_GPIO
  27. + tristate "GPIO /proc interface"
  28. + depends on PXA25x || PXA27x
  29. + help
  30. + This enables an interface under /proc/gpio which allows reading or setting
  31. + of any GPIO, and also changing the GPIO alt function mode of any line.
  32. +
  33. +config PROC_GPIO_DEBUG
  34. + boolean "Enable /proc/gpio debug logging"
  35. + depends on PROC_GPIO
  36. + help
  37. + This enables printk logging of activity done through /proc/gpio
  38. Index: linux-2.6.21gum/drivers/gpio/Makefile
  39. ===================================================================
  40. --- /dev/null
  41. +++ linux-2.6.21gum/drivers/gpio/Makefile
  42. @@ -0,0 +1,3 @@
  43. +# Expose GPIOs under /proc
  44. +obj-$(CONFIG_PROC_GPIO) += proc_gpio.o
  45. +
  46. Index: linux-2.6.21gum/drivers/gpio/proc_gpio.c
  47. ===================================================================
  48. --- /dev/null
  49. +++ linux-2.6.21gum/drivers/gpio/proc_gpio.c
  50. @@ -0,0 +1,276 @@
  51. +/*
  52. + *
  53. + * PXA25x GPIOs exposed under /proc for reading and writing
  54. + * They will show up under /proc/gpio/NN
  55. + *
  56. + * Based on patch 1773/1 in the arm kernel patch repository at arm.linux.co.uk
  57. + *
  58. + */
  59. +
  60. +#include <linux/module.h>
  61. +#include <linux/init.h>
  62. +#include <linux/proc_fs.h>
  63. +#include <linux/string.h>
  64. +#include <linux/ctype.h>
  65. +
  66. +#include <asm/hardware.h>
  67. +#include <asm/arch/pxa-regs.h>
  68. +#include <asm/uaccess.h>
  69. +
  70. +static struct proc_dir_entry *proc_gpio_parent;
  71. +static struct proc_dir_entry *proc_gpios[PXA_LAST_GPIO + 1];
  72. +
  73. +typedef struct
  74. +{
  75. + int gpio;
  76. + char name[32];
  77. +} gpio_summary_type;
  78. +
  79. +static gpio_summary_type gpio_summaries[PXA_LAST_GPIO + 1];
  80. +
  81. +static int proc_gpio_write(struct file *file, const char __user *buf,
  82. + unsigned long count, void *data)
  83. +{
  84. + char *cur, lbuf[count + 1];
  85. + gpio_summary_type *summary = data;
  86. + u32 altfn, direction, setclear, gafr;
  87. +
  88. + if (!capable(CAP_SYS_ADMIN))
  89. + return -EACCES;
  90. +
  91. + memset(lbuf, 0, count + 1);
  92. +
  93. + if (copy_from_user(lbuf, buf, count))
  94. + return -EFAULT;
  95. +
  96. + cur = lbuf;
  97. +
  98. + // Initialize to current state
  99. + altfn = ((GAFR(summary->gpio) >> ((summary->gpio & 0x0f) << 0x01)) & 0x03);
  100. + direction = GPDR(summary->gpio) & GPIO_bit(summary->gpio);
  101. + setclear = GPLR(summary->gpio) & GPIO_bit(summary->gpio);
  102. + while(1)
  103. + {
  104. + // We accept options: {GPIO|AF1|AF2|AF3}, {set|clear}, {in|out}
  105. + // Anything else is an error
  106. + while(cur[0] && (isspace(cur[0]) || ispunct(cur[0]))) cur = &(cur[1]);
  107. +
  108. + if('\0' == cur[0]) break;
  109. +
  110. + // Ok, so now we're pointing at the start of something
  111. + switch(cur[0])
  112. + {
  113. + case 'G':
  114. + // Check that next is "PIO" -- '\0' will cause safe short-circuit if end of buf
  115. + if(!(cur[1] == 'P' && cur[2] == 'I' && cur[3] == 'O')) goto parse_error;
  116. + // Ok, so set this GPIO to GPIO (non-ALT) function
  117. + altfn = 0;
  118. + cur = &(cur[4]);
  119. + break;
  120. + case 'A':
  121. + if(!(cur[1] == 'F' && cur[2] >= '1' && cur[2] <= '3')) goto parse_error;
  122. + altfn = cur[2] - '0';
  123. + cur = &(cur[3]);
  124. + break;
  125. + case 's':
  126. + if(!(cur[1] == 'e' && cur[2] == 't')) goto parse_error;
  127. + setclear = 1;
  128. + cur = &(cur[3]);
  129. + break;
  130. + case 'c':
  131. + if(!(cur[1] == 'l' && cur[2] == 'e' && cur[3] == 'a' && cur[4] == 'r')) goto parse_error;
  132. + setclear = 0;
  133. + cur = &(cur[5]);
  134. + break;
  135. + case 'i':
  136. + if(!(cur[1] == 'n')) goto parse_error;
  137. + direction = 0;
  138. + cur = &(cur[2]);
  139. + break;
  140. + case 'o':
  141. + if(!(cur[1] == 'u' && cur[2] == 't')) goto parse_error;
  142. + direction = 1;
  143. + cur = &(cur[3]);
  144. + break;
  145. + default: goto parse_error;
  146. + }
  147. + }
  148. + // Ok, now set gpio mode and value
  149. + if(direction)
  150. + GPDR(summary->gpio) |= GPIO_bit(summary->gpio);
  151. + else
  152. + GPDR(summary->gpio) &= ~GPIO_bit(summary->gpio);
  153. +
  154. + gafr = GAFR(summary->gpio) & ~(0x3 << (((summary->gpio) & 0xf)*2));
  155. + GAFR(summary->gpio) = gafr | (altfn << (((summary->gpio) & 0xf)*2));
  156. +
  157. + if(direction && !altfn)
  158. + {
  159. + if(setclear) GPSR(summary->gpio) = GPIO_bit(summary->gpio);
  160. + else GPCR(summary->gpio) = GPIO_bit(summary->gpio);
  161. + }
  162. +
  163. +#ifdef CONFIG_PROC_GPIO_DEBUG
  164. + printk(KERN_INFO "Set (%s,%s,%s) via /proc/gpio/%s\n",altfn ? (altfn == 1 ? "AF1" : (altfn == 2 ? "AF2" : "AF3")) : "GPIO",
  165. + direction ? "out" : "in",
  166. + setclear ? "set" : "clear",
  167. + summary->name);
  168. +#endif
  169. +
  170. + return count;
  171. +
  172. +parse_error:
  173. + printk(KERN_CRIT "Parse error: Expect \"[GPIO|AF1|AF2|AF3]|[set|clear]|[in|out] ...\"\n");
  174. + return -EINVAL;
  175. +}
  176. +
  177. +static int proc_gpio_read(char *page, char **start, off_t off,
  178. + int count, int *eof, void *data)
  179. +{
  180. + char *p = page;
  181. + gpio_summary_type *summary = data;
  182. + int len, i, af;
  183. + i = summary->gpio;
  184. +
  185. + p += sprintf(p, "%d\t%s\t%s\t%s\n", i,
  186. + (af = ((GAFR(i) >> ((i & 0x0f) << 0x01)) & 0x03)) ? (af == 1 ? "AF1" : (af == 2 ? "AF2" : "AF3")) : "GPIO",
  187. + (GPDR(i) & GPIO_bit(i)) ? "out" : "in",
  188. + (GPLR(i) & GPIO_bit(i)) ? "set" : "clear");
  189. +
  190. + len = (p - page) - off;
  191. +
  192. + if(len < 0)
  193. + {
  194. + len = 0;
  195. + }
  196. +
  197. + *eof = (len <= count) ? 1 : 0;
  198. + *start = page + off;
  199. +
  200. + return len;
  201. +}
  202. +
  203. +
  204. +#ifdef CONFIG_PXA25x
  205. +static const char const *GAFR_DESC[] = { "GAFR0_L", "GAFR0_U", "GAFR1_L", "GAFR1_U", "GAFR2_L", "GAFR2_U" };
  206. +#elif defined(CONFIG_PXA27x)
  207. +static const char const *GAFR_DESC[] = { "GAFR0_L", "GAFR0_U", "GAFR1_L", "GAFR1_U", "GAFR2_L", "GAFR2_U", "GAFR3_L", "GAFR3_U" };
  208. +#endif
  209. +
  210. +static int proc_gafr_read(char *page, char **start, off_t off,
  211. + int count, int *eof, void *data)
  212. +{
  213. + char *p = page;
  214. + int i, len;
  215. +
  216. + for(i=0; i<ARRAY_SIZE(GAFR_DESC); i++)
  217. + {
  218. + p += sprintf(p, "%s: %08x\n", GAFR_DESC[i], GAFR(i*16));
  219. + }
  220. +
  221. + len = (p - page) - off;
  222. +
  223. + if(len < 0)
  224. + {
  225. + len = 0;
  226. + }
  227. +
  228. + *eof = (len <= count) ? 1 : 0;
  229. + *start = page + off;
  230. +
  231. + return len;
  232. +}
  233. +
  234. +static int proc_gpdr_read(char *page, char **start, off_t off,
  235. + int count, int *eof, void *data)
  236. +{
  237. + char *p = page;
  238. + int i, len;
  239. +
  240. + for(i=0; i<=2; i++)
  241. + {
  242. + p += sprintf(p, "GPDR%d: %08x\n", i, GPDR(i * 32));
  243. + }
  244. +
  245. + len = (p - page) - off;
  246. +
  247. + if(len < 0)
  248. + {
  249. + len = 0;
  250. + }
  251. +
  252. + *eof = (len <= count) ? 1 : 0;
  253. + *start = page + off;
  254. +
  255. + return len;
  256. +}
  257. +
  258. +static int proc_gplr_read(char *page, char **start, off_t off,
  259. + int count, int *eof, void *data)
  260. +{
  261. + char *p = page;
  262. + int i, len;
  263. +
  264. + for(i=0; i<=2; i++)
  265. + {
  266. + p += sprintf(p, "GPLR%d: %08x\n", i, GPLR(i * 32));
  267. + }
  268. +
  269. + len = (p - page) - off;
  270. +
  271. + if(len < 0)
  272. + {
  273. + len = 0;
  274. + }
  275. +
  276. + *eof = (len <= count) ? 1 : 0;
  277. + *start = page + off;
  278. +
  279. + return len;
  280. +}
  281. +
  282. +static int __init gpio_init(void)
  283. +{
  284. + int i;
  285. +
  286. + proc_gpio_parent = create_proc_entry("gpio", S_IFDIR | S_IRUGO | S_IXUGO, NULL);
  287. + if(!proc_gpio_parent) return 0;
  288. +
  289. + for(i=0; i < (PXA_LAST_GPIO+1); i++)
  290. + {
  291. + gpio_summaries[i].gpio = i;
  292. + sprintf(gpio_summaries[i].name, "GPIO%d", i);
  293. + proc_gpios[i] = create_proc_entry(gpio_summaries[i].name, 0644, proc_gpio_parent);
  294. + if(proc_gpios[i])
  295. + {
  296. + proc_gpios[i]->data = &gpio_summaries[i];
  297. + proc_gpios[i]->read_proc = proc_gpio_read;
  298. + proc_gpios[i]->write_proc = proc_gpio_write;
  299. + }
  300. + }
  301. +
  302. + create_proc_read_entry("GAFR", 0444, proc_gpio_parent, proc_gafr_read, NULL);
  303. + create_proc_read_entry("GPDR", 0444, proc_gpio_parent, proc_gpdr_read, NULL);
  304. + create_proc_read_entry("GPLR", 0444, proc_gpio_parent, proc_gplr_read, NULL);
  305. +
  306. + return 0;
  307. +}
  308. +
  309. +static void gpio_exit(void)
  310. +{
  311. + int i;
  312. +
  313. + remove_proc_entry("GAFR", proc_gpio_parent);
  314. + remove_proc_entry("GPDR", proc_gpio_parent);
  315. + remove_proc_entry("GPLR", proc_gpio_parent);
  316. +
  317. + for(i=0; i < (PXA_LAST_GPIO+1); i++)
  318. + {
  319. + if(proc_gpios[i]) remove_proc_entry(gpio_summaries[i].name, proc_gpio_parent);
  320. + }
  321. + if(proc_gpio_parent) remove_proc_entry("gpio", NULL);
  322. +}
  323. +
  324. +module_init(gpio_init);
  325. +module_exit(gpio_exit);
  326. +MODULE_LICENSE("GPL");