2 * Copyright (c) 2012 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/slab.h>
14 #include <linux/err.h>
16 #include <loongson1.h>
20 static DEFINE_SPINLOCK(_lock
);
22 static int ls1x_pll_clk_enable(struct clk_hw
*hw
)
27 static void ls1x_pll_clk_disable(struct clk_hw
*hw
)
31 static unsigned long ls1x_pll_recalc_rate(struct clk_hw
*hw
,
32 unsigned long parent_rate
)
36 pll
= __raw_readl(LS1X_CLK_PLL_FREQ
);
37 rate
= ((12 + (pll
& 0x3f)) * 1000000) +
38 ((((pll
>> 8) & 0x3ff) * 1000000) >> 10);
45 static const struct clk_ops ls1x_pll_clk_ops
= {
46 .enable
= ls1x_pll_clk_enable
,
47 .disable
= ls1x_pll_clk_disable
,
48 .recalc_rate
= ls1x_pll_recalc_rate
,
51 static struct clk
* __init
clk_register_pll(struct device
*dev
,
52 const char *name
, const char *parent_name
, unsigned long flags
)
56 struct clk_init_data init
;
58 /* allocate the divider */
59 hw
= kzalloc(sizeof(struct clk_hw
), GFP_KERNEL
);
61 pr_err("%s: could not allocate clk_hw\n", __func__
);
62 return ERR_PTR(-ENOMEM
);
66 init
.ops
= &ls1x_pll_clk_ops
;
67 init
.flags
= flags
| CLK_IS_BASIC
;
68 init
.parent_names
= (parent_name
? &parent_name
: NULL
);
69 init
.num_parents
= (parent_name
? 1 : 0);
72 /* register the clock */
73 clk
= clk_register(dev
, hw
);
81 void __init
ls1x_clk_init(void)
85 clk
= clk_register_pll(NULL
, "pll_clk", NULL
, CLK_IS_ROOT
);
86 clk_prepare_enable(clk
);
88 clk
= clk_register_divider(NULL
, "cpu_clk", "pll_clk",
89 CLK_SET_RATE_PARENT
, LS1X_CLK_PLL_DIV
, DIV_CPU_SHIFT
,
90 DIV_CPU_WIDTH
, CLK_DIVIDER_ONE_BASED
, &_lock
);
91 clk_prepare_enable(clk
);
92 clk_register_clkdev(clk
, "cpu", NULL
);
94 clk
= clk_register_divider(NULL
, "dc_clk", "pll_clk",
95 CLK_SET_RATE_PARENT
, LS1X_CLK_PLL_DIV
, DIV_DC_SHIFT
,
96 DIV_DC_WIDTH
, CLK_DIVIDER_ONE_BASED
, &_lock
);
97 clk_prepare_enable(clk
);
98 clk_register_clkdev(clk
, "dc", NULL
);
100 clk
= clk_register_divider(NULL
, "ahb_clk", "pll_clk",
101 CLK_SET_RATE_PARENT
, LS1X_CLK_PLL_DIV
, DIV_DDR_SHIFT
,
102 DIV_DDR_WIDTH
, CLK_DIVIDER_ONE_BASED
, &_lock
);
103 clk_prepare_enable(clk
);
104 clk_register_clkdev(clk
, "ahb", NULL
);
105 clk_register_clkdev(clk
, "stmmaceth", NULL
);
107 clk
= clk_register_fixed_factor(NULL
, "apb_clk", "ahb_clk", 0, 1, 2);
108 clk_prepare_enable(clk
);
109 clk_register_clkdev(clk
, "apb", NULL
);
110 clk_register_clkdev(clk
, "serial8250", NULL
);