/*
 * Copyright (C) 2014 Broadcom Corporation
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation version 2.
 *
 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
 * kind, whether express or implied; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include <linux/bitops.h>
#include <linux/clk.h>
#include <linux/gfp.h>
#include <linux/io.h>
#include <linux/input.h>
#include <linux/input/matrix_keypad.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/stddef.h>
#include <linux/types.h>

#define DEFAULT_CLK_HZ			31250
#define MAX_ROWS			8
#define MAX_COLS			8

/* Register/field definitions */
#define KPCR_OFFSET			0x00000080
#define KPCR_MODE			0x00000002
#define KPCR_MODE_SHIFT			1
#define KPCR_MODE_MASK			1
#define KPCR_ENABLE			0x00000001
#define KPCR_STATUSFILTERENABLE		0x00008000
#define KPCR_STATUSFILTERTYPE_SHIFT	12
#define KPCR_COLFILTERENABLE		0x00000800
#define KPCR_COLFILTERTYPE_SHIFT	8
#define KPCR_ROWWIDTH_SHIFT		20
#define KPCR_COLUMNWIDTH_SHIFT		16

#define KPIOR_OFFSET			0x00000084
#define KPIOR_ROWOCONTRL_SHIFT		24
#define KPIOR_ROWOCONTRL_MASK		0xFF000000
#define KPIOR_COLUMNOCONTRL_SHIFT	16
#define KPIOR_COLUMNOCONTRL_MASK	0x00FF0000
#define KPIOR_COLUMN_IO_DATA_SHIFT	0

#define KPEMR0_OFFSET			0x00000090
#define KPEMR1_OFFSET			0x00000094
#define KPEMR2_OFFSET			0x00000098
#define KPEMR3_OFFSET			0x0000009C
#define KPEMR_EDGETYPE_BOTH		3

#define KPSSR0_OFFSET			0x000000A0
#define KPSSR1_OFFSET			0x000000A4
#define KPSSRN_OFFSET(reg_n)		(KPSSR0_OFFSET + 4 * (reg_n))
#define KPIMR0_OFFSET			0x000000B0
#define KPIMR1_OFFSET			0x000000B4
#define KPICR0_OFFSET			0x000000B8
#define KPICR1_OFFSET			0x000000BC
#define KPICRN_OFFSET(reg_n)		(KPICR0_OFFSET + 4 * (reg_n))
#define KPISR0_OFFSET			0x000000C0
#define KPISR1_OFFSET			0x000000C4

#define KPCR_STATUSFILTERTYPE_MAX	7
#define KPCR_COLFILTERTYPE_MAX		7

/* Macros to determine the row/column from a bit that is set in SSR0/1. */
#define BIT_TO_ROW_SSRN(bit_nr, reg_n)	(((bit_nr) >> 3) + 4 * (reg_n))
#define BIT_TO_COL(bit_nr)		((bit_nr) % 8)

/* Structure representing various run-time entities */
struct bcm_kp {
	void __iomem *base;
	int irq;
	struct clk *clk;
	struct input_dev *input_dev;
	unsigned long last_state[2];
	unsigned int n_rows;
	unsigned int n_cols;
	u32 kpcr;
	u32 kpior;
	u32 kpemr;
	u32 imr0_val;
	u32 imr1_val;
};

/*
 * Returns the keycode from the input device keymap given the row and
 * column.
 */
static int bcm_kp_get_keycode(struct bcm_kp *kp, int row, int col)
{
	unsigned int row_shift = get_count_order(kp->n_cols);
	unsigned short *keymap = kp->input_dev->keycode;

	return keymap[MATRIX_SCAN_CODE(row, col, row_shift)];
}

static void bcm_kp_report_keys(struct bcm_kp *kp, int reg_num, int pull_mode)
{
	unsigned long state, change;
	int bit_nr;
	int key_press;
	int row, col;
	unsigned int keycode;

	/* Clear interrupts */
	writel(0xFFFFFFFF, kp->base + KPICRN_OFFSET(reg_num));

	state = readl(kp->base + KPSSRN_OFFSET(reg_num));
	change = kp->last_state[reg_num] ^ state;
	kp->last_state[reg_num] = state;

	for_each_set_bit(bit_nr, &change, BITS_PER_LONG) {
		key_press = state & BIT(bit_nr);
		/* The meaning of SSR register depends on pull mode. */
		key_press = pull_mode ? !key_press : key_press;
		row = BIT_TO_ROW_SSRN(bit_nr, reg_num);
		col = BIT_TO_COL(bit_nr);
		keycode = bcm_kp_get_keycode(kp, row, col);
		input_report_key(kp->input_dev, keycode, key_press);
	}
}

static irqreturn_t bcm_kp_isr_thread(int irq, void *dev_id)
{
	struct bcm_kp *kp = dev_id;
	int pull_mode = (kp->kpcr >> KPCR_MODE_SHIFT) & KPCR_MODE_MASK;
	int reg_num;

	for (reg_num = 0; reg_num <= 1; reg_num++)
		bcm_kp_report_keys(kp, reg_num, pull_mode);

	input_sync(kp->input_dev);

	return IRQ_HANDLED;
}

static int bcm_kp_start(struct bcm_kp *kp)
{
	int error;

	if (kp->clk) {
		error = clk_prepare_enable(kp->clk);
		if (error)
			return error;
	}

	writel(kp->kpior, kp->base + KPIOR_OFFSET);

	writel(kp->imr0_val, kp->base + KPIMR0_OFFSET);
	writel(kp->imr1_val, kp->base + KPIMR1_OFFSET);

	writel(kp->kpemr, kp->base + KPEMR0_OFFSET);
	writel(kp->kpemr, kp->base + KPEMR1_OFFSET);
	writel(kp->kpemr, kp->base + KPEMR2_OFFSET);
	writel(kp->kpemr, kp->base + KPEMR3_OFFSET);

	writel(0xFFFFFFFF, kp->base + KPICR0_OFFSET);
	writel(0xFFFFFFFF, kp->base + KPICR1_OFFSET);

	kp->last_state[0] = readl(kp->base + KPSSR0_OFFSET);
	kp->last_state[0] = readl(kp->base + KPSSR1_OFFSET);

	writel(kp->kpcr | KPCR_ENABLE, kp->base + KPCR_OFFSET);

	return 0;
}

static void bcm_kp_stop(const struct bcm_kp *kp)
{
	u32 val;

	val = readl(kp->base + KPCR_OFFSET);
	val &= ~KPCR_ENABLE;
	writel(0, kp->base + KPCR_OFFSET);
	writel(0, kp->base + KPIMR0_OFFSET);
	writel(0, kp->base + KPIMR1_OFFSET);
	writel(0xFFFFFFFF, kp->base + KPICR0_OFFSET);
	writel(0xFFFFFFFF, kp->base + KPICR1_OFFSET);

	if (kp->clk)
		clk_disable_unprepare(kp->clk);
}

static int bcm_kp_open(struct input_dev *dev)
{
	struct bcm_kp *kp = input_get_drvdata(dev);

	return bcm_kp_start(kp);
}

static void bcm_kp_close(struct input_dev *dev)
{
	struct bcm_kp *kp = input_get_drvdata(dev);

	bcm_kp_stop(kp);
}

static int bcm_kp_matrix_key_parse_dt(struct bcm_kp *kp)
{
	struct device *dev = kp->input_dev->dev.parent;
	struct device_node *np = dev->of_node;
	int error;
	unsigned int dt_val;
	unsigned int i;
	unsigned int num_rows, col_mask, rows_set;

	/* Initialize the KPCR Keypad Configuration Register */
	kp->kpcr = KPCR_STATUSFILTERENABLE | KPCR_COLFILTERENABLE;

	error = matrix_keypad_parse_properties(dev, &kp->n_rows, &kp->n_cols);
	if (error) {
		dev_err(dev, "failed to parse kp params\n");
		return error;
	}

	/* Set row width for the ASIC block. */
	kp->kpcr |= (kp->n_rows - 1) << KPCR_ROWWIDTH_SHIFT;

	/* Set column width for the ASIC block. */
	kp->kpcr |= (kp->n_cols - 1) << KPCR_COLUMNWIDTH_SHIFT;

	/* Configure the IMR registers */

	/*
	 * IMR registers contain interrupt enable bits for 8x8 matrix
	 * IMR0 register format: <row3> <row2> <row1> <row0>
	 * IMR1 register format: <row7> <row6> <row5> <row4>
	 */
	col_mask = (1 << (kp->n_cols)) - 1;
	num_rows = kp->n_rows;

	/* Set column bits in rows 0 to 3 in IMR0 */
	kp->imr0_val = col_mask;

	rows_set = 1;
	while (--num_rows && rows_set++ < 4)
		kp->imr0_val |= kp->imr0_val << MAX_COLS;

	/* Set column bits in rows 4 to 7 in IMR1 */
	kp->imr1_val = 0;
	if (num_rows) {
		kp->imr1_val = col_mask;
		while (--num_rows)
			kp->imr1_val |= kp->imr1_val << MAX_COLS;
	}

	/* Initialize the KPEMR Keypress Edge Mode Registers */
	/* Trigger on both edges */
	kp->kpemr = 0;
	for (i = 0; i <= 30; i += 2)
		kp->kpemr |= (KPEMR_EDGETYPE_BOTH << i);

	/*
	 * Obtain the Status filter debounce value and verify against the
	 * possible values specified in the DT binding.
	 */
	of_property_read_u32(np, "status-debounce-filter-period", &dt_val);

	if (dt_val > KPCR_STATUSFILTERTYPE_MAX) {
		dev_err(dev, "Invalid Status filter debounce value %d\n",
			dt_val);
		return -EINVAL;
	}

	kp->kpcr |= dt_val << KPCR_STATUSFILTERTYPE_SHIFT;

	/*
	 * Obtain the Column filter debounce value and verify against the
	 * possible values specified in the DT binding.
	 */
	of_property_read_u32(np, "col-debounce-filter-period", &dt_val);

	if (dt_val > KPCR_COLFILTERTYPE_MAX) {
		dev_err(dev, "Invalid Column filter debounce value %d\n",
			dt_val);
		return -EINVAL;
	}

	kp->kpcr |= dt_val << KPCR_COLFILTERTYPE_SHIFT;

	/*
	 * Determine between the row and column,
	 * which should be configured as output.
	 */
	if (of_property_read_bool(np, "row-output-enabled")) {
		/*
		* Set RowOContrl or ColumnOContrl in KPIOR
		* to the number of pins to drive as outputs
		*/
		kp->kpior = ((1 << kp->n_rows) - 1) <<
				KPIOR_ROWOCONTRL_SHIFT;
	} else {
		kp->kpior = ((1 << kp->n_cols) - 1) <<
				KPIOR_COLUMNOCONTRL_SHIFT;
	}

	/*
	 * Determine if the scan pull up needs to be enabled
	 */
	if (of_property_read_bool(np, "pull-up-enabled"))
		kp->kpcr |= KPCR_MODE;

	dev_dbg(dev, "n_rows=%d n_col=%d kpcr=%x kpior=%x kpemr=%x\n",
		kp->n_rows, kp->n_cols,
		kp->kpcr, kp->kpior, kp->kpemr);

	return 0;
}


static int bcm_kp_probe(struct platform_device *pdev)
{
	struct bcm_kp *kp;
	struct input_dev *input_dev;
	struct resource *res;
	int error;

	kp = devm_kzalloc(&pdev->dev, sizeof(*kp), GFP_KERNEL);
	if (!kp)
		return -ENOMEM;

	input_dev = devm_input_allocate_device(&pdev->dev);
	if (!input_dev) {
		dev_err(&pdev->dev, "failed to allocate the input device\n");
		return -ENOMEM;
	}

	__set_bit(EV_KEY, input_dev->evbit);

	/* Enable auto repeat feature of Linux input subsystem */
	if (of_property_read_bool(pdev->dev.of_node, "autorepeat"))
		__set_bit(EV_REP, input_dev->evbit);

	input_dev->name = pdev->name;
	input_dev->phys = "keypad/input0";
	input_dev->dev.parent = &pdev->dev;
	input_dev->open = bcm_kp_open;
	input_dev->close = bcm_kp_close;

	input_dev->id.bustype = BUS_HOST;
	input_dev->id.vendor = 0x0001;
	input_dev->id.product = 0x0001;
	input_dev->id.version = 0x0100;

	input_set_drvdata(input_dev, kp);

	kp->input_dev = input_dev;

	error = bcm_kp_matrix_key_parse_dt(kp);
	if (error)
		return error;

	error = matrix_keypad_build_keymap(NULL, NULL,
					   kp->n_rows, kp->n_cols,
					   NULL, input_dev);
	if (error) {
		dev_err(&pdev->dev, "failed to build keymap\n");
		return error;
	}

	/* Get the KEYPAD base address */
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		dev_err(&pdev->dev, "Missing keypad base address resource\n");
		return -ENODEV;
	}

	kp->base = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(kp->base))
		return PTR_ERR(kp->base);

	/* Enable clock */
	kp->clk = devm_clk_get(&pdev->dev, "peri_clk");
	if (IS_ERR(kp->clk)) {
		error = PTR_ERR(kp->clk);
		if (error != -ENOENT) {
			if (error != -EPROBE_DEFER)
				dev_err(&pdev->dev, "Failed to get clock\n");
			return error;
		}
		dev_dbg(&pdev->dev,
			"No clock specified. Assuming it's enabled\n");
		kp->clk = NULL;
	} else {
		unsigned int desired_rate;
		long actual_rate;

		error = of_property_read_u32(pdev->dev.of_node,
					     "clock-frequency", &desired_rate);
		if (error < 0)
			desired_rate = DEFAULT_CLK_HZ;

		actual_rate = clk_round_rate(kp->clk, desired_rate);
		if (actual_rate <= 0)
			return -EINVAL;

		error = clk_set_rate(kp->clk, actual_rate);
		if (error)
			return error;

		error = clk_prepare_enable(kp->clk);
		if (error)
			return error;
	}

	/* Put the kp into a known sane state */
	bcm_kp_stop(kp);

	kp->irq = platform_get_irq(pdev, 0);
	if (kp->irq < 0) {
		dev_err(&pdev->dev, "no IRQ specified\n");
		return -EINVAL;
	}

	error = devm_request_threaded_irq(&pdev->dev, kp->irq,
					  NULL, bcm_kp_isr_thread,
					  IRQF_ONESHOT, pdev->name, kp);
	if (error) {
		dev_err(&pdev->dev, "failed to request IRQ\n");
		return error;
	}

	error = input_register_device(input_dev);
	if (error) {
		dev_err(&pdev->dev, "failed to register input device\n");
		return error;
	}

	return 0;
}

static const struct of_device_id bcm_kp_of_match[] = {
	{ .compatible = "brcm,bcm-keypad" },
	{ },
};
MODULE_DEVICE_TABLE(of, bcm_kp_of_match);

static struct platform_driver bcm_kp_device_driver = {
	.probe		= bcm_kp_probe,
	.driver		= {
		.name	= "bcm-keypad",
		.of_match_table = of_match_ptr(bcm_kp_of_match),
	}
};

module_platform_driver(bcm_kp_device_driver);

MODULE_AUTHOR("Broadcom Corporation");
MODULE_DESCRIPTION("BCM Keypad Driver");
MODULE_LICENSE("GPL v2");
