diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index fa3fd876105b..229162481fd6 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -79,6 +79,7 @@ enum {
 
 enum SCI_CLKS {
 	SCI_FCK,		/* Functional Clock */
+	SCI_SCK,		/* Optional External Clock */
 	SCI_NUM_CLKS
 };
 
@@ -1924,6 +1925,39 @@ static void sci_shutdown(struct uart_port *port)
 	sci_free_irq(s);
 }
 
+static int sci_sck_calc(struct sci_port *s, unsigned int bps,
+			unsigned int *srr)
+{
+	unsigned long freq = s->clk_rates[SCI_SCK];
+	unsigned int min_sr, max_sr, sr;
+	int err, min_err = INT_MAX;
+
+	if (s->sampling_rate) {
+		/* SCI(F) has a fixed sampling rate */
+		min_sr = max_sr = s->sampling_rate / 2;
+	} else {
+		/* HSCIF has a variable 1/(8..32) sampling rate */
+		min_sr = 8;
+		max_sr = 32;
+	}
+
+	for (sr = max_sr; sr >= min_sr; sr--) {
+		err = DIV_ROUND_CLOSEST(freq, sr) - bps;
+		if (abs(err) >= abs(min_err))
+			continue;
+
+		min_err = err;
+		*srr = sr - 1;
+
+		if (!err)
+			break;
+	}
+
+	dev_dbg(s->port.dev, "SCK: %u%+d bps using SR %u\n", bps, min_err,
+		*srr + 1);
+	return min_err;
+}
+
 /* calculate sample rate, BRR, and clock select */
 static int sci_scbrr_calc(struct sci_port *s, unsigned int bps,
 			  unsigned int *brr, unsigned int *srr,
@@ -2019,7 +2053,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
 			    struct ktermios *old)
 {
 	unsigned int baud, smr_val = 0, scr_val = 0, i;
-	unsigned int brr = 255, cks = 0, srr = 15;
+	unsigned int brr = 255, cks = 0, srr = 15, sccks = 0;
 	unsigned int brr1 = 255, cks1 = 0, srr1 = 15;
 	struct sci_port *s = to_sci_port(port);
 	const struct plat_sci_reg *reg;
@@ -2062,10 +2096,26 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
 	 * that gives us the smallest deviation from the desired baud rate.
 	 */
 
+	/* Optional Undivided External Clock */
+	if (s->clk_rates[SCI_SCK] && port->type != PORT_SCIFA &&
+	    port->type != PORT_SCIFB) {
+		err = sci_sck_calc(s, baud, &srr1);
+		if (abs(err) < abs(min_err)) {
+			best_clk = SCI_SCK;
+			scr_val = SCSCR_CKE1;
+			sccks = SCCKS_CKS;
+			min_err = err;
+			srr = srr1;
+			if (!err)
+				goto done;
+		}
+	}
+
 	/* Divided Functional Clock using standard Bit Rate Register */
 	err = sci_scbrr_calc(s, baud, &brr1, &srr1, &cks1);
 	if (abs(err) < abs(min_err)) {
 		best_clk = SCI_FCK;
+		scr_val = 0;
 		min_err = err;
 		brr = brr1;
 		srr = srr1;
@@ -2079,14 +2129,23 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
 
 	sci_port_enable(s);
 
+	/*
+	 * Program the optional External Baud Rate Generator (BRG) first.
+	 * It controls the mux to select (H)SCK or frequency divided clock.
+	 */
+	if (best_clk >= 0 && sci_getreg(port, SCCKS)->size)
+		serial_port_out(port, SCCKS, sccks);
+
 	sci_reset(port);
 
 	uart_update_timeout(port, termios->c_cflag, baud);
 
 	if (best_clk >= 0) {
 		smr_val |= cks;
-		dev_dbg(port->dev, "SMR 0x%x BRR %u SRR %u\n", smr_val, brr,
-			srr);
+		dev_dbg(port->dev,
+			 "SCR 0x%x SMR 0x%x BRR %u CKS 0x%x SRR %u\n",
+			 scr_val, smr_val, brr, sccks, srr);
+		serial_port_out(port, SCSCR, scr_val);
 		serial_port_out(port, SCSMR, smr_val);
 		serial_port_out(port, SCBRR, brr);
 		if (sci_getreg(port, HSSRR)->size)
@@ -2322,10 +2381,14 @@ static int sci_init_clocks(struct sci_port *sci_port, struct device *dev)
 {
 	const char *clk_names[] = {
 		[SCI_FCK] = "fck",
+		[SCI_SCK] = "sck",
 	};
 	struct clk *clk;
 	unsigned int i;
 
+	if (sci_port->cfg->type == PORT_HSCIF)
+		clk_names[SCI_SCK] = "hsck";
+
 	for (i = 0; i < SCI_NUM_CLKS; i++) {
 		clk = devm_clk_get(dev, clk_names[i]);
 		if (PTR_ERR(clk) == -EPROBE_DEFER)