Merge "msm_serial_hs : Add support to select device id with BLSP Based UART"
diff --git a/Documentation/devicetree/bindings/tty/serial/msm_serial_hs.txt b/Documentation/devicetree/bindings/tty/serial/msm_serial_hs.txt
index 91c2461..e00584f 100644
--- a/Documentation/devicetree/bindings/tty/serial/msm_serial_hs.txt
+++ b/Documentation/devicetree/bindings/tty/serial/msm_serial_hs.txt
@@ -3,10 +3,6 @@
 Required properties:
 - compatible :
 	- "qcom,msm-hsuart-v14" to be used for UARTDM Core v1.4
-- cell-index : cell-index to be used as device id to enumerate
-	       TTY based HSUART device as /dev/ttyHS<cell-index>.
-	       Device probe fails if cell-index is not available.
-	       The cell-index value should be from 0 to 255.
 - reg : offset and length of the register set for both the device,
 	uart core and bam core
 - reg-names :
@@ -34,14 +30,15 @@
 
 Example:
 
-	uart7@f995d000 {
+	uart7: uart@f995d000 {
 		compatible = "qcom,msm-hsuart-v14";
-		cell-index = <0>;
 		reg = <0xf995d000 0x1000>,
 		      <0xf9944000 0x5000>;
 		reg-names = "core_mem", "bam_mem";
 		interrupts = <0 113 0>, <0 239 0>;
 		interrupt-names = "core_irq", "bam_irq";
+		qcom,bam-tx-ep-pipe-index = <0>;
+		qcom,bam-rx-ep-pipe-index = <1>;
 	};
 
 Optional properties:
@@ -59,11 +56,21 @@
 - qcom, rx_to_inject : The character to be inserted on wakeup.
 
 
+Aliases :
+An alias may be optionally used to bind the UART device to a TTY device
+(ttyHS<alias_num>) with a given alias number. Aliases are of the form
+uart<n> where <n> is an integer representing the alias number to use.
+On systems with multiple UART devices present, an alias may optionally be
+defined for such devices. The alias value should be from 0 to 255.
+
 Example:
 
+	aliases {
+		uart4 = &uart7; // This device will be enumerated as ttyHS4
+	};
+
 	uart7: uart@f995d000 {
 		compatible = "qcom,msm-hsuart-v14"
-		cell-index = <0>;
 		reg = <0x19c40000 0x1000">,
 		      <0xf9944000 0x5000>;
 		reg-names = "core_mem", "bam_mem";
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index 6684fc4..efd9a32 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -40,6 +40,7 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/ioport.h>
+#include <linux/atomic.h>
 #include <linux/kernel.h>
 #include <linux/timer.h>
 #include <linux/clk.h>
@@ -2593,9 +2594,13 @@
 	return rc;
 }
 
+#define BLSP_UART_NR	12
+static int deviceid[BLSP_UART_NR] = {0};
+static atomic_t msm_serial_hs_next_id = ATOMIC_INIT(0);
+
 static int __devinit msm_hs_probe(struct platform_device *pdev)
 {
-	int ret = 0;
+	int ret = 0, alias_num = -1;
 	struct uart_port *uport;
 	struct msm_hs_port *msm_uport;
 	struct resource *core_resource;
@@ -2603,7 +2608,6 @@
 	struct resource *resource;
 	int core_irqres, bam_irqres;
 	struct msm_serial_hs_platform_data *pdata = pdev->dev.platform_data;
-	struct device_node *node = pdev->dev.of_node;
 
 	if (pdev->dev.of_node) {
 		dev_dbg(&pdev->dev, "device tree enabled\n");
@@ -2611,8 +2615,32 @@
 		if (IS_ERR(pdata))
 			return PTR_ERR(pdata);
 
-		of_property_read_u32(node, "cell-index",
-					&pdev->id);
+		if (pdev->id == -1) {
+			pdev->id = atomic_inc_return(&msm_serial_hs_next_id)-1;
+			deviceid[pdev->id] = 1;
+		}
+
+		/* Use alias from device tree if present
+		 * Alias is used as an optional property
+		 */
+		alias_num = of_alias_get_id(pdev->dev.of_node, "uart");
+		if (alias_num >= 0) {
+			/* If alias_num is between 0 and 11, check that it not
+			 * equal to previous incremented pdev-ids. If it is
+			 * equal to previous pdev.ids , fail deviceprobe.
+			 */
+			if (alias_num < BLSP_UART_NR) {
+				if (deviceid[alias_num] == 0) {
+					pdev->id = alias_num;
+				} else {
+					pr_err("alias_num=%d already used\n",
+								alias_num);
+					return -EINVAL;
+				}
+			} else {
+				pdev->id = alias_num;
+			}
+		}
 
 		pdev->dev.platform_data = pdata;
 	}