示例#1
0
void ptp_clock_event(struct ptp_clock *ptp, struct ptp_clock_event *event)
{
	struct pps_event_time evt;

	switch (event->type) {

	case PTP_CLOCK_ALARM:
		break;

	case PTP_CLOCK_EXTTS:
		enqueue_external_timestamp(&ptp->tsevq, event);
		wake_up_interruptible(&ptp->tsev_wq);
		break;

	case PTP_CLOCK_PPS:
		pps_get_ts(&evt);
		pps_event(ptp->pps_source, &evt, PTP_PPS_EVENT, NULL);
		break;

	case PTP_CLOCK_PPSUSR:
		pps_event(ptp->pps_source, &event->pps_times,
			  PTP_PPS_EVENT, NULL);
		break;
	}
}
示例#2
0
static void            
xrpu_poll_pps(struct timecounter *tc)
{               
        struct softc *sc = tc->tc_priv;
	int i, j;
        unsigned count1, ppscount; 
                
	for (i = 0; i < XRPU_MAX_PPS; i++) {
		if (sc->assert[i]) {
			ppscount = *(sc->assert[i]) & tc->tc_counter_mask;
			j = 0;
			do {
				count1 = ppscount;
				ppscount =  *(sc->assert[i]) & tc->tc_counter_mask;
			} while (ppscount != count1 && ++j < 5);
			pps_event(&sc->pps[i], tc, ppscount, PPS_CAPTUREASSERT);
		}
		if (sc->clear[i]) {
			j = 0;
			ppscount = *(sc->clear[i]) & tc->tc_counter_mask;
			do {
				count1 = ppscount;
				ppscount =  *(sc->clear[i]) & tc->tc_counter_mask;
			} while (ppscount != count1 && ++j < 5);
			pps_event(&sc->pps[i], tc, ppscount, PPS_CAPTURECLEAR);
		}
	}
}
示例#3
0
static void
uart_pps_process(struct uart_softc *sc, int ser_sig)
{
	sbintime_t now;
	int is_assert, pps_sig;

	/* Which signal is configured as PPS?  Early out if none. */
	switch(sc->sc_pps_mode & UART_PPS_SIGNAL_MASK) {
	case UART_PPS_CTS:
		pps_sig = SER_CTS;
		break;
	case UART_PPS_DCD:
		pps_sig = SER_DCD;
		break;
	default:
		return;
	}

	/* Early out if there is no change in the signal configured as PPS. */
	if ((ser_sig & SER_DELTA(pps_sig)) == 0)
		return;

	/*
	 * In narrow-pulse mode we need to synthesize both capture and clear
	 * events from a single "delta occurred" indication from the uart
	 * hardware because the pulse width is too narrow to reliably detect
	 * both edges.  However, when the pulse width is close to our interrupt
	 * processing latency we might intermittantly catch both edges.  To
	 * guard against generating spurious events when that happens, we use a
	 * separate timer to ensure at least half a second elapses before we
	 * generate another event.
	 */
	pps_capture(&sc->sc_pps);
	if (sc->sc_pps_mode & UART_PPS_NARROW_PULSE) {
		now = getsbinuptime();
		if (now > sc->sc_pps_captime + 500 * SBT_1MS) {
			sc->sc_pps_captime = now;
			pps_event(&sc->sc_pps, PPS_CAPTUREASSERT);
			pps_event(&sc->sc_pps, PPS_CAPTURECLEAR);
		}
	} else  {
		is_assert = ser_sig & pps_sig;
		if (sc->sc_pps_mode & UART_PPS_INVERT_PULSE)
			is_assert = !is_assert;
		pps_event(&sc->sc_pps, is_assert ? PPS_CAPTUREASSERT :
		    PPS_CAPTURECLEAR);
	}
}
示例#4
0
文件: ucom.c 项目: ryoon/netbsd-xhci
void
ucom_status_change(struct ucom_softc *sc)
{
	struct tty *tp = sc->sc_tty;
	u_char old_msr;

	if (sc->sc_methods->ucom_get_status != NULL) {
		old_msr = sc->sc_msr;
		sc->sc_methods->ucom_get_status(sc->sc_parent, sc->sc_portno,
		    &sc->sc_lsr, &sc->sc_msr);
		if (ISSET((sc->sc_msr ^ old_msr), UMSR_DCD)) {
			mutex_spin_enter(&timecounter_lock);
			pps_capture(&sc->sc_pps_state);
			pps_event(&sc->sc_pps_state,
			    (sc->sc_msr & UMSR_DCD) ?
			    PPS_CAPTUREASSERT :
			    PPS_CAPTURECLEAR);
			mutex_spin_exit(&timecounter_lock);

			(*tp->t_linesw->l_modem)(tp,
			    ISSET(sc->sc_msr, UMSR_DCD));
		}
	} else {
		sc->sc_lsr = 0;
		/* Assume DCD is present, if we have no chance to check it. */
		sc->sc_msr = UMSR_DCD;
	}
}
示例#5
0
static void
elan_poll_pps(struct timecounter *tc)
{
	static int state;
	int i;
	uint16_t u, x, y, z;
	register_t saveintr;

	/*
	 * Grab the HW state as quickly and compactly as we can.  Disable
	 * interrupts to avoid measuring our interrupt service time on
	 * hw with quality clock sources.
	 */
	saveintr = intr_disable();
	x = *pps_ap[0];	/* state, must be first, see below */
	y = *pps_ap[1]; /* timer2 */
	z = *pps_ap[2]; /* timer1 */
	intr_restore(saveintr);

	/*
	 * Order is important here.  We need to check the state of the GPIO
	 * pin first, in order to avoid reading timer 1 right before the
	 * state change.  Technically pps_a may be zero in which case we
	 * harmlessly read the REVID register and the contents of pps_d is
	 * of no concern.
	 */

	i = x & pps_d;

	/* If state did not change or we don't have a GPIO pin, return */
	if (i == state || pps_a == 0)
		return;

	state = i;

	/* If the state is "low", flip the echo GPIO and return.  */
	if (!i) {
		if (echo_a)
			mmcrptr[(echo_a ^ 0xc) / 2] = echo_d;
		return;
	}

	/*
	 * Subtract timer1 from timer2 to compensate for time from the
	 * edge until we read the counters.
	 */
	u = y - z;

	pps_capture(&elan_pps);
	elan_pps.capcount = u;
	pps_event(&elan_pps, PPS_CAPTUREASSERT);

	/* Twiddle echo bit */
	if (echo_a)
		mmcrptr[echo_a / 2] = echo_d;
}
static void pps_ktimer_event(unsigned long ptr)
{
	struct pps_event_time ts;

	/*                                       */
	pps_get_ts(&ts);

	pps_event(pps, &ts, PPS_CAPTUREASSERT, NULL);

	mod_timer(&ktimer, jiffies + HZ);
}
示例#7
0
static irqreturn_t pps_gpio_irq_handler(int irq, void *data)
{
	const struct pps_gpio_device_data *info;
	struct pps_event_time ts;
	int rising_edge;

	/* Get the time stamp first */
	pps_get_ts(&ts);

	info = data;

	rising_edge = gpio_get_value(info->pdata->gpio_pin);
	if ((rising_edge && !info->pdata->assert_falling_edge) ||
			(!rising_edge && info->pdata->assert_falling_edge))
		pps_event(info->pps, &ts, PPS_CAPTUREASSERT, NULL);
	else if (info->pdata->capture_clear &&
			((rising_edge && info->pdata->assert_falling_edge) ||
			 (!rising_edge && !info->pdata->assert_falling_edge)))
		pps_event(info->pps, &ts, PPS_CAPTURECLEAR, NULL);

	return IRQ_HANDLED;
}
示例#8
0
static void pps_ktimer_event(unsigned long ptr)
{
	struct pps_event_time ts;

	/* First of all we get the time stamp... */
	pps_get_ts(&ts);

	dev_info(pps->dev, "PPS event at %lu\n", jiffies);

	pps_event(pps, &ts, PPS_CAPTUREASSERT, NULL);

	mod_timer(&ktimer, jiffies + HZ);
}
示例#9
0
static void pps_tty_dcd_change(struct tty_struct *tty, unsigned int status,
				struct pps_event_time *ts)
{
	struct pps_device *pps = (struct pps_device *)tty->disc_data;

	BUG_ON(pps == NULL);

	/* Now do the PPS event report */
	pps_event(pps, ts, status ? PPS_CAPTUREASSERT :
			PPS_CAPTURECLEAR, NULL);

	dev_dbg(pps->dev, "PPS %s at %lu\n",
			status ? "assert" : "clear", jiffies);
}
示例#10
0
static void
am335x_dmtimer_process_pps_event(void *arg, int pending)
{
	struct am335x_dmtimer_softc *sc;

	sc = arg;

	/* This is the task function that gets enqueued by poll_pps.  Once the
	 * time has been captured in the hw interrupt context, the remaining
	 * (more expensive) work to process the event is done later in a
	 * non-fast-interrupt context.
	 *
	 * We only support capture of the rising or falling edge, not both at
	 * once; tell the kernel to process whichever mode is currently active.
	 */
	pps_event(&sc->pps, sc->pps.ppsparam.mode & PPS_CAPTUREBOTH);
}
示例#11
0
文件: ktimer.c 项目: kzlin129/tt-gpl
static void pps_ktimer_event(unsigned long ptr)
{
    struct timespec __ts;
    struct pps_ktime ts;

    /* First of all we get the time stamp... */
    getnstimeofday(&__ts);

    pr_info("PPS event at %lu\n", jiffies);

    /* ... and translate it to PPS time data struct */
    ts.sec = __ts.tv_sec;
    ts.nsec = __ts.tv_nsec;

    pps_event(source, &ts, PPS_CAPTUREASSERT, NULL);

    mod_timer(&ktimer, jiffies + HZ);
}
示例#12
0
static void
ucom_cfg_status_change(struct usb_proc_msg *_task)
{
	struct ucom_cfg_task *task = 
	    (struct ucom_cfg_task *)_task;
	struct ucom_softc *sc = task->sc;
	struct tty *tp;
	uint8_t new_msr;
	uint8_t new_lsr;
	uint8_t msr_delta;
	uint8_t lsr_delta;

	tp = sc->sc_tty;

	UCOM_MTX_ASSERT(sc, MA_OWNED);

	if (!(sc->sc_flag & UCOM_FLAG_LL_READY)) {
		return;
	}
	if (sc->sc_callback->ucom_cfg_get_status == NULL) {
		return;
	}
	/* get status */

	new_msr = 0;
	new_lsr = 0;

	(sc->sc_callback->ucom_cfg_get_status) (sc, &new_lsr, &new_msr);

	if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) {
		/* TTY device closed */
		return;
	}
	msr_delta = (sc->sc_msr ^ new_msr);
	lsr_delta = (sc->sc_lsr ^ new_lsr);

	sc->sc_msr = new_msr;
	sc->sc_lsr = new_lsr;

	/*
	 * Time pulse counting support. Note that both CTS and DCD are
	 * active-low signals. The status bit is high to indicate that
	 * the signal on the line is low, which corresponds to a PPS
	 * clear event.
	 */
	switch(ucom_pps_mode) {
	case 1:
		if ((sc->sc_pps.ppsparam.mode & PPS_CAPTUREBOTH) &&
		    (msr_delta & SER_CTS)) {
			pps_capture(&sc->sc_pps);
			pps_event(&sc->sc_pps, (sc->sc_msr & SER_CTS) ?
			    PPS_CAPTURECLEAR : PPS_CAPTUREASSERT);
		}
		break;
	case 2:
		if ((sc->sc_pps.ppsparam.mode & PPS_CAPTUREBOTH) &&
		    (msr_delta & SER_DCD)) {
			pps_capture(&sc->sc_pps);
			pps_event(&sc->sc_pps, (sc->sc_msr & SER_DCD) ?
			    PPS_CAPTURECLEAR : PPS_CAPTUREASSERT);
		}
		break;
	default:
		break;
	}

	if (msr_delta & SER_DCD) {

		int onoff = (sc->sc_msr & SER_DCD) ? 1 : 0;

		DPRINTF("DCD changed to %d\n", onoff);

		ttydisc_modem(tp, onoff);
	}

	if ((lsr_delta & ULSR_BI) && (sc->sc_lsr & ULSR_BI)) {

		DPRINTF("BREAK detected\n");

		ttydisc_rint(tp, 0, TRE_BREAK);
		ttydisc_rint_done(tp);
	}

	if ((lsr_delta & ULSR_FE) && (sc->sc_lsr & ULSR_FE)) {

		DPRINTF("Frame error detected\n");

		ttydisc_rint(tp, 0, TRE_FRAMING);
		ttydisc_rint_done(tp);
	}

	if ((lsr_delta & ULSR_PE) && (sc->sc_lsr & ULSR_PE)) {

		DPRINTF("Parity error detected\n");

		ttydisc_rint(tp, 0, TRE_PARITY);
		ttydisc_rint_done(tp);
	}
}
示例#13
0
static void
ucom_cfg_status_change(struct usb_proc_msg *_task)
{
	struct ucom_cfg_task *task = 
	    (struct ucom_cfg_task *)_task;
	struct ucom_softc *sc = task->sc;
	struct tty *tp;
	int onoff;
	uint8_t new_msr;
	uint8_t new_lsr;
	uint8_t msr_delta;
	uint8_t lsr_delta;
	uint8_t pps_signal;

	tp = sc->sc_tty;

	UCOM_MTX_ASSERT(sc, MA_OWNED);

	if (!(sc->sc_flag & UCOM_FLAG_LL_READY)) {
		return;
	}
	if (sc->sc_callback->ucom_cfg_get_status == NULL) {
		return;
	}
	/* get status */

	new_msr = 0;
	new_lsr = 0;

	(sc->sc_callback->ucom_cfg_get_status) (sc, &new_lsr, &new_msr);

	if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) {
		/* TTY device closed */
		return;
	}
	msr_delta = (sc->sc_msr ^ new_msr);
	lsr_delta = (sc->sc_lsr ^ new_lsr);

	sc->sc_msr = new_msr;
	sc->sc_lsr = new_lsr;

	/*
	 * Time pulse counting support.
	 */
	switch(ucom_pps_mode & UART_PPS_SIGNAL_MASK) {
	case UART_PPS_CTS:
		pps_signal = SER_CTS;
		break;
	case UART_PPS_DCD:
		pps_signal = SER_DCD;
		break;
	default:
		pps_signal = 0;
		break;
	}

	if ((sc->sc_pps.ppsparam.mode & PPS_CAPTUREBOTH) &&
	    (msr_delta & pps_signal)) {
		pps_capture(&sc->sc_pps);
		onoff = (sc->sc_msr & pps_signal) ? 1 : 0;
		if (ucom_pps_mode & UART_PPS_INVERT_PULSE)
			onoff = !onoff;
		pps_event(&sc->sc_pps, onoff ? PPS_CAPTUREASSERT :
		    PPS_CAPTURECLEAR);
	}

	if (msr_delta & SER_DCD) {

		onoff = (sc->sc_msr & SER_DCD) ? 1 : 0;

		DPRINTF("DCD changed to %d\n", onoff);

		ttydisc_modem(tp, onoff);
	}

	if ((lsr_delta & ULSR_BI) && (sc->sc_lsr & ULSR_BI)) {

		DPRINTF("BREAK detected\n");

		ttydisc_rint(tp, 0, TRE_BREAK);
		ttydisc_rint_done(tp);
	}

	if ((lsr_delta & ULSR_FE) && (sc->sc_lsr & ULSR_FE)) {

		DPRINTF("Frame error detected\n");

		ttydisc_rint(tp, 0, TRE_FRAMING);
		ttydisc_rint_done(tp);
	}

	if ((lsr_delta & ULSR_PE) && (sc->sc_lsr & ULSR_PE)) {

		DPRINTF("Parity error detected\n");

		ttydisc_rint(tp, 0, TRE_PARITY);
		ttydisc_rint_done(tp);
	}
}