0001
0002
0003
0004
0005
0006 #include <linux/clkdev.h>
0007 #include <linux/clk-provider.h>
0008 #include <linux/io.h>
0009 #include <linux/err.h>
0010
0011 #include <loongson1.h>
0012 #include "clk.h"
0013
0014 #define OSC (33 * 1000000)
0015 #define DIV_APB 2
0016
0017 static DEFINE_SPINLOCK(_lock);
0018
0019 static unsigned long ls1x_pll_recalc_rate(struct clk_hw *hw,
0020 unsigned long parent_rate)
0021 {
0022 u32 pll, rate;
0023
0024 pll = __raw_readl(LS1X_CLK_PLL_FREQ);
0025 rate = 12 + (pll & GENMASK(5, 0));
0026 rate *= OSC;
0027 rate >>= 1;
0028
0029 return rate;
0030 }
0031
0032 static const struct clk_ops ls1x_pll_clk_ops = {
0033 .recalc_rate = ls1x_pll_recalc_rate,
0034 };
0035
0036 static const char *const cpu_parents[] = { "cpu_clk_div", "osc_clk", };
0037 static const char *const ahb_parents[] = { "ahb_clk_div", "osc_clk", };
0038 static const char *const dc_parents[] = { "dc_clk_div", "osc_clk", };
0039
0040 void __init ls1x_clk_init(void)
0041 {
0042 struct clk_hw *hw;
0043
0044 hw = clk_hw_register_fixed_rate(NULL, "osc_clk", NULL, 0, OSC);
0045 clk_hw_register_clkdev(hw, "osc_clk", NULL);
0046
0047
0048 hw = clk_hw_register_pll(NULL, "pll_clk", "osc_clk",
0049 &ls1x_pll_clk_ops, 0);
0050 clk_hw_register_clkdev(hw, "pll_clk", NULL);
0051
0052
0053
0054
0055
0056
0057
0058
0059 hw = clk_hw_register_divider(NULL, "cpu_clk_div", "pll_clk",
0060 CLK_GET_RATE_NOCACHE, LS1X_CLK_PLL_DIV,
0061 DIV_CPU_SHIFT, DIV_CPU_WIDTH,
0062 CLK_DIVIDER_ONE_BASED |
0063 CLK_DIVIDER_ROUND_CLOSEST, &_lock);
0064 clk_hw_register_clkdev(hw, "cpu_clk_div", NULL);
0065 hw = clk_hw_register_mux(NULL, "cpu_clk", cpu_parents,
0066 ARRAY_SIZE(cpu_parents),
0067 CLK_SET_RATE_NO_REPARENT, LS1X_CLK_PLL_DIV,
0068 BYPASS_CPU_SHIFT, BYPASS_CPU_WIDTH, 0, &_lock);
0069 clk_hw_register_clkdev(hw, "cpu_clk", NULL);
0070
0071
0072
0073
0074
0075
0076
0077 hw = clk_hw_register_divider(NULL, "dc_clk_div", "pll_clk",
0078 0, LS1X_CLK_PLL_DIV, DIV_DC_SHIFT,
0079 DIV_DC_WIDTH, CLK_DIVIDER_ONE_BASED, &_lock);
0080 clk_hw_register_clkdev(hw, "dc_clk_div", NULL);
0081 hw = clk_hw_register_mux(NULL, "dc_clk", dc_parents,
0082 ARRAY_SIZE(dc_parents),
0083 CLK_SET_RATE_NO_REPARENT, LS1X_CLK_PLL_DIV,
0084 BYPASS_DC_SHIFT, BYPASS_DC_WIDTH, 0, &_lock);
0085 clk_hw_register_clkdev(hw, "dc_clk", NULL);
0086
0087
0088
0089
0090
0091
0092
0093 hw = clk_hw_register_divider(NULL, "ahb_clk_div", "pll_clk",
0094 0, LS1X_CLK_PLL_DIV, DIV_DDR_SHIFT,
0095 DIV_DDR_WIDTH, CLK_DIVIDER_ONE_BASED,
0096 &_lock);
0097 clk_hw_register_clkdev(hw, "ahb_clk_div", NULL);
0098 hw = clk_hw_register_mux(NULL, "ahb_clk", ahb_parents,
0099 ARRAY_SIZE(ahb_parents),
0100 CLK_SET_RATE_NO_REPARENT, LS1X_CLK_PLL_DIV,
0101 BYPASS_DDR_SHIFT, BYPASS_DDR_WIDTH, 0, &_lock);
0102 clk_hw_register_clkdev(hw, "ahb_clk", NULL);
0103 clk_hw_register_clkdev(hw, "ls1x-dma", NULL);
0104 clk_hw_register_clkdev(hw, "stmmaceth", NULL);
0105
0106
0107
0108 hw = clk_hw_register_fixed_factor(NULL, "apb_clk", "ahb_clk", 0, 1,
0109 DIV_APB);
0110 clk_hw_register_clkdev(hw, "apb_clk", NULL);
0111 clk_hw_register_clkdev(hw, "ls1x-ac97", NULL);
0112 clk_hw_register_clkdev(hw, "ls1x-i2c", NULL);
0113 clk_hw_register_clkdev(hw, "ls1x-nand", NULL);
0114 clk_hw_register_clkdev(hw, "ls1x-pwmtimer", NULL);
0115 clk_hw_register_clkdev(hw, "ls1x-spi", NULL);
0116 clk_hw_register_clkdev(hw, "ls1x-wdt", NULL);
0117 clk_hw_register_clkdev(hw, "serial8250", NULL);
0118 }