diff options
Diffstat (limited to 'drivers/tty/serial/mvebu-uart.c')
-rw-r--r-- | drivers/tty/serial/mvebu-uart.c | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/drivers/tty/serial/mvebu-uart.c b/drivers/tty/serial/mvebu-uart.c index f503fab1e268..d04b5eeea3c6 100644 --- a/drivers/tty/serial/mvebu-uart.c +++ b/drivers/tty/serial/mvebu-uart.c | |||
@@ -71,6 +71,8 @@ | |||
71 | #define UART_BRDV 0x10 | 71 | #define UART_BRDV 0x10 |
72 | #define BRDV_BAUD_MASK 0x3FF | 72 | #define BRDV_BAUD_MASK 0x3FF |
73 | 73 | ||
74 | #define UART_OSAMP 0x14 | ||
75 | |||
74 | #define MVEBU_NR_UARTS 2 | 76 | #define MVEBU_NR_UARTS 2 |
75 | 77 | ||
76 | #define MVEBU_UART_TYPE "mvebu-uart" | 78 | #define MVEBU_UART_TYPE "mvebu-uart" |
@@ -108,6 +110,17 @@ struct mvebu_uart_driver_data { | |||
108 | struct uart_flags flags; | 110 | struct uart_flags flags; |
109 | }; | 111 | }; |
110 | 112 | ||
113 | /* Saved registers during suspend */ | ||
114 | struct mvebu_uart_pm_regs { | ||
115 | unsigned int rbr; | ||
116 | unsigned int tsh; | ||
117 | unsigned int ctrl; | ||
118 | unsigned int intr; | ||
119 | unsigned int stat; | ||
120 | unsigned int brdv; | ||
121 | unsigned int osamp; | ||
122 | }; | ||
123 | |||
111 | /* MVEBU UART driver structure */ | 124 | /* MVEBU UART driver structure */ |
112 | struct mvebu_uart { | 125 | struct mvebu_uart { |
113 | struct uart_port *port; | 126 | struct uart_port *port; |
@@ -115,6 +128,9 @@ struct mvebu_uart { | |||
115 | int irq[UART_IRQ_COUNT]; | 128 | int irq[UART_IRQ_COUNT]; |
116 | unsigned char __iomem *nb; | 129 | unsigned char __iomem *nb; |
117 | struct mvebu_uart_driver_data *data; | 130 | struct mvebu_uart_driver_data *data; |
131 | #if defined(CONFIG_PM) | ||
132 | struct mvebu_uart_pm_regs pm_regs; | ||
133 | #endif /* CONFIG_PM */ | ||
118 | }; | 134 | }; |
119 | 135 | ||
120 | static struct mvebu_uart *to_mvuart(struct uart_port *port) | 136 | static struct mvebu_uart *to_mvuart(struct uart_port *port) |
@@ -718,6 +734,51 @@ static struct uart_driver mvebu_uart_driver = { | |||
718 | #endif | 734 | #endif |
719 | }; | 735 | }; |
720 | 736 | ||
737 | #if defined(CONFIG_PM) | ||
738 | static int mvebu_uart_suspend(struct device *dev) | ||
739 | { | ||
740 | struct mvebu_uart *mvuart = dev_get_drvdata(dev); | ||
741 | struct uart_port *port = mvuart->port; | ||
742 | |||
743 | uart_suspend_port(&mvebu_uart_driver, port); | ||
744 | |||
745 | mvuart->pm_regs.rbr = readl(port->membase + UART_RBR(port)); | ||
746 | mvuart->pm_regs.tsh = readl(port->membase + UART_TSH(port)); | ||
747 | mvuart->pm_regs.ctrl = readl(port->membase + UART_CTRL(port)); | ||
748 | mvuart->pm_regs.intr = readl(port->membase + UART_INTR(port)); | ||
749 | mvuart->pm_regs.stat = readl(port->membase + UART_STAT); | ||
750 | mvuart->pm_regs.brdv = readl(port->membase + UART_BRDV); | ||
751 | mvuart->pm_regs.osamp = readl(port->membase + UART_OSAMP); | ||
752 | |||
753 | device_set_wakeup_enable(dev, true); | ||
754 | |||
755 | return 0; | ||
756 | } | ||
757 | |||
758 | static int mvebu_uart_resume(struct device *dev) | ||
759 | { | ||
760 | struct mvebu_uart *mvuart = dev_get_drvdata(dev); | ||
761 | struct uart_port *port = mvuart->port; | ||
762 | |||
763 | writel(mvuart->pm_regs.rbr, port->membase + UART_RBR(port)); | ||
764 | writel(mvuart->pm_regs.tsh, port->membase + UART_TSH(port)); | ||
765 | writel(mvuart->pm_regs.ctrl, port->membase + UART_CTRL(port)); | ||
766 | writel(mvuart->pm_regs.intr, port->membase + UART_INTR(port)); | ||
767 | writel(mvuart->pm_regs.stat, port->membase + UART_STAT); | ||
768 | writel(mvuart->pm_regs.brdv, port->membase + UART_BRDV); | ||
769 | writel(mvuart->pm_regs.osamp, port->membase + UART_OSAMP); | ||
770 | |||
771 | uart_resume_port(&mvebu_uart_driver, port); | ||
772 | |||
773 | return 0; | ||
774 | } | ||
775 | |||
776 | static const struct dev_pm_ops mvebu_uart_pm_ops = { | ||
777 | .suspend = mvebu_uart_suspend, | ||
778 | .resume = mvebu_uart_resume, | ||
779 | }; | ||
780 | #endif /* CONFIG_PM */ | ||
781 | |||
721 | static const struct of_device_id mvebu_uart_of_match[]; | 782 | static const struct of_device_id mvebu_uart_of_match[]; |
722 | 783 | ||
723 | /* Counter to keep track of each UART port id when not using CONFIG_OF */ | 784 | /* Counter to keep track of each UART port id when not using CONFIG_OF */ |
@@ -891,6 +952,9 @@ static struct platform_driver mvebu_uart_platform_driver = { | |||
891 | .name = "mvebu-uart", | 952 | .name = "mvebu-uart", |
892 | .of_match_table = of_match_ptr(mvebu_uart_of_match), | 953 | .of_match_table = of_match_ptr(mvebu_uart_of_match), |
893 | .suppress_bind_attrs = true, | 954 | .suppress_bind_attrs = true, |
955 | #if defined(CONFIG_PM) | ||
956 | .pm = &mvebu_uart_pm_ops, | ||
957 | #endif /* CONFIG_PM */ | ||
894 | }, | 958 | }, |
895 | }; | 959 | }; |
896 | 960 | ||