0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
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
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
0038 #define INTC_EXTCTL0 0x0000
0039 #define INTC_EXTCTL1 0x0328
0040 #define INTC_EXTCTL2 0x032c
0041
0042 struct owl_sirq_params {
0043
0044 bool reg_shared;
0045
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
0057 static const struct owl_sirq_params owl_sirq_s500_params = {
0058 .reg_shared = true,
0059 .reg_offset = { 0, 0, 0 },
0060 };
0061
0062
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
0139
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
0166
0167
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
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);