diff options
-rw-r--r-- | arch/sh/kernel/cpu/sh4a/setup-sh7757.c | 56 | ||||
-rw-r--r-- | drivers/tty/serial/sh-sci.c | 197 | ||||
-rw-r--r-- | include/linux/serial_sci.h | 7 |
3 files changed, 155 insertions, 105 deletions
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c index 717a76b399b1..e915deafac89 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c | |||
@@ -183,7 +183,7 @@ static const struct sh_dmae_slave_config sh7757_dmae1_slaves[] = { | |||
183 | { | 183 | { |
184 | .slave_id = SHDMA_SLAVE_SCIF2_RX, | 184 | .slave_id = SHDMA_SLAVE_SCIF2_RX, |
185 | .addr = 0x1f4b0014, | 185 | .addr = 0x1f4b0014, |
186 | .chcr = SM_INC | 0x800 | 0x40000000 | | 186 | .chcr = DM_INC | 0x800 | 0x40000000 | |
187 | TS_INDEX2VAL(XMIT_SZ_8BIT), | 187 | TS_INDEX2VAL(XMIT_SZ_8BIT), |
188 | .mid_rid = 0x22, | 188 | .mid_rid = 0x22, |
189 | }, | 189 | }, |
@@ -197,7 +197,7 @@ static const struct sh_dmae_slave_config sh7757_dmae1_slaves[] = { | |||
197 | { | 197 | { |
198 | .slave_id = SHDMA_SLAVE_SCIF3_RX, | 198 | .slave_id = SHDMA_SLAVE_SCIF3_RX, |
199 | .addr = 0x1f4c0014, | 199 | .addr = 0x1f4c0014, |
200 | .chcr = SM_INC | 0x800 | 0x40000000 | | 200 | .chcr = DM_INC | 0x800 | 0x40000000 | |
201 | TS_INDEX2VAL(XMIT_SZ_8BIT), | 201 | TS_INDEX2VAL(XMIT_SZ_8BIT), |
202 | .mid_rid = 0x2a, | 202 | .mid_rid = 0x2a, |
203 | }, | 203 | }, |
@@ -211,7 +211,7 @@ static const struct sh_dmae_slave_config sh7757_dmae1_slaves[] = { | |||
211 | { | 211 | { |
212 | .slave_id = SHDMA_SLAVE_SCIF4_RX, | 212 | .slave_id = SHDMA_SLAVE_SCIF4_RX, |
213 | .addr = 0x1f4d0014, | 213 | .addr = 0x1f4d0014, |
214 | .chcr = SM_INC | 0x800 | 0x40000000 | | 214 | .chcr = DM_INC | 0x800 | 0x40000000 | |
215 | TS_INDEX2VAL(XMIT_SZ_8BIT), | 215 | TS_INDEX2VAL(XMIT_SZ_8BIT), |
216 | .mid_rid = 0x42, | 216 | .mid_rid = 0x42, |
217 | }, | 217 | }, |
@@ -228,7 +228,7 @@ static const struct sh_dmae_slave_config sh7757_dmae2_slaves[] = { | |||
228 | { | 228 | { |
229 | .slave_id = SHDMA_SLAVE_RIIC0_RX, | 229 | .slave_id = SHDMA_SLAVE_RIIC0_RX, |
230 | .addr = 0x1e500013, | 230 | .addr = 0x1e500013, |
231 | .chcr = SM_INC | 0x800 | 0x40000000 | | 231 | .chcr = DM_INC | 0x800 | 0x40000000 | |
232 | TS_INDEX2VAL(XMIT_SZ_8BIT), | 232 | TS_INDEX2VAL(XMIT_SZ_8BIT), |
233 | .mid_rid = 0x22, | 233 | .mid_rid = 0x22, |
234 | }, | 234 | }, |
@@ -242,7 +242,7 @@ static const struct sh_dmae_slave_config sh7757_dmae2_slaves[] = { | |||
242 | { | 242 | { |
243 | .slave_id = SHDMA_SLAVE_RIIC1_RX, | 243 | .slave_id = SHDMA_SLAVE_RIIC1_RX, |
244 | .addr = 0x1e510013, | 244 | .addr = 0x1e510013, |
245 | .chcr = SM_INC | 0x800 | 0x40000000 | | 245 | .chcr = DM_INC | 0x800 | 0x40000000 | |
246 | TS_INDEX2VAL(XMIT_SZ_8BIT), | 246 | TS_INDEX2VAL(XMIT_SZ_8BIT), |
247 | .mid_rid = 0x2a, | 247 | .mid_rid = 0x2a, |
248 | }, | 248 | }, |
@@ -256,7 +256,7 @@ static const struct sh_dmae_slave_config sh7757_dmae2_slaves[] = { | |||
256 | { | 256 | { |
257 | .slave_id = SHDMA_SLAVE_RIIC2_RX, | 257 | .slave_id = SHDMA_SLAVE_RIIC2_RX, |
258 | .addr = 0x1e520013, | 258 | .addr = 0x1e520013, |
259 | .chcr = SM_INC | 0x800 | 0x40000000 | | 259 | .chcr = DM_INC | 0x800 | 0x40000000 | |
260 | TS_INDEX2VAL(XMIT_SZ_8BIT), | 260 | TS_INDEX2VAL(XMIT_SZ_8BIT), |
261 | .mid_rid = 0xa2, | 261 | .mid_rid = 0xa2, |
262 | }, | 262 | }, |
@@ -265,12 +265,12 @@ static const struct sh_dmae_slave_config sh7757_dmae2_slaves[] = { | |||
265 | .addr = 0x1e530012, | 265 | .addr = 0x1e530012, |
266 | .chcr = SM_INC | 0x800 | 0x40000000 | | 266 | .chcr = SM_INC | 0x800 | 0x40000000 | |
267 | TS_INDEX2VAL(XMIT_SZ_8BIT), | 267 | TS_INDEX2VAL(XMIT_SZ_8BIT), |
268 | .mid_rid = 0xab, | 268 | .mid_rid = 0xa9, |
269 | }, | 269 | }, |
270 | { | 270 | { |
271 | .slave_id = SHDMA_SLAVE_RIIC3_RX, | 271 | .slave_id = SHDMA_SLAVE_RIIC3_RX, |
272 | .addr = 0x1e530013, | 272 | .addr = 0x1e530013, |
273 | .chcr = SM_INC | 0x800 | 0x40000000 | | 273 | .chcr = DM_INC | 0x800 | 0x40000000 | |
274 | TS_INDEX2VAL(XMIT_SZ_8BIT), | 274 | TS_INDEX2VAL(XMIT_SZ_8BIT), |
275 | .mid_rid = 0xaf, | 275 | .mid_rid = 0xaf, |
276 | }, | 276 | }, |
@@ -279,14 +279,14 @@ static const struct sh_dmae_slave_config sh7757_dmae2_slaves[] = { | |||
279 | .addr = 0x1e540012, | 279 | .addr = 0x1e540012, |
280 | .chcr = SM_INC | 0x800 | 0x40000000 | | 280 | .chcr = SM_INC | 0x800 | 0x40000000 | |
281 | TS_INDEX2VAL(XMIT_SZ_8BIT), | 281 | TS_INDEX2VAL(XMIT_SZ_8BIT), |
282 | .mid_rid = 0xc1, | 282 | .mid_rid = 0xc5, |
283 | }, | 283 | }, |
284 | { | 284 | { |
285 | .slave_id = SHDMA_SLAVE_RIIC4_RX, | 285 | .slave_id = SHDMA_SLAVE_RIIC4_RX, |
286 | .addr = 0x1e540013, | 286 | .addr = 0x1e540013, |
287 | .chcr = SM_INC | 0x800 | 0x40000000 | | 287 | .chcr = DM_INC | 0x800 | 0x40000000 | |
288 | TS_INDEX2VAL(XMIT_SZ_8BIT), | 288 | TS_INDEX2VAL(XMIT_SZ_8BIT), |
289 | .mid_rid = 0xc2, | 289 | .mid_rid = 0xc6, |
290 | }, | 290 | }, |
291 | }; | 291 | }; |
292 | 292 | ||
@@ -301,7 +301,7 @@ static const struct sh_dmae_slave_config sh7757_dmae3_slaves[] = { | |||
301 | { | 301 | { |
302 | .slave_id = SHDMA_SLAVE_RIIC5_RX, | 302 | .slave_id = SHDMA_SLAVE_RIIC5_RX, |
303 | .addr = 0x1e550013, | 303 | .addr = 0x1e550013, |
304 | .chcr = SM_INC | 0x800 | 0x40000000 | | 304 | .chcr = DM_INC | 0x800 | 0x40000000 | |
305 | TS_INDEX2VAL(XMIT_SZ_8BIT), | 305 | TS_INDEX2VAL(XMIT_SZ_8BIT), |
306 | .mid_rid = 0x22, | 306 | .mid_rid = 0x22, |
307 | }, | 307 | }, |
@@ -315,7 +315,7 @@ static const struct sh_dmae_slave_config sh7757_dmae3_slaves[] = { | |||
315 | { | 315 | { |
316 | .slave_id = SHDMA_SLAVE_RIIC6_RX, | 316 | .slave_id = SHDMA_SLAVE_RIIC6_RX, |
317 | .addr = 0x1e560013, | 317 | .addr = 0x1e560013, |
318 | .chcr = SM_INC | 0x800 | 0x40000000 | | 318 | .chcr = DM_INC | 0x800 | 0x40000000 | |
319 | TS_INDEX2VAL(XMIT_SZ_8BIT), | 319 | TS_INDEX2VAL(XMIT_SZ_8BIT), |
320 | .mid_rid = 0x2a, | 320 | .mid_rid = 0x2a, |
321 | }, | 321 | }, |
@@ -329,7 +329,7 @@ static const struct sh_dmae_slave_config sh7757_dmae3_slaves[] = { | |||
329 | { | 329 | { |
330 | .slave_id = SHDMA_SLAVE_RIIC7_RX, | 330 | .slave_id = SHDMA_SLAVE_RIIC7_RX, |
331 | .addr = 0x1e570013, | 331 | .addr = 0x1e570013, |
332 | .chcr = SM_INC | 0x800 | 0x40000000 | | 332 | .chcr = DM_INC | 0x800 | 0x40000000 | |
333 | TS_INDEX2VAL(XMIT_SZ_8BIT), | 333 | TS_INDEX2VAL(XMIT_SZ_8BIT), |
334 | .mid_rid = 0x42, | 334 | .mid_rid = 0x42, |
335 | }, | 335 | }, |
@@ -343,7 +343,7 @@ static const struct sh_dmae_slave_config sh7757_dmae3_slaves[] = { | |||
343 | { | 343 | { |
344 | .slave_id = SHDMA_SLAVE_RIIC8_RX, | 344 | .slave_id = SHDMA_SLAVE_RIIC8_RX, |
345 | .addr = 0x1e580013, | 345 | .addr = 0x1e580013, |
346 | .chcr = SM_INC | 0x800 | 0x40000000 | | 346 | .chcr = DM_INC | 0x800 | 0x40000000 | |
347 | TS_INDEX2VAL(XMIT_SZ_8BIT), | 347 | TS_INDEX2VAL(XMIT_SZ_8BIT), |
348 | .mid_rid = 0x46, | 348 | .mid_rid = 0x46, |
349 | }, | 349 | }, |
@@ -357,7 +357,7 @@ static const struct sh_dmae_slave_config sh7757_dmae3_slaves[] = { | |||
357 | { | 357 | { |
358 | .slave_id = SHDMA_SLAVE_RIIC9_RX, | 358 | .slave_id = SHDMA_SLAVE_RIIC9_RX, |
359 | .addr = 0x1e590013, | 359 | .addr = 0x1e590013, |
360 | .chcr = SM_INC | 0x800 | 0x40000000 | | 360 | .chcr = DM_INC | 0x800 | 0x40000000 | |
361 | TS_INDEX2VAL(XMIT_SZ_8BIT), | 361 | TS_INDEX2VAL(XMIT_SZ_8BIT), |
362 | .mid_rid = 0x52, | 362 | .mid_rid = 0x52, |
363 | }, | 363 | }, |
@@ -1089,13 +1089,13 @@ static DECLARE_INTC_DESC(intc_desc, "sh7757", vectors, groups, | |||
1089 | 1089 | ||
1090 | /* Support for external interrupt pins in IRQ mode */ | 1090 | /* Support for external interrupt pins in IRQ mode */ |
1091 | static struct intc_vect vectors_irq0123[] __initdata = { | 1091 | static struct intc_vect vectors_irq0123[] __initdata = { |
1092 | INTC_VECT(IRQ0, 0x240), INTC_VECT(IRQ1, 0x280), | 1092 | INTC_VECT(IRQ0, 0x200), INTC_VECT(IRQ1, 0x240), |
1093 | INTC_VECT(IRQ2, 0x2c0), INTC_VECT(IRQ3, 0x300), | 1093 | INTC_VECT(IRQ2, 0x280), INTC_VECT(IRQ3, 0x2c0), |
1094 | }; | 1094 | }; |
1095 | 1095 | ||
1096 | static struct intc_vect vectors_irq4567[] __initdata = { | 1096 | static struct intc_vect vectors_irq4567[] __initdata = { |
1097 | INTC_VECT(IRQ4, 0x340), INTC_VECT(IRQ5, 0x380), | 1097 | INTC_VECT(IRQ4, 0x300), INTC_VECT(IRQ5, 0x340), |
1098 | INTC_VECT(IRQ6, 0x3c0), INTC_VECT(IRQ7, 0x200), | 1098 | INTC_VECT(IRQ6, 0x380), INTC_VECT(IRQ7, 0x3c0), |
1099 | }; | 1099 | }; |
1100 | 1100 | ||
1101 | static struct intc_sense_reg sense_registers[] __initdata = { | 1101 | static struct intc_sense_reg sense_registers[] __initdata = { |
@@ -1129,14 +1129,14 @@ static struct intc_vect vectors_irl0123[] __initdata = { | |||
1129 | }; | 1129 | }; |
1130 | 1130 | ||
1131 | static struct intc_vect vectors_irl4567[] __initdata = { | 1131 | static struct intc_vect vectors_irl4567[] __initdata = { |
1132 | INTC_VECT(IRL4_LLLL, 0xb00), INTC_VECT(IRL4_LLLH, 0xb20), | 1132 | INTC_VECT(IRL4_LLLL, 0x200), INTC_VECT(IRL4_LLLH, 0x220), |
1133 | INTC_VECT(IRL4_LLHL, 0xb40), INTC_VECT(IRL4_LLHH, 0xb60), | 1133 | INTC_VECT(IRL4_LLHL, 0x240), INTC_VECT(IRL4_LLHH, 0x260), |
1134 | INTC_VECT(IRL4_LHLL, 0xb80), INTC_VECT(IRL4_LHLH, 0xba0), | 1134 | INTC_VECT(IRL4_LHLL, 0x280), INTC_VECT(IRL4_LHLH, 0x2a0), |
1135 | INTC_VECT(IRL4_LHHL, 0xbc0), INTC_VECT(IRL4_LHHH, 0xbe0), | 1135 | INTC_VECT(IRL4_LHHL, 0x2c0), INTC_VECT(IRL4_LHHH, 0x2e0), |
1136 | INTC_VECT(IRL4_HLLL, 0xc00), INTC_VECT(IRL4_HLLH, 0xc20), | 1136 | INTC_VECT(IRL4_HLLL, 0x300), INTC_VECT(IRL4_HLLH, 0x320), |
1137 | INTC_VECT(IRL4_HLHL, 0xc40), INTC_VECT(IRL4_HLHH, 0xc60), | 1137 | INTC_VECT(IRL4_HLHL, 0x340), INTC_VECT(IRL4_HLHH, 0x360), |
1138 | INTC_VECT(IRL4_HHLL, 0xc80), INTC_VECT(IRL4_HHLH, 0xca0), | 1138 | INTC_VECT(IRL4_HHLL, 0x380), INTC_VECT(IRL4_HHLH, 0x3a0), |
1139 | INTC_VECT(IRL4_HHHL, 0xcc0), | 1139 | INTC_VECT(IRL4_HHHL, 0x3c0), |
1140 | }; | 1140 | }; |
1141 | 1141 | ||
1142 | static DECLARE_INTC_DESC(intc_desc_irl0123, "sh7757-irl0123", vectors_irl0123, | 1142 | static DECLARE_INTC_DESC(intc_desc_irl0123, "sh7757-irl0123", vectors_irl0123, |
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 8e55e0a2733a..d0a56235c50e 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c | |||
@@ -62,12 +62,6 @@ struct sci_port { | |||
62 | /* Platform configuration */ | 62 | /* Platform configuration */ |
63 | struct plat_sci_port *cfg; | 63 | struct plat_sci_port *cfg; |
64 | 64 | ||
65 | /* Port enable callback */ | ||
66 | void (*enable)(struct uart_port *port); | ||
67 | |||
68 | /* Port disable callback */ | ||
69 | void (*disable)(struct uart_port *port); | ||
70 | |||
71 | /* Break timer */ | 65 | /* Break timer */ |
72 | struct timer_list break_timer; | 66 | struct timer_list break_timer; |
73 | int break_flag; | 67 | int break_flag; |
@@ -77,6 +71,8 @@ struct sci_port { | |||
77 | /* Function clock */ | 71 | /* Function clock */ |
78 | struct clk *fclk; | 72 | struct clk *fclk; |
79 | 73 | ||
74 | char *irqstr[SCIx_NR_IRQS]; | ||
75 | |||
80 | struct dma_chan *chan_tx; | 76 | struct dma_chan *chan_tx; |
81 | struct dma_chan *chan_rx; | 77 | struct dma_chan *chan_rx; |
82 | 78 | ||
@@ -366,6 +362,29 @@ static int sci_probe_regmap(struct plat_sci_port *cfg) | |||
366 | return 0; | 362 | return 0; |
367 | } | 363 | } |
368 | 364 | ||
365 | static void sci_port_enable(struct sci_port *sci_port) | ||
366 | { | ||
367 | if (!sci_port->port.dev) | ||
368 | return; | ||
369 | |||
370 | pm_runtime_get_sync(sci_port->port.dev); | ||
371 | |||
372 | clk_enable(sci_port->iclk); | ||
373 | sci_port->port.uartclk = clk_get_rate(sci_port->iclk); | ||
374 | clk_enable(sci_port->fclk); | ||
375 | } | ||
376 | |||
377 | static void sci_port_disable(struct sci_port *sci_port) | ||
378 | { | ||
379 | if (!sci_port->port.dev) | ||
380 | return; | ||
381 | |||
382 | clk_disable(sci_port->fclk); | ||
383 | clk_disable(sci_port->iclk); | ||
384 | |||
385 | pm_runtime_put_sync(sci_port->port.dev); | ||
386 | } | ||
387 | |||
369 | #if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_SH_SCI_CONSOLE) | 388 | #if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_SH_SCI_CONSOLE) |
370 | 389 | ||
371 | #ifdef CONFIG_CONSOLE_POLL | 390 | #ifdef CONFIG_CONSOLE_POLL |
@@ -651,8 +670,7 @@ static void sci_break_timer(unsigned long data) | |||
651 | { | 670 | { |
652 | struct sci_port *port = (struct sci_port *)data; | 671 | struct sci_port *port = (struct sci_port *)data; |
653 | 672 | ||
654 | if (port->enable) | 673 | sci_port_enable(port); |
655 | port->enable(&port->port); | ||
656 | 674 | ||
657 | if (sci_rxd_in(&port->port) == 0) { | 675 | if (sci_rxd_in(&port->port) == 0) { |
658 | port->break_flag = 1; | 676 | port->break_flag = 1; |
@@ -664,8 +682,7 @@ static void sci_break_timer(unsigned long data) | |||
664 | } else | 682 | } else |
665 | port->break_flag = 0; | 683 | port->break_flag = 0; |
666 | 684 | ||
667 | if (port->disable) | 685 | sci_port_disable(port); |
668 | port->disable(&port->port); | ||
669 | } | 686 | } |
670 | 687 | ||
671 | static int sci_handle_errors(struct uart_port *port) | 688 | static int sci_handle_errors(struct uart_port *port) |
@@ -939,74 +956,102 @@ static int sci_notifier(struct notifier_block *self, | |||
939 | return NOTIFY_OK; | 956 | return NOTIFY_OK; |
940 | } | 957 | } |
941 | 958 | ||
942 | static void sci_clk_enable(struct uart_port *port) | 959 | static struct sci_irq_desc { |
943 | { | 960 | const char *desc; |
944 | struct sci_port *sci_port = to_sci_port(port); | 961 | irq_handler_t handler; |
945 | 962 | } sci_irq_desc[] = { | |
946 | pm_runtime_get_sync(port->dev); | 963 | /* |
964 | * Split out handlers, the default case. | ||
965 | */ | ||
966 | [SCIx_ERI_IRQ] = { | ||
967 | .desc = "rx err", | ||
968 | .handler = sci_er_interrupt, | ||
969 | }, | ||
947 | 970 | ||
948 | clk_enable(sci_port->iclk); | 971 | [SCIx_RXI_IRQ] = { |
949 | sci_port->port.uartclk = clk_get_rate(sci_port->iclk); | 972 | .desc = "rx full", |
950 | clk_enable(sci_port->fclk); | 973 | .handler = sci_rx_interrupt, |
951 | } | 974 | }, |
952 | 975 | ||
953 | static void sci_clk_disable(struct uart_port *port) | 976 | [SCIx_TXI_IRQ] = { |
954 | { | 977 | .desc = "tx empty", |
955 | struct sci_port *sci_port = to_sci_port(port); | 978 | .handler = sci_tx_interrupt, |
979 | }, | ||
956 | 980 | ||
957 | clk_disable(sci_port->fclk); | 981 | [SCIx_BRI_IRQ] = { |
958 | clk_disable(sci_port->iclk); | 982 | .desc = "break", |
983 | .handler = sci_br_interrupt, | ||
984 | }, | ||
959 | 985 | ||
960 | pm_runtime_put_sync(port->dev); | 986 | /* |
961 | } | 987 | * Special muxed handler. |
988 | */ | ||
989 | [SCIx_MUX_IRQ] = { | ||
990 | .desc = "mux", | ||
991 | .handler = sci_mpxed_interrupt, | ||
992 | }, | ||
993 | }; | ||
962 | 994 | ||
963 | static int sci_request_irq(struct sci_port *port) | 995 | static int sci_request_irq(struct sci_port *port) |
964 | { | 996 | { |
965 | int i; | 997 | struct uart_port *up = &port->port; |
966 | irqreturn_t (*handlers[4])(int irq, void *ptr) = { | 998 | int i, j, ret = 0; |
967 | sci_er_interrupt, sci_rx_interrupt, sci_tx_interrupt, | 999 | |
968 | sci_br_interrupt, | 1000 | for (i = j = 0; i < SCIx_NR_IRQS; i++, j++) { |
969 | }; | 1001 | struct sci_irq_desc *desc; |
970 | const char *desc[] = { "SCI Receive Error", "SCI Receive Data Full", | 1002 | unsigned int irq; |
971 | "SCI Transmit Data Empty", "SCI Break" }; | 1003 | |
972 | 1004 | if (SCIx_IRQ_IS_MUXED(port)) { | |
973 | if (port->cfg->irqs[0] == port->cfg->irqs[1]) { | 1005 | i = SCIx_MUX_IRQ; |
974 | if (unlikely(!port->cfg->irqs[0])) | 1006 | irq = up->irq; |
975 | return -ENODEV; | 1007 | } else |
976 | 1008 | irq = port->cfg->irqs[i]; | |
977 | if (request_irq(port->cfg->irqs[0], sci_mpxed_interrupt, | 1009 | |
978 | IRQF_DISABLED, "sci", port)) { | 1010 | desc = sci_irq_desc + i; |
979 | dev_err(port->port.dev, "Can't allocate IRQ\n"); | 1011 | port->irqstr[j] = kasprintf(GFP_KERNEL, "%s:%s", |
980 | return -ENODEV; | 1012 | dev_name(up->dev), desc->desc); |
1013 | if (!port->irqstr[j]) { | ||
1014 | dev_err(up->dev, "Failed to allocate %s IRQ string\n", | ||
1015 | desc->desc); | ||
1016 | goto out_nomem; | ||
981 | } | 1017 | } |
982 | } else { | 1018 | |
983 | for (i = 0; i < ARRAY_SIZE(handlers); i++) { | 1019 | ret = request_irq(irq, desc->handler, up->irqflags, |
984 | if (unlikely(!port->cfg->irqs[i])) | 1020 | port->irqstr[j], port); |
985 | continue; | 1021 | if (unlikely(ret)) { |
986 | 1022 | dev_err(up->dev, "Can't allocate %s IRQ\n", desc->desc); | |
987 | if (request_irq(port->cfg->irqs[i], handlers[i], | 1023 | goto out_noirq; |
988 | IRQF_DISABLED, desc[i], port)) { | ||
989 | dev_err(port->port.dev, "Can't allocate IRQ\n"); | ||
990 | return -ENODEV; | ||
991 | } | ||
992 | } | 1024 | } |
993 | } | 1025 | } |
994 | 1026 | ||
995 | return 0; | 1027 | return 0; |
1028 | |||
1029 | out_noirq: | ||
1030 | while (--i >= 0) | ||
1031 | free_irq(port->cfg->irqs[i], port); | ||
1032 | |||
1033 | out_nomem: | ||
1034 | while (--j >= 0) | ||
1035 | kfree(port->irqstr[j]); | ||
1036 | |||
1037 | return ret; | ||
996 | } | 1038 | } |
997 | 1039 | ||
998 | static void sci_free_irq(struct sci_port *port) | 1040 | static void sci_free_irq(struct sci_port *port) |
999 | { | 1041 | { |
1000 | int i; | 1042 | int i; |
1001 | 1043 | ||
1002 | if (port->cfg->irqs[0] == port->cfg->irqs[1]) | 1044 | /* |
1003 | free_irq(port->cfg->irqs[0], port); | 1045 | * Intentionally in reverse order so we iterate over the muxed |
1004 | else { | 1046 | * IRQ first. |
1005 | for (i = 0; i < ARRAY_SIZE(port->cfg->irqs); i++) { | 1047 | */ |
1006 | if (!port->cfg->irqs[i]) | 1048 | for (i = 0; i < SCIx_NR_IRQS; i++) { |
1007 | continue; | 1049 | free_irq(port->cfg->irqs[i], port); |
1050 | kfree(port->irqstr[i]); | ||
1008 | 1051 | ||
1009 | free_irq(port->cfg->irqs[i], port); | 1052 | if (SCIx_IRQ_IS_MUXED(port)) { |
1053 | /* If there's only one IRQ, we're done. */ | ||
1054 | return; | ||
1010 | } | 1055 | } |
1011 | } | 1056 | } |
1012 | } | 1057 | } |
@@ -1537,8 +1582,7 @@ static int sci_startup(struct uart_port *port) | |||
1537 | 1582 | ||
1538 | dev_dbg(port->dev, "%s(%d)\n", __func__, port->line); | 1583 | dev_dbg(port->dev, "%s(%d)\n", __func__, port->line); |
1539 | 1584 | ||
1540 | if (s->enable) | 1585 | sci_port_enable(s); |
1541 | s->enable(port); | ||
1542 | 1586 | ||
1543 | ret = sci_request_irq(s); | 1587 | ret = sci_request_irq(s); |
1544 | if (unlikely(ret < 0)) | 1588 | if (unlikely(ret < 0)) |
@@ -1564,8 +1608,7 @@ static void sci_shutdown(struct uart_port *port) | |||
1564 | sci_free_dma(port); | 1608 | sci_free_dma(port); |
1565 | sci_free_irq(s); | 1609 | sci_free_irq(s); |
1566 | 1610 | ||
1567 | if (s->disable) | 1611 | sci_port_disable(s); |
1568 | s->disable(port); | ||
1569 | } | 1612 | } |
1570 | 1613 | ||
1571 | static unsigned int sci_scbrr_calc(unsigned int algo_id, unsigned int bps, | 1614 | static unsigned int sci_scbrr_calc(unsigned int algo_id, unsigned int bps, |
@@ -1612,8 +1655,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, | |||
1612 | if (likely(baud && port->uartclk)) | 1655 | if (likely(baud && port->uartclk)) |
1613 | t = sci_scbrr_calc(s->cfg->scbrr_algo_id, baud, port->uartclk); | 1656 | t = sci_scbrr_calc(s->cfg->scbrr_algo_id, baud, port->uartclk); |
1614 | 1657 | ||
1615 | if (s->enable) | 1658 | sci_port_enable(s); |
1616 | s->enable(port); | ||
1617 | 1659 | ||
1618 | do { | 1660 | do { |
1619 | status = sci_in(port, SCxSR); | 1661 | status = sci_in(port, SCxSR); |
@@ -1683,8 +1725,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, | |||
1683 | if ((termios->c_cflag & CREAD) != 0) | 1725 | if ((termios->c_cflag & CREAD) != 0) |
1684 | sci_start_rx(port); | 1726 | sci_start_rx(port); |
1685 | 1727 | ||
1686 | if (s->disable) | 1728 | sci_port_disable(s); |
1687 | s->disable(port); | ||
1688 | } | 1729 | } |
1689 | 1730 | ||
1690 | static const char *sci_type(struct uart_port *port) | 1731 | static const char *sci_type(struct uart_port *port) |
@@ -1825,6 +1866,7 @@ static int __devinit sci_init_single(struct platform_device *dev, | |||
1825 | struct plat_sci_port *p) | 1866 | struct plat_sci_port *p) |
1826 | { | 1867 | { |
1827 | struct uart_port *port = &sci_port->port; | 1868 | struct uart_port *port = &sci_port->port; |
1869 | int ret; | ||
1828 | 1870 | ||
1829 | port->ops = &sci_uart_ops; | 1871 | port->ops = &sci_uart_ops; |
1830 | port->iotype = UPIO_MEM; | 1872 | port->iotype = UPIO_MEM; |
@@ -1845,8 +1887,11 @@ static int __devinit sci_init_single(struct platform_device *dev, | |||
1845 | break; | 1887 | break; |
1846 | } | 1888 | } |
1847 | 1889 | ||
1848 | if (p->regtype == SCIx_PROBE_REGTYPE) | 1890 | if (p->regtype == SCIx_PROBE_REGTYPE) { |
1849 | BUG_ON(sci_probe_regmap(p) != 0); | 1891 | ret = sci_probe_regmap(p); |
1892 | if (unlikely(!ret)) | ||
1893 | return ret; | ||
1894 | } | ||
1850 | 1895 | ||
1851 | if (dev) { | 1896 | if (dev) { |
1852 | sci_port->iclk = clk_get(&dev->dev, "sci_ick"); | 1897 | sci_port->iclk = clk_get(&dev->dev, "sci_ick"); |
@@ -1866,8 +1911,6 @@ static int __devinit sci_init_single(struct platform_device *dev, | |||
1866 | if (IS_ERR(sci_port->fclk)) | 1911 | if (IS_ERR(sci_port->fclk)) |
1867 | sci_port->fclk = NULL; | 1912 | sci_port->fclk = NULL; |
1868 | 1913 | ||
1869 | sci_port->enable = sci_clk_enable; | ||
1870 | sci_port->disable = sci_clk_disable; | ||
1871 | port->dev = &dev->dev; | 1914 | port->dev = &dev->dev; |
1872 | 1915 | ||
1873 | pm_runtime_enable(&dev->dev); | 1916 | pm_runtime_enable(&dev->dev); |
@@ -1918,6 +1961,7 @@ static int __devinit sci_init_single(struct platform_device *dev, | |||
1918 | * For the muxed case there's nothing more to do. | 1961 | * For the muxed case there's nothing more to do. |
1919 | */ | 1962 | */ |
1920 | port->irq = p->irqs[SCIx_RXI_IRQ]; | 1963 | port->irq = p->irqs[SCIx_RXI_IRQ]; |
1964 | port->irqflags = IRQF_DISABLED; | ||
1921 | 1965 | ||
1922 | port->serial_in = sci_serial_in; | 1966 | port->serial_in = sci_serial_in; |
1923 | port->serial_out = sci_serial_out; | 1967 | port->serial_out = sci_serial_out; |
@@ -1946,8 +1990,7 @@ static void serial_console_write(struct console *co, const char *s, | |||
1946 | struct uart_port *port = &sci_port->port; | 1990 | struct uart_port *port = &sci_port->port; |
1947 | unsigned short bits; | 1991 | unsigned short bits; |
1948 | 1992 | ||
1949 | if (sci_port->enable) | 1993 | sci_port_enable(sci_port); |
1950 | sci_port->enable(port); | ||
1951 | 1994 | ||
1952 | uart_console_write(port, s, count, serial_console_putchar); | 1995 | uart_console_write(port, s, count, serial_console_putchar); |
1953 | 1996 | ||
@@ -1956,8 +1999,7 @@ static void serial_console_write(struct console *co, const char *s, | |||
1956 | while ((sci_in(port, SCxSR) & bits) != bits) | 1999 | while ((sci_in(port, SCxSR) & bits) != bits) |
1957 | cpu_relax(); | 2000 | cpu_relax(); |
1958 | 2001 | ||
1959 | if (sci_port->disable) | 2002 | sci_port_disable(sci_port); |
1960 | sci_port->disable(port); | ||
1961 | } | 2003 | } |
1962 | 2004 | ||
1963 | static int __devinit serial_console_setup(struct console *co, char *options) | 2005 | static int __devinit serial_console_setup(struct console *co, char *options) |
@@ -1989,8 +2031,7 @@ static int __devinit serial_console_setup(struct console *co, char *options) | |||
1989 | if (unlikely(ret != 0)) | 2031 | if (unlikely(ret != 0)) |
1990 | return ret; | 2032 | return ret; |
1991 | 2033 | ||
1992 | if (sci_port->enable) | 2034 | sci_port_enable(sci_port); |
1993 | sci_port->enable(port); | ||
1994 | 2035 | ||
1995 | if (options) | 2036 | if (options) |
1996 | uart_parse_options(options, &baud, &parity, &bits, &flow); | 2037 | uart_parse_options(options, &baud, &parity, &bits, &flow); |
@@ -2207,3 +2248,5 @@ module_exit(sci_exit); | |||
2207 | 2248 | ||
2208 | MODULE_LICENSE("GPL"); | 2249 | MODULE_LICENSE("GPL"); |
2209 | MODULE_ALIAS("platform:sh-sci"); | 2250 | MODULE_ALIAS("platform:sh-sci"); |
2251 | MODULE_AUTHOR("Paul Mundt"); | ||
2252 | MODULE_DESCRIPTION("SuperH SCI(F) serial driver"); | ||
diff --git a/include/linux/serial_sci.h b/include/linux/serial_sci.h index 4ca130a90ea5..8bffe9ae2ca0 100644 --- a/include/linux/serial_sci.h +++ b/include/linux/serial_sci.h | |||
@@ -56,6 +56,8 @@ enum { | |||
56 | SCIx_TXI_IRQ, | 56 | SCIx_TXI_IRQ, |
57 | SCIx_BRI_IRQ, | 57 | SCIx_BRI_IRQ, |
58 | SCIx_NR_IRQS, | 58 | SCIx_NR_IRQS, |
59 | |||
60 | SCIx_MUX_IRQ = SCIx_NR_IRQS, /* special case */ | ||
59 | }; | 61 | }; |
60 | 62 | ||
61 | enum { | 63 | enum { |
@@ -82,6 +84,11 @@ enum { | |||
82 | [SCIx_BRI_IRQ] = (irq), \ | 84 | [SCIx_BRI_IRQ] = (irq), \ |
83 | } | 85 | } |
84 | 86 | ||
87 | #define SCIx_IRQ_IS_MUXED(port) \ | ||
88 | ((port)->cfg->irqs[SCIx_ERI_IRQ] == \ | ||
89 | (port)->cfg->irqs[SCIx_RXI_IRQ]) || \ | ||
90 | ((port)->cfg->irqs[SCIx_ERI_IRQ] && \ | ||
91 | !(port)->cfg->irqs[SCIx_RXI_IRQ]) | ||
85 | /* | 92 | /* |
86 | * SCI register subset common for all port types. | 93 | * SCI register subset common for all port types. |
87 | * Not all registers will exist on all parts. | 94 | * Not all registers will exist on all parts. |