Tegra PMC has clk_out_1, clk_out_2, clk_out_3 and blink controls which
are currently registered by Tegra clock driver using clk_regiser_mux and
clk_register_gate which performs direct Tegra PMC register access.
When Tegra PMC is in secure mode, any access from non-secure world will
not go through.
This patch series adds these Tegra PMC clocks and blink controls to Tegra
PMC driver with PMC as clock provider and removed them from Tegra clock
driver. This also adds PMC specific clock id's to use in device tree and
removed clock ids of PMC clock from Tegra clock driver.
clk_out_1 is dedicated for audio mclk and current ASoC driver does not
setting extern1 as parent for clk_out_1 and enabling clk_out_1 and
currently this is taken care by Tegra clock driver during clock inits
and there is no need to enable this during clock init.
So, this series also includes patch that updates ASoC driver to take
care of configuring parent of mclk and enabling mclk using both extern1
and clk_out_1 and updates all device trees to use clk_out_1 from pmc as
mclk incase if device tree don't specify assigned-clock-parents.
This series also includes a patch for mclk fallback to use extern1
when retrieving mclk fails with new device tree which uses pmc provider
to have this backward compatible of new DT with old kernels.
This series also includes a patch to remove clock ids for these clocks
from clock dt-binding as these clocks are not used in any of the existing
device tree except in tegra210-smaug.dts and this series includes a patch
to update clock provider from tegra_car to pmc in tegra210-smaug.dts for
clk_out_2.
[v3]: Changes between v2 and v3 are
- Removes set parent of clk_out_1_mux to extern1 and enabling
extern1 from the clock driver.
- Doesn't enable clk_out_1 and blink by default in pmc driver
- Updates ASoC driver to take care of audio mclk parent
configuration incase if device tree don't specify assigned
clock parent properties and enables mclk using both clk_out_1
and extern1.
- updates all device trees using extern1 as mclk in sound node
to use clk_out_1 from pmc.
- patch for YAML format pmc dt-binding
- Includes v2 feedback
[v2]: Changes between v1 and v2 are
- v2 includes patches for adding clk_out_1, clk_out_2, clk_out_3,
blink controls to Tegra PMC driver and removing clk-tegra-pmc.
- feedback related to pmc clocks in Tegra PMC driver from v1
- Removed patches for WB0 PLLM overrides and PLLE IDDQ PMC programming
by the clock driver using helper functions from Tegra PMC.
Note:
To use helper functions from PMC driver, PMC early init need to
happen prior to using helper functions and these helper functions are
for PLLM Override and PLLE IDDQ programming in PMC during PLLM/PLLE
clock registration which happen in clock_init prior to Tegra PMC
probe.
Moving PLLM/PLLE clocks registration to happen after Tegra PMC
impacts other clocks EMC, MC and corresponding tegra_emc_init and
tegra_mc_init.
This implementation of configuring PMC registers thru helper
functions in clock driver needs proper changes across PMC, Clock,
EMC and MC inits to have it work across all Tegra platforms.
Currently PLLM Override is not enabled in the bootloader so proper
patches for this fix will be taken care separately.
[v1]: v1 includes patches for below fixes.
- adding clk_out_1, clk_out_2, clk_out_3, blink controls to Tegra PMC
driver and removing clk-tegra-pmc.
- updated clock provider from tegra_car to pmc in the device tree
tegra210-smaug.dts that uses clk_out_2.
- Added helper functions in PMC driver for WB0 PLLM overrides and PLLE
IDDQ programming to use by clock driver and updated clock driver to
use these helper functions and removed direct PMC access from clock
driver and all pmc base address references in clock driver.
Sowjanya Komatineni (15):
dt-bindings: soc: tegra-pmc: Add Tegra PMC clock bindings
dt-bindings: tegra: Convert Tegra PMC bindings to YAML
soc: tegra: Add Tegra PMC clock registrations into PMC driver
dt-bindings: soc: tegra-pmc: Add id for Tegra PMC blink control
soc: pmc: Add blink output clock registration to Tegra PMC
clk: tegra: Remove tegra_pmc_clk_init along with clk ids
dt-bindings: clock: tegra: Remove pmc clock ids from clock dt-bindings
ASoC: tegra: Add audio mclk control through clk_out_1 and extern1
ASoC: tegra: Add fallback for audio mclk
clk: tegra: Remove extern1 and cdev1 from clocks inittable
ARM: dts: tegra: Add clock-cells property to pmc
arm64: tegra: Add clock-cells property to Tegra PMC node
ARM: tegra: Update sound node clocks in device tree
arm64: tegra: smaug: Change clk_out_2 provider to pmc
ASoC: nau8825: change Tegra clk_out_2 provider from tegra_car to pmc
.../bindings/arm/tegra/nvidia,tegra20-pmc.txt | 45 ++-
.../bindings/arm/tegra/nvidia,tegra20-pmc.yaml | 291 ++++++++++++++++++
.../devicetree/bindings/sound/nau8825.txt | 2 +-
arch/arm/boot/dts/tegra114-dalmore.dts | 7 +-
arch/arm/boot/dts/tegra114.dtsi | 4 +-
arch/arm/boot/dts/tegra124-apalis-v1.2.dtsi | 7 +-
arch/arm/boot/dts/tegra124-apalis.dtsi | 7 +-
arch/arm/boot/dts/tegra124-jetson-tk1.dts | 7 +-
arch/arm/boot/dts/tegra124-nyan.dtsi | 7 +-
arch/arm/boot/dts/tegra124-venice2.dts | 7 +-
arch/arm/boot/dts/tegra124.dtsi | 4 +-
arch/arm/boot/dts/tegra20.dtsi | 4 +-
arch/arm/boot/dts/tegra30-apalis-v1.1.dtsi | 7 +-
arch/arm/boot/dts/tegra30-apalis.dtsi | 7 +-
arch/arm/boot/dts/tegra30-beaver.dts | 7 +-
arch/arm/boot/dts/tegra30-cardhu.dtsi | 7 +-
arch/arm/boot/dts/tegra30-colibri.dtsi | 7 +-
arch/arm/boot/dts/tegra30.dtsi | 4 +-
arch/arm64/boot/dts/nvidia/tegra132.dtsi | 4 +-
arch/arm64/boot/dts/nvidia/tegra210-smaug.dts | 2 +-
arch/arm64/boot/dts/nvidia/tegra210.dtsi | 2 +
drivers/clk/tegra/Makefile | 1 -
drivers/clk/tegra/clk-id.h | 7 -
drivers/clk/tegra/clk-tegra-pmc.c | 122 --------
drivers/clk/tegra/clk-tegra114.c | 12 -
drivers/clk/tegra/clk-tegra124.c | 28 +-
drivers/clk/tegra/clk-tegra20.c | 5 -
drivers/clk/tegra/clk-tegra210.c | 12 -
drivers/clk/tegra/clk-tegra30.c | 13 -
drivers/clk/tegra/clk.h | 1 -
drivers/soc/tegra/pmc.c | 340 +++++++++++++++++++++
include/dt-bindings/clock/tegra114-car.h | 14 +-
include/dt-bindings/clock/tegra124-car-common.h | 14 +-
include/dt-bindings/clock/tegra20-car.h | 2 +-
include/dt-bindings/clock/tegra210-car.h | 14 +-
include/dt-bindings/clock/tegra30-car.h | 14 +-
include/dt-bindings/soc/tegra-pmc.h | 19 ++
sound/soc/tegra/tegra_asoc_utils.c | 76 ++++-
sound/soc/tegra/tegra_asoc_utils.h | 1 +
39 files changed, 890 insertions(+), 244 deletions(-)
create mode 100644 Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.yaml
delete mode 100644 drivers/clk/tegra/clk-tegra-pmc.c
create mode 100644 include/dt-bindings/soc/tegra-pmc.h
--
2.7.4
Tegra PMC has a blinking control to output 32 KHz clock to blink
pin.
This patch adds id for this blink control to use for enabling or
disabling the blink output through devicetree.
Signed-off-by: Sowjanya Komatineni <[email protected]>
---
include/dt-bindings/soc/tegra-pmc.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/include/dt-bindings/soc/tegra-pmc.h b/include/dt-bindings/soc/tegra-pmc.h
index 705ee8083070..6fe28516017e 100644
--- a/include/dt-bindings/soc/tegra-pmc.h
+++ b/include/dt-bindings/soc/tegra-pmc.h
@@ -12,7 +12,8 @@
#define TEGRA_PMC_CLK_OUT_2 3
#define TEGRA_PMC_CLK_OUT_3_MUX 4
#define TEGRA_PMC_CLK_OUT_3 5
+#define TEGRA_PMC_CLK_BLINK 6
-#define TEGRA_PMC_CLK_MAX 6
+#define TEGRA_PMC_CLK_MAX 7
#endif /* _DT_BINDINGS_SOC_TEGRA_PMC_H */
--
2.7.4
This patch adds YAML schema for Tegra PMC bindings.
Signed-off-by: Sowjanya Komatineni <[email protected]>
---
.../bindings/arm/tegra/nvidia,tegra20-pmc.yaml | 291 +++++++++++++++++++++
1 file changed, 291 insertions(+)
create mode 100644 Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.yaml
diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.yaml b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.yaml
new file mode 100644
index 000000000000..ab614f1be177
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.yaml
@@ -0,0 +1,291 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/arm/tegra/nvidia,tegra20-pmc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Tegra Power Management Controller (PMC)
+
+maintainers:
+ - Thierry Reding <[email protected]>
+ - Jonathan Hunter <[email protected]>
+
+properties:
+ compatible:
+ oneOf:
+ - items:
+ - const: nvidia,tegra20-pmc
+ - const: nvidia,tegra20-pmc
+ - const: nvidia,tegra30-pmc
+ - const: nvidia,tegra114-pmc
+ - const: nvidia,tegra124-pmc
+ - const: nvidia,tegra210-pmc
+
+ reg:
+ maxItems: 1
+
+ clock-names:
+ items:
+ - const: pclk, clk32k_in
+ description:
+ pclk is the Tegra clock of that name and clk32k_in is 32KHz clock
+ input to Tegra.
+
+ clocks:
+ maxItems: 2
+
+ '#clock-cells':
+ const: 1
+ description:
+ Tegra PMC has clk_out_1, clk_out_2, and clk_out_3.
+ Consumer of PMC clock should specify the desired clock by having
+ the clock ID in its "clocks" phandle cell with pmc clock provider.
+ See include/dt-bindings/soc/tegra-pmc.h for the list of Tegra PMC
+ clock IDs.
+
+ nvidia,invert-interrupt:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description: Inverts the PMU interrupt signal.
+ The PMU is an external Power Management Unit, whose interrupt output
+ signal is fed into the PMC. This signal is optionally inverted, and
+ then fed into the ARM GIC. The PMC is not involved in the detection
+ or handling of this interrupt signal, merely its inversion.
+
+ nvidia,core-power-req-active-high:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description: Core power request active-high.
+
+ nvidia,sys-clock-req-active-high:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description: System clock request active-high.
+
+ nvidia,combined-power-req:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description: combined power request for CPU and Core.
+
+ nvidia,cpu-pwr-good-en:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description:
+ CPU power good signal from external PMIC to PMC is enabled.
+
+ nvidia,suspend-mode:
+ allOf:
+ - $ref: /schemas/types.yaml#/definitions/uint32
+ - enum: [0, 1, 2]
+ description:
+ The suspend mode that the platform should use.
+ Mode 0 is for LP0, CPU + Core voltage off and DRAM in self-refresh
+ Mode 1 is for LP1, CPU voltage off and DRAM in self-refresh
+ Mode 2 is for LP2, CPU voltage off
+
+ nvidia,cpu-pwr-good-time:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: CPU power good time in uSec.
+
+ nvidia,cpu-pwr-off-time:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: CPU power off time in uSec.
+
+ nvidia,core-pwr-good-time:
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ description:
+ <Oscillator-stable-time Power-stable-time>
+ Core power good time in uSec.
+
+ nvidia,core-pwr-off-time:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: Core power off time in uSec.
+
+ nvidia,lp0-vec:
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ description:
+ <start length> Starting address and length of LP0 vector.
+ The LP0 vector contains the warm boot code that is executed
+ by AVP when resuming from the LP0 state.
+ The AVP (Audio-Video Processor) is an ARM7 processor and
+ always being the first boot processor when chip is power on
+ or resume from deep sleep mode. When the system is resumed
+ from the deep sleep mode, the warm boot code will restore
+ some PLLs, clocks and then brings up CPU0 for resuming the
+ system.
+
+ i2c-thermtrip:
+ type: object
+ description:
+ On Tegra30, Tegra114 and Tegra124 if i2c-thermtrip subnode exists,
+ hardware-triggered thermal reset will be enabled.
+
+ properties:
+ nvidia,i2c-controller-id:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ ID of I2C controller to send poweroff command to PMU.
+ Valid values are described in section 9.2.148
+ "APBDEV_PMC_SCRATCH53_0" of the Tegra K1 Technical Reference
+ Manual.
+
+ nvidia,bus-addr:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: Bus address of the PMU on the I2C bus.
+
+ nvidia,reg-addr:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: PMU I2C register address to issue poweroff command.
+
+ nvidia,reg-data:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: Poweroff command to write to PMU.
+
+ nvidia,pinmux-id:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ Pinmux used by the hardware when issuing Poweroff command.
+ Defaults to 0. Valid values are described in section 12.5.2
+ "Pinmux Support" of the Tegra4 Technical Reference Manual.
+
+ required:
+ - nvidia,i2c-controller-id
+ - nvidia,bus-addr
+ - nvidia,reg-addr
+ - nvidia,reg-data
+
+ powergates:
+ type: object
+ description:
+ This node contains a hierarchy of power domain nodes, which should
+ match the powergates on the Tegra SoC. Each powergate node
+ represents a power-domain on the Tegra SoC that can be power-gated
+ by the Tegra PMC.
+ Hardware blocks belonging to a power domain should contain
+ "power-domains" property that is a phandle pointing to corresponding
+ powergate node.
+ Please refer to Tegra TRM for mode details on the powergate nodes to
+ use for each power-gate block inside Tegra.
+
+ patternProperties:
+ "^[a-z0-9]+$":
+ if:
+ type: object
+ then:
+ patternProperties:
+ clocks:
+ description:
+ Must contain an entry for each clock required by the PMC
+ for controlling a power-gate.
+ See ../clocks/clock-bindings.txt document for more details.
+
+ resets:
+ description:
+ Must contain an entry for each reset required by the PMC
+ for controlling a power-gate.
+ See ../reset/reset.txt for more details.
+
+ '#power-domain-cells':
+ description: Must be 0.
+
+ required:
+ - clocks
+ - resets
+ - '#power-domain-cells'
+
+patternProperties:
+ "^.*@[0-9a-f]+$":
+ type: object
+
+ properties:
+ pins:
+ $ref: /schemas/types.yaml#/definitions/string
+ description: Must contain name of the pad(s) to be configured.
+
+ low-power-enable:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description: Configure the pad into power down mode.
+
+ low-power-disable:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description: Configure the pad into active mode.
+
+ power-source:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ Must contain either TEGRA_IO_PAD_VOLTAGE_1V8 or
+ TEGRA_IO_PAD_VOLTAGE_3V3 to select between signaling voltages.
+ The values are defined in
+ include/dt-bindings/pinctrl/pinctrl-tegra-io-pad.h.
+ Power state can be configured on all Tegra124 and Tegra132
+ pads. None of the Tegra124 or Tegra132 pads support signaling
+ voltage switching.
+ All of the listed Tegra210 pads except pex-cntrl support power
+ state configuration. Signaling voltage switching is supported
+ on below Tegra210 pads.
+ audio, audio-hv, cam, dbg, dmic, gpio, pex-cntrl, sdmmc1,
+ sdmmc3, spi, spi-hv, and uart.
+
+ required:
+ - pins
+
+required:
+ - compatible
+ - reg
+ - clock-names
+ - clocks
+ - '#clock-cells'
+
+if:
+ properties:
+ nvidia,suspend-mode:
+ contains:
+ const: 2
+
+then:
+ required:
+ - nvidia,cpu-pwr-good-time
+ - nvidia,cpu-pwr-off-time
+ - nvidia,core-pwr-good-time
+ - nvidia,core-pwr-off-time
+
+examples:
+ - |
+ #include <dt-bindings/soc/tegra-pmc.h>
+
+ pmc: pmc@7000e400 {
+ compatible = "nvidia,tegra210-pmc";
+ reg = <0x0 0x7000e400 0x0 0x400>;
+ clocks = <&tegra_car TEGRA210_CLK_PCLK>, <&clk32k_in>;
+ clock-names = "pclk", "clk32k_in";
+ #clock-cells = <1>;
+
+ powergates {
+ pd_audio: aud {
+ clocks = <&tegra_car TEGRA210_CLK_APE>,
+ <&tegra_car TEGRA210_CLK_APB2APE>;
+ resets = <&tegra_car 198>;
+ #power-domain-cells = <0>;
+ };
+
+ pd_xusbss: xusba {
+ clocks = <&tegra_car TEGRA210_CLK_XUSB_SS>;
+ resets = <&tegra_car TEGRA210_CLK_XUSB_SS>;
+ #power-domain-cells = <0>;
+ };
+ };
+
+ sdmmc1_3v3: sdmmc1-3v3 {
+ pins = "sdmmc1";
+ power-source = <TEGRA_IO_PAD_VOLTAGE_3V3>;
+ };
+
+ sdmmc1_1v8: sdmmc1-1v8 {
+ pins = "sdmmc1";
+ power-source = <TEGRA_IO_PAD_VOLTAGE_1V8>;
+ };
+
+ nvidia,invert-interrupt;
+ nvidia,suspend-mode = <0>;
+ nvidia,cpu-pwr-good-time = <0>;
+ nvidia,cpu-pwr-off-time = <0>;
+ nvidia,core-pwr-good-time = <4587 3876>;
+ nvidia,core-pwr-off-time = <39065>;
+ nvidia,core-power-req-active-high;
+ nvidia,sys-clock-req-active-high;
+ };
--
2.7.4
mclk is from clk_out_1 which is part of Tegra PMC block and pmc clocks
are moved to Tegra PMC driver with pmc as clock provider and using pmc
clock ids.
New device tree uses clk_out_1 from pmc clock provider.
So, this patch adds fallback to extern1 in case of retrieving mclk fails
to be backward compatible of new device tree with older kernels.
Cc: [email protected]
Signed-off-by: Sowjanya Komatineni <[email protected]>
---
sound/soc/tegra/tegra_asoc_utils.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/sound/soc/tegra/tegra_asoc_utils.c b/sound/soc/tegra/tegra_asoc_utils.c
index 8e3a3740df7c..f7408d5240c0 100644
--- a/sound/soc/tegra/tegra_asoc_utils.c
+++ b/sound/soc/tegra/tegra_asoc_utils.c
@@ -211,8 +211,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)) {
+ dev_err(data->dev, "Can't retrieve clk extern1\n");
+ ret = PTR_ERR(data->clk_cdev1);
+ goto err_put_pll_a_out0;
+ }
+
+ dev_err(data->dev, "Falling back to extern1\n");
}
/*
--
2.7.4
Tegra PMC has clk_out_1, clk_out_2, clk_out_3 with mux and gate
for each of these clocks and 32 kHz blink.
These clocks are moved from clock driver to pmc driver with pmc
as the clock provider for these clocks.
This patch adds #clock-cells property with 1 clock specifier to
the Tegra PMC node in device tree.
Signed-off-by: Sowjanya Komatineni <[email protected]>
---
arch/arm/boot/dts/tegra114.dtsi | 4 +++-
arch/arm/boot/dts/tegra124.dtsi | 4 +++-
arch/arm/boot/dts/tegra20.dtsi | 4 +++-
arch/arm/boot/dts/tegra30.dtsi | 4 +++-
4 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/arch/arm/boot/dts/tegra114.dtsi b/arch/arm/boot/dts/tegra114.dtsi
index 0d7a6327e404..b8f12f24f314 100644
--- a/arch/arm/boot/dts/tegra114.dtsi
+++ b/arch/arm/boot/dts/tegra114.dtsi
@@ -4,6 +4,7 @@
#include <dt-bindings/memory/tegra114-mc.h>
#include <dt-bindings/pinctrl/pinctrl-tegra.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/soc/tegra-pmc.h>
/ {
compatible = "nvidia,tegra114";
@@ -514,11 +515,12 @@
status = "disabled";
};
- pmc@7000e400 {
+ pmc: pmc@7000e400 {
compatible = "nvidia,tegra114-pmc";
reg = <0x7000e400 0x400>;
clocks = <&tegra_car TEGRA114_CLK_PCLK>, <&clk32k_in>;
clock-names = "pclk", "clk32k_in";
+ #clock-cells = <1>;
};
fuse@7000f800 {
diff --git a/arch/arm/boot/dts/tegra124.dtsi b/arch/arm/boot/dts/tegra124.dtsi
index 413bfb981de8..d0802c4ae3bf 100644
--- a/arch/arm/boot/dts/tegra124.dtsi
+++ b/arch/arm/boot/dts/tegra124.dtsi
@@ -6,6 +6,7 @@
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/reset/tegra124-car.h>
#include <dt-bindings/thermal/tegra124-soctherm.h>
+#include <dt-bindings/soc/tegra-pmc.h>
/ {
compatible = "nvidia,tegra124";
@@ -595,11 +596,12 @@
clocks = <&tegra_car TEGRA124_CLK_RTC>;
};
- pmc@7000e400 {
+ pmc: pmc@7000e400 {
compatible = "nvidia,tegra124-pmc";
reg = <0x0 0x7000e400 0x0 0x400>;
clocks = <&tegra_car TEGRA124_CLK_PCLK>, <&clk32k_in>;
clock-names = "pclk", "clk32k_in";
+ #clock-cells = <1>;
};
fuse@7000f800 {
diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
index 9c58e7fcf5c0..85a64747bec6 100644
--- a/arch/arm/boot/dts/tegra20.dtsi
+++ b/arch/arm/boot/dts/tegra20.dtsi
@@ -4,6 +4,7 @@
#include <dt-bindings/memory/tegra20-mc.h>
#include <dt-bindings/pinctrl/pinctrl-tegra.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/soc/tegra-pmc.h>
/ {
compatible = "nvidia,tegra20";
@@ -608,11 +609,12 @@
status = "disabled";
};
- pmc@7000e400 {
+ pmc: pmc@7000e400 {
compatible = "nvidia,tegra20-pmc";
reg = <0x7000e400 0x400>;
clocks = <&tegra_car TEGRA20_CLK_PCLK>, <&clk32k_in>;
clock-names = "pclk", "clk32k_in";
+ #clock-cells = <1>;
};
mc: memory-controller@7000f000 {
diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi
index 55ae050042ce..4d5e9d0001d3 100644
--- a/arch/arm/boot/dts/tegra30.dtsi
+++ b/arch/arm/boot/dts/tegra30.dtsi
@@ -4,6 +4,7 @@
#include <dt-bindings/memory/tegra30-mc.h>
#include <dt-bindings/pinctrl/pinctrl-tegra.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/soc/tegra-pmc.h>
/ {
compatible = "nvidia,tegra30";
@@ -714,11 +715,12 @@
status = "disabled";
};
- pmc@7000e400 {
+ pmc: pmc@7000e400 {
compatible = "nvidia,tegra30-pmc";
reg = <0x7000e400 0x400>;
clocks = <&tegra_car TEGRA30_CLK_PCLK>, <&clk32k_in>;
clock-names = "pclk", "clk32k_in";
+ #clock-cells = <1>;
};
mc: memory-controller@7000f000 {
--
2.7.4
Current ASoC driver uses extern1 as cdev1 clock from Tegra30 onwards
through device tree.
Actual audio mclk is clk_out_1 and to use PLLA for mclk rate control,
need to clk_out_1_mux parent to extern1 and extern1 parent to PLLA_OUT0.
Currently Tegra clock driver init sets the parents and enables both
clk_out_1 and extern1 clocks. But these clocks parent and enables should
be controlled by ASoC driver.
Clock parents can be specified in device tree using assigned-clocks
and assigned-clock-parents.
To enable audio mclk, both clk_out_1 and extern1 clocks need to be
enabled.
This patch configures parents for clk_out_1 and extern1 clocks if device
tree does not specify clock parents inorder to support old device tree
and controls mclk using both clk_out_1 and extern1 clocks.
Signed-off-by: Sowjanya Komatineni <[email protected]>
---
sound/soc/tegra/tegra_asoc_utils.c | 66 ++++++++++++++++++++++++++++++++++++++
sound/soc/tegra/tegra_asoc_utils.h | 1 +
2 files changed, 67 insertions(+)
diff --git a/sound/soc/tegra/tegra_asoc_utils.c b/sound/soc/tegra/tegra_asoc_utils.c
index 536a578e9512..8e3a3740df7c 100644
--- a/sound/soc/tegra/tegra_asoc_utils.c
+++ b/sound/soc/tegra/tegra_asoc_utils.c
@@ -60,6 +60,7 @@ int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,
data->set_mclk = 0;
clk_disable_unprepare(data->clk_cdev1);
+ clk_disable_unprepare(data->clk_extern1);
clk_disable_unprepare(data->clk_pll_a_out0);
clk_disable_unprepare(data->clk_pll_a);
@@ -89,6 +90,14 @@ int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,
return err;
}
+ if (!IS_ERR_OR_NULL(data->clk_extern1)) {
+ err = clk_prepare_enable(data->clk_extern1);
+ if (err) {
+ dev_err(data->dev, "Can't enable extern1: %d\n", err);
+ return err;
+ }
+ }
+
err = clk_prepare_enable(data->clk_cdev1);
if (err) {
dev_err(data->dev, "Can't enable cdev1: %d\n", err);
@@ -109,6 +118,7 @@ int tegra_asoc_utils_set_ac97_rate(struct tegra_asoc_utils_data *data)
int err;
clk_disable_unprepare(data->clk_cdev1);
+ clk_disable_unprepare(data->clk_extern1);
clk_disable_unprepare(data->clk_pll_a_out0);
clk_disable_unprepare(data->clk_pll_a);
@@ -142,6 +152,14 @@ int tegra_asoc_utils_set_ac97_rate(struct tegra_asoc_utils_data *data)
return err;
}
+ if (!IS_ERR_OR_NULL(data->clk_extern1)) {
+ err = clk_prepare_enable(data->clk_extern1);
+ if (err) {
+ dev_err(data->dev, "Can't enable extern1: %d\n", err);
+ return err;
+ }
+ }
+
err = clk_prepare_enable(data->clk_cdev1);
if (err) {
dev_err(data->dev, "Can't enable cdev1: %d\n", err);
@@ -158,6 +176,7 @@ EXPORT_SYMBOL_GPL(tegra_asoc_utils_set_ac97_rate);
int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data,
struct device *dev)
{
+ struct clk *clk_out_1_mux;
int ret;
data->dev = dev;
@@ -196,6 +215,51 @@ int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data,
goto err_put_pll_a_out0;
}
+ /*
+ * If clock parents are not set in DT, configure here to use clk_out_1
+ * as mclk and extern1 as parent for Tegra30 and higher.
+ */
+ if (!of_find_property(dev->of_node, "assigned-clock-parents", NULL) &&
+ data->soc > TEGRA_ASOC_UTILS_SOC_TEGRA20) {
+ data->clk_extern1 = clk_get_sys("clk_out_1", "extern1");
+ if (IS_ERR(data->clk_extern1)) {
+ dev_err(data->dev, "Can't retrieve clk extern1\n");
+ ret = PTR_ERR(data->clk_extern1);
+ goto err_put_cdev1;
+ }
+
+ ret = clk_set_parent(data->clk_extern1, data->clk_pll_a_out0);
+ if (ret < 0) {
+ dev_err(data->dev,
+ "Set parent failed for clk extern1: %d\n",
+ ret);
+ goto err_put_cdev1;
+ }
+
+ clk_out_1_mux = clk_get_sys(NULL, "clk_out_1_mux");
+ if (IS_ERR(clk_out_1_mux)) {
+ dev_err(data->dev, "Can't retrieve clk clk_out_1_mux\n");
+ ret = PTR_ERR(clk_out_1_mux);
+ goto err_put_cdev1;
+ }
+
+ ret = clk_set_parent(clk_out_1_mux, data->clk_extern1);
+ if (ret < 0) {
+ dev_err(data->dev,
+ "Set parent failed for clk_out_1_mux: %d\n",
+ ret);
+ clk_put(clk_out_1_mux);
+ goto err_put_cdev1;
+ }
+
+ data->clk_cdev1 = clk_get_sys(NULL, "clk_out_1");
+ if (IS_ERR(data->clk_cdev1)) {
+ dev_err(data->dev, "Can't retrieve clk clk_out_1\n");
+ ret = PTR_ERR(data->clk_cdev1);
+ goto err_put_cdev1;
+ }
+ }
+
ret = tegra_asoc_utils_set_rate(data, 44100, 256 * 44100);
if (ret)
goto err_put_cdev1;
@@ -215,6 +279,8 @@ EXPORT_SYMBOL_GPL(tegra_asoc_utils_init);
void tegra_asoc_utils_fini(struct tegra_asoc_utils_data *data)
{
+ if (!IS_ERR_OR_NULL(data->clk_extern1))
+ clk_put(data->clk_extern1);
clk_put(data->clk_cdev1);
clk_put(data->clk_pll_a_out0);
clk_put(data->clk_pll_a);
diff --git a/sound/soc/tegra/tegra_asoc_utils.h b/sound/soc/tegra/tegra_asoc_utils.h
index 0c13818dee75..5f2b96478caf 100644
--- a/sound/soc/tegra/tegra_asoc_utils.h
+++ b/sound/soc/tegra/tegra_asoc_utils.h
@@ -25,6 +25,7 @@ struct tegra_asoc_utils_data {
struct clk *clk_pll_a;
struct clk *clk_pll_a_out0;
struct clk *clk_cdev1;
+ struct clk *clk_extern1;
int set_baseclock;
int set_mclk;
};
--
2.7.4
Tegra PMC has blink control to output 32 Khz clock out to Tegra
blink pin. Blink pad DPD state and enable controls are part of
Tegra PMC register space.
Currently Tegra clock driver registers blink control by passing
PMC address and register offset to clk_register_gate which performs
direct PMC access during clk_ops and with this when PMC is in secure
mode, any access from non-secure world does not go through.
This patch adds blink control registration to the Tegra PMC driver
using PMC specific clock gate operations that use tegra_pmc_readl
and tegra_pmc_writel to support both secure mode and non-secure
mode PMC register access.
Signed-off-by: Sowjanya Komatineni <[email protected]>
---
drivers/soc/tegra/pmc.c | 35 +++++++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index b8f6eb0ed8aa..c62ab84cce9c 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -61,12 +61,15 @@
#define PMC_CNTRL_SYSCLK_OE BIT(11) /* system clock enable */
#define PMC_CNTRL_SYSCLK_POLARITY BIT(10) /* sys clk polarity */
#define PMC_CNTRL_PWRREQ_POLARITY BIT(8)
+#define PMC_CNTRL_BLINK_EN 7
#define PMC_CNTRL_MAIN_RST BIT(4)
#define PMC_WAKE_MASK 0x0c
#define PMC_WAKE_LEVEL 0x10
#define PMC_WAKE_STATUS 0x14
#define PMC_SW_WAKE_STATUS 0x18
+#define PMC_DPD_PADS_ORIDE 0x1c
+#define PMC_DPD_PADS_ORIDE_BLINK 20
#define DPD_SAMPLE 0x020
#define DPD_SAMPLE_ENABLE BIT(0)
@@ -79,6 +82,7 @@
#define PWRGATE_STATUS 0x38
+#define PMC_BLINK_TIMER 0x40
#define PMC_IMPL_E_33V_PWR 0x40
#define PMC_PWR_DET 0x48
@@ -339,6 +343,7 @@ struct tegra_pmc_soc {
const struct pmc_clk_init_data *pmc_clks_data;
unsigned int num_pmc_clks;
+ bool has_blink_output;
};
static const char * const tegra186_reset_sources[] = {
@@ -2388,6 +2393,9 @@ static void tegra_pmc_clock_register(struct tegra_pmc *pmc,
/* each pmc clock output has a mux and a gate */
num_clks = pmc->soc->num_pmc_clks * 2;
+ if (pmc->soc->has_blink_output)
+ num_clks += 1;
+
if (!num_clks)
return;
@@ -2442,6 +2450,26 @@ static void tegra_pmc_clock_register(struct tegra_pmc *pmc,
clk_register_clkdev(clk, data->dev_name, data->gate_name);
}
+ if (pmc->soc->has_blink_output) {
+ tegra_pmc_writel(pmc, 0x0, PMC_BLINK_TIMER);
+ clk = tegra_pmc_clk_gate_register("blink_override",
+ "clk_32k", 0,
+ PMC_DPD_PADS_ORIDE,
+ PMC_DPD_PADS_ORIDE_BLINK);
+ if (IS_ERR(clk))
+ goto free_clks;
+
+ clk = tegra_pmc_clk_gate_register("blink",
+ "blink_override", 0,
+ PMC_CNTRL,
+ PMC_CNTRL_BLINK_EN);
+ if (IS_ERR(clk))
+ goto free_clks;
+
+ clk_data->clks[TEGRA_PMC_CLK_BLINK] = clk;
+ clk_register_clkdev(clk, "blink", NULL);
+ }
+
of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);
return;
@@ -2715,6 +2743,7 @@ static const struct tegra_pmc_soc tegra20_pmc_soc = {
.num_reset_levels = 0,
.pmc_clks_data = NULL,
.num_pmc_clks = 0,
+ .has_blink_output = true,
};
static const char * const tegra30_powergates[] = {
@@ -2764,6 +2793,7 @@ static const struct tegra_pmc_soc tegra30_pmc_soc = {
.num_reset_levels = 0,
.pmc_clks_data = tegra_pmc_clks_data,
.num_pmc_clks = ARRAY_SIZE(tegra_pmc_clks_data),
+ .has_blink_output = true,
};
static const char * const tegra114_powergates[] = {
@@ -2817,6 +2847,7 @@ static const struct tegra_pmc_soc tegra114_pmc_soc = {
.num_reset_levels = 0,
.pmc_clks_data = tegra_pmc_clks_data,
.num_pmc_clks = ARRAY_SIZE(tegra_pmc_clks_data),
+ .has_blink_output = true,
};
static const char * const tegra124_powergates[] = {
@@ -2930,6 +2961,7 @@ static const struct tegra_pmc_soc tegra124_pmc_soc = {
.num_reset_levels = 0,
.pmc_clks_data = tegra_pmc_clks_data,
.num_pmc_clks = ARRAY_SIZE(tegra_pmc_clks_data),
+ .has_blink_output = true,
};
static const char * const tegra210_powergates[] = {
@@ -3046,6 +3078,7 @@ static const struct tegra_pmc_soc tegra210_pmc_soc = {
.wake_events = tegra210_wake_events,
.pmc_clks_data = tegra_pmc_clks_data,
.num_pmc_clks = ARRAY_SIZE(tegra_pmc_clks_data),
+ .has_blink_output = true,
};
#define TEGRA186_IO_PAD_TABLE(_pad) \
@@ -3177,6 +3210,7 @@ static const struct tegra_pmc_soc tegra186_pmc_soc = {
.wake_events = tegra186_wake_events,
.pmc_clks_data = NULL,
.num_pmc_clks = 0,
+ .has_blink_output = false,
};
static const struct tegra_io_pad_soc tegra194_io_pads[] = {
@@ -3296,6 +3330,7 @@ static const struct tegra_pmc_soc tegra194_pmc_soc = {
.wake_events = tegra194_wake_events,
.pmc_clks_data = NULL,
.num_pmc_clks = 0,
+ .has_blink_output = false,
};
static const struct of_device_id tegra_pmc_match[] = {
--
2.7.4
Current Tegra clock driver registers PMC clocks clk_out_1, clk_out_2,
clk_out_3 and blink output in tegra_pmc_init() which does direct Tegra
PMC access during clk_ops and these PMC register read and write access
will not happen when PMC is in secure mode.
Any direct PMC register access from non-secure world will not go
through and all the PMC clocks and blink control are done in Tegra PMC
driver with PMC as clock provider.
This patch removes tegra_pmc_clk_init along with corresponding clk ids
from Tegra clock driver.
Signed-off-by: Sowjanya Komatineni <[email protected]>
---
drivers/clk/tegra/Makefile | 1 -
drivers/clk/tegra/clk-id.h | 7 ---
drivers/clk/tegra/clk-tegra-pmc.c | 122 --------------------------------------
drivers/clk/tegra/clk-tegra114.c | 11 ----
drivers/clk/tegra/clk-tegra124.c | 27 +++------
drivers/clk/tegra/clk-tegra20.c | 4 --
drivers/clk/tegra/clk-tegra210.c | 11 ----
drivers/clk/tegra/clk-tegra30.c | 12 ----
drivers/clk/tegra/clk.h | 1 -
9 files changed, 7 insertions(+), 189 deletions(-)
delete mode 100644 drivers/clk/tegra/clk-tegra-pmc.c
diff --git a/drivers/clk/tegra/Makefile b/drivers/clk/tegra/Makefile
index df966ca06788..1f7c30f87ece 100644
--- a/drivers/clk/tegra/Makefile
+++ b/drivers/clk/tegra/Makefile
@@ -12,7 +12,6 @@ obj-y += clk-sdmmc-mux.o
obj-y += clk-super.o
obj-y += clk-tegra-audio.o
obj-y += clk-tegra-periph.o
-obj-y += clk-tegra-pmc.o
obj-y += clk-tegra-fixed.o
obj-y += clk-tegra-super-gen4.o
obj-$(CONFIG_TEGRA_CLK_EMC) += clk-emc.o
diff --git a/drivers/clk/tegra/clk-id.h b/drivers/clk/tegra/clk-id.h
index c4faebd32760..5913357a8000 100644
--- a/drivers/clk/tegra/clk-id.h
+++ b/drivers/clk/tegra/clk-id.h
@@ -32,7 +32,6 @@ enum clk_id {
tegra_clk_audio4,
tegra_clk_audio4_2x,
tegra_clk_audio4_mux,
- tegra_clk_blink,
tegra_clk_bsea,
tegra_clk_bsev,
tegra_clk_cclk_g,
@@ -46,12 +45,6 @@ enum clk_id {
tegra_clk_clk_m,
tegra_clk_clk_m_div2,
tegra_clk_clk_m_div4,
- tegra_clk_clk_out_1,
- tegra_clk_clk_out_1_mux,
- tegra_clk_clk_out_2,
- tegra_clk_clk_out_2_mux,
- tegra_clk_clk_out_3,
- tegra_clk_clk_out_3_mux,
tegra_clk_cml0,
tegra_clk_cml1,
tegra_clk_csi,
diff --git a/drivers/clk/tegra/clk-tegra-pmc.c b/drivers/clk/tegra/clk-tegra-pmc.c
deleted file mode 100644
index bec3e008335f..000000000000
--- a/drivers/clk/tegra/clk-tegra-pmc.c
+++ /dev/null
@@ -1,122 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (c) 2012, 2013, NVIDIA CORPORATION. All rights reserved.
- */
-
-#include <linux/io.h>
-#include <linux/clk-provider.h>
-#include <linux/clkdev.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/delay.h>
-#include <linux/export.h>
-#include <linux/clk/tegra.h>
-
-#include "clk.h"
-#include "clk-id.h"
-
-#define PMC_CLK_OUT_CNTRL 0x1a8
-#define PMC_DPD_PADS_ORIDE 0x1c
-#define PMC_DPD_PADS_ORIDE_BLINK_ENB 20
-#define PMC_CTRL 0
-#define PMC_CTRL_BLINK_ENB 7
-#define PMC_BLINK_TIMER 0x40
-
-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;
-};
-
-#define PMC_CLK(_num, _mux_shift, _gate_shift)\
- {\
- .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_clk_clk_out_ ##_num ##_mux,\
- .gate_id = tegra_clk_clk_out_ ##_num,\
- .dev_name = "extern" #_num,\
- .mux_shift = _mux_shift,\
- .gate_shift = _gate_shift,\
- }
-
-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",
-};
-
-static struct pmc_clk_init_data pmc_clks[] = {
- PMC_CLK(1, 6, 2),
- PMC_CLK(2, 14, 10),
- PMC_CLK(3, 22, 18),
-};
-
-void __init tegra_pmc_clk_init(void __iomem *pmc_base,
- struct tegra_clk *tegra_clks)
-{
- struct clk *clk;
- struct clk **dt_clk;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(pmc_clks); i++) {
- struct pmc_clk_init_data *data;
-
- data = pmc_clks + i;
-
- dt_clk = tegra_lookup_dt_id(data->mux_id, tegra_clks);
- if (!dt_clk)
- continue;
-
- clk = clk_register_mux(NULL, data->mux_name, data->parents,
- data->num_parents,
- CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT,
- pmc_base + PMC_CLK_OUT_CNTRL, data->mux_shift,
- 3, 0, &clk_out_lock);
- *dt_clk = clk;
-
-
- dt_clk = tegra_lookup_dt_id(data->gate_id, tegra_clks);
- if (!dt_clk)
- continue;
-
- clk = clk_register_gate(NULL, data->gate_name, data->mux_name,
- CLK_SET_RATE_PARENT,
- pmc_base + PMC_CLK_OUT_CNTRL,
- data->gate_shift, 0, &clk_out_lock);
- *dt_clk = clk;
- clk_register_clkdev(clk, data->dev_name, data->gate_name);
- }
-
- /* blink */
- writel_relaxed(0, pmc_base + PMC_BLINK_TIMER);
- clk = clk_register_gate(NULL, "blink_override", "clk_32k", 0,
- pmc_base + PMC_DPD_PADS_ORIDE,
- PMC_DPD_PADS_ORIDE_BLINK_ENB, 0, NULL);
-
- dt_clk = tegra_lookup_dt_id(tegra_clk_blink, tegra_clks);
- if (!dt_clk)
- return;
-
- clk = clk_register_gate(NULL, "blink", "blink_override", 0,
- pmc_base + PMC_CTRL,
- PMC_CTRL_BLINK_ENB, 0, NULL);
- clk_register_clkdev(clk, "blink", NULL);
- *dt_clk = clk;
-}
-
diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c
index 4efcaaf51b3a..36ba1eb3dbe0 100644
--- a/drivers/clk/tegra/clk-tegra114.c
+++ b/drivers/clk/tegra/clk-tegra114.c
@@ -778,10 +778,6 @@ static struct tegra_clk tegra114_clks[tegra_clk_max] __initdata = {
[tegra_clk_audio3] = { .dt_id = TEGRA114_CLK_AUDIO3, .present = true },
[tegra_clk_audio4] = { .dt_id = TEGRA114_CLK_AUDIO4, .present = true },
[tegra_clk_spdif] = { .dt_id = TEGRA114_CLK_SPDIF, .present = true },
- [tegra_clk_clk_out_1] = { .dt_id = TEGRA114_CLK_CLK_OUT_1, .present = true },
- [tegra_clk_clk_out_2] = { .dt_id = TEGRA114_CLK_CLK_OUT_2, .present = true },
- [tegra_clk_clk_out_3] = { .dt_id = TEGRA114_CLK_CLK_OUT_3, .present = true },
- [tegra_clk_blink] = { .dt_id = TEGRA114_CLK_BLINK, .present = true },
[tegra_clk_xusb_host_src] = { .dt_id = TEGRA114_CLK_XUSB_HOST_SRC, .present = true },
[tegra_clk_xusb_falcon_src] = { .dt_id = TEGRA114_CLK_XUSB_FALCON_SRC, .present = true },
[tegra_clk_xusb_fs_src] = { .dt_id = TEGRA114_CLK_XUSB_FS_SRC, .present = true },
@@ -803,9 +799,6 @@ static struct tegra_clk tegra114_clks[tegra_clk_max] __initdata = {
[tegra_clk_audio3_mux] = { .dt_id = TEGRA114_CLK_AUDIO3_MUX, .present = true },
[tegra_clk_audio4_mux] = { .dt_id = TEGRA114_CLK_AUDIO4_MUX, .present = true },
[tegra_clk_spdif_mux] = { .dt_id = TEGRA114_CLK_SPDIF_MUX, .present = true },
- [tegra_clk_clk_out_1_mux] = { .dt_id = TEGRA114_CLK_CLK_OUT_1_MUX, .present = true },
- [tegra_clk_clk_out_2_mux] = { .dt_id = TEGRA114_CLK_CLK_OUT_2_MUX, .present = true },
- [tegra_clk_clk_out_3_mux] = { .dt_id = TEGRA114_CLK_CLK_OUT_3_MUX, .present = true },
[tegra_clk_dsia_mux] = { .dt_id = TEGRA114_CLK_DSIA_MUX, .present = true },
[tegra_clk_dsib_mux] = { .dt_id = TEGRA114_CLK_DSIB_MUX, .present = true },
[tegra_clk_cec] = { .dt_id = TEGRA114_CLK_CEC, .present = true },
@@ -866,7 +859,6 @@ static struct tegra_devclk devclks[] __initdata = {
{ .con_id = "extern1", .dev_id = "clk_out_1", .dt_id = TEGRA114_CLK_EXTERN1 },
{ .con_id = "extern2", .dev_id = "clk_out_2", .dt_id = TEGRA114_CLK_EXTERN2 },
{ .con_id = "extern3", .dev_id = "clk_out_3", .dt_id = TEGRA114_CLK_EXTERN3 },
- { .con_id = "blink", .dt_id = TEGRA114_CLK_BLINK },
{ .con_id = "cclk_g", .dt_id = TEGRA114_CLK_CCLK_G },
{ .con_id = "cclk_lp", .dt_id = TEGRA114_CLK_CCLK_LP },
{ .con_id = "sclk", .dt_id = TEGRA114_CLK_SCLK },
@@ -1156,8 +1148,6 @@ static struct tegra_clk_init_table init_table[] __initdata = {
{ TEGRA114_CLK_PLL_A, TEGRA114_CLK_CLK_MAX, 564480000, 1 },
{ TEGRA114_CLK_PLL_A_OUT0, TEGRA114_CLK_CLK_MAX, 11289600, 1 },
{ TEGRA114_CLK_EXTERN1, TEGRA114_CLK_PLL_A_OUT0, 0, 1 },
- { TEGRA114_CLK_CLK_OUT_1_MUX, TEGRA114_CLK_EXTERN1, 0, 1 },
- { TEGRA114_CLK_CLK_OUT_1, TEGRA114_CLK_CLK_MAX, 0, 1 },
{ TEGRA114_CLK_I2S0, TEGRA114_CLK_PLL_A_OUT0, 11289600, 0 },
{ TEGRA114_CLK_I2S1, TEGRA114_CLK_PLL_A_OUT0, 11289600, 0 },
{ TEGRA114_CLK_I2S2, TEGRA114_CLK_PLL_A_OUT0, 11289600, 0 },
@@ -1359,7 +1349,6 @@ static void __init tegra114_clock_init(struct device_node *np)
tegra_audio_clk_init(clk_base, pmc_base, tegra114_clks,
tegra114_audio_plls,
ARRAY_SIZE(tegra114_audio_plls), 24000000);
- tegra_pmc_clk_init(pmc_base, tegra114_clks);
tegra_super_clk_gen4_init(clk_base, pmc_base, tegra114_clks,
&pll_x_params);
diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c
index b3110d5b5a6c..24532d70e469 100644
--- a/drivers/clk/tegra/clk-tegra124.c
+++ b/drivers/clk/tegra/clk-tegra124.c
@@ -902,10 +902,6 @@ static struct tegra_clk tegra124_clks[tegra_clk_max] __initdata = {
[tegra_clk_audio3] = { .dt_id = TEGRA124_CLK_AUDIO3, .present = true },
[tegra_clk_audio4] = { .dt_id = TEGRA124_CLK_AUDIO4, .present = true },
[tegra_clk_spdif] = { .dt_id = TEGRA124_CLK_SPDIF, .present = true },
- [tegra_clk_clk_out_1] = { .dt_id = TEGRA124_CLK_CLK_OUT_1, .present = true },
- [tegra_clk_clk_out_2] = { .dt_id = TEGRA124_CLK_CLK_OUT_2, .present = true },
- [tegra_clk_clk_out_3] = { .dt_id = TEGRA124_CLK_CLK_OUT_3, .present = true },
- [tegra_clk_blink] = { .dt_id = TEGRA124_CLK_BLINK, .present = true },
[tegra_clk_xusb_host_src] = { .dt_id = TEGRA124_CLK_XUSB_HOST_SRC, .present = true },
[tegra_clk_xusb_falcon_src] = { .dt_id = TEGRA124_CLK_XUSB_FALCON_SRC, .present = true },
[tegra_clk_xusb_fs_src] = { .dt_id = TEGRA124_CLK_XUSB_FS_SRC, .present = true },
@@ -931,9 +927,6 @@ static struct tegra_clk tegra124_clks[tegra_clk_max] __initdata = {
[tegra_clk_audio3_mux] = { .dt_id = TEGRA124_CLK_AUDIO3_MUX, .present = true },
[tegra_clk_audio4_mux] = { .dt_id = TEGRA124_CLK_AUDIO4_MUX, .present = true },
[tegra_clk_spdif_mux] = { .dt_id = TEGRA124_CLK_SPDIF_MUX, .present = true },
- [tegra_clk_clk_out_1_mux] = { .dt_id = TEGRA124_CLK_CLK_OUT_1_MUX, .present = true },
- [tegra_clk_clk_out_2_mux] = { .dt_id = TEGRA124_CLK_CLK_OUT_2_MUX, .present = true },
- [tegra_clk_clk_out_3_mux] = { .dt_id = TEGRA124_CLK_CLK_OUT_3_MUX, .present = true },
[tegra_clk_cec] = { .dt_id = TEGRA124_CLK_CEC, .present = true },
};
@@ -991,7 +984,6 @@ static struct tegra_devclk devclks[] __initdata = {
{ .con_id = "extern1", .dev_id = "clk_out_1", .dt_id = TEGRA124_CLK_EXTERN1 },
{ .con_id = "extern2", .dev_id = "clk_out_2", .dt_id = TEGRA124_CLK_EXTERN2 },
{ .con_id = "extern3", .dev_id = "clk_out_3", .dt_id = TEGRA124_CLK_EXTERN3 },
- { .con_id = "blink", .dt_id = TEGRA124_CLK_BLINK },
{ .con_id = "cclk_g", .dt_id = TEGRA124_CLK_CCLK_G },
{ .con_id = "cclk_lp", .dt_id = TEGRA124_CLK_CCLK_LP },
{ .con_id = "sclk", .dt_id = TEGRA124_CLK_SCLK },
@@ -1301,8 +1293,6 @@ static struct tegra_clk_init_table common_init_table[] __initdata = {
{ TEGRA124_CLK_PLL_A, TEGRA124_CLK_CLK_MAX, 564480000, 1 },
{ TEGRA124_CLK_PLL_A_OUT0, TEGRA124_CLK_CLK_MAX, 11289600, 1 },
{ TEGRA124_CLK_EXTERN1, TEGRA124_CLK_PLL_A_OUT0, 0, 1 },
- { TEGRA124_CLK_CLK_OUT_1_MUX, TEGRA124_CLK_EXTERN1, 0, 1 },
- { TEGRA124_CLK_CLK_OUT_1, TEGRA124_CLK_CLK_MAX, 0, 1 },
{ TEGRA124_CLK_I2S0, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0 },
{ TEGRA124_CLK_I2S1, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0 },
{ TEGRA124_CLK_I2S2, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0 },
@@ -1457,11 +1447,9 @@ static void __init tegra132_clock_apply_init_table(void)
* tegra124_132_clock_init_pre - clock initialization preamble for T124/T132
* @np: struct device_node * of the DT node for the SoC CAR IP block
*
- * Register most of the clocks controlled by the CAR IP block, along
- * with a few clocks controlled by the PMC IP block. Everything in
- * this function should be common to Tegra124 and Tegra132. XXX The
- * PMC clock initialization should probably be moved to PMC-specific
- * driver code. No return value.
+ * Register most of the clocks controlled by the CAR IP block.
+ * Everything in this function should be common to Tegra124 and Tegra132.
+ * No return value.
*/
static void __init tegra124_132_clock_init_pre(struct device_node *np)
{
@@ -1504,7 +1492,6 @@ static void __init tegra124_132_clock_init_pre(struct device_node *np)
tegra_audio_clk_init(clk_base, pmc_base, tegra124_clks,
tegra124_audio_plls,
ARRAY_SIZE(tegra124_audio_plls), 24576000);
- tegra_pmc_clk_init(pmc_base, tegra124_clks);
/* For Tegra124 & Tegra132, PLLD is the only source for DSIA & DSIB */
plld_base = readl(clk_base + PLLD_BASE);
@@ -1516,11 +1503,11 @@ static void __init tegra124_132_clock_init_pre(struct device_node *np)
* tegra124_132_clock_init_post - clock initialization postamble for T124/T132
* @np: struct device_node * of the DT node for the SoC CAR IP block
*
- * Register most of the along with a few clocks controlled by the PMC
- * IP block. Everything in this function should be common to Tegra124
+ * Register most of the clocks controlled by the CAR IP block.
+ * Everything in this function should be common to Tegra124
* and Tegra132. This function must be called after
- * tegra124_132_clock_init_pre(), otherwise clk_base and pmc_base will
- * not be set. No return value.
+ * tegra124_132_clock_init_pre(), otherwise clk_base will not be set.
+ * No return value.
*/
static void __init tegra124_132_clock_init_post(struct device_node *np)
{
diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c
index 4d8222f5c638..fe536f1d770d 100644
--- a/drivers/clk/tegra/clk-tegra20.c
+++ b/drivers/clk/tegra/clk-tegra20.c
@@ -458,7 +458,6 @@ static struct tegra_devclk devclks[] __initdata = {
{ .con_id = "cdev1", .dt_id = TEGRA20_CLK_CDEV1 },
{ .con_id = "cdev2", .dt_id = TEGRA20_CLK_CDEV2 },
{ .con_id = "clk_32k", .dt_id = TEGRA20_CLK_CLK_32K },
- { .con_id = "blink", .dt_id = TEGRA20_CLK_BLINK },
{ .con_id = "clk_m", .dt_id = TEGRA20_CLK_CLK_M },
{ .con_id = "pll_ref", .dt_id = TEGRA20_CLK_PLL_REF },
{ .dev_id = "tegra20-i2s.0", .dt_id = TEGRA20_CLK_I2S1 },
@@ -537,7 +536,6 @@ static struct tegra_clk tegra20_clks[tegra_clk_max] __initdata = {
[tegra_clk_csi] = { .dt_id = TEGRA20_CLK_CSI, .present = true },
[tegra_clk_isp] = { .dt_id = TEGRA20_CLK_ISP, .present = true },
[tegra_clk_clk_32k] = { .dt_id = TEGRA20_CLK_CLK_32K, .present = true },
- [tegra_clk_blink] = { .dt_id = TEGRA20_CLK_BLINK, .present = true },
[tegra_clk_hclk] = { .dt_id = TEGRA20_CLK_HCLK, .present = true },
[tegra_clk_pclk] = { .dt_id = TEGRA20_CLK_PCLK, .present = true },
[tegra_clk_pll_p_out1] = { .dt_id = TEGRA20_CLK_PLL_P_OUT1, .present = true },
@@ -1034,7 +1032,6 @@ static struct tegra_clk_init_table init_table[] __initdata = {
{ TEGRA20_CLK_PLL_A, TEGRA20_CLK_CLK_MAX, 56448000, 1 },
{ TEGRA20_CLK_PLL_A_OUT0, TEGRA20_CLK_CLK_MAX, 11289600, 1 },
{ TEGRA20_CLK_CDEV1, TEGRA20_CLK_CLK_MAX, 0, 1 },
- { TEGRA20_CLK_BLINK, TEGRA20_CLK_CLK_MAX, 32768, 1 },
{ TEGRA20_CLK_I2S1, TEGRA20_CLK_PLL_A_OUT0, 11289600, 0 },
{ TEGRA20_CLK_I2S2, TEGRA20_CLK_PLL_A_OUT0, 11289600, 0 },
{ TEGRA20_CLK_SDMMC1, TEGRA20_CLK_PLL_P, 48000000, 0 },
@@ -1148,7 +1145,6 @@ static void __init tegra20_clock_init(struct device_node *np)
tegra_super_clk_gen4_init(clk_base, pmc_base, tegra20_clks, NULL);
tegra20_periph_clk_init();
tegra20_audio_clk_init();
- tegra_pmc_clk_init(pmc_base, tegra20_clks);
tegra_init_dup_clks(tegra_clk_duplicates, clks, TEGRA20_CLK_CLK_MAX);
diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c
index 762cd186f714..af5119481d54 100644
--- a/drivers/clk/tegra/clk-tegra210.c
+++ b/drivers/clk/tegra/clk-tegra210.c
@@ -2417,10 +2417,6 @@ static struct tegra_clk tegra210_clks[tegra_clk_max] __initdata = {
[tegra_clk_audio3] = { .dt_id = TEGRA210_CLK_AUDIO3, .present = true },
[tegra_clk_audio4] = { .dt_id = TEGRA210_CLK_AUDIO4, .present = true },
[tegra_clk_spdif] = { .dt_id = TEGRA210_CLK_SPDIF, .present = true },
- [tegra_clk_clk_out_1] = { .dt_id = TEGRA210_CLK_CLK_OUT_1, .present = true },
- [tegra_clk_clk_out_2] = { .dt_id = TEGRA210_CLK_CLK_OUT_2, .present = true },
- [tegra_clk_clk_out_3] = { .dt_id = TEGRA210_CLK_CLK_OUT_3, .present = true },
- [tegra_clk_blink] = { .dt_id = TEGRA210_CLK_BLINK, .present = true },
[tegra_clk_xusb_gate] = { .dt_id = TEGRA210_CLK_XUSB_GATE, .present = true },
[tegra_clk_xusb_host_src_8] = { .dt_id = TEGRA210_CLK_XUSB_HOST_SRC, .present = true },
[tegra_clk_xusb_falcon_src_8] = { .dt_id = TEGRA210_CLK_XUSB_FALCON_SRC, .present = true },
@@ -2452,9 +2448,6 @@ static struct tegra_clk tegra210_clks[tegra_clk_max] __initdata = {
[tegra_clk_audio3_mux] = { .dt_id = TEGRA210_CLK_AUDIO3_MUX, .present = true },
[tegra_clk_audio4_mux] = { .dt_id = TEGRA210_CLK_AUDIO4_MUX, .present = true },
[tegra_clk_spdif_mux] = { .dt_id = TEGRA210_CLK_SPDIF_MUX, .present = true },
- [tegra_clk_clk_out_1_mux] = { .dt_id = TEGRA210_CLK_CLK_OUT_1_MUX, .present = true },
- [tegra_clk_clk_out_2_mux] = { .dt_id = TEGRA210_CLK_CLK_OUT_2_MUX, .present = true },
- [tegra_clk_clk_out_3_mux] = { .dt_id = TEGRA210_CLK_CLK_OUT_3_MUX, .present = true },
[tegra_clk_maud] = { .dt_id = TEGRA210_CLK_MAUD, .present = true },
[tegra_clk_mipibif] = { .dt_id = TEGRA210_CLK_MIPIBIF, .present = true },
[tegra_clk_qspi] = { .dt_id = TEGRA210_CLK_QSPI, .present = true },
@@ -2543,7 +2536,6 @@ static struct tegra_devclk devclks[] __initdata = {
{ .con_id = "extern1", .dev_id = "clk_out_1", .dt_id = TEGRA210_CLK_EXTERN1 },
{ .con_id = "extern2", .dev_id = "clk_out_2", .dt_id = TEGRA210_CLK_EXTERN2 },
{ .con_id = "extern3", .dev_id = "clk_out_3", .dt_id = TEGRA210_CLK_EXTERN3 },
- { .con_id = "blink", .dt_id = TEGRA210_CLK_BLINK },
{ .con_id = "cclk_g", .dt_id = TEGRA210_CLK_CCLK_G },
{ .con_id = "cclk_lp", .dt_id = TEGRA210_CLK_CCLK_LP },
{ .con_id = "sclk", .dt_id = TEGRA210_CLK_SCLK },
@@ -3451,8 +3443,6 @@ static struct tegra_clk_init_table init_table[] __initdata = {
{ TEGRA210_CLK_PLL_A, TEGRA210_CLK_CLK_MAX, 564480000, 1 },
{ TEGRA210_CLK_PLL_A_OUT0, TEGRA210_CLK_CLK_MAX, 11289600, 1 },
{ TEGRA210_CLK_EXTERN1, TEGRA210_CLK_PLL_A_OUT0, 0, 1 },
- { TEGRA210_CLK_CLK_OUT_1_MUX, TEGRA210_CLK_EXTERN1, 0, 1 },
- { TEGRA210_CLK_CLK_OUT_1, TEGRA210_CLK_CLK_MAX, 0, 1 },
{ TEGRA210_CLK_I2S0, TEGRA210_CLK_PLL_A_OUT0, 11289600, 0 },
{ TEGRA210_CLK_I2S1, TEGRA210_CLK_PLL_A_OUT0, 11289600, 0 },
{ TEGRA210_CLK_I2S2, TEGRA210_CLK_PLL_A_OUT0, 11289600, 0 },
@@ -3693,7 +3683,6 @@ static void __init tegra210_clock_init(struct device_node *np)
tegra_audio_clk_init(clk_base, pmc_base, tegra210_clks,
tegra210_audio_plls,
ARRAY_SIZE(tegra210_audio_plls), 24576000);
- tegra_pmc_clk_init(pmc_base, tegra210_clks);
/* For Tegra210, PLLD is the only source for DSIA & DSIB */
value = readl(clk_base + PLLD_BASE);
diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c
index c8bc18e4d7e5..24599ed2e6ff 100644
--- a/drivers/clk/tegra/clk-tegra30.c
+++ b/drivers/clk/tegra/clk-tegra30.c
@@ -572,7 +572,6 @@ static struct tegra_devclk devclks[] __initdata = {
{ .con_id = "extern1", .dev_id = "clk_out_1", .dt_id = TEGRA30_CLK_EXTERN1 },
{ .con_id = "extern2", .dev_id = "clk_out_2", .dt_id = TEGRA30_CLK_EXTERN2 },
{ .con_id = "extern3", .dev_id = "clk_out_3", .dt_id = TEGRA30_CLK_EXTERN3 },
- { .con_id = "blink", .dt_id = TEGRA30_CLK_BLINK },
{ .con_id = "cclk_g", .dt_id = TEGRA30_CLK_CCLK_G },
{ .con_id = "cclk_lp", .dt_id = TEGRA30_CLK_CCLK_LP },
{ .con_id = "sclk", .dt_id = TEGRA30_CLK_SCLK },
@@ -711,13 +710,6 @@ static struct tegra_clk tegra30_clks[tegra_clk_max] __initdata = {
[tegra_clk_audio3_2x] = { .dt_id = TEGRA30_CLK_AUDIO3_2X, .present = true },
[tegra_clk_audio4_2x] = { .dt_id = TEGRA30_CLK_AUDIO4_2X, .present = true },
[tegra_clk_spdif_2x] = { .dt_id = TEGRA30_CLK_SPDIF_2X, .present = true },
- [tegra_clk_clk_out_1] = { .dt_id = TEGRA30_CLK_CLK_OUT_1, .present = true },
- [tegra_clk_clk_out_2] = { .dt_id = TEGRA30_CLK_CLK_OUT_2, .present = true },
- [tegra_clk_clk_out_3] = { .dt_id = TEGRA30_CLK_CLK_OUT_3, .present = true },
- [tegra_clk_blink] = { .dt_id = TEGRA30_CLK_BLINK, .present = true },
- [tegra_clk_clk_out_1_mux] = { .dt_id = TEGRA30_CLK_CLK_OUT_1_MUX, .present = true },
- [tegra_clk_clk_out_2_mux] = { .dt_id = TEGRA30_CLK_CLK_OUT_2_MUX, .present = true },
- [tegra_clk_clk_out_3_mux] = { .dt_id = TEGRA30_CLK_CLK_OUT_3_MUX, .present = true },
[tegra_clk_hclk] = { .dt_id = TEGRA30_CLK_HCLK, .present = true },
[tegra_clk_pclk] = { .dt_id = TEGRA30_CLK_PCLK, .present = true },
[tegra_clk_i2s0] = { .dt_id = TEGRA30_CLK_I2S0, .present = true },
@@ -1230,9 +1222,6 @@ static struct tegra_clk_init_table init_table[] __initdata = {
{ TEGRA30_CLK_PLL_A, TEGRA30_CLK_CLK_MAX, 564480000, 1 },
{ TEGRA30_CLK_PLL_A_OUT0, TEGRA30_CLK_CLK_MAX, 11289600, 1 },
{ TEGRA30_CLK_EXTERN1, TEGRA30_CLK_PLL_A_OUT0, 0, 1 },
- { TEGRA30_CLK_CLK_OUT_1_MUX, TEGRA30_CLK_EXTERN1, 0, 0 },
- { TEGRA30_CLK_CLK_OUT_1, TEGRA30_CLK_CLK_MAX, 0, 1 },
- { TEGRA30_CLK_BLINK, TEGRA30_CLK_CLK_MAX, 0, 1 },
{ TEGRA30_CLK_I2S0, TEGRA30_CLK_PLL_A_OUT0, 11289600, 0 },
{ TEGRA30_CLK_I2S1, TEGRA30_CLK_PLL_A_OUT0, 11289600, 0 },
{ TEGRA30_CLK_I2S2, TEGRA30_CLK_PLL_A_OUT0, 11289600, 0 },
@@ -1364,7 +1353,6 @@ static void __init tegra30_clock_init(struct device_node *np)
tegra_audio_clk_init(clk_base, pmc_base, tegra30_clks,
tegra30_audio_plls,
ARRAY_SIZE(tegra30_audio_plls), 24000000);
- tegra_pmc_clk_init(pmc_base, tegra30_clks);
tegra_init_dup_clks(tegra_clk_duplicates, clks, TEGRA30_CLK_CLK_MAX);
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index 416a6b09f6a3..2c9a68302e02 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -854,7 +854,6 @@ void tegra_periph_clk_init(void __iomem *clk_base, void __iomem *pmc_base,
struct tegra_clk *tegra_clks,
struct tegra_clk_pll_params *pll_params);
-void tegra_pmc_clk_init(void __iomem *pmc_base, struct tegra_clk *tegra_clks);
void tegra_fixed_clk_init(struct tegra_clk *tegra_clks);
int tegra_osc_clk_init(void __iomem *clk_base, struct tegra_clk *clks,
unsigned long *input_freqs, unsigned int num,
--
2.7.4
Current clock driver enables cdev1 on Tegra20 and extern1 on Tegra30
and above as a part of clocks init and there is no need to have this
clock enabled during the boot.
extern1 is used as parent for clk_out_1 and clk_out_1 is dedicated
for audio mclk on Tegra30 and above Tegra platforms and these clocks
are taken care by ASoC driver.
So, this patch removes parenting and enabling extern1 from clock init
of Tegra30 and above and removes enabling cdev1 from Tegra20 clock init.
Signed-off-by: Sowjanya Komatineni <[email protected]>
---
drivers/clk/tegra/clk-tegra114.c | 1 -
drivers/clk/tegra/clk-tegra124.c | 1 -
drivers/clk/tegra/clk-tegra20.c | 1 -
drivers/clk/tegra/clk-tegra210.c | 1 -
drivers/clk/tegra/clk-tegra30.c | 1 -
5 files changed, 5 deletions(-)
diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c
index 36ba1eb3dbe0..3c29896b19a7 100644
--- a/drivers/clk/tegra/clk-tegra114.c
+++ b/drivers/clk/tegra/clk-tegra114.c
@@ -1147,7 +1147,6 @@ static struct tegra_clk_init_table init_table[] __initdata = {
{ TEGRA114_CLK_UARTD, TEGRA114_CLK_PLL_P, 408000000, 0 },
{ TEGRA114_CLK_PLL_A, TEGRA114_CLK_CLK_MAX, 564480000, 1 },
{ TEGRA114_CLK_PLL_A_OUT0, TEGRA114_CLK_CLK_MAX, 11289600, 1 },
- { TEGRA114_CLK_EXTERN1, TEGRA114_CLK_PLL_A_OUT0, 0, 1 },
{ TEGRA114_CLK_I2S0, TEGRA114_CLK_PLL_A_OUT0, 11289600, 0 },
{ TEGRA114_CLK_I2S1, TEGRA114_CLK_PLL_A_OUT0, 11289600, 0 },
{ TEGRA114_CLK_I2S2, TEGRA114_CLK_PLL_A_OUT0, 11289600, 0 },
diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c
index 24532d70e469..6861ded135e0 100644
--- a/drivers/clk/tegra/clk-tegra124.c
+++ b/drivers/clk/tegra/clk-tegra124.c
@@ -1292,7 +1292,6 @@ static struct tegra_clk_init_table common_init_table[] __initdata = {
{ TEGRA124_CLK_UARTD, TEGRA124_CLK_PLL_P, 408000000, 0 },
{ TEGRA124_CLK_PLL_A, TEGRA124_CLK_CLK_MAX, 564480000, 1 },
{ TEGRA124_CLK_PLL_A_OUT0, TEGRA124_CLK_CLK_MAX, 11289600, 1 },
- { TEGRA124_CLK_EXTERN1, TEGRA124_CLK_PLL_A_OUT0, 0, 1 },
{ TEGRA124_CLK_I2S0, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0 },
{ TEGRA124_CLK_I2S1, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0 },
{ TEGRA124_CLK_I2S2, TEGRA124_CLK_PLL_A_OUT0, 11289600, 0 },
diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c
index fe536f1d770d..a552dafb8174 100644
--- a/drivers/clk/tegra/clk-tegra20.c
+++ b/drivers/clk/tegra/clk-tegra20.c
@@ -1031,7 +1031,6 @@ static struct tegra_clk_init_table init_table[] __initdata = {
{ TEGRA20_CLK_UARTE, TEGRA20_CLK_PLL_P, 0, 0 },
{ TEGRA20_CLK_PLL_A, TEGRA20_CLK_CLK_MAX, 56448000, 1 },
{ TEGRA20_CLK_PLL_A_OUT0, TEGRA20_CLK_CLK_MAX, 11289600, 1 },
- { TEGRA20_CLK_CDEV1, TEGRA20_CLK_CLK_MAX, 0, 1 },
{ TEGRA20_CLK_I2S1, TEGRA20_CLK_PLL_A_OUT0, 11289600, 0 },
{ TEGRA20_CLK_I2S2, TEGRA20_CLK_PLL_A_OUT0, 11289600, 0 },
{ TEGRA20_CLK_SDMMC1, TEGRA20_CLK_PLL_P, 48000000, 0 },
diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c
index af5119481d54..252859faeb4a 100644
--- a/drivers/clk/tegra/clk-tegra210.c
+++ b/drivers/clk/tegra/clk-tegra210.c
@@ -3442,7 +3442,6 @@ static struct tegra_clk_init_table init_table[] __initdata = {
{ TEGRA210_CLK_UARTD, TEGRA210_CLK_PLL_P, 408000000, 0 },
{ TEGRA210_CLK_PLL_A, TEGRA210_CLK_CLK_MAX, 564480000, 1 },
{ TEGRA210_CLK_PLL_A_OUT0, TEGRA210_CLK_CLK_MAX, 11289600, 1 },
- { TEGRA210_CLK_EXTERN1, TEGRA210_CLK_PLL_A_OUT0, 0, 1 },
{ TEGRA210_CLK_I2S0, TEGRA210_CLK_PLL_A_OUT0, 11289600, 0 },
{ TEGRA210_CLK_I2S1, TEGRA210_CLK_PLL_A_OUT0, 11289600, 0 },
{ TEGRA210_CLK_I2S2, TEGRA210_CLK_PLL_A_OUT0, 11289600, 0 },
diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c
index 24599ed2e6ff..65fdead2c764 100644
--- a/drivers/clk/tegra/clk-tegra30.c
+++ b/drivers/clk/tegra/clk-tegra30.c
@@ -1221,7 +1221,6 @@ static struct tegra_clk_init_table init_table[] __initdata = {
{ TEGRA30_CLK_UARTE, TEGRA30_CLK_PLL_P, 408000000, 0 },
{ TEGRA30_CLK_PLL_A, TEGRA30_CLK_CLK_MAX, 564480000, 1 },
{ TEGRA30_CLK_PLL_A_OUT0, TEGRA30_CLK_CLK_MAX, 11289600, 1 },
- { TEGRA30_CLK_EXTERN1, TEGRA30_CLK_PLL_A_OUT0, 0, 1 },
{ TEGRA30_CLK_I2S0, TEGRA30_CLK_PLL_A_OUT0, 11289600, 0 },
{ TEGRA30_CLK_I2S1, TEGRA30_CLK_PLL_A_OUT0, 11289600, 0 },
{ TEGRA30_CLK_I2S2, TEGRA30_CLK_PLL_A_OUT0, 11289600, 0 },
--
2.7.4
clk_out_1, clk_out_2, clk_out_3, blink are part of Tegra PMC block and
these clocks are moved to Tegra PMC driver with pmc as clock provider
and uses clock ids from dt-bindings/soc/tegra-pmc.h
So, this patch removes ids for these clocks from Tegra clock dt-bindings.
Signed-off-by: Sowjanya Komatineni <[email protected]>
---
include/dt-bindings/clock/tegra114-car.h | 14 +++++++-------
include/dt-bindings/clock/tegra124-car-common.h | 14 +++++++-------
include/dt-bindings/clock/tegra20-car.h | 2 +-
include/dt-bindings/clock/tegra210-car.h | 14 +++++++-------
include/dt-bindings/clock/tegra30-car.h | 14 +++++++-------
5 files changed, 29 insertions(+), 29 deletions(-)
diff --git a/include/dt-bindings/clock/tegra114-car.h b/include/dt-bindings/clock/tegra114-car.h
index bb5c2c999c05..9175cd0571b5 100644
--- a/include/dt-bindings/clock/tegra114-car.h
+++ b/include/dt-bindings/clock/tegra114-car.h
@@ -270,10 +270,10 @@
#define TEGRA114_CLK_AUDIO3 242
#define TEGRA114_CLK_AUDIO4 243
#define TEGRA114_CLK_SPDIF 244
-#define TEGRA114_CLK_CLK_OUT_1 245
-#define TEGRA114_CLK_CLK_OUT_2 246
-#define TEGRA114_CLK_CLK_OUT_3 247
-#define TEGRA114_CLK_BLINK 248
+/* 245 */
+/* 246 */
+/* 247 */
+/* 248 */
/* 249 */
/* 250 */
/* 251 */
@@ -333,9 +333,9 @@
#define TEGRA114_CLK_AUDIO3_MUX 303
#define TEGRA114_CLK_AUDIO4_MUX 304
#define TEGRA114_CLK_SPDIF_MUX 305
-#define TEGRA114_CLK_CLK_OUT_1_MUX 306
-#define TEGRA114_CLK_CLK_OUT_2_MUX 307
-#define TEGRA114_CLK_CLK_OUT_3_MUX 308
+/* 306 */
+/* 307 */
+/* 308 */
#define TEGRA114_CLK_DSIA_MUX 309
#define TEGRA114_CLK_DSIB_MUX 310
#define TEGRA114_CLK_XUSB_SS_DIV2 311
diff --git a/include/dt-bindings/clock/tegra124-car-common.h b/include/dt-bindings/clock/tegra124-car-common.h
index 0c4f5be0a742..90a0c5e7eb5f 100644
--- a/include/dt-bindings/clock/tegra124-car-common.h
+++ b/include/dt-bindings/clock/tegra124-car-common.h
@@ -269,10 +269,10 @@
#define TEGRA124_CLK_AUDIO3 242
#define TEGRA124_CLK_AUDIO4 243
#define TEGRA124_CLK_SPDIF 244
-#define TEGRA124_CLK_CLK_OUT_1 245
-#define TEGRA124_CLK_CLK_OUT_2 246
-#define TEGRA124_CLK_CLK_OUT_3 247
-#define TEGRA124_CLK_BLINK 248
+/* 245 */
+/* 246 */
+/* 247 */
+/* 248 */
/* 249 */
/* 250 */
/* 251 */
@@ -332,9 +332,9 @@
#define TEGRA124_CLK_AUDIO3_MUX 303
#define TEGRA124_CLK_AUDIO4_MUX 304
#define TEGRA124_CLK_SPDIF_MUX 305
-#define TEGRA124_CLK_CLK_OUT_1_MUX 306
-#define TEGRA124_CLK_CLK_OUT_2_MUX 307
-#define TEGRA124_CLK_CLK_OUT_3_MUX 308
+/* 306 */
+/* 307 */
+/* 308 */
/* 309 */
/* 310 */
#define TEGRA124_CLK_SOR0_LVDS 311 /* deprecated */
diff --git a/include/dt-bindings/clock/tegra20-car.h b/include/dt-bindings/clock/tegra20-car.h
index b21a0eb32921..fe541f627965 100644
--- a/include/dt-bindings/clock/tegra20-car.h
+++ b/include/dt-bindings/clock/tegra20-car.h
@@ -131,7 +131,7 @@
#define TEGRA20_CLK_CCLK 108
#define TEGRA20_CLK_HCLK 109
#define TEGRA20_CLK_PCLK 110
-#define TEGRA20_CLK_BLINK 111
+/* 111 */
#define TEGRA20_CLK_PLL_A 112
#define TEGRA20_CLK_PLL_A_OUT0 113
#define TEGRA20_CLK_PLL_C 114
diff --git a/include/dt-bindings/clock/tegra210-car.h b/include/dt-bindings/clock/tegra210-car.h
index 44f60623f99b..a3d8d3e75728 100644
--- a/include/dt-bindings/clock/tegra210-car.h
+++ b/include/dt-bindings/clock/tegra210-car.h
@@ -304,10 +304,10 @@
#define TEGRA210_CLK_AUDIO3 274
#define TEGRA210_CLK_AUDIO4 275
#define TEGRA210_CLK_SPDIF 276
-#define TEGRA210_CLK_CLK_OUT_1 277
-#define TEGRA210_CLK_CLK_OUT_2 278
-#define TEGRA210_CLK_CLK_OUT_3 279
-#define TEGRA210_CLK_BLINK 280
+/* 277 */
+/* 278 */
+/* 279 */
+/* 280 */
#define TEGRA210_CLK_SOR0_LVDS 281 /* deprecated */
#define TEGRA210_CLK_SOR0_OUT 281
#define TEGRA210_CLK_SOR1_OUT 282
@@ -386,9 +386,9 @@
#define TEGRA210_CLK_AUDIO3_MUX 353
#define TEGRA210_CLK_AUDIO4_MUX 354
#define TEGRA210_CLK_SPDIF_MUX 355
-#define TEGRA210_CLK_CLK_OUT_1_MUX 356
-#define TEGRA210_CLK_CLK_OUT_2_MUX 357
-#define TEGRA210_CLK_CLK_OUT_3_MUX 358
+/* 356 */
+/* 357 */
+/* 358 */
#define TEGRA210_CLK_DSIA_MUX 359
#define TEGRA210_CLK_DSIB_MUX 360
/* 361 */
diff --git a/include/dt-bindings/clock/tegra30-car.h b/include/dt-bindings/clock/tegra30-car.h
index 3c90f1535551..20ef2462d9e1 100644
--- a/include/dt-bindings/clock/tegra30-car.h
+++ b/include/dt-bindings/clock/tegra30-car.h
@@ -230,11 +230,11 @@
#define TEGRA30_CLK_AUDIO3 204
#define TEGRA30_CLK_AUDIO4 205
#define TEGRA30_CLK_SPDIF 206
-#define TEGRA30_CLK_CLK_OUT_1 207 /* (extern1) */
-#define TEGRA30_CLK_CLK_OUT_2 208 /* (extern2) */
-#define TEGRA30_CLK_CLK_OUT_3 209 /* (extern3) */
+/* 207 */
+/* 208 */
+/* 209 */
#define TEGRA30_CLK_SCLK 210
-#define TEGRA30_CLK_BLINK 211
+/* 211 */
#define TEGRA30_CLK_CCLK_G 212
#define TEGRA30_CLK_CCLK_LP 213
#define TEGRA30_CLK_TWD 214
@@ -260,9 +260,9 @@
/* 297 */
/* 298 */
/* 299 */
-#define TEGRA30_CLK_CLK_OUT_1_MUX 300
-#define TEGRA30_CLK_CLK_OUT_2_MUX 301
-#define TEGRA30_CLK_CLK_OUT_3_MUX 302
+/* 300 */
+/* 301 */
+/* 302 */
#define TEGRA30_CLK_AUDIO0_MUX 303
#define TEGRA30_CLK_AUDIO1_MUX 304
#define TEGRA30_CLK_AUDIO2_MUX 305
--
2.7.4
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 <[email protected]>
---
drivers/soc/tegra/pmc.c | 305 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 305 insertions(+)
diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index ea0e11a09c12..b8f6eb0ed8aa 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,83 @@
#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;
+};
+
+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 const 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,
+ },
+ {
+ .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,
+ },
+ {
+ .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,
+ },
+};
+
struct tegra_powergate {
struct generic_pm_domain genpd;
struct tegra_pmc *pmc;
@@ -254,6 +336,9 @@ struct tegra_pmc_soc {
*/
const struct tegra_wake_event *wake_events;
unsigned int num_wake_events;
+
+ const struct pmc_clk_init_data *pmc_clks_data;
+ unsigned int num_pmc_clks;
};
static const char * const tegra186_reset_sources[] = {
@@ -2163,6 +2248,211 @@ 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;
+ 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 = TEGRA_PMC_CLK_MAX;
+
+ for (i = 0; i < TEGRA_PMC_CLK_MAX; i++)
+ clk_data->clks[i] = ERR_PTR(-ENOENT);
+
+ for (i = 0; i < pmc->soc->num_pmc_clks; i++) {
+ const 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: %d\n",
+ __clk_get_name(clk),
+ __clk_get_name(clkmux), ret);
+ }
+
+ clk_register_clkdev(clk, data->dev_name, data->gate_name);
+ }
+
+ of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);
+
+ return;
+
+free_clks:
+ kfree(clk_data->clks);
+free_clkdata:
+ kfree(clk_data);
+ WARN(1, "failed to register Tegra PMC clocks\n");
+}
+
static int tegra_pmc_probe(struct platform_device *pdev)
{
void __iomem *base;
@@ -2281,6 +2571,7 @@ static int tegra_pmc_probe(struct platform_device *pdev)
pmc->base = base;
mutex_unlock(&pmc->powergates_lock);
+ tegra_pmc_clock_register(pmc, pdev->dev.of_node);
platform_set_drvdata(pdev, pmc);
return 0;
@@ -2422,6 +2713,8 @@ static const struct tegra_pmc_soc tegra20_pmc_soc = {
.num_reset_sources = 0,
.reset_levels = NULL,
.num_reset_levels = 0,
+ .pmc_clks_data = NULL,
+ .num_pmc_clks = 0,
};
static const char * const tegra30_powergates[] = {
@@ -2469,6 +2762,8 @@ static const struct tegra_pmc_soc tegra30_pmc_soc = {
.num_reset_sources = ARRAY_SIZE(tegra30_reset_sources),
.reset_levels = NULL,
.num_reset_levels = 0,
+ .pmc_clks_data = tegra_pmc_clks_data,
+ .num_pmc_clks = ARRAY_SIZE(tegra_pmc_clks_data),
};
static const char * const tegra114_powergates[] = {
@@ -2520,6 +2815,8 @@ static const struct tegra_pmc_soc tegra114_pmc_soc = {
.num_reset_sources = ARRAY_SIZE(tegra30_reset_sources),
.reset_levels = NULL,
.num_reset_levels = 0,
+ .pmc_clks_data = tegra_pmc_clks_data,
+ .num_pmc_clks = ARRAY_SIZE(tegra_pmc_clks_data),
};
static const char * const tegra124_powergates[] = {
@@ -2631,6 +2928,8 @@ static const struct tegra_pmc_soc tegra124_pmc_soc = {
.num_reset_sources = ARRAY_SIZE(tegra30_reset_sources),
.reset_levels = NULL,
.num_reset_levels = 0,
+ .pmc_clks_data = tegra_pmc_clks_data,
+ .num_pmc_clks = ARRAY_SIZE(tegra_pmc_clks_data),
};
static const char * const tegra210_powergates[] = {
@@ -2745,6 +3044,8 @@ static const struct tegra_pmc_soc tegra210_pmc_soc = {
.num_reset_levels = 0,
.num_wake_events = ARRAY_SIZE(tegra210_wake_events),
.wake_events = tegra210_wake_events,
+ .pmc_clks_data = tegra_pmc_clks_data,
+ .num_pmc_clks = ARRAY_SIZE(tegra_pmc_clks_data),
};
#define TEGRA186_IO_PAD_TABLE(_pad) \
@@ -2874,6 +3175,8 @@ static const struct tegra_pmc_soc tegra186_pmc_soc = {
.num_reset_levels = ARRAY_SIZE(tegra186_reset_levels),
.num_wake_events = ARRAY_SIZE(tegra186_wake_events),
.wake_events = tegra186_wake_events,
+ .pmc_clks_data = NULL,
+ .num_pmc_clks = 0,
};
static const struct tegra_io_pad_soc tegra194_io_pads[] = {
@@ -2991,6 +3294,8 @@ static const struct tegra_pmc_soc tegra194_pmc_soc = {
.num_reset_levels = ARRAY_SIZE(tegra186_reset_levels),
.num_wake_events = ARRAY_SIZE(tegra194_wake_events),
.wake_events = tegra194_wake_events,
+ .pmc_clks_data = NULL,
+ .num_pmc_clks = 0,
};
static const struct of_device_id tegra_pmc_match[] = {
--
2.7.4
Thanks Greg.
Sorry, Will send this patch separately (out of this series) with stable
tag to get this applied to stable kernels once review is done for this
series.
On 12/5/19 6:48 PM, Sowjanya Komatineni wrote:
> mclk is from clk_out_1 which is part of Tegra PMC block and pmc clocks
> are moved to Tegra PMC driver with pmc as clock provider and using pmc
> clock ids.
>
> New device tree uses clk_out_1 from pmc clock provider.
>
> So, this patch adds fallback to extern1 in case of retrieving mclk fails
> to be backward compatible of new device tree with older kernels.
>
> Cc: [email protected]
>
> Signed-off-by: Sowjanya Komatineni <[email protected]>
> ---
> sound/soc/tegra/tegra_asoc_utils.c | 10 ++++++++--
> 1 file changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/sound/soc/tegra/tegra_asoc_utils.c b/sound/soc/tegra/tegra_asoc_utils.c
> index 8e3a3740df7c..f7408d5240c0 100644
> --- a/sound/soc/tegra/tegra_asoc_utils.c
> +++ b/sound/soc/tegra/tegra_asoc_utils.c
> @@ -211,8 +211,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)) {
> + dev_err(data->dev, "Can't retrieve clk extern1\n");
> + ret = PTR_ERR(data->clk_cdev1);
> + goto err_put_pll_a_out0;
> + }
> +
> + dev_err(data->dev, "Falling back to extern1\n");
> }
>
> /*
On Fri, Dec 06, 2019 at 09:49:49AM -0800, Sowjanya Komatineni wrote:
> Thanks Greg.
>
> Sorry, Will send this patch separately (out of this series) with stable tag
> to get this applied to stable kernels once review is done for this series.
Why not just properly add the tag in the original patch when it gets
merged? That's how everyone else does it :)
This isn't new, it's been happening this way for 12+ years now...
thanks,
greg k-h
06.12.2019 05:48, Sowjanya Komatineni пишет:
> Tegra PMC has clk_out_1, clk_out_2, clk_out_3 and blink controls which
> are currently registered by Tegra clock driver using clk_regiser_mux and
> clk_register_gate which performs direct Tegra PMC register access.
>
> When Tegra PMC is in secure mode, any access from non-secure world will
> not go through.
>
> This patch series adds these Tegra PMC clocks and blink controls to Tegra
> PMC driver with PMC as clock provider and removed them from Tegra clock
> driver. This also adds PMC specific clock id's to use in device tree and
> removed clock ids of PMC clock from Tegra clock driver.
>
> clk_out_1 is dedicated for audio mclk and current ASoC driver does not
> setting extern1 as parent for clk_out_1 and enabling clk_out_1 and
> currently this is taken care by Tegra clock driver during clock inits
> and there is no need to enable this during clock init.
>
> So, this series also includes patch that updates ASoC driver to take
> care of configuring parent of mclk and enabling mclk using both extern1
> and clk_out_1 and updates all device trees to use clk_out_1 from pmc as
> mclk incase if device tree don't specify assigned-clock-parents.
>
> This series also includes a patch for mclk fallback to use extern1
> when retrieving mclk fails with new device tree which uses pmc provider
> to have this backward compatible of new DT with old kernels.
>
> This series also includes a patch to remove clock ids for these clocks
> from clock dt-binding as these clocks are not used in any of the existing
> device tree except in tegra210-smaug.dts and this series includes a patch
> to update clock provider from tegra_car to pmc in tegra210-smaug.dts for
> clk_out_2.
>
> [v3]: Changes between v2 and v3 are
> - Removes set parent of clk_out_1_mux to extern1 and enabling
> extern1 from the clock driver.
> - Doesn't enable clk_out_1 and blink by default in pmc driver
> - Updates ASoC driver to take care of audio mclk parent
> configuration incase if device tree don't specify assigned
> clock parent properties and enables mclk using both clk_out_1
> and extern1.
> - updates all device trees using extern1 as mclk in sound node
> to use clk_out_1 from pmc.
> - patch for YAML format pmc dt-binding
> - Includes v2 feedback
>
> [v2]: Changes between v1 and v2 are
> - v2 includes patches for adding clk_out_1, clk_out_2, clk_out_3,
> blink controls to Tegra PMC driver and removing clk-tegra-pmc.
> - feedback related to pmc clocks in Tegra PMC driver from v1
> - Removed patches for WB0 PLLM overrides and PLLE IDDQ PMC programming
> by the clock driver using helper functions from Tegra PMC.
>
> Note:
> To use helper functions from PMC driver, PMC early init need to
> happen prior to using helper functions and these helper functions are
> for PLLM Override and PLLE IDDQ programming in PMC during PLLM/PLLE
> clock registration which happen in clock_init prior to Tegra PMC
> probe.
> Moving PLLM/PLLE clocks registration to happen after Tegra PMC
> impacts other clocks EMC, MC and corresponding tegra_emc_init and
> tegra_mc_init.
> This implementation of configuring PMC registers thru helper
> functions in clock driver needs proper changes across PMC, Clock,
> EMC and MC inits to have it work across all Tegra platforms.
>
> Currently PLLM Override is not enabled in the bootloader so proper
> patches for this fix will be taken care separately.
>
> [v1]: v1 includes patches for below fixes.
> - adding clk_out_1, clk_out_2, clk_out_3, blink controls to Tegra PMC
> driver and removing clk-tegra-pmc.
> - updated clock provider from tegra_car to pmc in the device tree
> tegra210-smaug.dts that uses clk_out_2.
> - Added helper functions in PMC driver for WB0 PLLM overrides and PLLE
> IDDQ programming to use by clock driver and updated clock driver to
> use these helper functions and removed direct PMC access from clock
> driver and all pmc base address references in clock driver.
>
>
> Sowjanya Komatineni (15):
> dt-bindings: soc: tegra-pmc: Add Tegra PMC clock bindings
> dt-bindings: tegra: Convert Tegra PMC bindings to YAML
> soc: tegra: Add Tegra PMC clock registrations into PMC driver
> dt-bindings: soc: tegra-pmc: Add id for Tegra PMC blink control
> soc: pmc: Add blink output clock registration to Tegra PMC
> clk: tegra: Remove tegra_pmc_clk_init along with clk ids
> dt-bindings: clock: tegra: Remove pmc clock ids from clock dt-bindings
> ASoC: tegra: Add audio mclk control through clk_out_1 and extern1
> ASoC: tegra: Add fallback for audio mclk
> clk: tegra: Remove extern1 and cdev1 from clocks inittable
> ARM: dts: tegra: Add clock-cells property to pmc
> arm64: tegra: Add clock-cells property to Tegra PMC node
> ARM: tegra: Update sound node clocks in device tree
> arm64: tegra: smaug: Change clk_out_2 provider to pmc
> ASoC: nau8825: change Tegra clk_out_2 provider from tegra_car to pmc
Hello Sowjanya,
Something gone wrong with these patches because I didn't receive them
and don't see them on the ML either.
Also, the list of email correspondents looks a bit too larger. I'm
pretty sure some of the people do not care much about this series. I
tend to use script/get_maintainer.pl and then manually pick the relevant
people for patches.
06.12.2019 05:48, 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 <[email protected]>
> ---
> drivers/soc/tegra/pmc.c | 305 ++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 305 insertions(+)
>
> diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
> index ea0e11a09c12..b8f6eb0ed8aa 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,83 @@
> #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;
> +};
> +
> +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 const 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,
> + },
> + {
> + .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,
> + },
> + {
> + .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,
> + },
> +};
> +
> struct tegra_powergate {
> struct generic_pm_domain genpd;
> struct tegra_pmc *pmc;
> @@ -254,6 +336,9 @@ struct tegra_pmc_soc {
> */
> const struct tegra_wake_event *wake_events;
> unsigned int num_wake_events;
> +
> + const struct pmc_clk_init_data *pmc_clks_data;
> + unsigned int num_pmc_clks;
> };
>
> static const char * const tegra186_reset_sources[] = {
> @@ -2163,6 +2248,211 @@ 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;
How this could ever happen?
Why are you returning negative value for u8? It doesn't different from
returning val >= num_parents.
> + 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,
> +};
What's the benefit of separating GATE from the MUX?
I think it could be a single clock.
> +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;
> + 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 = TEGRA_PMC_CLK_MAX;
> +
> + for (i = 0; i < TEGRA_PMC_CLK_MAX; i++)
> + clk_data->clks[i] = ERR_PTR(-ENOENT);
> +
> + for (i = 0; i < pmc->soc->num_pmc_clks; i++) {
> + const 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: %d\n",
> + __clk_get_name(clk),
> + __clk_get_name(clkmux), ret);
> + }
is this really needed? GATE clock has a single parent, the MUX.
06.12.2019 05:48, Sowjanya Komatineni пишет:
> Current Tegra clock driver registers PMC clocks clk_out_1, clk_out_2,
> clk_out_3 and blink output in tegra_pmc_init() which does direct Tegra
> PMC access during clk_ops and these PMC register read and write access
> will not happen when PMC is in secure mode.
>
> Any direct PMC register access from non-secure world will not go
> through and all the PMC clocks and blink control are done in Tegra PMC
> driver with PMC as clock provider.
>
> This patch removes tegra_pmc_clk_init along with corresponding clk ids
> from Tegra clock driver.
>
> Signed-off-by: Sowjanya Komatineni <[email protected]>
> ---
[snip]
> @@ -1230,9 +1222,6 @@ static struct tegra_clk_init_table init_table[] __initdata = {
> { TEGRA30_CLK_PLL_A, TEGRA30_CLK_CLK_MAX, 564480000, 1 },
> { TEGRA30_CLK_PLL_A_OUT0, TEGRA30_CLK_CLK_MAX, 11289600, 1 },
> { TEGRA30_CLK_EXTERN1, TEGRA30_CLK_PLL_A_OUT0, 0, 1 },
Perhaps these clocks do not need to be always-enabled?
[snip]
07.12.2019 17:33, Dmitry Osipenko пишет:
> 06.12.2019 05:48, Sowjanya Komatineni пишет:
>> Current Tegra clock driver registers PMC clocks clk_out_1, clk_out_2,
>> clk_out_3 and blink output in tegra_pmc_init() which does direct Tegra
>> PMC access during clk_ops and these PMC register read and write access
>> will not happen when PMC is in secure mode.
>>
>> Any direct PMC register access from non-secure world will not go
>> through and all the PMC clocks and blink control are done in Tegra PMC
>> driver with PMC as clock provider.
>>
>> This patch removes tegra_pmc_clk_init along with corresponding clk ids
>> from Tegra clock driver.
>>
>> Signed-off-by: Sowjanya Komatineni <[email protected]>
>> ---
>
> [snip]
>
>> @@ -1230,9 +1222,6 @@ static struct tegra_clk_init_table init_table[] __initdata = {
>
>> { TEGRA30_CLK_PLL_A, TEGRA30_CLK_CLK_MAX, 564480000, 1 },
>> { TEGRA30_CLK_PLL_A_OUT0, TEGRA30_CLK_CLK_MAX, 11289600, 1 },
>> { TEGRA30_CLK_EXTERN1, TEGRA30_CLK_PLL_A_OUT0, 0, 1 },
>
> Perhaps these clocks do not need to be always-enabled?
>
> [snip]
>
Also, EXTERN1 parent configuration should be moved to the audio
driver/device-tree as well.
Maybe it even makes sense to move the whole configuration, including
PLLA. I don't see why clk driver need to do something for the audio driver.
06.12.2019 05:48, Sowjanya Komatineni пишет:
> Current ASoC driver uses extern1 as cdev1 clock from Tegra30 onwards
> through device tree.
>
> Actual audio mclk is clk_out_1 and to use PLLA for mclk rate control,
> need to clk_out_1_mux parent to extern1 and extern1 parent to PLLA_OUT0.
>
> Currently Tegra clock driver init sets the parents and enables both
> clk_out_1 and extern1 clocks. But these clocks parent and enables should
> be controlled by ASoC driver.
>
> Clock parents can be specified in device tree using assigned-clocks
> and assigned-clock-parents.
>
> To enable audio mclk, both clk_out_1 and extern1 clocks need to be
> enabled.
>
> This patch configures parents for clk_out_1 and extern1 clocks if device
> tree does not specify clock parents inorder to support old device tree
> and controls mclk using both clk_out_1 and extern1 clocks.
>
> Signed-off-by: Sowjanya Komatineni <[email protected]>
> ---
> sound/soc/tegra/tegra_asoc_utils.c | 66 ++++++++++++++++++++++++++++++++++++++
> sound/soc/tegra/tegra_asoc_utils.h | 1 +
> 2 files changed, 67 insertions(+)
>
> diff --git a/sound/soc/tegra/tegra_asoc_utils.c b/sound/soc/tegra/tegra_asoc_utils.c
> index 536a578e9512..8e3a3740df7c 100644
> --- a/sound/soc/tegra/tegra_asoc_utils.c
> +++ b/sound/soc/tegra/tegra_asoc_utils.c
> @@ -60,6 +60,7 @@ int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,
> data->set_mclk = 0;
>
> clk_disable_unprepare(data->clk_cdev1);
> + clk_disable_unprepare(data->clk_extern1);
> clk_disable_unprepare(data->clk_pll_a_out0);
> clk_disable_unprepare(data->clk_pll_a);
>
> @@ -89,6 +90,14 @@ int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,
> return err;
> }
>
> + if (!IS_ERR_OR_NULL(data->clk_extern1)) {
> + err = clk_prepare_enable(data->clk_extern1);
> + if (err) {
> + dev_err(data->dev, "Can't enable extern1: %d\n", err);
> + return err;
> + }
> + }
> +
> err = clk_prepare_enable(data->clk_cdev1);
> if (err) {
> dev_err(data->dev, "Can't enable cdev1: %d\n", err);
> @@ -109,6 +118,7 @@ int tegra_asoc_utils_set_ac97_rate(struct tegra_asoc_utils_data *data)
> int err;
>
> clk_disable_unprepare(data->clk_cdev1);
> + clk_disable_unprepare(data->clk_extern1);
> clk_disable_unprepare(data->clk_pll_a_out0);
> clk_disable_unprepare(data->clk_pll_a);
>
> @@ -142,6 +152,14 @@ int tegra_asoc_utils_set_ac97_rate(struct tegra_asoc_utils_data *data)
> return err;
> }
>
> + if (!IS_ERR_OR_NULL(data->clk_extern1)) {
> + err = clk_prepare_enable(data->clk_extern1);
> + if (err) {
> + dev_err(data->dev, "Can't enable extern1: %d\n", err);
> + return err;
> + }
> + }
Why this is needed given that clk_extern1 is either a child of MCLK or
MCLK itself (on T20)? The child clocks are enabled when the parent is
enabled.
> err = clk_prepare_enable(data->clk_cdev1);
> if (err) {
> dev_err(data->dev, "Can't enable cdev1: %d\n", err);
> @@ -158,6 +176,7 @@ EXPORT_SYMBOL_GPL(tegra_asoc_utils_set_ac97_rate);
> int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data,
> struct device *dev)
> {
> + struct clk *clk_out_1_mux;
> int ret;
>
> data->dev = dev;
> @@ -196,6 +215,51 @@ int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data,
> goto err_put_pll_a_out0;
> }
In a previous patch you added fallback to EXTPERIPH when clk_get(MCLK)
fails. This will work perfectly fine for the older kernels which have
all clocks in the same single CaR driver, but this may not work that
great for the newer kernels because PMC driver isn't registered early
during boot and thus it is possible to get a legit -EPROBE_DEFER which
shouldn't be ignored. In other words, you need to add into this patch a
check for the error code returned by clk_get(MCLK) and fallback only for
-EINVAL.
> + /*
> + * If clock parents are not set in DT, configure here to use clk_out_1
> + * as mclk and extern1 as parent for Tegra30 and higher.
> + */
> + if (!of_find_property(dev->of_node, "assigned-clock-parents", NULL) &&
> + data->soc > TEGRA_ASOC_UTILS_SOC_TEGRA20) {
> + data->clk_extern1 = clk_get_sys("clk_out_1", "extern1");
> + if (IS_ERR(data->clk_extern1)) {
> + dev_err(data->dev, "Can't retrieve clk extern1\n");
> + ret = PTR_ERR(data->clk_extern1);
> + goto err_put_cdev1;
> + }
> +
> + ret = clk_set_parent(data->clk_extern1, data->clk_pll_a_out0);
> + if (ret < 0) {
> + dev_err(data->dev,
> + "Set parent failed for clk extern1: %d\n",
> + ret);
> + goto err_put_cdev1;
> + }
> +
> + clk_out_1_mux = clk_get_sys(NULL, "clk_out_1_mux");
Note1: clk_get(dev, "clk_out_1_mux") should work here by letting clk
core to fall back to the clk_get_sys() by itself. Either way should be good.
Note2: devm_clk_get() could be used everywhere here. Maybe it won't hurt
to convert tegra_asoc_utils to use managed resources to keep code a bit
cleaner. It should be a separate patch.
> + if (IS_ERR(clk_out_1_mux)) {
> + dev_err(data->dev, "Can't retrieve clk clk_out_1_mux\n");
> + ret = PTR_ERR(clk_out_1_mux);
> + goto err_put_cdev1;
> + }
> +
> + ret = clk_set_parent(clk_out_1_mux, data->clk_extern1);
> + if (ret < 0) {
> + dev_err(data->dev,
> + "Set parent failed for clk_out_1_mux: %d\n",
> + ret);
> + clk_put(clk_out_1_mux);
> + goto err_put_cdev1;
> + }
clk_put(clk_cdev1);
> + data->clk_cdev1 = clk_get_sys(NULL, "clk_out_1");
> + if (IS_ERR(data->clk_cdev1)) {
> + dev_err(data->dev, "Can't retrieve clk clk_out_1\n");
> + ret = PTR_ERR(data->clk_cdev1);
> + goto err_put_cdev1;
goto err_put_pll_a_out0;
> + }
> + }
> +
> ret = tegra_asoc_utils_set_rate(data, 44100, 256 * 44100);
> if (ret)
> goto err_put_cdev1;
> @@ -215,6 +279,8 @@ EXPORT_SYMBOL_GPL(tegra_asoc_utils_init);
>
> void tegra_asoc_utils_fini(struct tegra_asoc_utils_data *data)
> {
> + if (!IS_ERR_OR_NULL(data->clk_extern1))
> + clk_put(data->clk_extern1);
> clk_put(data->clk_cdev1);
> clk_put(data->clk_pll_a_out0);
> clk_put(data->clk_pll_a);
> diff --git a/sound/soc/tegra/tegra_asoc_utils.h b/sound/soc/tegra/tegra_asoc_utils.h
> index 0c13818dee75..5f2b96478caf 100644
> --- a/sound/soc/tegra/tegra_asoc_utils.h
> +++ b/sound/soc/tegra/tegra_asoc_utils.h
> @@ -25,6 +25,7 @@ struct tegra_asoc_utils_data {
> struct clk *clk_pll_a;
> struct clk *clk_pll_a_out0;
> struct clk *clk_cdev1;
> + struct clk *clk_extern1;
> int set_baseclock;
> int set_mclk;
> };
>
07.12.2019 17:43, Dmitry Osipenko пишет:
> 07.12.2019 17:33, Dmitry Osipenko пишет:
>> 06.12.2019 05:48, Sowjanya Komatineni пишет:
>>> Current Tegra clock driver registers PMC clocks clk_out_1, clk_out_2,
>>> clk_out_3 and blink output in tegra_pmc_init() which does direct Tegra
>>> PMC access during clk_ops and these PMC register read and write access
>>> will not happen when PMC is in secure mode.
>>>
>>> Any direct PMC register access from non-secure world will not go
>>> through and all the PMC clocks and blink control are done in Tegra PMC
>>> driver with PMC as clock provider.
>>>
>>> This patch removes tegra_pmc_clk_init along with corresponding clk ids
>>> from Tegra clock driver.
>>>
>>> Signed-off-by: Sowjanya Komatineni <[email protected]>
>>> ---
>>
>> [snip]
>>
>>> @@ -1230,9 +1222,6 @@ static struct tegra_clk_init_table init_table[] __initdata = {
>>
>>> { TEGRA30_CLK_PLL_A, TEGRA30_CLK_CLK_MAX, 564480000, 1 },
>>> { TEGRA30_CLK_PLL_A_OUT0, TEGRA30_CLK_CLK_MAX, 11289600, 1 },
>>> { TEGRA30_CLK_EXTERN1, TEGRA30_CLK_PLL_A_OUT0, 0, 1 },
>>
>> Perhaps these clocks do not need to be always-enabled?
>>
>> [snip]
>>
>
> Also, EXTERN1 parent configuration should be moved to the audio
> driver/device-tree as well.
Ah, I missed that it's done in the patch #10.
> Maybe it even makes sense to move the whole configuration, including
> PLLA. I don't see why clk driver need to do something for the audio driver.
07.12.2019 17:28, Dmitry Osipenko пишет:
> 06.12.2019 05:48, 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 <[email protected]>
>> ---
[snip]
>> +
>> +static const struct clk_ops pmc_clk_gate_ops = {
>> + .is_enabled = pmc_clk_is_enabled,
>> + .enable = pmc_clk_enable,
>> + .disable = pmc_clk_disable,
>> +};
>
> What's the benefit of separating GATE from the MUX?
>
> I think it could be a single clock.
According to TRM:
1. GATE and MUX are separate entities.
2. GATE is the parent of MUX (see PMC's CLK_OUT paths diagram in TRM).
3. PMC doesn't gate EXTPERIPH clock but could "force-enable" it, correct?
[snip]
07.12.2019 18:47, Dmitry Osipenko пишет:
> 07.12.2019 17:28, Dmitry Osipenko пишет:
>> 06.12.2019 05:48, 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 <[email protected]>
>>> ---
>
> [snip]
>
>>> +
>>> +static const struct clk_ops pmc_clk_gate_ops = {
>>> + .is_enabled = pmc_clk_is_enabled,
>>> + .enable = pmc_clk_enable,
>>> + .disable = pmc_clk_disable,
>>> +};
>>
>> What's the benefit of separating GATE from the MUX?
>>
>> I think it could be a single clock.
>
> According to TRM:
>
> 1. GATE and MUX are separate entities.
>
> 2. GATE is the parent of MUX (see PMC's CLK_OUT paths diagram in TRM).
>
> 3. PMC doesn't gate EXTPERIPH clock but could "force-enable" it, correct?
4. clk_m_div2/4 are internal PMC OSC dividers and thus these clocks
should belong to PMC.
07.12.2019 18:53, Dmitry Osipenko пишет:
> 07.12.2019 18:47, Dmitry Osipenko пишет:
>> 07.12.2019 17:28, Dmitry Osipenko пишет:
>>> 06.12.2019 05:48, 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 <[email protected]>
>>>> ---
>>
>> [snip]
>>
>>>> +
>>>> +static const struct clk_ops pmc_clk_gate_ops = {
>>>> + .is_enabled = pmc_clk_is_enabled,
>>>> + .enable = pmc_clk_enable,
>>>> + .disable = pmc_clk_disable,
>>>> +};
>>>
>>> What's the benefit of separating GATE from the MUX?
>>>
>>> I think it could be a single clock.
>>
>> According to TRM:
>>
>> 1. GATE and MUX are separate entities.
>>
>> 2. GATE is the parent of MUX (see PMC's CLK_OUT paths diagram in TRM).
>>
>> 3. PMC doesn't gate EXTPERIPH clock but could "force-enable" it, correct?
>
> 4. clk_m_div2/4 are internal PMC OSC dividers and thus these clocks
> should belong to PMC.
Also, it should be "osc" and not "clk_m".
On 12/7/19 6:58 AM, Dmitry Osipenko wrote:
> 06.12.2019 05:48, Sowjanya Komatineni пишет:
>> Current ASoC driver uses extern1 as cdev1 clock from Tegra30 onwards
>> through device tree.
>>
>> Actual audio mclk is clk_out_1 and to use PLLA for mclk rate control,
>> need to clk_out_1_mux parent to extern1 and extern1 parent to PLLA_OUT0.
>>
>> Currently Tegra clock driver init sets the parents and enables both
>> clk_out_1 and extern1 clocks. But these clocks parent and enables should
>> be controlled by ASoC driver.
>>
>> Clock parents can be specified in device tree using assigned-clocks
>> and assigned-clock-parents.
>>
>> To enable audio mclk, both clk_out_1 and extern1 clocks need to be
>> enabled.
>>
>> This patch configures parents for clk_out_1 and extern1 clocks if device
>> tree does not specify clock parents inorder to support old device tree
>> and controls mclk using both clk_out_1 and extern1 clocks.
>>
>> Signed-off-by: Sowjanya Komatineni <[email protected]>
>> ---
>> sound/soc/tegra/tegra_asoc_utils.c | 66 ++++++++++++++++++++++++++++++++++++++
>> sound/soc/tegra/tegra_asoc_utils.h | 1 +
>> 2 files changed, 67 insertions(+)
>>
>> diff --git a/sound/soc/tegra/tegra_asoc_utils.c b/sound/soc/tegra/tegra_asoc_utils.c
>> index 536a578e9512..8e3a3740df7c 100644
>> --- a/sound/soc/tegra/tegra_asoc_utils.c
>> +++ b/sound/soc/tegra/tegra_asoc_utils.c
>> @@ -60,6 +60,7 @@ int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,
>> data->set_mclk = 0;
>>
>> clk_disable_unprepare(data->clk_cdev1);
>> + clk_disable_unprepare(data->clk_extern1);
>> clk_disable_unprepare(data->clk_pll_a_out0);
>> clk_disable_unprepare(data->clk_pll_a);
>>
>> @@ -89,6 +90,14 @@ int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,
>> return err;
>> }
>>
>> + if (!IS_ERR_OR_NULL(data->clk_extern1)) {
>> + err = clk_prepare_enable(data->clk_extern1);
>> + if (err) {
>> + dev_err(data->dev, "Can't enable extern1: %d\n", err);
>> + return err;
>> + }
>> + }
>> +
>> err = clk_prepare_enable(data->clk_cdev1);
>> if (err) {
>> dev_err(data->dev, "Can't enable cdev1: %d\n", err);
>> @@ -109,6 +118,7 @@ int tegra_asoc_utils_set_ac97_rate(struct tegra_asoc_utils_data *data)
>> int err;
>>
>> clk_disable_unprepare(data->clk_cdev1);
>> + clk_disable_unprepare(data->clk_extern1);
>> clk_disable_unprepare(data->clk_pll_a_out0);
>> clk_disable_unprepare(data->clk_pll_a);
>>
>> @@ -142,6 +152,14 @@ int tegra_asoc_utils_set_ac97_rate(struct tegra_asoc_utils_data *data)
>> return err;
>> }
>>
>> + if (!IS_ERR_OR_NULL(data->clk_extern1)) {
>> + err = clk_prepare_enable(data->clk_extern1);
>> + if (err) {
>> + dev_err(data->dev, "Can't enable extern1: %d\n", err);
>> + return err;
>> + }
>> + }
> Why this is needed given that clk_extern1 is either a child of MCLK or
> MCLK itself (on T20)? The child clocks are enabled when the parent is
> enabled.
For T30 and later, clk_extern1 is one of the source for clk_out_1_mux.
clk_extern1 is in CAR and it has its own gate and mux.
As audio mclk related clocks (clk_out_1, clk_out_1_mux, and extern1) are
moved into ASoC driver from clock driver
need to enable extern1 gate as well along with clk_out1 for T30 through
T210.
Just FYI, extern1 enable here happens only when data->clk_extern1 is
available which is for T30 onwards.
>> err = clk_prepare_enable(data->clk_cdev1);
>> if (err) {
>> dev_err(data->dev, "Can't enable cdev1: %d\n", err);
>> @@ -158,6 +176,7 @@ EXPORT_SYMBOL_GPL(tegra_asoc_utils_set_ac97_rate);
>> int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data,
>> struct device *dev)
>> {
>> + struct clk *clk_out_1_mux;
>> int ret;
>>
>> data->dev = dev;
>> @@ -196,6 +215,51 @@ int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data,
>> goto err_put_pll_a_out0;
>> }
> In a previous patch you added fallback to EXTPERIPH when clk_get(MCLK)
> fails. This will work perfectly fine for the older kernels which have
> all clocks in the same single CaR driver, but this may not work that
> great for the newer kernels because PMC driver isn't registered early
> during boot and thus it is possible to get a legit -EPROBE_DEFER which
> shouldn't be ignored. In other words, you need to add into this patch a
> check for the error code returned by clk_get(MCLK) and fallback only for
> -EINVAL.
yeah right, will add check in next version.
>> + /*
>> + * If clock parents are not set in DT, configure here to use clk_out_1
>> + * as mclk and extern1 as parent for Tegra30 and higher.
>> + */
>> + if (!of_find_property(dev->of_node, "assigned-clock-parents", NULL) &&
>> + data->soc > TEGRA_ASOC_UTILS_SOC_TEGRA20) {
>> + data->clk_extern1 = clk_get_sys("clk_out_1", "extern1");
>> + if (IS_ERR(data->clk_extern1)) {
>> + dev_err(data->dev, "Can't retrieve clk extern1\n");
>> + ret = PTR_ERR(data->clk_extern1);
>> + goto err_put_cdev1;
>> + }
>> +
>> + ret = clk_set_parent(data->clk_extern1, data->clk_pll_a_out0);
>> + if (ret < 0) {
>> + dev_err(data->dev,
>> + "Set parent failed for clk extern1: %d\n",
>> + ret);
>> + goto err_put_cdev1;
>> + }
>> +
>> + clk_out_1_mux = clk_get_sys(NULL, "clk_out_1_mux");
> Note1: clk_get(dev, "clk_out_1_mux") should work here by letting clk
> core to fall back to the clk_get_sys() by itself. Either way should be good.
>
> Note2: devm_clk_get() could be used everywhere here. Maybe it won't hurt
> to convert tegra_asoc_utils to use managed resources to keep code a bit
> cleaner. It should be a separate patch.
OK Will add patch to use devm_clk_get() in tegra_asoc_utils_init and
will use same for these patches
>> + if (IS_ERR(clk_out_1_mux)) {
>> + dev_err(data->dev, "Can't retrieve clk clk_out_1_mux\n");
>> + ret = PTR_ERR(clk_out_1_mux);
>> + goto err_put_cdev1;
>> + }
>> +
>> + ret = clk_set_parent(clk_out_1_mux, data->clk_extern1);
>> + if (ret < 0) {
>> + dev_err(data->dev,
>> + "Set parent failed for clk_out_1_mux: %d\n",
>> + ret);
>> + clk_put(clk_out_1_mux);
>> + goto err_put_cdev1;
>> + }
> clk_put(clk_cdev1);
>
>> + data->clk_cdev1 = clk_get_sys(NULL, "clk_out_1");
>> + if (IS_ERR(data->clk_cdev1)) {
>> + dev_err(data->dev, "Can't retrieve clk clk_out_1\n");
>> + ret = PTR_ERR(data->clk_cdev1);
>> + goto err_put_cdev1;
> goto err_put_pll_a_out0;
>
>> + }
>> + }
>> +
>> ret = tegra_asoc_utils_set_rate(data, 44100, 256 * 44100);
>> if (ret)
>> goto err_put_cdev1;
>> @@ -215,6 +279,8 @@ EXPORT_SYMBOL_GPL(tegra_asoc_utils_init);
>>
>> void tegra_asoc_utils_fini(struct tegra_asoc_utils_data *data)
>> {
>> + if (!IS_ERR_OR_NULL(data->clk_extern1))
>> + clk_put(data->clk_extern1);
>> clk_put(data->clk_cdev1);
>> clk_put(data->clk_pll_a_out0);
>> clk_put(data->clk_pll_a);
>> diff --git a/sound/soc/tegra/tegra_asoc_utils.h b/sound/soc/tegra/tegra_asoc_utils.h
>> index 0c13818dee75..5f2b96478caf 100644
>> --- a/sound/soc/tegra/tegra_asoc_utils.h
>> +++ b/sound/soc/tegra/tegra_asoc_utils.h
>> @@ -25,6 +25,7 @@ struct tegra_asoc_utils_data {
>> struct clk *clk_pll_a;
>> struct clk *clk_pll_a_out0;
>> struct clk *clk_cdev1;
>> + struct clk *clk_extern1;
>> int set_baseclock;
>> int set_mclk;
>> };
>>
On 12/7/19 6:26 AM, Dmitry Osipenko wrote:
> 06.12.2019 05:48, Sowjanya Komatineni пишет:
>> Tegra PMC has clk_out_1, clk_out_2, clk_out_3 and blink controls which
>> are currently registered by Tegra clock driver using clk_regiser_mux and
>> clk_register_gate which performs direct Tegra PMC register access.
>>
>> When Tegra PMC is in secure mode, any access from non-secure world will
>> not go through.
>>
>> This patch series adds these Tegra PMC clocks and blink controls to Tegra
>> PMC driver with PMC as clock provider and removed them from Tegra clock
>> driver. This also adds PMC specific clock id's to use in device tree and
>> removed clock ids of PMC clock from Tegra clock driver.
>>
>> clk_out_1 is dedicated for audio mclk and current ASoC driver does not
>> setting extern1 as parent for clk_out_1 and enabling clk_out_1 and
>> currently this is taken care by Tegra clock driver during clock inits
>> and there is no need to enable this during clock init.
>>
>> So, this series also includes patch that updates ASoC driver to take
>> care of configuring parent of mclk and enabling mclk using both extern1
>> and clk_out_1 and updates all device trees to use clk_out_1 from pmc as
>> mclk incase if device tree don't specify assigned-clock-parents.
>>
>> This series also includes a patch for mclk fallback to use extern1
>> when retrieving mclk fails with new device tree which uses pmc provider
>> to have this backward compatible of new DT with old kernels.
>>
>> This series also includes a patch to remove clock ids for these clocks
>> from clock dt-binding as these clocks are not used in any of the existing
>> device tree except in tegra210-smaug.dts and this series includes a patch
>> to update clock provider from tegra_car to pmc in tegra210-smaug.dts for
>> clk_out_2.
>>
>> [v3]: Changes between v2 and v3 are
>> - Removes set parent of clk_out_1_mux to extern1 and enabling
>> extern1 from the clock driver.
>> - Doesn't enable clk_out_1 and blink by default in pmc driver
>> - Updates ASoC driver to take care of audio mclk parent
>> configuration incase if device tree don't specify assigned
>> clock parent properties and enables mclk using both clk_out_1
>> and extern1.
>> - updates all device trees using extern1 as mclk in sound node
>> to use clk_out_1 from pmc.
>> - patch for YAML format pmc dt-binding
>> - Includes v2 feedback
>>
>> [v2]: Changes between v1 and v2 are
>> - v2 includes patches for adding clk_out_1, clk_out_2, clk_out_3,
>> blink controls to Tegra PMC driver and removing clk-tegra-pmc.
>> - feedback related to pmc clocks in Tegra PMC driver from v1
>> - Removed patches for WB0 PLLM overrides and PLLE IDDQ PMC programming
>> by the clock driver using helper functions from Tegra PMC.
>>
>> Note:
>> To use helper functions from PMC driver, PMC early init need to
>> happen prior to using helper functions and these helper functions are
>> for PLLM Override and PLLE IDDQ programming in PMC during PLLM/PLLE
>> clock registration which happen in clock_init prior to Tegra PMC
>> probe.
>> Moving PLLM/PLLE clocks registration to happen after Tegra PMC
>> impacts other clocks EMC, MC and corresponding tegra_emc_init and
>> tegra_mc_init.
>> This implementation of configuring PMC registers thru helper
>> functions in clock driver needs proper changes across PMC, Clock,
>> EMC and MC inits to have it work across all Tegra platforms.
>>
>> Currently PLLM Override is not enabled in the bootloader so proper
>> patches for this fix will be taken care separately.
>>
>> [v1]: v1 includes patches for below fixes.
>> - adding clk_out_1, clk_out_2, clk_out_3, blink controls to Tegra PMC
>> driver and removing clk-tegra-pmc.
>> - updated clock provider from tegra_car to pmc in the device tree
>> tegra210-smaug.dts that uses clk_out_2.
>> - Added helper functions in PMC driver for WB0 PLLM overrides and PLLE
>> IDDQ programming to use by clock driver and updated clock driver to
>> use these helper functions and removed direct PMC access from clock
>> driver and all pmc base address references in clock driver.
>>
>>
>> Sowjanya Komatineni (15):
>> dt-bindings: soc: tegra-pmc: Add Tegra PMC clock bindings
>> dt-bindings: tegra: Convert Tegra PMC bindings to YAML
>> soc: tegra: Add Tegra PMC clock registrations into PMC driver
>> dt-bindings: soc: tegra-pmc: Add id for Tegra PMC blink control
>> soc: pmc: Add blink output clock registration to Tegra PMC
>> clk: tegra: Remove tegra_pmc_clk_init along with clk ids
>> dt-bindings: clock: tegra: Remove pmc clock ids from clock dt-bindings
>> ASoC: tegra: Add audio mclk control through clk_out_1 and extern1
>> ASoC: tegra: Add fallback for audio mclk
>> clk: tegra: Remove extern1 and cdev1 from clocks inittable
>> ARM: dts: tegra: Add clock-cells property to pmc
>
>> arm64: tegra: Add clock-cells property to Tegra PMC node
>> ARM: tegra: Update sound node clocks in device tree
>> arm64: tegra: smaug: Change clk_out_2 provider to pmc
>> ASoC: nau8825: change Tegra clk_out_2 provider from tegra_car to pmc
> Hello Sowjanya,
>
> Something gone wrong with these patches because I didn't receive them
> and don't see them on the ML either.
>
> Also, the list of email correspondents looks a bit too larger. I'm
> pretty sure some of the people do not care much about this series. I
> tend to use script/get_maintainer.pl and then manually pick the relevant
> people for patches.
Not sure what went wrong. I sent this series to all previous mailing
list and inaddition added based on get_maintainers scripts for ASoC and
device tree related.
Will manually pick and reduce mailing list for next series..
On 12/7/19 7:04 AM, Dmitry Osipenko wrote:
> 07.12.2019 17:43, Dmitry Osipenko пишет:
>> 07.12.2019 17:33, Dmitry Osipenko пишет:
>>> 06.12.2019 05:48, Sowjanya Komatineni пишет:
>>>> Current Tegra clock driver registers PMC clocks clk_out_1, clk_out_2,
>>>> clk_out_3 and blink output in tegra_pmc_init() which does direct Tegra
>>>> PMC access during clk_ops and these PMC register read and write access
>>>> will not happen when PMC is in secure mode.
>>>>
>>>> Any direct PMC register access from non-secure world will not go
>>>> through and all the PMC clocks and blink control are done in Tegra PMC
>>>> driver with PMC as clock provider.
>>>>
>>>> This patch removes tegra_pmc_clk_init along with corresponding clk ids
>>>> from Tegra clock driver.
>>>>
>>>> Signed-off-by: Sowjanya Komatineni <[email protected]>
>>>> ---
>>> [snip]
>>>
>>>> @@ -1230,9 +1222,6 @@ static struct tegra_clk_init_table init_table[] __initdata = {
>>>> { TEGRA30_CLK_PLL_A, TEGRA30_CLK_CLK_MAX, 564480000, 1 },
>>>> { TEGRA30_CLK_PLL_A_OUT0, TEGRA30_CLK_CLK_MAX, 11289600, 1 },
>>>> { TEGRA30_CLK_EXTERN1, TEGRA30_CLK_PLL_A_OUT0, 0, 1 },
>>> Perhaps these clocks do not need to be always-enabled?
>>>
>>> [snip]
>>>
>> Also, EXTERN1 parent configuration should be moved to the audio
>> driver/device-tree as well.
> Ah, I missed that it's done in the patch #10.
Yes its done in Patch#10
>
>> Maybe it even makes sense to move the whole configuration, including
>> PLLA. I don't see why clk driver need to do something for the audio driver.
Current ASoC driver already takes care of PLLA rate and enables.
So PLLA init can be removed from clock driver too. I didn't went through
complete audio driver to be confident to remove this.
But PLLA is needed for i2s clock also and currently I2S driver takes
care of only I2S clock rate using PLLA as parent set by clock driver and
clock driver enables PLLA earlier to have it ready by the time both I2S
driver and ASoC driver .
On 12/7/19 8:00 AM, Dmitry Osipenko wrote:
> 07.12.2019 18:53, Dmitry Osipenko пишет:
>> 07.12.2019 18:47, Dmitry Osipenko пишет:
>>> 07.12.2019 17:28, Dmitry Osipenko пишет:
>>>> 06.12.2019 05:48, 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 <[email protected]>
>>>>> ---
>>> [snip]
>>>
>>>>> +
>>>>> +static const struct clk_ops pmc_clk_gate_ops = {
>>>>> + .is_enabled = pmc_clk_is_enabled,
>>>>> + .enable = pmc_clk_enable,
>>>>> + .disable = pmc_clk_disable,
>>>>> +};
>>>> What's the benefit of separating GATE from the MUX?
>>>>
>>>> I think it could be a single clock.
>>> According to TRM:
>>>
>>> 1. GATE and MUX are separate entities.
>>>
>>> 2. GATE is the parent of MUX (see PMC's CLK_OUT paths diagram in TRM).
>>>
>>> 3. PMC doesn't gate EXTPERIPH clock but could "force-enable" it, correct?
>> 4. clk_m_div2/4 are internal PMC OSC dividers and thus these clocks
>> should belong to PMC.
> Also, it should be "osc" and not "clk_m".
I followed the same parents as it were in existing clk-tegra-pmc driver.
Yeah they are wrong and they should be from osc and not clk_m.
Will fix in next version.
On 12/7/19 11:59 AM, Sowjanya Komatineni wrote:
>
> On 12/7/19 8:00 AM, Dmitry Osipenko wrote:
>> 07.12.2019 18:53, Dmitry Osipenko пишет:
>>> 07.12.2019 18:47, Dmitry Osipenko пишет:
>>>> 07.12.2019 17:28, Dmitry Osipenko пишет:
>>>>> 06.12.2019 05:48, 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 <[email protected]>
>>>>>> ---
>>>> [snip]
>>>>
>>>>>> +
>>>>>> +static const struct clk_ops pmc_clk_gate_ops = {
>>>>>> + .is_enabled = pmc_clk_is_enabled,
>>>>>> + .enable = pmc_clk_enable,
>>>>>> + .disable = pmc_clk_disable,
>>>>>> +};
>>>>> What's the benefit of separating GATE from the MUX?
>>>>>
>>>>> I think it could be a single clock.
>>>> According to TRM:
>>>>
>>>> 1. GATE and MUX are separate entities.
>>>>
>>>> 2. GATE is the parent of MUX (see PMC's CLK_OUT paths diagram in TRM).
>>>>
>>>> 3. PMC doesn't gate EXTPERIPH clock but could "force-enable" it,
>>>> correct?
Was following existing clk-tegra-pmc as I am not sure of reason for
having these clocks registered as separate mux and gate clocks.
Yes, PMC clocks can be registered as single clock and can use clk_ops
for set/get parent and enable/disable.
enable/disable of PMC clocks is for force-enable to force the clock to
run regardless of ACCEPT_REQ or INVERT_REQ.
>>> 4. clk_m_div2/4 are internal PMC OSC dividers and thus these clocks
>>> should belong to PMC.
>> Also, it should be "osc" and not "clk_m".
>
> I followed the same parents as it were in existing clk-tegra-pmc driver.
>
> Yeah they are wrong and they should be from osc and not clk_m.
>
> Will fix in next version.
>
07.12.2019 22:35, Sowjanya Komatineni пишет:
>
> On 12/7/19 7:04 AM, Dmitry Osipenko wrote:
>> 07.12.2019 17:43, Dmitry Osipenko пишет:
>>> 07.12.2019 17:33, Dmitry Osipenko пишет:
>>>> 06.12.2019 05:48, Sowjanya Komatineni пишет:
>>>>> Current Tegra clock driver registers PMC clocks clk_out_1, clk_out_2,
>>>>> clk_out_3 and blink output in tegra_pmc_init() which does direct Tegra
>>>>> PMC access during clk_ops and these PMC register read and write access
>>>>> will not happen when PMC is in secure mode.
>>>>>
>>>>> Any direct PMC register access from non-secure world will not go
>>>>> through and all the PMC clocks and blink control are done in Tegra PMC
>>>>> driver with PMC as clock provider.
>>>>>
>>>>> This patch removes tegra_pmc_clk_init along with corresponding clk ids
>>>>> from Tegra clock driver.
>>>>>
>>>>> Signed-off-by: Sowjanya Komatineni <[email protected]>
>>>>> ---
>>>> [snip]
>>>>
>>>>> @@ -1230,9 +1222,6 @@ static struct tegra_clk_init_table
>>>>> init_table[] __initdata = {
>>>>> { TEGRA30_CLK_PLL_A, TEGRA30_CLK_CLK_MAX, 564480000, 1 },
>>>>> { TEGRA30_CLK_PLL_A_OUT0, TEGRA30_CLK_CLK_MAX, 11289600, 1 },
>>>>> { TEGRA30_CLK_EXTERN1, TEGRA30_CLK_PLL_A_OUT0, 0, 1 },
>>>> Perhaps these clocks do not need to be always-enabled?
>>>>
>>>> [snip]
>>>>
>>> Also, EXTERN1 parent configuration should be moved to the audio
>>> driver/device-tree as well.
>> Ah, I missed that it's done in the patch #10.
> Yes its done in Patch#10
>>
>>> Maybe it even makes sense to move the whole configuration, including
>>> PLLA. I don't see why clk driver need to do something for the audio
>>> driver.
>
> Current ASoC driver already takes care of PLLA rate and enables.
>
> So PLLA init can be removed from clock driver too. I didn't went through
> complete audio driver to be confident to remove this.
>
> But PLLA is needed for i2s clock also and currently I2S driver takes
> care of only I2S clock rate using PLLA as parent set by clock driver and
> clock driver enables PLLA earlier to have it ready by the time both I2S
> driver and ASoC driver .
I2S could use assigned-clocks, but probably it's not really necessary
and predefined configuration in the clk driver is good enough.
At least PLLA doesn't need to be always-enabled since audio drivers
enable it when necessary.
On Thu, Dec 05, 2019 at 06:48:49PM -0800, Sowjanya Komatineni wrote:
> mclk is from clk_out_1 which is part of Tegra PMC block and pmc clocks
> are moved to Tegra PMC driver with pmc as clock provider and using pmc
> clock ids.
>
> New device tree uses clk_out_1 from pmc clock provider.
>
> So, this patch adds fallback to extern1 in case of retrieving mclk fails
> to be backward compatible of new device tree with older kernels.
>
> Cc: [email protected]
Why would this need to be a stable fix? Presumably people with stable
kernels are using the old device tree anyway?
07.12.2019 22:20, Sowjanya Komatineni пишет:
>
> On 12/7/19 6:58 AM, Dmitry Osipenko wrote:
>> 06.12.2019 05:48, Sowjanya Komatineni пишет:
>>> Current ASoC driver uses extern1 as cdev1 clock from Tegra30 onwards
>>> through device tree.
>>>
>>> Actual audio mclk is clk_out_1 and to use PLLA for mclk rate control,
>>> need to clk_out_1_mux parent to extern1 and extern1 parent to PLLA_OUT0.
>>>
>>> Currently Tegra clock driver init sets the parents and enables both
>>> clk_out_1 and extern1 clocks. But these clocks parent and enables should
>>> be controlled by ASoC driver.
>>>
>>> Clock parents can be specified in device tree using assigned-clocks
>>> and assigned-clock-parents.
>>>
>>> To enable audio mclk, both clk_out_1 and extern1 clocks need to be
>>> enabled.
>>>
>>> This patch configures parents for clk_out_1 and extern1 clocks if device
>>> tree does not specify clock parents inorder to support old device tree
>>> and controls mclk using both clk_out_1 and extern1 clocks.
>>>
>>> Signed-off-by: Sowjanya Komatineni <[email protected]>
>>> ---
>>> sound/soc/tegra/tegra_asoc_utils.c | 66
>>> ++++++++++++++++++++++++++++++++++++++
>>> sound/soc/tegra/tegra_asoc_utils.h | 1 +
>>> 2 files changed, 67 insertions(+)
>>>
>>> diff --git a/sound/soc/tegra/tegra_asoc_utils.c
>>> b/sound/soc/tegra/tegra_asoc_utils.c
>>> index 536a578e9512..8e3a3740df7c 100644
>>> --- a/sound/soc/tegra/tegra_asoc_utils.c
>>> +++ b/sound/soc/tegra/tegra_asoc_utils.c
>>> @@ -60,6 +60,7 @@ int tegra_asoc_utils_set_rate(struct
>>> tegra_asoc_utils_data *data, int srate,
>>> data->set_mclk = 0;
>>> clk_disable_unprepare(data->clk_cdev1);
>>> + clk_disable_unprepare(data->clk_extern1);
>>> clk_disable_unprepare(data->clk_pll_a_out0);
>>> clk_disable_unprepare(data->clk_pll_a);
>>> @@ -89,6 +90,14 @@ int tegra_asoc_utils_set_rate(struct
>>> tegra_asoc_utils_data *data, int srate,
>>> return err;
>>> }
>>> + if (!IS_ERR_OR_NULL(data->clk_extern1)) {
>>> + err = clk_prepare_enable(data->clk_extern1);
>>> + if (err) {
>>> + dev_err(data->dev, "Can't enable extern1: %d\n", err);
>>> + return err;
>>> + }
>>> + }
>>> +
>>> err = clk_prepare_enable(data->clk_cdev1);
>>> if (err) {
>>> dev_err(data->dev, "Can't enable cdev1: %d\n", err);
>>> @@ -109,6 +118,7 @@ int tegra_asoc_utils_set_ac97_rate(struct
>>> tegra_asoc_utils_data *data)
>>> int err;
>>> clk_disable_unprepare(data->clk_cdev1);
>>> + clk_disable_unprepare(data->clk_extern1);
>>> clk_disable_unprepare(data->clk_pll_a_out0);
>>> clk_disable_unprepare(data->clk_pll_a);
>>> @@ -142,6 +152,14 @@ int tegra_asoc_utils_set_ac97_rate(struct
>>> tegra_asoc_utils_data *data)
>>> return err;
>>> }
>>> + if (!IS_ERR_OR_NULL(data->clk_extern1)) {
>>> + err = clk_prepare_enable(data->clk_extern1);
>>> + if (err) {
>>> + dev_err(data->dev, "Can't enable extern1: %d\n", err);
>>> + return err;
>>> + }
>>> + }
>> Why this is needed given that clk_extern1 is either a child of MCLK or
>> MCLK itself (on T20)? The child clocks are enabled when the parent is
>> enabled.
>
> For T30 and later, clk_extern1 is one of the source for clk_out_1_mux.
> clk_extern1 is in CAR and it has its own gate and mux.
>
> As audio mclk related clocks (clk_out_1, clk_out_1_mux, and extern1) are
> moved into ASoC driver from clock driver
>
> need to enable extern1 gate as well along with clk_out1 for T30 through
> T210.
>
> Just FYI, extern1 enable here happens only when data->clk_extern1 is
> available which is for T30 onwards.
clk_out_1 is the parent of extern1, thus extern1 is enabled by the clk
core whenever clk_out_1 is enabled because data->clk_cdev1=clk_out_1. An
I missing something?
[snip]
08.12.2019 00:36, Sowjanya Komatineni пишет:
>
> On 12/7/19 11:59 AM, Sowjanya Komatineni wrote:
>>
>> On 12/7/19 8:00 AM, Dmitry Osipenko wrote:
>>> 07.12.2019 18:53, Dmitry Osipenko пишет:
>>>> 07.12.2019 18:47, Dmitry Osipenko пишет:
>>>>> 07.12.2019 17:28, Dmitry Osipenko пишет:
>>>>>> 06.12.2019 05:48, 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 <[email protected]>
>>>>>>> ---
>>>>> [snip]
>>>>>
>>>>>>> +
>>>>>>> +static const struct clk_ops pmc_clk_gate_ops = {
>>>>>>> + .is_enabled = pmc_clk_is_enabled,
>>>>>>> + .enable = pmc_clk_enable,
>>>>>>> + .disable = pmc_clk_disable,
>>>>>>> +};
>>>>>> What's the benefit of separating GATE from the MUX?
>>>>>>
>>>>>> I think it could be a single clock.
>>>>> According to TRM:
>>>>>
>>>>> 1. GATE and MUX are separate entities.
>>>>>
>>>>> 2. GATE is the parent of MUX (see PMC's CLK_OUT paths diagram in TRM).
>>>>>
>>>>> 3. PMC doesn't gate EXTPERIPH clock but could "force-enable" it,
>>>>> correct?
>
> Was following existing clk-tegra-pmc as I am not sure of reason for
> having these clocks registered as separate mux and gate clocks.
>
> Yes, PMC clocks can be registered as single clock and can use clk_ops
> for set/get parent and enable/disable.
>
> enable/disable of PMC clocks is for force-enable to force the clock to
> run regardless of ACCEPT_REQ or INVERT_REQ.
>
>>>> 4. clk_m_div2/4 are internal PMC OSC dividers and thus these clocks
>>>> should belong to PMC.
>>> Also, it should be "osc" and not "clk_m".
>>
>> I followed the same parents as it were in existing clk-tegra-pmc driver.
>>
>> Yeah they are wrong and they should be from osc and not clk_m.
>>
>> Will fix in next version.
>>
Could you please describe the full EXTPERIPH clock topology and how the
pinmux configuration is related to it all?
What is internal to the Tegra chip and what are the external outputs?
Is it possible to bypass PMC on T30+ for the EXTPERIPH clocks?
09.12.2019 19:40, Mark Brown пишет:
> On Thu, Dec 05, 2019 at 06:48:49PM -0800, Sowjanya Komatineni wrote:
>> mclk is from clk_out_1 which is part of Tegra PMC block and pmc clocks
>> are moved to Tegra PMC driver with pmc as clock provider and using pmc
>> clock ids.
>>
>> New device tree uses clk_out_1 from pmc clock provider.
>>
>> So, this patch adds fallback to extern1 in case of retrieving mclk fails
>> to be backward compatible of new device tree with older kernels.
>>
>> Cc: [email protected]
>
> Why would this need to be a stable fix? Presumably people with stable
> kernels are using the old device tree anyway?
>
Presumably, yes.
At least Rob Herring is asking to maintain backwards compatibility
because some ditros are using newer device-trees with stable kernels.
I'm personally also tending to use the newer DTB with older kernel
version whenever there is a need to check something using stable kernel.
Perhaps losing sound is not very important, but will be nicer if that
doesn't happen.
On 12/9/19 12:12 PM, Dmitry Osipenko wrote:
> 08.12.2019 00:36, Sowjanya Komatineni пишет:
>> On 12/7/19 11:59 AM, Sowjanya Komatineni wrote:
>>> On 12/7/19 8:00 AM, Dmitry Osipenko wrote:
>>>> 07.12.2019 18:53, Dmitry Osipenko пишет:
>>>>> 07.12.2019 18:47, Dmitry Osipenko пишет:
>>>>>> 07.12.2019 17:28, Dmitry Osipenko пишет:
>>>>>>> 06.12.2019 05:48, 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 <[email protected]>
>>>>>>>> ---
>>>>>> [snip]
>>>>>>
>>>>>>>> +
>>>>>>>> +static const struct clk_ops pmc_clk_gate_ops = {
>>>>>>>> + .is_enabled = pmc_clk_is_enabled,
>>>>>>>> + .enable = pmc_clk_enable,
>>>>>>>> + .disable = pmc_clk_disable,
>>>>>>>> +};
>>>>>>> What's the benefit of separating GATE from the MUX?
>>>>>>>
>>>>>>> I think it could be a single clock.
>>>>>> According to TRM:
>>>>>>
>>>>>> 1. GATE and MUX are separate entities.
>>>>>>
>>>>>> 2. GATE is the parent of MUX (see PMC's CLK_OUT paths diagram in TRM).
>>>>>>
>>>>>> 3. PMC doesn't gate EXTPERIPH clock but could "force-enable" it,
>>>>>> correct?
>> Was following existing clk-tegra-pmc as I am not sure of reason for
>> having these clocks registered as separate mux and gate clocks.
>>
>> Yes, PMC clocks can be registered as single clock and can use clk_ops
>> for set/get parent and enable/disable.
>>
>> enable/disable of PMC clocks is for force-enable to force the clock to
>> run regardless of ACCEPT_REQ or INVERT_REQ.
>>
>>>>> 4. clk_m_div2/4 are internal PMC OSC dividers and thus these clocks
>>>>> should belong to PMC.
>>>> Also, it should be "osc" and not "clk_m".
>>> I followed the same parents as it were in existing clk-tegra-pmc driver.
>>>
>>> Yeah they are wrong and they should be from osc and not clk_m.
>>>
>>> Will fix in next version.
>>>
> Could you please describe the full EXTPERIPH clock topology and how the
> pinmux configuration is related to it all?
>
> What is internal to the Tegra chip and what are the external outputs?
>
> Is it possible to bypass PMC on T30+ for the EXTPERIPH clocks?
PMC CLK1/2/3 possible sources are OSC_DIV1, OSC_DIV2, OSC_DIV4,
EXTPERIPH from CAR.
OSC_DIV1/2/4 are with internal dividers at the OSC Pads
EXTPERIPH is from CAR and it has reset and enable controls along with
clock source selections to choose one of the PLLA_OUT0, CLK_S,
PLLP_OUT0, CLK_M, PLLE_OUT0
So, PMC CLK1/2/4 possible parents are OSC_DIV1, OSC_DIV2, OSC_DIV4, EXTERN.
CLK1/2/3 also has Pinmux to route EXTPERIPH output on to these pins.
When EXTERN output clock is selected for these PMC clocks thru
CLKx_SRC_SEL, output clock is from driver by EXTPERIPH from CAR via
Pinmux logic or driven as per CLKx_SRC_SEL bypassing pinmux based on
CLKx_ACCEPT_REQ bit.
PMC Clock control register has bit CLKx_ACCEPT_REQ
When CLKx_ACCEPT_REQ = 0, output clock driver is from by EXTPERIPH
through the pinmux
When CLKx_ACCEPT_REQ = 1, output clock is based on CLKx_SRC_SEL bits
(OSC_DIV1/2/4 and EXTPERIPH clock bypassing the pinmux)
FORCE_EN bit in PMC CLock control register forces the clock to run
regardless of this.
On Mon, Dec 09, 2019 at 11:31:59PM +0300, Dmitry Osipenko wrote:
> 09.12.2019 19:40, Mark Brown пишет:
> > Why would this need to be a stable fix? Presumably people with stable
> > kernels are using the old device tree anyway?
> At least Rob Herring is asking to maintain backwards compatibility
> because some ditros are using newer device-trees with stable kernels.
You're talking about forwards compatibility not backwards here. Are
those distros actually using LTS kernels?
> I'm personally also tending to use the newer DTB with older kernel
> version whenever there is a need to check something using stable kernel.
> Perhaps losing sound is not very important, but will be nicer if that
> doesn't happen.
That really does sound like a "you broke it, you get all the pieces"
situation TBH... I'd be a lot more comfortable if the stable kernels
were sticking to bugfix only though I do appreciate that they're not
really that any more.
On 12/9/19 12:46 PM, Sowjanya Komatineni wrote:
>
> On 12/9/19 12:12 PM, Dmitry Osipenko wrote:
>> 08.12.2019 00:36, Sowjanya Komatineni пишет:
>>> On 12/7/19 11:59 AM, Sowjanya Komatineni wrote:
>>>> On 12/7/19 8:00 AM, Dmitry Osipenko wrote:
>>>>> 07.12.2019 18:53, Dmitry Osipenko пишет:
>>>>>> 07.12.2019 18:47, Dmitry Osipenko пишет:
>>>>>>> 07.12.2019 17:28, Dmitry Osipenko пишет:
>>>>>>>> 06.12.2019 05:48, 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 <[email protected]>
>>>>>>>>> ---
>>>>>>> [snip]
>>>>>>>
>>>>>>>>> +
>>>>>>>>> +static const struct clk_ops pmc_clk_gate_ops = {
>>>>>>>>> + .is_enabled = pmc_clk_is_enabled,
>>>>>>>>> + .enable = pmc_clk_enable,
>>>>>>>>> + .disable = pmc_clk_disable,
>>>>>>>>> +};
>>>>>>>> What's the benefit of separating GATE from the MUX?
>>>>>>>>
>>>>>>>> I think it could be a single clock.
>>>>>>> According to TRM:
>>>>>>>
>>>>>>> 1. GATE and MUX are separate entities.
>>>>>>>
>>>>>>> 2. GATE is the parent of MUX (see PMC's CLK_OUT paths diagram in
>>>>>>> TRM).
>>>>>>>
>>>>>>> 3. PMC doesn't gate EXTPERIPH clock but could "force-enable" it,
>>>>>>> correct?
>>> Was following existing clk-tegra-pmc as I am not sure of reason for
>>> having these clocks registered as separate mux and gate clocks.
>>>
>>> Yes, PMC clocks can be registered as single clock and can use clk_ops
>>> for set/get parent and enable/disable.
>>>
>>> enable/disable of PMC clocks is for force-enable to force the clock to
>>> run regardless of ACCEPT_REQ or INVERT_REQ.
>>>
>>>>>> 4. clk_m_div2/4 are internal PMC OSC dividers and thus these clocks
>>>>>> should belong to PMC.
>>>>> Also, it should be "osc" and not "clk_m".
>>>> I followed the same parents as it were in existing clk-tegra-pmc
>>>> driver.
>>>>
>>>> Yeah they are wrong and they should be from osc and not clk_m.
>>>>
>>>> Will fix in next version.
>>>>
Reg clk_m_div2/3, they are dividers at OSC pad and not really internal
to PMC block.
current clock driver creates clk_m_div clocks which should actually be
osc_div2/osc_div4 clocks with osc as parent.
There are no clk_m_div2 and clk_m_div4 from clk_m
Will fix this in next version.
>> Could you please describe the full EXTPERIPH clock topology and how the
>> pinmux configuration is related to it all?
>>
>> What is internal to the Tegra chip and what are the external outputs?
>>
>> Is it possible to bypass PMC on T30+ for the EXTPERIPH clocks?
>
> PMC CLK1/2/3 possible sources are OSC_DIV1, OSC_DIV2, OSC_DIV4,
> EXTPERIPH from CAR.
>
> OSC_DIV1/2/4 are with internal dividers at the OSC Pads
>
> EXTPERIPH is from CAR and it has reset and enable controls along with
> clock source selections to choose one of the PLLA_OUT0, CLK_S,
> PLLP_OUT0, CLK_M, PLLE_OUT0
>
> So, PMC CLK1/2/4 possible parents are OSC_DIV1, OSC_DIV2, OSC_DIV4,
> EXTERN.
>
>
> CLK1/2/3 also has Pinmux to route EXTPERIPH output on to these pins.
>
>
> When EXTERN output clock is selected for these PMC clocks thru
> CLKx_SRC_SEL, output clock is from driver by EXTPERIPH from CAR via
> Pinmux logic or driven as per CLKx_SRC_SEL bypassing pinmux based on
> CLKx_ACCEPT_REQ bit.
>
>
> PMC Clock control register has bit CLKx_ACCEPT_REQ
> When CLKx_ACCEPT_REQ = 0, output clock driver is from by EXTPERIPH
> through the pinmux
> When CLKx_ACCEPT_REQ = 1, output clock is based on CLKx_SRC_SEL bits
> (OSC_DIV1/2/4 and EXTPERIPH clock bypassing the pinmux)
>
> FORCE_EN bit in PMC CLock control register forces the clock to run
> regardless of this.
On 12/9/19 12:06 PM, Dmitry Osipenko wrote:
> 07.12.2019 22:20, Sowjanya Komatineni пишет:
>> On 12/7/19 6:58 AM, Dmitry Osipenko wrote:
>>> 06.12.2019 05:48, Sowjanya Komatineni пишет:
>>>> Current ASoC driver uses extern1 as cdev1 clock from Tegra30 onwards
>>>> through device tree.
>>>>
>>>> Actual audio mclk is clk_out_1 and to use PLLA for mclk rate control,
>>>> need to clk_out_1_mux parent to extern1 and extern1 parent to PLLA_OUT0.
>>>>
>>>> Currently Tegra clock driver init sets the parents and enables both
>>>> clk_out_1 and extern1 clocks. But these clocks parent and enables should
>>>> be controlled by ASoC driver.
>>>>
>>>> Clock parents can be specified in device tree using assigned-clocks
>>>> and assigned-clock-parents.
>>>>
>>>> To enable audio mclk, both clk_out_1 and extern1 clocks need to be
>>>> enabled.
>>>>
>>>> This patch configures parents for clk_out_1 and extern1 clocks if device
>>>> tree does not specify clock parents inorder to support old device tree
>>>> and controls mclk using both clk_out_1 and extern1 clocks.
>>>>
>>>> Signed-off-by: Sowjanya Komatineni <[email protected]>
>>>> ---
>>>> sound/soc/tegra/tegra_asoc_utils.c | 66
>>>> ++++++++++++++++++++++++++++++++++++++
>>>> sound/soc/tegra/tegra_asoc_utils.h | 1 +
>>>> 2 files changed, 67 insertions(+)
>>>>
>>>> diff --git a/sound/soc/tegra/tegra_asoc_utils.c
>>>> b/sound/soc/tegra/tegra_asoc_utils.c
>>>> index 536a578e9512..8e3a3740df7c 100644
>>>> --- a/sound/soc/tegra/tegra_asoc_utils.c
>>>> +++ b/sound/soc/tegra/tegra_asoc_utils.c
>>>> @@ -60,6 +60,7 @@ int tegra_asoc_utils_set_rate(struct
>>>> tegra_asoc_utils_data *data, int srate,
>>>> data->set_mclk = 0;
>>>> clk_disable_unprepare(data->clk_cdev1);
>>>> + clk_disable_unprepare(data->clk_extern1);
>>>> clk_disable_unprepare(data->clk_pll_a_out0);
>>>> clk_disable_unprepare(data->clk_pll_a);
>>>> @@ -89,6 +90,14 @@ int tegra_asoc_utils_set_rate(struct
>>>> tegra_asoc_utils_data *data, int srate,
>>>> return err;
>>>> }
>>>> + if (!IS_ERR_OR_NULL(data->clk_extern1)) {
>>>> + err = clk_prepare_enable(data->clk_extern1);
>>>> + if (err) {
>>>> + dev_err(data->dev, "Can't enable extern1: %d\n", err);
>>>> + return err;
>>>> + }
>>>> + }
>>>> +
>>>> err = clk_prepare_enable(data->clk_cdev1);
>>>> if (err) {
>>>> dev_err(data->dev, "Can't enable cdev1: %d\n", err);
>>>> @@ -109,6 +118,7 @@ int tegra_asoc_utils_set_ac97_rate(struct
>>>> tegra_asoc_utils_data *data)
>>>> int err;
>>>> clk_disable_unprepare(data->clk_cdev1);
>>>> + clk_disable_unprepare(data->clk_extern1);
>>>> clk_disable_unprepare(data->clk_pll_a_out0);
>>>> clk_disable_unprepare(data->clk_pll_a);
>>>> @@ -142,6 +152,14 @@ int tegra_asoc_utils_set_ac97_rate(struct
>>>> tegra_asoc_utils_data *data)
>>>> return err;
>>>> }
>>>> + if (!IS_ERR_OR_NULL(data->clk_extern1)) {
>>>> + err = clk_prepare_enable(data->clk_extern1);
>>>> + if (err) {
>>>> + dev_err(data->dev, "Can't enable extern1: %d\n", err);
>>>> + return err;
>>>> + }
>>>> + }
>>> Why this is needed given that clk_extern1 is either a child of MCLK or
>>> MCLK itself (on T20)? The child clocks are enabled when the parent is
>>> enabled.
>> For T30 and later, clk_extern1 is one of the source for clk_out_1_mux.
>> clk_extern1 is in CAR and it has its own gate and mux.
>>
>> As audio mclk related clocks (clk_out_1, clk_out_1_mux, and extern1) are
>> moved into ASoC driver from clock driver
>>
>> need to enable extern1 gate as well along with clk_out1 for T30 through
>> T210.
>>
>> Just FYI, extern1 enable here happens only when data->clk_extern1 is
>> available which is for T30 onwards.
> clk_out_1 is the parent of extern1, thus extern1 is enabled by the clk
> core whenever clk_out_1 is enabled because data->clk_cdev1=clk_out_1. An
> I missing something?
>
> [snip]
extern1 is the parent for clk_out_1. explained extern1 clock path to
clk_out in reply to your comment in other patch of this series.
10.12.2019 02:05, Sowjanya Komatineni пишет:
>
> On 12/9/19 12:06 PM, Dmitry Osipenko wrote:
>> 07.12.2019 22:20, Sowjanya Komatineni пишет:
>>> On 12/7/19 6:58 AM, Dmitry Osipenko wrote:
>>>> 06.12.2019 05:48, Sowjanya Komatineni пишет:
>>>>> Current ASoC driver uses extern1 as cdev1 clock from Tegra30 onwards
>>>>> through device tree.
>>>>>
>>>>> Actual audio mclk is clk_out_1 and to use PLLA for mclk rate control,
>>>>> need to clk_out_1_mux parent to extern1 and extern1 parent to
>>>>> PLLA_OUT0.
>>>>>
>>>>> Currently Tegra clock driver init sets the parents and enables both
>>>>> clk_out_1 and extern1 clocks. But these clocks parent and enables
>>>>> should
>>>>> be controlled by ASoC driver.
>>>>>
>>>>> Clock parents can be specified in device tree using assigned-clocks
>>>>> and assigned-clock-parents.
>>>>>
>>>>> To enable audio mclk, both clk_out_1 and extern1 clocks need to be
>>>>> enabled.
>>>>>
>>>>> This patch configures parents for clk_out_1 and extern1 clocks if
>>>>> device
>>>>> tree does not specify clock parents inorder to support old device tree
>>>>> and controls mclk using both clk_out_1 and extern1 clocks.
>>>>>
>>>>> Signed-off-by: Sowjanya Komatineni <[email protected]>
>>>>> ---
>>>>> sound/soc/tegra/tegra_asoc_utils.c | 66
>>>>> ++++++++++++++++++++++++++++++++++++++
>>>>> sound/soc/tegra/tegra_asoc_utils.h | 1 +
>>>>> 2 files changed, 67 insertions(+)
>>>>>
>>>>> diff --git a/sound/soc/tegra/tegra_asoc_utils.c
>>>>> b/sound/soc/tegra/tegra_asoc_utils.c
>>>>> index 536a578e9512..8e3a3740df7c 100644
>>>>> --- a/sound/soc/tegra/tegra_asoc_utils.c
>>>>> +++ b/sound/soc/tegra/tegra_asoc_utils.c
>>>>> @@ -60,6 +60,7 @@ int tegra_asoc_utils_set_rate(struct
>>>>> tegra_asoc_utils_data *data, int srate,
>>>>> data->set_mclk = 0;
>>>>> clk_disable_unprepare(data->clk_cdev1);
>>>>> + clk_disable_unprepare(data->clk_extern1);
>>>>> clk_disable_unprepare(data->clk_pll_a_out0);
>>>>> clk_disable_unprepare(data->clk_pll_a);
>>>>> @@ -89,6 +90,14 @@ int tegra_asoc_utils_set_rate(struct
>>>>> tegra_asoc_utils_data *data, int srate,
>>>>> return err;
>>>>> }
>>>>> + if (!IS_ERR_OR_NULL(data->clk_extern1)) {
>>>>> + err = clk_prepare_enable(data->clk_extern1);
>>>>> + if (err) {
>>>>> + dev_err(data->dev, "Can't enable extern1: %d\n", err);
>>>>> + return err;
>>>>> + }
>>>>> + }
>>>>> +
>>>>> err = clk_prepare_enable(data->clk_cdev1);
>>>>> if (err) {
>>>>> dev_err(data->dev, "Can't enable cdev1: %d\n", err);
>>>>> @@ -109,6 +118,7 @@ int tegra_asoc_utils_set_ac97_rate(struct
>>>>> tegra_asoc_utils_data *data)
>>>>> int err;
>>>>> clk_disable_unprepare(data->clk_cdev1);
>>>>> + clk_disable_unprepare(data->clk_extern1);
>>>>> clk_disable_unprepare(data->clk_pll_a_out0);
>>>>> clk_disable_unprepare(data->clk_pll_a);
>>>>> @@ -142,6 +152,14 @@ int tegra_asoc_utils_set_ac97_rate(struct
>>>>> tegra_asoc_utils_data *data)
>>>>> return err;
>>>>> }
>>>>> + if (!IS_ERR_OR_NULL(data->clk_extern1)) {
>>>>> + err = clk_prepare_enable(data->clk_extern1);
>>>>> + if (err) {
>>>>> + dev_err(data->dev, "Can't enable extern1: %d\n", err);
>>>>> + return err;
>>>>> + }
>>>>> + }
>>>> Why this is needed given that clk_extern1 is either a child of MCLK or
>>>> MCLK itself (on T20)? The child clocks are enabled when the parent is
>>>> enabled.
>>> For T30 and later, clk_extern1 is one of the source for clk_out_1_mux.
>>> clk_extern1 is in CAR and it has its own gate and mux.
>>>
>>> As audio mclk related clocks (clk_out_1, clk_out_1_mux, and extern1) are
>>> moved into ASoC driver from clock driver
>>>
>>> need to enable extern1 gate as well along with clk_out1 for T30 through
>>> T210.
>>>
>>> Just FYI, extern1 enable here happens only when data->clk_extern1 is
>>> available which is for T30 onwards.
>> clk_out_1 is the parent of extern1, thus extern1 is enabled by the clk
>> core whenever clk_out_1 is enabled because data->clk_cdev1=clk_out_1. An
>> I missing something?
>>
>> [snip]
> extern1 is the parent for clk_out_1. explained extern1 clock path to
> clk_out in reply to your comment in other patch of this series.
Right, I meant extern1 the parent of clk_out_1, sorry for the confusion.
So when clk_out_1 (child) is enabled, extern1 (parent) is enabled as well.
I'll take a closer look at the other email tomorrow.
On 12/9/19 3:12 PM, Dmitry Osipenko wrote:
> 10.12.2019 02:05, Sowjanya Komatineni пишет:
>> On 12/9/19 12:06 PM, Dmitry Osipenko wrote:
>>> 07.12.2019 22:20, Sowjanya Komatineni пишет:
>>>> On 12/7/19 6:58 AM, Dmitry Osipenko wrote:
>>>>> 06.12.2019 05:48, Sowjanya Komatineni пишет:
>>>>>> Current ASoC driver uses extern1 as cdev1 clock from Tegra30 onwards
>>>>>> through device tree.
>>>>>>
>>>>>> Actual audio mclk is clk_out_1 and to use PLLA for mclk rate control,
>>>>>> need to clk_out_1_mux parent to extern1 and extern1 parent to
>>>>>> PLLA_OUT0.
>>>>>>
>>>>>> Currently Tegra clock driver init sets the parents and enables both
>>>>>> clk_out_1 and extern1 clocks. But these clocks parent and enables
>>>>>> should
>>>>>> be controlled by ASoC driver.
>>>>>>
>>>>>> Clock parents can be specified in device tree using assigned-clocks
>>>>>> and assigned-clock-parents.
>>>>>>
>>>>>> To enable audio mclk, both clk_out_1 and extern1 clocks need to be
>>>>>> enabled.
>>>>>>
>>>>>> This patch configures parents for clk_out_1 and extern1 clocks if
>>>>>> device
>>>>>> tree does not specify clock parents inorder to support old device tree
>>>>>> and controls mclk using both clk_out_1 and extern1 clocks.
>>>>>>
>>>>>> Signed-off-by: Sowjanya Komatineni <[email protected]>
>>>>>> ---
>>>>>> sound/soc/tegra/tegra_asoc_utils.c | 66
>>>>>> ++++++++++++++++++++++++++++++++++++++
>>>>>> sound/soc/tegra/tegra_asoc_utils.h | 1 +
>>>>>> 2 files changed, 67 insertions(+)
>>>>>>
>>>>>> diff --git a/sound/soc/tegra/tegra_asoc_utils.c
>>>>>> b/sound/soc/tegra/tegra_asoc_utils.c
>>>>>> index 536a578e9512..8e3a3740df7c 100644
>>>>>> --- a/sound/soc/tegra/tegra_asoc_utils.c
>>>>>> +++ b/sound/soc/tegra/tegra_asoc_utils.c
>>>>>> @@ -60,6 +60,7 @@ int tegra_asoc_utils_set_rate(struct
>>>>>> tegra_asoc_utils_data *data, int srate,
>>>>>> data->set_mclk = 0;
>>>>>> clk_disable_unprepare(data->clk_cdev1);
>>>>>> + clk_disable_unprepare(data->clk_extern1);
>>>>>> clk_disable_unprepare(data->clk_pll_a_out0);
>>>>>> clk_disable_unprepare(data->clk_pll_a);
>>>>>> @@ -89,6 +90,14 @@ int tegra_asoc_utils_set_rate(struct
>>>>>> tegra_asoc_utils_data *data, int srate,
>>>>>> return err;
>>>>>> }
>>>>>> + if (!IS_ERR_OR_NULL(data->clk_extern1)) {
>>>>>> + err = clk_prepare_enable(data->clk_extern1);
>>>>>> + if (err) {
>>>>>> + dev_err(data->dev, "Can't enable extern1: %d\n", err);
>>>>>> + return err;
>>>>>> + }
>>>>>> + }
>>>>>> +
>>>>>> err = clk_prepare_enable(data->clk_cdev1);
>>>>>> if (err) {
>>>>>> dev_err(data->dev, "Can't enable cdev1: %d\n", err);
>>>>>> @@ -109,6 +118,7 @@ int tegra_asoc_utils_set_ac97_rate(struct
>>>>>> tegra_asoc_utils_data *data)
>>>>>> int err;
>>>>>> clk_disable_unprepare(data->clk_cdev1);
>>>>>> + clk_disable_unprepare(data->clk_extern1);
>>>>>> clk_disable_unprepare(data->clk_pll_a_out0);
>>>>>> clk_disable_unprepare(data->clk_pll_a);
>>>>>> @@ -142,6 +152,14 @@ int tegra_asoc_utils_set_ac97_rate(struct
>>>>>> tegra_asoc_utils_data *data)
>>>>>> return err;
>>>>>> }
>>>>>> + if (!IS_ERR_OR_NULL(data->clk_extern1)) {
>>>>>> + err = clk_prepare_enable(data->clk_extern1);
>>>>>> + if (err) {
>>>>>> + dev_err(data->dev, "Can't enable extern1: %d\n", err);
>>>>>> + return err;
>>>>>> + }
>>>>>> + }
>>>>> Why this is needed given that clk_extern1 is either a child of MCLK or
>>>>> MCLK itself (on T20)? The child clocks are enabled when the parent is
>>>>> enabled.
>>>> For T30 and later, clk_extern1 is one of the source for clk_out_1_mux.
>>>> clk_extern1 is in CAR and it has its own gate and mux.
>>>>
>>>> As audio mclk related clocks (clk_out_1, clk_out_1_mux, and extern1) are
>>>> moved into ASoC driver from clock driver
>>>>
>>>> need to enable extern1 gate as well along with clk_out1 for T30 through
>>>> T210.
>>>>
>>>> Just FYI, extern1 enable here happens only when data->clk_extern1 is
>>>> available which is for T30 onwards.
>>> clk_out_1 is the parent of extern1, thus extern1 is enabled by the clk
>>> core whenever clk_out_1 is enabled because data->clk_cdev1=clk_out_1. An
>>> I missing something?
>>>
>>> [snip]
>> extern1 is the parent for clk_out_1. explained extern1 clock path to
>> clk_out in reply to your comment in other patch of this series.
> Right, I meant extern1 the parent of clk_out_1, sorry for the confusion.
> So when clk_out_1 (child) is enabled, extern1 (parent) is enabled as well.
>
> I'll take a closer look at the other email tomorrow.
yes, will remove explicitly enabling extern1 in next version.
On 12/9/19 3:03 PM, Sowjanya Komatineni wrote:
>
> On 12/9/19 12:46 PM, Sowjanya Komatineni wrote:
>>
>> On 12/9/19 12:12 PM, Dmitry Osipenko wrote:
>>> 08.12.2019 00:36, Sowjanya Komatineni пишет:
>>>> On 12/7/19 11:59 AM, Sowjanya Komatineni wrote:
>>>>> On 12/7/19 8:00 AM, Dmitry Osipenko wrote:
>>>>>> 07.12.2019 18:53, Dmitry Osipenko пишет:
>>>>>>> 07.12.2019 18:47, Dmitry Osipenko пишет:
>>>>>>>> 07.12.2019 17:28, Dmitry Osipenko пишет:
>>>>>>>>> 06.12.2019 05:48, 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 <[email protected]>
>>>>>>>>>> ---
>>>>>>>> [snip]
>>>>>>>>
>>>>>>>>>> +
>>>>>>>>>> +static const struct clk_ops pmc_clk_gate_ops = {
>>>>>>>>>> + .is_enabled = pmc_clk_is_enabled,
>>>>>>>>>> + .enable = pmc_clk_enable,
>>>>>>>>>> + .disable = pmc_clk_disable,
>>>>>>>>>> +};
>>>>>>>>> What's the benefit of separating GATE from the MUX?
>>>>>>>>>
>>>>>>>>> I think it could be a single clock.
>>>>>>>> According to TRM:
>>>>>>>>
>>>>>>>> 1. GATE and MUX are separate entities.
>>>>>>>>
>>>>>>>> 2. GATE is the parent of MUX (see PMC's CLK_OUT paths diagram
>>>>>>>> in TRM).
>>>>>>>>
>>>>>>>> 3. PMC doesn't gate EXTPERIPH clock but could "force-enable" it,
>>>>>>>> correct?
>>>> Was following existing clk-tegra-pmc as I am not sure of reason for
>>>> having these clocks registered as separate mux and gate clocks.
>>>>
>>>> Yes, PMC clocks can be registered as single clock and can use clk_ops
>>>> for set/get parent and enable/disable.
>>>>
>>>> enable/disable of PMC clocks is for force-enable to force the clock to
>>>> run regardless of ACCEPT_REQ or INVERT_REQ.
>>>>
>>>>>>> 4. clk_m_div2/4 are internal PMC OSC dividers and thus these clocks
>>>>>>> should belong to PMC.
>>>>>> Also, it should be "osc" and not "clk_m".
>>>>> I followed the same parents as it were in existing clk-tegra-pmc
>>>>> driver.
>>>>>
>>>>> Yeah they are wrong and they should be from osc and not clk_m.
>>>>>
>>>>> Will fix in next version.
>>>>>
> Reg clk_m_div2/3, they are dividers at OSC pad and not really internal
> to PMC block.
>
> current clock driver creates clk_m_div clocks which should actually be
> osc_div2/osc_div4 clocks with osc as parent.
>
> There are no clk_m_div2 and clk_m_div4 from clk_m
>
> Will fix this in next version.
>
>>> Could you please describe the full EXTPERIPH clock topology and how the
>>> pinmux configuration is related to it all?
>>>
>>> What is internal to the Tegra chip and what are the external outputs?
>>>
>>> Is it possible to bypass PMC on T30+ for the EXTPERIPH clocks?
>>
>> PMC CLK1/2/3 possible sources are OSC_DIV1, OSC_DIV2, OSC_DIV4,
>> EXTPERIPH from CAR.
>>
>> OSC_DIV1/2/4 are with internal dividers at the OSC Pads
>>
>> EXTPERIPH is from CAR and it has reset and enable controls along with
>> clock source selections to choose one of the PLLA_OUT0, CLK_S,
>> PLLP_OUT0, CLK_M, PLLE_OUT0
>>
>> So, PMC CLK1/2/4 possible parents are OSC_DIV1, OSC_DIV2, OSC_DIV4,
>> EXTERN.
>>
>>
>> CLK1/2/3 also has Pinmux to route EXTPERIPH output on to these pins.
>>
>>
>> When EXTERN output clock is selected for these PMC clocks thru
>> CLKx_SRC_SEL, output clock is from driver by EXTPERIPH from CAR via
>> Pinmux logic or driven as per CLKx_SRC_SEL bypassing pinmux based on
>> CLKx_ACCEPT_REQ bit.
>>
>>
>> PMC Clock control register has bit CLKx_ACCEPT_REQ
>> When CLKx_ACCEPT_REQ = 0, output clock driver is from by EXTPERIPH
>> through the pinmux
>> When CLKx_ACCEPT_REQ = 1, output clock is based on CLKx_SRC_SEL bits
>> (OSC_DIV1/2/4 and EXTPERIPH clock bypassing the pinmux)
>>
>> FORCE_EN bit in PMC CLock control register forces the clock to run
>> regardless of this.
PMC clock gate is based on the state of CLKx_ACCEPT_REQ and FORCE_EN
like explained above.
CLKx_ACCEPT_REQ is 0 default and FORCE_EN acts as gate to enable/disable
EXTPERIPH clock output to PMC CLK_OUT_1/2/3.
So I believe we need to register as MUX and Gate rather than as a single
clock. Please confirm.
09.12.2019 23:46, Sowjanya Komatineni пишет:
>
> On 12/9/19 12:12 PM, Dmitry Osipenko wrote:
>> 08.12.2019 00:36, Sowjanya Komatineni пишет:
>>> On 12/7/19 11:59 AM, Sowjanya Komatineni wrote:
>>>> On 12/7/19 8:00 AM, Dmitry Osipenko wrote:
>>>>> 07.12.2019 18:53, Dmitry Osipenko пишет:
>>>>>> 07.12.2019 18:47, Dmitry Osipenko пишет:
>>>>>>> 07.12.2019 17:28, Dmitry Osipenko пишет:
>>>>>>>> 06.12.2019 05:48, 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 <[email protected]>
>>>>>>>>> ---
>>>>>>> [snip]
>>>>>>>
>>>>>>>>> +
>>>>>>>>> +static const struct clk_ops pmc_clk_gate_ops = {
>>>>>>>>> + .is_enabled = pmc_clk_is_enabled,
>>>>>>>>> + .enable = pmc_clk_enable,
>>>>>>>>> + .disable = pmc_clk_disable,
>>>>>>>>> +};
>>>>>>>> What's the benefit of separating GATE from the MUX?
>>>>>>>>
>>>>>>>> I think it could be a single clock.
>>>>>>> According to TRM:
>>>>>>>
>>>>>>> 1. GATE and MUX are separate entities.
>>>>>>>
>>>>>>> 2. GATE is the parent of MUX (see PMC's CLK_OUT paths diagram in
>>>>>>> TRM).
>>>>>>>
>>>>>>> 3. PMC doesn't gate EXTPERIPH clock but could "force-enable" it,
>>>>>>> correct?
>>> Was following existing clk-tegra-pmc as I am not sure of reason for
>>> having these clocks registered as separate mux and gate clocks.
>>>
>>> Yes, PMC clocks can be registered as single clock and can use clk_ops
>>> for set/get parent and enable/disable.
>>>
>>> enable/disable of PMC clocks is for force-enable to force the clock to
>>> run regardless of ACCEPT_REQ or INVERT_REQ.
>>>
>>>>>> 4. clk_m_div2/4 are internal PMC OSC dividers and thus these clocks
>>>>>> should belong to PMC.
>>>>> Also, it should be "osc" and not "clk_m".
>>>> I followed the same parents as it were in existing clk-tegra-pmc
>>>> driver.
>>>>
>>>> Yeah they are wrong and they should be from osc and not clk_m.
>>>>
>>>> Will fix in next version.
>>>>
>> Could you please describe the full EXTPERIPH clock topology and how the
>> pinmux configuration is related to it all?
>>
>> What is internal to the Tegra chip and what are the external outputs?
>>
>> Is it possible to bypass PMC on T30+ for the EXTPERIPH clocks?
>
> PMC CLK1/2/3 possible sources are OSC_DIV1, OSC_DIV2, OSC_DIV4,
> EXTPERIPH from CAR.
>
> OSC_DIV1/2/4 are with internal dividers at the OSC Pads
>
> EXTPERIPH is from CAR and it has reset and enable controls along with
> clock source selections to choose one of the PLLA_OUT0, CLK_S,
> PLLP_OUT0, CLK_M, PLLE_OUT0
Are you sure that EXTPERIPH has a reset? What will it reset? Why it's
not documented in TRM?
> So, PMC CLK1/2/4 possible parents are OSC_DIV1, OSC_DIV2, OSC_DIV4, EXTERN.
>
>
> CLK1/2/3 also has Pinmux to route EXTPERIPH output on to these pins.
Could you please clarify what are "these" pins? Perhaps you meant the
EXTERN pin of PMC?
> When EXTERN output clock is selected for these PMC clocks thru
> CLKx_SRC_SEL, output clock is from driver by EXTPERIPH from CAR via
> Pinmux logic or driven as per CLKx_SRC_SEL bypassing pinmux based on
> CLKx_ACCEPT_REQ bit.
>
>
> PMC Clock control register has bit CLKx_ACCEPT_REQ
> When CLKx_ACCEPT_REQ = 0, output clock driver is from by EXTPERIPH
> through the pinmux
> When CLKx_ACCEPT_REQ = 1, output clock is based on CLKx_SRC_SEL bits
> (OSC_DIV1/2/4 and EXTPERIPH clock bypassing the pinmux)
>
> FORCE_EN bit in PMC CLock control register forces the clock to run
> regardless of this.
Okay.
10.12.2019 19:53, Sowjanya Komatineni пишет:
>
> On 12/9/19 3:03 PM, Sowjanya Komatineni wrote:
>>
>> On 12/9/19 12:46 PM, Sowjanya Komatineni wrote:
>>>
>>> On 12/9/19 12:12 PM, Dmitry Osipenko wrote:
>>>> 08.12.2019 00:36, Sowjanya Komatineni пишет:
>>>>> On 12/7/19 11:59 AM, Sowjanya Komatineni wrote:
>>>>>> On 12/7/19 8:00 AM, Dmitry Osipenko wrote:
>>>>>>> 07.12.2019 18:53, Dmitry Osipenko пишет:
>>>>>>>> 07.12.2019 18:47, Dmitry Osipenko пишет:
>>>>>>>>> 07.12.2019 17:28, Dmitry Osipenko пишет:
>>>>>>>>>> 06.12.2019 05:48, 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 <[email protected]>
>>>>>>>>>>> ---
>>>>>>>>> [snip]
>>>>>>>>>
>>>>>>>>>>> +
>>>>>>>>>>> +static const struct clk_ops pmc_clk_gate_ops = {
>>>>>>>>>>> + .is_enabled = pmc_clk_is_enabled,
>>>>>>>>>>> + .enable = pmc_clk_enable,
>>>>>>>>>>> + .disable = pmc_clk_disable,
>>>>>>>>>>> +};
>>>>>>>>>> What's the benefit of separating GATE from the MUX?
>>>>>>>>>>
>>>>>>>>>> I think it could be a single clock.
>>>>>>>>> According to TRM:
>>>>>>>>>
>>>>>>>>> 1. GATE and MUX are separate entities.
>>>>>>>>>
>>>>>>>>> 2. GATE is the parent of MUX (see PMC's CLK_OUT paths diagram
>>>>>>>>> in TRM).
>>>>>>>>>
>>>>>>>>> 3. PMC doesn't gate EXTPERIPH clock but could "force-enable" it,
>>>>>>>>> correct?
>>>>> Was following existing clk-tegra-pmc as I am not sure of reason for
>>>>> having these clocks registered as separate mux and gate clocks.
>>>>>
>>>>> Yes, PMC clocks can be registered as single clock and can use clk_ops
>>>>> for set/get parent and enable/disable.
>>>>>
>>>>> enable/disable of PMC clocks is for force-enable to force the clock to
>>>>> run regardless of ACCEPT_REQ or INVERT_REQ.
>>>>>
>>>>>>>> 4. clk_m_div2/4 are internal PMC OSC dividers and thus these clocks
>>>>>>>> should belong to PMC.
>>>>>>> Also, it should be "osc" and not "clk_m".
>>>>>> I followed the same parents as it were in existing clk-tegra-pmc
>>>>>> driver.
>>>>>>
>>>>>> Yeah they are wrong and they should be from osc and not clk_m.
>>>>>>
>>>>>> Will fix in next version.
>>>>>>
>> Reg clk_m_div2/3, they are dividers at OSC pad and not really internal
>> to PMC block.
>>
>> current clock driver creates clk_m_div clocks which should actually be
>> osc_div2/osc_div4 clocks with osc as parent.
>>
>> There are no clk_m_div2 and clk_m_div4 from clk_m
>>
>> Will fix this in next version.
>>
>>>> Could you please describe the full EXTPERIPH clock topology and how the
>>>> pinmux configuration is related to it all?
>>>>
>>>> What is internal to the Tegra chip and what are the external outputs?
>>>>
>>>> Is it possible to bypass PMC on T30+ for the EXTPERIPH clocks?
>>>
>>> PMC CLK1/2/3 possible sources are OSC_DIV1, OSC_DIV2, OSC_DIV4,
>>> EXTPERIPH from CAR.
>>>
>>> OSC_DIV1/2/4 are with internal dividers at the OSC Pads
>>>
>>> EXTPERIPH is from CAR and it has reset and enable controls along with
>>> clock source selections to choose one of the PLLA_OUT0, CLK_S,
>>> PLLP_OUT0, CLK_M, PLLE_OUT0
>>>
>>> So, PMC CLK1/2/4 possible parents are OSC_DIV1, OSC_DIV2, OSC_DIV4,
>>> EXTERN.
>>>
>>>
>>> CLK1/2/3 also has Pinmux to route EXTPERIPH output on to these pins.
>>>
>>>
>>> When EXTERN output clock is selected for these PMC clocks thru
>>> CLKx_SRC_SEL, output clock is from driver by EXTPERIPH from CAR via
>>> Pinmux logic or driven as per CLKx_SRC_SEL bypassing pinmux based on
>>> CLKx_ACCEPT_REQ bit.
>>>
>>>
>>> PMC Clock control register has bit CLKx_ACCEPT_REQ
>>> When CLKx_ACCEPT_REQ = 0, output clock driver is from by EXTPERIPH
>>> through the pinmux
>>> When CLKx_ACCEPT_REQ = 1, output clock is based on CLKx_SRC_SEL bits
>>> (OSC_DIV1/2/4 and EXTPERIPH clock bypassing the pinmux)
>>>
>>> FORCE_EN bit in PMC CLock control register forces the clock to run
>>> regardless of this.
>
> PMC clock gate is based on the state of CLKx_ACCEPT_REQ and FORCE_EN
> like explained above.
>
> CLKx_ACCEPT_REQ is 0 default and FORCE_EN acts as gate to enable/disable
> EXTPERIPH clock output to PMC CLK_OUT_1/2/3.
[and to enable OSC as well]
> So I believe we need to register as MUX and Gate rather than as a single
> clock. Please confirm.
1. The force-enabling is applied to both OSC and EXTERN sources of
PMC_CLK_OUT_x by PMC at once.
2. Both of PMC's force-enabling and OSC/EXTERN selection is internal to PMC.
Should be better to define it as a single "pmc_clk_out_x". I don't see
any good reasons for differentiating PMC's Gate from the MUX, it's a
single hardware unit from a point of view of the rest of the system.
Peter, do you have any objections?
09.12.2019 23:47, Mark Brown пишет:
> On Mon, Dec 09, 2019 at 11:31:59PM +0300, Dmitry Osipenko wrote:
>> 09.12.2019 19:40, Mark Brown пишет:
>
>>> Why would this need to be a stable fix? Presumably people with stable
>>> kernels are using the old device tree anyway?
>
>> At least Rob Herring is asking to maintain backwards compatibility
>> because some ditros are using newer device-trees with stable kernels.
>
> You're talking about forwards compatibility not backwards here. Are
> those distros actually using LTS kernels?
I think openSUSE Leap could be one of those distros that use LTS kernel
with newer device-trees, but that's not 100%. Maybe Rob could help
clarifying that.
>> I'm personally also tending to use the newer DTB with older kernel
>> version whenever there is a need to check something using stable kernel.
>> Perhaps losing sound is not very important, but will be nicer if that
>> doesn't happen.
>
> That really does sound like a "you broke it, you get all the pieces"
> situation TBH... I'd be a lot more comfortable if the stable kernels
> were sticking to bugfix only though I do appreciate that they're not
> really that any more.
In some cases it could be painful to maintain device-tree compatibility
for platforms like NVIDIA Tegra SoCs because hardware wasn't modeled
correctly from the start.
I agree that people should use relevant device-trees. It's quite a lot
of hassle to care about compatibility for platforms that are permanently
in a development state. It could be more reasonable to go through the
pain if kernel required a full-featured device tree for every SoC from
the start.
But maybe Tegra / device-tree maintainers have a different opinion.
IIUC, device-trees are meant to be stable and software-agnostic, at
least that was the case not so long time ago and I don't think that this
premise changed.
10.12.2019 20:48, Sowjanya Komatineni пишет:
>
> On 12/10/19 9:41 AM, Dmitry Osipenko wrote:
>> 09.12.2019 23:46, Sowjanya Komatineni пишет:
>>> On 12/9/19 12:12 PM, Dmitry Osipenko wrote:
>>>> 08.12.2019 00:36, Sowjanya Komatineni пишет:
>>>>> On 12/7/19 11:59 AM, Sowjanya Komatineni wrote:
>>>>>> On 12/7/19 8:00 AM, Dmitry Osipenko wrote:
>>>>>>> 07.12.2019 18:53, Dmitry Osipenko пишет:
>>>>>>>> 07.12.2019 18:47, Dmitry Osipenko пишет:
>>>>>>>>> 07.12.2019 17:28, Dmitry Osipenko пишет:
>>>>>>>>>> 06.12.2019 05:48, 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 <[email protected]>
>>>>>>>>>>> ---
>>>>>>>>> [snip]
>>>>>>>>>
>>>>>>>>>>> +
>>>>>>>>>>> +static const struct clk_ops pmc_clk_gate_ops = {
>>>>>>>>>>> + .is_enabled = pmc_clk_is_enabled,
>>>>>>>>>>> + .enable = pmc_clk_enable,
>>>>>>>>>>> + .disable = pmc_clk_disable,
>>>>>>>>>>> +};
>>>>>>>>>> What's the benefit of separating GATE from the MUX?
>>>>>>>>>>
>>>>>>>>>> I think it could be a single clock.
>>>>>>>>> According to TRM:
>>>>>>>>>
>>>>>>>>> 1. GATE and MUX are separate entities.
>>>>>>>>>
>>>>>>>>> 2. GATE is the parent of MUX (see PMC's CLK_OUT paths diagram in
>>>>>>>>> TRM).
>>>>>>>>>
>>>>>>>>> 3. PMC doesn't gate EXTPERIPH clock but could "force-enable" it,
>>>>>>>>> correct?
>>>>> Was following existing clk-tegra-pmc as I am not sure of reason for
>>>>> having these clocks registered as separate mux and gate clocks.
>>>>>
>>>>> Yes, PMC clocks can be registered as single clock and can use clk_ops
>>>>> for set/get parent and enable/disable.
>>>>>
>>>>> enable/disable of PMC clocks is for force-enable to force the clock to
>>>>> run regardless of ACCEPT_REQ or INVERT_REQ.
>>>>>
>>>>>>>> 4. clk_m_div2/4 are internal PMC OSC dividers and thus these clocks
>>>>>>>> should belong to PMC.
>>>>>>> Also, it should be "osc" and not "clk_m".
>>>>>> I followed the same parents as it were in existing clk-tegra-pmc
>>>>>> driver.
>>>>>>
>>>>>> Yeah they are wrong and they should be from osc and not clk_m.
>>>>>>
>>>>>> Will fix in next version.
>>>>>>
>>>> Could you please describe the full EXTPERIPH clock topology and how the
>>>> pinmux configuration is related to it all?
>>>>
>>>> What is internal to the Tegra chip and what are the external outputs?
>>>>
>>>> Is it possible to bypass PMC on T30+ for the EXTPERIPH clocks?
>>> PMC CLK1/2/3 possible sources are OSC_DIV1, OSC_DIV2, OSC_DIV4,
>>> EXTPERIPH from CAR.
>>>
>>> OSC_DIV1/2/4 are with internal dividers at the OSC Pads
>>>
>>> EXTPERIPH is from CAR and it has reset and enable controls along with
>>> clock source selections to choose one of the PLLA_OUT0, CLK_S,
>>> PLLP_OUT0, CLK_M, PLLE_OUT0
>> Are you sure that EXTPERIPH has a reset? What will it reset? Why it's
>> not documented in TRM?
> Yes, Extperiph1/2/3 has RST part of CAR RST_DEVICES_V bits 24/25/26
Are these bits not documented in a public TRMs? I checked
T30/114/124/210 TRMs and CLK_RST_CONTROLLER_RST_DEVICES_V_0 doesn't have
those bits in the docs.
>>> So, PMC CLK1/2/4 possible parents are OSC_DIV1, OSC_DIV2, OSC_DIV4, EXTERN.
>>>
>>>
>>> CLK1/2/3 also has Pinmux to route EXTPERIPH output on to these pins.
>> Could you please clarify what are "these" pins? Perhaps you meant the
>> EXTERN pin of PMC?
> By CLK1/2/3 pins, I am referring to CLK_OUT_1/2/3 pins from Tegra
I see now what you meant, thanks.
[snip}
On Tue, Dec 10, 2019 at 09:24:43PM +0300, Dmitry Osipenko wrote:
> In some cases it could be painful to maintain device-tree compatibility
> for platforms like NVIDIA Tegra SoCs because hardware wasn't modeled
> correctly from the start.
> I agree that people should use relevant device-trees. It's quite a lot
> of hassle to care about compatibility for platforms that are permanently
> in a development state. It could be more reasonable to go through the
> pain if kernel required a full-featured device tree for every SoC from
> the start.
We absolutely should support the newer kernel with older device tree
case, what's less clear to me is the new device tree with old kernel
which is applying LTS updates case. That does seem incredibly
specialist - I'd honestly never heard of people doing that before this
thread.
On 12/10/19 10:30 AM, Dmitry Osipenko wrote:
> 10.12.2019 20:48, Sowjanya Komatineni пишет:
>> On 12/10/19 9:41 AM, Dmitry Osipenko wrote:
>>> 09.12.2019 23:46, Sowjanya Komatineni пишет:
>>>> On 12/9/19 12:12 PM, Dmitry Osipenko wrote:
>>>>> 08.12.2019 00:36, Sowjanya Komatineni пишет:
>>>>>> On 12/7/19 11:59 AM, Sowjanya Komatineni wrote:
>>>>>>> On 12/7/19 8:00 AM, Dmitry Osipenko wrote:
>>>>>>>> 07.12.2019 18:53, Dmitry Osipenko пишет:
>>>>>>>>> 07.12.2019 18:47, Dmitry Osipenko пишет:
>>>>>>>>>> 07.12.2019 17:28, Dmitry Osipenko пишет:
>>>>>>>>>>> 06.12.2019 05:48, 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 <[email protected]>
>>>>>>>>>>>> ---
>>>>>>>>>> [snip]
>>>>>>>>>>
>>>>>>>>>>>> +
>>>>>>>>>>>> +static const struct clk_ops pmc_clk_gate_ops = {
>>>>>>>>>>>> + .is_enabled = pmc_clk_is_enabled,
>>>>>>>>>>>> + .enable = pmc_clk_enable,
>>>>>>>>>>>> + .disable = pmc_clk_disable,
>>>>>>>>>>>> +};
>>>>>>>>>>> What's the benefit of separating GATE from the MUX?
>>>>>>>>>>>
>>>>>>>>>>> I think it could be a single clock.
>>>>>>>>>> According to TRM:
>>>>>>>>>>
>>>>>>>>>> 1. GATE and MUX are separate entities.
>>>>>>>>>>
>>>>>>>>>> 2. GATE is the parent of MUX (see PMC's CLK_OUT paths diagram in
>>>>>>>>>> TRM).
>>>>>>>>>>
>>>>>>>>>> 3. PMC doesn't gate EXTPERIPH clock but could "force-enable" it,
>>>>>>>>>> correct?
>>>>>> Was following existing clk-tegra-pmc as I am not sure of reason for
>>>>>> having these clocks registered as separate mux and gate clocks.
>>>>>>
>>>>>> Yes, PMC clocks can be registered as single clock and can use clk_ops
>>>>>> for set/get parent and enable/disable.
>>>>>>
>>>>>> enable/disable of PMC clocks is for force-enable to force the clock to
>>>>>> run regardless of ACCEPT_REQ or INVERT_REQ.
>>>>>>
>>>>>>>>> 4. clk_m_div2/4 are internal PMC OSC dividers and thus these clocks
>>>>>>>>> should belong to PMC.
>>>>>>>> Also, it should be "osc" and not "clk_m".
>>>>>>> I followed the same parents as it were in existing clk-tegra-pmc
>>>>>>> driver.
>>>>>>>
>>>>>>> Yeah they are wrong and they should be from osc and not clk_m.
>>>>>>>
>>>>>>> Will fix in next version.
>>>>>>>
>>>>> Could you please describe the full EXTPERIPH clock topology and how the
>>>>> pinmux configuration is related to it all?
>>>>>
>>>>> What is internal to the Tegra chip and what are the external outputs?
>>>>>
>>>>> Is it possible to bypass PMC on T30+ for the EXTPERIPH clocks?
>>>> PMC CLK1/2/3 possible sources are OSC_DIV1, OSC_DIV2, OSC_DIV4,
>>>> EXTPERIPH from CAR.
>>>>
>>>> OSC_DIV1/2/4 are with internal dividers at the OSC Pads
>>>>
>>>> EXTPERIPH is from CAR and it has reset and enable controls along with
>>>> clock source selections to choose one of the PLLA_OUT0, CLK_S,
>>>> PLLP_OUT0, CLK_M, PLLE_OUT0
>>> Are you sure that EXTPERIPH has a reset? What will it reset? Why it's
>>> not documented in TRM?
>> Yes, Extperiph1/2/3 has RST part of CAR RST_DEVICES_V bits 24/25/26
> Are these bits not documented in a public TRMs? I checked
> T30/114/124/210 TRMs and CLK_RST_CONTROLLER_RST_DEVICES_V_0 doesn't have
> those bits in the docs.
>
Yeah these bits are missing in all Tegra TRM docs. Will request for
having EXTPERIPH reset bits to be updated in TRM...
>>>> So, PMC CLK1/2/4 possible parents are OSC_DIV1, OSC_DIV2, OSC_DIV4, EXTERN.
>>>>
>>>>
>>>> CLK1/2/3 also has Pinmux to route EXTPERIPH output on to these pins.
>>> Could you please clarify what are "these" pins? Perhaps you meant the
>>> EXTERN pin of PMC?
>> By CLK1/2/3 pins, I am referring to CLK_OUT_1/2/3 pins from Tegra
> I see now what you meant, thanks.
>
> [snip}
10.12.2019 22:18, Sowjanya Komatineni пишет:
>
> On 12/10/19 10:30 AM, Dmitry Osipenko wrote:
>> 10.12.2019 20:48, Sowjanya Komatineni пишет:
>>> On 12/10/19 9:41 AM, Dmitry Osipenko wrote:
>>>> 09.12.2019 23:46, Sowjanya Komatineni пишет:
>>>>> On 12/9/19 12:12 PM, Dmitry Osipenko wrote:
>>>>>> 08.12.2019 00:36, Sowjanya Komatineni пишет:
>>>>>>> On 12/7/19 11:59 AM, Sowjanya Komatineni wrote:
>>>>>>>> On 12/7/19 8:00 AM, Dmitry Osipenko wrote:
>>>>>>>>> 07.12.2019 18:53, Dmitry Osipenko пишет:
>>>>>>>>>> 07.12.2019 18:47, Dmitry Osipenko пишет:
>>>>>>>>>>> 07.12.2019 17:28, Dmitry Osipenko пишет:
>>>>>>>>>>>> 06.12.2019 05:48, 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 <[email protected]>
>>>>>>>>>>>>> ---
>>>>>>>>>>> [snip]
>>>>>>>>>>>
>>>>>>>>>>>>> +
>>>>>>>>>>>>> +static const struct clk_ops pmc_clk_gate_ops = {
>>>>>>>>>>>>> + .is_enabled = pmc_clk_is_enabled,
>>>>>>>>>>>>> + .enable = pmc_clk_enable,
>>>>>>>>>>>>> + .disable = pmc_clk_disable,
>>>>>>>>>>>>> +};
>>>>>>>>>>>> What's the benefit of separating GATE from the MUX?
>>>>>>>>>>>>
>>>>>>>>>>>> I think it could be a single clock.
>>>>>>>>>>> According to TRM:
>>>>>>>>>>>
>>>>>>>>>>> 1. GATE and MUX are separate entities.
>>>>>>>>>>>
>>>>>>>>>>> 2. GATE is the parent of MUX (see PMC's CLK_OUT paths diagram in
>>>>>>>>>>> TRM).
>>>>>>>>>>>
>>>>>>>>>>> 3. PMC doesn't gate EXTPERIPH clock but could "force-enable" it,
>>>>>>>>>>> correct?
>>>>>>> Was following existing clk-tegra-pmc as I am not sure of reason for
>>>>>>> having these clocks registered as separate mux and gate clocks.
>>>>>>>
>>>>>>> Yes, PMC clocks can be registered as single clock and can use
>>>>>>> clk_ops
>>>>>>> for set/get parent and enable/disable.
>>>>>>>
>>>>>>> enable/disable of PMC clocks is for force-enable to force the
>>>>>>> clock to
>>>>>>> run regardless of ACCEPT_REQ or INVERT_REQ.
>>>>>>>
>>>>>>>>>> 4. clk_m_div2/4 are internal PMC OSC dividers and thus these
>>>>>>>>>> clocks
>>>>>>>>>> should belong to PMC.
>>>>>>>>> Also, it should be "osc" and not "clk_m".
>>>>>>>> I followed the same parents as it were in existing clk-tegra-pmc
>>>>>>>> driver.
>>>>>>>>
>>>>>>>> Yeah they are wrong and they should be from osc and not clk_m.
>>>>>>>>
>>>>>>>> Will fix in next version.
>>>>>>>>
>>>>>> Could you please describe the full EXTPERIPH clock topology and
>>>>>> how the
>>>>>> pinmux configuration is related to it all?
>>>>>>
>>>>>> What is internal to the Tegra chip and what are the external outputs?
>>>>>>
>>>>>> Is it possible to bypass PMC on T30+ for the EXTPERIPH clocks?
>>>>> PMC CLK1/2/3 possible sources are OSC_DIV1, OSC_DIV2, OSC_DIV4,
>>>>> EXTPERIPH from CAR.
>>>>>
>>>>> OSC_DIV1/2/4 are with internal dividers at the OSC Pads
>>>>>
>>>>> EXTPERIPH is from CAR and it has reset and enable controls along with
>>>>> clock source selections to choose one of the PLLA_OUT0, CLK_S,
>>>>> PLLP_OUT0, CLK_M, PLLE_OUT0
>>>> Are you sure that EXTPERIPH has a reset? What will it reset? Why it's
>>>> not documented in TRM?
>>> Yes, Extperiph1/2/3 has RST part of CAR RST_DEVICES_V bits 24/25/26
>> Are these bits not documented in a public TRMs? I checked
>> T30/114/124/210 TRMs and CLK_RST_CONTROLLER_RST_DEVICES_V_0 doesn't have
>> those bits in the docs.
>>
> Yeah these bits are missing in all Tegra TRM docs. Will request for
> having EXTPERIPH reset bits to be updated in TRM...
Thanks
On 12/10/19 9:41 AM, Dmitry Osipenko wrote:
> 10.12.2019 19:53, Sowjanya Komatineni пишет:
>> On 12/9/19 3:03 PM, Sowjanya Komatineni wrote:
>>> On 12/9/19 12:46 PM, Sowjanya Komatineni wrote:
>>>> On 12/9/19 12:12 PM, Dmitry Osipenko wrote:
>>>>> 08.12.2019 00:36, Sowjanya Komatineni пишет:
>>>>>> On 12/7/19 11:59 AM, Sowjanya Komatineni wrote:
>>>>>>> On 12/7/19 8:00 AM, Dmitry Osipenko wrote:
>>>>>>>> 07.12.2019 18:53, Dmitry Osipenko пишет:
>>>>>>>>> 07.12.2019 18:47, Dmitry Osipenko пишет:
>>>>>>>>>> 07.12.2019 17:28, Dmitry Osipenko пишет:
>>>>>>>>>>> 06.12.2019 05:48, 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 <[email protected]>
>>>>>>>>>>>> ---
>>>>>>>>>> [snip]
>>>>>>>>>>
>>>>>>>>>>>> +
>>>>>>>>>>>> +static const struct clk_ops pmc_clk_gate_ops = {
>>>>>>>>>>>> + .is_enabled = pmc_clk_is_enabled,
>>>>>>>>>>>> + .enable = pmc_clk_enable,
>>>>>>>>>>>> + .disable = pmc_clk_disable,
>>>>>>>>>>>> +};
>>>>>>>>>>> What's the benefit of separating GATE from the MUX?
>>>>>>>>>>>
>>>>>>>>>>> I think it could be a single clock.
>>>>>>>>>> According to TRM:
>>>>>>>>>>
>>>>>>>>>> 1. GATE and MUX are separate entities.
>>>>>>>>>>
>>>>>>>>>> 2. GATE is the parent of MUX (see PMC's CLK_OUT paths diagram
>>>>>>>>>> in TRM).
>>>>>>>>>>
>>>>>>>>>> 3. PMC doesn't gate EXTPERIPH clock but could "force-enable" it,
>>>>>>>>>> correct?
>>>>>> Was following existing clk-tegra-pmc as I am not sure of reason for
>>>>>> having these clocks registered as separate mux and gate clocks.
>>>>>>
>>>>>> Yes, PMC clocks can be registered as single clock and can use clk_ops
>>>>>> for set/get parent and enable/disable.
>>>>>>
>>>>>> enable/disable of PMC clocks is for force-enable to force the clock to
>>>>>> run regardless of ACCEPT_REQ or INVERT_REQ.
>>>>>>
>>>>>>>>> 4. clk_m_div2/4 are internal PMC OSC dividers and thus these clocks
>>>>>>>>> should belong to PMC.
>>>>>>>> Also, it should be "osc" and not "clk_m".
>>>>>>> I followed the same parents as it were in existing clk-tegra-pmc
>>>>>>> driver.
>>>>>>>
>>>>>>> Yeah they are wrong and they should be from osc and not clk_m.
>>>>>>>
>>>>>>> Will fix in next version.
>>>>>>>
>>> Reg clk_m_div2/3, they are dividers at OSC pad and not really internal
>>> to PMC block.
>>>
>>> current clock driver creates clk_m_div clocks which should actually be
>>> osc_div2/osc_div4 clocks with osc as parent.
>>>
>>> There are no clk_m_div2 and clk_m_div4 from clk_m
>>>
>>> Will fix this in next version.
>>>
>>>>> Could you please describe the full EXTPERIPH clock topology and how the
>>>>> pinmux configuration is related to it all?
>>>>>
>>>>> What is internal to the Tegra chip and what are the external outputs?
>>>>>
>>>>> Is it possible to bypass PMC on T30+ for the EXTPERIPH clocks?
>>>> PMC CLK1/2/3 possible sources are OSC_DIV1, OSC_DIV2, OSC_DIV4,
>>>> EXTPERIPH from CAR.
>>>>
>>>> OSC_DIV1/2/4 are with internal dividers at the OSC Pads
>>>>
>>>> EXTPERIPH is from CAR and it has reset and enable controls along with
>>>> clock source selections to choose one of the PLLA_OUT0, CLK_S,
>>>> PLLP_OUT0, CLK_M, PLLE_OUT0
>>>>
>>>> So, PMC CLK1/2/4 possible parents are OSC_DIV1, OSC_DIV2, OSC_DIV4,
>>>> EXTERN.
>>>>
>>>>
>>>> CLK1/2/3 also has Pinmux to route EXTPERIPH output on to these pins.
>>>>
>>>>
>>>> When EXTERN output clock is selected for these PMC clocks thru
>>>> CLKx_SRC_SEL, output clock is from driver by EXTPERIPH from CAR via
>>>> Pinmux logic or driven as per CLKx_SRC_SEL bypassing pinmux based on
>>>> CLKx_ACCEPT_REQ bit.
>>>>
>>>>
>>>> PMC Clock control register has bit CLKx_ACCEPT_REQ
>>>> When CLKx_ACCEPT_REQ = 0, output clock driver is from by EXTPERIPH
>>>> through the pinmux
>>>> When CLKx_ACCEPT_REQ = 1, output clock is based on CLKx_SRC_SEL bits
>>>> (OSC_DIV1/2/4 and EXTPERIPH clock bypassing the pinmux)
>>>>
>>>> FORCE_EN bit in PMC CLock control register forces the clock to run
>>>> regardless of this.
>> PMC clock gate is based on the state of CLKx_ACCEPT_REQ and FORCE_EN
>> like explained above.
>>
>> CLKx_ACCEPT_REQ is 0 default and FORCE_EN acts as gate to enable/disable
>> EXTPERIPH clock output to PMC CLK_OUT_1/2/3.
> [and to enable OSC as well]
>
>> So I believe we need to register as MUX and Gate rather than as a single
>> clock. Please confirm.
> 1. The force-enabling is applied to both OSC and EXTERN sources of
> PMC_CLK_OUT_x by PMC at once.
>
> 2. Both of PMC's force-enabling and OSC/EXTERN selection is internal to PMC.
>
> Should be better to define it as a single "pmc_clk_out_x". I don't see
> any good reasons for differentiating PMC's Gate from the MUX, it's a
> single hardware unit from a point of view of the rest of the system.
>
> Peter, do you have any objections?
We added fallback option for audio mclk and also added check for
assigned-clock-parents dt property in audio driver and if its not then
we do parent init configuration in audio driver.
Current clock driver creates 2 separate clocks clk_out_1_mux and
clk_out_1 for each pmc clock in clock driver and uses extern1 as parent
to clk_out_1_mux and clk_out_1_mux is parent to clk_out_1.
With change of registering each pmc clock as a single clock, when we do
parent init assignment in audio driver when assigned-clock-properties
are not used in DT (as we removed parent inits for extern and clk_outs
from clock driver), we should still try to get clock based on
clk_out_1_mux as parent assignment of extern1 is for clk_out_1_mux as
per existing clock tree.
clk_out_1_mux clock retrieve will fail with this change of single clock
when any new platform device tree doesn't specify assigned-clock-parents
properties and tegra_asoc_utils_init fails.
With single clock, extern1 is the parent for clk_out_1 and with separate
clocks for mux and gate, extern1 is the parent for clk_out_1_mux.
On Tue, Dec 10, 2019 at 08:41:56PM +0300, Dmitry Osipenko wrote:
..
> >
> > PMC clock gate is based on the state of CLKx_ACCEPT_REQ and FORCE_EN
> > like explained above.
> >
> > CLKx_ACCEPT_REQ is 0 default and FORCE_EN acts as gate to enable/disable
> > EXTPERIPH clock output to PMC CLK_OUT_1/2/3.
>
> [and to enable OSC as well]
>
> > So I believe we need to register as MUX and Gate rather than as a single
> > clock. Please confirm.
>
> 1. The force-enabling is applied to both OSC and EXTERN sources of
> PMC_CLK_OUT_x by PMC at once.
>
> 2. Both of PMC's force-enabling and OSC/EXTERN selection is internal to PMC.
>
> Should be better to define it as a single "pmc_clk_out_x". I don't see
> any good reasons for differentiating PMC's Gate from the MUX, it's a
> single hardware unit from a point of view of the rest of the system.
>
> Peter, do you have any objections?
The reason to have separate gate and mux clocks, is to preserve compatibility
with existing users.
Otherwise the current users would need to figure out if there's a
single clock or 2 clocks to configure. I don't think adding that code in
each user is worth it only to have a sligthly nicer modelling of the
hardware.
Cheers,
Peter.
On 12/10/19 5:06 PM, Sowjanya Komatineni wrote:
>
> On 12/10/19 9:41 AM, Dmitry Osipenko wrote:
>> 10.12.2019 19:53, Sowjanya Komatineni пишет:
>>> On 12/9/19 3:03 PM, Sowjanya Komatineni wrote:
>>>> On 12/9/19 12:46 PM, Sowjanya Komatineni wrote:
>>>>> On 12/9/19 12:12 PM, Dmitry Osipenko wrote:
>>>>>> 08.12.2019 00:36, Sowjanya Komatineni пишет:
>>>>>>> On 12/7/19 11:59 AM, Sowjanya Komatineni wrote:
>>>>>>>> On 12/7/19 8:00 AM, Dmitry Osipenko wrote:
>>>>>>>>> 07.12.2019 18:53, Dmitry Osipenko пишет:
>>>>>>>>>> 07.12.2019 18:47, Dmitry Osipenko пишет:
>>>>>>>>>>> 07.12.2019 17:28, Dmitry Osipenko пишет:
>>>>>>>>>>>> 06.12.2019 05:48, 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 <[email protected]>
>>>>>>>>>>>>> ---
>>>>>>>>>>> [snip]
>>>>>>>>>>>
>>>>>>>>>>>>> +
>>>>>>>>>>>>> +static const struct clk_ops pmc_clk_gate_ops = {
>>>>>>>>>>>>> + .is_enabled = pmc_clk_is_enabled,
>>>>>>>>>>>>> + .enable = pmc_clk_enable,
>>>>>>>>>>>>> + .disable = pmc_clk_disable,
>>>>>>>>>>>>> +};
>>>>>>>>>>>> What's the benefit of separating GATE from the MUX?
>>>>>>>>>>>>
>>>>>>>>>>>> I think it could be a single clock.
>>>>>>>>>>> According to TRM:
>>>>>>>>>>>
>>>>>>>>>>> 1. GATE and MUX are separate entities.
>>>>>>>>>>>
>>>>>>>>>>> 2. GATE is the parent of MUX (see PMC's CLK_OUT paths diagram
>>>>>>>>>>> in TRM).
>>>>>>>>>>>
>>>>>>>>>>> 3. PMC doesn't gate EXTPERIPH clock but could "force-enable"
>>>>>>>>>>> it,
>>>>>>>>>>> correct?
>>>>>>> Was following existing clk-tegra-pmc as I am not sure of reason for
>>>>>>> having these clocks registered as separate mux and gate clocks.
>>>>>>>
>>>>>>> Yes, PMC clocks can be registered as single clock and can use
>>>>>>> clk_ops
>>>>>>> for set/get parent and enable/disable.
>>>>>>>
>>>>>>> enable/disable of PMC clocks is for force-enable to force the
>>>>>>> clock to
>>>>>>> run regardless of ACCEPT_REQ or INVERT_REQ.
>>>>>>>
>>>>>>>>>> 4. clk_m_div2/4 are internal PMC OSC dividers and thus these
>>>>>>>>>> clocks
>>>>>>>>>> should belong to PMC.
>>>>>>>>> Also, it should be "osc" and not "clk_m".
>>>>>>>> I followed the same parents as it were in existing clk-tegra-pmc
>>>>>>>> driver.
>>>>>>>>
>>>>>>>> Yeah they are wrong and they should be from osc and not clk_m.
>>>>>>>>
>>>>>>>> Will fix in next version.
>>>>>>>>
>>>> Reg clk_m_div2/3, they are dividers at OSC pad and not really internal
>>>> to PMC block.
>>>>
>>>> current clock driver creates clk_m_div clocks which should actually be
>>>> osc_div2/osc_div4 clocks with osc as parent.
>>>>
>>>> There are no clk_m_div2 and clk_m_div4 from clk_m
>>>>
>>>> Will fix this in next version.
>>>>
>>>>>> Could you please describe the full EXTPERIPH clock topology and
>>>>>> how the
>>>>>> pinmux configuration is related to it all?
>>>>>>
>>>>>> What is internal to the Tegra chip and what are the external
>>>>>> outputs?
>>>>>>
>>>>>> Is it possible to bypass PMC on T30+ for the EXTPERIPH clocks?
>>>>> PMC CLK1/2/3 possible sources are OSC_DIV1, OSC_DIV2, OSC_DIV4,
>>>>> EXTPERIPH from CAR.
>>>>>
>>>>> OSC_DIV1/2/4 are with internal dividers at the OSC Pads
>>>>>
>>>>> EXTPERIPH is from CAR and it has reset and enable controls along with
>>>>> clock source selections to choose one of the PLLA_OUT0, CLK_S,
>>>>> PLLP_OUT0, CLK_M, PLLE_OUT0
>>>>>
>>>>> So, PMC CLK1/2/4 possible parents are OSC_DIV1, OSC_DIV2, OSC_DIV4,
>>>>> EXTERN.
>>>>>
>>>>>
>>>>> CLK1/2/3 also has Pinmux to route EXTPERIPH output on to these pins.
>>>>>
>>>>>
>>>>> When EXTERN output clock is selected for these PMC clocks thru
>>>>> CLKx_SRC_SEL, output clock is from driver by EXTPERIPH from CAR via
>>>>> Pinmux logic or driven as per CLKx_SRC_SEL bypassing pinmux based on
>>>>> CLKx_ACCEPT_REQ bit.
>>>>>
>>>>>
>>>>> PMC Clock control register has bit CLKx_ACCEPT_REQ
>>>>> When CLKx_ACCEPT_REQ = 0, output clock driver is from by EXTPERIPH
>>>>> through the pinmux
>>>>> When CLKx_ACCEPT_REQ = 1, output clock is based on CLKx_SRC_SEL bits
>>>>> (OSC_DIV1/2/4 and EXTPERIPH clock bypassing the pinmux)
>>>>>
>>>>> FORCE_EN bit in PMC CLock control register forces the clock to run
>>>>> regardless of this.
>>> PMC clock gate is based on the state of CLKx_ACCEPT_REQ and FORCE_EN
>>> like explained above.
>>>
>>> CLKx_ACCEPT_REQ is 0 default and FORCE_EN acts as gate to
>>> enable/disable
>>> EXTPERIPH clock output to PMC CLK_OUT_1/2/3.
>> [and to enable OSC as well]
>>
>>> So I believe we need to register as MUX and Gate rather than as a
>>> single
>>> clock. Please confirm.
>> 1. The force-enabling is applied to both OSC and EXTERN sources of
>> PMC_CLK_OUT_x by PMC at once.
>>
>> 2. Both of PMC's force-enabling and OSC/EXTERN selection is internal
>> to PMC.
>>
>> Should be better to define it as a single "pmc_clk_out_x". I don't see
>> any good reasons for differentiating PMC's Gate from the MUX, it's a
>> single hardware unit from a point of view of the rest of the system.
>>
>> Peter, do you have any objections?
>
> We added fallback option for audio mclk and also added check for
> assigned-clock-parents dt property in audio driver and if its not then
> we do parent init configuration in audio driver.
>
> Current clock driver creates 2 separate clocks clk_out_1_mux and
> clk_out_1 for each pmc clock in clock driver and uses extern1 as
> parent to clk_out_1_mux and clk_out_1_mux is parent to clk_out_1.
>
> With change of registering each pmc clock as a single clock, when we
> do parent init assignment in audio driver when
> assigned-clock-properties are not used in DT (as we removed parent
> inits for extern and clk_outs from clock driver), we should still try
> to get clock based on clk_out_1_mux as parent assignment of extern1 is
> for clk_out_1_mux as per existing clock tree.
>
> clk_out_1_mux clock retrieve will fail with this change of single
> clock when any new platform device tree doesn't specify
> assigned-clock-parents properties and tegra_asoc_utils_init fails.
>
> With single clock, extern1 is the parent for clk_out_1 and with
> separate clocks for mux and gate, extern1 is the parent for
> clk_out_1_mux.
If we move to single clock now, it need one more additional fallback
implementation in audio driver during parent configuration as
clk_out_1_mux will not be there with single clock change and old/current
kernel has it as it uses separate clocks for pmc mux and gate.
Also, with single clock for both PMC mux and gate now, new DT should use
extern1 as parent to CLK_OUT_1 as CLK_OUT_1_MUX will not be there old
PMC dt-bindings has separate clocks for MUX (CLK_OUT_1_MUX) and gate
(CLK_OUT_1)
DT bindings will not be compatible b/w old and new changes if we move to
Single PMC clock now.
Should we go with same separate clocks to have it compatible to avoid
all this?
11.12.2019 21:50, Sowjanya Komatineni пишет:
>
> On 12/10/19 5:06 PM, Sowjanya Komatineni wrote:
>>
>> On 12/10/19 9:41 AM, Dmitry Osipenko wrote:
>>> 10.12.2019 19:53, Sowjanya Komatineni пишет:
>>>> On 12/9/19 3:03 PM, Sowjanya Komatineni wrote:
>>>>> On 12/9/19 12:46 PM, Sowjanya Komatineni wrote:
>>>>>> On 12/9/19 12:12 PM, Dmitry Osipenko wrote:
>>>>>>> 08.12.2019 00:36, Sowjanya Komatineni пишет:
>>>>>>>> On 12/7/19 11:59 AM, Sowjanya Komatineni wrote:
>>>>>>>>> On 12/7/19 8:00 AM, Dmitry Osipenko wrote:
>>>>>>>>>> 07.12.2019 18:53, Dmitry Osipenko пишет:
>>>>>>>>>>> 07.12.2019 18:47, Dmitry Osipenko пишет:
>>>>>>>>>>>> 07.12.2019 17:28, Dmitry Osipenko пишет:
>>>>>>>>>>>>> 06.12.2019 05:48, 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 <[email protected]>
>>>>>>>>>>>>>> ---
>>>>>>>>>>>> [snip]
>>>>>>>>>>>>
>>>>>>>>>>>>>> +
>>>>>>>>>>>>>> +static const struct clk_ops pmc_clk_gate_ops = {
>>>>>>>>>>>>>> + .is_enabled = pmc_clk_is_enabled,
>>>>>>>>>>>>>> + .enable = pmc_clk_enable,
>>>>>>>>>>>>>> + .disable = pmc_clk_disable,
>>>>>>>>>>>>>> +};
>>>>>>>>>>>>> What's the benefit of separating GATE from the MUX?
>>>>>>>>>>>>>
>>>>>>>>>>>>> I think it could be a single clock.
>>>>>>>>>>>> According to TRM:
>>>>>>>>>>>>
>>>>>>>>>>>> 1. GATE and MUX are separate entities.
>>>>>>>>>>>>
>>>>>>>>>>>> 2. GATE is the parent of MUX (see PMC's CLK_OUT paths diagram
>>>>>>>>>>>> in TRM).
>>>>>>>>>>>>
>>>>>>>>>>>> 3. PMC doesn't gate EXTPERIPH clock but could "force-enable"
>>>>>>>>>>>> it,
>>>>>>>>>>>> correct?
>>>>>>>> Was following existing clk-tegra-pmc as I am not sure of reason for
>>>>>>>> having these clocks registered as separate mux and gate clocks.
>>>>>>>>
>>>>>>>> Yes, PMC clocks can be registered as single clock and can use
>>>>>>>> clk_ops
>>>>>>>> for set/get parent and enable/disable.
>>>>>>>>
>>>>>>>> enable/disable of PMC clocks is for force-enable to force the
>>>>>>>> clock to
>>>>>>>> run regardless of ACCEPT_REQ or INVERT_REQ.
>>>>>>>>
>>>>>>>>>>> 4. clk_m_div2/4 are internal PMC OSC dividers and thus these
>>>>>>>>>>> clocks
>>>>>>>>>>> should belong to PMC.
>>>>>>>>>> Also, it should be "osc" and not "clk_m".
>>>>>>>>> I followed the same parents as it were in existing clk-tegra-pmc
>>>>>>>>> driver.
>>>>>>>>>
>>>>>>>>> Yeah they are wrong and they should be from osc and not clk_m.
>>>>>>>>>
>>>>>>>>> Will fix in next version.
>>>>>>>>>
>>>>> Reg clk_m_div2/3, they are dividers at OSC pad and not really internal
>>>>> to PMC block.
>>>>>
>>>>> current clock driver creates clk_m_div clocks which should actually be
>>>>> osc_div2/osc_div4 clocks with osc as parent.
>>>>>
>>>>> There are no clk_m_div2 and clk_m_div4 from clk_m
>>>>>
>>>>> Will fix this in next version.
>>>>>
>>>>>>> Could you please describe the full EXTPERIPH clock topology and
>>>>>>> how the
>>>>>>> pinmux configuration is related to it all?
>>>>>>>
>>>>>>> What is internal to the Tegra chip and what are the external
>>>>>>> outputs?
>>>>>>>
>>>>>>> Is it possible to bypass PMC on T30+ for the EXTPERIPH clocks?
>>>>>> PMC CLK1/2/3 possible sources are OSC_DIV1, OSC_DIV2, OSC_DIV4,
>>>>>> EXTPERIPH from CAR.
>>>>>>
>>>>>> OSC_DIV1/2/4 are with internal dividers at the OSC Pads
>>>>>>
>>>>>> EXTPERIPH is from CAR and it has reset and enable controls along with
>>>>>> clock source selections to choose one of the PLLA_OUT0, CLK_S,
>>>>>> PLLP_OUT0, CLK_M, PLLE_OUT0
>>>>>>
>>>>>> So, PMC CLK1/2/4 possible parents are OSC_DIV1, OSC_DIV2, OSC_DIV4,
>>>>>> EXTERN.
>>>>>>
>>>>>>
>>>>>> CLK1/2/3 also has Pinmux to route EXTPERIPH output on to these pins.
>>>>>>
>>>>>>
>>>>>> When EXTERN output clock is selected for these PMC clocks thru
>>>>>> CLKx_SRC_SEL, output clock is from driver by EXTPERIPH from CAR via
>>>>>> Pinmux logic or driven as per CLKx_SRC_SEL bypassing pinmux based on
>>>>>> CLKx_ACCEPT_REQ bit.
>>>>>>
>>>>>>
>>>>>> PMC Clock control register has bit CLKx_ACCEPT_REQ
>>>>>> When CLKx_ACCEPT_REQ = 0, output clock driver is from by EXTPERIPH
>>>>>> through the pinmux
>>>>>> When CLKx_ACCEPT_REQ = 1, output clock is based on CLKx_SRC_SEL bits
>>>>>> (OSC_DIV1/2/4 and EXTPERIPH clock bypassing the pinmux)
>>>>>>
>>>>>> FORCE_EN bit in PMC CLock control register forces the clock to run
>>>>>> regardless of this.
>>>> PMC clock gate is based on the state of CLKx_ACCEPT_REQ and FORCE_EN
>>>> like explained above.
>>>>
>>>> CLKx_ACCEPT_REQ is 0 default and FORCE_EN acts as gate to
>>>> enable/disable
>>>> EXTPERIPH clock output to PMC CLK_OUT_1/2/3.
>>> [and to enable OSC as well]
>>>
>>>> So I believe we need to register as MUX and Gate rather than as a
>>>> single
>>>> clock. Please confirm.
>>> 1. The force-enabling is applied to both OSC and EXTERN sources of
>>> PMC_CLK_OUT_x by PMC at once.
>>>
>>> 2. Both of PMC's force-enabling and OSC/EXTERN selection is internal
>>> to PMC.
>>>
>>> Should be better to define it as a single "pmc_clk_out_x". I don't see
>>> any good reasons for differentiating PMC's Gate from the MUX, it's a
>>> single hardware unit from a point of view of the rest of the system.
>>>
>>> Peter, do you have any objections?
>>
>> We added fallback option for audio mclk and also added check for
>> assigned-clock-parents dt property in audio driver and if its not then
>> we do parent init configuration in audio driver.
>>
>> Current clock driver creates 2 separate clocks clk_out_1_mux and
>> clk_out_1 for each pmc clock in clock driver and uses extern1 as
>> parent to clk_out_1_mux and clk_out_1_mux is parent to clk_out_1.
>>
>> With change of registering each pmc clock as a single clock, when we
>> do parent init assignment in audio driver when
>> assigned-clock-properties are not used in DT (as we removed parent
>> inits for extern and clk_outs from clock driver), we should still try
>> to get clock based on clk_out_1_mux as parent assignment of extern1 is
>> for clk_out_1_mux as per existing clock tree.
>>
>> clk_out_1_mux clock retrieve will fail with this change of single
>> clock when any new platform device tree doesn't specify
>> assigned-clock-parents properties and tegra_asoc_utils_init fails.
You made the PMC/CaR changes before the audio changes, the clk_out_1_mux
won't exist for the audio driver patches.
If you care about bisect-ability of the patches, then the clock and
audio changes need to be done in a single patch. But I don't think that
it's worthwhile.
>> With single clock, extern1 is the parent for clk_out_1 and with
>> separate clocks for mux and gate, extern1 is the parent for
>> clk_out_1_mux.
>
> If we move to single clock now, it need one more additional fallback
> implementation in audio driver during parent configuration as
> clk_out_1_mux will not be there with single clock change and old/current
> kernel has it as it uses separate clocks for pmc mux and gate.
Why additional fallback? Additional to what?
> Also, with single clock for both PMC mux and gate now, new DT should use
> extern1 as parent to CLK_OUT_1 as CLK_OUT_1_MUX will not be there old
> PMC dt-bindings has separate clocks for MUX (CLK_OUT_1_MUX) and gate
> (CLK_OUT_1)
>
> DT bindings will not be compatible b/w old and new changes if we move to
> Single PMC clock now.
Sorry, I don't understand what you're meaning by the "new changes".
> Should we go with same separate clocks to have it compatible to avoid
> all this?
>
11.12.2019 18:10, Peter De Schrijver пишет:
> On Tue, Dec 10, 2019 at 08:41:56PM +0300, Dmitry Osipenko wrote:
>
> ..
>
>>>
>>> PMC clock gate is based on the state of CLKx_ACCEPT_REQ and FORCE_EN
>>> like explained above.
>>>
>>> CLKx_ACCEPT_REQ is 0 default and FORCE_EN acts as gate to enable/disable
>>> EXTPERIPH clock output to PMC CLK_OUT_1/2/3.
>>
>> [and to enable OSC as well]
>>
>>> So I believe we need to register as MUX and Gate rather than as a single
>>> clock. Please confirm.
>>
>> 1. The force-enabling is applied to both OSC and EXTERN sources of
>> PMC_CLK_OUT_x by PMC at once.
>>
>> 2. Both of PMC's force-enabling and OSC/EXTERN selection is internal to PMC.
>>
>> Should be better to define it as a single "pmc_clk_out_x". I don't see
>> any good reasons for differentiating PMC's Gate from the MUX, it's a
>> single hardware unit from a point of view of the rest of the system.
>>
>> Peter, do you have any objections?
>
> The reason to have separate gate and mux clocks, is to preserve compatibility
> with existing users.
> Otherwise the current users would need to figure out if there's a
> single clock or 2 clocks to configure. I don't think adding that code in
> each user is worth it only to have a sligthly nicer modelling of the
> hardware.
Could you please clarify what do you mean by the "existing users"?
AFAIK, nothing in kernel uses mux clocks.
10.12.2019 21:59, Mark Brown пишет:
> On Tue, Dec 10, 2019 at 09:24:43PM +0300, Dmitry Osipenko wrote:
>
>> In some cases it could be painful to maintain device-tree compatibility
>> for platforms like NVIDIA Tegra SoCs because hardware wasn't modeled
>> correctly from the start.
>
>> I agree that people should use relevant device-trees. It's quite a lot
>> of hassle to care about compatibility for platforms that are permanently
>> in a development state. It could be more reasonable to go through the
>> pain if kernel required a full-featured device tree for every SoC from
>> the start.
>
> We absolutely should support the newer kernel with older device tree
> case, what's less clear to me is the new device tree with old kernel
> which is applying LTS updates case. That does seem incredibly
> specialist - I'd honestly never heard of people doing that before this
> thread.
>
There was a precedent in the past [1].
[1] https://lkml.org/lkml/2018/8/20/497
On 12/11/19 5:39 PM, Dmitry Osipenko wrote:
> 11.12.2019 21:50, Sowjanya Komatineni пишет:
>> On 12/10/19 5:06 PM, Sowjanya Komatineni wrote:
>>> On 12/10/19 9:41 AM, Dmitry Osipenko wrote:
>>>> 10.12.2019 19:53, Sowjanya Komatineni пишет:
>>>>> On 12/9/19 3:03 PM, Sowjanya Komatineni wrote:
>>>>>> On 12/9/19 12:46 PM, Sowjanya Komatineni wrote:
>>>>>>> On 12/9/19 12:12 PM, Dmitry Osipenko wrote:
>>>>>>>> 08.12.2019 00:36, Sowjanya Komatineni пишет:
>>>>>>>>> On 12/7/19 11:59 AM, Sowjanya Komatineni wrote:
>>>>>>>>>> On 12/7/19 8:00 AM, Dmitry Osipenko wrote:
>>>>>>>>>>> 07.12.2019 18:53, Dmitry Osipenko пишет:
>>>>>>>>>>>> 07.12.2019 18:47, Dmitry Osipenko пишет:
>>>>>>>>>>>>> 07.12.2019 17:28, Dmitry Osipenko пишет:
>>>>>>>>>>>>>> 06.12.2019 05:48, 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 <[email protected]>
>>>>>>>>>>>>>>> ---
>>>>>>>>>>>>> [snip]
>>>>>>>>>>>>>
>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>> +static const struct clk_ops pmc_clk_gate_ops = {
>>>>>>>>>>>>>>> + .is_enabled = pmc_clk_is_enabled,
>>>>>>>>>>>>>>> + .enable = pmc_clk_enable,
>>>>>>>>>>>>>>> + .disable = pmc_clk_disable,
>>>>>>>>>>>>>>> +};
>>>>>>>>>>>>>> What's the benefit of separating GATE from the MUX?
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> I think it could be a single clock.
>>>>>>>>>>>>> According to TRM:
>>>>>>>>>>>>>
>>>>>>>>>>>>> 1. GATE and MUX are separate entities.
>>>>>>>>>>>>>
>>>>>>>>>>>>> 2. GATE is the parent of MUX (see PMC's CLK_OUT paths diagram
>>>>>>>>>>>>> in TRM).
>>>>>>>>>>>>>
>>>>>>>>>>>>> 3. PMC doesn't gate EXTPERIPH clock but could "force-enable"
>>>>>>>>>>>>> it,
>>>>>>>>>>>>> correct?
>>>>>>>>> Was following existing clk-tegra-pmc as I am not sure of reason for
>>>>>>>>> having these clocks registered as separate mux and gate clocks.
>>>>>>>>>
>>>>>>>>> Yes, PMC clocks can be registered as single clock and can use
>>>>>>>>> clk_ops
>>>>>>>>> for set/get parent and enable/disable.
>>>>>>>>>
>>>>>>>>> enable/disable of PMC clocks is for force-enable to force the
>>>>>>>>> clock to
>>>>>>>>> run regardless of ACCEPT_REQ or INVERT_REQ.
>>>>>>>>>
>>>>>>>>>>>> 4. clk_m_div2/4 are internal PMC OSC dividers and thus these
>>>>>>>>>>>> clocks
>>>>>>>>>>>> should belong to PMC.
>>>>>>>>>>> Also, it should be "osc" and not "clk_m".
>>>>>>>>>> I followed the same parents as it were in existing clk-tegra-pmc
>>>>>>>>>> driver.
>>>>>>>>>>
>>>>>>>>>> Yeah they are wrong and they should be from osc and not clk_m.
>>>>>>>>>>
>>>>>>>>>> Will fix in next version.
>>>>>>>>>>
>>>>>> Reg clk_m_div2/3, they are dividers at OSC pad and not really internal
>>>>>> to PMC block.
>>>>>>
>>>>>> current clock driver creates clk_m_div clocks which should actually be
>>>>>> osc_div2/osc_div4 clocks with osc as parent.
>>>>>>
>>>>>> There are no clk_m_div2 and clk_m_div4 from clk_m
>>>>>>
>>>>>> Will fix this in next version.
>>>>>>
>>>>>>>> Could you please describe the full EXTPERIPH clock topology and
>>>>>>>> how the
>>>>>>>> pinmux configuration is related to it all?
>>>>>>>>
>>>>>>>> What is internal to the Tegra chip and what are the external
>>>>>>>> outputs?
>>>>>>>>
>>>>>>>> Is it possible to bypass PMC on T30+ for the EXTPERIPH clocks?
>>>>>>> PMC CLK1/2/3 possible sources are OSC_DIV1, OSC_DIV2, OSC_DIV4,
>>>>>>> EXTPERIPH from CAR.
>>>>>>>
>>>>>>> OSC_DIV1/2/4 are with internal dividers at the OSC Pads
>>>>>>>
>>>>>>> EXTPERIPH is from CAR and it has reset and enable controls along with
>>>>>>> clock source selections to choose one of the PLLA_OUT0, CLK_S,
>>>>>>> PLLP_OUT0, CLK_M, PLLE_OUT0
>>>>>>>
>>>>>>> So, PMC CLK1/2/4 possible parents are OSC_DIV1, OSC_DIV2, OSC_DIV4,
>>>>>>> EXTERN.
>>>>>>>
>>>>>>>
>>>>>>> CLK1/2/3 also has Pinmux to route EXTPERIPH output on to these pins.
>>>>>>>
>>>>>>>
>>>>>>> When EXTERN output clock is selected for these PMC clocks thru
>>>>>>> CLKx_SRC_SEL, output clock is from driver by EXTPERIPH from CAR via
>>>>>>> Pinmux logic or driven as per CLKx_SRC_SEL bypassing pinmux based on
>>>>>>> CLKx_ACCEPT_REQ bit.
>>>>>>>
>>>>>>>
>>>>>>> PMC Clock control register has bit CLKx_ACCEPT_REQ
>>>>>>> When CLKx_ACCEPT_REQ = 0, output clock driver is from by EXTPERIPH
>>>>>>> through the pinmux
>>>>>>> When CLKx_ACCEPT_REQ = 1, output clock is based on CLKx_SRC_SEL bits
>>>>>>> (OSC_DIV1/2/4 and EXTPERIPH clock bypassing the pinmux)
>>>>>>>
>>>>>>> FORCE_EN bit in PMC CLock control register forces the clock to run
>>>>>>> regardless of this.
>>>>> PMC clock gate is based on the state of CLKx_ACCEPT_REQ and FORCE_EN
>>>>> like explained above.
>>>>>
>>>>> CLKx_ACCEPT_REQ is 0 default and FORCE_EN acts as gate to
>>>>> enable/disable
>>>>> EXTPERIPH clock output to PMC CLK_OUT_1/2/3.
>>>> [and to enable OSC as well]
>>>>
>>>>> So I believe we need to register as MUX and Gate rather than as a
>>>>> single
>>>>> clock. Please confirm.
>>>> 1. The force-enabling is applied to both OSC and EXTERN sources of
>>>> PMC_CLK_OUT_x by PMC at once.
>>>>
>>>> 2. Both of PMC's force-enabling and OSC/EXTERN selection is internal
>>>> to PMC.
>>>>
>>>> Should be better to define it as a single "pmc_clk_out_x". I don't see
>>>> any good reasons for differentiating PMC's Gate from the MUX, it's a
>>>> single hardware unit from a point of view of the rest of the system.
>>>>
>>>> Peter, do you have any objections?
>>> We added fallback option for audio mclk and also added check for
>>> assigned-clock-parents dt property in audio driver and if its not then
>>> we do parent init configuration in audio driver.
>>>
>>> Current clock driver creates 2 separate clocks clk_out_1_mux and
>>> clk_out_1 for each pmc clock in clock driver and uses extern1 as
>>> parent to clk_out_1_mux and clk_out_1_mux is parent to clk_out_1.
>>>
>>> With change of registering each pmc clock as a single clock, when we
>>> do parent init assignment in audio driver when
>>> assigned-clock-properties are not used in DT (as we removed parent
>>> inits for extern and clk_outs from clock driver), we should still try
>>> to get clock based on clk_out_1_mux as parent assignment of extern1 is
>>> for clk_out_1_mux as per existing clock tree.
>>>
>>> clk_out_1_mux clock retrieve will fail with this change of single
>>> clock when any new platform device tree doesn't specify
>>> assigned-clock-parents properties and tegra_asoc_utils_init fails.
> You made the PMC/CaR changes before the audio changes, the clk_out_1_mux
> won't exist for the audio driver patches.
>
> If you care about bisect-ability of the patches, then the clock and
> audio changes need to be done in a single patch. But I don't think that
> it's worthwhile.
>
>>> With single clock, extern1 is the parent for clk_out_1 and with
>>> separate clocks for mux and gate, extern1 is the parent for
>>> clk_out_1_mux.
>> If we move to single clock now, it need one more additional fallback
>> implementation in audio driver during parent configuration as
>> clk_out_1_mux will not be there with single clock change and old/current
>> kernel has it as it uses separate clocks for pmc mux and gate.
> Why additional fallback? Additional to what?
>
>> Also, with single clock for both PMC mux and gate now, new DT should use
>> extern1 as parent to CLK_OUT_1 as CLK_OUT_1_MUX will not be there old
>> PMC dt-bindings has separate clocks for MUX (CLK_OUT_1_MUX) and gate
>> (CLK_OUT_1)
>>
>> DT bindings will not be compatible b/w old and new changes if we move to
>> Single PMC clock now.
> Sorry, I don't understand what you're meaning by the "new changes".
>
>> Should we go with same separate clocks to have it compatible to avoid
>> all this?
>>
The reason we added mclk fallback and also for doing parent
configuration based on presence of assigned-clock-parents property is to
have old dt compatible with new kernel and also to have new dt
compatible with old kernel.
So the point I was mentioning is to have new DT to work with old kernel,
setting extern1 as parent to clk_out_1 (with single pmc clock) through
assigned-clock-parents in DT will fail as old kernel has mux and gate as
separate clocks and parent configuration is for mux clock (clk_out_1_mux)
On 12/11/19 7:45 PM, Sowjanya Komatineni wrote:
>
> On 12/11/19 5:39 PM, Dmitry Osipenko wrote:
>> 11.12.2019 21:50, Sowjanya Komatineni пишет:
>>> On 12/10/19 5:06 PM, Sowjanya Komatineni wrote:
>>>> On 12/10/19 9:41 AM, Dmitry Osipenko wrote:
>>>>> 10.12.2019 19:53, Sowjanya Komatineni пишет:
>>>>>> On 12/9/19 3:03 PM, Sowjanya Komatineni wrote:
>>>>>>> On 12/9/19 12:46 PM, Sowjanya Komatineni wrote:
>>>>>>>> On 12/9/19 12:12 PM, Dmitry Osipenko wrote:
>>>>>>>>> 08.12.2019 00:36, Sowjanya Komatineni пишет:
>>>>>>>>>> On 12/7/19 11:59 AM, Sowjanya Komatineni wrote:
>>>>>>>>>>> On 12/7/19 8:00 AM, Dmitry Osipenko wrote:
>>>>>>>>>>>> 07.12.2019 18:53, Dmitry Osipenko пишет:
>>>>>>>>>>>>> 07.12.2019 18:47, Dmitry Osipenko пишет:
>>>>>>>>>>>>>> 07.12.2019 17:28, Dmitry Osipenko пишет:
>>>>>>>>>>>>>>> 06.12.2019 05:48, 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
>>>>>>>>>>>>>>>> <[email protected]>
>>>>>>>>>>>>>>>> ---
>>>>>>>>>>>>>> [snip]
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>> +static const struct clk_ops pmc_clk_gate_ops = {
>>>>>>>>>>>>>>>> + .is_enabled = pmc_clk_is_enabled,
>>>>>>>>>>>>>>>> + .enable = pmc_clk_enable,
>>>>>>>>>>>>>>>> + .disable = pmc_clk_disable,
>>>>>>>>>>>>>>>> +};
>>>>>>>>>>>>>>> What's the benefit of separating GATE from the MUX?
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> I think it could be a single clock.
>>>>>>>>>>>>>> According to TRM:
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> 1. GATE and MUX are separate entities.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> 2. GATE is the parent of MUX (see PMC's CLK_OUT paths
>>>>>>>>>>>>>> diagram
>>>>>>>>>>>>>> in TRM).
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> 3. PMC doesn't gate EXTPERIPH clock but could "force-enable"
>>>>>>>>>>>>>> it,
>>>>>>>>>>>>>> correct?
>>>>>>>>>> Was following existing clk-tegra-pmc as I am not sure of
>>>>>>>>>> reason for
>>>>>>>>>> having these clocks registered as separate mux and gate clocks.
>>>>>>>>>>
>>>>>>>>>> Yes, PMC clocks can be registered as single clock and can use
>>>>>>>>>> clk_ops
>>>>>>>>>> for set/get parent and enable/disable.
>>>>>>>>>>
>>>>>>>>>> enable/disable of PMC clocks is for force-enable to force the
>>>>>>>>>> clock to
>>>>>>>>>> run regardless of ACCEPT_REQ or INVERT_REQ.
>>>>>>>>>>
>>>>>>>>>>>>> 4. clk_m_div2/4 are internal PMC OSC dividers and thus these
>>>>>>>>>>>>> clocks
>>>>>>>>>>>>> should belong to PMC.
>>>>>>>>>>>> Also, it should be "osc" and not "clk_m".
>>>>>>>>>>> I followed the same parents as it were in existing
>>>>>>>>>>> clk-tegra-pmc
>>>>>>>>>>> driver.
>>>>>>>>>>>
>>>>>>>>>>> Yeah they are wrong and they should be from osc and not clk_m.
>>>>>>>>>>>
>>>>>>>>>>> Will fix in next version.
>>>>>>>>>>>
>>>>>>> Reg clk_m_div2/3, they are dividers at OSC pad and not really
>>>>>>> internal
>>>>>>> to PMC block.
>>>>>>>
>>>>>>> current clock driver creates clk_m_div clocks which should
>>>>>>> actually be
>>>>>>> osc_div2/osc_div4 clocks with osc as parent.
>>>>>>>
>>>>>>> There are no clk_m_div2 and clk_m_div4 from clk_m
>>>>>>>
>>>>>>> Will fix this in next version.
>>>>>>>
>>>>>>>>> Could you please describe the full EXTPERIPH clock topology and
>>>>>>>>> how the
>>>>>>>>> pinmux configuration is related to it all?
>>>>>>>>>
>>>>>>>>> What is internal to the Tegra chip and what are the external
>>>>>>>>> outputs?
>>>>>>>>>
>>>>>>>>> Is it possible to bypass PMC on T30+ for the EXTPERIPH clocks?
>>>>>>>> PMC CLK1/2/3 possible sources are OSC_DIV1, OSC_DIV2, OSC_DIV4,
>>>>>>>> EXTPERIPH from CAR.
>>>>>>>>
>>>>>>>> OSC_DIV1/2/4 are with internal dividers at the OSC Pads
>>>>>>>>
>>>>>>>> EXTPERIPH is from CAR and it has reset and enable controls
>>>>>>>> along with
>>>>>>>> clock source selections to choose one of the PLLA_OUT0, CLK_S,
>>>>>>>> PLLP_OUT0, CLK_M, PLLE_OUT0
>>>>>>>>
>>>>>>>> So, PMC CLK1/2/4 possible parents are OSC_DIV1, OSC_DIV2,
>>>>>>>> OSC_DIV4,
>>>>>>>> EXTERN.
>>>>>>>>
>>>>>>>>
>>>>>>>> CLK1/2/3 also has Pinmux to route EXTPERIPH output on to these
>>>>>>>> pins.
>>>>>>>>
>>>>>>>>
>>>>>>>> When EXTERN output clock is selected for these PMC clocks thru
>>>>>>>> CLKx_SRC_SEL, output clock is from driver by EXTPERIPH from CAR
>>>>>>>> via
>>>>>>>> Pinmux logic or driven as per CLKx_SRC_SEL bypassing pinmux
>>>>>>>> based on
>>>>>>>> CLKx_ACCEPT_REQ bit.
>>>>>>>>
>>>>>>>>
>>>>>>>> PMC Clock control register has bit CLKx_ACCEPT_REQ
>>>>>>>> When CLKx_ACCEPT_REQ = 0, output clock driver is from by EXTPERIPH
>>>>>>>> through the pinmux
>>>>>>>> When CLKx_ACCEPT_REQ = 1, output clock is based on CLKx_SRC_SEL
>>>>>>>> bits
>>>>>>>> (OSC_DIV1/2/4 and EXTPERIPH clock bypassing the pinmux)
>>>>>>>>
>>>>>>>> FORCE_EN bit in PMC CLock control register forces the clock to run
>>>>>>>> regardless of this.
>>>>>> PMC clock gate is based on the state of CLKx_ACCEPT_REQ and FORCE_EN
>>>>>> like explained above.
>>>>>>
>>>>>> CLKx_ACCEPT_REQ is 0 default and FORCE_EN acts as gate to
>>>>>> enable/disable
>>>>>> EXTPERIPH clock output to PMC CLK_OUT_1/2/3.
>>>>> [and to enable OSC as well]
>>>>>
>>>>>> So I believe we need to register as MUX and Gate rather than as a
>>>>>> single
>>>>>> clock. Please confirm.
>>>>> 1. The force-enabling is applied to both OSC and EXTERN sources of
>>>>> PMC_CLK_OUT_x by PMC at once.
>>>>>
>>>>> 2. Both of PMC's force-enabling and OSC/EXTERN selection is internal
>>>>> to PMC.
>>>>>
>>>>> Should be better to define it as a single "pmc_clk_out_x". I don't
>>>>> see
>>>>> any good reasons for differentiating PMC's Gate from the MUX, it's a
>>>>> single hardware unit from a point of view of the rest of the system.
>>>>>
>>>>> Peter, do you have any objections?
>>>> We added fallback option for audio mclk and also added check for
>>>> assigned-clock-parents dt property in audio driver and if its not then
>>>> we do parent init configuration in audio driver.
>>>>
>>>> Current clock driver creates 2 separate clocks clk_out_1_mux and
>>>> clk_out_1 for each pmc clock in clock driver and uses extern1 as
>>>> parent to clk_out_1_mux and clk_out_1_mux is parent to clk_out_1.
>>>>
>>>> With change of registering each pmc clock as a single clock, when we
>>>> do parent init assignment in audio driver when
>>>> assigned-clock-properties are not used in DT (as we removed parent
>>>> inits for extern and clk_outs from clock driver), we should still try
>>>> to get clock based on clk_out_1_mux as parent assignment of extern1 is
>>>> for clk_out_1_mux as per existing clock tree.
>>>>
>>>> clk_out_1_mux clock retrieve will fail with this change of single
>>>> clock when any new platform device tree doesn't specify
>>>> assigned-clock-parents properties and tegra_asoc_utils_init fails.
>> You made the PMC/CaR changes before the audio changes, the clk_out_1_mux
>> won't exist for the audio driver patches.
>>
>> If you care about bisect-ability of the patches, then the clock and
>> audio changes need to be done in a single patch. But I don't think that
>> it's worthwhile.
>>
>>>> With single clock, extern1 is the parent for clk_out_1 and with
>>>> separate clocks for mux and gate, extern1 is the parent for
>>>> clk_out_1_mux.
>>> If we move to single clock now, it need one more additional fallback
>>> implementation in audio driver during parent configuration as
>>> clk_out_1_mux will not be there with single clock change and
>>> old/current
>>> kernel has it as it uses separate clocks for pmc mux and gate.
>> Why additional fallback? Additional to what?
>>
>>> Also, with single clock for both PMC mux and gate now, new DT should
>>> use
>>> extern1 as parent to CLK_OUT_1 as CLK_OUT_1_MUX will not be there old
>>> PMC dt-bindings has separate clocks for MUX (CLK_OUT_1_MUX) and gate
>>> (CLK_OUT_1)
>>>
>>> DT bindings will not be compatible b/w old and new changes if we
>>> move to
>>> Single PMC clock now.
>> Sorry, I don't understand what you're meaning by the "new changes".
>>
>>> Should we go with same separate clocks to have it compatible to avoid
>>> all this?
>>>
> The reason we added mclk fallback and also for doing parent
> configuration based on presence of assigned-clock-parents property is
> to have old dt compatible with new kernel and also to have new dt
> compatible with old kernel.
>
> So the point I was mentioning is to have new DT to work with old
> kernel, setting extern1 as parent to clk_out_1 (with single pmc clock)
> through assigned-clock-parents in DT will fail as old kernel has mux
> and gate as separate clocks and parent configuration is for mux clock
> (clk_out_1_mux)
>
Sorry never mind, with old kernel clock driver does all parent
configuration so should be ok. So no additional fallbacks are needed
except to the one we already added.
OK, So its just that changes are slightly more to switch to single clock
compared to using separate clocks as gate clk_ops (which are needed
anyway for blink control) of clock enable and disable can't be used for
clk_out_1 enable/disable and need additional clk_enable and disable
callbacks.
Will make changes to use single clock..
12.12.2019 06:54, Sowjanya Komatineni пишет:
>
> On 12/11/19 7:45 PM, Sowjanya Komatineni wrote:
>>
>> On 12/11/19 5:39 PM, Dmitry Osipenko wrote:
>>> 11.12.2019 21:50, Sowjanya Komatineni пишет:
>>>> On 12/10/19 5:06 PM, Sowjanya Komatineni wrote:
>>>>> On 12/10/19 9:41 AM, Dmitry Osipenko wrote:
>>>>>> 10.12.2019 19:53, Sowjanya Komatineni пишет:
>>>>>>> On 12/9/19 3:03 PM, Sowjanya Komatineni wrote:
>>>>>>>> On 12/9/19 12:46 PM, Sowjanya Komatineni wrote:
>>>>>>>>> On 12/9/19 12:12 PM, Dmitry Osipenko wrote:
>>>>>>>>>> 08.12.2019 00:36, Sowjanya Komatineni пишет:
>>>>>>>>>>> On 12/7/19 11:59 AM, Sowjanya Komatineni wrote:
>>>>>>>>>>>> On 12/7/19 8:00 AM, Dmitry Osipenko wrote:
>>>>>>>>>>>>> 07.12.2019 18:53, Dmitry Osipenko пишет:
>>>>>>>>>>>>>> 07.12.2019 18:47, Dmitry Osipenko пишет:
>>>>>>>>>>>>>>> 07.12.2019 17:28, Dmitry Osipenko пишет:
>>>>>>>>>>>>>>>> 06.12.2019 05:48, 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
>>>>>>>>>>>>>>>>> <[email protected]>
>>>>>>>>>>>>>>>>> ---
>>>>>>>>>>>>>>> [snip]
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>> +
>>>>>>>>>>>>>>>>> +static const struct clk_ops pmc_clk_gate_ops = {
>>>>>>>>>>>>>>>>> + .is_enabled = pmc_clk_is_enabled,
>>>>>>>>>>>>>>>>> + .enable = pmc_clk_enable,
>>>>>>>>>>>>>>>>> + .disable = pmc_clk_disable,
>>>>>>>>>>>>>>>>> +};
>>>>>>>>>>>>>>>> What's the benefit of separating GATE from the MUX?
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> I think it could be a single clock.
>>>>>>>>>>>>>>> According to TRM:
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> 1. GATE and MUX are separate entities.
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> 2. GATE is the parent of MUX (see PMC's CLK_OUT paths
>>>>>>>>>>>>>>> diagram
>>>>>>>>>>>>>>> in TRM).
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> 3. PMC doesn't gate EXTPERIPH clock but could "force-enable"
>>>>>>>>>>>>>>> it,
>>>>>>>>>>>>>>> correct?
>>>>>>>>>>> Was following existing clk-tegra-pmc as I am not sure of
>>>>>>>>>>> reason for
>>>>>>>>>>> having these clocks registered as separate mux and gate clocks.
>>>>>>>>>>>
>>>>>>>>>>> Yes, PMC clocks can be registered as single clock and can use
>>>>>>>>>>> clk_ops
>>>>>>>>>>> for set/get parent and enable/disable.
>>>>>>>>>>>
>>>>>>>>>>> enable/disable of PMC clocks is for force-enable to force the
>>>>>>>>>>> clock to
>>>>>>>>>>> run regardless of ACCEPT_REQ or INVERT_REQ.
>>>>>>>>>>>
>>>>>>>>>>>>>> 4. clk_m_div2/4 are internal PMC OSC dividers and thus these
>>>>>>>>>>>>>> clocks
>>>>>>>>>>>>>> should belong to PMC.
>>>>>>>>>>>>> Also, it should be "osc" and not "clk_m".
>>>>>>>>>>>> I followed the same parents as it were in existing
>>>>>>>>>>>> clk-tegra-pmc
>>>>>>>>>>>> driver.
>>>>>>>>>>>>
>>>>>>>>>>>> Yeah they are wrong and they should be from osc and not clk_m.
>>>>>>>>>>>>
>>>>>>>>>>>> Will fix in next version.
>>>>>>>>>>>>
>>>>>>>> Reg clk_m_div2/3, they are dividers at OSC pad and not really
>>>>>>>> internal
>>>>>>>> to PMC block.
>>>>>>>>
>>>>>>>> current clock driver creates clk_m_div clocks which should
>>>>>>>> actually be
>>>>>>>> osc_div2/osc_div4 clocks with osc as parent.
>>>>>>>>
>>>>>>>> There are no clk_m_div2 and clk_m_div4 from clk_m
>>>>>>>>
>>>>>>>> Will fix this in next version.
>>>>>>>>
>>>>>>>>>> Could you please describe the full EXTPERIPH clock topology and
>>>>>>>>>> how the
>>>>>>>>>> pinmux configuration is related to it all?
>>>>>>>>>>
>>>>>>>>>> What is internal to the Tegra chip and what are the external
>>>>>>>>>> outputs?
>>>>>>>>>>
>>>>>>>>>> Is it possible to bypass PMC on T30+ for the EXTPERIPH clocks?
>>>>>>>>> PMC CLK1/2/3 possible sources are OSC_DIV1, OSC_DIV2, OSC_DIV4,
>>>>>>>>> EXTPERIPH from CAR.
>>>>>>>>>
>>>>>>>>> OSC_DIV1/2/4 are with internal dividers at the OSC Pads
>>>>>>>>>
>>>>>>>>> EXTPERIPH is from CAR and it has reset and enable controls
>>>>>>>>> along with
>>>>>>>>> clock source selections to choose one of the PLLA_OUT0, CLK_S,
>>>>>>>>> PLLP_OUT0, CLK_M, PLLE_OUT0
>>>>>>>>>
>>>>>>>>> So, PMC CLK1/2/4 possible parents are OSC_DIV1, OSC_DIV2,
>>>>>>>>> OSC_DIV4,
>>>>>>>>> EXTERN.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> CLK1/2/3 also has Pinmux to route EXTPERIPH output on to these
>>>>>>>>> pins.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> When EXTERN output clock is selected for these PMC clocks thru
>>>>>>>>> CLKx_SRC_SEL, output clock is from driver by EXTPERIPH from CAR
>>>>>>>>> via
>>>>>>>>> Pinmux logic or driven as per CLKx_SRC_SEL bypassing pinmux
>>>>>>>>> based on
>>>>>>>>> CLKx_ACCEPT_REQ bit.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> PMC Clock control register has bit CLKx_ACCEPT_REQ
>>>>>>>>> When CLKx_ACCEPT_REQ = 0, output clock driver is from by EXTPERIPH
>>>>>>>>> through the pinmux
>>>>>>>>> When CLKx_ACCEPT_REQ = 1, output clock is based on CLKx_SRC_SEL
>>>>>>>>> bits
>>>>>>>>> (OSC_DIV1/2/4 and EXTPERIPH clock bypassing the pinmux)
>>>>>>>>>
>>>>>>>>> FORCE_EN bit in PMC CLock control register forces the clock to run
>>>>>>>>> regardless of this.
>>>>>>> PMC clock gate is based on the state of CLKx_ACCEPT_REQ and FORCE_EN
>>>>>>> like explained above.
>>>>>>>
>>>>>>> CLKx_ACCEPT_REQ is 0 default and FORCE_EN acts as gate to
>>>>>>> enable/disable
>>>>>>> EXTPERIPH clock output to PMC CLK_OUT_1/2/3.
>>>>>> [and to enable OSC as well]
>>>>>>
>>>>>>> So I believe we need to register as MUX and Gate rather than as a
>>>>>>> single
>>>>>>> clock. Please confirm.
>>>>>> 1. The force-enabling is applied to both OSC and EXTERN sources of
>>>>>> PMC_CLK_OUT_x by PMC at once.
>>>>>>
>>>>>> 2. Both of PMC's force-enabling and OSC/EXTERN selection is internal
>>>>>> to PMC.
>>>>>>
>>>>>> Should be better to define it as a single "pmc_clk_out_x". I don't
>>>>>> see
>>>>>> any good reasons for differentiating PMC's Gate from the MUX, it's a
>>>>>> single hardware unit from a point of view of the rest of the system.
>>>>>>
>>>>>> Peter, do you have any objections?
>>>>> We added fallback option for audio mclk and also added check for
>>>>> assigned-clock-parents dt property in audio driver and if its not then
>>>>> we do parent init configuration in audio driver.
>>>>>
>>>>> Current clock driver creates 2 separate clocks clk_out_1_mux and
>>>>> clk_out_1 for each pmc clock in clock driver and uses extern1 as
>>>>> parent to clk_out_1_mux and clk_out_1_mux is parent to clk_out_1.
>>>>>
>>>>> With change of registering each pmc clock as a single clock, when we
>>>>> do parent init assignment in audio driver when
>>>>> assigned-clock-properties are not used in DT (as we removed parent
>>>>> inits for extern and clk_outs from clock driver), we should still try
>>>>> to get clock based on clk_out_1_mux as parent assignment of extern1 is
>>>>> for clk_out_1_mux as per existing clock tree.
>>>>>
>>>>> clk_out_1_mux clock retrieve will fail with this change of single
>>>>> clock when any new platform device tree doesn't specify
>>>>> assigned-clock-parents properties and tegra_asoc_utils_init fails.
>>> You made the PMC/CaR changes before the audio changes, the clk_out_1_mux
>>> won't exist for the audio driver patches.
>>>
>>> If you care about bisect-ability of the patches, then the clock and
>>> audio changes need to be done in a single patch. But I don't think that
>>> it's worthwhile.
>>>
>>>>> With single clock, extern1 is the parent for clk_out_1 and with
>>>>> separate clocks for mux and gate, extern1 is the parent for
>>>>> clk_out_1_mux.
>>>> If we move to single clock now, it need one more additional fallback
>>>> implementation in audio driver during parent configuration as
>>>> clk_out_1_mux will not be there with single clock change and
>>>> old/current
>>>> kernel has it as it uses separate clocks for pmc mux and gate.
>>> Why additional fallback? Additional to what?
>>>
>>>> Also, with single clock for both PMC mux and gate now, new DT should
>>>> use
>>>> extern1 as parent to CLK_OUT_1 as CLK_OUT_1_MUX will not be there old
>>>> PMC dt-bindings has separate clocks for MUX (CLK_OUT_1_MUX) and gate
>>>> (CLK_OUT_1)
>>>>
>>>> DT bindings will not be compatible b/w old and new changes if we
>>>> move to
>>>> Single PMC clock now.
>>> Sorry, I don't understand what you're meaning by the "new changes".
>>>
>>>> Should we go with same separate clocks to have it compatible to avoid
>>>> all this?
>>>>
>> The reason we added mclk fallback and also for doing parent
>> configuration based on presence of assigned-clock-parents property is
>> to have old dt compatible with new kernel and also to have new dt
>> compatible with old kernel.
>>
>> So the point I was mentioning is to have new DT to work with old
>> kernel, setting extern1 as parent to clk_out_1 (with single pmc clock)
>> through assigned-clock-parents in DT will fail as old kernel has mux
>> and gate as separate clocks and parent configuration is for mux clock
>> (clk_out_1_mux)
>>
> Sorry never mind, with old kernel clock driver does all parent
> configuration so should be ok. So no additional fallbacks are needed
> except to the one we already added.
>
> OK, So its just that changes are slightly more to switch to single clock
> compared to using separate clocks as gate clk_ops (which are needed
> anyway for blink control) of clock enable and disable can't be used for
> clk_out_1 enable/disable and need additional clk_enable and disable
> callbacks.
>
> Will make changes to use single clock..
Please wait for the Peter's reply.