irqreturn_t ptp_qoriq_isr(int irq, void *priv) { struct ptp_qoriq *ptp_qoriq = priv; struct ptp_qoriq_registers *regs = &ptp_qoriq->regs; struct ptp_clock_event event; u64 ns; u32 ack = 0, lo, hi, mask, val, irqs; spin_lock(&ptp_qoriq->lock); val = ptp_qoriq->read(®s->ctrl_regs->tmr_tevent); mask = ptp_qoriq->read(®s->ctrl_regs->tmr_temask); spin_unlock(&ptp_qoriq->lock); irqs = val & mask; if (irqs & ETS1) { ack |= ETS1; extts_clean_up(ptp_qoriq, 0, true); } if (irqs & ETS2) { ack |= ETS2; extts_clean_up(ptp_qoriq, 1, true); } if (irqs & ALM2) { ack |= ALM2; if (ptp_qoriq->alarm_value) { event.type = PTP_CLOCK_ALARM; event.index = 0; event.timestamp = ptp_qoriq->alarm_value; ptp_clock_event(ptp_qoriq->clock, &event); } if (ptp_qoriq->alarm_interval) { ns = ptp_qoriq->alarm_value + ptp_qoriq->alarm_interval; hi = ns >> 32; lo = ns & 0xffffffff; ptp_qoriq->write(®s->alarm_regs->tmr_alarm2_l, lo); ptp_qoriq->write(®s->alarm_regs->tmr_alarm2_h, hi); ptp_qoriq->alarm_value = ns; } else {
static int extts_clean_up(struct ptp_qoriq *ptp_qoriq, int index, bool update_event) { struct ptp_qoriq_registers *regs = &ptp_qoriq->regs; struct ptp_clock_event event; void __iomem *reg_etts_l; void __iomem *reg_etts_h; u32 valid, stat, lo, hi; switch (index) { case 0: valid = ETS1_VLD; reg_etts_l = ®s->etts_regs->tmr_etts1_l; reg_etts_h = ®s->etts_regs->tmr_etts1_h; break; case 1: valid = ETS2_VLD; reg_etts_l = ®s->etts_regs->tmr_etts2_l; reg_etts_h = ®s->etts_regs->tmr_etts2_h; break; default: return -EINVAL; } event.type = PTP_CLOCK_EXTTS; event.index = index; do { lo = ptp_qoriq->read(reg_etts_l); hi = ptp_qoriq->read(reg_etts_h); if (update_event) { event.timestamp = ((u64) hi) << 32; event.timestamp |= lo; ptp_clock_event(ptp_qoriq->clock, &event); } stat = ptp_qoriq->read(®s->ctrl_regs->tmr_stat); } while (ptp_qoriq->extts_fifo_support && (stat & valid)); return 0; }
/** * ixgbe_ptp_check_pps_event * @adapter - the private adapter structure * @eicr - the interrupt cause register value * * This function is called by the interrupt routine when checking for * interrupts. It will check and handle a pps event. */ void ixgbe_ptp_check_pps_event(struct ixgbe_adapter *adapter, u32 eicr) { struct ixgbe_hw *hw = &adapter->hw; struct ptp_clock_event event; event.type = PTP_CLOCK_PPS; /* Make sure ptp clock is valid, and PPS event enabled */ if (!adapter->ptp_clock || !(adapter->flags2 & IXGBE_FLAG2_PTP_PPS_ENABLED)) return; switch (hw->mac.type) { case ixgbe_mac_X540: if (eicr & IXGBE_EICR_TIMESYNC) ptp_clock_event(adapter->ptp_clock, &event); break; default: break; } }
/** * ixgbe_ptp_check_pps_event * @adapter: the private adapter structure * @eicr: the interrupt cause register value * * This function is called by the interrupt routine when checking for * interrupts. It will check and handle a pps event. */ void ixgbe_ptp_check_pps_event(struct ixgbe_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; struct ptp_clock_event event; event.type = PTP_CLOCK_PPS; /* this check is necessary in case the interrupt was enabled via some * alternative means (ex. debug_fs). Better to check here than * everywhere that calls this function. */ if (!adapter->ptp_clock) return; switch (hw->mac.type) { case ixgbe_mac_X540: ptp_clock_event(adapter->ptp_clock, &event); break; default: break; } }