0001
0002 #include <linux/bits.h>
0003 #include <linux/clk.h>
0004 #include <linux/clk-provider.h>
0005 #include <linux/err.h>
0006 #include <linux/io.h>
0007 #include <linux/module.h>
0008 #include <linux/of.h>
0009 #include <linux/slab.h>
0010 #include <linux/spinlock.h>
0011 #include "clk.h"
0012
0013 #define CCM_CCDR 0x4
0014 #define CCDR_MMDC_CH0_MASK BIT(17)
0015 #define CCDR_MMDC_CH1_MASK BIT(16)
0016
0017 DEFINE_SPINLOCK(imx_ccm_lock);
0018 EXPORT_SYMBOL_GPL(imx_ccm_lock);
0019
0020 bool mcore_booted;
0021 EXPORT_SYMBOL_GPL(mcore_booted);
0022
0023 void imx_unregister_clocks(struct clk *clks[], unsigned int count)
0024 {
0025 unsigned int i;
0026
0027 for (i = 0; i < count; i++)
0028 clk_unregister(clks[i]);
0029 }
0030
0031 void imx_unregister_hw_clocks(struct clk_hw *hws[], unsigned int count)
0032 {
0033 unsigned int i;
0034
0035 for (i = 0; i < count; i++)
0036 clk_hw_unregister(hws[i]);
0037 }
0038 EXPORT_SYMBOL_GPL(imx_unregister_hw_clocks);
0039
0040 void imx_mmdc_mask_handshake(void __iomem *ccm_base,
0041 unsigned int chn)
0042 {
0043 unsigned int reg;
0044
0045 reg = readl_relaxed(ccm_base + CCM_CCDR);
0046 reg |= chn == 0 ? CCDR_MMDC_CH0_MASK : CCDR_MMDC_CH1_MASK;
0047 writel_relaxed(reg, ccm_base + CCM_CCDR);
0048 }
0049
0050 void imx_check_clocks(struct clk *clks[], unsigned int count)
0051 {
0052 unsigned i;
0053
0054 for (i = 0; i < count; i++)
0055 if (IS_ERR(clks[i]))
0056 pr_err("i.MX clk %u: register failed with %ld\n",
0057 i, PTR_ERR(clks[i]));
0058 }
0059
0060 void imx_check_clk_hws(struct clk_hw *clks[], unsigned int count)
0061 {
0062 unsigned int i;
0063
0064 for (i = 0; i < count; i++)
0065 if (IS_ERR(clks[i]))
0066 pr_err("i.MX clk %u: register failed with %ld\n",
0067 i, PTR_ERR(clks[i]));
0068 }
0069 EXPORT_SYMBOL_GPL(imx_check_clk_hws);
0070
0071 static struct clk *imx_obtain_fixed_clock_from_dt(const char *name)
0072 {
0073 struct of_phandle_args phandle;
0074 struct clk *clk = ERR_PTR(-ENODEV);
0075 char *path;
0076
0077 path = kasprintf(GFP_KERNEL, "/clocks/%s", name);
0078 if (!path)
0079 return ERR_PTR(-ENOMEM);
0080
0081 phandle.np = of_find_node_by_path(path);
0082 kfree(path);
0083
0084 if (phandle.np) {
0085 clk = of_clk_get_from_provider(&phandle);
0086 of_node_put(phandle.np);
0087 }
0088 return clk;
0089 }
0090
0091 struct clk *imx_obtain_fixed_clock(
0092 const char *name, unsigned long rate)
0093 {
0094 struct clk *clk;
0095
0096 clk = imx_obtain_fixed_clock_from_dt(name);
0097 if (IS_ERR(clk))
0098 clk = imx_clk_fixed(name, rate);
0099 return clk;
0100 }
0101
0102 struct clk_hw *imx_obtain_fixed_clock_hw(
0103 const char *name, unsigned long rate)
0104 {
0105 struct clk *clk;
0106
0107 clk = imx_obtain_fixed_clock_from_dt(name);
0108 if (IS_ERR(clk))
0109 clk = imx_clk_fixed(name, rate);
0110 return __clk_get_hw(clk);
0111 }
0112
0113 struct clk_hw * imx_obtain_fixed_clk_hw(struct device_node *np,
0114 const char *name)
0115 {
0116 struct clk *clk;
0117
0118 clk = of_clk_get_by_name(np, name);
0119 if (IS_ERR(clk))
0120 return ERR_PTR(-ENOENT);
0121
0122 return __clk_get_hw(clk);
0123 }
0124 EXPORT_SYMBOL_GPL(imx_obtain_fixed_clk_hw);
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144 #define CSCMR1_FIXUP 0x00600000
0145
0146 void imx_cscmr1_fixup(u32 *val)
0147 {
0148 *val ^= CSCMR1_FIXUP;
0149 return;
0150 }
0151
0152 #ifndef MODULE
0153
0154 static bool imx_keep_uart_clocks;
0155 static int imx_enabled_uart_clocks;
0156 static struct clk **imx_uart_clocks;
0157
0158 static int __init imx_keep_uart_clocks_param(char *str)
0159 {
0160 imx_keep_uart_clocks = 1;
0161
0162 return 0;
0163 }
0164 __setup_param("earlycon", imx_keep_uart_earlycon,
0165 imx_keep_uart_clocks_param, 0);
0166 __setup_param("earlyprintk", imx_keep_uart_earlyprintk,
0167 imx_keep_uart_clocks_param, 0);
0168
0169 void imx_register_uart_clocks(unsigned int clk_count)
0170 {
0171 imx_enabled_uart_clocks = 0;
0172
0173
0174 #ifdef CONFIG_OF
0175 if (imx_keep_uart_clocks) {
0176 int i;
0177
0178 imx_uart_clocks = kcalloc(clk_count, sizeof(struct clk *), GFP_KERNEL);
0179 if (!imx_uart_clocks)
0180 return;
0181
0182 if (!of_stdout)
0183 return;
0184
0185 for (i = 0; i < clk_count; i++) {
0186 imx_uart_clocks[imx_enabled_uart_clocks] = of_clk_get(of_stdout, i);
0187
0188
0189 if (IS_ERR(imx_uart_clocks[imx_enabled_uart_clocks]))
0190 return;
0191
0192
0193 if (imx_uart_clocks[imx_enabled_uart_clocks])
0194 clk_prepare_enable(imx_uart_clocks[imx_enabled_uart_clocks++]);
0195 }
0196 }
0197 #endif
0198 }
0199
0200 static int __init imx_clk_disable_uart(void)
0201 {
0202 if (imx_keep_uart_clocks && imx_enabled_uart_clocks) {
0203 int i;
0204
0205 for (i = 0; i < imx_enabled_uart_clocks; i++) {
0206 clk_disable_unprepare(imx_uart_clocks[i]);
0207 clk_put(imx_uart_clocks[i]);
0208 }
0209 kfree(imx_uart_clocks);
0210 }
0211
0212 return 0;
0213 }
0214 late_initcall_sync(imx_clk_disable_uart);
0215 #endif
0216
0217 MODULE_LICENSE("GPL v2");