aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMagnus Damm <damm@igel.co.jp>2009-01-21 10:14:30 -0500
committerPaul Mundt <lethal@linux-sh.org>2009-05-08 10:22:26 -0400
commit501b825d01efb93766c87d29f299851152cf4eb0 (patch)
treee80ece8e1b458aae3f601f1f23dd7b1173b1b366
parent08f8cb315fdf9195b472aeb440ae65b189b151da (diff)
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>
-rw-r--r--drivers/serial/sh-sci.c77
-rw-r--r--include/linux/serial_sci.h1
2 files changed, 47 insertions, 31 deletions
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c
index 408624ae7fec..3daf76725ac6 100644
--- a/drivers/serial/sh-sci.c
+++ b/drivers/serial/sh-sci.c
@@ -76,8 +76,10 @@ struct sci_port {
76 int break_flag; 76 int break_flag;
77 77
78#ifdef CONFIG_HAVE_CLK 78#ifdef CONFIG_HAVE_CLK
79 /* Port clock */ 79 /* Interface clock */
80 struct clk *clk; 80 struct clk *iclk;
81 /* Data clock */
82 struct clk *dclk;
81#endif 83#endif
82 struct list_head node; 84 struct list_head node;
83}; 85};
@@ -166,12 +168,12 @@ static void h8300_sci_config(struct uart_port *port, unsigned int ctrl)
166 *mstpcrl &= ~mask; 168 *mstpcrl &= ~mask;
167} 169}
168 170
169static inline void h8300_sci_enable(struct uart_port *port) 171static void h8300_sci_enable(struct uart_port *port)
170{ 172{
171 h8300_sci_config(port, sci_enable); 173 h8300_sci_config(port, sci_enable);
172} 174}
173 175
174static inline void h8300_sci_disable(struct uart_port *port) 176static void h8300_sci_disable(struct uart_port *port)
175{ 177{
176 h8300_sci_config(port, sci_disable); 178 h8300_sci_config(port, sci_disable);
177} 179}
@@ -742,13 +744,34 @@ static int sci_notifier(struct notifier_block *self,
742 (phase == CPUFREQ_RESUMECHANGE)) { 744 (phase == CPUFREQ_RESUMECHANGE)) {
743 spin_lock_irqsave(&priv->lock, flags); 745 spin_lock_irqsave(&priv->lock, flags);
744 list_for_each_entry(sci_port, &priv->ports, node) 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 spin_unlock_irqrestore(&priv->lock, flags); 749 spin_unlock_irqrestore(&priv->lock, flags);
748 } 750 }
749 751
750 return NOTIFY_OK; 752 return NOTIFY_OK;
751} 753}
754
755static 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
766static 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#endif 775#endif
753 776
754static int sci_request_irq(struct sci_port *port) 777static int sci_request_irq(struct sci_port *port)
@@ -880,10 +903,6 @@ static int sci_startup(struct uart_port *port)
880 if (s->enable) 903 if (s->enable)
881 s->enable(port); 904 s->enable(port);
882 905
883#ifdef CONFIG_HAVE_CLK
884 s->clk = clk_get(NULL, "module_clk");
885#endif
886
887 sci_request_irq(s); 906 sci_request_irq(s);
888 sci_start_tx(port); 907 sci_start_tx(port);
889 sci_start_rx(port, 1); 908 sci_start_rx(port, 1);
@@ -901,11 +920,6 @@ static void sci_shutdown(struct uart_port *port)
901 920
902 if (s->disable) 921 if (s->disable)
903 s->disable(port); 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
911static void sci_set_termios(struct uart_port *port, struct ktermios *termios, 925static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
@@ -1048,7 +1062,8 @@ static struct uart_ops sci_uart_ops = {
1048#endif 1062#endif
1049}; 1063};
1050 1064
1051static void __devinit sci_init_single(struct sci_port *sci_port, 1065static void __devinit sci_init_single(struct platform_device *dev,
1066 struct sci_port *sci_port,
1052 unsigned int index, 1067 unsigned int index,
1053 struct plat_sci_port *p) 1068 struct plat_sci_port *p)
1054{ 1069{
@@ -1064,14 +1079,10 @@ static void __devinit sci_init_single(struct sci_port *sci_port,
1064#endif 1079#endif
1065 sci_port->port.uartclk = CONFIG_CPU_CLOCK; 1080 sci_port->port.uartclk = CONFIG_CPU_CLOCK;
1066#elif defined(CONFIG_HAVE_CLK) 1081#elif defined(CONFIG_HAVE_CLK)
1067 /* 1082 sci_port->iclk = p->clk ? clk_get(&dev->dev, p->clk) : NULL;
1068 * XXX: We should use a proper SCI/SCIF clock 1083 sci_port->dclk = clk_get(&dev->dev, "module_clk");
1069 */ 1084 sci_port->enable = sci_clk_enable;
1070 { 1085 sci_port->disable = sci_clk_disable;
1071 struct clk *clk = clk_get(NULL, "module_clk");
1072 sci_port->port.uartclk = clk_get_rate(clk);
1073 clk_put(clk);
1074 }
1075#else 1086#else
1076#error "Need a valid uartclk" 1087#error "Need a valid uartclk"
1077#endif 1088#endif
@@ -1085,9 +1096,11 @@ static void __devinit sci_init_single(struct sci_port *sci_port,
1085 1096
1086 sci_port->port.irq = p->irqs[SCIx_TXI_IRQ]; 1097 sci_port->port.irq = p->irqs[SCIx_TXI_IRQ];
1087 sci_port->port.flags = p->flags; 1098 sci_port->port.flags = p->flags;
1099 sci_port->port.dev = &dev->dev;
1088 sci_port->type = sci_port->port.type = p->type; 1100 sci_port->type = sci_port->port.type = p->type;
1089 1101
1090 memcpy(&sci_port->irqs, &p->irqs, sizeof(p->irqs)); 1102 memcpy(&sci_port->irqs, &p->irqs, sizeof(p->irqs));
1103
1091} 1104}
1092 1105
1093#ifdef CONFIG_SERIAL_SH_SCI_CONSOLE 1106#ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
@@ -1111,14 +1124,21 @@ static void serial_console_write(struct console *co, const char *s,
1111 unsigned count) 1124 unsigned count)
1112{ 1125{
1113 struct uart_port *port = co->data; 1126 struct uart_port *port = co->data;
1127 struct sci_port *sci_port = to_sci_port(port);
1114 unsigned short bits; 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);
1132
1133 uart_console_write(port, s, count, serial_console_putchar);
1117 1134
1118 /* wait until fifo is empty and last bit has been transmitted */ 1135 /* wait until fifo is empty and last bit has been transmitted */
1119 bits = SCxSR_TDxE(port) | SCxSR_TEND(port); 1136 bits = SCxSR_TDxE(port) | SCxSR_TEND(port);
1120 while ((sci_in(port, SCxSR) & bits) != bits) 1137 while ((sci_in(port, SCxSR) & bits) != bits)
1121 cpu_relax(); 1138 cpu_relax();
1139
1140 if (sci_port->disable);
1141 sci_port->disable(port);
1122} 1142}
1123 1143
1124static int __init serial_console_setup(struct console *co, char *options) 1144static int __init serial_console_setup(struct console *co, char *options)
@@ -1152,11 +1172,6 @@ static int __init serial_console_setup(struct console *co, char *options)
1152 if (!port->type) 1172 if (!port->type)
1153 return -ENODEV; 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 sci_config_port(port, 0); 1175 sci_config_port(port, 0);
1161 1176
1162 if (sci_port->enable) 1177 if (sci_port->enable)
@@ -1171,6 +1186,7 @@ static int __init serial_console_setup(struct console *co, char *options)
1171 if (ret == 0) 1186 if (ret == 0)
1172 sci_stop_rx(port); 1187 sci_stop_rx(port);
1173#endif 1188#endif
1189 /* TODO: disable clock */
1174 return ret; 1190 return ret;
1175} 1191}
1176 1192
@@ -1250,8 +1266,7 @@ static int __devinit sci_probe_single(struct platform_device *dev,
1250 return 0; 1266 return 0;
1251 } 1267 }
1252 1268
1253 sciport->port.dev = &dev->dev; 1269 sci_init_single(dev, sciport, index, p);
1254 sci_init_single(sciport, index, p);
1255 1270
1256 ret = uart_add_one_port(&sci_uart_driver, &sciport->port); 1271 ret = uart_add_one_port(&sci_uart_driver, &sciport->port);
1257 if (ret) 1272 if (ret)
diff --git a/include/linux/serial_sci.h b/include/linux/serial_sci.h
index 717059d6791f..1c297ddc9d5a 100644
--- a/include/linux/serial_sci.h
+++ b/include/linux/serial_sci.h
@@ -25,6 +25,7 @@ struct plat_sci_port {
25 unsigned int irqs[SCIx_NR_IRQS]; /* ERI, RXI, TXI, BRI */ 25 unsigned int irqs[SCIx_NR_IRQS]; /* ERI, RXI, TXI, BRI */
26 unsigned int type; /* SCI / SCIF / IRDA */ 26 unsigned int type; /* SCI / SCIF / IRDA */
27 upf_t flags; /* UPF_* flags */ 27 upf_t flags; /* UPF_* flags */
28 char *clk; /* clock string */
28}; 29};
29 30
30#endif /* __LINUX_SERIAL_SCI_H */ 31#endif /* __LINUX_SERIAL_SCI_H */