162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Marvell Orion SoC clocks
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2014 Thomas Petazzoni
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci */
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include <linux/kernel.h>
1262306a36Sopenharmony_ci#include <linux/clk-provider.h>
1362306a36Sopenharmony_ci#include <linux/io.h>
1462306a36Sopenharmony_ci#include <linux/of.h>
1562306a36Sopenharmony_ci#include "common.h"
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_cistatic const struct coreclk_ratio orion_coreclk_ratios[] __initconst = {
1862306a36Sopenharmony_ci	{ .id = 0, .name = "ddrclk", }
1962306a36Sopenharmony_ci};
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci/*
2262306a36Sopenharmony_ci * Orion 5181
2362306a36Sopenharmony_ci */
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#define SAR_MV88F5181_TCLK_FREQ      8
2662306a36Sopenharmony_ci#define SAR_MV88F5181_TCLK_FREQ_MASK 0x3
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_cistatic u32 __init mv88f5181_get_tclk_freq(void __iomem *sar)
2962306a36Sopenharmony_ci{
3062306a36Sopenharmony_ci	u32 opt = (readl(sar) >> SAR_MV88F5181_TCLK_FREQ) &
3162306a36Sopenharmony_ci		SAR_MV88F5181_TCLK_FREQ_MASK;
3262306a36Sopenharmony_ci	if (opt == 0)
3362306a36Sopenharmony_ci		return 133333333;
3462306a36Sopenharmony_ci	else if (opt == 1)
3562306a36Sopenharmony_ci		return 150000000;
3662306a36Sopenharmony_ci	else if (opt == 2)
3762306a36Sopenharmony_ci		return 166666667;
3862306a36Sopenharmony_ci	else
3962306a36Sopenharmony_ci		return 0;
4062306a36Sopenharmony_ci}
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci#define SAR_MV88F5181_CPU_FREQ       4
4362306a36Sopenharmony_ci#define SAR_MV88F5181_CPU_FREQ_MASK  0xf
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_cistatic u32 __init mv88f5181_get_cpu_freq(void __iomem *sar)
4662306a36Sopenharmony_ci{
4762306a36Sopenharmony_ci	u32 opt = (readl(sar) >> SAR_MV88F5181_CPU_FREQ) &
4862306a36Sopenharmony_ci		SAR_MV88F5181_CPU_FREQ_MASK;
4962306a36Sopenharmony_ci	if (opt == 0)
5062306a36Sopenharmony_ci		return 333333333;
5162306a36Sopenharmony_ci	else if (opt == 1 || opt == 2)
5262306a36Sopenharmony_ci		return 400000000;
5362306a36Sopenharmony_ci	else if (opt == 3)
5462306a36Sopenharmony_ci		return 500000000;
5562306a36Sopenharmony_ci	else
5662306a36Sopenharmony_ci		return 0;
5762306a36Sopenharmony_ci}
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_cistatic void __init mv88f5181_get_clk_ratio(void __iomem *sar, int id,
6062306a36Sopenharmony_ci					   int *mult, int *div)
6162306a36Sopenharmony_ci{
6262306a36Sopenharmony_ci	u32 opt = (readl(sar) >> SAR_MV88F5181_CPU_FREQ) &
6362306a36Sopenharmony_ci		SAR_MV88F5181_CPU_FREQ_MASK;
6462306a36Sopenharmony_ci	if (opt == 0 || opt == 1) {
6562306a36Sopenharmony_ci		*mult = 1;
6662306a36Sopenharmony_ci		*div  = 2;
6762306a36Sopenharmony_ci	} else if (opt == 2 || opt == 3) {
6862306a36Sopenharmony_ci		*mult = 1;
6962306a36Sopenharmony_ci		*div  = 3;
7062306a36Sopenharmony_ci	} else {
7162306a36Sopenharmony_ci		*mult = 0;
7262306a36Sopenharmony_ci		*div  = 1;
7362306a36Sopenharmony_ci	}
7462306a36Sopenharmony_ci}
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_cistatic const struct coreclk_soc_desc mv88f5181_coreclks = {
7762306a36Sopenharmony_ci	.get_tclk_freq = mv88f5181_get_tclk_freq,
7862306a36Sopenharmony_ci	.get_cpu_freq = mv88f5181_get_cpu_freq,
7962306a36Sopenharmony_ci	.get_clk_ratio = mv88f5181_get_clk_ratio,
8062306a36Sopenharmony_ci	.ratios = orion_coreclk_ratios,
8162306a36Sopenharmony_ci	.num_ratios = ARRAY_SIZE(orion_coreclk_ratios),
8262306a36Sopenharmony_ci};
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_cistatic void __init mv88f5181_clk_init(struct device_node *np)
8562306a36Sopenharmony_ci{
8662306a36Sopenharmony_ci	return mvebu_coreclk_setup(np, &mv88f5181_coreclks);
8762306a36Sopenharmony_ci}
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ciCLK_OF_DECLARE(mv88f5181_clk, "marvell,mv88f5181-core-clock", mv88f5181_clk_init);
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci/*
9262306a36Sopenharmony_ci * Orion 5182
9362306a36Sopenharmony_ci */
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci#define SAR_MV88F5182_TCLK_FREQ      8
9662306a36Sopenharmony_ci#define SAR_MV88F5182_TCLK_FREQ_MASK 0x3
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_cistatic u32 __init mv88f5182_get_tclk_freq(void __iomem *sar)
9962306a36Sopenharmony_ci{
10062306a36Sopenharmony_ci	u32 opt = (readl(sar) >> SAR_MV88F5182_TCLK_FREQ) &
10162306a36Sopenharmony_ci		SAR_MV88F5182_TCLK_FREQ_MASK;
10262306a36Sopenharmony_ci	if (opt == 1)
10362306a36Sopenharmony_ci		return 150000000;
10462306a36Sopenharmony_ci	else if (opt == 2)
10562306a36Sopenharmony_ci		return 166666667;
10662306a36Sopenharmony_ci	else
10762306a36Sopenharmony_ci		return 0;
10862306a36Sopenharmony_ci}
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci#define SAR_MV88F5182_CPU_FREQ       4
11162306a36Sopenharmony_ci#define SAR_MV88F5182_CPU_FREQ_MASK  0xf
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_cistatic u32 __init mv88f5182_get_cpu_freq(void __iomem *sar)
11462306a36Sopenharmony_ci{
11562306a36Sopenharmony_ci	u32 opt = (readl(sar) >> SAR_MV88F5182_CPU_FREQ) &
11662306a36Sopenharmony_ci		SAR_MV88F5182_CPU_FREQ_MASK;
11762306a36Sopenharmony_ci	if (opt == 0)
11862306a36Sopenharmony_ci		return 333333333;
11962306a36Sopenharmony_ci	else if (opt == 1 || opt == 2)
12062306a36Sopenharmony_ci		return 400000000;
12162306a36Sopenharmony_ci	else if (opt == 3)
12262306a36Sopenharmony_ci		return 500000000;
12362306a36Sopenharmony_ci	else
12462306a36Sopenharmony_ci		return 0;
12562306a36Sopenharmony_ci}
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_cistatic void __init mv88f5182_get_clk_ratio(void __iomem *sar, int id,
12862306a36Sopenharmony_ci					   int *mult, int *div)
12962306a36Sopenharmony_ci{
13062306a36Sopenharmony_ci	u32 opt = (readl(sar) >> SAR_MV88F5182_CPU_FREQ) &
13162306a36Sopenharmony_ci		SAR_MV88F5182_CPU_FREQ_MASK;
13262306a36Sopenharmony_ci	if (opt == 0 || opt == 1) {
13362306a36Sopenharmony_ci		*mult = 1;
13462306a36Sopenharmony_ci		*div  = 2;
13562306a36Sopenharmony_ci	} else if (opt == 2 || opt == 3) {
13662306a36Sopenharmony_ci		*mult = 1;
13762306a36Sopenharmony_ci		*div  = 3;
13862306a36Sopenharmony_ci	} else {
13962306a36Sopenharmony_ci		*mult = 0;
14062306a36Sopenharmony_ci		*div  = 1;
14162306a36Sopenharmony_ci	}
14262306a36Sopenharmony_ci}
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_cistatic const struct coreclk_soc_desc mv88f5182_coreclks = {
14562306a36Sopenharmony_ci	.get_tclk_freq = mv88f5182_get_tclk_freq,
14662306a36Sopenharmony_ci	.get_cpu_freq = mv88f5182_get_cpu_freq,
14762306a36Sopenharmony_ci	.get_clk_ratio = mv88f5182_get_clk_ratio,
14862306a36Sopenharmony_ci	.ratios = orion_coreclk_ratios,
14962306a36Sopenharmony_ci	.num_ratios = ARRAY_SIZE(orion_coreclk_ratios),
15062306a36Sopenharmony_ci};
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_cistatic void __init mv88f5182_clk_init(struct device_node *np)
15362306a36Sopenharmony_ci{
15462306a36Sopenharmony_ci	return mvebu_coreclk_setup(np, &mv88f5182_coreclks);
15562306a36Sopenharmony_ci}
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ciCLK_OF_DECLARE(mv88f5182_clk, "marvell,mv88f5182-core-clock", mv88f5182_clk_init);
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci/*
16062306a36Sopenharmony_ci * Orion 5281
16162306a36Sopenharmony_ci */
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_cistatic u32 __init mv88f5281_get_tclk_freq(void __iomem *sar)
16462306a36Sopenharmony_ci{
16562306a36Sopenharmony_ci	/* On 5281, tclk is always 166 Mhz */
16662306a36Sopenharmony_ci	return 166666667;
16762306a36Sopenharmony_ci}
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci#define SAR_MV88F5281_CPU_FREQ       4
17062306a36Sopenharmony_ci#define SAR_MV88F5281_CPU_FREQ_MASK  0xf
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_cistatic u32 __init mv88f5281_get_cpu_freq(void __iomem *sar)
17362306a36Sopenharmony_ci{
17462306a36Sopenharmony_ci	u32 opt = (readl(sar) >> SAR_MV88F5281_CPU_FREQ) &
17562306a36Sopenharmony_ci		SAR_MV88F5281_CPU_FREQ_MASK;
17662306a36Sopenharmony_ci	if (opt == 1 || opt == 2)
17762306a36Sopenharmony_ci		return 400000000;
17862306a36Sopenharmony_ci	else if (opt == 3)
17962306a36Sopenharmony_ci		return 500000000;
18062306a36Sopenharmony_ci	else
18162306a36Sopenharmony_ci		return 0;
18262306a36Sopenharmony_ci}
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_cistatic void __init mv88f5281_get_clk_ratio(void __iomem *sar, int id,
18562306a36Sopenharmony_ci					   int *mult, int *div)
18662306a36Sopenharmony_ci{
18762306a36Sopenharmony_ci	u32 opt = (readl(sar) >> SAR_MV88F5281_CPU_FREQ) &
18862306a36Sopenharmony_ci		SAR_MV88F5281_CPU_FREQ_MASK;
18962306a36Sopenharmony_ci	if (opt == 1) {
19062306a36Sopenharmony_ci		*mult = 1;
19162306a36Sopenharmony_ci		*div = 2;
19262306a36Sopenharmony_ci	} else if (opt == 2 || opt == 3) {
19362306a36Sopenharmony_ci		*mult = 1;
19462306a36Sopenharmony_ci		*div = 3;
19562306a36Sopenharmony_ci	} else {
19662306a36Sopenharmony_ci		*mult = 0;
19762306a36Sopenharmony_ci		*div = 1;
19862306a36Sopenharmony_ci	}
19962306a36Sopenharmony_ci}
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_cistatic const struct coreclk_soc_desc mv88f5281_coreclks = {
20262306a36Sopenharmony_ci	.get_tclk_freq = mv88f5281_get_tclk_freq,
20362306a36Sopenharmony_ci	.get_cpu_freq = mv88f5281_get_cpu_freq,
20462306a36Sopenharmony_ci	.get_clk_ratio = mv88f5281_get_clk_ratio,
20562306a36Sopenharmony_ci	.ratios = orion_coreclk_ratios,
20662306a36Sopenharmony_ci	.num_ratios = ARRAY_SIZE(orion_coreclk_ratios),
20762306a36Sopenharmony_ci};
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_cistatic void __init mv88f5281_clk_init(struct device_node *np)
21062306a36Sopenharmony_ci{
21162306a36Sopenharmony_ci	return mvebu_coreclk_setup(np, &mv88f5281_coreclks);
21262306a36Sopenharmony_ci}
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ciCLK_OF_DECLARE(mv88f5281_clk, "marvell,mv88f5281-core-clock", mv88f5281_clk_init);
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci/*
21762306a36Sopenharmony_ci * Orion 6183
21862306a36Sopenharmony_ci */
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci#define SAR_MV88F6183_TCLK_FREQ      9
22162306a36Sopenharmony_ci#define SAR_MV88F6183_TCLK_FREQ_MASK 0x1
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_cistatic u32 __init mv88f6183_get_tclk_freq(void __iomem *sar)
22462306a36Sopenharmony_ci{
22562306a36Sopenharmony_ci	u32 opt = (readl(sar) >> SAR_MV88F6183_TCLK_FREQ) &
22662306a36Sopenharmony_ci		SAR_MV88F6183_TCLK_FREQ_MASK;
22762306a36Sopenharmony_ci	if (opt == 0)
22862306a36Sopenharmony_ci		return 133333333;
22962306a36Sopenharmony_ci	else if (opt == 1)
23062306a36Sopenharmony_ci		return 166666667;
23162306a36Sopenharmony_ci	else
23262306a36Sopenharmony_ci		return 0;
23362306a36Sopenharmony_ci}
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci#define SAR_MV88F6183_CPU_FREQ       1
23662306a36Sopenharmony_ci#define SAR_MV88F6183_CPU_FREQ_MASK  0x3f
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_cistatic u32 __init mv88f6183_get_cpu_freq(void __iomem *sar)
23962306a36Sopenharmony_ci{
24062306a36Sopenharmony_ci	u32 opt = (readl(sar) >> SAR_MV88F6183_CPU_FREQ) &
24162306a36Sopenharmony_ci		SAR_MV88F6183_CPU_FREQ_MASK;
24262306a36Sopenharmony_ci	if (opt == 9)
24362306a36Sopenharmony_ci		return 333333333;
24462306a36Sopenharmony_ci	else if (opt == 17)
24562306a36Sopenharmony_ci		return 400000000;
24662306a36Sopenharmony_ci	else
24762306a36Sopenharmony_ci		return 0;
24862306a36Sopenharmony_ci}
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_cistatic void __init mv88f6183_get_clk_ratio(void __iomem *sar, int id,
25162306a36Sopenharmony_ci					   int *mult, int *div)
25262306a36Sopenharmony_ci{
25362306a36Sopenharmony_ci	u32 opt = (readl(sar) >> SAR_MV88F6183_CPU_FREQ) &
25462306a36Sopenharmony_ci		SAR_MV88F6183_CPU_FREQ_MASK;
25562306a36Sopenharmony_ci	if (opt == 9 || opt == 17) {
25662306a36Sopenharmony_ci		*mult = 1;
25762306a36Sopenharmony_ci		*div  = 2;
25862306a36Sopenharmony_ci	} else {
25962306a36Sopenharmony_ci		*mult = 0;
26062306a36Sopenharmony_ci		*div  = 1;
26162306a36Sopenharmony_ci	}
26262306a36Sopenharmony_ci}
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_cistatic const struct coreclk_soc_desc mv88f6183_coreclks = {
26562306a36Sopenharmony_ci	.get_tclk_freq = mv88f6183_get_tclk_freq,
26662306a36Sopenharmony_ci	.get_cpu_freq = mv88f6183_get_cpu_freq,
26762306a36Sopenharmony_ci	.get_clk_ratio = mv88f6183_get_clk_ratio,
26862306a36Sopenharmony_ci	.ratios = orion_coreclk_ratios,
26962306a36Sopenharmony_ci	.num_ratios = ARRAY_SIZE(orion_coreclk_ratios),
27062306a36Sopenharmony_ci};
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_cistatic void __init mv88f6183_clk_init(struct device_node *np)
27462306a36Sopenharmony_ci{
27562306a36Sopenharmony_ci	return mvebu_coreclk_setup(np, &mv88f6183_coreclks);
27662306a36Sopenharmony_ci}
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ciCLK_OF_DECLARE(mv88f6183_clk, "marvell,mv88f6183-core-clock", mv88f6183_clk_init);
279