summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLanqing Liu <lanqing.liu@unisoc.com>2019-03-04 03:58:22 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-03-27 11:30:00 -0400
commit4007098f4ce46c87c16ba34ddc00b042aa444b59 (patch)
tree061e53f3e9b33d5b2a7e6d827c23e68e26f80925
parent984df54e4304d1ebe3e2320a9750b12236f14f0a (diff)
serial: sprd: Add power management for the Spreadtrum serial controller
This patch adds power management for the Spreadtrum serial controller. Signed-off-by: Lanqing Liu <lanqing.liu@unisoc.com> Signed-off-by: Baolin Wang <baolin.wang@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/tty/serial/sprd_serial.c61
1 files changed, 57 insertions, 4 deletions
diff --git a/drivers/tty/serial/sprd_serial.c b/drivers/tty/serial/sprd_serial.c
index 1891a45ac05d..8f45b6671c19 100644
--- a/drivers/tty/serial/sprd_serial.c
+++ b/drivers/tty/serial/sprd_serial.c
@@ -100,10 +100,12 @@
100#define SPRD_IMSR_TX_FIFO_EMPTY BIT(1) 100#define SPRD_IMSR_TX_FIFO_EMPTY BIT(1)
101#define SPRD_IMSR_BREAK_DETECT BIT(7) 101#define SPRD_IMSR_BREAK_DETECT BIT(7)
102#define SPRD_IMSR_TIMEOUT BIT(13) 102#define SPRD_IMSR_TIMEOUT BIT(13)
103#define SPRD_DEFAULT_SOURCE_CLK 26000000
103 104
104struct sprd_uart_port { 105struct sprd_uart_port {
105 struct uart_port port; 106 struct uart_port port;
106 char name[16]; 107 char name[16];
108 struct clk *clk;
107}; 109};
108 110
109static struct sprd_uart_port *sprd_port[UART_NR_MAX]; 111static struct sprd_uart_port *sprd_port[UART_NR_MAX];
@@ -491,6 +493,22 @@ static int sprd_verify_port(struct uart_port *port, struct serial_struct *ser)
491 return 0; 493 return 0;
492} 494}
493 495
496static void sprd_pm(struct uart_port *port, unsigned int state,
497 unsigned int oldstate)
498{
499 struct sprd_uart_port *sup =
500 container_of(port, struct sprd_uart_port, port);
501
502 switch (state) {
503 case UART_PM_STATE_ON:
504 clk_prepare_enable(sup->clk);
505 break;
506 case UART_PM_STATE_OFF:
507 clk_disable_unprepare(sup->clk);
508 break;
509 }
510}
511
494static const struct uart_ops serial_sprd_ops = { 512static const struct uart_ops serial_sprd_ops = {
495 .tx_empty = sprd_tx_empty, 513 .tx_empty = sprd_tx_empty,
496 .get_mctrl = sprd_get_mctrl, 514 .get_mctrl = sprd_get_mctrl,
@@ -507,6 +525,7 @@ static const struct uart_ops serial_sprd_ops = {
507 .request_port = sprd_request_port, 525 .request_port = sprd_request_port,
508 .config_port = sprd_config_port, 526 .config_port = sprd_config_port,
509 .verify_port = sprd_verify_port, 527 .verify_port = sprd_verify_port,
528 .pm = sprd_pm,
510}; 529};
511 530
512#ifdef CONFIG_SERIAL_SPRD_CONSOLE 531#ifdef CONFIG_SERIAL_SPRD_CONSOLE
@@ -671,11 +690,45 @@ static int sprd_remove(struct platform_device *dev)
671 return 0; 690 return 0;
672} 691}
673 692
693static int sprd_clk_init(struct uart_port *uport)
694{
695 struct clk *clk_uart, *clk_parent;
696 struct sprd_uart_port *u = sprd_port[uport->line];
697
698 clk_uart = devm_clk_get(uport->dev, "uart");
699 if (IS_ERR(clk_uart)) {
700 dev_warn(uport->dev, "uart%d can't get uart clock\n",
701 uport->line);
702 clk_uart = NULL;
703 }
704
705 clk_parent = devm_clk_get(uport->dev, "source");
706 if (IS_ERR(clk_parent)) {
707 dev_warn(uport->dev, "uart%d can't get source clock\n",
708 uport->line);
709 clk_parent = NULL;
710 }
711
712 if (!clk_uart || clk_set_parent(clk_uart, clk_parent))
713 uport->uartclk = SPRD_DEFAULT_SOURCE_CLK;
714 else
715 uport->uartclk = clk_get_rate(clk_uart);
716
717 u->clk = devm_clk_get(uport->dev, "enable");
718 if (IS_ERR(u->clk)) {
719 if (PTR_ERR(u->clk) != -EPROBE_DEFER)
720 dev_err(uport->dev, "uart%d can't get enable clock\n",
721 uport->line);
722 return PTR_ERR(u->clk);
723 }
724
725 return 0;
726}
727
674static int sprd_probe(struct platform_device *pdev) 728static int sprd_probe(struct platform_device *pdev)
675{ 729{
676 struct resource *res; 730 struct resource *res;
677 struct uart_port *up; 731 struct uart_port *up;
678 struct clk *clk;
679 int irq; 732 int irq;
680 int index; 733 int index;
681 int ret; 734 int ret;
@@ -704,9 +757,9 @@ static int sprd_probe(struct platform_device *pdev)
704 up->ops = &serial_sprd_ops; 757 up->ops = &serial_sprd_ops;
705 up->flags = UPF_BOOT_AUTOCONF; 758 up->flags = UPF_BOOT_AUTOCONF;
706 759
707 clk = devm_clk_get(&pdev->dev, NULL); 760 ret = sprd_clk_init(up);
708 if (!IS_ERR_OR_NULL(clk)) 761 if (ret)
709 up->uartclk = clk_get_rate(clk); 762 return ret;
710 763
711 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 764 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
712 up->membase = devm_ioremap_resource(&pdev->dev, res); 765 up->membase = devm_ioremap_resource(&pdev->dev, res);