diff options
-rw-r--r-- | drivers/tty/serial/sh-sci.c | 77 |
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 */ | ||
1780 | static 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 */ |
1780 | static void sci_baud_calc_hscif(unsigned int bps, unsigned long freq, | 1796 | static 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 | ||