text: /* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
   * Use of this source code is governed by a BSD-style license that can be
   * found in the LICENSE file.
   *
   * IT83xx chip-specific part of the IRQ handling.
   */
  
  #include "common.h"
  #include "irq_chip.h"
  #include "registers.h"
  #include "util.h"
  
  #define IRQ_GROUP(n, cpu_ints...) \
  	{(uint32_t)&CONCAT2(IT83XX_INTC_ISR, n) - IT83XX_INTC_BASE, \
  	 (uint32_t)&CONCAT2(IT83XX_INTC_IER, n) - IT83XX_INTC_BASE, \
  	 ##cpu_ints}
  
  static const struct {
  	uint8_t isr_off;
  	uint8_t ier_off;
  	uint8_t cpu_int[8];
  } irq_groups[21] = {
  	IRQ_GROUP(0,  {-1,  2,  5,  4,  6,  2,  2,  4}),
  	IRQ_GROUP(1,  { 7,  6,  6,  5,  2,  2,  2,  8}),
  	IRQ_GROUP(2,  { 6,  2,  8,  8,  8,  2, 12, 12}),
  	IRQ_GROUP(3,  { 5,  4,  4,  4, 11, 11,  3,  2}),
  	IRQ_GROUP(4,  {11, 11, 11, 11,  8,  9,  9,  9}),
  	IRQ_GROUP(5,  { 2,  2,  2,  2,  2,  2,  2,  2}),
  	IRQ_GROUP(6,  { 2,  2,  2,  2,  2,  2,  2,  2}),
  	IRQ_GROUP(7,  {10, 10,  3, -1,  3,  3,  3,  3}),
  	IRQ_GROUP(8,  { 4,  4,  4,  4,  4,  4, -1, 12}),
  	IRQ_GROUP(9,  { 2,  2,  2,  2,  2,  2,  2,  2}),
  	IRQ_GROUP(10, { 3,  6, 12, 12,  5,  2,  2,  2}),
  	IRQ_GROUP(11, { 2,  2,  2,  2,  2,  2,  2,  2}),
  	IRQ_GROUP(12, { 2,  2,  2,  2,  2,  2,  2,  2}),
  	IRQ_GROUP(13, { 2,  2,  2,  2,  2,  2,  2,  2}),
  	IRQ_GROUP(14, { 2,  2,  2,  2,  2,  2,  2,  2}),
  	IRQ_GROUP(15, { 2,  2,  2,  2,  2,  2,  2,  2}),
  	IRQ_GROUP(16, { 2,  2,  2,  2,  2,  2,  2, -1}),
  	IRQ_GROUP(17, { 2,  2,  2,  2,  2,  2,  2,  2}),
  	IRQ_GROUP(18, {-1, -1, -1, -1, -1,  4,  4,  7}),
  	IRQ_GROUP(19, { 6,  6, 12,  3,  3,  3,  3,  3}),
  	IRQ_GROUP(20, {12, 12, 12, 12, 12, 12, 12, 12}),
  };
  
  int chip_enable_irq(int irq)
  {
  	int group = irq / 8;
  	int bit = irq % 8;
  
  	IT83XX_INTC_REG(irq_groups[group].ier_off) |= 1 << bit;
  	IT83XX_INTC_REG(IT83XX_INTC_EXT_IER_OFF(group)) |= 1 << bit;
  
  	return irq_groups[group].cpu_int[bit];
  }
  
  int chip_disable_irq(int irq)
  {
  	int group = irq / 8;
  	int bit = irq % 8;
  
  	IT83XX_INTC_REG(irq_groups[group].ier_off) &= ~(1 << bit);
  	IT83XX_INTC_REG(IT83XX_INTC_EXT_IER_OFF(group)) &= ~(1 << bit);
  
  	return -1; /* we don't want to mask other IRQs */
  }
  
  int chip_clear_pending_irq(int irq)
  {
  	int group = irq / 8;
  	int bit = irq % 8;
  
  	/* always write 1 clear, no | */
  	IT83XX_INTC_REG(irq_groups[group].isr_off) = 1 << bit;
  
  	return -1; /* everything has been done */
  }
  
  int chip_trigger_irq(int irq)
  {
  	int group = irq / 8;
  	int bit = irq % 8;
  
  	return irq_groups[group].cpu_int[bit];
  }
  
  void chip_init_irqs(void)
  {
  	int i;
  
  	/* Clear all IERx and EXT_IERx */
  	for (i = 0; i < ARRAY_SIZE(irq_groups); i++) {
  		IT83XX_INTC_REG(irq_groups[i].ier_off) = 0;
  		IT83XX_INTC_REG(IT83XX_INTC_EXT_IER_OFF(i)) = 0;
  	}
  }
  