Hi Prabhakar, On Wed, Jul 21, 2021 at 9:50 PM Lad Prabhakar <prabhakar.mahadev-lad.rj@xxxxxxxxxxxxxx> wrote: > CANFD block on RZ/G2L SoC is almost identical to one found on > R-Car Gen3 SoC's. On RZ/G2L SoC interrupt sources for each channel > are split into different sources and the IP doesn't divide (1/2) > CANFD clock within the IP. > > This patch adds compatible string for RZ/G2L family and registers > the irq handlers required for CANFD operation. IRQ numbers are now > fetched based on names instead of indices. For backward compatibility > on non RZ/G2L SoC's we fallback reading based on indices. > > Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@xxxxxxxxxxxxxx> Thanks for the update! I think you misunderstood my comment on v1 about the interrupt handlers, cfr. below. > --- a/drivers/net/can/rcar/rcar_canfd.c > +++ b/drivers/net/can/rcar/rcar_canfd.c > @@ -1577,6 +1586,53 @@ static int rcar_canfd_channel_probe(struct rcar_canfd_global *gpriv, u32 ch, > priv->can.clock.freq = fcan_freq; > dev_info(&pdev->dev, "can_clk rate is %u\n", priv->can.clock.freq); > > + if (gpriv->chip_id == RENESAS_RZG2L) { > + char *irq_name; > + int err_irq; > + int tx_irq; > + > + err_irq = platform_get_irq_byname(pdev, ch == 0 ? "ch0_err" : "ch1_err"); > + if (err_irq < 0) { > + err = err_irq; > + goto fail; > + } > + > + tx_irq = platform_get_irq_byname(pdev, ch == 0 ? "ch0_trx" : "ch1_trx"); > + if (tx_irq < 0) { > + err = tx_irq; > + goto fail; > + } > + > + irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, > + "canfd.ch%d_err", ch); > + if (!irq_name) { > + err = -ENOMEM; > + goto fail; > + } > + err = devm_request_irq(&pdev->dev, err_irq, > + rcar_canfd_channel_interrupt, 0, This is the same interrupt handler... > + irq_name, gpriv); > + if (err) { > + dev_err(&pdev->dev, "devm_request_irq CH Err(%d) failed, error %d\n", > + err_irq, err); > + goto fail; > + } > + irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, > + "canfd.ch%d_trx", ch); > + if (!irq_name) { > + err = -ENOMEM; > + goto fail; > + } > + err = devm_request_irq(&pdev->dev, tx_irq, > + rcar_canfd_channel_interrupt, 0, ... as this one. > + irq_name, gpriv); > + if (err) { > + dev_err(&pdev->dev, "devm_request_irq Tx (%d) failed, error %d\n", > + tx_irq, err); > + goto fail; > + } > + } > + > if (gpriv->fdmode) { > priv->can.bittiming_const = &rcar_canfd_nom_bittiming_const; > priv->can.data_bittiming_const = > @@ -1711,20 +1798,51 @@ static int rcar_canfd_probe(struct platform_device *pdev) > gpriv->base = addr; > > /* Request IRQ that's common for both channels */ > - err = devm_request_irq(&pdev->dev, ch_irq, > - rcar_canfd_channel_interrupt, 0, > - "canfd.chn", gpriv); > - if (err) { > - dev_err(&pdev->dev, "devm_request_irq(%d) failed, error %d\n", > - ch_irq, err); > - goto fail_dev; > + if (gpriv->chip_id == RENESAS_RCAR_GEN3) { > + err = devm_request_irq(&pdev->dev, ch_irq, > + rcar_canfd_channel_interrupt, 0, > + "canfd.ch_int", gpriv); > + if (err) { > + dev_err(&pdev->dev, "devm_request_irq(%d) failed, error %d\n", > + ch_irq, err); > + goto fail_dev; > + } > + > + err = devm_request_irq(&pdev->dev, g_irq, > + rcar_canfd_global_interrupt, 0, > + "canfd.g_int", gpriv); > + if (err) { > + dev_err(&pdev->dev, "devm_request_irq(%d) failed, error %d\n", > + g_irq, err); > + goto fail_dev; > + } > + } else { > + err = devm_request_irq(&pdev->dev, g_recc_irq, > + rcar_canfd_global_interrupt, 0, This is the same interrupt handler... > + "canfd.g_recc", gpriv); > + > + if (err) { > + dev_err(&pdev->dev, "devm_request_irq(%d) failed, error %d\n", > + g_recc_irq, err); > + goto fail_dev; > + } > + > + err = devm_request_irq(&pdev->dev, g_err_irq, > + rcar_canfd_global_interrupt, 0, ... as this one. > + "canfd.g_err", gpriv); > + if (err) { > + dev_err(&pdev->dev, "devm_request_irq(%d) failed, error %d\n", > + g_err_irq, err); > + goto fail_dev; > + } > } > - err = devm_request_irq(&pdev->dev, g_irq, > - rcar_canfd_global_interrupt, 0, > - "canfd.gbl", gpriv); > + > + err = reset_control_reset(gpriv->rstc1); > + if (err) > + goto fail_dev; > + err = reset_control_reset(gpriv->rstc2); > if (err) { > - dev_err(&pdev->dev, "devm_request_irq(%d) failed, error %d\n", > - g_irq, err); > + reset_control_assert(gpriv->rstc1); > goto fail_dev; > } I did not object to having fine-grained interrupt handlers on RZ/G2L. I did object to duplicating code in global and fine-grained interrupt handlers. The trick to have both is to let the global interrupt handlers call (conditionally) into the fine-grained handlers. In pseudo-code: global_interrupt_handler() { if (...) fine_grained_handler1(); if (...) fine_grained_handler2(); ... } On R-Car Gen3, you register the global interrupt handlers, as before. On RZ/G2L, you register the fine-grained interrupt handlers instead. Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@xxxxxxxxxxxxxx In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds