summaryrefslogtreecommitdiffstats
path: root/drivers/tty
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty')
-rw-r--r--drivers/tty/serial/msm_serial.c35
-rw-r--r--drivers/tty/serial/samsung.c4
-rw-r--r--drivers/tty/serial/sh-sci.c104
3 files changed, 115 insertions, 28 deletions
diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c
index b11e99797fd8..2c6cfb3cf032 100644
--- a/drivers/tty/serial/msm_serial.c
+++ b/drivers/tty/serial/msm_serial.c
@@ -408,9 +408,9 @@ static void msm_init_clock(struct uart_port *port)
{
struct msm_port *msm_port = UART_TO_MSM(port);
- clk_enable(msm_port->clk);
+ clk_prepare_enable(msm_port->clk);
if (!IS_ERR(msm_port->pclk))
- clk_enable(msm_port->pclk);
+ clk_prepare_enable(msm_port->pclk);
msm_serial_set_mnd_regs(port);
}
@@ -486,7 +486,7 @@ static void msm_shutdown(struct uart_port *port)
msm_port->imr = 0;
msm_write(port, 0, UART_IMR); /* disable interrupts */
- clk_disable(msm_port->clk);
+ clk_disable_unprepare(msm_port->clk);
free_irq(port->irq, port);
}
@@ -688,14 +688,14 @@ static void msm_power(struct uart_port *port, unsigned int state,
switch (state) {
case 0:
- clk_enable(msm_port->clk);
+ clk_prepare_enable(msm_port->clk);
if (!IS_ERR(msm_port->pclk))
- clk_enable(msm_port->pclk);
+ clk_prepare_enable(msm_port->pclk);
break;
case 3:
- clk_disable(msm_port->clk);
+ clk_disable_unprepare(msm_port->clk);
if (!IS_ERR(msm_port->pclk))
- clk_disable(msm_port->pclk);
+ clk_disable_unprepare(msm_port->pclk);
break;
default:
printk(KERN_ERR "msm_serial: Unknown PM state %d\n", state);
@@ -884,19 +884,22 @@ static int __init msm_serial_probe(struct platform_device *pdev)
msm_port->is_uartdm = 0;
if (msm_port->is_uartdm) {
- msm_port->clk = clk_get(&pdev->dev, "gsbi_uart_clk");
- msm_port->pclk = clk_get(&pdev->dev, "gsbi_pclk");
+ msm_port->clk = devm_clk_get(&pdev->dev, "gsbi_uart_clk");
+ msm_port->pclk = devm_clk_get(&pdev->dev, "gsbi_pclk");
} else {
- msm_port->clk = clk_get(&pdev->dev, "uart_clk");
+ msm_port->clk = devm_clk_get(&pdev->dev, "uart_clk");
msm_port->pclk = ERR_PTR(-ENOENT);
}
- if (unlikely(IS_ERR(msm_port->clk) || (IS_ERR(msm_port->pclk) &&
- msm_port->is_uartdm)))
- return PTR_ERR(msm_port->clk);
+ if (IS_ERR(msm_port->clk))
+ return PTR_ERR(msm_port->clk);
+
+ if (msm_port->is_uartdm) {
+ if (IS_ERR(msm_port->pclk))
+ return PTR_ERR(msm_port->pclk);
- if (msm_port->is_uartdm)
clk_set_rate(msm_port->clk, 1843200);
+ }
port->uartclk = clk_get_rate(msm_port->clk);
printk(KERN_INFO "uartclk = %d\n", port->uartclk);
@@ -919,9 +922,9 @@ static int __init msm_serial_probe(struct platform_device *pdev)
static int msm_serial_remove(struct platform_device *pdev)
{
- struct msm_port *msm_port = platform_get_drvdata(pdev);
+ struct uart_port *port = platform_get_drvdata(pdev);
- clk_put(msm_port->clk);
+ uart_remove_one_port(&msm_uart_driver, port);
return 0;
}
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index 81ebc86a9e23..376079b9bd75 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -1713,9 +1713,7 @@ static struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = {
#define S5PV210_SERIAL_DRV_DATA (kernel_ulong_t)NULL
#endif
-#if defined(CONFIG_CPU_EXYNOS4210) || defined(CONFIG_SOC_EXYNOS4212) || \
- defined(CONFIG_SOC_EXYNOS4412) || defined(CONFIG_SOC_EXYNOS5250) || \
- defined(CONFIG_SOC_EXYNOS5440)
+#if defined(CONFIG_ARCH_EXYNOS)
static struct s3c24xx_serial_drv_data exynos4210_serial_drv_data = {
.info = &(struct s3c24xx_uart_info) {
.name = "Samsung Exynos4 UART",
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index 156418619949..7477e0ea5cdb 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -146,6 +146,7 @@ static struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
[SCRFDR] = sci_reg_invalid,
[SCSPTR] = sci_reg_invalid,
[SCLSR] = sci_reg_invalid,
+ [HSSRR] = sci_reg_invalid,
},
/*
@@ -165,6 +166,7 @@ static struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
[SCRFDR] = sci_reg_invalid,
[SCSPTR] = sci_reg_invalid,
[SCLSR] = sci_reg_invalid,
+ [HSSRR] = sci_reg_invalid,
},
/*
@@ -183,6 +185,7 @@ static struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
[SCRFDR] = sci_reg_invalid,
[SCSPTR] = sci_reg_invalid,
[SCLSR] = sci_reg_invalid,
+ [HSSRR] = sci_reg_invalid,
},
/*
@@ -201,6 +204,7 @@ static struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
[SCRFDR] = { 0x3c, 16 },
[SCSPTR] = sci_reg_invalid,
[SCLSR] = sci_reg_invalid,
+ [HSSRR] = sci_reg_invalid,
},
/*
@@ -220,6 +224,7 @@ static struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
[SCRFDR] = sci_reg_invalid,
[SCSPTR] = { 0x20, 16 },
[SCLSR] = { 0x24, 16 },
+ [HSSRR] = sci_reg_invalid,
},
/*
@@ -238,6 +243,7 @@ static struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
[SCRFDR] = sci_reg_invalid,
[SCSPTR] = sci_reg_invalid,
[SCLSR] = sci_reg_invalid,
+ [HSSRR] = sci_reg_invalid,
},
/*
@@ -256,6 +262,26 @@ static struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
[SCRFDR] = sci_reg_invalid,
[SCSPTR] = { 0x20, 16 },
[SCLSR] = { 0x24, 16 },
+ [HSSRR] = sci_reg_invalid,
+ },
+
+ /*
+ * Common HSCIF definitions.
+ */
+ [SCIx_HSCIF_REGTYPE] = {
+ [SCSMR] = { 0x00, 16 },
+ [SCBRR] = { 0x04, 8 },
+ [SCSCR] = { 0x08, 16 },
+ [SCxTDR] = { 0x0c, 8 },
+ [SCxSR] = { 0x10, 16 },
+ [SCxRDR] = { 0x14, 8 },
+ [SCFCR] = { 0x18, 16 },
+ [SCFDR] = { 0x1c, 16 },
+ [SCTFDR] = sci_reg_invalid,
+ [SCRFDR] = sci_reg_invalid,
+ [SCSPTR] = { 0x20, 16 },
+ [SCLSR] = { 0x24, 16 },
+ [HSSRR] = { 0x40, 16 },
},
/*
@@ -275,6 +301,7 @@ static struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
[SCRFDR] = sci_reg_invalid,
[SCSPTR] = sci_reg_invalid,
[SCLSR] = { 0x24, 16 },
+ [HSSRR] = sci_reg_invalid,
},
/*
@@ -294,6 +321,7 @@ static struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
[SCRFDR] = { 0x20, 16 },
[SCSPTR] = { 0x24, 16 },
[SCLSR] = { 0x28, 16 },
+ [HSSRR] = sci_reg_invalid,
},
/*
@@ -313,6 +341,7 @@ static struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
[SCRFDR] = sci_reg_invalid,
[SCSPTR] = sci_reg_invalid,
[SCLSR] = sci_reg_invalid,
+ [HSSRR] = sci_reg_invalid,
},
};
@@ -374,6 +403,9 @@ static int sci_probe_regmap(struct plat_sci_port *cfg)
*/
cfg->regtype = SCIx_SH4_SCIF_REGTYPE;
break;
+ case PORT_HSCIF:
+ cfg->regtype = SCIx_HSCIF_REGTYPE;
+ break;
default:
printk(KERN_ERR "Can't probe register map for given port\n");
return -EINVAL;
@@ -1798,6 +1830,42 @@ static unsigned int sci_scbrr_calc(unsigned int algo_id, unsigned int bps,
return ((freq + 16 * bps) / (32 * bps) - 1);
}
+/* calculate sample rate, BRR, and clock select for HSCIF */
+static void sci_baud_calc_hscif(unsigned int bps, unsigned long freq,
+ int *brr, unsigned int *srr,
+ unsigned int *cks)
+{
+ int sr, c, br, err;
+ int min_err = 1000; /* 100% */
+
+ /* Find the combination of sample rate and clock select with the
+ smallest deviation from the desired baud rate. */
+ for (sr = 8; sr <= 32; sr++) {
+ for (c = 0; c <= 3; c++) {
+ /* integerized formulas from HSCIF documentation */
+ br = freq / (sr * (1 << (2 * c + 1)) * bps) - 1;
+ if (br < 0 || br > 255)
+ continue;
+ err = freq / ((br + 1) * bps * sr *
+ (1 << (2 * c + 1)) / 1000) - 1000;
+ if (min_err > err) {
+ min_err = err;
+ *brr = br;
+ *srr = sr - 1;
+ *cks = c;
+ }
+ }
+ }
+
+ if (min_err == 1000) {
+ WARN_ON(1);
+ /* use defaults */
+ *brr = 255;
+ *srr = 15;
+ *cks = 0;
+ }
+}
+
static void sci_reset(struct uart_port *port)
{
struct plat_sci_reg *reg;
@@ -1819,8 +1887,9 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
{
struct sci_port *s = to_sci_port(port);
struct plat_sci_reg *reg;
- unsigned int baud, smr_val, max_baud, cks;
+ unsigned int baud, smr_val, max_baud, cks = 0;
int t = -1;
+ unsigned int srr = 15;
/*
* earlyprintk comes here early on with port->uartclk set to zero.
@@ -1833,8 +1902,17 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
max_baud = port->uartclk ? port->uartclk / 16 : 115200;
baud = uart_get_baud_rate(port, termios, old, 0, max_baud);
- if (likely(baud && port->uartclk))
- t = sci_scbrr_calc(s->cfg->scbrr_algo_id, baud, port->uartclk);
+ if (likely(baud && port->uartclk)) {
+ if (s->cfg->scbrr_algo_id == SCBRR_ALGO_6) {
+ sci_baud_calc_hscif(baud, port->uartclk, &t, &srr,
+ &cks);
+ } else {
+ t = sci_scbrr_calc(s->cfg->scbrr_algo_id, baud,
+ port->uartclk);
+ for (cks = 0; t >= 256 && cks <= 3; cks++)
+ t >>= 2;
+ }
+ }
sci_port_enable(s);
@@ -1853,15 +1931,15 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
uart_update_timeout(port, termios->c_cflag, baud);
- for (cks = 0; t >= 256 && cks <= 3; cks++)
- t >>= 2;
-
dev_dbg(port->dev, "%s: SMR %x, cks %x, t %x, SCSCR %x\n",
__func__, smr_val, cks, t, s->cfg->scscr);
if (t >= 0) {
serial_port_out(port, SCSMR, (smr_val & ~3) | cks);
serial_port_out(port, SCBRR, t);
+ reg = sci_getreg(port, HSSRR);
+ if (reg->size)
+ serial_port_out(port, HSSRR, srr | HSCIF_SRE);
udelay((1000000+(baud-1)) / baud); /* Wait one bit interval */
} else
serial_port_out(port, SCSMR, smr_val);
@@ -1947,6 +2025,8 @@ static const char *sci_type(struct uart_port *port)
return "scifa";
case PORT_SCIFB:
return "scifb";
+ case PORT_HSCIF:
+ return "hscif";
}
return NULL;
@@ -1960,7 +2040,10 @@ static inline unsigned long sci_port_size(struct uart_port *port)
* from platform resource data at such a time that ports begin to
* behave more erratically.
*/
- return 64;
+ if (port->type == PORT_HSCIF)
+ return 96;
+ else
+ return 64;
}
static int sci_remap_port(struct uart_port *port)
@@ -2085,6 +2168,9 @@ static int sci_init_single(struct platform_device *dev,
case PORT_SCIFB:
port->fifosize = 256;
break;
+ case PORT_HSCIF:
+ port->fifosize = 128;
+ break;
case PORT_SCIFA:
port->fifosize = 64;
break;
@@ -2325,7 +2411,7 @@ static inline int sci_probe_earlyprintk(struct platform_device *pdev)
#endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */
static char banner[] __initdata =
- KERN_INFO "SuperH SCI(F) driver initialized\n";
+ KERN_INFO "SuperH (H)SCI(F) driver initialized\n";
static struct uart_driver sci_uart_driver = {
.owner = THIS_MODULE,
@@ -2484,4 +2570,4 @@ module_exit(sci_exit);
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:sh-sci");
MODULE_AUTHOR("Paul Mundt");
-MODULE_DESCRIPTION("SuperH SCI(F) serial driver");
+MODULE_DESCRIPTION("SuperH (H)SCI(F) serial driver");