serial: sh: Add HSCIF support for R-Car SoC

Provide the basic HSCIF support for R-Car SoC.

Reviewed-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
Signed-off-by: Hai Pham <hai.pham.ud@renesas.com>
Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
[Marek: Fill in HSSRR offset for Gen2 and SCBRR calculation for Gen2 and Gen3]
Reviewed-by: Simon Glass <sjg@chromium.org>
diff --git a/drivers/serial/serial_sh.h b/drivers/serial/serial_sh.h
index 128b077..149ec1f 100644
--- a/drivers/serial/serial_sh.h
+++ b/drivers/serial/serial_sh.h
@@ -213,6 +213,10 @@
 #define SCFCR_TCRST 0x4000
 #define SCFCR_MCE   0x0008
 
+/* HSSRR */
+#define HSSRR_SRE	BIT(15)
+#define HSSRR_SRCYC8	0x0007
+
 #define SCI_MAJOR		204
 #define SCI_MINOR_START		8
 
@@ -242,7 +246,8 @@
 
 #define CPU_SCIx_FNS(name, sci_offset, sci_size, scif_offset, scif_size)\
 	static inline unsigned int sci_##name##_in(struct uart_port *port) {\
-		if (port->type == PORT_SCIF || port->type == PORT_SCIFB) {\
+		if (port->type == PORT_SCIF || port->type == PORT_SCIFB ||\
+		    port->type == PORT_HSCIF) {\
 			SCI_IN(scif_size, scif_offset)\
 		} else { /* PORT_SCI or PORT_SCIFA */\
 			SCI_IN(sci_size, sci_offset);\
@@ -250,7 +255,8 @@
 	}\
 static inline void sci_##name##_out(struct uart_port *port,\
 				unsigned int value) {\
-	if (port->type == PORT_SCIF || port->type == PORT_SCIFB) {\
+	if (port->type == PORT_SCIF || port->type == PORT_SCIFB ||\
+	    port->type == PORT_HSCIF) {\
 		SCI_OUT(scif_size, scif_offset, value)\
 	} else {	/* PORT_SCI or PORT_SCIFA */\
 		SCI_OUT(sci_size, sci_offset, value);\
@@ -375,6 +381,7 @@
 SCIF_FNS(SCSPTR, 0,  0, 0x20, 16)
 SCIF_FNS(DL,     0,  0, 0x30, 16)
 SCIF_FNS(CKS,    0,  0, 0x34, 16)
+SCIF_FNS(HSSRR,  0,  0, 0x40, 16) /* HSCIF only */
 #if defined(CFG_SCIF_A)
 SCIF_FNS(SCLSR,  0,  0, 0x14, 16)
 #else
@@ -414,7 +421,9 @@
 #endif
 SCIF_FNS(SCLSR,				0,  0, 0x24, 16)
 #endif
-SCIF_FNS(DL,				0,  0, 0x0,  0) /* dummy */
+SCIF_FNS(DL,				0,  0, 0x30, 16)
+SCIF_FNS(CKS,				0,  0, 0x34, 16)
+SCIF_FNS(HSSRR,				0,  0, 0x40, 16) /* HSCIF only */
 #endif
 #define sci_in(port, reg) sci_##reg##_in(port)
 #define sci_out(port, reg, value) sci_##reg##_out(port, value)
@@ -485,11 +494,20 @@
 #define SCBRR_VALUE(bps, clk) scbrr_calc(port, bps, clk)
 #elif defined(CONFIG_RCAR_GEN2)
 #define DL_VALUE(bps, clk) (clk / bps / 16) /* External Clock */
- #if defined(CFG_SCIF_A)
+ #if defined(CFG_SCIF_A) || defined(CFG_HSCIF)
   #define SCBRR_VALUE(bps, clk) (clk / bps / 16 - 1) /* Internal Clock */
  #else
   #define SCBRR_VALUE(bps, clk) (clk / bps / 32 - 1) /* Internal Clock */
  #endif
+#elif defined(CONFIG_RCAR_64)
+static inline int scbrr_calc(struct uart_port *port, int bps, int clk)
+{
+	if (port->type == PORT_SCIF)
+		return (clk + 16 * bps) / (32 * bps) - 1;
+	else /* PORT_HSCIF */
+		return clk / bps / 8 / 2 - 1; /* Internal Clock, Sampling rate = 8 */
+}
+#define SCBRR_VALUE(bps, clk) scbrr_calc(port, bps, clk)
 #else /* Generic SH */
 #define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(32*bps)-1)
 #endif