Thread (92 messages) 92 messages, 13 authors, 2017-12-08

Re: [PATCH v2 27/35] irqchip: Andestech Internal Vector Interrupt Controller driver

From: Greentime Hu <hidden>
Date: 2017-11-29 15:24:18
Also in: linux-arch, linux-devicetree, linux-serial, lkml

Hi, Marc:

2017-11-28 17:37 GMT+08:00 Marc Zyngier [off-list ref]:
On 27/11/17 12:28, Greentime Hu wrote:
quoted
+static void ativic32_ack_irq(struct irq_data *data)
+{
+     __nds32__mtsr_dsb(1 << data->hwirq, NDS32_SR_INT_PEND2);
Consider writing (1 << data->hwirq) as BIT(data->hwirq).
Thanks for this suggestion. I will modify it in the next version patch.
quoted
+}
+
+static void ativic32_mask_irq(struct irq_data *data)
+{
+     unsigned long int_mask2 = __nds32__mfsr(NDS32_SR_INT_MASK2);
+     __nds32__mtsr_dsb(int_mask2 & (~(1 << data->hwirq)), NDS32_SR_INT_MASK2);
Same here.
Thanks for this suggestion. I will modify it in the next version patch.
quoted
+}
+
+static void ativic32_mask_ack_irq(struct irq_data *data)
+{
+     unsigned long int_mask2 = __nds32__mfsr(NDS32_SR_INT_MASK2);
+     __nds32__mtsr_dsb(int_mask2 & (~(1 << data->hwirq)), NDS32_SR_INT_MASK2);
+     __nds32__mtsr_dsb((1 << data->hwirq), NDS32_SR_INT_PEND2);
This is effectively MASK+ACK, so you're better off just writing it as
such. And since there is no advantage in your implementation in having
MASK_ACK over MASK+ACK, I suggest you remove this function completely,
and rely on the core code which will call them in sequence.
I think mask_ack is still better than mask + ack because we don't need
to do two function call.
We can save a prologue and a epilogue. It will benefit interrupt latency.
quoted
+
+}
+
+static void ativic32_unmask_irq(struct irq_data *data)
+{
+     unsigned long int_mask2 = __nds32__mfsr(NDS32_SR_INT_MASK2);
+     __nds32__mtsr_dsb(int_mask2 | (1 << data->hwirq), NDS32_SR_INT_MASK2);
Same BIT() here.
Thanks for this suggestion. I will modify it in the next version patch.
quoted
+}
+
+static struct irq_chip ativic32_chip = {
+     .name = "ativic32",
+     .irq_ack = ativic32_ack_irq,
+     .irq_mask = ativic32_mask_irq,
+     .irq_mask_ack = ativic32_mask_ack_irq,
+     .irq_unmask = ativic32_unmask_irq,
+};
+
+static unsigned int __initdata nivic_map[6] = { 6, 2, 10, 16, 24, 32 };
+
+static struct irq_domain *root_domain;
+static int ativic32_irq_domain_map(struct irq_domain *id, unsigned int virq,
+                               irq_hw_number_t hw)
+{
+
+     unsigned long int_trigger_type;
+     int_trigger_type = __nds32__mfsr(NDS32_SR_INT_TRIGGER);
+     if (int_trigger_type & (1 << hw))
And here.
Thanks for this suggestion. I will modify it in the next version patch.
quoted
+             irq_set_chip_and_handler(virq, &ativic32_chip, handle_edge_irq);
+     else
+             irq_set_chip_and_handler(virq, &ativic32_chip, handle_level_irq);
Since you do not express the trigger in DT, you need to tell the core
about it by calling irqd_set_trigger_type() with the right setting.
Since the comments say so, I will add ativic32_set_type() for irq_set_type()
in the next version patch.

/*
 * Must only be called inside irq_chip.irq_set_type() functions.
 */
static inline void irqd_set_trigger_type(struct irq_data *d, u32 type)
{
        __irqd_to_state(d) &= ~IRQD_TRIGGER_MASK;
        __irqd_to_state(d) |= type & IRQD_TRIGGER_MASK;
}

It will be like this.
static int ativic32_set_type(struct irq_data *data, unsigned int flow_type)
{
        irqd_set_trigger_type(data, flow_type);
        return IRQ_SET_MASK_OK;
}
quoted
+
+     return 0;
+}
+
+static struct irq_domain_ops ativic32_ops = {
+     .map = ativic32_irq_domain_map,
+     .xlate = irq_domain_xlate_onecell
+};
+
+static int get_intr_src(void)
I'm not sure "int" is the best return type here. I suspect something
unsigned would be preferable, or even the irq_hw_number_t type.
Thanks for this suggestion. I will modify it in the next version patch.
quoted
+{
+     return ((__nds32__mfsr(NDS32_SR_ITYPE)&ITYPE_mskVECTOR) >> ITYPE_offVECTOR)
Spaces around '&'.
Thanks for this suggestion. I will modify it in the next version patch.
quoted
+             - NDS32_VECTOR_offINTERRUPT;
+}
+
+asmlinkage void asm_do_IRQ(struct pt_regs *regs)
+{
+     int hwirq = get_intr_src();
irq_hw_number_t.
Thanks for this suggestion. I will modify it in the next version patch.
quoted
+     handle_domain_irq(root_domain, hwirq, regs);
+}
+
+int __init ativic32_init_irq(struct device_node *node, struct device_node *parent)
+{
+     unsigned long int_vec_base, nivic;
+
+     if (WARN(parent, "non-root ativic32 are not supported"))
+             return -EINVAL;
+
+     int_vec_base = __nds32__mfsr(NDS32_SR_IVB);
+
+     if (((int_vec_base & IVB_mskIVIC_VER) >> IVB_offIVIC_VER) == 0)
+             panic("Unable to use atcivic32 for this cpu.\n");
+
+     nivic = (int_vec_base & IVB_mskNIVIC) >> IVB_offNIVIC;
+     if (nivic >= (sizeof nivic_map / sizeof nivic_map[0]))
This should be:
        if (nivic >= ARRAY_SIZE(NIVIC_MAP))
Thanks for this suggestion. I will modify it in the next version patch.
quoted
+             panic("The number of input for ativic32 is not supported.\n");
+
+     nivic = nivic_map[nivic];
I'd rather you use another variable (nr_ints?).
Thanks for this suggestion. I will modify it in the next version patch.
quoted
+
+     root_domain = irq_domain_add_linear(node, nivic,
+                     &ativic32_ops, NULL);
+
+     if (!root_domain)
+             panic("%s: unable to create IRQ domain\n", node->full_name);
+
+     return 0;
+}
+IRQCHIP_DECLARE(ativic32, "andestech,ativic32", ativic32_init_irq);
Thanks,

        M.
--
Jazz is not dead. It just smells funny...
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help