dm: tegra: Convert keyboard driver to driver model

Adjust the tegra keyboard driver to support driver model, using the new
uclass. Make this the default for all Tegra boards so that those that use
a keyboard will build correctly with this driver.

Signed-off-by: Simon Glass <sjg@chromium.org>
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index a5b7e0d..de2454e 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -12,6 +12,7 @@
 	select DM_I2C
 	select DM_SPI
 	select DM_GPIO
+	select DM_KEYBOARD
 
 choice
 	prompt "Tegra SoC select"
diff --git a/drivers/input/tegra-kbc.c b/drivers/input/tegra-kbc.c
index 818ed8c..a7137f1 100644
--- a/drivers/input/tegra-kbc.c
+++ b/drivers/input/tegra-kbc.c
@@ -6,8 +6,10 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <fdtdec.h>
 #include <input.h>
+#include <keyboard.h>
 #include <key_matrix.h>
 #include <stdio_dev.h>
 #include <tegra-kbc.h>
@@ -40,14 +42,13 @@
 };
 
 /* keyboard controller config and state */
-static struct keyb {
-	struct input_config input;	/* The input layer */
+struct tegra_kbd_priv {
+	struct input_config *input;	/* The input layer */
 	struct key_matrix matrix;	/* The key matrix layer */
 
 	struct kbc_tegra *kbc;		/* tegra keyboard controller */
 	unsigned char inited;		/* 1 if keyboard has been inited */
 	unsigned char first_scan;	/* 1 if this is our first key scan */
-	unsigned char created;		/* 1 if driver has been created */
 
 	/*
 	 * After init we must wait a short time before polling the keyboard.
@@ -58,17 +59,17 @@
 	unsigned int start_time_ms;	/* Time that we inited (in ms) */
 	unsigned int last_poll_ms;	/* Time we should last polled */
 	unsigned int next_repeat_ms;	/* Next time we repeat a key */
-} config;
+};
 
 /**
  * reads the keyboard fifo for current keypresses
  *
- * @param config	Keyboard config
+ * @param priv		Keyboard private data
  * @param fifo		Place to put fifo results
  * @param max_keycodes	Maximum number of key codes to put in the fifo
  * @return number of items put into fifo
  */
-static int tegra_kbc_find_keys(struct keyb *config, int *fifo,
+static int tegra_kbc_find_keys(struct tegra_kbd_priv *priv, int *fifo,
 			       int max_keycodes)
 {
 	struct key_matrix_key keys[KBC_MAX_KPENT], *key;
@@ -78,7 +79,7 @@
 	for (key = keys, i = 0; i < KBC_MAX_KPENT; i++, key++) {
 		/* Get next word */
 		if (!(i & 3))
-			kp_ent = readl(&config->kbc->kp_ent[i / 4]);
+			kp_ent = readl(&priv->kbc->kp_ent[i / 4]);
 
 		key->valid = (kp_ent & KBC_KPENT_VALID) != 0;
 		key->row = (kp_ent >> 3) & 0xf;
@@ -87,7 +88,7 @@
 		/* Shift to get next entry */
 		kp_ent >>= 8;
 	}
-	return key_matrix_decode(&config->matrix, keys, KBC_MAX_KPENT, fifo,
+	return key_matrix_decode(&priv->matrix, keys, KBC_MAX_KPENT, fifo,
 				 max_keycodes);
 }
 
@@ -106,10 +107,10 @@
  * Note: if fifo_cnt is 0, we will tell the input layer that no keys are
  * pressed.
  *
- * @param config	Keyboard config
+ * @param priv		Keyboard private data
  * @param fifo_cnt	Number of entries in the keyboard fifo
  */
-static void process_fifo(struct keyb *config, int fifo_cnt)
+static void process_fifo(struct tegra_kbd_priv *priv, int fifo_cnt)
 {
 	int fifo[KBC_MAX_KPENT];
 	int cnt = 0;
@@ -117,9 +118,9 @@
 	/* Always call input_send_keycodes() at least once */
 	do {
 		if (fifo_cnt)
-			cnt = tegra_kbc_find_keys(config, fifo, KBC_MAX_KPENT);
+			cnt = tegra_kbc_find_keys(priv, fifo, KBC_MAX_KPENT);
 
-		input_send_keycodes(&config->input, fifo, cnt);
+		input_send_keycodes(priv->input, fifo, cnt);
 	} while (--fifo_cnt > 0);
 }
 
@@ -127,24 +128,24 @@
  * Check the keyboard controller and emit ASCII characters for any keys that
  * are pressed.
  *
- * @param config	Keyboard config
+ * @param priv		Keyboard private data
  */
-static void check_for_keys(struct keyb *config)
+static void check_for_keys(struct tegra_kbd_priv *priv)
 {
 	int fifo_cnt;
 
-	if (!config->first_scan &&
-			get_timer(config->last_poll_ms) < KBC_REPEAT_RATE_MS)
+	if (!priv->first_scan &&
+	    get_timer(priv->last_poll_ms) < KBC_REPEAT_RATE_MS)
 		return;
-	config->last_poll_ms = get_timer(0);
-	config->first_scan = 0;
+	priv->last_poll_ms = get_timer(0);
+	priv->first_scan = 0;
 
 	/*
 	 * Once we get here we know the keyboard has been scanned. So if there
 	 * scan waiting for us, we know that nothing is held down.
 	 */
-	fifo_cnt = (readl(&config->kbc->interrupt) >> 4) & 0xf;
-	process_fifo(config, fifo_cnt);
+	fifo_cnt = (readl(&priv->kbc->interrupt) >> 4) & 0xf;
+	process_fifo(priv, fifo_cnt);
 }
 
 /**
@@ -153,22 +154,22 @@
  * Wkup mode to Continous polling mode and the repoll time. We can
  * deduct the time that's already elapsed.
  *
- * @param config	Keyboard config
+ * @param priv		Keyboard private data
  */
-static void kbd_wait_for_fifo_init(struct keyb *config)
+static void kbd_wait_for_fifo_init(struct tegra_kbd_priv *priv)
 {
-	if (!config->inited) {
+	if (!priv->inited) {
 		unsigned long elapsed_time;
 		long delay_ms;
 
-		elapsed_time = get_timer(config->start_time_ms);
-		delay_ms = config->init_dly_ms - elapsed_time;
+		elapsed_time = get_timer(priv->start_time_ms);
+		delay_ms = priv->init_dly_ms - elapsed_time;
 		if (delay_ms > 0) {
 			udelay(delay_ms * 1000);
 			debug("%s: delay %ldms\n", __func__, delay_ms);
 		}
 
-		config->inited = 1;
+		priv->inited = 1;
 	}
 }
 
@@ -183,38 +184,16 @@
  */
 static int tegra_kbc_check(struct input_config *input)
 {
-	kbd_wait_for_fifo_init(&config);
-	check_for_keys(&config);
-
-	return 1;
-}
+	struct tegra_kbd_priv *priv = dev_get_priv(input->dev);
 
-/**
- * Test if keys are available to be read
- *
- * @return 0 if no keys available, 1 if keys are available
- */
-static int kbd_tstc(struct stdio_dev *dev)
-{
-	/* Just get input to do this for us */
-	return input_tstc(&config.input);
-}
+	kbd_wait_for_fifo_init(priv);
+	check_for_keys(priv);
 
-/**
- * Read a key
- *
- * TODO: U-Boot wants 0 for no key, but Ctrl-@ is a valid key...
- *
- * @return ASCII key code, or 0 if no key, or -1 if error
- */
-static int kbd_getc(struct stdio_dev *dev)
-{
-	/* Just get input to do this for us */
-	return input_getc(&config.input);
+	return 1;
 }
 
 /* configures keyboard GPIO registers to use the rows and columns */
-static void config_kbc_gpio(struct kbc_tegra *kbc)
+static void config_kbc_gpio(struct tegra_kbd_priv *priv, struct kbc_tegra *kbc)
 {
 	int i;
 
@@ -233,10 +212,10 @@
 		row_cfg &= ~r_mask;
 		col_cfg &= ~c_mask;
 
-		if (i < config.matrix.num_rows) {
+		if (i < priv->matrix.num_rows) {
 			row_cfg |= ((i << 1) | 1) << r_shift;
 		} else {
-			col_cfg |= (((i - config.matrix.num_rows) << 1) | 1)
+			col_cfg |= (((i - priv->matrix.num_rows) << 1) | 1)
 					<< c_shift;
 		}
 
@@ -248,9 +227,9 @@
 /**
  * Start up the keyboard device
  */
-static void tegra_kbc_open(void)
+static void tegra_kbc_open(struct tegra_kbd_priv *priv)
 {
-	struct kbc_tegra *kbc = config.kbc;
+	struct kbc_tegra *kbc = priv->kbc;
 	unsigned int scan_period;
 	u32 val;
 
@@ -265,18 +244,34 @@
 	 * Before reading from the keyboard we must wait for the init_dly
 	 * plus the rpt_delay, plus 2ms for the row scan time.
 	 */
-	config.init_dly_ms = scan_period * 2 + 2;
+	priv->init_dly_ms = scan_period * 2 + 2;
 
 	val = KBC_DEBOUNCE_COUNT << KBC_DEBOUNCE_CNT_SHIFT;
 	val |= 1 << KBC_FIFO_TH_CNT_SHIFT;	/* fifo interrupt threshold */
 	val |= KBC_CONTROL_KBC_EN;		/* enable */
 	writel(val, &kbc->control);
 
-	config.start_time_ms = get_timer(0);
-	config.last_poll_ms = config.next_repeat_ms = get_timer(0);
-	config.first_scan = 1;
+	priv->start_time_ms = get_timer(0);
+	priv->last_poll_ms = get_timer(0);
+	priv->next_repeat_ms = priv->last_poll_ms;
+	priv->first_scan = 1;
 }
 
+static int tegra_kbd_start(struct udevice *dev)
+{
+	struct tegra_kbd_priv *priv = dev_get_priv(dev);
+
+	/* Set up pin mux and enable the clock */
+	funcmux_select(PERIPH_ID_KBC, FUNCMUX_DEFAULT);
+	clock_enable(PERIPH_ID_KBC);
+	config_kbc_gpio(priv, priv->kbc);
+
+	tegra_kbc_open(priv);
+	debug("%s: Tegra keyboard ready\n", __func__);
+
+	return 0;
+}
+
 /**
  * Set up the tegra keyboard. This is called by the stdio device handler
  *
@@ -289,89 +284,73 @@
  *
  * @return 0 if ok, -ve on error
  */
-static int init_tegra_keyboard(struct stdio_dev *dev)
+static int tegra_kbd_probe(struct udevice *dev)
 {
-	/* check if already created */
-	if (config.created)
-		return 0;
-
-#if CONFIG_IS_ENABLED(OF_CONTROL)
-	int	node;
+	struct tegra_kbd_priv *priv = dev_get_priv(dev);
+	struct keyboard_priv *uc_priv = dev_get_uclass_priv(dev);
+	struct stdio_dev *sdev = &uc_priv->sdev;
+	struct input_config *input = &uc_priv->input;
+	int node = dev->of_offset;
+	int ret;
 
-	node = fdtdec_next_compatible(gd->fdt_blob, 0,
-					  COMPAT_NVIDIA_TEGRA20_KBC);
-	if (node < 0) {
-		debug("%s: cannot locate keyboard node\n", __func__);
-		return node;
-	}
-	config.kbc = (struct kbc_tegra *)fdtdec_get_addr(gd->fdt_blob,
-		       node, "reg");
-	if ((fdt_addr_t)config.kbc == FDT_ADDR_T_NONE) {
+	priv->kbc = (struct kbc_tegra *)dev_get_addr(dev);
+	if ((fdt_addr_t)priv->kbc == FDT_ADDR_T_NONE) {
 		debug("%s: No keyboard register found\n", __func__);
-		return -1;
+		return -EINVAL;
 	}
-	input_set_delays(&config.input, KBC_REPEAT_DELAY_MS,
-			KBC_REPEAT_RATE_MS);
+	input_set_delays(input, KBC_REPEAT_DELAY_MS, KBC_REPEAT_RATE_MS);
 
 	/* Decode the keyboard matrix information (16 rows, 8 columns) */
-	if (key_matrix_init(&config.matrix, 16, 8, 1)) {
-		debug("%s: Could not init key matrix\n", __func__);
-		return -1;
+	ret = key_matrix_init(&priv->matrix, 16, 8, 1);
+	if (ret) {
+		debug("%s: Could not init key matrix: %d\n", __func__, ret);
+		return ret;
 	}
-	if (key_matrix_decode_fdt(&config.matrix, gd->fdt_blob, node)) {
-		debug("%s: Could not decode key matrix from fdt\n", __func__);
-		return -1;
+	ret = key_matrix_decode_fdt(&priv->matrix, gd->fdt_blob, node);
+	if (ret) {
+		debug("%s: Could not decode key matrix from fdt: %d\n",
+		      __func__, ret);
+		return ret;
 	}
-	if (config.matrix.fn_keycode) {
-		if (input_add_table(&config.input, KEY_FN, -1,
-				    config.matrix.fn_keycode,
-				    config.matrix.key_count))
-			return -1;
+	if (priv->matrix.fn_keycode) {
+		ret = input_add_table(input, KEY_FN, -1,
+				      priv->matrix.fn_keycode,
+				      priv->matrix.key_count);
+		if (ret) {
+			debug("%s: input_add_table() failed\n", __func__);
+			return ret;
+		}
 	}
-#else
-#error "Tegra keyboard driver requires FDT definitions"
-#endif
-
-	/* Set up pin mux and enable the clock */
-	funcmux_select(PERIPH_ID_KBC, FUNCMUX_DEFAULT);
-	clock_enable(PERIPH_ID_KBC);
-	config_kbc_gpio(config.kbc);
 
-	tegra_kbc_open();
-	config.created = 1;
-	debug("%s: Tegra keyboard ready\n", __func__);
+	/* Register the device. init_tegra_keyboard() will be called soon */
+	priv->input = input;
+	input->dev = dev;
+	input->read_keys = tegra_kbc_check;
+	input_add_tables(input);
+	strcpy(sdev->name, "tegra-kbc");
+	ret = input_stdio_register(sdev);
+	if (ret) {
+		debug("%s: input_stdio_register() failed\n", __func__);
+		return ret;
+	}
 
 	return 0;
 }
 
-int drv_keyboard_init(void)
-{
-	struct stdio_dev dev;
-	char *stdinname = getenv("stdin");
-	int error;
-
-	if (input_init(&config.input, 0)) {
-		debug("%s: Cannot set up input\n", __func__);
-		return -1;
-	}
-	config.input.read_keys = tegra_kbc_check;
-	input_add_tables(input);
+static const struct keyboard_ops tegra_kbd_ops = {
+	.start	= tegra_kbd_start,
+};
 
-	memset(&dev, '\0', sizeof(dev));
-	strcpy(dev.name, "tegra-kbc");
-	dev.flags = DEV_FLAGS_INPUT;
-	dev.getc = kbd_getc;
-	dev.tstc = kbd_tstc;
-	dev.start = init_tegra_keyboard;
+static const struct udevice_id tegra_kbd_ids[] = {
+	{ .compatible = "nvidia,tegra20-kbc" },
+	{ }
+};
 
-	/* Register the device. init_tegra_keyboard() will be called soon */
-	error = input_stdio_register(&dev);
-	if (error)
-		return error;
-#ifdef CONFIG_CONSOLE_MUX
-	error = iomux_doenv(stdin, stdinname);
-	if (error)
-		return error;
-#endif
-	return 0;
-}
+U_BOOT_DRIVER(tegra_kbd) = {
+	.name	= "tegra_kbd",
+	.id	= UCLASS_KEYBOARD,
+	.of_match = tegra_kbd_ids,
+	.probe = tegra_kbd_probe,
+	.ops	= &tegra_kbd_ops,
+	.priv_auto_alloc_size = sizeof(struct tegra_kbd_priv),
+};
diff --git a/include/fdtdec.h b/include/fdtdec.h
index 3a6ff1f..79826d7 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -118,7 +118,6 @@
 	COMPAT_UNKNOWN,
 	COMPAT_NVIDIA_TEGRA20_EMC,	/* Tegra20 memory controller */
 	COMPAT_NVIDIA_TEGRA20_EMC_TABLE, /* Tegra20 memory timing table */
-	COMPAT_NVIDIA_TEGRA20_KBC,	/* Tegra20 Keyboard */
 	COMPAT_NVIDIA_TEGRA20_NAND,	/* Tegra2 NAND controller */
 	COMPAT_NVIDIA_TEGRA20_PWM,	/* Tegra 2 PWM controller */
 	COMPAT_NVIDIA_TEGRA124_DC,	/* Tegra 124 Display controller */
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index f1849bc..e0e6bb4 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -24,7 +24,6 @@
 	COMPAT(UNKNOWN, "<none>"),
 	COMPAT(NVIDIA_TEGRA20_EMC, "nvidia,tegra20-emc"),
 	COMPAT(NVIDIA_TEGRA20_EMC_TABLE, "nvidia,tegra20-emc-table"),
-	COMPAT(NVIDIA_TEGRA20_KBC, "nvidia,tegra20-kbc"),
 	COMPAT(NVIDIA_TEGRA20_NAND, "nvidia,tegra20-nand"),
 	COMPAT(NVIDIA_TEGRA20_PWM, "nvidia,tegra20-pwm"),
 	COMPAT(NVIDIA_TEGRA124_DC, "nvidia,tegra124-dc"),