2 * Copyright (c) 2012-2016 Zhang, Keguang <keguang.zhang@gmail.com>
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
10 #include <linux/clkdev.h>
11 #include <linux/clk-provider.h>
13 #include <linux/err.h>
15 #include <loongson1.h>
18 #define OSC (33 * 1000000)
21 static DEFINE_SPINLOCK(_lock
);
23 static unsigned long ls1x_pll_recalc_rate(struct clk_hw
*hw
,
24 unsigned long parent_rate
)
28 pll
= __raw_readl(LS1X_CLK_PLL_FREQ
);
29 rate
= 12 + (pll
& GENMASK(5, 0));
36 static const struct clk_ops ls1x_pll_clk_ops
= {
37 .recalc_rate
= ls1x_pll_recalc_rate
,
40 static const char *const cpu_parents
[] = { "cpu_clk_div", "osc_clk", };
41 static const char *const ahb_parents
[] = { "ahb_clk_div", "osc_clk", };
42 static const char *const dc_parents
[] = { "dc_clk_div", "osc_clk", };
44 void __init
ls1x_clk_init(void)
48 hw
= clk_hw_register_fixed_rate(NULL
, "osc_clk", NULL
, 0, OSC
);
49 clk_hw_register_clkdev(hw
, "osc_clk", NULL
);
51 /* clock derived from 33 MHz OSC clk */
52 hw
= clk_hw_register_pll(NULL
, "pll_clk", "osc_clk",
53 &ls1x_pll_clk_ops
, 0);
54 clk_hw_register_clkdev(hw
, "pll_clk", NULL
);
56 /* clock derived from PLL clk */
58 * _______________________| |
59 * OSC ___/ | MUX |___ CPU CLK
60 * \___ PLL ___ CPU DIV ___| |
63 hw
= clk_hw_register_divider(NULL
, "cpu_clk_div", "pll_clk",
64 CLK_GET_RATE_NOCACHE
, LS1X_CLK_PLL_DIV
,
65 DIV_CPU_SHIFT
, DIV_CPU_WIDTH
,
66 CLK_DIVIDER_ONE_BASED
|
67 CLK_DIVIDER_ROUND_CLOSEST
, &_lock
);
68 clk_hw_register_clkdev(hw
, "cpu_clk_div", NULL
);
69 hw
= clk_hw_register_mux(NULL
, "cpu_clk", cpu_parents
,
70 ARRAY_SIZE(cpu_parents
),
71 CLK_SET_RATE_NO_REPARENT
, LS1X_CLK_PLL_DIV
,
72 BYPASS_CPU_SHIFT
, BYPASS_CPU_WIDTH
, 0, &_lock
);
73 clk_hw_register_clkdev(hw
, "cpu_clk", NULL
);
76 * _______________________| |
77 * OSC ___/ | MUX |___ DC CLK
78 * \___ PLL ___ DC DIV ___| |
81 hw
= clk_hw_register_divider(NULL
, "dc_clk_div", "pll_clk",
82 0, LS1X_CLK_PLL_DIV
, DIV_DC_SHIFT
,
83 DIV_DC_WIDTH
, CLK_DIVIDER_ONE_BASED
, &_lock
);
84 clk_hw_register_clkdev(hw
, "dc_clk_div", NULL
);
85 hw
= clk_hw_register_mux(NULL
, "dc_clk", dc_parents
,
86 ARRAY_SIZE(dc_parents
),
87 CLK_SET_RATE_NO_REPARENT
, LS1X_CLK_PLL_DIV
,
88 BYPASS_DC_SHIFT
, BYPASS_DC_WIDTH
, 0, &_lock
);
89 clk_hw_register_clkdev(hw
, "dc_clk", NULL
);
92 * _______________________| |
93 * OSC ___/ | MUX |___ DDR CLK
94 * \___ PLL ___ DDR DIV ___| |
97 hw
= clk_hw_register_divider(NULL
, "ahb_clk_div", "pll_clk",
98 0, LS1X_CLK_PLL_DIV
, DIV_DDR_SHIFT
,
99 DIV_DDR_WIDTH
, CLK_DIVIDER_ONE_BASED
,
101 clk_hw_register_clkdev(hw
, "ahb_clk_div", NULL
);
102 hw
= clk_hw_register_mux(NULL
, "ahb_clk", ahb_parents
,
103 ARRAY_SIZE(ahb_parents
),
104 CLK_SET_RATE_NO_REPARENT
, LS1X_CLK_PLL_DIV
,
105 BYPASS_DDR_SHIFT
, BYPASS_DDR_WIDTH
, 0, &_lock
);
106 clk_hw_register_clkdev(hw
, "ahb_clk", NULL
);
107 clk_hw_register_clkdev(hw
, "ls1x-dma", NULL
);
108 clk_hw_register_clkdev(hw
, "stmmaceth", NULL
);
110 /* clock derived from AHB clk */
111 /* APB clk is always half of the AHB clk */
112 hw
= clk_hw_register_fixed_factor(NULL
, "apb_clk", "ahb_clk", 0, 1,
114 clk_hw_register_clkdev(hw
, "apb_clk", NULL
);
115 clk_hw_register_clkdev(hw
, "ls1x-ac97", NULL
);
116 clk_hw_register_clkdev(hw
, "ls1x-i2c", NULL
);
117 clk_hw_register_clkdev(hw
, "ls1x-nand", NULL
);
118 clk_hw_register_clkdev(hw
, "ls1x-pwmtimer", NULL
);
119 clk_hw_register_clkdev(hw
, "ls1x-spi", NULL
);
120 clk_hw_register_clkdev(hw
, "ls1x-wdt", NULL
);
121 clk_hw_register_clkdev(hw
, "serial8250", NULL
);