aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/brcm2708/patches-4.9/0156-clk-bcm2835-Register-the-DSI0-DSI1-pixel-clocks.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/brcm2708/patches-4.9/0156-clk-bcm2835-Register-the-DSI0-DSI1-pixel-clocks.patch')
-rw-r--r--target/linux/brcm2708/patches-4.9/0156-clk-bcm2835-Register-the-DSI0-DSI1-pixel-clocks.patch238
1 files changed, 238 insertions, 0 deletions
diff --git a/target/linux/brcm2708/patches-4.9/0156-clk-bcm2835-Register-the-DSI0-DSI1-pixel-clocks.patch b/target/linux/brcm2708/patches-4.9/0156-clk-bcm2835-Register-the-DSI0-DSI1-pixel-clocks.patch
new file mode 100644
index 0000000000..24e8aedbdc
--- /dev/null
+++ b/target/linux/brcm2708/patches-4.9/0156-clk-bcm2835-Register-the-DSI0-DSI1-pixel-clocks.patch
@@ -0,0 +1,238 @@
+From 876f8ef32ec09fb566cc6ecdf4c96a8348f135b6 Mon Sep 17 00:00:00 2001
+From: Eric Anholt <eric@anholt.net>
+Date: Wed, 18 Jan 2017 07:31:56 +1100
+Subject: [PATCH] clk: bcm2835: Register the DSI0/DSI1 pixel clocks.
+
+The DSI pixel clocks are muxed from clocks generated in the analog phy
+by the DSI driver. In order to set them as parents, we need to do the
+same name lookup dance on them as we do for our root oscillator.
+
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
+(cherry picked from commit 8a39e9fa578229fd4604266c6ebb1a3a77d7994c)
+---
+ .../bindings/clock/brcm,bcm2835-cprman.txt | 15 ++-
+ drivers/clk/bcm/clk-bcm2835.c | 121 +++++++++++++++++++--
+ include/dt-bindings/clock/bcm2835.h | 2 +
+ 3 files changed, 125 insertions(+), 13 deletions(-)
+
+--- a/Documentation/devicetree/bindings/clock/brcm,bcm2835-cprman.txt
++++ b/Documentation/devicetree/bindings/clock/brcm,bcm2835-cprman.txt
+@@ -16,7 +16,20 @@ Required properties:
+ - #clock-cells: Should be <1>. The permitted clock-specifier values can be
+ found in include/dt-bindings/clock/bcm2835.h
+ - reg: Specifies base physical address and size of the registers
+-- clocks: The external oscillator clock phandle
++- clocks: phandles to the parent clocks used as input to the module, in
++ the following order:
++
++ - External oscillator
++ - DSI0 byte clock
++ - DSI0 DDR2 clock
++ - DSI0 DDR clock
++ - DSI1 byte clock
++ - DSI1 DDR2 clock
++ - DSI1 DDR clock
++
++ Only external oscillator is required. The DSI clocks may
++ not be present, in which case their children will be
++ unusable.
+
+ Example:
+
+--- a/drivers/clk/bcm/clk-bcm2835.c
++++ b/drivers/clk/bcm/clk-bcm2835.c
+@@ -297,11 +297,32 @@
+ #define LOCK_TIMEOUT_NS 100000000
+ #define BCM2835_MAX_FB_RATE 1750000000u
+
++/*
++ * Names of clocks used within the driver that need to be replaced
++ * with an external parent's name. This array is in the order that
++ * the clocks node in the DT references external clocks.
++ */
++static const char *const cprman_parent_names[] = {
++ "xosc",
++ "dsi0_byte",
++ "dsi0_ddr2",
++ "dsi0_ddr",
++ "dsi1_byte",
++ "dsi1_ddr2",
++ "dsi1_ddr",
++};
++
+ struct bcm2835_cprman {
+ struct device *dev;
+ void __iomem *regs;
+ spinlock_t regs_lock; /* spinlock for all clocks */
+- const char *osc_name;
++
++ /*
++ * Real names of cprman clock parents looked up through
++ * of_clk_get_parent_name(), which will be used in the
++ * parent_names[] arrays for clock registration.
++ */
++ const char *real_parent_names[ARRAY_SIZE(cprman_parent_names)];
+
+ /* Must be last */
+ struct clk_hw_onecell_data onecell;
+@@ -907,6 +928,9 @@ static long bcm2835_clock_rate_from_divi
+ const struct bcm2835_clock_data *data = clock->data;
+ u64 temp;
+
++ if (data->int_bits == 0 && data->frac_bits == 0)
++ return parent_rate;
++
+ /*
+ * The divisor is a 12.12 fixed point field, but only some of
+ * the bits are populated in any given clock.
+@@ -930,7 +954,12 @@ static unsigned long bcm2835_clock_get_r
+ struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
+ struct bcm2835_cprman *cprman = clock->cprman;
+ const struct bcm2835_clock_data *data = clock->data;
+- u32 div = cprman_read(cprman, data->div_reg);
++ u32 div;
++
++ if (data->int_bits == 0 && data->frac_bits == 0)
++ return parent_rate;
++
++ div = cprman_read(cprman, data->div_reg);
+
+ return bcm2835_clock_rate_from_divisor(clock, parent_rate, div);
+ }
+@@ -1209,7 +1238,7 @@ static struct clk_hw *bcm2835_register_p
+ memset(&init, 0, sizeof(init));
+
+ /* All of the PLLs derive from the external oscillator. */
+- init.parent_names = &cprman->osc_name;
++ init.parent_names = &cprman->real_parent_names[0];
+ init.num_parents = 1;
+ init.name = data->name;
+ init.ops = &bcm2835_pll_clk_ops;
+@@ -1295,18 +1324,22 @@ static struct clk_hw *bcm2835_register_c
+ struct bcm2835_clock *clock;
+ struct clk_init_data init;
+ const char *parents[1 << CM_SRC_BITS];
+- size_t i;
++ size_t i, j;
+ int ret;
+
+ /*
+- * Replace our "xosc" references with the oscillator's
+- * actual name.
++ * Replace our strings referencing parent clocks with the
++ * actual clock-output-name of the parent.
+ */
+ for (i = 0; i < data->num_mux_parents; i++) {
+- if (strcmp(data->parents[i], "xosc") == 0)
+- parents[i] = cprman->osc_name;
+- else
+- parents[i] = data->parents[i];
++ parents[i] = data->parents[i];
++
++ for (j = 0; j < ARRAY_SIZE(cprman_parent_names); j++) {
++ if (strcmp(parents[i], cprman_parent_names[j]) == 0) {
++ parents[i] = cprman->real_parent_names[j];
++ break;
++ }
++ }
+ }
+
+ memset(&init, 0, sizeof(init));
+@@ -1442,6 +1475,47 @@ static const char *const bcm2835_clock_v
+ __VA_ARGS__)
+
+ /*
++ * DSI parent clocks. The DSI byte/DDR/DDR2 clocks come from the DSI
++ * analog PHY. The _inv variants are generated internally to cprman,
++ * but we don't use them so they aren't hooked up.
++ */
++static const char *const bcm2835_clock_dsi0_parents[] = {
++ "gnd",
++ "xosc",
++ "testdebug0",
++ "testdebug1",
++ "dsi0_ddr",
++ "dsi0_ddr_inv",
++ "dsi0_ddr2",
++ "dsi0_ddr2_inv",
++ "dsi0_byte",
++ "dsi0_byte_inv",
++};
++
++static const char *const bcm2835_clock_dsi1_parents[] = {
++ "gnd",
++ "xosc",
++ "testdebug0",
++ "testdebug1",
++ "dsi1_ddr",
++ "dsi1_ddr_inv",
++ "dsi1_ddr2",
++ "dsi1_ddr2_inv",
++ "dsi1_byte",
++ "dsi1_byte_inv",
++};
++
++#define REGISTER_DSI0_CLK(...) REGISTER_CLK( \
++ .num_mux_parents = ARRAY_SIZE(bcm2835_clock_dsi0_parents), \
++ .parents = bcm2835_clock_dsi0_parents, \
++ __VA_ARGS__)
++
++#define REGISTER_DSI1_CLK(...) REGISTER_CLK( \
++ .num_mux_parents = ARRAY_SIZE(bcm2835_clock_dsi1_parents), \
++ .parents = bcm2835_clock_dsi1_parents, \
++ __VA_ARGS__)
++
++/*
+ * the real definition of all the pll, pll_dividers and clocks
+ * these make use of the above REGISTER_* macros
+ */
+@@ -1904,6 +1978,18 @@ static const struct bcm2835_clk_desc clk
+ .div_reg = CM_DSI1EDIV,
+ .int_bits = 4,
+ .frac_bits = 8),
++ [BCM2835_CLOCK_DSI0P] = REGISTER_DSI0_CLK(
++ .name = "dsi0p",
++ .ctl_reg = CM_DSI0PCTL,
++ .div_reg = CM_DSI0PDIV,
++ .int_bits = 0,
++ .frac_bits = 0),
++ [BCM2835_CLOCK_DSI1P] = REGISTER_DSI1_CLK(
++ .name = "dsi1p",
++ .ctl_reg = CM_DSI1PCTL,
++ .div_reg = CM_DSI1PDIV,
++ .int_bits = 0,
++ .frac_bits = 0),
+
+ /* the gates */
+
+@@ -1962,8 +2048,19 @@ static int bcm2835_clk_probe(struct plat
+ if (IS_ERR(cprman->regs))
+ return PTR_ERR(cprman->regs);
+
+- cprman->osc_name = of_clk_get_parent_name(dev->of_node, 0);
+- if (!cprman->osc_name)
++ memcpy(cprman->real_parent_names, cprman_parent_names,
++ sizeof(cprman_parent_names));
++ of_clk_parent_fill(dev->of_node, cprman->real_parent_names,
++ ARRAY_SIZE(cprman_parent_names));
++
++ /*
++ * Make sure the external oscillator has been registered.
++ *
++ * The other (DSI) clocks are not present on older device
++ * trees, which we still need to support for backwards
++ * compatibility.
++ */
++ if (!cprman->real_parent_names[0])
+ return -ENODEV;
+
+ platform_set_drvdata(pdev, cprman);
+--- a/include/dt-bindings/clock/bcm2835.h
++++ b/include/dt-bindings/clock/bcm2835.h
+@@ -64,3 +64,5 @@
+ #define BCM2835_CLOCK_CAM1 46
+ #define BCM2835_CLOCK_DSI0E 47
+ #define BCM2835_CLOCK_DSI1E 48
++#define BCM2835_CLOCK_DSI0P 49
++#define BCM2835_CLOCK_DSI1P 50