Skip to content
atmel_serial.c 29.2 KiB
Newer Older
	UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);

	if (options)
		uart_parse_options(options, &baud, &parity, &bits, &flow);
	else
		atmel_console_get_options(port, &baud, &parity, &bits);

	return uart_set_options(port, co, baud, parity, bits, flow);
}

static struct uart_driver atmel_uart;
static struct console atmel_console = {
	.name		= ATMEL_DEVICENAME,
	.write		= atmel_console_write,
	.device		= uart_console_device,
	.setup		= atmel_console_setup,
	.flags		= CON_PRINTBUFFER,
	.index		= -1,
#define ATMEL_CONSOLE_DEVICE	&atmel_console
/*
 * Early console initialization (before VM subsystem initialized).
 */
static int __init atmel_console_init(void)
	if (atmel_default_console_device) {
		add_preferred_console(ATMEL_DEVICENAME,
				      atmel_default_console_device->id, NULL);
		atmel_init_port(&atmel_ports[atmel_default_console_device->id],
				atmel_default_console_device);
		register_console(&atmel_console);
console_initcall(atmel_console_init);
/*
 * Late console initialization.
 */
static int __init atmel_late_console_init(void)
	if (atmel_default_console_device
	    && !(atmel_console.flags & CON_ENABLED))
		register_console(&atmel_console);
core_initcall(atmel_late_console_init);
static inline bool atmel_is_console_port(struct uart_port *port)
{
	return port->cons && port->cons->index == port->line;
}

#define ATMEL_CONSOLE_DEVICE	NULL

static inline bool atmel_is_console_port(struct uart_port *port)
{
	return false;
}
static struct uart_driver atmel_uart = {
	.owner		= THIS_MODULE,
	.driver_name	= "atmel_serial",
	.dev_name	= ATMEL_DEVICENAME,
	.major		= SERIAL_ATMEL_MAJOR,
	.minor		= MINOR_START,
	.nr		= ATMEL_MAX_UART,
	.cons		= ATMEL_CONSOLE_DEVICE,
static int atmel_serial_suspend(struct platform_device *pdev,
				pm_message_t state)
	struct uart_port *port = platform_get_drvdata(pdev);
	struct atmel_uart_port *atmel_port = (struct atmel_uart_port *)port;
	if (device_may_wakeup(&pdev->dev)
	    && !at91_suspend_entering_slow_clock())
		enable_irq_wake(port->irq);
	else {
		uart_suspend_port(&atmel_uart, port);
		atmel_port->suspended = 1;
static int atmel_serial_resume(struct platform_device *pdev)
{
	struct uart_port *port = platform_get_drvdata(pdev);
	struct atmel_uart_port *atmel_port = (struct atmel_uart_port *)port;
	if (atmel_port->suspended) {
		uart_resume_port(&atmel_uart, port);
		atmel_port->suspended = 0;
#define atmel_serial_suspend NULL
#define atmel_serial_resume NULL
static int __devinit atmel_serial_probe(struct platform_device *pdev)
	struct atmel_uart_port *port;
	BUILD_BUG_ON(!is_power_of_2(ATMEL_SERIAL_RINGSIZE));

	port = &atmel_ports[pdev->id];
	atmel_init_port(port, pdev);
	ret = -ENOMEM;
	data = kmalloc(ATMEL_SERIAL_RINGSIZE, GFP_KERNEL);
	if (!data)
		goto err_alloc_ring;
	port->rx_ring.buf = data;

	ret = uart_add_one_port(&atmel_uart, &port->uart);
	if (ret)
		goto err_add_port;

	device_init_wakeup(&pdev->dev, 1);
	platform_set_drvdata(pdev, port);

	return 0;

err_add_port:
	kfree(port->rx_ring.buf);
	port->rx_ring.buf = NULL;
err_alloc_ring:
	if (!atmel_is_console_port(&port->uart)) {
		clk_disable(port->clk);
		clk_put(port->clk);
		port->clk = NULL;
static int __devexit atmel_serial_remove(struct platform_device *pdev)
{
	struct uart_port *port = platform_get_drvdata(pdev);
	struct atmel_uart_port *atmel_port = (struct atmel_uart_port *)port;
	int ret = 0;

	device_init_wakeup(&pdev->dev, 0);
	platform_set_drvdata(pdev, NULL);

	ret = uart_remove_one_port(&atmel_uart, port);

	tasklet_kill(&atmel_port->tasklet);
	kfree(atmel_port->rx_ring.buf);

	/* "port" is allocated statically, so we shouldn't free it */

	clk_disable(atmel_port->clk);
	clk_put(atmel_port->clk);
static struct platform_driver atmel_serial_driver = {
	.probe		= atmel_serial_probe,
	.remove		= __devexit_p(atmel_serial_remove),
	.suspend	= atmel_serial_suspend,
	.resume		= atmel_serial_resume,
static int __init atmel_serial_init(void)
	ret = uart_register_driver(&atmel_uart);
	ret = platform_driver_register(&atmel_serial_driver);
		uart_unregister_driver(&atmel_uart);
static void __exit atmel_serial_exit(void)
	platform_driver_unregister(&atmel_serial_driver);
	uart_unregister_driver(&atmel_uart);
module_init(atmel_serial_init);
module_exit(atmel_serial_exit);

MODULE_AUTHOR("Rick Bronson");
MODULE_DESCRIPTION("Atmel AT91 / AT32 serial port driver");
MODULE_LICENSE("GPL");