diff options
| -rw-r--r-- | drivers/tty/serial/sh-sci.c | 37 | ||||
| -rw-r--r-- | include/linux/serial_sci.h | 2 |
2 files changed, 32 insertions, 7 deletions
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index d5239d5ff98b..e4bf0e435af6 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c | |||
| @@ -65,6 +65,7 @@ struct sci_port { | |||
| 65 | struct plat_sci_port *cfg; | 65 | struct plat_sci_port *cfg; |
| 66 | int overrun_bit; | 66 | int overrun_bit; |
| 67 | unsigned int error_mask; | 67 | unsigned int error_mask; |
| 68 | unsigned int sampling_rate; | ||
| 68 | 69 | ||
| 69 | 70 | ||
| 70 | /* Break timer */ | 71 | /* Break timer */ |
| @@ -1750,10 +1751,13 @@ static void sci_shutdown(struct uart_port *port) | |||
| 1750 | sci_free_irq(s); | 1751 | sci_free_irq(s); |
| 1751 | } | 1752 | } |
| 1752 | 1753 | ||
| 1753 | static unsigned int sci_scbrr_calc(unsigned int algo_id, unsigned int bps, | 1754 | static unsigned int sci_scbrr_calc(struct sci_port *s, unsigned int bps, |
| 1754 | unsigned long freq) | 1755 | unsigned long freq) |
| 1755 | { | 1756 | { |
| 1756 | switch (algo_id) { | 1757 | if (s->sampling_rate) |
| 1758 | return DIV_ROUND_CLOSEST(freq, s->sampling_rate * bps) - 1; | ||
| 1759 | |||
| 1760 | switch (s->cfg->scbrr_algo_id) { | ||
| 1757 | case SCBRR_ALGO_1: | 1761 | case SCBRR_ALGO_1: |
| 1758 | return freq / (16 * bps); | 1762 | return freq / (16 * bps); |
| 1759 | case SCBRR_ALGO_2: | 1763 | case SCBRR_ALGO_2: |
| @@ -1843,12 +1847,11 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, | |||
| 1843 | 1847 | ||
| 1844 | baud = uart_get_baud_rate(port, termios, old, 0, max_baud); | 1848 | baud = uart_get_baud_rate(port, termios, old, 0, max_baud); |
| 1845 | if (likely(baud && port->uartclk)) { | 1849 | if (likely(baud && port->uartclk)) { |
| 1846 | if (s->cfg->scbrr_algo_id == SCBRR_ALGO_6) { | 1850 | if (s->cfg->type == PORT_HSCIF) { |
| 1847 | sci_baud_calc_hscif(baud, port->uartclk, &t, &srr, | 1851 | sci_baud_calc_hscif(baud, port->uartclk, &t, &srr, |
| 1848 | &cks); | 1852 | &cks); |
| 1849 | } else { | 1853 | } else { |
| 1850 | t = sci_scbrr_calc(s->cfg->scbrr_algo_id, baud, | 1854 | t = sci_scbrr_calc(s, baud, port->uartclk); |
| 1851 | port->uartclk); | ||
| 1852 | for (cks = 0; t >= 256 && cks <= 3; cks++) | 1855 | for (cks = 0; t >= 256 && cks <= 3; cks++) |
| 1853 | t >>= 2; | 1856 | t >>= 2; |
| 1854 | } | 1857 | } |
| @@ -2092,6 +2095,7 @@ static int sci_init_single(struct platform_device *dev, | |||
| 2092 | { | 2095 | { |
| 2093 | struct uart_port *port = &sci_port->port; | 2096 | struct uart_port *port = &sci_port->port; |
| 2094 | const struct resource *res; | 2097 | const struct resource *res; |
| 2098 | unsigned int sampling_rate; | ||
| 2095 | unsigned int i; | 2099 | unsigned int i; |
| 2096 | int ret; | 2100 | int ret; |
| 2097 | 2101 | ||
| @@ -2143,28 +2147,47 @@ static int sci_init_single(struct platform_device *dev, | |||
| 2143 | case PORT_SCIFB: | 2147 | case PORT_SCIFB: |
| 2144 | port->fifosize = 256; | 2148 | port->fifosize = 256; |
| 2145 | sci_port->overrun_bit = 9; | 2149 | sci_port->overrun_bit = 9; |
| 2150 | sampling_rate = 16; | ||
| 2146 | break; | 2151 | break; |
| 2147 | case PORT_HSCIF: | 2152 | case PORT_HSCIF: |
| 2148 | port->fifosize = 128; | 2153 | port->fifosize = 128; |
| 2154 | sampling_rate = 0; | ||
| 2149 | sci_port->overrun_bit = 0; | 2155 | sci_port->overrun_bit = 0; |
| 2150 | break; | 2156 | break; |
| 2151 | case PORT_SCIFA: | 2157 | case PORT_SCIFA: |
| 2152 | port->fifosize = 64; | 2158 | port->fifosize = 64; |
| 2153 | sci_port->overrun_bit = 9; | 2159 | sci_port->overrun_bit = 9; |
| 2160 | sampling_rate = 16; | ||
| 2154 | break; | 2161 | break; |
| 2155 | case PORT_SCIF: | 2162 | case PORT_SCIF: |
| 2156 | port->fifosize = 16; | 2163 | port->fifosize = 16; |
| 2157 | if (p->regtype == SCIx_SH7705_SCIF_REGTYPE) | 2164 | if (p->regtype == SCIx_SH7705_SCIF_REGTYPE) { |
| 2158 | sci_port->overrun_bit = 9; | 2165 | sci_port->overrun_bit = 9; |
| 2159 | else | 2166 | sampling_rate = 16; |
| 2167 | } else { | ||
| 2160 | sci_port->overrun_bit = 0; | 2168 | sci_port->overrun_bit = 0; |
| 2169 | sampling_rate = 32; | ||
| 2170 | } | ||
| 2161 | break; | 2171 | break; |
| 2162 | default: | 2172 | default: |
| 2163 | port->fifosize = 1; | 2173 | port->fifosize = 1; |
| 2164 | sci_port->overrun_bit = 5; | 2174 | sci_port->overrun_bit = 5; |
| 2175 | sampling_rate = 32; | ||
| 2165 | break; | 2176 | break; |
| 2166 | } | 2177 | } |
| 2167 | 2178 | ||
| 2179 | /* Set the sampling rate if the baud rate calculation algorithm isn't | ||
| 2180 | * specified. | ||
| 2181 | */ | ||
| 2182 | if (p->scbrr_algo_id == SCBRR_ALGO_NONE) { | ||
| 2183 | /* SCIFA on sh7723 and sh7724 need a custom sampling rate that | ||
| 2184 | * doesn't match the SoC datasheet, this should be investigated. | ||
| 2185 | * Let platform data override the sampling rate for now. | ||
| 2186 | */ | ||
| 2187 | sci_port->sampling_rate = p->sampling_rate ? p->sampling_rate | ||
| 2188 | : sampling_rate; | ||
| 2189 | } | ||
| 2190 | |||
| 2168 | if (!early) { | 2191 | if (!early) { |
| 2169 | sci_port->iclk = clk_get(&dev->dev, "sci_ick"); | 2192 | sci_port->iclk = clk_get(&dev->dev, "sci_ick"); |
| 2170 | if (IS_ERR(sci_port->iclk)) { | 2193 | if (IS_ERR(sci_port->iclk)) { |
diff --git a/include/linux/serial_sci.h b/include/linux/serial_sci.h index e9c3021a37ae..af414e1895a5 100644 --- a/include/linux/serial_sci.h +++ b/include/linux/serial_sci.h | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #define SCIx_NOT_SUPPORTED (-1) | 11 | #define SCIx_NOT_SUPPORTED (-1) |
| 12 | 12 | ||
| 13 | enum { | 13 | enum { |
| 14 | SCBRR_ALGO_NONE, /* Compute sampling rate in the driver */ | ||
| 14 | SCBRR_ALGO_1, /* clk / (16 * bps) */ | 15 | SCBRR_ALGO_1, /* clk / (16 * bps) */ |
| 15 | SCBRR_ALGO_2, /* DIV_ROUND_CLOSEST(clk, 32 * bps) - 1 */ | 16 | SCBRR_ALGO_2, /* DIV_ROUND_CLOSEST(clk, 32 * bps) - 1 */ |
| 16 | SCBRR_ALGO_3, /* clk / (8 * bps) */ | 17 | SCBRR_ALGO_3, /* clk / (8 * bps) */ |
| @@ -134,6 +135,7 @@ struct plat_sci_port { | |||
| 134 | upf_t flags; /* UPF_* flags */ | 135 | upf_t flags; /* UPF_* flags */ |
| 135 | unsigned long capabilities; /* Port features/capabilities */ | 136 | unsigned long capabilities; /* Port features/capabilities */ |
| 136 | 137 | ||
| 138 | unsigned int sampling_rate; | ||
| 137 | unsigned int scbrr_algo_id; /* SCBRR calculation algo */ | 139 | unsigned int scbrr_algo_id; /* SCBRR calculation algo */ |
| 138 | unsigned int scscr; /* SCSCR initialization */ | 140 | unsigned int scscr; /* SCSCR initialization */ |
| 139 | 141 | ||
