[alsa-devel] [PATCH 0/4] ASoC: mt8183: fix audio playback slowly after playback
This series patches add reset controller for MT8183, and audio will use it in machine driver during bootup, they depend on the following patch:
1. this series add support reset-controller in infra [v5,2/2] clk: reset: Modify reset-controller driver
*** BLURB HERE ***
Jiaxin Yu (2): WIP: dt-bindings: medaitek: mt8183: add property "resets" && "reset-names" WIP: ASoC: mt8183: fix audio playback slowly after playback during bootup
yong.liang (2): WIP: dt-bindings: mediatek: mt8183: Add #reset-cells WIP: watchdog: mtk_wdt: mt8183: Add reset controller
.../bindings/sound/mt8183-afe-pcm.txt | 6 + .../devicetree/bindings/watchdog/mtk-wdt.txt | 9 +- drivers/watchdog/Kconfig | 1 + drivers/watchdog/mtk_wdt.c | 110 +++++++++++++++++- .../reset-controller/mt8183-resets.h | 13 +++ sound/soc/mediatek/mt8183/mt8183-afe-pcm.c | 15 +++ 6 files changed, 150 insertions(+), 4 deletions(-)
From: "yong.liang" yong.liang@mediatek.corp-partner.google.com
Add #reset-cells property and update example.
Signed-off-by: yong.liang yong.liang@mediatek.com --- .../devicetree/bindings/watchdog/mtk-wdt.txt | 9 ++++++--- .../dt-bindings/reset-controller/mt8183-resets.h | 13 +++++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/watchdog/mtk-wdt.txt b/Documentation/devicetree/bindings/watchdog/mtk-wdt.txt index 3ee625d0812f..ecb9ff784832 100644 --- a/Documentation/devicetree/bindings/watchdog/mtk-wdt.txt +++ b/Documentation/devicetree/bindings/watchdog/mtk-wdt.txt @@ -16,11 +16,14 @@ Required properties:
Optional properties: - timeout-sec: contains the watchdog timeout in seconds. +- #reset-cells: Should be 1.
Example:
-wdt: watchdog@10000000 { - compatible = "mediatek,mt6589-wdt"; - reg = <0x10000000 0x18>; +watchdog: watchdog@10007000 { + compatible = "mediatek,mt8183-wdt", + "mediatek,mt6589-wdt"; + reg = <0 0x10007000 0 0x100>; timeout-sec = <10>; + #reset-cells = <1>; }; diff --git a/include/dt-bindings/reset-controller/mt8183-resets.h b/include/dt-bindings/reset-controller/mt8183-resets.h index 8804e34ebdd4..47dadcf3fd24 100644 --- a/include/dt-bindings/reset-controller/mt8183-resets.h +++ b/include/dt-bindings/reset-controller/mt8183-resets.h @@ -78,4 +78,17 @@ #define MT8183_INFRACFG_AO_I2C7_SW_RST 126 #define MT8183_INFRACFG_AO_I2C8_SW_RST 127
+#define MT8183_TOPRGU_MM_SW_RST 1 +#define MT8183_TOPRGU_MFG_SW_RST 2 +#define MT8183_TOPRGU_VENC_SW_RST 3 +#define MT8183_TOPRGU_VDEC_SW_RST 4 +#define MT8183_TOPRGU_IMG_SW_RST 5 +#define MT8183_TOPRGU_MD_SW_RST 7 +#define MT8183_TOPRGU_CONN_SW_RST 9 +#define MT8183_TOPRGU_CONN_MCU_SW_RST 12 +#define MT8183_TOPRGU_IPU0_SW_RST 14 +#define MT8183_TOPRGU_IPU1_SW_RST 15 +#define MT8183_TOPRGU_AUDIO_SW_RST 17 +#define MT8183_TOPRGU_CAMSYS_SW_RST 18 + #endif /* _DT_BINDINGS_RESET_CONTROLLER_MT8183 */
From: "yong.liang" yong.liang@mediatek.com
Provide assert/deassert/reset API in watchdog driver. Register reset controller for toprgu device in watchdog probe.
Signed-off-by: yong.liang yong.liang@mediatek.com --- drivers/watchdog/Kconfig | 1 + drivers/watchdog/mtk_wdt.c | 110 ++++++++++++++++++++++++++++++++++++- 2 files changed, 110 insertions(+), 1 deletion(-)
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 2e07caab9db2..629249fe5305 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -717,6 +717,7 @@ config MEDIATEK_WATCHDOG tristate "Mediatek SoCs watchdog support" depends on ARCH_MEDIATEK || COMPILE_TEST select WATCHDOG_CORE + select RESET_CONTROLLER help Say Y here to include support for the watchdog timer in Mediatek SoCs. diff --git a/drivers/watchdog/mtk_wdt.c b/drivers/watchdog/mtk_wdt.c index 9c3d0033260d..660fb0e48d8e 100644 --- a/drivers/watchdog/mtk_wdt.c +++ b/drivers/watchdog/mtk_wdt.c @@ -20,6 +20,10 @@ #include <linux/types.h> #include <linux/watchdog.h> #include <linux/delay.h> +#include <linux/reset-controller.h> +#include <linux/slab.h> +#include <linux/reset.h> +#include <linux/of_device.h>
#define WDT_MAX_TIMEOUT 31 #define WDT_MIN_TIMEOUT 1 @@ -44,17 +48,113 @@ #define WDT_SWRST 0x14 #define WDT_SWRST_KEY 0x1209
+#define WDT_SWSYSRST 0x18U +#define WDT_SWSYS_RST_KEY 0x88000000 + #define DRV_NAME "mtk-wdt" #define DRV_VERSION "1.0"
static bool nowayout = WATCHDOG_NOWAYOUT; static unsigned int timeout;
+struct toprgu_reset { + spinlock_t lock; /* Protects reset_controller access */ + void __iomem *toprgu_swrst_base; + int regofs; + struct reset_controller_dev rcdev; +}; + struct mtk_wdt_dev { struct watchdog_device wdt_dev; void __iomem *wdt_base; + struct toprgu_reset reset_controller; + const struct mtk_wdt_compatible *dev_comp; +}; + +struct mtk_wdt_compatible { + int sw_rst_num; +}; + +static int toprgu_reset_assert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + unsigned int tmp; + unsigned long flags; + struct toprgu_reset *data = container_of(rcdev, + struct toprgu_reset, rcdev); + + spin_lock_irqsave(&data->lock, flags); + + tmp = __raw_readl(data->toprgu_swrst_base + data->regofs); + tmp |= BIT(id); + tmp |= WDT_SWSYS_RST_KEY; + writel(tmp, data->toprgu_swrst_base + data->regofs); + + spin_unlock_irqrestore(&data->lock, flags); + + return 0; +} + +static int toprgu_reset_deassert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + unsigned int tmp; + unsigned long flags; + struct toprgu_reset *data = container_of(rcdev, + struct toprgu_reset, rcdev); + + spin_lock_irqsave(&data->lock, flags); + + tmp = __raw_readl(data->toprgu_swrst_base + data->regofs); + tmp &= ~BIT(id); + tmp |= WDT_SWSYS_RST_KEY; + writel(tmp, data->toprgu_swrst_base + data->regofs); + + spin_unlock_irqrestore(&data->lock, flags); + + return 0; +} + +static int toprgu_reset(struct reset_controller_dev *rcdev, + unsigned long id) +{ + int ret; + + ret = toprgu_reset_assert(rcdev, id); + if (ret) + return ret; + + return toprgu_reset_deassert(rcdev, id); +} + +static struct reset_control_ops toprgu_reset_ops = { + .assert = toprgu_reset_assert, + .deassert = toprgu_reset_deassert, + .reset = toprgu_reset, };
+static void toprgu_register_reset_controller(struct platform_device *pdev, + int regofs) +{ + int ret; + struct mtk_wdt_dev *mtk_wdt = platform_get_drvdata(pdev); + + spin_lock_init(&mtk_wdt->reset_controller.lock); + + mtk_wdt->dev_comp = of_device_get_match_data(&pdev->dev); + mtk_wdt->reset_controller.toprgu_swrst_base = mtk_wdt->wdt_base; + mtk_wdt->reset_controller.regofs = regofs; + mtk_wdt->reset_controller.rcdev.owner = THIS_MODULE; + mtk_wdt->reset_controller.rcdev.nr_resets = + mtk_wdt->dev_comp->sw_rst_num; + mtk_wdt->reset_controller.rcdev.ops = &toprgu_reset_ops; + mtk_wdt->reset_controller.rcdev.of_node = pdev->dev.of_node; + ret = reset_controller_register(&mtk_wdt->reset_controller.rcdev); + if (ret != 0) + dev_err(&pdev->dev, + "couldn't register wdt reset controller: %d\n", ret); +} + static int mtk_wdt_restart(struct watchdog_device *wdt_dev, unsigned long action, void *data) { @@ -187,9 +287,12 @@ static int mtk_wdt_probe(struct platform_device *pdev) if (unlikely(err)) return err;
- dev_info(dev, "Watchdog enabled (timeout=%d sec, nowayout=%d)\n", + dev_info(&pdev->dev, "Watchdog enabled (timeout=%d sec, nowayout=%d)\n", mtk_wdt->wdt_dev.timeout, nowayout);
+ mtk_wdt->dev_comp = of_device_get_match_data(&pdev->dev); + if (mtk_wdt->dev_comp) + toprgu_register_reset_controller(pdev, WDT_SWSYSRST); return 0; }
@@ -217,7 +320,12 @@ static int mtk_wdt_resume(struct device *dev) } #endif
+static const struct mtk_wdt_compatible mt8183_compat = { + .sw_rst_num = 18, +}; + static const struct of_device_id mtk_wdt_dt_ids[] = { + { .compatible = "mediatek,mt8183-wdt", .data = &mt8183_compat }, { .compatible = "mediatek,mt6589-wdt" }, { /* sentinel */ } };
This patch add property "resets" && "reset-names" in examples so that we can use reset controller to reset audio domain regs.
Signed-off-by: Jiaxin Yu jiaxin.yu@mediatek.com --- Documentation/devicetree/bindings/sound/mt8183-afe-pcm.txt | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/Documentation/devicetree/bindings/sound/mt8183-afe-pcm.txt b/Documentation/devicetree/bindings/sound/mt8183-afe-pcm.txt index 396ba38619f6..1f1cba4152ce 100644 --- a/Documentation/devicetree/bindings/sound/mt8183-afe-pcm.txt +++ b/Documentation/devicetree/bindings/sound/mt8183-afe-pcm.txt @@ -4,6 +4,10 @@ Required properties: - compatible = "mediatek,mt68183-audio"; - reg: register location and size - interrupts: should contain AFE interrupt +- resets: Must contain an entry for each entry in reset-names + See ../reset/reset.txt for details. +- reset-names: should have these reset names: + "audiosys"; - power-domains: should define the power domain - clocks: Must contain an entry for each entry in clock-names - clock-names: should have these clock names: @@ -20,6 +24,8 @@ Example: compatible = "mediatek,mt8183-audio"; reg = <0 0x11220000 0 0x1000>; interrupts = <GIC_SPI 161 IRQ_TYPE_LEVEL_LOW>; + resets = <&watchdog MT8183_TOPRGU_AUDIO_SW_RST>; + reset-names = "audiosys"; power-domains = <&scpsys MT8183_POWER_DOMAIN_AUDIO>; clocks = <&infrasys CLK_INFRA_AUDIO>, <&infrasys CLK_INFRA_AUDIO_26M_BCLK>,
Before regmap_reinit_cache we must reset audio regs as default values. So we use reset controller unit(toprgu) to reset audio hw.
Signed-off-by: Jiaxin Yu jiaxin.yu@mediatek.com --- sound/soc/mediatek/mt8183/mt8183-afe-pcm.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
diff --git a/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c b/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c index 4a31106d3471..721632386a50 100644 --- a/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c +++ b/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c @@ -11,6 +11,7 @@ #include <linux/of.h> #include <linux/of_address.h> #include <linux/pm_runtime.h> +#include <linux/reset.h>
#include "mt8183-afe-common.h" #include "mt8183-afe-clk.h" @@ -1089,6 +1090,7 @@ static int mt8183_afe_pcm_dev_probe(struct platform_device *pdev) struct mtk_base_afe *afe; struct mt8183_afe_private *afe_priv; struct device *dev; + struct reset_control *rstc; int i, irq_id, ret;
afe = devm_kzalloc(&pdev->dev, sizeof(*afe), GFP_KERNEL); @@ -1126,6 +1128,19 @@ static int mt8183_afe_pcm_dev_probe(struct platform_device *pdev) return ret; }
+ rstc = devm_reset_control_get(dev, "audiosys"); + if (IS_ERR(rstc)) { + ret = PTR_ERR(rstc); + dev_err(dev, "could not get audiosys reset:%d\n", ret); + return ret; + } + + ret = reset_control_reset(rstc); + if (ret) { + dev_err(dev, "failed to trigger audio reset:%d\n", ret); + return ret; + } + /* enable clock for regcache get default value from hw */ afe_priv->pm_runtime_bypass_reg_ctl = true; pm_runtime_get_sync(&pdev->dev);
participants (1)
-
Jiaxin Yu