]> git.sur5r.net Git - u-boot/blobdiff - arch/arm/cpu/armv7/zynq/slcr.c
clock_am43xx:Set the MAC clock to /5 for OPP100
[u-boot] / arch / arm / cpu / armv7 / zynq / slcr.c
index e5fe9929827cd6117ec683d1986a804f998c9f29..2521589c07e9cf0c07a2f59990a521aafcfea7c8 100644 (file)
@@ -8,25 +8,75 @@
 #include <asm/io.h>
 #include <malloc.h>
 #include <asm/arch/hardware.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/arch/clk.h>
 
 #define SLCR_LOCK_MAGIC                0x767B
 #define SLCR_UNLOCK_MAGIC      0xDF0D
 
+#define SLCR_USB_L1_SEL                        0x04
+
 #define SLCR_IDCODE_MASK       0x1F000
 #define SLCR_IDCODE_SHIFT      12
 
+/*
+ * zynq_slcr_mio_get_status - Get the status of MIO peripheral.
+ *
+ * @peri_name: Name of the peripheral for checking MIO status
+ * @get_pins: Pointer to array of get pin for this peripheral
+ * @num_pins: Number of pins for this peripheral
+ * @mask: Mask value
+ * @check_val: Required check value to get the status of  periph
+ */
+struct zynq_slcr_mio_get_status {
+       const char *peri_name;
+       const int *get_pins;
+       int num_pins;
+       u32 mask;
+       u32 check_val;
+};
+
+static const int usb0_pins[] = {
+       28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39
+};
+
+static const int usb1_pins[] = {
+       40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
+};
+
+static const struct zynq_slcr_mio_get_status mio_periphs[] = {
+       {
+               "usb0",
+               usb0_pins,
+               ARRAY_SIZE(usb0_pins),
+               SLCR_USB_L1_SEL,
+               SLCR_USB_L1_SEL,
+       },
+       {
+               "usb1",
+               usb1_pins,
+               ARRAY_SIZE(usb1_pins),
+               SLCR_USB_L1_SEL,
+               SLCR_USB_L1_SEL,
+       },
+};
+
 static int slcr_lock = 1; /* 1 means locked, 0 means unlocked */
 
 void zynq_slcr_lock(void)
 {
-       if (!slcr_lock)
+       if (!slcr_lock) {
                writel(SLCR_LOCK_MAGIC, &slcr_base->slcr_lock);
+               slcr_lock = 1;
+       }
 }
 
 void zynq_slcr_unlock(void)
 {
-       if (slcr_lock)
+       if (slcr_lock) {
                writel(SLCR_UNLOCK_MAGIC, &slcr_base->slcr_unlock);
+               slcr_lock = 0;
+       }
 }
 
 /* Reset the entire system */
@@ -50,8 +100,10 @@ void zynq_slcr_cpu_reset(void)
 }
 
 /* Setup clk for network */
-void zynq_slcr_gem_clk_setup(u32 gem_id, u32 rclk, u32 clk)
+void zynq_slcr_gem_clk_setup(u32 gem_id, unsigned long clk_rate)
 {
+       int ret;
+
        zynq_slcr_unlock();
 
        if (gem_id > 1) {
@@ -59,18 +111,18 @@ void zynq_slcr_gem_clk_setup(u32 gem_id, u32 rclk, u32 clk)
                goto out;
        }
 
+       ret = zynq_clk_set_rate(gem0_clk + gem_id, clk_rate);
+       if (ret)
+               goto out;
+
        if (gem_id) {
-               /* Set divisors for appropriate frequency in GEM_CLK_CTRL */
-               writel(clk, &slcr_base->gem1_clk_ctrl);
                /* Configure GEM_RCLK_CTRL */
-               writel(rclk, &slcr_base->gem1_rclk_ctrl);
+               writel(1, &slcr_base->gem1_rclk_ctrl);
        } else {
-               /* Set divisors for appropriate frequency in GEM_CLK_CTRL */
-               writel(clk, &slcr_base->gem0_clk_ctrl);
                /* Configure GEM_RCLK_CTRL */
-               writel(rclk, &slcr_base->gem0_rclk_ctrl);
+               writel(1, &slcr_base->gem0_rclk_ctrl);
        }
-
+       udelay(100000);
 out:
        zynq_slcr_lock();
 }
@@ -79,8 +131,8 @@ void zynq_slcr_devcfg_disable(void)
 {
        zynq_slcr_unlock();
 
-       /* Disable AXI interface */
-       writel(0xFFFFFFFF, &slcr_base->fpga_rst_ctrl);
+       /* Disable AXI interface by asserting FPGA resets */
+       writel(0xF, &slcr_base->fpga_rst_ctrl);
 
        /* Set Level Shifters DT618760 */
        writel(0xA, &slcr_base->lvl_shftr_en);
@@ -95,14 +147,50 @@ void zynq_slcr_devcfg_enable(void)
        /* Set Level Shifters DT618760 */
        writel(0xF, &slcr_base->lvl_shftr_en);
 
-       /* Disable AXI interface */
+       /* Enable AXI interface by de-asserting FPGA resets */
        writel(0x0, &slcr_base->fpga_rst_ctrl);
 
        zynq_slcr_lock();
 }
 
+u32 zynq_slcr_get_boot_mode(void)
+{
+       /* Get the bootmode register value */
+       return readl(&slcr_base->boot_mode);
+}
+
 u32 zynq_slcr_get_idcode(void)
 {
        return (readl(&slcr_base->pss_idcode) & SLCR_IDCODE_MASK) >>
                                                        SLCR_IDCODE_SHIFT;
 }
+
+/*
+ * zynq_slcr_get_mio_pin_status - Get the MIO pin status of peripheral.
+ *
+ * @periph: Name of the peripheral
+ *
+ * Returns count to indicate the number of pins configured for the
+ * given @periph.
+ */
+int zynq_slcr_get_mio_pin_status(const char *periph)
+{
+       const struct zynq_slcr_mio_get_status *mio_ptr;
+       int val, i, j;
+       int mio = 0;
+
+       for (i = 0; i < ARRAY_SIZE(mio_periphs); i++) {
+               if (strcmp(periph, mio_periphs[i].peri_name) == 0) {
+                       mio_ptr = &mio_periphs[i];
+                       for (j = 0; j < mio_ptr->num_pins; j++) {
+                               val = readl(&slcr_base->mio_pin
+                                               [mio_ptr->get_pins[j]]);
+                               if ((val & mio_ptr->mask) == mio_ptr->check_val)
+                                       mio++;
+                       }
+                       break;
+               }
+       }
+
+       return mio;
+}