PageRenderTime 35ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/arch/arm/mach-msm/board-sapphire-gpio.c

https://bitbucket.org/sammyz/iscream_thunderc-2.6.35-rebase
C | 326 lines | 215 code | 55 blank | 56 comment | 19 complexity | 31426d6facc2c3d0382180922aa55863 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
  1. /* arch/arm/mach-msm/board-sapphire-gpio.c
  2. * Copyright (C) 2007-2009 HTC Corporation.
  3. * Author: Thomas Tsai <thomas_tsai@htc.com>
  4. *
  5. * This software is licensed under the terms of the GNU General Public
  6. * License version 2, as published by the Free Software Foundation, and
  7. * may be copied, distributed, and modified under those terms.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. */
  14. #include <linux/kernel.h>
  15. #include <linux/errno.h>
  16. #include <linux/irq.h>
  17. #include <linux/pm.h>
  18. #include <linux/sysdev.h>
  19. #include <linux/io.h>
  20. #include <linux/gpio.h>
  21. #include <asm/mach-types.h>
  22. #include "gpio_chip.h"
  23. #include "board-sapphire.h"
  24. #ifdef DEBUG_SAPPHIRE_GPIO
  25. #define DBG(fmt, arg...) printk(KERN_INFO "%s: " fmt "\n", __func__, ## arg)
  26. #else
  27. #define DBG(fmt, arg...) do {} while (0)
  28. #endif
  29. #define SAPPHIRE_CPLD_INT_STATUS (SAPPHIRE_CPLD_BASE + 0x0E)
  30. #define SAPPHIRE_CPLD_INT_LEVEL (SAPPHIRE_CPLD_BASE + 0x08)
  31. #define SAPPHIRE_CPLD_INT_MASK (SAPPHIRE_CPLD_BASE + 0x0C)
  32. /*CPLD misc reg offset*/
  33. static const int _g_CPLD_MISCn_Offset[] = { 0x0A, /*misc1 reg*/
  34. 0x00, /*misc2 reg*/
  35. 0x02, /*misc3 reg*/
  36. 0x04, /*misc4 reg*/
  37. 0x06}; /*misc5 reg*/
  38. /*CPLD INT Bank*/
  39. /*BANK0: int1 status, int2 level, int3 mask*/
  40. static const int _g_INT_BANK_Offset[][3] = {{0x0E, 0x08, 0x0C} };
  41. static uint8_t sapphire_cpld_initdata[4] = {
  42. [0] = 0x80, /* for serial debug UART3, low current misc2*/
  43. [1] = 0x34, /* jog & tp enable, I2C pull misc3*/
  44. [3] = 0x04, /* mmdi 32k en misc5*/
  45. };
  46. /*save current working int mask, so the value can be restored after resume.
  47. Sapphire has only bank0.*/
  48. static uint8_t sapphire_int_mask[] = {
  49. [0] = 0xfb, /* enable all interrupts, bit 2 is not used */
  50. };
  51. /*Sleep have to prepare the wake up source in advance.
  52. default to disable all wakeup sources when suspend.*/
  53. static uint8_t sapphire_sleep_int_mask[] = {
  54. [0] = 0x00, /* bit2 is not used */
  55. };
  56. static int sapphire_suspended;
  57. static int sapphire_gpio_read(struct gpio_chip *chip, unsigned n)
  58. {
  59. if (n < SAPPHIRE_GPIO_INT_B0_BASE) /*MISCn*/
  60. return !!(readb(CPLD_GPIO_REG(n)) & CPLD_GPIO_BIT_POS_MASK(n));
  61. else if (n <= SAPPHIRE_GPIO_END) /*gpio n is INT pin*/
  62. return !!(readb(CPLD_INT_LEVEL_REG_G(n)) &
  63. CPLD_GPIO_BIT_POS_MASK(n));
  64. return 0;
  65. }
  66. /*CPLD Write only register :MISC2, MISC3, MISC4, MISC5 => reg=0,2,4,6
  67. Reading from write-only registers is undefined, so the writing value
  68. should be kept in shadow for later usage.*/
  69. int sapphire_gpio_write(struct gpio_chip *chip, unsigned n, unsigned on)
  70. {
  71. unsigned long flags;
  72. uint8_t reg_val;
  73. if (n > SAPPHIRE_GPIO_END)
  74. return -1;
  75. local_irq_save(flags);
  76. reg_val = readb(CPLD_GPIO_REG(n));
  77. if (on)
  78. reg_val |= CPLD_GPIO_BIT_POS_MASK(n);
  79. else
  80. reg_val &= ~CPLD_GPIO_BIT_POS_MASK(n);
  81. writeb(reg_val, CPLD_GPIO_REG(n));
  82. DBG("gpio=%d, l=0x%x\r\n", n, readb(SAPPHIRE_CPLD_INT_LEVEL));
  83. local_irq_restore(flags);
  84. return 0;
  85. }
  86. static int sapphire_gpio_configure(struct gpio_chip *chip, unsigned int gpio,
  87. unsigned long flags)
  88. {
  89. if (flags & (GPIOF_OUTPUT_LOW | GPIOF_OUTPUT_HIGH))
  90. sapphire_gpio_write(chip, gpio, flags & GPIOF_OUTPUT_HIGH);
  91. DBG("gpio=%d, l=0x%x\r\n", gpio, readb(SAPPHIRE_CPLD_INT_LEVEL));
  92. return 0;
  93. }
  94. static int sapphire_gpio_get_irq_num(struct gpio_chip *chip, unsigned int gpio,
  95. unsigned int *irqp, unsigned long *irqnumflagsp)
  96. {
  97. DBG("gpio=%d, l=0x%x\r\n", gpio, readb(SAPPHIRE_CPLD_INT_LEVEL));
  98. DBG("SAPPHIRE_GPIO_INT_B0_BASE=%d, SAPPHIRE_GPIO_LAST_INT=%d\r\n",
  99. SAPPHIRE_GPIO_INT_B0_BASE, SAPPHIRE_GPIO_LAST_INT);
  100. if ((gpio < SAPPHIRE_GPIO_INT_B0_BASE) ||
  101. (gpio > SAPPHIRE_GPIO_LAST_INT))
  102. return -ENOENT;
  103. *irqp = SAPPHIRE_GPIO_TO_INT(gpio);
  104. DBG("*irqp=%d\r\n", *irqp);
  105. if (irqnumflagsp)
  106. *irqnumflagsp = 0;
  107. return 0;
  108. }
  109. /*write 1 to clear INT status bit.*/
  110. static void sapphire_gpio_irq_ack(unsigned int irq)
  111. {
  112. /*write 1 to clear*/
  113. writeb(SAPPHIRE_INT_BIT_MASK(irq), CPLD_INT_STATUS_REG(irq));
  114. }
  115. /*unmask/enable the INT
  116. static void sapphire_gpio_irq_unmask(unsigned int irq)*/
  117. static void sapphire_gpio_irq_enable(unsigned int irq)
  118. {
  119. unsigned long flags;
  120. uint8_t reg_val;
  121. local_irq_save(flags); /*disabling all interrupts*/
  122. reg_val = readb(CPLD_INT_MASK_REG(irq)) | SAPPHIRE_INT_BIT_MASK(irq);
  123. DBG("(irq=%d,0x%x, 0x%x)\r\n", irq, CPLD_INT_MASK_REG(irq),
  124. SAPPHIRE_INT_BIT_MASK(irq));
  125. DBG("sapphire_suspended=%d\r\n", sapphire_suspended);
  126. /*printk(KERN_INFO "sapphire_gpio_irq_mask irq %d => %d:%02x\n",
  127. irq, bank, reg_val);*/
  128. if (!sapphire_suspended)
  129. writeb(reg_val, CPLD_INT_MASK_REG(irq));
  130. reg_val = readb(CPLD_INT_MASK_REG(irq));
  131. DBG("reg_val= 0x%x\r\n", reg_val);
  132. DBG("l=0x%x\r\n", readb(SAPPHIRE_CPLD_INT_LEVEL));
  133. local_irq_restore(flags); /*restore the interrupts*/
  134. }
  135. /*mask/disable INT
  136. static void sapphire_gpio_irq_mask(unsigned int irq)*/
  137. static void sapphire_gpio_irq_disable(unsigned int irq)
  138. {
  139. unsigned long flags;
  140. uint8_t reg_val;
  141. local_irq_save(flags);
  142. reg_val = readb(CPLD_INT_MASK_REG(irq)) & ~SAPPHIRE_INT_BIT_MASK(irq);
  143. /*CPLD INT MASK is r/w now.*/
  144. /*printk(KERN_INFO "sapphire_gpio_irq_unmask irq %d => %d:%02x\n",
  145. irq, bank, reg_val);*/
  146. DBG("(%d,0x%x, 0x%x, 0x%x)\r\n", irq, reg_val, CPLD_INT_MASK_REG(irq),
  147. SAPPHIRE_INT_BIT_MASK(irq));
  148. DBG("sapphire_suspended=%d\r\n", sapphire_suspended);
  149. if (!sapphire_suspended)
  150. writeb(reg_val, CPLD_INT_MASK_REG(irq));
  151. reg_val = readb(CPLD_INT_MASK_REG(irq));
  152. DBG("reg_val= 0x%x\r\n", reg_val);
  153. DBG("l=0x%x\r\n", readb(SAPPHIRE_CPLD_INT_LEVEL));
  154. local_irq_restore(flags);
  155. }
  156. /*preparing enable/disable wake source before sleep*/
  157. int sapphire_gpio_irq_set_wake(unsigned int irq, unsigned int on)
  158. {
  159. unsigned long flags;
  160. uint8_t mask = SAPPHIRE_INT_BIT_MASK(irq);
  161. local_irq_save(flags);
  162. if (on) /*wake on -> mask the bit*/
  163. sapphire_sleep_int_mask[CPLD_INT_TO_BANK(irq)] |= mask;
  164. else /*no wake -> unmask the bit*/
  165. sapphire_sleep_int_mask[CPLD_INT_TO_BANK(irq)] &= ~mask;
  166. local_irq_restore(flags);
  167. return 0;
  168. }
  169. /*Sapphire has only one INT Bank.*/
  170. static void sapphire_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
  171. {
  172. int j;
  173. unsigned v;
  174. int int_base = SAPPHIRE_INT_START;
  175. v = readb(SAPPHIRE_CPLD_INT_STATUS); /*INT1 status reg, BANK0*/
  176. for (j = 0; j < 8 ; j++) { /*8 bit per bank*/
  177. if (v & (1U << j)) { /*got the INT Bit*/
  178. DBG("generic_handle_irq j=0x%x\r\n", j);
  179. generic_handle_irq(int_base + j);
  180. }
  181. }
  182. desc->chip->ack(irq); /*clear CPLD INT in SOC side.*/
  183. DBG("irq=%d, l=0x%x\r\n", irq, readb(SAPPHIRE_CPLD_INT_LEVEL));
  184. }
  185. /*Save current working sources before sleep, so we can restore it after
  186. * resume.*/
  187. static int sapphire_sysdev_suspend(struct sys_device *dev, pm_message_t state)
  188. {
  189. sapphire_suspended = 1;
  190. /*save current masking*/
  191. sapphire_int_mask[0] = readb(SAPPHIRE_CPLD_BASE +
  192. SAPPHIRE_GPIO_INT_B0_MASK_REG);
  193. /*set waking source before sleep.*/
  194. writeb(sapphire_sleep_int_mask[0],
  195. SAPPHIRE_CPLD_BASE + SAPPHIRE_GPIO_INT_B0_MASK_REG);
  196. return 0;
  197. }
  198. /*All the registers will be kept till a power loss...*/
  199. int sapphire_sysdev_resume(struct sys_device *dev)
  200. {
  201. /*restore the working mask saved before sleep*/
  202. writeb(sapphire_int_mask[0], SAPPHIRE_CPLD_BASE +
  203. SAPPHIRE_GPIO_INT_B0_MASK_REG);
  204. sapphire_suspended = 0;
  205. return 0;
  206. }
  207. /**
  208. * linux/irq.h :: struct irq_chip
  209. * @enable: enable the interrupt (defaults to chip->unmask if NULL)
  210. * @disable: disable the interrupt (defaults to chip->mask if NULL)
  211. * @ack: start of a new interrupt
  212. * @mask: mask an interrupt source
  213. * @mask_ack: ack and mask an interrupt source
  214. * @unmask: unmask an interrupt source
  215. */
  216. static struct irq_chip sapphire_gpio_irq_chip = {
  217. .name = "sapphiregpio",
  218. .ack = sapphire_gpio_irq_ack,
  219. .mask = sapphire_gpio_irq_disable, /*sapphire_gpio_irq_mask,*/
  220. .unmask = sapphire_gpio_irq_enable, /*sapphire_gpio_irq_unmask,*/
  221. .set_wake = sapphire_gpio_irq_set_wake,
  222. /*.set_type = sapphire_gpio_irq_set_type,*/
  223. };
  224. /*Thomas:For CPLD*/
  225. static struct gpio_chip sapphire_gpio_chip = {
  226. .start = SAPPHIRE_GPIO_START,
  227. .end = SAPPHIRE_GPIO_END,
  228. .configure = sapphire_gpio_configure,
  229. .get_irq_num = sapphire_gpio_get_irq_num,
  230. .read = sapphire_gpio_read,
  231. .write = sapphire_gpio_write,
  232. /* .read_detect_status = sapphire_gpio_read_detect_status,
  233. .clear_detect_status = sapphire_gpio_clear_detect_status */
  234. };
  235. struct sysdev_class sapphire_sysdev_class = {
  236. .name = "sapphiregpio_irq",
  237. .suspend = sapphire_sysdev_suspend,
  238. .resume = sapphire_sysdev_resume,
  239. };
  240. static struct sys_device sapphire_irq_device = {
  241. .cls = &sapphire_sysdev_class,
  242. };
  243. int sapphire_init_gpio(void)
  244. {
  245. int i;
  246. if (!machine_is_sapphire())
  247. return 0;
  248. DBG("%d,%d\r\n", SAPPHIRE_INT_START, SAPPHIRE_INT_END);
  249. DBG("NR_MSM_IRQS=%d, NR_GPIO_IRQS=%d\r\n", NR_MSM_IRQS, NR_GPIO_IRQS);
  250. for (i = SAPPHIRE_INT_START; i <= SAPPHIRE_INT_END; i++) {
  251. set_irq_chip(i, &sapphire_gpio_irq_chip);
  252. set_irq_handler(i, handle_edge_irq);
  253. set_irq_flags(i, IRQF_VALID);
  254. }
  255. register_gpio_chip(&sapphire_gpio_chip);
  256. /*setup CPLD INT connecting to SOC's gpio 17 */
  257. set_irq_type(MSM_GPIO_TO_INT(17), IRQF_TRIGGER_HIGH);
  258. set_irq_chained_handler(MSM_GPIO_TO_INT(17), sapphire_gpio_irq_handler);
  259. set_irq_wake(MSM_GPIO_TO_INT(17), 1);
  260. if (sysdev_class_register(&sapphire_sysdev_class) == 0)
  261. sysdev_register(&sapphire_irq_device);
  262. return 0;
  263. }
  264. int sapphire_init_cpld(unsigned int sys_rev)
  265. {
  266. int i;
  267. for (i = 0; i < ARRAY_SIZE(sapphire_cpld_initdata); i++)
  268. writeb(sapphire_cpld_initdata[i], SAPPHIRE_CPLD_BASE + i * 2);
  269. return 0;
  270. }
  271. postcore_initcall(sapphire_init_gpio);