Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Soren Brinkmann and committed by
Michal Simek
30e1e285 0ee52b15

+118 -80
+21 -50
arch/arm/boot/dts/zynq-7000.dtsi
··· 49 49 50 50 uart0: uart@e0000000 { 51 51 compatible = "xlnx,xuartps"; 52 + clocks = <&clkc 23>, <&clkc 40>; 53 + clock-names = "ref_clk", "aper_clk"; 52 54 reg = <0xE0000000 0x1000>; 53 55 interrupts = <0 27 4>; 54 - clocks = <&uart_clk 0>; 55 56 }; 56 57 57 58 uart1: uart@e0001000 { 58 59 compatible = "xlnx,xuartps"; 60 + clocks = <&clkc 24>, <&clkc 41>; 61 + clock-names = "ref_clk", "aper_clk"; 59 62 reg = <0xE0001000 0x1000>; 60 63 interrupts = <0 50 4>; 61 - clocks = <&uart_clk 1>; 62 64 }; 63 65 64 66 slcr: slcr@f8000000 { ··· 71 69 #address-cells = <1>; 72 70 #size-cells = <0>; 73 71 74 - ps_clk: ps_clk { 75 - #clock-cells = <0>; 76 - compatible = "fixed-clock"; 77 - /* clock-frequency set in board-specific file */ 78 - clock-output-names = "ps_clk"; 79 - }; 80 - armpll: armpll { 81 - #clock-cells = <0>; 82 - compatible = "xlnx,zynq-pll"; 83 - clocks = <&ps_clk>; 84 - reg = <0x100 0x110>; 85 - clock-output-names = "armpll"; 86 - }; 87 - ddrpll: ddrpll { 88 - #clock-cells = <0>; 89 - compatible = "xlnx,zynq-pll"; 90 - clocks = <&ps_clk>; 91 - reg = <0x104 0x114>; 92 - clock-output-names = "ddrpll"; 93 - }; 94 - iopll: iopll { 95 - #clock-cells = <0>; 96 - compatible = "xlnx,zynq-pll"; 97 - clocks = <&ps_clk>; 98 - reg = <0x108 0x118>; 99 - clock-output-names = "iopll"; 100 - }; 101 - uart_clk: uart_clk { 72 + clkc: clkc { 102 73 #clock-cells = <1>; 103 - compatible = "xlnx,zynq-periph-clock"; 104 - clocks = <&iopll &armpll &ddrpll>; 105 - reg = <0x154>; 106 - clock-output-names = "uart0_ref_clk", 107 - "uart1_ref_clk"; 108 - }; 109 - cpu_clk: cpu_clk { 110 - #clock-cells = <1>; 111 - compatible = "xlnx,zynq-cpu-clock"; 112 - clocks = <&iopll &armpll &ddrpll>; 113 - reg = <0x120 0x1C4>; 114 - clock-output-names = "cpu_6x4x", 115 - "cpu_3x2x", 116 - "cpu_2x", 117 - "cpu_1x"; 74 + compatible = "xlnx,ps7-clkc"; 75 + ps-clk-frequency = <33333333>; 76 + clock-output-names = "armpll", "ddrpll", "iopll", "cpu_6or4x", 77 + "cpu_3or2x", "cpu_2x", "cpu_1x", "ddr2x", "ddr3x", 78 + "dci", "lqspi", "smc", "pcap", "gem0", "gem1", 79 + "fclk0", "fclk1", "fclk2", "fclk3", "can0", "can1", 80 + "sdio0", "sdio1", "uart0", "uart1", "spi0", "spi1", 81 + "dma", "usb0_aper", "usb1_aper", "gem0_aper", 82 + "gem1_aper", "sdio0_aper", "sdio1_aper", 83 + "spi0_aper", "spi1_aper", "can0_aper", "can1_aper", 84 + "i2c0_aper", "i2c1_aper", "uart0_aper", "uart1_aper", 85 + "gpio_aper", "lqspi_aper", "smc_aper", "swdt", 86 + "dbg_trc", "dbg_apb"; 118 87 }; 119 88 }; 120 89 }; ··· 94 121 interrupt-parent = <&intc>; 95 122 interrupts = < 0 10 4 0 11 4 0 12 4 >; 96 123 compatible = "cdns,ttc"; 124 + clocks = <&clkc 6>; 97 125 reg = <0xF8001000 0x1000>; 98 - clocks = <&cpu_clk 3>; 99 - clock-names = "cpu_1x"; 100 126 clock-ranges; 101 127 }; 102 128 ··· 103 131 interrupt-parent = <&intc>; 104 132 interrupts = < 0 37 4 0 38 4 0 39 4 >; 105 133 compatible = "cdns,ttc"; 134 + clocks = <&clkc 6>; 106 135 reg = <0xF8002000 0x1000>; 107 - clocks = <&cpu_clk 3>; 108 - clock-names = "cpu_1x"; 109 136 clock-ranges; 110 137 }; 111 138 scutimer: scutimer@f8f00600 { ··· 112 141 interrupts = < 1 13 0x301 >; 113 142 compatible = "arm,cortex-a9-twd-timer"; 114 143 reg = < 0xf8f00600 0x20 >; 115 - clocks = <&cpu_clk 1>; 144 + clocks = <&clkc 4>; 116 145 } ; 117 146 }; 118 147 };
-4
arch/arm/boot/dts/zynq-zc702.dts
··· 28 28 }; 29 29 30 30 }; 31 - 32 - &ps_clk { 33 - clock-frequency = <33333330>; 34 - };
+1 -1
arch/arm/mach-zynq/slcr.c
··· 117 117 118 118 pr_info("%s mapped to %p\n", np->name, zynq_slcr_base); 119 119 120 - xilinx_zynq_clocks_init(zynq_slcr_base); 120 + zynq_clock_init(zynq_slcr_base); 121 121 122 122 of_node_put(np); 123 123
+1 -1
drivers/clk/Makefile
··· 27 27 obj-$(CONFIG_ARCH_SUNXI) += sunxi/ 28 28 obj-$(CONFIG_ARCH_U8500) += ux500/ 29 29 obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o 30 - obj-$(CONFIG_ARCH_ZYNQ) += clk-zynq.o 30 + obj-$(CONFIG_ARCH_ZYNQ) += zynq/ 31 31 obj-$(CONFIG_ARCH_TEGRA) += tegra/ 32 32 obj-$(CONFIG_PLAT_SAMSUNG) += samsung/ 33 33
+3
drivers/clk/zynq/Makefile
··· 1 + # Zynq clock specific Makefile 2 + 3 + obj-$(CONFIG_ARCH_ZYNQ) += clkc.o pll.o
+18 -5
drivers/clocksource/cadence_ttc_timer.c
··· 51 51 52 52 #define TTC_CNT_CNTRL_DISABLE_MASK 0x1 53 53 54 + #define TTC_CLK_CNTRL_CSRC_MASK (1 << 5) /* clock source */ 55 + 54 56 /* 55 57 * Setup the timers to use pre-scaling, using a fixed value for now that will 56 58 * work across most input frequency, but it may need to be more dynamic ··· 398 396 { 399 397 unsigned int irq; 400 398 void __iomem *timer_baseaddr; 401 - struct clk *clk; 399 + struct clk *clk_cs, *clk_ce; 402 400 static int initialized; 401 + int clksel; 403 402 404 403 if (initialized) 405 404 return; ··· 424 421 BUG(); 425 422 } 426 423 427 - clk = of_clk_get_by_name(timer, "cpu_1x"); 428 - if (IS_ERR(clk)) { 424 + clksel = __raw_readl(timer_baseaddr + TTC_CLK_CNTRL_OFFSET); 425 + clksel = !!(clksel & TTC_CLK_CNTRL_CSRC_MASK); 426 + clk_cs = of_clk_get(timer, clksel); 427 + if (IS_ERR(clk_cs)) { 429 428 pr_err("ERROR: timer input clock not found\n"); 430 429 BUG(); 431 430 } 432 431 433 - ttc_setup_clocksource(clk, timer_baseaddr); 434 - ttc_setup_clockevent(clk, timer_baseaddr + 4, irq); 432 + clksel = __raw_readl(timer_baseaddr + 4 + TTC_CLK_CNTRL_OFFSET); 433 + clksel = !!(clksel & TTC_CLK_CNTRL_CSRC_MASK); 434 + clk_ce = of_clk_get(timer, clksel); 435 + if (IS_ERR(clk_ce)) { 436 + pr_err("ERROR: timer input clock not found\n"); 437 + BUG(); 438 + } 439 + 440 + ttc_setup_clocksource(clk_cs, timer_baseaddr); 441 + ttc_setup_clockevent(clk_ce, timer_baseaddr + 4, irq); 435 442 436 443 pr_info("%s #0 at %p, irq=%d\n", timer->name, timer_baseaddr, irq); 437 444 }
+67 -18
drivers/tty/serial/xilinx_uartps.c
··· 14 14 #include <linux/platform_device.h> 15 15 #include <linux/serial.h> 16 16 #include <linux/serial_core.h> 17 + #include <linux/slab.h> 17 18 #include <linux/tty.h> 18 19 #include <linux/tty_flip.h> 19 20 #include <linux/console.h> ··· 138 137 #define XUARTPS_SR_TXEMPTY 0x00000008 /* TX FIFO empty */ 139 138 #define XUARTPS_SR_TXFULL 0x00000010 /* TX FIFO full */ 140 139 #define XUARTPS_SR_RXTRIG 0x00000001 /* Rx Trigger */ 140 + 141 + /** 142 + * struct xuartps - device data 143 + * @refclk Reference clock 144 + * @aperclk APB clock 145 + */ 146 + struct xuartps { 147 + struct clk *refclk; 148 + struct clk *aperclk; 149 + }; 141 150 142 151 /** 143 152 * xuartps_isr - Interrupt handler ··· 947 936 int rc; 948 937 struct uart_port *port; 949 938 struct resource *res, *res2; 950 - struct clk *clk; 939 + struct xuartps *xuartps_data; 951 940 952 - clk = of_clk_get(pdev->dev.of_node, 0); 953 - if (IS_ERR(clk)) { 954 - dev_err(&pdev->dev, "no clock specified\n"); 955 - return PTR_ERR(clk); 941 + xuartps_data = kzalloc(sizeof(*xuartps_data), GFP_KERNEL); 942 + if (!xuartps_data) 943 + return -ENOMEM; 944 + 945 + xuartps_data->aperclk = clk_get(&pdev->dev, "aper_clk"); 946 + if (IS_ERR(xuartps_data->aperclk)) { 947 + dev_err(&pdev->dev, "aper_clk clock not found.\n"); 948 + rc = PTR_ERR(xuartps_data->aperclk); 949 + goto err_out_free; 950 + } 951 + xuartps_data->refclk = clk_get(&pdev->dev, "ref_clk"); 952 + if (IS_ERR(xuartps_data->refclk)) { 953 + dev_err(&pdev->dev, "ref_clk clock not found.\n"); 954 + rc = PTR_ERR(xuartps_data->refclk); 955 + goto err_out_clk_put_aper; 956 956 } 957 957 958 - rc = clk_prepare_enable(clk); 958 + rc = clk_prepare_enable(xuartps_data->aperclk); 959 959 if (rc) { 960 - dev_err(&pdev->dev, "could not enable clock\n"); 961 - return -EBUSY; 960 + dev_err(&pdev->dev, "Unable to enable APER clock.\n"); 961 + goto err_out_clk_put; 962 + } 963 + rc = clk_prepare_enable(xuartps_data->refclk); 964 + if (rc) { 965 + dev_err(&pdev->dev, "Unable to enable device clock.\n"); 966 + goto err_out_clk_dis_aper; 962 967 } 963 968 964 969 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 965 - if (!res) 966 - return -ENODEV; 970 + if (!res) { 971 + rc = -ENODEV; 972 + goto err_out_clk_disable; 973 + } 967 974 968 975 res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 969 - if (!res2) 970 - return -ENODEV; 976 + if (!res2) { 977 + rc = -ENODEV; 978 + goto err_out_clk_disable; 979 + } 971 980 972 981 /* Initialize the port structure */ 973 982 port = xuartps_get_port(); 974 983 975 984 if (!port) { 976 985 dev_err(&pdev->dev, "Cannot get uart_port structure\n"); 977 - return -ENODEV; 986 + rc = -ENODEV; 987 + goto err_out_clk_disable; 978 988 } else { 979 989 /* Register the port. 980 990 * This function also registers this device with the tty layer ··· 1004 972 port->mapbase = res->start; 1005 973 port->irq = res2->start; 1006 974 port->dev = &pdev->dev; 1007 - port->uartclk = clk_get_rate(clk); 1008 - port->private_data = clk; 975 + port->uartclk = clk_get_rate(xuartps_data->refclk); 976 + port->private_data = xuartps_data; 1009 977 dev_set_drvdata(&pdev->dev, port); 1010 978 rc = uart_add_one_port(&xuartps_uart_driver, port); 1011 979 if (rc) { 1012 980 dev_err(&pdev->dev, 1013 981 "uart_add_one_port() failed; err=%i\n", rc); 1014 982 dev_set_drvdata(&pdev->dev, NULL); 1015 - return rc; 983 + goto err_out_clk_disable; 1016 984 } 1017 985 return 0; 1018 986 } 987 + 988 + err_out_clk_disable: 989 + clk_disable_unprepare(xuartps_data->refclk); 990 + err_out_clk_dis_aper: 991 + clk_disable_unprepare(xuartps_data->aperclk); 992 + err_out_clk_put: 993 + clk_put(xuartps_data->refclk); 994 + err_out_clk_put_aper: 995 + clk_put(xuartps_data->aperclk); 996 + err_out_free: 997 + kfree(xuartps_data); 998 + 999 + return rc; 1019 1000 } 1020 1001 1021 1002 /** ··· 1040 995 static int xuartps_remove(struct platform_device *pdev) 1041 996 { 1042 997 struct uart_port *port = dev_get_drvdata(&pdev->dev); 1043 - struct clk *clk = port->private_data; 998 + struct xuartps *xuartps_data = port->private_data; 1044 999 int rc; 1045 1000 1046 1001 /* Remove the xuartps port from the serial core */ 1047 1002 rc = uart_remove_one_port(&xuartps_uart_driver, port); 1048 1003 dev_set_drvdata(&pdev->dev, NULL); 1049 1004 port->mapbase = 0; 1050 - clk_disable_unprepare(clk); 1005 + clk_disable_unprepare(xuartps_data->refclk); 1006 + clk_disable_unprepare(xuartps_data->aperclk); 1007 + clk_put(xuartps_data->refclk); 1008 + clk_put(xuartps_data->aperclk); 1009 + kfree(xuartps_data); 1051 1010 return rc; 1052 1011 } 1053 1012
+7 -1
include/linux/clk/zynq.h
··· 1 1 /* 2 + * Copyright (C) 2013 Xilinx Inc. 2 3 * Copyright (C) 2012 National Instruments 3 4 * 4 5 * This program is free software; you can redistribute it and/or modify ··· 20 19 #ifndef __LINUX_CLK_ZYNQ_H_ 21 20 #define __LINUX_CLK_ZYNQ_H_ 22 21 23 - void __init xilinx_zynq_clocks_init(void __iomem *slcr); 22 + #include <linux/spinlock.h> 24 23 24 + void zynq_clock_init(void __iomem *slcr); 25 + 26 + struct clk *clk_register_zynq_pll(const char *name, const char *parent, 27 + void __iomem *pll_ctrl, void __iomem *pll_status, u8 lock_index, 28 + spinlock_t *lock); 25 29 #endif