summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/clk/mvebu/ap806-system-controller.c140
1 files changed, 77 insertions, 63 deletions
diff --git a/drivers/clk/mvebu/ap806-system-controller.c b/drivers/clk/mvebu/ap806-system-controller.c
index bc43adff02e0..c64e2cc4a3ba 100644
--- a/drivers/clk/mvebu/ap806-system-controller.c
+++ b/drivers/clk/mvebu/ap806-system-controller.c
@@ -30,100 +30,114 @@ static struct clk_onecell_data ap806_clk_data = {
.clk_num = AP806_CLK_NUM,
};
-static int ap806_syscon_common_probe(struct platform_device *pdev,
- struct device_node *syscon_node)
+static int ap806_get_sar_clocks(unsigned int freq_mode,
+ unsigned int *cpuclk_freq,
+ unsigned int *dclk_freq)
{
- unsigned int freq_mode, cpuclk_freq, dclk_freq;
- const char *name, *fixedclk_name;
- struct device *dev = &pdev->dev;
- struct device_node *np = dev->of_node;
- struct regmap *regmap;
- u32 reg;
- int ret;
-
- regmap = syscon_node_to_regmap(syscon_node);
- if (IS_ERR(regmap)) {
- dev_err(dev, "cannot get regmap\n");
- return PTR_ERR(regmap);
- }
-
- ret = regmap_read(regmap, AP806_SAR_REG, &reg);
- if (ret) {
- dev_err(dev, "cannot read from regmap\n");
- return ret;
- }
-
- freq_mode = reg & AP806_SAR_CLKFREQ_MODE_MASK;
switch (freq_mode) {
case 0x0:
+ *cpuclk_freq = 2000;
+ *dclk_freq = 600;
+ break;
case 0x1:
- cpuclk_freq = 2000;
+ *cpuclk_freq = 2000;
+ *dclk_freq = 525;
break;
case 0x6:
+ *cpuclk_freq = 1800;
+ *dclk_freq = 600;
+ break;
case 0x7:
- cpuclk_freq = 1800;
+ *cpuclk_freq = 1800;
+ *dclk_freq = 525;
break;
case 0x4:
+ *cpuclk_freq = 1600;
+ *dclk_freq = 400;
+ break;
case 0xB:
+ *cpuclk_freq = 1600;
+ *dclk_freq = 450;
+ break;
case 0xD:
- cpuclk_freq = 1600;
+ *cpuclk_freq = 1600;
+ *dclk_freq = 525;
break;
case 0x1a:
- cpuclk_freq = 1400;
+ *cpuclk_freq = 1400;
+ *dclk_freq = 400;
break;
case 0x14:
+ *cpuclk_freq = 1300;
+ *dclk_freq = 400;
+ break;
case 0x17:
- cpuclk_freq = 1300;
+ *cpuclk_freq = 1300;
+ *dclk_freq = 325;
break;
case 0x19:
- cpuclk_freq = 1200;
+ *cpuclk_freq = 1200;
+ *dclk_freq = 400;
break;
case 0x13:
+ *cpuclk_freq = 1000;
+ *dclk_freq = 325;
+ break;
case 0x1d:
- cpuclk_freq = 1000;
+ *cpuclk_freq = 1000;
+ *dclk_freq = 400;
break;
case 0x1c:
- cpuclk_freq = 800;
+ *cpuclk_freq = 800;
+ *dclk_freq = 400;
break;
case 0x1b:
- cpuclk_freq = 600;
+ *cpuclk_freq = 600;
+ *dclk_freq = 400;
break;
default:
- dev_err(dev, "invalid Sample at Reset value\n");
return -EINVAL;
}
- /* Get DCLK frequency (DCLK = DDR_CLK / 2) */
- switch (freq_mode) {
- case 0x0:
- case 0x6:
- /* DDR_CLK = 1200Mhz */
- dclk_freq = 600;
- break;
- case 0x1:
- case 0x7:
- case 0xD:
- /* DDR_CLK = 1050Mhz */
- dclk_freq = 525;
- break;
- case 0x13:
- case 0x17:
- /* DDR_CLK = 650Mhz */
- dclk_freq = 325;
- break;
- case 0x4:
- case 0x14:
- case 0x19:
- case 0x1A:
- case 0x1B:
- case 0x1C:
- case 0x1D:
- /* DDR_CLK = 800Mhz */
- dclk_freq = 400;
- break;
- default:
- dclk_freq = 0;
+ return 0;
+}
+
+static int ap806_syscon_common_probe(struct platform_device *pdev,
+ struct device_node *syscon_node)
+{
+ unsigned int freq_mode, cpuclk_freq, dclk_freq;
+ const char *name, *fixedclk_name;
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct regmap *regmap;
+ u32 reg;
+ int ret;
+
+ regmap = syscon_node_to_regmap(syscon_node);
+ if (IS_ERR(regmap)) {
+ dev_err(dev, "cannot get regmap\n");
+ return PTR_ERR(regmap);
+ }
+
+ ret = regmap_read(regmap, AP806_SAR_REG, &reg);
+ if (ret) {
+ dev_err(dev, "cannot read from regmap\n");
+ return ret;
+ }
+
+ freq_mode = reg & AP806_SAR_CLKFREQ_MODE_MASK;
+
+ if (of_device_is_compatible(pdev->dev.of_node,
+ "marvell,ap806-clock")) {
+ ret = ap806_get_sar_clocks(freq_mode, &cpuclk_freq, &dclk_freq);
+ } else {
+ dev_err(dev, "compatible not supported\n");
+ return -EINVAL;
+ }
+
+ if (ret) {
dev_err(dev, "invalid Sample at Reset value\n");
+ return ret;
}
/* Convert to hertz */