Commit 501b825d01efb93766c87d29f299851152cf4eb0
Committed by
Paul Mundt
1 parent
08f8cb315f
Exists in
master
and in
40 other branches
sh-sci: improve clock framework support
Use enable/disable hooks for clock framework integration. Make sure we control the clock for the serial console as well. Signed-off-by: Magnus Damm <damm@igel.co.jp> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Showing 2 changed files with 47 additions and 31 deletions Side-by-side Diff
drivers/serial/sh-sci.c
... | ... | @@ -76,8 +76,10 @@ |
76 | 76 | int break_flag; |
77 | 77 | |
78 | 78 | #ifdef CONFIG_HAVE_CLK |
79 | - /* Port clock */ | |
80 | - struct clk *clk; | |
79 | + /* Interface clock */ | |
80 | + struct clk *iclk; | |
81 | + /* Data clock */ | |
82 | + struct clk *dclk; | |
81 | 83 | #endif |
82 | 84 | struct list_head node; |
83 | 85 | }; |
84 | 86 | |
... | ... | @@ -166,12 +168,12 @@ |
166 | 168 | *mstpcrl &= ~mask; |
167 | 169 | } |
168 | 170 | |
169 | -static inline void h8300_sci_enable(struct uart_port *port) | |
171 | +static void h8300_sci_enable(struct uart_port *port) | |
170 | 172 | { |
171 | 173 | h8300_sci_config(port, sci_enable); |
172 | 174 | } |
173 | 175 | |
174 | -static inline void h8300_sci_disable(struct uart_port *port) | |
176 | +static void h8300_sci_disable(struct uart_port *port) | |
175 | 177 | { |
176 | 178 | h8300_sci_config(port, sci_disable); |
177 | 179 | } |
178 | 180 | |
... | ... | @@ -742,13 +744,34 @@ |
742 | 744 | (phase == CPUFREQ_RESUMECHANGE)) { |
743 | 745 | spin_lock_irqsave(&priv->lock, flags); |
744 | 746 | list_for_each_entry(sci_port, &priv->ports, node) |
745 | - sci_port->port.uartclk = clk_get_rate(sci_port->clk); | |
747 | + sci_port->port.uartclk = clk_get_rate(sci_port->dclk); | |
746 | 748 | |
747 | 749 | spin_unlock_irqrestore(&priv->lock, flags); |
748 | 750 | } |
749 | 751 | |
750 | 752 | return NOTIFY_OK; |
751 | 753 | } |
754 | + | |
755 | +static void sci_clk_enable(struct uart_port *port) | |
756 | +{ | |
757 | + struct sci_port *sci_port = to_sci_port(port); | |
758 | + | |
759 | + clk_enable(sci_port->dclk); | |
760 | + sci_port->port.uartclk = clk_get_rate(sci_port->dclk); | |
761 | + | |
762 | + if (sci_port->iclk) | |
763 | + clk_enable(sci_port->iclk); | |
764 | +} | |
765 | + | |
766 | +static void sci_clk_disable(struct uart_port *port) | |
767 | +{ | |
768 | + struct sci_port *sci_port = to_sci_port(port); | |
769 | + | |
770 | + if (sci_port->iclk) | |
771 | + clk_disable(sci_port->iclk); | |
772 | + | |
773 | + clk_disable(sci_port->dclk); | |
774 | +} | |
752 | 775 | #endif |
753 | 776 | |
754 | 777 | static int sci_request_irq(struct sci_port *port) |
... | ... | @@ -880,10 +903,6 @@ |
880 | 903 | if (s->enable) |
881 | 904 | s->enable(port); |
882 | 905 | |
883 | -#ifdef CONFIG_HAVE_CLK | |
884 | - s->clk = clk_get(NULL, "module_clk"); | |
885 | -#endif | |
886 | - | |
887 | 906 | sci_request_irq(s); |
888 | 907 | sci_start_tx(port); |
889 | 908 | sci_start_rx(port, 1); |
... | ... | @@ -901,11 +920,6 @@ |
901 | 920 | |
902 | 921 | if (s->disable) |
903 | 922 | s->disable(port); |
904 | - | |
905 | -#ifdef CONFIG_HAVE_CLK | |
906 | - clk_put(s->clk); | |
907 | - s->clk = NULL; | |
908 | -#endif | |
909 | 923 | } |
910 | 924 | |
911 | 925 | static void sci_set_termios(struct uart_port *port, struct ktermios *termios, |
... | ... | @@ -1048,7 +1062,8 @@ |
1048 | 1062 | #endif |
1049 | 1063 | }; |
1050 | 1064 | |
1051 | -static void __devinit sci_init_single(struct sci_port *sci_port, | |
1065 | +static void __devinit sci_init_single(struct platform_device *dev, | |
1066 | + struct sci_port *sci_port, | |
1052 | 1067 | unsigned int index, |
1053 | 1068 | struct plat_sci_port *p) |
1054 | 1069 | { |
... | ... | @@ -1064,14 +1079,10 @@ |
1064 | 1079 | #endif |
1065 | 1080 | sci_port->port.uartclk = CONFIG_CPU_CLOCK; |
1066 | 1081 | #elif defined(CONFIG_HAVE_CLK) |
1067 | - /* | |
1068 | - * XXX: We should use a proper SCI/SCIF clock | |
1069 | - */ | |
1070 | - { | |
1071 | - struct clk *clk = clk_get(NULL, "module_clk"); | |
1072 | - sci_port->port.uartclk = clk_get_rate(clk); | |
1073 | - clk_put(clk); | |
1074 | - } | |
1082 | + sci_port->iclk = p->clk ? clk_get(&dev->dev, p->clk) : NULL; | |
1083 | + sci_port->dclk = clk_get(&dev->dev, "module_clk"); | |
1084 | + sci_port->enable = sci_clk_enable; | |
1085 | + sci_port->disable = sci_clk_disable; | |
1075 | 1086 | #else |
1076 | 1087 | #error "Need a valid uartclk" |
1077 | 1088 | #endif |
1078 | 1089 | |
... | ... | @@ -1085,9 +1096,11 @@ |
1085 | 1096 | |
1086 | 1097 | sci_port->port.irq = p->irqs[SCIx_TXI_IRQ]; |
1087 | 1098 | sci_port->port.flags = p->flags; |
1099 | + sci_port->port.dev = &dev->dev; | |
1088 | 1100 | sci_port->type = sci_port->port.type = p->type; |
1089 | 1101 | |
1090 | 1102 | memcpy(&sci_port->irqs, &p->irqs, sizeof(p->irqs)); |
1103 | + | |
1091 | 1104 | } |
1092 | 1105 | |
1093 | 1106 | #ifdef CONFIG_SERIAL_SH_SCI_CONSOLE |
1094 | 1107 | |
1095 | 1108 | |
1096 | 1109 | |
... | ... | @@ -1111,14 +1124,21 @@ |
1111 | 1124 | unsigned count) |
1112 | 1125 | { |
1113 | 1126 | struct uart_port *port = co->data; |
1127 | + struct sci_port *sci_port = to_sci_port(port); | |
1114 | 1128 | unsigned short bits; |
1115 | 1129 | |
1116 | - uart_console_write(co->data, s, count, serial_console_putchar); | |
1130 | + if (sci_port->enable) | |
1131 | + sci_port->enable(port); | |
1117 | 1132 | |
1133 | + uart_console_write(port, s, count, serial_console_putchar); | |
1134 | + | |
1118 | 1135 | /* wait until fifo is empty and last bit has been transmitted */ |
1119 | 1136 | bits = SCxSR_TDxE(port) | SCxSR_TEND(port); |
1120 | 1137 | while ((sci_in(port, SCxSR) & bits) != bits) |
1121 | 1138 | cpu_relax(); |
1139 | + | |
1140 | + if (sci_port->disable); | |
1141 | + sci_port->disable(port); | |
1122 | 1142 | } |
1123 | 1143 | |
1124 | 1144 | static int __init serial_console_setup(struct console *co, char *options) |
... | ... | @@ -1152,11 +1172,6 @@ |
1152 | 1172 | if (!port->type) |
1153 | 1173 | return -ENODEV; |
1154 | 1174 | |
1155 | -#ifdef CONFIG_HAVE_CLK | |
1156 | - if (!sci_port->clk) | |
1157 | - sci_port->clk = clk_get(NULL, "module_clk"); | |
1158 | -#endif | |
1159 | - | |
1160 | 1175 | sci_config_port(port, 0); |
1161 | 1176 | |
1162 | 1177 | if (sci_port->enable) |
... | ... | @@ -1171,6 +1186,7 @@ |
1171 | 1186 | if (ret == 0) |
1172 | 1187 | sci_stop_rx(port); |
1173 | 1188 | #endif |
1189 | + /* TODO: disable clock */ | |
1174 | 1190 | return ret; |
1175 | 1191 | } |
1176 | 1192 | |
... | ... | @@ -1250,8 +1266,7 @@ |
1250 | 1266 | return 0; |
1251 | 1267 | } |
1252 | 1268 | |
1253 | - sciport->port.dev = &dev->dev; | |
1254 | - sci_init_single(sciport, index, p); | |
1269 | + sci_init_single(dev, sciport, index, p); | |
1255 | 1270 | |
1256 | 1271 | ret = uart_add_one_port(&sci_uart_driver, &sciport->port); |
1257 | 1272 | if (ret) |
include/linux/serial_sci.h