Skip to contentSkip to conversation

clk: socfpga: add divider registers to the main pll outputs

PATCH New dinguyen at altera.com 3 participants 6 messages Apr 16, 2014 – Apr 17, 2014

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/2 clk: socfpga: add divider registers to the main pll outputs

From: Dinh Nguyen <[email protected]>

The C0(mpu_clk), C1(main_clk), and C2(dbg_base_clk) outputs from the main PLL go through a pre-divider before coming into the system. These registers were hidden for the CycloneV platform, but are not used for the ArriaV platform.

This patch updates the clock driver to read the div-reg property for the socfpga-periph-clk clocks. Also moves the div_mask define to clk.h for re-use.

---
 drivers/clk/socfpga/clk-gate.c   |    1 -
 drivers/clk/socfpga/clk-periph.c |   22 +++++++++++++++++++---
 drivers/clk/socfpga/clk.h        |    4 ++++
 3 files changed, 23 insertions(+), 4 deletions(-)
drivers/clk/socfpga/clk-gate.c +0 -1
index 501d513..dd3a78c 100644
@@ -32,7 +32,6 @@
 #define SOCFPGA_MMC_CLK			"sdmmc_clk"
 #define SOCFPGA_GPIO_DB_CLK_OFFSET	0xA8
 
-#define div_mask(width)	((1 << (width)) - 1)
 #define streq(a, b) (strcmp((a), (b)) == 0)
 
 #define to_socfpga_gate_clk(p) container_of(p, struct socfpga_gate_clk, hw.hw)
drivers/clk/socfpga/clk-periph.c +19 -3
index 81623a3..46531c3 100644
@@ -29,12 +29,18 @@ static unsigned long clk_periclk_recalc_rate(struct clk_hw *hwclk,
 					     unsigned long parent_rate)
 {
 	struct socfpga_periph_clk *socfpgaclk = to_socfpga_periph_clk(hwclk);
-	u32 div;
+	u32 div, val;
 
-	if (socfpgaclk->fixed_div)
+	if (socfpgaclk->fixed_div) {
 		div = socfpgaclk->fixed_div;
-	else
+	} else {
+		if (socfpgaclk->div_reg) {
+			val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
+			val &= div_mask(socfpgaclk->width);
+			parent_rate /= (val + 1);
+		}
 		div = ((readl(socfpgaclk->hw.reg) & 0x1ff) + 1);
+	}
 
 	return parent_rate / div;
 }
@@ -54,6 +60,7 @@ static __init void __socfpga_periph_init(struct device_node *node,
 	struct clk_init_data init;
 	int rc;
 	u32 fixed_div;
+	u32 div_reg[3];
 
 	of_property_read_u32(node, "reg", &reg);
 
@@ -63,6 +70,15 @@ static __init void __socfpga_periph_init(struct device_node *node,
 
 	periph_clk->hw.reg = clk_mgr_base_addr + reg;
 
+	rc = of_property_read_u32_array(node, "div-reg", div_reg, 3);
+	if (!rc) {
+		periph_clk->div_reg = clk_mgr_base_addr + div_reg[0];
+		periph_clk->shift = div_reg[1];
+		periph_clk->width = div_reg[2];
+	} else {
+		periph_clk->div_reg = 0;
+	}
+
 	rc = of_property_read_u32(node, "fixed-divider", &fixed_div);
 	if (rc)
 		periph_clk->fixed_div = 0;
drivers/clk/socfpga/clk.h +4 -0
index d2e5401..d291f60 100644
@@ -27,6 +27,7 @@
 #define CLKMGR_PERPLL_SRC	0xAC
 
 #define SOCFPGA_MAX_PARENTS		3
+#define div_mask(width) ((1 << (width)) - 1)
 
 extern void __iomem *clk_mgr_base_addr;
 
@@ -52,6 +53,9 @@ struct socfpga_periph_clk {
 	struct clk_gate hw;
 	char *parent_name;
 	u32 fixed_div;
+	void __iomem *div_reg;
+	u32 width;      /* only valid if div_reg != 0 */
+	u32 shift;      /* only valid if div_reg != 0 */
 };
 
 #endif /* SOCFPGA_CLK_H */
Signature · 1 line
1.7.9.5
#1 lore raw

PATCH 2/2 ARM: socfpga: dts: Add div-reg to the main_pll clocks

From: Dinh Nguyen <[email protected]>

The mpu_clk, main_clk, and dbg_base_clk outputs from the main PLL go through a pre-divider. Update socfpga.dtsi to represent those dividers for these clocks.

Re-use the "div-reg" property that was used for the socfpga-gate-clock as this is the same thing. Also update the documentation.

---
 .../devicetree/bindings/clock/altr_socfpga.txt     |    4 ++--
 arch/arm/boot/dts/socfpga.dtsi                     |    6 +++---
 2 files changed, 5 insertions(+), 5 deletions(-)
Documentation/devicetree/bindings/clock/altr_socfpga.txt +2 -2
index 5dfd145..f72e80e 100644
@@ -21,8 +21,8 @@ Optional properties:
 - fixed-divider : If clocks have a fixed divider value, use this property.
 - clk-gate : For "socfpga-gate-clk", clk-gate contains the gating register
         and the bit index.
-- div-reg : For "socfpga-gate-clk", div-reg contains the divider register, bit shift,
-        and width.
+- div-reg : For "socfpga-gate-clk" and "socfpga-periph-clock", div-reg contains
+	the divider register, bit shift, and width.
 - clk-phase : For the sdmmc_clk, contains the value of the clock phase that controls
 	the SDMMC CIU clock. The first value is the clk_sample(smpsel), and the second
 	value is the cclk_in_drv(drvsel). The clk-phase is used to enable the correct
arch/arm/boot/dts/socfpga.dtsi +3 -3
index 56fc214..291eff1 100644
@@ -124,7 +124,7 @@
 							#clock-cells = <0>;
 							compatible = "altr,socfpga-perip-clk";
 							clocks = <&main_pll>;
-							fixed-divider = <2>;
+							div-reg = <0xe0 0 9>;
 							reg = <0x48>;
 						};
 
@@ -132,7 +132,7 @@
 							#clock-cells = <0>;
 							compatible = "altr,socfpga-perip-clk";
 							clocks = <&main_pll>;
-							fixed-divider = <4>;
+							div-reg = <0xe4 0 9>;
 							reg = <0x4C>;
 						};
 
@@ -140,7 +140,7 @@
 							#clock-cells = <0>;
 							compatible = "altr,socfpga-perip-clk";
 							clocks = <&main_pll>;
-							fixed-divider = <4>;
+							div-reg = <0xe8 0 9>;
 							reg = <0x50>;
 						};
 
Signature · 1 line
1.7.9.5
#2 lore raw

PATCH 1/2 clk: socfpga: add divider registers to the main pll outputs

In reply to dinguyen at altera.com
Quoted 5 lines · dinguyen at altera.com

From: Dinh Nguyen <[email protected]>

The C0(mpu_clk), C1(main_clk), and C2(dbg_base_clk) outputs from the main PLL go through a pre-divider before coming into the system. These registers were hidden for the CycloneV platform, but are not used for the ArriaV

Sorry but this should be "but are now used"

Quoted 97 lines

platform.

This patch updates the clock driver to read the div-reg property for the socfpga-periph-clk clocks. Also moves the div_mask define to clk.h for re-use.

---
  drivers/clk/socfpga/clk-gate.c   |    1 -
  drivers/clk/socfpga/clk-periph.c |   22 +++++++++++++++++++---
  drivers/clk/socfpga/clk.h        |    4 ++++
  3 files changed, 23 insertions(+), 4 deletions(-)
drivers/clk/socfpga/clk-gate.c +0 -1
index 501d513..dd3a78c 100644
@@ -32,7 +32,6 @@
  #define SOCFPGA_MMC_CLK			"sdmmc_clk"
  #define SOCFPGA_GPIO_DB_CLK_OFFSET	0xA8
 
-#define div_mask(width)	((1 << (width)) - 1)
  #define streq(a, b) (strcmp((a), (b)) == 0)
 
  #define to_socfpga_gate_clk(p) container_of(p, struct socfpga_gate_clk, hw.hw)
drivers/clk/socfpga/clk-periph.c +19 -3
index 81623a3..46531c3 100644
@@ -29,12 +29,18 @@ static unsigned long clk_periclk_recalc_rate(struct clk_hw *hwclk,
  					     unsigned long parent_rate)
  {
  	struct socfpga_periph_clk *socfpgaclk = to_socfpga_periph_clk(hwclk);
-	u32 div;
+	u32 div, val;
 
-	if (socfpgaclk->fixed_div)
+	if (socfpgaclk->fixed_div) {
  		div = socfpgaclk->fixed_div;
-	else
+	} else {
+		if (socfpgaclk->div_reg) {
+			val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
+			val &= div_mask(socfpgaclk->width);
+			parent_rate /= (val + 1);
+		}
  		div = ((readl(socfpgaclk->hw.reg) & 0x1ff) + 1);
+	}
 
  	return parent_rate / div;
  }
@@ -54,6 +60,7 @@ static __init void __socfpga_periph_init(struct device_node *node,
  	struct clk_init_data init;
  	int rc;
  	u32 fixed_div;
+	u32 div_reg[3];
 
  	of_property_read_u32(node, "reg", &reg);
 
@@ -63,6 +70,15 @@ static __init void __socfpga_periph_init(struct device_node *node,
 
  	periph_clk->hw.reg = clk_mgr_base_addr + reg;
 
+	rc = of_property_read_u32_array(node, "div-reg", div_reg, 3);
+	if (!rc) {
+		periph_clk->div_reg = clk_mgr_base_addr + div_reg[0];
+		periph_clk->shift = div_reg[1];
+		periph_clk->width = div_reg[2];
+	} else {
+		periph_clk->div_reg = 0;
+	}
+
  	rc = of_property_read_u32(node, "fixed-divider", &fixed_div);
  	if (rc)
  		periph_clk->fixed_div = 0;
drivers/clk/socfpga/clk.h +4 -0
index d2e5401..d291f60 100644
@@ -27,6 +27,7 @@
  #define CLKMGR_PERPLL_SRC	0xAC
 
  #define SOCFPGA_MAX_PARENTS		3
+#define div_mask(width) ((1 << (width)) - 1)
 
  extern void __iomem *clk_mgr_base_addr;
 
@@ -52,6 +53,9 @@ struct socfpga_periph_clk {
  	struct clk_gate hw;
  	char *parent_name;
  	u32 fixed_div;
+	void __iomem *div_reg;
+	u32 width;      /* only valid if div_reg != 0 */
+	u32 shift;      /* only valid if div_reg != 0 */
  };
 
  #endif /* SOCFPGA_CLK_H */
#3 lore raw

PATCH 1/2 clk: socfpga: add divider registers to the main pll outputs

Hi!

Quoted 11 lines · Dinh Nguyen
Quoted 5 lines · dinguyen at altera.com

From: Dinh Nguyen <[email protected]>

The C0(mpu_clk), C1(main_clk), and C2(dbg_base_clk) outputs from the main PLL go through a pre-divider before coming into the system. These registers were hidden for the CycloneV platform, but are not used for the ArriaV

Sorry but this should be "but are now used"

???

I don't get it. Do we have these registers on the cyclone V AND arria V or do we only have them on the arria V ?

IIRC I had made a patch that adds dividers to some place in the clocktree, but I can't remember if these are the same.

Regards,
Steffen

Quoted 6 lines
Quoted 6 lines

platform.

This patch updates the clock driver to read the div-reg property for the socfpga-periph-clk clocks. Also moves the div_mask define to clk.h for re-use.

Signature · 4 lines
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
#4 lore raw

PATCH 1/2 clk: socfpga: add divider registers to the main pll outputs

Quoted 12 lines · Steffen Trumtrar

Hi!

Quoted 9 lines · Dinh Nguyen
Quoted 5 lines · dinguyen at altera.com

From: Dinh Nguyen <[email protected]>

The C0(mpu_clk), C1(main_clk), and C2(dbg_base_clk) outputs from the main PLL go through a pre-divider before coming into the system. These registers were hidden for the CycloneV platform, but are not used for the ArriaV

Quoted 7 lines
Quoted 2 lines

Sorry but this should be "but are now used"

???

I don't get it. Do we have these registers on the cyclone V AND arria V or do we only have them on the arria V ?

These registers are there for both CycloneV and ArriaV.They are configured by the preloader, so it was "hidden" as a fixed-divider. I could have designated these values as fixed for the ArriaV as well, but it would be better if I just read this "hidden" register to get the divider value.

Dinh

Quoted 14 lines

IIRC I had made a patch that adds dividers to some place in the clocktree, but I can't remember if these are the same.

Regards,
Steffen

Quoted 6 lines
Quoted 6 lines

platform.

This patch updates the clock driver to read the div-reg property for the socfpga-periph-clk clocks. Also moves the div_mask define to clk.h for re-use.

#5 lore raw

PATCH 1/2 clk: socfpga: add divider registers to the main pll outputs

Quoted 18 lines · Dinh Nguyen
Quoted 17 lines · Steffen Trumtrar

Hi!

Quoted 11 lines · Dinh Nguyen
Quoted 5 lines · dinguyen at altera.com

From: Dinh Nguyen <[email protected]>

The C0(mpu_clk), C1(main_clk), and C2(dbg_base_clk) outputs from the main PLL go through a pre-divider before coming into the system. These registers were hidden for the CycloneV platform, but are not used for the ArriaV

Sorry but this should be "but are now used"

???

Quoted 9 lines
Quoted 2 lines

I don't get it. Do we have these registers on the cyclone V AND arria V or do we only have them on the arria V ?

These registers are there for both CycloneV and ArriaV.They are configured by the preloader, so it was "hidden" as a fixed-divider. I could have designated these values as fixed for the ArriaV as well, but it would be better if I just read this "hidden" register to get the divider value.

Ah, okay, now I get it. Then we want to have these represented in the clock tree of course. Especially when they are not fixed.

Regards,
Steffen

Signature · 4 lines
Pengutronix e.K.                           | Steffen Trumtrar            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |