0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042 #include <linux/bitmap.h>
0043 #include <linux/interrupt.h>
0044 #include <linux/irq.h>
0045 #include <linux/irqchip.h>
0046 #include <linux/irqdomain.h>
0047 #include <linux/of.h>
0048 #include <linux/of_address.h>
0049 #include <linux/of_irq.h>
0050 #include <linux/syscore_ops.h>
0051
0052 #include <dt-bindings/interrupt-controller/arm-gic.h>
0053
0054 #define SUN6I_NMI_CTRL (0x0c)
0055 #define SUN6I_IRQ_PENDING(n) (0x10 + 4 * (n))
0056 #define SUN6I_IRQ_ENABLE(n) (0x40 + 4 * (n))
0057 #define SUN6I_MUX_ENABLE(n) (0xc0 + 4 * (n))
0058
0059 #define SUN6I_NMI_SRC_TYPE_LEVEL_LOW 0
0060 #define SUN6I_NMI_SRC_TYPE_EDGE_FALLING 1
0061 #define SUN6I_NMI_SRC_TYPE_LEVEL_HIGH 2
0062 #define SUN6I_NMI_SRC_TYPE_EDGE_RISING 3
0063
0064 #define SUN6I_NMI_BIT BIT(0)
0065
0066 #define SUN6I_NMI_NEEDS_ACK ((void *)1)
0067
0068 #define SUN6I_NR_TOP_LEVEL_IRQS 64
0069 #define SUN6I_NR_DIRECT_IRQS 16
0070 #define SUN6I_NR_MUX_BITS 128
0071
0072 struct sun6i_r_intc_variant {
0073 u32 first_mux_irq;
0074 u32 nr_mux_irqs;
0075 u32 mux_valid[BITS_TO_U32(SUN6I_NR_MUX_BITS)];
0076 };
0077
0078 static void __iomem *base;
0079 static irq_hw_number_t nmi_hwirq;
0080 static DECLARE_BITMAP(wake_irq_enabled, SUN6I_NR_TOP_LEVEL_IRQS);
0081 static DECLARE_BITMAP(wake_mux_enabled, SUN6I_NR_MUX_BITS);
0082 static DECLARE_BITMAP(wake_mux_valid, SUN6I_NR_MUX_BITS);
0083
0084 static void sun6i_r_intc_ack_nmi(void)
0085 {
0086 writel_relaxed(SUN6I_NMI_BIT, base + SUN6I_IRQ_PENDING(0));
0087 }
0088
0089 static void sun6i_r_intc_nmi_ack(struct irq_data *data)
0090 {
0091 if (irqd_get_trigger_type(data) & IRQ_TYPE_EDGE_BOTH)
0092 sun6i_r_intc_ack_nmi();
0093 else
0094 data->chip_data = SUN6I_NMI_NEEDS_ACK;
0095 }
0096
0097 static void sun6i_r_intc_nmi_eoi(struct irq_data *data)
0098 {
0099
0100 if (data->chip_data == SUN6I_NMI_NEEDS_ACK && !irqd_irq_masked(data)) {
0101 data->chip_data = NULL;
0102 sun6i_r_intc_ack_nmi();
0103 }
0104
0105 irq_chip_eoi_parent(data);
0106 }
0107
0108 static void sun6i_r_intc_nmi_unmask(struct irq_data *data)
0109 {
0110 if (data->chip_data == SUN6I_NMI_NEEDS_ACK) {
0111 data->chip_data = NULL;
0112 sun6i_r_intc_ack_nmi();
0113 }
0114
0115 irq_chip_unmask_parent(data);
0116 }
0117
0118 static int sun6i_r_intc_nmi_set_type(struct irq_data *data, unsigned int type)
0119 {
0120 u32 nmi_src_type;
0121
0122 switch (type) {
0123 case IRQ_TYPE_EDGE_RISING:
0124 nmi_src_type = SUN6I_NMI_SRC_TYPE_EDGE_RISING;
0125 break;
0126 case IRQ_TYPE_EDGE_FALLING:
0127 nmi_src_type = SUN6I_NMI_SRC_TYPE_EDGE_FALLING;
0128 break;
0129 case IRQ_TYPE_LEVEL_HIGH:
0130 nmi_src_type = SUN6I_NMI_SRC_TYPE_LEVEL_HIGH;
0131 break;
0132 case IRQ_TYPE_LEVEL_LOW:
0133 nmi_src_type = SUN6I_NMI_SRC_TYPE_LEVEL_LOW;
0134 break;
0135 default:
0136 return -EINVAL;
0137 }
0138
0139 writel_relaxed(nmi_src_type, base + SUN6I_NMI_CTRL);
0140
0141
0142
0143
0144
0145
0146 return irq_chip_set_type_parent(data, IRQ_TYPE_LEVEL_HIGH);
0147 }
0148
0149 static int sun6i_r_intc_nmi_set_irqchip_state(struct irq_data *data,
0150 enum irqchip_irq_state which,
0151 bool state)
0152 {
0153 if (which == IRQCHIP_STATE_PENDING && !state)
0154 sun6i_r_intc_ack_nmi();
0155
0156 return irq_chip_set_parent_state(data, which, state);
0157 }
0158
0159 static int sun6i_r_intc_irq_set_wake(struct irq_data *data, unsigned int on)
0160 {
0161 unsigned long offset_from_nmi = data->hwirq - nmi_hwirq;
0162
0163 if (offset_from_nmi < SUN6I_NR_DIRECT_IRQS)
0164 assign_bit(offset_from_nmi, wake_irq_enabled, on);
0165 else if (test_bit(data->hwirq, wake_mux_valid))
0166 assign_bit(data->hwirq, wake_mux_enabled, on);
0167 else
0168
0169 return -EPERM;
0170
0171 return 0;
0172 }
0173
0174 static struct irq_chip sun6i_r_intc_nmi_chip = {
0175 .name = "sun6i-r-intc",
0176 .irq_ack = sun6i_r_intc_nmi_ack,
0177 .irq_mask = irq_chip_mask_parent,
0178 .irq_unmask = sun6i_r_intc_nmi_unmask,
0179 .irq_eoi = sun6i_r_intc_nmi_eoi,
0180 .irq_set_affinity = irq_chip_set_affinity_parent,
0181 .irq_set_type = sun6i_r_intc_nmi_set_type,
0182 .irq_set_irqchip_state = sun6i_r_intc_nmi_set_irqchip_state,
0183 .irq_set_wake = sun6i_r_intc_irq_set_wake,
0184 .flags = IRQCHIP_SET_TYPE_MASKED,
0185 };
0186
0187 static struct irq_chip sun6i_r_intc_wakeup_chip = {
0188 .name = "sun6i-r-intc",
0189 .irq_mask = irq_chip_mask_parent,
0190 .irq_unmask = irq_chip_unmask_parent,
0191 .irq_eoi = irq_chip_eoi_parent,
0192 .irq_set_affinity = irq_chip_set_affinity_parent,
0193 .irq_set_type = irq_chip_set_type_parent,
0194 .irq_set_wake = sun6i_r_intc_irq_set_wake,
0195 .flags = IRQCHIP_SET_TYPE_MASKED,
0196 };
0197
0198 static int sun6i_r_intc_domain_translate(struct irq_domain *domain,
0199 struct irq_fwspec *fwspec,
0200 unsigned long *hwirq,
0201 unsigned int *type)
0202 {
0203
0204 if (fwspec->param_count == 2 && fwspec->param[0] == 0) {
0205 *hwirq = nmi_hwirq;
0206 *type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;
0207 return 0;
0208 }
0209
0210
0211 if (fwspec->param_count < 3)
0212 return -EINVAL;
0213 if (fwspec->param[0] != GIC_SPI)
0214 return -EINVAL;
0215
0216 *hwirq = fwspec->param[1];
0217 *type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;
0218
0219 return 0;
0220 }
0221
0222 static int sun6i_r_intc_domain_alloc(struct irq_domain *domain,
0223 unsigned int virq,
0224 unsigned int nr_irqs, void *arg)
0225 {
0226 struct irq_fwspec *fwspec = arg;
0227 struct irq_fwspec gic_fwspec;
0228 unsigned long hwirq;
0229 unsigned int type;
0230 int i, ret;
0231
0232 ret = sun6i_r_intc_domain_translate(domain, fwspec, &hwirq, &type);
0233 if (ret)
0234 return ret;
0235 if (hwirq + nr_irqs > SUN6I_NR_MUX_BITS)
0236 return -EINVAL;
0237
0238
0239 gic_fwspec = (struct irq_fwspec) {
0240 .fwnode = domain->parent->fwnode,
0241 .param_count = 3,
0242 .param = { GIC_SPI, hwirq, type },
0243 };
0244
0245 ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &gic_fwspec);
0246 if (ret)
0247 return ret;
0248
0249 for (i = 0; i < nr_irqs; ++i, ++hwirq, ++virq) {
0250 if (hwirq == nmi_hwirq) {
0251 irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
0252 &sun6i_r_intc_nmi_chip,
0253 NULL);
0254 irq_set_handler(virq, handle_fasteoi_ack_irq);
0255 } else {
0256 irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
0257 &sun6i_r_intc_wakeup_chip,
0258 NULL);
0259 }
0260 }
0261
0262 return 0;
0263 }
0264
0265 static const struct irq_domain_ops sun6i_r_intc_domain_ops = {
0266 .translate = sun6i_r_intc_domain_translate,
0267 .alloc = sun6i_r_intc_domain_alloc,
0268 .free = irq_domain_free_irqs_common,
0269 };
0270
0271 static int sun6i_r_intc_suspend(void)
0272 {
0273 u32 buf[BITS_TO_U32(max(SUN6I_NR_TOP_LEVEL_IRQS, SUN6I_NR_MUX_BITS))];
0274 int i;
0275
0276
0277 bitmap_to_arr32(buf, wake_irq_enabled, SUN6I_NR_TOP_LEVEL_IRQS);
0278 for (i = 0; i < BITS_TO_U32(SUN6I_NR_TOP_LEVEL_IRQS); ++i)
0279 writel_relaxed(buf[i], base + SUN6I_IRQ_ENABLE(i));
0280 bitmap_to_arr32(buf, wake_mux_enabled, SUN6I_NR_MUX_BITS);
0281 for (i = 0; i < BITS_TO_U32(SUN6I_NR_MUX_BITS); ++i)
0282 writel_relaxed(buf[i], base + SUN6I_MUX_ENABLE(i));
0283
0284 return 0;
0285 }
0286
0287 static void sun6i_r_intc_resume(void)
0288 {
0289 int i;
0290
0291
0292 writel_relaxed(SUN6I_NMI_BIT, base + SUN6I_IRQ_ENABLE(0));
0293 for (i = 1; i < BITS_TO_U32(SUN6I_NR_TOP_LEVEL_IRQS); ++i)
0294 writel_relaxed(0, base + SUN6I_IRQ_ENABLE(i));
0295 }
0296
0297 static void sun6i_r_intc_shutdown(void)
0298 {
0299 sun6i_r_intc_suspend();
0300 }
0301
0302 static struct syscore_ops sun6i_r_intc_syscore_ops = {
0303 .suspend = sun6i_r_intc_suspend,
0304 .resume = sun6i_r_intc_resume,
0305 .shutdown = sun6i_r_intc_shutdown,
0306 };
0307
0308 static int __init sun6i_r_intc_init(struct device_node *node,
0309 struct device_node *parent,
0310 const struct sun6i_r_intc_variant *v)
0311 {
0312 struct irq_domain *domain, *parent_domain;
0313 struct of_phandle_args nmi_parent;
0314 int ret;
0315
0316
0317 ret = of_irq_parse_one(node, 0, &nmi_parent);
0318 if (ret)
0319 return ret;
0320 if (nmi_parent.args_count < 3 ||
0321 nmi_parent.args[0] != GIC_SPI ||
0322 nmi_parent.args[2] != IRQ_TYPE_LEVEL_HIGH)
0323 return -EINVAL;
0324 nmi_hwirq = nmi_parent.args[1];
0325
0326 bitmap_set(wake_irq_enabled, v->first_mux_irq, v->nr_mux_irqs);
0327 bitmap_from_arr32(wake_mux_valid, v->mux_valid, SUN6I_NR_MUX_BITS);
0328
0329 parent_domain = irq_find_host(parent);
0330 if (!parent_domain) {
0331 pr_err("%pOF: Failed to obtain parent domain\n", node);
0332 return -ENXIO;
0333 }
0334
0335 base = of_io_request_and_map(node, 0, NULL);
0336 if (IS_ERR(base)) {
0337 pr_err("%pOF: Failed to map MMIO region\n", node);
0338 return PTR_ERR(base);
0339 }
0340
0341 domain = irq_domain_add_hierarchy(parent_domain, 0, 0, node,
0342 &sun6i_r_intc_domain_ops, NULL);
0343 if (!domain) {
0344 pr_err("%pOF: Failed to allocate domain\n", node);
0345 iounmap(base);
0346 return -ENOMEM;
0347 }
0348
0349 register_syscore_ops(&sun6i_r_intc_syscore_ops);
0350
0351 sun6i_r_intc_ack_nmi();
0352 sun6i_r_intc_resume();
0353
0354 return 0;
0355 }
0356
0357 static const struct sun6i_r_intc_variant sun6i_a31_r_intc_variant __initconst = {
0358 .first_mux_irq = 19,
0359 .nr_mux_irqs = 13,
0360 .mux_valid = { 0xffffffff, 0xfff80000, 0xffffffff, 0x0000000f },
0361 };
0362
0363 static int __init sun6i_a31_r_intc_init(struct device_node *node,
0364 struct device_node *parent)
0365 {
0366 return sun6i_r_intc_init(node, parent, &sun6i_a31_r_intc_variant);
0367 }
0368 IRQCHIP_DECLARE(sun6i_a31_r_intc, "allwinner,sun6i-a31-r-intc", sun6i_a31_r_intc_init);
0369
0370 static const struct sun6i_r_intc_variant sun50i_h6_r_intc_variant __initconst = {
0371 .first_mux_irq = 21,
0372 .nr_mux_irqs = 16,
0373 .mux_valid = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff },
0374 };
0375
0376 static int __init sun50i_h6_r_intc_init(struct device_node *node,
0377 struct device_node *parent)
0378 {
0379 return sun6i_r_intc_init(node, parent, &sun50i_h6_r_intc_variant);
0380 }
0381 IRQCHIP_DECLARE(sun50i_h6_r_intc, "allwinner,sun50i-h6-r-intc", sun50i_h6_r_intc_init);