aboutsummaryrefslogtreecommitdiff
path: root/src/soc/nvidia/tegra124/include/soc/clock.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/soc/nvidia/tegra124/include/soc/clock.h')
-rw-r--r--src/soc/nvidia/tegra124/include/soc/clock.h64
1 files changed, 60 insertions, 4 deletions
diff --git a/src/soc/nvidia/tegra124/include/soc/clock.h b/src/soc/nvidia/tegra124/include/soc/clock.h
index 056a38b2e0..675fbfb4f2 100644
--- a/src/soc/nvidia/tegra124/include/soc/clock.h
+++ b/src/soc/nvidia/tegra124/include/soc/clock.h
@@ -149,13 +149,69 @@ enum {
#define CLOCK_PLL_STABLE_DELAY_US 300
#define IO_STABILIZATION_DELAY (2)
-/* Calculate clock fractional divider value from ref and target frequencies */
+/* Calculate clock fractional divider value from ref and target frequencies.
+ * This is for a U7.1 format. This is not well written up in the book and
+ * there have been some questions about this macro, so here we go.
+ * U7.1 format is defined as (ddddddd+1) + (h*.5)
+ * The lowest order bit is actually a fractional bit.
+ * Hence, the divider can be thought of as 9 bits.
+ * So:
+ * divider = ((ref/freq) << 1 - 1) (upper 7 bits) |
+ * (ref/freq & 1) (low order half-bit)
+ * however we can't do fractional arithmetic ... these are integers!
+ * So we normalize by shifting the result left 1 bit, and extracting
+ * ddddddd and h directly to the returned u8.
+ * divider = 2*(ref/freq);
+ * We want to
+ * preserve 7 bits of divisor and one bit of fraction, in 8 bits, as well as
+ * subtract one from ddddddd. Since we computed ref*2, the dddddd is now nicely
+ * situated in the upper 7 bits, and the h is sitting there in the low order
+ * bit. To subtract 1 from ddddddd, just subtract 2 from the 8-bit number
+ * and voila, upper 7 bits are (ref/freq-1), and lowest bit is h. Since you
+ * will assign this to a u8, it gets nicely truncated for you.
+ */
#define CLK_DIVIDER(REF, FREQ) ((((REF) * 2) / FREQ) - 2)
-/* Calculate clock frequency value from reference and clock divider value */
+/* Calculate clock frequency value from reference and clock divider value
+ * The discussion in the book is pretty lacking.
+ * The idea is that we need to divide a ref clock by a divisor
+ * in U7.1 format, where 7 upper bits are the integer
+ * and lowest order bit is a fraction.
+ * from the book, U7.1 is (ddddddd+1) + (h*.5)
+ * To normalize to an actual number, we might do this:
+ * ((d>>7+1)&0x7f) + (d&1 >> 1)
+ * but as you might guess, the low order bit would be lost.
+ * Since we can't express the fractional bit, we need to multiply it all by 2.
+ * ((d + 2)&0xfe) + (d & 1)
+ * Since we're just adding +2, the lowest order bit is preserved. Hence
+ * (d+2) is the same as ((d + 2)&0xfe) + (d & 1)
+ *
+ * Since you multiply denominator * 2 (by NOT shifting it),
+ * you multiply numerator * 2 to cancel it out.
+ */
#define CLK_FREQUENCY(REF, REG) (((REF) * 2) / (REG + 2))
+/* Warning: Some devices just use different bits for the same sources for no
+ * apparent reason. *Always* double-check the TRM before trusting this macro. */
+#define clock_configure_source(device, src, freq) \
+ clrsetbits_le32(&clk_rst->clk_src_##device, \
+ CLK_SOURCE_MASK | CLK_DIVISOR_MASK, \
+ src << CLK_SOURCE_SHIFT | CLK_DIVIDER(TEGRA_##src##_KHZ, freq));
+
+enum clock_source { /* Careful: Not true for all sources, always check TRM! */
+ PLLP = 0,
+ PLLC2 = 1,
+ PLLC = 2,
+ PLLD = 2,
+ PLLC3 = 3,
+ PLLA = 3,
+ PLLM = 4,
+ PLLD2 = 5,
+ CLK_M = 6,
+};
+
/* soc-specific */
+#define TEGRA_CLK_M_KHZ clock_get_osc_khz()
#define TEGRA_PLLX_KHZ (1900000)
#define TEGRA_PLLP_KHZ (408000)
#define TEGRA_PLLC_KHZ (600000)
@@ -165,7 +221,7 @@ enum {
int clock_get_osc_khz(void);
void clock_early_uart(void);
void clock_cpu0_config_and_reset(void * entry);
-void clock_config(void);
+void clock_enable_clear_reset(u32 l, u32 h, u32 u, u32 v, u32 w);
void clock_init(void);
-void clock_ll_set_source_divisor(u32 *reg, u32 source, u32 divisor);
+void clock_init_arm_generic_timer(void);
#endif /* __SOC_NVIDIA_TEGRA124_CLOCK_H__ */