

diff -uprN 1/ql-ol-sdk/ql-ol-kernel/drivers/tty/serial/msm_serial_hs.c ql-ol-sdk/ql-ol-kernel/drivers/tty/serial/msm_serial_hs.c
--- 1/ql-ol-sdk/ql-ol-kernel/drivers/tty/serial/msm_serial_hs.c	2018-08-02 09:28:08.000000000 +0800
+++ ql-ol-sdk/ql-ol-kernel/drivers/tty/serial/msm_serial_hs.c	2019-06-05 11:10:06.609501112 +0800
@@ -61,6 +61,7 @@
 #include <linux/ipc_logging.h>
 #include <asm/irq.h>
 #include <linux/kthread.h>
+#include <linux/delay.h>   //larry.zhang-20190604:add RS485 function
 
 #include <linux/msm-sps.h>
 #include <linux/platform_data/msm_serial_hs.h>
@@ -257,6 +258,8 @@ struct msm_hs_port {
 	struct mutex wlock_mutex;
 	atomic_t startup_count;
 #endif
+  struct serial_rs485		rs485;
+#define rs485_rts_gpio rs485.padding[3]
 };
 
 static struct of_device_id msm_hs_match_table[] = {
@@ -319,6 +322,51 @@ static int msm_hs_ioctl(struct uart_port
 			__func__, cmd, state);
 		break;
 	}
+ 
+ //larry.zhang-20190604:add RS485 function
+ #if defined(TIOCSRS485) && defined(TIOCGRS485)
+ case TIOCSRS485:
+		if (copy_from_user(&msm_uport->rs485, (void __user *)arg, sizeof(struct serial_rs485)))
+			return -EFAULT;
+
+		if(msm_uport->rs485.flags & SER_RS485_ENABLED){
+  			int ret = 0;
+  			if(msm_uport->rs485_rts_gpio == 0)
+  			{
+  				pr_err("gpio:invalid %d\n",msm_uport->rs485_rts_gpio);
+  				return -1;
+  			}
+        
+        ret = gpio_request(msm_uport->rs485_rts_gpio,"RS485_RTS_GPIO");
+  			if (unlikely(ret)) 
+        {
+  				pr_err("gpio request failed for:%d\n",msm_uport->rs485_rts_gpio);
+  				return -1;
+  			}
+        
+  		   if(msm_uport->rs485.flags & SER_RS485_RTS_ON_SEND)
+         {
+      	  	gpio_direction_output(msm_uport->rs485_rts_gpio,0);
+  			 }else{
+  				gpio_direction_output(msm_uport->rs485_rts_gpio,1);
+  			 }  
+          
+  			printk("111RS485 config ok,rts_gpio=%d\n",msm_uport->rs485_rts_gpio);
+	  	}else{
+			  gpio_free(msm_uport->rs485_rts_gpio);
+		}
+    printk("setting TIOCSRS485 ok....\n");
+		return 0;
+   
+	case TIOCGRS485:
+		if (copy_to_user((void __user *)arg,&(msm_uport->rs485),sizeof(struct serial_rs485)))
+			return -EFAULT;
+      
+      printk("TIOCGRS485 setting TIOCGRS485 ok....\n");  
+		return 0;
+#endif
+ //end
+
 	default: {
 		MSM_HS_DBG("%s():Unknown cmd specified: cmd=%d\n", __func__,
 			   cmd);
@@ -1827,7 +1875,29 @@ static void msm_hs_start_tx_locked(struc
 	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
 	struct msm_hs_tx *tx = &msm_uport->tx;
 
-	/* Bail if transfer in progress */
+ //larry.zhang-20190604:add RS485 function
+	if (msm_uport->rs485.flags & SER_RS485_ENABLED)
+  {
+    msm_hs_write(uport, UART_DM_CR, CLEAR_TX_READY);
+  	msm_uport->imr_reg |= UARTDM_ISR_TX_COMP_BMSK;
+  	msm_hs_write(uport, UART_DM_IMR, msm_uport->imr_reg);
+  
+		if(msm_uport->rs485.flags & SER_RS485_RTS_ON_SEND)
+		{
+		    gpio_set_value(msm_uport->rs485_rts_gpio,1);
+		}
+		else
+		{
+		  	gpio_set_value(msm_uport->rs485_rts_gpio,0);
+		}
+		if(msm_uport->rs485.delay_rts_before_send > 0)
+		{
+		  	mdelay(msm_uport->rs485.delay_rts_before_send);
+		}
+	}
+//end
+
+  /* Bail if transfer in progress */
 	if (tx->flush < FLUSH_STOP || tx->dma_in_flight) {
 		MSM_HS_DBG("%s(): retry, flush %d, dma_in_flight %d\n",
 			__func__, tx->flush, tx->dma_in_flight);
@@ -2122,6 +2192,33 @@ static irqreturn_t msm_hs_isr(int irq, v
 	MSM_HS_INFO("%s: DM_ISR: 0x%x\n", __func__, isr_status);
 	dump_uart_hs_registers(msm_uport);
 
+
+//larry.zhang-20190604:add RS485 function
+	/* Uart TCOMP starting */
+  if (msm_uport->rs485.flags & SER_RS485_ENABLED/* & ( tx_flag!= 0)*/)
+  {
+  	if (isr_status & UARTDM_ISR_TX_COMP_BMSK)
+  	{
+  	        if(msm_uport->rs485.delay_rts_after_send > 0)
+  	        {
+  		        	mdelay(msm_uport->rs485.delay_rts_after_send);  
+  	        }
+  		  	  if(msm_uport->rs485.flags & SER_RS485_RTS_ON_SEND)
+  		  	  {
+  			        gpio_set_value(msm_uport->rs485_rts_gpio,0);
+  		   	  }
+  		   	  else
+  		   	  {
+  				      gpio_set_value(msm_uport->rs485_rts_gpio,1);
+  			    }
+	
+  	  	msm_hs_write(uport, UART_DM_CR, CLEAR_TX_TCOMP);
+  		  mb();
+  	}
+  }
+//end
+
+
 	/* Uart RX starting */
 	if (isr_status & UARTDM_ISR_RXLEV_BMSK) {
 		MSM_HS_DBG("%s:UARTDM_ISR_RXLEV_BMSK\n", __func__);
@@ -3593,7 +3690,9 @@ static int msm_hs_probe(struct platform_
 	}
 
 	msm_serial_debugfs_init(msm_uport, pdev->id);
-
+//larry.zhang-20190604:add RS485 function
+  msm_uport->rs485.flags = 0;
+//end  
 	uport->line = pdev->id;
 	if (pdata->userid && pdata->userid <= UARTDM_NR)
 		uport->line = pdata->userid;
@@ -3605,6 +3704,7 @@ static int msm_hs_probe(struct platform_
 		return ret;
 	}
 
+
 err_clock:
 	msm_hs_clk_bus_unvote(msm_uport);
 
diff -uprN 1/ql-ol-sdk/ql-ol-kernel/drivers/tty/serial/msm_serial_hs_hwreg.h ql-ol-sdk/ql-ol-kernel/drivers/tty/serial/msm_serial_hs_hwreg.h
--- 1/ql-ol-sdk/ql-ol-kernel/drivers/tty/serial/msm_serial_hs_hwreg.h	2018-08-02 09:28:08.000000000 +0800
+++ ql-ol-sdk/ql-ol-kernel/drivers/tty/serial/msm_serial_hs_hwreg.h	2019-06-04 15:54:51.058969573 +0800
@@ -176,7 +176,9 @@ enum msm_hs_regs {
 #define CLEAR_TX_READY		0x300
 #define RESET_TX_ERROR		0x800
 #define RESET_TX_DONE		0x810
-
+//larry.zhang-20190604:add RS485 function
+#define CLEAR_TX_TCOMP		0x8B0
+//end
 /*
  * UARTDM_CR BAM IFC comman bit value
  * for UARTDM Core v1.4
@@ -227,6 +229,9 @@ enum msm_hs_regs {
 #define UARTDM_IPR_STALE_LSB_BMSK 0x1f
 
 /* These can be used for both ISR and IMR register */
+//larry.zhang-20190604:add RS485 function
+#define UARTDM_ISR_TX_COMP_BMSK	BIT(15)
+//end
 #define UARTDM_ISR_TX_READY_BMSK	BIT(7)
 #define UARTDM_ISR_CURRENT_CTS_BMSK	BIT(6)
 #define UARTDM_ISR_DELTA_CTS_BMSK	BIT(5)




diff -uprN 1/ql-ol-sdk/ql-ol-kernel/arch/arm/boot/dts/qcom/mdm9607.dtsi ql-ol-sdk/ql-ol-kernel/arch/arm/boot/dts/qcom/mdm9607.dtsi
--- 1/ql-ol-sdk/ql-ol-kernel/arch/arm/boot/dts/qcom/mdm9607.dtsi	2018-08-02 09:27:01.000000000 +0800
+++ ql-ol-sdk/ql-ol-kernel/arch/arm/boot/dts/qcom/mdm9607.dtsi	2019-06-04 16:39:29.027578176 +0800
@@ -67,6 +67,11 @@
 		/*smd11 = &smdtty_data11;*/ /*modified by max.tang@20160118. del Data11 from APP to be used by second USB AT port*/
 		smd21 = &smdtty_data21;
 		smd36 = &smdtty_loopback;
+   
+   /* uart device */
+		uart0 = &blsp1_uart3;	//main uart
+		uart1 = &blsp1_uart2;
+   
 		/* spi device */
 		/*spi1  = &spi_1;*///2016-01-19, comment out by jun.wu, remove spi from device tree
 		spi6 = &spi_6;	
@@ -598,7 +603,7 @@
 	};*/
 	
 	/* BLSP1 UART2 */
-	
+/*	
 	blsp1_uart2: serial@78b0000 {
 		compatible = "qcom,msm-lsuart-v14";
 		reg = <0x78b0000 0x200>;
@@ -617,6 +622,40 @@
 				<86 512 500 800>;
 		status = "disabled";
 	};
+*/
+//larry.zhang-20190604:add RS485 function
+  blsp1_uart2: uart@78b0000 {
+		compatible = "qcom,msm-hsuart-v14";
+		reg = <0x78b0000 0x200>,
+			<0x7884000 0x2b000>;
+		reg-names = "core_mem", "bam_mem";
+		interrupt-names = "core_irq", "bam_irq";
+		#address-cells = <0>;
+		interrupt-parent = <&blsp1_uart2>;
+		interrupts = <0 1>; 			//disable uart rx wakeup source
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0xffffffff>;
+		interrupt-map = <0 &intc 0 108 0
+				1 &intc 0 238 0>;
+
+		qcom,bam-tx-ep-pipe-index = <2>;
+		qcom,bam-rx-ep-pipe-index = <3>;
+		qcom,master-id = <86>;
+		clock-names = "core_clk", "iface_clk";
+		clocks = <&clock_gcc clk_gcc_blsp1_uart2_apps_clk>,
+				<&clock_gcc clk_gcc_blsp1_ahb_clk>;
+		pinctrl-names = "sleep", "default";
+		pinctrl-0 = <&blsp1_uart2_sleep>;
+		pinctrl-1 = <&blsp1_uart2_active>;
+		qcom,msm-bus,name = "blsp1_uart2";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<86 512 0 0>,
+				<86 512 500 800>;
+		status = "disabled";
+	};
+//end
 
 	/*2018-03-15, Modify by Quinn.Zhao, to support hardware flow control*/ 
 	blsp1_uart6: serial@78b4000 {
diff -uprN 1/ql-ol-sdk/ql-ol-kernel/arch/arm/boot/dts/qcom/mdm9607-mtp.dtsi ql-ol-sdk/ql-ol-kernel/arch/arm/boot/dts/qcom/mdm9607-mtp.dtsi
--- 1/ql-ol-sdk/ql-ol-kernel/arch/arm/boot/dts/qcom/mdm9607-mtp.dtsi	2018-08-02 09:27:01.000000000 +0800
+++ ql-ol-sdk/ql-ol-kernel/arch/arm/boot/dts/qcom/mdm9607-mtp.dtsi	2019-06-04 16:39:04.667468388 +0800
@@ -55,12 +55,11 @@
 	status = "ok";
 };
 
+//larry.zhang-20190604:add RS485 function
 &blsp1_uart2 {
-	status = "disabled";	//if need, user can enable by themselves
-	pinctrl-names ="sleep", "default";
-	pinctrl-0 = <&blsp1_uart2_sleep>;
-	pinctrl-1 = <&blsp1_uart2_active>;
+	status = "ok";
 };
+//end
 
 &blsp1_uart6 {
 	status = "disabled";
diff -uprN 1/ql-ol-sdk/ql-ol-kernel/arch/arm/boot/dts/qcom/mdm9607-pinctrl.dtsi ql-ol-sdk/ql-ol-kernel/arch/arm/boot/dts/qcom/mdm9607-pinctrl.dtsi
--- 1/ql-ol-sdk/ql-ol-kernel/arch/arm/boot/dts/qcom/mdm9607-pinctrl.dtsi	2018-08-02 09:27:01.000000000 +0800
+++ ql-ol-sdk/ql-ol-kernel/arch/arm/boot/dts/qcom/mdm9607-pinctrl.dtsi	2019-06-04 13:09:53.702073343 +0800
@@ -221,12 +221,12 @@
 
 		blsp1_uart3_active: blsp1_uart3_active {
 			mux {
-				pins = "gpio0", "gpio1", "gpio2", "gpio3";
+				pins = "gpio0", "gpio1";
 				function = "blsp_uart3";
 			};
 
 			config {
-				pins = "gpio0", "gpio1", "gpio2", "gpio3";
+				pins = "gpio0", "gpio1";
 				drive-strength = <2>;
 				bias-disable;
 			};
@@ -234,13 +234,13 @@
 
 		blsp1_uart3_sleep: blsp1_uart3_sleep {
 			mux {
-				pins = "gpio0", "gpio1", "gpio2", "gpio3";
+				pins = "gpio0", "gpio1";
 				function = "gpio";
 			};
 
 
 			config {
-				pins = "gpio0", "gpio1", "gpio2", "gpio3";
+				pins = "gpio0", "gpio1";
 				drive-strength = <2>;
 				bias-disable;
 				output-low;	//output low when sleep















diff -uprN 1/ql-ol-sdk/ql-ol-extsdk/example/uart/example_uart.c ql-ol-sdk/ql-ol-extsdk/example/uart/example_uart.c
--- 1/ql-ol-sdk/ql-ol-extsdk/example/uart/example_uart.c	2018-08-02 11:20:24.000000000 +0800
+++ ql-ol-sdk/ql-ol-extsdk/example/uart/example_uart.c	2019-06-04 16:02:28.245389775 +0800
@@ -1,5 +1,6 @@
 #include "ql_oe.h"
-
+#include <linux/serial.h>
+#include <sys/ioctl.h>
 
 #define QL_UART1_DEV  "/dev/ttyHS0"
 
@@ -12,6 +13,7 @@ int main(int argc, char* argv[])
 {
 	int iRet;
 	int baudRate;
+	struct serial_rs485 rs485conf;
 	char strTmp[] = "uart test, =+-_0)9(8*7&6^5%4$3#2@1!`~)\n";
 
 	if (argc < 2)
@@ -20,33 +22,43 @@ int main(int argc, char* argv[])
 		return -1;
 	}
 
-	printf("< OpenLinux: UART example >\n");
+	printf("< 11OpenLinux: UART example >\n");
 
 	baudRate = atoi(argv[1]);
 	fd_uart = Ql_UART_Open(QL_UART1_DEV, baudRate, FC_NONE);
 	printf("< open(\"%s\", %d)=%d\n", QL_UART1_DEV, baudRate, fd_uart);
 
 
-	/* Start: If need, to modify uart dcb config */
-	ST_UARTDCB dcb = {
-		.flowctrl = FC_NONE,	//none flow control
-		.databit = DB_CS8,	//databit: 8
-		.stopbit = SB_1,	//stopbit: 1
-		.parity = PB_NONE,	//parity check: none
-		.baudrate = B_115200	//baudrate: 115200
-	};
-
-	iRet = Ql_UART_SetDCB(fd_uart, &dcb);
-	printf("SET DCB ret: %d\n", iRet);
-	iRet = Ql_UART_GetDCB(fd_uart, &dcb);
-	printf("GET DCB ret: %d: baudrate: %d, flowctrl: %d, databit: %d, stopbit: %d, paritybit: %d\n", 
-				iRet, dcb.baudrate, dcb.flowctrl, dcb.databit, dcb.stopbit, dcb.parity);
-	/* End: if need, to modify uart dcb config */
+	if(fd_uart > 0)
+	{
+		/* Enable RS485 mode: */
+		rs485conf.flags |= SER_RS485_ENABLED;
+
+		/* Set logical level for RTS pin equal to 1 when sending: */
+		rs485conf.flags |= SER_RS485_RTS_ON_SEND;
+
+		/* Set logical level for RTS pin equal to 1 after sending: */
+		rs485conf.flags |= SER_RS485_RTS_AFTER_SEND;
 
+		/* Set rts delay before send, if needed: */
+		rs485conf.delay_rts_before_send = 0;
+
+		/* Set rts delay after send, if needed: */
+		rs485conf.delay_rts_after_send = 0;
+		
+		rs485conf.padding[3] = 25;
+
+		if (ioctl (fd_uart, TIOCSRS485, &rs485conf) < 0) {
+
+			printf("IOCTL ERROR !\n");
+		}
+	}else{
+		printf("OPEN  ERROR !\n");
+	}
 
 	/*
-	*  Create a thread to handle uart rx data
-	*/
+	 *  Create a thread to handle uart rx data
+	 */
 	if (pthread_create(&thrd_uart_rcv, NULL, UartRecv_Proc, NULL) != 0)
 	{
 		printf("Fail to create thread!\n");




















