aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/brcm2708/patches-4.9/0157-clk-bcm2835-Add-leaf-clock-measurement-support-disab.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/brcm2708/patches-4.9/0157-clk-bcm2835-Add-leaf-clock-measurement-support-disab.patch')
-rw-r--r--target/linux/brcm2708/patches-4.9/0157-clk-bcm2835-Add-leaf-clock-measurement-support-disab.patch346
1 files changed, 346 insertions, 0 deletions
diff --git a/target/linux/brcm2708/patches-4.9/0157-clk-bcm2835-Add-leaf-clock-measurement-support-disab.patch b/target/linux/brcm2708/patches-4.9/0157-clk-bcm2835-Add-leaf-clock-measurement-support-disab.patch
new file mode 100644
index 0000000000..16c5ec5cbf
--- /dev/null
+++ b/target/linux/brcm2708/patches-4.9/0157-clk-bcm2835-Add-leaf-clock-measurement-support-disab.patch
@@ -0,0 +1,346 @@
+From 546bac0479e51024027f8c8820f912573643b101 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Wed, 18 Jan 2017 07:31:57 +1100
+Subject: [PATCH] clk: bcm2835: Add leaf clock measurement support, disabled by
+ default
+
+This proved incredibly useful during debugging of the DSI driver, to
+see if our clocks were running at rate we requested. Let's leave it
+here for the next person interacting with clocks on the platform (and
+so that hopefully we can just hook it up to debugfs some day).
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
+(cherry picked from commit 3f9195811d8d829556c4cd88d3f9e56a80d5ba60)
+---
+ drivers/clk/bcm/clk-bcm2835.c | 144 ++++++++++++++++++++++++++++++++++--------
+ 1 file changed, 119 insertions(+), 25 deletions(-)
+
+--- a/drivers/clk/bcm/clk-bcm2835.c
++++ b/drivers/clk/bcm/clk-bcm2835.c
+@@ -39,6 +39,7 @@
+ #include <linux/clk.h>
+ #include <linux/clk/bcm2835.h>
+ #include <linux/debugfs.h>
++#include <linux/delay.h>
+ #include <linux/module.h>
+ #include <linux/of.h>
+ #include <linux/platform_device.h>
+@@ -98,7 +99,8 @@
+ #define CM_SMIDIV 0x0b4
+ /* no definition for 0x0b8 and 0x0bc */
+ #define CM_TCNTCTL 0x0c0
+-#define CM_TCNTDIV 0x0c4
++# define CM_TCNT_SRC1_SHIFT 12
++#define CM_TCNTCNT 0x0c4
+ #define CM_TECCTL 0x0c8
+ #define CM_TECDIV 0x0cc
+ #define CM_TD0CTL 0x0d0
+@@ -338,6 +340,61 @@ static inline u32 cprman_read(struct bcm
+ return readl(cprman->regs + reg);
+ }
+
++/* Does a cycle of measuring a clock through the TCNT clock, which may
++ * source from many other clocks in the system.
++ */
++static unsigned long bcm2835_measure_tcnt_mux(struct bcm2835_cprman *cprman,
++ u32 tcnt_mux)
++{
++ u32 osccount = 19200; /* 1ms */
++ u32 count;
++ ktime_t timeout;
++
++ spin_lock(&cprman->regs_lock);
++
++ cprman_write(cprman, CM_TCNTCTL, CM_KILL);
++
++ cprman_write(cprman, CM_TCNTCTL,
++ (tcnt_mux & CM_SRC_MASK) |
++ (tcnt_mux >> CM_SRC_BITS) << CM_TCNT_SRC1_SHIFT);
++
++ cprman_write(cprman, CM_OSCCOUNT, osccount);
++
++ /* do a kind delay at the start */
++ mdelay(1);
++
++ /* Finish off whatever is left of OSCCOUNT */
++ timeout = ktime_add_ns(ktime_get(), LOCK_TIMEOUT_NS);
++ while (cprman_read(cprman, CM_OSCCOUNT)) {
++ if (ktime_after(ktime_get(), timeout)) {
++ dev_err(cprman->dev, "timeout waiting for OSCCOUNT\n");
++ count = 0;
++ goto out;
++ }
++ cpu_relax();
++ }
++
++ /* Wait for BUSY to clear. */
++ timeout = ktime_add_ns(ktime_get(), LOCK_TIMEOUT_NS);
++ while (cprman_read(cprman, CM_TCNTCTL) & CM_BUSY) {
++ if (ktime_after(ktime_get(), timeout)) {
++ dev_err(cprman->dev, "timeout waiting for !BUSY\n");
++ count = 0;
++ goto out;
++ }
++ cpu_relax();
++ }
++
++ count = cprman_read(cprman, CM_TCNTCNT);
++
++ cprman_write(cprman, CM_TCNTCTL, 0);
++
++out:
++ spin_unlock(&cprman->regs_lock);
++
++ return count * 1000;
++}
++
+ static int bcm2835_debugfs_regset(struct bcm2835_cprman *cprman, u32 base,
+ struct debugfs_reg32 *regs, size_t nregs,
+ struct dentry *dentry)
+@@ -473,6 +530,8 @@ struct bcm2835_clock_data {
+
+ bool is_vpu_clock;
+ bool is_mash_clock;
++
++ u32 tcnt_mux;
+ };
+
+ struct bcm2835_gate_data {
+@@ -1008,6 +1067,17 @@ static int bcm2835_clock_on(struct clk_h
+ CM_GATE);
+ spin_unlock(&cprman->regs_lock);
+
++ /* Debug code to measure the clock once it's turned on to see
++ * if it's ticking at the rate we expect.
++ */
++ if (data->tcnt_mux && false) {
++ dev_info(cprman->dev,
++ "clk %s: rate %ld, measure %ld\n",
++ data->name,
++ clk_hw_get_rate(hw),
++ bcm2835_measure_tcnt_mux(cprman, data->tcnt_mux));
++ }
++
+ return 0;
+ }
+
+@@ -1774,7 +1844,8 @@ static const struct bcm2835_clk_desc clk
+ .ctl_reg = CM_OTPCTL,
+ .div_reg = CM_OTPDIV,
+ .int_bits = 4,
+- .frac_bits = 0),
++ .frac_bits = 0,
++ .tcnt_mux = 6),
+ /*
+ * Used for a 1Mhz clock for the system clocksource, and also used
+ * bythe watchdog timer and the camera pulse generator.
+@@ -1808,13 +1879,15 @@ static const struct bcm2835_clk_desc clk
+ .ctl_reg = CM_H264CTL,
+ .div_reg = CM_H264DIV,
+ .int_bits = 4,
+- .frac_bits = 8),
++ .frac_bits = 8,
++ .tcnt_mux = 1),
+ [BCM2835_CLOCK_ISP] = REGISTER_VPU_CLK(
+ .name = "isp",
+ .ctl_reg = CM_ISPCTL,
+ .div_reg = CM_ISPDIV,
+ .int_bits = 4,
+- .frac_bits = 8),
++ .frac_bits = 8,
++ .tcnt_mux = 2),
+
+ /*
+ * Secondary SDRAM clock. Used for low-voltage modes when the PLL
+@@ -1825,13 +1898,15 @@ static const struct bcm2835_clk_desc clk
+ .ctl_reg = CM_SDCCTL,
+ .div_reg = CM_SDCDIV,
+ .int_bits = 6,
+- .frac_bits = 0),
++ .frac_bits = 0,
++ .tcnt_mux = 3),
+ [BCM2835_CLOCK_V3D] = REGISTER_VPU_CLK(
+ .name = "v3d",
+ .ctl_reg = CM_V3DCTL,
+ .div_reg = CM_V3DDIV,
+ .int_bits = 4,
+- .frac_bits = 8),
++ .frac_bits = 8,
++ .tcnt_mux = 4),
+ /*
+ * VPU clock. This doesn't have an enable bit, since it drives
+ * the bus for everything else, and is special so it doesn't need
+@@ -1845,7 +1920,8 @@ static const struct bcm2835_clk_desc clk
+ .int_bits = 12,
+ .frac_bits = 8,
+ .flags = CLK_IS_CRITICAL,
+- .is_vpu_clock = true),
++ .is_vpu_clock = true,
++ .tcnt_mux = 5),
+
+ /* clocks with per parent mux */
+ [BCM2835_CLOCK_AVEO] = REGISTER_PER_CLK(
+@@ -1853,19 +1929,22 @@ static const struct bcm2835_clk_desc clk
+ .ctl_reg = CM_AVEOCTL,
+ .div_reg = CM_AVEODIV,
+ .int_bits = 4,
+- .frac_bits = 0),
++ .frac_bits = 0,
++ .tcnt_mux = 38),
+ [BCM2835_CLOCK_CAM0] = REGISTER_PER_CLK(
+ .name = "cam0",
+ .ctl_reg = CM_CAM0CTL,
+ .div_reg = CM_CAM0DIV,
+ .int_bits = 4,
+- .frac_bits = 8),
++ .frac_bits = 8,
++ .tcnt_mux = 14),
+ [BCM2835_CLOCK_CAM1] = REGISTER_PER_CLK(
+ .name = "cam1",
+ .ctl_reg = CM_CAM1CTL,
+ .div_reg = CM_CAM1DIV,
+ .int_bits = 4,
+- .frac_bits = 8),
++ .frac_bits = 8,
++ .tcnt_mux = 15),
+ [BCM2835_CLOCK_DFT] = REGISTER_PER_CLK(
+ .name = "dft",
+ .ctl_reg = CM_DFTCTL,
+@@ -1877,7 +1956,8 @@ static const struct bcm2835_clk_desc clk
+ .ctl_reg = CM_DPICTL,
+ .div_reg = CM_DPIDIV,
+ .int_bits = 4,
+- .frac_bits = 8),
++ .frac_bits = 8,
++ .tcnt_mux = 17),
+
+ /* Arasan EMMC clock */
+ [BCM2835_CLOCK_EMMC] = REGISTER_PER_CLK(
+@@ -1885,7 +1965,8 @@ static const struct bcm2835_clk_desc clk
+ .ctl_reg = CM_EMMCCTL,
+ .div_reg = CM_EMMCDIV,
+ .int_bits = 4,
+- .frac_bits = 8),
++ .frac_bits = 8,
++ .tcnt_mux = 39),
+
+ /* General purpose (GPIO) clocks */
+ [BCM2835_CLOCK_GP0] = REGISTER_PER_CLK(
+@@ -1894,7 +1975,8 @@ static const struct bcm2835_clk_desc clk
+ .div_reg = CM_GP0DIV,
+ .int_bits = 12,
+ .frac_bits = 12,
+- .is_mash_clock = true),
++ .is_mash_clock = true,
++ .tcnt_mux = 20),
+ [BCM2835_CLOCK_GP1] = REGISTER_PER_CLK(
+ .name = "gp1",
+ .ctl_reg = CM_GP1CTL,
+@@ -1902,7 +1984,8 @@ static const struct bcm2835_clk_desc clk
+ .int_bits = 12,
+ .frac_bits = 12,
+ .flags = CLK_IS_CRITICAL,
+- .is_mash_clock = true),
++ .is_mash_clock = true,
++ .tcnt_mux = 21),
+ [BCM2835_CLOCK_GP2] = REGISTER_PER_CLK(
+ .name = "gp2",
+ .ctl_reg = CM_GP2CTL,
+@@ -1917,40 +2000,46 @@ static const struct bcm2835_clk_desc clk
+ .ctl_reg = CM_HSMCTL,
+ .div_reg = CM_HSMDIV,
+ .int_bits = 4,
+- .frac_bits = 8),
++ .frac_bits = 8,
++ .tcnt_mux = 22),
+ [BCM2835_CLOCK_PCM] = REGISTER_PER_CLK(
+ .name = "pcm",
+ .ctl_reg = CM_PCMCTL,
+ .div_reg = CM_PCMDIV,
+ .int_bits = 12,
+ .frac_bits = 12,
+- .is_mash_clock = true),
++ .is_mash_clock = true,
++ .tcnt_mux = 23),
+ [BCM2835_CLOCK_PWM] = REGISTER_PER_CLK(
+ .name = "pwm",
+ .ctl_reg = CM_PWMCTL,
+ .div_reg = CM_PWMDIV,
+ .int_bits = 12,
+ .frac_bits = 12,
+- .is_mash_clock = true),
++ .is_mash_clock = true,
++ .tcnt_mux = 24),
+ [BCM2835_CLOCK_SLIM] = REGISTER_PER_CLK(
+ .name = "slim",
+ .ctl_reg = CM_SLIMCTL,
+ .div_reg = CM_SLIMDIV,
+ .int_bits = 12,
+ .frac_bits = 12,
+- .is_mash_clock = true),
++ .is_mash_clock = true,
++ .tcnt_mux = 25),
+ [BCM2835_CLOCK_SMI] = REGISTER_PER_CLK(
+ .name = "smi",
+ .ctl_reg = CM_SMICTL,
+ .div_reg = CM_SMIDIV,
+ .int_bits = 4,
+- .frac_bits = 8),
++ .frac_bits = 8,
++ .tcnt_mux = 27),
+ [BCM2835_CLOCK_UART] = REGISTER_PER_CLK(
+ .name = "uart",
+ .ctl_reg = CM_UARTCTL,
+ .div_reg = CM_UARTDIV,
+ .int_bits = 10,
+- .frac_bits = 12),
++ .frac_bits = 12,
++ .tcnt_mux = 28),
+
+ /* TV encoder clock. Only operating frequency is 108Mhz. */
+ [BCM2835_CLOCK_VEC] = REGISTER_PER_CLK(
+@@ -1963,7 +2052,8 @@ static const struct bcm2835_clk_desc clk
+ * Allow rate change propagation only on PLLH_AUX which is
+ * assigned index 7 in the parent array.
+ */
+- .set_rate_parent = BIT(7)),
++ .set_rate_parent = BIT(7),
++ .tcnt_mux = 29),
+
+ /* dsi clocks */
+ [BCM2835_CLOCK_DSI0E] = REGISTER_PER_CLK(
+@@ -1971,25 +2061,29 @@ static const struct bcm2835_clk_desc clk
+ .ctl_reg = CM_DSI0ECTL,
+ .div_reg = CM_DSI0EDIV,
+ .int_bits = 4,
+- .frac_bits = 8),
++ .frac_bits = 8,
++ .tcnt_mux = 18),
+ [BCM2835_CLOCK_DSI1E] = REGISTER_PER_CLK(
+ .name = "dsi1e",
+ .ctl_reg = CM_DSI1ECTL,
+ .div_reg = CM_DSI1EDIV,
+ .int_bits = 4,
+- .frac_bits = 8),
++ .frac_bits = 8,
++ .tcnt_mux = 19),
+ [BCM2835_CLOCK_DSI0P] = REGISTER_DSI0_CLK(
+ .name = "dsi0p",
+ .ctl_reg = CM_DSI0PCTL,
+ .div_reg = CM_DSI0PDIV,
+ .int_bits = 0,
+- .frac_bits = 0),
++ .frac_bits = 0,
++ .tcnt_mux = 12),
+ [BCM2835_CLOCK_DSI1P] = REGISTER_DSI1_CLK(
+ .name = "dsi1p",
+ .ctl_reg = CM_DSI1PCTL,
+ .div_reg = CM_DSI1PDIV,
+ .int_bits = 0,
+- .frac_bits = 0),
++ .frac_bits = 0,
++ .tcnt_mux = 13),
+
+ /* the gates */
+