aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial/8250
diff options
context:
space:
mode:
authorHeikki Krogerus <heikki.krogerus@linux.intel.com>2014-06-05 09:51:40 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-07-10 18:27:37 -0400
commit4e26b134bd17234e373376b561d2fc5cba3fccb2 (patch)
tree63943ed94407a41bd3cf36cb39e4f6ffded65fae /drivers/tty/serial/8250
parent1ff5b64dccbf23acfe7993b9132b6992922a4756 (diff)
serial: 8250_dw: clock rate handling for all ACPI platforms
This replaces the Baytrail specific custom set_termios hook with a more generic one where the clock framework is used to set the rate. The method also doesn't need to be limited to just Baytrail, so it's used with all ACPI platforms. Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/serial/8250')
-rw-r--r--drivers/tty/serial/8250/8250_dw.c103
1 files changed, 28 insertions, 75 deletions
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index 51b307aab75e..b8e4eb3e7cbe 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -62,70 +62,12 @@ struct dw8250_data {
62 struct uart_8250_dma dma; 62 struct uart_8250_dma dma;
63}; 63};
64 64
65struct dw8250_acpi_desc {
66 void (*set_termios)(struct uart_port *p, struct ktermios *termios,
67 struct ktermios *old);
68};
69
70#define BYT_PRV_CLK 0x800 65#define BYT_PRV_CLK 0x800
71#define BYT_PRV_CLK_EN (1 << 0) 66#define BYT_PRV_CLK_EN (1 << 0)
72#define BYT_PRV_CLK_M_VAL_SHIFT 1 67#define BYT_PRV_CLK_M_VAL_SHIFT 1
73#define BYT_PRV_CLK_N_VAL_SHIFT 16 68#define BYT_PRV_CLK_N_VAL_SHIFT 16
74#define BYT_PRV_CLK_UPDATE (1 << 31) 69#define BYT_PRV_CLK_UPDATE (1 << 31)
75 70
76static void byt_set_termios(struct uart_port *p, struct ktermios *termios,
77 struct ktermios *old)
78{
79 unsigned int baud = tty_termios_baud_rate(termios);
80 unsigned int m, n;
81 u32 reg;
82
83 /*
84 * For baud rates 0.5M, 1M, 1.5M, 2M, 2.5M, 3M, 3.5M and 4M the
85 * dividers must be adjusted.
86 *
87 * uartclk = (m / n) * 100 MHz, where m <= n
88 */
89 switch (baud) {
90 case 500000:
91 case 1000000:
92 case 2000000:
93 case 4000000:
94 m = 64;
95 n = 100;
96 p->uartclk = 64000000;
97 break;
98 case 3500000:
99 m = 56;
100 n = 100;
101 p->uartclk = 56000000;
102 break;
103 case 1500000:
104 case 3000000:
105 m = 48;
106 n = 100;
107 p->uartclk = 48000000;
108 break;
109 case 2500000:
110 m = 40;
111 n = 100;
112 p->uartclk = 40000000;
113 break;
114 default:
115 m = 2304;
116 n = 3125;
117 p->uartclk = 73728000;
118 }
119
120 /* Reset the clock */
121 reg = (m << BYT_PRV_CLK_M_VAL_SHIFT) | (n << BYT_PRV_CLK_N_VAL_SHIFT);
122 writel(reg, p->membase + BYT_PRV_CLK);
123 reg |= BYT_PRV_CLK_EN | BYT_PRV_CLK_UPDATE;
124 writel(reg, p->membase + BYT_PRV_CLK);
125
126 serial8250_do_set_termios(p, termios, old);
127}
128
129static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value) 71static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value)
130{ 72{
131 struct dw8250_data *d = p->private_data; 73 struct dw8250_data *d = p->private_data;
@@ -242,6 +184,32 @@ dw8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old)
242 pm_runtime_put_sync_suspend(port->dev); 184 pm_runtime_put_sync_suspend(port->dev);
243} 185}
244 186
187static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
188 struct ktermios *old)
189{
190 unsigned int baud = tty_termios_baud_rate(termios);
191 struct dw8250_data *d = p->private_data;
192 unsigned int rate;
193 int ret;
194
195 if (IS_ERR(d->clk) || !old)
196 goto out;
197
198 /* Not requesting clock rates below 1.8432Mhz */
199 if (baud < 115200)
200 baud = 115200;
201
202 clk_disable_unprepare(d->clk);
203 rate = clk_round_rate(d->clk, baud * 16);
204 ret = clk_set_rate(d->clk, rate);
205 clk_prepare_enable(d->clk);
206
207 if (!ret)
208 p->uartclk = rate;
209out:
210 serial8250_do_set_termios(p, termios, old);
211}
212
245static bool dw8250_dma_filter(struct dma_chan *chan, void *param) 213static bool dw8250_dma_filter(struct dma_chan *chan, void *param)
246{ 214{
247 struct dw8250_data *data = param; 215 struct dw8250_data *data = param;
@@ -340,16 +308,10 @@ static int dw8250_probe_of(struct uart_port *p,
340static int dw8250_probe_acpi(struct uart_8250_port *up, 308static int dw8250_probe_acpi(struct uart_8250_port *up,
341 struct dw8250_data *data) 309 struct dw8250_data *data)
342{ 310{
343 const struct acpi_device_id *id;
344 struct uart_port *p = &up->port; 311 struct uart_port *p = &up->port;
345 struct dw8250_acpi_desc *acpi_desc;
346 312
347 dw8250_setup_port(up); 313 dw8250_setup_port(up);
348 314
349 id = acpi_match_device(p->dev->driver->acpi_match_table, p->dev);
350 if (!id)
351 return -ENODEV;
352
353 p->iotype = UPIO_MEM32; 315 p->iotype = UPIO_MEM32;
354 p->serial_in = dw8250_serial_in32; 316 p->serial_in = dw8250_serial_in32;
355 p->serial_out = dw8250_serial_out32; 317 p->serial_out = dw8250_serial_out32;
@@ -360,12 +322,7 @@ static int dw8250_probe_acpi(struct uart_8250_port *up,
360 up->dma->rxconf.src_maxburst = p->fifosize / 4; 322 up->dma->rxconf.src_maxburst = p->fifosize / 4;
361 up->dma->txconf.dst_maxburst = p->fifosize / 4; 323 up->dma->txconf.dst_maxburst = p->fifosize / 4;
362 324
363 acpi_desc = (struct dw8250_acpi_desc *)id->driver_data; 325 up->port.set_termios = dw8250_set_termios;
364 if (!acpi_desc)
365 return 0;
366
367 if (acpi_desc->set_termios)
368 p->set_termios = acpi_desc->set_termios;
369 326
370 return 0; 327 return 0;
371} 328}
@@ -514,16 +471,12 @@ static const struct of_device_id dw8250_of_match[] = {
514}; 471};
515MODULE_DEVICE_TABLE(of, dw8250_of_match); 472MODULE_DEVICE_TABLE(of, dw8250_of_match);
516 473
517static struct dw8250_acpi_desc byt_8250_desc = {
518 .set_termios = byt_set_termios,
519};
520
521static const struct acpi_device_id dw8250_acpi_match[] = { 474static const struct acpi_device_id dw8250_acpi_match[] = {
522 { "INT33C4", 0 }, 475 { "INT33C4", 0 },
523 { "INT33C5", 0 }, 476 { "INT33C5", 0 },
524 { "INT3434", 0 }, 477 { "INT3434", 0 },
525 { "INT3435", 0 }, 478 { "INT3435", 0 },
526 { "80860F0A", (kernel_ulong_t)&byt_8250_desc}, 479 { "80860F0A", 0 },
527 { }, 480 { },
528}; 481};
529MODULE_DEVICE_TABLE(acpi, dw8250_acpi_match); 482MODULE_DEVICE_TABLE(acpi, dw8250_acpi_match);