Blame view

arch/arm/mach-tegra/irq.c 3.08 KB
5ad36c5f0   Erik Gilling   [ARM] tegra: Add ...
1
  /*
938fa349f   Colin Cross   ARM: tegra: irq: ...
2
   * Copyright (C) 2011 Google, Inc.
5ad36c5f0   Erik Gilling   [ARM] tegra: Add ...
3
4
   *
   * Author:
938fa349f   Colin Cross   ARM: tegra: irq: ...
5
   *	Colin Cross <ccross@android.com>
5ad36c5f0   Erik Gilling   [ARM] tegra: Add ...
6
   *
460907bc2   Gary King   [ARM] tegra: add ...
7
8
   * Copyright (C) 2010, NVIDIA Corporation
   *
5ad36c5f0   Erik Gilling   [ARM] tegra: Add ...
9
10
11
12
13
14
15
16
17
18
19
20
   * This software is licensed under the terms of the GNU General Public
   * License version 2, as published by the Free Software Foundation, and
   * may be copied, distributed, and modified under those terms.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   */
  
  #include <linux/kernel.h>
5ad36c5f0   Erik Gilling   [ARM] tegra: Add ...
21
22
23
  #include <linux/interrupt.h>
  #include <linux/irq.h>
  #include <linux/io.h>
0d4f74792   pdeschrijver@nvidia.com   arm/tegra: conver...
24
  #include <linux/of.h>
5ad36c5f0   Erik Gilling   [ARM] tegra: Add ...
25
26
27
28
29
30
  
  #include <asm/hardware/gic.h>
  
  #include <mach/iomap.h>
  
  #include "board.h"
d1d8c6666   Colin Cross   ARM: tegra: irq: ...
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
  #define ICTLR_CPU_IEP_VFIQ	0x08
  #define ICTLR_CPU_IEP_FIR	0x14
  #define ICTLR_CPU_IEP_FIR_SET	0x18
  #define ICTLR_CPU_IEP_FIR_CLR	0x1c
  
  #define ICTLR_CPU_IER		0x20
  #define ICTLR_CPU_IER_SET	0x24
  #define ICTLR_CPU_IER_CLR	0x28
  #define ICTLR_CPU_IEP_CLASS	0x2C
  
  #define ICTLR_COP_IER		0x30
  #define ICTLR_COP_IER_SET	0x34
  #define ICTLR_COP_IER_CLR	0x38
  #define ICTLR_COP_IEP_CLASS	0x3c
  
  #define NUM_ICTLRS 4
  #define FIRST_LEGACY_IRQ 32
  
  static void __iomem *ictlr_reg_base[] = {
  	IO_ADDRESS(TEGRA_PRIMARY_ICTLR_BASE),
  	IO_ADDRESS(TEGRA_SECONDARY_ICTLR_BASE),
  	IO_ADDRESS(TEGRA_TERTIARY_ICTLR_BASE),
  	IO_ADDRESS(TEGRA_QUATERNARY_ICTLR_BASE),
  };
  
  static inline void tegra_irq_write_mask(unsigned int irq, unsigned long reg)
  {
  	void __iomem *base;
  	u32 mask;
  
  	BUG_ON(irq < FIRST_LEGACY_IRQ ||
  		irq >= FIRST_LEGACY_IRQ + NUM_ICTLRS * 32);
  
  	base = ictlr_reg_base[(irq - FIRST_LEGACY_IRQ) / 32];
  	mask = BIT((irq - FIRST_LEGACY_IRQ) % 32);
  
  	__raw_writel(mask, base + reg);
  }
3524b70ef   Colin Cross   ARM: tegra: irq: ...
69
70
  static void tegra_mask(struct irq_data *d)
  {
d1d8c6666   Colin Cross   ARM: tegra: irq: ...
71
72
73
74
  	if (d->irq < FIRST_LEGACY_IRQ)
  		return;
  
  	tegra_irq_write_mask(d->irq, ICTLR_CPU_IER_CLR);
3524b70ef   Colin Cross   ARM: tegra: irq: ...
75
  }
460907bc2   Gary King   [ARM] tegra: add ...
76

3524b70ef   Colin Cross   ARM: tegra: irq: ...
77
  static void tegra_unmask(struct irq_data *d)
460907bc2   Gary King   [ARM] tegra: add ...
78
  {
d1d8c6666   Colin Cross   ARM: tegra: irq: ...
79
80
81
82
  	if (d->irq < FIRST_LEGACY_IRQ)
  		return;
  
  	tegra_irq_write_mask(d->irq, ICTLR_CPU_IER_SET);
460907bc2   Gary King   [ARM] tegra: add ...
83
  }
460907bc2   Gary King   [ARM] tegra: add ...
84

26d902c0c   Colin Cross   ARM: tegra: irq: ...
85
86
  static void tegra_ack(struct irq_data *d)
  {
d1d8c6666   Colin Cross   ARM: tegra: irq: ...
87
88
89
90
  	if (d->irq < FIRST_LEGACY_IRQ)
  		return;
  
  	tegra_irq_write_mask(d->irq, ICTLR_CPU_IEP_FIR_CLR);
26d902c0c   Colin Cross   ARM: tegra: irq: ...
91
  }
4bd66cfde   Colin Cross   ARM: tegra: irq: ...
92
93
94
95
96
97
98
  static void tegra_eoi(struct irq_data *d)
  {
  	if (d->irq < FIRST_LEGACY_IRQ)
  		return;
  
  	tegra_irq_write_mask(d->irq, ICTLR_CPU_IEP_FIR_CLR);
  }
26d902c0c   Colin Cross   ARM: tegra: irq: ...
99
100
  static int tegra_retrigger(struct irq_data *d)
  {
d1d8c6666   Colin Cross   ARM: tegra: irq: ...
101
  	if (d->irq < FIRST_LEGACY_IRQ)
938fa349f   Colin Cross   ARM: tegra: irq: ...
102
  		return 0;
d1d8c6666   Colin Cross   ARM: tegra: irq: ...
103
  	tegra_irq_write_mask(d->irq, ICTLR_CPU_IEP_FIR_SET);
26d902c0c   Colin Cross   ARM: tegra: irq: ...
104
105
  	return 1;
  }
5ad36c5f0   Erik Gilling   [ARM] tegra: Add ...
106
107
  void __init tegra_init_irq(void)
  {
d1d8c6666   Colin Cross   ARM: tegra: irq: ...
108
109
110
111
112
113
114
  	int i;
  
  	for (i = 0; i < NUM_ICTLRS; i++) {
  		void __iomem *ictlr = ictlr_reg_base[i];
  		writel(~0, ictlr + ICTLR_CPU_IER_CLR);
  		writel(0, ictlr + ICTLR_CPU_IEP_CLASS);
  	}
460907bc2   Gary King   [ARM] tegra: add ...
115

938fa349f   Colin Cross   ARM: tegra: irq: ...
116
  	gic_arch_extn.irq_ack = tegra_ack;
4bd66cfde   Colin Cross   ARM: tegra: irq: ...
117
  	gic_arch_extn.irq_eoi = tegra_eoi;
938fa349f   Colin Cross   ARM: tegra: irq: ...
118
119
120
  	gic_arch_extn.irq_mask = tegra_mask;
  	gic_arch_extn.irq_unmask = tegra_unmask;
  	gic_arch_extn.irq_retrigger = tegra_retrigger;
0d4f74792   pdeschrijver@nvidia.com   arm/tegra: conver...
121
122
123
124
125
126
127
  	/*
  	 * Check if there is a devicetree present, since the GIC will be
  	 * initialized elsewhere under DT.
  	 */
  	if (!of_have_populated_dt())
  		gic_init(0, 29, IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE),
  			IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100));
460907bc2   Gary King   [ARM] tegra: add ...
128
  }