]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge tag 'zynq-cleanup-for-3.15-v2' of git://git.xilinx.com/linux-xlnx into next...
authorArnd Bergmann <arnd@arndb.de>
Thu, 27 Mar 2014 01:10:57 +0000 (02:10 +0100)
committerArnd Bergmann <arnd@arndb.de>
Thu, 27 Mar 2014 01:19:41 +0000 (02:19 +0100)
Merge "arm: Xilinx Zynq cleanup patches for v3.15" from Michal Simek:

- Redesign SLCR initialization to enable
  driver developing which targets SLCR space

* tag 'zynq-cleanup-for-3.15-v2' of git://git.xilinx.com/linux-xlnx:
  ARM: zynq: Add waituart implementation
  ARM: zynq: Move of_clk_init from clock driver
  ARM: zynq: Introduce zynq_slcr_unlock()
  ARM: zynq: Add and use zynq_slcr_read/write() helper functions
  ARM: zynq: Make zynq_slcr_base static
  ARM: zynq: Map I/O memory on clkc init
  ARM: zynq: Hang iomapped slcr address on device_node
  ARM: zynq: Split slcr in two parts
  ARM: zynq: Move clock_init from slcr to common
  arm: dt: zynq: Add fclk-enable property to clkc node

[Arnd: remove SOC_BUS support from pull request]

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Documentation/devicetree/bindings/clock/zynq-7000.txt
arch/arm/boot/dts/zynq-7000.dtsi
arch/arm/include/debug/zynq.S
arch/arm/mach-zynq/Kconfig
arch/arm/mach-zynq/common.c
arch/arm/mach-zynq/common.h
arch/arm/mach-zynq/slcr.c
drivers/clk/zynq/clkc.c
include/linux/clk/zynq.h

index 17b4a94916d6d87c9d1fb9f42da49522594b5e2d..d93746cf29751e9ada09eb02ff9a5797cd186e9f 100644 (file)
@@ -14,6 +14,7 @@ for all clock consumers of PS clocks.
 Required properties:
  - #clock-cells : Must be 1
  - compatible : "xlnx,ps7-clkc"
+ - reg : SLCR offset and size taken via syscon < 0x100 0x100 >
  - ps-clk-frequency : Frequency of the oscillator providing ps_clk in HZ
                      (usually 33 MHz oscillators are used for Zynq platforms)
  - clock-output-names : List of strings used to name the clock outputs. Shall be
@@ -87,10 +88,11 @@ Clock outputs:
  47: dbg_apb
 
 Example:
-       clkc: clkc {
+       clkc: clkc@100 {
                #clock-cells = <1>;
                compatible = "xlnx,ps7-clkc";
                ps-clk-frequency = <33333333>;
+               reg = <0x100 0x100>;
                clock-output-names = "armpll", "ddrpll", "iopll", "cpu_6or4x",
                                "cpu_3or2x", "cpu_2x", "cpu_1x", "ddr2x", "ddr3x",
                                "dci", "lqspi", "smc", "pcap", "gem0", "gem1",
index 8b67b19392eca7ac1359dfe1db0ec4a16e5d1ade..602e12eedb01511d1bc4e09575501d0f7f1c78ba 100644 (file)
                } ;
 
                slcr: slcr@f8000000 {
-                       compatible = "xlnx,zynq-slcr";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       compatible = "xlnx,zynq-slcr", "syscon";
                        reg = <0xF8000000 0x1000>;
-
-                       clocks {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-
-                               clkc: clkc {
-                                       #clock-cells = <1>;
-                                       compatible = "xlnx,ps7-clkc";
-                                       ps-clk-frequency = <33333333>;
-                                       clock-output-names = "armpll", "ddrpll", "iopll", "cpu_6or4x",
-                                                       "cpu_3or2x", "cpu_2x", "cpu_1x", "ddr2x", "ddr3x",
-                                                       "dci", "lqspi", "smc", "pcap", "gem0", "gem1",
-                                                       "fclk0", "fclk1", "fclk2", "fclk3", "can0", "can1",
-                                                       "sdio0", "sdio1", "uart0", "uart1", "spi0", "spi1",
-                                                       "dma", "usb0_aper", "usb1_aper", "gem0_aper",
-                                                       "gem1_aper", "sdio0_aper", "sdio1_aper",
-                                                       "spi0_aper", "spi1_aper", "can0_aper", "can1_aper",
-                                                       "i2c0_aper", "i2c1_aper", "uart0_aper", "uart1_aper",
-                                                       "gpio_aper", "lqspi_aper", "smc_aper", "swdt",
-                                                       "dbg_trc", "dbg_apb";
-                               };
+                       ranges;
+                       clkc: clkc@100 {
+                               #clock-cells = <1>;
+                               compatible = "xlnx,ps7-clkc";
+                               ps-clk-frequency = <33333333>;
+                               fclk-enable = <0>;
+                               clock-output-names = "armpll", "ddrpll", "iopll", "cpu_6or4x",
+                                               "cpu_3or2x", "cpu_2x", "cpu_1x", "ddr2x", "ddr3x",
+                                               "dci", "lqspi", "smc", "pcap", "gem0", "gem1",
+                                               "fclk0", "fclk1", "fclk2", "fclk3", "can0", "can1",
+                                               "sdio0", "sdio1", "uart0", "uart1", "spi0", "spi1",
+                                               "dma", "usb0_aper", "usb1_aper", "gem0_aper",
+                                               "gem1_aper", "sdio0_aper", "sdio1_aper",
+                                               "spi0_aper", "spi1_aper", "can0_aper", "can1_aper",
+                                               "i2c0_aper", "i2c1_aper", "uart0_aper", "uart1_aper",
+                                               "gpio_aper", "lqspi_aper", "smc_aper", "swdt",
+                                               "dbg_trc", "dbg_apb";
+                               reg = <0x100 0x100>;
                        };
                };
 
index f9aa9740a73f09676d5a963f47e2d8e4f7d83e6c..0b762fafa7586a092399f8864f1cfdeaf3ff05ce 100644 (file)
@@ -42,6 +42,9 @@
                .endm
 
                .macro  waituart,rd,rx
+1001:          ldr     \rd, [\rx, #UART_SR_OFFSET]
+               tst     \rd, #UART_SR_TXEMPTY
+               beq     1001b
                .endm
 
                .macro  busyuart,rd,rx
index 6b04260aa142da12e290b20aab00a35cc105d364..323e5053cb9fd5c621320f5ea13b9016f0149636 100644 (file)
@@ -14,5 +14,6 @@ config ARCH_ZYNQ
        select SPARSE_IRQ
        select CADENCE_TTC_TIMER
        select ARM_GLOBAL_TIMER
+       select MFD_SYSCON
        help
          Support for Xilinx Zynq ARM Cortex A9 Platform
index 8c09a8393fb63056a171e12351e3a52d35d5de4d..dca60d5ba756472b4f9e62fba0cfacce0583204c 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/cpumask.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include <linux/clk/zynq.h>
 #include <linux/clocksource.h>
 #include <linux/of_address.h>
@@ -72,11 +73,16 @@ static void __init zynq_init_machine(void)
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 
        platform_device_register(&zynq_cpuidle_device);
+
+       zynq_slcr_init();
 }
 
 static void __init zynq_timer_init(void)
 {
-       zynq_slcr_init();
+       zynq_early_slcr_init();
+
+       zynq_clock_init();
+       of_clk_init(NULL);
        clocksource_of_init();
 }
 
index c22c92cea8cb47e1baba978c93d99b6e8d5ab244..b097844d3175ad7ac8204cfd3dcfd3362e88c265 100644 (file)
@@ -20,6 +20,7 @@
 void zynq_secondary_startup(void);
 
 extern int zynq_slcr_init(void);
+extern int zynq_early_slcr_init(void);
 extern void zynq_slcr_system_reset(void);
 extern void zynq_slcr_cpu_stop(int cpu);
 extern void zynq_slcr_cpu_start(int cpu);
@@ -33,7 +34,6 @@ extern int zynq_cpun_start(u32 address, int cpu);
 extern struct smp_operations zynq_smp_ops __initdata;
 #endif
 
-extern void __iomem *zynq_slcr_base;
 extern void __iomem *zynq_scu_base;
 
 /* Hotplug */
index 1836d5a34606a6a252057e5d060f9f14583c2715..a37d49a6e6578cddf922f45cb8a87c6b306dae25 100644 (file)
@@ -15,7 +15,9 @@
  */
 
 #include <linux/io.h>
+#include <linux/mfd/syscon.h>
 #include <linux/of_address.h>
+#include <linux/regmap.h>
 #include <linux/clk/zynq.h>
 #include "common.h"
 
 #define SLCR_A9_CPU_CLKSTOP            0x10
 #define SLCR_A9_CPU_RST                        0x1
 
-void __iomem *zynq_slcr_base;
+static void __iomem *zynq_slcr_base;
+static struct regmap *zynq_slcr_regmap;
+
+/**
+ * zynq_slcr_write - Write to a register in SLCR block
+ *
+ * @val:       Value to write to the register
+ * @offset:    Register offset in SLCR block
+ *
+ * Return:     a negative value on error, 0 on success
+ */
+static int zynq_slcr_write(u32 val, u32 offset)
+{
+       if (!zynq_slcr_regmap) {
+               writel(val, zynq_slcr_base + offset);
+               return 0;
+       }
+
+       return regmap_write(zynq_slcr_regmap, offset, val);
+}
+
+/**
+ * zynq_slcr_read - Read a register in SLCR block
+ *
+ * @val:       Pointer to value to be read from SLCR
+ * @offset:    Register offset in SLCR block
+ *
+ * Return:     a negative value on error, 0 on success
+ */
+static int zynq_slcr_read(u32 *val, u32 offset)
+{
+       if (zynq_slcr_regmap)
+               return regmap_read(zynq_slcr_regmap, offset, val);
+
+       *val = readl(zynq_slcr_base + offset);
+
+       return 0;
+}
+
+/**
+ * zynq_slcr_unlock - Unlock SLCR registers
+ *
+ * Return:     a negative value on error, 0 on success
+ */
+static inline int zynq_slcr_unlock(void)
+{
+       zynq_slcr_write(SLCR_UNLOCK_MAGIC, SLCR_UNLOCK_OFFSET);
+
+       return 0;
+}
 
 /**
  * zynq_slcr_system_reset - Reset the entire system.
@@ -43,16 +94,16 @@ void zynq_slcr_system_reset(void)
         * Note that this seems to require raw i/o
         * functions or there's a lockup?
         */
-       writel(SLCR_UNLOCK_MAGIC, zynq_slcr_base + SLCR_UNLOCK_OFFSET);
+       zynq_slcr_unlock();
 
        /*
         * Clear 0x0F000000 bits of reboot status register to workaround
         * the FSBL not loading the bitstream after soft-reboot
         * This is a temporary solution until we know more.
         */
-       reboot = readl(zynq_slcr_base + SLCR_REBOOT_STATUS_OFFSET);
-       writel(reboot & 0xF0FFFFFF, zynq_slcr_base + SLCR_REBOOT_STATUS_OFFSET);
-       writel(1, zynq_slcr_base + SLCR_PS_RST_CTRL_OFFSET);
+       zynq_slcr_read(&reboot, SLCR_REBOOT_STATUS_OFFSET);
+       zynq_slcr_write(reboot & 0xF0FFFFFF, SLCR_REBOOT_STATUS_OFFSET);
+       zynq_slcr_write(1, SLCR_PS_RST_CTRL_OFFSET);
 }
 
 /**
@@ -61,11 +112,13 @@ void zynq_slcr_system_reset(void)
  */
 void zynq_slcr_cpu_start(int cpu)
 {
-       u32 reg = readl(zynq_slcr_base + SLCR_A9_CPU_RST_CTRL_OFFSET);
+       u32 reg;
+
+       zynq_slcr_read(&reg, SLCR_A9_CPU_RST_CTRL_OFFSET);
        reg &= ~(SLCR_A9_CPU_RST << cpu);
-       writel(reg, zynq_slcr_base + SLCR_A9_CPU_RST_CTRL_OFFSET);
+       zynq_slcr_write(reg, SLCR_A9_CPU_RST_CTRL_OFFSET);
        reg &= ~(SLCR_A9_CPU_CLKSTOP << cpu);
-       writel(reg, zynq_slcr_base + SLCR_A9_CPU_RST_CTRL_OFFSET);
+       zynq_slcr_write(reg, SLCR_A9_CPU_RST_CTRL_OFFSET);
 }
 
 /**
@@ -74,18 +127,39 @@ void zynq_slcr_cpu_start(int cpu)
  */
 void zynq_slcr_cpu_stop(int cpu)
 {
-       u32 reg = readl(zynq_slcr_base + SLCR_A9_CPU_RST_CTRL_OFFSET);
+       u32 reg;
+
+       zynq_slcr_read(&reg, SLCR_A9_CPU_RST_CTRL_OFFSET);
        reg |= (SLCR_A9_CPU_CLKSTOP | SLCR_A9_CPU_RST) << cpu;
-       writel(reg, zynq_slcr_base + SLCR_A9_CPU_RST_CTRL_OFFSET);
+       zynq_slcr_write(reg, SLCR_A9_CPU_RST_CTRL_OFFSET);
 }
 
 /**
- * zynq_slcr_init
- * Returns 0 on success, negative errno otherwise.
+ * zynq_slcr_init - Regular slcr driver init
+ *
+ * Return:     0 on success, negative errno otherwise.
  *
  * Called early during boot from platform code to remap SLCR area.
  */
 int __init zynq_slcr_init(void)
+{
+       zynq_slcr_regmap = syscon_regmap_lookup_by_compatible("xlnx,zynq-slcr");
+       if (IS_ERR(zynq_slcr_regmap)) {
+               pr_err("%s: failed to find zynq-slcr\n", __func__);
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+/**
+ * zynq_early_slcr_init - Early slcr init function
+ *
+ * Return:     0 on success, negative errno otherwise.
+ *
+ * Called very early during boot from platform code to unlock SLCR.
+ */
+int __init zynq_early_slcr_init(void)
 {
        struct device_node *np;
 
@@ -101,13 +175,13 @@ int __init zynq_slcr_init(void)
                BUG();
        }
 
+       np->data = (__force void *)zynq_slcr_base;
+
        /* unlock the SLCR so that registers can be changed */
-       writel(SLCR_UNLOCK_MAGIC, zynq_slcr_base + SLCR_UNLOCK_OFFSET);
+       zynq_slcr_unlock();
 
        pr_info("%s mapped to %p\n", np->name, zynq_slcr_base);
 
-       zynq_clock_init(zynq_slcr_base);
-
        of_node_put(np);
 
        return 0;
index 09dd0173ea0ae616dc4395f2b76724740310522c..c812b93a52b28774232e420a389c34b21aef5544 100644 (file)
 #include <linux/clk/zynq.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/io.h>
 
-static void __iomem *zynq_slcr_base_priv;
-
-#define SLCR_ARMPLL_CTRL               (zynq_slcr_base_priv + 0x100)
-#define SLCR_DDRPLL_CTRL               (zynq_slcr_base_priv + 0x104)
-#define SLCR_IOPLL_CTRL                        (zynq_slcr_base_priv + 0x108)
-#define SLCR_PLL_STATUS                        (zynq_slcr_base_priv + 0x10c)
-#define SLCR_ARM_CLK_CTRL              (zynq_slcr_base_priv + 0x120)
-#define SLCR_DDR_CLK_CTRL              (zynq_slcr_base_priv + 0x124)
-#define SLCR_DCI_CLK_CTRL              (zynq_slcr_base_priv + 0x128)
-#define SLCR_APER_CLK_CTRL             (zynq_slcr_base_priv + 0x12c)
-#define SLCR_GEM0_CLK_CTRL             (zynq_slcr_base_priv + 0x140)
-#define SLCR_GEM1_CLK_CTRL             (zynq_slcr_base_priv + 0x144)
-#define SLCR_SMC_CLK_CTRL              (zynq_slcr_base_priv + 0x148)
-#define SLCR_LQSPI_CLK_CTRL            (zynq_slcr_base_priv + 0x14c)
-#define SLCR_SDIO_CLK_CTRL             (zynq_slcr_base_priv + 0x150)
-#define SLCR_UART_CLK_CTRL             (zynq_slcr_base_priv + 0x154)
-#define SLCR_SPI_CLK_CTRL              (zynq_slcr_base_priv + 0x158)
-#define SLCR_CAN_CLK_CTRL              (zynq_slcr_base_priv + 0x15c)
-#define SLCR_CAN_MIOCLK_CTRL           (zynq_slcr_base_priv + 0x160)
-#define SLCR_DBG_CLK_CTRL              (zynq_slcr_base_priv + 0x164)
-#define SLCR_PCAP_CLK_CTRL             (zynq_slcr_base_priv + 0x168)
-#define SLCR_FPGA0_CLK_CTRL            (zynq_slcr_base_priv + 0x170)
-#define SLCR_621_TRUE                  (zynq_slcr_base_priv + 0x1c4)
-#define SLCR_SWDT_CLK_SEL              (zynq_slcr_base_priv + 0x304)
+static void __iomem *zynq_clkc_base;
+
+#define SLCR_ARMPLL_CTRL               (zynq_clkc_base + 0x00)
+#define SLCR_DDRPLL_CTRL               (zynq_clkc_base + 0x04)
+#define SLCR_IOPLL_CTRL                        (zynq_clkc_base + 0x08)
+#define SLCR_PLL_STATUS                        (zynq_clkc_base + 0x0c)
+#define SLCR_ARM_CLK_CTRL              (zynq_clkc_base + 0x20)
+#define SLCR_DDR_CLK_CTRL              (zynq_clkc_base + 0x24)
+#define SLCR_DCI_CLK_CTRL              (zynq_clkc_base + 0x28)
+#define SLCR_APER_CLK_CTRL             (zynq_clkc_base + 0x2c)
+#define SLCR_GEM0_CLK_CTRL             (zynq_clkc_base + 0x40)
+#define SLCR_GEM1_CLK_CTRL             (zynq_clkc_base + 0x44)
+#define SLCR_SMC_CLK_CTRL              (zynq_clkc_base + 0x48)
+#define SLCR_LQSPI_CLK_CTRL            (zynq_clkc_base + 0x4c)
+#define SLCR_SDIO_CLK_CTRL             (zynq_clkc_base + 0x50)
+#define SLCR_UART_CLK_CTRL             (zynq_clkc_base + 0x54)
+#define SLCR_SPI_CLK_CTRL              (zynq_clkc_base + 0x58)
+#define SLCR_CAN_CLK_CTRL              (zynq_clkc_base + 0x5c)
+#define SLCR_CAN_MIOCLK_CTRL           (zynq_clkc_base + 0x60)
+#define SLCR_DBG_CLK_CTRL              (zynq_clkc_base + 0x64)
+#define SLCR_PCAP_CLK_CTRL             (zynq_clkc_base + 0x68)
+#define SLCR_FPGA0_CLK_CTRL            (zynq_clkc_base + 0x70)
+#define SLCR_621_TRUE                  (zynq_clkc_base + 0xc4)
+#define SLCR_SWDT_CLK_SEL              (zynq_clkc_base + 0x204)
 
 #define NUM_MIO_PINS   54
 
@@ -569,8 +570,42 @@ static void __init zynq_clk_setup(struct device_node *np)
 
 CLK_OF_DECLARE(zynq_clkc, "xlnx,ps7-clkc", zynq_clk_setup);
 
-void __init zynq_clock_init(void __iomem *slcr_base)
+void __init zynq_clock_init(void)
 {
-       zynq_slcr_base_priv = slcr_base;
-       of_clk_init(NULL);
+       struct device_node *np;
+       struct device_node *slcr;
+       struct resource res;
+
+       np = of_find_compatible_node(NULL, NULL, "xlnx,ps7-clkc");
+       if (!np) {
+               pr_err("%s: clkc node not found\n", __func__);
+               goto np_err;
+       }
+
+       if (of_address_to_resource(np, 0, &res)) {
+               pr_err("%s: failed to get resource\n", np->name);
+               goto np_err;
+       }
+
+       slcr = of_get_parent(np);
+
+       if (slcr->data) {
+               zynq_clkc_base = (__force void __iomem *)slcr->data + res.start;
+       } else {
+               pr_err("%s: Unable to get I/O memory\n", np->name);
+               of_node_put(slcr);
+               goto np_err;
+       }
+
+       pr_info("%s: clkc starts at %p\n", __func__, zynq_clkc_base);
+
+       of_node_put(slcr);
+       of_node_put(np);
+
+       return;
+
+np_err:
+       of_node_put(np);
+       BUG();
+       return;
 }
index e062d317cccea96d5e6f6c236fc2cec8ef3108a1..7a5633b71533932c54bc69a22d33d503b8d6e772 100644 (file)
@@ -22,7 +22,7 @@
 
 #include <linux/spinlock.h>
 
-void zynq_clock_init(void __iomem *slcr);
+void zynq_clock_init(void);
 
 struct clk *clk_register_zynq_pll(const char *name, const char *parent,
                void __iomem *pll_ctrl, void __iomem *pll_status, u8 lock_index,