File Index
Files and directories
Sign in
FILE

ccu_frac.c

File preview with syntax highlighting.

linux-6.19.14/drivers/clk/sunxi-ng/ccu_frac.c C
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * Copyright (C) 2016 Maxime Ripard
  4 * Maxime Ripard <maxime.ripard@free-electrons.com>
  5 */
  6
  7#include <linux/clk-provider.h>
  8#include <linux/io.h>
  9#include <linux/spinlock.h>
 10
 11#include "ccu_frac.h"
 12
 13bool ccu_frac_helper_is_enabled(struct ccu_common *common,
 14				struct ccu_frac_internal *cf)
 15{
 16	if (!(common->features & CCU_FEATURE_FRACTIONAL))
 17		return false;
 18
 19	return !(readl(common->base + common->reg) & cf->enable);
 20}
 21EXPORT_SYMBOL_NS_GPL(ccu_frac_helper_is_enabled, "SUNXI_CCU");
 22
 23void ccu_frac_helper_enable(struct ccu_common *common,
 24			    struct ccu_frac_internal *cf)
 25{
 26	unsigned long flags;
 27	u32 reg;
 28
 29	if (!(common->features & CCU_FEATURE_FRACTIONAL))
 30		return;
 31
 32	spin_lock_irqsave(common->lock, flags);
 33	reg = readl(common->base + common->reg);
 34	writel(reg & ~cf->enable, common->base + common->reg);
 35	spin_unlock_irqrestore(common->lock, flags);
 36}
 37EXPORT_SYMBOL_NS_GPL(ccu_frac_helper_enable, "SUNXI_CCU");
 38
 39void ccu_frac_helper_disable(struct ccu_common *common,
 40			     struct ccu_frac_internal *cf)
 41{
 42	unsigned long flags;
 43	u32 reg;
 44
 45	if (!(common->features & CCU_FEATURE_FRACTIONAL))
 46		return;
 47
 48	spin_lock_irqsave(common->lock, flags);
 49	reg = readl(common->base + common->reg);
 50	writel(reg | cf->enable, common->base + common->reg);
 51	spin_unlock_irqrestore(common->lock, flags);
 52}
 53EXPORT_SYMBOL_NS_GPL(ccu_frac_helper_disable, "SUNXI_CCU");
 54
 55bool ccu_frac_helper_has_rate(struct ccu_common *common,
 56			      struct ccu_frac_internal *cf,
 57			      unsigned long rate)
 58{
 59	if (!(common->features & CCU_FEATURE_FRACTIONAL))
 60		return false;
 61
 62	return (cf->rates[0] == rate) || (cf->rates[1] == rate);
 63}
 64EXPORT_SYMBOL_NS_GPL(ccu_frac_helper_has_rate, "SUNXI_CCU");
 65
 66unsigned long ccu_frac_helper_read_rate(struct ccu_common *common,
 67					struct ccu_frac_internal *cf)
 68{
 69	u32 reg;
 70
 71	pr_debug("%s: Read fractional\n", clk_hw_get_name(&common->hw));
 72
 73	if (!(common->features & CCU_FEATURE_FRACTIONAL))
 74		return 0;
 75
 76	pr_debug("%s: clock is fractional (rates %lu and %lu)\n",
 77		 clk_hw_get_name(&common->hw), cf->rates[0], cf->rates[1]);
 78
 79	reg = readl(common->base + common->reg);
 80
 81	pr_debug("%s: clock reg is 0x%x (select is 0x%x)\n",
 82		 clk_hw_get_name(&common->hw), reg, cf->select);
 83
 84	return (reg & cf->select) ? cf->rates[1] : cf->rates[0];
 85}
 86EXPORT_SYMBOL_NS_GPL(ccu_frac_helper_read_rate, "SUNXI_CCU");
 87
 88int ccu_frac_helper_set_rate(struct ccu_common *common,
 89			     struct ccu_frac_internal *cf,
 90			     unsigned long rate, u32 lock)
 91{
 92	unsigned long flags;
 93	u32 reg, sel;
 94
 95	if (!(common->features & CCU_FEATURE_FRACTIONAL))
 96		return -EINVAL;
 97
 98	if (cf->rates[0] == rate)
 99		sel = 0;
100	else if (cf->rates[1] == rate)
101		sel = cf->select;
102	else
103		return -EINVAL;
104
105	spin_lock_irqsave(common->lock, flags);
106	reg = readl(common->base + common->reg);
107	reg &= ~cf->select;
108	writel(reg | sel, common->base + common->reg);
109	spin_unlock_irqrestore(common->lock, flags);
110
111	ccu_helper_wait_for_lock(common, lock);
112
113	return 0;
114}
115EXPORT_SYMBOL_NS_GPL(ccu_frac_helper_set_rate, "SUNXI_CCU");
~/ Read-only file preview.