aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/tty/serial/sh-sci.c77
1 files changed, 59 insertions, 18 deletions
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index 091b65587c7c..3081e46085ce 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -1776,13 +1776,30 @@ static unsigned int sci_scbrr_calc(struct sci_port *s, unsigned int bps,
1776 return ((freq + 16 * bps) / (32 * bps) - 1); 1776 return ((freq + 16 * bps) / (32 * bps) - 1);
1777} 1777}
1778 1778
1779/* calculate frame length from SMR */
1780static int sci_baud_calc_frame_len(unsigned int smr_val)
1781{
1782 int len = 10;
1783
1784 if (smr_val & SCSMR_CHR)
1785 len--;
1786 if (smr_val & SCSMR_PE)
1787 len++;
1788 if (smr_val & SCSMR_STOP)
1789 len++;
1790
1791 return len;
1792}
1793
1794
1779/* calculate sample rate, BRR, and clock select for HSCIF */ 1795/* calculate sample rate, BRR, and clock select for HSCIF */
1780static void sci_baud_calc_hscif(unsigned int bps, unsigned long freq, 1796static void sci_baud_calc_hscif(unsigned int bps, unsigned long freq,
1781 int *brr, unsigned int *srr, 1797 int *brr, unsigned int *srr,
1782 unsigned int *cks) 1798 unsigned int *cks, int frame_len)
1783{ 1799{
1784 int sr, c, br, err; 1800 int sr, c, br, err, recv_margin;
1785 int min_err = 1000; /* 100% */ 1801 int min_err = 1000; /* 100% */
1802 int recv_max_margin = 0;
1786 1803
1787 /* Find the combination of sample rate and clock select with the 1804 /* Find the combination of sample rate and clock select with the
1788 smallest deviation from the desired baud rate. */ 1805 smallest deviation from the desired baud rate. */
@@ -1795,12 +1812,35 @@ static void sci_baud_calc_hscif(unsigned int bps, unsigned long freq,
1795 err = DIV_ROUND_CLOSEST(freq, ((br + 1) * bps * sr * 1812 err = DIV_ROUND_CLOSEST(freq, ((br + 1) * bps * sr *
1796 (1 << (2 * c + 1)) / 1000)) - 1813 (1 << (2 * c + 1)) / 1000)) -
1797 1000; 1814 1000;
1815 if (err < 0)
1816 continue;
1817
1818 /* Calc recv margin
1819 * M: Receive margin (%)
1820 * N: Ratio of bit rate to clock (N = sampling rate)
1821 * D: Clock duty (D = 0 to 1.0)
1822 * L: Frame length (L = 9 to 12)
1823 * F: Absolute value of clock frequency deviation
1824 *
1825 * M = |(0.5 - 1 / 2 * N) - ((L - 0.5) * F) -
1826 * (|D - 0.5| / N * (1 + F))|
1827 * NOTE: Usually, treat D for 0.5, F is 0 by this
1828 * calculation.
1829 */
1830 recv_margin = abs((500 -
1831 DIV_ROUND_CLOSEST(1000, sr << 1)) / 10);
1798 if (min_err > err) { 1832 if (min_err > err) {
1799 min_err = err; 1833 min_err = err;
1800 *brr = br; 1834 recv_max_margin = recv_margin;
1801 *srr = sr - 1; 1835 } else if ((min_err == err) &&
1802 *cks = c; 1836 (recv_margin > recv_max_margin))
1803 } 1837 recv_max_margin = recv_margin;
1838 else
1839 continue;
1840
1841 *brr = br;
1842 *srr = sr - 1;
1843 *cks = c;
1804 } 1844 }
1805 } 1845 }
1806 1846
@@ -1834,10 +1874,19 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
1834{ 1874{
1835 struct sci_port *s = to_sci_port(port); 1875 struct sci_port *s = to_sci_port(port);
1836 struct plat_sci_reg *reg; 1876 struct plat_sci_reg *reg;
1837 unsigned int baud, smr_val, max_baud, cks = 0; 1877 unsigned int baud, smr_val = 0, max_baud, cks = 0;
1838 int t = -1; 1878 int t = -1;
1839 unsigned int srr = 15; 1879 unsigned int srr = 15;
1840 1880
1881 if ((termios->c_cflag & CSIZE) == CS7)
1882 smr_val |= SCSMR_CHR;
1883 if (termios->c_cflag & PARENB)
1884 smr_val |= SCSMR_PE;
1885 if (termios->c_cflag & PARODD)
1886 smr_val |= SCSMR_PE | SCSMR_ODD;
1887 if (termios->c_cflag & CSTOPB)
1888 smr_val |= SCSMR_STOP;
1889
1841 /* 1890 /*
1842 * earlyprintk comes here early on with port->uartclk set to zero. 1891 * earlyprintk comes here early on with port->uartclk set to zero.
1843 * the clock framework is not up and running at this point so here 1892 * the clock framework is not up and running at this point so here
@@ -1851,8 +1900,9 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
1851 baud = uart_get_baud_rate(port, termios, old, 0, max_baud); 1900 baud = uart_get_baud_rate(port, termios, old, 0, max_baud);
1852 if (likely(baud && port->uartclk)) { 1901 if (likely(baud && port->uartclk)) {
1853 if (s->cfg->type == PORT_HSCIF) { 1902 if (s->cfg->type == PORT_HSCIF) {
1903 int frame_len = sci_baud_calc_frame_len(smr_val);
1854 sci_baud_calc_hscif(baud, port->uartclk, &t, &srr, 1904 sci_baud_calc_hscif(baud, port->uartclk, &t, &srr,
1855 &cks); 1905 &cks, frame_len);
1856 } else { 1906 } else {
1857 t = sci_scbrr_calc(s, baud, port->uartclk); 1907 t = sci_scbrr_calc(s, baud, port->uartclk);
1858 for (cks = 0; t >= 256 && cks <= 3; cks++) 1908 for (cks = 0; t >= 256 && cks <= 3; cks++)
@@ -1864,16 +1914,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
1864 1914
1865 sci_reset(port); 1915 sci_reset(port);
1866 1916
1867 smr_val = serial_port_in(port, SCSMR) & 3; 1917 smr_val |= serial_port_in(port, SCSMR) & 3;
1868
1869 if ((termios->c_cflag & CSIZE) == CS7)
1870 smr_val |= SCSMR_CHR;
1871 if (termios->c_cflag & PARENB)
1872 smr_val |= SCSMR_PE;
1873 if (termios->c_cflag & PARODD)
1874 smr_val |= SCSMR_PE | SCSMR_ODD;
1875 if (termios->c_cflag & CSTOPB)
1876 smr_val |= SCSMR_STOP;
1877 1918
1878 uart_update_timeout(port, termios->c_cflag, baud); 1919 uart_update_timeout(port, termios->c_cflag, baud);
1879 1920