0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #include <linux/io.h>
0017 #include <linux/irq.h>
0018 #include <linux/irqchip.h>
0019 #include <linux/irqdomain.h>
0020 #include <linux/of_address.h>
0021 #include <linux/slab.h>
0022 #include <linux/syscore_ops.h>
0023
0024 #include <dt-bindings/interrupt-controller/arm-gic.h>
0025
0026 #define ICTLR_CPU_IEP_VFIQ 0x08
0027 #define ICTLR_CPU_IEP_FIR 0x14
0028 #define ICTLR_CPU_IEP_FIR_SET 0x18
0029 #define ICTLR_CPU_IEP_FIR_CLR 0x1c
0030
0031 #define ICTLR_CPU_IER 0x20
0032 #define ICTLR_CPU_IER_SET 0x24
0033 #define ICTLR_CPU_IER_CLR 0x28
0034 #define ICTLR_CPU_IEP_CLASS 0x2C
0035
0036 #define ICTLR_COP_IER 0x30
0037 #define ICTLR_COP_IER_SET 0x34
0038 #define ICTLR_COP_IER_CLR 0x38
0039 #define ICTLR_COP_IEP_CLASS 0x3c
0040
0041 #define TEGRA_MAX_NUM_ICTLRS 6
0042
0043 static unsigned int num_ictlrs;
0044
0045 struct tegra_ictlr_soc {
0046 unsigned int num_ictlrs;
0047 };
0048
0049 static const struct tegra_ictlr_soc tegra20_ictlr_soc = {
0050 .num_ictlrs = 4,
0051 };
0052
0053 static const struct tegra_ictlr_soc tegra30_ictlr_soc = {
0054 .num_ictlrs = 5,
0055 };
0056
0057 static const struct tegra_ictlr_soc tegra210_ictlr_soc = {
0058 .num_ictlrs = 6,
0059 };
0060
0061 static const struct of_device_id ictlr_matches[] = {
0062 { .compatible = "nvidia,tegra210-ictlr", .data = &tegra210_ictlr_soc },
0063 { .compatible = "nvidia,tegra30-ictlr", .data = &tegra30_ictlr_soc },
0064 { .compatible = "nvidia,tegra20-ictlr", .data = &tegra20_ictlr_soc },
0065 { }
0066 };
0067
0068 struct tegra_ictlr_info {
0069 void __iomem *base[TEGRA_MAX_NUM_ICTLRS];
0070 #ifdef CONFIG_PM_SLEEP
0071 u32 cop_ier[TEGRA_MAX_NUM_ICTLRS];
0072 u32 cop_iep[TEGRA_MAX_NUM_ICTLRS];
0073 u32 cpu_ier[TEGRA_MAX_NUM_ICTLRS];
0074 u32 cpu_iep[TEGRA_MAX_NUM_ICTLRS];
0075
0076 u32 ictlr_wake_mask[TEGRA_MAX_NUM_ICTLRS];
0077 #endif
0078 };
0079
0080 static struct tegra_ictlr_info *lic;
0081
0082 static inline void tegra_ictlr_write_mask(struct irq_data *d, unsigned long reg)
0083 {
0084 void __iomem *base = (void __iomem __force *)d->chip_data;
0085 u32 mask;
0086
0087 mask = BIT(d->hwirq % 32);
0088 writel_relaxed(mask, base + reg);
0089 }
0090
0091 static void tegra_mask(struct irq_data *d)
0092 {
0093 tegra_ictlr_write_mask(d, ICTLR_CPU_IER_CLR);
0094 irq_chip_mask_parent(d);
0095 }
0096
0097 static void tegra_unmask(struct irq_data *d)
0098 {
0099 tegra_ictlr_write_mask(d, ICTLR_CPU_IER_SET);
0100 irq_chip_unmask_parent(d);
0101 }
0102
0103 static void tegra_eoi(struct irq_data *d)
0104 {
0105 tegra_ictlr_write_mask(d, ICTLR_CPU_IEP_FIR_CLR);
0106 irq_chip_eoi_parent(d);
0107 }
0108
0109 static int tegra_retrigger(struct irq_data *d)
0110 {
0111 tegra_ictlr_write_mask(d, ICTLR_CPU_IEP_FIR_SET);
0112 return irq_chip_retrigger_hierarchy(d);
0113 }
0114
0115 #ifdef CONFIG_PM_SLEEP
0116 static int tegra_set_wake(struct irq_data *d, unsigned int enable)
0117 {
0118 u32 irq = d->hwirq;
0119 u32 index, mask;
0120
0121 index = (irq / 32);
0122 mask = BIT(irq % 32);
0123 if (enable)
0124 lic->ictlr_wake_mask[index] |= mask;
0125 else
0126 lic->ictlr_wake_mask[index] &= ~mask;
0127
0128
0129
0130
0131
0132 return 0;
0133 }
0134
0135 static int tegra_ictlr_suspend(void)
0136 {
0137 unsigned long flags;
0138 unsigned int i;
0139
0140 local_irq_save(flags);
0141 for (i = 0; i < num_ictlrs; i++) {
0142 void __iomem *ictlr = lic->base[i];
0143
0144
0145 lic->cpu_ier[i] = readl_relaxed(ictlr + ICTLR_CPU_IER);
0146 lic->cpu_iep[i] = readl_relaxed(ictlr + ICTLR_CPU_IEP_CLASS);
0147 lic->cop_ier[i] = readl_relaxed(ictlr + ICTLR_COP_IER);
0148 lic->cop_iep[i] = readl_relaxed(ictlr + ICTLR_COP_IEP_CLASS);
0149
0150
0151 writel_relaxed(GENMASK(31, 0), ictlr + ICTLR_COP_IER_CLR);
0152
0153
0154 writel_relaxed(GENMASK(31, 0), ictlr + ICTLR_CPU_IER_CLR);
0155
0156
0157 writel_relaxed(lic->ictlr_wake_mask[i], ictlr + ICTLR_CPU_IER_SET);
0158 }
0159 local_irq_restore(flags);
0160
0161 return 0;
0162 }
0163
0164 static void tegra_ictlr_resume(void)
0165 {
0166 unsigned long flags;
0167 unsigned int i;
0168
0169 local_irq_save(flags);
0170 for (i = 0; i < num_ictlrs; i++) {
0171 void __iomem *ictlr = lic->base[i];
0172
0173 writel_relaxed(lic->cpu_iep[i],
0174 ictlr + ICTLR_CPU_IEP_CLASS);
0175 writel_relaxed(GENMASK(31, 0), ictlr + ICTLR_CPU_IER_CLR);
0176 writel_relaxed(lic->cpu_ier[i],
0177 ictlr + ICTLR_CPU_IER_SET);
0178 writel_relaxed(lic->cop_iep[i],
0179 ictlr + ICTLR_COP_IEP_CLASS);
0180 writel_relaxed(GENMASK(31, 0), ictlr + ICTLR_COP_IER_CLR);
0181 writel_relaxed(lic->cop_ier[i],
0182 ictlr + ICTLR_COP_IER_SET);
0183 }
0184 local_irq_restore(flags);
0185 }
0186
0187 static struct syscore_ops tegra_ictlr_syscore_ops = {
0188 .suspend = tegra_ictlr_suspend,
0189 .resume = tegra_ictlr_resume,
0190 };
0191
0192 static void tegra_ictlr_syscore_init(void)
0193 {
0194 register_syscore_ops(&tegra_ictlr_syscore_ops);
0195 }
0196 #else
0197 #define tegra_set_wake NULL
0198 static inline void tegra_ictlr_syscore_init(void) {}
0199 #endif
0200
0201 static struct irq_chip tegra_ictlr_chip = {
0202 .name = "LIC",
0203 .irq_eoi = tegra_eoi,
0204 .irq_mask = tegra_mask,
0205 .irq_unmask = tegra_unmask,
0206 .irq_retrigger = tegra_retrigger,
0207 .irq_set_wake = tegra_set_wake,
0208 .irq_set_type = irq_chip_set_type_parent,
0209 .flags = IRQCHIP_MASK_ON_SUSPEND,
0210 #ifdef CONFIG_SMP
0211 .irq_set_affinity = irq_chip_set_affinity_parent,
0212 #endif
0213 };
0214
0215 static int tegra_ictlr_domain_translate(struct irq_domain *d,
0216 struct irq_fwspec *fwspec,
0217 unsigned long *hwirq,
0218 unsigned int *type)
0219 {
0220 if (is_of_node(fwspec->fwnode)) {
0221 if (fwspec->param_count != 3)
0222 return -EINVAL;
0223
0224
0225 if (fwspec->param[0] != 0)
0226 return -EINVAL;
0227
0228 *hwirq = fwspec->param[1];
0229 *type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;
0230 return 0;
0231 }
0232
0233 return -EINVAL;
0234 }
0235
0236 static int tegra_ictlr_domain_alloc(struct irq_domain *domain,
0237 unsigned int virq,
0238 unsigned int nr_irqs, void *data)
0239 {
0240 struct irq_fwspec *fwspec = data;
0241 struct irq_fwspec parent_fwspec;
0242 struct tegra_ictlr_info *info = domain->host_data;
0243 irq_hw_number_t hwirq;
0244 unsigned int i;
0245
0246 if (fwspec->param_count != 3)
0247 return -EINVAL;
0248 if (fwspec->param[0] != GIC_SPI)
0249 return -EINVAL;
0250
0251 hwirq = fwspec->param[1];
0252 if (hwirq >= (num_ictlrs * 32))
0253 return -EINVAL;
0254
0255 for (i = 0; i < nr_irqs; i++) {
0256 int ictlr = (hwirq + i) / 32;
0257
0258 irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
0259 &tegra_ictlr_chip,
0260 (void __force *)info->base[ictlr]);
0261 }
0262
0263 parent_fwspec = *fwspec;
0264 parent_fwspec.fwnode = domain->parent->fwnode;
0265 return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs,
0266 &parent_fwspec);
0267 }
0268
0269 static const struct irq_domain_ops tegra_ictlr_domain_ops = {
0270 .translate = tegra_ictlr_domain_translate,
0271 .alloc = tegra_ictlr_domain_alloc,
0272 .free = irq_domain_free_irqs_common,
0273 };
0274
0275 static int __init tegra_ictlr_init(struct device_node *node,
0276 struct device_node *parent)
0277 {
0278 struct irq_domain *parent_domain, *domain;
0279 const struct of_device_id *match;
0280 const struct tegra_ictlr_soc *soc;
0281 unsigned int i;
0282 int err;
0283
0284 if (!parent) {
0285 pr_err("%pOF: no parent, giving up\n", node);
0286 return -ENODEV;
0287 }
0288
0289 parent_domain = irq_find_host(parent);
0290 if (!parent_domain) {
0291 pr_err("%pOF: unable to obtain parent domain\n", node);
0292 return -ENXIO;
0293 }
0294
0295 match = of_match_node(ictlr_matches, node);
0296 if (!match)
0297 return -ENODEV;
0298
0299 soc = match->data;
0300
0301 lic = kzalloc(sizeof(*lic), GFP_KERNEL);
0302 if (!lic)
0303 return -ENOMEM;
0304
0305 for (i = 0; i < TEGRA_MAX_NUM_ICTLRS; i++) {
0306 void __iomem *base;
0307
0308 base = of_iomap(node, i);
0309 if (!base)
0310 break;
0311
0312 lic->base[i] = base;
0313
0314
0315 writel_relaxed(GENMASK(31, 0), base + ICTLR_CPU_IER_CLR);
0316
0317 writel_relaxed(0, base + ICTLR_CPU_IEP_CLASS);
0318
0319 num_ictlrs++;
0320 }
0321
0322 if (!num_ictlrs) {
0323 pr_err("%pOF: no valid regions, giving up\n", node);
0324 err = -ENOMEM;
0325 goto out_free;
0326 }
0327
0328 WARN(num_ictlrs != soc->num_ictlrs,
0329 "%pOF: Found %u interrupt controllers in DT; expected %u.\n",
0330 node, num_ictlrs, soc->num_ictlrs);
0331
0332
0333 domain = irq_domain_add_hierarchy(parent_domain, 0, num_ictlrs * 32,
0334 node, &tegra_ictlr_domain_ops,
0335 lic);
0336 if (!domain) {
0337 pr_err("%pOF: failed to allocated domain\n", node);
0338 err = -ENOMEM;
0339 goto out_unmap;
0340 }
0341
0342 tegra_ictlr_syscore_init();
0343
0344 pr_info("%pOF: %d interrupts forwarded to %pOF\n",
0345 node, num_ictlrs * 32, parent);
0346
0347 return 0;
0348
0349 out_unmap:
0350 for (i = 0; i < num_ictlrs; i++)
0351 iounmap(lic->base[i]);
0352 out_free:
0353 kfree(lic);
0354 return err;
0355 }
0356
0357 IRQCHIP_DECLARE(tegra20_ictlr, "nvidia,tegra20-ictlr", tegra_ictlr_init);
0358 IRQCHIP_DECLARE(tegra30_ictlr, "nvidia,tegra30-ictlr", tegra_ictlr_init);
0359 IRQCHIP_DECLARE(tegra210_ictlr, "nvidia,tegra210-ictlr", tegra_ictlr_init);