Merge tag 'clk-for-linus-20151104' of git://git.kernel.org/pub/scm/linux/kernel/git...
[firefly-linux-kernel-4.4.55.git] / drivers / clk / rockchip / clk-mmc-phase.c
index a797d8625f6d28718b91b94d6f479d65aa4455d0..2685644826a06ed5a6f21240ad8af040bf4b0b9e 100644 (file)
@@ -41,6 +41,8 @@ static unsigned long rockchip_mmc_recalc(struct clk_hw *hw,
 #define ROCKCHIP_MMC_DEGREE_MASK 0x3
 #define ROCKCHIP_MMC_DELAYNUM_OFFSET 2
 #define ROCKCHIP_MMC_DELAYNUM_MASK (0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET)
+#define ROCKCHIP_MMC_INIT_STATE_RESET 0x1
+#define ROCKCHIP_MMC_INIT_STATE_SHIFT 1
 
 #define PSECS_PER_SEC 1000000000000LL
 
@@ -69,7 +71,7 @@ static int rockchip_mmc_get_phase(struct clk_hw *hw)
 
                delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK);
                delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET;
-               degrees += delay_num * factor / 10000;
+               degrees += DIV_ROUND_CLOSEST(delay_num * factor, 10000);
        }
 
        return degrees % 360;
@@ -82,7 +84,7 @@ static int rockchip_mmc_set_phase(struct clk_hw *hw, int degrees)
        u8 nineties, remainder;
        u8 delay_num;
        u32 raw_value;
-       u64 delay;
+       u32 delay;
 
        nineties = degrees / 90;
        remainder = (degrees % 90);
@@ -110,12 +112,13 @@ static int rockchip_mmc_set_phase(struct clk_hw *hw, int degrees)
         * Convert to delay; do a little extra work to make sure we
         * don't overflow 32-bit / 64-bit numbers.
         */
-       delay = PSECS_PER_SEC;
+       delay = 10000000; /* PSECS_PER_SEC / 10000 / 10 */
        delay *= remainder;
-       do_div(delay, 10000);
-       do_div(delay, (rate / 1000) * 36 * ROCKCHIP_MMC_DELAY_ELEMENT_PSEC);
+       delay = DIV_ROUND_CLOSEST(delay,
+                       (rate / 1000) * 36 *
+                               (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10));
 
-       delay_num = (u8) min(delay, 255ULL);
+       delay_num = (u8) min_t(u32, delay, 255);
 
        raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0;
        raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET;
@@ -158,6 +161,15 @@ struct clk *rockchip_clk_register_mmc(const char *name,
        mmc_clock->reg = reg;
        mmc_clock->shift = shift;
 
+       /*
+        * Assert init_state to soft reset the CLKGEN
+        * for mmc tuning phase and degree
+        */
+       if (mmc_clock->shift == ROCKCHIP_MMC_INIT_STATE_SHIFT)
+               writel(HIWORD_UPDATE(ROCKCHIP_MMC_INIT_STATE_RESET,
+                                    ROCKCHIP_MMC_INIT_STATE_RESET,
+                                    mmc_clock->shift), mmc_clock->reg);
+
        clk = clk_register(NULL, &mmc_clock->hw);
        if (IS_ERR(clk))
                goto err_free;