From: Troy Kisky <troy.ki...@boundarydevices.com> Sent: Saturday, November 04, 2017 1:30 AM >This is better for code locality and should slightly speed up normal >interrupts. > >This also allows PPS clock output to start working for i.mx7. This is because >i.mx7 was already using the limit of 3 interrupts, and needed another. > >Signed-off-by: Troy Kisky <troy.ki...@boundarydevices.com> >
This version seems fine for me. Thanks. Acked-by: Fugang Duan <fugang.d...@nxp.com> >--- > >v2: made this change independent of any devicetree change so that old dtbs >continue to work. > >Continue to register ptp clock if interrupt is not found. > >v3: renamed "ptp" interrupt to "pps" interrupt > >v4: no change > >v5: moving binding documentation to this patch > as requested by Shawn Guo > s/irq_index/irq_idx/ > add function fec_enet_get_irq_cnt() to encapsulate if, > as requested by Andy Duan >--- > Documentation/devicetree/bindings/net/fsl-fec.txt | 13 ++++ > drivers/net/ethernet/freescale/fec.h | 3 +- > drivers/net/ethernet/freescale/fec_main.c | 31 ++++++--- > drivers/net/ethernet/freescale/fec_ptp.c | 82 +++++++++++++---------- > 4 files changed, 84 insertions(+), 45 deletions(-) > >diff --git a/Documentation/devicetree/bindings/net/fsl-fec.txt >b/Documentation/devicetree/bindings/net/fsl-fec.txt >index 6f55bdd52f8a..f0dc94409107 100644 >--- a/Documentation/devicetree/bindings/net/fsl-fec.txt >+++ b/Documentation/devicetree/bindings/net/fsl-fec.txt >@@ -34,6 +34,19 @@ Optional properties: > - fsl,err006687-workaround-present: If present indicates that the system has > the hardware workaround for ERR006687 applied and does not need a >software > workaround. >+ -interrupt-names: names of the interrupts listed in interrupts >+property in >+ the same order. The defaults if not specified are >+ __Number of interrupts__ __Default__ >+ 1 "int0" >+ 2 "int0", "pps" >+ 3 "int0", "int1", "int2" >+ 4 "int0", "int1", "int2", "pps" >+ The order may be changed as long as they correspond to the interrupts >+ property. Currently, only i.mx7 uses "int1" and "int2". They >+correspond to >+ tx/rx queues 1 and 2. "int0" will be used for queue 0 and ENET_MII >interrupts. >+ For imx6sx, "int0" handles all 3 queues and ENET_MII. "pps" is for >+the pulse >+ per second interrupt associated with 1588 precision time protocol(PTP). >+ > > Optional subnodes: > - mdio : specifies the mdio bus in the FEC, used as a container for phy nodes >diff --git a/drivers/net/ethernet/freescale/fec.h >b/drivers/net/ethernet/freescale/fec.h >index ede1876a9a19..0af58991ca8f 100644 >--- a/drivers/net/ethernet/freescale/fec.h >+++ b/drivers/net/ethernet/freescale/fec.h >@@ -582,12 +582,11 @@ struct fec_enet_private { > u64 ethtool_stats[0]; > }; > >-void fec_ptp_init(struct platform_device *pdev); >+void fec_ptp_init(struct platform_device *pdev, int irq_idx); > void fec_ptp_stop(struct platform_device *pdev); void >fec_ptp_start_cyclecounter(struct net_device *ndev); int fec_ptp_set(struct >net_device *ndev, struct ifreq *ifr); int fec_ptp_get(struct net_device *ndev, >struct ifreq *ifr); -uint fec_ptp_check_pps_event(struct fec_enet_private >*fep); > > >/********************************************************** >******************/ > #endif /* FEC_H */ >diff --git a/drivers/net/ethernet/freescale/fec_main.c >b/drivers/net/ethernet/freescale/fec_main.c >index 3dc2d771a222..610573855213 100644 >--- a/drivers/net/ethernet/freescale/fec_main.c >+++ b/drivers/net/ethernet/freescale/fec_main.c >@@ -1602,10 +1602,6 @@ fec_enet_interrupt(int irq, void *dev_id) > ret = IRQ_HANDLED; > complete(&fep->mdio_done); > } >- >- if (fep->ptp_clock) >- if (fec_ptp_check_pps_event(fep)) >- ret = IRQ_HANDLED; > return ret; > } > >@@ -3312,6 +3308,19 @@ fec_enet_get_queue_num(struct platform_device >*pdev, int *num_tx, int *num_rx) > > } > >+static int fec_enet_get_irq_cnt(struct platform_device *pdev) { >+ int irq_cnt = platform_irq_count(pdev); >+ >+ if (irq_cnt > FEC_IRQ_NUM) >+ irq_cnt = FEC_IRQ_NUM; /* last for pps */ >+ else if (irq_cnt == 2) >+ irq_cnt = 1; /* last for pps */ >+ else if (irq_cnt <= 0) >+ irq_cnt = 1; /* At least 1 irq is needed */ >+ return irq_cnt; >+} >+ > static int > fec_probe(struct platform_device *pdev) { @@ -3325,6 +3334,8 @@ >fec_probe(struct platform_device *pdev) > struct device_node *np = pdev->dev.of_node, *phy_node; > int num_tx_qs; > int num_rx_qs; >+ char irq_name[8]; >+ int irq_cnt; > > fec_enet_get_queue_num(pdev, &num_tx_qs, &num_rx_qs); > >@@ -3465,18 +3476,20 @@ fec_probe(struct platform_device *pdev) > if (ret) > goto failed_reset; > >+ irq_cnt = fec_enet_get_irq_cnt(pdev); > if (fep->bufdesc_ex) >- fec_ptp_init(pdev); >+ fec_ptp_init(pdev, irq_cnt); > > ret = fec_enet_init(ndev); > if (ret) > goto failed_init; > >- for (i = 0; i < FEC_IRQ_NUM; i++) { >- irq = platform_get_irq(pdev, i); >+ for (i = 0; i < irq_cnt; i++) { >+ sprintf(irq_name, "int%d", i); >+ irq = platform_get_irq_byname(pdev, irq_name); >+ if (irq < 0) >+ irq = platform_get_irq(pdev, i); > if (irq < 0) { >- if (i) >- break; > ret = irq; > goto failed_irq; > } >diff --git a/drivers/net/ethernet/freescale/fec_ptp.c >b/drivers/net/ethernet/freescale/fec_ptp.c >index 6ebad3fac81d..f81439796ac7 100644 >--- a/drivers/net/ethernet/freescale/fec_ptp.c >+++ b/drivers/net/ethernet/freescale/fec_ptp.c >@@ -549,6 +549,37 @@ static void fec_time_keep(struct work_struct *work) > schedule_delayed_work(&fep->time_keep, HZ); } > >+/* This function checks the pps event and reloads the timer compare >+counter. */ static irqreturn_t fec_pps_interrupt(int irq, void *dev_id) >+{ >+ struct net_device *ndev = dev_id; >+ struct fec_enet_private *fep = netdev_priv(ndev); >+ u32 val; >+ u8 channel = fep->pps_channel; >+ struct ptp_clock_event event; >+ >+ val = readl(fep->hwp + FEC_TCSR(channel)); >+ if (val & FEC_T_TF_MASK) { >+ /* Write the next next compare(not the next according the >spec) >+ * value to the register >+ */ >+ writel(fep->next_counter, fep->hwp + FEC_TCCR(channel)); >+ do { >+ writel(val, fep->hwp + FEC_TCSR(channel)); >+ } while (readl(fep->hwp + FEC_TCSR(channel)) & >FEC_T_TF_MASK); >+ >+ /* Update the counter; */ >+ fep->next_counter = (fep->next_counter + fep- >>reload_period) & >+ fep->cc.mask; >+ >+ event.type = PTP_CLOCK_PPS; >+ ptp_clock_event(fep->ptp_clock, &event); >+ return IRQ_HANDLED; >+ } >+ >+ return IRQ_NONE; >+} >+ > /** > * fec_ptp_init > * @ndev: The FEC network adapter >@@ -558,10 +589,12 @@ static void fec_time_keep(struct work_struct *work) > * cyclecounter init routine and exits. > */ > >-void fec_ptp_init(struct platform_device *pdev) >+void fec_ptp_init(struct platform_device *pdev, int irq_idx) > { > struct net_device *ndev = platform_get_drvdata(pdev); > struct fec_enet_private *fep = netdev_priv(ndev); >+ int irq; >+ int ret; > > fep->ptp_caps.owner = THIS_MODULE; > snprintf(fep->ptp_caps.name, 16, "fec ptp"); @@ -587,6 +620,20 @@ >void fec_ptp_init(struct platform_device *pdev) > > INIT_DELAYED_WORK(&fep->time_keep, fec_time_keep); > >+ irq = platform_get_irq_byname(pdev, "pps"); >+ if (irq < 0) >+ irq = platform_get_irq(pdev, irq_idx); >+ /* Failure to get an irq is not fatal, >+ * only the PTP_CLOCK_PPS clock events should stop >+ */ >+ if (irq >= 0) { >+ ret = devm_request_irq(&pdev->dev, irq, fec_pps_interrupt, >+ 0, pdev->name, ndev); >+ if (ret < 0) >+ dev_warn(&pdev->dev, "request for pps irq >failed(%d)\n", >+ ret); >+ } >+ > fep->ptp_clock = ptp_clock_register(&fep->ptp_caps, &pdev->dev); > if (IS_ERR(fep->ptp_clock)) { > fep->ptp_clock = NULL; >@@ -605,36 +652,3 @@ void fec_ptp_stop(struct platform_device *pdev) > if (fep->ptp_clock) > ptp_clock_unregister(fep->ptp_clock); > } >- >-/** >- * fec_ptp_check_pps_event >- * @fep: the fec_enet_private structure handle >- * >- * This function check the pps event and reload the timer compare counter. >- */ >-uint fec_ptp_check_pps_event(struct fec_enet_private *fep) -{ >- u32 val; >- u8 channel = fep->pps_channel; >- struct ptp_clock_event event; >- >- val = readl(fep->hwp + FEC_TCSR(channel)); >- if (val & FEC_T_TF_MASK) { >- /* Write the next next compare(not the next according the >spec) >- * value to the register >- */ >- writel(fep->next_counter, fep->hwp + FEC_TCCR(channel)); >- do { >- writel(val, fep->hwp + FEC_TCSR(channel)); >- } while (readl(fep->hwp + FEC_TCSR(channel)) & >FEC_T_TF_MASK); >- >- /* Update the counter; */ >- fep->next_counter = (fep->next_counter + fep- >>reload_period) & fep->cc.mask; >- >- event.type = PTP_CLOCK_PPS; >- ptp_clock_event(fep->ptp_clock, &event); >- return 1; >- } >- >- return 0; >-} >-- >2.11.0