Skip to contentSkip to conversation

Tegra114: Add support for more clock sources for T114 periphs

PATCH Superseded Tom Warren 2 participants 4 messages Oct 15, 2013 – Jan 22, 2014

Subsystems (2)
lore
Share & tools
lore

Tom Warren

author
#0 lore raw

PATCH v2 1/1 Tegra114: Add support for more clock sources for T114 periphs

Some T114 peripherals can take up to 8 different clock sources (parents), including 4 new ones that don't exist on previous chips (PLLC2/C3/MEM2/SRC2). Expand clock/pll code/tables to support these additional bits/sources.

Changes were made to some common code. Testing on T30/T20 showed no changes in periph clock sources/divisors.

Also, peripheral clock sources that no longer exist on T114 were removed from the clock_periph_type table (CVE, TVDAC, etc.), and periphs that are gone or not needed in early init are no longer brought out of reset/enabled (FUSE, IRAMA/B/C/D, etc.).

---
v2:
- Removed some periph enables/resets that are not needed for early init
- Fixed an assert test for a divisor value (s/b >0, not >=0)
- Remove some unused code

 arch/arm/cpu/arm720t/tegra114/cpu.c               |   8 -
 arch/arm/cpu/tegra-common/clock.c                 |  21 +-
 arch/arm/cpu/tegra114-common/clock.c              | 422 +++++++++++++---------
 arch/arm/cpu/tegra30-common/clock.c               |   6 -
 arch/arm/include/asm/arch-tegra/clk_rst.h         |   3 +
 arch/arm/include/asm/arch-tegra/clock.h           |  17 +
 arch/arm/include/asm/arch-tegra114/clock-tables.h | 178 +++++----
 7 files changed, 390 insertions(+), 265 deletions(-)
arch/arm/cpu/arm720t/tegra114/cpu.c +0 -8
index 8f7bce4..c8e54b6 100644
@@ -152,18 +152,11 @@ void t114_init_clocks(void)
 	clock_set_enable(PERIPH_ID_CACHE2, 1);
 	clock_set_enable(PERIPH_ID_GPIO, 1);
 	clock_set_enable(PERIPH_ID_TMR, 1);
-	clock_set_enable(PERIPH_ID_RTC, 1);
 	clock_set_enable(PERIPH_ID_CPU, 1);
 	clock_set_enable(PERIPH_ID_EMC, 1);
 	clock_set_enable(PERIPH_ID_I2C5, 1);
-	clock_set_enable(PERIPH_ID_FUSE, 1);
-	clock_set_enable(PERIPH_ID_PMC, 1);
 	clock_set_enable(PERIPH_ID_APBDMA, 1);
 	clock_set_enable(PERIPH_ID_MEM, 1);
-	clock_set_enable(PERIPH_ID_IRAMA, 1);
-	clock_set_enable(PERIPH_ID_IRAMB, 1);
-	clock_set_enable(PERIPH_ID_IRAMC, 1);
-	clock_set_enable(PERIPH_ID_IRAMD, 1);
 	clock_set_enable(PERIPH_ID_CORESIGHT, 1);
 	clock_set_enable(PERIPH_ID_MSELECT, 1);
 	clock_set_enable(PERIPH_ID_EMC1, 1);
@@ -192,7 +185,6 @@ void t114_init_clocks(void)
 	reset_set_enable(PERIPH_ID_COP, 0);
 	reset_set_enable(PERIPH_ID_EMC, 0);
 	reset_set_enable(PERIPH_ID_I2C5, 0);
-	reset_set_enable(PERIPH_ID_FUSE, 0);
 	reset_set_enable(PERIPH_ID_APBDMA, 0);
 	reset_set_enable(PERIPH_ID_MEM, 0);
 	reset_set_enable(PERIPH_ID_CORESIGHT, 0);
arch/arm/cpu/tegra-common/clock.c +16 -5
index 268fb91..62a2191 100644
@@ -304,13 +304,24 @@ static int adjust_periph_pll(enum periph_id periph_id, int source,
 	/* work out the source clock and set it */
 	if (source < 0)
 		return -1;
-	if (mux_bits == 4) {
-		clrsetbits_le32(reg, OUT_CLK_SOURCE4_MASK,
-			source << OUT_CLK_SOURCE4_SHIFT);
-	} else {
+
+	switch (mux_bits) {
+	case MASK_BITS_31_30:
 		clrsetbits_le32(reg, OUT_CLK_SOURCE_MASK,
 			source << OUT_CLK_SOURCE_SHIFT);
+		break;
+
+	case MASK_BITS_31_29:
+		clrsetbits_le32(reg, OUT_CLK_SOURCE3_MASK,
+			source << OUT_CLK_SOURCE3_SHIFT);
+		break;
+
+	case MASK_BITS_29_28:
+		clrsetbits_le32(reg, OUT_CLK_SOURCE4_MASK,
+			source << OUT_CLK_SOURCE4_SHIFT);
+		break;
 	}
+
 	udelay(2);
 	return 0;
 }
@@ -332,7 +343,7 @@ unsigned clock_adjust_periph_pll_div(enum periph_id periph_id,
 	if (extra_div)
 		*extra_div = xdiv;
 
-	assert(divider >= 0);
+	assert(divider > 0);
 	if (adjust_periph_pll(periph_id, source, mux_bits, divider))
 		return -1U;
 	debug("periph %d, rate=%d, reg=%p = %x\n", periph_id, rate,
arch/arm/cpu/tegra114-common/clock.c +255 -167

582 lines not on this page · raw message

arch/arm/cpu/tegra30-common/clock.c +0 -6
index 74bd22b..89c3529 100644
@@ -60,12 +60,6 @@ enum {
 	CLOCK_MAX_MUX   = 8     /* number of source options for each clock */
 };
 
-enum {
-	MASK_BITS_31_30 = 2,    /* num of bits used to specify clock source */
-	MASK_BITS_31_29,
-	MASK_BITS_29_28,
-};
-
 /*
  * Clock source mux for each clock type. This just converts our enum into
  * a list of mux sources for use by the code.
arch/arm/include/asm/arch-tegra/clk_rst.h +3 -0
index a4c17e7..8200090 100644
@@ -243,6 +243,9 @@ enum {
 #define OUT_CLK_SOURCE_SHIFT	30
 #define OUT_CLK_SOURCE_MASK	(3U << OUT_CLK_SOURCE_SHIFT)
 
+#define OUT_CLK_SOURCE3_SHIFT	29
+#define OUT_CLK_SOURCE3_MASK	(7U << OUT_CLK_SOURCE3_SHIFT)
+
 #define OUT_CLK_SOURCE4_SHIFT	28
 #define OUT_CLK_SOURCE4_MASK	(15U << OUT_CLK_SOURCE4_SHIFT)
 
arch/arm/include/asm/arch-tegra/clock.h +17 -0
index c3174bd..9495179 100644
@@ -20,6 +20,12 @@ enum clock_osc_freq {
 	CLOCK_OSC_FREQ_COUNT,
 };
 
+enum {
+	MASK_BITS_31_30 = 2,	/* num of bits used to specify clock source */
+	MASK_BITS_31_29,
+	MASK_BITS_29_28,
+};
+
 #include <asm/arch/clock-tables.h>
 /* PLL stabilization delay in usec */
 #define CLOCK_PLL_STABLE_DELAY_US 300
@@ -305,4 +311,15 @@ int clock_set_rate(enum clock_id clkid, u32 n, u32 m, u32 p, u32 cpcon);
 /* SoC-specific TSC init */
 void arch_timer_init(void);
 
+/**
+ * Enable a peripheral clock with a certain clock source/divisor
+ *
+ * @param periph_id     peripheral to enable/change
+ * @param src           PLL id of required parent clock
+ * @param divisor       required integer divisor (not 7.1)
+ * @return 0 if ok
+ *        -1 on error (bad divisor, etc.).
+ */
+int clock_periph_enable(enum periph_id pid, int src, int divisor);
+
 #endif  /* _TEGRA_CLOCK_H_ */
arch/arm/include/asm/arch-tegra114/clock-tables.h +99 -79

314 lines not on this page · raw message

Signature · 1 line
1.8.1.5
#1 lore raw

PATCH v2 1/1 Tegra114: Add support for more clock sources for T114 periphs

Quoted 4 lines · Tom Warren

Some T114 peripherals can take up to 8 different clock sources (parents), including 4 new ones that don't exist on previous chips (PLLC2/C3/MEM2/SRC2). Expand clock/pll code/tables to support these additional bits/sources.

I would really like Peter De Schrijver to review this patch, since he wrote the upstream Tegra124 clock driver, which involved a lot of driver unification with previous SoCs. I'd like him to take a look at the mux mask widths in particular, w.r.t. making sure that U-Boot, the kernel, and the TRM all agree on which peripherals have which size mux field.

In particular, clk-tegra-periph.c in Peter's patches contains clocks with mux fields in bits 31:30 or bits 31:29; there is no clock with a mux field in bits 31:28. Yet, OUT_CLK_SOURCE4_* in U-Boot (before this patch) represent a mux field in bits 31:28. If this is wrong, I believe we need to fix it before applying this patch. If the TRM is wrong, we need to file a bug agaist it.

Quoted 7 lines

Changes were made to some common code. Testing on T30/T20 showed no changes in periph clock sources/divisors.

Also, peripheral clock sources that no longer exist on T114 were removed from the clock_periph_type table (CVE, TVDAC, etc.), and periphs that are gone or not needed in early init are no longer brought out of reset/enabled (FUSE, IRAMA/B/C/D, etc.).

As I mentioned in the response I just sent to V1, removing things seems like it should be in a separate patch, so each patch does just one logical thing.

arch/arm/cpu/tegra-common/clock.c static int adjust_periph_pll(enum periph_id periph_id, int source, · line 307

Quoted 9 lines
arch/arm/cpu/tegra-common/clock.c +0 -1
index 268fb91..62a2191 100644
@@ -304,13 +304,24 @@ static int adjust_periph_pll(enum periph_id periph_id, int source,
 	/* work out the source clock and set it */
 	if (source < 0)
 		return -1;
-	if (mux_bits == 4) {

mux_bits is a parameter to this function. I don't see this patch changing the way this function is called, so I have to assume that the same values are passed to the function before and after this patch. Based on the switch statement that's added below, I assume that the defines MASK_BITS_* are passed into this function as mux_bits.

In that case, the "4" in that if expression means MASK_BITS_29_28. However, OUT_CLK_SOURCE4_MASK/SHIFT means a mask in bits 31:28. Perhaps the "4" wasn't originally meant to indicate "number of bits in mux field", but rather "number of possible values representable in the mux field"?

While this may be a pre-existing issue, I believe it is imperative that we fix this before confusing the matter further by building more patches on top of it.

arch/arm/cpu/tegra-common/clock.c static int adjust_periph_pll(enum periph_id periph_id, int source, · line 311

Quoted 8 lines
arch/arm/cpu/tegra-common/clock.c +3 -3
-		clrsetbits_le32(reg, OUT_CLK_SOURCE4_MASK,
-			source << OUT_CLK_SOURCE4_SHIFT);
-	} else {
+
+	switch (mux_bits) {
+	case MASK_BITS_31_30:
 		clrsetbits_le32(reg, OUT_CLK_SOURCE_MASK,
 			source << OUT_CLK_SOURCE_SHIFT);

OUT_CLK_SOURCE_* do indeed represent a mask/shift for bits 31:30, so that's probably OK.

arch/arm/cpu/tegra-common/clock.c static int adjust_periph_pll(enum periph_id periph_id, int source, · line 316

Quoted 5 lines
arch/arm/cpu/tegra-common/clock.c +5 -0
+		break;
+
+	case MASK_BITS_31_29:
+		clrsetbits_le32(reg, OUT_CLK_SOURCE3_MASK,
+			source << OUT_CLK_SOURCE3_SHIFT);

OUT_CLK_SOURCE3_* do indeed represent a mask/shift for bits 31:30, so that's probably OK.

arch/arm/cpu/tegra-common/clock.c static int adjust_periph_pll(enum periph_id periph_id, int source, · line 321

Quoted 5 lines
arch/arm/cpu/tegra-common/clock.c +5 -0
+		break;
+
+	case MASK_BITS_29_28:
+		clrsetbits_le32(reg, OUT_CLK_SOURCE4_MASK,
+			source << OUT_CLK_SOURCE4_SHIFT);

OUT_CLK_SOURCE4_* do NOT represent a mask/shift for bits 29:28, but rather for bits 31:28. Again, I think the meaning, value, and name of MASK_BITS_29_28 and OUT_CLK_SOURCE4_* need to be fixed and made consistent prior to this patch.

I would also suggest making separate patches for the following so they're all much simpler:

* Removing clock definitions.

* Removing reset twiddling for some clocks.

* The assert fix.

* Updating adjust_periph_pll() to support different mux mask location/size.

* Adding new clocks that rely on the the new mux mask location/size. Or, perhaps just adding new clocks, period.

#2 lore raw

PATCH v2 1/1 Tegra114: Add support for more clock sources for T114 periphs

In reply to Tom Warren
Quoted 21 lines · Tom Warren

Some T114 peripherals can take up to 8 different clock sources (parents), including 4 new ones that don't exist on previous chips (PLLC2/C3/MEM2/SRC2). Expand clock/pll code/tables to support these additional bits/sources.

Changes were made to some common code. Testing on T30/T20 showed no changes in periph clock sources/divisors.

Also, peripheral clock sources that no longer exist on T114 were removed from the clock_periph_type table (CVE, TVDAC, etc.), and periphs that are gone or not needed in early init are no longer brought out of reset/enabled (FUSE, IRAMA/B/C/D, etc.).

---
v2:
- Fixed an assert test for a divisor value (s/b >0, not >=0)

arch/arm/cpu/tegra-common/clock.c unsigned clock_adjust_periph_pll_div(enum periph_id periph_id, · line 349

Quoted 8 lines
arch/arm/cpu/tegra-common/clock.c +1 -1
@@ -332,7 +343,7 @@ unsigned clock_adjust_periph_pll_div(enum periph_id periph_id,
 	if (extra_div)
 		*extra_div = xdiv;
 
-	assert(divider >= 0);
+	assert(divider > 0);
 	if (adjust_periph_pll(periph_id, source, mux_bits, divider))
 		return -1U;
 	debug("periph %d, rate=%d, reg=%p = %x\n", periph_id, rate,

(For context, I'm working on applying the review feedback to this patch myself, so save Tom some time)

I think that's the wrong assert to change.

When I pointed out this issue in V1 of the patch, the problem was inside function clock_periph_enable(). However, that function isn't actually used anywhere, and was dropped from V2 of the patch.

So, unless you tell me otherwise, I think I'll drop the change I quoted above from this patch, since it doesn't seem right.

author
#3 lore raw

PATCH v2 1/1 Tegra114: Add support for more clock sources for T114 periphs

Quoted 15 lines · Stephen Warren
Quoted 13 lines · Tom Warren

Some T114 peripherals can take up to 8 different clock sources (parents), including 4 new ones that don't exist on previous chips (PLLC2/C3/MEM2/SRC2). Expand clock/pll code/tables to support these additional bits/sources.

Changes were made to some common code. Testing on T30/T20 showed no changes in periph clock sources/divisors.

Also, peripheral clock sources that no longer exist on T114 were removed from the clock_periph_type table (CVE, TVDAC, etc.), and periphs that are gone or not needed in early init are no longer brought out of reset/enabled (FUSE, IRAMA/B/C/D, etc.).

Quoted 6 lines

Review

Quoted 6 lines

---
v2:
- Fixed an assert test for a divisor value (s/b >0, not >=0)

(quoted diff) +0 -0

b/arch/arm/cpu/tegra-common/clock.c

Quoted 2 lines

Review unsigned clock_adjust_periph_pll_div(enum periph_id

Quoted 2 lines
(quoted diff) +0 -0
@@ -332,7 +343,7 @@ unsigned clock_adjust_periph_pll_div(enum periph_id

periph_id,

Quoted 12 lines

arch/arm/cpu/tegra-common/clock.c unsigned clock_adjust_periph_pll_div(enum periph_id periph_id, · line 349

Quoted 8 lines
arch/arm/cpu/tegra-common/clock.c +1 -1
      if (extra_div)
              *extra_div = xdiv;
 
-     assert(divider >= 0);
+     assert(divider > 0);
      if (adjust_periph_pll(periph_id, source, mux_bits, divider))
              return -1U;
      debug("periph %d, rate=%d, reg=%p = %x\n", periph_id, rate,

(For context, I'm working on applying the review feedback to this patch myself, so save Tom some time)

Quoted 8 lines

I think that's the wrong assert to change.

When I pointed out this issue in V1 of the patch, the problem was inside function clock_periph_enable(). However, that function isn't actually used anywhere, and was dropped from V2 of the patch.

So, unless you tell me otherwise, I think I'll drop the change I quoted above from this patch, since it doesn't seem right.

Sounds good to me.