diff options
author | Matteo Facchinetti <matteo.facchinetti@sirius-es.it> | 2013-05-24 14:24:58 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-06-03 13:22:35 -0400 |
commit | 2574b27eee4f00f2773d1c209218b3f4cf34a3ca (patch) | |
tree | 505b17eacf962c3e0be4a105b9c9bab72071fc7d /drivers/tty | |
parent | 696faedd616e202f5c510cd03dcc8853c11ca6db (diff) |
serial/mpc52xx_uart: prepare for adding MPC5125 PSC UART support
MPC5125 PSC controller has different register layout than MPC5121.
To support MPC5125 PSC in this driver we have to provide further
psc_ops functions for SoC specific register accesses.
Add new register access functions to the psc_ops structure and
provide MPC52xx and MPC512x specific implementation for them.
Then replace remaining direct register accesses in the driver by
appropriate psc_ops function calls. The subsequent patch can now
add MPC5125 specific set of psc_ops functions.
Signed-off-by: Vladimir Ermakov <vooon341@gmail.com>
Signed-off-by: Matteo Facchinetti <matteo.facchinetti@sirius-es.it>
Signed-off-by: Anatolij Gustschin <agust@denx.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty')
-rw-r--r-- | drivers/tty/serial/mpc52xx_uart.c | 161 |
1 files changed, 119 insertions, 42 deletions
diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c index 2c03904359b9..019ecb1c6847 100644 --- a/drivers/tty/serial/mpc52xx_uart.c +++ b/drivers/tty/serial/mpc52xx_uart.c | |||
@@ -112,6 +112,15 @@ struct psc_ops { | |||
112 | void (*fifoc_uninit)(void); | 112 | void (*fifoc_uninit)(void); |
113 | void (*get_irq)(struct uart_port *, struct device_node *); | 113 | void (*get_irq)(struct uart_port *, struct device_node *); |
114 | irqreturn_t (*handle_irq)(struct uart_port *port); | 114 | irqreturn_t (*handle_irq)(struct uart_port *port); |
115 | u16 (*get_status)(struct uart_port *port); | ||
116 | u8 (*get_ipcr)(struct uart_port *port); | ||
117 | void (*command)(struct uart_port *port, u8 cmd); | ||
118 | void (*set_mode)(struct uart_port *port, u8 mr1, u8 mr2); | ||
119 | void (*set_rts)(struct uart_port *port, int state); | ||
120 | void (*enable_ms)(struct uart_port *port); | ||
121 | void (*set_sicr)(struct uart_port *port, u32 val); | ||
122 | void (*set_imr)(struct uart_port *port, u16 val); | ||
123 | u8 (*get_mr1)(struct uart_port *port); | ||
115 | }; | 124 | }; |
116 | 125 | ||
117 | /* setting the prescaler and divisor reg is common for all chips */ | 126 | /* setting the prescaler and divisor reg is common for all chips */ |
@@ -124,6 +133,65 @@ static inline void mpc52xx_set_divisor(struct mpc52xx_psc __iomem *psc, | |||
124 | out_8(&psc->ctlr, divisor & 0xff); | 133 | out_8(&psc->ctlr, divisor & 0xff); |
125 | } | 134 | } |
126 | 135 | ||
136 | static u16 mpc52xx_psc_get_status(struct uart_port *port) | ||
137 | { | ||
138 | return in_be16(&PSC(port)->mpc52xx_psc_status); | ||
139 | } | ||
140 | |||
141 | static u8 mpc52xx_psc_get_ipcr(struct uart_port *port) | ||
142 | { | ||
143 | return in_8(&PSC(port)->mpc52xx_psc_ipcr); | ||
144 | } | ||
145 | |||
146 | static void mpc52xx_psc_command(struct uart_port *port, u8 cmd) | ||
147 | { | ||
148 | out_8(&PSC(port)->command, cmd); | ||
149 | } | ||
150 | |||
151 | static void mpc52xx_psc_set_mode(struct uart_port *port, u8 mr1, u8 mr2) | ||
152 | { | ||
153 | out_8(&PSC(port)->command, MPC52xx_PSC_SEL_MODE_REG_1); | ||
154 | out_8(&PSC(port)->mode, mr1); | ||
155 | out_8(&PSC(port)->mode, mr2); | ||
156 | } | ||
157 | |||
158 | static void mpc52xx_psc_set_rts(struct uart_port *port, int state) | ||
159 | { | ||
160 | if (state) | ||
161 | out_8(&PSC(port)->op1, MPC52xx_PSC_OP_RTS); | ||
162 | else | ||
163 | out_8(&PSC(port)->op0, MPC52xx_PSC_OP_RTS); | ||
164 | } | ||
165 | |||
166 | static void mpc52xx_psc_enable_ms(struct uart_port *port) | ||
167 | { | ||
168 | struct mpc52xx_psc __iomem *psc = PSC(port); | ||
169 | |||
170 | /* clear D_*-bits by reading them */ | ||
171 | in_8(&psc->mpc52xx_psc_ipcr); | ||
172 | /* enable CTS and DCD as IPC interrupts */ | ||
173 | out_8(&psc->mpc52xx_psc_acr, MPC52xx_PSC_IEC_CTS | MPC52xx_PSC_IEC_DCD); | ||
174 | |||
175 | port->read_status_mask |= MPC52xx_PSC_IMR_IPC; | ||
176 | out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask); | ||
177 | } | ||
178 | |||
179 | static void mpc52xx_psc_set_sicr(struct uart_port *port, u32 val) | ||
180 | { | ||
181 | out_be32(&PSC(port)->sicr, val); | ||
182 | } | ||
183 | |||
184 | static void mpc52xx_psc_set_imr(struct uart_port *port, u16 val) | ||
185 | { | ||
186 | out_be16(&PSC(port)->mpc52xx_psc_imr, val); | ||
187 | } | ||
188 | |||
189 | static u8 mpc52xx_psc_get_mr1(struct uart_port *port) | ||
190 | { | ||
191 | out_8(&PSC(port)->command, MPC52xx_PSC_SEL_MODE_REG_1); | ||
192 | return in_8(&PSC(port)->mode); | ||
193 | } | ||
194 | |||
127 | #ifdef CONFIG_PPC_MPC52xx | 195 | #ifdef CONFIG_PPC_MPC52xx |
128 | #define FIFO_52xx(port) ((struct mpc52xx_psc_fifo __iomem *)(PSC(port)+1)) | 196 | #define FIFO_52xx(port) ((struct mpc52xx_psc_fifo __iomem *)(PSC(port)+1)) |
129 | static void mpc52xx_psc_fifo_init(struct uart_port *port) | 197 | static void mpc52xx_psc_fifo_init(struct uart_port *port) |
@@ -294,6 +362,15 @@ static struct psc_ops mpc52xx_psc_ops = { | |||
294 | .set_baudrate = mpc5200_psc_set_baudrate, | 362 | .set_baudrate = mpc5200_psc_set_baudrate, |
295 | .get_irq = mpc52xx_psc_get_irq, | 363 | .get_irq = mpc52xx_psc_get_irq, |
296 | .handle_irq = mpc52xx_psc_handle_irq, | 364 | .handle_irq = mpc52xx_psc_handle_irq, |
365 | .get_status = mpc52xx_psc_get_status, | ||
366 | .get_ipcr = mpc52xx_psc_get_ipcr, | ||
367 | .command = mpc52xx_psc_command, | ||
368 | .set_mode = mpc52xx_psc_set_mode, | ||
369 | .set_rts = mpc52xx_psc_set_rts, | ||
370 | .enable_ms = mpc52xx_psc_enable_ms, | ||
371 | .set_sicr = mpc52xx_psc_set_sicr, | ||
372 | .set_imr = mpc52xx_psc_set_imr, | ||
373 | .get_mr1 = mpc52xx_psc_get_mr1, | ||
297 | }; | 374 | }; |
298 | 375 | ||
299 | static struct psc_ops mpc5200b_psc_ops = { | 376 | static struct psc_ops mpc5200b_psc_ops = { |
@@ -315,6 +392,15 @@ static struct psc_ops mpc5200b_psc_ops = { | |||
315 | .set_baudrate = mpc5200b_psc_set_baudrate, | 392 | .set_baudrate = mpc5200b_psc_set_baudrate, |
316 | .get_irq = mpc52xx_psc_get_irq, | 393 | .get_irq = mpc52xx_psc_get_irq, |
317 | .handle_irq = mpc52xx_psc_handle_irq, | 394 | .handle_irq = mpc52xx_psc_handle_irq, |
395 | .get_status = mpc52xx_psc_get_status, | ||
396 | .get_ipcr = mpc52xx_psc_get_ipcr, | ||
397 | .command = mpc52xx_psc_command, | ||
398 | .set_mode = mpc52xx_psc_set_mode, | ||
399 | .set_rts = mpc52xx_psc_set_rts, | ||
400 | .enable_ms = mpc52xx_psc_enable_ms, | ||
401 | .set_sicr = mpc52xx_psc_set_sicr, | ||
402 | .set_imr = mpc52xx_psc_set_imr, | ||
403 | .get_mr1 = mpc52xx_psc_get_mr1, | ||
318 | }; | 404 | }; |
319 | 405 | ||
320 | #endif /* CONFIG_MPC52xx */ | 406 | #endif /* CONFIG_MPC52xx */ |
@@ -585,8 +671,18 @@ static struct psc_ops mpc512x_psc_ops = { | |||
585 | .fifoc_uninit = mpc512x_psc_fifoc_uninit, | 671 | .fifoc_uninit = mpc512x_psc_fifoc_uninit, |
586 | .get_irq = mpc512x_psc_get_irq, | 672 | .get_irq = mpc512x_psc_get_irq, |
587 | .handle_irq = mpc512x_psc_handle_irq, | 673 | .handle_irq = mpc512x_psc_handle_irq, |
674 | .get_status = mpc52xx_psc_get_status, | ||
675 | .get_ipcr = mpc52xx_psc_get_ipcr, | ||
676 | .command = mpc52xx_psc_command, | ||
677 | .set_mode = mpc52xx_psc_set_mode, | ||
678 | .set_rts = mpc52xx_psc_set_rts, | ||
679 | .enable_ms = mpc52xx_psc_enable_ms, | ||
680 | .set_sicr = mpc52xx_psc_set_sicr, | ||
681 | .set_imr = mpc52xx_psc_set_imr, | ||
682 | .get_mr1 = mpc52xx_psc_get_mr1, | ||
588 | }; | 683 | }; |
589 | #endif | 684 | #endif /* CONFIG_PPC_MPC512x */ |
685 | |||
590 | 686 | ||
591 | static const struct psc_ops *psc_ops; | 687 | static const struct psc_ops *psc_ops; |
592 | 688 | ||
@@ -603,17 +699,14 @@ mpc52xx_uart_tx_empty(struct uart_port *port) | |||
603 | static void | 699 | static void |
604 | mpc52xx_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) | 700 | mpc52xx_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) |
605 | { | 701 | { |
606 | if (mctrl & TIOCM_RTS) | 702 | psc_ops->set_rts(port, mctrl & TIOCM_RTS); |
607 | out_8(&PSC(port)->op1, MPC52xx_PSC_OP_RTS); | ||
608 | else | ||
609 | out_8(&PSC(port)->op0, MPC52xx_PSC_OP_RTS); | ||
610 | } | 703 | } |
611 | 704 | ||
612 | static unsigned int | 705 | static unsigned int |
613 | mpc52xx_uart_get_mctrl(struct uart_port *port) | 706 | mpc52xx_uart_get_mctrl(struct uart_port *port) |
614 | { | 707 | { |
615 | unsigned int ret = TIOCM_DSR; | 708 | unsigned int ret = TIOCM_DSR; |
616 | u8 status = in_8(&PSC(port)->mpc52xx_psc_ipcr); | 709 | u8 status = psc_ops->get_ipcr(port); |
617 | 710 | ||
618 | if (!(status & MPC52xx_PSC_CTS)) | 711 | if (!(status & MPC52xx_PSC_CTS)) |
619 | ret |= TIOCM_CTS; | 712 | ret |= TIOCM_CTS; |
@@ -663,15 +756,7 @@ mpc52xx_uart_stop_rx(struct uart_port *port) | |||
663 | static void | 756 | static void |
664 | mpc52xx_uart_enable_ms(struct uart_port *port) | 757 | mpc52xx_uart_enable_ms(struct uart_port *port) |
665 | { | 758 | { |
666 | struct mpc52xx_psc __iomem *psc = PSC(port); | 759 | psc_ops->enable_ms(port); |
667 | |||
668 | /* clear D_*-bits by reading them */ | ||
669 | in_8(&psc->mpc52xx_psc_ipcr); | ||
670 | /* enable CTS and DCD as IPC interrupts */ | ||
671 | out_8(&psc->mpc52xx_psc_acr, MPC52xx_PSC_IEC_CTS | MPC52xx_PSC_IEC_DCD); | ||
672 | |||
673 | port->read_status_mask |= MPC52xx_PSC_IMR_IPC; | ||
674 | out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask); | ||
675 | } | 760 | } |
676 | 761 | ||
677 | static void | 762 | static void |
@@ -681,9 +766,9 @@ mpc52xx_uart_break_ctl(struct uart_port *port, int ctl) | |||
681 | spin_lock_irqsave(&port->lock, flags); | 766 | spin_lock_irqsave(&port->lock, flags); |
682 | 767 | ||
683 | if (ctl == -1) | 768 | if (ctl == -1) |
684 | out_8(&PSC(port)->command, MPC52xx_PSC_START_BRK); | 769 | psc_ops->command(port, MPC52xx_PSC_START_BRK); |
685 | else | 770 | else |
686 | out_8(&PSC(port)->command, MPC52xx_PSC_STOP_BRK); | 771 | psc_ops->command(port, MPC52xx_PSC_STOP_BRK); |
687 | 772 | ||
688 | spin_unlock_irqrestore(&port->lock, flags); | 773 | spin_unlock_irqrestore(&port->lock, flags); |
689 | } | 774 | } |
@@ -691,7 +776,6 @@ mpc52xx_uart_break_ctl(struct uart_port *port, int ctl) | |||
691 | static int | 776 | static int |
692 | mpc52xx_uart_startup(struct uart_port *port) | 777 | mpc52xx_uart_startup(struct uart_port *port) |
693 | { | 778 | { |
694 | struct mpc52xx_psc __iomem *psc = PSC(port); | ||
695 | int ret; | 779 | int ret; |
696 | 780 | ||
697 | if (psc_ops->clock) { | 781 | if (psc_ops->clock) { |
@@ -707,15 +791,15 @@ mpc52xx_uart_startup(struct uart_port *port) | |||
707 | return ret; | 791 | return ret; |
708 | 792 | ||
709 | /* Reset/activate the port, clear and enable interrupts */ | 793 | /* Reset/activate the port, clear and enable interrupts */ |
710 | out_8(&psc->command, MPC52xx_PSC_RST_RX); | 794 | psc_ops->command(port, MPC52xx_PSC_RST_RX); |
711 | out_8(&psc->command, MPC52xx_PSC_RST_TX); | 795 | psc_ops->command(port, MPC52xx_PSC_RST_TX); |
712 | 796 | ||
713 | out_be32(&psc->sicr, 0); /* UART mode DCD ignored */ | 797 | psc_ops->set_sicr(port, 0); /* UART mode DCD ignored */ |
714 | 798 | ||
715 | psc_ops->fifo_init(port); | 799 | psc_ops->fifo_init(port); |
716 | 800 | ||
717 | out_8(&psc->command, MPC52xx_PSC_TX_ENABLE); | 801 | psc_ops->command(port, MPC52xx_PSC_TX_ENABLE); |
718 | out_8(&psc->command, MPC52xx_PSC_RX_ENABLE); | 802 | psc_ops->command(port, MPC52xx_PSC_RX_ENABLE); |
719 | 803 | ||
720 | return 0; | 804 | return 0; |
721 | } | 805 | } |
@@ -723,15 +807,13 @@ mpc52xx_uart_startup(struct uart_port *port) | |||
723 | static void | 807 | static void |
724 | mpc52xx_uart_shutdown(struct uart_port *port) | 808 | mpc52xx_uart_shutdown(struct uart_port *port) |
725 | { | 809 | { |
726 | struct mpc52xx_psc __iomem *psc = PSC(port); | ||
727 | |||
728 | /* Shut down the port. Leave TX active if on a console port */ | 810 | /* Shut down the port. Leave TX active if on a console port */ |
729 | out_8(&psc->command, MPC52xx_PSC_RST_RX); | 811 | psc_ops->command(port, MPC52xx_PSC_RST_RX); |
730 | if (!uart_console(port)) | 812 | if (!uart_console(port)) |
731 | out_8(&psc->command, MPC52xx_PSC_RST_TX); | 813 | psc_ops->command(port, MPC52xx_PSC_RST_TX); |
732 | 814 | ||
733 | port->read_status_mask = 0; | 815 | port->read_status_mask = 0; |
734 | out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask); | 816 | psc_ops->set_imr(port, port->read_status_mask); |
735 | 817 | ||
736 | if (psc_ops->clock) | 818 | if (psc_ops->clock) |
737 | psc_ops->clock(port, 0); | 819 | psc_ops->clock(port, 0); |
@@ -744,7 +826,6 @@ static void | |||
744 | mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new, | 826 | mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new, |
745 | struct ktermios *old) | 827 | struct ktermios *old) |
746 | { | 828 | { |
747 | struct mpc52xx_psc __iomem *psc = PSC(port); | ||
748 | unsigned long flags; | 829 | unsigned long flags; |
749 | unsigned char mr1, mr2; | 830 | unsigned char mr1, mr2; |
750 | unsigned int j; | 831 | unsigned int j; |
@@ -808,13 +889,11 @@ mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new, | |||
808 | "Some chars may have been lost.\n"); | 889 | "Some chars may have been lost.\n"); |
809 | 890 | ||
810 | /* Reset the TX & RX */ | 891 | /* Reset the TX & RX */ |
811 | out_8(&psc->command, MPC52xx_PSC_RST_RX); | 892 | psc_ops->command(port, MPC52xx_PSC_RST_RX); |
812 | out_8(&psc->command, MPC52xx_PSC_RST_TX); | 893 | psc_ops->command(port, MPC52xx_PSC_RST_TX); |
813 | 894 | ||
814 | /* Send new mode settings */ | 895 | /* Send new mode settings */ |
815 | out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1); | 896 | psc_ops->set_mode(port, mr1, mr2); |
816 | out_8(&psc->mode, mr1); | ||
817 | out_8(&psc->mode, mr2); | ||
818 | baud = psc_ops->set_baudrate(port, new, old); | 897 | baud = psc_ops->set_baudrate(port, new, old); |
819 | 898 | ||
820 | /* Update the per-port timeout */ | 899 | /* Update the per-port timeout */ |
@@ -824,8 +903,8 @@ mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new, | |||
824 | mpc52xx_uart_enable_ms(port); | 903 | mpc52xx_uart_enable_ms(port); |
825 | 904 | ||
826 | /* Reenable TX & RX */ | 905 | /* Reenable TX & RX */ |
827 | out_8(&psc->command, MPC52xx_PSC_TX_ENABLE); | 906 | psc_ops->command(port, MPC52xx_PSC_TX_ENABLE); |
828 | out_8(&psc->command, MPC52xx_PSC_RX_ENABLE); | 907 | psc_ops->command(port, MPC52xx_PSC_RX_ENABLE); |
829 | 908 | ||
830 | /* We're all set, release the lock */ | 909 | /* We're all set, release the lock */ |
831 | spin_unlock_irqrestore(&port->lock, flags); | 910 | spin_unlock_irqrestore(&port->lock, flags); |
@@ -953,7 +1032,7 @@ mpc52xx_uart_int_rx_chars(struct uart_port *port) | |||
953 | flag = TTY_NORMAL; | 1032 | flag = TTY_NORMAL; |
954 | port->icount.rx++; | 1033 | port->icount.rx++; |
955 | 1034 | ||
956 | status = in_be16(&PSC(port)->mpc52xx_psc_status); | 1035 | status = psc_ops->get_status(port); |
957 | 1036 | ||
958 | if (status & (MPC52xx_PSC_SR_PE | | 1037 | if (status & (MPC52xx_PSC_SR_PE | |
959 | MPC52xx_PSC_SR_FE | | 1038 | MPC52xx_PSC_SR_FE | |
@@ -973,7 +1052,7 @@ mpc52xx_uart_int_rx_chars(struct uart_port *port) | |||
973 | } | 1052 | } |
974 | 1053 | ||
975 | /* Clear error condition */ | 1054 | /* Clear error condition */ |
976 | out_8(&PSC(port)->command, MPC52xx_PSC_RST_ERR_STAT); | 1055 | psc_ops->command(port, MPC52xx_PSC_RST_ERR_STAT); |
977 | 1056 | ||
978 | } | 1057 | } |
979 | tty_insert_flip_char(tport, ch, flag); | 1058 | tty_insert_flip_char(tport, ch, flag); |
@@ -1056,7 +1135,7 @@ mpc5xxx_uart_process_int(struct uart_port *port) | |||
1056 | if (psc_ops->tx_rdy(port)) | 1135 | if (psc_ops->tx_rdy(port)) |
1057 | keepgoing |= mpc52xx_uart_int_tx_chars(port); | 1136 | keepgoing |= mpc52xx_uart_int_tx_chars(port); |
1058 | 1137 | ||
1059 | status = in_8(&PSC(port)->mpc52xx_psc_ipcr); | 1138 | status = psc_ops->get_ipcr(port); |
1060 | if (status & MPC52xx_PSC_D_DCD) | 1139 | if (status & MPC52xx_PSC_D_DCD) |
1061 | uart_handle_dcd_change(port, !(status & MPC52xx_PSC_DCD)); | 1140 | uart_handle_dcd_change(port, !(status & MPC52xx_PSC_DCD)); |
1062 | 1141 | ||
@@ -1097,14 +1176,12 @@ static void __init | |||
1097 | mpc52xx_console_get_options(struct uart_port *port, | 1176 | mpc52xx_console_get_options(struct uart_port *port, |
1098 | int *baud, int *parity, int *bits, int *flow) | 1177 | int *baud, int *parity, int *bits, int *flow) |
1099 | { | 1178 | { |
1100 | struct mpc52xx_psc __iomem *psc = PSC(port); | ||
1101 | unsigned char mr1; | 1179 | unsigned char mr1; |
1102 | 1180 | ||
1103 | pr_debug("mpc52xx_console_get_options(port=%p)\n", port); | 1181 | pr_debug("mpc52xx_console_get_options(port=%p)\n", port); |
1104 | 1182 | ||
1105 | /* Read the mode registers */ | 1183 | /* Read the mode registers */ |
1106 | out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1); | 1184 | mr1 = psc_ops->get_mr1(port); |
1107 | mr1 = in_8(&psc->mode); | ||
1108 | 1185 | ||
1109 | /* CT{U,L}R are write-only ! */ | 1186 | /* CT{U,L}R are write-only ! */ |
1110 | *baud = CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD; | 1187 | *baud = CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD; |