0001
0002
0003
0004
0005
0006 #include <linux/clk/mxs.h>
0007 #include <linux/clk.h>
0008 #include <linux/clk-provider.h>
0009 #include <linux/err.h>
0010 #include <linux/init.h>
0011 #include <linux/io.h>
0012 #include <linux/of.h>
0013 #include <linux/of_address.h>
0014 #include "clk.h"
0015
0016 static void __iomem *clkctrl;
0017 static void __iomem *digctrl;
0018
0019 #define CLKCTRL clkctrl
0020 #define DIGCTRL digctrl
0021
0022 #define PLLCTRL0 (CLKCTRL + 0x0000)
0023 #define CPU (CLKCTRL + 0x0020)
0024 #define HBUS (CLKCTRL + 0x0030)
0025 #define XBUS (CLKCTRL + 0x0040)
0026 #define XTAL (CLKCTRL + 0x0050)
0027 #define PIX (CLKCTRL + 0x0060)
0028 #define SSP (CLKCTRL + 0x0070)
0029 #define GPMI (CLKCTRL + 0x0080)
0030 #define SPDIF (CLKCTRL + 0x0090)
0031 #define EMI (CLKCTRL + 0x00a0)
0032 #define SAIF (CLKCTRL + 0x00c0)
0033 #define TV (CLKCTRL + 0x00d0)
0034 #define ETM (CLKCTRL + 0x00e0)
0035 #define FRAC (CLKCTRL + 0x00f0)
0036 #define CLKSEQ (CLKCTRL + 0x0110)
0037
0038 #define BP_CPU_INTERRUPT_WAIT 12
0039 #define BP_CLKSEQ_BYPASS_SAIF 0
0040 #define BP_CLKSEQ_BYPASS_SSP 5
0041 #define BP_SAIF_DIV_FRAC_EN 16
0042 #define BP_FRAC_IOFRAC 24
0043
0044 static void __init clk_misc_init(void)
0045 {
0046 u32 val;
0047
0048
0049 writel_relaxed(1 << BP_CPU_INTERRUPT_WAIT, CPU + SET);
0050
0051
0052 writel_relaxed(1 << BP_CLKSEQ_BYPASS_SAIF, CLKSEQ + CLR);
0053
0054
0055 val = readl_relaxed(SAIF);
0056 val |= 1 << BP_SAIF_DIV_FRAC_EN;
0057 writel_relaxed(val, SAIF);
0058
0059
0060
0061
0062
0063 writel_relaxed(1 << BP_CLKSEQ_BYPASS_SSP, CLKSEQ + CLR);
0064
0065
0066
0067
0068
0069 writel_relaxed(0x3f << BP_FRAC_IOFRAC, FRAC + CLR);
0070 writel_relaxed(30 << BP_FRAC_IOFRAC, FRAC + SET);
0071 }
0072
0073 static const char *const sel_pll[] __initconst = { "pll", "ref_xtal", };
0074 static const char *const sel_cpu[] __initconst = { "ref_cpu", "ref_xtal", };
0075 static const char *const sel_pix[] __initconst = { "ref_pix", "ref_xtal", };
0076 static const char *const sel_io[] __initconst = { "ref_io", "ref_xtal", };
0077 static const char *const cpu_sels[] __initconst = { "cpu_pll", "cpu_xtal", };
0078 static const char *const emi_sels[] __initconst = { "emi_pll", "emi_xtal", };
0079
0080 enum imx23_clk {
0081 ref_xtal, pll, ref_cpu, ref_emi, ref_pix, ref_io, saif_sel,
0082 lcdif_sel, gpmi_sel, ssp_sel, emi_sel, cpu, etm_sel, cpu_pll,
0083 cpu_xtal, hbus, xbus, lcdif_div, ssp_div, gpmi_div, emi_pll,
0084 emi_xtal, etm_div, saif_div, clk32k_div, rtc, adc, spdif_div,
0085 clk32k, dri, pwm, filt, uart, ssp, gpmi, spdif, emi, saif,
0086 lcdif, etm, usb, usb_phy,
0087 clk_max
0088 };
0089
0090 static struct clk *clks[clk_max];
0091 static struct clk_onecell_data clk_data;
0092
0093 static enum imx23_clk clks_init_on[] __initdata = {
0094 cpu, hbus, xbus, emi, uart,
0095 };
0096
0097 static void __init mx23_clocks_init(struct device_node *np)
0098 {
0099 struct device_node *dcnp;
0100 u32 i;
0101
0102 dcnp = of_find_compatible_node(NULL, NULL, "fsl,imx23-digctl");
0103 digctrl = of_iomap(dcnp, 0);
0104 WARN_ON(!digctrl);
0105 of_node_put(dcnp);
0106
0107 clkctrl = of_iomap(np, 0);
0108 WARN_ON(!clkctrl);
0109
0110 clk_misc_init();
0111
0112 clks[ref_xtal] = mxs_clk_fixed("ref_xtal", 24000000);
0113 clks[pll] = mxs_clk_pll("pll", "ref_xtal", PLLCTRL0, 16, 480000000);
0114 clks[ref_cpu] = mxs_clk_ref("ref_cpu", "pll", FRAC, 0);
0115 clks[ref_emi] = mxs_clk_ref("ref_emi", "pll", FRAC, 1);
0116 clks[ref_pix] = mxs_clk_ref("ref_pix", "pll", FRAC, 2);
0117 clks[ref_io] = mxs_clk_ref("ref_io", "pll", FRAC, 3);
0118 clks[saif_sel] = mxs_clk_mux("saif_sel", CLKSEQ, 0, 1, sel_pll, ARRAY_SIZE(sel_pll));
0119 clks[lcdif_sel] = mxs_clk_mux("lcdif_sel", CLKSEQ, 1, 1, sel_pix, ARRAY_SIZE(sel_pix));
0120 clks[gpmi_sel] = mxs_clk_mux("gpmi_sel", CLKSEQ, 4, 1, sel_io, ARRAY_SIZE(sel_io));
0121 clks[ssp_sel] = mxs_clk_mux("ssp_sel", CLKSEQ, 5, 1, sel_io, ARRAY_SIZE(sel_io));
0122 clks[emi_sel] = mxs_clk_mux("emi_sel", CLKSEQ, 6, 1, emi_sels, ARRAY_SIZE(emi_sels));
0123 clks[cpu] = mxs_clk_mux("cpu", CLKSEQ, 7, 1, cpu_sels, ARRAY_SIZE(cpu_sels));
0124 clks[etm_sel] = mxs_clk_mux("etm_sel", CLKSEQ, 8, 1, sel_cpu, ARRAY_SIZE(sel_cpu));
0125 clks[cpu_pll] = mxs_clk_div("cpu_pll", "ref_cpu", CPU, 0, 6, 28);
0126 clks[cpu_xtal] = mxs_clk_div("cpu_xtal", "ref_xtal", CPU, 16, 10, 29);
0127 clks[hbus] = mxs_clk_div("hbus", "cpu", HBUS, 0, 5, 29);
0128 clks[xbus] = mxs_clk_div("xbus", "ref_xtal", XBUS, 0, 10, 31);
0129 clks[lcdif_div] = mxs_clk_div("lcdif_div", "lcdif_sel", PIX, 0, 12, 29);
0130 clks[ssp_div] = mxs_clk_div("ssp_div", "ssp_sel", SSP, 0, 9, 29);
0131 clks[gpmi_div] = mxs_clk_div("gpmi_div", "gpmi_sel", GPMI, 0, 10, 29);
0132 clks[emi_pll] = mxs_clk_div("emi_pll", "ref_emi", EMI, 0, 6, 28);
0133 clks[emi_xtal] = mxs_clk_div("emi_xtal", "ref_xtal", EMI, 8, 4, 29);
0134 clks[etm_div] = mxs_clk_div("etm_div", "etm_sel", ETM, 0, 6, 29);
0135 clks[saif_div] = mxs_clk_frac("saif_div", "saif_sel", SAIF, 0, 16, 29);
0136 clks[clk32k_div] = mxs_clk_fixed_factor("clk32k_div", "ref_xtal", 1, 750);
0137 clks[rtc] = mxs_clk_fixed_factor("rtc", "ref_xtal", 1, 768);
0138 clks[adc] = mxs_clk_fixed_factor("adc", "clk32k", 1, 16);
0139 clks[spdif_div] = mxs_clk_fixed_factor("spdif_div", "pll", 1, 4);
0140 clks[clk32k] = mxs_clk_gate("clk32k", "clk32k_div", XTAL, 26);
0141 clks[dri] = mxs_clk_gate("dri", "ref_xtal", XTAL, 28);
0142 clks[pwm] = mxs_clk_gate("pwm", "ref_xtal", XTAL, 29);
0143 clks[filt] = mxs_clk_gate("filt", "ref_xtal", XTAL, 30);
0144 clks[uart] = mxs_clk_gate("uart", "ref_xtal", XTAL, 31);
0145 clks[ssp] = mxs_clk_gate("ssp", "ssp_div", SSP, 31);
0146 clks[gpmi] = mxs_clk_gate("gpmi", "gpmi_div", GPMI, 31);
0147 clks[spdif] = mxs_clk_gate("spdif", "spdif_div", SPDIF, 31);
0148 clks[emi] = mxs_clk_gate("emi", "emi_sel", EMI, 31);
0149 clks[saif] = mxs_clk_gate("saif", "saif_div", SAIF, 31);
0150 clks[lcdif] = mxs_clk_gate("lcdif", "lcdif_div", PIX, 31);
0151 clks[etm] = mxs_clk_gate("etm", "etm_div", ETM, 31);
0152 clks[usb] = mxs_clk_gate("usb", "usb_phy", DIGCTRL, 2);
0153 clks[usb_phy] = clk_register_gate(NULL, "usb_phy", "pll", 0, PLLCTRL0, 18, 0, &mxs_lock);
0154
0155 for (i = 0; i < ARRAY_SIZE(clks); i++)
0156 if (IS_ERR(clks[i])) {
0157 pr_err("i.MX23 clk %d: register failed with %ld\n",
0158 i, PTR_ERR(clks[i]));
0159 return;
0160 }
0161
0162 clk_data.clks = clks;
0163 clk_data.clk_num = ARRAY_SIZE(clks);
0164 of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
0165
0166 for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
0167 clk_prepare_enable(clks[clks_init_on[i]]);
0168
0169 }
0170 CLK_OF_DECLARE(imx23_clkctrl, "fsl,imx23-clkctrl", mx23_clocks_init);