chip.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. /*
  2. * IRQ chip definitions for INTC IRQs.
  3. *
  4. * Copyright (C) 2007, 2008 Magnus Damm
  5. * Copyright (C) 2009, 2010 Paul Mundt
  6. *
  7. * This file is subject to the terms and conditions of the GNU General Public
  8. * License. See the file "COPYING" in the main directory of this archive
  9. * for more details.
  10. */
  11. #include <linux/cpumask.h>
  12. #include <linux/io.h>
  13. #include "internals.h"
  14. void _intc_enable(struct irq_data *data, unsigned long handle)
  15. {
  16. unsigned int irq = data->irq;
  17. struct intc_desc_int *d = get_intc_desc(irq);
  18. unsigned long addr;
  19. unsigned int cpu;
  20. for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_E(handle)); cpu++) {
  21. #ifdef CONFIG_SMP
  22. if (!cpumask_test_cpu(cpu, data->affinity))
  23. continue;
  24. #endif
  25. addr = INTC_REG(d, _INTC_ADDR_E(handle), cpu);
  26. intc_enable_fns[_INTC_MODE(handle)](addr, handle, intc_reg_fns\
  27. [_INTC_FN(handle)], irq);
  28. }
  29. intc_balancing_enable(irq);
  30. }
  31. static void intc_enable(struct irq_data *data)
  32. {
  33. _intc_enable(data, (unsigned long)irq_data_get_irq_chip_data(data));
  34. }
  35. static void intc_disable(struct irq_data *data)
  36. {
  37. unsigned int irq = data->irq;
  38. struct intc_desc_int *d = get_intc_desc(irq);
  39. unsigned long handle = (unsigned long)irq_data_get_irq_chip_data(data);
  40. unsigned long addr;
  41. unsigned int cpu;
  42. intc_balancing_disable(irq);
  43. for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_D(handle)); cpu++) {
  44. #ifdef CONFIG_SMP
  45. if (!cpumask_test_cpu(cpu, data->affinity))
  46. continue;
  47. #endif
  48. addr = INTC_REG(d, _INTC_ADDR_D(handle), cpu);
  49. intc_disable_fns[_INTC_MODE(handle)](addr, handle,intc_reg_fns\
  50. [_INTC_FN(handle)], irq);
  51. }
  52. }
  53. static int intc_set_wake(struct irq_data *data, unsigned int on)
  54. {
  55. return 0; /* allow wakeup, but setup hardware in intc_suspend() */
  56. }
  57. #ifdef CONFIG_SMP
  58. /*
  59. * This is held with the irq desc lock held, so we don't require any
  60. * additional locking here at the intc desc level. The affinity mask is
  61. * later tested in the enable/disable paths.
  62. */
  63. static int intc_set_affinity(struct irq_data *data,
  64. const struct cpumask *cpumask,
  65. bool force)
  66. {
  67. if (!cpumask_intersects(cpumask, cpu_online_mask))
  68. return -1;
  69. cpumask_copy(data->affinity, cpumask);
  70. return 0;
  71. }
  72. #endif
  73. static void intc_mask_ack(struct irq_data *data)
  74. {
  75. unsigned int irq = data->irq;
  76. struct intc_desc_int *d = get_intc_desc(irq);
  77. unsigned long handle = intc_get_ack_handle(irq);
  78. unsigned long addr;
  79. intc_disable(data);
  80. /* read register and write zero only to the associated bit */
  81. if (handle) {
  82. unsigned int value;
  83. addr = INTC_REG(d, _INTC_ADDR_D(handle), 0);
  84. value = intc_set_field_from_handle(0, 1, handle);
  85. switch (_INTC_FN(handle)) {
  86. case REG_FN_MODIFY_BASE + 0: /* 8bit */
  87. __raw_readb(addr);
  88. __raw_writeb(0xff ^ value, addr);
  89. break;
  90. case REG_FN_MODIFY_BASE + 1: /* 16bit */
  91. __raw_readw(addr);
  92. __raw_writew(0xffff ^ value, addr);
  93. break;
  94. case REG_FN_MODIFY_BASE + 3: /* 32bit */
  95. __raw_readl(addr);
  96. __raw_writel(0xffffffff ^ value, addr);
  97. break;
  98. default:
  99. BUG();
  100. break;
  101. }
  102. }
  103. }
  104. static struct intc_handle_int *intc_find_irq(struct intc_handle_int *hp,
  105. unsigned int nr_hp,
  106. unsigned int irq)
  107. {
  108. int i;
  109. /*
  110. * this doesn't scale well, but...
  111. *
  112. * this function should only be used for cerain uncommon
  113. * operations such as intc_set_priority() and intc_set_type()
  114. * and in those rare cases performance doesn't matter that much.
  115. * keeping the memory footprint low is more important.
  116. *
  117. * one rather simple way to speed this up and still keep the
  118. * memory footprint down is to make sure the array is sorted
  119. * and then perform a bisect to lookup the irq.
  120. */
  121. for (i = 0; i < nr_hp; i++) {
  122. if ((hp + i)->irq != irq)
  123. continue;
  124. return hp + i;
  125. }
  126. return NULL;
  127. }
  128. int intc_set_priority(unsigned int irq, unsigned int prio)
  129. {
  130. struct intc_desc_int *d = get_intc_desc(irq);
  131. struct irq_data *data = irq_get_irq_data(irq);
  132. struct intc_handle_int *ihp;
  133. if (!intc_get_prio_level(irq) || prio <= 1)
  134. return -EINVAL;
  135. ihp = intc_find_irq(d->prio, d->nr_prio, irq);
  136. if (ihp) {
  137. if (prio >= (1 << _INTC_WIDTH(ihp->handle)))
  138. return -EINVAL;
  139. intc_set_prio_level(irq, prio);
  140. /*
  141. * only set secondary masking method directly
  142. * primary masking method is using intc_prio_level[irq]
  143. * priority level will be set during next enable()
  144. */
  145. if (_INTC_FN(ihp->handle) != REG_FN_ERR)
  146. _intc_enable(data, ihp->handle);
  147. }
  148. return 0;
  149. }
  150. #define SENSE_VALID_FLAG 0x80
  151. #define VALID(x) (x | SENSE_VALID_FLAG)
  152. static unsigned char intc_irq_sense_table[IRQ_TYPE_SENSE_MASK + 1] = {
  153. [IRQ_TYPE_EDGE_FALLING] = VALID(0),
  154. [IRQ_TYPE_EDGE_RISING] = VALID(1),
  155. [IRQ_TYPE_LEVEL_LOW] = VALID(2),
  156. /* SH7706, SH7707 and SH7709 do not support high level triggered */
  157. #if !defined(CONFIG_CPU_SUBTYPE_SH7706) && \
  158. !defined(CONFIG_CPU_SUBTYPE_SH7707) && \
  159. !defined(CONFIG_CPU_SUBTYPE_SH7709)
  160. [IRQ_TYPE_LEVEL_HIGH] = VALID(3),
  161. #endif
  162. };
  163. static int intc_set_type(struct irq_data *data, unsigned int type)
  164. {
  165. unsigned int irq = data->irq;
  166. struct intc_desc_int *d = get_intc_desc(irq);
  167. unsigned char value = intc_irq_sense_table[type & IRQ_TYPE_SENSE_MASK];
  168. struct intc_handle_int *ihp;
  169. unsigned long addr;
  170. if (!value)
  171. return -EINVAL;
  172. ihp = intc_find_irq(d->sense, d->nr_sense, irq);
  173. if (ihp) {
  174. addr = INTC_REG(d, _INTC_ADDR_E(ihp->handle), 0);
  175. intc_reg_fns[_INTC_FN(ihp->handle)](addr, ihp->handle,
  176. value & ~SENSE_VALID_FLAG);
  177. }
  178. return 0;
  179. }
  180. struct irq_chip intc_irq_chip = {
  181. .irq_mask = intc_disable,
  182. .irq_unmask = intc_enable,
  183. .irq_mask_ack = intc_mask_ack,
  184. .irq_enable = intc_enable,
  185. .irq_disable = intc_disable,
  186. .irq_shutdown = intc_disable,
  187. .irq_set_type = intc_set_type,
  188. .irq_set_wake = intc_set_wake,
  189. #ifdef CONFIG_SMP
  190. .irq_set_affinity = intc_set_affinity,
  191. #endif
  192. };