0001
0002
0003
0004
0005
0006 #include <linux/clk-provider.h>
0007 #include <linux/io.h>
0008 #include <linux/spinlock.h>
0009
0010 #include "ccu_sdm.h"
0011
0012 bool ccu_sdm_helper_is_enabled(struct ccu_common *common,
0013 struct ccu_sdm_internal *sdm)
0014 {
0015 if (!(common->features & CCU_FEATURE_SIGMA_DELTA_MOD))
0016 return false;
0017
0018 if (sdm->enable && !(readl(common->base + common->reg) & sdm->enable))
0019 return false;
0020
0021 return !!(readl(common->base + sdm->tuning_reg) & sdm->tuning_enable);
0022 }
0023 EXPORT_SYMBOL_NS_GPL(ccu_sdm_helper_is_enabled, SUNXI_CCU);
0024
0025 void ccu_sdm_helper_enable(struct ccu_common *common,
0026 struct ccu_sdm_internal *sdm,
0027 unsigned long rate)
0028 {
0029 unsigned long flags;
0030 unsigned int i;
0031 u32 reg;
0032
0033 if (!(common->features & CCU_FEATURE_SIGMA_DELTA_MOD))
0034 return;
0035
0036
0037 for (i = 0; i < sdm->table_size; i++)
0038 if (sdm->table[i].rate == rate)
0039 writel(sdm->table[i].pattern,
0040 common->base + sdm->tuning_reg);
0041
0042
0043 spin_lock_irqsave(common->lock, flags);
0044 reg = readl(common->base + sdm->tuning_reg);
0045 writel(reg | sdm->tuning_enable, common->base + sdm->tuning_reg);
0046 spin_unlock_irqrestore(common->lock, flags);
0047
0048 spin_lock_irqsave(common->lock, flags);
0049 reg = readl(common->base + common->reg);
0050 writel(reg | sdm->enable, common->base + common->reg);
0051 spin_unlock_irqrestore(common->lock, flags);
0052 }
0053 EXPORT_SYMBOL_NS_GPL(ccu_sdm_helper_enable, SUNXI_CCU);
0054
0055 void ccu_sdm_helper_disable(struct ccu_common *common,
0056 struct ccu_sdm_internal *sdm)
0057 {
0058 unsigned long flags;
0059 u32 reg;
0060
0061 if (!(common->features & CCU_FEATURE_SIGMA_DELTA_MOD))
0062 return;
0063
0064 spin_lock_irqsave(common->lock, flags);
0065 reg = readl(common->base + common->reg);
0066 writel(reg & ~sdm->enable, common->base + common->reg);
0067 spin_unlock_irqrestore(common->lock, flags);
0068
0069 spin_lock_irqsave(common->lock, flags);
0070 reg = readl(common->base + sdm->tuning_reg);
0071 writel(reg & ~sdm->tuning_enable, common->base + sdm->tuning_reg);
0072 spin_unlock_irqrestore(common->lock, flags);
0073 }
0074 EXPORT_SYMBOL_NS_GPL(ccu_sdm_helper_disable, SUNXI_CCU);
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093 bool ccu_sdm_helper_has_rate(struct ccu_common *common,
0094 struct ccu_sdm_internal *sdm,
0095 unsigned long rate)
0096 {
0097 unsigned int i;
0098
0099 if (!(common->features & CCU_FEATURE_SIGMA_DELTA_MOD))
0100 return false;
0101
0102 for (i = 0; i < sdm->table_size; i++)
0103 if (sdm->table[i].rate == rate)
0104 return true;
0105
0106 return false;
0107 }
0108 EXPORT_SYMBOL_NS_GPL(ccu_sdm_helper_has_rate, SUNXI_CCU);
0109
0110 unsigned long ccu_sdm_helper_read_rate(struct ccu_common *common,
0111 struct ccu_sdm_internal *sdm,
0112 u32 m, u32 n)
0113 {
0114 unsigned int i;
0115 u32 reg;
0116
0117 pr_debug("%s: Read sigma-delta modulation setting\n",
0118 clk_hw_get_name(&common->hw));
0119
0120 if (!(common->features & CCU_FEATURE_SIGMA_DELTA_MOD))
0121 return 0;
0122
0123 pr_debug("%s: clock is sigma-delta modulated\n",
0124 clk_hw_get_name(&common->hw));
0125
0126 reg = readl(common->base + sdm->tuning_reg);
0127
0128 pr_debug("%s: pattern reg is 0x%x",
0129 clk_hw_get_name(&common->hw), reg);
0130
0131 for (i = 0; i < sdm->table_size; i++)
0132 if (sdm->table[i].pattern == reg &&
0133 sdm->table[i].m == m && sdm->table[i].n == n)
0134 return sdm->table[i].rate;
0135
0136
0137 return 0;
0138 }
0139 EXPORT_SYMBOL_NS_GPL(ccu_sdm_helper_read_rate, SUNXI_CCU);
0140
0141 int ccu_sdm_helper_get_factors(struct ccu_common *common,
0142 struct ccu_sdm_internal *sdm,
0143 unsigned long rate,
0144 unsigned long *m, unsigned long *n)
0145 {
0146 unsigned int i;
0147
0148 if (!(common->features & CCU_FEATURE_SIGMA_DELTA_MOD))
0149 return -EINVAL;
0150
0151 for (i = 0; i < sdm->table_size; i++)
0152 if (sdm->table[i].rate == rate) {
0153 *m = sdm->table[i].m;
0154 *n = sdm->table[i].n;
0155 return 0;
0156 }
0157
0158
0159 return -EINVAL;
0160 }
0161 EXPORT_SYMBOL_NS_GPL(ccu_sdm_helper_get_factors, SUNXI_CCU);