0001
0002
0003
0004
0005
0006
0007 #include <linux/clk.h>
0008 #include <linux/interrupt.h>
0009 #include <linux/irqchip.h>
0010 #include <linux/irqchip/chained_irq.h>
0011 #include <linux/mfd/ingenic-tcu.h>
0012 #include <linux/mfd/syscon.h>
0013 #include <linux/of_irq.h>
0014 #include <linux/regmap.h>
0015
0016 struct ingenic_tcu {
0017 struct regmap *map;
0018 struct clk *clk;
0019 struct irq_domain *domain;
0020 unsigned int nb_parent_irqs;
0021 u32 parent_irqs[3];
0022 };
0023
0024 static void ingenic_tcu_intc_cascade(struct irq_desc *desc)
0025 {
0026 struct irq_chip *irq_chip = irq_data_get_irq_chip(&desc->irq_data);
0027 struct irq_domain *domain = irq_desc_get_handler_data(desc);
0028 struct irq_chip_generic *gc = irq_get_domain_generic_chip(domain, 0);
0029 struct regmap *map = gc->private;
0030 uint32_t irq_reg, irq_mask;
0031 unsigned long bits;
0032 unsigned int i;
0033
0034 regmap_read(map, TCU_REG_TFR, &irq_reg);
0035 regmap_read(map, TCU_REG_TMR, &irq_mask);
0036
0037 chained_irq_enter(irq_chip, desc);
0038
0039 irq_reg &= ~irq_mask;
0040 bits = irq_reg;
0041
0042 for_each_set_bit(i, &bits, 32)
0043 generic_handle_domain_irq(domain, i);
0044
0045 chained_irq_exit(irq_chip, desc);
0046 }
0047
0048 static void ingenic_tcu_gc_unmask_enable_reg(struct irq_data *d)
0049 {
0050 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
0051 struct irq_chip_type *ct = irq_data_get_chip_type(d);
0052 struct regmap *map = gc->private;
0053 u32 mask = d->mask;
0054
0055 irq_gc_lock(gc);
0056 regmap_write(map, ct->regs.ack, mask);
0057 regmap_write(map, ct->regs.enable, mask);
0058 *ct->mask_cache |= mask;
0059 irq_gc_unlock(gc);
0060 }
0061
0062 static void ingenic_tcu_gc_mask_disable_reg(struct irq_data *d)
0063 {
0064 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
0065 struct irq_chip_type *ct = irq_data_get_chip_type(d);
0066 struct regmap *map = gc->private;
0067 u32 mask = d->mask;
0068
0069 irq_gc_lock(gc);
0070 regmap_write(map, ct->regs.disable, mask);
0071 *ct->mask_cache &= ~mask;
0072 irq_gc_unlock(gc);
0073 }
0074
0075 static void ingenic_tcu_gc_mask_disable_reg_and_ack(struct irq_data *d)
0076 {
0077 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
0078 struct irq_chip_type *ct = irq_data_get_chip_type(d);
0079 struct regmap *map = gc->private;
0080 u32 mask = d->mask;
0081
0082 irq_gc_lock(gc);
0083 regmap_write(map, ct->regs.ack, mask);
0084 regmap_write(map, ct->regs.disable, mask);
0085 irq_gc_unlock(gc);
0086 }
0087
0088 static int __init ingenic_tcu_irq_init(struct device_node *np,
0089 struct device_node *parent)
0090 {
0091 struct irq_chip_generic *gc;
0092 struct irq_chip_type *ct;
0093 struct ingenic_tcu *tcu;
0094 struct regmap *map;
0095 unsigned int i;
0096 int ret, irqs;
0097
0098 map = device_node_to_regmap(np);
0099 if (IS_ERR(map))
0100 return PTR_ERR(map);
0101
0102 tcu = kzalloc(sizeof(*tcu), GFP_KERNEL);
0103 if (!tcu)
0104 return -ENOMEM;
0105
0106 tcu->map = map;
0107
0108 irqs = of_property_count_elems_of_size(np, "interrupts", sizeof(u32));
0109 if (irqs < 0 || irqs > ARRAY_SIZE(tcu->parent_irqs)) {
0110 pr_crit("%s: Invalid 'interrupts' property\n", __func__);
0111 ret = -EINVAL;
0112 goto err_free_tcu;
0113 }
0114
0115 tcu->nb_parent_irqs = irqs;
0116
0117 tcu->domain = irq_domain_add_linear(np, 32, &irq_generic_chip_ops,
0118 NULL);
0119 if (!tcu->domain) {
0120 ret = -ENOMEM;
0121 goto err_free_tcu;
0122 }
0123
0124 ret = irq_alloc_domain_generic_chips(tcu->domain, 32, 1, "TCU",
0125 handle_level_irq, 0,
0126 IRQ_NOPROBE | IRQ_LEVEL, 0);
0127 if (ret) {
0128 pr_crit("%s: Invalid 'interrupts' property\n", __func__);
0129 goto out_domain_remove;
0130 }
0131
0132 gc = irq_get_domain_generic_chip(tcu->domain, 0);
0133 ct = gc->chip_types;
0134
0135 gc->wake_enabled = IRQ_MSK(32);
0136 gc->private = tcu->map;
0137
0138 ct->regs.disable = TCU_REG_TMSR;
0139 ct->regs.enable = TCU_REG_TMCR;
0140 ct->regs.ack = TCU_REG_TFCR;
0141 ct->chip.irq_unmask = ingenic_tcu_gc_unmask_enable_reg;
0142 ct->chip.irq_mask = ingenic_tcu_gc_mask_disable_reg;
0143 ct->chip.irq_mask_ack = ingenic_tcu_gc_mask_disable_reg_and_ack;
0144 ct->chip.flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE;
0145
0146
0147 regmap_write(tcu->map, TCU_REG_TMSR, IRQ_MSK(32));
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159 for (i = 0; i < irqs; i++) {
0160 tcu->parent_irqs[i] = irq_of_parse_and_map(np, i);
0161 if (!tcu->parent_irqs[i]) {
0162 ret = -EINVAL;
0163 goto out_unmap_irqs;
0164 }
0165
0166 irq_set_chained_handler_and_data(tcu->parent_irqs[i],
0167 ingenic_tcu_intc_cascade,
0168 tcu->domain);
0169 }
0170
0171 return 0;
0172
0173 out_unmap_irqs:
0174 for (; i > 0; i--)
0175 irq_dispose_mapping(tcu->parent_irqs[i - 1]);
0176 out_domain_remove:
0177 irq_domain_remove(tcu->domain);
0178 err_free_tcu:
0179 kfree(tcu);
0180 return ret;
0181 }
0182 IRQCHIP_DECLARE(jz4740_tcu_irq, "ingenic,jz4740-tcu", ingenic_tcu_irq_init);
0183 IRQCHIP_DECLARE(jz4725b_tcu_irq, "ingenic,jz4725b-tcu", ingenic_tcu_irq_init);
0184 IRQCHIP_DECLARE(jz4760_tcu_irq, "ingenic,jz4760-tcu", ingenic_tcu_irq_init);
0185 IRQCHIP_DECLARE(jz4770_tcu_irq, "ingenic,jz4770-tcu", ingenic_tcu_irq_init);
0186 IRQCHIP_DECLARE(x1000_tcu_irq, "ingenic,x1000-tcu", ingenic_tcu_irq_init);