xref: /openbmc/linux/drivers/clk/mvebu/orion.c (revision 3eb66e91a25497065c5322b1268cbc3953642227)
1*c3828949SGregory CLEMENT // SPDX-License-Identifier: GPL-2.0
266ecbfeaSThomas Petazzoni /*
366ecbfeaSThomas Petazzoni  * Marvell Orion SoC clocks
466ecbfeaSThomas Petazzoni  *
566ecbfeaSThomas Petazzoni  * Copyright (C) 2014 Thomas Petazzoni
666ecbfeaSThomas Petazzoni  *
766ecbfeaSThomas Petazzoni  * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
866ecbfeaSThomas Petazzoni  *
966ecbfeaSThomas Petazzoni  */
1066ecbfeaSThomas Petazzoni 
1166ecbfeaSThomas Petazzoni #include <linux/kernel.h>
1266ecbfeaSThomas Petazzoni #include <linux/clk-provider.h>
1366ecbfeaSThomas Petazzoni #include <linux/io.h>
1466ecbfeaSThomas Petazzoni #include <linux/of.h>
1566ecbfeaSThomas Petazzoni #include "common.h"
1666ecbfeaSThomas Petazzoni 
1766ecbfeaSThomas Petazzoni static const struct coreclk_ratio orion_coreclk_ratios[] __initconst = {
1866ecbfeaSThomas Petazzoni 	{ .id = 0, .name = "ddrclk", }
1966ecbfeaSThomas Petazzoni };
2066ecbfeaSThomas Petazzoni 
2166ecbfeaSThomas Petazzoni /*
2257d0ee07SJamie Lentin  * Orion 5181
2357d0ee07SJamie Lentin  */
2457d0ee07SJamie Lentin 
2557d0ee07SJamie Lentin #define SAR_MV88F5181_TCLK_FREQ      8
2657d0ee07SJamie Lentin #define SAR_MV88F5181_TCLK_FREQ_MASK 0x3
2757d0ee07SJamie Lentin 
mv88f5181_get_tclk_freq(void __iomem * sar)2857d0ee07SJamie Lentin static u32 __init mv88f5181_get_tclk_freq(void __iomem *sar)
2957d0ee07SJamie Lentin {
3057d0ee07SJamie Lentin 	u32 opt = (readl(sar) >> SAR_MV88F5181_TCLK_FREQ) &
3157d0ee07SJamie Lentin 		SAR_MV88F5181_TCLK_FREQ_MASK;
3257d0ee07SJamie Lentin 	if (opt == 0)
3357d0ee07SJamie Lentin 		return 133333333;
3457d0ee07SJamie Lentin 	else if (opt == 1)
3557d0ee07SJamie Lentin 		return 150000000;
3657d0ee07SJamie Lentin 	else if (opt == 2)
3757d0ee07SJamie Lentin 		return 166666667;
3857d0ee07SJamie Lentin 	else
3957d0ee07SJamie Lentin 		return 0;
4057d0ee07SJamie Lentin }
4157d0ee07SJamie Lentin 
4257d0ee07SJamie Lentin #define SAR_MV88F5181_CPU_FREQ       4
4357d0ee07SJamie Lentin #define SAR_MV88F5181_CPU_FREQ_MASK  0xf
4457d0ee07SJamie Lentin 
mv88f5181_get_cpu_freq(void __iomem * sar)4557d0ee07SJamie Lentin static u32 __init mv88f5181_get_cpu_freq(void __iomem *sar)
4657d0ee07SJamie Lentin {
4757d0ee07SJamie Lentin 	u32 opt = (readl(sar) >> SAR_MV88F5181_CPU_FREQ) &
4857d0ee07SJamie Lentin 		SAR_MV88F5181_CPU_FREQ_MASK;
4957d0ee07SJamie Lentin 	if (opt == 0)
5057d0ee07SJamie Lentin 		return 333333333;
5157d0ee07SJamie Lentin 	else if (opt == 1 || opt == 2)
5257d0ee07SJamie Lentin 		return 400000000;
5357d0ee07SJamie Lentin 	else if (opt == 3)
5457d0ee07SJamie Lentin 		return 500000000;
5557d0ee07SJamie Lentin 	else
5657d0ee07SJamie Lentin 		return 0;
5757d0ee07SJamie Lentin }
5857d0ee07SJamie Lentin 
mv88f5181_get_clk_ratio(void __iomem * sar,int id,int * mult,int * div)5957d0ee07SJamie Lentin static void __init mv88f5181_get_clk_ratio(void __iomem *sar, int id,
6057d0ee07SJamie Lentin 					   int *mult, int *div)
6157d0ee07SJamie Lentin {
6257d0ee07SJamie Lentin 	u32 opt = (readl(sar) >> SAR_MV88F5181_CPU_FREQ) &
6357d0ee07SJamie Lentin 		SAR_MV88F5181_CPU_FREQ_MASK;
6457d0ee07SJamie Lentin 	if (opt == 0 || opt == 1) {
6557d0ee07SJamie Lentin 		*mult = 1;
6657d0ee07SJamie Lentin 		*div  = 2;
6757d0ee07SJamie Lentin 	} else if (opt == 2 || opt == 3) {
6857d0ee07SJamie Lentin 		*mult = 1;
6957d0ee07SJamie Lentin 		*div  = 3;
7057d0ee07SJamie Lentin 	} else {
7157d0ee07SJamie Lentin 		*mult = 0;
7257d0ee07SJamie Lentin 		*div  = 1;
7357d0ee07SJamie Lentin 	}
7457d0ee07SJamie Lentin }
7557d0ee07SJamie Lentin 
7657d0ee07SJamie Lentin static const struct coreclk_soc_desc mv88f5181_coreclks = {
7757d0ee07SJamie Lentin 	.get_tclk_freq = mv88f5181_get_tclk_freq,
7857d0ee07SJamie Lentin 	.get_cpu_freq = mv88f5181_get_cpu_freq,
7957d0ee07SJamie Lentin 	.get_clk_ratio = mv88f5181_get_clk_ratio,
8057d0ee07SJamie Lentin 	.ratios = orion_coreclk_ratios,
8157d0ee07SJamie Lentin 	.num_ratios = ARRAY_SIZE(orion_coreclk_ratios),
8257d0ee07SJamie Lentin };
8357d0ee07SJamie Lentin 
mv88f5181_clk_init(struct device_node * np)8457d0ee07SJamie Lentin static void __init mv88f5181_clk_init(struct device_node *np)
8557d0ee07SJamie Lentin {
8657d0ee07SJamie Lentin 	return mvebu_coreclk_setup(np, &mv88f5181_coreclks);
8757d0ee07SJamie Lentin }
8857d0ee07SJamie Lentin 
8957d0ee07SJamie Lentin CLK_OF_DECLARE(mv88f5181_clk, "marvell,mv88f5181-core-clock", mv88f5181_clk_init);
9057d0ee07SJamie Lentin 
9157d0ee07SJamie Lentin /*
9266ecbfeaSThomas Petazzoni  * Orion 5182
9366ecbfeaSThomas Petazzoni  */
9466ecbfeaSThomas Petazzoni 
9566ecbfeaSThomas Petazzoni #define SAR_MV88F5182_TCLK_FREQ      8
9666ecbfeaSThomas Petazzoni #define SAR_MV88F5182_TCLK_FREQ_MASK 0x3
9766ecbfeaSThomas Petazzoni 
mv88f5182_get_tclk_freq(void __iomem * sar)9866ecbfeaSThomas Petazzoni static u32 __init mv88f5182_get_tclk_freq(void __iomem *sar)
9966ecbfeaSThomas Petazzoni {
10066ecbfeaSThomas Petazzoni 	u32 opt = (readl(sar) >> SAR_MV88F5182_TCLK_FREQ) &
10166ecbfeaSThomas Petazzoni 		SAR_MV88F5182_TCLK_FREQ_MASK;
10266ecbfeaSThomas Petazzoni 	if (opt == 1)
10366ecbfeaSThomas Petazzoni 		return 150000000;
10466ecbfeaSThomas Petazzoni 	else if (opt == 2)
10566ecbfeaSThomas Petazzoni 		return 166666667;
10666ecbfeaSThomas Petazzoni 	else
10766ecbfeaSThomas Petazzoni 		return 0;
10866ecbfeaSThomas Petazzoni }
10966ecbfeaSThomas Petazzoni 
11066ecbfeaSThomas Petazzoni #define SAR_MV88F5182_CPU_FREQ       4
11166ecbfeaSThomas Petazzoni #define SAR_MV88F5182_CPU_FREQ_MASK  0xf
11266ecbfeaSThomas Petazzoni 
mv88f5182_get_cpu_freq(void __iomem * sar)11366ecbfeaSThomas Petazzoni static u32 __init mv88f5182_get_cpu_freq(void __iomem *sar)
11466ecbfeaSThomas Petazzoni {
11566ecbfeaSThomas Petazzoni 	u32 opt = (readl(sar) >> SAR_MV88F5182_CPU_FREQ) &
11666ecbfeaSThomas Petazzoni 		SAR_MV88F5182_CPU_FREQ_MASK;
11766ecbfeaSThomas Petazzoni 	if (opt == 0)
11866ecbfeaSThomas Petazzoni 		return 333333333;
11966ecbfeaSThomas Petazzoni 	else if (opt == 1 || opt == 2)
12066ecbfeaSThomas Petazzoni 		return 400000000;
12166ecbfeaSThomas Petazzoni 	else if (opt == 3)
12266ecbfeaSThomas Petazzoni 		return 500000000;
12366ecbfeaSThomas Petazzoni 	else
12466ecbfeaSThomas Petazzoni 		return 0;
12566ecbfeaSThomas Petazzoni }
12666ecbfeaSThomas Petazzoni 
mv88f5182_get_clk_ratio(void __iomem * sar,int id,int * mult,int * div)12766ecbfeaSThomas Petazzoni static void __init mv88f5182_get_clk_ratio(void __iomem *sar, int id,
12866ecbfeaSThomas Petazzoni 					   int *mult, int *div)
12966ecbfeaSThomas Petazzoni {
13066ecbfeaSThomas Petazzoni 	u32 opt = (readl(sar) >> SAR_MV88F5182_CPU_FREQ) &
13166ecbfeaSThomas Petazzoni 		SAR_MV88F5182_CPU_FREQ_MASK;
13266ecbfeaSThomas Petazzoni 	if (opt == 0 || opt == 1) {
13366ecbfeaSThomas Petazzoni 		*mult = 1;
13466ecbfeaSThomas Petazzoni 		*div  = 2;
13566ecbfeaSThomas Petazzoni 	} else if (opt == 2 || opt == 3) {
13666ecbfeaSThomas Petazzoni 		*mult = 1;
13766ecbfeaSThomas Petazzoni 		*div  = 3;
13866ecbfeaSThomas Petazzoni 	} else {
13966ecbfeaSThomas Petazzoni 		*mult = 0;
14066ecbfeaSThomas Petazzoni 		*div  = 1;
14166ecbfeaSThomas Petazzoni 	}
14266ecbfeaSThomas Petazzoni }
14366ecbfeaSThomas Petazzoni 
14466ecbfeaSThomas Petazzoni static const struct coreclk_soc_desc mv88f5182_coreclks = {
14566ecbfeaSThomas Petazzoni 	.get_tclk_freq = mv88f5182_get_tclk_freq,
14666ecbfeaSThomas Petazzoni 	.get_cpu_freq = mv88f5182_get_cpu_freq,
14766ecbfeaSThomas Petazzoni 	.get_clk_ratio = mv88f5182_get_clk_ratio,
14866ecbfeaSThomas Petazzoni 	.ratios = orion_coreclk_ratios,
14966ecbfeaSThomas Petazzoni 	.num_ratios = ARRAY_SIZE(orion_coreclk_ratios),
15066ecbfeaSThomas Petazzoni };
15166ecbfeaSThomas Petazzoni 
mv88f5182_clk_init(struct device_node * np)15266ecbfeaSThomas Petazzoni static void __init mv88f5182_clk_init(struct device_node *np)
15366ecbfeaSThomas Petazzoni {
15466ecbfeaSThomas Petazzoni 	return mvebu_coreclk_setup(np, &mv88f5182_coreclks);
15566ecbfeaSThomas Petazzoni }
15666ecbfeaSThomas Petazzoni 
15766ecbfeaSThomas Petazzoni CLK_OF_DECLARE(mv88f5182_clk, "marvell,mv88f5182-core-clock", mv88f5182_clk_init);
15866ecbfeaSThomas Petazzoni 
15966ecbfeaSThomas Petazzoni /*
16066ecbfeaSThomas Petazzoni  * Orion 5281
16166ecbfeaSThomas Petazzoni  */
16266ecbfeaSThomas Petazzoni 
mv88f5281_get_tclk_freq(void __iomem * sar)16366ecbfeaSThomas Petazzoni static u32 __init mv88f5281_get_tclk_freq(void __iomem *sar)
16466ecbfeaSThomas Petazzoni {
16566ecbfeaSThomas Petazzoni 	/* On 5281, tclk is always 166 Mhz */
16666ecbfeaSThomas Petazzoni 	return 166666667;
16766ecbfeaSThomas Petazzoni }
16866ecbfeaSThomas Petazzoni 
16966ecbfeaSThomas Petazzoni #define SAR_MV88F5281_CPU_FREQ       4
17066ecbfeaSThomas Petazzoni #define SAR_MV88F5281_CPU_FREQ_MASK  0xf
17166ecbfeaSThomas Petazzoni 
mv88f5281_get_cpu_freq(void __iomem * sar)17266ecbfeaSThomas Petazzoni static u32 __init mv88f5281_get_cpu_freq(void __iomem *sar)
17366ecbfeaSThomas Petazzoni {
17466ecbfeaSThomas Petazzoni 	u32 opt = (readl(sar) >> SAR_MV88F5281_CPU_FREQ) &
17566ecbfeaSThomas Petazzoni 		SAR_MV88F5281_CPU_FREQ_MASK;
17666ecbfeaSThomas Petazzoni 	if (opt == 1 || opt == 2)
17766ecbfeaSThomas Petazzoni 		return 400000000;
17866ecbfeaSThomas Petazzoni 	else if (opt == 3)
17966ecbfeaSThomas Petazzoni 		return 500000000;
18066ecbfeaSThomas Petazzoni 	else
18166ecbfeaSThomas Petazzoni 		return 0;
18266ecbfeaSThomas Petazzoni }
18366ecbfeaSThomas Petazzoni 
mv88f5281_get_clk_ratio(void __iomem * sar,int id,int * mult,int * div)18466ecbfeaSThomas Petazzoni static void __init mv88f5281_get_clk_ratio(void __iomem *sar, int id,
18566ecbfeaSThomas Petazzoni 					   int *mult, int *div)
18666ecbfeaSThomas Petazzoni {
18766ecbfeaSThomas Petazzoni 	u32 opt = (readl(sar) >> SAR_MV88F5281_CPU_FREQ) &
18866ecbfeaSThomas Petazzoni 		SAR_MV88F5281_CPU_FREQ_MASK;
18966ecbfeaSThomas Petazzoni 	if (opt == 1) {
19066ecbfeaSThomas Petazzoni 		*mult = 1;
19166ecbfeaSThomas Petazzoni 		*div = 2;
19266ecbfeaSThomas Petazzoni 	} else if (opt == 2 || opt == 3) {
19366ecbfeaSThomas Petazzoni 		*mult = 1;
19466ecbfeaSThomas Petazzoni 		*div = 3;
19566ecbfeaSThomas Petazzoni 	} else {
19666ecbfeaSThomas Petazzoni 		*mult = 0;
19766ecbfeaSThomas Petazzoni 		*div = 1;
19866ecbfeaSThomas Petazzoni 	}
19966ecbfeaSThomas Petazzoni }
20066ecbfeaSThomas Petazzoni 
20166ecbfeaSThomas Petazzoni static const struct coreclk_soc_desc mv88f5281_coreclks = {
20266ecbfeaSThomas Petazzoni 	.get_tclk_freq = mv88f5281_get_tclk_freq,
20366ecbfeaSThomas Petazzoni 	.get_cpu_freq = mv88f5281_get_cpu_freq,
20466ecbfeaSThomas Petazzoni 	.get_clk_ratio = mv88f5281_get_clk_ratio,
20566ecbfeaSThomas Petazzoni 	.ratios = orion_coreclk_ratios,
20666ecbfeaSThomas Petazzoni 	.num_ratios = ARRAY_SIZE(orion_coreclk_ratios),
20766ecbfeaSThomas Petazzoni };
20866ecbfeaSThomas Petazzoni 
mv88f5281_clk_init(struct device_node * np)20966ecbfeaSThomas Petazzoni static void __init mv88f5281_clk_init(struct device_node *np)
21066ecbfeaSThomas Petazzoni {
21166ecbfeaSThomas Petazzoni 	return mvebu_coreclk_setup(np, &mv88f5281_coreclks);
21266ecbfeaSThomas Petazzoni }
21366ecbfeaSThomas Petazzoni 
21466ecbfeaSThomas Petazzoni CLK_OF_DECLARE(mv88f5281_clk, "marvell,mv88f5281-core-clock", mv88f5281_clk_init);
21566ecbfeaSThomas Petazzoni 
21666ecbfeaSThomas Petazzoni /*
21766ecbfeaSThomas Petazzoni  * Orion 6183
21866ecbfeaSThomas Petazzoni  */
21966ecbfeaSThomas Petazzoni 
22066ecbfeaSThomas Petazzoni #define SAR_MV88F6183_TCLK_FREQ      9
22166ecbfeaSThomas Petazzoni #define SAR_MV88F6183_TCLK_FREQ_MASK 0x1
22266ecbfeaSThomas Petazzoni 
mv88f6183_get_tclk_freq(void __iomem * sar)22366ecbfeaSThomas Petazzoni static u32 __init mv88f6183_get_tclk_freq(void __iomem *sar)
22466ecbfeaSThomas Petazzoni {
22566ecbfeaSThomas Petazzoni 	u32 opt = (readl(sar) >> SAR_MV88F6183_TCLK_FREQ) &
22666ecbfeaSThomas Petazzoni 		SAR_MV88F6183_TCLK_FREQ_MASK;
22766ecbfeaSThomas Petazzoni 	if (opt == 0)
22866ecbfeaSThomas Petazzoni 		return 133333333;
22966ecbfeaSThomas Petazzoni 	else if (opt == 1)
23066ecbfeaSThomas Petazzoni 		return 166666667;
23166ecbfeaSThomas Petazzoni 	else
23266ecbfeaSThomas Petazzoni 		return 0;
23366ecbfeaSThomas Petazzoni }
23466ecbfeaSThomas Petazzoni 
23566ecbfeaSThomas Petazzoni #define SAR_MV88F6183_CPU_FREQ       1
23666ecbfeaSThomas Petazzoni #define SAR_MV88F6183_CPU_FREQ_MASK  0x3f
23766ecbfeaSThomas Petazzoni 
mv88f6183_get_cpu_freq(void __iomem * sar)23866ecbfeaSThomas Petazzoni static u32 __init mv88f6183_get_cpu_freq(void __iomem *sar)
23966ecbfeaSThomas Petazzoni {
24066ecbfeaSThomas Petazzoni 	u32 opt = (readl(sar) >> SAR_MV88F6183_CPU_FREQ) &
24166ecbfeaSThomas Petazzoni 		SAR_MV88F6183_CPU_FREQ_MASK;
24266ecbfeaSThomas Petazzoni 	if (opt == 9)
24366ecbfeaSThomas Petazzoni 		return 333333333;
24466ecbfeaSThomas Petazzoni 	else if (opt == 17)
24566ecbfeaSThomas Petazzoni 		return 400000000;
24666ecbfeaSThomas Petazzoni 	else
24766ecbfeaSThomas Petazzoni 		return 0;
24866ecbfeaSThomas Petazzoni }
24966ecbfeaSThomas Petazzoni 
mv88f6183_get_clk_ratio(void __iomem * sar,int id,int * mult,int * div)25066ecbfeaSThomas Petazzoni static void __init mv88f6183_get_clk_ratio(void __iomem *sar, int id,
25166ecbfeaSThomas Petazzoni 					   int *mult, int *div)
25266ecbfeaSThomas Petazzoni {
25366ecbfeaSThomas Petazzoni 	u32 opt = (readl(sar) >> SAR_MV88F6183_CPU_FREQ) &
25466ecbfeaSThomas Petazzoni 		SAR_MV88F6183_CPU_FREQ_MASK;
25566ecbfeaSThomas Petazzoni 	if (opt == 9 || opt == 17) {
25666ecbfeaSThomas Petazzoni 		*mult = 1;
25766ecbfeaSThomas Petazzoni 		*div  = 2;
25866ecbfeaSThomas Petazzoni 	} else {
25966ecbfeaSThomas Petazzoni 		*mult = 0;
26066ecbfeaSThomas Petazzoni 		*div  = 1;
26166ecbfeaSThomas Petazzoni 	}
26266ecbfeaSThomas Petazzoni }
26366ecbfeaSThomas Petazzoni 
26466ecbfeaSThomas Petazzoni static const struct coreclk_soc_desc mv88f6183_coreclks = {
26566ecbfeaSThomas Petazzoni 	.get_tclk_freq = mv88f6183_get_tclk_freq,
26666ecbfeaSThomas Petazzoni 	.get_cpu_freq = mv88f6183_get_cpu_freq,
26766ecbfeaSThomas Petazzoni 	.get_clk_ratio = mv88f6183_get_clk_ratio,
26866ecbfeaSThomas Petazzoni 	.ratios = orion_coreclk_ratios,
26966ecbfeaSThomas Petazzoni 	.num_ratios = ARRAY_SIZE(orion_coreclk_ratios),
27066ecbfeaSThomas Petazzoni };
27166ecbfeaSThomas Petazzoni 
27266ecbfeaSThomas Petazzoni 
mv88f6183_clk_init(struct device_node * np)27366ecbfeaSThomas Petazzoni static void __init mv88f6183_clk_init(struct device_node *np)
27466ecbfeaSThomas Petazzoni {
27566ecbfeaSThomas Petazzoni 	return mvebu_coreclk_setup(np, &mv88f6183_coreclks);
27666ecbfeaSThomas Petazzoni }
27766ecbfeaSThomas Petazzoni 
27866ecbfeaSThomas Petazzoni CLK_OF_DECLARE(mv88f6183_clk, "marvell,mv88f6183-core-clock", mv88f6183_clk_init);
279