sh-sci.c 33.4 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5
/*
 * drivers/serial/sh-sci.c
 *
 * SuperH on-chip serial module support.  (SCI with no FIFO / with FIFO)
 *
6
 *  Copyright (C) 2002 - 2008  Paul Mundt
M
Markus Brunner 已提交
7
 *  Modified to support SH7720 SCIF. Markus Brunner, Mark Jonas (Jul 2007).
L
Linus Torvalds 已提交
8 9 10 11 12 13 14 15
 *
 * based off of the old drivers/char/sh-sci.c by:
 *
 *   Copyright (C) 1999, 2000  Niibe Yutaka
 *   Copyright (C) 2000  Sugioka Toshinobu
 *   Modified to support multiple serial ports. Stuart Menefy (May 2000).
 *   Modified to support SecureEdge. David McCullough (2002)
 *   Modified to support SH7300 SCIF. Takashi Kusuda (Jun 2003).
16
 *   Removed SH7300 support (Jul 2007).
L
Linus Torvalds 已提交
17 18 19 20 21
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 */
22 23 24
#if defined(CONFIG_SERIAL_SH_SCI_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
#endif
L
Linus Torvalds 已提交
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42

#undef DEBUG

#include <linux/module.h>
#include <linux/errno.h>
#include <linux/timer.h>
#include <linux/interrupt.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial.h>
#include <linux/major.h>
#include <linux/string.h>
#include <linux/sysrq.h>
#include <linux/ioport.h>
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/console.h>
43
#include <linux/platform_device.h>
44
#include <linux/serial_sci.h>
L
Linus Torvalds 已提交
45 46
#include <linux/notifier.h>
#include <linux/cpufreq.h>
47
#include <linux/clk.h>
P
Paul Mundt 已提交
48
#include <linux/ctype.h>
49
#include <linux/err.h>
50
#include <linux/list.h>
51 52

#ifdef CONFIG_SUPERH
L
Linus Torvalds 已提交
53 54 55
#include <asm/sh_bios.h>
#endif

56 57 58 59
#ifdef CONFIG_H8300
#include <asm/gpio.h>
#endif

L
Linus Torvalds 已提交
60 61
#include "sh-sci.h"

62 63 64 65 66 67 68
struct sci_port {
	struct uart_port	port;

	/* Port type */
	unsigned int		type;

	/* Port IRQs: ERI, RXI, TXI, BRI (optional) */
69
	unsigned int		irqs[SCIx_NR_IRQS];
70 71 72 73 74 75 76 77 78 79

	/* Port enable callback */
	void			(*enable)(struct uart_port *port);

	/* Port disable callback */
	void			(*disable)(struct uart_port *port);

	/* Break timer */
	struct timer_list	break_timer;
	int			break_flag;
80

81 82 83 84
	/* Interface clock */
	struct clk		*iclk;
	/* Data clock */
	struct clk		*dclk;
85

86 87 88 89 90 91 92
	struct list_head	node;
};

struct sh_sci_priv {
	spinlock_t lock;
	struct list_head ports;
	struct notifier_block clk_nb;
93 94
};

L
Linus Torvalds 已提交
95
/* Function prototypes */
96
static void sci_stop_tx(struct uart_port *port);
L
Linus Torvalds 已提交
97

98
#define SCI_NPORTS CONFIG_SERIAL_SH_SCI_NR_UARTS
99

100 101
static struct sci_port sci_ports[SCI_NPORTS];
static struct uart_driver sci_uart_driver;
L
Linus Torvalds 已提交
102

103 104 105 106 107 108
static inline struct sci_port *
to_sci_port(struct uart_port *uart)
{
	return container_of(uart, struct sci_port, port);
}

109
#if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_SH_SCI_CONSOLE)
110 111

#ifdef CONFIG_CONSOLE_POLL
112 113 114
static inline void handle_error(struct uart_port *port)
{
	/* Clear error flags */
L
Linus Torvalds 已提交
115 116 117
	sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
}

118
static int sci_poll_get_char(struct uart_port *port)
L
Linus Torvalds 已提交
119 120 121 122
{
	unsigned short status;
	int c;

123
	do {
L
Linus Torvalds 已提交
124 125 126 127 128 129
		status = sci_in(port, SCxSR);
		if (status & SCxSR_ERRORS(port)) {
			handle_error(port);
			continue;
		}
	} while (!(status & SCxSR_RDxF(port)));
130

L
Linus Torvalds 已提交
131
	c = sci_in(port, SCxRDR);
132

133 134
	/* Dummy read */
	sci_in(port, SCxSR);
L
Linus Torvalds 已提交
135 136 137 138
	sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));

	return c;
}
139
#endif
L
Linus Torvalds 已提交
140

141
static void sci_poll_put_char(struct uart_port *port, unsigned char c)
L
Linus Torvalds 已提交
142 143 144 145 146 147 148
{
	unsigned short status;

	do {
		status = sci_in(port, SCxSR);
	} while (!(status & SCxSR_TDxE(port)));

149
	sci_out(port, SCxTDR, c);
150
	sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port) & ~SCxSR_TEND(port));
L
Linus Torvalds 已提交
151
}
152
#endif /* CONFIG_CONSOLE_POLL || CONFIG_SERIAL_SH_SCI_CONSOLE */
L
Linus Torvalds 已提交
153

154
#if defined(__H8300H__) || defined(__H8300S__)
155
static void sci_init_pins(struct uart_port *port, unsigned int cflag)
L
Linus Torvalds 已提交
156 157 158 159
{
	int ch = (port->mapbase - SMR0) >> 3;

	/* set DDR regs */
160 161 162 163 164 165 166
	H8300_GPIO_DDR(h8300_sci_pins[ch].port,
		       h8300_sci_pins[ch].rx,
		       H8300_GPIO_INPUT);
	H8300_GPIO_DDR(h8300_sci_pins[ch].port,
		       h8300_sci_pins[ch].tx,
		       H8300_GPIO_OUTPUT);

L
Linus Torvalds 已提交
167 168 169
	/* tx mark output*/
	H8300_SCI_DR(ch) |= h8300_sci_pins[ch].tx;
}
170 171
#elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712)
static inline void sci_init_pins(struct uart_port *port, unsigned int cflag)
172
{
173 174 175 176 177
	if (port->mapbase == 0xA4400000) {
		__raw_writew(__raw_readw(PACR) & 0xffc0, PACR);
		__raw_writew(__raw_readw(PBCR) & 0x0fff, PBCR);
	} else if (port->mapbase == 0xA4410000)
		__raw_writew(__raw_readw(PBCR) & 0xf003, PBCR);
178
}
179
#elif defined(CONFIG_CPU_SUBTYPE_SH7720) || defined(CONFIG_CPU_SUBTYPE_SH7721)
180
static inline void sci_init_pins(struct uart_port *port, unsigned int cflag)
M
Markus Brunner 已提交
181 182 183 184 185 186 187
{
	unsigned short data;

	if (cflag & CRTSCTS) {
		/* enable RTS/CTS */
		if (port->mapbase == 0xa4430000) { /* SCIF0 */
			/* Clear PTCR bit 9-2; enable all scif pins but sck */
188 189
			data = __raw_readw(PORT_PTCR);
			__raw_writew((data & 0xfc03), PORT_PTCR);
M
Markus Brunner 已提交
190 191
		} else if (port->mapbase == 0xa4438000) { /* SCIF1 */
			/* Clear PVCR bit 9-2 */
192 193
			data = __raw_readw(PORT_PVCR);
			__raw_writew((data & 0xfc03), PORT_PVCR);
M
Markus Brunner 已提交
194 195 196 197
		}
	} else {
		if (port->mapbase == 0xa4430000) { /* SCIF0 */
			/* Clear PTCR bit 5-2; enable only tx and rx  */
198 199
			data = __raw_readw(PORT_PTCR);
			__raw_writew((data & 0xffc3), PORT_PTCR);
M
Markus Brunner 已提交
200 201
		} else if (port->mapbase == 0xa4438000) { /* SCIF1 */
			/* Clear PVCR bit 5-2 */
202 203
			data = __raw_readw(PORT_PVCR);
			__raw_writew((data & 0xffc3), PORT_PVCR);
M
Markus Brunner 已提交
204 205 206
		}
	}
}
207
#elif defined(CONFIG_CPU_SH3)
208
/* For SH7705, SH7706, SH7707, SH7709, SH7709A, SH7729 */
209
static inline void sci_init_pins(struct uart_port *port, unsigned int cflag)
L
Linus Torvalds 已提交
210
{
211 212 213
	unsigned short data;

	/* We need to set SCPCR to enable RTS/CTS */
214
	data = __raw_readw(SCPCR);
215
	/* Clear out SCP7MD1,0, SCP6MD1,0, SCP4MD1,0*/
216
	__raw_writew(data & 0x0fcf, SCPCR);
L
Linus Torvalds 已提交
217

218
	if (!(cflag & CRTSCTS)) {
L
Linus Torvalds 已提交
219
		/* We need to set SCPCR to enable RTS/CTS */
220
		data = __raw_readw(SCPCR);
L
Linus Torvalds 已提交
221 222
		/* Clear out SCP7MD1,0, SCP4MD1,0,
		   Set SCP6MD1,0 = {01} (output)  */
223
		__raw_writew((data & 0x0fcf) | 0x1000, SCPCR);
L
Linus Torvalds 已提交
224

225
		data = __raw_readb(SCPDR);
L
Linus Torvalds 已提交
226
		/* Set /RTS2 (bit6) = 0 */
227
		__raw_writeb(data & 0xbf, SCPDR);
L
Linus Torvalds 已提交
228 229
	}
}
P
Paul Mundt 已提交
230
#elif defined(CONFIG_CPU_SUBTYPE_SH7722)
231
static inline void sci_init_pins(struct uart_port *port, unsigned int cflag)
P
Paul Mundt 已提交
232
{
M
Magnus Damm 已提交
233
	unsigned short data;
P
Paul Mundt 已提交
234

M
Magnus Damm 已提交
235
	if (port->mapbase == 0xffe00000) {
236
		data = __raw_readw(PSCR);
M
Magnus Damm 已提交
237
		data &= ~0x03cf;
238
		if (!(cflag & CRTSCTS))
M
Magnus Damm 已提交
239
			data |= 0x0340;
P
Paul Mundt 已提交
240

241
		__raw_writew(data, PSCR);
P
Paul Mundt 已提交
242
	}
243
}
244 245
#elif defined(CONFIG_CPU_SUBTYPE_SH7757) || \
      defined(CONFIG_CPU_SUBTYPE_SH7763) || \
246
      defined(CONFIG_CPU_SUBTYPE_SH7780) || \
247
      defined(CONFIG_CPU_SUBTYPE_SH7785) || \
248
      defined(CONFIG_CPU_SUBTYPE_SH7786) || \
249
      defined(CONFIG_CPU_SUBTYPE_SHX3)
250 251 252 253 254
static inline void sci_init_pins(struct uart_port *port, unsigned int cflag)
{
	if (!(cflag & CRTSCTS))
		__raw_writew(0x0080, SCSPTR0); /* Set RTS = 1 */
}
255
#elif defined(CONFIG_CPU_SH4) && !defined(CONFIG_CPU_SH4A)
256 257 258 259 260
static inline void sci_init_pins(struct uart_port *port, unsigned int cflag)
{
	if (!(cflag & CRTSCTS))
		__raw_writew(0x0080, SCSPTR2); /* Set RTS = 1 */
}
261
#else
262 263 264
static inline void sci_init_pins(struct uart_port *port, unsigned int cflag)
{
	/* Nothing to do */
L
Linus Torvalds 已提交
265
}
266 267
#endif

268 269
#if defined(CONFIG_CPU_SUBTYPE_SH7760) || \
    defined(CONFIG_CPU_SUBTYPE_SH7780) || \
270 271
    defined(CONFIG_CPU_SUBTYPE_SH7785) || \
    defined(CONFIG_CPU_SUBTYPE_SH7786)
272 273
static inline int scif_txroom(struct uart_port *port)
{
274
	return SCIF_TXROOM_MAX - (sci_in(port, SCTFDR) & 0xff);
275 276 277 278
}

static inline int scif_rxroom(struct uart_port *port)
{
279
	return sci_in(port, SCRFDR) & 0xff;
280
}
281 282 283
#elif defined(CONFIG_CPU_SUBTYPE_SH7763)
static inline int scif_txroom(struct uart_port *port)
{
284 285 286
	if ((port->mapbase == 0xffe00000) ||
	    (port->mapbase == 0xffe08000)) {
		/* SCIF0/1*/
287
		return SCIF_TXROOM_MAX - (sci_in(port, SCTFDR) & 0xff);
288 289
	} else {
		/* SCIF2 */
290
		return SCIF2_TXROOM_MAX - (sci_in(port, SCFDR) >> 8);
291
	}
292 293 294 295
}

static inline int scif_rxroom(struct uart_port *port)
{
296 297 298
	if ((port->mapbase == 0xffe00000) ||
	    (port->mapbase == 0xffe08000)) {
		/* SCIF0/1*/
299
		return sci_in(port, SCRFDR) & 0xff;
300 301
	} else {
		/* SCIF2 */
302
		return sci_in(port, SCFDR) & SCIF2_RFDC_MASK;
303
	}
304
}
305 306 307 308 309
#else
static inline int scif_txroom(struct uart_port *port)
{
	return SCIF_TXROOM_MAX - (sci_in(port, SCFDR) >> 8);
}
L
Linus Torvalds 已提交
310

311 312 313 314
static inline int scif_rxroom(struct uart_port *port)
{
	return sci_in(port, SCFDR) & SCIF_RFDC_MASK;
}
L
Linus Torvalds 已提交
315 316
#endif

317 318
static inline int sci_txroom(struct uart_port *port)
{
319
	return (sci_in(port, SCxSR) & SCI_TDRE) != 0;
320 321 322 323
}

static inline int sci_rxroom(struct uart_port *port)
{
324
	return (sci_in(port, SCxSR) & SCxSR_RDxF(port)) != 0;
325 326
}

L
Linus Torvalds 已提交
327 328 329 330 331 332
/* ********************************************************************** *
 *                   the interrupt related routines                       *
 * ********************************************************************** */

static void sci_transmit_chars(struct uart_port *port)
{
A
Alan Cox 已提交
333
	struct circ_buf *xmit = &port->state->xmit;
L
Linus Torvalds 已提交
334 335 336
	unsigned int stopped = uart_tx_stopped(port);
	unsigned short status;
	unsigned short ctrl;
337
	int count;
L
Linus Torvalds 已提交
338 339 340 341

	status = sci_in(port, SCxSR);
	if (!(status & SCxSR_TDxE(port))) {
		ctrl = sci_in(port, SCSCR);
342
		if (uart_circ_empty(xmit))
L
Linus Torvalds 已提交
343
			ctrl &= ~SCI_CTRL_FLAGS_TIE;
344
		else
L
Linus Torvalds 已提交
345 346 347 348 349
			ctrl |= SCI_CTRL_FLAGS_TIE;
		sci_out(port, SCSCR, ctrl);
		return;
	}

350
	if (port->type == PORT_SCI)
351
		count = sci_txroom(port);
352 353
	else
		count = scif_txroom(port);
L
Linus Torvalds 已提交
354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377

	do {
		unsigned char c;

		if (port->x_char) {
			c = port->x_char;
			port->x_char = 0;
		} else if (!uart_circ_empty(xmit) && !stopped) {
			c = xmit->buf[xmit->tail];
			xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
		} else {
			break;
		}

		sci_out(port, SCxTDR, c);

		port->icount.tx++;
	} while (--count > 0);

	sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port));

	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
		uart_write_wakeup(port);
	if (uart_circ_empty(xmit)) {
378
		sci_stop_tx(port);
L
Linus Torvalds 已提交
379 380 381
	} else {
		ctrl = sci_in(port, SCSCR);

382
		if (port->type != PORT_SCI) {
L
Linus Torvalds 已提交
383 384 385 386 387 388 389 390 391 392
			sci_in(port, SCxSR); /* Dummy read */
			sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port));
		}

		ctrl |= SCI_CTRL_FLAGS_TIE;
		sci_out(port, SCSCR, ctrl);
	}
}

/* On SH3, SCIF may read end-of-break as a space->mark char */
393
#define STEPFN(c)  ({int __c = (c); (((__c-1)|(__c)) == -1); })
L
Linus Torvalds 已提交
394

395
static inline void sci_receive_chars(struct uart_port *port)
L
Linus Torvalds 已提交
396
{
397
	struct sci_port *sci_port = to_sci_port(port);
A
Alan Cox 已提交
398
	struct tty_struct *tty = port->state->port.tty;
L
Linus Torvalds 已提交
399 400
	int i, count, copied = 0;
	unsigned short status;
A
Alan Cox 已提交
401
	unsigned char flag;
L
Linus Torvalds 已提交
402 403 404 405 406 407

	status = sci_in(port, SCxSR);
	if (!(status & SCxSR_RDxF(port)))
		return;

	while (1) {
408
		if (port->type == PORT_SCI)
409
			count = sci_rxroom(port);
410 411
		else
			count = scif_rxroom(port);
L
Linus Torvalds 已提交
412 413

		/* Don't copy more bytes than there is room for in the buffer */
A
Alan Cox 已提交
414
		count = tty_buffer_request_room(tty, count);
L
Linus Torvalds 已提交
415 416 417 418 419 420 421

		/* If for any reason we can't copy more data, we're done! */
		if (count == 0)
			break;

		if (port->type == PORT_SCI) {
			char c = sci_in(port, SCxRDR);
422 423
			if (uart_handle_sysrq_char(port, c) ||
			    sci_port->break_flag)
L
Linus Torvalds 已提交
424
				count = 0;
425
			else
426
				tty_insert_flip_char(tty, c, TTY_NORMAL);
L
Linus Torvalds 已提交
427
		} else {
428
			for (i = 0; i < count; i++) {
L
Linus Torvalds 已提交
429 430 431 432
				char c = sci_in(port, SCxRDR);
				status = sci_in(port, SCxSR);
#if defined(CONFIG_CPU_SH3)
				/* Skip "chars" during break */
433
				if (sci_port->break_flag) {
L
Linus Torvalds 已提交
434 435 436 437 438
					if ((c == 0) &&
					    (status & SCxSR_FER(port))) {
						count--; i--;
						continue;
					}
439

L
Linus Torvalds 已提交
440
					/* Nonzero => end-of-break */
441
					dev_dbg(port->dev, "debounce<%02x>\n", c);
442 443
					sci_port->break_flag = 0;

L
Linus Torvalds 已提交
444 445 446 447 448 449
					if (STEPFN(c)) {
						count--; i--;
						continue;
					}
				}
#endif /* CONFIG_CPU_SH3 */
450
				if (uart_handle_sysrq_char(port, c)) {
L
Linus Torvalds 已提交
451 452 453 454 455 456
					count--; i--;
					continue;
				}

				/* Store data and status */
				if (status&SCxSR_FER(port)) {
A
Alan Cox 已提交
457
					flag = TTY_FRAME;
458
					dev_notice(port->dev, "frame error\n");
L
Linus Torvalds 已提交
459
				} else if (status&SCxSR_PER(port)) {
A
Alan Cox 已提交
460
					flag = TTY_PARITY;
461
					dev_notice(port->dev, "parity error\n");
A
Alan Cox 已提交
462 463
				} else
					flag = TTY_NORMAL;
464

A
Alan Cox 已提交
465
				tty_insert_flip_char(tty, c, flag);
L
Linus Torvalds 已提交
466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500
			}
		}

		sci_in(port, SCxSR); /* dummy read */
		sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));

		copied += count;
		port->icount.rx += count;
	}

	if (copied) {
		/* Tell the rest of the system the news. New characters! */
		tty_flip_buffer_push(tty);
	} else {
		sci_in(port, SCxSR); /* dummy read */
		sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
	}
}

#define SCI_BREAK_JIFFIES (HZ/20)
/* The sci generates interrupts during the break,
 * 1 per millisecond or so during the break period, for 9600 baud.
 * So dont bother disabling interrupts.
 * But dont want more than 1 break event.
 * Use a kernel timer to periodically poll the rx line until
 * the break is finished.
 */
static void sci_schedule_break_timer(struct sci_port *port)
{
	port->break_timer.expires = jiffies + SCI_BREAK_JIFFIES;
	add_timer(&port->break_timer);
}
/* Ensure that two consecutive samples find the break over. */
static void sci_break_timer(unsigned long data)
{
501 502 503
	struct sci_port *port = (struct sci_port *)data;

	if (sci_rxd_in(&port->port) == 0) {
L
Linus Torvalds 已提交
504
		port->break_flag = 1;
505 506
		sci_schedule_break_timer(port);
	} else if (port->break_flag == 1) {
L
Linus Torvalds 已提交
507 508
		/* break is over. */
		port->break_flag = 2;
509 510 511
		sci_schedule_break_timer(port);
	} else
		port->break_flag = 0;
L
Linus Torvalds 已提交
512 513 514 515 516 517
}

static inline int sci_handle_errors(struct uart_port *port)
{
	int copied = 0;
	unsigned short status = sci_in(port, SCxSR);
A
Alan Cox 已提交
518
	struct tty_struct *tty = port->state->port.tty;
L
Linus Torvalds 已提交
519

520
	if (status & SCxSR_ORER(port)) {
L
Linus Torvalds 已提交
521
		/* overrun error */
522
		if (tty_insert_flip_char(tty, 0, TTY_OVERRUN))
A
Alan Cox 已提交
523
			copied++;
524 525

		dev_notice(port->dev, "overrun error");
L
Linus Torvalds 已提交
526 527
	}

528
	if (status & SCxSR_FER(port)) {
L
Linus Torvalds 已提交
529 530
		if (sci_rxd_in(port) == 0) {
			/* Notify of BREAK */
531
			struct sci_port *sci_port = to_sci_port(port);
532 533 534 535 536

			if (!sci_port->break_flag) {
				sci_port->break_flag = 1;
				sci_schedule_break_timer(sci_port);

L
Linus Torvalds 已提交
537
				/* Do sysrq handling. */
538
				if (uart_handle_break(port))
L
Linus Torvalds 已提交
539
					return 0;
540 541 542

				dev_dbg(port->dev, "BREAK detected\n");

543
				if (tty_insert_flip_char(tty, 0, TTY_BREAK))
544 545 546
					copied++;
			}

547
		} else {
L
Linus Torvalds 已提交
548
			/* frame error */
549
			if (tty_insert_flip_char(tty, 0, TTY_FRAME))
A
Alan Cox 已提交
550
				copied++;
551 552

			dev_notice(port->dev, "frame error\n");
L
Linus Torvalds 已提交
553 554 555
		}
	}

556
	if (status & SCxSR_PER(port)) {
L
Linus Torvalds 已提交
557
		/* parity error */
558 559
		if (tty_insert_flip_char(tty, 0, TTY_PARITY))
			copied++;
560 561

		dev_notice(port->dev, "parity error");
L
Linus Torvalds 已提交
562 563
	}

A
Alan Cox 已提交
564
	if (copied)
L
Linus Torvalds 已提交
565 566 567 568 569
		tty_flip_buffer_push(tty);

	return copied;
}

570 571
static inline int sci_handle_fifo_overrun(struct uart_port *port)
{
A
Alan Cox 已提交
572
	struct tty_struct *tty = port->state->port.tty;
573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590
	int copied = 0;

	if (port->type != PORT_SCIF)
		return 0;

	if ((sci_in(port, SCLSR) & SCIF_ORER) != 0) {
		sci_out(port, SCLSR, 0);

		tty_insert_flip_char(tty, 0, TTY_OVERRUN);
		tty_flip_buffer_push(tty);

		dev_notice(port->dev, "overrun error\n");
		copied++;
	}

	return copied;
}

L
Linus Torvalds 已提交
591 592 593 594
static inline int sci_handle_breaks(struct uart_port *port)
{
	int copied = 0;
	unsigned short status = sci_in(port, SCxSR);
A
Alan Cox 已提交
595
	struct tty_struct *tty = port->state->port.tty;
596
	struct sci_port *s = to_sci_port(port);
L
Linus Torvalds 已提交
597

598 599 600
	if (uart_handle_break(port))
		return 0;

601
	if (!s->break_flag && status & SCxSR_BRK(port)) {
L
Linus Torvalds 已提交
602 603 604 605 606
#if defined(CONFIG_CPU_SH3)
		/* Debounce break */
		s->break_flag = 1;
#endif
		/* Notify of BREAK */
607
		if (tty_insert_flip_char(tty, 0, TTY_BREAK))
A
Alan Cox 已提交
608
			copied++;
609 610

		dev_dbg(port->dev, "BREAK detected\n");
L
Linus Torvalds 已提交
611 612
	}

A
Alan Cox 已提交
613
	if (copied)
L
Linus Torvalds 已提交
614
		tty_flip_buffer_push(tty);
615

616 617
	copied += sci_handle_fifo_overrun(port);

L
Linus Torvalds 已提交
618 619 620
	return copied;
}

621
static irqreturn_t sci_rx_interrupt(int irq, void *port)
L
Linus Torvalds 已提交
622 623 624 625 626
{
	/* I think sci_receive_chars has to be called irrespective
	 * of whether the I_IXOFF is set, otherwise, how is the interrupt
	 * to be disabled?
	 */
627
	sci_receive_chars(port);
L
Linus Torvalds 已提交
628 629 630 631

	return IRQ_HANDLED;
}

632
static irqreturn_t sci_tx_interrupt(int irq, void *ptr)
L
Linus Torvalds 已提交
633 634
{
	struct uart_port *port = ptr;
635
	unsigned long flags;
L
Linus Torvalds 已提交
636

637
	spin_lock_irqsave(&port->lock, flags);
L
Linus Torvalds 已提交
638
	sci_transmit_chars(port);
639
	spin_unlock_irqrestore(&port->lock, flags);
L
Linus Torvalds 已提交
640 641 642 643

	return IRQ_HANDLED;
}

644
static irqreturn_t sci_er_interrupt(int irq, void *ptr)
L
Linus Torvalds 已提交
645 646 647 648 649 650 651 652 653 654 655
{
	struct uart_port *port = ptr;

	/* Handle errors */
	if (port->type == PORT_SCI) {
		if (sci_handle_errors(port)) {
			/* discard character in rx buffer */
			sci_in(port, SCxSR);
			sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
		}
	} else {
656
		sci_handle_fifo_overrun(port);
657
		sci_rx_interrupt(irq, ptr);
L
Linus Torvalds 已提交
658 659 660 661 662
	}

	sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));

	/* Kick the transmission */
663
	sci_tx_interrupt(irq, ptr);
L
Linus Torvalds 已提交
664 665 666 667

	return IRQ_HANDLED;
}

668
static irqreturn_t sci_br_interrupt(int irq, void *ptr)
L
Linus Torvalds 已提交
669 670 671 672 673 674 675 676 677 678
{
	struct uart_port *port = ptr;

	/* Handle BREAKs */
	sci_handle_breaks(port);
	sci_out(port, SCxSR, SCxSR_BREAK_CLEAR(port));

	return IRQ_HANDLED;
}

679
static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr)
L
Linus Torvalds 已提交
680
{
681
	unsigned short ssr_status, scr_status, err_enabled;
682 683
	struct uart_port *port = ptr;
	irqreturn_t ret = IRQ_NONE;
L
Linus Torvalds 已提交
684

685 686
	ssr_status = sci_in(port, SCxSR);
	scr_status = sci_in(port, SCSCR);
687
	err_enabled = scr_status & (SCI_CTRL_FLAGS_REIE | SCI_CTRL_FLAGS_RIE);
L
Linus Torvalds 已提交
688 689

	/* Tx Interrupt */
690
	if ((ssr_status & SCxSR_TDxE(port)) && (scr_status & SCI_CTRL_FLAGS_TIE))
691
		ret = sci_tx_interrupt(irq, ptr);
L
Linus Torvalds 已提交
692
	/* Rx Interrupt */
693
	if ((ssr_status & SCxSR_RDxF(port)) && (scr_status & SCI_CTRL_FLAGS_RIE))
694
		ret = sci_rx_interrupt(irq, ptr);
L
Linus Torvalds 已提交
695
	/* Error Interrupt */
696
	if ((ssr_status & SCxSR_ERRORS(port)) && err_enabled)
697
		ret = sci_er_interrupt(irq, ptr);
L
Linus Torvalds 已提交
698
	/* Break Interrupt */
699
	if ((ssr_status & SCxSR_BRK(port)) && err_enabled)
700
		ret = sci_br_interrupt(irq, ptr);
L
Linus Torvalds 已提交
701

702
	return ret;
L
Linus Torvalds 已提交
703 704 705 706 707 708
}

/*
 * Here we define a transistion notifier so that we can update all of our
 * ports' baud rate when the peripheral clock changes.
 */
709 710
static int sci_notifier(struct notifier_block *self,
			unsigned long phase, void *p)
L
Linus Torvalds 已提交
711
{
712 713 714 715
	struct sh_sci_priv *priv = container_of(self,
						struct sh_sci_priv, clk_nb);
	struct sci_port *sci_port;
	unsigned long flags;
L
Linus Torvalds 已提交
716 717

	if ((phase == CPUFREQ_POSTCHANGE) ||
718 719 720
	    (phase == CPUFREQ_RESUMECHANGE)) {
		spin_lock_irqsave(&priv->lock, flags);
		list_for_each_entry(sci_port, &priv->ports, node)
721
			sci_port->port.uartclk = clk_get_rate(sci_port->dclk);
722 723
		spin_unlock_irqrestore(&priv->lock, flags);
	}
L
Linus Torvalds 已提交
724 725 726

	return NOTIFY_OK;
}
727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747

static void sci_clk_enable(struct uart_port *port)
{
	struct sci_port *sci_port = to_sci_port(port);

	clk_enable(sci_port->dclk);
	sci_port->port.uartclk = clk_get_rate(sci_port->dclk);

	if (sci_port->iclk)
		clk_enable(sci_port->iclk);
}

static void sci_clk_disable(struct uart_port *port)
{
	struct sci_port *sci_port = to_sci_port(port);

	if (sci_port->iclk)
		clk_disable(sci_port->iclk);

	clk_disable(sci_port->dclk);
}
L
Linus Torvalds 已提交
748 749 750 751

static int sci_request_irq(struct sci_port *port)
{
	int i;
752
	irqreturn_t (*handlers[4])(int irq, void *ptr) = {
L
Linus Torvalds 已提交
753 754 755 756 757 758 759
		sci_er_interrupt, sci_rx_interrupt, sci_tx_interrupt,
		sci_br_interrupt,
	};
	const char *desc[] = { "SCI Receive Error", "SCI Receive Data Full",
			       "SCI Transmit Data Empty", "SCI Break" };

	if (port->irqs[0] == port->irqs[1]) {
760
		if (unlikely(!port->irqs[0]))
L
Linus Torvalds 已提交
761
			return -ENODEV;
762 763

		if (request_irq(port->irqs[0], sci_mpxed_interrupt,
P
Paul Mundt 已提交
764
				IRQF_DISABLED, "sci", port)) {
765
			dev_err(port->port.dev, "Can't allocate IRQ\n");
L
Linus Torvalds 已提交
766 767 768 769
			return -ENODEV;
		}
	} else {
		for (i = 0; i < ARRAY_SIZE(handlers); i++) {
770
			if (unlikely(!port->irqs[i]))
L
Linus Torvalds 已提交
771
				continue;
772

773
			if (request_irq(port->irqs[i], handlers[i],
P
Paul Mundt 已提交
774
					IRQF_DISABLED, desc[i], port)) {
775
				dev_err(port->port.dev, "Can't allocate IRQ\n");
L
Linus Torvalds 已提交
776 777 778 779 780 781 782 783 784 785 786 787
				return -ENODEV;
			}
		}
	}

	return 0;
}

static void sci_free_irq(struct sci_port *port)
{
	int i;

788 789 790
	if (port->irqs[0] == port->irqs[1])
		free_irq(port->irqs[0], port);
	else {
L
Linus Torvalds 已提交
791 792 793 794 795 796 797 798 799 800 801
		for (i = 0; i < ARRAY_SIZE(port->irqs); i++) {
			if (!port->irqs[i])
				continue;

			free_irq(port->irqs[i], port);
		}
	}
}

static unsigned int sci_tx_empty(struct uart_port *port)
{
802 803
	unsigned short status = sci_in(port, SCxSR);
	return status & SCxSR_TEND(port) ? TIOCSER_TEMT : 0;
L
Linus Torvalds 已提交
804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820
}

static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
	/* This routine is used for seting signals of: DTR, DCD, CTS/RTS */
	/* We use SCIF's hardware for CTS/RTS, so don't need any for that. */
	/* If you have signals for DTR and DCD, please implement here. */
}

static unsigned int sci_get_mctrl(struct uart_port *port)
{
	/* This routine is used for geting signals of: DTR, DCD, DSR, RI,
	   and CTS/RTS */

	return TIOCM_DTR | TIOCM_RTS | TIOCM_DSR;
}

821
static void sci_start_tx(struct uart_port *port)
L
Linus Torvalds 已提交
822
{
823
	unsigned short ctrl;
L
Linus Torvalds 已提交
824

825 826 827 828
	/* Set TIE (Transmit Interrupt Enable) bit in SCSCR */
	ctrl = sci_in(port, SCSCR);
	ctrl |= SCI_CTRL_FLAGS_TIE;
	sci_out(port, SCSCR, ctrl);
L
Linus Torvalds 已提交
829 830
}

831
static void sci_stop_tx(struct uart_port *port)
L
Linus Torvalds 已提交
832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872
{
	unsigned short ctrl;

	/* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */
	ctrl = sci_in(port, SCSCR);
	ctrl &= ~SCI_CTRL_FLAGS_TIE;
	sci_out(port, SCSCR, ctrl);
}

static void sci_start_rx(struct uart_port *port, unsigned int tty_start)
{
	unsigned short ctrl;

	/* Set RIE (Receive Interrupt Enable) bit in SCSCR */
	ctrl = sci_in(port, SCSCR);
	ctrl |= SCI_CTRL_FLAGS_RIE | SCI_CTRL_FLAGS_REIE;
	sci_out(port, SCSCR, ctrl);
}

static void sci_stop_rx(struct uart_port *port)
{
	unsigned short ctrl;

	/* Clear RIE (Receive Interrupt Enable) bit in SCSCR */
	ctrl = sci_in(port, SCSCR);
	ctrl &= ~(SCI_CTRL_FLAGS_RIE | SCI_CTRL_FLAGS_REIE);
	sci_out(port, SCSCR, ctrl);
}

static void sci_enable_ms(struct uart_port *port)
{
	/* Nothing here yet .. */
}

static void sci_break_ctl(struct uart_port *port, int break_state)
{
	/* Nothing here yet .. */
}

static int sci_startup(struct uart_port *port)
{
873
	struct sci_port *s = to_sci_port(port);
L
Linus Torvalds 已提交
874

875 876
	if (s->enable)
		s->enable(port);
L
Linus Torvalds 已提交
877 878

	sci_request_irq(s);
879
	sci_start_tx(port);
L
Linus Torvalds 已提交
880 881 882 883 884 885 886
	sci_start_rx(port, 1);

	return 0;
}

static void sci_shutdown(struct uart_port *port)
{
887
	struct sci_port *s = to_sci_port(port);
L
Linus Torvalds 已提交
888 889

	sci_stop_rx(port);
890
	sci_stop_tx(port);
L
Linus Torvalds 已提交
891 892
	sci_free_irq(s);

893 894
	if (s->disable)
		s->disable(port);
L
Linus Torvalds 已提交
895 896
}

A
Alan Cox 已提交
897 898
static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
			    struct ktermios *old)
L
Linus Torvalds 已提交
899
{
900
	unsigned int status, baud, smr_val, max_baud;
901
	int t = -1;
L
Linus Torvalds 已提交
902

903 904 905 906 907 908 909 910 911 912 913 914
	/*
	 * earlyprintk comes here early on with port->uartclk set to zero.
	 * the clock framework is not up and running at this point so here
	 * we assume that 115200 is the maximum baud rate. please note that
	 * the baud rate is not programmed during earlyprintk - it is assumed
	 * that the previous boot loader has enabled required clocks and
	 * setup the baud rate generator hardware for us already.
	 */
	max_baud = port->uartclk ? port->uartclk / 16 : 115200;

	baud = uart_get_baud_rate(port, termios, old, 0, max_baud);
	if (likely(baud && port->uartclk))
915
		t = SCBRR_VALUE(baud, port->uartclk);
916

L
Linus Torvalds 已提交
917 918 919 920 921 922
	do {
		status = sci_in(port, SCxSR);
	} while (!(status & SCxSR_TEND(port)));

	sci_out(port, SCSCR, 0x00);	/* TE=0, RE=0, CKE1=0 */

923
	if (port->type != PORT_SCI)
L
Linus Torvalds 已提交
924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940
		sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST);

	smr_val = sci_in(port, SCSMR) & 3;
	if ((termios->c_cflag & CSIZE) == CS7)
		smr_val |= 0x40;
	if (termios->c_cflag & PARENB)
		smr_val |= 0x20;
	if (termios->c_cflag & PARODD)
		smr_val |= 0x30;
	if (termios->c_cflag & CSTOPB)
		smr_val |= 0x08;

	uart_update_timeout(port, termios->c_cflag, baud);

	sci_out(port, SCSMR, smr_val);

	if (t > 0) {
941
		if (t >= 256) {
L
Linus Torvalds 已提交
942 943
			sci_out(port, SCSMR, (sci_in(port, SCSMR) & ~3) | 1);
			t >>= 2;
944
		} else
L
Linus Torvalds 已提交
945
			sci_out(port, SCSMR, sci_in(port, SCSMR) & ~3);
946

L
Linus Torvalds 已提交
947 948 949 950
		sci_out(port, SCBRR, t);
		udelay((1000000+(baud-1)) / baud); /* Wait one bit interval */
	}

951 952
	sci_init_pins(port, termios->c_cflag);
	sci_out(port, SCFCR, (termios->c_cflag & CRTSCTS) ? SCFCR_MCE : 0);
953

L
Linus Torvalds 已提交
954 955 956
	sci_out(port, SCSCR, SCSCR_INIT(port));

	if ((termios->c_cflag & CREAD) != 0)
957
		sci_start_rx(port, 0);
L
Linus Torvalds 已提交
958 959 960 961 962
}

static const char *sci_type(struct uart_port *port)
{
	switch (port->type) {
963 964 965 966 967 968 969 970
	case PORT_IRDA:
		return "irda";
	case PORT_SCI:
		return "sci";
	case PORT_SCIF:
		return "scif";
	case PORT_SCIFA:
		return "scifa";
L
Linus Torvalds 已提交
971 972
	}

P
Paul Mundt 已提交
973
	return NULL;
L
Linus Torvalds 已提交
974 975 976 977 978 979 980 981 982 983 984 985 986 987 988
}

static void sci_release_port(struct uart_port *port)
{
	/* Nothing here yet .. */
}

static int sci_request_port(struct uart_port *port)
{
	/* Nothing here yet .. */
	return 0;
}

static void sci_config_port(struct uart_port *port, int flags)
{
989
	struct sci_port *s = to_sci_port(port);
L
Linus Torvalds 已提交
990 991 992

	port->type = s->type;

993 994 995 996
	if (port->membase)
		return;

	if (port->flags & UPF_IOREMAP) {
997
		port->membase = ioremap_nocache(port->mapbase, 0x40);
998 999 1000 1001 1002 1003 1004 1005 1006 1007

		if (IS_ERR(port->membase))
			dev_err(port->dev, "can't remap port#%d\n", port->line);
	} else {
		/*
		 * For the simple (and majority of) cases where we don't
		 * need to do any remapping, just cast the cookie
		 * directly.
		 */
		port->membase = (void __iomem *)port->mapbase;
1008
	}
L
Linus Torvalds 已提交
1009 1010 1011 1012
}

static int sci_verify_port(struct uart_port *port, struct serial_struct *ser)
{
1013
	struct sci_port *s = to_sci_port(port);
L
Linus Torvalds 已提交
1014

Y
Yinghai Lu 已提交
1015
	if (ser->irq != s->irqs[SCIx_TXI_IRQ] || ser->irq > nr_irqs)
L
Linus Torvalds 已提交
1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040
		return -EINVAL;
	if (ser->baud_base < 2400)
		/* No paper tape reader for Mitch.. */
		return -EINVAL;

	return 0;
}

static struct uart_ops sci_uart_ops = {
	.tx_empty	= sci_tx_empty,
	.set_mctrl	= sci_set_mctrl,
	.get_mctrl	= sci_get_mctrl,
	.start_tx	= sci_start_tx,
	.stop_tx	= sci_stop_tx,
	.stop_rx	= sci_stop_rx,
	.enable_ms	= sci_enable_ms,
	.break_ctl	= sci_break_ctl,
	.startup	= sci_startup,
	.shutdown	= sci_shutdown,
	.set_termios	= sci_set_termios,
	.type		= sci_type,
	.release_port	= sci_release_port,
	.request_port	= sci_request_port,
	.config_port	= sci_config_port,
	.verify_port	= sci_verify_port,
1041 1042 1043 1044
#ifdef CONFIG_CONSOLE_POLL
	.poll_get_char	= sci_poll_get_char,
	.poll_put_char	= sci_poll_put_char,
#endif
L
Linus Torvalds 已提交
1045 1046
};

1047 1048
static void __devinit sci_init_single(struct platform_device *dev,
				      struct sci_port *sci_port,
1049 1050
				      unsigned int index,
				      struct plat_sci_port *p)
1051
{
M
Magnus Damm 已提交
1052 1053 1054
	sci_port->port.ops	= &sci_uart_ops;
	sci_port->port.iotype	= UPIO_MEM;
	sci_port->port.line	= index;
1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066

	switch (p->type) {
	case PORT_SCIFA:
		sci_port->port.fifosize = 64;
		break;
	case PORT_SCIF:
		sci_port->port.fifosize = 16;
		break;
	default:
		sci_port->port.fifosize = 1;
		break;
	}
1067 1068 1069 1070 1071 1072 1073 1074

	if (dev) {
		sci_port->iclk = p->clk ? clk_get(&dev->dev, p->clk) : NULL;
		sci_port->dclk = clk_get(&dev->dev, "peripheral_clk");
		sci_port->enable = sci_clk_enable;
		sci_port->disable = sci_clk_disable;
		sci_port->port.dev = &dev->dev;
	}
1075

M
Magnus Damm 已提交
1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087
	sci_port->break_timer.data = (unsigned long)sci_port;
	sci_port->break_timer.function = sci_break_timer;
	init_timer(&sci_port->break_timer);

	sci_port->port.mapbase	= p->mapbase;
	sci_port->port.membase	= p->membase;

	sci_port->port.irq	= p->irqs[SCIx_TXI_IRQ];
	sci_port->port.flags	= p->flags;
	sci_port->type		= sci_port->port.type = p->type;

	memcpy(&sci_port->irqs, &p->irqs, sizeof(p->irqs));
1088 1089
}

L
Linus Torvalds 已提交
1090
#ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102
static struct tty_driver *serial_console_device(struct console *co, int *index)
{
	struct uart_driver *p = &sci_uart_driver;
	*index = co->index;
	return p->tty_driver;
}

static void serial_console_putchar(struct uart_port *port, int ch)
{
	sci_poll_put_char(port, ch);
}

L
Linus Torvalds 已提交
1103 1104 1105 1106 1107 1108 1109
/*
 *	Print a string to the serial port trying not to disturb
 *	any possible real use of the port...
 */
static void serial_console_write(struct console *co, const char *s,
				 unsigned count)
{
1110
	struct uart_port *port = co->data;
1111
	struct sci_port *sci_port = to_sci_port(port);
M
Magnus Damm 已提交
1112
	unsigned short bits;
1113

1114 1115 1116 1117
	if (sci_port->enable)
		sci_port->enable(port);

	uart_console_write(port, s, count, serial_console_putchar);
M
Magnus Damm 已提交
1118 1119 1120 1121 1122

	/* wait until fifo is empty and last bit has been transmitted */
	bits = SCxSR_TDxE(port) | SCxSR_TEND(port);
	while ((sci_in(port, SCxSR) & bits) != bits)
		cpu_relax();
1123

1124
	if (sci_port->disable)
1125
		sci_port->disable(port);
L
Linus Torvalds 已提交
1126 1127
}

1128
static int __devinit serial_console_setup(struct console *co, char *options)
L
Linus Torvalds 已提交
1129
{
1130
	struct sci_port *sci_port;
L
Linus Torvalds 已提交
1131 1132 1133 1134 1135 1136 1137
	struct uart_port *port;
	int baud = 115200;
	int bits = 8;
	int parity = 'n';
	int flow = 'n';
	int ret;

1138 1139 1140 1141 1142 1143 1144 1145
	/*
	 * Check whether an invalid uart number has been specified, and
	 * if so, search for the first available port that does have
	 * console support.
	 */
	if (co->index >= SCI_NPORTS)
		co->index = 0;

1146 1147 1148 1149 1150 1151 1152 1153
	if (co->data) {
		port = co->data;
		sci_port = to_sci_port(port);
	} else {
		sci_port = &sci_ports[co->index];
		port = &sci_port->port;
		co->data = port;
	}
L
Linus Torvalds 已提交
1154 1155

	/*
1156 1157 1158 1159
	 * Also need to check port->type, we don't actually have any
	 * UPIO_PORT ports, but uart_report_port() handily misreports
	 * it anyways if we don't have a port available by the time this is
	 * called.
L
Linus Torvalds 已提交
1160
	 */
1161 1162 1163
	if (!port->type)
		return -ENODEV;

1164
	sci_config_port(port, 0);
1165

1166 1167
	if (sci_port->enable)
		sci_port->enable(port);
1168

L
Linus Torvalds 已提交
1169 1170 1171 1172 1173 1174 1175 1176 1177
	if (options)
		uart_parse_options(options, &baud, &parity, &bits, &flow);

	ret = uart_set_options(port, co, baud, parity, bits, flow);
#if defined(__H8300H__) || defined(__H8300S__)
	/* disable rx interrupt */
	if (ret == 0)
		sci_stop_rx(port);
#endif
1178
	/* TODO: disable clock */
L
Linus Torvalds 已提交
1179 1180 1181 1182 1183
	return ret;
}

static struct console serial_console = {
	.name		= "ttySC",
1184
	.device		= serial_console_device,
L
Linus Torvalds 已提交
1185 1186
	.write		= serial_console_write,
	.setup		= serial_console_setup,
P
Paul Mundt 已提交
1187
	.flags		= CON_PRINTBUFFER,
L
Linus Torvalds 已提交
1188 1189 1190 1191 1192 1193 1194 1195 1196
	.index		= -1,
};

static int __init sci_console_init(void)
{
	register_console(&serial_console);
	return 0;
}
console_initcall(sci_console_init);
1197 1198 1199 1200 1201 1202 1203 1204 1205

static struct sci_port early_serial_port;
static struct console early_serial_console = {
	.name           = "early_ttySC",
	.write          = serial_console_write,
	.flags          = CON_PRINTBUFFER,
};
static char early_serial_buf[32];

L
Linus Torvalds 已提交
1206 1207
#endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */

1208
#if defined(CONFIG_SERIAL_SH_SCI_CONSOLE)
1209
#define SCI_CONSOLE	(&serial_console)
L
Linus Torvalds 已提交
1210
#else
1211
#define SCI_CONSOLE	0
L
Linus Torvalds 已提交
1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222
#endif

static char banner[] __initdata =
	KERN_INFO "SuperH SCI(F) driver initialized\n";

static struct uart_driver sci_uart_driver = {
	.owner		= THIS_MODULE,
	.driver_name	= "sci",
	.dev_name	= "ttySC",
	.major		= SCI_MAJOR,
	.minor		= SCI_MINOR_START,
1223
	.nr		= SCI_NPORTS,
L
Linus Torvalds 已提交
1224 1225 1226
	.cons		= SCI_CONSOLE,
};

1227

1228
static int sci_remove(struct platform_device *dev)
1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244
{
	struct sh_sci_priv *priv = platform_get_drvdata(dev);
	struct sci_port *p;
	unsigned long flags;

	cpufreq_unregister_notifier(&priv->clk_nb, CPUFREQ_TRANSITION_NOTIFIER);

	spin_lock_irqsave(&priv->lock, flags);
	list_for_each_entry(p, &priv->ports, node)
		uart_remove_one_port(&sci_uart_driver, &p->port);
	spin_unlock_irqrestore(&priv->lock, flags);

	kfree(priv);
	return 0;
}

1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263
static int __devinit sci_probe_single(struct platform_device *dev,
				      unsigned int index,
				      struct plat_sci_port *p,
				      struct sci_port *sciport)
{
	struct sh_sci_priv *priv = platform_get_drvdata(dev);
	unsigned long flags;
	int ret;

	/* Sanity check */
	if (unlikely(index >= SCI_NPORTS)) {
		dev_notice(&dev->dev, "Attempting to register port "
			   "%d when only %d are available.\n",
			   index+1, SCI_NPORTS);
		dev_notice(&dev->dev, "Consider bumping "
			   "CONFIG_SERIAL_SH_SCI_NR_UARTS!\n");
		return 0;
	}

1264
	sci_init_single(dev, sciport, index, p);
1265 1266

	ret = uart_add_one_port(&sci_uart_driver, &sciport->port);
1267
	if (ret)
1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278
		return ret;

	INIT_LIST_HEAD(&sciport->node);

	spin_lock_irqsave(&priv->lock, flags);
	list_add(&sciport->node, &priv->ports);
	spin_unlock_irqrestore(&priv->lock, flags);

	return 0;
}

1279 1280 1281 1282 1283 1284 1285
/*
 * Register a set of serial devices attached to a platform device.  The
 * list is terminated with a zero flags entry, which means we expect
 * all entries to have at least UPF_BOOT_AUTOCONF set. Platforms that need
 * remapping (such as sh64) should also set UPF_IOREMAP.
 */
static int __devinit sci_probe(struct platform_device *dev)
L
Linus Torvalds 已提交
1286
{
1287
	struct plat_sci_port *p = dev->dev.platform_data;
1288
	struct sh_sci_priv *priv;
1289
	int i, ret = -EINVAL;
1290

1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305
#ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
	if (is_early_platform_device(dev)) {
		if (dev->id == -1)
			return -ENOTSUPP;
		early_serial_console.index = dev->id;
		early_serial_console.data = &early_serial_port.port;
		sci_init_single(NULL, &early_serial_port, dev->id, p);
		serial_console_setup(&early_serial_console, early_serial_buf);
		if (!strstr(early_serial_buf, "keep"))
			early_serial_console.flags |= CON_BOOT;
		register_console(&early_serial_console);
		return 0;
	}
#endif

1306 1307 1308 1309 1310 1311 1312 1313 1314 1315
	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
	if (!priv)
		return -ENOMEM;

	INIT_LIST_HEAD(&priv->ports);
	spin_lock_init(&priv->lock);
	platform_set_drvdata(dev, priv);

	priv->clk_nb.notifier_call = sci_notifier;
	cpufreq_register_notifier(&priv->clk_nb, CPUFREQ_TRANSITION_NOTIFIER);
L
Linus Torvalds 已提交
1316

1317 1318 1319
	if (dev->id != -1) {
		ret = sci_probe_single(dev, dev->id, p, &sci_ports[dev->id]);
		if (ret)
1320
			goto err_unreg;
1321 1322 1323 1324 1325
	} else {
		for (i = 0; p && p->flags != 0; p++, i++) {
			ret = sci_probe_single(dev, i, p, &sci_ports[i]);
			if (ret)
				goto err_unreg;
1326 1327
		}
	}
L
Linus Torvalds 已提交
1328 1329 1330 1331 1332

#ifdef CONFIG_SH_STANDARD_BIOS
	sh_bios_gdb_detach();
#endif

1333
	return 0;
1334 1335

err_unreg:
1336
	sci_remove(dev);
1337
	return ret;
L
Linus Torvalds 已提交
1338 1339
}

1340
static int sci_suspend(struct device *dev)
L
Linus Torvalds 已提交
1341
{
1342
	struct sh_sci_priv *priv = dev_get_drvdata(dev);
1343 1344
	struct sci_port *p;
	unsigned long flags;
1345

1346 1347 1348 1349
	spin_lock_irqsave(&priv->lock, flags);
	list_for_each_entry(p, &priv->ports, node)
		uart_suspend_port(&sci_uart_driver, &p->port);
	spin_unlock_irqrestore(&priv->lock, flags);
L
Linus Torvalds 已提交
1350

1351 1352
	return 0;
}
L
Linus Torvalds 已提交
1353

1354
static int sci_resume(struct device *dev)
1355
{
1356
	struct sh_sci_priv *priv = dev_get_drvdata(dev);
1357 1358
	struct sci_port *p;
	unsigned long flags;
1359

1360 1361 1362 1363
	spin_lock_irqsave(&priv->lock, flags);
	list_for_each_entry(p, &priv->ports, node)
		uart_resume_port(&sci_uart_driver, &p->port);
	spin_unlock_irqrestore(&priv->lock, flags);
1364 1365 1366 1367

	return 0;
}

1368
static const struct dev_pm_ops sci_dev_pm_ops = {
1369 1370 1371 1372
	.suspend	= sci_suspend,
	.resume		= sci_resume,
};

1373 1374
static struct platform_driver sci_driver = {
	.probe		= sci_probe,
1375
	.remove		= sci_remove,
1376 1377 1378
	.driver		= {
		.name	= "sh-sci",
		.owner	= THIS_MODULE,
1379
		.pm	= &sci_dev_pm_ops,
1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401
	},
};

static int __init sci_init(void)
{
	int ret;

	printk(banner);

	ret = uart_register_driver(&sci_uart_driver);
	if (likely(ret == 0)) {
		ret = platform_driver_register(&sci_driver);
		if (unlikely(ret))
			uart_unregister_driver(&sci_uart_driver);
	}

	return ret;
}

static void __exit sci_exit(void)
{
	platform_driver_unregister(&sci_driver);
L
Linus Torvalds 已提交
1402 1403 1404
	uart_unregister_driver(&sci_uart_driver);
}

1405 1406 1407 1408
#ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
early_platform_init_buffer("earlyprintk", &sci_driver,
			   early_serial_buf, ARRAY_SIZE(early_serial_buf));
#endif
L
Linus Torvalds 已提交
1409 1410 1411
module_init(sci_init);
module_exit(sci_exit);

1412
MODULE_LICENSE("GPL");
1413
MODULE_ALIAS("platform:sh-sci");