0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/clk-provider.h>
0010 #include <linux/slab.h>
0011 #include <linux/io.h>
0012 #include <linux/err.h>
0013 #include <linux/types.h>
0014
0015 #include "clk.h"
0016
0017 #define PRCC_PCKEN 0x000
0018 #define PRCC_PCKDIS 0x004
0019 #define PRCC_KCKEN 0x008
0020 #define PRCC_KCKDIS 0x00C
0021 #define PRCC_PCKSR 0x010
0022 #define PRCC_KCKSR 0x014
0023
0024 #define to_clk_prcc(_hw) container_of(_hw, struct clk_prcc, hw)
0025
0026 struct clk_prcc {
0027 struct clk_hw hw;
0028 void __iomem *base;
0029 u32 cg_sel;
0030 int is_enabled;
0031 };
0032
0033
0034
0035 static int clk_prcc_pclk_enable(struct clk_hw *hw)
0036 {
0037 struct clk_prcc *clk = to_clk_prcc(hw);
0038
0039 writel(clk->cg_sel, (clk->base + PRCC_PCKEN));
0040 while (!(readl(clk->base + PRCC_PCKSR) & clk->cg_sel))
0041 cpu_relax();
0042
0043 clk->is_enabled = 1;
0044 return 0;
0045 }
0046
0047 static void clk_prcc_pclk_disable(struct clk_hw *hw)
0048 {
0049 struct clk_prcc *clk = to_clk_prcc(hw);
0050
0051 writel(clk->cg_sel, (clk->base + PRCC_PCKDIS));
0052 clk->is_enabled = 0;
0053 }
0054
0055 static int clk_prcc_kclk_enable(struct clk_hw *hw)
0056 {
0057 struct clk_prcc *clk = to_clk_prcc(hw);
0058
0059 writel(clk->cg_sel, (clk->base + PRCC_KCKEN));
0060 while (!(readl(clk->base + PRCC_KCKSR) & clk->cg_sel))
0061 cpu_relax();
0062
0063 clk->is_enabled = 1;
0064 return 0;
0065 }
0066
0067 static void clk_prcc_kclk_disable(struct clk_hw *hw)
0068 {
0069 struct clk_prcc *clk = to_clk_prcc(hw);
0070
0071 writel(clk->cg_sel, (clk->base + PRCC_KCKDIS));
0072 clk->is_enabled = 0;
0073 }
0074
0075 static int clk_prcc_is_enabled(struct clk_hw *hw)
0076 {
0077 struct clk_prcc *clk = to_clk_prcc(hw);
0078 return clk->is_enabled;
0079 }
0080
0081 static const struct clk_ops clk_prcc_pclk_ops = {
0082 .enable = clk_prcc_pclk_enable,
0083 .disable = clk_prcc_pclk_disable,
0084 .is_enabled = clk_prcc_is_enabled,
0085 };
0086
0087 static const struct clk_ops clk_prcc_kclk_ops = {
0088 .enable = clk_prcc_kclk_enable,
0089 .disable = clk_prcc_kclk_disable,
0090 .is_enabled = clk_prcc_is_enabled,
0091 };
0092
0093 static struct clk *clk_reg_prcc(const char *name,
0094 const char *parent_name,
0095 resource_size_t phy_base,
0096 u32 cg_sel,
0097 unsigned long flags,
0098 const struct clk_ops *clk_prcc_ops)
0099 {
0100 struct clk_prcc *clk;
0101 struct clk_init_data clk_prcc_init;
0102 struct clk *clk_reg;
0103
0104 if (!name) {
0105 pr_err("clk_prcc: %s invalid arguments passed\n", __func__);
0106 return ERR_PTR(-EINVAL);
0107 }
0108
0109 clk = kzalloc(sizeof(*clk), GFP_KERNEL);
0110 if (!clk)
0111 return ERR_PTR(-ENOMEM);
0112
0113 clk->base = ioremap(phy_base, SZ_4K);
0114 if (!clk->base)
0115 goto free_clk;
0116
0117 clk->cg_sel = cg_sel;
0118 clk->is_enabled = 1;
0119
0120 clk_prcc_init.name = name;
0121 clk_prcc_init.ops = clk_prcc_ops;
0122 clk_prcc_init.flags = flags;
0123 clk_prcc_init.parent_names = (parent_name ? &parent_name : NULL);
0124 clk_prcc_init.num_parents = (parent_name ? 1 : 0);
0125 clk->hw.init = &clk_prcc_init;
0126
0127 clk_reg = clk_register(NULL, &clk->hw);
0128 if (IS_ERR_OR_NULL(clk_reg))
0129 goto unmap_clk;
0130
0131 return clk_reg;
0132
0133 unmap_clk:
0134 iounmap(clk->base);
0135 free_clk:
0136 kfree(clk);
0137 pr_err("clk_prcc: %s failed to register clk\n", __func__);
0138 return ERR_PTR(-ENOMEM);
0139 }
0140
0141 struct clk *clk_reg_prcc_pclk(const char *name,
0142 const char *parent_name,
0143 resource_size_t phy_base,
0144 u32 cg_sel,
0145 unsigned long flags)
0146 {
0147 return clk_reg_prcc(name, parent_name, phy_base, cg_sel, flags,
0148 &clk_prcc_pclk_ops);
0149 }
0150
0151 struct clk *clk_reg_prcc_kclk(const char *name,
0152 const char *parent_name,
0153 resource_size_t phy_base,
0154 u32 cg_sel,
0155 unsigned long flags)
0156 {
0157 return clk_reg_prcc(name, parent_name, phy_base, cg_sel, flags,
0158 &clk_prcc_kclk_ops);
0159 }