0002-MIPS-ralink-adds-irq-code.patch 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. From 833836f47b4191e93267b91fcab38dd15affcd28 Mon Sep 17 00:00:00 2001
  2. From: John Crispin <[email protected]>
  3. Date: Sun, 20 Jan 2013 22:00:50 +0100
  4. Subject: [PATCH 02/79] MIPS: ralink: adds irq code
  5. All of the Ralink Wifi SoC currently supported by this series share the same
  6. interrupt controller (INTC).
  7. Signed-off-by: John Crispin <[email protected]>
  8. Signed-off-by: Gabor Juhos <[email protected]>
  9. Patchwork: http://patchwork.linux-mips.org/patch/4890/
  10. ---
  11. arch/mips/ralink/irq.c | 176 ++++++++++++++++++++++++++++++++++++++++++++++++
  12. 1 file changed, 176 insertions(+)
  13. create mode 100644 arch/mips/ralink/irq.c
  14. diff --git a/arch/mips/ralink/irq.c b/arch/mips/ralink/irq.c
  15. new file mode 100644
  16. index 0000000..e62c975
  17. --- /dev/null
  18. +++ b/arch/mips/ralink/irq.c
  19. @@ -0,0 +1,176 @@
  20. +/*
  21. + * This program is free software; you can redistribute it and/or modify it
  22. + * under the terms of the GNU General Public License version 2 as published
  23. + * by the Free Software Foundation.
  24. + *
  25. + * Copyright (C) 2009 Gabor Juhos <[email protected]>
  26. + * Copyright (C) 2013 John Crispin <[email protected]>
  27. + */
  28. +
  29. +#include <linux/io.h>
  30. +#include <linux/bitops.h>
  31. +#include <linux/of_platform.h>
  32. +#include <linux/of_address.h>
  33. +#include <linux/of_irq.h>
  34. +#include <linux/irqdomain.h>
  35. +#include <linux/interrupt.h>
  36. +
  37. +#include <asm/irq_cpu.h>
  38. +#include <asm/mipsregs.h>
  39. +
  40. +#include "common.h"
  41. +
  42. +/* INTC register offsets */
  43. +#define INTC_REG_STATUS0 0x00
  44. +#define INTC_REG_STATUS1 0x04
  45. +#define INTC_REG_TYPE 0x20
  46. +#define INTC_REG_RAW_STATUS 0x30
  47. +#define INTC_REG_ENABLE 0x34
  48. +#define INTC_REG_DISABLE 0x38
  49. +
  50. +#define INTC_INT_GLOBAL BIT(31)
  51. +
  52. +#define RALINK_CPU_IRQ_INTC (MIPS_CPU_IRQ_BASE + 2)
  53. +#define RALINK_CPU_IRQ_FE (MIPS_CPU_IRQ_BASE + 5)
  54. +#define RALINK_CPU_IRQ_WIFI (MIPS_CPU_IRQ_BASE + 6)
  55. +#define RALINK_CPU_IRQ_COUNTER (MIPS_CPU_IRQ_BASE + 7)
  56. +
  57. +/* we have a cascade of 8 irqs */
  58. +#define RALINK_INTC_IRQ_BASE 8
  59. +
  60. +/* we have 32 SoC irqs */
  61. +#define RALINK_INTC_IRQ_COUNT 32
  62. +
  63. +#define RALINK_INTC_IRQ_PERFC (RALINK_INTC_IRQ_BASE + 9)
  64. +
  65. +static void __iomem *rt_intc_membase;
  66. +
  67. +static inline void rt_intc_w32(u32 val, unsigned reg)
  68. +{
  69. + __raw_writel(val, rt_intc_membase + reg);
  70. +}
  71. +
  72. +static inline u32 rt_intc_r32(unsigned reg)
  73. +{
  74. + return __raw_readl(rt_intc_membase + reg);
  75. +}
  76. +
  77. +static void ralink_intc_irq_unmask(struct irq_data *d)
  78. +{
  79. + rt_intc_w32(BIT(d->hwirq), INTC_REG_ENABLE);
  80. +}
  81. +
  82. +static void ralink_intc_irq_mask(struct irq_data *d)
  83. +{
  84. + rt_intc_w32(BIT(d->hwirq), INTC_REG_DISABLE);
  85. +}
  86. +
  87. +static struct irq_chip ralink_intc_irq_chip = {
  88. + .name = "INTC",
  89. + .irq_unmask = ralink_intc_irq_unmask,
  90. + .irq_mask = ralink_intc_irq_mask,
  91. + .irq_mask_ack = ralink_intc_irq_mask,
  92. +};
  93. +
  94. +unsigned int __cpuinit get_c0_compare_int(void)
  95. +{
  96. + return CP0_LEGACY_COMPARE_IRQ;
  97. +}
  98. +
  99. +static void ralink_intc_irq_handler(unsigned int irq, struct irq_desc *desc)
  100. +{
  101. + u32 pending = rt_intc_r32(INTC_REG_STATUS0);
  102. +
  103. + if (pending) {
  104. + struct irq_domain *domain = irq_get_handler_data(irq);
  105. + generic_handle_irq(irq_find_mapping(domain, __ffs(pending)));
  106. + } else {
  107. + spurious_interrupt();
  108. + }
  109. +}
  110. +
  111. +asmlinkage void plat_irq_dispatch(void)
  112. +{
  113. + unsigned long pending;
  114. +
  115. + pending = read_c0_status() & read_c0_cause() & ST0_IM;
  116. +
  117. + if (pending & STATUSF_IP7)
  118. + do_IRQ(RALINK_CPU_IRQ_COUNTER);
  119. +
  120. + else if (pending & STATUSF_IP5)
  121. + do_IRQ(RALINK_CPU_IRQ_FE);
  122. +
  123. + else if (pending & STATUSF_IP6)
  124. + do_IRQ(RALINK_CPU_IRQ_WIFI);
  125. +
  126. + else if (pending & STATUSF_IP2)
  127. + do_IRQ(RALINK_CPU_IRQ_INTC);
  128. +
  129. + else
  130. + spurious_interrupt();
  131. +}
  132. +
  133. +static int intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
  134. +{
  135. + irq_set_chip_and_handler(irq, &ralink_intc_irq_chip, handle_level_irq);
  136. +
  137. + return 0;
  138. +}
  139. +
  140. +static const struct irq_domain_ops irq_domain_ops = {
  141. + .xlate = irq_domain_xlate_onecell,
  142. + .map = intc_map,
  143. +};
  144. +
  145. +static int __init intc_of_init(struct device_node *node,
  146. + struct device_node *parent)
  147. +{
  148. + struct resource res;
  149. + struct irq_domain *domain;
  150. +
  151. + mips_cpu_irq_init();
  152. +
  153. + if (of_address_to_resource(node, 0, &res))
  154. + panic("Failed to get intc memory range");
  155. +
  156. + if (request_mem_region(res.start, resource_size(&res),
  157. + res.name) < 0)
  158. + pr_err("Failed to request intc memory");
  159. +
  160. + rt_intc_membase = ioremap_nocache(res.start,
  161. + resource_size(&res));
  162. + if (!rt_intc_membase)
  163. + panic("Failed to remap intc memory");
  164. +
  165. + /* disable all interrupts */
  166. + rt_intc_w32(~0, INTC_REG_DISABLE);
  167. +
  168. + /* route all INTC interrupts to MIPS HW0 interrupt */
  169. + rt_intc_w32(0, INTC_REG_TYPE);
  170. +
  171. + domain = irq_domain_add_legacy(node, RALINK_INTC_IRQ_COUNT,
  172. + RALINK_INTC_IRQ_BASE, 0, &irq_domain_ops, NULL);
  173. + if (!domain)
  174. + panic("Failed to add irqdomain");
  175. +
  176. + rt_intc_w32(INTC_INT_GLOBAL, INTC_REG_ENABLE);
  177. +
  178. + irq_set_chained_handler(RALINK_CPU_IRQ_INTC, ralink_intc_irq_handler);
  179. + irq_set_handler_data(RALINK_CPU_IRQ_INTC, domain);
  180. +
  181. + cp0_perfcount_irq = irq_create_mapping(domain, 9);
  182. +
  183. + return 0;
  184. +}
  185. +
  186. +static struct of_device_id __initdata of_irq_ids[] = {
  187. + { .compatible = "ralink,rt2880-intc", .data = intc_of_init },
  188. + {},
  189. +};
  190. +
  191. +void __init arch_init_irq(void)
  192. +{
  193. + of_irq_init(of_irq_ids);
  194. +}
  195. +
  196. --
  197. 1.7.10.4