]> Git Repo - J-linux.git/commitdiff
reset: imx8mp-audiomix: Add AudioMix Block Control reset driver
authorShengjiu Wang <[email protected]>
Mon, 24 Jun 2024 03:39:05 +0000 (11:39 +0800)
committerPhilipp Zabel <[email protected]>
Mon, 24 Jun 2024 09:27:04 +0000 (11:27 +0200)
Add support for the resets on i.MX8MP Audio Block Control module,
which includes the EARC PHY software reset and EARC controller
software reset. The reset controller is created using the auxiliary
device framework and set up in the clock driver.

Signed-off-by: Shengjiu Wang <[email protected]>
Reviewed-by: Marco Felsch <[email protected]>
Reviewed-by: Abel Vesa <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Philipp Zabel <[email protected]>
drivers/reset/Kconfig
drivers/reset/Makefile
drivers/reset/reset-imx8mp-audiomix.c [new file with mode: 0644]

index 7112f59326095a2d643f5353c89a03051c5e93e5..509f70e5c4c06f285dfe46b47c94507a6224fd9a 100644 (file)
@@ -91,6 +91,13 @@ config RESET_IMX7
        help
          This enables the reset controller driver for i.MX7 SoCs.
 
+config RESET_IMX8MP_AUDIOMIX
+       tristate "i.MX8MP AudioMix Reset Driver"
+       select AUXILIARY_BUS
+       default CLK_IMX8MP
+       help
+         This enables the reset controller driver for i.MX8MP AudioMix
+
 config RESET_INTEL_GW
        bool "Intel Reset Controller Driver"
        depends on X86 || COMPILE_TEST
index ff716f9afc84a73f68a3f483ccfc9dce9f802162..47a8148a92f385b78e3702856ae1dbe2c65ddd86 100644 (file)
@@ -14,6 +14,7 @@ obj-$(CONFIG_RESET_BRCMSTB_RESCAL) += reset-brcmstb-rescal.o
 obj-$(CONFIG_RESET_GPIO) += reset-gpio.o
 obj-$(CONFIG_RESET_HSDK) += reset-hsdk.o
 obj-$(CONFIG_RESET_IMX7) += reset-imx7.o
+obj-$(CONFIG_RESET_IMX8MP_AUDIOMIX) += reset-imx8mp-audiomix.o
 obj-$(CONFIG_RESET_INTEL_GW) += reset-intel-gw.o
 obj-$(CONFIG_RESET_K210) += reset-k210.o
 obj-$(CONFIG_RESET_LANTIQ) += reset-lantiq.o
diff --git a/drivers/reset/reset-imx8mp-audiomix.c b/drivers/reset/reset-imx8mp-audiomix.c
new file mode 100644 (file)
index 0000000..6e3f306
--- /dev/null
@@ -0,0 +1,128 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2024 NXP
+ */
+
+#include <linux/auxiliary_bus.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/reset-controller.h>
+
+#define EARC                   0x200
+#define EARC_RESET_MASK                0x3
+
+struct imx8mp_audiomix_reset {
+       struct reset_controller_dev rcdev;
+       spinlock_t lock; /* protect register read-modify-write cycle */
+       void __iomem *base;
+};
+
+static struct imx8mp_audiomix_reset *to_imx8mp_audiomix_reset(struct reset_controller_dev *rcdev)
+{
+       return container_of(rcdev, struct imx8mp_audiomix_reset, rcdev);
+}
+
+static int imx8mp_audiomix_reset_assert(struct reset_controller_dev *rcdev,
+                                       unsigned long id)
+{
+       struct imx8mp_audiomix_reset *priv = to_imx8mp_audiomix_reset(rcdev);
+       void __iomem *reg_addr = priv->base;
+       unsigned int mask, reg;
+       unsigned long flags;
+
+       mask = BIT(id);
+       spin_lock_irqsave(&priv->lock, flags);
+       reg = readl(reg_addr + EARC);
+       writel(reg & ~mask, reg_addr + EARC);
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       return 0;
+}
+
+static int imx8mp_audiomix_reset_deassert(struct reset_controller_dev *rcdev,
+                                         unsigned long id)
+{
+       struct imx8mp_audiomix_reset *priv = to_imx8mp_audiomix_reset(rcdev);
+       void __iomem *reg_addr = priv->base;
+       unsigned int mask, reg;
+       unsigned long flags;
+
+       mask = BIT(id);
+       spin_lock_irqsave(&priv->lock, flags);
+       reg = readl(reg_addr + EARC);
+       writel(reg | mask, reg_addr + EARC);
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       return 0;
+}
+
+static const struct reset_control_ops imx8mp_audiomix_reset_ops = {
+       .assert   = imx8mp_audiomix_reset_assert,
+       .deassert = imx8mp_audiomix_reset_deassert,
+};
+
+static int imx8mp_audiomix_reset_probe(struct auxiliary_device *adev,
+                                      const struct auxiliary_device_id *id)
+{
+       struct imx8mp_audiomix_reset *priv;
+       struct device *dev = &adev->dev;
+       int ret;
+
+       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       spin_lock_init(&priv->lock);
+
+       priv->rcdev.owner     = THIS_MODULE;
+       priv->rcdev.nr_resets = fls(EARC_RESET_MASK);
+       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 = devm_reset_controller_register(dev, &priv->rcdev);
+       if (ret)
+               goto out_unmap;
+
+       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[] = {
+       {
+               .name = "clk_imx8mp_audiomix.reset",
+       },
+       { }
+};
+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,
+};
+
+module_auxiliary_driver(imx8mp_audiomix_reset_driver);
+
+MODULE_AUTHOR("Shengjiu Wang <[email protected]>");
+MODULE_DESCRIPTION("Freescale i.MX8MP Audio Block Controller reset driver");
+MODULE_LICENSE("GPL");
This page took 0.058613 seconds and 4 git commands to generate.