* [PATCH v4 0/8] Add support for i.MX8ULP's SIM LPAV
@ 2025-11-04 12:02 Laurentiu Mihalcea
2025-11-04 12:02 ` [PATCH v4 1/8] reset: imx8mp-audiomix: Fix bad mask values Laurentiu Mihalcea
` (7 more replies)
0 siblings, 8 replies; 18+ messages in thread
From: Laurentiu Mihalcea @ 2025-11-04 12:02 UTC (permalink / raw)
To: Abel Vesa, Michael Turquette, Stephen Boyd, Krzysztof Kozlowski,
Conor Dooley, Shawn Guo, Fabio Estevam, Philipp Zabel,
Daniel Baluta, Shengjiu Wang, Frank Li
Cc: linux-clk, imx, devicetree, linux-arm-kernel, linux-kernel,
Pengutronix Kernel Team
From: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
The LPAV System Integration Module (SIM) is an IP found inside i.MX8ULP's
LPAV subsystem, which offers clock gating, reset line
assertion/de-assertion, and various other misc. options.
This series adds support for the IP by introducing a new clock HW provider
driver and by modifying i.MX8MP's AUDIOMIX block control reset driver to
allow it to be used for i.MX8ULP's SIM LPAV as well.
This series is a spin-off from [1].
[1]: https://lore.kernel.org/lkml/20240922174225.75948-1-laurentiumihalcea111@gmail.com/
---
Changes in v4:
* shorten commit message for patch 5
* drop base from "struct imx8mp_audiomix_reset" and use local variable
* imx8mp_audiomix_reset_get_regmap() now takes "struct imx8mp_audiomix_reset *"
as its argument instead of a "struct device *"
* use base pointer as the data argument for devm_add_action_or_reset()
* shorten commit message for patch 6
* drop regmap field from "struct clk_imx8ulp_sim_lpav_data", use local
variable and let devres manage it
* drop base field from "struct clk_imx8ulp_sim_lpav_data", use local
variable and let devres manage it.
* CONFIG_CLK_IMX8ULP now selects CONFIG_AUXILIARY_BUS, which is needed
for devm_auxiliary_device_create().
* drop static definition of "struct regmap_config" and change to using
local one in the clock driver.
* link to v3: https://lore.kernel.org/lkml/20251029135229.890-1-laurentiumihalcea111@gmail.com/
Changes in v3:
* rename "lpav_bus", "hifi_core", and "hifi_plat" to "bus", "core", "plat"
* don't assign the "name" field of "struct clk_parent_data". Previously, we
were assigning the local parent name to this field, which wouldn't have
worked anyways if, for whatever reason, the fallback mechanism would kick in.
* replace the whole auxiliary reset driver creation chunk by
a single devm_auxiliary_device_create() call.
* replace the "shift" field from "struct imx8mp_reset_map" with the usage of
ffs()
* shorten commit description for patch 6
* cast "id->driver_data" to "void *" instead of the previous
"const struct imx8mp_reset_info *", which makes the line shorter.
* open question resulting from Peng Fan's comment on V2: how to access
interconnect QoS registers? do we need to model the sim_lpav as an
interconnect provider as well or is it fine to have another interconnect
provider that references the sim_lpav node and accesses its registers
via regmap (dev_get_regmap(), specifically, NOT syscon).
* link to v2: https://lore.kernel.org/lkml/20251017112025.11997-1-laurentiumihalcea111@gmail.com/
Changes in v2:
* drop redundant description for "#clock-cells"/"#reset-cells" properties
from binding
* make "mux-controller" and "#reset-cells" properties mandatory
* add "mux-controller" child to binding example node
* drop the compatiblity with syscon - this was never actually needed and
it was done to allow using "mmio-mux", which requires a syscon parent
* modify the auxiliary reset driver to use regmap - this will allow the
mux controller, clock control and reset control APIs to use the same
spinlock.
* rename "imx8ulp-reset-sim-lpav.h" to "fsl,imx8ulp-sim-lpav.h"
* drop the "IMX8ULP_CLK_SIM_LPAV_END" macro, which doesn't belong to the
binding headers
* fix the values of "IMX8MP_AUDIOMIX_EARC_RESET_MASK" and
"IMX8MP_AUDIOMIX_EARC_PHY_RESET_MASK", which were previously incorrect
* drop redundant macros from auxiliary reset driver - replace their
occurrences with their values
* squash the binding-related macro additions into the binding patch
* add mux-controller child node to the sim_lpav node
* make the "gates" array static
* link to v1: https://lore.kernel.org/lkml/20250804155407.285353-1-laurentiumihalcea111@gmail.com/
---
Laurentiu Mihalcea (8):
reset: imx8mp-audiomix: Fix bad mask values
dt-bindings: clock: document 8ULP's SIM LPAV
clk: imx: add driver for imx8ulp's sim lpav
reset: imx8mp-audiomix: Drop unneeded macros
reset: imx8mp-audiomix: Switch to using regmap API
reset: imx8mp-audiomix: Extend the driver usage
reset: imx8mp-audiomix: Support i.MX8ULP SIM LPAV
arm64: dts: imx8ulp: add sim lpav node
.../bindings/clock/fsl,imx8ulp-sim-lpav.yaml | 72 ++++++++
arch/arm64/boot/dts/freescale/imx8ulp.dtsi | 17 ++
drivers/clk/imx/Kconfig | 1 +
drivers/clk/imx/Makefile | 1 +
drivers/clk/imx/clk-imx8ulp-sim-lpav.c | 156 ++++++++++++++++
drivers/reset/reset-imx8mp-audiomix.c | 166 +++++++++++++-----
include/dt-bindings/clock/imx8ulp-clock.h | 5 +
.../dt-bindings/reset/fsl,imx8ulp-sim-lpav.h | 16 ++
8 files changed, 390 insertions(+), 44 deletions(-)
create mode 100644 Documentation/devicetree/bindings/clock/fsl,imx8ulp-sim-lpav.yaml
create mode 100644 drivers/clk/imx/clk-imx8ulp-sim-lpav.c
create mode 100644 include/dt-bindings/reset/fsl,imx8ulp-sim-lpav.h
--
2.43.0
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v4 1/8] reset: imx8mp-audiomix: Fix bad mask values
2025-11-04 12:02 [PATCH v4 0/8] Add support for i.MX8ULP's SIM LPAV Laurentiu Mihalcea
@ 2025-11-04 12:02 ` Laurentiu Mihalcea
2025-11-05 15:16 ` Philipp Zabel
2025-11-04 12:02 ` [PATCH v4 2/8] dt-bindings: clock: document 8ULP's SIM LPAV Laurentiu Mihalcea
` (6 subsequent siblings)
7 siblings, 1 reply; 18+ messages in thread
From: Laurentiu Mihalcea @ 2025-11-04 12:02 UTC (permalink / raw)
To: Abel Vesa, Michael Turquette, Stephen Boyd, Krzysztof Kozlowski,
Conor Dooley, Shawn Guo, Fabio Estevam, Philipp Zabel,
Daniel Baluta, Shengjiu Wang, Frank Li
Cc: linux-clk, imx, devicetree, linux-arm-kernel, linux-kernel,
Pengutronix Kernel Team
From: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
As per the i.MX8MP TRM, section 14.2 "AUDIO_BLK_CTRL", table 14.2.3.1.1
"memory map", the definition of the EARC control register shows that the
EARC controller software reset is controlled via bit 0, while the EARC PHY
software reset is controlled via bit 1.
This means that the current definitions of IMX8MP_AUDIOMIX_EARC_RESET_MASK
and IMX8MP_AUDIOMIX_EARC_PHY_RESET_MASK are wrong since their values would
imply that the EARC controller software reset is controlled via bit 1 and
the EARC PHY software reset is controlled via bit 2. Fix them.
Fixes: a83bc87cd30a ("reset: imx8mp-audiomix: Prepare the code for more reset bits")
Cc: stable@vger.kernel.org
Reviewed-by: Shengjiu Wang <shengjiu.wang@gmail.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Reviewed-by: Daniel Baluta <daniel.baluta@nxp.com>
Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
---
drivers/reset/reset-imx8mp-audiomix.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/reset/reset-imx8mp-audiomix.c b/drivers/reset/reset-imx8mp-audiomix.c
index 6b357adfe646..eceb37ff5dc5 100644
--- a/drivers/reset/reset-imx8mp-audiomix.c
+++ b/drivers/reset/reset-imx8mp-audiomix.c
@@ -14,8 +14,8 @@
#include <linux/reset-controller.h>
#define IMX8MP_AUDIOMIX_EARC_RESET_OFFSET 0x200
-#define IMX8MP_AUDIOMIX_EARC_RESET_MASK BIT(1)
-#define IMX8MP_AUDIOMIX_EARC_PHY_RESET_MASK BIT(2)
+#define IMX8MP_AUDIOMIX_EARC_RESET_MASK BIT(0)
+#define IMX8MP_AUDIOMIX_EARC_PHY_RESET_MASK BIT(1)
#define IMX8MP_AUDIOMIX_DSP_RUNSTALL_OFFSET 0x108
#define IMX8MP_AUDIOMIX_DSP_RUNSTALL_MASK BIT(5)
--
2.43.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v4 2/8] dt-bindings: clock: document 8ULP's SIM LPAV
2025-11-04 12:02 [PATCH v4 0/8] Add support for i.MX8ULP's SIM LPAV Laurentiu Mihalcea
2025-11-04 12:02 ` [PATCH v4 1/8] reset: imx8mp-audiomix: Fix bad mask values Laurentiu Mihalcea
@ 2025-11-04 12:02 ` Laurentiu Mihalcea
2025-11-04 12:02 ` [PATCH v4 3/8] clk: imx: add driver for imx8ulp's sim lpav Laurentiu Mihalcea
` (5 subsequent siblings)
7 siblings, 0 replies; 18+ messages in thread
From: Laurentiu Mihalcea @ 2025-11-04 12:02 UTC (permalink / raw)
To: Abel Vesa, Michael Turquette, Stephen Boyd, Krzysztof Kozlowski,
Conor Dooley, Shawn Guo, Fabio Estevam, Philipp Zabel,
Daniel Baluta, Shengjiu Wang, Frank Li
Cc: linux-clk, imx, devicetree, linux-arm-kernel, linux-kernel,
Pengutronix Kernel Team
From: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
Add documentation for i.MX8ULP's SIM LPAV module.
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Reviewed-by: Daniel Baluta <daniel.baluta@nxp.com>
Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
---
.../bindings/clock/fsl,imx8ulp-sim-lpav.yaml | 72 +++++++++++++++++++
include/dt-bindings/clock/imx8ulp-clock.h | 5 ++
.../dt-bindings/reset/fsl,imx8ulp-sim-lpav.h | 16 +++++
3 files changed, 93 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/fsl,imx8ulp-sim-lpav.yaml
create mode 100644 include/dt-bindings/reset/fsl,imx8ulp-sim-lpav.h
diff --git a/Documentation/devicetree/bindings/clock/fsl,imx8ulp-sim-lpav.yaml b/Documentation/devicetree/bindings/clock/fsl,imx8ulp-sim-lpav.yaml
new file mode 100644
index 000000000000..662e07528d76
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/fsl,imx8ulp-sim-lpav.yaml
@@ -0,0 +1,72 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/fsl,imx8ulp-sim-lpav.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP i.MX8ULP LPAV System Integration Module (SIM)
+
+maintainers:
+ - Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
+
+description:
+ The i.MX8ULP LPAV subsystem contains a block control module known as
+ SIM LPAV, which offers functionalities such as clock gating or reset
+ line assertion/de-assertion.
+
+properties:
+ compatible:
+ const: fsl,imx8ulp-sim-lpav
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 3
+
+ clock-names:
+ items:
+ - const: bus
+ - const: core
+ - const: plat
+
+ '#clock-cells':
+ const: 1
+
+ '#reset-cells':
+ const: 1
+
+ mux-controller:
+ $ref: /schemas/mux/reg-mux.yaml#
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+ - '#clock-cells'
+ - '#reset-cells'
+ - mux-controller
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/imx8ulp-clock.h>
+
+ clock-controller@2da50000 {
+ compatible = "fsl,imx8ulp-sim-lpav";
+ reg = <0x2da50000 0x10000>;
+ clocks = <&cgc2 IMX8ULP_CLK_LPAV_BUS_DIV>,
+ <&cgc2 IMX8ULP_CLK_HIFI_DIVCORE>,
+ <&cgc2 IMX8ULP_CLK_HIFI_DIVPLAT>;
+ clock-names = "bus", "core", "plat";
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+
+ mux-controller {
+ compatible = "reg-mux";
+ #mux-control-cells = <1>;
+ mux-reg-masks = <0x8 0x00000200>;
+ };
+ };
diff --git a/include/dt-bindings/clock/imx8ulp-clock.h b/include/dt-bindings/clock/imx8ulp-clock.h
index 827404fadf5c..c62d84d093a9 100644
--- a/include/dt-bindings/clock/imx8ulp-clock.h
+++ b/include/dt-bindings/clock/imx8ulp-clock.h
@@ -255,4 +255,9 @@
#define IMX8ULP_CLK_PCC5_END 56
+/* LPAV SIM */
+#define IMX8ULP_CLK_SIM_LPAV_HIFI_CORE 0
+#define IMX8ULP_CLK_SIM_LPAV_HIFI_PBCLK 1
+#define IMX8ULP_CLK_SIM_LPAV_HIFI_PLAT 2
+
#endif
diff --git a/include/dt-bindings/reset/fsl,imx8ulp-sim-lpav.h b/include/dt-bindings/reset/fsl,imx8ulp-sim-lpav.h
new file mode 100644
index 000000000000..adf95bb26d21
--- /dev/null
+++ b/include/dt-bindings/reset/fsl,imx8ulp-sim-lpav.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright 2025 NXP
+ */
+
+#ifndef DT_BINDING_RESET_IMX8ULP_SIM_LPAV_H
+#define DT_BINDING_RESET_IMX8ULP_SIM_LPAV_H
+
+#define IMX8ULP_SIM_LPAV_HIFI4_DSP_DBG_RST 0
+#define IMX8ULP_SIM_LPAV_HIFI4_DSP_RST 1
+#define IMX8ULP_SIM_LPAV_HIFI4_DSP_STALL 2
+#define IMX8ULP_SIM_LPAV_DSI_RST_BYTE_N 3
+#define IMX8ULP_SIM_LPAV_DSI_RST_ESC_N 4
+#define IMX8ULP_SIM_LPAV_DSI_RST_DPI_N 5
+
+#endif /* DT_BINDING_RESET_IMX8ULP_SIM_LPAV_H */
--
2.43.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v4 3/8] clk: imx: add driver for imx8ulp's sim lpav
2025-11-04 12:02 [PATCH v4 0/8] Add support for i.MX8ULP's SIM LPAV Laurentiu Mihalcea
2025-11-04 12:02 ` [PATCH v4 1/8] reset: imx8mp-audiomix: Fix bad mask values Laurentiu Mihalcea
2025-11-04 12:02 ` [PATCH v4 2/8] dt-bindings: clock: document 8ULP's SIM LPAV Laurentiu Mihalcea
@ 2025-11-04 12:02 ` Laurentiu Mihalcea
2025-11-04 12:45 ` Peng Fan
2025-11-05 9:36 ` Daniel Baluta
2025-11-04 12:02 ` [PATCH v4 4/8] reset: imx8mp-audiomix: Drop unneeded macros Laurentiu Mihalcea
` (4 subsequent siblings)
7 siblings, 2 replies; 18+ messages in thread
From: Laurentiu Mihalcea @ 2025-11-04 12:02 UTC (permalink / raw)
To: Abel Vesa, Michael Turquette, Stephen Boyd, Krzysztof Kozlowski,
Conor Dooley, Shawn Guo, Fabio Estevam, Philipp Zabel,
Daniel Baluta, Shengjiu Wang, Frank Li
Cc: linux-clk, imx, devicetree, linux-arm-kernel, linux-kernel,
Pengutronix Kernel Team
From: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
The i.MX8ULP System Integration Module (SIM) LPAV module is a block
control module found inside the LPAV subsystem, which offers some clock
gating options and reset line assertion/de-assertion capabilities.
Therefore, the clock gate management is supported by registering the
module's driver as a clock provider, while the reset capabilities are
managed via the auxiliary device API to allow the DT node to act as a
reset and clock provider.
Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
---
drivers/clk/imx/Kconfig | 1 +
drivers/clk/imx/Makefile | 1 +
drivers/clk/imx/clk-imx8ulp-sim-lpav.c | 156 +++++++++++++++++++++++++
3 files changed, 158 insertions(+)
create mode 100644 drivers/clk/imx/clk-imx8ulp-sim-lpav.c
diff --git a/drivers/clk/imx/Kconfig b/drivers/clk/imx/Kconfig
index 6ff6d934848a..b292e7ca5c24 100644
--- a/drivers/clk/imx/Kconfig
+++ b/drivers/clk/imx/Kconfig
@@ -105,6 +105,7 @@ config CLK_IMX8ULP
tristate "IMX8ULP CCM Clock Driver"
depends on ARCH_MXC || COMPILE_TEST
select MXC_CLK
+ select AUXILIARY_BUS
help
Build the driver for i.MX8ULP CCM Clock Driver
diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index 03f2b2a1ab63..208b46873a18 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -41,6 +41,7 @@ clk-imx-lpcg-scu-$(CONFIG_CLK_IMX8QXP) += clk-lpcg-scu.o clk-imx8qxp-lpcg.o
clk-imx-acm-$(CONFIG_CLK_IMX8QXP) = clk-imx8-acm.o
obj-$(CONFIG_CLK_IMX8ULP) += clk-imx8ulp.o
+obj-$(CONFIG_CLK_IMX8ULP) += clk-imx8ulp-sim-lpav.o
obj-$(CONFIG_CLK_IMX1) += clk-imx1.o
obj-$(CONFIG_CLK_IMX25) += clk-imx25.o
diff --git a/drivers/clk/imx/clk-imx8ulp-sim-lpav.c b/drivers/clk/imx/clk-imx8ulp-sim-lpav.c
new file mode 100644
index 000000000000..990c95b89b75
--- /dev/null
+++ b/drivers/clk/imx/clk-imx8ulp-sim-lpav.c
@@ -0,0 +1,156 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2025 NXP
+ */
+
+#include <dt-bindings/clock/imx8ulp-clock.h>
+
+#include <linux/auxiliary_bus.h>
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#define SYSCTRL0 0x8
+
+#define IMX8ULP_HIFI_CLK_GATE(gname, cname, pname, bidx) \
+ { \
+ .name = gname "_cg", \
+ .id = IMX8ULP_CLK_SIM_LPAV_HIFI_##cname, \
+ .parent = { .fw_name = pname }, \
+ .bit = bidx, \
+ }
+
+struct clk_imx8ulp_sim_lpav_data {
+ spinlock_t lock; /* shared by MUX, clock gate and reset */
+ unsigned long flags; /* for spinlock usage */
+ struct clk_hw_onecell_data clk_data; /* keep last */
+};
+
+struct clk_imx8ulp_sim_lpav_gate {
+ const char *name;
+ int id;
+ const struct clk_parent_data parent;
+ u8 bit;
+};
+
+static struct clk_imx8ulp_sim_lpav_gate gates[] = {
+ IMX8ULP_HIFI_CLK_GATE("hifi_core", CORE, "core", 17),
+ IMX8ULP_HIFI_CLK_GATE("hifi_pbclk", PBCLK, "bus", 18),
+ IMX8ULP_HIFI_CLK_GATE("hifi_plat", PLAT, "plat", 19)
+};
+
+static void clk_imx8ulp_sim_lpav_lock(void *arg) __acquires(&data->lock)
+{
+ struct clk_imx8ulp_sim_lpav_data *data = dev_get_drvdata(arg);
+
+ spin_lock_irqsave(&data->lock, data->flags);
+}
+
+static void clk_imx8ulp_sim_lpav_unlock(void *arg) __releases(&data->lock)
+{
+ struct clk_imx8ulp_sim_lpav_data *data = dev_get_drvdata(arg);
+
+ spin_unlock_irqrestore(&data->lock, data->flags);
+}
+
+static int clk_imx8ulp_sim_lpav_probe(struct platform_device *pdev)
+{
+ const struct regmap_config regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+ .lock = clk_imx8ulp_sim_lpav_lock,
+ .unlock = clk_imx8ulp_sim_lpav_unlock,
+ .lock_arg = &pdev->dev,
+ };
+ struct clk_imx8ulp_sim_lpav_data *data;
+ struct auxiliary_device *adev;
+ struct regmap *regmap;
+ void __iomem *base;
+ struct clk_hw *hw;
+ int i, ret;
+
+ data = devm_kzalloc(&pdev->dev,
+ struct_size(data, clk_data.hws, ARRAY_SIZE(gates)),
+ GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ dev_set_drvdata(&pdev->dev, data);
+
+ /*
+ * this lock is used directly by the clock gate and indirectly
+ * by the reset and mux controller via the regmap API
+ */
+ spin_lock_init(&data->lock);
+
+ base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(base))
+ return dev_err_probe(&pdev->dev, PTR_ERR(base),
+ "failed to ioremap base\n");
+ /*
+ * although the clock gate doesn't use the regmap API to modify the
+ * registers, we still need the regmap because of the reset auxiliary
+ * driver and the MUX drivers, which use the parent device's regmap
+ */
+ regmap = devm_regmap_init_mmio(&pdev->dev, base, ®map_config);
+ if (IS_ERR(regmap))
+ return dev_err_probe(&pdev->dev, PTR_ERR(regmap),
+ "failed to initialize regmap\n");
+
+ data->clk_data.num = ARRAY_SIZE(gates);
+
+ for (i = 0; i < ARRAY_SIZE(gates); i++) {
+ hw = devm_clk_hw_register_gate_parent_data(&pdev->dev,
+ gates[i].name,
+ &gates[i].parent,
+ CLK_SET_RATE_PARENT,
+ base + SYSCTRL0,
+ gates[i].bit,
+ 0x0, &data->lock);
+ if (IS_ERR(hw))
+ return dev_err_probe(&pdev->dev, PTR_ERR(hw),
+ "failed to register %s gate\n",
+ gates[i].name);
+
+ data->clk_data.hws[i] = hw;
+ }
+
+ adev = devm_auxiliary_device_create(&pdev->dev, "reset", NULL);
+ if (!adev)
+ return dev_err_probe(&pdev->dev, -ENODEV,
+ "failed to register aux reset\n");
+
+ ret = devm_of_clk_add_hw_provider(&pdev->dev,
+ of_clk_hw_onecell_get,
+ &data->clk_data);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
+ "failed to register clk hw provider\n");
+
+ /* used to probe MUX child device */
+ return devm_of_platform_populate(&pdev->dev);
+}
+
+static const struct of_device_id clk_imx8ulp_sim_lpav_of_match[] = {
+ { .compatible = "fsl,imx8ulp-sim-lpav" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, clk_imx8ulp_sim_lpav_of_match);
+
+static struct platform_driver clk_imx8ulp_sim_lpav_driver = {
+ .probe = clk_imx8ulp_sim_lpav_probe,
+ .driver = {
+ .name = "clk-imx8ulp-sim-lpav",
+ .of_match_table = clk_imx8ulp_sim_lpav_of_match,
+ },
+};
+module_platform_driver(clk_imx8ulp_sim_lpav_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("i.MX8ULP LPAV System Integration Module (SIM) clock driver");
+MODULE_AUTHOR("Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>");
--
2.43.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v4 4/8] reset: imx8mp-audiomix: Drop unneeded macros
2025-11-04 12:02 [PATCH v4 0/8] Add support for i.MX8ULP's SIM LPAV Laurentiu Mihalcea
` (2 preceding siblings ...)
2025-11-04 12:02 ` [PATCH v4 3/8] clk: imx: add driver for imx8ulp's sim lpav Laurentiu Mihalcea
@ 2025-11-04 12:02 ` Laurentiu Mihalcea
2025-11-05 15:10 ` Philipp Zabel
2025-11-04 12:02 ` [PATCH v4 5/8] reset: imx8mp-audiomix: Switch to using regmap API Laurentiu Mihalcea
` (3 subsequent siblings)
7 siblings, 1 reply; 18+ messages in thread
From: Laurentiu Mihalcea @ 2025-11-04 12:02 UTC (permalink / raw)
To: Abel Vesa, Michael Turquette, Stephen Boyd, Krzysztof Kozlowski,
Conor Dooley, Shawn Guo, Fabio Estevam, Philipp Zabel,
Daniel Baluta, Shengjiu Wang, Frank Li
Cc: linux-clk, imx, devicetree, linux-arm-kernel, linux-kernel,
Pengutronix Kernel Team
From: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
The macros defining the mask values for the EARC, EARC PHY resets,
and the DSP RUN_STALL signal can be dropped as they are not and will
not be used anywhere else except to set the value of the "mask" field
from "struct imx8mp_reset_map". In this particular case, based on the
name of the "mask" field, you can already deduce what these values are
for, which is why defining macros for them doesn't offer any new
information, nor does it help with the code readability.
Reviewed-by: Daniel Baluta <daniel.baluta@nxp.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
---
drivers/reset/reset-imx8mp-audiomix.c | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)
diff --git a/drivers/reset/reset-imx8mp-audiomix.c b/drivers/reset/reset-imx8mp-audiomix.c
index eceb37ff5dc5..e9643365a62c 100644
--- a/drivers/reset/reset-imx8mp-audiomix.c
+++ b/drivers/reset/reset-imx8mp-audiomix.c
@@ -14,11 +14,7 @@
#include <linux/reset-controller.h>
#define IMX8MP_AUDIOMIX_EARC_RESET_OFFSET 0x200
-#define IMX8MP_AUDIOMIX_EARC_RESET_MASK BIT(0)
-#define IMX8MP_AUDIOMIX_EARC_PHY_RESET_MASK BIT(1)
-
#define IMX8MP_AUDIOMIX_DSP_RUNSTALL_OFFSET 0x108
-#define IMX8MP_AUDIOMIX_DSP_RUNSTALL_MASK BIT(5)
struct imx8mp_reset_map {
unsigned int offset;
@@ -29,17 +25,17 @@ struct imx8mp_reset_map {
static const struct imx8mp_reset_map reset_map[] = {
[IMX8MP_AUDIOMIX_EARC_RESET] = {
.offset = IMX8MP_AUDIOMIX_EARC_RESET_OFFSET,
- .mask = IMX8MP_AUDIOMIX_EARC_RESET_MASK,
+ .mask = BIT(0),
.active_low = true,
},
[IMX8MP_AUDIOMIX_EARC_PHY_RESET] = {
.offset = IMX8MP_AUDIOMIX_EARC_RESET_OFFSET,
- .mask = IMX8MP_AUDIOMIX_EARC_PHY_RESET_MASK,
+ .mask = BIT(1),
.active_low = true,
},
[IMX8MP_AUDIOMIX_DSP_RUNSTALL] = {
.offset = IMX8MP_AUDIOMIX_DSP_RUNSTALL_OFFSET,
- .mask = IMX8MP_AUDIOMIX_DSP_RUNSTALL_MASK,
+ .mask = BIT(5),
.active_low = false,
},
};
--
2.43.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v4 5/8] reset: imx8mp-audiomix: Switch to using regmap API
2025-11-04 12:02 [PATCH v4 0/8] Add support for i.MX8ULP's SIM LPAV Laurentiu Mihalcea
` (3 preceding siblings ...)
2025-11-04 12:02 ` [PATCH v4 4/8] reset: imx8mp-audiomix: Drop unneeded macros Laurentiu Mihalcea
@ 2025-11-04 12:02 ` Laurentiu Mihalcea
2025-11-04 16:44 ` Frank Li
2025-11-05 15:10 ` Philipp Zabel
2025-11-04 12:02 ` [PATCH v4 6/8] reset: imx8mp-audiomix: Extend the driver usage Laurentiu Mihalcea
` (2 subsequent siblings)
7 siblings, 2 replies; 18+ messages in thread
From: Laurentiu Mihalcea @ 2025-11-04 12:02 UTC (permalink / raw)
To: Abel Vesa, Michael Turquette, Stephen Boyd, Krzysztof Kozlowski,
Conor Dooley, Shawn Guo, Fabio Estevam, Philipp Zabel,
Daniel Baluta, Shengjiu Wang, Frank Li
Cc: linux-clk, imx, devicetree, linux-arm-kernel, linux-kernel,
Pengutronix Kernel Team
From: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
Switch to using the regmap API to allow performing register operations
under the same lock. This is needed for cases such as i.MX8ULP's SIM LPAV
where clock gating, reset control and MUX-ing is performed via the same
register (i.e. SYSCTRL0) and different subsystem APIs.
Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
---
drivers/reset/reset-imx8mp-audiomix.c | 93 +++++++++++++++++----------
1 file changed, 58 insertions(+), 35 deletions(-)
diff --git a/drivers/reset/reset-imx8mp-audiomix.c b/drivers/reset/reset-imx8mp-audiomix.c
index e9643365a62c..18a7f68aa59f 100644
--- a/drivers/reset/reset-imx8mp-audiomix.c
+++ b/drivers/reset/reset-imx8mp-audiomix.c
@@ -11,6 +11,7 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/regmap.h>
#include <linux/reset-controller.h>
#define IMX8MP_AUDIOMIX_EARC_RESET_OFFSET 0x200
@@ -42,8 +43,7 @@ static const struct imx8mp_reset_map reset_map[] = {
struct imx8mp_audiomix_reset {
struct reset_controller_dev rcdev;
- spinlock_t lock; /* protect register read-modify-write cycle */
- void __iomem *base;
+ struct regmap *regmap;
};
static struct imx8mp_audiomix_reset *to_imx8mp_audiomix_reset(struct reset_controller_dev *rcdev)
@@ -55,26 +55,15 @@ static int imx8mp_audiomix_update(struct reset_controller_dev *rcdev,
unsigned long id, bool assert)
{
struct imx8mp_audiomix_reset *priv = to_imx8mp_audiomix_reset(rcdev);
- void __iomem *reg_addr = priv->base;
- unsigned int mask, offset, active_low;
- unsigned long reg, flags;
+ unsigned int mask, offset, active_low, shift, val;
mask = reset_map[id].mask;
offset = reset_map[id].offset;
active_low = reset_map[id].active_low;
+ shift = ffs(mask) - 1;
+ val = (active_low ^ assert) << shift;
- spin_lock_irqsave(&priv->lock, flags);
-
- reg = readl(reg_addr + offset);
- if (active_low ^ assert)
- reg |= mask;
- else
- reg &= ~mask;
- writel(reg, reg_addr + offset);
-
- spin_unlock_irqrestore(&priv->lock, flags);
-
- return 0;
+ return regmap_update_bits(priv->regmap, offset, mask, val);
}
static int imx8mp_audiomix_reset_assert(struct reset_controller_dev *rcdev,
@@ -94,6 +83,52 @@ static const struct reset_control_ops imx8mp_audiomix_reset_ops = {
.deassert = imx8mp_audiomix_reset_deassert,
};
+static const struct regmap_config regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+};
+
+/* assumption: registered only if not using parent regmap */
+static void imx8mp_audiomix_reset_iounmap(void *data)
+{
+ void __iomem *base = (void __iomem *)data;
+
+ iounmap(base);
+}
+
+static int imx8mp_audiomix_reset_get_regmap(struct imx8mp_audiomix_reset *priv)
+{
+ void __iomem *base;
+ struct device *dev;
+ int ret;
+
+ dev = priv->rcdev.dev;
+
+ /* try to use the parent's regmap */
+ priv->regmap = dev_get_regmap(dev->parent, NULL);
+ if (priv->regmap)
+ return 0;
+
+ /* ... if that's not possible then initialize the regmap right now */
+ base = of_iomap(dev->parent->of_node, 0);
+ if (!base)
+ return dev_err_probe(dev, -ENOMEM, "failed to iomap address space\n");
+
+ ret = devm_add_action_or_reset(dev,
+ imx8mp_audiomix_reset_iounmap,
+ (void __force *)base);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to register action\n");
+
+ priv->regmap = devm_regmap_init_mmio(dev, base, ®map_config);
+ if (IS_ERR(priv->regmap))
+ return dev_err_probe(dev, PTR_ERR(priv->regmap),
+ "failed to initialize regmap\n");
+
+ return 0;
+}
+
static int imx8mp_audiomix_reset_probe(struct auxiliary_device *adev,
const struct auxiliary_device_id *id)
{
@@ -105,36 +140,25 @@ static int imx8mp_audiomix_reset_probe(struct auxiliary_device *adev,
if (!priv)
return -ENOMEM;
- spin_lock_init(&priv->lock);
-
priv->rcdev.owner = THIS_MODULE;
priv->rcdev.nr_resets = ARRAY_SIZE(reset_map);
priv->rcdev.ops = &imx8mp_audiomix_reset_ops;
priv->rcdev.of_node = dev->parent->of_node;
priv->rcdev.dev = dev;
priv->rcdev.of_reset_n_cells = 1;
- priv->base = of_iomap(dev->parent->of_node, 0);
- if (!priv->base)
- return -ENOMEM;
dev_set_drvdata(dev, priv);
+ ret = imx8mp_audiomix_reset_get_regmap(priv);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to get regmap\n");
+
ret = devm_reset_controller_register(dev, &priv->rcdev);
if (ret)
- goto out_unmap;
+ return dev_err_probe(dev, ret,
+ "failed to register reset controller\n");
return 0;
-
-out_unmap:
- iounmap(priv->base);
- return ret;
-}
-
-static void imx8mp_audiomix_reset_remove(struct auxiliary_device *adev)
-{
- struct imx8mp_audiomix_reset *priv = dev_get_drvdata(&adev->dev);
-
- iounmap(priv->base);
}
static const struct auxiliary_device_id imx8mp_audiomix_reset_ids[] = {
@@ -147,7 +171,6 @@ MODULE_DEVICE_TABLE(auxiliary, imx8mp_audiomix_reset_ids);
static struct auxiliary_driver imx8mp_audiomix_reset_driver = {
.probe = imx8mp_audiomix_reset_probe,
- .remove = imx8mp_audiomix_reset_remove,
.id_table = imx8mp_audiomix_reset_ids,
};
--
2.43.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v4 6/8] reset: imx8mp-audiomix: Extend the driver usage
2025-11-04 12:02 [PATCH v4 0/8] Add support for i.MX8ULP's SIM LPAV Laurentiu Mihalcea
` (4 preceding siblings ...)
2025-11-04 12:02 ` [PATCH v4 5/8] reset: imx8mp-audiomix: Switch to using regmap API Laurentiu Mihalcea
@ 2025-11-04 12:02 ` Laurentiu Mihalcea
2025-11-04 16:46 ` Frank Li
2025-11-04 12:03 ` [PATCH v4 7/8] reset: imx8mp-audiomix: Support i.MX8ULP SIM LPAV Laurentiu Mihalcea
2025-11-04 12:03 ` [PATCH v4 8/8] arm64: dts: imx8ulp: add sim lpav node Laurentiu Mihalcea
7 siblings, 1 reply; 18+ messages in thread
From: Laurentiu Mihalcea @ 2025-11-04 12:02 UTC (permalink / raw)
To: Abel Vesa, Michael Turquette, Stephen Boyd, Krzysztof Kozlowski,
Conor Dooley, Shawn Guo, Fabio Estevam, Philipp Zabel,
Daniel Baluta, Shengjiu Wang, Frank Li
Cc: linux-clk, imx, devicetree, linux-arm-kernel, linux-kernel,
Pengutronix Kernel Team
From: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
Switch to per-device reset map to allow reusing the driver for other NXP
block control IPs.
Reviewed-by: Daniel Baluta <daniel.baluta@nxp.com>
Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
---
drivers/reset/reset-imx8mp-audiomix.c | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/drivers/reset/reset-imx8mp-audiomix.c b/drivers/reset/reset-imx8mp-audiomix.c
index 18a7f68aa59f..745b7e22b954 100644
--- a/drivers/reset/reset-imx8mp-audiomix.c
+++ b/drivers/reset/reset-imx8mp-audiomix.c
@@ -23,7 +23,12 @@ struct imx8mp_reset_map {
bool active_low;
};
-static const struct imx8mp_reset_map reset_map[] = {
+struct imx8mp_reset_info {
+ const struct imx8mp_reset_map *map;
+ int num_lines;
+};
+
+static const struct imx8mp_reset_map imx8mp_reset_map[] = {
[IMX8MP_AUDIOMIX_EARC_RESET] = {
.offset = IMX8MP_AUDIOMIX_EARC_RESET_OFFSET,
.mask = BIT(0),
@@ -41,9 +46,15 @@ static const struct imx8mp_reset_map reset_map[] = {
},
};
+static const struct imx8mp_reset_info imx8mp_reset_info = {
+ .map = imx8mp_reset_map,
+ .num_lines = ARRAY_SIZE(imx8mp_reset_map),
+};
+
struct imx8mp_audiomix_reset {
struct reset_controller_dev rcdev;
struct regmap *regmap;
+ const struct imx8mp_reset_info *rinfo;
};
static struct imx8mp_audiomix_reset *to_imx8mp_audiomix_reset(struct reset_controller_dev *rcdev)
@@ -55,6 +66,7 @@ static int imx8mp_audiomix_update(struct reset_controller_dev *rcdev,
unsigned long id, bool assert)
{
struct imx8mp_audiomix_reset *priv = to_imx8mp_audiomix_reset(rcdev);
+ const struct imx8mp_reset_map *reset_map = priv->rinfo->map;
unsigned int mask, offset, active_low, shift, val;
mask = reset_map[id].mask;
@@ -141,7 +153,8 @@ static int imx8mp_audiomix_reset_probe(struct auxiliary_device *adev,
return -ENOMEM;
priv->rcdev.owner = THIS_MODULE;
- priv->rcdev.nr_resets = ARRAY_SIZE(reset_map);
+ priv->rinfo = (void *)id->driver_data;
+ priv->rcdev.nr_resets = priv->rinfo->num_lines;
priv->rcdev.ops = &imx8mp_audiomix_reset_ops;
priv->rcdev.of_node = dev->parent->of_node;
priv->rcdev.dev = dev;
@@ -164,6 +177,7 @@ static int imx8mp_audiomix_reset_probe(struct auxiliary_device *adev,
static const struct auxiliary_device_id imx8mp_audiomix_reset_ids[] = {
{
.name = "clk_imx8mp_audiomix.reset",
+ .driver_data = (kernel_ulong_t)&imx8mp_reset_info,
},
{ }
};
--
2.43.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v4 7/8] reset: imx8mp-audiomix: Support i.MX8ULP SIM LPAV
2025-11-04 12:02 [PATCH v4 0/8] Add support for i.MX8ULP's SIM LPAV Laurentiu Mihalcea
` (5 preceding siblings ...)
2025-11-04 12:02 ` [PATCH v4 6/8] reset: imx8mp-audiomix: Extend the driver usage Laurentiu Mihalcea
@ 2025-11-04 12:03 ` Laurentiu Mihalcea
2025-11-04 12:03 ` [PATCH v4 8/8] arm64: dts: imx8ulp: add sim lpav node Laurentiu Mihalcea
7 siblings, 0 replies; 18+ messages in thread
From: Laurentiu Mihalcea @ 2025-11-04 12:03 UTC (permalink / raw)
To: Abel Vesa, Michael Turquette, Stephen Boyd, Krzysztof Kozlowski,
Conor Dooley, Shawn Guo, Fabio Estevam, Philipp Zabel,
Daniel Baluta, Shengjiu Wang, Frank Li
Cc: linux-clk, imx, devicetree, linux-arm-kernel, linux-kernel,
Pengutronix Kernel Team
From: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
Support i.MX8ULP's SIM LPAV by adding its reset map definition.
Reviewed-by: Daniel Baluta <daniel.baluta@nxp.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
---
drivers/reset/reset-imx8mp-audiomix.c | 45 +++++++++++++++++++++++++++
1 file changed, 45 insertions(+)
diff --git a/drivers/reset/reset-imx8mp-audiomix.c b/drivers/reset/reset-imx8mp-audiomix.c
index 745b7e22b954..af8d585d6c18 100644
--- a/drivers/reset/reset-imx8mp-audiomix.c
+++ b/drivers/reset/reset-imx8mp-audiomix.c
@@ -3,6 +3,7 @@
* Copyright 2024 NXP
*/
+#include <dt-bindings/reset/fsl,imx8ulp-sim-lpav.h>
#include <dt-bindings/reset/imx8mp-reset-audiomix.h>
#include <linux/auxiliary_bus.h>
@@ -17,6 +18,8 @@
#define IMX8MP_AUDIOMIX_EARC_RESET_OFFSET 0x200
#define IMX8MP_AUDIOMIX_DSP_RUNSTALL_OFFSET 0x108
+#define IMX8ULP_SIM_LPAV_SYSCTRL0_OFFSET 0x8
+
struct imx8mp_reset_map {
unsigned int offset;
unsigned int mask;
@@ -51,6 +54,44 @@ static const struct imx8mp_reset_info imx8mp_reset_info = {
.num_lines = ARRAY_SIZE(imx8mp_reset_map),
};
+static const struct imx8mp_reset_map imx8ulp_reset_map[] = {
+ [IMX8ULP_SIM_LPAV_HIFI4_DSP_DBG_RST] = {
+ .offset = IMX8ULP_SIM_LPAV_SYSCTRL0_OFFSET,
+ .mask = BIT(25),
+ .active_low = false,
+ },
+ [IMX8ULP_SIM_LPAV_HIFI4_DSP_RST] = {
+ .offset = IMX8ULP_SIM_LPAV_SYSCTRL0_OFFSET,
+ .mask = BIT(16),
+ .active_low = false,
+ },
+ [IMX8ULP_SIM_LPAV_HIFI4_DSP_STALL] = {
+ .offset = IMX8ULP_SIM_LPAV_SYSCTRL0_OFFSET,
+ .mask = BIT(13),
+ .active_low = false,
+ },
+ [IMX8ULP_SIM_LPAV_DSI_RST_BYTE_N] = {
+ .offset = IMX8ULP_SIM_LPAV_SYSCTRL0_OFFSET,
+ .mask = BIT(5),
+ .active_low = true,
+ },
+ [IMX8ULP_SIM_LPAV_DSI_RST_ESC_N] = {
+ .offset = IMX8ULP_SIM_LPAV_SYSCTRL0_OFFSET,
+ .mask = BIT(4),
+ .active_low = true,
+ },
+ [IMX8ULP_SIM_LPAV_DSI_RST_DPI_N] = {
+ .offset = IMX8ULP_SIM_LPAV_SYSCTRL0_OFFSET,
+ .mask = BIT(3),
+ .active_low = true,
+ },
+};
+
+static const struct imx8mp_reset_info imx8ulp_reset_info = {
+ .map = imx8ulp_reset_map,
+ .num_lines = ARRAY_SIZE(imx8ulp_reset_map),
+};
+
struct imx8mp_audiomix_reset {
struct reset_controller_dev rcdev;
struct regmap *regmap;
@@ -179,6 +220,10 @@ static const struct auxiliary_device_id imx8mp_audiomix_reset_ids[] = {
.name = "clk_imx8mp_audiomix.reset",
.driver_data = (kernel_ulong_t)&imx8mp_reset_info,
},
+ {
+ .name = "clk_imx8ulp_sim_lpav.reset",
+ .driver_data = (kernel_ulong_t)&imx8ulp_reset_info,
+ },
{ }
};
MODULE_DEVICE_TABLE(auxiliary, imx8mp_audiomix_reset_ids);
--
2.43.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v4 8/8] arm64: dts: imx8ulp: add sim lpav node
2025-11-04 12:02 [PATCH v4 0/8] Add support for i.MX8ULP's SIM LPAV Laurentiu Mihalcea
` (6 preceding siblings ...)
2025-11-04 12:03 ` [PATCH v4 7/8] reset: imx8mp-audiomix: Support i.MX8ULP SIM LPAV Laurentiu Mihalcea
@ 2025-11-04 12:03 ` Laurentiu Mihalcea
7 siblings, 0 replies; 18+ messages in thread
From: Laurentiu Mihalcea @ 2025-11-04 12:03 UTC (permalink / raw)
To: Abel Vesa, Michael Turquette, Stephen Boyd, Krzysztof Kozlowski,
Conor Dooley, Shawn Guo, Fabio Estevam, Philipp Zabel,
Daniel Baluta, Shengjiu Wang, Frank Li
Cc: linux-clk, imx, devicetree, linux-arm-kernel, linux-kernel,
Pengutronix Kernel Team
From: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
Add DT node for the SIM LPAV module.
Reviewed-by: Daniel Baluta <daniel.baluta@nxp.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
---
arch/arm64/boot/dts/freescale/imx8ulp.dtsi | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/arch/arm64/boot/dts/freescale/imx8ulp.dtsi b/arch/arm64/boot/dts/freescale/imx8ulp.dtsi
index 13b01f3aa2a4..9b5d98766512 100644
--- a/arch/arm64/boot/dts/freescale/imx8ulp.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8ulp.dtsi
@@ -776,6 +776,23 @@ edma2: dma-controller@2d800000 {
"ch28", "ch29", "ch30", "ch31";
};
+ sim_lpav: clock-controller@2da50000 {
+ compatible = "fsl,imx8ulp-sim-lpav";
+ reg = <0x2da50000 0x10000>;
+ clocks = <&cgc2 IMX8ULP_CLK_LPAV_BUS_DIV>,
+ <&cgc2 IMX8ULP_CLK_HIFI_DIVCORE>,
+ <&cgc2 IMX8ULP_CLK_HIFI_DIVPLAT>;
+ clock-names = "bus", "core", "plat";
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+
+ sim_lpav_mux: mux-controller {
+ compatible = "reg-mux";
+ #mux-control-cells = <1>;
+ mux-reg-masks = <0x8 0x00000200>;
+ };
+ };
+
cgc2: clock-controller@2da60000 {
compatible = "fsl,imx8ulp-cgc2";
reg = <0x2da60000 0x10000>;
--
2.43.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* RE: [PATCH v4 3/8] clk: imx: add driver for imx8ulp's sim lpav
2025-11-04 12:02 ` [PATCH v4 3/8] clk: imx: add driver for imx8ulp's sim lpav Laurentiu Mihalcea
@ 2025-11-04 12:45 ` Peng Fan
2025-11-05 9:36 ` Daniel Baluta
1 sibling, 0 replies; 18+ messages in thread
From: Peng Fan @ 2025-11-04 12:45 UTC (permalink / raw)
To: Laurentiu Mihalcea, Abel Vesa, Michael Turquette, Stephen Boyd,
Krzysztof Kozlowski, Conor Dooley, Shawn Guo, Fabio Estevam,
Philipp Zabel, Daniel Baluta, S.J. Wang, Frank Li
Cc: linux-clk@vger.kernel.org, imx@lists.linux.dev,
devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, Pengutronix Kernel Team
> Subject: [PATCH v4 3/8] clk: imx: add driver for imx8ulp's sim lpav
>
> From: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
>
> The i.MX8ULP System Integration Module (SIM) LPAV module is a
> block control module found inside the LPAV subsystem, which offers
> some clock gating options and reset line assertion/de-assertion
> capabilities.
>
> Therefore, the clock gate management is supported by registering the
> module's driver as a clock provider, while the reset capabilities are
> managed via the auxiliary device API to allow the DT node to act as a
> reset and clock provider.
>
> Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
Reviewed-by: Peng Fan <peng.fan@nxp.com>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v4 5/8] reset: imx8mp-audiomix: Switch to using regmap API
2025-11-04 12:02 ` [PATCH v4 5/8] reset: imx8mp-audiomix: Switch to using regmap API Laurentiu Mihalcea
@ 2025-11-04 16:44 ` Frank Li
2025-11-05 11:53 ` Laurentiu Mihalcea
2025-11-05 15:10 ` Philipp Zabel
1 sibling, 1 reply; 18+ messages in thread
From: Frank Li @ 2025-11-04 16:44 UTC (permalink / raw)
To: Laurentiu Mihalcea
Cc: Abel Vesa, Michael Turquette, Stephen Boyd, Krzysztof Kozlowski,
Conor Dooley, Shawn Guo, Fabio Estevam, Philipp Zabel,
Daniel Baluta, Shengjiu Wang, linux-clk, imx, devicetree,
linux-arm-kernel, linux-kernel, Pengutronix Kernel Team
On Tue, Nov 04, 2025 at 04:02:58AM -0800, Laurentiu Mihalcea wrote:
> From: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
>
> Switch to using the regmap API to allow performing register operations
> under the same lock. This is needed for cases such as i.MX8ULP's SIM LPAV
> where clock gating, reset control and MUX-ing is performed via the same
> register (i.e. SYSCTRL0) and different subsystem APIs.
>
> Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
> ---
> drivers/reset/reset-imx8mp-audiomix.c | 93 +++++++++++++++++----------
> 1 file changed, 58 insertions(+), 35 deletions(-)
>
> diff --git a/drivers/reset/reset-imx8mp-audiomix.c b/drivers/reset/reset-imx8mp-audiomix.c
> index e9643365a62c..18a7f68aa59f 100644
> --- a/drivers/reset/reset-imx8mp-audiomix.c
> +++ b/drivers/reset/reset-imx8mp-audiomix.c
> @@ -11,6 +11,7 @@
> #include <linux/module.h>
> #include <linux/of.h>
> #include <linux/of_address.h>
> +#include <linux/regmap.h>
> #include <linux/reset-controller.h>
>
> #define IMX8MP_AUDIOMIX_EARC_RESET_OFFSET 0x200
> @@ -42,8 +43,7 @@ static const struct imx8mp_reset_map reset_map[] = {
>
> struct imx8mp_audiomix_reset {
> struct reset_controller_dev rcdev;
> - spinlock_t lock; /* protect register read-modify-write cycle */
> - void __iomem *base;
> + struct regmap *regmap;
> };
>
> static struct imx8mp_audiomix_reset *to_imx8mp_audiomix_reset(struct reset_controller_dev *rcdev)
> @@ -55,26 +55,15 @@ static int imx8mp_audiomix_update(struct reset_controller_dev *rcdev,
> unsigned long id, bool assert)
> {
> struct imx8mp_audiomix_reset *priv = to_imx8mp_audiomix_reset(rcdev);
> - void __iomem *reg_addr = priv->base;
> - unsigned int mask, offset, active_low;
> - unsigned long reg, flags;
> + unsigned int mask, offset, active_low, shift, val;
>
> mask = reset_map[id].mask;
> offset = reset_map[id].offset;
> active_low = reset_map[id].active_low;
> + shift = ffs(mask) - 1;
> + val = (active_low ^ assert) << shift;
>
> - spin_lock_irqsave(&priv->lock, flags);
> -
> - reg = readl(reg_addr + offset);
> - if (active_low ^ assert)
> - reg |= mask;
> - else
> - reg &= ~mask;
> - writel(reg, reg_addr + offset);
> -
> - spin_unlock_irqrestore(&priv->lock, flags);
> -
> - return 0;
> + return regmap_update_bits(priv->regmap, offset, mask, val);
> }
>
> static int imx8mp_audiomix_reset_assert(struct reset_controller_dev *rcdev,
> @@ -94,6 +83,52 @@ static const struct reset_control_ops imx8mp_audiomix_reset_ops = {
> .deassert = imx8mp_audiomix_reset_deassert,
> };
>
> +static const struct regmap_config regmap_config = {
> + .reg_bits = 32,
> + .val_bits = 32,
> + .reg_stride = 4,
> +};
> +
> +/* assumption: registered only if not using parent regmap */
> +static void imx8mp_audiomix_reset_iounmap(void *data)
> +{
> + void __iomem *base = (void __iomem *)data;
> +
> + iounmap(base);
> +}
> +
> +static int imx8mp_audiomix_reset_get_regmap(struct imx8mp_audiomix_reset *priv)
> +{
> + void __iomem *base;
> + struct device *dev;
> + int ret;
> +
> + dev = priv->rcdev.dev;
> +
> + /* try to use the parent's regmap */
> + priv->regmap = dev_get_regmap(dev->parent, NULL);
> + if (priv->regmap)
> + return 0;
> +
> + /* ... if that's not possible then initialize the regmap right now */
> + base = of_iomap(dev->parent->of_node, 0);
> + if (!base)
> + return dev_err_probe(dev, -ENOMEM, "failed to iomap address space\n");
> +
> + ret = devm_add_action_or_reset(dev,
> + imx8mp_audiomix_reset_iounmap,
> + (void __force *)base);
> + if (ret)
> + return dev_err_probe(dev, ret, "failed to register action\n");
> +
> + priv->regmap = devm_regmap_init_mmio(dev, base, ®map_config);
> + if (IS_ERR(priv->regmap))
> + return dev_err_probe(dev, PTR_ERR(priv->regmap),
> + "failed to initialize regmap\n");
Does anyone still base? Supposed aux device probed by parent devices,
if all parent already switch to regmap, you can remove this part.
Frank
> +
> + return 0;
> +}
> +
> static int imx8mp_audiomix_reset_probe(struct auxiliary_device *adev,
> const struct auxiliary_device_id *id)
> {
> @@ -105,36 +140,25 @@ static int imx8mp_audiomix_reset_probe(struct auxiliary_device *adev,
> if (!priv)
> return -ENOMEM;
>
> - spin_lock_init(&priv->lock);
> -
> priv->rcdev.owner = THIS_MODULE;
> priv->rcdev.nr_resets = ARRAY_SIZE(reset_map);
> priv->rcdev.ops = &imx8mp_audiomix_reset_ops;
> priv->rcdev.of_node = dev->parent->of_node;
> priv->rcdev.dev = dev;
> priv->rcdev.of_reset_n_cells = 1;
> - priv->base = of_iomap(dev->parent->of_node, 0);
> - if (!priv->base)
> - return -ENOMEM;
>
> dev_set_drvdata(dev, priv);
>
> + ret = imx8mp_audiomix_reset_get_regmap(priv);
> + if (ret)
> + return dev_err_probe(dev, ret, "failed to get regmap\n");
> +
> ret = devm_reset_controller_register(dev, &priv->rcdev);
> if (ret)
> - goto out_unmap;
> + return dev_err_probe(dev, ret,
> + "failed to register reset controller\n");
>
> return 0;
> -
> -out_unmap:
> - iounmap(priv->base);
> - return ret;
> -}
> -
> -static void imx8mp_audiomix_reset_remove(struct auxiliary_device *adev)
> -{
> - struct imx8mp_audiomix_reset *priv = dev_get_drvdata(&adev->dev);
> -
> - iounmap(priv->base);
> }
>
> static const struct auxiliary_device_id imx8mp_audiomix_reset_ids[] = {
> @@ -147,7 +171,6 @@ MODULE_DEVICE_TABLE(auxiliary, imx8mp_audiomix_reset_ids);
>
> static struct auxiliary_driver imx8mp_audiomix_reset_driver = {
> .probe = imx8mp_audiomix_reset_probe,
> - .remove = imx8mp_audiomix_reset_remove,
> .id_table = imx8mp_audiomix_reset_ids,
> };
>
> --
> 2.43.0
>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v4 6/8] reset: imx8mp-audiomix: Extend the driver usage
2025-11-04 12:02 ` [PATCH v4 6/8] reset: imx8mp-audiomix: Extend the driver usage Laurentiu Mihalcea
@ 2025-11-04 16:46 ` Frank Li
0 siblings, 0 replies; 18+ messages in thread
From: Frank Li @ 2025-11-04 16:46 UTC (permalink / raw)
To: Laurentiu Mihalcea
Cc: Abel Vesa, Michael Turquette, Stephen Boyd, Krzysztof Kozlowski,
Conor Dooley, Shawn Guo, Fabio Estevam, Philipp Zabel,
Daniel Baluta, Shengjiu Wang, linux-clk, imx, devicetree,
linux-arm-kernel, linux-kernel, Pengutronix Kernel Team
On Tue, Nov 04, 2025 at 04:02:59AM -0800, Laurentiu Mihalcea wrote:
> From: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
>
> Switch to per-device reset map to allow reusing the driver for other NXP
> block control IPs.
>
> Reviewed-by: Daniel Baluta <daniel.baluta@nxp.com>
> Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
> ---
> drivers/reset/reset-imx8mp-audiomix.c | 18 ++++++++++++++++--
> 1 file changed, 16 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/reset/reset-imx8mp-audiomix.c b/drivers/reset/reset-imx8mp-audiomix.c
> index 18a7f68aa59f..745b7e22b954 100644
> --- a/drivers/reset/reset-imx8mp-audiomix.c
> +++ b/drivers/reset/reset-imx8mp-audiomix.c
> @@ -23,7 +23,12 @@ struct imx8mp_reset_map {
> bool active_low;
> };
>
> -static const struct imx8mp_reset_map reset_map[] = {
> +struct imx8mp_reset_info {
> + const struct imx8mp_reset_map *map;
> + int num_lines;
> +};
> +
> +static const struct imx8mp_reset_map imx8mp_reset_map[] = {
> [IMX8MP_AUDIOMIX_EARC_RESET] = {
> .offset = IMX8MP_AUDIOMIX_EARC_RESET_OFFSET,
> .mask = BIT(0),
> @@ -41,9 +46,15 @@ static const struct imx8mp_reset_map reset_map[] = {
> },
> };
>
> +static const struct imx8mp_reset_info imx8mp_reset_info = {
> + .map = imx8mp_reset_map,
> + .num_lines = ARRAY_SIZE(imx8mp_reset_map),
> +};
> +
> struct imx8mp_audiomix_reset {
> struct reset_controller_dev rcdev;
> struct regmap *regmap;
> + const struct imx8mp_reset_info *rinfo;
> };
>
> static struct imx8mp_audiomix_reset *to_imx8mp_audiomix_reset(struct reset_controller_dev *rcdev)
> @@ -55,6 +66,7 @@ static int imx8mp_audiomix_update(struct reset_controller_dev *rcdev,
> unsigned long id, bool assert)
> {
> struct imx8mp_audiomix_reset *priv = to_imx8mp_audiomix_reset(rcdev);
> + const struct imx8mp_reset_map *reset_map = priv->rinfo->map;
> unsigned int mask, offset, active_low, shift, val;
>
> mask = reset_map[id].mask;
> @@ -141,7 +153,8 @@ static int imx8mp_audiomix_reset_probe(struct auxiliary_device *adev,
> return -ENOMEM;
>
> priv->rcdev.owner = THIS_MODULE;
> - priv->rcdev.nr_resets = ARRAY_SIZE(reset_map);
> + priv->rinfo = (void *)id->driver_data;
> + priv->rcdev.nr_resets = priv->rinfo->num_lines;
> priv->rcdev.ops = &imx8mp_audiomix_reset_ops;
> priv->rcdev.of_node = dev->parent->of_node;
> priv->rcdev.dev = dev;
> @@ -164,6 +177,7 @@ static int imx8mp_audiomix_reset_probe(struct auxiliary_device *adev,
> static const struct auxiliary_device_id imx8mp_audiomix_reset_ids[] = {
> {
> .name = "clk_imx8mp_audiomix.reset",
> + .driver_data = (kernel_ulong_t)&imx8mp_reset_info,
> },
> { }
> };
> --
> 2.43.0
>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v4 3/8] clk: imx: add driver for imx8ulp's sim lpav
2025-11-04 12:02 ` [PATCH v4 3/8] clk: imx: add driver for imx8ulp's sim lpav Laurentiu Mihalcea
2025-11-04 12:45 ` Peng Fan
@ 2025-11-05 9:36 ` Daniel Baluta
1 sibling, 0 replies; 18+ messages in thread
From: Daniel Baluta @ 2025-11-05 9:36 UTC (permalink / raw)
To: Laurentiu Mihalcea
Cc: Abel Vesa, Michael Turquette, Stephen Boyd, Krzysztof Kozlowski,
Conor Dooley, Shawn Guo, Fabio Estevam, Philipp Zabel,
Daniel Baluta, Shengjiu Wang, Frank Li, linux-clk, imx,
devicetree, linux-arm-kernel, linux-kernel,
Pengutronix Kernel Team
On Tue, Nov 4, 2025 at 2:05 PM Laurentiu Mihalcea
<laurentiumihalcea111@gmail.com> wrote:
>
> From: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
>
> The i.MX8ULP System Integration Module (SIM) LPAV module is a block
> control module found inside the LPAV subsystem, which offers some clock
> gating options and reset line assertion/de-assertion capabilities.
>
> Therefore, the clock gate management is supported by registering the
> module's driver as a clock provider, while the reset capabilities are
> managed via the auxiliary device API to allow the DT node to act as a
> reset and clock provider.
>
> Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
Reviewed-by: Daniel Baluta <daniel.baluta@nxp.com>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v4 5/8] reset: imx8mp-audiomix: Switch to using regmap API
2025-11-04 16:44 ` Frank Li
@ 2025-11-05 11:53 ` Laurentiu Mihalcea
2025-11-05 15:23 ` Frank Li
0 siblings, 1 reply; 18+ messages in thread
From: Laurentiu Mihalcea @ 2025-11-05 11:53 UTC (permalink / raw)
To: Frank Li
Cc: Abel Vesa, Michael Turquette, Stephen Boyd, Krzysztof Kozlowski,
Conor Dooley, Shawn Guo, Fabio Estevam, Philipp Zabel,
Daniel Baluta, Shengjiu Wang, linux-clk, imx, devicetree,
linux-arm-kernel, linux-kernel, Pengutronix Kernel Team
On 11/4/2025 8:44 AM, Frank Li wrote:
> On Tue, Nov 04, 2025 at 04:02:58AM -0800, Laurentiu Mihalcea wrote:
>> From: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
>>
>> Switch to using the regmap API to allow performing register operations
>> under the same lock. This is needed for cases such as i.MX8ULP's SIM LPAV
>> where clock gating, reset control and MUX-ing is performed via the same
>> register (i.e. SYSCTRL0) and different subsystem APIs.
>>
>> Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
>> ---
>> drivers/reset/reset-imx8mp-audiomix.c | 93 +++++++++++++++++----------
>> 1 file changed, 58 insertions(+), 35 deletions(-)
>>
>> diff --git a/drivers/reset/reset-imx8mp-audiomix.c b/drivers/reset/reset-imx8mp-audiomix.c
>> index e9643365a62c..18a7f68aa59f 100644
>> --- a/drivers/reset/reset-imx8mp-audiomix.c
>> +++ b/drivers/reset/reset-imx8mp-audiomix.c
>> @@ -11,6 +11,7 @@
>> #include <linux/module.h>
>> #include <linux/of.h>
>> #include <linux/of_address.h>
>> +#include <linux/regmap.h>
>> #include <linux/reset-controller.h>
>>
>> #define IMX8MP_AUDIOMIX_EARC_RESET_OFFSET 0x200
>> @@ -42,8 +43,7 @@ static const struct imx8mp_reset_map reset_map[] = {
>>
>> struct imx8mp_audiomix_reset {
>> struct reset_controller_dev rcdev;
>> - spinlock_t lock; /* protect register read-modify-write cycle */
>> - void __iomem *base;
>> + struct regmap *regmap;
>> };
>>
>> static struct imx8mp_audiomix_reset *to_imx8mp_audiomix_reset(struct reset_controller_dev *rcdev)
>> @@ -55,26 +55,15 @@ static int imx8mp_audiomix_update(struct reset_controller_dev *rcdev,
>> unsigned long id, bool assert)
>> {
>> struct imx8mp_audiomix_reset *priv = to_imx8mp_audiomix_reset(rcdev);
>> - void __iomem *reg_addr = priv->base;
>> - unsigned int mask, offset, active_low;
>> - unsigned long reg, flags;
>> + unsigned int mask, offset, active_low, shift, val;
>>
>> mask = reset_map[id].mask;
>> offset = reset_map[id].offset;
>> active_low = reset_map[id].active_low;
>> + shift = ffs(mask) - 1;
>> + val = (active_low ^ assert) << shift;
>>
>> - spin_lock_irqsave(&priv->lock, flags);
>> -
>> - reg = readl(reg_addr + offset);
>> - if (active_low ^ assert)
>> - reg |= mask;
>> - else
>> - reg &= ~mask;
>> - writel(reg, reg_addr + offset);
>> -
>> - spin_unlock_irqrestore(&priv->lock, flags);
>> -
>> - return 0;
>> + return regmap_update_bits(priv->regmap, offset, mask, val);
>> }
>>
>> static int imx8mp_audiomix_reset_assert(struct reset_controller_dev *rcdev,
>> @@ -94,6 +83,52 @@ static const struct reset_control_ops imx8mp_audiomix_reset_ops = {
>> .deassert = imx8mp_audiomix_reset_deassert,
>> };
>>
>> +static const struct regmap_config regmap_config = {
>> + .reg_bits = 32,
>> + .val_bits = 32,
>> + .reg_stride = 4,
>> +};
>> +
>> +/* assumption: registered only if not using parent regmap */
>> +static void imx8mp_audiomix_reset_iounmap(void *data)
>> +{
>> + void __iomem *base = (void __iomem *)data;
>> +
>> + iounmap(base);
>> +}
>> +
>> +static int imx8mp_audiomix_reset_get_regmap(struct imx8mp_audiomix_reset *priv)
>> +{
>> + void __iomem *base;
>> + struct device *dev;
>> + int ret;
>> +
>> + dev = priv->rcdev.dev;
>> +
>> + /* try to use the parent's regmap */
>> + priv->regmap = dev_get_regmap(dev->parent, NULL);
>> + if (priv->regmap)
>> + return 0;
>> +
>> + /* ... if that's not possible then initialize the regmap right now */
>> + base = of_iomap(dev->parent->of_node, 0);
>> + if (!base)
>> + return dev_err_probe(dev, -ENOMEM, "failed to iomap address space\n");
>> +
>> + ret = devm_add_action_or_reset(dev,
>> + imx8mp_audiomix_reset_iounmap,
>> + (void __force *)base);
>> + if (ret)
>> + return dev_err_probe(dev, ret, "failed to register action\n");
>> +
>> + priv->regmap = devm_regmap_init_mmio(dev, base, ®map_config);
>> + if (IS_ERR(priv->regmap))
>> + return dev_err_probe(dev, PTR_ERR(priv->regmap),
>> + "failed to initialize regmap\n");
> Does anyone still base? Supposed aux device probed by parent devices,
> if all parent already switch to regmap, you can remove this part.
>
> Frank
both clk-imx8ulp-sim-lpav and clk-imx8mp-audiomix don't handle the clock gate
functionality by themselves. Instead, they use the generic clock gate driver, which
doesn't use regmap. ATM, I don't plan on extending that to use regmap (how would
that work? would we want that? would it be useful for other people as well?)
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v4 4/8] reset: imx8mp-audiomix: Drop unneeded macros
2025-11-04 12:02 ` [PATCH v4 4/8] reset: imx8mp-audiomix: Drop unneeded macros Laurentiu Mihalcea
@ 2025-11-05 15:10 ` Philipp Zabel
0 siblings, 0 replies; 18+ messages in thread
From: Philipp Zabel @ 2025-11-05 15:10 UTC (permalink / raw)
To: Laurentiu Mihalcea, Abel Vesa, Michael Turquette, Stephen Boyd,
Krzysztof Kozlowski, Conor Dooley, Shawn Guo, Fabio Estevam,
Daniel Baluta, Shengjiu Wang, Frank Li
Cc: linux-clk, imx, devicetree, linux-arm-kernel, linux-kernel,
Pengutronix Kernel Team
On Di, 2025-11-04 at 04:02 -0800, Laurentiu Mihalcea wrote:
> From: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
>
> The macros defining the mask values for the EARC, EARC PHY resets,
> and the DSP RUN_STALL signal can be dropped as they are not and will
> not be used anywhere else except to set the value of the "mask" field
> from "struct imx8mp_reset_map". In this particular case, based on the
> name of the "mask" field, you can already deduce what these values are
> for, which is why defining macros for them doesn't offer any new
> information, nor does it help with the code readability.
>
> Reviewed-by: Daniel Baluta <daniel.baluta@nxp.com>
> Reviewed-by: Frank Li <Frank.Li@nxp.com>
> Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
> ---
> drivers/reset/reset-imx8mp-audiomix.c | 10 +++-------
> 1 file changed, 3 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/reset/reset-imx8mp-audiomix.c b/drivers/reset/reset-imx8mp-audiomix.c
> index eceb37ff5dc5..e9643365a62c 100644
> --- a/drivers/reset/reset-imx8mp-audiomix.c
> +++ b/drivers/reset/reset-imx8mp-audiomix.c
> @@ -14,11 +14,7 @@
> #include <linux/reset-controller.h>
>
> #define IMX8MP_AUDIOMIX_EARC_RESET_OFFSET 0x200
> -#define IMX8MP_AUDIOMIX_EARC_RESET_MASK BIT(0)
> -#define IMX8MP_AUDIOMIX_EARC_PHY_RESET_MASK BIT(1)
> -
> #define IMX8MP_AUDIOMIX_DSP_RUNSTALL_OFFSET 0x108
> -#define IMX8MP_AUDIOMIX_DSP_RUNSTALL_MASK BIT(5)
>
> struct imx8mp_reset_map {
> unsigned int offset;
> @@ -29,17 +25,17 @@ struct imx8mp_reset_map {
> static const struct imx8mp_reset_map reset_map[] = {
> [IMX8MP_AUDIOMIX_EARC_RESET] = {
> .offset = IMX8MP_AUDIOMIX_EARC_RESET_OFFSET,
> - .mask = IMX8MP_AUDIOMIX_EARC_RESET_MASK,
> + .mask = BIT(0),
Since the masks are all single-bit, and you make that mandatory in the
next patch, I suggest storing the bit offset in the reset map instead:
- .mask = IMX8MP_AUDIOMIX_EARC_RESET_MASK,
+ .bit = 0,
and so on. That way it's clear that no reset control ever manipulates
multiple bits at the same time.
Either way, either in this patch or the next, add an
#include <linux/bits.h>
for BIT().
regards
Philipp
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v4 5/8] reset: imx8mp-audiomix: Switch to using regmap API
2025-11-04 12:02 ` [PATCH v4 5/8] reset: imx8mp-audiomix: Switch to using regmap API Laurentiu Mihalcea
2025-11-04 16:44 ` Frank Li
@ 2025-11-05 15:10 ` Philipp Zabel
1 sibling, 0 replies; 18+ messages in thread
From: Philipp Zabel @ 2025-11-05 15:10 UTC (permalink / raw)
To: Laurentiu Mihalcea, Abel Vesa, Michael Turquette, Stephen Boyd,
Krzysztof Kozlowski, Conor Dooley, Shawn Guo, Fabio Estevam,
Daniel Baluta, Shengjiu Wang, Frank Li
Cc: linux-clk, imx, devicetree, linux-arm-kernel, linux-kernel,
Pengutronix Kernel Team
On Di, 2025-11-04 at 04:02 -0800, Laurentiu Mihalcea wrote:
> From: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
>
> Switch to using the regmap API to allow performing register operations
> under the same lock. This is needed for cases such as i.MX8ULP's SIM LPAV
> where clock gating, reset control and MUX-ing is performed via the same
> register (i.e. SYSCTRL0) and different subsystem APIs.
>
> Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
> ---
> drivers/reset/reset-imx8mp-audiomix.c | 93 +++++++++++++++++----------
> 1 file changed, 58 insertions(+), 35 deletions(-)
>
> diff --git a/drivers/reset/reset-imx8mp-audiomix.c b/drivers/reset/reset-imx8mp-audiomix.c
> index e9643365a62c..18a7f68aa59f 100644
> --- a/drivers/reset/reset-imx8mp-audiomix.c
> +++ b/drivers/reset/reset-imx8mp-audiomix.c
> @@ -11,6 +11,7 @@
> #include <linux/module.h>
> #include <linux/of.h>
> #include <linux/of_address.h>
> +#include <linux/regmap.h>
> #include <linux/reset-controller.h>
>
> #define IMX8MP_AUDIOMIX_EARC_RESET_OFFSET 0x200
> @@ -42,8 +43,7 @@ static const struct imx8mp_reset_map reset_map[] = {
>
> struct imx8mp_audiomix_reset {
> struct reset_controller_dev rcdev;
> - spinlock_t lock; /* protect register read-modify-write cycle */
> - void __iomem *base;
> + struct regmap *regmap;
> };
>
> static struct imx8mp_audiomix_reset *to_imx8mp_audiomix_reset(struct reset_controller_dev *rcdev)
> @@ -55,26 +55,15 @@ static int imx8mp_audiomix_update(struct reset_controller_dev *rcdev,
> unsigned long id, bool assert)
> {
> struct imx8mp_audiomix_reset *priv = to_imx8mp_audiomix_reset(rcdev);
> - void __iomem *reg_addr = priv->base;
> - unsigned int mask, offset, active_low;
> - unsigned long reg, flags;
> + unsigned int mask, offset, active_low, shift, val;
>
> mask = reset_map[id].mask;
> offset = reset_map[id].offset;
> active_low = reset_map[id].active_low;
> + shift = ffs(mask) - 1;
> + val = (active_low ^ assert) << shift;
If you store the bit offset in the reset map, this can become
mask = BIT(reset_map[id].bit);
/* ... */
val = (active_low ^ assert) << reset_map[id].bit;
regards
Philipp
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v4 1/8] reset: imx8mp-audiomix: Fix bad mask values
2025-11-04 12:02 ` [PATCH v4 1/8] reset: imx8mp-audiomix: Fix bad mask values Laurentiu Mihalcea
@ 2025-11-05 15:16 ` Philipp Zabel
0 siblings, 0 replies; 18+ messages in thread
From: Philipp Zabel @ 2025-11-05 15:16 UTC (permalink / raw)
To: Laurentiu Mihalcea, Abel Vesa, Michael Turquette, Stephen Boyd,
Krzysztof Kozlowski, Conor Dooley, Shawn Guo, Fabio Estevam,
Daniel Baluta, Shengjiu Wang, Frank Li
Cc: linux-clk, imx, devicetree, linux-arm-kernel, linux-kernel,
Pengutronix Kernel Team
On Di, 2025-11-04 at 04:02 -0800, Laurentiu Mihalcea wrote:
> From: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
>
> As per the i.MX8MP TRM, section 14.2 "AUDIO_BLK_CTRL", table 14.2.3.1.1
> "memory map", the definition of the EARC control register shows that the
> EARC controller software reset is controlled via bit 0, while the EARC PHY
> software reset is controlled via bit 1.
>
> This means that the current definitions of IMX8MP_AUDIOMIX_EARC_RESET_MASK
> and IMX8MP_AUDIOMIX_EARC_PHY_RESET_MASK are wrong since their values would
> imply that the EARC controller software reset is controlled via bit 1 and
> the EARC PHY software reset is controlled via bit 2. Fix them.
>
> Fixes: a83bc87cd30a ("reset: imx8mp-audiomix: Prepare the code for more reset bits")
> Cc: stable@vger.kernel.org
> Reviewed-by: Shengjiu Wang <shengjiu.wang@gmail.com>
> Reviewed-by: Frank Li <Frank.Li@nxp.com>
> Reviewed-by: Daniel Baluta <daniel.baluta@nxp.com>
> Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
Applied patch 1 to reset/fixes, thanks!
[1/8] reset: imx8mp-audiomix: Fix bad mask values
https://git.pengutronix.de/cgit/pza/linux/commit/?id=997c06330fd5
regards
Philipp
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v4 5/8] reset: imx8mp-audiomix: Switch to using regmap API
2025-11-05 11:53 ` Laurentiu Mihalcea
@ 2025-11-05 15:23 ` Frank Li
0 siblings, 0 replies; 18+ messages in thread
From: Frank Li @ 2025-11-05 15:23 UTC (permalink / raw)
To: Laurentiu Mihalcea
Cc: Abel Vesa, Michael Turquette, Stephen Boyd, Krzysztof Kozlowski,
Conor Dooley, Shawn Guo, Fabio Estevam, Philipp Zabel,
Daniel Baluta, Shengjiu Wang, linux-clk, imx, devicetree,
linux-arm-kernel, linux-kernel, Pengutronix Kernel Team
On Wed, Nov 05, 2025 at 03:53:59AM -0800, Laurentiu Mihalcea wrote:
>
> On 11/4/2025 8:44 AM, Frank Li wrote:
> > On Tue, Nov 04, 2025 at 04:02:58AM -0800, Laurentiu Mihalcea wrote:
> >> From: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
> >>
> >> Switch to using the regmap API to allow performing register operations
> >> under the same lock. This is needed for cases such as i.MX8ULP's SIM LPAV
> >> where clock gating, reset control and MUX-ing is performed via the same
> >> register (i.e. SYSCTRL0) and different subsystem APIs.
> >>
> >> Signed-off-by: Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>
> >> ---
> >> drivers/reset/reset-imx8mp-audiomix.c | 93 +++++++++++++++++----------
> >> 1 file changed, 58 insertions(+), 35 deletions(-)
> >>
> >> diff --git a/drivers/reset/reset-imx8mp-audiomix.c b/drivers/reset/reset-imx8mp-audiomix.c
> >> index e9643365a62c..18a7f68aa59f 100644
> >> --- a/drivers/reset/reset-imx8mp-audiomix.c
> >> +++ b/drivers/reset/reset-imx8mp-audiomix.c
> >> @@ -11,6 +11,7 @@
> >> #include <linux/module.h>
> >> #include <linux/of.h>
> >> #include <linux/of_address.h>
> >> +#include <linux/regmap.h>
> >> #include <linux/reset-controller.h>
> >>
> >> #define IMX8MP_AUDIOMIX_EARC_RESET_OFFSET 0x200
> >> @@ -42,8 +43,7 @@ static const struct imx8mp_reset_map reset_map[] = {
> >>
> >> struct imx8mp_audiomix_reset {
> >> struct reset_controller_dev rcdev;
> >> - spinlock_t lock; /* protect register read-modify-write cycle */
> >> - void __iomem *base;
> >> + struct regmap *regmap;
> >> };
> >>
> >> static struct imx8mp_audiomix_reset *to_imx8mp_audiomix_reset(struct reset_controller_dev *rcdev)
> >> @@ -55,26 +55,15 @@ static int imx8mp_audiomix_update(struct reset_controller_dev *rcdev,
> >> unsigned long id, bool assert)
> >> {
> >> struct imx8mp_audiomix_reset *priv = to_imx8mp_audiomix_reset(rcdev);
> >> - void __iomem *reg_addr = priv->base;
> >> - unsigned int mask, offset, active_low;
> >> - unsigned long reg, flags;
> >> + unsigned int mask, offset, active_low, shift, val;
> >>
> >> mask = reset_map[id].mask;
> >> offset = reset_map[id].offset;
> >> active_low = reset_map[id].active_low;
> >> + shift = ffs(mask) - 1;
> >> + val = (active_low ^ assert) << shift;
> >>
> >> - spin_lock_irqsave(&priv->lock, flags);
> >> -
> >> - reg = readl(reg_addr + offset);
> >> - if (active_low ^ assert)
> >> - reg |= mask;
> >> - else
> >> - reg &= ~mask;
> >> - writel(reg, reg_addr + offset);
> >> -
> >> - spin_unlock_irqrestore(&priv->lock, flags);
> >> -
> >> - return 0;
> >> + return regmap_update_bits(priv->regmap, offset, mask, val);
> >> }
> >>
> >> static int imx8mp_audiomix_reset_assert(struct reset_controller_dev *rcdev,
> >> @@ -94,6 +83,52 @@ static const struct reset_control_ops imx8mp_audiomix_reset_ops = {
> >> .deassert = imx8mp_audiomix_reset_deassert,
> >> };
> >>
> >> +static const struct regmap_config regmap_config = {
> >> + .reg_bits = 32,
> >> + .val_bits = 32,
> >> + .reg_stride = 4,
> >> +};
> >> +
> >> +/* assumption: registered only if not using parent regmap */
> >> +static void imx8mp_audiomix_reset_iounmap(void *data)
> >> +{
> >> + void __iomem *base = (void __iomem *)data;
> >> +
> >> + iounmap(base);
> >> +}
> >> +
> >> +static int imx8mp_audiomix_reset_get_regmap(struct imx8mp_audiomix_reset *priv)
> >> +{
> >> + void __iomem *base;
> >> + struct device *dev;
> >> + int ret;
> >> +
> >> + dev = priv->rcdev.dev;
> >> +
> >> + /* try to use the parent's regmap */
> >> + priv->regmap = dev_get_regmap(dev->parent, NULL);
> >> + if (priv->regmap)
> >> + return 0;
> >> +
> >> + /* ... if that's not possible then initialize the regmap right now */
> >> + base = of_iomap(dev->parent->of_node, 0);
> >> + if (!base)
> >> + return dev_err_probe(dev, -ENOMEM, "failed to iomap address space\n");
> >> +
> >> + ret = devm_add_action_or_reset(dev,
> >> + imx8mp_audiomix_reset_iounmap,
> >> + (void __force *)base);
> >> + if (ret)
> >> + return dev_err_probe(dev, ret, "failed to register action\n");
> >> +
> >> + priv->regmap = devm_regmap_init_mmio(dev, base, ®map_config);
> >> + if (IS_ERR(priv->regmap))
> >> + return dev_err_probe(dev, PTR_ERR(priv->regmap),
> >> + "failed to initialize regmap\n");
> > Does anyone still base? Supposed aux device probed by parent devices,
> > if all parent already switch to regmap, you can remove this part.
> >
> > Frank
>
>
> both clk-imx8ulp-sim-lpav and clk-imx8mp-audiomix don't handle the clock gate
>
> functionality by themselves. Instead, they use the generic clock gate driver, which
>
> doesn't use regmap. ATM, I don't plan on extending that to use regmap (how would
>
> that work? would we want that? would it be useful for other people as well?)
Okay, I suppose parent clock driver use iomap also, which cause map the
same area twice. Although it works, I think it'd better pass down mapped
address to this driver. Anyways you may improve later.
Frank
>
^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2025-11-05 15:24 UTC | newest]
Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-04 12:02 [PATCH v4 0/8] Add support for i.MX8ULP's SIM LPAV Laurentiu Mihalcea
2025-11-04 12:02 ` [PATCH v4 1/8] reset: imx8mp-audiomix: Fix bad mask values Laurentiu Mihalcea
2025-11-05 15:16 ` Philipp Zabel
2025-11-04 12:02 ` [PATCH v4 2/8] dt-bindings: clock: document 8ULP's SIM LPAV Laurentiu Mihalcea
2025-11-04 12:02 ` [PATCH v4 3/8] clk: imx: add driver for imx8ulp's sim lpav Laurentiu Mihalcea
2025-11-04 12:45 ` Peng Fan
2025-11-05 9:36 ` Daniel Baluta
2025-11-04 12:02 ` [PATCH v4 4/8] reset: imx8mp-audiomix: Drop unneeded macros Laurentiu Mihalcea
2025-11-05 15:10 ` Philipp Zabel
2025-11-04 12:02 ` [PATCH v4 5/8] reset: imx8mp-audiomix: Switch to using regmap API Laurentiu Mihalcea
2025-11-04 16:44 ` Frank Li
2025-11-05 11:53 ` Laurentiu Mihalcea
2025-11-05 15:23 ` Frank Li
2025-11-05 15:10 ` Philipp Zabel
2025-11-04 12:02 ` [PATCH v4 6/8] reset: imx8mp-audiomix: Extend the driver usage Laurentiu Mihalcea
2025-11-04 16:46 ` Frank Li
2025-11-04 12:03 ` [PATCH v4 7/8] reset: imx8mp-audiomix: Support i.MX8ULP SIM LPAV Laurentiu Mihalcea
2025-11-04 12:03 ` [PATCH v4 8/8] arm64: dts: imx8ulp: add sim lpav node Laurentiu Mihalcea
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).