return state;
 }
 
-static int clk_periph_enable(struct clk_hw *hw)
+static void clk_periph_enable_locked(struct clk_hw *hw)
 {
        struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw);
-       unsigned long flags = 0;
-
-       spin_lock_irqsave(&periph_ref_lock, flags);
-
-       gate->enable_refcnt[gate->clk_num]++;
-       if (gate->enable_refcnt[gate->clk_num] > 1) {
-               spin_unlock_irqrestore(&periph_ref_lock, flags);
-               return 0;
-       }
 
        write_enb_set(periph_clk_to_bit(gate), gate);
        udelay(2);
                udelay(1);
                writel_relaxed(0, gate->clk_base + LVL2_CLK_GATE_OVRE);
        }
+}
+
+static void clk_periph_disable_locked(struct clk_hw *hw)
+{
+       struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw);
+
+       /*
+        * If peripheral is in the APB bus then read the APB bus to
+        * flush the write operation in apb bus. This will avoid the
+        * peripheral access after disabling clock
+        */
+       if (gate->flags & TEGRA_PERIPH_ON_APB)
+               tegra_read_chipid();
+
+       write_enb_clr(periph_clk_to_bit(gate), gate);
+}
+
+static int clk_periph_enable(struct clk_hw *hw)
+{
+       struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw);
+       unsigned long flags = 0;
+
+       spin_lock_irqsave(&periph_ref_lock, flags);
+
+       if (!gate->enable_refcnt[gate->clk_num]++)
+               clk_periph_enable_locked(hw);
 
        spin_unlock_irqrestore(&periph_ref_lock, flags);
 
 
        spin_lock_irqsave(&periph_ref_lock, flags);
 
-       gate->enable_refcnt[gate->clk_num]--;
-       if (gate->enable_refcnt[gate->clk_num] > 0) {
-               spin_unlock_irqrestore(&periph_ref_lock, flags);
-               return;
-       }
+       WARN_ON(!gate->enable_refcnt[gate->clk_num]);
+
+       if (--gate->enable_refcnt[gate->clk_num] == 0)
+               clk_periph_disable_locked(hw);
+
+       spin_unlock_irqrestore(&periph_ref_lock, flags);
+}
+
+static void clk_periph_disable_unused(struct clk_hw *hw)
+{
+       struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw);
+       unsigned long flags = 0;
+
+       spin_lock_irqsave(&periph_ref_lock, flags);
 
        /*
-        * If peripheral is in the APB bus then read the APB bus to
-        * flush the write operation in apb bus. This will avoid the
-        * peripheral access after disabling clock
+        * Some clocks are duplicated and some of them are marked as critical,
+        * like fuse and fuse_burn for example, thus the enable_refcnt will
+        * be non-zero here if the "unused" duplicate is disabled by CCF.
         */
-       if (gate->flags & TEGRA_PERIPH_ON_APB)
-               tegra_read_chipid();
-
-       write_enb_clr(periph_clk_to_bit(gate), gate);
+       if (!gate->enable_refcnt[gate->clk_num])
+               clk_periph_disable_locked(hw);
 
        spin_unlock_irqrestore(&periph_ref_lock, flags);
 }
        .is_enabled = clk_periph_is_enabled,
        .enable = clk_periph_enable,
        .disable = clk_periph_disable,
+       .disable_unused = clk_periph_disable_unused,
 };
 
 struct clk *tegra_clk_register_periph_gate(const char *name,
        gate->enable_refcnt = enable_refcnt;
        gate->regs = pregs;
 
-       if (read_enb(gate) & periph_clk_to_bit(gate))
-               enable_refcnt[clk_num]++;
-
        /* Data in .init is copied by clk_register(), so stack variable OK */
        gate->hw.init = &init;
 
 
        gate_ops->disable(gate_hw);
 }
 
+static void clk_periph_disable_unused(struct clk_hw *hw)
+{
+       struct tegra_clk_periph *periph = to_clk_periph(hw);
+       const struct clk_ops *gate_ops = periph->gate_ops;
+       struct clk_hw *gate_hw = &periph->gate.hw;
+
+       gate_ops->disable_unused(gate_hw);
+}
+
 static void clk_periph_restore_context(struct clk_hw *hw)
 {
        struct tegra_clk_periph *periph = to_clk_periph(hw);
        .is_enabled = clk_periph_is_enabled,
        .enable = clk_periph_enable,
        .disable = clk_periph_disable,
+       .disable_unused = clk_periph_disable_unused,
        .restore_context = clk_periph_restore_context,
 };
 
        .is_enabled = clk_periph_is_enabled,
        .enable = clk_periph_enable,
        .disable = clk_periph_disable,
+       .disable_unused = clk_periph_disable_unused,
        .restore_context = clk_periph_restore_context,
 };