Re: [PATCH v1 04/17] soc: tegra: Add Tegra PMC clock registrations into PMC driver

From: Dmitry Osipenko
Date: Wed Nov 20 2019 - 12:46:10 EST


19.11.2019 23:08, Sowjanya Komatineni ÐÐÑÐÑ:
>
> On 11/19/19 11:33 AM, Dmitry Osipenko wrote:
>> 19.11.2019 09:50, Sowjanya Komatineni ÐÐÑÐÑ:
>>> 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 7a5aab0b993b..790a6619ba32 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 */
>>> @@ -108,6 +112,7 @@
>>> Â #define PMC_WAKE2_STATUSÂÂÂÂÂÂÂ 0x168
>>> Â #define PMC_SW_WAKE2_STATUSÂÂÂÂÂÂÂ 0x16c
>>> Â +#define PMC_CLK_OUT_CNTRLÂÂÂÂÂÂÂ 0x1a8
>>> Â #define PMC_SATA_PWRGTÂÂÂÂÂÂÂÂÂÂÂ 0x1ac
>>> Â #define PMC_SATA_PWRGT_PLLE_IDDQ_VALUE BIT(5)
>>> Â #define PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL BIT(4)
>>> @@ -170,6 +175,78 @@
>>>  #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;
>>> +ÂÂÂ /* register lock */
>>> +ÂÂÂ spinlock_tÂÂÂ *lock;
>>> +};
>>> +
>>> +#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;
>>> +ÂÂÂ /* register lock */
>>> +ÂÂÂ spinlock_tÂÂÂ *lock;

Why clk_out_lock is needed at all? CCLK framework already takes care of
the clock's locking and then nothing else in PMC code uses that lock to
avoid races, thus that spinlock doesn't do anything useful and should be
removed from both mux and gate.

>>> +};
>>> +
>>> +#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;
>>> +ÂÂÂ int init_state;
>>> +ÂÂÂ struct pmc_clk_mux mux;
>>> +ÂÂÂ struct pmc_clk_gate gate;
>>> +};
>>> +
>>> +#define PMC_CLK(_num, _mux_shift, _gate_shift, _init_parent,
>>> _init_state)\
>>> +ÂÂÂ {\
>>> +ÂÂÂÂÂÂÂ .mux_name = "clk_out_" #_num "_mux",\
>>> +ÂÂÂÂÂÂÂ .gate_name = "clk_out_" #_num,\
>>> +ÂÂÂÂÂÂÂ .parents = clk_out ##_num ##_parents,\
>>> +ÂÂÂÂÂÂÂ .num_parents = ARRAY_SIZE(clk_out ##_num ##_parents),\
>>> +ÂÂÂÂÂÂÂ .mux_id = TEGRA_PMC_CLK_OUT_ ##_num ##_MUX,\
>>> +ÂÂÂÂÂÂÂ .gate_id = TEGRA_PMC_CLK_OUT_ ##_num,\
>>> +ÂÂÂÂÂÂÂ .dev_name = "extern" #_num,\
>>> +ÂÂÂÂÂÂÂ .mux_shift = _mux_shift,\
>>> +ÂÂÂÂÂÂÂ .gate_shift = _gate_shift,\
>>> +ÂÂÂÂÂÂÂ .init_parent = _init_parent,\
>>> +ÂÂÂÂÂÂÂ .init_state = _init_state,\
>>> +ÂÂÂ }
>>> +
>>> +static DEFINE_SPINLOCK(clk_out_lock);
>>> +
>>> +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",
>>> +};
>> Why these are unused?
> They are used in PMC_CLK macro

Looks like it will better to define those three structs directly,
without the PMC_CLK macro.

[snip]