Commit e4bbb519 authored by Michal Simek's avatar Michal Simek Committed by Greg Kroah-Hartman

serial: uartps: Move register to probe based on run time detection

Register uart driver in probe to be able to register one device with
unique major/minor separately. Also calculate number of instances of
this driver to be able to call uart_unregister_driver() when there is no
instance.
Signed-off-by: default avatarMichal Simek <michal.simek@xilinx.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 14090ad1
...@@ -1394,6 +1394,9 @@ static const struct of_device_id cdns_uart_of_match[] = { ...@@ -1394,6 +1394,9 @@ static const struct of_device_id cdns_uart_of_match[] = {
}; };
MODULE_DEVICE_TABLE(of, cdns_uart_of_match); MODULE_DEVICE_TABLE(of, cdns_uart_of_match);
/* Temporary variable for storing number of instances */
static int instances;
/** /**
* cdns_uart_probe - Platform driver probe * cdns_uart_probe - Platform driver probe
* @pdev: Pointer to the platform device structure * @pdev: Pointer to the platform device structure
...@@ -1426,6 +1429,14 @@ static int cdns_uart_probe(struct platform_device *pdev) ...@@ -1426,6 +1429,14 @@ static int cdns_uart_probe(struct platform_device *pdev)
return -ENODEV; return -ENODEV;
} }
if (!cdns_uart_uart_driver.state) {
rc = uart_register_driver(&cdns_uart_uart_driver);
if (rc < 0) {
dev_err(&pdev->dev, "Failed to register driver\n");
return rc;
}
}
cdns_uart_data->cdns_uart_driver = &cdns_uart_uart_driver; cdns_uart_data->cdns_uart_driver = &cdns_uart_uart_driver;
match = of_match_node(cdns_uart_of_match, pdev->dev.of_node); match = of_match_node(cdns_uart_of_match, pdev->dev.of_node);
...@@ -1443,7 +1454,8 @@ static int cdns_uart_probe(struct platform_device *pdev) ...@@ -1443,7 +1454,8 @@ static int cdns_uart_probe(struct platform_device *pdev)
} }
if (IS_ERR(cdns_uart_data->pclk)) { if (IS_ERR(cdns_uart_data->pclk)) {
dev_err(&pdev->dev, "pclk clock not found.\n"); dev_err(&pdev->dev, "pclk clock not found.\n");
return PTR_ERR(cdns_uart_data->pclk); rc = PTR_ERR(cdns_uart_data->pclk);
goto err_out_unregister_driver;
} }
cdns_uart_data->uartclk = devm_clk_get(&pdev->dev, "uart_clk"); cdns_uart_data->uartclk = devm_clk_get(&pdev->dev, "uart_clk");
...@@ -1454,13 +1466,14 @@ static int cdns_uart_probe(struct platform_device *pdev) ...@@ -1454,13 +1466,14 @@ static int cdns_uart_probe(struct platform_device *pdev)
} }
if (IS_ERR(cdns_uart_data->uartclk)) { if (IS_ERR(cdns_uart_data->uartclk)) {
dev_err(&pdev->dev, "uart_clk clock not found.\n"); dev_err(&pdev->dev, "uart_clk clock not found.\n");
return PTR_ERR(cdns_uart_data->uartclk); rc = PTR_ERR(cdns_uart_data->uartclk);
goto err_out_unregister_driver;
} }
rc = clk_prepare_enable(cdns_uart_data->pclk); rc = clk_prepare_enable(cdns_uart_data->pclk);
if (rc) { if (rc) {
dev_err(&pdev->dev, "Unable to enable pclk clock.\n"); dev_err(&pdev->dev, "Unable to enable pclk clock.\n");
return rc; goto err_out_unregister_driver;
} }
rc = clk_prepare_enable(cdns_uart_data->uartclk); rc = clk_prepare_enable(cdns_uart_data->uartclk);
if (rc) { if (rc) {
...@@ -1539,6 +1552,7 @@ static int cdns_uart_probe(struct platform_device *pdev) ...@@ -1539,6 +1552,7 @@ static int cdns_uart_probe(struct platform_device *pdev)
console_port = NULL; console_port = NULL;
#endif #endif
instances++;
return 0; return 0;
err_out_pm_disable: err_out_pm_disable:
...@@ -1553,7 +1567,9 @@ static int cdns_uart_probe(struct platform_device *pdev) ...@@ -1553,7 +1567,9 @@ static int cdns_uart_probe(struct platform_device *pdev)
clk_disable_unprepare(cdns_uart_data->uartclk); clk_disable_unprepare(cdns_uart_data->uartclk);
err_out_clk_dis_pclk: err_out_clk_dis_pclk:
clk_disable_unprepare(cdns_uart_data->pclk); clk_disable_unprepare(cdns_uart_data->pclk);
err_out_unregister_driver:
if (!instances)
uart_unregister_driver(cdns_uart_data->cdns_uart_driver);
return rc; return rc;
} }
...@@ -1581,6 +1597,8 @@ static int cdns_uart_remove(struct platform_device *pdev) ...@@ -1581,6 +1597,8 @@ static int cdns_uart_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev); pm_runtime_set_suspended(&pdev->dev);
pm_runtime_dont_use_autosuspend(&pdev->dev); pm_runtime_dont_use_autosuspend(&pdev->dev);
if (!--instances)
uart_unregister_driver(cdns_uart_data->cdns_uart_driver);
return rc; return rc;
} }
...@@ -1596,28 +1614,14 @@ static struct platform_driver cdns_uart_platform_driver = { ...@@ -1596,28 +1614,14 @@ static struct platform_driver cdns_uart_platform_driver = {
static int __init cdns_uart_init(void) static int __init cdns_uart_init(void)
{ {
int retval = 0;
/* Register the cdns_uart driver with the serial core */
retval = uart_register_driver(&cdns_uart_uart_driver);
if (retval)
return retval;
/* Register the platform driver */ /* Register the platform driver */
retval = platform_driver_register(&cdns_uart_platform_driver); return platform_driver_register(&cdns_uart_platform_driver);
if (retval)
uart_unregister_driver(&cdns_uart_uart_driver);
return retval;
} }
static void __exit cdns_uart_exit(void) static void __exit cdns_uart_exit(void)
{ {
/* Unregister the platform driver */ /* Unregister the platform driver */
platform_driver_unregister(&cdns_uart_platform_driver); platform_driver_unregister(&cdns_uart_platform_driver);
/* Unregister the cdns_uart driver */
uart_unregister_driver(&cdns_uart_uart_driver);
} }
arch_initcall(cdns_uart_init); arch_initcall(cdns_uart_init);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment