summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/freescale/fec_ptp.c
diff options
context:
space:
mode:
authorTroy Kisky <troy.kisky@boundarydevices.com>2017-11-03 20:29:59 +0300
committerDavid S. Miller <davem@davemloft.net>2017-11-08 04:36:11 +0300
commit4ad1ceec05e49175d0f967cc87628101e79176f6 (patch)
treeead46b7d681cf0cc792af942752f173f66d82d94 /drivers/net/ethernet/freescale/fec_ptp.c
parentca1b17b7e843123f5a1e4c8bd2d7b6596ffe6e93 (diff)
downloadlinux-4ad1ceec05e49175d0f967cc87628101e79176f6.tar.xz
net: fec: Let fec_ptp have its own interrupt routine
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.kisky@boundarydevices.com> Acked-by: Fugang Duan <fugang.duan@nxp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/freescale/fec_ptp.c')
-rw-r--r--drivers/net/ethernet/freescale/fec_ptp.c82
1 files changed, 48 insertions, 34 deletions
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;
-}