diff options
Diffstat (limited to 'target/linux/brcm2708/patches-4.9/950-0156-clk-bcm2835-Register-the-DSI0-DSI1-pixel-clocks.patch')
-rw-r--r-- | target/linux/brcm2708/patches-4.9/950-0156-clk-bcm2835-Register-the-DSI0-DSI1-pixel-clocks.patch | 238 |
1 files changed, 238 insertions, 0 deletions
diff --git a/target/linux/brcm2708/patches-4.9/950-0156-clk-bcm2835-Register-the-DSI0-DSI1-pixel-clocks.patch b/target/linux/brcm2708/patches-4.9/950-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/950-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 |