/* * It works on following logic: * * For enabling clock, enable = 1 * set2dis = 1 -> clear bit -> set = 0 * set2dis = 0 -> set bit -> set = 1 * * For disabling clock, enable = 0 * set2dis = 1 -> set bit -> set = 1 * set2dis = 0 -> clear bit -> set = 0 * * So, result is always: enable xor set2dis. */ static void clk_gate_endisable(struct clk_hw *hw, int enable) { struct clk_gate *gate = to_clk_gate(hw); int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0; unsigned long uninitialized_var(flags); u32 reg; set ^= enable; if (gate->lock) spin_lock_irqsave(gate->lock, flags); else __acquire(gate->lock); if (gate->flags & CLK_GATE_HIWORD_MASK) { reg = BIT(gate->bit_idx + 16); if (set) reg |= BIT(gate->bit_idx); } else { reg = clk_readl(gate->reg); if (set) reg |= BIT(gate->bit_idx); else reg &= ~BIT(gate->bit_idx); } clk_writel(reg, gate->reg); if (gate->lock) spin_unlock_irqrestore(gate->lock, flags); else __release(gate->lock); }
/* * It works on following logic: * * For enabling clock, enable = 1 * set2dis = 1 -> clear bit -> set = 0 * set2dis = 0 -> set bit -> set = 1 * * For disabling clock, enable = 0 * set2dis = 1 -> set bit -> set = 1 * set2dis = 0 -> clear bit -> set = 0 * * So, result is always: enable xor set2dis. */ static void clk_gate_endisable(struct clk_hw *hw, int enable) { struct clk_gate *gate = to_clk_gate(hw); int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0; unsigned long flags = 0; u32 reg; set ^= enable; #ifdef CONFIG_HISI_CLK #define CLK_GATE_ALWAYS_ON_MASK 0x4 if ((!set) && (gate->flags & CLK_GATE_ALWAYS_ON_MASK)) return; #endif if (gate->lock) spin_lock_irqsave(gate->lock, flags); if (gate->flags & CLK_GATE_HIWORD_MASK) { reg = BIT(gate->bit_idx + 16); if (set) reg |= BIT(gate->bit_idx); } else { reg = readl(gate->reg); if (set) reg |= BIT(gate->bit_idx); else reg &= ~BIT(gate->bit_idx); } writel(reg, gate->reg); if (gate->lock) spin_unlock_irqrestore(gate->lock, flags); }
/* * It works on following logic: * * For enabling clock, enable = 1 * set2dis = 1 -> clear bit -> set = 0 * set2dis = 0 -> set bit -> set = 1 * * For disabling clock, enable = 0 * set2dis = 1 -> set bit -> set = 1 * set2dis = 0 -> clear bit -> set = 0 * * So, result is always: enable xor set2dis. */ static void clk_gate_endisable(struct clk_hw *hw, int enable) { struct clk_gate *gate = to_clk_gate(hw); int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0; u32 reg; int ret; set ^= enable; if (gate->flags & CLK_GATE_HIWORD_MASK) { reg = BIT(gate->bit_idx + 16); } else { ret = zynqmp_pm_mmio_read((u32)(ulong)gate->reg, ®); if (ret) pr_warn_once("Read fail gate address: %x\n", (u32)(ulong)gate->reg); if (!set) reg &= ~BIT(gate->bit_idx); } if (set) reg |= BIT(gate->bit_idx); ret = zynqmp_pm_mmio_writel(reg, gate->reg); if (ret) pr_warn_once("Write failed gate address:%x\n", (u32)(ulong)reg); }
static int lpc18xx_ccu_gate_endisable(struct clk_hw *hw, bool enable) { struct clk_gate *gate = to_clk_gate(hw); u32 val; /* * Divider field is write only, so divider stat field must * be read so divider field can be set accordingly. */ val = clk_readl(gate->reg); if (val & LPC18XX_CCU_DIVSTAT) val |= LPC18XX_CCU_DIV; if (enable) { val |= LPC18XX_CCU_RUN; } else { /* * To safely disable a branch clock a squence of two separate * writes must be used. First write should set the AUTO bit * and the next write should clear the RUN bit. */ val |= LPC18XX_CCU_AUTO; clk_writel(val, gate->reg); val &= ~LPC18XX_CCU_RUN; } clk_writel(val, gate->reg); return 0; }
static void clk_gate_disable(struct clk_hw *hw) { struct clk_gate *gate = to_clk_gate(hw); if (gate->flags & CLK_GATE_SET_TO_DISABLE) clk_gate_set_bit(gate); else clk_gate_clear_bit(gate); }
void clk_hw_unregister_gate(struct clk_hw *hw) { struct clk_gate *gate; gate = to_clk_gate(hw); clk_hw_unregister(hw); kfree(gate); }
static int mtk_cg_bit_is_set(struct clk_hw *hw) { struct mtk_clk_gate *cg = to_clk_gate(hw); u32 val; regmap_read(cg->regmap, cg->sta_ofs, &val); val &= BIT(cg->bit); return val != 0; }
static int clk_gate_enable(struct clk_hw *hw) { struct clk_gate *gate = to_clk_gate(hw); if (gate->flags & CLK_GATE_SET_TO_DISABLE) clk_gate_clear_bit(gate); else clk_gate_set_bit(gate); return 0; }
void clk_unregister_gate(struct clk *clk) { struct clk_gate *gate; struct clk_hw *hw; hw = __clk_get_hw(clk); if (!hw) return; gate = to_clk_gate(hw); clk_unregister(clk); kfree(gate); }
static int clk_gate_is_enabled(struct clk_hw *hw) { u32 reg; struct clk_gate *gate = to_clk_gate(hw); reg = clk_readl(gate->reg); /* if a set bit disables this clk, flip it before masking */ if (gate->flags & CLK_GATE_SET_TO_DISABLE) reg ^= BIT(gate->bit_idx); reg &= BIT(gate->bit_idx); return reg ? 1 : 0; }
static struct clk *clk_gating_get_src( struct of_phandle_args *clkspec, void *data) { int n; if (clkspec->args_count < 1) return ERR_PTR(-EINVAL); for (n = 0; n < ctrl->num_gates; n++) { struct clk_gate *gate = to_clk_gate(__clk_get_hw(ctrl->gates[n])); if (clkspec->args[0] == gate->bit_idx) return ctrl->gates[n]; } return ERR_PTR(-ENODEV); }
static int zynqmp_clk_gate_is_enabled(struct clk_hw *hw) { u32 reg; int ret; struct clk_gate *gate = to_clk_gate(hw); ret = zynqmp_pm_mmio_read((u32)(ulong)gate->reg, ®); if (ret) pr_warn_once("Read failed gate address: %x\n", (u32)(ulong)gate->reg); /* if a set bit disables this clk, flip it before masking */ if (gate->flags & CLK_GATE_SET_TO_DISABLE) reg ^= BIT(gate->bit_idx); reg &= BIT(gate->bit_idx); return reg ? 1 : 0; }
static int cg_is_enabled(struct clk_hw *hw) { struct mtk_clk_gate *cg = to_clk_gate(hw); u32 mask; u32 val; int r; #ifdef Bring_Up return 0; #endif mask = BIT(cg->bit); val = mask & readl(cg->sta_addr); r = (cg->flags & CLK_GATE_INVERSE) ? (val != 0) : (val == 0); pr_debug("%d, %s, bit[%d]\n", r, __clk_get_name(hw->clk), (int)cg->bit); return r; }
static int clk_gate_is_enabled(struct clk_hw *hw) { u32 reg; struct clk_gate *gate = to_clk_gate(hw); #if !defined(CONFIG_MTK_LEGACY) /* FIXME: only for bring up */ printk("[CCF] %s: %s\n", __func__, __clk_get_name(hw->clk)); return 1; #endif /* !defined(CONFIG_MTK_LEGACY) */ reg = readl(gate->reg); /* if a set bit disables this clk, flip it before masking */ if (gate->flags & CLK_GATE_SET_TO_DISABLE) reg ^= BIT(gate->bit_idx); reg &= BIT(gate->bit_idx); return reg ? 1 : 0; }
static void cg_disable(struct clk_hw *hw) { unsigned long flags = 0; struct mtk_clk_gate *cg = to_clk_gate(hw); u32 mask = BIT(cg->bit); #ifdef Bring_Up pr_debug("[CCF] %s: %s, bit: %u\n", __func__, __clk_get_name(hw->clk), cg->bit); return; #endif pr_debug("%s, bit: %u\n", __clk_get_name(hw->clk), cg->bit); mtk_clk_lock(flags); if (cg->flags & CLK_GATE_INVERSE) cg_clr_mask(cg, mask); else cg_set_mask(cg, mask); mtk_clk_unlock(flags); }
/* * It works on following logic: * * For enabling clock, enable = 1 * set2dis = 1 -> clear bit -> set = 0 * set2dis = 0 -> set bit -> set = 1 * * For disabling clock, enable = 0 * set2dis = 1 -> set bit -> set = 1 * set2dis = 0 -> clear bit -> set = 0 * * So, result is always: enable xor set2dis. */ static void clk_gate_endisable(struct clk_hw *hw, int enable) { struct clk_gate *gate = to_clk_gate(hw); int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0; unsigned long flags = 0; u32 reg; set ^= enable; if (gate->lock) spin_lock_irqsave(gate->lock, flags); reg = readl(gate->reg); if (set) reg |= BIT(gate->bit_idx); else reg &= ~BIT(gate->bit_idx); writel(reg, gate->reg); if (gate->lock) spin_unlock_irqrestore(gate->lock, flags); }
static void mtk_cg_clr_bit(struct clk_hw *hw) { struct mtk_clk_gate *cg = to_clk_gate(hw); regmap_write(cg->regmap, cg->clr_ofs, BIT(cg->bit)); }