static irqreturn_t lpc32xx_ts_interrupt(int irq, void *dev_id)
{
	u32 tmp, rv[4], xs[4], ys[4];
	int idx;
	struct lpc32xx_tsc *tsc = dev_id;
	struct input_dev *input = tsc->dev;

	tmp = tsc_readl(tsc, LPC32XX_TSC_STAT);

	if (tmp & LPC32XX_TSC_STAT_FIFO_OVRRN) {
		/* FIFO overflow - throw away samples */
		lpc32xx_fifo_clear(tsc);
		return IRQ_HANDLED;
	}

	/*
	 * Gather and normalize 4 samples. Pen-up events may have less
	 * than 4 samples, but its ok to pop 4 and let the last sample
	 * pen status check drop the samples.
	 */
	idx = 0;
	while (idx < 4 &&
	       !(tsc_readl(tsc, LPC32XX_TSC_STAT) &
			LPC32XX_TSC_STAT_FIFO_EMPTY)) {
		tmp = tsc_readl(tsc, LPC32XX_TSC_FIFO);
		xs[idx] = LPC32XX_TSC_ADCDAT_VALUE_MASK -
			LPC32XX_TSC_FIFO_NORMALIZE_X_VAL(tmp);
		ys[idx] = LPC32XX_TSC_ADCDAT_VALUE_MASK -
			LPC32XX_TSC_FIFO_NORMALIZE_Y_VAL(tmp);
		rv[idx] = tmp;
		idx++;
	}

	/* Data is only valid if pen is still down in last sample */
	if (!(rv[3] & LPC32XX_TSC_FIFO_TS_P_LEVEL) && idx == 4) {
		/* Use average of 2nd and 3rd sample for position */
		input_report_abs(input, ABS_X, (xs[1] + xs[2]) / 2);
		input_report_abs(input, ABS_Y, (ys[1] + ys[2]) / 2);
		input_report_key(input, BTN_TOUCH, 1);
	} else {
		input_report_key(input, BTN_TOUCH, 0);
	}

	input_sync(input);

	return IRQ_HANDLED;
}
static void lpc32xx_stop_tsc(struct lpc32xx_tsc *tsc)
{
	/* Disable auto mode */
	tsc_writel(tsc, LPC32XX_TSC_CON,
		   tsc_readl(tsc, LPC32XX_TSC_CON) &
			     ~LPC32XX_TSC_ADCCON_AUTO_EN);

	clk_disable(tsc->clk);
}
static irqreturn_t lpc32xx_ts_interrupt(int irq, void *dev_id)
{
    u32 tmp, rv[4], xs[4], ys[4];
    int idx;
    struct lpc32xx_tsc *tsc = dev_id;
    struct input_dev *input = tsc->dev;

    tmp = tsc_readl(tsc, LPC32XX_TSC_STAT);

    if (tmp & LPC32XX_TSC_STAT_FIFO_OVRRN) {

        lpc32xx_fifo_clear(tsc);
        return IRQ_HANDLED;
    }

    idx = 0;
    while (idx < 4 &&
            !(tsc_readl(tsc, LPC32XX_TSC_STAT) &
              LPC32XX_TSC_STAT_FIFO_EMPTY)) {
        tmp = tsc_readl(tsc, LPC32XX_TSC_FIFO);
        xs[idx] = LPC32XX_TSC_ADCDAT_VALUE_MASK -
                  LPC32XX_TSC_FIFO_NORMALIZE_X_VAL(tmp);
        ys[idx] = LPC32XX_TSC_ADCDAT_VALUE_MASK -
                  LPC32XX_TSC_FIFO_NORMALIZE_Y_VAL(tmp);
        rv[idx] = tmp;
        idx++;
    }


    if (!(rv[3] & LPC32XX_TSC_FIFO_TS_P_LEVEL) && idx == 4) {

        input_report_abs(input, ABS_X, (xs[1] + xs[2]) / 2);
        input_report_abs(input, ABS_Y, (ys[1] + ys[2]) / 2);
        input_report_key(input, BTN_TOUCH, 1);
    } else {
        input_report_key(input, BTN_TOUCH, 0);
    }

    input_sync(input);

    return IRQ_HANDLED;
}
static void lpc32xx_setup_tsc(struct lpc32xx_tsc *tsc)
{
	u32 tmp;

	clk_enable(tsc->clk);

	tmp = tsc_readl(tsc, LPC32XX_TSC_CON) & ~LPC32XX_TSC_ADCCON_POWER_UP;

	/* Set the TSC FIFO depth to 4 samples @ 10-bits per sample (max) */
	tmp = LPC32XX_TSC_ADCCON_IRQ_TO_FIFO_4 |
	      LPC32XX_TSC_ADCCON_X_SAMPLE_SIZE(10) |
	      LPC32XX_TSC_ADCCON_Y_SAMPLE_SIZE(10);
	tsc_writel(tsc, LPC32XX_TSC_CON, tmp);

	/* These values are all preset */
	tsc_writel(tsc, LPC32XX_TSC_SEL, LPC32XX_TSC_SEL_DEFVAL);
	tsc_writel(tsc, LPC32XX_TSC_MIN_X, LPC32XX_TSC_MIN_XY_VAL);
	tsc_writel(tsc, LPC32XX_TSC_MAX_X, LPC32XX_TSC_MAX_XY_VAL);
	tsc_writel(tsc, LPC32XX_TSC_MIN_Y, LPC32XX_TSC_MIN_XY_VAL);
	tsc_writel(tsc, LPC32XX_TSC_MAX_Y, LPC32XX_TSC_MAX_XY_VAL);

	/* Aux support is not used */
	tsc_writel(tsc, LPC32XX_TSC_AUX_UTR, 0);
	tsc_writel(tsc, LPC32XX_TSC_AUX_MIN, 0);
	tsc_writel(tsc, LPC32XX_TSC_AUX_MAX, 0);

	/*
	 * Set sample rate to about 240Hz per X/Y pair. A single measurement
	 * consists of 4 pairs which gives about a 60Hz sample rate based on
	 * a stable 32768Hz clock source. Values are in clocks.
	 * Rate is (32768 / (RTR + XCONV + RTR + YCONV + DXP + TTR + UTR) / 4
	 */
	tsc_writel(tsc, LPC32XX_TSC_RTR, 0x2);
	tsc_writel(tsc, LPC32XX_TSC_DTR, 0x2);
	tsc_writel(tsc, LPC32XX_TSC_TTR, 0x10);
	tsc_writel(tsc, LPC32XX_TSC_DXP, 0x4);
	tsc_writel(tsc, LPC32XX_TSC_UTR, 88);

	lpc32xx_fifo_clear(tsc);

	/* Enable automatic ts event capture */
	tsc_writel(tsc, LPC32XX_TSC_CON, tmp | LPC32XX_TSC_ADCCON_AUTO_EN);
}
static void lpc32xx_setup_tsc(struct lpc32xx_tsc *tsc)
{
    u32 tmp;

    clk_enable(tsc->clk);

    tmp = tsc_readl(tsc, LPC32XX_TSC_CON) & ~LPC32XX_TSC_ADCCON_POWER_UP;


    tmp = LPC32XX_TSC_ADCCON_IRQ_TO_FIFO_4 |
          LPC32XX_TSC_ADCCON_X_SAMPLE_SIZE(10) |
          LPC32XX_TSC_ADCCON_Y_SAMPLE_SIZE(10);
    tsc_writel(tsc, LPC32XX_TSC_CON, tmp);


    tsc_writel(tsc, LPC32XX_TSC_SEL, LPC32XX_TSC_SEL_DEFVAL);
    tsc_writel(tsc, LPC32XX_TSC_MIN_X, LPC32XX_TSC_MIN_XY_VAL);
    tsc_writel(tsc, LPC32XX_TSC_MAX_X, LPC32XX_TSC_MAX_XY_VAL);
    tsc_writel(tsc, LPC32XX_TSC_MIN_Y, LPC32XX_TSC_MIN_XY_VAL);
    tsc_writel(tsc, LPC32XX_TSC_MAX_Y, LPC32XX_TSC_MAX_XY_VAL);


    tsc_writel(tsc, LPC32XX_TSC_AUX_UTR, 0);
    tsc_writel(tsc, LPC32XX_TSC_AUX_MIN, 0);
    tsc_writel(tsc, LPC32XX_TSC_AUX_MAX, 0);

    tsc_writel(tsc, LPC32XX_TSC_RTR, 0x2);
    tsc_writel(tsc, LPC32XX_TSC_DTR, 0x2);
    tsc_writel(tsc, LPC32XX_TSC_TTR, 0x10);
    tsc_writel(tsc, LPC32XX_TSC_DXP, 0x4);
    tsc_writel(tsc, LPC32XX_TSC_UTR, 88);

    lpc32xx_fifo_clear(tsc);


    tsc_writel(tsc, LPC32XX_TSC_CON, tmp | LPC32XX_TSC_ADCCON_AUTO_EN);
}
static void lpc32xx_fifo_clear(struct lpc32xx_tsc *tsc)
{
	while (!(tsc_readl(tsc, LPC32XX_TSC_STAT) &
			LPC32XX_TSC_STAT_FIFO_EMPTY))
		tsc_readl(tsc, LPC32XX_TSC_FIFO);
}