diff options
author | Yang Ling <gnaygnil@gmail.com> | 2016-09-20 11:54:56 -0400 |
---|---|---|
committer | Stephen Boyd <sboyd@codeaurora.org> | 2016-09-23 17:49:21 -0400 |
commit | b4626a7f489238a59f08f0b216e883bac07260d7 (patch) | |
tree | 425e1acdb376f0499575d97f019e4b3f0961468c | |
parent | f0ffaf187addb5dcab76885fff9314b716fc8072 (diff) |
CLK: Add Loongson1C clock support
This patch adds clock support to Loongson1C SoC.
Signed-off-by: Yang Ling <gnaygnil@gmail.com>
Acked-by: Keguang Zhang <keguang.zhang@gmail.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
-rw-r--r-- | drivers/clk/loongson1/Makefile | 1 | ||||
-rw-r--r-- | drivers/clk/loongson1/clk-loongson1c.c | 97 |
2 files changed, 98 insertions, 0 deletions
diff --git a/drivers/clk/loongson1/Makefile b/drivers/clk/loongson1/Makefile index 5a162a1b9bf6..b7f6a16390e0 100644 --- a/drivers/clk/loongson1/Makefile +++ b/drivers/clk/loongson1/Makefile | |||
@@ -1,2 +1,3 @@ | |||
1 | obj-y += clk.o | 1 | obj-y += clk.o |
2 | obj-$(CONFIG_LOONGSON1_LS1B) += clk-loongson1b.o | 2 | obj-$(CONFIG_LOONGSON1_LS1B) += clk-loongson1b.o |
3 | obj-$(CONFIG_LOONGSON1_LS1C) += clk-loongson1c.o | ||
diff --git a/drivers/clk/loongson1/clk-loongson1c.c b/drivers/clk/loongson1/clk-loongson1c.c new file mode 100644 index 000000000000..3466f7320b40 --- /dev/null +++ b/drivers/clk/loongson1/clk-loongson1c.c | |||
@@ -0,0 +1,97 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2016 Yang Ling <gnaygnil@gmail.com> | ||
3 | * | ||
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. | ||
8 | */ | ||
9 | |||
10 | #include <linux/clkdev.h> | ||
11 | #include <linux/clk-provider.h> | ||
12 | |||
13 | #include <loongson1.h> | ||
14 | #include "clk.h" | ||
15 | |||
16 | #define OSC (24 * 1000000) | ||
17 | #define DIV_APB 1 | ||
18 | |||
19 | static DEFINE_SPINLOCK(_lock); | ||
20 | |||
21 | static unsigned long ls1x_pll_recalc_rate(struct clk_hw *hw, | ||
22 | unsigned long parent_rate) | ||
23 | { | ||
24 | u32 pll, rate; | ||
25 | |||
26 | pll = __raw_readl(LS1X_CLK_PLL_FREQ); | ||
27 | rate = ((pll >> 8) & 0xff) + ((pll >> 16) & 0xff); | ||
28 | rate *= OSC; | ||
29 | rate >>= 2; | ||
30 | |||
31 | return rate; | ||
32 | } | ||
33 | |||
34 | static const struct clk_ops ls1x_pll_clk_ops = { | ||
35 | .recalc_rate = ls1x_pll_recalc_rate, | ||
36 | }; | ||
37 | |||
38 | static const struct clk_div_table ahb_div_table[] = { | ||
39 | [0] = { .val = 0, .div = 2 }, | ||
40 | [1] = { .val = 1, .div = 4 }, | ||
41 | [2] = { .val = 2, .div = 3 }, | ||
42 | [3] = { .val = 3, .div = 3 }, | ||
43 | }; | ||
44 | |||
45 | void __init ls1x_clk_init(void) | ||
46 | { | ||
47 | struct clk_hw *hw; | ||
48 | |||
49 | hw = clk_hw_register_fixed_rate(NULL, "osc_clk", NULL, 0, OSC); | ||
50 | clk_hw_register_clkdev(hw, "osc_clk", NULL); | ||
51 | |||
52 | /* clock derived from 24 MHz OSC clk */ | ||
53 | hw = clk_hw_register_pll(NULL, "pll_clk", "osc_clk", | ||
54 | &ls1x_pll_clk_ops, 0); | ||
55 | clk_hw_register_clkdev(hw, "pll_clk", NULL); | ||
56 | |||
57 | hw = clk_hw_register_divider(NULL, "cpu_clk_div", "pll_clk", | ||
58 | CLK_GET_RATE_NOCACHE, LS1X_CLK_PLL_DIV, | ||
59 | DIV_CPU_SHIFT, DIV_CPU_WIDTH, | ||
60 | CLK_DIVIDER_ONE_BASED | | ||
61 | CLK_DIVIDER_ROUND_CLOSEST, &_lock); | ||
62 | clk_hw_register_clkdev(hw, "cpu_clk_div", NULL); | ||
63 | hw = clk_hw_register_fixed_factor(NULL, "cpu_clk", "cpu_clk_div", | ||
64 | 0, 1, 1); | ||
65 | clk_hw_register_clkdev(hw, "cpu_clk", NULL); | ||
66 | |||
67 | hw = clk_hw_register_divider(NULL, "dc_clk_div", "pll_clk", | ||
68 | 0, LS1X_CLK_PLL_DIV, DIV_DC_SHIFT, | ||
69 | DIV_DC_WIDTH, CLK_DIVIDER_ONE_BASED, &_lock); | ||
70 | clk_hw_register_clkdev(hw, "dc_clk_div", NULL); | ||
71 | hw = clk_hw_register_fixed_factor(NULL, "dc_clk", "dc_clk_div", | ||
72 | 0, 1, 1); | ||
73 | clk_hw_register_clkdev(hw, "dc_clk", NULL); | ||
74 | |||
75 | hw = clk_hw_register_divider_table(NULL, "ahb_clk_div", "cpu_clk_div", | ||
76 | 0, LS1X_CLK_PLL_FREQ, DIV_DDR_SHIFT, | ||
77 | DIV_DDR_WIDTH, CLK_DIVIDER_ALLOW_ZERO, | ||
78 | ahb_div_table, &_lock); | ||
79 | clk_hw_register_clkdev(hw, "ahb_clk_div", NULL); | ||
80 | hw = clk_hw_register_fixed_factor(NULL, "ahb_clk", "ahb_clk_div", | ||
81 | 0, 1, 1); | ||
82 | clk_hw_register_clkdev(hw, "ahb_clk", NULL); | ||
83 | clk_hw_register_clkdev(hw, "ls1x-dma", NULL); | ||
84 | clk_hw_register_clkdev(hw, "stmmaceth", NULL); | ||
85 | |||
86 | /* clock derived from AHB clk */ | ||
87 | hw = clk_hw_register_fixed_factor(NULL, "apb_clk", "ahb_clk", 0, 1, | ||
88 | DIV_APB); | ||
89 | clk_hw_register_clkdev(hw, "apb_clk", NULL); | ||
90 | clk_hw_register_clkdev(hw, "ls1x-ac97", NULL); | ||
91 | clk_hw_register_clkdev(hw, "ls1x-i2c", NULL); | ||
92 | clk_hw_register_clkdev(hw, "ls1x-nand", NULL); | ||
93 | clk_hw_register_clkdev(hw, "ls1x-pwmtimer", NULL); | ||
94 | clk_hw_register_clkdev(hw, "ls1x-spi", NULL); | ||
95 | clk_hw_register_clkdev(hw, "ls1x-wdt", NULL); | ||
96 | clk_hw_register_clkdev(hw, "serial8250", NULL); | ||
97 | } | ||