diff --git a/Documentation/devicetree/bindings/input/gpio-matrix-keypad.txt b/Documentation/devicetree/bindings/input/gpio-matrix-keypad.txt
index 75e9e28..1562681 100644
--- a/Documentation/devicetree/bindings/input/gpio-matrix-keypad.txt
+++ b/Documentation/devicetree/bindings/input/gpio-matrix-keypad.txt
@@ -93,7 +93,10 @@ Optional Properties:
 			a column line and reading back its row status,
 			such that pin levels can settle after
 			propagating through the matrix and its
-			associated hardware components
+			associated hardware components, can be specified
+			with either one value giving the exact delay, or
+			with two values giving a delay range (allowing
+			for reduced timer management overhead)
 - col-switch-delay-ms:	columns switch interval in milliseconds instead
 			of using interrupts to detect key press changes,
 			enables polling mode when specified
@@ -146,7 +149,7 @@ Examples:
 	matrix_keypad {
 		compatible = "gpio-matrix-keypad";
 		debounce-delay-ms = <5>;
-		col-scan-delay-us = <1>;
+		col-scan-delay-us = <2 10>;
 		col-switch-delay-ms = <20>;
 
 		col-gpios-binary;
diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c
index c015f0d..275b157 100644
--- a/drivers/input/keyboard/matrix_keypad.c
+++ b/drivers/input/keyboard/matrix_keypad.c
@@ -100,6 +100,7 @@ static void activate_col(const struct matrix_keypad_platform_data *pdata,
 			 int col, bool on)
 {
 	int bit, lvl;
+	u32 delay_min, delay_max;
 
 	if (!pdata->col_gpios_binary_encoded) {
 		/* one-out-of-N approach, just setup the one pin */
@@ -115,8 +116,19 @@ static void activate_col(const struct matrix_keypad_platform_data *pdata,
 		/* EMPTY */
 	}
 
-	if (on && pdata->col_scan_delay_us)
-		udelay(pdata->col_scan_delay_us);
+	if (on && pdata->col_scan_delay_us) {
+		/*
+		 * the platform data is 'const' aka 'read-only' here, so
+		 * we may not modify it, yet might not have had a chance
+		 * to normalize its data before (we did for the DT case,
+		 * but did not for non-DT cases), which is why we have
+		 * to use local variables here to enforce sane input
+		 * data for the usleep range spec
+		 */
+		delay_min = pdata->col_scan_delay_us;
+		delay_max = max(delay_min, pdata->col_scan_delay_us_max);
+		usleep_range(delay_min, delay_max);
+	}
 }
 
 /*
@@ -609,6 +621,7 @@ matrix_keypad_parse_dt(struct device *dev)
 	unsigned int *gpios;
 	int i;
 	int err;
+	u32 us[2];
 
 	if (!np) {
 		dev_err(dev, "device lacks DT data for the keypad config\n");
@@ -655,8 +668,15 @@ matrix_keypad_parse_dt(struct device *dev)
 
 	/* get delay and interval timing specs */
 	of_property_read_u32(np, "debounce-delay-ms", &pdata->debounce_ms);
-	of_property_read_u32(np, "col-scan-delay-us",
-			     &pdata->col_scan_delay_us);
+	us[0] = us[1] = 0;
+	err = of_property_read_u32_array(np, "col-scan-delay-us", &us[0], 2);
+	if (err == -EOVERFLOW) {
+		err = of_property_read_u32(np, "col-scan-delay-us", &us[0]);
+		us[1] = us[0];
+	}
+	us[1] = max(us[1], us[0]);
+	pdata->col_scan_delay_us = us[0];
+	pdata->col_scan_delay_us_max = us[1];
 	of_property_read_u32(np, "col-switch-delay-ms",
 			     &pdata->col_switch_delay_ms);
 	if (pdata->col_gpios_binary_encoded && !pdata->col_switch_delay_ms) {
@@ -744,6 +764,7 @@ static int matrix_keypad_probe(struct platform_device *pdev)
 	/* start in stopped state, open(2) will activate the scan */
 	keypad->stopped = true;
 	INIT_DELAYED_WORK(&keypad->work_scan_matrix, matrix_keypad_scan);
+	/* we cannot normalize pdata here for the non-DT case, it's read-only */
 	INIT_DELAYED_WORK(&keypad->work_switch_column, matrix_keypad_switch);
 	keypad->col_to_poll = pdata->num_matrix_cols;
 	spin_lock_init(&keypad->lock);
diff --git a/include/linux/input/matrix_keypad.h b/include/linux/input/matrix_keypad.h
index 82db84a..fa093b2 100644
--- a/include/linux/input/matrix_keypad.h
+++ b/include/linux/input/matrix_keypad.h
@@ -43,6 +43,10 @@ struct matrix_keymap_data {
  * @num_matrix_cols: number of logical column lines in the matrix
  * @col_scan_delay_us: delay in microseconds, the interval between
  *	activating a column and reading back row information
+ * @col_scan_delay_us_max: maximum delay in microseconds between
+ *	activating a column and reading back row information,
+ *	defaults to @col_scan_delay_us when not specified, allows
+ *	for reduced timer management overhead
  * @col_switch_delay_ms: delay in milliseconds, the interval with which
  *	colums periodically get checked for changes in key press status
  * @debounce_ms: debounce interval in milliseconds, the interval between
@@ -80,6 +84,7 @@ struct matrix_keypad_platform_data {
 
 	/* delays and intervals specs */
 	unsigned int	col_scan_delay_us;
+	unsigned int	col_scan_delay_us_max;
 	unsigned int	col_switch_delay_ms;
 	unsigned int	debounce_ms;
 
