0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #define pr_fmt(fmt) "bt1-ccu-pll: " fmt
0013
0014 #include <linux/kernel.h>
0015 #include <linux/printk.h>
0016 #include <linux/slab.h>
0017 #include <linux/clk-provider.h>
0018 #include <linux/mfd/syscon.h>
0019 #include <linux/of.h>
0020 #include <linux/of_address.h>
0021 #include <linux/ioport.h>
0022 #include <linux/regmap.h>
0023
0024 #include <dt-bindings/clock/bt1-ccu.h>
0025
0026 #include "ccu-pll.h"
0027
0028 #define CCU_CPU_PLL_BASE 0x000
0029 #define CCU_SATA_PLL_BASE 0x008
0030 #define CCU_DDR_PLL_BASE 0x010
0031 #define CCU_PCIE_PLL_BASE 0x018
0032 #define CCU_ETH_PLL_BASE 0x020
0033
0034 #define CCU_PLL_INFO(_id, _name, _pname, _base, _flags) \
0035 { \
0036 .id = _id, \
0037 .name = _name, \
0038 .parent_name = _pname, \
0039 .base = _base, \
0040 .flags = _flags \
0041 }
0042
0043 #define CCU_PLL_NUM ARRAY_SIZE(pll_info)
0044
0045 struct ccu_pll_info {
0046 unsigned int id;
0047 const char *name;
0048 const char *parent_name;
0049 unsigned int base;
0050 unsigned long flags;
0051 };
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062 static const struct ccu_pll_info pll_info[] = {
0063 CCU_PLL_INFO(CCU_CPU_PLL, "cpu_pll", "ref_clk", CCU_CPU_PLL_BASE,
0064 CLK_IS_CRITICAL),
0065 CCU_PLL_INFO(CCU_SATA_PLL, "sata_pll", "ref_clk", CCU_SATA_PLL_BASE,
0066 CLK_IS_CRITICAL | CLK_SET_RATE_GATE),
0067 CCU_PLL_INFO(CCU_DDR_PLL, "ddr_pll", "ref_clk", CCU_DDR_PLL_BASE,
0068 CLK_IS_CRITICAL | CLK_SET_RATE_GATE),
0069 CCU_PLL_INFO(CCU_PCIE_PLL, "pcie_pll", "ref_clk", CCU_PCIE_PLL_BASE,
0070 CLK_IS_CRITICAL),
0071 CCU_PLL_INFO(CCU_ETH_PLL, "eth_pll", "ref_clk", CCU_ETH_PLL_BASE,
0072 CLK_IS_CRITICAL | CLK_SET_RATE_GATE)
0073 };
0074
0075 struct ccu_pll_data {
0076 struct device_node *np;
0077 struct regmap *sys_regs;
0078 struct ccu_pll *plls[CCU_PLL_NUM];
0079 };
0080
0081 static struct ccu_pll *ccu_pll_find_desc(struct ccu_pll_data *data,
0082 unsigned int clk_id)
0083 {
0084 struct ccu_pll *pll;
0085 int idx;
0086
0087 for (idx = 0; idx < CCU_PLL_NUM; ++idx) {
0088 pll = data->plls[idx];
0089 if (pll && pll->id == clk_id)
0090 return pll;
0091 }
0092
0093 return ERR_PTR(-EINVAL);
0094 }
0095
0096 static struct ccu_pll_data *ccu_pll_create_data(struct device_node *np)
0097 {
0098 struct ccu_pll_data *data;
0099
0100 data = kzalloc(sizeof(*data), GFP_KERNEL);
0101 if (!data)
0102 return ERR_PTR(-ENOMEM);
0103
0104 data->np = np;
0105
0106 return data;
0107 }
0108
0109 static void ccu_pll_free_data(struct ccu_pll_data *data)
0110 {
0111 kfree(data);
0112 }
0113
0114 static int ccu_pll_find_sys_regs(struct ccu_pll_data *data)
0115 {
0116 data->sys_regs = syscon_node_to_regmap(data->np->parent);
0117 if (IS_ERR(data->sys_regs)) {
0118 pr_err("Failed to find syscon regs for '%s'\n",
0119 of_node_full_name(data->np));
0120 return PTR_ERR(data->sys_regs);
0121 }
0122
0123 return 0;
0124 }
0125
0126 static struct clk_hw *ccu_pll_of_clk_hw_get(struct of_phandle_args *clkspec,
0127 void *priv)
0128 {
0129 struct ccu_pll_data *data = priv;
0130 struct ccu_pll *pll;
0131 unsigned int clk_id;
0132
0133 clk_id = clkspec->args[0];
0134 pll = ccu_pll_find_desc(data, clk_id);
0135 if (IS_ERR(pll)) {
0136 pr_info("Invalid PLL clock ID %d specified\n", clk_id);
0137 return ERR_CAST(pll);
0138 }
0139
0140 return ccu_pll_get_clk_hw(pll);
0141 }
0142
0143 static int ccu_pll_clk_register(struct ccu_pll_data *data)
0144 {
0145 int idx, ret;
0146
0147 for (idx = 0; idx < CCU_PLL_NUM; ++idx) {
0148 const struct ccu_pll_info *info = &pll_info[idx];
0149 struct ccu_pll_init_data init = {0};
0150
0151 init.id = info->id;
0152 init.name = info->name;
0153 init.parent_name = info->parent_name;
0154 init.base = info->base;
0155 init.sys_regs = data->sys_regs;
0156 init.np = data->np;
0157 init.flags = info->flags;
0158
0159 data->plls[idx] = ccu_pll_hw_register(&init);
0160 if (IS_ERR(data->plls[idx])) {
0161 ret = PTR_ERR(data->plls[idx]);
0162 pr_err("Couldn't register PLL hw '%s'\n",
0163 init.name);
0164 goto err_hw_unregister;
0165 }
0166 }
0167
0168 ret = of_clk_add_hw_provider(data->np, ccu_pll_of_clk_hw_get, data);
0169 if (ret) {
0170 pr_err("Couldn't register PLL provider of '%s'\n",
0171 of_node_full_name(data->np));
0172 goto err_hw_unregister;
0173 }
0174
0175 return 0;
0176
0177 err_hw_unregister:
0178 for (--idx; idx >= 0; --idx)
0179 ccu_pll_hw_unregister(data->plls[idx]);
0180
0181 return ret;
0182 }
0183
0184 static __init void ccu_pll_init(struct device_node *np)
0185 {
0186 struct ccu_pll_data *data;
0187 int ret;
0188
0189 data = ccu_pll_create_data(np);
0190 if (IS_ERR(data))
0191 return;
0192
0193 ret = ccu_pll_find_sys_regs(data);
0194 if (ret)
0195 goto err_free_data;
0196
0197 ret = ccu_pll_clk_register(data);
0198 if (ret)
0199 goto err_free_data;
0200
0201 return;
0202
0203 err_free_data:
0204 ccu_pll_free_data(data);
0205 }
0206 CLK_OF_DECLARE(ccu_pll, "baikal,bt1-ccu-pll", ccu_pll_init);