diff options
author | Soren Brinkmann <soren.brinkmann@xilinx.com> | 2013-05-13 19:46:38 +0200 |
---|---|---|
committer | Michal Simek <michal.simek@xilinx.com> | 2013-05-27 09:21:22 +0200 |
commit | 30e1e28598c2674c133148d8aec6d431d7acd314 (patch) | |
tree | e17a5fba2151cf6d32d0f39b9d69910f85b71a9f /drivers | |
parent | clk: zynq: Add clock controller driver (diff) | |
download | linux-30e1e28598c2674c133148d8aec6d431d7acd314.tar.xz linux-30e1e28598c2674c133148d8aec6d431d7acd314.zip |
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')
-rw-r--r-- | drivers/clk/Makefile | 2 | ||||
-rw-r--r-- | drivers/clk/zynq/Makefile | 3 | ||||
-rw-r--r-- | drivers/clocksource/cadence_ttc_timer.c | 23 | ||||
-rw-r--r-- | drivers/tty/serial/xilinx_uartps.c | 85 |
4 files changed, 89 insertions, 24 deletions
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 137d3e730f86..fa435bcf9f1a 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -27,7 +27,7 @@ obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o obj-$(CONFIG_ARCH_SUNXI) += sunxi/ obj-$(CONFIG_ARCH_U8500) += ux500/ obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o -obj-$(CONFIG_ARCH_ZYNQ) += clk-zynq.o +obj-$(CONFIG_ARCH_ZYNQ) += zynq/ obj-$(CONFIG_ARCH_TEGRA) += tegra/ obj-$(CONFIG_PLAT_SAMSUNG) += samsung/ diff --git a/drivers/clk/zynq/Makefile b/drivers/clk/zynq/Makefile new file mode 100644 index 000000000000..156d923f4fa9 --- /dev/null +++ b/drivers/clk/zynq/Makefile @@ -0,0 +1,3 @@ +# Zynq clock specific Makefile + +obj-$(CONFIG_ARCH_ZYNQ) += clkc.o pll.o diff --git a/drivers/clocksource/cadence_ttc_timer.c b/drivers/clocksource/cadence_ttc_timer.c index 685bc60e210a..4cbe28c74631 100644 --- a/drivers/clocksource/cadence_ttc_timer.c +++ b/drivers/clocksource/cadence_ttc_timer.c @@ -51,6 +51,8 @@ #define TTC_CNT_CNTRL_DISABLE_MASK 0x1 +#define TTC_CLK_CNTRL_CSRC_MASK (1 << 5) /* clock source */ + /* * Setup the timers to use pre-scaling, using a fixed value for now that will * work across most input frequency, but it may need to be more dynamic @@ -396,8 +398,9 @@ static void __init ttc_timer_init(struct device_node *timer) { unsigned int irq; void __iomem *timer_baseaddr; - struct clk *clk; + struct clk *clk_cs, *clk_ce; static int initialized; + int clksel; if (initialized) return; @@ -421,14 +424,24 @@ static void __init ttc_timer_init(struct device_node *timer) BUG(); } - clk = of_clk_get_by_name(timer, "cpu_1x"); - if (IS_ERR(clk)) { + clksel = __raw_readl(timer_baseaddr + TTC_CLK_CNTRL_OFFSET); + clksel = !!(clksel & TTC_CLK_CNTRL_CSRC_MASK); + clk_cs = of_clk_get(timer, clksel); + if (IS_ERR(clk_cs)) { + pr_err("ERROR: timer input clock not found\n"); + BUG(); + } + + clksel = __raw_readl(timer_baseaddr + 4 + TTC_CLK_CNTRL_OFFSET); + clksel = !!(clksel & TTC_CLK_CNTRL_CSRC_MASK); + clk_ce = of_clk_get(timer, clksel); + if (IS_ERR(clk_ce)) { pr_err("ERROR: timer input clock not found\n"); BUG(); } - ttc_setup_clocksource(clk, timer_baseaddr); - ttc_setup_clockevent(clk, timer_baseaddr + 4, irq); + ttc_setup_clocksource(clk_cs, timer_baseaddr); + ttc_setup_clockevent(clk_ce, timer_baseaddr + 4, irq); pr_info("%s #0 at %p, irq=%d\n", timer->name, timer_baseaddr, irq); } 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 @@ #include <linux/platform_device.h> #include <linux/serial.h> #include <linux/serial_core.h> +#include <linux/slab.h> #include <linux/tty.h> #include <linux/tty_flip.h> #include <linux/console.h> @@ -139,6 +140,16 @@ #define XUARTPS_SR_RXTRIG 0x00000001 /* Rx Trigger */ /** + * struct xuartps - device data + * @refclk Reference clock + * @aperclk APB clock + */ +struct xuartps { + struct clk *refclk; + struct clk *aperclk; +}; + +/** * xuartps_isr - Interrupt handler * @irq: Irq number * @dev_id: Id of the port @@ -936,34 +947,55 @@ static int xuartps_probe(struct platform_device *pdev) int rc; struct uart_port *port; struct resource *res, *res2; - struct clk *clk; + struct xuartps *xuartps_data; - clk = of_clk_get(pdev->dev.of_node, 0); - if (IS_ERR(clk)) { - dev_err(&pdev->dev, "no clock specified\n"); - return PTR_ERR(clk); + xuartps_data = kzalloc(sizeof(*xuartps_data), GFP_KERNEL); + if (!xuartps_data) + return -ENOMEM; + + xuartps_data->aperclk = clk_get(&pdev->dev, "aper_clk"); + if (IS_ERR(xuartps_data->aperclk)) { + dev_err(&pdev->dev, "aper_clk clock not found.\n"); + rc = PTR_ERR(xuartps_data->aperclk); + goto err_out_free; + } + xuartps_data->refclk = clk_get(&pdev->dev, "ref_clk"); + if (IS_ERR(xuartps_data->refclk)) { + dev_err(&pdev->dev, "ref_clk clock not found.\n"); + rc = PTR_ERR(xuartps_data->refclk); + goto err_out_clk_put_aper; } - rc = clk_prepare_enable(clk); + rc = clk_prepare_enable(xuartps_data->aperclk); + if (rc) { + dev_err(&pdev->dev, "Unable to enable APER clock.\n"); + goto err_out_clk_put; + } + rc = clk_prepare_enable(xuartps_data->refclk); if (rc) { - dev_err(&pdev->dev, "could not enable clock\n"); - return -EBUSY; + dev_err(&pdev->dev, "Unable to enable device clock.\n"); + goto err_out_clk_dis_aper; } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENODEV; + if (!res) { + rc = -ENODEV; + goto err_out_clk_disable; + } res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!res2) - return -ENODEV; + if (!res2) { + rc = -ENODEV; + goto err_out_clk_disable; + } /* Initialize the port structure */ port = xuartps_get_port(); if (!port) { dev_err(&pdev->dev, "Cannot get uart_port structure\n"); - return -ENODEV; + rc = -ENODEV; + goto err_out_clk_disable; } else { /* Register the port. * This function also registers this device with the tty layer @@ -972,18 +1004,31 @@ static int xuartps_probe(struct platform_device *pdev) port->mapbase = res->start; port->irq = res2->start; port->dev = &pdev->dev; - port->uartclk = clk_get_rate(clk); - port->private_data = clk; + port->uartclk = clk_get_rate(xuartps_data->refclk); + port->private_data = xuartps_data; dev_set_drvdata(&pdev->dev, port); rc = uart_add_one_port(&xuartps_uart_driver, port); if (rc) { dev_err(&pdev->dev, "uart_add_one_port() failed; err=%i\n", rc); dev_set_drvdata(&pdev->dev, NULL); - return rc; + goto err_out_clk_disable; } return 0; } + +err_out_clk_disable: + clk_disable_unprepare(xuartps_data->refclk); +err_out_clk_dis_aper: + clk_disable_unprepare(xuartps_data->aperclk); +err_out_clk_put: + clk_put(xuartps_data->refclk); +err_out_clk_put_aper: + clk_put(xuartps_data->aperclk); +err_out_free: + kfree(xuartps_data); + + return rc; } /** @@ -995,14 +1040,18 @@ static int xuartps_probe(struct platform_device *pdev) static int xuartps_remove(struct platform_device *pdev) { struct uart_port *port = dev_get_drvdata(&pdev->dev); - struct clk *clk = port->private_data; + struct xuartps *xuartps_data = port->private_data; int rc; /* Remove the xuartps port from the serial core */ rc = uart_remove_one_port(&xuartps_uart_driver, port); dev_set_drvdata(&pdev->dev, NULL); port->mapbase = 0; - clk_disable_unprepare(clk); + clk_disable_unprepare(xuartps_data->refclk); + clk_disable_unprepare(xuartps_data->aperclk); + clk_put(xuartps_data->refclk); + clk_put(xuartps_data->aperclk); + kfree(xuartps_data); return rc; } |