Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Actions Semi Owl SoCs SIRQ interrupt controller driver
0004  *
0005  * Copyright (C) 2014 Actions Semi Inc.
0006  * David Liu <liuwei@actions-semi.com>
0007  *
0008  * Author: Parthiban Nallathambi <pn@denx.de>
0009  * Author: Saravanan Sekar <sravanhome@gmail.com>
0010  * Author: Cristian Ciocaltea <cristian.ciocaltea@gmail.com>
0011  */
0012 
0013 #include <linux/bitfield.h>
0014 #include <linux/interrupt.h>
0015 #include <linux/irqchip.h>
0016 #include <linux/of_address.h>
0017 #include <linux/of_irq.h>
0018 
0019 #include <dt-bindings/interrupt-controller/arm-gic.h>
0020 
0021 #define NUM_SIRQ            3
0022 
0023 #define INTC_EXTCTL_PENDING     BIT(0)
0024 #define INTC_EXTCTL_CLK_SEL     BIT(4)
0025 #define INTC_EXTCTL_EN          BIT(5)
0026 #define INTC_EXTCTL_TYPE_MASK       GENMASK(7, 6)
0027 #define INTC_EXTCTL_TYPE_HIGH       0
0028 #define INTC_EXTCTL_TYPE_LOW        BIT(6)
0029 #define INTC_EXTCTL_TYPE_RISING     BIT(7)
0030 #define INTC_EXTCTL_TYPE_FALLING    (BIT(6) | BIT(7))
0031 
0032 /* S500 & S700 SIRQ control register masks */
0033 #define INTC_EXTCTL_SIRQ0_MASK      GENMASK(23, 16)
0034 #define INTC_EXTCTL_SIRQ1_MASK      GENMASK(15, 8)
0035 #define INTC_EXTCTL_SIRQ2_MASK      GENMASK(7, 0)
0036 
0037 /* S900 SIRQ control register offsets, relative to controller base address */
0038 #define INTC_EXTCTL0            0x0000
0039 #define INTC_EXTCTL1            0x0328
0040 #define INTC_EXTCTL2            0x032c
0041 
0042 struct owl_sirq_params {
0043     /* INTC_EXTCTL reg shared for all three SIRQ lines */
0044     bool reg_shared;
0045     /* INTC_EXTCTL reg offsets relative to controller base address */
0046     u16 reg_offset[NUM_SIRQ];
0047 };
0048 
0049 struct owl_sirq_chip_data {
0050     const struct owl_sirq_params    *params;
0051     void __iomem            *base;
0052     raw_spinlock_t          lock;
0053     u32             ext_irqs[NUM_SIRQ];
0054 };
0055 
0056 /* S500 & S700 SoCs */
0057 static const struct owl_sirq_params owl_sirq_s500_params = {
0058     .reg_shared = true,
0059     .reg_offset = { 0, 0, 0 },
0060 };
0061 
0062 /* S900 SoC */
0063 static const struct owl_sirq_params owl_sirq_s900_params = {
0064     .reg_shared = false,
0065     .reg_offset = { INTC_EXTCTL0, INTC_EXTCTL1, INTC_EXTCTL2 },
0066 };
0067 
0068 static u32 owl_field_get(u32 val, u32 index)
0069 {
0070     switch (index) {
0071     case 0:
0072         return FIELD_GET(INTC_EXTCTL_SIRQ0_MASK, val);
0073     case 1:
0074         return FIELD_GET(INTC_EXTCTL_SIRQ1_MASK, val);
0075     case 2:
0076     default:
0077         return FIELD_GET(INTC_EXTCTL_SIRQ2_MASK, val);
0078     }
0079 }
0080 
0081 static u32 owl_field_prep(u32 val, u32 index)
0082 {
0083     switch (index) {
0084     case 0:
0085         return FIELD_PREP(INTC_EXTCTL_SIRQ0_MASK, val);
0086     case 1:
0087         return FIELD_PREP(INTC_EXTCTL_SIRQ1_MASK, val);
0088     case 2:
0089     default:
0090         return FIELD_PREP(INTC_EXTCTL_SIRQ2_MASK, val);
0091     }
0092 }
0093 
0094 static u32 owl_sirq_read_extctl(struct owl_sirq_chip_data *data, u32 index)
0095 {
0096     u32 val;
0097 
0098     val = readl_relaxed(data->base + data->params->reg_offset[index]);
0099     if (data->params->reg_shared)
0100         val = owl_field_get(val, index);
0101 
0102     return val;
0103 }
0104 
0105 static void owl_sirq_write_extctl(struct owl_sirq_chip_data *data,
0106                   u32 extctl, u32 index)
0107 {
0108     u32 val;
0109 
0110     if (data->params->reg_shared) {
0111         val = readl_relaxed(data->base + data->params->reg_offset[index]);
0112         val &= ~owl_field_prep(0xff, index);
0113         extctl = owl_field_prep(extctl, index) | val;
0114     }
0115 
0116     writel_relaxed(extctl, data->base + data->params->reg_offset[index]);
0117 }
0118 
0119 static void owl_sirq_clear_set_extctl(struct owl_sirq_chip_data *d,
0120                       u32 clear, u32 set, u32 index)
0121 {
0122     unsigned long flags;
0123     u32 val;
0124 
0125     raw_spin_lock_irqsave(&d->lock, flags);
0126     val = owl_sirq_read_extctl(d, index);
0127     val &= ~clear;
0128     val |= set;
0129     owl_sirq_write_extctl(d, val, index);
0130     raw_spin_unlock_irqrestore(&d->lock, flags);
0131 }
0132 
0133 static void owl_sirq_eoi(struct irq_data *data)
0134 {
0135     struct owl_sirq_chip_data *chip_data = irq_data_get_irq_chip_data(data);
0136 
0137     /*
0138      * Software must clear external interrupt pending, when interrupt type
0139      * is edge triggered, so we need per SIRQ based clearing.
0140      */
0141     if (!irqd_is_level_type(data))
0142         owl_sirq_clear_set_extctl(chip_data, 0, INTC_EXTCTL_PENDING,
0143                       data->hwirq);
0144 
0145     irq_chip_eoi_parent(data);
0146 }
0147 
0148 static void owl_sirq_mask(struct irq_data *data)
0149 {
0150     struct owl_sirq_chip_data *chip_data = irq_data_get_irq_chip_data(data);
0151 
0152     owl_sirq_clear_set_extctl(chip_data, INTC_EXTCTL_EN, 0, data->hwirq);
0153     irq_chip_mask_parent(data);
0154 }
0155 
0156 static void owl_sirq_unmask(struct irq_data *data)
0157 {
0158     struct owl_sirq_chip_data *chip_data = irq_data_get_irq_chip_data(data);
0159 
0160     owl_sirq_clear_set_extctl(chip_data, 0, INTC_EXTCTL_EN, data->hwirq);
0161     irq_chip_unmask_parent(data);
0162 }
0163 
0164 /*
0165  * GIC does not handle falling edge or active low, hence SIRQ shall be
0166  * programmed to convert falling edge to rising edge signal and active
0167  * low to active high signal.
0168  */
0169 static int owl_sirq_set_type(struct irq_data *data, unsigned int type)
0170 {
0171     struct owl_sirq_chip_data *chip_data = irq_data_get_irq_chip_data(data);
0172     u32 sirq_type;
0173 
0174     switch (type) {
0175     case IRQ_TYPE_LEVEL_LOW:
0176         sirq_type = INTC_EXTCTL_TYPE_LOW;
0177         type = IRQ_TYPE_LEVEL_HIGH;
0178         break;
0179     case IRQ_TYPE_LEVEL_HIGH:
0180         sirq_type = INTC_EXTCTL_TYPE_HIGH;
0181         break;
0182     case IRQ_TYPE_EDGE_FALLING:
0183         sirq_type = INTC_EXTCTL_TYPE_FALLING;
0184         type = IRQ_TYPE_EDGE_RISING;
0185         break;
0186     case IRQ_TYPE_EDGE_RISING:
0187         sirq_type = INTC_EXTCTL_TYPE_RISING;
0188         break;
0189     default:
0190         return -EINVAL;
0191     }
0192 
0193     owl_sirq_clear_set_extctl(chip_data, INTC_EXTCTL_TYPE_MASK, sirq_type,
0194                   data->hwirq);
0195 
0196     return irq_chip_set_type_parent(data, type);
0197 }
0198 
0199 static struct irq_chip owl_sirq_chip = {
0200     .name       = "owl-sirq",
0201     .irq_mask   = owl_sirq_mask,
0202     .irq_unmask = owl_sirq_unmask,
0203     .irq_eoi    = owl_sirq_eoi,
0204     .irq_set_type   = owl_sirq_set_type,
0205     .irq_retrigger  = irq_chip_retrigger_hierarchy,
0206 #ifdef CONFIG_SMP
0207     .irq_set_affinity = irq_chip_set_affinity_parent,
0208 #endif
0209 };
0210 
0211 static int owl_sirq_domain_translate(struct irq_domain *d,
0212                      struct irq_fwspec *fwspec,
0213                      unsigned long *hwirq,
0214                      unsigned int *type)
0215 {
0216     if (!is_of_node(fwspec->fwnode))
0217         return -EINVAL;
0218 
0219     if (fwspec->param_count != 2 || fwspec->param[0] >= NUM_SIRQ)
0220         return -EINVAL;
0221 
0222     *hwirq = fwspec->param[0];
0223     *type = fwspec->param[1];
0224 
0225     return 0;
0226 }
0227 
0228 static int owl_sirq_domain_alloc(struct irq_domain *domain, unsigned int virq,
0229                  unsigned int nr_irqs, void *data)
0230 {
0231     struct owl_sirq_chip_data *chip_data = domain->host_data;
0232     struct irq_fwspec *fwspec = data;
0233     struct irq_fwspec parent_fwspec;
0234     irq_hw_number_t hwirq;
0235     unsigned int type;
0236     int ret;
0237 
0238     if (WARN_ON(nr_irqs != 1))
0239         return -EINVAL;
0240 
0241     ret = owl_sirq_domain_translate(domain, fwspec, &hwirq, &type);
0242     if (ret)
0243         return ret;
0244 
0245     switch (type) {
0246     case IRQ_TYPE_EDGE_RISING:
0247     case IRQ_TYPE_LEVEL_HIGH:
0248         break;
0249     case IRQ_TYPE_EDGE_FALLING:
0250         type = IRQ_TYPE_EDGE_RISING;
0251         break;
0252     case IRQ_TYPE_LEVEL_LOW:
0253         type = IRQ_TYPE_LEVEL_HIGH;
0254         break;
0255     default:
0256         return -EINVAL;
0257     }
0258 
0259     irq_domain_set_hwirq_and_chip(domain, virq, hwirq, &owl_sirq_chip,
0260                       chip_data);
0261 
0262     parent_fwspec.fwnode = domain->parent->fwnode;
0263     parent_fwspec.param_count = 3;
0264     parent_fwspec.param[0] = GIC_SPI;
0265     parent_fwspec.param[1] = chip_data->ext_irqs[hwirq];
0266     parent_fwspec.param[2] = type;
0267 
0268     return irq_domain_alloc_irqs_parent(domain, virq, 1, &parent_fwspec);
0269 }
0270 
0271 static const struct irq_domain_ops owl_sirq_domain_ops = {
0272     .translate  = owl_sirq_domain_translate,
0273     .alloc      = owl_sirq_domain_alloc,
0274     .free       = irq_domain_free_irqs_common,
0275 };
0276 
0277 static int __init owl_sirq_init(const struct owl_sirq_params *params,
0278                 struct device_node *node,
0279                 struct device_node *parent)
0280 {
0281     struct irq_domain *domain, *parent_domain;
0282     struct owl_sirq_chip_data *chip_data;
0283     int ret, i;
0284 
0285     parent_domain = irq_find_host(parent);
0286     if (!parent_domain) {
0287         pr_err("%pOF: failed to find sirq parent domain\n", node);
0288         return -ENXIO;
0289     }
0290 
0291     chip_data = kzalloc(sizeof(*chip_data), GFP_KERNEL);
0292     if (!chip_data)
0293         return -ENOMEM;
0294 
0295     raw_spin_lock_init(&chip_data->lock);
0296 
0297     chip_data->params = params;
0298 
0299     chip_data->base = of_iomap(node, 0);
0300     if (!chip_data->base) {
0301         pr_err("%pOF: failed to map sirq registers\n", node);
0302         ret = -ENXIO;
0303         goto out_free;
0304     }
0305 
0306     for (i = 0; i < NUM_SIRQ; i++) {
0307         struct of_phandle_args irq;
0308 
0309         ret = of_irq_parse_one(node, i, &irq);
0310         if (ret) {
0311             pr_err("%pOF: failed to parse interrupt %d\n", node, i);
0312             goto out_unmap;
0313         }
0314 
0315         if (WARN_ON(irq.args_count != 3)) {
0316             ret = -EINVAL;
0317             goto out_unmap;
0318         }
0319 
0320         chip_data->ext_irqs[i] = irq.args[1];
0321 
0322         /* Set 24MHz external interrupt clock freq */
0323         owl_sirq_clear_set_extctl(chip_data, 0, INTC_EXTCTL_CLK_SEL, i);
0324     }
0325 
0326     domain = irq_domain_add_hierarchy(parent_domain, 0, NUM_SIRQ, node,
0327                       &owl_sirq_domain_ops, chip_data);
0328     if (!domain) {
0329         pr_err("%pOF: failed to add domain\n", node);
0330         ret = -ENOMEM;
0331         goto out_unmap;
0332     }
0333 
0334     return 0;
0335 
0336 out_unmap:
0337     iounmap(chip_data->base);
0338 out_free:
0339     kfree(chip_data);
0340 
0341     return ret;
0342 }
0343 
0344 static int __init owl_sirq_s500_of_init(struct device_node *node,
0345                     struct device_node *parent)
0346 {
0347     return owl_sirq_init(&owl_sirq_s500_params, node, parent);
0348 }
0349 
0350 IRQCHIP_DECLARE(owl_sirq_s500, "actions,s500-sirq", owl_sirq_s500_of_init);
0351 IRQCHIP_DECLARE(owl_sirq_s700, "actions,s700-sirq", owl_sirq_s500_of_init);
0352 
0353 static int __init owl_sirq_s900_of_init(struct device_node *node,
0354                     struct device_node *parent)
0355 {
0356     return owl_sirq_init(&owl_sirq_s900_params, node, parent);
0357 }
0358 
0359 IRQCHIP_DECLARE(owl_sirq_s900, "actions,s900-sirq", owl_sirq_s900_of_init);