diff options
author | Paul Mundt <lethal@linux-sh.org> | 2009-05-22 00:29:37 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2009-05-22 00:29:37 -0400 |
commit | 5f8371cec93b94a24a55ba1de642ce6eade6d62c (patch) | |
tree | 61b6d2acb10226b3c0f2d31bda3a49288e540eba /drivers/serial | |
parent | 8e9bb19ef97d6594e735bee64b6d72103e350854 (diff) | |
parent | d8586ba6e1415150e1bab89f0a05447bb6f2d6d5 (diff) |
Merge branches 'sh/stable-updates' and 'sh/sparseirq'
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/sh-sci.c | 385 | ||||
-rw-r--r-- | drivers/serial/sh-sci.h | 42 |
2 files changed, 248 insertions, 179 deletions
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index dbf5357a77b3..4e3248d58602 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c | |||
@@ -47,12 +47,17 @@ | |||
47 | #include <linux/clk.h> | 47 | #include <linux/clk.h> |
48 | #include <linux/ctype.h> | 48 | #include <linux/ctype.h> |
49 | #include <linux/err.h> | 49 | #include <linux/err.h> |
50 | #include <linux/list.h> | ||
50 | 51 | ||
51 | #ifdef CONFIG_SUPERH | 52 | #ifdef CONFIG_SUPERH |
52 | #include <asm/clock.h> | 53 | #include <asm/clock.h> |
53 | #include <asm/sh_bios.h> | 54 | #include <asm/sh_bios.h> |
54 | #endif | 55 | #endif |
55 | 56 | ||
57 | #ifdef CONFIG_H8300 | ||
58 | #include <asm/gpio.h> | ||
59 | #endif | ||
60 | |||
56 | #include "sh-sci.h" | 61 | #include "sh-sci.h" |
57 | 62 | ||
58 | struct sci_port { | 63 | struct sci_port { |
@@ -75,14 +80,22 @@ struct sci_port { | |||
75 | int break_flag; | 80 | int break_flag; |
76 | 81 | ||
77 | #ifdef CONFIG_HAVE_CLK | 82 | #ifdef CONFIG_HAVE_CLK |
78 | /* Port clock */ | 83 | /* Interface clock */ |
79 | struct clk *clk; | 84 | struct clk *iclk; |
85 | /* Data clock */ | ||
86 | struct clk *dclk; | ||
80 | #endif | 87 | #endif |
88 | struct list_head node; | ||
81 | }; | 89 | }; |
82 | 90 | ||
83 | #ifdef CONFIG_SERIAL_SH_SCI_CONSOLE | 91 | struct sh_sci_priv { |
84 | static struct sci_port *serial_console_port; | 92 | spinlock_t lock; |
93 | struct list_head ports; | ||
94 | |||
95 | #ifdef CONFIG_HAVE_CLK | ||
96 | struct notifier_block clk_nb; | ||
85 | #endif | 97 | #endif |
98 | }; | ||
86 | 99 | ||
87 | /* Function prototypes */ | 100 | /* Function prototypes */ |
88 | static void sci_stop_tx(struct uart_port *port); | 101 | static void sci_stop_tx(struct uart_port *port); |
@@ -159,12 +172,12 @@ static void h8300_sci_config(struct uart_port *port, unsigned int ctrl) | |||
159 | *mstpcrl &= ~mask; | 172 | *mstpcrl &= ~mask; |
160 | } | 173 | } |
161 | 174 | ||
162 | static inline void h8300_sci_enable(struct uart_port *port) | 175 | static void h8300_sci_enable(struct uart_port *port) |
163 | { | 176 | { |
164 | h8300_sci_config(port, sci_enable); | 177 | h8300_sci_config(port, sci_enable); |
165 | } | 178 | } |
166 | 179 | ||
167 | static inline void h8300_sci_disable(struct uart_port *port) | 180 | static void h8300_sci_disable(struct uart_port *port) |
168 | { | 181 | { |
169 | h8300_sci_config(port, sci_disable); | 182 | h8300_sci_config(port, sci_disable); |
170 | } | 183 | } |
@@ -611,7 +624,7 @@ static inline int sci_handle_breaks(struct uart_port *port) | |||
611 | int copied = 0; | 624 | int copied = 0; |
612 | unsigned short status = sci_in(port, SCxSR); | 625 | unsigned short status = sci_in(port, SCxSR); |
613 | struct tty_struct *tty = port->info->port.tty; | 626 | struct tty_struct *tty = port->info->port.tty; |
614 | struct sci_port *s = &sci_ports[port->line]; | 627 | struct sci_port *s = to_sci_port(port); |
615 | 628 | ||
616 | if (uart_handle_break(port)) | 629 | if (uart_handle_break(port)) |
617 | return 0; | 630 | return 0; |
@@ -726,19 +739,43 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr) | |||
726 | static int sci_notifier(struct notifier_block *self, | 739 | static int sci_notifier(struct notifier_block *self, |
727 | unsigned long phase, void *p) | 740 | unsigned long phase, void *p) |
728 | { | 741 | { |
729 | int i; | 742 | struct sh_sci_priv *priv = container_of(self, |
743 | struct sh_sci_priv, clk_nb); | ||
744 | struct sci_port *sci_port; | ||
745 | unsigned long flags; | ||
730 | 746 | ||
731 | if ((phase == CPUFREQ_POSTCHANGE) || | 747 | if ((phase == CPUFREQ_POSTCHANGE) || |
732 | (phase == CPUFREQ_RESUMECHANGE)) | 748 | (phase == CPUFREQ_RESUMECHANGE)) { |
733 | for (i = 0; i < SCI_NPORTS; i++) { | 749 | spin_lock_irqsave(&priv->lock, flags); |
734 | struct sci_port *s = &sci_ports[i]; | 750 | list_for_each_entry(sci_port, &priv->ports, node) |
735 | s->port.uartclk = clk_get_rate(s->clk); | 751 | sci_port->port.uartclk = clk_get_rate(sci_port->dclk); |
736 | } | 752 | |
753 | spin_unlock_irqrestore(&priv->lock, flags); | ||
754 | } | ||
737 | 755 | ||
738 | return NOTIFY_OK; | 756 | return NOTIFY_OK; |
739 | } | 757 | } |
740 | 758 | ||
741 | static struct notifier_block sci_nb = { &sci_notifier, NULL, 0 }; | 759 | static void sci_clk_enable(struct uart_port *port) |
760 | { | ||
761 | struct sci_port *sci_port = to_sci_port(port); | ||
762 | |||
763 | clk_enable(sci_port->dclk); | ||
764 | sci_port->port.uartclk = clk_get_rate(sci_port->dclk); | ||
765 | |||
766 | if (sci_port->iclk) | ||
767 | clk_enable(sci_port->iclk); | ||
768 | } | ||
769 | |||
770 | static void sci_clk_disable(struct uart_port *port) | ||
771 | { | ||
772 | struct sci_port *sci_port = to_sci_port(port); | ||
773 | |||
774 | if (sci_port->iclk) | ||
775 | clk_disable(sci_port->iclk); | ||
776 | |||
777 | clk_disable(sci_port->dclk); | ||
778 | } | ||
742 | #endif | 779 | #endif |
743 | 780 | ||
744 | static int sci_request_irq(struct sci_port *port) | 781 | static int sci_request_irq(struct sci_port *port) |
@@ -865,15 +902,11 @@ static void sci_break_ctl(struct uart_port *port, int break_state) | |||
865 | 902 | ||
866 | static int sci_startup(struct uart_port *port) | 903 | static int sci_startup(struct uart_port *port) |
867 | { | 904 | { |
868 | struct sci_port *s = &sci_ports[port->line]; | 905 | struct sci_port *s = to_sci_port(port); |
869 | 906 | ||
870 | if (s->enable) | 907 | if (s->enable) |
871 | s->enable(port); | 908 | s->enable(port); |
872 | 909 | ||
873 | #ifdef CONFIG_HAVE_CLK | ||
874 | s->clk = clk_get(NULL, "module_clk"); | ||
875 | #endif | ||
876 | |||
877 | sci_request_irq(s); | 910 | sci_request_irq(s); |
878 | sci_start_tx(port); | 911 | sci_start_tx(port); |
879 | sci_start_rx(port, 1); | 912 | sci_start_rx(port, 1); |
@@ -883,7 +916,7 @@ static int sci_startup(struct uart_port *port) | |||
883 | 916 | ||
884 | static void sci_shutdown(struct uart_port *port) | 917 | static void sci_shutdown(struct uart_port *port) |
885 | { | 918 | { |
886 | struct sci_port *s = &sci_ports[port->line]; | 919 | struct sci_port *s = to_sci_port(port); |
887 | 920 | ||
888 | sci_stop_rx(port); | 921 | sci_stop_rx(port); |
889 | sci_stop_tx(port); | 922 | sci_stop_tx(port); |
@@ -891,11 +924,6 @@ static void sci_shutdown(struct uart_port *port) | |||
891 | 924 | ||
892 | if (s->disable) | 925 | if (s->disable) |
893 | s->disable(port); | 926 | s->disable(port); |
894 | |||
895 | #ifdef CONFIG_HAVE_CLK | ||
896 | clk_put(s->clk); | ||
897 | s->clk = NULL; | ||
898 | #endif | ||
899 | } | 927 | } |
900 | 928 | ||
901 | static void sci_set_termios(struct uart_port *port, struct ktermios *termios, | 929 | static void sci_set_termios(struct uart_port *port, struct ktermios *termios, |
@@ -980,25 +1008,31 @@ static int sci_request_port(struct uart_port *port) | |||
980 | 1008 | ||
981 | static void sci_config_port(struct uart_port *port, int flags) | 1009 | static void sci_config_port(struct uart_port *port, int flags) |
982 | { | 1010 | { |
983 | struct sci_port *s = &sci_ports[port->line]; | 1011 | struct sci_port *s = to_sci_port(port); |
984 | 1012 | ||
985 | port->type = s->type; | 1013 | port->type = s->type; |
986 | 1014 | ||
987 | if (port->flags & UPF_IOREMAP && !port->membase) { | 1015 | if (port->membase) |
988 | #if defined(CONFIG_SUPERH64) | 1016 | return; |
989 | port->mapbase = onchip_remap(SCIF_ADDR_SH5, 1024, "SCIF"); | 1017 | |
990 | port->membase = (void __iomem *)port->mapbase; | 1018 | if (port->flags & UPF_IOREMAP) { |
991 | #else | ||
992 | port->membase = ioremap_nocache(port->mapbase, 0x40); | 1019 | port->membase = ioremap_nocache(port->mapbase, 0x40); |
993 | #endif | ||
994 | 1020 | ||
995 | dev_err(port->dev, "can't remap port#%d\n", port->line); | 1021 | if (IS_ERR(port->membase)) |
1022 | dev_err(port->dev, "can't remap port#%d\n", port->line); | ||
1023 | } else { | ||
1024 | /* | ||
1025 | * For the simple (and majority of) cases where we don't | ||
1026 | * need to do any remapping, just cast the cookie | ||
1027 | * directly. | ||
1028 | */ | ||
1029 | port->membase = (void __iomem *)port->mapbase; | ||
996 | } | 1030 | } |
997 | } | 1031 | } |
998 | 1032 | ||
999 | static int sci_verify_port(struct uart_port *port, struct serial_struct *ser) | 1033 | static int sci_verify_port(struct uart_port *port, struct serial_struct *ser) |
1000 | { | 1034 | { |
1001 | struct sci_port *s = &sci_ports[port->line]; | 1035 | struct sci_port *s = to_sci_port(port); |
1002 | 1036 | ||
1003 | if (ser->irq != s->irqs[SCIx_TXI_IRQ] || ser->irq > nr_irqs) | 1037 | if (ser->irq != s->irqs[SCIx_TXI_IRQ] || ser->irq > nr_irqs) |
1004 | return -EINVAL; | 1038 | return -EINVAL; |
@@ -1032,63 +1066,60 @@ static struct uart_ops sci_uart_ops = { | |||
1032 | #endif | 1066 | #endif |
1033 | }; | 1067 | }; |
1034 | 1068 | ||
1035 | static void __init sci_init_ports(void) | 1069 | static void __devinit sci_init_single(struct platform_device *dev, |
1070 | struct sci_port *sci_port, | ||
1071 | unsigned int index, | ||
1072 | struct plat_sci_port *p) | ||
1036 | { | 1073 | { |
1037 | static int first = 1; | 1074 | sci_port->port.ops = &sci_uart_ops; |
1038 | int i; | 1075 | sci_port->port.iotype = UPIO_MEM; |
1039 | 1076 | sci_port->port.line = index; | |
1040 | if (!first) | 1077 | sci_port->port.fifosize = 1; |
1041 | return; | ||
1042 | |||
1043 | first = 0; | ||
1044 | |||
1045 | for (i = 0; i < SCI_NPORTS; i++) { | ||
1046 | sci_ports[i].port.ops = &sci_uart_ops; | ||
1047 | sci_ports[i].port.iotype = UPIO_MEM; | ||
1048 | sci_ports[i].port.line = i; | ||
1049 | sci_ports[i].port.fifosize = 1; | ||
1050 | 1078 | ||
1051 | #if defined(__H8300H__) || defined(__H8300S__) | 1079 | #if defined(__H8300H__) || defined(__H8300S__) |
1052 | #ifdef __H8300S__ | 1080 | #ifdef __H8300S__ |
1053 | sci_ports[i].enable = h8300_sci_enable; | 1081 | sci_port->enable = h8300_sci_enable; |
1054 | sci_ports[i].disable = h8300_sci_disable; | 1082 | sci_port->disable = h8300_sci_disable; |
1055 | #endif | 1083 | #endif |
1056 | sci_ports[i].port.uartclk = CONFIG_CPU_CLOCK; | 1084 | sci_port->port.uartclk = CONFIG_CPU_CLOCK; |
1057 | #elif defined(CONFIG_HAVE_CLK) | 1085 | #elif defined(CONFIG_HAVE_CLK) |
1058 | /* | 1086 | sci_port->iclk = p->clk ? clk_get(&dev->dev, p->clk) : NULL; |
1059 | * XXX: We should use a proper SCI/SCIF clock | 1087 | sci_port->dclk = clk_get(&dev->dev, "module_clk"); |
1060 | */ | 1088 | sci_port->enable = sci_clk_enable; |
1061 | { | 1089 | sci_port->disable = sci_clk_disable; |
1062 | struct clk *clk = clk_get(NULL, "module_clk"); | ||
1063 | sci_ports[i].port.uartclk = clk_get_rate(clk); | ||
1064 | clk_put(clk); | ||
1065 | } | ||
1066 | #else | 1090 | #else |
1067 | #error "Need a valid uartclk" | 1091 | #error "Need a valid uartclk" |
1068 | #endif | 1092 | #endif |
1069 | 1093 | ||
1070 | sci_ports[i].break_timer.data = (unsigned long)&sci_ports[i]; | 1094 | sci_port->break_timer.data = (unsigned long)sci_port; |
1071 | sci_ports[i].break_timer.function = sci_break_timer; | 1095 | sci_port->break_timer.function = sci_break_timer; |
1072 | 1096 | init_timer(&sci_port->break_timer); | |
1073 | init_timer(&sci_ports[i].break_timer); | ||
1074 | } | ||
1075 | } | ||
1076 | 1097 | ||
1077 | int __init early_sci_setup(struct uart_port *port) | 1098 | sci_port->port.mapbase = p->mapbase; |
1078 | { | 1099 | sci_port->port.membase = p->membase; |
1079 | if (unlikely(port->line > SCI_NPORTS)) | ||
1080 | return -ENODEV; | ||
1081 | 1100 | ||
1082 | sci_init_ports(); | 1101 | sci_port->port.irq = p->irqs[SCIx_TXI_IRQ]; |
1102 | sci_port->port.flags = p->flags; | ||
1103 | sci_port->port.dev = &dev->dev; | ||
1104 | sci_port->type = sci_port->port.type = p->type; | ||
1083 | 1105 | ||
1084 | sci_ports[port->line].port.membase = port->membase; | 1106 | memcpy(&sci_port->irqs, &p->irqs, sizeof(p->irqs)); |
1085 | sci_ports[port->line].port.mapbase = port->mapbase; | ||
1086 | sci_ports[port->line].port.type = port->type; | ||
1087 | 1107 | ||
1088 | return 0; | ||
1089 | } | 1108 | } |
1090 | 1109 | ||
1091 | #ifdef CONFIG_SERIAL_SH_SCI_CONSOLE | 1110 | #ifdef CONFIG_SERIAL_SH_SCI_CONSOLE |
1111 | static struct tty_driver *serial_console_device(struct console *co, int *index) | ||
1112 | { | ||
1113 | struct uart_driver *p = &sci_uart_driver; | ||
1114 | *index = co->index; | ||
1115 | return p->tty_driver; | ||
1116 | } | ||
1117 | |||
1118 | static void serial_console_putchar(struct uart_port *port, int ch) | ||
1119 | { | ||
1120 | sci_poll_put_char(port, ch); | ||
1121 | } | ||
1122 | |||
1092 | /* | 1123 | /* |
1093 | * Print a string to the serial port trying not to disturb | 1124 | * Print a string to the serial port trying not to disturb |
1094 | * any possible real use of the port... | 1125 | * any possible real use of the port... |
@@ -1096,25 +1127,27 @@ int __init early_sci_setup(struct uart_port *port) | |||
1096 | static void serial_console_write(struct console *co, const char *s, | 1127 | static void serial_console_write(struct console *co, const char *s, |
1097 | unsigned count) | 1128 | unsigned count) |
1098 | { | 1129 | { |
1099 | struct uart_port *port = &serial_console_port->port; | 1130 | struct uart_port *port = co->data; |
1131 | struct sci_port *sci_port = to_sci_port(port); | ||
1100 | unsigned short bits; | 1132 | unsigned short bits; |
1101 | int i; | ||
1102 | 1133 | ||
1103 | for (i = 0; i < count; i++) { | 1134 | if (sci_port->enable) |
1104 | if (*s == 10) | 1135 | sci_port->enable(port); |
1105 | sci_poll_put_char(port, '\r'); | ||
1106 | 1136 | ||
1107 | sci_poll_put_char(port, *s++); | 1137 | uart_console_write(port, s, count, serial_console_putchar); |
1108 | } | ||
1109 | 1138 | ||
1110 | /* wait until fifo is empty and last bit has been transmitted */ | 1139 | /* wait until fifo is empty and last bit has been transmitted */ |
1111 | bits = SCxSR_TDxE(port) | SCxSR_TEND(port); | 1140 | bits = SCxSR_TDxE(port) | SCxSR_TEND(port); |
1112 | while ((sci_in(port, SCxSR) & bits) != bits) | 1141 | while ((sci_in(port, SCxSR) & bits) != bits) |
1113 | cpu_relax(); | 1142 | cpu_relax(); |
1143 | |||
1144 | if (sci_port->disable); | ||
1145 | sci_port->disable(port); | ||
1114 | } | 1146 | } |
1115 | 1147 | ||
1116 | static int __init serial_console_setup(struct console *co, char *options) | 1148 | static int __init serial_console_setup(struct console *co, char *options) |
1117 | { | 1149 | { |
1150 | struct sci_port *sci_port; | ||
1118 | struct uart_port *port; | 1151 | struct uart_port *port; |
1119 | int baud = 115200; | 1152 | int baud = 115200; |
1120 | int bits = 8; | 1153 | int bits = 8; |
@@ -1130,8 +1163,9 @@ static int __init serial_console_setup(struct console *co, char *options) | |||
1130 | if (co->index >= SCI_NPORTS) | 1163 | if (co->index >= SCI_NPORTS) |
1131 | co->index = 0; | 1164 | co->index = 0; |
1132 | 1165 | ||
1133 | serial_console_port = &sci_ports[co->index]; | 1166 | sci_port = &sci_ports[co->index]; |
1134 | port = &serial_console_port->port; | 1167 | port = &sci_port->port; |
1168 | co->data = port; | ||
1135 | 1169 | ||
1136 | /* | 1170 | /* |
1137 | * Also need to check port->type, we don't actually have any | 1171 | * Also need to check port->type, we don't actually have any |
@@ -1141,21 +1175,11 @@ static int __init serial_console_setup(struct console *co, char *options) | |||
1141 | */ | 1175 | */ |
1142 | if (!port->type) | 1176 | if (!port->type) |
1143 | return -ENODEV; | 1177 | return -ENODEV; |
1144 | if (!port->membase || !port->mapbase) | ||
1145 | return -ENODEV; | ||
1146 | |||
1147 | port->type = serial_console_port->type; | ||
1148 | |||
1149 | #ifdef CONFIG_HAVE_CLK | ||
1150 | if (!serial_console_port->clk) | ||
1151 | serial_console_port->clk = clk_get(NULL, "module_clk"); | ||
1152 | #endif | ||
1153 | 1178 | ||
1154 | if (port->flags & UPF_IOREMAP) | 1179 | sci_config_port(port, 0); |
1155 | sci_config_port(port, 0); | ||
1156 | 1180 | ||
1157 | if (serial_console_port->enable) | 1181 | if (sci_port->enable) |
1158 | serial_console_port->enable(port); | 1182 | sci_port->enable(port); |
1159 | 1183 | ||
1160 | if (options) | 1184 | if (options) |
1161 | uart_parse_options(options, &baud, &parity, &bits, &flow); | 1185 | uart_parse_options(options, &baud, &parity, &bits, &flow); |
@@ -1166,22 +1190,21 @@ static int __init serial_console_setup(struct console *co, char *options) | |||
1166 | if (ret == 0) | 1190 | if (ret == 0) |
1167 | sci_stop_rx(port); | 1191 | sci_stop_rx(port); |
1168 | #endif | 1192 | #endif |
1193 | /* TODO: disable clock */ | ||
1169 | return ret; | 1194 | return ret; |
1170 | } | 1195 | } |
1171 | 1196 | ||
1172 | static struct console serial_console = { | 1197 | static struct console serial_console = { |
1173 | .name = "ttySC", | 1198 | .name = "ttySC", |
1174 | .device = uart_console_device, | 1199 | .device = serial_console_device, |
1175 | .write = serial_console_write, | 1200 | .write = serial_console_write, |
1176 | .setup = serial_console_setup, | 1201 | .setup = serial_console_setup, |
1177 | .flags = CON_PRINTBUFFER, | 1202 | .flags = CON_PRINTBUFFER, |
1178 | .index = -1, | 1203 | .index = -1, |
1179 | .data = &sci_uart_driver, | ||
1180 | }; | 1204 | }; |
1181 | 1205 | ||
1182 | static int __init sci_console_init(void) | 1206 | static int __init sci_console_init(void) |
1183 | { | 1207 | { |
1184 | sci_init_ports(); | ||
1185 | register_console(&serial_console); | 1208 | register_console(&serial_console); |
1186 | return 0; | 1209 | return 0; |
1187 | } | 1210 | } |
@@ -1207,6 +1230,61 @@ static struct uart_driver sci_uart_driver = { | |||
1207 | .cons = SCI_CONSOLE, | 1230 | .cons = SCI_CONSOLE, |
1208 | }; | 1231 | }; |
1209 | 1232 | ||
1233 | |||
1234 | static int sci_remove(struct platform_device *dev) | ||
1235 | { | ||
1236 | struct sh_sci_priv *priv = platform_get_drvdata(dev); | ||
1237 | struct sci_port *p; | ||
1238 | unsigned long flags; | ||
1239 | |||
1240 | #ifdef CONFIG_HAVE_CLK | ||
1241 | cpufreq_unregister_notifier(&priv->clk_nb, CPUFREQ_TRANSITION_NOTIFIER); | ||
1242 | #endif | ||
1243 | |||
1244 | spin_lock_irqsave(&priv->lock, flags); | ||
1245 | list_for_each_entry(p, &priv->ports, node) | ||
1246 | uart_remove_one_port(&sci_uart_driver, &p->port); | ||
1247 | |||
1248 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1249 | |||
1250 | kfree(priv); | ||
1251 | return 0; | ||
1252 | } | ||
1253 | |||
1254 | static int __devinit sci_probe_single(struct platform_device *dev, | ||
1255 | unsigned int index, | ||
1256 | struct plat_sci_port *p, | ||
1257 | struct sci_port *sciport) | ||
1258 | { | ||
1259 | struct sh_sci_priv *priv = platform_get_drvdata(dev); | ||
1260 | unsigned long flags; | ||
1261 | int ret; | ||
1262 | |||
1263 | /* Sanity check */ | ||
1264 | if (unlikely(index >= SCI_NPORTS)) { | ||
1265 | dev_notice(&dev->dev, "Attempting to register port " | ||
1266 | "%d when only %d are available.\n", | ||
1267 | index+1, SCI_NPORTS); | ||
1268 | dev_notice(&dev->dev, "Consider bumping " | ||
1269 | "CONFIG_SERIAL_SH_SCI_NR_UARTS!\n"); | ||
1270 | return 0; | ||
1271 | } | ||
1272 | |||
1273 | sci_init_single(dev, sciport, index, p); | ||
1274 | |||
1275 | ret = uart_add_one_port(&sci_uart_driver, &sciport->port); | ||
1276 | if (ret) | ||
1277 | return ret; | ||
1278 | |||
1279 | INIT_LIST_HEAD(&sciport->node); | ||
1280 | |||
1281 | spin_lock_irqsave(&priv->lock, flags); | ||
1282 | list_add(&sciport->node, &priv->ports); | ||
1283 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1284 | |||
1285 | return 0; | ||
1286 | } | ||
1287 | |||
1210 | /* | 1288 | /* |
1211 | * Register a set of serial devices attached to a platform device. The | 1289 | * Register a set of serial devices attached to a platform device. The |
1212 | * list is terminated with a zero flags entry, which means we expect | 1290 | * list is terminated with a zero flags entry, which means we expect |
@@ -1216,57 +1294,34 @@ static struct uart_driver sci_uart_driver = { | |||
1216 | static int __devinit sci_probe(struct platform_device *dev) | 1294 | static int __devinit sci_probe(struct platform_device *dev) |
1217 | { | 1295 | { |
1218 | struct plat_sci_port *p = dev->dev.platform_data; | 1296 | struct plat_sci_port *p = dev->dev.platform_data; |
1297 | struct sh_sci_priv *priv; | ||
1219 | int i, ret = -EINVAL; | 1298 | int i, ret = -EINVAL; |
1220 | 1299 | ||
1221 | for (i = 0; p && p->flags != 0; p++, i++) { | 1300 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); |
1222 | struct sci_port *sciport = &sci_ports[i]; | 1301 | if (!priv) |
1302 | return -ENOMEM; | ||
1223 | 1303 | ||
1224 | /* Sanity check */ | 1304 | INIT_LIST_HEAD(&priv->ports); |
1225 | if (unlikely(i == SCI_NPORTS)) { | 1305 | spin_lock_init(&priv->lock); |
1226 | dev_notice(&dev->dev, "Attempting to register port " | 1306 | platform_set_drvdata(dev, priv); |
1227 | "%d when only %d are available.\n", | ||
1228 | i+1, SCI_NPORTS); | ||
1229 | dev_notice(&dev->dev, "Consider bumping " | ||
1230 | "CONFIG_SERIAL_SH_SCI_NR_UARTS!\n"); | ||
1231 | break; | ||
1232 | } | ||
1233 | 1307 | ||
1234 | sciport->port.mapbase = p->mapbase; | 1308 | #ifdef CONFIG_HAVE_CLK |
1309 | priv->clk_nb.notifier_call = sci_notifier; | ||
1310 | cpufreq_register_notifier(&priv->clk_nb, CPUFREQ_TRANSITION_NOTIFIER); | ||
1311 | #endif | ||
1235 | 1312 | ||
1236 | if (p->mapbase && !p->membase) { | 1313 | if (dev->id != -1) { |
1237 | if (p->flags & UPF_IOREMAP) { | 1314 | ret = sci_probe_single(dev, dev->id, p, &sci_ports[dev->id]); |
1238 | p->membase = ioremap_nocache(p->mapbase, 0x40); | 1315 | if (ret) |
1239 | if (IS_ERR(p->membase)) { | 1316 | goto err_unreg; |
1240 | ret = PTR_ERR(p->membase); | 1317 | } else { |
1241 | goto err_unreg; | 1318 | for (i = 0; p && p->flags != 0; p++, i++) { |
1242 | } | 1319 | ret = sci_probe_single(dev, i, p, &sci_ports[i]); |
1243 | } else { | 1320 | if (ret) |
1244 | /* | 1321 | goto err_unreg; |
1245 | * For the simple (and majority of) cases | ||
1246 | * where we don't need to do any remapping, | ||
1247 | * just cast the cookie directly. | ||
1248 | */ | ||
1249 | p->membase = (void __iomem *)p->mapbase; | ||
1250 | } | ||
1251 | } | 1322 | } |
1252 | |||
1253 | sciport->port.membase = p->membase; | ||
1254 | |||
1255 | sciport->port.irq = p->irqs[SCIx_TXI_IRQ]; | ||
1256 | sciport->port.flags = p->flags; | ||
1257 | sciport->port.dev = &dev->dev; | ||
1258 | |||
1259 | sciport->type = sciport->port.type = p->type; | ||
1260 | |||
1261 | memcpy(&sciport->irqs, &p->irqs, sizeof(p->irqs)); | ||
1262 | |||
1263 | uart_add_one_port(&sci_uart_driver, &sciport->port); | ||
1264 | } | 1323 | } |
1265 | 1324 | ||
1266 | #ifdef CONFIG_HAVE_CLK | ||
1267 | cpufreq_register_notifier(&sci_nb, CPUFREQ_TRANSITION_NOTIFIER); | ||
1268 | #endif | ||
1269 | |||
1270 | #ifdef CONFIG_SH_STANDARD_BIOS | 1325 | #ifdef CONFIG_SH_STANDARD_BIOS |
1271 | sh_bios_gdb_detach(); | 1326 | sh_bios_gdb_detach(); |
1272 | #endif | 1327 | #endif |
@@ -1274,50 +1329,36 @@ static int __devinit sci_probe(struct platform_device *dev) | |||
1274 | return 0; | 1329 | return 0; |
1275 | 1330 | ||
1276 | err_unreg: | 1331 | err_unreg: |
1277 | for (i = i - 1; i >= 0; i--) | 1332 | sci_remove(dev); |
1278 | uart_remove_one_port(&sci_uart_driver, &sci_ports[i].port); | ||
1279 | |||
1280 | return ret; | 1333 | return ret; |
1281 | } | 1334 | } |
1282 | 1335 | ||
1283 | static int __devexit sci_remove(struct platform_device *dev) | ||
1284 | { | ||
1285 | int i; | ||
1286 | |||
1287 | #ifdef CONFIG_HAVE_CLK | ||
1288 | cpufreq_unregister_notifier(&sci_nb, CPUFREQ_TRANSITION_NOTIFIER); | ||
1289 | #endif | ||
1290 | |||
1291 | for (i = 0; i < SCI_NPORTS; i++) | ||
1292 | uart_remove_one_port(&sci_uart_driver, &sci_ports[i].port); | ||
1293 | |||
1294 | return 0; | ||
1295 | } | ||
1296 | |||
1297 | static int sci_suspend(struct platform_device *dev, pm_message_t state) | 1336 | static int sci_suspend(struct platform_device *dev, pm_message_t state) |
1298 | { | 1337 | { |
1299 | int i; | 1338 | struct sh_sci_priv *priv = platform_get_drvdata(dev); |
1339 | struct sci_port *p; | ||
1340 | unsigned long flags; | ||
1300 | 1341 | ||
1301 | for (i = 0; i < SCI_NPORTS; i++) { | 1342 | spin_lock_irqsave(&priv->lock, flags); |
1302 | struct sci_port *p = &sci_ports[i]; | 1343 | list_for_each_entry(p, &priv->ports, node) |
1344 | uart_suspend_port(&sci_uart_driver, &p->port); | ||
1303 | 1345 | ||
1304 | if (p->type != PORT_UNKNOWN && p->port.dev == &dev->dev) | 1346 | spin_unlock_irqrestore(&priv->lock, flags); |
1305 | uart_suspend_port(&sci_uart_driver, &p->port); | ||
1306 | } | ||
1307 | 1347 | ||
1308 | return 0; | 1348 | return 0; |
1309 | } | 1349 | } |
1310 | 1350 | ||
1311 | static int sci_resume(struct platform_device *dev) | 1351 | static int sci_resume(struct platform_device *dev) |
1312 | { | 1352 | { |
1313 | int i; | 1353 | struct sh_sci_priv *priv = platform_get_drvdata(dev); |
1354 | struct sci_port *p; | ||
1355 | unsigned long flags; | ||
1314 | 1356 | ||
1315 | for (i = 0; i < SCI_NPORTS; i++) { | 1357 | spin_lock_irqsave(&priv->lock, flags); |
1316 | struct sci_port *p = &sci_ports[i]; | 1358 | list_for_each_entry(p, &priv->ports, node) |
1359 | uart_resume_port(&sci_uart_driver, &p->port); | ||
1317 | 1360 | ||
1318 | if (p->type != PORT_UNKNOWN && p->port.dev == &dev->dev) | 1361 | spin_unlock_irqrestore(&priv->lock, flags); |
1319 | uart_resume_port(&sci_uart_driver, &p->port); | ||
1320 | } | ||
1321 | 1362 | ||
1322 | return 0; | 1363 | return 0; |
1323 | } | 1364 | } |
@@ -1339,8 +1380,6 @@ static int __init sci_init(void) | |||
1339 | 1380 | ||
1340 | printk(banner); | 1381 | printk(banner); |
1341 | 1382 | ||
1342 | sci_init_ports(); | ||
1343 | |||
1344 | ret = uart_register_driver(&sci_uart_driver); | 1383 | ret = uart_register_driver(&sci_uart_driver); |
1345 | if (likely(ret == 0)) { | 1384 | if (likely(ret == 0)) { |
1346 | ret = platform_driver_register(&sci_driver); | 1385 | ret = platform_driver_register(&sci_driver); |
diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index d0aa82d7fce0..38072c15b845 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h | |||
@@ -91,6 +91,9 @@ | |||
91 | # define SCSPTR5 0xa4050128 | 91 | # define SCSPTR5 0xa4050128 |
92 | # define SCIF_ORER 0x0001 /* overrun error bit */ | 92 | # define SCIF_ORER 0x0001 /* overrun error bit */ |
93 | # define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ | 93 | # define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ |
94 | #elif defined(CONFIG_CPU_SUBTYPE_SH7724) | ||
95 | # define SCIF_ORER 0x0001 /* overrun error bit */ | ||
96 | # define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ | ||
94 | #elif defined(CONFIG_CPU_SUBTYPE_SH4_202) | 97 | #elif defined(CONFIG_CPU_SUBTYPE_SH4_202) |
95 | # define SCSPTR2 0xffe80020 /* 16 bit SCIF */ | 98 | # define SCSPTR2 0xffe80020 /* 16 bit SCIF */ |
96 | # define SCIF_ORER 0x0001 /* overrun error bit */ | 99 | # define SCIF_ORER 0x0001 /* overrun error bit */ |
@@ -314,7 +317,18 @@ | |||
314 | } \ | 317 | } \ |
315 | } | 318 | } |
316 | 319 | ||
317 | #define CPU_SCIF_FNS(name, scif_offset, scif_size) \ | 320 | #ifdef CONFIG_H8300 |
321 | /* h8300 don't have SCIF */ | ||
322 | #define CPU_SCIF_FNS(name) \ | ||
323 | static inline unsigned int sci_##name##_in(struct uart_port *port) \ | ||
324 | { \ | ||
325 | return 0; \ | ||
326 | } \ | ||
327 | static inline void sci_##name##_out(struct uart_port *port, unsigned int value) \ | ||
328 | { \ | ||
329 | } | ||
330 | #else | ||
331 | #define CPU_SCIF_FNS(name, scif_offset, scif_size) \ | ||
318 | static inline unsigned int sci_##name##_in(struct uart_port *port) \ | 332 | static inline unsigned int sci_##name##_in(struct uart_port *port) \ |
319 | { \ | 333 | { \ |
320 | SCI_IN(scif_size, scif_offset); \ | 334 | SCI_IN(scif_size, scif_offset); \ |
@@ -323,6 +337,7 @@ | |||
323 | { \ | 337 | { \ |
324 | SCI_OUT(scif_size, scif_offset, value); \ | 338 | SCI_OUT(scif_size, scif_offset, value); \ |
325 | } | 339 | } |
340 | #endif | ||
326 | 341 | ||
327 | #define CPU_SCI_FNS(name, sci_offset, sci_size) \ | 342 | #define CPU_SCI_FNS(name, sci_offset, sci_size) \ |
328 | static inline unsigned int sci_##name##_in(struct uart_port* port) \ | 343 | static inline unsigned int sci_##name##_in(struct uart_port* port) \ |
@@ -360,8 +375,10 @@ | |||
360 | sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size, \ | 375 | sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size, \ |
361 | h8_sci_offset, h8_sci_size) \ | 376 | h8_sci_offset, h8_sci_size) \ |
362 | CPU_SCI_FNS(name, h8_sci_offset, h8_sci_size) | 377 | CPU_SCI_FNS(name, h8_sci_offset, h8_sci_size) |
363 | #define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size) | 378 | #define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size) \ |
364 | #elif defined(CONFIG_CPU_SUBTYPE_SH7723) | 379 | CPU_SCIF_FNS(name) |
380 | #elif defined(CONFIG_CPU_SUBTYPE_SH7723) ||\ | ||
381 | defined(CONFIG_CPU_SUBTYPE_SH7724) | ||
365 | #define SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scif_offset, sh4_scif_size) \ | 382 | #define SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scif_offset, sh4_scif_size) \ |
366 | CPU_SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scif_offset, sh4_scif_size) | 383 | CPU_SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scif_offset, sh4_scif_size) |
367 | #define SCIF_FNS(name, sh4_scif_offset, sh4_scif_size) \ | 384 | #define SCIF_FNS(name, sh4_scif_offset, sh4_scif_size) \ |
@@ -390,7 +407,8 @@ SCIF_FNS(SCFDR, 0x1c, 16) | |||
390 | SCIF_FNS(SCxTDR, 0x20, 8) | 407 | SCIF_FNS(SCxTDR, 0x20, 8) |
391 | SCIF_FNS(SCxRDR, 0x24, 8) | 408 | SCIF_FNS(SCxRDR, 0x24, 8) |
392 | SCIF_FNS(SCLSR, 0x24, 16) | 409 | SCIF_FNS(SCLSR, 0x24, 16) |
393 | #elif defined(CONFIG_CPU_SUBTYPE_SH7723) | 410 | #elif defined(CONFIG_CPU_SUBTYPE_SH7723) ||\ |
411 | defined(CONFIG_CPU_SUBTYPE_SH7724) | ||
394 | SCIx_FNS(SCSMR, 0x00, 16, 0x00, 16) | 412 | SCIx_FNS(SCSMR, 0x00, 16, 0x00, 16) |
395 | SCIx_FNS(SCBRR, 0x04, 8, 0x04, 8) | 413 | SCIx_FNS(SCBRR, 0x04, 8, 0x04, 8) |
396 | SCIx_FNS(SCSCR, 0x08, 16, 0x08, 16) | 414 | SCIx_FNS(SCSCR, 0x08, 16, 0x08, 16) |
@@ -604,10 +622,21 @@ static inline int sci_rxd_in(struct uart_port *port) | |||
604 | return ctrl_inb(SCSPTR5) & 0x0008 ? 1 : 0; /* SCIF5 */ | 622 | return ctrl_inb(SCSPTR5) & 0x0008 ? 1 : 0; /* SCIF5 */ |
605 | return 1; | 623 | return 1; |
606 | } | 624 | } |
625 | #elif defined(CONFIG_CPU_SUBTYPE_SH7724) | ||
626 | # define SCFSR 0x0010 | ||
627 | # define SCASSR 0x0014 | ||
628 | static inline int sci_rxd_in(struct uart_port *port) | ||
629 | { | ||
630 | if (port->type == PORT_SCIF) | ||
631 | return ctrl_inw((port->mapbase + SCFSR)) & SCIF_BRK ? 1 : 0; | ||
632 | if (port->type == PORT_SCIFA) | ||
633 | return ctrl_inw((port->mapbase + SCASSR)) & SCIF_BRK ? 1 : 0; | ||
634 | return 1; | ||
635 | } | ||
607 | #elif defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103) | 636 | #elif defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103) |
608 | static inline int sci_rxd_in(struct uart_port *port) | 637 | static inline int sci_rxd_in(struct uart_port *port) |
609 | { | 638 | { |
610 | return sci_in(port, SCSPTR2)&0x0001 ? 1 : 0; /* SCIF */ | 639 | return sci_in(port, SCSPTR)&0x0001 ? 1 : 0; /* SCIF */ |
611 | } | 640 | } |
612 | #elif defined(__H8300H__) || defined(__H8300S__) | 641 | #elif defined(__H8300H__) || defined(__H8300S__) |
613 | static inline int sci_rxd_in(struct uart_port *port) | 642 | static inline int sci_rxd_in(struct uart_port *port) |
@@ -757,7 +786,8 @@ static inline int sci_rxd_in(struct uart_port *port) | |||
757 | defined(CONFIG_CPU_SUBTYPE_SH7720) || \ | 786 | defined(CONFIG_CPU_SUBTYPE_SH7720) || \ |
758 | defined(CONFIG_CPU_SUBTYPE_SH7721) | 787 | defined(CONFIG_CPU_SUBTYPE_SH7721) |
759 | #define SCBRR_VALUE(bps, clk) (((clk*2)+16*bps)/(32*bps)-1) | 788 | #define SCBRR_VALUE(bps, clk) (((clk*2)+16*bps)/(32*bps)-1) |
760 | #elif defined(CONFIG_CPU_SUBTYPE_SH7723) | 789 | #elif defined(CONFIG_CPU_SUBTYPE_SH7723) ||\ |
790 | defined(CONFIG_CPU_SUBTYPE_SH7724) | ||
761 | static inline int scbrr_calc(struct uart_port *port, int bps, int clk) | 791 | static inline int scbrr_calc(struct uart_port *port, int bps, int clk) |
762 | { | 792 | { |
763 | if (port->type == PORT_SCIF) | 793 | if (port->type == PORT_SCIF) |