diff options
author | Soren Brinkmann <soren.brinkmann@xilinx.com> | 2013-05-13 13:46:38 -0400 |
---|---|---|
committer | Michal Simek <michal.simek@xilinx.com> | 2013-05-27 03:21:22 -0400 |
commit | 30e1e28598c2674c133148d8aec6d431d7acd314 (patch) | |
tree | e17a5fba2151cf6d32d0f39b9d69910f85b71a9f /drivers/tty | |
parent | 0ee52b157b8ed88550ddd6291e54bb4bfabde364 (diff) |
arm: zynq: Migrate platform to clock controller
Migrate the Zynq platform and its drivers to use the new clock
controller driver.
Signed-off-by: Soren Brinkmann <soren.brinkmann@xilinx.com>
Cc: John Stultz <john.stultz@linaro.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.cz>
Cc: linux-serial@vger.kernel.org
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
Acked-by: Mike Turquette <mturquette@linaro.org>
Diffstat (limited to 'drivers/tty')
-rw-r--r-- | drivers/tty/serial/xilinx_uartps.c | 85 |
1 files changed, 67 insertions, 18 deletions
diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 4e5c77834c50..a4a3028103e3 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
15 | #include <linux/serial.h> | 15 | #include <linux/serial.h> |
16 | #include <linux/serial_core.h> | 16 | #include <linux/serial_core.h> |
17 | #include <linux/slab.h> | ||
17 | #include <linux/tty.h> | 18 | #include <linux/tty.h> |
18 | #include <linux/tty_flip.h> | 19 | #include <linux/tty_flip.h> |
19 | #include <linux/console.h> | 20 | #include <linux/console.h> |
@@ -139,6 +140,16 @@ | |||
139 | #define XUARTPS_SR_RXTRIG 0x00000001 /* Rx Trigger */ | 140 | #define XUARTPS_SR_RXTRIG 0x00000001 /* Rx Trigger */ |
140 | 141 | ||
141 | /** | 142 | /** |
143 | * struct xuartps - device data | ||
144 | * @refclk Reference clock | ||
145 | * @aperclk APB clock | ||
146 | */ | ||
147 | struct xuartps { | ||
148 | struct clk *refclk; | ||
149 | struct clk *aperclk; | ||
150 | }; | ||
151 | |||
152 | /** | ||
142 | * xuartps_isr - Interrupt handler | 153 | * xuartps_isr - Interrupt handler |
143 | * @irq: Irq number | 154 | * @irq: Irq number |
144 | * @dev_id: Id of the port | 155 | * @dev_id: Id of the port |
@@ -936,34 +947,55 @@ static int xuartps_probe(struct platform_device *pdev) | |||
936 | int rc; | 947 | int rc; |
937 | struct uart_port *port; | 948 | struct uart_port *port; |
938 | struct resource *res, *res2; | 949 | struct resource *res, *res2; |
939 | struct clk *clk; | 950 | struct xuartps *xuartps_data; |
940 | 951 | ||
941 | clk = of_clk_get(pdev->dev.of_node, 0); | 952 | xuartps_data = kzalloc(sizeof(*xuartps_data), GFP_KERNEL); |
942 | if (IS_ERR(clk)) { | 953 | if (!xuartps_data) |
943 | dev_err(&pdev->dev, "no clock specified\n"); | 954 | return -ENOMEM; |
944 | return PTR_ERR(clk); | 955 | |
956 | xuartps_data->aperclk = clk_get(&pdev->dev, "aper_clk"); | ||
957 | if (IS_ERR(xuartps_data->aperclk)) { | ||
958 | dev_err(&pdev->dev, "aper_clk clock not found.\n"); | ||
959 | rc = PTR_ERR(xuartps_data->aperclk); | ||
960 | goto err_out_free; | ||
961 | } | ||
962 | xuartps_data->refclk = clk_get(&pdev->dev, "ref_clk"); | ||
963 | if (IS_ERR(xuartps_data->refclk)) { | ||
964 | dev_err(&pdev->dev, "ref_clk clock not found.\n"); | ||
965 | rc = PTR_ERR(xuartps_data->refclk); | ||
966 | goto err_out_clk_put_aper; | ||
945 | } | 967 | } |
946 | 968 | ||
947 | rc = clk_prepare_enable(clk); | 969 | rc = clk_prepare_enable(xuartps_data->aperclk); |
970 | if (rc) { | ||
971 | dev_err(&pdev->dev, "Unable to enable APER clock.\n"); | ||
972 | goto err_out_clk_put; | ||
973 | } | ||
974 | rc = clk_prepare_enable(xuartps_data->refclk); | ||
948 | if (rc) { | 975 | if (rc) { |
949 | dev_err(&pdev->dev, "could not enable clock\n"); | 976 | dev_err(&pdev->dev, "Unable to enable device clock.\n"); |
950 | return -EBUSY; | 977 | goto err_out_clk_dis_aper; |
951 | } | 978 | } |
952 | 979 | ||
953 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 980 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
954 | if (!res) | 981 | if (!res) { |
955 | return -ENODEV; | 982 | rc = -ENODEV; |
983 | goto err_out_clk_disable; | ||
984 | } | ||
956 | 985 | ||
957 | res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | 986 | res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0); |
958 | if (!res2) | 987 | if (!res2) { |
959 | return -ENODEV; | 988 | rc = -ENODEV; |
989 | goto err_out_clk_disable; | ||
990 | } | ||
960 | 991 | ||
961 | /* Initialize the port structure */ | 992 | /* Initialize the port structure */ |
962 | port = xuartps_get_port(); | 993 | port = xuartps_get_port(); |
963 | 994 | ||
964 | if (!port) { | 995 | if (!port) { |
965 | dev_err(&pdev->dev, "Cannot get uart_port structure\n"); | 996 | dev_err(&pdev->dev, "Cannot get uart_port structure\n"); |
966 | return -ENODEV; | 997 | rc = -ENODEV; |
998 | goto err_out_clk_disable; | ||
967 | } else { | 999 | } else { |
968 | /* Register the port. | 1000 | /* Register the port. |
969 | * This function also registers this device with the tty layer | 1001 | * This function also registers this device with the tty layer |
@@ -972,18 +1004,31 @@ static int xuartps_probe(struct platform_device *pdev) | |||
972 | port->mapbase = res->start; | 1004 | port->mapbase = res->start; |
973 | port->irq = res2->start; | 1005 | port->irq = res2->start; |
974 | port->dev = &pdev->dev; | 1006 | port->dev = &pdev->dev; |
975 | port->uartclk = clk_get_rate(clk); | 1007 | port->uartclk = clk_get_rate(xuartps_data->refclk); |
976 | port->private_data = clk; | 1008 | port->private_data = xuartps_data; |
977 | dev_set_drvdata(&pdev->dev, port); | 1009 | dev_set_drvdata(&pdev->dev, port); |
978 | rc = uart_add_one_port(&xuartps_uart_driver, port); | 1010 | rc = uart_add_one_port(&xuartps_uart_driver, port); |
979 | if (rc) { | 1011 | if (rc) { |
980 | dev_err(&pdev->dev, | 1012 | dev_err(&pdev->dev, |
981 | "uart_add_one_port() failed; err=%i\n", rc); | 1013 | "uart_add_one_port() failed; err=%i\n", rc); |
982 | dev_set_drvdata(&pdev->dev, NULL); | 1014 | dev_set_drvdata(&pdev->dev, NULL); |
983 | return rc; | 1015 | goto err_out_clk_disable; |
984 | } | 1016 | } |
985 | return 0; | 1017 | return 0; |
986 | } | 1018 | } |
1019 | |||
1020 | err_out_clk_disable: | ||
1021 | clk_disable_unprepare(xuartps_data->refclk); | ||
1022 | err_out_clk_dis_aper: | ||
1023 | clk_disable_unprepare(xuartps_data->aperclk); | ||
1024 | err_out_clk_put: | ||
1025 | clk_put(xuartps_data->refclk); | ||
1026 | err_out_clk_put_aper: | ||
1027 | clk_put(xuartps_data->aperclk); | ||
1028 | err_out_free: | ||
1029 | kfree(xuartps_data); | ||
1030 | |||
1031 | return rc; | ||
987 | } | 1032 | } |
988 | 1033 | ||
989 | /** | 1034 | /** |
@@ -995,14 +1040,18 @@ static int xuartps_probe(struct platform_device *pdev) | |||
995 | static int xuartps_remove(struct platform_device *pdev) | 1040 | static int xuartps_remove(struct platform_device *pdev) |
996 | { | 1041 | { |
997 | struct uart_port *port = dev_get_drvdata(&pdev->dev); | 1042 | struct uart_port *port = dev_get_drvdata(&pdev->dev); |
998 | struct clk *clk = port->private_data; | 1043 | struct xuartps *xuartps_data = port->private_data; |
999 | int rc; | 1044 | int rc; |
1000 | 1045 | ||
1001 | /* Remove the xuartps port from the serial core */ | 1046 | /* Remove the xuartps port from the serial core */ |
1002 | rc = uart_remove_one_port(&xuartps_uart_driver, port); | 1047 | rc = uart_remove_one_port(&xuartps_uart_driver, port); |
1003 | dev_set_drvdata(&pdev->dev, NULL); | 1048 | dev_set_drvdata(&pdev->dev, NULL); |
1004 | port->mapbase = 0; | 1049 | port->mapbase = 0; |
1005 | clk_disable_unprepare(clk); | 1050 | clk_disable_unprepare(xuartps_data->refclk); |
1051 | clk_disable_unprepare(xuartps_data->aperclk); | ||
1052 | clk_put(xuartps_data->refclk); | ||
1053 | clk_put(xuartps_data->aperclk); | ||
1054 | kfree(xuartps_data); | ||
1006 | return rc; | 1055 | return rc; |
1007 | } | 1056 | } |
1008 | 1057 | ||