Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Applied "ASoC: mediatek: rework clock functions for MT2701" to the asoc tree
From: Mark Brown @ 2018-01-03 15:43 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <0dc98a0b1d315a8b04472324b5789c640c337cb6.1514881870.git.ryder.lee@mediatek.com>

The patch

   ASoC: mediatek: rework clock functions for MT2701

has been applied to the asoc tree at

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From d8d99d8ed658a705909b07ba21b643c53851d70c Mon Sep 17 00:00:00 2001
From: Ryder Lee <ryder.lee@mediatek.com>
Date: Tue, 2 Jan 2018 19:47:19 +0800
Subject: [PATCH] ASoC: mediatek: rework clock functions for MT2701

Reworks clock part to make it more reasonable. The current changes are:

- Replace regmap operations by CCF APIs. Doing so, we just need to handle
  the element clocks and can also get accurate information via CCF.

- Rename clocks to make them more generic so that the future revisions
  of the IP can adapt gracefully.

- Regroup 'aud_clks[]' by usage - the basic needs and I2S parts:

  The new code just keep the common clocks in array and let SoC self decide
  I2S numbers - If future chips have different sets of channels we will
  add a little more abstract here.

  Moreover, this patch moves I2S clocks to the struct mt2701_i2s_data
  so that we can easily manage them when calls .prepare() and .shutdown().

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Tested-by: Garlic Tseng <garlic.tseng@mediatek.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c | 518 +++++++---------------
 sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.h |  15 +-
 sound/soc/mediatek/mt2701/mt2701-afe-common.h     |  64 +--
 sound/soc/mediatek/mt2701/mt2701-afe-pcm.c        |  45 +-
 4 files changed, 200 insertions(+), 442 deletions(-)

diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c b/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c
index affa7fb25dd9..75ccdca5811d 100644
--- a/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c
+++ b/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c
@@ -21,442 +21,256 @@
 #include "mt2701-afe-common.h"
 #include "mt2701-afe-clock-ctrl.h"
 
-static const char *aud_clks[MT2701_CLOCK_NUM] = {
-	[MT2701_AUD_INFRA_SYS_AUDIO] = "infra_sys_audio_clk",
-	[MT2701_AUD_AUD_MUX1_SEL] = "top_audio_mux1_sel",
-	[MT2701_AUD_AUD_MUX2_SEL] = "top_audio_mux2_sel",
-	[MT2701_AUD_AUD_MUX1_DIV] = "top_audio_mux1_div",
-	[MT2701_AUD_AUD_MUX2_DIV] = "top_audio_mux2_div",
-	[MT2701_AUD_AUD_48K_TIMING] = "top_audio_48k_timing",
-	[MT2701_AUD_AUD_44K_TIMING] = "top_audio_44k_timing",
-	[MT2701_AUD_AUDPLL_MUX_SEL] = "top_audpll_mux_sel",
-	[MT2701_AUD_APLL_SEL] = "top_apll_sel",
-	[MT2701_AUD_AUD1PLL_98M] = "top_aud1_pll_98M",
-	[MT2701_AUD_AUD2PLL_90M] = "top_aud2_pll_90M",
-	[MT2701_AUD_HADDS2PLL_98M] = "top_hadds2_pll_98M",
-	[MT2701_AUD_HADDS2PLL_294M] = "top_hadds2_pll_294M",
-	[MT2701_AUD_AUDPLL] = "top_audpll",
-	[MT2701_AUD_AUDPLL_D4] = "top_audpll_d4",
-	[MT2701_AUD_AUDPLL_D8] = "top_audpll_d8",
-	[MT2701_AUD_AUDPLL_D16] = "top_audpll_d16",
-	[MT2701_AUD_AUDPLL_D24] = "top_audpll_d24",
-	[MT2701_AUD_AUDINTBUS] = "top_audintbus_sel",
-	[MT2701_AUD_CLK_26M] = "clk_26m",
-	[MT2701_AUD_SYSPLL1_D4] = "top_syspll1_d4",
-	[MT2701_AUD_AUD_K1_SRC_SEL] = "top_aud_k1_src_sel",
-	[MT2701_AUD_AUD_K2_SRC_SEL] = "top_aud_k2_src_sel",
-	[MT2701_AUD_AUD_K3_SRC_SEL] = "top_aud_k3_src_sel",
-	[MT2701_AUD_AUD_K4_SRC_SEL] = "top_aud_k4_src_sel",
-	[MT2701_AUD_AUD_K5_SRC_SEL] = "top_aud_k5_src_sel",
-	[MT2701_AUD_AUD_K6_SRC_SEL] = "top_aud_k6_src_sel",
-	[MT2701_AUD_AUD_K1_SRC_DIV] = "top_aud_k1_src_div",
-	[MT2701_AUD_AUD_K2_SRC_DIV] = "top_aud_k2_src_div",
-	[MT2701_AUD_AUD_K3_SRC_DIV] = "top_aud_k3_src_div",
-	[MT2701_AUD_AUD_K4_SRC_DIV] = "top_aud_k4_src_div",
-	[MT2701_AUD_AUD_K5_SRC_DIV] = "top_aud_k5_src_div",
-	[MT2701_AUD_AUD_K6_SRC_DIV] = "top_aud_k6_src_div",
-	[MT2701_AUD_AUD_I2S1_MCLK] = "top_aud_i2s1_mclk",
-	[MT2701_AUD_AUD_I2S2_MCLK] = "top_aud_i2s2_mclk",
-	[MT2701_AUD_AUD_I2S3_MCLK] = "top_aud_i2s3_mclk",
-	[MT2701_AUD_AUD_I2S4_MCLK] = "top_aud_i2s4_mclk",
-	[MT2701_AUD_AUD_I2S5_MCLK] = "top_aud_i2s5_mclk",
-	[MT2701_AUD_AUD_I2S6_MCLK] = "top_aud_i2s6_mclk",
-	[MT2701_AUD_ASM_M_SEL] = "top_asm_m_sel",
-	[MT2701_AUD_ASM_H_SEL] = "top_asm_h_sel",
-	[MT2701_AUD_UNIVPLL2_D4] = "top_univpll2_d4",
-	[MT2701_AUD_UNIVPLL2_D2] = "top_univpll2_d2",
-	[MT2701_AUD_SYSPLL_D5] = "top_syspll_d5",
+static const char *const base_clks[] = {
+	[MT2701_TOP_AUD_MCLK_SRC0] = "top_audio_mux1_sel",
+	[MT2701_TOP_AUD_MCLK_SRC1] = "top_audio_mux2_sel",
+	[MT2701_AUDSYS_AFE] = "audio_afe_pd",
+	[MT2701_AUDSYS_AFE_CONN] = "audio_afe_conn_pd",
+	[MT2701_AUDSYS_A1SYS] = "audio_a1sys_pd",
+	[MT2701_AUDSYS_A2SYS] = "audio_a2sys_pd",
 };
 
 int mt2701_init_clock(struct mtk_base_afe *afe)
 {
 	struct mt2701_afe_private *afe_priv = afe->platform_priv;
-	int i = 0;
-
-	for (i = 0; i < MT2701_CLOCK_NUM; i++) {
-		afe_priv->clocks[i] = devm_clk_get(afe->dev, aud_clks[i]);
-		if (IS_ERR(afe_priv->clocks[i])) {
-			dev_warn(afe->dev, "%s devm_clk_get %s fail\n",
-				 __func__, aud_clks[i]);
-			return PTR_ERR(aud_clks[i]);
+	int i;
+
+	for (i = 0; i < MT2701_BASE_CLK_NUM; i++) {
+		afe_priv->base_ck[i] = devm_clk_get(afe->dev, base_clks[i]);
+		if (IS_ERR(afe_priv->base_ck[i])) {
+			dev_err(afe->dev, "failed to get %s\n", base_clks[i]);
+			return PTR_ERR(afe_priv->base_ck[i]);
 		}
 	}
 
-	return 0;
-}
+	/* Get I2S related clocks */
+	for (i = 0; i < MT2701_I2S_NUM; i++) {
+		struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[i];
+		char name[13];
 
-int mt2701_afe_enable_clock(struct mtk_base_afe *afe)
-{
-	int ret = 0;
+		snprintf(name, sizeof(name), "i2s%d_src_sel", i);
+		i2s_path->sel_ck = devm_clk_get(afe->dev, name);
+		if (IS_ERR(i2s_path->sel_ck)) {
+			dev_err(afe->dev, "failed to get %s\n", name);
+			return PTR_ERR(i2s_path->sel_ck);
+		}
 
-	ret = mt2701_turn_on_a1sys_clock(afe);
-	if (ret) {
-		dev_err(afe->dev, "%s turn_on_a1sys_clock fail %d\n",
-			__func__, ret);
-		return ret;
-	}
+		snprintf(name, sizeof(name), "i2s%d_src_div", i);
+		i2s_path->div_ck = devm_clk_get(afe->dev, name);
+		if (IS_ERR(i2s_path->div_ck)) {
+			dev_err(afe->dev, "failed to get %s\n", name);
+			return PTR_ERR(i2s_path->div_ck);
+		}
 
-	ret = mt2701_turn_on_a2sys_clock(afe);
-	if (ret) {
-		dev_err(afe->dev, "%s turn_on_a2sys_clock fail %d\n",
-			__func__, ret);
-		mt2701_turn_off_a1sys_clock(afe);
-		return ret;
-	}
+		snprintf(name, sizeof(name), "i2s%d_mclk_en", i);
+		i2s_path->mclk_ck = devm_clk_get(afe->dev, name);
+		if (IS_ERR(i2s_path->mclk_ck)) {
+			dev_err(afe->dev, "failed to get %s\n", name);
+			return PTR_ERR(i2s_path->mclk_ck);
+		}
 
-	ret = mt2701_turn_on_afe_clock(afe);
-	if (ret) {
-		dev_err(afe->dev, "%s turn_on_afe_clock fail %d\n",
-			__func__, ret);
-		mt2701_turn_off_a1sys_clock(afe);
-		mt2701_turn_off_a2sys_clock(afe);
-		return ret;
+		snprintf(name, sizeof(name), "i2so%d_hop_ck", i);
+		i2s_path->hop_ck[I2S_OUT] = devm_clk_get(afe->dev, name);
+		if (IS_ERR(i2s_path->hop_ck[I2S_OUT])) {
+			dev_err(afe->dev, "failed to get %s\n", name);
+			return PTR_ERR(i2s_path->hop_ck[I2S_OUT]);
+		}
+
+		snprintf(name, sizeof(name), "i2si%d_hop_ck", i);
+		i2s_path->hop_ck[I2S_IN] = devm_clk_get(afe->dev, name);
+		if (IS_ERR(i2s_path->hop_ck[I2S_IN])) {
+			dev_err(afe->dev, "failed to get %s\n", name);
+			return PTR_ERR(i2s_path->hop_ck[I2S_IN]);
+		}
+
+		snprintf(name, sizeof(name), "asrc%d_out_ck", i);
+		i2s_path->asrco_ck = devm_clk_get(afe->dev, name);
+		if (IS_ERR(i2s_path->asrco_ck)) {
+			dev_err(afe->dev, "failed to get %s\n", name);
+			return PTR_ERR(i2s_path->asrco_ck);
+		}
 	}
 
-	regmap_update_bits(afe->regmap, ASYS_TOP_CON,
-			   AUDIO_TOP_CON0_A1SYS_A2SYS_ON,
-			   AUDIO_TOP_CON0_A1SYS_A2SYS_ON);
-	regmap_update_bits(afe->regmap, AFE_DAC_CON0,
-			   AFE_DAC_CON0_AFE_ON,
-			   AFE_DAC_CON0_AFE_ON);
-	regmap_write(afe->regmap, PWR2_TOP_CON,
-		     PWR2_TOP_CON_INIT_VAL);
-	regmap_write(afe->regmap, PWR1_ASM_CON1,
-		     PWR1_ASM_CON1_INIT_VAL);
-	regmap_write(afe->regmap, PWR2_ASM_CON1,
-		     PWR2_ASM_CON1_INIT_VAL);
+	/* Some platforms may support BT path */
+	afe_priv->mrgif_ck = devm_clk_get(afe->dev, "audio_mrgif_pd");
+	if (IS_ERR(afe_priv->mrgif_ck)) {
+		if (PTR_ERR(afe_priv->mrgif_ck) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
 
-	return 0;
-}
+		afe_priv->mrgif_ck = NULL;
+	}
 
-void mt2701_afe_disable_clock(struct mtk_base_afe *afe)
-{
-	mt2701_turn_off_afe_clock(afe);
-	mt2701_turn_off_a1sys_clock(afe);
-	mt2701_turn_off_a2sys_clock(afe);
-	regmap_update_bits(afe->regmap, ASYS_TOP_CON,
-			   AUDIO_TOP_CON0_A1SYS_A2SYS_ON, 0);
-	regmap_update_bits(afe->regmap, AFE_DAC_CON0,
-			   AFE_DAC_CON0_AFE_ON, 0);
+	return 0;
 }
 
-int mt2701_turn_on_a1sys_clock(struct mtk_base_afe *afe)
+int mt2701_afe_enable_i2s(struct mtk_base_afe *afe, int id, int dir)
 {
 	struct mt2701_afe_private *afe_priv = afe->platform_priv;
-	int ret = 0;
+	struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[id];
+	int ret;
 
-	/* Set Mux */
-	ret = clk_prepare_enable(afe_priv->clocks[MT2701_AUD_AUD_MUX1_SEL]);
+	ret = clk_prepare_enable(i2s_path->asrco_ck);
 	if (ret) {
-		dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
-			__func__, aud_clks[MT2701_AUD_AUD_MUX1_SEL], ret);
-		goto A1SYS_CLK_AUD_MUX1_SEL_ERR;
+		dev_err(afe->dev, "failed to enable ASRC clock %d\n", ret);
+		return ret;
 	}
 
-	ret = clk_set_parent(afe_priv->clocks[MT2701_AUD_AUD_MUX1_SEL],
-			     afe_priv->clocks[MT2701_AUD_AUD1PLL_98M]);
+	ret = clk_prepare_enable(i2s_path->hop_ck[dir]);
 	if (ret) {
-		dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n", __func__,
-			aud_clks[MT2701_AUD_AUD_MUX1_SEL],
-			aud_clks[MT2701_AUD_AUD1PLL_98M], ret);
-		goto A1SYS_CLK_AUD_MUX1_SEL_ERR;
+		dev_err(afe->dev, "failed to enable I2S clock %d\n", ret);
+		goto err_hop_ck;
 	}
 
-	/* Set Divider */
-	ret = clk_prepare_enable(afe_priv->clocks[MT2701_AUD_AUD_MUX1_DIV]);
-	if (ret) {
-		dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
-			__func__,
-			aud_clks[MT2701_AUD_AUD_MUX1_DIV],
-			ret);
-		goto A1SYS_CLK_AUD_MUX1_DIV_ERR;
-	}
+	return 0;
 
-	ret = clk_set_rate(afe_priv->clocks[MT2701_AUD_AUD_MUX1_DIV],
-			   MT2701_AUD_AUD_MUX1_DIV_RATE);
-	if (ret) {
-		dev_err(afe->dev, "%s clk_set_parent %s-%d fail %d\n", __func__,
-			aud_clks[MT2701_AUD_AUD_MUX1_DIV],
-			MT2701_AUD_AUD_MUX1_DIV_RATE, ret);
-		goto A1SYS_CLK_AUD_MUX1_DIV_ERR;
-	}
+err_hop_ck:
+	clk_disable_unprepare(i2s_path->asrco_ck);
 
-	/* Enable clock gate */
-	ret = clk_prepare_enable(afe_priv->clocks[MT2701_AUD_AUD_48K_TIMING]);
-	if (ret) {
-		dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
-			__func__, aud_clks[MT2701_AUD_AUD_48K_TIMING], ret);
-		goto A1SYS_CLK_AUD_48K_ERR;
-	}
+	return ret;
+}
 
-	/* Enable infra audio */
-	ret = clk_prepare_enable(afe_priv->clocks[MT2701_AUD_INFRA_SYS_AUDIO]);
-	if (ret) {
-		dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
-			__func__, aud_clks[MT2701_AUD_INFRA_SYS_AUDIO], ret);
-		goto A1SYS_CLK_INFRA_ERR;
-	}
+void mt2701_afe_disable_i2s(struct mtk_base_afe *afe, int id, int dir)
+{
+	struct mt2701_afe_private *afe_priv = afe->platform_priv;
+	struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[id];
 
-	return 0;
+	clk_disable_unprepare(i2s_path->hop_ck[dir]);
+	clk_disable_unprepare(i2s_path->asrco_ck);
+}
 
-A1SYS_CLK_INFRA_ERR:
-	clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_INFRA_SYS_AUDIO]);
-A1SYS_CLK_AUD_48K_ERR:
-	clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_AUD_48K_TIMING]);
-A1SYS_CLK_AUD_MUX1_DIV_ERR:
-	clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_AUD_MUX1_DIV]);
-A1SYS_CLK_AUD_MUX1_SEL_ERR:
-	clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_AUD_MUX1_SEL]);
+int mt2701_afe_enable_mclk(struct mtk_base_afe *afe, int id)
+{
+	struct mt2701_afe_private *afe_priv = afe->platform_priv;
+	struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[id];
 
-	return ret;
+	return clk_prepare_enable(i2s_path->mclk_ck);
 }
 
-void mt2701_turn_off_a1sys_clock(struct mtk_base_afe *afe)
+void mt2701_afe_disable_mclk(struct mtk_base_afe *afe, int id)
 {
 	struct mt2701_afe_private *afe_priv = afe->platform_priv;
+	struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[id];
 
-	clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_INFRA_SYS_AUDIO]);
-	clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_AUD_48K_TIMING]);
-	clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_AUD_MUX1_DIV]);
-	clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_AUD_MUX1_SEL]);
+	clk_disable_unprepare(i2s_path->mclk_ck);
 }
 
-int mt2701_turn_on_a2sys_clock(struct mtk_base_afe *afe)
+int mt2701_enable_btmrg_clk(struct mtk_base_afe *afe)
 {
 	struct mt2701_afe_private *afe_priv = afe->platform_priv;
-	int ret = 0;
 
-	/* Set Mux */
-	ret = clk_prepare_enable(afe_priv->clocks[MT2701_AUD_AUD_MUX2_SEL]);
-	if (ret) {
-		dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
-			__func__, aud_clks[MT2701_AUD_AUD_MUX2_SEL], ret);
-		goto A2SYS_CLK_AUD_MUX2_SEL_ERR;
-	}
+	return clk_prepare_enable(afe_priv->mrgif_ck);
+}
 
-	ret = clk_set_parent(afe_priv->clocks[MT2701_AUD_AUD_MUX2_SEL],
-			     afe_priv->clocks[MT2701_AUD_AUD2PLL_90M]);
-	if (ret) {
-		dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n", __func__,
-			aud_clks[MT2701_AUD_AUD_MUX2_SEL],
-			aud_clks[MT2701_AUD_AUD2PLL_90M], ret);
-		goto A2SYS_CLK_AUD_MUX2_SEL_ERR;
-	}
+void mt2701_disable_btmrg_clk(struct mtk_base_afe *afe)
+{
+	struct mt2701_afe_private *afe_priv = afe->platform_priv;
 
-	/* Set Divider */
-	ret = clk_prepare_enable(afe_priv->clocks[MT2701_AUD_AUD_MUX2_DIV]);
-	if (ret) {
-		dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
-			__func__, aud_clks[MT2701_AUD_AUD_MUX2_DIV], ret);
-		goto A2SYS_CLK_AUD_MUX2_DIV_ERR;
-	}
+	clk_disable_unprepare(afe_priv->mrgif_ck);
+}
 
-	ret = clk_set_rate(afe_priv->clocks[MT2701_AUD_AUD_MUX2_DIV],
-			   MT2701_AUD_AUD_MUX2_DIV_RATE);
-	if (ret) {
-		dev_err(afe->dev, "%s clk_set_parent %s-%d fail %d\n", __func__,
-			aud_clks[MT2701_AUD_AUD_MUX2_DIV],
-			MT2701_AUD_AUD_MUX2_DIV_RATE, ret);
-		goto A2SYS_CLK_AUD_MUX2_DIV_ERR;
-	}
+static int mt2701_afe_enable_audsys(struct mtk_base_afe *afe)
+{
+	struct mt2701_afe_private *afe_priv = afe->platform_priv;
+	int ret;
 
-	/* Enable clock gate */
-	ret = clk_prepare_enable(afe_priv->clocks[MT2701_AUD_AUD_44K_TIMING]);
-	if (ret) {
-		dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
-			__func__, aud_clks[MT2701_AUD_AUD_44K_TIMING], ret);
-		goto A2SYS_CLK_AUD_44K_ERR;
-	}
+	ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_AFE]);
+	if (ret)
+		return ret;
 
-	/* Enable infra audio */
-	ret = clk_prepare_enable(afe_priv->clocks[MT2701_AUD_INFRA_SYS_AUDIO]);
-	if (ret) {
-		dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
-			__func__, aud_clks[MT2701_AUD_INFRA_SYS_AUDIO], ret);
-		goto A2SYS_CLK_INFRA_ERR;
-	}
+	ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_A1SYS]);
+	if (ret)
+		goto err_audio_a1sys;
+
+	ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_A2SYS]);
+	if (ret)
+		goto err_audio_a2sys;
+
+	ret = clk_prepare_enable(afe_priv->base_ck[MT2701_AUDSYS_AFE_CONN]);
+	if (ret)
+		goto err_afe_conn;
 
 	return 0;
 
-A2SYS_CLK_INFRA_ERR:
-	clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_INFRA_SYS_AUDIO]);
-A2SYS_CLK_AUD_44K_ERR:
-	clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_AUD_44K_TIMING]);
-A2SYS_CLK_AUD_MUX2_DIV_ERR:
-	clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_AUD_MUX2_DIV]);
-A2SYS_CLK_AUD_MUX2_SEL_ERR:
-	clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_AUD_MUX2_SEL]);
+err_afe_conn:
+	clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A2SYS]);
+err_audio_a2sys:
+	clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A1SYS]);
+err_audio_a1sys:
+	clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_AFE]);
 
 	return ret;
 }
 
-void mt2701_turn_off_a2sys_clock(struct mtk_base_afe *afe)
+static void mt2701_afe_disable_audsys(struct mtk_base_afe *afe)
 {
 	struct mt2701_afe_private *afe_priv = afe->platform_priv;
 
-	clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_INFRA_SYS_AUDIO]);
-	clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_AUD_44K_TIMING]);
-	clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_AUD_MUX2_DIV]);
-	clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_AUD_MUX2_SEL]);
+	clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_AFE_CONN]);
+	clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A2SYS]);
+	clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_A1SYS]);
+	clk_disable_unprepare(afe_priv->base_ck[MT2701_AUDSYS_AFE]);
 }
 
-int mt2701_turn_on_afe_clock(struct mtk_base_afe *afe)
+int mt2701_afe_enable_clock(struct mtk_base_afe *afe)
 {
-	struct mt2701_afe_private *afe_priv = afe->platform_priv;
 	int ret;
 
-	/* enable INFRA_SYS */
-	ret = clk_prepare_enable(afe_priv->clocks[MT2701_AUD_INFRA_SYS_AUDIO]);
-	if (ret) {
-		dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
-			__func__, aud_clks[MT2701_AUD_INFRA_SYS_AUDIO], ret);
-		goto AFE_AUD_INFRA_ERR;
-	}
-
-	/* Set MT2701_AUD_AUDINTBUS to MT2701_AUD_SYSPLL1_D4 */
-	ret = clk_prepare_enable(afe_priv->clocks[MT2701_AUD_AUDINTBUS]);
-	if (ret) {
-		dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
-			__func__, aud_clks[MT2701_AUD_AUDINTBUS], ret);
-		goto AFE_AUD_AUDINTBUS_ERR;
-	}
-
-	ret = clk_set_parent(afe_priv->clocks[MT2701_AUD_AUDINTBUS],
-			     afe_priv->clocks[MT2701_AUD_SYSPLL1_D4]);
-	if (ret) {
-		dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n", __func__,
-			aud_clks[MT2701_AUD_AUDINTBUS],
-			aud_clks[MT2701_AUD_SYSPLL1_D4], ret);
-		goto AFE_AUD_AUDINTBUS_ERR;
-	}
-
-	/* Set MT2701_AUD_ASM_H_SEL to MT2701_AUD_UNIVPLL2_D2 */
-	ret = clk_prepare_enable(afe_priv->clocks[MT2701_AUD_ASM_H_SEL]);
-	if (ret) {
-		dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
-			__func__, aud_clks[MT2701_AUD_ASM_H_SEL], ret);
-		goto AFE_AUD_ASM_H_ERR;
-	}
-
-	ret = clk_set_parent(afe_priv->clocks[MT2701_AUD_ASM_H_SEL],
-			     afe_priv->clocks[MT2701_AUD_UNIVPLL2_D2]);
-	if (ret) {
-		dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n", __func__,
-			aud_clks[MT2701_AUD_ASM_H_SEL],
-			aud_clks[MT2701_AUD_UNIVPLL2_D2], ret);
-		goto AFE_AUD_ASM_H_ERR;
-	}
-
-	/* Set MT2701_AUD_ASM_M_SEL to MT2701_AUD_UNIVPLL2_D4 */
-	ret = clk_prepare_enable(afe_priv->clocks[MT2701_AUD_ASM_M_SEL]);
+	/* Enable audio system */
+	ret = mt2701_afe_enable_audsys(afe);
 	if (ret) {
-		dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
-			__func__, aud_clks[MT2701_AUD_ASM_M_SEL], ret);
-		goto AFE_AUD_ASM_M_ERR;
+		dev_err(afe->dev, "failed to enable audio system %d\n", ret);
+		return ret;
 	}
 
-	ret = clk_set_parent(afe_priv->clocks[MT2701_AUD_ASM_M_SEL],
-			     afe_priv->clocks[MT2701_AUD_UNIVPLL2_D4]);
-	if (ret) {
-		dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n", __func__,
-			aud_clks[MT2701_AUD_ASM_M_SEL],
-			aud_clks[MT2701_AUD_UNIVPLL2_D4], ret);
-		goto AFE_AUD_ASM_M_ERR;
-	}
+	regmap_update_bits(afe->regmap, ASYS_TOP_CON,
+			   AUDIO_TOP_CON0_A1SYS_A2SYS_ON,
+			   AUDIO_TOP_CON0_A1SYS_A2SYS_ON);
+	regmap_update_bits(afe->regmap, AFE_DAC_CON0,
+			   AFE_DAC_CON0_AFE_ON,
+			   AFE_DAC_CON0_AFE_ON);
 
-	regmap_update_bits(afe->regmap, AUDIO_TOP_CON0,
-			   AUDIO_TOP_CON0_PDN_AFE, 0);
-	regmap_update_bits(afe->regmap, AUDIO_TOP_CON0,
-			   AUDIO_TOP_CON0_PDN_APLL_CK, 0);
-	regmap_update_bits(afe->regmap, AUDIO_TOP_CON4,
-			   AUDIO_TOP_CON4_PDN_A1SYS, 0);
-	regmap_update_bits(afe->regmap, AUDIO_TOP_CON4,
-			   AUDIO_TOP_CON4_PDN_A2SYS, 0);
-	regmap_update_bits(afe->regmap, AUDIO_TOP_CON4,
-			   AUDIO_TOP_CON4_PDN_AFE_CONN, 0);
+	/* Configure ASRC */
+	regmap_write(afe->regmap, PWR1_ASM_CON1, PWR1_ASM_CON1_INIT_VAL);
+	regmap_write(afe->regmap, PWR2_ASM_CON1, PWR2_ASM_CON1_INIT_VAL);
 
 	return 0;
-
-AFE_AUD_ASM_M_ERR:
-	clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_ASM_M_SEL]);
-AFE_AUD_ASM_H_ERR:
-	clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_ASM_H_SEL]);
-AFE_AUD_AUDINTBUS_ERR:
-	clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_AUDINTBUS]);
-AFE_AUD_INFRA_ERR:
-	clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_INFRA_SYS_AUDIO]);
-
-	return ret;
 }
 
-void mt2701_turn_off_afe_clock(struct mtk_base_afe *afe)
+int mt2701_afe_disable_clock(struct mtk_base_afe *afe)
 {
-	struct mt2701_afe_private *afe_priv = afe->platform_priv;
+	regmap_update_bits(afe->regmap, ASYS_TOP_CON,
+			   AUDIO_TOP_CON0_A1SYS_A2SYS_ON, 0);
+	regmap_update_bits(afe->regmap, AFE_DAC_CON0,
+			   AFE_DAC_CON0_AFE_ON, 0);
 
-	clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_INFRA_SYS_AUDIO]);
-
-	clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_AUDINTBUS]);
-	clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_ASM_H_SEL]);
-	clk_disable_unprepare(afe_priv->clocks[MT2701_AUD_ASM_M_SEL]);
-
-	regmap_update_bits(afe->regmap, AUDIO_TOP_CON0,
-			   AUDIO_TOP_CON0_PDN_AFE, AUDIO_TOP_CON0_PDN_AFE);
-	regmap_update_bits(afe->regmap, AUDIO_TOP_CON0,
-			   AUDIO_TOP_CON0_PDN_APLL_CK,
-			   AUDIO_TOP_CON0_PDN_APLL_CK);
-	regmap_update_bits(afe->regmap, AUDIO_TOP_CON4,
-			   AUDIO_TOP_CON4_PDN_A1SYS,
-			   AUDIO_TOP_CON4_PDN_A1SYS);
-	regmap_update_bits(afe->regmap, AUDIO_TOP_CON4,
-			   AUDIO_TOP_CON4_PDN_A2SYS,
-			   AUDIO_TOP_CON4_PDN_A2SYS);
-	regmap_update_bits(afe->regmap, AUDIO_TOP_CON4,
-			   AUDIO_TOP_CON4_PDN_AFE_CONN,
-			   AUDIO_TOP_CON4_PDN_AFE_CONN);
+	mt2701_afe_disable_audsys(afe);
+
+	return 0;
 }
 
 void mt2701_mclk_configuration(struct mtk_base_afe *afe, int id, int domain,
 			       int mclk)
 {
-	struct mt2701_afe_private *afe_priv = afe->platform_priv;
+	struct mt2701_afe_private *priv = afe->platform_priv;
+	struct mt2701_i2s_path *i2s_path = &priv->i2s_path[id];
 	int ret;
-	int aud_src_div_id = MT2701_AUD_AUD_K1_SRC_DIV + id;
-	int aud_src_clk_id = MT2701_AUD_AUD_K1_SRC_SEL + id;
 
-	/* Set MCLK Kx_SRC_SEL(domain) */
-	ret = clk_prepare_enable(afe_priv->clocks[aud_src_clk_id]);
-	if (ret)
-		dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
-			__func__, aud_clks[aud_src_clk_id], ret);
-
-	if (domain == 0) {
-		ret = clk_set_parent(afe_priv->clocks[aud_src_clk_id],
-				     afe_priv->clocks[MT2701_AUD_AUD_MUX1_SEL]);
-		if (ret)
-			dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
-				__func__, aud_clks[aud_src_clk_id],
-				aud_clks[MT2701_AUD_AUD_MUX1_SEL], ret);
-	} else {
-		ret = clk_set_parent(afe_priv->clocks[aud_src_clk_id],
-				     afe_priv->clocks[MT2701_AUD_AUD_MUX2_SEL]);
-		if (ret)
-			dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n",
-				__func__, aud_clks[aud_src_clk_id],
-				aud_clks[MT2701_AUD_AUD_MUX2_SEL], ret);
-	}
-	clk_disable_unprepare(afe_priv->clocks[aud_src_clk_id]);
+	/* Set mclk source */
+	if (domain == 0)
+		ret = clk_set_parent(i2s_path->sel_ck,
+				     priv->base_ck[MT2701_TOP_AUD_MCLK_SRC0]);
+	else
+		ret = clk_set_parent(i2s_path->sel_ck,
+				     priv->base_ck[MT2701_TOP_AUD_MCLK_SRC1]);
 
-	/* Set MCLK Kx_SRC_DIV(divider) */
-	ret = clk_prepare_enable(afe_priv->clocks[aud_src_div_id]);
 	if (ret)
-		dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n",
-			__func__, aud_clks[aud_src_div_id], ret);
+		dev_err(afe->dev, "failed to set domain%d mclk source %d\n",
+			domain, ret);
 
-	ret = clk_set_rate(afe_priv->clocks[aud_src_div_id], mclk);
+	/* Set mclk divider */
+	ret = clk_set_rate(i2s_path->div_ck, mclk);
 	if (ret)
-		dev_err(afe->dev, "%s clk_set_rate %s-%d fail %d\n", __func__,
-			aud_clks[aud_src_div_id], mclk, ret);
-	clk_disable_unprepare(afe_priv->clocks[aud_src_div_id]);
+		dev_err(afe->dev, "failed to set mclk divider %d\n", ret);
 }
 
 MODULE_DESCRIPTION("MT2701 afe clock control");
diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.h b/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.h
index 6497d570cf09..15417d9d6597 100644
--- a/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.h
+++ b/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.h
@@ -21,16 +21,15 @@ struct mtk_base_afe;
 
 int mt2701_init_clock(struct mtk_base_afe *afe);
 int mt2701_afe_enable_clock(struct mtk_base_afe *afe);
-void mt2701_afe_disable_clock(struct mtk_base_afe *afe);
+int mt2701_afe_disable_clock(struct mtk_base_afe *afe);
 
-int mt2701_turn_on_a1sys_clock(struct mtk_base_afe *afe);
-void mt2701_turn_off_a1sys_clock(struct mtk_base_afe *afe);
+int mt2701_afe_enable_i2s(struct mtk_base_afe *afe, int id, int dir);
+void mt2701_afe_disable_i2s(struct mtk_base_afe *afe, int id, int dir);
+int mt2701_afe_enable_mclk(struct mtk_base_afe *afe, int id);
+void mt2701_afe_disable_mclk(struct mtk_base_afe *afe, int id);
 
-int mt2701_turn_on_a2sys_clock(struct mtk_base_afe *afe);
-void mt2701_turn_off_a2sys_clock(struct mtk_base_afe *afe);
-
-int mt2701_turn_on_afe_clock(struct mtk_base_afe *afe);
-void mt2701_turn_off_afe_clock(struct mtk_base_afe *afe);
+int mt2701_enable_btmrg_clk(struct mtk_base_afe *afe);
+void mt2701_disable_btmrg_clk(struct mtk_base_afe *afe);
 
 void mt2701_mclk_configuration(struct mtk_base_afe *afe, int id, int domain,
 			       int mclk);
diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-common.h b/sound/soc/mediatek/mt2701/mt2701-afe-common.h
index c19430e98adf..ce5bd4dc864d 100644
--- a/sound/soc/mediatek/mt2701/mt2701-afe-common.h
+++ b/sound/soc/mediatek/mt2701/mt2701-afe-common.h
@@ -69,53 +69,14 @@ enum {
 	MT2701_IRQ_ASYS_END,
 };
 
-/* 2701 clock def */
-enum audio_system_clock_type {
-	MT2701_AUD_INFRA_SYS_AUDIO,
-	MT2701_AUD_AUD_MUX1_SEL,
-	MT2701_AUD_AUD_MUX2_SEL,
-	MT2701_AUD_AUD_MUX1_DIV,
-	MT2701_AUD_AUD_MUX2_DIV,
-	MT2701_AUD_AUD_48K_TIMING,
-	MT2701_AUD_AUD_44K_TIMING,
-	MT2701_AUD_AUDPLL_MUX_SEL,
-	MT2701_AUD_APLL_SEL,
-	MT2701_AUD_AUD1PLL_98M,
-	MT2701_AUD_AUD2PLL_90M,
-	MT2701_AUD_HADDS2PLL_98M,
-	MT2701_AUD_HADDS2PLL_294M,
-	MT2701_AUD_AUDPLL,
-	MT2701_AUD_AUDPLL_D4,
-	MT2701_AUD_AUDPLL_D8,
-	MT2701_AUD_AUDPLL_D16,
-	MT2701_AUD_AUDPLL_D24,
-	MT2701_AUD_AUDINTBUS,
-	MT2701_AUD_CLK_26M,
-	MT2701_AUD_SYSPLL1_D4,
-	MT2701_AUD_AUD_K1_SRC_SEL,
-	MT2701_AUD_AUD_K2_SRC_SEL,
-	MT2701_AUD_AUD_K3_SRC_SEL,
-	MT2701_AUD_AUD_K4_SRC_SEL,
-	MT2701_AUD_AUD_K5_SRC_SEL,
-	MT2701_AUD_AUD_K6_SRC_SEL,
-	MT2701_AUD_AUD_K1_SRC_DIV,
-	MT2701_AUD_AUD_K2_SRC_DIV,
-	MT2701_AUD_AUD_K3_SRC_DIV,
-	MT2701_AUD_AUD_K4_SRC_DIV,
-	MT2701_AUD_AUD_K5_SRC_DIV,
-	MT2701_AUD_AUD_K6_SRC_DIV,
-	MT2701_AUD_AUD_I2S1_MCLK,
-	MT2701_AUD_AUD_I2S2_MCLK,
-	MT2701_AUD_AUD_I2S3_MCLK,
-	MT2701_AUD_AUD_I2S4_MCLK,
-	MT2701_AUD_AUD_I2S5_MCLK,
-	MT2701_AUD_AUD_I2S6_MCLK,
-	MT2701_AUD_ASM_M_SEL,
-	MT2701_AUD_ASM_H_SEL,
-	MT2701_AUD_UNIVPLL2_D4,
-	MT2701_AUD_UNIVPLL2_D2,
-	MT2701_AUD_SYSPLL_D5,
-	MT2701_CLOCK_NUM
+enum audio_base_clock {
+	MT2701_TOP_AUD_MCLK_SRC0,
+	MT2701_TOP_AUD_MCLK_SRC1,
+	MT2701_AUDSYS_AFE,
+	MT2701_AUDSYS_AFE_CONN,
+	MT2701_AUDSYS_A1SYS,
+	MT2701_AUDSYS_A2SYS,
+	MT2701_BASE_CLK_NUM,
 };
 
 static const unsigned int mt2701_afe_backup_list[] = {
@@ -144,7 +105,6 @@ struct mtk_base_irq_data;
 
 struct mt2701_i2s_data {
 	int i2s_ctrl_reg;
-	int i2s_pwn_shift;
 	int i2s_asrc_fs_shift;
 	int i2s_asrc_fs_mask;
 };
@@ -161,11 +121,17 @@ struct mt2701_i2s_path {
 	int on[I2S_DIR_NUM];
 	int occupied[I2S_DIR_NUM];
 	const struct mt2701_i2s_data *i2s_data[2];
+	struct clk *hop_ck[I2S_DIR_NUM];
+	struct clk *sel_ck;
+	struct clk *div_ck;
+	struct clk *mclk_ck;
+	struct clk *asrco_ck;
 };
 
 struct mt2701_afe_private {
-	struct clk *clocks[MT2701_CLOCK_NUM];
 	struct mt2701_i2s_path i2s_path[MT2701_I2S_NUM];
+	struct clk *base_ck[MT2701_BASE_CLK_NUM];
+	struct clk *mrgif_ck;
 	bool mrg_enable[MT2701_STREAM_DIR_NUM];
 };
 
diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c
index a7362d1cda1b..33f809228f25 100644
--- a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c
+++ b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c
@@ -97,21 +97,12 @@ static int mt2701_afe_i2s_startup(struct snd_pcm_substream *substream,
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct mtk_base_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
-	struct mt2701_afe_private *afe_priv = afe->platform_priv;
 	int i2s_num = mt2701_dai_num_to_i2s(afe, dai->id);
-	int clk_num = MT2701_AUD_AUD_I2S1_MCLK + i2s_num;
-	int ret = 0;
 
 	if (i2s_num < 0)
 		return i2s_num;
 
-	/* enable mclk */
-	ret = clk_prepare_enable(afe_priv->clocks[clk_num]);
-	if (ret)
-		dev_err(afe->dev, "Failed to enable mclk for I2S: %d\n",
-			i2s_num);
-
-	return ret;
+	return mt2701_afe_enable_mclk(afe, i2s_num);
 }
 
 static int mt2701_afe_i2s_path_shutdown(struct snd_pcm_substream *substream,
@@ -151,9 +142,9 @@ static int mt2701_afe_i2s_path_shutdown(struct snd_pcm_substream *substream,
 	/* disable i2s */
 	regmap_update_bits(afe->regmap, i2s_data->i2s_ctrl_reg,
 			   ASYS_I2S_CON_I2S_EN, 0);
-	regmap_update_bits(afe->regmap, AUDIO_TOP_CON4,
-			   1 << i2s_data->i2s_pwn_shift,
-			   1 << i2s_data->i2s_pwn_shift);
+
+	mt2701_afe_disable_i2s(afe, i2s_num, stream_dir);
+
 	return 0;
 }
 
@@ -165,7 +156,6 @@ static void mt2701_afe_i2s_shutdown(struct snd_pcm_substream *substream,
 	struct mt2701_afe_private *afe_priv = afe->platform_priv;
 	int i2s_num = mt2701_dai_num_to_i2s(afe, dai->id);
 	struct mt2701_i2s_path *i2s_path;
-	int clk_num = MT2701_AUD_AUD_I2S1_MCLK + i2s_num;
 
 	if (i2s_num < 0)
 		return;
@@ -185,7 +175,7 @@ static void mt2701_afe_i2s_shutdown(struct snd_pcm_substream *substream,
 
 I2S_UNSTART:
 	/* disable mclk */
-	clk_disable_unprepare(afe_priv->clocks[clk_num]);
+	mt2701_afe_disable_mclk(afe, i2s_num);
 }
 
 static int mt2701_i2s_path_prepare_enable(struct snd_pcm_substream *substream,
@@ -251,9 +241,7 @@ static int mt2701_i2s_path_prepare_enable(struct snd_pcm_substream *substream,
 			   fs << i2s_data->i2s_asrc_fs_shift);
 
 	/* enable i2s */
-	regmap_update_bits(afe->regmap, AUDIO_TOP_CON4,
-			   1 << i2s_data->i2s_pwn_shift,
-			   0 << i2s_data->i2s_pwn_shift);
+	mt2701_afe_enable_i2s(afe, i2s_num, stream_dir);
 
 	/* reset i2s hw status before enable */
 	regmap_update_bits(afe->regmap, i2s_data->i2s_ctrl_reg,
@@ -339,9 +327,11 @@ static int mt2701_btmrg_startup(struct snd_pcm_substream *substream,
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct mtk_base_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
 	struct mt2701_afe_private *afe_priv = afe->platform_priv;
+	int ret;
 
-	regmap_update_bits(afe->regmap, AUDIO_TOP_CON4,
-			   AUDIO_TOP_CON4_PDN_MRGIF, 0);
+	ret = mt2701_enable_btmrg_clk(afe);
+	if (ret)
+		return ret;
 
 	afe_priv->mrg_enable[substream->stream] = 1;
 	return 0;
@@ -406,9 +396,7 @@ static void mt2701_btmrg_shutdown(struct snd_pcm_substream *substream,
 				   AFE_MRGIF_CON_MRG_EN, 0);
 		regmap_update_bits(afe->regmap, AFE_MRGIF_CON,
 				   AFE_MRGIF_CON_MRG_I2S_EN, 0);
-		regmap_update_bits(afe->regmap, AUDIO_TOP_CON4,
-				   AUDIO_TOP_CON4_PDN_MRGIF,
-				   AUDIO_TOP_CON4_PDN_MRGIF);
+		mt2701_disable_btmrg_clk(afe);
 	}
 	afe_priv->mrg_enable[substream->stream] = 0;
 }
@@ -1386,14 +1374,12 @@ static const struct mt2701_i2s_data mt2701_i2s_data[MT2701_I2S_NUM][2] = {
 	{
 		{
 			.i2s_ctrl_reg = ASYS_I2SO1_CON,
-			.i2s_pwn_shift = 6,
 			.i2s_asrc_fs_shift = 0,
 			.i2s_asrc_fs_mask = 0x1f,
 
 		},
 		{
 			.i2s_ctrl_reg = ASYS_I2SIN1_CON,
-			.i2s_pwn_shift = 0,
 			.i2s_asrc_fs_shift = 0,
 			.i2s_asrc_fs_mask = 0x1f,
 
@@ -1402,14 +1388,12 @@ static const struct mt2701_i2s_data mt2701_i2s_data[MT2701_I2S_NUM][2] = {
 	{
 		{
 			.i2s_ctrl_reg = ASYS_I2SO2_CON,
-			.i2s_pwn_shift = 7,
 			.i2s_asrc_fs_shift = 5,
 			.i2s_asrc_fs_mask = 0x1f,
 
 		},
 		{
 			.i2s_ctrl_reg = ASYS_I2SIN2_CON,
-			.i2s_pwn_shift = 1,
 			.i2s_asrc_fs_shift = 5,
 			.i2s_asrc_fs_mask = 0x1f,
 
@@ -1418,14 +1402,12 @@ static const struct mt2701_i2s_data mt2701_i2s_data[MT2701_I2S_NUM][2] = {
 	{
 		{
 			.i2s_ctrl_reg = ASYS_I2SO3_CON,
-			.i2s_pwn_shift = 8,
 			.i2s_asrc_fs_shift = 10,
 			.i2s_asrc_fs_mask = 0x1f,
 
 		},
 		{
 			.i2s_ctrl_reg = ASYS_I2SIN3_CON,
-			.i2s_pwn_shift = 2,
 			.i2s_asrc_fs_shift = 10,
 			.i2s_asrc_fs_mask = 0x1f,
 
@@ -1434,14 +1416,12 @@ static const struct mt2701_i2s_data mt2701_i2s_data[MT2701_I2S_NUM][2] = {
 	{
 		{
 			.i2s_ctrl_reg = ASYS_I2SO4_CON,
-			.i2s_pwn_shift = 9,
 			.i2s_asrc_fs_shift = 15,
 			.i2s_asrc_fs_mask = 0x1f,
 
 		},
 		{
 			.i2s_ctrl_reg = ASYS_I2SIN4_CON,
-			.i2s_pwn_shift = 3,
 			.i2s_asrc_fs_shift = 15,
 			.i2s_asrc_fs_mask = 0x1f,
 
@@ -1483,8 +1463,7 @@ static int mt2701_afe_runtime_suspend(struct device *dev)
 {
 	struct mtk_base_afe *afe = dev_get_drvdata(dev);
 
-	mt2701_afe_disable_clock(afe);
-	return 0;
+	return mt2701_afe_disable_clock(afe);
 }
 
 static int mt2701_afe_runtime_resume(struct device *dev)
-- 
2.15.1

^ permalink raw reply related

* Applied "ASoC: mediatek: cleanup audio driver for MT2701" to the asoc tree
From: Mark Brown @ 2018-01-03 15:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <eadb3c22b52b8631319b1aae53d9282bc3bdf328.1514881870.git.ryder.lee@mediatek.com>

The patch

   ASoC: mediatek: cleanup audio driver for MT2701

has been applied to the asoc tree at

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 600b2fd4f0f7ae5ebcb604c39c9a97e573f9d23e Mon Sep 17 00:00:00 2001
From: Ryder Lee <ryder.lee@mediatek.com>
Date: Tue, 2 Jan 2018 19:47:20 +0800
Subject: [PATCH] ASoC: mediatek: cleanup audio driver for MT2701

Cleanup unused code such as 'i2s_num' guard, headers, indentation
and some defines.

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c | 14 +---
 sound/soc/mediatek/mt2701/mt2701-afe-common.h     | 20 +----
 sound/soc/mediatek/mt2701/mt2701-afe-pcm.c        | 94 ++++-------------------
 sound/soc/mediatek/mt2701/mt2701-reg.h            | 41 +---------
 4 files changed, 24 insertions(+), 145 deletions(-)

diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c b/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c
index 75ccdca5811d..56a057c78c9a 100644
--- a/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c
+++ b/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c
@@ -14,10 +14,6 @@
  * GNU General Public License for more details.
  */
 
-#include <sound/soc.h>
-#include <linux/regmap.h>
-#include <linux/pm_runtime.h>
-
 #include "mt2701-afe-common.h"
 #include "mt2701-afe-clock-ctrl.h"
 
@@ -223,8 +219,8 @@ int mt2701_afe_enable_clock(struct mtk_base_afe *afe)
 	}
 
 	regmap_update_bits(afe->regmap, ASYS_TOP_CON,
-			   AUDIO_TOP_CON0_A1SYS_A2SYS_ON,
-			   AUDIO_TOP_CON0_A1SYS_A2SYS_ON);
+			   ASYS_TOP_CON_ASYS_TIMING_ON,
+			   ASYS_TOP_CON_ASYS_TIMING_ON);
 	regmap_update_bits(afe->regmap, AFE_DAC_CON0,
 			   AFE_DAC_CON0_AFE_ON,
 			   AFE_DAC_CON0_AFE_ON);
@@ -239,7 +235,7 @@ int mt2701_afe_enable_clock(struct mtk_base_afe *afe)
 int mt2701_afe_disable_clock(struct mtk_base_afe *afe)
 {
 	regmap_update_bits(afe->regmap, ASYS_TOP_CON,
-			   AUDIO_TOP_CON0_A1SYS_A2SYS_ON, 0);
+			   ASYS_TOP_CON_ASYS_TIMING_ON, 0);
 	regmap_update_bits(afe->regmap, AFE_DAC_CON0,
 			   AFE_DAC_CON0_AFE_ON, 0);
 
@@ -272,7 +268,3 @@ void mt2701_mclk_configuration(struct mtk_base_afe *afe, int id, int domain,
 	if (ret)
 		dev_err(afe->dev, "failed to set mclk divider %d\n", ret);
 }
-
-MODULE_DESCRIPTION("MT2701 afe clock control");
-MODULE_AUTHOR("Garlic Tseng <garlic.tseng@mediatek.com>");
-MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-common.h b/sound/soc/mediatek/mt2701/mt2701-afe-common.h
index ce5bd4dc864d..9a2b301a4c21 100644
--- a/sound/soc/mediatek/mt2701/mt2701-afe-common.h
+++ b/sound/soc/mediatek/mt2701/mt2701-afe-common.h
@@ -16,6 +16,7 @@
 
 #ifndef _MT_2701_AFE_COMMON_H_
 #define _MT_2701_AFE_COMMON_H_
+
 #include <sound/soc.h>
 #include <linux/clk.h>
 #include <linux/regmap.h>
@@ -25,16 +26,7 @@
 #define MT2701_STREAM_DIR_NUM (SNDRV_PCM_STREAM_LAST + 1)
 #define MT2701_PLL_DOMAIN_0_RATE	98304000
 #define MT2701_PLL_DOMAIN_1_RATE	90316800
-#define MT2701_AUD_AUD_MUX1_DIV_RATE (MT2701_PLL_DOMAIN_0_RATE / 2)
-#define MT2701_AUD_AUD_MUX2_DIV_RATE (MT2701_PLL_DOMAIN_1_RATE / 2)
-
-enum {
-	MT2701_I2S_1,
-	MT2701_I2S_2,
-	MT2701_I2S_3,
-	MT2701_I2S_4,
-	MT2701_I2S_NUM,
-};
+#define MT2701_I2S_NUM	4
 
 enum {
 	MT2701_MEMIF_DL1,
@@ -62,8 +54,7 @@ enum {
 };
 
 enum {
-	MT2701_IRQ_ASYS_START,
-	MT2701_IRQ_ASYS_IRQ1 = MT2701_IRQ_ASYS_START,
+	MT2701_IRQ_ASYS_IRQ1,
 	MT2701_IRQ_ASYS_IRQ2,
 	MT2701_IRQ_ASYS_IRQ3,
 	MT2701_IRQ_ASYS_END,
@@ -100,9 +91,6 @@ static const unsigned int mt2701_afe_backup_list[] = {
 	AFE_MEMIF_PBUF_SIZE,
 };
 
-struct snd_pcm_substream;
-struct mtk_base_irq_data;
-
 struct mt2701_i2s_data {
 	int i2s_ctrl_reg;
 	int i2s_asrc_fs_shift;
@@ -120,7 +108,7 @@ struct mt2701_i2s_path {
 	int mclk_rate;
 	int on[I2S_DIR_NUM];
 	int occupied[I2S_DIR_NUM];
-	const struct mt2701_i2s_data *i2s_data[2];
+	const struct mt2701_i2s_data *i2s_data[I2S_DIR_NUM];
 	struct clk *hop_ck[I2S_DIR_NUM];
 	struct clk *sel_ck;
 	struct clk *div_ck;
diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c
index 33f809228f25..0edadca12a5e 100644
--- a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c
+++ b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c
@@ -20,16 +20,12 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/pm_runtime.h>
-#include <sound/soc.h>
 
 #include "mt2701-afe-common.h"
-
 #include "mt2701-afe-clock-ctrl.h"
 #include "../common/mtk-afe-platform-driver.h"
 #include "../common/mtk-afe-fe-dai.h"
 
-#define AFE_IRQ_STATUS_BITS	0xff
-
 static const struct snd_pcm_hardware mt2701_afe_hardware = {
 	.info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED
 		| SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_MMAP_VALID,
@@ -107,21 +103,16 @@ static int mt2701_afe_i2s_startup(struct snd_pcm_substream *substream,
 
 static int mt2701_afe_i2s_path_shutdown(struct snd_pcm_substream *substream,
 					struct snd_soc_dai *dai,
+					int i2s_num,
 					int dir_invert)
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct mtk_base_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
 	struct mt2701_afe_private *afe_priv = afe->platform_priv;
-	int i2s_num = mt2701_dai_num_to_i2s(afe, dai->id);
-	struct mt2701_i2s_path *i2s_path;
+	struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[i2s_num];
 	const struct mt2701_i2s_data *i2s_data;
 	int stream_dir = substream->stream;
 
-	if (i2s_num < 0)
-		return i2s_num;
-
-	i2s_path = &afe_priv->i2s_path[i2s_num];
-
 	if (dir_invert)	{
 		if (stream_dir == SNDRV_PCM_STREAM_PLAYBACK)
 			stream_dir = SNDRV_PCM_STREAM_CAPTURE;
@@ -167,11 +158,11 @@ static void mt2701_afe_i2s_shutdown(struct snd_pcm_substream *substream,
 	else
 		goto I2S_UNSTART;
 
-	mt2701_afe_i2s_path_shutdown(substream, dai, 0);
+	mt2701_afe_i2s_path_shutdown(substream, dai, i2s_num, 0);
 
 	/* need to disable i2s-out path when disable i2s-in */
 	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
-		mt2701_afe_i2s_path_shutdown(substream, dai, 1);
+		mt2701_afe_i2s_path_shutdown(substream, dai, i2s_num, 1);
 
 I2S_UNSTART:
 	/* disable mclk */
@@ -180,24 +171,19 @@ static void mt2701_afe_i2s_shutdown(struct snd_pcm_substream *substream,
 
 static int mt2701_i2s_path_prepare_enable(struct snd_pcm_substream *substream,
 					  struct snd_soc_dai *dai,
+					  int i2s_num,
 					  int dir_invert)
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct mtk_base_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
 	struct mt2701_afe_private *afe_priv = afe->platform_priv;
-	int i2s_num = mt2701_dai_num_to_i2s(afe, dai->id);
-	struct mt2701_i2s_path *i2s_path;
+	struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[i2s_num];
 	const struct mt2701_i2s_data *i2s_data;
 	struct snd_pcm_runtime * const runtime = substream->runtime;
 	int reg, fs, w_len = 1; /* now we support bck 64bits only */
 	int stream_dir = substream->stream;
 	unsigned int mask = 0, val = 0;
 
-	if (i2s_num < 0)
-		return i2s_num;
-
-	i2s_path = &afe_priv->i2s_path[i2s_num];
-
 	if (dir_invert) {
 		if (stream_dir == SNDRV_PCM_STREAM_PLAYBACK)
 			stream_dir = SNDRV_PCM_STREAM_CAPTURE;
@@ -288,13 +274,13 @@ static int mt2701_afe_i2s_prepare(struct snd_pcm_substream *substream,
 	mt2701_mclk_configuration(afe, i2s_num, clk_domain, mclk_rate);
 
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		mt2701_i2s_path_prepare_enable(substream, dai, 0);
+		mt2701_i2s_path_prepare_enable(substream, dai, i2s_num, 0);
 	} else {
 		/* need to enable i2s-out path when enable i2s-in */
 		/* prepare for another direction "out" */
-		mt2701_i2s_path_prepare_enable(substream, dai, 1);
+		mt2701_i2s_path_prepare_enable(substream, dai, i2s_num, 1);
 		/* prepare for "in" */
-		mt2701_i2s_path_prepare_enable(substream, dai, 0);
+		mt2701_i2s_path_prepare_enable(substream, dai, i2s_num, 0);
 	}
 
 	return 0;
@@ -562,7 +548,6 @@ static const struct snd_soc_dai_ops mt2701_single_memif_dai_ops = {
 	.hw_free	= mtk_afe_fe_hw_free,
 	.prepare	= mtk_afe_fe_prepare,
 	.trigger	= mtk_afe_fe_trigger,
-
 };
 
 static const struct snd_soc_dai_ops mt2701_dlm_memif_dai_ops = {
@@ -903,31 +888,6 @@ static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_i2s4[] = {
 				    PWR2_TOP_CON, 19, 1, 0),
 };
 
-static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_asrc0[] = {
-	SOC_DAPM_SINGLE_AUTODISABLE("Asrc0 out Switch", AUDIO_TOP_CON4, 14, 1,
-				    1),
-};
-
-static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_asrc1[] = {
-	SOC_DAPM_SINGLE_AUTODISABLE("Asrc1 out Switch", AUDIO_TOP_CON4, 15, 1,
-				    1),
-};
-
-static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_asrc2[] = {
-	SOC_DAPM_SINGLE_AUTODISABLE("Asrc2 out Switch", PWR2_TOP_CON, 6, 1,
-				    1),
-};
-
-static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_asrc3[] = {
-	SOC_DAPM_SINGLE_AUTODISABLE("Asrc3 out Switch", PWR2_TOP_CON, 7, 1,
-				    1),
-};
-
-static const struct snd_kcontrol_new mt2701_afe_multi_ch_out_asrc4[] = {
-	SOC_DAPM_SINGLE_AUTODISABLE("Asrc4 out Switch", PWR2_TOP_CON, 8, 1,
-				    1),
-};
-
 static const struct snd_soc_dapm_widget mt2701_afe_pcm_widgets[] = {
 	/* inter-connections */
 	SND_SOC_DAPM_MIXER("I00", SND_SOC_NOPM, 0, 0, NULL, 0),
@@ -987,19 +947,6 @@ static const struct snd_soc_dapm_widget mt2701_afe_pcm_widgets[] = {
 	SND_SOC_DAPM_MIXER("I18I19", SND_SOC_NOPM, 0, 0,
 			   mt2701_afe_multi_ch_out_i2s3,
 			   ARRAY_SIZE(mt2701_afe_multi_ch_out_i2s3)),
-
-	SND_SOC_DAPM_MIXER("ASRC_O0", SND_SOC_NOPM, 0, 0,
-			   mt2701_afe_multi_ch_out_asrc0,
-			   ARRAY_SIZE(mt2701_afe_multi_ch_out_asrc0)),
-	SND_SOC_DAPM_MIXER("ASRC_O1", SND_SOC_NOPM, 0, 0,
-			   mt2701_afe_multi_ch_out_asrc1,
-			   ARRAY_SIZE(mt2701_afe_multi_ch_out_asrc1)),
-	SND_SOC_DAPM_MIXER("ASRC_O2", SND_SOC_NOPM, 0, 0,
-			   mt2701_afe_multi_ch_out_asrc2,
-			   ARRAY_SIZE(mt2701_afe_multi_ch_out_asrc2)),
-	SND_SOC_DAPM_MIXER("ASRC_O3", SND_SOC_NOPM, 0, 0,
-			   mt2701_afe_multi_ch_out_asrc3,
-			   ARRAY_SIZE(mt2701_afe_multi_ch_out_asrc3)),
 };
 
 static const struct snd_soc_dapm_route mt2701_afe_pcm_routes[] = {
@@ -1009,7 +956,6 @@ static const struct snd_soc_dapm_route mt2701_afe_pcm_routes[] = {
 
 	{"I2S0 Playback", NULL, "O15"},
 	{"I2S0 Playback", NULL, "O16"},
-
 	{"I2S1 Playback", NULL, "O17"},
 	{"I2S1 Playback", NULL, "O18"},
 	{"I2S2 Playback", NULL, "O19"},
@@ -1026,7 +972,6 @@ static const struct snd_soc_dapm_route mt2701_afe_pcm_routes[] = {
 
 	{"I00", NULL, "I2S0 Capture"},
 	{"I01", NULL, "I2S0 Capture"},
-
 	{"I02", NULL, "I2S1 Capture"},
 	{"I03", NULL, "I2S1 Capture"},
 	/* I02,03 link to UL2, also need to open I2S0 */
@@ -1034,15 +979,10 @@ static const struct snd_soc_dapm_route mt2701_afe_pcm_routes[] = {
 
 	{"I26", NULL, "BT Capture"},
 
-	{"ASRC_O0", "Asrc0 out Switch", "DLM"},
-	{"ASRC_O1", "Asrc1 out Switch", "DLM"},
-	{"ASRC_O2", "Asrc2 out Switch", "DLM"},
-	{"ASRC_O3", "Asrc3 out Switch", "DLM"},
-
-	{"I12I13", "Multich I2S0 Out Switch", "ASRC_O0"},
-	{"I14I15", "Multich I2S1 Out Switch", "ASRC_O1"},
-	{"I16I17", "Multich I2S2 Out Switch", "ASRC_O2"},
-	{"I18I19", "Multich I2S3 Out Switch", "ASRC_O3"},
+	{"I12I13", "Multich I2S0 Out Switch", "DLM"},
+	{"I14I15", "Multich I2S1 Out Switch", "DLM"},
+	{"I16I17", "Multich I2S2 Out Switch", "DLM"},
+	{"I18I19", "Multich I2S3 Out Switch", "DLM"},
 
 	{ "I12", NULL, "I12I13" },
 	{ "I13", NULL, "I12I13" },
@@ -1067,7 +1007,6 @@ static const struct snd_soc_dapm_route mt2701_afe_pcm_routes[] = {
 	{ "O21", "I18 Switch", "I18" },
 	{ "O22", "I19 Switch", "I19" },
 	{ "O31", "I35 Switch", "I35" },
-
 };
 
 static const struct snd_soc_component_driver mt2701_afe_pcm_dai_component = {
@@ -1484,12 +1423,13 @@ static int mt2701_afe_pcm_dev_probe(struct platform_device *pdev)
 	afe = devm_kzalloc(&pdev->dev, sizeof(*afe), GFP_KERNEL);
 	if (!afe)
 		return -ENOMEM;
+
 	afe->platform_priv = devm_kzalloc(&pdev->dev, sizeof(*afe_priv),
 					  GFP_KERNEL);
 	if (!afe->platform_priv)
 		return -ENOMEM;
-	afe_priv = afe->platform_priv;
 
+	afe_priv = afe->platform_priv;
 	afe->dev = &pdev->dev;
 	dev = afe->dev;
 
@@ -1524,7 +1464,6 @@ static int mt2701_afe_pcm_dev_probe(struct platform_device *pdev)
 	afe->memif_size = MT2701_MEMIF_NUM;
 	afe->memif = devm_kcalloc(dev, afe->memif_size, sizeof(*afe->memif),
 				  GFP_KERNEL);
-
 	if (!afe->memif)
 		return -ENOMEM;
 
@@ -1537,7 +1476,6 @@ static int mt2701_afe_pcm_dev_probe(struct platform_device *pdev)
 	afe->irqs_size = MT2701_IRQ_ASYS_END;
 	afe->irqs = devm_kcalloc(dev, afe->irqs_size, sizeof(*afe->irqs),
 				 GFP_KERNEL);
-
 	if (!afe->irqs)
 		return -ENOMEM;
 
@@ -1555,7 +1493,6 @@ static int mt2701_afe_pcm_dev_probe(struct platform_device *pdev)
 	afe->mtk_afe_hardware = &mt2701_afe_hardware;
 	afe->memif_fs = mt2701_memif_fs;
 	afe->irq_fs = mt2701_irq_fs;
-
 	afe->reg_back_up_list = mt2701_afe_backup_list;
 	afe->reg_back_up_list_num = ARRAY_SIZE(mt2701_afe_backup_list);
 	afe->runtime_resume = mt2701_afe_runtime_resume;
@@ -1646,4 +1583,3 @@ module_platform_driver(mt2701_afe_pcm_driver);
 MODULE_DESCRIPTION("Mediatek ALSA SoC AFE platform driver for 2701");
 MODULE_AUTHOR("Garlic Tseng <garlic.tseng@mediatek.com>");
 MODULE_LICENSE("GPL v2");
-
diff --git a/sound/soc/mediatek/mt2701/mt2701-reg.h b/sound/soc/mediatek/mt2701/mt2701-reg.h
index bb62b1c55957..f17c76f37b5f 100644
--- a/sound/soc/mediatek/mt2701/mt2701-reg.h
+++ b/sound/soc/mediatek/mt2701/mt2701-reg.h
@@ -17,17 +17,6 @@
 #ifndef _MT2701_REG_H_
 #define _MT2701_REG_H_
 
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/pm_runtime.h>
-#include <sound/soc.h>
-#include "mt2701-afe-common.h"
-
-/*****************************************************************************
- *                  R E G I S T E R       D E F I N I T I O N
- *****************************************************************************/
 #define AUDIO_TOP_CON0 0x0000
 #define AUDIO_TOP_CON4 0x0010
 #define AUDIO_TOP_CON5 0x0014
@@ -109,18 +98,6 @@
 #define AFE_DAI_BASE 0x1370
 #define AFE_DAI_CUR 0x137c
 
-/* AUDIO_TOP_CON0 (0x0000) */
-#define AUDIO_TOP_CON0_A1SYS_A2SYS_ON	(0x3 << 0)
-#define AUDIO_TOP_CON0_PDN_AFE		(0x1 << 2)
-#define AUDIO_TOP_CON0_PDN_APLL_CK	(0x1 << 23)
-
-/* AUDIO_TOP_CON4 (0x0010) */
-#define AUDIO_TOP_CON4_I2SO1_PWN	(0x1 << 6)
-#define AUDIO_TOP_CON4_PDN_A1SYS	(0x1 << 21)
-#define AUDIO_TOP_CON4_PDN_A2SYS	(0x1 << 22)
-#define AUDIO_TOP_CON4_PDN_AFE_CONN	(0x1 << 23)
-#define AUDIO_TOP_CON4_PDN_MRGIF	(0x1 << 25)
-
 /* AFE_DAIBT_CON0 (0x001c) */
 #define AFE_DAIBT_CON0_DAIBT_EN		(0x1 << 0)
 #define AFE_DAIBT_CON0_BT_FUNC_EN	(0x1 << 1)
@@ -137,22 +114,8 @@
 #define AFE_MRGIF_CON_I2S_MODE_MASK	(0xf << 20)
 #define AFE_MRGIF_CON_I2S_MODE_32K	(0x4 << 20)
 
-/* ASYS_I2SO1_CON (0x061c) */
-#define ASYS_I2SO1_CON_FS		(0x1f << 8)
-#define ASYS_I2SO1_CON_FS_SET(x)	((x) << 8)
-#define ASYS_I2SO1_CON_MULTI_CH		(0x1 << 16)
-#define ASYS_I2SO1_CON_SIDEGEN		(0x1 << 30)
-#define ASYS_I2SO1_CON_I2S_EN		(0x1 << 0)
-/* 0:EIAJ 1:I2S */
-#define ASYS_I2SO1_CON_I2S_MODE		(0x1 << 3)
-#define ASYS_I2SO1_CON_WIDE_MODE	(0x1 << 1)
-#define ASYS_I2SO1_CON_WIDE_MODE_SET(x)	((x) << 1)
-
-/* PWR2_TOP_CON (0x0634) */
-#define PWR2_TOP_CON_INIT_VAL		(0xffe1ffff)
-
-/* ASYS_IRQ_CLR (0x07c0) */
-#define ASYS_IRQ_CLR_ALL		(0xffffffff)
+/* ASYS_TOP_CON (0x0600) */
+#define ASYS_TOP_CON_ASYS_TIMING_ON		(0x3 << 0)
 
 /* PWR2_ASM_CON1 (0x1070) */
 #define PWR2_ASM_CON1_INIT_VAL		(0x492492)
-- 
2.15.1

^ permalink raw reply related

* Vibrations, audio, charging, radio on N9/N950
From: Pali Rohár @ 2018-01-03 15:40 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <64f11661-794d-826e-89fc-08b4c15ee673@gmail.com>

On Wednesday 03 January 2018 16:34:15 Filip Matijevi? wrote:
> Hi,
> 
> On 01/03/2018 02:56 PM, Pavel Machek wrote:
> > Hi!
> > 
> > Sebasian, you submitted patch to enable vibrations on N950. I am
> > trying to do the same now on N9... I guess I enabled the dts, but
> > .. how do I actually ask for vibrations? /dev/input/eventX does not
> > seem to be present.
> > 
> > Did anyone get audio to run on N9/N950? It is marked as supported on
> > https://elinux.org/N950 with dt glue missing...
> > 
> 
> I have fairly recent patches (for v4.10) here:
> https://github.com/filippz/pmbootstrap/commit/600473432d8ff61ae80a7e2a198d9442fd3a6f2e
> (from 0015 trough 0022 w/o 0016). Vibration was working as was audio
> playback from twl5031 and tvl320dac33 together with tpa6140a2. More
> details here: http://talk.maemo.org/showpost.php?p=1492590&postcount=112
> I hope that you can use those patches at least to some degree.
> 
> > Even more importantly, does battery charging work for someone? It does
> > not work here :-(. After USB is plugged in, it maybe tries to charge,
> > but gives up after 30 seconds.
> > 
> > Maybe least important, but... does anyone have FM radio working? I'd
> > like to play some music...
> 
> I haven't used FM radio nor BT (wl1273), so I can't comment on that, but
> they are in there but probably need some work.

IIRC there were some problems with FM chip on N9 or N950... something
like chip was not connected to antenna... But do not remember details.

-- 
Pali Roh?r
pali.rohar at gmail.com

^ permalink raw reply

* Vibrations, audio, charging, radio on N9/N950
From: Filip Matijević @ 2018-01-03 15:34 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180103135635.GA17854@amd>

Hi,

On 01/03/2018 02:56 PM, Pavel Machek wrote:
> Hi!
> 
> Sebasian, you submitted patch to enable vibrations on N950. I am
> trying to do the same now on N9... I guess I enabled the dts, but
> .. how do I actually ask for vibrations? /dev/input/eventX does not
> seem to be present.
> 
> Did anyone get audio to run on N9/N950? It is marked as supported on
> https://elinux.org/N950 with dt glue missing...
> 

I have fairly recent patches (for v4.10) here:
https://github.com/filippz/pmbootstrap/commit/600473432d8ff61ae80a7e2a198d9442fd3a6f2e
(from 0015 trough 0022 w/o 0016). Vibration was working as was audio
playback from twl5031 and tvl320dac33 together with tpa6140a2. More
details here: http://talk.maemo.org/showpost.php?p=1492590&postcount=112
I hope that you can use those patches at least to some degree.

> Even more importantly, does battery charging work for someone? It does
> not work here :-(. After USB is plugged in, it maybe tries to charge,
> but gives up after 30 seconds.
> 
> Maybe least important, but... does anyone have FM radio working? I'd
> like to play some music...

I haven't used FM radio nor BT (wl1273), so I can't comment on that, but
they are in there but probably need some work.

> 
> 									Pavel
> 

Best regards,
Filip

^ permalink raw reply

* [PATCH] arm64: dts: marvell: add Ethernet aliases
From: Antoine Tenart @ 2018-01-03 15:18 UTC (permalink / raw)
  To: linux-arm-kernel

From: Yan Markman <ymarkman@marvell.com>

This patch adds Ethernet aliases in the Marvell Armada 7040 DB, 8040 DB
and 8040 mcbin device trees so that the bootloader setup the MAC
addresses correctly.

Signed-off-by: Yan Markman <ymarkman@marvell.com>
[Antoine: commit message, small fixes]
Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
---

Hi,

This patch is based on the latest mvebu/dt64 tree, which already
contains Thomas' DT de-duplication patches, so there shouldn't be any
conflict.

Thanks!
Antoine

 arch/arm64/boot/dts/marvell/armada-7040-db.dts    | 6 ++++++
 arch/arm64/boot/dts/marvell/armada-8040-db.dts    | 7 +++++++
 arch/arm64/boot/dts/marvell/armada-8040-mcbin.dts | 6 ++++++
 3 files changed, 19 insertions(+)

diff --git a/arch/arm64/boot/dts/marvell/armada-7040-db.dts b/arch/arm64/boot/dts/marvell/armada-7040-db.dts
index 44c95b97a422..3ae05eee2c9a 100644
--- a/arch/arm64/boot/dts/marvell/armada-7040-db.dts
+++ b/arch/arm64/boot/dts/marvell/armada-7040-db.dts
@@ -61,6 +61,12 @@
 		reg = <0x0 0x0 0x0 0x80000000>;
 	};
 
+	aliases {
+		ethernet0 = &cp0_eth0;
+		ethernet1 = &cp0_eth1;
+		ethernet2 = &cp0_eth2;
+	};
+
 	cp0_reg_usb3_0_vbus: cp0-usb3-0-vbus {
 		compatible = "regulator-fixed";
 		regulator-name = "usb3h0-vbus";
diff --git a/arch/arm64/boot/dts/marvell/armada-8040-db.dts b/arch/arm64/boot/dts/marvell/armada-8040-db.dts
index 13e3209d554a..dba55baff20f 100644
--- a/arch/arm64/boot/dts/marvell/armada-8040-db.dts
+++ b/arch/arm64/boot/dts/marvell/armada-8040-db.dts
@@ -61,6 +61,13 @@
 		reg = <0x0 0x0 0x0 0x80000000>;
 	};
 
+	aliases {
+		ethernet0 = &cp0_eth0;
+		ethernet1 = &cp0_eth2;
+		ethernet2 = &cp1_eth0;
+		ethernet3 = &cp1_eth1;
+	};
+
 	cp0_reg_usb3_0_vbus: cp0-usb3-0-vbus {
 		compatible = "regulator-fixed";
 		regulator-name = "cp0-usb3h0-vbus";
diff --git a/arch/arm64/boot/dts/marvell/armada-8040-mcbin.dts b/arch/arm64/boot/dts/marvell/armada-8040-mcbin.dts
index cf0ebd38a2b9..91c19dd04082 100644
--- a/arch/arm64/boot/dts/marvell/armada-8040-mcbin.dts
+++ b/arch/arm64/boot/dts/marvell/armada-8040-mcbin.dts
@@ -62,6 +62,12 @@
 		reg = <0x0 0x0 0x0 0x80000000>;
 	};
 
+	aliases {
+		ethernet0 = &cp0_eth0;
+		ethernet1 = &cp1_eth0;
+		ethernet2 = &cp1_eth1;
+	};
+
 	/* Regulator labels correspond with schematics */
 	v_3_3: regulator-3-3v {
 		compatible = "regulator-fixed";
-- 
2.14.3

^ permalink raw reply related

* [PATCH net-next 1/6] phy: add 2.5G SGMII mode to the phy_mode enum
From: Andrew Lunn @ 2018-01-03 15:08 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180103143541.GE21727@kwain>

> > >>> diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h
> > >>> index 4f8423a948d5..70459a28f3a1 100644
> > >>> --- a/include/linux/phy/phy.h
> > >>> +++ b/include/linux/phy/phy.h
> > >>> @@ -28,6 +28,7 @@ enum phy_mode {
> > >>>  	PHY_MODE_USB_DEVICE,
> > >>>  	PHY_MODE_USB_OTG,
> > >>>  	PHY_MODE_SGMII,
> > >>> +	PHY_MODE_SGMII_2_5G,
> > >>>  	PHY_MODE_10GKR,
> > >>>  	PHY_MODE_UFS_HS_A,
> > >>>  	PHY_MODE_UFS_HS_B,
> > >>
> > >> There was a discussion maybe last month about adding 2.5G SGMII. I
> > >> would prefer 2500SGMII. Putting the number first makes it uniform with
> > >> the other defines, 1000BASEX, 25000BASEX, 10GKR.
> > > 
> > > Good to know. I wasn't completely sure how to name this mode properly,
> > > but I'm fine with PHY_MODE_2500SGMII. I'll update the patches and send a
> > > v2 (without the dt part).
> > 
> > And since you are respinning, please make sure you update phy_modes() in
> > the same header file as well as
> > Documentation/devicetree/bindings/net/ethernet.txt with the newly added
> > PHY interface mode.
> 
> Actually it's a generic PHY mode I'm adding, not a network PHY mode.
> There's no phy_modes() function for generic PHYs (and this 2500BaseX
> mode already is supported in the network PHY modes).

Hi Antoine

Don't you need it in both include/linux/phy/phy.h and
include/linux/phy.h?

	Andrew

^ permalink raw reply

* [PATCH net-next 1/6] phy: add 2.5G SGMII mode to the phy_mode enum
From: Antoine Tenart @ 2018-01-03 14:35 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <91838ce5-a1a8-c41a-36e8-bef7adaf82fd@gmail.com>

Hi Florian,

On Thu, Dec 28, 2017 at 06:16:51AM -0800, Florian Fainelli wrote:
> On 12/28/2017 02:06 AM, Antoine Tenart wrote:
> > On Thu, Dec 28, 2017 at 08:20:53AM +0100, Andrew Lunn wrote:
> >> On Wed, Dec 27, 2017 at 11:14:41PM +0100, Antoine Tenart wrote:
> >>> This patch adds one more generic PHY mode to the phy_mode enum, to allow
> >>> configuring generic PHYs to the 2.5G SGMII mode by using the set_mode
> >>> callback.
> >>>
> >>> Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
> >>> ---
> >>>  include/linux/phy/phy.h | 1 +
> >>>  1 file changed, 1 insertion(+)
> >>>
> >>> diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h
> >>> index 4f8423a948d5..70459a28f3a1 100644
> >>> --- a/include/linux/phy/phy.h
> >>> +++ b/include/linux/phy/phy.h
> >>> @@ -28,6 +28,7 @@ enum phy_mode {
> >>>  	PHY_MODE_USB_DEVICE,
> >>>  	PHY_MODE_USB_OTG,
> >>>  	PHY_MODE_SGMII,
> >>> +	PHY_MODE_SGMII_2_5G,
> >>>  	PHY_MODE_10GKR,
> >>>  	PHY_MODE_UFS_HS_A,
> >>>  	PHY_MODE_UFS_HS_B,
> >>
> >> There was a discussion maybe last month about adding 2.5G SGMII. I
> >> would prefer 2500SGMII. Putting the number first makes it uniform with
> >> the other defines, 1000BASEX, 25000BASEX, 10GKR.
> > 
> > Good to know. I wasn't completely sure how to name this mode properly,
> > but I'm fine with PHY_MODE_2500SGMII. I'll update the patches and send a
> > v2 (without the dt part).
> 
> And since you are respinning, please make sure you update phy_modes() in
> the same header file as well as
> Documentation/devicetree/bindings/net/ethernet.txt with the newly added
> PHY interface mode.

Actually it's a generic PHY mode I'm adding, not a network PHY mode.
There's no phy_modes() function for generic PHYs (and this 2500BaseX
mode already is supported in the network PHY modes).

Thanks!
Antoine

-- 
Antoine T?nart, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

^ permalink raw reply

* [PATCH v5 7/9] arm64: Topology, rename cluster_id
From: Sudeep Holla @ 2018-01-03 14:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <965127a6-816b-8e0c-d228-a3d73a8c643a@huawei.com>


On 02/01/18 02:29, Xiongfeng Wang wrote:
> Hi,
> 
> On 2017/12/18 20:42, Morten Rasmussen wrote:
>> On Fri, Dec 15, 2017 at 10:36:35AM -0600, Jeremy Linton wrote:
>>> Hi,
>>>
>>> On 12/13/2017 12:02 PM, Lorenzo Pieralisi wrote:
>>>> [+Morten, Dietmar]
>>>>
>>>> $SUBJECT should be:
>>>>
>>>> arm64: topology: rename cluster_id
>>>
> [cut]
>>>
> I think we still need the information describing which cores are in one
> cluster. Many arm64 chips have the architecture core/cluster/socket. Cores
> in one cluster may share a same L2 cache. That information can be used to
> build the sched_domain. If we put cores in one cluster in one sched_domain,
> the performance will be better.(please see kernel/sched/topology.c:1197,
> cpu_coregroup_mask() uses 'core_sibling' to build a multi-core
> sched_domain).

We get all the cache information from DT/ACPI PPTT(mainly topology) and now
even the geometry. So ideally, the sharing information must come from that.
Any other solution might end up in conflict if DT/PPTT and that mismatch.

> So I think we still need variable to record which cores are in one
> sched_domain for future use.

I tend to say no, at-least not as is.
-- 
Regards,
Sudeep

^ permalink raw reply

* [PATCH v5 4/9] drivers: base cacheinfo: Add support for ACPI based firmware tables
From: Sudeep Holla @ 2018-01-03 14:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <fdb60100-3973-b9e3-487a-882836f8751e@arm.com>

(Sorry for the delay, just returning from vacation)

On 12/12/17 23:37, Jeremy Linton wrote:
> On 12/12/2017 05:02 PM, Rafael J. Wysocki wrote:

[...]

>>
>> So call this field "token" or similar.? Don't call it "of_node" and
>> don't introduce another "firmware_node" thing in addition to that.
>> That just is a mess, sorry.

I completely agree. Both me and Lorenzo pointed that out in previous
revisions and fair enough you have a valid concern it's use with PPTT.

> 
> I sort of agree, I think I can just change the whole of_node to a
> generic 'void *firmware_unique' which works fine for the PPTT code, it
> should also work for the DT code in cache_leaves_are_shared().
>

Should be fine.

> The slight gocha is there is a bit of DT code which initially runs
> earlier that uses of_node as an indirect parameter to a couple functions
> (by just passing the cacheinfo). Let me see if I can tweak that a bit.
>

May be use a simple inline wrapper functions to convert, might help if
we diverge too.

> Frankly, If I understood completely all the *priv cases I suspect it
> might be possible to collapse *of_node into that as well. That is as
> long as no one decides to flush out DT on x86, or PPTT on x86.
> 

priv is used to save architecture/cache specific details that can't be
generalized. I doubt if this of_node or PPTT pointer/offset falls in
that category.


-- 
Regards,
Sudeep

^ permalink raw reply

* [PATCHv2] nokia N9: Add support for magnetometer
From: Pavel Machek @ 2018-01-03 14:12 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180102172720.ghtez4d3d2fgcmj6@earth.universe>


This adds dts support for magnetometer on Nokia N9.

Signed-off-by: Pavel Machek <pavel@ucw.cz>

diff --git a/arch/arm/boot/dts/omap3-n9.dts b/arch/arm/boot/dts/omap3-n9.dts
index 39e35f8..af321d8 100644
--- a/arch/arm/boot/dts/omap3-n9.dts
+++ b/arch/arm/boot/dts/omap3-n9.dts
@@ -36,6 +57,12 @@
 			};
 		};
 	};
+
+&i2c3 {
+	ak8975 at 0f {
+		compatible = "asahi-kasei,ak8975";
+		reg = <0x0f>;
+	};
 };
 
 &isp {

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180103/657d091d/attachment.sig>

^ permalink raw reply related

* [PATCH v3 3/3] arm64: dts: renesas: r8a7796: Add OPPs table for cpu devices
From: Geert Uytterhoeven @ 2018-01-03 14:07 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180103124105.1999-4-horms+renesas@verge.net.au>

On Wed, Jan 3, 2018 at 1:41 PM, Simon Horman <horms+renesas@verge.net.au> wrote:
> From: Dien Pham <dien.pham.ry@rvc.renesas.com>
>
> Define OOP tables for all CPUs.
> This allows CPUFreq to function.
>
> Based in part on work by Hien Dang.
>
> Signed-off-by: Dien Pham <dien.pham.ry@rvc.renesas.com>
> Signed-off-by: Takeshi Kihara <takeshi.kihara.df@renesas.com>
> Signed-off-by: Simon Horman <horms+renesas@verge.net.au>

Looks good and matches the bindings.
I cannot verify the operating point tuples, though.
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply

* [PATCH v3 2/3] arm64: dts: renesas: r8a7795: Add OPPs table for cpu devices
From: Geert Uytterhoeven @ 2018-01-03 14:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180103124105.1999-3-horms+renesas@verge.net.au>

On Wed, Jan 3, 2018 at 1:41 PM, Simon Horman <horms+renesas@verge.net.au> wrote:
> From: Dien Pham <dien.pham.ry@rvc.renesas.com>
>
> Define OOP tables for all CPUs.
> This allows CPUFreq to function.
>
> Based in part on work by Hien Dang.
>
> Signed-off-by: Dien Pham <dien.pham.ry@rvc.renesas.com>
> Signed-off-by: Takeshi Kihara <takeshi.kihara.df@renesas.com>
> Signed-off-by: Simon Horman <horms+renesas@verge.net.au>

Looks good and matches the bindings.
I cannot verify the operating point tuples, though.
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply

* [PATCH v3 1/3] arm64: dts: renesas: r8a7795: move scif node into alphabetical order
From: Geert Uytterhoeven @ 2018-01-03 14:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180103124105.1999-2-horms+renesas@verge.net.au>

On Wed, Jan 3, 2018 at 1:41 PM, Simon Horman <horms+renesas@verge.net.au> wrote:
> Move scif node so that sub-nodes of the root node are in
> alphabetical order.
>
> Signed-off-by: Simon Horman <horms+renesas@verge.net.au>

Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply

* [kernel-hardening] [PATCH] arm: kernel: implement fast refcount checking
From: Ard Biesheuvel @ 2018-01-03 13:57 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAErMHp_zm2UbUyd=E3gKOLUbjq+t+gnphUsxbUYjCMqOQN86qA@mail.gmail.com>

On 3 January 2018 at 13:36, Jinbum Park <jinb.park7@gmail.com> wrote:
>>> This is a nice result. However, without any insight into the presence
>>> of actual refcount hot spots, it is not obvious that we need this
>>> patch. This is the reason we ended up enabling CONFIG_REFCOUNT_FULL
>>> for arm64. I will let others comment on whether we want this patch in
>>> the first place,
>
> Dear Ard, Dave,
>
> I wanna hear some comment on above point.
> Is CONFIG_REFCOUNT_FULL much better for arm?
> If it is, I don't need to prepare v2 patch. (then, just needed to add
> "select REFCOUNT_FULL")
>

Well, we should probably turn that around. Please use REFCOUNT_FULL,
until you run into a use case where the slowdown is noticeable. If
nobody ever notices, we don't need to fix anything.

^ permalink raw reply

* Vibrations, audio, charging, radio on N9/N950
From: Pavel Machek @ 2018-01-03 13:56 UTC (permalink / raw)
  To: linux-arm-kernel

Hi!

Sebasian, you submitted patch to enable vibrations on N950. I am
trying to do the same now on N9... I guess I enabled the dts, but
.. how do I actually ask for vibrations? /dev/input/eventX does not
seem to be present.

Did anyone get audio to run on N9/N950? It is marked as supported on
https://elinux.org/N950 with dt glue missing...

Even more importantly, does battery charging work for someone? It does
not work here :-(. After USB is plugged in, it maybe tries to charge,
but gives up after 30 seconds.

Maybe least important, but... does anyone have FM radio working? I'd
like to play some music...

									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180103/d6154afd/attachment.sig>

^ permalink raw reply

* [kernel-hardening] [PATCH] arm: kernel: implement fast refcount checking
From: Jinbum Park @ 2018-01-03 13:36 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAKv+Gu9j7YmF5UUjs0ZAVbws1jEuuoUbCwo68QgD7eAv7Uh16g@mail.gmail.com>

>> This is a nice result. However, without any insight into the presence
>> of actual refcount hot spots, it is not obvious that we need this
>> patch. This is the reason we ended up enabling CONFIG_REFCOUNT_FULL
>> for arm64. I will let others comment on whether we want this patch in
>> the first place,

Dear Ard, Dave,

I wanna hear some comment on above point.
Is CONFIG_REFCOUNT_FULL much better for arm?
If it is, I don't need to prepare v2 patch. (then, just needed to add
"select REFCOUNT_FULL")



2017-12-21 18:20 GMT+09:00 Ard Biesheuvel <ard.biesheuvel@linaro.org>:
> (add Dave)
>
> On 21 December 2017 at 09:18, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
>> On 21 December 2017 at 07:50, Jinbum Park <jinb.park7@gmail.com> wrote:
>>> This adds support to arm for fast refcount checking.
>>> It's heavily based on x86, arm64 implementation.
>>> (7a46ec0e2f48 ("locking/refcounts,
>>> x86/asm: Implement fast refcount overflow protection)
>>>
>>> This doesn't support under-ARMv6, thumb2-kernel yet.
>>>
>>> Test result of this patch is as follows.
>>>
>>> 1. LKDTM test
>>>
>>> - All REFCOUNT_* tests in LKDTM have passed.
>>>
>>> 2. Performance test
>>>
>>> - Cortex-A7, Quad Core, 450 MHz
>>> - Case with CONFIG_ARCH_HAS_REFCOUNT,
>>>
>>> perf stat -B -- echo ATOMIC_TIMING \
>>>                 >/sys/kernel/debug/provoke-crash/DIRECT
>>> 204.364247057 seconds time elapsed
>>>
>>> perf stat -B -- echo REFCOUNT_TIMING \
>>>                 >/sys/kernel/debug/provoke-crash/DIRECT
>>> 208.006062212 seconds time elapsed
>>>
>>> - Case with CONFIG_REFCOUNT_FULL,
>>>
>>> perf stat -B -- echo REFCOUNT_TIMING \
>>>                 >/sys/kernel/debug/provoke-crash/DIRECT
>>> 369.256523453 seconds time elapsed
>>>
>>
>> This is a nice result. However, without any insight into the presence
>> of actual refcount hot spots, it is not obvious that we need this
>> patch. This is the reason we ended up enabling CONFIG_REFCOUNT_FULL
>> for arm64. I will let others comment on whether we want this patch in
>> the first place, and I will give some feedback on the implementation
>> below.
>>
>>> Signed-off-by: Jinbum Park <jinb.park7@gmail.com>
>>> ---
>>>  arch/arm/Kconfig                |  1 +
>>>  arch/arm/include/asm/atomic.h   | 82 +++++++++++++++++++++++++++++++++++++++++
>>>  arch/arm/include/asm/refcount.h | 55 +++++++++++++++++++++++++++
>>>  arch/arm/kernel/traps.c         | 44 ++++++++++++++++++++++
>>>  4 files changed, 182 insertions(+)
>>>  create mode 100644 arch/arm/include/asm/refcount.h
>>>
>>> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
>>> index 3ea00d6..e07b986 100644
>>> --- a/arch/arm/Kconfig
>>> +++ b/arch/arm/Kconfig
>>> @@ -7,6 +7,7 @@ config ARM
>>>         select ARCH_HAS_DEBUG_VIRTUAL
>>>         select ARCH_HAS_DEVMEM_IS_ALLOWED
>>>         select ARCH_HAS_ELF_RANDOMIZE
>>> +       select ARCH_HAS_REFCOUNT if __LINUX_ARM_ARCH__ >= 6 && (!THUMB2_KERNEL)
>>>         select ARCH_HAS_SET_MEMORY
>>>         select ARCH_HAS_STRICT_KERNEL_RWX if MMU && !XIP_KERNEL
>>>         select ARCH_HAS_STRICT_MODULE_RWX if MMU
>>> diff --git a/arch/arm/include/asm/atomic.h b/arch/arm/include/asm/atomic.h
>>> index 66d0e21..b203396 100644
>>> --- a/arch/arm/include/asm/atomic.h
>>> +++ b/arch/arm/include/asm/atomic.h
>>> @@ -17,6 +17,7 @@
>>>  #include <linux/irqflags.h>
>>>  #include <asm/barrier.h>
>>>  #include <asm/cmpxchg.h>
>>> +#include <asm/opcodes.h>
>>>
>>>  #define ATOMIC_INIT(i) { (i) }
>>>
>>> @@ -32,6 +33,87 @@
>>>
>>>  #if __LINUX_ARM_ARCH__ >= 6
>>>
>>> +#ifdef CONFIG_ARCH_HAS_REFCOUNT
>>> +
>>> +#define REFCOUNT_ARM_BKPT_INSTR 0xfff001fc
>>> +
>>> +/*
>>> + * 1) encode call site that detect overflow in dummy b instruction.
>>> + * 2) overflow handler can decode dummy b, and get call site.
>>> + * 3) "(call site + 4) == strex" is always true.
>>> + * 4) the handler can get counter address via decoding strex.
>>> + */
>>> +#define REFCOUNT_TRIGGER_BKPT \
>>> +       __inst_arm(REFCOUNT_ARM_BKPT_INSTR) \
>>> +"      b       22b\n"
>>
>> In my arm64 implementation, I used a cbz instruction so I could encode
>> both a register number and a relative offset easily. In your case, you
>> only need to encode the offset, so it is much better to use '.long 22b
>> - .' instead.
>>
>>> +
>>> +/* If bkpt is triggered, skip strex routines after handling overflow */
>>> +#define REFCOUNT_CHECK_TAIL \
>>> +"      strex   %1, %0, [%3]\n" \
>>> +"      teq     %1, #0\n" \
>>> +"      bne     1b\n" \
>>> +"      .subsection     1\n" \
>>> +"33:\n" \
>>> +       REFCOUNT_TRIGGER_BKPT \
>>> +"      .previous\n"
>>> +
>>> +#define REFCOUNT_POST_CHECK_NEG \
>>> +"22:   bmi       33f\n" \
>>
>> It may be better to put the label on the 'strex' instruction directly,
>> to make things less confusing.
>>
>>> +       REFCOUNT_CHECK_TAIL
>>> +
>>> +#define REFCOUNT_POST_CHECK_NEG_OR_ZERO \
>>> +"      beq     33f\n" \
>>> +       REFCOUNT_POST_CHECK_NEG
>>> +
>>> +#define REFCOUNT_SMP_MB smp_mb()
>>> +#define REFCOUNT_SMP_NONE_MB
>>> +
>>> +#define REFCOUNT_OP(op, c_op, asm_op, post, mb) \
>>> +static inline int __refcount_##op(int i, atomic_t *v) \
>>> +{ \
>>> +       unsigned long tmp; \
>>> +       int result; \
>>> +\
>>> +       REFCOUNT_SMP_ ## mb; \
>>> +       prefetchw(&v->counter); \
>>> +       __asm__ __volatile__("@ __refcount_" #op "\n" \
>>> +"1:    ldrex   %0, [%3]\n" \
>>> +"      " #asm_op "     %0, %0, %4\n" \
>>> +       REFCOUNT_POST_CHECK_ ## post \
>>> +       : "=&r" (result), "=&r" (tmp), "+Qo" (v->counter) \
>>> +       : "r" (&v->counter), "Ir" (i) \
>>> +       : "cc"); \
>>> +\
>>> +       REFCOUNT_SMP_ ## mb; \
>>> +       return result; \
>>> +} \
>>> +
>>> +REFCOUNT_OP(add_lt, +=, adds, NEG_OR_ZERO, NONE_MB);
>>> +REFCOUNT_OP(sub_lt, -=, subs, NEG, MB);
>>> +REFCOUNT_OP(sub_le, -=, subs, NEG_OR_ZERO, NONE_MB);
>>> +
>>> +static inline int __refcount_add_not_zero(int i, atomic_t *v)
>>> +{
>>> +       unsigned long tmp;
>>> +       int result;
>>> +
>>> +       prefetchw(&v->counter);
>>> +       __asm__ __volatile__("@ __refcount_add_not_zero\n"
>>> +"1:    ldrex   %0, [%3]\n"
>>> +"      teq             %0, #0\n"
>>> +"      beq             2f\n"
>>> +"      adds    %0, %0, %4\n"
>>> +       REFCOUNT_POST_CHECK_NEG
>>> +"2:"
>>> +       : "=&r" (result), "=&r" (tmp), "+Qo" (v->counter)
>>> +       : "r" (&v->counter), "Ir" (i)
>>> +       : "cc");
>>> +
>>> +       return result;
>>> +}
>>> +
>>> +#endif /* CONFIG_ARCH_HAS_REFCOUNT */
>>> +
>>>  /*
>>>   * ARMv6 UP and SMP safe atomic ops.  We use load exclusive and
>>>   * store exclusive to ensure that these are atomic.  We may loop
>>> diff --git a/arch/arm/include/asm/refcount.h b/arch/arm/include/asm/refcount.h
>>> new file mode 100644
>>> index 0000000..300a2d5
>>> --- /dev/null
>>> +++ b/arch/arm/include/asm/refcount.h
>>> @@ -0,0 +1,55 @@
>>> +/*
>>> + * arm-specific implementation of refcount_t. Based on x86 version and
>>> + * PAX_REFCOUNT from PaX/grsecurity.
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License version 2 as
>>> + * published by the Free Software Foundation.
>>> + */
>>> +
>>> +#ifndef __ASM_REFCOUNT_H
>>> +#define __ASM_REFCOUNT_H
>>> +
>>> +#include <linux/refcount.h>
>>> +
>>> +#include <asm/atomic.h>
>>> +#include <asm/uaccess.h>
>>> +
>>> +static __always_inline void refcount_add(int i, refcount_t *r)
>>> +{
>>> +       __refcount_add_lt(i, &r->refs);
>>> +}
>>> +
>>> +static __always_inline void refcount_inc(refcount_t *r)
>>> +{
>>> +       __refcount_add_lt(1, &r->refs);
>>> +}
>>> +
>>> +static __always_inline void refcount_dec(refcount_t *r)
>>> +{
>>> +       __refcount_sub_le(1, &r->refs);
>>> +}
>>> +
>>> +static __always_inline __must_check bool refcount_sub_and_test(unsigned int i,
>>> +                                                               refcount_t *r)
>>> +{
>>> +       return __refcount_sub_lt(i, &r->refs) == 0;
>>> +}
>>> +
>>> +static __always_inline __must_check bool refcount_dec_and_test(refcount_t *r)
>>> +{
>>> +       return __refcount_sub_lt(1, &r->refs) == 0;
>>> +}
>>> +
>>> +static __always_inline __must_check bool refcount_add_not_zero(unsigned int i,
>>> +                                                               refcount_t *r)
>>> +{
>>> +       return __refcount_add_not_zero(i, &r->refs) != 0;
>>> +}
>>> +
>>> +static __always_inline __must_check bool refcount_inc_not_zero(refcount_t *r)
>>> +{
>>> +       return __refcount_add_not_zero(1, &r->refs) != 0;
>>> +}
>>> +
>>> +#endif
>>> diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
>>> index 5cf0488..a309215 100644
>>> --- a/arch/arm/kernel/traps.c
>>> +++ b/arch/arm/kernel/traps.c
>>> @@ -795,8 +795,52 @@ void abort(void)
>>>  }
>>>  EXPORT_SYMBOL(abort);
>>>
>>> +#ifdef CONFIG_ARCH_HAS_REFCOUNT
>>> +
>>> +static int refcount_overflow_handler(struct pt_regs *regs, unsigned int instr)
>>> +{
>>> +       u32 dummy_b = le32_to_cpup((__le32 *)(regs->ARM_pc + 4));
>>> +       u32 strex;
>>> +       u32 rt;
>>> +       bool zero = regs->ARM_cpsr & PSR_Z_BIT;
>>> +
>>> +       /* point pc to the branch instruction that detected the overflow */
>>> +       regs->ARM_pc += 4 + (((s32)dummy_b << 8) >> 6) + 8;
>>> +
>>
>> This would become something like
>>
>> s32 offset = *(s32 *)(regs->ARM_pc + 4);
>>
>> /* point pc to the strex instruction that will overflow the refcount */
>> regs->ARM_pc += offset + 4;
>>
>>
>>> +       /* decode strex to set refcount */
>>> +       strex = le32_to_cpup((__le32 *)(regs->ARM_pc + 4));
>>> +       rt = (strex << 12) >> 28;
>>> +
>>
>> Don't we have better ways to decode an instruction? Also, could you
>> add a Thumb2 variant here? (and for the breakpoint instruction)
>>
>>
>>> +       /* unconditionally saturate the refcount */
>>> +       *(int *)regs->uregs[rt] = INT_MIN / 2;
>>> +
>>> +       /* report error */
>>> +       refcount_error_report(regs, zero ? "hit zero" : "overflow");
>>> +
>>> +       /* advance pc and proceed, skip "strex" routine */
>>> +       regs->ARM_pc += 16;
>>
>> Please use a macro here to clarify that you are skipping the remaining
>> instructions in REFCOUNT_CHECK_TAIL
>>
>>> +       return 0;
>>> +}
>>> +
>>> +static struct undef_hook refcount_break_hook = {
>>> +       .instr_mask     = 0xffffffff,
>>> +       .instr_val      = REFCOUNT_ARM_BKPT_INSTR,
>>> +       .cpsr_mask      = 0,
>>> +       .cpsr_val       = 0,
>>> +       .fn             = refcount_overflow_handler,
>>> +};
>>> +
>>> +#define register_refcount_break_hook() register_undef_hook(&refcount_break_hook)
>>> +
>>> +#else /* !CONFIG_ARCH_HAS_REFCOUNT */
>>> +
>>> +#define register_refcount_break_hook()
>>> +
>>> +#endif /* CONFIG_ARCH_HAS_REFCOUNT */
>>> +
>>>  void __init trap_init(void)
>>>  {
>>> +       register_refcount_break_hook();
>>>         return;
>>>  }
>>>
>>> --
>>> 1.9.1
>>>

^ permalink raw reply

* [net-next: PATCH 0/8] Armada 7k/8k PP2 ACPI support
From: Marcin Wojtas @ 2018-01-03 13:36 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180103133341.GJ15036@lunn.ch>

2018-01-03 14:33 GMT+01:00 Andrew Lunn <andrew@lunn.ch>:
> On Wed, Jan 03, 2018 at 02:13:09PM +0100, Marcin Wojtas wrote:
>> Hi Andrew,
>>
>> 2018-01-03 13:47 GMT+01:00 Andrew Lunn <andrew@lunn.ch>:
>> >> I already agreed with 'reg' being awkward in the later emails.
>> >> Wouldn't _ADR be more appropriate to specify PHY address on MDIO bus?
>> >
>> > Also, how do you specify which MDIO bus the PHY is on. To fully
>> > specify a PHY, you need both bits of information.
>> >
>> > In DT, the phy-handle phandle can point to any PHY anywhere in the
>> > system. This is particularly important when a Ethernet device has two
>> > MDIO busses.
>> >
>>
>> For now, my local MDIO bus description is pretty DT-like, i.e. master
>> bus with children PHYs:
>>         Device (MDIO)
>>         {
>>             Name (_HID, "MRVL0100")                             //
>> _HID: Hardware ID
>>             Name (_UID, 0x00)                                   //
>> _UID: Unique ID
>>             Name (_CRS, ResourceTemplate ()
>>             {
>>                 Memory32Fixed (ReadWrite,
>>                     0xf212a200,                                 // Address Base
>>                     0x00000010,                                 //
>> Address Length
>>                     )
>>             })
>>             Device (GPHY)
>>             {
>>               Name (_ADR, 0x0)
>>             }
>>         }
>>
>>         Device (XSMI)
>>         {
>>             Name (_HID, "MRVL0101")                             //
>> _HID: Hardware ID
>>             Name (_UID, 0x00)                                   //
>> _UID: Unique ID
>>             Name (_CRS, ResourceTemplate ()
>>             {
>>                 Memory32Fixed (ReadWrite,
>>                     0xf212a600,                                 // Address Base
>>                     0x00000010,                                 //
>> Address Length
>>                     )
>>             })
>>             Device (PHY0)
>>             {
>>               Name (_ADR, 0x0)
>>               Name (_CID, "ethernet-phy-ieee802.3-c45")
>>             }
>>             Device (PHY8)
>>             {
>>               Name (_ADR, 0x8)
>>               Name (_CID, "ethernet-phy-ieee802.3-c45")
>>             }
>>         }
>>
>> Which is referenced in the port's node:
>>
>> Package () { "phy", Package (){\_SB.XSMI.PHY0}},
>
> Hi Marcin
>
> This reference looks good, giving both the bus and the PHY on the bus.
>
> I assume you can use references like this within the Device (PHY8)
> node?

Yes.

> You need to be able to reference a GPIO used for resetting the
> PHY. And you also need to reference a GPIO at the Device (MDIO) level
> for resetting all the PHYs on the MDIO bus.
>

Yes, for full support of PHYs the GPIO must be supported, as well as
the PHY's IRQs.

Best regards,
Marcin

^ permalink raw reply

* [net-next: PATCH 0/8] Armada 7k/8k PP2 ACPI support
From: Andrew Lunn @ 2018-01-03 13:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAPv3WKfZN+=9wFJ5ct+8nttd=bikaZ=Ei741pyTVXjQz2zq2dg@mail.gmail.com>

On Wed, Jan 03, 2018 at 02:13:09PM +0100, Marcin Wojtas wrote:
> Hi Andrew,
> 
> 2018-01-03 13:47 GMT+01:00 Andrew Lunn <andrew@lunn.ch>:
> >> I already agreed with 'reg' being awkward in the later emails.
> >> Wouldn't _ADR be more appropriate to specify PHY address on MDIO bus?
> >
> > Also, how do you specify which MDIO bus the PHY is on. To fully
> > specify a PHY, you need both bits of information.
> >
> > In DT, the phy-handle phandle can point to any PHY anywhere in the
> > system. This is particularly important when a Ethernet device has two
> > MDIO busses.
> >
> 
> For now, my local MDIO bus description is pretty DT-like, i.e. master
> bus with children PHYs:
>         Device (MDIO)
>         {
>             Name (_HID, "MRVL0100")                             //
> _HID: Hardware ID
>             Name (_UID, 0x00)                                   //
> _UID: Unique ID
>             Name (_CRS, ResourceTemplate ()
>             {
>                 Memory32Fixed (ReadWrite,
>                     0xf212a200,                                 // Address Base
>                     0x00000010,                                 //
> Address Length
>                     )
>             })
>             Device (GPHY)
>             {
>               Name (_ADR, 0x0)
>             }
>         }
> 
>         Device (XSMI)
>         {
>             Name (_HID, "MRVL0101")                             //
> _HID: Hardware ID
>             Name (_UID, 0x00)                                   //
> _UID: Unique ID
>             Name (_CRS, ResourceTemplate ()
>             {
>                 Memory32Fixed (ReadWrite,
>                     0xf212a600,                                 // Address Base
>                     0x00000010,                                 //
> Address Length
>                     )
>             })
>             Device (PHY0)
>             {
>               Name (_ADR, 0x0)
>               Name (_CID, "ethernet-phy-ieee802.3-c45")
>             }
>             Device (PHY8)
>             {
>               Name (_ADR, 0x8)
>               Name (_CID, "ethernet-phy-ieee802.3-c45")
>             }
>         }
> 
> Which is referenced in the port's node:
> 
> Package () { "phy", Package (){\_SB.XSMI.PHY0}},

Hi Marcin

This reference looks good, giving both the bus and the PHY on the bus.

I assume you can use references like this within the Device (PHY8)
node? You need to be able to reference a GPIO used for resetting the
PHY. And you also need to reference a GPIO at the Device (MDIO) level
for resetting all the PHYs on the MDIO bus.

    Andrew

^ permalink raw reply

* [net-next: PATCH 0/8] Armada 7k/8k PP2 ACPI support
From: Marcin Wojtas @ 2018-01-03 13:13 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180103124720.GG15036@lunn.ch>

Hi Andrew,

2018-01-03 13:47 GMT+01:00 Andrew Lunn <andrew@lunn.ch>:
>> I already agreed with 'reg' being awkward in the later emails.
>> Wouldn't _ADR be more appropriate to specify PHY address on MDIO bus?
>
> Also, how do you specify which MDIO bus the PHY is on. To fully
> specify a PHY, you need both bits of information.
>
> In DT, the phy-handle phandle can point to any PHY anywhere in the
> system. This is particularly important when a Ethernet device has two
> MDIO busses.
>

For now, my local MDIO bus description is pretty DT-like, i.e. master
bus with children PHYs:
        Device (MDIO)
        {
            Name (_HID, "MRVL0100")                             //
_HID: Hardware ID
            Name (_UID, 0x00)                                   //
_UID: Unique ID
            Name (_CRS, ResourceTemplate ()
            {
                Memory32Fixed (ReadWrite,
                    0xf212a200,                                 // Address Base
                    0x00000010,                                 //
Address Length
                    )
            })
            Device (GPHY)
            {
              Name (_ADR, 0x0)
            }
        }

        Device (XSMI)
        {
            Name (_HID, "MRVL0101")                             //
_HID: Hardware ID
            Name (_UID, 0x00)                                   //
_UID: Unique ID
            Name (_CRS, ResourceTemplate ()
            {
                Memory32Fixed (ReadWrite,
                    0xf212a600,                                 // Address Base
                    0x00000010,                                 //
Address Length
                    )
            })
            Device (PHY0)
            {
              Name (_ADR, 0x0)
              Name (_CID, "ethernet-phy-ieee802.3-c45")
            }
            Device (PHY8)
            {
              Name (_ADR, 0x8)
              Name (_CID, "ethernet-phy-ieee802.3-c45")
            }
        }

Which is referenced in the port's node:

Package () { "phy", Package (){\_SB.XSMI.PHY0}},

I'm studying an alternatives with graphs, as suggested by Tomasz
Nowicki, but to me above is pretty natural and not complicated.

Best regards,
Marcin

^ permalink raw reply

* [PATCH] arm64: dirty memory check, enable soft dirty for arm64
From: Steve Capper @ 2018-01-03 13:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180102181910.gxiqaehznpw2hc6u@armageddon.cambridge.arm.com>

Hi Catalin,

On Tue, Jan 02, 2018 at 06:19:10PM +0000, Catalin Marinas wrote:
> Hi Bin,
> 
> On Thu, Nov 30, 2017 at 12:14:09AM -0800, Bin Lu wrote:
> >     pmd_dirty and pmd_mkclean for THP page MADV_FREE also were
> >     supported in this patch.
> [...]
> > --- a/arch/arm64/include/asm/pgtable.h
> > +++ b/arch/arm64/include/asm/pgtable.h
> > @@ -306,6 +306,28 @@ static inline pgprot_t mk_sect_prot(pgprot_t prot)
> >  	return __pgprot(pgprot_val(prot) & ~PTE_TABLE_BIT);
> >  }
> >  
> > +#ifdef CONFIG_HAVE_ARCH_SOFT_DIRTY
> > +static inline bool pte_soft_dirty(pte_t pte)
> > +{
> > +        return pte_sw_dirty(pte);
> > +}
> > +
> > +static inline pte_t pte_mksoft_dirty(pte_t pte)
> > +{
> > +        return pte_mkdirty(pte);
> > +}
> > +
> > +static inline pte_t pte_clear_soft_dirty(pte_t pte)
> > +{
> > +        return pte_mkclean(pte);
> > +}
> > +
> > +#define pmd_soft_dirty(pmd)    pte_soft_dirty(pmd_pte(pmd))
> > +#define pmd_mksoft_dirty(pmd)  pte_pmd(pte_mksoft_dirty(pmd_pte(pmd)))
> > +#define pmd_clear_soft_dirty(pmd) pte_pmd(pte_clear_soft_dirty(pmd_pte(pmd)))
> 
> IIUC, a pmd_mkclean() would result in a pte_soft_dirty() == false. Is
> this the expected behaviour with MADV_FREE? The x86 code sets both
> _PAGE_DIRTY and _PAGE_SOFT_DIRTY in pmd_mkdirty() but only clears
> _PAGE_DIRTY in pmd_mkclean().
> 

For MADV_FREE, my understanding is that userspace hints to the memory
manager that pages are no longer needed and if no subsequent
modifications are made to the page then the kernel can free the pages
(and swap in a zero page should userspace attempt to read back the page
after it's been freed).

We would get a divergence in behaviour between arm64 and x86 when a
userspace program calls MADV_FREE on a soft dirty page, and where the
memory manager has not yet freed it.

So on x86 the page would be flagged as soft dirty and on arm64 this
would not be soft dirty.  I originally thought that this would be okay
as userspace has flagged the page as no longer needed. Having had
another big think about it though, I think we'd have one potential
problem with the following course of events:

 * CRIU dumps out page A from running process,
 * process subsequently modifies page A -> marked as soft dirty,
 * process calls MADV_FREE, page A no longer soft dirty,
 * CRIU does not pick up on the changes made to page A, so the other end
   gets an old page restored.

Apologies for missing this before, I neglected to make the distinction
between stale data and dropped data (userspace knows about dropped data
because the page comes back in as zeros).

The arm64 pte_dirty() checks for software and hardware dirty, thus our
pte_mkclean() should clear both states lest MADV_FREE would result in no
pages being swapped out under memory pressure.

Adding an extra dirty bit would fix this (but then we'd have effectively
three dirty bits for ptes), it is not clear to me whether or not the
HW/SW dirty bit logic could be tweaked for arm64 to give us behaviour
parity with x86.

Anyway some more thought required :-).

Cheers,
-- 
Steve

^ permalink raw reply

* [PATCH V4 06/26] edd: deprecate pci_get_bus_and_slot()
From: Sinan Kaya @ 2018-01-03 12:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1513661883-28662-7-git-send-email-okaya@codeaurora.org>

On 12/19/2017 12:37 AM, Sinan Kaya wrote:
> pci_get_bus_and_slot() is restrictive such that it assumes domain=0 as
> where a PCI device is present. This restricts the device drivers to be
> reused for other domain numbers.
> 
> Getting ready to remove pci_get_bus_and_slot() function in favor of
> pci_get_domain_bus_and_slot().
> 
> Domain number is not available in struct edd_info. Hard-coding the domain
> number as 0.
> 
> Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
> ---
>  drivers/firmware/edd.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/firmware/edd.c b/drivers/firmware/edd.c
> index e229576..60a8f13 100644
> --- a/drivers/firmware/edd.c
> +++ b/drivers/firmware/edd.c
> @@ -669,10 +669,10 @@ static void edd_release(struct kobject * kobj)
>  	struct edd_info *info = edd_dev_get_info(edev);
>  
>  	if (edd_dev_is_type(edev, "PCI") || edd_dev_is_type(edev, "XPRS")) {
> -		return pci_get_bus_and_slot(info->params.interface_path.pci.bus,
> -				     PCI_DEVFN(info->params.interface_path.pci.slot,
> -					       info->params.interface_path.pci.
> -					       function));
> +		return pci_get_domain_bus_and_slot(0,
> +				info->params.interface_path.pci.bus,
> +				PCI_DEVFN(info->params.interface_path.pci.slot,
> +				info->params.interface_path.pci.function));
>  	}
>  	return NULL;
>  }
> 

Any feedback here? most of the remaining patches have the ACK except these.


-- 
Sinan Kaya
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.

^ permalink raw reply

* [net-next: PATCH 0/8] Armada 7k/8k PP2 ACPI support
From: Andrew Lunn @ 2018-01-03 12:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAPv3WKcM8WWvh64A=FTtuWkEr6V_QSKjBpNpWnMpp_P=cMU9sw@mail.gmail.com>

> I already agreed with 'reg' being awkward in the later emails.
> Wouldn't _ADR be more appropriate to specify PHY address on MDIO bus?

Also, how do you specify which MDIO bus the PHY is on. To fully
specify a PHY, you need both bits of information.

In DT, the phy-handle phandle can point to any PHY anywhere in the
system. This is particularly important when a Ethernet device has two
MDIO busses.

     Andrew

^ permalink raw reply

* [PATCH v4 2/6] clk: renesas: rcar-gen3: Add Z2 clock divider support
From: Geert Uytterhoeven @ 2018-01-03 12:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180103121840.29316-3-horms+renesas@verge.net.au>

Hi Simon,

On Wed, Jan 3, 2018 at 1:18 PM, Simon Horman <horms+renesas@verge.net.au> wrote:
> From: Takeshi Kihara <takeshi.kihara.df@renesas.com>
>
> This patch adds Z2 clock divider support for R-Car Gen3 SoC.
>
> Signed-off-by: Takeshi Kihara <takeshi.kihara.df@renesas.com>
> Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
> ---
> v4 [Simon Horman]
> * Rebase
> * Use __ffs as FIELD_{GET,PREP} don't not work with non-constant masks
> * Use correct mask in cpg_z_clk_recalc_rate()

Thanks for the update!

> --- a/drivers/clk/renesas/rcar-gen3-cpg.c
> +++ b/drivers/clk/renesas/rcar-gen3-cpg.c
> @@ -63,7 +63,7 @@ static void cpg_simple_notifier_register(struct raw_notifier_head *notifiers,
>  }
>
>  /*
> - * Z Clock
> + * Z Clock & Z2 Clock
>   *
>   * Traits of this clock:
>   * prepare - clk_prepare only ensures that parents are prepared
> @@ -75,11 +75,13 @@ static void cpg_simple_notifier_register(struct raw_notifier_head *notifiers,
>  #define CPG_FRQCRB_KICK                        BIT(31)
>  #define CPG_FRQCRC                     0x000000e0
>  #define CPG_FRQCRC_ZFC_MASK            GENMASK(12, 8)
> +#define CPG_FRQCRC_Z2FC_MASK           GENMASK(4, 0)
>
>  struct cpg_z_clk {
>         struct clk_hw hw;
>         void __iomem *reg;
>         void __iomem *kick_reg;
> +       unsigned long mask;
>  };
>
>  #define to_z_clk(_hw)  container_of(_hw, struct cpg_z_clk, hw)
> @@ -89,8 +91,10 @@ static unsigned long cpg_z_clk_recalc_rate(struct clk_hw *hw,
>  {
>         struct cpg_z_clk *zclk = to_z_clk(hw);
>         unsigned int mult;
> +       u32 val;
>
> -       mult = 32 - FIELD_GET(CPG_FRQCRC_ZFC_MASK, clk_readl(zclk->reg));
> +       val = clk_readl(zclk->reg) & zclk->mask;
> +       mult = 32 - (val >> (__ffs(zclk->mask) - 1));

Shouldn't that be

        mult = 32 - (val >> __ffs(zclk->mask));

(same below)?

__ffs() returns 0..31, so you will shift right by 7 (Z) or -1 (Z2)?

As the CPG/MSSR driver now has suspend/resume support, do we need
a notifier to restore the Z or Z2 registers? Or is that handled automatically
by cpufreq during system resume, for both the primary and the secondary
CPU cores?

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply

* [PATCH V4 05/26] agp: nvidia: deprecate pci_get_bus_and_slot()
From: Sinan Kaya @ 2018-01-03 12:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1513661883-28662-6-git-send-email-okaya@codeaurora.org>

On 12/19/2017 12:37 AM, Sinan Kaya wrote:
> pci_get_bus_and_slot() is restrictive such that it assumes domain=0 as
> where a PCI device is present. This restricts the device drivers to be
> reused for other domain numbers.
> 
> Getting ready to remove pci_get_bus_and_slot() function in favor of
> pci_get_domain_bus_and_slot().
> 
> Replace pci_get_bus_and_slot() with pci_get_domain_bus_and_slot()
> and extract the domain number from struct pci_dev.
> 
> Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
> ---
>  drivers/char/agp/nvidia-agp.c | 12 +++++++++---
>  drivers/char/agp/sworks-agp.c |  3 ++-
>  2 files changed, 11 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c
> index 828b344..623205b 100644
> --- a/drivers/char/agp/nvidia-agp.c
> +++ b/drivers/char/agp/nvidia-agp.c
> @@ -340,11 +340,17 @@ static int agp_nvidia_probe(struct pci_dev *pdev,
>  	u8 cap_ptr;
>  
>  	nvidia_private.dev_1 =
> -		pci_get_bus_and_slot((unsigned int)pdev->bus->number, PCI_DEVFN(0, 1));
> +		pci_get_domain_bus_and_slot(pci_domain_nr(pdev->bus),
> +					    (unsigned int)pdev->bus->number,
> +					    PCI_DEVFN(0, 1));
>  	nvidia_private.dev_2 =
> -		pci_get_bus_and_slot((unsigned int)pdev->bus->number, PCI_DEVFN(0, 2));
> +		pci_get_domain_bus_and_slot(pci_domain_nr(pdev->bus),
> +					    (unsigned int)pdev->bus->number,
> +					    PCI_DEVFN(0, 2));
>  	nvidia_private.dev_3 =
> -		pci_get_bus_and_slot((unsigned int)pdev->bus->number, PCI_DEVFN(30, 0));
> +		pci_get_domain_bus_and_slot(pci_domain_nr(pdev->bus),
> +					    (unsigned int)pdev->bus->number,
> +					    PCI_DEVFN(30, 0));
>  
>  	if (!nvidia_private.dev_1 || !nvidia_private.dev_2 || !nvidia_private.dev_3) {
>  		printk(KERN_INFO PFX "Detected an NVIDIA nForce/nForce2 "
> diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c
> index 03be4ac..4dbdd3b 100644
> --- a/drivers/char/agp/sworks-agp.c
> +++ b/drivers/char/agp/sworks-agp.c
> @@ -474,7 +474,8 @@ static int agp_serverworks_probe(struct pci_dev *pdev,
>  	}
>  
>  	/* Everything is on func 1 here so we are hardcoding function one */
> -	bridge_dev = pci_get_bus_and_slot((unsigned int)pdev->bus->number,
> +	bridge_dev = pci_get_domain_bus_and_slot(pci_domain_nr(pdev->bus),
> +			(unsigned int)pdev->bus->number,
>  			PCI_DEVFN(0, 1));
>  	if (!bridge_dev) {
>  		dev_info(&pdev->dev, "can't find secondary device\n");
> 

Any feedback here? most of the remaining patches have the ACK except these.


-- 
Sinan Kaya
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.

^ permalink raw reply

* [PATCH V4 01/26] alpha/PCI: deprecate pci_get_bus_and_slot()
From: Sinan Kaya @ 2018-01-03 12:43 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1513661883-28662-2-git-send-email-okaya@codeaurora.org>

On 12/19/2017 12:37 AM, Sinan Kaya wrote:
> pci_get_bus_and_slot() is restrictive such that it assumes domain=0 as
> where a PCI device is present. This restricts the device drivers to be
> reused for other domain numbers.
> 
> Use pci_get_domain_bus_and_slot() with a domain number of 0 where we can't
> extract the domain number. Other places, use the actual domain number from
> the device.
> 
> Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
> ---
>  arch/alpha/kernel/pci.c          | 2 +-
>  arch/alpha/kernel/sys_nautilus.c | 2 +-
>  2 files changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c
> index 87da005..2e86ebb 100644
> --- a/arch/alpha/kernel/pci.c
> +++ b/arch/alpha/kernel/pci.c
> @@ -425,7 +425,7 @@ struct resource * __init
>  		if (bus == 0 && dfn == 0) {
>  			hose = pci_isa_hose;
>  		} else {
> -			dev = pci_get_bus_and_slot(bus, dfn);
> +			dev = pci_get_domain_bus_and_slot(0, bus, dfn);
>  			if (!dev)
>  				return -ENODEV;
>  			hose = dev->sysdata;
> diff --git a/arch/alpha/kernel/sys_nautilus.c b/arch/alpha/kernel/sys_nautilus.c
> index 239dc0e..ff4f54b 100644
> --- a/arch/alpha/kernel/sys_nautilus.c
> +++ b/arch/alpha/kernel/sys_nautilus.c
> @@ -237,7 +237,7 @@
>  	bus = hose->bus = bridge->bus;
>  	pcibios_claim_one_bus(bus);
>  
> -	irongate = pci_get_bus_and_slot(0, 0);
> +	irongate = pci_get_domain_bus_and_slot(pci_domain_nr(bus), 0, 0);
>  	bus->self = irongate;
>  	bus->resource[0] = &irongate_io;
>  	bus->resource[1] = &irongate_mem;
> 

Any feedback here? most of the remaining patches have the ACK except these.


-- 
Sinan Kaya
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox