mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-01 02:32:49 -04:00
Merge tag 'reset-for-v6.11' of git://git.pengutronix.de/pza/linux into soc/drivers
Reset controller updates for v6.11
Move reset controller registration to the end in rzg2l-usbphy-ctrl, to
simplify the probe error path, add a new i.MX8MP AudioMix reset driver,
allow to build some drivers under COMPILE_TEST with fewer dependencies,
and use the devm_clk_get_enabled convenience wrapper in meson-audio-arb.
The latter causes a trivial merge conflict [1] with
b99e9c0961 ("reset: meson-audio-arb: Convert to platform remove callback returning void")
because I didn't manage to send that in last round. There is no overlap
though.
[1] https://lore.kernel.org/all/Znmufb9L78FCoSSS@sirena.org.uk/
* tag 'reset-for-v6.11' of git://git.pengutronix.de/pza/linux:
reset: RESET_IMX8MP_AUDIOMIX should depend on ARCH_MXC
reset: zynqmp: allow building under COMPILE_TEST
reset: imx8mp-audiomix: Add AudioMix Block Control reset driver
reset: meson-audio-arb: Use devm_clk_get_enabled()
reset: sti: allow building under COMPILE_TEST
reset: rzg2l-usbphy-ctrl: Move reset controller registration
Link: https://lore.kernel.org/r/20240626163258.61222-1-p.zabel@pengutronix.de
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
@@ -91,6 +91,14 @@ config RESET_IMX7
|
||||
help
|
||||
This enables the reset controller driver for i.MX7 SoCs.
|
||||
|
||||
config RESET_IMX8MP_AUDIOMIX
|
||||
tristate "i.MX8MP AudioMix Reset Driver"
|
||||
depends on ARCH_MXC || COMPILE_TEST
|
||||
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
|
||||
@@ -328,6 +336,12 @@ config RESET_ZYNQ
|
||||
help
|
||||
This enables the reset controller driver for Xilinx Zynq SoCs.
|
||||
|
||||
config RESET_ZYNQMP
|
||||
bool "ZYNQMP Reset Driver" if COMPILE_TEST
|
||||
default ARCH_ZYNQMP
|
||||
help
|
||||
This enables the reset controller driver for Xilinx ZynqMP SoCs.
|
||||
|
||||
source "drivers/reset/starfive/Kconfig"
|
||||
source "drivers/reset/sti/Kconfig"
|
||||
source "drivers/reset/hisilicon/Kconfig"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
obj-y += core.o
|
||||
obj-y += hisilicon/
|
||||
obj-y += starfive/
|
||||
obj-$(CONFIG_ARCH_STI) += sti/
|
||||
obj-y += sti/
|
||||
obj-$(CONFIG_ARCH_TEGRA) += tegra/
|
||||
obj-$(CONFIG_RESET_A10SR) += reset-a10sr.o
|
||||
obj-$(CONFIG_RESET_ATH79) += reset-ath79.o
|
||||
@@ -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
|
||||
@@ -41,4 +42,4 @@ obj-$(CONFIG_RESET_TN48M_CPLD) += reset-tn48m.o
|
||||
obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
|
||||
obj-$(CONFIG_RESET_UNIPHIER_GLUE) += reset-uniphier-glue.o
|
||||
obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o
|
||||
obj-$(CONFIG_ARCH_ZYNQMP) += reset-zynqmp.o
|
||||
obj-$(CONFIG_RESET_ZYNQMP) += reset-zynqmp.o
|
||||
|
||||
128
drivers/reset/reset-imx8mp-audiomix.c
Normal file
128
drivers/reset/reset-imx8mp-audiomix.c
Normal file
@@ -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 <shengjiu.wang@nxp.com>");
|
||||
MODULE_DESCRIPTION("Freescale i.MX8MP Audio Block Controller reset driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -129,8 +129,6 @@ static int meson_audio_arb_remove(struct platform_device *pdev)
|
||||
writel(0, arb->regs);
|
||||
spin_unlock(&arb->lock);
|
||||
|
||||
clk_disable_unprepare(arb->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -150,7 +148,7 @@ static int meson_audio_arb_probe(struct platform_device *pdev)
|
||||
return -ENOMEM;
|
||||
platform_set_drvdata(pdev, arb);
|
||||
|
||||
arb->clk = devm_clk_get(dev, NULL);
|
||||
arb->clk = devm_clk_get_enabled(dev, NULL);
|
||||
if (IS_ERR(arb->clk))
|
||||
return dev_err_probe(dev, PTR_ERR(arb->clk), "failed to get clock\n");
|
||||
|
||||
@@ -170,11 +168,6 @@ static int meson_audio_arb_probe(struct platform_device *pdev)
|
||||
* In the initial state, all memory interfaces are disabled
|
||||
* and the general bit is on
|
||||
*/
|
||||
ret = clk_prepare_enable(arb->clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to enable arb clock\n");
|
||||
return ret;
|
||||
}
|
||||
writel(BIT(ARB_GENERAL_BIT), arb->regs);
|
||||
|
||||
/* Register reset controller */
|
||||
|
||||
@@ -125,25 +125,14 @@ static int rzg2l_usbphy_ctrl_probe(struct platform_device *pdev)
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
priv->rcdev.ops = &rzg2l_usbphy_ctrl_reset_ops;
|
||||
priv->rcdev.of_reset_n_cells = 1;
|
||||
priv->rcdev.nr_resets = NUM_PORTS;
|
||||
priv->rcdev.of_node = dev->of_node;
|
||||
priv->rcdev.dev = dev;
|
||||
|
||||
error = devm_reset_controller_register(dev, &priv->rcdev);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
spin_lock_init(&priv->lock);
|
||||
dev_set_drvdata(dev, priv);
|
||||
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
error = pm_runtime_resume_and_get(&pdev->dev);
|
||||
if (error < 0) {
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
reset_control_assert(priv->rstc);
|
||||
return dev_err_probe(&pdev->dev, error, "pm_runtime_resume_and_get failed");
|
||||
dev_err_probe(&pdev->dev, error, "pm_runtime_resume_and_get failed");
|
||||
goto err_pm_disable_reset_deassert;
|
||||
}
|
||||
|
||||
/* put pll and phy into reset state */
|
||||
@@ -153,7 +142,24 @@ static int rzg2l_usbphy_ctrl_probe(struct platform_device *pdev)
|
||||
writel(val, priv->base + RESET);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
priv->rcdev.ops = &rzg2l_usbphy_ctrl_reset_ops;
|
||||
priv->rcdev.of_reset_n_cells = 1;
|
||||
priv->rcdev.nr_resets = NUM_PORTS;
|
||||
priv->rcdev.of_node = dev->of_node;
|
||||
priv->rcdev.dev = dev;
|
||||
|
||||
error = devm_reset_controller_register(dev, &priv->rcdev);
|
||||
if (error)
|
||||
goto err_pm_runtime_put;
|
||||
|
||||
return 0;
|
||||
|
||||
err_pm_runtime_put:
|
||||
pm_runtime_put(&pdev->dev);
|
||||
err_pm_disable_reset_deassert:
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
reset_control_assert(priv->rstc);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int rzg2l_usbphy_ctrl_remove(struct platform_device *pdev)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
if ARCH_STI
|
||||
if ARCH_STI || COMPILE_TEST
|
||||
|
||||
config STIH407_RESET
|
||||
bool
|
||||
bool "STIH407 Reset Driver" if COMPILE_TEST
|
||||
|
||||
endif
|
||||
|
||||
Reference in New Issue
Block a user