irq-mtk-intpol.c 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. /*
  2. * Support MediaTek intpol through gic_arch_extn
  3. *
  4. * Copyright (C) 2014 Mediatek Inc.
  5. *
  6. * This software is licensed under the terms of the GNU General Public
  7. * License version 2, as published by the Free Software Foundation, and
  8. * may be copied, distributed, and modified under those terms.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. */
  15. #include <linux/err.h>
  16. #include <linux/of_address.h>
  17. #include <linux/of_irq.h>
  18. #include <linux/io.h>
  19. #include <linux/irq.h>
  20. #include <linux/irqchip/arm-gic.h>
  21. #include "irqchip.h"
  22. #define GIC_HW_IRQ_BASE 32
  23. #define INT_POL_INDEX(a) ((a) - GIC_HW_IRQ_BASE)
  24. static void __iomem *int_pol_base;
  25. static int mtk_int_pol_set_type(struct irq_data *d, unsigned int type)
  26. {
  27. unsigned int irq = d->hwirq;
  28. u32 offset, reg_index, value;
  29. offset = INT_POL_INDEX(irq) & 0x1F;
  30. reg_index = INT_POL_INDEX(irq) >> 5;
  31. /* This arch extension was called with irq_controller_lock held,
  32. so the read-modify-write will be atomic */
  33. value = readl(int_pol_base + reg_index * 4);
  34. if (type == IRQ_TYPE_LEVEL_LOW || type == IRQ_TYPE_EDGE_FALLING)
  35. value |= (1 << offset);
  36. else
  37. value &= ~(1 << offset);
  38. writel(value, int_pol_base + reg_index * 4);
  39. return 0;
  40. }
  41. static int __init mtk_intpol_of_init(struct device_node *node,
  42. struct device_node *parent)
  43. {
  44. int_pol_base = of_io_request_and_map(node, 0, "intpol");
  45. if (IS_ERR(int_pol_base)) {
  46. pr_warn("Can't get resource\n");
  47. return PTR_ERR(int_pol_base);
  48. }
  49. gic_arch_extn.irq_set_type = mtk_int_pol_set_type;
  50. return 0;
  51. }
  52. IRQCHIP_DECLARE(mtk_intpol, "mediatek,mt6577-intpol", mtk_intpol_of_init);