04.12.2019 23:33, Sowjanya Komatineni ÐÐÑÐÑ:
On 12/4/19 12:28 PM, Dmitry Osipenko wrote:It should be okay to fallback to extern1 for a backwards compatibility
04.12.2019 23:08, Sowjanya Komatineni ÐÐÑÐÑ:we can do parent init in audio driver which is not an issue.
On 12/4/19 8:02 AM, Sowjanya Komatineni wrote:There souldn't be any problem with enabling CLK_OUT_1 by the audio
On 12/4/19 5:39 AM, Dmitry Osipenko wrote:Actually if we change mclk to use clk_out_1, then it will break with old
03.12.2019 19:45, Sowjanya Komatineni ÐÐÑÐÑ:OK, will have this in v3
On 12/2/19 4:07 PM, Sowjanya Komatineni wrote:Hello Sowjanya,
On 12/2/19 3:14 PM, Sowjanya Komatineni wrote:Hi Dmitry,
On 12/2/19 3:10 PM, Sowjanya Komatineni wrote:clk_out_1 is for audio and its not required to be enabled during the
On 12/2/19 2:58 PM, Sowjanya Komatineni wrote:How about default ON/OFF init state for the clocks? I see
On 12/2/19 1:50 PM, Dmitry Osipenko wrote:assigned-clock properties should be set in consumer node of these
02.12.2019 23:09, Sowjanya Komatineni ÐÐÑÐÑ:Yes, of_clk_add_provider() does of_clk_set_defaults which sets
On 11/28/19 5:25 AM, Dmitry Osipenko wrote:Couldn't the default parent be defined using "assigned clock"
28.11.2019 01:57, Sowjanya Komatineni ÐÐÑÐÑ:
On 11/27/19 7:14 AM, Dmitry Osipenko wrote:
27.11.2019 07:59, Sowjanya Komatineni ÐÐÑÐÑ:
Tegra210 and prior Tegra PMC has clk_out_1, clk_out_2,
clk_out_3 with
mux and gate for each of these clocks.
Currently these PMC clocks are registered by Tegra clock
driver using
clk_register_mux and clk_register_gate by passing PMC base
address
and register offsets and PMC programming for these clocks
happens
through direct PMC access by the clock driver.
With this, when PMC is in secure mode any direct PMC access
from the
non-secure world does not go through and these clocks will
not be
functional.
This patch adds these clocks registration with PMC as a
clock
provider
for these clocks. clk_ops callback implementations for
these
clocks
uses tegra_pmc_readl and tegra_pmc_writel which supports
PMC
programming
in secure mode and non-secure mode.
Signed-off-by: Sowjanya Komatineni <skomatineni@xxxxxxxxxx>
---
ÂÂÂÂÂ drivers/soc/tegra/pmc.c | 330
++++++++++++++++++++++++++++++++++++++++++++++++
ÂÂÂÂÂ 1 file changed, 330 insertions(+)
diff --git a/drivers/soc/tegra/pmc.c
b/drivers/soc/tegra/pmc.c
index ea0e11a09c12..a353f6d0a832 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -13,6 +13,9 @@
ÂÂÂÂÂ Â #include <linux/arm-smccc.h>
ÂÂÂÂÂ #include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/clk/clk-conf.h>
ÂÂÂÂÂ #include <linux/clk/tegra.h>
ÂÂÂÂÂ #include <linux/debugfs.h>
ÂÂÂÂÂ #include <linux/delay.h>
@@ -48,6 +51,7 @@
ÂÂÂÂÂ #include <dt-bindings/pinctrl/pinctrl-tegra-io-pad.h>
ÂÂÂÂÂ #include <dt-bindings/gpio/tegra186-gpio.h>
ÂÂÂÂÂ #include <dt-bindings/gpio/tegra194-gpio.h>
+#include <dt-bindings/soc/tegra-pmc.h>
ÂÂÂÂÂ Â #define PMC_CNTRLÂÂÂÂÂÂÂÂÂÂÂ 0x0
 #define PMC_CNTRL_INTR_POLARITY BIT(17) /*
inverts INTR
polarity */
@@ -100,6 +104,7 @@
ÂÂÂÂÂ #define PMC_WAKE2_STATUSÂÂÂÂÂÂÂ 0x168
ÂÂÂÂÂ #define PMC_SW_WAKE2_STATUS 0x16c
ÂÂÂÂÂ +#define PMC_CLK_OUT_CNTRL 0x1a8
ÂÂÂÂÂ #define PMC_SENSOR_CTRL 0x1b0
ÂÂÂÂÂ #define PMC_SENSOR_CTRL_SCRATCH_WRITE BIT(2)
 #define PMC_SENSOR_CTRL_ENABLE_RST BIT(1)
@@ -155,6 +160,91 @@
 #define TEGRA_SMC_PMC_READ 0xaa
 #define TEGRA_SMC_PMC_WRITE 0xbb
ÂÂÂÂÂ +struct pmc_clk_mux {
+ÂÂÂ struct clk_hwÂÂÂ hw;
+ÂÂÂ unsigned longÂÂÂ offs;
+ÂÂÂ u32ÂÂÂÂÂÂÂ mask;
+ÂÂÂ u32ÂÂÂÂÂÂÂ shift;
+};
+
+#define to_pmc_clk_mux(_hw) container_of(_hw, struct
pmc_clk_mux, hw)
+
+struct pmc_clk_gate {
+ÂÂÂ struct clk_hwÂÂÂ hw;
+ÂÂÂ unsigned longÂÂÂ offs;
+ÂÂÂ u32ÂÂÂÂÂÂÂ shift;
+};
+
+#define to_pmc_clk_gate(_hw) container_of(_hw, struct
pmc_clk_gate, hw)
+
+struct pmc_clk_init_data {
+ÂÂÂ char *mux_name;
+ÂÂÂ char *gate_name;
+ÂÂÂ const char **parents;
+ÂÂÂ int num_parents;
+ÂÂÂ int mux_id;
+ÂÂÂ int gate_id;
+ÂÂÂ char *dev_name;
+ÂÂÂ u8 mux_shift;
+ÂÂÂ u8 gate_shift;
+ÂÂÂ u8 init_parent_index;
+ÂÂÂ int init_state;
+};
+
+static const char *clk_out1_parents[] = { "clk_m",
"clk_m_div2",
+ÂÂÂ "clk_m_div4", "extern1",
+};
+
+static const char *clk_out2_parents[] = { "clk_m",
"clk_m_div2",
+ÂÂÂ "clk_m_div4", "extern2",
+};
+
+static const char *clk_out3_parents[] = { "clk_m",
"clk_m_div2",
+ÂÂÂ "clk_m_div4", "extern3",
+};
+
+static struct pmc_clk_init_data tegra_pmc_clks_data[] = {
+ÂÂÂ {
+ÂÂÂÂÂÂÂ .mux_name = "clk_out_1_mux",
+ÂÂÂÂÂÂÂ .gate_name = "clk_out_1",
+ÂÂÂÂÂÂÂ .parents = clk_out1_parents,
+ÂÂÂÂÂÂÂ .num_parents = ARRAY_SIZE(clk_out1_parents),
+ÂÂÂÂÂÂÂ .mux_id = TEGRA_PMC_CLK_OUT_1_MUX,
+ÂÂÂÂÂÂÂ .gate_id = TEGRA_PMC_CLK_OUT_1,
+ÂÂÂÂÂÂÂ .dev_name = "extern1",
+ÂÂÂÂÂÂÂ .mux_shift = 6,
+ÂÂÂÂÂÂÂ .gate_shift = 2,
+ÂÂÂÂÂÂÂ .init_parent_index = 3,
+ÂÂÂÂÂÂÂ .init_state = 1,
+ÂÂÂ },
+ÂÂÂ {
+ÂÂÂÂÂÂÂ .mux_name = "clk_out_2_mux",
+ÂÂÂÂÂÂÂ .gate_name = "clk_out_2",
+ÂÂÂÂÂÂÂ .parents = clk_out2_parents,
+ÂÂÂÂÂÂÂ .num_parents = ARRAY_SIZE(clk_out2_parents),
+ÂÂÂÂÂÂÂ .mux_id = TEGRA_PMC_CLK_OUT_2_MUX,
+ÂÂÂÂÂÂÂ .gate_id = TEGRA_PMC_CLK_OUT_2,
+ÂÂÂÂÂÂÂ .dev_name = "extern2",
+ÂÂÂÂÂÂÂ .mux_shift = 14,
+ÂÂÂÂÂÂÂ .gate_shift = 10,
+ÂÂÂÂÂÂÂ .init_parent_index = 0,
+ÂÂÂÂÂÂÂ .init_state = 0,
+ÂÂÂ },
+ÂÂÂ {
+ÂÂÂÂÂÂÂ .mux_name = "clk_out_3_mux",
+ÂÂÂÂÂÂÂ .gate_name = "clk_out_3",
+ÂÂÂÂÂÂÂ .parents = clk_out3_parents,
+ÂÂÂÂÂÂÂ .num_parents = ARRAY_SIZE(clk_out3_parents),
+ÂÂÂÂÂÂÂ .mux_id = TEGRA_PMC_CLK_OUT_3_MUX,
+ÂÂÂÂÂÂÂ .gate_id = TEGRA_PMC_CLK_OUT_3,
+ÂÂÂÂÂÂÂ .dev_name = "extern3",
+ÂÂÂÂÂÂÂ .mux_shift = 22,
+ÂÂÂÂÂÂÂ .gate_shift = 18,
+ÂÂÂÂÂÂÂ .init_parent_index = 0,
+ÂÂÂÂÂÂÂ .init_state = 0,
+ÂÂÂ },
+};
+
ÂÂÂÂÂ struct tegra_powergate {
ÂÂÂÂÂÂÂÂÂ struct generic_pm_domain genpd;
ÂÂÂÂÂÂÂÂÂ struct tegra_pmc *pmc;
@@ -254,6 +344,9 @@ struct tegra_pmc_soc {
ÂÂÂÂÂÂÂÂÂÂ */
ÂÂÂÂÂÂÂÂÂ const struct tegra_wake_event *wake_events;
ÂÂÂÂÂÂÂÂÂ unsigned int num_wake_events;
+
+ÂÂÂ struct pmc_clk_init_data *pmc_clks_data;
+ÂÂÂ unsigned int num_pmc_clks;
ÂÂÂÂÂ };
ÂÂÂÂÂ Â static const char * const
tegra186_reset_sources[] = {
@@ -2163,6 +2256,228 @@ static int
tegra_pmc_clk_notify_cb(struct
notifier_block *nb,
ÂÂÂÂÂÂÂÂÂ return NOTIFY_OK;
ÂÂÂÂÂ }
ÂÂÂÂÂ +static void pmc_clk_fence_udelay(u32 offset)
+{
+ÂÂÂ tegra_pmc_readl(pmc, offset);
+ÂÂÂ /* pmc clk propagation delay 2 us */
+ÂÂÂ udelay(2);
+}
+
+static u8 pmc_clk_mux_get_parent(struct clk_hw *hw)
+{
+ÂÂÂ struct pmc_clk_mux *mux = to_pmc_clk_mux(hw);
+ÂÂÂ int num_parents = clk_hw_get_num_parents(hw);
+ÂÂÂ u32 val;
+
+ÂÂÂ val = tegra_pmc_readl(pmc, mux->offs) >> mux->shift;
+ÂÂÂ val &= mux->mask;
+
+ÂÂÂ if (val >= num_parents)
+ÂÂÂÂÂÂÂ return -EINVAL;
+
+ÂÂÂ return val;
+}
+
+static int pmc_clk_mux_set_parent(struct clk_hw *hw, u8
index)
+{
+ÂÂÂ struct pmc_clk_mux *mux = to_pmc_clk_mux(hw);
+ÂÂÂ u32 val;
+
+ÂÂÂ val = tegra_pmc_readl(pmc, mux->offs);
+ÂÂÂ val &= ~(mux->mask << mux->shift);
+ÂÂÂ val |= index << mux->shift;
+ÂÂÂ tegra_pmc_writel(pmc, val, mux->offs);
+ÂÂÂ pmc_clk_fence_udelay(mux->offs);
+
+ÂÂÂ return 0;
+}
+
+static const struct clk_ops pmc_clk_mux_ops = {
+ÂÂÂ .get_parent = pmc_clk_mux_get_parent,
+ÂÂÂ .set_parent = pmc_clk_mux_set_parent,
+ÂÂÂ .determine_rate = __clk_mux_determine_rate,
+};
+
+static struct clk *
+tegra_pmc_clk_mux_register(const char *name, const char *
const
*parent_names,
+ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ int num_parents, unsigned long flags,
+ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ unsigned long offset, u32 shift, u32 mask)
+{
+ÂÂÂ struct clk_init_data init;
+ÂÂÂ struct pmc_clk_mux *mux;
+
+ÂÂÂ mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+ÂÂÂ if (!mux)
+ÂÂÂÂÂÂÂ return ERR_PTR(-ENOMEM);
+
+ÂÂÂ init.name = name;
+ÂÂÂ init.ops = &pmc_clk_mux_ops;
+ÂÂÂ init.parent_names = parent_names;
+ÂÂÂ init.num_parents = num_parents;
+ÂÂÂ init.flags = flags;
+
+ÂÂÂ mux->hw.init = &init;
+ÂÂÂ mux->offs = offset;
+ÂÂÂ mux->mask = mask;
+ÂÂÂ mux->shift = shift;
+
+ÂÂÂ return clk_register(NULL, &mux->hw);
+}
+
+static int pmc_clk_is_enabled(struct clk_hw *hw)
+{
+ÂÂÂ struct pmc_clk_gate *gate = to_pmc_clk_gate(hw);
+
+ÂÂÂ return tegra_pmc_readl(pmc, gate->offs) &
BIT(gate->shift) ? 1
: 0;
+}
+
+static void pmc_clk_set_state(struct clk_hw *hw, int
state)
+{
+ÂÂÂ struct pmc_clk_gate *gate = to_pmc_clk_gate(hw);
+ÂÂÂ u32 val;
+
+ÂÂÂ val = tegra_pmc_readl(pmc, gate->offs);
+ÂÂÂ val = state ? (val | BIT(gate->shift)) : (val &
~BIT(gate->shift));
+ÂÂÂ tegra_pmc_writel(pmc, val, gate->offs);
+ÂÂÂ pmc_clk_fence_udelay(gate->offs);
+}
+
+static int pmc_clk_enable(struct clk_hw *hw)
+{
+ÂÂÂ pmc_clk_set_state(hw, 1);
+
+ÂÂÂ return 0;
+}
+
+static void pmc_clk_disable(struct clk_hw *hw)
+{
+ÂÂÂ pmc_clk_set_state(hw, 0);
+}
+
+static const struct clk_ops pmc_clk_gate_ops = {
+ÂÂÂ .is_enabled = pmc_clk_is_enabled,
+ÂÂÂ .enable = pmc_clk_enable,
+ÂÂÂ .disable = pmc_clk_disable,
+};
+
+static struct clk *
+tegra_pmc_clk_gate_register(const char *name, const char
*parent_name,
+ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ unsigned long flags, unsigned long offset,
+ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ u32 shift)
+{
+ÂÂÂ struct clk_init_data init;
+ÂÂÂ struct pmc_clk_gate *gate;
+
+ÂÂÂ gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+ÂÂÂ if (!gate)
+ÂÂÂÂÂÂÂ return ERR_PTR(-ENOMEM);
+
+ÂÂÂ init.name = name;
+ÂÂÂ init.ops = &pmc_clk_gate_ops;
+ÂÂÂ init.parent_names = &parent_name;
+ÂÂÂ init.num_parents = 1;
+ÂÂÂ init.flags = flags;
+
+ÂÂÂ gate->hw.init = &init;
+ÂÂÂ gate->offs = offset;
+ÂÂÂ gate->shift = shift;
+
+ÂÂÂ return clk_register(NULL, &gate->hw);
+}
+
+static void tegra_pmc_clock_register(struct tegra_pmc
*pmc,
+ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ struct device_node *np)
+{
+ÂÂÂ struct clk *clkmux, *clk, *parent;
+ÂÂÂ struct clk_onecell_data *clk_data;
+ÂÂÂ unsigned int num_clks;
+ÂÂÂ int i, ret;
+
+ÂÂÂ /* each pmc clock output has a mux and a gate */
+ÂÂÂ num_clks = pmc->soc->num_pmc_clks * 2;
+
+ÂÂÂ if (!num_clks)
+ÂÂÂÂÂÂÂ return;
+
+ÂÂÂ clk_data = kmalloc(sizeof(*clk_data), GFP_KERNEL);
+ÂÂÂ if (!clk_data)
+ÂÂÂÂÂÂÂ return;
+
+ÂÂÂ clk_data->clks = kcalloc(TEGRA_PMC_CLK_MAX,
sizeof(*clk_data->clks),
+ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ GFP_KERNEL);
+ÂÂÂ if (!clk_data->clks)
+ÂÂÂÂÂÂÂ goto free_clkdata;
+
+ÂÂÂ clk_data->clk_num = num_clks;
+
+ÂÂÂ for (i = 0; i < pmc->soc->num_pmc_clks; i++) {
+ÂÂÂÂÂÂÂ struct pmc_clk_init_data *data;
+
+ÂÂÂÂÂÂÂ data = pmc->soc->pmc_clks_data + i;
+
+ÂÂÂÂÂÂÂ clkmux =
tegra_pmc_clk_mux_register(data->mux_name,
+ data->parents,
+ data->num_parents,
+ CLK_SET_RATE_NO_REPARENT |
+ CLK_SET_RATE_PARENT,
+ PMC_CLK_OUT_CNTRL,
+ data->mux_shift, 3);
+ÂÂÂÂÂÂÂ if (IS_ERR(clkmux))
+ÂÂÂÂÂÂÂÂÂÂÂ goto free_clks;
+
+ clk_data->clks[data->mux_id] = clkmux;
+
+ÂÂÂÂÂÂÂ clk = tegra_pmc_clk_gate_register(data->gate_name,
+ data->mux_name,
+ CLK_SET_RATE_PARENT,
+ PMC_CLK_OUT_CNTRL,
+ data->gate_shift);
+ÂÂÂÂÂÂÂ if (IS_ERR(clk))
+ÂÂÂÂÂÂÂÂÂÂÂ goto free_clks;
+
+ clk_data->clks[data->gate_id] = clk;
+
+ÂÂÂÂÂÂÂ ret = clk_set_parent(clk, clkmux);
+ÂÂÂÂÂÂÂ if (ret < 0) {
+ÂÂÂÂÂÂÂÂÂÂÂ pr_err("failed to set parent of %s to %s\n",
+ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ __func__, __clk_get_name(clk),
+ __clk_get_name(clkmux));
+ÂÂÂÂÂÂÂ }
+
+ÂÂÂÂÂÂÂ clk_register_clkdev(clk, data->dev_name,
data->gate_name);
+
+ÂÂÂÂÂÂÂ /* configure initial clock parent and state */
+ÂÂÂÂÂÂÂ parent = clk_get_sys(data->gate_name,
+ data->parents[data->init_parent_index]);
in a
device-tree? Please see "Assigned clock parents and rates" in
the
doc.
https://www.kernel.org/doc/Documentation/devicetree/bindings/clock/clock-bindings.txt
Then you could simply use of_clk_set_defaults(pmc->dev->of_node,
true).
based on assigned parents and clock rates.
This need device tree to specify assigned clock parent
properties.
Will update device tree and remove init parent from the driver.
clocks and currently these clocks are not used yet.
So will just remove init parent from driver and when these clocks
are used device tree can be updated in corresponding consumer node
with these properties.
assigned-clock properties for parent and rate only.
But based on existing clock-tegra-pmc driver, I see clk_out_1 is
default enabled with extern1 parent for T30 thru T210 platforms.
Peter/Thierry, What was the reason we enable clk_out_1 right
from the
clock registration?
boot and audio driver can enable/disable it.
same with blink 32khz which is used for WIFI. WIFI driver can
enable/disable during power up/down sequence and technically as per
design we dont need to have it always on right from the boot.
So can remove out clocks init states from driver once thierry also
agree on this.
Looking at audio driver, it doesn't take care of mclk which is from
clk_out_1 and expects mclk to be always on.
So probably we should have this init state enables in pmc driver for
32Khz and clk_out's to not break existing functionality.
IIUC, it's a bug in the device-trees and sound's MCLK actually
should be
set to CLK_OUT_1 of PMC instead of CaR's EXTPERIPH1. If that's the
case,
then the device-trees need to be fixed.
device trees.
Currently clk_out_1 parent is set to extern1 as init state by the clock
driver and device tree for sound node is using extern1 as mclk works and
extern1 itself has enable and disable. But yes implementation wise, its
incorrect as mclk should really be clk_out_1.
Now, with moving clk_out_1 to tegra PMC, pmc is the clock provider and
if we now change the device tree to use CLK_OUT_1 as mclk then it will
break old device tree.
driver itself (in the code) if an old device-tree is detected.
ÂÂÂÂclk_out_1 = clk_get(dev, "clk_out_1");
ÂÂÂÂclk_set_parent(clk_out_1, clk_extern1);
ÂÂÂÂ...
ÂÂÂÂdata->clk_cdev1 = clk_out_1;
Maybe it will be even better to compare clocks for detection of an
older DT:
ÂÂÂÂif (tegra_get_chip_id() > TEGRA20 &&
ÂÂÂÂÂÂÂ clk_is_match(data->clk_cdev1, clk_extern1)) {
ÂÂÂÂ...
But I was saying we can keep extern1 as mclk in device tree instead of
changing to clk_out_1 from pmc as it will break old device tree becasue
we moved clk_out_1 from clock driver to pmc driver.
once we do init parent in audio driver, we still can use extern1 as mclk
in device tree.
mclk -> clk_out_1 -> extern1 -> plla_out0 -> plla
with init of clk_out_1 parent to extern1, mclk can use extern1 handle
for rate/enable/disable clk operations
of the new DT with older kernels.
@@ -192,8 +192,14 @@ int tegra_asoc_utils_init(struct
tegra_asoc_utils_data *data,
data->clk_cdev1 = clk_get(dev, "mclk");
if (IS_ERR(data->clk_cdev1)) {
dev_err(data->dev, "Can't retrieve clk cdev1\n");
- ret = PTR_ERR(data->clk_cdev1);
- goto err_put_pll_a_out0;
+
+ data->clk_cdev1 = clk_get_sys("clk_out_1", "extern1");
+ if (IS_ERR(data->clk_cdev1)) {
+ ret = PTR_ERR(data->clk_cdev1);
+ goto err_put_pll_a_out0;
+ }
+
+ dev_err(data->dev, "Falling back to extern1\n");
}
ret = tegra_asoc_utils_set_rate(data, 44100, 256 * 44100);
This change should be a standalone patch and it should be requsted for
backporting into stable kernels.
Will update clk-tegra, pmc and audio driver to move init stateRegarding using assigned-clock properties for init parent andSo it's the sound node which should have had the assigned clocks in
removing
init parent from driver, it also needs consumer node in device
tree to
be updated to specify assigned-clock properties for default/init
parent.
This breaks device tree ABI as prior Tegra210 supports audio driver.
device-tree in order to define route for the audio MCLK clock from CaR
to PMC.
Given that the audio clocks configuration is the same for all of the
currently supported boards, I think it will be better to remove the
entire audio clocks initialization from the clk drivers and move it
all
to the audio driver. It could be something like this:
int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data,
ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ struct device *dev)
{
ÂÂÂÂÂ...
ÂÂÂÂÂif (!of_find_property(dev->of_node, "assigned-clock-parents",
NULL) &&
ÂÂÂÂÂÂÂÂ tegra_get_chip_id() > TEGRA20) {
ÂÂÂÂÂÂÂÂ clk_extern1 = clk_get(dev, "extern1");
ÂÂÂÂÂÂÂÂ ...
ÂÂÂÂÂÂÂÂ clk_set_parent(clk_extern1, clk_pll_a_out0);
ÂÂÂÂÂÂÂÂ ...
ÂÂÂÂÂÂÂÂ clk_put(data->clk_cdev1);
ÂÂÂÂÂÂÂÂ data->clk_cdev1 = clk_out_1;
ÂÂÂÂÂ}
ÂÂÂÂÂ...
So now the old device-trees will cointinue to work and new could have
the assigned-clocks and set MCLK to CLK_OUT_1.
[snip]
configuration for extern1 and clk_out_1 into audio driver and will use
assigned clock properties in device tree.