Newer
Older
clk_put(atmel_port->clk);
atmel_port->clk = NULL;
err_clear_bit:
clear_bit(atmel_port->uart.line, atmel_ports_in_use);
/*
* Even if the driver is not modular, it makes sense to be able to
* unbind a device: there can be many bound devices, and there are
* situations where dynamic binding and unbinding can be useful.
*
* For example, a connected device can require a specific firmware update
* protocol that needs bitbanging on IO lines, but use the regular serial
* port in the normal case.
*/
static int atmel_serial_remove(struct platform_device *pdev)
{
struct uart_port *port = platform_get_drvdata(pdev);
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
int ret = 0;
tasklet_kill(&atmel_port->tasklet_rx);
tasklet_kill(&atmel_port->tasklet_tx);
device_init_wakeup(&pdev->dev, 0);
ret = uart_remove_one_port(&atmel_uart, port);
kfree(atmel_port->rx_ring.buf);
/* "port" is allocated statically, so we shouldn't free it */
clear_bit(port->line, atmel_ports_in_use);
clk_put(atmel_port->clk);
atmel_port->clk = NULL;
pdev->dev.of_node = NULL;
return ret;
}
static struct platform_driver atmel_serial_driver = {
.probe = atmel_serial_probe,
.remove = atmel_serial_remove,
.suspend = atmel_serial_suspend,
.resume = atmel_serial_resume,
.name = "atmel_usart_serial",
.of_match_table = of_match_ptr(atmel_serial_dt_ids),
static int __init atmel_serial_init(void)
ret = uart_register_driver(&atmel_uart);
if (ret)
return ret;
ret = platform_driver_register(&atmel_serial_driver);
uart_unregister_driver(&atmel_uart);
device_initcall(atmel_serial_init);