/*
 * Copyright (C) 2009-2014 Freescale Semiconductor, Inc. All Rights Reserved.
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

/*!
 * @file mxc_keyb.c
 *
 * @brief Driver for the Freescale Semiconductor MXC keypad port.
 *
 * The keypad driver is designed as a standard Input driver which interacts
 * with low level keypad port hardware. Upon opening, the Keypad driver
 * initializes the keypad port. When the keypad interrupt happens the driver
 * calles keypad polling timer and scans the keypad matrix for key
 * press/release. If all key press/release happened it comes out of timer and
 * waits for key press interrupt. The scancode for key press and release events
 * are passed to Input subsytem.
 *
 * @ingroup keypad
 */

#include <asm/io.h>
#include <common.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <asm/imx-common/mxc_key_defs.h>
#include <malloc.h>

/*
 *  * Module header file
 *   */
#include <mxc_keyb.h>

/*!
 * Comment KPP_DEBUG to disable debug messages
 */

#undef	KPP_DEBUG

#ifdef	KPP_DEBUG
#define	KPP_PRINTF(fmt, args...)	printf(fmt , ##args)

static void mxc_kpp_dump_regs()
{
	unsigned short t1, t2, t3;

	t1 = __raw_readw(KPCR);
	t2 = __raw_readw(KPSR);
	t3 = __raw_readw(KDDR);
	/*
	KPP_PRINTF("KPCR=0x%04x, KPSR=0x%04x, KDDR=0x%04x\n",
		t1, t2, t3);
		*/
}
#else
#define KPP_PRINTF(fmt, args...)
#endif

static u16 mxc_key_mapping[] = CONFIG_MXC_KEYMAPPING;

/*!
 * This structure holds the keypad private data structure.
 */
static struct keypad_priv kpp_dev;

/*! Indicates if the key pad device is enabled. */

/*! This static variable indicates whether a key event is pressed/released. */
static unsigned short KPress;

/*! cur_rcmap and prev_rcmap array is used to detect key press and release. */
static unsigned short *cur_rcmap;	/* max 64 bits (8x8 matrix) */
static unsigned short *prev_rcmap;

/*!
 * Debounce polling period(10ms) in system ticks.
 */
/*static unsigned short KScanRate = (10 * CONFIG_SYS_HZ) / 1000;*/

/*!
 * These arrays are used to store press and release scancodes.
 */
static short **press_scancode;
static short **release_scancode;

static const unsigned short *mxckpd_keycodes;
static unsigned short mxckpd_keycodes_size;

/*!
 * This function is called to scan the keypad matrix to find out the key press
 * and key release events. Make scancode and break scancode are generated for
 * key press and key release events.
 *
 * The following scanning sequence are done for
 * keypad row and column scanning,
 * -# Write 1's to KPDR[15:8], setting column data to 1's
 * -# Configure columns as totem pole outputs(for quick discharging of keypad
 * capacitance)
 * -# Configure columns as open-drain
 * -# Write a single column to 0, others to 1.
 * -# Sample row inputs and save data. Multiple key presses can be detected on
 * a single column.
 * -# Repeat steps the above steps for remaining columns.
 * -# Return all columns to 0 in preparation for standby mode.
 * -# Clear KPKD and KPKR status bit(s) by writing to a 1,
 *    Set the KPKR synchronizer chain by writing "1" to KRSS register,
 *    Clear the KPKD synchronizer chain by writing "1" to KDSC register
 *
 * @result    Number of key pressed/released.
 */
static int mxc_kpp_scan_matrix(void)
{
	unsigned short reg_val;
	int col, row;
	short scancode = 0;
	int keycnt = 0;		/* How many keys are still pressed */

	/*
	 * wmb() linux kernel function which guarantees orderings in write
	 * operations
	 */
	/* wmb(); */

	/* save cur keypad matrix to prev */
	memcpy(prev_rcmap, cur_rcmap, kpp_dev.kpp_rows * sizeof(prev_rcmap[0]));
	memset(cur_rcmap, 0, kpp_dev.kpp_rows * sizeof(cur_rcmap[0]));

	/*1. Disable both (depress and release) keypad interrupts.*/

	/* KDIE has been disabled in mxc_kpp_getc before calling scan matrix.
	  * KRIE is always disabled in this driver.
	  */

	for (col = 0; col < kpp_dev.kpp_cols; col++) {	/* Col */
		/* 2. Write 1.s to KPDR[15:8] setting column data to 1.s */
		reg_val = __raw_readw(KPDR);
		reg_val |= 0xff00;
		__raw_writew(reg_val, KPDR);

		/*
		 * 3. Configure columns as totem pole outputs(for quick
		 * discharging of keypad capacitance)
		 */
		reg_val = __raw_readw(KPCR);
		reg_val &= 0x00ff;
		__raw_writew(reg_val, KPCR);

		udelay(2);

#ifdef KPP_DEBUG
		mxc_kpp_dump_regs();
#endif

		/*
		 * 4. Configure columns as open-drain
		 */
		reg_val = __raw_readw(KPCR);
		reg_val |= ((1 << kpp_dev.kpp_cols) - 1) << 8;
		__raw_writew(reg_val, KPCR);

		/*
		 * 5. Write a single column to 0, others to 1.
		 * 6. Sample row inputs and save data. Multiple key presses
		 * can be detected on a single column.
		 * 7. Repeat steps 2 - 6 for remaining columns.
		 */

		/* Col bit starts at 8th bit in KPDR */
		reg_val = __raw_readw(KPDR);
		reg_val &= ~(1 << (8 + col));
		__raw_writew(reg_val, KPDR);

		/* Delay added to avoid propagating the 0 from column to row
		 * when scanning. */

		udelay(5);

#ifdef KPP_DEBUG
		mxc_kpp_dump_regs();
#endif

		/* Read row input */
		reg_val = __raw_readw(KPDR);
		for (row = 0; row < kpp_dev.kpp_rows; row++) {	/* sample row */
			if (TEST_BIT(reg_val, row) == 0) {
				cur_rcmap[row] = BITSET(cur_rcmap[row], col);
				keycnt++;
			}
		}
	}

	/*
	 * 8. Return all columns to 0 in preparation for standby mode.
	 * 9. Clear KPKD and KPKR status bit(s) by writing to a .1.,
	 * set the KPKR synchronizer chain by writing "1" to KRSS register,
	 * clear the KPKD synchronizer chain by writing "1" to KDSC register
	 */
	reg_val = 0x00;
	__raw_writew(reg_val, KPDR);
	reg_val = __raw_readw(KPDR);
	reg_val = __raw_readw(KPSR);
	reg_val |= KBD_STAT_KPKD | KBD_STAT_KPKR | KBD_STAT_KRSS |
	    KBD_STAT_KDSC;
	__raw_writew(reg_val, KPSR);

#ifdef KPP_DEBUG
	mxc_kpp_dump_regs();
#endif

	/* Check key press status change */

	/*
	 * prev_rcmap array will contain the previous status of the keypad
	 * matrix.  cur_rcmap array will contains the present status of the
	 * keypad matrix. If a bit is set in the array, that (row, col) bit is
	 * pressed, else it is not pressed.
	 *
	 * XORing these two variables will give us the change in bit for
	 * particular row and column.  If a bit is set in XOR output, then that
	 * (row, col) has a change of status from the previous state.  From
	 * the diff variable the key press and key release of row and column
	 * are found out.
	 *
	 * If the key press is determined then scancode for key pressed
	 * can be generated using the following statement:
	 *    scancode = ((row * 8) + col);
	 *
	 * If the key release is determined then scancode for key release
	 * can be generated using the following statement:
	 *    scancode = ((row * 8) + col) + MXC_KEYRELEASE;
	 */
	for (row = 0; row < kpp_dev.kpp_rows; row++) {
		unsigned char diff;

		/*
		 * Calculate the change in the keypad row status
		 */
		diff = prev_rcmap[row] ^ cur_rcmap[row];

		for (col = 0; col < kpp_dev.kpp_cols; col++) {
			if ((diff >> col) & 0x1) {
				/* There is a status change on col */
				if ((prev_rcmap[row] & BITSET(0, col)) == 0) {
					/*
					 * Previous state is 0, so now
					 * a key is pressed
					 */
					scancode =
					    ((row * kpp_dev.kpp_cols) +
					     col);
					KPress = 1;
					kpp_dev.iKeyState = KStateUp;

					KPP_PRINTF("Press   (%d, %d) scan=%d "
						 "Kpress=%d\n",
						 row, col, scancode, KPress);
					press_scancode[row][col] =
					    (short)scancode;
				} else {
					/*
					 * Previous state is not 0, so
					 * now a key is released
					 */
					scancode =
					    (row * kpp_dev.kpp_cols) +
					    col + MXC_KEYRELEASE;
					KPress = 0;
					kpp_dev.iKeyState = KStateDown;

					KPP_PRINTF
					    ("Release (%d, %d) scan=%d Kpress=%d\n",
					     row, col, scancode, KPress);
					release_scancode[row][col] =
					    (short)scancode;
					keycnt++;
				}
			}
		}
	}

	return keycnt;
}

static int mxc_kpp_reset(void)
{
	unsigned short reg_val;
	int i;

	/*
	* Stop scanning and wait for interrupt.
	* Enable press interrupt and disable release interrupt.
	*/
	__raw_writew(0x00FF, KPDR);
	reg_val = __raw_readw(KPSR);
	reg_val |= (KBD_STAT_KPKR | KBD_STAT_KPKD);
	reg_val |= KBD_STAT_KRSS | KBD_STAT_KDSC;
	__raw_writew(reg_val, KPSR);
	reg_val |= KBD_STAT_KDIE;
	reg_val &= ~KBD_STAT_KRIE;
	__raw_writew(reg_val, KPSR);

#ifdef KPP_DEBUG
	mxc_kpp_dump_regs();
#endif

	/*
	* No more keys pressed... make sure unwanted key codes are
	* not given upstairs
	*/
	for (i = 0; i < kpp_dev.kpp_rows; i++) {
		memset(press_scancode[i], -1,
			sizeof(press_scancode[0][0]) * kpp_dev.kpp_cols);
		memset(release_scancode[i], -1,
			sizeof(release_scancode[0][0]) *
			kpp_dev.kpp_cols);
	}

	return 0;
}

int mxc_kpp_getc(struct kpp_key_info **key_info)
{
	int col, row;
	int key_cnt;
	unsigned short reg_val;
	short scancode = 0;
	int index = 0;
	struct kpp_key_info *keyi;

	reg_val = __raw_readw(KPSR);

	if (reg_val & KBD_STAT_KPKD) {
		/*
		* Disable key press(KDIE status bit) interrupt
		*/
		reg_val &= ~KBD_STAT_KDIE;
		__raw_writew(reg_val, KPSR);

#ifdef KPP_DEBUG
		mxc_kpp_dump_regs();
#endif

		key_cnt = mxc_kpp_scan_matrix();
	} else {
		return 0;
	}

	if (key_cnt <= 0)
		return 0;

	*key_info = keyi =
		(struct kpp_key_info *)malloc
		(sizeof(struct kpp_key_info) * key_cnt);

	/*
	* This switch case statement is the
	* implementation of state machine of debounc
	* logic for key press/release.
	* The explaination of state machine is as
	* follows:
	*
	* KStateUp State:
	* This is in intial state of the state machine
	* this state it checks for any key presses.
	* The key press can be checked using the
	* variable KPress. If KPress is set, then key
	* press is identified and switches the to
	* KStateFirstDown state for key press to
	* debounce.
	*
	* KStateFirstDown:
	* After debounce delay(10ms), if the KPress is
	* still set then pass scancode generated to
	* input device and change the state to
	* KStateDown, else key press debounce is not
	* satisfied so change the state to KStateUp.
	*
	* KStateDown:
	* In this state it checks for any key release.
	* If KPress variable is cleared, then key
	* release is indicated and so, switch the
	* state to KStateFirstUp else to state
	* KStateDown.
	*
	* KStateFirstUp:
	* After debounce delay(10ms), if the KPress is
	* still reset then pass the key release
	* scancode to input device and change
	* the state to KStateUp else key release is
	* not satisfied so change the state to
	* KStateDown.
	*/

	for (row = 0; row < kpp_dev.kpp_rows; row++) {
		for (col = 0; col < kpp_dev.kpp_cols; col++) {
			if ((press_scancode[row][col] != -1)) {
				/* Still Down, so add scancode */
				scancode =
				    press_scancode[row][col];

				keyi[index].val = mxckpd_keycodes[scancode];
				keyi[index++].evt = KDepress;

				KPP_PRINTF("KStateFirstDown: scan=%d val=%d\n",
					scancode, mxckpd_keycodes[scancode]);
				if (index >= key_cnt)
					goto key_detect;

				kpp_dev.iKeyState = KStateDown;
				press_scancode[row][col] = -1;
			}
		}
	}

	for (row = 0; row < kpp_dev.kpp_rows; row++) {
		for (col = 0; col < kpp_dev.kpp_cols; col++) {
			if ((release_scancode[row][col] != -1)) {
				scancode =
				    release_scancode[row][col];
				scancode =
					scancode - MXC_KEYRELEASE;

				keyi[index].val = mxckpd_keycodes[scancode];
				keyi[index++].evt = KRelease;

				KPP_PRINTF("KStateFirstUp: scan=%d val=%d\n",
					scancode, mxckpd_keycodes[scancode]);
				if (index >= key_cnt)
					goto key_detect;

				kpp_dev.iKeyState = KStateUp;
				release_scancode[row][col] = -1;
			}
		}
	}

key_detect:
	mxc_kpp_reset();
	return key_cnt;
}

/*!
 * This function is called to free the allocated memory for local arrays
 */
static void mxc_kpp_free_allocated(void)
{
	int i;

	if (press_scancode) {
		for (i = 0; i < kpp_dev.kpp_rows; i++) {
			if (press_scancode[i])
				free(press_scancode[i]);
		}
		free(press_scancode);
	}

	if (release_scancode) {
		for (i = 0; i < kpp_dev.kpp_rows; i++) {
			if (release_scancode[i])
				free(release_scancode[i]);
		}
		free(release_scancode);
	}

	if (cur_rcmap)
		free(cur_rcmap);

	if (prev_rcmap)
		free(prev_rcmap);
}

/*!
 * This function is called during the driver binding process.
 *
 * @param   pdev  the device structure used to store device specific
 *                information that is used by the suspend, resume and remove
 *                functions.
 *
 * @return  The function returns 0 on successful registration. Otherwise returns
 *          specific error code.
 */
int mxc_kpp_init(void)
{
	int i;
	int retval;
	unsigned int reg_val;

	kpp_dev.kpp_cols = CONFIG_MXC_KPD_COLMAX;
	kpp_dev.kpp_rows = CONFIG_MXC_KPD_ROWMAX;

	/* clock and IOMUX configuration for keypad */
	setup_mxc_kpd();

	/* Configure keypad */

	/* Enable number of rows in keypad (KPCR[7:0])
	 * Configure keypad columns as open-drain (KPCR[15:8])
	 *
	 * Configure the rows/cols in KPP
	 * LSB nibble in KPP is for 8 rows
	 * MSB nibble in KPP is for 8 cols
	 */
	reg_val = __raw_readw(KPCR);
	reg_val |= (1  << kpp_dev.kpp_rows) - 1;	/* LSB */
	reg_val |= ((1 << kpp_dev.kpp_cols) - 1) << 8;	/* MSB */
	__raw_writew(reg_val, KPCR);

	/* Write 0's to KPDR[15:8] */
	reg_val = __raw_readw(KPDR);
	reg_val &= 0x00ff;
	__raw_writew(reg_val, KPDR);

	/* Configure columns as output,
	 * rows as input (KDDR[15:0]) */
	reg_val = __raw_readw(KDDR);
	reg_val |= 0xff00;
	reg_val &= 0xff00;
	__raw_writew(reg_val, KDDR);

	/* Clear the KPKD Status Flag
	 * and Synchronizer chain. */
	reg_val = __raw_readw(KPSR);
	reg_val &= ~(KBD_STAT_KPKR | KBD_STAT_KPKD);
	reg_val |= KBD_STAT_KPKD;
	reg_val |= KBD_STAT_KRSS | KBD_STAT_KDSC;
	__raw_writew(reg_val, KPSR);
	/* Set the KDIE control bit, and clear the KRIE
	 * control bit (avoid false release events). */
	reg_val |= KBD_STAT_KDIE;
	reg_val &= ~KBD_STAT_KRIE;
	__raw_writew(reg_val, KPSR);

#ifdef KPP_DEBUG
	mxc_kpp_dump_regs();
#endif

	mxckpd_keycodes = mxc_key_mapping;
	mxckpd_keycodes_size = kpp_dev.kpp_cols * kpp_dev.kpp_rows;

	if ((mxckpd_keycodes == (void *)0)
	    || (mxckpd_keycodes_size == 0)) {
		retval = -ENODEV;
		goto err;
	}

	/* allocate required memory */
	press_scancode   = (short **)malloc(kpp_dev.kpp_rows * sizeof(press_scancode[0]));
	release_scancode = (short **)malloc(kpp_dev.kpp_rows * sizeof(release_scancode[0]));

	if (!press_scancode || !release_scancode) {
		retval = -ENOMEM;
		goto err;
	}

	for (i = 0; i < kpp_dev.kpp_rows; i++) {
		press_scancode[i] = (short *)malloc(kpp_dev.kpp_cols
					    * sizeof(press_scancode[0][0]));
		release_scancode[i] =
		    (short *)malloc(kpp_dev.kpp_cols * sizeof(release_scancode[0][0]));

		if (!press_scancode[i] || !release_scancode[i]) {
			retval = -ENOMEM;
			goto err;
		}
	}

	cur_rcmap =
	    (unsigned short *)malloc(kpp_dev.kpp_rows * sizeof(cur_rcmap[0]));
	prev_rcmap =
	    (unsigned short *)malloc(kpp_dev.kpp_rows * sizeof(prev_rcmap[0]));

	if (!cur_rcmap || !prev_rcmap) {
		retval = -ENOMEM;
		goto err;
	}

	for (i = 0; i < kpp_dev.kpp_rows; i++) {
		memset(press_scancode[i], -1,
		       sizeof(press_scancode[0][0]) * kpp_dev.kpp_cols);
		memset(release_scancode[i], -1,
		       sizeof(release_scancode[0][0]) * kpp_dev.kpp_cols);
	}
	memset(cur_rcmap, 0, kpp_dev.kpp_rows * sizeof(cur_rcmap[0]));
	memset(prev_rcmap, 0, kpp_dev.kpp_rows * sizeof(prev_rcmap[0]));

	return 0;

err:
	mxc_kpp_free_allocated();
	return retval;
}
