Re: [PATCH v7 08/11] misc: rp1: RaspberryPi RP1 misc driver

Andrea della Porta
2025-02-20T17:33:18Z

Hi Stefan,

On 15:21 Sat 08 Feb , Stefan Wahren wrote:
> Hi Andrea,
>
> Am 07.02.25 um 22:31 schrieb Andrea della Porta:
> > The RaspberryPi RP1 is a PCI multi function device containing
> > peripherals ranging from Ethernet to USB controller, I2C, SPI
> > and others.

...

> > +static int rp1_irq_set_type(struct irq_data *irqd, unsigned int type)
> > +{
> > + struct rp1_dev *rp1 = irqd->domain->host_data;
> > + unsigned int hwirq = (unsigned int)irqd->hwirq;
> > +
> > + switch (type) {
> > + case IRQ_TYPE_LEVEL_HIGH:
> > + dev_dbg(&rp1->pdev->dev, "MSIX IACK EN for irq %d\n", hwirq);
> This looks a little bit inconsistent. Only this type has a debug
> message. So either we drop this or add at least a message for

I think that this is indeed asymmetric. That warning says
that the 'special' IACK management is engaged for level triggered
interrupt, which is mandatory in order to avoid missing further
interrupts without the performance loss of busy-polling for
active interrupts. This is explained in par. 6.2 of:

https://datasheets.raspberrypi.com/rp1/rp1-peripherals.pdf

The point is that we're not stating the type of the interrupt
(edge/level triggered), but we warn that we're enabling a mechanism
useful for one type only (level triggered).

> IRQ_TYPE_EDGE_RISING, too. Btw the format specifier looks wrong
> (unsigned int vs %d).

Ack.

> > + msix_cfg_set(rp1, hwirq, MSIX_CFG_IACK_EN);
> > + rp1->level_triggered_irq[hwirq] = true;
> > + break;
> > + case IRQ_TYPE_EDGE_RISING:
> > + msix_cfg_clr(rp1, hwirq, MSIX_CFG_IACK_EN);
> > + rp1->level_triggered_irq[hwirq] = false;
> > + break;
> > + default:
> > + return -EINVAL;
> It would be nice to document why only IRQ_TYPE_LEVEL_HIGH and
> IRQ_TYPE_EDGE_RISING are supported. In case it's a software limitation,
> this function would be a good place. In case this is a hardware
> limitation this should be in the binding.

All ints are level-triggered. I guess I should add a short comment in
the bindings.

> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static struct irq_chip rp1_irq_chip = {
> > + .name = "rp1_irq_chip",
> > + .irq_mask = rp1_mask_irq,
> > + .irq_unmask = rp1_unmask_irq,
> > + .irq_set_type = rp1_irq_set_type,
> > +};

...

> > + irq_set_chip_and_handler(irq, &rp1_irq_chip, handle_level_irq);
> > + irq_set_probe(irq);
> > + irq_set_chained_handler_and_data(pci_irq_vector(pdev, i),
> > + rp1_chained_handle_irq, rp1);
> > + }
> > +
> > + err = of_overlay_fdt_apply(dtbo_start, dtbo_size, &rp1->ovcs_id, rp1_node);
> > + if (err)
> > + goto err_unregister_interrupts;
> > +
> > + err = of_platform_default_populate(rp1_node, NULL, dev);
> > + if (err)
> > + goto err_unload_overlay;
> I think in this case it's worth to add a suitable dev_err() here.

Ack.

Many thanks,
Andrea

>
> Thanks